@aparte/engine 0.13.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -12
- package/dist/agent/parsers/artifact-kind.d.ts +19 -0
- package/dist/agent/parsers/artifact-kind.d.ts.map +1 -0
- package/dist/agent/stream-events.d.ts +17 -38
- package/dist/agent/stream-events.d.ts.map +1 -1
- package/dist/agent/stream-run.d.ts +18 -6
- package/dist/agent/stream-run.d.ts.map +1 -1
- package/dist/conversation/selector.d.ts +78 -0
- package/dist/conversation/selector.d.ts.map +1 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +57 -203
- package/dist/index.js.map +1 -1
- package/package.json +2 -6
- package/dist/agent/parsers/artifact-xml-state-machine.d.ts +0 -87
- package/dist/agent/parsers/artifact-xml-state-machine.d.ts.map +0 -1
- package/dist/agent/stream-events.contract.d.ts +0 -74
- package/dist/agent/stream-events.contract.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -7,29 +7,28 @@ dependencies, runs in the browser or Node.
|
|
|
7
7
|
npm install @aparte/engine @aparte/core
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
`@aparte/core` is
|
|
10
|
+
`@aparte/core` is **not a dependency** of this package — it is the other way round: core depends on the engine. Install core for the recommended path below.
|
|
11
11
|
|
|
12
12
|
```ts
|
|
13
|
-
import { runStreamAgent } from '@aparte/engine';
|
|
14
13
|
import { AparteClient } from '@aparte/core';
|
|
15
14
|
|
|
16
|
-
//
|
|
17
|
-
new AparteClient(
|
|
15
|
+
// Nothing to inject: the client runs this package's loop and renders its events.
|
|
16
|
+
new AparteClient().start();
|
|
18
17
|
```
|
|
19
18
|
|
|
20
19
|
Its core export is **`runStreamAgent`**: a DOM-free structured-stream loop that turns a
|
|
21
20
|
transport's token stream into high-level run events (text, thinking, tool calls, artifacts),
|
|
22
21
|
drives the tool-calling loop (with optional human-in-the-loop approval), and reports usage.
|
|
23
22
|
|
|
24
|
-
`@aparte/core`
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
transport and asserts identical output).
|
|
23
|
+
`@aparte/core` runs this loop by default — it used to embed a copy of it inline, and the
|
|
24
|
+
two were held equal by a parity suite; the copy is gone, and that suite now lives in core
|
|
25
|
+
with the loop's call sequences pinned as snapshots. `AparteClientOptions.streamRunner` is
|
|
26
|
+
the seam to wrap it (`(opts) => runStreamAgent({ ...opts, onHistoryAppend })` for a host
|
|
27
|
+
that owns its transcript) or to replace it with a loop of your own emitting the same events.
|
|
30
28
|
|
|
31
|
-
`@aparte/core` is
|
|
32
|
-
it;
|
|
29
|
+
`@aparte/core` is not needed here — `runStreamAgent`, the parsers and the compactor import
|
|
30
|
+
nothing from it; `createCompactionSelector` is typed structurally, so core's messages fit it
|
|
31
|
+
without core being named.
|
|
33
32
|
|
|
34
33
|
## Owning the history (prefix-cache hosts)
|
|
35
34
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map an artifact MIME type to a renderer kind — `'react'`, `'html'`, `'js'`, `'css'`,
|
|
3
|
+
* `'svg'`, `'json'`, `'markdown'`, `'csv'`, `'text'` — or `fallback` (default
|
|
4
|
+
* `'unknown'`) for anything else. Anthropic's `application/vnd.ant.*` namespace maps to
|
|
5
|
+
* its suffix; exact standard MIMEs are matched first, then a substring rescue for
|
|
6
|
+
* parameterised or vendor variants (`text/html; charset=utf-8`, `application/ld+json`).
|
|
7
|
+
*
|
|
8
|
+
* THE implementation: `@aparte/core` re-exports it under the same name. It used to
|
|
9
|
+
* live in the XML artifact state machine, which the 2026-08-28 audit's D2 removed —
|
|
10
|
+
* the core parser reads `<artifact>` tags natively — and this is the one piece of
|
|
11
|
+
* that file the built-in `create_artifact` and the artifact card still need.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* deriveArtifactKind('application/vnd.ant.react') // 'react'
|
|
15
|
+
* deriveArtifactKind('text/html; charset=utf-8') // 'html'
|
|
16
|
+
* deriveArtifactKind('font/woff2', 'text') // 'text' (fallback)
|
|
17
|
+
*/
|
|
18
|
+
export declare function deriveArtifactKind(mimeType: string, fallback?: string): string;
|
|
19
|
+
//# sourceMappingURL=artifact-kind.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-kind.d.ts","sourceRoot":"","sources":["../../../src/agent/parsers/artifact-kind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAY,GAAG,MAAM,CAqBjF"}
|
|
@@ -5,21 +5,21 @@
|
|
|
5
5
|
* `runAgent` ({@link ./agent-loop}): where `runAgent` drives a text-only
|
|
6
6
|
* provider (`chat → string`, tool calls re-parsed from text), `runStreamAgent`
|
|
7
7
|
* consumes a **structured** `AsyncIterable<StreamChatEvent>` (text / thinking /
|
|
8
|
-
* tool_use / done / error) — the
|
|
9
|
-
*
|
|
8
|
+
* tool_use / done / error) — the stream core's inline loop used to read. That loop
|
|
9
|
+
* is gone (audit 2026-08-28, D1): this is THE loop, and `AparteClient` runs it.
|
|
10
10
|
*
|
|
11
11
|
* DOM stays out of here. The loop emits high-level {@link StreamRunEvent}s in the
|
|
12
|
-
* exact order
|
|
12
|
+
* exact order the inline loop performed its `targetElement.*` calls; a thin adapter
|
|
13
13
|
* (in `@aparte/core`, where the parser and renderers live) translates each event
|
|
14
14
|
* into the imperative viewport surface. So this module — and {@link ./stream-run}
|
|
15
15
|
* — import **nothing** from `@aparte/core`: the types below structurally mirror the
|
|
16
16
|
* core types (`AparteStreamEvent`, `AparteUsage`, `AparteChatMessage`, `AparteToolCall`)
|
|
17
17
|
* so the adapter passes the real objects through with zero runtime conversion.
|
|
18
18
|
*
|
|
19
|
-
* SCOPE: text · thinking · tool_use (+ HITL approval) · done · error ·
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
19
|
+
* SCOPE: text · thinking · tool_use (+ HITL approval) · done · error · the built-in
|
|
20
|
+
* create_artifact · synthetic toolChoice bypass. Code-fence promotion and `<artifact>`
|
|
21
|
+
* tags in the text are adapter-side (they need the core parser); the raw / XML
|
|
22
|
+
* artifact modes and the multi-phase pipeline were removed (audit 2026-08-28, D2).
|
|
23
23
|
*/
|
|
24
24
|
/**
|
|
25
25
|
* Token usage. Structurally a superset-compatible mirror of `AparteUsage`: the
|
|
@@ -44,7 +44,7 @@ export interface StreamToolCall {
|
|
|
44
44
|
* `unknown` looked safer — the loop does not read tool input, it forwards it —
|
|
45
45
|
* but the seam needs assignability in BOTH directions (`transportCall` is
|
|
46
46
|
* contravariant), and `unknown` is not assignable to `Record<string, unknown>`.
|
|
47
|
-
*
|
|
47
|
+
* Core's composition compiles against it.
|
|
48
48
|
*/
|
|
49
49
|
input: Record<string, unknown>;
|
|
50
50
|
}
|
|
@@ -73,7 +73,7 @@ export type StreamChatEvent = {
|
|
|
73
73
|
* The loop forwards the inventory to the transport and reads `maxTurns` and
|
|
74
74
|
* `needsApproval` from its own lookup — it never interprets the schema. Mirrored
|
|
75
75
|
* exactly all the same, because the seam needs assignability in both directions;
|
|
76
|
-
*
|
|
76
|
+
* core's composition compiles against it.
|
|
77
77
|
*/
|
|
78
78
|
export interface StreamTool {
|
|
79
79
|
name: string;
|
|
@@ -90,9 +90,9 @@ export interface StreamTool {
|
|
|
90
90
|
* file: engine stays zero-import at runtime. Mirrored EXACTLY rather than
|
|
91
91
|
* loosened to `unknown[]`, which was the first attempt: `transportCall` is
|
|
92
92
|
* contravariant, so the message type has to be assignable to core's AND core's to
|
|
93
|
-
* it, and `unknown[]` fails the second direction.
|
|
94
|
-
*
|
|
95
|
-
* rather than a silent divergence.
|
|
93
|
+
* it, and `unknown[]` fails the second direction. Core compiles
|
|
94
|
+
* `streamRunner: runStreamAgent`, so a part added on one side and not the other is
|
|
95
|
+
* a typecheck error there rather than a silent divergence.
|
|
96
96
|
*
|
|
97
97
|
* The loop never looks inside content — it carries messages to the transport and
|
|
98
98
|
* appends results. This exists to make the seam type-check, not to be read.
|
|
@@ -125,7 +125,7 @@ export type StreamContentPart = StreamTextPart | StreamImagePart | StreamFilePar
|
|
|
125
125
|
* chain that stopped `streamRunner: runStreamAgent` from compiling.
|
|
126
126
|
*
|
|
127
127
|
* Mirrored structurally rather than imported, to keep this package zero-import at
|
|
128
|
-
* runtime;
|
|
128
|
+
* runtime; core, which depends on this package, compiles the two against each other.
|
|
129
129
|
*/
|
|
130
130
|
export interface StreamAgentMessage {
|
|
131
131
|
role: 'user' | 'assistant' | 'system' | 'tool_call' | 'tool_result';
|
|
@@ -159,7 +159,7 @@ export interface StreamAgentMessage {
|
|
|
159
159
|
* because TypeScript only excess-property-checks object literals.
|
|
160
160
|
*
|
|
161
161
|
* Types kept structural (not imported from core) so this package stays
|
|
162
|
-
* zero-import at runtime;
|
|
162
|
+
* zero-import at runtime; core's composition compiles the two against each other.
|
|
163
163
|
*/
|
|
164
164
|
export interface StreamChatRequest {
|
|
165
165
|
messages: StreamAgentMessage[];
|
|
@@ -170,7 +170,7 @@ export interface StreamChatRequest {
|
|
|
170
170
|
* un-assignable — from the opposite direction to the `messages` mismatch.
|
|
171
171
|
*/
|
|
172
172
|
modelId: string;
|
|
173
|
-
/** Per-turn hints
|
|
173
|
+
/** Per-turn hints carried through for the adapter (`artifactHint`, `prefixSegments`); the loop reads none. */
|
|
174
174
|
_meta?: Record<string, unknown>;
|
|
175
175
|
/** `'none'` makes the loop drop the tool inventory for that turn. */
|
|
176
176
|
toolChoice?: 'auto' | 'none' | {
|
|
@@ -203,11 +203,11 @@ export type StreamApprovalResolver = (call: {
|
|
|
203
203
|
instruction?: string;
|
|
204
204
|
}>;
|
|
205
205
|
/**
|
|
206
|
-
* High-level, DOM-free events isomorphic to
|
|
206
|
+
* High-level, DOM-free events isomorphic to the inline loop's `targetElement.*`
|
|
207
207
|
* call sequence. Emitted **synchronously and in order** (see {@link StreamRunEmitter})
|
|
208
208
|
* so the adapter reproduces the exact streaming update order.
|
|
209
209
|
*
|
|
210
|
-
* Mapping to
|
|
210
|
+
* Mapping to the inline loop it replaced, for the adapter:
|
|
211
211
|
* - `run-start` → updateMessage(status:'streaming') once at loop entry (the leading write before turn 1)
|
|
212
212
|
* - `turn-start` → reset the per-turn parser / thinking / streaming-segment state (no DOM); one per turn
|
|
213
213
|
* - `text-delta` → parser-driven addSegment/updateSegment, else typeName/updateLastMessage
|
|
@@ -223,8 +223,6 @@ export type StreamApprovalResolver = (call: {
|
|
|
223
223
|
* - `tool-aborted` → updateSegment('aborted') (no-handler path, timeout/abort path, or per-tool maxTurns path)
|
|
224
224
|
* - `turn-limit-exceeded` scope:'global' → addSegment(error 'MAX_TURNS_EXCEEDED');
|
|
225
225
|
* scope:'tool' → updateSegment('aborted')
|
|
226
|
-
* - `phase-advance` → addSegment({type:'pipeline-waiting'}); the loop has already
|
|
227
|
-
* pushed the phase's reply into history and bumped the phase index
|
|
228
226
|
* - `run-aborted` → dispatch `aparte-message-aborted` (from the inner-loop abort check or the outer turn-boundary abort check)
|
|
229
227
|
* - `run-done` → updateMessage(status:'completed') always + setUsage if usage
|
|
230
228
|
*/
|
|
@@ -235,27 +233,11 @@ export type StreamRunEvent = {
|
|
|
235
233
|
} | {
|
|
236
234
|
type: 'text-delta';
|
|
237
235
|
delta: string;
|
|
238
|
-
reduced?: boolean;
|
|
239
236
|
} | {
|
|
240
237
|
type: 'text-flush';
|
|
241
238
|
} | {
|
|
242
239
|
type: 'thinking-delta';
|
|
243
240
|
delta: string;
|
|
244
|
-
} | {
|
|
245
|
-
type: 'artifact-open';
|
|
246
|
-
id: string;
|
|
247
|
-
mimeType: string;
|
|
248
|
-
kind: string;
|
|
249
|
-
title: string;
|
|
250
|
-
} | {
|
|
251
|
-
type: 'artifact-chunk';
|
|
252
|
-
id: string;
|
|
253
|
-
content: string;
|
|
254
|
-
} | {
|
|
255
|
-
type: 'artifact-close';
|
|
256
|
-
id: string;
|
|
257
|
-
content: string;
|
|
258
|
-
inline: boolean;
|
|
259
241
|
} | {
|
|
260
242
|
type: 'artifact-ready';
|
|
261
243
|
id: string;
|
|
@@ -292,9 +274,6 @@ export type StreamRunEvent = {
|
|
|
292
274
|
scope: 'global' | 'tool';
|
|
293
275
|
limit: number;
|
|
294
276
|
toolCallId?: string;
|
|
295
|
-
} | {
|
|
296
|
-
type: 'phase-advance';
|
|
297
|
-
index: number;
|
|
298
277
|
} | {
|
|
299
278
|
type: 'run-aborted';
|
|
300
279
|
} | {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-events.d.ts","sourceRoot":"","sources":["../../src/agent/stream-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CAevB;AAED,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnC,CAAC;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG,cAAc,CAAC,GACvC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAE5C;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,cAAc;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAC9D,MAAM,WAAW,eAAe;IAAG,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;AACpF,MAAM,WAAW,cAAc;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE;AAC/F,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,eAAe,GAAG,cAAc,CAAC;AAElF;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,aAAa,CAAC;IACpE;;;;;;;;OAQG;IACH,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAAC;IACtC,6EAA6E;IAC7E,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;CAY1B;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,
|
|
1
|
+
{"version":3,"file":"stream-events.d.ts","sourceRoot":"","sources":["../../src/agent/stream-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* stream-run.ts — framework-free structured-stream agent loop.
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
4
|
+
* The agent loop — extracted from core's inline `_streamLoop`, which it has since
|
|
5
|
+
* replaced (audit 2026-08-28, D1): a `while(tool_use)` loop
|
|
5
6
|
* that consumes a structured `AsyncIterable<StreamChatEvent>` from a transport,
|
|
6
7
|
* runs approved tools, feeds their results back into the history, and re-calls
|
|
7
8
|
* the transport until the model stops asking for tools. It performs **no DOM
|
|
8
|
-
* work** — it emits {@link StreamRunEvent}s (in
|
|
9
|
+
* work** — it emits {@link StreamRunEvent}s (in the inline loop's exact order) that
|
|
9
10
|
* an adapter in `@aparte/core` turns into `targetElement.*` calls.
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* Code-fence promotion stays
|
|
12
|
+
* Formerly the parity target of core's inline loop; now the one loop, its call
|
|
13
|
+
* sequences pinned by core's `stream-parity` snapshots.
|
|
14
|
+
* Scope: text · thinking · tool_use (+ HITL) · done · error · the built-in
|
|
15
|
+
* create_artifact · synthetic toolChoice bypass. Code-fence promotion stays
|
|
16
|
+
* adapter-side (it needs the core parser), and so do `<artifact>` tags in the
|
|
17
|
+
* text: the core parser reads them natively. The raw / XML artifact modes and the
|
|
18
|
+
* multi-phase pipeline were removed (audit 2026-08-28, D2) — orchestration is the
|
|
19
|
+
* product's, and a mode nothing in this repository emitted was a contract
|
|
20
|
+
* maintained for nobody.
|
|
15
21
|
*/
|
|
16
22
|
import type { StreamRunEmitter, StreamChatEvent, StreamChatRequest, StreamAgentMessage, StreamToolHandler, StreamToolConfig, StreamApprovalResolver, StreamUsage } from './stream-events.js';
|
|
17
23
|
export interface StreamRunOptions {
|
|
@@ -53,6 +59,12 @@ export interface StreamRunOptions {
|
|
|
53
59
|
* `request.messages` — and mirrors these notifications into its append-only
|
|
54
60
|
* log, instead of reimplementing the loop's tool bookkeeping. Synchronous and
|
|
55
61
|
* ordered, like {@link emitter}.
|
|
62
|
+
*
|
|
63
|
+
* One rule about the envelope: a turn's `tool_call` message is reported ONCE, when
|
|
64
|
+
* its first call completes, and the calls that complete later in the same turn are
|
|
65
|
+
* already in that same object's `toolCalls` — the array is shared by reference, not
|
|
66
|
+
* copied. Hold the reference, not a snapshot, and every result you receive after it
|
|
67
|
+
* is declared by it.
|
|
56
68
|
*/
|
|
57
69
|
onHistoryAppend?: (message: StreamAgentMessage) => void;
|
|
58
70
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-run.d.ts","sourceRoot":"","sources":["../../src/agent/stream-run.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"stream-run.d.ts","sourceRoot":"","sources":["../../src/agent/stream-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EACR,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAElB,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACtB,WAAW,EACd,MAAM,oBAAoB,CAAC;AAQ5B,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,uFAAuF;IACvF,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;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACxD;;;;;OAKG;IACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC;AAeD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CA0Y7F"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* conversation/selector.ts — the budget-aware `compactionSelector` for `AparteClient`.
|
|
3
|
+
*
|
|
4
|
+
* `AparteClient.compact()` decides what to summarise through one function:
|
|
5
|
+
* `(messages) => { keep, drop }`. Its default drops everything — summarise all,
|
|
6
|
+
* replace all. This is the other half the seam was written for: the newest turns
|
|
7
|
+
* that still fit the history budget stay verbatim, the older ones are summarised.
|
|
8
|
+
*
|
|
9
|
+
* The budget is the compactor's (`computeHistoryBudget` + `splitHistoryBudget`), so
|
|
10
|
+
* the gauge a page shows, the selector `compact()` uses and the window the model
|
|
11
|
+
* declares all speak the same numbers. The budget is closed over here by the
|
|
12
|
+
* consumer — the window is theirs to know, the client's to never guess.
|
|
13
|
+
*/
|
|
14
|
+
import { type CompactionConfig } from './compactor.js';
|
|
15
|
+
/**
|
|
16
|
+
* The least a message must carry to be costed: its text, or segments with text.
|
|
17
|
+
* Structural on purpose — this package imports nothing from core — and core's
|
|
18
|
+
* `AparteMessage` satisfies it, which is what makes the selector below exactly the
|
|
19
|
+
* `compactionSelector` `AparteClient` takes.
|
|
20
|
+
*/
|
|
21
|
+
export interface CompactableMessage {
|
|
22
|
+
content?: string;
|
|
23
|
+
/**
|
|
24
|
+
* `unknown` elements, read defensively below: core's segment union includes a
|
|
25
|
+
* segment with no `content` at all, and TypeScript refuses a type with no property
|
|
26
|
+
* in common with the all-optional `{ content?: unknown }` (a "weak type"), so that
|
|
27
|
+
* tighter shape made `AparteMessage` unassignable here.
|
|
28
|
+
*/
|
|
29
|
+
segments?: ReadonlyArray<unknown>;
|
|
30
|
+
}
|
|
31
|
+
/** What `compact()` asks for: the messages kept verbatim and the ones to summarise. */
|
|
32
|
+
export interface CompactionSelection<M> {
|
|
33
|
+
keep: M[];
|
|
34
|
+
drop: M[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The selector itself — generic in the MESSAGE type, so it is assignable to core's
|
|
38
|
+
* `AparteCompactionSelector` (messages of `AparteMessage`) without importing it. The
|
|
39
|
+
* generic sits on the returned function, not on the factory: a factory-level `<M>`
|
|
40
|
+
* has no inference site at `createCompactionSelector({...})` and falls back to the
|
|
41
|
+
* bare `CompactableMessage`, which is not what the client's option type wants back.
|
|
42
|
+
*/
|
|
43
|
+
export type CompactionSelector = <M extends CompactableMessage>(messages: M[]) => CompactionSelection<M>;
|
|
44
|
+
export interface CompactionSelectorOptions {
|
|
45
|
+
/**
|
|
46
|
+
* The active model's context window, in tokens — a number, or a getter read at
|
|
47
|
+
* each call so a model change is picked up (`() => aparteGlobalConfig.getCurrentModel()?.contextWindow`).
|
|
48
|
+
* Unknown (`undefined`) means nothing is dropped: without a window there is no
|
|
49
|
+
* budget to be over.
|
|
50
|
+
*/
|
|
51
|
+
contextWindow: number | (() => number | undefined);
|
|
52
|
+
/** The system prompt the request carries, for the budget. A string or a getter. Default none. */
|
|
53
|
+
systemPrompt?: string | (() => string | null | undefined);
|
|
54
|
+
/** The tools declared to the model, for the budget. A value or a getter. Default none. */
|
|
55
|
+
tools?: unknown | (() => unknown);
|
|
56
|
+
/** Partial override of the compactor's config — reserves, ratios, floors. */
|
|
57
|
+
config?: Partial<Omit<CompactionConfig, 'contextWindow'>>;
|
|
58
|
+
/** Never summarise fewer than this many of the newest messages. Default 2 — the last exchange. */
|
|
59
|
+
minKeep?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Build the selector. Give it to the client:
|
|
63
|
+
*
|
|
64
|
+
* ```ts
|
|
65
|
+
* new AparteClient({
|
|
66
|
+
* compactionSelector: createCompactionSelector({
|
|
67
|
+
* contextWindow: () => aparteGlobalConfig.getCurrentModel()?.contextWindow,
|
|
68
|
+
* systemPrompt: () => aparteGlobalConfig.resolveSystemPrompt(),
|
|
69
|
+
* }),
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* Walks the history from the newest message: what fits the sliding window's budget
|
|
74
|
+
* is kept verbatim, the rest is dropped for summarising. When everything fits,
|
|
75
|
+
* `drop` is empty and `compact()` reports `{ skipped: true }` — nothing to do.
|
|
76
|
+
*/
|
|
77
|
+
export declare function createCompactionSelector(options: CompactionSelectorOptions): CompactionSelector;
|
|
78
|
+
//# sourceMappingURL=selector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../../src/conversation/selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAA4D,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEjH;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CACrC;AAED,uFAAuF;AACvF,MAAM,WAAW,mBAAmB,CAAC,CAAC;IAClC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,IAAI,EAAE,CAAC,EAAE,CAAC;CACb;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,SAAS,kBAAkB,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAEzG,MAAM,WAAW,yBAAyB;IACtC;;;;;OAKG;IACH,aAAa,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;IACnD,iGAAiG;IACjG,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAC1D,0FAA0F;IAC1F,KAAK,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC;IAClC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC,CAAC;IAC1D,kGAAkG;IAClG,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAeD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,kBAAkB,CAyB/F"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Zero runtime dependencies, no DOM: usable from any in-browser or Node AI-chat app.
|
|
5
5
|
* The headline export is `runStreamAgent`, the headless extraction of
|
|
6
|
-
*
|
|
7
|
-
* renders its events through `createStreamAdapter`.
|
|
8
|
-
*
|
|
6
|
+
* core's inline loop, which it has since replaced — `AparteClient` runs it by default, and core
|
|
7
|
+
* renders its events through `createStreamAdapter`. Its call sequences are pinned by
|
|
8
|
+
* core's `stream-parity` snapshots, recorded while the inline loop still ran beside it.
|
|
9
9
|
*
|
|
10
10
|
* Deliberately just the loop core drives, plus the agnostic context compactor. Opt-in
|
|
11
11
|
* *tools* (ask-user / RAG / skills / code) belong in `plugins/*`; product behaviour
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export * from './agent/stream-events.js';
|
|
15
15
|
export * from './agent/stream-run.js';
|
|
16
|
-
export {
|
|
17
|
-
export type { XmlArtifactEvent, XmlArtifactHint, XmlArtifactState } from './agent/parsers/artifact-xml-state-machine.js';
|
|
16
|
+
export { deriveArtifactKind } from './agent/parsers/artifact-kind.js';
|
|
18
17
|
export * from './conversation/compactor.js';
|
|
18
|
+
export { createCompactionSelector } from './conversation/selector.js';
|
|
19
|
+
export type { CompactionSelectorOptions, CompactableMessage, CompactionSelection, CompactionSelector } from './conversation/selector.js';
|
|
19
20
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AAMtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAGtE,cAAc,6BAA6B,CAAC;AAE5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,YAAY,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC"}
|