@ny4n/durable 0.0.0-stage → 1.0.1

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 (303) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +711 -2
  3. package/dist/documents.d.ts +66 -0
  4. package/dist/documents.d.ts.map +1 -0
  5. package/dist/documents.js +98 -0
  6. package/dist/documents.js.map +1 -0
  7. package/dist/entries.d.ts +31 -0
  8. package/dist/entries.d.ts.map +1 -0
  9. package/dist/entries.js +31 -0
  10. package/dist/entries.js.map +1 -0
  11. package/dist/env/decode.d.ts +16 -0
  12. package/dist/env/decode.d.ts.map +1 -0
  13. package/dist/env/decode.js +28 -0
  14. package/dist/env/decode.js.map +1 -0
  15. package/dist/env/index.d.ts +263 -0
  16. package/dist/env/index.d.ts.map +1 -0
  17. package/dist/env/index.js +49 -0
  18. package/dist/env/index.js.map +1 -0
  19. package/dist/env/line-scan.d.ts +13 -0
  20. package/dist/env/line-scan.d.ts.map +1 -0
  21. package/dist/env/line-scan.js +147 -0
  22. package/dist/env/line-scan.js.map +1 -0
  23. package/dist/env/node-watch.d.ts +29 -0
  24. package/dist/env/node-watch.d.ts.map +1 -0
  25. package/dist/env/node-watch.js +485 -0
  26. package/dist/env/node-watch.js.map +1 -0
  27. package/dist/env/node.d.ts +56 -0
  28. package/dist/env/node.d.ts.map +1 -0
  29. package/dist/env/node.js +1166 -0
  30. package/dist/env/node.js.map +1 -0
  31. package/dist/errors.d.ts +32 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +53 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/harness/agent.d.ts +33 -0
  36. package/dist/harness/agent.d.ts.map +1 -0
  37. package/dist/harness/agent.js +235 -0
  38. package/dist/harness/agent.js.map +1 -0
  39. package/dist/harness/assistant.d.ts +15 -0
  40. package/dist/harness/assistant.d.ts.map +1 -0
  41. package/dist/harness/assistant.js +23 -0
  42. package/dist/harness/assistant.js.map +1 -0
  43. package/dist/harness/compaction.d.ts +56 -0
  44. package/dist/harness/compaction.d.ts.map +1 -0
  45. package/dist/harness/compaction.js +384 -0
  46. package/dist/harness/compaction.js.map +1 -0
  47. package/dist/harness/context.d.ts +63 -0
  48. package/dist/harness/context.d.ts.map +1 -0
  49. package/dist/harness/context.js +221 -0
  50. package/dist/harness/context.js.map +1 -0
  51. package/dist/harness/define.d.ts +18 -0
  52. package/dist/harness/define.d.ts.map +1 -0
  53. package/dist/harness/define.js +25 -0
  54. package/dist/harness/define.js.map +1 -0
  55. package/dist/harness/events.d.ts +180 -0
  56. package/dist/harness/events.d.ts.map +1 -0
  57. package/dist/harness/events.js +370 -0
  58. package/dist/harness/events.js.map +1 -0
  59. package/dist/harness/generation.d.ts +54 -0
  60. package/dist/harness/generation.d.ts.map +1 -0
  61. package/dist/harness/generation.js +514 -0
  62. package/dist/harness/generation.js.map +1 -0
  63. package/dist/harness/harness.d.ts +17 -0
  64. package/dist/harness/harness.d.ts.map +1 -0
  65. package/dist/harness/harness.js +332 -0
  66. package/dist/harness/harness.js.map +1 -0
  67. package/dist/harness/inbox.d.ts +59 -0
  68. package/dist/harness/inbox.d.ts.map +1 -0
  69. package/dist/harness/inbox.js +97 -0
  70. package/dist/harness/inbox.js.map +1 -0
  71. package/dist/harness/json.d.ts +10 -0
  72. package/dist/harness/json.d.ts.map +1 -0
  73. package/dist/harness/json.js +33 -0
  74. package/dist/harness/json.js.map +1 -0
  75. package/dist/harness/live.d.ts +142 -0
  76. package/dist/harness/live.d.ts.map +1 -0
  77. package/dist/harness/live.js +149 -0
  78. package/dist/harness/live.js.map +1 -0
  79. package/dist/harness/output.d.ts +69 -0
  80. package/dist/harness/output.d.ts.map +1 -0
  81. package/dist/harness/output.js +318 -0
  82. package/dist/harness/output.js.map +1 -0
  83. package/dist/harness/prompt.d.ts +27 -0
  84. package/dist/harness/prompt.d.ts.map +1 -0
  85. package/dist/harness/prompt.js +131 -0
  86. package/dist/harness/prompt.js.map +1 -0
  87. package/dist/harness/provider.d.ts +14 -0
  88. package/dist/harness/provider.d.ts.map +1 -0
  89. package/dist/harness/provider.js +30 -0
  90. package/dist/harness/provider.js.map +1 -0
  91. package/dist/harness/registry.d.ts +6 -0
  92. package/dist/harness/registry.d.ts.map +1 -0
  93. package/dist/harness/registry.js +101 -0
  94. package/dist/harness/registry.js.map +1 -0
  95. package/dist/harness/run.d.ts +17 -0
  96. package/dist/harness/run.d.ts.map +1 -0
  97. package/dist/harness/run.js +26 -0
  98. package/dist/harness/run.js.map +1 -0
  99. package/dist/harness/scheduler.d.ts +106 -0
  100. package/dist/harness/scheduler.d.ts.map +1 -0
  101. package/dist/harness/scheduler.js +1743 -0
  102. package/dist/harness/scheduler.js.map +1 -0
  103. package/dist/harness/submissions.d.ts +29 -0
  104. package/dist/harness/submissions.d.ts.map +1 -0
  105. package/dist/harness/submissions.js +175 -0
  106. package/dist/harness/submissions.js.map +1 -0
  107. package/dist/harness/task-graph.d.ts +49 -0
  108. package/dist/harness/task-graph.d.ts.map +1 -0
  109. package/dist/harness/task-graph.js +168 -0
  110. package/dist/harness/task-graph.js.map +1 -0
  111. package/dist/harness/tool.d.ts +76 -0
  112. package/dist/harness/tool.d.ts.map +1 -0
  113. package/dist/harness/tool.js +736 -0
  114. package/dist/harness/tool.js.map +1 -0
  115. package/dist/harness/types.d.ts +713 -0
  116. package/dist/harness/types.d.ts.map +1 -0
  117. package/dist/harness/types.js +2 -0
  118. package/dist/harness/types.js.map +1 -0
  119. package/dist/harness/usage.d.ts +18 -0
  120. package/dist/harness/usage.d.ts.map +1 -0
  121. package/dist/harness/usage.js +57 -0
  122. package/dist/harness/usage.js.map +1 -0
  123. package/dist/harness/util.d.ts +19 -0
  124. package/dist/harness/util.d.ts.map +1 -0
  125. package/dist/harness/util.js +58 -0
  126. package/dist/harness/util.js.map +1 -0
  127. package/dist/harness/view.d.ts +47 -0
  128. package/dist/harness/view.d.ts.map +1 -0
  129. package/dist/harness/view.js +206 -0
  130. package/dist/harness/view.js.map +1 -0
  131. package/dist/ids.d.ts +6 -0
  132. package/dist/ids.d.ts.map +1 -0
  133. package/dist/ids.js +9 -0
  134. package/dist/ids.js.map +1 -0
  135. package/dist/images/cloudflare.d.ts +4 -0
  136. package/dist/images/cloudflare.d.ts.map +1 -0
  137. package/dist/images/cloudflare.js +9 -0
  138. package/dist/images/cloudflare.js.map +1 -0
  139. package/dist/images/exif.d.ts +3 -0
  140. package/dist/images/exif.d.ts.map +1 -0
  141. package/dist/images/exif.js +71 -0
  142. package/dist/images/exif.js.map +1 -0
  143. package/dist/images/index.d.ts +18 -0
  144. package/dist/images/index.d.ts.map +1 -0
  145. package/dist/images/index.js +125 -0
  146. package/dist/images/index.js.map +1 -0
  147. package/dist/images/node-worker.d.ts +17 -0
  148. package/dist/images/node-worker.d.ts.map +1 -0
  149. package/dist/images/node-worker.js +16 -0
  150. package/dist/images/node-worker.js.map +1 -0
  151. package/dist/images/node.d.ts +21 -0
  152. package/dist/images/node.d.ts.map +1 -0
  153. package/dist/images/node.js +121 -0
  154. package/dist/images/node.js.map +1 -0
  155. package/dist/index.d.ts +24 -0
  156. package/dist/index.d.ts.map +1 -0
  157. package/dist/index.js +20 -0
  158. package/dist/index.js.map +1 -0
  159. package/dist/session/forks.d.ts +10 -0
  160. package/dist/session/forks.d.ts.map +1 -0
  161. package/dist/session/forks.js +42 -0
  162. package/dist/session/forks.js.map +1 -0
  163. package/dist/session/observation.d.ts +42 -0
  164. package/dist/session/observation.d.ts.map +1 -0
  165. package/dist/session/observation.js +281 -0
  166. package/dist/session/observation.js.map +1 -0
  167. package/dist/session/session.d.ts +133 -0
  168. package/dist/session/session.d.ts.map +1 -0
  169. package/dist/session/session.js +811 -0
  170. package/dist/session/session.js.map +1 -0
  171. package/dist/session/transaction.d.ts +119 -0
  172. package/dist/session/transaction.d.ts.map +1 -0
  173. package/dist/session/transaction.js +795 -0
  174. package/dist/session/transaction.js.map +1 -0
  175. package/dist/storage/jsonl/index.d.ts +2 -0
  176. package/dist/storage/jsonl/index.d.ts.map +1 -0
  177. package/dist/storage/jsonl/index.js +2 -0
  178. package/dist/storage/jsonl/index.js.map +1 -0
  179. package/dist/storage/jsonl/node.d.ts +6 -0
  180. package/dist/storage/jsonl/node.d.ts.map +1 -0
  181. package/dist/storage/jsonl/node.js +8 -0
  182. package/dist/storage/jsonl/node.js.map +1 -0
  183. package/dist/storage/jsonl/storage.d.ts +143 -0
  184. package/dist/storage/jsonl/storage.d.ts.map +1 -0
  185. package/dist/storage/jsonl/storage.js +682 -0
  186. package/dist/storage/jsonl/storage.js.map +1 -0
  187. package/dist/storage/memory.d.ts +62 -0
  188. package/dist/storage/memory.d.ts.map +1 -0
  189. package/dist/storage/memory.js +733 -0
  190. package/dist/storage/memory.js.map +1 -0
  191. package/dist/storage/scan.d.ts +18 -0
  192. package/dist/storage/scan.d.ts.map +1 -0
  193. package/dist/storage/scan.js +29 -0
  194. package/dist/storage/scan.js.map +1 -0
  195. package/dist/storage/sqlite/cloudflare.d.ts +46 -0
  196. package/dist/storage/sqlite/cloudflare.d.ts.map +1 -0
  197. package/dist/storage/sqlite/cloudflare.js +106 -0
  198. package/dist/storage/sqlite/cloudflare.js.map +1 -0
  199. package/dist/storage/sqlite/database.d.ts +37 -0
  200. package/dist/storage/sqlite/database.d.ts.map +1 -0
  201. package/dist/storage/sqlite/database.js +2 -0
  202. package/dist/storage/sqlite/database.js.map +1 -0
  203. package/dist/storage/sqlite/index.d.ts +4 -0
  204. package/dist/storage/sqlite/index.d.ts.map +1 -0
  205. package/dist/storage/sqlite/index.js +3 -0
  206. package/dist/storage/sqlite/index.js.map +1 -0
  207. package/dist/storage/sqlite/migrations.d.ts +11 -0
  208. package/dist/storage/sqlite/migrations.d.ts.map +1 -0
  209. package/dist/storage/sqlite/migrations.js +111 -0
  210. package/dist/storage/sqlite/migrations.js.map +1 -0
  211. package/dist/storage/sqlite/node.d.ts +41 -0
  212. package/dist/storage/sqlite/node.d.ts.map +1 -0
  213. package/dist/storage/sqlite/node.js +179 -0
  214. package/dist/storage/sqlite/node.js.map +1 -0
  215. package/dist/storage/sqlite/storage.d.ts +65 -0
  216. package/dist/storage/sqlite/storage.d.ts.map +1 -0
  217. package/dist/storage/sqlite/storage.js +670 -0
  218. package/dist/storage/sqlite/storage.js.map +1 -0
  219. package/dist/tasks.d.ts +6 -0
  220. package/dist/tasks.d.ts.map +1 -0
  221. package/dist/tasks.js +5 -0
  222. package/dist/tasks.js.map +1 -0
  223. package/dist/testing/assertions.d.ts +5 -0
  224. package/dist/testing/assertions.d.ts.map +1 -0
  225. package/dist/testing/assertions.js +25 -0
  226. package/dist/testing/assertions.js.map +1 -0
  227. package/dist/testing/env-conformance.d.ts +7 -0
  228. package/dist/testing/env-conformance.d.ts.map +1 -0
  229. package/dist/testing/env-conformance.js +431 -0
  230. package/dist/testing/env-conformance.js.map +1 -0
  231. package/dist/testing/index.d.ts +7 -0
  232. package/dist/testing/index.d.ts.map +1 -0
  233. package/dist/testing/index.js +6 -0
  234. package/dist/testing/index.js.map +1 -0
  235. package/dist/testing/runner.d.ts +12 -0
  236. package/dist/testing/runner.d.ts.map +1 -0
  237. package/dist/testing/runner.js +23 -0
  238. package/dist/testing/runner.js.map +1 -0
  239. package/dist/testing/storage-benchmark.d.ts +41 -0
  240. package/dist/testing/storage-benchmark.d.ts.map +1 -0
  241. package/dist/testing/storage-benchmark.js +350 -0
  242. package/dist/testing/storage-benchmark.js.map +1 -0
  243. package/dist/testing/storage-conformance.d.ts +4 -0
  244. package/dist/testing/storage-conformance.d.ts.map +1 -0
  245. package/dist/testing/storage-conformance.js +1213 -0
  246. package/dist/testing/storage-conformance.js.map +1 -0
  247. package/dist/testing/types.d.ts +37 -0
  248. package/dist/testing/types.d.ts.map +1 -0
  249. package/dist/testing/types.js +2 -0
  250. package/dist/testing/types.js.map +1 -0
  251. package/dist/tools/bash.d.ts +55 -0
  252. package/dist/tools/bash.d.ts.map +1 -0
  253. package/dist/tools/bash.js +138 -0
  254. package/dist/tools/bash.js.map +1 -0
  255. package/dist/tools/edit-diff.d.ts +89 -0
  256. package/dist/tools/edit-diff.d.ts.map +1 -0
  257. package/dist/tools/edit-diff.js +386 -0
  258. package/dist/tools/edit-diff.js.map +1 -0
  259. package/dist/tools/edit.d.ts +18 -0
  260. package/dist/tools/edit.d.ts.map +1 -0
  261. package/dist/tools/edit.js +117 -0
  262. package/dist/tools/edit.js.map +1 -0
  263. package/dist/tools/env.d.ts +5 -0
  264. package/dist/tools/env.d.ts.map +1 -0
  265. package/dist/tools/env.js +7 -0
  266. package/dist/tools/env.js.map +1 -0
  267. package/dist/tools/file-mutation-queue.d.ts +9 -0
  268. package/dist/tools/file-mutation-queue.d.ts.map +1 -0
  269. package/dist/tools/file-mutation-queue.js +52 -0
  270. package/dist/tools/file-mutation-queue.js.map +1 -0
  271. package/dist/tools/image-processor.d.ts +47 -0
  272. package/dist/tools/image-processor.d.ts.map +1 -0
  273. package/dist/tools/image-processor.js +30 -0
  274. package/dist/tools/image-processor.js.map +1 -0
  275. package/dist/tools/image.d.ts +20 -0
  276. package/dist/tools/image.d.ts.map +1 -0
  277. package/dist/tools/image.js +178 -0
  278. package/dist/tools/image.js.map +1 -0
  279. package/dist/tools/index.d.ts +46 -0
  280. package/dist/tools/index.d.ts.map +1 -0
  281. package/dist/tools/index.js +23 -0
  282. package/dist/tools/index.js.map +1 -0
  283. package/dist/tools/path-utils.d.ts +5 -0
  284. package/dist/tools/path-utils.d.ts.map +1 -0
  285. package/dist/tools/path-utils.js +26 -0
  286. package/dist/tools/path-utils.js.map +1 -0
  287. package/dist/tools/read.d.ts +25 -0
  288. package/dist/tools/read.d.ts.map +1 -0
  289. package/dist/tools/read.js +235 -0
  290. package/dist/tools/read.js.map +1 -0
  291. package/dist/tools/write.d.ts +10 -0
  292. package/dist/tools/write.d.ts.map +1 -0
  293. package/dist/tools/write.js +31 -0
  294. package/dist/tools/write.js.map +1 -0
  295. package/dist/truncate.d.ts +64 -0
  296. package/dist/truncate.d.ts.map +1 -0
  297. package/dist/truncate.js +154 -0
  298. package/dist/truncate.js.map +1 -0
  299. package/dist/types.d.ts +932 -0
  300. package/dist/types.d.ts.map +1 -0
  301. package/dist/types.js +3 -0
  302. package/dist/types.js.map +1 -0
  303. package/package.json +140 -5
@@ -0,0 +1,63 @@
1
+ import type { Message } from "@ny4n/ai/contracts";
2
+ import type { Context } from "@ny4n/chord";
3
+ import type { SessionImpl } from "../session/session.ts";
4
+ import type { ConversationId, EntryId, EntryRecord, Storage } from "../types.ts";
5
+ import type { ContextView } from "./types.ts";
6
+ /** Head marker and newest visible entry that fix one committed context range. */
7
+ export type ContextBounds = {
8
+ readonly head: (EntryRecord & {
9
+ readonly head: EntryId;
10
+ }) | undefined;
11
+ readonly tail: EntryId;
12
+ };
13
+ /**
14
+ * Capture the bounds of the current context, or of the context cut off at the visible entry `at`, with two O(1)
15
+ * reads. Run this on the Session line; entries at or below the tail are immutable, so `deriveContext()` can then scan
16
+ * them off the line.
17
+ */
18
+ export declare function captureContextBounds(storage: Storage, conversationId: ConversationId, context: Context, at?: EntryId): Promise<ContextBounds | undefined>;
19
+ /**
20
+ * One context read: the visible entries it scanned, from the head marker's head, or transcript start, through
21
+ * `bounds.tail`, oldest first, and the view derived from them. Entries at or below the tail never change, so a later
22
+ * read with the same head marker extends both.
23
+ */
24
+ export type ContextRange = {
25
+ readonly bounds: ContextBounds;
26
+ readonly entries: readonly EntryRecord[];
27
+ readonly view: ContextView;
28
+ /** Targets of the edits in `entries`. */
29
+ readonly edited: ReadonlySet<EntryId>;
30
+ /**
31
+ * `view.messages` from the contributed messages before the last assistant message. Tool results are ordered within
32
+ * the messages up to the next assistant message, so later entries cannot change these.
33
+ */
34
+ readonly settled: readonly Message[];
35
+ /** Contributed messages from the last assistant message on, before tool result ordering. */
36
+ readonly open: readonly Message[];
37
+ };
38
+ /**
39
+ * `readContext()` that reuses `previous`, an earlier range of the same conversation: with the same head marker, only
40
+ * entries after its tail are scanned. Returns the view and the range to pass to the next read. A range outlives the
41
+ * read, so its entries are frozen like `MemoryStorage` records, and the returned view has its own arrays.
42
+ */
43
+ export declare function readContextFrom(session: SessionImpl, storage: Storage, conversationId: ConversationId, context: Context, at: EntryId | undefined, previous: ContextRange | undefined): Promise<{
44
+ readonly view: ContextView;
45
+ readonly range: ContextRange | undefined;
46
+ }>;
47
+ /** Committed context of one conversation: bounds captured on the Session line, entries derived off it. */
48
+ export declare function readContext(session: SessionImpl, storage: Storage, conversationId: ConversationId, context: Context, at?: EntryId): Promise<ContextView>;
49
+ /**
50
+ * Derive the active transcript and model context of one conversation within captured bounds.
51
+ *
52
+ * H = newest visible head marker; the range runs from `H.head` (or transcript start) through the tail. Per target,
53
+ * the newest edit in the range wins. Context entries are H followed by the range's non-head entries.
54
+ */
55
+ export declare function deriveContext(storage: Storage, conversationId: ConversationId, bounds: ContextBounds | undefined, context: Context): Promise<ContextView>;
56
+ /** The raw active entries within captured bounds, without deriving model context. */
57
+ export declare function activeEntries(storage: Storage, conversationId: ConversationId, bounds: ContextBounds | undefined, context: Context): Promise<readonly EntryRecord[]>;
58
+ /**
59
+ * Place each assistant's tool results directly after it in call order. Results are taken from the messages before
60
+ * the next assistant; a missing result is synthesized and unmatched results are dropped.
61
+ */
62
+ export declare function orderToolResults(messages: readonly Message[]): Message[];
63
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/harness/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,OAAO,EAA+B,MAAM,oBAAoB,CAAC;AACjG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAe,cAAc,EAAU,OAAO,EAAc,WAAW,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAClH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,iFAAiF;AACjF,MAAM,MAAM,aAAa,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,SAAS,CAAC;IACtE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,oBAAoB,CACzC,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,OAAO,EAChB,EAAE,CAAC,EAAE,OAAO,GACV,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAYpC;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG;IAC1B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,CAAC;IACrC,4FAA4F;IAC5F,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;CAClC,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,eAAe,CACpC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,OAAO,GAAG,SAAS,EACvB,QAAQ,EAAE,YAAY,GAAG,SAAS,GAChC,OAAO,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,CAAA;CAAE,CAAC,CA6BnF;AAED,0GAA0G;AAC1G,wBAAsB,WAAW,CAChC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,OAAO,EAChB,EAAE,CAAC,EAAE,OAAO,GACV,OAAO,CAAC,WAAW,CAAC,CAGtB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAClC,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,aAAa,GAAG,SAAS,EACjC,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,WAAW,CAAC,CAGtB;AAqFD,qFAAqF;AACrF,wBAAsB,aAAa,CAClC,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,aAAa,GAAG,SAAS,EACjC,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAGjC;AA8BD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE,CAsBxE"}
@@ -0,0 +1,221 @@
1
+ import { idFromNumber } from "../ids.js";
2
+ const SCAN_PAGE_SIZE = 256;
3
+ const EXCLUDED_STOP_REASONS = new Set(["aborted", "error", "deferred"]);
4
+ const MISSING_RESULT_TEXT = "Tool result unavailable: history ends before this call completed.";
5
+ /**
6
+ * Capture the bounds of the current context, or of the context cut off at the visible entry `at`, with two O(1)
7
+ * reads. Run this on the Session line; entries at or below the tail are immutable, so `deriveContext()` can then scan
8
+ * them off the line.
9
+ */
10
+ export async function captureContextBounds(storage, conversationId, context, at) {
11
+ let tail;
12
+ if (at === undefined) {
13
+ tail = (await storage.scanEntries({ conversationId }, 1, undefined, context)).items[0]?.id;
14
+ if (tail === undefined)
15
+ return undefined;
16
+ }
17
+ else {
18
+ if ((await storage.entry(conversationId, at, context)) === undefined) {
19
+ throw new Error(`Entry ${at} is not visible from conversation ${conversationId}`);
20
+ }
21
+ tail = at;
22
+ }
23
+ return { head: await storage.findLatestHeadMarker(conversationId, tail, context), tail };
24
+ }
25
+ /**
26
+ * `readContext()` that reuses `previous`, an earlier range of the same conversation: with the same head marker, only
27
+ * entries after its tail are scanned. Returns the view and the range to pass to the next read. A range outlives the
28
+ * read, so its entries are frozen like `MemoryStorage` records, and the returned view has its own arrays.
29
+ */
30
+ export async function readContextFrom(session, storage, conversationId, context, at, previous) {
31
+ const bounds = await session.readOnLine(() => captureContextBounds(storage, conversationId, context, at));
32
+ if (bounds === undefined)
33
+ return { view: emptyView(), range: undefined };
34
+ freezeJson(bounds.head);
35
+ let range;
36
+ if (previous === undefined || previous.bounds.head?.id !== bounds.head?.id) {
37
+ range = deriveRange(bounds, freezeJson(await scanRange(storage, conversationId, rangeQuery(bounds), context)));
38
+ }
39
+ else if (bounds.tail === previous.bounds.tail) {
40
+ range = previous;
41
+ }
42
+ else if (bounds.tail < previous.bounds.tail) {
43
+ range = deriveRange(bounds, previous.entries.filter((entry) => entry.id <= bounds.tail));
44
+ }
45
+ else {
46
+ const minEntryId = idFromNumber(previous.bounds.tail + 1);
47
+ const added = await scanRange(storage, conversationId, { minEntryId, maxEntryId: bounds.tail }, context);
48
+ range = extendRange(previous, bounds, freezeJson(added));
49
+ }
50
+ const { view } = range;
51
+ return {
52
+ view: {
53
+ ...view,
54
+ entries: [...view.entries],
55
+ contributions: [...view.contributions],
56
+ messages: [...view.messages],
57
+ },
58
+ range,
59
+ };
60
+ }
61
+ /** Committed context of one conversation: bounds captured on the Session line, entries derived off it. */
62
+ export async function readContext(session, storage, conversationId, context, at) {
63
+ const bounds = await session.readOnLine(() => captureContextBounds(storage, conversationId, context, at));
64
+ return deriveContext(storage, conversationId, bounds, context);
65
+ }
66
+ /**
67
+ * Derive the active transcript and model context of one conversation within captured bounds.
68
+ *
69
+ * H = newest visible head marker; the range runs from `H.head` (or transcript start) through the tail. Per target,
70
+ * the newest edit in the range wins. Context entries are H followed by the range's non-head entries.
71
+ */
72
+ export async function deriveContext(storage, conversationId, bounds, context) {
73
+ if (bounds === undefined)
74
+ return emptyView();
75
+ return deriveRange(bounds, await scanRange(storage, conversationId, rangeQuery(bounds), context)).view;
76
+ }
77
+ function emptyView() {
78
+ return { head: undefined, entries: [], contributions: [], messages: [] };
79
+ }
80
+ /** Derive the context view from the entries scanned within `bounds`. */
81
+ function deriveRange(bounds, entries) {
82
+ const edits = new Map();
83
+ // Edits of every entry in the range count, including older head markers that `selectActive()` drops.
84
+ for (const entry of entries)
85
+ for (const edit of entry.edits ?? [])
86
+ edits.set(edit.target, edit);
87
+ const active = selectActive(bounds.head, entries);
88
+ const contributions = active.map((entry) => contribute(entry, edits.get(entry.id)));
89
+ const { settled, open } = settle([], contributions.flat());
90
+ const messages = leadWithSystem([...settled, ...orderToolResults(open)]);
91
+ const view = { head: bounds.head, entries: active, contributions, messages };
92
+ return { bounds, entries, view, edited: new Set(edits.keys()), settled, open };
93
+ }
94
+ /**
95
+ * `previous` extended by the entries `added` after its tail under the same head marker: only their contributions and
96
+ * the open messages are derived. An added edit can change an earlier entry, so it derives the whole range again.
97
+ */
98
+ function extendRange(previous, bounds, added) {
99
+ const entries = [...previous.entries, ...added];
100
+ if (added.some((entry) => entry.edits !== undefined || entry.head !== undefined || previous.edited.has(entry.id))) {
101
+ return deriveRange(bounds, entries);
102
+ }
103
+ const contributions = added.map((entry) => contribute(entry, undefined));
104
+ const { settled, open } = settle(previous.settled, [...previous.open, ...contributions.flat()]);
105
+ const view = {
106
+ head: bounds.head,
107
+ entries: [...previous.view.entries, ...added],
108
+ contributions: [...previous.view.contributions, ...contributions],
109
+ messages: leadWithSystem([...settled, ...orderToolResults(open)]),
110
+ };
111
+ return { bounds, entries, view, edited: previous.edited, settled, open };
112
+ }
113
+ /**
114
+ * Move a system message that only user messages precede to the front. A run's input is committed before generation
115
+ * renders the system prompt, so a transcript, or the range after a compaction or reset, starts with user messages
116
+ * followed by the baseline system message. Providers treat only a leading system message as the initial prompt and tool
117
+ * set; without it, a later tool change rewrites the request's tool list and invalidates the whole prompt cache.
118
+ */
119
+ function leadWithSystem(messages) {
120
+ const index = messages.findIndex((message) => message.role !== "user");
121
+ if (index <= 0 || messages[index].role !== "system")
122
+ return messages;
123
+ return [messages[index], ...messages.slice(0, index), ...messages.slice(index + 1)];
124
+ }
125
+ /** One active entry's model messages after its edit and excluded stop reasons, before tool result ordering. */
126
+ function contribute(entry, edit) {
127
+ if (edit?.action === "omit")
128
+ return Object.freeze([]);
129
+ const contributed = edit?.action === "replace" ? edit.messages : (entry.model ?? []);
130
+ return Object.freeze(contributed.filter((message) => message.role !== "assistant" || !EXCLUDED_STOP_REASONS.has(message.stopReason)));
131
+ }
132
+ /** Objects `freezeJson()` froze with everything in them. `Object.isFrozen()` holds for shallow freezes too. */
133
+ const deeplyFrozen = new WeakSet();
134
+ /** Freeze a JSON value and everything in it. */
135
+ function freezeJson(value) {
136
+ if (value === null || typeof value !== "object" || deeplyFrozen.has(value))
137
+ return value;
138
+ for (const child of Object.values(value))
139
+ freezeJson(child);
140
+ Object.freeze(value);
141
+ deeplyFrozen.add(value);
142
+ return value;
143
+ }
144
+ /**
145
+ * Move the ordered messages before the last assistant message of `open` to `settled`. `orderToolResults()` of a
146
+ * sequence equals the concatenation over its parts when each later part starts with an assistant message.
147
+ */
148
+ function settle(settled, open) {
149
+ const last = open.findLastIndex((message) => message.role === "assistant");
150
+ if (last <= 0)
151
+ return { settled, open };
152
+ return { settled: [...settled, ...orderToolResults(open.slice(0, last))], open: open.slice(last) };
153
+ }
154
+ /** The raw active entries within captured bounds, without deriving model context. */
155
+ export async function activeEntries(storage, conversationId, bounds, context) {
156
+ if (bounds === undefined)
157
+ return [];
158
+ return selectActive(bounds.head, await scanRange(storage, conversationId, rangeQuery(bounds), context));
159
+ }
160
+ /** The visible range of `bounds`: from the head marker's head, or transcript start, through the tail. */
161
+ function rangeQuery(bounds) {
162
+ const head = bounds.head;
163
+ return head === undefined ? { maxEntryId: bounds.tail } : { minEntryId: head.head, maxEntryId: bounds.tail };
164
+ }
165
+ /** Visible entries within `range`, oldest first. */
166
+ async function scanRange(storage, conversationId, range, context) {
167
+ const entries = [];
168
+ let cursor;
169
+ do {
170
+ const page = await storage.scanEntries({ conversationId, ...range }, SCAN_PAGE_SIZE, cursor, context);
171
+ entries.push(...page.items);
172
+ cursor = page.next;
173
+ } while (cursor !== undefined);
174
+ return entries.reverse();
175
+ }
176
+ /** The head marker followed by the range's non-head entries, or the whole range without a marker. */
177
+ function selectActive(head, range) {
178
+ return head === undefined ? range : [head, ...range.filter((entry) => entry.head === undefined)];
179
+ }
180
+ /**
181
+ * Place each assistant's tool results directly after it in call order. Results are taken from the messages before
182
+ * the next assistant; a missing result is synthesized and unmatched results are dropped.
183
+ */
184
+ export function orderToolResults(messages) {
185
+ const ordered = [];
186
+ for (let index = 0; index < messages.length; index++) {
187
+ const message = messages[index];
188
+ if (message.role === "toolResult")
189
+ continue;
190
+ ordered.push(message);
191
+ if (message.role !== "assistant")
192
+ continue;
193
+ const calls = message.content.filter((content) => content.type === "toolCall");
194
+ if (calls.length === 0)
195
+ continue;
196
+ const results = new Map();
197
+ for (let next = index + 1; next < messages.length && messages[next].role !== "assistant"; next++) {
198
+ const candidate = messages[next];
199
+ if (candidate.role === "toolResult" && !results.has(candidate.toolCallId)) {
200
+ results.set(candidate.toolCallId, next);
201
+ }
202
+ }
203
+ for (const call of calls) {
204
+ const resultIndex = results.get(call.id);
205
+ ordered.push(resultIndex === undefined ? missingResult(call, message.timestamp) : messages[resultIndex]);
206
+ }
207
+ }
208
+ return ordered;
209
+ }
210
+ function missingResult(call, timestamp) {
211
+ return freezeJson({
212
+ role: "toolResult",
213
+ toolCallId: call.id,
214
+ toolName: call.name,
215
+ content: [{ type: "text", text: MISSING_RESULT_TEXT }],
216
+ isError: true,
217
+ details: { reason: "missing_result" },
218
+ timestamp,
219
+ });
220
+ }
221
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/harness/context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAKzC,MAAM,cAAc,GAAG,GAAG,CAAC;AAC3B,MAAM,qBAAqB,GAAgD,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;AACrH,MAAM,mBAAmB,GAAG,mEAAmE,CAAC;AAQhG;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACzC,OAAgB,EAChB,cAA8B,EAC9B,OAAgB,EAChB,EAAY;IAEZ,IAAI,IAAyB,CAAC;IAC9B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC3F,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;IAC1C,CAAC;SAAM,CAAC;QACP,IAAI,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YACtE,MAAM,IAAI,KAAK,CAAC,SAAS,EAAE,qCAAqC,cAAc,EAAE,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,GAAG,EAAE,CAAC;IACX,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,oBAAoB,CAAC,cAAc,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC;AAC1F,CAAC;AAsBD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACpC,OAAoB,EACpB,OAAgB,EAChB,cAA8B,EAC9B,OAAgB,EAChB,EAAuB,EACvB,QAAkC;IAElC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1G,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACzE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxB,IAAI,KAAmB,CAAC;IACxB,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;QAC5E,KAAK,GAAG,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAChH,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACjD,KAAK,GAAG,QAAQ,CAAC;IAClB,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC/C,KAAK,GAAG,WAAW,CAClB,MAAM,EACN,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,CAC3D,CAAC;IACH,CAAC;SAAM,CAAC;QACP,MAAM,UAAU,GAAG,YAAY,CAAU,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;QACzG,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACvB,OAAO;QACN,IAAI,EAAE;YACL,GAAG,IAAI;YACP,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YAC1B,aAAa,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC;YACtC,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;SAC5B;QACD,KAAK;KACL,CAAC;AACH,CAAC;AAED,0GAA0G;AAC1G,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,OAAoB,EACpB,OAAgB,EAChB,cAA8B,EAC9B,OAAgB,EAChB,EAAY;IAEZ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1G,OAAO,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAChE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,OAAgB,EAChB,cAA8B,EAC9B,MAAiC,EACjC,OAAgB;IAEhB,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,EAAE,CAAC;IAC7C,OAAO,WAAW,CAAC,MAAM,EAAE,MAAM,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACxG,CAAC;AAED,SAAS,SAAS;IACjB,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAC1E,CAAC;AAED,wEAAwE;AACxE,SAAS,WAAW,CAAC,MAAqB,EAAE,OAA+B;IAC1E,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC9C,qGAAqG;IACrG,KAAK,MAAM,KAAK,IAAI,OAAO;QAAE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,EAAE;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChG,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACpF,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC;IAC7E,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAChF,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAC,QAAsB,EAAE,MAAqB,EAAE,KAA6B;IAChG,MAAM,OAAO,GAAG,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC;IAChD,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACnH,OAAO,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;IACzE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAChG,MAAM,IAAI,GAAG;QACZ,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC;QAC7C,aAAa,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,aAAa,CAAC;QACjE,QAAQ,EAAE,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;KACjE,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,QAAmB;IAC1C,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACvE,IAAI,KAAK,IAAI,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAE,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IACtE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAE,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,+GAA+G;AAC/G,SAAS,UAAU,CAAC,KAAkB,EAAE,IAA6B;IACpE,IAAI,IAAI,EAAE,MAAM,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACrF,OAAO,MAAM,CAAC,MAAM,CACnB,WAAW,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAC/G,CAAC;AACH,CAAC;AAED,+GAA+G;AAC/G,MAAM,YAAY,GAAG,IAAI,OAAO,EAAU,CAAC;AAE3C,gDAAgD;AAChD,SAAS,UAAU,CAAI,KAAQ;IAC9B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACzF,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrB,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,MAAM,CACd,OAA2B,EAC3B,IAAwB;IAExB,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IAC3E,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACxC,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACpG,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,OAAgB,EAChB,cAA8B,EAC9B,MAAiC,EACjC,OAAgB;IAEhB,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACpC,OAAO,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACzG,CAAC;AAED,yGAAyG;AACzG,SAAS,UAAU,CAAC,MAAqB;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;AAC9G,CAAC;AAED,oDAAoD;AACpD,KAAK,UAAU,SAAS,CACvB,OAAgB,EAChB,cAA8B,EAC9B,KAAyC,EACzC,OAAgB;IAEhB,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,IAAI,MAA0B,CAAC;IAC/B,GAAG,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,EAAE,cAAc,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QACtG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5B,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC;IACpB,CAAC,QAAQ,MAAM,KAAK,SAAS,EAAE;IAC/B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;AAC1B,CAAC;AAED,qGAAqG;AACrG,SAAS,YAAY,CAAC,IAA2B,EAAE,KAA6B;IAC/E,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC;AAClG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAA4B;IAC5D,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAE,CAAC;QACjC,IAAI,OAAO,CAAC,IAAI,KAAK,YAAY;YAAE,SAAS;QAC5C,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;YAAE,SAAS;QAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,EAAuB,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QACpG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACjC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC1C,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,CAAC,EAAE,IAAI,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAE,CAAC,IAAI,KAAK,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;YACnG,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAE,CAAC;YAClC,IAAI,SAAS,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC3E,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YACzC,CAAC;QACF,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAE,CAAC,CAAC;QAC3G,CAAC;IACF,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,IAAc,EAAE,SAAiB;IACvD,OAAO,UAAU,CAAC;QACjB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE,IAAI,CAAC,EAAE;QACnB,QAAQ,EAAE,IAAI,CAAC,IAAI;QACnB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC;QACtD,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE;QACrC,SAAS;KACT,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import type { AssistantMessage, Message, ToolCall, ToolResultMessage } from \"@ny4n/ai/contracts\";\nimport type { Context } from \"@ny4n/chord\";\nimport { idFromNumber } from \"../ids.ts\";\nimport type { SessionImpl } from \"../session/session.ts\";\nimport type { ContextEdit, ConversationId, Cursor, EntryId, EntryQuery, EntryRecord, Storage } from \"../types.ts\";\nimport type { ContextView } from \"./types.ts\";\n\nconst SCAN_PAGE_SIZE = 256;\nconst EXCLUDED_STOP_REASONS: ReadonlySet<AssistantMessage[\"stopReason\"]> = new Set([\"aborted\", \"error\", \"deferred\"]);\nconst MISSING_RESULT_TEXT = \"Tool result unavailable: history ends before this call completed.\";\n\n/** Head marker and newest visible entry that fix one committed context range. */\nexport type ContextBounds = {\n\treadonly head: (EntryRecord & { readonly head: EntryId }) | undefined;\n\treadonly tail: EntryId;\n};\n\n/**\n * Capture the bounds of the current context, or of the context cut off at the visible entry `at`, with two O(1)\n * reads. Run this on the Session line; entries at or below the tail are immutable, so `deriveContext()` can then scan\n * them off the line.\n */\nexport async function captureContextBounds(\n\tstorage: Storage,\n\tconversationId: ConversationId,\n\tcontext: Context,\n\tat?: EntryId,\n): Promise<ContextBounds | undefined> {\n\tlet tail: EntryId | undefined;\n\tif (at === undefined) {\n\t\ttail = (await storage.scanEntries({ conversationId }, 1, undefined, context)).items[0]?.id;\n\t\tif (tail === undefined) return undefined;\n\t} else {\n\t\tif ((await storage.entry(conversationId, at, context)) === undefined) {\n\t\t\tthrow new Error(`Entry ${at} is not visible from conversation ${conversationId}`);\n\t\t}\n\t\ttail = at;\n\t}\n\treturn { head: await storage.findLatestHeadMarker(conversationId, tail, context), tail };\n}\n\n/**\n * One context read: the visible entries it scanned, from the head marker's head, or transcript start, through\n * `bounds.tail`, oldest first, and the view derived from them. Entries at or below the tail never change, so a later\n * read with the same head marker extends both.\n */\nexport type ContextRange = {\n\treadonly bounds: ContextBounds;\n\treadonly entries: readonly EntryRecord[];\n\treadonly view: ContextView;\n\t/** Targets of the edits in `entries`. */\n\treadonly edited: ReadonlySet<EntryId>;\n\t/**\n\t * `view.messages` from the contributed messages before the last assistant message. Tool results are ordered within\n\t * the messages up to the next assistant message, so later entries cannot change these.\n\t */\n\treadonly settled: readonly Message[];\n\t/** Contributed messages from the last assistant message on, before tool result ordering. */\n\treadonly open: readonly Message[];\n};\n\n/**\n * `readContext()` that reuses `previous`, an earlier range of the same conversation: with the same head marker, only\n * entries after its tail are scanned. Returns the view and the range to pass to the next read. A range outlives the\n * read, so its entries are frozen like `MemoryStorage` records, and the returned view has its own arrays.\n */\nexport async function readContextFrom(\n\tsession: SessionImpl,\n\tstorage: Storage,\n\tconversationId: ConversationId,\n\tcontext: Context,\n\tat: EntryId | undefined,\n\tprevious: ContextRange | undefined,\n): Promise<{ readonly view: ContextView; readonly range: ContextRange | undefined }> {\n\tconst bounds = await session.readOnLine(() => captureContextBounds(storage, conversationId, context, at));\n\tif (bounds === undefined) return { view: emptyView(), range: undefined };\n\tfreezeJson(bounds.head);\n\tlet range: ContextRange;\n\tif (previous === undefined || previous.bounds.head?.id !== bounds.head?.id) {\n\t\trange = deriveRange(bounds, freezeJson(await scanRange(storage, conversationId, rangeQuery(bounds), context)));\n\t} else if (bounds.tail === previous.bounds.tail) {\n\t\trange = previous;\n\t} else if (bounds.tail < previous.bounds.tail) {\n\t\trange = deriveRange(\n\t\t\tbounds,\n\t\t\tprevious.entries.filter((entry) => entry.id <= bounds.tail),\n\t\t);\n\t} else {\n\t\tconst minEntryId = idFromNumber<EntryId>(previous.bounds.tail + 1);\n\t\tconst added = await scanRange(storage, conversationId, { minEntryId, maxEntryId: bounds.tail }, context);\n\t\trange = extendRange(previous, bounds, freezeJson(added));\n\t}\n\tconst { view } = range;\n\treturn {\n\t\tview: {\n\t\t\t...view,\n\t\t\tentries: [...view.entries],\n\t\t\tcontributions: [...view.contributions],\n\t\t\tmessages: [...view.messages],\n\t\t},\n\t\trange,\n\t};\n}\n\n/** Committed context of one conversation: bounds captured on the Session line, entries derived off it. */\nexport async function readContext(\n\tsession: SessionImpl,\n\tstorage: Storage,\n\tconversationId: ConversationId,\n\tcontext: Context,\n\tat?: EntryId,\n): Promise<ContextView> {\n\tconst bounds = await session.readOnLine(() => captureContextBounds(storage, conversationId, context, at));\n\treturn deriveContext(storage, conversationId, bounds, context);\n}\n\n/**\n * Derive the active transcript and model context of one conversation within captured bounds.\n *\n * H = newest visible head marker; the range runs from `H.head` (or transcript start) through the tail. Per target,\n * the newest edit in the range wins. Context entries are H followed by the range's non-head entries.\n */\nexport async function deriveContext(\n\tstorage: Storage,\n\tconversationId: ConversationId,\n\tbounds: ContextBounds | undefined,\n\tcontext: Context,\n): Promise<ContextView> {\n\tif (bounds === undefined) return emptyView();\n\treturn deriveRange(bounds, await scanRange(storage, conversationId, rangeQuery(bounds), context)).view;\n}\n\nfunction emptyView(): ContextView {\n\treturn { head: undefined, entries: [], contributions: [], messages: [] };\n}\n\n/** Derive the context view from the entries scanned within `bounds`. */\nfunction deriveRange(bounds: ContextBounds, entries: readonly EntryRecord[]): ContextRange {\n\tconst edits = new Map<EntryId, ContextEdit>();\n\t// Edits of every entry in the range count, including older head markers that `selectActive()` drops.\n\tfor (const entry of entries) for (const edit of entry.edits ?? []) edits.set(edit.target, edit);\n\tconst active = selectActive(bounds.head, entries);\n\tconst contributions = active.map((entry) => contribute(entry, edits.get(entry.id)));\n\tconst { settled, open } = settle([], contributions.flat());\n\tconst messages = leadWithSystem([...settled, ...orderToolResults(open)]);\n\tconst view = { head: bounds.head, entries: active, contributions, messages };\n\treturn { bounds, entries, view, edited: new Set(edits.keys()), settled, open };\n}\n\n/**\n * `previous` extended by the entries `added` after its tail under the same head marker: only their contributions and\n * the open messages are derived. An added edit can change an earlier entry, so it derives the whole range again.\n */\nfunction extendRange(previous: ContextRange, bounds: ContextBounds, added: readonly EntryRecord[]): ContextRange {\n\tconst entries = [...previous.entries, ...added];\n\tif (added.some((entry) => entry.edits !== undefined || entry.head !== undefined || previous.edited.has(entry.id))) {\n\t\treturn deriveRange(bounds, entries);\n\t}\n\tconst contributions = added.map((entry) => contribute(entry, undefined));\n\tconst { settled, open } = settle(previous.settled, [...previous.open, ...contributions.flat()]);\n\tconst view = {\n\t\thead: bounds.head,\n\t\tentries: [...previous.view.entries, ...added],\n\t\tcontributions: [...previous.view.contributions, ...contributions],\n\t\tmessages: leadWithSystem([...settled, ...orderToolResults(open)]),\n\t};\n\treturn { bounds, entries, view, edited: previous.edited, settled, open };\n}\n\n/**\n * Move a system message that only user messages precede to the front. A run's input is committed before generation\n * renders the system prompt, so a transcript, or the range after a compaction or reset, starts with user messages\n * followed by the baseline system message. Providers treat only a leading system message as the initial prompt and tool\n * set; without it, a later tool change rewrites the request's tool list and invalidates the whole prompt cache.\n */\nfunction leadWithSystem(messages: Message[]): Message[] {\n\tconst index = messages.findIndex((message) => message.role !== \"user\");\n\tif (index <= 0 || messages[index]!.role !== \"system\") return messages;\n\treturn [messages[index]!, ...messages.slice(0, index), ...messages.slice(index + 1)];\n}\n\n/** One active entry's model messages after its edit and excluded stop reasons, before tool result ordering. */\nfunction contribute(entry: EntryRecord, edit: ContextEdit | undefined): readonly Message[] {\n\tif (edit?.action === \"omit\") return Object.freeze([]);\n\tconst contributed = edit?.action === \"replace\" ? edit.messages : (entry.model ?? []);\n\treturn Object.freeze(\n\t\tcontributed.filter((message) => message.role !== \"assistant\" || !EXCLUDED_STOP_REASONS.has(message.stopReason)),\n\t);\n}\n\n/** Objects `freezeJson()` froze with everything in them. `Object.isFrozen()` holds for shallow freezes too. */\nconst deeplyFrozen = new WeakSet<object>();\n\n/** Freeze a JSON value and everything in it. */\nfunction freezeJson<T>(value: T): T {\n\tif (value === null || typeof value !== \"object\" || deeplyFrozen.has(value)) return value;\n\tfor (const child of Object.values(value)) freezeJson(child);\n\tObject.freeze(value);\n\tdeeplyFrozen.add(value);\n\treturn value;\n}\n\n/**\n * Move the ordered messages before the last assistant message of `open` to `settled`. `orderToolResults()` of a\n * sequence equals the concatenation over its parts when each later part starts with an assistant message.\n */\nfunction settle(\n\tsettled: readonly Message[],\n\topen: readonly Message[],\n): { readonly settled: readonly Message[]; readonly open: readonly Message[] } {\n\tconst last = open.findLastIndex((message) => message.role === \"assistant\");\n\tif (last <= 0) return { settled, open };\n\treturn { settled: [...settled, ...orderToolResults(open.slice(0, last))], open: open.slice(last) };\n}\n\n/** The raw active entries within captured bounds, without deriving model context. */\nexport async function activeEntries(\n\tstorage: Storage,\n\tconversationId: ConversationId,\n\tbounds: ContextBounds | undefined,\n\tcontext: Context,\n): Promise<readonly EntryRecord[]> {\n\tif (bounds === undefined) return [];\n\treturn selectActive(bounds.head, await scanRange(storage, conversationId, rangeQuery(bounds), context));\n}\n\n/** The visible range of `bounds`: from the head marker's head, or transcript start, through the tail. */\nfunction rangeQuery(bounds: ContextBounds): Omit<EntryQuery, \"conversationId\"> {\n\tconst head = bounds.head;\n\treturn head === undefined ? { maxEntryId: bounds.tail } : { minEntryId: head.head, maxEntryId: bounds.tail };\n}\n\n/** Visible entries within `range`, oldest first. */\nasync function scanRange(\n\tstorage: Storage,\n\tconversationId: ConversationId,\n\trange: Omit<EntryQuery, \"conversationId\">,\n\tcontext: Context,\n): Promise<EntryRecord[]> {\n\tconst entries: EntryRecord[] = [];\n\tlet cursor: Cursor | undefined;\n\tdo {\n\t\tconst page = await storage.scanEntries({ conversationId, ...range }, SCAN_PAGE_SIZE, cursor, context);\n\t\tentries.push(...page.items);\n\t\tcursor = page.next;\n\t} while (cursor !== undefined);\n\treturn entries.reverse();\n}\n\n/** The head marker followed by the range's non-head entries, or the whole range without a marker. */\nfunction selectActive(head: ContextBounds[\"head\"], range: readonly EntryRecord[]): readonly EntryRecord[] {\n\treturn head === undefined ? range : [head, ...range.filter((entry) => entry.head === undefined)];\n}\n\n/**\n * Place each assistant's tool results directly after it in call order. Results are taken from the messages before\n * the next assistant; a missing result is synthesized and unmatched results are dropped.\n */\nexport function orderToolResults(messages: readonly Message[]): Message[] {\n\tconst ordered: Message[] = [];\n\tfor (let index = 0; index < messages.length; index++) {\n\t\tconst message = messages[index]!;\n\t\tif (message.role === \"toolResult\") continue;\n\t\tordered.push(message);\n\t\tif (message.role !== \"assistant\") continue;\n\t\tconst calls = message.content.filter((content): content is ToolCall => content.type === \"toolCall\");\n\t\tif (calls.length === 0) continue;\n\t\tconst results = new Map<string, number>();\n\t\tfor (let next = index + 1; next < messages.length && messages[next]!.role !== \"assistant\"; next++) {\n\t\t\tconst candidate = messages[next]!;\n\t\t\tif (candidate.role === \"toolResult\" && !results.has(candidate.toolCallId)) {\n\t\t\t\tresults.set(candidate.toolCallId, next);\n\t\t\t}\n\t\t}\n\t\tfor (const call of calls) {\n\t\t\tconst resultIndex = results.get(call.id);\n\t\t\tordered.push(resultIndex === undefined ? missingResult(call, message.timestamp) : messages[resultIndex]!);\n\t\t}\n\t}\n\treturn ordered;\n}\n\nfunction missingResult(call: ToolCall, timestamp: number): ToolResultMessage {\n\treturn freezeJson({\n\t\trole: \"toolResult\",\n\t\ttoolCallId: call.id,\n\t\ttoolName: call.name,\n\t\tcontent: [{ type: \"text\", text: MISSING_RESULT_TEXT }],\n\t\tisError: true,\n\t\tdetails: { reason: \"missing_result\" },\n\t\ttimestamp,\n\t});\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import type { TSchema } from "@ny4n/ai/contracts";
2
+ import type { JsonValue } from "@ny4n/chord";
3
+ import type { AnyTask, Extension, HookRegistration, HooksOf, PromptSection, ToolRegistration, Wrap } from "./types.ts";
4
+ /** Identity function that types an extension. */
5
+ export declare function defineExtension<Tool extends ToolRegistration = ToolRegistration>(extension: Extension<Tool>): Extension<Tool>;
6
+ /** Identity function that types a tool: `args` from `parameters`, details from what it reports. */
7
+ export declare function defineTool<TParameters extends TSchema, TDetails extends JsonValue = JsonValue>(tool: ToolRegistration<TParameters, TDetails>): ToolRegistration<TParameters, TDetails>;
8
+ /** A prompt section; tagged unless `tag` is false. */
9
+ export declare function section<Tool extends ToolRegistration = ToolRegistration>(key: string, render: PromptSection<Tool>["render"], options?: {
10
+ readonly tag?: boolean;
11
+ }): PromptSection<Tool>;
12
+ /** Hook handlers for tasks with `task`'s name. */
13
+ export declare function hook<K extends AnyTask>(task: K, handlers: Partial<HooksOf<K>>): HookRegistration;
14
+ /** Wrap the tool named like `tool` wherever the wrapping extension is selected. */
15
+ export declare function wrapTool<Tool extends ToolRegistration>(tool: Tool, wrapper: (tool: Tool) => Tool): Wrap<Tool>;
16
+ /** Wrap the section `key` wherever the wrapping extension is selected. */
17
+ export declare function wrapSection<Tool extends ToolRegistration = ToolRegistration>(key: string, wrapper: (section: PromptSection<Tool>) => PromptSection<Tool>): Wrap<Tool>;
18
+ //# sourceMappingURL=define.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/harness/define.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvH,iDAAiD;AACjD,wBAAgB,eAAe,CAAC,IAAI,SAAS,gBAAgB,GAAG,gBAAgB,EAC/E,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,GACxB,SAAS,CAAC,IAAI,CAAC,CAEjB;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,WAAW,SAAS,OAAO,EAAE,QAAQ,SAAS,SAAS,GAAG,SAAS,EAC7F,IAAI,EAAE,gBAAgB,CAAC,WAAW,EAAE,QAAQ,CAAC,GAC3C,gBAAgB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAEzC;AAED,sDAAsD;AACtD,wBAAgB,OAAO,CAAC,IAAI,SAAS,gBAAgB,GAAG,gBAAgB,EACvE,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EACrC,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,aAAa,CAAC,IAAI,CAAC,CAErB;AAED,kDAAkD;AAClD,wBAAgB,IAAI,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAEhG;AAED,mFAAmF;AACnF,wBAAgB,QAAQ,CAAC,IAAI,SAAS,gBAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAE7G;AAED,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,IAAI,SAAS,gBAAgB,GAAG,gBAAgB,EAC3E,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,aAAa,CAAC,IAAI,CAAC,GAC5D,IAAI,CAAC,IAAI,CAAC,CAEZ"}
@@ -0,0 +1,25 @@
1
+ /** Identity function that types an extension. */
2
+ export function defineExtension(extension) {
3
+ return extension;
4
+ }
5
+ /** Identity function that types a tool: `args` from `parameters`, details from what it reports. */
6
+ export function defineTool(tool) {
7
+ return tool;
8
+ }
9
+ /** A prompt section; tagged unless `tag` is false. */
10
+ export function section(key, render, options) {
11
+ return options?.tag === undefined ? { key, render } : { key, render, tag: options.tag };
12
+ }
13
+ /** Hook handlers for tasks with `task`'s name. */
14
+ export function hook(task, handlers) {
15
+ return { task: task.definition.name, handlers };
16
+ }
17
+ /** Wrap the tool named like `tool` wherever the wrapping extension is selected. */
18
+ export function wrapTool(tool, wrapper) {
19
+ return { tool: tool.name, wrap: wrapper };
20
+ }
21
+ /** Wrap the section `key` wherever the wrapping extension is selected. */
22
+ export function wrapSection(key, wrapper) {
23
+ return { section: key, wrap: wrapper };
24
+ }
25
+ //# sourceMappingURL=define.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/harness/define.ts"],"names":[],"mappings":"AAIA,iDAAiD;AACjD,MAAM,UAAU,eAAe,CAC9B,SAA0B;IAE1B,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,UAAU,CACzB,IAA6C;IAE7C,OAAO,IAAI,CAAC;AACb,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,OAAO,CACtB,GAAW,EACX,MAAqC,EACrC,OAAoC;IAEpC,OAAO,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;AACzF,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,IAAI,CAAoB,IAAO,EAAE,QAA6B;IAC7E,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC;AACjD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,QAAQ,CAAgC,IAAU,EAAE,OAA6B;IAChG,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3C,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,WAAW,CAC1B,GAAW,EACX,OAA8D;IAE9D,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACxC,CAAC","sourcesContent":["import type { TSchema } from \"@ny4n/ai/contracts\";\nimport type { JsonValue } from \"@ny4n/chord\";\nimport type { AnyTask, Extension, HookRegistration, HooksOf, PromptSection, ToolRegistration, Wrap } from \"./types.ts\";\n\n/** Identity function that types an extension. */\nexport function defineExtension<Tool extends ToolRegistration = ToolRegistration>(\n\textension: Extension<Tool>,\n): Extension<Tool> {\n\treturn extension;\n}\n\n/** Identity function that types a tool: `args` from `parameters`, details from what it reports. */\nexport function defineTool<TParameters extends TSchema, TDetails extends JsonValue = JsonValue>(\n\ttool: ToolRegistration<TParameters, TDetails>,\n): ToolRegistration<TParameters, TDetails> {\n\treturn tool;\n}\n\n/** A prompt section; tagged unless `tag` is false. */\nexport function section<Tool extends ToolRegistration = ToolRegistration>(\n\tkey: string,\n\trender: PromptSection<Tool>[\"render\"],\n\toptions?: { readonly tag?: boolean },\n): PromptSection<Tool> {\n\treturn options?.tag === undefined ? { key, render } : { key, render, tag: options.tag };\n}\n\n/** Hook handlers for tasks with `task`'s name. */\nexport function hook<K extends AnyTask>(task: K, handlers: Partial<HooksOf<K>>): HookRegistration {\n\treturn { task: task.definition.name, handlers };\n}\n\n/** Wrap the tool named like `tool` wherever the wrapping extension is selected. */\nexport function wrapTool<Tool extends ToolRegistration>(tool: Tool, wrapper: (tool: Tool) => Tool): Wrap<Tool> {\n\treturn { tool: tool.name, wrap: wrapper };\n}\n\n/** Wrap the section `key` wherever the wrapping extension is selected. */\nexport function wrapSection<Tool extends ToolRegistration = ToolRegistration>(\n\tkey: string,\n\twrapper: (section: PromptSection<Tool>) => PromptSection<Tool>,\n): Wrap<Tool> {\n\treturn { section: key, wrap: wrapper };\n}\n"]}
@@ -0,0 +1,180 @@
1
+ import type { AssistantMessage, Message, Usage } from "@ny4n/ai/contracts";
2
+ import type { Context, JsonValue } from "@ny4n/chord";
3
+ import type { ConversationId, EntryRecord, JsonObject, SubmissionId, SubmissionRecord, TaskId, WatchEnd } from "../types.ts";
4
+ import type { InboxItem } from "./inbox.ts";
5
+ import type { CompactionStatus, NestedToolSlot, ToolSlot } from "./live.ts";
6
+ import type { AgentState, CompactionReason, Harness, NestedToolExecutionResult, ToolDiagnostic } from "./types.ts";
7
+ import { type UsageState } from "./usage.ts";
8
+ type Block = AssistantMessage["content"][number];
9
+ type QueuedItem = {
10
+ id: SubmissionId;
11
+ mode: InboxItem["mode"];
12
+ };
13
+ /** One change to the in-flight assistant message, relative to that message. */
14
+ export type MessageChange = {
15
+ type: "text_start" | "thinking_start" | "toolcall_start";
16
+ contentIndex: number;
17
+ block: Block;
18
+ } | {
19
+ type: "text_delta" | "thinking_delta";
20
+ contentIndex: number;
21
+ delta: string;
22
+ } | {
23
+ type: "toolcall_delta";
24
+ contentIndex: number;
25
+ path: readonly (string | number)[];
26
+ delta: string;
27
+ } | {
28
+ type: "block";
29
+ contentIndex: number;
30
+ block: Block;
31
+ } | {
32
+ type: "message";
33
+ message: AssistantMessage;
34
+ };
35
+ export type SnapshotEvent = {
36
+ type: "snapshot";
37
+ entries: readonly EntryRecord[];
38
+ run?: {
39
+ inputs: readonly SubmissionId[];
40
+ };
41
+ /** Current generation attempt: its in-flight partial, retry backoff, or deferred poll. */
42
+ generation?: {
43
+ attempt: number;
44
+ message?: AssistantMessage;
45
+ retry?: {
46
+ at: number;
47
+ error: string;
48
+ };
49
+ deferred?: {
50
+ pollAt: number;
51
+ };
52
+ };
53
+ tools: readonly ToolSlot[];
54
+ /** `nyan.live.nestedTools`: nested calls of running tool calls. */
55
+ nestedTools: readonly NestedToolSlot[];
56
+ /** `nyan.live.compactions`: live compactions with their attempt and retry backoff. */
57
+ compactions: readonly CompactionStatus[];
58
+ inbox: readonly QueuedItem[];
59
+ /** `nyan.agent`; `{}` when absent. */
60
+ agent: AgentState;
61
+ usage: UsageState;
62
+ };
63
+ /** Experimental agent event, shaped like the coding agent's session events (spec §9.4). */
64
+ export type AgentEvent = SnapshotEvent | {
65
+ type: "run_start";
66
+ inputs: readonly SubmissionId[];
67
+ } | {
68
+ type: "run_end";
69
+ inputs: readonly SubmissionId[];
70
+ } | {
71
+ type: "turn_start";
72
+ } | {
73
+ type: "turn_end";
74
+ } | {
75
+ type: "message_start";
76
+ message: Message;
77
+ }
78
+ /** `usage` is the partial's current usage, as in the coding agent's JSON mode. */
79
+ | {
80
+ type: "message_update";
81
+ usage: Usage;
82
+ changes: readonly MessageChange[];
83
+ } | {
84
+ type: "message_end";
85
+ entry: EntryRecord;
86
+ } | ({
87
+ type: "tool_execution_start";
88
+ args: JsonObject;
89
+ } & ToolEventCall) | ({
90
+ type: "tool_execution_update";
91
+ /** A front trim and then an append of the retained window, or its replacement. */
92
+ output?: {
93
+ trimStart?: number;
94
+ append?: string;
95
+ } | {
96
+ set: string;
97
+ };
98
+ details?: JsonValue;
99
+ diagnostics?: readonly ToolDiagnostic[];
100
+ } & ToolEventCall)
101
+ /**
102
+ * A model-issued call ends with its result `entry`, a nested call with its `result`. Both are absent when the tool
103
+ * task faulted or was orphaned, or when the call's slot left `nyan.live` unfinished: its run ended, or its parent
104
+ * settled first.
105
+ */
106
+ | ({
107
+ type: "tool_execution_end";
108
+ entry?: EntryRecord;
109
+ result?: NestedToolExecutionResult;
110
+ } & ToolEventCall) | {
111
+ type: "inbox_update";
112
+ items: readonly QueuedItem[];
113
+ } | {
114
+ type: "submission";
115
+ record: SubmissionRecord;
116
+ } | {
117
+ type: "auto_retry_start";
118
+ attempt: number;
119
+ at: number;
120
+ errorMessage: string;
121
+ } | {
122
+ type: "auto_retry_end";
123
+ attempt: number;
124
+ } | {
125
+ type: "deferred_poll";
126
+ pollAt: number;
127
+ } | {
128
+ type: "entry_appended";
129
+ entry: EntryRecord;
130
+ } | {
131
+ type: "agent_changed";
132
+ agent: AgentState;
133
+ } | {
134
+ type: "usage_changed";
135
+ usage: UsageState;
136
+ } | {
137
+ type: "task_failed";
138
+ taskId: TaskId;
139
+ kind: string;
140
+ message: string;
141
+ } | {
142
+ type: "compaction_start";
143
+ taskId: TaskId;
144
+ reason: CompactionReason;
145
+ blocking: boolean;
146
+ }
147
+ /** The task's receipt tells whether it produced a summary; the summary entry has its own events. */
148
+ | {
149
+ type: "compaction_end";
150
+ taskId: TaskId;
151
+ reason: CompactionReason;
152
+ };
153
+ /**
154
+ * Which call a tool event is about. `toolCallId` is the call's ID in the transcript and in tool events: the provider's
155
+ * ID for a model-issued call, `<parent call ID>/<key>` for a nested one. Match events by it; do not parse it. `taskId`
156
+ * is the call's tool task, absent for a call that never got one (not offered, or not started in a sequential round).
157
+ * A nested call also names the call that made it, by call ID and by tool task.
158
+ */
159
+ export type ToolEventCall = {
160
+ toolCallId: string;
161
+ toolName: string;
162
+ taskId?: TaskId;
163
+ parentToolCallId?: string;
164
+ parentTaskId?: TaskId;
165
+ };
166
+ /** Serialized stream of one conversation's event batches, one per commit. */
167
+ export interface AgentEventStream {
168
+ /** The `snapshot` event at attachment. */
169
+ readonly snapshot: SnapshotEvent;
170
+ start(listener: (events: readonly AgentEvent[], context: Context) => Promise<void>): void;
171
+ stop(): Promise<WatchEnd>;
172
+ readonly closed: Promise<WatchEnd>;
173
+ }
174
+ /**
175
+ * Experimental: attach to one conversation's agent events (spec §9.4). The snapshot and the registration for later
176
+ * commits are captured atomically on the Session line; overflow replaces undelivered batches with one snapshot.
177
+ */
178
+ export declare function watchEvents(harness: Harness, conversationId: ConversationId, context: Context): Promise<AgentEventStream>;
179
+ export {};
180
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/harness/events.ts"],"names":[],"mappings":"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"}