@dougbots/avenor-opencode 0.9.0 → 0.10.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 CHANGED
@@ -58,17 +58,36 @@ Dispatch an agent run in the current working directory.
58
58
 
59
59
  | Argument | Required | Description |
60
60
  |---|---|---|
61
- | `agent` | yes | Agent name (no default — must be specified) |
61
+ | `agent` | no | Agent name; omission uses the supplied model or runtime defaults |
62
62
  | `prompt` | no | Prompt text |
63
63
  | `prompt_file` | no | Path to a prompt file |
64
64
  | `label` | no | Human-readable label for the run |
65
65
  | `timeout` | no | Timeout duration (e.g. `3600s`, `30m`) |
66
66
  | `model` | no | Model override |
67
+ | `thinking` | no | Run-level reasoning control; unsupported effective backends reject explicit values |
68
+ | `backend` | no | Backend override; direct mode defaults to Avenor's `opencode-acp` backend when omitted |
69
+ | `roster_file` | no | Path to a top-level roster map |
70
+ | `roster_entry` | no | Key within `roster_file` |
67
71
  | `wait` | no | Block until complete (default `true`) |
68
72
  | `supervisor_id` | no | Reuse an existing supervisor by socket path |
69
73
 
70
74
  The working directory (`dir`) is injected automatically from your OpenCode session context — it is not a user-facing argument.
71
75
 
76
+ #### Direct and roster modes
77
+
78
+ Use `roster_file` plus `roster_entry` to select a complete identity. Every roster entry requires `backend` and at least one of `agent` or `model`; roster mode rejects direct `agent`, `model`, and `backend` overrides. Direct mode allows all three identity fields to be omitted independently, including backend-only selection. Roster mode does not apply the direct `opencode-acp` default.
79
+
80
+ ```json
81
+ {
82
+ "prompt": "Review the repository",
83
+ "roster_file": "/repo/roster.json",
84
+ "roster_entry": "reviewer",
85
+ "wait": true
86
+ }
87
+ ```
88
+
89
+ Roster entries currently support only `backend`, `agent`, and `model`. `system` and `thinking` are rejected; `thinking` remains a run-level value and is validated against the effective backend. A resumed session cannot change backend. The plugin passes `roster_file` as supplied, so an absolute path avoids ambiguity when the OpenCode process directory differs from the project directory.
90
+
72
91
  ### `avenor_status`
73
92
 
74
93
  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.
package/dist/index.d.ts CHANGED
@@ -6,7 +6,14 @@ type TrackedRun = {
6
6
  runId: string;
7
7
  runtimeId?: string;
8
8
  sessionId?: string;
9
- agent: string;
9
+ agent?: string;
10
+ model?: string;
11
+ backend?: string;
12
+ rosterFile?: string;
13
+ rosterEntry?: string;
14
+ effectiveAgent?: string;
15
+ effectiveModel?: string;
16
+ effectiveBackend?: string;
10
17
  orchestratorSessionId: string;
11
18
  label: string;
12
19
  supervisorId?: string;
@@ -15,7 +22,12 @@ type TrackedRun = {
15
22
  lastSnapshot?: RunSnapshot;
16
23
  };
17
24
  declare function terminalStatus(snapshot: RunSnapshot, fallback?: StatusResult): string;
25
+ type HostIdentityMetadataInput = Pick<TrackedRun, 'agent' | 'model' | 'backend' | 'rosterFile' | 'rosterEntry' | 'effectiveAgent' | 'effectiveModel' | 'effectiveBackend'>;
26
+ type HostIdentityStatus = Pick<StatusResult, 'roster_file' | 'roster_entry' | 'agent' | 'model' | 'backend' | 'effective_agent' | 'effective_model' | 'effective_backend'>;
27
+ /** Project shared spawn identity into OpenCode metadata without resolving rosters here. */
28
+ declare function hostIdentityMetadata(run?: HostIdentityMetadataInput, status?: HostIdentityStatus): Record<string, unknown>;
29
+ declare function buildSnapshotMetadata(snapshot: RunSnapshot, run?: HostIdentityMetadataInput, status?: HostIdentityStatus): Record<string, unknown>;
18
30
  declare function buildWaitingText(run: TrackedRun, snapshot: RunSnapshot): string;
19
31
  declare const AvenorPlugin: Plugin;
20
32
  //#endregion
21
- export { AvenorPlugin, buildWaitingText, terminalStatus };
33
+ export { AvenorPlugin, buildSnapshotMetadata, buildWaitingText, hostIdentityMetadata, terminalStatus };
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, extractEventText, followUpTool, inspectTool, observeRun, resultTool, shutdownTool, spawnTool, statusTool } from "@dougbots/avenor-core";
3
+ import { Supervisor, THINKING_LEVELS, answerPermissionTool, createRunSnapshot, dial, eventsTool, extractEventText, followUpTool, inspectTool, observeRun, resultTool, shutdownTool, spawnTool, statusTool, validateSpawnSelection, workflowCompleteTool, workflowEventsTool, workflowGateTool, workflowInspectTool, workflowStatusTool, workflowWaitTool } from "@dougbots/avenor-core";
4
4
  //#region src/render.ts
5
5
  const FINAL_OUTPUT_CHARS$1 = 1500;
6
6
  const SCALAR_CHARS = 240;
@@ -462,7 +462,20 @@ function formatTranscriptPreview(snapshot) {
462
462
  if (lines.length === 0) return void 0;
463
463
  return clipTail(lines.join("\n"), METADATA_TEXT_CHARS);
464
464
  }
465
- function buildSnapshotMetadata(snapshot) {
465
+ /** Project shared spawn identity into OpenCode metadata without resolving rosters here. */
466
+ function hostIdentityMetadata(run = {}, status) {
467
+ const metadata = {};
468
+ const add = (key, value) => {
469
+ if (typeof value === "string" && value.length > 0) metadata[key] = value;
470
+ };
471
+ add("roster_file", status?.roster_file ?? run.rosterFile);
472
+ add("roster_entry", status?.roster_entry ?? run.rosterEntry);
473
+ add("effective_agent", status?.effective_agent ?? status?.agent ?? run.effectiveAgent);
474
+ add("effective_model", status?.effective_model ?? status?.model ?? run.effectiveModel);
475
+ add("effective_backend", status?.effective_backend ?? status?.backend ?? run.effectiveBackend);
476
+ return metadata;
477
+ }
478
+ function buildSnapshotMetadata(snapshot, run, status) {
466
479
  const metadata = {};
467
480
  if (snapshot.phase) metadata.phase = snapshot.phase;
468
481
  if (snapshot.latest_seq !== void 0) metadata.latest_seq = snapshot.latest_seq;
@@ -472,6 +485,7 @@ function buildSnapshotMetadata(snapshot) {
472
485
  if (transcriptPreview) metadata.transcript_preview = transcriptPreview;
473
486
  const pendingPermission = clipTail(snapshot.pending_permission?.description ?? snapshot.pending_permission?.question ?? snapshot.phase_label, METADATA_TEXT_CHARS);
474
487
  if (pendingPermission) metadata.pending_permission = pendingPermission;
488
+ Object.assign(metadata, hostIdentityMetadata(run, status));
475
489
  return metadata;
476
490
  }
477
491
  function buildWaitingText(run, snapshot) {
@@ -544,6 +558,16 @@ const AvenorPlugin = async (ctx) => {
544
558
  if (snapshot.latest_seq !== void 0) run.latestSeq = snapshot.latest_seq;
545
559
  registerSessionId(snapshot.identity.session_id, snapshot.identity.runtime_id, run.runId);
546
560
  }
561
+ function updateRunIdentity(run, status) {
562
+ run.rosterFile = status.roster_file ?? run.rosterFile;
563
+ run.rosterEntry = status.roster_entry ?? run.rosterEntry;
564
+ run.effectiveAgent = status.effective_agent ?? status.agent ?? run.effectiveAgent;
565
+ run.effectiveModel = status.effective_model ?? status.model ?? run.effectiveModel;
566
+ run.effectiveBackend = status.effective_backend ?? status.backend ?? run.effectiveBackend;
567
+ run.agent = run.effectiveAgent ?? run.agent;
568
+ run.model = run.effectiveModel ?? run.model;
569
+ run.backend = run.effectiveBackend ?? run.backend;
570
+ }
547
571
  async function primeTrackedRun(run, options = {}) {
548
572
  try {
549
573
  const raw = await statusTool({
@@ -553,6 +577,7 @@ const AvenorPlugin = async (ctx) => {
553
577
  const status = Array.isArray(raw) ? raw[0] : raw;
554
578
  if (!status) return void 0;
555
579
  registerSessionId(status.session_id, status.runtime_id, run.runId);
580
+ updateRunIdentity(run, status);
556
581
  if (status.latest_seq !== void 0 && options.captureLatestSeq) run.latestSeq = status.latest_seq;
557
582
  return status;
558
583
  } catch {
@@ -578,10 +603,12 @@ const AvenorPlugin = async (ctx) => {
578
603
  }
579
604
  async function loadInspection(run) {
580
605
  try {
581
- return await inspectTool({
606
+ const inspection = await inspectTool({
582
607
  runId: run.runId,
583
608
  supervisorId: run.supervisorId
584
609
  });
610
+ updateRunIdentity(run, inspection.status);
611
+ return inspection;
585
612
  } catch {
586
613
  return;
587
614
  }
@@ -840,43 +867,46 @@ const AvenorPlugin = async (ctx) => {
840
867
  },
841
868
  tool: {
842
869
  avenor_spawn: tool({
843
- description: "Dispatch an agent run via avenor. Optional thinking accepts off, minimal, low, medium, high, xhigh, or max; unsupported backends reject explicit values. Blocks by default, showing live progress as an updating tool call. Set wait=false for fire-and-forget — you will be re-prompted automatically on completion.",
870
+ description: `Dispatch an agent run via avenor. Optional thinking accepts ${[...THINKING_LEVELS].slice(0, -1).join(", ")}, or ${THINKING_LEVELS[THINKING_LEVELS.length - 1]}; unsupported backends reject explicit values. Blocks by default, showing live progress as an updating tool call. Set wait=false for fire-and-forget — you will be re-prompted automatically on completion.`,
844
871
  args: {
845
- agent: tool.schema.string().describe("Agent name (required, no default)"),
872
+ agent: tool.schema.string().optional().describe("Optional agent name; omission uses the supplied model or runtime defaults"),
846
873
  prompt: tool.schema.string().optional().describe("Prompt text"),
847
874
  prompt_file: tool.schema.string().optional().describe("Path to prompt file"),
848
875
  dir: tool.schema.string().optional().describe("Working directory for the run (defaults to the session project directory)"),
849
876
  label: tool.schema.string().optional().describe("Human-readable label for the run"),
850
877
  timeout: tool.schema.string().optional().describe("Timeout duration (e.g. 3600s)"),
851
878
  model: tool.schema.string().optional().describe("Model override"),
852
- thinking: tool.schema.enum([
853
- "off",
854
- "minimal",
855
- "low",
856
- "medium",
857
- "high",
858
- "xhigh",
859
- "max"
860
- ]).optional().describe("Thinking level; omission uses the backend default"),
879
+ thinking: tool.schema.enum([...THINKING_LEVELS]).optional().describe("Thinking level; omission uses the backend default"),
861
880
  backend: tool.schema.string().optional().describe("Backend override"),
881
+ roster_file: tool.schema.string().optional().describe("Path to the roster map"),
882
+ roster_entry: tool.schema.string().optional().describe("Roster entry to select"),
862
883
  server_url: tool.schema.string().optional().describe("Backend server URL"),
863
884
  supervisor_id: tool.schema.string().optional().describe("Reuse an existing supervisor by socket path"),
864
885
  wait: tool.schema.boolean().default(true).describe("Block until complete with live status updates. False = fire-and-forget.")
865
886
  },
866
887
  async execute(args, context) {
867
- const ownerRunId = ensureParentRunId();
868
- const result = await spawnTool({
888
+ validateSpawnSelection({
869
889
  agent: args.agent,
870
- prompt: args.prompt,
871
- promptFile: args.prompt_file,
872
- label: args.label,
873
- dir: args.dir ?? context.directory,
874
- timeout: args.timeout,
875
890
  model: args.model,
876
- thinking: args.thinking,
877
891
  backend: args.backend,
878
- serverUrl: args.server_url,
879
- supervisorId: args.supervisor_id,
892
+ roster_file: args.roster_file,
893
+ roster_entry: args.roster_entry
894
+ });
895
+ const ownerRunId = ensureParentRunId();
896
+ const result = await spawnTool({
897
+ ...args.agent !== void 0 ? { agent: args.agent } : {},
898
+ ...args.prompt !== void 0 ? { prompt: args.prompt } : {},
899
+ ...args.prompt_file !== void 0 ? { promptFile: args.prompt_file } : {},
900
+ ...args.label !== void 0 ? { label: args.label } : {},
901
+ dir: args.dir ?? context.directory,
902
+ ...args.timeout !== void 0 ? { timeout: args.timeout } : {},
903
+ ...args.model !== void 0 ? { model: args.model } : {},
904
+ ...args.thinking !== void 0 ? { thinking: args.thinking } : {},
905
+ ...args.backend !== void 0 ? { backend: args.backend } : {},
906
+ ...args.roster_file !== void 0 ? { rosterFile: args.roster_file } : {},
907
+ ...args.roster_entry !== void 0 ? { rosterEntry: args.roster_entry } : {},
908
+ ...args.server_url !== void 0 ? { serverUrl: args.server_url } : {},
909
+ ...args.supervisor_id !== void 0 ? { supervisorId: args.supervisor_id } : {},
880
910
  parent_run_id: ownerRunId
881
911
  });
882
912
  if (result.broker_url) brokerUrl = result.broker_url;
@@ -885,6 +915,10 @@ const AvenorPlugin = async (ctx) => {
885
915
  runId: result.run_id,
886
916
  runtimeId: result.runtime_id,
887
917
  agent: args.agent,
918
+ model: args.model,
919
+ backend: args.backend,
920
+ rosterFile: args.roster_file,
921
+ rosterEntry: args.roster_entry,
888
922
  orchestratorSessionId: context.sessionID,
889
923
  label: result.label,
890
924
  supervisorId: result.supervisor_id || args.supervisor_id,
@@ -897,7 +931,8 @@ const AvenorPlugin = async (ctx) => {
897
931
  monitorRun(run).catch(console.error);
898
932
  return {
899
933
  title: `${result.label} — dispatched`,
900
- 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.`
934
+ 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.`,
935
+ metadata: hostIdentityMetadata(run)
901
936
  };
902
937
  }
903
938
  context.metadata({ title: `Starting ${result.label}…` });
@@ -906,7 +941,7 @@ const AvenorPlugin = async (ctx) => {
906
941
  onSnapshot: (snapshot) => {
907
942
  context.metadata({
908
943
  title: snapshot.pending_permission ? `[blocked] ${result.label}` : result.label,
909
- metadata: buildSnapshotMetadata(snapshot)
944
+ metadata: buildSnapshotMetadata(snapshot, run)
910
945
  });
911
946
  }
912
947
  });
@@ -921,7 +956,7 @@ const AvenorPlugin = async (ctx) => {
921
956
  run_id: result.run_id,
922
957
  session_id: inspection?.status.session_id ?? snapshot.identity.session_id,
923
958
  final_output: clipTail(inspection?.final_output ?? snapshot.final_output, FINAL_OUTPUT_CHARS),
924
- ...buildSnapshotMetadata(snapshot)
959
+ ...buildSnapshotMetadata(snapshot, run, inspection?.status)
925
960
  }
926
961
  };
927
962
  }
@@ -934,20 +969,26 @@ const AvenorPlugin = async (ctx) => {
934
969
  metadata: {
935
970
  run_id: result.run_id,
936
971
  session_id: inspection?.status.session_id ?? snapshot.identity.session_id,
937
- ...buildSnapshotMetadata(snapshot)
972
+ ...buildSnapshotMetadata(snapshot, run, inspection?.status)
938
973
  }
939
974
  };
940
975
  }
941
976
  if (outcome.kind === "error") return {
942
977
  title: `${result.label} — monitoring error`,
943
978
  output: `Monitoring failed: ${outcome.error ?? "unknown error"}. The run may still be active — use avenor_status to check.`,
944
- metadata: { run_id: result.run_id }
979
+ metadata: {
980
+ run_id: result.run_id,
981
+ ...hostIdentityMetadata(run)
982
+ }
945
983
  };
946
984
  unregisterRun(result.run_id);
947
985
  return {
948
986
  title: `${result.label} — aborted`,
949
987
  output: `Monitoring of "${result.label}" (run_id: ${result.run_id}) was interrupted. The run may still be active — use avenor_status to check.`,
950
- metadata: { run_id: result.run_id }
988
+ metadata: {
989
+ run_id: result.run_id,
990
+ ...hostIdentityMetadata(run)
991
+ }
951
992
  };
952
993
  }
953
994
  }),
@@ -1090,9 +1131,146 @@ const AvenorPlugin = async (ctx) => {
1090
1131
  force: args.force
1091
1132
  }));
1092
1133
  }
1134
+ }),
1135
+ avenor_workflow_status: tool({
1136
+ description: "Get lightweight status for a workflow instance",
1137
+ args: {
1138
+ workflow_id: tool.schema.string().describe("Workflow ID"),
1139
+ supervisor_id: tool.schema.string().optional().describe("Supervisor ID for multi-supervisor mode")
1140
+ },
1141
+ async execute(args, _context) {
1142
+ const result = await workflowStatusTool({
1143
+ workflowId: args.workflow_id,
1144
+ supervisorId: args.supervisor_id
1145
+ });
1146
+ return {
1147
+ title: "workflow",
1148
+ output: JSON.stringify(result, null, 2)
1149
+ };
1150
+ }
1151
+ }),
1152
+ avenor_workflow_wait: tool({
1153
+ description: "Wait for a workflow to reach a terminal state or until timeout",
1154
+ args: {
1155
+ workflow_id: tool.schema.string().describe("Workflow ID"),
1156
+ timeout: tool.schema.string().optional().describe("Timeout (e.g. 30s, 5m)"),
1157
+ supervisor_id: tool.schema.string().optional().describe("Supervisor ID for multi-supervisor mode")
1158
+ },
1159
+ async execute(args, _context) {
1160
+ const result = await workflowWaitTool({
1161
+ workflowId: args.workflow_id,
1162
+ timeout: args.timeout,
1163
+ supervisorId: args.supervisor_id
1164
+ });
1165
+ return {
1166
+ title: "workflow",
1167
+ output: JSON.stringify(result, null, 2)
1168
+ };
1169
+ }
1170
+ }),
1171
+ avenor_workflow_inspect: tool({
1172
+ description: "Return the full instance detail for a workflow",
1173
+ args: {
1174
+ workflow_id: tool.schema.string().describe("Workflow ID"),
1175
+ supervisor_id: tool.schema.string().optional().describe("Supervisor ID for multi-supervisor mode")
1176
+ },
1177
+ async execute(args, _context) {
1178
+ const result = await workflowInspectTool({
1179
+ workflowId: args.workflow_id,
1180
+ supervisorId: args.supervisor_id
1181
+ });
1182
+ return {
1183
+ title: "workflow",
1184
+ output: JSON.stringify(result, null, 2)
1185
+ };
1186
+ }
1187
+ }),
1188
+ avenor_workflow_events: tool({
1189
+ description: "Read log events from a workflow instance's event log",
1190
+ args: {
1191
+ workflow_id: tool.schema.string().describe("Workflow ID"),
1192
+ after_seq: tool.schema.number().optional().describe("Only include events after this sequence number"),
1193
+ limit: tool.schema.number().optional().describe("Max events to return (default 50)"),
1194
+ supervisor_id: tool.schema.string().optional().describe("Supervisor ID for multi-supervisor mode")
1195
+ },
1196
+ async execute(args, _context) {
1197
+ const result = await workflowEventsTool({
1198
+ workflowId: args.workflow_id,
1199
+ afterSeq: args.after_seq,
1200
+ limit: args.limit,
1201
+ supervisorId: args.supervisor_id
1202
+ });
1203
+ return {
1204
+ title: "workflow",
1205
+ output: JSON.stringify(result, null, 2)
1206
+ };
1207
+ }
1208
+ }),
1209
+ avenor_workflow_complete: tool({
1210
+ description: "Atomically complete a machine/external handoff activation",
1211
+ args: {
1212
+ workflow_id: tool.schema.string().describe("Workflow ID"),
1213
+ node_id: tool.schema.string().describe("Node ID"),
1214
+ activation_id: tool.schema.string().describe("Activation ID"),
1215
+ attempt_id: tool.schema.string().describe("Attempt ID"),
1216
+ lease_id: tool.schema.string().describe("Lease ID"),
1217
+ owner_token: tool.schema.string().describe("Owner token"),
1218
+ outcome: tool.schema.string().describe("Outcome"),
1219
+ outputs: tool.schema.unknown().optional().describe("Outputs"),
1220
+ artifacts: tool.schema.unknown().optional().describe("Artifacts"),
1221
+ supervisor_id: tool.schema.string().optional().describe("Supervisor ID for multi-supervisor mode")
1222
+ },
1223
+ async execute(args, _context) {
1224
+ const { supervisor_id, ...rest } = args;
1225
+ const result = await workflowCompleteTool({
1226
+ ...rest,
1227
+ supervisorId: supervisor_id
1228
+ });
1229
+ return {
1230
+ title: "workflow",
1231
+ output: JSON.stringify(result, null, 2)
1232
+ };
1233
+ }
1234
+ }),
1235
+ avenor_workflow_gate: tool({
1236
+ description: "Record a gate decision on a parked awaiting_gate activation",
1237
+ args: {
1238
+ workflow_id: tool.schema.string().describe("Workflow ID"),
1239
+ node_id: tool.schema.string().describe("Node ID"),
1240
+ gate_id: tool.schema.string().describe("Gate ID"),
1241
+ activation_id: tool.schema.string().describe("Activation ID"),
1242
+ operation: tool.schema.enum([
1243
+ "satisfy",
1244
+ "reject",
1245
+ "waive",
1246
+ "external_result"
1247
+ ]).describe("Gate operation"),
1248
+ actor: tool.schema.string().optional().describe("Actor"),
1249
+ reason: tool.schema.string().optional().describe("Reason"),
1250
+ outcome: tool.schema.string().optional().describe("Outcome"),
1251
+ subject: tool.schema.unknown().optional().describe("Subject"),
1252
+ poll_id: tool.schema.string().optional().describe("Poll ID"),
1253
+ source: tool.schema.string().optional().describe("Source"),
1254
+ result: tool.schema.string().optional().describe("Result"),
1255
+ response_hash: tool.schema.string().optional().describe("Response hash"),
1256
+ observed_at: tool.schema.string().optional().describe("Observed at"),
1257
+ evidence_ids: tool.schema.array(tool.schema.string()).optional().describe("Evidence IDs"),
1258
+ supervisor_id: tool.schema.string().optional().describe("Supervisor ID for multi-supervisor mode")
1259
+ },
1260
+ async execute(args, _context) {
1261
+ const { supervisor_id, ...rest } = args;
1262
+ const result = await workflowGateTool({
1263
+ ...rest,
1264
+ supervisorId: supervisor_id
1265
+ });
1266
+ return {
1267
+ title: "workflow",
1268
+ output: JSON.stringify(result, null, 2)
1269
+ };
1270
+ }
1093
1271
  })
1094
1272
  }
1095
1273
  };
1096
1274
  };
1097
1275
  //#endregion
1098
- export { AvenorPlugin, buildWaitingText, terminalStatus };
1276
+ export { AvenorPlugin, buildSnapshotMetadata, buildWaitingText, hostIdentityMetadata, terminalStatus };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dougbots/avenor-opencode",
3
- "version": "0.9.0",
3
+ "version": "0.10.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.9.0"
30
+ "@dougbots/avenor-core": "^0.10.1"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "@opencode-ai/plugin": "1.15.3"