@earendil-works/pi-durable 1.3.0 → 1.5.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/CHANGELOG.md +227 -0
- package/README.md +287 -82
- package/dist/codemode/codemode.d.ts +4 -4
- package/dist/codemode/codemode.d.ts.map +1 -1
- package/dist/codemode/codemode.js +21 -16
- package/dist/codemode/codemode.js.map +1 -1
- package/dist/codemode/models.d.ts.map +1 -1
- package/dist/codemode/models.js +6 -4
- package/dist/codemode/models.js.map +1 -1
- package/dist/documents.d.ts +1 -1
- package/dist/documents.d.ts.map +1 -1
- package/dist/documents.js.map +1 -1
- package/dist/env/index.d.ts +12 -10
- package/dist/env/index.d.ts.map +1 -1
- package/dist/env/index.js.map +1 -1
- package/dist/env/node-watch.d.ts +3 -3
- package/dist/env/node-watch.d.ts.map +1 -1
- package/dist/env/node-watch.js +18 -16
- package/dist/env/node-watch.js.map +1 -1
- package/dist/env/node.d.ts +2 -2
- package/dist/env/node.d.ts.map +1 -1
- package/dist/env/node.js +12 -4
- package/dist/env/node.js.map +1 -1
- package/dist/errors.d.ts +18 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +26 -3
- package/dist/errors.js.map +1 -1
- package/dist/harness/agent.d.ts +13 -2
- package/dist/harness/agent.d.ts.map +1 -1
- package/dist/harness/agent.js +48 -6
- package/dist/harness/agent.js.map +1 -1
- package/dist/harness/compaction.d.ts +3 -1
- package/dist/harness/compaction.d.ts.map +1 -1
- package/dist/harness/compaction.js +38 -6
- package/dist/harness/compaction.js.map +1 -1
- package/dist/harness/context.d.ts +23 -7
- package/dist/harness/context.d.ts.map +1 -1
- package/dist/harness/context.js +71 -25
- package/dist/harness/context.js.map +1 -1
- package/dist/harness/define.d.ts +7 -3
- package/dist/harness/define.d.ts.map +1 -1
- package/dist/harness/define.js +4 -0
- package/dist/harness/define.js.map +1 -1
- package/dist/harness/generation.d.ts +38 -5
- package/dist/harness/generation.d.ts.map +1 -1
- package/dist/harness/generation.js +497 -108
- package/dist/harness/generation.js.map +1 -1
- package/dist/harness/harness.d.ts +7 -2
- package/dist/harness/harness.d.ts.map +1 -1
- package/dist/harness/harness.js +147 -57
- package/dist/harness/harness.js.map +1 -1
- package/dist/harness/inbox.d.ts +7 -3
- package/dist/harness/inbox.d.ts.map +1 -1
- package/dist/harness/inbox.js +7 -4
- package/dist/harness/inbox.js.map +1 -1
- package/dist/harness/json.d.ts +20 -4
- package/dist/harness/json.d.ts.map +1 -1
- package/dist/harness/json.js +23 -5
- package/dist/harness/json.js.map +1 -1
- package/dist/harness/live.d.ts +122 -16
- package/dist/harness/live.d.ts.map +1 -1
- package/dist/harness/live.js +93 -12
- package/dist/harness/live.js.map +1 -1
- package/dist/harness/partial-changes.d.ts +54 -0
- package/dist/harness/partial-changes.d.ts.map +1 -0
- package/dist/harness/partial-changes.js +162 -0
- package/dist/harness/partial-changes.js.map +1 -0
- package/dist/harness/prompt.d.ts +1 -1
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +1 -1
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/registry-reader.d.ts +11 -0
- package/dist/harness/registry-reader.d.ts.map +1 -0
- package/dist/harness/registry-reader.js +25 -0
- package/dist/harness/registry-reader.js.map +1 -0
- package/dist/harness/scheduler.d.ts +86 -14
- package/dist/harness/scheduler.d.ts.map +1 -1
- package/dist/harness/scheduler.js +1459 -369
- package/dist/harness/scheduler.js.map +1 -1
- package/dist/harness/submissions.d.ts +23 -11
- package/dist/harness/submissions.d.ts.map +1 -1
- package/dist/harness/submissions.js +104 -36
- package/dist/harness/submissions.js.map +1 -1
- package/dist/harness/task-graph.d.ts +28 -8
- package/dist/harness/task-graph.d.ts.map +1 -1
- package/dist/harness/task-graph.js +85 -36
- package/dist/harness/task-graph.js.map +1 -1
- package/dist/harness/telemetry.d.ts +307 -0
- package/dist/harness/telemetry.d.ts.map +1 -0
- package/dist/harness/telemetry.js +136 -0
- package/dist/harness/telemetry.js.map +1 -0
- package/dist/harness/tool.d.ts +2 -0
- package/dist/harness/tool.d.ts.map +1 -1
- package/dist/harness/tool.js +223 -61
- package/dist/harness/tool.js.map +1 -1
- package/dist/harness/transcript.d.ts +72 -0
- package/dist/harness/transcript.d.ts.map +1 -0
- package/dist/harness/transcript.js +264 -0
- package/dist/harness/transcript.js.map +1 -0
- package/dist/harness/types.d.ts +302 -48
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/util.d.ts +7 -1
- package/dist/harness/util.d.ts.map +1 -1
- package/dist/harness/util.js +13 -0
- package/dist/harness/util.js.map +1 -1
- package/dist/harness/view.d.ts +43 -22
- package/dist/harness/view.d.ts.map +1 -1
- package/dist/harness/view.js +130 -71
- package/dist/harness/view.js.map +1 -1
- package/dist/index.d.ts +13 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/search.d.ts +19 -3
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +107 -44
- package/dist/search.js.map +1 -1
- package/dist/session/cached-storage.d.ts +71 -0
- package/dist/session/cached-storage.d.ts.map +1 -0
- package/dist/session/cached-storage.js +269 -0
- package/dist/session/cached-storage.js.map +1 -0
- package/dist/session/conversation-tails.d.ts +33 -0
- package/dist/session/conversation-tails.d.ts.map +1 -0
- package/dist/session/conversation-tails.js +101 -0
- package/dist/session/conversation-tails.js.map +1 -0
- package/dist/session/keys.d.ts +68 -0
- package/dist/session/keys.d.ts.map +1 -0
- package/dist/session/keys.js +161 -0
- package/dist/session/keys.js.map +1 -0
- package/dist/session/session.d.ts +181 -29
- package/dist/session/session.d.ts.map +1 -1
- package/dist/session/session.js +1073 -183
- package/dist/session/session.js.map +1 -1
- package/dist/session/transaction.d.ts +86 -4
- package/dist/session/transaction.d.ts.map +1 -1
- package/dist/session/transaction.js +250 -38
- package/dist/session/transaction.js.map +1 -1
- package/dist/session/writer.d.ts +74 -0
- package/dist/session/writer.d.ts.map +1 -0
- package/dist/session/writer.js +294 -0
- package/dist/session/writer.js.map +1 -0
- package/dist/storage/indexeddb.d.ts +68 -0
- package/dist/storage/indexeddb.d.ts.map +1 -0
- package/dist/storage/indexeddb.js +881 -0
- package/dist/storage/indexeddb.js.map +1 -0
- package/dist/storage/jsonl/storage.d.ts +30 -2
- package/dist/storage/jsonl/storage.d.ts.map +1 -1
- package/dist/storage/jsonl/storage.js +88 -24
- package/dist/storage/jsonl/storage.js.map +1 -1
- package/dist/storage/memory.d.ts +7 -2
- package/dist/storage/memory.d.ts.map +1 -1
- package/dist/storage/memory.js +29 -3
- package/dist/storage/memory.js.map +1 -1
- package/dist/storage/sqlite/cloudflare.d.ts +2 -51
- package/dist/storage/sqlite/cloudflare.d.ts.map +1 -1
- package/dist/storage/sqlite/cloudflare.js +2 -133
- package/dist/storage/sqlite/cloudflare.js.map +1 -1
- package/dist/storage/sqlite/database.d.ts +1 -36
- package/dist/storage/sqlite/database.d.ts.map +1 -1
- package/dist/storage/sqlite/database.js.map +1 -1
- package/dist/storage/sqlite/index.d.ts +1 -1
- package/dist/storage/sqlite/index.d.ts.map +1 -1
- package/dist/storage/sqlite/index.js.map +1 -1
- package/dist/storage/sqlite/migrations.d.ts +2 -5
- package/dist/storage/sqlite/migrations.d.ts.map +1 -1
- package/dist/storage/sqlite/migrations.js +28 -28
- package/dist/storage/sqlite/migrations.js.map +1 -1
- package/dist/storage/sqlite/node.d.ts +2 -37
- package/dist/storage/sqlite/node.d.ts.map +1 -1
- package/dist/storage/sqlite/node.js +3 -174
- package/dist/storage/sqlite/node.js.map +1 -1
- package/dist/storage/sqlite/schema.d.ts +1 -3
- package/dist/storage/sqlite/schema.d.ts.map +1 -1
- package/dist/storage/sqlite/schema.js +2 -9
- package/dist/storage/sqlite/schema.js.map +1 -1
- package/dist/storage/sqlite/storage.d.ts +15 -3
- package/dist/storage/sqlite/storage.d.ts.map +1 -1
- package/dist/storage/sqlite/storage.js +110 -36
- package/dist/storage/sqlite/storage.js.map +1 -1
- package/dist/storage/store/commit.d.ts +33 -0
- package/dist/storage/store/commit.d.ts.map +1 -0
- package/dist/storage/store/commit.js +286 -0
- package/dist/storage/store/commit.js.map +1 -0
- package/dist/storage/store/documents.d.ts +43 -0
- package/dist/storage/store/documents.d.ts.map +1 -0
- package/dist/storage/store/documents.js +102 -0
- package/dist/storage/store/documents.js.map +1 -0
- package/dist/storage/store/index.d.ts +2 -0
- package/dist/storage/store/index.d.ts.map +1 -0
- package/dist/storage/store/index.js +2 -0
- package/dist/storage/store/index.js.map +1 -0
- package/dist/storage/store/queries.d.ts +49 -0
- package/dist/storage/store/queries.d.ts.map +1 -0
- package/dist/storage/store/queries.js +93 -0
- package/dist/storage/store/queries.js.map +1 -0
- package/dist/storage/store/storage.d.ts +59 -0
- package/dist/storage/store/storage.d.ts.map +1 -0
- package/dist/storage/store/storage.js +438 -0
- package/dist/storage/store/storage.js.map +1 -0
- package/dist/storage/store/tables.d.ts +54 -0
- package/dist/storage/store/tables.d.ts.map +1 -0
- package/dist/storage/store/tables.js +108 -0
- package/dist/storage/store/tables.js.map +1 -0
- package/dist/testing/commit-writes.d.ts +5 -0
- package/dist/testing/commit-writes.d.ts.map +1 -0
- package/dist/testing/commit-writes.js +12 -0
- package/dist/testing/commit-writes.js.map +1 -0
- package/dist/testing/env-conformance.js +7 -7
- package/dist/testing/env-conformance.js.map +1 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/storage-benchmark.d.ts.map +1 -1
- package/dist/testing/storage-benchmark.js +18 -17
- package/dist/testing/storage-benchmark.js.map +1 -1
- package/dist/testing/storage-conformance.d.ts.map +1 -1
- package/dist/testing/storage-conformance.js +369 -67
- package/dist/testing/storage-conformance.js.map +1 -1
- package/dist/timers.d.ts +21 -0
- package/dist/timers.d.ts.map +1 -0
- package/dist/timers.js +72 -0
- package/dist/timers.js.map +1 -0
- package/dist/tool-search/tool-search.d.ts +6 -12
- package/dist/tool-search/tool-search.d.ts.map +1 -1
- package/dist/tool-search/tool-search.js +7 -7
- package/dist/tool-search/tool-search.js.map +1 -1
- package/dist/tools/bash.d.ts +12 -12
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +16 -15
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts +7 -7
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +9 -9
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/index.d.ts +32 -32
- package/dist/tools/read.d.ts +6 -6
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +19 -8
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/write.d.ts +4 -4
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +5 -5
- package/dist/tools/write.js.map +1 -1
- package/dist/types.d.ts +331 -64
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +27 -10
- package/dist/harness/events.d.ts +0 -186
- package/dist/harness/events.d.ts.map +0 -1
- package/dist/harness/events.js +0 -373
- package/dist/harness/events.js.map +0 -1
- package/dist/session/observation.d.ts +0 -42
- package/dist/session/observation.d.ts.map +0 -1
- package/dist/session/observation.js +0 -281
- package/dist/session/observation.js.map +0 -1
package/dist/harness/view.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Watch, } from "@earendil-works/chord";
|
|
2
2
|
import { withoutAbortSignal } from "@earendil-works/chord/context";
|
|
3
3
|
import { applyImmutable } from "@earendil-works/chord/delta";
|
|
4
|
-
import {
|
|
5
|
-
import { contained } from "../session/session.js";
|
|
4
|
+
import { idFromNumber } from "../ids.js";
|
|
5
|
+
import { closeEndOf, closeEnds, contained, guardObserver, observation, } from "../session/session.js";
|
|
6
6
|
import { AgentDoc } from "./agent.js";
|
|
7
|
-
import { activeEntries, captureContextBounds } from "./context.js";
|
|
8
7
|
import { InboxDoc } from "./inbox.js";
|
|
9
8
|
import { LiveDoc } from "./live.js";
|
|
10
9
|
import { ProviderDoc } from "./provider.js";
|
|
11
10
|
import { UsageDoc } from "./usage.js";
|
|
12
11
|
import { closedError } from "./util.js";
|
|
12
|
+
/** Default `ConversationWindow.min`. */
|
|
13
|
+
const DEFAULT_WINDOW_MIN = 50;
|
|
13
14
|
const MOUNTED = [
|
|
14
15
|
AgentDoc,
|
|
15
16
|
LiveDoc,
|
|
@@ -18,6 +19,7 @@ const MOUNTED = [
|
|
|
18
19
|
UsageDoc,
|
|
19
20
|
];
|
|
20
21
|
const MOUNTED_KINDS = new Set(MOUNTED.map((token) => token.definition.kind));
|
|
22
|
+
const SCAN_PAGE_SIZE = 256;
|
|
21
23
|
const VIEWS = new WeakMap();
|
|
22
24
|
/** The view mounts of a Harness, for adapters built on them. */
|
|
23
25
|
export function conversationViews(harness) {
|
|
@@ -26,28 +28,43 @@ export function conversationViews(harness) {
|
|
|
26
28
|
throw new Error("Not a Harness");
|
|
27
29
|
return views;
|
|
28
30
|
}
|
|
31
|
+
/** `window` with its defaults; throws a `RangeError` for bounds that are not integers or `max` below `min`. */
|
|
32
|
+
function resolveWindow(window) {
|
|
33
|
+
const min = window?.min ?? DEFAULT_WINDOW_MIN;
|
|
34
|
+
if (!Number.isSafeInteger(min) || min < 1)
|
|
35
|
+
throw new RangeError(`Window min must be an integer >= 1, got ${min}`);
|
|
36
|
+
const max = window?.max ?? 2 * min;
|
|
37
|
+
if (!Number.isSafeInteger(max) || max < min) {
|
|
38
|
+
throw new RangeError(`Window max must be an integer >= min (${min}), got ${max}`);
|
|
39
|
+
}
|
|
40
|
+
const from = window?.from;
|
|
41
|
+
if (from !== undefined && !Number.isSafeInteger(from)) {
|
|
42
|
+
throw new RangeError(`Window from must be an entry ID, got ${from}`);
|
|
43
|
+
}
|
|
44
|
+
return { from, min, max };
|
|
45
|
+
}
|
|
29
46
|
/**
|
|
30
47
|
* The Harness's conversation view mounts: at most one per conversation, built on the Session line by its first
|
|
31
|
-
* observer and dropped with its last. Each mount advances from the Session's
|
|
48
|
+
* observer and dropped with its last. Each mount advances from the Session's commits as memory adopts them, deferred ones
|
|
49
|
+
* (`CommitPersistence`) before they are stored, and hands each observer the next revision of its own window.
|
|
32
50
|
*/
|
|
33
51
|
export class ConversationViews {
|
|
34
52
|
#session;
|
|
35
|
-
#storage;
|
|
36
53
|
#mounts = new Map();
|
|
37
54
|
#closed = false;
|
|
38
|
-
constructor(session
|
|
55
|
+
constructor(session) {
|
|
39
56
|
this.#session = session;
|
|
40
|
-
this.#storage = storage;
|
|
41
57
|
VIEWS.set(session, this);
|
|
42
|
-
session.
|
|
58
|
+
session.followCommits((publication, context) => {
|
|
43
59
|
for (const [id, mount] of this.#mounts)
|
|
44
60
|
advance(id, mount, publication, context, (error) => this.report(error));
|
|
45
61
|
});
|
|
46
62
|
session.subscribeClose(() => {
|
|
47
63
|
this.#closed = true;
|
|
64
|
+
const ends = closeEnds(this.#session.failure);
|
|
48
65
|
for (const mount of this.#mounts.values())
|
|
49
|
-
for (const
|
|
50
|
-
contained(() => observer.
|
|
66
|
+
for (const windowed of [...mount.observers]) {
|
|
67
|
+
contained(() => windowed.observer.end(closeEndOf(windowed.observer, ends)), (error) => this.report(error));
|
|
51
68
|
}
|
|
52
69
|
this.#mounts.clear();
|
|
53
70
|
});
|
|
@@ -56,58 +73,68 @@ export class ConversationViews {
|
|
|
56
73
|
report(error) {
|
|
57
74
|
this.#session.report(error);
|
|
58
75
|
}
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Attach a synchronous observer of the view (`Harness.observeConversation()`), behind `guardObserver()`; `context`
|
|
78
|
+
* governs only the attachment.
|
|
79
|
+
*/
|
|
80
|
+
async observe(id, observer, context, window) {
|
|
81
|
+
let value;
|
|
82
|
+
const attached = await this.attach(id, window, (current, release) => {
|
|
83
|
+
value = current;
|
|
84
|
+
return guardObserver(observer, release, (error) => this.report(error));
|
|
85
|
+
}, context);
|
|
86
|
+
const signal = context.abortSignal;
|
|
87
|
+
if (signal?.aborted) {
|
|
88
|
+
attached.detach();
|
|
89
|
+
throw signal.reason;
|
|
68
90
|
}
|
|
91
|
+
return observation(value, attached.observer);
|
|
69
92
|
}
|
|
70
|
-
/** A serialized
|
|
71
|
-
async watch(id, context) {
|
|
72
|
-
const { observer } = await this.attach(id, (value, release) => new
|
|
93
|
+
/** A serialized watch of the view, an observer of its mount; aborting `context` ends it `aborted`. */
|
|
94
|
+
async watch(id, context, window) {
|
|
95
|
+
const { observer } = await this.attach(id, window, (value, release) => new Watch(value, release, (error) => this.#session.report(error)), context);
|
|
73
96
|
const signal = context.abortSignal;
|
|
74
97
|
if (signal?.aborted) {
|
|
75
|
-
observer.
|
|
98
|
+
observer.abort();
|
|
76
99
|
throw signal.reason;
|
|
77
100
|
}
|
|
78
101
|
if (signal !== undefined)
|
|
79
|
-
observer.
|
|
102
|
+
observer.observeAbort(signal);
|
|
80
103
|
return observer;
|
|
81
104
|
}
|
|
82
105
|
/**
|
|
83
|
-
* Register an observer created from
|
|
84
|
-
* publication and nothing earlier. `
|
|
85
|
-
* the mount with its last observer.
|
|
106
|
+
* Register an observer created from its window's first revision, atomically on the Session line: it sees every later
|
|
107
|
+
* publication and nothing earlier. `release` drops it, and the mount with its last observer.
|
|
86
108
|
*/
|
|
87
|
-
attach(id, create, context) {
|
|
88
|
-
|
|
89
|
-
|
|
109
|
+
async attach(id, window, create, context) {
|
|
110
|
+
const bounds = resolveWindow(window);
|
|
111
|
+
return this.#session.readOnLine(async (storage) => {
|
|
112
|
+
const mount = this.#mounts.get(id) ?? (await this.#build(storage, id, context));
|
|
113
|
+
const { entries, before } = await loadWindow(storage, id, bounds, context);
|
|
114
|
+
const value = view(mount.conversation, entries, before, mount.docs);
|
|
115
|
+
let windowed;
|
|
90
116
|
const detach = () => {
|
|
91
|
-
|
|
117
|
+
if (windowed !== undefined)
|
|
118
|
+
mount.observers.delete(windowed);
|
|
92
119
|
if (mount.observers.size === 0 && this.#mounts.get(id) === mount)
|
|
93
120
|
this.#mounts.delete(id);
|
|
94
121
|
};
|
|
95
|
-
const observer =
|
|
122
|
+
const observer = create(value, detach);
|
|
96
123
|
// Close or cancellation may begin while the mount hydrates; register nothing then.
|
|
97
124
|
if (this.#closed)
|
|
98
125
|
throw closedError(this.#session);
|
|
99
126
|
context.abortSignal?.throwIfAborted();
|
|
127
|
+
windowed = { min: bounds.min, max: bounds.max, value, observer };
|
|
100
128
|
this.#mounts.set(id, mount);
|
|
101
|
-
mount.observers.add(
|
|
129
|
+
mount.observers.add(windowed);
|
|
102
130
|
return { observer, detach };
|
|
103
131
|
});
|
|
104
132
|
}
|
|
105
|
-
|
|
106
|
-
|
|
133
|
+
/** Hydrate a mount on the line, through the line's `storage`. */
|
|
134
|
+
async #build(storage, id, context) {
|
|
135
|
+
const conversation = await storage.conversation(id, context);
|
|
107
136
|
if (conversation === undefined)
|
|
108
137
|
throw new Error(`Conversation ${id} does not exist`);
|
|
109
|
-
const bounds = await captureContextBounds(this.#storage, id, context);
|
|
110
|
-
const entries = await activeEntries(this.#storage, id, bounds, context);
|
|
111
138
|
const docs = {};
|
|
112
139
|
const incarnations = new Map();
|
|
113
140
|
for (const token of MOUNTED) {
|
|
@@ -117,34 +144,54 @@ export class ConversationViews {
|
|
|
117
144
|
docs[token.definition.kind] = loaded.value;
|
|
118
145
|
incarnations.set(token.definition.kind, { id: loaded.record.id, version: loaded.version });
|
|
119
146
|
}
|
|
120
|
-
return {
|
|
147
|
+
return { conversation, docs, incarnations, observers: new Set() };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** A view revision; `before` is a key only when set. */
|
|
151
|
+
function view(conversation, entries, before, docs) {
|
|
152
|
+
return before === undefined ? { conversation, entries, docs } : { conversation, entries, before, docs };
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* A new observer's window, read on the Session line with bounded scans: the entries from `from` when at most `max` are
|
|
156
|
+
* at or after it, otherwise the newest `min`, and the entry before them.
|
|
157
|
+
*/
|
|
158
|
+
async function loadWindow(storage, conversationId, bounds, context) {
|
|
159
|
+
const { from, min, max } = bounds;
|
|
160
|
+
if (from !== undefined) {
|
|
161
|
+
const since = await scanUpTo(storage, { conversationId, minEntryId: from, order: "ascending" }, max + 1, context);
|
|
162
|
+
if (since.length <= max) {
|
|
163
|
+
const query = { conversationId, maxEntryId: idFromNumber(from - 1) };
|
|
164
|
+
const previous = (await storage.scanEntries(query, 1, undefined, context)).items[0];
|
|
165
|
+
return { entries: since, before: previous?.id };
|
|
166
|
+
}
|
|
121
167
|
}
|
|
168
|
+
const newest = await scanUpTo(storage, { conversationId }, min + 1, context);
|
|
169
|
+
const before = newest.length > min ? newest.pop().id : undefined;
|
|
170
|
+
return { entries: newest.reverse(), before };
|
|
171
|
+
}
|
|
172
|
+
/** Up to `limit` entries of `query`, following cursors past short pages. */
|
|
173
|
+
async function scanUpTo(storage, query, limit, context) {
|
|
174
|
+
const entries = [];
|
|
175
|
+
let cursor;
|
|
176
|
+
do {
|
|
177
|
+
const page = await storage.scanEntries(query, Math.min(SCAN_PAGE_SIZE, limit - entries.length), cursor, context);
|
|
178
|
+
entries.push(...page.items);
|
|
179
|
+
cursor = page.next;
|
|
180
|
+
} while (cursor !== undefined && entries.length < limit);
|
|
181
|
+
return entries;
|
|
122
182
|
}
|
|
123
183
|
/**
|
|
124
|
-
* Derive the mount's operations from one publication
|
|
125
|
-
* throws is reported through `report`, and the others still get
|
|
184
|
+
* Derive the mount's operations from one publication and hand each observer the next revision of its window; one that
|
|
185
|
+
* throws is reported through `report`, and the others still get theirs. Documents are applied once and shared; each
|
|
186
|
+
* window takes the appended entries and, past its `max`, drops its oldest down to its `min` in one splice.
|
|
126
187
|
*/
|
|
127
188
|
function advance(id, mount, publication, context, report) {
|
|
128
189
|
const docOps = [];
|
|
129
|
-
const entryOps = [];
|
|
130
|
-
let entries = mount.value.entries;
|
|
131
190
|
// Entry writes are published in ID order.
|
|
191
|
+
const appended = [];
|
|
132
192
|
for (const change of publication.changes) {
|
|
133
193
|
if (change.type === "entry" && change.value.conversationId === id) {
|
|
134
|
-
|
|
135
|
-
const value = entry;
|
|
136
|
-
if (entry.head === undefined) {
|
|
137
|
-
entryOps.push(["p", ["entries"], entries.length, 0, [value]]);
|
|
138
|
-
entries = [...entries, entry];
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
// A head marker keeps the non-head entries from its head, which are always a suffix, and goes in front.
|
|
142
|
-
const target = entry.head;
|
|
143
|
-
let kept = entries.findIndex((candidate) => candidate.head === undefined && candidate.id >= target);
|
|
144
|
-
if (kept < 0)
|
|
145
|
-
kept = entries.length;
|
|
146
|
-
entryOps.push(["p", ["entries"], 0, kept, [value]]);
|
|
147
|
-
entries = [entry, ...entries.slice(kept)];
|
|
194
|
+
appended.push(change.value);
|
|
148
195
|
continue;
|
|
149
196
|
}
|
|
150
197
|
if (change.type !== "document" || change.conversationId !== id)
|
|
@@ -153,11 +200,11 @@ function advance(id, mount, publication, context, report) {
|
|
|
153
200
|
if (!MOUNTED_KINDS.has(kind) || change.record.key !== undefined)
|
|
154
201
|
continue;
|
|
155
202
|
const path = ["docs", kind];
|
|
156
|
-
const mounted = mount.
|
|
157
|
-
if (change.
|
|
203
|
+
const mounted = mount.incarnations.get(kind);
|
|
204
|
+
if (change.kind === "retire") {
|
|
158
205
|
if (mounted?.id !== change.record.id)
|
|
159
206
|
continue;
|
|
160
|
-
mount.
|
|
207
|
+
mount.incarnations.delete(kind);
|
|
161
208
|
docOps.push(["d", path]);
|
|
162
209
|
}
|
|
163
210
|
else if (mounted?.id === change.record.id && mounted.version === change.version) {
|
|
@@ -165,22 +212,34 @@ function advance(id, mount, publication, context, report) {
|
|
|
165
212
|
docOps.push(prefixed(op, path));
|
|
166
213
|
}
|
|
167
214
|
else {
|
|
168
|
-
mount.
|
|
215
|
+
mount.incarnations.set(kind, { id: change.record.id, version: change.version });
|
|
169
216
|
docOps.push(["s", path, change.value]);
|
|
170
217
|
}
|
|
171
218
|
}
|
|
172
|
-
|
|
173
|
-
|
|
219
|
+
if (docOps.length === 0 && appended.length === 0)
|
|
220
|
+
return;
|
|
221
|
+
if (docOps.length > 0)
|
|
222
|
+
mount.docs = applyImmutable({ docs: mount.docs }, docOps).docs;
|
|
174
223
|
const frameContext = withoutAbortSignal(context);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
224
|
+
const inserted = appended;
|
|
225
|
+
for (const windowed of [...mount.observers]) {
|
|
226
|
+
const previous = windowed.value;
|
|
227
|
+
let entries = previous.entries;
|
|
228
|
+
let before = previous.before;
|
|
229
|
+
let ops = docOps;
|
|
230
|
+
if (appended.length > 0) {
|
|
231
|
+
ops = [...docOps, ["p", ["entries"], entries.length, 0, inserted]];
|
|
232
|
+
entries = entries.concat(appended);
|
|
233
|
+
if (entries.length > windowed.max) {
|
|
234
|
+
const drop = entries.length - windowed.min;
|
|
235
|
+
before = entries[drop - 1].id;
|
|
236
|
+
entries = entries.slice(drop);
|
|
237
|
+
ops.push(["p", ["entries"], 0, drop, []], ["s", ["before"], before]);
|
|
238
|
+
}
|
|
180
239
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
contained(() => observer.
|
|
240
|
+
windowed.value = view(mount.conversation, entries, before, mount.docs);
|
|
241
|
+
const call = { kind: "value", value: windowed.value, ops, retired: false };
|
|
242
|
+
contained(() => windowed.observer.advance(call, frameContext), report);
|
|
184
243
|
}
|
|
185
244
|
}
|
|
186
245
|
/** `op` moved under `prefix`; a root replacement becomes a set of the prefix. */
|
package/dist/harness/view.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/harness/view.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AttachedReplicatedState, type Context, type JsonValue, replicatedState } from \"@earendil-works/chord\";\nimport { withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport { applyImmutable, type NonEmptyPath, type Op, type Path } from \"@earendil-works/chord/delta\";\nimport { CommittedStateSource, CommittedWatch } from \"../session/observation.ts\";\nimport { contained, type SessionImpl } from \"../session/session.ts\";\nimport type {\n\tCommitPublication,\n\tConversationDocToken,\n\tConversationId,\n\tConversationRecord,\n\tDocumentId,\n\tEntryRecord,\n\tJsonObject,\n\tStorage,\n\tWatchHandle,\n} from \"../types.ts\";\nimport { AgentDoc } from \"./agent.ts\";\nimport { activeEntries, captureContextBounds } from \"./context.ts\";\nimport { InboxDoc } from \"./inbox.ts\";\nimport { LiveDoc } from \"./live.ts\";\nimport { ProviderDoc } from \"./provider.ts\";\nimport { UsageDoc } from \"./usage.ts\";\nimport { closedError } from \"./util.ts\";\n\n/** Structural mount of one conversation's active transcript and built-in documents (spec §9.3). */\nexport type ConversationView = {\n\treadonly conversation: ConversationRecord;\n\t/** Raw active entries, as `ContextView.entries`: the head marker, then the non-head entries from its head. */\n\treadonly entries: readonly EntryRecord[];\n\t/** Built-in conversation documents keyed by kind; absent documents are absent. */\n\treadonly docs: Readonly<Record<string, JsonObject>>;\n};\n\n/** Receives each next revision of a mount, and the Session's close. */\nexport type ViewObserver = {\n\tadvance?(value: ConversationView, ops: readonly Op[], context: Context): void;\n\t/** Every publication, after the mount took it; `ops` are the mount's, possibly none. */\n\tpublication?(\n\t\tbefore: ConversationView,\n\t\tafter: ConversationView,\n\t\tops: readonly Op[],\n\t\tpublication: CommitPublication,\n\t\tcontext: Context,\n\t): void;\n\tcloseSession(failure: { readonly error: unknown } | undefined): void;\n};\n\nconst MOUNTED = [\n\tAgentDoc,\n\tLiveDoc,\n\tInboxDoc,\n\tProviderDoc,\n\tUsageDoc,\n] as unknown as readonly ConversationDocToken<JsonObject>[];\nconst MOUNTED_KINDS: ReadonlySet<string> = new Set(MOUNTED.map((token) => token.definition.kind));\n\n/** One conversation's mount: its current revision, the document incarnations it shows, and its observers. */\ntype Mount = {\n\tvalue: ConversationView;\n\t/** Mounted incarnation and definition version per kind; another incarnation or version is set whole. */\n\treadonly docs: Map<string, { id: DocumentId; version: number }>;\n\treadonly observers: Set<ViewObserver>;\n};\n\nconst VIEWS = new WeakMap<object, ConversationViews>();\n\n/** The view mounts of a Harness, for adapters built on them. */\nexport function conversationViews(harness: object): ConversationViews {\n\tconst views = VIEWS.get(harness);\n\tif (views === undefined) throw new Error(\"Not a Harness\");\n\treturn views;\n}\n\n/**\n * The Harness's conversation view mounts: at most one per conversation, built on the Session line by its first\n * observer and dropped with its last. Each mount advances from the Session's commit publications, which are durable.\n */\nexport class ConversationViews {\n\treadonly #session: SessionImpl;\n\treadonly #storage: Storage;\n\treadonly #mounts = new Map<ConversationId, Mount>();\n\t#closed = false;\n\n\tconstructor(session: SessionImpl, storage: Storage) {\n\t\tthis.#session = session;\n\t\tthis.#storage = storage;\n\t\tVIEWS.set(session, this);\n\t\tsession.observeCommits((publication, context) => {\n\t\t\tfor (const [id, mount] of this.#mounts)\n\t\t\t\tadvance(id, mount, publication, context, (error) => this.report(error));\n\t\t});\n\t\tsession.subscribeClose(() => {\n\t\t\tthis.#closed = true;\n\t\t\tfor (const mount of this.#mounts.values())\n\t\t\t\tfor (const observer of [...mount.observers]) {\n\t\t\t\t\tcontained(\n\t\t\t\t\t\t() => observer.closeSession(this.#session.failure),\n\t\t\t\t\t\t(error) => this.report(error),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\tthis.#mounts.clear();\n\t\t});\n\t}\n\n\t/** Report an observer's listener error through the Harness. */\n\treport(error: unknown): void {\n\t\tthis.#session.report(error);\n\t}\n\n\t/** A disposable read-only Chord state of the view. */\n\tasync state(id: ConversationId, context: Context): Promise<AttachedReplicatedState<ConversationView>> {\n\t\tconst { observer, detach } = await this.attach(\n\t\t\tid,\n\t\t\t(value, release) => new CommittedStateSource<ConversationView>(value, release),\n\t\t\tcontext,\n\t\t);\n\t\ttry {\n\t\t\treturn replicatedState(observer, { onError: (error) => this.#session.report(error) });\n\t\t} catch (error) {\n\t\t\tdetach();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/** A serialized exact-frame watch of the view; cancelling `context` stops it. */\n\tasync watch(id: ConversationId, context: Context): Promise<WatchHandle<ConversationView>> {\n\t\tconst { observer } = await this.attach(\n\t\t\tid,\n\t\t\t(value, release) =>\n\t\t\t\tnew CommittedWatch<ConversationView>(value, release, (error) => this.#session.report(error)),\n\t\t\tcontext,\n\t\t);\n\t\tconst signal = context.abortSignal;\n\t\tif (signal?.aborted) {\n\t\t\tobserver.cancel();\n\t\t\tthrow signal.reason;\n\t\t}\n\t\tif (signal !== undefined) observer.observeCancellation(signal);\n\t\treturn observer;\n\t}\n\n\t/**\n\t * Register an observer created from the current revision, atomically on the Session line: it sees every later\n\t * publication and nothing earlier. `create` may read committed Storage, still on the line. `release` drops it, and\n\t * the mount with its last observer.\n\t */\n\tattach<O extends ViewObserver>(\n\t\tid: ConversationId,\n\t\tcreate: (value: ConversationView, release: () => void, storage: Storage) => O | Promise<O>,\n\t\tcontext: Context,\n\t): Promise<{ observer: O; detach: () => void }> {\n\t\treturn this.#session.readOnLine(async () => {\n\t\t\tconst mount = this.#mounts.get(id) ?? (await this.#build(id, context));\n\t\t\tconst detach = (): void => {\n\t\t\t\tmount.observers.delete(observer);\n\t\t\t\tif (mount.observers.size === 0 && this.#mounts.get(id) === mount) this.#mounts.delete(id);\n\t\t\t};\n\t\t\tconst observer = await create(mount.value, detach, this.#storage);\n\t\t\t// Close or cancellation may begin while the mount hydrates; register nothing then.\n\t\t\tif (this.#closed) throw closedError(this.#session);\n\t\t\tcontext.abortSignal?.throwIfAborted();\n\t\t\tthis.#mounts.set(id, mount);\n\t\t\tmount.observers.add(observer);\n\t\t\treturn { observer, detach };\n\t\t});\n\t}\n\n\tasync #build(id: ConversationId, context: Context): Promise<Mount> {\n\t\tconst conversation = await this.#storage.conversation(id, context);\n\t\tif (conversation === undefined) throw new Error(`Conversation ${id} does not exist`);\n\t\tconst bounds = await captureContextBounds(this.#storage, id, context);\n\t\tconst entries = await activeEntries(this.#storage, id, bounds, context);\n\t\tconst docs: Record<string, JsonObject> = {};\n\t\tconst incarnations = new Map<string, { id: DocumentId; version: number }>();\n\t\tfor (const token of MOUNTED) {\n\t\t\tconst loaded = await this.#session.conversationDocumentOnLine(token, id, context);\n\t\t\tif (loaded === undefined) continue;\n\t\t\tdocs[token.definition.kind] = loaded.value;\n\t\t\tincarnations.set(token.definition.kind, { id: loaded.record.id, version: loaded.version });\n\t\t}\n\t\treturn { value: { conversation, entries, docs }, docs: incarnations, observers: new Set() };\n\t}\n}\n\n/**\n * Derive the mount's operations from one publication, apply them, and hand the revision to every observer; one that\n * throws is reported through `report`, and the others still get it.\n */\nfunction advance(\n\tid: ConversationId,\n\tmount: Mount,\n\tpublication: CommitPublication,\n\tcontext: Context,\n\treport: (error: unknown) => void,\n): void {\n\tconst docOps: Op[] = [];\n\tconst entryOps: Op[] = [];\n\tlet entries = mount.value.entries;\n\t// Entry writes are published in ID order.\n\tfor (const change of publication.changes) {\n\t\tif (change.type === \"entry\" && change.value.conversationId === id) {\n\t\t\tconst entry = change.value;\n\t\t\tconst value = entry as unknown as JsonValue;\n\t\t\tif (entry.head === undefined) {\n\t\t\t\tentryOps.push([\"p\", [\"entries\"], entries.length, 0, [value]]);\n\t\t\t\tentries = [...entries, entry];\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// A head marker keeps the non-head entries from its head, which are always a suffix, and goes in front.\n\t\t\tconst target = entry.head;\n\t\t\tlet kept = entries.findIndex((candidate) => candidate.head === undefined && candidate.id >= target);\n\t\t\tif (kept < 0) kept = entries.length;\n\t\t\tentryOps.push([\"p\", [\"entries\"], 0, kept, [value]]);\n\t\t\tentries = [entry, ...entries.slice(kept)];\n\t\t\tcontinue;\n\t\t}\n\t\tif (change.type !== \"document\" || change.conversationId !== id) continue;\n\t\tconst kind = change.record.kind;\n\t\tif (!MOUNTED_KINDS.has(kind) || change.record.key !== undefined) continue;\n\t\tconst path: NonEmptyPath = [\"docs\", kind];\n\t\tconst mounted = mount.docs.get(kind);\n\t\tif (change.value === null) {\n\t\t\tif (mounted?.id !== change.record.id) continue;\n\t\t\tmount.docs.delete(kind);\n\t\t\tdocOps.push([\"d\", path]);\n\t\t} else if (mounted?.id === change.record.id && mounted.version === change.version) {\n\t\t\tfor (const op of change.ops) docOps.push(prefixed(op, path));\n\t\t} else {\n\t\t\tmount.docs.set(kind, { id: change.record.id, version: change.version! });\n\t\t\tdocOps.push([\"s\", path, change.value]);\n\t\t}\n\t}\n\tconst before = mount.value;\n\tconst ops = [...docOps, ...entryOps];\n\tconst frameContext = withoutAbortSignal(context);\n\tif (ops.length > 0) {\n\t\tconst value = docOps.length === 0 ? mount.value : applyImmutable(mount.value, docOps);\n\t\tmount.value = entries === value.entries ? value : { ...value, entries };\n\t\tfor (const observer of [...mount.observers]) {\n\t\t\tcontained(() => observer.advance?.(mount.value, ops, frameContext), report);\n\t\t}\n\t}\n\tfor (const observer of [...mount.observers]) {\n\t\tcontained(() => observer.publication?.(before, mount.value, ops, publication, frameContext), report);\n\t}\n}\n\n/** `op` moved under `prefix`; a root replacement becomes a set of the prefix. */\nfunction prefixed(op: Op, prefix: NonEmptyPath): Op {\n\tconst at = (path: Path): NonEmptyPath => [...prefix, ...path] as unknown as NonEmptyPath;\n\tswitch (op[0]) {\n\t\tcase \"r\":\n\t\t\treturn [\"s\", prefix, op[1]];\n\t\tcase \"p\":\n\t\t\treturn [\"p\", at(op[1]), op[2], op[3], op[4]];\n\t\tcase \"m\":\n\t\t\treturn [\"m\", at(op[1]), op[2]];\n\t\tcase \"s\":\n\t\t\treturn [\"s\", at(op[1]), op[2]];\n\t\tcase \"d\":\n\t\t\treturn [\"d\", at(op[1])];\n\t\tcase \"a\":\n\t\t\treturn [\"a\", at(op[1]), op[2]];\n\t\tcase \"t\":\n\t\t\treturn [\"t\", at(op[1]), op[2]];\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/harness/view.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Context,\n\ttype JsonValue,\n\tWatch,\n\ttype WatchCall,\n\ttype WatchEnd,\n\ttype WatchHandle,\n} from \"@earendil-works/chord\";\nimport { withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport { applyImmutable, type NonEmptyPath, type Op, type Path } from \"@earendil-works/chord/delta\";\nimport { idFromNumber } from \"../ids.ts\";\nimport {\n\tcloseEndOf,\n\tcloseEnds,\n\tcontained,\n\tguardObserver,\n\ttype ObservedCommit,\n\tobservation,\n\ttype SessionImpl,\n} from \"../session/session.ts\";\nimport type {\n\tConversationDocToken,\n\tConversationId,\n\tConversationRecord,\n\tCursor,\n\tDocumentId,\n\tEntryId,\n\tEntryQuery,\n\tEntryRecord,\n\tJsonObject,\n\tObservation,\n\tObserver,\n\tStorage,\n} from \"../types.ts\";\nimport { AgentDoc } from \"./agent.ts\";\nimport { InboxDoc } from \"./inbox.ts\";\nimport { LiveDoc } from \"./live.ts\";\nimport { ProviderDoc } from \"./provider.ts\";\nimport { UsageDoc } from \"./usage.ts\";\nimport { closedError } from \"./util.ts\";\n\n/** Structural view of one conversation: a window over its transcript and its built-in documents (spec §9.3). */\nexport type ConversationView = {\n\treadonly conversation: ConversationRecord;\n\t/**\n\t * A window over the transcript, its fork-aware history (`Conversation.entries()`), in entry ID order. Head markers\n\t * such as compaction summaries sit where they were written; their `head` tells where the entries they summarize end.\n\t */\n\treadonly entries: readonly EntryRecord[];\n\t/** ID of the entry just before the window; absent when the window starts the transcript. */\n\treadonly before?: EntryId;\n\t/** Built-in conversation documents keyed by kind; absent documents are absent. */\n\treadonly docs: Readonly<Record<string, JsonObject>>;\n};\n\n/**\n * Which entries a view's window holds (spec §9.3). The window holds between `min` and `max` entries: it starts with\n * the newest `min` entries, takes appends, and once it would hold more than `max`, drops its oldest in one splice down\n * to `min`. With `from`, it starts at `from` instead when at most `max` entries are at or after it.\n */\nexport type ConversationWindow = {\n\t/**\n\t * Where the first value's window starts, inclusive, such as right after the newest entry a client has\n\t * (`ConversationTranscript.resume`). It selects only that first value: every entry committed after the attachment is\n\t * appended, whatever its ID. A `from` past the newest entry starts the window empty, with `before` the newest entry.\n\t */\n\treadonly from?: EntryId;\n\t/** Default 50; an integer, at least 1. */\n\treadonly min?: number;\n\t/** Default `2 * min`; an integer, at least `min`. */\n\treadonly max?: number;\n};\n\n/** Default `ConversationWindow.min`. */\nconst DEFAULT_WINDOW_MIN = 50;\n\n/** Receives each next revision of one observer's window, and the Session's close. */\nexport type ViewObserver = {\n\tadvance(call: WatchCall<ConversationView>, context: Context): void;\n\t/** The Session closed (`ended`), or failed (`failed`). */\n\tend(end: WatchEnd): void;\n};\n\nconst MOUNTED = [\n\tAgentDoc,\n\tLiveDoc,\n\tInboxDoc,\n\tProviderDoc,\n\tUsageDoc,\n] as unknown as readonly ConversationDocToken<JsonObject>[];\nconst MOUNTED_KINDS: ReadonlySet<string> = new Set(MOUNTED.map((token) => token.definition.kind));\nconst SCAN_PAGE_SIZE = 256;\n\n/** One observer of a mount and its window: the bounds and the revision it was last given. */\ntype Windowed = {\n\treadonly min: number;\n\treadonly max: number;\n\tvalue: ConversationView;\n\treadonly observer: ViewObserver;\n};\n\n/**\n * One conversation's mount: the documents it shows, shared by every observer, and the observers, each with its own\n * window over the entries.\n */\ntype Mount = {\n\treadonly conversation: ConversationRecord;\n\tdocs: Readonly<Record<string, JsonObject>>;\n\t/** Mounted incarnation and definition version per kind; another incarnation or version is set whole. */\n\treadonly incarnations: Map<string, { id: DocumentId; version: number }>;\n\treadonly observers: Set<Windowed>;\n};\n\nconst VIEWS = new WeakMap<object, ConversationViews>();\n\n/** The view mounts of a Harness, for adapters built on them. */\nexport function conversationViews(harness: object): ConversationViews {\n\tconst views = VIEWS.get(harness);\n\tif (views === undefined) throw new Error(\"Not a Harness\");\n\treturn views;\n}\n\n/** A window with its defaults applied. */\ntype WindowBounds = { readonly from: EntryId | undefined; readonly min: number; readonly max: number };\n\n/** `window` with its defaults; throws a `RangeError` for bounds that are not integers or `max` below `min`. */\nfunction resolveWindow(window: ConversationWindow | undefined): WindowBounds {\n\tconst min = window?.min ?? DEFAULT_WINDOW_MIN;\n\tif (!Number.isSafeInteger(min) || min < 1) throw new RangeError(`Window min must be an integer >= 1, got ${min}`);\n\tconst max = window?.max ?? 2 * min;\n\tif (!Number.isSafeInteger(max) || max < min) {\n\t\tthrow new RangeError(`Window max must be an integer >= min (${min}), got ${max}`);\n\t}\n\tconst from = window?.from;\n\tif (from !== undefined && !Number.isSafeInteger(from)) {\n\t\tthrow new RangeError(`Window from must be an entry ID, got ${from}`);\n\t}\n\treturn { from, min, max };\n}\n\n/**\n * The Harness's conversation view mounts: at most one per conversation, built on the Session line by its first\n * observer and dropped with its last. Each mount advances from the Session's commits as memory adopts them, deferred ones\n * (`CommitPersistence`) before they are stored, and hands each observer the next revision of its own window.\n */\nexport class ConversationViews {\n\treadonly #session: SessionImpl;\n\treadonly #mounts = new Map<ConversationId, Mount>();\n\t#closed = false;\n\n\tconstructor(session: SessionImpl) {\n\t\tthis.#session = session;\n\t\tVIEWS.set(session, this);\n\t\tsession.followCommits((publication, context) => {\n\t\t\tfor (const [id, mount] of this.#mounts)\n\t\t\t\tadvance(id, mount, publication, context, (error) => this.report(error));\n\t\t});\n\t\tsession.subscribeClose(() => {\n\t\t\tthis.#closed = true;\n\t\t\tconst ends = closeEnds(this.#session.failure);\n\t\t\tfor (const mount of this.#mounts.values())\n\t\t\t\tfor (const windowed of [...mount.observers]) {\n\t\t\t\t\tcontained(\n\t\t\t\t\t\t() => windowed.observer.end(closeEndOf(windowed.observer, ends)),\n\t\t\t\t\t\t(error) => this.report(error),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\tthis.#mounts.clear();\n\t\t});\n\t}\n\n\t/** Report an observer's listener error through the Harness. */\n\treport(error: unknown): void {\n\t\tthis.#session.report(error);\n\t}\n\n\t/**\n\t * Attach a synchronous observer of the view (`Harness.observeConversation()`), behind `guardObserver()`; `context`\n\t * governs only the attachment.\n\t */\n\tasync observe(\n\t\tid: ConversationId,\n\t\tobserver: Observer<ConversationView>,\n\t\tcontext: Context,\n\t\twindow?: ConversationWindow,\n\t): Promise<Observation<ConversationView>> {\n\t\tlet value!: ConversationView;\n\t\tconst attached = await this.attach(\n\t\t\tid,\n\t\t\twindow,\n\t\t\t(current, release) => {\n\t\t\t\tvalue = current;\n\t\t\t\treturn guardObserver(observer, release, (error) => this.report(error));\n\t\t\t},\n\t\t\tcontext,\n\t\t);\n\t\tconst signal = context.abortSignal;\n\t\tif (signal?.aborted) {\n\t\t\tattached.detach();\n\t\t\tthrow signal.reason;\n\t\t}\n\t\treturn observation(value, attached.observer);\n\t}\n\n\t/** A serialized watch of the view, an observer of its mount; aborting `context` ends it `aborted`. */\n\tasync watch(\n\t\tid: ConversationId,\n\t\tcontext: Context,\n\t\twindow?: ConversationWindow,\n\t): Promise<WatchHandle<ConversationView>> {\n\t\tconst { observer } = await this.attach(\n\t\t\tid,\n\t\t\twindow,\n\t\t\t(value, release) => new Watch<ConversationView>(value, release, (error) => this.#session.report(error)),\n\t\t\tcontext,\n\t\t);\n\t\tconst signal = context.abortSignal;\n\t\tif (signal?.aborted) {\n\t\t\tobserver.abort();\n\t\t\tthrow signal.reason;\n\t\t}\n\t\tif (signal !== undefined) observer.observeAbort(signal);\n\t\treturn observer;\n\t}\n\n\t/**\n\t * Register an observer created from its window's first revision, atomically on the Session line: it sees every later\n\t * publication and nothing earlier. `release` drops it, and the mount with its last observer.\n\t */\n\tasync attach<O extends ViewObserver>(\n\t\tid: ConversationId,\n\t\twindow: ConversationWindow | undefined,\n\t\tcreate: (value: ConversationView, release: () => void) => O,\n\t\tcontext: Context,\n\t): Promise<{ observer: O; detach: () => void }> {\n\t\tconst bounds = resolveWindow(window);\n\t\treturn this.#session.readOnLine(async (storage) => {\n\t\t\tconst mount = this.#mounts.get(id) ?? (await this.#build(storage, id, context));\n\t\t\tconst { entries, before } = await loadWindow(storage, id, bounds, context);\n\t\t\tconst value = view(mount.conversation, entries, before, mount.docs);\n\t\t\tlet windowed: Windowed | undefined;\n\t\t\tconst detach = (): void => {\n\t\t\t\tif (windowed !== undefined) mount.observers.delete(windowed);\n\t\t\t\tif (mount.observers.size === 0 && this.#mounts.get(id) === mount) this.#mounts.delete(id);\n\t\t\t};\n\t\t\tconst observer = create(value, detach);\n\t\t\t// Close or cancellation may begin while the mount hydrates; register nothing then.\n\t\t\tif (this.#closed) throw closedError(this.#session);\n\t\t\tcontext.abortSignal?.throwIfAborted();\n\t\t\twindowed = { min: bounds.min, max: bounds.max, value, observer };\n\t\t\tthis.#mounts.set(id, mount);\n\t\t\tmount.observers.add(windowed);\n\t\t\treturn { observer, detach };\n\t\t});\n\t}\n\n\t/** Hydrate a mount on the line, through the line's `storage`. */\n\tasync #build(storage: Storage, id: ConversationId, context: Context): Promise<Mount> {\n\t\tconst conversation = await storage.conversation(id, context);\n\t\tif (conversation === undefined) throw new Error(`Conversation ${id} does not exist`);\n\t\tconst docs: Record<string, JsonObject> = {};\n\t\tconst incarnations = new Map<string, { id: DocumentId; version: number }>();\n\t\tfor (const token of MOUNTED) {\n\t\t\tconst loaded = await this.#session.conversationDocumentOnLine(token, id, context);\n\t\t\tif (loaded === undefined) continue;\n\t\t\tdocs[token.definition.kind] = loaded.value;\n\t\t\tincarnations.set(token.definition.kind, { id: loaded.record.id, version: loaded.version });\n\t\t}\n\t\treturn { conversation, docs, incarnations, observers: new Set() };\n\t}\n}\n\n/** A view revision; `before` is a key only when set. */\nfunction view(\n\tconversation: ConversationRecord,\n\tentries: readonly EntryRecord[],\n\tbefore: EntryId | undefined,\n\tdocs: Readonly<Record<string, JsonObject>>,\n): ConversationView {\n\treturn before === undefined ? { conversation, entries, docs } : { conversation, entries, before, docs };\n}\n\n/**\n * A new observer's window, read on the Session line with bounded scans: the entries from `from` when at most `max` are\n * at or after it, otherwise the newest `min`, and the entry before them.\n */\nasync function loadWindow(\n\tstorage: Storage,\n\tconversationId: ConversationId,\n\tbounds: WindowBounds,\n\tcontext: Context,\n): Promise<{ entries: readonly EntryRecord[]; before: EntryId | undefined }> {\n\tconst { from, min, max } = bounds;\n\tif (from !== undefined) {\n\t\tconst since = await scanUpTo(storage, { conversationId, minEntryId: from, order: \"ascending\" }, max + 1, context);\n\t\tif (since.length <= max) {\n\t\t\tconst query = { conversationId, maxEntryId: idFromNumber<EntryId>(from - 1) };\n\t\t\tconst previous = (await storage.scanEntries(query, 1, undefined, context)).items[0];\n\t\t\treturn { entries: since, before: previous?.id };\n\t\t}\n\t}\n\tconst newest = await scanUpTo(storage, { conversationId }, min + 1, context);\n\tconst before = newest.length > min ? newest.pop()!.id : undefined;\n\treturn { entries: newest.reverse(), before };\n}\n\n/** Up to `limit` entries of `query`, following cursors past short pages. */\nasync function scanUpTo(storage: Storage, query: EntryQuery, limit: number, context: Context): Promise<EntryRecord[]> {\n\tconst entries: EntryRecord[] = [];\n\tlet cursor: Cursor | undefined;\n\tdo {\n\t\tconst page = await storage.scanEntries(query, Math.min(SCAN_PAGE_SIZE, limit - entries.length), cursor, context);\n\t\tentries.push(...page.items);\n\t\tcursor = page.next;\n\t} while (cursor !== undefined && entries.length < limit);\n\treturn entries;\n}\n\n/**\n * Derive the mount's operations from one publication and hand each observer the next revision of its window; one that\n * throws is reported through `report`, and the others still get theirs. Documents are applied once and shared; each\n * window takes the appended entries and, past its `max`, drops its oldest down to its `min` in one splice.\n */\nfunction advance(\n\tid: ConversationId,\n\tmount: Mount,\n\tpublication: ObservedCommit,\n\tcontext: Context,\n\treport: (error: unknown) => void,\n): void {\n\tconst docOps: Op[] = [];\n\t// Entry writes are published in ID order.\n\tconst appended: EntryRecord[] = [];\n\tfor (const change of publication.changes) {\n\t\tif (change.type === \"entry\" && change.value.conversationId === id) {\n\t\t\tappended.push(change.value);\n\t\t\tcontinue;\n\t\t}\n\t\tif (change.type !== \"document\" || change.conversationId !== id) continue;\n\t\tconst kind = change.record.kind;\n\t\tif (!MOUNTED_KINDS.has(kind) || change.record.key !== undefined) continue;\n\t\tconst path: NonEmptyPath = [\"docs\", kind];\n\t\tconst mounted = mount.incarnations.get(kind);\n\t\tif (change.kind === \"retire\") {\n\t\t\tif (mounted?.id !== change.record.id) continue;\n\t\t\tmount.incarnations.delete(kind);\n\t\t\tdocOps.push([\"d\", path]);\n\t\t} else if (mounted?.id === change.record.id && mounted.version === change.version) {\n\t\t\tfor (const op of change.ops) docOps.push(prefixed(op, path));\n\t\t} else {\n\t\t\tmount.incarnations.set(kind, { id: change.record.id, version: change.version });\n\t\t\tdocOps.push([\"s\", path, change.value]);\n\t\t}\n\t}\n\tif (docOps.length === 0 && appended.length === 0) return;\n\tif (docOps.length > 0) mount.docs = applyImmutable({ docs: mount.docs }, docOps).docs;\n\tconst frameContext = withoutAbortSignal(context);\n\tconst inserted = appended as unknown as JsonValue[];\n\tfor (const windowed of [...mount.observers]) {\n\t\tconst previous = windowed.value;\n\t\tlet entries = previous.entries;\n\t\tlet before = previous.before;\n\t\tlet ops: Op[] = docOps;\n\t\tif (appended.length > 0) {\n\t\t\tops = [...docOps, [\"p\", [\"entries\"], entries.length, 0, inserted]];\n\t\t\tentries = entries.concat(appended);\n\t\t\tif (entries.length > windowed.max) {\n\t\t\t\tconst drop = entries.length - windowed.min;\n\t\t\t\tbefore = entries[drop - 1]!.id;\n\t\t\t\tentries = entries.slice(drop);\n\t\t\t\tops.push([\"p\", [\"entries\"], 0, drop, []], [\"s\", [\"before\"], before]);\n\t\t\t}\n\t\t}\n\t\twindowed.value = view(mount.conversation, entries, before, mount.docs);\n\t\tconst call: WatchCall<ConversationView> = { kind: \"value\", value: windowed.value, ops, retired: false };\n\t\tcontained(() => windowed.observer.advance(call, frameContext), report);\n\t}\n}\n\n/** `op` moved under `prefix`; a root replacement becomes a set of the prefix. */\nfunction prefixed(op: Op, prefix: NonEmptyPath): Op {\n\tconst at = (path: Path): NonEmptyPath => [...prefix, ...path] as unknown as NonEmptyPath;\n\tswitch (op[0]) {\n\t\tcase \"r\":\n\t\t\treturn [\"s\", prefix, op[1]];\n\t\tcase \"p\":\n\t\t\treturn [\"p\", at(op[1]), op[2], op[3], op[4]];\n\t\tcase \"m\":\n\t\t\treturn [\"m\", at(op[1]), op[2]];\n\t\tcase \"s\":\n\t\t\treturn [\"s\", at(op[1]), op[2]];\n\t\tcase \"d\":\n\t\t\treturn [\"d\", at(op[1])];\n\t\tcase \"a\":\n\t\t\treturn [\"a\", at(op[1]), op[2]];\n\t\tcase \"t\":\n\t\t\treturn [\"t\", at(op[1]), op[2]];\n\t}\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
|
+
export type { NativeWatchCall, WatchCall, WatchEnd, WatchHandle } from "@earendil-works/chord";
|
|
1
2
|
export { defineDoc, defineDocFamily } from "./documents.ts";
|
|
2
3
|
export { AssistantEntry, CompactionEntry, defineEntry, ResetEntry, SystemEntry, ToolResultEntry, UserEntry, } from "./entries.ts";
|
|
3
|
-
export { ConversationBusy, ReadAfterWrite, SessionFailed, StorageRequestError } from "./errors.ts";
|
|
4
|
-
export { AgentDoc, configure, DEFAULT_COMPACTION_POLICY, DEFAULT_PROGRESS_POLICY, DEFAULT_RETRY_POLICY, } from "./harness/agent.ts";
|
|
4
|
+
export { ConversationBusy, ConversationIdle, ReadAfterWrite, ReadOnlySession, SessionFailed, StorageRequestError, } from "./errors.ts";
|
|
5
|
+
export { AgentDoc, configure, DEFAULT_COMPACTION_POLICY, DEFAULT_PROGRESS_POLICY, DEFAULT_RESTART_LIMIT, DEFAULT_RETRY_POLICY, } from "./harness/agent.ts";
|
|
5
6
|
export { type CompactionCheckpoint, type CompactionInput, CompactionTask, type SummaryRequest, } from "./harness/compaction.ts";
|
|
6
|
-
export { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from "./harness/define.ts";
|
|
7
|
-
export { type AgentEvent, type AgentEventStream, type MessageChange, type SnapshotEvent, type ToolEventCall, watchEvents, } from "./harness/events.ts";
|
|
7
|
+
export { defineExtension, defineTool, hook, runEndTask, section, wrapSection, wrapTool } from "./harness/define.ts";
|
|
8
8
|
export { type GenerationCheckpoint, type GenerationInput, type GenerationResult, GenerationTask, } from "./harness/generation.ts";
|
|
9
|
-
export { Harness } from "./harness/harness.ts";
|
|
9
|
+
export { DEFAULT_HARNESS_IDENTITY, Harness } from "./harness/harness.ts";
|
|
10
10
|
export { InboxDoc, type InboxItem, type InboxState } from "./harness/inbox.ts";
|
|
11
|
-
export { type CompactionFailure, type CompactionStatus, LiveDoc, type LiveState, type NestedToolSlot, type NestedToolSummary, type ToolSlot, } from "./harness/live.ts";
|
|
11
|
+
export { type CompactionFailure, type CompactionStatus, LiveDoc, type LiveRun, type LiveState, type NestedToolSlot, type NestedToolSummary, type RunFailure, type RunFailureReason, type ToolSlot, } from "./harness/live.ts";
|
|
12
12
|
export { ProviderDoc, type ProviderState } from "./harness/provider.ts";
|
|
13
13
|
export { createRegistry } from "./harness/registry.ts";
|
|
14
|
+
export { registryReader } from "./harness/registry-reader.ts";
|
|
15
|
+
export type { BlockedReason } from "./harness/scheduler.ts";
|
|
14
16
|
export type { TaskGraph, TaskGraphNode, TaskGraphState, TaskGraphWatch } from "./harness/task-graph.ts";
|
|
17
|
+
export { DURABLE_TELEMETRY_SCHEMA } from "./harness/telemetry.ts";
|
|
15
18
|
export { NestedCallDoc, type NestedCallState, ToolTask, type ToolTaskCheckpoint, type ToolTaskInput, type ToolTaskResult, } from "./harness/tool.ts";
|
|
16
|
-
export
|
|
19
|
+
export { ConversationTranscript, type ConversationTranscriptOptions, type EntryLoader, type TranscriptItem, type TranscriptView, } from "./harness/transcript.ts";
|
|
20
|
+
export type { AfterFailedRun, Agent, AgentChange, AgentState, AnyTask, CompactionHooks, CompactionPolicy, CompactionReason, CompactionResult, CompactionSettings, ContextView, Conversation, ConversationAbortOptions, ConversationCreateOptions, ConversationHandle, ConversationInit, ConversationRetryPolicy, ConversationStreamOptions, ConversationWatch, EnvTarget, Extension, GenerationHooks, HarnessInspection, HarnessOptions, HarnessSettings, HookApi, HookRegistration, HookResult, HooksOf, InputEntry, InputSubmissionDraft, ModelRef, NestedToolExecutionResult, ProgressPolicy, PromptInput, PromptSection, QueueMode, Registry, RegistryReader, RegistrySnapshot, RunEndTask, RunSummary, Settings, SettledSubmissionRecord, SettledTask, Submission, SubmissionDraft, TaskInspection, ToolControl, ToolDiagnostic, ToolExecutionApi, ToolExecutionMode, ToolExecutionResult, ToolHookCall, ToolHooks, ToolRegistration, UserInput, Wake, Wrap, } from "./harness/types.ts";
|
|
17
21
|
export { UsageDoc, type UsageState } from "./harness/usage.ts";
|
|
18
|
-
export type { ConversationView } from "./harness/view.ts";
|
|
22
|
+
export type { ConversationView, ConversationWindow } from "./harness/view.ts";
|
|
19
23
|
export { createSession } from "./session/session.ts";
|
|
20
24
|
export { MemoryStorage } from "./storage/memory.ts";
|
|
21
25
|
export { defineTask } from "./tasks.ts";
|
|
22
|
-
export type { CheckpointInfo, CommitChange, CommitPublication, CommonDocDefinition, ContextEdit, ConversationDocFamilyToken, ConversationDocToken, ConversationId, ConversationOwnership, ConversationQuery, ConversationRecord, Cursor, DocDefinition, DocFamilyDefinition, DocFamilyToken, DocToken, DocumentAddress, DocumentCommitChange, DocumentContent, DocumentCopySource, DocumentCreate, DocumentId, DocumentObserver, DocumentPoint, DocumentQuery, DocumentReader, DocumentRecord, DocumentSemantics,
|
|
26
|
+
export type { CheckpointInfo, CommitChange, CommitObservation, CommitObserver, CommitOptions, CommitPersistence, CommitPublication, CommitResult, CommonDocDefinition, ContextEdit, ConversationDocFamilyToken, ConversationDocToken, ConversationId, ConversationOwnership, ConversationQuery, ConversationRecord, Cursor, DocDefinition, DocFamilyDefinition, DocFamilyToken, DocToken, DocumentAddress, DocumentCommitChange, DocumentContent, DocumentCopySource, DocumentCreate, DocumentId, DocumentObserver, DocumentPoint, DocumentQuery, DocumentReader, DocumentRecord, DocumentSemantics, DocumentWatch, Entry, EntryDraft, EntryId, EntryQuery, EntryRecord, HookRunner, HostCallback, Id, JoinPolicy, JsonObject, LatestConversationSemantics, NextTaskState, Observation, Observer, Page, PhaseHandler, Report, ReportFrom, ReportInfo, ReportTask, RewindableConversationDocFamilyToken, RewindableConversationDocToken, RewindableConversationSemantics, RunningTask, ScanOrder, Seq, Session, SessionDocFamilyToken, SessionDocToken, SessionEnd, SetTimer, Storage, StorageWrite, StoredDocument, SubmissionCreate, SubmissionId, SubmissionQuery, SubmissionRecord, SubmissionSettlement, TableCommitChange, Task, TaskDefinition, TaskDocFamilyToken, TaskDocToken, TaskId, TaskOptions, TaskOutcome, TaskOutcomeError, TaskOwnership, TaskQuery, TaskRecord, TaskRuntime, TaskState, Tx, TypedEntry, TypedEntryDraft, } from "./types.ts";
|
|
23
27
|
export { ROOT_CONVERSATION_ID } from "./types.ts";
|
|
24
28
|
//# 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,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EACN,cAAc,EACd,eAAe,EACf,WAAW,EACX,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
export { defineDoc, defineDocFamily } from "./documents.js";
|
|
2
2
|
export { AssistantEntry, CompactionEntry, defineEntry, ResetEntry, SystemEntry, ToolResultEntry, UserEntry, } from "./entries.js";
|
|
3
|
-
export { ConversationBusy, ReadAfterWrite, SessionFailed, StorageRequestError } from "./errors.js";
|
|
4
|
-
export { AgentDoc, configure, DEFAULT_COMPACTION_POLICY, DEFAULT_PROGRESS_POLICY, DEFAULT_RETRY_POLICY, } from "./harness/agent.js";
|
|
3
|
+
export { ConversationBusy, ConversationIdle, ReadAfterWrite, ReadOnlySession, SessionFailed, StorageRequestError, } from "./errors.js";
|
|
4
|
+
export { AgentDoc, configure, DEFAULT_COMPACTION_POLICY, DEFAULT_PROGRESS_POLICY, DEFAULT_RESTART_LIMIT, DEFAULT_RETRY_POLICY, } from "./harness/agent.js";
|
|
5
5
|
export { CompactionTask, } from "./harness/compaction.js";
|
|
6
|
-
export { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from "./harness/define.js";
|
|
7
|
-
export { watchEvents, } from "./harness/events.js";
|
|
6
|
+
export { defineExtension, defineTool, hook, runEndTask, section, wrapSection, wrapTool } from "./harness/define.js";
|
|
8
7
|
export { GenerationTask, } from "./harness/generation.js";
|
|
9
|
-
export { Harness } from "./harness/harness.js";
|
|
8
|
+
export { DEFAULT_HARNESS_IDENTITY, Harness } from "./harness/harness.js";
|
|
10
9
|
export { InboxDoc } from "./harness/inbox.js";
|
|
11
10
|
export { LiveDoc, } from "./harness/live.js";
|
|
12
11
|
export { ProviderDoc } from "./harness/provider.js";
|
|
13
12
|
export { createRegistry } from "./harness/registry.js";
|
|
13
|
+
export { registryReader } from "./harness/registry-reader.js";
|
|
14
|
+
export { DURABLE_TELEMETRY_SCHEMA } from "./harness/telemetry.js";
|
|
14
15
|
export { NestedCallDoc, ToolTask, } from "./harness/tool.js";
|
|
16
|
+
export { ConversationTranscript, } from "./harness/transcript.js";
|
|
15
17
|
export { UsageDoc } from "./harness/usage.js";
|
|
16
18
|
export { createSession } from "./session/session.js";
|
|
17
19
|
export { MemoryStorage } from "./storage/memory.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EACN,cAAc,EACd,eAAe,EACf,WAAW,EACX,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,aAAa,EACb,mBAAmB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,QAAQ,EACR,SAAS,EACT,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAGN,cAAc,GAEd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpH,OAAO,EAIN,cAAc,GACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,wBAAwB,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAmC,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAGN,OAAO,GAQP,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAsB,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EACN,aAAa,EAEb,QAAQ,GAIR,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,sBAAsB,GAKtB,MAAM,yBAAyB,CAAC;AA8DjC,OAAO,EAAE,QAAQ,EAAmB,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA6FxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC","sourcesContent":["export type { NativeWatchCall, WatchCall, WatchEnd, WatchHandle } from \"@earendil-works/chord\";\nexport { defineDoc, defineDocFamily } from \"./documents.ts\";\nexport {\n\tAssistantEntry,\n\tCompactionEntry,\n\tdefineEntry,\n\tResetEntry,\n\tSystemEntry,\n\tToolResultEntry,\n\tUserEntry,\n} from \"./entries.ts\";\nexport {\n\tConversationBusy,\n\tConversationIdle,\n\tReadAfterWrite,\n\tReadOnlySession,\n\tSessionFailed,\n\tStorageRequestError,\n} from \"./errors.ts\";\nexport {\n\tAgentDoc,\n\tconfigure,\n\tDEFAULT_COMPACTION_POLICY,\n\tDEFAULT_PROGRESS_POLICY,\n\tDEFAULT_RESTART_LIMIT,\n\tDEFAULT_RETRY_POLICY,\n} from \"./harness/agent.ts\";\nexport {\n\ttype CompactionCheckpoint,\n\ttype CompactionInput,\n\tCompactionTask,\n\ttype SummaryRequest,\n} from \"./harness/compaction.ts\";\nexport { defineExtension, defineTool, hook, runEndTask, section, wrapSection, wrapTool } from \"./harness/define.ts\";\nexport {\n\ttype GenerationCheckpoint,\n\ttype GenerationInput,\n\ttype GenerationResult,\n\tGenerationTask,\n} from \"./harness/generation.ts\";\nexport { DEFAULT_HARNESS_IDENTITY, Harness } from \"./harness/harness.ts\";\nexport { InboxDoc, type InboxItem, type InboxState } from \"./harness/inbox.ts\";\nexport {\n\ttype CompactionFailure,\n\ttype CompactionStatus,\n\tLiveDoc,\n\ttype LiveRun,\n\ttype LiveState,\n\ttype NestedToolSlot,\n\ttype NestedToolSummary,\n\ttype RunFailure,\n\ttype RunFailureReason,\n\ttype ToolSlot,\n} from \"./harness/live.ts\";\nexport { ProviderDoc, type ProviderState } from \"./harness/provider.ts\";\nexport { createRegistry } from \"./harness/registry.ts\";\nexport { registryReader } from \"./harness/registry-reader.ts\";\nexport type { BlockedReason } from \"./harness/scheduler.ts\";\nexport type { TaskGraph, TaskGraphNode, TaskGraphState, TaskGraphWatch } from \"./harness/task-graph.ts\";\nexport { DURABLE_TELEMETRY_SCHEMA } from \"./harness/telemetry.ts\";\nexport {\n\tNestedCallDoc,\n\ttype NestedCallState,\n\tToolTask,\n\ttype ToolTaskCheckpoint,\n\ttype ToolTaskInput,\n\ttype ToolTaskResult,\n} from \"./harness/tool.ts\";\nexport {\n\tConversationTranscript,\n\ttype ConversationTranscriptOptions,\n\ttype EntryLoader,\n\ttype TranscriptItem,\n\ttype TranscriptView,\n} from \"./harness/transcript.ts\";\nexport type {\n\tAfterFailedRun,\n\tAgent,\n\tAgentChange,\n\tAgentState,\n\tAnyTask,\n\tCompactionHooks,\n\tCompactionPolicy,\n\tCompactionReason,\n\tCompactionResult,\n\tCompactionSettings,\n\tContextView,\n\tConversation,\n\tConversationAbortOptions,\n\tConversationCreateOptions,\n\tConversationHandle,\n\tConversationInit,\n\tConversationRetryPolicy,\n\tConversationStreamOptions,\n\tConversationWatch,\n\tEnvTarget,\n\tExtension,\n\tGenerationHooks,\n\tHarnessInspection,\n\tHarnessOptions,\n\tHarnessSettings,\n\tHookApi,\n\tHookRegistration,\n\tHookResult,\n\tHooksOf,\n\tInputEntry,\n\tInputSubmissionDraft,\n\tModelRef,\n\tNestedToolExecutionResult,\n\tProgressPolicy,\n\tPromptInput,\n\tPromptSection,\n\tQueueMode,\n\tRegistry,\n\tRegistryReader,\n\tRegistrySnapshot,\n\tRunEndTask,\n\tRunSummary,\n\tSettings,\n\tSettledSubmissionRecord,\n\tSettledTask,\n\tSubmission,\n\tSubmissionDraft,\n\tTaskInspection,\n\tToolControl,\n\tToolDiagnostic,\n\tToolExecutionApi,\n\tToolExecutionMode,\n\tToolExecutionResult,\n\tToolHookCall,\n\tToolHooks,\n\tToolRegistration,\n\tUserInput,\n\tWake,\n\tWrap,\n} from \"./harness/types.ts\";\nexport { UsageDoc, type UsageState } from \"./harness/usage.ts\";\nexport type { ConversationView, ConversationWindow } from \"./harness/view.ts\";\nexport { createSession } from \"./session/session.ts\";\nexport { MemoryStorage } from \"./storage/memory.ts\";\nexport { defineTask } from \"./tasks.ts\";\nexport type {\n\tCheckpointInfo,\n\tCommitChange,\n\tCommitObservation,\n\tCommitObserver,\n\tCommitOptions,\n\tCommitPersistence,\n\tCommitPublication,\n\tCommitResult,\n\tCommonDocDefinition,\n\tContextEdit,\n\tConversationDocFamilyToken,\n\tConversationDocToken,\n\tConversationId,\n\tConversationOwnership,\n\tConversationQuery,\n\tConversationRecord,\n\tCursor,\n\tDocDefinition,\n\tDocFamilyDefinition,\n\tDocFamilyToken,\n\tDocToken,\n\tDocumentAddress,\n\tDocumentCommitChange,\n\tDocumentContent,\n\tDocumentCopySource,\n\tDocumentCreate,\n\tDocumentId,\n\tDocumentObserver,\n\tDocumentPoint,\n\tDocumentQuery,\n\tDocumentReader,\n\tDocumentRecord,\n\tDocumentSemantics,\n\tDocumentWatch,\n\tEntry,\n\tEntryDraft,\n\tEntryId,\n\tEntryQuery,\n\tEntryRecord,\n\tHookRunner,\n\tHostCallback,\n\tId,\n\tJoinPolicy,\n\tJsonObject,\n\tLatestConversationSemantics,\n\tNextTaskState,\n\tObservation,\n\tObserver,\n\tPage,\n\tPhaseHandler,\n\tReport,\n\tReportFrom,\n\tReportInfo,\n\tReportTask,\n\tRewindableConversationDocFamilyToken,\n\tRewindableConversationDocToken,\n\tRewindableConversationSemantics,\n\tRunningTask,\n\tScanOrder,\n\tSeq,\n\tSession,\n\tSessionDocFamilyToken,\n\tSessionDocToken,\n\tSessionEnd,\n\tSetTimer,\n\tStorage,\n\tStorageWrite,\n\tStoredDocument,\n\tSubmissionCreate,\n\tSubmissionId,\n\tSubmissionQuery,\n\tSubmissionRecord,\n\tSubmissionSettlement,\n\tTableCommitChange,\n\tTask,\n\tTaskDefinition,\n\tTaskDocFamilyToken,\n\tTaskDocToken,\n\tTaskId,\n\tTaskOptions,\n\tTaskOutcome,\n\tTaskOutcomeError,\n\tTaskOwnership,\n\tTaskQuery,\n\tTaskRecord,\n\tTaskRuntime,\n\tTaskState,\n\tTx,\n\tTypedEntry,\n\tTypedEntryDraft,\n} from \"./types.ts\";\nexport { ROOT_CONVERSATION_ID } from \"./types.ts\";\n"]}
|
package/dist/search.d.ts
CHANGED
|
@@ -2,12 +2,28 @@
|
|
|
2
2
|
* BM25 tool search for code mode's `searchTools()` and the `tool_search` tool, a copy of the coding agent's tool search
|
|
3
3
|
* ranking: durable keeps its own copy of what it needs from the coding agent.
|
|
4
4
|
*/
|
|
5
|
+
/** A tool as the ranker sees it: its name, its text, and the text of its namespace. */
|
|
5
6
|
export type SearchDocument = {
|
|
6
7
|
readonly name: string;
|
|
8
|
+
/** Description and parameter names and descriptions; not the name, which the ranker reads from `name`. */
|
|
7
9
|
readonly text: string;
|
|
10
|
+
/** Name, description, and instructions of the tool's namespace. */
|
|
11
|
+
readonly namespaceText?: string;
|
|
8
12
|
};
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Okapi BM25 (k1 1.2, b 0.75) over `text`, with the name and the namespace as separate fields: the names of the best
|
|
15
|
+
* matches, best first; ties keep document order.
|
|
16
|
+
* - A tool that matches more of the query's terms, in any field, ranks above one that matches fewer, whatever their
|
|
17
|
+
* scores: for `screenshot window`, a tool whose description has both words beats `window` whose name has one.
|
|
18
|
+
* - A query term in the name scores more than any number of mentions in the text.
|
|
19
|
+
* - A tool whose whole local name (after the last `__`) is in the query gets a bonus worth one more match of every
|
|
20
|
+
* query term, so among tools matching as many terms, `peekaboo app` finds `mcp__peekaboo__app` over tools that
|
|
21
|
+
* only mention the words.
|
|
22
|
+
* - A query that is exactly a tool's name, or its name after a `__`, ranks that tool first, before coverage.
|
|
23
|
+
*
|
|
24
|
+
* Only `text` is length-normalized, so a long name or long namespace instructions do not lower a tool's score.
|
|
25
|
+
*/
|
|
12
26
|
export declare function rankDocuments(query: string, documents: readonly SearchDocument[], limit: number): string[];
|
|
27
|
+
/** Unicode word segmentation with identifier boundaries and English stop words/singular forms. */
|
|
28
|
+
export declare function tokenize(text: string): string[];
|
|
13
29
|
//# sourceMappingURL=search.d.ts.map
|
package/dist/search.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,cAAc,GAAG;
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,uFAAuF;AACvF,MAAM,MAAM,cAAc,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0GAA0G;IAC1G,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA0C1G;AAsED,kGAAkG;AAClG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAe/C"}
|