@aparte/engine 0.2.0-alpha.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 aparté
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # @aparte/engine
2
+
3
+ The **headless agent loop** behind `@aparte/*` — framework-agnostic, zero runtime
4
+ dependencies, runs in the browser or Node.
5
+
6
+ Its core export is **`runStreamAgent`**: a DOM-free structured-stream loop that turns a
7
+ transport's token stream into high-level run events (text, thinking, tool calls, artifacts),
8
+ drives the tool-calling loop (with optional human-in-the-loop approval), and reports usage.
9
+
10
+ `@aparte/core` embeds the same loop inline (`AparteClient._streamLoop`) so **core works
11
+ without this package**. `@aparte/engine` is the *recommended path*: inject `runStreamAgent`
12
+ via `AparteClientOptions.streamRunner` and core renders its events through
13
+ `createStreamAdapter`. Parity between the two is proven by this package's `stream-parity`
14
+ suite (it drives core's real `_streamLoop` and `runStreamAgent` against the same scripted
15
+ transport and asserts identical output).
16
+
17
+ `@aparte/core` is an **optional peer** — `runStreamAgent` and its parsers import nothing from
18
+ it; the orchestrator/memory helpers use core's config/types when present.
19
+
20
+ > Part of the [aparté](https://github.com/apartejs/aparte) monorepo. ESM-only.
@@ -0,0 +1,86 @@
1
+ /**
2
+ * artifact-xml-state-machine.ts — streaming `<artifact>` XML parser (pure).
3
+ *
4
+ * The framework-free extraction of the XML-artifact branch inside
5
+ * `AparteClient._streamLoop` (aparte-client.ts :1268-1392 + finalize :1658-1669).
6
+ * Small models emit artifacts as `…chat text… <artifact mimeType="…" title="…">
7
+ * BODY</artifact> …more text…`, streamed in arbitrary chunks that can split the
8
+ * opening tag, the body, or the closing tag across delta boundaries.
9
+ *
10
+ * This module owns only the PARSING (state + buffering); it emits DOM-free
11
+ * micro-events. The `@aparte/core` adapter turns them into segment/lifecycle calls
12
+ * (addSegment / updateSegment / _dispatchArtifactLifecycle) exactly as
13
+ * `_streamLoop` does — so no DOM, no `@aparte/core` import here.
14
+ *
15
+ * Ported faithfully, including quirks: a `<artifact` split as `<arti`+`fact`
16
+ * (so `indexOf('<artifact')` misses it) is treated as chat text, matching the
17
+ * source. Providers emit the tag atomically in practice.
18
+ */
19
+ /** Where the streaming parser is between artifacts. */
20
+ export type XmlArtifactState = 'normal' | 'scanning' | 'in-artifact';
21
+ /** Fallback mime/kind for an artifact whose open tag omits the attribute. */
22
+ export interface XmlArtifactHint {
23
+ mimeType: string;
24
+ kind: string;
25
+ }
26
+ /** DOM-free micro-events the machine emits; the adapter renders them. */
27
+ export type XmlArtifactEvent = {
28
+ type: 'chat-text';
29
+ text: string;
30
+ reduced?: boolean;
31
+ } | {
32
+ type: 'artifact-open';
33
+ id: string;
34
+ mimeType: string;
35
+ kind: string;
36
+ title: string;
37
+ } | {
38
+ type: 'artifact-chunk';
39
+ id: string;
40
+ content: string;
41
+ } | {
42
+ type: 'artifact-close';
43
+ id: string;
44
+ content: string;
45
+ inline: boolean;
46
+ };
47
+ /**
48
+ * Map an artifact mimeType to a renderer kind. Byte-identical copy of core's
49
+ * canonical `deriveArtifactKind` (parsers/aparte-stream-parser.ts) — the
50
+ * duplicate stays because `@aparte/core` is an OPTIONAL peer of the engine, so
51
+ * no runtime import is possible. Kept in sync mechanically by
52
+ * `__tests__/derive-artifact-kind-parity.test.ts`.
53
+ */
54
+ export declare function deriveArtifactKind(mimeType: string, fallback?: string): string;
55
+ /**
56
+ * A stateful streaming parser for one turn's `<artifact>` blocks. Feed it each
57
+ * text delta; drain the returned events. Call {@link finalize} when the stream
58
+ * ends to flush a truncated (unclosed) artifact.
59
+ */
60
+ export declare class ArtifactXmlStateMachine {
61
+ private readonly hint;
62
+ private state;
63
+ /** Buffers the opening tag until its `>` arrives (may span deltas). */
64
+ private scanBuf;
65
+ /** Buffers the tail that might be the start of a split `</artifact>`. */
66
+ private closeBuf;
67
+ private segId;
68
+ private content;
69
+ private mime;
70
+ private kind;
71
+ private title;
72
+ private seq;
73
+ private readonly idGen;
74
+ constructor(hint: XmlArtifactHint, idGen?: () => string);
75
+ /** Feed one text delta; returns the ordered micro-events it produced. */
76
+ feed(delta: string): XmlArtifactEvent[];
77
+ /**
78
+ * Flush a truncated artifact: if the stream ended mid-body (model cut off
79
+ * before `</artifact>`), emit a close with whatever was buffered. Mirrors
80
+ * `_streamLoop`'s finalize block (:1658-1669).
81
+ */
82
+ finalize(): XmlArtifactEvent[];
83
+ /** Current parser state (for the adapter to decide finalize routing). */
84
+ get currentState(): XmlArtifactState;
85
+ }
86
+ //# sourceMappingURL=artifact-xml-state-machine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-xml-state-machine.d.ts","sourceRoot":"","sources":["../../../src/agent/parsers/artifact-xml-state-machine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,uDAAuD;AACvD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,UAAU,GAAG,aAAa,CAAC;AAErE,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,yEAAyE;AACzE,MAAM,MAAM,gBAAgB,GAMtB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpF;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AAO/E;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAY,GAAG,MAAM,CAqBjF;AAED;;;;GAIG;AACH,qBAAa,uBAAuB;IAcpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAbjC,OAAO,CAAC,KAAK,CAA8B;IAC3C,uEAAuE;IACvE,OAAO,CAAC,OAAO,CAAM;IACrB,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAER,IAAI,EAAE,eAAe,EAAE,KAAK,CAAC,EAAE,MAAM,MAAM;IAIxE,yEAAyE;IACzE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,EAAE;IA4DvC;;;;OAIG;IACH,QAAQ,IAAI,gBAAgB,EAAE;IAY9B,yEAAyE;IACzE,IAAI,YAAY,IAAI,gBAAgB,CAEnC;CACJ"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * stream-events.contract.ts — COMPILE-TIME guard for the core↔engine run-event mirror.
3
+ *
4
+ * `StreamRunEvent` (this package) and `AparteStreamRunEvent` (@aparte/core's adapter)
5
+ * are hand-mirrored across the zero-import boundary: core is the zero-dep leaf and must
6
+ * never import engine, and engine keeps its stream contract standalone (see
7
+ * `stream-events.ts`). That leaves the two unions synced BY HAND — the seam's one
8
+ * unguarded soft spot. A silent drift here (a renamed/added variant, a changed payload
9
+ * field) would corrupt streaming with no CI signal.
10
+ *
11
+ * This file makes that drift a TYPECHECK ERROR. It ships nothing: it only declares
12
+ * type aliases (erased) and `import type`s core (erased → no runtime dep, so the
13
+ * runtime zero-import rule still holds; core is present as engine's dev/peer dep at
14
+ * typecheck time). It is not imported by the barrel, so it stays out of the bundle.
15
+ *
16
+ * The ONE intentional difference is `run-done.usage`: core carries the rich
17
+ * `AparteUsage` (named provider-timing fields — ttft/decode/phases/…), engine an
18
+ * opaque `StreamUsage` passthrough (five common fields + an index signature). We
19
+ * normalize that single field to compare the rest of the contract for EXACT equality,
20
+ * and separately assert the usage stays forwardable engine→core (the seam direction:
21
+ * core's adapter consumes engine's `run-done` and forwards its usage to `setUsage`).
22
+ */
23
+ import type { AparteStreamRunEvent, AparteStreamRunEmitter } from '@aparte/core';
24
+ import type { StreamRunEvent, StreamRunEmitter } from './stream-events.js';
25
+ /** Invariant type-equality — distinguishes optional vs required and index signatures. */
26
+ type Equal<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false;
27
+ /** Compiles only when its argument is exactly `true`. */
28
+ type Expect<T extends true> = T;
29
+ /** Distributes over a union `A`: `true` iff every member is assignable to `B`. */
30
+ type Assignable<A, B> = A extends B ? true : false;
31
+ /** Erase the sole intentional difference (run-done.usage) before the equality check. */
32
+ type NormalizeRunDone<E> = E extends {
33
+ type: 'run-done';
34
+ } ? {
35
+ type: 'run-done';
36
+ usage?: unknown;
37
+ } : E;
38
+ /**
39
+ * Each element compiles only if its contract holds; a drift turns one into a
40
+ * `false`, which fails `Expect<...>` and breaks the typecheck. Exported so it isn't
41
+ * flagged as unused — this file is not re-exported by the barrel, so it never reaches
42
+ * `@aparte/engine`'s public surface.
43
+ *
44
+ * 1. Every variant except `run-done.usage` is structurally identical (exact equality).
45
+ * 2. The `run-done` usage stays forwardable engine→core (lets core's adapter treat it
46
+ * as `AparteUsage`).
47
+ * 3. The emitter core injects into `runStreamAgent` satisfies engine's emitter contract.
48
+ */
49
+ export type StreamEventContract = [
50
+ Expect<Equal<NormalizeRunDone<StreamRunEvent>, NormalizeRunDone<AparteStreamRunEvent>>>,
51
+ Expect<Assignable<StreamRunEvent, AparteStreamRunEvent>>,
52
+ Expect<Assignable<AparteStreamRunEmitter, StreamRunEmitter>>
53
+ ];
54
+ export {};
55
+ //# sourceMappingURL=stream-events.contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-events.contract.d.ts","sourceRoot":"","sources":["../../src/agent/stream-events.contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACjF,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,yFAAyF;AACzF,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC,IACX,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;AACzF,yDAAyD;AACzD,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;AAChC,kFAAkF;AAClF,KAAK,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;AAEnD,wFAAwF;AACxF,KAAK,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,CAAC,CAAC;AAEtG;;;;;;;;;;GAUG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAC9B,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,EAAE,gBAAgB,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACvF,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAC;IACxD,MAAM,CAAC,UAAU,CAAC,sBAAsB,EAAE,gBAAgB,CAAC,CAAC;CAC/D,CAAC"}
@@ -0,0 +1,209 @@
1
+ /**
2
+ * stream-events.ts — contract for the framework-free structured-stream agent loop.
3
+ *
4
+ * `runStreamAgent` ({@link ./stream-run}) is the cloud-structured sibling of
5
+ * `runAgent` ({@link ./agent-loop}): where `runAgent` drives a text-only
6
+ * provider (`chat → string`, tool calls re-parsed from text), `runStreamAgent`
7
+ * consumes a **structured** `AsyncIterable<StreamChatEvent>` (text / thinking /
8
+ * tool_use / done / error) — the exact stream `AparteClient._streamLoop` reads
9
+ * today. It is the extraction target for that 700-line DOM-coupled loop.
10
+ *
11
+ * DOM stays out of here. The loop emits high-level {@link StreamRunEvent}s in the
12
+ * exact order `_streamLoop` performs its `targetElement.*` calls; a thin adapter
13
+ * (in `@aparte/core`, where the parser and renderers live) translates each event
14
+ * into the imperative viewport surface. So this module — and {@link ./stream-run}
15
+ * — import **nothing** from `@aparte/core`: the types below structurally mirror the
16
+ * core types (`AparteStreamEvent`, `AparteUsage`, `AparteChatMessage`, `AparteToolCall`)
17
+ * so the adapter passes the real objects through with zero runtime conversion.
18
+ *
19
+ * SCOPE: text · thinking · tool_use (+ HITL approval) · done · error · artifacts
20
+ * (raw / XML state machine / create_artifact) · multi-phase pipeline · synthetic
21
+ * toolChoice bypass. Code-fence promotion is the only `_streamLoop` mechanism
22
+ * left out here — it is adapter-side (it needs the core parser).
23
+ */
24
+ /**
25
+ * Token usage. Structurally a superset-compatible mirror of `AparteUsage`: the
26
+ * five common fields plus an index signature that carries the provider-specific
27
+ * rest (ttft/decode/phases/…) opaquely — the loop transports usage, never reads
28
+ * past these five.
29
+ */
30
+ export interface StreamUsage {
31
+ inputTokens: number;
32
+ outputTokens: number;
33
+ totalTokens?: number;
34
+ cacheReadTokens?: number;
35
+ durationMs?: number;
36
+ [key: string]: unknown;
37
+ }
38
+ /** One tool call as surfaced by the provider stream (mirrors `AparteToolCall`). */
39
+ export interface StreamToolCall {
40
+ id: string;
41
+ name: string;
42
+ input: unknown;
43
+ }
44
+ /**
45
+ * A structured stream event from the transport (mirrors `AparteStreamEvent`). The
46
+ * `tool_use` variant spreads {@link StreamToolCall} exactly like core's does.
47
+ */
48
+ export type StreamChatEvent = {
49
+ type: 'text';
50
+ delta: string;
51
+ } | {
52
+ type: 'thinking';
53
+ delta: string;
54
+ } | {
55
+ type: 'tool_use';
56
+ id: string;
57
+ name: string;
58
+ input: unknown;
59
+ } | {
60
+ type: 'error';
61
+ message: string;
62
+ } | {
63
+ type: 'done';
64
+ usage?: StreamUsage;
65
+ };
66
+ /**
67
+ * A conversation message (mirrors `AparteChatMessage`). `role` is left open
68
+ * (`string`) so the loop can push the `'tool_call'` / `'tool_result'` envelope
69
+ * roles `_streamLoop` uses without importing core's union.
70
+ */
71
+ export interface StreamAgentMessage {
72
+ role: string;
73
+ content: string;
74
+ /** Present on a `'tool_call'` envelope — the whole turn's calls, grouped. */
75
+ toolCalls?: StreamToolCall[];
76
+ /** Present on a `'tool_result'` message — which call it answers. */
77
+ toolCallId?: string;
78
+ /** Assistant text that preceded the tool call(s) this turn. */
79
+ precedingText?: string;
80
+ [key: string]: unknown;
81
+ }
82
+ /** The request handed to the transport each turn (mirrors `AparteChatRequest`). */
83
+ export interface StreamChatRequest {
84
+ messages: StreamAgentMessage[];
85
+ [key: string]: unknown;
86
+ }
87
+ /** A tool handler (mirrors the resolved `AparteToolHandler`). */
88
+ export type StreamToolHandler = (call: StreamToolCall, signal: AbortSignal) => Promise<{
89
+ content: string;
90
+ }>;
91
+ /** Per-tool loop configuration (mirrors the `AparteTool` subset the loop reads). */
92
+ export interface StreamToolConfig {
93
+ maxTurns?: number;
94
+ needsApproval?: boolean;
95
+ }
96
+ /**
97
+ * Resolves a human-in-the-loop approval (mirrors core's
98
+ * `AparteToolApprovalResolver`). Injected so the loop stays headless.
99
+ */
100
+ export type StreamApprovalResolver = (toolCallId: string, signal: AbortSignal) => Promise<{
101
+ approved: boolean;
102
+ payload?: unknown;
103
+ }>;
104
+ /**
105
+ * High-level, DOM-free events isomorphic to `_streamLoop`'s `targetElement.*`
106
+ * call sequence. Emitted **synchronously and in order** (see {@link StreamRunEmitter})
107
+ * so the adapter reproduces the exact streaming update order.
108
+ *
109
+ * Mapping to `_streamLoop` (aparte-client.ts) for the adapter:
110
+ * - `run-start` → updateMessage(status:'streaming') once at loop entry (the leading write before turn 1)
111
+ * - `turn-start` → reset the per-turn parser / thinking / streaming-segment state (no DOM); one per turn
112
+ * - `text-delta` → parser-driven addSegment/updateSegment, else typeName/updateLastMessage
113
+ * - `text-flush` → textParser.finalize() then addSegment/updateSegment the finalized segments;
114
+ * one per turn, after the inner SSE loop ends (surfaced by the spike — a turn-boundary flush)
115
+ * - `thinking-delta` → addSegment('thinking') then updateSegment(content); first `text-delta` after
116
+ * thinking collapses it (updateSegment collapsed:true)
117
+ * - `tool-start` → renderer lookup + per-tool-name CSS inject into document.head + addSegment
118
+ * - `tool-awaiting-approval` → updateSegment('awaiting-approval') + dispatch `aparte-tool-approval-request`
119
+ * - `tool-approved` → updateSegment('pending')
120
+ * - `tool-rejected` → updateSegment('rejected', result)
121
+ * - `tool-resolved` → updateSegment('resolved', result)
122
+ * - `tool-aborted` → updateSegment('aborted') (no-handler path, timeout/abort path, or per-tool maxTurns path)
123
+ * - `turn-limit-exceeded` scope:'global' → addSegment(error 'MAX_TURNS_EXCEEDED');
124
+ * scope:'tool' → updateSegment('aborted')
125
+ * - `phase-advance` → addSegment({type:'pipeline-waiting'}); the loop has already
126
+ * pushed the phase's reply into history and bumped the phase index
127
+ * - `run-aborted` → dispatch `aparte-message-aborted` (from the inner-loop abort check or the outer turn-boundary abort check)
128
+ * - `run-done` → updateMessage(status:'completed') always + setUsage if usage
129
+ */
130
+ export type StreamRunEvent = {
131
+ type: 'run-start';
132
+ } | {
133
+ type: 'turn-start';
134
+ } | {
135
+ type: 'text-delta';
136
+ delta: string;
137
+ reduced?: boolean;
138
+ } | {
139
+ type: 'text-flush';
140
+ } | {
141
+ type: 'thinking-delta';
142
+ delta: string;
143
+ } | {
144
+ type: 'artifact-open';
145
+ id: string;
146
+ mimeType: string;
147
+ kind: string;
148
+ title: string;
149
+ } | {
150
+ type: 'artifact-chunk';
151
+ id: string;
152
+ content: string;
153
+ } | {
154
+ type: 'artifact-close';
155
+ id: string;
156
+ content: string;
157
+ inline: boolean;
158
+ } | {
159
+ type: 'artifact-ready';
160
+ id: string;
161
+ mimeType: string;
162
+ kind: string;
163
+ title: string;
164
+ content: string;
165
+ } | {
166
+ type: 'tool-start';
167
+ toolCallId: string;
168
+ name: string;
169
+ input: unknown;
170
+ } | {
171
+ type: 'tool-awaiting-approval';
172
+ toolCallId: string;
173
+ name: string;
174
+ input: unknown;
175
+ } | {
176
+ type: 'tool-approved';
177
+ toolCallId: string;
178
+ } | {
179
+ type: 'tool-rejected';
180
+ toolCallId: string;
181
+ reason: string;
182
+ } | {
183
+ type: 'tool-resolved';
184
+ toolCallId: string;
185
+ result: string;
186
+ } | {
187
+ type: 'tool-aborted';
188
+ toolCallId: string;
189
+ } | {
190
+ type: 'turn-limit-exceeded';
191
+ scope: 'global' | 'tool';
192
+ limit: number;
193
+ toolCallId?: string;
194
+ } | {
195
+ type: 'phase-advance';
196
+ index: number;
197
+ } | {
198
+ type: 'run-aborted';
199
+ } | {
200
+ type: 'run-done';
201
+ usage?: StreamUsage;
202
+ };
203
+ /**
204
+ * Synchronous event sink — mirrors `AGUIEmitter`. Synchronous by contract: the
205
+ * loop must never yield between emitting an event and its ordered successor, or
206
+ * the adapter's streaming updates would interleave out of order.
207
+ */
208
+ export type StreamRunEmitter = (event: StreamRunEvent) => void;
209
+ //# sourceMappingURL=stream-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-events.d.ts","sourceRoot":"","sources":["../../src/agent/stream-events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * stream-run.ts — framework-free structured-stream agent loop.
3
+ *
4
+ * The headless extraction of `AparteClient._streamLoop`: a `while(tool_use)` loop
5
+ * that consumes a structured `AsyncIterable<StreamChatEvent>` from a transport,
6
+ * runs approved tools, feeds their results back into the history, and re-calls
7
+ * the transport until the model stops asking for tools. It performs **no DOM
8
+ * work** — it emits {@link StreamRunEvent}s (in `_streamLoop`'s exact order) that
9
+ * an adapter in `@aparte/core` turns into `targetElement.*` calls.
10
+ *
11
+ * Parity target: `@aparte/core`'s `AparteClient._streamLoop`.
12
+ * Scope: text · thinking · tool_use (+ HITL) · done · error · artifacts (raw /
13
+ * XML / create_artifact) · multi-phase pipeline · synthetic toolChoice bypass.
14
+ * Code-fence promotion stays adapter-side (it needs the core parser).
15
+ */
16
+ import type { StreamRunEmitter, StreamChatEvent, StreamChatRequest, StreamToolHandler, StreamToolConfig, StreamApprovalResolver, StreamUsage } from './stream-events.js';
17
+ export interface StreamRunOptions {
18
+ /** Id of the assistant message being streamed (opaque; carried in events). */
19
+ messageId: string;
20
+ /** Turn-1 request; the loop clones its `messages` and enriches them per turn. */
21
+ baseRequest: StreamChatRequest;
22
+ /**
23
+ * Calls the transport with the (possibly enriched) request. Returns the
24
+ * structured stream, or a plain string for a non-streaming provider. Mirrors
25
+ * `getTransport().chat(provider, request, auth, ctx)` with provider/auth/ctx
26
+ * closed over by the adapter.
27
+ */
28
+ transportCall: (request: StreamChatRequest) => Promise<AsyncIterable<StreamChatEvent> | string>;
29
+ /** Resolves a tool's handler by name (mirrors `AparteConfig.getToolHandler`). */
30
+ toolLookup: (name: string) => StreamToolHandler | undefined;
31
+ /** Resolves a tool's loop config by name (maxTurns / needsApproval). */
32
+ toolConfigLookup?: (name: string) => StreamToolConfig | undefined;
33
+ /** HITL approval resolver for `needsApproval` tools (default: never called). */
34
+ approvalResolver?: StreamApprovalResolver;
35
+ /** Synchronous, ordered event sink consumed by the adapter. */
36
+ emitter: StreamRunEmitter;
37
+ /** Single abort signal composing `_isAborted` + the stream controller. */
38
+ signal: AbortSignal;
39
+ /** Global turn cap. @default 10 */
40
+ maxTurns?: number;
41
+ /** Per-tool-call handler timeout in ms. @default 300000 */
42
+ toolTimeoutMs?: number;
43
+ /**
44
+ * Generates artifact segment ids (`prefix` is e.g. `'artifact-raw'`). The
45
+ * default is a deterministic per-run counter; the adapter injects a
46
+ * crypto-based one to match `_streamLoop`'s `artifact-*-<uuid>`. (Tool ids
47
+ * still flow from the stream; only artifacts need generated ids.)
48
+ */
49
+ idGen?: (prefix: string) => string;
50
+ }
51
+ /**
52
+ * Run the structured-stream agent loop. Resolves the last turn's usage (the
53
+ * `done{usage}` last-write-wins, mirroring `_streamLoop`'s return), or
54
+ * `undefined`. Throws on a stream `error` event or a non-abort tool failure —
55
+ * the caller (adapter) routes that to its lifecycle-error handler, exactly as
56
+ * `_handleSend`/`_handleRetry`/`_handleEdit` catch `_streamLoop`.
57
+ */
58
+ export declare function runStreamAgent(opts: StreamRunOptions): Promise<StreamUsage | undefined>;
59
+ //# sourceMappingURL=stream-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-run.d.ts","sourceRoot":"","sources":["../../src/agent/stream-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACR,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EAGjB,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACtB,WAAW,EACd,MAAM,oBAAoB,CAAC;AAmB5B,MAAM,WAAW,gBAAgB;IAC7B,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,WAAW,EAAE,iBAAiB,CAAC;IAC/B;;;;;OAKG;IACH,aAAa,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC,CAAC;IAChG,iFAAiF;IACjF,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC;IAC5D,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,gBAAgB,GAAG,SAAS,CAAC;IAClE,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAC1C,+DAA+D;IAC/D,OAAO,EAAE,gBAAgB,CAAC;IAC1B,0EAA0E;IAC1E,MAAM,EAAE,WAAW,CAAC;IACpB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAmU7F"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * conversation/compactor.ts — adaptive budgeting + context-window assembly.
3
+ *
4
+ * Conversation history budgeting and sliding-window assembly —
5
+ * framework-free and tokenizer-free (char-count heuristic).
6
+ *
7
+ * Pattern (cf. Claude Code /context, OpenAI Agents SDK TrimmingSession):
8
+ * Budget = CONTEXT_WINDOW − systemPrompt − tools − reservedThinking
9
+ * − reservedGeneration − autocompactBuffer − safetyMargin
10
+ *
11
+ * The history budget is then split into:
12
+ * - summary (global summary, LLM-generated, ~10%)
13
+ * - ragHist (older turns retrieved by cosine similarity, ~25%)
14
+ * - window (verbatim sliding window, the rest)
15
+ *
16
+ * Drop priority on overflow:
17
+ * 1. summary (async-regenerable)
18
+ * 2. ragHist (retrievable on the next turn)
19
+ * 3. window oldest turns
20
+ * X. NEVER dropped: currentUser + lastAssistant (absolute working memory)
21
+ *
22
+ * Browser-portable: zero deps, just an estimateTokens heuristic.
23
+ */
24
+ export interface CompactionMessage {
25
+ role: 'system' | 'user' | 'assistant' | 'tool';
26
+ content: string;
27
+ }
28
+ export interface RetrievedTurn {
29
+ role: 'user' | 'assistant';
30
+ content: string;
31
+ score?: number;
32
+ }
33
+ export interface CompactionConfig {
34
+ /** Total context window of the active model, in tokens. */
35
+ contextWindow: number;
36
+ /** Reserved budget for the model's thinking/reasoning block, in tokens. */
37
+ reservedThinking: number;
38
+ /** Reserved budget for the assistant response (max_new_tokens cap). */
39
+ reservedGeneration: number;
40
+ /** Fraction of context_window kept as autocompact buffer (0..1). */
41
+ autocompactBufferPct: number;
42
+ /** Hard safety margin in tokens. */
43
+ safetyMargin: number;
44
+ /** Floor for history budget — never compact below this. */
45
+ minHistoryBudget: number;
46
+ /** Ratio of history budget allocated to the summary block. */
47
+ summaryRatio: number;
48
+ /** Hard cap for summary tokens. */
49
+ summaryMaxTokens: number;
50
+ /** Ratio of history budget allocated to the RAG-retrieved old turns. */
51
+ ragHistRatio: number;
52
+ /** Hard cap for ragHist tokens. */
53
+ ragHistMaxTokens: number;
54
+ /** Trigger summarization once history usage reaches this % of the budget. */
55
+ triggerSummaryThresholdPct: number;
56
+ /** Re-run summarization every N user turns. */
57
+ summarizeEveryNTurns: number;
58
+ /** Header prepended to the summary block injected into the model context. English
59
+ * by default — override to localise (the compactor ships no locale system). */
60
+ summaryLabel: string;
61
+ /** Header prepended to the RAG-retrieved old turns injected into the context. */
62
+ ragIntroLabel: string;
63
+ }
64
+ export interface BudgetBreakdown {
65
+ contextWindow: number;
66
+ systemPrompt: number;
67
+ tools: number;
68
+ reservedThinking: number;
69
+ reservedGeneration: number;
70
+ autocompactBuffer: number;
71
+ safetyMargin: number;
72
+ historyAvailable: number;
73
+ }
74
+ export interface BudgetResult {
75
+ historyBudget: number;
76
+ breakdown: BudgetBreakdown;
77
+ config: CompactionConfig;
78
+ }
79
+ export interface SplitBudget {
80
+ summary: number;
81
+ ragHist: number;
82
+ window: number;
83
+ }
84
+ export interface UsageBreakdown {
85
+ system: number;
86
+ summary: number;
87
+ ragHist: number;
88
+ window: number;
89
+ }
90
+ export interface DroppedBreakdown {
91
+ ragHits: number;
92
+ oldTurns: number;
93
+ summary: boolean;
94
+ }
95
+ export interface FullBreakdown extends BudgetBreakdown {
96
+ historyAllocated: SplitBudget;
97
+ historyUsed: UsageBreakdown;
98
+ totalUsed: number;
99
+ /** Free tokens left in the context window after all reservations + actual use. */
100
+ free: number;
101
+ dropped: DroppedBreakdown;
102
+ }
103
+ export interface CompactionInput {
104
+ messages: CompactionMessage[];
105
+ systemPrompt: string;
106
+ /** Tools array passed to apply_chat_template (or null/undefined when no tools). */
107
+ toolsArray?: unknown;
108
+ /** Running summary text (regenerable). */
109
+ summary?: string;
110
+ /** RAG-retrieved old turns (older than the sliding window). */
111
+ retrievedTurns?: RetrievedTurn[];
112
+ /** Partial override of the default config. */
113
+ config?: Partial<CompactionConfig>;
114
+ }
115
+ export interface CompactionResult {
116
+ compactedMessages: CompactionMessage[];
117
+ breakdown: FullBreakdown;
118
+ }
119
+ export declare const DEFAULT_COMPACTION_CONFIG: CompactionConfig;
120
+ /**
121
+ * Token heuristic (FR ~3.5 chars/tok, EN ~4 chars/tok).
122
+ * Accurate to ±10% — enough for budgeting, and it avoids `tokenizer.encode()`,
123
+ * which costs ~5ms per message × N (too slow to run on every turn).
124
+ */
125
+ export declare function estimateTokens(text: string | null | undefined): number;
126
+ /**
127
+ * Estimate tokens for a JSON-serializable structure (e.g. tools array).
128
+ */
129
+ export declare function estimateTokensJson(obj: unknown): number;
130
+ /**
131
+ * Compute the available history budget after subtracting fixed costs.
132
+ */
133
+ export declare function computeHistoryBudget(input: {
134
+ systemPrompt: string;
135
+ toolsArray?: unknown;
136
+ config?: Partial<CompactionConfig>;
137
+ }): BudgetResult;
138
+ /**
139
+ * Split history budget into summary / ragHist / window slots.
140
+ */
141
+ export declare function splitHistoryBudget(historyBudget: number, cfg?: CompactionConfig): SplitBudget;
142
+ interface AssembleParams {
143
+ messages: CompactionMessage[];
144
+ summary?: string;
145
+ retrievedTurns?: RetrievedTurn[];
146
+ windowBudget: number;
147
+ summaryBudget: number;
148
+ ragBudget: number;
149
+ systemContent?: string;
150
+ /** Context-injection headers; default to English (DEFAULT_COMPACTION_CONFIG). */
151
+ summaryLabel?: string;
152
+ ragIntroLabel?: string;
153
+ }
154
+ interface AssembleResult {
155
+ compactedMessages: CompactionMessage[];
156
+ used: UsageBreakdown;
157
+ dropped: DroppedBreakdown;
158
+ }
159
+ /**
160
+ * Assemble compacted message list given a budget and conversation state.
161
+ *
162
+ * Output order:
163
+ * [system?] → [summary system msg?] → [ragHist system msg?] → window verbatim
164
+ *
165
+ * Always keeps the last 2 non-system messages verbatim (working memory),
166
+ * regardless of windowBudget — these are the floor that can never be dropped.
167
+ */
168
+ export declare function assembleCompacted(params: AssembleParams): AssembleResult;
169
+ /**
170
+ * Compute budget + assemble in one call. The primary entry point for
171
+ * consumers (a browser request interceptor, mobile, Node tests).
172
+ */
173
+ export declare function compactConversation(input: CompactionInput): CompactionResult;
174
+ export {};
175
+ //# sourceMappingURL=compactor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compactor.d.ts","sourceRoot":"","sources":["../../src/conversation/compactor.ts"],"names":[],"mappings":"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"}