@arnilo/prism 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/dist/agent-session/create-agent.d.ts +6 -0
- package/dist/agent-session/create-agent.js +13 -0
- package/dist/agent-session/event-subscriber.d.ts +17 -0
- package/dist/agent-session/event-subscriber.js +68 -0
- package/dist/agent-session/helpers.d.ts +44 -0
- package/dist/agent-session/helpers.js +194 -0
- package/dist/agent-session/session.d.ts +101 -0
- package/dist/agent-session/session.js +1568 -0
- package/dist/agent-session.d.ts +6 -105
- package/dist/agent-session.js +6 -1833
- package/dist/contracts-core/agent.d.ts +257 -0
- package/dist/contracts-core/agent.js +5 -0
- package/dist/contracts-core/compaction.d.ts +72 -0
- package/dist/contracts-core/compaction.js +2 -0
- package/dist/contracts-core/content.d.ts +116 -0
- package/dist/contracts-core/content.js +2 -0
- package/dist/contracts-core/extensions.d.ts +163 -0
- package/dist/contracts-core/extensions.js +2 -0
- package/dist/contracts-core/loop.d.ts +98 -0
- package/dist/contracts-core/loop.js +2 -0
- package/dist/contracts-core/persistence.d.ts +366 -0
- package/dist/contracts-core/persistence.js +9 -0
- package/dist/contracts-core/provider.d.ts +97 -0
- package/dist/contracts-core/provider.js +2 -0
- package/dist/contracts-core/resources.d.ts +44 -0
- package/dist/contracts-core/resources.js +7 -0
- package/dist/contracts-core/run-limits.d.ts +81 -0
- package/dist/contracts-core/run-limits.js +2 -0
- package/dist/contracts-core/session.d.ts +187 -0
- package/dist/contracts-core/session.js +131 -0
- package/dist/contracts-core.d.ts +13 -1425
- package/dist/contracts-core.js +10 -138
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/docs/0.1.0-readiness.md +10 -10
- package/docs/index.md +2 -2
- package/docs/migration.md +4 -0
- package/docs/release-and-install.md +26 -3
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.5] - 2026-08-15
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- **Release 0.2.5 (plan 025)** is the maintainability-and-bounded-performance cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.5: expected deltas are the version literal plus 105 additive internal-helper exports — 84 Task 1 cross-family helpers across core/coding-agent/workflows/server/ag-ui and 21 `prism-session-store-codecs` helpers; zero removals; no `--allow-break`). Five roadmap items, no runtime contract change and no migration: (1) **god-module splits** (`god-module-split`, 0.1.4 precedent) — the six remaining implementation god-modules split along cohesive boundaries into internal family files behind preserved barrels: `src/contracts-core.ts` (1,719 L → 10 families, max 403 L), `src/agent-session.ts` (2,049 L → 4 modules; the 1,686-L `RuntimeAgentSession` class kept intact — a single TS class cannot span files without exporting private methods, recorded reason), `packages/workflows/src/run.ts` (1,227 L → 6 families, max 417 L), `packages/server/src/handler.ts` (1,005 L → 8 families, max 444 L), `packages/coding-agent/src/repository.ts` (974 L → 7 families, max 299 L), `packages/ag-ui/src/acp/agent.ts` (836 L → 8 families, max 386 L); no `exports`-map subpath added; `ponytail:` comments preserved; zero breaking compat deltas (`scripts/phase25-compat-diff.mjs`). (2) **persistence-mechanics dedup** (`session-store-codecs`) — 21 pure helpers (ownership scope/assertion, checkpoint stale/encode/decode, branch cursors, lifecycle quota/reason/page-limit, search metadata/clipping, deepFreeze/string-array/throwIfAborted, feedback row mapping) moved into the dependency-free codecs package (426 → 624 L, stdlib only); the postgres/sqlite adapters shrank 273 lines total; SQL dialect/DDL/query execution stay per-adapter; no persisted-shape change; cross-store conformance green before/after. (3) **quadratic accumulation removed** (`bounded-accumulation`) — the per-push `Buffer.concat` loops in `LspFrameReader` (language framing) and `summarizeTarStream` (tar parsing) became chunk-array readers (two-phase header parse, offset-advance drop, take/drop sliding window); caps + fail-closed overflow byte-identical; framing ~100–200× faster at 4,000 chunks (1,298.4 ms → 11.2 ms), tar linear at 8 MiB; CLI `collectOutput` audited and kept (already linear, plan 020); the 10-test near-limit probe `scripts/phase25-bounded-accumulation.test.mjs` is wired into the npm test gate segment and asserts linear copying by byte-count instrumentation. (4) **dead-code cleanup, internal-only** (`dead-code`) — the 62 `dead-exports.mjs` candidates triaged in `docs/_evidence/phase25-dead-exports-triage.md`: 2 internal removals (`PostgresPersistenceCloseOptions`, `SqlitePersistenceCloseOptions` — never re-exported from their adapter indexes), 37 test-used false positives, 20 dead-but-compat-tracked + 3 public type aliases deferred to the 0.3.0 breaking cut; the named-internal audit (`agent-session`/`cache-telemetry`/`skill-load`) recorded clean at 0.2.4; no public export removed. (5) **coverage close, behavior-backed** (`coverage`) — 76 focused regressions (approval 43, conversations 22, artifacts 6, tool-effect-store conformance 5; compaction via its 17 existing package suites); core coverage 90.53/84.20/90.54 → **91.43/84.80/91.60** lines/branches/functions (gate 60/70/75; all 39 non-protected packages above their evidence thresholds). Release graph stays **50** publishable manifests at exact **0.2.5**; zero new runtime dependency names (core remains dependency-free). Store compatibility with 0.2.4: **compatible, no migration** (no persisted-shape change; rollback = restore the 0.2.4 manifests/tag — downgrade is store-safe and code-safe, the added exports simply disappear). Exit gate green (core + script gates incl. `phase24-truth` 12 + `phase25-bounded-accumulation` 10, coverage gate, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.5 — version literal + additive exports only, protected Postgres durable + cross-store conformance evidence per the release skip manifest, release-evidence manifest with zero blocked surfaces, evidence in `scripts/phase25-baseline.json`). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.5 publish handoff` — signed `v0.2.5` tag + npm OIDC).
|
|
7
|
+
|
|
3
8
|
## [0.2.4] - 2026-08-14
|
|
4
9
|
|
|
5
10
|
### Changed
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** create-agent (0.2.5 plan 025 Task 1 split). Moved verbatim from agent-session.ts; public surface unchanged behind the barrel. */
|
|
2
|
+
import type { Agent, AgentConfig, AgentSession, AgentSessionConfig } from "../contracts.js";
|
|
3
|
+
export declare function createAgent(config: AgentConfig): Agent;
|
|
4
|
+
export declare function createAgentSession(config: AgentSessionConfig & {
|
|
5
|
+
readonly agent: Agent;
|
|
6
|
+
}): AgentSession;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RuntimeAgentSession } from "./session.js";
|
|
2
|
+
export function createAgent(config) {
|
|
3
|
+
return {
|
|
4
|
+
config,
|
|
5
|
+
createSession(sessionConfig = {}) {
|
|
6
|
+
return createAgentSession({ ...sessionConfig, agent: this });
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function createAgentSession(config) {
|
|
11
|
+
return new RuntimeAgentSession(config);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=create-agent.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** event-subscriber (0.2.5 plan 025 Task 1 split). Moved verbatim from agent-session.ts; public surface unchanged behind the barrel. */
|
|
2
|
+
import type { AgentEvent, SubscribeOptions } from "../contracts.js";
|
|
3
|
+
export declare class EventSubscriber implements AsyncIterable<AgentEvent>, AsyncIterator<AgentEvent> {
|
|
4
|
+
private readonly sessionId;
|
|
5
|
+
private readonly onClose;
|
|
6
|
+
private readonly queue;
|
|
7
|
+
private readonly waiters;
|
|
8
|
+
private readonly maxQueuedEvents;
|
|
9
|
+
private readonly overflow;
|
|
10
|
+
private closed;
|
|
11
|
+
constructor(sessionId: string, options: SubscribeOptions, onClose: () => void);
|
|
12
|
+
[Symbol.asyncIterator](): AsyncIterator<AgentEvent>;
|
|
13
|
+
next(): Promise<IteratorResult<AgentEvent>>;
|
|
14
|
+
return(): Promise<IteratorResult<AgentEvent>>;
|
|
15
|
+
push(event: AgentEvent): void;
|
|
16
|
+
close(): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export class EventSubscriber {
|
|
2
|
+
sessionId;
|
|
3
|
+
onClose;
|
|
4
|
+
queue = [];
|
|
5
|
+
waiters = [];
|
|
6
|
+
maxQueuedEvents;
|
|
7
|
+
overflow;
|
|
8
|
+
closed = false;
|
|
9
|
+
constructor(sessionId, options, onClose) {
|
|
10
|
+
this.sessionId = sessionId;
|
|
11
|
+
this.onClose = onClose;
|
|
12
|
+
const maxQueuedEvents = options.maxQueuedEvents ?? 1024;
|
|
13
|
+
this.maxQueuedEvents = Number.isFinite(maxQueuedEvents) ? Math.max(1, Math.floor(maxQueuedEvents)) : 1024;
|
|
14
|
+
this.overflow = options.overflow ?? "close";
|
|
15
|
+
}
|
|
16
|
+
[Symbol.asyncIterator]() {
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
next() {
|
|
20
|
+
const event = this.queue.shift();
|
|
21
|
+
if (event)
|
|
22
|
+
return Promise.resolve({ value: event, done: false });
|
|
23
|
+
if (this.closed)
|
|
24
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
25
|
+
return new Promise((resolve) => this.waiters.push(resolve));
|
|
26
|
+
}
|
|
27
|
+
return() {
|
|
28
|
+
this.close();
|
|
29
|
+
this.onClose();
|
|
30
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
31
|
+
}
|
|
32
|
+
push(event) {
|
|
33
|
+
const waiter = this.waiters.shift();
|
|
34
|
+
if (waiter) {
|
|
35
|
+
waiter({ value: event, done: false });
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (this.closed)
|
|
39
|
+
return;
|
|
40
|
+
if (this.queue.length < this.maxQueuedEvents) {
|
|
41
|
+
this.queue.push(event);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (this.overflow === "drop_oldest") {
|
|
45
|
+
this.queue.shift();
|
|
46
|
+
this.queue.push(event);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (this.overflow === "drop_newest")
|
|
50
|
+
return;
|
|
51
|
+
const droppedEvents = this.queue.length + 1;
|
|
52
|
+
this.queue.splice(0, this.queue.length, {
|
|
53
|
+
type: "event_subscriber_overflow",
|
|
54
|
+
sessionId: this.sessionId,
|
|
55
|
+
droppedEvents,
|
|
56
|
+
maxQueuedEvents: this.maxQueuedEvents,
|
|
57
|
+
overflow: this.overflow,
|
|
58
|
+
});
|
|
59
|
+
this.close();
|
|
60
|
+
this.onClose();
|
|
61
|
+
}
|
|
62
|
+
close() {
|
|
63
|
+
this.closed = true;
|
|
64
|
+
for (const waiter of this.waiters.splice(0))
|
|
65
|
+
waiter({ value: undefined, done: true });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=event-subscriber.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** helpers (0.2.5 plan 025 Task 1 split). Moved verbatim from agent-session.ts; public surface unchanged behind the barrel. */
|
|
2
|
+
import type { CompactionOptions, ContentBlock, ErrorInfo, Guardrails, Message, ProviderEvent, RetryOptions, ToolCallContent, Usage } from "../contracts.js";
|
|
3
|
+
import type { AgentInput } from "../input.js";
|
|
4
|
+
import { createId } from "../ids.js";
|
|
5
|
+
export declare function providerContent(event: Extract<ProviderEvent, {
|
|
6
|
+
type: "content_delta" | "tool_call";
|
|
7
|
+
}>): ContentBlock;
|
|
8
|
+
export declare function reconstructMissingToolCalls(deltas: readonly ProviderEvent[], calls: readonly ToolCallContent[]): readonly ToolCallContent[];
|
|
9
|
+
export declare function inputToMessages(input: AgentInput): Message[];
|
|
10
|
+
export declare function messageTextBytes(message: Message): number;
|
|
11
|
+
export declare class SteerSoftInterrupt extends Error {
|
|
12
|
+
readonly code = "steer_soft_interrupt";
|
|
13
|
+
constructor();
|
|
14
|
+
}
|
|
15
|
+
export declare function isSteerSoftInterrupt(error: unknown): boolean;
|
|
16
|
+
export declare function finalAssistantMessage(history: readonly Message[]): {
|
|
17
|
+
readonly message?: Message;
|
|
18
|
+
readonly content: readonly ContentBlock[];
|
|
19
|
+
readonly text: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function errorFromInfo(error: ErrorInfo): Error;
|
|
22
|
+
export declare class ProviderTurnFailure extends Error {
|
|
23
|
+
readonly info: ErrorInfo;
|
|
24
|
+
readonly observable: boolean;
|
|
25
|
+
constructor(info: ErrorInfo, observable: boolean);
|
|
26
|
+
}
|
|
27
|
+
export declare function mergeRetry(agent: false | RetryOptions | undefined, run: false | RetryOptions | undefined): RetryOptions | undefined;
|
|
28
|
+
export declare function mergeCompaction(agent: false | CompactionOptions | undefined, run: false | CompactionOptions | undefined): CompactionOptions | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Durable-run gate: built-in option forms and the single-shot singleton are durable via the
|
|
31
|
+
* pending-call mechanism; a custom strategy must declare both snapshot and restore hooks.
|
|
32
|
+
*/
|
|
33
|
+
export declare function isDurableLoop(loop: import("../contracts.js").AgentLoopStrategy | import("../contracts.js").AgentLoopOptions): boolean;
|
|
34
|
+
export declare function mergeGuardrails(agent: Guardrails | undefined, run: Guardrails | undefined): Guardrails | undefined;
|
|
35
|
+
export declare function withoutTrailingInput(messages: readonly Message[], input: readonly Message[]): Message[];
|
|
36
|
+
export declare function bridgeAbort(signal: AbortSignal | undefined, controller: AbortController): () => void;
|
|
37
|
+
export declare function throwIfAborted(signal: AbortSignal): void;
|
|
38
|
+
export declare function throwIfAbortedSignal(signal: AbortSignal | undefined): void;
|
|
39
|
+
export declare function jsonBytes(value: unknown): number;
|
|
40
|
+
export declare function createUsageAccumulator(): {
|
|
41
|
+
add(usage: Usage): void;
|
|
42
|
+
value(): Usage | undefined;
|
|
43
|
+
};
|
|
44
|
+
export declare const randomId: typeof createId;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { createId } from "../ids.js";
|
|
2
|
+
import { reconstructToolCallDeltas } from "../provider-events.js";
|
|
3
|
+
import { singleShotLoop } from "../agent-loops.js";
|
|
4
|
+
export function providerContent(event) {
|
|
5
|
+
return event.type === "content_delta" ? event.content : event.call;
|
|
6
|
+
}
|
|
7
|
+
export function reconstructMissingToolCalls(deltas, calls) {
|
|
8
|
+
if (deltas.length === 0)
|
|
9
|
+
return [];
|
|
10
|
+
const seen = new Set(calls.map((call) => call.id));
|
|
11
|
+
return reconstructToolCallDeltas(deltas).filter((call) => !seen.has(call.id));
|
|
12
|
+
}
|
|
13
|
+
export function inputToMessages(input) {
|
|
14
|
+
if (typeof input === "string")
|
|
15
|
+
return [{ role: "user", content: [{ type: "text", text: input }] }];
|
|
16
|
+
if ("role" in input)
|
|
17
|
+
return [input];
|
|
18
|
+
return [...input];
|
|
19
|
+
}
|
|
20
|
+
const steerTextEncoder = new TextEncoder();
|
|
21
|
+
export function messageTextBytes(message) {
|
|
22
|
+
let total = 0;
|
|
23
|
+
for (const block of message.content) {
|
|
24
|
+
if (block.type === "text")
|
|
25
|
+
total += steerTextEncoder.encode(block.text).byteLength;
|
|
26
|
+
}
|
|
27
|
+
return total;
|
|
28
|
+
}
|
|
29
|
+
const STEER_SOFT_INTERRUPT_CODE = "steer_soft_interrupt";
|
|
30
|
+
export class SteerSoftInterrupt extends Error {
|
|
31
|
+
code = STEER_SOFT_INTERRUPT_CODE;
|
|
32
|
+
constructor() {
|
|
33
|
+
super("Provider turn soft-interrupted by steer");
|
|
34
|
+
this.name = "SteerSoftInterrupt";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function isSteerSoftInterrupt(error) {
|
|
38
|
+
return (error instanceof SteerSoftInterrupt ||
|
|
39
|
+
(typeof error === "object" && error !== null && error.code === STEER_SOFT_INTERRUPT_CODE));
|
|
40
|
+
}
|
|
41
|
+
export function finalAssistantMessage(history) {
|
|
42
|
+
for (let index = history.length - 1; index >= 0; index -= 1) {
|
|
43
|
+
const message = history[index];
|
|
44
|
+
if (message.role !== "assistant")
|
|
45
|
+
continue;
|
|
46
|
+
const text = message.content
|
|
47
|
+
.filter((block) => block.type === "text")
|
|
48
|
+
.map((block) => block.text)
|
|
49
|
+
.join("");
|
|
50
|
+
return { message, content: message.content, text };
|
|
51
|
+
}
|
|
52
|
+
return { content: [], text: "" };
|
|
53
|
+
}
|
|
54
|
+
export function errorFromInfo(error) {
|
|
55
|
+
return Object.assign(new Error(error.message), { name: error.name ?? "Error", cause: error.cause, code: error.code });
|
|
56
|
+
}
|
|
57
|
+
export class ProviderTurnFailure extends Error {
|
|
58
|
+
info;
|
|
59
|
+
observable;
|
|
60
|
+
constructor(info, observable) {
|
|
61
|
+
super(info.message);
|
|
62
|
+
this.info = info;
|
|
63
|
+
this.observable = observable;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function mergeRetry(agent, run) {
|
|
67
|
+
if (run === false)
|
|
68
|
+
return undefined;
|
|
69
|
+
if (run)
|
|
70
|
+
return { ...(agent || {}), ...run };
|
|
71
|
+
return agent || undefined;
|
|
72
|
+
}
|
|
73
|
+
export function mergeCompaction(agent, run) {
|
|
74
|
+
if (run === false)
|
|
75
|
+
return undefined;
|
|
76
|
+
if (run)
|
|
77
|
+
return { ...(agent || {}), ...run };
|
|
78
|
+
return agent || undefined;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Durable-run gate: built-in option forms and the single-shot singleton are durable via the
|
|
82
|
+
* pending-call mechanism; a custom strategy must declare both snapshot and restore hooks.
|
|
83
|
+
*/
|
|
84
|
+
export function isDurableLoop(loop) {
|
|
85
|
+
if (typeof loop !== "object" || loop === null)
|
|
86
|
+
return true;
|
|
87
|
+
if ("strategy" in loop)
|
|
88
|
+
return true;
|
|
89
|
+
if (loop === singleShotLoop)
|
|
90
|
+
return true;
|
|
91
|
+
return typeof loop.snapshot === "function" && typeof loop.restore === "function";
|
|
92
|
+
}
|
|
93
|
+
export function mergeGuardrails(agent, run) {
|
|
94
|
+
if (!agent && !run)
|
|
95
|
+
return undefined;
|
|
96
|
+
return {
|
|
97
|
+
input: [...(agent?.input ?? []), ...(run?.input ?? [])],
|
|
98
|
+
output: [...(agent?.output ?? []), ...(run?.output ?? [])],
|
|
99
|
+
toolInput: [...(agent?.toolInput ?? []), ...(run?.toolInput ?? [])],
|
|
100
|
+
toolOutput: [...(agent?.toolOutput ?? []), ...(run?.toolOutput ?? [])],
|
|
101
|
+
maxConcurrency: run?.maxConcurrency ?? agent?.maxConcurrency,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export function withoutTrailingInput(messages, input) {
|
|
105
|
+
const next = [...messages];
|
|
106
|
+
for (let i = input.length - 1; i >= 0; i -= 1) {
|
|
107
|
+
const last = next.at(-1);
|
|
108
|
+
if (last && stableMessageKey(last) === stableMessageKey(input[i]))
|
|
109
|
+
next.pop();
|
|
110
|
+
}
|
|
111
|
+
return next;
|
|
112
|
+
}
|
|
113
|
+
// Key-order-insensitive comparison: a redacted-then-reassembled message with reordered
|
|
114
|
+
// keys must still dedupe against the trailing input, or auto-compaction duplicates it.
|
|
115
|
+
function stableMessageKey(value) {
|
|
116
|
+
if (Array.isArray(value))
|
|
117
|
+
return `[${value.map(stableMessageKey).join(",")}]`;
|
|
118
|
+
if (value !== null && typeof value === "object") {
|
|
119
|
+
const record = value;
|
|
120
|
+
return `{${Object.keys(record)
|
|
121
|
+
.sort()
|
|
122
|
+
.map((key) => `${JSON.stringify(key)}:${stableMessageKey(record[key])}`)
|
|
123
|
+
.join(",")}}`;
|
|
124
|
+
}
|
|
125
|
+
return JSON.stringify(value) ?? "null";
|
|
126
|
+
}
|
|
127
|
+
export function bridgeAbort(signal, controller) {
|
|
128
|
+
if (!signal)
|
|
129
|
+
return () => undefined;
|
|
130
|
+
const abort = () => controller.abort(signal.reason);
|
|
131
|
+
if (signal.aborted)
|
|
132
|
+
abort();
|
|
133
|
+
else
|
|
134
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
135
|
+
return () => signal.removeEventListener("abort", abort);
|
|
136
|
+
}
|
|
137
|
+
export function throwIfAborted(signal) {
|
|
138
|
+
throwIfAbortedSignal(signal);
|
|
139
|
+
}
|
|
140
|
+
export function throwIfAbortedSignal(signal) {
|
|
141
|
+
if (signal?.aborted)
|
|
142
|
+
throw signal.reason instanceof Error ? signal.reason : new Error("Agent run aborted");
|
|
143
|
+
}
|
|
144
|
+
const jsonTextEncoder = new TextEncoder();
|
|
145
|
+
export function jsonBytes(value) {
|
|
146
|
+
try {
|
|
147
|
+
return jsonTextEncoder.encode(JSON.stringify(value)).byteLength;
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
throw new TypeError("Provider request or event must be JSON-serializable for run limits");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
export function createUsageAccumulator() {
|
|
154
|
+
const sums = new Map();
|
|
155
|
+
let costCurrency;
|
|
156
|
+
let costCompatible = true;
|
|
157
|
+
return {
|
|
158
|
+
add(usage) {
|
|
159
|
+
for (const key of ["inputTokens", "outputTokens", "cacheReadTokens", "cacheWriteTokens"]) {
|
|
160
|
+
const value = usage[key];
|
|
161
|
+
if (value !== undefined)
|
|
162
|
+
sums.set(key, (sums.get(key) ?? 0) + value);
|
|
163
|
+
}
|
|
164
|
+
const total = usage.totalTokens ??
|
|
165
|
+
(usage.inputTokens !== undefined || usage.outputTokens !== undefined
|
|
166
|
+
? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0)
|
|
167
|
+
: undefined);
|
|
168
|
+
if (total !== undefined)
|
|
169
|
+
sums.set("totalTokens", (sums.get("totalTokens") ?? 0) + total);
|
|
170
|
+
if (usage.cost !== undefined && costCompatible) {
|
|
171
|
+
if (!sums.has("cost"))
|
|
172
|
+
costCurrency = usage.currency;
|
|
173
|
+
else if (usage.currency !== costCurrency)
|
|
174
|
+
costCompatible = false;
|
|
175
|
+
if (costCompatible)
|
|
176
|
+
sums.set("cost", (sums.get("cost") ?? 0) + usage.cost);
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
value() {
|
|
180
|
+
if (sums.size === 0)
|
|
181
|
+
return undefined;
|
|
182
|
+
const usage = {};
|
|
183
|
+
for (const [key, value] of sums) {
|
|
184
|
+
if (key !== "cost" || costCompatible)
|
|
185
|
+
usage[key] = value;
|
|
186
|
+
}
|
|
187
|
+
if (costCompatible && sums.has("cost") && costCurrency !== undefined)
|
|
188
|
+
usage.currency = costCurrency;
|
|
189
|
+
return Object.keys(usage).length > 0 ? usage : undefined;
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
export const randomId = createId;
|
|
194
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/** session (0.2.5 plan 025 Task 1 split). Moved verbatim from agent-session.ts; public surface unchanged behind the barrel. */
|
|
2
|
+
import type { Agent, AgentEvent, AgentRunResult, AgentRunStateOptions, AgentSession, AgentSessionConfig, CompactionOptions, CompactionResult, OwnershipScope, RunDecision, RunOptions, SessionEntry, SteerOptions, SubscribeOptions } from "../contracts.js";
|
|
3
|
+
import type { AgentInput } from "../input.js";
|
|
4
|
+
import type { LoadedSkillBodiesEntry } from "../skill-load.js";
|
|
5
|
+
import type { StoredAgentRunState } from "../agent-run-state.js";
|
|
6
|
+
export declare class RuntimeAgentSession implements AgentSession {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
private readonly agent;
|
|
9
|
+
private readonly metadata?;
|
|
10
|
+
private readonly store;
|
|
11
|
+
private readonly subscribers;
|
|
12
|
+
private currentLeafId?;
|
|
13
|
+
private history;
|
|
14
|
+
private activeRun?;
|
|
15
|
+
private activeRunId?;
|
|
16
|
+
private activeProviderTurnAbort?;
|
|
17
|
+
private pendingSoftInterrupt;
|
|
18
|
+
private pendingSteers;
|
|
19
|
+
private pendingSteerBytes;
|
|
20
|
+
private activeRedactor?;
|
|
21
|
+
private activeProvider?;
|
|
22
|
+
private activeLedger?;
|
|
23
|
+
private activeEffectStore?;
|
|
24
|
+
private activeOwnership?;
|
|
25
|
+
private activeIdentity?;
|
|
26
|
+
private activeIdempotencyKey?;
|
|
27
|
+
private activeGuardrails?;
|
|
28
|
+
private activeMetadata?;
|
|
29
|
+
private activeLimits?;
|
|
30
|
+
private activeLimitOutputBuffer;
|
|
31
|
+
private activeDurable?;
|
|
32
|
+
private activeLoop?;
|
|
33
|
+
/** Gated calls of the current tool round awaiting one collected suspension. */
|
|
34
|
+
private activeGatedRound?;
|
|
35
|
+
private activeLoopTurn;
|
|
36
|
+
private readonly loadedSkills;
|
|
37
|
+
/** Plan 018 Task 6 (closeout `checkpoint-bodies`): persisted exact instructions, registry-independent. */
|
|
38
|
+
private restoredSkillBodies;
|
|
39
|
+
/** Skills of the current run (for the bodies snapshot); replaced at each run start. */
|
|
40
|
+
private activeRunSkills;
|
|
41
|
+
/** Plan 015 Task 4: re-add persisted loaded-skill names (names only; bodies re-resolve on demand). */
|
|
42
|
+
restoreLoadedSkills(names: readonly string[]): void;
|
|
43
|
+
/** Plan 018 Task 6: restore persisted loaded-skill bodies (already validated fail-closed at load). */
|
|
44
|
+
restoreLoadedSkillBodies(bodies: readonly LoadedSkillBodiesEntry[]): void;
|
|
45
|
+
private ledgerChain;
|
|
46
|
+
private ledgerFailure;
|
|
47
|
+
private snapshotGeneration;
|
|
48
|
+
private snapshotCache?;
|
|
49
|
+
constructor(config: AgentSessionConfig & {
|
|
50
|
+
readonly agent: Agent;
|
|
51
|
+
});
|
|
52
|
+
get leafId(): string | undefined;
|
|
53
|
+
subscribe(options?: SubscribeOptions): AsyncIterable<AgentEvent>;
|
|
54
|
+
run(input: AgentInput, options?: RunOptions): Promise<AgentRunResult>;
|
|
55
|
+
steer(input: AgentInput, options?: SteerOptions): void;
|
|
56
|
+
resumeDurable(state: StoredAgentRunState, runState: AgentRunStateOptions, ownership?: OwnershipScope, signal?: AbortSignal, decisions?: ReadonlyMap<string, RunDecision>): Promise<AgentRunResult>;
|
|
57
|
+
recordDurableResumption(runId: string, interruption: import("../contracts.js").AgentRunInterruption, version: number, ownership?: OwnershipScope): Promise<void>;
|
|
58
|
+
recordDurableDenial(runId: string, interruption: import("../contracts.js").AgentRunInterruption, version: number, ownership?: OwnershipScope): Promise<void>;
|
|
59
|
+
private runInternal;
|
|
60
|
+
prompt(input: string, options?: RunOptions): Promise<AgentRunResult>;
|
|
61
|
+
stream(input: AgentInput, options?: RunOptions & SubscribeOptions): AsyncGenerator<AgentEvent>;
|
|
62
|
+
private buildRunResult;
|
|
63
|
+
private suspendDurable;
|
|
64
|
+
/** First attributed sticky whose scope and delegation path exactly match a nested decision. */
|
|
65
|
+
private matchNestedSticky;
|
|
66
|
+
/** First sticky decision whose scope exactly matches this call, if any. */
|
|
67
|
+
private matchStickyDecision;
|
|
68
|
+
/** Redacted pending-decision descriptor for one gated call; never carries raw arguments. */
|
|
69
|
+
private buildPendingDecision;
|
|
70
|
+
private persistDurable;
|
|
71
|
+
compact(options?: CompactionOptions): Promise<CompactionResult>;
|
|
72
|
+
abort(reason?: unknown): void;
|
|
73
|
+
entries(): Promise<readonly SessionEntry[]>;
|
|
74
|
+
checkout(leafId?: string): Promise<void>;
|
|
75
|
+
fork(options?: {
|
|
76
|
+
readonly leafId?: string;
|
|
77
|
+
}): AgentSession;
|
|
78
|
+
clone(options?: {
|
|
79
|
+
readonly id?: string;
|
|
80
|
+
readonly leafId?: string;
|
|
81
|
+
}): Promise<AgentSession>;
|
|
82
|
+
private branchReader;
|
|
83
|
+
private resolveRunProvider;
|
|
84
|
+
private resolveRunSkills;
|
|
85
|
+
private emit;
|
|
86
|
+
private closeSubscribers;
|
|
87
|
+
private drainLedger;
|
|
88
|
+
private generateWithRetry;
|
|
89
|
+
private generateProviderTurn;
|
|
90
|
+
private applyPendingSteers;
|
|
91
|
+
private applyProviderRequestPolicies;
|
|
92
|
+
private appendMessage;
|
|
93
|
+
private autoCompact;
|
|
94
|
+
private compactBranch;
|
|
95
|
+
private appendEntry;
|
|
96
|
+
private invalidateSnapshot;
|
|
97
|
+
private redact;
|
|
98
|
+
private redactProviderRequest;
|
|
99
|
+
private rebuildHistory;
|
|
100
|
+
private snapshot;
|
|
101
|
+
}
|