@lota-sdk/core 0.4.13 → 0.4.15
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 +4 -4
- package/src/ai/embedding-cache.ts +17 -11
- package/src/ai-gateway/ai-gateway.ts +164 -94
- package/src/ai-gateway/index.ts +4 -1
- package/src/config/agent-defaults.ts +2 -2
- package/src/config/agent-types.ts +1 -1
- package/src/config/constants.ts +1 -1
- package/src/create-runtime.ts +259 -200
- package/src/db/cursor-pagination.ts +2 -9
- package/src/db/memory-store.ts +194 -175
- package/src/db/memory.ts +125 -71
- package/src/db/schema-fingerprint.ts +5 -4
- package/src/db/service-normalization.ts +4 -3
- package/src/db/service.ts +3 -2
- package/src/db/startup.ts +15 -16
- package/src/effect/errors.ts +161 -21
- package/src/effect/index.ts +0 -1
- package/src/embeddings/provider.ts +15 -7
- package/src/queues/autonomous-job.queue.ts +10 -22
- package/src/queues/delayed-node-promotion.queue.ts +8 -14
- package/src/queues/document-processor.queue.ts +13 -4
- package/src/queues/memory-consolidation.queue.ts +26 -14
- package/src/queues/plan-agent-heartbeat.queue.ts +48 -31
- package/src/queues/plan-scheduler.queue.ts +37 -15
- package/src/queues/queue-factory.ts +59 -35
- package/src/queues/standalone-worker.ts +3 -2
- package/src/redis/connection.ts +10 -3
- package/src/redis/org-memory-lock.ts +1 -1
- package/src/redis/redis-lease-lock.ts +5 -5
- package/src/redis/stream-context.ts +1 -1
- package/src/runtime/chat-message.ts +64 -1
- package/src/runtime/chat-run-orchestration.ts +33 -20
- package/src/runtime/context-compaction/context-compaction-runtime.ts +14 -7
- package/src/runtime/context-compaction/context-compaction.ts +78 -66
- package/src/runtime/domain-layer.ts +19 -13
- package/src/runtime/execution-plan.ts +7 -3
- package/src/runtime/memory/memory-block.ts +3 -9
- package/src/runtime/memory/memory-scope.ts +3 -1
- package/src/runtime/plugin-resolution.ts +2 -1
- package/src/runtime/post-turn-side-effects.ts +6 -5
- package/src/runtime/retrieval-adapters.ts +8 -20
- package/src/runtime/runtime-config.ts +3 -9
- package/src/runtime/runtime-extensions.ts +2 -4
- package/src/runtime/runtime-lifecycle.ts +56 -16
- package/src/runtime/runtime-services.ts +180 -102
- package/src/runtime/runtime-worker-registry.ts +3 -1
- package/src/runtime/social-chat/social-chat-agent-runner.ts +1 -1
- package/src/runtime/social-chat/social-chat-history.ts +21 -18
- package/src/runtime/social-chat/social-chat.ts +356 -223
- package/src/runtime/specialist-runner.ts +3 -1
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +3 -2
- package/src/runtime/thread-turn-context.ts +142 -102
- package/src/runtime/turn-lifecycle.ts +15 -46
- package/src/services/agent-activity.service.ts +1 -1
- package/src/services/agent-executor.service.ts +107 -77
- package/src/services/autonomous-job.service.ts +354 -293
- package/src/services/background-work.service.ts +3 -3
- package/src/services/context-compaction.service.ts +7 -2
- package/src/services/document-chunk.service.ts +50 -32
- package/src/services/execution-plan/execution-plan-schedule.ts +5 -3
- package/src/services/execution-plan/execution-plan.service.ts +162 -179
- package/src/services/feedback-loop.service.ts +5 -4
- package/src/services/graph-full-routing.ts +37 -36
- package/src/services/institutional-memory.service.ts +28 -30
- package/src/services/learned-skill.service.ts +107 -72
- package/src/services/memory/memory-errors.ts +4 -23
- package/src/services/memory/memory-org-memory.ts +10 -5
- package/src/services/memory/memory-rerank.ts +18 -6
- package/src/services/memory/memory.service.ts +170 -111
- package/src/services/memory/rerank.service.ts +29 -20
- package/src/services/organization-member.service.ts +1 -1
- package/src/services/organization.service.ts +69 -75
- package/src/services/ownership-dispatcher.service.ts +40 -39
- package/src/services/plan/plan-agent-heartbeat.service.ts +22 -24
- package/src/services/plan/plan-agent-query.service.ts +39 -31
- package/src/services/plan/plan-completion-side-effects.ts +13 -17
- package/src/services/plan/plan-coordination.service.ts +2 -1
- package/src/services/plan/plan-cycle.service.ts +6 -5
- package/src/services/plan/plan-deadline.service.ts +57 -54
- package/src/services/plan/plan-event-delivery.service.ts +5 -4
- package/src/services/plan/plan-executor-graph.ts +18 -15
- package/src/services/plan/plan-executor.service.ts +235 -262
- package/src/services/plan/plan-run.service.ts +169 -93
- package/src/services/plan/plan-scheduler.service.ts +192 -202
- package/src/services/plan/plan-template.service.ts +1 -1
- package/src/services/plan/plan-transaction-events.ts +1 -1
- package/src/services/plan/plan-workspace.service.ts +23 -14
- package/src/services/plugin-executor.service.ts +5 -9
- package/src/services/queue-job.service.ts +117 -59
- package/src/services/recent-activity-title.service.ts +13 -12
- package/src/services/recent-activity.service.ts +6 -1
- package/src/services/social-chat-history.service.ts +29 -25
- package/src/services/system-executor.service.ts +5 -9
- package/src/services/thread/thread-active-run.ts +2 -2
- package/src/services/thread/thread-listing.ts +61 -57
- package/src/services/thread/thread-memory-block.ts +73 -48
- package/src/services/thread/thread-message.service.ts +76 -65
- package/src/services/thread/thread-record-store.ts +8 -8
- package/src/services/thread/thread-title.service.ts +10 -4
- package/src/services/thread/thread-turn-execution.ts +43 -45
- package/src/services/thread/thread-turn-preparation.service.ts +257 -135
- package/src/services/thread/thread-turn-streaming.ts +83 -92
- package/src/services/thread/thread-turn.ts +18 -16
- package/src/services/thread/thread.service.ts +135 -100
- package/src/services/user.service.ts +45 -48
- package/src/storage/attachment-parser.ts +6 -2
- package/src/storage/attachment-storage.service.ts +5 -6
- package/src/storage/generated-document-storage.service.ts +1 -1
- package/src/system-agents/context-compaction.agent.ts +10 -9
- package/src/system-agents/delegated-agent-factory.ts +30 -6
- package/src/system-agents/memory-reranker.agent.ts +10 -9
- package/src/system-agents/memory.agent.ts +10 -9
- package/src/system-agents/recent-activity-title-refiner.agent.ts +13 -15
- package/src/system-agents/regular-chat-memory-digest.agent.ts +13 -12
- package/src/system-agents/skill-extractor.agent.ts +13 -12
- package/src/system-agents/skill-manager.agent.ts +13 -12
- package/src/system-agents/thread-router.agent.ts +11 -7
- package/src/system-agents/title-generator.agent.ts +13 -12
- package/src/tools/fetch-webpage.tool.ts +13 -13
- package/src/tools/memory-block.tool.ts +3 -1
- package/src/tools/plan-approval.tool.ts +4 -2
- package/src/tools/read-file-parts.tool.ts +10 -4
- package/src/tools/remember-memory.tool.ts +3 -1
- package/src/tools/research-topic.tool.ts +9 -5
- package/src/tools/search-web.tool.ts +16 -16
- package/src/tools/search.tool.ts +20 -5
- package/src/tools/team-think.tool.ts +61 -38
- package/src/utils/async.ts +5 -5
- package/src/utils/errors.ts +19 -18
- package/src/utils/sse-keepalive.ts +28 -25
- package/src/workers/bootstrap.ts +75 -11
- package/src/workers/memory-consolidation.worker.ts +82 -91
- package/src/workers/organization-learning.worker.ts +14 -4
- package/src/workers/regular-chat-memory-digest.runner.ts +105 -67
- package/src/workers/skill-extraction.runner.ts +97 -61
- package/src/workers/utils/repo-structure-extractor.ts +13 -8
- package/src/workers/utils/thread-message-query.ts +24 -24
- package/src/workers/worker-utils.ts +23 -4
- package/src/effect/helpers.ts +0 -123
|
@@ -8,8 +8,7 @@ import type { RecordIdInput } from '../../db/record-id'
|
|
|
8
8
|
import { ensureRecordId, recordIdToString } from '../../db/record-id'
|
|
9
9
|
import type { DatabaseTransaction } from '../../db/service'
|
|
10
10
|
import { TABLES } from '../../db/tables'
|
|
11
|
-
import { BadRequestError, NotFoundError } from '../../effect/errors'
|
|
12
|
-
import { effectTryPromise as effectTryPromiseShared } from '../../effect/helpers'
|
|
11
|
+
import { ERROR_TAGS, BadRequestError, NotFoundError } from '../../effect/errors'
|
|
13
12
|
import { DatabaseServiceTag } from '../../effect/services'
|
|
14
13
|
import type { DelayedNodePromotionQueueRuntime } from '../../queues/delayed-node-promotion.queue'
|
|
15
14
|
import { LotaQueuesServiceTag } from '../../queues/queues.service'
|
|
@@ -17,7 +16,7 @@ import { GeneratedDocumentStorageServiceTag } from '../../storage/generated-docu
|
|
|
17
16
|
import { nowDate } from '../../utils/date-time'
|
|
18
17
|
import { toError } from '../../utils/errors'
|
|
19
18
|
import { ArtifactServiceTag } from '../artifact.service'
|
|
20
|
-
import {
|
|
19
|
+
import { BackgroundWorkServiceTag } from '../background-work.service'
|
|
21
20
|
import { FeedbackLoopServiceTag } from '../feedback-loop.service'
|
|
22
21
|
import { InstitutionalMemoryServiceTag } from '../institutional-memory.service'
|
|
23
22
|
import { QualityMetricsServiceTag } from '../quality-metrics.service'
|
|
@@ -85,15 +84,12 @@ function saveCheckpointWithContext(
|
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
class PlanExecutorInternalError extends Schema.TaggedErrorClass<PlanExecutorInternalError>()(
|
|
88
|
-
'PlanExecutorInternalError',
|
|
87
|
+
'@lota-sdk/core/PlanExecutorInternalError',
|
|
89
88
|
{ message: Schema.String, cause: Schema.optional(Schema.Defect) },
|
|
90
89
|
) {}
|
|
91
90
|
|
|
92
|
-
function
|
|
93
|
-
return
|
|
94
|
-
thunk,
|
|
95
|
-
(cause) => new PlanExecutorInternalError({ message: toError(cause).message, cause }),
|
|
96
|
-
)
|
|
91
|
+
function toPlanExecutorInternalError(cause: unknown): PlanExecutorInternalError {
|
|
92
|
+
return new PlanExecutorInternalError({ message: toError(cause).message, cause })
|
|
97
93
|
}
|
|
98
94
|
|
|
99
95
|
function parseRowOrFail<T>(
|
|
@@ -320,25 +316,24 @@ function persistNodeResultAttemptEffect(
|
|
|
320
316
|
issues: [...submission.validation.blocking, ...submission.validation.warnings],
|
|
321
317
|
})
|
|
322
318
|
|
|
323
|
-
const updatedAttemptRow = yield*
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
.
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
)
|
|
341
|
-
void (yield* parseRowOrFail(PlanNodeAttemptSchema, updatedAttemptRow, 'plan node attempt'))
|
|
319
|
+
const updatedAttemptRow = yield* tx
|
|
320
|
+
.update(ensureRecordId(attempt.id, TABLES.PLAN_NODE_ATTEMPT))
|
|
321
|
+
.content({
|
|
322
|
+
runId: ensureRecordId(attempt.runId, TABLES.PLAN_RUN),
|
|
323
|
+
nodeRunId: ensureRecordId(attempt.nodeRunId, TABLES.PLAN_NODE_RUN),
|
|
324
|
+
nodeId: attempt.nodeId,
|
|
325
|
+
emittedBy: attempt.emittedBy,
|
|
326
|
+
status: attempt.status,
|
|
327
|
+
...(attempt.structuredOutput ? { structuredOutput: attempt.structuredOutput } : {}),
|
|
328
|
+
...(attempt.notes ? { notes: attempt.notes } : {}),
|
|
329
|
+
validationIssueIds: issues.map((issue: { id: RecordIdInput }) =>
|
|
330
|
+
ensureRecordId(issue.id, TABLES.PLAN_VALIDATION_ISSUE),
|
|
331
|
+
),
|
|
332
|
+
...(attempt.failureClass ? { failureClass: attempt.failureClass } : {}),
|
|
333
|
+
})
|
|
334
|
+
.output('after')
|
|
335
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
336
|
+
yield* Effect.asVoid(parseRowOrFail(PlanNodeAttemptSchema, updatedAttemptRow, 'plan node attempt'))
|
|
342
337
|
|
|
343
338
|
const publishedArtifacts =
|
|
344
339
|
submission.validation.blocking.length > 0
|
|
@@ -362,19 +357,18 @@ function persistNodeResultAttemptEffect(
|
|
|
362
357
|
artifacts: publishedArtifacts,
|
|
363
358
|
})
|
|
364
359
|
|
|
365
|
-
const nextNodeRunRow = yield*
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
.
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
)
|
|
360
|
+
const nextNodeRunRow = yield* tx
|
|
361
|
+
.update(ensureRecordId(submission.nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
362
|
+
.content(
|
|
363
|
+
toNodeRunData(submission.nodeRun, {
|
|
364
|
+
attemptCount: submission.nodeRun.attemptCount + 1,
|
|
365
|
+
latestAttemptId: attempt.id,
|
|
366
|
+
latestStructuredOutput: result.structuredOutput ?? null,
|
|
367
|
+
latestNotes: result.notes,
|
|
368
|
+
}),
|
|
369
|
+
)
|
|
370
|
+
.output('after')
|
|
371
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
378
372
|
const nextNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, nextNodeRunRow, 'plan node run')
|
|
379
373
|
|
|
380
374
|
const nodeRuns = yield* context.planRunService.listNodeRuns(submission.run.id)
|
|
@@ -401,22 +395,21 @@ function handleRetryNodeResultEffect(
|
|
|
401
395
|
const { tx, emittedEvents, submission, persisted, emittedBy } = params
|
|
402
396
|
|
|
403
397
|
return Effect.gen(function* () {
|
|
404
|
-
const retryNodeRunRow = yield*
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
.
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
)
|
|
398
|
+
const retryNodeRunRow = yield* tx
|
|
399
|
+
.update(ensureRecordId(persisted.nextNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
400
|
+
.content(
|
|
401
|
+
toNodeRunData(persisted.nextNodeRun, {
|
|
402
|
+
status: 'ready',
|
|
403
|
+
retryCount: persisted.nextNodeRun.retryCount + 1,
|
|
404
|
+
failureClass: submission.validation.failureClass,
|
|
405
|
+
blockedReason: submission.validation.blocking[0]?.message ?? null,
|
|
406
|
+
readyAt: nowDate(),
|
|
407
|
+
startedAt: null,
|
|
408
|
+
completedAt: null,
|
|
409
|
+
}),
|
|
410
|
+
)
|
|
411
|
+
.output('after')
|
|
412
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
420
413
|
const retryNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, retryNodeRunRow, 'plan node run')
|
|
421
414
|
|
|
422
415
|
yield* emitEvent({
|
|
@@ -447,18 +440,16 @@ function handleRetryNodeResultEffect(
|
|
|
447
440
|
capturedEvents: emittedEvents,
|
|
448
441
|
})
|
|
449
442
|
|
|
450
|
-
const synced = yield*
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}),
|
|
461
|
-
)
|
|
443
|
+
const synced = yield* syncRunGraph(context, {
|
|
444
|
+
tx,
|
|
445
|
+
run: submission.run,
|
|
446
|
+
spec: submission.spec,
|
|
447
|
+
nodeSpecs: submission.nodeSpecs,
|
|
448
|
+
nodeRuns: replaceNodeRunInList(persisted.withUpdatedNodeRuns, retryNodeRun),
|
|
449
|
+
artifacts: persisted.nextArtifacts,
|
|
450
|
+
emittedBy,
|
|
451
|
+
capturedEvents: emittedEvents,
|
|
452
|
+
}).pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
462
453
|
|
|
463
454
|
yield* saveAndAttachCheckpointEffect(context, {
|
|
464
455
|
tx,
|
|
@@ -486,20 +477,19 @@ function handleHumanReviewNodeResultEffect(
|
|
|
486
477
|
const { tx, emittedEvents, submission, persisted, emittedBy } = params
|
|
487
478
|
|
|
488
479
|
return Effect.gen(function* () {
|
|
489
|
-
const awaitingHumanNodeRunRow = yield*
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
.
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
)
|
|
480
|
+
const awaitingHumanNodeRunRow = yield* tx
|
|
481
|
+
.update(ensureRecordId(persisted.nextNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
482
|
+
.content(
|
|
483
|
+
toNodeRunData(persisted.nextNodeRun, {
|
|
484
|
+
status: 'awaiting-human',
|
|
485
|
+
retryCount: persisted.nextNodeRun.retryCount + 1,
|
|
486
|
+
failureClass: submission.validation.failureClass,
|
|
487
|
+
blockedReason: submission.validation.blocking[0]?.message ?? null,
|
|
488
|
+
startedAt: persisted.nextNodeRun.startedAt ?? nowDate(),
|
|
489
|
+
}),
|
|
490
|
+
)
|
|
491
|
+
.output('after')
|
|
492
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
503
493
|
const awaitingHumanNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, awaitingHumanNodeRunRow, 'plan node run')
|
|
504
494
|
|
|
505
495
|
const approval = yield* context.planApprovalService
|
|
@@ -517,7 +507,7 @@ function handleHumanReviewNodeResultEffect(
|
|
|
517
507
|
validationIssues: submission.validation.blocking,
|
|
518
508
|
},
|
|
519
509
|
})
|
|
520
|
-
.pipe(Effect.mapError(
|
|
510
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
521
511
|
|
|
522
512
|
const awaitingHumanRun = yield* replaceRun(tx, submission.run, {
|
|
523
513
|
status: 'awaiting-human',
|
|
@@ -569,19 +559,18 @@ function handleReplanNodeResultEffect(
|
|
|
569
559
|
const { tx, emittedEvents, submission, persisted, emittedBy } = params
|
|
570
560
|
|
|
571
561
|
return Effect.gen(function* () {
|
|
572
|
-
const blockedNodeRunRow = yield*
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
.
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
)
|
|
562
|
+
const blockedNodeRunRow = yield* tx
|
|
563
|
+
.update(ensureRecordId(persisted.nextNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
564
|
+
.content(
|
|
565
|
+
toNodeRunData(persisted.nextNodeRun, {
|
|
566
|
+
status: 'blocked',
|
|
567
|
+
retryCount: persisted.nextNodeRun.retryCount + 1,
|
|
568
|
+
failureClass: submission.validation.failureClass,
|
|
569
|
+
blockedReason: submission.validation.blocking[0]?.message ?? null,
|
|
570
|
+
}),
|
|
571
|
+
)
|
|
572
|
+
.output('after')
|
|
573
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
585
574
|
const blockedNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, blockedNodeRunRow, 'plan node run')
|
|
586
575
|
|
|
587
576
|
const blockedRun = yield* replaceRun(tx, submission.run, {
|
|
@@ -636,20 +625,19 @@ function handleFailedNodeResultEffect(
|
|
|
636
625
|
const { tx, emittedEvents, submission, persisted, emittedBy } = params
|
|
637
626
|
|
|
638
627
|
return Effect.gen(function* () {
|
|
639
|
-
const failedNodeRunRow = yield*
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
.
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
)
|
|
628
|
+
const failedNodeRunRow = yield* tx
|
|
629
|
+
.update(ensureRecordId(persisted.nextNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
630
|
+
.content(
|
|
631
|
+
toNodeRunData(persisted.nextNodeRun, {
|
|
632
|
+
status: 'failed',
|
|
633
|
+
retryCount: persisted.nextNodeRun.retryCount + 1,
|
|
634
|
+
failureClass: submission.validation.failureClass,
|
|
635
|
+
blockedReason: submission.validation.blocking[0]?.message ?? null,
|
|
636
|
+
completedAt: nowDate(),
|
|
637
|
+
}),
|
|
638
|
+
)
|
|
639
|
+
.output('after')
|
|
640
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
653
641
|
const failedNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, failedNodeRunRow, 'plan node run')
|
|
654
642
|
|
|
655
643
|
const failedRun = yield* replaceRun(tx, submission.run, {
|
|
@@ -741,22 +729,21 @@ function handleSuccessfulNodeResultEffect(
|
|
|
741
729
|
const { tx, emittedEvents, submission, persisted, emittedBy, result } = params
|
|
742
730
|
|
|
743
731
|
return Effect.gen(function* () {
|
|
744
|
-
const completedNodeRunRow = yield*
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
.
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
)
|
|
732
|
+
const completedNodeRunRow = yield* tx
|
|
733
|
+
.update(ensureRecordId(persisted.nextNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
734
|
+
.content(
|
|
735
|
+
toNodeRunData(persisted.nextNodeRun, {
|
|
736
|
+
status: submission.validation.warnings.length > 0 ? 'partial' : 'completed',
|
|
737
|
+
latestAttemptId: persisted.attemptId,
|
|
738
|
+
latestStructuredOutput: result.structuredOutput ?? null,
|
|
739
|
+
latestNotes: result.notes,
|
|
740
|
+
blockedReason: null,
|
|
741
|
+
failureClass: null,
|
|
742
|
+
completedAt: nowDate(),
|
|
743
|
+
}),
|
|
744
|
+
)
|
|
745
|
+
.output('after')
|
|
746
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
760
747
|
const completedNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, completedNodeRunRow, 'plan node run')
|
|
761
748
|
|
|
762
749
|
yield* emitEvent({
|
|
@@ -777,18 +764,16 @@ function handleSuccessfulNodeResultEffect(
|
|
|
777
764
|
capturedEvents: emittedEvents,
|
|
778
765
|
})
|
|
779
766
|
|
|
780
|
-
const synced = yield*
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
}),
|
|
791
|
-
)
|
|
767
|
+
const synced = yield* syncRunGraph(context, {
|
|
768
|
+
tx,
|
|
769
|
+
run: submission.run,
|
|
770
|
+
spec: submission.spec,
|
|
771
|
+
nodeSpecs: submission.nodeSpecs,
|
|
772
|
+
nodeRuns: replaceNodeRunInList(persisted.withUpdatedNodeRuns, completedNodeRun),
|
|
773
|
+
artifacts: persisted.nextArtifacts,
|
|
774
|
+
emittedBy,
|
|
775
|
+
capturedEvents: emittedEvents,
|
|
776
|
+
}).pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
792
777
|
|
|
793
778
|
yield* saveAndAttachCheckpointEffect(context, {
|
|
794
779
|
tx,
|
|
@@ -954,43 +939,41 @@ function persistHumanNodeResponseAttemptEffect(
|
|
|
954
939
|
issues: [...submission.validation.blocking, ...submission.validation.warnings],
|
|
955
940
|
})
|
|
956
941
|
|
|
957
|
-
const updatedHumanAttemptRow = yield*
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
.
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
)
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
.output('after'),
|
|
993
|
-
)
|
|
942
|
+
const updatedHumanAttemptRow = yield* tx
|
|
943
|
+
.update(ensureRecordId(attempt.id, TABLES.PLAN_NODE_ATTEMPT))
|
|
944
|
+
.content({
|
|
945
|
+
runId: ensureRecordId(attempt.runId, TABLES.PLAN_RUN),
|
|
946
|
+
nodeRunId: ensureRecordId(attempt.nodeRunId, TABLES.PLAN_NODE_RUN),
|
|
947
|
+
nodeId: attempt.nodeId,
|
|
948
|
+
emittedBy: attempt.emittedBy,
|
|
949
|
+
status: attempt.status,
|
|
950
|
+
structuredOutput: response,
|
|
951
|
+
validationIssueIds: issues.map((issue: { id: RecordIdInput }) =>
|
|
952
|
+
ensureRecordId(issue.id, TABLES.PLAN_VALIDATION_ISSUE),
|
|
953
|
+
),
|
|
954
|
+
...(attempt.notes ? { notes: attempt.notes } : {}),
|
|
955
|
+
...(attempt.failureClass ? { failureClass: attempt.failureClass } : {}),
|
|
956
|
+
})
|
|
957
|
+
.output('after')
|
|
958
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
959
|
+
yield* Effect.asVoid(parseRowOrFail(PlanNodeAttemptSchema, updatedHumanAttemptRow, 'plan node attempt'))
|
|
960
|
+
|
|
961
|
+
const nextNodeRunRow = yield* tx
|
|
962
|
+
.update(ensureRecordId(submission.nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
963
|
+
.content(
|
|
964
|
+
toNodeRunData(submission.nodeRun, {
|
|
965
|
+
status: submission.validation.blocking.length > 0 ? 'blocked' : 'completed',
|
|
966
|
+
attemptCount: submission.nodeRun.attemptCount + 1,
|
|
967
|
+
latestAttemptId: attempt.id,
|
|
968
|
+
latestStructuredOutput: response,
|
|
969
|
+
latestNotes: submission.responseComments ?? null,
|
|
970
|
+
blockedReason: submission.validation.blocking[0]?.message ?? null,
|
|
971
|
+
failureClass: submission.validation.blocking.length > 0 ? submission.validation.failureClass : null,
|
|
972
|
+
...(submission.validation.blocking.length > 0 ? {} : { completedAt: nowDate() }),
|
|
973
|
+
}),
|
|
974
|
+
)
|
|
975
|
+
.output('after')
|
|
976
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
994
977
|
const nextNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, nextNodeRunRow, 'plan node run')
|
|
995
978
|
|
|
996
979
|
const nodeRuns = replaceNodeRunInList(yield* context.planRunService.listNodeRuns(submission.run.id), nextNodeRun)
|
|
@@ -1065,18 +1048,16 @@ function handleAcceptedHumanNodeResponseEffect(
|
|
|
1065
1048
|
const { tx, emittedEvents, submission, persisted, respondedBy } = params
|
|
1066
1049
|
|
|
1067
1050
|
return Effect.gen(function* () {
|
|
1068
|
-
const synced = yield*
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
}),
|
|
1079
|
-
)
|
|
1051
|
+
const synced = yield* syncRunGraph(context, {
|
|
1052
|
+
tx,
|
|
1053
|
+
run: submission.run,
|
|
1054
|
+
spec: submission.spec,
|
|
1055
|
+
nodeSpecs: submission.nodeSpecs,
|
|
1056
|
+
nodeRuns: persisted.nodeRuns,
|
|
1057
|
+
artifacts: submission.existingArtifacts,
|
|
1058
|
+
emittedBy: respondedBy,
|
|
1059
|
+
capturedEvents: emittedEvents,
|
|
1060
|
+
}).pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
1080
1061
|
|
|
1081
1062
|
yield* emitEvent({
|
|
1082
1063
|
tx,
|
|
@@ -1176,11 +1157,11 @@ const submitNodeResult = Effect.fn('PlanExecutor.submitNodeResult')(function* (
|
|
|
1176
1157
|
const orgId = recordIdToString(submission.run.organizationId, TABLES.ORGANIZATION)
|
|
1177
1158
|
const runIdStr = recordIdToString(submission.run.id, TABLES.PLAN_RUN)
|
|
1178
1159
|
|
|
1179
|
-
const background = yield*
|
|
1160
|
+
const background = yield* BackgroundWorkServiceTag
|
|
1180
1161
|
|
|
1181
1162
|
yield* background.run(
|
|
1182
|
-
|
|
1183
|
-
|
|
1163
|
+
planCompletionSideEffects
|
|
1164
|
+
.runPlanNodeCompletionSideEffects({
|
|
1184
1165
|
runId: runIdStr,
|
|
1185
1166
|
organizationId: orgId,
|
|
1186
1167
|
nodeId: params.nodeId,
|
|
@@ -1192,24 +1173,24 @@ const submitNodeResult = Effect.fn('PlanExecutor.submitNodeResult')(function* (
|
|
|
1192
1173
|
nodeAttemptCount: submission.nodeRun.attemptCount + 1,
|
|
1193
1174
|
artifactCount: params.result.artifacts.length,
|
|
1194
1175
|
validationIssues: [...submission.validation.blocking, ...submission.validation.warnings],
|
|
1195
|
-
})
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
Effect.
|
|
1199
|
-
|
|
1200
|
-
|
|
1176
|
+
})
|
|
1177
|
+
.pipe(
|
|
1178
|
+
Effect.mapError(toPlanExecutorInternalError),
|
|
1179
|
+
Effect.catchTag(ERROR_TAGS.PlanExecutorInternalError, (error) =>
|
|
1180
|
+
Effect.sync(() => {
|
|
1181
|
+
aiLogger.warn`Failed to record node completion metrics for run ${runIdStr} node ${params.nodeId}: ${error.message}`
|
|
1182
|
+
}),
|
|
1183
|
+
),
|
|
1201
1184
|
),
|
|
1202
|
-
),
|
|
1203
1185
|
'plan-executor.recordNodeCompletionMetrics',
|
|
1204
1186
|
)
|
|
1205
1187
|
|
|
1206
1188
|
const updatedRun = yield* planRunService.getRunById(submission.run.id)
|
|
1207
1189
|
if (updatedRun.status === 'completed') {
|
|
1208
1190
|
yield* background.run(
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
Effect.catchTag('PlanExecutorInternalError', (error) =>
|
|
1191
|
+
planCompletionSideEffects.runPlanCompletionSideEffectsSafely({ runId: runIdStr, organizationId: orgId }).pipe(
|
|
1192
|
+
Effect.mapError(toPlanExecutorInternalError),
|
|
1193
|
+
Effect.catchTag(ERROR_TAGS.PlanExecutorInternalError, (error) =>
|
|
1213
1194
|
Effect.sync(() => {
|
|
1214
1195
|
aiLogger.warn`Plan completion side-effects failed for run ${runIdStr}: ${error.message}`
|
|
1215
1196
|
}),
|
|
@@ -1302,18 +1283,17 @@ const resumeRun = Effect.fn('PlanExecutor.resumeRun')(function* (
|
|
|
1302
1283
|
Effect.gen(function* () {
|
|
1303
1284
|
let currentNodeRuns = [...nodeRuns]
|
|
1304
1285
|
for (const currentNodeRun of currentNodeRuns.filter((candidate) => candidate.status === 'running')) {
|
|
1305
|
-
const resetNodeRunRow = yield*
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
)
|
|
1286
|
+
const resetNodeRunRow = yield* tx
|
|
1287
|
+
.update(ensureRecordId(currentNodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
1288
|
+
.content(
|
|
1289
|
+
toNodeRunData(currentNodeRun, {
|
|
1290
|
+
status: 'ready',
|
|
1291
|
+
readyAt: nowDate(),
|
|
1292
|
+
startedAt: currentNodeRun.startedAt ?? nowDate(),
|
|
1293
|
+
}),
|
|
1294
|
+
)
|
|
1295
|
+
.output('after')
|
|
1296
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
1317
1297
|
const resetNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, resetNodeRunRow, 'plan node run')
|
|
1318
1298
|
currentNodeRuns = currentNodeRuns.map((candidate) =>
|
|
1319
1299
|
candidate.nodeId === resetNodeRun.nodeId ? resetNodeRun : candidate,
|
|
@@ -1347,18 +1327,16 @@ const resumeRun = Effect.fn('PlanExecutor.resumeRun')(function* (
|
|
|
1347
1327
|
const synced =
|
|
1348
1328
|
resetRun.status === 'awaiting-human'
|
|
1349
1329
|
? { run: resetRun, nodeRuns: currentNodeRuns, artifacts }
|
|
1350
|
-
: yield*
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
}),
|
|
1361
|
-
)
|
|
1330
|
+
: yield* syncRunGraph(context, {
|
|
1331
|
+
tx,
|
|
1332
|
+
run: resetRun,
|
|
1333
|
+
spec,
|
|
1334
|
+
nodeSpecs,
|
|
1335
|
+
nodeRuns: currentNodeRuns,
|
|
1336
|
+
artifacts,
|
|
1337
|
+
emittedBy: params.emittedBy,
|
|
1338
|
+
capturedEvents: emittedEvents,
|
|
1339
|
+
}).pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
1362
1340
|
|
|
1363
1341
|
const checkpoint = yield* saveCheckpointWithContext(context, {
|
|
1364
1342
|
tx,
|
|
@@ -1395,12 +1373,11 @@ const transitionNodeToRunning = Effect.fn('PlanExecutor.transitionNodeToRunning'
|
|
|
1395
1373
|
|
|
1396
1374
|
yield* withDatabaseTransactionEffect(databaseService, (tx) =>
|
|
1397
1375
|
Effect.gen(function* () {
|
|
1398
|
-
const runningNodeRunRow = yield*
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
)
|
|
1376
|
+
const runningNodeRunRow = yield* tx
|
|
1377
|
+
.update(ensureRecordId(nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
1378
|
+
.content(toNodeRunData(nodeRun, { status: 'running', startedAt: nodeRun.startedAt ?? nowDate() }))
|
|
1379
|
+
.output('after')
|
|
1380
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
1404
1381
|
const runningNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, runningNodeRunRow, 'plan node run')
|
|
1405
1382
|
|
|
1406
1383
|
const nodeRuns = yield* planRunService.listNodeRuns(run.id)
|
|
@@ -1447,18 +1424,17 @@ const blockNodeOnDispatchFailure = Effect.fn('PlanExecutor.blockNodeOnDispatchFa
|
|
|
1447
1424
|
if (nodeRun.status === 'blocked') {
|
|
1448
1425
|
blockedNodeRun = nodeRun
|
|
1449
1426
|
} else {
|
|
1450
|
-
const blockedNodeRunRow = yield*
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
)
|
|
1427
|
+
const blockedNodeRunRow = yield* tx
|
|
1428
|
+
.update(ensureRecordId(nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
1429
|
+
.content(
|
|
1430
|
+
toNodeRunData(nodeRun, {
|
|
1431
|
+
status: 'blocked',
|
|
1432
|
+
blockedReason: params.message,
|
|
1433
|
+
failureClass: params.failureClass,
|
|
1434
|
+
}),
|
|
1435
|
+
)
|
|
1436
|
+
.output('after')
|
|
1437
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
1462
1438
|
blockedNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, blockedNodeRunRow, 'plan node run')
|
|
1463
1439
|
}
|
|
1464
1440
|
|
|
@@ -1531,12 +1507,11 @@ const promoteDelayedNode = Effect.fn('PlanExecutor.promoteDelayedNode')(function
|
|
|
1531
1507
|
planEventDeliveryService,
|
|
1532
1508
|
run: (tx, emittedEvents) =>
|
|
1533
1509
|
Effect.gen(function* () {
|
|
1534
|
-
const readyNodeRunRow = yield*
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
)
|
|
1510
|
+
const readyNodeRunRow = yield* tx
|
|
1511
|
+
.update(ensureRecordId(nodeRun.id, TABLES.PLAN_NODE_RUN))
|
|
1512
|
+
.content(toNodeRunData(nodeRun, { status: 'ready', readyAt: nowDate() }))
|
|
1513
|
+
.output('after')
|
|
1514
|
+
.pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
1540
1515
|
const readyNodeRun = yield* parseRowOrFail(PlanNodeRunSchema, readyNodeRunRow, 'plan node run')
|
|
1541
1516
|
|
|
1542
1517
|
const updatedNodeRuns = nodeRuns.map((candidate) =>
|
|
@@ -1557,18 +1532,16 @@ const promoteDelayedNode = Effect.fn('PlanExecutor.promoteDelayedNode')(function
|
|
|
1557
1532
|
capturedEvents: emittedEvents,
|
|
1558
1533
|
})
|
|
1559
1534
|
|
|
1560
|
-
const synced = yield*
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
}),
|
|
1571
|
-
)
|
|
1535
|
+
const synced = yield* syncRunGraph(context, {
|
|
1536
|
+
tx,
|
|
1537
|
+
run,
|
|
1538
|
+
spec,
|
|
1539
|
+
nodeSpecs,
|
|
1540
|
+
nodeRuns: updatedNodeRuns,
|
|
1541
|
+
artifacts,
|
|
1542
|
+
emittedBy: params.emittedBy,
|
|
1543
|
+
capturedEvents: emittedEvents,
|
|
1544
|
+
}).pipe(Effect.mapError(toPlanExecutorInternalError))
|
|
1572
1545
|
|
|
1573
1546
|
const checkpoint = yield* saveCheckpointWithContext(context, {
|
|
1574
1547
|
tx,
|