tubeless 0.3.0 → 0.3.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 (133) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/agent-identity.d.ts +2 -0
  3. package/dist/agent/agent-identity.js +8 -0
  4. package/dist/agent/agent-identity.js.map +1 -0
  5. package/dist/agent/agent-state.d.ts +1 -0
  6. package/dist/agent/agent-state.js +3 -0
  7. package/dist/agent/agent-state.js.map +1 -1
  8. package/dist/agent/agent-types.d.ts +6 -0
  9. package/dist/agent/agent-types.js.map +1 -1
  10. package/dist/agent/agent.d.ts +3 -0
  11. package/dist/agent/agent.js +2 -0
  12. package/dist/agent/agent.js.map +1 -1
  13. package/dist/agent/checkpoint-calls.d.ts +8 -0
  14. package/dist/agent/checkpoint-calls.js +46 -0
  15. package/dist/agent/checkpoint-calls.js.map +1 -0
  16. package/dist/agent/checkpoint-codec.d.ts +3 -0
  17. package/dist/agent/checkpoint-codec.js +108 -0
  18. package/dist/agent/checkpoint-codec.js.map +1 -0
  19. package/dist/agent/checkpoint-format.d.ts +80 -0
  20. package/dist/agent/checkpoint-format.js +116 -0
  21. package/dist/agent/checkpoint-format.js.map +1 -0
  22. package/dist/agent/checkpoint-key.d.ts +1 -0
  23. package/dist/agent/checkpoint-key.js +6 -0
  24. package/dist/agent/checkpoint-key.js.map +1 -0
  25. package/dist/agent/checkpoint-session.d.ts +38 -0
  26. package/dist/agent/checkpoint-session.js +226 -0
  27. package/dist/agent/checkpoint-session.js.map +1 -0
  28. package/dist/agent/checkpoint-types.d.ts +31 -0
  29. package/dist/agent/checkpoint-types.js +2 -0
  30. package/dist/agent/checkpoint-types.js.map +1 -0
  31. package/dist/agent/compile-agent.js +11 -10
  32. package/dist/agent/compile-agent.js.map +1 -1
  33. package/dist/agent/decision.d.ts +1 -1
  34. package/dist/agent/decision.js +2 -2
  35. package/dist/agent/decision.js.map +1 -1
  36. package/dist/agent/default-tools.d.ts +6 -6
  37. package/dist/agent/default-tools.js +12 -9
  38. package/dist/agent/default-tools.js.map +1 -1
  39. package/dist/agent/execution-scope.d.ts +21 -6
  40. package/dist/agent/execution-scope.js +73 -17
  41. package/dist/agent/execution-scope.js.map +1 -1
  42. package/dist/agent/invocation.d.ts +13 -4
  43. package/dist/agent/invocation.js +47 -3
  44. package/dist/agent/invocation.js.map +1 -1
  45. package/dist/agent/memory-checkpoint-store.d.ts +3 -0
  46. package/dist/agent/memory-checkpoint-store.js +37 -0
  47. package/dist/agent/memory-checkpoint-store.js.map +1 -0
  48. package/dist/agent/model-agent.d.ts +4 -0
  49. package/dist/agent/model-agent.js.map +1 -1
  50. package/dist/agent/node.d.ts +2 -0
  51. package/dist/agent/node.js +1 -0
  52. package/dist/agent/node.js.map +1 -1
  53. package/dist/agent/pipeline-tool.d.ts +3 -0
  54. package/dist/agent/pipeline-tool.js +6 -0
  55. package/dist/agent/pipeline-tool.js.map +1 -1
  56. package/dist/agent/sqlite-checkpoint-store.d.ts +8 -0
  57. package/dist/agent/sqlite-checkpoint-store.js +117 -0
  58. package/dist/agent/sqlite-checkpoint-store.js.map +1 -0
  59. package/dist/agent/tools.d.ts +5 -0
  60. package/dist/agent/tools.js +7 -2
  61. package/dist/agent/tools.js.map +1 -1
  62. package/dist/agent/turn.d.ts +2 -9
  63. package/dist/agent/turn.js +64 -16
  64. package/dist/agent/turn.js.map +1 -1
  65. package/dist/core/child-execution.d.ts +4 -0
  66. package/dist/core/child-execution.js +16 -4
  67. package/dist/core/child-execution.js.map +1 -1
  68. package/dist/core/execution-scope.d.ts +11 -1
  69. package/dist/core/execution-scope.js +7 -6
  70. package/dist/core/execution-scope.js.map +1 -1
  71. package/dist/core/iteration.js +2 -0
  72. package/dist/core/iteration.js.map +1 -1
  73. package/dist/core/pipeline-steps.js +2 -2
  74. package/dist/core/pipeline-steps.js.map +1 -1
  75. package/dist/core/prepared-options.d.ts +3 -1
  76. package/dist/core/prepared-options.js +5 -1
  77. package/dist/core/prepared-options.js.map +1 -1
  78. package/dist/run-store/run-history.d.ts +42 -0
  79. package/dist/run-store/run-history.js +213 -0
  80. package/dist/run-store/run-history.js.map +1 -0
  81. package/dist/run-store/run-store-schema.d.ts +7 -0
  82. package/dist/run-store/run-store-schema.js +138 -0
  83. package/dist/run-store/run-store-schema.js.map +1 -0
  84. package/dist/run-store/run-store-sqlite.js +7 -1
  85. package/dist/run-store/run-store-sqlite.js.map +1 -1
  86. package/dist/studio/run-store-ui-api.d.ts +1 -1
  87. package/dist/studio/run-store-ui-api.js +44 -10
  88. package/dist/studio/run-store-ui-api.js.map +1 -1
  89. package/dist/studio/run-store-ui-client-browser.js +2 -2
  90. package/dist/studio/run-store-ui-client-transport.d.ts +11 -9
  91. package/dist/studio/run-store-ui-client-transport.js +54 -216
  92. package/dist/studio/run-store-ui-client-transport.js.map +1 -1
  93. package/dist/studio/run-store-ui-client.d.ts +12 -21
  94. package/dist/studio/run-store-ui-client.js +55 -249
  95. package/dist/studio/run-store-ui-client.js.map +1 -1
  96. package/dist/studio/run-store-ui-data-controller.d.ts +29 -5
  97. package/dist/studio/run-store-ui-data-controller.js +122 -69
  98. package/dist/studio/run-store-ui-data-controller.js.map +1 -1
  99. package/dist/studio/run-store-ui-definitions.d.ts +21 -5
  100. package/dist/studio/run-store-ui-definitions.js +53 -14
  101. package/dist/studio/run-store-ui-definitions.js.map +1 -1
  102. package/dist/studio/run-store-ui-protocol.js +2 -32
  103. package/dist/studio/run-store-ui-protocol.js.map +1 -1
  104. package/dist/studio/run-store-ui-resource.d.ts +8 -0
  105. package/dist/studio/run-store-ui-resource.js +53 -0
  106. package/dist/studio/run-store-ui-resource.js.map +1 -0
  107. package/dist/studio/run-store-ui-schema.d.ts +52 -0
  108. package/dist/studio/run-store-ui-schema.js +132 -0
  109. package/dist/studio/run-store-ui-schema.js.map +1 -0
  110. package/dist/studio/run-store-ui-state.d.ts +6 -3
  111. package/dist/studio/run-store-ui-state.js +97 -4
  112. package/dist/studio/run-store-ui-state.js.map +1 -1
  113. package/dist/tracing/tracing-codec.d.ts +1 -3
  114. package/dist/tracing/tracing-codec.js +1 -5
  115. package/dist/tracing/tracing-codec.js.map +1 -1
  116. package/dist/tracing/tracing-schema.d.ts +139 -56
  117. package/dist/tracing/tracing-schema.js +14 -13
  118. package/dist/tracing/tracing-schema.js.map +1 -1
  119. package/dist/tracing/wire-schema.d.ts +1 -1
  120. package/dist/tracing/wire-schema.js.map +1 -1
  121. package/docs/agent-guide.md +15 -4
  122. package/docs/agents.md +114 -6
  123. package/docs/api-reference.md +44 -35
  124. package/docs/api-report.json +21 -10
  125. package/docs/recipes.md +6 -2
  126. package/docs/studio.md +17 -10
  127. package/examples/agent-durable.ts +82 -0
  128. package/examples/project/tubeless.project.ts +3 -1
  129. package/package.json +1 -1
  130. package/skills/tubeless/SKILL.md +13 -4
  131. package/dist/run-store/run-store-codec.d.ts +0 -6
  132. package/dist/run-store/run-store-codec.js +0 -42
  133. package/dist/run-store/run-store-codec.js.map +0 -1
package/README.md CHANGED
@@ -94,7 +94,7 @@ flags after `--`. Record runs with `--store` or `--trace`, then inspect them wit
94
94
  - Start with a [typed import](./examples/typed-import.ts) or add
95
95
  [dry runs and write gates](./examples/publish-with-gates.ts) to a publishing job.
96
96
  - Build workflows with [child pipelines](./examples/child-pipeline.ts) and [fan-out](./examples/fan-out-progress.ts).
97
- - Run bounded model decisions, default filesystem/shell tools, custom tools, and subagents with [in-process agents](./docs/agents.md).
97
+ - Run bounded model decisions, workspace tools, custom tools, and subagents with [agents](./docs/agents.md), optional durable checkpoints, and local or remote execution environments.
98
98
  - Optional: the [peloton example](./examples/peloton.ts) is a cycling-themed kitchen sink for the live TUI.
99
99
 
100
100
  The [recipe index](./docs/recipes.md) covers validation, retries, tracing, testing,
@@ -0,0 +1,2 @@
1
+ export declare function markAgent(pipeline: object): void;
2
+ export declare function isAgent(pipeline: object): boolean;
@@ -0,0 +1,8 @@
1
+ const agents = new WeakSet();
2
+ export function markAgent(pipeline) {
3
+ agents.add(pipeline);
4
+ }
5
+ export function isAgent(pipeline) {
6
+ return agents.has(pipeline);
7
+ }
8
+ //# sourceMappingURL=agent-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-identity.js","sourceRoot":"","sources":["../../src/agent/agent-identity.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,IAAI,OAAO,EAAU,CAAC;AACrC,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC;AACD,MAAM,UAAU,OAAO,CAAC,QAAgB;IACtC,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC","sourcesContent":["const agents = new WeakSet<object>();\nexport function markAgent(pipeline: object): void {\n agents.add(pipeline);\n}\nexport function isAgent(pipeline: object): boolean {\n return agents.has(pipeline);\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import type { StandardSchemaV1 } from "../core/pipeline-types.js";
2
2
  import type { AgentState } from "./agent-types.js";
3
3
  export declare function agentError(code: string, message: string, cause?: unknown): Error;
4
+ export declare function limit(name: string, bound: number, consumed: number, requested: number, scope: string): never;
4
5
  export declare function ownState<T>(state: T): AgentState<T>;
5
6
  export declare function checkSchema(schema: StandardSchemaV1, label: string): void;
6
7
  export declare function jsonDescriptor(schema: StandardSchemaV1, explicit: Readonly<Record<string, unknown>> | undefined, label: string): Readonly<Record<string, unknown>>;
@@ -2,6 +2,9 @@ import { createHash } from "node:crypto";
2
2
  export function agentError(code, message, cause) {
3
3
  return Object.assign(new Error(message, cause === undefined ? undefined : { cause }), { code });
4
4
  }
5
+ export function limit(name, bound, consumed, requested, scope) {
6
+ throw agentError("TUBELESS_AGENT_LIMIT_REACHED", `Agent ${name}=${bound} exceeded (consumed=${consumed}, requested=${requested}, scope=${scope})`);
7
+ }
5
8
  /** Copy plain data into owned, frozen snapshots; repeated references are copied, cycles fail. */
6
9
  function copy(value, ancestors, json) {
7
10
  if (value === null || typeof value === "string" || typeof value === "boolean")
@@ -1 +1 @@
1
- {"version":3,"file":"agent-state.js","sourceRoot":"","sources":["../../src/agent/agent-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { StandardSchemaV1 } from \"../core/pipeline-types.js\";\nimport type { AgentState } from \"./agent-types.js\";\n\nexport function agentError(code: string, message: string, cause?: unknown): Error {\n return Object.assign(new Error(message, cause === undefined ? undefined : { cause }), { code });\n}\n\n/** Copy plain data into owned, frozen snapshots; repeated references are copied, cycles fail. */\nfunction copy(value: unknown, ancestors: Set<object>, json: boolean): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n if (value === undefined && !json) return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"object\" || value === null) throw new Error(\"Expected finite plain data\");\n if (ancestors.has(value)) throw new Error(\"Cyclic data is not supported\");\n if (\n !Array.isArray(value) &&\n Object.getPrototypeOf(value) !== Object.prototype &&\n Object.getPrototypeOf(value) !== null\n ) {\n throw new Error(\"Expected an array or plain record\");\n }\n ancestors.add(value);\n const result: Record<string, unknown> | unknown[] = Array.isArray(value)\n ? new Array(value.length)\n : {};\n const keys = Reflect.ownKeys(value);\n if (json) keys.sort((a, b) => (String(a) < String(b) ? -1 : String(a) > String(b) ? 1 : 0));\n for (const key of keys) {\n if (Array.isArray(value) && key === \"length\") continue;\n const property = Object.getOwnPropertyDescriptor(value, key)!;\n if (typeof key !== \"string\" || !(\"value\" in property) || !property.enumerable) {\n throw new Error(\"State and descriptors require enumerable data properties\");\n }\n Object.defineProperty(result, key, {\n value: copy(property.value, ancestors, json),\n enumerable: true,\n });\n }\n ancestors.delete(value);\n return Object.freeze(result);\n}\n\nexport function ownState<T>(state: T): AgentState<T> {\n try {\n // SAFETY: copying retains every plain-data value and only adds deep readonly ownership.\n return copy(state, new Set(), false) as AgentState<T>;\n } catch (cause) {\n throw agentError(\n \"TUBELESS_AGENT_INVALID_STATE\",\n \"Agent state must contain finite primitives, arrays, and plain records\",\n cause\n );\n }\n}\n\nexport function checkSchema(schema: StandardSchemaV1, label: string): void {\n if (schema?.[\"~standard\"]?.version !== 1 || typeof schema[\"~standard\"].validate !== \"function\") {\n throw agentError(\n \"TUBELESS_AGENT_INVALID_DEFINITION\",\n `${label} requires a Standard Schema validator`\n );\n }\n}\n\nexport function jsonDescriptor(\n schema: StandardSchemaV1,\n explicit: Readonly<Record<string, unknown>> | undefined,\n label: string\n): Readonly<Record<string, unknown>> {\n checkSchema(schema, label);\n try {\n const descriptor =\n explicit ?? schema[\"~standard\"].jsonSchema?.input({ target: \"draft-2020-12\" });\n if (descriptor === null || typeof descriptor !== \"object\" || Array.isArray(descriptor))\n throw new Error(\"Missing JSON Schema object\");\n // SAFETY: the object guard and plain JSON copy validate the descriptor's representation.\n return copy(descriptor, new Set(), true) as Readonly<Record<string, unknown>>;\n } catch (cause) {\n throw agentError(\n \"TUBELESS_AGENT_INVALID_DEFINITION\",\n `${label} requires a JSON Schema input descriptor or explicit fallback`,\n cause\n );\n }\n}\n\nexport function descriptorFingerprint(descriptor: Readonly<Record<string, unknown>>): string {\n return `sha256:${createHash(\"sha256\").update(JSON.stringify(descriptor)).digest(\"hex\")}`;\n}\n\nexport function checkDescription(description: string): void {\n if (typeof description !== \"string\" || !description.trim() || description.length > 4096)\n throw agentError(\n \"TUBELESS_AGENT_INVALID_DEFINITION\",\n \"Tool description must be nonblank and at most 4096 characters\"\n );\n}\n"]}
1
+ {"version":3,"file":"agent-state.js","sourceRoot":"","sources":["../../src/agent/agent-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { StandardSchemaV1 } from \"../core/pipeline-types.js\";\nimport type { AgentState } from \"./agent-types.js\";\n\nexport function agentError(code: string, message: string, cause?: unknown): Error {\n return Object.assign(new Error(message, cause === undefined ? undefined : { cause }), { code });\n}\n\nexport function limit(\n name: string,\n bound: number,\n consumed: number,\n requested: number,\n scope: string\n): never {\n throw agentError(\n \"TUBELESS_AGENT_LIMIT_REACHED\",\n `Agent ${name}=${bound} exceeded (consumed=${consumed}, requested=${requested}, scope=${scope})`\n );\n}\n\n/** Copy plain data into owned, frozen snapshots; repeated references are copied, cycles fail. */\nfunction copy(value: unknown, ancestors: Set<object>, json: boolean): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n if (value === undefined && !json) return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"object\" || value === null) throw new Error(\"Expected finite plain data\");\n if (ancestors.has(value)) throw new Error(\"Cyclic data is not supported\");\n if (\n !Array.isArray(value) &&\n Object.getPrototypeOf(value) !== Object.prototype &&\n Object.getPrototypeOf(value) !== null\n ) {\n throw new Error(\"Expected an array or plain record\");\n }\n ancestors.add(value);\n const result: Record<string, unknown> | unknown[] = Array.isArray(value)\n ? new Array(value.length)\n : {};\n const keys = Reflect.ownKeys(value);\n if (json) keys.sort((a, b) => (String(a) < String(b) ? -1 : String(a) > String(b) ? 1 : 0));\n for (const key of keys) {\n if (Array.isArray(value) && key === \"length\") continue;\n const property = Object.getOwnPropertyDescriptor(value, key)!;\n if (typeof key !== \"string\" || !(\"value\" in property) || !property.enumerable) {\n throw new Error(\"State and descriptors require enumerable data properties\");\n }\n Object.defineProperty(result, key, {\n value: copy(property.value, ancestors, json),\n enumerable: true,\n });\n }\n ancestors.delete(value);\n return Object.freeze(result);\n}\n\nexport function ownState<T>(state: T): AgentState<T> {\n try {\n // SAFETY: copying retains every plain-data value and only adds deep readonly ownership.\n return copy(state, new Set(), false) as AgentState<T>;\n } catch (cause) {\n throw agentError(\n \"TUBELESS_AGENT_INVALID_STATE\",\n \"Agent state must contain finite primitives, arrays, and plain records\",\n cause\n );\n }\n}\n\nexport function checkSchema(schema: StandardSchemaV1, label: string): void {\n if (schema?.[\"~standard\"]?.version !== 1 || typeof schema[\"~standard\"].validate !== \"function\") {\n throw agentError(\n \"TUBELESS_AGENT_INVALID_DEFINITION\",\n `${label} requires a Standard Schema validator`\n );\n }\n}\n\nexport function jsonDescriptor(\n schema: StandardSchemaV1,\n explicit: Readonly<Record<string, unknown>> | undefined,\n label: string\n): Readonly<Record<string, unknown>> {\n checkSchema(schema, label);\n try {\n const descriptor =\n explicit ?? schema[\"~standard\"].jsonSchema?.input({ target: \"draft-2020-12\" });\n if (descriptor === null || typeof descriptor !== \"object\" || Array.isArray(descriptor))\n throw new Error(\"Missing JSON Schema object\");\n // SAFETY: the object guard and plain JSON copy validate the descriptor's representation.\n return copy(descriptor, new Set(), true) as Readonly<Record<string, unknown>>;\n } catch (cause) {\n throw agentError(\n \"TUBELESS_AGENT_INVALID_DEFINITION\",\n `${label} requires a JSON Schema input descriptor or explicit fallback`,\n cause\n );\n }\n}\n\nexport function descriptorFingerprint(descriptor: Readonly<Record<string, unknown>>): string {\n return `sha256:${createHash(\"sha256\").update(JSON.stringify(descriptor)).digest(\"hex\")}`;\n}\n\nexport function checkDescription(description: string): void {\n if (typeof description !== \"string\" || !description.trim() || description.length > 4096)\n throw agentError(\n \"TUBELESS_AGENT_INVALID_DEFINITION\",\n \"Tool description must be nonblank and at most 4096 characters\"\n );\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import type { PipelineStepContext, StandardSchemaV1 } from "../core/pipeline-types.js";
2
2
  import type { AgentEnvironment, AgentEnvironmentProvider } from "./environment.js";
3
+ import type { AgentDurability, AgentExecutionIdentity } from "./checkpoint-types.js";
3
4
  import type { DefaultAgentTools } from "./default-tools.js";
4
5
  export type Awaitable<T> = T | Promise<T>;
5
6
  export type Input<S extends StandardSchemaV1> = NonNullable<S["~standard"]["types"]>["input"];
@@ -70,10 +71,12 @@ export interface AgentLimits {
70
71
  /** Step services and the workspace capability available to a registered tool. */
71
72
  export interface AgentToolContext extends PipelineStepContext<{}> {
72
73
  readonly environment: AgentEnvironment;
74
+ readonly execution?: AgentExecutionIdentity;
73
75
  }
74
76
  /** Model-facing descriptors and ordinary step services, without executable tools. */
75
77
  export interface AgentDecisionContext<Options extends object> extends PipelineStepContext<Options> {
76
78
  readonly environment: AgentEnvironment;
79
+ readonly execution?: AgentExecutionIdentity;
77
80
  readonly turn: number;
78
81
  readonly stateVersion: number;
79
82
  readonly capabilities: readonly {
@@ -87,6 +90,7 @@ export interface AgentDefinition<Id extends string, Options extends StandardSche
87
90
  readonly id: Id;
88
91
  readonly name?: string;
89
92
  readonly description?: string;
93
+ /** Semantic revision; required when this agent uses or inherits durable recovery. */
90
94
  readonly implementationVersion?: string;
91
95
  readonly inputSchema: Options;
92
96
  readonly resultSchema: Result;
@@ -96,6 +100,8 @@ export interface AgentDefinition<Id extends string, Options extends StandardSche
96
100
  readonly limits?: AgentLimits;
97
101
  /** Workspace capabilities; descendants inherit them unless explicitly replaced. */
98
102
  readonly environment?: AgentEnvironmentProvider;
103
+ /** Acknowledged recovery checkpoints; requires an explicit implementationVersion. */
104
+ readonly durability?: AgentDurability<Output<Options>>;
99
105
  initialState(options: Output<Options>): State;
100
106
  decide(state: AgentState<NoInfer<State>>, context: AgentDecisionContext<Output<Options>>): Awaitable<unknown>;
101
107
  reduce?(state: AgentState<NoInfer<State>>, outcomes: readonly AgentOutcome<Registry>[]): NoInfer<State>;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-types.js","sourceRoot":"","sources":["../../src/agent/agent-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { PipelineStepContext, StandardSchemaV1 } from \"../core/pipeline-types.js\";\nimport type { AgentEnvironment, AgentEnvironmentProvider } from \"./environment.js\";\nimport type { DefaultAgentTools } from \"./default-tools.js\";\n\nexport type Awaitable<T> = T | Promise<T>;\nexport type Input<S extends StandardSchemaV1> = NonNullable<S[\"~standard\"][\"types\"]>[\"input\"];\nexport type Output<S extends StandardSchemaV1> = NonNullable<S[\"~standard\"][\"types\"]>[\"output\"];\n/** Deeply read-only view of the owned plain-data state supplied to agent callbacks. */\nexport type AgentState<T> = { readonly [K in keyof T]: AgentState<T[K]> };\ndeclare const capabilityTypes: unique symbol;\n\n/** Opaque capability created by defineTool or pipelineTool; model decisions contain data only. */\nexport interface AgentTool<Arguments, Result> {\n readonly [capabilityTypes]: { readonly input: Arguments; readonly output: Result };\n}\n\nexport type Tools = Readonly<Record<string, AgentTool<unknown, unknown>>>;\ntype RegisteredTools<Custom extends Tools> = Omit<DefaultAgentTools, keyof Custom> & Custom;\n\ntype ToolCall<Registry extends Tools> = {\n [Name in keyof Registry & string]: {\n readonly id: string;\n readonly tool: Name;\n readonly input: Registry[Name][typeof capabilityTypes][\"input\"];\n };\n}[keyof Registry & string];\n\n/** One built-in or custom call with raw model arguments; custom names replace defaults. */\nexport type AgentCall<Registry extends Tools = {}> = ToolCall<RegisteredTools<Registry>>;\n\ntype ToolOutcome<Registry extends Tools> = {\n [Name in keyof Registry & string]: {\n readonly id: string;\n readonly tool: Name;\n } & (\n | {\n readonly ok: true;\n readonly value: Registry[Name][typeof capabilityTypes][\"output\"];\n }\n | { readonly ok: false; readonly error: { readonly code: string; readonly message: string } }\n );\n}[keyof Registry & string];\n\n/** Input-order result or deliberately recoverable handler failure, including default tools. */\nexport type AgentOutcome<Registry extends Tools = {}> = ToolOutcome<RegisteredTools<Registry>>;\n\n/** A nonempty batch of independent calls, or the raw input to the final-result schema. */\nexport type AgentDecision<Registry extends Tools, Result> =\n | {\n readonly kind: \"continue\";\n readonly calls: readonly [AgentCall<Registry>, ...AgentCall<Registry>[]];\n readonly result?: never;\n }\n | { readonly kind: \"finish\"; readonly result: Result; readonly calls?: never };\n\n/** Finite limits for this agent and its descendants; child limits may only tighten them. */\nexport interface AgentLimits {\n /** Decision callbacks, including finish. Defaults to 20. */\n readonly maxTurns?: number;\n /** Admitted subtree calls, including calls stopped before dispatch. Defaults to 100. */\n readonly maxCalls?: number;\n /** Subtree decision callback admissions. Defaults to 100; provider retries are application-owned. */\n readonly maxDecisions?: number;\n /** Pipeline-tool delegation edges below this agent. Defaults to 4; zero allows leaf tools only. */\n readonly maxDepth?: number;\n /** Active decision callbacks and leaf handlers across the subtree. Defaults to 1. */\n readonly maxConcurrency?: number;\n}\n\n/** Step services and the workspace capability available to a registered tool. */\nexport interface AgentToolContext extends PipelineStepContext<{}> {\n readonly environment: AgentEnvironment;\n}\n\n/** Model-facing descriptors and ordinary step services, without executable tools. */\nexport interface AgentDecisionContext<Options extends object> extends PipelineStepContext<Options> {\n readonly environment: AgentEnvironment;\n readonly turn: number;\n readonly stateVersion: number;\n readonly capabilities: readonly {\n readonly name: string;\n readonly description: string;\n readonly inputJsonSchema: Readonly<Record<string, unknown>>;\n }[];\n readonly resultJsonSchema: Readonly<Record<string, unknown>>;\n}\n\nexport interface AgentDefinition<\n Id extends string,\n Options extends StandardSchemaV1<object, object>,\n Result extends StandardSchemaV1,\n State,\n Registry extends Tools,\n> {\n readonly id: Id;\n readonly name?: string;\n readonly description?: string;\n readonly implementationVersion?: string;\n readonly inputSchema: Options;\n readonly resultSchema: Result;\n readonly resultJsonSchema?: Readonly<Record<string, unknown>>;\n /** Extend the standard tools; a custom tool with the same name replaces that default. */\n readonly tools?: Registry;\n readonly limits?: AgentLimits;\n /** Workspace capabilities; descendants inherit them unless explicitly replaced. */\n readonly environment?: AgentEnvironmentProvider;\n initialState(options: Output<Options>): State;\n decide(\n state: AgentState<NoInfer<State>>,\n context: AgentDecisionContext<Output<Options>>\n ): Awaitable<unknown>;\n reduce?(\n state: AgentState<NoInfer<State>>,\n outcomes: readonly AgentOutcome<Registry>[]\n ): NoInfer<State>;\n dryRun?(\n state: AgentState<NoInfer<State>>,\n context: AgentDecisionContext<Output<Options>>\n ): Awaitable<unknown>;\n}\n"]}
1
+ {"version":3,"file":"agent-types.js","sourceRoot":"","sources":["../../src/agent/agent-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { PipelineStepContext, StandardSchemaV1 } from \"../core/pipeline-types.js\";\nimport type { AgentEnvironment, AgentEnvironmentProvider } from \"./environment.js\";\nimport type { AgentDurability, AgentExecutionIdentity } from \"./checkpoint-types.js\";\nimport type { DefaultAgentTools } from \"./default-tools.js\";\n\nexport type Awaitable<T> = T | Promise<T>;\nexport type Input<S extends StandardSchemaV1> = NonNullable<S[\"~standard\"][\"types\"]>[\"input\"];\nexport type Output<S extends StandardSchemaV1> = NonNullable<S[\"~standard\"][\"types\"]>[\"output\"];\n/** Deeply read-only view of the owned plain-data state supplied to agent callbacks. */\nexport type AgentState<T> = { readonly [K in keyof T]: AgentState<T[K]> };\ndeclare const capabilityTypes: unique symbol;\n\n/** Opaque capability created by defineTool or pipelineTool; model decisions contain data only. */\nexport interface AgentTool<Arguments, Result> {\n readonly [capabilityTypes]: { readonly input: Arguments; readonly output: Result };\n}\n\nexport type Tools = Readonly<Record<string, AgentTool<unknown, unknown>>>;\ntype RegisteredTools<Custom extends Tools> = Omit<DefaultAgentTools, keyof Custom> & Custom;\n\ntype ToolCall<Registry extends Tools> = {\n [Name in keyof Registry & string]: {\n readonly id: string;\n readonly tool: Name;\n readonly input: Registry[Name][typeof capabilityTypes][\"input\"];\n };\n}[keyof Registry & string];\n\n/** One built-in or custom call with raw model arguments; custom names replace defaults. */\nexport type AgentCall<Registry extends Tools = {}> = ToolCall<RegisteredTools<Registry>>;\n\ntype ToolOutcome<Registry extends Tools> = {\n [Name in keyof Registry & string]: {\n readonly id: string;\n readonly tool: Name;\n } & (\n | {\n readonly ok: true;\n readonly value: Registry[Name][typeof capabilityTypes][\"output\"];\n }\n | { readonly ok: false; readonly error: { readonly code: string; readonly message: string } }\n );\n}[keyof Registry & string];\n\n/** Input-order result or deliberately recoverable handler failure, including default tools. */\nexport type AgentOutcome<Registry extends Tools = {}> = ToolOutcome<RegisteredTools<Registry>>;\n\n/** A nonempty batch of independent calls, or the raw input to the final-result schema. */\nexport type AgentDecision<Registry extends Tools, Result> =\n | {\n readonly kind: \"continue\";\n readonly calls: readonly [AgentCall<Registry>, ...AgentCall<Registry>[]];\n readonly result?: never;\n }\n | { readonly kind: \"finish\"; readonly result: Result; readonly calls?: never };\n\n/** Finite limits for this agent and its descendants; child limits may only tighten them. */\nexport interface AgentLimits {\n /** Decision callbacks, including finish. Defaults to 20. */\n readonly maxTurns?: number;\n /** Admitted subtree calls, including calls stopped before dispatch. Defaults to 100. */\n readonly maxCalls?: number;\n /** Subtree decision callback admissions. Defaults to 100; provider retries are application-owned. */\n readonly maxDecisions?: number;\n /** Pipeline-tool delegation edges below this agent. Defaults to 4; zero allows leaf tools only. */\n readonly maxDepth?: number;\n /** Active decision callbacks and leaf handlers across the subtree. Defaults to 1. */\n readonly maxConcurrency?: number;\n}\n\n/** Step services and the workspace capability available to a registered tool. */\nexport interface AgentToolContext extends PipelineStepContext<{}> {\n readonly environment: AgentEnvironment;\n readonly execution?: AgentExecutionIdentity;\n}\n\n/** Model-facing descriptors and ordinary step services, without executable tools. */\nexport interface AgentDecisionContext<Options extends object> extends PipelineStepContext<Options> {\n readonly environment: AgentEnvironment;\n readonly execution?: AgentExecutionIdentity;\n readonly turn: number;\n readonly stateVersion: number;\n readonly capabilities: readonly {\n readonly name: string;\n readonly description: string;\n readonly inputJsonSchema: Readonly<Record<string, unknown>>;\n }[];\n readonly resultJsonSchema: Readonly<Record<string, unknown>>;\n}\n\nexport interface AgentDefinition<\n Id extends string,\n Options extends StandardSchemaV1<object, object>,\n Result extends StandardSchemaV1,\n State,\n Registry extends Tools,\n> {\n readonly id: Id;\n readonly name?: string;\n readonly description?: string;\n /** Semantic revision; required when this agent uses or inherits durable recovery. */\n readonly implementationVersion?: string;\n readonly inputSchema: Options;\n readonly resultSchema: Result;\n readonly resultJsonSchema?: Readonly<Record<string, unknown>>;\n /** Extend the standard tools; a custom tool with the same name replaces that default. */\n readonly tools?: Registry;\n readonly limits?: AgentLimits;\n /** Workspace capabilities; descendants inherit them unless explicitly replaced. */\n readonly environment?: AgentEnvironmentProvider;\n /** Acknowledged recovery checkpoints; requires an explicit implementationVersion. */\n readonly durability?: AgentDurability<Output<Options>>;\n initialState(options: Output<Options>): State;\n decide(\n state: AgentState<NoInfer<State>>,\n context: AgentDecisionContext<Output<Options>>\n ): Awaitable<unknown>;\n reduce?(\n state: AgentState<NoInfer<State>>,\n outcomes: readonly AgentOutcome<Registry>[]\n ): NoInfer<State>;\n dryRun?(\n state: AgentState<NoInfer<State>>,\n context: AgentDecisionContext<Output<Options>>\n ): Awaitable<unknown>;\n}\n"]}
@@ -5,6 +5,9 @@ export { defineTool, ToolError } from "./tools.js";
5
5
  export type { DefaultAgentTools } from "./default-tools.js";
6
6
  export type { AgentCall, AgentDecision, AgentDecisionContext, AgentLimits, AgentOutcome, AgentState, AgentTool, AgentToolContext, } from "./agent-types.js";
7
7
  export type { AgentEnvironment, AgentEnvironmentContext, AgentEnvironmentProvider, AgentProjectInstruction, } from "./environment.js";
8
+ export { createMemoryAgentCheckpointStore } from "./memory-checkpoint-store.js";
9
+ export { plainAgentCheckpointCodec } from "./checkpoint-codec.js";
10
+ export type { AgentCheckpointLease, AgentCheckpointStore, AgentCheckpointCodec, AgentDurability, AgentExecutionIdentity, } from "./checkpoint-types.js";
8
11
  export { defineModelAgent } from "./model-agent.js";
9
12
  export type { AgentModel, AgentModelRequest, AgentModelResponse } from "./model-types.js";
10
13
  /** Build a bounded in-process agent as an ordinary pipeline with one target, agent. */
@@ -2,6 +2,8 @@ import { agentError } from "./agent-state.js";
2
2
  import { compileAgent } from "./compile-agent.js";
3
3
  export { pipelineTool } from "./pipeline-tool.js";
4
4
  export { defineTool, ToolError } from "./tools.js";
5
+ export { createMemoryAgentCheckpointStore } from "./memory-checkpoint-store.js";
6
+ export { plainAgentCheckpointCodec } from "./checkpoint-codec.js";
5
7
  export { defineModelAgent } from "./model-agent.js";
6
8
  /** Build a bounded in-process agent as an ordinary pipeline with one target, agent. */
7
9
  export function defineAgent(definition) {
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAoBnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGpD,uFAAuF;AACvF,MAAM,UAAU,WAAW,CAMzB,UAAiE;IACjE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IACtC,IAAI,OAAO,MAAM,KAAK,UAAU,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,UAAU,CAAC;QACxF,MAAM,UAAU,CACd,mCAAmC,EACnC,iDAAiD,CAClD,CAAC;IACJ,OAAO,YAAY,CAAuC;QACxD,GAAG,UAAU;QACb,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;QACrF,MAAM,EACJ,MAAM,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;KAC5F,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { StandardSchemaV1 } from \"../core/pipeline-types.js\";\nimport type { AgentDefinition, Tools } from \"./agent-types.js\";\nimport { agentError } from \"./agent-state.js\";\nimport { compileAgent } from \"./compile-agent.js\";\n\nexport { pipelineTool } from \"./pipeline-tool.js\";\nexport { defineTool, ToolError } from \"./tools.js\";\nexport type { DefaultAgentTools } from \"./default-tools.js\";\nexport type {\n AgentCall,\n AgentDecision,\n AgentDecisionContext,\n AgentLimits,\n AgentOutcome,\n AgentState,\n AgentTool,\n AgentToolContext,\n} from \"./agent-types.js\";\n\nexport type {\n AgentEnvironment,\n AgentEnvironmentContext,\n AgentEnvironmentProvider,\n AgentProjectInstruction,\n} from \"./environment.js\";\n\nexport { defineModelAgent } from \"./model-agent.js\";\nexport type { AgentModel, AgentModelRequest, AgentModelResponse } from \"./model-types.js\";\n\n/** Build a bounded in-process agent as an ordinary pipeline with one target, agent. */\nexport function defineAgent<\n const Id extends string,\n const Options extends StandardSchemaV1<object, object>,\n const Result extends StandardSchemaV1,\n State,\n const Registry extends Tools = {},\n>(definition: AgentDefinition<Id, Options, Result, State, Registry>) {\n const { decide, dryRun } = definition;\n if (typeof decide !== \"function\" || (dryRun !== undefined && typeof dryRun !== \"function\"))\n throw agentError(\n \"TUBELESS_AGENT_INVALID_DEFINITION\",\n \"Agent requires callable decide/dryRun callbacks\"\n );\n return compileAgent<Id, Options, Result, State, Registry>({\n ...definition,\n decide: async (state, context) => ({ decision: await decide(state, context), state }),\n dryRun:\n dryRun && (async (state, context) => ({ decision: await dryRun(state, context), state })),\n });\n}\n"]}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAoBnD,OAAO,EAAE,gCAAgC,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AASlE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGpD,uFAAuF;AACvF,MAAM,UAAU,WAAW,CAMzB,UAAiE;IACjE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IACtC,IAAI,OAAO,MAAM,KAAK,UAAU,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,UAAU,CAAC;QACxF,MAAM,UAAU,CACd,mCAAmC,EACnC,iDAAiD,CAClD,CAAC;IACJ,OAAO,YAAY,CAAuC;QACxD,GAAG,UAAU;QACb,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;QACrF,MAAM,EACJ,MAAM,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;KAC5F,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { StandardSchemaV1 } from \"../core/pipeline-types.js\";\nimport type { AgentDefinition, Tools } from \"./agent-types.js\";\nimport { agentError } from \"./agent-state.js\";\nimport { compileAgent } from \"./compile-agent.js\";\n\nexport { pipelineTool } from \"./pipeline-tool.js\";\nexport { defineTool, ToolError } from \"./tools.js\";\nexport type { DefaultAgentTools } from \"./default-tools.js\";\nexport type {\n AgentCall,\n AgentDecision,\n AgentDecisionContext,\n AgentLimits,\n AgentOutcome,\n AgentState,\n AgentTool,\n AgentToolContext,\n} from \"./agent-types.js\";\n\nexport type {\n AgentEnvironment,\n AgentEnvironmentContext,\n AgentEnvironmentProvider,\n AgentProjectInstruction,\n} from \"./environment.js\";\n\nexport { createMemoryAgentCheckpointStore } from \"./memory-checkpoint-store.js\";\nexport { plainAgentCheckpointCodec } from \"./checkpoint-codec.js\";\nexport type {\n AgentCheckpointLease,\n AgentCheckpointStore,\n AgentCheckpointCodec,\n AgentDurability,\n AgentExecutionIdentity,\n} from \"./checkpoint-types.js\";\n\nexport { defineModelAgent } from \"./model-agent.js\";\nexport type { AgentModel, AgentModelRequest, AgentModelResponse } from \"./model-types.js\";\n\n/** Build a bounded in-process agent as an ordinary pipeline with one target, agent. */\nexport function defineAgent<\n const Id extends string,\n const Options extends StandardSchemaV1<object, object>,\n const Result extends StandardSchemaV1,\n State,\n const Registry extends Tools = {},\n>(definition: AgentDefinition<Id, Options, Result, State, Registry>) {\n const { decide, dryRun } = definition;\n if (typeof decide !== \"function\" || (dryRun !== undefined && typeof dryRun !== \"function\"))\n throw agentError(\n \"TUBELESS_AGENT_INVALID_DEFINITION\",\n \"Agent requires callable decide/dryRun callbacks\"\n );\n return compileAgent<Id, Options, Result, State, Registry>({\n ...definition,\n decide: async (state, context) => ({ decision: await decide(state, context), state }),\n dryRun:\n dryRun && (async (state, context) => ({ decision: await dryRun(state, context), state })),\n });\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { SavedCall } from "./checkpoint-format.js";
2
+ import type { PreparedCall } from "./decision.js";
3
+ import type { AgentExecutionScope } from "./execution-scope.js";
4
+ import type { CompiledTool } from "./tools.js";
5
+ import type { PipelineStepContext } from "../core/pipeline-types.js";
6
+ export declare function saveCalls(calls: readonly PreparedCall[]): SavedCall[];
7
+ /** Reconstruct privately prepared invocations after the owning definition has matched. */
8
+ export declare function restoreCalls(saved: readonly SavedCall[], registry: ReadonlyMap<string, CompiledTool>, scope: AgentExecutionScope, turn: number, context: PipelineStepContext<object>): PreparedCall[];
@@ -0,0 +1,46 @@
1
+ import { PreparedOptions } from "../core/prepared-options.js";
2
+ import { agentError } from "./agent-state.js";
3
+ export function saveCalls(calls) {
4
+ return calls.map((call) => {
5
+ const receipt = {
6
+ id: call.id,
7
+ tool: call.tool.name,
8
+ replay: call.tool.replay,
9
+ status: "pending",
10
+ };
11
+ return call.kind === "handler"
12
+ ? { ...receipt, kind: "handler", input: call.input }
13
+ : {
14
+ ...receipt,
15
+ kind: "pipeline",
16
+ input: call.options,
17
+ validatedOptions: call.preparedOptions.read(call.tool.pipeline.optionsSchema, call.options),
18
+ };
19
+ });
20
+ }
21
+ /** Reconstruct privately prepared invocations after the owning definition has matched. */
22
+ export function restoreCalls(saved, registry, scope, turn, context) {
23
+ return saved.map((call) => {
24
+ const tool = registry.get(call.tool);
25
+ if (!tool || tool.kind !== call.kind)
26
+ throw agentError("TUBELESS_AGENT_CHECKPOINT_MISMATCH", `Saved tool ${call.tool} differs`);
27
+ const plan = tool.pipeline.plan({ dryRun: context.dryRun, cache: context.cachePolicy });
28
+ if (!plan.ok)
29
+ throw agentError("TUBELESS_AGENT_CHECKPOINT_MISMATCH", `Saved tool ${call.tool} has an invalid plan`);
30
+ if (tool.kind === "handler" && call.kind === "handler")
31
+ return { kind: "handler", id: call.id, tool, input: call.input, plan };
32
+ if (tool.kind !== "pipeline" || call.kind !== "pipeline")
33
+ throw new Error("Saved pipeline call differs from its tool");
34
+ const options = call.input;
35
+ return {
36
+ kind: "pipeline",
37
+ id: call.id,
38
+ tool,
39
+ options,
40
+ preparedOptions: PreparedOptions.restore(tool.pipeline.optionsSchema, options, call.validatedOptions),
41
+ scope: scope.delegate(turn, call.id),
42
+ plan,
43
+ };
44
+ });
45
+ }
46
+ //# sourceMappingURL=checkpoint-calls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint-calls.js","sourceRoot":"","sources":["../../src/agent/checkpoint-calls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAO9C,MAAM,UAAU,SAAS,CAAC,KAA8B;IACtD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAa,EAAE;QACnC,MAAM,OAAO,GAAG;YACd,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI;YACpB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;YACxB,MAAM,EAAE,SAAkB;SAC3B,CAAC;QACF,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS;YAC5B,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;YACpD,CAAC,CAAC;gBACE,GAAG,OAAO;gBACV,IAAI,EAAE,UAAU;gBAChB,KAAK,EAAE,IAAI,CAAC,OAAO;gBACnB,gBAAgB,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CACzC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAChC,IAAI,CAAC,OAAO,CACb;aACF,CAAC;IACR,CAAC,CAAC,CAAC;AACL,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,YAAY,CAC1B,KAA2B,EAC3B,QAA2C,EAC3C,KAA0B,EAC1B,IAAY,EACZ,OAAoC;IAEpC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;YAClC,MAAM,UAAU,CAAC,oCAAoC,EAAE,cAAc,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC;QAC5F,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACxF,IAAI,CAAC,IAAI,CAAC,EAAE;YACV,MAAM,UAAU,CACd,oCAAoC,EACpC,cAAc,IAAI,CAAC,IAAI,sBAAsB,CAC9C,CAAC;QACJ,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YACpD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;QACzE,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU;YACtD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;QAC3B,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI;YACJ,OAAO;YACP,eAAe,EAAE,eAAe,CAAC,OAAO,CACtC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAC3B,OAAO,EACP,IAAI,CAAC,gBAAgB,CACtB;YACD,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACpC,IAAI;SACL,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { PreparedOptions } from \"../core/prepared-options.js\";\nimport { agentError } from \"./agent-state.js\";\nimport type { SavedCall } from \"./checkpoint-format.js\";\nimport type { PreparedCall } from \"./decision.js\";\nimport type { AgentExecutionScope } from \"./execution-scope.js\";\nimport type { CompiledTool } from \"./tools.js\";\nimport type { PipelineStepContext } from \"../core/pipeline-types.js\";\n\nexport function saveCalls(calls: readonly PreparedCall[]): SavedCall[] {\n return calls.map((call): SavedCall => {\n const receipt = {\n id: call.id,\n tool: call.tool.name,\n replay: call.tool.replay,\n status: \"pending\" as const,\n };\n return call.kind === \"handler\"\n ? { ...receipt, kind: \"handler\", input: call.input }\n : {\n ...receipt,\n kind: \"pipeline\",\n input: call.options,\n validatedOptions: call.preparedOptions.read(\n call.tool.pipeline.optionsSchema,\n call.options\n ),\n };\n });\n}\n\n/** Reconstruct privately prepared invocations after the owning definition has matched. */\nexport function restoreCalls(\n saved: readonly SavedCall[],\n registry: ReadonlyMap<string, CompiledTool>,\n scope: AgentExecutionScope,\n turn: number,\n context: PipelineStepContext<object>\n): PreparedCall[] {\n return saved.map((call) => {\n const tool = registry.get(call.tool);\n if (!tool || tool.kind !== call.kind)\n throw agentError(\"TUBELESS_AGENT_CHECKPOINT_MISMATCH\", `Saved tool ${call.tool} differs`);\n const plan = tool.pipeline.plan({ dryRun: context.dryRun, cache: context.cachePolicy });\n if (!plan.ok)\n throw agentError(\n \"TUBELESS_AGENT_CHECKPOINT_MISMATCH\",\n `Saved tool ${call.tool} has an invalid plan`\n );\n if (tool.kind === \"handler\" && call.kind === \"handler\")\n return { kind: \"handler\", id: call.id, tool, input: call.input, plan };\n if (tool.kind !== \"pipeline\" || call.kind !== \"pipeline\")\n throw new Error(\"Saved pipeline call differs from its tool\");\n const options = call.input;\n return {\n kind: \"pipeline\",\n id: call.id,\n tool,\n options,\n preparedOptions: PreparedOptions.restore(\n tool.pipeline.optionsSchema,\n options,\n call.validatedOptions\n ),\n scope: scope.delegate(turn, call.id),\n plan,\n };\n });\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { AgentCheckpointCodec } from "./checkpoint-types.js";
2
+ /** Lossless, tagged JSON codec for finite plain data; preserves undefined and sparse arrays. */
3
+ export declare const plainAgentCheckpointCodec: AgentCheckpointCodec;
@@ -0,0 +1,108 @@
1
+ import { agentError } from "./agent-state.js";
2
+ function encode(value, ancestors) {
3
+ if (value === undefined)
4
+ return ["undefined"];
5
+ if (value === null)
6
+ return ["null"];
7
+ if (typeof value === "string")
8
+ return ["string", value];
9
+ if (typeof value === "boolean")
10
+ return ["boolean", value];
11
+ if (typeof value === "number" && Number.isFinite(value))
12
+ return ["number", Object.is(value, -0) ? "-0" : String(value)];
13
+ if (typeof value !== "object" || ancestors.has(value))
14
+ throw new Error("Expected acyclic finite plain data");
15
+ const array = Array.isArray(value);
16
+ if (array && Object.getPrototypeOf(value) !== Array.prototype)
17
+ throw new Error("Expected a plain array; supply a lossless codec for array subclasses");
18
+ if (!array &&
19
+ Object.getPrototypeOf(value) !== Object.prototype &&
20
+ Object.getPrototypeOf(value) !== null)
21
+ throw new Error("Expected an array or plain record; supply a lossless codec for other values");
22
+ ancestors.add(value);
23
+ const properties = [];
24
+ for (const key of Reflect.ownKeys(value).sort((a, b) => String(a) < String(b) ? -1 : String(a) > String(b) ? 1 : 0)) {
25
+ if (array && key === "length")
26
+ continue;
27
+ const property = Object.getOwnPropertyDescriptor(value, key);
28
+ if (typeof key !== "string" || !("value" in property) || !property.enumerable)
29
+ throw new Error("Expected enumerable data properties");
30
+ properties.push([key, encode(property.value, ancestors)]);
31
+ }
32
+ ancestors.delete(value);
33
+ return array
34
+ ? ["array", value.length, properties]
35
+ : [Object.getPrototypeOf(value) === null ? "null-record" : "record", properties];
36
+ }
37
+ function decode(value) {
38
+ if (!Array.isArray(value))
39
+ throw new Error("Invalid checkpoint value");
40
+ const [tag, payload, properties] = value;
41
+ if (tag === "undefined" && value.length === 1)
42
+ return undefined;
43
+ if (tag === "null" && value.length === 1)
44
+ return null;
45
+ if (tag === "string" && value.length === 2 && typeof payload === "string")
46
+ return payload;
47
+ if (tag === "boolean" && value.length === 2 && typeof payload === "boolean")
48
+ return payload;
49
+ if (tag === "number" &&
50
+ value.length === 2 &&
51
+ typeof payload === "string" &&
52
+ Number.isFinite(Number(payload)) &&
53
+ (payload === "-0" || String(Number(payload)) === payload))
54
+ return Number(payload);
55
+ const array = tag === "array" &&
56
+ value.length === 3 &&
57
+ Number.isSafeInteger(payload) &&
58
+ payload >= 0 &&
59
+ payload <= 0xffff_ffff;
60
+ const entries = array
61
+ ? properties
62
+ : (tag === "record" || tag === "null-record") && value.length === 2
63
+ ? payload
64
+ : undefined;
65
+ if (!Array.isArray(entries))
66
+ throw new Error("Invalid checkpoint properties");
67
+ const result = array
68
+ ? new Array(payload)
69
+ : tag === "null-record"
70
+ ? Object.create(null)
71
+ : {};
72
+ for (const entry of entries) {
73
+ if (!Array.isArray(entry) ||
74
+ entry.length !== 2 ||
75
+ typeof entry[0] !== "string" ||
76
+ Object.hasOwn(result, entry[0]))
77
+ throw new Error("Invalid or duplicate checkpoint property");
78
+ Object.defineProperty(result, entry[0], {
79
+ value: decode(entry[1]),
80
+ enumerable: true,
81
+ writable: true,
82
+ configurable: true,
83
+ });
84
+ }
85
+ if (array && result.length !== payload)
86
+ throw new Error("Invalid checkpoint array length");
87
+ return result;
88
+ }
89
+ /** Lossless, tagged JSON codec for finite plain data; preserves undefined and sparse arrays. */
90
+ export const plainAgentCheckpointCodec = Object.freeze({
91
+ encode: (value) => {
92
+ try {
93
+ return JSON.stringify(encode(value, new Set()));
94
+ }
95
+ catch (cause) {
96
+ throw agentError("TUBELESS_AGENT_CHECKPOINT_CODEC", "Cannot encode agent checkpoint losslessly", cause);
97
+ }
98
+ },
99
+ decode: (checkpoint) => {
100
+ try {
101
+ return decode(JSON.parse(checkpoint));
102
+ }
103
+ catch (cause) {
104
+ throw agentError("TUBELESS_AGENT_CHECKPOINT_CODEC", "Invalid encoded agent checkpoint", cause);
105
+ }
106
+ },
107
+ });
108
+ //# sourceMappingURL=checkpoint-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint-codec.js","sourceRoot":"","sources":["../../src/agent/checkpoint-codec.ts"],"names":[],"mappings":"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","sourcesContent":["import { agentError } from \"./agent-state.js\";\nimport type { AgentCheckpointCodec } from \"./checkpoint-types.js\";\n\ntype Encoded =\n | [\"undefined\"]\n | [\"null\"]\n | [\"string\", string]\n | [\"boolean\", boolean]\n | [\"number\", string]\n | [\"array\", number, [string, Encoded][]]\n | [\"record\" | \"null-record\", [string, Encoded][]];\n\nfunction encode(value: unknown, ancestors: Set<object>): Encoded {\n if (value === undefined) return [\"undefined\"];\n if (value === null) return [\"null\"];\n if (typeof value === \"string\") return [\"string\", value];\n if (typeof value === \"boolean\") return [\"boolean\", value];\n if (typeof value === \"number\" && Number.isFinite(value))\n return [\"number\", Object.is(value, -0) ? \"-0\" : String(value)];\n if (typeof value !== \"object\" || ancestors.has(value))\n throw new Error(\"Expected acyclic finite plain data\");\n const array = Array.isArray(value);\n if (array && Object.getPrototypeOf(value) !== Array.prototype)\n throw new Error(\"Expected a plain array; supply a lossless codec for array subclasses\");\n if (\n !array &&\n Object.getPrototypeOf(value) !== Object.prototype &&\n Object.getPrototypeOf(value) !== null\n )\n throw new Error(\"Expected an array or plain record; supply a lossless codec for other values\");\n ancestors.add(value);\n const properties: [string, Encoded][] = [];\n for (const key of Reflect.ownKeys(value).sort((a, b) =>\n String(a) < String(b) ? -1 : String(a) > String(b) ? 1 : 0\n )) {\n if (array && key === \"length\") continue;\n const property = Object.getOwnPropertyDescriptor(value, key)!;\n if (typeof key !== \"string\" || !(\"value\" in property) || !property.enumerable)\n throw new Error(\"Expected enumerable data properties\");\n properties.push([key, encode(property.value, ancestors)]);\n }\n ancestors.delete(value);\n return array\n ? [\"array\", value.length, properties]\n : [Object.getPrototypeOf(value) === null ? \"null-record\" : \"record\", properties];\n}\n\nfunction decode(value: unknown): unknown {\n if (!Array.isArray(value)) throw new Error(\"Invalid checkpoint value\");\n const [tag, payload, properties] = value;\n if (tag === \"undefined\" && value.length === 1) return undefined;\n if (tag === \"null\" && value.length === 1) return null;\n if (tag === \"string\" && value.length === 2 && typeof payload === \"string\") return payload;\n if (tag === \"boolean\" && value.length === 2 && typeof payload === \"boolean\") return payload;\n if (\n tag === \"number\" &&\n value.length === 2 &&\n typeof payload === \"string\" &&\n Number.isFinite(Number(payload)) &&\n (payload === \"-0\" || String(Number(payload)) === payload)\n )\n return Number(payload);\n const array =\n tag === \"array\" &&\n value.length === 3 &&\n Number.isSafeInteger(payload) &&\n payload >= 0 &&\n payload <= 0xffff_ffff;\n const entries = array\n ? properties\n : (tag === \"record\" || tag === \"null-record\") && value.length === 2\n ? payload\n : undefined;\n if (!Array.isArray(entries)) throw new Error(\"Invalid checkpoint properties\");\n const result: unknown[] | Record<string, unknown> = array\n ? new Array(payload)\n : tag === \"null-record\"\n ? Object.create(null)\n : {};\n for (const entry of entries) {\n if (\n !Array.isArray(entry) ||\n entry.length !== 2 ||\n typeof entry[0] !== \"string\" ||\n Object.hasOwn(result, entry[0])\n )\n throw new Error(\"Invalid or duplicate checkpoint property\");\n Object.defineProperty(result, entry[0], {\n value: decode(entry[1]),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n if (array && (result as unknown[]).length !== payload)\n throw new Error(\"Invalid checkpoint array length\");\n return result;\n}\n\n/** Lossless, tagged JSON codec for finite plain data; preserves undefined and sparse arrays. */\nexport const plainAgentCheckpointCodec: AgentCheckpointCodec = Object.freeze({\n encode: (value: unknown) => {\n try {\n return JSON.stringify(encode(value, new Set()));\n } catch (cause) {\n throw agentError(\n \"TUBELESS_AGENT_CHECKPOINT_CODEC\",\n \"Cannot encode agent checkpoint losslessly\",\n cause\n );\n }\n },\n decode: (checkpoint: string) => {\n try {\n return decode(JSON.parse(checkpoint));\n } catch (cause) {\n throw agentError(\n \"TUBELESS_AGENT_CHECKPOINT_CODEC\",\n \"Invalid encoded agent checkpoint\",\n cause\n );\n }\n },\n});\n"]}
@@ -0,0 +1,80 @@
1
+ import type { AgentLimits, AgentOutcome, Tools } from "./agent-types.js";
2
+ export interface StoredBudget {
3
+ depth: number;
4
+ limits: Required<AgentLimits>;
5
+ maxCalls: number;
6
+ maxDecisions: number;
7
+ }
8
+ export type CallOutcome = AgentOutcome<Tools>;
9
+ export type SavedCall = {
10
+ id: string;
11
+ tool: string;
12
+ replay: "safe" | "unsafe";
13
+ } & ({
14
+ kind: "handler";
15
+ input: unknown;
16
+ validatedOptions?: never;
17
+ } | {
18
+ kind: "pipeline";
19
+ input: object;
20
+ validatedOptions: object;
21
+ }) & ({
22
+ status: "pending" | "running";
23
+ outcome?: never;
24
+ } | {
25
+ status: "completed";
26
+ outcome: CallOutcome;
27
+ });
28
+ export interface SavedDecision {
29
+ state: unknown;
30
+ calls: SavedCall[];
31
+ admitted: boolean;
32
+ }
33
+ interface AgentSnapshot {
34
+ metadata: {
35
+ definition: string;
36
+ implementationVersion?: string;
37
+ options: object;
38
+ environment: string;
39
+ cwd: string;
40
+ cache: "use" | "recompute" | "bypass";
41
+ };
42
+ execution: {
43
+ state: unknown;
44
+ turn: number;
45
+ stateVersion: number;
46
+ calls: number;
47
+ };
48
+ }
49
+ export type SavedAgent = AgentSnapshot & ({
50
+ phase: "decide";
51
+ decision?: never;
52
+ result?: never;
53
+ failure?: never;
54
+ } | {
55
+ phase: "calls";
56
+ decision: SavedDecision;
57
+ result?: never;
58
+ failure?: never;
59
+ } | {
60
+ phase: "completed";
61
+ result: unknown;
62
+ decision?: never;
63
+ failure?: never;
64
+ } | {
65
+ phase: "failed";
66
+ failure: {
67
+ code: string;
68
+ message: string;
69
+ };
70
+ decision?: never;
71
+ result?: never;
72
+ });
73
+ export interface Checkpoint {
74
+ version: 1;
75
+ agents: Record<string, SavedAgent>;
76
+ budgets: Record<string, StoredBudget>;
77
+ }
78
+ /** Validate receipts and counters before treating decoded storage as prepared work. */
79
+ export declare function checkedCheckpoint(value: unknown): Checkpoint;
80
+ export {};
@@ -0,0 +1,116 @@
1
+ function record(value) {
2
+ return (value !== null &&
3
+ typeof value === "object" &&
4
+ !Array.isArray(value) &&
5
+ (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null));
6
+ }
7
+ function natural(value) {
8
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
9
+ }
10
+ function options(value) {
11
+ return value !== null && typeof value === "object" && !Array.isArray(value);
12
+ }
13
+ function failure(value) {
14
+ return record(value) && typeof value.code === "string" && typeof value.message === "string";
15
+ }
16
+ function checkCall(call, admitted, ids) {
17
+ if (!record(call) ||
18
+ typeof call.id !== "string" ||
19
+ !call.id.trim() ||
20
+ call.id.length > 256 ||
21
+ ids.has(call.id) ||
22
+ typeof call.tool !== "string" ||
23
+ !/^[A-Za-z][A-Za-z0-9_-]{0,127}$/.test(call.tool) ||
24
+ !["handler", "pipeline"].includes(String(call.kind)) ||
25
+ !["safe", "unsafe"].includes(String(call.replay)) ||
26
+ !["pending", "running", "completed"].includes(String(call.status)) ||
27
+ !Object.hasOwn(call, "input"))
28
+ throw new Error("Invalid saved call");
29
+ ids.add(call.id);
30
+ if (call.kind === "pipeline" && (!options(call.input) || !options(call.validatedOptions)))
31
+ throw new Error("Invalid saved pipeline options");
32
+ if (!admitted && call.status !== "pending")
33
+ throw new Error("Unadmitted call has started");
34
+ if (call.status === "completed") {
35
+ const outcome = call.outcome;
36
+ if (!record(outcome) ||
37
+ outcome.id !== call.id ||
38
+ outcome.tool !== call.tool ||
39
+ typeof outcome.ok !== "boolean" ||
40
+ (outcome.ok ? !Object.hasOwn(outcome, "value") : !failure(outcome.error)))
41
+ throw new Error("Invalid saved call outcome");
42
+ }
43
+ }
44
+ function checkAgent(agent) {
45
+ if (!record(agent) || !record(agent.metadata) || !record(agent.execution))
46
+ throw new Error("Invalid saved agent");
47
+ const { metadata, execution } = agent;
48
+ if (typeof metadata.definition !== "string" ||
49
+ typeof metadata.environment !== "string" ||
50
+ typeof metadata.cwd !== "string" ||
51
+ !options(metadata.options) ||
52
+ (metadata.implementationVersion !== undefined &&
53
+ typeof metadata.implementationVersion !== "string") ||
54
+ !["use", "recompute", "bypass"].includes(String(metadata.cache)))
55
+ throw new Error("Invalid saved agent metadata");
56
+ if (!Object.hasOwn(execution, "state") ||
57
+ !natural(execution.turn) ||
58
+ execution.turn < 1 ||
59
+ !natural(execution.stateVersion) ||
60
+ !natural(execution.calls) ||
61
+ !["decide", "calls", "completed", "failed"].includes(String(agent.phase)))
62
+ throw new Error("Invalid saved agent execution");
63
+ if (agent.phase === "completed" && !Object.hasOwn(agent, "result"))
64
+ throw new Error("Missing saved agent result");
65
+ if (agent.phase === "failed" && !failure(agent.failure))
66
+ throw new Error("Invalid saved agent failure");
67
+ if (agent.phase === "calls") {
68
+ const decision = agent.decision;
69
+ if (!record(decision) ||
70
+ !Object.hasOwn(decision, "state") ||
71
+ !Array.isArray(decision.calls) ||
72
+ decision.calls.length === 0 ||
73
+ typeof decision.admitted !== "boolean")
74
+ throw new Error("Invalid saved call batch");
75
+ const ids = new Set();
76
+ for (const call of decision.calls)
77
+ checkCall(call, decision.admitted, ids);
78
+ }
79
+ }
80
+ function checkBudget(budget) {
81
+ if (!record(budget) ||
82
+ !natural(budget.depth) ||
83
+ !natural(budget.maxCalls) ||
84
+ !natural(budget.maxDecisions) ||
85
+ !record(budget.limits))
86
+ throw new Error("Invalid saved agent budget");
87
+ for (const name of [
88
+ "maxTurns",
89
+ "maxCalls",
90
+ "maxDecisions",
91
+ "maxDepth",
92
+ "maxConcurrency",
93
+ ]) {
94
+ const bound = budget.limits[name];
95
+ if (!natural(bound) || (!["maxCalls", "maxDepth"].includes(name) && bound === 0))
96
+ throw new Error("Invalid saved agent limits");
97
+ }
98
+ if (budget.maxCalls > Number(budget.limits.maxCalls) ||
99
+ budget.maxDecisions > Number(budget.limits.maxDecisions))
100
+ throw new Error("Saved agent budget exceeds its limits");
101
+ }
102
+ /** Validate receipts and counters before treating decoded storage as prepared work. */
103
+ export function checkedCheckpoint(value) {
104
+ if (!record(value) || value.version !== 1 || !record(value.agents) || !record(value.budgets))
105
+ throw new Error("Invalid agent checkpoint envelope");
106
+ for (const [key, agent] of Object.entries(value.agents)) {
107
+ checkAgent(agent);
108
+ if (!Object.hasOwn(value.budgets, key))
109
+ throw new Error("Missing saved agent budget");
110
+ }
111
+ for (const budget of Object.values(value.budgets))
112
+ checkBudget(budget);
113
+ // SAFETY: metadata, execution counters, call receipts and budget contracts were checked above.
114
+ return value;
115
+ }
116
+ //# sourceMappingURL=checkpoint-format.js.map