@qvac/harness 0.7.1 → 1.0.0-rc.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.
Files changed (201) hide show
  1. package/README.md +224 -0
  2. package/dist-lib/index.d.ts +55 -3
  3. package/dist-lib/index.js +721 -236
  4. package/dist-lib/lib/capabilities/completion-engine/abort-polyfill.d.ts +1 -0
  5. package/dist-lib/lib/capabilities/completion-engine/abort-polyfill.js +10 -0
  6. package/dist-lib/lib/capabilities/completion-engine/actors/answering.d.ts +3 -0
  7. package/dist-lib/lib/capabilities/completion-engine/actors/answering.js +17 -0
  8. package/dist-lib/lib/capabilities/completion-engine/actors/approval.d.ts +4 -0
  9. package/dist-lib/lib/capabilities/completion-engine/actors/approval.js +29 -0
  10. package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.d.ts +4 -0
  11. package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.js +73 -0
  12. package/dist-lib/lib/capabilities/completion-engine/actors/execute.d.ts +41 -0
  13. package/dist-lib/lib/capabilities/completion-engine/actors/execute.js +49 -0
  14. package/dist-lib/lib/capabilities/completion-engine/actors/executing.d.ts +3 -0
  15. package/dist-lib/lib/capabilities/completion-engine/actors/executing.js +102 -0
  16. package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.d.ts +47 -0
  17. package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.js +87 -0
  18. package/dist-lib/lib/capabilities/completion-engine/actors/finishing.d.ts +2 -0
  19. package/dist-lib/lib/capabilities/completion-engine/actors/finishing.js +32 -0
  20. package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.d.ts +3 -0
  21. package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.js +75 -0
  22. package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.d.ts +3 -0
  23. package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.js +152 -0
  24. package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.d.ts +3 -0
  25. package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.js +94 -0
  26. package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.d.ts +9 -0
  27. package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.js +11 -0
  28. package/dist-lib/lib/capabilities/completion-engine/actors/preloading.d.ts +3 -0
  29. package/dist-lib/lib/capabilities/completion-engine/actors/preloading.js +114 -0
  30. package/dist-lib/lib/capabilities/completion-engine/actors/preparing.d.ts +3 -0
  31. package/dist-lib/lib/capabilities/completion-engine/actors/preparing.js +198 -0
  32. package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.d.ts +3 -0
  33. package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.js +71 -0
  34. package/dist-lib/lib/capabilities/completion-engine/actors/rejection.d.ts +18 -0
  35. package/dist-lib/lib/capabilities/completion-engine/actors/rejection.js +70 -0
  36. package/dist-lib/lib/capabilities/completion-engine/actors/resolving.d.ts +3 -0
  37. package/dist-lib/lib/capabilities/completion-engine/actors/resolving.js +60 -0
  38. package/dist-lib/lib/capabilities/completion-engine/actors/stream.d.ts +21 -0
  39. package/dist-lib/lib/capabilities/completion-engine/actors/stream.js +48 -0
  40. package/dist-lib/lib/capabilities/completion-engine/actors/streaming.d.ts +3 -0
  41. package/dist-lib/lib/capabilities/completion-engine/actors/streaming.js +156 -0
  42. package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.d.ts +7 -0
  43. package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.js +61 -0
  44. package/dist-lib/lib/capabilities/completion-engine/driver.d.ts +25 -0
  45. package/dist-lib/lib/capabilities/completion-engine/driver.js +553 -0
  46. package/dist-lib/lib/capabilities/completion-engine/durable.d.ts +61 -0
  47. package/dist-lib/lib/capabilities/completion-engine/durable.js +150 -0
  48. package/dist-lib/lib/capabilities/completion-engine/operations.d.ts +6 -0
  49. package/dist-lib/lib/capabilities/completion-engine/operations.js +239 -0
  50. package/dist-lib/lib/capabilities/completion-engine/ports.d.ts +3 -0
  51. package/dist-lib/lib/capabilities/completion-engine/ports.js +267 -0
  52. package/dist-lib/lib/capabilities/completion-engine/session.d.ts +76 -0
  53. package/dist-lib/lib/capabilities/completion-engine/session.js +70 -0
  54. package/dist-lib/lib/capabilities/completion-loop/index.d.ts +80 -0
  55. package/dist-lib/lib/capabilities/completion-loop/index.js +158 -0
  56. package/dist-lib/lib/capabilities/completion-loop/metrics.d.ts +5 -0
  57. package/dist-lib/lib/capabilities/completion-loop/metrics.js +29 -0
  58. package/dist-lib/lib/capabilities/completion-loop/round.d.ts +33 -0
  59. package/dist-lib/lib/capabilities/completion-loop/round.js +353 -0
  60. package/dist-lib/lib/capabilities/completion-loop/tool-execution.d.ts +60 -0
  61. package/dist-lib/lib/capabilities/completion-loop/tool-execution.js +270 -0
  62. package/dist-lib/lib/capabilities/completion-loop/turns.d.ts +23 -0
  63. package/dist-lib/lib/capabilities/completion-loop/turns.js +112 -0
  64. package/dist-lib/lib/capabilities/completion-runtime.d.ts +46 -0
  65. package/dist-lib/lib/capabilities/completion-runtime.js +74 -0
  66. package/dist-lib/lib/capabilities/completion.d.ts +18 -335
  67. package/dist-lib/lib/capabilities/completion.js +20 -1301
  68. package/dist-lib/lib/capabilities/download.d.ts +1 -1
  69. package/dist-lib/lib/capabilities/download.js +7 -2
  70. package/dist-lib/lib/capabilities/invoke.js +5 -3
  71. package/dist-lib/lib/capabilities/tool-plan.d.ts +35 -0
  72. package/dist-lib/lib/capabilities/tool-plan.js +66 -0
  73. package/dist-lib/lib/capabilities/tool-turns.d.ts +11 -2
  74. package/dist-lib/lib/capabilities/tool-turns.js +30 -2
  75. package/dist-lib/lib/capabilities/types.d.ts +287 -0
  76. package/dist-lib/lib/capabilities/types.js +1 -0
  77. package/dist-lib/lib/completion-lifecycle.d.ts +14 -0
  78. package/dist-lib/lib/completion-lifecycle.js +126 -0
  79. package/dist-lib/lib/connect.d.ts +10 -3
  80. package/dist-lib/lib/connect.js +329 -23
  81. package/dist-lib/lib/contract-types.d.ts +19 -2
  82. package/dist-lib/lib/harness-lifecycle.d.ts +66 -0
  83. package/dist-lib/lib/harness-lifecycle.js +129 -0
  84. package/dist-lib/lib/helpers/detach-json.d.ts +1 -0
  85. package/dist-lib/lib/helpers/detach-json.js +146 -0
  86. package/dist-lib/lib/helpers/markup-scanner.d.ts +26 -0
  87. package/dist-lib/lib/helpers/markup-scanner.js +156 -0
  88. package/dist-lib/lib/helpers/markup-stream-filter.js +138 -35
  89. package/dist-lib/lib/helpers/race-abort.d.ts +9 -4
  90. package/dist-lib/lib/helpers/race-abort.js +2 -7
  91. package/dist-lib/lib/helpers/recovery-required.d.ts +1 -0
  92. package/dist-lib/lib/helpers/recovery-required.js +1 -0
  93. package/dist-lib/lib/helpers/run-outcome.d.ts +10 -2
  94. package/dist-lib/lib/helpers/run-outcome.js +8 -5
  95. package/dist-lib/lib/helpers/tool-call-markup.d.ts +2 -0
  96. package/dist-lib/lib/helpers/tool-call-markup.js +197 -82
  97. package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +1 -0
  98. package/dist-lib/lib/hooks/built-in/arg-repair.js +1 -0
  99. package/dist-lib/lib/hooks/built-in/egress.d.ts +1 -0
  100. package/dist-lib/lib/hooks/built-in/egress.js +2 -1
  101. package/dist-lib/lib/hooks/built-in/sandbox.d.ts +1 -0
  102. package/dist-lib/lib/hooks/built-in/sandbox.js +6 -1
  103. package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +1 -0
  104. package/dist-lib/lib/hooks/built-in/skill-catalog.js +2 -1
  105. package/dist-lib/lib/hooks/pipeline.d.ts +4 -1
  106. package/dist-lib/lib/hooks/pipeline.js +24 -2
  107. package/dist-lib/lib/hooks/run.d.ts +2 -1
  108. package/dist-lib/lib/hooks/run.js +19 -7
  109. package/dist-lib/lib/hooks/types.d.ts +17 -6
  110. package/dist-lib/lib/machine/completion/actions/approval.d.ts +3 -0
  111. package/dist-lib/lib/machine/completion/actions/approval.js +16 -0
  112. package/dist-lib/lib/machine/completion/actions/completion.d.ts +23 -0
  113. package/dist-lib/lib/machine/completion/actions/completion.js +142 -0
  114. package/dist-lib/lib/machine/completion/actions/skills.d.ts +9 -0
  115. package/dist-lib/lib/machine/completion/actions/skills.js +83 -0
  116. package/dist-lib/lib/machine/completion/actions/tools.d.ts +16 -0
  117. package/dist-lib/lib/machine/completion/actions/tools.js +173 -0
  118. package/dist-lib/lib/machine/completion/context.d.ts +9 -0
  119. package/dist-lib/lib/machine/completion/context.js +44 -0
  120. package/dist-lib/lib/machine/completion/contract.d.ts +6 -0
  121. package/dist-lib/lib/machine/completion/contract.js +1 -0
  122. package/dist-lib/lib/machine/completion/guards/retry.d.ts +9 -0
  123. package/dist-lib/lib/machine/completion/guards/retry.js +25 -0
  124. package/dist-lib/lib/machine/completion/implementations.d.ts +81 -0
  125. package/dist-lib/lib/machine/completion/implementations.js +152 -0
  126. package/dist-lib/lib/machine/completion/machine.d.ts +375 -0
  127. package/dist-lib/lib/machine/completion/machine.js +511 -0
  128. package/dist-lib/lib/machine/completion/ports.d.ts +65 -0
  129. package/dist-lib/lib/machine/completion/ports.js +224 -0
  130. package/dist-lib/lib/machine/completion/rules.d.ts +39 -0
  131. package/dist-lib/lib/machine/completion/rules.js +115 -0
  132. package/dist-lib/lib/machine/completion/types.d.ts +493 -0
  133. package/dist-lib/lib/machine/completion/types.js +1 -0
  134. package/dist-lib/lib/machine/engine.d.ts +93 -0
  135. package/dist-lib/lib/machine/engine.js +483 -0
  136. package/dist-lib/lib/machine/errors.d.ts +44 -0
  137. package/dist-lib/lib/machine/errors.js +373 -0
  138. package/dist-lib/lib/machine/guards.d.ts +2 -0
  139. package/dist-lib/lib/machine/guards.js +6 -0
  140. package/dist-lib/lib/machine/index.d.ts +20 -0
  141. package/dist-lib/lib/machine/index.js +11 -0
  142. package/dist-lib/lib/machine/replay-output.d.ts +24 -0
  143. package/dist-lib/lib/machine/replay-output.js +50 -0
  144. package/dist-lib/lib/machine/stable-stringify.d.ts +1 -0
  145. package/dist-lib/lib/machine/stable-stringify.js +11 -0
  146. package/dist-lib/lib/models/model-pool.d.ts +14 -6
  147. package/dist-lib/lib/models/model-pool.js +95 -30
  148. package/dist-lib/lib/run-log/history-codec.d.ts +23 -0
  149. package/dist-lib/lib/run-log/history-codec.js +973 -0
  150. package/dist-lib/lib/run-log/patch.d.ts +6 -0
  151. package/dist-lib/lib/run-log/patch.js +93 -0
  152. package/dist-lib/lib/run-log/persisted-actor.d.ts +18 -0
  153. package/dist-lib/lib/run-log/persisted-actor.js +218 -0
  154. package/dist-lib/lib/run-log/protocol-types.d.ts +153 -0
  155. package/dist-lib/lib/run-log/protocol-types.js +1 -0
  156. package/dist-lib/lib/run-log/protocol.d.ts +27 -0
  157. package/dist-lib/lib/run-log/protocol.js +1056 -0
  158. package/dist-lib/lib/run-log/replay.d.ts +25 -0
  159. package/dist-lib/lib/run-log/replay.js +129 -0
  160. package/dist-lib/lib/run-log/run-journal.d.ts +125 -0
  161. package/dist-lib/lib/run-log/run-journal.js +783 -0
  162. package/dist-lib/lib/run-log-inspect.d.ts +25 -0
  163. package/dist-lib/lib/run-log-inspect.js +627 -0
  164. package/dist-lib/lib/run-log-protocol.d.ts +2 -0
  165. package/dist-lib/lib/run-log-protocol.js +1 -0
  166. package/dist-lib/lib/run-log-redact.d.ts +27 -0
  167. package/dist-lib/lib/run-log-redact.js +1107 -0
  168. package/dist-lib/lib/serve.js +307 -11
  169. package/dist-lib/lib/spawn.js +3 -2
  170. package/dist-lib/lib/tool-call-display.d.ts +1 -21
  171. package/dist-lib/lib/tools/exec/adapters/python/wheels.js +2 -1
  172. package/dist-lib/lib/tools/exec.d.ts +2 -1
  173. package/dist-lib/lib/tools/exec.js +57 -2
  174. package/dist-lib/lib/tools/generate-image.js +1 -1
  175. package/dist-lib/lib/tools/generate-music.js +1 -1
  176. package/dist-lib/lib/tools/http-request.d.ts +2 -1
  177. package/dist-lib/lib/tools/http-request.js +2 -1
  178. package/dist-lib/lib/tools/mcp-call.js +8 -1
  179. package/dist-lib/lib/tools/operations/builders.d.ts +1 -0
  180. package/dist-lib/lib/tools/operations/builders.js +1 -0
  181. package/dist-lib/lib/tools/operations/compile.js +11 -1
  182. package/dist-lib/lib/tools/operations/manifest.js +1 -0
  183. package/dist-lib/lib/tools/outbound-guard.d.ts +8 -6
  184. package/dist-lib/lib/tools/outbound-guard.js +25 -8
  185. package/dist-lib/lib/tools/skills/catalog.d.ts +1 -0
  186. package/dist-lib/lib/tools/skills/catalog.js +35 -0
  187. package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +1 -0
  188. package/dist-lib/lib/tools/skills/cli-schema.js +25 -0
  189. package/dist-lib/lib/wire.d.ts +5 -0
  190. package/dist-lib/lib/wire.js +128 -5
  191. package/dist-lib/schema/harness.js +20 -5
  192. package/dist-lib/spec/hrpc/messages.js +95 -15
  193. package/dist-lib/spec/hyperschema/index.js +95 -15
  194. package/dist-lib/spec/hyperschema/schema.json +69 -1
  195. package/dist-lib/spec/hyperschema/types.d.ts +10 -3
  196. package/package.json +20 -2
  197. package/patches/@qvac%2Finference@0.20.0.patch +67 -0
  198. package/patches/bare-stow@0.1.5.patch +68 -0
  199. package/patches/hypercore-blob-server@1.15.0.patch +15 -0
  200. package/patches/localwatch@1.4.3.patch +13 -0
  201. package/patches/pyodide@314.0.2.patch +144 -0
@@ -0,0 +1 @@
1
+ export declare function installAbortControllerPolyfill(): void;
@@ -0,0 +1,10 @@
1
+ import { AbortController as BareAbortController } from 'bare-abort-controller';
2
+ export function installAbortControllerPolyfill() {
3
+ if (typeof globalThis.AbortController === 'undefined') {
4
+ Object.defineProperty(globalThis, 'AbortController', {
5
+ value: BareAbortController,
6
+ writable: true,
7
+ configurable: true
8
+ });
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ import type { AnsweredPayload } from '../../../machine/index.ts';
2
+ import type { CompletionActor } from '../session.ts';
3
+ export declare const answering: CompletionActor<AnsweredPayload>;
@@ -0,0 +1,17 @@
1
+ import { assembleAnswer } from './stream.js';
2
+ import { stripToolCallMarkup } from '../../../helpers/tool-call-markup.js';
3
+ export const answering = async function answering({ emit, input: { session }, context }) {
4
+ const round = context.lastRound;
5
+ if (round.response && !round.contentText.trim() && !round.replay) {
6
+ emit({ type: 'content', text: round.response });
7
+ return { response: round.response };
8
+ }
9
+ const replay = round.replay ? stripToolCallMarkup(round.replay) : '';
10
+ const response = await assembleAnswer({
11
+ contentText: round.contentText,
12
+ replay,
13
+ landed: session.landed,
14
+ emit
15
+ });
16
+ return { response };
17
+ };
@@ -0,0 +1,4 @@
1
+ import type { CompletionActor } from '../session.ts';
2
+ export declare const approval: CompletionActor<{
3
+ approved: boolean;
4
+ }>;
@@ -0,0 +1,29 @@
1
+ import { raceAbort } from '../../../helpers/race-abort.js';
2
+ import { detachJson } from '../../../helpers/detach-json.js';
3
+ export const approval = async function approval({ emit, input: { args, operations }, context, signal }) {
4
+ const call = context.pendingCall;
5
+ const approve = args.approve;
6
+ if (!call || !approve) {
7
+ return { approved: false };
8
+ }
9
+ const currentCall = context.currentCall;
10
+ const rawCall = context.currentCall?.rawCall;
11
+ emit({
12
+ type: 'tool-call',
13
+ name: call.name,
14
+ args: call.arguments,
15
+ rawCall,
16
+ effect: call.effect ?? 'write',
17
+ display: call.display ?? undefined
18
+ });
19
+ const id = `${context.runId}:round-${context.round}:${currentCall?.id ?? call.name}:approve`;
20
+ const approved = await operations.operation({ id, name: 'human:approve', args: call.arguments, effect: 'read' }, () => raceAbort(raceAbort(approve({
21
+ ...call,
22
+ arguments: detachJson(call.arguments),
23
+ resource: detachJson(call.resource),
24
+ display: detachJson(call.display),
25
+ callId: currentCall?.id,
26
+ round: context.round
27
+ }), args.signal), signal), undefined, signal);
28
+ return { approved };
29
+ };
@@ -0,0 +1,4 @@
1
+ import type { CompletionMachineContext as CompletionContext, DirectToolOutput, SearchingOutput } from '../../../machine/index.ts';
2
+ import type { CompletionActor, CompletionDeps } from '../session.ts';
3
+ export declare const directSearch: CompletionActor<SearchingOutput>;
4
+ export declare function startDirectSearch(deps: CompletionDeps, context: CompletionContext, query: string): Promise<DirectToolOutput | null>;
@@ -0,0 +1,73 @@
1
+ import { AbortedError } from '../../../helpers/race-abort.js';
2
+ import { WEB_SEARCH_TOOL_NAME } from '../../tool-names.js';
3
+ import { DIRECT_CALL_ID } from '../../tool-turns.js';
4
+ import { approvalGate, trustedSources } from './execution-plan.js';
5
+ import { detachJson } from '../../../helpers/detach-json.js';
6
+ import { deniedWithoutApprover, gateRejection, policyActivity } from './rejection.js';
7
+ export const directSearch = async function directSearch({ input: deps, context }) {
8
+ return {
9
+ directTool: context.pendingSearch
10
+ ? await startDirectSearch(deps, context, context.pendingSearch)
11
+ : null
12
+ };
13
+ };
14
+ export async function startDirectSearch(deps, context, query) {
15
+ const { args, session } = deps;
16
+ const webSearch = session.enabled.find((tool) => tool.name === WEB_SEARCH_TOOL_NAME);
17
+ if (!webSearch) {
18
+ return null;
19
+ }
20
+ const fold = await session.pipeline.runPreToolFold({
21
+ runId: session.runId,
22
+ callId: DIRECT_CALL_ID,
23
+ toolName: webSearch.name,
24
+ args: { query },
25
+ agentId: args.agent?.id ?? null,
26
+ signal: args.signal
27
+ });
28
+ const searchArgs = fold.ok ? detachJson(fold.args) : { query };
29
+ if (args.signal?.aborted) {
30
+ throw new AbortedError();
31
+ }
32
+ const call = {
33
+ id: DIRECT_CALL_ID,
34
+ key: session.callKey(webSearch.name, searchArgs),
35
+ name: webSearch.name,
36
+ args: searchArgs
37
+ };
38
+ const effect = webSearch.effect(detachJson(searchArgs));
39
+ const execution = { kind: 'direct', effect, skillName: null, webSearch: true };
40
+ if (fold.ok) {
41
+ const sources = trustedSources(deps, context);
42
+ const gate = approvalGate({
43
+ deps,
44
+ context,
45
+ call,
46
+ tool: webSearch,
47
+ effect,
48
+ sources
49
+ });
50
+ const gated = { ...execution, gate };
51
+ const resource = gate.call.resource ?? null;
52
+ const rejection = { context, call, execution: gated, resource, source: 'tool-result' };
53
+ return {
54
+ call,
55
+ execution: gated,
56
+ hookRejection: null,
57
+ resource,
58
+ rejection: gateRejection(rejection) ?? deniedWithoutApprover(rejection)
59
+ };
60
+ }
61
+ return {
62
+ call,
63
+ execution,
64
+ hookRejection: fold.rejection,
65
+ resource: null,
66
+ rejection: {
67
+ result: fold.rejection,
68
+ activity: policyActivity({ call, effect, resource: null }),
69
+ effect,
70
+ source: 'tool-result'
71
+ }
72
+ };
73
+ }
@@ -0,0 +1,41 @@
1
+ import { type ToolCallDisplay, type ToolExecutionOutcome, type ToolPreflight, type ToolActivityEvent } from '../../../machine/index.ts';
2
+ import type { ToolDefinition, ToolExecuteContext } from '../../completion.ts';
3
+ import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
4
+ import type { ToolPolicySources } from './execution-plan.ts';
5
+ import type { HookPipeline } from '../../../hooks/pipeline.ts';
6
+ export interface ToolCallPlan {
7
+ resolved: {
8
+ call: {
9
+ id: string;
10
+ name: string;
11
+ arguments: Record<string, unknown>;
12
+ rawCall?: string;
13
+ };
14
+ tool: ToolDefinition;
15
+ };
16
+ context: ToolExecuteContext;
17
+ effect: 'read' | 'write';
18
+ skillName: string | null;
19
+ webSearch: boolean;
20
+ }
21
+ export interface ToolCallRunOptions {
22
+ approve?: () => Promise<boolean>;
23
+ sources: ToolPolicySources;
24
+ preflight: ToolPreflight;
25
+ onDisplay?: (event: ToolActivityEvent) => void;
26
+ signal?: BareAbortSignal;
27
+ denied: Set<string>;
28
+ pipeline: HookPipeline;
29
+ runId: string;
30
+ callId: string;
31
+ skipApprovals: boolean;
32
+ intent?: string;
33
+ display?: ToolCallDisplay;
34
+ }
35
+ export interface ToolCallRunResult {
36
+ output: unknown;
37
+ outcome: ToolExecutionOutcome;
38
+ executed: boolean;
39
+ activity: ToolActivityEvent | null;
40
+ }
41
+ export declare function runToolCall(plan: ToolCallPlan, options: ToolCallRunOptions): Promise<ToolCallRunResult>;
@@ -0,0 +1,49 @@
1
+ import { AbortedError } from '../../../helpers/race-abort.js';
2
+ import { RecoveryRequired, ToolPolicyChanged } from '../../../machine/index.js';
3
+ import { executeCall } from '../../completion-loop/index.js';
4
+ import { errorMessage } from '../../../guards.js';
5
+ export async function runToolCall(plan, options) {
6
+ let activity = null;
7
+ try {
8
+ const executed = await executeCall(plan.resolved.tool, plan.resolved.call.arguments, plan.context, {
9
+ runId: options.runId,
10
+ approve: options.approve,
11
+ signal: options.signal,
12
+ denied: options.denied,
13
+ preflight: options.preflight,
14
+ sources: options.sources.sources,
15
+ sourceFacts: options.sources.sourceFacts,
16
+ pipeline: options.pipeline,
17
+ effect: plan.effect,
18
+ callId: options.callId,
19
+ skipApprovals: options.skipApprovals,
20
+ intent: options.intent,
21
+ display: options.display,
22
+ onToolActivity: (value) => {
23
+ activity = value;
24
+ options.onDisplay?.(value);
25
+ }
26
+ });
27
+ return {
28
+ output: executed.result,
29
+ outcome: executed.outcome,
30
+ executed: executed.executed,
31
+ activity
32
+ };
33
+ }
34
+ catch (error) {
35
+ if (error instanceof RecoveryRequired || error instanceof ToolPolicyChanged) {
36
+ throw error;
37
+ }
38
+ if (error instanceof AbortedError || options.signal?.aborted) {
39
+ throw new AbortedError();
40
+ }
41
+ const message = errorMessage(error);
42
+ return {
43
+ output: { error: message },
44
+ outcome: { kind: 'error', message, error },
45
+ executed: false,
46
+ activity
47
+ };
48
+ }
49
+ }
@@ -0,0 +1,3 @@
1
+ import { type ToolDonePayload } from '../../../machine/index.ts';
2
+ import type { CompletionActor } from '../session.ts';
3
+ export declare const executing: CompletionActor<ToolDonePayload>;
@@ -0,0 +1,102 @@
1
+ import { AbortedError } from '../../../helpers/race-abort.js';
2
+ import { failureResultRef, storeFailureResult, spliceFrom } from '../../../machine/index.js';
3
+ import { callSucceeded, directToolHistory, labelOf, readyPreflightFromFacts, settledFailure } from '../../completion-loop/index.js';
4
+ import { DIRECT_CALL_ID, toolResultHistoryEntry, toolResultTurn } from '../../tool-turns.js';
5
+ import { trustedSourceFacts } from '../../../tools/outbound-guard.js';
6
+ import { executionPlan, trustedSources } from './execution-plan.js';
7
+ import { runToolCall } from './execute.js';
8
+ export const executing = async function executing({ emit, input: deps, context }) {
9
+ const { args, session } = deps;
10
+ const plan = executionPlan(deps, context);
11
+ const { call, args: callArgs, rawCall, intent } = plan.resolved;
12
+ const callKey = plan.resolved.key;
13
+ const display = labelOf(call.name, callArgs, session.skillIcon);
14
+ if (args.signal?.aborted) {
15
+ throw new AbortedError();
16
+ }
17
+ const denied = new Set(context.deniedKeys);
18
+ const sources = trustedSources(deps, context);
19
+ const facts = context.execution?.gate?.facts;
20
+ if (!facts) {
21
+ throw new Error('selected tool has no inspected policy facts');
22
+ }
23
+ const preflight = readyPreflightFromFacts(facts);
24
+ if (context.approval.status === 'idle') {
25
+ emit({
26
+ type: 'tool-call',
27
+ name: call.name,
28
+ args: callArgs,
29
+ rawCall,
30
+ effect: plan.effect,
31
+ display
32
+ });
33
+ }
34
+ let output;
35
+ let outcome;
36
+ let ran = false;
37
+ let activity = null;
38
+ const landedBefore = session.landed.length;
39
+ const executed = await runToolCall(plan, {
40
+ approve: context.approval.status === 'idle'
41
+ ? undefined
42
+ : () => Promise.resolve(context.approval.status === 'approved'),
43
+ signal: args.signal,
44
+ denied,
45
+ preflight,
46
+ sources,
47
+ pipeline: session.pipeline,
48
+ runId: session.runId,
49
+ callId: call.id,
50
+ skipApprovals: args.agent?.approvalMode === 'skip-all',
51
+ intent,
52
+ display
53
+ });
54
+ output = executed.output;
55
+ outcome = executed.outcome;
56
+ ran = executed.executed;
57
+ activity = executed.activity;
58
+ if (outcome.kind !== 'success' && session.landed.length > landedBefore) {
59
+ session.landed.length = landedBefore;
60
+ }
61
+ session.runOutcomes.record(output, outcome);
62
+ if (activity) {
63
+ emit(activity);
64
+ }
65
+ emit({ type: 'tool-result', name: call.name, result: output });
66
+ const failed = settledFailure(output, outcome);
67
+ const direct = context.execution?.kind === 'direct';
68
+ const resultTurnId = direct ? DIRECT_CALL_ID : call.id;
69
+ const failure = failed
70
+ ? {
71
+ key: callKey,
72
+ resultRef: failureResultRef(callKey, context.round, call.id),
73
+ outcome,
74
+ value: {
75
+ name: call.name,
76
+ result: storeFailureResult(output)
77
+ }
78
+ }
79
+ : undefined;
80
+ const turn = toolResultTurn(call.name, resultTurnId, output);
81
+ const history = direct
82
+ ? directToolHistory(context.history, callArgs, output, failure?.resultRef)
83
+ : [
84
+ ...context.history,
85
+ toolResultHistoryEntry({
86
+ name: call.name,
87
+ id: resultTurnId,
88
+ output,
89
+ resultRef: failure?.resultRef
90
+ })
91
+ ];
92
+ const deniedKey = [...denied].find((key) => !context.deniedKeys.includes(key));
93
+ const progressed = ran && callSucceeded(output, outcome) ? true : undefined;
94
+ return {
95
+ deniedKey,
96
+ webSearch: plan.webSearch,
97
+ history: spliceFrom(context.history, history),
98
+ source: trustedSourceFacts('tool-result', turn),
99
+ failed: failure,
100
+ progressed
101
+ };
102
+ };
@@ -0,0 +1,47 @@
1
+ import type { ToolDefinition, ToolExecuteContext } from '../../completion.ts';
2
+ import { type ResolvedCall } from '../../completion-loop/index.ts';
3
+ import type { CompletionDeps } from '../session.ts';
4
+ import type { ApprovalGate, CompletionMachineContext as CompletionContext, ResolvedCallSnapshot, ToolEffect, TrustedSource, TrustedSourceFacts } from '../../../machine/index.ts';
5
+ export interface ToolPolicySources {
6
+ sources: TrustedSource[];
7
+ sourceFacts: TrustedSourceFacts[];
8
+ }
9
+ interface ResolvedToolCall extends ResolvedCall {
10
+ key: string;
11
+ tool: ToolDefinition;
12
+ }
13
+ interface OpaqueResolvedCall extends ResolvedCall {
14
+ key: string;
15
+ }
16
+ export interface ToolExecutionPlan {
17
+ type: 'execute';
18
+ route: 'tool' | 'skill';
19
+ resolved: ResolvedToolCall;
20
+ context: ToolExecuteContext;
21
+ effect: ToolEffect;
22
+ skillName: string | null;
23
+ webSearch: boolean;
24
+ }
25
+ interface ResolvedCallInput {
26
+ session: CompletionDeps['session'];
27
+ context: CompletionContext;
28
+ }
29
+ export declare function resolvedCall({ session, context }: ResolvedCallInput): OpaqueResolvedCall;
30
+ interface ToolContextInput {
31
+ deps: CompletionDeps;
32
+ context: CompletionContext;
33
+ name: string;
34
+ }
35
+ export declare function toolContext({ deps, context, name }: ToolContextInput): ToolExecuteContext;
36
+ export declare function executionPlan(deps: CompletionDeps, context: CompletionContext): ToolExecutionPlan;
37
+ export declare function trustedSources({ args }: CompletionDeps, context: Pick<CompletionContext, 'sources'>): ToolPolicySources;
38
+ interface ApprovalGateInput {
39
+ deps: CompletionDeps;
40
+ context: CompletionContext;
41
+ call: ResolvedCallSnapshot;
42
+ tool: ToolDefinition;
43
+ effect: ToolEffect;
44
+ sources: ToolPolicySources;
45
+ }
46
+ export declare function approvalGate({ deps, context, call, tool, effect, sources }: ApprovalGateInput): ApprovalGate;
47
+ export {};
@@ -0,0 +1,87 @@
1
+ import { labelOf, inspectToolPolicy, sanitizeTurn, trustedSourcesFrom } from '../../completion-loop/index.js';
2
+ export function resolvedCall({ session, context }) {
3
+ const call = context.currentCall;
4
+ if (!call) {
5
+ throw new Error('completion graph selected a tool without a current call');
6
+ }
7
+ const tool = session.enabled.find((tool) => tool.name === call.name);
8
+ return {
9
+ key: call.key,
10
+ call: { id: call.id, name: call.name, arguments: call.args },
11
+ args: call.args,
12
+ tool,
13
+ rawCall: call.rawCall,
14
+ intent: call.intent,
15
+ rejection: call.rejection
16
+ };
17
+ }
18
+ export function toolContext({ deps, context, name }) {
19
+ const { args, session, commitFacts } = deps;
20
+ const { skillsSelected, enabledSkills, mention } = session.activation;
21
+ return {
22
+ ...session.toolContext(session.turnImages, args.ctxSize, args.signal),
23
+ skills: (context.skills.snapshot?.loaded ?? []).filter((skill) => !skillsSelected || enabledSkills.includes(skill) || skill === mention),
24
+ settings: args.toolConfigs?.[name],
25
+ toolOps: session.grantedOps,
26
+ fsRoots: args.fsRoots ?? [],
27
+ fsWriteRoots: session.writableRoots,
28
+ sandboxMode: args.agent?.sandboxMode === true,
29
+ toolNames: session.enabled.map((tool) => tool.name),
30
+ reportBackend: (use) => {
31
+ session.backends.push(use);
32
+ commitFacts?.();
33
+ }
34
+ };
35
+ }
36
+ export function executionPlan(deps, context) {
37
+ const execution = context.execution;
38
+ if (!execution) {
39
+ throw new Error('completion graph selected execution without execution facts');
40
+ }
41
+ const resolved = resolvedCall({ session: deps.session, context });
42
+ if (!resolved.tool) {
43
+ throw new Error(`tool implementation not found: ${resolved.call.name}`);
44
+ }
45
+ const resolvedWithTool = { ...resolved, tool: resolved.tool };
46
+ return {
47
+ type: 'execute',
48
+ route: execution.kind === 'skill' ? 'skill' : 'tool',
49
+ resolved: resolvedWithTool,
50
+ context: toolContext({ deps, context, name: resolved.call.name }),
51
+ effect: execution.effect,
52
+ skillName: execution.skillName,
53
+ webSearch: execution.webSearch
54
+ };
55
+ }
56
+ const requestSources = new WeakMap();
57
+ export function trustedSources({ args }, context) {
58
+ let sources = requestSources.get(args.messages);
59
+ if (!sources) {
60
+ sources = trustedSourcesFrom(args.messages.map(sanitizeTurn));
61
+ requestSources.set(args.messages, sources);
62
+ }
63
+ return { sources, sourceFacts: context.sources };
64
+ }
65
+ export function approvalGate({ deps, context, call, tool, effect, sources }) {
66
+ const { args, session } = deps;
67
+ const facts = inspectToolPolicy(tool, call.args, toolContext({ deps, context, name: call.name }), {
68
+ sources: sources.sources,
69
+ sourceFacts: sources.sourceFacts,
70
+ denied: new Set(context.deniedKeys),
71
+ effect,
72
+ key: call.key,
73
+ skipApprovals: args.agent?.approvalMode === 'skip-all'
74
+ });
75
+ return {
76
+ facts,
77
+ approver: Boolean(args.approve),
78
+ call: {
79
+ name: call.name,
80
+ arguments: call.args,
81
+ resource: facts.resource,
82
+ effect: facts.effect,
83
+ intent: call.intent ?? null,
84
+ display: labelOf(call.name, call.args, session.skillIcon)
85
+ }
86
+ };
87
+ }
@@ -0,0 +1,2 @@
1
+ import type { CompletionActor } from '../session.ts';
2
+ export declare const finishing: CompletionActor<void>;
@@ -0,0 +1,32 @@
1
+ import { AbortedError } from '../../../helpers/race-abort.js';
2
+ import { rehydrateError } from '../../../machine/index.js';
3
+ export const finishing = async ({ input: deps, context, signal }) => {
4
+ if (signal.aborted)
5
+ throw new AbortedError();
6
+ if (!deps.session.runStarted)
7
+ return;
8
+ const { failure } = context;
9
+ const payload = {
10
+ runId: context.runId,
11
+ agentId: context.agentId,
12
+ stats: {
13
+ totalTokens: context.metrics.tokens,
14
+ durationMs: Math.round(context.metrics.durationMs),
15
+ timeToFirstToken: context.metrics.ttft
16
+ },
17
+ outcome: context.outcome === 'failed' ? 'error' : 'done',
18
+ error: failure ? rehydrateError(failure, failure.message) : undefined
19
+ };
20
+ if (!deps.session.pipeline.hasPhase('runEnd')) {
21
+ await deps.session.pipeline.onRunEnd(payload);
22
+ return;
23
+ }
24
+ await deps.operations.operation({
25
+ id: `${context.runId}:hook-runEnd`,
26
+ name: 'hook:runEnd',
27
+ args: { outcome: context.outcome },
28
+ effect: 'write'
29
+ }, async () => {
30
+ await deps.session.pipeline.onRunEnd(payload);
31
+ });
32
+ };
@@ -0,0 +1,3 @@
1
+ import { type PreloadInspectionOutput } from '../../../machine/index.ts';
2
+ import type { CompletionActor } from '../session.ts';
3
+ export declare const inspectPreload: CompletionActor<PreloadInspectionOutput>;
@@ -0,0 +1,75 @@
1
+ import { AbortedError } from '../../../helpers/race-abort.js';
2
+ import { copy, toolDeniedResult } from '../../../machine/index.js';
3
+ import { inspectToolPolicy } from '../../completion-loop/index.js';
4
+ import { SKILL_TOOL_NAME } from '../../tool-names.js';
5
+ import { toolContext, trustedSources } from './execution-plan.js';
6
+ import { preloadFailure } from './preload-failure.js';
7
+ export const inspectPreload = async function inspectPreload({ input: deps, context }) {
8
+ const { args, session } = deps;
9
+ const pending = context.skillPreload;
10
+ if (!pending) {
11
+ throw new Error('preload inspection requires a pending skill');
12
+ }
13
+ const loader = session.enabled.find((tool) => tool.name === SKILL_TOOL_NAME);
14
+ if (!loader) {
15
+ throw new Error('skill preload requires the skill tool');
16
+ }
17
+ if (args.signal?.aborted) {
18
+ throw new AbortedError();
19
+ }
20
+ const loaderArgs = { name: pending.name };
21
+ const callId = `preload-${pending.name}`;
22
+ const executeContext = toolContext({ deps, context, name: loader.name });
23
+ const fold = await session.pipeline.runPreToolFold({
24
+ runId: session.runId,
25
+ callId,
26
+ toolName: loader.name,
27
+ agentId: args.agent?.id ?? null,
28
+ args: loaderArgs,
29
+ skillNames: session.inContextSkills.map((skill) => skill.name),
30
+ parameters: loader.parameters,
31
+ sandboxMode: args.agent?.sandboxMode === true,
32
+ signal: args.signal
33
+ });
34
+ if (args.signal?.aborted) {
35
+ throw new AbortedError();
36
+ }
37
+ if (!fold.ok) {
38
+ return {
39
+ name: pending.name,
40
+ args: loaderArgs,
41
+ facts: null,
42
+ hookRejection: fold.rejection,
43
+ failure: preloadFailure({
44
+ history: context.history,
45
+ startedAt: session.startedAt,
46
+ name: pending.name,
47
+ error: fold.rejection.error
48
+ })
49
+ };
50
+ }
51
+ const facts = inspectToolPolicy(loader, fold.args, executeContext, {
52
+ ...trustedSources(deps, context),
53
+ denied: new Set(context.deniedKeys),
54
+ key: session.callKey(loader.name, fold.args),
55
+ skipApprovals: false
56
+ });
57
+ const failureReason = facts.validationError ??
58
+ facts.refusal ??
59
+ (facts.deniedKey ? toolDeniedResult().error : null) ??
60
+ (facts.effect !== 'read' ? 'Skill loading requires a read-only tool.' : null);
61
+ return {
62
+ name: pending.name,
63
+ args: copy(fold.args),
64
+ facts,
65
+ hookRejection: null,
66
+ failure: failureReason
67
+ ? preloadFailure({
68
+ history: context.history,
69
+ startedAt: session.startedAt,
70
+ name: pending.name,
71
+ error: failureReason
72
+ })
73
+ : null
74
+ };
75
+ };
@@ -0,0 +1,3 @@
1
+ import type { CompletionActor } from '../session.ts';
2
+ import type { InspectingOutput } from '../../../machine/index.ts';
3
+ export declare const inspecting: CompletionActor<InspectingOutput>;