@lota-sdk/core 0.4.9 → 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.
- package/package.json +2 -2
- package/src/ai/embedding-cache.ts +3 -1
- package/src/ai-gateway/ai-gateway.ts +38 -10
- package/src/config/agent-defaults.ts +22 -9
- package/src/config/agent-types.ts +1 -1
- package/src/config/background-processing.ts +1 -1
- package/src/config/index.ts +0 -1
- package/src/config/logger.ts +20 -7
- package/src/config/thread-defaults.ts +12 -4
- package/src/create-runtime.ts +69 -656
- package/src/db/memory-query-builder.ts +2 -1
- package/src/db/memory-store.ts +29 -20
- package/src/db/memory.ts +188 -195
- package/src/db/service-normalization.ts +97 -64
- package/src/db/service.ts +706 -538
- package/src/db/startup.ts +30 -19
- package/src/effect/awaitable-effect.ts +46 -37
- package/src/effect/helpers.ts +30 -5
- package/src/effect/index.ts +7 -5
- package/src/effect/layers.ts +82 -72
- package/src/effect/runtime.ts +18 -3
- package/src/effect/services.ts +15 -11
- package/src/embeddings/provider.ts +65 -66
- package/src/index.ts +13 -11
- package/src/queues/autonomous-job.queue.ts +59 -71
- package/src/queues/context-compaction.queue.ts +6 -18
- package/src/queues/delayed-node-promotion.queue.ts +9 -17
- package/src/queues/organization-learning.queue.ts +17 -4
- package/src/queues/plan-agent-heartbeat.queue.ts +23 -20
- package/src/queues/plan-scheduler.queue.ts +6 -18
- package/src/queues/post-chat-memory.queue.ts +6 -18
- package/src/queues/queue-factory.ts +128 -50
- package/src/queues/title-generation.queue.ts +6 -17
- package/src/redis/connection.ts +181 -164
- package/src/redis/runtime-connection.ts +13 -3
- package/src/redis/stream-context.ts +17 -9
- package/src/runtime/agent-runtime-policy.ts +1 -1
- package/src/runtime/agent-stream-helpers.ts +15 -11
- package/src/runtime/chat-run-orchestration.ts +1 -1
- package/src/runtime/context-compaction/context-compaction-runtime.ts +1 -1
- package/src/runtime/context-compaction/context-compaction.ts +126 -82
- package/src/runtime/domain-layer.ts +192 -0
- package/src/runtime/graph-designer.ts +15 -7
- package/src/runtime/helper-model.ts +8 -4
- package/src/runtime/index.ts +0 -1
- package/src/runtime/memory/memory-block.ts +19 -9
- package/src/runtime/memory/memory-pipeline.ts +53 -66
- package/src/runtime/memory/memory-scope.ts +33 -29
- package/src/runtime/plugin-resolution.ts +33 -54
- package/src/runtime/post-turn-side-effects.ts +6 -26
- package/src/runtime/retrieval-adapters.ts +4 -4
- package/src/runtime/runtime-accessors.ts +92 -0
- package/src/runtime/runtime-config.ts +3 -3
- package/src/runtime/runtime-extensions.ts +20 -9
- package/src/runtime/runtime-lifecycle.ts +124 -0
- package/src/runtime/runtime-services.ts +386 -0
- package/src/runtime/runtime-token.ts +47 -0
- package/src/runtime/social-chat/social-chat-agent-runner.ts +7 -5
- package/src/runtime/social-chat/social-chat-history.ts +21 -12
- package/src/runtime/social-chat/social-chat.ts +401 -365
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +58 -52
- package/src/runtime/thread-turn-context.ts +21 -27
- package/src/services/agent-activity.service.ts +1 -1
- package/src/services/agent-executor.service.ts +179 -187
- package/src/services/artifact.service.ts +10 -5
- package/src/services/attachment.service.ts +35 -1
- package/src/services/autonomous-job.service.ts +58 -56
- package/src/services/background-work.service.ts +54 -0
- package/src/services/chat-run-registry.service.ts +3 -1
- package/src/services/context-compaction.service.ts +1 -1
- package/src/services/document-chunk.service.ts +8 -17
- package/src/services/execution-plan/execution-plan-graph.ts +74 -52
- package/src/services/execution-plan/execution-plan.service.ts +1 -1
- package/src/services/feedback-loop.service.ts +1 -1
- package/src/services/global-orchestrator.service.ts +33 -10
- package/src/services/graph-full-routing.ts +44 -33
- package/src/services/index.ts +1 -0
- package/src/services/institutional-memory.service.ts +8 -17
- package/src/services/learned-skill.service.ts +38 -35
- package/src/services/memory/memory-errors.ts +27 -0
- package/src/services/memory/memory-org-memory.ts +14 -3
- package/src/services/memory/memory-preseeded.ts +10 -4
- package/src/services/memory/memory-utils.ts +2 -1
- package/src/services/memory/memory.service.ts +26 -44
- package/src/services/memory/rerank.service.ts +3 -11
- package/src/services/monitoring-window.service.ts +1 -1
- package/src/services/mutating-approval.service.ts +1 -1
- package/src/services/node-workspace.service.ts +2 -2
- package/src/services/notification.service.ts +16 -4
- package/src/services/organization-member.service.ts +1 -1
- package/src/services/organization.service.ts +34 -51
- package/src/services/ownership-dispatcher.service.ts +132 -90
- package/src/services/plan/plan-agent-heartbeat.service.ts +1 -1
- package/src/services/plan/plan-agent-query.service.ts +1 -1
- package/src/services/plan/plan-approval.service.ts +52 -48
- package/src/services/plan/plan-artifact.service.ts +2 -2
- package/src/services/plan/plan-builder.service.ts +2 -2
- package/src/services/plan/plan-checkpoint.service.ts +1 -1
- package/src/services/plan/plan-compiler.service.ts +1 -1
- package/src/services/plan/plan-completion-side-effects.ts +18 -24
- package/src/services/plan/plan-coordination.service.ts +1 -1
- package/src/services/plan/plan-cycle.service.ts +171 -164
- package/src/services/plan/plan-deadline.service.ts +290 -304
- package/src/services/plan/plan-event-delivery.service.ts +44 -39
- package/src/services/plan/plan-executor-graph.ts +114 -67
- package/src/services/plan/plan-executor-helpers.ts +60 -75
- package/src/services/plan/plan-executor.service.ts +550 -467
- package/src/services/plan/plan-run.service.ts +12 -19
- package/src/services/plan/plan-scheduler.service.ts +27 -33
- package/src/services/plan/plan-template.service.ts +1 -1
- package/src/services/plan/plan-transaction-events.ts +8 -5
- package/src/services/plan/plan-validator.service.ts +1 -1
- package/src/services/plan/plan-workspace.service.ts +17 -11
- package/src/services/plugin-executor.service.ts +26 -21
- package/src/services/quality-metrics.service.ts +1 -1
- package/src/services/queue-job.service.ts +8 -17
- package/src/services/recent-activity-title.service.ts +17 -9
- package/src/services/recent-activity.service.ts +1 -1
- package/src/services/skill-resolver.service.ts +1 -1
- package/src/services/social-chat-history.service.ts +37 -20
- package/src/services/system-executor.service.ts +25 -20
- package/src/services/thread/thread-bootstrap.ts +26 -10
- package/src/services/thread/thread-listing.ts +2 -1
- package/src/services/thread/thread-memory-block.ts +18 -5
- package/src/services/thread/thread-message.service.ts +24 -8
- package/src/services/thread/thread-title.service.ts +1 -1
- package/src/services/thread/thread-turn-execution.ts +1 -1
- package/src/services/thread/thread-turn-preparation.service.ts +18 -16
- package/src/services/thread/thread-turn-streaming.ts +12 -11
- package/src/services/thread/thread-turn.ts +43 -10
- package/src/services/thread/thread.service.ts +11 -2
- package/src/services/user.service.ts +1 -1
- package/src/services/write-intent-validator.service.ts +1 -1
- package/src/storage/attachment-storage.service.ts +7 -4
- package/src/storage/generated-document-storage.service.ts +1 -1
- package/src/system-agents/context-compaction.agent.ts +1 -1
- package/src/system-agents/helper-agent-options.ts +1 -1
- package/src/system-agents/memory-reranker.agent.ts +1 -1
- package/src/system-agents/memory.agent.ts +1 -1
- package/src/system-agents/recent-activity-title-refiner.agent.ts +1 -1
- package/src/system-agents/regular-chat-memory-digest.agent.ts +1 -1
- package/src/system-agents/skill-extractor.agent.ts +1 -1
- package/src/system-agents/skill-manager.agent.ts +1 -1
- package/src/system-agents/title-generator.agent.ts +1 -1
- package/src/tools/execution-plan.tool.ts +28 -17
- package/src/tools/fetch-webpage.tool.ts +20 -13
- package/src/tools/firecrawl-client.ts +13 -3
- package/src/tools/plan-approval.tool.ts +9 -1
- package/src/tools/search-web.tool.ts +16 -9
- package/src/tools/team-think.tool.ts +2 -2
- package/src/utils/async.ts +15 -6
- package/src/utils/errors.ts +27 -15
- package/src/workers/bootstrap.ts +25 -48
- package/src/workers/organization-learning.worker.ts +1 -1
- package/src/workers/regular-chat-memory-digest.runner.ts +25 -15
- package/src/workers/worker-utils.ts +20 -2
- package/src/config/search.ts +0 -3
- package/src/runtime/agent-types.ts +0 -1
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
PlanArtifactRecord,
|
|
5
5
|
PlanArtifactSubmission,
|
|
6
6
|
PlanFailureClass,
|
|
7
|
+
PlanNodeResultSubmission,
|
|
7
8
|
PlanNodeRunRecord,
|
|
8
9
|
PlanNodeSpec,
|
|
9
10
|
PlanNodeSpecRecord,
|
|
@@ -14,15 +15,15 @@ import type {
|
|
|
14
15
|
PlanDraft,
|
|
15
16
|
UpstreamHandoff,
|
|
16
17
|
} from '@lota-sdk/shared'
|
|
17
|
-
import { Cause, Context, Effect, Layer, Match } from 'effect'
|
|
18
|
+
import { Cause, Context, Effect, Exit, Layer, Match } from 'effect'
|
|
18
19
|
|
|
19
20
|
import type { ResolvedAgentConfig } from '../config/agent-defaults'
|
|
20
21
|
import type { RecordIdInput } from '../db/record-id'
|
|
21
22
|
import { ensureRecordId, recordIdToString } from '../db/record-id'
|
|
22
23
|
import type { SurrealDBService } from '../db/service'
|
|
23
24
|
import { TABLES } from '../db/tables'
|
|
24
|
-
import { BadRequestError, ConfigurationError, DatabaseError } from '../effect/errors'
|
|
25
|
-
import { isPromiseLike } from '../effect/helpers'
|
|
25
|
+
import { BadRequestError, ConfigurationError, DatabaseError, ServiceError } from '../effect/errors'
|
|
26
|
+
import { isPromiseLike, makeEffectTryPromiseWithMessage } from '../effect/helpers'
|
|
26
27
|
import { AgentConfigServiceTag, DatabaseServiceTag, RuntimeAdaptersServiceTag } from '../effect/services'
|
|
27
28
|
import { resolvePlanNodeExecutionVisibility, shouldPlanNodeUseVisibleTurn } from '../runtime/execution-plan-visibility'
|
|
28
29
|
import type { LotaRuntimeAdapters } from '../runtime/runtime-extensions'
|
|
@@ -51,14 +52,20 @@ interface OwnershipDispatcherDeps {
|
|
|
51
52
|
db: SurrealDBService
|
|
52
53
|
agentConfig: ResolvedAgentConfig
|
|
53
54
|
runtimeAdapters: LotaRuntimeAdapters
|
|
54
|
-
agentExecutor: ReturnType<typeof makeAgentExecutorService
|
|
55
|
-
monitoringWindow: ReturnType<typeof makeMonitoringWindowService
|
|
55
|
+
agentExecutor: NoContextService<Pick<ReturnType<typeof makeAgentExecutorService>, 'executeNode'>>
|
|
56
|
+
monitoringWindow: NoContextService<Pick<ReturnType<typeof makeMonitoringWindowService>, 'startMonitoringWindow'>>
|
|
56
57
|
planExecutor: ReturnType<typeof makePlanExecutorService>
|
|
57
58
|
planRun: ReturnType<typeof makePlanRunService>
|
|
58
|
-
pluginExecutor: ReturnType<typeof makePluginExecutorService
|
|
59
|
-
skillResolver: SkillResolverService
|
|
60
|
-
systemExecutor: ReturnType<typeof makeSystemExecutorService
|
|
61
|
-
user: ReturnType<typeof makeUserService
|
|
59
|
+
pluginExecutor: NoContextService<Pick<ReturnType<typeof makePluginExecutorService>, 'executeNode' | 'validateOwner'>>
|
|
60
|
+
skillResolver: NoContextService<Pick<SkillResolverService, 'resolve'>>
|
|
61
|
+
systemExecutor: NoContextService<Pick<ReturnType<typeof makeSystemExecutorService>, 'executeNode' | 'validateOwner'>>
|
|
62
|
+
user: NoContextService<Pick<ReturnType<typeof makeUserService>, 'getUser'>>
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
type NoContextService<TService> = {
|
|
66
|
+
[K in keyof TService]: TService[K] extends (...args: infer TArgs) => Effect.Effect<infer A, infer E, unknown>
|
|
67
|
+
? (...args: TArgs) => Effect.Effect<A, E, never>
|
|
68
|
+
: TService[K]
|
|
62
69
|
}
|
|
63
70
|
|
|
64
71
|
const STABLE_RUN_STATUSES = new Set(['pending-approval', 'awaiting-human', 'blocked', 'failed', 'completed', 'aborted'])
|
|
@@ -132,6 +139,8 @@ function toDispatchDatabaseError(message: string, cause: unknown) {
|
|
|
132
139
|
return new DatabaseError({ message, cause })
|
|
133
140
|
}
|
|
134
141
|
|
|
142
|
+
const tryDispatchPromise = makeEffectTryPromiseWithMessage((message, cause) => new ServiceError({ message, cause }))
|
|
143
|
+
|
|
135
144
|
const matchDraftExecutor = (deps: OwnershipDispatcherDeps, node: { id: string; label: string }) =>
|
|
136
145
|
Match.type<PlanNodeOwner>().pipe(
|
|
137
146
|
Match.discriminator('executorType')('agent', (owner): PlanValidationIssueInput[] =>
|
|
@@ -169,8 +178,9 @@ const shouldAutoDispatchEffect = (deps: OwnershipDispatcherDeps, run: PlanRunRec
|
|
|
169
178
|
return true
|
|
170
179
|
}
|
|
171
180
|
|
|
172
|
-
const workspace = yield*
|
|
173
|
-
workspaceProvider.getWorkspace(ensureRecordId(run.organizationId, TABLES.ORGANIZATION)),
|
|
181
|
+
const workspace = yield* tryDispatchPromise(
|
|
182
|
+
() => workspaceProvider.getWorkspace(ensureRecordId(run.organizationId, TABLES.ORGANIZATION)),
|
|
183
|
+
'Failed to load workspace for dispatch eligibility.',
|
|
174
184
|
)
|
|
175
185
|
if (!workspaceProvider.getLifecycleState) {
|
|
176
186
|
return true
|
|
@@ -179,7 +189,7 @@ const shouldAutoDispatchEffect = (deps: OwnershipDispatcherDeps, run: PlanRunRec
|
|
|
179
189
|
const lifecycleState = yield* Effect.gen(function* () {
|
|
180
190
|
const result = workspaceProvider.getLifecycleState?.call(workspaceProvider, workspace)
|
|
181
191
|
if (isPromiseLike(result)) {
|
|
182
|
-
return yield*
|
|
192
|
+
return yield* tryDispatchPromise(() => result, 'Failed to read workspace lifecycle state.')
|
|
183
193
|
}
|
|
184
194
|
|
|
185
195
|
return result
|
|
@@ -210,7 +220,9 @@ const buildDispatchContextEffect = (
|
|
|
210
220
|
])
|
|
211
221
|
const userId = thread?.userId ? recordIdToString(thread.userId, TABLES.USER) : undefined
|
|
212
222
|
const userResult = userId ? yield* Effect.exit(deps.user.getUser(userId)) : undefined
|
|
213
|
-
const userName = userResult
|
|
223
|
+
const userName = userResult
|
|
224
|
+
? Exit.match(userResult, { onSuccess: (user) => user.name, onFailure: () => undefined })
|
|
225
|
+
: undefined
|
|
214
226
|
const nodeSpecsById = new Map(nodeSpecs.map((candidate) => [candidate.nodeId, candidate]))
|
|
215
227
|
const upstreamHandoffs: UpstreamHandoff[] = nodeRuns
|
|
216
228
|
.filter(
|
|
@@ -274,71 +286,81 @@ const dispatchNodeEffect = (
|
|
|
274
286
|
}
|
|
275
287
|
}
|
|
276
288
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
289
|
+
return yield* Match.value(params.nodeSpec.owner.executorType).pipe(
|
|
290
|
+
Match.when('agent', () =>
|
|
291
|
+
deps.agentExecutor.executeNode({
|
|
280
292
|
nodeSpec: params.nodeSpec,
|
|
281
293
|
resolvedInput: params.resolvedInput,
|
|
282
294
|
inputArtifacts: params.inputArtifacts,
|
|
283
295
|
context: params.context,
|
|
284
296
|
executionMode: effectiveExecutionMode,
|
|
285
297
|
schemaRegistry: params.schemaRegistry,
|
|
286
|
-
})
|
|
287
|
-
|
|
288
|
-
|
|
298
|
+
}),
|
|
299
|
+
),
|
|
300
|
+
Match.when('plugin', () =>
|
|
301
|
+
deps.pluginExecutor.executeNode({
|
|
289
302
|
nodeSpec: params.nodeSpec,
|
|
290
303
|
resolvedInput: params.resolvedInput,
|
|
291
304
|
context: params.context,
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
|
|
305
|
+
}),
|
|
306
|
+
),
|
|
307
|
+
Match.when('system', () =>
|
|
308
|
+
deps.systemExecutor.executeNode({
|
|
295
309
|
nodeSpec: params.nodeSpec,
|
|
296
310
|
resolvedInput: params.resolvedInput,
|
|
297
311
|
context: params.context,
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
return yield* new ConfigurationError({
|
|
306
|
-
message: `Skill "${params.nodeSpec.owner.ref}" could not be resolved. This is a configuration error.`,
|
|
312
|
+
}),
|
|
313
|
+
),
|
|
314
|
+
Match.when('skill', () =>
|
|
315
|
+
Effect.gen(function* () {
|
|
316
|
+
const resolved = yield* deps.skillResolver.resolve({
|
|
317
|
+
skillRef: params.nodeSpec.owner.ref,
|
|
318
|
+
organizationId: params.context.organizationId,
|
|
307
319
|
})
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
320
|
+
if (!resolved) {
|
|
321
|
+
return yield* new ConfigurationError({
|
|
322
|
+
message: `Skill "${params.nodeSpec.owner.ref}" could not be resolved. This is a configuration error.`,
|
|
323
|
+
})
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (resolved.executorType === 'agent') {
|
|
327
|
+
const skillNodeSpec = { ...params.nodeSpec, owner: { executorType: 'agent' as const, ref: resolved.ref } }
|
|
328
|
+
return yield* deps.agentExecutor.executeNode({
|
|
329
|
+
nodeSpec: skillNodeSpec,
|
|
330
|
+
resolvedInput: params.resolvedInput,
|
|
331
|
+
inputArtifacts: params.inputArtifacts,
|
|
332
|
+
context: params.context,
|
|
333
|
+
executionMode: effectiveExecutionMode,
|
|
334
|
+
schemaRegistry: params.schemaRegistry,
|
|
335
|
+
})
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return yield* deps.pluginExecutor.executeNode({
|
|
339
|
+
nodeSpec: {
|
|
340
|
+
...params.nodeSpec,
|
|
341
|
+
owner: {
|
|
342
|
+
executorType: 'plugin' as const,
|
|
343
|
+
ref: resolved.ref,
|
|
344
|
+
operation: resolved.operation ?? params.nodeSpec.owner.ref,
|
|
345
|
+
},
|
|
346
|
+
},
|
|
314
347
|
resolvedInput: params.resolvedInput,
|
|
315
|
-
inputArtifacts: params.inputArtifacts,
|
|
316
348
|
context: params.context,
|
|
317
|
-
executionMode: effectiveExecutionMode,
|
|
318
|
-
schemaRegistry: params.schemaRegistry,
|
|
319
349
|
})
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
operation: resolved.operation ?? params.nodeSpec.owner.ref,
|
|
329
|
-
},
|
|
330
|
-
},
|
|
331
|
-
resolvedInput: params.resolvedInput,
|
|
332
|
-
context: params.context,
|
|
333
|
-
})
|
|
334
|
-
}
|
|
335
|
-
case 'user':
|
|
336
|
-
return yield* new BadRequestError({
|
|
337
|
-
message: `User-owned node "${params.nodeSpec.id}" cannot be auto-dispatched.`,
|
|
338
|
-
})
|
|
339
|
-
}
|
|
350
|
+
}),
|
|
351
|
+
),
|
|
352
|
+
Match.when(
|
|
353
|
+
'user',
|
|
354
|
+
() => new BadRequestError({ message: `User-owned node "${params.nodeSpec.id}" cannot be auto-dispatched.` }),
|
|
355
|
+
),
|
|
356
|
+
Match.exhaustive,
|
|
357
|
+
)
|
|
340
358
|
})
|
|
341
359
|
|
|
360
|
+
type GraphFullDispatchReadyNode = (
|
|
361
|
+
params: Parameters<typeof dispatchReadyNodeEffect>[1],
|
|
362
|
+
) => Effect.Effect<PlanNodeResultSubmission, Effect.Error<ReturnType<typeof dispatchReadyNodeEffect>>, never>
|
|
363
|
+
|
|
342
364
|
const dispatchRunToStableBoundaryEffect = (
|
|
343
365
|
deps: OwnershipDispatcherDeps,
|
|
344
366
|
params: { runId: RecordIdInput; emittedBy: string },
|
|
@@ -359,20 +381,22 @@ const dispatchRunToStableBoundaryEffect = (
|
|
|
359
381
|
const spec = yield* deps.planRun.getPlanSpecById(run.planSpecId)
|
|
360
382
|
|
|
361
383
|
if (spec.executionMode === 'graph-full') {
|
|
384
|
+
const dispatchReadyNodeForGraphFull: GraphFullDispatchReadyNode = (dispatchParams) =>
|
|
385
|
+
dispatchReadyNodeEffect(deps, dispatchParams)
|
|
386
|
+
|
|
362
387
|
yield* routeGraphFullEffect(
|
|
363
388
|
{ threadId: recordIdToString(run.threadId, TABLES.THREAD), runId: recordIdToString(run.id, TABLES.PLAN_RUN) },
|
|
364
389
|
{
|
|
365
|
-
dispatchReadyNode:
|
|
390
|
+
dispatchReadyNode: dispatchReadyNodeForGraphFull,
|
|
366
391
|
planExecutorService: deps.planExecutor,
|
|
367
392
|
planRunService: deps.planRun,
|
|
368
393
|
},
|
|
369
394
|
).pipe(
|
|
370
|
-
Effect.
|
|
371
|
-
|
|
395
|
+
Effect.mapError(
|
|
396
|
+
() =>
|
|
372
397
|
new ConfigurationError({
|
|
373
398
|
message: `Failed to route graph-full execution for run ${recordIdToString(run.id, TABLES.PLAN_RUN)}.`,
|
|
374
399
|
}),
|
|
375
|
-
),
|
|
376
400
|
),
|
|
377
401
|
)
|
|
378
402
|
return yield* serializeRunEffect(deps, run.id)
|
|
@@ -428,29 +452,33 @@ const dispatchRunToStableBoundaryEffect = (
|
|
|
428
452
|
schemaRegistry: spec.schemaRegistry,
|
|
429
453
|
})
|
|
430
454
|
|
|
431
|
-
yield*
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
455
|
+
yield* tryDispatchPromise(
|
|
456
|
+
() =>
|
|
457
|
+
deps.planExecutor.submitNodeResult({
|
|
458
|
+
threadId: run.threadId,
|
|
459
|
+
runId: recordIdToString(run.id, TABLES.PLAN_RUN),
|
|
460
|
+
nodeId: planNode.id,
|
|
461
|
+
emittedBy: planNode.owner.ref,
|
|
462
|
+
result,
|
|
463
|
+
}),
|
|
464
|
+
'Failed to submit plan node result.',
|
|
439
465
|
)
|
|
440
466
|
}),
|
|
441
467
|
)
|
|
442
468
|
|
|
443
|
-
if (dispatchExit
|
|
469
|
+
if (Exit.isFailure(dispatchExit)) {
|
|
444
470
|
const failure = Cause.squash(dispatchExit.cause)
|
|
445
|
-
yield*
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
471
|
+
yield* tryDispatchPromise(
|
|
472
|
+
() =>
|
|
473
|
+
deps.planExecutor.blockNodeOnDispatchFailure({
|
|
474
|
+
threadId: run.threadId,
|
|
475
|
+
runId: recordIdToString(run.id, TABLES.PLAN_RUN),
|
|
476
|
+
nodeId: planNode.id,
|
|
477
|
+
emittedBy: planNode.owner.ref,
|
|
478
|
+
message: formatDispatchError(failure),
|
|
479
|
+
failureClass: classifyDispatchFailure({ ownerType: planNode.owner.executorType, error: failure }),
|
|
480
|
+
}),
|
|
481
|
+
'Failed to block plan node on dispatch failure.',
|
|
454
482
|
)
|
|
455
483
|
return yield* serializeRunEffect(deps, run.id)
|
|
456
484
|
}
|
|
@@ -541,14 +569,19 @@ export function makeOwnershipDispatcherService(deps: OwnershipDispatcherDeps) {
|
|
|
541
569
|
} as const
|
|
542
570
|
}
|
|
543
571
|
|
|
572
|
+
export interface OwnershipDispatcherService extends ReturnType<typeof makeOwnershipDispatcherService> {}
|
|
573
|
+
|
|
544
574
|
export class OwnershipDispatcherServiceTag extends Context.Service<
|
|
545
575
|
OwnershipDispatcherServiceTag,
|
|
546
|
-
|
|
547
|
-
>()('OwnershipDispatcherService') {}
|
|
576
|
+
OwnershipDispatcherService
|
|
577
|
+
>()('@lota-sdk/core/OwnershipDispatcherService') {}
|
|
548
578
|
|
|
549
579
|
export const OwnershipDispatcherServiceLive = Layer.effect(
|
|
550
580
|
OwnershipDispatcherServiceTag,
|
|
551
581
|
Effect.gen(function* () {
|
|
582
|
+
const currentContext = yield* Effect.context()
|
|
583
|
+
const provideCurrentContext = <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, never> =>
|
|
584
|
+
effect.pipe(Effect.provide(currentContext)) as Effect.Effect<A, E, never>
|
|
552
585
|
const db = yield* DatabaseServiceTag
|
|
553
586
|
const agentConfig = yield* AgentConfigServiceTag
|
|
554
587
|
const runtimeAdapters = yield* RuntimeAdaptersServiceTag
|
|
@@ -560,18 +593,27 @@ export const OwnershipDispatcherServiceLive = Layer.effect(
|
|
|
560
593
|
const skillResolver = yield* SkillResolverServiceTag
|
|
561
594
|
const systemExecutor = yield* SystemExecutorServiceTag
|
|
562
595
|
const user = yield* UserServiceTag
|
|
596
|
+
const executeAgentNode = agentExecutor.executeNode as OwnershipDispatcherDeps['agentExecutor']['executeNode']
|
|
563
597
|
return makeOwnershipDispatcherService({
|
|
564
598
|
db,
|
|
565
599
|
agentConfig,
|
|
566
600
|
runtimeAdapters,
|
|
567
|
-
agentExecutor,
|
|
568
|
-
monitoringWindow
|
|
601
|
+
agentExecutor: { executeNode: executeAgentNode },
|
|
602
|
+
monitoringWindow: {
|
|
603
|
+
startMonitoringWindow: (params) => provideCurrentContext(monitoringWindow.startMonitoringWindow(params)),
|
|
604
|
+
},
|
|
569
605
|
planExecutor,
|
|
570
606
|
planRun,
|
|
571
|
-
pluginExecutor
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
607
|
+
pluginExecutor: {
|
|
608
|
+
validateOwner: (owner, nodeId) => pluginExecutor.validateOwner(owner, nodeId),
|
|
609
|
+
executeNode: (params) => provideCurrentContext(pluginExecutor.executeNode(params)),
|
|
610
|
+
},
|
|
611
|
+
skillResolver: { resolve: (params) => provideCurrentContext(skillResolver.resolve(params)) },
|
|
612
|
+
systemExecutor: {
|
|
613
|
+
validateOwner: (owner, nodeId) => systemExecutor.validateOwner(owner, nodeId),
|
|
614
|
+
executeNode: (params) => provideCurrentContext(systemExecutor.executeNode(params)),
|
|
615
|
+
},
|
|
616
|
+
user: { getUser: (userId) => provideCurrentContext(user.getUser(userId)) },
|
|
575
617
|
})
|
|
576
618
|
}),
|
|
577
619
|
)
|
|
@@ -213,7 +213,7 @@ export function makePlanAgentHeartbeatService(deps: PlanAgentHeartbeatDeps) {
|
|
|
213
213
|
export class PlanAgentHeartbeatServiceTag extends Context.Service<
|
|
214
214
|
PlanAgentHeartbeatServiceTag,
|
|
215
215
|
ReturnType<typeof makePlanAgentHeartbeatService>
|
|
216
|
-
>()('PlanAgentHeartbeatService') {}
|
|
216
|
+
>()('@lota-sdk/core/PlanAgentHeartbeatService') {}
|
|
217
217
|
|
|
218
218
|
export const PlanAgentHeartbeatServiceLive = Layer.effect(
|
|
219
219
|
PlanAgentHeartbeatServiceTag,
|
|
@@ -310,7 +310,7 @@ export function makePlanAgentQueryService(deps: PlanAgentQueryDeps) {
|
|
|
310
310
|
export class PlanAgentQueryServiceTag extends Context.Service<
|
|
311
311
|
PlanAgentQueryServiceTag,
|
|
312
312
|
ReturnType<typeof makePlanAgentQueryService>
|
|
313
|
-
>()('PlanAgentQueryService') {}
|
|
313
|
+
>()('@lota-sdk/core/PlanAgentQueryService') {}
|
|
314
314
|
|
|
315
315
|
export const PlanAgentQueryServiceLive = Layer.effect(
|
|
316
316
|
PlanAgentQueryServiceTag,
|
|
@@ -12,48 +12,53 @@ import { nowDate } from '../../utils/date-time'
|
|
|
12
12
|
import type { HumanNodeResponsePayload } from './plan-executor-helpers'
|
|
13
13
|
|
|
14
14
|
export function makePlanApprovalService(db: SurrealDBService) {
|
|
15
|
-
const createPendingApprovalEffect = (params: {
|
|
15
|
+
const createPendingApprovalEffect = Effect.fn('PlanApproval.createPendingApproval')(function* (params: {
|
|
16
16
|
tx: DatabaseTransaction
|
|
17
17
|
runId: RecordIdInput
|
|
18
18
|
nodeRunId: RecordIdInput
|
|
19
19
|
nodeId: string
|
|
20
20
|
requestedBy: string
|
|
21
21
|
presented: Record<string, unknown>
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
.output('after')
|
|
22
|
+
}) {
|
|
23
|
+
const approvalId = new RecordId(TABLES.PLAN_APPROVAL, Bun.randomUUIDv7())
|
|
24
|
+
const created = yield* params.tx
|
|
25
|
+
.create(approvalId)
|
|
26
|
+
.content({
|
|
27
|
+
runId: ensureRecordId(params.runId, TABLES.PLAN_RUN),
|
|
28
|
+
nodeRunId: ensureRecordId(params.nodeRunId, TABLES.PLAN_NODE_RUN),
|
|
29
|
+
nodeId: params.nodeId,
|
|
30
|
+
status: 'pending',
|
|
31
|
+
requestedBy: params.requestedBy,
|
|
32
|
+
presented: params.presented,
|
|
33
|
+
requiredEdits: [],
|
|
34
|
+
})
|
|
35
|
+
.output('after')
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
return PlanApprovalSchema.parse(created)
|
|
38
|
+
})
|
|
40
39
|
|
|
41
|
-
const getApprovalByIdEffect = (approvalId: RecordIdInput)
|
|
42
|
-
db.findOne(
|
|
40
|
+
const getApprovalByIdEffect = Effect.fn('PlanApproval.getApprovalById')(function* (approvalId: RecordIdInput) {
|
|
41
|
+
return yield* db.findOne(
|
|
42
|
+
TABLES.PLAN_APPROVAL,
|
|
43
|
+
{ id: ensureRecordId(approvalId, TABLES.PLAN_APPROVAL) },
|
|
44
|
+
PlanApprovalSchema,
|
|
45
|
+
)
|
|
46
|
+
})
|
|
43
47
|
|
|
44
|
-
const getPendingApprovalForNodeRunEffect = (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
const getPendingApprovalForNodeRunEffect = Effect.fn('PlanApproval.getPendingApprovalForNodeRun')(function* (
|
|
49
|
+
nodeRunId: RecordIdInput,
|
|
50
|
+
) {
|
|
51
|
+
const approvals = yield* db.findMany(
|
|
52
|
+
TABLES.PLAN_APPROVAL,
|
|
53
|
+
{ nodeRunId: ensureRecordId(nodeRunId, TABLES.PLAN_NODE_RUN), status: 'pending' },
|
|
54
|
+
PlanApprovalSchema,
|
|
55
|
+
{ orderBy: 'createdAt', orderDir: 'DESC', limit: 1 },
|
|
56
|
+
)
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
return approvals.at(0) ?? null
|
|
59
|
+
})
|
|
55
60
|
|
|
56
|
-
const updateApprovalResponseEffect = (params: {
|
|
61
|
+
const updateApprovalResponseEffect = Effect.fn('PlanApproval.updateApprovalResponse')(function* (params: {
|
|
57
62
|
tx: DatabaseTransaction
|
|
58
63
|
approval: PlanApprovalRecord
|
|
59
64
|
status: PlanApprovalStatus
|
|
@@ -62,23 +67,22 @@ export function makePlanApprovalService(db: SurrealDBService) {
|
|
|
62
67
|
approvalMessageId?: string
|
|
63
68
|
comments?: string
|
|
64
69
|
requiredEdits?: string[]
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
.output('after')
|
|
70
|
+
}) {
|
|
71
|
+
const updated = yield* params.tx
|
|
72
|
+
.update(ensureRecordId(params.approval.id, TABLES.PLAN_APPROVAL))
|
|
73
|
+
.merge({
|
|
74
|
+
status: params.status,
|
|
75
|
+
response: params.response,
|
|
76
|
+
respondedBy: params.respondedBy,
|
|
77
|
+
...(params.approvalMessageId ? { approvalMessageId: params.approvalMessageId } : {}),
|
|
78
|
+
...(params.comments ? { comments: params.comments } : {}),
|
|
79
|
+
...(params.requiredEdits ? { requiredEdits: params.requiredEdits } : {}),
|
|
80
|
+
respondedAt: nowDate(),
|
|
81
|
+
})
|
|
82
|
+
.output('after')
|
|
79
83
|
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
return PlanApprovalSchema.parse(updated)
|
|
85
|
+
})
|
|
82
86
|
|
|
83
87
|
return {
|
|
84
88
|
createPendingApproval: createPendingApprovalEffect,
|
|
@@ -91,7 +95,7 @@ export function makePlanApprovalService(db: SurrealDBService) {
|
|
|
91
95
|
export class PlanApprovalServiceTag extends Context.Service<
|
|
92
96
|
PlanApprovalServiceTag,
|
|
93
97
|
ReturnType<typeof makePlanApprovalService>
|
|
94
|
-
>()('PlanApprovalService') {}
|
|
98
|
+
>()('@lota-sdk/core/PlanApprovalService') {}
|
|
95
99
|
|
|
96
100
|
export const PlanApprovalServiceLive = Layer.effect(
|
|
97
101
|
PlanApprovalServiceTag,
|
|
@@ -55,6 +55,6 @@ export function makePlanArtifactService() {
|
|
|
55
55
|
export class PlanArtifactServiceTag extends Context.Service<
|
|
56
56
|
PlanArtifactServiceTag,
|
|
57
57
|
ReturnType<typeof makePlanArtifactService>
|
|
58
|
-
>()('PlanArtifactService') {}
|
|
58
|
+
>()('@lota-sdk/core/PlanArtifactService') {}
|
|
59
59
|
|
|
60
|
-
export const PlanArtifactServiceLive = Layer.
|
|
60
|
+
export const PlanArtifactServiceLive = Layer.sync(PlanArtifactServiceTag, () => makePlanArtifactService())
|
|
@@ -71,6 +71,6 @@ export function makePlanBuilderService() {
|
|
|
71
71
|
export class PlanBuilderServiceTag extends Context.Service<
|
|
72
72
|
PlanBuilderServiceTag,
|
|
73
73
|
ReturnType<typeof makePlanBuilderService>
|
|
74
|
-
>()('PlanBuilderService') {}
|
|
74
|
+
>()('@lota-sdk/core/PlanBuilderService') {}
|
|
75
75
|
|
|
76
|
-
export const PlanBuilderServiceLive = Layer.
|
|
76
|
+
export const PlanBuilderServiceLive = Layer.sync(PlanBuilderServiceTag, () => makePlanBuilderService())
|
|
@@ -91,7 +91,7 @@ export function makePlanCheckpointService(deps: PlanCheckpointDeps) {
|
|
|
91
91
|
export class PlanCheckpointServiceTag extends Context.Service<
|
|
92
92
|
PlanCheckpointServiceTag,
|
|
93
93
|
ReturnType<typeof makePlanCheckpointService>
|
|
94
|
-
>()('PlanCheckpointService') {}
|
|
94
|
+
>()('@lota-sdk/core/PlanCheckpointService') {}
|
|
95
95
|
|
|
96
96
|
export const PlanCheckpointServiceLive = Layer.effect(
|
|
97
97
|
PlanCheckpointServiceTag,
|
|
@@ -95,7 +95,7 @@ export function makePlanCompilerService(planValidatorService: ReturnType<typeof
|
|
|
95
95
|
export class PlanCompilerServiceTag extends Context.Service<
|
|
96
96
|
PlanCompilerServiceTag,
|
|
97
97
|
ReturnType<typeof makePlanCompilerService>
|
|
98
|
-
>()('PlanCompilerService') {}
|
|
98
|
+
>()('@lota-sdk/core/PlanCompilerService') {}
|
|
99
99
|
|
|
100
100
|
export const PlanCompilerServiceLive = Layer.effect(
|
|
101
101
|
PlanCompilerServiceTag,
|
|
@@ -6,6 +6,7 @@ import { aiLogger } from '../../config/logger'
|
|
|
6
6
|
import { ensureRecordId } from '../../db/record-id'
|
|
7
7
|
import type { SurrealDBService } from '../../db/service'
|
|
8
8
|
import { TABLES } from '../../db/tables'
|
|
9
|
+
import { makeEffectTryPromiseWithMessage } from '../../effect/helpers'
|
|
9
10
|
import { runPromise } from '../../effect/runtime'
|
|
10
11
|
import { nowEpochMillis, unsafeDateFrom } from '../../utils/date-time'
|
|
11
12
|
import type { makeFeedbackLoopService } from '../feedback-loop.service'
|
|
@@ -33,25 +34,15 @@ class PlanCompletionSideEffectsError extends Schema.TaggedErrorClass<PlanComplet
|
|
|
33
34
|
{ message: Schema.String, cause: Schema.Defect },
|
|
34
35
|
) {}
|
|
35
36
|
|
|
37
|
+
const effectTryPlanCompletionPromise = makeEffectTryPromiseWithMessage(
|
|
38
|
+
(message, cause) => new PlanCompletionSideEffectsError({ message, cause }),
|
|
39
|
+
)
|
|
40
|
+
|
|
36
41
|
function tryPlanCompletionPromise<A>(
|
|
37
42
|
message: string,
|
|
38
|
-
|
|
43
|
+
evaluate: () => PromiseLike<A> | Effect.Effect<A, unknown>,
|
|
39
44
|
): Effect.Effect<A, PlanCompletionSideEffectsError> {
|
|
40
|
-
return
|
|
41
|
-
try {
|
|
42
|
-
const value = thunk()
|
|
43
|
-
if (Effect.isEffect(value)) {
|
|
44
|
-
return value.pipe(Effect.mapError((cause) => new PlanCompletionSideEffectsError({ message, cause })))
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return Effect.tryPromise({
|
|
48
|
-
try: () => Promise.resolve(value),
|
|
49
|
-
catch: (cause) => new PlanCompletionSideEffectsError({ message, cause }),
|
|
50
|
-
})
|
|
51
|
-
} catch (cause) {
|
|
52
|
-
return Effect.fail(new PlanCompletionSideEffectsError({ message, cause }))
|
|
53
|
-
}
|
|
54
|
-
})
|
|
45
|
+
return effectTryPlanCompletionPromise(evaluate, message)
|
|
55
46
|
}
|
|
56
47
|
|
|
57
48
|
export function makePlanCompletionSideEffects({
|
|
@@ -134,14 +125,17 @@ export function makePlanCompletionSideEffects({
|
|
|
134
125
|
PlanEventSchema,
|
|
135
126
|
),
|
|
136
127
|
)
|
|
137
|
-
yield*
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
128
|
+
yield* planEventDeliveryService
|
|
129
|
+
.dispatchEventEffect(event)
|
|
130
|
+
.pipe(
|
|
131
|
+
Effect.mapError(
|
|
132
|
+
(error) =>
|
|
133
|
+
new PlanCompletionSideEffectsError({
|
|
134
|
+
message: 'Failed to dispatch feedback analyzed plan event.',
|
|
135
|
+
cause: error,
|
|
136
|
+
}),
|
|
137
|
+
),
|
|
138
|
+
)
|
|
145
139
|
}
|
|
146
140
|
|
|
147
141
|
yield* institutionalMemoryService
|
|
@@ -170,7 +170,7 @@ export function makePlanCoordinationService(planRunService: ReturnType<typeof ma
|
|
|
170
170
|
export class PlanCoordinationServiceTag extends Context.Service<
|
|
171
171
|
PlanCoordinationServiceTag,
|
|
172
172
|
ReturnType<typeof makePlanCoordinationService>
|
|
173
|
-
>()('PlanCoordinationService') {}
|
|
173
|
+
>()('@lota-sdk/core/PlanCoordinationService') {}
|
|
174
174
|
|
|
175
175
|
export const PlanCoordinationServiceLive = Layer.effect(
|
|
176
176
|
PlanCoordinationServiceTag,
|