@orkestrel/agent 0.0.7 → 0.0.9
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 +1 -1
- package/dist/src/core/index.cjs +293 -92
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +241 -50
- package/dist/src/core/index.d.ts +241 -50
- package/dist/src/core/index.js +286 -93
- package/dist/src/core/index.js.map +1 -1
- package/package.json +24 -21
package/dist/src/core/index.js
CHANGED
|
@@ -73,6 +73,24 @@ var THINK_CLOSE = "</think>";
|
|
|
73
73
|
*/
|
|
74
74
|
var WORKSPACE_SECTION_HEADER = "## Workspace";
|
|
75
75
|
/**
|
|
76
|
+
* The estimated per-message role/framing overhead {@link import('./helpers.js').estimateMessages}
|
|
77
|
+
* adds on top of a message's content estimate — accounts for the fixed wire framing every
|
|
78
|
+
* conversation turn carries (its role tag, delimiters) that {@link import('./helpers.js').estimateTokens}'s
|
|
79
|
+
* content-only heuristic does not otherwise capture.
|
|
80
|
+
*/
|
|
81
|
+
var MESSAGE_TOKEN_OVERHEAD = 4;
|
|
82
|
+
/**
|
|
83
|
+
* The coarse, deliberately-approximate per-image token cost {@link import('./helpers.js').estimateMessages}
|
|
84
|
+
* charges for each attached image.
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* A base64 image payload's LENGTH is NOT a reliable token proxy (a vision model's actual image
|
|
88
|
+
* token cost depends on resolution / tiling, not byte size), so this is a fixed, coarse
|
|
89
|
+
* per-image estimate rather than a derivation from `image.length` — a planning heuristic, not an
|
|
90
|
+
* exact count.
|
|
91
|
+
*/
|
|
92
|
+
var IMAGE_TOKEN_ESTIMATE = 512;
|
|
93
|
+
/**
|
|
76
94
|
* The extension→language table {@link import('./helpers.js').inferLanguage} reads to
|
|
77
95
|
* map a file path's extension to a fenced-code language tag. Covers the common source /
|
|
78
96
|
* markup / data extensions; an unlisted extension falls back to `'text'`.
|
|
@@ -201,18 +219,21 @@ function isAgentJobError(value) {
|
|
|
201
219
|
}
|
|
202
220
|
/**
|
|
203
221
|
* Thrown by a {@link ConversationInterface}'s `compact()` when the conversation has no
|
|
204
|
-
* {@link ConversationSummarizer} to fold its messages with
|
|
205
|
-
* `code`.
|
|
222
|
+
* {@link ConversationSummarizer} to fold its messages with, or when its `sections` cap is
|
|
223
|
+
* structurally invalid — carries a machine-readable `code`.
|
|
206
224
|
*
|
|
207
225
|
* @remarks
|
|
208
226
|
* Compaction REQUIRES a summarizer (it digests the folded slice into a section summary and
|
|
209
227
|
* regenerates the rollup); a conversation created without one can still store + `view()` its
|
|
210
|
-
* live tail, but a `compact()` is a programmer error (§12) and throws this
|
|
211
|
-
* `
|
|
228
|
+
* live tail, but a `compact()` is a programmer error (§12) and throws this with `'SUMMARIZER'`.
|
|
229
|
+
* A `sections` cap (§F2, on {@link import('./types.js').ConversationOptions} /
|
|
230
|
+
* {@link import('./types.js').ConversationManagerOptions} /
|
|
231
|
+
* {@link import('./types.js').CompactOptions}) must be `>= 1` — a sub-1 cap is a programmer
|
|
232
|
+
* error and throws this with `'SECTIONS'`. Narrow a caught value with
|
|
212
233
|
* {@link isConversationError} and branch on `error.code`.
|
|
213
234
|
*/
|
|
214
235
|
var ConversationError = class extends Error {
|
|
215
|
-
/** The machine-readable condition — `'SUMMARIZER'`: a `compact()` with no summarizer. */
|
|
236
|
+
/** The machine-readable condition — `'SUMMARIZER'`: a `compact()` with no summarizer; `'SECTIONS'`: a sub-1 `sections` cap. */
|
|
216
237
|
code;
|
|
217
238
|
constructor(code, message) {
|
|
218
239
|
super(message);
|
|
@@ -256,7 +277,7 @@ var WorkspaceError = class extends Error {
|
|
|
256
277
|
super(message);
|
|
257
278
|
this.name = "WorkspaceError";
|
|
258
279
|
this.code = code;
|
|
259
|
-
this.context = context;
|
|
280
|
+
if (context !== void 0) this.context = context;
|
|
260
281
|
}
|
|
261
282
|
};
|
|
262
283
|
/**
|
|
@@ -277,6 +298,45 @@ var WorkspaceError = class extends Error {
|
|
|
277
298
|
function isWorkspaceError(value) {
|
|
278
299
|
return value instanceof WorkspaceError;
|
|
279
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Thrown synchronously by an {@link AgentInterface}'s `stream()` when a concurrent run would
|
|
303
|
+
* corrupt SHARED per-agent accounting — carries a machine-readable `code`.
|
|
304
|
+
*
|
|
305
|
+
* @remarks
|
|
306
|
+
* A run already in flight on the same agent, PLUS a construction-level `window` (a shared
|
|
307
|
+
* context budget) or a construction-level `budget` with no per-run override (a shared cost
|
|
308
|
+
* budget), means a second concurrent `stream()` would race its charges against the same
|
|
309
|
+
* shared instance — corrupting the accounting. `code` is `'CONCURRENCY'` (the only condition
|
|
310
|
+
* so far). Use separate agents, or per-run `budget` overrides with no `window`, for genuinely
|
|
311
|
+
* concurrent runs. Narrow a caught value with {@link isAgentError} and branch on `error.code`.
|
|
312
|
+
*/
|
|
313
|
+
var AgentError = class extends Error {
|
|
314
|
+
/** The machine-readable condition — `'CONCURRENCY'`: a concurrent run on a shared accounting agent. */
|
|
315
|
+
code;
|
|
316
|
+
constructor(code, message) {
|
|
317
|
+
super(message);
|
|
318
|
+
this.name = "AgentError";
|
|
319
|
+
this.code = code;
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
/**
|
|
323
|
+
* Narrow an unknown caught value to an {@link AgentError}.
|
|
324
|
+
*
|
|
325
|
+
* @param value - The value to test (typically a `catch` binding)
|
|
326
|
+
* @returns `true` when `value` is an {@link AgentError}
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```ts
|
|
330
|
+
* try {
|
|
331
|
+
* agent.stream()
|
|
332
|
+
* } catch (error) {
|
|
333
|
+
* if (isAgentError(error) && error.code === 'CONCURRENCY') useSeparateAgents()
|
|
334
|
+
* }
|
|
335
|
+
* ```
|
|
336
|
+
*/
|
|
337
|
+
function isAgentError(value) {
|
|
338
|
+
return value instanceof AgentError;
|
|
339
|
+
}
|
|
280
340
|
//#endregion
|
|
281
341
|
//#region src/core/conversations/Conversation.ts
|
|
282
342
|
/**
|
|
@@ -330,17 +390,20 @@ var Conversation = class {
|
|
|
330
390
|
#emitter;
|
|
331
391
|
#summarize;
|
|
332
392
|
#keep;
|
|
393
|
+
#cap;
|
|
333
394
|
#sections = [];
|
|
334
395
|
#summary;
|
|
335
396
|
#messages = /* @__PURE__ */ new Map();
|
|
336
397
|
constructor(options, seed) {
|
|
337
398
|
this.#id = seed?.id ?? options?.id ?? crypto.randomUUID();
|
|
338
399
|
this.#emitter = new Emitter({
|
|
339
|
-
on: options
|
|
340
|
-
error: options
|
|
400
|
+
...options?.on === void 0 ? {} : { on: options.on },
|
|
401
|
+
...options?.error === void 0 ? {} : { error: options.error }
|
|
341
402
|
});
|
|
342
403
|
this.#summarize = options?.summarize;
|
|
343
404
|
this.#keep = options?.keep ?? 0;
|
|
405
|
+
if (options?.sections !== void 0 && options.sections < 1) throw new ConversationError("SECTIONS", "a sections cap must be >= 1");
|
|
406
|
+
this.#cap = options?.sections;
|
|
344
407
|
if (seed) {
|
|
345
408
|
this.#summary = seed.summary;
|
|
346
409
|
for (const section of seed.sections) this.#sections.push(section);
|
|
@@ -392,6 +455,8 @@ var Conversation = class {
|
|
|
392
455
|
async compact(options) {
|
|
393
456
|
const summarize = this.#summarize;
|
|
394
457
|
if (summarize === void 0) throw new ConversationError("SUMMARIZER", "cannot compact a conversation without a summarizer");
|
|
458
|
+
const cap = options?.sections ?? this.#cap;
|
|
459
|
+
if (cap !== void 0 && cap < 1) throw new ConversationError("SECTIONS", "a sections cap must be >= 1");
|
|
395
460
|
const keep = options?.keep ?? this.#keep;
|
|
396
461
|
const live = [...this.#messages.values()];
|
|
397
462
|
const fold = keep <= 0 ? live.length : live.length - keep;
|
|
@@ -405,6 +470,23 @@ var Conversation = class {
|
|
|
405
470
|
};
|
|
406
471
|
for (const message of slice) this.#messages.delete(message.id);
|
|
407
472
|
this.#sections.push(section);
|
|
473
|
+
if (cap !== void 0 && this.#sections.length > cap) {
|
|
474
|
+
const overflow = this.#sections.length - cap + 1;
|
|
475
|
+
const folded = this.#sections.slice(0, overflow);
|
|
476
|
+
try {
|
|
477
|
+
const merged = {
|
|
478
|
+
id: crypto.randomUUID(),
|
|
479
|
+
summary: await summarize(folded.map((one) => this.#summaryMessage(one))),
|
|
480
|
+
messages: folded.flatMap((one) => one.messages)
|
|
481
|
+
};
|
|
482
|
+
this.#sections.splice(0, overflow, merged);
|
|
483
|
+
this.#emitter.emit("collapse", merged);
|
|
484
|
+
} catch (error) {
|
|
485
|
+
this.#summary = await summarize(this.#sections.map((one) => this.#summaryMessage(one)));
|
|
486
|
+
this.#emitter.emit("summary", this.#summary);
|
|
487
|
+
throw error;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
408
490
|
this.#summary = await summarize(this.#sections.map((one) => this.#summaryMessage(one)));
|
|
409
491
|
this.#emitter.emit("summary", this.#summary);
|
|
410
492
|
this.#emitter.emit("compact", section);
|
|
@@ -504,10 +586,12 @@ var ConversationManager = class {
|
|
|
504
586
|
#active;
|
|
505
587
|
#summarize;
|
|
506
588
|
#keep;
|
|
589
|
+
#sections;
|
|
507
590
|
#store;
|
|
508
591
|
constructor(options) {
|
|
509
592
|
this.#summarize = options?.summarize;
|
|
510
593
|
this.#keep = options?.keep ?? 0;
|
|
594
|
+
this.#sections = options?.sections;
|
|
511
595
|
this.#store = options?.store;
|
|
512
596
|
}
|
|
513
597
|
get count() {
|
|
@@ -523,11 +607,14 @@ var ConversationManager = class {
|
|
|
523
607
|
return [...this.#conversations.values()];
|
|
524
608
|
}
|
|
525
609
|
add(input) {
|
|
610
|
+
const sections = input?.sections ?? this.#sections;
|
|
611
|
+
const summarize = input?.summarize ?? this.#summarize;
|
|
526
612
|
const conversation = new Conversation({
|
|
527
613
|
...input?.id === void 0 ? {} : { id: input.id },
|
|
528
614
|
...input?.on === void 0 ? {} : { on: input.on },
|
|
529
|
-
summarize:
|
|
530
|
-
keep: input?.keep ?? this.#keep
|
|
615
|
+
...summarize === void 0 ? {} : { summarize },
|
|
616
|
+
keep: input?.keep ?? this.#keep,
|
|
617
|
+
...sections === void 0 ? {} : { sections }
|
|
531
618
|
}, input?.snapshot);
|
|
532
619
|
this.#conversations.set(conversation.id, conversation);
|
|
533
620
|
if (this.#active === void 0) this.#active = conversation.id;
|
|
@@ -668,23 +755,40 @@ function estimateTokens(text) {
|
|
|
668
755
|
* (the {@link import('./types.js').AgentOptions} `window`).
|
|
669
756
|
*
|
|
670
757
|
* @remarks
|
|
671
|
-
* Sums {@link estimateTokens} over
|
|
672
|
-
* heuristic)
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
758
|
+
* Sums, per message, {@link estimateTokens} over its `content` (the `ceil(length / 4)` char
|
|
759
|
+
* heuristic) PLUS {@link import('./constants.js').MESSAGE_TOKEN_OVERHEAD} (a fixed per-message
|
|
760
|
+
* role/framing overhead) PLUS, when present, {@link estimateTokens} over its JSON-stringified
|
|
761
|
+
* `calls` PLUS `images.length * `{@link import('./constants.js').IMAGE_TOKEN_ESTIMATE} (a coarse,
|
|
762
|
+
* deliberately-approximate per-image cost — a base64 length is NOT a token proxy). Deterministic
|
|
763
|
+
* and provider-free — the same messages always yield the same estimate, with an empty batch `0`.
|
|
764
|
+
* It is the fully-swappable default an agent's auto-compaction context budget charges each
|
|
765
|
+
* turn's new messages through; a caller wanting a sharper count supplies its own `consume` to
|
|
766
|
+
* `createBudget` instead. Total — never throws: a `calls` `JSON.stringify` that throws (a
|
|
767
|
+
* circular `ToolCall.arguments`) is caught and replaced with a conservative fixed contribution of
|
|
768
|
+
* {@link import('./constants.js').MESSAGE_TOKEN_OVERHEAD} (the same per-message overhead scale)
|
|
769
|
+
* instead of estimating the (unreachable) serialized length.
|
|
676
770
|
*
|
|
677
771
|
* @param messages - The messages to estimate (a turn's appended assistant + tool messages)
|
|
678
|
-
* @returns The summed estimated token count (
|
|
772
|
+
* @returns The summed estimated token count (`0` when empty)
|
|
679
773
|
*
|
|
680
774
|
* @example
|
|
681
775
|
* ```ts
|
|
682
776
|
* estimateMessages([]) // 0
|
|
683
|
-
* estimateMessages([{ id: '1', role: 'user', content: 'hello' }]) // 2
|
|
777
|
+
* estimateMessages([{ id: '1', role: 'user', content: 'hello' }]) // 6 (2 content + 4 overhead)
|
|
684
778
|
* ```
|
|
685
779
|
*/
|
|
686
780
|
function estimateMessages(messages) {
|
|
687
|
-
return messages.reduce((sum, message) =>
|
|
781
|
+
return messages.reduce((sum, message) => {
|
|
782
|
+
const content = estimateTokens(message.content) + 4;
|
|
783
|
+
let calls = 0;
|
|
784
|
+
if (message.calls?.length) try {
|
|
785
|
+
calls = estimateTokens(JSON.stringify(message.calls));
|
|
786
|
+
} catch {
|
|
787
|
+
calls = 4;
|
|
788
|
+
}
|
|
789
|
+
const images = (message.images?.length ?? 0) * 512;
|
|
790
|
+
return sum + content + calls + images;
|
|
791
|
+
}, 0);
|
|
688
792
|
}
|
|
689
793
|
/**
|
|
690
794
|
* Run one rehydrated agent and apply the partial-as-configurable-failure policy — the
|
|
@@ -714,6 +818,38 @@ async function settleAgentJob(agent, allowPartial) {
|
|
|
714
818
|
return result;
|
|
715
819
|
}
|
|
716
820
|
/**
|
|
821
|
+
* Handle one queued agent job by rehydrating it through a registry with the queue
|
|
822
|
+
* attempt's signal, then applying the shared partial-result policy.
|
|
823
|
+
*
|
|
824
|
+
* @param registry - The registry that rehydrates the serializable job
|
|
825
|
+
* @param allowPartial - Whether a partial result resolves instead of throwing
|
|
826
|
+
* @param input - The serializable agent job
|
|
827
|
+
* @param execution - The queue attempt whose signal bounds the agent
|
|
828
|
+
* @returns The settled agent result
|
|
829
|
+
*/
|
|
830
|
+
function handleAgentQueueJob(registry, allowPartial, input, execution) {
|
|
831
|
+
return settleAgentJob(registry.build(input, execution.signal), allowPartial);
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Handle one runner agent job by fanning out its declared children, rehydrating the
|
|
835
|
+
* parent through a registry with the controller signal, and applying the shared
|
|
836
|
+
* partial-result policy.
|
|
837
|
+
*
|
|
838
|
+
* @remarks
|
|
839
|
+
* Children are fired and tracked through the runner controller without awaiting them
|
|
840
|
+
* inline, preserving bounded-runner progress.
|
|
841
|
+
*
|
|
842
|
+
* @param registry - The registry that rehydrates serializable jobs
|
|
843
|
+
* @param allowPartial - Whether a partial result resolves instead of throwing
|
|
844
|
+
* @param controller - The runner controller for this parent job
|
|
845
|
+
* @returns The settled parent agent result
|
|
846
|
+
*/
|
|
847
|
+
function handleAgentRunnerJob(registry, allowPartial, controller) {
|
|
848
|
+
const children = controller.input.children;
|
|
849
|
+
if (children !== void 0) for (const child of children) controller.spawn(child);
|
|
850
|
+
return settleAgentJob(registry.build(controller.input, controller.signal), allowPartial);
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
717
853
|
* Whether a {@link FileContent} is the TEXT arm — the narrowing guard for the text-vs-binary
|
|
718
854
|
* union (AGENTS §14: narrow an untyped arm via a guard, never an `as`).
|
|
719
855
|
*
|
|
@@ -1310,6 +1446,40 @@ function fencedFile(path, language, content) {
|
|
|
1310
1446
|
function escapeRegExp(value) {
|
|
1311
1447
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1312
1448
|
}
|
|
1449
|
+
/**
|
|
1450
|
+
* Sanitize one reported token count into a safe non-negative integer.
|
|
1451
|
+
*
|
|
1452
|
+
* @param value - The token count to sanitize
|
|
1453
|
+
* @returns The floored count, or `0` when the value is non-finite or non-positive
|
|
1454
|
+
*/
|
|
1455
|
+
function sanitizeToken(value) {
|
|
1456
|
+
return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
1457
|
+
}
|
|
1458
|
+
/**
|
|
1459
|
+
* Sanitize a {@link TokenUsage} into safe, non-negative integers — the guard an agent's
|
|
1460
|
+
* abort-usage path applies to a provider's partial usage before it is charged against a
|
|
1461
|
+
* budget or folded into the run total.
|
|
1462
|
+
*
|
|
1463
|
+
* @remarks
|
|
1464
|
+
* Per field (`prompt` / `completion` / `total`): a non-finite value (`NaN`, `+Infinity`,
|
|
1465
|
+
* `-Infinity`) or a negative value floors to `0`; a fractional value floors to its
|
|
1466
|
+
* non-negative integer part. No upper cap is applied. Total — never throws.
|
|
1467
|
+
*
|
|
1468
|
+
* @param usage - The token usage to sanitize (e.g. a provider's abort-partial usage)
|
|
1469
|
+
* @returns A new {@link TokenUsage} with every field a safe non-negative integer
|
|
1470
|
+
*
|
|
1471
|
+
* @example
|
|
1472
|
+
* ```ts
|
|
1473
|
+
* sanitizeUsage({ prompt: -5, completion: NaN, total: 12.7 }) // { prompt: 0, completion: 0, total: 12 }
|
|
1474
|
+
* ```
|
|
1475
|
+
*/
|
|
1476
|
+
function sanitizeUsage(usage) {
|
|
1477
|
+
return {
|
|
1478
|
+
prompt: sanitizeToken(usage.prompt),
|
|
1479
|
+
completion: sanitizeToken(usage.completion),
|
|
1480
|
+
total: sanitizeToken(usage.total)
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1313
1483
|
//#endregion
|
|
1314
1484
|
//#region src/core/instructions/Instruction.ts
|
|
1315
1485
|
/**
|
|
@@ -1391,8 +1561,8 @@ var InstructionManager = class {
|
|
|
1391
1561
|
#format;
|
|
1392
1562
|
constructor(options) {
|
|
1393
1563
|
this.#emitter = new Emitter({
|
|
1394
|
-
on: options
|
|
1395
|
-
error: options
|
|
1564
|
+
...options?.on === void 0 ? {} : { on: options.on },
|
|
1565
|
+
...options?.error === void 0 ? {} : { error: options.error }
|
|
1396
1566
|
});
|
|
1397
1567
|
this.#format = options?.format;
|
|
1398
1568
|
}
|
|
@@ -1594,8 +1764,8 @@ var Workspace = class {
|
|
|
1594
1764
|
constructor(options, seed) {
|
|
1595
1765
|
this.#id = options?.id ?? crypto.randomUUID();
|
|
1596
1766
|
this.#emitter = new Emitter({
|
|
1597
|
-
on: options
|
|
1598
|
-
error: options
|
|
1767
|
+
...options?.on === void 0 ? {} : { on: options.on },
|
|
1768
|
+
...options?.error === void 0 ? {} : { error: options.error }
|
|
1599
1769
|
});
|
|
1600
1770
|
if (seed) for (const [path, file] of seed) this.#files.set(path, file);
|
|
1601
1771
|
}
|
|
@@ -1888,10 +2058,12 @@ var WorkspaceManager = class {
|
|
|
1888
2058
|
return [...this.#workspaces.values()];
|
|
1889
2059
|
}
|
|
1890
2060
|
add(input) {
|
|
2061
|
+
const on = input?.on ?? this.#on;
|
|
2062
|
+
const error = input?.error ?? this.#error;
|
|
1891
2063
|
const workspace = new Workspace({
|
|
1892
2064
|
...input?.id === void 0 ? {} : { id: input.id },
|
|
1893
|
-
on:
|
|
1894
|
-
error:
|
|
2065
|
+
...on === void 0 ? {} : { on },
|
|
2066
|
+
...error === void 0 ? {} : { error }
|
|
1895
2067
|
}, input?.seed);
|
|
1896
2068
|
this.#workspaces.set(workspace.id, workspace);
|
|
1897
2069
|
if (this.#active === void 0) this.#active = workspace.id;
|
|
@@ -2235,6 +2407,7 @@ var Agent = class {
|
|
|
2235
2407
|
#signal;
|
|
2236
2408
|
#authority;
|
|
2237
2409
|
#window;
|
|
2410
|
+
#strict;
|
|
2238
2411
|
#emitter;
|
|
2239
2412
|
id = crypto.randomUUID();
|
|
2240
2413
|
#status = "idle";
|
|
@@ -2242,9 +2415,12 @@ var Agent = class {
|
|
|
2242
2415
|
constructor(provider, options) {
|
|
2243
2416
|
this.#provider = provider;
|
|
2244
2417
|
this.#context = new AgentContext({
|
|
2245
|
-
system: options
|
|
2246
|
-
tools: options
|
|
2247
|
-
|
|
2418
|
+
...options?.system === void 0 ? {} : { system: options.system },
|
|
2419
|
+
...options?.tools === void 0 ? {} : { tools: options.tools },
|
|
2420
|
+
...options?.instructions === void 0 ? {} : { instructions: options.instructions },
|
|
2421
|
+
...options?.workspaces === void 0 ? {} : { workspaces: options.workspaces },
|
|
2422
|
+
...options?.scope === void 0 ? {} : { scope: options.scope },
|
|
2423
|
+
...options?.conversations === void 0 ? {} : { conversations: options.conversations }
|
|
2248
2424
|
});
|
|
2249
2425
|
this.#limit = options?.limit ?? 10;
|
|
2250
2426
|
this.#timeoutMs = options?.timeout;
|
|
@@ -2253,9 +2429,10 @@ var Agent = class {
|
|
|
2253
2429
|
this.#signal = options?.signal;
|
|
2254
2430
|
this.#authority = options?.authority;
|
|
2255
2431
|
this.#window = options?.window;
|
|
2432
|
+
this.#strict = options?.strict ?? false;
|
|
2256
2433
|
this.#emitter = new Emitter({
|
|
2257
|
-
on: options
|
|
2258
|
-
error: options
|
|
2434
|
+
...options?.on === void 0 ? {} : { on: options.on },
|
|
2435
|
+
...options?.error === void 0 ? {} : { error: options.error }
|
|
2259
2436
|
});
|
|
2260
2437
|
}
|
|
2261
2438
|
get emitter() {
|
|
@@ -2271,48 +2448,49 @@ var Agent = class {
|
|
|
2271
2448
|
return this.stream(options).result;
|
|
2272
2449
|
}
|
|
2273
2450
|
stream(options) {
|
|
2451
|
+
if (this.#runs.size > 0 && (this.#window !== void 0 || this.#budget !== void 0 && options?.budget === void 0)) throw new AgentError("CONCURRENCY", "concurrent runs on one agent with a shared construction window/budget corrupt accounting; use separate agents or per-run budgets");
|
|
2274
2452
|
const timeoutMs = options?.timeout ?? this.#timeoutMs;
|
|
2275
2453
|
const timeout = timeoutMs === void 0 ? void 0 : createTimeout({ ms: timeoutMs });
|
|
2276
2454
|
timeout?.start();
|
|
2277
2455
|
const budget = options?.budget ?? this.#budget;
|
|
2278
2456
|
budget?.start();
|
|
2279
2457
|
const limit = options?.limit ?? this.#limit;
|
|
2280
|
-
const
|
|
2458
|
+
const signal = this.#parents(timeout, budget, options?.signal);
|
|
2459
|
+
const abort = createAbort(signal === void 0 ? {} : { signal });
|
|
2281
2460
|
this.#runs.add(abort);
|
|
2282
2461
|
this.#status = "running";
|
|
2283
2462
|
this.#emitter.emit("start", this.id);
|
|
2284
|
-
const
|
|
2463
|
+
const state = { outcome: {
|
|
2285
2464
|
content: "",
|
|
2286
2465
|
thinking: void 0,
|
|
2287
2466
|
usage: void 0,
|
|
2288
2467
|
partial: false,
|
|
2289
2468
|
exhausted: false
|
|
2290
|
-
};
|
|
2469
|
+
} };
|
|
2291
2470
|
const channel = new Channel();
|
|
2292
2471
|
const settled = createDeferred();
|
|
2293
|
-
this.#pump(abort,
|
|
2472
|
+
this.#pump(abort, state, timeout, channel, settled, options?.think, options?.schema, limit, budget);
|
|
2294
2473
|
settled.promise.catch(() => {});
|
|
2295
2474
|
return {
|
|
2296
2475
|
events: this.#events(channel, abort),
|
|
2297
2476
|
result: settled.promise,
|
|
2298
|
-
abort: (
|
|
2299
|
-
abort.abort(reason);
|
|
2300
|
-
}
|
|
2477
|
+
abort: abort.abort.bind(abort)
|
|
2301
2478
|
};
|
|
2302
2479
|
}
|
|
2303
2480
|
abort(reason) {
|
|
2304
2481
|
for (const abort of [...this.#runs]) abort.abort(reason);
|
|
2305
2482
|
}
|
|
2306
|
-
async #pump(abort,
|
|
2483
|
+
async #pump(abort, state, timeout, channel, settled, think, schema, limit, budget) {
|
|
2307
2484
|
let failure;
|
|
2308
2485
|
try {
|
|
2309
|
-
for await (const chunk of this.#run(abort,
|
|
2486
|
+
for await (const chunk of this.#run(abort, state, think, schema, limit, budget)) channel.push(chunk);
|
|
2310
2487
|
} catch (error) {
|
|
2311
2488
|
failure = { error };
|
|
2312
2489
|
} finally {
|
|
2313
2490
|
timeout?.clear();
|
|
2314
2491
|
this.#runs.delete(abort);
|
|
2315
2492
|
if (failure === void 0) {
|
|
2493
|
+
const outcome = state.outcome;
|
|
2316
2494
|
this.#status = "done";
|
|
2317
2495
|
channel.close();
|
|
2318
2496
|
const result = this.#result(outcome);
|
|
@@ -2335,7 +2513,7 @@ var Agent = class {
|
|
|
2335
2513
|
abort.abort();
|
|
2336
2514
|
}
|
|
2337
2515
|
}
|
|
2338
|
-
async *#run(abort,
|
|
2516
|
+
async *#run(abort, state, think, schema, limit, budget) {
|
|
2339
2517
|
const messages = [...this.#context.build(this.#provider.format)];
|
|
2340
2518
|
const tools = this.#context.tools;
|
|
2341
2519
|
let content = "";
|
|
@@ -2343,7 +2521,7 @@ var Agent = class {
|
|
|
2343
2521
|
let usage;
|
|
2344
2522
|
let pending = false;
|
|
2345
2523
|
let broke = false;
|
|
2346
|
-
const compaction = { futile: false };
|
|
2524
|
+
const compaction = { state: { futile: false } };
|
|
2347
2525
|
const compacting = this.#window !== void 0 && this.#context.conversations.active?.summarizable === true;
|
|
2348
2526
|
if (compacting) {
|
|
2349
2527
|
this.#window?.clear();
|
|
@@ -2355,14 +2533,20 @@ var Agent = class {
|
|
|
2355
2533
|
await this.#scheduler?.yield({ signal: abort.signal });
|
|
2356
2534
|
} catch (error) {
|
|
2357
2535
|
if (abort.signal.aborted) {
|
|
2358
|
-
outcome
|
|
2536
|
+
state.outcome = {
|
|
2537
|
+
...state.outcome,
|
|
2538
|
+
partial: true
|
|
2539
|
+
};
|
|
2359
2540
|
broke = true;
|
|
2360
2541
|
break;
|
|
2361
2542
|
}
|
|
2362
2543
|
throw error;
|
|
2363
2544
|
}
|
|
2364
2545
|
if (abort.signal.aborted) {
|
|
2365
|
-
outcome
|
|
2546
|
+
state.outcome = {
|
|
2547
|
+
...state.outcome,
|
|
2548
|
+
partial: true
|
|
2549
|
+
};
|
|
2366
2550
|
broke = true;
|
|
2367
2551
|
break;
|
|
2368
2552
|
}
|
|
@@ -2390,7 +2574,7 @@ var Agent = class {
|
|
|
2390
2574
|
if (isProviderAbortError(error)) {
|
|
2391
2575
|
if (error.partial.thinking !== void 0) thinking = this.#thought(thinking, error.partial.thinking);
|
|
2392
2576
|
if (error.partial.usage !== void 0) {
|
|
2393
|
-
const abortUsage = error.partial.usage;
|
|
2577
|
+
const abortUsage = sanitizeUsage(error.partial.usage);
|
|
2394
2578
|
budget?.consume({
|
|
2395
2579
|
prompt: abortUsage.prompt,
|
|
2396
2580
|
completion: Math.max(0, abortUsage.completion - charged),
|
|
@@ -2399,7 +2583,10 @@ var Agent = class {
|
|
|
2399
2583
|
usage = this.#sum(usage, abortUsage);
|
|
2400
2584
|
}
|
|
2401
2585
|
}
|
|
2402
|
-
outcome
|
|
2586
|
+
state.outcome = {
|
|
2587
|
+
...state.outcome,
|
|
2588
|
+
partial: true
|
|
2589
|
+
};
|
|
2403
2590
|
broke = true;
|
|
2404
2591
|
break;
|
|
2405
2592
|
}
|
|
@@ -2407,16 +2594,17 @@ var Agent = class {
|
|
|
2407
2594
|
}
|
|
2408
2595
|
if (result.thinking !== void 0 && result.thinking.length > 0) thinking = this.#thought(thinking, result.thinking);
|
|
2409
2596
|
if (result.usage !== void 0) {
|
|
2597
|
+
const resultUsage = sanitizeUsage(result.usage);
|
|
2410
2598
|
budget?.consume({
|
|
2411
|
-
prompt:
|
|
2412
|
-
completion: Math.max(0,
|
|
2413
|
-
total: Math.max(0,
|
|
2599
|
+
prompt: resultUsage.prompt,
|
|
2600
|
+
completion: Math.max(0, resultUsage.completion - charged),
|
|
2601
|
+
total: Math.max(0, resultUsage.total - charged)
|
|
2414
2602
|
});
|
|
2415
|
-
usage = this.#sum(usage,
|
|
2416
|
-
this.#emitter.emit("usage",
|
|
2603
|
+
usage = this.#sum(usage, resultUsage);
|
|
2604
|
+
this.#emitter.emit("usage", resultUsage);
|
|
2417
2605
|
yield {
|
|
2418
2606
|
type: "usage",
|
|
2419
|
-
usage:
|
|
2607
|
+
usage: resultUsage
|
|
2420
2608
|
};
|
|
2421
2609
|
}
|
|
2422
2610
|
if (result.tools !== void 0 && result.tools.length > 0) {
|
|
@@ -2456,17 +2644,21 @@ var Agent = class {
|
|
|
2456
2644
|
broke = true;
|
|
2457
2645
|
break;
|
|
2458
2646
|
}
|
|
2459
|
-
if (!broke && pending) {
|
|
2460
|
-
outcome
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
outcome
|
|
2465
|
-
|
|
2647
|
+
if (!broke && pending) state.outcome = {
|
|
2648
|
+
...state.outcome,
|
|
2649
|
+
partial: true,
|
|
2650
|
+
exhausted: !abort.signal.aborted
|
|
2651
|
+
};
|
|
2652
|
+
state.outcome = {
|
|
2653
|
+
...state.outcome,
|
|
2654
|
+
content,
|
|
2655
|
+
thinking,
|
|
2656
|
+
usage
|
|
2657
|
+
};
|
|
2466
2658
|
}
|
|
2467
2659
|
async #trim(messages, compaction, latchFutile) {
|
|
2468
2660
|
const conversation = this.#context.conversations.active;
|
|
2469
|
-
if (this.#window === void 0 || conversation?.summarizable !== true || compaction.futile) return;
|
|
2661
|
+
if (this.#window === void 0 || conversation?.summarizable !== true || compaction.state.futile) return;
|
|
2470
2662
|
this.#window.clear();
|
|
2471
2663
|
this.#window.consume(messages);
|
|
2472
2664
|
if (!this.#window.exhausted) return;
|
|
@@ -2475,10 +2667,11 @@ var Agent = class {
|
|
|
2475
2667
|
section = await conversation.compact();
|
|
2476
2668
|
} catch (error) {
|
|
2477
2669
|
this.#emitter.emit("compactError", error);
|
|
2670
|
+
if (this.#strict) throw error;
|
|
2478
2671
|
return;
|
|
2479
2672
|
}
|
|
2480
2673
|
if (section === void 0) {
|
|
2481
|
-
if (latchFutile) compaction.
|
|
2674
|
+
if (latchFutile) compaction.state = { futile: true };
|
|
2482
2675
|
return;
|
|
2483
2676
|
}
|
|
2484
2677
|
messages.splice(0, messages.length, ...this.#context.build(this.#provider.format));
|
|
@@ -2640,16 +2833,17 @@ var AgentRegistry = class {
|
|
|
2640
2833
|
return agent;
|
|
2641
2834
|
}
|
|
2642
2835
|
#options(input, signal) {
|
|
2836
|
+
const budget = this.#budget(input.budget);
|
|
2643
2837
|
return {
|
|
2644
|
-
system: input.system,
|
|
2645
2838
|
tools: this.#manager(input.tools),
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2839
|
+
...input.system === void 0 ? {} : { system: input.system },
|
|
2840
|
+
...input.limit === void 0 ? {} : { limit: input.limit },
|
|
2841
|
+
...input.timeout === void 0 ? {} : { timeout: input.timeout },
|
|
2842
|
+
...budget === void 0 ? {} : { budget },
|
|
2843
|
+
...input.authority === void 0 ? {} : { authority: this.authority(input.authority) },
|
|
2844
|
+
...input.scheduler === void 0 ? {} : { scheduler: this.scheduler(input.scheduler) },
|
|
2845
|
+
...this.#store === void 0 ? {} : { conversations: new ConversationManager({ store: this.#store }) },
|
|
2846
|
+
...signal === void 0 ? {} : { signal }
|
|
2653
2847
|
};
|
|
2654
2848
|
}
|
|
2655
2849
|
#manager(names) {
|
|
@@ -2715,7 +2909,7 @@ var Authority = class {
|
|
|
2715
2909
|
for (const rule of this.#rules) if (rule.match(context)) return {
|
|
2716
2910
|
zone: rule.zone,
|
|
2717
2911
|
allowed: rule.allowed ?? true,
|
|
2718
|
-
reason: rule.reason
|
|
2912
|
+
...rule.reason === void 0 ? {} : { reason: rule.reason }
|
|
2719
2913
|
};
|
|
2720
2914
|
return this.#fallback;
|
|
2721
2915
|
}
|
|
@@ -2894,16 +3088,19 @@ var Scope = class Scope {
|
|
|
2894
3088
|
files;
|
|
2895
3089
|
constructor(input) {
|
|
2896
3090
|
this.name = input.name;
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
3091
|
+
if (input.instructions !== void 0) this.instructions = [...input.instructions];
|
|
3092
|
+
if (input.tools !== void 0) this.tools = [...input.tools];
|
|
3093
|
+
if (input.files !== void 0) this.files = [...input.files];
|
|
2900
3094
|
}
|
|
2901
3095
|
narrow(config) {
|
|
3096
|
+
const instructions = Scope.#intersect(this.instructions, config.instructions);
|
|
3097
|
+
const tools = Scope.#intersect(this.tools, config.tools);
|
|
3098
|
+
const files = Scope.#intersect(this.files, config.files);
|
|
2902
3099
|
return new Scope({
|
|
2903
3100
|
name: this.name,
|
|
2904
|
-
instructions:
|
|
2905
|
-
tools:
|
|
2906
|
-
files:
|
|
3101
|
+
...instructions === void 0 ? {} : { instructions },
|
|
3102
|
+
...tools === void 0 ? {} : { tools },
|
|
3103
|
+
...files === void 0 ? {} : { files }
|
|
2907
3104
|
});
|
|
2908
3105
|
}
|
|
2909
3106
|
static #intersect(parent, child) {
|
|
@@ -2947,8 +3144,8 @@ var ScopeManager = class {
|
|
|
2947
3144
|
#emitter;
|
|
2948
3145
|
constructor(on, error) {
|
|
2949
3146
|
this.#emitter = new Emitter({
|
|
2950
|
-
on,
|
|
2951
|
-
error
|
|
3147
|
+
...on === void 0 ? {} : { on },
|
|
3148
|
+
...error === void 0 ? {} : { error }
|
|
2952
3149
|
});
|
|
2953
3150
|
}
|
|
2954
3151
|
get emitter() {
|
|
@@ -3138,9 +3335,9 @@ var Tool = class {
|
|
|
3138
3335
|
#execute;
|
|
3139
3336
|
constructor(options) {
|
|
3140
3337
|
this.name = options.name;
|
|
3141
|
-
this.description = options.description;
|
|
3142
|
-
this.summary = options.summary;
|
|
3143
|
-
this.parameters = options.parameters;
|
|
3338
|
+
if (options.description !== void 0) this.description = options.description;
|
|
3339
|
+
if (options.summary !== void 0) this.summary = options.summary;
|
|
3340
|
+
if (options.parameters !== void 0) this.parameters = options.parameters;
|
|
3144
3341
|
this.#execute = options.execute;
|
|
3145
3342
|
}
|
|
3146
3343
|
execute(args) {
|
|
@@ -3798,11 +3995,11 @@ function createAgentRegistry(options) {
|
|
|
3798
3995
|
function createAgentQueue(options) {
|
|
3799
3996
|
const { registry, allowPartial = false, concurrency, retries, timeout, store } = options;
|
|
3800
3997
|
return createQueue({
|
|
3801
|
-
concurrency,
|
|
3802
|
-
retries,
|
|
3803
|
-
timeout,
|
|
3804
|
-
store,
|
|
3805
|
-
handler: (
|
|
3998
|
+
...concurrency === void 0 ? {} : { concurrency },
|
|
3999
|
+
...retries === void 0 ? {} : { retries },
|
|
4000
|
+
...timeout === void 0 ? {} : { timeout },
|
|
4001
|
+
...store === void 0 ? {} : { store },
|
|
4002
|
+
handler: handleAgentQueueJob.bind(void 0, registry, allowPartial)
|
|
3806
4003
|
});
|
|
3807
4004
|
}
|
|
3808
4005
|
/**
|
|
@@ -3844,14 +4041,10 @@ function createAgentQueue(options) {
|
|
|
3844
4041
|
function createAgentRunner(options) {
|
|
3845
4042
|
const { registry, allowPartial = false, concurrency, retries, timeout } = options;
|
|
3846
4043
|
return createRunner({
|
|
3847
|
-
concurrency,
|
|
3848
|
-
retries,
|
|
3849
|
-
timeout,
|
|
3850
|
-
handler: (
|
|
3851
|
-
const children = controller.input.children;
|
|
3852
|
-
if (children !== void 0) for (const child of children) controller.spawn(child);
|
|
3853
|
-
return settleAgentJob(registry.build(controller.input, controller.signal), allowPartial);
|
|
3854
|
-
}
|
|
4044
|
+
...concurrency === void 0 ? {} : { concurrency },
|
|
4045
|
+
...retries === void 0 ? {} : { retries },
|
|
4046
|
+
...timeout === void 0 ? {} : { timeout },
|
|
4047
|
+
handler: handleAgentRunnerJob.bind(void 0, registry, allowPartial)
|
|
3855
4048
|
});
|
|
3856
4049
|
}
|
|
3857
4050
|
/**
|
|
@@ -4061,6 +4254,6 @@ function createWorkspaceManager(options) {
|
|
|
4061
4254
|
return new WorkspaceManager(options);
|
|
4062
4255
|
}
|
|
4063
4256
|
//#endregion
|
|
4064
|
-
export { Agent, AgentContext, AgentJobError, AgentRegistry, Authority, CONVERSATION_RECAP_PREFIX, Channel, Conversation, ConversationError, ConversationManager, DEFAULT_AGENT_LIMIT, DEFAULT_AUTHORITY_ZONE, DEFAULT_CONVERSATION_KEEP, DatabaseConversationStore, DatabaseWorkspaceStore, EXTENSION_TO_LANGUAGE, Instruction, InstructionManager, MemoryConversationStore, MemoryWorkspaceStore, ProviderAbortError, Scope, ScopeManager, THINK_CLOSE, THINK_OPEN, ThinkSplitter, Tool, ToolManager, WORKSPACE_SECTION_HEADER, Workspace, WorkspaceError, WorkspaceManager, buildToolResult, clampPosition, clampRange, computeSize, countLines, createAgent, createAgentContext, createAgentQueue, createAgentRegistry, createAgentRunner, createAuthority, createBinaryContent, createConversation, createConversationManager, createDatabaseConversationStore, createDatabaseWorkspaceStore, createFile, createInstruction, createInstructionManager, createMemoryConversationStore, createMemoryWorkspaceStore, createScope, createScopeManager, createTextContent, createThinkSplitter, createTool, createToolManager, createWorkspace, createWorkspaceManager, decodedSize, escapeRegExp, estimateMessages, estimateTokens, fencedFile, filterAllowList, inferLanguage, isAgentJobError, isBinary, isConversationError, isConversationSnapshot, isFile, isImage, isMessage, isProviderAbortError, isSection, isText, isToolCall, isValidRange, isWorkspaceError, isWorkspaceSnapshot, offsetAt, rangeOf, settleAgentJob, sliceRange, spliceRange };
|
|
4257
|
+
export { Agent, AgentContext, AgentError, AgentJobError, AgentRegistry, Authority, CONVERSATION_RECAP_PREFIX, Channel, Conversation, ConversationError, ConversationManager, DEFAULT_AGENT_LIMIT, DEFAULT_AUTHORITY_ZONE, DEFAULT_CONVERSATION_KEEP, DatabaseConversationStore, DatabaseWorkspaceStore, EXTENSION_TO_LANGUAGE, IMAGE_TOKEN_ESTIMATE, Instruction, InstructionManager, MESSAGE_TOKEN_OVERHEAD, MemoryConversationStore, MemoryWorkspaceStore, ProviderAbortError, Scope, ScopeManager, THINK_CLOSE, THINK_OPEN, ThinkSplitter, Tool, ToolManager, WORKSPACE_SECTION_HEADER, Workspace, WorkspaceError, WorkspaceManager, buildToolResult, clampPosition, clampRange, computeSize, countLines, createAgent, createAgentContext, createAgentQueue, createAgentRegistry, createAgentRunner, createAuthority, createBinaryContent, createConversation, createConversationManager, createDatabaseConversationStore, createDatabaseWorkspaceStore, createFile, createInstruction, createInstructionManager, createMemoryConversationStore, createMemoryWorkspaceStore, createScope, createScopeManager, createTextContent, createThinkSplitter, createTool, createToolManager, createWorkspace, createWorkspaceManager, decodedSize, escapeRegExp, estimateMessages, estimateTokens, fencedFile, filterAllowList, handleAgentQueueJob, handleAgentRunnerJob, inferLanguage, isAgentError, isAgentJobError, isBinary, isConversationError, isConversationSnapshot, isFile, isImage, isMessage, isProviderAbortError, isSection, isText, isToolCall, isValidRange, isWorkspaceError, isWorkspaceSnapshot, offsetAt, rangeOf, sanitizeToken, sanitizeUsage, settleAgentJob, sliceRange, spliceRange };
|
|
4065
4258
|
|
|
4066
4259
|
//# sourceMappingURL=index.js.map
|