@earendil-works/pi-durable 0.99.0 → 0.99.2
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 +435 -46
- package/dist/entries.d.ts +20 -2
- package/dist/entries.d.ts.map +1 -1
- package/dist/entries.js +14 -1
- package/dist/entries.js.map +1 -1
- package/dist/env/index.d.ts +13 -38
- package/dist/env/index.d.ts.map +1 -1
- package/dist/env/index.js +2 -0
- package/dist/env/index.js.map +1 -1
- package/dist/env/node.d.ts.map +1 -1
- package/dist/env/node.js +51 -58
- package/dist/env/node.js.map +1 -1
- package/dist/harness/compaction.d.ts +56 -0
- package/dist/harness/compaction.d.ts.map +1 -0
- package/dist/harness/compaction.js +385 -0
- package/dist/harness/compaction.js.map +1 -0
- package/dist/harness/config.d.ts +10 -1
- package/dist/harness/config.d.ts.map +1 -1
- package/dist/harness/config.js +6 -0
- package/dist/harness/config.js.map +1 -1
- package/dist/harness/context.d.ts +8 -0
- package/dist/harness/context.d.ts.map +1 -1
- package/dist/harness/context.js +32 -21
- package/dist/harness/context.js.map +1 -1
- package/dist/harness/events.d.ts +166 -0
- package/dist/harness/events.d.ts.map +1 -0
- package/dist/harness/events.js +319 -0
- package/dist/harness/events.js.map +1 -0
- package/dist/harness/generation.d.ts +37 -6
- package/dist/harness/generation.d.ts.map +1 -1
- package/dist/harness/generation.js +350 -72
- package/dist/harness/generation.js.map +1 -1
- package/dist/harness/harness.d.ts.map +1 -1
- package/dist/harness/harness.js +124 -3
- package/dist/harness/harness.js.map +1 -1
- package/dist/harness/inbox.d.ts +57 -0
- package/dist/harness/inbox.d.ts.map +1 -0
- package/dist/harness/inbox.js +99 -0
- package/dist/harness/inbox.js.map +1 -0
- package/dist/harness/json.d.ts +10 -0
- package/dist/harness/json.d.ts.map +1 -0
- package/dist/harness/json.js +33 -0
- package/dist/harness/json.js.map +1 -0
- package/dist/harness/live.d.ts +66 -7
- package/dist/harness/live.d.ts.map +1 -1
- package/dist/harness/live.js +71 -7
- package/dist/harness/live.js.map +1 -1
- package/dist/harness/output.d.ts +62 -0
- package/dist/harness/output.d.ts.map +1 -0
- package/dist/harness/output.js +261 -0
- package/dist/harness/output.js.map +1 -0
- package/dist/harness/prompt.d.ts +10 -5
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +66 -13
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/registry.d.ts.map +1 -1
- package/dist/harness/registry.js +11 -2
- package/dist/harness/registry.js.map +1 -1
- package/dist/harness/scheduler.d.ts +37 -12
- package/dist/harness/scheduler.d.ts.map +1 -1
- package/dist/harness/scheduler.js +632 -72
- package/dist/harness/scheduler.js.map +1 -1
- package/dist/harness/submissions.d.ts +12 -7
- package/dist/harness/submissions.d.ts.map +1 -1
- package/dist/harness/submissions.js +72 -33
- package/dist/harness/submissions.js.map +1 -1
- package/dist/harness/tool.d.ts +36 -0
- package/dist/harness/tool.d.ts.map +1 -0
- package/dist/harness/tool.js +412 -0
- package/dist/harness/tool.js.map +1 -0
- package/dist/harness/types.d.ts +185 -11
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/usage.d.ts +18 -0
- package/dist/harness/usage.d.ts.map +1 -0
- package/dist/harness/usage.js +57 -0
- package/dist/harness/usage.js.map +1 -0
- package/dist/harness/view.d.ts +43 -0
- package/dist/harness/view.d.ts.map +1 -0
- package/dist/harness/view.js +194 -0
- package/dist/harness/view.js.map +1 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/session/observation.d.ts +18 -11
- package/dist/session/observation.d.ts.map +1 -1
- package/dist/session/observation.js +24 -13
- package/dist/session/observation.js.map +1 -1
- package/dist/session/session.d.ts +10 -1
- package/dist/session/session.d.ts.map +1 -1
- package/dist/session/session.js +18 -4
- package/dist/session/session.js.map +1 -1
- package/dist/session/transaction.d.ts +10 -1
- package/dist/session/transaction.d.ts.map +1 -1
- package/dist/session/transaction.js +83 -27
- package/dist/session/transaction.js.map +1 -1
- package/dist/storage/jsonl/storage.d.ts +22 -2
- package/dist/storage/jsonl/storage.d.ts.map +1 -1
- package/dist/storage/jsonl/storage.js +1 -1
- package/dist/storage/jsonl/storage.js.map +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/memory.js.map +1 -1
- package/dist/storage/sqlite/migrations.js +1 -1
- package/dist/storage/sqlite/migrations.js.map +1 -1
- package/dist/testing/storage-benchmark.d.ts.map +1 -1
- package/dist/testing/storage-benchmark.js +0 -1
- 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 +34 -2
- package/dist/testing/storage-conformance.js.map +1 -1
- package/dist/tools/bash.d.ts +28 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +69 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit-diff.d.ts +89 -0
- package/dist/tools/edit-diff.d.ts.map +1 -0
- package/dist/tools/edit-diff.js +386 -0
- package/dist/tools/edit-diff.js.map +1 -0
- package/dist/tools/edit.d.ts +18 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +116 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/env.d.ts +5 -0
- package/dist/tools/env.d.ts.map +1 -0
- package/dist/tools/env.js +7 -0
- package/dist/tools/env.js.map +1 -0
- package/dist/tools/file-mutation-queue.d.ts +5 -0
- package/dist/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/tools/file-mutation-queue.js +46 -0
- package/dist/tools/file-mutation-queue.js.map +1 -0
- package/dist/tools/image.d.ts +2 -0
- package/dist/tools/image.d.ts.map +1 -0
- package/dist/tools/image.js +92 -0
- package/dist/tools/image.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/path-utils.d.ts +5 -0
- package/dist/tools/path-utils.d.ts.map +1 -0
- package/dist/tools/path-utils.js +26 -0
- package/dist/tools/path-utils.js.map +1 -0
- package/dist/tools/read.d.ts +17 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +100 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/write.d.ts +10 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +30 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/{env/utils/truncate.d.ts → truncate.d.ts} +1 -17
- package/dist/truncate.d.ts.map +1 -0
- package/dist/truncate.js +146 -0
- package/dist/truncate.js.map +1 -0
- package/dist/types.d.ts +86 -19
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/docs/pico-v5-handoff.md +366 -86
- package/docs/pico-v5.md +1373 -283
- package/package.json +11 -3
- package/dist/env/utils/adaptive-publisher.d.ts +0 -24
- package/dist/env/utils/adaptive-publisher.d.ts.map +0 -1
- package/dist/env/utils/adaptive-publisher.js +0 -79
- package/dist/env/utils/adaptive-publisher.js.map +0 -1
- package/dist/env/utils/output-capture.d.ts +0 -31
- package/dist/env/utils/output-capture.d.ts.map +0 -1
- package/dist/env/utils/output-capture.js +0 -238
- package/dist/env/utils/output-capture.js.map +0 -1
- package/dist/env/utils/truncate.d.ts.map +0 -1
- package/dist/env/utils/truncate.js +0 -294
- package/dist/env/utils/truncate.js.map +0 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type AttachedReplicatedState, type Context } from "@earendil-works/chord";
|
|
2
|
+
import { type Op } from "@earendil-works/chord/delta";
|
|
3
|
+
import type { SessionImpl } from "../session/session.ts";
|
|
4
|
+
import type { CommitPublication, ConversationId, ConversationRecord, EntryRecord, JsonObject, Storage, WatchHandle } from "../types.ts";
|
|
5
|
+
/** Structural mount of one conversation's active transcript and built-in documents (spec §9.3). */
|
|
6
|
+
export type ConversationView = {
|
|
7
|
+
readonly conversation: ConversationRecord;
|
|
8
|
+
/** Raw active entries, as `ContextView.entries`: the head marker, then the non-head entries from its head. */
|
|
9
|
+
readonly entries: readonly EntryRecord[];
|
|
10
|
+
/** `pi.conversation.config`, `pi.live`, `pi.inbox`, and `pi.usage`, keyed by kind; absent documents are absent. */
|
|
11
|
+
readonly docs: Readonly<Record<string, JsonObject>>;
|
|
12
|
+
};
|
|
13
|
+
/** Receives each next revision of a mount, and the Session's close. */
|
|
14
|
+
export type ViewObserver = {
|
|
15
|
+
advance?(value: ConversationView, ops: readonly Op[], context: Context): void;
|
|
16
|
+
/** Every publication, after the mount took it; `ops` are the mount's, possibly none. */
|
|
17
|
+
publication?(before: ConversationView, after: ConversationView, ops: readonly Op[], publication: CommitPublication, context: Context): void;
|
|
18
|
+
closeSession(): void;
|
|
19
|
+
};
|
|
20
|
+
/** The view mounts of a Harness, for adapters built on them. */
|
|
21
|
+
export declare function conversationViews(harness: object): ConversationViews;
|
|
22
|
+
/**
|
|
23
|
+
* The Harness's conversation view mounts: at most one per conversation, built on the Session line by its first
|
|
24
|
+
* observer and dropped with its last. Each mount advances from the Session's commit publications, which are durable.
|
|
25
|
+
*/
|
|
26
|
+
export declare class ConversationViews {
|
|
27
|
+
#private;
|
|
28
|
+
constructor(session: SessionImpl, storage: Storage);
|
|
29
|
+
/** A disposable read-only Chord state of the view. */
|
|
30
|
+
state(id: ConversationId, context: Context): Promise<AttachedReplicatedState<ConversationView>>;
|
|
31
|
+
/** A serialized exact-frame watch of the view; cancelling `context` stops it. */
|
|
32
|
+
watch(id: ConversationId, context: Context): Promise<WatchHandle<ConversationView>>;
|
|
33
|
+
/**
|
|
34
|
+
* Register an observer created from the current revision, atomically on the Session line: it sees every later
|
|
35
|
+
* publication and nothing earlier. `create` may read committed Storage, still on the line. `release` drops it, and
|
|
36
|
+
* the mount with its last observer.
|
|
37
|
+
*/
|
|
38
|
+
attach<O extends ViewObserver>(id: ConversationId, create: (value: ConversationView, release: () => void, storage: Storage) => O | Promise<O>, context: Context): Promise<{
|
|
39
|
+
observer: O;
|
|
40
|
+
detach: () => void;
|
|
41
|
+
}>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/harness/view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,OAAO,EAAmC,MAAM,uBAAuB,CAAC;AAEpH,OAAO,EAAqC,KAAK,EAAE,EAAa,MAAM,6BAA6B,CAAC;AAEpG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EACX,iBAAiB,EAEjB,cAAc,EACd,kBAAkB,EAElB,WAAW,EACX,UAAU,EACV,OAAO,EACP,WAAW,EACX,MAAM,aAAa,CAAC;AAQrB,mGAAmG;AACnG,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAC;IAC1C,8GAA8G;IAC9G,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,mHAAmH;IACnH,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;CACpD,CAAC;AAEF,uEAAuE;AACvE,MAAM,MAAM,YAAY,GAAG;IAC1B,OAAO,CAAC,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9E,wFAAwF;IACxF,WAAW,CAAC,CACX,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,gBAAgB,EACvB,GAAG,EAAE,SAAS,EAAE,EAAE,EAClB,WAAW,EAAE,iBAAiB,EAC9B,OAAO,EAAE,OAAO,GACd,IAAI,CAAC;IACR,YAAY,IAAI,IAAI,CAAC;CACrB,CAAC;AAoBF,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAIpE;AAED;;;GAGG;AACH,qBAAa,iBAAiB;;IAM7B,YAAY,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAajD;IAED,sDAAsD;IAChD,KAAK,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,CAAC,CAYpG;IAED,iFAAiF;IAC3E,KAAK,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAaxF;IAED;;;;OAIG;IACH,MAAM,CAAC,CAAC,SAAS,YAAY,EAC5B,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,OAAO,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC1F,OAAO,EAAE,OAAO,GACd,OAAO,CAAC;QAAE,QAAQ,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAe9C;CAiBD"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { replicatedState } from "@earendil-works/chord";
|
|
2
|
+
import { withoutAbortSignal } from "@earendil-works/chord/context";
|
|
3
|
+
import { applyImmutable } from "@earendil-works/chord/delta";
|
|
4
|
+
import { CommittedStateSource, CommittedWatch } from "../session/observation.js";
|
|
5
|
+
import { ConversationConfig } from "./config.js";
|
|
6
|
+
import { activeEntries, captureContextBounds } from "./context.js";
|
|
7
|
+
import { InboxDoc } from "./inbox.js";
|
|
8
|
+
import { LiveDoc } from "./live.js";
|
|
9
|
+
import { UsageDoc } from "./usage.js";
|
|
10
|
+
import { closedError } from "./util.js";
|
|
11
|
+
const MOUNTED = [
|
|
12
|
+
ConversationConfig,
|
|
13
|
+
LiveDoc,
|
|
14
|
+
InboxDoc,
|
|
15
|
+
UsageDoc,
|
|
16
|
+
];
|
|
17
|
+
const MOUNTED_KINDS = new Set(MOUNTED.map((token) => token.definition.kind));
|
|
18
|
+
const VIEWS = new WeakMap();
|
|
19
|
+
/** The view mounts of a Harness, for adapters built on them. */
|
|
20
|
+
export function conversationViews(harness) {
|
|
21
|
+
const views = VIEWS.get(harness);
|
|
22
|
+
if (views === undefined)
|
|
23
|
+
throw new Error("Not a Harness");
|
|
24
|
+
return views;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The Harness's conversation view mounts: at most one per conversation, built on the Session line by its first
|
|
28
|
+
* observer and dropped with its last. Each mount advances from the Session's commit publications, which are durable.
|
|
29
|
+
*/
|
|
30
|
+
export class ConversationViews {
|
|
31
|
+
#session;
|
|
32
|
+
#storage;
|
|
33
|
+
#mounts = new Map();
|
|
34
|
+
#closed = false;
|
|
35
|
+
constructor(session, storage) {
|
|
36
|
+
this.#session = session;
|
|
37
|
+
this.#storage = storage;
|
|
38
|
+
VIEWS.set(session, this);
|
|
39
|
+
session.subscribeCommits((publication, context) => {
|
|
40
|
+
for (const [id, mount] of this.#mounts)
|
|
41
|
+
advance(id, mount, publication, context);
|
|
42
|
+
});
|
|
43
|
+
session.subscribeClose(() => {
|
|
44
|
+
this.#closed = true;
|
|
45
|
+
for (const mount of this.#mounts.values())
|
|
46
|
+
for (const observer of [...mount.observers])
|
|
47
|
+
observer.closeSession();
|
|
48
|
+
this.#mounts.clear();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** A disposable read-only Chord state of the view. */
|
|
52
|
+
async state(id, context) {
|
|
53
|
+
const { observer, detach } = await this.attach(id, (value, release) => new CommittedStateSource(value, release), context);
|
|
54
|
+
try {
|
|
55
|
+
return replicatedState(observer);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
detach();
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** A serialized exact-frame watch of the view; cancelling `context` stops it. */
|
|
63
|
+
async watch(id, context) {
|
|
64
|
+
const { observer } = await this.attach(id, (value, release) => new CommittedWatch(value, release), context);
|
|
65
|
+
const signal = context.abortSignal;
|
|
66
|
+
if (signal?.aborted) {
|
|
67
|
+
observer.cancel();
|
|
68
|
+
throw signal.reason;
|
|
69
|
+
}
|
|
70
|
+
if (signal !== undefined)
|
|
71
|
+
observer.observeCancellation(signal);
|
|
72
|
+
return observer;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Register an observer created from the current revision, atomically on the Session line: it sees every later
|
|
76
|
+
* publication and nothing earlier. `create` may read committed Storage, still on the line. `release` drops it, and
|
|
77
|
+
* the mount with its last observer.
|
|
78
|
+
*/
|
|
79
|
+
attach(id, create, context) {
|
|
80
|
+
return this.#session.readOnLine(async () => {
|
|
81
|
+
const mount = this.#mounts.get(id) ?? (await this.#build(id, context));
|
|
82
|
+
const detach = () => {
|
|
83
|
+
mount.observers.delete(observer);
|
|
84
|
+
if (mount.observers.size === 0 && this.#mounts.get(id) === mount)
|
|
85
|
+
this.#mounts.delete(id);
|
|
86
|
+
};
|
|
87
|
+
const observer = await create(mount.value, detach, this.#storage);
|
|
88
|
+
// Close or cancellation may begin while the mount hydrates; register nothing then.
|
|
89
|
+
if (this.#closed)
|
|
90
|
+
throw closedError();
|
|
91
|
+
context.abortSignal?.throwIfAborted();
|
|
92
|
+
this.#mounts.set(id, mount);
|
|
93
|
+
mount.observers.add(observer);
|
|
94
|
+
return { observer, detach };
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
async #build(id, context) {
|
|
98
|
+
const conversation = await this.#storage.conversation(id, context);
|
|
99
|
+
if (conversation === undefined)
|
|
100
|
+
throw new Error(`Conversation ${id} does not exist`);
|
|
101
|
+
const bounds = await captureContextBounds(this.#storage, id, context);
|
|
102
|
+
const entries = await activeEntries(this.#storage, id, bounds, context);
|
|
103
|
+
const docs = {};
|
|
104
|
+
const incarnations = new Map();
|
|
105
|
+
for (const token of MOUNTED) {
|
|
106
|
+
const loaded = await this.#session.conversationDocumentOnLine(token, id, context);
|
|
107
|
+
if (loaded === undefined)
|
|
108
|
+
continue;
|
|
109
|
+
docs[token.definition.kind] = loaded.value;
|
|
110
|
+
incarnations.set(token.definition.kind, { id: loaded.record.id, version: loaded.version });
|
|
111
|
+
}
|
|
112
|
+
return { value: { conversation, entries, docs }, docs: incarnations, observers: new Set() };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** Derive the mount's operations from one publication, apply them, and hand the revision to every observer. */
|
|
116
|
+
function advance(id, mount, publication, context) {
|
|
117
|
+
const docOps = [];
|
|
118
|
+
const entryOps = [];
|
|
119
|
+
let entries = mount.value.entries;
|
|
120
|
+
// Entry writes are published in ID order.
|
|
121
|
+
for (const change of publication.changes) {
|
|
122
|
+
if (change.type === "entry" && change.value.conversationId === id) {
|
|
123
|
+
const entry = change.value;
|
|
124
|
+
const value = entry;
|
|
125
|
+
if (entry.head === undefined) {
|
|
126
|
+
entryOps.push(["p", ["entries"], entries.length, 0, [value]]);
|
|
127
|
+
entries = [...entries, entry];
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
// A head marker keeps the non-head entries from its head, which are always a suffix, and goes in front.
|
|
131
|
+
const target = entry.head;
|
|
132
|
+
let kept = entries.findIndex((candidate) => candidate.head === undefined && candidate.id >= target);
|
|
133
|
+
if (kept < 0)
|
|
134
|
+
kept = entries.length;
|
|
135
|
+
entryOps.push(["p", ["entries"], 0, kept, [value]]);
|
|
136
|
+
entries = [entry, ...entries.slice(kept)];
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (change.type !== "document" || change.conversationId !== id)
|
|
140
|
+
continue;
|
|
141
|
+
const kind = change.record.kind;
|
|
142
|
+
if (!MOUNTED_KINDS.has(kind) || change.record.key !== undefined)
|
|
143
|
+
continue;
|
|
144
|
+
const path = ["docs", kind];
|
|
145
|
+
const mounted = mount.docs.get(kind);
|
|
146
|
+
if (change.value === null) {
|
|
147
|
+
if (mounted?.id !== change.record.id)
|
|
148
|
+
continue;
|
|
149
|
+
mount.docs.delete(kind);
|
|
150
|
+
docOps.push(["d", path]);
|
|
151
|
+
}
|
|
152
|
+
else if (mounted?.id === change.record.id && mounted.version === change.version) {
|
|
153
|
+
for (const op of change.ops)
|
|
154
|
+
docOps.push(prefixed(op, path));
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
mount.docs.set(kind, { id: change.record.id, version: change.version });
|
|
158
|
+
docOps.push(["s", path, change.value]);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const before = mount.value;
|
|
162
|
+
const ops = [...docOps, ...entryOps];
|
|
163
|
+
const frameContext = withoutAbortSignal(context);
|
|
164
|
+
if (ops.length > 0) {
|
|
165
|
+
const value = docOps.length === 0 ? mount.value : applyImmutable(mount.value, docOps);
|
|
166
|
+
mount.value = entries === value.entries ? value : { ...value, entries };
|
|
167
|
+
for (const observer of [...mount.observers])
|
|
168
|
+
observer.advance?.(mount.value, ops, frameContext);
|
|
169
|
+
}
|
|
170
|
+
for (const observer of [...mount.observers]) {
|
|
171
|
+
observer.publication?.(before, mount.value, ops, publication, frameContext);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** `op` moved under `prefix`; a root replacement becomes a set of the prefix. */
|
|
175
|
+
function prefixed(op, prefix) {
|
|
176
|
+
const at = (path) => [...prefix, ...path];
|
|
177
|
+
switch (op[0]) {
|
|
178
|
+
case "r":
|
|
179
|
+
return ["s", prefix, op[1]];
|
|
180
|
+
case "p":
|
|
181
|
+
return ["p", at(op[1]), op[2], op[3], op[4]];
|
|
182
|
+
case "m":
|
|
183
|
+
return ["m", at(op[1]), op[2]];
|
|
184
|
+
case "s":
|
|
185
|
+
return ["s", at(op[1]), op[2]];
|
|
186
|
+
case "d":
|
|
187
|
+
return ["d", at(op[1])];
|
|
188
|
+
case "a":
|
|
189
|
+
return ["a", at(op[1]), op[2]];
|
|
190
|
+
case "t":
|
|
191
|
+
return ["t", at(op[1]), op[2]];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/harness/view.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8D,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACpH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAyC,MAAM,6BAA6B,CAAC;AACpG,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAajF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAyBxC,MAAM,OAAO,GAAG;IACf,kBAAkB;IAClB,OAAO;IACP,QAAQ;IACR,QAAQ;CACkD,CAAC;AAC5D,MAAM,aAAa,GAAwB,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AAUlG,MAAM,KAAK,GAAG,IAAI,OAAO,EAA6B,CAAC;AAEvD,gEAAgE;AAChE,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAChD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IACpB,QAAQ,CAAc;IACtB,QAAQ,CAAU;IAClB,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IACpD,OAAO,GAAG,KAAK,CAAC;IAEhB,YAAY,OAAoB,EAAE,OAAgB;QACjD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACzB,OAAO,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE;YACjD,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO;gBAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE;YAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;gBACxC,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;oBAAE,QAAQ,CAAC,YAAY,EAAE,CAAC;YACtE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,sDAAsD;IACtD,KAAK,CAAC,KAAK,CAAC,EAAkB,EAAE,OAAgB;QAC/C,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAC7C,EAAE,EACF,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,oBAAoB,CAAmB,KAAK,EAAE,OAAO,CAAC,EAC9E,OAAO,CACP,CAAC;QACF,IAAI,CAAC;YACJ,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,EAAE,CAAC;YACT,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,KAAK,CAAC,EAAkB,EAAE,OAAgB;QAC/C,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CACrC,EAAE,EACF,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,cAAc,CAAmB,KAAK,EAAE,OAAO,CAAC,EACxE,OAAO,CACP,CAAC;QACF,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;QACnC,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACrB,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,MAAM,CAAC,MAAM,CAAC;QACrB,CAAC;QACD,IAAI,MAAM,KAAK,SAAS;YAAE,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC/D,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,MAAM,CACL,EAAkB,EAClB,MAA0F,EAC1F,OAAgB;QAEhB,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;YACvE,MAAM,MAAM,GAAG,GAAS,EAAE;gBACzB,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACjC,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,KAAK;oBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC3F,CAAC,CAAC;YACF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClE,mFAAmF;YACnF,IAAI,IAAI,CAAC,OAAO;gBAAE,MAAM,WAAW,EAAE,CAAC;YACtC,OAAO,CAAC,WAAW,EAAE,cAAc,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC5B,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAkB,EAAE,OAAgB;QAChD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACnE,IAAI,YAAY,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;QACrF,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QACxE,MAAM,IAAI,GAA+B,EAAE,CAAC;QAC5C,MAAM,YAAY,GAAG,IAAI,GAAG,EAA+C,CAAC;QAC5E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC,KAAK,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;YAClF,IAAI,MAAM,KAAK,SAAS;gBAAE,SAAS;YACnC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;YAC3C,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IAC7F,CAAC;CACD;AAED,+GAA+G;AAC/G,SAAS,OAAO,CAAC,EAAkB,EAAE,KAAY,EAAE,WAA8B,EAAE,OAAgB;IAClG,MAAM,MAAM,GAAS,EAAE,CAAC;IACxB,MAAM,QAAQ,GAAS,EAAE,CAAC;IAC1B,IAAI,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;IAClC,0CAA0C;IAC1C,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;QAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,cAAc,KAAK,EAAE,EAAE,CAAC;YACnE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC3B,MAAM,KAAK,GAAG,KAA6B,CAAC;YAC5C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC9B,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC9D,OAAO,GAAG,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,CAAC;gBAC9B,SAAS;YACV,CAAC;YACD,wGAAwG;YACxG,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;YAC1B,IAAI,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS,IAAI,SAAS,CAAC,EAAE,IAAI,MAAM,CAAC,CAAC;YACpG,IAAI,IAAI,GAAG,CAAC;gBAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;YACpC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACpD,OAAO,GAAG,CAAC,KAAK,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1C,SAAS;QACV,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,cAAc,KAAK,EAAE;YAAE,SAAS;QACzE,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;QAChC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,SAAS;YAAE,SAAS;QAC1E,MAAM,IAAI,GAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC3B,IAAI,OAAO,EAAE,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE;gBAAE,SAAS;YAC/C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,OAAO,EAAE,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,OAAO,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;YACnF,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,GAAG;gBAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9D,CAAC;aAAM,CAAC;YACP,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAQ,EAAE,CAAC,CAAC;YACzE,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;IAC3B,MAAM,GAAG,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC;IACrC,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACtF,KAAK,CAAC,KAAK,GAAG,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,CAAC;QACxE,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;YAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC;IACjG,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;IAC7E,CAAC;AACF,CAAC;AAED,iFAAiF;AACjF,SAAS,QAAQ,CAAC,EAAM,EAAE,MAAoB;IAC7C,MAAM,EAAE,GAAG,CAAC,IAAU,EAAgB,EAAE,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,IAAI,CAA4B,CAAC;IACzF,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACf,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,KAAK,GAAG;YACP,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;AACF,CAAC","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 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 { ConversationConfig } from \"./config.ts\";\nimport { activeEntries, captureContextBounds } from \"./context.ts\";\nimport { InboxDoc } from \"./inbox.ts\";\nimport { LiveDoc } from \"./live.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/** `pi.conversation.config`, `pi.live`, `pi.inbox`, and `pi.usage`, 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(): void;\n};\n\nconst MOUNTED = [\n\tConversationConfig,\n\tLiveDoc,\n\tInboxDoc,\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.subscribeCommits((publication, context) => {\n\t\t\tfor (const [id, mount] of this.#mounts) advance(id, mount, publication, context);\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]) observer.closeSession();\n\t\t\tthis.#mounts.clear();\n\t\t});\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);\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) => new CommittedWatch<ConversationView>(value, release),\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();\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/** Derive the mount's operations from one publication, apply them, and hand the revision to every observer. */\nfunction advance(id: ConversationId, mount: Mount, publication: CommitPublication, context: Context): 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]) observer.advance?.(mount.value, ops, frameContext);\n\t}\n\tfor (const observer of [...mount.observers]) {\n\t\tobserver.publication?.(before, mount.value, ops, publication, frameContext);\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,15 +1,21 @@
|
|
|
1
1
|
export { defineDoc, defineDocFamily } from "./documents.ts";
|
|
2
|
-
export { AssistantEntry, defineEntry, SystemEntry, ToolResultEntry, UserEntry } from "./entries.ts";
|
|
2
|
+
export { AssistantEntry, CompactionEntry, defineEntry, ResetEntry, SystemEntry, ToolResultEntry, UserEntry, } from "./entries.ts";
|
|
3
3
|
export { ConversationBusy, ReadAfterWrite, StorageRejected } from "./errors.ts";
|
|
4
|
+
export { type CompactionCheckpoint, type CompactionInput, CompactionTask, type SummaryRequest, } from "./harness/compaction.ts";
|
|
4
5
|
export { ConversationConfig, type ConversationConfigState } from "./harness/config.ts";
|
|
6
|
+
export { type AgentEvent, type AgentEventStream, type MessageChange, type SnapshotEvent, watchEvents, } from "./harness/events.ts";
|
|
5
7
|
export { type GenerationCheckpoint, type GenerationInput, type GenerationResult, GenerationTask, } from "./harness/generation.ts";
|
|
6
8
|
export { Harness } from "./harness/harness.ts";
|
|
7
|
-
export {
|
|
9
|
+
export { InboxDoc, type InboxItem, type InboxState } from "./harness/inbox.ts";
|
|
10
|
+
export { type CompactionStatus, LiveDoc, type LiveState, type ToolSlot } from "./harness/live.ts";
|
|
8
11
|
export { createRegistry } from "./harness/registry.ts";
|
|
9
|
-
export
|
|
12
|
+
export { ToolTask, type ToolTaskCheckpoint, type ToolTaskInput, type ToolTaskResult } from "./harness/tool.ts";
|
|
13
|
+
export type { AnyTask, CompactionHooks, CompactionPolicy, CompactionReason, CompactionResult, ContextView, Conversation, ConversationAbortOptions, ConversationCreateOptions, ConversationHandle, ConversationInit, ConversationRetryPolicy, ConversationSetup, ConversationStreamOptions, GenerationHooks, HarnessInspection, HarnessOptions, HookApi, HookRegistration, HookResult, HookScope, HooksOf, InputSubmissionDraft, ModelRef, PromptInput, PromptSection, PromptSectionWrapper, QueueMode, Registration, Registry, RegistryFailure, RegistryReader, RegistrySnapshot, SettledSubmissionRecord, SettledTask, Submission, SubmissionDraft, TaskInspection, ToolControl, ToolDiagnostic, ToolExecutionApi, ToolExecutionMode, ToolExecutionResult, ToolHooks, ToolRegistration, ToolWrapper, UserInput, } from "./harness/types.ts";
|
|
14
|
+
export { UsageDoc, type UsageState } from "./harness/usage.ts";
|
|
15
|
+
export type { ConversationView } from "./harness/view.ts";
|
|
10
16
|
export { createSession } from "./session/session.ts";
|
|
11
17
|
export { MemoryStorage } from "./storage/memory.ts";
|
|
12
18
|
export { defineTask } from "./tasks.ts";
|
|
13
|
-
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, DocumentState, DocumentWatch, Entry, EntryDraft, EntryId, EntryQuery, EntryRecord, Id, JsonObject, LatestConversationSemantics, NextTaskState, Page, PhaseHandler, RewindableConversationDocFamilyToken, RewindableConversationDocToken, RewindableConversationSemantics, RunningTask, Seq, Session, SessionDocFamilyToken, SessionDocToken, Storage, StorageWrite, StoredDocument, SubmissionCreate, SubmissionId, SubmissionQuery, SubmissionRecord, SubmissionSettlement, TableCommitChange, Task, TaskDefinition, TaskDocFamilyToken, TaskDocToken, TaskId, TaskOptions, TaskOutcome, TaskOutcomeError, TaskQuery, TaskRecord, TaskRuntime, TaskState, Tx, TypedEntry, TypedEntryDraft, WatchEnd, WatchHandle, } from "./types.ts";
|
|
19
|
+
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, DocumentState, DocumentWatch, Entry, EntryDraft, EntryId, EntryQuery, EntryRecord, HookRunner, Id, JoinPolicy, JsonObject, LatestConversationSemantics, NextTaskState, Page, PhaseHandler, RewindableConversationDocFamilyToken, RewindableConversationDocToken, RewindableConversationSemantics, RunningTask, Seq, Session, SessionDocFamilyToken, SessionDocToken, 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, WatchEnd, WatchHandle, } from "./types.ts";
|
|
14
20
|
export { ROOT_CONVERSATION_ID } from "./types.ts";
|
|
15
21
|
//# 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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
export { defineDoc, defineDocFamily } from "./documents.js";
|
|
2
|
-
export { AssistantEntry, defineEntry, SystemEntry, ToolResultEntry, UserEntry } from "./entries.js";
|
|
2
|
+
export { AssistantEntry, CompactionEntry, defineEntry, ResetEntry, SystemEntry, ToolResultEntry, UserEntry, } from "./entries.js";
|
|
3
3
|
export { ConversationBusy, ReadAfterWrite, StorageRejected } from "./errors.js";
|
|
4
|
+
export { CompactionTask, } from "./harness/compaction.js";
|
|
4
5
|
export { ConversationConfig } from "./harness/config.js";
|
|
6
|
+
export { watchEvents, } from "./harness/events.js";
|
|
5
7
|
export { GenerationTask, } from "./harness/generation.js";
|
|
6
8
|
export { Harness } from "./harness/harness.js";
|
|
9
|
+
export { InboxDoc } from "./harness/inbox.js";
|
|
7
10
|
export { LiveDoc } from "./harness/live.js";
|
|
8
11
|
export { createRegistry } from "./harness/registry.js";
|
|
12
|
+
export { ToolTask } from "./harness/tool.js";
|
|
13
|
+
export { UsageDoc } from "./harness/usage.js";
|
|
9
14
|
export { createSession } from "./session/session.js";
|
|
10
15
|
export { MemoryStorage } from "./storage/memory.js";
|
|
11
16
|
export { defineTask } from "./tasks.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","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,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAGN,cAAc,GAEd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAgC,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAKN,WAAW,GACX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAIN,cAAc,GACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAmC,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAyB,OAAO,EAAiC,MAAM,mBAAmB,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAoE,MAAM,mBAAmB,CAAC;AAkD/G,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;AAiFxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC","sourcesContent":["export { 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 { ConversationBusy, ReadAfterWrite, StorageRejected } from \"./errors.ts\";\nexport {\n\ttype CompactionCheckpoint,\n\ttype CompactionInput,\n\tCompactionTask,\n\ttype SummaryRequest,\n} from \"./harness/compaction.ts\";\nexport { ConversationConfig, type ConversationConfigState } from \"./harness/config.ts\";\nexport {\n\ttype AgentEvent,\n\ttype AgentEventStream,\n\ttype MessageChange,\n\ttype SnapshotEvent,\n\twatchEvents,\n} from \"./harness/events.ts\";\nexport {\n\ttype GenerationCheckpoint,\n\ttype GenerationInput,\n\ttype GenerationResult,\n\tGenerationTask,\n} from \"./harness/generation.ts\";\nexport { Harness } from \"./harness/harness.ts\";\nexport { InboxDoc, type InboxItem, type InboxState } from \"./harness/inbox.ts\";\nexport { type CompactionStatus, LiveDoc, type LiveState, type ToolSlot } from \"./harness/live.ts\";\nexport { createRegistry } from \"./harness/registry.ts\";\nexport { ToolTask, type ToolTaskCheckpoint, type ToolTaskInput, type ToolTaskResult } from \"./harness/tool.ts\";\nexport type {\n\tAnyTask,\n\tCompactionHooks,\n\tCompactionPolicy,\n\tCompactionReason,\n\tCompactionResult,\n\tContextView,\n\tConversation,\n\tConversationAbortOptions,\n\tConversationCreateOptions,\n\tConversationHandle,\n\tConversationInit,\n\tConversationRetryPolicy,\n\tConversationSetup,\n\tConversationStreamOptions,\n\tGenerationHooks,\n\tHarnessInspection,\n\tHarnessOptions,\n\tHookApi,\n\tHookRegistration,\n\tHookResult,\n\tHookScope,\n\tHooksOf,\n\tInputSubmissionDraft,\n\tModelRef,\n\tPromptInput,\n\tPromptSection,\n\tPromptSectionWrapper,\n\tQueueMode,\n\tRegistration,\n\tRegistry,\n\tRegistryFailure,\n\tRegistryReader,\n\tRegistrySnapshot,\n\tSettledSubmissionRecord,\n\tSettledTask,\n\tSubmission,\n\tSubmissionDraft,\n\tTaskInspection,\n\tToolControl,\n\tToolDiagnostic,\n\tToolExecutionApi,\n\tToolExecutionMode,\n\tToolExecutionResult,\n\tToolHooks,\n\tToolRegistration,\n\tToolWrapper,\n\tUserInput,\n} from \"./harness/types.ts\";\nexport { UsageDoc, type UsageState } from \"./harness/usage.ts\";\nexport type { ConversationView } 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\tCommitPublication,\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\tDocumentState,\n\tDocumentWatch,\n\tEntry,\n\tEntryDraft,\n\tEntryId,\n\tEntryQuery,\n\tEntryRecord,\n\tHookRunner,\n\tId,\n\tJoinPolicy,\n\tJsonObject,\n\tLatestConversationSemantics,\n\tNextTaskState,\n\tPage,\n\tPhaseHandler,\n\tRewindableConversationDocFamilyToken,\n\tRewindableConversationDocToken,\n\tRewindableConversationSemantics,\n\tRunningTask,\n\tSeq,\n\tSession,\n\tSessionDocFamilyToken,\n\tSessionDocToken,\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\tWatchEnd,\n\tWatchHandle,\n} from \"./types.ts\";\nexport { ROOT_CONVERSATION_ID } from \"./types.ts\";\n"]}
|
|
@@ -4,25 +4,32 @@ import type { JsonObject, WatchEnd, WatchHandle } from "../types.ts";
|
|
|
4
4
|
export type ObservedDocumentValue = Readonly<JsonObject> | null;
|
|
5
5
|
/** Canonical terminal update for a retired document incarnation. */
|
|
6
6
|
export declare const RETIREMENT_OPERATIONS: readonly Op[];
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Session-to-Chord bridge owned one-to-one by one attached state: a document, or a conversation view. A `null` value
|
|
9
|
+
* retires it. @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare class CommittedStateSource<T = ObservedDocumentValue> implements ReplicatedStateSource<T> {
|
|
9
12
|
#private;
|
|
10
|
-
constructor(value:
|
|
11
|
-
attach(): ReplicatedStateSourceAttachment<
|
|
12
|
-
advance(value:
|
|
13
|
+
constructor(value: T, release: () => void);
|
|
14
|
+
attach(): ReplicatedStateSourceAttachment<T>;
|
|
15
|
+
advance(value: T, ops: readonly Op[], context: Context): void;
|
|
13
16
|
closeSession(): void;
|
|
14
17
|
}
|
|
15
|
-
/**
|
|
16
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Serialized exact-frame watch bound to one document incarnation or conversation view. A `null` value retires it.
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export declare class CommittedWatch<T = ObservedDocumentValue> implements WatchHandle<T> {
|
|
17
23
|
#private;
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
/** `replace` gives the value an overflow delivers; by default the newest value. */
|
|
25
|
+
constructor(value: T, detach: () => void, replace?: () => T);
|
|
26
|
+
get value(): T;
|
|
20
27
|
get closed(): Promise<WatchEnd>;
|
|
21
|
-
start(listener: (value:
|
|
28
|
+
start(listener: (value: T, ops: readonly Op[], context: Context) => Promise<void>): void;
|
|
22
29
|
stop(): Promise<WatchEnd>;
|
|
23
30
|
observeCancellation(signal: AbortSignal): void;
|
|
24
31
|
cancel(): void;
|
|
25
32
|
closeSession(): void;
|
|
26
|
-
advance(value:
|
|
33
|
+
advance(value: T, ops: readonly Op[], context: Context): void;
|
|
27
34
|
}
|
|
28
35
|
//# sourceMappingURL=observation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../../src/session/observation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,OAAO,
|
|
1
|
+
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../../src/session/observation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,OAAO,EAEP,qBAAqB,EACrB,+BAA+B,EAE/B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAErE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;AAKhE,oEAAoE;AACpE,eAAO,MAAM,qBAAqB,EAAE,SAAS,EAAE,EAAkB,CAAC;AAElE;;;GAGG;AACH,qBAAa,oBAAoB,CAAC,CAAC,GAAG,qBAAqB,CAAE,YAAW,qBAAqB,CAAC,CAAC,CAAC;;IAS/F,YAAY,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,IAAI,EAGxC;IAED,MAAM,IAAI,+BAA+B,CAAC,CAAC,CAAC,CAQ3C;IAED,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAY5D;IAED,YAAY,IAAI,IAAI,CAInB;CAUD;AA2ED;;;GAGG;AACH,qBAAa,cAAc,CAAC,CAAC,GAAG,qBAAqB,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;;IAkB/E,mFAAmF;IACnF,YAAY,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAO1D;IAED,IAAI,KAAK,IAAI,CAAC,CAEb;IAED,IAAI,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,CAE9B;IAED,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAMvF;IAED,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,CAGxB;IAED,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAO7C;IAED,MAAM,IAAI,IAAI,CAEb;IAED,YAAY,IAAI,IAAI,CAEnB;IAED,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAW5D;CAiED"}
|
|
@@ -3,10 +3,14 @@ import { withoutAbortSignal } from "@earendil-works/chord/context";
|
|
|
3
3
|
const MAX_PENDING_WATCH_FRAMES = 100;
|
|
4
4
|
/** Canonical terminal update for a retired document incarnation. */
|
|
5
5
|
export const RETIREMENT_OPERATIONS = [["r", null]];
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Session-to-Chord bridge owned one-to-one by one attached state: a document, or a conversation view. A `null` value
|
|
8
|
+
* retires it. @internal
|
|
9
|
+
*/
|
|
10
|
+
export class CommittedStateSource {
|
|
8
11
|
#attachments = new Set();
|
|
9
12
|
#release;
|
|
13
|
+
/** Released on disposal. */
|
|
10
14
|
#value;
|
|
11
15
|
#cursor = 0;
|
|
12
16
|
#retired = false;
|
|
@@ -17,7 +21,7 @@ export class SessionDocumentSource {
|
|
|
17
21
|
}
|
|
18
22
|
attach() {
|
|
19
23
|
if (this.#closed)
|
|
20
|
-
throw new Error("
|
|
24
|
+
throw new Error("State source is closed");
|
|
21
25
|
const attachment = new SessionSourceAttachment({ value: this.#value, cursor: this.#cursor }, () => {
|
|
22
26
|
this.#attachments.delete(attachment);
|
|
23
27
|
if (this.#attachments.size === 0)
|
|
@@ -53,7 +57,7 @@ export class SessionDocumentSource {
|
|
|
53
57
|
if (this.#closed)
|
|
54
58
|
return;
|
|
55
59
|
this.#closed = true;
|
|
56
|
-
this.#value =
|
|
60
|
+
this.#value = undefined;
|
|
57
61
|
const release = this.#release;
|
|
58
62
|
this.#release = undefined;
|
|
59
63
|
release?.();
|
|
@@ -74,9 +78,9 @@ class SessionSourceAttachment {
|
|
|
74
78
|
}
|
|
75
79
|
activate(listener) {
|
|
76
80
|
if (this.#activated)
|
|
77
|
-
throw new Error("
|
|
81
|
+
throw new Error("State attachment is already active");
|
|
78
82
|
if (this.#disposed)
|
|
79
|
-
throw new Error("
|
|
83
|
+
throw new Error("State attachment is disposed");
|
|
80
84
|
this.#activated = true;
|
|
81
85
|
this.#listener = listener;
|
|
82
86
|
this.#drain();
|
|
@@ -130,9 +134,13 @@ class SessionSourceAttachment {
|
|
|
130
134
|
}
|
|
131
135
|
}
|
|
132
136
|
}
|
|
133
|
-
/**
|
|
134
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Serialized exact-frame watch bound to one document incarnation or conversation view. A `null` value retires it.
|
|
139
|
+
* @internal
|
|
140
|
+
*/
|
|
141
|
+
export class CommittedWatch {
|
|
135
142
|
#detach;
|
|
143
|
+
#replace;
|
|
136
144
|
#closedPromise;
|
|
137
145
|
#pending = [];
|
|
138
146
|
#resolveClosed;
|
|
@@ -147,9 +155,11 @@ export class SessionDocumentWatch {
|
|
|
147
155
|
#resolved = false;
|
|
148
156
|
#cancellationSignal;
|
|
149
157
|
#cancellationListener;
|
|
150
|
-
|
|
158
|
+
/** `replace` gives the value an overflow delivers; by default the newest value. */
|
|
159
|
+
constructor(value, detach, replace) {
|
|
151
160
|
this.#value = value;
|
|
152
161
|
this.#detach = detach;
|
|
162
|
+
this.#replace = replace;
|
|
153
163
|
this.#closedPromise = new Promise((resolve) => {
|
|
154
164
|
this.#resolveClosed = resolve;
|
|
155
165
|
});
|
|
@@ -162,9 +172,9 @@ export class SessionDocumentWatch {
|
|
|
162
172
|
}
|
|
163
173
|
start(listener) {
|
|
164
174
|
if (this.#started)
|
|
165
|
-
throw new Error("
|
|
175
|
+
throw new Error("Watch is already started");
|
|
166
176
|
if (this.#end !== undefined)
|
|
167
|
-
throw new Error("
|
|
177
|
+
throw new Error("Watch is stopped");
|
|
168
178
|
this.#started = true;
|
|
169
179
|
this.#listener = listener;
|
|
170
180
|
if (this.#pending.length > 0)
|
|
@@ -176,7 +186,7 @@ export class SessionDocumentWatch {
|
|
|
176
186
|
}
|
|
177
187
|
observeCancellation(signal) {
|
|
178
188
|
if (this.#cancellationSignal !== undefined)
|
|
179
|
-
throw new Error("
|
|
189
|
+
throw new Error("Watch cancellation is already installed");
|
|
180
190
|
if (this.#end !== undefined)
|
|
181
191
|
return;
|
|
182
192
|
this.#cancellationSignal = signal;
|
|
@@ -198,7 +208,8 @@ export class SessionDocumentWatch {
|
|
|
198
208
|
this.#retired = true;
|
|
199
209
|
if (this.#pending.length >= MAX_PENDING_WATCH_FRAMES) {
|
|
200
210
|
this.#pending.length = 0;
|
|
201
|
-
this.#
|
|
211
|
+
const replacement = this.#replace?.() ?? value;
|
|
212
|
+
this.#pending.push({ value: replacement, ops: [["r", replacement]], context });
|
|
202
213
|
}
|
|
203
214
|
else {
|
|
204
215
|
this.#pending.push({ value, ops, context });
|