@vercel/factory 0.0.15 → 0.0.16

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 (214) hide show
  1. package/CHANGELOG.md +356 -0
  2. package/README.md +49 -261
  3. package/dist/agent-routes.d.mts +47 -3
  4. package/dist/agent-routes.mjs +28 -1
  5. package/dist/agent-routes.mjs.map +1 -1
  6. package/dist/api-contracts.d.mts +20 -1
  7. package/dist/api-contracts.mjs +2 -1
  8. package/dist/api-contracts.mjs.map +1 -1
  9. package/dist/api.d.mts +45 -2
  10. package/dist/api.mjs +199 -10
  11. package/dist/api.mjs.map +1 -1
  12. package/dist/approval-contracts.d.mts +6 -0
  13. package/dist/blob/index.d.mts +51 -14
  14. package/dist/blob/index.mjs +26 -10
  15. package/dist/blob/index.mjs.map +1 -1
  16. package/dist/budget.d.mts +7 -0
  17. package/dist/budget.mjs +6 -0
  18. package/dist/budget.mjs.map +1 -1
  19. package/dist/build-factory.d.mts +1 -0
  20. package/dist/change-verification/dispatch.d.mts +16 -3
  21. package/dist/change-verification/dispatch.mjs +45 -7
  22. package/dist/change-verification/dispatch.mjs.map +1 -1
  23. package/dist/change-verification/eve-tool.d.mts +2 -1
  24. package/dist/change-verification/eve-tool.mjs +35 -47
  25. package/dist/change-verification/eve-tool.mjs.map +1 -1
  26. package/dist/change-verification/result.mjs +130 -0
  27. package/dist/change-verification/result.mjs.map +1 -0
  28. package/dist/changes/eve-record-change.d.mts +2 -2
  29. package/dist/changes/eve-record-change.mjs +43 -9
  30. package/dist/changes/eve-record-change.mjs.map +1 -1
  31. package/dist/changes.d.mts +4 -3
  32. package/dist/changes.mjs +2 -2
  33. package/dist/changes.mjs.map +1 -1
  34. package/dist/client-events.d.mts +10 -3
  35. package/dist/client-events.mjs +6 -2
  36. package/dist/client-events.mjs.map +1 -1
  37. package/dist/client-stream.mjs +8 -2
  38. package/dist/client-stream.mjs.map +1 -1
  39. package/dist/client-transcript.mjs +5 -1
  40. package/dist/client-transcript.mjs.map +1 -1
  41. package/dist/client.d.mts +121 -12
  42. package/dist/client.mjs +117 -9
  43. package/dist/client.mjs.map +1 -1
  44. package/dist/code-review/contracts.d.mts +1 -0
  45. package/dist/code-review/eve-post-review.d.mts +4 -4
  46. package/dist/code-review/eve-post-review.mjs +29 -17
  47. package/dist/code-review/eve-post-review.mjs.map +1 -1
  48. package/dist/code-review/eve-review-comments.d.mts +13 -2
  49. package/dist/code-review/eve-review-comments.mjs +45 -11
  50. package/dist/code-review/eve-review-comments.mjs.map +1 -1
  51. package/dist/code-review/github-reporter.d.mts +2 -0
  52. package/dist/code-review/github-reporter.mjs +7 -5
  53. package/dist/code-review/github-reporter.mjs.map +1 -1
  54. package/dist/code-review.d.mts +3 -2
  55. package/dist/deepsec/eve-tool.mjs +3 -1
  56. package/dist/deepsec/eve-tool.mjs.map +1 -1
  57. package/dist/dispatch.d.mts +79 -8
  58. package/dist/dispatch.mjs +68 -9
  59. package/dist/dispatch.mjs.map +1 -1
  60. package/dist/eve/index.d.mts +70 -10
  61. package/dist/eve/index.mjs +93 -22
  62. package/dist/eve/index.mjs.map +1 -1
  63. package/dist/eve/invoke.mjs +24 -11
  64. package/dist/eve/invoke.mjs.map +1 -1
  65. package/dist/eve/session-client.d.mts +122 -4
  66. package/dist/eve/session-client.mjs +127 -13
  67. package/dist/eve/session-client.mjs.map +1 -1
  68. package/dist/eve/task-execution.d.mts +380 -0
  69. package/dist/eve/task-execution.mjs +57 -2
  70. package/dist/eve/task-execution.mjs.map +1 -1
  71. package/dist/eve/task-session.d.mts +44 -2
  72. package/dist/eve/task-session.mjs +44 -2
  73. package/dist/eve/task-session.mjs.map +1 -1
  74. package/dist/eve/transcript.mjs +5 -1
  75. package/dist/eve/transcript.mjs.map +1 -1
  76. package/dist/execution.d.mts +117 -9
  77. package/dist/execution.mjs +76 -6
  78. package/dist/execution.mjs.map +1 -1
  79. package/dist/finding-remediation/admission.d.mts +2 -0
  80. package/dist/finding-remediation/admission.mjs +4 -1
  81. package/dist/finding-remediation/admission.mjs.map +1 -1
  82. package/dist/findings.d.mts +1 -0
  83. package/dist/github-publication.d.mts +1 -0
  84. package/dist/github-publication.mjs +97 -84
  85. package/dist/github-publication.mjs.map +1 -1
  86. package/dist/github-transfer.d.mts +15 -6
  87. package/dist/github-transfer.mjs +214 -66
  88. package/dist/github-transfer.mjs.map +1 -1
  89. package/dist/github.d.mts +51 -11
  90. package/dist/github.mjs +126 -24
  91. package/dist/github.mjs.map +1 -1
  92. package/dist/inbox-activity.d.mts +53 -0
  93. package/dist/inbox-activity.mjs +41 -0
  94. package/dist/inbox-activity.mjs.map +1 -0
  95. package/dist/index.d.mts +3 -1
  96. package/dist/index.mjs +3 -2
  97. package/dist/intake-contracts.d.mts +0 -1
  98. package/dist/integrations/deepsec.d.mts +1 -0
  99. package/dist/integrations/github.d.mts +2 -2
  100. package/dist/integrations/github.mjs +2 -2
  101. package/dist/integrations/slack.d.mts +3 -1
  102. package/dist/integrations/slack.mjs +3 -1
  103. package/dist/integrations/vercel.d.mts +4 -2
  104. package/dist/integrations/vercel.mjs +3 -2
  105. package/dist/merge-resolution/eve-tools.d.mts +1 -0
  106. package/dist/merge-resolution/eve-tools.mjs +7 -2
  107. package/dist/merge-resolution/eve-tools.mjs.map +1 -1
  108. package/dist/model-settings.d.mts +41 -0
  109. package/dist/model-settings.mjs +35 -0
  110. package/dist/model-settings.mjs.map +1 -0
  111. package/dist/planning/reconcile.mjs +6 -0
  112. package/dist/planning/reconcile.mjs.map +1 -1
  113. package/dist/postgres/index.d.mts +43 -2
  114. package/dist/postgres/index.mjs +40 -2
  115. package/dist/postgres/index.mjs.map +1 -1
  116. package/dist/presets/software-development/dispatch.d.mts +4 -1
  117. package/dist/presets/software-development/dispatch.mjs +2 -1
  118. package/dist/presets/software-development/dispatch.mjs.map +1 -1
  119. package/dist/presets/software-development/task-communication.d.mts +1 -0
  120. package/dist/presets/software-development/task-communication.mjs +48 -11
  121. package/dist/presets/software-development/task-communication.mjs.map +1 -1
  122. package/dist/presets/software-development.d.mts +1 -0
  123. package/dist/pull-requests/github-publisher.d.mts +15 -1
  124. package/dist/pull-requests/github-publisher.mjs +61 -1
  125. package/dist/pull-requests/github-publisher.mjs.map +1 -1
  126. package/dist/pull-requests.d.mts +1 -0
  127. package/dist/sandbox/index.d.mts +1 -0
  128. package/dist/schema/agent-route.d.mts +19 -1
  129. package/dist/schema/agent-route.mjs +19 -1
  130. package/dist/schema/agent-route.mjs.map +1 -1
  131. package/dist/schema/factory-config.d.mts +27 -0
  132. package/dist/schema/factory-config.mjs +33 -3
  133. package/dist/schema/factory-config.mjs.map +1 -1
  134. package/dist/schema/repository.d.mts +4 -0
  135. package/dist/schema/repository.mjs +5 -1
  136. package/dist/schema/repository.mjs.map +1 -1
  137. package/dist/schema/session.d.mts +1 -0
  138. package/dist/schema/session.mjs +1 -0
  139. package/dist/schema/session.mjs.map +1 -1
  140. package/dist/schema/slack-pr-notifications.d.mts +12 -0
  141. package/dist/schema/slack-pr-notifications.mjs +11 -0
  142. package/dist/schema/slack-pr-notifications.mjs.map +1 -0
  143. package/dist/schema/task-graph.d.mts +39 -0
  144. package/dist/schema/task.d.mts +1 -0
  145. package/dist/schema/task.mjs +2 -1
  146. package/dist/schema/task.mjs.map +1 -1
  147. package/dist/schema/transcript.d.mts +6 -0
  148. package/dist/schema/transcript.mjs +2 -1
  149. package/dist/schema/transcript.mjs.map +1 -1
  150. package/dist/schema/work.d.mts +52 -3
  151. package/dist/schema/work.mjs.map +1 -1
  152. package/dist/session-previews.d.mts +76 -0
  153. package/dist/session-previews.mjs +55 -0
  154. package/dist/session-previews.mjs.map +1 -0
  155. package/dist/session-review.d.mts +120 -0
  156. package/dist/session-review.mjs +79 -0
  157. package/dist/session-review.mjs.map +1 -0
  158. package/dist/signal-triage.mjs +1 -1
  159. package/dist/signals.d.mts +1 -0
  160. package/dist/stall.d.mts +4 -1
  161. package/dist/stall.mjs +6 -2
  162. package/dist/stall.mjs.map +1 -1
  163. package/dist/store/driver.d.mts +1 -1
  164. package/dist/store/driver.mjs.map +1 -1
  165. package/dist/store/engine.d.mts +206 -8
  166. package/dist/store/engine.mjs +147 -13
  167. package/dist/store/engine.mjs.map +1 -1
  168. package/dist/store/memory.d.mts +18 -1
  169. package/dist/store/memory.mjs +18 -1
  170. package/dist/store/memory.mjs.map +1 -1
  171. package/dist/store/slack-pr-notifications.d.mts +44 -0
  172. package/dist/store/slack-pr-notifications.mjs +121 -0
  173. package/dist/store/slack-pr-notifications.mjs.map +1 -0
  174. package/dist/store/task-work.d.mts +121 -6
  175. package/dist/store/task-work.mjs +7 -4
  176. package/dist/store/task-work.mjs.map +1 -1
  177. package/dist/sweep.d.mts +28 -6
  178. package/dist/sweep.mjs +34 -6
  179. package/dist/sweep.mjs.map +1 -1
  180. package/dist/task-graph-view.d.mts +3 -0
  181. package/dist/tasks.d.mts +3 -3
  182. package/dist/tasks.mjs +3 -3
  183. package/dist/vercel-git.d.mts +35 -3
  184. package/dist/vercel-git.mjs +265 -33
  185. package/dist/vercel-git.mjs.map +1 -1
  186. package/dist/vercel-github-api.d.mts +103 -0
  187. package/dist/vercel-github-api.mjs +363 -0
  188. package/dist/vercel-github-api.mjs.map +1 -0
  189. package/dist/vercel.d.mts +3 -2
  190. package/dist/vercel.mjs +3 -2
  191. package/dist/vercel.mjs.map +1 -1
  192. package/dist/work-triage.d.mts +1 -0
  193. package/dist/workflows.d.mts +102 -4
  194. package/dist/workflows.mjs +55 -2
  195. package/dist/workflows.mjs.map +1 -1
  196. package/dist/workspace-files-git.d.mts +15 -0
  197. package/dist/workspace-files-git.mjs +61 -0
  198. package/dist/workspace-files-git.mjs.map +1 -0
  199. package/dist/workspace-files.d.mts +107 -0
  200. package/dist/workspace-files.mjs +74 -0
  201. package/dist/workspace-files.mjs.map +1 -0
  202. package/docs/getting-started.md +104 -0
  203. package/docs/index.md +100 -0
  204. package/docs/recipes/cancellation.md +215 -0
  205. package/docs/recipes/custom-workflow.md +153 -0
  206. package/docs/recipes/dependent-tasks.md +207 -0
  207. package/docs/recipes/eve-agent.md +277 -0
  208. package/docs/recipes/human-input.md +204 -0
  209. package/docs/recipes/persistence-recovery.md +268 -0
  210. package/docs/recipes/retry-recovery.md +241 -0
  211. package/docs/recipes/task-messaging.md +215 -0
  212. package/docs/recipes/typed-eve-result.md +161 -0
  213. package/docs/runtime-integration.md +137 -0
  214. package/package.json +17 -6
@@ -1 +1 @@
1
- {"version":3,"file":"client-stream.mjs","names":[],"sources":["../src/client-stream.ts"],"sourcesContent":["import { ApiError, type FactoryClient } from \"./client\";\nimport { readEvents } from \"./client-events\";\nimport { Transcript } from \"./client-transcript\";\nimport type { SessionView } from \"./api-contracts\";\nimport type { TaskId } from \"./schema/id\";\nimport type { AgentSessionId } from \"./schema/session\";\nimport { transcriptSnapshotSchema } from \"./schema/transcript\";\n\n/** Client operations required to hydrate and follow a Factory session stream. */\nexport type SessionStreamClient = Pick<\n FactoryClient,\n \"getSessionTranscriptResponse\" | \"getSessionEventStreamResponse\"\n>;\n\n/** Callbacks and exact execution identity used while following a session stream. */\nexport interface FollowSessionStreamOptions {\n readonly sessionId: AgentSessionId;\n readonly executionId: string | null;\n readonly taskId?: TaskId;\n readonly history?: readonly NonNullable<SessionView[\"history\"]>[number][];\n readonly transcript: Transcript;\n readonly signal: AbortSignal;\n readonly pollIntervalMs?: number;\n readonly onHydrated: () => void;\n readonly onChange: () => void;\n readonly onConnection: (state: \"connected\" | \"reconnecting\") => void;\n readonly onError: (error: unknown) => void;\n readonly onConflict: () => Promise<void>;\n}\n\nfunction pause(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const finish = () => {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", finish);\n resolve();\n };\n const timer = setTimeout(finish, ms);\n signal.addEventListener(\"abort\", finish, { once: true });\n if (signal.aborted) finish();\n });\n}\n\nasync function readSnapshot(\n client: SessionStreamClient,\n input: {\n sessionId: AgentSessionId;\n executionId: string;\n taskId?: TaskId;\n history: boolean;\n transcript: Transcript;\n signal: AbortSignal;\n pollIntervalMs: number;\n onRetry?(error: unknown): void;\n },\n) {\n let failures = 0;\n while (!input.signal.aborted) {\n try {\n const requestSignal = AbortSignal.any([input.signal, AbortSignal.timeout(15_000)]);\n const response = await client.getSessionTranscriptResponse({\n sessionId: input.sessionId,\n executionId: input.executionId,\n ...(input.taskId === undefined ? {} : { taskId: input.taskId }),\n ...(input.history ? { history: true } : {}),\n signal: requestSignal,\n });\n input.transcript.hydrate(transcriptSnapshotSchema.parse(await response.json()));\n return;\n } catch (error) {\n if (input.signal.aborted) return;\n if (error instanceof ApiError) throw error;\n input.onRetry?.(error);\n failures++;\n await pause(\n Math.min(15_000, input.pollIntervalMs * 2 ** Math.min(failures, 3)),\n input.signal,\n );\n }\n }\n}\n\nasync function loadHistory(\n client: SessionStreamClient,\n options: FollowSessionStreamOptions,\n): Promise<{ id: string; transcript: Transcript }[]> {\n const entries = options.history ?? [];\n const results = new Map<number, { id: string; transcript: Transcript }>();\n let next = 0;\n await Promise.all(\n Array.from({ length: Math.min(4, entries.length) }, async () => {\n while (next < entries.length) {\n const index = next++;\n const entry = entries[index];\n if (!entry) throw new Error(\"Historical transcript index is unavailable\");\n const id = entry.execution.sessionId;\n const previous = new Transcript(entry.message, entry.attachments);\n const header = {\n id: \"run\",\n kind: \"status\",\n title: entry.agent,\n text: entry.taskId ? `Earlier work · ${entry.taskId}` : \"Earlier execution\",\n } as const;\n try {\n const historySignal = AbortSignal.any([options.signal, AbortSignal.timeout(15_000)]);\n await readSnapshot(client, {\n sessionId: options.sessionId,\n executionId: id,\n history: true,\n transcript: previous,\n signal: historySignal,\n pollIntervalMs: options.pollIntervalMs ?? 2000,\n });\n if (historySignal.aborted && !options.signal.aborted)\n throw new Error(\"Historical transcript loading timed out\");\n } catch (error) {\n if (options.signal.aborted) return;\n if (error instanceof ApiError && [401, 403].includes(error.status)) throw error;\n previous.put({\n id: \"unavailable\",\n kind: \"status\",\n title: \"History unavailable\",\n text: \"This execution's transcript could not be loaded.\",\n });\n }\n previous.blocks.unshift(header);\n results.set(index, { id, transcript: previous });\n }\n }),\n );\n return entries.map((_, index) => {\n const result = results.get(index);\n if (!result) throw new Error(\"Historical transcript loading did not complete\");\n return result;\n });\n}\n\nasync function hydrateCurrent(\n client: SessionStreamClient,\n options: FollowSessionStreamOptions,\n): Promise<boolean> {\n const executionId = options.executionId;\n if (executionId === null) return true;\n let failures = 0;\n while (!options.signal.aborted) {\n try {\n await readSnapshot(client, {\n sessionId: options.sessionId,\n executionId,\n taskId: options.taskId,\n history: false,\n transcript: options.transcript,\n signal: options.signal,\n pollIntervalMs: options.pollIntervalMs ?? 2000,\n onRetry: (error) => {\n options.onConnection(\"reconnecting\");\n options.onError(error);\n },\n });\n if (options.signal.aborted) return false;\n options.onConnection(\"connected\");\n return true;\n } catch (error) {\n if (options.signal.aborted) return false;\n options.onConnection(\"reconnecting\");\n failures++;\n options.onError(error);\n if (\n error instanceof ApiError &&\n [0, 301, 302, 303, 307, 308, 401, 403].includes(error.status)\n )\n return false;\n if (error instanceof ApiError && options.taskId && error.status === 404) return false;\n if (error instanceof ApiError && error.status === 409) {\n await options.onConflict();\n return false;\n }\n await pause(\n Math.min(15_000, (options.pollIntervalMs ?? 2000) * 2 ** Math.min(failures, 3)),\n options.signal,\n );\n }\n }\n return false;\n}\n\n/** Hydrates a transcript and follows its current execution until completion or disconnection. */\nexport async function followSessionStream(\n client: SessionStreamClient,\n options: FollowSessionStreamOptions,\n): Promise<void> {\n const { sessionId, executionId, transcript, signal } = options;\n let history: { id: string; transcript: Transcript }[];\n let hydrated: boolean;\n try {\n [history, hydrated] = await Promise.all([\n loadHistory(client, options),\n hydrateCurrent(client, options),\n ]);\n } catch (error) {\n if (!signal.aborted) options.onError(error);\n return;\n }\n if (signal.aborted || !hydrated) return;\n transcript.prependHistory(history);\n if (executionId === null) transcript.state = \"waiting\";\n options.onHydrated();\n if (executionId === null || [\"completed\", \"failed\"].includes(transcript.state)) return;\n let failures = 0;\n while (!signal.aborted) {\n const recycle = AbortSignal.timeout(60_000);\n let established = false;\n try {\n const response = await client.getSessionEventStreamResponse({\n sessionId,\n executionId,\n cursor: transcript.cursor,\n ...(options.taskId === undefined ? {} : { taskId: options.taskId }),\n signal: AbortSignal.any([signal, recycle]),\n });\n if (!response.body) throw new Error(\"The factory returned an empty stream\");\n established = true;\n options.onConnection(\"connected\");\n for await (const event of readEvents(response.body)) {\n if (signal.aborted) return;\n transcript.accept(event);\n failures = 0;\n options.onChange();\n }\n if ([\"completed\", \"failed\"].includes(transcript.state)) return;\n } catch (error) {\n if (signal.aborted) return;\n options.onConnection(\"reconnecting\");\n if (recycle.aborted && established) {\n failures = 0;\n continue;\n }\n failures++;\n options.onError(error);\n if (\n error instanceof ApiError &&\n [0, 301, 302, 303, 307, 308, 401, 403].includes(error.status)\n )\n return;\n if (error instanceof ApiError && options.taskId && error.status === 404) return;\n if (error instanceof ApiError && error.status === 409) {\n await options.onConflict();\n return;\n }\n }\n await pause(\n Math.min(15_000, (options.pollIntervalMs ?? 2000) * 2 ** Math.min(failures, 3)),\n signal,\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client-stream.mjs","names":[],"sources":["../src/client-stream.ts"],"sourcesContent":["import { ApiError, type FactoryClient } from \"./client\";\nimport { readEvents } from \"./client-events\";\nimport { Transcript } from \"./client-transcript\";\nimport type { SessionView } from \"./api-contracts\";\nimport type { TaskId } from \"./schema/id\";\nimport type { AgentSessionId } from \"./schema/session\";\nimport { transcriptSnapshotSchema } from \"./schema/transcript\";\n\n/** Client operations required to hydrate and follow a Factory session stream. */\nexport type SessionStreamClient = Pick<\n FactoryClient,\n \"getSessionTranscriptResponse\" | \"getSessionEventStreamResponse\"\n>;\n\n/** Callbacks and exact execution identity used while following a session stream. */\nexport interface FollowSessionStreamOptions {\n readonly sessionId: AgentSessionId;\n readonly executionId: string | null;\n readonly taskId?: TaskId;\n readonly history?: readonly NonNullable<SessionView[\"history\"]>[number][];\n readonly transcript: Transcript;\n readonly signal: AbortSignal;\n readonly pollIntervalMs?: number;\n readonly onHydrated: () => void;\n readonly onChange: () => void;\n readonly onConnection: (state: \"connected\" | \"reconnecting\") => void;\n readonly onError: (error: unknown) => void;\n readonly onConflict: () => Promise<void>;\n}\n\nfunction pause(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const finish = () => {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", finish);\n resolve();\n };\n const timer = setTimeout(finish, ms);\n signal.addEventListener(\"abort\", finish, { once: true });\n if (signal.aborted) finish();\n });\n}\n\nasync function readSnapshot(\n client: SessionStreamClient,\n input: {\n sessionId: AgentSessionId;\n executionId: string;\n taskId?: TaskId;\n history: boolean;\n transcript: Transcript;\n signal: AbortSignal;\n pollIntervalMs: number;\n onRetry?(error: unknown): void;\n },\n) {\n let failures = 0;\n while (!input.signal.aborted) {\n try {\n const requestSignal = AbortSignal.any([input.signal, AbortSignal.timeout(15_000)]);\n const response = await client.getSessionTranscriptResponse({\n sessionId: input.sessionId,\n executionId: input.executionId,\n ...(input.taskId === undefined ? {} : { taskId: input.taskId }),\n ...(input.history ? { history: true } : {}),\n signal: requestSignal,\n });\n input.transcript.hydrate(transcriptSnapshotSchema.parse(await response.json()));\n return;\n } catch (error) {\n if (input.signal.aborted) return;\n if (error instanceof ApiError) throw error;\n input.onRetry?.(error);\n failures++;\n await pause(\n Math.min(15_000, input.pollIntervalMs * 2 ** Math.min(failures, 3)),\n input.signal,\n );\n }\n }\n}\n\nasync function loadHistory(\n client: SessionStreamClient,\n options: FollowSessionStreamOptions,\n): Promise<{ id: string; transcript: Transcript }[]> {\n const entries = options.history ?? [];\n const results = new Map<number, { id: string; transcript: Transcript }>();\n let next = 0;\n await Promise.all(\n Array.from({ length: Math.min(4, entries.length) }, async () => {\n while (next < entries.length) {\n const index = next++;\n const entry = entries[index];\n if (!entry) throw new Error(\"Historical transcript index is unavailable\");\n const id = entry.execution.sessionId;\n const previous = new Transcript(entry.message, entry.attachments);\n const header = {\n id: \"run\",\n kind: \"status\",\n title: entry.agent,\n text: entry.taskId ? `Earlier work · ${entry.taskId}` : \"Earlier execution\",\n } as const;\n try {\n const historySignal = AbortSignal.any([options.signal, AbortSignal.timeout(15_000)]);\n await readSnapshot(client, {\n sessionId: options.sessionId,\n executionId: id,\n history: true,\n transcript: previous,\n signal: historySignal,\n pollIntervalMs: options.pollIntervalMs ?? 2000,\n });\n if (historySignal.aborted && !options.signal.aborted)\n throw new Error(\"Historical transcript loading timed out\");\n } catch (error) {\n if (options.signal.aborted) return;\n if (error instanceof ApiError && [401, 403].includes(error.status)) throw error;\n previous.put({\n id: \"unavailable\",\n kind: \"status\",\n title: \"History unavailable\",\n text: \"This execution's transcript could not be loaded.\",\n });\n }\n previous.blocks.unshift(header);\n results.set(index, { id, transcript: previous });\n }\n }),\n );\n return entries.map((_, index) => {\n const result = results.get(index);\n if (!result) throw new Error(\"Historical transcript loading did not complete\");\n return result;\n });\n}\n\nasync function hydrateCurrent(\n client: SessionStreamClient,\n options: FollowSessionStreamOptions,\n): Promise<boolean> {\n const executionId = options.executionId;\n if (executionId === null) return true;\n let failures = 0;\n while (!options.signal.aborted) {\n try {\n await readSnapshot(client, {\n sessionId: options.sessionId,\n executionId,\n taskId: options.taskId,\n history: false,\n transcript: options.transcript,\n signal: options.signal,\n pollIntervalMs: options.pollIntervalMs ?? 2000,\n onRetry: (error) => {\n options.onConnection(\"reconnecting\");\n options.onError(error);\n },\n });\n if (options.signal.aborted) return false;\n options.onConnection(\"connected\");\n return true;\n } catch (error) {\n if (options.signal.aborted) return false;\n options.onConnection(\"reconnecting\");\n failures++;\n options.onError(error);\n if (\n error instanceof ApiError &&\n [0, 301, 302, 303, 307, 308, 401, 403].includes(error.status)\n )\n return false;\n if (error instanceof ApiError && error.status === 404) return false;\n if (error instanceof ApiError && error.status === 409) {\n await options.onConflict();\n return false;\n }\n await pause(\n Math.min(15_000, (options.pollIntervalMs ?? 2000) * 2 ** Math.min(failures, 3)),\n options.signal,\n );\n }\n }\n return false;\n}\n\n/** Hydrates a transcript and follows its current execution until completion or disconnection. */\nexport async function followSessionStream(\n client: SessionStreamClient,\n options: FollowSessionStreamOptions,\n): Promise<void> {\n const { sessionId, executionId, transcript, signal } = options;\n let history: { id: string; transcript: Transcript }[];\n let hydrated: boolean;\n try {\n [history, hydrated] = await Promise.all([\n loadHistory(client, options),\n hydrateCurrent(client, options),\n ]);\n } catch (error) {\n if (!signal.aborted) options.onError(error);\n return;\n }\n if (signal.aborted || !hydrated) return;\n transcript.prependHistory(history);\n if (executionId === null) transcript.state = \"waiting\";\n options.onHydrated();\n if (executionId === null || [\"completed\", \"failed\"].includes(transcript.state)) return;\n let failures = 0;\n while (!signal.aborted) {\n const recycle = AbortSignal.timeout(60_000);\n let established = false;\n try {\n const response = await client.getSessionEventStreamResponse({\n sessionId,\n executionId,\n cursor: transcript.cursor,\n ...(options.taskId === undefined ? {} : { taskId: options.taskId }),\n signal: AbortSignal.any([signal, recycle]),\n });\n if (!response.body) throw new Error(\"The factory returned an empty stream\");\n established = true;\n options.onConnection(\"connected\");\n for await (const event of readEvents(response.body)) {\n if (signal.aborted) return;\n transcript.accept(event);\n failures = 0;\n options.onChange();\n }\n if ([\"completed\", \"failed\"].includes(transcript.state)) return;\n } catch (error) {\n if (signal.aborted) return;\n options.onConnection(\"reconnecting\");\n if (recycle.aborted && established) {\n failures = 0;\n continue;\n }\n failures++;\n options.onError(error);\n if (\n error instanceof ApiError &&\n [0, 301, 302, 303, 307, 308, 401, 403].includes(error.status)\n )\n return;\n if (error instanceof ApiError && error.status === 404) {\n if (transcript.state === \"running\") {\n transcript.state = \"connecting\";\n options.onChange();\n }\n return;\n }\n if (error instanceof ApiError && error.status === 409) {\n await options.onConflict();\n return;\n }\n }\n await pause(\n Math.min(15_000, (options.pollIntervalMs ?? 2000) * 2 ** Math.min(failures, 3)),\n signal,\n );\n }\n}\n"],"mappings":"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"}
@@ -202,7 +202,11 @@ var Transcript = class {
202
202
  const total = (value) => typeof value === "number" ? value : Number(record(value).total ?? 0);
203
203
  this.tokens += total(usage.inputTokens) + total(usage.outputTokens);
204
204
  }
205
- if (type === "session.waiting") this.state = this.inputs.size > 0 ? "needs input" : "waiting";
205
+ if (type === "session.waiting" || [
206
+ "turn.completed",
207
+ "turn.failed",
208
+ "turn.cancelled"
209
+ ].includes(type) && (this.turnId === void 0 || data.turnId === this.turnId)) this.state = this.inputs.size > 0 ? "needs input" : "waiting";
206
210
  if (["session.completed", "session.failed"].includes(type)) this.state = type.slice(8);
207
211
  if (type.endsWith(".failed") || type === "turn.cancelled" || type.startsWith("compaction.") || type.startsWith("authorization.") || type.startsWith("subagent.")) this.put({
208
212
  id: `event:${event.meta?.id ?? this.cursor}`,
@@ -1 +1 @@
1
- {"version":3,"file":"client-transcript.mjs","names":[],"sources":["../src/client-transcript.ts"],"sourcesContent":["import { receivedImages, type ImageAttachment } from \"./image-input\";\nimport type { StreamEvent } from \"./client-events\";\nimport {\n inputRequestSchema,\n transcriptSnapshotSchema,\n type InputRequest,\n type ToolCall,\n type TranscriptBlock,\n type TranscriptSnapshot,\n} from \"./schema/transcript\";\n\nexport type {\n InputRequest,\n ToolCall,\n TranscriptBlock,\n TranscriptSnapshot,\n} from \"./schema/transcript\";\n\nfunction record(value: unknown): Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\nfunction string(value: unknown): string {\n return typeof value === \"string\" ? value : (JSON.stringify(value, null, 2) ?? \"\");\n}\nfunction parseInput(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\nfunction settled(tool: ToolCall) {\n return [\"completed\", \"failed\", \"cancelled\", \"rejected\"].includes(tool.state);\n}\n\n/** Mutable client-side projection of snapshot and live Factory transcript events. */\nexport class Transcript {\n blocks: TranscriptBlock[] = [];\n inputs = new Map<string, InputRequest>();\n cursor = 0;\n state = \"connecting\";\n turnId?: string;\n tokens = 0;\n private seen = new Set<string>();\n private tools = new Map<string, ToolCall>();\n constructor(\n private initialMessage?: string,\n private initialAttachments?: readonly ImageAttachment[],\n ) {}\n\n snapshot(): TranscriptSnapshot {\n return transcriptSnapshotSchema.parse({\n blocks: this.blocks,\n inputs: [...this.inputs.values()],\n cursor: this.cursor,\n state: this.state,\n turnId: this.turnId,\n tokens: this.tokens,\n });\n }\n\n hydrate(value: TranscriptSnapshot): void {\n const snapshot = transcriptSnapshotSchema.parse(value);\n this.blocks = snapshot.blocks.map((block) => ({ ...block }));\n const firstUser = this.blocks.find(\n (block): block is Extract<TranscriptBlock, { kind: \"user\" }> => block.kind === \"user\",\n );\n if (\n firstUser !== undefined &&\n (this.initialMessage !== undefined || this.initialAttachments !== undefined)\n ) {\n const text = this.initialMessage ?? firstUser.text;\n const attachments = this.initialAttachments ?? firstUser.attachments;\n const firstUserIndex = this.blocks.indexOf(firstUser);\n if (attachments?.length) {\n this.blocks[firstUserIndex] = { ...firstUser, text, attachments: [...attachments] };\n } else {\n const { attachments: _attachments, ...withoutAttachments } = firstUser;\n this.blocks[firstUserIndex] = { ...withoutAttachments, text };\n }\n }\n this.inputs = new Map(snapshot.inputs.map((request) => [request.requestId, request]));\n this.cursor = snapshot.cursor;\n this.state = snapshot.state;\n this.turnId = snapshot.turnId;\n this.tokens = snapshot.tokens;\n this.seen.clear();\n this.tools = new Map(\n this.blocks.flatMap((block) =>\n block.tool ? [[block.tool.callId, block.tool] as const] : [],\n ),\n );\n this.initialMessage = undefined;\n this.initialAttachments = undefined;\n }\n\n put(block: TranscriptBlock) {\n const index = this.blocks.findIndex((item) => item.id === block.id);\n if (index < 0) this.blocks.push(block);\n else this.blocks[index] = block;\n }\n\n appendHistory(id: string, transcript: Transcript) {\n for (const block of transcript.blocks) this.put({ ...block, id: `history:${id}:${block.id}` });\n }\n\n prependHistory(entries: readonly { id: string; transcript: Transcript }[]) {\n const history = entries.flatMap(({ id, transcript }) =>\n transcript.blocks.map((block) => ({ ...block, id: `history:${id}:${block.id}` })),\n );\n const ids = new Set(history.map((block) => block.id));\n this.blocks = [...history, ...this.blocks.filter((block) => !ids.has(block.id))];\n }\n\n accept(event: StreamEvent) {\n this.cursor++;\n if (event.meta?.id !== undefined) {\n if (this.seen.has(event.meta.id)) return;\n this.seen.add(event.meta.id);\n }\n const { type, data } = event;\n const coordinate = `${data.turnId}:${data.stepIndex}:${data.sequence}`;\n if (type === \"turn.started\") {\n this.turnId = string(data.turnId);\n this.state = \"running\";\n }\n if (type === \"message.received\") {\n const attachments = this.initialAttachments ?? receivedImages(data.parts);\n const partsText = Array.isArray(data.parts)\n ? data.parts\n .filter((part) => record(part).type === \"text\")\n .map((part) => string(record(part).text))\n .join(\"\\n\")\n : undefined;\n this.put({\n id: `user:${event.meta?.id ?? this.cursor}`,\n kind: \"user\",\n title: \"You\",\n text:\n this.initialMessage ?? (attachments.length ? (partsText ?? \"\") : string(data.message)),\n ...(attachments.length ? { attachments: [...attachments] } : {}),\n });\n this.initialMessage = undefined;\n this.initialAttachments = undefined;\n }\n if (type === \"message.appended\" || type === \"message.completed\")\n this.put({\n id: `message:${coordinate}`,\n kind: \"assistant\",\n title: \"Assistant\",\n text: string(data.message),\n });\n if (type === \"result.completed\")\n this.put({\n id: `result:${coordinate}`,\n kind: \"assistant\",\n title: \"Result\",\n text: `\\`\\`\\`json\\n${string(data.result)}\\n\\`\\`\\``,\n });\n if (type === \"reasoning.appended\" || type === \"reasoning.completed\")\n this.put({\n id: `reasoning:${coordinate}`,\n kind: \"reasoning\",\n title: \"Reasoning\",\n text: string(data.reasoning),\n });\n if (type === \"actions.requested\" && Array.isArray(data.actions))\n for (const item of data.actions) {\n const action = record(item);\n const callId = string(action.callId);\n const previous = this.tools.get(callId);\n this.tool({\n ...previous,\n callId,\n input: action.input,\n inputText: string(action.input),\n name: string(action.toolName ?? action.name ?? action.kind),\n state: previous?.state === \"input-streaming\" ? \"running\" : (previous?.state ?? \"running\"),\n });\n }\n if (type === \"action.input.appended\") {\n const id = string(data.callId);\n const previous = this.tools.get(id);\n const offset = data.inputTextOffset;\n const delta = string(data.inputTextDelta);\n if (\n (!previous || previous.state === \"input-streaming\") &&\n (offset === 0 || offset === previous?.inputText.length)\n ) {\n const inputText = (offset === 0 ? \"\" : (previous?.inputText ?? \"\")) + delta;\n this.tool({\n callId: id,\n input: parseInput(inputText),\n inputText,\n name: string(data.toolName),\n state: \"input-streaming\",\n });\n }\n }\n if (type === \"action.result\" || type === \"action.partial\") {\n const result = record(data.result);\n const id = string(result.callId);\n const previous = this.tools.get(id);\n if (type !== \"action.partial\" || !previous || !settled(previous))\n this.tool({\n ...previous,\n callId: id,\n input: previous?.input,\n inputText: previous?.inputText ?? \"\",\n name: previous?.name ?? string(result.toolName ?? result.kind),\n output: \"output\" in result ? result.output : result,\n error: data.error,\n state:\n type === \"action.partial\"\n ? \"running\"\n : data.status === \"rejected\"\n ? \"rejected\"\n : data.status === \"failed\" || data.error != null\n ? \"failed\"\n : \"completed\",\n });\n }\n if (type === \"turn.cancelled\" || type === \"turn.failed\" || type === \"session.failed\")\n for (const tool of this.tools.values()) {\n if (!settled(tool))\n this.tool({\n ...tool,\n state: type === \"turn.cancelled\" ? \"cancelled\" : \"failed\",\n error: data.message,\n });\n }\n if (type === \"input.requested\") {\n for (const request of inputRequestSchema.array().parse(data.requests))\n this.inputs.set(request.requestId, request);\n this.state = \"needs input\";\n }\n if (type === \"input.resolved\" && Array.isArray(data.resolutions))\n for (const resolution of data.resolutions)\n this.inputs.delete(string(record(resolution).requestId));\n if (type === \"step.completed\") {\n const usage = record(data.usage);\n const total = (value: unknown) =>\n typeof value === \"number\" ? value : Number(record(value).total ?? 0);\n this.tokens += total(usage.inputTokens) + total(usage.outputTokens);\n }\n if (type === \"session.waiting\") this.state = this.inputs.size > 0 ? \"needs input\" : \"waiting\";\n if ([\"session.completed\", \"session.failed\"].includes(type)) this.state = type.slice(8);\n if (\n type.endsWith(\".failed\") ||\n type === \"turn.cancelled\" ||\n type.startsWith(\"compaction.\") ||\n type.startsWith(\"authorization.\") ||\n type.startsWith(\"subagent.\")\n ) {\n this.put({\n id: `event:${event.meta?.id ?? this.cursor}`,\n kind: type.endsWith(\".failed\") ? \"error\" : \"status\",\n title: type,\n text: string(\n data.message ?? data.output ?? data.authorization ?? data.subagentName ?? data.name ?? \"\",\n ),\n });\n }\n }\n\n private tool(tool: ToolCall) {\n this.tools.set(tool.callId, tool);\n const output = tool.error ?? tool.output;\n this.put({\n id: `tool:${tool.callId}`,\n kind: \"tool\",\n title: tool.name,\n tool,\n text: `Input\\n\\`\\`\\`json\\n${tool.inputText}\\n\\`\\`\\`${output === undefined ? \"\" : `\\n\\nOutput\\n\\`\\`\\`\\n${string(output)}\\n\\`\\`\\``}`,\n });\n }\n}\n"],"mappings":";;;AAkBA,SAAS,OAAO,OAAyC;CACvD,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK,IACrE,QACD,CAAC;AACP;AACA,SAAS,OAAO,OAAwB;CACtC,OAAO,OAAO,UAAU,WAAW,QAAS,KAAK,UAAU,OAAO,MAAM,CAAC,KAAK;AAChF;AACA,SAAS,WAAW,MAAuB;CACzC,IAAI;EACF,OAAO,KAAK,MAAM,IAAI;CACxB,QAAQ;EACN;CACF;AACF;AACA,SAAS,QAAQ,MAAgB;CAC/B,OAAO;EAAC;EAAa;EAAU;EAAa;CAAU,CAAC,CAAC,SAAS,KAAK,KAAK;AAC7E;;AAGA,IAAa,aAAb,MAAwB;CAUZ;CACA;CAVV,SAA4B,CAAC;CAC7B,yBAAS,IAAI,IAA0B;CACvC,SAAS;CACT,QAAQ;CACR;CACA,SAAS;CACT,uBAAe,IAAI,IAAY;CAC/B,wBAAgB,IAAI,IAAsB;CAC1C,YACE,gBACA,oBACA;EAFQ,KAAA,iBAAA;EACA,KAAA,qBAAA;CACP;CAEH,WAA+B;EAC7B,OAAO,yBAAyB,MAAM;GACpC,QAAQ,KAAK;GACb,QAAQ,CAAC,GAAG,KAAK,OAAO,OAAO,CAAC;GAChC,QAAQ,KAAK;GACb,OAAO,KAAK;GACZ,QAAQ,KAAK;GACb,QAAQ,KAAK;EACf,CAAC;CACH;CAEA,QAAQ,OAAiC;EACvC,MAAM,WAAW,yBAAyB,MAAM,KAAK;EACrD,KAAK,SAAS,SAAS,OAAO,KAAK,WAAW,EAAE,GAAG,MAAM,EAAE;EAC3D,MAAM,YAAY,KAAK,OAAO,MAC3B,UAA+D,MAAM,SAAS,MACjF;EACA,IACE,cAAc,KAAA,MACb,KAAK,mBAAmB,KAAA,KAAa,KAAK,uBAAuB,KAAA,IAClE;GACA,MAAM,OAAO,KAAK,kBAAkB,UAAU;GAC9C,MAAM,cAAc,KAAK,sBAAsB,UAAU;GACzD,MAAM,iBAAiB,KAAK,OAAO,QAAQ,SAAS;GACpD,IAAI,aAAa,QACf,KAAK,OAAO,kBAAkB;IAAE,GAAG;IAAW;IAAM,aAAa,CAAC,GAAG,WAAW;GAAE;QAC7E;IACL,MAAM,EAAE,aAAa,cAAc,GAAG,uBAAuB;IAC7D,KAAK,OAAO,kBAAkB;KAAE,GAAG;KAAoB;IAAK;GAC9D;EACF;EACA,KAAK,SAAS,IAAI,IAAI,SAAS,OAAO,KAAK,YAAY,CAAC,QAAQ,WAAW,OAAO,CAAC,CAAC;EACpF,KAAK,SAAS,SAAS;EACvB,KAAK,QAAQ,SAAS;EACtB,KAAK,SAAS,SAAS;EACvB,KAAK,SAAS,SAAS;EACvB,KAAK,KAAK,MAAM;EAChB,KAAK,QAAQ,IAAI,IACf,KAAK,OAAO,SAAS,UACnB,MAAM,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,MAAM,IAAI,CAAU,IAAI,CAAC,CAC7D,CACF;EACA,KAAK,iBAAiB,KAAA;EACtB,KAAK,qBAAqB,KAAA;CAC5B;CAEA,IAAI,OAAwB;EAC1B,MAAM,QAAQ,KAAK,OAAO,WAAW,SAAS,KAAK,OAAO,MAAM,EAAE;EAClE,IAAI,QAAQ,GAAG,KAAK,OAAO,KAAK,KAAK;OAChC,KAAK,OAAO,SAAS;CAC5B;CAEA,cAAc,IAAY,YAAwB;EAChD,KAAK,MAAM,SAAS,WAAW,QAAQ,KAAK,IAAI;GAAE,GAAG;GAAO,IAAI,WAAW,GAAG,GAAG,MAAM;EAAK,CAAC;CAC/F;CAEA,eAAe,SAA4D;EACzE,MAAM,UAAU,QAAQ,SAAS,EAAE,IAAI,iBACrC,WAAW,OAAO,KAAK,WAAW;GAAE,GAAG;GAAO,IAAI,WAAW,GAAG,GAAG,MAAM;EAAK,EAAE,CAClF;EACA,MAAM,MAAM,IAAI,IAAI,QAAQ,KAAK,UAAU,MAAM,EAAE,CAAC;EACpD,KAAK,SAAS,CAAC,GAAG,SAAS,GAAG,KAAK,OAAO,QAAQ,UAAU,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC;CACjF;CAEA,OAAO,OAAoB;EACzB,KAAK;EACL,IAAI,MAAM,MAAM,OAAO,KAAA,GAAW;GAChC,IAAI,KAAK,KAAK,IAAI,MAAM,KAAK,EAAE,GAAG;GAClC,KAAK,KAAK,IAAI,MAAM,KAAK,EAAE;EAC7B;EACA,MAAM,EAAE,MAAM,SAAS;EACvB,MAAM,aAAa,GAAG,KAAK,OAAO,GAAG,KAAK,UAAU,GAAG,KAAK;EAC5D,IAAI,SAAS,gBAAgB;GAC3B,KAAK,SAAS,OAAO,KAAK,MAAM;GAChC,KAAK,QAAQ;EACf;EACA,IAAI,SAAS,oBAAoB;GAC/B,MAAM,cAAc,KAAK,sBAAsB,eAAe,KAAK,KAAK;GACxE,MAAM,YAAY,MAAM,QAAQ,KAAK,KAAK,IACtC,KAAK,MACF,QAAQ,SAAS,OAAO,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,CAC9C,KAAK,SAAS,OAAO,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CACxC,KAAK,IAAI,IACZ,KAAA;GACJ,KAAK,IAAI;IACP,IAAI,QAAQ,MAAM,MAAM,MAAM,KAAK;IACnC,MAAM;IACN,OAAO;IACP,MACE,KAAK,mBAAmB,YAAY,SAAU,aAAa,KAAM,OAAO,KAAK,OAAO;IACtF,GAAI,YAAY,SAAS,EAAE,aAAa,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC;GAChE,CAAC;GACD,KAAK,iBAAiB,KAAA;GACtB,KAAK,qBAAqB,KAAA;EAC5B;EACA,IAAI,SAAS,sBAAsB,SAAS,qBAC1C,KAAK,IAAI;GACP,IAAI,WAAW;GACf,MAAM;GACN,OAAO;GACP,MAAM,OAAO,KAAK,OAAO;EAC3B,CAAC;EACH,IAAI,SAAS,oBACX,KAAK,IAAI;GACP,IAAI,UAAU;GACd,MAAM;GACN,OAAO;GACP,MAAM,eAAe,OAAO,KAAK,MAAM,EAAE;EAC3C,CAAC;EACH,IAAI,SAAS,wBAAwB,SAAS,uBAC5C,KAAK,IAAI;GACP,IAAI,aAAa;GACjB,MAAM;GACN,OAAO;GACP,MAAM,OAAO,KAAK,SAAS;EAC7B,CAAC;EACH,IAAI,SAAS,uBAAuB,MAAM,QAAQ,KAAK,OAAO,GAC5D,KAAK,MAAM,QAAQ,KAAK,SAAS;GAC/B,MAAM,SAAS,OAAO,IAAI;GAC1B,MAAM,SAAS,OAAO,OAAO,MAAM;GACnC,MAAM,WAAW,KAAK,MAAM,IAAI,MAAM;GACtC,KAAK,KAAK;IACR,GAAG;IACH;IACA,OAAO,OAAO;IACd,WAAW,OAAO,OAAO,KAAK;IAC9B,MAAM,OAAO,OAAO,YAAY,OAAO,QAAQ,OAAO,IAAI;IAC1D,OAAO,UAAU,UAAU,oBAAoB,YAAa,UAAU,SAAS;GACjF,CAAC;EACH;EACF,IAAI,SAAS,yBAAyB;GACpC,MAAM,KAAK,OAAO,KAAK,MAAM;GAC7B,MAAM,WAAW,KAAK,MAAM,IAAI,EAAE;GAClC,MAAM,SAAS,KAAK;GACpB,MAAM,QAAQ,OAAO,KAAK,cAAc;GACxC,KACG,CAAC,YAAY,SAAS,UAAU,uBAChC,WAAW,KAAK,WAAW,UAAU,UAAU,SAChD;IACA,MAAM,aAAa,WAAW,IAAI,KAAM,UAAU,aAAa,MAAO;IACtE,KAAK,KAAK;KACR,QAAQ;KACR,OAAO,WAAW,SAAS;KAC3B;KACA,MAAM,OAAO,KAAK,QAAQ;KAC1B,OAAO;IACT,CAAC;GACH;EACF;EACA,IAAI,SAAS,mBAAmB,SAAS,kBAAkB;GACzD,MAAM,SAAS,OAAO,KAAK,MAAM;GACjC,MAAM,KAAK,OAAO,OAAO,MAAM;GAC/B,MAAM,WAAW,KAAK,MAAM,IAAI,EAAE;GAClC,IAAI,SAAS,oBAAoB,CAAC,YAAY,CAAC,QAAQ,QAAQ,GAC7D,KAAK,KAAK;IACR,GAAG;IACH,QAAQ;IACR,OAAO,UAAU;IACjB,WAAW,UAAU,aAAa;IAClC,MAAM,UAAU,QAAQ,OAAO,OAAO,YAAY,OAAO,IAAI;IAC7D,QAAQ,YAAY,SAAS,OAAO,SAAS;IAC7C,OAAO,KAAK;IACZ,OACE,SAAS,mBACL,YACA,KAAK,WAAW,aACd,aACA,KAAK,WAAW,YAAY,KAAK,SAAS,OACxC,WACA;GACZ,CAAC;EACL;EACA,IAAI,SAAS,oBAAoB,SAAS,iBAAiB,SAAS,kBAC7D;QAAA,MAAM,QAAQ,KAAK,MAAM,OAAO,GACnC,IAAI,CAAC,QAAQ,IAAI,GACf,KAAK,KAAK;IACR,GAAG;IACH,OAAO,SAAS,mBAAmB,cAAc;IACjD,OAAO,KAAK;GACd,CAAC;EAAA;EAEP,IAAI,SAAS,mBAAmB;GAC9B,KAAK,MAAM,WAAW,mBAAmB,MAAM,CAAC,CAAC,MAAM,KAAK,QAAQ,GAClE,KAAK,OAAO,IAAI,QAAQ,WAAW,OAAO;GAC5C,KAAK,QAAQ;EACf;EACA,IAAI,SAAS,oBAAoB,MAAM,QAAQ,KAAK,WAAW,GAC7D,KAAK,MAAM,cAAc,KAAK,aAC5B,KAAK,OAAO,OAAO,OAAO,OAAO,UAAU,CAAC,CAAC,SAAS,CAAC;EAC3D,IAAI,SAAS,kBAAkB;GAC7B,MAAM,QAAQ,OAAO,KAAK,KAAK;GAC/B,MAAM,SAAS,UACb,OAAO,UAAU,WAAW,QAAQ,OAAO,OAAO,KAAK,CAAC,CAAC,SAAS,CAAC;GACrE,KAAK,UAAU,MAAM,MAAM,WAAW,IAAI,MAAM,MAAM,YAAY;EACpE;EACA,IAAI,SAAS,mBAAmB,KAAK,QAAQ,KAAK,OAAO,OAAO,IAAI,gBAAgB;EACpF,IAAI,CAAC,qBAAqB,gBAAgB,CAAC,CAAC,SAAS,IAAI,GAAG,KAAK,QAAQ,KAAK,MAAM,CAAC;EACrF,IACE,KAAK,SAAS,SAAS,KACvB,SAAS,oBACT,KAAK,WAAW,aAAa,KAC7B,KAAK,WAAW,gBAAgB,KAChC,KAAK,WAAW,WAAW,GAE3B,KAAK,IAAI;GACP,IAAI,SAAS,MAAM,MAAM,MAAM,KAAK;GACpC,MAAM,KAAK,SAAS,SAAS,IAAI,UAAU;GAC3C,OAAO;GACP,MAAM,OACJ,KAAK,WAAW,KAAK,UAAU,KAAK,iBAAiB,KAAK,gBAAgB,KAAK,QAAQ,EACzF;EACF,CAAC;CAEL;CAEA,KAAa,MAAgB;EAC3B,KAAK,MAAM,IAAI,KAAK,QAAQ,IAAI;EAChC,MAAM,SAAS,KAAK,SAAS,KAAK;EAClC,KAAK,IAAI;GACP,IAAI,QAAQ,KAAK;GACjB,MAAM;GACN,OAAO,KAAK;GACZ;GACA,MAAM,sBAAsB,KAAK,UAAU,UAAU,WAAW,KAAA,IAAY,KAAK,uBAAuB,OAAO,MAAM,EAAE;EACzH,CAAC;CACH;AACF"}
1
+ {"version":3,"file":"client-transcript.mjs","names":[],"sources":["../src/client-transcript.ts"],"sourcesContent":["import { receivedImages, type ImageAttachment } from \"./image-input\";\nimport type { StreamEvent } from \"./client-events\";\nimport {\n inputRequestSchema,\n transcriptSnapshotSchema,\n type InputRequest,\n type ToolCall,\n type TranscriptBlock,\n type TranscriptSnapshot,\n} from \"./schema/transcript\";\n\nexport type {\n InputRequest,\n ToolCall,\n TranscriptBlock,\n TranscriptSnapshot,\n} from \"./schema/transcript\";\n\nfunction record(value: unknown): Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\nfunction string(value: unknown): string {\n return typeof value === \"string\" ? value : (JSON.stringify(value, null, 2) ?? \"\");\n}\nfunction parseInput(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\nfunction settled(tool: ToolCall) {\n return [\"completed\", \"failed\", \"cancelled\", \"rejected\"].includes(tool.state);\n}\n\n/** Mutable client-side projection of snapshot and live Factory transcript events. */\nexport class Transcript {\n blocks: TranscriptBlock[] = [];\n inputs = new Map<string, InputRequest>();\n cursor = 0;\n state = \"connecting\";\n turnId?: string;\n tokens = 0;\n private seen = new Set<string>();\n private tools = new Map<string, ToolCall>();\n constructor(\n private initialMessage?: string,\n private initialAttachments?: readonly ImageAttachment[],\n ) {}\n\n snapshot(): TranscriptSnapshot {\n return transcriptSnapshotSchema.parse({\n blocks: this.blocks,\n inputs: [...this.inputs.values()],\n cursor: this.cursor,\n state: this.state,\n turnId: this.turnId,\n tokens: this.tokens,\n });\n }\n\n hydrate(value: TranscriptSnapshot): void {\n const snapshot = transcriptSnapshotSchema.parse(value);\n this.blocks = snapshot.blocks.map((block) => ({ ...block }));\n const firstUser = this.blocks.find(\n (block): block is Extract<TranscriptBlock, { kind: \"user\" }> => block.kind === \"user\",\n );\n if (\n firstUser !== undefined &&\n (this.initialMessage !== undefined || this.initialAttachments !== undefined)\n ) {\n const text = this.initialMessage ?? firstUser.text;\n const attachments = this.initialAttachments ?? firstUser.attachments;\n const firstUserIndex = this.blocks.indexOf(firstUser);\n if (attachments?.length) {\n this.blocks[firstUserIndex] = { ...firstUser, text, attachments: [...attachments] };\n } else {\n const { attachments: _attachments, ...withoutAttachments } = firstUser;\n this.blocks[firstUserIndex] = { ...withoutAttachments, text };\n }\n }\n this.inputs = new Map(snapshot.inputs.map((request) => [request.requestId, request]));\n this.cursor = snapshot.cursor;\n this.state = snapshot.state;\n this.turnId = snapshot.turnId;\n this.tokens = snapshot.tokens;\n this.seen.clear();\n this.tools = new Map(\n this.blocks.flatMap((block) =>\n block.tool ? [[block.tool.callId, block.tool] as const] : [],\n ),\n );\n this.initialMessage = undefined;\n this.initialAttachments = undefined;\n }\n\n put(block: TranscriptBlock) {\n const index = this.blocks.findIndex((item) => item.id === block.id);\n if (index < 0) this.blocks.push(block);\n else this.blocks[index] = block;\n }\n\n appendHistory(id: string, transcript: Transcript) {\n for (const block of transcript.blocks) this.put({ ...block, id: `history:${id}:${block.id}` });\n }\n\n prependHistory(entries: readonly { id: string; transcript: Transcript }[]) {\n const history = entries.flatMap(({ id, transcript }) =>\n transcript.blocks.map((block) => ({ ...block, id: `history:${id}:${block.id}` })),\n );\n const ids = new Set(history.map((block) => block.id));\n this.blocks = [...history, ...this.blocks.filter((block) => !ids.has(block.id))];\n }\n\n accept(event: StreamEvent) {\n this.cursor++;\n if (event.meta?.id !== undefined) {\n if (this.seen.has(event.meta.id)) return;\n this.seen.add(event.meta.id);\n }\n const { type, data } = event;\n const coordinate = `${data.turnId}:${data.stepIndex}:${data.sequence}`;\n if (type === \"turn.started\") {\n this.turnId = string(data.turnId);\n this.state = \"running\";\n }\n if (type === \"message.received\") {\n const attachments = this.initialAttachments ?? receivedImages(data.parts);\n const partsText = Array.isArray(data.parts)\n ? data.parts\n .filter((part) => record(part).type === \"text\")\n .map((part) => string(record(part).text))\n .join(\"\\n\")\n : undefined;\n this.put({\n id: `user:${event.meta?.id ?? this.cursor}`,\n kind: \"user\",\n title: \"You\",\n text:\n this.initialMessage ?? (attachments.length ? (partsText ?? \"\") : string(data.message)),\n ...(attachments.length ? { attachments: [...attachments] } : {}),\n });\n this.initialMessage = undefined;\n this.initialAttachments = undefined;\n }\n if (type === \"message.appended\" || type === \"message.completed\")\n this.put({\n id: `message:${coordinate}`,\n kind: \"assistant\",\n title: \"Assistant\",\n text: string(data.message),\n });\n if (type === \"result.completed\")\n this.put({\n id: `result:${coordinate}`,\n kind: \"assistant\",\n title: \"Result\",\n text: `\\`\\`\\`json\\n${string(data.result)}\\n\\`\\`\\``,\n });\n if (type === \"reasoning.appended\" || type === \"reasoning.completed\")\n this.put({\n id: `reasoning:${coordinate}`,\n kind: \"reasoning\",\n title: \"Reasoning\",\n text: string(data.reasoning),\n });\n if (type === \"actions.requested\" && Array.isArray(data.actions))\n for (const item of data.actions) {\n const action = record(item);\n const callId = string(action.callId);\n const previous = this.tools.get(callId);\n this.tool({\n ...previous,\n callId,\n input: action.input,\n inputText: string(action.input),\n name: string(action.toolName ?? action.name ?? action.kind),\n state: previous?.state === \"input-streaming\" ? \"running\" : (previous?.state ?? \"running\"),\n });\n }\n if (type === \"action.input.appended\") {\n const id = string(data.callId);\n const previous = this.tools.get(id);\n const offset = data.inputTextOffset;\n const delta = string(data.inputTextDelta);\n if (\n (!previous || previous.state === \"input-streaming\") &&\n (offset === 0 || offset === previous?.inputText.length)\n ) {\n const inputText = (offset === 0 ? \"\" : (previous?.inputText ?? \"\")) + delta;\n this.tool({\n callId: id,\n input: parseInput(inputText),\n inputText,\n name: string(data.toolName),\n state: \"input-streaming\",\n });\n }\n }\n if (type === \"action.result\" || type === \"action.partial\") {\n const result = record(data.result);\n const id = string(result.callId);\n const previous = this.tools.get(id);\n if (type !== \"action.partial\" || !previous || !settled(previous))\n this.tool({\n ...previous,\n callId: id,\n input: previous?.input,\n inputText: previous?.inputText ?? \"\",\n name: previous?.name ?? string(result.toolName ?? result.kind),\n output: \"output\" in result ? result.output : result,\n error: data.error,\n state:\n type === \"action.partial\"\n ? \"running\"\n : data.status === \"rejected\"\n ? \"rejected\"\n : data.status === \"failed\" || data.error != null\n ? \"failed\"\n : \"completed\",\n });\n }\n if (type === \"turn.cancelled\" || type === \"turn.failed\" || type === \"session.failed\")\n for (const tool of this.tools.values()) {\n if (!settled(tool))\n this.tool({\n ...tool,\n state: type === \"turn.cancelled\" ? \"cancelled\" : \"failed\",\n error: data.message,\n });\n }\n if (type === \"input.requested\") {\n for (const request of inputRequestSchema.array().parse(data.requests))\n this.inputs.set(request.requestId, request);\n this.state = \"needs input\";\n }\n if (type === \"input.resolved\" && Array.isArray(data.resolutions))\n for (const resolution of data.resolutions)\n this.inputs.delete(string(record(resolution).requestId));\n if (type === \"step.completed\") {\n const usage = record(data.usage);\n const total = (value: unknown) =>\n typeof value === \"number\" ? value : Number(record(value).total ?? 0);\n this.tokens += total(usage.inputTokens) + total(usage.outputTokens);\n }\n if (\n type === \"session.waiting\" ||\n ([\"turn.completed\", \"turn.failed\", \"turn.cancelled\"].includes(type) &&\n (this.turnId === undefined || data.turnId === this.turnId))\n )\n this.state = this.inputs.size > 0 ? \"needs input\" : \"waiting\";\n if ([\"session.completed\", \"session.failed\"].includes(type)) this.state = type.slice(8);\n if (\n type.endsWith(\".failed\") ||\n type === \"turn.cancelled\" ||\n type.startsWith(\"compaction.\") ||\n type.startsWith(\"authorization.\") ||\n type.startsWith(\"subagent.\")\n ) {\n this.put({\n id: `event:${event.meta?.id ?? this.cursor}`,\n kind: type.endsWith(\".failed\") ? \"error\" : \"status\",\n title: type,\n text: string(\n data.message ?? data.output ?? data.authorization ?? data.subagentName ?? data.name ?? \"\",\n ),\n });\n }\n }\n\n private tool(tool: ToolCall) {\n this.tools.set(tool.callId, tool);\n const output = tool.error ?? tool.output;\n this.put({\n id: `tool:${tool.callId}`,\n kind: \"tool\",\n title: tool.name,\n tool,\n text: `Input\\n\\`\\`\\`json\\n${tool.inputText}\\n\\`\\`\\`${output === undefined ? \"\" : `\\n\\nOutput\\n\\`\\`\\`\\n${string(output)}\\n\\`\\`\\``}`,\n });\n }\n}\n"],"mappings":"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"}
package/dist/client.d.mts CHANGED
@@ -1,5 +1,10 @@
1
+ import { InboxActivity, InboxActivityItem, inboxActivityItemSchema, inboxActivitySchema } from "./inbox-activity.mjs";
2
+ import { AgentModelConfig, ModelSettings, UpdateModelDefaults, agentModelConfigSchema, modelSettingsSchema, updateModelDefaultsSchema } from "./model-settings.mjs";
3
+ import { SessionPreview, SessionPreviews, sessionPreviewSchema, sessionPreviewsSchema } from "./session-previews.mjs";
4
+ import { SessionReview, SessionReviewCheck, SessionReviewIssue, SessionReviewScreenshot, sessionReviewCheckSchema, sessionReviewIssueSchema, sessionReviewSchema, sessionReviewScreenshotSchema } from "./session-review.mjs";
5
+ import { WorkspaceFileEntry, WorkspaceFiles, WorkspaceFilesRequest, workspaceFileContentSchema, workspaceFileEntrySchema, workspaceFilesRequestSchema, workspaceFilesSchema, workspacePathSchema } from "./workspace-files.mjs";
1
6
  import { SignalSource } from "./schema/signal.mjs";
2
- import { TaskId } from "./schema/id.mjs";
7
+ import { RepositoryId, TaskId } from "./schema/id.mjs";
3
8
  import { RepositorySlug } from "./schema/repository.mjs";
4
9
  import { Task } from "./schema/task.mjs";
5
10
  import { MaybePromise } from "./schema/common.mjs";
@@ -9,7 +14,6 @@ import { Change } from "./schema/change.mjs";
9
14
  import { InputRequest, ToolCall, TranscriptBlock, TranscriptSnapshot, inputRequestSchema, toolCallSchema, transcriptBlockSchema, transcriptSnapshotSchema } from "./schema/transcript.mjs";
10
15
  import { ApprovalListOptions, ApprovalPage, ApprovalView } from "./approval-contracts.mjs";
11
16
  import { WorkspaceDiff, WorkspaceDiffFile, workspaceDiffFileSchema, workspaceDiffSchema } from "./workspace-diff.mjs";
12
- import "./signals.mjs";
13
17
  import { IntakeView, describeIntake } from "./intake-contracts.mjs";
14
18
  import { TaskGraphView } from "./task-graph-view.mjs";
15
19
  import { StreamEvent, readEvents, streamEventSchema } from "./client-events.mjs";
@@ -24,7 +28,7 @@ interface SessionListOptions {
24
28
  readonly scope?: "all" | "interactive";
25
29
  readonly detail?: "full" | "summary";
26
30
  readonly limit?: number;
27
- readonly cursor?: AgentSessionId;
31
+ readonly cursor?: string;
28
32
  readonly query?: string;
29
33
  readonly repository?: RepositorySlug;
30
34
  readonly agent?: string;
@@ -42,8 +46,17 @@ declare class ApiError extends Error {
42
46
  }
43
47
  /** Connection and request customization for {@link FactoryClient}. */
44
48
  interface FactoryClientOptions {
49
+ /**
50
+ * Canonical Factory origin. It must be HTTPS, except for HTTP loopback development, and cannot
51
+ * contain credentials, a path, query parameters, or a fragment.
52
+ */
45
53
  readonly url: string;
54
+ /**
55
+ * Headers resolved immediately before every request, allowing short-lived authentication to be
56
+ * refreshed. Factory always sets `content-type` to `application/json` afterward.
57
+ */
46
58
  readonly headers?: () => MaybePromise<HeadersInit>;
59
+ /** Fetch implementation used for every request; defaults to `globalThis.fetch`. */
47
60
  readonly fetch?: typeof globalThis.fetch;
48
61
  }
49
62
  /** Identifies an uploaded image and optionally controls cancellation of its download. */
@@ -56,6 +69,18 @@ interface GetSessionOptions {
56
69
  readonly id: AgentSessionId;
57
70
  readonly detail?: "full" | "summary";
58
71
  }
72
+ /** Selects the observed execution whose review evidence should be read. */
73
+ interface SessionReviewOptions {
74
+ readonly sessionId: AgentSessionId;
75
+ readonly executionId: string | null;
76
+ readonly signal?: AbortSignal;
77
+ }
78
+ /** Selects the observed execution whose preview links and instructions should be read. */
79
+ interface SessionPreviewsOptions {
80
+ readonly sessionId: AgentSessionId;
81
+ readonly executionId: string | null;
82
+ readonly signal?: AbortSignal;
83
+ }
59
84
  /** Identifies the operator session whose canonical task graph should be read. */
60
85
  interface GetSessionGraphOptions {
61
86
  readonly id: AgentSessionId;
@@ -68,6 +93,12 @@ interface GraphTranscriptOptions {
68
93
  readonly executionId: string;
69
94
  readonly signal?: AbortSignal;
70
95
  }
96
+ /** Identifies a file or directory at an observed execution and optional immutable revision. */
97
+ interface WorkspaceFilesOptions extends WorkspaceFilesRequest {
98
+ readonly sessionId: AgentSessionId;
99
+ readonly executionId: string | null;
100
+ readonly signal?: AbortSignal;
101
+ }
71
102
  /** Identifies the execution whose committed workspace should be compared. */
72
103
  interface WorkspaceDiffOptions {
73
104
  readonly sessionId: AgentSessionId;
@@ -90,10 +121,24 @@ interface SessionEventStreamRequest {
90
121
  readonly taskId?: TaskId;
91
122
  readonly signal: AbortSignal;
92
123
  }
93
- /** Browser-safe typed client for the public Factory HTTP API. */
124
+ /**
125
+ * Browser-safe typed client for the public Factory HTTP API.
126
+ *
127
+ * @remarks
128
+ * Requests use same-origin credentials, bypass HTTP caches, and refuse redirects so authentication
129
+ * redirects cannot be mistaken for API responses. When no caller signal is available, requests
130
+ * time out after 30 seconds. Non-success responses throw {@link ApiError}; successful JSON bodies
131
+ * are still validated against their public schemas before being returned.
132
+ */
94
133
  declare class FactoryClient {
95
134
  private readonly options;
96
135
  private readonly origin;
136
+ /**
137
+ * Creates a client for one canonical Factory origin without performing a request.
138
+ *
139
+ * @param options - Factory origin plus optional per-request headers and fetch implementation.
140
+ * @throws When `options.url` is not an HTTPS origin or an HTTP loopback origin.
141
+ */
97
142
  constructor(options: FactoryClientOptions);
98
143
  private response;
99
144
  /** Read authorized intake and pre-task triage failures. */
@@ -183,15 +228,36 @@ declare class FactoryClient {
183
228
  listChanges(repository?: RepositorySlug): Promise<readonly Change[]>;
184
229
  /** Lists canonical Tasks exposed by the operator API. */
185
230
  listTasks(): Promise<readonly Task[]>;
186
- /** Lists sessions matching the requested operator scope. */
231
+ /**
232
+ * Lists sessions matching the requested operator scope without pagination metadata.
233
+ *
234
+ * @param options - Optional scope and detail projection; both use their server defaults when omitted.
235
+ * @returns The first matching page's sessions. Use {@link getSessionPage} to follow cursors.
236
+ */
187
237
  listSessions(options?: Pick<SessionListOptions, "scope" | "detail">): Promise<readonly SessionView[]>;
188
- /** Reads a filtered, cursor-paginated page of sessions. */
238
+ /**
239
+ * Reads a filtered, cursor-paginated page of sessions.
240
+ *
241
+ * @param options - Filters, cursor, projection detail, and page limit sent to the API.
242
+ * @returns The validated page, including its continuation cursor and optional total count.
243
+ */
189
244
  getSessionPage(options?: SessionListOptions): Promise<SessionPage>;
245
+ /** Reads application-owned external work requiring operator attention. */
246
+ getInboxActivity(): Promise<InboxActivity>;
247
+ /** Reads application model choices and optional repository defaults. */
248
+ getModelSettings(repository?: RepositorySlug): Promise<ModelSettings>;
249
+ /** Saves repository defaults only when their observed revision still matches. */
250
+ updateModelDefaults(input: UpdateModelDefaults): Promise<ModelSettings>;
190
251
  /** Counts sessions that currently require operator attention. */
191
252
  getInboxCount(): Promise<number>;
192
253
  /** Reads a summary batch for the provided session IDs. */
193
254
  getSessionBatch(ids: readonly AgentSessionId[]): Promise<readonly SessionView[]>;
194
- /** Reads one operator session. */
255
+ /**
256
+ * Reads one operator session.
257
+ *
258
+ * @param options - Stable session ID and optional summary or full projection.
259
+ * @returns The current validated session view; it is a snapshot and does not follow live events.
260
+ */
195
261
  getSession(options: GetSessionOptions): Promise<SessionView>;
196
262
  /** Reads the canonical task graph projected for one session. */
197
263
  getSessionGraph(options: GetSessionGraphOptions): Promise<TaskGraphView>;
@@ -199,17 +265,60 @@ declare class FactoryClient {
199
265
  getGraphTranscript(options: GraphTranscriptOptions): Promise<TranscriptSnapshot>;
200
266
  /** Refreshes a session summary and reloads its history when the active execution changes. */
201
267
  refreshSession(previous: SessionView): Promise<SessionView>;
268
+ /** Reads application-owned previews without starting an agent, deployment, or server. */
269
+ getSessionPreviews(options: SessionPreviewsOptions): Promise<SessionPreviews>;
270
+ /** Reads recorded checks, screenshots, and issues through the application's review reader. */
271
+ getSessionReview(options: SessionReviewOptions): Promise<SessionReview>;
272
+ /** Reads a directory or complete file through the factory's configured workspace adapter. */
273
+ getWorkspaceFiles(options: WorkspaceFilesOptions): Promise<WorkspaceFiles>;
202
274
  /** Reads the committed workspace comparison for one observed execution. */
203
275
  getWorkspaceDiff(options: WorkspaceDiffOptions): Promise<WorkspaceDiff>;
204
- /** Creates or recovers an idempotent conversational session. */
276
+ /**
277
+ * Creates or recovers an idempotent conversational session.
278
+ *
279
+ * @remarks
280
+ * Retain `input.operationId` unchanged across ambiguous failures. Reusing it with identical input
281
+ * returns the original session; reusing it with different input is a conflict. The returned view
282
+ * means admission and any initial dispatch attempt finished, not that the agent's work completed.
283
+ *
284
+ * @param input - Agent, initial content, optional repository/change, and client idempotency key.
285
+ * @returns The admitted or recovered session snapshot.
286
+ */
205
287
  createSession(input: CreateSessionRequest): Promise<SessionView>;
206
288
  /** Creates or recovers idempotent workflow work through a specialist signal. */
207
289
  createSignal(input: CreateSessionRequest): Promise<SessionView>;
208
- /** Sends a message to an existing session. */
290
+ /** Starts a deepsec security scan of a repository, or returns its already-active scan. */
291
+ runSecurityScan(repositoryId: RepositoryId): Promise<{
292
+ taskId: TaskId;
293
+ reused: boolean;
294
+ }>;
295
+ /**
296
+ * Sends a message to an existing session using optimistic execution matching.
297
+ *
298
+ * @remarks
299
+ * `input.executionId` must be the execution the caller observed, or `null` when none was active.
300
+ * A completed Task follow-up also requires an `operationId`, which must be retained for retries.
301
+ * Resolving means the API accepted the message; provider or follow-up work may still be running.
302
+ *
303
+ * @param id - Stable Factory session receiving the message.
304
+ * @param input - Message, observed execution, steering policy, attachments, and optional retry key.
305
+ * @returns Nothing after the API accepts the request.
306
+ */
209
307
  sendSessionMessage(id: AgentSessionId, input: SendSessionMessageRequest): Promise<void>;
210
- /** Submits responses to pending provider input requests. */
308
+ /**
309
+ * Submits responses to pending provider input requests.
310
+ *
311
+ * @param id - Stable Factory session whose provider requested input.
312
+ * @param input - Observed execution ID and one or more request-correlated responses.
313
+ * @returns Nothing after the API accepts the responses; stale execution IDs are rejected.
314
+ */
211
315
  submitSessionInput(id: AgentSessionId, input: SubmitSessionInputRequest): Promise<void>;
212
- /** Dispatches queued workflow work associated with a session. */
316
+ /**
317
+ * Attempts to dispatch queued workflow work associated with a session.
318
+ *
319
+ * @param id - Stable Factory session whose current work should be dispatched.
320
+ * @returns The refreshed session after the bounded dispatch attempt, which may still be queued.
321
+ */
213
322
  dispatchSession(id: AgentSessionId): Promise<SessionView>;
214
323
  /** Answers a workflow question associated with a session. */
215
324
  answerSessionQuestion(id: AgentSessionId, input: AnswerSessionQuestionRequest): Promise<SessionView>;
@@ -230,5 +339,5 @@ declare class FactoryClient {
230
339
  private controlSession;
231
340
  }
232
341
  //#endregion
233
- export { type AgentSession, type AgentSessionId, type AnswerSessionQuestionRequest, type ApiAgent, ApiError, type ApprovalListOptions, type ApprovalPage, type ApprovalView, type ControlSessionRequest, type CreateSessionRequest, type DirectAgentSession, type ExternalAgentSession, FactoryClient, FactoryClientOptions, type FollowSessionStreamOptions, GetImageOptions, GetSessionGraphOptions, GetSessionOptions, GraphTranscriptOptions, type ImageAttachment, type ImageId, type ImageUploadInput, type InputRequest, type IntakeView, MAX_IMAGES, MAX_IMAGE_BYTES, type PendingFollowUp, type RepositoryDetails, type RepositorySummary, type SendSessionMessageRequest, SessionEventStreamRequest, type SessionInputResponse, SessionListOptions, type SessionPage, type SessionStreamClient, SessionTranscriptRequest, type SessionView, type StreamEvent, type SubmitSessionInputRequest, type TaskAgentSession, type TaskGraphView, type ToolCall, Transcript, type TranscriptBlock, type TranscriptSnapshot, type WorkspaceDiff, type WorkspaceDiffFile, WorkspaceDiffOptions, agentSessionIdSchema, agentSessionSchema, answerSessionQuestionRequestSchema, apiAgentSchema, controlSessionRequestSchema, createSessionRequestSchema, describeIntake, followSessionStream, imageAttachmentSchema, imageAttachmentsSchema, imageIdSchema, inputRequestSchema, pendingFollowUpSchema, readEvents, repositoryDetailsSchema, repositorySummarySchema, sendSessionMessageRequestSchema, sessionInputResponseSchema, sessionPageSchema, sessionViewSchema, streamEventSchema, submitSessionInputRequestSchema, taskStates, toolCallSchema, transcriptBlockSchema, transcriptSnapshotSchema, workspaceDiffFileSchema, workspaceDiffSchema };
342
+ export { type AgentModelConfig, type AgentSession, type AgentSessionId, type AnswerSessionQuestionRequest, type ApiAgent, ApiError, type ApprovalListOptions, type ApprovalPage, type ApprovalView, type ControlSessionRequest, type CreateSessionRequest, type DirectAgentSession, type ExternalAgentSession, FactoryClient, FactoryClientOptions, type FollowSessionStreamOptions, GetImageOptions, GetSessionGraphOptions, GetSessionOptions, GraphTranscriptOptions, type ImageAttachment, type ImageId, type ImageUploadInput, type InboxActivity, type InboxActivityItem, type InputRequest, type IntakeView, MAX_IMAGES, MAX_IMAGE_BYTES, type ModelSettings, type PendingFollowUp, type RepositoryDetails, type RepositorySummary, type SendSessionMessageRequest, SessionEventStreamRequest, type SessionInputResponse, SessionListOptions, type SessionPage, type SessionPreview, type SessionPreviews, SessionPreviewsOptions, type SessionReview, type SessionReviewCheck, type SessionReviewIssue, SessionReviewOptions, type SessionReviewScreenshot, type SessionStreamClient, SessionTranscriptRequest, type SessionView, type StreamEvent, type SubmitSessionInputRequest, type TaskAgentSession, type TaskGraphView, type ToolCall, Transcript, type TranscriptBlock, type TranscriptSnapshot, type UpdateModelDefaults, type WorkspaceDiff, type WorkspaceDiffFile, WorkspaceDiffOptions, type WorkspaceFileEntry, type WorkspaceFiles, WorkspaceFilesOptions, type WorkspaceFilesRequest, agentModelConfigSchema, agentSessionIdSchema, agentSessionSchema, answerSessionQuestionRequestSchema, apiAgentSchema, controlSessionRequestSchema, createSessionRequestSchema, describeIntake, followSessionStream, imageAttachmentSchema, imageAttachmentsSchema, imageIdSchema, inboxActivityItemSchema, inboxActivitySchema, inputRequestSchema, modelSettingsSchema, pendingFollowUpSchema, readEvents, repositoryDetailsSchema, repositorySummarySchema, sendSessionMessageRequestSchema, sessionInputResponseSchema, sessionPageSchema, sessionPreviewSchema, sessionPreviewsSchema, sessionReviewCheckSchema, sessionReviewIssueSchema, sessionReviewSchema, sessionReviewScreenshotSchema, sessionViewSchema, streamEventSchema, submitSessionInputRequestSchema, taskStates, toolCallSchema, transcriptBlockSchema, transcriptSnapshotSchema, updateModelDefaultsSchema, workspaceDiffFileSchema, workspaceDiffSchema, workspaceFileContentSchema, workspaceFileEntrySchema, workspaceFilesRequestSchema, workspaceFilesSchema, workspacePathSchema };
234
343
  //# sourceMappingURL=client.d.mts.map
package/dist/client.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { taskIdSchema } from "./schema/id.mjs";
1
2
  import { repositorySlugSchema } from "./schema/repository.mjs";
2
3
  import { taskSchema, taskStateSchema } from "./schema/task.mjs";
3
4
  import { readEvents, streamEventSchema } from "./client-events.mjs";
@@ -7,6 +8,11 @@ import { Transcript } from "./client-transcript.mjs";
7
8
  import { approvalPageSchema, approvalRequestSchema, approvalViewSchema } from "./approval-contracts.mjs";
8
9
  import { agentSessionIdSchema, agentSessionSchema } from "./schema/session.mjs";
9
10
  import { changeSchema } from "./schema/change.mjs";
11
+ import { inboxActivityItemSchema, inboxActivitySchema } from "./inbox-activity.mjs";
12
+ import { agentModelConfigSchema, modelSettingsSchema, updateModelDefaultsSchema } from "./model-settings.mjs";
13
+ import { sessionPreviewSchema, sessionPreviewsSchema } from "./session-previews.mjs";
14
+ import { sessionReviewCheckSchema, sessionReviewIssueSchema, sessionReviewSchema, sessionReviewScreenshotSchema } from "./session-review.mjs";
15
+ import { workspaceFileContentSchema, workspaceFileEntrySchema, workspaceFilesRequestSchema, workspaceFilesSchema, workspacePathSchema } from "./workspace-files.mjs";
10
16
  import { describeIntake, intakePageSchema, intakeViewSchema, retryIntakeSchema } from "./intake-contracts.mjs";
11
17
  import { answerSessionQuestionRequestSchema, apiAgentSchema, controlSessionRequestSchema, createSessionRequestSchema, pendingFollowUpSchema, repositoryDetailsSchema, repositorySummarySchema, sendSessionMessageRequestSchema, sessionInputResponseSchema, sessionPageSchema, sessionViewSchema, submitSessionInputRequestSchema } from "./api-contracts.mjs";
12
18
  import { workspaceDiffFileSchema, workspaceDiffSchema } from "./workspace-diff.mjs";
@@ -26,10 +32,24 @@ var ApiError = class extends Error {
26
32
  this.actor = actor;
27
33
  }
28
34
  };
29
- /** Browser-safe typed client for the public Factory HTTP API. */
35
+ /**
36
+ * Browser-safe typed client for the public Factory HTTP API.
37
+ *
38
+ * @remarks
39
+ * Requests use same-origin credentials, bypass HTTP caches, and refuse redirects so authentication
40
+ * redirects cannot be mistaken for API responses. When no caller signal is available, requests
41
+ * time out after 30 seconds. Non-success responses throw {@link ApiError}; successful JSON bodies
42
+ * are still validated against their public schemas before being returned.
43
+ */
30
44
  var FactoryClient = class {
31
45
  options;
32
46
  origin;
47
+ /**
48
+ * Creates a client for one canonical Factory origin without performing a request.
49
+ *
50
+ * @param options - Factory origin plus optional per-request headers and fetch implementation.
51
+ * @throws When `options.url` is not an HTTPS origin or an HTTP loopback origin.
52
+ */
33
53
  constructor(options) {
34
54
  this.options = options;
35
55
  const url = new URL(options.url);
@@ -134,15 +154,38 @@ var FactoryClient = class {
134
154
  async listTasks() {
135
155
  return z.strictObject({ tasks: z.array(taskSchema).readonly() }).parse(await (await this.response("tasks")).json()).tasks;
136
156
  }
137
- /** Lists sessions matching the requested operator scope. */
157
+ /**
158
+ * Lists sessions matching the requested operator scope without pagination metadata.
159
+ *
160
+ * @param options - Optional scope and detail projection; both use their server defaults when omitted.
161
+ * @returns The first matching page's sessions. Use {@link getSessionPage} to follow cursors.
162
+ */
138
163
  async listSessions(options = {}) {
139
164
  return (await this.getSessionPage(options)).sessions;
140
165
  }
141
- /** Reads a filtered, cursor-paginated page of sessions. */
166
+ /**
167
+ * Reads a filtered, cursor-paginated page of sessions.
168
+ *
169
+ * @param options - Filters, cursor, projection detail, and page limit sent to the API.
170
+ * @returns The validated page, including its continuation cursor and optional total count.
171
+ */
142
172
  async getSessionPage(options = {}) {
143
173
  const query = new URLSearchParams(Object.entries(options).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])).toString();
144
174
  return sessionPageSchema.parse(await (await this.response(`sessions${query ? `?${query}` : ""}`)).json());
145
175
  }
176
+ /** Reads application-owned external work requiring operator attention. */
177
+ async getInboxActivity() {
178
+ return inboxActivitySchema.parse(await (await this.response("inbox-activity")).json());
179
+ }
180
+ /** Reads application model choices and optional repository defaults. */
181
+ async getModelSettings(repository) {
182
+ const query = repository ? `?${new URLSearchParams({ repository })}` : "";
183
+ return modelSettingsSchema.parse(await (await this.response(`models${query}`)).json());
184
+ }
185
+ /** Saves repository defaults only when their observed revision still matches. */
186
+ async updateModelDefaults(input) {
187
+ return modelSettingsSchema.parse(await (await this.response("models", updateModelDefaultsSchema.parse(input))).json());
188
+ }
146
189
  /** Counts sessions that currently require operator attention. */
147
190
  async getInboxCount() {
148
191
  return z.object({ totalCount: z.number().int().nonnegative() }).parse(await (await this.response("sessions?scope=all&detail=summary&attention=true&includeTotal=true&limit=1")).json()).totalCount;
@@ -156,7 +199,12 @@ var FactoryClient = class {
156
199
  });
157
200
  return z.object({ sessions: z.array(sessionViewSchema).readonly() }).parse(await (await this.response(`sessions?${query}`)).json()).sessions;
158
201
  }
159
- /** Reads one operator session. */
202
+ /**
203
+ * Reads one operator session.
204
+ *
205
+ * @param options - Stable session ID and optional summary or full projection.
206
+ * @returns The current validated session view; it is a snapshot and does not follow live events.
207
+ */
160
208
  async getSession(options) {
161
209
  return sessionViewSchema.parse(await (await this.response(`sessions/${encodeURIComponent(options.id)}${options.detail ? `?detail=${options.detail}` : ""}`)).json());
162
210
  }
@@ -184,11 +232,42 @@ var FactoryClient = class {
184
232
  history: previous.history
185
233
  };
186
234
  }
235
+ /** Reads application-owned previews without starting an agent, deployment, or server. */
236
+ async getSessionPreviews(options) {
237
+ return sessionPreviewsSchema.parse(await (await this.response(`sessions/${encodeURIComponent(options.sessionId)}/previews?${new URLSearchParams({ executionId: options.executionId ?? "" })}`, void 0, options.signal)).json());
238
+ }
239
+ /** Reads recorded checks, screenshots, and issues through the application's review reader. */
240
+ async getSessionReview(options) {
241
+ return sessionReviewSchema.parse(await (await this.response(`sessions/${encodeURIComponent(options.sessionId)}/review?${new URLSearchParams({ executionId: options.executionId ?? "" })}`, void 0, options.signal)).json());
242
+ }
243
+ /** Reads a directory or complete file through the factory's configured workspace adapter. */
244
+ async getWorkspaceFiles(options) {
245
+ const query = workspaceFilesRequestSchema.parse({
246
+ path: options.path,
247
+ revision: options.revision
248
+ });
249
+ const params = new URLSearchParams({
250
+ executionId: options.executionId ?? "",
251
+ path: query.path
252
+ });
253
+ if (query.revision !== void 0) params.set("revision", query.revision);
254
+ return workspaceFilesSchema.parse(await (await this.response(`sessions/${encodeURIComponent(options.sessionId)}/files?${params}`, void 0, options.signal)).json());
255
+ }
187
256
  /** Reads the committed workspace comparison for one observed execution. */
188
257
  async getWorkspaceDiff(options) {
189
258
  return workspaceDiffSchema.parse(await (await this.response(`sessions/${encodeURIComponent(options.sessionId)}/diff?${new URLSearchParams({ executionId: options.executionId ?? "" })}`, void 0, options.signal)).json());
190
259
  }
191
- /** Creates or recovers an idempotent conversational session. */
260
+ /**
261
+ * Creates or recovers an idempotent conversational session.
262
+ *
263
+ * @remarks
264
+ * Retain `input.operationId` unchanged across ambiguous failures. Reusing it with identical input
265
+ * returns the original session; reusing it with different input is a conflict. The returned view
266
+ * means admission and any initial dispatch attempt finished, not that the agent's work completed.
267
+ *
268
+ * @param input - Agent, initial content, optional repository/change, and client idempotency key.
269
+ * @returns The admitted or recovered session snapshot.
270
+ */
192
271
  async createSession(input) {
193
272
  return sessionViewSchema.parse(await (await this.response("sessions", createSessionRequestSchema.parse(input))).json());
194
273
  }
@@ -196,15 +275,44 @@ var FactoryClient = class {
196
275
  async createSignal(input) {
197
276
  return sessionViewSchema.parse(await (await this.response("signals", createSessionRequestSchema.parse(input))).json());
198
277
  }
199
- /** Sends a message to an existing session. */
278
+ /** Starts a deepsec security scan of a repository, or returns its already-active scan. */
279
+ async runSecurityScan(repositoryId) {
280
+ return z.strictObject({
281
+ taskId: taskIdSchema,
282
+ reused: z.boolean()
283
+ }).parse(await (await this.response(`repositories/${repositoryId}/security-scan`, {})).json());
284
+ }
285
+ /**
286
+ * Sends a message to an existing session using optimistic execution matching.
287
+ *
288
+ * @remarks
289
+ * `input.executionId` must be the execution the caller observed, or `null` when none was active.
290
+ * A completed Task follow-up also requires an `operationId`, which must be retained for retries.
291
+ * Resolving means the API accepted the message; provider or follow-up work may still be running.
292
+ *
293
+ * @param id - Stable Factory session receiving the message.
294
+ * @param input - Message, observed execution, steering policy, attachments, and optional retry key.
295
+ * @returns Nothing after the API accepts the request.
296
+ */
200
297
  async sendSessionMessage(id, input) {
201
298
  await (await this.response(`sessions/${encodeURIComponent(id)}/messages`, sendSessionMessageRequestSchema.parse(input))).body?.cancel();
202
299
  }
203
- /** Submits responses to pending provider input requests. */
300
+ /**
301
+ * Submits responses to pending provider input requests.
302
+ *
303
+ * @param id - Stable Factory session whose provider requested input.
304
+ * @param input - Observed execution ID and one or more request-correlated responses.
305
+ * @returns Nothing after the API accepts the responses; stale execution IDs are rejected.
306
+ */
204
307
  async submitSessionInput(id, input) {
205
308
  await (await this.response(`sessions/${encodeURIComponent(id)}/input`, submitSessionInputRequestSchema.parse(input))).body?.cancel();
206
309
  }
207
- /** Dispatches queued workflow work associated with a session. */
310
+ /**
311
+ * Attempts to dispatch queued workflow work associated with a session.
312
+ *
313
+ * @param id - Stable Factory session whose current work should be dispatched.
314
+ * @returns The refreshed session after the bounded dispatch attempt, which may still be queued.
315
+ */
208
316
  async dispatchSession(id) {
209
317
  return sessionViewSchema.parse(await (await this.response(`sessions/${encodeURIComponent(id)}/dispatch`, {})).json());
210
318
  }
@@ -253,6 +361,6 @@ var FactoryClient = class {
253
361
  }
254
362
  };
255
363
  //#endregion
256
- export { ApiError, FactoryClient, MAX_IMAGES, MAX_IMAGE_BYTES, Transcript, agentSessionIdSchema, agentSessionSchema, answerSessionQuestionRequestSchema, apiAgentSchema, controlSessionRequestSchema, createSessionRequestSchema, describeIntake, followSessionStream, imageAttachmentSchema, imageAttachmentsSchema, imageIdSchema, inputRequestSchema, pendingFollowUpSchema, readEvents, repositoryDetailsSchema, repositorySummarySchema, sendSessionMessageRequestSchema, sessionInputResponseSchema, sessionPageSchema, sessionViewSchema, streamEventSchema, submitSessionInputRequestSchema, taskStates, toolCallSchema, transcriptBlockSchema, transcriptSnapshotSchema, workspaceDiffFileSchema, workspaceDiffSchema };
364
+ export { ApiError, FactoryClient, MAX_IMAGES, MAX_IMAGE_BYTES, Transcript, agentModelConfigSchema, agentSessionIdSchema, agentSessionSchema, answerSessionQuestionRequestSchema, apiAgentSchema, controlSessionRequestSchema, createSessionRequestSchema, describeIntake, followSessionStream, imageAttachmentSchema, imageAttachmentsSchema, imageIdSchema, inboxActivityItemSchema, inboxActivitySchema, inputRequestSchema, modelSettingsSchema, pendingFollowUpSchema, readEvents, repositoryDetailsSchema, repositorySummarySchema, sendSessionMessageRequestSchema, sessionInputResponseSchema, sessionPageSchema, sessionPreviewSchema, sessionPreviewsSchema, sessionReviewCheckSchema, sessionReviewIssueSchema, sessionReviewSchema, sessionReviewScreenshotSchema, sessionViewSchema, streamEventSchema, submitSessionInputRequestSchema, taskStates, toolCallSchema, transcriptBlockSchema, transcriptSnapshotSchema, updateModelDefaultsSchema, workspaceDiffFileSchema, workspaceDiffSchema, workspaceFileContentSchema, workspaceFileEntrySchema, workspaceFilesRequestSchema, workspaceFilesSchema, workspacePathSchema };
257
365
 
258
366
  //# sourceMappingURL=client.mjs.map