@noetic-tools/types 3.2.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/schemas/workflow.d.ts +93 -26
- package/dist/schemas/workflow.js +87 -38
- package/dist/types/acp.d.ts +525 -0
- package/dist/types/acp.js +101 -0
- package/dist/types/common.d.ts +6 -0
- package/dist/types/context-harness.d.ts +5 -3
- package/dist/types/context-layer.d.ts +10 -0
- package/dist/types/context.d.ts +1 -1
- package/dist/types/output-codec.d.ts +1 -1
- package/dist/types/output-codec.js +1 -1
- package/dist/types/runtime.d.ts +20 -6
- package/dist/types/steering.d.ts +9 -0
- package/dist/types/step.d.ts +33 -19
- package/dist/types/tool.d.ts +30 -0
- package/package.json +2 -1
- package/dist/types/sub-harness.d.ts +0 -273
- package/dist/types/sub-harness.js +0 -106
package/dist/types/context.d.ts
CHANGED
|
@@ -110,7 +110,7 @@ export interface Context<TContext = ContextData, TState = unknown> {
|
|
|
110
110
|
*
|
|
111
111
|
* Aborting rejects operations blocked on the context (channel `recv` waiters,
|
|
112
112
|
* parked back-pressure senders) with `cancelled`, cuts short the in-flight
|
|
113
|
-
* model call or
|
|
113
|
+
* model call or ACP agent turn, and makes the next step boundary throw
|
|
114
114
|
* `cancelled`. Context-layer teardown is NOT run — use
|
|
115
115
|
* `harness.cancel(ctx, reason)` for that.
|
|
116
116
|
*/
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `StepCallModel.output`: instead of JSON-parsing the assistant text once at turn
|
|
6
6
|
* end, a codec is fed each text delta as it streams and produces a typed
|
|
7
7
|
* value when the turn finishes. OpenUI Lang is one dialect; the contract
|
|
8
|
-
* lives here — next to `ContextLayer` and `
|
|
8
|
+
* lives here — next to `ContextLayer` and `AcpAgent` — so `core` and
|
|
9
9
|
* dialect packages both depend on it without forming a cycle.
|
|
10
10
|
*/
|
|
11
11
|
/**
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `StepCallModel.output`: instead of JSON-parsing the assistant text once at turn
|
|
6
6
|
* end, a codec is fed each text delta as it streams and produces a typed
|
|
7
7
|
* value when the turn finishes. OpenUI Lang is one dialect; the contract
|
|
8
|
-
* lives here — next to `ContextLayer` and `
|
|
8
|
+
* lives here — next to `ContextLayer` and `AcpAgent` — so `core` and
|
|
9
9
|
* dialect packages both depend on it without forming a cycle.
|
|
10
10
|
*/
|
|
11
11
|
/**
|
package/dist/types/runtime.d.ts
CHANGED
|
@@ -101,12 +101,17 @@ interface CallModelRequestWithTools extends CallModelRequestBase {
|
|
|
101
101
|
/** When set, restricts which tools the model may invoke for this call. */
|
|
102
102
|
allowedToolNames?: string[];
|
|
103
103
|
}
|
|
104
|
-
/**
|
|
105
|
-
*
|
|
104
|
+
/**
|
|
105
|
+
* @public Request shape when no tools are provided. `ctx` is still accepted —
|
|
106
|
+
* it carries the session broadcaster, without which a tool-less call streams
|
|
107
|
+
* nothing to `getFullStream`/`getTextStream` — it just isn't *required* the
|
|
108
|
+
* way the tools variant needs it for execution callbacks.
|
|
109
|
+
*/
|
|
106
110
|
interface CallModelRequestWithoutTools extends CallModelRequestBase {
|
|
107
111
|
tools?: undefined;
|
|
108
|
-
ctx?:
|
|
109
|
-
layers?:
|
|
112
|
+
ctx?: Context;
|
|
113
|
+
layers?: ContextLayer[];
|
|
114
|
+
allowedToolNames?: undefined;
|
|
110
115
|
}
|
|
111
116
|
/** @public Request object for `AgentHarnessContract.callModel()`. Encapsulates all parameters needed for an LLM call using only Noetic types. */
|
|
112
117
|
export type CallModelRequest = CallModelRequestWithTools | CallModelRequestWithoutTools;
|
|
@@ -117,6 +122,13 @@ export interface ExecuteOptions {
|
|
|
117
122
|
state?: unknown;
|
|
118
123
|
/** Context layers to apply to the execution context. Overrides harness-level layers if provided. */
|
|
119
124
|
contextLayers?: ContextLayer[];
|
|
125
|
+
/**
|
|
126
|
+
* Additional context layers appended AFTER the effective layer set
|
|
127
|
+
* (harness-level layers, or `contextLayers` when that override is given).
|
|
128
|
+
* Use this to inject a per-turn layer — a permission gate, an observer —
|
|
129
|
+
* without discarding the layers the harness was built with.
|
|
130
|
+
*/
|
|
131
|
+
extraContextLayers?: ContextLayer[];
|
|
120
132
|
/** Override the harness's default delivery mode for this message only. */
|
|
121
133
|
deliveryMode?: DeliveryMode;
|
|
122
134
|
/**
|
|
@@ -244,6 +256,8 @@ export interface AgentHarnessContract<TParams extends Record<string, unknown> =
|
|
|
244
256
|
threadId?: string;
|
|
245
257
|
resourceId?: string;
|
|
246
258
|
contextLayers?: ContextLayer[];
|
|
259
|
+
/** Additional layers appended AFTER the effective layer set (see `ExecuteOptions.extraContextLayers`). */
|
|
260
|
+
extraContextLayers?: ContextLayer[];
|
|
247
261
|
/** Override the new context's initial cwd. */
|
|
248
262
|
cwdInit?: string;
|
|
249
263
|
}): Context;
|
|
@@ -308,7 +322,7 @@ export interface AgentHarnessContract<TParams extends Record<string, unknown> =
|
|
|
308
322
|
* (`onComplete` with `outcome: 'aborted'`, then `dispose`) bottom-up.
|
|
309
323
|
*
|
|
310
324
|
* Blocked channel operations reject with `cancelled`, the in-flight model
|
|
311
|
-
* call and
|
|
325
|
+
* call and ACP agent turn are cut short, and the next step boundary throws
|
|
312
326
|
* `cancelled`. Idempotent: cancelling an already-cancelled context is a
|
|
313
327
|
* no-op. Use `ctx.abort()` when you want the signal without layer teardown.
|
|
314
328
|
*/
|
|
@@ -318,7 +332,7 @@ export interface AgentHarnessContract<TParams extends Record<string, unknown> =
|
|
|
318
332
|
createSpan(name: string, parent: Span | null): Span;
|
|
319
333
|
getLayerState<T>(executionId: string, layerId: string): T | undefined;
|
|
320
334
|
setLayerState<T>(executionId: string, layerId: string, state: T): void;
|
|
321
|
-
beforeToolCall(layers: ContextLayer[], toolName: string, toolArgs: unknown, ctx: Context): Promise<SteeringDecision>;
|
|
335
|
+
beforeToolCall(layers: ContextLayer[], toolName: string, toolArgs: unknown, ctx: Context, callId?: string): Promise<SteeringDecision>;
|
|
322
336
|
afterModelCall(layers: ContextLayer[], response: LLMResponse, ctx: Context): Promise<SteeringDecision>;
|
|
323
337
|
/**
|
|
324
338
|
* Project the history items through every layer's `projectHistory` hook in
|
package/dist/types/steering.d.ts
CHANGED
|
@@ -42,6 +42,15 @@ export interface LedgerEntry {
|
|
|
42
42
|
export interface BeforeToolCallParams<TState = unknown> {
|
|
43
43
|
toolName: string;
|
|
44
44
|
toolArgs: unknown;
|
|
45
|
+
/**
|
|
46
|
+
* Correlation id of the pending call — the same id carried by the
|
|
47
|
+
* `tool_call_started` framework event (the model's `callId` on model-driven
|
|
48
|
+
* calls, the step id on a direct `invokeTool`). Lets a gating layer tie its
|
|
49
|
+
* decision to the call it is reported as, e.g. when forwarding the request
|
|
50
|
+
* to an external approver. Optional because a custom caller of the gate may
|
|
51
|
+
* have no call identity; every built-in tool-executing path supplies it.
|
|
52
|
+
*/
|
|
53
|
+
callId?: string;
|
|
45
54
|
ctx: ExecutionContext;
|
|
46
55
|
state: TState;
|
|
47
56
|
}
|
package/dist/types/step.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import type { AcpAgent, AcpClientCapabilityConfig, AcpContentBlock, AcpMcpServer, AcpPermissionHandler, AcpPermissionPolicy, AcpSessionPolicy } from './acp.js';
|
|
2
3
|
import type { Channel } from './channel.js';
|
|
3
4
|
import type { ModelParams, RetryPolicy, ServerToolSpec, StepMeta } from './common.js';
|
|
4
5
|
import type { Context } from './context.js';
|
|
5
6
|
import type { ContextConfig, ContextData, ContextLayer, ProjectionPolicy } from './context-layer.js';
|
|
6
7
|
import type { NoeticError } from './error.js';
|
|
7
8
|
import type { OutputCodec } from './output-codec.js';
|
|
8
|
-
import type { SubHarness, SubHarnessKind, SubHarnessSessionPolicy, SubHarnessSettings } from './sub-harness.js';
|
|
9
9
|
import type { SubprocessAdapter } from './subprocess-adapter.js';
|
|
10
10
|
import type { Tool } from './tool.js';
|
|
11
11
|
/**
|
|
@@ -73,7 +73,7 @@ export interface SettleResult<O> {
|
|
|
73
73
|
error?: NoeticError;
|
|
74
74
|
}
|
|
75
75
|
/** @public Discriminated union of all step kinds that can be composed into an execution tree. */
|
|
76
|
-
export type Step<TContext = ContextData, I = unknown, O = unknown> = StepRunCode<TContext, I, O> | StepCallModel<TContext, I, O> |
|
|
76
|
+
export type Step<TContext = ContextData, I = unknown, O = unknown> = StepRunCode<TContext, I, O> | StepCallModel<TContext, I, O> | StepAcpAgent<TContext, I, O> | StepInvokeTool<TContext, I, O> | StepConditional<TContext, I, O> | StepInParallel<TContext, I, O> | StepSpawn<TContext, I, O> | StepWithContext<TContext, I, O> | StepLoop<TContext, I, O> | StepSchedule<TContext, I, O>;
|
|
77
77
|
/** @public A step that executes arbitrary async logic via a user-supplied function. */
|
|
78
78
|
export interface StepRunCode<TContext = ContextData, I = unknown, O = unknown> {
|
|
79
79
|
kind: 'runCode';
|
|
@@ -123,32 +123,46 @@ export interface StepCallModel<TContext = ContextData, _I = unknown, O = unknown
|
|
|
123
123
|
projection?: ProjectionPolicy;
|
|
124
124
|
}
|
|
125
125
|
/**
|
|
126
|
-
* A step that delegates a turn to an external coding
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* interpreter handler.
|
|
126
|
+
* A step that delegates a turn to an external coding agent over the Agent
|
|
127
|
+
* Client Protocol. One step kind serves every ACP-speaking agent — the agent
|
|
128
|
+
* itself is supplied as an adapter, so the set of supported agents is open.
|
|
130
129
|
* @public
|
|
131
130
|
*/
|
|
132
|
-
export interface
|
|
133
|
-
|
|
134
|
-
kind: SubHarnessKind;
|
|
131
|
+
export interface StepAcpAgent<TContext = ContextData, _I = unknown, O = unknown> {
|
|
132
|
+
kind: 'acp-agent';
|
|
135
133
|
id: string;
|
|
136
134
|
/**
|
|
137
|
-
* The
|
|
135
|
+
* The ACP agent adapter that runs the turn. Eager or `(ctx) => AcpAgent`.
|
|
138
136
|
* Programmatic builders take it inline; the JSON hydrator resolves it from
|
|
139
|
-
* the workflow's
|
|
137
|
+
* the workflow's agent registry and inlines it here.
|
|
140
138
|
*/
|
|
141
|
-
|
|
142
|
-
/** Turn prompt. Eager string or `(ctx) => string` getter. */
|
|
143
|
-
prompt
|
|
144
|
-
/**
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
139
|
+
agent: Lazy<AcpAgent, TContext>;
|
|
140
|
+
/** Turn prompt as plain text. Eager string or `(ctx) => string` getter. */
|
|
141
|
+
prompt?: Lazy<string, TContext>;
|
|
142
|
+
/**
|
|
143
|
+
* Full ACP prompt content — images, audio, resource links, embedded context.
|
|
144
|
+
* Appended after `prompt` when both are given. Validated against the agent's
|
|
145
|
+
* advertised `promptCapabilities` before the turn is sent.
|
|
146
|
+
*/
|
|
147
|
+
content?: Lazy<ReadonlyArray<AcpContentBlock> | undefined, TContext>;
|
|
148
|
+
/** MCP servers to expose to the agent for this session. */
|
|
149
|
+
mcpServers?: Lazy<ReadonlyArray<AcpMcpServer> | undefined, TContext>;
|
|
150
|
+
/** Working directory for the session. Defaults to `ctx.cwdState.cwd`. */
|
|
151
|
+
cwd?: Lazy<string | undefined, TContext>;
|
|
152
|
+
/** Session mode to switch to before prompting (e.g. `'plan'`). */
|
|
153
|
+
mode?: Lazy<string | undefined, TContext>;
|
|
154
|
+
/** Model to select before prompting, for agents that expose model selection. */
|
|
155
|
+
model?: Lazy<string | undefined, TContext>;
|
|
156
|
+
/** Declarative answer to the agent's permission requests. */
|
|
157
|
+
permissions?: AcpPermissionPolicy;
|
|
158
|
+
/** Async resolver consulted when policy and steering both abstain. */
|
|
159
|
+
onPermissionRequest?: AcpPermissionHandler;
|
|
160
|
+
/** Which client capabilities to advertise to the agent. */
|
|
161
|
+
clientCapabilities?: AcpClientCapabilityConfig;
|
|
148
162
|
/** When set, the assistant text is JSON-parsed and validated against this Standard Schema. */
|
|
149
163
|
output?: StandardSchemaV1<unknown, O>;
|
|
150
164
|
/** Session reuse + teardown policy across steps. */
|
|
151
|
-
session?:
|
|
165
|
+
session?: AcpSessionPolicy;
|
|
152
166
|
/** Controls framework event emission for this step. Defaults to `true`. */
|
|
153
167
|
emit?: boolean | ((eventType: string, data: Record<string, unknown>) => boolean);
|
|
154
168
|
}
|
package/dist/types/tool.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import type { AcpToolKind } from './acp.js';
|
|
2
3
|
import type { FunctionCallItem, FunctionCallOutputItem, Item, ItemSchemaExtensions, ToolResultExtensionItem } from './items.js';
|
|
3
4
|
import type { InferSchemaOutput } from './schema.js';
|
|
4
5
|
type ToolExecutionResult<O extends StandardSchemaV1> = Promise<InferSchemaOutput<O>> | AsyncGenerator<unknown, InferSchemaOutput<O>>;
|
|
@@ -50,6 +51,33 @@ export interface ToolUiDeclaration<I extends StandardSchemaV1 = StandardSchemaV1
|
|
|
50
51
|
/** Replaces the tool's region when execution throws. */
|
|
51
52
|
error?(err: unknown, args: InferSchemaOutput<I>): UiFragment | null;
|
|
52
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* How a tool call presents in an ACP client's UI when the harness is served
|
|
56
|
+
* as an ACP agent (`toAcpAgent`/`serveAcp` in `@noetic-tools/acp`).
|
|
57
|
+
*
|
|
58
|
+
* Presentation only — it never gates anything. An undeclared tool falls back
|
|
59
|
+
* to kind `other` with its name as the title. Declared as methods (bivariant
|
|
60
|
+
* params) for the same reason as `ToolUiDeclaration`.
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
63
|
+
export interface ToolAcpDeclaration<I extends StandardSchemaV1 = StandardSchemaV1> {
|
|
64
|
+
/** ACP tool kind (`read`, `edit`, `execute`, …) for editor rendering. */
|
|
65
|
+
kind?: AcpToolKind;
|
|
66
|
+
/** Human-readable title; a function receives the call's parsed args. */
|
|
67
|
+
title?: string | ToolAcpTitleFn<I>;
|
|
68
|
+
/** File paths the call affects, surfaced as ACP `locations`. */
|
|
69
|
+
locations?(args: InferSchemaOutput<I>): string[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Bivariant function type for `ToolAcpDeclaration.title` — a union member
|
|
73
|
+
* cannot use method syntax, so the method-bearing object type is indexed to
|
|
74
|
+
* recover the same bivariance `ToolUiDeclaration`'s methods get, keeping a
|
|
75
|
+
* concretely-typed tool assignable to the erased `Tool` form.
|
|
76
|
+
* @public
|
|
77
|
+
*/
|
|
78
|
+
export type ToolAcpTitleFn<I extends StandardSchemaV1 = StandardSchemaV1> = {
|
|
79
|
+
bivariant(args: InferSchemaOutput<I>): string;
|
|
80
|
+
}['bivariant'];
|
|
53
81
|
/**
|
|
54
82
|
* A tool definition that an LLM can invoke during execution.
|
|
55
83
|
*
|
|
@@ -105,5 +133,7 @@ export interface Tool<I extends StandardSchemaV1 = StandardSchemaV1, O extends S
|
|
|
105
133
|
context?: ToolContextDeclaration;
|
|
106
134
|
/** Optional UI declaration — the runtime emits the rendered fragments at call/progress/result points. */
|
|
107
135
|
ui?: ToolUiDeclaration<I, O>;
|
|
136
|
+
/** Optional ACP presentation — how the call renders in an ACP client when the harness is served as an agent. */
|
|
137
|
+
acp?: ToolAcpDeclaration<I>;
|
|
108
138
|
}
|
|
109
139
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noetic-tools/types",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Foundational type contracts and primitives shared across the Noetic framework (items, LLM config, adapters, steering, errors).",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@openrouter/agent": "^0.6.0",
|
|
58
58
|
"@standard-schema/spec": "1.1.0",
|
|
59
|
+
"@zed-industries/agent-client-protocol": "^0.4.5",
|
|
59
60
|
"zod": "^4.0.0"
|
|
60
61
|
},
|
|
61
62
|
"scripts": {
|
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Coding-agent harness contract.
|
|
3
|
-
*
|
|
4
|
-
* A "harness" here is a pluggable backend that drives an external agentic
|
|
5
|
-
* coding tool — Claude Code, Codex, opencode, pi — as a Noetic step. It is the
|
|
6
|
-
* direct analogue of the `ContextLayer` contract: defined in the dependency-free
|
|
7
|
-
* `@noetic-tools/types` foundation so both `@noetic-tools/core` (which executes
|
|
8
|
-
* harness steps) and the per-tool `@noetic-tools/sub-harness-*` packages (which
|
|
9
|
-
* implement them) can depend on it without forming a cycle.
|
|
10
|
-
*
|
|
11
|
-
* Modelled on Vercel's `HarnessV1` spec: a tagged spec version, a small set of
|
|
12
|
-
* descriptive fields, and a single `doStart` entry point that yields a session.
|
|
13
|
-
* Optional capabilities are signalled by the presence of optional methods, not
|
|
14
|
-
* a static capabilities object — an adapter that cannot satisfy a request
|
|
15
|
-
* throws {@link SubHarnessCapabilityError} from the relevant method.
|
|
16
|
-
*/
|
|
17
|
-
import { z } from 'zod';
|
|
18
|
-
import type { TokenUsage } from './common.js';
|
|
19
|
-
import type { FsAdapter } from './fs-adapter.js';
|
|
20
|
-
import type { Item } from './items.js';
|
|
21
|
-
import type { ShellAdapter } from './shell-adapter.js';
|
|
22
|
-
import type { SubprocessAdapter } from './subprocess-adapter.js';
|
|
23
|
-
/**
|
|
24
|
-
* The set of harness step kinds. Each value is a distinct `Step.kind`, so a
|
|
25
|
-
* `step.claudeCode(...)` and a `step.codex(...)` are separate, individually
|
|
26
|
-
* typed step variants — while the interpreter routes all of them through a
|
|
27
|
-
* single shared `executeSubHarness` handler.
|
|
28
|
-
* @public
|
|
29
|
-
*/
|
|
30
|
-
export declare const SubHarnessKind: {
|
|
31
|
-
readonly ClaudeCode: 'claude-code';
|
|
32
|
-
readonly Codex: 'codex';
|
|
33
|
-
readonly Opencode: 'opencode';
|
|
34
|
-
readonly Pi: 'pi';
|
|
35
|
-
};
|
|
36
|
-
/** @public Union of all harness step kinds. */
|
|
37
|
-
export type SubHarnessKind = (typeof SubHarnessKind)[keyof typeof SubHarnessKind];
|
|
38
|
-
/** @public Ordered list of every harness kind — the single source of truth consumed by the JSON schema and the interpreter. */
|
|
39
|
-
export declare const SUB_HARNESS_KINDS: ReadonlyArray<SubHarnessKind>;
|
|
40
|
-
/**
|
|
41
|
-
* Settings shared by every harness step. Tool-specific knobs that don't map to
|
|
42
|
-
* a shared concept go through `extra`, which each adapter interprets (and may
|
|
43
|
-
* reject with {@link SubHarnessCapabilityError}).
|
|
44
|
-
* @public
|
|
45
|
-
*/
|
|
46
|
-
export interface SubHarnessSettings {
|
|
47
|
-
/** Model identifier for the underlying agent (e.g. `claude-opus-4-8`). */
|
|
48
|
-
model?: string;
|
|
49
|
-
/** Permission posture for tool/file mutations the agent attempts. */
|
|
50
|
-
permissionMode?: 'default' | 'plan' | 'acceptEdits' | 'bypassPermissions';
|
|
51
|
-
/** Hard cap on internal agent turns before it must yield. */
|
|
52
|
-
maxTurns?: number;
|
|
53
|
-
/** Restrict the agent to this set of built-in tool names. */
|
|
54
|
-
allowedTools?: ReadonlyArray<string>;
|
|
55
|
-
/** Tool-specific passthrough options interpreted by the adapter. */
|
|
56
|
-
extra?: Record<string, unknown>;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Controls how a harness session is reused and torn down across steps.
|
|
60
|
-
* @public
|
|
61
|
-
*/
|
|
62
|
-
export interface SubHarnessSessionPolicy {
|
|
63
|
-
/**
|
|
64
|
-
* Reuse a live session keyed by this id across multiple harness steps. When
|
|
65
|
-
* omitted, each step gets a fresh session that is stopped on completion.
|
|
66
|
-
*/
|
|
67
|
-
reuse?: string;
|
|
68
|
-
/**
|
|
69
|
-
* Lifecycle action when the step completes. `'stop'` (default) persists state
|
|
70
|
-
* and stops the runtime; `'detach'` parks it for later resume; `'destroy'`
|
|
71
|
-
* discards it with no resume state.
|
|
72
|
-
*/
|
|
73
|
-
onComplete?: 'stop' | 'detach' | 'destroy';
|
|
74
|
-
}
|
|
75
|
-
/** @public Why an agentic turn ended. */
|
|
76
|
-
export type SubHarnessFinishReason = 'stop' | 'length' | 'aborted' | 'error' | 'tool-calls';
|
|
77
|
-
/**
|
|
78
|
-
* Runtime validation schema for {@link SubHarnessStreamPart}. Adapters that move
|
|
79
|
-
* events across a process or transport boundary (e.g. a sandbox bridge)
|
|
80
|
-
* validate with this before forwarding.
|
|
81
|
-
* @public
|
|
82
|
-
*/
|
|
83
|
-
export declare const SubHarnessStreamPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
84
|
-
type: z.ZodLiteral<"stream-start">;
|
|
85
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
86
|
-
type: z.ZodLiteral<"text-delta">;
|
|
87
|
-
delta: z.ZodString;
|
|
88
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
89
|
-
type: z.ZodLiteral<"reasoning-delta">;
|
|
90
|
-
delta: z.ZodString;
|
|
91
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
92
|
-
type: z.ZodLiteral<"tool-call">;
|
|
93
|
-
toolCallId: z.ZodString;
|
|
94
|
-
toolName: z.ZodString;
|
|
95
|
-
input: z.ZodUnknown;
|
|
96
|
-
providerExecuted: z.ZodOptional<z.ZodBoolean>;
|
|
97
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
98
|
-
type: z.ZodLiteral<"tool-result">;
|
|
99
|
-
toolCallId: z.ZodString;
|
|
100
|
-
toolName: z.ZodString;
|
|
101
|
-
output: z.ZodUnknown;
|
|
102
|
-
isError: z.ZodOptional<z.ZodBoolean>;
|
|
103
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
104
|
-
type: z.ZodLiteral<"file-change">;
|
|
105
|
-
path: z.ZodOptional<z.ZodString>;
|
|
106
|
-
summary: z.ZodOptional<z.ZodString>;
|
|
107
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
108
|
-
type: z.ZodLiteral<"finish">;
|
|
109
|
-
finishReason: z.ZodEnum<{
|
|
110
|
-
aborted: "aborted";
|
|
111
|
-
error: "error";
|
|
112
|
-
length: "length";
|
|
113
|
-
stop: "stop";
|
|
114
|
-
"tool-calls": "tool-calls";
|
|
115
|
-
}>;
|
|
116
|
-
usage: z.ZodOptional<z.ZodObject<{
|
|
117
|
-
input: z.ZodNumber;
|
|
118
|
-
output: z.ZodNumber;
|
|
119
|
-
total: z.ZodOptional<z.ZodNumber>;
|
|
120
|
-
cached: z.ZodOptional<z.ZodNumber>;
|
|
121
|
-
}, z.core.$strip>>;
|
|
122
|
-
cost: z.ZodOptional<z.ZodNumber>;
|
|
123
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
124
|
-
type: z.ZodLiteral<"error">;
|
|
125
|
-
error: z.ZodString;
|
|
126
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
127
|
-
type: z.ZodLiteral<"raw">;
|
|
128
|
-
value: z.ZodUnknown;
|
|
129
|
-
}, z.core.$strip>], "type">;
|
|
130
|
-
/**
|
|
131
|
-
* A single event emitted by a harness during a turn. Mirrors the model-stream
|
|
132
|
-
* primitives so the interpreter can forward them as framework events with
|
|
133
|
-
* minimal translation. Adapter-specific metadata rides on `raw`.
|
|
134
|
-
* @public
|
|
135
|
-
*/
|
|
136
|
-
export type SubHarnessStreamPart = z.infer<typeof SubHarnessStreamPartSchema>;
|
|
137
|
-
/**
|
|
138
|
-
* The workspace surface a harness session may touch during a turn. A focused
|
|
139
|
-
* subset of {@link Context} so adapters don't depend on the full runtime type.
|
|
140
|
-
* @public
|
|
141
|
-
*/
|
|
142
|
-
export interface SubHarnessRunContext {
|
|
143
|
-
/** Working directory the agent runs in (resolved from `ctx.cwdState.cwd`). */
|
|
144
|
-
readonly cwd: string;
|
|
145
|
-
readonly fs: FsAdapter;
|
|
146
|
-
readonly shell: ShellAdapter;
|
|
147
|
-
readonly subprocess: SubprocessAdapter;
|
|
148
|
-
/** Conversation thread id, for adapters that persist per-thread session state. */
|
|
149
|
-
readonly threadId: string;
|
|
150
|
-
/** Abort signal for the surrounding execution. */
|
|
151
|
-
readonly signal?: AbortSignal;
|
|
152
|
-
}
|
|
153
|
-
/** @public Opaque, adapter-defined state for resuming a stopped/detached session. */
|
|
154
|
-
export interface SubHarnessResumeState {
|
|
155
|
-
readonly harnessId: string;
|
|
156
|
-
readonly sessionId: string;
|
|
157
|
-
readonly state: unknown;
|
|
158
|
-
}
|
|
159
|
-
/** @public Opaque, adapter-defined state for continuing a turn frozen mid-flight. */
|
|
160
|
-
export interface SubHarnessContinueState {
|
|
161
|
-
readonly harnessId: string;
|
|
162
|
-
readonly sessionId: string;
|
|
163
|
-
readonly state: unknown;
|
|
164
|
-
}
|
|
165
|
-
/** @public Options handed to {@link SubHarness.doStart}. */
|
|
166
|
-
export interface SubHarnessStartOptions<TSettings = SubHarnessSettings> {
|
|
167
|
-
/** Per-step settings (model, permission mode, …). */
|
|
168
|
-
settings?: TSettings;
|
|
169
|
-
/**
|
|
170
|
-
* System instructions applied once on the first message of a fresh session.
|
|
171
|
-
* Never re-applied on resume.
|
|
172
|
-
*/
|
|
173
|
-
instructions?: string;
|
|
174
|
-
/**
|
|
175
|
-
* Prior conversation history (from earlier LLM/sub-harness steps and turns)
|
|
176
|
-
* used to seed a fresh session so the agent has full context of the
|
|
177
|
-
* conversation so far. Empty for the very first step of a run.
|
|
178
|
-
*/
|
|
179
|
-
history?: ReadonlyArray<Item>;
|
|
180
|
-
/** The workspace surface for this run. */
|
|
181
|
-
ctx: SubHarnessRunContext;
|
|
182
|
-
/** Resume a previously stopped/detached session. */
|
|
183
|
-
resumeFrom?: SubHarnessResumeState;
|
|
184
|
-
/** Continue a turn previously frozen via {@link SubHarnessSession.doSuspendTurn}. */
|
|
185
|
-
continueFrom?: SubHarnessContinueState;
|
|
186
|
-
signal?: AbortSignal;
|
|
187
|
-
}
|
|
188
|
-
/** @public Options for a single agentic turn. */
|
|
189
|
-
export interface SubHarnessPromptTurnOptions {
|
|
190
|
-
/** Fresh turn input only — the session owns conversation history. */
|
|
191
|
-
prompt: string;
|
|
192
|
-
/** Sink for stream events produced during the turn. */
|
|
193
|
-
emit: (part: SubHarnessStreamPart) => void;
|
|
194
|
-
signal?: AbortSignal;
|
|
195
|
-
}
|
|
196
|
-
/** @public Options for continuing a turn frozen mid-flight. */
|
|
197
|
-
export interface SubHarnessContinueTurnOptions {
|
|
198
|
-
emit: (part: SubHarnessStreamPart) => void;
|
|
199
|
-
signal?: AbortSignal;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Result of a completed agentic turn. The interpreter appends `items` to the
|
|
203
|
-
* item log, charges `usage`/`cost`, and returns `text` (or parses it through
|
|
204
|
-
* the step's output schema).
|
|
205
|
-
* @public
|
|
206
|
-
*/
|
|
207
|
-
export interface SubHarnessTurnResult {
|
|
208
|
-
/** Noetic Items produced this turn (assistant message, tool calls/results). */
|
|
209
|
-
items: Item[];
|
|
210
|
-
/** Final assistant text of the turn. */
|
|
211
|
-
text: string;
|
|
212
|
-
usage?: TokenUsage;
|
|
213
|
-
cost?: number;
|
|
214
|
-
finishReason?: SubHarnessFinishReason;
|
|
215
|
-
/** Adapter-specific metadata (peer to provider metadata, not a subtype). */
|
|
216
|
-
harnessMetadata?: Record<string, unknown>;
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Describes a tool the underlying agent executes natively, mapped to a shared
|
|
220
|
-
* `commonName` so consumers can recognise "the same kind of tool" across
|
|
221
|
-
* harnesses (Claude's `Bash`, Codex's `shell`, pi's `bash` → `shell`).
|
|
222
|
-
* @public
|
|
223
|
-
*/
|
|
224
|
-
export interface SubHarnessBuiltinTool {
|
|
225
|
-
/** The agent's native tool name. */
|
|
226
|
-
readonly nativeName: string;
|
|
227
|
-
/** Shared cross-harness name, when one exists. */
|
|
228
|
-
readonly commonName?: string;
|
|
229
|
-
readonly description?: string;
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* A live harness session: one workspace + one conversation history + one
|
|
233
|
-
* running runtime, kept across turns by the interpreter.
|
|
234
|
-
* @public
|
|
235
|
-
*/
|
|
236
|
-
export interface SubHarnessSession {
|
|
237
|
-
readonly sessionId: string;
|
|
238
|
-
/** True when this session was resumed rather than freshly started. */
|
|
239
|
-
readonly isResume: boolean;
|
|
240
|
-
/** The model the session resolved to, when the runtime reports it. */
|
|
241
|
-
readonly modelId?: string;
|
|
242
|
-
/** Run one agentic turn to completion. */
|
|
243
|
-
doPromptTurn(opts: SubHarnessPromptTurnOptions): Promise<SubHarnessTurnResult>;
|
|
244
|
-
/** Continue a turn previously frozen via {@link doSuspendTurn}. */
|
|
245
|
-
doContinueTurn?(opts: SubHarnessContinueTurnOptions): Promise<SubHarnessTurnResult>;
|
|
246
|
-
/** Freeze the current turn at a precise event cursor; runtime stays alive. */
|
|
247
|
-
doSuspendTurn?(): Promise<SubHarnessContinueState>;
|
|
248
|
-
/** Manually compact conversation history. Throws {@link SubHarnessCapabilityError} if unsupported. */
|
|
249
|
-
doCompact?(customInstructions?: string): Promise<void>;
|
|
250
|
-
/** Park the session between turns; runtime stays alive. */
|
|
251
|
-
doDetach?(): Promise<SubHarnessResumeState>;
|
|
252
|
-
/** Persist state and stop the runtime. */
|
|
253
|
-
doStop(): Promise<SubHarnessResumeState>;
|
|
254
|
-
/** Stop the runtime with no resume state. */
|
|
255
|
-
doDestroy?(): Promise<void>;
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* A coding-agent harness. Each `@noetic-tools/sub-harness-*` package exports a
|
|
259
|
-
* factory returning one of these (e.g. `claudeCode({ model })`).
|
|
260
|
-
* @public
|
|
261
|
-
*/
|
|
262
|
-
export interface SubHarness<TSettings = SubHarnessSettings> {
|
|
263
|
-
/** Spec tag for forward-compatibility. */
|
|
264
|
-
readonly specificationVersion: 'harness-v1';
|
|
265
|
-
/** Stable identifier, equal to the step kind it backs (e.g. `claude-code`). */
|
|
266
|
-
readonly harnessId: SubHarnessKind;
|
|
267
|
-
/** Tools the underlying agent executes natively. */
|
|
268
|
-
readonly builtinTools?: ReadonlyArray<SubHarnessBuiltinTool>;
|
|
269
|
-
/** Validates `resumeFrom`/`continueFrom` payloads, when the adapter persists them. */
|
|
270
|
-
readonly lifecycleStateSchema?: z.ZodType;
|
|
271
|
-
/** Start (or resume/continue) a session. */
|
|
272
|
-
doStart(opts: SubHarnessStartOptions<TSettings>): Promise<SubHarnessSession>;
|
|
273
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Coding-agent harness contract.
|
|
3
|
-
*
|
|
4
|
-
* A "harness" here is a pluggable backend that drives an external agentic
|
|
5
|
-
* coding tool — Claude Code, Codex, opencode, pi — as a Noetic step. It is the
|
|
6
|
-
* direct analogue of the `ContextLayer` contract: defined in the dependency-free
|
|
7
|
-
* `@noetic-tools/types` foundation so both `@noetic-tools/core` (which executes
|
|
8
|
-
* harness steps) and the per-tool `@noetic-tools/sub-harness-*` packages (which
|
|
9
|
-
* implement them) can depend on it without forming a cycle.
|
|
10
|
-
*
|
|
11
|
-
* Modelled on Vercel's `HarnessV1` spec: a tagged spec version, a small set of
|
|
12
|
-
* descriptive fields, and a single `doStart` entry point that yields a session.
|
|
13
|
-
* Optional capabilities are signalled by the presence of optional methods, not
|
|
14
|
-
* a static capabilities object — an adapter that cannot satisfy a request
|
|
15
|
-
* throws {@link SubHarnessCapabilityError} from the relevant method.
|
|
16
|
-
*/
|
|
17
|
-
import { z } from 'zod';
|
|
18
|
-
//#region Step-kind discriminator
|
|
19
|
-
/**
|
|
20
|
-
* The set of harness step kinds. Each value is a distinct `Step.kind`, so a
|
|
21
|
-
* `step.claudeCode(...)` and a `step.codex(...)` are separate, individually
|
|
22
|
-
* typed step variants — while the interpreter routes all of them through a
|
|
23
|
-
* single shared `executeSubHarness` handler.
|
|
24
|
-
* @public
|
|
25
|
-
*/
|
|
26
|
-
export const SubHarnessKind = {
|
|
27
|
-
ClaudeCode: 'claude-code',
|
|
28
|
-
Codex: 'codex',
|
|
29
|
-
Opencode: 'opencode',
|
|
30
|
-
Pi: 'pi',
|
|
31
|
-
};
|
|
32
|
-
/** @public Ordered list of every harness kind — the single source of truth consumed by the JSON schema and the interpreter. */
|
|
33
|
-
export const SUB_HARNESS_KINDS = [
|
|
34
|
-
SubHarnessKind.ClaudeCode,
|
|
35
|
-
SubHarnessKind.Codex,
|
|
36
|
-
SubHarnessKind.Opencode,
|
|
37
|
-
SubHarnessKind.Pi,
|
|
38
|
-
];
|
|
39
|
-
const HarnessFinishReasonSchema = z.enum([
|
|
40
|
-
'stop',
|
|
41
|
-
'length',
|
|
42
|
-
'aborted',
|
|
43
|
-
'error',
|
|
44
|
-
'tool-calls',
|
|
45
|
-
]);
|
|
46
|
-
const TokenUsageSchema = z.object({
|
|
47
|
-
input: z.number(),
|
|
48
|
-
output: z.number(),
|
|
49
|
-
total: z.number().optional(),
|
|
50
|
-
cached: z.number().optional(),
|
|
51
|
-
});
|
|
52
|
-
/**
|
|
53
|
-
* Runtime validation schema for {@link SubHarnessStreamPart}. Adapters that move
|
|
54
|
-
* events across a process or transport boundary (e.g. a sandbox bridge)
|
|
55
|
-
* validate with this before forwarding.
|
|
56
|
-
* @public
|
|
57
|
-
*/
|
|
58
|
-
export const SubHarnessStreamPartSchema = z.discriminatedUnion('type', [
|
|
59
|
-
z.object({
|
|
60
|
-
type: z.literal('stream-start'),
|
|
61
|
-
}),
|
|
62
|
-
z.object({
|
|
63
|
-
type: z.literal('text-delta'),
|
|
64
|
-
delta: z.string(),
|
|
65
|
-
}),
|
|
66
|
-
z.object({
|
|
67
|
-
type: z.literal('reasoning-delta'),
|
|
68
|
-
delta: z.string(),
|
|
69
|
-
}),
|
|
70
|
-
z.object({
|
|
71
|
-
type: z.literal('tool-call'),
|
|
72
|
-
toolCallId: z.string(),
|
|
73
|
-
toolName: z.string(),
|
|
74
|
-
input: z.unknown(),
|
|
75
|
-
/** True when the underlying agent executed the tool itself (vs. host dispatch). */
|
|
76
|
-
providerExecuted: z.boolean().optional(),
|
|
77
|
-
}),
|
|
78
|
-
z.object({
|
|
79
|
-
type: z.literal('tool-result'),
|
|
80
|
-
toolCallId: z.string(),
|
|
81
|
-
toolName: z.string(),
|
|
82
|
-
output: z.unknown(),
|
|
83
|
-
isError: z.boolean().optional(),
|
|
84
|
-
}),
|
|
85
|
-
z.object({
|
|
86
|
-
type: z.literal('file-change'),
|
|
87
|
-
path: z.string().optional(),
|
|
88
|
-
summary: z.string().optional(),
|
|
89
|
-
}),
|
|
90
|
-
z.object({
|
|
91
|
-
type: z.literal('finish'),
|
|
92
|
-
finishReason: HarnessFinishReasonSchema,
|
|
93
|
-
usage: TokenUsageSchema.optional(),
|
|
94
|
-
cost: z.number().optional(),
|
|
95
|
-
}),
|
|
96
|
-
z.object({
|
|
97
|
-
type: z.literal('error'),
|
|
98
|
-
error: z.string(),
|
|
99
|
-
}),
|
|
100
|
-
/** Adapter-specific passthrough for events with no canonical mapping. */
|
|
101
|
-
z.object({
|
|
102
|
-
type: z.literal('raw'),
|
|
103
|
-
value: z.unknown(),
|
|
104
|
-
}),
|
|
105
|
-
]);
|
|
106
|
-
//#endregion
|