@lota-sdk/core 0.4.10 → 0.4.11
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-gateway/ai-gateway.ts +149 -95
- package/src/ai-gateway/index.ts +16 -1
- package/src/config/agent-defaults.ts +4 -120
- package/src/config/logger.ts +18 -34
- package/src/config/thread-defaults.ts +1 -18
- package/src/create-runtime.ts +90 -28
- package/src/db/base.service.ts +30 -38
- package/src/db/service.ts +489 -545
- package/src/effect/index.ts +0 -2
- package/src/effect/layers.ts +6 -13
- package/src/embeddings/provider.ts +2 -7
- package/src/index.ts +4 -5
- package/src/queues/autonomous-job.queue.ts +159 -113
- package/src/queues/context-compaction.queue.ts +39 -25
- package/src/queues/delayed-node-promotion.queue.ts +56 -29
- package/src/queues/document-processor.queue.ts +5 -3
- package/src/queues/index.ts +1 -0
- package/src/queues/memory-consolidation.queue.ts +79 -53
- package/src/queues/organization-learning.queue.ts +63 -39
- package/src/queues/plan-agent-heartbeat.queue.ts +104 -79
- package/src/queues/plan-scheduler.queue.ts +100 -84
- package/src/queues/post-chat-memory.queue.ts +55 -33
- package/src/queues/queue-factory.ts +40 -41
- package/src/queues/queues.service.ts +61 -0
- package/src/queues/title-generation.queue.ts +42 -31
- package/src/redis/org-memory-lock.ts +24 -9
- package/src/redis/redis-lease-lock.ts +8 -1
- package/src/runtime/agent-identity-overrides.ts +7 -3
- package/src/runtime/agent-runtime-policy.ts +9 -4
- package/src/runtime/agent-stream-helpers.ts +9 -4
- package/src/runtime/context-compaction/context-compaction-runtime.ts +28 -32
- package/src/runtime/context-compaction/context-compaction.ts +9 -7
- package/src/runtime/domain-layer.ts +15 -4
- package/src/runtime/execution-plan-visibility.ts +5 -2
- package/src/runtime/graph-designer.ts +0 -22
- package/src/runtime/index.ts +1 -0
- package/src/runtime/indexed-repositories-policy.ts +2 -6
- package/src/runtime/plugin-resolution.ts +29 -12
- package/src/runtime/post-turn-side-effects.ts +139 -141
- package/src/runtime/runtime-config.ts +0 -6
- package/src/runtime/runtime-extensions.ts +0 -54
- package/src/runtime/runtime-lifecycle.ts +4 -4
- package/src/runtime/runtime-services.ts +122 -53
- package/src/runtime/runtime-worker-registry.ts +113 -30
- package/src/runtime/social-chat/social-chat-agent-runner.ts +6 -3
- package/src/runtime/social-chat/social-chat-history.ts +3 -1
- package/src/runtime/social-chat/social-chat.ts +35 -20
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +6 -5
- package/src/runtime/team-consultation/team-consultation-prompts.ts +11 -6
- package/src/runtime/thread-chat-helpers.ts +18 -9
- package/src/runtime/thread-turn-context.ts +7 -47
- package/src/runtime/turn-lifecycle.ts +6 -14
- package/src/services/agent-activity.service.ts +168 -175
- package/src/services/agent-executor.service.ts +35 -16
- package/src/services/attachment.service.ts +4 -70
- package/src/services/autonomous-job.service.ts +53 -61
- package/src/services/context-compaction.service.ts +7 -9
- package/src/services/execution-plan/execution-plan-graph.ts +106 -115
- package/src/services/execution-plan/execution-plan-schedule.ts +1 -15
- package/src/services/execution-plan/execution-plan.service.ts +67 -50
- package/src/services/global-orchestrator.service.ts +18 -7
- package/src/services/graph-full-routing.ts +7 -6
- package/src/services/memory/memory-conversation.ts +10 -5
- package/src/services/memory/memory.service.ts +11 -8
- package/src/services/ownership-dispatcher.service.ts +16 -5
- package/src/services/plan/plan-agent-heartbeat.service.ts +29 -15
- package/src/services/plan/plan-agent-query.service.ts +12 -8
- package/src/services/plan/plan-completion-side-effects.ts +93 -101
- package/src/services/plan/plan-cycle.service.ts +7 -45
- package/src/services/plan/plan-deadline.service.ts +28 -17
- package/src/services/plan/plan-event-delivery.service.ts +47 -40
- package/src/services/plan/plan-executor-context.ts +2 -0
- package/src/services/plan/plan-executor-graph.ts +366 -391
- package/src/services/plan/plan-executor.service.ts +13 -91
- package/src/services/plan/plan-scheduler.service.ts +62 -49
- package/src/services/plan/plan-transaction-events.ts +1 -1
- package/src/services/recent-activity-title.service.ts +6 -2
- package/src/services/thread/thread-bootstrap.ts +11 -9
- package/src/services/thread/thread-message.service.ts +6 -5
- package/src/services/thread/thread-turn-execution.ts +86 -82
- package/src/services/thread/thread-turn-preparation.service.ts +47 -24
- package/src/services/thread/thread-turn-streaming.ts +20 -25
- package/src/services/thread/thread-turn.ts +25 -44
- package/src/services/thread/thread.service.ts +21 -6
- package/src/system-agents/recent-activity-title-refiner.agent.ts +8 -5
- package/src/system-agents/thread-router.agent.ts +23 -20
- package/src/tools/execution-plan.tool.ts +8 -3
- package/src/tools/fetch-webpage.tool.ts +10 -9
- package/src/tools/firecrawl-client.ts +0 -15
- package/src/tools/remember-memory.tool.ts +3 -6
- package/src/tools/research-topic.tool.ts +12 -3
- package/src/tools/search-web.tool.ts +10 -9
- package/src/tools/search.tool.ts +4 -5
- package/src/tools/team-think.tool.ts +139 -121
- package/src/workers/bootstrap.ts +9 -10
- package/src/workers/memory-consolidation.worker.ts +4 -1
- package/src/workers/organization-learning.worker.ts +15 -2
- package/src/workers/regular-chat-memory-digest.helpers.ts +3 -4
- package/src/workers/regular-chat-memory-digest.runner.ts +21 -14
- package/src/workers/skill-extraction.runner.ts +13 -15
- package/src/workers/worker-utils.ts +6 -18
- package/src/effect/awaitable-effect.ts +0 -96
- package/src/effect/runtime-ref.ts +0 -25
- package/src/effect/runtime.ts +0 -46
- package/src/redis/runtime-connection.ts +0 -20
- package/src/runtime/runtime-accessors.ts +0 -92
- package/src/runtime/runtime-token.ts +0 -47
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
import { PlanDraftSchema, PlanRunSchema, PlanSpecSchema } from '@lota-sdk/shared'
|
|
11
11
|
import { Context, Schema, Effect, Layer, Match } from 'effect'
|
|
12
12
|
import { RecordId } from 'surrealdb'
|
|
13
|
+
import type { z } from 'zod'
|
|
13
14
|
|
|
14
15
|
import type { RecordIdInput } from '../../db/record-id'
|
|
15
16
|
import { ensureRecordId, recordIdToString } from '../../db/record-id'
|
|
@@ -84,6 +85,17 @@ const effectTryPromise = makeEffectTryPromiseWithMessage(
|
|
|
84
85
|
(message, cause) => new ExecutionPlanServiceError({ message, cause }),
|
|
85
86
|
)
|
|
86
87
|
|
|
88
|
+
function parseRowEffect<TSchema extends z.ZodTypeAny>(
|
|
89
|
+
schema: TSchema,
|
|
90
|
+
value: unknown,
|
|
91
|
+
label: string,
|
|
92
|
+
): Effect.Effect<z.infer<TSchema>, ExecutionPlanServiceError> {
|
|
93
|
+
return Effect.try({
|
|
94
|
+
try: () => schema.parse(value) as z.infer<TSchema>,
|
|
95
|
+
catch: (cause) => new ExecutionPlanServiceError({ message: `Failed to parse ${label}.`, cause }),
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
87
99
|
function toSerializablePlanEffect(
|
|
88
100
|
deps: ExecutionPlanDeps,
|
|
89
101
|
run: PlanRunRecord,
|
|
@@ -285,7 +297,8 @@ function createPlanEffect(
|
|
|
285
297
|
const databaseService = deps.db
|
|
286
298
|
const requireApproval =
|
|
287
299
|
params.requireApproval ?? hasCrossThreadSourceContext(params.sourceThreadId, params.threadId)
|
|
288
|
-
const
|
|
300
|
+
const parsedDraft = yield* parseRowEffect(PlanDraftSchema, params.input, 'plan draft input')
|
|
301
|
+
const preparedDraft = deps.planBuilder.prepareDraft(parsedDraft)
|
|
289
302
|
const validation = deps.planValidator.validateDraft(preparedDraft)
|
|
290
303
|
if (validation.blocking.length > 0) {
|
|
291
304
|
return yield* new BadRequestError({
|
|
@@ -319,7 +332,7 @@ function createPlanEffect(
|
|
|
319
332
|
.output('after'),
|
|
320
333
|
'Failed to create execution plan spec.',
|
|
321
334
|
)
|
|
322
|
-
const spec = PlanSpecSchema
|
|
335
|
+
const spec = yield* parseRowEffect(PlanSpecSchema, createdSpec, 'created plan spec')
|
|
323
336
|
|
|
324
337
|
yield* effectTryPromise(
|
|
325
338
|
() =>
|
|
@@ -391,7 +404,8 @@ function replacePlanEffect(
|
|
|
391
404
|
|
|
392
405
|
const activeSpec = yield* deps.planRun.getPlanSpecById(activeRun.planSpecId)
|
|
393
406
|
const { runId: _runId, reason: _reason, requireApproval: requestedRequireApproval, ...draftInput } = params.input
|
|
394
|
-
const
|
|
407
|
+
const parsedDraft = yield* parseRowEffect(PlanDraftSchema, draftInput, 'plan draft replacement input')
|
|
408
|
+
const preparedDraft = deps.planBuilder.prepareDraft(parsedDraft)
|
|
395
409
|
const validation = deps.planValidator.validateDraft(preparedDraft)
|
|
396
410
|
if (validation.blocking.length > 0) {
|
|
397
411
|
return yield* new BadRequestError({
|
|
@@ -419,7 +433,7 @@ function replacePlanEffect(
|
|
|
419
433
|
.output('after'),
|
|
420
434
|
'Failed to update superseded execution plan spec.',
|
|
421
435
|
)
|
|
422
|
-
const supersededSpec = PlanSpecSchema
|
|
436
|
+
const supersededSpec = yield* parseRowEffect(PlanSpecSchema, updatedSpec, 'superseded plan spec')
|
|
423
437
|
|
|
424
438
|
const updatedRun = yield* effectTryPromise(
|
|
425
439
|
() =>
|
|
@@ -437,7 +451,7 @@ function replacePlanEffect(
|
|
|
437
451
|
.output('after'),
|
|
438
452
|
'Failed to abort previous execution run.',
|
|
439
453
|
)
|
|
440
|
-
const abortedRun = PlanRunSchema
|
|
454
|
+
const abortedRun = yield* parseRowEffect(PlanRunSchema, updatedRun, 'aborted plan run')
|
|
441
455
|
|
|
442
456
|
const createdSpec = yield* effectTryPromise(
|
|
443
457
|
() =>
|
|
@@ -456,7 +470,7 @@ function replacePlanEffect(
|
|
|
456
470
|
.output('after'),
|
|
457
471
|
'Failed to create replacement execution plan spec.',
|
|
458
472
|
)
|
|
459
|
-
const spec = PlanSpecSchema
|
|
473
|
+
const spec = yield* parseRowEffect(PlanSpecSchema, createdSpec, 'replacement plan spec')
|
|
460
474
|
|
|
461
475
|
yield* effectTryPromise(
|
|
462
476
|
() =>
|
|
@@ -523,18 +537,19 @@ function submitPlanTurnResultEffect(
|
|
|
523
537
|
},
|
|
524
538
|
) {
|
|
525
539
|
return Effect.gen(function* () {
|
|
526
|
-
const result = yield*
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
540
|
+
const result = yield* deps.planExecutor
|
|
541
|
+
.submitNodeResult({
|
|
542
|
+
threadId: params.threadId,
|
|
543
|
+
runId: params.runId,
|
|
544
|
+
nodeId: params.nodeId,
|
|
545
|
+
emittedBy: params.emittedBy,
|
|
546
|
+
result: params.input,
|
|
547
|
+
})
|
|
548
|
+
.pipe(
|
|
549
|
+
Effect.mapError(
|
|
550
|
+
(cause) => new ExecutionPlanServiceError({ message: 'Failed to submit execution plan node result.', cause }),
|
|
551
|
+
),
|
|
552
|
+
)
|
|
538
553
|
|
|
539
554
|
const plan = yield* finalizePlanSnapshotEffect(deps, { runId: params.runId, emittedBy: params.emittedBy })
|
|
540
555
|
return buildExecutionPlanToolResult({
|
|
@@ -550,15 +565,13 @@ function resumeRunEffect(
|
|
|
550
565
|
params: { threadId: RecordIdInput; emittedBy: string; input: { runId: string } },
|
|
551
566
|
) {
|
|
552
567
|
return Effect.gen(function* () {
|
|
553
|
-
const result = yield*
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
catch: (cause) => new ExecutionPlanServiceError({ message: 'Failed to resume execution run.', cause }),
|
|
561
|
-
})
|
|
568
|
+
const result = yield* deps.planExecutor
|
|
569
|
+
.resumeRun({ threadId: params.threadId, runId: params.input.runId, emittedBy: params.emittedBy })
|
|
570
|
+
.pipe(
|
|
571
|
+
Effect.mapError(
|
|
572
|
+
(cause) => new ExecutionPlanServiceError({ message: 'Failed to resume execution run.', cause }),
|
|
573
|
+
),
|
|
574
|
+
)
|
|
562
575
|
|
|
563
576
|
const plan = yield* finalizePlanSnapshotEffect(deps, { runId: params.input.runId, emittedBy: params.emittedBy })
|
|
564
577
|
return buildExecutionPlanToolResult({
|
|
@@ -609,7 +622,7 @@ function approvePlanEffect(
|
|
|
609
622
|
.output('after'),
|
|
610
623
|
'Failed to activate execution run.',
|
|
611
624
|
)
|
|
612
|
-
const activatedRun = PlanRunSchema
|
|
625
|
+
const activatedRun = yield* parseRowEffect(PlanRunSchema, updatedRun, 'activated plan run')
|
|
613
626
|
|
|
614
627
|
const synced = yield* effectTryPromise(
|
|
615
628
|
() =>
|
|
@@ -729,7 +742,7 @@ function rejectPlanEffect(
|
|
|
729
742
|
.output('after'),
|
|
730
743
|
'Failed to abort execution run.',
|
|
731
744
|
)
|
|
732
|
-
const rejectedRun = PlanRunSchema
|
|
745
|
+
const rejectedRun = yield* parseRowEffect(PlanRunSchema, updatedRun, 'rejected plan run')
|
|
733
746
|
|
|
734
747
|
yield* emitEvent({
|
|
735
748
|
tx,
|
|
@@ -778,17 +791,19 @@ function respondToApprovalEffect(
|
|
|
778
791
|
const run = yield* deps.planRun.getActiveRunRecord(params.threadId)
|
|
779
792
|
if (!run) return null
|
|
780
793
|
|
|
781
|
-
const plan = yield*
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
794
|
+
const plan = yield* deps.planExecutor
|
|
795
|
+
.submitHumanNodeResponse({
|
|
796
|
+
threadId: params.threadId,
|
|
797
|
+
approvalId: params.input.approvalId,
|
|
798
|
+
respondedBy: params.emittedBy,
|
|
799
|
+
response: params.input.response,
|
|
800
|
+
approvalMessageId: params.input.approvalMessageId,
|
|
801
|
+
})
|
|
802
|
+
.pipe(
|
|
803
|
+
Effect.mapError(
|
|
804
|
+
(cause) => new ExecutionPlanServiceError({ message: 'Failed to submit human approval response.', cause }),
|
|
805
|
+
),
|
|
806
|
+
)
|
|
792
807
|
if (!plan) return null
|
|
793
808
|
|
|
794
809
|
return yield* finalizePlanSnapshotEffect(deps, { runId: run.id, emittedBy: params.emittedBy })
|
|
@@ -825,16 +840,18 @@ function applyHumanInputFromUserMessageEffect(
|
|
|
825
840
|
)
|
|
826
841
|
if (!response) return null
|
|
827
842
|
|
|
828
|
-
const plan = yield*
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
843
|
+
const plan = yield* deps.planExecutor
|
|
844
|
+
.submitHumanNodeResponse({
|
|
845
|
+
threadId: params.threadId,
|
|
846
|
+
respondedBy: params.respondedBy,
|
|
847
|
+
response,
|
|
848
|
+
approvalMessageId: params.message.id,
|
|
849
|
+
})
|
|
850
|
+
.pipe(
|
|
851
|
+
Effect.mapError(
|
|
852
|
+
(cause) => new ExecutionPlanServiceError({ message: 'Failed to submit human node response.', cause }),
|
|
853
|
+
),
|
|
854
|
+
)
|
|
838
855
|
if (!plan) return null
|
|
839
856
|
|
|
840
857
|
return yield* finalizePlanSnapshotEffect(deps, { runId: run.id, emittedBy: params.respondedBy })
|
|
@@ -9,7 +9,10 @@ import type {
|
|
|
9
9
|
} from '@lota-sdk/shared'
|
|
10
10
|
import { Context, Effect, Layer } from 'effect'
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import type { ResolvedAgentConfig } from '../config/agent-defaults'
|
|
13
|
+
import { AgentConfigServiceTag } from '../effect/services'
|
|
14
|
+
import type { PlanAgentHeartbeatQueueRuntime } from '../queues/plan-agent-heartbeat.queue'
|
|
15
|
+
import { LotaQueuesServiceTag } from '../queues/queues.service'
|
|
13
16
|
import { routeGraphFullEffect } from './graph-full-routing'
|
|
14
17
|
import type { OwnershipDispatcherService } from './ownership-dispatcher.service'
|
|
15
18
|
import { OwnershipDispatcherServiceTag } from './ownership-dispatcher.service'
|
|
@@ -55,9 +58,11 @@ function decideRerouteAction(params: {
|
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
interface GlobalOrchestratorDeps {
|
|
61
|
+
agentConfig: ResolvedAgentConfig
|
|
58
62
|
ownershipDispatcherService: Pick<OwnershipDispatcherService, 'dispatchReadyNode'>
|
|
59
63
|
planExecutorService: ReturnType<typeof makePlanExecutorService>
|
|
60
64
|
planRunService: ReturnType<typeof makePlanRunService>
|
|
65
|
+
planAgentHeartbeatQueue: PlanAgentHeartbeatQueueRuntime
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
type DispatchReadyNodeParams = {
|
|
@@ -78,9 +83,11 @@ export function makeGlobalOrchestratorService(deps: GlobalOrchestratorDeps) {
|
|
|
78
83
|
decideRerouteAction,
|
|
79
84
|
routeGraphFull: (params: { threadId: string; runId: string }) =>
|
|
80
85
|
routeGraphFullEffect(params, {
|
|
86
|
+
agentConfig: deps.agentConfig,
|
|
81
87
|
dispatchReadyNode,
|
|
82
88
|
planExecutorService: deps.planExecutorService,
|
|
83
89
|
planRunService: deps.planRunService,
|
|
90
|
+
planAgentHeartbeatQueue: deps.planAgentHeartbeatQueue,
|
|
84
91
|
}),
|
|
85
92
|
}
|
|
86
93
|
}
|
|
@@ -93,21 +100,25 @@ export class GlobalOrchestratorServiceTag extends Context.Service<
|
|
|
93
100
|
export const GlobalOrchestratorServiceLive = Layer.effect(
|
|
94
101
|
GlobalOrchestratorServiceTag,
|
|
95
102
|
Effect.gen(function* () {
|
|
103
|
+
const agentConfig = yield* AgentConfigServiceTag
|
|
96
104
|
const ownershipDispatcherService = yield* OwnershipDispatcherServiceTag
|
|
97
105
|
const planExecutorService = yield* PlanExecutorServiceTag
|
|
98
106
|
const planRunService = yield* PlanRunServiceTag
|
|
99
|
-
|
|
107
|
+
const queues = yield* LotaQueuesServiceTag
|
|
108
|
+
return makeGlobalOrchestratorService({
|
|
109
|
+
agentConfig,
|
|
110
|
+
ownershipDispatcherService,
|
|
111
|
+
planExecutorService,
|
|
112
|
+
planRunService,
|
|
113
|
+
planAgentHeartbeatQueue: queues.planAgentHeartbeat,
|
|
114
|
+
})
|
|
100
115
|
}),
|
|
101
116
|
)
|
|
102
117
|
|
|
103
|
-
const
|
|
118
|
+
export const routeGraphFull = Effect.fn('GlobalOrchestrator.routeGraphFull')(function* (params: {
|
|
104
119
|
threadId: string
|
|
105
120
|
runId: string
|
|
106
121
|
}) {
|
|
107
122
|
const globalOrchestratorService = yield* GlobalOrchestratorServiceTag
|
|
108
123
|
return yield* globalOrchestratorService.routeGraphFull(params)
|
|
109
124
|
})
|
|
110
|
-
|
|
111
|
-
export function routeGraphFull(params: { threadId: string; runId: string }): Promise<void> {
|
|
112
|
-
return runPromise(routeGraphFullWithRuntime(params))
|
|
113
|
-
}
|
|
@@ -9,11 +9,13 @@ import type {
|
|
|
9
9
|
} from '@lota-sdk/shared'
|
|
10
10
|
import { Effect } from 'effect'
|
|
11
11
|
|
|
12
|
+
import type { ResolvedAgentConfig } from '../config/agent-defaults'
|
|
12
13
|
import { serverLogger } from '../config/logger'
|
|
13
14
|
import { recordIdToString } from '../db/record-id'
|
|
14
15
|
import { TABLES } from '../db/tables'
|
|
15
16
|
import { BadRequestError, ServiceError } from '../effect/errors'
|
|
16
17
|
import { makeEffectTryPromiseWithMessage } from '../effect/helpers'
|
|
18
|
+
import type { PlanAgentHeartbeatQueueRuntime } from '../queues/plan-agent-heartbeat.queue'
|
|
17
19
|
import { shouldPlanNodeUseVisibleTurn } from '../runtime/execution-plan-visibility'
|
|
18
20
|
import type { makePlanExecutorService } from './plan/plan-executor.service'
|
|
19
21
|
import type { makePlanRunService } from './plan/plan-run.service'
|
|
@@ -34,6 +36,7 @@ function formatDispatchError(error: unknown): string {
|
|
|
34
36
|
const STABLE_RUN_STATUSES = new Set(['pending-approval', 'awaiting-human', 'blocked', 'failed', 'completed', 'aborted'])
|
|
35
37
|
|
|
36
38
|
interface GraphFullRoutingDeps<E = never> {
|
|
39
|
+
agentConfig: ResolvedAgentConfig
|
|
37
40
|
dispatchReadyNode(params: {
|
|
38
41
|
run: PlanRunRecord
|
|
39
42
|
nodeSpecRecord: PlanNodeSpecRecord
|
|
@@ -43,6 +46,7 @@ interface GraphFullRoutingDeps<E = never> {
|
|
|
43
46
|
}): Effect.Effect<PlanNodeResultSubmission, E, never>
|
|
44
47
|
planExecutorService: ReturnType<typeof makePlanExecutorService>
|
|
45
48
|
planRunService: ReturnType<typeof makePlanRunService>
|
|
49
|
+
planAgentHeartbeatQueue: PlanAgentHeartbeatQueueRuntime
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
export function routeGraphFullEffect<E>(params: { threadId: string; runId: string }, deps: GraphFullRoutingDeps<E>) {
|
|
@@ -68,11 +72,11 @@ export function routeGraphFullEffect<E>(params: { threadId: string; runId: strin
|
|
|
68
72
|
|
|
69
73
|
const silentNodes = readyNodes.filter((nr: PlanNodeRunRecord) => {
|
|
70
74
|
const ns = nodeSpecs.find((s: PlanNodeSpecRecord) => s.nodeId === nr.nodeId)
|
|
71
|
-
return ns && !shouldPlanNodeUseVisibleTurn(spec, ns)
|
|
75
|
+
return ns && !shouldPlanNodeUseVisibleTurn(deps.agentConfig, spec, ns)
|
|
72
76
|
})
|
|
73
77
|
const visibleNodes = readyNodes.filter((nr: PlanNodeRunRecord) => {
|
|
74
78
|
const ns = nodeSpecs.find((s: PlanNodeSpecRecord) => s.nodeId === nr.nodeId)
|
|
75
|
-
return ns && shouldPlanNodeUseVisibleTurn(spec, ns)
|
|
79
|
+
return ns && shouldPlanNodeUseVisibleTurn(deps.agentConfig, spec, ns)
|
|
76
80
|
})
|
|
77
81
|
|
|
78
82
|
yield* Effect.forEach(
|
|
@@ -86,10 +90,7 @@ export function routeGraphFullEffect<E>(params: { threadId: string; runId: strin
|
|
|
86
90
|
)
|
|
87
91
|
|
|
88
92
|
if (visibleNodes.length > 0) {
|
|
89
|
-
const
|
|
90
|
-
() => import('../queues/plan-agent-heartbeat.queue'),
|
|
91
|
-
'Failed to load plan agent heartbeat queue module.',
|
|
92
|
-
)
|
|
93
|
+
const enqueuePlanAgentHeartbeatWake = deps.planAgentHeartbeatQueue.enqueuePlanAgentHeartbeatWake
|
|
93
94
|
const updatedRunForWake = yield* deps.planRunService.getRunById(params.runId)
|
|
94
95
|
yield* Effect.forEach(
|
|
95
96
|
visibleNodes,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ResolvedAgentConfig } from '../../config/agent-defaults'
|
|
2
|
+
import { isAgentName } from '../../config/agent-defaults'
|
|
2
3
|
import type { ExtractedFact, Message } from '../../db/memory-types'
|
|
3
4
|
import { sanitizeAgentOutputForMemory } from '../../runtime/llm-content'
|
|
4
5
|
import { compactWhitespace, truncateText } from '../../utils/string'
|
|
@@ -9,8 +10,8 @@ const MAX_CONVERSATION_MEMORY_BLOCK_CHARS = 2_000
|
|
|
9
10
|
const MAX_CONVERSATION_ATTACHMENT_CONTEXT_CHARS = 6_000
|
|
10
11
|
const LOW_VALUE_MEMORY_IMPORTANCE_THRESHOLD = 0.45
|
|
11
12
|
|
|
12
|
-
export const isRoutableAgentName = (value?: string): value is string =>
|
|
13
|
-
|
|
13
|
+
export const isRoutableAgentName = (agentConfig: ResolvedAgentConfig, value?: string): value is string =>
|
|
14
|
+
isAgentName(agentConfig, value)
|
|
14
15
|
|
|
15
16
|
function normalizeConversationText(value: string, maxChars: number): string {
|
|
16
17
|
const normalized = compactWhitespace(value)
|
|
@@ -18,7 +19,11 @@ function normalizeConversationText(value: string, maxChars: number): string {
|
|
|
18
19
|
return truncateText(normalized, maxChars)
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
export function resolveAgentScopeNames(
|
|
22
|
+
export function resolveAgentScopeNames(
|
|
23
|
+
agentConfig: ResolvedAgentConfig,
|
|
24
|
+
agentName?: string,
|
|
25
|
+
agentNames: string[] = [],
|
|
26
|
+
): string[] {
|
|
22
27
|
const unique = new Set<string>()
|
|
23
28
|
if (typeof agentName === 'string' && agentName.trim()) {
|
|
24
29
|
unique.add(agentName.trim())
|
|
@@ -29,7 +34,7 @@ export function resolveAgentScopeNames(agentName?: string, agentNames: string[]
|
|
|
29
34
|
if (!normalized) continue
|
|
30
35
|
unique.add(normalized)
|
|
31
36
|
}
|
|
32
|
-
return [...unique].filter((name) => isRoutableAgentName(name))
|
|
37
|
+
return [...unique].filter((name) => isRoutableAgentName(agentConfig, name))
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
export function buildConversationMessages(params: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Context, Schema, Effect, Layer } from 'effect'
|
|
2
2
|
|
|
3
|
+
import type { ResolvedAgentConfig } from '../../config/agent-defaults'
|
|
3
4
|
import { aiLogger } from '../../config/logger'
|
|
4
5
|
import type { Memory } from '../../db/memory'
|
|
5
6
|
import { isUniqueIndexConflict } from '../../db/memory-store.helpers'
|
|
@@ -12,7 +13,7 @@ import type {
|
|
|
12
13
|
MemoryType,
|
|
13
14
|
RelationType,
|
|
14
15
|
} from '../../db/memory-types'
|
|
15
|
-
import { DatabaseServiceTag, RuntimeConfigServiceTag } from '../../effect/services'
|
|
16
|
+
import { AgentConfigServiceTag, DatabaseServiceTag, RuntimeConfigServiceTag } from '../../effect/services'
|
|
16
17
|
import { withOrgMemoryLockEffect } from '../../redis/org-memory-lock'
|
|
17
18
|
import type { HelperModelRuntime } from '../../runtime/helper-model'
|
|
18
19
|
import { HelperModelTag } from '../../runtime/helper-model'
|
|
@@ -177,10 +178,11 @@ interface MemoryServiceDeps {
|
|
|
177
178
|
rerankService: ReturnType<typeof makeRerankService>
|
|
178
179
|
helperModelRuntime: HelperModelRuntime
|
|
179
180
|
orgMemoryCache: OrgMemoryCache
|
|
181
|
+
agentConfig: ResolvedAgentConfig
|
|
180
182
|
}
|
|
181
183
|
|
|
182
184
|
export function createMemoryService(deps: MemoryServiceDeps) {
|
|
183
|
-
const { runtimeConfig, helperModelRuntime, orgMemoryCache } = deps
|
|
185
|
+
const { runtimeConfig, helperModelRuntime, orgMemoryCache, agentConfig } = deps
|
|
184
186
|
const resolveRerankService = () => deps.rerankService
|
|
185
187
|
const service = {
|
|
186
188
|
searchOrganizationMemories: Effect.fn('MemoryService.searchOrganizationMemories')(function* (
|
|
@@ -251,7 +253,7 @@ export function createMemoryService(deps: MemoryServiceDeps) {
|
|
|
251
253
|
agentName: string,
|
|
252
254
|
query: string,
|
|
253
255
|
) {
|
|
254
|
-
if (!isRoutableAgentName(agentName)) {
|
|
256
|
+
if (!isRoutableAgentName(agentConfig, agentName)) {
|
|
255
257
|
aiLogger.debug`Agent memory search skipped - invalid agentName: ${agentName}`
|
|
256
258
|
return 'No stored memories.'
|
|
257
259
|
}
|
|
@@ -329,7 +331,7 @@ export function createMemoryService(deps: MemoryServiceDeps) {
|
|
|
329
331
|
},
|
|
330
332
|
]
|
|
331
333
|
|
|
332
|
-
if (isRoutableAgentName(agentName)) {
|
|
334
|
+
if (isRoutableAgentName(agentConfig, agentName)) {
|
|
333
335
|
const agentScoped = yield* agentScopeId(orgId, agentName)
|
|
334
336
|
retrievalTasks.push({
|
|
335
337
|
scopeTag: `agent:${agentName}`,
|
|
@@ -449,7 +451,7 @@ export function createMemoryService(deps: MemoryServiceDeps) {
|
|
|
449
451
|
metadata?: Record<string, unknown>
|
|
450
452
|
importance?: number
|
|
451
453
|
}) {
|
|
452
|
-
if (!isRoutableAgentName(agentName)) {
|
|
454
|
+
if (!isRoutableAgentName(agentConfig, agentName)) {
|
|
453
455
|
return Effect.fail(new InvalidAgentNameError({ agentName }))
|
|
454
456
|
}
|
|
455
457
|
|
|
@@ -536,7 +538,7 @@ export function createMemoryService(deps: MemoryServiceDeps) {
|
|
|
536
538
|
},
|
|
537
539
|
]
|
|
538
540
|
|
|
539
|
-
for (const scopedAgentName of resolveAgentScopeNames(undefined, params.agentNames ?? [])) {
|
|
541
|
+
for (const scopedAgentName of resolveAgentScopeNames(agentConfig, undefined, params.agentNames ?? [])) {
|
|
540
542
|
const agentScopedValue = yield* agentScopeId(params.orgId, scopedAgentName)
|
|
541
543
|
scopes.push({
|
|
542
544
|
scopeId: agentScopedValue,
|
|
@@ -619,7 +621,7 @@ export function createMemoryService(deps: MemoryServiceDeps) {
|
|
|
619
621
|
},
|
|
620
622
|
]
|
|
621
623
|
|
|
622
|
-
for (const scopedAgentName of resolveAgentScopeNames(agentName, agentNames)) {
|
|
624
|
+
for (const scopedAgentName of resolveAgentScopeNames(agentConfig, agentName, agentNames)) {
|
|
623
625
|
const agentId = yield* agentScopeId(orgId, scopedAgentName)
|
|
624
626
|
scopes.push({
|
|
625
627
|
scopeId: agentId,
|
|
@@ -668,7 +670,8 @@ export const MemoryServiceLive = Layer.effect(
|
|
|
668
670
|
const rerankService = yield* RerankServiceTag
|
|
669
671
|
const helperModelRuntime = yield* HelperModelTag
|
|
670
672
|
const background = yield* BackgroundWorkService
|
|
673
|
+
const agentConfig = yield* AgentConfigServiceTag
|
|
671
674
|
const orgMemoryCache = yield* makeOrgMemoryCache({ db, runtimeConfig, helperModelRuntime, background })
|
|
672
|
-
return createMemoryService({ runtimeConfig, rerankService, helperModelRuntime, orgMemoryCache })
|
|
675
|
+
return createMemoryService({ runtimeConfig, rerankService, helperModelRuntime, orgMemoryCache, agentConfig })
|
|
673
676
|
}),
|
|
674
677
|
)
|
|
@@ -25,6 +25,8 @@ import { TABLES } from '../db/tables'
|
|
|
25
25
|
import { BadRequestError, ConfigurationError, DatabaseError, ServiceError } from '../effect/errors'
|
|
26
26
|
import { isPromiseLike, makeEffectTryPromiseWithMessage } from '../effect/helpers'
|
|
27
27
|
import { AgentConfigServiceTag, DatabaseServiceTag, RuntimeAdaptersServiceTag } from '../effect/services'
|
|
28
|
+
import type { PlanAgentHeartbeatQueueRuntime } from '../queues/plan-agent-heartbeat.queue'
|
|
29
|
+
import { LotaQueuesServiceTag } from '../queues/queues.service'
|
|
28
30
|
import { resolvePlanNodeExecutionVisibility, shouldPlanNodeUseVisibleTurn } from '../runtime/execution-plan-visibility'
|
|
29
31
|
import type { LotaRuntimeAdapters } from '../runtime/runtime-extensions'
|
|
30
32
|
import type { makeAgentExecutorService } from './agent-executor.service'
|
|
@@ -60,6 +62,7 @@ interface OwnershipDispatcherDeps {
|
|
|
60
62
|
skillResolver: NoContextService<Pick<SkillResolverService, 'resolve'>>
|
|
61
63
|
systemExecutor: NoContextService<Pick<ReturnType<typeof makeSystemExecutorService>, 'executeNode' | 'validateOwner'>>
|
|
62
64
|
user: NoContextService<Pick<ReturnType<typeof makeUserService>, 'getUser'>>
|
|
65
|
+
planAgentHeartbeatQueue: PlanAgentHeartbeatQueueRuntime
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
type NoContextService<TService> = {
|
|
@@ -387,9 +390,11 @@ const dispatchRunToStableBoundaryEffect = (
|
|
|
387
390
|
yield* routeGraphFullEffect(
|
|
388
391
|
{ threadId: recordIdToString(run.threadId, TABLES.THREAD), runId: recordIdToString(run.id, TABLES.PLAN_RUN) },
|
|
389
392
|
{
|
|
393
|
+
agentConfig: deps.agentConfig,
|
|
390
394
|
dispatchReadyNode: dispatchReadyNodeForGraphFull,
|
|
391
395
|
planExecutorService: deps.planExecutor,
|
|
392
396
|
planRunService: deps.planRun,
|
|
397
|
+
planAgentHeartbeatQueue: deps.planAgentHeartbeatQueue,
|
|
393
398
|
},
|
|
394
399
|
).pipe(
|
|
395
400
|
Effect.mapError(
|
|
@@ -427,7 +432,7 @@ const dispatchRunToStableBoundaryEffect = (
|
|
|
427
432
|
if (nodeRun.status !== 'running') {
|
|
428
433
|
return yield* serializeRunEffect(deps, run.id)
|
|
429
434
|
}
|
|
430
|
-
if (shouldPlanNodeUseVisibleTurn(spec, nodeSpecRecord)) {
|
|
435
|
+
if (shouldPlanNodeUseVisibleTurn(deps.agentConfig, spec, nodeSpecRecord)) {
|
|
431
436
|
return yield* serializeRunEffect(deps, run.id)
|
|
432
437
|
}
|
|
433
438
|
|
|
@@ -503,7 +508,7 @@ const dispatchReadyNodeEffect = (
|
|
|
503
508
|
},
|
|
504
509
|
) =>
|
|
505
510
|
Effect.gen(function* () {
|
|
506
|
-
if (shouldPlanNodeUseVisibleTurn(params.spec, params.nodeSpecRecord)) {
|
|
511
|
+
if (shouldPlanNodeUseVisibleTurn(deps.agentConfig, params.spec, params.nodeSpecRecord)) {
|
|
507
512
|
return yield* new BadRequestError({
|
|
508
513
|
message: `Node "${params.nodeSpecRecord.nodeId}" requires a visible plan turn and cannot be silently dispatched.`,
|
|
509
514
|
})
|
|
@@ -531,8 +536,12 @@ const dispatchReadyNodeEffect = (
|
|
|
531
536
|
})
|
|
532
537
|
})
|
|
533
538
|
|
|
534
|
-
function resolveExecutionVisibility(params: {
|
|
535
|
-
|
|
539
|
+
function resolveExecutionVisibility(params: {
|
|
540
|
+
agentConfig: ResolvedAgentConfig
|
|
541
|
+
spec: PlanSpecRecord
|
|
542
|
+
nodeSpecRecord: PlanNodeSpecRecord
|
|
543
|
+
}) {
|
|
544
|
+
return resolvePlanNodeExecutionVisibility(params.agentConfig, params.spec, params.nodeSpecRecord)
|
|
536
545
|
}
|
|
537
546
|
|
|
538
547
|
export function makeOwnershipDispatcherService(deps: OwnershipDispatcherDeps) {
|
|
@@ -553,7 +562,7 @@ export function makeOwnershipDispatcherService(deps: OwnershipDispatcherDeps) {
|
|
|
553
562
|
return dispatchReadyNodeEffect(deps, params)
|
|
554
563
|
},
|
|
555
564
|
resolveExecutionVisibility(params: { spec: PlanSpecRecord; nodeSpecRecord: PlanNodeSpecRecord }) {
|
|
556
|
-
return resolveExecutionVisibility(params)
|
|
565
|
+
return resolveExecutionVisibility({ ...params, agentConfig: deps.agentConfig })
|
|
557
566
|
},
|
|
558
567
|
dispatchNode(params: {
|
|
559
568
|
nodeSpec: PlanNodeSpec
|
|
@@ -593,6 +602,7 @@ export const OwnershipDispatcherServiceLive = Layer.effect(
|
|
|
593
602
|
const skillResolver = yield* SkillResolverServiceTag
|
|
594
603
|
const systemExecutor = yield* SystemExecutorServiceTag
|
|
595
604
|
const user = yield* UserServiceTag
|
|
605
|
+
const queues = yield* LotaQueuesServiceTag
|
|
596
606
|
const executeAgentNode = agentExecutor.executeNode as OwnershipDispatcherDeps['agentExecutor']['executeNode']
|
|
597
607
|
return makeOwnershipDispatcherService({
|
|
598
608
|
db,
|
|
@@ -614,6 +624,7 @@ export const OwnershipDispatcherServiceLive = Layer.effect(
|
|
|
614
624
|
executeNode: (params) => provideCurrentContext(systemExecutor.executeNode(params)),
|
|
615
625
|
},
|
|
616
626
|
user: { getUser: (userId) => provideCurrentContext(user.getUser(userId)) },
|
|
627
|
+
planAgentHeartbeatQueue: queues.planAgentHeartbeat,
|
|
617
628
|
})
|
|
618
629
|
}),
|
|
619
630
|
)
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { Context, Schema, Effect, Layer } from 'effect'
|
|
2
2
|
|
|
3
|
+
import type { ResolvedAgentConfig } from '../../config/agent-defaults'
|
|
3
4
|
import { serverLogger } from '../../config/logger'
|
|
4
5
|
import { ensureRecordId } from '../../db/record-id'
|
|
5
6
|
import { TABLES } from '../../db/tables'
|
|
6
7
|
import { effectTryPromise } from '../../effect/helpers'
|
|
7
|
-
import { RedisServiceTag } from '../../effect/services'
|
|
8
|
+
import { AgentConfigServiceTag, RedisServiceTag } from '../../effect/services'
|
|
9
|
+
import type { PlanAgentHeartbeatQueueRuntime } from '../../queues/plan-agent-heartbeat.queue'
|
|
10
|
+
import { LotaQueuesServiceTag } from '../../queues/queues.service'
|
|
8
11
|
import type { RedisConnectionManager } from '../../redis/connection'
|
|
9
12
|
import { withLeaseLock } from '../../redis/redis-lease-lock'
|
|
10
13
|
import { resolvePlanNodeExecutionVisibility } from '../../runtime/execution-plan-visibility'
|
|
@@ -39,30 +42,40 @@ class PlanAgentHeartbeatError extends Schema.TaggedErrorClass<PlanAgentHeartbeat
|
|
|
39
42
|
cause: Schema.Defect,
|
|
40
43
|
}) {}
|
|
41
44
|
|
|
42
|
-
function tryHeartbeatPromise<A>(
|
|
45
|
+
function tryHeartbeatPromise<A, R = never>(
|
|
43
46
|
operation: string,
|
|
44
|
-
thunk: () => PromiseLike<A> | Effect.Effect<A, unknown>,
|
|
45
|
-
): Effect.Effect<A, PlanAgentHeartbeatError> {
|
|
47
|
+
thunk: () => PromiseLike<A> | Effect.Effect<A, unknown, R>,
|
|
48
|
+
): Effect.Effect<A, PlanAgentHeartbeatError, R> {
|
|
46
49
|
return effectTryPromise(thunk, (cause) => new PlanAgentHeartbeatError({ operation, cause }))
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
function heartbeatServiceEffect<A, E>(
|
|
52
|
+
function heartbeatServiceEffect<A, E, R = never>(
|
|
50
53
|
operation: string,
|
|
51
|
-
effect: Effect.Effect<A, E>,
|
|
52
|
-
): Effect.Effect<A, PlanAgentHeartbeatError> {
|
|
54
|
+
effect: Effect.Effect<A, E, R>,
|
|
55
|
+
): Effect.Effect<A, PlanAgentHeartbeatError, R> {
|
|
53
56
|
return effect.pipe(Effect.mapError((cause) => new PlanAgentHeartbeatError({ operation, cause })))
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
interface PlanAgentHeartbeatDeps {
|
|
60
|
+
agentConfig: ResolvedAgentConfig
|
|
57
61
|
redis: RedisConnectionManager
|
|
58
62
|
planAgentQueryService: ReturnType<typeof makePlanAgentQueryService>
|
|
59
63
|
planExecutorService: ReturnType<typeof makePlanExecutorService>
|
|
60
64
|
planRunService: ReturnType<typeof makePlanRunService>
|
|
61
65
|
threadService: ReturnType<typeof makeThreadService>
|
|
66
|
+
planAgentHeartbeatQueue: PlanAgentHeartbeatQueueRuntime
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
export function makePlanAgentHeartbeatService(deps: PlanAgentHeartbeatDeps) {
|
|
65
|
-
const {
|
|
70
|
+
const {
|
|
71
|
+
agentConfig,
|
|
72
|
+
planExecutorService,
|
|
73
|
+
planRunService,
|
|
74
|
+
redis,
|
|
75
|
+
planAgentQueryService,
|
|
76
|
+
threadService,
|
|
77
|
+
planAgentHeartbeatQueue,
|
|
78
|
+
} = deps
|
|
66
79
|
|
|
67
80
|
const wakeNodeEffect = (params: {
|
|
68
81
|
organizationId: string
|
|
@@ -71,7 +84,7 @@ export function makePlanAgentHeartbeatService(deps: PlanAgentHeartbeatDeps) {
|
|
|
71
84
|
nodeId: string
|
|
72
85
|
agentId: string
|
|
73
86
|
reason: string
|
|
74
|
-
}): Effect.Effect<boolean, PlanAgentHeartbeatError> =>
|
|
87
|
+
}): Effect.Effect<boolean, PlanAgentHeartbeatError, unknown> =>
|
|
75
88
|
Effect.gen(function* () {
|
|
76
89
|
const threadRef = ensureRecordId(params.threadId, TABLES.THREAD)
|
|
77
90
|
yield* heartbeatServiceEffect(
|
|
@@ -125,7 +138,7 @@ export function makePlanAgentHeartbeatService(deps: PlanAgentHeartbeatDeps) {
|
|
|
125
138
|
return false
|
|
126
139
|
}
|
|
127
140
|
|
|
128
|
-
const visibility = resolvePlanNodeExecutionVisibility(spec, nodeSpec)
|
|
141
|
+
const visibility = resolvePlanNodeExecutionVisibility(agentConfig, spec, nodeSpec)
|
|
129
142
|
if (visibility !== 'visible') {
|
|
130
143
|
return false
|
|
131
144
|
}
|
|
@@ -153,12 +166,9 @@ export function makePlanAgentHeartbeatService(deps: PlanAgentHeartbeatDeps) {
|
|
|
153
166
|
).pipe(Effect.mapError((cause) => new PlanAgentHeartbeatError({ operation: 'wake-node-lock', cause })))
|
|
154
167
|
})
|
|
155
168
|
|
|
156
|
-
const sweepEffect = (params?: { organizationId?: string }): Effect.Effect<void, PlanAgentHeartbeatError> =>
|
|
169
|
+
const sweepEffect = (params?: { organizationId?: string }): Effect.Effect<void, PlanAgentHeartbeatError, unknown> =>
|
|
157
170
|
Effect.gen(function* () {
|
|
158
|
-
const
|
|
159
|
-
'import-heartbeat-queue',
|
|
160
|
-
() => import('../../queues/plan-agent-heartbeat.queue'),
|
|
161
|
-
)
|
|
171
|
+
const enqueuePlanAgentHeartbeatWake = planAgentHeartbeatQueue.enqueuePlanAgentHeartbeatWake
|
|
162
172
|
const [actionable, recentlyUnblocked, approachingDeadlines] = yield* Effect.all([
|
|
163
173
|
heartbeatServiceEffect(
|
|
164
174
|
'get-actionable-nodes-for-agent',
|
|
@@ -218,17 +228,21 @@ export class PlanAgentHeartbeatServiceTag extends Context.Service<
|
|
|
218
228
|
export const PlanAgentHeartbeatServiceLive = Layer.effect(
|
|
219
229
|
PlanAgentHeartbeatServiceTag,
|
|
220
230
|
Effect.gen(function* () {
|
|
231
|
+
const agentConfig = yield* AgentConfigServiceTag
|
|
221
232
|
const redis = yield* RedisServiceTag
|
|
222
233
|
const planAgentQueryService = yield* PlanAgentQueryServiceTag
|
|
223
234
|
const planRunService = yield* PlanRunServiceTag
|
|
224
235
|
const planExecutor = yield* PlanExecutorServiceTag
|
|
225
236
|
const threadSvc = yield* ThreadServiceTag
|
|
237
|
+
const queues = yield* LotaQueuesServiceTag
|
|
226
238
|
return makePlanAgentHeartbeatService({
|
|
239
|
+
agentConfig,
|
|
227
240
|
redis,
|
|
228
241
|
planAgentQueryService,
|
|
229
242
|
planExecutorService: planExecutor,
|
|
230
243
|
planRunService,
|
|
231
244
|
threadService: threadSvc,
|
|
245
|
+
planAgentHeartbeatQueue: queues.planAgentHeartbeat,
|
|
232
246
|
})
|
|
233
247
|
}),
|
|
234
248
|
)
|