@dougbots/avenor-core 0.10.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/dist/index.d.ts CHANGED
@@ -1,6 +1,34 @@
1
1
  import { n as getVersion, r as installerBinaryPath, t as getInstallDir } from "./install-path-DagQIDKB.js";
2
2
  import * as net from "node:net";
3
3
 
4
+ //#region src/thinking-policy.d.ts
5
+ /**
6
+ * Portable thinking-policy contract.
7
+ *
8
+ * THINKING_LEVELS is the single TypeScript source for the canonical tuple and
9
+ * is exported for hosts (MCP, OpenCode, Pi) to derive their enums from. It is
10
+ * verified against schemas/thinking_policy.umpire.json and the Go tuple by
11
+ * introspection and conformance tests so all languages agree.
12
+ *
13
+ * The backend policy (which canonical values each backend supports, on start
14
+ * vs. explicit resume) is modelled directly in the Umpire schema's eitherOf
15
+ * branches with fairWhen rules and conditions (backend, resume). Both Go and
16
+ * TypeScript derive the policy from the schema, eliminating hand-written
17
+ * policy tables that could drift apart.
18
+ */
19
+ declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
20
+ type ThinkingLevel = (typeof THINKING_LEVELS)[number];
21
+ declare function isThinkingLevel(value: string): boolean;
22
+ /** Accepts an empty value (backend default) or a canonical thinking level. */
23
+ declare function validateThinking(value: unknown): void;
24
+ type ThinkingOutcome = 'ok' | 'unsupportedCapability' | 'unsupportedValue' | 'startOnly';
25
+ /** Evaluates the schema-derived backend policy for a (backend, value, resume) combination. */
26
+ declare function evaluateThinkingPolicy(backend: string, value: string, resume?: boolean): ThinkingOutcome;
27
+ /** Accepts a value iff it is valid under the static backend policy (start). */
28
+ declare function validateThinkingForBackend(backend: string, value: unknown): void;
29
+ /** Accepts a value iff it is valid on an explicit resume for the backend. */
30
+ declare function validateThinkingForBackendResume(backend: string, value: unknown): void;
31
+ //#endregion
4
32
  //#region src/client.d.ts
5
33
  interface Event {
6
34
  event: string;
@@ -24,7 +52,6 @@ interface HistoryResult<TEvent = Event> {
24
52
  events: TEvent[];
25
53
  latest_seq?: number;
26
54
  }
27
- type ThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
28
55
  interface SpawnParams {
29
56
  agent?: string;
30
57
  prompt_file?: string;
@@ -41,6 +68,10 @@ interface SpawnParams {
41
68
  server_url?: string;
42
69
  session_id?: string;
43
70
  sentinel_file?: string;
71
+ workflow_id?: string;
72
+ node_id?: string;
73
+ activation_id?: string;
74
+ attempt_id?: string;
44
75
  on_event?: string;
45
76
  auto_approve?: boolean;
46
77
  [key: string]: unknown;
@@ -63,6 +94,52 @@ interface SpawnResult {
63
94
  effective_backend?: string;
64
95
  [key: string]: unknown;
65
96
  }
97
+ interface ExecutionIdentity {
98
+ supervisor_id?: string;
99
+ workflow_id?: string;
100
+ node_id?: string;
101
+ activation_id?: string;
102
+ attempt_id?: string;
103
+ run_id?: string;
104
+ runtime_id?: string;
105
+ session_id?: string;
106
+ }
107
+ type WorkflowGateOperation = 'satisfy' | 'reject' | 'waive' | 'external_result';
108
+ interface WorkflowCompleteParams {
109
+ workflow_id: string;
110
+ node_id: string;
111
+ activation_id: string;
112
+ attempt_id: string;
113
+ lease_id: string;
114
+ owner_token: string;
115
+ outcome: string;
116
+ outputs?: unknown;
117
+ artifacts?: unknown;
118
+ }
119
+ interface WorkflowGateParams {
120
+ workflow_id: string;
121
+ node_id: string;
122
+ gate_id: string;
123
+ activation_id: string;
124
+ operation: WorkflowGateOperation;
125
+ actor?: string;
126
+ reason?: string;
127
+ outcome?: string;
128
+ subject?: unknown;
129
+ poll_id?: string;
130
+ source?: string;
131
+ result?: string;
132
+ response_hash?: string;
133
+ observed_at?: string;
134
+ evidence_ids?: string[];
135
+ }
136
+ interface WorkflowHeartbeatParams {
137
+ workflow_id: string;
138
+ node_id: string;
139
+ activation_id?: string;
140
+ lease_id: string;
141
+ owner_token: string;
142
+ }
66
143
  declare class Client {
67
144
  private socket;
68
145
  private rl;
@@ -95,6 +172,28 @@ declare class Client {
95
172
  prompt(runtimeId: string, text: string): Promise<void>;
96
173
  interruptAndPrompt(runtimeId: string, text: string, keepQueue?: boolean): Promise<void>;
97
174
  cancel(runtimeId?: string): Promise<void>;
175
+ workflowStatus(workflowId: string): Promise<Record<string, unknown>>;
176
+ workflowWait(workflowId: string, timeoutMs?: number): Promise<Record<string, unknown>>;
177
+ workflowInspect(workflowId: string): Promise<Record<string, unknown>>;
178
+ workflowEvents(workflowId: string, opts?: {
179
+ afterSeq?: number;
180
+ limit?: number;
181
+ }): Promise<Record<string, unknown>>;
182
+ workflowCommand(workflowId: string, command: unknown): Promise<Record<string, unknown>>;
183
+ workflowComplete(params: WorkflowCompleteParams): Promise<Record<string, unknown>>;
184
+ workflowGate(params: WorkflowGateParams): Promise<Record<string, unknown>>;
185
+ workflowHeartbeat(params: WorkflowHeartbeatParams): Promise<Record<string, unknown>>;
186
+ brokerSend(fromRunId: string, toRunId: string, message: string, role?: string): Promise<void>;
187
+ brokerAsk(toRunId: string, message: string, role?: string): Promise<Record<string, unknown>>;
188
+ brokerPeers(): Promise<Array<Record<string, unknown>>>;
189
+ brokerCancel(messageId: string): Promise<void>;
190
+ brokerReceive(): Promise<Array<{
191
+ from_run_id: string;
192
+ message_id: string;
193
+ message: string;
194
+ role?: string;
195
+ }>>;
196
+ brokerReply(toRunId: string, replyTo: string, message: string): Promise<void>;
98
197
  isClosed(): boolean;
99
198
  close(): void;
100
199
  }
@@ -320,6 +419,14 @@ declare class Supervisor {
320
419
  //#region src/paths.d.ts
321
420
  declare function socketsRoot(): string;
322
421
  //#endregion
422
+ //#region src/tools/get-supervisor-client.d.ts
423
+ declare function getSupervisorClient(supervisorId: string): Promise<{
424
+ client: Client;
425
+ isSingleton: boolean;
426
+ sup: Supervisor | null;
427
+ supervisorId: string;
428
+ }>;
429
+ //#endregion
323
430
  //#region src/tools/spawn.d.ts
324
431
  interface SpawnToolArgs {
325
432
  agent?: string;
@@ -504,4 +611,128 @@ declare function shutdownTool(args: {
504
611
  cleaned_up: string[];
505
612
  }>;
506
613
  //#endregion
507
- export { type Client, DEFAULT_RUN_REDUCER_LIMITS, type Event, type FollowUpToolArgs, type FollowUpToolResult, type HistoryOptions, type HistoryResult, type InspectResult, type NormalizedRunEvent, type ObserveRunOptions, type ResultResult, type ResultToolArgs, type RunChunkRole, type RunIdentity, type RunInfo, type RunObserver, type RunObserverClient, type RunPermissionOption, type RunPermissionSummary, RunReducer, type RunReducerLimits, type RunSnapshot, type RunSnapshotSeed, type RunToolState, type RunToolSummary, type RunTranscriptEntry, type SpawnMetadata, type SpawnParams, type SpawnResult, type SpawnSelectionInput, type SpawnToolArgs, type SpawnToolResult, type StatusResult, type StatusToolArgs, type StatusView, type SubscribeOptions, Supervisor, type SupervisorOptions, type ThinkingLevel, answerPermissionTool, createRunSnapshot, dial, eventsTool, extractEventText, findAvenorBinary, followUpTool, getInstallDir, getVersion, inspectTool, installerBinaryPath, normalizeRunEvent, observeRun, reduceRunSnapshot, resultTool, shutdownTool, socketsRoot, spawnTool, statusTool, validateSpawnSelection };
614
+ //#region src/tools/ask.d.ts
615
+ interface AskToolArgs {
616
+ toRunId: string;
617
+ message: string;
618
+ supervisorId?: string;
619
+ }
620
+ interface AskResult {
621
+ reply: string;
622
+ from_run_id: string;
623
+ }
624
+ declare const askTool: (args: AskToolArgs) => Promise<AskResult>;
625
+ //#endregion
626
+ //#region src/tools/peers.d.ts
627
+ interface PeersToolArgs {
628
+ supervisorId?: string;
629
+ }
630
+ interface PeerEntry {
631
+ run_id: string;
632
+ label?: string;
633
+ status?: string;
634
+ backend?: string;
635
+ model?: string;
636
+ dir?: string;
637
+ }
638
+ interface PeersResult {
639
+ peers: PeerEntry[];
640
+ }
641
+ declare const peersTool: (args: PeersToolArgs) => Promise<PeersResult>;
642
+ //#endregion
643
+ //#region src/tools/cancel.d.ts
644
+ interface CancelToolArgs {
645
+ messageId: string;
646
+ supervisorId?: string;
647
+ }
648
+ interface CancelResult {
649
+ cancelled: boolean;
650
+ }
651
+ declare const cancelTool: (args: CancelToolArgs) => Promise<CancelResult>;
652
+ //#endregion
653
+ //#region src/tools/broker-receive.d.ts
654
+ interface BrokerReceiveArgs {
655
+ supervisorId?: string;
656
+ }
657
+ interface InboundAsk {
658
+ from_run_id: string;
659
+ message_id: string;
660
+ message: string;
661
+ role?: string;
662
+ }
663
+ interface BrokerReceiveResult {
664
+ asks: InboundAsk[];
665
+ }
666
+ declare const brokerReceiveTool: (args: BrokerReceiveArgs) => Promise<BrokerReceiveResult>;
667
+ //#endregion
668
+ //#region src/tools/broker-reply.d.ts
669
+ interface BrokerReplyArgs {
670
+ toRunId: string;
671
+ replyTo: string;
672
+ message: string;
673
+ supervisorId?: string;
674
+ }
675
+ interface BrokerReplyResult {
676
+ ok: true;
677
+ }
678
+ declare const brokerReplyTool: (args: BrokerReplyArgs) => Promise<BrokerReplyResult>;
679
+ //#endregion
680
+ //#region src/tools/workflow-client.d.ts
681
+ type GetSupervisorClient = typeof getSupervisorClient;
682
+ //#endregion
683
+ //#region src/tools/workflow-status.d.ts
684
+ interface WorkflowStatusToolArgs {
685
+ workflowId: string;
686
+ supervisorId?: string;
687
+ }
688
+ type WorkflowStatusResult = Record<string, unknown>;
689
+ declare function createWorkflowStatusTool(getSupervisorClient: GetSupervisorClient): (args: WorkflowStatusToolArgs) => Promise<WorkflowStatusResult>;
690
+ declare const workflowStatusTool: (args: WorkflowStatusToolArgs) => Promise<WorkflowStatusResult>;
691
+ //#endregion
692
+ //#region src/tools/workflow-wait.d.ts
693
+ interface WorkflowWaitToolArgs {
694
+ workflowId: string;
695
+ timeout?: string;
696
+ supervisorId?: string;
697
+ }
698
+ type WorkflowWaitResult = Record<string, unknown>;
699
+ declare function createWorkflowWaitTool(getSupervisorClient: GetSupervisorClient): (args: WorkflowWaitToolArgs) => Promise<WorkflowWaitResult>;
700
+ declare const workflowWaitTool: (args: WorkflowWaitToolArgs) => Promise<WorkflowWaitResult>;
701
+ //#endregion
702
+ //#region src/tools/workflow-inspect.d.ts
703
+ interface WorkflowInspectToolArgs {
704
+ workflowId: string;
705
+ supervisorId?: string;
706
+ }
707
+ type WorkflowInspectResult = Record<string, unknown>;
708
+ declare function createWorkflowInspectTool(getSupervisorClient: GetSupervisorClient): (args: WorkflowInspectToolArgs) => Promise<WorkflowInspectResult>;
709
+ declare const workflowInspectTool: (args: WorkflowInspectToolArgs) => Promise<WorkflowInspectResult>;
710
+ //#endregion
711
+ //#region src/tools/workflow-events.d.ts
712
+ interface WorkflowEventsToolArgs {
713
+ workflowId: string;
714
+ afterSeq?: number;
715
+ limit?: number;
716
+ supervisorId?: string;
717
+ }
718
+ type WorkflowEventsResult = Record<string, unknown>;
719
+ declare function createWorkflowEventsTool(getSupervisorClient: GetSupervisorClient): (args: WorkflowEventsToolArgs) => Promise<WorkflowEventsResult>;
720
+ declare const workflowEventsTool: (args: WorkflowEventsToolArgs) => Promise<WorkflowEventsResult>;
721
+ //#endregion
722
+ //#region src/tools/workflow-complete.d.ts
723
+ interface WorkflowCompleteToolArgs extends WorkflowCompleteParams {
724
+ supervisorId?: string;
725
+ }
726
+ type WorkflowCompleteResult = Record<string, unknown>;
727
+ declare function createWorkflowCompleteTool(getSupervisorClient: GetSupervisorClient): (args: WorkflowCompleteToolArgs) => Promise<WorkflowCompleteResult>;
728
+ declare const workflowCompleteTool: (args: WorkflowCompleteToolArgs) => Promise<WorkflowCompleteResult>;
729
+ //#endregion
730
+ //#region src/tools/workflow-gate.d.ts
731
+ interface WorkflowGateToolArgs extends WorkflowGateParams {
732
+ supervisorId?: string;
733
+ }
734
+ type WorkflowGateResult = Record<string, unknown>;
735
+ declare function createWorkflowGateTool(getSupervisorClient: GetSupervisorClient): (args: WorkflowGateToolArgs) => Promise<WorkflowGateResult>;
736
+ declare const workflowGateTool: (args: WorkflowGateToolArgs) => Promise<WorkflowGateResult>;
737
+ //#endregion
738
+ export { type AskResult, type AskToolArgs, type BrokerReceiveArgs, type BrokerReceiveResult, type BrokerReplyArgs, type BrokerReplyResult, type CancelResult, type CancelToolArgs, type Client, DEFAULT_RUN_REDUCER_LIMITS, type Event, type ExecutionIdentity, type FollowUpToolArgs, type FollowUpToolResult, type HistoryOptions, type HistoryResult, type InboundAsk, type InspectResult, type NormalizedRunEvent, type ObserveRunOptions, type PeerEntry, type PeersResult, type ResultResult, type ResultToolArgs, type RunChunkRole, type RunIdentity, type RunInfo, type RunObserver, type RunObserverClient, type RunPermissionOption, type RunPermissionSummary, RunReducer, type RunReducerLimits, type RunSnapshot, type RunSnapshotSeed, type RunToolState, type RunToolSummary, type RunTranscriptEntry, type SpawnMetadata, type SpawnParams, type SpawnResult, type SpawnSelectionInput, type SpawnToolArgs, type SpawnToolResult, type StatusResult, type StatusToolArgs, type StatusView, type SubscribeOptions, Supervisor, type SupervisorOptions, THINKING_LEVELS, type ThinkingLevel, type ThinkingOutcome, type WorkflowCompleteParams, type WorkflowCompleteResult, type WorkflowCompleteToolArgs, type WorkflowEventsResult, type WorkflowEventsToolArgs, type WorkflowGateOperation, type WorkflowGateParams, type WorkflowGateResult, type WorkflowGateToolArgs, type WorkflowHeartbeatParams, type WorkflowInspectResult, type WorkflowInspectToolArgs, type WorkflowStatusResult, type WorkflowStatusToolArgs, type WorkflowWaitResult, type WorkflowWaitToolArgs, answerPermissionTool, askTool, brokerReceiveTool, brokerReplyTool, cancelTool, createRunSnapshot, createWorkflowCompleteTool, createWorkflowEventsTool, createWorkflowGateTool, createWorkflowInspectTool, createWorkflowStatusTool, createWorkflowWaitTool, dial, evaluateThinkingPolicy, eventsTool, extractEventText, findAvenorBinary, followUpTool, getInstallDir, getVersion, inspectTool, installerBinaryPath, isThinkingLevel, normalizeRunEvent, observeRun, peersTool, reduceRunSnapshot, resultTool, shutdownTool, socketsRoot, spawnTool, statusTool, validateSpawnSelection, validateThinking, validateThinkingForBackend, validateThinkingForBackendResume, workflowCompleteTool, workflowEventsTool, workflowGateTool, workflowInspectTool, workflowStatusTool, workflowWaitTool };
package/dist/index.js CHANGED
@@ -282,6 +282,107 @@ var Client = class {
282
282
  const params = runtimeId ? { runtime_id: runtimeId } : void 0;
283
283
  await this.call("cancel", params);
284
284
  }
285
+ async workflowStatus(workflowId) {
286
+ return this.call("workflow.status", { workflow_id: workflowId });
287
+ }
288
+ async workflowWait(workflowId, timeoutMs) {
289
+ const params = { workflow_id: workflowId };
290
+ if (timeoutMs !== void 0) params.timeout_ms = timeoutMs;
291
+ return this.call("workflow.wait", params);
292
+ }
293
+ async workflowInspect(workflowId) {
294
+ return this.call("workflow.inspect", { workflow_id: workflowId });
295
+ }
296
+ async workflowEvents(workflowId, opts) {
297
+ const params = { workflow_id: workflowId };
298
+ if (opts?.afterSeq !== void 0) params.after_seq = opts.afterSeq;
299
+ if (opts?.limit !== void 0) params.limit = opts.limit;
300
+ return this.call("workflow.events", params);
301
+ }
302
+ async workflowCommand(workflowId, command) {
303
+ return this.call("workflow.command", {
304
+ workflow_id: workflowId,
305
+ command
306
+ });
307
+ }
308
+ async workflowComplete(params) {
309
+ const command = {
310
+ op: "complete",
311
+ node_id: params.node_id,
312
+ activation_id: params.activation_id,
313
+ attempt_id: params.attempt_id,
314
+ lease_id: params.lease_id,
315
+ owner_token: params.owner_token,
316
+ outcome: params.outcome
317
+ };
318
+ if (params.outputs !== void 0) command.outputs = params.outputs;
319
+ if (params.artifacts !== void 0) command.artifacts = params.artifacts;
320
+ return this.workflowCommand(params.workflow_id, command);
321
+ }
322
+ async workflowGate(params) {
323
+ const command = {
324
+ op: "gate",
325
+ node_id: params.node_id,
326
+ activation_id: params.activation_id,
327
+ gate_id: params.gate_id,
328
+ operation: params.operation
329
+ };
330
+ const optional = [
331
+ ["actor", params.actor],
332
+ ["reason", params.reason],
333
+ ["outcome", params.outcome],
334
+ ["subject", params.subject],
335
+ ["poll_id", params.poll_id],
336
+ ["source", params.source],
337
+ ["result", params.result],
338
+ ["response_hash", params.response_hash],
339
+ ["observed_at", params.observed_at],
340
+ ["evidence_ids", params.evidence_ids]
341
+ ];
342
+ for (const [key, value] of optional) if (value !== void 0) command[key] = value;
343
+ return this.workflowCommand(params.workflow_id, command);
344
+ }
345
+ async workflowHeartbeat(params) {
346
+ const command = {
347
+ op: "heartbeat",
348
+ node_id: params.node_id,
349
+ lease_id: params.lease_id,
350
+ owner_token: params.owner_token
351
+ };
352
+ if (params.activation_id !== void 0) command.activation_id = params.activation_id;
353
+ return this.workflowCommand(params.workflow_id, command);
354
+ }
355
+ async brokerSend(fromRunId, toRunId, message, role) {
356
+ await this.call("broker_send", {
357
+ from_run_id: fromRunId,
358
+ to_run_id: toRunId,
359
+ message,
360
+ role: role ?? "agent"
361
+ });
362
+ }
363
+ async brokerAsk(toRunId, message, role) {
364
+ return await this.call("broker_ask", {
365
+ to_run_id: toRunId,
366
+ message,
367
+ role: role ?? "agent"
368
+ });
369
+ }
370
+ async brokerPeers() {
371
+ return (await this.call("broker_peers")).sessions ?? [];
372
+ }
373
+ async brokerCancel(messageId) {
374
+ await this.call("broker_cancel", { message_id: messageId });
375
+ }
376
+ async brokerReceive() {
377
+ return await this.call("broker_receive");
378
+ }
379
+ async brokerReply(toRunId, replyTo, message) {
380
+ await this.call("broker_reply", {
381
+ to_run_id: toRunId,
382
+ reply_to: replyTo,
383
+ message
384
+ });
385
+ }
285
386
  isClosed() {
286
387
  return this.closed || this.socket.destroyed || this.socket.writableEnded;
287
388
  }
@@ -1534,6 +1635,9 @@ function validateSupervisorSocketPath(supervisorId) {
1534
1635
  if (parent !== root || !/^avenor-mcp-[^/\\]+\.sock$/.test(basename)) throw new Error(`invalid supervisorId: ${supervisorId}`);
1535
1636
  return path.join(parent, basename);
1536
1637
  }
1638
+ function validateObservedAt(observedAt) {
1639
+ if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(observedAt)) throw new Error("observed_at must be an RFC3339 timestamp");
1640
+ }
1537
1641
  //#endregion
1538
1642
  //#region src/tools/get-supervisor-client.ts
1539
1643
  async function getSupervisorClient(supervisorId) {
@@ -1763,6 +1867,232 @@ function createSpawnTool(getSupervisorClient) {
1763
1867
  }
1764
1868
  const spawnTool = createSpawnTool(getSupervisorClient);
1765
1869
  //#endregion
1870
+ //#region ../../schemas/thinking_policy.umpire.json
1871
+ var thinking_policy_umpire_default = {
1872
+ version: 1,
1873
+ conditions: {
1874
+ "backend": {
1875
+ "type": "string",
1876
+ "description": "Backend identifier (e.g. codex-app-server, pi, claude)."
1877
+ },
1878
+ "resume": {
1879
+ "type": "boolean",
1880
+ "description": "Whether the value is being applied on an explicit resume rather than a fresh start."
1881
+ }
1882
+ },
1883
+ fields: { "thinking": {
1884
+ "isEmpty": "string",
1885
+ "description": "Canonical thinking level, or empty to use the backend default."
1886
+ } },
1887
+ rules: [{
1888
+ "type": "check",
1889
+ "field": "thinking",
1890
+ "check": {
1891
+ "op": "in",
1892
+ "field": "thinking",
1893
+ "value": [
1894
+ "off",
1895
+ "minimal",
1896
+ "low",
1897
+ "medium",
1898
+ "high",
1899
+ "xhigh",
1900
+ "max"
1901
+ ]
1902
+ },
1903
+ "reason": "not a canonical thinking value (off, minimal, low, medium, high, xhigh, max)"
1904
+ }, {
1905
+ "type": "eitherOf",
1906
+ "group": "thinkingPolicy",
1907
+ "field": "thinking",
1908
+ "branches": {
1909
+ "empty": [{
1910
+ "type": "fairWhen",
1911
+ "field": "thinking",
1912
+ "when": {
1913
+ "op": "absent",
1914
+ "field": "thinking"
1915
+ },
1916
+ "reason": "thinking is empty (backend default)"
1917
+ }],
1918
+ "fullSupport": [{
1919
+ "type": "fairWhen",
1920
+ "field": "thinking",
1921
+ "when": {
1922
+ "op": "and",
1923
+ "exprs": [{
1924
+ "op": "condIn",
1925
+ "condition": "backend",
1926
+ "values": ["codex-app-server", "pi"]
1927
+ }, {
1928
+ "op": "in",
1929
+ "field": "thinking",
1930
+ "values": [
1931
+ "off",
1932
+ "minimal",
1933
+ "low",
1934
+ "medium",
1935
+ "high",
1936
+ "xhigh",
1937
+ "max"
1938
+ ]
1939
+ }]
1940
+ },
1941
+ "reason": "codex-app-server and pi support all canonical thinking values on start and resume"
1942
+ }],
1943
+ "claudeStart": [{
1944
+ "type": "fairWhen",
1945
+ "field": "thinking",
1946
+ "when": {
1947
+ "op": "and",
1948
+ "exprs": [
1949
+ {
1950
+ "op": "condIn",
1951
+ "condition": "backend",
1952
+ "values": ["claude", "claude-channel"]
1953
+ },
1954
+ {
1955
+ "op": "condEq",
1956
+ "condition": "resume",
1957
+ "value": false
1958
+ },
1959
+ {
1960
+ "op": "in",
1961
+ "field": "thinking",
1962
+ "values": [
1963
+ "low",
1964
+ "medium",
1965
+ "high",
1966
+ "xhigh",
1967
+ "max"
1968
+ ]
1969
+ }
1970
+ ]
1971
+ },
1972
+ "reason": "claude and claude-channel support low through max only on a new session"
1973
+ }]
1974
+ }
1975
+ }]
1976
+ };
1977
+ //#endregion
1978
+ //#region src/thinking-policy.ts
1979
+ /**
1980
+ * Portable thinking-policy contract.
1981
+ *
1982
+ * THINKING_LEVELS is the single TypeScript source for the canonical tuple and
1983
+ * is exported for hosts (MCP, OpenCode, Pi) to derive their enums from. It is
1984
+ * verified against schemas/thinking_policy.umpire.json and the Go tuple by
1985
+ * introspection and conformance tests so all languages agree.
1986
+ *
1987
+ * The backend policy (which canonical values each backend supports, on start
1988
+ * vs. explicit resume) is modelled directly in the Umpire schema's eitherOf
1989
+ * branches with fairWhen rules and conditions (backend, resume). Both Go and
1990
+ * TypeScript derive the policy from the schema, eliminating hand-written
1991
+ * policy tables that could drift apart.
1992
+ */
1993
+ const THINKING_LEVELS = [
1994
+ "off",
1995
+ "minimal",
1996
+ "low",
1997
+ "medium",
1998
+ "high",
1999
+ "xhigh",
2000
+ "max"
2001
+ ];
2002
+ function isThinkingLevel(value) {
2003
+ return THINKING_LEVELS.includes(value);
2004
+ }
2005
+ /** Accepts an empty value (backend default) or a canonical thinking level. */
2006
+ function validateThinking(value) {
2007
+ if (value === void 0 || value === "") return;
2008
+ if (typeof value !== "string" || !isThinkingLevel(value)) throw new Error(`invalid thinking value ${JSON.stringify(value)} (allowed: ${THINKING_LEVELS.join(", ")})`);
2009
+ }
2010
+ const thinkingSchema = thinking_policy_umpire_default;
2011
+ thinkingSchema.rules.find((r) => r.check?.op === "in")?.check?.value;
2012
+ const policyBranches = (() => {
2013
+ const eitherOf = thinkingSchema.rules.find((r) => r.type === "eitherOf");
2014
+ if (!eitherOf?.branches) return [];
2015
+ const branches = [];
2016
+ for (const branchRules of Object.values(eitherOf.branches)) for (const rule of branchRules) if (rule.type === "fairWhen") branches.push({
2017
+ when: rule.when,
2018
+ reason: rule.reason
2019
+ });
2020
+ return branches;
2021
+ })();
2022
+ const supportedBackends = (() => {
2023
+ const backends = /* @__PURE__ */ new Set();
2024
+ for (const branch of policyBranches) collectBackends(branch.when, backends);
2025
+ return backends;
2026
+ })();
2027
+ function collectBackends(expr, backends) {
2028
+ if (expr.op === "condIn" && expr.condition === "backend") {
2029
+ for (const v of expr.values) backends.add(v);
2030
+ return;
2031
+ }
2032
+ if (expr.op === "and" || expr.op === "or") for (const sub of expr.exprs) collectBackends(sub, backends);
2033
+ }
2034
+ function evalExpr(expr, value, backend, resume) {
2035
+ switch (expr.op) {
2036
+ case "absent": return value === "";
2037
+ case "in": return expr.values.includes(value);
2038
+ case "condIn": return expr.condition === "backend" && expr.values.includes(backend);
2039
+ case "condEq":
2040
+ if (expr.condition === "backend") return backend === expr.value;
2041
+ if (expr.condition === "resume") return resume === expr.value;
2042
+ return false;
2043
+ case "and": return expr.exprs.every((e) => evalExpr(e, value, backend, resume));
2044
+ case "or": return expr.exprs.some((e) => evalExpr(e, value, backend, resume));
2045
+ default: return false;
2046
+ }
2047
+ }
2048
+ /** Evaluates the schema-derived backend policy for a (backend, value, resume) combination. */
2049
+ function evaluateThinkingPolicy(backend, value, resume = false) {
2050
+ if (value === "") return "ok";
2051
+ if (policyBranches.some((b) => evalExpr(b.when, value, backend, resume))) return "ok";
2052
+ if (!supportedBackends.has(backend)) return "unsupportedCapability";
2053
+ if (resume) {
2054
+ if (policyBranches.some((b) => evalExpr(b.when, value, backend, false))) return "startOnly";
2055
+ }
2056
+ return "unsupportedValue";
2057
+ }
2058
+ /** Returns the canonical values supported by backend on a fresh start. */
2059
+ function startValues(backend) {
2060
+ if (!supportedBackends.has(backend)) return [];
2061
+ return THINKING_LEVELS.filter((v) => policyBranches.some((b) => evalExpr(b.when, v, backend, false)));
2062
+ }
2063
+ /** Returns the canonical values supported by backend on an explicit resume. */
2064
+ function resumeValues(backend) {
2065
+ if (!supportedBackends.has(backend)) return [];
2066
+ return THINKING_LEVELS.filter((v) => policyBranches.some((b) => evalExpr(b.when, v, backend, true)));
2067
+ }
2068
+ /** Accepts a value iff it is valid under the static backend policy (start). */
2069
+ function validateThinkingForBackend(backend, value) {
2070
+ validateThinking(value);
2071
+ const v = value === void 0 ? "" : String(value);
2072
+ if (v === "") return;
2073
+ const outcome = evaluateThinkingPolicy(backend, v, false);
2074
+ if (outcome === "ok") return;
2075
+ if (outcome === "unsupportedValue") {
2076
+ const allowed = startValues(backend).join(", ");
2077
+ throw new Error(`backend ${JSON.stringify(backend)} does not support thinking value ${JSON.stringify(v)} (allowed: ${allowed})`);
2078
+ }
2079
+ throw new Error(`backend ${JSON.stringify(backend)} does not support parameter "thinking"`);
2080
+ }
2081
+ /** Accepts a value iff it is valid on an explicit resume for the backend. */
2082
+ function validateThinkingForBackendResume(backend, value) {
2083
+ validateThinking(value);
2084
+ const v = value === void 0 ? "" : String(value);
2085
+ if (v === "") return;
2086
+ const outcome = evaluateThinkingPolicy(backend, v, true);
2087
+ if (outcome === "ok") return;
2088
+ if (outcome === "startOnly") throw new Error(`backend ${JSON.stringify(backend)} supports parameter "thinking" only when starting a session`);
2089
+ if (outcome === "unsupportedValue") {
2090
+ const allowed = resumeValues(backend).join(", ");
2091
+ throw new Error(`backend ${JSON.stringify(backend)} does not support thinking value ${JSON.stringify(v)} (allowed: ${allowed})`);
2092
+ }
2093
+ throw new Error(`backend ${JSON.stringify(backend)} does not support parameter "thinking"`);
2094
+ }
2095
+ //#endregion
1766
2096
  //#region src/tools/run-resolution.ts
1767
2097
  /** Resolve a local public run ID before considering a label alias. */
1768
2098
  function findLocalRunByReference(sup, reference) {
@@ -2674,4 +3004,184 @@ async function shutdownTool(args) {
2674
3004
  };
2675
3005
  }
2676
3006
  //#endregion
2677
- export { DEFAULT_RUN_REDUCER_LIMITS, RunReducer, Supervisor, answerPermissionTool, createRunSnapshot, dial, eventsTool, extractEventText, findAvenorBinary, followUpTool, getInstallDir, getVersion, inspectTool, installerBinaryPath, normalizeRunEvent, observeRun, reduceRunSnapshot, resultTool, shutdownTool, socketsRoot, spawnTool, statusTool, validateSpawnSelection };
3007
+ //#region src/tools/ask.ts
3008
+ function extractReplyMessage(result) {
3009
+ if (result.timeout === true) return "(timeout: no reply received)";
3010
+ if (result.cancelled === true) return "(cancelled)";
3011
+ const payload = result.payload;
3012
+ if (payload && typeof payload === "object") {
3013
+ const msg = payload.message;
3014
+ if (typeof msg === "string" && msg) return msg;
3015
+ }
3016
+ return JSON.stringify(result);
3017
+ }
3018
+ async function executeAskTool(args, getSupervisorClient) {
3019
+ const { client, isSingleton } = await getSupervisorClient(args.supervisorId);
3020
+ try {
3021
+ const result = await client.brokerAsk(args.toRunId, args.message);
3022
+ return {
3023
+ reply: extractReplyMessage(result),
3024
+ from_run_id: result.from_run_id ?? ""
3025
+ };
3026
+ } finally {
3027
+ if (!isSingleton) client.close();
3028
+ }
3029
+ }
3030
+ function createAskTool(getSupervisorClient) {
3031
+ return (args) => executeAskTool(args, getSupervisorClient);
3032
+ }
3033
+ const askTool = createAskTool(getSupervisorClient);
3034
+ //#endregion
3035
+ //#region src/tools/peers.ts
3036
+ async function executePeersTool(args, getSupervisorClient) {
3037
+ const { client, isSingleton } = await getSupervisorClient(args.supervisorId);
3038
+ try {
3039
+ return { peers: await client.brokerPeers() };
3040
+ } finally {
3041
+ if (!isSingleton) client.close();
3042
+ }
3043
+ }
3044
+ function createPeersTool(getSupervisorClient) {
3045
+ return (args) => executePeersTool(args, getSupervisorClient);
3046
+ }
3047
+ const peersTool = createPeersTool(getSupervisorClient);
3048
+ //#endregion
3049
+ //#region src/tools/cancel.ts
3050
+ async function executeCancelTool(args, getSupervisorClient) {
3051
+ const { client, isSingleton } = await getSupervisorClient(args.supervisorId);
3052
+ try {
3053
+ await client.brokerCancel(args.messageId);
3054
+ return { cancelled: true };
3055
+ } finally {
3056
+ if (!isSingleton) client.close();
3057
+ }
3058
+ }
3059
+ function createCancelTool(getSupervisorClient) {
3060
+ return (args) => executeCancelTool(args, getSupervisorClient);
3061
+ }
3062
+ const cancelTool = createCancelTool(getSupervisorClient);
3063
+ //#endregion
3064
+ //#region src/tools/broker-receive.ts
3065
+ async function executeBrokerReceive(args, getSupervisorClient) {
3066
+ const { client, isSingleton } = await getSupervisorClient(args.supervisorId);
3067
+ try {
3068
+ return { asks: await client.brokerReceive() };
3069
+ } finally {
3070
+ if (!isSingleton) client.close();
3071
+ }
3072
+ }
3073
+ function createBrokerReceiveTool(getSupervisorClient) {
3074
+ return (args) => executeBrokerReceive(args, getSupervisorClient);
3075
+ }
3076
+ const brokerReceiveTool = createBrokerReceiveTool(getSupervisorClient);
3077
+ //#endregion
3078
+ //#region src/tools/broker-reply.ts
3079
+ async function executeBrokerReply(args, getSupervisorClient) {
3080
+ const { client, isSingleton } = await getSupervisorClient(args.supervisorId);
3081
+ try {
3082
+ await client.brokerReply(args.toRunId, args.replyTo, args.message);
3083
+ return { ok: true };
3084
+ } finally {
3085
+ if (!isSingleton) client.close();
3086
+ }
3087
+ }
3088
+ function createBrokerReplyTool(getSupervisorClient) {
3089
+ return (args) => executeBrokerReply(args, getSupervisorClient);
3090
+ }
3091
+ const brokerReplyTool = createBrokerReplyTool(getSupervisorClient);
3092
+ //#endregion
3093
+ //#region src/tools/workflow-client.ts
3094
+ /**
3095
+ * Run `work` against the client for the given supervisor, or the singleton when none is
3096
+ * supplied. External supervisors are dialed on demand and closed again; the singleton client is
3097
+ * reused. Workflow host tools correlate by supervisor ID so runtime ids (e.g. rt_1) that collide
3098
+ * across supervisors never route to the wrong host.
3099
+ */
3100
+ async function withWorkflowClient(supervisorId, work, getSupervisorClient$1 = getSupervisorClient) {
3101
+ if (supervisorId) {
3102
+ const { client, isSingleton } = await getSupervisorClient$1(supervisorId);
3103
+ try {
3104
+ return await work(client);
3105
+ } finally {
3106
+ if (!isSingleton) client.close();
3107
+ }
3108
+ }
3109
+ return work((await Supervisor.get()).getClient());
3110
+ }
3111
+ //#endregion
3112
+ //#region src/tools/workflow-status.ts
3113
+ function createWorkflowStatusTool(getSupervisorClient) {
3114
+ return async (args) => {
3115
+ if (!args.workflowId) throw new Error("workflowId is required");
3116
+ return withWorkflowClient(args.supervisorId, (client) => client.workflowStatus(args.workflowId), getSupervisorClient);
3117
+ };
3118
+ }
3119
+ const workflowStatusTool = createWorkflowStatusTool(getSupervisorClient);
3120
+ //#endregion
3121
+ //#region src/tools/workflow-wait.ts
3122
+ function createWorkflowWaitTool(getSupervisorClient) {
3123
+ return async (args) => {
3124
+ if (!args.workflowId) throw new Error("workflowId is required");
3125
+ const timeoutMs = args.timeout ? validateTimeout(args.timeout) * 1e3 : 3e4;
3126
+ return withWorkflowClient(args.supervisorId, (client) => client.workflowWait(args.workflowId, timeoutMs), getSupervisorClient);
3127
+ };
3128
+ }
3129
+ const workflowWaitTool = createWorkflowWaitTool(getSupervisorClient);
3130
+ //#endregion
3131
+ //#region src/tools/workflow-inspect.ts
3132
+ function createWorkflowInspectTool(getSupervisorClient) {
3133
+ return async (args) => {
3134
+ if (!args.workflowId) throw new Error("workflowId is required");
3135
+ return withWorkflowClient(args.supervisorId, (client) => client.workflowInspect(args.workflowId), getSupervisorClient);
3136
+ };
3137
+ }
3138
+ const workflowInspectTool = createWorkflowInspectTool(getSupervisorClient);
3139
+ //#endregion
3140
+ //#region src/tools/workflow-events.ts
3141
+ function createWorkflowEventsTool(getSupervisorClient) {
3142
+ return async (args) => {
3143
+ if (!args.workflowId) throw new Error("workflowId is required");
3144
+ return withWorkflowClient(args.supervisorId, (client) => client.workflowEvents(args.workflowId, {
3145
+ afterSeq: args.afterSeq,
3146
+ limit: args.limit
3147
+ }), getSupervisorClient);
3148
+ };
3149
+ }
3150
+ const workflowEventsTool = createWorkflowEventsTool(getSupervisorClient);
3151
+ //#endregion
3152
+ //#region src/tools/workflow-complete.ts
3153
+ function createWorkflowCompleteTool(getSupervisorClient) {
3154
+ return async (args) => {
3155
+ if (!args.workflow_id) throw new Error("workflow_id is required");
3156
+ if (!args.node_id) throw new Error("node_id is required");
3157
+ if (!args.activation_id) throw new Error("activation_id is required");
3158
+ if (!args.attempt_id) throw new Error("attempt_id is required");
3159
+ if (!args.lease_id) throw new Error("lease_id is required");
3160
+ if (!args.owner_token) throw new Error("owner_token is required");
3161
+ if (!args.outcome) throw new Error("outcome is required");
3162
+ return withWorkflowClient(args.supervisorId, (client) => client.workflowComplete(args), getSupervisorClient);
3163
+ };
3164
+ }
3165
+ const workflowCompleteTool = createWorkflowCompleteTool(getSupervisorClient);
3166
+ //#endregion
3167
+ //#region src/tools/workflow-gate.ts
3168
+ function createWorkflowGateTool(getSupervisorClient) {
3169
+ return async (args) => {
3170
+ if (!args.workflow_id) throw new Error("workflow_id is required");
3171
+ if (!args.node_id) throw new Error("node_id is required");
3172
+ if (!args.gate_id) throw new Error("gate_id is required");
3173
+ if (!args.activation_id) throw new Error("activation_id is required");
3174
+ if (!args.operation) throw new Error("operation is required");
3175
+ if (![
3176
+ "satisfy",
3177
+ "reject",
3178
+ "waive",
3179
+ "external_result"
3180
+ ].includes(args.operation)) throw new Error(`unknown gate operation "${args.operation}" (allowed: satisfy, reject, waive, external_result)`);
3181
+ if (args.observed_at) validateObservedAt(args.observed_at);
3182
+ return withWorkflowClient(args.supervisorId, (client) => client.workflowGate(args), getSupervisorClient);
3183
+ };
3184
+ }
3185
+ const workflowGateTool = createWorkflowGateTool(getSupervisorClient);
3186
+ //#endregion
3187
+ export { DEFAULT_RUN_REDUCER_LIMITS, RunReducer, Supervisor, THINKING_LEVELS, answerPermissionTool, askTool, brokerReceiveTool, brokerReplyTool, cancelTool, createRunSnapshot, createWorkflowCompleteTool, createWorkflowEventsTool, createWorkflowGateTool, createWorkflowInspectTool, createWorkflowStatusTool, createWorkflowWaitTool, dial, evaluateThinkingPolicy, eventsTool, extractEventText, findAvenorBinary, followUpTool, getInstallDir, getVersion, inspectTool, installerBinaryPath, isThinkingLevel, normalizeRunEvent, observeRun, peersTool, reduceRunSnapshot, resultTool, shutdownTool, socketsRoot, spawnTool, statusTool, validateSpawnSelection, validateThinking, validateThinkingForBackend, validateThinkingForBackendResume, workflowCompleteTool, workflowEventsTool, workflowGateTool, workflowInspectTool, workflowStatusTool, workflowWaitTool };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dougbots/avenor-core",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",