@nylorun/harness 0.12.0-beta → 0.15.0-beta

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 (137) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/HOST_CONTRACT.md +27 -0
  3. package/README.md +86 -5
  4. package/dist/compatibility.d.ts +3 -0
  5. package/dist/compatibility.js +3 -0
  6. package/dist/definition/agent-definition.d.ts +19 -0
  7. package/dist/definition/agent-definition.js +20 -0
  8. package/dist/definition/compatibility.d.ts +11 -0
  9. package/dist/definition/compatibility.js +30 -0
  10. package/dist/definition/registry.d.ts +10 -0
  11. package/dist/definition/registry.js +49 -0
  12. package/dist/index.d.ts +4 -15
  13. package/dist/index.js +1 -6
  14. package/dist/loop/dispatch.d.ts +2 -0
  15. package/dist/loop/dispatch.js +327 -0
  16. package/dist/loop/host-suspension.d.ts +6 -0
  17. package/dist/loop/host-suspension.js +10 -0
  18. package/dist/loop/initial-state.d.ts +13 -0
  19. package/dist/loop/initial-state.js +30 -0
  20. package/dist/loop/invocation.d.ts +24 -0
  21. package/dist/loop/invocation.js +37 -0
  22. package/dist/{model → loop/model}/adapters.d.ts +4 -2
  23. package/dist/{model → loop/model}/adapters.js +3 -2
  24. package/dist/{model → loop/model}/normalize.d.ts +2 -2
  25. package/dist/{model → loop/model}/normalize.js +2 -2
  26. package/dist/{model → loop/model}/prepared.d.ts +3 -3
  27. package/dist/{step → loop/model}/project.d.ts +1 -1
  28. package/dist/{step → loop/model}/project.js +2 -10
  29. package/dist/loop/observe.d.ts +17 -0
  30. package/dist/loop/observe.js +53 -0
  31. package/dist/loop/options.d.ts +11 -0
  32. package/dist/loop/options.js +69 -0
  33. package/dist/loop/resume.d.ts +4 -0
  34. package/dist/loop/resume.js +52 -0
  35. package/dist/loop/run.d.ts +5 -0
  36. package/dist/loop/run.js +264 -0
  37. package/dist/loop/state.d.ts +8 -0
  38. package/dist/loop/state.js +218 -0
  39. package/dist/{step → loop/step}/canonicalize.d.ts +2 -2
  40. package/dist/{step → loop/step}/canonicalize.js +2 -2
  41. package/dist/{step → loop/step}/compose.d.ts +3 -2
  42. package/dist/{step → loop/step}/compose.js +8 -5
  43. package/dist/loop/step/context-draft.d.ts +8 -0
  44. package/dist/{step → loop/step}/context-draft.js +5 -22
  45. package/dist/loop/step/describe.d.ts +9 -0
  46. package/dist/loop/step/describe.js +22 -0
  47. package/dist/loop/step/dynamics.d.ts +29 -0
  48. package/dist/loop/step/dynamics.js +147 -0
  49. package/dist/{step → loop/step}/model-configuration.d.ts +4 -3
  50. package/dist/{step → loop/step}/model-configuration.js +3 -3
  51. package/dist/loop/step/resolve.d.ts +11 -0
  52. package/dist/{step → loop/step}/resolve.js +5 -3
  53. package/dist/loop/step/run.d.ts +30 -0
  54. package/dist/{step → loop/step}/run.js +104 -53
  55. package/dist/loop/step/runtime.d.ts +40 -0
  56. package/dist/{step → loop/step}/seal.d.ts +13 -8
  57. package/dist/{step → loop/step}/seal.js +8 -6
  58. package/dist/{step → loop/step}/slot-assembly.d.ts +4 -4
  59. package/dist/{step → loop/step}/slot-assembly.js +4 -4
  60. package/dist/{step → loop/step}/step-context.d.ts +11 -12
  61. package/dist/{step → loop/step}/step-context.js +5 -27
  62. package/dist/loop/tool-result.d.ts +4 -0
  63. package/dist/loop/tool-result.js +30 -0
  64. package/dist/loop/transcript.d.ts +2 -0
  65. package/dist/{session/seed.js → loop/transcript.js} +11 -41
  66. package/dist/loop/waits.d.ts +50 -0
  67. package/dist/loop/waits.js +11 -0
  68. package/dist/run/durable.d.ts +71 -0
  69. package/dist/run/durable.js +164 -0
  70. package/dist/run/index.d.ts +33 -0
  71. package/dist/run/index.js +38 -0
  72. package/dist/types/client.d.ts +88 -0
  73. package/dist/types/execution.d.ts +114 -0
  74. package/dist/utils/ids.d.ts +1 -0
  75. package/dist/utils/ids.js +11 -1
  76. package/package.json +18 -6
  77. package/dist/build/agent.d.ts +0 -17
  78. package/dist/build/agent.js +0 -32
  79. package/dist/build/assemble.d.ts +0 -7
  80. package/dist/build/assemble.js +0 -41
  81. package/dist/build/bind-tool.d.ts +0 -3
  82. package/dist/build/bind-tool.js +0 -18
  83. package/dist/build/builder.d.ts +0 -38
  84. package/dist/build/builder.js +0 -136
  85. package/dist/build/helpers.d.ts +0 -6
  86. package/dist/build/helpers.js +0 -4
  87. package/dist/build/manifest.d.ts +0 -7
  88. package/dist/build/manifest.js +0 -20
  89. package/dist/build/schema.d.ts +0 -14
  90. package/dist/build/schema.js +0 -205
  91. package/dist/errors.d.ts +0 -17
  92. package/dist/errors.js +0 -17
  93. package/dist/session/capability-state.d.ts +0 -14
  94. package/dist/session/capability-state.js +0 -67
  95. package/dist/session/event-log.d.ts +0 -12
  96. package/dist/session/event-log.js +0 -63
  97. package/dist/session/input-queue.d.ts +0 -41
  98. package/dist/session/input-queue.js +0 -94
  99. package/dist/session/output-contract.d.ts +0 -6
  100. package/dist/session/output-contract.js +0 -12
  101. package/dist/session/record.d.ts +0 -11
  102. package/dist/session/record.js +0 -26
  103. package/dist/session/scheduler.d.ts +0 -62
  104. package/dist/session/scheduler.js +0 -475
  105. package/dist/session/seed.d.ts +0 -10
  106. package/dist/session/session.d.ts +0 -17
  107. package/dist/session/session.js +0 -101
  108. package/dist/session/state.d.ts +0 -15
  109. package/dist/session/state.js +0 -48
  110. package/dist/session/submission-stream.d.ts +0 -16
  111. package/dist/session/submission-stream.js +0 -46
  112. package/dist/step/context-draft.d.ts +0 -10
  113. package/dist/step/resolve.d.ts +0 -10
  114. package/dist/step/run.d.ts +0 -33
  115. package/dist/turn/plan-runner.d.ts +0 -72
  116. package/dist/turn/plan-runner.js +0 -389
  117. package/dist/turn/runner.d.ts +0 -69
  118. package/dist/turn/runner.js +0 -159
  119. package/dist/types/manifest.d.ts +0 -19
  120. package/dist/types/middleware.d.ts +0 -95
  121. package/dist/types/model.d.ts +0 -184
  122. package/dist/types/session.d.ts +0 -230
  123. package/dist/types/session.js +0 -1
  124. package/dist/types/shared.d.ts +0 -249
  125. package/dist/types/shared.js +0 -1
  126. package/dist/types/tool.d.ts +0 -139
  127. package/dist/types/tool.js +0 -1
  128. package/dist/utils/immutable.d.ts +0 -5
  129. package/dist/utils/immutable.js +0 -68
  130. package/dist/utils/maps.d.ts +0 -1
  131. package/dist/utils/maps.js +0 -37
  132. package/dist/utils/observe.d.ts +0 -3
  133. package/dist/utils/observe.js +0 -13
  134. /package/dist/{model → loop/model}/prepared.js +0 -0
  135. /package/dist/{types/manifest.js → loop/step/runtime.js} +0 -0
  136. /package/dist/types/{middleware.js → client.js} +0 -0
  137. /package/dist/types/{model.js → execution.js} +0 -0
@@ -1,38 +0,0 @@
1
- import type { BoundMiddleware, CapabilityDeclaration, StepMiddleware } from "../types/middleware.js";
2
- import type { BuildDiagnostic } from "../types/shared.js";
3
- import { HarnessError } from "../errors.js";
4
- import type { BuiltAgent } from "./agent.js";
5
- export interface AgentOptions {
6
- readonly id: string;
7
- readonly name: string;
8
- readonly instructions?: string | readonly string[];
9
- }
10
- interface BuilderState {
11
- readonly id: string;
12
- readonly name: string;
13
- readonly middleware: BoundMiddleware[];
14
- sealed: boolean;
15
- agent?: BuiltAgent;
16
- error?: AgentBuildError;
17
- middlewareSeq: number;
18
- }
19
- export declare class AgentBuildError extends HarnessError {
20
- readonly diagnostics: readonly BuildDiagnostic[];
21
- constructor(diagnostics: readonly BuildDiagnostic[]);
22
- }
23
- export declare class AgentLifecycleError extends HarnessError {
24
- constructor(message: string);
25
- }
26
- export declare function Agent(options: AgentOptions): AgentBuilder;
27
- export declare class AgentBuilder {
28
- private readonly state;
29
- constructor(state: BuilderState);
30
- use(middleware: StepMiddleware): this;
31
- use(id: string, middleware: StepMiddleware): this;
32
- use<State>(declaration: CapabilityDeclaration<State>): this;
33
- build(): BuiltAgent;
34
- private nextMiddlewareId;
35
- private push;
36
- private assertOpen;
37
- }
38
- export {};
@@ -1,136 +0,0 @@
1
- import { HarnessError } from "../errors.js";
2
- import { assembleAgent } from "./assemble.js";
3
- export class AgentBuildError extends HarnessError {
4
- diagnostics;
5
- constructor(diagnostics) {
6
- super("agent.build-failed", diagnostics.map((item) => item.message).join("; ") || "Agent build failed");
7
- this.diagnostics = diagnostics;
8
- this.name = "AgentBuildError";
9
- }
10
- }
11
- export class AgentLifecycleError extends HarnessError {
12
- constructor(message) {
13
- super("agent.lifecycle-sealed", message);
14
- this.name = "AgentLifecycleError";
15
- }
16
- }
17
- export function Agent(options) {
18
- return new AgentBuilder(createState(options));
19
- }
20
- export class AgentBuilder {
21
- state;
22
- constructor(state) {
23
- this.state = state;
24
- }
25
- use(idOrMiddleware, middleware) {
26
- if (typeof idOrMiddleware === "function") {
27
- return this.push({ id: this.nextMiddlewareId(), handle: idOrMiddleware });
28
- }
29
- if (typeof idOrMiddleware === "object")
30
- return this.push(compileDeclaration(idOrMiddleware));
31
- return this.push({ id: idOrMiddleware, handle: middleware });
32
- }
33
- build() {
34
- if (this.state.agent)
35
- return this.state.agent;
36
- if (this.state.error)
37
- throw this.state.error;
38
- this.state.sealed = true;
39
- const result = assembleAgent(this.state.middleware, {
40
- id: this.state.id,
41
- name: this.state.name,
42
- });
43
- if (!result.ok) {
44
- this.state.error = new AgentBuildError(result.diagnostics);
45
- throw this.state.error;
46
- }
47
- this.state.agent = result.agent;
48
- return this.state.agent;
49
- }
50
- nextMiddlewareId() {
51
- const taken = new Set(this.state.middleware.map((item) => item.id));
52
- let id;
53
- do {
54
- this.state.middlewareSeq += 1;
55
- id = `middleware-${this.state.middlewareSeq}`;
56
- } while (taken.has(id));
57
- return id;
58
- }
59
- push(entry) {
60
- this.assertOpen();
61
- this.state.middleware.push(entry);
62
- return this;
63
- }
64
- assertOpen() {
65
- if (this.state.sealed)
66
- throw new AgentLifecycleError("AgentBuilder cannot be changed after build()");
67
- }
68
- }
69
- function createState(options) {
70
- const middleware = [];
71
- if (options.instructions !== undefined) {
72
- const instructions = typeof options.instructions === "string" ? [options.instructions] : options.instructions;
73
- middleware.push(compileDeclaration({ id: "agent", instructions }));
74
- }
75
- return {
76
- id: options.id,
77
- name: options.name,
78
- middleware,
79
- sealed: false,
80
- middlewareSeq: 0,
81
- };
82
- }
83
- function compileDeclaration(declaration) {
84
- const tools = copyItems(declaration.tools, declaration.id);
85
- const instructions = copyItems(declaration.instructions, declaration.id);
86
- const model = declaration.model;
87
- const contributions = snapshotContributions(instructions?.items, tools?.items, model);
88
- const handle = async (request, next) => {
89
- if (tools)
90
- request.configuration.tools.set(tools.slot, tools.items);
91
- if (instructions)
92
- request.configuration.instructions.set(instructions.slot, instructions.items);
93
- if (model)
94
- request.configuration.model.select(model);
95
- return declaration.middleware ? declaration.middleware(request, next) : next();
96
- };
97
- return {
98
- id: declaration.id,
99
- handle,
100
- ...(declaration.state === undefined
101
- ? {}
102
- : { state: declaration.state }),
103
- ...(contributions === undefined ? {} : { contributions }),
104
- };
105
- }
106
- function snapshotContributions(instructions, tools, model) {
107
- const snapInstructions = instructions === undefined ? undefined : Object.freeze([...instructions]);
108
- const snapTools = tools === undefined
109
- ? undefined
110
- : Object.freeze(tools.map((tool) => Object.freeze({
111
- name: tool.name,
112
- ...(tool.description === undefined ? {} : { description: tool.description }),
113
- })));
114
- const snapModel = model === undefined ? undefined : snapshotModel(model);
115
- if (snapInstructions === undefined && snapTools === undefined && snapModel === undefined) {
116
- return undefined;
117
- }
118
- return Object.freeze({
119
- ...(snapInstructions === undefined ? {} : { instructions: snapInstructions }),
120
- ...(snapTools === undefined ? {} : { tools: snapTools }),
121
- ...(snapModel === undefined ? {} : { model: snapModel }),
122
- });
123
- }
124
- function snapshotModel(model) {
125
- return Object.freeze({
126
- ...(model.id === undefined ? {} : { id: model.id }),
127
- ...(model.controls === undefined ? {} : { controls: Object.freeze({ ...model.controls }) }),
128
- });
129
- }
130
- function copyItems(value, defaultSlot) {
131
- if (value === undefined)
132
- return undefined;
133
- if (!("items" in value))
134
- return Object.freeze({ slot: defaultSlot, items: Object.freeze([...value]) });
135
- return Object.freeze({ slot: value.slot, items: Object.freeze([...value.items]) });
136
- }
@@ -1,6 +0,0 @@
1
- import type { ModelAdapter } from "../types/model.js";
2
- import type { StepMiddleware } from "../types/middleware.js";
3
- import type { ToolDefinition, ToolInputSchema, ToolOutputSchema } from "../types/tool.js";
4
- export declare const tool: <InputSchema extends ToolInputSchema, State = never, OutputSchema extends ToolOutputSchema | undefined = undefined>(value: ToolDefinition<InputSchema, State, OutputSchema>) => ToolDefinition<InputSchema, State, OutputSchema>;
5
- export declare const model: <T extends ModelAdapter>(value: T) => T;
6
- export declare const middleware: <T extends StepMiddleware>(value: T) => T;
@@ -1,4 +0,0 @@
1
- import { prepareTool } from "./schema.js";
2
- export const tool = (value) => prepareTool(value);
3
- export const model = (value) => value;
4
- export const middleware = (value) => value;
@@ -1,7 +0,0 @@
1
- import type { AgentManifest } from "../types/manifest.js";
2
- import type { BoundMiddleware } from "../types/middleware.js";
3
- export declare function createManifest(input: {
4
- id: string;
5
- name: string;
6
- middleware: readonly BoundMiddleware[];
7
- }): AgentManifest;
@@ -1,20 +0,0 @@
1
- import { deepFreeze } from "../utils/immutable.js";
2
- export function createManifest(input) {
3
- const middleware = input.middleware.map((item) => projectMiddleware(item));
4
- return deepFreeze({
5
- id: input.id,
6
- name: input.name,
7
- middleware,
8
- });
9
- }
10
- function projectMiddleware(item) {
11
- const contributions = item.contributions;
12
- return {
13
- id: item.id,
14
- ...(contributions?.instructions === undefined
15
- ? {}
16
- : { instructions: contributions.instructions }),
17
- ...(contributions?.tools === undefined ? {} : { tools: contributions.tools }),
18
- ...(contributions?.model === undefined ? {} : { model: contributions.model }),
19
- };
20
- }
@@ -1,14 +0,0 @@
1
- import type { BoundToolSchema, ToolDefinition, ToolSchema, ToolSchemaSource } from "../types/tool.js";
2
- export type { SchemaValidation } from "../types/tool.js";
3
- interface NormalizedToolSchemas {
4
- readonly inputSchema: BoundToolSchema<unknown>;
5
- readonly outputSchema?: BoundToolSchema<unknown>;
6
- }
7
- /** Creates a portable, explicitly validated schema source from raw JSON Schema. */
8
- export declare function defineSchema<T>(value: ToolSchema<T>): ToolSchema<T>;
9
- /** Eagerly prepares a definition authored through Harness's tool() helper. */
10
- export declare function prepareTool<T extends ToolDefinition>(definition: T): T;
11
- /** Returns cached normalized contracts, preparing raw definitions on first bind. */
12
- export declare function normalizedSchemasFor(definition: ToolDefinition): NormalizedToolSchemas;
13
- /** Converts an accepted tool schema source into Harness's immutable runtime representation. */
14
- export declare function normalizeSchema<T>(source: ToolSchemaSource<T>, role: "input" | "output"): BoundToolSchema<T>;
@@ -1,205 +0,0 @@
1
- import { z } from "zod";
2
- import { HarnessError } from "../errors.js";
3
- import { copyJsonObject } from "../utils/immutable.js";
4
- const preparedSchemas = new WeakMap();
5
- /** Creates a portable, explicitly validated schema source from raw JSON Schema. */
6
- export function defineSchema(value) {
7
- if (!value || typeof value !== "object" || typeof value.validate !== "function")
8
- throw new HarnessError("tool.invalid-schema", "Tool schema must provide validate()");
9
- return Object.freeze({
10
- jsonSchema: copyJsonObject(value.jsonSchema, "tool schema jsonSchema"),
11
- validate: value.validate.bind(value),
12
- });
13
- }
14
- /** Eagerly prepares a definition authored through Harness's tool() helper. */
15
- export function prepareTool(definition) {
16
- normalizedSchemasFor(definition);
17
- return definition;
18
- }
19
- /** Returns cached normalized contracts, preparing raw definitions on first bind. */
20
- export function normalizedSchemasFor(definition) {
21
- const cached = preparedSchemas.get(definition);
22
- if (cached)
23
- return cached;
24
- const normalized = Object.freeze({
25
- inputSchema: normalizeSchema(definition.inputSchema, "input"),
26
- ...(definition.outputSchema === undefined
27
- ? {}
28
- : { outputSchema: normalizeSchema(definition.outputSchema, "output") }),
29
- });
30
- preparedSchemas.set(definition, normalized);
31
- return normalized;
32
- }
33
- /** Converts an accepted tool schema source into Harness's immutable runtime representation. */
34
- export function normalizeSchema(source, role) {
35
- const normalized = isZodSchema(source)
36
- ? normalizeZodSchema(source, role)
37
- : isStandardSchema(source)
38
- ? normalizeStandardSchema(source, role)
39
- : isToolSchema(source)
40
- ? normalizeExplicitSchema(source)
41
- : undefined;
42
- if (!normalized)
43
- throw new HarnessError("tool.invalid-schema", "Tool schema must be a Zod schema, synchronous Standard Schema with JSON Schema conversion, or defineSchema() contract");
44
- if (role === "input" && normalized.jsonSchema.type !== "object")
45
- throw new HarnessError("tool.invalid-schema", "Tool inputSchema JSON Schema root type must be object");
46
- return normalized;
47
- }
48
- function normalizeZodSchema(source, role) {
49
- if (hasDeclaredAsyncWork(source))
50
- throw new HarnessError("tool.invalid-schema", "Tool schema must validate synchronously");
51
- let jsonSchema;
52
- try {
53
- jsonSchema = copyJsonObject(z.toJSONSchema(source, { target: "draft-07" }), `tool.${role}Schema.jsonSchema`);
54
- }
55
- catch (error) {
56
- throw new HarnessError("tool.invalid-schema", `Tool ${role}Schema must convert to JSON Schema: ${message(error)}`, { cause: error });
57
- }
58
- return Object.freeze({
59
- jsonSchema,
60
- validate(value) {
61
- try {
62
- const result = source.safeParse(value);
63
- if (result.success)
64
- return { ok: true, value: result.data };
65
- return {
66
- ok: false,
67
- issues: Object.freeze(result.error.issues.map((entry) => issue(entry.path.filter(isPathSegment), entry.code, entry.message))),
68
- };
69
- }
70
- catch (error) {
71
- return { ok: false, issues: [issue([], "schema_error", synchronousIssue(error))] };
72
- }
73
- },
74
- });
75
- }
76
- function normalizeStandardSchema(source, role) {
77
- let jsonSchema;
78
- try {
79
- jsonSchema = copyJsonObject(role === "input"
80
- ? source["~standard"].jsonSchema.input()
81
- : source["~standard"].jsonSchema.output(), `tool.${role}Schema.jsonSchema`);
82
- }
83
- catch (error) {
84
- throw new HarnessError("tool.invalid-schema", `Tool ${role}Schema must convert to JSON Schema: ${message(error)}`, { cause: error });
85
- }
86
- return Object.freeze({
87
- jsonSchema,
88
- validate(value) {
89
- try {
90
- const result = source["~standard"].validate(value);
91
- if (isPromiseLike(result))
92
- return {
93
- ok: false,
94
- issues: [issue([], "async_validation", "Schema validation must be synchronous")],
95
- };
96
- if (result && typeof result === "object" && "issues" in result && result.issues)
97
- return { ok: false, issues: Object.freeze(result.issues.map(standardIssue)) };
98
- if (result && typeof result === "object" && "value" in result)
99
- return { ok: true, value: result.value };
100
- return {
101
- ok: false,
102
- issues: [issue([], "schema_error", "Standard Schema returned an invalid result")],
103
- };
104
- }
105
- catch (error) {
106
- return { ok: false, issues: [issue([], "schema_error", synchronousIssue(error))] };
107
- }
108
- },
109
- });
110
- }
111
- function normalizeExplicitSchema(source) {
112
- return Object.freeze({
113
- jsonSchema: copyJsonObject(source.jsonSchema, "tool schema jsonSchema"),
114
- validate(value) {
115
- try {
116
- const result = source.validate(value);
117
- if (isPromiseLike(result))
118
- return {
119
- ok: false,
120
- issues: [issue([], "async_validation", "Schema validation must be synchronous")],
121
- };
122
- if (!result || typeof result !== "object" || typeof result.ok !== "boolean")
123
- return {
124
- ok: false,
125
- issues: [issue([], "schema_error", "Tool schema returned an invalid result")],
126
- };
127
- if (result.ok)
128
- return { ok: true, value: result.value };
129
- return { ok: false, issues: Object.freeze(result.issues.map(normalizeIssue)) };
130
- }
131
- catch (error) {
132
- return { ok: false, issues: [issue([], "schema_error", synchronousIssue(error))] };
133
- }
134
- },
135
- });
136
- }
137
- function isZodSchema(value) {
138
- return value instanceof z.ZodType;
139
- }
140
- function isStandardSchema(value) {
141
- if (!value || typeof value !== "object" || !("~standard" in value))
142
- return false;
143
- const standard = value["~standard"];
144
- if (!standard || typeof standard !== "object")
145
- return false;
146
- const record = standard;
147
- if (typeof record.validate !== "function" ||
148
- !record.jsonSchema ||
149
- typeof record.jsonSchema !== "object")
150
- return false;
151
- const jsonSchema = record.jsonSchema;
152
- return typeof jsonSchema.input === "function" && typeof jsonSchema.output === "function";
153
- }
154
- function isToolSchema(value) {
155
- return (!!value &&
156
- typeof value === "object" &&
157
- "jsonSchema" in value &&
158
- "validate" in value &&
159
- typeof value.validate === "function");
160
- }
161
- /** Zod exposes declared checks in its stable v4 definition graph; reject async checks before a run. */
162
- function hasDeclaredAsyncWork(schema) {
163
- return visitDefinition(schema._zod?.def, new Set());
164
- }
165
- function visitDefinition(value, seen) {
166
- if (typeof value === "function")
167
- return value.constructor.name === "AsyncFunction";
168
- if (!value || typeof value !== "object")
169
- return false;
170
- if (seen.has(value))
171
- return false;
172
- seen.add(value);
173
- const nestedDefinition = value._zod?.def;
174
- if (nestedDefinition !== undefined && nestedDefinition !== value)
175
- return visitDefinition(nestedDefinition, seen);
176
- for (const item of Object.values(value)) {
177
- if (visitDefinition(item, seen))
178
- return true;
179
- }
180
- return false;
181
- }
182
- function standardIssue(value) {
183
- return issue(value.path?.filter(isPathSegment) ?? [], value.code ?? "invalid", value.message ?? "Invalid value");
184
- }
185
- function normalizeIssue(value) {
186
- return issue(value.path?.filter(isPathSegment) ?? [], value.code ?? "invalid", value.message ?? "Invalid value");
187
- }
188
- function issue(path, code, text) {
189
- return Object.freeze({ path: Object.freeze([...path]), code, message: text });
190
- }
191
- function isPathSegment(value) {
192
- return typeof value === "string" || typeof value === "number";
193
- }
194
- function isPromiseLike(value) {
195
- return (!!value && typeof value === "object" && typeof value.then === "function");
196
- }
197
- function synchronousIssue(error) {
198
- const reason = message(error);
199
- return reason.includes("Promise during synchronous parse")
200
- ? "Schema validation must be synchronous"
201
- : reason;
202
- }
203
- function message(error) {
204
- return error instanceof Error ? error.message : String(error);
205
- }
package/dist/errors.d.ts DELETED
@@ -1,17 +0,0 @@
1
- /** Machine-readable error raised by Harness-owned code. */
2
- export type HarnessErrorCode = "agent.build-failed" | "agent.lifecycle-sealed" | "capability.state.create-failed" | "capability.state.undeclared" | "context.invalid-item" | "context.invalid-item-type" | "context.invalid-order" | "context.invalid-reason" | "context.invalid-slot" | "interaction.invalid" | "interaction.missing-resume" | "interaction.uncorrelated-resume" | "input.invalid-content" | "output.invalid" | "output.invalid-schema" | "json.invalid-data" | "json.invalid-object" | "middleware.next-after-return" | "middleware.next-called-twice" | "middleware.request-mutators-revoked" | "model.candidate-missing" | "model.adapter-invalid-options" | "model.adapter-invalid-response" | "model.invalid-candidate" | "model.invalid-directive" | "model.unsupported-content" | "model.unsupported-output-schema" | "configuration.duplicate-tool-name" | "configuration.invalid" | "configuration.invalid-instructions" | "configuration.invalid-order" | "configuration.invalid-reason" | "configuration.invalid-slot" | "configuration.invalid-tools" | "configuration.model-selection-conflict" | "response.invalid-replacement" | "session.invalid-seed" | "session.record-failed" | "session.stale-result" | "tool.invalid" | "tool.invalid-arguments" | "tool.invalid-output" | "tool.invalid-name" | "tool.invalid-schema" | "tool.invalid-tool-result";
3
- export type HarnessErrorDetails = Readonly<Record<string, string | number | boolean>>;
4
- export interface HarnessErrorOptions {
5
- readonly cause?: unknown;
6
- readonly details?: HarnessErrorDetails;
7
- }
8
- /**
9
- * The sole error shape produced by Harness itself. Message text is explanatory;
10
- * callers must branch on `code`.
11
- */
12
- export declare class HarnessError extends Error {
13
- readonly code: HarnessErrorCode;
14
- readonly details: HarnessErrorDetails;
15
- constructor(code: HarnessErrorCode, message: string, options?: HarnessErrorOptions);
16
- }
17
- export declare function isHarnessError(error: unknown): error is HarnessError;
package/dist/errors.js DELETED
@@ -1,17 +0,0 @@
1
- /**
2
- * The sole error shape produced by Harness itself. Message text is explanatory;
3
- * callers must branch on `code`.
4
- */
5
- export class HarnessError extends Error {
6
- code;
7
- details;
8
- constructor(code, message, options = {}) {
9
- super(message, options.cause === undefined ? undefined : { cause: options.cause });
10
- this.name = "HarnessError";
11
- this.code = code;
12
- this.details = Object.freeze({ ...(options.details ?? {}) });
13
- }
14
- }
15
- export function isHarnessError(error) {
16
- return error instanceof HarnessError;
17
- }
@@ -1,14 +0,0 @@
1
- import type { BoundMiddleware } from "../types/middleware.js";
2
- import type { SessionIdentity } from "../types/session.js";
3
- import type { ObserveEmit } from "../utils/observe.js";
4
- /** Owns declared, process-local state for exactly one Session. */
5
- export declare class CapabilityStateRegistry {
6
- #private;
7
- private readonly session;
8
- private readonly observe;
9
- constructor(middleware: readonly BoundMiddleware[], session: SessionIdentity, observe: ObserveEmit);
10
- has(id: string): boolean;
11
- get(id: string): Promise<unknown>;
12
- abort(reason: unknown): void;
13
- shutdown(reason: unknown): Promise<void>;
14
- }
@@ -1,67 +0,0 @@
1
- import { HarnessError } from "../errors.js";
2
- /** Owns declared, process-local state for exactly one Session. */
3
- export class CapabilityStateRegistry {
4
- session;
5
- observe;
6
- #entries = new Map();
7
- #controller = new AbortController();
8
- #shutdown;
9
- constructor(middleware, session, observe) {
10
- this.session = session;
11
- this.observe = observe;
12
- for (const middlewareEntry of middleware) {
13
- if (middlewareEntry.state)
14
- this.#entries.set(middlewareEntry.id, {
15
- id: middlewareEntry.id,
16
- state: middlewareEntry.state,
17
- });
18
- }
19
- }
20
- has(id) {
21
- return this.#entries.has(id);
22
- }
23
- get(id) {
24
- const entry = this.#entries.get(id);
25
- if (!entry)
26
- return Promise.reject(new HarnessError("capability.state.undeclared", `Capability '${id}' did not declare session state`));
27
- if (!entry.promise) {
28
- entry.promise = Promise.resolve()
29
- .then(() => entry.state.create(this.session, this.#controller.signal))
30
- .then((value) => {
31
- entry.value = value;
32
- entry.created = true;
33
- return value;
34
- }, (cause) => {
35
- throw new HarnessError("capability.state.create-failed", `Capability '${id}' failed to create session state`, { cause });
36
- });
37
- }
38
- return entry.promise;
39
- }
40
- abort(reason) {
41
- this.#controller.abort(reason);
42
- }
43
- shutdown(reason) {
44
- if (this.#shutdown)
45
- return this.#shutdown;
46
- this.abort(reason);
47
- this.#shutdown = (async () => {
48
- const created = [...this.#entries.values()].filter((entry) => entry.promise);
49
- await Promise.allSettled(created.map((entry) => entry.promise));
50
- for (const entry of [...created].reverse()) {
51
- if (!entry.created || !entry.state.dispose)
52
- continue;
53
- try {
54
- await entry.state.dispose(entry.value);
55
- }
56
- catch (error) {
57
- this.observe({
58
- type: "capability.state.dispose.failed",
59
- capabilityId: entry.id,
60
- attributes: { message: error instanceof Error ? error.message : String(error) },
61
- });
62
- }
63
- }
64
- })();
65
- return this.#shutdown;
66
- }
67
- }
@@ -1,12 +0,0 @@
1
- import type { SessionEvent } from "../types/session.js";
2
- import type { JsonValue } from "../types/shared.js";
3
- /** Session-lifetime conversation log. Each stream() call replays from the start. */
4
- export declare class SessionEventLog implements AsyncIterable<SessionEvent<JsonValue>> {
5
- private readonly events;
6
- private readonly subscribers;
7
- private done;
8
- emit(event: SessionEvent<JsonValue>): void;
9
- finish(): void;
10
- [Symbol.asyncIterator](): AsyncIterator<SessionEvent<JsonValue>>;
11
- private wake;
12
- }
@@ -1,63 +0,0 @@
1
- /** Session-lifetime conversation log. Each stream() call replays from the start. */
2
- export class SessionEventLog {
3
- events = [];
4
- subscribers = [];
5
- done = false;
6
- emit(event) {
7
- if (this.done)
8
- return;
9
- this.events.push(event);
10
- this.wake();
11
- }
12
- finish() {
13
- if (this.done)
14
- return;
15
- this.done = true;
16
- this.wake();
17
- this.subscribers.length = 0;
18
- }
19
- [Symbol.asyncIterator]() {
20
- let index = 0;
21
- let closed = false;
22
- const waiting = [];
23
- this.subscribers.push(waiting);
24
- const detach = () => {
25
- const position = this.subscribers.indexOf(waiting);
26
- if (position !== -1)
27
- this.subscribers.splice(position, 1);
28
- };
29
- const complete = () => {
30
- closed = true;
31
- detach();
32
- return { done: true, value: undefined };
33
- };
34
- const pull = () => {
35
- if (closed)
36
- return Promise.resolve({ done: true, value: undefined });
37
- if (index < this.events.length)
38
- return Promise.resolve({ done: false, value: this.events[index++] });
39
- if (this.done)
40
- return Promise.resolve(complete());
41
- return new Promise((resolve) => {
42
- waiting.push(() => {
43
- void pull().then(resolve);
44
- });
45
- });
46
- };
47
- return {
48
- next: pull,
49
- return: () => {
50
- const result = complete();
51
- while (waiting.length)
52
- waiting.shift()();
53
- return Promise.resolve(result);
54
- },
55
- };
56
- }
57
- wake() {
58
- for (const waiting of this.subscribers) {
59
- while (waiting.length)
60
- waiting.shift()();
61
- }
62
- }
63
- }