@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.
Files changed (257) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/README.md +287 -82
  3. package/dist/codemode/codemode.d.ts +4 -4
  4. package/dist/codemode/codemode.d.ts.map +1 -1
  5. package/dist/codemode/codemode.js +21 -16
  6. package/dist/codemode/codemode.js.map +1 -1
  7. package/dist/codemode/models.d.ts.map +1 -1
  8. package/dist/codemode/models.js +6 -4
  9. package/dist/codemode/models.js.map +1 -1
  10. package/dist/documents.d.ts +1 -1
  11. package/dist/documents.d.ts.map +1 -1
  12. package/dist/documents.js.map +1 -1
  13. package/dist/env/index.d.ts +12 -10
  14. package/dist/env/index.d.ts.map +1 -1
  15. package/dist/env/index.js.map +1 -1
  16. package/dist/env/node-watch.d.ts +3 -3
  17. package/dist/env/node-watch.d.ts.map +1 -1
  18. package/dist/env/node-watch.js +18 -16
  19. package/dist/env/node-watch.js.map +1 -1
  20. package/dist/env/node.d.ts +2 -2
  21. package/dist/env/node.d.ts.map +1 -1
  22. package/dist/env/node.js +12 -4
  23. package/dist/env/node.js.map +1 -1
  24. package/dist/errors.d.ts +18 -2
  25. package/dist/errors.d.ts.map +1 -1
  26. package/dist/errors.js +26 -3
  27. package/dist/errors.js.map +1 -1
  28. package/dist/harness/agent.d.ts +13 -2
  29. package/dist/harness/agent.d.ts.map +1 -1
  30. package/dist/harness/agent.js +48 -6
  31. package/dist/harness/agent.js.map +1 -1
  32. package/dist/harness/compaction.d.ts +3 -1
  33. package/dist/harness/compaction.d.ts.map +1 -1
  34. package/dist/harness/compaction.js +38 -6
  35. package/dist/harness/compaction.js.map +1 -1
  36. package/dist/harness/context.d.ts +23 -7
  37. package/dist/harness/context.d.ts.map +1 -1
  38. package/dist/harness/context.js +71 -25
  39. package/dist/harness/context.js.map +1 -1
  40. package/dist/harness/define.d.ts +7 -3
  41. package/dist/harness/define.d.ts.map +1 -1
  42. package/dist/harness/define.js +4 -0
  43. package/dist/harness/define.js.map +1 -1
  44. package/dist/harness/generation.d.ts +38 -5
  45. package/dist/harness/generation.d.ts.map +1 -1
  46. package/dist/harness/generation.js +497 -108
  47. package/dist/harness/generation.js.map +1 -1
  48. package/dist/harness/harness.d.ts +7 -2
  49. package/dist/harness/harness.d.ts.map +1 -1
  50. package/dist/harness/harness.js +147 -57
  51. package/dist/harness/harness.js.map +1 -1
  52. package/dist/harness/inbox.d.ts +7 -3
  53. package/dist/harness/inbox.d.ts.map +1 -1
  54. package/dist/harness/inbox.js +7 -4
  55. package/dist/harness/inbox.js.map +1 -1
  56. package/dist/harness/json.d.ts +20 -4
  57. package/dist/harness/json.d.ts.map +1 -1
  58. package/dist/harness/json.js +23 -5
  59. package/dist/harness/json.js.map +1 -1
  60. package/dist/harness/live.d.ts +122 -16
  61. package/dist/harness/live.d.ts.map +1 -1
  62. package/dist/harness/live.js +93 -12
  63. package/dist/harness/live.js.map +1 -1
  64. package/dist/harness/partial-changes.d.ts +54 -0
  65. package/dist/harness/partial-changes.d.ts.map +1 -0
  66. package/dist/harness/partial-changes.js +162 -0
  67. package/dist/harness/partial-changes.js.map +1 -0
  68. package/dist/harness/prompt.d.ts +1 -1
  69. package/dist/harness/prompt.d.ts.map +1 -1
  70. package/dist/harness/prompt.js +1 -1
  71. package/dist/harness/prompt.js.map +1 -1
  72. package/dist/harness/registry-reader.d.ts +11 -0
  73. package/dist/harness/registry-reader.d.ts.map +1 -0
  74. package/dist/harness/registry-reader.js +25 -0
  75. package/dist/harness/registry-reader.js.map +1 -0
  76. package/dist/harness/scheduler.d.ts +86 -14
  77. package/dist/harness/scheduler.d.ts.map +1 -1
  78. package/dist/harness/scheduler.js +1459 -369
  79. package/dist/harness/scheduler.js.map +1 -1
  80. package/dist/harness/submissions.d.ts +23 -11
  81. package/dist/harness/submissions.d.ts.map +1 -1
  82. package/dist/harness/submissions.js +104 -36
  83. package/dist/harness/submissions.js.map +1 -1
  84. package/dist/harness/task-graph.d.ts +28 -8
  85. package/dist/harness/task-graph.d.ts.map +1 -1
  86. package/dist/harness/task-graph.js +85 -36
  87. package/dist/harness/task-graph.js.map +1 -1
  88. package/dist/harness/telemetry.d.ts +307 -0
  89. package/dist/harness/telemetry.d.ts.map +1 -0
  90. package/dist/harness/telemetry.js +136 -0
  91. package/dist/harness/telemetry.js.map +1 -0
  92. package/dist/harness/tool.d.ts +2 -0
  93. package/dist/harness/tool.d.ts.map +1 -1
  94. package/dist/harness/tool.js +223 -61
  95. package/dist/harness/tool.js.map +1 -1
  96. package/dist/harness/transcript.d.ts +72 -0
  97. package/dist/harness/transcript.d.ts.map +1 -0
  98. package/dist/harness/transcript.js +264 -0
  99. package/dist/harness/transcript.js.map +1 -0
  100. package/dist/harness/types.d.ts +302 -48
  101. package/dist/harness/types.d.ts.map +1 -1
  102. package/dist/harness/types.js.map +1 -1
  103. package/dist/harness/util.d.ts +7 -1
  104. package/dist/harness/util.d.ts.map +1 -1
  105. package/dist/harness/util.js +13 -0
  106. package/dist/harness/util.js.map +1 -1
  107. package/dist/harness/view.d.ts +43 -22
  108. package/dist/harness/view.d.ts.map +1 -1
  109. package/dist/harness/view.js +130 -71
  110. package/dist/harness/view.js.map +1 -1
  111. package/dist/index.d.ts +13 -9
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +7 -5
  114. package/dist/index.js.map +1 -1
  115. package/dist/search.d.ts +19 -3
  116. package/dist/search.d.ts.map +1 -1
  117. package/dist/search.js +107 -44
  118. package/dist/search.js.map +1 -1
  119. package/dist/session/cached-storage.d.ts +71 -0
  120. package/dist/session/cached-storage.d.ts.map +1 -0
  121. package/dist/session/cached-storage.js +269 -0
  122. package/dist/session/cached-storage.js.map +1 -0
  123. package/dist/session/conversation-tails.d.ts +33 -0
  124. package/dist/session/conversation-tails.d.ts.map +1 -0
  125. package/dist/session/conversation-tails.js +101 -0
  126. package/dist/session/conversation-tails.js.map +1 -0
  127. package/dist/session/keys.d.ts +68 -0
  128. package/dist/session/keys.d.ts.map +1 -0
  129. package/dist/session/keys.js +161 -0
  130. package/dist/session/keys.js.map +1 -0
  131. package/dist/session/session.d.ts +181 -29
  132. package/dist/session/session.d.ts.map +1 -1
  133. package/dist/session/session.js +1073 -183
  134. package/dist/session/session.js.map +1 -1
  135. package/dist/session/transaction.d.ts +86 -4
  136. package/dist/session/transaction.d.ts.map +1 -1
  137. package/dist/session/transaction.js +250 -38
  138. package/dist/session/transaction.js.map +1 -1
  139. package/dist/session/writer.d.ts +74 -0
  140. package/dist/session/writer.d.ts.map +1 -0
  141. package/dist/session/writer.js +294 -0
  142. package/dist/session/writer.js.map +1 -0
  143. package/dist/storage/indexeddb.d.ts +68 -0
  144. package/dist/storage/indexeddb.d.ts.map +1 -0
  145. package/dist/storage/indexeddb.js +881 -0
  146. package/dist/storage/indexeddb.js.map +1 -0
  147. package/dist/storage/jsonl/storage.d.ts +30 -2
  148. package/dist/storage/jsonl/storage.d.ts.map +1 -1
  149. package/dist/storage/jsonl/storage.js +88 -24
  150. package/dist/storage/jsonl/storage.js.map +1 -1
  151. package/dist/storage/memory.d.ts +7 -2
  152. package/dist/storage/memory.d.ts.map +1 -1
  153. package/dist/storage/memory.js +29 -3
  154. package/dist/storage/memory.js.map +1 -1
  155. package/dist/storage/sqlite/cloudflare.d.ts +2 -51
  156. package/dist/storage/sqlite/cloudflare.d.ts.map +1 -1
  157. package/dist/storage/sqlite/cloudflare.js +2 -133
  158. package/dist/storage/sqlite/cloudflare.js.map +1 -1
  159. package/dist/storage/sqlite/database.d.ts +1 -36
  160. package/dist/storage/sqlite/database.d.ts.map +1 -1
  161. package/dist/storage/sqlite/database.js.map +1 -1
  162. package/dist/storage/sqlite/index.d.ts +1 -1
  163. package/dist/storage/sqlite/index.d.ts.map +1 -1
  164. package/dist/storage/sqlite/index.js.map +1 -1
  165. package/dist/storage/sqlite/migrations.d.ts +2 -5
  166. package/dist/storage/sqlite/migrations.d.ts.map +1 -1
  167. package/dist/storage/sqlite/migrations.js +28 -28
  168. package/dist/storage/sqlite/migrations.js.map +1 -1
  169. package/dist/storage/sqlite/node.d.ts +2 -37
  170. package/dist/storage/sqlite/node.d.ts.map +1 -1
  171. package/dist/storage/sqlite/node.js +3 -174
  172. package/dist/storage/sqlite/node.js.map +1 -1
  173. package/dist/storage/sqlite/schema.d.ts +1 -3
  174. package/dist/storage/sqlite/schema.d.ts.map +1 -1
  175. package/dist/storage/sqlite/schema.js +2 -9
  176. package/dist/storage/sqlite/schema.js.map +1 -1
  177. package/dist/storage/sqlite/storage.d.ts +15 -3
  178. package/dist/storage/sqlite/storage.d.ts.map +1 -1
  179. package/dist/storage/sqlite/storage.js +110 -36
  180. package/dist/storage/sqlite/storage.js.map +1 -1
  181. package/dist/storage/store/commit.d.ts +33 -0
  182. package/dist/storage/store/commit.d.ts.map +1 -0
  183. package/dist/storage/store/commit.js +286 -0
  184. package/dist/storage/store/commit.js.map +1 -0
  185. package/dist/storage/store/documents.d.ts +43 -0
  186. package/dist/storage/store/documents.d.ts.map +1 -0
  187. package/dist/storage/store/documents.js +102 -0
  188. package/dist/storage/store/documents.js.map +1 -0
  189. package/dist/storage/store/index.d.ts +2 -0
  190. package/dist/storage/store/index.d.ts.map +1 -0
  191. package/dist/storage/store/index.js +2 -0
  192. package/dist/storage/store/index.js.map +1 -0
  193. package/dist/storage/store/queries.d.ts +49 -0
  194. package/dist/storage/store/queries.d.ts.map +1 -0
  195. package/dist/storage/store/queries.js +93 -0
  196. package/dist/storage/store/queries.js.map +1 -0
  197. package/dist/storage/store/storage.d.ts +59 -0
  198. package/dist/storage/store/storage.d.ts.map +1 -0
  199. package/dist/storage/store/storage.js +438 -0
  200. package/dist/storage/store/storage.js.map +1 -0
  201. package/dist/storage/store/tables.d.ts +54 -0
  202. package/dist/storage/store/tables.d.ts.map +1 -0
  203. package/dist/storage/store/tables.js +108 -0
  204. package/dist/storage/store/tables.js.map +1 -0
  205. package/dist/testing/commit-writes.d.ts +5 -0
  206. package/dist/testing/commit-writes.d.ts.map +1 -0
  207. package/dist/testing/commit-writes.js +12 -0
  208. package/dist/testing/commit-writes.js.map +1 -0
  209. package/dist/testing/env-conformance.js +7 -7
  210. package/dist/testing/env-conformance.js.map +1 -1
  211. package/dist/testing/index.d.ts +1 -0
  212. package/dist/testing/index.d.ts.map +1 -1
  213. package/dist/testing/index.js +1 -0
  214. package/dist/testing/index.js.map +1 -1
  215. package/dist/testing/storage-benchmark.d.ts.map +1 -1
  216. package/dist/testing/storage-benchmark.js +18 -17
  217. package/dist/testing/storage-benchmark.js.map +1 -1
  218. package/dist/testing/storage-conformance.d.ts.map +1 -1
  219. package/dist/testing/storage-conformance.js +369 -67
  220. package/dist/testing/storage-conformance.js.map +1 -1
  221. package/dist/timers.d.ts +21 -0
  222. package/dist/timers.d.ts.map +1 -0
  223. package/dist/timers.js +72 -0
  224. package/dist/timers.js.map +1 -0
  225. package/dist/tool-search/tool-search.d.ts +6 -12
  226. package/dist/tool-search/tool-search.d.ts.map +1 -1
  227. package/dist/tool-search/tool-search.js +7 -7
  228. package/dist/tool-search/tool-search.js.map +1 -1
  229. package/dist/tools/bash.d.ts +12 -12
  230. package/dist/tools/bash.d.ts.map +1 -1
  231. package/dist/tools/bash.js +16 -15
  232. package/dist/tools/bash.js.map +1 -1
  233. package/dist/tools/edit.d.ts +7 -7
  234. package/dist/tools/edit.d.ts.map +1 -1
  235. package/dist/tools/edit.js +9 -9
  236. package/dist/tools/edit.js.map +1 -1
  237. package/dist/tools/index.d.ts +32 -32
  238. package/dist/tools/read.d.ts +6 -6
  239. package/dist/tools/read.d.ts.map +1 -1
  240. package/dist/tools/read.js +19 -8
  241. package/dist/tools/read.js.map +1 -1
  242. package/dist/tools/write.d.ts +4 -4
  243. package/dist/tools/write.d.ts.map +1 -1
  244. package/dist/tools/write.js +5 -5
  245. package/dist/tools/write.js.map +1 -1
  246. package/dist/types.d.ts +331 -64
  247. package/dist/types.d.ts.map +1 -1
  248. package/dist/types.js.map +1 -1
  249. package/package.json +27 -10
  250. package/dist/harness/events.d.ts +0 -186
  251. package/dist/harness/events.d.ts.map +0 -1
  252. package/dist/harness/events.js +0 -373
  253. package/dist/harness/events.js.map +0 -1
  254. package/dist/session/observation.d.ts +0 -42
  255. package/dist/session/observation.d.ts.map +0 -1
  256. package/dist/session/observation.js +0 -281
  257. package/dist/session/observation.js.map +0 -1
@@ -1,15 +1,16 @@
1
- import { replicatedState } from "@earendil-works/chord";
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 { CommittedStateSource, CommittedWatch } from "../session/observation.js";
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 commit publications, which are durable.
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, storage) {
55
+ constructor(session) {
39
56
  this.#session = session;
40
- this.#storage = storage;
41
57
  VIEWS.set(session, this);
42
- session.observeCommits((publication, context) => {
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 observer of [...mount.observers]) {
50
- contained(() => observer.closeSession(this.#session.failure), (error) => this.report(error));
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
- /** A disposable read-only Chord state of the view. */
60
- async state(id, context) {
61
- const { observer, detach } = await this.attach(id, (value, release) => new CommittedStateSource(value, release), context);
62
- try {
63
- return replicatedState(observer, { onError: (error) => this.#session.report(error) });
64
- }
65
- catch (error) {
66
- detach();
67
- throw error;
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 exact-frame watch of the view; cancelling `context` stops it. */
71
- async watch(id, context) {
72
- const { observer } = await this.attach(id, (value, release) => new CommittedWatch(value, release, (error) => this.#session.report(error)), context);
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.cancel();
98
+ observer.abort();
76
99
  throw signal.reason;
77
100
  }
78
101
  if (signal !== undefined)
79
- observer.observeCancellation(signal);
102
+ observer.observeAbort(signal);
80
103
  return observer;
81
104
  }
82
105
  /**
83
- * Register an observer created from the current revision, atomically on the Session line: it sees every later
84
- * publication and nothing earlier. `create` may read committed Storage, still on the line. `release` drops it, and
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
- return this.#session.readOnLine(async () => {
89
- const mount = this.#mounts.get(id) ?? (await this.#build(id, context));
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
- mount.observers.delete(observer);
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 = await create(mount.value, detach, this.#storage);
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(observer);
129
+ mount.observers.add(windowed);
102
130
  return { observer, detach };
103
131
  });
104
132
  }
105
- async #build(id, context) {
106
- const conversation = await this.#storage.conversation(id, context);
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 { value: { conversation, entries, docs }, docs: incarnations, observers: new Set() };
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, apply them, and hand the revision to every observer; one that
125
- * throws is reported through `report`, and the others still get it.
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
- const entry = change.value;
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.docs.get(kind);
157
- if (change.value === null) {
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.docs.delete(kind);
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.docs.set(kind, { id: change.record.id, version: change.version });
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
- const before = mount.value;
173
- const ops = [...docOps, ...entryOps];
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
- if (ops.length > 0) {
176
- const value = docOps.length === 0 ? mount.value : applyImmutable(mount.value, docOps);
177
- mount.value = entries === value.entries ? value : { ...value, entries };
178
- for (const observer of [...mount.observers]) {
179
- contained(() => observer.advance?.(mount.value, ops, frameContext), report);
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
- for (const observer of [...mount.observers]) {
183
- contained(() => observer.publication?.(before, mount.value, ops, publication, frameContext), report);
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. */
@@ -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 type { Agent, AgentChange, AgentState, AnyTask, CompactionHooks, CompactionPolicy, CompactionReason, CompactionResult, 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, Settings, SettledSubmissionRecord, SettledTask, Submission, SubmissionDraft, TaskInspection, ToolControl, ToolDiagnostic, ToolExecutionApi, ToolExecutionMode, ToolExecutionResult, ToolHookCall, ToolHooks, ToolRegistration, UserInput, Wrap, } from "./harness/types.ts";
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, DocumentState, DocumentWatch, Entry, EntryDraft, EntryId, EntryQuery, EntryRecord, HookRunner, Id, JoinPolicy, JsonObject, LatestConversationSemantics, NextTaskState, Page, PhaseHandler, RewindableConversationDocFamilyToken, RewindableConversationDocToken, RewindableConversationSemantics, RunningTask, ScanOrder, Seq, Session, SessionDocFamilyToken, SessionDocToken, SessionEnd, 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";
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
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":"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,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EACN,QAAQ,EACR,SAAS,EACT,yBAAyB,EACzB,uBAAuB,EACvB,oBAAoB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAGN,cAAc,GAEd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAMN,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,EAGN,OAAO,GAKP,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAsB,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EACN,aAAa,EAEb,QAAQ,GAIR,MAAM,mBAAmB,CAAC;AAyD3B,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;AAmFxC,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, SessionFailed, StorageRequestError } from \"./errors.ts\";\nexport {\n\tAgentDoc,\n\tconfigure,\n\tDEFAULT_COMPACTION_POLICY,\n\tDEFAULT_PROGRESS_POLICY,\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, section, wrapSection, wrapTool } from \"./harness/define.ts\";\nexport {\n\ttype AgentEvent,\n\ttype AgentEventStream,\n\ttype MessageChange,\n\ttype SnapshotEvent,\n\ttype ToolEventCall,\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 {\n\ttype CompactionFailure,\n\ttype CompactionStatus,\n\tLiveDoc,\n\ttype LiveState,\n\ttype NestedToolSlot,\n\ttype NestedToolSummary,\n\ttype ToolSlot,\n} from \"./harness/live.ts\";\nexport { ProviderDoc, type ProviderState } from \"./harness/provider.ts\";\nexport { createRegistry } from \"./harness/registry.ts\";\nexport type { TaskGraph, TaskGraphNode, TaskGraphState, TaskGraphWatch } from \"./harness/task-graph.ts\";\nexport {\n\tNestedCallDoc,\n\ttype NestedCallState,\n\tToolTask,\n\ttype ToolTaskCheckpoint,\n\ttype ToolTaskInput,\n\ttype ToolTaskResult,\n} from \"./harness/tool.ts\";\nexport type {\n\tAgent,\n\tAgentChange,\n\tAgentState,\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\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\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\tWrap,\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\tScanOrder,\n\tSeq,\n\tSession,\n\tSessionDocFamilyToken,\n\tSessionDocToken,\n\tSessionEnd,\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"]}
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
- /** Lowercase terms, split at camelCase boundaries and non-alphanumerics, without stop words. */
10
- export declare function tokenize(text: string): string[];
11
- /** Okapi BM25 (k1 1.2, b 0.75): the names of the best matches, best first; ties keep document order. */
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
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAkC9E,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ/C;AAED,wGAAwG;AACxG,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAiC1G"}
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"}