@dougbots/avenor-opencode 0.4.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -5
- package/dist/index.js +42 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ Add `@dougbots/avenor-opencode` to your OpenCode configuration. If you use a glo
|
|
|
33
33
|
|
|
34
34
|
For a project-level config, add the same entry to `.opencode.json` in your repo root.
|
|
35
35
|
|
|
36
|
-
Once registered, the plugin exposes
|
|
36
|
+
Once registered, the plugin exposes eight tools that your OpenCode agent can call directly — no extra configuration required.
|
|
37
37
|
|
|
38
38
|
## Behaviour
|
|
39
39
|
|
|
@@ -68,13 +68,27 @@ The working directory (`dir`) is injected automatically from your OpenCode sessi
|
|
|
68
68
|
|
|
69
69
|
### `avenor_status`
|
|
70
70
|
|
|
71
|
-
Get status of a specific run or all active runs.
|
|
71
|
+
Get status of a specific run or all active runs. Use the compact `lifecycle` view for progress and pending permission checks; `full` remains the compatibility default.
|
|
72
72
|
|
|
73
73
|
| Argument | Required | Description |
|
|
74
74
|
|---|---|---|
|
|
75
75
|
| `run_id` | no | Specific run ID to query (omit for all runs) |
|
|
76
|
+
| `view` | no | Response detail: `lifecycle` or `full` (default) |
|
|
76
77
|
| `supervisor_id` | no | Reuse an existing supervisor by socket path |
|
|
77
78
|
|
|
79
|
+
### `avenor_result`
|
|
80
|
+
|
|
81
|
+
Wait for a run to finish and return its bounded final output without transcript or event details. This is the output retrieval tool; `avenor_status` remains a lifecycle check.
|
|
82
|
+
|
|
83
|
+
| Argument | Required | Description |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `run_id` | yes | Run ID to await |
|
|
86
|
+
| `wait` | no | Wait for a terminal result (default `true`) |
|
|
87
|
+
| `timeout` | no | Maximum time to wait (for example `30s` or `5m`) |
|
|
88
|
+
| `supervisor_id` | no | Reuse an existing supervisor by socket path |
|
|
89
|
+
|
|
90
|
+
A blocked run returns its pending permission instead of waiting forever. If this tool's own timeout expires, it returns the latest status with `ready: false` and `timed_out: true`.
|
|
91
|
+
|
|
78
92
|
### `avenor_answer_permission`
|
|
79
93
|
|
|
80
94
|
Answer a pending permission request. The `option_id` comes from the `pending_permission.options` array returned by `avenor_status`.
|
|
@@ -123,8 +137,8 @@ Shut down the avenor supervisor process and clean up temp files. Call this when
|
|
|
123
137
|
```
|
|
124
138
|
1. avenor_spawn → tool call shows live progress, blocks until done
|
|
125
139
|
2. (avenor_answer_permission → if a permission is routed to this session mid-run)
|
|
126
|
-
3. tool call returns →
|
|
127
|
-
4.
|
|
140
|
+
3. tool call returns → completion preview with status + session_id
|
|
141
|
+
4. avenor_result → retrieve the bounded final output when needed
|
|
128
142
|
5. avenor_follow_up → optionally iterate
|
|
129
143
|
6. avenor_shutdown → clean up when finished
|
|
130
144
|
```
|
|
@@ -135,7 +149,8 @@ Shut down the avenor supervisor process and clean up temp files. Call this when
|
|
|
135
149
|
2. plugin starts monitoring each run immediately
|
|
136
150
|
3. (sub-agent finishes) → plugin re-prompts this session automatically
|
|
137
151
|
4. avenor_answer_permission → if a permission was routed here mid-run
|
|
138
|
-
5.
|
|
152
|
+
5. avenor_result → wait for and retrieve the final output
|
|
153
|
+
6. avenor_events → inspect raw event history when needed
|
|
139
154
|
```
|
|
140
155
|
|
|
141
156
|
## Dependencies
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { tool } from "@opencode-ai/plugin";
|
|
2
2
|
import * as crypto from "node:crypto";
|
|
3
|
-
import { Supervisor, answerPermissionTool, createRunSnapshot, dial, eventsTool, followUpTool, inspectTool, observeRun, shutdownTool, spawnTool, statusTool } from "@dougbots/avenor-core";
|
|
3
|
+
import { Supervisor, answerPermissionTool, createRunSnapshot, dial, eventsTool, followUpTool, inspectTool, observeRun, resultTool, shutdownTool, spawnTool, statusTool } from "@dougbots/avenor-core";
|
|
4
4
|
//#region src/plugin.ts
|
|
5
5
|
const TERMINAL_STATUSES = new Set([
|
|
6
6
|
"done",
|
|
@@ -206,6 +206,10 @@ const AvenorPlugin = async (ctx) => {
|
|
|
206
206
|
kind: "aborted",
|
|
207
207
|
snapshot: current
|
|
208
208
|
};
|
|
209
|
+
if (handle.stopReason === "result") return {
|
|
210
|
+
kind: "stopped",
|
|
211
|
+
snapshot: current
|
|
212
|
+
};
|
|
209
213
|
return {
|
|
210
214
|
kind: "shutdown",
|
|
211
215
|
snapshot: current
|
|
@@ -241,6 +245,10 @@ const AvenorPlugin = async (ctx) => {
|
|
|
241
245
|
kind: "shutdown",
|
|
242
246
|
snapshot: current
|
|
243
247
|
};
|
|
248
|
+
if (handle.stopReason === "result") return {
|
|
249
|
+
kind: "stopped",
|
|
250
|
+
snapshot: current
|
|
251
|
+
};
|
|
244
252
|
if (current.pending_permission || current.phase === "waiting") return {
|
|
245
253
|
kind: "waiting",
|
|
246
254
|
snapshot: current
|
|
@@ -471,7 +479,7 @@ const AvenorPlugin = async (ctx) => {
|
|
|
471
479
|
monitorRun(run).catch(console.error);
|
|
472
480
|
return {
|
|
473
481
|
title: `${result.label} — dispatched`,
|
|
474
|
-
output: `Dispatched "${result.label}" (run_id: ${result.run_id}).
|
|
482
|
+
output: `Dispatched "${result.label}" (run_id: ${result.run_id}). Completion will be delivered automatically; use avenor_status with view "lifecycle" for progress or avenor_result to wait for the final result.`
|
|
475
483
|
};
|
|
476
484
|
}
|
|
477
485
|
context.metadata({ title: `Starting ${result.label}…` });
|
|
@@ -526,19 +534,49 @@ const AvenorPlugin = async (ctx) => {
|
|
|
526
534
|
}
|
|
527
535
|
}),
|
|
528
536
|
avenor_status: tool({
|
|
529
|
-
description: "Get status of a run or all runs.
|
|
537
|
+
description: "Get lifecycle status of a run or all runs. Use view=\"lifecycle\" for compact polling; full is the compatibility default.",
|
|
530
538
|
args: {
|
|
531
539
|
run_id: tool.schema.string().optional().describe("Specific run ID to query"),
|
|
540
|
+
view: tool.schema.enum(["lifecycle", "full"]).optional().describe("Response detail (default full for compatibility)"),
|
|
532
541
|
supervisor_id: tool.schema.string().optional().describe("Reuse an existing supervisor by socket path")
|
|
533
542
|
},
|
|
534
543
|
async execute(args, _context) {
|
|
535
544
|
const result = await statusTool({
|
|
536
545
|
runId: args.run_id,
|
|
537
|
-
supervisorId: args.supervisor_id
|
|
546
|
+
supervisorId: args.supervisor_id,
|
|
547
|
+
view: args.view
|
|
538
548
|
});
|
|
539
549
|
return JSON.stringify(result, null, 2);
|
|
540
550
|
}
|
|
541
551
|
}),
|
|
552
|
+
avenor_result: tool({
|
|
553
|
+
description: "Wait for a run to finish and return its bounded final output without transcript or event details.",
|
|
554
|
+
args: {
|
|
555
|
+
run_id: tool.schema.string().describe("Run ID to await"),
|
|
556
|
+
wait: tool.schema.boolean().optional().describe("Wait for a terminal result (default true)"),
|
|
557
|
+
timeout: tool.schema.string().optional().describe("Maximum time to wait (e.g. 30s, 5m)"),
|
|
558
|
+
supervisor_id: tool.schema.string().optional().describe("Reuse an existing supervisor by socket path")
|
|
559
|
+
},
|
|
560
|
+
async execute(args, context) {
|
|
561
|
+
const run = trackedRuns.get(args.run_id);
|
|
562
|
+
if (run) await stopMonitor(run.runId, "result");
|
|
563
|
+
try {
|
|
564
|
+
const result = await resultTool({
|
|
565
|
+
runId: args.run_id,
|
|
566
|
+
supervisorId: args.supervisor_id,
|
|
567
|
+
wait: args.wait,
|
|
568
|
+
timeout: args.timeout,
|
|
569
|
+
signal: context.abort
|
|
570
|
+
});
|
|
571
|
+
if (result.ready) unregisterRun(args.run_id);
|
|
572
|
+
else if (run) monitorRun(run).catch(console.error);
|
|
573
|
+
return JSON.stringify(result, null, 2);
|
|
574
|
+
} catch (error) {
|
|
575
|
+
if (run) monitorRun(run).catch(console.error);
|
|
576
|
+
throw error;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}),
|
|
542
580
|
avenor_answer_permission: tool({
|
|
543
581
|
description: "Answer a pending permission request for a sub-agent. Pass option_id from avenor_status pending_permission.options, or use \"allow_once\", \"allow_always\", \"deny\".",
|
|
544
582
|
args: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dougbots/avenor-opencode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"dev": "tsdown --watch"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@dougbots/avenor-core": "^0.
|
|
30
|
+
"@dougbots/avenor-core": "^0.5.1"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@opencode-ai/plugin": "1.15.3"
|