@superblocksteam/gateway 2.0.161 → 2.0.162-next.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 (235) hide show
  1. package/README.md +135 -39
  2. package/dist/agents/resolve-orchestrator-url.d.ts +18 -0
  3. package/dist/agents/resolve-orchestrator-url.js +64 -1
  4. package/dist/agents/resolve-orchestrator-url.js.map +1 -1
  5. package/dist/capabilities/lifecycle.d.ts +46 -29
  6. package/dist/capabilities/lifecycle.js +1731 -843
  7. package/dist/capabilities/lifecycle.js.map +1 -1
  8. package/dist/capabilities/query-integration.d.ts +14 -0
  9. package/dist/capabilities/query-integration.js +172 -0
  10. package/dist/capabilities/query-integration.js.map +1 -0
  11. package/dist/capabilities/source-files-archive.d.ts +11 -0
  12. package/dist/capabilities/source-files-archive.js +54 -0
  13. package/dist/capabilities/source-files-archive.js.map +1 -0
  14. package/dist/capabilities/types.d.ts +197 -119
  15. package/dist/capabilities/types.js +45 -6
  16. package/dist/capabilities/types.js.map +1 -1
  17. package/dist/capture/browser-contract.d.ts +15 -5
  18. package/dist/capture/browser-contract.js +13 -3
  19. package/dist/capture/browser-contract.js.map +1 -1
  20. package/dist/capture/browser-instructions.d.ts +3 -2
  21. package/dist/capture/browser-instructions.js +3 -2
  22. package/dist/capture/browser-instructions.js.map +1 -1
  23. package/dist/capture/mode.d.ts +8 -1
  24. package/dist/capture/mode.js +22 -2
  25. package/dist/capture/mode.js.map +1 -1
  26. package/dist/config.d.ts +22 -23
  27. package/dist/config.js +13 -12
  28. package/dist/config.js.map +1 -1
  29. package/dist/deps.d.ts +7 -7
  30. package/dist/index.d.ts +2 -4
  31. package/dist/index.js +2 -4
  32. package/dist/index.js.map +1 -1
  33. package/dist/integrations/read-only-postgres-query.d.ts +2 -0
  34. package/dist/integrations/read-only-postgres-query.js +164 -0
  35. package/dist/integrations/read-only-postgres-query.js.map +1 -0
  36. package/dist/main.js +1 -1
  37. package/dist/main.js.map +1 -1
  38. package/dist/playwright/ensure-chromium.d.ts +5 -7
  39. package/dist/playwright/ensure-chromium.js +13 -13
  40. package/dist/playwright/ensure-chromium.js.map +1 -1
  41. package/dist/preview/capture-screenshot.d.ts +30 -4
  42. package/dist/preview/capture-screenshot.js +67 -17
  43. package/dist/preview/capture-screenshot.js.map +1 -1
  44. package/dist/preview/viewer-url.js +3 -1
  45. package/dist/preview/viewer-url.js.map +1 -1
  46. package/dist/process/fault-barrier.js +1 -1
  47. package/dist/process/fault-barrier.js.map +1 -1
  48. package/dist/sabs/agent-facing-text.d.ts +2 -0
  49. package/dist/sabs/agent-facing-text.js +56 -2
  50. package/dist/sabs/agent-facing-text.js.map +1 -1
  51. package/dist/sabs/app-state.d.ts +126 -0
  52. package/dist/sabs/app-state.js +332 -0
  53. package/dist/sabs/app-state.js.map +1 -0
  54. package/dist/sabs/awaited-decision.d.ts +49 -0
  55. package/dist/sabs/awaited-decision.js +129 -0
  56. package/dist/sabs/awaited-decision.js.map +1 -0
  57. package/dist/sabs/editor-client-methods.d.ts +23 -5
  58. package/dist/sabs/editor-client-methods.js +45 -4
  59. package/dist/sabs/editor-client-methods.js.map +1 -1
  60. package/dist/sabs/editor-socket.d.ts +85 -0
  61. package/dist/sabs/editor-socket.js +67 -0
  62. package/dist/sabs/editor-socket.js.map +1 -0
  63. package/dist/sabs/session-peer.d.ts +119 -82
  64. package/dist/sabs/session-peer.js +10 -1
  65. package/dist/sabs/session-peer.js.map +1 -1
  66. package/dist/sabs/streamed-reply.d.ts +45 -0
  67. package/dist/sabs/streamed-reply.js +125 -0
  68. package/dist/sabs/streamed-reply.js.map +1 -0
  69. package/dist/sabs/turn-collector.d.ts +50 -35
  70. package/dist/sabs/turn-collector.js +110 -176
  71. package/dist/sabs/turn-collector.js.map +1 -1
  72. package/dist/sabs/websocket-session-peer.d.ts +104 -69
  73. package/dist/sabs/websocket-session-peer.js +1333 -477
  74. package/dist/sabs/websocket-session-peer.js.map +1 -1
  75. package/dist/server/client.d.ts +41 -9
  76. package/dist/server/client.js +126 -21
  77. package/dist/server/client.js.map +1 -1
  78. package/dist/start.d.ts +1 -1
  79. package/dist/start.js +30 -8
  80. package/dist/start.js.map +1 -1
  81. package/dist/stores/memory.d.ts +46 -0
  82. package/dist/stores/memory.js +163 -0
  83. package/dist/stores/memory.js.map +1 -0
  84. package/dist/stores/types.d.ts +92 -0
  85. package/dist/stores/types.js +11 -0
  86. package/dist/stores/types.js.map +1 -0
  87. package/dist/telemetry/mcp-client.d.ts +6 -1
  88. package/dist/telemetry/mcp-client.js +100 -4
  89. package/dist/telemetry/mcp-client.js.map +1 -1
  90. package/dist/telemetry/metrics.d.ts +12 -3
  91. package/dist/telemetry/metrics.js +60 -14
  92. package/dist/telemetry/metrics.js.map +1 -1
  93. package/dist/telemetry/runtime.js +4 -6
  94. package/dist/telemetry/runtime.js.map +1 -1
  95. package/dist/transports/mcp/admin-tools.d.ts +8 -0
  96. package/dist/transports/mcp/admin-tools.js +115 -4
  97. package/dist/transports/mcp/admin-tools.js.map +1 -1
  98. package/dist/transports/mcp/app-status-html.d.ts +4 -8
  99. package/dist/transports/mcp/app-status-html.js +336 -128
  100. package/dist/transports/mcp/app-status-html.js.map +1 -1
  101. package/dist/transports/mcp/client-presentation.d.ts +16 -0
  102. package/dist/transports/mcp/client-presentation.js +13 -0
  103. package/dist/transports/mcp/client-presentation.js.map +1 -0
  104. package/dist/transports/mcp/cowork-editor-url.d.ts +6 -0
  105. package/dist/transports/mcp/cowork-editor-url.js +10 -0
  106. package/dist/transports/mcp/cowork-editor-url.js.map +1 -0
  107. package/dist/transports/mcp/decision-card-html.d.ts +26 -0
  108. package/dist/transports/mcp/decision-card-html.js +876 -0
  109. package/dist/transports/mcp/decision-card-html.js.map +1 -0
  110. package/dist/transports/mcp/decision-elicitation.d.ts +42 -0
  111. package/dist/transports/mcp/decision-elicitation.js +59 -0
  112. package/dist/transports/mcp/decision-elicitation.js.map +1 -1
  113. package/dist/transports/mcp/editor-document-probe.d.ts +4 -0
  114. package/dist/transports/mcp/editor-document-probe.js +35 -0
  115. package/dist/transports/mcp/editor-document-probe.js.map +1 -0
  116. package/dist/transports/mcp/editor-integration-setup-url.d.ts +14 -0
  117. package/dist/transports/mcp/editor-integration-setup-url.js +29 -0
  118. package/dist/transports/mcp/editor-integration-setup-url.js.map +1 -0
  119. package/dist/transports/mcp/format-tool-content.d.ts +13 -18
  120. package/dist/transports/mcp/format-tool-content.js +172 -13
  121. package/dist/transports/mcp/format-tool-content.js.map +1 -1
  122. package/dist/transports/mcp/instructions/index.d.ts +23 -0
  123. package/dist/transports/mcp/instructions/index.js +81 -0
  124. package/dist/transports/mcp/instructions/index.js.map +1 -0
  125. package/dist/transports/mcp/instructions/result.d.ts +18 -0
  126. package/dist/transports/mcp/instructions/result.js +58 -0
  127. package/dist/transports/mcp/instructions/result.js.map +1 -0
  128. package/dist/transports/mcp/instructions/tools/ask-user.d.ts +2 -0
  129. package/dist/transports/mcp/instructions/tools/ask-user.js +20 -0
  130. package/dist/transports/mcp/instructions/tools/ask-user.js.map +1 -0
  131. package/dist/transports/mcp/instructions/tools/build-app.d.ts +4 -0
  132. package/dist/transports/mcp/instructions/tools/build-app.js +54 -0
  133. package/dist/transports/mcp/instructions/tools/build-app.js.map +1 -0
  134. package/dist/transports/mcp/instructions/tools/check-app-progress.d.ts +3 -0
  135. package/dist/transports/mcp/instructions/tools/check-app-progress.js +79 -0
  136. package/dist/transports/mcp/instructions/tools/check-app-progress.js.map +1 -0
  137. package/dist/transports/mcp/instructions/tools/check-publish-progress.d.ts +3 -0
  138. package/dist/transports/mcp/instructions/tools/check-publish-progress.js +23 -0
  139. package/dist/transports/mcp/instructions/tools/check-publish-progress.js.map +1 -0
  140. package/dist/transports/mcp/instructions/tools/copy.d.ts +18 -0
  141. package/dist/transports/mcp/instructions/tools/copy.js +49 -0
  142. package/dist/transports/mcp/instructions/tools/copy.js.map +1 -0
  143. package/dist/transports/mcp/instructions/tools/create-integration.d.ts +4 -0
  144. package/dist/transports/mcp/instructions/tools/create-integration.js +41 -0
  145. package/dist/transports/mcp/instructions/tools/create-integration.js.map +1 -0
  146. package/dist/transports/mcp/instructions/tools/edit-app.d.ts +3 -0
  147. package/dist/transports/mcp/instructions/tools/edit-app.js +18 -0
  148. package/dist/transports/mcp/instructions/tools/edit-app.js.map +1 -0
  149. package/dist/transports/mcp/instructions/tools/get-app.d.ts +3 -0
  150. package/dist/transports/mcp/instructions/tools/get-app.js +49 -0
  151. package/dist/transports/mcp/instructions/tools/get-app.js.map +1 -0
  152. package/dist/transports/mcp/instructions/tools/get-integration-metadata.d.ts +2 -0
  153. package/dist/transports/mcp/instructions/tools/get-integration-metadata.js +13 -0
  154. package/dist/transports/mcp/instructions/tools/get-integration-metadata.js.map +1 -0
  155. package/dist/transports/mcp/instructions/tools/index.d.ts +7 -0
  156. package/dist/transports/mcp/instructions/tools/index.js +31 -0
  157. package/dist/transports/mcp/instructions/tools/index.js.map +1 -0
  158. package/dist/transports/mcp/instructions/tools/publish-app.d.ts +3 -0
  159. package/dist/transports/mcp/instructions/tools/publish-app.js +23 -0
  160. package/dist/transports/mcp/instructions/tools/publish-app.js.map +1 -0
  161. package/dist/transports/mcp/instructions/tools/start-app.d.ts +3 -0
  162. package/dist/transports/mcp/instructions/tools/start-app.js +22 -0
  163. package/dist/transports/mcp/instructions/tools/start-app.js.map +1 -0
  164. package/dist/transports/mcp/instructions/tools/upload-artifact.d.ts +2 -0
  165. package/dist/transports/mcp/instructions/tools/upload-artifact.js +13 -0
  166. package/dist/transports/mcp/instructions/tools/upload-artifact.js.map +1 -0
  167. package/dist/transports/mcp/mcp-app-brand-css.d.ts +1 -0
  168. package/dist/transports/mcp/mcp-app-brand-css.js +180 -0
  169. package/dist/transports/mcp/mcp-app-brand-css.js.map +1 -0
  170. package/dist/transports/mcp/mount.d.ts +14 -1
  171. package/dist/transports/mcp/mount.js +729 -172
  172. package/dist/transports/mcp/mount.js.map +1 -1
  173. package/dist/transports/mcp/native-browser-presence.d.ts +45 -0
  174. package/dist/transports/mcp/native-browser-presence.js +158 -0
  175. package/dist/transports/mcp/native-browser-presence.js.map +1 -0
  176. package/dist/transports/mcp/plan-approval.d.ts +44 -0
  177. package/dist/transports/mcp/plan-approval.js +179 -0
  178. package/dist/transports/mcp/plan-approval.js.map +1 -0
  179. package/dist/transports/mcp/session-directory.d.ts +7 -0
  180. package/dist/transports/mcp/session-directory.js +18 -0
  181. package/dist/transports/mcp/session-directory.js.map +1 -0
  182. package/dist/transports/mcp/tool-names.d.ts +2 -0
  183. package/dist/transports/mcp/tool-names.js +2 -0
  184. package/dist/transports/mcp/tool-names.js.map +1 -0
  185. package/package.json +16 -7
  186. package/skills/superblocks-build/SKILL.md +59 -0
  187. package/skills/superblocks-import/SKILL.md +125 -0
  188. package/dist/capabilities/import-prompt.d.ts +0 -11
  189. package/dist/capabilities/import-prompt.js +0 -96
  190. package/dist/capabilities/import-prompt.js.map +0 -1
  191. package/dist/capabilities/persisted-progress.d.ts +0 -46
  192. package/dist/capabilities/persisted-progress.js +0 -246
  193. package/dist/capabilities/persisted-progress.js.map +0 -1
  194. package/dist/events/cursor.d.ts +0 -43
  195. package/dist/events/cursor.js +0 -78
  196. package/dist/events/cursor.js.map +0 -1
  197. package/dist/events/memory-event-store.d.ts +0 -34
  198. package/dist/events/memory-event-store.js +0 -110
  199. package/dist/events/memory-event-store.js.map +0 -1
  200. package/dist/events/merge.d.ts +0 -23
  201. package/dist/events/merge.js +0 -97
  202. package/dist/events/merge.js.map +0 -1
  203. package/dist/events/normalized-collector.d.ts +0 -62
  204. package/dist/events/normalized-collector.js +0 -156
  205. package/dist/events/normalized-collector.js.map +0 -1
  206. package/dist/events/schema.d.ts +0 -9
  207. package/dist/events/schema.js +0 -93
  208. package/dist/events/schema.js.map +0 -1
  209. package/dist/events/snapshot.d.ts +0 -32
  210. package/dist/events/snapshot.js +0 -57
  211. package/dist/events/snapshot.js.map +0 -1
  212. package/dist/events/stream-key.d.ts +0 -2
  213. package/dist/events/stream-key.js +0 -31
  214. package/dist/events/stream-key.js.map +0 -1
  215. package/dist/events/types.d.ts +0 -179
  216. package/dist/events/types.js +0 -66
  217. package/dist/events/types.js.map +0 -1
  218. package/dist/resume/memory-progress-store.d.ts +0 -39
  219. package/dist/resume/memory-progress-store.js +0 -82
  220. package/dist/resume/memory-progress-store.js.map +0 -1
  221. package/dist/resume/memory-recent-app-store.d.ts +0 -14
  222. package/dist/resume/memory-recent-app-store.js +0 -27
  223. package/dist/resume/memory-recent-app-store.js.map +0 -1
  224. package/dist/resume/memory-turn-store.d.ts +0 -18
  225. package/dist/resume/memory-turn-store.js +0 -73
  226. package/dist/resume/memory-turn-store.js.map +0 -1
  227. package/dist/resume/progress-key.d.ts +0 -21
  228. package/dist/resume/progress-key.js +0 -58
  229. package/dist/resume/progress-key.js.map +0 -1
  230. package/dist/resume/stores.d.ts +0 -14
  231. package/dist/resume/stores.js +0 -18
  232. package/dist/resume/stores.js.map +0 -1
  233. package/dist/resume/types.d.ts +0 -124
  234. package/dist/resume/types.js +0 -13
  235. package/dist/resume/types.js.map +0 -1
@@ -1,93 +0,0 @@
1
- import { z } from "zod";
2
- import { CHAT_ROLES, EVENT_CONTRACT_VERSION, EVENT_PRODUCERS, GENERATION_STATES, MAX_IDENTIFIER_LENGTH, MAX_LABEL_LENGTH, MAX_SEQUENCE, MAX_TEXT_LENGTH, SESSION_STATUSES, } from "./types.js";
3
- const identifier = z.string().min(1).max(MAX_IDENTIFIER_LENGTH);
4
- /**
5
- * Payloads are strict objects: an unrecognized key fails the parse rather than
6
- * being dropped. A field nobody declared is a field nobody bounded, and this
7
- * body arrives from outside the process.
8
- */
9
- const payloadByKind = {
10
- auth_required: z
11
- .object({ reason: z.string().max(MAX_LABEL_LENGTH).optional() })
12
- .strict(),
13
- chat_message: z
14
- .object({
15
- messageId: z.string().max(MAX_IDENTIFIER_LENGTH).optional(),
16
- messageType: z.string().max(MAX_IDENTIFIER_LENGTH).optional(),
17
- role: z.enum(CHAT_ROLES),
18
- text: z.string().min(1).max(MAX_TEXT_LENGTH),
19
- })
20
- .strict(),
21
- generation_state: z
22
- .object({
23
- hasError: z.boolean().optional(),
24
- hasSuggestions: z.boolean().optional(),
25
- state: z.enum(GENERATION_STATES),
26
- })
27
- .strict(),
28
- progress: z
29
- .object({ label: z.string().min(1).max(MAX_LABEL_LENGTH) })
30
- .strict(),
31
- session: z.object({ status: z.enum(SESSION_STATUSES) }).strict(),
32
- };
33
- const envelope = z
34
- .object({
35
- applicationId: identifier,
36
- eventId: identifier,
37
- gatewayTurnId: z.string().max(MAX_IDENTIFIER_LENGTH).optional(),
38
- kind: z.enum(Object.keys(payloadByKind)),
39
- liveEditId: identifier,
40
- occurredAt: z.string().min(1),
41
- organizationId: identifier,
42
- payload: z.unknown(),
43
- producer: z.enum(EVENT_PRODUCERS),
44
- sequence: z.number().int().positive().max(MAX_SEQUENCE),
45
- version: z.number().int(),
46
- })
47
- .strict();
48
- /**
49
- * Validates one inbound event against the contract.
50
- *
51
- * SABS validates the same shape before pushing it, which is not a reason to
52
- * skip it here: a validated producer is not a trusted one, and this is the
53
- * process boundary where the bytes become Gateway's problem.
54
- */
55
- export function parseLiveEditEvent(input) {
56
- const parsed = envelope.safeParse(input);
57
- if (!parsed.success) {
58
- return { ok: false, reason: "malformed_event" };
59
- }
60
- // Version is checked before the payload so an event from a future contract
61
- // is reported as such rather than as a malformed body.
62
- if (parsed.data.version !== EVENT_CONTRACT_VERSION) {
63
- return { ok: false, reason: "unsupported_version" };
64
- }
65
- const occurredAtMs = Date.parse(parsed.data.occurredAt);
66
- if (Number.isNaN(occurredAtMs)) {
67
- return { ok: false, reason: "malformed_event" };
68
- }
69
- const payload = payloadByKind[parsed.data.kind].safeParse(parsed.data.payload);
70
- if (!payload.success) {
71
- return { ok: false, reason: "malformed_event" };
72
- }
73
- const event = {
74
- applicationId: parsed.data.applicationId,
75
- eventId: parsed.data.eventId,
76
- ...(parsed.data.gatewayTurnId
77
- ? { gatewayTurnId: parsed.data.gatewayTurnId }
78
- : {}),
79
- kind: parsed.data.kind,
80
- liveEditId: parsed.data.liveEditId,
81
- occurredAtMs,
82
- organizationId: parsed.data.organizationId,
83
- payload: {
84
- kind: parsed.data.kind,
85
- ...payload.data,
86
- },
87
- producer: parsed.data.producer,
88
- sequence: parsed.data.sequence,
89
- version: EVENT_CONTRACT_VERSION,
90
- };
91
- return { ok: true, event };
92
- }
93
- //# sourceMappingURL=schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/events/schema.ts"],"names":[],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- import { type EventCursor } from "./cursor.js";
2
- import type { EventProducer, EventSnapshot, LiveEditEvent } from "./types.js";
3
- export type SnapshotReads = {
4
- /**
5
- * Lowest sequence this producer's stream still holds, or undefined when the
6
- * stream is empty. This is the retention boundary a stale cursor fell off.
7
- */
8
- firstRetainedSequence(producer: EventProducer): Promise<number | undefined>;
9
- /** Strictly-after-sequence read, done by the store rather than by filtering. */
10
- readAfter(input: {
11
- afterSequence: number;
12
- limit?: number;
13
- producer: EventProducer;
14
- }): Promise<LiveEditEvent[]>;
15
- /** Newest `count` events of one producer's stream, oldest first. */
16
- readTail(input: {
17
- count: number;
18
- producer: EventProducer;
19
- }): Promise<LiveEditEvent[]>;
20
- };
21
- /**
22
- * Assembles a snapshot from a store's three reads.
23
- *
24
- * Shared rather than written twice so the memory and Redis stores cannot drift
25
- * into disagreeing about what resuming means — the same reason both build
26
- * their keys from one builder. Each store supplies only the reads; the cursor
27
- * arithmetic and the staleness rule live here.
28
- */
29
- export declare function buildSnapshot(input: {
30
- cursor?: EventCursor;
31
- limit?: number;
32
- }, reads: SnapshotReads): Promise<EventSnapshot>;
@@ -1,57 +0,0 @@
1
- import { advanceEventCursor, cursorPosition, } from "./cursor.js";
2
- import { PRODUCERS_IN_ORDER, sortEvents } from "./merge.js";
3
- import { EVENT_SNAPSHOT_TAIL } from "./types.js";
4
- /**
5
- * Assembles a snapshot from a store's three reads.
6
- *
7
- * Shared rather than written twice so the memory and Redis stores cannot drift
8
- * into disagreeing about what resuming means — the same reason both build
9
- * their keys from one builder. Each store supplies only the reads; the cursor
10
- * arithmetic and the staleness rule live here.
11
- */
12
- export async function buildSnapshot(input, reads) {
13
- const collected = [];
14
- const tail = [];
15
- const lost = [];
16
- for (const producer of PRODUCERS_IN_ORDER) {
17
- const resumedAfterSequence = cursorPosition(input.cursor, producer);
18
- const afterEvents = await reads.readAfter({
19
- afterSequence: resumedAfterSequence,
20
- ...(input.limit === undefined ? {} : { limit: input.limit }),
21
- producer,
22
- });
23
- collected.push(...afterEvents);
24
- tail.push(...(await reads.readTail({ count: EVENT_SNAPSHOT_TAIL, producer })));
25
- const firstRetainedSequence = await reads.firstRetainedSequence(producer);
26
- // readAfter and firstRetainedSequence are two separate reads, not one
27
- // atomic one, so retention can advance between them: firstRetainedSequence
28
- // can then report a boundary past events readAfter had already captured
29
- // moments earlier. A delivered sequence below that boundary proves the
30
- // read beat the eviction, so what looks like a gap here never actually
31
- // reached the caller as one.
32
- const minDelivered = afterEvents.length > 0
33
- ? Math.min(...afterEvents.map((event) => event.sequence))
34
- : undefined;
35
- const provenByDelivery = firstRetainedSequence !== undefined &&
36
- minDelivered !== undefined &&
37
- minDelivered < firstRetainedSequence;
38
- // A gap only exists when the stream starts *past* the next sequence the
39
- // cursor expects. An empty stream is not a gap: nothing was produced yet.
40
- if (firstRetainedSequence !== undefined &&
41
- firstRetainedSequence > resumedAfterSequence + 1 &&
42
- !provenByDelivery) {
43
- lost.push({ firstRetainedSequence, producer, resumedAfterSequence });
44
- }
45
- }
46
- const events = sortEvents(collected);
47
- const limited = input.limit === undefined ? events : events.slice(0, input.limit);
48
- return {
49
- // Advanced past what is actually being handed over, never past what was
50
- // read and then cut by the limit — otherwise the remainder is skipped.
51
- cursor: advanceEventCursor(input.cursor, limited),
52
- events: limited,
53
- lost,
54
- tail: sortEvents(tail),
55
- };
56
- }
57
- //# sourceMappingURL=snapshot.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/events/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,cAAc,GAEf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE5D,OAAO,EAAE,mBAAmB,EAAuB,MAAM,YAAY,CAAC;AAqBtE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAA+C,EAC/C,KAAoB;IAEpB,MAAM,SAAS,GAAoB,EAAE,CAAC;IACtC,MAAM,IAAI,GAAoB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAqB,EAAE,CAAC;IAElC,KAAK,MAAM,QAAQ,IAAI,kBAAkB,EAAE,CAAC;QAC1C,MAAM,oBAAoB,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACpE,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC;YACxC,aAAa,EAAE,oBAAoB;YACnC,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5D,QAAQ;SACT,CAAC,CAAC;QACH,SAAS,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,CACP,GAAG,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,CAAC,CAAC,CACpE,CAAC;QAEF,MAAM,qBAAqB,GAAG,MAAM,KAAK,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAC1E,sEAAsE;QACtE,2EAA2E;QAC3E,wEAAwE;QACxE,uEAAuE;QACvE,uEAAuE;QACvE,6BAA6B;QAC7B,MAAM,YAAY,GAChB,WAAW,CAAC,MAAM,GAAG,CAAC;YACpB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACzD,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,gBAAgB,GACpB,qBAAqB,KAAK,SAAS;YACnC,YAAY,KAAK,SAAS;YAC1B,YAAY,GAAG,qBAAqB,CAAC;QAEvC,wEAAwE;QACxE,0EAA0E;QAC1E,IACE,qBAAqB,KAAK,SAAS;YACnC,qBAAqB,GAAG,oBAAoB,GAAG,CAAC;YAChD,CAAC,gBAAgB,EACjB,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,EAAE,qBAAqB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;IACrC,MAAM,OAAO,GACX,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACpE,OAAO;QACL,wEAAwE;QACxE,uEAAuE;QACvE,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC;QACjD,MAAM,EAAE,OAAO;QACf,IAAI;QACJ,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC;KACvB,CAAC;AACJ,CAAC"}
@@ -1,2 +0,0 @@
1
- import type { EventProducer, EventScope } from "./types.js";
2
- export declare function streamSuffix(scope: EventScope, producer: EventProducer): string;
@@ -1,31 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- /**
3
- * Builds the stream address shared by every event store, so the two
4
- * implementations cannot drift into addressing streams differently.
5
- *
6
- * Tenant identifiers (organization, application, live edit) are length-
7
- * prefixed and SHA-256-digested before they reach Redis. Length-prefixing
8
- * keeps `a:b`+`c` and `a`+`b:c` from colliding; digesting keeps the
9
- * identifiers themselves out of key listings — ProgressStore already does
10
- * the same for caller/org/app. The producer stays in the clear: it is a
11
- * closed enum (`dev_server` | `sabs`), cannot identify a tenant, and naming
12
- * the stream at a glance is worth more than the nothing it discloses.
13
- *
14
- * v0 has not shipped this key format, so there is no dual-read. Existing
15
- * local Redis event keys from earlier builds are orphaned after deploy.
16
- */
17
- function digest(parts) {
18
- const hash = createHash("sha256");
19
- for (const part of parts) {
20
- hash.update(`${part.length}:${part}`);
21
- }
22
- return hash.digest("hex");
23
- }
24
- export function streamSuffix(scope, producer) {
25
- return `${digest([
26
- scope.organizationId,
27
- scope.applicationId,
28
- scope.liveEditId,
29
- ])}:${producer}`;
30
- }
31
- //# sourceMappingURL=stream-key.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream-key.js","sourceRoot":"","sources":["../../src/events/stream-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC;;;;;;;;;;;;;;GAcG;AACH,SAAS,MAAM,CAAC,KAAwB;IACtC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,KAAiB,EACjB,QAAuB;IAEvB,OAAO,GAAG,MAAM,CAAC;QACf,KAAK,CAAC,cAAc;QACpB,KAAK,CAAC,aAAa;QACnB,KAAK,CAAC,UAAU;KACjB,CAAC,IAAI,QAAQ,EAAE,CAAC;AACnB,CAAC"}
@@ -1,179 +0,0 @@
1
- import type { EventCursor } from "./cursor.js";
2
- /**
3
- * The versioned event contract SABS pushes over the direct authenticated
4
- * callback. This mirrors `sabs/internal/gateway/event.go`; the two are kept in
5
- * step by hand because the channel is deliberately not proto, and the bounds
6
- * below are the only thing standing between a producer bug and unbounded
7
- * Redis growth.
8
- */
9
- export declare const EVENT_CONTRACT_VERSION = 1;
10
- export declare const MAX_IDENTIFIER_LENGTH = 128;
11
- export declare const MAX_LABEL_LENGTH = 512;
12
- export declare const MAX_TEXT_LENGTH = 8192;
13
- /**
14
- * Ceiling on an inbound sequence number. Every consumer of `sequence`
15
- * (cursor comparisons, gap detection) does so with ordinary JS number
16
- * arithmetic, which stops being exact past this point; a producer sequence
17
- * that reached it would silently corrupt ordering rather than fail loudly.
18
- */
19
- export declare const MAX_SEQUENCE: number;
20
- /** Kinds of fact a live-edit session reports. */
21
- export declare const EVENT_KINDS: readonly ["auth_required", "chat_message", "generation_state", "progress", "session"];
22
- export type LiveEditEventKind = (typeof EVENT_KINDS)[number];
23
- /**
24
- * Which stream a sequence number belongs to. The SABS control plane and the
25
- * dev server both push about the same live edit and neither can see the
26
- * other's counter, so ordering is defined per producer and Gateway keeps the
27
- * two streams apart.
28
- */
29
- export declare const EVENT_PRODUCERS: readonly ["dev_server", "sabs"];
30
- export type EventProducer = (typeof EVENT_PRODUCERS)[number];
31
- export declare const GENERATION_STATES: readonly ["awaiting_user_input", "cancelled", "completed", "debugging", "generating", "idle", "summarizing"];
32
- export declare const CHAT_ROLES: readonly ["assistant", "user"];
33
- export declare const SESSION_STATUSES: readonly ["created", "terminated"];
34
- export type LiveEditEventPayload = {
35
- kind: "auth_required";
36
- reason?: string;
37
- } | {
38
- kind: "chat_message";
39
- messageId?: string;
40
- messageType?: string;
41
- role: (typeof CHAT_ROLES)[number];
42
- text: string;
43
- } | {
44
- kind: "generation_state";
45
- hasError?: boolean;
46
- hasSuggestions?: boolean;
47
- state: (typeof GENERATION_STATES)[number];
48
- } | {
49
- kind: "progress";
50
- label: string;
51
- } | {
52
- kind: "session";
53
- status: (typeof SESSION_STATUSES)[number];
54
- };
55
- /**
56
- * One accepted event. `occurredAtMs` replaces the wire's ISO string so
57
- * ordering never depends on re-parsing, and `payload` is narrowed by `kind`.
58
- */
59
- export type LiveEditEvent = {
60
- applicationId: string;
61
- eventId: string;
62
- gatewayTurnId?: string;
63
- kind: LiveEditEventKind;
64
- liveEditId: string;
65
- occurredAtMs: number;
66
- organizationId: string;
67
- payload: LiveEditEventPayload;
68
- producer: EventProducer;
69
- sequence: number;
70
- version: typeof EVENT_CONTRACT_VERSION;
71
- };
72
- /**
73
- * Why an event was refused. These values reach a metric label, so the set is
74
- * closed and carries nothing derived from the event's content.
75
- */
76
- export type EventRejectionReason = "malformed_event" | "unsupported_version";
77
- export type ParseResult = {
78
- ok: true;
79
- event: LiveEditEvent;
80
- } | {
81
- ok: false;
82
- reason: EventRejectionReason;
83
- };
84
- /** Outcome of persisting one event. */
85
- export type AppendOutcome = "accepted" | "duplicate";
86
- /**
87
- * The whole tenant path to one live-edit stream.
88
- *
89
- * A live-edit id alone would be enough to address a stream, and that is
90
- * exactly the problem: it makes the store's isolation depend entirely on
91
- * every caller having validated ownership first. Carrying the tenant in the
92
- * key means a read cannot reach another tenant's history even if something
93
- * upstream let the wrong id through.
94
- */
95
- export type EventScope = {
96
- applicationId: string;
97
- liveEditId: string;
98
- organizationId: string;
99
- };
100
- /**
101
- * A producer whose retention boundary overtook a caller's cursor.
102
- *
103
- * Reported rather than hidden: the caller asked to continue from a position
104
- * that no longer exists, and answering with only the events that survived
105
- * would present a stream with a hole in it as a complete one. Naming the
106
- * producer and both boundaries lets a caller say exactly what it lost.
107
- */
108
- export type LostEventRange = {
109
- /** Lowest sequence this producer's stream still holds. */
110
- firstRetainedSequence: number;
111
- producer: EventProducer;
112
- /** Last sequence the caller's cursor had consumed. */
113
- resumedAfterSequence: number;
114
- };
115
- /**
116
- * How many events at the end of each producer's stream a snapshot carries.
117
- *
118
- * Current state has to be read from the stream's end rather than from the
119
- * window after the cursor: a caller that already consumed the terminal event
120
- * would otherwise be told nothing is known and would poll a build that ended.
121
- * A tail bounds that read so it does not grow with the length of the session.
122
- */
123
- export declare const EVENT_SNAPSHOT_TAIL = 64;
124
- /**
125
- * What one caller sees when it resumes reading a live edit.
126
- *
127
- * `events` is what is new for this caller and `tail` is where the session
128
- * currently stands; the two overlap freely and a reader is expected to take
129
- * activity from the first and state from the second.
130
- */
131
- export type EventSnapshot = {
132
- /** Advanced past every event in {@link EventSnapshot.events}. */
133
- cursor: EventCursor;
134
- /** Strictly after the incoming cursor, ordered deterministically. */
135
- events: LiveEditEvent[];
136
- /** Empty when the cursor was still inside every stream's retention. */
137
- lost: LostEventRange[];
138
- /** Newest {@link EVENT_SNAPSHOT_TAIL} events per producer, cursor aside. */
139
- tail: LiveEditEvent[];
140
- };
141
- /**
142
- * Durable, bounded record of what happened in a live-edit session.
143
- *
144
- * Retention is bounded twice over: a stream holds at most
145
- * {@link MAX_EVENTS_PER_STREAM} events and expires after
146
- * {@link EVENT_STREAM_TTL_MS} of silence. This is the source a resumed caller
147
- * reads. Live turns hear Clark over the editor websocket.
148
- */
149
- export type EventStore = {
150
- /** The event carries its own scope, so an append cannot be misfiled. */
151
- append(event: LiveEditEvent): Promise<AppendOutcome>;
152
- /** Events for a live edit, ordered deterministically across producers. */
153
- list(input: EventScope & {
154
- afterSequence?: number;
155
- limit?: number;
156
- producer?: EventProducer;
157
- }): Promise<LiveEditEvent[]>;
158
- /**
159
- * Everything one caller needs to continue from where it left off, read
160
- * without consuming anything: two callers resuming the same live edit each
161
- * get their own view of it.
162
- */
163
- snapshot(input: EventScope & {
164
- cursor?: EventCursor;
165
- limit?: number;
166
- }): Promise<EventSnapshot>;
167
- };
168
- /**
169
- * Per-(live edit, producer) retention bound. A runaway producer overwrites its
170
- * own oldest events rather than growing Redis without limit. The trade-off is
171
- * explicit: an event evicted by count loses its de-duplication record, so a
172
- * redelivery arriving after eviction is accepted again. Bounded memory is
173
- * worth more than perfect de-duplication of an event nobody can still read.
174
- */
175
- export declare const MAX_EVENTS_PER_STREAM = 500;
176
- /** How long a silent stream is kept before Redis reclaims it. */
177
- export declare const EVENT_STREAM_TTL_MS = 3600000;
178
- /** Cap on one inbound batch, matching the SABS publish bound. */
179
- export declare const MAX_EVENTS_PER_REQUEST = 64;
@@ -1,66 +0,0 @@
1
- /**
2
- * The versioned event contract SABS pushes over the direct authenticated
3
- * callback. This mirrors `sabs/internal/gateway/event.go`; the two are kept in
4
- * step by hand because the channel is deliberately not proto, and the bounds
5
- * below are the only thing standing between a producer bug and unbounded
6
- * Redis growth.
7
- */
8
- export const EVENT_CONTRACT_VERSION = 1;
9
- export const MAX_IDENTIFIER_LENGTH = 128;
10
- export const MAX_LABEL_LENGTH = 512;
11
- export const MAX_TEXT_LENGTH = 8192;
12
- /**
13
- * Ceiling on an inbound sequence number. Every consumer of `sequence`
14
- * (cursor comparisons, gap detection) does so with ordinary JS number
15
- * arithmetic, which stops being exact past this point; a producer sequence
16
- * that reached it would silently corrupt ordering rather than fail loudly.
17
- */
18
- export const MAX_SEQUENCE = Number.MAX_SAFE_INTEGER;
19
- /** Kinds of fact a live-edit session reports. */
20
- export const EVENT_KINDS = [
21
- "auth_required",
22
- "chat_message",
23
- "generation_state",
24
- "progress",
25
- "session",
26
- ];
27
- /**
28
- * Which stream a sequence number belongs to. The SABS control plane and the
29
- * dev server both push about the same live edit and neither can see the
30
- * other's counter, so ordering is defined per producer and Gateway keeps the
31
- * two streams apart.
32
- */
33
- export const EVENT_PRODUCERS = ["dev_server", "sabs"];
34
- export const GENERATION_STATES = [
35
- "awaiting_user_input",
36
- "cancelled",
37
- "completed",
38
- "debugging",
39
- "generating",
40
- "idle",
41
- "summarizing",
42
- ];
43
- export const CHAT_ROLES = ["assistant", "user"];
44
- export const SESSION_STATUSES = ["created", "terminated"];
45
- /**
46
- * How many events at the end of each producer's stream a snapshot carries.
47
- *
48
- * Current state has to be read from the stream's end rather than from the
49
- * window after the cursor: a caller that already consumed the terminal event
50
- * would otherwise be told nothing is known and would poll a build that ended.
51
- * A tail bounds that read so it does not grow with the length of the session.
52
- */
53
- export const EVENT_SNAPSHOT_TAIL = 64;
54
- /**
55
- * Per-(live edit, producer) retention bound. A runaway producer overwrites its
56
- * own oldest events rather than growing Redis without limit. The trade-off is
57
- * explicit: an event evicted by count loses its de-duplication record, so a
58
- * redelivery arriving after eviction is accepted again. Bounded memory is
59
- * worth more than perfect de-duplication of an event nobody can still read.
60
- */
61
- export const MAX_EVENTS_PER_STREAM = 500;
62
- /** How long a silent stream is kept before Redis reclaims it. */
63
- export const EVENT_STREAM_TTL_MS = 3_600_000;
64
- /** Cap on one inbound batch, matching the SABS publish bound. */
65
- export const MAX_EVENTS_PER_REQUEST = 64;
66
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/events/types.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AACzC,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AACpC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAEpD,iDAAiD;AACjD,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,eAAe;IACf,cAAc;IACd,kBAAkB;IAClB,UAAU;IACV,SAAS;CACD,CAAC;AAGX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,YAAY,EAAE,MAAM,CAAU,CAAC;AAG/D,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,qBAAqB;IACrB,WAAW;IACX,WAAW;IACX,WAAW;IACX,YAAY;IACZ,MAAM;IACN,aAAa;CACL,CAAC;AAEX,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,WAAW,EAAE,MAAM,CAAU,CAAC;AAEzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,YAAY,CAAU,CAAC;AAkFnE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAiDtC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAEzC,iEAAiE;AACjE,MAAM,CAAC,MAAM,mBAAmB,GAAG,SAAS,CAAC;AAE7C,iEAAiE;AACjE,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC"}
@@ -1,39 +0,0 @@
1
- import { type AppScopeKey, type ProgressCursorKey, type ProgressCursorRecord, type ProgressStore } from "./types.js";
2
- /**
3
- * Cap on how many cursors and pointers a single process will hold.
4
- *
5
- * Redis expires keys on its own; a plain Map does not, and a gateway that ran
6
- * for a week would hold one entry per (caller, application) it had ever
7
- * served. Insertion order is iteration order for a Map, so the oldest write
8
- * is the one dropped — a caller evicted this way re-reads the retained
9
- * history rather than losing anything, which is the same outcome as its
10
- * cursor having expired.
11
- */
12
- export declare const MAX_MEMORY_PROGRESS_ENTRIES = 2048;
13
- /**
14
- * Local-only fallback, matching the other in-memory stores.
15
- *
16
- * Not a second source of truth: two replicas with private maps would hand the
17
- * same caller two different positions in the same stream, which is exactly
18
- * the divergence Redis is required outside local to prevent.
19
- */
20
- export declare class MemoryProgressStore implements ProgressStore {
21
- private readonly cursors;
22
- private readonly lastActivity;
23
- private readonly liveEdits;
24
- getCursor(key: ProgressCursorKey): Promise<ProgressCursorRecord | undefined>;
25
- getLastActivityAtMs(key: AppScopeKey): Promise<number | undefined>;
26
- getLiveEditId(key: AppScopeKey): Promise<string | undefined>;
27
- setCursor(input: ProgressCursorKey & {
28
- record: ProgressCursorRecord;
29
- ttlMs?: number;
30
- }): Promise<void>;
31
- setLastActivityAtMs(input: AppScopeKey & {
32
- atMs: number;
33
- ttlMs?: number;
34
- }): Promise<void>;
35
- setLiveEditId(input: AppScopeKey & {
36
- liveEditId: string;
37
- ttlMs?: number;
38
- }): Promise<void>;
39
- }
@@ -1,82 +0,0 @@
1
- import { cursorKey, lastActivityKey, liveEditKey } from "./progress-key.js";
2
- import { DEFAULT_LIVE_EDIT_POINTER_TTL_MS, DEFAULT_PROGRESS_CURSOR_TTL_MS, } from "./types.js";
3
- /**
4
- * Cap on how many cursors and pointers a single process will hold.
5
- *
6
- * Redis expires keys on its own; a plain Map does not, and a gateway that ran
7
- * for a week would hold one entry per (caller, application) it had ever
8
- * served. Insertion order is iteration order for a Map, so the oldest write
9
- * is the one dropped — a caller evicted this way re-reads the retained
10
- * history rather than losing anything, which is the same outcome as its
11
- * cursor having expired.
12
- */
13
- export const MAX_MEMORY_PROGRESS_ENTRIES = 2_048;
14
- /**
15
- * Local-only fallback, matching the other in-memory stores.
16
- *
17
- * Not a second source of truth: two replicas with private maps would hand the
18
- * same caller two different positions in the same stream, which is exactly
19
- * the divergence Redis is required outside local to prevent.
20
- */
21
- export class MemoryProgressStore {
22
- cursors = new Map();
23
- lastActivity = new Map();
24
- liveEdits = new Map();
25
- async getCursor(key) {
26
- return read(this.cursors, cursorKey(key));
27
- }
28
- async getLastActivityAtMs(key) {
29
- return read(this.lastActivity, lastActivityKey(key));
30
- }
31
- async getLiveEditId(key) {
32
- return read(this.liveEdits, liveEditKey(key));
33
- }
34
- async setCursor(input) {
35
- write(this.cursors, cursorKey(input), input.record, {
36
- ttlMs: input.ttlMs ?? DEFAULT_PROGRESS_CURSOR_TTL_MS,
37
- });
38
- }
39
- async setLastActivityAtMs(input) {
40
- // Same retention as a cursor: past that, there is no history left to
41
- // measure a quiet spell against anyway.
42
- write(this.lastActivity, lastActivityKey(input), input.atMs, {
43
- ttlMs: input.ttlMs ?? DEFAULT_PROGRESS_CURSOR_TTL_MS,
44
- });
45
- }
46
- async setLiveEditId(input) {
47
- write(this.liveEdits, liveEditKey(input), input.liveEditId, {
48
- ttlMs: input.ttlMs ?? DEFAULT_LIVE_EDIT_POINTER_TTL_MS,
49
- });
50
- }
51
- }
52
- function read(entries, key) {
53
- const entry = entries.get(key);
54
- if (!entry) {
55
- return undefined;
56
- }
57
- if (entry.expiresAtMs <= Date.now()) {
58
- entries.delete(key);
59
- return undefined;
60
- }
61
- return entry.value;
62
- }
63
- function write(entries, key, value, options) {
64
- const now = Date.now();
65
- for (const [candidate, entry] of entries) {
66
- if (entry.expiresAtMs <= now) {
67
- entries.delete(candidate);
68
- }
69
- }
70
- // Re-inserting moves the key to the end, so a cursor being written is never
71
- // the next one evicted.
72
- entries.delete(key);
73
- entries.set(key, { expiresAtMs: now + options.ttlMs, value });
74
- while (entries.size > MAX_MEMORY_PROGRESS_ENTRIES) {
75
- const oldest = entries.keys().next();
76
- if (oldest.done) {
77
- return;
78
- }
79
- entries.delete(oldest.value);
80
- }
81
- }
82
- //# sourceMappingURL=memory-progress-store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory-progress-store.js","sourceRoot":"","sources":["../../src/resume/memory-progress-store.ts"],"names":[],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- import { type RecentApp, type RecentAppStore } from "./types.js";
2
- export declare class MemoryRecentAppStore implements RecentAppStore {
3
- private readonly byPrincipal;
4
- get(input: {
5
- organizationId: string;
6
- userId: string;
7
- }): Promise<RecentApp | undefined>;
8
- set(input: {
9
- applicationId: string;
10
- organizationId: string;
11
- ttlMs?: number;
12
- userId: string;
13
- }): Promise<void>;
14
- }
@@ -1,27 +0,0 @@
1
- import { DEFAULT_RECENT_APP_TTL_MS, } from "./types.js";
2
- function principalKey(organizationId, userId) {
3
- return `${organizationId}:${userId}`;
4
- }
5
- export class MemoryRecentAppStore {
6
- byPrincipal = new Map();
7
- async get(input) {
8
- const key = principalKey(input.organizationId, input.userId);
9
- const entry = this.byPrincipal.get(key);
10
- if (!entry) {
11
- return undefined;
12
- }
13
- if (entry.expiresAtMs <= Date.now()) {
14
- this.byPrincipal.delete(key);
15
- return undefined;
16
- }
17
- return { applicationId: entry.applicationId };
18
- }
19
- async set(input) {
20
- const ttlMs = input.ttlMs ?? DEFAULT_RECENT_APP_TTL_MS;
21
- this.byPrincipal.set(principalKey(input.organizationId, input.userId), {
22
- applicationId: input.applicationId,
23
- expiresAtMs: Date.now() + ttlMs,
24
- });
25
- }
26
- }
27
- //# sourceMappingURL=memory-recent-app-store.js.map