@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
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
} from '@lota-sdk/shared'
|
|
7
7
|
import { PlanNodeAttemptSchema, PlanNodeRunSchema } from '@lota-sdk/shared'
|
|
8
8
|
import { Context, Schema, Effect, Layer } from 'effect'
|
|
9
|
+
import type { z } from 'zod'
|
|
9
10
|
|
|
10
11
|
import { aiLogger } from '../../config/logger'
|
|
11
12
|
import type { RecordIdInput } from '../../db/record-id'
|
|
@@ -20,6 +21,7 @@ import { GeneratedDocumentStorageServiceTag } from '../../storage/generated-docu
|
|
|
20
21
|
import { nowDate } from '../../utils/date-time'
|
|
21
22
|
import { toError } from '../../utils/errors'
|
|
22
23
|
import { ArtifactServiceTag } from '../artifact.service'
|
|
24
|
+
import { BackgroundWorkService } from '../background-work.service'
|
|
23
25
|
import { FeedbackLoopServiceTag } from '../feedback-loop.service'
|
|
24
26
|
import { InstitutionalMemoryServiceTag } from '../institutional-memory.service'
|
|
25
27
|
import { QualityMetricsServiceTag } from '../quality-metrics.service'
|
|
@@ -97,6 +99,17 @@ function fromPromise<A>(thunk: () => PromiseLike<A> | Effect.Effect<A, unknown>)
|
|
|
97
99
|
)
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
function parseRowOrFail<T>(
|
|
103
|
+
schema: z.ZodType<T>,
|
|
104
|
+
value: unknown,
|
|
105
|
+
operation: string,
|
|
106
|
+
): Effect.Effect<T, PlanExecutorInternalError> {
|
|
107
|
+
return Effect.try({
|
|
108
|
+
try: () => schema.parse(value),
|
|
109
|
+
catch: (cause) => new PlanExecutorInternalError({ message: `Failed to parse ${operation} row`, cause }),
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
100
113
|
function withDatabaseTransactionEffect<A, E, R>(
|
|
101
114
|
databaseService: Context.Service.Shape<typeof DatabaseServiceTag>,
|
|
102
115
|
run: (tx: DatabaseTransaction) => Effect.Effect<A, E, R>,
|
|
@@ -310,7 +323,7 @@ function persistNodeResultAttemptEffect(
|
|
|
310
323
|
issues: [...submission.validation.blocking, ...submission.validation.warnings],
|
|
311
324
|
})
|
|
312
325
|
|
|
313
|
-
|
|
326
|
+
const updatedAttemptRow = yield* fromPromise(() =>
|
|
314
327
|
tx
|
|
315
328
|
.update(ensureRecordId(attempt.id, TABLES.PLAN_NODE_ATTEMPT))
|
|
316
329
|
.content({
|
|
@@ -327,7 +340,8 @@ function persistNodeResultAttemptEffect(
|
|
|
327
340
|
...(attempt.failureClass ? { failureClass: attempt.failureClass } : {}),
|
|
328
341
|
})
|
|
329
342
|
.output('after'),
|
|
330
|
-
)
|
|
343
|
+
)
|
|
344
|
+
void (yield* parseRowOrFail(PlanNodeAttemptSchema, updatedAttemptRow, 'plan node attempt'))
|
|
331
345
|
|
|
332
346
|
const publishedArtifacts =
|
|
333
347
|
submission.validation.blocking.length > 0
|
|
@@ -351,21 +365,20 @@ function persistNodeResultAttemptEffect(
|
|
|
351
365
|
artifacts: publishedArtifacts,
|
|
352
366
|
})
|
|
353
367
|
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
.
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
.output('after'),
|
|
367
|
-
),
|
|
368
|
+
const nextNodeRunRow = yield* fromPromise(() =>
|
|
369
|
+
tx
|
|
370
|
+
.update(ensureRecordId(submission.nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
371
|
+
.content(
|
|
372
|
+
toNodeRunData(submission.nodeRun, {
|
|
373
|
+
attemptCount: submission.nodeRun.attemptCount + 1,
|
|
374
|
+
latestAttemptId: attempt.id,
|
|
375
|
+
latestStructuredOutput: result.structuredOutput ?? null,
|
|
376
|
+
latestNotes: result.notes,
|
|
377
|
+
}),
|
|
378
|
+
)
|
|
379
|
+
.output('after'),
|
|
368
380
|
)
|
|
381
|
+
const nextNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, nextNodeRunRow, 'plan node run')
|
|
369
382
|
|
|
370
383
|
const nodeRuns = yield* context.planRunService.listNodeRuns(submission.run.id)
|
|
371
384
|
|
|
@@ -391,24 +404,23 @@ function handleRetryNodeResultEffect(
|
|
|
391
404
|
const { tx, emittedEvents, submission, persisted, emittedBy } = params
|
|
392
405
|
|
|
393
406
|
return Effect.gen(function* () {
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
.output('after'),
|
|
410
|
-
),
|
|
407
|
+
const retryNodeRunRow = yield* fromPromise(() =>
|
|
408
|
+
tx
|
|
409
|
+
.update(ensureRecordId(persisted.nextNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
410
|
+
.content(
|
|
411
|
+
toNodeRunData(persisted.nextNodeRun, {
|
|
412
|
+
status: 'ready',
|
|
413
|
+
retryCount: persisted.nextNodeRun.retryCount + 1,
|
|
414
|
+
failureClass: submission.validation.failureClass,
|
|
415
|
+
blockedReason: submission.validation.blocking[0]?.message ?? null,
|
|
416
|
+
readyAt: nowDate(),
|
|
417
|
+
startedAt: null,
|
|
418
|
+
completedAt: null,
|
|
419
|
+
}),
|
|
420
|
+
)
|
|
421
|
+
.output('after'),
|
|
411
422
|
)
|
|
423
|
+
const retryNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, retryNodeRunRow, 'plan node run')
|
|
412
424
|
|
|
413
425
|
yield* emitEvent({
|
|
414
426
|
tx,
|
|
@@ -477,22 +489,21 @@ function handleHumanReviewNodeResultEffect(
|
|
|
477
489
|
const { tx, emittedEvents, submission, persisted, emittedBy } = params
|
|
478
490
|
|
|
479
491
|
return Effect.gen(function* () {
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
.
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
.output('after'),
|
|
494
|
-
),
|
|
492
|
+
const awaitingHumanNodeRunRow = yield* fromPromise(() =>
|
|
493
|
+
tx
|
|
494
|
+
.update(ensureRecordId(persisted.nextNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
495
|
+
.content(
|
|
496
|
+
toNodeRunData(persisted.nextNodeRun, {
|
|
497
|
+
status: 'awaiting-human',
|
|
498
|
+
retryCount: persisted.nextNodeRun.retryCount + 1,
|
|
499
|
+
failureClass: submission.validation.failureClass,
|
|
500
|
+
blockedReason: submission.validation.blocking[0]?.message ?? null,
|
|
501
|
+
startedAt: persisted.nextNodeRun.startedAt ?? nowDate(),
|
|
502
|
+
}),
|
|
503
|
+
)
|
|
504
|
+
.output('after'),
|
|
495
505
|
)
|
|
506
|
+
const awaitingHumanNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, awaitingHumanNodeRunRow, 'plan node run')
|
|
496
507
|
|
|
497
508
|
const approval = yield* context.planApprovalService
|
|
498
509
|
.createPendingApproval({
|
|
@@ -561,21 +572,20 @@ function handleReplanNodeResultEffect(
|
|
|
561
572
|
const { tx, emittedEvents, submission, persisted, emittedBy } = params
|
|
562
573
|
|
|
563
574
|
return Effect.gen(function* () {
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
.
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
.output('after'),
|
|
577
|
-
),
|
|
575
|
+
const blockedNodeRunRow = yield* fromPromise(() =>
|
|
576
|
+
tx
|
|
577
|
+
.update(ensureRecordId(persisted.nextNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
578
|
+
.content(
|
|
579
|
+
toNodeRunData(persisted.nextNodeRun, {
|
|
580
|
+
status: 'blocked',
|
|
581
|
+
retryCount: persisted.nextNodeRun.retryCount + 1,
|
|
582
|
+
failureClass: submission.validation.failureClass,
|
|
583
|
+
blockedReason: submission.validation.blocking[0]?.message ?? null,
|
|
584
|
+
}),
|
|
585
|
+
)
|
|
586
|
+
.output('after'),
|
|
578
587
|
)
|
|
588
|
+
const blockedNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, blockedNodeRunRow, 'plan node run')
|
|
579
589
|
|
|
580
590
|
const blockedRun = yield* replaceRun(tx, submission.run, {
|
|
581
591
|
status: 'blocked',
|
|
@@ -629,22 +639,21 @@ function handleFailedNodeResultEffect(
|
|
|
629
639
|
const { tx, emittedEvents, submission, persisted, emittedBy } = params
|
|
630
640
|
|
|
631
641
|
return Effect.gen(function* () {
|
|
632
|
-
const
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
.
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
.output('after'),
|
|
646
|
-
),
|
|
642
|
+
const failedNodeRunRow = yield* fromPromise(() =>
|
|
643
|
+
tx
|
|
644
|
+
.update(ensureRecordId(persisted.nextNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
645
|
+
.content(
|
|
646
|
+
toNodeRunData(persisted.nextNodeRun, {
|
|
647
|
+
status: 'failed',
|
|
648
|
+
retryCount: persisted.nextNodeRun.retryCount + 1,
|
|
649
|
+
failureClass: submission.validation.failureClass,
|
|
650
|
+
blockedReason: submission.validation.blocking[0]?.message ?? null,
|
|
651
|
+
completedAt: nowDate(),
|
|
652
|
+
}),
|
|
653
|
+
)
|
|
654
|
+
.output('after'),
|
|
647
655
|
)
|
|
656
|
+
const failedNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, failedNodeRunRow, 'plan node run')
|
|
648
657
|
|
|
649
658
|
const failedRun = yield* replaceRun(tx, submission.run, {
|
|
650
659
|
status: 'failed',
|
|
@@ -735,24 +744,23 @@ function handleSuccessfulNodeResultEffect(
|
|
|
735
744
|
const { tx, emittedEvents, submission, persisted, emittedBy, result } = params
|
|
736
745
|
|
|
737
746
|
return Effect.gen(function* () {
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
.
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
.output('after'),
|
|
754
|
-
),
|
|
747
|
+
const completedNodeRunRow = yield* fromPromise(() =>
|
|
748
|
+
tx
|
|
749
|
+
.update(ensureRecordId(persisted.nextNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
750
|
+
.content(
|
|
751
|
+
toNodeRunData(persisted.nextNodeRun, {
|
|
752
|
+
status: submission.validation.warnings.length > 0 ? 'partial' : 'completed',
|
|
753
|
+
latestAttemptId: persisted.attemptId,
|
|
754
|
+
latestStructuredOutput: result.structuredOutput ?? null,
|
|
755
|
+
latestNotes: result.notes,
|
|
756
|
+
blockedReason: null,
|
|
757
|
+
failureClass: null,
|
|
758
|
+
completedAt: nowDate(),
|
|
759
|
+
}),
|
|
760
|
+
)
|
|
761
|
+
.output('after'),
|
|
755
762
|
)
|
|
763
|
+
const completedNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, completedNodeRunRow, 'plan node run')
|
|
756
764
|
|
|
757
765
|
yield* emitEvent({
|
|
758
766
|
tx,
|
|
@@ -949,7 +957,7 @@ function persistHumanNodeResponseAttemptEffect(
|
|
|
949
957
|
issues: [...submission.validation.blocking, ...submission.validation.warnings],
|
|
950
958
|
})
|
|
951
959
|
|
|
952
|
-
|
|
960
|
+
const updatedHumanAttemptRow = yield* fromPromise(() =>
|
|
953
961
|
tx
|
|
954
962
|
.update(ensureRecordId(attempt.id, TABLES.PLAN_NODE_ATTEMPT))
|
|
955
963
|
.content({
|
|
@@ -966,27 +974,27 @@ function persistHumanNodeResponseAttemptEffect(
|
|
|
966
974
|
...(attempt.failureClass ? { failureClass: attempt.failureClass } : {}),
|
|
967
975
|
})
|
|
968
976
|
.output('after'),
|
|
969
|
-
)
|
|
977
|
+
)
|
|
978
|
+
void (yield* parseRowOrFail(PlanNodeAttemptSchema, updatedHumanAttemptRow, 'plan node attempt'))
|
|
970
979
|
|
|
971
|
-
const
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
.
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
.output('after'),
|
|
988
|
-
),
|
|
980
|
+
const nextNodeRunRow = yield* fromPromise(() =>
|
|
981
|
+
tx
|
|
982
|
+
.update(ensureRecordId(submission.nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
983
|
+
.content(
|
|
984
|
+
toNodeRunData(submission.nodeRun, {
|
|
985
|
+
status: submission.validation.blocking.length > 0 ? 'blocked' : 'completed',
|
|
986
|
+
attemptCount: submission.nodeRun.attemptCount + 1,
|
|
987
|
+
latestAttemptId: attempt.id,
|
|
988
|
+
latestStructuredOutput: response,
|
|
989
|
+
latestNotes: submission.responseComments ?? null,
|
|
990
|
+
blockedReason: submission.validation.blocking[0]?.message ?? null,
|
|
991
|
+
failureClass: submission.validation.blocking.length > 0 ? submission.validation.failureClass : null,
|
|
992
|
+
...(submission.validation.blocking.length > 0 ? {} : { completedAt: nowDate() }),
|
|
993
|
+
}),
|
|
994
|
+
)
|
|
995
|
+
.output('after'),
|
|
989
996
|
)
|
|
997
|
+
const nextNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, nextNodeRunRow, 'plan node run')
|
|
990
998
|
|
|
991
999
|
const nodeRuns = replaceNodeRunInList(yield* context.planRunService.listNodeRuns(submission.run.id), nextNodeRun)
|
|
992
1000
|
|
|
@@ -1105,8 +1113,7 @@ function handleAcceptedHumanNodeResponseEffect(
|
|
|
1105
1113
|
})
|
|
1106
1114
|
}
|
|
1107
1115
|
|
|
1108
|
-
|
|
1109
|
-
function submitNodeResult(
|
|
1116
|
+
const submitNodeResultEffect = Effect.fn('PlanExecutor.submitNodeResult')(function* (
|
|
1110
1117
|
context: PlanExecutorContext,
|
|
1111
1118
|
params: {
|
|
1112
1119
|
threadId: RecordIdInput
|
|
@@ -1115,7 +1122,7 @@ function submitNodeResult(
|
|
|
1115
1122
|
emittedBy: string
|
|
1116
1123
|
result: PlanNodeResultSubmission
|
|
1117
1124
|
},
|
|
1118
|
-
)
|
|
1125
|
+
) {
|
|
1119
1126
|
const {
|
|
1120
1127
|
databaseService,
|
|
1121
1128
|
generatedDocumentStorageService,
|
|
@@ -1124,55 +1131,58 @@ function submitNodeResult(
|
|
|
1124
1131
|
planRunService,
|
|
1125
1132
|
} = context
|
|
1126
1133
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
const publishedArtifactStorageKeys: string[] = []
|
|
1130
|
-
|
|
1131
|
-
yield* withTransactionAndEventsEffect({
|
|
1132
|
-
db: databaseService,
|
|
1133
|
-
planEventDeliveryService,
|
|
1134
|
-
run: (tx, emittedEvents) =>
|
|
1135
|
-
Effect.gen(function* () {
|
|
1136
|
-
const persisted = yield* persistNodeResultAttemptEffect(context, {
|
|
1137
|
-
tx,
|
|
1138
|
-
submission,
|
|
1139
|
-
nodeId: params.nodeId,
|
|
1140
|
-
emittedBy: params.emittedBy,
|
|
1141
|
-
result: params.result,
|
|
1142
|
-
publishedArtifactStorageKeys,
|
|
1143
|
-
})
|
|
1134
|
+
const submission = yield* loadNodeResultSubmissionContextEffect(context, params)
|
|
1135
|
+
const publishedArtifactStorageKeys: string[] = []
|
|
1144
1136
|
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1137
|
+
yield* withTransactionAndEventsEffect({
|
|
1138
|
+
db: databaseService,
|
|
1139
|
+
planEventDeliveryService,
|
|
1140
|
+
run: (tx, emittedEvents) =>
|
|
1141
|
+
Effect.gen(function* () {
|
|
1142
|
+
const persisted = yield* persistNodeResultAttemptEffect(context, {
|
|
1143
|
+
tx,
|
|
1144
|
+
submission,
|
|
1145
|
+
nodeId: params.nodeId,
|
|
1146
|
+
emittedBy: params.emittedBy,
|
|
1147
|
+
result: params.result,
|
|
1148
|
+
publishedArtifactStorageKeys,
|
|
1149
|
+
})
|
|
1150
|
+
|
|
1151
|
+
if (submission.validation.blocking.length > 0) {
|
|
1152
|
+
return yield* handleBlockedNodeResultEffect(context, {
|
|
1156
1153
|
tx,
|
|
1157
1154
|
emittedEvents,
|
|
1158
1155
|
submission,
|
|
1159
1156
|
persisted,
|
|
1160
1157
|
emittedBy: params.emittedBy,
|
|
1161
|
-
result: params.result,
|
|
1162
1158
|
})
|
|
1163
|
-
}
|
|
1164
|
-
}).pipe(
|
|
1165
|
-
Effect.tapError(() =>
|
|
1166
|
-
Effect.forEach(publishedArtifactStorageKeys, (storageKey) =>
|
|
1167
|
-
generatedDocumentStorageService.deleteTextArtifact(storageKey).pipe(Effect.ignore),
|
|
1168
|
-
).pipe(Effect.asVoid),
|
|
1169
|
-
),
|
|
1170
|
-
)
|
|
1159
|
+
}
|
|
1171
1160
|
|
|
1172
|
-
|
|
1173
|
-
|
|
1161
|
+
return yield* handleSuccessfulNodeResultEffect(context, {
|
|
1162
|
+
tx,
|
|
1163
|
+
emittedEvents,
|
|
1164
|
+
submission,
|
|
1165
|
+
persisted,
|
|
1166
|
+
emittedBy: params.emittedBy,
|
|
1167
|
+
result: params.result,
|
|
1168
|
+
})
|
|
1169
|
+
}),
|
|
1170
|
+
}).pipe(
|
|
1171
|
+
Effect.withSpan('PlanExecutor.submitNodeResult.persistTransaction'),
|
|
1172
|
+
Effect.tapError(() =>
|
|
1173
|
+
Effect.forEach(publishedArtifactStorageKeys, (storageKey) =>
|
|
1174
|
+
generatedDocumentStorageService.deleteTextArtifact(storageKey).pipe(Effect.ignore),
|
|
1175
|
+
).pipe(Effect.asVoid),
|
|
1176
|
+
),
|
|
1177
|
+
)
|
|
1174
1178
|
|
|
1175
|
-
|
|
1179
|
+
const orgId = recordIdToString(submission.run.organizationId, TABLES.ORGANIZATION)
|
|
1180
|
+
const runIdStr = recordIdToString(submission.run.id, TABLES.PLAN_RUN)
|
|
1181
|
+
|
|
1182
|
+
const background = yield* BackgroundWorkService
|
|
1183
|
+
|
|
1184
|
+
yield* background.run(
|
|
1185
|
+
fromPromise(() =>
|
|
1176
1186
|
planCompletionSideEffects.runPlanNodeCompletionSideEffects({
|
|
1177
1187
|
runId: runIdStr,
|
|
1178
1188
|
organizationId: orgId,
|
|
@@ -1192,31 +1202,50 @@ function submitNodeResult(
|
|
|
1192
1202
|
aiLogger.warn`Failed to record node completion metrics for run ${runIdStr} node ${params.nodeId}: ${error.message}`
|
|
1193
1203
|
}),
|
|
1194
1204
|
),
|
|
1195
|
-
|
|
1196
|
-
|
|
1205
|
+
),
|
|
1206
|
+
'plan-executor.recordNodeCompletionMetrics',
|
|
1207
|
+
)
|
|
1197
1208
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1209
|
+
const updatedRun = yield* planRunService.getRunById(submission.run.id)
|
|
1210
|
+
if (updatedRun.status === 'completed') {
|
|
1211
|
+
yield* background.run(
|
|
1212
|
+
fromPromise(() =>
|
|
1201
1213
|
planCompletionSideEffects.runPlanCompletionSideEffectsSafely({ runId: runIdStr, organizationId: orgId }),
|
|
1202
1214
|
).pipe(
|
|
1203
|
-
Effect.catchTag('PlanExecutorInternalError', () =>
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1215
|
+
Effect.catchTag('PlanExecutorInternalError', (error) =>
|
|
1216
|
+
Effect.sync(() => {
|
|
1217
|
+
aiLogger.warn`Plan completion side-effects failed for run ${runIdStr}: ${error.message}`
|
|
1218
|
+
}),
|
|
1219
|
+
),
|
|
1220
|
+
),
|
|
1221
|
+
'plan-executor.runPlanCompletionSideEffects',
|
|
1222
|
+
)
|
|
1223
|
+
}
|
|
1207
1224
|
|
|
1208
|
-
|
|
1225
|
+
const snapshot = yield* serializeRunFull(planRunService, updatedRun)
|
|
1209
1226
|
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
}
|
|
1227
|
+
return buildExecutionPlanToolResult({
|
|
1228
|
+
action: 'node-result-submitted',
|
|
1229
|
+
plan: snapshot,
|
|
1230
|
+
message: `Submitted result for node "${submission.nodeSpec.label}".`,
|
|
1231
|
+
})
|
|
1232
|
+
})
|
|
1217
1233
|
|
|
1218
1234
|
/** @lintignore */
|
|
1219
|
-
function
|
|
1235
|
+
function submitNodeResult(
|
|
1236
|
+
context: PlanExecutorContext,
|
|
1237
|
+
params: {
|
|
1238
|
+
threadId: RecordIdInput
|
|
1239
|
+
runId: string
|
|
1240
|
+
nodeId: string
|
|
1241
|
+
emittedBy: string
|
|
1242
|
+
result: PlanNodeResultSubmission
|
|
1243
|
+
},
|
|
1244
|
+
): Promise<ExecutionPlanToolResultData> {
|
|
1245
|
+
return submitNodeResultEffect(context, params).pipe(runPromise)
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
const submitHumanNodeResponseEffect = Effect.fn('PlanExecutor.submitHumanNodeResponse')(function* (
|
|
1220
1249
|
context: PlanExecutorContext,
|
|
1221
1250
|
params: {
|
|
1222
1251
|
threadId: RecordIdInput
|
|
@@ -1225,192 +1254,302 @@ function submitHumanNodeResponse(
|
|
|
1225
1254
|
response: HumanNodeResponsePayload
|
|
1226
1255
|
approvalMessageId?: string
|
|
1227
1256
|
},
|
|
1228
|
-
)
|
|
1257
|
+
) {
|
|
1229
1258
|
const { databaseService, planEventDeliveryService } = context
|
|
1230
1259
|
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
}
|
|
1260
|
+
const submission = yield* loadHumanNodeResponseContextEffect(context, params)
|
|
1261
|
+
if (!submission) {
|
|
1262
|
+
return null
|
|
1263
|
+
}
|
|
1236
1264
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1265
|
+
return yield* withTransactionAndEventsEffect({
|
|
1266
|
+
db: databaseService,
|
|
1267
|
+
planEventDeliveryService,
|
|
1268
|
+
run: (tx, emittedEvents) =>
|
|
1269
|
+
Effect.gen(function* () {
|
|
1270
|
+
const persisted = yield* persistHumanNodeResponseAttemptEffect(context, {
|
|
1271
|
+
tx,
|
|
1272
|
+
submission,
|
|
1273
|
+
respondedBy: params.respondedBy,
|
|
1274
|
+
approvalMessageId: params.approvalMessageId,
|
|
1275
|
+
response: params.response,
|
|
1276
|
+
})
|
|
1249
1277
|
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
tx,
|
|
1253
|
-
emittedEvents,
|
|
1254
|
-
submission,
|
|
1255
|
-
persisted,
|
|
1256
|
-
respondedBy: params.respondedBy,
|
|
1257
|
-
})
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
return yield* handleAcceptedHumanNodeResponseEffect(context, {
|
|
1278
|
+
if (submission.validation.blocking.length > 0) {
|
|
1279
|
+
return yield* handleBlockedHumanNodeResponseEffect(context, {
|
|
1261
1280
|
tx,
|
|
1262
1281
|
emittedEvents,
|
|
1263
1282
|
submission,
|
|
1264
1283
|
persisted,
|
|
1265
1284
|
respondedBy: params.respondedBy,
|
|
1266
1285
|
})
|
|
1267
|
-
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
return yield* handleAcceptedHumanNodeResponseEffect(context, {
|
|
1289
|
+
tx,
|
|
1290
|
+
emittedEvents,
|
|
1291
|
+
submission,
|
|
1292
|
+
persisted,
|
|
1293
|
+
respondedBy: params.respondedBy,
|
|
1294
|
+
})
|
|
1295
|
+
}),
|
|
1296
|
+
}).pipe(Effect.withSpan('PlanExecutor.submitHumanNodeResponse.persistTransaction'))
|
|
1297
|
+
})
|
|
1271
1298
|
|
|
1272
1299
|
/** @lintignore */
|
|
1273
|
-
function
|
|
1300
|
+
function submitHumanNodeResponse(
|
|
1301
|
+
context: PlanExecutorContext,
|
|
1302
|
+
params: {
|
|
1303
|
+
threadId: RecordIdInput
|
|
1304
|
+
approvalId?: string
|
|
1305
|
+
respondedBy: string
|
|
1306
|
+
response: HumanNodeResponsePayload
|
|
1307
|
+
approvalMessageId?: string
|
|
1308
|
+
},
|
|
1309
|
+
): Promise<SerializableExecutionPlan | null> {
|
|
1310
|
+
return submitHumanNodeResponseEffect(context, params).pipe(runPromise)
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
const resumeRunEffect = Effect.fn('PlanExecutor.resumeRun')(function* (
|
|
1274
1314
|
context: PlanExecutorContext,
|
|
1275
1315
|
params: { threadId: RecordIdInput; runId: string; emittedBy: string },
|
|
1276
|
-
)
|
|
1316
|
+
) {
|
|
1277
1317
|
const { databaseService, planEventDeliveryService, planRunService } = context
|
|
1278
1318
|
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1319
|
+
const run = yield* planRunService.getRunById(params.runId)
|
|
1320
|
+
const spec = yield* planRunService.getPlanSpecById(run.planSpecId)
|
|
1321
|
+
const [nodeSpecs, nodeRuns, artifacts, latestCheckpoint, nextCheckpointSequence] = yield* Effect.all([
|
|
1322
|
+
planRunService.listNodeSpecs(spec.id),
|
|
1323
|
+
planRunService.listNodeRuns(run.id),
|
|
1324
|
+
planRunService.listArtifacts(run.id),
|
|
1325
|
+
planRunService.getLatestCheckpoint(run.id),
|
|
1326
|
+
planRunService.getNextCheckpointSequence(run.id),
|
|
1327
|
+
]).pipe(Effect.withSpan('PlanExecutor.resumeRun.loadRunGraph'))
|
|
1328
|
+
|
|
1329
|
+
const snapshot = yield* withTransactionAndEventsEffect({
|
|
1330
|
+
db: databaseService,
|
|
1331
|
+
planEventDeliveryService,
|
|
1332
|
+
run: (tx, emittedEvents) =>
|
|
1333
|
+
Effect.gen(function* () {
|
|
1334
|
+
let currentNodeRuns = [...nodeRuns]
|
|
1335
|
+
for (const currentNodeRun of currentNodeRuns.filter((candidate) => candidate.status === 'running')) {
|
|
1336
|
+
const resetNodeRunRow = yield* fromPromise(() =>
|
|
1337
|
+
tx
|
|
1338
|
+
.update(ensureRecordId(currentNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
1339
|
+
.content(
|
|
1340
|
+
toNodeRunData(currentNodeRun, {
|
|
1341
|
+
status: 'ready',
|
|
1342
|
+
readyAt: nowDate(),
|
|
1343
|
+
startedAt: currentNodeRun.startedAt ?? nowDate(),
|
|
1344
|
+
}),
|
|
1345
|
+
)
|
|
1346
|
+
.output('after'),
|
|
1347
|
+
)
|
|
1348
|
+
const resetNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, resetNodeRunRow, 'plan node run')
|
|
1349
|
+
currentNodeRuns = currentNodeRuns.map((candidate) =>
|
|
1350
|
+
candidate.nodeId === resetNodeRun.nodeId ? resetNodeRun : candidate,
|
|
1351
|
+
)
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
const resetRun = yield* replaceRun(tx, run, {
|
|
1355
|
+
status: run.status === 'awaiting-human' ? 'awaiting-human' : 'running',
|
|
1356
|
+
currentNodeId: run.status === 'awaiting-human' ? (run.currentNodeId ?? null) : null,
|
|
1357
|
+
waitingNodeId: run.status === 'awaiting-human' ? (run.waitingNodeId ?? null) : null,
|
|
1358
|
+
readyNodeIds: currentNodeRuns
|
|
1359
|
+
.filter((candidate) => candidate.status === 'ready')
|
|
1360
|
+
.map((candidate) => candidate.nodeId),
|
|
1361
|
+
})
|
|
1322
1362
|
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1363
|
+
yield* emitEvent({
|
|
1364
|
+
tx,
|
|
1365
|
+
run: resetRun,
|
|
1366
|
+
spec,
|
|
1367
|
+
eventType: 'run-resumed',
|
|
1368
|
+
fromStatus: run.status,
|
|
1369
|
+
toStatus: resetRun.status,
|
|
1370
|
+
message: `Run "${spec.title}" resumed from the latest checkpoint.`,
|
|
1371
|
+
detail: latestCheckpoint
|
|
1372
|
+
? { checkpointId: recordIdToString(latestCheckpoint.id, TABLES.PLAN_CHECKPOINT) }
|
|
1373
|
+
: {},
|
|
1374
|
+
emittedBy: params.emittedBy,
|
|
1375
|
+
capturedEvents: emittedEvents,
|
|
1376
|
+
})
|
|
1337
1377
|
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1378
|
+
const synced =
|
|
1379
|
+
resetRun.status === 'awaiting-human'
|
|
1380
|
+
? { run: resetRun, nodeRuns: currentNodeRuns, artifacts }
|
|
1381
|
+
: yield* fromPromise(() =>
|
|
1382
|
+
syncRunGraph(context, {
|
|
1383
|
+
tx,
|
|
1384
|
+
run: resetRun,
|
|
1385
|
+
spec,
|
|
1386
|
+
nodeSpecs,
|
|
1387
|
+
nodeRuns: currentNodeRuns,
|
|
1388
|
+
artifacts,
|
|
1389
|
+
emittedBy: params.emittedBy,
|
|
1390
|
+
capturedEvents: emittedEvents,
|
|
1391
|
+
}),
|
|
1392
|
+
)
|
|
1393
|
+
|
|
1394
|
+
const checkpoint = yield* saveCheckpointWithContext(context, {
|
|
1395
|
+
tx,
|
|
1396
|
+
run: synced.run,
|
|
1397
|
+
spec,
|
|
1398
|
+
nodeRuns: synced.nodeRuns,
|
|
1399
|
+
artifacts: synced.artifacts,
|
|
1400
|
+
sequence: nextCheckpointSequence,
|
|
1401
|
+
reason: 'run-resumed',
|
|
1402
|
+
capturedEvents: emittedEvents,
|
|
1403
|
+
})
|
|
1404
|
+
yield* attachCheckpoint(tx, synced.run, checkpoint)
|
|
1405
|
+
const latestRun = yield* planRunService.getRunById(run.id)
|
|
1406
|
+
return yield* serializeRunFull(planRunService, latestRun)
|
|
1407
|
+
}),
|
|
1408
|
+
}).pipe(Effect.withSpan('PlanExecutor.resumeRun.persistTransaction'))
|
|
1369
1409
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1410
|
+
return buildExecutionPlanToolResult({
|
|
1411
|
+
action: 'run-resumed',
|
|
1412
|
+
plan: snapshot,
|
|
1413
|
+
message: `Resumed execution run "${snapshot.title}".`,
|
|
1414
|
+
})
|
|
1415
|
+
})
|
|
1416
|
+
|
|
1417
|
+
/** @lintignore */
|
|
1418
|
+
function resumeRun(
|
|
1419
|
+
context: PlanExecutorContext,
|
|
1420
|
+
params: { threadId: RecordIdInput; runId: string; emittedBy: string },
|
|
1421
|
+
): Promise<ExecutionPlanToolResultData> {
|
|
1422
|
+
return resumeRunEffect(context, params).pipe(runPromise)
|
|
1376
1423
|
}
|
|
1377
1424
|
|
|
1425
|
+
const transitionNodeToRunningEffect = Effect.fn('PlanExecutor.transitionNodeToRunning')(function* (
|
|
1426
|
+
context: PlanExecutorContext,
|
|
1427
|
+
params: { runId: string; nodeId: string },
|
|
1428
|
+
) {
|
|
1429
|
+
const { databaseService, planRunService } = context
|
|
1430
|
+
|
|
1431
|
+
const run = yield* planRunService.getRunById(params.runId)
|
|
1432
|
+
const nodeRun = yield* planRunService.getNodeRunByNodeId(run.id, params.nodeId)
|
|
1433
|
+
if (nodeRun.status !== 'ready') return
|
|
1434
|
+
|
|
1435
|
+
yield* withDatabaseTransactionEffect(databaseService, (tx) =>
|
|
1436
|
+
Effect.gen(function* () {
|
|
1437
|
+
const runningNodeRunRow = yield* fromPromise(() =>
|
|
1438
|
+
tx
|
|
1439
|
+
.update(ensureRecordId(nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
1440
|
+
.content(toNodeRunData(nodeRun, { status: 'running', startedAt: nodeRun.startedAt ?? nowDate() }))
|
|
1441
|
+
.output('after'),
|
|
1442
|
+
)
|
|
1443
|
+
const runningNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, runningNodeRunRow, 'plan node run')
|
|
1444
|
+
|
|
1445
|
+
const nodeRuns = yield* planRunService.listNodeRuns(run.id)
|
|
1446
|
+
yield* replaceRun(tx, run, {
|
|
1447
|
+
status: 'running',
|
|
1448
|
+
currentNodeId: runningNodeRun.nodeId,
|
|
1449
|
+
waitingNodeId: null,
|
|
1450
|
+
readyNodeIds: nodeRuns
|
|
1451
|
+
.filter((candidate) => candidate.status === 'ready' && candidate.nodeId !== runningNodeRun.nodeId)
|
|
1452
|
+
.map((candidate) => candidate.nodeId),
|
|
1453
|
+
})
|
|
1454
|
+
}),
|
|
1455
|
+
).pipe(Effect.withSpan('PlanExecutor.transitionNodeToRunning.persistTransaction'))
|
|
1456
|
+
})
|
|
1457
|
+
|
|
1378
1458
|
/** @lintignore */
|
|
1379
1459
|
function transitionNodeToRunning(
|
|
1380
1460
|
context: PlanExecutorContext,
|
|
1381
1461
|
params: { runId: string; nodeId: string },
|
|
1382
1462
|
): Promise<void> {
|
|
1383
|
-
|
|
1463
|
+
return transitionNodeToRunningEffect(context, params).pipe(runPromise)
|
|
1464
|
+
}
|
|
1384
1465
|
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1466
|
+
const blockNodeOnDispatchFailureEffect = Effect.fn('PlanExecutor.blockNodeOnDispatchFailure')(function* (
|
|
1467
|
+
context: PlanExecutorContext,
|
|
1468
|
+
params: {
|
|
1469
|
+
threadId: RecordIdInput
|
|
1470
|
+
runId: string
|
|
1471
|
+
nodeId: string
|
|
1472
|
+
emittedBy: string
|
|
1473
|
+
message: string
|
|
1474
|
+
failureClass: PlanFailureClass
|
|
1475
|
+
},
|
|
1476
|
+
) {
|
|
1477
|
+
const { databaseService, planEventDeliveryService, planRunService } = context
|
|
1389
1478
|
|
|
1390
|
-
|
|
1479
|
+
const run = yield* planRunService.getRunById(params.runId)
|
|
1480
|
+
const spec = yield* planRunService.getPlanSpecById(run.planSpecId)
|
|
1481
|
+
const [nodeSpec, nodeRun, artifacts, nextCheckpointSequence] = yield* Effect.all([
|
|
1482
|
+
planRunService.getNodeSpecByNodeId(spec.id, params.nodeId),
|
|
1483
|
+
planRunService.getNodeRunByNodeId(run.id, params.nodeId),
|
|
1484
|
+
planRunService.listArtifacts(run.id),
|
|
1485
|
+
planRunService.getNextCheckpointSequence(run.id),
|
|
1486
|
+
]).pipe(Effect.withSpan('PlanExecutor.blockNodeOnDispatchFailure.loadNodeContext'))
|
|
1487
|
+
|
|
1488
|
+
return yield* withTransactionAndEventsEffect({
|
|
1489
|
+
db: databaseService,
|
|
1490
|
+
planEventDeliveryService,
|
|
1491
|
+
run: (tx, emittedEvents) =>
|
|
1391
1492
|
Effect.gen(function* () {
|
|
1392
|
-
|
|
1393
|
-
|
|
1493
|
+
let blockedNodeRun: PlanNodeRunRecord
|
|
1494
|
+
if (nodeRun.status === 'blocked') {
|
|
1495
|
+
blockedNodeRun = nodeRun
|
|
1496
|
+
} else {
|
|
1497
|
+
const blockedNodeRunRow = yield* fromPromise(() =>
|
|
1394
1498
|
tx
|
|
1395
1499
|
.update(ensureRecordId(nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
1396
|
-
.content(
|
|
1500
|
+
.content(
|
|
1501
|
+
toNodeRunData(nodeRun, {
|
|
1502
|
+
status: 'blocked',
|
|
1503
|
+
blockedReason: params.message,
|
|
1504
|
+
failureClass: params.failureClass,
|
|
1505
|
+
}),
|
|
1506
|
+
)
|
|
1397
1507
|
.output('after'),
|
|
1398
|
-
)
|
|
1399
|
-
|
|
1508
|
+
)
|
|
1509
|
+
blockedNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, blockedNodeRunRow, 'plan node run')
|
|
1510
|
+
}
|
|
1400
1511
|
|
|
1401
|
-
const
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
currentNodeId: runningNodeRun.nodeId,
|
|
1512
|
+
const blockedRun = yield* replaceRun(tx, run, {
|
|
1513
|
+
status: 'blocked',
|
|
1514
|
+
currentNodeId: blockedNodeRun.nodeId,
|
|
1405
1515
|
waitingNodeId: null,
|
|
1406
|
-
readyNodeIds:
|
|
1407
|
-
|
|
1408
|
-
.map((candidate) => candidate.nodeId),
|
|
1516
|
+
readyNodeIds: [],
|
|
1517
|
+
failureCount: run.failureCount + 1,
|
|
1409
1518
|
})
|
|
1519
|
+
|
|
1520
|
+
yield* emitEvent({
|
|
1521
|
+
tx,
|
|
1522
|
+
run: blockedRun,
|
|
1523
|
+
spec,
|
|
1524
|
+
nodeId: blockedNodeRun.nodeId,
|
|
1525
|
+
eventType: 'node-blocked',
|
|
1526
|
+
fromStatus: nodeRun.status,
|
|
1527
|
+
toStatus: blockedNodeRun.status,
|
|
1528
|
+
message: `Node "${nodeSpec.label}" failed during owner dispatch.`,
|
|
1529
|
+
detail: { failureClass: params.failureClass, phase: 'dispatch', error: params.message },
|
|
1530
|
+
emittedBy: params.emittedBy,
|
|
1531
|
+
capturedEvents: emittedEvents,
|
|
1532
|
+
})
|
|
1533
|
+
|
|
1534
|
+
const checkpointNodeRuns = (yield* planRunService.listNodeRuns(run.id)).map((candidate) =>
|
|
1535
|
+
candidate.nodeId === blockedNodeRun.nodeId ? blockedNodeRun : candidate,
|
|
1536
|
+
)
|
|
1537
|
+
const checkpoint = yield* saveCheckpointWithContext(context, {
|
|
1538
|
+
tx,
|
|
1539
|
+
run: blockedRun,
|
|
1540
|
+
spec,
|
|
1541
|
+
nodeRuns: checkpointNodeRuns,
|
|
1542
|
+
artifacts,
|
|
1543
|
+
sequence: nextCheckpointSequence,
|
|
1544
|
+
reason: 'owner-dispatch-failed',
|
|
1545
|
+
capturedEvents: emittedEvents,
|
|
1546
|
+
})
|
|
1547
|
+
yield* attachCheckpoint(tx, blockedRun, checkpoint)
|
|
1548
|
+
const latestRun = yield* planRunService.getRunById(run.id)
|
|
1549
|
+
return yield* serializeRunFull(planRunService, latestRun)
|
|
1410
1550
|
}),
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
}
|
|
1551
|
+
}).pipe(Effect.withSpan('PlanExecutor.blockNodeOnDispatchFailure.persistTransaction'))
|
|
1552
|
+
})
|
|
1414
1553
|
|
|
1415
1554
|
/** @lintignore */
|
|
1416
1555
|
function blockNodeOnDispatchFailure(
|
|
@@ -1424,163 +1563,96 @@ function blockNodeOnDispatchFailure(
|
|
|
1424
1563
|
failureClass: PlanFailureClass
|
|
1425
1564
|
},
|
|
1426
1565
|
): Promise<SerializableExecutionPlan> {
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
return Effect.gen(function* () {
|
|
1430
|
-
const run = yield* planRunService.getRunById(params.runId)
|
|
1431
|
-
const spec = yield* planRunService.getPlanSpecById(run.planSpecId)
|
|
1432
|
-
const nodeSpec = yield* planRunService.getNodeSpecByNodeId(spec.id, params.nodeId)
|
|
1433
|
-
const nodeRun = yield* planRunService.getNodeRunByNodeId(run.id, params.nodeId)
|
|
1434
|
-
const artifacts = yield* planRunService.listArtifacts(run.id)
|
|
1435
|
-
const nextCheckpointSequence = yield* planRunService.getNextCheckpointSequence(run.id)
|
|
1436
|
-
|
|
1437
|
-
return yield* withTransactionAndEventsEffect({
|
|
1438
|
-
db: databaseService,
|
|
1439
|
-
planEventDeliveryService,
|
|
1440
|
-
run: (tx, emittedEvents) =>
|
|
1441
|
-
Effect.gen(function* () {
|
|
1442
|
-
const blockedNodeRun =
|
|
1443
|
-
nodeRun.status === 'blocked'
|
|
1444
|
-
? nodeRun
|
|
1445
|
-
: PlanNodeRunSchema.parse(
|
|
1446
|
-
yield* fromPromise(() =>
|
|
1447
|
-
tx
|
|
1448
|
-
.update(ensureRecordId(nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
1449
|
-
.content(
|
|
1450
|
-
toNodeRunData(nodeRun, {
|
|
1451
|
-
status: 'blocked',
|
|
1452
|
-
blockedReason: params.message,
|
|
1453
|
-
failureClass: params.failureClass,
|
|
1454
|
-
}),
|
|
1455
|
-
)
|
|
1456
|
-
.output('after'),
|
|
1457
|
-
),
|
|
1458
|
-
)
|
|
1459
|
-
|
|
1460
|
-
const blockedRun = yield* replaceRun(tx, run, {
|
|
1461
|
-
status: 'blocked',
|
|
1462
|
-
currentNodeId: blockedNodeRun.nodeId,
|
|
1463
|
-
waitingNodeId: null,
|
|
1464
|
-
readyNodeIds: [],
|
|
1465
|
-
failureCount: run.failureCount + 1,
|
|
1466
|
-
})
|
|
1467
|
-
|
|
1468
|
-
yield* emitEvent({
|
|
1469
|
-
tx,
|
|
1470
|
-
run: blockedRun,
|
|
1471
|
-
spec,
|
|
1472
|
-
nodeId: blockedNodeRun.nodeId,
|
|
1473
|
-
eventType: 'node-blocked',
|
|
1474
|
-
fromStatus: nodeRun.status,
|
|
1475
|
-
toStatus: blockedNodeRun.status,
|
|
1476
|
-
message: `Node "${nodeSpec.label}" failed during owner dispatch.`,
|
|
1477
|
-
detail: { failureClass: params.failureClass, phase: 'dispatch', error: params.message },
|
|
1478
|
-
emittedBy: params.emittedBy,
|
|
1479
|
-
capturedEvents: emittedEvents,
|
|
1480
|
-
})
|
|
1481
|
-
|
|
1482
|
-
const checkpointNodeRuns = (yield* planRunService.listNodeRuns(run.id)).map((candidate) =>
|
|
1483
|
-
candidate.nodeId === blockedNodeRun.nodeId ? blockedNodeRun : candidate,
|
|
1484
|
-
)
|
|
1485
|
-
const checkpoint = yield* saveCheckpointWithContext(context, {
|
|
1486
|
-
tx,
|
|
1487
|
-
run: blockedRun,
|
|
1488
|
-
spec,
|
|
1489
|
-
nodeRuns: checkpointNodeRuns,
|
|
1490
|
-
artifacts,
|
|
1491
|
-
sequence: nextCheckpointSequence,
|
|
1492
|
-
reason: 'owner-dispatch-failed',
|
|
1493
|
-
capturedEvents: emittedEvents,
|
|
1494
|
-
})
|
|
1495
|
-
yield* attachCheckpoint(tx, blockedRun, checkpoint)
|
|
1496
|
-
const latestRun = yield* planRunService.getRunById(run.id)
|
|
1497
|
-
return yield* serializeRunFull(planRunService, latestRun)
|
|
1498
|
-
}),
|
|
1499
|
-
})
|
|
1500
|
-
}).pipe(runPromise)
|
|
1566
|
+
return blockNodeOnDispatchFailureEffect(context, params).pipe(runPromise)
|
|
1501
1567
|
}
|
|
1502
1568
|
|
|
1503
|
-
|
|
1504
|
-
function promoteDelayedNode(
|
|
1569
|
+
const promoteDelayedNodeEffect = Effect.fn('PlanExecutor.promoteDelayedNode')(function* (
|
|
1505
1570
|
context: PlanExecutorContext,
|
|
1506
1571
|
params: { runId: string; nodeId: string; emittedBy: string },
|
|
1507
|
-
)
|
|
1572
|
+
) {
|
|
1508
1573
|
const { databaseService, planEventDeliveryService, planRunService } = context
|
|
1509
1574
|
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
}
|
|
1575
|
+
const run = yield* planRunService.getRunById(params.runId)
|
|
1576
|
+
if (run.status === 'completed' || run.status === 'failed' || run.status === 'aborted') {
|
|
1577
|
+
return
|
|
1578
|
+
}
|
|
1515
1579
|
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
const nodeRuns = yield* planRunService.listNodeRuns(run.id)
|
|
1522
|
-
const artifacts = yield* planRunService.listArtifacts(run.id)
|
|
1523
|
-
const nextCheckpointSequence = yield* planRunService.getNextCheckpointSequence(run.id)
|
|
1524
|
-
|
|
1525
|
-
yield* withTransactionAndEventsEffect({
|
|
1526
|
-
db: databaseService,
|
|
1527
|
-
planEventDeliveryService,
|
|
1528
|
-
run: (tx, emittedEvents) =>
|
|
1529
|
-
Effect.gen(function* () {
|
|
1530
|
-
const readyNodeRun = PlanNodeRunSchema.parse(
|
|
1531
|
-
yield* fromPromise(() =>
|
|
1532
|
-
tx
|
|
1533
|
-
.update(ensureRecordId(nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
1534
|
-
.content(toNodeRunData(nodeRun, { status: 'ready', readyAt: nowDate() }))
|
|
1535
|
-
.output('after'),
|
|
1536
|
-
),
|
|
1537
|
-
)
|
|
1580
|
+
const spec = yield* planRunService.getPlanSpecById(run.planSpecId)
|
|
1581
|
+
const nodeSpecs = yield* planRunService.listNodeSpecs(spec.id)
|
|
1582
|
+
const nodeRun = yield* planRunService.getNodeRunByNodeId(run.id, params.nodeId)
|
|
1583
|
+
if (nodeRun.status !== 'scheduled') return
|
|
1538
1584
|
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1585
|
+
const [nodeRuns, artifacts, nextCheckpointSequence] = yield* Effect.all([
|
|
1586
|
+
planRunService.listNodeRuns(run.id),
|
|
1587
|
+
planRunService.listArtifacts(run.id),
|
|
1588
|
+
planRunService.getNextCheckpointSequence(run.id),
|
|
1589
|
+
]).pipe(Effect.withSpan('PlanExecutor.promoteDelayedNode.loadRunContext'))
|
|
1542
1590
|
|
|
1543
|
-
|
|
1544
|
-
|
|
1591
|
+
yield* withTransactionAndEventsEffect({
|
|
1592
|
+
db: databaseService,
|
|
1593
|
+
planEventDeliveryService,
|
|
1594
|
+
run: (tx, emittedEvents) =>
|
|
1595
|
+
Effect.gen(function* () {
|
|
1596
|
+
const readyNodeRunRow = yield* fromPromise(() =>
|
|
1597
|
+
tx
|
|
1598
|
+
.update(ensureRecordId(nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
1599
|
+
.content(toNodeRunData(nodeRun, { status: 'ready', readyAt: nowDate() }))
|
|
1600
|
+
.output('after'),
|
|
1601
|
+
)
|
|
1602
|
+
const readyNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, readyNodeRunRow, 'plan node run')
|
|
1603
|
+
|
|
1604
|
+
const updatedNodeRuns = nodeRuns.map((candidate) =>
|
|
1605
|
+
candidate.nodeId === readyNodeRun.nodeId ? readyNodeRun : candidate,
|
|
1606
|
+
)
|
|
1607
|
+
|
|
1608
|
+
const currentNodeSpec = nodeSpecs.find((s) => s.nodeId === params.nodeId)
|
|
1609
|
+
yield* emitEvent({
|
|
1610
|
+
tx,
|
|
1611
|
+
run,
|
|
1612
|
+
spec,
|
|
1613
|
+
nodeId: readyNodeRun.nodeId,
|
|
1614
|
+
eventType: 'node-ready',
|
|
1615
|
+
fromStatus: nodeRun.status,
|
|
1616
|
+
toStatus: readyNodeRun.status,
|
|
1617
|
+
message: `Node "${currentNodeSpec?.label ?? params.nodeId}" promoted to ready after delay.`,
|
|
1618
|
+
emittedBy: params.emittedBy,
|
|
1619
|
+
capturedEvents: emittedEvents,
|
|
1620
|
+
})
|
|
1621
|
+
|
|
1622
|
+
const synced = yield* fromPromise(() =>
|
|
1623
|
+
syncRunGraph(context, {
|
|
1545
1624
|
tx,
|
|
1546
1625
|
run,
|
|
1547
1626
|
spec,
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
toStatus: readyNodeRun.status,
|
|
1552
|
-
message: `Node "${currentNodeSpec?.label ?? params.nodeId}" promoted to ready after delay.`,
|
|
1627
|
+
nodeSpecs,
|
|
1628
|
+
nodeRuns: updatedNodeRuns,
|
|
1629
|
+
artifacts,
|
|
1553
1630
|
emittedBy: params.emittedBy,
|
|
1554
1631
|
capturedEvents: emittedEvents,
|
|
1555
|
-
})
|
|
1632
|
+
}),
|
|
1633
|
+
)
|
|
1556
1634
|
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1635
|
+
const checkpoint = yield* saveCheckpointWithContext(context, {
|
|
1636
|
+
tx,
|
|
1637
|
+
run: synced.run,
|
|
1638
|
+
spec,
|
|
1639
|
+
nodeRuns: synced.nodeRuns,
|
|
1640
|
+
artifacts: synced.artifacts,
|
|
1641
|
+
sequence: nextCheckpointSequence,
|
|
1642
|
+
reason: 'delayed-node-promoted',
|
|
1643
|
+
capturedEvents: emittedEvents,
|
|
1644
|
+
})
|
|
1645
|
+
yield* attachCheckpoint(tx, synced.run, checkpoint)
|
|
1646
|
+
}),
|
|
1647
|
+
}).pipe(Effect.withSpan('PlanExecutor.promoteDelayedNode.persistTransaction'))
|
|
1648
|
+
})
|
|
1569
1649
|
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
sequence: nextCheckpointSequence,
|
|
1577
|
-
reason: 'delayed-node-promoted',
|
|
1578
|
-
capturedEvents: emittedEvents,
|
|
1579
|
-
})
|
|
1580
|
-
yield* attachCheckpoint(tx, synced.run, checkpoint)
|
|
1581
|
-
}),
|
|
1582
|
-
})
|
|
1583
|
-
}).pipe(runPromise)
|
|
1650
|
+
/** @lintignore */
|
|
1651
|
+
function promoteDelayedNode(
|
|
1652
|
+
context: PlanExecutorContext,
|
|
1653
|
+
params: { runId: string; nodeId: string; emittedBy: string },
|
|
1654
|
+
): Promise<void> {
|
|
1655
|
+
return promoteDelayedNodeEffect(context, params).pipe(runPromise)
|
|
1584
1656
|
}
|
|
1585
1657
|
|
|
1586
1658
|
export function makePlanExecutorService(deps: PlanExecutorDeps) {
|
|
@@ -1611,14 +1683,25 @@ export function makePlanExecutorService(deps: PlanExecutorDeps) {
|
|
|
1611
1683
|
|
|
1612
1684
|
return {
|
|
1613
1685
|
submitNodeResult: (params: Parameters<typeof submitNodeResult>[1]) => submitNodeResult(context, params),
|
|
1686
|
+
submitNodeResultEffect: (params: Parameters<typeof submitNodeResultEffect>[1]) =>
|
|
1687
|
+
submitNodeResultEffect(context, params),
|
|
1614
1688
|
submitHumanNodeResponse: (params: Parameters<typeof submitHumanNodeResponse>[1]) =>
|
|
1615
1689
|
submitHumanNodeResponse(context, params),
|
|
1690
|
+
submitHumanNodeResponseEffect: (params: Parameters<typeof submitHumanNodeResponseEffect>[1]) =>
|
|
1691
|
+
submitHumanNodeResponseEffect(context, params),
|
|
1616
1692
|
resumeRun: (params: Parameters<typeof resumeRun>[1]) => resumeRun(context, params),
|
|
1693
|
+
resumeRunEffect: (params: Parameters<typeof resumeRunEffect>[1]) => resumeRunEffect(context, params),
|
|
1617
1694
|
transitionNodeToRunning: (params: Parameters<typeof transitionNodeToRunning>[1]) =>
|
|
1618
1695
|
transitionNodeToRunning(context, params),
|
|
1696
|
+
transitionNodeToRunningEffect: (params: Parameters<typeof transitionNodeToRunningEffect>[1]) =>
|
|
1697
|
+
transitionNodeToRunningEffect(context, params),
|
|
1619
1698
|
blockNodeOnDispatchFailure: (params: Parameters<typeof blockNodeOnDispatchFailure>[1]) =>
|
|
1620
1699
|
blockNodeOnDispatchFailure(context, params),
|
|
1700
|
+
blockNodeOnDispatchFailureEffect: (params: Parameters<typeof blockNodeOnDispatchFailureEffect>[1]) =>
|
|
1701
|
+
blockNodeOnDispatchFailureEffect(context, params),
|
|
1621
1702
|
promoteDelayedNode: (params: Parameters<typeof promoteDelayedNode>[1]) => promoteDelayedNode(context, params),
|
|
1703
|
+
promoteDelayedNodeEffect: (params: Parameters<typeof promoteDelayedNodeEffect>[1]) =>
|
|
1704
|
+
promoteDelayedNodeEffect(context, params),
|
|
1622
1705
|
syncRunGraph: (params: Parameters<typeof syncRunGraph>[1]) => syncRunGraph(context, params),
|
|
1623
1706
|
resolveFailureAction,
|
|
1624
1707
|
buildResolvedInput,
|
|
@@ -1626,7 +1709,7 @@ export function makePlanExecutorService(deps: PlanExecutorDeps) {
|
|
|
1626
1709
|
}
|
|
1627
1710
|
|
|
1628
1711
|
export class PlanExecutorServiceTag extends Context.Service<PlanExecutorServiceTag, PlanExecutorService>()(
|
|
1629
|
-
'PlanExecutorService',
|
|
1712
|
+
'@lota-sdk/core/PlanExecutorService',
|
|
1630
1713
|
) {}
|
|
1631
1714
|
|
|
1632
1715
|
export const PlanExecutorServiceLive = Layer.effect(
|