@nylorun/harness 0.13.0-beta → 0.16.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 +60 -0
- package/HOST_CONTRACT.md +27 -0
- package/README.md +62 -100
- package/dist/compatibility.d.ts +3 -0
- package/dist/compatibility.js +3 -0
- package/dist/definition/agent-definition.d.ts +11 -3
- package/dist/definition/agent-definition.js +18 -10
- package/dist/definition/compatibility.d.ts +11 -0
- package/dist/definition/compatibility.js +30 -0
- package/dist/definition/registry.d.ts +2 -2
- package/dist/definition/registry.js +8 -7
- package/dist/index.d.ts +4 -18
- package/dist/index.js +1 -6
- package/dist/loop/dispatch.js +327 -0
- package/dist/loop/host-suspension.d.ts +6 -0
- package/dist/loop/host-suspension.js +10 -0
- package/dist/loop/initial-state.d.ts +13 -0
- package/dist/loop/initial-state.js +30 -0
- package/dist/{execution → loop}/invocation.d.ts +5 -2
- package/dist/{execution → loop}/invocation.js +8 -3
- package/dist/{execution → loop}/model/adapters.d.ts +4 -2
- package/dist/{execution → loop}/model/adapters.js +3 -2
- package/dist/{execution → loop}/model/normalize.d.ts +2 -2
- package/dist/{execution → loop}/model/normalize.js +2 -2
- package/dist/{execution → loop}/model/prepared.d.ts +2 -2
- package/dist/{execution → loop}/model/project.d.ts +1 -1
- package/dist/{execution → loop}/model/project.js +1 -1
- package/dist/{execution → loop}/observe.d.ts +2 -2
- package/dist/{execution → loop}/observe.js +1 -1
- package/dist/{execution → loop}/options.d.ts +2 -1
- package/dist/{execution → loop}/options.js +28 -8
- package/dist/{execution → loop}/resume.d.ts +1 -1
- package/dist/{execution → loop}/resume.js +2 -2
- package/dist/{execution → loop}/run.d.ts +1 -1
- package/dist/{execution → loop}/run.js +9 -1
- package/dist/{execution → loop}/state.d.ts +2 -2
- package/dist/{execution → loop}/state.js +13 -3
- package/dist/{execution → loop}/step/canonicalize.d.ts +2 -2
- package/dist/{execution → loop}/step/canonicalize.js +1 -1
- package/dist/{execution → loop}/step/compose.d.ts +2 -2
- package/dist/{execution → loop}/step/compose.js +4 -1
- package/dist/{execution → loop}/step/context-draft.d.ts +2 -2
- package/dist/{execution → loop}/step/context-draft.js +2 -2
- package/dist/{execution → loop}/step/describe.d.ts +3 -3
- package/dist/{execution → loop}/step/describe.js +1 -1
- package/dist/loop/step/dynamics.d.ts +29 -0
- package/dist/loop/step/dynamics.js +149 -0
- package/dist/{execution → loop}/step/model-configuration.d.ts +2 -2
- package/dist/{execution → loop}/step/model-configuration.js +3 -3
- package/dist/{execution → loop}/step/resolve.d.ts +4 -4
- package/dist/{execution → loop}/step/run.d.ts +5 -4
- package/dist/{execution → loop}/step/run.js +87 -2
- package/dist/{execution → loop}/step/runtime.d.ts +12 -4
- package/dist/{execution → loop}/step/seal.d.ts +5 -5
- package/dist/{execution → loop}/step/seal.js +2 -2
- package/dist/{execution → loop}/step/slot-assembly.d.ts +1 -1
- package/dist/{execution → loop}/step/slot-assembly.js +1 -1
- package/dist/{execution → loop}/step/step-context.d.ts +5 -5
- package/dist/{execution → loop}/step/step-context.js +2 -2
- package/dist/{execution → loop}/tool-result.d.ts +2 -2
- package/dist/{execution → loop}/tool-result.js +2 -2
- package/dist/{execution → loop}/transcript.d.ts +1 -1
- package/dist/{execution → loop}/transcript.js +2 -2
- package/dist/loop/waits.d.ts +50 -0
- package/dist/loop/waits.js +11 -0
- package/dist/run/durable.d.ts +80 -0
- package/dist/run/durable.js +176 -0
- package/dist/run/index.d.ts +33 -0
- package/dist/run/index.js +38 -0
- package/dist/types/client.d.ts +88 -0
- package/dist/types/execution.d.ts +22 -5
- package/dist/utils/ids.d.ts +1 -0
- package/dist/utils/ids.js +11 -1
- package/package.json +21 -9
- package/dist/definition/assemble.d.ts +0 -22
- package/dist/definition/assemble.js +0 -43
- package/dist/definition/bind-agent.d.ts +0 -9
- package/dist/definition/bind-agent.js +0 -21
- package/dist/definition/bind-tool.d.ts +0 -4
- package/dist/definition/bind-tool.js +0 -19
- package/dist/definition/bound.d.ts +0 -16
- package/dist/definition/builder.d.ts +0 -30
- package/dist/definition/builder.js +0 -94
- package/dist/definition/declaration.d.ts +0 -3
- package/dist/definition/declaration.js +0 -53
- package/dist/definition/helpers.d.ts +0 -6
- package/dist/definition/helpers.js +0 -4
- package/dist/definition/manifest.d.ts +0 -9
- package/dist/definition/manifest.js +0 -45
- package/dist/definition/output-contract.d.ts +0 -6
- package/dist/definition/output-contract.js +0 -12
- package/dist/definition/schema.d.ts +0 -14
- package/dist/definition/schema.js +0 -205
- package/dist/errors.d.ts +0 -17
- package/dist/errors.js +0 -17
- package/dist/execution/dispatch.js +0 -164
- package/dist/execution/initial-state.d.ts +0 -3
- package/dist/execution/initial-state.js +0 -14
- package/dist/types/agent.d.ts +0 -9
- package/dist/types/agent.js +0 -1
- package/dist/types/manifest.d.ts +0 -22
- package/dist/types/manifest.js +0 -1
- package/dist/types/middleware.d.ts +0 -66
- package/dist/types/middleware.js +0 -1
- package/dist/types/model.d.ts +0 -184
- package/dist/types/model.js +0 -1
- package/dist/types/observe.d.ts +0 -165
- package/dist/types/observe.js +0 -1
- package/dist/types/shared.d.ts +0 -25
- package/dist/types/shared.js +0 -1
- package/dist/types/tool.d.ts +0 -138
- package/dist/types/tool.js +0 -1
- package/dist/types/transcript.d.ts +0 -65
- package/dist/types/transcript.js +0 -1
- package/dist/utils/canonical.d.ts +0 -1
- package/dist/utils/canonical.js +0 -10
- package/dist/utils/immutable.d.ts +0 -6
- package/dist/utils/immutable.js +0 -76
- /package/dist/{execution → loop}/dispatch.d.ts +0 -0
- /package/dist/{execution → loop}/model/prepared.js +0 -0
- /package/dist/{execution → loop}/step/resolve.js +0 -0
- /package/dist/{execution → loop}/step/runtime.js +0 -0
- /package/dist/{definition/bound.js → types/client.js} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { HarnessError } from "
|
|
3
|
-
import { assertJson, copyJson } from "
|
|
2
|
+
import { HarnessError } from "@nylorun/core/define";
|
|
3
|
+
import { assertJson, copyJson } from "@nylorun/core/define";
|
|
4
4
|
import { definitionFor } from "../definition/agent-definition.js";
|
|
5
5
|
import { initializeExecutionState } from "./initial-state.js";
|
|
6
|
-
import { validateTranscript } from "
|
|
6
|
+
import { validateTranscript } from "./transcript.js";
|
|
7
7
|
const id = z.string().min(1);
|
|
8
8
|
const json = z.unknown().refine((value) => {
|
|
9
9
|
try {
|
|
@@ -74,12 +74,21 @@ const call = z
|
|
|
74
74
|
])
|
|
75
75
|
.optional(),
|
|
76
76
|
token: json.optional(),
|
|
77
|
+
wait: z
|
|
78
|
+
.object({
|
|
79
|
+
kind: z.enum(["ask", "approve", "sleep", "waitFor"]),
|
|
80
|
+
waitId: id,
|
|
81
|
+
name: z.string().optional(),
|
|
82
|
+
})
|
|
83
|
+
.strict()
|
|
84
|
+
.optional(),
|
|
77
85
|
})
|
|
78
86
|
.strict();
|
|
79
87
|
const schema = z
|
|
80
88
|
.object({
|
|
81
89
|
version: z.literal(1),
|
|
82
90
|
agentId: id,
|
|
91
|
+
manifestHash: id.optional(),
|
|
83
92
|
executionId: id,
|
|
84
93
|
outputContract: z.record(z.string(), json).optional(),
|
|
85
94
|
revision: z.number().int().nonnegative(),
|
|
@@ -87,6 +96,7 @@ const schema = z
|
|
|
87
96
|
transcript: z.array(json),
|
|
88
97
|
status: z.enum(["ready", "active", "completed", "paused", "cancelled", "failed"]),
|
|
89
98
|
cancelledCalls: z.array(call).optional(),
|
|
99
|
+
state: z.record(z.string(), json).optional(),
|
|
90
100
|
plan: z
|
|
91
101
|
.object({
|
|
92
102
|
turnId: id,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ModelCandidate, ModelOutputBlock, ModelToolCall } from "
|
|
2
|
-
import type { JsonObject } from "
|
|
1
|
+
import type { ModelCandidate, ModelOutputBlock, ModelToolCall } from "@nylorun/core/define";
|
|
2
|
+
import type { JsonObject } from "@nylorun/core/define";
|
|
3
3
|
export interface CanonicalCall {
|
|
4
4
|
readonly id: string;
|
|
5
5
|
readonly name: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { BoundMiddleware } from "
|
|
2
|
-
import type { StepResponse } from "
|
|
1
|
+
import type { BoundMiddleware } from "@nylorun/core/define";
|
|
2
|
+
import type { StepResponse } from "@nylorun/core/define";
|
|
3
3
|
import type { ObserveEmit } from "../observe.js";
|
|
4
4
|
import { StepContext } from "./step-context.js";
|
|
5
5
|
export declare function runMiddleware(middleware: readonly BoundMiddleware[], context: StepContext, terminal: () => Promise<StepResponse>, observe: ObserveEmit): Promise<StepResponse>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HostSuspension } from "../host-suspension.js";
|
|
2
|
+
import { HarnessError, isHarnessError } from "@nylorun/core/define";
|
|
2
3
|
import { isBrandedResponse, StepContext } from "./step-context.js";
|
|
3
4
|
export async function runMiddleware(middleware, context, terminal, observe) {
|
|
4
5
|
const dispatch = async (index) => {
|
|
@@ -49,6 +50,8 @@ export async function runMiddleware(middleware, context, terminal, observe) {
|
|
|
49
50
|
handlerError ??= error;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
53
|
+
if (handlerError instanceof HostSuspension)
|
|
54
|
+
throw handlerError;
|
|
52
55
|
if (handlerError) {
|
|
53
56
|
if (nextCalledTwice ||
|
|
54
57
|
(isHarnessError(handlerError) && handlerError.code === "middleware.next-called-twice")) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ContextMutationOptions, ContextSnapshot } from "
|
|
2
|
-
import type { ContextItem } from "
|
|
1
|
+
import type { ContextMutationOptions, ContextSnapshot } from "@nylorun/core/define";
|
|
2
|
+
import type { ContextItem } from "@nylorun/core/define";
|
|
3
3
|
/** Per-step model-visible context supplied explicitly by middleware. */
|
|
4
4
|
export declare class ContextDraft {
|
|
5
5
|
#private;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { HarnessError } from "
|
|
2
|
-
import { copyJson } from "
|
|
1
|
+
import { HarnessError } from "@nylorun/core/define";
|
|
2
|
+
import { copyJson } from "@nylorun/core/define";
|
|
3
3
|
import { SlotDraft } from "./slot-assembly.js";
|
|
4
4
|
const CONTEXT_TYPE = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
|
|
5
5
|
/** Per-step model-visible context supplied explicitly by middleware. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ModelConfigurationSnapshot } from "
|
|
2
|
-
import type { ToolDescriptor } from "
|
|
3
|
-
import type { BoundToolDefinition } from "
|
|
1
|
+
import type { ModelConfigurationSnapshot } from "@nylorun/core/define";
|
|
2
|
+
import type { ToolDescriptor } from "@nylorun/core/define";
|
|
3
|
+
import type { BoundToolDefinition } from "@nylorun/core/define";
|
|
4
4
|
/** Executable configuration stays inside the invocation. */
|
|
5
5
|
export interface InternalModelConfigurationSnapshot extends Omit<ModelConfigurationSnapshot, "tools"> {
|
|
6
6
|
readonly tools: readonly BoundToolDefinition[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AgentDefinition } from "../../definition/agent-definition.js";
|
|
2
|
+
import type { Decision } from "@nylorun/core/define";
|
|
3
|
+
import type { JsonValue } from "@nylorun/core/define";
|
|
4
|
+
import type { PromptItem } from "@nylorun/core/define";
|
|
5
|
+
import type { InputEvent } from "@nylorun/core/define";
|
|
6
|
+
import type { ModelConfigurationDraft } from "./model-configuration.js";
|
|
7
|
+
export interface DynamicsContext {
|
|
8
|
+
readonly agent: AgentDefinition;
|
|
9
|
+
readonly info?: unknown;
|
|
10
|
+
readonly step: number;
|
|
11
|
+
readonly arrivals: readonly InputEvent[];
|
|
12
|
+
readonly messages: readonly PromptItem[];
|
|
13
|
+
sessionState: Record<string, JsonValue>;
|
|
14
|
+
}
|
|
15
|
+
/** Run all beforeModelCall handlers in capability `.use()` order. */
|
|
16
|
+
export declare function applyBeforeModelCall(ctx: DynamicsContext, configuration: ModelConfigurationDraft): Promise<{
|
|
17
|
+
readonly blocked?: string;
|
|
18
|
+
}>;
|
|
19
|
+
/** Run all afterModelCall handlers; merge with strictest-wins rules. */
|
|
20
|
+
export declare function applyAfterModelCall(ctx: DynamicsContext, args: {
|
|
21
|
+
readonly text?: string;
|
|
22
|
+
readonly toolCalls: readonly {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly args: JsonValue;
|
|
26
|
+
}[];
|
|
27
|
+
}): Promise<Decision>;
|
|
28
|
+
export declare function mergeDecisions(decisions: readonly Decision[]): Decision;
|
|
29
|
+
export declare function hasDynamics(agent: AgentDefinition): boolean;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { HarnessError } from "@nylorun/core/define";
|
|
2
|
+
/** Run all beforeModelCall handlers in capability `.use()` order. */
|
|
3
|
+
export async function applyBeforeModelCall(ctx, configuration) {
|
|
4
|
+
const patches = [];
|
|
5
|
+
for (const capability of ctx.agent.manifest.capabilities) {
|
|
6
|
+
const impl = ctx.agent.implementations[capability.id];
|
|
7
|
+
if (!impl?.beforeModelCall)
|
|
8
|
+
continue;
|
|
9
|
+
const raw = await impl.beforeModelCall({
|
|
10
|
+
input: projectInput(ctx.arrivals),
|
|
11
|
+
info: ctx.info,
|
|
12
|
+
state: { ...ctx.sessionState },
|
|
13
|
+
messages: ctx.messages,
|
|
14
|
+
step: ctx.step,
|
|
15
|
+
});
|
|
16
|
+
const patch = normalizeCapabilityPatch(capability.id, raw ?? {}, capability.id === "agent");
|
|
17
|
+
patches.push({ id: capability.id, patch, agentLevel: capability.id === "agent" });
|
|
18
|
+
}
|
|
19
|
+
if (!patches.length)
|
|
20
|
+
return {};
|
|
21
|
+
let blocked;
|
|
22
|
+
const capabilitySwitches = new Map();
|
|
23
|
+
const toolSwitches = new Map();
|
|
24
|
+
const extraInstructions = [];
|
|
25
|
+
for (const { id, patch, agentLevel } of patches) {
|
|
26
|
+
if (patch.block)
|
|
27
|
+
blocked = patch.block;
|
|
28
|
+
if (patch.state) {
|
|
29
|
+
for (const [key, value] of Object.entries(patch.state))
|
|
30
|
+
ctx.sessionState[key] = value;
|
|
31
|
+
}
|
|
32
|
+
if (patch.instructions)
|
|
33
|
+
extraInstructions.push(...patch.instructions);
|
|
34
|
+
if (patch.capabilities) {
|
|
35
|
+
for (const [name, on] of Object.entries(patch.capabilities)) {
|
|
36
|
+
if (!agentLevel && name !== id)
|
|
37
|
+
throw new HarnessError("configuration.invalid", `Capability '${id}' beforeModelCall may only toggle itself, not '${name}'`);
|
|
38
|
+
if (!ctx.agent.manifest.capabilities.some((item) => item.id === name))
|
|
39
|
+
throw new HarnessError("configuration.invalid", `beforeModelCall referenced unknown capability '${name}'`);
|
|
40
|
+
capabilitySwitches.set(name, on);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (patch.tools) {
|
|
44
|
+
for (const [name, on] of Object.entries(patch.tools)) {
|
|
45
|
+
const known = ctx.agent.manifest.capabilities.some((cap) => cap.tools?.some((tool) => tool.name === name) ||
|
|
46
|
+
ctx.agent.implementations[cap.id]?.tools?.[name] !== undefined);
|
|
47
|
+
if (!known)
|
|
48
|
+
throw new HarnessError("configuration.invalid", `beforeModelCall referenced unknown tool '${name}'`);
|
|
49
|
+
if (!agentLevel) {
|
|
50
|
+
const declared = ctx.agent.manifest.capabilities
|
|
51
|
+
.find((cap) => cap.id === id)
|
|
52
|
+
?.tools?.some((tool) => tool.name === name);
|
|
53
|
+
const owned = declared || ctx.agent.implementations[id]?.tools?.[name] !== undefined;
|
|
54
|
+
if (!owned)
|
|
55
|
+
throw new HarnessError("configuration.invalid", `Capability '${id}' beforeModelCall may only toggle its own tools`);
|
|
56
|
+
}
|
|
57
|
+
toolSwitches.set(name, on);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (blocked)
|
|
62
|
+
return { blocked };
|
|
63
|
+
let order = 10_000;
|
|
64
|
+
for (const [capabilityId, on] of capabilitySwitches) {
|
|
65
|
+
if (on)
|
|
66
|
+
continue;
|
|
67
|
+
configuration.setTools("dynamics", order++, capabilityId, []);
|
|
68
|
+
}
|
|
69
|
+
for (const [toolName, on] of toolSwitches) {
|
|
70
|
+
if (on)
|
|
71
|
+
continue;
|
|
72
|
+
for (const capability of ctx.agent.manifest.capabilities) {
|
|
73
|
+
const tools = ctx.agent.implementations[capability.id]?.tools;
|
|
74
|
+
if (!tools?.[toolName])
|
|
75
|
+
continue;
|
|
76
|
+
const remaining = Object.values(tools).filter((tool) => tool.name !== toolName);
|
|
77
|
+
configuration.setTools("dynamics", order++, capability.id, remaining);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (extraInstructions.length)
|
|
81
|
+
configuration.setInstructions("dynamics", order++, "dynamics", Object.freeze([...extraInstructions]));
|
|
82
|
+
return {};
|
|
83
|
+
}
|
|
84
|
+
/** Run all afterModelCall handlers; merge with strictest-wins rules. */
|
|
85
|
+
export async function applyAfterModelCall(ctx, args) {
|
|
86
|
+
const decisions = [];
|
|
87
|
+
for (const capability of ctx.agent.manifest.capabilities) {
|
|
88
|
+
const impl = ctx.agent.implementations[capability.id];
|
|
89
|
+
if (!impl?.afterModelCall)
|
|
90
|
+
continue;
|
|
91
|
+
const decision = await impl.afterModelCall(args, {
|
|
92
|
+
info: ctx.info,
|
|
93
|
+
state: { ...ctx.sessionState },
|
|
94
|
+
});
|
|
95
|
+
decisions.push(decision ?? {});
|
|
96
|
+
}
|
|
97
|
+
return mergeDecisions(decisions);
|
|
98
|
+
}
|
|
99
|
+
export function mergeDecisions(decisions) {
|
|
100
|
+
let block;
|
|
101
|
+
let retry;
|
|
102
|
+
const deny = new Map();
|
|
103
|
+
const approve = new Map();
|
|
104
|
+
let text;
|
|
105
|
+
for (const decision of decisions) {
|
|
106
|
+
if (decision.block)
|
|
107
|
+
block = decision.block;
|
|
108
|
+
if (decision.retry)
|
|
109
|
+
retry = decision.retry;
|
|
110
|
+
for (const item of decision.deny ?? [])
|
|
111
|
+
deny.set(item.id, item.reason);
|
|
112
|
+
for (const item of decision.approve ?? [])
|
|
113
|
+
approve.set(item.id, item.prompt);
|
|
114
|
+
if (decision.text !== undefined)
|
|
115
|
+
text = decision.text;
|
|
116
|
+
}
|
|
117
|
+
if (block)
|
|
118
|
+
return { block };
|
|
119
|
+
if (retry)
|
|
120
|
+
return { retry, ...(text === undefined ? {} : { text }) };
|
|
121
|
+
return {
|
|
122
|
+
...(text === undefined ? {} : { text }),
|
|
123
|
+
...(deny.size ? { deny: [...deny.entries()].map(([id, reason]) => ({ id, reason })) } : {}),
|
|
124
|
+
...(approve.size
|
|
125
|
+
? { approve: [...approve.entries()].map(([id, prompt]) => ({ id, prompt })) }
|
|
126
|
+
: {}),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
export function hasDynamics(agent) {
|
|
130
|
+
return agent.manifest.capabilities.some((capability) => capability.beforeModelCall || capability.afterModelCall);
|
|
131
|
+
}
|
|
132
|
+
function normalizeCapabilityPatch(id, patch, agentLevel) {
|
|
133
|
+
if (patch.active === undefined)
|
|
134
|
+
return patch;
|
|
135
|
+
if (agentLevel)
|
|
136
|
+
throw new HarnessError("configuration.invalid", "Agent-level beforeModelCall must use capabilities{}, not active");
|
|
137
|
+
return {
|
|
138
|
+
...patch,
|
|
139
|
+
capabilities: { ...(patch.capabilities ?? {}), [id]: patch.active },
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function projectInput(arrivals) {
|
|
143
|
+
const message = arrivals.find((item) => item.kind === "user-message");
|
|
144
|
+
if (!message)
|
|
145
|
+
return undefined;
|
|
146
|
+
if ("text" in message && typeof message.text === "string")
|
|
147
|
+
return message.text;
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { InternalModelConfigurationSnapshot } from "./describe.js";
|
|
2
|
-
import type { ModelConfigurationMutationOptions, ModelDirective } from "
|
|
3
|
-
import type { ToolDefinition } from "
|
|
2
|
+
import type { ModelConfigurationMutationOptions, ModelDirective } from "@nylorun/core/define";
|
|
3
|
+
import type { ToolDefinition } from "@nylorun/core/define";
|
|
4
4
|
/** Per-step, middleware-owned model configuration draft. It never persists past the call. */
|
|
5
5
|
export declare class ModelConfigurationDraft {
|
|
6
6
|
#private;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { bindTool } from "
|
|
2
|
-
import { HarnessError, isHarnessError } from "
|
|
1
|
+
import { bindTool } from "@nylorun/core/define";
|
|
2
|
+
import { HarnessError, isHarnessError } from "@nylorun/core/define";
|
|
3
3
|
import { normalizeDirective, sameDirective } from "../model/normalize.js";
|
|
4
|
-
import { copyJson } from "
|
|
4
|
+
import { copyJson } from "@nylorun/core/define";
|
|
5
5
|
import { checkedReason, slotOwner, SlotDraft } from "./slot-assembly.js";
|
|
6
6
|
/** Per-step, middleware-owned model configuration draft. It never persists past the call. */
|
|
7
7
|
export class ModelConfigurationDraft {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { TurnOutputContract } from "
|
|
2
|
-
import type { InputEvent } from "
|
|
3
|
-
import type { ModelRequest } from "
|
|
4
|
-
import type { ToolResult } from "
|
|
1
|
+
import type { TurnOutputContract } from "@nylorun/core/define";
|
|
2
|
+
import type { InputEvent } from "@nylorun/core/define";
|
|
3
|
+
import type { ModelRequest } from "@nylorun/core/define";
|
|
4
|
+
import type { ToolResult } from "@nylorun/core/define";
|
|
5
5
|
import type { StepContext } from "./step-context.js";
|
|
6
6
|
export declare function resolveModelRequest(input: {
|
|
7
7
|
context: StepContext;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ExecutionSnapshot, StepRuntime } from "./runtime.js";
|
|
2
|
-
import type { TurnOutputContract } from "
|
|
3
|
-
import type { ModelCandidate } from "
|
|
4
|
-
import type { InputEvent } from "
|
|
5
|
-
import type { ToolResult } from "
|
|
2
|
+
import type { TurnOutputContract } from "@nylorun/core/define";
|
|
3
|
+
import type { ModelCandidate } from "@nylorun/core/define";
|
|
4
|
+
import type { InputEvent } from "@nylorun/core/define";
|
|
5
|
+
import type { ToolResult } from "@nylorun/core/define";
|
|
6
6
|
import type { ObserveEmit } from "../observe.js";
|
|
7
7
|
import { type SealedStepOutput } from "./seal.js";
|
|
8
8
|
export interface StepRunResult {
|
|
@@ -11,6 +11,7 @@ export interface StepRunResult {
|
|
|
11
11
|
readonly output: SealedStepOutput;
|
|
12
12
|
readonly requestedModelId?: string;
|
|
13
13
|
readonly modelInvocationId?: string;
|
|
14
|
+
readonly retry?: string;
|
|
14
15
|
}
|
|
15
16
|
export declare function runStep(input: {
|
|
16
17
|
agent: StepRuntime;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { HostSuspension } from "../host-suspension.js";
|
|
1
2
|
import { normalizeCandidate } from "../model/normalize.js";
|
|
2
|
-
import { HarnessError, isHarnessError } from "
|
|
3
|
-
import { copyJson } from "
|
|
3
|
+
import { HarnessError, isHarnessError } from "@nylorun/core/define";
|
|
4
|
+
import { copyJson } from "@nylorun/core/define";
|
|
4
5
|
import { runMiddleware } from "./compose.js";
|
|
5
6
|
import { ContextDraft } from "./context-draft.js";
|
|
6
7
|
import { StepContext } from "./step-context.js";
|
|
@@ -9,9 +10,11 @@ import { resolveModelRequest } from "./resolve.js";
|
|
|
9
10
|
import { sealStep } from "./seal.js";
|
|
10
11
|
import { ModelConfigurationDraft } from "./model-configuration.js";
|
|
11
12
|
import { createId } from "../../utils/ids.js";
|
|
13
|
+
import { applyAfterModelCall, applyBeforeModelCall, hasDynamics, } from "./dynamics.js";
|
|
12
14
|
export async function runStep(input) {
|
|
13
15
|
let requestedModelId;
|
|
14
16
|
let modelInvocationId;
|
|
17
|
+
let retryFeedback;
|
|
15
18
|
const stepInput = Object.freeze({
|
|
16
19
|
executionId: input.executionId,
|
|
17
20
|
turnId: input.turnId,
|
|
@@ -38,6 +41,46 @@ export async function runStep(input) {
|
|
|
38
41
|
input.signal.throwIfAborted();
|
|
39
42
|
if (context.currentTripwire)
|
|
40
43
|
return context.tripwire(context.currentTripwire);
|
|
44
|
+
const definition = input.agent.definition;
|
|
45
|
+
const dynamicsCtx = definition && hasDynamics(definition)
|
|
46
|
+
? {
|
|
47
|
+
agent: definition,
|
|
48
|
+
info: input.info,
|
|
49
|
+
step: input.stepNumber - 1,
|
|
50
|
+
arrivals: input.arrivals,
|
|
51
|
+
messages: projectModelCall(resolveModelRequest({
|
|
52
|
+
context,
|
|
53
|
+
arrivals: input.arrivals,
|
|
54
|
+
toolResults: input.toolResults,
|
|
55
|
+
output: input.output,
|
|
56
|
+
})).prompt,
|
|
57
|
+
sessionState: input.agent.sessionState ?? {},
|
|
58
|
+
}
|
|
59
|
+
: undefined;
|
|
60
|
+
if (dynamicsCtx) {
|
|
61
|
+
try {
|
|
62
|
+
const before = await applyBeforeModelCall(dynamicsCtx, configuration);
|
|
63
|
+
if (input.agent.sessionState) {
|
|
64
|
+
Object.assign(input.agent.sessionState, dynamicsCtx.sessionState);
|
|
65
|
+
}
|
|
66
|
+
if (input.agent.recordAfterDynamics)
|
|
67
|
+
await input.agent.recordAfterDynamics();
|
|
68
|
+
if (before.blocked) {
|
|
69
|
+
return context.tripwire({
|
|
70
|
+
code: "dynamics.blocked",
|
|
71
|
+
message: before.blocked,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (error instanceof HostSuspension)
|
|
77
|
+
throw error;
|
|
78
|
+
return context.tripwire({
|
|
79
|
+
code: isHarnessError(error) ? error.code : "configuration.invalid",
|
|
80
|
+
message: error instanceof Error ? error.message : String(error),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
41
84
|
try {
|
|
42
85
|
const selected = configuration.snapshot();
|
|
43
86
|
for (const tool of selected.tools)
|
|
@@ -46,6 +89,8 @@ export async function runStep(input) {
|
|
|
46
89
|
context.sealContext(runtimeContext.snapshot());
|
|
47
90
|
}
|
|
48
91
|
catch (error) {
|
|
92
|
+
if (error instanceof HostSuspension)
|
|
93
|
+
throw error;
|
|
49
94
|
const message = error instanceof Error ? error.message : String(error);
|
|
50
95
|
return context.tripwire({
|
|
51
96
|
code: isHarnessError(error) ? error.code : "configuration.invalid",
|
|
@@ -103,9 +148,48 @@ export async function runStep(input) {
|
|
|
103
148
|
const candidate = context.currentCandidate;
|
|
104
149
|
if (!candidate)
|
|
105
150
|
throw new HarnessError("model.candidate-missing", "Model candidate missing after mint");
|
|
151
|
+
if (dynamicsCtx) {
|
|
152
|
+
const text = candidate.output
|
|
153
|
+
?.filter((block) => block.type === "text")
|
|
154
|
+
.map((block) => block.text)
|
|
155
|
+
.join("");
|
|
156
|
+
const toolCalls = (candidate.output ?? [])
|
|
157
|
+
.filter((block) => block.type === "tool-call")
|
|
158
|
+
.map((block) => {
|
|
159
|
+
const call = block;
|
|
160
|
+
return { id: call.id, name: call.name, args: call.args };
|
|
161
|
+
});
|
|
162
|
+
const decision = await applyAfterModelCall(dynamicsCtx, {
|
|
163
|
+
...(text ? { text } : {}),
|
|
164
|
+
toolCalls,
|
|
165
|
+
});
|
|
166
|
+
if (input.agent.recordAfterDynamics)
|
|
167
|
+
await input.agent.recordAfterDynamics();
|
|
168
|
+
if (decision.block) {
|
|
169
|
+
return context.tripwire({ code: "dynamics.blocked", message: decision.block });
|
|
170
|
+
}
|
|
171
|
+
if (decision.retry) {
|
|
172
|
+
retryFeedback = decision.retry;
|
|
173
|
+
return context.tripwire({ code: "dynamics.retry", message: decision.retry });
|
|
174
|
+
}
|
|
175
|
+
if (decision.text !== undefined) {
|
|
176
|
+
minted.replace({
|
|
177
|
+
output: [{ type: "text", text: decision.text }],
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
for (const item of decision.deny ?? [])
|
|
181
|
+
minted.deny(item.id, item.reason);
|
|
182
|
+
for (const item of decision.approve ?? [])
|
|
183
|
+
minted.requireInteraction(item.id, {
|
|
184
|
+
kind: "approval",
|
|
185
|
+
prompt: item.prompt,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
106
188
|
return minted;
|
|
107
189
|
}
|
|
108
190
|
catch (error) {
|
|
191
|
+
if (error instanceof HostSuspension)
|
|
192
|
+
throw error;
|
|
109
193
|
if (input.signal.aborted)
|
|
110
194
|
throw input.signal.reason;
|
|
111
195
|
return context.tripwire({
|
|
@@ -122,6 +206,7 @@ export async function runStep(input) {
|
|
|
122
206
|
...(requestedModelId === undefined ? {} : { requestedModelId }),
|
|
123
207
|
output,
|
|
124
208
|
...(modelInvocationId ? { modelInvocationId } : {}),
|
|
209
|
+
...(retryFeedback ? { retry: retryFeedback } : {}),
|
|
125
210
|
});
|
|
126
211
|
}
|
|
127
212
|
function snapshotStepStart(input) {
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import type { ToolRegistry } from "../../definition/registry.js";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
2
|
+
import type { AgentDefinition } from "../../definition/agent-definition.js";
|
|
3
|
+
import type { ModelAdapter } from "@nylorun/core/define";
|
|
4
|
+
import type { InputEvent, TranscriptEntry } from "@nylorun/core/define";
|
|
5
|
+
import type { ToolResult } from "@nylorun/core/define";
|
|
6
|
+
import type { BoundMiddleware } from "@nylorun/core/define";
|
|
7
|
+
import type { JsonValue } from "@nylorun/core/define";
|
|
6
8
|
/** Compiled definition pieces plus the per-run model adapter for one step. */
|
|
7
9
|
export interface StepRuntime {
|
|
8
10
|
readonly middleware: readonly BoundMiddleware[];
|
|
9
11
|
readonly invoke: ModelAdapter;
|
|
10
12
|
readonly registry: ToolRegistry;
|
|
13
|
+
/** Full definition for before/after dynamics (optional for middleware-only agents). */
|
|
14
|
+
readonly definition?: AgentDefinition;
|
|
15
|
+
/** Mutable session memory bag shared with tools. */
|
|
16
|
+
sessionState?: Record<string, JsonValue>;
|
|
17
|
+
/** Called after Patch/Decision applied so the host can record. */
|
|
18
|
+
recordAfterDynamics?: () => Promise<void>;
|
|
11
19
|
}
|
|
12
20
|
export interface StepInput {
|
|
13
21
|
readonly executionId: string;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { BoundToolDefinition } from "
|
|
2
|
-
import type { ModelCandidate } from "
|
|
3
|
-
import type { JsonValue, Tripwire } from "
|
|
4
|
-
import type { RequiredInteraction, ToolOwner, ToolResult } from "
|
|
1
|
+
import type { BoundToolDefinition } from "@nylorun/core/define";
|
|
2
|
+
import type { ModelCandidate } from "@nylorun/core/define";
|
|
3
|
+
import type { JsonValue, Tripwire } from "@nylorun/core/define";
|
|
4
|
+
import type { RequiredInteraction, ToolOwner, ToolResult } from "@nylorun/core/define";
|
|
5
5
|
import type { StepContext } from "./step-context.js";
|
|
6
|
-
import type { TurnOutputContract } from "
|
|
6
|
+
import type { TurnOutputContract } from "@nylorun/core/define";
|
|
7
7
|
export interface SealedToolCall {
|
|
8
8
|
readonly callId: string;
|
|
9
9
|
readonly toolName: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { textFromOutput } from "../model/normalize.js";
|
|
2
2
|
import { createId } from "../../utils/ids.js";
|
|
3
|
-
import { HarnessError, isHarnessError } from "
|
|
4
|
-
import { assertJson, copyJson } from "
|
|
3
|
+
import { HarnessError, isHarnessError } from "@nylorun/core/define";
|
|
4
|
+
import { assertJson, copyJson } from "@nylorun/core/define";
|
|
5
5
|
const failed = (callId, toolName, code, message, details) => Object.freeze({
|
|
6
6
|
kind: "failed",
|
|
7
7
|
callId,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HarnessError } from "
|
|
1
|
+
import { HarnessError } from "@nylorun/core/define";
|
|
2
2
|
/**
|
|
3
3
|
* Shared per-step slot store. Declarations are discarded with the draft that owns this instance.
|
|
4
4
|
* Configuration and context supply their typed values and snapshot them after this assembler has
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { BoundToolDefinition } from "
|
|
1
|
+
import type { BoundToolDefinition } from "@nylorun/core/define";
|
|
2
2
|
import type { StepInput } from "./runtime.js";
|
|
3
3
|
import type { InternalModelConfigurationSnapshot } from "./describe.js";
|
|
4
|
-
import type { ContextSnapshot, ModelCandidate, ModelDirective } from "
|
|
5
|
-
import type { StepRequest, StepResponse } from "
|
|
6
|
-
import type { Tripwire } from "
|
|
4
|
+
import type { ContextSnapshot, ModelCandidate, ModelDirective } from "@nylorun/core/define";
|
|
5
|
+
import type { StepRequest, StepResponse } from "@nylorun/core/define";
|
|
6
|
+
import type { Tripwire } from "@nylorun/core/define";
|
|
7
7
|
import type { ObserveEmit } from "../observe.js";
|
|
8
|
-
import type { Interaction } from "
|
|
8
|
+
import type { Interaction } from "@nylorun/core/define";
|
|
9
9
|
import { type CanonicalCall } from "./canonicalize.js";
|
|
10
10
|
import { ContextDraft } from "./context-draft.js";
|
|
11
11
|
import { ModelConfigurationDraft } from "./model-configuration.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { HarnessError, isHarnessError } from "
|
|
2
|
-
import { freezeGraph } from "
|
|
1
|
+
import { HarnessError, isHarnessError } from "@nylorun/core/define";
|
|
2
|
+
import { freezeGraph } from "@nylorun/core/define";
|
|
3
3
|
import { callsFromCanonical, candidateFromCanonical, canonicalizeOutput, identityKey, } from "./canonicalize.js";
|
|
4
4
|
import { normalizeCandidate } from "../model/normalize.js";
|
|
5
5
|
import { ContextDraft } from "./context-draft.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BoundToolDefinition } from "
|
|
1
|
+
import type { BoundToolDefinition } from "@nylorun/core/define";
|
|
2
2
|
import type { SavedToolCall } from "../types/execution.js";
|
|
3
|
-
import type { ToolOutcome, ToolResult } from "
|
|
3
|
+
import type { ToolOutcome, ToolResult } from "@nylorun/core/define";
|
|
4
4
|
export declare function toolResult(call: SavedToolCall, definition: BoundToolDefinition, outcome: ToolOutcome): ToolResult;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { HarnessError } from "
|
|
2
|
-
import { copyJson } from "
|
|
1
|
+
import { HarnessError } from "@nylorun/core/define";
|
|
2
|
+
import { copyJson } from "@nylorun/core/define";
|
|
3
3
|
export function toolResult(call, definition, outcome) {
|
|
4
4
|
const identity = { callId: call.callId, toolName: call.toolName };
|
|
5
5
|
if (outcome.kind === "completed") {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { TranscriptEntry } from "
|
|
1
|
+
import type { TranscriptEntry } from "@nylorun/core/define";
|
|
2
2
|
export declare function validateTranscript(value: readonly TranscriptEntry[]): readonly TranscriptEntry[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { HarnessError } from "
|
|
1
|
+
import { HarnessError } from "@nylorun/core/define";
|
|
2
2
|
import { normalizeCandidate } from "./model/normalize.js";
|
|
3
|
-
import { assertJson, copyJson, copyJsonObject } from "
|
|
3
|
+
import { assertJson, copyJson, copyJsonObject } from "@nylorun/core/define";
|
|
4
4
|
export function validateTranscript(value) {
|
|
5
5
|
try {
|
|
6
6
|
if (!Array.isArray(value))
|