@fifthrevision/axle 0.17.0 → 0.19.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/README.md +125 -12
- package/dist/ProceduralMemory-CNxHj5B2.js +45 -0
- package/dist/accumulator-D2NgIGxp.d.ts +547 -0
- package/dist/accumulator-vmmD3pxt.js +1 -0
- package/dist/cli.js +5 -5
- package/dist/index.d.ts +128 -415
- package/dist/index.js +1 -1
- package/dist/models-Bp_jVWHN.js +1 -0
- package/dist/models-C7fdWvZ6.js +1 -0
- package/dist/{models-CI5k-LHn.d.ts → models-Whj6ZP3l.d.ts} +3 -1
- package/dist/providers/models.d.ts +1 -1
- package/dist/providers/models.js +1 -1
- package/dist/ui.d.ts +2 -0
- package/dist/ui.js +1 -0
- package/package.json +15 -11
- package/dist/ProceduralMemory-JWM3glv-.js +0 -45
- package/dist/models-CKz-RHh1.js +0 -1
- package/dist/models-DlE4tfcj.js +0 -1
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Token usage reported by a provider response.
|
|
4
|
+
*/
|
|
5
|
+
interface Stats {
|
|
6
|
+
/** Total effective input tokens. Includes `cachedIn` and `cacheWriteIn` when reported. */
|
|
7
|
+
in: number;
|
|
8
|
+
/** Total output tokens. Includes `reasoningOut` when reported. */
|
|
9
|
+
out: number;
|
|
10
|
+
/** Input tokens served from provider prompt/context cache. Included in `in`. */
|
|
11
|
+
cachedIn?: number;
|
|
12
|
+
/** Input tokens written into provider prompt/context cache. Included in `in`. */
|
|
13
|
+
cacheWriteIn?: number;
|
|
14
|
+
/** Output tokens spent on reasoning/thinking. Included in `out`. */
|
|
15
|
+
reasoningOut?: number;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/tracer/types.d.ts
|
|
19
|
+
type SpanStatus = "ok" | "error";
|
|
20
|
+
type EventLevel = "debug" | "info" | "warn" | "error";
|
|
21
|
+
type SpanType = string;
|
|
22
|
+
interface SpanEvent {
|
|
23
|
+
name: string;
|
|
24
|
+
timestamp: number;
|
|
25
|
+
level: EventLevel;
|
|
26
|
+
attributes?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
interface SpanData {
|
|
29
|
+
traceId: string;
|
|
30
|
+
spanId: string;
|
|
31
|
+
parentSpanId?: string;
|
|
32
|
+
name: string;
|
|
33
|
+
type?: SpanType;
|
|
34
|
+
startTime: number;
|
|
35
|
+
endTime?: number;
|
|
36
|
+
status: SpanStatus;
|
|
37
|
+
attributes: Record<string, unknown>;
|
|
38
|
+
events: SpanEvent[];
|
|
39
|
+
result?: SpanResult;
|
|
40
|
+
}
|
|
41
|
+
interface SpanOptions {
|
|
42
|
+
type?: SpanType;
|
|
43
|
+
}
|
|
44
|
+
type SpanResult = LLMResult | ToolResult;
|
|
45
|
+
interface LLMResult {
|
|
46
|
+
kind: "llm";
|
|
47
|
+
model: string;
|
|
48
|
+
request: LLMRequest;
|
|
49
|
+
response: LLMResponse;
|
|
50
|
+
usage?: TokenUsage;
|
|
51
|
+
finishReason?: string;
|
|
52
|
+
}
|
|
53
|
+
interface LLMRequest {
|
|
54
|
+
messages: unknown[];
|
|
55
|
+
system?: string;
|
|
56
|
+
tools?: unknown[];
|
|
57
|
+
}
|
|
58
|
+
interface LLMResponse {
|
|
59
|
+
content: unknown;
|
|
60
|
+
}
|
|
61
|
+
interface TokenUsage {
|
|
62
|
+
inputTokens?: number;
|
|
63
|
+
outputTokens?: number;
|
|
64
|
+
totalTokens?: number;
|
|
65
|
+
cachedInputTokens?: number;
|
|
66
|
+
cacheWriteInputTokens?: number;
|
|
67
|
+
reasoningOutputTokens?: number;
|
|
68
|
+
}
|
|
69
|
+
interface ToolResult {
|
|
70
|
+
kind: "tool";
|
|
71
|
+
name: string;
|
|
72
|
+
input: unknown;
|
|
73
|
+
output: unknown;
|
|
74
|
+
}
|
|
75
|
+
interface TraceWriter {
|
|
76
|
+
onSpanStart(span: SpanData): void;
|
|
77
|
+
onSpanUpdate?(span: SpanData): void;
|
|
78
|
+
onSpanEnd(span: SpanData): void;
|
|
79
|
+
onEvent?(span: SpanData, event: SpanEvent): void;
|
|
80
|
+
flush?(): Promise<void>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Tracing context for a span. Created by Tracer.startSpan().
|
|
84
|
+
* Can create child spans and log events within the span's scope.
|
|
85
|
+
*/
|
|
86
|
+
interface TracingContext {
|
|
87
|
+
startSpan(name: string, options?: SpanOptions): TracingContext;
|
|
88
|
+
end(status?: SpanStatus): void;
|
|
89
|
+
debug(message: string, attributes?: Record<string, unknown>): void;
|
|
90
|
+
info(message: string, attributes?: Record<string, unknown>): void;
|
|
91
|
+
warn(message: string, attributes?: Record<string, unknown>): void;
|
|
92
|
+
error(message: string, attributes?: Record<string, unknown>): void;
|
|
93
|
+
setAttribute(key: string, value: unknown): void;
|
|
94
|
+
setAttributes(attributes: Record<string, unknown>): void;
|
|
95
|
+
setResult(result: SpanResult): void;
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/utils/file.d.ts
|
|
99
|
+
type FileKind = "image" | "document" | "text";
|
|
100
|
+
type TextSource = {
|
|
101
|
+
type: "text";
|
|
102
|
+
content: string;
|
|
103
|
+
} | {
|
|
104
|
+
type: "url";
|
|
105
|
+
url: string;
|
|
106
|
+
} | {
|
|
107
|
+
type: "ref";
|
|
108
|
+
ref: unknown;
|
|
109
|
+
};
|
|
110
|
+
type BinarySource = {
|
|
111
|
+
type: "base64";
|
|
112
|
+
data: string;
|
|
113
|
+
} | {
|
|
114
|
+
type: "url";
|
|
115
|
+
url: string;
|
|
116
|
+
} | {
|
|
117
|
+
type: "ref";
|
|
118
|
+
ref: unknown;
|
|
119
|
+
};
|
|
120
|
+
interface BaseFile {
|
|
121
|
+
mimeType: string;
|
|
122
|
+
name: string;
|
|
123
|
+
size?: number;
|
|
124
|
+
}
|
|
125
|
+
type TextFileInfo = BaseFile & {
|
|
126
|
+
kind: "text";
|
|
127
|
+
source: TextSource;
|
|
128
|
+
};
|
|
129
|
+
type BinaryFileInfo = BaseFile & {
|
|
130
|
+
kind: "image" | "document";
|
|
131
|
+
source: BinarySource;
|
|
132
|
+
};
|
|
133
|
+
type FileInfo = TextFileInfo | BinaryFileInfo;
|
|
134
|
+
type InlineTextFile = TextFileInfo & {
|
|
135
|
+
source: {
|
|
136
|
+
type: "text";
|
|
137
|
+
content: string;
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
type InlineBinaryFile = BinaryFileInfo & {
|
|
141
|
+
source: {
|
|
142
|
+
type: "base64";
|
|
143
|
+
data: string;
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
type DeferredFileInfo = FileInfo & {
|
|
147
|
+
source: {
|
|
148
|
+
type: "ref";
|
|
149
|
+
ref: unknown;
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
type ConcreteFileInfo = FileInfo & {
|
|
153
|
+
source: {
|
|
154
|
+
type: "text";
|
|
155
|
+
} | {
|
|
156
|
+
type: "base64";
|
|
157
|
+
} | {
|
|
158
|
+
type: "url";
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
type FileProviderId = "anthropic" | "openai" | "gemini" | "chatcompletions";
|
|
162
|
+
type FileResolveFormat = "base64" | "url" | "text" | "gemini-file-uri";
|
|
163
|
+
type ResolvedFileSource = {
|
|
164
|
+
type: "base64";
|
|
165
|
+
data: string;
|
|
166
|
+
mimeType?: string;
|
|
167
|
+
name?: string;
|
|
168
|
+
} | {
|
|
169
|
+
type: "url";
|
|
170
|
+
url: string;
|
|
171
|
+
mimeType?: string;
|
|
172
|
+
name?: string;
|
|
173
|
+
} | {
|
|
174
|
+
type: "text";
|
|
175
|
+
content: string;
|
|
176
|
+
mimeType?: string;
|
|
177
|
+
name?: string;
|
|
178
|
+
} | {
|
|
179
|
+
type: "gemini-file-uri";
|
|
180
|
+
uri: string;
|
|
181
|
+
mimeType?: string;
|
|
182
|
+
name?: string;
|
|
183
|
+
};
|
|
184
|
+
interface FileResolveRequest {
|
|
185
|
+
file: DeferredFileInfo;
|
|
186
|
+
ref: unknown;
|
|
187
|
+
provider: FileProviderId;
|
|
188
|
+
model: string;
|
|
189
|
+
accepted: FileResolveFormat[];
|
|
190
|
+
signal?: AbortSignal;
|
|
191
|
+
}
|
|
192
|
+
type FileResolver = (request: FileResolveRequest) => Promise<ResolvedFileSource>;
|
|
193
|
+
/**
|
|
194
|
+
* Load a file with the specified encoding or auto-detect based on file extension
|
|
195
|
+
* @param filePath - Path to the file
|
|
196
|
+
* @param encoding - How to load the file: "utf-8" for text, "base64" for binary, or omit for auto-detection
|
|
197
|
+
* @returns FileInfo object with appropriate content based on encoding
|
|
198
|
+
*/
|
|
199
|
+
declare function loadFileContent(filePath: string): Promise<FileInfo>;
|
|
200
|
+
declare function loadFileContent(filePath: string, encoding: "utf-8"): Promise<InlineTextFile>;
|
|
201
|
+
declare function loadFileContent(filePath: string, encoding: "base64"): Promise<InlineBinaryFile>;
|
|
202
|
+
//#endregion
|
|
203
|
+
//#region src/turns/types.d.ts
|
|
204
|
+
/**
|
|
205
|
+
* Lifecycle state for a renderable turn.
|
|
206
|
+
*
|
|
207
|
+
* Turns are presentation state. They describe what a consumer can render, not
|
|
208
|
+
* the canonical model conversation state.
|
|
209
|
+
*/
|
|
210
|
+
type TurnStatus = "streaming" | "complete" | "cancelled" | "error";
|
|
211
|
+
/**
|
|
212
|
+
* ISO timestamp metadata for a turn, part, action, or annotation.
|
|
213
|
+
*/
|
|
214
|
+
interface TimingInfo {
|
|
215
|
+
/** ISO timestamp for when the item started. */
|
|
216
|
+
start: string;
|
|
217
|
+
/** ISO timestamp for when the item finished, when known. */
|
|
218
|
+
end?: string;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Where an annotation should render relative to its target.
|
|
222
|
+
*/
|
|
223
|
+
type AnnotationPlacement = "before" | "after";
|
|
224
|
+
/**
|
|
225
|
+
* Lifecycle state for an annotation.
|
|
226
|
+
*
|
|
227
|
+
* Omit this for static/informational annotations that do not have a running or
|
|
228
|
+
* terminal state.
|
|
229
|
+
*/
|
|
230
|
+
type AnnotationStatus = "running" | "complete" | "cancelled" | "error";
|
|
231
|
+
/**
|
|
232
|
+
* Render metadata attached to a session, turn, or turn part.
|
|
233
|
+
*
|
|
234
|
+
* Annotations let hosts attach out-of-band UI such as sandbox startup, eval
|
|
235
|
+
* results, or deployment state without turning that data into model state.
|
|
236
|
+
*
|
|
237
|
+
* @typeParam TData - Consumer-owned payload for the annotation kind.
|
|
238
|
+
* @typeParam TKind - Discriminator for the annotation kind.
|
|
239
|
+
*/
|
|
240
|
+
interface Annotation<TData = unknown, TKind extends string = string> {
|
|
241
|
+
/** Globally unique annotation id. */
|
|
242
|
+
id: string;
|
|
243
|
+
/** Consumer-defined annotation kind, used as a discriminator. */
|
|
244
|
+
kind: TKind;
|
|
245
|
+
/** Human-readable label for generic renderers. */
|
|
246
|
+
label: string;
|
|
247
|
+
/** Render placement relative to the target. Defaults to `"after"` when accumulated. */
|
|
248
|
+
placement?: AnnotationPlacement;
|
|
249
|
+
/** Optional lifecycle state for the annotation. */
|
|
250
|
+
status?: AnnotationStatus;
|
|
251
|
+
/** Consumer-owned annotation payload. */
|
|
252
|
+
data?: TData;
|
|
253
|
+
/** Optional timing metadata. */
|
|
254
|
+
timing?: TimingInfo;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Renderable presentation state for one user or agent turn.
|
|
258
|
+
*
|
|
259
|
+
* `Turn` is the snapshot counterpart to `TurnEvent`: events describe changes,
|
|
260
|
+
* and turns are the accumulated render state. The model-facing conversation
|
|
261
|
+
* remains `AxleMessage[]`.
|
|
262
|
+
*
|
|
263
|
+
* @typeParam TAnnotation - Annotation union supported by the host renderer.
|
|
264
|
+
*/
|
|
265
|
+
interface Turn<TAnnotation extends Annotation = Annotation> {
|
|
266
|
+
/** Stable turn id. */
|
|
267
|
+
id: string;
|
|
268
|
+
/** Whether the turn was produced by the user or the agent. */
|
|
269
|
+
owner: "user" | "agent";
|
|
270
|
+
/** Renderable parts in display order. */
|
|
271
|
+
parts: TurnPart<TAnnotation>[];
|
|
272
|
+
/** Current lifecycle state for the turn. */
|
|
273
|
+
status: TurnStatus;
|
|
274
|
+
/** Annotations attached to the whole turn. */
|
|
275
|
+
annotations?: TAnnotation[];
|
|
276
|
+
/** Optional timing metadata. */
|
|
277
|
+
timing?: TimingInfo;
|
|
278
|
+
/** Token usage accumulated for this turn, when available. */
|
|
279
|
+
usage?: Stats;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Any renderable part within a turn.
|
|
283
|
+
*/
|
|
284
|
+
type TurnPart<TAnnotation extends Annotation = Annotation> = TextPart<TAnnotation> | FilePart<TAnnotation> | ThinkingPart<TAnnotation> | ActionPart<TAnnotation>;
|
|
285
|
+
/**
|
|
286
|
+
* Assistant or user text content.
|
|
287
|
+
*/
|
|
288
|
+
interface TextPart<TAnnotation extends Annotation = Annotation> {
|
|
289
|
+
/** Stable part id. */
|
|
290
|
+
id: string;
|
|
291
|
+
/** Part discriminator. */
|
|
292
|
+
type: "text";
|
|
293
|
+
/** Accumulated text content. */
|
|
294
|
+
text: string;
|
|
295
|
+
/** Annotations attached to this part. */
|
|
296
|
+
annotations?: TAnnotation[];
|
|
297
|
+
/** Optional timing metadata. */
|
|
298
|
+
timing?: TimingInfo;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* File content attached to a user turn.
|
|
302
|
+
*/
|
|
303
|
+
interface FilePart<TAnnotation extends Annotation = Annotation> {
|
|
304
|
+
/** Stable part id. */
|
|
305
|
+
id: string;
|
|
306
|
+
/** Part discriminator. */
|
|
307
|
+
type: "file";
|
|
308
|
+
/** File metadata and source reference. */
|
|
309
|
+
file: FileInfo;
|
|
310
|
+
/** Annotations attached to this part. */
|
|
311
|
+
annotations?: TAnnotation[];
|
|
312
|
+
/** Optional timing metadata. */
|
|
313
|
+
timing?: TimingInfo;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Model thinking or reasoning content when surfaced by the provider.
|
|
317
|
+
*/
|
|
318
|
+
interface ThinkingPart<TAnnotation extends Annotation = Annotation> {
|
|
319
|
+
/** Stable part id. */
|
|
320
|
+
id: string;
|
|
321
|
+
/** Part discriminator. */
|
|
322
|
+
type: "thinking";
|
|
323
|
+
/** Accumulated thinking text. */
|
|
324
|
+
text: string;
|
|
325
|
+
/** Optional provider-supplied summary. */
|
|
326
|
+
summary?: string;
|
|
327
|
+
/** Whether the provider marked the thinking content as redacted. */
|
|
328
|
+
redacted?: boolean;
|
|
329
|
+
/** Annotations attached to this part. */
|
|
330
|
+
annotations?: TAnnotation[];
|
|
331
|
+
/** Optional timing metadata. */
|
|
332
|
+
timing?: TimingInfo;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Shared fields for tool, subagent, and provider-managed actions.
|
|
336
|
+
*
|
|
337
|
+
* @internal
|
|
338
|
+
*/
|
|
339
|
+
interface ActionPartBase<TAnnotation extends Annotation = Annotation> {
|
|
340
|
+
id: string;
|
|
341
|
+
type: "action";
|
|
342
|
+
kind: string;
|
|
343
|
+
status: "pending" | "running" | "complete" | "cancelled" | "error";
|
|
344
|
+
annotations?: TAnnotation[];
|
|
345
|
+
timing?: TimingInfo;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Action part for an executable Axle tool call.
|
|
349
|
+
*/
|
|
350
|
+
interface ToolAction<TAnnotation extends Annotation = Annotation> extends ActionPartBase<TAnnotation> {
|
|
351
|
+
/** Action discriminator. */
|
|
352
|
+
kind: "tool";
|
|
353
|
+
/** Tool display and execution details. */
|
|
354
|
+
detail: {
|
|
355
|
+
/** Tool name. */name: string; /** Parsed tool parameters once execution starts. */
|
|
356
|
+
parameters: Record<string, unknown>; /** Accumulated JSON argument text before parameters are parsed. */
|
|
357
|
+
pendingArgs?: string; /** Tool result or in-progress output. */
|
|
358
|
+
result?: ActionResult;
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Action part for a nested agent/subagent run.
|
|
363
|
+
*/
|
|
364
|
+
interface SubagentAction<TAnnotation extends Annotation = Annotation> extends ActionPartBase<TAnnotation> {
|
|
365
|
+
/** Action discriminator. */
|
|
366
|
+
kind: "agent";
|
|
367
|
+
/** Subagent display and result details. */
|
|
368
|
+
detail: {
|
|
369
|
+
/** Subagent name. */name: string; /** Optional subagent configuration shown to renderers. */
|
|
370
|
+
config?: Record<string, unknown>; /** Child turns produced by the subagent. */
|
|
371
|
+
children: Turn<TAnnotation>[]; /** Final subagent result, when available. */
|
|
372
|
+
result?: ActionResult;
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Action part for provider-managed tools such as hosted web search or code
|
|
377
|
+
* execution.
|
|
378
|
+
*/
|
|
379
|
+
interface ProviderToolAction<TAnnotation extends Annotation = Annotation> extends ActionPartBase<TAnnotation> {
|
|
380
|
+
/** Action discriminator. */
|
|
381
|
+
kind: "provider-tool";
|
|
382
|
+
/** Provider tool display and result details. */
|
|
383
|
+
detail: {
|
|
384
|
+
/** Provider tool name. */name: string; /** Provider-specific input, when surfaced. */
|
|
385
|
+
input?: unknown; /** Provider tool result, when surfaced. */
|
|
386
|
+
result?: ActionResult;
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Any action part in a turn.
|
|
391
|
+
*/
|
|
392
|
+
type ActionPart<TAnnotation extends Annotation = Annotation> = ToolAction<TAnnotation> | SubagentAction<TAnnotation> | ProviderToolAction<TAnnotation>;
|
|
393
|
+
/**
|
|
394
|
+
* Renderable result for an action.
|
|
395
|
+
*/
|
|
396
|
+
type ActionResult = {
|
|
397
|
+
type: "in-progress";
|
|
398
|
+
content: string;
|
|
399
|
+
} | {
|
|
400
|
+
type: "success";
|
|
401
|
+
content: unknown;
|
|
402
|
+
} | {
|
|
403
|
+
type: "error";
|
|
404
|
+
error: {
|
|
405
|
+
type: string;
|
|
406
|
+
message: string;
|
|
407
|
+
};
|
|
408
|
+
};
|
|
409
|
+
//#endregion
|
|
410
|
+
//#region src/turns/events.d.ts
|
|
411
|
+
type AnnotationTarget = {
|
|
412
|
+
type: "session";
|
|
413
|
+
} | {
|
|
414
|
+
type: "turn";
|
|
415
|
+
turnId: string;
|
|
416
|
+
} | {
|
|
417
|
+
type: "part";
|
|
418
|
+
turnId: string;
|
|
419
|
+
partId: string;
|
|
420
|
+
};
|
|
421
|
+
type AnnotationEvent<TAnnotation extends Annotation = Annotation> = {
|
|
422
|
+
type: "annotation:start";
|
|
423
|
+
target: AnnotationTarget;
|
|
424
|
+
annotation: TAnnotation;
|
|
425
|
+
} | {
|
|
426
|
+
type: "annotation:update";
|
|
427
|
+
target: AnnotationTarget;
|
|
428
|
+
annotation: TAnnotation;
|
|
429
|
+
} | {
|
|
430
|
+
type: "annotation:end";
|
|
431
|
+
target: AnnotationTarget;
|
|
432
|
+
annotation: TAnnotation;
|
|
433
|
+
};
|
|
434
|
+
type TurnEvent<TAnnotation extends Annotation = Annotation> = {
|
|
435
|
+
type: "session:restore";
|
|
436
|
+
turns: Turn<TAnnotation>[];
|
|
437
|
+
sessionAnnotations?: TAnnotation[];
|
|
438
|
+
config?: Record<string, unknown>;
|
|
439
|
+
} | {
|
|
440
|
+
type: "turn:user";
|
|
441
|
+
turn: Turn<TAnnotation>;
|
|
442
|
+
} | {
|
|
443
|
+
type: "turn:start";
|
|
444
|
+
turnId: string;
|
|
445
|
+
timing?: TimingInfo;
|
|
446
|
+
} | {
|
|
447
|
+
type: "turn:end";
|
|
448
|
+
turnId: string;
|
|
449
|
+
status: TurnStatus;
|
|
450
|
+
usage: Stats;
|
|
451
|
+
timing?: TimingInfo;
|
|
452
|
+
} | {
|
|
453
|
+
type: "part:start";
|
|
454
|
+
turnId: string;
|
|
455
|
+
part: TurnPart<TAnnotation>;
|
|
456
|
+
} | {
|
|
457
|
+
type: "text:delta";
|
|
458
|
+
turnId: string;
|
|
459
|
+
partId: string;
|
|
460
|
+
delta: string;
|
|
461
|
+
} | {
|
|
462
|
+
type: "thinking:delta";
|
|
463
|
+
turnId: string;
|
|
464
|
+
partId: string;
|
|
465
|
+
delta: string;
|
|
466
|
+
} | {
|
|
467
|
+
type: "part:end";
|
|
468
|
+
turnId: string;
|
|
469
|
+
partId: string;
|
|
470
|
+
timing?: TimingInfo;
|
|
471
|
+
} | {
|
|
472
|
+
type: "action:args-delta";
|
|
473
|
+
turnId: string;
|
|
474
|
+
partId: string;
|
|
475
|
+
delta: string;
|
|
476
|
+
accumulated: string;
|
|
477
|
+
} | {
|
|
478
|
+
type: "action:running";
|
|
479
|
+
turnId: string;
|
|
480
|
+
partId: string;
|
|
481
|
+
parameters?: Record<string, unknown>;
|
|
482
|
+
} | {
|
|
483
|
+
type: "action:progress";
|
|
484
|
+
turnId: string;
|
|
485
|
+
partId: string;
|
|
486
|
+
chunk: string;
|
|
487
|
+
} | {
|
|
488
|
+
type: "action:complete";
|
|
489
|
+
turnId: string;
|
|
490
|
+
partId: string;
|
|
491
|
+
result: ActionResult;
|
|
492
|
+
timing?: TimingInfo;
|
|
493
|
+
} | {
|
|
494
|
+
type: "action:error";
|
|
495
|
+
turnId: string;
|
|
496
|
+
partId: string;
|
|
497
|
+
error: {
|
|
498
|
+
type: string;
|
|
499
|
+
message: string;
|
|
500
|
+
};
|
|
501
|
+
timing?: TimingInfo;
|
|
502
|
+
} | {
|
|
503
|
+
type: "action:child-event";
|
|
504
|
+
turnId: string;
|
|
505
|
+
partId: string;
|
|
506
|
+
event: TurnEvent<TAnnotation>;
|
|
507
|
+
} | AnnotationEvent<TAnnotation> | {
|
|
508
|
+
type: "error";
|
|
509
|
+
error: {
|
|
510
|
+
type: string;
|
|
511
|
+
message: string;
|
|
512
|
+
};
|
|
513
|
+
};
|
|
514
|
+
//#endregion
|
|
515
|
+
//#region src/turns/accumulator.d.ts
|
|
516
|
+
interface TurnAccumulatorState<TAnnotation extends Annotation = Annotation> {
|
|
517
|
+
turns: Turn<TAnnotation>[];
|
|
518
|
+
sessionAnnotations?: TAnnotation[];
|
|
519
|
+
}
|
|
520
|
+
type UnknownEvent = {
|
|
521
|
+
type: string;
|
|
522
|
+
};
|
|
523
|
+
type AccumulatableEvent<TAnnotation extends Annotation = Annotation, THostEvent extends UnknownEvent = UnknownEvent> = TurnEvent<TAnnotation> | THostEvent;
|
|
524
|
+
type TurnAccumulatorResult<TAnnotation extends Annotation = Annotation, THostEvent extends UnknownEvent = UnknownEvent> = {
|
|
525
|
+
handled: true;
|
|
526
|
+
state: TurnAccumulatorState<TAnnotation>;
|
|
527
|
+
event: TurnEvent<TAnnotation>;
|
|
528
|
+
} | {
|
|
529
|
+
handled: false;
|
|
530
|
+
state: TurnAccumulatorState<TAnnotation>;
|
|
531
|
+
event: THostEvent;
|
|
532
|
+
};
|
|
533
|
+
declare class TurnAccumulator<TAnnotation extends Annotation = Annotation, THostEvent extends UnknownEvent = UnknownEvent> {
|
|
534
|
+
private _state;
|
|
535
|
+
constructor(init?: TurnAccumulatorState<TAnnotation>);
|
|
536
|
+
get state(): TurnAccumulatorState<TAnnotation>;
|
|
537
|
+
apply(event: AccumulatableEvent<TAnnotation, THostEvent>): TurnAccumulatorResult<TAnnotation, THostEvent>;
|
|
538
|
+
private replaceState;
|
|
539
|
+
private replaceTurns;
|
|
540
|
+
private updateTurn;
|
|
541
|
+
private updatePart;
|
|
542
|
+
private addAnnotation;
|
|
543
|
+
private replaceAnnotation;
|
|
544
|
+
private handled;
|
|
545
|
+
}
|
|
546
|
+
//#endregion
|
|
547
|
+
export { FileResolveRequest as A, TracingContext as B, TurnStatus as C, FileKind as D, FileInfo as E, SpanData as F, SpanEvent as I, SpanOptions as L, ResolvedFileSource as M, loadFileContent as N, FileProviderId as O, EventLevel as P, SpanType as R, TurnPart as S, DeferredFileInfo as T, Stats as V, TextPart as _, UnknownEvent as a, ToolAction as b, TurnEvent as c, Annotation as d, AnnotationPlacement as f, SubagentAction as g, ProviderToolAction as h, TurnAccumulatorState as i, FileResolver as j, FileResolveFormat as k, ActionPart as l, FilePart as m, TurnAccumulator as n, AnnotationEvent as o, AnnotationStatus as p, TurnAccumulatorResult as r, AnnotationTarget as s, AccumulatableEvent as t, ActionResult as u, ThinkingPart as v, ConcreteFileInfo as w, Turn as x, TimingInfo as y, TraceWriter as z };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=class{_state;constructor(e){this._state={turns:e?.turns??[],sessionAnnotations:e?.sessionAnnotations}}get state(){return this._state}apply(e){let t=e;switch(e.type){case`session:restore`:return this.replaceState({turns:t.turns??[],sessionAnnotations:t.sessionAnnotations},e);case`turn:user`:return this.replaceTurns([...this._state.turns,t.turn],e);case`turn:start`:{let n={id:t.turnId,owner:`agent`,parts:[],status:`streaming`,...t.timing?{timing:t.timing}:{}};return this.replaceTurns([...this._state.turns,n],e)}case`part:start`:return this.updateTurn(t.turnId,e,e=>({...e,parts:[...e.parts,t.part]}));case`text:delta`:return this.updatePart(t.turnId,t.partId,e,e=>e.type===`text`?{...e,text:e.text+t.delta}:e);case`thinking:delta`:return this.updatePart(t.turnId,t.partId,e,e=>e.type===`thinking`?{...e,text:e.text+t.delta}:e);case`part:end`:return this.updatePart(t.turnId,t.partId,e,e=>({...e,timing:t.timing??e.timing}));case`action:args-delta`:return this.updatePart(t.turnId,t.partId,e,e=>e.type!==`action`||e.kind!==`tool`?e:{...e,detail:{...e.detail,pendingArgs:t.accumulated}});case`action:running`:return this.updatePart(t.turnId,t.partId,e,e=>{if(e.type!==`action`)return e;if(e.kind===`tool`){let{pendingArgs:n,...r}=e.detail;return{...e,status:`running`,detail:t.parameters?{...r,parameters:t.parameters}:r}}return{...e,status:`running`}});case`action:progress`:return this.updatePart(t.turnId,t.partId,e,e=>{if(e.type!==`action`)return e;let n=e.detail.result,r=n?.type===`in-progress`?n.content:``;return{...e,detail:{...e.detail,result:{type:`in-progress`,content:r+t.chunk}}}});case`action:complete`:return this.updatePart(t.turnId,t.partId,e,e=>e.type===`action`?{...e,status:`complete`,detail:{...e.detail,result:t.result},timing:t.timing??e.timing}:e);case`action:error`:return this.updatePart(t.turnId,t.partId,e,e=>e.type===`action`?{...e,status:`error`,detail:{...e.detail,result:{type:`error`,error:t.error}},timing:t.timing??e.timing}:e);case`turn:end`:return this.updateTurn(t.turnId,e,e=>({...e,status:t.status,usage:t.usage,timing:t.timing??e.timing}));case`annotation:start`:return this.addAnnotation(e);case`annotation:update`:return this.replaceAnnotation(e,!1);case`annotation:end`:return this.replaceAnnotation(e,!0);case`error`:case`action:child-event`:return this.handled(e);default:return{handled:!1,state:this._state,event:e}}}replaceState(e,t){return this._state=e,this.handled(t)}replaceTurns(e,t){return this.replaceState({...this._state,turns:e},t)}updateTurn(e,t,n){let r=!1,i=this._state.turns.map(t=>{if(t.id!==e)return t;let i=n(t);return i===t?t:(r=!0,i)});return r?this.replaceTurns(i,t):this.handled(t)}updatePart(e,t,n,r){return this.updateTurn(e,n,e=>{let n=!1,i=e.parts.map(e=>{if(e.id!==t)return e;let i=r(e);return i===e?e:(n=!0,i)});return n?{...e,parts:i}:e})}addAnnotation(e){let n=e,r=n.target,i=t(n.annotation);return!r||!i?this.handled(e):r.type===`session`?this.replaceState({...this._state,sessionAnnotations:[...this._state.sessionAnnotations??[],i]},e):r.type===`turn`?this.updateTurn(r.turnId,e,e=>({...e,annotations:[...e.annotations??[],i]})):r.type===`part`?this.updatePart(r.turnId,r.partId,e,e=>({...e,annotations:[...e.annotations??[],i]})):this.handled(e)}replaceAnnotation(e,r){let i=e,a=i.target,o=t(i.annotation,r);if(!a||!o)return this.handled(e);if(a.type===`session`){let t=n(this._state.sessionAnnotations,o);return t?this.replaceState({...this._state,sessionAnnotations:t},e):this.handled(e)}return a.type===`turn`?this.updateTurn(a.turnId,e,e=>{let t=n(e.annotations,o);return t?{...e,annotations:t}:e}):a.type===`part`?this.updatePart(a.turnId,a.partId,e,e=>{let t=n(e.annotations,o);return t?{...e,annotations:t}:e}):this.handled(e)}handled(e){return{handled:!0,state:this._state,event:e}}};function t(e,t=!1){if(!e)return;let n=t?e.status??`complete`:e.status,r={...e,placement:e.placement??`after`};return n?{...r,status:n}:r}function n(e,t){if(!e)return;let n=!1,r=e.map(e=>e.id===t.id?(n=!0,t):e);return n?r:void 0}export{e as t};
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
3
|
-
`)}async function
|
|
4
|
-
`)){let n=e.trim();if(n)try{let e=JSON.parse(n);e.file&&e.hash&&t.set(e.file,e)}catch{}}return t}async function
|
|
5
|
-
`,`utf-8`)}async function
|
|
6
|
-
> `);if(r===null||r.trim()===``)break;try{let i=await e.send(r.trim()).final;if(t
|
|
2
|
+
import{A as e,_ as t,a as n,c as r,d as i,g as a,h as o,i as s,k as c,l,m as u,n as d,o as f,r as p,s as m,t as h,u as g,v as _,x as v,y}from"./ProceduralMemory-CNxHj5B2.js";import{i as b,s as x,t as S}from"./models-C7fdWvZ6.js";import{z as C}from"zod";import{appendFile as w,mkdir as ee,readFile as T}from"node:fs/promises";import{basename as te,dirname as ne,extname as re}from"node:path";import{glob as ie}from"glob";import{createHash as ae}from"node:crypto";import{Command as oe}from"@commander-js/extra-typings";import E from"yaml";import{createInterface as se}from"node:readline";var ce=`0.19.0`;C.object({value:C.string()});const D=C.object({"api-key":C.string(),rateLimit:C.number().optional()});C.object({timeout:C.number().optional(),maxBuffer:C.number().optional(),cwd:C.string().optional()});const le=C.object({type:C.literal(`chatcompletions`)}).loose(),ue=C.object({type:C.literal(`anthropic`)}).loose(),de=C.object({type:C.literal(`openai`)}).loose(),fe=C.object({type:C.literal(`gemini`)}).loose(),pe=C.discriminatedUnion(`type`,[le,ue,de,fe]),me=C.object({chatcompletions:C.custom().optional(),anthropic:C.custom().optional(),openai:C.custom().optional(),gemini:C.custom().optional(),brave:D.optional()}).loose(),he=C.object({transport:C.literal(`stdio`),name:C.string().optional(),command:C.string(),args:C.array(C.string()).optional(),env:C.record(C.string(),C.string()).optional()}),ge=C.object({transport:C.literal(`http`),name:C.string().optional(),url:C.string(),headers:C.record(C.string(),C.string()).optional()}),O=C.discriminatedUnion(`transport`,[he,ge]),k=C.object({files:C.string(),resume:C.boolean().default(!1),concurrency:C.number().int().positive().default(3)}),A=C.object({name:C.string().optional(),provider:pe,task:C.string(),tools:C.array(C.string()).optional(),provider_tools:C.array(C.string()).optional(),files:C.array(C.string()).optional(),mcps:C.array(O).optional(),batch:k.optional()}),j=[`yaml`,`yml`,`json`];async function M(e,t){let{tracer:n}=t,{content:r,format:i,path:a}=await _(e,{defaults:{name:`axle.job`,formats:j},tag:`Job File`}),o=null;if(i===`json`)o=JSON.parse(r);else if(i===`yaml`||i===`yml`)o=E.parse(r);else throw Error(`Invalid job file format`);n?.debug(`Job config: `+JSON.stringify(o,null,2));let s=A.safeParse(o);if(!s.success)throw Error(`The job file is not valid:\n${F(s.error)}`);return s.data.name||(s.data.name=te(a,re(a))),s.data}const N=[`yaml`,`yml`,`json`];async function P(e,t){let{tracer:n}=t,{content:r,format:i}=await _(e,{defaults:{name:`axle.config`,formats:N},tag:`Config File`}),a=null;if(i===`json`)a=JSON.parse(r);else if(i===`yaml`||i===`yml`)a=E.parse(r);else throw Error(`Invalid config file format`);n?.debug(`Service config: `+JSON.stringify(a,null,2));let o=me.safeParse(a);if(!o.success)throw Error(`The config file is not valid:\n${F(o.error)}`);return o.data}function F(e){return e.issues.map(e=>` - ${e.path.join(`.`)||`root`}: ${e.message}`).join(`
|
|
3
|
+
`)}async function I(e,t){let n=[];for(let r of e){let e=new s(r);await e.connect({tracer:t}),n.push(e)}return n}async function L(e,t){for(let n of e)try{await n.close({tracer:t})}catch{}}const R=`.axle/batch.jsonl`;function _e(e,t){let n=ae(`sha256`);return n.update(e),n.update(`\0`),n.update(t),n.digest(`hex`)}async function ve(e=R){let t=new Map,n;try{n=await T(e,`utf-8`)}catch{return t}for(let e of n.split(`
|
|
4
|
+
`)){let n=e.trim();if(n)try{let e=JSON.parse(n);e.file&&e.hash&&t.set(e.file,e)}catch{}}return t}async function z(e,t=R){await ee(ne(t),{recursive:!0}),await w(t,JSON.stringify(e)+`
|
|
5
|
+
`,`utf-8`)}async function ye(e,n,r,i,a,o,s,l,u,d,f){let p=new y({prompt:e.task});if(e.files)for(let n of e.files)p.addFile(await t(n));let m=d.startSpan(`job`,{type:`workflow`}),h=new v({provider:n,model:r,tools:i,providerTools:a,mcps:o,tracer:m,name:e.name,memory:f});try{let e=await h.send(p.withInputs(s)).final;if(c(u,e.usage),e.response){let t=e.response;d.info(t,{markdown:!0})}l.interactive&&await be(h,u,d),m.end()}catch(e){let t=e instanceof Error?e.message:String(e);throw m.error(t),m.end(`error`),e}}async function be(e,t,n){let r=se({input:process.stdin,output:process.stdout});r.on(`SIGINT`,()=>{r.close()});let i=e=>new Promise(t=>{r.question(e,t),r.once(`close`,()=>t(null))});try{for(;;){let r=await i(`
|
|
6
|
+
> `);if(r===null||r.trim()===``)break;try{let i=await e.send(r.trim()).final;if(c(t,i.usage),i.response){let e=i.response;n.info(e,{markdown:!0})}}catch(e){let t=e instanceof Error?e.message:String(e);n.error(t)}}}finally{r.close()}}async function xe(e,n,r,i,a,o,s,l,u,d,f){let p=e.batch,m=await ie(p.files);if(m.length===0){d.warn(`No files matched pattern: ${p.files}`);return}d.info(`Batch: ${m.length} file(s) matched "${p.files}"`);let h=p.resume?await ve():new Map,g=e.files?await Promise.all(e.files.map(e=>t(e))):[],_=0,b=0,x=0;await Se(p.concurrency??3,m,async l=>{let m=d.startSpan(`batch:${l}`,{type:`workflow`});try{let d=await T(l),x=_e(e.task,d),S=h.get(l);if(p.resume&&S&&S.hash===x){m.info(`Skipped (already completed)`),m.end(),b++;return}let C=new y({prompt:e.task});for(let e of g)C.addFile(e);C.addFile(await t(l));let w={...s,file:l};c(u,(await new v({provider:n,model:r,tools:i,providerTools:a,mcps:o,tracer:m,name:e.name,memory:f}).send(C.withInputs(w)).final).usage),await z({file:l,hash:x,timestamp:Date.now()}),m.end(),_++}catch(e){let t=e instanceof Error?e.message:String(e);m.error(`Failed: ${t}`),m.end(`error`),x++}}),d.info(`Batch complete: ${_} completed, ${b} skipped, ${x} failed`)}async function Se(e,t,n){let r=0;async function i(){for(;r<t.length;)await n(t[r++])}let a=Array.from({length:Math.min(e,t.length)},()=>i());await Promise.all(a)}function Ce(e,t){switch(e){case`brave`:{let e=t?.brave;return e&&g.configure(e),g}case`calculator`:return l;case`exec`:{let e=t?.exec;return e&&r.configure(e),r}case`patch-file`:return m;case`read-file`:return f;case`write-file`:return n;default:throw Error(`Unknown tool: ${e}`)}}function we(e,t){return e.map(e=>Ce(e,t))}const B=new oe().name(`axle`).description(`Axle is a CLI tool for running AI workflows`).version(ce).option(`-c, --config <path>`,`Path to the config file`).option(`-j, --job <path>`,`Path to the job file`).option(`--no-log`,`Do not write the output to a log file`).option(`-d, --debug`,`Print additional debug information`).option(`-i, --interactive`,`Continue the conversation interactively after the initial task`).option(`--args <args...>`,`Additional arguments in the form key=value`);B.parse(process.argv);const V=B.opts(),H={date:new Date().toISOString().split(`T`)[0],datetime:new Date().toISOString(),cwd:process.cwd()};V.args&&V.args.forEach(e=>{let[t,n]=e.split(`=`);t&&n&&(H[t.trim()]=n.trim())});const U=new p;V.debug&&(U.minLevel=`debug`);const Te=new d({minLevel:V.debug?`debug`:`info`,showInternal:V.debug,showTimestamp:!0,markdown:!0});if(U.addWriter(Te),V.log){let e=new d({minLevel:`debug`,showInternal:!0,showTimestamp:!0,output:e=>{}});U.addWriter(e)}const W=U.startSpan(`cli`,{type:`root`});process.on(`uncaughtException`,async e=>{console.error(`Uncaught exception:`),console.error(e),W.error(`Uncaught exception:`),W.error(e.message),W.error(e.stack||``),W.end(`error`),await U.flush(),process.exit(1)}),V.debug&&(W.debug(`Options: `+JSON.stringify(V,null,2)),W.debug(`Additional Arguments: `+JSON.stringify(H,null,2)));let G,K;try{G=await P(V.config??null,{tracer:W}),K=await M(V.job??null,{tracer:W})}catch(e){let t=e instanceof Error?e:Error(String(e));W.error(t.message),W.debug(t.stack??``),W.end(`error`),await U.flush(),B.outputHelp(),process.exit(1)}let q,J;try{let{type:e,...t}=K.provider;switch(e){case`openai`:{let e={...G.openai,...t},n=e[`api-key`];if(!n)throw Error(`The provider openai is not configured. Please check your configuration.`);let r={"api-key":n,model:e.model};q=i(r[`api-key`]),J=r.model||S;break}case`anthropic`:{let e={...G.anthropic,...t},n=e[`api-key`];if(!n)throw Error(`The provider anthropic is not configured. Please check your configuration.`);let r={"api-key":n,model:e.model};q=a(r[`api-key`]),J=r.model||x;break}case`gemini`:{let e={...G.gemini,...t},n=e[`api-key`];if(!n)throw Error(`The provider gemini is not configured. Please check your configuration.`);let r={"api-key":n,model:e.model};q=u(r[`api-key`]),J=r.model||b;break}case`chatcompletions`:{let e={...G.chatcompletions,...t},n=e[`base-url`],r=e.model;if(!n||!r)throw Error(`The provider chatcompletions is not configured. Please check your configuration.`);let i={"base-url":n,model:r,"api-key":e[`api-key`]};q=o(i[`base-url`],i[`api-key`]),J=i.model;break}}}catch(e){let t=e instanceof Error?e:Error(String(e));W.error(t.message),W.error(t.stack??``),W.end(`error`),await U.flush(),B.outputHelp(),process.exit(1)}W.info(`All systems operational. Running job...`);const Y=new h({provider:q,model:J}),X=(K.provider_tools??[]).map(e=>({type:`provider`,name:e})),Z=K.tools?.length?we(K.tools):[];let Q=[];if(K.mcps?.length)try{Q=await I(K.mcps,W)}catch(e){let t=e instanceof Error?e:Error(String(e));W.error(`Failed to connect MCP servers: `+t.message),W.end(`error`),await U.flush(),process.exit(1)}const $=e(),Ee=performance.now();try{K.batch?await xe(K,q,J,Z,X,Q,H,V,$,W,Y):await ye(K,q,J,Z,X,Q,H,V,$,W,Y)}catch(e){let t=e instanceof Error?e:Error(String(e));W.error(t.message),W.debug(t.stack??``)}finally{Q.length>0&&await L(Q,W)}const De=performance.now()-Ee;W.info(`Total run time: ${Math.round(De)}ms`),W.info(`Input tokens: ${$.in}`),W.info(`Output tokens: ${$.out}`),$.cachedIn!==void 0&&W.info(`Cached input tokens: ${$.cachedIn}`),$.cacheWriteIn!==void 0&&W.info(`Cache write input tokens: ${$.cacheWriteIn}`),$.reasoningOut!==void 0&&W.info(`Reasoning output tokens: ${$.reasoningOut}`),W.info(`Complete. Goodbye`),W.end(),await U.flush();export{};
|