@actor0/harness 0.0.0-stage → 0.5.2

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.
@@ -0,0 +1,241 @@
1
+ export type ChatRole = "system" | "user" | "assistant" | "tool";
2
+ export type ToolCall = {
3
+ id: string;
4
+ type: "function";
5
+ function: {
6
+ name: string;
7
+ arguments: string;
8
+ };
9
+ };
10
+ export type ChatMessage = {
11
+ role: ChatRole;
12
+ content: string;
13
+ tool_calls?: ToolCall[];
14
+ tool_call_id?: string;
15
+ name?: string;
16
+ };
17
+ export type ToolDefinition = {
18
+ type: "function";
19
+ function: {
20
+ name: string;
21
+ description: string;
22
+ parameters: Record<string, unknown>;
23
+ };
24
+ };
25
+ export type Usage = {
26
+ prompt_tokens: number;
27
+ completion_tokens: number;
28
+ total_tokens: number;
29
+ cached_tokens?: number;
30
+ reasoning_tokens?: number;
31
+ };
32
+ export type ModelEvent = {
33
+ type: "token";
34
+ delta: string;
35
+ } | {
36
+ type: "reasoning";
37
+ delta: string;
38
+ } | {
39
+ type: "tool_call";
40
+ tool_calls: ToolCall[];
41
+ } | {
42
+ type: "usage";
43
+ usage: Usage;
44
+ } | {
45
+ type: "status";
46
+ note: string;
47
+ } | {
48
+ type: "provider";
49
+ name: string;
50
+ } | {
51
+ type: "done";
52
+ /**
53
+ * The endpoint stopped mid-answer — the output-token cap, or the
54
+ * model's own window, ran out. The text so far is the beginning of
55
+ * an answer, not one, and a caller that cannot tell the difference
56
+ * will save a fragment and call it a reply.
57
+ */
58
+ truncated?: boolean;
59
+ /** The endpoint's own word for it, kept for a message that must name a cause. */
60
+ reason?: string;
61
+ };
62
+ /**
63
+ * A protocol block the answer filter refused. `call` is the synthetic call
64
+ * that carries the error tool result into the transcript (the harness authors
65
+ * the result itself; no tool host runs), and `reason` is the sentence both
66
+ * the model and the UI see.
67
+ */
68
+ export type RejectedToolBlock = {
69
+ /** The name the model asked for — "unknown" when it emitted none. */
70
+ name: string;
71
+ call: ToolCall;
72
+ reason: string;
73
+ };
74
+ export type PlanPrefix = {
75
+ title: string;
76
+ plan: string;
77
+ consumed: number;
78
+ };
79
+ export type ReasoningSummary = {
80
+ title: string;
81
+ summary: string;
82
+ };
83
+ export type HarnessEvent = {
84
+ type: "token";
85
+ delta: string;
86
+ } | {
87
+ type: "reasoning";
88
+ delta: string;
89
+ } | {
90
+ type: "status";
91
+ status: string;
92
+ source: "marker" | "note";
93
+ } | {
94
+ type: "plan";
95
+ plan: PlanPrefix;
96
+ }
97
+ /**
98
+ * A model attempt is about to stream. Everything a host renders from the
99
+ * events that follow belongs to this attempt; a host that snapshots its
100
+ * render state here can discard exactly this attempt's output when the
101
+ * matching `reset` arrives.
102
+ */
103
+ | {
104
+ type: "attempt_start";
105
+ } | {
106
+ type: "reset";
107
+ attemptText: string;
108
+ } | {
109
+ type: "tool_start";
110
+ call: ToolCall;
111
+ } | {
112
+ type: "tool_result";
113
+ call: ToolCall;
114
+ output: string;
115
+ error?: string;
116
+ } | {
117
+ type: "tool_call";
118
+ tool_calls: ToolCall[];
119
+ }
120
+ /**
121
+ * A tool-call block was refused (unoffered tool, or arguments that were not
122
+ * valid JSON). Nothing reaches the answer text; the UI shows a cross and
123
+ * the model receives the error result next round.
124
+ */
125
+ | {
126
+ type: "tool_rejected";
127
+ rejection: RejectedToolBlock;
128
+ } | {
129
+ type: "provider";
130
+ name: string;
131
+ } | {
132
+ type: "usage";
133
+ usage: Usage;
134
+ } | {
135
+ type: "partial";
136
+ text: string;
137
+ } | {
138
+ type: "done";
139
+ text: string;
140
+ complete: boolean;
141
+ /** The endpoint cut this answer off at its output cap. `complete` is then false. */
142
+ truncated?: boolean;
143
+ /** The endpoint's finish/stop reason, when it named one. */
144
+ reason?: string;
145
+ }
146
+ /**
147
+ * The turn stopped because it could not make progress on its own. The
148
+ * harness does not decide to give up here — it reports the condition and the
149
+ * host decides, typically by asking the user whether to keep going.
150
+ */
151
+ | {
152
+ type: "needs_user";
153
+ reason: "tool_errors" | "round_limit";
154
+ message: string;
155
+ } | {
156
+ type: "error";
157
+ message: string;
158
+ retriable: boolean;
159
+ };
160
+ export type ModelClient = {
161
+ stream(messages: ChatMessage[], tools: ToolDefinition[], signal: AbortSignal): AsyncIterable<ModelEvent>;
162
+ };
163
+ export type ToolHost = {
164
+ definitions(): ToolDefinition[];
165
+ execute(call: ToolCall, signal: AbortSignal): Promise<string>;
166
+ };
167
+ export type HarnessObserver = {
168
+ event?(event: HarnessEvent): void | Promise<void>;
169
+ };
170
+ export type RoundResult = {
171
+ text: string;
172
+ toolCalls: ToolCall[];
173
+ /** Protocol blocks refused this round — see RejectedToolBlock. */
174
+ rejectedBlocks: RejectedToolBlock[];
175
+ complete: boolean;
176
+ /** The endpoint stopped this round's answer short — see the `done` event. */
177
+ truncated: boolean;
178
+ /** The endpoint's finish/stop reason, when it named one. */
179
+ truncationReason?: string;
180
+ reasoning: ReasoningSummary;
181
+ usage: Usage[];
182
+ };
183
+ export type ToolRoundPolicy = {
184
+ /** Return true when the completed tool round is already the final answer. */
185
+ shouldStopAfterTools?(input: {
186
+ calls: ToolCall[];
187
+ text: string;
188
+ round: number;
189
+ }): boolean;
190
+ /** Prompt used for the one permitted empty-answer continuation. */
191
+ emptyContinuationMessage?: string;
192
+ /** Prompt used for the one permitted continuation of a cut-off answer. */
193
+ truncationContinuationMessage?: string;
194
+ };
195
+ /**
196
+ * What one turn actually did, for a local audit log.
197
+ *
198
+ * `usage` is the token accounting; this is everything else a host would want
199
+ * to total up afterwards — how many rounds it took, which tools the model
200
+ * reached for and how often, and whether it finished. It is computed by the
201
+ * harness (which is the only thing that sees every round) and handed back on
202
+ * `RunResult`, so a host records it without re-deriving it from the event
203
+ * stream. It deliberately carries no model name or timestamp: the harness
204
+ * knows neither, and the host that does supplies them when it writes the log.
205
+ */
206
+ export type TurnAudit = {
207
+ /** Model rounds that ran (a round is one model call plus its tool executions). */
208
+ rounds: number;
209
+ /** Whether the turn ended with a complete, untruncated answer. */
210
+ complete: boolean;
211
+ /** Tool calls the model made, by tool name. Counts attempts, including failures. */
212
+ toolCalls: Record<string, number>;
213
+ /** Total tool calls across the turn — the sum of `toolCalls`. */
214
+ toolCallCount: number;
215
+ /** Tokens summed across every round. */
216
+ promptTokens: number;
217
+ completionTokens: number;
218
+ totalTokens: number;
219
+ };
220
+ export type RunResult = {
221
+ messages: ChatMessage[];
222
+ text: string;
223
+ complete: boolean;
224
+ rounds: number;
225
+ usage: Usage[];
226
+ reasoning: ReasoningSummary;
227
+ /** What the turn did, for a host's audit log — see TurnAudit. */
228
+ audit: TurnAudit;
229
+ /** True when the turn stopped on `needs_user` and can be resumed. */
230
+ blocked?: boolean;
231
+ /**
232
+ * The turn ended with the model's answer cut off by the output cap, and
233
+ * the one permitted continuation did not finish it either. The text is
234
+ * real and is returned, but the host has to say it is unfinished.
235
+ */
236
+ truncated?: boolean;
237
+ /** The endpoint's finish/stop reason, when it named one. */
238
+ truncationReason?: string;
239
+ };
240
+ export declare const emptyUsage: () => Usage;
241
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;AAEhE,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACrC,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,QAAQ,EAAE,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IACE,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE;AACpC;;;;;GAKG;GACD;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,QAAQ,EAAE,CAAA;CAAE;AAC/C;;;;GAIG;GACD;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,SAAS,EAAE,iBAAiB,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IACA,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AACD;;;;GAIG;GACD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC;AAE3D,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,CACJ,QAAQ,EAAE,WAAW,EAAE,EACvB,KAAK,EAAE,cAAc,EAAE,EACvB,MAAM,EAAE,WAAW,GAClB,aAAa,CAAC,UAAU,CAAC,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,WAAW,IAAI,cAAc,EAAE,CAAC;IAChC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,kEAAkE;IAClE,cAAc,EAAE,iBAAiB,EAAE,CAAC;IACpC,QAAQ,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,SAAS,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,KAAK,EAAE,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,6EAA6E;IAC7E,oBAAoB,CAAC,CAAC,KAAK,EAAE;QAC3B,KAAK,EAAE,QAAQ,EAAE,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC;IACZ,mEAAmE;IACnE,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,0EAA0E;IAC1E,6BAA6B,CAAC,EAAE,MAAM,CAAC;CACxC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,QAAQ,EAAE,OAAO,CAAC;IAClB,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,iEAAiE;IACjE,aAAa,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,SAAS,EAAE,gBAAgB,CAAC;IAC5B,iEAAiE;IACjE,KAAK,EAAE,SAAS,CAAC;IACjB,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,UAAU,QAAO,KAI5B,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ export const emptyUsage = () => ({
2
+ prompt_tokens: 0,
3
+ completion_tokens: 0,
4
+ total_tokens: 0,
5
+ });
package/package.json CHANGED
@@ -1,6 +1,30 @@
1
- {
2
- "name": "@actor0/harness",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {
2
+ "name": "@actor0/harness",
3
+ "version": "0.5.2",
4
+ "type": "module",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "scripts": {
17
+ "build": "tsc -p tsconfig.build.json --tsBuildInfoFile dist/.tsbuildinfo",
18
+ "prepack": "node -e \"require('fs').rmSync('dist/.tsbuildinfo',{force:true})\"",
19
+ "test": "node --import tsx --test \"src/**/*.test.ts\"",
20
+ "typecheck": "tsc -p tsconfig.json --noEmit"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^20",
24
+ "tsx": "^4.20",
25
+ "typescript": "^5.9"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ }
30
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.