@vercel/factory 0.0.17 → 0.0.19

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 (186) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/api-contracts.d.mts +665 -715
  3. package/dist/api-contracts.mjs +91 -4
  4. package/dist/api-contracts.mjs.map +1 -1
  5. package/dist/api-task-graph.mjs +14 -5
  6. package/dist/api-task-graph.mjs.map +1 -1
  7. package/dist/api.d.mts +58 -11
  8. package/dist/api.mjs +715 -399
  9. package/dist/api.mjs.map +1 -1
  10. package/dist/approval-access.d.mts +1 -1
  11. package/dist/approval-contracts.d.mts +3 -4
  12. package/dist/approval-contracts.mjs +1 -2
  13. package/dist/approval-contracts.mjs.map +1 -1
  14. package/dist/blob/index.d.mts +1 -1
  15. package/dist/budget.mjs +20 -3
  16. package/dist/budget.mjs.map +1 -1
  17. package/dist/change-verification/brief.d.mts +1 -1
  18. package/dist/change-verification/dispatch.mjs +8 -1
  19. package/dist/change-verification/dispatch.mjs.map +1 -1
  20. package/dist/changes/eve-record-change.mjs +4 -1
  21. package/dist/changes/eve-record-change.mjs.map +1 -1
  22. package/dist/client-stream.d.mts +19 -2
  23. package/dist/client-stream.mjs +115 -53
  24. package/dist/client-stream.mjs.map +1 -1
  25. package/dist/client-transcript.d.mts +25 -2
  26. package/dist/client-transcript.mjs +95 -13
  27. package/dist/client-transcript.mjs.map +1 -1
  28. package/dist/client.d.mts +145 -19
  29. package/dist/client.mjs +89 -16
  30. package/dist/client.mjs.map +1 -1
  31. package/dist/code-review/contracts.d.mts +1 -0
  32. package/dist/code-review/eve-post-review.d.mts +4 -2
  33. package/dist/code-review/eve-post-review.mjs +8 -0
  34. package/dist/code-review/eve-post-review.mjs.map +1 -1
  35. package/dist/code-review/github-reporter.d.mts +6 -2
  36. package/dist/code-review/github-reporter.mjs +86 -35
  37. package/dist/code-review/github-reporter.mjs.map +1 -1
  38. package/dist/code-review/preparation.d.mts +2 -1
  39. package/dist/code-review/preparation.mjs +2 -1
  40. package/dist/code-review/preparation.mjs.map +1 -1
  41. package/dist/code-review/stall.mjs +11 -2
  42. package/dist/code-review/stall.mjs.map +1 -1
  43. package/dist/connectors/github.d.mts +1 -1
  44. package/dist/connectors/index.d.mts +1 -1
  45. package/dist/connectors/slack.d.mts +1 -1
  46. package/dist/delivery-metrics/metrics.d.mts +1 -1
  47. package/dist/dispatch.mjs +3 -3
  48. package/dist/dispatch.mjs.map +1 -1
  49. package/dist/eve/index.d.mts +1 -1
  50. package/dist/eve/index.mjs +8 -1
  51. package/dist/eve/index.mjs.map +1 -1
  52. package/dist/eve/task-execution.d.mts +4 -4
  53. package/dist/eve/transcript.d.mts +3 -1
  54. package/dist/eve/transcript.mjs.map +1 -1
  55. package/dist/finding-remediation/admission.d.mts +1 -1
  56. package/dist/finding-remediation/brief.d.mts +1 -1
  57. package/dist/github-app.d.mts +1 -1
  58. package/dist/github-publication.d.mts +1 -1
  59. package/dist/github.d.mts +9 -1
  60. package/dist/github.mjs +29 -11
  61. package/dist/github.mjs.map +1 -1
  62. package/dist/index.d.mts +1 -1
  63. package/dist/intake-contracts.d.mts +1 -0
  64. package/dist/intake-contracts.mjs +2 -1
  65. package/dist/intake-contracts.mjs.map +1 -1
  66. package/dist/integrations/github-issues.d.mts +64 -0
  67. package/dist/integrations/github-issues.mjs +175 -0
  68. package/dist/integrations/github-issues.mjs.map +1 -0
  69. package/dist/integrations/github.d.mts +2 -1
  70. package/dist/integrations/github.mjs +2 -1
  71. package/dist/multi-repository-changes/coordination.mjs +1 -1
  72. package/dist/planning/reconcile.mjs +15 -2
  73. package/dist/planning/reconcile.mjs.map +1 -1
  74. package/dist/postgres/index.d.mts +2 -1
  75. package/dist/postgres/index.mjs +11 -5
  76. package/dist/postgres/index.mjs.map +1 -1
  77. package/dist/postgres/indexed-codec.mjs +137 -0
  78. package/dist/postgres/indexed-codec.mjs.map +1 -0
  79. package/dist/postgres/indexed-schema.mjs +99 -0
  80. package/dist/postgres/indexed-schema.mjs.map +1 -0
  81. package/dist/postgres/indexed.d.mts +28 -0
  82. package/dist/postgres/indexed.mjs +277 -0
  83. package/dist/postgres/indexed.mjs.map +1 -0
  84. package/dist/postgres/record-predicates.mjs +23 -0
  85. package/dist/postgres/record-predicates.mjs.map +1 -0
  86. package/dist/presets/software-development/deepsec-brief.d.mts +1 -1
  87. package/dist/presets/software-development/dispatch.mjs +1 -1
  88. package/dist/presets/software-development/dispatch.mjs.map +1 -1
  89. package/dist/presets/software-development/recovery.mjs +9 -2
  90. package/dist/presets/software-development/recovery.mjs.map +1 -1
  91. package/dist/pull-requests/eve-fetch.d.mts +4 -1
  92. package/dist/pull-requests/eve-fetch.mjs +9 -0
  93. package/dist/pull-requests/eve-fetch.mjs.map +1 -1
  94. package/dist/pull-requests/github-publisher.d.mts +1 -1
  95. package/dist/pull-requests/github-publisher.mjs +19 -7
  96. package/dist/pull-requests/github-publisher.mjs.map +1 -1
  97. package/dist/repositories.mjs +20 -13
  98. package/dist/repositories.mjs.map +1 -1
  99. package/dist/sandbox/execution-run-ledger.d.mts +2 -2
  100. package/dist/sandbox/execution-run-ledger.mjs.map +1 -1
  101. package/dist/sandbox/execution.d.mts +2 -2
  102. package/dist/sandbox/execution.mjs.map +1 -1
  103. package/dist/schema/catalog.mjs +1 -1
  104. package/dist/schema/change.d.mts +1 -1
  105. package/dist/schema/communication.d.mts +2 -2
  106. package/dist/schema/factory-config.d.mts +1 -1
  107. package/dist/schema/outbox.d.mts +6 -6
  108. package/dist/schema/session-summary.d.mts +218 -0
  109. package/dist/schema/session-summary.mjs +68 -0
  110. package/dist/schema/session-summary.mjs.map +1 -0
  111. package/dist/schema/session.d.mts +39 -59
  112. package/dist/schema/session.mjs +6 -6
  113. package/dist/schema/session.mjs.map +1 -1
  114. package/dist/schema/task-graph.d.mts +24 -24
  115. package/dist/schema/transcript.d.mts +141 -3
  116. package/dist/schema/transcript.mjs +19 -3
  117. package/dist/schema/transcript.mjs.map +1 -1
  118. package/dist/schema/transitions.d.mts +1 -1
  119. package/dist/schema/transitions.mjs +1 -1
  120. package/dist/schema/transitions.mjs.map +1 -1
  121. package/dist/signals.d.mts +1 -1
  122. package/dist/stall.mjs +10 -2
  123. package/dist/stall.mjs.map +1 -1
  124. package/dist/storage.d.mts +10 -1
  125. package/dist/storage.mjs +7 -1
  126. package/dist/store/approvals.d.mts +14 -0
  127. package/dist/store/approvals.mjs +78 -0
  128. package/dist/store/approvals.mjs.map +1 -0
  129. package/dist/store/conversations.d.mts +59 -0
  130. package/dist/store/conversations.mjs +549 -0
  131. package/dist/store/conversations.mjs.map +1 -0
  132. package/dist/store/driver.d.mts +1 -1
  133. package/dist/store/driver.mjs.map +1 -1
  134. package/dist/store/engine.d.mts +38 -16
  135. package/dist/store/engine.mjs +229 -106
  136. package/dist/store/engine.mjs.map +1 -1
  137. package/dist/store/indexed-engine.d.mts +57 -0
  138. package/dist/store/indexed-engine.mjs +155 -0
  139. package/dist/store/indexed-engine.mjs.map +1 -0
  140. package/dist/store/indexed-memory.d.mts +7 -0
  141. package/dist/store/indexed-memory.mjs +200 -0
  142. package/dist/store/indexed-memory.mjs.map +1 -0
  143. package/dist/store/indexed-projections.d.mts +280 -0
  144. package/dist/store/indexed-projections.mjs +481 -0
  145. package/dist/store/indexed-projections.mjs.map +1 -0
  146. package/dist/store/indexed.d.mts +101 -0
  147. package/dist/store/indexed.mjs +19 -0
  148. package/dist/store/indexed.mjs.map +1 -0
  149. package/dist/store/iterate.d.mts +9 -0
  150. package/dist/store/iterate.mjs +23 -0
  151. package/dist/store/iterate.mjs.map +1 -0
  152. package/dist/store/query-scope.mjs +62 -0
  153. package/dist/store/query-scope.mjs.map +1 -0
  154. package/dist/store/query.d.mts +32 -0
  155. package/dist/store/query.mjs +103 -0
  156. package/dist/store/query.mjs.map +1 -0
  157. package/dist/store/session-history.mjs +24 -0
  158. package/dist/store/session-history.mjs.map +1 -0
  159. package/dist/store/slack-pr-notifications.d.mts +2 -2
  160. package/dist/store/slack-pr-notifications.mjs.map +1 -1
  161. package/dist/store/state.d.mts +26 -0
  162. package/dist/store/state.mjs +95 -0
  163. package/dist/store/state.mjs.map +1 -0
  164. package/dist/store/task-effects.d.mts +1 -1
  165. package/dist/store/task-graphs.d.mts +1 -1
  166. package/dist/store/task-messages.d.mts +1 -1
  167. package/dist/store/task-work.d.mts +1 -1
  168. package/dist/store/task-work.mjs +1 -1
  169. package/dist/store/transcripts.mjs +308 -0
  170. package/dist/store/transcripts.mjs.map +1 -0
  171. package/dist/sweep.d.mts +1 -1
  172. package/dist/sweep.mjs +12 -7
  173. package/dist/sweep.mjs.map +1 -1
  174. package/dist/task-communication.mjs +15 -1
  175. package/dist/task-communication.mjs.map +1 -1
  176. package/dist/task-protocols.d.mts +3 -3
  177. package/dist/tasks.d.mts +1 -1
  178. package/dist/vercel.d.mts +1 -1
  179. package/dist/work-triage/find-existing-work.d.mts +1 -1
  180. package/dist/work-triage/find-existing-work.mjs +12 -2
  181. package/dist/work-triage/find-existing-work.mjs.map +1 -1
  182. package/docs/index.md +4 -0
  183. package/docs/recipes/persistence-recovery.md +15 -9
  184. package/docs/recipes/postgres-indexed-engine.md +108 -0
  185. package/docs/recipes/postgres-indexed-storage.md +145 -0
  186. package/package.json +3 -1
@@ -0,0 +1,549 @@
1
+ import { repositoryIdSchema, taskIdSchema } from "../schema/id.mjs";
2
+ import { replyToSchema } from "../schema/common.mjs";
3
+ import { executionReferenceSchema, taskSchema } from "../schema/task.mjs";
4
+ import { imageAttachmentsSchema } from "../image-input.mjs";
5
+ import { agentSessionIdSchema, agentSessionSchema } from "../schema/session.mjs";
6
+ import { conversationStatusSchema, conversationSummarySchema } from "../schema/session-summary.mjs";
7
+ import { createHash, randomUUID } from "node:crypto";
8
+ import { z } from "zod";
9
+ //#region src/store/conversations.ts
10
+ const recordSchema = z.object({
11
+ id: z.string(),
12
+ owner: z.string(),
13
+ createdAt: z.string(),
14
+ repositoryIds: z.array(repositoryIdSchema),
15
+ agent: z.string(),
16
+ sessionAgent: z.string(),
17
+ routeKey: z.string(),
18
+ routeAgent: z.string(),
19
+ state: z.string(),
20
+ automatic: z.boolean(),
21
+ attached: z.boolean(),
22
+ interactive: z.boolean(),
23
+ topLevel: z.boolean(),
24
+ needsAttention: z.boolean(),
25
+ searchText: z.string(),
26
+ summary: conversationSummarySchema
27
+ });
28
+ const conversationExecutionSchema = z.object({
29
+ taskId: taskIdSchema.optional(),
30
+ agent: z.string(),
31
+ message: z.string(),
32
+ attachments: imageAttachmentsSchema.optional(),
33
+ execution: executionReferenceSchema
34
+ });
35
+ const historyKey = (sessionId, executionId) => `history_${hash([sessionId, executionId])}`;
36
+ const historyIndex = (sessionId) => `conversation-history:${sessionId}`;
37
+ const questionFactSchema = z.object({
38
+ repositoryIds: z.array(repositoryIdSchema),
39
+ parentId: taskIdSchema,
40
+ questionId: taskIdSchema,
41
+ replyTo: replyToSchema
42
+ });
43
+ const json = (value) => JSON.parse(JSON.stringify(value));
44
+ const hash = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
45
+ function conversationIndex(owner, repositoryId, attention = false) {
46
+ return `conversations:${hash([
47
+ owner,
48
+ repositoryId ?? null,
49
+ attention
50
+ ])}`;
51
+ }
52
+ function conversationTaskIndex(replyTo, repositoryIds) {
53
+ return `conversation-tasks:${hash([
54
+ replyTo.channel,
55
+ replyTo.address,
56
+ [...repositoryIds].sort()
57
+ ])}`;
58
+ }
59
+ async function conversationTaskMemberships(stores, task) {
60
+ if (!task.work.route || task.replyTo.channel !== "api") return [];
61
+ let parentId = task.parentTaskId;
62
+ let depth = 0;
63
+ while (parentId) {
64
+ if (++depth > 256) throw new Error("Conversation Task ancestry exceeds graph bound");
65
+ const parent = await stores.tasks.get(parentId);
66
+ if (!parent) throw new Error("Conversation Task parent is missing");
67
+ parentId = parent.parentTaskId;
68
+ }
69
+ return [{
70
+ index: conversationTaskIndex(task.replyTo, task.repositoryIds),
71
+ sortKey: `${task.createdAt}:${String(depth).padStart(3, "0")}`,
72
+ summary: { id: task.id }
73
+ }];
74
+ }
75
+ async function saveExecution(store, stores, session, task, options) {
76
+ if (task && !session.taskId) return;
77
+ const continuation = task ? await stores.sessions.getContinuation(session.id, task.id) : null;
78
+ const agent = task ? (task.work.route ? options.routes.get(task.work.route)?.agent : void 0) ?? continuation?.agent : session.agent;
79
+ const execution = task ? task.execution : session.execution;
80
+ if (!agent || !execution) return;
81
+ const key = historyKey(session.id, execution.sessionId);
82
+ const saved = await store.get("conversationExecutions", key);
83
+ if (saved) {
84
+ if (conversationExecutionSchema.parse(saved.value).execution.provider !== execution.provider) throw new Error("Execution ID collides with a different provider in this conversation");
85
+ return;
86
+ }
87
+ const history = conversationExecutionSchema.parse({
88
+ taskId: task?.id,
89
+ agent,
90
+ execution,
91
+ message: continuation?.message ?? (task && task.id !== session.taskId ? task.work.title : session.message),
92
+ attachments: continuation?.attachments ?? (!task || task.id === session.taskId ? session.attachments : void 0)
93
+ });
94
+ await store.write({
95
+ collection: "conversationExecutions",
96
+ id: key,
97
+ expectedVersion: 0,
98
+ operationId: randomUUID(),
99
+ value: json(history),
100
+ indexes: [{
101
+ index: historyIndex(session.id),
102
+ sortKey: task?.updatedAt ?? session.createdAt,
103
+ summary: { id: key }
104
+ }]
105
+ });
106
+ }
107
+ function dependencyIndex(kind, id) {
108
+ return `conversation-dependency:${hash([kind, id])}`;
109
+ }
110
+ function questionIndex(replyTo) {
111
+ return `conversation-questions:${hash([replyTo.channel, replyTo.address])}`;
112
+ }
113
+ const activeConversationStates = [
114
+ "queued",
115
+ "running",
116
+ "verifying",
117
+ "needs_human",
118
+ "stalled"
119
+ ];
120
+ const activeConversationStateSet = new Set(activeConversationStates);
121
+ const terminalConversationStates = [
122
+ "succeeded",
123
+ "failed",
124
+ "cancelled"
125
+ ];
126
+ const terminalConversationStateSet = new Set(terminalConversationStates);
127
+ function conversationStatus(input) {
128
+ const { session, question, transcript, tasks } = input;
129
+ const active = tasks.filter((task) => activeConversationStateSet.has(task.state));
130
+ if (question || transcript?.state === "needs input") return "needs_input";
131
+ if (active.some((task) => task.approval === "required" && task.state === "queued")) return "awaiting_approval";
132
+ if (active.some((task) => task.state === "verifying" || task.work.route?.id === "verification")) return "verifying";
133
+ if (active.some((task) => task.state === "stalled")) return "stalled";
134
+ if (transcript?.state === "running" || transcript?.state === "connecting") return "working";
135
+ if (active.length) return active.some((task) => task.id !== session.taskId && task.work.route?.id !== "conversation") ? "delegated" : "working";
136
+ if (tasks.filter((task) => terminalConversationStateSet.has(task.state)).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt))[0]?.state === "failed" || transcript?.state === "failed") return "failed";
137
+ return "ready";
138
+ }
139
+ function conversationStatusRevision(input) {
140
+ return hash({
141
+ status: input.status,
142
+ question: input.question ? [
143
+ input.question.id,
144
+ input.question.attempt,
145
+ input.question.updatedAt
146
+ ] : null,
147
+ transcript: input.transcript?.state ?? null,
148
+ tasks: input.tasks.map((task) => [
149
+ task.id,
150
+ task.state,
151
+ task.attempt,
152
+ task.approval ?? null,
153
+ task.changeId ?? null,
154
+ task.questionTaskId ?? null
155
+ ]).sort(([left], [right]) => String(left).localeCompare(String(right)))
156
+ });
157
+ }
158
+ function createConversationStore(store) {
159
+ return {
160
+ async history(id, query) {
161
+ const page = await store.queryRecords({
162
+ ...query,
163
+ sources: [{
164
+ collection: "conversationExecutions",
165
+ index: historyIndex(id)
166
+ }]
167
+ });
168
+ return {
169
+ items: page.entries.map((row) => conversationExecutionSchema.parse(row.record.value)),
170
+ nextCursor: page.nextCursor
171
+ };
172
+ },
173
+ async execution(id, executionId) {
174
+ const row = await store.get("conversationExecutions", historyKey(id, executionId));
175
+ return row ? conversationExecutionSchema.parse(row.value) : null;
176
+ },
177
+ async get(id) {
178
+ const row = await store.get("conversations", id);
179
+ return row ? recordSchema.parse(row.value).summary : null;
180
+ },
181
+ async list({ owner, repositoryId, attention, ...query }) {
182
+ const page = await store.queryRecords({
183
+ ...query,
184
+ includeTotal: query.includeTotal && !!(query.search || query.since || query.until),
185
+ sources: [{
186
+ collection: "conversations",
187
+ index: conversationIndex(owner, repositoryId, attention)
188
+ }]
189
+ });
190
+ const alternatives = query.match === void 0 ? [{}] : Array.isArray(query.match) ? query.match : [query.match];
191
+ const totalCount = query.includeTotal && !query.search && !query.since && !query.until ? await store.sumCounts("conversation-facets", {
192
+ match: alternatives.map((match) => ({
193
+ ...match,
194
+ owner,
195
+ ...repositoryId ? { repositoryIds: [repositoryId] } : {},
196
+ ...attention ? { needsAttention: true } : {}
197
+ })),
198
+ fields: query.fields
199
+ }) : page.totalCount;
200
+ return {
201
+ items: page.entries.map((row) => recordSchema.parse(row.record.value).summary),
202
+ nextCursor: page.nextCursor,
203
+ totalCount
204
+ };
205
+ },
206
+ count(owner, repositoryId, attention) {
207
+ return store.count(conversationIndex(owner, repositoryId, attention));
208
+ }
209
+ };
210
+ }
211
+ async function questionFact(store, stores, task) {
212
+ const parent = task.question && task.parentTaskId ? await stores.tasks.get(task.parentTaskId) : task;
213
+ if (!parent) return;
214
+ const question = parent.questionTaskId ? await stores.tasks.get(parent.questionTaskId) : null;
215
+ const valid = parent.state === "needs_human" && question?.state === "needs_human" && question.question && question.parentTaskId === parent.id && question.parentTaskAttempt === parent.attempt && question.replyTo.channel === parent.replyTo.channel && question.replyTo.address === parent.replyTo.address;
216
+ const previous = await store.get("conversationQuestions", parent.id);
217
+ if (!valid && !previous) return;
218
+ const value = valid ? {
219
+ repositoryIds: parent.repositoryIds,
220
+ parentId: parent.id,
221
+ questionId: question.id,
222
+ replyTo: parent.replyTo
223
+ } : null;
224
+ if (JSON.stringify(previous?.value) === JSON.stringify(value)) return;
225
+ await store.write({
226
+ collection: "conversationQuestions",
227
+ id: parent.id,
228
+ operationId: randomUUID(),
229
+ expectedVersion: previous?.version ?? 0,
230
+ value,
231
+ indexes: valid ? [{
232
+ index: questionIndex(parent.replyTo),
233
+ sortKey: parent.createdAt,
234
+ summary: value
235
+ }] : []
236
+ });
237
+ }
238
+ async function projectConversation(store, stores, id, options) {
239
+ const session = await stores.sessions.get(id);
240
+ if (!session) return;
241
+ const root = session.taskId ? await stores.tasks.get(session.taskId) : null;
242
+ const replyTo = session.external?.replyTo ?? {
243
+ channel: "api",
244
+ address: id
245
+ };
246
+ const match = {
247
+ replyTo,
248
+ ...session.repositoryId ? { repositoryIds: [session.repositoryId] } : {}
249
+ };
250
+ const scopeFields = [session.external ? {
251
+ path: ["repositoryIds"],
252
+ test: "subset",
253
+ value: session.external.repositoryIds
254
+ } : {
255
+ path: ["repositoryIds"],
256
+ test: "eq",
257
+ value: session.repositoryId ? [session.repositoryId] : []
258
+ }];
259
+ const candidates = root ? await store.queryRecords({
260
+ sources: [{
261
+ collection: "tasks",
262
+ index: conversationTaskIndex(replyTo, session.repositoryId ? [session.repositoryId] : [])
263
+ }],
264
+ limit: 1,
265
+ fields: [{
266
+ path: ["id"],
267
+ test: "ne",
268
+ value: root.id
269
+ }]
270
+ }) : null;
271
+ const task = candidates?.entries[0] ? taskSchema.parse(candidates.entries[0].record.value) : root;
272
+ const workMatch = match;
273
+ const workflowFields = [
274
+ ...scopeFields,
275
+ {
276
+ path: ["work", "route"],
277
+ test: "missing"
278
+ },
279
+ {
280
+ path: ["question"],
281
+ test: "missing"
282
+ }
283
+ ];
284
+ const [failed, stalled, active, activeStatusTasks, terminalStatusTasks, facts] = await Promise.all([
285
+ stores.tasks.list({
286
+ limit: 1,
287
+ match: {
288
+ ...workMatch,
289
+ state: "failed"
290
+ },
291
+ fields: workflowFields
292
+ }),
293
+ stores.tasks.list({
294
+ limit: 1,
295
+ match: {
296
+ ...workMatch,
297
+ state: "stalled"
298
+ },
299
+ fields: workflowFields
300
+ }),
301
+ stores.tasks.list({
302
+ limit: 1,
303
+ match: [
304
+ "queued",
305
+ "running",
306
+ "verifying",
307
+ "needs_human",
308
+ "stalled"
309
+ ].map((state) => ({
310
+ ...workMatch,
311
+ state
312
+ })),
313
+ fields: workflowFields
314
+ }),
315
+ stores.tasks.list({
316
+ limit: 100,
317
+ match: activeConversationStates.map((state) => ({
318
+ ...workMatch,
319
+ state
320
+ })),
321
+ fields: [...scopeFields, {
322
+ path: ["question"],
323
+ test: "missing"
324
+ }]
325
+ }),
326
+ stores.tasks.list({
327
+ limit: 100,
328
+ match: terminalConversationStates.map((state) => ({
329
+ ...workMatch,
330
+ state
331
+ })),
332
+ fields: [...scopeFields, {
333
+ path: ["question"],
334
+ test: "missing"
335
+ }]
336
+ }),
337
+ store.queryRecords({
338
+ sources: [{
339
+ collection: "conversationQuestions",
340
+ index: questionIndex(replyTo)
341
+ }],
342
+ limit: 1,
343
+ order: "asc",
344
+ fields: [{
345
+ path: ["repositoryIds"],
346
+ test: "subset",
347
+ value: session.external?.repositoryIds ?? (session.repositoryId ? [session.repositoryId] : [])
348
+ }]
349
+ })
350
+ ]);
351
+ let question = facts.entries[0] ? await stores.tasks.get(questionFactSchema.parse(facts.entries[0].record.value).questionId) : null;
352
+ if (!question && root?.state === "needs_human" && root.questionTaskId) {
353
+ const fact = await store.get("conversationQuestions", root.id);
354
+ if (fact?.value) question = await stores.tasks.get(questionFactSchema.parse(fact.value).questionId);
355
+ }
356
+ const continuation = task ? await stores.sessions.getContinuation(id, task.id) : null;
357
+ const route = task?.work.route ? options.routes.get(task.work.route) : void 0;
358
+ const activeAgent = task ? route?.agent ?? continuation?.agent : session.agent;
359
+ const execution = (activeAgent ? task?.execution ?? (!task ? session.execution : void 0) : void 0) ?? null;
360
+ const changeIds = [...new Set([
361
+ task?.changeId,
362
+ root?.changeId,
363
+ session.changeId
364
+ ].filter((value) => value !== void 0))];
365
+ const change = changeIds[0] ? await stores.changes.get(changeIds[0]) : null;
366
+ const signal = root?.origin.signalId ? await stores.signals.get(root.origin.signalId) : null;
367
+ const transcript = session.execution ? await stores.transcripts.head(session.execution) : null;
368
+ const statusTasks = [...activeStatusTasks.items, ...terminalStatusTasks.items];
369
+ const status = conversationStatus({
370
+ session,
371
+ question,
372
+ transcript,
373
+ tasks: statusTasks
374
+ });
375
+ const statusRevision = conversationStatusRevision({
376
+ status,
377
+ question,
378
+ transcript,
379
+ tasks: statusTasks
380
+ });
381
+ const attention = question ? "question" : !session.external && failed.items.length ? "failed" : !session.external && stalled.items.length ? "stalled" : task?.state === "failed" || task?.state === "stalled" ? task.state : change?.state === "ready" ? "review" : transcript?.state === "failed" ? "failed" : session.external && (transcript?.state === "waiting" || transcript?.state === "needs input") ? "conversation" : void 0;
382
+ const graph = task ? await stores.graphs.get(task.rootTaskId) : null;
383
+ const summary = conversationSummarySchema.parse({
384
+ session: {
385
+ ...session,
386
+ message: Array.from(session.message).slice(0, 128).join("")
387
+ },
388
+ task,
389
+ question,
390
+ execution,
391
+ activeAgent,
392
+ source: session.external?.replyTo.channel ?? (session.attached ? signal?.source ?? "factory" : void 0),
393
+ prUrl: change?.prUrl,
394
+ attention,
395
+ status: conversationStatusSchema.parse(status),
396
+ statusRevision,
397
+ hasWorkflowFailure: !session.external && failed.items.length > 0,
398
+ canCancel: task === null || !["succeeded", "cancelled"].includes(task.state) || active.items.length > 0,
399
+ canFollowUp: options.continuationAgent !== void 0 && root !== null,
400
+ dependencyTaskIds: graph?.nodes.find((node) => node.taskId === task?.id)?.dependencies
401
+ });
402
+ const repositoryIds = [.../* @__PURE__ */ new Set([
403
+ ...root?.repositoryIds ?? [],
404
+ ...task?.repositoryIds ?? [],
405
+ ...session.repositoryId ? [session.repositoryId] : [],
406
+ ...session.external?.repositoryIds ?? []
407
+ ])];
408
+ const repositories = await Promise.all(repositoryIds.map((repositoryId) => stores.repositories.get(repositoryId)));
409
+ const routeKey = task?.work.route ? `${task.work.route.id}@${task.work.route.version}` : "";
410
+ const value = recordSchema.parse({
411
+ id,
412
+ owner: session.owner,
413
+ createdAt: session.createdAt,
414
+ repositoryIds,
415
+ agent: activeAgent ?? session.agent,
416
+ sessionAgent: session.agent,
417
+ routeKey,
418
+ routeAgent: JSON.stringify([routeKey, activeAgent ?? session.agent]),
419
+ state: task?.state ?? "conversation",
420
+ automatic: !!(session.attached || session.external),
421
+ attached: !!session.attached,
422
+ interactive: !(session.attached || session.external),
423
+ topLevel: !!root && root.parentTaskId === void 0,
424
+ needsAttention: !!attention,
425
+ searchText: [
426
+ id,
427
+ session.message,
428
+ ...(session.attachments ?? []).map((attachment) => attachment.filename),
429
+ task?.id,
430
+ activeAgent,
431
+ ...repositories.map((repo) => repo?.slug),
432
+ signal?.source,
433
+ task?.work.title,
434
+ route?.id.replaceAll("-", " "),
435
+ root?.replyTo.address,
436
+ session.external?.replyTo.channel,
437
+ session.external?.replyTo.address
438
+ ].join(" "),
439
+ summary
440
+ });
441
+ const indexes = [];
442
+ const add = (index) => indexes.push({
443
+ index,
444
+ sortKey: session.createdAt,
445
+ summary: { id }
446
+ });
447
+ for (const repositoryId of [void 0, ...repositoryIds]) {
448
+ add(conversationIndex(session.owner, repositoryId));
449
+ if (attention) add(conversationIndex(session.owner, repositoryId, true));
450
+ }
451
+ add(dependencyIndex("reply", [replyTo.channel, replyTo.address]));
452
+ for (const taskId of new Set([session.taskId, task?.id].filter(Boolean))) add(dependencyIndex("task", taskId));
453
+ for (const changeId of changeIds) add(dependencyIndex("change", changeId));
454
+ for (const repositoryId of repositoryIds) add(dependencyIndex("repository", repositoryId));
455
+ if (root?.origin.signalId) add(dependencyIndex("signal", root.origin.signalId));
456
+ if (task) add(dependencyIndex("graph", task.rootTaskId));
457
+ if (execution) add(dependencyIndex("execution", [execution.provider, execution.sessionId]));
458
+ await saveExecution(store, stores, session, task, options);
459
+ const attributes = {
460
+ owner: value.owner,
461
+ repositoryIds: [...value.repositoryIds].sort(),
462
+ agent: value.agent,
463
+ sessionAgent: value.sessionAgent,
464
+ routeKey: value.routeKey,
465
+ routeAgent: value.routeAgent,
466
+ state: value.state,
467
+ automatic: value.automatic,
468
+ attached: value.attached,
469
+ interactive: value.interactive,
470
+ topLevel: value.topLevel,
471
+ needsAttention: value.needsAttention
472
+ };
473
+ indexes.push({
474
+ index: `conversation-facet:${hash(attributes)}`,
475
+ sortKey: value.createdAt,
476
+ summary: { id },
477
+ countGroup: {
478
+ group: "conversation-facets",
479
+ attributes
480
+ }
481
+ });
482
+ const previous = await store.get("conversations", id);
483
+ const canonical = json(value);
484
+ if (JSON.stringify(previous?.value) === JSON.stringify(canonical)) return;
485
+ await store.write({
486
+ collection: "conversations",
487
+ id,
488
+ expectedVersion: previous?.version ?? 0,
489
+ operationId: randomUUID(),
490
+ value: canonical,
491
+ indexes
492
+ });
493
+ }
494
+ async function refreshConversations(store, stores, collection, id, value, options) {
495
+ const sessions = /* @__PURE__ */ new Set();
496
+ const dependencies = [];
497
+ if (collection === "sessions" || collection === "externalSessions") sessions.add(agentSessionSchema.parse(value).id);
498
+ else if (collection === "tasks") {
499
+ const task = taskSchema.parse(value);
500
+ await questionFact(store, stores, task);
501
+ if (options.workspaceOwner && task.replyTo.channel !== "api" && task.repositoryIds.length === 1 && task.work.route) {
502
+ const route = options.routes.get(task.work.route);
503
+ if (route) sessions.add((await stores.sessions.attachTask({
504
+ owner: options.workspaceOwner,
505
+ taskId: task.id,
506
+ agent: route.agent,
507
+ message: task.work.title
508
+ })).id);
509
+ }
510
+ dependencies.push(dependencyIndex("task", id), dependencyIndex("reply", [task.replyTo.channel, task.replyTo.address]));
511
+ } else if (collection === "changes") dependencies.push(dependencyIndex("change", id));
512
+ else if (collection === "repositories") dependencies.push(dependencyIndex("repository", id));
513
+ else if (collection === "signals") dependencies.push(dependencyIndex("signal", id));
514
+ else if (collection === "taskGraphs") dependencies.push(dependencyIndex("graph", id));
515
+ else if (collection === "transcripts") {
516
+ const { execution } = z.object({ execution: z.object({
517
+ provider: z.string(),
518
+ sessionId: z.string()
519
+ }) }).parse(value);
520
+ dependencies.push(dependencyIndex("execution", [execution.provider, execution.sessionId]));
521
+ } else if (collection === "sessionContinuations") {
522
+ const { sessionId } = z.object({ sessionId: agentSessionIdSchema }).parse(value);
523
+ sessions.add(sessionId);
524
+ }
525
+ for (const index of dependencies) {
526
+ let cursor;
527
+ do {
528
+ const page = await store.query({
529
+ index,
530
+ limit: 100,
531
+ cursor
532
+ });
533
+ for (const entry of page.entries) sessions.add(entry.id);
534
+ cursor = page.nextCursor ?? void 0;
535
+ } while (cursor);
536
+ }
537
+ for (const sessionId of sessions) {
538
+ if (collection === "tasks") {
539
+ const session = await stores.sessions.get(sessionId);
540
+ const task = taskSchema.parse(value);
541
+ if (session && !session.external && (session.taskId === task.id || task.replyTo.channel === "api" && task.replyTo.address === session.id && task.repositoryIds.length === 1 && task.repositoryIds[0] === session.repositoryId)) await saveExecution(store, stores, session, task, options);
542
+ }
543
+ await projectConversation(store, stores, sessionId, options);
544
+ }
545
+ }
546
+ //#endregion
547
+ export { conversationTaskMemberships, createConversationStore, refreshConversations };
548
+
549
+ //# sourceMappingURL=conversations.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversations.mjs","names":[],"sources":["../../src/store/conversations.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { z } from \"zod\";\nimport type { AgentRouteRegistry } from \"../agent-routes\";\nimport {\n conversationStatusSchema,\n conversationSummarySchema,\n type ConversationStatus,\n type ConversationSummary,\n} from \"../schema/session-summary\";\nimport {\n agentSessionSchema,\n agentSessionIdSchema,\n type AgentSessionId,\n type AgentSession,\n} from \"../schema/session\";\nimport { taskSchema, executionReferenceSchema, type Task } from \"../schema/task\";\nimport { imageAttachmentsSchema } from \"../image-input\";\nimport { taskIdSchema, repositoryIdSchema } from \"../schema/id\";\nimport { replyToSchema } from \"../schema/common\";\nimport type { FactoryStores } from \"./engine\";\nimport type { CollectionName } from \"./driver\";\nimport type { IndexedStore, StoreIndexEntry } from \"./indexed\";\nimport type { FactoryRecordQuery, FactoryRecordPage } from \"./query\";\n\n/** Application-owned conversation routing and optional automatic-work workspace. */\nexport interface ConversationProjectionOptions {\n readonly routes: AgentRouteRegistry;\n readonly continuationAgent?: string;\n /** Explicit shared workspace receiving newly admitted external routed Tasks. */\n readonly workspaceOwner?: string;\n}\n\nconst recordSchema = z.object({\n id: z.string(),\n owner: z.string(),\n createdAt: z.string(),\n repositoryIds: z.array(repositoryIdSchema),\n agent: z.string(),\n sessionAgent: z.string(),\n routeKey: z.string(),\n routeAgent: z.string(),\n state: z.string(),\n automatic: z.boolean(),\n attached: z.boolean(),\n interactive: z.boolean(),\n topLevel: z.boolean(),\n needsAttention: z.boolean(),\n searchText: z.string(),\n summary: conversationSummarySchema,\n});\nconst conversationExecutionSchema = z.object({\n taskId: taskIdSchema.optional(),\n agent: z.string(),\n message: z.string(),\n attachments: imageAttachmentsSchema.optional(),\n execution: executionReferenceSchema,\n});\ntype ConversationExecution = z.infer<typeof conversationExecutionSchema>;\nconst historyKey = (sessionId: string, executionId: string) =>\n `history_${hash([sessionId, executionId])}`;\nconst historyIndex = (sessionId: string) => `conversation-history:${sessionId}`;\nconst questionFactSchema = z.object({\n repositoryIds: z.array(repositoryIdSchema),\n parentId: taskIdSchema,\n questionId: taskIdSchema,\n replyTo: replyToSchema,\n});\nconst json = (value: unknown): unknown => JSON.parse(JSON.stringify(value)) as unknown;\nconst hash = (value: unknown) => createHash(\"sha256\").update(JSON.stringify(value)).digest(\"hex\");\n\nfunction conversationIndex(owner: string, repositoryId?: string, attention = false): string {\n return `conversations:${hash([owner, repositoryId ?? null, attention])}`;\n}\nfunction conversationTaskIndex(replyTo: Task[\"replyTo\"], repositoryIds: readonly string[]): string {\n return `conversation-tasks:${hash([replyTo.channel, replyTo.address, [...repositoryIds].sort()])}`;\n}\n\nexport async function conversationTaskMemberships(\n stores: FactoryStores,\n task: Task,\n): Promise<StoreIndexEntry[]> {\n if (!task.work.route || task.replyTo.channel !== \"api\") return [];\n let parentId = task.parentTaskId;\n let depth = 0;\n while (parentId) {\n if (++depth > 256) throw new Error(\"Conversation Task ancestry exceeds graph bound\");\n const parent = await stores.tasks.get(parentId);\n if (!parent) throw new Error(\"Conversation Task parent is missing\");\n parentId = parent.parentTaskId;\n }\n return [\n {\n index: conversationTaskIndex(task.replyTo, task.repositoryIds),\n sortKey: `${task.createdAt}:${String(depth).padStart(3, \"0\")}`,\n summary: { id: task.id },\n },\n ];\n}\n\nasync function saveExecution(\n store: IndexedStore,\n stores: FactoryStores,\n session: AgentSession,\n task: Task | null,\n options: ConversationProjectionOptions,\n) {\n if (task && !session.taskId) return;\n const continuation = task ? await stores.sessions.getContinuation(session.id, task.id) : null;\n const agent = task\n ? ((task.work.route ? options.routes.get(task.work.route)?.agent : undefined) ??\n continuation?.agent)\n : session.agent;\n const execution = task ? task.execution : session.execution;\n if (!agent || !execution) return;\n const key = historyKey(session.id, execution.sessionId);\n const saved = await store.get(\"conversationExecutions\", key);\n if (saved) {\n if (conversationExecutionSchema.parse(saved.value).execution.provider !== execution.provider)\n throw new Error(\"Execution ID collides with a different provider in this conversation\");\n return;\n }\n const history = conversationExecutionSchema.parse({\n taskId: task?.id,\n agent,\n execution,\n message:\n continuation?.message ??\n (task && task.id !== session.taskId ? task.work.title : session.message),\n attachments:\n continuation?.attachments ??\n (!task || task.id === session.taskId ? session.attachments : undefined),\n });\n await store.write({\n collection: \"conversationExecutions\",\n id: key,\n expectedVersion: 0,\n operationId: randomUUID(),\n value: json(history),\n indexes: [\n {\n index: historyIndex(session.id),\n sortKey: task?.updatedAt ?? session.createdAt,\n summary: { id: key },\n },\n ],\n });\n}\n\nfunction dependencyIndex(kind: string, id: unknown): string {\n return `conversation-dependency:${hash([kind, id])}`;\n}\nfunction questionIndex(replyTo: Task[\"replyTo\"]): string {\n return `conversation-questions:${hash([replyTo.channel, replyTo.address])}`;\n}\n\nconst activeConversationStates = [\n \"queued\",\n \"running\",\n \"verifying\",\n \"needs_human\",\n \"stalled\",\n] as const satisfies readonly Task[\"state\"][];\nconst activeConversationStateSet = new Set<Task[\"state\"]>(activeConversationStates);\nconst terminalConversationStates = [\n \"succeeded\",\n \"failed\",\n \"cancelled\",\n] as const satisfies readonly Task[\"state\"][];\nconst terminalConversationStateSet = new Set<Task[\"state\"]>(terminalConversationStates);\n\nfunction conversationStatus(input: {\n session: AgentSession;\n question: Task | null;\n transcript: Awaited<ReturnType<FactoryStores[\"transcripts\"][\"head\"]>>;\n tasks: readonly Task[];\n}): ConversationStatus {\n const { session, question, transcript, tasks } = input;\n const active = tasks.filter((task) => activeConversationStateSet.has(task.state));\n if (question || transcript?.state === \"needs input\") return \"needs_input\";\n if (active.some((task) => task.approval === \"required\" && task.state === \"queued\"))\n return \"awaiting_approval\";\n if (active.some((task) => task.state === \"verifying\" || task.work.route?.id === \"verification\"))\n return \"verifying\";\n if (active.some((task) => task.state === \"stalled\")) return \"stalled\";\n if (transcript?.state === \"running\" || transcript?.state === \"connecting\") return \"working\";\n if (active.length) {\n const delegated = active.some(\n (task) => task.id !== session.taskId && task.work.route?.id !== \"conversation\",\n );\n return delegated ? \"delegated\" : \"working\";\n }\n const latestTerminal = tasks\n .filter((task) => terminalConversationStateSet.has(task.state))\n .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt))[0];\n if (latestTerminal?.state === \"failed\" || transcript?.state === \"failed\") return \"failed\";\n return \"ready\";\n}\n\nfunction conversationStatusRevision(input: {\n status: ConversationStatus;\n question: Task | null;\n transcript: Awaited<ReturnType<FactoryStores[\"transcripts\"][\"head\"]>>;\n tasks: readonly Task[];\n}) {\n return hash({\n status: input.status,\n question: input.question\n ? [input.question.id, input.question.attempt, input.question.updatedAt]\n : null,\n transcript: input.transcript?.state ?? null,\n tasks: input.tasks\n .map((task) => [\n task.id,\n task.state,\n task.attempt,\n task.approval ?? null,\n task.changeId ?? null,\n task.questionTaskId ?? null,\n ])\n .sort(([left], [right]) => String(left).localeCompare(String(right))),\n });\n}\n\n/** Authorized query of compact conversation records; never reads canonical Task payloads. */\nexport interface ConversationQuery extends FactoryRecordQuery {\n readonly owner: string;\n readonly repositoryId?: string;\n readonly attention?: boolean;\n}\n/** Compact conversation discovery and maintained exact-owner attention count. */\nexport interface ConversationStore {\n history(\n id: AgentSessionId,\n query: { limit: number; cursor?: string },\n ): Promise<FactoryRecordPage<ConversationExecution>>;\n execution(id: AgentSessionId, executionId: string): Promise<ConversationExecution | null>;\n get(id: AgentSessionId): Promise<ConversationSummary | null>;\n list(query: ConversationQuery): Promise<FactoryRecordPage<ConversationSummary>>;\n count(owner: string, repositoryId?: string, attention?: boolean): Promise<number>;\n}\n\nexport function createConversationStore(store: IndexedStore): ConversationStore {\n return {\n async history(id, query) {\n const page = await store.queryRecords({\n ...query,\n sources: [{ collection: \"conversationExecutions\", index: historyIndex(id) }],\n });\n return {\n items: page.entries.map((row) => conversationExecutionSchema.parse(row.record.value)),\n nextCursor: page.nextCursor,\n };\n },\n async execution(id, executionId) {\n const row = await store.get(\"conversationExecutions\", historyKey(id, executionId));\n return row ? conversationExecutionSchema.parse(row.value) : null;\n },\n async get(id) {\n const row = await store.get(\"conversations\", id);\n return row ? recordSchema.parse(row.value).summary : null;\n },\n async list({ owner, repositoryId, attention, ...query }) {\n const page = await store.queryRecords({\n ...query,\n includeTotal: query.includeTotal && !!(query.search || query.since || query.until),\n sources: [\n { collection: \"conversations\", index: conversationIndex(owner, repositoryId, attention) },\n ],\n });\n const alternatives =\n query.match === undefined ? [{}] : Array.isArray(query.match) ? query.match : [query.match];\n const totalCount =\n query.includeTotal && !query.search && !query.since && !query.until\n ? await store.sumCounts(\"conversation-facets\", {\n match: alternatives.map((match) => ({\n ...match,\n owner,\n ...(repositoryId ? { repositoryIds: [repositoryId] } : {}),\n ...(attention ? { needsAttention: true } : {}),\n })),\n fields: query.fields,\n })\n : page.totalCount;\n return {\n items: page.entries.map((row) => recordSchema.parse(row.record.value).summary),\n nextCursor: page.nextCursor,\n totalCount,\n };\n },\n count(owner, repositoryId, attention) {\n return store.count(conversationIndex(owner, repositoryId, attention));\n },\n };\n}\n\nasync function questionFact(store: IndexedStore, stores: FactoryStores, task: Task) {\n const parent =\n task.question && task.parentTaskId ? await stores.tasks.get(task.parentTaskId) : task;\n if (!parent) return;\n const question = parent.questionTaskId ? await stores.tasks.get(parent.questionTaskId) : null;\n const valid =\n parent.state === \"needs_human\" &&\n question?.state === \"needs_human\" &&\n question.question &&\n question.parentTaskId === parent.id &&\n question.parentTaskAttempt === parent.attempt &&\n question.replyTo.channel === parent.replyTo.channel &&\n question.replyTo.address === parent.replyTo.address;\n const previous = await store.get(\"conversationQuestions\", parent.id);\n if (!valid && !previous) return;\n const value = valid\n ? {\n repositoryIds: parent.repositoryIds,\n parentId: parent.id,\n questionId: question.id,\n replyTo: parent.replyTo,\n }\n : null;\n if (JSON.stringify(previous?.value) === JSON.stringify(value)) return;\n await store.write({\n collection: \"conversationQuestions\",\n id: parent.id,\n operationId: randomUUID(),\n expectedVersion: previous?.version ?? 0,\n value,\n indexes: valid\n ? [{ index: questionIndex(parent.replyTo), sortKey: parent.createdAt, summary: value }]\n : [],\n });\n}\n\nasync function projectConversation(\n store: IndexedStore,\n stores: FactoryStores,\n id: AgentSessionId,\n options: ConversationProjectionOptions,\n): Promise<void> {\n const session = await stores.sessions.get(id);\n if (!session) return;\n const root = session.taskId ? await stores.tasks.get(session.taskId) : null;\n const replyTo = session.external?.replyTo ?? { channel: \"api\", address: id };\n const match = {\n replyTo,\n ...(session.repositoryId ? { repositoryIds: [session.repositoryId] } : {}),\n };\n const scopeFields = [\n session.external\n ? {\n path: [\"repositoryIds\"],\n test: \"subset\" as const,\n value: session.external.repositoryIds,\n }\n : {\n path: [\"repositoryIds\"],\n test: \"eq\" as const,\n value: session.repositoryId ? [session.repositoryId] : [],\n },\n ];\n const candidates = root\n ? await store.queryRecords({\n sources: [\n {\n collection: \"tasks\",\n index: conversationTaskIndex(\n replyTo,\n session.repositoryId ? [session.repositoryId] : [],\n ),\n },\n ],\n limit: 1,\n fields: [{ path: [\"id\"], test: \"ne\", value: root.id }],\n })\n : null;\n const task = candidates?.entries[0] ? taskSchema.parse(candidates.entries[0].record.value) : root;\n const workMatch = match;\n const workflowFields = [\n ...scopeFields,\n { path: [\"work\", \"route\"], test: \"missing\" as const },\n { path: [\"question\"], test: \"missing\" as const },\n ];\n const [failed, stalled, active, activeStatusTasks, terminalStatusTasks, facts] =\n await Promise.all([\n stores.tasks.list({\n limit: 1,\n match: { ...workMatch, state: \"failed\" },\n fields: workflowFields,\n }),\n stores.tasks.list({\n limit: 1,\n match: { ...workMatch, state: \"stalled\" },\n fields: workflowFields,\n }),\n stores.tasks.list({\n limit: 1,\n match: [\"queued\", \"running\", \"verifying\", \"needs_human\", \"stalled\"].map((state) => ({\n ...workMatch,\n state,\n })),\n fields: workflowFields,\n }),\n stores.tasks.list({\n limit: 100,\n match: activeConversationStates.map((state) => ({ ...workMatch, state })),\n fields: [...scopeFields, { path: [\"question\"], test: \"missing\" }],\n }),\n stores.tasks.list({\n limit: 100,\n match: terminalConversationStates.map((state) => ({ ...workMatch, state })),\n fields: [...scopeFields, { path: [\"question\"], test: \"missing\" }],\n }),\n store.queryRecords({\n sources: [{ collection: \"conversationQuestions\", index: questionIndex(replyTo) }],\n limit: 1,\n order: \"asc\",\n fields: [\n {\n path: [\"repositoryIds\"],\n test: \"subset\",\n value:\n session.external?.repositoryIds ??\n (session.repositoryId ? [session.repositoryId] : []),\n },\n ],\n }),\n ]);\n let question = facts.entries[0]\n ? await stores.tasks.get(questionFactSchema.parse(facts.entries[0].record.value).questionId)\n : null;\n if (!question && root?.state === \"needs_human\" && root.questionTaskId) {\n const fact = await store.get(\"conversationQuestions\", root.id);\n if (fact?.value)\n question = await stores.tasks.get(questionFactSchema.parse(fact.value).questionId);\n }\n const continuation = task ? await stores.sessions.getContinuation(id, task.id) : null;\n const route = task?.work.route ? options.routes.get(task.work.route) : undefined;\n const activeAgent = task ? (route?.agent ?? continuation?.agent) : session.agent;\n const execution =\n (activeAgent ? (task?.execution ?? (!task ? session.execution : undefined)) : undefined) ??\n null;\n const changeIds = [\n ...new Set(\n [task?.changeId, root?.changeId, session.changeId].filter((value) => value !== undefined),\n ),\n ];\n const change = changeIds[0] ? await stores.changes.get(changeIds[0]) : null;\n const signal = root?.origin.signalId ? await stores.signals.get(root.origin.signalId) : null;\n const transcript = session.execution ? await stores.transcripts.head(session.execution) : null;\n const statusTasks = [...activeStatusTasks.items, ...terminalStatusTasks.items];\n const status = conversationStatus({ session, question, transcript, tasks: statusTasks });\n const statusRevision = conversationStatusRevision({\n status,\n question,\n transcript,\n tasks: statusTasks,\n });\n const attention = question\n ? \"question\"\n : !session.external && failed.items.length\n ? \"failed\"\n : !session.external && stalled.items.length\n ? \"stalled\"\n : task?.state === \"failed\" || task?.state === \"stalled\"\n ? task.state\n : change?.state === \"ready\"\n ? \"review\"\n : transcript?.state === \"failed\"\n ? \"failed\"\n : session.external &&\n (transcript?.state === \"waiting\" || transcript?.state === \"needs input\")\n ? \"conversation\"\n : undefined;\n const graph = task ? await stores.graphs.get(task.rootTaskId) : null;\n const summary = conversationSummarySchema.parse({\n session: { ...session, message: Array.from(session.message).slice(0, 128).join(\"\") },\n task,\n question,\n execution,\n activeAgent,\n source:\n session.external?.replyTo.channel ??\n (session.attached ? (signal?.source ?? \"factory\") : undefined),\n prUrl: change?.prUrl,\n attention,\n status: conversationStatusSchema.parse(status),\n statusRevision,\n hasWorkflowFailure: !session.external && failed.items.length > 0,\n canCancel:\n task === null || ![\"succeeded\", \"cancelled\"].includes(task.state) || active.items.length > 0,\n canFollowUp: options.continuationAgent !== undefined && root !== null,\n dependencyTaskIds: graph?.nodes.find((node) => node.taskId === task?.id)?.dependencies,\n });\n const repositoryIds = [\n ...new Set([\n ...(root?.repositoryIds ?? []),\n ...(task?.repositoryIds ?? []),\n ...(session.repositoryId ? [session.repositoryId] : []),\n ...(session.external?.repositoryIds ?? []),\n ]),\n ];\n const repositories = await Promise.all(\n repositoryIds.map((repositoryId) => stores.repositories.get(repositoryId)),\n );\n const routeKey = task?.work.route ? `${task.work.route.id}@${task.work.route.version}` : \"\";\n const value = recordSchema.parse({\n id,\n owner: session.owner,\n createdAt: session.createdAt,\n repositoryIds,\n agent: activeAgent ?? session.agent,\n sessionAgent: session.agent,\n routeKey,\n routeAgent: JSON.stringify([routeKey, activeAgent ?? session.agent]),\n state: task?.state ?? \"conversation\",\n automatic: !!(session.attached || session.external),\n attached: !!session.attached,\n interactive: !(session.attached || session.external),\n topLevel: !!root && root.parentTaskId === undefined,\n needsAttention: !!attention,\n searchText: [\n id,\n session.message,\n ...(session.attachments ?? []).map((attachment) => attachment.filename),\n task?.id,\n activeAgent,\n ...repositories.map((repo) => repo?.slug),\n signal?.source,\n task?.work.title,\n route?.id.replaceAll(\"-\", \" \"),\n root?.replyTo.address,\n session.external?.replyTo.channel,\n session.external?.replyTo.address,\n ].join(\" \"),\n summary,\n });\n const indexes: StoreIndexEntry[] = [];\n const add = (index: string) =>\n indexes.push({ index, sortKey: session.createdAt, summary: { id } });\n for (const repositoryId of [undefined, ...repositoryIds]) {\n add(conversationIndex(session.owner, repositoryId));\n if (attention) add(conversationIndex(session.owner, repositoryId, true));\n }\n add(dependencyIndex(\"reply\", [replyTo.channel, replyTo.address]));\n for (const taskId of new Set([session.taskId, task?.id].filter(Boolean)))\n add(dependencyIndex(\"task\", taskId));\n for (const changeId of changeIds) add(dependencyIndex(\"change\", changeId));\n for (const repositoryId of repositoryIds) add(dependencyIndex(\"repository\", repositoryId));\n if (root?.origin.signalId) add(dependencyIndex(\"signal\", root.origin.signalId));\n if (task) add(dependencyIndex(\"graph\", task.rootTaskId));\n if (execution) add(dependencyIndex(\"execution\", [execution.provider, execution.sessionId]));\n await saveExecution(store, stores, session, task, options);\n const attributes = {\n owner: value.owner,\n repositoryIds: [...value.repositoryIds].sort(),\n agent: value.agent,\n sessionAgent: value.sessionAgent,\n routeKey: value.routeKey,\n routeAgent: value.routeAgent,\n state: value.state,\n automatic: value.automatic,\n attached: value.attached,\n interactive: value.interactive,\n topLevel: value.topLevel,\n needsAttention: value.needsAttention,\n };\n indexes.push({\n index: `conversation-facet:${hash(attributes)}`,\n sortKey: value.createdAt,\n summary: { id },\n countGroup: { group: \"conversation-facets\", attributes },\n });\n const previous = await store.get(\"conversations\", id);\n const canonical = json(value);\n if (JSON.stringify(previous?.value) === JSON.stringify(canonical)) return;\n await store.write({\n collection: \"conversations\",\n id,\n expectedVersion: previous?.version ?? 0,\n operationId: randomUUID(),\n value: canonical,\n indexes,\n });\n}\n\nexport async function refreshConversations(\n store: IndexedStore,\n stores: FactoryStores,\n collection: CollectionName,\n id: string,\n value: unknown,\n options: ConversationProjectionOptions,\n): Promise<void> {\n const sessions = new Set<AgentSessionId>();\n const dependencies: string[] = [];\n if (collection === \"sessions\" || collection === \"externalSessions\")\n sessions.add(agentSessionSchema.parse(value).id);\n else if (collection === \"tasks\") {\n const task = taskSchema.parse(value);\n await questionFact(store, stores, task);\n if (\n options.workspaceOwner &&\n task.replyTo.channel !== \"api\" &&\n task.repositoryIds.length === 1 &&\n task.work.route\n ) {\n const route = options.routes.get(task.work.route);\n if (route)\n sessions.add(\n (\n await stores.sessions.attachTask({\n owner: options.workspaceOwner,\n taskId: task.id,\n agent: route.agent,\n message: task.work.title,\n })\n ).id,\n );\n }\n dependencies.push(\n dependencyIndex(\"task\", id),\n dependencyIndex(\"reply\", [task.replyTo.channel, task.replyTo.address]),\n );\n } else if (collection === \"changes\") dependencies.push(dependencyIndex(\"change\", id));\n else if (collection === \"repositories\") dependencies.push(dependencyIndex(\"repository\", id));\n else if (collection === \"signals\") dependencies.push(dependencyIndex(\"signal\", id));\n else if (collection === \"taskGraphs\") dependencies.push(dependencyIndex(\"graph\", id));\n else if (collection === \"transcripts\") {\n const { execution } = z\n .object({ execution: z.object({ provider: z.string(), sessionId: z.string() }) })\n .parse(value);\n dependencies.push(dependencyIndex(\"execution\", [execution.provider, execution.sessionId]));\n } else if (collection === \"sessionContinuations\") {\n const { sessionId } = z.object({ sessionId: agentSessionIdSchema }).parse(value);\n // Continuation commits must update the same session projection as head admission.\n sessions.add(sessionId);\n }\n for (const index of dependencies) {\n let cursor: string | undefined;\n do {\n const page = await store.query({ index, limit: 100, cursor });\n for (const entry of page.entries) sessions.add(entry.id as AgentSessionId);\n cursor = page.nextCursor ?? undefined;\n } while (cursor);\n }\n for (const sessionId of sessions) {\n if (collection === \"tasks\") {\n const session = await stores.sessions.get(sessionId);\n const task = taskSchema.parse(value);\n if (\n session &&\n !session.external &&\n (session.taskId === task.id ||\n (task.replyTo.channel === \"api\" &&\n task.replyTo.address === session.id &&\n task.repositoryIds.length === 1 &&\n task.repositoryIds[0] === session.repositoryId))\n )\n await saveExecution(store, stores, session, task, options);\n }\n await projectConversation(store, stores, sessionId, options);\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  //#region src/store/driver.d.ts
2
2
  /** Closed set of persistence collections understood by Factory store drivers. */
3
- type CollectionName = "repositories" | "signals" | "tasks" | "changes" | "receipts" | "budgets" | "answers" | "sessions" | "externalSessions" | "transcripts" | "images" | "questionRoutes" | "taskCatalogs" | "changeCatalogs" | "sessionCatalogs" | "externalSessionCatalogs" | "taskRoutes" | "outboxQueues" | "outboxDeliveries" | "communicationSettings" | "taskGraphs" | "taskMessages" | "taskEffects" | "taskInboxes" | "taskMessageProcessing" | "taskMessageDecisions" | "taskMessageDiscards" | "plannerActivations" | "plannerCancellations";
3
+ type CollectionName = "approvalRecords" | "applicationState" | "applicationChunks" | "conversations" | "conversationQuestions" | "conversationExecutions" | "repositories" | "signals" | "tasks" | "changes" | "receipts" | "budgets" | "answers" | "sessions" | "externalSessions" | "sessionContinuations" | "sessionNotifications" | "transcripts" | "transcriptBlocks" | "transcriptChunks" | "images" | "questionRoutes" | "taskCatalogs" | "changeCatalogs" | "sessionCatalogs" | "externalSessionCatalogs" | "taskRoutes" | "outboxQueues" | "outboxDeliveries" | "communicationSettings" | "taskGraphs" | "taskMessages" | "taskEffects" | "taskInboxes" | "taskMessageProcessing" | "taskMessageDecisions" | "taskMessageDiscards" | "plannerActivations" | "plannerCancellations";
4
4
  /** Opaque persisted value paired with its compare-and-swap version. */
5
5
  interface StoredRecord {
6
6
  readonly value: unknown;