@lota-sdk/core 0.4.8 → 0.4.10

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 (272) hide show
  1. package/package.json +11 -12
  2. package/src/ai/embedding-cache.ts +96 -22
  3. package/src/ai-gateway/ai-gateway.ts +766 -223
  4. package/src/config/agent-defaults.ts +189 -75
  5. package/src/config/agent-types.ts +54 -4
  6. package/src/config/background-processing.ts +1 -1
  7. package/src/config/constants.ts +8 -2
  8. package/src/config/index.ts +0 -1
  9. package/src/config/logger.ts +299 -19
  10. package/src/config/thread-defaults.ts +40 -20
  11. package/src/create-runtime.ts +200 -449
  12. package/src/db/base.service.ts +52 -28
  13. package/src/db/cursor-pagination.ts +71 -30
  14. package/src/db/memory-query-builder.ts +2 -1
  15. package/src/db/memory-store.helpers.ts +4 -7
  16. package/src/db/memory-store.ts +868 -601
  17. package/src/db/memory.ts +396 -280
  18. package/src/db/record-id.ts +32 -10
  19. package/src/db/schema-fingerprint.ts +30 -12
  20. package/src/db/service-normalization.ts +288 -0
  21. package/src/db/service.ts +912 -779
  22. package/src/db/startup.ts +153 -68
  23. package/src/db/transaction-conflict.ts +15 -0
  24. package/src/effect/awaitable-effect.ts +96 -0
  25. package/src/effect/errors.ts +121 -0
  26. package/src/effect/helpers.ts +123 -0
  27. package/src/effect/index.ts +24 -0
  28. package/src/effect/layers.ts +238 -0
  29. package/src/effect/runtime-ref.ts +25 -0
  30. package/src/effect/runtime.ts +46 -0
  31. package/src/effect/services.ts +61 -0
  32. package/src/effect/zod.ts +43 -0
  33. package/src/embeddings/provider.ts +128 -83
  34. package/src/index.ts +48 -1
  35. package/src/openrouter/direct-provider.ts +11 -35
  36. package/src/queues/autonomous-job.queue.ts +117 -73
  37. package/src/queues/context-compaction.queue.ts +50 -17
  38. package/src/queues/delayed-node-promotion.queue.ts +46 -17
  39. package/src/queues/document-processor.queue.ts +52 -77
  40. package/src/queues/memory-consolidation.queue.ts +47 -32
  41. package/src/queues/organization-learning.queue.ts +26 -4
  42. package/src/queues/plan-agent-heartbeat.queue.ts +71 -24
  43. package/src/queues/plan-scheduler.queue.ts +97 -33
  44. package/src/queues/post-chat-memory.queue.ts +56 -26
  45. package/src/queues/queue-factory.ts +227 -59
  46. package/src/queues/standalone-worker.ts +39 -0
  47. package/src/queues/title-generation.queue.ts +45 -11
  48. package/src/redis/connection.ts +182 -113
  49. package/src/redis/index.ts +6 -8
  50. package/src/redis/org-memory-lock.ts +60 -27
  51. package/src/redis/redis-lease-lock.ts +200 -121
  52. package/src/redis/runtime-connection.ts +20 -0
  53. package/src/redis/stream-context.ts +92 -46
  54. package/src/runtime/agent-identity-overrides.ts +2 -2
  55. package/src/runtime/agent-runtime-policy.ts +5 -2
  56. package/src/runtime/agent-stream-helpers.ts +24 -9
  57. package/src/runtime/chat-run-orchestration.ts +102 -19
  58. package/src/runtime/chat-run-registry.ts +36 -2
  59. package/src/runtime/context-compaction/context-compaction-runtime.ts +107 -0
  60. package/src/runtime/{context-compaction.ts → context-compaction/context-compaction.ts} +161 -94
  61. package/src/runtime/domain-layer.ts +192 -0
  62. package/src/runtime/execution-plan-visibility.ts +2 -2
  63. package/src/runtime/execution-plan.ts +42 -15
  64. package/src/runtime/graph-designer.ts +16 -4
  65. package/src/runtime/helper-model.ts +139 -48
  66. package/src/runtime/index.ts +7 -8
  67. package/src/runtime/indexed-repositories-policy.ts +3 -3
  68. package/src/runtime/{memory-block.ts → memory/memory-block.ts} +50 -36
  69. package/src/runtime/{memory-digest-policy.ts → memory/memory-digest-policy.ts} +1 -1
  70. package/src/runtime/{memory-pipeline.ts → memory/memory-pipeline.ts} +54 -67
  71. package/src/runtime/{memory-prompts-fact.ts → memory/memory-prompts-fact.ts} +2 -2
  72. package/src/runtime/memory/memory-scope.ts +53 -0
  73. package/src/runtime/plugin-resolution.ts +124 -25
  74. package/src/runtime/plugin-types.ts +9 -1
  75. package/src/runtime/post-turn-side-effects.ts +177 -130
  76. package/src/runtime/retrieval-adapters.ts +40 -6
  77. package/src/runtime/runtime-accessors.ts +92 -0
  78. package/src/runtime/runtime-config.ts +150 -61
  79. package/src/runtime/runtime-extensions.ts +23 -25
  80. package/src/runtime/runtime-lifecycle.ts +124 -0
  81. package/src/runtime/runtime-services.ts +386 -0
  82. package/src/runtime/runtime-token.ts +47 -0
  83. package/src/runtime/social-chat/social-chat-agent-runner.ts +159 -0
  84. package/src/runtime/{social-chat-history.ts → social-chat/social-chat-history.ts} +51 -20
  85. package/src/runtime/social-chat/social-chat.ts +630 -0
  86. package/src/runtime/specialist-runner.ts +36 -10
  87. package/src/runtime/team-consultation/team-consultation-orchestrator.ts +433 -0
  88. package/src/runtime/{team-consultation-prompts.ts → team-consultation/team-consultation-prompts.ts} +6 -2
  89. package/src/runtime/thread-chat-helpers.ts +2 -2
  90. package/src/runtime/thread-plan-turn.ts +2 -1
  91. package/src/runtime/thread-turn-context.ts +183 -111
  92. package/src/runtime/turn-lifecycle.ts +93 -27
  93. package/src/services/agent-activity.service.ts +287 -203
  94. package/src/services/agent-executor.service.ts +253 -149
  95. package/src/services/artifact.service.ts +231 -149
  96. package/src/services/attachment.service.ts +171 -115
  97. package/src/services/autonomous-job.service.ts +890 -491
  98. package/src/services/background-work.service.ts +54 -0
  99. package/src/services/chat-run-registry.service.ts +13 -1
  100. package/src/services/context-compaction.service.ts +136 -86
  101. package/src/services/document-chunk.service.ts +151 -88
  102. package/src/services/execution-plan/execution-plan-approval.ts +26 -0
  103. package/src/services/execution-plan/execution-plan-context.ts +29 -0
  104. package/src/services/execution-plan/execution-plan-graph.ts +278 -0
  105. package/src/services/execution-plan/execution-plan-schedule.ts +84 -0
  106. package/src/services/execution-plan/execution-plan-spec.ts +75 -0
  107. package/src/services/execution-plan/execution-plan.service.ts +1041 -0
  108. package/src/services/feedback-loop.service.ts +132 -76
  109. package/src/services/global-orchestrator.service.ts +101 -168
  110. package/src/services/graph-full-routing.ts +193 -0
  111. package/src/services/index.ts +19 -21
  112. package/src/services/institutional-memory.service.ts +213 -125
  113. package/src/services/learned-skill.service.ts +368 -260
  114. package/src/services/memory/memory-conversation.ts +95 -0
  115. package/src/services/memory/memory-errors.ts +27 -0
  116. package/src/services/memory/memory-org-memory.ts +50 -0
  117. package/src/services/memory/memory-preseeded.ts +86 -0
  118. package/src/services/memory/memory-rerank.ts +297 -0
  119. package/src/services/{memory-utils.ts → memory/memory-utils.ts} +6 -5
  120. package/src/services/memory/memory.service.ts +674 -0
  121. package/src/services/memory/rerank.service.ts +201 -0
  122. package/src/services/monitoring-window.service.ts +92 -70
  123. package/src/services/mutating-approval.service.ts +62 -53
  124. package/src/services/node-workspace.service.ts +141 -98
  125. package/src/services/notification.service.ts +29 -16
  126. package/src/services/organization-member.service.ts +120 -66
  127. package/src/services/organization.service.ts +153 -77
  128. package/src/services/ownership-dispatcher.service.ts +456 -263
  129. package/src/services/plan/plan-agent-heartbeat.service.ts +234 -0
  130. package/src/services/plan/plan-agent-query.service.ts +322 -0
  131. package/src/services/{plan-approval.service.ts → plan/plan-approval.service.ts} +45 -22
  132. package/src/services/plan/plan-artifact.service.ts +60 -0
  133. package/src/services/plan/plan-builder.service.ts +76 -0
  134. package/src/services/plan/plan-checkpoint.service.ts +103 -0
  135. package/src/services/{plan-compiler.service.ts → plan/plan-compiler.service.ts} +26 -9
  136. package/src/services/plan/plan-completion-side-effects.ts +169 -0
  137. package/src/services/plan/plan-coordination.service.ts +181 -0
  138. package/src/services/plan/plan-cycle.service.ts +405 -0
  139. package/src/services/plan/plan-deadline.service.ts +533 -0
  140. package/src/services/plan/plan-event-delivery.service.ts +266 -0
  141. package/src/services/plan/plan-executor-context.ts +35 -0
  142. package/src/services/plan/plan-executor-graph.ts +522 -0
  143. package/src/services/plan/plan-executor-helpers.ts +307 -0
  144. package/src/services/plan/plan-executor-persistence.ts +209 -0
  145. package/src/services/plan/plan-executor.service.ts +1737 -0
  146. package/src/services/{plan-helpers.ts → plan/plan-helpers.ts} +1 -1
  147. package/src/services/{plan-run-data.ts → plan/plan-run-data.ts} +4 -4
  148. package/src/services/plan/plan-run-serialization.ts +15 -0
  149. package/src/services/plan/plan-run.service.ts +637 -0
  150. package/src/services/plan/plan-scheduler.service.ts +379 -0
  151. package/src/services/plan/plan-template.service.ts +224 -0
  152. package/src/services/plan/plan-transaction-events.ts +36 -0
  153. package/src/services/plan/plan-validator.service.ts +907 -0
  154. package/src/services/plan/plan-workspace.service.ts +131 -0
  155. package/src/services/plugin-executor.service.ts +102 -68
  156. package/src/services/quality-metrics.service.ts +112 -94
  157. package/src/services/queue-job.service.ts +288 -231
  158. package/src/services/recent-activity-title.service.ts +73 -36
  159. package/src/services/recent-activity.service.ts +274 -259
  160. package/src/services/skill-resolver.service.ts +38 -12
  161. package/src/services/social-chat-history.service.ts +190 -122
  162. package/src/services/system-executor.service.ts +96 -61
  163. package/src/services/thread/thread-active-run.ts +203 -0
  164. package/src/services/thread/thread-bootstrap.ts +385 -0
  165. package/src/services/thread/thread-listing.ts +199 -0
  166. package/src/services/thread/thread-memory-block.ts +130 -0
  167. package/src/services/thread/thread-message.service.ts +379 -0
  168. package/src/services/thread/thread-record-store.ts +155 -0
  169. package/src/services/thread/thread-title.service.ts +74 -0
  170. package/src/services/thread/thread-turn-execution.ts +280 -0
  171. package/src/services/thread/thread-turn-message-context.ts +73 -0
  172. package/src/services/thread/thread-turn-preparation.service.ts +1148 -0
  173. package/src/services/thread/thread-turn-streaming.ts +403 -0
  174. package/src/services/thread/thread-turn-tracing.ts +35 -0
  175. package/src/services/thread/thread-turn.ts +376 -0
  176. package/src/services/thread/thread.service.ts +344 -0
  177. package/src/services/user.service.ts +82 -32
  178. package/src/services/write-intent-validator.service.ts +63 -51
  179. package/src/storage/attachment-parser.ts +69 -27
  180. package/src/storage/attachment-storage.service.ts +334 -275
  181. package/src/storage/generated-document-storage.service.ts +66 -34
  182. package/src/system-agents/agent-result.ts +3 -1
  183. package/src/system-agents/context-compaction.agent.ts +3 -3
  184. package/src/system-agents/delegated-agent-factory.ts +159 -90
  185. package/src/system-agents/helper-agent-options.ts +1 -1
  186. package/src/system-agents/memory-reranker.agent.ts +3 -3
  187. package/src/system-agents/memory.agent.ts +3 -3
  188. package/src/system-agents/recent-activity-title-refiner.agent.ts +3 -3
  189. package/src/system-agents/regular-chat-memory-digest.agent.ts +3 -3
  190. package/src/system-agents/skill-extractor.agent.ts +3 -3
  191. package/src/system-agents/skill-manager.agent.ts +3 -3
  192. package/src/system-agents/thread-router.agent.ts +157 -113
  193. package/src/system-agents/title-generator.agent.ts +3 -3
  194. package/src/tools/execution-plan.tool.ts +241 -171
  195. package/src/tools/fetch-webpage.tool.ts +29 -18
  196. package/src/tools/firecrawl-client.ts +26 -6
  197. package/src/tools/index.ts +1 -0
  198. package/src/tools/memory-block.tool.ts +14 -6
  199. package/src/tools/plan-approval.tool.ts +57 -47
  200. package/src/tools/read-file-parts.tool.ts +44 -33
  201. package/src/tools/remember-memory.tool.ts +65 -45
  202. package/src/tools/search-web.tool.ts +33 -22
  203. package/src/tools/search.tool.ts +41 -29
  204. package/src/tools/team-think.tool.ts +125 -84
  205. package/src/tools/user-questions.tool.ts +4 -3
  206. package/src/tools/web-tool-shared.ts +6 -0
  207. package/src/utils/async.ts +25 -22
  208. package/src/utils/crypto.ts +21 -0
  209. package/src/utils/date-time.ts +40 -1
  210. package/src/utils/errors.ts +111 -20
  211. package/src/utils/hono-error-handler.ts +24 -39
  212. package/src/utils/index.ts +2 -1
  213. package/src/utils/null-proto-record.ts +41 -0
  214. package/src/utils/sse-keepalive.ts +124 -21
  215. package/src/workers/bootstrap.ts +164 -52
  216. package/src/workers/memory-consolidation.worker.ts +325 -237
  217. package/src/workers/organization-learning.worker.ts +50 -16
  218. package/src/workers/regular-chat-memory-digest.helpers.ts +28 -27
  219. package/src/workers/regular-chat-memory-digest.runner.ts +185 -114
  220. package/src/workers/skill-extraction.runner.ts +176 -93
  221. package/src/workers/utils/file-section-chunker.ts +8 -10
  222. package/src/workers/utils/repo-structure-extractor.ts +349 -260
  223. package/src/workers/utils/repomix-file-sections.ts +2 -2
  224. package/src/workers/utils/thread-message-query.ts +97 -38
  225. package/src/workers/worker-utils.ts +74 -31
  226. package/src/config/debug-logger.ts +0 -47
  227. package/src/config/search.ts +0 -3
  228. package/src/redis/connection-accessor.ts +0 -26
  229. package/src/runtime/agent-types.ts +0 -1
  230. package/src/runtime/context-compaction-runtime.ts +0 -87
  231. package/src/runtime/memory-scope.ts +0 -43
  232. package/src/runtime/social-chat-agent-runner.ts +0 -118
  233. package/src/runtime/social-chat.ts +0 -516
  234. package/src/runtime/team-consultation-orchestrator.ts +0 -272
  235. package/src/services/adaptive-playbook.service.ts +0 -152
  236. package/src/services/artifact-provenance.service.ts +0 -172
  237. package/src/services/chat-attachments.service.ts +0 -17
  238. package/src/services/context-compaction-runtime.singleton.ts +0 -13
  239. package/src/services/execution-plan.service.ts +0 -1118
  240. package/src/services/memory.service.ts +0 -914
  241. package/src/services/plan-agent-heartbeat.service.ts +0 -136
  242. package/src/services/plan-agent-query.service.ts +0 -267
  243. package/src/services/plan-artifact.service.ts +0 -50
  244. package/src/services/plan-builder.service.ts +0 -67
  245. package/src/services/plan-checkpoint.service.ts +0 -81
  246. package/src/services/plan-completion-side-effects.ts +0 -80
  247. package/src/services/plan-coordination.service.ts +0 -157
  248. package/src/services/plan-cycle.service.ts +0 -284
  249. package/src/services/plan-deadline.service.ts +0 -430
  250. package/src/services/plan-event-delivery.service.ts +0 -166
  251. package/src/services/plan-executor.service.ts +0 -1950
  252. package/src/services/plan-run.service.ts +0 -515
  253. package/src/services/plan-scheduler.service.ts +0 -240
  254. package/src/services/plan-template.service.ts +0 -177
  255. package/src/services/plan-validator.service.ts +0 -818
  256. package/src/services/plan-workspace.service.ts +0 -83
  257. package/src/services/rerank.service.ts +0 -156
  258. package/src/services/thread-message.service.ts +0 -275
  259. package/src/services/thread-plan-registry.service.ts +0 -22
  260. package/src/services/thread-title.service.ts +0 -39
  261. package/src/services/thread-turn-preparation.service.ts +0 -1147
  262. package/src/services/thread-turn.ts +0 -172
  263. package/src/services/thread.service.ts +0 -869
  264. package/src/utils/env.ts +0 -8
  265. /package/src/runtime/{context-compaction-constants.ts → context-compaction/context-compaction-constants.ts} +0 -0
  266. /package/src/runtime/{memory-format.ts → memory/memory-format.ts} +0 -0
  267. /package/src/runtime/{memory-prompts-parse.ts → memory/memory-prompts-parse.ts} +0 -0
  268. /package/src/runtime/{memory-prompts-update.ts → memory/memory-prompts-update.ts} +0 -0
  269. /package/src/runtime/{social-chat-prompts.ts → social-chat/social-chat-prompts.ts} +0 -0
  270. /package/src/services/{plan-node-spec.ts → plan/plan-node-spec.ts} +0 -0
  271. /package/src/services/{thread-constants.ts → thread/thread-constants.ts} +0 -0
  272. /package/src/services/{thread.types.ts → thread/thread.types.ts} +0 -0
@@ -1,515 +0,0 @@
1
- import {
2
- PlanApprovalSchema,
3
- PlanArtifactSchema,
4
- PlanCheckpointSchema,
5
- PlanEventSchema,
6
- PlanNodeAttemptSchema,
7
- PlanNodeRunSchema,
8
- PlanNodeSpecRecordSchema,
9
- PlanRunSchema,
10
- PlanSpecSchema,
11
- PlanValidationIssueSchema,
12
- } from '@lota-sdk/shared'
13
- import type {
14
- PlanApprovalRecord,
15
- PlanArtifactRecord,
16
- PlanCheckpointRecord,
17
- PlanEventRecord,
18
- PlanNodeAttemptRecord,
19
- PlanNodeRunRecord,
20
- PlanNodeRunStatus,
21
- PlanNodeSpecRecord,
22
- PlanRunRecord,
23
- PlanSpecRecord,
24
- PlanValidationIssueRecord,
25
- SerializableExecutionPlan,
26
- SerializablePlanApproval,
27
- SerializablePlanArtifact,
28
- SerializablePlanCheckpoint,
29
- SerializablePlanEvent,
30
- SerializablePlanNode,
31
- SerializablePlanValidationIssue,
32
- } from '@lota-sdk/shared'
33
-
34
- import type { RecordIdInput } from '../db/record-id'
35
- import { ensureRecordId, recordIdToString } from '../db/record-id'
36
- import { databaseService } from '../db/service'
37
- import { TABLES } from '../db/tables'
38
- import { toIsoDateTimeString, toOptionalIsoDateTimeString } from '../utils/date-time'
39
-
40
- const ACTIVE_RUN_STATUSES = new Set(['pending-approval', 'running', 'awaiting-human', 'blocked'])
41
-
42
- function buildProgress(nodeRuns: PlanNodeRunRecord[]) {
43
- const counts = nodeRuns.reduce(
44
- (summary, nodeRun) => {
45
- summary[nodeRun.status] += 1
46
- return summary
47
- },
48
- {
49
- pending: 0,
50
- ready: 0,
51
- running: 0,
52
- 'awaiting-human': 0,
53
- completed: 0,
54
- partial: 0,
55
- blocked: 0,
56
- failed: 0,
57
- skipped: 0,
58
- scheduled: 0,
59
- monitoring: 0,
60
- } satisfies Record<PlanNodeRunStatus, number>,
61
- )
62
-
63
- const total = nodeRuns.length
64
- const completedWork = counts.completed + counts.partial + counts.skipped
65
-
66
- return {
67
- total,
68
- pending: counts.pending,
69
- ready: counts.ready,
70
- running: counts.running,
71
- awaitingHuman: counts['awaiting-human'],
72
- completed: counts.completed,
73
- partial: counts.partial,
74
- blocked: counts.blocked,
75
- failed: counts.failed,
76
- skipped: counts.skipped,
77
- scheduled: counts.scheduled,
78
- monitoring: counts.monitoring,
79
- completionRatio: total > 0 ? Number((completedWork / total).toFixed(4)) : undefined,
80
- }
81
- }
82
-
83
- function serializeArtifact(artifact: PlanArtifactRecord): SerializablePlanArtifact {
84
- return {
85
- id: recordIdToString(artifact.id, TABLES.PLAN_ARTIFACT),
86
- nodeId: artifact.nodeId,
87
- attemptId: recordIdToString(artifact.attemptId, TABLES.PLAN_NODE_ATTEMPT),
88
- name: artifact.name,
89
- kind: artifact.kind,
90
- pointer: artifact.pointer,
91
- schemaRef: artifact.schemaRef,
92
- description: artifact.description,
93
- content: artifact.content,
94
- payload: artifact.payload,
95
- publishedArtifactId: artifact.publishedArtifactId
96
- ? recordIdToString(artifact.publishedArtifactId, TABLES.ARTIFACT)
97
- : undefined,
98
- createdAt: toIsoDateTimeString(artifact.createdAt),
99
- }
100
- }
101
-
102
- function serializeValidationIssue(issue: PlanValidationIssueRecord): SerializablePlanValidationIssue {
103
- return {
104
- id: recordIdToString(issue.id, TABLES.PLAN_VALIDATION_ISSUE),
105
- nodeId: issue.nodeId,
106
- attemptId: issue.attemptId ? recordIdToString(issue.attemptId, TABLES.PLAN_NODE_ATTEMPT) : undefined,
107
- severity: issue.severity,
108
- code: issue.code,
109
- message: issue.message,
110
- detail: issue.detail,
111
- createdAt: toIsoDateTimeString(issue.createdAt),
112
- }
113
- }
114
-
115
- function serializeApproval(approval: PlanApprovalRecord): SerializablePlanApproval {
116
- return {
117
- id: recordIdToString(approval.id, TABLES.PLAN_APPROVAL),
118
- nodeId: approval.nodeId,
119
- status: approval.status,
120
- presented: approval.presented,
121
- response: approval.response,
122
- requestedBy: approval.requestedBy,
123
- respondedBy: approval.respondedBy,
124
- approvalMessageId: approval.approvalMessageId,
125
- comments: approval.comments,
126
- requiredEdits: [...approval.requiredEdits],
127
- createdAt: toIsoDateTimeString(approval.createdAt),
128
- respondedAt: toOptionalIsoDateTimeString(approval.respondedAt),
129
- }
130
- }
131
-
132
- function serializeCheckpoint(checkpoint: PlanCheckpointRecord): SerializablePlanCheckpoint {
133
- return {
134
- id: recordIdToString(checkpoint.id, TABLES.PLAN_CHECKPOINT),
135
- sequence: checkpoint.sequence,
136
- runStatus: checkpoint.runStatus,
137
- readyNodeIds: [...checkpoint.readyNodeIds],
138
- activeNodeIds: [...checkpoint.activeNodeIds],
139
- artifactIds: checkpoint.artifactIds.map((artifactId) => recordIdToString(artifactId, TABLES.PLAN_ARTIFACT)),
140
- lastCompletedNodeIds: [...checkpoint.lastCompletedNodeIds],
141
- snapshot: checkpoint.snapshot,
142
- createdAt: toIsoDateTimeString(checkpoint.createdAt),
143
- }
144
- }
145
-
146
- function serializeEvent(event: PlanEventRecord): SerializablePlanEvent {
147
- return {
148
- id: recordIdToString(event.id, TABLES.PLAN_EVENT),
149
- nodeId: event.nodeId,
150
- attemptId: event.attemptId ? recordIdToString(event.attemptId, TABLES.PLAN_NODE_ATTEMPT) : undefined,
151
- approvalId: event.approvalId ? recordIdToString(event.approvalId, TABLES.PLAN_APPROVAL) : undefined,
152
- eventType: event.eventType,
153
- fromStatus: event.fromStatus,
154
- toStatus: event.toStatus,
155
- message: event.message,
156
- detail: event.detail,
157
- emittedBy: event.emittedBy,
158
- createdAt: toIsoDateTimeString(event.createdAt),
159
- }
160
- }
161
-
162
- class PlanRunService {
163
- async getPlanSpecById(planSpecId: RecordIdInput): Promise<PlanSpecRecord> {
164
- const spec = await databaseService.findOne(
165
- TABLES.PLAN_SPEC,
166
- { id: ensureRecordId(planSpecId, TABLES.PLAN_SPEC) },
167
- PlanSpecSchema,
168
- )
169
- if (!spec) {
170
- throw new Error(`Plan spec not found: ${recordIdToString(planSpecId, TABLES.PLAN_SPEC)}`)
171
- }
172
- return spec
173
- }
174
-
175
- async listPlanSpecsByThread(threadId: RecordIdInput): Promise<PlanSpecRecord[]> {
176
- return databaseService.findMany(
177
- TABLES.PLAN_SPEC,
178
- { threadId: ensureRecordId(threadId, TABLES.THREAD) },
179
- PlanSpecSchema,
180
- { orderBy: 'createdAt', orderDir: 'DESC' },
181
- )
182
- }
183
-
184
- async listRunsBySpec(planSpecId: RecordIdInput): Promise<PlanRunRecord[]> {
185
- return databaseService.findMany(
186
- TABLES.PLAN_RUN,
187
- { planSpecId: ensureRecordId(planSpecId, TABLES.PLAN_SPEC) },
188
- PlanRunSchema,
189
- { orderBy: 'createdAt', orderDir: 'DESC' },
190
- )
191
- }
192
-
193
- async listNodeSpecs(planSpecId: RecordIdInput): Promise<PlanNodeSpecRecord[]> {
194
- return databaseService.findMany(
195
- TABLES.PLAN_NODE_SPEC,
196
- { planSpecId: ensureRecordId(planSpecId, TABLES.PLAN_SPEC) },
197
- PlanNodeSpecRecordSchema,
198
- { orderBy: 'position', orderDir: 'ASC' },
199
- )
200
- }
201
-
202
- async getNodeSpecByNodeId(planSpecId: RecordIdInput, nodeId: string): Promise<PlanNodeSpecRecord> {
203
- const nodeSpec = await databaseService.findOne(
204
- TABLES.PLAN_NODE_SPEC,
205
- { planSpecId: ensureRecordId(planSpecId, TABLES.PLAN_SPEC), nodeId },
206
- PlanNodeSpecRecordSchema,
207
- )
208
- if (!nodeSpec) {
209
- throw new Error(`Plan node spec "${nodeId}" not found.`)
210
- }
211
- return nodeSpec
212
- }
213
-
214
- async getRunById(runId: RecordIdInput): Promise<PlanRunRecord> {
215
- const run = await databaseService.findOne(
216
- TABLES.PLAN_RUN,
217
- { id: ensureRecordId(runId, TABLES.PLAN_RUN) },
218
- PlanRunSchema,
219
- )
220
- if (!run) {
221
- throw new Error(`Plan run not found: ${recordIdToString(runId, TABLES.PLAN_RUN)}`)
222
- }
223
- return run
224
- }
225
-
226
- async getActiveRunRecord(threadId: RecordIdInput): Promise<PlanRunRecord | null> {
227
- const runs = await this.getActiveRunRecords(threadId)
228
- return runs[0] ?? null
229
- }
230
-
231
- async getActiveRunRecords(threadId: RecordIdInput): Promise<PlanRunRecord[]> {
232
- const runs = await databaseService.findMany(
233
- TABLES.PLAN_RUN,
234
- { threadId: ensureRecordId(threadId, TABLES.THREAD) },
235
- PlanRunSchema,
236
- { orderBy: 'updatedAt', orderDir: 'DESC' },
237
- )
238
-
239
- return runs.filter((run) => ACTIVE_RUN_STATUSES.has(run.status))
240
- }
241
-
242
- async getRunsCreatedInContext(params: {
243
- organizationId: RecordIdInput
244
- sourceThreadId?: RecordIdInput
245
- createdByAgentId?: string
246
- statuses?: ReadonlyArray<PlanRunRecord['status']>
247
- }): Promise<PlanRunRecord[]> {
248
- const filter: Record<string, unknown> = {
249
- organizationId: ensureRecordId(params.organizationId, TABLES.ORGANIZATION),
250
- }
251
- if (params.sourceThreadId) {
252
- filter.sourceThreadId = ensureRecordId(params.sourceThreadId, TABLES.THREAD)
253
- }
254
- if (params.createdByAgentId) {
255
- filter.createdByAgentId = params.createdByAgentId
256
- }
257
-
258
- const runs = await databaseService.findMany(TABLES.PLAN_RUN, filter, PlanRunSchema, {
259
- orderBy: 'updatedAt',
260
- orderDir: 'DESC',
261
- })
262
-
263
- const statuses = params.statuses ? new Set(params.statuses) : ACTIVE_RUN_STATUSES
264
- return runs.filter((run) => statuses.has(run.status))
265
- }
266
-
267
- async listNodeRuns(runId: RecordIdInput): Promise<PlanNodeRunRecord[]> {
268
- return databaseService.findMany(
269
- TABLES.PLAN_NODE_RUN,
270
- { runId: ensureRecordId(runId, TABLES.PLAN_RUN) },
271
- PlanNodeRunSchema,
272
- { orderBy: 'nodeId', orderDir: 'ASC' },
273
- )
274
- }
275
-
276
- async getNodeRunByNodeId(runId: RecordIdInput, nodeId: string): Promise<PlanNodeRunRecord> {
277
- const nodeRun = await databaseService.findOne(
278
- TABLES.PLAN_NODE_RUN,
279
- { runId: ensureRecordId(runId, TABLES.PLAN_RUN), nodeId },
280
- PlanNodeRunSchema,
281
- )
282
- if (!nodeRun) {
283
- throw new Error(`Plan node run "${nodeId}" not found.`)
284
- }
285
- return nodeRun
286
- }
287
-
288
- async listArtifacts(runId: RecordIdInput): Promise<PlanArtifactRecord[]> {
289
- return databaseService.findMany(
290
- TABLES.PLAN_ARTIFACT,
291
- { runId: ensureRecordId(runId, TABLES.PLAN_RUN) },
292
- PlanArtifactSchema,
293
- { orderBy: 'createdAt', orderDir: 'ASC' },
294
- )
295
- }
296
-
297
- async listAttempts(runId: RecordIdInput): Promise<PlanNodeAttemptRecord[]> {
298
- return databaseService.findMany(
299
- TABLES.PLAN_NODE_ATTEMPT,
300
- { runId: ensureRecordId(runId, TABLES.PLAN_RUN) },
301
- PlanNodeAttemptSchema,
302
- { orderBy: 'createdAt', orderDir: 'ASC' },
303
- )
304
- }
305
-
306
- async listValidationIssues(params: {
307
- runId?: RecordIdInput
308
- planSpecId?: RecordIdInput
309
- attemptId?: RecordIdInput
310
- }): Promise<PlanValidationIssueRecord[]> {
311
- const filter: Record<string, unknown> = {}
312
- if (params.runId) filter.runId = ensureRecordId(params.runId, TABLES.PLAN_RUN)
313
- if (params.planSpecId) filter.planSpecId = ensureRecordId(params.planSpecId, TABLES.PLAN_SPEC)
314
- if (params.attemptId) filter.attemptId = ensureRecordId(params.attemptId, TABLES.PLAN_NODE_ATTEMPT)
315
-
316
- return databaseService.findMany(TABLES.PLAN_VALIDATION_ISSUE, filter, PlanValidationIssueSchema, {
317
- orderBy: 'createdAt',
318
- orderDir: 'ASC',
319
- })
320
- }
321
-
322
- async listApprovals(runId: RecordIdInput): Promise<PlanApprovalRecord[]> {
323
- return databaseService.findMany(
324
- TABLES.PLAN_APPROVAL,
325
- { runId: ensureRecordId(runId, TABLES.PLAN_RUN) },
326
- PlanApprovalSchema,
327
- { orderBy: 'createdAt', orderDir: 'ASC' },
328
- )
329
- }
330
-
331
- async getLatestCheckpoint(runId: RecordIdInput): Promise<PlanCheckpointRecord | null> {
332
- const checkpoints = await databaseService.findMany(
333
- TABLES.PLAN_CHECKPOINT,
334
- { runId: ensureRecordId(runId, TABLES.PLAN_RUN) },
335
- PlanCheckpointSchema,
336
- { orderBy: 'sequence', orderDir: 'DESC', limit: 1 },
337
- )
338
-
339
- return checkpoints.at(0) ?? null
340
- }
341
-
342
- async getNextCheckpointSequence(runId: RecordIdInput): Promise<number> {
343
- const latestCheckpoint = await this.getLatestCheckpoint(runId)
344
- return latestCheckpoint ? latestCheckpoint.sequence + 1 : 1
345
- }
346
-
347
- async listEvents(runId: RecordIdInput, limit = 20): Promise<PlanEventRecord[]> {
348
- return (
349
- await databaseService.findMany(
350
- TABLES.PLAN_EVENT,
351
- { runId: ensureRecordId(runId, TABLES.PLAN_RUN) },
352
- PlanEventSchema,
353
- { orderBy: 'createdAt', orderDir: 'DESC', limit },
354
- )
355
- ).reverse()
356
- }
357
-
358
- async toSerializablePlan(
359
- run: PlanRunRecord,
360
- options?: {
361
- includeArtifacts?: boolean
362
- includeApprovals?: boolean
363
- includeCheckpoints?: boolean
364
- includeEvents?: boolean
365
- includeValidationIssues?: boolean
366
- /** When true, non-active/ready nodes are summarized (id, label, status, owner, objective, edges). Reduces prompt tokens. */
367
- slim?: boolean
368
- },
369
- ): Promise<SerializableExecutionPlan> {
370
- const slim = options?.slim === true
371
- const spec = await this.getPlanSpecById(run.planSpecId)
372
- const nodeSpecs = await this.listNodeSpecs(spec.id)
373
- const nodeRuns = await this.listNodeRuns(run.id)
374
- const artifacts = options?.includeArtifacts === false ? [] : await this.listArtifacts(run.id)
375
- const lineageArtifacts = options?.includeArtifacts === false || slim ? [] : await this.collectLineageArtifacts(run)
376
- const approvals = options?.includeApprovals === false || slim ? [] : await this.listApprovals(run.id)
377
- const validationIssues =
378
- options?.includeValidationIssues === false || slim
379
- ? []
380
- : await this.listValidationIssues({ runId: run.id, planSpecId: spec.id })
381
- const latestCheckpoint = options?.includeCheckpoints ? await this.getLatestCheckpoint(run.id) : null
382
- const eventLimit = slim ? 5 : 20
383
- const recentEvents = options?.includeEvents === false ? [] : await this.listEvents(run.id, eventLimit)
384
- const nodeRunsById = new Map(nodeRuns.map((nodeRun) => [nodeRun.nodeId, nodeRun]))
385
- const activeNodeIds = new Set(run.currentNodeId ? [run.currentNodeId] : [])
386
- const readyNodeIds = new Set(run.readyNodeIds)
387
-
388
- const nodes: SerializablePlanNode[] = nodeSpecs.map((nodeSpec) => {
389
- const nodeRun = nodeRunsById.get(nodeSpec.nodeId)
390
- if (!nodeRun) {
391
- throw new Error(
392
- `Plan run ${recordIdToString(run.id, TABLES.PLAN_RUN)} is missing node run "${nodeSpec.nodeId}".`,
393
- )
394
- }
395
-
396
- const isActiveOrReady = activeNodeIds.has(nodeSpec.nodeId) || readyNodeIds.has(nodeSpec.nodeId)
397
-
398
- // Slim mode: non-active/ready nodes get summary only (used for prompt injection via JSON.stringify).
399
- // The cast is safe — this data is only consumed by formatExecutionPlansForPrompt, not by Zod validation.
400
- // executionPlanQuery calls toSerializablePlan without slim=true for full inspection payloads.
401
- if (slim && !isActiveOrReady) {
402
- return {
403
- id: nodeSpec.nodeId,
404
- type: nodeSpec.type,
405
- label: nodeSpec.label,
406
- owner: { executorType: nodeSpec.owner.executorType, ref: nodeSpec.owner.ref },
407
- objective: nodeSpec.objective,
408
- status: nodeRun.status,
409
- upstreamNodeIds: [...nodeSpec.upstreamNodeIds],
410
- downstreamNodeIds: [...nodeSpec.downstreamNodeIds],
411
- ...(nodeRun.completedAt ? { completedAt: toOptionalIsoDateTimeString(nodeRun.completedAt) } : {}),
412
- } as SerializablePlanNode
413
- }
414
-
415
- return {
416
- id: nodeSpec.nodeId,
417
- type: nodeSpec.type,
418
- label: nodeSpec.label,
419
- owner: nodeSpec.owner,
420
- objective: nodeSpec.objective,
421
- instructions: nodeSpec.instructions,
422
- inputSchemaRef: nodeSpec.inputSchemaRef,
423
- outputSchemaRef: nodeSpec.outputSchemaRef,
424
- deliverables: [...nodeSpec.deliverables],
425
- successCriteria: [...nodeSpec.successCriteria],
426
- completionChecks: [...nodeSpec.completionChecks],
427
- retryPolicy: { ...nodeSpec.retryPolicy, retryOn: [...nodeSpec.retryPolicy.retryOn] },
428
- failurePolicy: [...nodeSpec.failurePolicy],
429
- timeoutMs: nodeSpec.timeoutMs,
430
- toolPolicy: { allow: [...nodeSpec.toolPolicy.allow], deny: [...nodeSpec.toolPolicy.deny] },
431
- contextPolicy: {
432
- retrievalScopes: [...nodeSpec.contextPolicy.retrievalScopes],
433
- attachmentPolicy: nodeSpec.contextPolicy.attachmentPolicy,
434
- webPolicy: nodeSpec.contextPolicy.webPolicy,
435
- },
436
- executionVisibility: nodeSpec.executionVisibility,
437
- schedule: nodeSpec.schedule,
438
- deadline: nodeSpec.deadline,
439
- escalation: nodeSpec.escalation,
440
- monitoringConfig: nodeSpec.monitoringConfig,
441
- delayAfterPredecessorMs: nodeSpec.delayAfterPredecessorMs,
442
- deliberationConfig: nodeSpec.deliberationConfig,
443
- status: nodeRun.status,
444
- attemptCount: nodeRun.attemptCount,
445
- retryCount: nodeRun.retryCount,
446
- resolvedInput: nodeRun.resolvedInput,
447
- latestStructuredOutput: nodeRun.latestStructuredOutput,
448
- latestNotes: nodeRun.latestNotes,
449
- blockedReason: nodeRun.blockedReason,
450
- failureClass: nodeRun.failureClass,
451
- upstreamNodeIds: [...nodeSpec.upstreamNodeIds],
452
- downstreamNodeIds: [...nodeSpec.downstreamNodeIds],
453
- readyAt: toOptionalIsoDateTimeString(nodeRun.readyAt),
454
- startedAt: toOptionalIsoDateTimeString(nodeRun.startedAt),
455
- completedAt: toOptionalIsoDateTimeString(nodeRun.completedAt),
456
- }
457
- })
458
-
459
- return {
460
- specId: recordIdToString(spec.id, TABLES.PLAN_SPEC),
461
- runId: recordIdToString(run.id, TABLES.PLAN_RUN),
462
- threadId: recordIdToString(run.threadId, TABLES.THREAD),
463
- sourceThreadId: run.sourceThreadId ? recordIdToString(run.sourceThreadId, TABLES.THREAD) : undefined,
464
- organizationId: recordIdToString(run.organizationId, TABLES.ORGANIZATION),
465
- title: spec.title,
466
- objective: spec.objective,
467
- version: spec.version,
468
- status: run.status,
469
- leadAgentId: run.leadAgentId,
470
- createdByAgentId: run.createdByAgentId,
471
- defaultExecutionVisibility: spec.defaultExecutionVisibility,
472
- executionMode: spec.executionMode,
473
- schemaRegistry: slim ? {} : structuredClone(spec.schemaRegistry),
474
- entryNodeIds: [...spec.entryNodeIds],
475
- edges: [...spec.edges],
476
- schedule: spec.schedule,
477
- activeNodeIds: run.currentNodeId ? [run.currentNodeId] : [],
478
- readyNodeIds: [...run.readyNodeIds],
479
- waitingNodeId: run.waitingNodeId,
480
- replacedRunId: run.replacedRunId ? recordIdToString(run.replacedRunId, TABLES.PLAN_RUN) : undefined,
481
- failureCount: run.failureCount,
482
- startedAt: toOptionalIsoDateTimeString(run.startedAt),
483
- completedAt: toOptionalIsoDateTimeString(run.completedAt),
484
- progress: buildProgress(nodeRuns),
485
- nodes,
486
- artifacts: artifacts.map(serializeArtifact),
487
- lineageArtifacts,
488
- validationIssues: validationIssues.map(serializeValidationIssue),
489
- approvals: approvals.map(serializeApproval),
490
- latestCheckpoint: latestCheckpoint ? serializeCheckpoint(latestCheckpoint) : null,
491
- recentEvents: recentEvents.map(serializeEvent),
492
- }
493
- }
494
-
495
- private async collectLineageArtifacts(run: PlanRunRecord): Promise<SerializablePlanArtifact[]> {
496
- const lineageArtifacts: SerializablePlanArtifact[] = []
497
- let currentRunId = run.replacedRunId ? ensureRecordId(run.replacedRunId, TABLES.PLAN_RUN) : null
498
- let depth = 0
499
-
500
- while (currentRunId && depth < 5) {
501
- const previousRun = await databaseService.findOne(TABLES.PLAN_RUN, { id: currentRunId }, PlanRunSchema)
502
- if (!previousRun) break
503
-
504
- const artifacts = await this.listArtifacts(previousRun.id)
505
- lineageArtifacts.unshift(...artifacts.map(serializeArtifact))
506
-
507
- currentRunId = previousRun.replacedRunId ? ensureRecordId(previousRun.replacedRunId, TABLES.PLAN_RUN) : null
508
- depth += 1
509
- }
510
-
511
- return lineageArtifacts
512
- }
513
- }
514
-
515
- export const planRunService = new PlanRunService()