@lota-sdk/core 0.4.7 → 0.4.9

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 (259) hide show
  1. package/package.json +11 -12
  2. package/src/ai/embedding-cache.ts +94 -22
  3. package/src/ai-gateway/ai-gateway.ts +738 -223
  4. package/src/config/agent-defaults.ts +176 -75
  5. package/src/config/agent-types.ts +54 -4
  6. package/src/config/constants.ts +8 -2
  7. package/src/config/logger.ts +286 -19
  8. package/src/config/model-constants.ts +1 -0
  9. package/src/config/thread-defaults.ts +33 -21
  10. package/src/create-runtime.ts +725 -383
  11. package/src/db/base.service.ts +52 -28
  12. package/src/db/cursor-pagination.ts +71 -30
  13. package/src/db/memory-store.helpers.ts +4 -7
  14. package/src/db/memory-store.ts +856 -598
  15. package/src/db/memory.ts +398 -275
  16. package/src/db/record-id.ts +32 -10
  17. package/src/db/schema-fingerprint.ts +30 -12
  18. package/src/db/service-normalization.ts +255 -0
  19. package/src/db/service.ts +726 -761
  20. package/src/db/startup.ts +140 -66
  21. package/src/db/transaction-conflict.ts +15 -0
  22. package/src/effect/awaitable-effect.ts +87 -0
  23. package/src/effect/errors.ts +121 -0
  24. package/src/effect/helpers.ts +98 -0
  25. package/src/effect/index.ts +22 -0
  26. package/src/effect/layers.ts +228 -0
  27. package/src/effect/runtime-ref.ts +25 -0
  28. package/src/effect/runtime.ts +31 -0
  29. package/src/effect/services.ts +57 -0
  30. package/src/effect/zod.ts +43 -0
  31. package/src/embeddings/provider.ts +122 -71
  32. package/src/index.ts +46 -1
  33. package/src/openrouter/direct-provider.ts +29 -0
  34. package/src/queues/autonomous-job.queue.ts +130 -74
  35. package/src/queues/context-compaction.queue.ts +60 -15
  36. package/src/queues/delayed-node-promotion.queue.ts +52 -15
  37. package/src/queues/document-processor.queue.ts +52 -77
  38. package/src/queues/memory-consolidation.queue.ts +47 -32
  39. package/src/queues/organization-learning.queue.ts +13 -4
  40. package/src/queues/plan-agent-heartbeat.queue.ts +65 -21
  41. package/src/queues/plan-scheduler.queue.ts +107 -31
  42. package/src/queues/post-chat-memory.queue.ts +66 -24
  43. package/src/queues/queue-factory.ts +142 -52
  44. package/src/queues/standalone-worker.ts +39 -0
  45. package/src/queues/title-generation.queue.ts +54 -9
  46. package/src/redis/connection.ts +84 -32
  47. package/src/redis/index.ts +6 -8
  48. package/src/redis/org-memory-lock.ts +60 -27
  49. package/src/redis/redis-lease-lock.ts +200 -121
  50. package/src/redis/runtime-connection.ts +10 -0
  51. package/src/redis/stream-context.ts +84 -46
  52. package/src/runtime/agent-identity-overrides.ts +2 -2
  53. package/src/runtime/agent-runtime-policy.ts +4 -1
  54. package/src/runtime/agent-stream-helpers.ts +20 -9
  55. package/src/runtime/chat-run-orchestration.ts +102 -19
  56. package/src/runtime/chat-run-registry.ts +36 -2
  57. package/src/runtime/context-compaction/context-compaction-runtime.ts +107 -0
  58. package/src/runtime/{context-compaction.ts → context-compaction/context-compaction.ts} +114 -91
  59. package/src/runtime/execution-plan-visibility.ts +2 -2
  60. package/src/runtime/execution-plan.ts +42 -15
  61. package/src/runtime/graph-designer.ts +11 -7
  62. package/src/runtime/helper-model.ts +135 -48
  63. package/src/runtime/index.ts +7 -7
  64. package/src/runtime/indexed-repositories-policy.ts +3 -3
  65. package/src/runtime/{memory-block.ts → memory/memory-block.ts} +40 -36
  66. package/src/runtime/{memory-digest-policy.ts → memory/memory-digest-policy.ts} +1 -1
  67. package/src/runtime/{memory-pipeline.ts → memory/memory-pipeline.ts} +1 -1
  68. package/src/runtime/{memory-prompts-fact.ts → memory/memory-prompts-fact.ts} +2 -2
  69. package/src/runtime/{memory-scope.ts → memory/memory-scope.ts} +12 -6
  70. package/src/runtime/plugin-resolution.ts +144 -24
  71. package/src/runtime/plugin-types.ts +9 -1
  72. package/src/runtime/post-turn-side-effects.ts +197 -130
  73. package/src/runtime/retrieval-adapters.ts +38 -4
  74. package/src/runtime/runtime-config.ts +165 -61
  75. package/src/runtime/runtime-extensions.ts +21 -34
  76. package/src/runtime/social-chat/social-chat-agent-runner.ts +157 -0
  77. package/src/runtime/{social-chat-history.ts → social-chat/social-chat-history.ts} +42 -20
  78. package/src/runtime/social-chat/social-chat.ts +594 -0
  79. package/src/runtime/specialist-runner.ts +36 -10
  80. package/src/runtime/team-consultation/team-consultation-orchestrator.ts +427 -0
  81. package/src/runtime/{team-consultation-prompts.ts → team-consultation/team-consultation-prompts.ts} +6 -2
  82. package/src/runtime/thread-chat-helpers.ts +2 -2
  83. package/src/runtime/thread-plan-turn.ts +2 -1
  84. package/src/runtime/thread-turn-context.ts +172 -94
  85. package/src/runtime/turn-lifecycle.ts +93 -27
  86. package/src/services/agent-activity.service.ts +287 -203
  87. package/src/services/agent-executor.service.ts +329 -217
  88. package/src/services/artifact.service.ts +225 -148
  89. package/src/services/attachment.service.ts +137 -115
  90. package/src/services/autonomous-job.service.ts +888 -491
  91. package/src/services/chat-run-registry.service.ts +11 -1
  92. package/src/services/context-compaction.service.ts +136 -86
  93. package/src/services/document-chunk.service.ts +162 -90
  94. package/src/services/execution-plan/execution-plan-approval.ts +26 -0
  95. package/src/services/execution-plan/execution-plan-context.ts +29 -0
  96. package/src/services/execution-plan/execution-plan-graph.ts +256 -0
  97. package/src/services/execution-plan/execution-plan-schedule.ts +84 -0
  98. package/src/services/execution-plan/execution-plan-spec.ts +75 -0
  99. package/src/services/execution-plan/execution-plan.service.ts +1041 -0
  100. package/src/services/feedback-loop.service.ts +132 -76
  101. package/src/services/global-orchestrator.service.ts +80 -170
  102. package/src/services/graph-full-routing.ts +182 -0
  103. package/src/services/index.ts +18 -20
  104. package/src/services/institutional-memory.service.ts +220 -123
  105. package/src/services/learned-skill.service.ts +364 -259
  106. package/src/services/memory/memory-conversation.ts +95 -0
  107. package/src/services/memory/memory-org-memory.ts +39 -0
  108. package/src/services/memory/memory-preseeded.ts +80 -0
  109. package/src/services/memory/memory-rerank.ts +297 -0
  110. package/src/services/{memory-utils.ts → memory/memory-utils.ts} +5 -5
  111. package/src/services/memory/memory.service.ts +692 -0
  112. package/src/services/memory/rerank.service.ts +209 -0
  113. package/src/services/monitoring-window.service.ts +92 -70
  114. package/src/services/mutating-approval.service.ts +62 -53
  115. package/src/services/node-workspace.service.ts +141 -98
  116. package/src/services/notification.service.ts +17 -16
  117. package/src/services/organization-member.service.ts +120 -66
  118. package/src/services/organization.service.ts +144 -51
  119. package/src/services/ownership-dispatcher.service.ts +415 -264
  120. package/src/services/plan/plan-agent-heartbeat.service.ts +234 -0
  121. package/src/services/plan/plan-agent-query.service.ts +322 -0
  122. package/src/services/plan/plan-approval.service.ts +102 -0
  123. package/src/services/plan/plan-artifact.service.ts +60 -0
  124. package/src/services/plan/plan-builder.service.ts +76 -0
  125. package/src/services/plan/plan-checkpoint.service.ts +103 -0
  126. package/src/services/{plan-compiler.service.ts → plan/plan-compiler.service.ts} +26 -9
  127. package/src/services/plan/plan-completion-side-effects.ts +175 -0
  128. package/src/services/plan/plan-coordination.service.ts +181 -0
  129. package/src/services/plan/plan-cycle.service.ts +398 -0
  130. package/src/services/plan/plan-deadline.service.ts +547 -0
  131. package/src/services/plan/plan-event-delivery.service.ts +261 -0
  132. package/src/services/plan/plan-executor-context.ts +35 -0
  133. package/src/services/plan/plan-executor-graph.ts +475 -0
  134. package/src/services/plan/plan-executor-helpers.ts +322 -0
  135. package/src/services/plan/plan-executor-persistence.ts +209 -0
  136. package/src/services/plan/plan-executor.service.ts +1654 -0
  137. package/src/services/{plan-helpers.ts → plan/plan-helpers.ts} +1 -1
  138. package/src/services/{plan-run-data.ts → plan/plan-run-data.ts} +4 -4
  139. package/src/services/plan/plan-run-serialization.ts +15 -0
  140. package/src/services/plan/plan-run.service.ts +644 -0
  141. package/src/services/plan/plan-scheduler.service.ts +385 -0
  142. package/src/services/plan/plan-template.service.ts +224 -0
  143. package/src/services/plan/plan-transaction-events.ts +33 -0
  144. package/src/services/plan/plan-validator.service.ts +907 -0
  145. package/src/services/plan/plan-workspace.service.ts +125 -0
  146. package/src/services/plugin-executor.service.ts +97 -68
  147. package/src/services/quality-metrics.service.ts +112 -94
  148. package/src/services/queue-job.service.ts +296 -230
  149. package/src/services/recent-activity-title.service.ts +65 -36
  150. package/src/services/recent-activity.service.ts +274 -259
  151. package/src/services/skill-resolver.service.ts +38 -12
  152. package/src/services/social-chat-history.service.ts +176 -125
  153. package/src/services/system-executor.service.ts +91 -61
  154. package/src/services/thread/thread-active-run.ts +203 -0
  155. package/src/services/thread/thread-bootstrap.ts +369 -0
  156. package/src/services/thread/thread-listing.ts +198 -0
  157. package/src/services/thread/thread-memory-block.ts +117 -0
  158. package/src/services/thread/thread-message.service.ts +363 -0
  159. package/src/services/thread/thread-record-store.ts +155 -0
  160. package/src/services/thread/thread-title.service.ts +74 -0
  161. package/src/services/thread/thread-turn-execution.ts +280 -0
  162. package/src/services/thread/thread-turn-message-context.ts +73 -0
  163. package/src/services/thread/thread-turn-preparation.service.ts +1146 -0
  164. package/src/services/thread/thread-turn-streaming.ts +402 -0
  165. package/src/services/thread/thread-turn-tracing.ts +35 -0
  166. package/src/services/thread/thread-turn.ts +343 -0
  167. package/src/services/thread/thread.service.ts +335 -0
  168. package/src/services/user.service.ts +82 -32
  169. package/src/services/write-intent-validator.service.ts +63 -51
  170. package/src/storage/attachment-parser.ts +69 -27
  171. package/src/storage/attachment-storage.service.ts +331 -275
  172. package/src/storage/generated-document-storage.service.ts +66 -34
  173. package/src/system-agents/agent-result.ts +3 -1
  174. package/src/system-agents/context-compaction.agent.ts +2 -2
  175. package/src/system-agents/delegated-agent-factory.ts +159 -90
  176. package/src/system-agents/memory-reranker.agent.ts +2 -2
  177. package/src/system-agents/memory.agent.ts +2 -2
  178. package/src/system-agents/recent-activity-title-refiner.agent.ts +2 -2
  179. package/src/system-agents/regular-chat-memory-digest.agent.ts +2 -2
  180. package/src/system-agents/skill-extractor.agent.ts +2 -2
  181. package/src/system-agents/skill-manager.agent.ts +2 -2
  182. package/src/system-agents/thread-router.agent.ts +157 -113
  183. package/src/system-agents/title-generator.agent.ts +2 -2
  184. package/src/tools/execution-plan.tool.ts +220 -161
  185. package/src/tools/fetch-webpage.tool.ts +21 -17
  186. package/src/tools/firecrawl-client.ts +16 -6
  187. package/src/tools/index.ts +1 -0
  188. package/src/tools/memory-block.tool.ts +14 -6
  189. package/src/tools/plan-approval.tool.ts +49 -47
  190. package/src/tools/read-file-parts.tool.ts +44 -33
  191. package/src/tools/remember-memory.tool.ts +65 -45
  192. package/src/tools/search-web.tool.ts +26 -22
  193. package/src/tools/search.tool.ts +41 -29
  194. package/src/tools/team-think.tool.ts +124 -83
  195. package/src/tools/user-questions.tool.ts +4 -3
  196. package/src/tools/web-tool-shared.ts +6 -0
  197. package/src/utils/async.ts +17 -23
  198. package/src/utils/crypto.ts +21 -0
  199. package/src/utils/date-time.ts +40 -1
  200. package/src/utils/errors.ts +95 -16
  201. package/src/utils/hono-error-handler.ts +24 -39
  202. package/src/utils/index.ts +2 -1
  203. package/src/utils/null-proto-record.ts +41 -0
  204. package/src/utils/sse-keepalive.ts +124 -21
  205. package/src/workers/bootstrap.ts +186 -51
  206. package/src/workers/memory-consolidation.worker.ts +325 -237
  207. package/src/workers/organization-learning.worker.ts +50 -16
  208. package/src/workers/regular-chat-memory-digest.helpers.ts +28 -27
  209. package/src/workers/regular-chat-memory-digest.runner.ts +175 -114
  210. package/src/workers/skill-extraction.runner.ts +176 -93
  211. package/src/workers/utils/file-section-chunker.ts +8 -10
  212. package/src/workers/utils/repo-structure-extractor.ts +349 -260
  213. package/src/workers/utils/repomix-file-sections.ts +2 -2
  214. package/src/workers/utils/thread-message-query.ts +97 -38
  215. package/src/workers/worker-utils.ts +56 -31
  216. package/src/config/debug-logger.ts +0 -47
  217. package/src/redis/connection-accessor.ts +0 -26
  218. package/src/runtime/context-compaction-runtime.ts +0 -87
  219. package/src/runtime/social-chat-agent-runner.ts +0 -118
  220. package/src/runtime/social-chat.ts +0 -516
  221. package/src/runtime/team-consultation-orchestrator.ts +0 -272
  222. package/src/services/adaptive-playbook.service.ts +0 -152
  223. package/src/services/artifact-provenance.service.ts +0 -172
  224. package/src/services/chat-attachments.service.ts +0 -17
  225. package/src/services/context-compaction-runtime.singleton.ts +0 -13
  226. package/src/services/execution-plan.service.ts +0 -1118
  227. package/src/services/memory.service.ts +0 -844
  228. package/src/services/plan-agent-heartbeat.service.ts +0 -136
  229. package/src/services/plan-agent-query.service.ts +0 -267
  230. package/src/services/plan-approval.service.ts +0 -83
  231. package/src/services/plan-artifact.service.ts +0 -50
  232. package/src/services/plan-builder.service.ts +0 -67
  233. package/src/services/plan-checkpoint.service.ts +0 -81
  234. package/src/services/plan-completion-side-effects.ts +0 -80
  235. package/src/services/plan-coordination.service.ts +0 -157
  236. package/src/services/plan-cycle.service.ts +0 -284
  237. package/src/services/plan-deadline.service.ts +0 -430
  238. package/src/services/plan-event-delivery.service.ts +0 -166
  239. package/src/services/plan-executor.service.ts +0 -1950
  240. package/src/services/plan-run.service.ts +0 -515
  241. package/src/services/plan-scheduler.service.ts +0 -240
  242. package/src/services/plan-template.service.ts +0 -177
  243. package/src/services/plan-validator.service.ts +0 -818
  244. package/src/services/plan-workspace.service.ts +0 -83
  245. package/src/services/thread-message.service.ts +0 -275
  246. package/src/services/thread-plan-registry.service.ts +0 -22
  247. package/src/services/thread-title.service.ts +0 -39
  248. package/src/services/thread-turn-preparation.service.ts +0 -1147
  249. package/src/services/thread-turn.ts +0 -172
  250. package/src/services/thread.service.ts +0 -869
  251. package/src/utils/env.ts +0 -8
  252. /package/src/runtime/{context-compaction-constants.ts → context-compaction/context-compaction-constants.ts} +0 -0
  253. /package/src/runtime/{memory-format.ts → memory/memory-format.ts} +0 -0
  254. /package/src/runtime/{memory-prompts-parse.ts → memory/memory-prompts-parse.ts} +0 -0
  255. /package/src/runtime/{memory-prompts-update.ts → memory/memory-prompts-update.ts} +0 -0
  256. /package/src/runtime/{social-chat-prompts.ts → social-chat/social-chat-prompts.ts} +0 -0
  257. /package/src/services/{plan-node-spec.ts → plan/plan-node-spec.ts} +0 -0
  258. /package/src/services/{thread-constants.ts → thread/thread-constants.ts} +0 -0
  259. /package/src/services/{thread.types.ts → thread/thread.types.ts} +0 -0
@@ -0,0 +1,256 @@
1
+ import type { PlanEventRecord, PlanNodeRunRecord, PlanNodeSpecRecord, PlanSpecRecord } from '@lota-sdk/shared'
2
+ import {
3
+ PlanCheckpointSchema,
4
+ PlanEventSchema,
5
+ PlanNodeRunSchema,
6
+ PlanNodeSpecRecordSchema,
7
+ PlanRunSchema,
8
+ } from '@lota-sdk/shared'
9
+ import { Effect } from 'effect'
10
+ import { RecordId } from 'surrealdb'
11
+
12
+ import type { RecordIdInput } from '../../db/record-id'
13
+ import { ensureRecordId, recordIdToString } from '../../db/record-id'
14
+ import type { DatabaseTransaction } from '../../db/service'
15
+ import { TABLES } from '../../db/tables'
16
+ import { runPromise } from '../../effect/runtime'
17
+ import { nowDate } from '../../utils/date-time'
18
+ import type { CompiledPlanNode } from '../plan/plan-compiler.service'
19
+ import type { syncRunGraph } from '../plan/plan-executor-graph'
20
+ import { toRunData } from '../plan/plan-run-data'
21
+
22
+ type SyncRunGraphParams = Parameters<typeof syncRunGraph>[1]
23
+ type SyncRunGraphResult = Awaited<ReturnType<typeof syncRunGraph>>
24
+
25
+ interface ExecutionPlanGraphExecutor {
26
+ syncRunGraph(params: SyncRunGraphParams): Promise<SyncRunGraphResult>
27
+ }
28
+
29
+ function buildNodeSpecCreateContent(compiledNode: CompiledPlanNode, planSpecId: RecordIdInput) {
30
+ return {
31
+ planSpecId: ensureRecordId(planSpecId, TABLES.PLAN_SPEC),
32
+ nodeId: compiledNode.node.id,
33
+ position: compiledNode.position,
34
+ type: compiledNode.node.type,
35
+ label: compiledNode.node.label,
36
+ owner: compiledNode.node.owner,
37
+ objective: compiledNode.node.objective,
38
+ instructions: compiledNode.node.instructions,
39
+ ...(compiledNode.node.inputSchemaRef ? { inputSchemaRef: compiledNode.node.inputSchemaRef } : {}),
40
+ ...(compiledNode.node.outputSchemaRef ? { outputSchemaRef: compiledNode.node.outputSchemaRef } : {}),
41
+ deliverables: [...compiledNode.node.deliverables],
42
+ successCriteria: [...compiledNode.node.successCriteria],
43
+ completionChecks: [...compiledNode.node.completionChecks],
44
+ retryPolicy: { ...compiledNode.node.retryPolicy, retryOn: [...compiledNode.node.retryPolicy.retryOn] },
45
+ failurePolicy: [...compiledNode.node.failurePolicy],
46
+ ...(compiledNode.node.timeoutMs ? { timeoutMs: compiledNode.node.timeoutMs } : {}),
47
+ toolPolicy: { allow: [...compiledNode.node.toolPolicy.allow], deny: [...compiledNode.node.toolPolicy.deny] },
48
+ contextPolicy: {
49
+ retrievalScopes: [...compiledNode.node.contextPolicy.retrievalScopes],
50
+ attachmentPolicy: compiledNode.node.contextPolicy.attachmentPolicy,
51
+ webPolicy: compiledNode.node.contextPolicy.webPolicy,
52
+ },
53
+ executionVisibility: compiledNode.node.executionVisibility,
54
+ ...(compiledNode.node.schedule ? { schedule: compiledNode.node.schedule } : {}),
55
+ ...(compiledNode.node.deadline ? { deadline: compiledNode.node.deadline } : {}),
56
+ ...(compiledNode.node.escalation ? { escalation: compiledNode.node.escalation } : {}),
57
+ ...(compiledNode.node.monitoringConfig ? { monitoringConfig: compiledNode.node.monitoringConfig } : {}),
58
+ ...(compiledNode.node.delayAfterPredecessorMs
59
+ ? { delayAfterPredecessorMs: compiledNode.node.delayAfterPredecessorMs }
60
+ : {}),
61
+ ...(compiledNode.node.deliberationConfig ? { deliberationConfig: compiledNode.node.deliberationConfig } : {}),
62
+ upstreamNodeIds: [...compiledNode.upstreamNodeIds],
63
+ downstreamNodeIds: [...compiledNode.downstreamNodeIds],
64
+ }
65
+ }
66
+
67
+ function buildNodeRunCreateContent(runId: RecordIdInput, planSpecId: RecordIdInput, nodeSpec: PlanNodeSpecRecord) {
68
+ return {
69
+ runId: ensureRecordId(runId, TABLES.PLAN_RUN),
70
+ planSpecId: ensureRecordId(planSpecId, TABLES.PLAN_SPEC),
71
+ nodeId: nodeSpec.nodeId,
72
+ status: 'pending' as const,
73
+ attemptCount: 0,
74
+ retryCount: 0,
75
+ }
76
+ }
77
+
78
+ function createNodeSpecs(tx: DatabaseTransaction, planSpecId: RecordIdInput, nodes: CompiledPlanNode[]) {
79
+ return Effect.gen(function* () {
80
+ const createdRecords: PlanNodeSpecRecord[] = []
81
+
82
+ // Sequential: SurrealDB transactions require ordered operations
83
+ for (const compiledNode of nodes) {
84
+ const nodeSpecId = new RecordId(TABLES.PLAN_NODE_SPEC, Bun.randomUUIDv7())
85
+ const created = yield* tx
86
+ .create(nodeSpecId)
87
+ .content(buildNodeSpecCreateContent(compiledNode, planSpecId))
88
+ .output('after')
89
+ createdRecords.push(PlanNodeSpecRecordSchema.parse(created))
90
+ }
91
+
92
+ return createdRecords
93
+ })
94
+ }
95
+
96
+ function createNodeRuns(
97
+ tx: DatabaseTransaction,
98
+ runId: RecordIdInput,
99
+ planSpecId: RecordIdInput,
100
+ nodeSpecs: PlanNodeSpecRecord[],
101
+ ) {
102
+ return Effect.gen(function* () {
103
+ const createdNodeRuns: PlanNodeRunRecord[] = []
104
+
105
+ // Sequential: SurrealDB transactions require ordered operations
106
+ for (const nodeSpec of nodeSpecs) {
107
+ const nodeRunId = new RecordId(TABLES.PLAN_NODE_RUN, Bun.randomUUIDv7())
108
+ const created = yield* tx
109
+ .create(nodeRunId)
110
+ .content(buildNodeRunCreateContent(runId, planSpecId, nodeSpec))
111
+ .output('after')
112
+ createdNodeRuns.push(PlanNodeRunSchema.parse(created))
113
+ }
114
+
115
+ return createdNodeRuns
116
+ })
117
+ }
118
+
119
+ export function createInitializedRunGraph(params: {
120
+ tx: DatabaseTransaction
121
+ runId: RecordIdInput
122
+ spec: PlanSpecRecord
123
+ organizationId: RecordIdInput
124
+ threadId: RecordIdInput
125
+ sourceThreadId?: RecordIdInput
126
+ leadAgentId: string
127
+ createdByAgentId?: string
128
+ requireApproval: boolean
129
+ nodes: CompiledPlanNode[]
130
+ emittedEvents: PlanEventRecord[]
131
+ createdEventType: 'plan-created' | 'plan-replaced'
132
+ createdEventMessage: string
133
+ createdEventDetail: Record<string, unknown>
134
+ checkpointReason: 'plan-created' | 'plan-replaced'
135
+ runPatch?: { replacedRunId?: RecordIdInput }
136
+ planExecutor: ExecutionPlanGraphExecutor
137
+ }) {
138
+ return runPromise(
139
+ Effect.gen(function* () {
140
+ const nodeSpecs = yield* createNodeSpecs(params.tx, params.spec.id, params.nodes)
141
+ const run = PlanRunSchema.parse(
142
+ yield* params.tx
143
+ .create(ensureRecordId(params.runId, TABLES.PLAN_RUN))
144
+ .content({
145
+ planSpecId: ensureRecordId(params.spec.id, TABLES.PLAN_SPEC),
146
+ organizationId: ensureRecordId(params.organizationId, TABLES.ORGANIZATION),
147
+ threadId: ensureRecordId(params.threadId, TABLES.THREAD),
148
+ ...(params.sourceThreadId ? { sourceThreadId: ensureRecordId(params.sourceThreadId, TABLES.THREAD) } : {}),
149
+ leadAgentId: params.leadAgentId,
150
+ ...(params.createdByAgentId ? { createdByAgentId: params.createdByAgentId } : {}),
151
+ status: params.requireApproval ? 'pending-approval' : 'running',
152
+ readyNodeIds: [],
153
+ failureCount: 0,
154
+ ...(params.runPatch?.replacedRunId
155
+ ? { replacedRunId: ensureRecordId(params.runPatch.replacedRunId, TABLES.PLAN_RUN) }
156
+ : {}),
157
+ ...(params.requireApproval ? {} : { startedAt: nowDate() }),
158
+ })
159
+ .output('after'),
160
+ )
161
+
162
+ const nodeRuns = yield* createNodeRuns(params.tx, run.id, params.spec.id, nodeSpecs)
163
+ const synced = params.requireApproval
164
+ ? { run, nodeRuns }
165
+ : yield* Effect.tryPromise(() =>
166
+ params.planExecutor.syncRunGraph({
167
+ tx: params.tx,
168
+ run,
169
+ spec: params.spec,
170
+ nodeSpecs,
171
+ nodeRuns,
172
+ artifacts: [],
173
+ emittedBy: params.leadAgentId,
174
+ capturedEvents: params.emittedEvents,
175
+ }),
176
+ )
177
+
178
+ const event = yield* params.tx
179
+ .create(new RecordId(TABLES.PLAN_EVENT, Bun.randomUUIDv7()))
180
+ .content({
181
+ planSpecId: ensureRecordId(params.spec.id, TABLES.PLAN_SPEC),
182
+ runId: ensureRecordId(synced.run.id, TABLES.PLAN_RUN),
183
+ eventType: params.createdEventType,
184
+ message: params.createdEventMessage,
185
+ emittedBy: params.leadAgentId,
186
+ detail: { ...params.createdEventDetail, nodeCount: nodeSpecs.length },
187
+ })
188
+ .output('after')
189
+ params.emittedEvents.push(PlanEventSchema.parse(event))
190
+
191
+ if (params.requireApproval) {
192
+ const pendingApprovalEvent = yield* params.tx
193
+ .create(new RecordId(TABLES.PLAN_EVENT, Bun.randomUUIDv7()))
194
+ .content({
195
+ planSpecId: ensureRecordId(params.spec.id, TABLES.PLAN_SPEC),
196
+ runId: ensureRecordId(synced.run.id, TABLES.PLAN_RUN),
197
+ eventType: 'plan-pending-approval',
198
+ toStatus: synced.run.status,
199
+ message: `Execution plan "${params.spec.title}" is pending approval.`,
200
+ emittedBy: params.leadAgentId,
201
+ detail: { ...params.createdEventDetail, nodeCount: nodeSpecs.length },
202
+ })
203
+ .output('after')
204
+ params.emittedEvents.push(PlanEventSchema.parse(pendingApprovalEvent))
205
+ }
206
+
207
+ const checkpoint = PlanCheckpointSchema.parse(
208
+ yield* params.tx
209
+ .create(new RecordId(TABLES.PLAN_CHECKPOINT, Bun.randomUUIDv7()))
210
+ .content({
211
+ runId: ensureRecordId(synced.run.id, TABLES.PLAN_RUN),
212
+ sequence: 1,
213
+ runStatus: synced.run.status,
214
+ readyNodeIds: [...synced.run.readyNodeIds],
215
+ activeNodeIds: synced.run.currentNodeId ? [synced.run.currentNodeId] : [],
216
+ artifactIds: [],
217
+ lastCompletedNodeIds: synced.nodeRuns
218
+ .filter((nodeRun) => nodeRun.status === 'completed' || nodeRun.status === 'partial')
219
+ .map((nodeRun) => nodeRun.nodeId),
220
+ snapshot: {
221
+ reason: params.checkpointReason,
222
+ currentNodeId: synced.run.currentNodeId,
223
+ waitingNodeId: synced.run.waitingNodeId,
224
+ readyNodeIds: synced.run.readyNodeIds,
225
+ },
226
+ })
227
+ .output('after'),
228
+ )
229
+
230
+ const updatedRun = PlanRunSchema.parse(
231
+ yield* params.tx
232
+ .update(ensureRecordId(synced.run.id, TABLES.PLAN_RUN))
233
+ .content(toRunData(synced.run, { lastCheckpointId: checkpoint.id }))
234
+ .output('after'),
235
+ )
236
+
237
+ const checkpointEvent = yield* params.tx
238
+ .create(new RecordId(TABLES.PLAN_EVENT, Bun.randomUUIDv7()))
239
+ .content({
240
+ planSpecId: ensureRecordId(params.spec.id, TABLES.PLAN_SPEC),
241
+ runId: ensureRecordId(updatedRun.id, TABLES.PLAN_RUN),
242
+ eventType: 'checkpoint-saved',
243
+ message: 'Saved checkpoint 1.',
244
+ emittedBy: 'system',
245
+ detail: {
246
+ checkpointId: recordIdToString(checkpoint.id, TABLES.PLAN_CHECKPOINT),
247
+ reason: params.checkpointReason,
248
+ },
249
+ })
250
+ .output('after')
251
+ params.emittedEvents.push(PlanEventSchema.parse(checkpointEvent))
252
+
253
+ return updatedRun
254
+ }),
255
+ )
256
+ }
@@ -0,0 +1,84 @@
1
+ import type { PlanRunRecord } from '@lota-sdk/shared'
2
+ import { PlanRunSchema } from '@lota-sdk/shared'
3
+ import { Schema, Effect } from 'effect'
4
+
5
+ import type { RecordIdInput } from '../../db/record-id'
6
+ import { ensureRecordId } from '../../db/record-id'
7
+ import type { SurrealDBService } from '../../db/service'
8
+ import { TABLES } from '../../db/tables'
9
+ import { runPromise } from '../../effect/runtime'
10
+ import { toDatabaseDateTime } from '../../utils/date-time'
11
+ import { toRunData } from '../plan/plan-run-data'
12
+ import type { makePlanRunService } from '../plan/plan-run.service'
13
+ import type { makePlanSchedulerService } from '../plan/plan-scheduler.service'
14
+
15
+ class PlanScheduleAttachError extends Schema.TaggedErrorClass<PlanScheduleAttachError>()('PlanScheduleAttachError', {
16
+ cause: Schema.String,
17
+ }) {}
18
+
19
+ function toPlanScheduleAttachError(operation: string, cause: unknown) {
20
+ const detail = cause instanceof Error ? cause.message : String(cause)
21
+ return new PlanScheduleAttachError({ cause: `${operation}: ${detail}` })
22
+ }
23
+
24
+ function attachPlanScheduleIfNeededEffect(params: {
25
+ db: SurrealDBService
26
+ planRunService: ReturnType<typeof makePlanRunService>
27
+ planSchedulerService: ReturnType<typeof makePlanSchedulerService>
28
+ organizationId: RecordIdInput
29
+ threadId: RecordIdInput
30
+ runId: RecordIdInput
31
+ planSpecId: RecordIdInput
32
+ }) {
33
+ return Effect.gen(function* () {
34
+ const [run, spec] = yield* Effect.all([
35
+ params.planRunService
36
+ .getRunById(params.runId)
37
+ .pipe(Effect.mapError((cause) => toPlanScheduleAttachError('get-run-by-id', cause))),
38
+ params.planRunService
39
+ .getPlanSpecById(params.planSpecId)
40
+ .pipe(Effect.mapError((cause) => toPlanScheduleAttachError('get-plan-spec-by-id', cause))),
41
+ ])
42
+
43
+ const scheduleSpec = spec.schedule
44
+ if (!scheduleSpec || run.scheduleId) {
45
+ return run
46
+ }
47
+
48
+ const schedule = yield* params.planSchedulerService
49
+ .createSchedule({
50
+ organizationId: params.organizationId,
51
+ threadId: params.threadId,
52
+ planSpecId: params.planSpecId,
53
+ runId: params.runId,
54
+ scheduleSpec,
55
+ })
56
+ .pipe(Effect.mapError((cause) => toPlanScheduleAttachError('create-schedule', cause)))
57
+
58
+ const updatedRun = yield* params.db
59
+ .update(
60
+ TABLES.PLAN_RUN,
61
+ ensureRecordId(params.runId, TABLES.PLAN_RUN),
62
+ toRunData(run, {
63
+ scheduleId: schedule.id,
64
+ scheduledAt: schedule.nextFireAt ? toDatabaseDateTime(schedule.nextFireAt) : undefined,
65
+ }),
66
+ PlanRunSchema,
67
+ )
68
+ .pipe(Effect.mapError((cause) => toPlanScheduleAttachError('attach-plan-schedule', cause)))
69
+
70
+ return updatedRun ?? run
71
+ })
72
+ }
73
+
74
+ export function attachPlanScheduleIfNeeded(params: {
75
+ db: SurrealDBService
76
+ planRunService: ReturnType<typeof makePlanRunService>
77
+ planSchedulerService: ReturnType<typeof makePlanSchedulerService>
78
+ organizationId: RecordIdInput
79
+ threadId: RecordIdInput
80
+ runId: RecordIdInput
81
+ planSpecId: RecordIdInput
82
+ }): Promise<PlanRunRecord> {
83
+ return runPromise(attachPlanScheduleIfNeededEffect(params))
84
+ }
@@ -0,0 +1,75 @@
1
+ import type { PlanDraft, PlanSpecRecord } from '@lota-sdk/shared'
2
+
3
+ import type { RecordIdInput } from '../../db/record-id'
4
+ import { ensureRecordId } from '../../db/record-id'
5
+ import { TABLES } from '../../db/tables'
6
+ import { nowDate, toDatabaseDateTime } from '../../utils/date-time'
7
+
8
+ export function toSpecData(
9
+ spec: PlanSpecRecord,
10
+ patch: Partial<PlanSpecRecord> & { replacedSpecId?: RecordIdInput | null },
11
+ ) {
12
+ return {
13
+ organizationId: ensureRecordId(spec.organizationId, TABLES.ORGANIZATION),
14
+ threadId: ensureRecordId(spec.threadId, TABLES.THREAD),
15
+ title: patch.title ?? spec.title,
16
+ objective: patch.objective ?? spec.objective,
17
+ version: patch.version ?? spec.version,
18
+ status: patch.status ?? spec.status,
19
+ leadAgentId: patch.leadAgentId ?? spec.leadAgentId,
20
+ schemaRegistry: patch.schemaRegistry ? structuredClone(patch.schemaRegistry) : structuredClone(spec.schemaRegistry),
21
+ edges: patch.edges ? [...patch.edges] : [...spec.edges],
22
+ entryNodeIds: patch.entryNodeIds ? [...patch.entryNodeIds] : [...spec.entryNodeIds],
23
+ defaultExecutionVisibility: patch.defaultExecutionVisibility ?? spec.defaultExecutionVisibility,
24
+ executionMode: patch.executionMode ?? spec.executionMode,
25
+ ...(patch.schedule !== undefined ? { schedule: patch.schedule } : spec.schedule ? { schedule: spec.schedule } : {}),
26
+ ...(patch.dependencies !== undefined
27
+ ? { dependencies: patch.dependencies }
28
+ : spec.dependencies
29
+ ? { dependencies: spec.dependencies }
30
+ : {}),
31
+ ...(spec.contextEnrichments ? { contextEnrichments: spec.contextEnrichments } : {}),
32
+ ...(patch.replacedSpecId
33
+ ? { replacedSpecId: ensureRecordId(patch.replacedSpecId, TABLES.PLAN_SPEC) }
34
+ : spec.replacedSpecId
35
+ ? { replacedSpecId: ensureRecordId(spec.replacedSpecId, TABLES.PLAN_SPEC) }
36
+ : {}),
37
+ ...(patch.compiledAt !== undefined
38
+ ? { compiledAt: toDatabaseDateTime(patch.compiledAt) }
39
+ : spec.compiledAt
40
+ ? { compiledAt: toDatabaseDateTime(spec.compiledAt) }
41
+ : {}),
42
+ }
43
+ }
44
+
45
+ export function buildCompiledSpecCreateData(params: {
46
+ organizationId: RecordIdInput
47
+ threadId: RecordIdInput
48
+ leadAgentId: string
49
+ compiled: { draft: PlanDraft }
50
+ version: number
51
+ replacedSpecId?: RecordIdInput
52
+ contextEnrichments?: PlanSpecRecord['contextEnrichments']
53
+ }) {
54
+ return {
55
+ organizationId: ensureRecordId(params.organizationId, TABLES.ORGANIZATION),
56
+ threadId: ensureRecordId(params.threadId, TABLES.THREAD),
57
+ title: params.compiled.draft.title,
58
+ objective: params.compiled.draft.objective,
59
+ version: params.version,
60
+ status: 'compiled' as const,
61
+ leadAgentId: params.leadAgentId,
62
+ schemaRegistry: structuredClone(params.compiled.draft.schemas),
63
+ defaultExecutionVisibility: params.compiled.draft.defaultExecutionVisibility,
64
+ ...(params.contextEnrichments?.length
65
+ ? { contextEnrichments: params.contextEnrichments.map((entry) => ({ ...entry })) }
66
+ : {}),
67
+ edges: [...params.compiled.draft.edges],
68
+ entryNodeIds: [...(params.compiled.draft.entryNodeIds ?? [])],
69
+ executionMode: params.compiled.draft.executionMode ?? 'linear',
70
+ ...(params.compiled.draft.schedule ? { schedule: params.compiled.draft.schedule } : {}),
71
+ ...(params.compiled.draft.dependencies ? { dependencies: params.compiled.draft.dependencies } : {}),
72
+ ...(params.replacedSpecId ? { replacedSpecId: ensureRecordId(params.replacedSpecId, TABLES.PLAN_SPEC) } : {}),
73
+ compiledAt: nowDate(),
74
+ }
75
+ }