Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -466,25 +466,49 @@ jobs:

- name: Update package.json versions
run: |
jq --arg v "${{ needs.version.outputs.version }}" '.version = $v' vscode-extension/package.json > tmp.json && mv tmp.json vscode-extension/package.json
for f in vscode-extension/package.json \
backstage-server/package.json \
agnt-plugin/package.json \
agnt-plugin/manifest.json; do
jq --arg v "${{ needs.version.outputs.version }}" '.version = $v' "$f" > tmp.json && mv tmp.json "$f"
done

- name: Update opr8r Cargo.toml version
run: |
sed -i 's/^version = ".*"/version = "${{ needs.version.outputs.version }}"/' opr8r/Cargo.toml
cd opr8r && cargo update --workspace

- name: Update zed-extension versions
run: |
sed -i 's/^version = ".*"/version = "${{ needs.version.outputs.version }}"/' zed-extension/Cargo.toml
sed -i 's/^version = ".*"/version = "${{ needs.version.outputs.version }}"/' zed-extension/extension.toml
cd zed-extension && cargo update -p operator-zed

- name: Update TypeScript VERSION constant
run: |
sed -i "s/const VERSION = '[^']*'/const VERSION = '${{ needs.version.outputs.version }}'/" vscode-extension/src/webhook-server.ts

# openapi.json's version is code-derived (env!("CARGO_PKG_VERSION")); the
# already-built linux binary embeds the new version, so regenerate the
# committed spec from it instead of recompiling.
- name: Regenerate OpenAPI spec
run: |
BIN=$(find artifacts -type f -name 'operator-linux-x86_64' | head -1)
chmod +x "$BIN"
"$BIN" docs --only openapi

- name: Commit version bump
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add VERSION Cargo.toml Cargo.lock docs/_config.yml \
vscode-extension/package.json \
vscode-extension/src/webhook-server.ts \
opr8r/Cargo.toml opr8r/Cargo.lock
opr8r/Cargo.toml opr8r/Cargo.lock \
zed-extension/Cargo.toml zed-extension/extension.toml zed-extension/Cargo.lock \
backstage-server/package.json \
agnt-plugin/package.json agnt-plugin/manifest.json \
docs/schemas/openapi.json
git commit -m "chore: bump version to v${{ needs.version.outputs.version }} [skip ci]"
git push

Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ on:
- 'src/docs_gen/**'
- 'src/taxonomy/taxonomy.toml'
- 'src/templates/*.json'
- 'src/collections/**'
- 'src/schemas/**'
- '.github/workflows/docs.yml'
workflow_dispatch:

Expand Down
32 changes: 25 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,28 @@ Aim for functional software development with a focus on stateless, single respon

### Mandatory Before Committing

All changes MUST pass these checks before committing:
All changes MUST pass these checks before committing. Run them with `make check`,
which mirrors the CI `lint-test` job exactly (so a clean local run means a clean
CI run):

```bash
cargo fmt # Format code
cargo clippy -- -D warnings # Lint (warnings are errors)
cargo test # Run all tests
make check
# equivalent to the exact CI commands:
cargo fmt --all -- --check # Format check
cargo clippy --locked --all-targets --all-features -- -D warnings # Lint (warnings are errors)
cargo test --locked # Run all tests
```

> The `--locked --all-targets --all-features` flags matter: plain
> `cargo clippy` misses test-target and feature-gated lints (e.g. a dependency
> deprecation that only surfaces under `--all-targets`), which is how a clippy
> failure can pass locally yet break CI. Always use the full command above.

Install the pre-push hook once per clone so this gate runs automatically before
every push:

```bash
make install-hooks # sets core.hooksPath=.githooks
```

If any of these fail, fix the issues before proceeding. Do NOT use `#[allow(...)]` attributes to silence warnings unless there's a documented reason (e.g., code used only in tests).
Expand Down Expand Up @@ -65,7 +81,7 @@ cargo test test_new_feature -- --nocapture
cargo test

# 5. Run full validation before committing
cargo fmt && cargo clippy -- -D warnings && cargo test
make check
```

### Test Organization
Expand All @@ -77,8 +93,10 @@ cargo fmt && cargo clippy -- -D warnings && cargo test
## Quick Reference

```bash
make check # Full CI-parity gate (fmt + clippy + test)
make install-hooks # Install the pre-push hook (once per clone)
cargo fmt # Format code
cargo clippy -- -D warnings # Lint (warnings as errors)
cargo clippy --locked --all-targets --all-features -- -D warnings # Lint (CI parity)
cargo test # Run all tests
cargo test <name> # Run specific test
cargo run # Run TUI
Expand Down Expand Up @@ -192,7 +210,7 @@ On startup, operator scans the configured projects directory for subdirectories

### Completing Work

1. Run full validation: `cargo fmt && cargo clippy -- -D warnings && cargo test`
1. Run full validation: `make check` (CI-parity fmt + clippy + test)
2. Ensure all tests pass and no clippy warnings
3. Commit with message: `{type}({project}): {summary}\n\nTicket: {ID}\n`

Expand Down
33 changes: 33 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Operator developer tasks.
#
# `make check` mirrors the CI `lint-test` job exactly so a clean local run means
# a clean CI run. `make install-hooks` wires the committed pre-push hook so the
# same gate runs automatically before every push.

.PHONY: check fmt clippy test build run install-hooks

# Full CI-parity gate. Keep these commands byte-identical to
# .github/workflows/build.yaml so local and CI never disagree.
check: fmt clippy test

fmt:
cargo fmt --all -- --check

clippy:
cargo clippy --locked --all-targets --all-features -- -D warnings

test:
cargo test --locked

# Optimized release binary at target/release/operator.
build:
cargo build --release

# Run the TUI from source (development).
run:
cargo run

# One-time per clone: route git hooks at the committed .githooks/ directory.
install-hooks:
git config core.hooksPath .githooks
@echo "pre-push hook installed (runs 'make check')"
66 changes: 4 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@

* **LLM Tool** [![Claude](https://img.shields.io/badge/Claude-D97757?logo=claude&logoColor=white)](https://operator.untra.io/getting-started/agents/claude/) [![Codex](https://img.shields.io/badge/Codex-000000?logo=openai&logoColor=white)](https://operator.untra.io/getting-started/agents/codex/) [![Gemini CLI](https://img.shields.io/badge/Gemini_CLI-8E75B2?logo=googlegemini&logoColor=white)](https://operator.untra.io/getting-started/agents/gemini-cli/)

* **Model Provider** [![Anthropic](https://img.shields.io/badge/Anthropic-D97757?logo=anthropic&logoColor=white)](https://operator.untra.io/getting-started/model-servers/anthropic/) [![OpenAI](https://img.shields.io/badge/OpenAI-000000?logo=openai&logoColor=white)](https://operator.untra.io/getting-started/model-servers/openai/) [![Google](https://img.shields.io/badge/Google-4285F4?logo=google&logoColor=white)](https://operator.untra.io/getting-started/model-servers/google/) [![OpenRouter](https://img.shields.io/badge/OpenRouter-6566F1?logo=openrouter&logoColor=white)](https://operator.untra.io/getting-started/model-servers/openrouter/) [![Ollama](https://img.shields.io/badge/Ollama-000000?logo=ollama&logoColor=white)](https://operator.untra.io/getting-started/model-servers/ollama/)
* **Model Provider** [![Anthropic](https://img.shields.io/badge/Anthropic-D97757?logo=anthropic&logoColor=white)](https://operator.untra.io/getting-started/model-servers/anthropic/) [![OpenAI](https://img.shields.io/badge/OpenAI-000000?logo=openai&logoColor=white)](https://operator.untra.io/getting-started/model-servers/openai/) [![Google](https://img.shields.io/badge/Google-4285F4?logo=google&logoColor=white)](https://operator.untra.io/getting-started/model-servers/google/) [![OpenRouter](https://img.shields.io/badge/OpenRouter-94A3B8?logo=openrouter&logoColor=white)](https://operator.untra.io/getting-started/model-servers/openrouter/) [![Ollama](https://img.shields.io/badge/Ollama-000000?logo=ollama&logoColor=white)](https://operator.untra.io/getting-started/model-servers/ollama/)


* **Git Version Control** [![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://operator.untra.io/getting-started/git/github/) [![GitLab](https://img.shields.io/badge/GitLab-FC6D26?logo=gitlab&logoColor=white)](https://operator.untra.io/getting-started/git/gitlab/)

* **Platform** [![Docker](https://img.shields.io/badge/Docker-2496ED?logo=docker&logoColor=white)](https://operator.untra.io/getting-started/platforms/docker/) [![Coder](https://img.shields.io/badge/Coder-7C71FF?logo=coder&logoColor=white)](https://operator.untra.io/getting-started/platforms/coder/)

* **Workflow Format** [![Claude Workflow](https://img.shields.io/badge/Claude_Workflow-D97757?logo=claude&logoColor=white)](https://operator.untra.io/getting-started/workflows/claude/) [![AGNT Workflow](https://img.shields.io/badge/AGNT_Workflow-6E56CF)](https://operator.untra.io/getting-started/workflows/agnt/)

An orchestration tool for [**AI-assisted**](https://operator.untra.io/getting-started/agents/) [_kanban-shaped_](https://operator.untra.io/getting-started/kanban/) [git-versioned](https://operator.untra.io/getting-started/git/) software development.

<a href="https://marketplace.visualstudio.com/items?itemName=untra.operator-terminals" target="_blank" class="button">Install <b>Operator! Terminals</b> extension from Visual Studio Code Marketplace</a>
Expand Down Expand Up @@ -98,7 +100,7 @@ Or build from source:
```bash
git clone https://github.com/untra/operator.git
cd operator
cargo build --release
make build # cargo build --release
sudo cp target/release/operator /usr/local/bin/
```

Expand Down Expand Up @@ -296,63 +298,3 @@ operator launch --llm-tool codex --model qwen2.5-coder --model-server ollama-loc

Current release ships the infrastructure — ollama detection and automatic env-var injection on spawn land in the next release. See `docs/getting-started/model-servers/` for the full walkthrough.

## Development

```bash
# Run in development
cargo run

# Run tests
cargo test

# Build release
cargo build --release
```

## Documentation

Reference documentation is auto-generated from source-of-truth files to minimize maintenance.

### Available References

| Generator | Source | Output |
|-----------|--------|--------|
| taxonomy | `src/taxonomy/taxonomy.toml` | `docs/taxonomy/index.md` |
| issuetype-schema | `src/schemas/issuetype_schema.json` | `docs/schemas/issuetype.md` |
| metadata-schema | `src/schemas/ticket_metadata.schema.json` | `docs/schemas/metadata.md` |
| shortcuts | `src/ui/keybindings.rs` | `docs/shortcuts/index.md` |
| cli | `src/main.rs`, `src/env_vars.rs` | `docs/cli/index.md` |
| config | `src/config.rs` | `docs/configuration/index.md` |
| OpenAPI | `src/rest/` (utoipa annotations) | `docs/schemas/openapi.json` |
| llm-tools | `src/llm/tools/tool_config.schema.json` | `docs/llm-tools/index.md` |
| startup | `src/startup/mod.rs` | `docs/startup/index.md` |
| config-schema | `docs/schemas/config.json` | `docs/schemas/config.md` |
| state-schema | `docs/schemas/state.json` | `docs/schemas/state.md` |
| schema-index | `docs/schemas/` | `docs/schemas/index.md` |
| jira-api | `docs/schemas/jira-api.json` | `docs/getting-started/kanban/jira-api.md` |

### Viewing Documentation

```bash
# Serve docs locally with Jekyll
cd docs && bundle install && bundle exec jekyll serve
# Visit http://localhost:4000

# View OpenAPI spec with Swagger UI
# After starting Jekyll, visit http://localhost:4000/schemas/api/
```

### Regenerating Documentation

```bash
# Regenerate all auto-generated docs
cargo run -- docs

# Regenerate specific docs
cargo run -- docs --only openapi
cargo run -- docs --only config

# Available generators: taxonomy, issuetype-schema, metadata-schema, shortcuts,
# cli, config, OpenAPI, llm-tools, startup, config-schema, state-schema,
# schema-index, jira-api
```
3 changes: 3 additions & 0 deletions agnt-plugin/alert.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import { callOperator } from "./lib/operator-client.js";

class AlertTool {
constructor() {
this.name = "operator-alert";
}
async execute(params, _inputData, _workflowEngine) {
if (!params || !params.message) {
return { success: false, result: null, error: "missing required param: message" };
Expand Down
3 changes: 3 additions & 0 deletions agnt-plugin/create-ticket.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import { callOperator } from "./lib/operator-client.js";

class CreateTicketTool {
constructor() {
this.name = "operator-create-ticket";
}
async execute(params, _inputData, _workflowEngine) {
if (!params || !params.template) {
return { success: false, result: null, error: "missing required param: template" };
Expand Down
3 changes: 3 additions & 0 deletions agnt-plugin/export.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import { callOperator } from "./lib/operator-client.js";

class ExportWorkflowTool {
constructor() {
this.name = "operator-export-workflow";
}
async execute(params, _inputData, _workflowEngine) {
if (!params || !params.id) {
return { success: false, result: null, error: "missing required param: id" };
Expand Down
3 changes: 3 additions & 0 deletions agnt-plugin/launch.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import { callOperator } from "./lib/operator-client.js";

class LaunchAgentTool {
constructor() {
this.name = "operator-launch-agent";
}
async execute(params, _inputData, _workflowEngine) {
if (!params || !params.id) {
return { success: false, result: null, error: "missing required param: id" };
Expand Down
2 changes: 1 addition & 1 deletion agnt-plugin/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "operator-plugin",
"version": "0.2.1",
"version": "0.2.2",
"description": "Orchestrate Operator! ticket-driven coding agents from AGNT workflows",
"author": "untra",
"displayName": "Operator!",
Expand Down
2 changes: 1 addition & 1 deletion agnt-plugin/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "operator-plugin",
"version": "0.2.1",
"version": "0.2.2",
"description": "Orchestrate Operator! ticket-driven coding agents from AGNT workflows",
"author": "untra",
"license": "MIT",
Expand Down
3 changes: 3 additions & 0 deletions agnt-plugin/queue.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import { callOperator } from "./lib/operator-client.js";

class QueueStatusTool {
constructor() {
this.name = "operator-queue-status";
}
async execute(params, _inputData, _workflowEngine) {
return callOperator({ params, path: "/api/v1/queue/status" });
}
Expand Down
3 changes: 3 additions & 0 deletions agnt-plugin/run-step.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import { callOperator } from "./lib/operator-client.js";

class RunStepTool {
constructor() {
this.name = "operator-run-step";
}
async execute(params, _inputData, _workflowEngine) {
const ticket = params && (params.ticket || params.id);
if (!ticket) {
Expand Down
2 changes: 1 addition & 1 deletion backstage-server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "operator-backstage",
"version": "0.2.0",
"version": "0.2.2",
"author": {
"name": "Samuel Volin",
"email": "untra.sam@gmail.com",
Expand Down
15 changes: 14 additions & 1 deletion bindings/CollectionResponse.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { WorkflowHintsDto } from "./WorkflowHintsDto";

/**
* Response for a collection
*/
export type CollectionResponse = { name: string, description: string, types: Array<string>, is_active: boolean, };
export type CollectionResponse = { name: string, description: string, types: Array<string>, is_active: boolean,
/**
* Collection semver (present for hosted collections).
*/
version?: string | null,
/**
* Publisher identifier (present for hosted collections).
*/
publisher?: string | null,
/**
* Descriptive workflow hints (present for hosted collections).
*/
workflow_hints?: WorkflowHintsDto | null, };
4 changes: 3 additions & 1 deletion bindings/Delegator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ model_server: string | null,
* delegator carrying this CANNOT be launched locally — resolution errors out
* (see `delegator_resolution`). It is stored, listed, serialized into an
* `AgentProfile`, and — for `platform == "agnt"` — surfaced in the
* `--format agnt` workflow export as an `agnt-agent` node. `None` = ordinary,
* `--format agnt` workflow export as a native AGNT `agnt-agent` node, whose
* `agentId` is this reference's `id` (AGNT identifies agents by UUID, so the
* `id` must be the agent's UUID, not its display name). `None` = ordinary,
* locally launchable delegator.
*/
remote_agent?: RemoteAgentRef | null,
Expand Down
Loading
Loading