@nylorun/harness 0.11.1-beta → 0.13.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.
- package/CHANGELOG.md +29 -0
- package/README.md +124 -5
- package/dist/definition/agent-definition.d.ts +11 -0
- package/dist/definition/agent-definition.js +12 -0
- package/dist/definition/assemble.d.ts +22 -0
- package/dist/{build → definition}/assemble.js +6 -7
- package/dist/definition/bind-agent.d.ts +9 -0
- package/dist/definition/bind-agent.js +21 -0
- package/dist/{build → definition}/bind-tool.d.ts +2 -1
- package/dist/{build → definition}/bind-tool.js +1 -0
- package/dist/definition/bound.d.ts +16 -0
- package/dist/definition/builder.d.ts +30 -0
- package/dist/definition/builder.js +94 -0
- package/dist/definition/declaration.d.ts +3 -0
- package/dist/definition/declaration.js +53 -0
- package/dist/{build → definition}/helpers.d.ts +1 -1
- package/dist/{build → definition}/manifest.d.ts +3 -1
- package/dist/definition/manifest.js +45 -0
- package/dist/{session → definition}/output-contract.d.ts +2 -2
- package/dist/{session → definition}/output-contract.js +1 -1
- package/dist/definition/registry.d.ts +10 -0
- package/dist/definition/registry.js +48 -0
- package/dist/{build → definition}/schema.d.ts +4 -4
- package/dist/errors.d.ts +1 -1
- package/dist/execution/dispatch.d.ts +2 -0
- package/dist/execution/dispatch.js +164 -0
- package/dist/execution/initial-state.d.ts +3 -0
- package/dist/execution/initial-state.js +14 -0
- package/dist/execution/invocation.d.ts +21 -0
- package/dist/execution/invocation.js +32 -0
- package/dist/{model → execution/model}/adapters.d.ts +2 -2
- package/dist/{model → execution/model}/adapters.js +2 -2
- package/dist/{model → execution/model}/normalize.d.ts +2 -2
- package/dist/{model → execution/model}/normalize.js +2 -2
- package/dist/{model → execution/model}/prepared.d.ts +3 -3
- package/dist/{step → execution/model}/project.d.ts +1 -1
- package/dist/{step → execution/model}/project.js +2 -10
- package/dist/execution/observe.d.ts +17 -0
- package/dist/execution/observe.js +53 -0
- package/dist/execution/options.d.ts +10 -0
- package/dist/execution/options.js +49 -0
- package/dist/execution/resume.d.ts +4 -0
- package/dist/execution/resume.js +52 -0
- package/dist/execution/run.d.ts +5 -0
- package/dist/execution/run.js +256 -0
- package/dist/execution/state.d.ts +8 -0
- package/dist/execution/state.js +208 -0
- package/dist/{step → execution/step}/canonicalize.d.ts +2 -2
- package/dist/{step → execution/step}/canonicalize.js +2 -2
- package/dist/{step → execution/step}/compose.d.ts +3 -2
- package/dist/{step → execution/step}/compose.js +5 -5
- package/dist/{step → execution/step}/context-draft.d.ts +3 -5
- package/dist/{step → execution/step}/context-draft.js +5 -22
- package/dist/execution/step/describe.d.ts +9 -0
- package/dist/execution/step/describe.js +22 -0
- package/dist/{step → execution/step}/model-configuration.d.ts +4 -3
- package/dist/{step → execution/step}/model-configuration.js +3 -3
- package/dist/execution/step/resolve.d.ts +11 -0
- package/dist/{step → execution/step}/resolve.js +5 -3
- package/dist/execution/step/run.d.ts +29 -0
- package/dist/{step → execution/step}/run.js +19 -53
- package/dist/execution/step/runtime.d.ts +32 -0
- package/dist/execution/step/runtime.js +1 -0
- package/dist/{step → execution/step}/seal.d.ts +13 -8
- package/dist/{step → execution/step}/seal.js +8 -6
- package/dist/{step → execution/step}/slot-assembly.d.ts +4 -4
- package/dist/{step → execution/step}/slot-assembly.js +4 -4
- package/dist/{step → execution/step}/step-context.d.ts +11 -12
- package/dist/{step → execution/step}/step-context.js +5 -27
- package/dist/execution/tool-result.d.ts +4 -0
- package/dist/execution/tool-result.js +30 -0
- package/dist/execution/transcript.d.ts +2 -0
- package/dist/{session/seed.js → execution/transcript.js} +9 -39
- package/dist/index.d.ts +15 -12
- package/dist/index.js +5 -5
- package/dist/types/agent.d.ts +9 -0
- package/dist/types/agent.js +1 -0
- package/dist/types/execution.d.ts +97 -0
- package/dist/types/execution.js +1 -0
- package/dist/types/manifest.d.ts +16 -13
- package/dist/types/middleware.d.ts +11 -40
- package/dist/types/model.d.ts +10 -10
- package/dist/types/observe.d.ts +165 -0
- package/dist/types/observe.js +1 -0
- package/dist/types/shared.d.ts +1 -225
- package/dist/types/tool.d.ts +21 -19
- package/dist/types/transcript.d.ts +65 -0
- package/dist/types/transcript.js +1 -0
- package/dist/utils/canonical.d.ts +1 -0
- package/dist/utils/canonical.js +10 -0
- package/dist/utils/immutable.d.ts +1 -0
- package/dist/utils/immutable.js +8 -0
- package/package.json +5 -5
- package/dist/build/agent.d.ts +0 -18
- package/dist/build/agent.js +0 -37
- package/dist/build/assemble.d.ts +0 -8
- package/dist/build/builder.d.ts +0 -46
- package/dist/build/builder.js +0 -151
- package/dist/build/manifest.js +0 -20
- package/dist/session/capability-state.d.ts +0 -14
- package/dist/session/capability-state.js +0 -67
- package/dist/session/event-log.d.ts +0 -12
- package/dist/session/event-log.js +0 -63
- package/dist/session/input-queue.d.ts +0 -41
- package/dist/session/input-queue.js +0 -94
- package/dist/session/record.d.ts +0 -11
- package/dist/session/record.js +0 -26
- package/dist/session/scheduler.d.ts +0 -62
- package/dist/session/scheduler.js +0 -485
- package/dist/session/seed.d.ts +0 -10
- package/dist/session/session.d.ts +0 -18
- package/dist/session/session.js +0 -103
- package/dist/session/state.d.ts +0 -15
- package/dist/session/state.js +0 -48
- package/dist/session/submission-stream.d.ts +0 -16
- package/dist/session/submission-stream.js +0 -46
- package/dist/step/resolve.d.ts +0 -10
- package/dist/step/run.d.ts +0 -33
- package/dist/turn/plan-runner.d.ts +0 -70
- package/dist/turn/plan-runner.js +0 -388
- package/dist/turn/runner.d.ts +0 -69
- package/dist/turn/runner.js +0 -158
- package/dist/types/session.d.ts +0 -227
- package/dist/utils/maps.d.ts +0 -1
- package/dist/utils/maps.js +0 -37
- package/dist/utils/observe.d.ts +0 -8
- package/dist/utils/observe.js +0 -29
- /package/dist/{types/session.js → definition/bound.js} +0 -0
- /package/dist/{build → definition}/helpers.js +0 -0
- /package/dist/{build → definition}/schema.js +0 -0
- /package/dist/{model → execution/model}/prepared.js +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TurnOutputContract } from "../../definition/output-contract.js";
|
|
2
|
+
import type { InputEvent } from "../../types/transcript.js";
|
|
3
|
+
import type { ModelRequest } from "../../types/model.js";
|
|
4
|
+
import type { ToolResult } from "../../types/tool.js";
|
|
5
|
+
import type { StepContext } from "./step-context.js";
|
|
6
|
+
export declare function resolveModelRequest(input: {
|
|
7
|
+
context: StepContext;
|
|
8
|
+
arrivals: readonly InputEvent[];
|
|
9
|
+
toolResults: readonly ToolResult[];
|
|
10
|
+
output?: TurnOutputContract;
|
|
11
|
+
}): ModelRequest;
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
import { describeConfiguration } from "./describe.js";
|
|
1
2
|
export function resolveModelRequest(input) {
|
|
2
3
|
const ctx = input.context;
|
|
4
|
+
const configuration = describeConfiguration(ctx.configurationSnapshot());
|
|
3
5
|
return Object.freeze({
|
|
4
|
-
|
|
6
|
+
executionId: ctx.input.executionId,
|
|
5
7
|
turnId: ctx.input.turnId,
|
|
6
8
|
stepId: ctx.input.stepId,
|
|
7
9
|
...(ctx.selectedDirective === undefined ? {} : { model: ctx.selectedDirective }),
|
|
8
|
-
configuration
|
|
10
|
+
configuration,
|
|
9
11
|
instructions: Object.freeze([...ctx.instructions]),
|
|
10
12
|
context: ctx.contextSnapshot(),
|
|
11
13
|
transcript: Object.freeze([...ctx.input.transcript]),
|
|
12
14
|
arrivals: Object.freeze([...input.arrivals]),
|
|
13
15
|
toolResults: Object.freeze([...input.toolResults]),
|
|
14
|
-
tools:
|
|
16
|
+
tools: configuration.tools,
|
|
15
17
|
...(input.output === undefined ? {} : { outputSchema: input.output.schema.jsonSchema }),
|
|
16
18
|
});
|
|
17
19
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ExecutionSnapshot, StepRuntime } from "./runtime.js";
|
|
2
|
+
import type { TurnOutputContract } from "../../definition/output-contract.js";
|
|
3
|
+
import type { ModelCandidate } from "../../types/model.js";
|
|
4
|
+
import type { InputEvent } from "../../types/transcript.js";
|
|
5
|
+
import type { ToolResult } from "../../types/tool.js";
|
|
6
|
+
import type { ObserveEmit } from "../observe.js";
|
|
7
|
+
import { type SealedStepOutput } from "./seal.js";
|
|
8
|
+
export interface StepRunResult {
|
|
9
|
+
readonly stepId: string;
|
|
10
|
+
readonly candidate?: ModelCandidate;
|
|
11
|
+
readonly output: SealedStepOutput;
|
|
12
|
+
readonly requestedModelId?: string;
|
|
13
|
+
readonly modelInvocationId?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function runStep(input: {
|
|
16
|
+
agent: StepRuntime;
|
|
17
|
+
observe: ObserveEmit;
|
|
18
|
+
state: ExecutionSnapshot;
|
|
19
|
+
executionId: string;
|
|
20
|
+
turnId: string;
|
|
21
|
+
stepId: string;
|
|
22
|
+
turnNumber: number;
|
|
23
|
+
stepNumber: number;
|
|
24
|
+
arrivals: readonly InputEvent[];
|
|
25
|
+
toolResults: readonly ToolResult[];
|
|
26
|
+
signal: AbortSignal;
|
|
27
|
+
info?: unknown;
|
|
28
|
+
output?: TurnOutputContract;
|
|
29
|
+
}): Promise<StepRunResult>;
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
import { normalizeCandidate } from "../model/normalize.js";
|
|
2
|
-
import { HarnessError, isHarnessError } from "
|
|
3
|
-
import { copyJson } from "
|
|
2
|
+
import { HarnessError, isHarnessError } from "../../errors.js";
|
|
3
|
+
import { copyJson } from "../../utils/immutable.js";
|
|
4
4
|
import { runMiddleware } from "./compose.js";
|
|
5
5
|
import { ContextDraft } from "./context-draft.js";
|
|
6
6
|
import { StepContext } from "./step-context.js";
|
|
7
|
-
import { projectModelCall } from "
|
|
7
|
+
import { projectModelCall } from "../model/project.js";
|
|
8
8
|
import { resolveModelRequest } from "./resolve.js";
|
|
9
9
|
import { sealStep } from "./seal.js";
|
|
10
10
|
import { ModelConfigurationDraft } from "./model-configuration.js";
|
|
11
|
-
import { createId } from "
|
|
11
|
+
import { createId } from "../../utils/ids.js";
|
|
12
12
|
export async function runStep(input) {
|
|
13
|
-
let state = input.state;
|
|
14
13
|
let requestedModelId;
|
|
14
|
+
let modelInvocationId;
|
|
15
15
|
const stepInput = Object.freeze({
|
|
16
|
-
|
|
16
|
+
executionId: input.executionId,
|
|
17
17
|
turnId: input.turnId,
|
|
18
18
|
stepId: input.stepId,
|
|
19
19
|
turnNumber: input.turnNumber,
|
|
20
20
|
stepNumber: input.stepNumber,
|
|
21
|
-
|
|
21
|
+
info: input.info,
|
|
22
22
|
arrivals: Object.freeze([...input.arrivals]),
|
|
23
23
|
toolResults: Object.freeze([...input.toolResults]),
|
|
24
24
|
transcript: Object.freeze([...input.state.transcript]),
|
|
25
25
|
});
|
|
26
26
|
const configuration = new ModelConfigurationDraft();
|
|
27
|
-
const runtimeContext = new ContextDraft(
|
|
28
|
-
const context = new StepContext(stepInput, input.observe, configuration, runtimeContext
|
|
27
|
+
const runtimeContext = new ContextDraft();
|
|
28
|
+
const context = new StepContext(stepInput, input.observe, configuration, runtimeContext);
|
|
29
29
|
input.observe(() => ({
|
|
30
30
|
type: "step.started",
|
|
31
31
|
turnId: input.turnId,
|
|
@@ -35,10 +35,14 @@ export async function runStep(input) {
|
|
|
35
35
|
attributes: snapshotStepStart(stepInput),
|
|
36
36
|
}));
|
|
37
37
|
await runMiddleware(input.agent.middleware, context, async () => {
|
|
38
|
+
input.signal.throwIfAborted();
|
|
38
39
|
if (context.currentTripwire)
|
|
39
40
|
return context.tripwire(context.currentTripwire);
|
|
40
41
|
try {
|
|
41
|
-
|
|
42
|
+
const selected = configuration.snapshot();
|
|
43
|
+
for (const tool of selected.tools)
|
|
44
|
+
input.agent.registry.reference(tool);
|
|
45
|
+
context.sealConfiguration(selected);
|
|
42
46
|
context.sealContext(runtimeContext.snapshot());
|
|
43
47
|
}
|
|
44
48
|
catch (error) {
|
|
@@ -57,16 +61,10 @@ export async function runStep(input) {
|
|
|
57
61
|
requestedModelId = request.model?.id;
|
|
58
62
|
const call = projectModelCall(request);
|
|
59
63
|
const invocationId = createId("invocation");
|
|
60
|
-
|
|
61
|
-
kind: "model",
|
|
62
|
-
turnId: input.turnId,
|
|
63
|
-
stepId: input.stepId,
|
|
64
|
-
invocationId,
|
|
65
|
-
call,
|
|
66
|
-
});
|
|
67
|
-
state = await input.recordModelRequested(state, active);
|
|
64
|
+
modelInvocationId = invocationId;
|
|
68
65
|
input.observe(() => ({
|
|
69
66
|
type: "model.requested",
|
|
67
|
+
invocationId,
|
|
70
68
|
turnId: input.turnId,
|
|
71
69
|
stepId: input.stepId,
|
|
72
70
|
...(request.model?.id === undefined ? {} : { requestedModelId: request.model.id }),
|
|
@@ -91,6 +89,7 @@ export async function runStep(input) {
|
|
|
91
89
|
const reported = Object.freeze({ adapter: value.adapter, call: copyJson(value.call) });
|
|
92
90
|
input.observe(() => ({
|
|
93
91
|
type: "model.prepared",
|
|
92
|
+
invocationId,
|
|
94
93
|
turnId: input.turnId,
|
|
95
94
|
stepId: input.stepId,
|
|
96
95
|
...(request.model?.id === undefined ? {} : { requestedModelId: request.model.id }),
|
|
@@ -100,11 +99,6 @@ export async function runStep(input) {
|
|
|
100
99
|
});
|
|
101
100
|
if (input.signal.aborted)
|
|
102
101
|
throw input.signal.reason;
|
|
103
|
-
if (isDeferred(outcome))
|
|
104
|
-
return context.deferModel(Object.freeze({
|
|
105
|
-
...active,
|
|
106
|
-
...(outcome.token === undefined ? {} : { token: copyJson(outcome.token) }),
|
|
107
|
-
}));
|
|
108
102
|
const minted = context.mintFromModel(normalizeCandidate(outcome));
|
|
109
103
|
const candidate = context.currentCandidate;
|
|
110
104
|
if (!candidate)
|
|
@@ -124,47 +118,19 @@ export async function runStep(input) {
|
|
|
124
118
|
const candidate = output.kind === "tools" ? output.plan.candidate : context.currentCandidate;
|
|
125
119
|
return Object.freeze({
|
|
126
120
|
stepId: input.stepId,
|
|
127
|
-
state,
|
|
128
121
|
...(candidate ? { candidate } : {}),
|
|
129
122
|
...(requestedModelId === undefined ? {} : { requestedModelId }),
|
|
130
123
|
output,
|
|
124
|
+
...(modelInvocationId ? { modelInvocationId } : {}),
|
|
131
125
|
});
|
|
132
126
|
}
|
|
133
|
-
function isDeferred(value) {
|
|
134
|
-
return (typeof value === "object" && value !== null && "kind" in value && value.kind === "deferred");
|
|
135
|
-
}
|
|
136
127
|
function snapshotStepStart(input) {
|
|
137
|
-
const session = Object.freeze({
|
|
138
|
-
...(input.session.userId === undefined ? {} : { userId: input.session.userId }),
|
|
139
|
-
...(input.session.context === undefined ? {} : { context: copyJson(input.session.context) }),
|
|
140
|
-
});
|
|
141
128
|
return Object.freeze({
|
|
142
|
-
...(Object.keys(session).length === 0 ? {} : { session }),
|
|
143
129
|
arrivals: copyJson(input.arrivals),
|
|
144
130
|
toolResults: copyJson(input.toolResults),
|
|
145
131
|
transcript: input.transcript,
|
|
146
132
|
});
|
|
147
133
|
}
|
|
148
134
|
function snapshotConfiguration(configuration) {
|
|
149
|
-
return
|
|
150
|
-
version: configuration.version,
|
|
151
|
-
...(configuration.model === undefined ? {} : { model: copyJson(configuration.model) }),
|
|
152
|
-
instructions: copyJson(configuration.instructions),
|
|
153
|
-
tools: snapshotTools(configuration.tools),
|
|
154
|
-
toolContracts: copyJson(configuration.toolContracts),
|
|
155
|
-
contributors: copyJson(configuration.contributors),
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
function snapshotTools(tools) {
|
|
159
|
-
return Object.freeze(tools.map((tool) => Object.freeze({
|
|
160
|
-
name: tool.name,
|
|
161
|
-
...(tool.description === undefined ? {} : { description: tool.description }),
|
|
162
|
-
owner: tool.owner,
|
|
163
|
-
inputSchema: Object.freeze({ jsonSchema: copyJson(tool.inputSchema.jsonSchema) }),
|
|
164
|
-
...(tool.outputSchema === undefined
|
|
165
|
-
? {}
|
|
166
|
-
: {
|
|
167
|
-
outputSchema: Object.freeze({ jsonSchema: copyJson(tool.outputSchema.jsonSchema) }),
|
|
168
|
-
}),
|
|
169
|
-
})));
|
|
135
|
+
return copyJson(configuration);
|
|
170
136
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ToolRegistry } from "../../definition/registry.js";
|
|
2
|
+
import type { ModelAdapter } from "../../types/model.js";
|
|
3
|
+
import type { InputEvent, TranscriptEntry } from "../../types/transcript.js";
|
|
4
|
+
import type { ToolResult } from "../../types/tool.js";
|
|
5
|
+
import type { BoundMiddleware } from "../../definition/bound.js";
|
|
6
|
+
/** Compiled definition pieces plus the per-run model adapter for one step. */
|
|
7
|
+
export interface StepRuntime {
|
|
8
|
+
readonly middleware: readonly BoundMiddleware[];
|
|
9
|
+
readonly invoke: ModelAdapter;
|
|
10
|
+
readonly registry: ToolRegistry;
|
|
11
|
+
}
|
|
12
|
+
export interface StepInput {
|
|
13
|
+
readonly executionId: string;
|
|
14
|
+
readonly turnId: string;
|
|
15
|
+
readonly stepId: string;
|
|
16
|
+
/** One-based position of this turn within the execution. */
|
|
17
|
+
readonly turnNumber: number;
|
|
18
|
+
/** One-based position of this Model Step within the Turn. */
|
|
19
|
+
readonly stepNumber: number;
|
|
20
|
+
readonly info?: unknown;
|
|
21
|
+
readonly arrivals: readonly InputEvent[];
|
|
22
|
+
readonly toolResults: readonly ToolResult[];
|
|
23
|
+
readonly transcript: readonly TranscriptEntry[];
|
|
24
|
+
}
|
|
25
|
+
/** Internal view consumed by a single model step. */
|
|
26
|
+
export interface ExecutionSnapshot {
|
|
27
|
+
readonly id: string;
|
|
28
|
+
readonly status: "running";
|
|
29
|
+
readonly turnCount: number;
|
|
30
|
+
readonly revision: number;
|
|
31
|
+
readonly transcript: readonly TranscriptEntry[];
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import type { BoundToolDefinition } from "../../definition/bound.js";
|
|
2
|
+
import type { ModelCandidate } from "../../types/model.js";
|
|
3
|
+
import type { JsonValue, Tripwire } from "../../types/shared.js";
|
|
4
|
+
import type { RequiredInteraction, ToolOwner, ToolResult } from "../../types/tool.js";
|
|
4
5
|
import type { StepContext } from "./step-context.js";
|
|
5
|
-
import type { TurnOutputContract } from "
|
|
6
|
+
import type { TurnOutputContract } from "../../definition/output-contract.js";
|
|
7
|
+
export interface SealedToolCall {
|
|
8
|
+
readonly callId: string;
|
|
9
|
+
readonly toolName: string;
|
|
10
|
+
readonly args: JsonValue;
|
|
11
|
+
}
|
|
6
12
|
export interface ExecutablePlanEntry {
|
|
13
|
+
readonly definition: BoundToolDefinition;
|
|
14
|
+
readonly rawArgs: JsonValue;
|
|
7
15
|
readonly call: SealedToolCall;
|
|
8
16
|
readonly invocationId: string;
|
|
9
17
|
readonly owner: ToolOwner;
|
|
@@ -25,10 +33,7 @@ export type SealedStepOutput = {
|
|
|
25
33
|
readonly tripwire: Tripwire;
|
|
26
34
|
} | {
|
|
27
35
|
readonly kind: "final";
|
|
28
|
-
readonly output:
|
|
29
|
-
} | {
|
|
30
|
-
readonly kind: "deferred-model";
|
|
31
|
-
readonly active: import("../types/session.js").ActiveModelExecutionRecord;
|
|
36
|
+
readonly output: JsonValue;
|
|
32
37
|
} | {
|
|
33
38
|
readonly kind: "tools";
|
|
34
39
|
readonly plan: InternalToolPlan;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { textFromOutput } from "../model/normalize.js";
|
|
2
|
-
import { createId } from "
|
|
3
|
-
import { HarnessError, isHarnessError } from "
|
|
4
|
-
import { assertJson, copyJson } from "
|
|
2
|
+
import { createId } from "../../utils/ids.js";
|
|
3
|
+
import { HarnessError, isHarnessError } from "../../errors.js";
|
|
4
|
+
import { assertJson, copyJson } from "../../utils/immutable.js";
|
|
5
5
|
const failed = (callId, toolName, code, message, details) => Object.freeze({
|
|
6
6
|
kind: "failed",
|
|
7
7
|
callId,
|
|
@@ -14,8 +14,6 @@ const failed = (callId, toolName, code, message, details) => Object.freeze({
|
|
|
14
14
|
export function sealStep(context, outputContract) {
|
|
15
15
|
if (context.currentTripwire)
|
|
16
16
|
return Object.freeze({ kind: "tripwire", tripwire: context.currentTripwire });
|
|
17
|
-
if (context.currentModelDeferred)
|
|
18
|
-
return Object.freeze({ kind: "deferred-model", active: context.currentModelDeferred });
|
|
19
17
|
const calls = context.canonicalCalls();
|
|
20
18
|
if (!calls.length) {
|
|
21
19
|
if (outputContract)
|
|
@@ -45,7 +43,9 @@ function sealStructuredOutput(context, contract) {
|
|
|
45
43
|
return invalidOutput("Structured terminal output must contain exactly one JSON block and no text blocks");
|
|
46
44
|
const validation = contract.schema.validate(json[0].value);
|
|
47
45
|
if (!validation.ok)
|
|
48
|
-
return invalidOutput(`Structured terminal output failed validation: ${validation.issues
|
|
46
|
+
return invalidOutput(`Structured terminal output failed validation: ${validation.issues
|
|
47
|
+
.map(renderIssue)
|
|
48
|
+
.join("; ")}`);
|
|
49
49
|
try {
|
|
50
50
|
assertJson(validation.value, "structured terminal output");
|
|
51
51
|
return Object.freeze({ kind: "final", output: copyJson(validation.value) });
|
|
@@ -113,6 +113,8 @@ function sealCall(context, catalog, candidate) {
|
|
|
113
113
|
order,
|
|
114
114
|
canonical,
|
|
115
115
|
executable: Object.freeze({
|
|
116
|
+
definition: tool,
|
|
117
|
+
rawArgs: copyJson(candidate.args),
|
|
116
118
|
call: Object.freeze({
|
|
117
119
|
callId: candidate.id,
|
|
118
120
|
toolName: candidate.name,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type HarnessErrorCode } from "
|
|
1
|
+
import { type HarnessErrorCode } from "../../errors.js";
|
|
2
2
|
export interface SlotOwner {
|
|
3
3
|
readonly middlewareId: string;
|
|
4
4
|
readonly middlewareOrder: number;
|
|
@@ -11,9 +11,9 @@ export interface SlotDeclaration<Value> {
|
|
|
11
11
|
readonly reason?: string;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* Shared per-step slot store.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* Shared per-step slot store. Declarations are discarded with the draft that owns this instance.
|
|
15
|
+
* Configuration and context supply their typed values and snapshot them after this assembler has
|
|
16
|
+
* applied ownership, replacement, and canonical ordering.
|
|
17
17
|
*/
|
|
18
18
|
export declare class SlotDraft<Value> {
|
|
19
19
|
#private;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { HarnessError } from "
|
|
1
|
+
import { HarnessError } from "../../errors.js";
|
|
2
2
|
/**
|
|
3
|
-
* Shared per-step slot store.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Shared per-step slot store. Declarations are discarded with the draft that owns this instance.
|
|
4
|
+
* Configuration and context supply their typed values and snapshot them after this assembler has
|
|
5
|
+
* applied ownership, replacement, and canonical ordering.
|
|
6
6
|
*/
|
|
7
7
|
export class SlotDraft {
|
|
8
8
|
#slots = new Map();
|
|
@@ -1,35 +1,34 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { StepInput
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
1
|
+
import type { BoundToolDefinition } from "../../definition/bound.js";
|
|
2
|
+
import type { StepInput } from "./runtime.js";
|
|
3
|
+
import type { InternalModelConfigurationSnapshot } from "./describe.js";
|
|
4
|
+
import type { ContextSnapshot, ModelCandidate, ModelDirective } from "../../types/model.js";
|
|
5
|
+
import type { StepRequest, StepResponse } from "../../types/middleware.js";
|
|
6
|
+
import type { Tripwire } from "../../types/shared.js";
|
|
7
|
+
import type { ObserveEmit } from "../observe.js";
|
|
8
|
+
import type { Interaction } from "../../types/tool.js";
|
|
7
9
|
import { type CanonicalCall } from "./canonicalize.js";
|
|
8
10
|
import { ContextDraft } from "./context-draft.js";
|
|
9
11
|
import { ModelConfigurationDraft } from "./model-configuration.js";
|
|
10
|
-
import type { CapabilityStateRegistry } from "../session/capability-state.js";
|
|
11
12
|
export declare function isBrandedResponse(value: unknown): value is StepResponse;
|
|
12
13
|
/** Mutable Step state. Middleware receives leased request views and one branded response. */
|
|
13
14
|
export declare class StepContext {
|
|
14
15
|
#private;
|
|
15
16
|
readonly input: Readonly<StepInput>;
|
|
16
|
-
constructor(input: Readonly<StepInput>, observe: ObserveEmit, configuration: ModelConfigurationDraft, context: ContextDraft
|
|
17
|
+
constructor(input: Readonly<StepInput>, observe: ObserveEmit, configuration: ModelConfigurationDraft, context: ContextDraft);
|
|
17
18
|
get currentTripwire(): Tripwire | undefined;
|
|
18
19
|
get currentCandidate(): Readonly<ModelCandidate> | undefined;
|
|
19
|
-
get currentModelDeferred(): ActiveModelExecutionRecord | undefined;
|
|
20
20
|
get selectedDirective(): ModelDirective | undefined;
|
|
21
21
|
get instructions(): readonly string[];
|
|
22
22
|
contextSnapshot(): ContextSnapshot;
|
|
23
23
|
get offeredTools(): readonly BoundToolDefinition[];
|
|
24
24
|
get catalogByName(): ReadonlyMap<string, BoundToolDefinition>;
|
|
25
|
-
configurationSnapshot():
|
|
26
|
-
sealConfiguration(snapshot:
|
|
25
|
+
configurationSnapshot(): InternalModelConfigurationSnapshot;
|
|
26
|
+
sealConfiguration(snapshot: InternalModelConfigurationSnapshot): void;
|
|
27
27
|
sealContext(snapshot: ContextSnapshot): void;
|
|
28
28
|
denialFor(callId: string): string | undefined;
|
|
29
29
|
interactionFor(callId: string): Interaction | undefined;
|
|
30
30
|
canonicalCalls(): readonly CanonicalCall[];
|
|
31
31
|
mintFromModel(candidate: Readonly<ModelCandidate>): StepResponse;
|
|
32
|
-
deferModel(active: ActiveModelExecutionRecord): StepResponse;
|
|
33
32
|
tripwire(error: Tripwire): StepResponse;
|
|
34
33
|
seal(): void;
|
|
35
34
|
requestFacade(middlewareId: string, middlewareOrder: number): {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { HarnessError, isHarnessError } from "
|
|
1
|
+
import { HarnessError, isHarnessError } from "../../errors.js";
|
|
2
|
+
import { freezeGraph } from "../../utils/immutable.js";
|
|
2
3
|
import { callsFromCanonical, candidateFromCanonical, canonicalizeOutput, identityKey, } from "./canonicalize.js";
|
|
3
4
|
import { normalizeCandidate } from "../model/normalize.js";
|
|
4
5
|
import { ContextDraft } from "./context-draft.js";
|
|
@@ -13,24 +14,21 @@ export class StepContext {
|
|
|
13
14
|
#observe;
|
|
14
15
|
#context;
|
|
15
16
|
#configuration;
|
|
16
|
-
#states;
|
|
17
17
|
#denials = new Map();
|
|
18
18
|
#interactions = new Map();
|
|
19
19
|
#identities = new Map();
|
|
20
20
|
#canonical = Object.freeze([]);
|
|
21
21
|
#candidate;
|
|
22
22
|
#tripwire;
|
|
23
|
-
#modelDeferred;
|
|
24
23
|
#response;
|
|
25
24
|
#sealed = false;
|
|
26
25
|
#configurationSnapshot;
|
|
27
26
|
#contextSnapshot;
|
|
28
|
-
constructor(input, observe, configuration, context
|
|
27
|
+
constructor(input, observe, configuration, context) {
|
|
29
28
|
this.input = input;
|
|
30
29
|
this.#observe = observe;
|
|
31
30
|
this.#configuration = configuration;
|
|
32
31
|
this.#context = context;
|
|
33
|
-
this.#states = states;
|
|
34
32
|
}
|
|
35
33
|
get currentTripwire() {
|
|
36
34
|
return this.#tripwire;
|
|
@@ -38,9 +36,6 @@ export class StepContext {
|
|
|
38
36
|
get currentCandidate() {
|
|
39
37
|
return this.#candidate;
|
|
40
38
|
}
|
|
41
|
-
get currentModelDeferred() {
|
|
42
|
-
return this.#modelDeferred;
|
|
43
|
-
}
|
|
44
39
|
get selectedDirective() {
|
|
45
40
|
return this.configurationSnapshot().model;
|
|
46
41
|
}
|
|
@@ -83,10 +78,6 @@ export class StepContext {
|
|
|
83
78
|
this.#identities.set(call.id, identityKey(call.name, call.args));
|
|
84
79
|
return this.#ensureResponse();
|
|
85
80
|
}
|
|
86
|
-
deferModel(active) {
|
|
87
|
-
this.#modelDeferred = active;
|
|
88
|
-
return this.#ensureResponse();
|
|
89
|
-
}
|
|
90
81
|
tripwire(error) {
|
|
91
82
|
this.#tripwire ??= Object.freeze({ ...error });
|
|
92
83
|
return this.#ensureResponse();
|
|
@@ -138,10 +129,10 @@ export class StepContext {
|
|
|
138
129
|
}
|
|
139
130
|
});
|
|
140
131
|
const request = {
|
|
141
|
-
|
|
132
|
+
executionId: this.input.executionId,
|
|
142
133
|
turnId: this.input.turnId,
|
|
143
134
|
stepId: this.input.stepId,
|
|
144
|
-
|
|
135
|
+
info: this.input.info,
|
|
145
136
|
turnNumber: this.input.turnNumber,
|
|
146
137
|
stepNumber: this.input.stepNumber,
|
|
147
138
|
arrivals: this.input.arrivals,
|
|
@@ -171,11 +162,6 @@ export class StepContext {
|
|
|
171
162
|
return minted;
|
|
172
163
|
},
|
|
173
164
|
};
|
|
174
|
-
if (this.#states?.has(middlewareId))
|
|
175
|
-
Object.defineProperty(request, "state", {
|
|
176
|
-
enumerable: true,
|
|
177
|
-
get: () => this.#states.get(middlewareId),
|
|
178
|
-
});
|
|
179
165
|
const value = Object.freeze(request);
|
|
180
166
|
return Object.freeze({
|
|
181
167
|
value,
|
|
@@ -253,11 +239,3 @@ function pickSidecar(key, replacement, normalized, current) {
|
|
|
253
239
|
const value = source?.[key];
|
|
254
240
|
return value === undefined ? {} : { [key]: value };
|
|
255
241
|
}
|
|
256
|
-
function freezeGraph(value, seen = new WeakSet()) {
|
|
257
|
-
if (!value || typeof value !== "object" || seen.has(value))
|
|
258
|
-
return value;
|
|
259
|
-
seen.add(value);
|
|
260
|
-
for (const item of Object.values(value))
|
|
261
|
-
freezeGraph(item, seen);
|
|
262
|
-
return Object.freeze(value);
|
|
263
|
-
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { BoundToolDefinition } from "../definition/bound.js";
|
|
2
|
+
import type { SavedToolCall } from "../types/execution.js";
|
|
3
|
+
import type { ToolOutcome, ToolResult } from "../types/tool.js";
|
|
4
|
+
export declare function toolResult(call: SavedToolCall, definition: BoundToolDefinition, outcome: ToolOutcome): ToolResult;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { HarnessError } from "../errors.js";
|
|
2
|
+
import { copyJson } from "../utils/immutable.js";
|
|
3
|
+
export function toolResult(call, definition, outcome) {
|
|
4
|
+
const identity = { callId: call.callId, toolName: call.toolName };
|
|
5
|
+
if (outcome.kind === "completed") {
|
|
6
|
+
const checked = definition.outputSchema?.validate(outcome.output);
|
|
7
|
+
if (checked && !checked.ok)
|
|
8
|
+
return {
|
|
9
|
+
...identity,
|
|
10
|
+
kind: "failed",
|
|
11
|
+
code: "tool.invalid-output",
|
|
12
|
+
message: checked.issues.map((issue) => issue.message).join("; "),
|
|
13
|
+
details: { phase: "output", issues: checked.issues },
|
|
14
|
+
};
|
|
15
|
+
return copyJson({
|
|
16
|
+
...identity,
|
|
17
|
+
kind: "completed",
|
|
18
|
+
output: checked?.ok ? checked.value : outcome.output,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (outcome.kind === "failed" &&
|
|
22
|
+
typeof outcome.code === "string" &&
|
|
23
|
+
typeof outcome.message === "string")
|
|
24
|
+
return copyJson({ ...identity, kind: "failed", code: outcome.code, message: outcome.message });
|
|
25
|
+
if (outcome.kind === "denied" && typeof outcome.reason !== "string")
|
|
26
|
+
throw new HarnessError("tool.invalid-tool-result", "Tool denial reason must be a string");
|
|
27
|
+
if (outcome.kind === "denied" && typeof outcome.reason === "string")
|
|
28
|
+
return copyJson({ ...identity, kind: "denied", reason: outcome.reason });
|
|
29
|
+
throw new HarnessError("tool.invalid-tool-result", "Expected a completed, failed, or denied tool result");
|
|
30
|
+
}
|
|
@@ -1,39 +1,20 @@
|
|
|
1
1
|
import { HarnessError } from "../errors.js";
|
|
2
|
-
import { normalizeCandidate } from "
|
|
2
|
+
import { normalizeCandidate } from "./model/normalize.js";
|
|
3
3
|
import { assertJson, copyJson, copyJsonObject } from "../utils/immutable.js";
|
|
4
|
-
export function
|
|
4
|
+
export function validateTranscript(value) {
|
|
5
5
|
try {
|
|
6
|
-
|
|
6
|
+
if (!Array.isArray(value))
|
|
7
|
+
fail("Transcript must be an array");
|
|
8
|
+
return Object.freeze(value.map((entry, index) => entryAt(entry, index)));
|
|
7
9
|
}
|
|
8
10
|
catch (cause) {
|
|
9
|
-
if (cause instanceof HarnessError && cause.code === "
|
|
11
|
+
if (cause instanceof HarnessError && cause.code === "execution.invalid-state")
|
|
10
12
|
throw cause;
|
|
11
|
-
throw new HarnessError("
|
|
13
|
+
throw new HarnessError("execution.invalid-state", "Transcript contains invalid typed JSON", {
|
|
12
14
|
cause,
|
|
13
15
|
});
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
|
-
function normalizeSeed(seed) {
|
|
17
|
-
if (!seed || typeof seed !== "object")
|
|
18
|
-
fail("Session seed must be an object");
|
|
19
|
-
if (!Array.isArray(seed.transcript))
|
|
20
|
-
fail("Session seed transcript must be an array");
|
|
21
|
-
optionalString(seed.id, "Session seed id");
|
|
22
|
-
optionalString(seed.userId, "Session seed userId");
|
|
23
|
-
const turnCount = count(seed.turnCount, "turnCount");
|
|
24
|
-
const revision = count(seed.revision, "revision");
|
|
25
|
-
const transcript = Object.freeze(seed.transcript.map((entry, index) => entryAt(entry, index)));
|
|
26
|
-
return Object.freeze({
|
|
27
|
-
...(seed.id === undefined ? {} : { id: seed.id }),
|
|
28
|
-
...(seed.userId === undefined ? {} : { userId: seed.userId }),
|
|
29
|
-
...(seed.context === undefined
|
|
30
|
-
? {}
|
|
31
|
-
: { context: copyJsonObject(seed.context, "session seed context") }),
|
|
32
|
-
turnCount,
|
|
33
|
-
revision,
|
|
34
|
-
transcript,
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
18
|
function entryAt(value, index) {
|
|
38
19
|
if (!value || typeof value !== "object")
|
|
39
20
|
fail(`Transcript entry ${index} must be an object`);
|
|
@@ -61,7 +42,7 @@ function entryAt(value, index) {
|
|
|
61
42
|
});
|
|
62
43
|
}
|
|
63
44
|
catch (cause) {
|
|
64
|
-
throw new HarnessError("
|
|
45
|
+
throw new HarnessError("execution.invalid-state", `Invalid candidate at transcript ${index}`, {
|
|
65
46
|
cause,
|
|
66
47
|
});
|
|
67
48
|
}
|
|
@@ -273,21 +254,10 @@ function exactKeys(value, allowed, label) {
|
|
|
273
254
|
if (!allowed.includes(key))
|
|
274
255
|
fail(`${label} has unknown field '${key}'`);
|
|
275
256
|
}
|
|
276
|
-
function count(value, label) {
|
|
277
|
-
if (value === undefined)
|
|
278
|
-
return 0;
|
|
279
|
-
if (!Number.isSafeInteger(value) || value < 0)
|
|
280
|
-
fail(`Session seed ${label} must be a non-negative safe integer`);
|
|
281
|
-
return value;
|
|
282
|
-
}
|
|
283
|
-
function optionalString(value, label) {
|
|
284
|
-
if (value !== undefined)
|
|
285
|
-
requiredString(value, label);
|
|
286
|
-
}
|
|
287
257
|
function requiredString(value, label) {
|
|
288
258
|
if (typeof value !== "string" || value.length === 0)
|
|
289
259
|
fail(`${label} must be a non-empty string`);
|
|
290
260
|
}
|
|
291
261
|
function fail(message) {
|
|
292
|
-
throw new HarnessError("
|
|
262
|
+
throw new HarnessError("execution.invalid-state", message);
|
|
293
263
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
export { Agent, AgentBuilder, AgentBuildError, AgentLifecycleError
|
|
2
|
-
export type { AgentOptions } from "./
|
|
1
|
+
export { Agent, AgentBuilder, AgentBuildError, AgentLifecycleError } from "./definition/builder.js";
|
|
2
|
+
export type { AgentOptions } from "./definition/builder.js";
|
|
3
3
|
export { HarnessError, isHarnessError } from "./errors.js";
|
|
4
4
|
export type { HarnessErrorCode, HarnessErrorDetails, HarnessErrorOptions } from "./errors.js";
|
|
5
|
-
export { BuiltAgent } from "./
|
|
6
|
-
export { middleware, model, tool } from "./
|
|
7
|
-
export { defineSchema } from "./
|
|
8
|
-
export { preparedModel } from "./model/prepared.js";
|
|
9
|
-
export type { PreparedModelOptions } from "./model/prepared.js";
|
|
10
|
-
export type { AgentManifest,
|
|
11
|
-
export type {
|
|
5
|
+
export type { BuiltAgent } from "./types/agent.js";
|
|
6
|
+
export { middleware, model, tool } from "./definition/helpers.js";
|
|
7
|
+
export { defineSchema } from "./definition/schema.js";
|
|
8
|
+
export { preparedModel } from "./execution/model/prepared.js";
|
|
9
|
+
export type { PreparedModelOptions } from "./execution/model/prepared.js";
|
|
10
|
+
export type { AgentManifest, CapabilityManifest, ManifestTool } from "./types/manifest.js";
|
|
11
|
+
export type { CapabilityDeclaration, CapabilityItems, MiddlewareContributions, StepMiddleware, StepRequest, StepResponse, } from "./types/middleware.js";
|
|
12
12
|
export type { ModelCandidate, ModelControls, ModelDirective, ModelEvidence, ModelFinishReason, ModelAdapter, ModelAdapterContext, ModelPreparedCall, ContextContributor, ContextMutationOptions, ContextSnapshot, ModelCall, ModelCallTool, ModelOutputBlock, PromptContentPart, PromptItem, ModelConfigurationContributor, ModelConfigurationInstruction, ModelConfigurationMutationOptions, ModelConfigurationSnapshot, ModelConfigurationTool, ModelRequest, ModelToolCall, ModelUsage, } from "./types/model.js";
|
|
13
|
-
export type { BuildDiagnostic, ContextItem, DeferredOutcome, JsonObject, JsonPrimitive, JsonValue,
|
|
14
|
-
export type {
|
|
15
|
-
export type {
|
|
13
|
+
export type { BuildDiagnostic, ContextItem, DeferredOutcome, JsonObject, JsonPrimitive, JsonValue, Tripwire, } from "./types/shared.js";
|
|
14
|
+
export type { ObserveEvent, ObserveModelConfigurationSnapshot, ObserveModelRequested, ObserveSealedCall, ObserveToolSnapshot, Observer, } from "./types/observe.js";
|
|
15
|
+
export type { InputEvent, MessageInput, InteractionReply, TranscriptEntry, UserContentPart, } from "./types/transcript.js";
|
|
16
|
+
export type { ExecutionInput, ExecutionState, ExecutionEvent, RunOptions, RunResult, SavedToolCall, ExecutionPlan, ToolReference, } from "./types/execution.js";
|
|
17
|
+
export { createExecutionState, validateExecutionState } from "./execution/state.js";
|
|
18
|
+
export type { Interaction, RequiredInteraction, ToolContent, ToolDefinition, ToolDescriptor, ToolExecutionContext, ToolExecutionResume, ToolInputSchema, ToolOutputSchema, ToolSchema, ToolSchemaSource, StandardToolSchema, StandardSchemaIssue, SchemaIssue, SchemaValidation, SchemaOutput, ToolOwner, ToolOutcome, ToolResult, ToolValidationFailureDetails, } from "./types/tool.js";
|