@theokit/sdk 5.12.0 → 5.13.0

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 (139) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/dist/{agent-IG7BP6GN.js → agent-5DSDDH7K.js} +5 -5
  3. package/dist/{agent-IG7BP6GN.js.map → agent-5DSDDH7K.js.map} +1 -1
  4. package/dist/{agent-CVzDy_Oj.d.ts → agent-DSMuwADp.d.ts} +9 -2
  5. package/dist/{agent-BVKIUP7F.cjs → agent-WOMRT3KX.cjs} +6 -6
  6. package/dist/{agent-BVKIUP7F.cjs.map → agent-WOMRT3KX.cjs.map} +1 -1
  7. package/dist/{agent-Cn0sphpA.d.cts → agent-iW5kPpfT.d.cts} +9 -2
  8. package/dist/{chunk-XJ4C4NFX.js → chunk-2PRGRYEQ.js} +61 -47
  9. package/dist/chunk-2PRGRYEQ.js.map +1 -0
  10. package/dist/{chunk-HN4IKB6X.cjs → chunk-2XWAYCFM.cjs} +15 -13
  11. package/dist/chunk-2XWAYCFM.cjs.map +1 -0
  12. package/dist/{chunk-VVGFZQZC.js → chunk-3LMVJTNJ.js} +9 -5
  13. package/dist/chunk-3LMVJTNJ.js.map +1 -0
  14. package/dist/{chunk-IO4RI5ZJ.cjs → chunk-47EACDOC.cjs} +4 -4
  15. package/dist/{chunk-IO4RI5ZJ.cjs.map → chunk-47EACDOC.cjs.map} +1 -1
  16. package/dist/{chunk-LSWHDOCL.cjs → chunk-4UYHP6NF.cjs} +64 -48
  17. package/dist/chunk-4UYHP6NF.cjs.map +1 -0
  18. package/dist/{chunk-ZLFFDPXC.js → chunk-73IITAF7.js} +36 -14
  19. package/dist/chunk-73IITAF7.js.map +1 -0
  20. package/dist/{chunk-XRPMZ7TO.js → chunk-CYWOJA6B.js} +6 -4
  21. package/dist/chunk-CYWOJA6B.js.map +1 -0
  22. package/dist/{chunk-AQW54OWQ.js → chunk-DFBWYETS.js} +5 -3
  23. package/dist/chunk-DFBWYETS.js.map +1 -0
  24. package/dist/{chunk-YOVZMN4P.cjs → chunk-DVP3YMDA.cjs} +3 -3
  25. package/dist/{chunk-YOVZMN4P.cjs.map → chunk-DVP3YMDA.cjs.map} +1 -1
  26. package/dist/{chunk-BRWI4HLK.cjs → chunk-FLDHYF5C.cjs} +13 -3
  27. package/dist/chunk-FLDHYF5C.cjs.map +1 -0
  28. package/dist/{chunk-BJ7BPLQK.js → chunk-JX4LB6XO.js} +124 -13
  29. package/dist/chunk-JX4LB6XO.js.map +1 -0
  30. package/dist/{chunk-Q6WT5535.cjs → chunk-KL7ZUMK3.cjs} +161 -50
  31. package/dist/chunk-KL7ZUMK3.cjs.map +1 -0
  32. package/dist/{chunk-FEAWEBWN.cjs → chunk-PDOXYXWX.cjs} +6 -4
  33. package/dist/chunk-PDOXYXWX.cjs.map +1 -0
  34. package/dist/{chunk-EEK7S77K.js → chunk-QGDPMM3C.js} +13 -3
  35. package/dist/chunk-QGDPMM3C.js.map +1 -0
  36. package/dist/{chunk-ZWLFHSON.cjs → chunk-R35ZJAYT.cjs} +38 -15
  37. package/dist/chunk-R35ZJAYT.cjs.map +1 -0
  38. package/dist/{chunk-4YD2WI57.cjs → chunk-R427EOZE.cjs} +19 -15
  39. package/dist/chunk-R427EOZE.cjs.map +1 -0
  40. package/dist/{chunk-TLVI2OQK.cjs → chunk-SETHRLQS.cjs} +18 -2
  41. package/dist/chunk-SETHRLQS.cjs.map +1 -0
  42. package/dist/{chunk-BO3PV3OP.js → chunk-TDED5XES.js} +18 -3
  43. package/dist/chunk-TDED5XES.js.map +1 -0
  44. package/dist/{chunk-4GUFNDZR.js → chunk-XOYNB3YN.js} +3 -3
  45. package/dist/{chunk-4GUFNDZR.js.map → chunk-XOYNB3YN.js.map} +1 -1
  46. package/dist/{chunk-NJBJ3CUG.js → chunk-ZTP6ZACR.js} +3 -3
  47. package/dist/{chunk-NJBJ3CUG.js.map → chunk-ZTP6ZACR.js.map} +1 -1
  48. package/dist/{compact-session-3U2JYTVG.js → compact-session-5HMX6KYT.js} +3 -3
  49. package/dist/{compact-session-3U2JYTVG.js.map → compact-session-5HMX6KYT.js.map} +1 -1
  50. package/dist/{compact-session-NM56BREJ.cjs → compact-session-B7P6EU3Z.cjs} +12 -12
  51. package/dist/{compact-session-NM56BREJ.cjs.map → compact-session-B7P6EU3Z.cjs.map} +1 -1
  52. package/dist/{cron-BWDYetbq.d.cts → cron-BvxrLW5J.d.cts} +1 -1
  53. package/dist/{cron-CHn-F0fC.d.ts → cron-DdKzwJqK.d.ts} +1 -1
  54. package/dist/cron.cjs +5 -5
  55. package/dist/cron.d.cts +2 -2
  56. package/dist/cron.d.ts +2 -2
  57. package/dist/cron.js +4 -4
  58. package/dist/eval.cjs +9 -9
  59. package/dist/eval.js +4 -4
  60. package/dist/{executor-HKHT4CWS.cjs → executor-5QL5AXIZ.cjs} +18 -15
  61. package/dist/executor-5QL5AXIZ.cjs.map +1 -0
  62. package/dist/{executor-3D2UDJHW.js → executor-THUXNAFR.js} +6 -3
  63. package/dist/executor-THUXNAFR.js.map +1 -0
  64. package/dist/generate-object-A5F576IT.cjs +20 -0
  65. package/dist/{generate-object-XBWD2PU7.cjs.map → generate-object-A5F576IT.cjs.map} +1 -1
  66. package/dist/{generate-object-S7MNVF2V.js → generate-object-TBDOBBYW.js} +4 -4
  67. package/dist/{generate-object-S7MNVF2V.js.map → generate-object-TBDOBBYW.js.map} +1 -1
  68. package/dist/generate-object.d.ts +14 -1
  69. package/dist/index.cjs +43 -43
  70. package/dist/index.d.cts +30 -4
  71. package/dist/index.d.ts +30 -4
  72. package/dist/index.js +13 -13
  73. package/dist/{inject-session-THABTKJY.js → inject-session-75L3NCNL.js} +3 -3
  74. package/dist/{inject-session-THABTKJY.js.map → inject-session-75L3NCNL.js.map} +1 -1
  75. package/dist/{inject-session-JVTZNQF6.cjs → inject-session-WOH7TPDX.cjs} +4 -4
  76. package/dist/{inject-session-JVTZNQF6.cjs.map → inject-session-WOH7TPDX.cjs.map} +1 -1
  77. package/dist/internal/providers/discovery.d.ts +2 -2
  78. package/dist/internal/providers/trust-gate.d.ts +35 -0
  79. package/dist/internal/runtime/plugin-loader/manifest-entry-import.d.ts +17 -0
  80. package/dist/internal/runtime/plugin-loader/workspace-plugin-trust.d.ts +16 -0
  81. package/dist/internal/structured-output-helpers.d.ts +5 -2
  82. package/dist/sandbox/bwrap.d.cts +10 -8
  83. package/dist/sandbox/bwrap.d.ts +10 -8
  84. package/dist/sandbox/deny-read.d.cts +24 -0
  85. package/dist/sandbox/deny-read.d.ts +24 -0
  86. package/dist/sandbox/index.cjs +198 -46
  87. package/dist/sandbox/index.cjs.map +1 -1
  88. package/dist/sandbox/index.d.cts +2 -1
  89. package/dist/sandbox/index.d.ts +2 -1
  90. package/dist/sandbox/index.js +184 -36
  91. package/dist/sandbox/index.js.map +1 -1
  92. package/dist/sandbox/linux-sandbox.d.cts +40 -5
  93. package/dist/sandbox/linux-sandbox.d.ts +40 -5
  94. package/dist/sandbox/local-sandbox.d.cts +3 -1
  95. package/dist/sandbox/local-sandbox.d.ts +3 -1
  96. package/dist/sandbox/seccomp-delivery.d.cts +49 -0
  97. package/dist/sandbox/seccomp-delivery.d.ts +49 -0
  98. package/dist/sandbox/shell-escape.d.cts +14 -2
  99. package/dist/sandbox/shell-escape.d.ts +14 -2
  100. package/dist/sandbox/types.d.cts +45 -0
  101. package/dist/sandbox/types.d.ts +45 -0
  102. package/dist/stream-object-AS4YYM4B.cjs +20 -0
  103. package/dist/{stream-object-TEEK3CAX.cjs.map → stream-object-AS4YYM4B.cjs.map} +1 -1
  104. package/dist/stream-object-EKM4WGTI.js +7 -0
  105. package/dist/{stream-object-R6SMYV4R.js.map → stream-object-EKM4WGTI.js.map} +1 -1
  106. package/dist/stream-object.d.ts +14 -1
  107. package/dist/subagents-loader.d.cts +1 -1
  108. package/dist/subagents-loader.d.ts +1 -1
  109. package/dist/types/agent.d.ts +8 -1
  110. package/dist/workflow-as-tool.d.ts +39 -5
  111. package/dist/workflow-errors.d.ts +16 -0
  112. package/dist/workflow.cjs +31 -23
  113. package/dist/workflow.d.cts +54 -4
  114. package/dist/workflow.d.ts +54 -4
  115. package/dist/workflow.js +2 -2
  116. package/docs/error-codes.md +16 -13
  117. package/docs/harness-capability-map.md +51 -5
  118. package/package.json +1 -1
  119. package/dist/chunk-4YD2WI57.cjs.map +0 -1
  120. package/dist/chunk-AQW54OWQ.js.map +0 -1
  121. package/dist/chunk-BJ7BPLQK.js.map +0 -1
  122. package/dist/chunk-BO3PV3OP.js.map +0 -1
  123. package/dist/chunk-BRWI4HLK.cjs.map +0 -1
  124. package/dist/chunk-EEK7S77K.js.map +0 -1
  125. package/dist/chunk-FEAWEBWN.cjs.map +0 -1
  126. package/dist/chunk-HN4IKB6X.cjs.map +0 -1
  127. package/dist/chunk-LSWHDOCL.cjs.map +0 -1
  128. package/dist/chunk-Q6WT5535.cjs.map +0 -1
  129. package/dist/chunk-TLVI2OQK.cjs.map +0 -1
  130. package/dist/chunk-VVGFZQZC.js.map +0 -1
  131. package/dist/chunk-XJ4C4NFX.js.map +0 -1
  132. package/dist/chunk-XRPMZ7TO.js.map +0 -1
  133. package/dist/chunk-ZLFFDPXC.js.map +0 -1
  134. package/dist/chunk-ZWLFHSON.cjs.map +0 -1
  135. package/dist/executor-3D2UDJHW.js.map +0 -1
  136. package/dist/executor-HKHT4CWS.cjs.map +0 -1
  137. package/dist/generate-object-XBWD2PU7.cjs +0 -20
  138. package/dist/stream-object-R6SMYV4R.js +0 -7
  139. package/dist/stream-object-TEEK3CAX.cjs +0 -20
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/workflow-errors.ts","../src/internal/workflow/snapshot-store.ts"],"names":[],"mappings":"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","file":"chunk-BO3PV3OP.js","sourcesContent":["/**\n * The workflow error hierarchy — runtime classes, deliberately NOT in `types/`.\n *\n * `types/index.ts` calls itself \"the canonical public contract\" and re-exports every sibling with\n * `export type *`, which cannot carry a value; `.dependency-cruiser.cjs` restates the same rule as\n * \"src/types/* are pure type definitions\". These twelve classes lived in `types/workflow.ts` anyway\n * and reached consumers only because the DTS rollup hoists a declaration the runtime bundle never\n * emitted — the shape that shipped #279 for `isValidTaskId`. `tests/lint/types-are-types-only.test.ts`\n * is what stops it recurring.\n *\n * The home mirrors `task-errors.ts`: errors for one public surface, next to it, at the src root.\n * Re-exported by name from `workflow.ts`, so `@theokit/sdk/workflow` is unchanged.\n *\n * @public\n */\n\nimport { TheokitAgentError } from \"./errors-base.js\";\nimport type { WorkflowRun } from \"./types/workflow.js\";\n\n/**\n * Thrown by `.commit()` when one step id appears twice anywhere in the workflow — including inside a\n * parallel branch, a branch predicate, the fallback, and the inner step of a `foreach` or `dowhile`.\n *\n * Ids address steps in snapshots and on resume, so this is refused at build time rather than\n * discovered mid-run. Workflows nested with `workflowStep()` are exempt: the child runs in its own\n * executor with its own id-space, so its ids cannot collide with the parent's.\n */\nexport class WorkflowDuplicateStepIdError extends TheokitAgentError {\n override readonly name = \"WorkflowDuplicateStepIdError\";\n constructor(public readonly stepId: string) {\n super(`Duplicate step id \"${stepId}\" in workflow.`, {\n code: \"workflow_duplicate_step_id\",\n isRetryable: false,\n });\n }\n}\n\n/**\n * SE27 — the whole-workflow `inputSchema` rejected `run(input)` (before step 1).\n * `detail` is a pre-formatted issues summary (a string, NOT Zod's `ZodIssue[]`).\n */\nexport class WorkflowInputError extends TheokitAgentError {\n override readonly name = \"WorkflowInputError\";\n constructor(\n public readonly workflowName: string,\n public readonly detail: string,\n ) {\n super(`Workflow \"${workflowName}\" input failed schema validation: ${detail}`, {\n code: \"workflow_input_invalid\",\n isRetryable: false,\n });\n }\n}\n\n/**\n * SE27 — the whole-workflow `outputSchema` rejected the final output (on `completed`).\n * `detail` is a pre-formatted issues summary (a string, NOT Zod's `ZodIssue[]`).\n */\nexport class WorkflowOutputError extends TheokitAgentError {\n override readonly name = \"WorkflowOutputError\";\n constructor(\n public readonly workflowName: string,\n public readonly detail: string,\n ) {\n super(`Workflow \"${workflowName}\" output failed schema validation: ${detail}`, {\n code: \"workflow_output_invalid\",\n isRetryable: false,\n });\n }\n}\n\n/**\n * SE29 — `WorkflowOptions.stateSchema` rejected an `initialState` or a\n * `setState(next)` call. `detail` is a pre-formatted issues summary.\n */\nexport class WorkflowStateError extends TheokitAgentError {\n override readonly name = \"WorkflowStateError\";\n constructor(\n public readonly workflowName: string,\n public readonly detail: string,\n ) {\n super(`Workflow \"${workflowName}\" state failed schema validation: ${detail}`, {\n code: \"workflow_state_invalid\",\n isRetryable: false,\n });\n }\n}\n\n/**\n * SE30 — a nested workflow (via `workflowStep`) did not `complete`. A nested\n * `suspended` is NOT resumable in v1 (resume continues AFTER the step, so the\n * child would be skipped) — restructure with a top-level suspend. A nested\n * `failed`/`cancelled` fails the parent step with the child's error attached.\n */\nexport class WorkflowNestedError extends TheokitAgentError {\n override readonly name = \"WorkflowNestedError\";\n constructor(\n public readonly stepId: string,\n public readonly childName: string,\n public readonly childStatus: Exclude<WorkflowRun[\"status\"], \"completed\">,\n public readonly childError?: { name: string; message: string },\n ) {\n super(\n `Nested workflow \"${childName}\" (step \"${stepId}\") ended with status \"${childStatus}\"${\n childStatus === \"suspended\"\n ? \" — nested suspend/resume is not supported in v1 (use a top-level suspend)\"\n : \"\"\n }${childError ? `: ${childError.name}: ${childError.message}` : \"\"}`,\n // Reconstruct a synthetic Error from the serialized child-error shape so\n // debuggers surface the nested cause chain — the original Error instance is\n // lost at the WorkflowRun serialization boundary, so this is the best\n // achievable without changing the run protocol.\n {\n code: \"workflow_nested_failed\",\n isRetryable: false,\n ...(childError\n ? { cause: Object.assign(new Error(childError.message), { name: childError.name }) }\n : {}),\n },\n );\n }\n}\n\n/**\n * Thrown out of `Workflow.run()` — one of the few workflow failures that rejects instead of arriving\n * as `run.status === \"failed\"` — when the committed workflow already has a run in flight under the\n * same run id.\n *\n * The lock key pairs the id minted at `.commit()` with the run id, not `WorkflowOptions.name`, so\n * two workflows sharing a name are independent and concurrent runs with distinct minted ids never\n * collide. In practice this only fires when a caller pins `WorkflowRunOptions.runId`, or resumes a\n * run id that is still executing. The registry is an in-process map: a crash releases every lock, and\n * it says nothing about runs in other processes.\n */\nexport class WorkflowAlreadyRunningError extends TheokitAgentError {\n override readonly name = \"WorkflowAlreadyRunningError\";\n constructor(\n public readonly workflowName: string,\n public readonly runId: string,\n ) {\n super(`Workflow \"${workflowName}\" run \"${runId}\" already in-flight.`, {\n code: \"workflow_already_running\",\n isRetryable: true,\n });\n }\n}\n\n/**\n * Thrown by `Workflow.resume()` when no snapshot exists for the given run id.\n *\n * The message suggests configuring persistence, which is the common cause but not the only one. The\n * run may never have suspended; it may have suspended under the default memory backend in a process\n * that has since exited; or the snapshot may already have been consumed, since resume deletes it\n * before re-entering the executor and a second resume of the same run id lands here.\n */\nexport class WorkflowSnapshotNotFoundError extends TheokitAgentError {\n override readonly name = \"WorkflowSnapshotNotFoundError\";\n constructor(public readonly runId: string) {\n super(`No snapshot found for runId \"${runId}\". Configure persistence to enable resume.`, {\n code: \"workflow_snapshot_not_found\",\n isRetryable: false,\n });\n }\n}\n\n/**\n * Raised when a `dowhile` step's condition kept returning true past `maxIterations` (default 100).\n *\n * It does not escape `run()`: the step fails, the run ends `status: \"failed\"`, and the error reaches\n * the caller flattened as `run.error` with `name: \"WorkflowMaxIterationsExceededError\"` — match on\n * the name, the instance does not survive. The guard is evaluated before each iteration, so the inner\n * step runs at most `maxIterations` times; raising the ceiling is a `maxIterations` on the step, and\n * there is no global default to change.\n */\nexport class WorkflowMaxIterationsExceededError extends TheokitAgentError {\n override readonly name = \"WorkflowMaxIterationsExceededError\";\n constructor(\n public readonly stepId: string,\n public readonly maxIterations: number,\n ) {\n super(`Step \"${stepId}\" exceeded max iterations (${maxIterations}).`, {\n code: \"workflow_max_iterations_exceeded\",\n isRetryable: false,\n });\n }\n}\n\n/** EC-4 absorbed — JSON.stringify failed on snapshot payload. */\nexport class WorkflowNotSerializableError extends TheokitAgentError {\n override readonly name = \"WorkflowNotSerializableError\";\n constructor(\n public readonly stepId: string,\n public readonly underlying: Error,\n ) {\n super(\n `Workflow snapshot at step \"${stepId}\" failed to serialize as JSON: ${underlying.message}. ` +\n `Persisted snapshots support only JSON-serializable values (no BigInt, no circular refs, no class instances with cycles).`,\n { code: \"workflow_not_serializable\", isRetryable: false },\n );\n }\n}\n\n/** EC-8 absorbed — `currentStepId` from snapshot not found in resumed workflow. */\nexport class WorkflowResumeStepNotFoundError extends TheokitAgentError {\n override readonly name = \"WorkflowResumeStepNotFoundError\";\n constructor(\n public readonly stepId: string,\n public readonly workflowName: string,\n ) {\n super(\n `Cannot resume: step \"${stepId}\" not found in workflow \"${workflowName}\". ` +\n `The Workflow definition diverged from the snapshot.`,\n { code: \"workflow_resume_step_not_found\", isRetryable: false },\n );\n }\n}\n\n/**\n * Aggregate failure from parallel branches.\n *\n * THE ONE PUBLIC WORKFLOW ERROR STILL OUTSIDE THE SDK HIERARCHY, deliberately. Its ten siblings were\n * reparented onto `TheokitAgentError` so `isTransientError` — and therefore `Retry.create`'s default\n * predicate — can see them at all. This one cannot follow without ceasing to be an `AggregateError`,\n * and `instanceof AggregateError` plus the standard `errors` array is the whole reason a caller\n * catches it: they want the branch failures, not a single message.\n *\n * The cost is stated rather than hidden: `isTransientError(err)` is `false` for this class, so a\n * parallel step whose branches failed transiently is not retried by the SDK's own helper. Inspect\n * `err.errors` and decide per branch — which is what an aggregate asks of a caller anyway, since\n * \"should this be retried\" has no single answer when the branches failed for different reasons.\n */\nexport class WorkflowParallelError extends AggregateError {\n override readonly name = \"WorkflowParallelError\";\n constructor(\n errors: ReadonlyArray<Error>,\n public readonly stepId: string,\n ) {\n super(errors, `${errors.length} branch(es) failed in parallel step \"${stepId}\".`);\n }\n}\n\n/** D238 — saga engine not yet implemented. */\nexport class WorkflowCompensateNotImplementedError extends TheokitAgentError {\n override readonly name = \"WorkflowCompensateNotImplementedError\";\n constructor(public readonly stepId: string) {\n super(\n `Step \"${stepId}\" defines compensate, but saga engine is deferred to v1.2. ` +\n `Remove compensate or implement rollback manually.`,\n { code: \"workflow_compensate_not_implemented\", isRetryable: false },\n );\n }\n}\n","/**\n * Snapshot store interface + InMemory and JsonFile backends (ADR D235).\n *\n * EC-4 absorbed: serialization happens here. `JSON.stringify` failure raises\n * `WorkflowNotSerializableError` instead of letting the underlying `TypeError`\n * leak.\n *\n * @internal\n */\n\nimport { mkdir, readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { WorkflowOptions, WorkflowSnapshot } from \"../../types/workflow.js\";\nimport { WorkflowNotSerializableError } from \"../../workflow-errors.js\";\nimport { atomicWriteText } from \"../persistence/atomic-write.js\";\n\nexport interface WorkflowSnapshotStore {\n save(snapshot: WorkflowSnapshot): Promise<void>;\n load(runId: string): Promise<WorkflowSnapshot | undefined>;\n delete(runId: string): Promise<void>;\n list(\n workflowName?: string,\n ): Promise<ReadonlyArray<{ runId: string; workflowName: string; suspendedAt: number }>>;\n}\n\n/* ─── InMemory backend (default) ─── */\n\nclass InMemoryWorkflowSnapshotStore implements WorkflowSnapshotStore {\n private readonly map = new Map<string, WorkflowSnapshot>();\n\n async save(snapshot: WorkflowSnapshot): Promise<void> {\n // Verify serializability even in-memory so behavior is consistent with json backend.\n try {\n JSON.stringify(snapshot);\n } catch (err) {\n throw new WorkflowNotSerializableError(\n snapshot.currentStepId,\n err instanceof Error ? err : new Error(String(err)),\n );\n }\n this.map.set(snapshot.runId, snapshot);\n }\n async load(runId: string): Promise<WorkflowSnapshot | undefined> {\n return this.map.get(runId);\n }\n async delete(runId: string): Promise<void> {\n this.map.delete(runId);\n }\n async list(\n workflowName?: string,\n ): Promise<ReadonlyArray<{ runId: string; workflowName: string; suspendedAt: number }>> {\n return [...this.map.values()]\n .filter((s) => workflowName === undefined || s.workflowName === workflowName)\n .map((s) => ({\n runId: s.runId,\n workflowName: s.workflowName,\n suspendedAt: s.suspendedAt,\n }));\n }\n}\n\n/* ─── Json file backend (opt-in) ─── */\n\nclass JsonFileWorkflowSnapshotStore implements WorkflowSnapshotStore {\n constructor(private readonly dir: string) {}\n\n private filePath(runId: string): string {\n return join(this.dir, `${runId}.json`);\n }\n\n async save(snapshot: WorkflowSnapshot): Promise<void> {\n let serialized: string;\n try {\n serialized = JSON.stringify(snapshot);\n } catch (err) {\n throw new WorkflowNotSerializableError(\n snapshot.currentStepId,\n err instanceof Error ? err : new Error(String(err)),\n );\n }\n await mkdir(this.dir, { recursive: true });\n await atomicWriteText(this.filePath(snapshot.runId), serialized);\n }\n\n async load(runId: string): Promise<WorkflowSnapshot | undefined> {\n try {\n const raw = await readFile(this.filePath(runId), \"utf8\");\n return JSON.parse(raw) as WorkflowSnapshot;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw err;\n }\n }\n\n async delete(runId: string): Promise<void> {\n try {\n await (await import(\"node:fs/promises\")).unlink(this.filePath(runId));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") throw err;\n }\n }\n\n private async readEntriesOrEmpty(): Promise<string[]> {\n try {\n return await readdir(this.dir);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw err;\n }\n }\n\n private async readSnapshotSafe(file: string): Promise<WorkflowSnapshot | undefined> {\n try {\n const raw = await readFile(join(this.dir, file), \"utf8\");\n return JSON.parse(raw) as WorkflowSnapshot;\n } catch {\n return undefined;\n }\n }\n\n async list(\n workflowName?: string,\n ): Promise<ReadonlyArray<{ runId: string; workflowName: string; suspendedAt: number }>> {\n const entries = await this.readEntriesOrEmpty();\n const results: Array<{ runId: string; workflowName: string; suspendedAt: number }> = [];\n for (const file of entries) {\n if (!file.endsWith(\".json\")) continue;\n const snap = await this.readSnapshotSafe(file);\n if (snap === undefined) continue;\n if (workflowName !== undefined && snap.workflowName !== workflowName) continue;\n results.push({\n runId: snap.runId,\n workflowName: snap.workflowName,\n suspendedAt: snap.suspendedAt,\n });\n }\n return results;\n }\n}\n\n/* ─── Resolver: per-Workflow store cache ─── */\n\nconst memoryStore = new InMemoryWorkflowSnapshotStore();\nconst jsonStores = new Map<string, JsonFileWorkflowSnapshotStore>();\n\nexport function getSnapshotStoreFor(options: WorkflowOptions): WorkflowSnapshotStore {\n if (options.persistence?.backend === \"json\") {\n const dir = options.persistence.dir as string; // schema enforces dir is set\n let store = jsonStores.get(dir);\n if (store === undefined) {\n store = new JsonFileWorkflowSnapshotStore(dir);\n jsonStores.set(dir, store);\n }\n return store;\n }\n return memoryStore;\n}\n\n/** Test seam — clear in-memory store between tests. */\nexport function __resetSnapshotStoresForTests(): void {\n jsonStores.clear();\n // memoryStore has private map; reset via assignment.\n // biome-ignore lint/suspicious/noExplicitAny: test-only seam\n (memoryStore as any).map.clear();\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/sandbox/shell-escape.ts","../src/sandbox/types.ts","../src/sandbox/local-sandbox.ts"],"names":["TheokitAgentError","ConfigurationError","execFile","resolveChildEnv","path","mkdir","dirname","fsWriteFile"],"mappings":"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","file":"chunk-BRWI4HLK.cjs","sourcesContent":["/**\n * POSIX shell escaping for values interpolated into a `SandboxBackend.execute`\n * command string. `execute` runs via `/bin/sh -c`, so any untrusted value\n * (repo URL, ref, path) MUST be quoted to prevent command injection.\n *\n * @internal\n */\n\n/** Wrap `arg` in single quotes, escaping embedded single quotes (`'\\''`). */\nexport function shellEscapePosix(arg: string): string {\n return `'${arg.replace(/'/g, \"'\\\\''\")}'`;\n}\n","/**\n * Sandbox backend protocol — pluggable execution environment for agent tools.\n *\n * Per ADR D1: only 2 abstract methods (`execute` + `uploadFile`). All\n * higher-level operations are derived on the base class. New backends\n * (Docker, Firecracker, E2B) only implement those 2 methods.\n *\n * @public\n */\n\nimport { ConfigurationError, TheokitAgentError } from \"../errors.js\";\nimport type { EnvPolicy } from \"../types/env-policy.js\";\nimport { shellEscapePosix } from \"./shell-escape.js\";\n\n/**\n * What a {@link SandboxBackend} returns for one command.\n *\n * `exitCode` is a coarse signal rather than the child's real exit status: the backends in this\n * package report `0` on success, `124` on timeout, and `1` for everything else — including a command\n * that exited with its own non-zero code. Read `timedOut` to tell a killed command from a failed one,\n * and `stderr` for the reason; branching on a specific exit code will not work here.\n *\n * `stdout` and `stderr` are truncated independently at `SandboxConfig.maxOutputBytes`, with a\n * trailing `...(truncated)` marker. Neither is safe to parse as a complete document without checking\n * for it.\n */\nexport interface ExecuteResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n timedOut: boolean;\n}\n\n/**\n * Construction-time settings shared by every {@link SandboxBackend}. All fields are optional and the\n * base constructor fills them in, so `{}` is a valid config: `workDir` `/tmp`, `timeoutMs` 30000,\n * `maxOutputBytes` 5 MiB, `env` `\"inherit-scrubbed\"`.\n *\n * `workDir` is the child process's cwd and the base a relative `uploadFile` path resolves against. It\n * is not a boundary — under `LocalSandbox` nothing stops a command, or an absolute path, from leaving\n * it. Only `LinuxSandbox` makes it enforceable.\n *\n * `timeoutMs` is the default for every call; `execute(command, { timeoutMs })` overrides it per\n * command. On expiry the child is killed and the result carries `timedOut: true` with `exitCode`\n * 124 — the partial output collected so far is still returned.\n */\nexport interface SandboxConfig {\n workDir?: string;\n timeoutMs?: number;\n maxOutputBytes?: number;\n /**\n * #54 — env inherit/scrub policy for the executed command's child process.\n * Defaults to `\"inherit-scrubbed\"` (drop secret-like vars: `*KEY*`, `*SECRET*`,\n * `*TOKEN*`, `*PASSWORD*`, `*_AUTH*`). Pass `\"all\"` to restore full inheritance\n * or `\"core\"` for a minimal safe allowlist.\n */\n env?: EnvPolicy;\n}\n\n/**\n * A backend refused a command on policy grounds — the environment works, and it said no. Carries a\n * stable `code: \"sandbox_security\"` for callers that prefer not to match on the class.\n *\n * Nothing in this package throws it, which is worth knowing before you write a `catch` for it:\n * `LocalSandbox` and `LinuxSandbox` report a refusal through {@link ExecuteResult} (non-zero\n * `exitCode`, reason on `stderr`), and a write blocked under confinement surfaces as a plain `Error`\n * from `uploadFile`. This type exists so a custom backend that must reject a command BEFORE spawning\n * anything — a container or VM runner enforcing its own policy — can do so in the protocol's\n * vocabulary instead of inventing an error of its own.\n */\nexport class SandboxSecurityError extends TheokitAgentError {\n override readonly name = \"SandboxSecurityError\";\n override readonly code = \"sandbox_security\" as const;\n constructor(message: string) {\n // not retryable: a refused command is refused every time; retrying re-asks the same question\n super(message, { code: \"sandbox_security\", isRetryable: false });\n }\n}\n\n/**\n * A backend cannot be used at all: its runtime is missing or unusable. The distinction from\n * {@link SandboxSecurityError} is which side failed — there the sandbox worked and denied the\n * command, here there is no sandbox. Carries `code: \"sandbox_not_available\"`.\n *\n * Nothing in this package throws it either, and that is a position rather than an oversight:\n * `createSandboxBackend` treats a missing bubblewrap as a degradation, warns once, and hands back an\n * unconfined `LocalSandbox`. Throw this instead from a backend that must never silently run outside\n * its isolation.\n */\nexport class SandboxNotAvailableError extends TheokitAgentError {\n override readonly name = \"SandboxNotAvailableError\";\n override readonly code = \"sandbox_not_available\" as const;\n constructor(message: string) {\n // not retryable: a missing runtime does not appear on a second attempt\n super(message, { code: \"sandbox_not_available\", isRetryable: false });\n }\n}\n\n/**\n * The execution capability handed to an agent tool, and the extension point for new environments.\n *\n * A backend implements exactly two methods, `execute` and `uploadFile`. Everything else here —\n * `readFile`, `glob`, `grep`, `listDir` — is derived from `execute` by shelling out `cat`, `find`,\n * `grep` and `ls`, so a subclass that overrides `execute` alone inherits confined reads, searches and\n * listings for free. It does not inherit confined writes: `writeFile` delegates to `uploadFile`, and\n * that is the second override `LinuxSandbox` needs.\n *\n * Choosing one: `LocalSandbox` runs the command on the host with no isolation and suits code you\n * already trust; `LinuxSandbox` adds kernel confinement where bubblewrap is available;\n * `createSandboxBackend` probes and picks between them, and is the right entry point unless you have\n * a reason to pin one. For genuinely untrusted code you want a container or VM backend, which this\n * package does not ship — write it against these two methods.\n *\n * Because the derived helpers assemble shell command lines (arguments escaped for POSIX `sh`), a\n * backend whose `execute` is not a POSIX shell must override them as well.\n */\nexport abstract class SandboxBackend {\n protected config: SandboxConfig;\n\n constructor(config: SandboxConfig = {}) {\n this.config = {\n workDir: config.workDir ?? \"/tmp\",\n timeoutMs: config.timeoutMs ?? 30_000,\n maxOutputBytes: config.maxOutputBytes ?? 5 * 1024 * 1024,\n // #54 — preserve the env policy so backends can scrub secrets.\n env: config.env ?? \"inherit-scrubbed\",\n };\n }\n\n abstract execute(command: string, opts?: { timeoutMs?: number }): Promise<ExecuteResult>;\n\n abstract uploadFile(path: string, content: string | Buffer): Promise<void>;\n\n async readFile(path: string): Promise<string> {\n const result = await this.execute(`cat ${this.shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`readFile failed: ${result.stderr}`);\n }\n return result.stdout;\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n await this.uploadFile(path, content);\n }\n\n async glob(pattern: string, cwd?: string): Promise<string[]> {\n const dir = cwd ?? this.config.workDir ?? \".\";\n const result = await this.execute(\n `find ${this.shellEscape(dir)} -name ${this.shellEscape(pattern)} -type f 2>/dev/null`,\n );\n this.assertCommandRan(\"glob\", result);\n return result.stdout.trim().split(\"\\n\").filter(Boolean);\n }\n\n async grep(pattern: string, path?: string): Promise<string[]> {\n const target = path ?? \".\";\n const result = await this.execute(\n `grep -rn ${this.shellEscape(pattern)} ${this.shellEscape(target)} 2>/dev/null`,\n );\n // `grep` exits 1 for NO MATCH and >= 2 for an error, so a 1 is an answer and is not asserted on.\n if (result.exitCode !== 1) this.assertCommandRan(\"grep\", result);\n return result.stdout.trim().split(\"\\n\").filter(Boolean);\n }\n\n async listDir(path: string): Promise<string[]> {\n const result = await this.execute(`ls -1 ${this.shellEscape(path)}`);\n this.assertCommandRan(\"listDir\", result);\n return result.stdout.trim().split(\"\\n\").filter(Boolean);\n }\n\n /**\n * Turns \"the command did not run\" into an error instead of an empty array.\n *\n * `glob`, `grep` and `listDir` used to `return []` on any non-zero exit, so a search that could not\n * run reported the same thing as a search that found nothing — opposite facts, one normal and one\n * meaning the agent is looking at a filesystem it cannot read. That is the failure mode a backend\n * whose `execute` is not a POSIX shell hits, which this class's own docblock warns about in prose\n * and could not enforce.\n *\n * A genuine no-match is still `[]`: `find` exits 0 with empty output, and `grep`'s exit 1 is\n * checked by its caller before this is reached.\n */\n private assertCommandRan(operation: string, result: ExecuteResult): void {\n if (result.exitCode === 0) return;\n throw new ConfigurationError(\n `${operation} failed (exit ${String(result.exitCode)}): ${result.stderr.trim() || \"no stderr\"}. ` +\n `The derived helpers shell out to POSIX \\`cat\\`/\\`find\\`/\\`grep\\`/\\`ls\\` — a backend whose ` +\n `execute() is not a POSIX shell must override them.`,\n { code: \"sandbox_derived_helper_failed\" },\n );\n }\n\n protected truncateOutput(output: string): string {\n const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;\n if (Buffer.byteLength(output) > max) {\n return `${output.slice(0, max)}\\n...(truncated)`;\n }\n return output;\n }\n\n private shellEscape(arg: string): string {\n return shellEscapePosix(arg);\n }\n}\n\n/**\n * A backend OR a per-request resolver of one — mirrors `FilesystemProvider` / `InteractiveProvider`.\n * A resolver runs at tool-execution time (request scope), so a multi-tenant / multi-role agent gets a\n * distinct sandbox per request without a shared mutable one. This is how a tool takes execution as an\n * INJECTED capability: the same tool runs on a local sandbox, a container/E2B backend (cluster/web), or\n * any future backend, with no direct `child_process` import.\n *\n * @public\n */\nexport type SandboxProvider<Ctx = unknown> =\n | SandboxBackend\n | ((ctx: Ctx) => SandboxBackend | Promise<SandboxBackend>);\n\n/** Resolve a {@link SandboxProvider} to a concrete backend for `ctx`. */\nexport async function resolveSandbox<Ctx>(\n provider: SandboxProvider<Ctx>,\n ctx: Ctx,\n): Promise<SandboxBackend> {\n return provider instanceof SandboxBackend ? provider : provider(ctx);\n}\n","/**\n * LocalSandbox — subprocess-based execution. **This is NOT an isolation\n * boundary.** It runs the command via `/bin/sh -c` in the SAME OS as the host\n * with the host's filesystem and network fully reachable — it provides NO\n * process, filesystem, or network isolation. Its only safety affordances are:\n * - a wall-clock timeout (kills a runaway command),\n * - an output-size cap (bounds memory), and\n * - env scrubbing (#54): secret-like parent env vars (`*KEY*`/`*SECRET*`/\n * `*TOKEN*`/`*PASSWORD*`/`*_AUTH*`) are dropped from the child by default\n * (`SandboxConfig.env`), so a shell tool cannot exfiltrate host secrets via\n * the environment.\n *\n * For real isolation (untrusted code), use a container/VM backend — NOT this.\n *\n * @public\n */\n\nimport { execFile } from \"node:child_process\";\nimport { writeFile as fsWriteFile, mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport { resolveChildEnv } from \"../internal/runtime/lifecycle/env-policy.js\";\nimport { type ExecuteResult, SandboxBackend, type SandboxConfig } from \"./types.js\";\n\n/**\n * Runs a command with `/bin/sh -c` on the host. NOT an isolation boundary — the\n * module note above states exactly what it does and does not protect.\n *\n * const sandbox = new LocalSandbox({ workDir: \"/srv/repo\", timeoutMs: 10_000 });\n * const { stdout, exitCode, timedOut } = await sandbox.execute(\"ls -1\");\n *\n * Needs a POSIX host with `/bin/sh`. Every helper inherited from\n * {@link SandboxBackend} — `readFile`, `glob`, `grep`, `listDir` — is built on\n * this `execute`, so they inherit that requirement too.\n *\n * How it fails: `execute` NEVER rejects. Every outcome, including a failure to\n * spawn, comes back as an {@link ExecuteResult}; read `timedOut` first\n * (`true` implies `exitCode` 124) and `stderr` for the reason. `uploadFile` DOES\n * reject, with the raw `node:fs` error, on a bad path or missing permission.\n *\n * Traps:\n * - `exitCode` is not the child's exit code. It is 0, 124 (timed out) or 1 — a\n * command that exits 3 is reported as 1, so branching on a specific code does\n * not work here.\n * - Output beyond `maxOutputBytes` (default 5 MiB) makes Node kill the child.\n * The result is `exitCode: 1` and `timedOut: false`, with the cut stream\n * carrying the `...(truncated)` marker described on `ExecuteResult` (#363).\n * Since `exitCode` is 1 either way, that marker is what tells a lost-output\n * result from a command that genuinely failed.\n * - `uploadFile` resolves a relative path against `workDir` but does not contain\n * it: an absolute path, or one containing `..`, writes wherever the process\n * can. `workDir` is a starting directory, not a jail.\n * - Secret-like parent env vars are dropped by default. Passing\n * `env: \"all\"` in {@link SandboxConfig} puts the host's API keys back within\n * reach of any command the agent runs.\n */\nexport class LocalSandbox extends SandboxBackend {\n constructor(config: SandboxConfig = {}) {\n super(config);\n }\n\n async execute(command: string, opts?: { timeoutMs?: number }): Promise<ExecuteResult> {\n const timeout = opts?.timeoutMs ?? this.config.timeoutMs ?? 30_000;\n const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;\n\n return new Promise<ExecuteResult>((resolve) => {\n const child = execFile(\n \"/bin/sh\",\n [\"-c\", command],\n {\n cwd: this.config.workDir,\n timeout,\n maxBuffer: max,\n encoding: \"utf-8\",\n // #54 — scrub secret-like host env vars from the child by default.\n env: resolveChildEnv({ policy: this.config.env }),\n },\n (error, stdout, stderr) => {\n resolve(this.buildResult(error, stdout ?? \"\", stderr ?? \"\"));\n },\n );\n\n // Safety: if child somehow doesn't callback\n child.on(\"error\", () => {\n resolve({ stdout: \"\", stderr: \"spawn error\", exitCode: 1, timedOut: false });\n });\n });\n }\n\n private buildResult(error: Error | null, stdout: string, stderr: string): ExecuteResult {\n const timedOut = error !== null && \"killed\" in error && (error as { killed: boolean }).killed;\n // #363 — the ONLY reliable signal that output was lost. Node caps the buffer AT `maxBuffer`, so\n // for ASCII output the string comes back exactly at the cap and `truncateOutput`'s `> max` test\n // never fires; a length comparison cannot tell a cut document from a complete one that happens\n // to be that long. The child being killed for overflow can.\n const overflowed =\n error !== null && (error as { code?: unknown }).code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\";\n return {\n stdout: this.markIfCut(this.truncateOutput(stdout), overflowed),\n stderr: this.markIfCut(this.truncateOutput(stderr), overflowed),\n exitCode: timedOut ? 124 : error ? 1 : 0,\n timedOut,\n };\n }\n\n /**\n * Append the `...(truncated)` marker `ExecuteResult` tells callers to branch on, when the child\n * was killed for exceeding `maxOutputBytes` and this stream is the one sitting at the cap.\n *\n * `truncateOutput` has already run, so an output it marked is left alone rather than marked\n * twice. Node does not say WHICH stream overflowed, so the stream at the cap is the one that\n * lost data — the other, being shorter, is complete.\n */\n private markIfCut(output: string, overflowed: boolean): string {\n if (!overflowed) return output;\n if (output.endsWith(\"...(truncated)\")) return output;\n const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;\n return Buffer.byteLength(output) >= max ? `${output}\\n...(truncated)` : output;\n }\n\n async uploadFile(path: string, content: string | Buffer): Promise<void> {\n const fullPath = path.startsWith(\"/\") ? path : `${this.config.workDir}/${path}`;\n await mkdir(dirname(fullPath), { recursive: true });\n await fsWriteFile(fullPath, content, \"utf-8\");\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/sandbox/shell-escape.ts","../src/sandbox/types.ts","../src/sandbox/local-sandbox.ts"],"names":["fsWriteFile"],"mappings":";;;;;;;AASO,SAAS,iBAAiB,GAAA,EAAqB;AACpD,EAAA,OAAO,CAAA,CAAA,EAAI,GAAA,CAAI,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAC,CAAA,CAAA,CAAA;AACvC;;;AC2DO,IAAM,oBAAA,GAAN,cAAmC,iBAAA,CAAkB;AAAA,EACxC,IAAA,GAAO,sBAAA;AAAA,EACP,IAAA,GAAO,kBAAA;AAAA,EACzB,YAAY,OAAA,EAAiB;AAE3B,IAAA,KAAA,CAAM,SAAS,EAAE,IAAA,EAAM,kBAAA,EAAoB,WAAA,EAAa,OAAO,CAAA;AAAA,EACjE;AACF;AAYO,IAAM,wBAAA,GAAN,cAAuC,iBAAA,CAAkB;AAAA,EAC5C,IAAA,GAAO,0BAAA;AAAA,EACP,IAAA,GAAO,uBAAA;AAAA,EACzB,YAAY,OAAA,EAAiB;AAE3B,IAAA,KAAA,CAAM,SAAS,EAAE,IAAA,EAAM,uBAAA,EAAyB,WAAA,EAAa,OAAO,CAAA;AAAA,EACtE;AACF;AAoBO,IAAe,iBAAf,MAA8B;AAAA,EACzB,MAAA;AAAA,EAEV,WAAA,CAAY,MAAA,GAAwB,EAAC,EAAG;AACtC,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,OAAA,EAAS,OAAO,OAAA,IAAW,MAAA;AAAA,MAC3B,SAAA,EAAW,OAAO,SAAA,IAAa,GAAA;AAAA,MAC/B,cAAA,EAAgB,MAAA,CAAO,cAAA,IAAkB,CAAA,GAAI,IAAA,GAAO,IAAA;AAAA;AAAA,MAEpD,GAAA,EAAK,OAAO,GAAA,IAAO;AAAA,KACrB;AAAA,EACF;AAAA,EAMA,MAAM,SAAS,IAAA,EAA+B;AAC5C,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAO,IAAA,CAAK,WAAA,CAAY,IAAI,CAAC,CAAA,CAAE,CAAA;AACjE,IAAA,IAAI,MAAA,CAAO,aAAa,CAAA,EAAG;AACzB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AAAA,IACrD;AACA,IAAA,OAAO,MAAA,CAAO,MAAA;AAAA,EAChB;AAAA,EAEA,MAAM,SAAA,CAAU,IAAA,EAAc,OAAA,EAAgC;AAC5D,IAAA,MAAM,IAAA,CAAK,UAAA,CAAW,IAAA,EAAM,OAAO,CAAA;AAAA,EACrC;AAAA,EAEA,MAAM,IAAA,CAAK,OAAA,EAAiB,GAAA,EAAiC;AAC3D,IAAA,MAAM,GAAA,GAAM,GAAA,IAAO,IAAA,CAAK,MAAA,CAAO,OAAA,IAAW,GAAA;AAC1C,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA;AAAA,MACxB,CAAA,KAAA,EAAQ,KAAK,WAAA,CAAY,GAAG,CAAC,CAAA,OAAA,EAAU,IAAA,CAAK,WAAA,CAAY,OAAO,CAAC,CAAA,oBAAA;AAAA,KAClE;AACA,IAAA,IAAA,CAAK,gBAAA,CAAiB,QAAQ,MAAM,CAAA;AACpC,IAAA,OAAO,MAAA,CAAO,OAAO,IAAA,EAAK,CAAE,MAAM,IAAI,CAAA,CAAE,OAAO,OAAO,CAAA;AAAA,EACxD;AAAA,EAEA,MAAM,IAAA,CAAK,OAAA,EAAiB,IAAA,EAAkC;AAC5D,IAAA,MAAM,SAAS,IAAA,IAAQ,GAAA;AACvB,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA;AAAA,MACxB,CAAA,SAAA,EAAY,KAAK,WAAA,CAAY,OAAO,CAAC,CAAA,CAAA,EAAI,IAAA,CAAK,WAAA,CAAY,MAAM,CAAC,CAAA,YAAA;AAAA,KACnE;AAEA,IAAA,IAAI,OAAO,QAAA,KAAa,CAAA,EAAG,IAAA,CAAK,gBAAA,CAAiB,QAAQ,MAAM,CAAA;AAC/D,IAAA,OAAO,MAAA,CAAO,OAAO,IAAA,EAAK,CAAE,MAAM,IAAI,CAAA,CAAE,OAAO,OAAO,CAAA;AAAA,EACxD;AAAA,EAEA,MAAM,QAAQ,IAAA,EAAiC;AAC7C,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,SAAS,IAAA,CAAK,WAAA,CAAY,IAAI,CAAC,CAAA,CAAE,CAAA;AACnE,IAAA,IAAA,CAAK,gBAAA,CAAiB,WAAW,MAAM,CAAA;AACvC,IAAA,OAAO,MAAA,CAAO,OAAO,IAAA,EAAK,CAAE,MAAM,IAAI,CAAA,CAAE,OAAO,OAAO,CAAA;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcQ,gBAAA,CAAiB,WAAmB,MAAA,EAA6B;AACvE,IAAA,IAAI,MAAA,CAAO,aAAa,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,kBAAA;AAAA,MACR,CAAA,EAAG,SAAS,CAAA,cAAA,EAAiB,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAC,CAAA,GAAA,EAAM,MAAA,CAAO,MAAA,CAAO,IAAA,EAAK,IAAK,WAAW,CAAA,mJAAA,CAAA;AAAA,MAG7F,EAAE,MAAM,+BAAA;AAAgC,KAC1C;AAAA,EACF;AAAA,EAEU,eAAe,MAAA,EAAwB;AAC/C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,cAAA,IAAkB,IAAI,IAAA,GAAO,IAAA;AACrD,IAAA,IAAI,MAAA,CAAO,UAAA,CAAW,MAAM,CAAA,GAAI,GAAA,EAAK;AACnC,MAAA,OAAO,CAAA,EAAG,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,GAAG,CAAC;AAAA,cAAA,CAAA;AAAA,IAChC;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEQ,YAAY,GAAA,EAAqB;AACvC,IAAA,OAAO,iBAAiB,GAAG,CAAA;AAAA,EAC7B;AACF;AAgBA,eAAsB,cAAA,CACpB,UACA,GAAA,EACyB;AACzB,EAAA,OAAO,QAAA,YAAoB,cAAA,GAAiB,QAAA,GAAW,QAAA,CAAS,GAAG,CAAA;AACrE;ACxKO,IAAM,YAAA,GAAN,cAA2B,cAAA,CAAe;AAAA,EAC/C,WAAA,CAAY,MAAA,GAAwB,EAAC,EAAG;AACtC,IAAA,KAAA,CAAM,MAAM,CAAA;AAAA,EACd;AAAA,EAEA,MAAM,OAAA,CAAQ,OAAA,EAAiB,IAAA,EAAuD;AACpF,IAAA,MAAM,OAAA,GAAU,IAAA,EAAM,SAAA,IAAa,IAAA,CAAK,OAAO,SAAA,IAAa,GAAA;AAC5D,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,cAAA,IAAkB,IAAI,IAAA,GAAO,IAAA;AAErD,IAAA,OAAO,IAAI,OAAA,CAAuB,CAAC,OAAA,KAAY;AAC7C,MAAA,MAAM,KAAA,GAAQ,QAAA;AAAA,QACZ,SAAA;AAAA,QACA,CAAC,MAAM,OAAO,CAAA;AAAA,QACd;AAAA,UACE,GAAA,EAAK,KAAK,MAAA,CAAO,OAAA;AAAA,UACjB,OAAA;AAAA,UACA,SAAA,EAAW,GAAA;AAAA,UACX,QAAA,EAAU,OAAA;AAAA;AAAA,UAEV,KAAK,eAAA,CAAgB,EAAE,QAAQ,IAAA,CAAK,MAAA,CAAO,KAAK;AAAA,SAClD;AAAA,QACA,CAAC,KAAA,EAAO,MAAA,EAAQ,MAAA,KAAW;AACzB,UAAA,OAAA,CAAQ,KAAK,WAAA,CAAY,KAAA,EAAO,UAAU,EAAA,EAAI,MAAA,IAAU,EAAE,CAAC,CAAA;AAAA,QAC7D;AAAA,OACF;AAGA,MAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AACtB,QAAA,OAAA,CAAQ,EAAE,QAAQ,EAAA,EAAI,MAAA,EAAQ,eAAe,QAAA,EAAU,CAAA,EAAG,QAAA,EAAU,KAAA,EAAO,CAAA;AAAA,MAC7E,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,WAAA,CAAY,KAAA,EAAqB,MAAA,EAAgB,MAAA,EAA+B;AACtF,IAAA,MAAM,QAAA,GAAW,KAAA,KAAU,IAAA,IAAQ,QAAA,IAAY,SAAU,KAAA,CAA8B,MAAA;AAKvF,IAAA,MAAM,UAAA,GACJ,KAAA,KAAU,IAAA,IAAS,KAAA,CAA6B,IAAA,KAAS,mCAAA;AAC3D,IAAA,OAAO;AAAA,MACL,QAAQ,IAAA,CAAK,SAAA,CAAU,KAAK,cAAA,CAAe,MAAM,GAAG,UAAU,CAAA;AAAA,MAC9D,QAAQ,IAAA,CAAK,SAAA,CAAU,KAAK,cAAA,CAAe,MAAM,GAAG,UAAU,CAAA;AAAA,MAC9D,QAAA,EAAU,QAAA,GAAW,GAAA,GAAM,KAAA,GAAQ,CAAA,GAAI,CAAA;AAAA,MACvC;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,SAAA,CAAU,QAAgB,UAAA,EAA6B;AAC7D,IAAA,IAAI,CAAC,YAAY,OAAO,MAAA;AACxB,IAAA,IAAI,MAAA,CAAO,QAAA,CAAS,gBAAgB,CAAA,EAAG,OAAO,MAAA;AAC9C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,cAAA,IAAkB,IAAI,IAAA,GAAO,IAAA;AACrD,IAAA,OAAO,OAAO,UAAA,CAAW,MAAM,CAAA,IAAK,GAAA,GAAM,GAAG,MAAM;AAAA,cAAA,CAAA,GAAqB,MAAA;AAAA,EAC1E;AAAA,EAEA,MAAM,UAAA,CAAW,IAAA,EAAc,OAAA,EAAyC;AACtE,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,GAAI,IAAA,GAAO,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAC7E,IAAA,MAAM,MAAM,OAAA,CAAQ,QAAQ,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAClD,IAAA,MAAMA,SAAA,CAAY,QAAA,EAAU,OAAA,EAAS,OAAO,CAAA;AAAA,EAC9C;AACF","file":"chunk-EEK7S77K.js","sourcesContent":["/**\n * POSIX shell escaping for values interpolated into a `SandboxBackend.execute`\n * command string. `execute` runs via `/bin/sh -c`, so any untrusted value\n * (repo URL, ref, path) MUST be quoted to prevent command injection.\n *\n * @internal\n */\n\n/** Wrap `arg` in single quotes, escaping embedded single quotes (`'\\''`). */\nexport function shellEscapePosix(arg: string): string {\n return `'${arg.replace(/'/g, \"'\\\\''\")}'`;\n}\n","/**\n * Sandbox backend protocol — pluggable execution environment for agent tools.\n *\n * Per ADR D1: only 2 abstract methods (`execute` + `uploadFile`). All\n * higher-level operations are derived on the base class. New backends\n * (Docker, Firecracker, E2B) only implement those 2 methods.\n *\n * @public\n */\n\nimport { ConfigurationError, TheokitAgentError } from \"../errors.js\";\nimport type { EnvPolicy } from \"../types/env-policy.js\";\nimport { shellEscapePosix } from \"./shell-escape.js\";\n\n/**\n * What a {@link SandboxBackend} returns for one command.\n *\n * `exitCode` is a coarse signal rather than the child's real exit status: the backends in this\n * package report `0` on success, `124` on timeout, and `1` for everything else — including a command\n * that exited with its own non-zero code. Read `timedOut` to tell a killed command from a failed one,\n * and `stderr` for the reason; branching on a specific exit code will not work here.\n *\n * `stdout` and `stderr` are truncated independently at `SandboxConfig.maxOutputBytes`, with a\n * trailing `...(truncated)` marker. Neither is safe to parse as a complete document without checking\n * for it.\n */\nexport interface ExecuteResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n timedOut: boolean;\n}\n\n/**\n * Construction-time settings shared by every {@link SandboxBackend}. All fields are optional and the\n * base constructor fills them in, so `{}` is a valid config: `workDir` `/tmp`, `timeoutMs` 30000,\n * `maxOutputBytes` 5 MiB, `env` `\"inherit-scrubbed\"`.\n *\n * `workDir` is the child process's cwd and the base a relative `uploadFile` path resolves against. It\n * is not a boundary — under `LocalSandbox` nothing stops a command, or an absolute path, from leaving\n * it. Only `LinuxSandbox` makes it enforceable.\n *\n * `timeoutMs` is the default for every call; `execute(command, { timeoutMs })` overrides it per\n * command. On expiry the child is killed and the result carries `timedOut: true` with `exitCode`\n * 124 — the partial output collected so far is still returned.\n */\nexport interface SandboxConfig {\n workDir?: string;\n timeoutMs?: number;\n maxOutputBytes?: number;\n /**\n * #54 — env inherit/scrub policy for the executed command's child process.\n * Defaults to `\"inherit-scrubbed\"` (drop secret-like vars: `*KEY*`, `*SECRET*`,\n * `*TOKEN*`, `*PASSWORD*`, `*_AUTH*`). Pass `\"all\"` to restore full inheritance\n * or `\"core\"` for a minimal safe allowlist.\n */\n env?: EnvPolicy;\n}\n\n/**\n * A backend refused a command on policy grounds — the environment works, and it said no. Carries a\n * stable `code: \"sandbox_security\"` for callers that prefer not to match on the class.\n *\n * Nothing in this package throws it, which is worth knowing before you write a `catch` for it:\n * `LocalSandbox` and `LinuxSandbox` report a refusal through {@link ExecuteResult} (non-zero\n * `exitCode`, reason on `stderr`), and a write blocked under confinement surfaces as a plain `Error`\n * from `uploadFile`. This type exists so a custom backend that must reject a command BEFORE spawning\n * anything — a container or VM runner enforcing its own policy — can do so in the protocol's\n * vocabulary instead of inventing an error of its own.\n */\nexport class SandboxSecurityError extends TheokitAgentError {\n override readonly name = \"SandboxSecurityError\";\n override readonly code = \"sandbox_security\" as const;\n constructor(message: string) {\n // not retryable: a refused command is refused every time; retrying re-asks the same question\n super(message, { code: \"sandbox_security\", isRetryable: false });\n }\n}\n\n/**\n * A backend cannot be used at all: its runtime is missing or unusable. The distinction from\n * {@link SandboxSecurityError} is which side failed — there the sandbox worked and denied the\n * command, here there is no sandbox. Carries `code: \"sandbox_not_available\"`.\n *\n * Nothing in this package throws it either, and that is a position rather than an oversight:\n * `createSandboxBackend` treats a missing bubblewrap as a degradation, warns once, and hands back an\n * unconfined `LocalSandbox`. Throw this instead from a backend that must never silently run outside\n * its isolation.\n */\nexport class SandboxNotAvailableError extends TheokitAgentError {\n override readonly name = \"SandboxNotAvailableError\";\n override readonly code = \"sandbox_not_available\" as const;\n constructor(message: string) {\n // not retryable: a missing runtime does not appear on a second attempt\n super(message, { code: \"sandbox_not_available\", isRetryable: false });\n }\n}\n\n/**\n * The execution capability handed to an agent tool, and the extension point for new environments.\n *\n * A backend implements exactly two methods, `execute` and `uploadFile`. Everything else here —\n * `readFile`, `glob`, `grep`, `listDir` — is derived from `execute` by shelling out `cat`, `find`,\n * `grep` and `ls`, so a subclass that overrides `execute` alone inherits confined reads, searches and\n * listings for free. It does not inherit confined writes: `writeFile` delegates to `uploadFile`, and\n * that is the second override `LinuxSandbox` needs.\n *\n * Choosing one: `LocalSandbox` runs the command on the host with no isolation and suits code you\n * already trust; `LinuxSandbox` adds kernel confinement where bubblewrap is available;\n * `createSandboxBackend` probes and picks between them, and is the right entry point unless you have\n * a reason to pin one. For genuinely untrusted code you want a container or VM backend, which this\n * package does not ship — write it against these two methods.\n *\n * Because the derived helpers assemble shell command lines (arguments escaped for POSIX `sh`), a\n * backend whose `execute` is not a POSIX shell must override them as well.\n */\nexport abstract class SandboxBackend {\n protected config: SandboxConfig;\n\n constructor(config: SandboxConfig = {}) {\n this.config = {\n workDir: config.workDir ?? \"/tmp\",\n timeoutMs: config.timeoutMs ?? 30_000,\n maxOutputBytes: config.maxOutputBytes ?? 5 * 1024 * 1024,\n // #54 — preserve the env policy so backends can scrub secrets.\n env: config.env ?? \"inherit-scrubbed\",\n };\n }\n\n abstract execute(command: string, opts?: { timeoutMs?: number }): Promise<ExecuteResult>;\n\n abstract uploadFile(path: string, content: string | Buffer): Promise<void>;\n\n async readFile(path: string): Promise<string> {\n const result = await this.execute(`cat ${this.shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`readFile failed: ${result.stderr}`);\n }\n return result.stdout;\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n await this.uploadFile(path, content);\n }\n\n async glob(pattern: string, cwd?: string): Promise<string[]> {\n const dir = cwd ?? this.config.workDir ?? \".\";\n const result = await this.execute(\n `find ${this.shellEscape(dir)} -name ${this.shellEscape(pattern)} -type f 2>/dev/null`,\n );\n this.assertCommandRan(\"glob\", result);\n return result.stdout.trim().split(\"\\n\").filter(Boolean);\n }\n\n async grep(pattern: string, path?: string): Promise<string[]> {\n const target = path ?? \".\";\n const result = await this.execute(\n `grep -rn ${this.shellEscape(pattern)} ${this.shellEscape(target)} 2>/dev/null`,\n );\n // `grep` exits 1 for NO MATCH and >= 2 for an error, so a 1 is an answer and is not asserted on.\n if (result.exitCode !== 1) this.assertCommandRan(\"grep\", result);\n return result.stdout.trim().split(\"\\n\").filter(Boolean);\n }\n\n async listDir(path: string): Promise<string[]> {\n const result = await this.execute(`ls -1 ${this.shellEscape(path)}`);\n this.assertCommandRan(\"listDir\", result);\n return result.stdout.trim().split(\"\\n\").filter(Boolean);\n }\n\n /**\n * Turns \"the command did not run\" into an error instead of an empty array.\n *\n * `glob`, `grep` and `listDir` used to `return []` on any non-zero exit, so a search that could not\n * run reported the same thing as a search that found nothing — opposite facts, one normal and one\n * meaning the agent is looking at a filesystem it cannot read. That is the failure mode a backend\n * whose `execute` is not a POSIX shell hits, which this class's own docblock warns about in prose\n * and could not enforce.\n *\n * A genuine no-match is still `[]`: `find` exits 0 with empty output, and `grep`'s exit 1 is\n * checked by its caller before this is reached.\n */\n private assertCommandRan(operation: string, result: ExecuteResult): void {\n if (result.exitCode === 0) return;\n throw new ConfigurationError(\n `${operation} failed (exit ${String(result.exitCode)}): ${result.stderr.trim() || \"no stderr\"}. ` +\n `The derived helpers shell out to POSIX \\`cat\\`/\\`find\\`/\\`grep\\`/\\`ls\\` — a backend whose ` +\n `execute() is not a POSIX shell must override them.`,\n { code: \"sandbox_derived_helper_failed\" },\n );\n }\n\n protected truncateOutput(output: string): string {\n const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;\n if (Buffer.byteLength(output) > max) {\n return `${output.slice(0, max)}\\n...(truncated)`;\n }\n return output;\n }\n\n private shellEscape(arg: string): string {\n return shellEscapePosix(arg);\n }\n}\n\n/**\n * A backend OR a per-request resolver of one — mirrors `FilesystemProvider` / `InteractiveProvider`.\n * A resolver runs at tool-execution time (request scope), so a multi-tenant / multi-role agent gets a\n * distinct sandbox per request without a shared mutable one. This is how a tool takes execution as an\n * INJECTED capability: the same tool runs on a local sandbox, a container/E2B backend (cluster/web), or\n * any future backend, with no direct `child_process` import.\n *\n * @public\n */\nexport type SandboxProvider<Ctx = unknown> =\n | SandboxBackend\n | ((ctx: Ctx) => SandboxBackend | Promise<SandboxBackend>);\n\n/** Resolve a {@link SandboxProvider} to a concrete backend for `ctx`. */\nexport async function resolveSandbox<Ctx>(\n provider: SandboxProvider<Ctx>,\n ctx: Ctx,\n): Promise<SandboxBackend> {\n return provider instanceof SandboxBackend ? provider : provider(ctx);\n}\n","/**\n * LocalSandbox — subprocess-based execution. **This is NOT an isolation\n * boundary.** It runs the command via `/bin/sh -c` in the SAME OS as the host\n * with the host's filesystem and network fully reachable — it provides NO\n * process, filesystem, or network isolation. Its only safety affordances are:\n * - a wall-clock timeout (kills a runaway command),\n * - an output-size cap (bounds memory), and\n * - env scrubbing (#54): secret-like parent env vars (`*KEY*`/`*SECRET*`/\n * `*TOKEN*`/`*PASSWORD*`/`*_AUTH*`) are dropped from the child by default\n * (`SandboxConfig.env`), so a shell tool cannot exfiltrate host secrets via\n * the environment.\n *\n * For real isolation (untrusted code), use a container/VM backend — NOT this.\n *\n * @public\n */\n\nimport { execFile } from \"node:child_process\";\nimport { writeFile as fsWriteFile, mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport { resolveChildEnv } from \"../internal/runtime/lifecycle/env-policy.js\";\nimport { type ExecuteResult, SandboxBackend, type SandboxConfig } from \"./types.js\";\n\n/**\n * Runs a command with `/bin/sh -c` on the host. NOT an isolation boundary — the\n * module note above states exactly what it does and does not protect.\n *\n * const sandbox = new LocalSandbox({ workDir: \"/srv/repo\", timeoutMs: 10_000 });\n * const { stdout, exitCode, timedOut } = await sandbox.execute(\"ls -1\");\n *\n * Needs a POSIX host with `/bin/sh`. Every helper inherited from\n * {@link SandboxBackend} — `readFile`, `glob`, `grep`, `listDir` — is built on\n * this `execute`, so they inherit that requirement too.\n *\n * How it fails: `execute` NEVER rejects. Every outcome, including a failure to\n * spawn, comes back as an {@link ExecuteResult}; read `timedOut` first\n * (`true` implies `exitCode` 124) and `stderr` for the reason. `uploadFile` DOES\n * reject, with the raw `node:fs` error, on a bad path or missing permission.\n *\n * Traps:\n * - `exitCode` is not the child's exit code. It is 0, 124 (timed out) or 1 — a\n * command that exits 3 is reported as 1, so branching on a specific code does\n * not work here.\n * - Output beyond `maxOutputBytes` (default 5 MiB) makes Node kill the child.\n * The result is `exitCode: 1` and `timedOut: false`, with the cut stream\n * carrying the `...(truncated)` marker described on `ExecuteResult` (#363).\n * Since `exitCode` is 1 either way, that marker is what tells a lost-output\n * result from a command that genuinely failed.\n * - `uploadFile` resolves a relative path against `workDir` but does not contain\n * it: an absolute path, or one containing `..`, writes wherever the process\n * can. `workDir` is a starting directory, not a jail.\n * - Secret-like parent env vars are dropped by default. Passing\n * `env: \"all\"` in {@link SandboxConfig} puts the host's API keys back within\n * reach of any command the agent runs.\n */\nexport class LocalSandbox extends SandboxBackend {\n constructor(config: SandboxConfig = {}) {\n super(config);\n }\n\n async execute(command: string, opts?: { timeoutMs?: number }): Promise<ExecuteResult> {\n const timeout = opts?.timeoutMs ?? this.config.timeoutMs ?? 30_000;\n const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;\n\n return new Promise<ExecuteResult>((resolve) => {\n const child = execFile(\n \"/bin/sh\",\n [\"-c\", command],\n {\n cwd: this.config.workDir,\n timeout,\n maxBuffer: max,\n encoding: \"utf-8\",\n // #54 — scrub secret-like host env vars from the child by default.\n env: resolveChildEnv({ policy: this.config.env }),\n },\n (error, stdout, stderr) => {\n resolve(this.buildResult(error, stdout ?? \"\", stderr ?? \"\"));\n },\n );\n\n // Safety: if child somehow doesn't callback\n child.on(\"error\", () => {\n resolve({ stdout: \"\", stderr: \"spawn error\", exitCode: 1, timedOut: false });\n });\n });\n }\n\n private buildResult(error: Error | null, stdout: string, stderr: string): ExecuteResult {\n const timedOut = error !== null && \"killed\" in error && (error as { killed: boolean }).killed;\n // #363 — the ONLY reliable signal that output was lost. Node caps the buffer AT `maxBuffer`, so\n // for ASCII output the string comes back exactly at the cap and `truncateOutput`'s `> max` test\n // never fires; a length comparison cannot tell a cut document from a complete one that happens\n // to be that long. The child being killed for overflow can.\n const overflowed =\n error !== null && (error as { code?: unknown }).code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\";\n return {\n stdout: this.markIfCut(this.truncateOutput(stdout), overflowed),\n stderr: this.markIfCut(this.truncateOutput(stderr), overflowed),\n exitCode: timedOut ? 124 : error ? 1 : 0,\n timedOut,\n };\n }\n\n /**\n * Append the `...(truncated)` marker `ExecuteResult` tells callers to branch on, when the child\n * was killed for exceeding `maxOutputBytes` and this stream is the one sitting at the cap.\n *\n * `truncateOutput` has already run, so an output it marked is left alone rather than marked\n * twice. Node does not say WHICH stream overflowed, so the stream at the cap is the one that\n * lost data — the other, being shorter, is complete.\n */\n private markIfCut(output: string, overflowed: boolean): string {\n if (!overflowed) return output;\n if (output.endsWith(\"...(truncated)\")) return output;\n const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;\n return Buffer.byteLength(output) >= max ? `${output}\\n...(truncated)` : output;\n }\n\n async uploadFile(path: string, content: string | Buffer): Promise<void> {\n const fullPath = path.startsWith(\"/\") ? path : `${this.config.workDir}/${path}`;\n await mkdir(dirname(fullPath), { recursive: true });\n await fsWriteFile(fullPath, content, \"utf-8\");\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/internal/structured-output-helpers.ts"],"names":["createRequire","ConfigurationError","toJsonSchema"],"mappings":"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","file":"chunk-FEAWEBWN.cjs","sourcesContent":["import { createRequire } from \"node:module\";\nimport type { z as ZodNamespace, ZodType } from \"zod\";\nimport { ConfigurationError } from \"../errors.js\";\nimport type { AgentOptions, CustomTool, LocalOptions, ModelSelection } from \"../types/agent.js\";\nimport type { ProviderRoutingSettings } from \"../types/providers.js\";\nimport { toJsonSchema } from \"./zod-to-json-schema.js\";\n\n/**\n * Shared helpers for `Agent.generateObject` (ADR D33) and\n * `Agent.streamObject` (ADR D39). Both build a transient agent with a\n * single synthetic `output` tool whose handler captures the model's\n * structured response.\n *\n * Extracted from inline duplicates to keep jscpd quiet AND to keep the\n * two public APIs in lockstep.\n *\n * @internal\n */\n\nlet cachedZ: typeof ZodNamespace | undefined;\n\n/**\n * Load Zod via createRequire (it's an optional peer dep). Throws a typed\n * ConfigurationError if Zod isn't installed.\n */\nexport function requireZod(): typeof ZodNamespace {\n if (cachedZ !== undefined) return cachedZ;\n const r = createRequire(import.meta.url);\n let mod: { z?: typeof ZodNamespace } & typeof ZodNamespace;\n try {\n mod = r(\"zod\") as typeof mod;\n } catch (cause) {\n throw new ConfigurationError(\n \"Structured output requires the optional peer dependency `zod`. \" +\n 'Add `\"zod\": \"^3.25.0 || ^4.0.0\"` to your package.json and reinstall.',\n { code: \"zod_not_installed\", cause },\n );\n }\n cachedZ = (mod.z ?? mod) as typeof ZodNamespace;\n return cachedZ;\n}\n\n/**\n * Build the synthetic `output` tool used by both `generateObject` and\n * `streamObject`. The handler captures the raw input on first call only\n * (EC-D10 / EC-6: parallel tool use in Claude 3.5+ may invoke `output`\n * twice; later calls are ignored).\n */\nexport function makeOutputTool(\n jsonSchema: Record<string, unknown>,\n onCapture: (input: unknown) => string | Promise<string> | undefined,\n): CustomTool {\n return {\n name: \"output\",\n description: \"Call this tool with your final structured answer. Match the JSON schema exactly.\",\n inputSchema: jsonSchema,\n handler: (input) => {\n const out = onCapture(input);\n // Some callers throw a sentinel (generate-object) and never return.\n // Others return a string (stream-object). Anything else → empty string.\n if (typeof out === \"string\") return out;\n if (out instanceof Promise) return out;\n return \"\";\n },\n };\n}\n\n/**\n * Assemble the AgentOptions for the transient agent. Shared shape:\n * model + local + tools[output] + systemPrompt + apiKey.\n */\nexport function buildTransientAgentOptions(params: {\n // SE8 — accepts the bare-string shorthand; forwarded to AgentOptions.model\n // (normalized at Agent.create).\n model: string | ModelSelection;\n local: LocalOptions;\n outputTool: CustomTool;\n systemPrompt?: string;\n apiKey?: string;\n providers?: ProviderRoutingSettings;\n}): AgentOptions {\n return {\n model: params.model,\n local: params.local,\n tools: [params.outputTool],\n systemPrompt:\n params.systemPrompt ??\n \"You produce structured output by calling the `output` tool exactly once. Match the JSON schema.\",\n ...(params.apiKey !== undefined ? { apiKey: params.apiKey } : {}),\n ...(params.providers !== undefined ? { providers: params.providers } : {}),\n };\n}\n\n/**\n * Best-effort extraction of token usage from a run result. Local runtimes\n * may not expose it; default to zeros.\n */\nexport function extractUsage(result: unknown): { inputTokens: number; outputTokens: number } {\n const u = (result as { usage?: { inputTokens?: number; outputTokens?: number } }).usage;\n if (u === undefined) return { inputTokens: 0, outputTokens: 0 };\n return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };\n}\n\n/**\n * Build the user-message prompt that instructs the model to call the\n * `output` tool with a schema-matched structured answer.\n */\nexport function buildToolPrompt(prompt: string): string {\n return `${prompt}\\n\\nRespond by calling the \\`output\\` tool with the structured answer that matches the schema.`;\n}\n\n/**\n * One-shot setup shared by both `generateObject` and `streamObject`. Loads\n * Zod, computes the JSON schema, primes the captured-raw / usage / retry\n * state. Returns the values needed by the caller's loop.\n */\nexport function setupStructuredOutput<T extends ZodType>(\n schema: T,\n maxRetries: number | undefined,\n) {\n const z = requireZod();\n // Universal Zod 3+4 conversion (feature-detects native v4, falls back to lib on v3).\n const jsonSchema = toJsonSchema(schema, { unrepresentable: \"any\" });\n return {\n z,\n jsonSchema,\n maxRetries: maxRetries ?? 1,\n initialUsage: { inputTokens: 0, outputTokens: 0 },\n };\n}\n\n/**\n * Cleanup the transient agent after generateObject/streamObject finish.\n * Disposes AND hard-deletes from the registry so the count stays stable.\n *\n * @internal\n */\nexport async function disposeAndDeleteTransient(\n agent: { dispose: () => Promise<void>; agentId: string },\n deletor: (agentId: string) => Promise<void>,\n): Promise<void> {\n await agent.dispose();\n try {\n await deletor(agent.agentId);\n } catch {\n // Best-effort cleanup.\n }\n}\n\n/**\n * The three failure messages, verbatim from what both entry points already emit.\n *\n * Identical strings in two files is how two APIs start describing the same failure differently: the\n * first person to improve one of them improves half the product.\n *\n * @internal\n */\nexport const STRUCTURED_OUTPUT_MESSAGES = {\n runFailed: (message: string | undefined, code: string | undefined): string =>\n `Agent run failed before the model could reply: ${message ?? \"unknown error\"} [${code ?? \"?\"}]`,\n noToolCall: \"The model returned text instead of calling the `output` tool.\",\n parseFailed: \"Schema parse failed after all retries.\",\n} as const;\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/stream-object.ts"],"names":["StructuredOutputError","setupStructuredOutput","makeOutputTool","buildTransientAgentOptions","buildToolPrompt","extractUsage","STRUCTURED_OUTPUT_MESSAGES","disposeAndDeleteTransient"],"mappings":"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","file":"chunk-HN4IKB6X.cjs","sourcesContent":["import type { z as ZodNamespace, ZodType } from \"zod\";\nimport { StructuredOutputError } from \"./errors.js\";\nimport {\n buildToolPrompt,\n buildTransientAgentOptions,\n disposeAndDeleteTransient,\n extractUsage,\n makeOutputTool,\n STRUCTURED_OUTPUT_MESSAGES,\n setupStructuredOutput,\n} from \"./internal/structured-output-helpers.js\";\nimport type { AgentOptions, LocalOptions, ModelSelection, SDKAgent } from \"./types/agent.js\";\nimport type { ProviderRoutingSettings } from \"./types/providers.js\";\n\n/**\n * Options accepted by {@link Agent.streamObject}. Same shape as\n * `Agent.generateObject` with the addition that the result is an\n * `AsyncIterator<StreamObjectEvent<T>>` rather than a single Promise. See ADR D39.\n *\n * @public\n */\nexport interface StreamObjectOptions<T extends ZodType> {\n schema: T;\n prompt: string;\n systemPrompt?: string;\n /** SE8 — accepts a bare-string id shorthand or a {@link ModelSelection}. */\n model: string | ModelSelection;\n apiKey?: string;\n local: LocalOptions;\n maxRetries?: number;\n /**\n * Optional provider routing forwarded to the transient agent. Required when\n * `model.id` uses a prefix (e.g. `openai/gpt-4o-mini`) but the credential is\n * for a unified gateway (e.g. OpenRouter). Without this, the SDK infers\n * provider from the prefix and may fail with `provider_unresolved` even\n * when the right env key is set under a different provider name.\n */\n providers?: ProviderRoutingSettings;\n}\n\n/**\n * Recursive partial — `T` where every nested field becomes optional.\n *\n * @public\n */\nexport type DeepPartial<T> = T extends (infer U)[]\n ? Array<DeepPartial<U>>\n : T extends object\n ? { [K in keyof T]?: DeepPartial<T[K]> }\n : T;\n\n/**\n * Event emitted by {@link Agent.streamObject}. Discriminate on `type`.\n *\n * - `partial` events fire zero or more times with monotonically increasing\n * `attempt`, carrying best-effort schema-parsed snapshots of the model's\n * accumulating output.\n * - `complete` fires exactly once at the end, carrying the fully Zod-parsed\n * object alongside usage and finishReason — semantically identical to a\n * successful `Agent.generateObject()` return.\n *\n * @public\n */\nexport type StreamObjectEvent<T> =\n | { type: \"partial\"; partial: DeepPartial<T>; attempt: number }\n | {\n type: \"complete\";\n object: T;\n raw: unknown;\n usage: { inputTokens: number; outputTokens: number };\n finishReason: \"tool_use\" | \"error\";\n };\n\n/**\n * Error thrown by {@link Agent.streamObject} when the model refuses to call\n * the synthetic `output` tool or when all retries fail to produce a\n * schema-valid object. Same code taxonomy as `GenerateObjectError`.\n *\n * @public\n */\nexport class StreamObjectError extends StructuredOutputError {\n override readonly name = \"StreamObjectError\";\n}\n\ninterface StreamObjectDeps {\n create: (options: AgentOptions) => Promise<SDKAgent>;\n delete: (agentId: string) => Promise<void>;\n}\n\n/**\n * Implementation of `Agent.streamObject` as an async generator. Mirrors the\n * synthetic-forced-tool pattern from `generate-object.ts` (ADR D33) with the\n * addition of intermediate `partial` events emitted from incremental parsing\n * of accumulating text deltas during the agent loop.\n *\n * REACHED BY DYNAMIC IMPORT — do not delete on a dead-code report (B-140).\n * `agent.ts` loads this module lazily to keep it off the eager path:\n *\n * streamObjectImport ??= import(\"./stream-object.js\");\n * const { streamObjectImpl } = await streamObjectImport;\n *\n * `knip` resolves imports statically and does not follow a destructure off a\n * dynamic-import promise, so it reports this export as unused on every run. It\n * is not: removing it breaks `Agent.streamObject`. The `@knipignore` tag below\n * silences that one false positive — a tool limitation, not a suppression of a\n * real finding, and the difference is the whole reason this comment exists.\n *\n * The tag replaced a whole-file entry in `knip.json`'s ignore list, which also\n * excluded the four other exports in this file from dead-code analysis. The tag\n * is scoped to the symbol knip actually cannot resolve, so the rest of the file\n * is examined again.\n *\n * @knipignore reached only via `await import()` in agent.ts; knip cannot follow it\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: streaming loop interleaves text-delta accumulation, partial-parse attempts, retries, and final dispose — splitting harms locality of the iterator contract.\nexport async function* streamObjectImpl<T extends ZodType>(\n options: StreamObjectOptions<T>,\n deps: StreamObjectDeps,\n): AsyncGenerator<StreamObjectEvent<ZodNamespace.infer<T>>, void, void> {\n const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(\n options.schema,\n options.maxRetries,\n );\n let capturedRaw: unknown;\n let lastUsage = initialUsage;\n\n const outputTool = makeOutputTool(jsonSchema, (input) => {\n // EC-6: first capture wins (parallel tool use in Claude 3.5+).\n if (capturedRaw === undefined) {\n capturedRaw = input;\n }\n return JSON.stringify({ ok: true });\n });\n\n const agentOptions: AgentOptions = buildTransientAgentOptions({\n model: options.model,\n local: options.local,\n outputTool,\n ...(options.systemPrompt !== undefined ? { systemPrompt: options.systemPrompt } : {}),\n ...(options.apiKey !== undefined ? { apiKey: options.apiKey } : {}),\n ...(options.providers !== undefined ? { providers: options.providers } : {}),\n });\n const agent = await deps.create(agentOptions);\n const userMessage = buildToolPrompt(options.prompt);\n\n try {\n let lastParseError: unknown;\n let attemptCounter = 0;\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n capturedRaw = undefined;\n const run = await agent.send(userMessage);\n\n // Buffer text deltas during streaming; try partial-parse on each.\n let textBuffer = \"\";\n for await (const msg of run.stream()) {\n if (msg.type === \"assistant\") {\n const newText = msg.message.content\n .filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n .map((c) => c.text)\n .join(\"\");\n if (newText.length > 0) {\n textBuffer += newText;\n const partial = bestEffortPartialParse(textBuffer, options.schema);\n if (partial !== undefined) {\n attemptCounter += 1;\n yield {\n type: \"partial\",\n partial: partial as DeepPartial<ZodNamespace.infer<T>>,\n attempt: attemptCounter,\n };\n }\n }\n }\n }\n const result = await run.wait();\n lastUsage = extractUsage(result);\n\n if (capturedRaw === undefined) {\n // EC: when the underlying run errored (e.g. provider_unresolved),\n // surface the original cause instead of the misleading \"model\n // returned text\" message — there was no model call at all.\n if (result.status === \"error\" && result.error !== undefined) {\n throw new StreamObjectError(\n \"no_tool_call\",\n STRUCTURED_OUTPUT_MESSAGES.runFailed(result.error.message, result.error.code),\n result.error,\n );\n }\n if (attempt === maxRetries) {\n throw new StreamObjectError(\"no_tool_call\", STRUCTURED_OUTPUT_MESSAGES.noToolCall);\n }\n continue;\n }\n\n const parsed = options.schema.safeParse(capturedRaw);\n if (parsed.success) {\n yield {\n type: \"complete\",\n object: parsed.data,\n raw: capturedRaw,\n usage: lastUsage,\n finishReason: \"tool_use\",\n };\n return;\n }\n lastParseError = parsed.error;\n }\n\n throw new StreamObjectError(\n \"parse_failed\",\n STRUCTURED_OUTPUT_MESSAGES.parseFailed,\n lastParseError,\n );\n } finally {\n // EC-4: even if consumer calls iter.return() mid-stream, this finally\n // runs — transient agent is disposed AND removed from registry.\n await disposeAndDeleteTransient(agent, deps.delete);\n }\n}\n\n/**\n * Try to extract a partial JSON object from a possibly-incomplete text\n * buffer and parse it via the schema in lenient mode. Returns `undefined`\n * if nothing parseable is found yet.\n *\n * Strategy: find the first `{`, find the LAST balanced `}` (greedy), parse\n * the substring as JSON, then `safeParse` against `schema.partial()` if the\n * schema supports it, else against the original schema.\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: stateful JSON-balancing scanner — string/brace/escape state must be co-located for the parser to remain correct.\nfunction bestEffortPartialParse<T extends ZodType>(text: string, schema: T): unknown | undefined {\n const start = text.indexOf(\"{\");\n if (start < 0) return undefined;\n // Find the longest balanced JSON object from `start`.\n let depth = 0;\n let inString = false;\n let isEscaped = false;\n let end = -1;\n for (let i = start; i < text.length; i += 1) {\n const ch = text[i];\n if (isEscaped) {\n isEscaped = false;\n continue;\n }\n if (ch === \"\\\\\" && inString) {\n isEscaped = true;\n continue;\n }\n if (ch === '\"') {\n inString = !inString;\n continue;\n }\n if (inString) continue;\n if (ch === \"{\") depth += 1;\n else if (ch === \"}\") {\n depth -= 1;\n if (depth === 0) end = i;\n }\n }\n if (end < 0) return undefined;\n const candidate = text.slice(start, end + 1);\n let parsed: unknown;\n try {\n parsed = JSON.parse(candidate);\n } catch {\n return undefined;\n }\n // Try schema.partial() if available (Zod objects support it); else fall\n // back to the original schema (loose match).\n const maybePartial = (schema as unknown as { partial?: () => ZodType }).partial;\n const looseSchema = typeof maybePartial === \"function\" ? maybePartial.call(schema) : schema;\n const result = looseSchema.safeParse(parsed);\n return result.success ? result.data : undefined;\n}\n"]}