@kortix/sdk 0.12.8 → 0.13.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 (261) hide show
  1. package/README.md +3 -6
  2. package/dist/browser/session-sync/session-sync-registry.d.ts +7 -2
  3. package/dist/browser/session-sync/session-sync-registry.d.ts.map +1 -1
  4. package/dist/browser/session-sync/session-sync-registry.js +33 -44
  5. package/dist/browser/session-sync/session-sync-registry.js.map +1 -1
  6. package/dist/browser/stores/opencode-compaction-store.d.ts +9 -3
  7. package/dist/browser/stores/opencode-compaction-store.d.ts.map +1 -1
  8. package/dist/browser/stores/opencode-compaction-store.js +5 -12
  9. package/dist/browser/stores/opencode-compaction-store.js.map +1 -1
  10. package/dist/browser/stores/sandbox-connection-store.d.ts +28 -17
  11. package/dist/browser/stores/sandbox-connection-store.d.ts.map +1 -1
  12. package/dist/browser/stores/sandbox-connection-store.js +32 -84
  13. package/dist/browser/stores/sandbox-connection-store.js.map +1 -1
  14. package/dist/browser/stores/session-working-store.d.ts +73 -0
  15. package/dist/browser/stores/session-working-store.d.ts.map +1 -0
  16. package/dist/browser/stores/session-working-store.js +86 -0
  17. package/dist/browser/stores/session-working-store.js.map +1 -0
  18. package/dist/browser/stores/sync-store/types.d.ts +14 -4
  19. package/dist/browser/stores/sync-store/types.d.ts.map +1 -1
  20. package/dist/browser/stores/sync-store.d.ts +140 -3
  21. package/dist/browser/stores/sync-store.d.ts.map +1 -1
  22. package/dist/browser/stores/sync-store.js +425 -36
  23. package/dist/browser/stores/sync-store.js.map +1 -1
  24. package/dist/core/client/kortix.d.ts +102 -1
  25. package/dist/core/client/kortix.d.ts.map +1 -1
  26. package/dist/core/client/kortix.js +78 -0
  27. package/dist/core/client/kortix.js.map +1 -1
  28. package/dist/core/files/client.d.ts +50 -2
  29. package/dist/core/files/client.d.ts.map +1 -1
  30. package/dist/core/files/client.js +253 -44
  31. package/dist/core/files/client.js.map +1 -1
  32. package/dist/core/files/types.d.ts +11 -0
  33. package/dist/core/files/types.d.ts.map +1 -1
  34. package/dist/core/http/abort-error.d.ts +89 -0
  35. package/dist/core/http/abort-error.d.ts.map +1 -0
  36. package/dist/core/http/abort-error.js +190 -0
  37. package/dist/core/http/abort-error.js.map +1 -0
  38. package/dist/core/http/api-client.d.ts.map +1 -1
  39. package/dist/core/http/api-client.js +18 -4
  40. package/dist/core/http/api-client.js.map +1 -1
  41. package/dist/core/rest/platform-client/github-app.d.ts +13 -0
  42. package/dist/core/rest/platform-client/github-app.d.ts.map +1 -1
  43. package/dist/core/rest/platform-client/github-app.js +2 -0
  44. package/dist/core/rest/platform-client/github-app.js.map +1 -1
  45. package/dist/core/rest/platform-client/members.d.ts +10 -64
  46. package/dist/core/rest/platform-client/members.d.ts.map +1 -1
  47. package/dist/core/rest/platform-client/members.js +10 -28
  48. package/dist/core/rest/platform-client/members.js.map +1 -1
  49. package/dist/core/rest/projects-client/accounts.d.ts +30 -1
  50. package/dist/core/rest/projects-client/accounts.d.ts.map +1 -1
  51. package/dist/core/rest/projects-client/accounts.js +1 -1
  52. package/dist/core/rest/projects-client/accounts.js.map +1 -1
  53. package/dist/core/rest/projects-client/apps.d.ts +13 -0
  54. package/dist/core/rest/projects-client/apps.d.ts.map +1 -1
  55. package/dist/core/rest/projects-client/apps.js.map +1 -1
  56. package/dist/core/rest/projects-client/assignments.d.ts +114 -0
  57. package/dist/core/rest/projects-client/assignments.d.ts.map +1 -0
  58. package/dist/core/rest/projects-client/assignments.js +91 -0
  59. package/dist/core/rest/projects-client/assignments.js.map +1 -0
  60. package/dist/core/rest/projects-client/billing.d.ts +10 -1
  61. package/dist/core/rest/projects-client/billing.d.ts.map +1 -1
  62. package/dist/core/rest/projects-client/billing.js +11 -2
  63. package/dist/core/rest/projects-client/billing.js.map +1 -1
  64. package/dist/core/rest/projects-client/connectors.d.ts +2 -0
  65. package/dist/core/rest/projects-client/connectors.d.ts.map +1 -1
  66. package/dist/core/rest/projects-client/connectors.js.map +1 -1
  67. package/dist/core/rest/projects-client/files.js +2 -2
  68. package/dist/core/rest/projects-client/files.js.map +1 -1
  69. package/dist/core/rest/projects-client/gateway.d.ts +51 -0
  70. package/dist/core/rest/projects-client/gateway.d.ts.map +1 -1
  71. package/dist/core/rest/projects-client/gateway.js.map +1 -1
  72. package/dist/core/rest/projects-client/iam.d.ts +51 -3
  73. package/dist/core/rest/projects-client/iam.d.ts.map +1 -1
  74. package/dist/core/rest/projects-client/iam.js +18 -1
  75. package/dist/core/rest/projects-client/iam.js.map +1 -1
  76. package/dist/core/rest/projects-client/index.d.ts +1 -0
  77. package/dist/core/rest/projects-client/index.d.ts.map +1 -1
  78. package/dist/core/rest/projects-client/index.js +1 -0
  79. package/dist/core/rest/projects-client/index.js.map +1 -1
  80. package/dist/core/rest/projects-client/projects.d.ts +1 -1
  81. package/dist/core/rest/projects-client/projects.d.ts.map +1 -1
  82. package/dist/core/rest/projects-client/projects.js +3 -0
  83. package/dist/core/rest/projects-client/projects.js.map +1 -1
  84. package/dist/core/rest/projects-client/secrets.d.ts +11 -0
  85. package/dist/core/rest/projects-client/secrets.d.ts.map +1 -1
  86. package/dist/core/rest/projects-client/secrets.js +1 -1
  87. package/dist/core/rest/projects-client/secrets.js.map +1 -1
  88. package/dist/core/rest/projects-client/session-costs.d.ts +33 -0
  89. package/dist/core/rest/projects-client/session-costs.d.ts.map +1 -1
  90. package/dist/core/rest/projects-client/session-costs.js.map +1 -1
  91. package/dist/core/rest/projects-client/sessions.d.ts +226 -2
  92. package/dist/core/rest/projects-client/sessions.d.ts.map +1 -1
  93. package/dist/core/rest/projects-client/sessions.js +101 -4
  94. package/dist/core/rest/projects-client/sessions.js.map +1 -1
  95. package/dist/core/rest/projects-client/shared.d.ts +10 -1
  96. package/dist/core/rest/projects-client/shared.d.ts.map +1 -1
  97. package/dist/core/rest/projects-client/shared.js.map +1 -1
  98. package/dist/core/rest/projects-client/tokens.d.ts +13 -1
  99. package/dist/core/rest/projects-client/tokens.d.ts.map +1 -1
  100. package/dist/core/rest/projects-client/tokens.js +7 -2
  101. package/dist/core/rest/projects-client/tokens.js.map +1 -1
  102. package/dist/core/rest/projects-client/triggers.d.ts +69 -2
  103. package/dist/core/rest/projects-client/triggers.d.ts.map +1 -1
  104. package/dist/core/rest/projects-client/triggers.js +1 -1
  105. package/dist/core/rest/projects-client/triggers.js.map +1 -1
  106. package/dist/core/session/compaction.d.ts +98 -0
  107. package/dist/core/session/compaction.d.ts.map +1 -0
  108. package/dist/core/session/compaction.js +108 -0
  109. package/dist/core/session/compaction.js.map +1 -0
  110. package/dist/core/session/health.d.ts +22 -0
  111. package/dist/core/session/health.d.ts.map +1 -1
  112. package/dist/core/session/health.js +31 -5
  113. package/dist/core/session/health.js.map +1 -1
  114. package/dist/core/session/index.d.ts +2 -0
  115. package/dist/core/session/index.d.ts.map +1 -1
  116. package/dist/core/session/index.js +2 -0
  117. package/dist/core/session/index.js.map +1 -1
  118. package/dist/core/session/message-queue.d.ts +79 -15
  119. package/dist/core/session/message-queue.d.ts.map +1 -1
  120. package/dist/core/session/message-queue.js +73 -27
  121. package/dist/core/session/message-queue.js.map +1 -1
  122. package/dist/core/session/rewind.d.ts +76 -10
  123. package/dist/core/session/rewind.d.ts.map +1 -1
  124. package/dist/core/session/rewind.js +68 -11
  125. package/dist/core/session/rewind.js.map +1 -1
  126. package/dist/core/session/working.d.ts +241 -0
  127. package/dist/core/session/working.d.ts.map +1 -0
  128. package/dist/core/session/working.js +261 -0
  129. package/dist/core/session/working.js.map +1 -0
  130. package/dist/core/session-sync/session-sync-controller.d.ts +35 -20
  131. package/dist/core/session-sync/session-sync-controller.d.ts.map +1 -1
  132. package/dist/core/session-sync/session-sync-controller.js +48 -115
  133. package/dist/core/session-sync/session-sync-controller.js.map +1 -1
  134. package/dist/core/stream/event-stream.d.ts +22 -0
  135. package/dist/core/stream/event-stream.d.ts.map +1 -1
  136. package/dist/core/stream/event-stream.js +132 -36
  137. package/dist/core/stream/event-stream.js.map +1 -1
  138. package/dist/core/turns/grouping.d.ts +32 -2
  139. package/dist/core/turns/grouping.d.ts.map +1 -1
  140. package/dist/core/turns/grouping.js +31 -2
  141. package/dist/core/turns/grouping.js.map +1 -1
  142. package/dist/core/turns/index.d.ts +1 -0
  143. package/dist/core/turns/index.d.ts.map +1 -1
  144. package/dist/core/turns/index.js +1 -0
  145. package/dist/core/turns/index.js.map +1 -1
  146. package/dist/core/turns/open-turn.d.ts +81 -0
  147. package/dist/core/turns/open-turn.d.ts.map +1 -0
  148. package/dist/core/turns/open-turn.js +77 -0
  149. package/dist/core/turns/open-turn.js.map +1 -0
  150. package/dist/core/turns/state.js +26 -26
  151. package/dist/core/turns/state.js.map +1 -1
  152. package/dist/core/turns/types.d.ts +5 -0
  153. package/dist/core/turns/types.d.ts.map +1 -1
  154. package/dist/index.d.ts +2 -1
  155. package/dist/index.d.ts.map +1 -1
  156. package/dist/index.js +2 -1
  157. package/dist/index.js.map +1 -1
  158. package/dist/kortix.esm.min.js +25 -25
  159. package/dist/kortix.global.js +25 -25
  160. package/dist/node/server.d.ts.map +1 -1
  161. package/dist/node/server.js +14 -2
  162. package/dist/node/server.js.map +1 -1
  163. package/dist/react/index.d.ts +2 -1
  164. package/dist/react/index.d.ts.map +1 -1
  165. package/dist/react/index.js +7 -1
  166. package/dist/react/index.js.map +1 -1
  167. package/dist/react/initial-session-pin.d.ts +17 -0
  168. package/dist/react/initial-session-pin.d.ts.map +1 -1
  169. package/dist/react/initial-session-pin.js +58 -0
  170. package/dist/react/initial-session-pin.js.map +1 -1
  171. package/dist/react/opencode.d.ts +6 -2
  172. package/dist/react/opencode.d.ts.map +1 -1
  173. package/dist/react/opencode.js +5 -1
  174. package/dist/react/opencode.js.map +1 -1
  175. package/dist/react/prefetch-session-start.d.ts +10 -4
  176. package/dist/react/prefetch-session-start.d.ts.map +1 -1
  177. package/dist/react/prefetch-session-start.js +10 -4
  178. package/dist/react/prefetch-session-start.js.map +1 -1
  179. package/dist/react/query-keys.d.ts +8 -2
  180. package/dist/react/query-keys.d.ts.map +1 -1
  181. package/dist/react/query-keys.js +8 -2
  182. package/dist/react/query-keys.js.map +1 -1
  183. package/dist/react/session-start-stash.d.ts +25 -0
  184. package/dist/react/session-start-stash.d.ts.map +1 -1
  185. package/dist/react/session-start-stash.js +34 -3
  186. package/dist/react/session-start-stash.js.map +1 -1
  187. package/dist/react/session-title-sync.d.ts +5 -1
  188. package/dist/react/session-title-sync.d.ts.map +1 -1
  189. package/dist/react/session-title-sync.js +16 -4
  190. package/dist/react/session-title-sync.js.map +1 -1
  191. package/dist/react/use-can.d.ts +105 -0
  192. package/dist/react/use-can.d.ts.map +1 -0
  193. package/dist/react/use-can.js +190 -0
  194. package/dist/react/use-can.js.map +1 -0
  195. package/dist/react/use-canonical-opencode-session.d.ts +6 -1
  196. package/dist/react/use-canonical-opencode-session.d.ts.map +1 -1
  197. package/dist/react/use-canonical-opencode-session.js +46 -3
  198. package/dist/react/use-canonical-opencode-session.js.map +1 -1
  199. package/dist/react/use-opencode-events/handle-event.d.ts +10 -0
  200. package/dist/react/use-opencode-events/handle-event.d.ts.map +1 -1
  201. package/dist/react/use-opencode-events/handle-event.js +76 -7
  202. package/dist/react/use-opencode-events/handle-event.js.map +1 -1
  203. package/dist/react/use-opencode-events/helpers.d.ts +21 -8
  204. package/dist/react/use-opencode-events/helpers.d.ts.map +1 -1
  205. package/dist/react/use-opencode-events/helpers.js +25 -26
  206. package/dist/react/use-opencode-events/helpers.js.map +1 -1
  207. package/dist/react/use-opencode-events/index.d.ts.map +1 -1
  208. package/dist/react/use-opencode-events/index.js +43 -26
  209. package/dist/react/use-opencode-events/index.js.map +1 -1
  210. package/dist/react/use-opencode-events/use-event-stream-refs.d.ts.map +1 -1
  211. package/dist/react/use-opencode-events/use-event-stream-refs.js +66 -3
  212. package/dist/react/use-opencode-events/use-event-stream-refs.js.map +1 -1
  213. package/dist/react/use-opencode-local.d.ts +17 -0
  214. package/dist/react/use-opencode-local.d.ts.map +1 -1
  215. package/dist/react/use-opencode-local.js +41 -7
  216. package/dist/react/use-opencode-local.js.map +1 -1
  217. package/dist/react/use-opencode-sessions/messages.d.ts +101 -1
  218. package/dist/react/use-opencode-sessions/messages.d.ts.map +1 -1
  219. package/dist/react/use-opencode-sessions/messages.js +481 -63
  220. package/dist/react/use-opencode-sessions/messages.js.map +1 -1
  221. package/dist/react/use-project-apps.d.ts +24 -1
  222. package/dist/react/use-project-apps.d.ts.map +1 -1
  223. package/dist/react/use-project-apps.js +5 -3
  224. package/dist/react/use-project-apps.js.map +1 -1
  225. package/dist/react/use-runtime-boot-stalled.d.ts +32 -0
  226. package/dist/react/use-runtime-boot-stalled.d.ts.map +1 -0
  227. package/dist/react/use-runtime-boot-stalled.js +48 -0
  228. package/dist/react/use-runtime-boot-stalled.js.map +1 -0
  229. package/dist/react/use-runtime-reconnect.d.ts +67 -1
  230. package/dist/react/use-runtime-reconnect.d.ts.map +1 -1
  231. package/dist/react/use-runtime-reconnect.js +116 -18
  232. package/dist/react/use-runtime-reconnect.js.map +1 -1
  233. package/dist/react/use-session-prompts.d.ts +113 -0
  234. package/dist/react/use-session-prompts.d.ts.map +1 -0
  235. package/dist/react/use-session-prompts.js +242 -0
  236. package/dist/react/use-session-prompts.js.map +1 -0
  237. package/dist/react/use-session-send.d.ts +169 -20
  238. package/dist/react/use-session-send.d.ts.map +1 -1
  239. package/dist/react/use-session-send.js +178 -29
  240. package/dist/react/use-session-send.js.map +1 -1
  241. package/dist/react/use-session-sync.d.ts +35 -2
  242. package/dist/react/use-session-sync.d.ts.map +1 -1
  243. package/dist/react/use-session-sync.js +46 -9
  244. package/dist/react/use-session-sync.js.map +1 -1
  245. package/dist/react/use-session-working.d.ts +57 -0
  246. package/dist/react/use-session-working.d.ts.map +1 -0
  247. package/dist/react/use-session-working.js +178 -0
  248. package/dist/react/use-session-working.js.map +1 -0
  249. package/dist/react/use-session.d.ts +122 -5
  250. package/dist/react/use-session.d.ts.map +1 -1
  251. package/dist/react/use-session.js +343 -69
  252. package/dist/react/use-session.js.map +1 -1
  253. package/package.json +2 -2
  254. package/dist/browser/stores/tab-store.d.ts +0 -91
  255. package/dist/browser/stores/tab-store.d.ts.map +0 -1
  256. package/dist/browser/stores/tab-store.js +0 -369
  257. package/dist/browser/stores/tab-store.js.map +0 -1
  258. package/dist/core/session/send-queue.d.ts +0 -70
  259. package/dist/core/session/send-queue.d.ts.map +0 -1
  260. package/dist/core/session/send-queue.js +0 -116
  261. package/dist/core/session/send-queue.js.map +0 -1
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Is this session COMPACTING? One pure projection, shaped like `working.ts`.
3
+ *
4
+ * Compaction is not a turn — `GET .../turn` reports nothing for it and the
5
+ * working projection deliberately knows nothing about it — but the composer
6
+ * still has to hold while it runs, so it had its own answer. That answer was a
7
+ * client-only boolean set by `startCompaction` and cleared ONLY by the
8
+ * `session.compacted` SSE frame: an unbounded latch on a signal that can be
9
+ * lost, which is the same defect the working projection was built to end.
10
+ *
11
+ * Two honest inputs replace it:
12
+ *
13
+ * - `serverCompactingAtMs` — `Session.time.compacting`, the runtime's own
14
+ * record, which nothing in this repo read before. It is what makes a
15
+ * compaction started by a second device or a trigger visible here at all.
16
+ * - `optimisticAtMs` — this tab's own `/compact`, which is accepted locally
17
+ * long before the row exists, and is therefore BOUNDED.
18
+ */
19
+ /**
20
+ * How long this tab's own `/compact` may claim `compacting` on its own.
21
+ *
22
+ * Generous next to a real compaction (a summarize call against the whole
23
+ * transcript), and finite because the release signal is one SSE frame. Missing
24
+ * that frame — a backgrounded tab, a stream reconnect — used to pin the
25
+ * composer for the lifetime of the tab.
26
+ */
27
+ export const OPTIMISTIC_COMPACTION_MAX_MS = 60_000;
28
+ /**
29
+ * Precedence, and there are only two rules:
30
+ *
31
+ * 1. The runtime says a compaction is open → compacting. It is an observation
32
+ * of the server's own row, so it is not bounded here; the row is cleared by
33
+ * the refetch `session.compacted` already triggers.
34
+ * 2. Otherwise this tab's own unanswered `/compact`, until it ages out.
35
+ */
36
+ export function projectCompacting(inputs) {
37
+ if (inputs.serverCompactingAtMs !== null)
38
+ return true;
39
+ if (inputs.optimisticAtMs === null)
40
+ return false;
41
+ return inputs.nowMs - inputs.optimisticAtMs < OPTIMISTIC_COMPACTION_MAX_MS;
42
+ }
43
+ /**
44
+ * The next instant at which {@link projectCompacting} could answer differently
45
+ * on its own — i.e. when the optimistic stamp ages out.
46
+ *
47
+ * The projection is pure and moves with `nowMs`, so something has to ask it
48
+ * again at that instant or the cap is never applied. Nothing else re-renders
49
+ * when a compaction quietly outlives its stamp: the store slot has not changed,
50
+ * the transcript is idle, and the lost frame is precisely the case where no
51
+ * further event arrives. Same mechanism, same reason, as `workingExpiryAtMs`.
52
+ *
53
+ * `null` when nothing is left to expire (deadlines already past are skipped, so
54
+ * re-arming from what this returns terminates).
55
+ */
56
+ export function compactionExpiryAtMs(inputs) {
57
+ if (inputs.serverCompactingAtMs !== null)
58
+ return null;
59
+ if (inputs.optimisticAtMs === null)
60
+ return null;
61
+ const deadline = inputs.optimisticAtMs + OPTIMISTIC_COMPACTION_MAX_MS;
62
+ return deadline > inputs.nowMs ? deadline : null;
63
+ }
64
+ /**
65
+ * How long a SERVER-observed `Session.time.compacting` may go unconfirmed
66
+ * before the caller must force a fresh read instead of trusting the cached
67
+ * row forever.
68
+ *
69
+ * Rule 1 of {@link projectCompacting} treats any non-null
70
+ * `serverCompactingAtMs` as authoritative for as long as it is observed — by
71
+ * design, since it is the runtime's own record, not a guess, and
72
+ * {@link compactionExpiryAtMs} deliberately arms no timer for it. But the
73
+ * only event that is SUPPOSED to clear that cached row
74
+ * (`session.compacted`, handled in `use-opencode-events/handle-event.ts`) can
75
+ * be lost the exact same way any SSE frame can — a backgrounded tab, a
76
+ * stream reconnect — and the targeted refetch that handler fires is its own
77
+ * network call that can itself fail. `useOpenCodeSession`
78
+ * (`use-opencode-sessions/sessions.ts`) reads the row with
79
+ * `staleTime: Infinity` and nothing else ever refetches it, so without a
80
+ * ceiling here "authoritative" becomes "wedged for the tab's lifetime" the
81
+ * moment either of those is lost — reproducing the exact unbounded-latch
82
+ * class this module exists to end.
83
+ *
84
+ * This is that ceiling. It does not change `projectCompacting`'s answer —
85
+ * rule 1 stays authoritative right up to the deadline — it only tells the
86
+ * caller (`use-session.ts`) WHEN to stop trusting the cached row and ask the
87
+ * server again, independent of whether `session.compacted` ever arrives.
88
+ */
89
+ export const SERVER_COMPACTION_REVALIDATE_MS = 90_000;
90
+ /**
91
+ * The next instant at which a server-observed compaction flag needs a live
92
+ * re-check (see {@link SERVER_COMPACTION_REVALIDATE_MS}), or `null` when no
93
+ * server flag is currently observed.
94
+ *
95
+ * Unlike {@link compactionExpiryAtMs}, this CAN return an instant already in
96
+ * the past: the deadline is anchored to `serverCompactingAtMs` (when the flag
97
+ * was FIRST observed), not to `nowMs`, so a session mounted well after
98
+ * compaction started — or one whose revalidation kept re-arming because the
99
+ * server kept confirming `compacting: true` — can already be overdue the
100
+ * moment this is read. The caller fires the re-check immediately in that
101
+ * case rather than skip it: a stale flag discovered late is still stale.
102
+ */
103
+ export function serverCompactionRevalidateAtMs(inputs) {
104
+ if (inputs.serverCompactingAtMs === null)
105
+ return null;
106
+ return inputs.serverCompactingAtMs + SERVER_COMPACTION_REVALIDATE_MS;
107
+ }
108
+ //# sourceMappingURL=compaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../../src/core/session/compaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAUnD;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAwB;IACxD,IAAI,MAAM,CAAC,oBAAoB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,MAAM,CAAC,cAAc,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACjD,OAAO,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,cAAc,GAAG,4BAA4B,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAwB;IAC3D,IAAI,MAAM,CAAC,oBAAoB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,MAAM,CAAC,cAAc,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,cAAc,GAAG,4BAA4B,CAAC;IACtE,OAAO,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,MAAM,CAAC;AAEtD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,8BAA8B,CAAC,MAAwB;IACrE,IAAI,MAAM,CAAC,oBAAoB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACtD,OAAO,MAAM,CAAC,oBAAoB,GAAG,+BAA+B,CAAC;AACvE,CAAC"}
@@ -22,6 +22,24 @@ export type SessionHealthResponse = {
22
22
  reason?: string | null;
23
23
  message?: string | null;
24
24
  };
25
+ /**
26
+ * Which hop of the sandbox proxy produced a failure, as the proxy itself
27
+ * reports it. Mirrors `apps/api/src/sandbox-proxy/proxy-hop.ts` — the two lists
28
+ * are one wire contract and must not drift.
29
+ *
30
+ * - `control_plane` — the platform answered from the session row; the box
31
+ * was never dialled.
32
+ * - `provider_ingress` — no address for the box, or its edge refused.
33
+ * - `daemon` — the box answers, the runtime process does not.
34
+ * - `upstream_port` — the user's own process on an app port is down.
35
+ *
36
+ * Only the middle two are evidence that the RUNTIME is unreachable.
37
+ */
38
+ export type ProxyHop = 'control_plane' | 'provider_ingress' | 'daemon' | 'upstream_port';
39
+ /** Narrow an untrusted header/body value to a hop, or null. Anything the proxy
40
+ * did not attribute — an intermediary's own 502, an older deployment — must
41
+ * read as "unattributed", never as a hop we happen to be lenient about. */
42
+ export declare function parseProxyHop(value: unknown): ProxyHop | null;
25
43
  export interface SessionHealthResult {
26
44
  /** HTTP status of the probe (0 when there is no active runtime URL). */
27
45
  status: number;
@@ -30,6 +48,10 @@ export interface SessionHealthResult {
30
48
  health: SessionHealthResponse | null;
31
49
  /** Raw response text — useful for non-ok diagnostics. */
32
50
  body: string;
51
+ /** Which proxy hop produced a failure, or null when nothing attributed it. */
52
+ hop: ProxyHop | null;
53
+ /** The status the failing hop itself returned, when it returned one. */
54
+ upstreamStatus: number | null;
33
55
  }
34
56
  /** Whether a health payload indicates the OpenCode runtime is ready. */
35
57
  export declare function isRuntimeReady(health: SessionHealthResponse | null): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../../src/core/session/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;IACZ,iEAAiE;IACjE,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACrC,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAU5E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,EAC1B,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,mBAAmB,CAAC,CAgB9B"}
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../../src/core/session/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,QAAQ,GAAG,eAAe,GAAG,kBAAkB,GAAG,QAAQ,GAAG,eAAe,CAAC;AASzF;;4EAE4E;AAC5E,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAE7D;AAED,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;IACZ,iEAAiE;IACjE,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACrC,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;IACrB,wEAAwE;IACxE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAU5E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,EAC1B,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,mBAAmB,CAAC,CAgC9B"}
@@ -15,6 +15,18 @@
15
15
  */
16
16
  import { authenticatedFetch } from '../http/auth.js';
17
17
  import { getActiveOpenCodeUrl } from './server-store/active.js';
18
+ const PROXY_HOPS = [
19
+ 'control_plane',
20
+ 'provider_ingress',
21
+ 'daemon',
22
+ 'upstream_port',
23
+ ];
24
+ /** Narrow an untrusted header/body value to a hop, or null. Anything the proxy
25
+ * did not attribute — an intermediary's own 502, an older deployment — must
26
+ * read as "unattributed", never as a hop we happen to be lenient about. */
27
+ export function parseProxyHop(value) {
28
+ return typeof value === 'string' && PROXY_HOPS.includes(value) ? value : null;
29
+ }
18
30
  /** Whether a health payload indicates the OpenCode runtime is ready. */
19
31
  export function isRuntimeReady(health) {
20
32
  if (!health)
@@ -42,16 +54,30 @@ export function isRuntimeReady(health) {
42
54
  export async function getSessionHealth(runtimeUrl, init) {
43
55
  const url = (runtimeUrl === undefined ? getActiveOpenCodeUrl() : runtimeUrl) || null;
44
56
  if (!url)
45
- return { status: 0, ok: false, health: null, body: '' };
57
+ return { status: 0, ok: false, health: null, body: '', hop: null, upstreamStatus: null };
46
58
  const res = await authenticatedFetch(`${url}/kortix/health`, { method: 'GET', ...init }, { retryOnAuthError: false });
47
59
  const body = await res.text().catch(() => '');
48
- let health = null;
60
+ let parsed = null;
49
61
  try {
50
- health = body ? JSON.parse(body) : null;
62
+ parsed = body ? JSON.parse(body) : null;
51
63
  }
52
64
  catch {
53
- health = null;
65
+ parsed = null;
54
66
  }
55
- return { status: res.status, ok: res.ok, health, body };
67
+ const health = parsed;
68
+ // Header first, body second. The header survives a HEAD and the proxy's HTML
69
+ // error page; the body fallback covers a deployment whose CORS config does not
70
+ // expose the header yet, where reading it would silently yield null.
71
+ const hop = parseProxyHop(res.headers.get('X-Kortix-Proxy-Hop')) ?? parseProxyHop(parsed?.hop);
72
+ // `Number(null)` and `Number('')` are both 0, so the `> 0` guard is what
73
+ // separates "absent" from a real status — there is no HTTP status 0.
74
+ const headerUpstream = Number(res.headers.get('X-Kortix-Upstream-Status'));
75
+ const bodyUpstream = parsed?.upstream_status;
76
+ const upstreamStatus = Number.isFinite(headerUpstream) && headerUpstream > 0
77
+ ? headerUpstream
78
+ : typeof bodyUpstream === 'number'
79
+ ? bodyUpstream
80
+ : null;
81
+ return { status: res.status, ok: res.ok, health, body, hop, upstreamStatus };
56
82
  }
57
83
  //# sourceMappingURL=health.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/core/session/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAsB7D,wEAAwE;AACxE,MAAM,UAAU,cAAc,CAAC,MAAoC;IACjE,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,YAAY,KAAK,IAAI,CAAC;IAC3E,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS;QAC/B,OAAO,MAAM,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC;IAC9D,OAAO,CACL,MAAM,CAAC,MAAM,KAAK,UAAU;QAC5B,MAAM,CAAC,MAAM,KAAK,MAAM;QACxB,MAAM,CAAC,MAAM,KAAK,OAAO,CAC1B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAA0B,EAC1B,IAAkB;IAElB,MAAM,GAAG,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;IACrF,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClE,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAClC,GAAG,GAAG,gBAAgB,EACtB,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAC1B,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAC5B,CAAC;IACF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9C,IAAI,MAAM,GAAiC,IAAI,CAAC;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAA2B,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC1D,CAAC"}
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/core/session/health.ts"],"names":[],"mappings":"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"}
@@ -19,4 +19,6 @@ export * from './preview.js';
19
19
  export * from './preview-auth.js';
20
20
  export * from './preview-probe.js';
21
21
  export * from './presentation.js';
22
+ export * from './working.js';
23
+ export * from './compaction.js';
22
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
@@ -19,4 +19,6 @@ export * from './preview.js';
19
19
  export * from './preview-auth.js';
20
20
  export * from './preview-probe.js';
21
21
  export * from './presentation.js';
22
+ export * from './working.js';
23
+ export * from './compaction.js';
22
24
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
@@ -1,9 +1,20 @@
1
1
  /**
2
+ * @deprecated since 0.12.9 — Kortix owns prompt ordering server-side
3
+ * (`POST /v1/projects/:projectId/sessions/:sessionId/prompts`). This module is
4
+ * retained ONLY so `@kortix/sdk/message-queue`, published in 0.12.8, keeps
5
+ * resolving for external consumers. It is not used by any Kortix host and will
6
+ * be removed in the next major.
7
+ *
2
8
  * The rules a message queue obeys, as pure functions.
3
9
  *
4
10
  * A message typed while the agent is mid-run is held until the turn ends. That
5
- * much is easy. What is not easy — and what three previous implementations got
6
- * wrong — is *when* it is released and *how many times*.
11
+ * much is easy. What is not easy — and what four implementations got wrong — is
12
+ * *when* it is released and *how many times*. The answer this module could
13
+ * never reach is that a browser tab does not know: it reads one guess at the
14
+ * session's state, a second tab reads another, and a closed tab loses the queue
15
+ * outright. The durable inbox above decides admission from the same turn
16
+ * authority `GET .../turn` serves from, so there is one queue per session
17
+ * rather than one per tab.
7
18
  *
8
19
  * The failures this module exists to make impossible:
9
20
  *
@@ -19,16 +30,23 @@
19
30
  * - **A queued message sending under the wrong model.** `agent`, `model`, and
20
31
  * `variant` are captured at enqueue and carried verbatim.
21
32
  *
22
- * The claimed item stays at `pending[0]` while it is in flight rather than
23
- * being spliced out. That makes `inFlightId` a real lock (one field to check),
24
- * makes "reorder cannot cross the in-flight slot" an index clamp rather than a
25
- * special case, and means a crash between claim and dispatch leaves the message
26
- * visible in the queue instead of silently gone.
33
+ * Claimed items stay at the head of `pending` while they are in flight rather
34
+ * than being spliced out. That makes the in-flight ids a real lock (one field
35
+ * to check), makes "reorder cannot cross what is sending" an index clamp rather
36
+ * than a special case, and means a crash between claim and dispatch leaves the
37
+ * messages visible in the queue instead of silently gone.
27
38
  *
28
39
  * Framework-free, storage-free, and timer-free by construction. There is no
29
40
  * `Date.now()` and no `crypto` here: ids and timestamps are inputs, so every
30
41
  * transition is deterministic and testable without fakes. Persistence and the
31
42
  * decision of *when* the turn ended belong to the host.
43
+ *
44
+ * **The export list is frozen at what 0.12.8 published.** `claimBatch` and
45
+ * `inFlightIdsOf` were added after that release, drove the browser batch drain
46
+ * that no longer exists, and are absent from the published `.d.ts` — so they
47
+ * are gone rather than deprecated. Nothing new may be added here either: an
48
+ * addition would be a new promise made by a module that exists only to keep an
49
+ * old one.
32
50
  */
33
51
  /** What a host hands in when the user queues a message. */
34
52
  export interface QueuedMessageInput<TFile = unknown, TMention = unknown> {
@@ -49,6 +67,29 @@ export interface QueuedMessageInput<TFile = unknown, TMention = unknown> {
49
67
  modelID: string;
50
68
  } | null;
51
69
  variant?: string | null;
70
+ /**
71
+ * A `/` slash command, when this entry runs one instead of sending `text`.
72
+ *
73
+ * The queue held only prompts, so a host with a command to send had nowhere
74
+ * to put it and ran it immediately — straight past a busy agent, ahead of
75
+ * everything already waiting. Ordering is the queue's entire purpose, and a
76
+ * command is a turn like any other; the only difference is which call puts it
77
+ * on the wire, which is the host's business at dispatch time.
78
+ *
79
+ * `name`, not a resolved command object: entries are serialized to survive a
80
+ * reload, and the command list is re-read when the entry actually runs, so a
81
+ * queued command can never go stale against a list that changed underneath
82
+ * it. `text` still carries the arguments, so an entry stays renderable and
83
+ * editable with no special case.
84
+ */
85
+ command?: {
86
+ name: string;
87
+ /** Where the chip sat in `text`, for display. See the host's serializer. */
88
+ split?: {
89
+ before: string;
90
+ after: string;
91
+ };
92
+ };
52
93
  createdAt: number;
53
94
  }
54
95
  /** A queued message, once the queue owns it. */
@@ -60,12 +101,33 @@ export interface QueuedMessage<TFile = unknown, TMention = unknown> extends Queu
60
101
  }
61
102
  /** One session's queue. */
62
103
  export interface SessionQueue<TFile = unknown, TMention = unknown> {
63
- /** Waiting to send, oldest first. `pending[0]` is in flight when claimed. */
104
+ /** Waiting to send, oldest first. The leading run is in flight when claimed. */
64
105
  pending: QueuedMessage<TFile, TMention>[];
65
106
  /** Gave up. Never blocks `pending`; a host offers these a retry. */
66
107
  failed: QueuedMessage<TFile, TMention>[];
67
- /** The id of the item currently on the wire, or null. This is the lock. */
108
+ /**
109
+ * The head of what is on the wire, or null.
110
+ *
111
+ * Kept because it is published API and because most readers only ever want
112
+ * "is something sending, and which row is it". `inFlightIds[0]` and this
113
+ * field are the same value by construction — every transition writes both.
114
+ */
68
115
  inFlightId: string | null;
116
+ /**
117
+ * Every id on the wire right now, oldest first. Empty when idle.
118
+ *
119
+ * A batch claim puts more than one message on a single prompt, so the lock
120
+ * has to name all of them: a row the user can still edit, remove or reorder
121
+ * is a row that is not being sent, and `inFlightId` alone could only ever
122
+ * protect the first.
123
+ *
124
+ * Optional because it was added after this type shipped, and requiring it
125
+ * would stop a consumer's hand-built `SessionQueue` literal from compiling.
126
+ * Every transition in this module writes it, and `createSessionQueue()`
127
+ * returns it, so it is absent only on a state that predates it — which is
128
+ * why every read goes through `inFlight` below rather than `?? []`.
129
+ */
130
+ inFlightIds?: string[];
69
131
  }
70
132
  export declare function createSessionQueue<TFile = unknown, TMention = unknown>(): SessionQueue<TFile, TMention>;
71
133
  /**
@@ -87,7 +149,7 @@ export declare function claimNext<TFile, TMention>(state: SessionQueue<TFile, TM
87
149
  state: SessionQueue<TFile, TMention>;
88
150
  claimed?: QueuedMessage<TFile, TMention>;
89
151
  };
90
- /** The send landed. Drop the item and free the queue. */
152
+ /** The send landed. Drop everything it carried and free the queue. */
91
153
  export declare function completeInFlight<TFile, TMention>(state: SessionQueue<TFile, TMention>): SessionQueue<TFile, TMention>;
92
154
  /**
93
155
  * The send failed for good. Set it aside — do not put it back at the head.
@@ -99,16 +161,18 @@ export declare function completeInFlight<TFile, TMention>(state: SessionQueue<TF
99
161
  export declare function failInFlight<TFile, TMention>(state: SessionQueue<TFile, TMention>, error: string): SessionQueue<TFile, TMention>;
100
162
  /** Put a failed item back at the tail, with its error cleared. */
101
163
  export declare function retryFailed<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string): SessionQueue<TFile, TMention>;
102
- /** Drop a message. Refuses the in-flight item — it is already on the wire. */
164
+ /** Drop a message. Refuses anything in flight — it is already on the wire. */
103
165
  export declare function removeQueued<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string): SessionQueue<TFile, TMention>;
104
- /** Rewrite a queued message. Refuses the in-flight item. */
166
+ /** Rewrite a queued message. Refuses anything in flight. */
105
167
  export declare function editQueued<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string, text: string): SessionQueue<TFile, TMention>;
106
168
  /**
107
169
  * Move a pending message to `toIndex`.
108
170
  *
109
- * `toIndex` is clamped to the movable range. While something is in flight that
110
- * range starts at 1, so nothing can be reordered into or past the slot that is
111
- * already sending — and the in-flight item itself cannot move at all.
171
+ * `toIndex` is clamped to the movable range. That range starts after whatever
172
+ * is in flight, so nothing can be reordered into or past a message already on
173
+ * the wire — and an in-flight message cannot move at all. That is one slot for
174
+ * a `claimNext` lock, and several for a state rehydrated from a host that
175
+ * claimed a batch.
112
176
  */
113
177
  export declare function reorderQueued<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string, toIndex: number): SessionQueue<TFile, TMention>;
114
178
  //# sourceMappingURL=message-queue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"message-queue.d.ts","sourceRoot":"","sources":["../../../src/core/session/message-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,2DAA2D;AAC3D,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IACrE,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACvD,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gDAAgD;AAChD,MAAM,WAAW,aAAa,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO,CAChE,SAAQ,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC;IAC3C,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,2BAA2B;AAC3B,MAAM,WAAW,YAAY,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IAC/D,6EAA6E;IAC7E,OAAO,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;IAC1C,oEAAoE;IACpE,MAAM,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;IACzC,2EAA2E;IAC3E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,kBAAkB,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO,KAAK,YAAY,CACrF,KAAK,EACL,QAAQ,CACT,CAEA;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,QAAQ,EACrC,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,KAAK,EAAE,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,GACzC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAE/B;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EACvC,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,GACnC;IAAE,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;CAAE,CAcpF;AAED,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAC9C,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,GACnC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAO/B;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAC1C,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,KAAK,EAAE,MAAM,GACZ,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAU/B;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,EACzC,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,EAAE,EAAE,MAAM,GACT,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAU/B;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAC1C,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,EAAE,EAAE,MAAM,GACT,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAS/B;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,EACxC,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GACX,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAQ/B;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAC3C,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAa/B"}
1
+ {"version":3,"file":"message-queue.d.ts","sourceRoot":"","sources":["../../../src/core/session/message-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,2DAA2D;AAC3D,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IACrE,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACvD,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,4EAA4E;QAC5E,KAAK,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3C,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gDAAgD;AAChD,MAAM,WAAW,aAAa,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO,CAChE,SAAQ,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC;IAC3C,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,2BAA2B;AAC3B,MAAM,WAAW,YAAY,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IAC/D,gFAAgF;IAChF,OAAO,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;IAC1C,oEAAoE;IACpE,MAAM,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;IACzC;;;;;;OAMG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO,KAAK,YAAY,CACrF,KAAK,EACL,QAAQ,CACT,CAEA;AAkBD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,QAAQ,EACrC,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,KAAK,EAAE,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,GACzC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAE/B;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EACvC,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,GACnC;IAAE,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;CAAE,CAepF;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAC9C,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,GACnC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAS/B;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAC1C,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,KAAK,EAAE,MAAM,GACZ,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAgB/B;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,EACzC,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,EAAE,EAAE,MAAM,GACT,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAU/B;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAC1C,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,EAAE,EAAE,MAAM,GACT,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAS/B;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,EACxC,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GACX,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAQ/B;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAC3C,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EACpC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAc/B"}
@@ -1,9 +1,20 @@
1
1
  /**
2
+ * @deprecated since 0.12.9 — Kortix owns prompt ordering server-side
3
+ * (`POST /v1/projects/:projectId/sessions/:sessionId/prompts`). This module is
4
+ * retained ONLY so `@kortix/sdk/message-queue`, published in 0.12.8, keeps
5
+ * resolving for external consumers. It is not used by any Kortix host and will
6
+ * be removed in the next major.
7
+ *
2
8
  * The rules a message queue obeys, as pure functions.
3
9
  *
4
10
  * A message typed while the agent is mid-run is held until the turn ends. That
5
- * much is easy. What is not easy — and what three previous implementations got
6
- * wrong — is *when* it is released and *how many times*.
11
+ * much is easy. What is not easy — and what four implementations got wrong — is
12
+ * *when* it is released and *how many times*. The answer this module could
13
+ * never reach is that a browser tab does not know: it reads one guess at the
14
+ * session's state, a second tab reads another, and a closed tab loses the queue
15
+ * outright. The durable inbox above decides admission from the same turn
16
+ * authority `GET .../turn` serves from, so there is one queue per session
17
+ * rather than one per tab.
7
18
  *
8
19
  * The failures this module exists to make impossible:
9
20
  *
@@ -19,19 +30,42 @@
19
30
  * - **A queued message sending under the wrong model.** `agent`, `model`, and
20
31
  * `variant` are captured at enqueue and carried verbatim.
21
32
  *
22
- * The claimed item stays at `pending[0]` while it is in flight rather than
23
- * being spliced out. That makes `inFlightId` a real lock (one field to check),
24
- * makes "reorder cannot cross the in-flight slot" an index clamp rather than a
25
- * special case, and means a crash between claim and dispatch leaves the message
26
- * visible in the queue instead of silently gone.
33
+ * Claimed items stay at the head of `pending` while they are in flight rather
34
+ * than being spliced out. That makes the in-flight ids a real lock (one field
35
+ * to check), makes "reorder cannot cross what is sending" an index clamp rather
36
+ * than a special case, and means a crash between claim and dispatch leaves the
37
+ * messages visible in the queue instead of silently gone.
27
38
  *
28
39
  * Framework-free, storage-free, and timer-free by construction. There is no
29
40
  * `Date.now()` and no `crypto` here: ids and timestamps are inputs, so every
30
41
  * transition is deterministic and testable without fakes. Persistence and the
31
42
  * decision of *when* the turn ended belong to the host.
43
+ *
44
+ * **The export list is frozen at what 0.12.8 published.** `claimBatch` and
45
+ * `inFlightIdsOf` were added after that release, drove the browser batch drain
46
+ * that no longer exists, and are absent from the published `.d.ts` — so they
47
+ * are gone rather than deprecated. Nothing new may be added here either: an
48
+ * addition would be a new promise made by a module that exists only to keep an
49
+ * old one.
32
50
  */
33
51
  export function createSessionQueue() {
34
- return { pending: [], failed: [], inFlightId: null };
52
+ return { pending: [], failed: [], inFlightId: null, inFlightIds: [] };
53
+ }
54
+ /**
55
+ * Everything on the wire, oldest first. Empty when the queue is idle.
56
+ *
57
+ * Module-private since 0.12.9. It was exported as `inFlightIdsOf` only for the
58
+ * browser drain that read the batch lock, and that drain is gone; 0.12.8 never
59
+ * published the name, so nothing external can be holding it.
60
+ *
61
+ * Tolerates a state that predates `inFlightIds` — a queue rehydrated from a
62
+ * host that persisted the older shape has only `inFlightId`, and reading
63
+ * through here means no call site has to know that.
64
+ */
65
+ function inFlight(state) {
66
+ if (state.inFlightIds?.length)
67
+ return state.inFlightIds;
68
+ return state.inFlightId ? [state.inFlightId] : [];
35
69
  }
36
70
  /**
37
71
  * Add a message to the tail.
@@ -51,7 +85,7 @@ export function enqueue(state, input) {
51
85
  * in flight — so a caller that races itself sends once, not twice.
52
86
  */
53
87
  export function claimNext(state) {
54
- if (state.inFlightId !== null)
88
+ if (inFlight(state).length > 0)
55
89
  return { state };
56
90
  const head = state.pending[0];
57
91
  if (!head)
@@ -62,18 +96,21 @@ export function claimNext(state) {
62
96
  ...state,
63
97
  pending: [claimed, ...state.pending.slice(1)],
64
98
  inFlightId: claimed.id,
99
+ inFlightIds: [claimed.id],
65
100
  },
66
101
  claimed,
67
102
  };
68
103
  }
69
- /** The send landed. Drop the item and free the queue. */
104
+ /** The send landed. Drop everything it carried and free the queue. */
70
105
  export function completeInFlight(state) {
71
- if (state.inFlightId === null)
106
+ const sending = inFlight(state);
107
+ if (sending.length === 0)
72
108
  return state;
73
109
  return {
74
110
  ...state,
75
- pending: state.pending.filter((m) => m.id !== state.inFlightId),
111
+ pending: state.pending.filter((m) => !sending.includes(m.id)),
76
112
  inFlightId: null,
113
+ inFlightIds: [],
77
114
  };
78
115
  }
79
116
  /**
@@ -84,15 +121,21 @@ export function completeInFlight(state) {
84
121
  * item lands in `failed` with its reason, and `pending` keeps moving.
85
122
  */
86
123
  export function failInFlight(state, error) {
87
- if (state.inFlightId === null)
124
+ const sending = inFlight(state);
125
+ if (sending.length === 0)
88
126
  return state;
89
- const item = state.pending.find((m) => m.id === state.inFlightId);
90
- if (!item)
91
- return { ...state, inFlightId: null };
127
+ // A list, not a single id: `claimNext` only ever locks one, but a state
128
+ // rehydrated from a host that claimed several still carries them, and one
129
+ // send failing is all of their failure. They land as separate rows so the
130
+ // user can retry the message that matters instead of re-sending three.
131
+ const items = state.pending.filter((m) => sending.includes(m.id));
132
+ if (items.length === 0)
133
+ return { ...state, inFlightId: null, inFlightIds: [] };
92
134
  return {
93
- pending: state.pending.filter((m) => m.id !== state.inFlightId),
94
- failed: [...state.failed, { ...item, lastError: error }],
135
+ pending: state.pending.filter((m) => !sending.includes(m.id)),
136
+ failed: [...state.failed, ...items.map((item) => ({ ...item, lastError: error }))],
95
137
  inFlightId: null,
138
+ inFlightIds: [],
96
139
  };
97
140
  }
98
141
  /** Put a failed item back at the tail, with its error cleared. */
@@ -107,9 +150,9 @@ export function retryFailed(state, id) {
107
150
  failed: state.failed.filter((m) => m.id !== id),
108
151
  };
109
152
  }
110
- /** Drop a message. Refuses the in-flight item — it is already on the wire. */
153
+ /** Drop a message. Refuses anything in flight — it is already on the wire. */
111
154
  export function removeQueued(state, id) {
112
- if (id === state.inFlightId)
155
+ if (inFlight(state).includes(id))
113
156
  return state;
114
157
  if (state.pending.some((m) => m.id === id)) {
115
158
  return { ...state, pending: state.pending.filter((m) => m.id !== id) };
@@ -119,9 +162,9 @@ export function removeQueued(state, id) {
119
162
  }
120
163
  return state;
121
164
  }
122
- /** Rewrite a queued message. Refuses the in-flight item. */
165
+ /** Rewrite a queued message. Refuses anything in flight. */
123
166
  export function editQueued(state, id, text) {
124
- if (id === state.inFlightId)
167
+ if (inFlight(state).includes(id))
125
168
  return state;
126
169
  if (!state.pending.some((m) => m.id === id))
127
170
  return state;
@@ -133,17 +176,20 @@ export function editQueued(state, id, text) {
133
176
  /**
134
177
  * Move a pending message to `toIndex`.
135
178
  *
136
- * `toIndex` is clamped to the movable range. While something is in flight that
137
- * range starts at 1, so nothing can be reordered into or past the slot that is
138
- * already sending — and the in-flight item itself cannot move at all.
179
+ * `toIndex` is clamped to the movable range. That range starts after whatever
180
+ * is in flight, so nothing can be reordered into or past a message already on
181
+ * the wire — and an in-flight message cannot move at all. That is one slot for
182
+ * a `claimNext` lock, and several for a state rehydrated from a host that
183
+ * claimed a batch.
139
184
  */
140
185
  export function reorderQueued(state, id, toIndex) {
141
- if (id === state.inFlightId)
186
+ const sending = inFlight(state);
187
+ if (sending.includes(id))
142
188
  return state;
143
189
  const from = state.pending.findIndex((m) => m.id === id);
144
190
  if (from === -1)
145
191
  return state;
146
- const first = state.inFlightId === null ? 0 : 1;
192
+ const first = sending.length;
147
193
  const to = Math.min(Math.max(toIndex, first), state.pending.length - 1);
148
194
  if (to === from)
149
195
  return state;
@@ -1 +1 @@
1
- {"version":3,"file":"message-queue.js","sourceRoot":"","sources":["../../../src/core/session/message-queue.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"message-queue.js","sourceRoot":"","sources":["../../../src/core/session/message-queue.ts"],"names":[],"mappings":"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"}