@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,18 @@
1
+ import { type CompletionMachineContext as CompletionContext, type ResolvedCallSnapshot, type ResourceDescriptor, type ToolActivityEvent, type ToolEffect, type ToolExecutionSnapshot, type ToolRejection } from '../../../machine/index.ts';
2
+ interface PolicyActivityInput {
3
+ call: ResolvedCallSnapshot;
4
+ effect: ToolEffect | undefined;
5
+ resource: ResourceDescriptor | null;
6
+ decision?: 'blocked' | 'denied';
7
+ }
8
+ export declare function policyActivity({ call, effect, resource, decision }: PolicyActivityInput): ToolActivityEvent;
9
+ export interface GateRejectionInput {
10
+ context: CompletionContext;
11
+ call: ResolvedCallSnapshot;
12
+ execution: ToolExecutionSnapshot | null;
13
+ resource: ResourceDescriptor | null;
14
+ source: ToolRejection['source'];
15
+ }
16
+ export declare function gateRejection({ call, execution, resource, source }: GateRejectionInput): ToolRejection | undefined;
17
+ export declare function deniedWithoutApprover({ context, call, execution, source }: GateRejectionInput): ToolRejection | undefined;
18
+ export {};
@@ -0,0 +1,70 @@
1
+ import { TOOL_DENIED_MESSAGE, toolDeniedResult } from '../../../machine/index.js';
2
+ export function policyActivity({ call, effect, resource, decision = 'blocked' }) {
3
+ return {
4
+ type: 'tool-activity',
5
+ name: call.name,
6
+ args: call.args,
7
+ resource,
8
+ effect: effect ?? 'write',
9
+ decision
10
+ };
11
+ }
12
+ export function gateRejection({ call, execution, resource, source }) {
13
+ const facts = execution?.gate?.facts;
14
+ if (!facts) {
15
+ return undefined;
16
+ }
17
+ const effect = execution.effect;
18
+ if (facts.validationError) {
19
+ return {
20
+ result: { error: facts.validationError, guidance: true },
21
+ outcome: { kind: 'guidance', message: facts.validationError },
22
+ activity: null,
23
+ effect,
24
+ source
25
+ };
26
+ }
27
+ if (facts.refusal) {
28
+ return {
29
+ result: { error: facts.refusal, guidance: true },
30
+ outcome: { kind: 'blocked', reason: facts.refusal },
31
+ activity: policyActivity({ call, effect, resource }),
32
+ effect,
33
+ source
34
+ };
35
+ }
36
+ if (facts.deniedKey) {
37
+ return {
38
+ result: toolDeniedResult(),
39
+ outcome: { kind: 'denied', reason: TOOL_DENIED_MESSAGE },
40
+ activity: null,
41
+ effect,
42
+ source
43
+ };
44
+ }
45
+ return undefined;
46
+ }
47
+ export function deniedWithoutApprover({ context, call, execution, source }) {
48
+ const gate = execution?.gate;
49
+ const facts = gate?.facts;
50
+ if (!gate || !facts) {
51
+ return undefined;
52
+ }
53
+ const autoRuns = facts.effect === 'read' || facts.autoApprove || facts.skipApprovals;
54
+ if (autoRuns || context.approval.status !== 'idle' || gate.approver) {
55
+ return undefined;
56
+ }
57
+ return {
58
+ result: toolDeniedResult(),
59
+ outcome: { kind: 'denied', reason: TOOL_DENIED_MESSAGE },
60
+ activity: policyActivity({
61
+ call,
62
+ effect: facts.effect,
63
+ resource: facts.resource,
64
+ decision: 'denied'
65
+ }),
66
+ effect: execution.effect,
67
+ source,
68
+ deniedKey: facts.key
69
+ };
70
+ }
@@ -0,0 +1,3 @@
1
+ import type { CompletionActor } from '../session.ts';
2
+ import type { ResolvingOutput } from '../../../machine/index.ts';
3
+ export declare const resolving: CompletionActor<ResolvingOutput>;
@@ -0,0 +1,60 @@
1
+ import { spliceFrom } from '../../../machine/index.js';
2
+ import { AbortedError } from '../../../helpers/race-abort.js';
3
+ import { hlog } from '../../../log.js';
4
+ import { stripToolCallMarkup } from '../../../helpers/tool-call-markup.js';
5
+ import { assistantToolTurn, resolveToolCalls } from '../../completion-loop/index.js';
6
+ const NARRATED_INTENT = /\b(I['’]ll|I will|Now I|Let me(?! know)|Next,? I)\b[^.!?]*[.!?]?\s*$/i;
7
+ export const resolving = async function resolving({ input: { args, session }, context }) {
8
+ const round = context.lastRound;
9
+ const toolCalls = round.toolCalls.map((call) => ({
10
+ id: call.id,
11
+ name: call.name,
12
+ arguments: call.arguments,
13
+ raw: call.raw
14
+ }));
15
+ if (!toolCalls.length) {
16
+ return answerFacts({ round, roundNumber: context.round, session });
17
+ }
18
+ const resolved = await resolveToolCalls(toolCalls, session.enabled, {
19
+ runId: session.runId,
20
+ agentId: args.agent?.id ?? null,
21
+ pipeline: session.pipeline,
22
+ skillNames: session.inContextSkills.map((skill) => skill.name),
23
+ sandboxMode: args.agent?.sandboxMode === true,
24
+ signal: args.signal
25
+ });
26
+ if (args.signal?.aborted) {
27
+ throw new AbortedError();
28
+ }
29
+ return resolvedOutput({ context, round, resolved, session });
30
+ };
31
+ function answerFacts({ round, roundNumber, session }) {
32
+ const replay = round.replay ? stripToolCallMarkup(round.replay) : '';
33
+ const spoken = round.contentText.trim();
34
+ const narrated = session.enabled.length && !replay && NARRATED_INTENT.test(spoken) ? spoken : undefined;
35
+ if (narrated) {
36
+ hlog('round narrated a tool call', { round: roundNumber });
37
+ }
38
+ return { calls: [], response: replay || round.contentText, narrated };
39
+ }
40
+ function resolvedOutput({ context, round, resolved, session }) {
41
+ const history = [
42
+ ...context.history,
43
+ {
44
+ role: 'assistant',
45
+ content: assistantToolTurn(round.contentText, resolved.map(({ call, args: callArgs }) => ({ name: call.name, arguments: callArgs })))
46
+ }
47
+ ];
48
+ return {
49
+ calls: resolved.map(({ call, args: callArgs, rawCall, intent, rejection }) => ({
50
+ id: call.id,
51
+ key: session.callKey(call.name, callArgs),
52
+ name: call.name,
53
+ args: callArgs,
54
+ rawCall,
55
+ intent,
56
+ rejection
57
+ })),
58
+ history: spliceFrom(context.history, history)
59
+ };
60
+ }
@@ -0,0 +1,21 @@
1
+ import type { CompletionEvent, CompletionSdk } from '../../completion.ts';
2
+ import { type RecoveredRound, type RoundArgs } from '../../completion-loop/index.ts';
3
+ interface ForwardStreamOptions<Result> {
4
+ stream: AsyncGenerator<CompletionEvent, Result> | Generator<CompletionEvent, Result>;
5
+ emit: (event: CompletionEvent) => void;
6
+ }
7
+ interface RunRoundOptions {
8
+ sdk: CompletionSdk | undefined;
9
+ args: RoundArgs;
10
+ emit: (event: CompletionEvent) => void;
11
+ }
12
+ export interface AssembleAnswerOptions {
13
+ contentText: string;
14
+ replay: string;
15
+ landed: string[];
16
+ emit: (event: CompletionEvent) => void;
17
+ }
18
+ export declare function forwardStream<Result>({ stream, emit }: ForwardStreamOptions<Result>): Promise<Result>;
19
+ export declare function runRound({ sdk, args, emit }: RunRoundOptions): Promise<RecoveredRound>;
20
+ export declare function assembleAnswer({ contentText, replay, landed, emit }: AssembleAnswerOptions): Promise<string>;
21
+ export {};
@@ -0,0 +1,48 @@
1
+ import { reportUnnamedWrites, runRecoveredRound } from '../../completion-loop/index.js';
2
+ import { AbortedError } from '../../../helpers/race-abort.js';
3
+ export async function forwardStream({ stream, emit }) {
4
+ try {
5
+ while (true) {
6
+ const step = await stream.next();
7
+ if (step.done) {
8
+ return step.value;
9
+ }
10
+ emit(step.value);
11
+ }
12
+ }
13
+ finally {
14
+ await Promise.resolve(stream.return(undefined)).catch(noop);
15
+ }
16
+ }
17
+ export async function runRound({ sdk, args, emit }) {
18
+ if (args.signal?.aborted)
19
+ throw new AbortedError();
20
+ try {
21
+ return await forwardStream({ stream: runRecoveredRound(sdk, args), emit });
22
+ }
23
+ catch (error) {
24
+ if (error instanceof AbortedError || args.signal?.aborted) {
25
+ throw new AbortedError();
26
+ }
27
+ throw error;
28
+ }
29
+ }
30
+ export async function assembleAnswer({ contentText, replay, landed, emit }) {
31
+ let response = replay || contentText;
32
+ if (replay) {
33
+ emit({ type: 'content', text: replay });
34
+ }
35
+ if (replay || contentText.trim()) {
36
+ await forwardStream({
37
+ stream: reportUnnamedWrites(`${contentText}\n${replay}`, landed),
38
+ emit: (event) => {
39
+ if (event.type === 'content') {
40
+ response += event.text;
41
+ }
42
+ emit(event);
43
+ }
44
+ });
45
+ }
46
+ return response;
47
+ }
48
+ const noop = () => { };
@@ -0,0 +1,3 @@
1
+ import { type RoundDonePayload } from '../../../machine/index.ts';
2
+ import type { CompletionActor } from '../session.ts';
3
+ export declare const streaming: CompletionActor<RoundDonePayload>;
@@ -0,0 +1,156 @@
1
+ import { spliceFrom } from '../../../machine/index.js';
2
+ import { runRound } from './stream.js';
3
+ import { truncateAtControlToken } from '../../../helpers/control-tokens.js';
4
+ import { recoverMarkupToolCalls, recoverPrintedSkillLoad, recoverSkillNamedCall, stripToolResponseBlocks } from '../../../helpers/tool-call-markup.js';
5
+ import { unquoteArg } from '../../../tools/model-args.js';
6
+ import { SKILL_TOOL_NAME } from '../../tool-names.js';
7
+ import { hlog } from '../../../log.js';
8
+ import { customToolDialect } from '../../../models/model-catalog.js';
9
+ export const streaming = async function streaming({ emit, input: { sdk, args, session }, context }) {
10
+ const { recovered, promptPrefix, thinkingText } = await generateStreamingRound({
11
+ sdk,
12
+ args,
13
+ session,
14
+ context,
15
+ emit
16
+ });
17
+ const rawToolCalls = recoverToolCalls({ recovered, session, round: context.round });
18
+ const toolCalls = identifyToolCalls(rawToolCalls, session.runId, context.round);
19
+ session.runOutcomes.finishRound();
20
+ session.runOutcomes.beginRound();
21
+ return {
22
+ contentText: recovered.contentText,
23
+ thinkingText,
24
+ toolCalls: toolCalls.map((call) => ({
25
+ id: call.id,
26
+ name: call.name,
27
+ arguments: call.arguments,
28
+ raw: call.raw
29
+ })),
30
+ stats: recovered.final.stats,
31
+ stopReason: recovered.final.stopReason,
32
+ promptPrefix,
33
+ replay: recovered.replay,
34
+ history: recovered.history ? spliceFrom(context.history, recovered.history) : undefined,
35
+ cacheable: recovered.cacheable
36
+ };
37
+ };
38
+ async function generateStreamingRound({ sdk, args, session, context, emit }) {
39
+ const prepared = prepareStreamingRound({ args, session, context });
40
+ let thinkingText = '';
41
+ const recovered = await runRound({
42
+ sdk,
43
+ args: prepared.args,
44
+ emit: (event) => {
45
+ if (event.type === 'thinking') {
46
+ thinkingText += event.text;
47
+ }
48
+ emit(event);
49
+ }
50
+ });
51
+ logRoundStats({ session, round: context.round, startedAt: prepared.startedAt, recovered });
52
+ return { recovered, promptPrefix: prepared.promptPrefix, thinkingText };
53
+ }
54
+ function logRoundStats({ session, round, startedAt, recovered }) {
55
+ hlog('round stats', Object.assign({ round, wallMs: session.now() - startedAt }, recovered.final.stats));
56
+ }
57
+ function roundLoadedSkills(context, session) {
58
+ return new Set([...(context.skills.snapshot?.loaded ?? []), ...session.loadedThisTurn]);
59
+ }
60
+ function prepareStreamingRound({ args, session, context }) {
61
+ const { modelId, acquireRound, responseFormat, signal } = args;
62
+ const cacheKey = context.cacheKey ?? undefined;
63
+ const model = args.model;
64
+ const toolDialect = model ? customToolDialect(model) : undefined;
65
+ const loadedSkills = roundLoadedSkills(context, session);
66
+ const promptPrefix = session.reselectTools?.(loadedSkills) ?? context.promptPrefix;
67
+ hlog('round start', {
68
+ round: context.round,
69
+ turns: context.history.length,
70
+ tools: session.sdkTools?.length ?? 0,
71
+ promptPrefix
72
+ });
73
+ const startedAt = session.now();
74
+ return {
75
+ args: {
76
+ modelId,
77
+ acquireRound,
78
+ history: context.history,
79
+ failureResults: context.failureResults,
80
+ tools: session.sdkTools,
81
+ generationParams: session.generationParams,
82
+ responseFormat,
83
+ toolDialect,
84
+ cacheKey,
85
+ signal,
86
+ round: context.round,
87
+ promptPrefix,
88
+ capture: args.captureInferenceCalls === true
89
+ },
90
+ promptPrefix,
91
+ startedAt
92
+ };
93
+ }
94
+ function recoverToolCalls({ recovered, session, round }) {
95
+ const markup = stripToolResponseBlocks(truncateAtControlToken(recovered.final.raw.fullText) || recovered.unproven || '');
96
+ let calls = recovered.final.toolCalls?.length
97
+ ? recovered.final.toolCalls
98
+ : recoverMarkupToolCalls(markup, session.enabled);
99
+ if (!calls.length) {
100
+ calls = recoverPrintedSkill(markup, session, round);
101
+ }
102
+ if (!calls.length) {
103
+ calls = recoverNamedSkill(markup, session, round);
104
+ }
105
+ return calls;
106
+ }
107
+ function recoverPrintedSkill(markup, session, round) {
108
+ if (!session.enabled.some((tool) => tool.name === SKILL_TOOL_NAME))
109
+ return [];
110
+ const rescued = recoverPrintedSkillLoad(markup, SKILL_TOOL_NAME);
111
+ const rescuedArgs = rescued[0]?.arguments;
112
+ const alreadyLoaded = rescuedArgs !== undefined &&
113
+ (session.loadedSkillFiles
114
+ .get(unquoteArg(rescuedArgs.name))
115
+ ?.has(unquoteArg(rescuedArgs.file)) ??
116
+ false);
117
+ if (alreadyLoaded) {
118
+ return [];
119
+ }
120
+ if (rescued.length) {
121
+ hlog('recovered printed skill load', { round });
122
+ }
123
+ return rescued;
124
+ }
125
+ function recoverNamedSkill(markup, session, round) {
126
+ if (!session.enabled.some((tool) => tool.name === SKILL_TOOL_NAME))
127
+ return [];
128
+ const calls = recoverSkillNamedCall(markup, session.inContextSkills
129
+ .filter((skill) => !session.nudgedSkills.has(skill.name))
130
+ .map((skill) => skill.name), SKILL_TOOL_NAME);
131
+ for (const call of calls) {
132
+ session.nudgedSkills.add(unquoteArg(call.arguments.name));
133
+ }
134
+ if (calls.length) {
135
+ hlog('recovered skill-named call', { round });
136
+ }
137
+ return calls;
138
+ }
139
+ function identifyToolCalls(calls, runId, round) {
140
+ const seen = new Set();
141
+ return calls.map((call, index) => {
142
+ let id = call.id;
143
+ if (typeof id !== 'string' || !id.trim() || seen.has(id)) {
144
+ let collision = 0;
145
+ do {
146
+ id = generatedId(index, collision++);
147
+ } while (seen.has(id));
148
+ }
149
+ seen.add(id);
150
+ return id === call.id ? call : { ...call, id };
151
+ });
152
+ function generatedId(index, collision = 0) {
153
+ const suffix = collision ? `-${collision}` : '';
154
+ return `${runId}:round-${round}:call-${index + 1}${suffix}`;
155
+ }
156
+ }
@@ -0,0 +1,7 @@
1
+ import { type RoundDonePayload } from '../../../machine/index.ts';
2
+ import type { CompletionActor } from '../session.ts';
3
+ interface WrapUpOutput extends RoundDonePayload {
4
+ response: string;
5
+ }
6
+ export declare const wrapUp: CompletionActor<WrapUpOutput>;
7
+ export {};
@@ -0,0 +1,61 @@
1
+ import { isFailureResultReference, spliceFrom } from '../../../machine/index.js';
2
+ import { runRound } from './stream.js';
3
+ import { degenerateAnswer } from '../../../helpers/run-outcome.js';
4
+ import { stripToolCallMarkup } from '../../../helpers/tool-call-markup.js';
5
+ import { promptPrefixHash } from '../../prompt-prefix.js';
6
+ import { materializeCompletionHistory } from '../../tool-turns.js';
7
+ export const wrapUp = async function wrapUp({ emit, input: { sdk, args, session }, context }) {
8
+ const { modelId, acquireRound, signal } = args;
9
+ const cacheKey = context.cacheKey ?? undefined;
10
+ const promptPrefix = promptPrefixHash({ system: systemMessage(context), tools: undefined });
11
+ const recovered = await runRound({
12
+ sdk,
13
+ args: {
14
+ modelId,
15
+ acquireRound,
16
+ history: context.history,
17
+ failureResults: context.failureResults,
18
+ tools: undefined,
19
+ generationParams: session.generationParams,
20
+ cacheKey,
21
+ signal,
22
+ round: context.roundsSent,
23
+ promptPrefix,
24
+ capture: args.captureInferenceCalls === true
25
+ },
26
+ emit
27
+ });
28
+ const replay = recovered.replay ? stripToolCallMarkup(recovered.replay) : '';
29
+ const fallbackResponse = degenerateAnswer(wrapOutcome(context), materializeCompletionHistory(context.history, context.failureResults), previewFinishedRound(session.runOutcomes.snapshot()));
30
+ return {
31
+ contentText: recovered.contentText,
32
+ thinkingText: '',
33
+ promptPrefix,
34
+ toolCalls: [],
35
+ stats: recovered.final.stats,
36
+ stopReason: recovered.final.stopReason,
37
+ replay,
38
+ history: recovered.history ? spliceFrom(context.history, recovered.history) : undefined,
39
+ cacheable: recovered.cacheable,
40
+ response: replay || recovered.contentText || fallbackResponse
41
+ };
42
+ };
43
+ function previewFinishedRound(state) {
44
+ return {
45
+ latestFailure: state.hasRoundResult ? state.roundFailure : state.latestFailure,
46
+ confirmedWrites: state.confirmedWrites
47
+ };
48
+ }
49
+ function systemMessage(context) {
50
+ const first = context.history[0];
51
+ return first && !isFailureResultReference(first) && first.role === 'system' ? first.content : null;
52
+ }
53
+ function wrapOutcome(ctx) {
54
+ if (ctx.outcome === 'mute' ||
55
+ ctx.outcome === 'exhausted' ||
56
+ ctx.outcome === 'search-capped' ||
57
+ ctx.outcome === 'time-capped') {
58
+ return ctx.outcome;
59
+ }
60
+ return 'exhausted';
61
+ }
@@ -0,0 +1,25 @@
1
+ import type { CompletionEvent, CompletionSdk } from '../completion.ts';
2
+ import { type CompletionArgs } from '../completion-loop/index.ts';
3
+ import { type EngineBoot, type EngineStep } from '../../machine/index.ts';
4
+ import type { RunLogRedactor } from '../../run-log-redact.ts';
5
+ export type CompletionRun = AsyncGenerator<CompletionEvent>;
6
+ export type CompletionRuntime = (request: CompletionArgs) => Promise<{
7
+ sdk?: CompletionSdk;
8
+ args?: Partial<CompletionArgs>;
9
+ }>;
10
+ export interface CompletionRunOptions {
11
+ boot?: EngineBoot;
12
+ onStep?: (step: EngineStep) => Promise<void>;
13
+ hostAppendTimeoutMs?: number;
14
+ onDetached?: (pending: Promise<void>, runId?: string) => void;
15
+ requestDigestKey?: Uint8Array;
16
+ redact?: RunLogRedactor;
17
+ redactShared?: <Value>(value: Value) => Value;
18
+ redactOperationResult?: RunLogRedactor['redactOperationResult'];
19
+ redactRecord?: RunLogRedactor['redactRecord'];
20
+ redactStep?: (step: EngineStep) => EngineStep;
21
+ lockOwner?: object;
22
+ resumeRequest?: Partial<CompletionArgs>;
23
+ bootRequest?: unknown;
24
+ }
25
+ export declare function driveCompletion(args: CompletionArgs, runtime: CompletionRuntime, options?: CompletionRunOptions): CompletionRun;