@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
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
UpdateAutonomousJobInput,
|
|
23
23
|
} from '@lota-sdk/shared'
|
|
24
24
|
import type { Job } from 'bullmq'
|
|
25
|
-
import { Context, Cron, Schema, Effect, Layer } from 'effect'
|
|
25
|
+
import { Context, Cron, Schema, Effect, Layer, Ref } from 'effect'
|
|
26
26
|
import { BoundQuery, RecordId } from 'surrealdb'
|
|
27
27
|
import { z } from 'zod'
|
|
28
28
|
|
|
@@ -968,70 +968,72 @@ function executeQueuedRunEffect(
|
|
|
968
968
|
deps: AutonomousJobDeps,
|
|
969
969
|
job: Job<AutonomousJobQueuePayload>,
|
|
970
970
|
): Effect.Effect<{ status: string; summary?: string }, AutonomousJobServiceError> {
|
|
971
|
-
let autonomousJobRow: AutonomousJobRow | null = null
|
|
972
|
-
let runRow: AutonomousJobRunRow | null = null
|
|
973
|
-
|
|
974
971
|
return Effect.gen(function* () {
|
|
975
|
-
yield*
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
972
|
+
const autonomousJobRowRef = yield* Ref.make<AutonomousJobRow | null>(null)
|
|
973
|
+
const runRowRef = yield* Ref.make<AutonomousJobRunRow | null>(null)
|
|
974
|
+
|
|
975
|
+
return yield* Effect.gen(function* () {
|
|
976
|
+
yield* effectTryPromise(() => deps.db.connect(), 'Failed to connect to autonomous job database.')
|
|
977
|
+
const currentJobRow = yield* getRowEffect(deps, job.data.autonomousJobId)
|
|
978
|
+
yield* Ref.set(autonomousJobRowRef, currentJobRow)
|
|
979
|
+
const { queueJobId, runRow: initialRunRow } = yield* getOrCreateQueuedRunRowEffect(deps, job, currentJobRow)
|
|
980
|
+
|
|
981
|
+
yield* Ref.set(runRowRef, initialRunRow)
|
|
982
|
+
if (currentJobRow.status !== 'active' && job.data.trigger === 'scheduled') {
|
|
983
|
+
return { status: 'skipped' }
|
|
984
|
+
}
|
|
979
985
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
986
|
+
const currentRunRow = yield* markQueuedRunRunningEffect(deps, initialRunRow, queueJobId)
|
|
987
|
+
yield* Ref.set(runRowRef, currentRunRow)
|
|
988
|
+
const inputMessage = buildSyntheticUserMessage(currentJobRow.prompt)
|
|
989
|
+
|
|
990
|
+
const [thread, turnModule] = yield* Effect.all([
|
|
991
|
+
deps.thread
|
|
992
|
+
.getThread(currentJobRow.threadId)
|
|
993
|
+
.pipe(
|
|
994
|
+
Effect.mapError(
|
|
995
|
+
(cause) => new AutonomousJobServiceError({ message: 'Failed to load autonomous job thread.', cause }),
|
|
996
|
+
),
|
|
997
|
+
),
|
|
998
|
+
effectTryPromise<ThreadTurnModule>(() => import('./thread/thread-turn'), 'Failed to load thread turn runtime.'),
|
|
999
|
+
])
|
|
984
1000
|
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1001
|
+
const turnResult = yield* effectTryPromise(
|
|
1002
|
+
() =>
|
|
1003
|
+
turnModule.runThreadTurnInBackground({
|
|
1004
|
+
thread,
|
|
1005
|
+
threadRef: ensureRecordId(currentJobRow.threadId, TABLES.THREAD),
|
|
1006
|
+
orgRef: ensureRecordId(currentJobRow.organizationId, TABLES.ORGANIZATION),
|
|
1007
|
+
userRef: ensureRecordId(currentJobRow.ownerUserId, TABLES.USER),
|
|
1008
|
+
userName: currentJobRow.ownerUserName,
|
|
1009
|
+
agentIdOverride: currentJobRow.agentId,
|
|
1010
|
+
inputMessage,
|
|
1011
|
+
}),
|
|
1012
|
+
'Failed to run autonomous job thread turn.',
|
|
1013
|
+
)
|
|
988
1014
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
.getThread(currentJobRow.threadId)
|
|
1015
|
+
const activePlan = yield* deps.executionPlan
|
|
1016
|
+
.getActivePlanForThread(currentJobRow.threadId)
|
|
992
1017
|
.pipe(
|
|
993
1018
|
Effect.mapError(
|
|
994
|
-
(cause) => new AutonomousJobServiceError({ message: 'Failed to load
|
|
1019
|
+
(cause) => new AutonomousJobServiceError({ message: 'Failed to load active execution plan.', cause }),
|
|
995
1020
|
),
|
|
996
|
-
)
|
|
997
|
-
effectTryPromise<ThreadTurnModule>(() => import('./thread/thread-turn'), 'Failed to load thread turn runtime.'),
|
|
998
|
-
])
|
|
1021
|
+
)
|
|
999
1022
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1023
|
+
return yield* completeQueuedRunEffect(deps, { job, currentJobRow, currentRunRow, turnResult, activePlan })
|
|
1024
|
+
}).pipe(
|
|
1025
|
+
Effect.catch((error: unknown) =>
|
|
1026
|
+
Effect.gen(function* () {
|
|
1027
|
+
const currentJobRow = yield* Ref.get(autonomousJobRowRef)
|
|
1028
|
+
const currentRunRow = yield* Ref.get(runRowRef)
|
|
1029
|
+
if (!currentJobRow || !currentRunRow) {
|
|
1030
|
+
return yield* new AutonomousJobServiceError({ message: 'Failed to execute autonomous job.', cause: error })
|
|
1031
|
+
}
|
|
1032
|
+
return yield* failQueuedRunEffect(deps, { job, currentJobRow, currentRunRow, error })
|
|
1010
1033
|
}),
|
|
1011
|
-
|
|
1034
|
+
),
|
|
1012
1035
|
)
|
|
1013
|
-
|
|
1014
|
-
const activePlan = yield* deps.executionPlan
|
|
1015
|
-
.getActivePlanForThread(currentJobRow.threadId)
|
|
1016
|
-
.pipe(
|
|
1017
|
-
Effect.mapError(
|
|
1018
|
-
(cause) => new AutonomousJobServiceError({ message: 'Failed to load active execution plan.', cause }),
|
|
1019
|
-
),
|
|
1020
|
-
)
|
|
1021
|
-
|
|
1022
|
-
return yield* completeQueuedRunEffect(deps, { job, currentJobRow, currentRunRow, turnResult, activePlan })
|
|
1023
|
-
}).pipe(
|
|
1024
|
-
Effect.catch((error: unknown) =>
|
|
1025
|
-
Effect.gen(function* () {
|
|
1026
|
-
const currentJobRow = autonomousJobRow
|
|
1027
|
-
const currentRunRow = runRow
|
|
1028
|
-
if (!currentJobRow || !currentRunRow) {
|
|
1029
|
-
return yield* new AutonomousJobServiceError({ message: 'Failed to execute autonomous job.', cause: error })
|
|
1030
|
-
}
|
|
1031
|
-
return yield* failQueuedRunEffect(deps, { job, currentJobRow, currentRunRow, error })
|
|
1032
|
-
}),
|
|
1033
|
-
),
|
|
1034
|
-
)
|
|
1036
|
+
})
|
|
1035
1037
|
}
|
|
1036
1038
|
|
|
1037
1039
|
function createAutonomousJobService(deps: AutonomousJobDeps) {
|
|
@@ -1068,7 +1070,7 @@ export function makeAutonomousJobService(deps: AutonomousJobDeps) {
|
|
|
1068
1070
|
export class AutonomousJobServiceTag extends Context.Service<
|
|
1069
1071
|
AutonomousJobServiceTag,
|
|
1070
1072
|
ReturnType<typeof makeAutonomousJobService>
|
|
1071
|
-
>()('AutonomousJobService') {}
|
|
1073
|
+
>()('@lota-sdk/core/AutonomousJobService') {}
|
|
1072
1074
|
|
|
1073
1075
|
export const AutonomousJobServiceLive = Layer.effect(
|
|
1074
1076
|
AutonomousJobServiceTag,
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Context, Effect, FiberSet, Layer, Schema } from 'effect'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tagged error for the BackgroundWorkService surface. The service itself
|
|
5
|
+
* never returns this — it's reserved for future API extensions.
|
|
6
|
+
*/
|
|
7
|
+
export class BackgroundWorkError extends Schema.TaggedErrorClass<BackgroundWorkError>()(
|
|
8
|
+
'@lota-sdk/core/BackgroundWorkError',
|
|
9
|
+
{ message: Schema.String, cause: Schema.optional(Schema.Defect) },
|
|
10
|
+
) {}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Supervised fire-and-forget fork pool.
|
|
14
|
+
*
|
|
15
|
+
* `run` schedules an effect on a process-wide FiberSet that is interrupted
|
|
16
|
+
* when the runtime scope closes — replaces ad-hoc `Effect.runFork`,
|
|
17
|
+
* `Effect.runForkWith`, and `Effect.forkDetach` call sites that would
|
|
18
|
+
* otherwise leak fibers across shutdown.
|
|
19
|
+
*
|
|
20
|
+
* Both methods accept any `Effect.Effect<A, E>`; failures are logged via
|
|
21
|
+
* `Effect.logError` and never propagate to the caller. `runForget` ignores
|
|
22
|
+
* both the result and the cause — use it for best-effort metrics, cache
|
|
23
|
+
* touches, and other strictly cosmetic side effects.
|
|
24
|
+
*/
|
|
25
|
+
export class BackgroundWorkService extends Context.Service<
|
|
26
|
+
BackgroundWorkService,
|
|
27
|
+
{
|
|
28
|
+
readonly run: <A, E>(effect: Effect.Effect<A, E>, label?: string) => Effect.Effect<void>
|
|
29
|
+
readonly runForget: <A, E>(effect: Effect.Effect<A, E>, label?: string) => Effect.Effect<void>
|
|
30
|
+
}
|
|
31
|
+
>()('@lota-sdk/core/BackgroundWorkService') {}
|
|
32
|
+
|
|
33
|
+
export const BackgroundWorkServiceLive = Layer.effect(
|
|
34
|
+
BackgroundWorkService,
|
|
35
|
+
Effect.gen(function* () {
|
|
36
|
+
const set = yield* FiberSet.make<unknown, unknown>()
|
|
37
|
+
|
|
38
|
+
const run = <A, E>(effect: Effect.Effect<A, E>, label?: string): Effect.Effect<void> =>
|
|
39
|
+
Effect.asVoid(
|
|
40
|
+
FiberSet.run(
|
|
41
|
+
set,
|
|
42
|
+
effect.pipe(
|
|
43
|
+
Effect.withLogSpan(label ?? 'background'),
|
|
44
|
+
Effect.catchCause((cause) => Effect.logError(cause)),
|
|
45
|
+
),
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
const runForget = <A, E>(effect: Effect.Effect<A, E>, label?: string): Effect.Effect<void> =>
|
|
50
|
+
Effect.asVoid(FiberSet.run(set, effect.pipe(Effect.withLogSpan(label ?? 'background-forget'), Effect.ignore)))
|
|
51
|
+
|
|
52
|
+
return { run, runForget } as const
|
|
53
|
+
}),
|
|
54
|
+
)
|
|
@@ -2,7 +2,9 @@ import { Context, Effect, FiberMap, Layer } from 'effect'
|
|
|
2
2
|
|
|
3
3
|
import { ChatRunRegistry } from '../runtime/chat-run-registry'
|
|
4
4
|
|
|
5
|
-
export class ChatRunRegistryTag extends Context.Service<ChatRunRegistryTag, ChatRunRegistry>()(
|
|
5
|
+
export class ChatRunRegistryTag extends Context.Service<ChatRunRegistryTag, ChatRunRegistry>()(
|
|
6
|
+
'@lota-sdk/core/ChatRunRegistry',
|
|
7
|
+
) {}
|
|
6
8
|
|
|
7
9
|
export const ChatRunRegistryLive = Layer.effect(
|
|
8
10
|
ChatRunRegistryTag,
|
|
@@ -146,7 +146,7 @@ export function makeContextCompactionService(deps: ContextCompactionDeps) {
|
|
|
146
146
|
export class ContextCompactionServiceTag extends Context.Service<
|
|
147
147
|
ContextCompactionServiceTag,
|
|
148
148
|
ReturnType<typeof makeContextCompactionService>
|
|
149
|
-
>()('ContextCompactionService') {}
|
|
149
|
+
>()('@lota-sdk/core/ContextCompactionService') {}
|
|
150
150
|
|
|
151
151
|
export const ContextCompactionServiceLive = Layer.effect(
|
|
152
152
|
ContextCompactionServiceTag,
|
|
@@ -2,6 +2,7 @@ import { Context, Schema, Effect, Layer } from 'effect'
|
|
|
2
2
|
|
|
3
3
|
import { chunkMarkdownDocument, chunkPagedDocument, chunkPlainTextDocument } from '../document/org-document-chunking'
|
|
4
4
|
import type { ParsedDocumentChunk } from '../document/org-document-chunking'
|
|
5
|
+
import { makeEffectTryPromiseWithMessage } from '../effect/helpers'
|
|
5
6
|
import { RuntimeConfigServiceTag } from '../effect/services'
|
|
6
7
|
import { ProviderEmbeddings } from '../embeddings/provider'
|
|
7
8
|
import { sha256Hex } from '../utils/crypto'
|
|
@@ -71,25 +72,15 @@ class DocumentChunkServiceError extends Schema.TaggedErrorClass<DocumentChunkSer
|
|
|
71
72
|
{ message: Schema.String, cause: Schema.Defect },
|
|
72
73
|
) {}
|
|
73
74
|
|
|
75
|
+
const effectTryDocumentChunkPromise = makeEffectTryPromiseWithMessage(
|
|
76
|
+
(message, cause) => new DocumentChunkServiceError({ message, cause }),
|
|
77
|
+
)
|
|
78
|
+
|
|
74
79
|
function tryDocumentChunkPromise<A>(
|
|
75
80
|
message: string,
|
|
76
|
-
|
|
81
|
+
evaluate: () => PromiseLike<A> | Effect.Effect<A, unknown>,
|
|
77
82
|
): Effect.Effect<A, DocumentChunkServiceError> {
|
|
78
|
-
return
|
|
79
|
-
try {
|
|
80
|
-
const value = thunk()
|
|
81
|
-
if (Effect.isEffect(value)) {
|
|
82
|
-
return value.pipe(Effect.mapError((cause) => new DocumentChunkServiceError({ message, cause })))
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return Effect.tryPromise({
|
|
86
|
-
try: () => Promise.resolve(value),
|
|
87
|
-
catch: (cause) => new DocumentChunkServiceError({ message, cause }),
|
|
88
|
-
})
|
|
89
|
-
} catch (cause) {
|
|
90
|
-
return Effect.fail(new DocumentChunkServiceError({ message, cause }))
|
|
91
|
-
}
|
|
92
|
-
})
|
|
83
|
+
return effectTryDocumentChunkPromise(evaluate, message)
|
|
93
84
|
}
|
|
94
85
|
|
|
95
86
|
export function makeDocumentChunkService(embeddings: DocumentChunkEmbeddings): DocumentChunkService {
|
|
@@ -200,7 +191,7 @@ export function makeDocumentChunkService(embeddings: DocumentChunkEmbeddings): D
|
|
|
200
191
|
}
|
|
201
192
|
|
|
202
193
|
export class DocumentChunkServiceTag extends Context.Service<DocumentChunkServiceTag, DocumentChunkService>()(
|
|
203
|
-
'DocumentChunkService',
|
|
194
|
+
'@lota-sdk/core/DocumentChunkService',
|
|
204
195
|
) {}
|
|
205
196
|
|
|
206
197
|
export const DocumentChunkServiceLive = Layer.effect(
|
|
@@ -8,17 +8,30 @@ import {
|
|
|
8
8
|
} from '@lota-sdk/shared'
|
|
9
9
|
import { Effect } from 'effect'
|
|
10
10
|
import { RecordId } from 'surrealdb'
|
|
11
|
+
import type { z } from 'zod'
|
|
11
12
|
|
|
12
13
|
import type { RecordIdInput } from '../../db/record-id'
|
|
13
14
|
import { ensureRecordId, recordIdToString } from '../../db/record-id'
|
|
14
15
|
import type { DatabaseTransaction } from '../../db/service'
|
|
15
16
|
import { TABLES } from '../../db/tables'
|
|
17
|
+
import { ServiceError } from '../../effect/errors'
|
|
16
18
|
import { runPromise } from '../../effect/runtime'
|
|
17
19
|
import { nowDate } from '../../utils/date-time'
|
|
18
20
|
import type { CompiledPlanNode } from '../plan/plan-compiler.service'
|
|
19
21
|
import type { syncRunGraph } from '../plan/plan-executor-graph'
|
|
20
22
|
import { toRunData } from '../plan/plan-run-data'
|
|
21
23
|
|
|
24
|
+
function parseRowOrFail<TSchema extends z.ZodTypeAny>(
|
|
25
|
+
schema: TSchema,
|
|
26
|
+
value: unknown,
|
|
27
|
+
operation: string,
|
|
28
|
+
): Effect.Effect<z.infer<TSchema>, ServiceError> {
|
|
29
|
+
return Effect.try({
|
|
30
|
+
try: () => schema.parse(value) as z.infer<TSchema>,
|
|
31
|
+
catch: (cause) => new ServiceError({ message: `Failed to parse row for ${operation}.`, cause }),
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
type SyncRunGraphParams = Parameters<typeof syncRunGraph>[1]
|
|
23
36
|
type SyncRunGraphResult = Awaited<ReturnType<typeof syncRunGraph>>
|
|
24
37
|
|
|
@@ -86,7 +99,7 @@ function createNodeSpecs(tx: DatabaseTransaction, planSpecId: RecordIdInput, nod
|
|
|
86
99
|
.create(nodeSpecId)
|
|
87
100
|
.content(buildNodeSpecCreateContent(compiledNode, planSpecId))
|
|
88
101
|
.output('after')
|
|
89
|
-
createdRecords.push(PlanNodeSpecRecordSchema
|
|
102
|
+
createdRecords.push(yield* parseRowOrFail(PlanNodeSpecRecordSchema, created, 'createNodeSpecs'))
|
|
90
103
|
}
|
|
91
104
|
|
|
92
105
|
return createdRecords
|
|
@@ -109,7 +122,7 @@ function createNodeRuns(
|
|
|
109
122
|
.create(nodeRunId)
|
|
110
123
|
.content(buildNodeRunCreateContent(runId, planSpecId, nodeSpec))
|
|
111
124
|
.output('after')
|
|
112
|
-
createdNodeRuns.push(PlanNodeRunSchema
|
|
125
|
+
createdNodeRuns.push(yield* parseRowOrFail(PlanNodeRunSchema, created, 'createNodeRuns'))
|
|
113
126
|
}
|
|
114
127
|
|
|
115
128
|
return createdNodeRuns
|
|
@@ -138,26 +151,25 @@ export function createInitializedRunGraph(params: {
|
|
|
138
151
|
return runPromise(
|
|
139
152
|
Effect.gen(function* () {
|
|
140
153
|
const nodeSpecs = yield* createNodeSpecs(params.tx, params.spec.id, params.nodes)
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
)
|
|
154
|
+
const runRaw = yield* params.tx
|
|
155
|
+
.create(ensureRecordId(params.runId, TABLES.PLAN_RUN))
|
|
156
|
+
.content({
|
|
157
|
+
planSpecId: ensureRecordId(params.spec.id, TABLES.PLAN_SPEC),
|
|
158
|
+
organizationId: ensureRecordId(params.organizationId, TABLES.ORGANIZATION),
|
|
159
|
+
threadId: ensureRecordId(params.threadId, TABLES.THREAD),
|
|
160
|
+
...(params.sourceThreadId ? { sourceThreadId: ensureRecordId(params.sourceThreadId, TABLES.THREAD) } : {}),
|
|
161
|
+
leadAgentId: params.leadAgentId,
|
|
162
|
+
...(params.createdByAgentId ? { createdByAgentId: params.createdByAgentId } : {}),
|
|
163
|
+
status: params.requireApproval ? 'pending-approval' : 'running',
|
|
164
|
+
readyNodeIds: [],
|
|
165
|
+
failureCount: 0,
|
|
166
|
+
...(params.runPatch?.replacedRunId
|
|
167
|
+
? { replacedRunId: ensureRecordId(params.runPatch.replacedRunId, TABLES.PLAN_RUN) }
|
|
168
|
+
: {}),
|
|
169
|
+
...(params.requireApproval ? {} : { startedAt: nowDate() }),
|
|
170
|
+
})
|
|
171
|
+
.output('after')
|
|
172
|
+
const run = yield* parseRowOrFail(PlanRunSchema, runRaw, 'createInitializedRunGraph:run')
|
|
161
173
|
|
|
162
174
|
const nodeRuns = yield* createNodeRuns(params.tx, run.id, params.spec.id, nodeSpecs)
|
|
163
175
|
const synced = params.requireApproval
|
|
@@ -186,7 +198,7 @@ export function createInitializedRunGraph(params: {
|
|
|
186
198
|
detail: { ...params.createdEventDetail, nodeCount: nodeSpecs.length },
|
|
187
199
|
})
|
|
188
200
|
.output('after')
|
|
189
|
-
params.emittedEvents.push(PlanEventSchema
|
|
201
|
+
params.emittedEvents.push(yield* parseRowOrFail(PlanEventSchema, event, 'createInitializedRunGraph:createdEvent'))
|
|
190
202
|
|
|
191
203
|
if (params.requireApproval) {
|
|
192
204
|
const pendingApprovalEvent = yield* params.tx
|
|
@@ -201,38 +213,46 @@ export function createInitializedRunGraph(params: {
|
|
|
201
213
|
detail: { ...params.createdEventDetail, nodeCount: nodeSpecs.length },
|
|
202
214
|
})
|
|
203
215
|
.output('after')
|
|
204
|
-
params.emittedEvents.push(
|
|
216
|
+
params.emittedEvents.push(
|
|
217
|
+
yield* parseRowOrFail(
|
|
218
|
+
PlanEventSchema,
|
|
219
|
+
pendingApprovalEvent,
|
|
220
|
+
'createInitializedRunGraph:pendingApprovalEvent',
|
|
221
|
+
),
|
|
222
|
+
)
|
|
205
223
|
}
|
|
206
224
|
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
const checkpointRaw = yield* params.tx
|
|
226
|
+
.create(new RecordId(TABLES.PLAN_CHECKPOINT, Bun.randomUUIDv7()))
|
|
227
|
+
.content({
|
|
228
|
+
runId: ensureRecordId(synced.run.id, TABLES.PLAN_RUN),
|
|
229
|
+
sequence: 1,
|
|
230
|
+
runStatus: synced.run.status,
|
|
231
|
+
readyNodeIds: [...synced.run.readyNodeIds],
|
|
232
|
+
activeNodeIds: synced.run.currentNodeId ? [synced.run.currentNodeId] : [],
|
|
233
|
+
artifactIds: [],
|
|
234
|
+
lastCompletedNodeIds: synced.nodeRuns
|
|
235
|
+
.filter((nodeRun) => nodeRun.status === 'completed' || nodeRun.status === 'partial')
|
|
236
|
+
.map((nodeRun) => nodeRun.nodeId),
|
|
237
|
+
snapshot: {
|
|
238
|
+
reason: params.checkpointReason,
|
|
239
|
+
currentNodeId: synced.run.currentNodeId,
|
|
240
|
+
waitingNodeId: synced.run.waitingNodeId,
|
|
241
|
+
readyNodeIds: synced.run.readyNodeIds,
|
|
242
|
+
},
|
|
243
|
+
})
|
|
244
|
+
.output('after')
|
|
245
|
+
const checkpoint = yield* parseRowOrFail(
|
|
246
|
+
PlanCheckpointSchema,
|
|
247
|
+
checkpointRaw,
|
|
248
|
+
'createInitializedRunGraph:checkpoint',
|
|
228
249
|
)
|
|
229
250
|
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
)
|
|
251
|
+
const updatedRunRaw = yield* params.tx
|
|
252
|
+
.update(ensureRecordId(synced.run.id, TABLES.PLAN_RUN))
|
|
253
|
+
.content(toRunData(synced.run, { lastCheckpointId: checkpoint.id }))
|
|
254
|
+
.output('after')
|
|
255
|
+
const updatedRun = yield* parseRowOrFail(PlanRunSchema, updatedRunRaw, 'createInitializedRunGraph:updatedRun')
|
|
236
256
|
|
|
237
257
|
const checkpointEvent = yield* params.tx
|
|
238
258
|
.create(new RecordId(TABLES.PLAN_EVENT, Bun.randomUUIDv7()))
|
|
@@ -248,7 +268,9 @@ export function createInitializedRunGraph(params: {
|
|
|
248
268
|
},
|
|
249
269
|
})
|
|
250
270
|
.output('after')
|
|
251
|
-
params.emittedEvents.push(
|
|
271
|
+
params.emittedEvents.push(
|
|
272
|
+
yield* parseRowOrFail(PlanEventSchema, checkpointEvent, 'createInitializedRunGraph:checkpointEvent'),
|
|
273
|
+
)
|
|
252
274
|
|
|
253
275
|
return updatedRun
|
|
254
276
|
}),
|
|
@@ -1010,7 +1010,7 @@ export function makeExecutionPlanService(deps: ExecutionPlanDeps) {
|
|
|
1010
1010
|
export class ExecutionPlanServiceTag extends Context.Service<
|
|
1011
1011
|
ExecutionPlanServiceTag,
|
|
1012
1012
|
ReturnType<typeof makeExecutionPlanService>
|
|
1013
|
-
>()('ExecutionPlanService') {}
|
|
1013
|
+
>()('@lota-sdk/core/ExecutionPlanService') {}
|
|
1014
1014
|
|
|
1015
1015
|
export const ExecutionPlanServiceLive = Layer.effect(
|
|
1016
1016
|
ExecutionPlanServiceTag,
|
|
@@ -141,7 +141,7 @@ export function makeFeedbackLoopService(planRunService: ReturnType<typeof makePl
|
|
|
141
141
|
export class FeedbackLoopServiceTag extends Context.Service<
|
|
142
142
|
FeedbackLoopServiceTag,
|
|
143
143
|
ReturnType<typeof makeFeedbackLoopService>
|
|
144
|
-
>()('FeedbackLoopService') {}
|
|
144
|
+
>()('@lota-sdk/core/FeedbackLoopService') {}
|
|
145
145
|
|
|
146
146
|
export const FeedbackLoopServiceLive = Layer.effect(
|
|
147
147
|
FeedbackLoopServiceTag,
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ConvergenceState,
|
|
3
|
+
ExecutionMode,
|
|
4
|
+
PlanNodeResultSubmission,
|
|
5
|
+
PlanNodeRunRecord,
|
|
6
|
+
PlanNodeSpecRecord,
|
|
7
|
+
PlanRunRecord,
|
|
8
|
+
PlanSpecRecord,
|
|
9
|
+
} from '@lota-sdk/shared'
|
|
2
10
|
import { Context, Effect, Layer } from 'effect'
|
|
3
11
|
|
|
4
12
|
import { runPromise } from '../effect/runtime'
|
|
5
|
-
import { getCurrentRuntime } from '../effect/runtime-ref'
|
|
6
13
|
import { routeGraphFullEffect } from './graph-full-routing'
|
|
7
|
-
import type {
|
|
14
|
+
import type { OwnershipDispatcherService } from './ownership-dispatcher.service'
|
|
8
15
|
import { OwnershipDispatcherServiceTag } from './ownership-dispatcher.service'
|
|
9
16
|
import type { makePlanExecutorService } from './plan/plan-executor.service'
|
|
10
17
|
import { PlanExecutorServiceTag } from './plan/plan-executor.service'
|
|
@@ -48,18 +55,30 @@ function decideRerouteAction(params: {
|
|
|
48
55
|
}
|
|
49
56
|
|
|
50
57
|
interface GlobalOrchestratorDeps {
|
|
51
|
-
ownershipDispatcherService:
|
|
58
|
+
ownershipDispatcherService: Pick<OwnershipDispatcherService, 'dispatchReadyNode'>
|
|
52
59
|
planExecutorService: ReturnType<typeof makePlanExecutorService>
|
|
53
60
|
planRunService: ReturnType<typeof makePlanRunService>
|
|
54
61
|
}
|
|
55
62
|
|
|
63
|
+
type DispatchReadyNodeParams = {
|
|
64
|
+
run: PlanRunRecord
|
|
65
|
+
nodeSpecRecord: PlanNodeSpecRecord
|
|
66
|
+
nodeRun: PlanNodeRunRecord
|
|
67
|
+
spec: PlanSpecRecord
|
|
68
|
+
executionModeOverride?: ExecutionMode
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
type DispatchReadyNode = (params: DispatchReadyNodeParams) => Effect.Effect<PlanNodeResultSubmission, unknown, never>
|
|
72
|
+
|
|
56
73
|
export function makeGlobalOrchestratorService(deps: GlobalOrchestratorDeps) {
|
|
74
|
+
const dispatchReadyNode: DispatchReadyNode = (params) => deps.ownershipDispatcherService.dispatchReadyNode(params)
|
|
75
|
+
|
|
57
76
|
return {
|
|
58
77
|
detectConvergence,
|
|
59
78
|
decideRerouteAction,
|
|
60
79
|
routeGraphFull: (params: { threadId: string; runId: string }) =>
|
|
61
80
|
routeGraphFullEffect(params, {
|
|
62
|
-
dispatchReadyNode
|
|
81
|
+
dispatchReadyNode,
|
|
63
82
|
planExecutorService: deps.planExecutorService,
|
|
64
83
|
planRunService: deps.planRunService,
|
|
65
84
|
}),
|
|
@@ -69,7 +88,7 @@ export function makeGlobalOrchestratorService(deps: GlobalOrchestratorDeps) {
|
|
|
69
88
|
export class GlobalOrchestratorServiceTag extends Context.Service<
|
|
70
89
|
GlobalOrchestratorServiceTag,
|
|
71
90
|
ReturnType<typeof makeGlobalOrchestratorService>
|
|
72
|
-
>()('GlobalOrchestratorService') {}
|
|
91
|
+
>()('@lota-sdk/core/GlobalOrchestratorService') {}
|
|
73
92
|
|
|
74
93
|
export const GlobalOrchestratorServiceLive = Layer.effect(
|
|
75
94
|
GlobalOrchestratorServiceTag,
|
|
@@ -81,10 +100,14 @@ export const GlobalOrchestratorServiceLive = Layer.effect(
|
|
|
81
100
|
}),
|
|
82
101
|
)
|
|
83
102
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
103
|
+
const routeGraphFullWithRuntime = Effect.fn('GlobalOrchestrator.routeGraphFullWithRuntime')(function* (params: {
|
|
104
|
+
threadId: string
|
|
105
|
+
runId: string
|
|
106
|
+
}) {
|
|
107
|
+
const globalOrchestratorService = yield* GlobalOrchestratorServiceTag
|
|
108
|
+
return yield* globalOrchestratorService.routeGraphFull(params)
|
|
109
|
+
})
|
|
87
110
|
|
|
88
111
|
export function routeGraphFull(params: { threadId: string; runId: string }): Promise<void> {
|
|
89
|
-
return runPromise(
|
|
112
|
+
return runPromise(routeGraphFullWithRuntime(params))
|
|
90
113
|
}
|