@lota-sdk/core 0.4.9 → 0.4.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/ai/embedding-cache.ts +3 -1
- package/src/ai-gateway/ai-gateway.ts +164 -82
- package/src/ai-gateway/index.ts +16 -1
- package/src/config/agent-defaults.ts +4 -107
- 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 +22 -25
- package/src/config/thread-defaults.ts +1 -10
- package/src/create-runtime.ts +145 -670
- package/src/db/base.service.ts +30 -38
- 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 +496 -384
- package/src/db/startup.ts +30 -19
- package/src/effect/helpers.ts +30 -5
- package/src/effect/index.ts +7 -7
- package/src/effect/layers.ts +75 -72
- package/src/effect/services.ts +15 -11
- package/src/embeddings/provider.ts +65 -71
- package/src/index.ts +13 -12
- package/src/queues/autonomous-job.queue.ts +177 -143
- package/src/queues/context-compaction.queue.ts +41 -39
- package/src/queues/delayed-node-promotion.queue.ts +61 -42
- package/src/queues/document-processor.queue.ts +5 -3
- package/src/queues/index.ts +1 -0
- package/src/queues/memory-consolidation.queue.ts +79 -53
- package/src/queues/organization-learning.queue.ts +70 -33
- package/src/queues/plan-agent-heartbeat.queue.ts +111 -83
- package/src/queues/plan-scheduler.queue.ts +101 -97
- package/src/queues/post-chat-memory.queue.ts +56 -46
- package/src/queues/queue-factory.ts +146 -69
- package/src/queues/queues.service.ts +61 -0
- package/src/queues/title-generation.queue.ts +44 -44
- package/src/redis/connection.ts +181 -164
- package/src/redis/org-memory-lock.ts +24 -9
- package/src/redis/redis-lease-lock.ts +8 -1
- package/src/redis/stream-context.ts +17 -9
- package/src/runtime/agent-identity-overrides.ts +7 -3
- package/src/runtime/agent-runtime-policy.ts +10 -5
- package/src/runtime/agent-stream-helpers.ts +24 -15
- package/src/runtime/chat-run-orchestration.ts +1 -1
- package/src/runtime/context-compaction/context-compaction-runtime.ts +28 -32
- package/src/runtime/context-compaction/context-compaction.ts +131 -85
- package/src/runtime/domain-layer.ts +203 -0
- package/src/runtime/execution-plan-visibility.ts +5 -2
- package/src/runtime/graph-designer.ts +0 -14
- package/src/runtime/helper-model.ts +8 -4
- package/src/runtime/index.ts +1 -1
- package/src/runtime/indexed-repositories-policy.ts +2 -6
- 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 +58 -62
- package/src/runtime/post-turn-side-effects.ts +139 -161
- package/src/runtime/retrieval-adapters.ts +4 -4
- package/src/runtime/runtime-config.ts +3 -9
- package/src/runtime/runtime-extensions.ts +0 -43
- package/src/runtime/runtime-lifecycle.ts +124 -0
- package/src/runtime/runtime-services.ts +455 -0
- package/src/runtime/runtime-worker-registry.ts +113 -30
- package/src/runtime/social-chat/social-chat-agent-runner.ts +13 -8
- package/src/runtime/social-chat/social-chat-history.ts +24 -13
- package/src/runtime/social-chat/social-chat.ts +420 -369
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +64 -57
- package/src/runtime/team-consultation/team-consultation-prompts.ts +11 -6
- package/src/runtime/thread-chat-helpers.ts +18 -9
- package/src/runtime/thread-turn-context.ts +28 -74
- package/src/runtime/turn-lifecycle.ts +6 -14
- package/src/services/agent-activity.service.ts +169 -176
- package/src/services/agent-executor.service.ts +207 -196
- package/src/services/artifact.service.ts +10 -5
- package/src/services/attachment.service.ts +16 -48
- package/src/services/autonomous-job.service.ts +81 -87
- 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 +8 -10
- package/src/services/document-chunk.service.ts +8 -17
- package/src/services/execution-plan/execution-plan-graph.ts +122 -109
- package/src/services/execution-plan/execution-plan-schedule.ts +1 -15
- package/src/services/execution-plan/execution-plan.service.ts +68 -51
- package/src/services/feedback-loop.service.ts +1 -1
- package/src/services/global-orchestrator.service.ts +49 -15
- package/src/services/graph-full-routing.ts +49 -37
- 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-conversation.ts +10 -5
- 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 +37 -52
- 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 +148 -95
- package/src/services/plan/plan-agent-heartbeat.service.ts +30 -16
- package/src/services/plan/plan-agent-query.service.ts +13 -9
- 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 +99 -113
- package/src/services/plan/plan-coordination.service.ts +1 -1
- package/src/services/plan/plan-cycle.service.ts +171 -202
- package/src/services/plan/plan-deadline.service.ts +304 -307
- package/src/services/plan/plan-event-delivery.service.ts +84 -72
- package/src/services/plan/plan-executor-context.ts +2 -0
- package/src/services/plan/plan-executor-graph.ts +375 -353
- package/src/services/plan/plan-executor-helpers.ts +60 -75
- package/src/services/plan/plan-executor.service.ts +494 -489
- package/src/services/plan/plan-run.service.ts +12 -19
- package/src/services/plan/plan-scheduler.service.ts +89 -82
- 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 +22 -10
- 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 +37 -19
- 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 +30 -13
- package/src/services/thread/thread-title.service.ts +1 -1
- package/src/services/thread/thread-turn-execution.ts +87 -83
- package/src/services/thread/thread-turn-preparation.service.ts +65 -40
- package/src/services/thread/thread-turn-streaming.ts +32 -36
- package/src/services/thread/thread-turn.ts +43 -29
- package/src/services/thread/thread.service.ts +32 -8
- 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 +9 -6
- 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/thread-router.agent.ts +23 -20
- package/src/system-agents/title-generator.agent.ts +1 -1
- package/src/tools/execution-plan.tool.ts +36 -20
- package/src/tools/fetch-webpage.tool.ts +30 -22
- package/src/tools/firecrawl-client.ts +1 -6
- package/src/tools/plan-approval.tool.ts +9 -1
- package/src/tools/remember-memory.tool.ts +3 -6
- package/src/tools/research-topic.tool.ts +12 -3
- package/src/tools/search-web.tool.ts +26 -18
- package/src/tools/search.tool.ts +4 -5
- package/src/tools/team-think.tool.ts +139 -121
- package/src/utils/async.ts +15 -6
- package/src/utils/errors.ts +27 -15
- package/src/workers/bootstrap.ts +34 -58
- package/src/workers/memory-consolidation.worker.ts +4 -1
- package/src/workers/organization-learning.worker.ts +16 -3
- package/src/workers/regular-chat-memory-digest.helpers.ts +3 -4
- package/src/workers/regular-chat-memory-digest.runner.ts +46 -29
- package/src/workers/skill-extraction.runner.ts +13 -15
- package/src/workers/worker-utils.ts +14 -8
- package/src/config/search.ts +0 -3
- package/src/effect/awaitable-effect.ts +0 -87
- package/src/effect/runtime-ref.ts +0 -25
- package/src/effect/runtime.ts +0 -31
- package/src/redis/runtime-connection.ts +0 -10
- package/src/runtime/agent-types.ts +0 -1
|
@@ -33,7 +33,7 @@ import type { RecordIdInput } from '../../db/record-id'
|
|
|
33
33
|
import { ensureRecordId, recordIdToString } from '../../db/record-id'
|
|
34
34
|
import type { SurrealDBService } from '../../db/service'
|
|
35
35
|
import { TABLES } from '../../db/tables'
|
|
36
|
-
import {
|
|
36
|
+
import { makeEffectTryPromiseWithMessage } from '../../effect/helpers'
|
|
37
37
|
import { DatabaseServiceTag } from '../../effect/services'
|
|
38
38
|
import { toIsoDateTimeString, toOptionalIsoDateTimeString } from '../../utils/date-time'
|
|
39
39
|
|
|
@@ -159,7 +159,10 @@ function serializeEvent(event: PlanEventRecord): SerializablePlanEvent {
|
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
class PlanRunServiceError extends Schema.TaggedErrorClass<PlanRunServiceError>()('PlanRunServiceError', {
|
|
163
|
+
message: Schema.String,
|
|
164
|
+
cause: Schema.optional(Schema.Defect),
|
|
165
|
+
}) {}
|
|
163
166
|
|
|
164
167
|
class PlanRunNotFoundError extends Schema.TaggedErrorClass<PlanRunNotFoundError>()('PlanRunNotFoundError', {
|
|
165
168
|
message: Schema.String,
|
|
@@ -172,25 +175,15 @@ class PlanRunSerializationError extends Schema.TaggedErrorClass<PlanRunSerializa
|
|
|
172
175
|
{ message: Schema.String },
|
|
173
176
|
) {}
|
|
174
177
|
|
|
178
|
+
const effectTryPlanRunPromise = makeEffectTryPromiseWithMessage(
|
|
179
|
+
(message, cause) => new PlanRunServiceError({ message, cause }),
|
|
180
|
+
)
|
|
181
|
+
|
|
175
182
|
function tryPlanRunPromise<A>(
|
|
176
183
|
message: string,
|
|
177
|
-
|
|
184
|
+
evaluate: () => PromiseLike<A> | Effect.Effect<A, unknown>,
|
|
178
185
|
): Effect.Effect<A, PlanRunServiceError> {
|
|
179
|
-
return
|
|
180
|
-
try {
|
|
181
|
-
const value = thunk()
|
|
182
|
-
if (Effect.isEffect(value)) {
|
|
183
|
-
return value.pipe(Effect.mapError((cause) => new ServiceError({ message, cause })))
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return Effect.tryPromise({
|
|
187
|
-
try: () => Promise.resolve(value),
|
|
188
|
-
catch: (cause) => new ServiceError({ message, cause }),
|
|
189
|
-
})
|
|
190
|
-
} catch (cause) {
|
|
191
|
-
return Effect.fail(new ServiceError({ message, cause }))
|
|
192
|
-
}
|
|
193
|
-
})
|
|
186
|
+
return effectTryPlanRunPromise(evaluate, message)
|
|
194
187
|
}
|
|
195
188
|
|
|
196
189
|
export function makePlanRunService(db: SurrealDBService) {
|
|
@@ -632,7 +625,7 @@ export function makePlanRunService(db: SurrealDBService) {
|
|
|
632
625
|
}
|
|
633
626
|
|
|
634
627
|
export class PlanRunServiceTag extends Context.Service<PlanRunServiceTag, ReturnType<typeof makePlanRunService>>()(
|
|
635
|
-
'PlanRunService',
|
|
628
|
+
'@lota-sdk/core/PlanRunService',
|
|
636
629
|
) {}
|
|
637
630
|
|
|
638
631
|
export const PlanRunServiceLive = Layer.effect(
|
|
@@ -8,8 +8,10 @@ import { ensureRecordId, recordIdToString } from '../../db/record-id'
|
|
|
8
8
|
import type { SurrealDBService } from '../../db/service'
|
|
9
9
|
import { TABLES } from '../../db/tables'
|
|
10
10
|
import { NotFoundError } from '../../effect/errors'
|
|
11
|
-
import {
|
|
11
|
+
import { makeEffectTryPromiseWithMessage } from '../../effect/helpers'
|
|
12
12
|
import { DatabaseServiceTag } from '../../effect/services'
|
|
13
|
+
import type { PlanSchedulerQueueRuntime } from '../../queues/plan-scheduler.queue'
|
|
14
|
+
import { LotaQueuesServiceTag } from '../../queues/queues.service'
|
|
13
15
|
import { nowDate, nowEpochMillis, toDatabaseDateTime, unsafeDateFrom } from '../../utils/date-time'
|
|
14
16
|
|
|
15
17
|
interface PlanSchedulerRuntimeDeps {
|
|
@@ -23,72 +25,77 @@ class PlanSchedulerError extends Schema.TaggedErrorClass<PlanSchedulerError>()('
|
|
|
23
25
|
cause: Schema.optional(Schema.Defect),
|
|
24
26
|
}) {}
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
evaluate: () => PromiseLike<A> | Effect.Effect<A, unknown>,
|
|
28
|
-
message: string,
|
|
29
|
-
): Effect.Effect<A, PlanSchedulerError> {
|
|
30
|
-
return effectTryPromiseShared(evaluate, (cause) => new PlanSchedulerError({ message, cause }))
|
|
31
|
-
}
|
|
28
|
+
const effectTryPromise = makeEffectTryPromiseWithMessage((message, cause) => new PlanSchedulerError({ message, cause }))
|
|
32
29
|
|
|
33
|
-
function
|
|
34
|
-
|
|
30
|
+
function requireScheduleField<A>(value: A | undefined, message: string): A {
|
|
31
|
+
if (value === undefined) {
|
|
32
|
+
throw new PlanSchedulerError({ message })
|
|
33
|
+
}
|
|
34
|
+
return value
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
function
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
function computeNextCronDate(cronExpression: string, baseTime: Date): Date {
|
|
38
|
+
const parsedCron = Cron.parse(cronExpression)
|
|
39
|
+
if (!Result.isSuccess(parsedCron)) {
|
|
40
|
+
throw new PlanSchedulerError({ message: `Invalid cron expression: "${cronExpression}".` })
|
|
41
|
+
}
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return yield* Effect.try({
|
|
49
|
-
try: () => Cron.next(cron, baseTime),
|
|
50
|
-
catch: (cause) =>
|
|
51
|
-
new PlanSchedulerError({
|
|
52
|
-
message: `Failed to compute the next fire time for cron expression "${cronExpression}".`,
|
|
53
|
-
cause,
|
|
54
|
-
}),
|
|
43
|
+
try {
|
|
44
|
+
return Cron.next(parsedCron.success, baseTime)
|
|
45
|
+
} catch (cause) {
|
|
46
|
+
throw new PlanSchedulerError({
|
|
47
|
+
message: `Failed to compute the next fire time for cron expression "${cronExpression}".`,
|
|
48
|
+
cause,
|
|
55
49
|
})
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const computeNextFireAtEffect: (spec: PlanScheduleSpec, baseTime?: Date) => Effect.Effect<Date, PlanSchedulerError> =
|
|
59
|
-
Effect.fn('PlanScheduler.computeNextFireAt')(function* (spec: PlanScheduleSpec, baseTime: Date = nowDate()) {
|
|
60
|
-
switch (spec.type) {
|
|
61
|
-
case 'immediate':
|
|
62
|
-
return baseTime
|
|
50
|
+
}
|
|
51
|
+
}
|
|
63
52
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
// `computeNextFireAt` must stay purely synchronous — no Clock, no service lookups, no async.
|
|
54
|
+
// `computeNextFireAtEffect` wraps it with `Effect.try` so the same logic is composable from
|
|
55
|
+
// Effect callers without an `Effect.runSync` round trip.
|
|
56
|
+
function computeNextFireAt(spec: PlanScheduleSpec, baseTime: Date = nowDate()): Date {
|
|
57
|
+
switch (spec.type) {
|
|
58
|
+
case 'immediate':
|
|
59
|
+
return baseTime
|
|
68
60
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return unsafeDateFrom(baseTime.getTime() + delayMs)
|
|
72
|
-
}
|
|
61
|
+
case 'absolute':
|
|
62
|
+
return unsafeDateFrom(requireScheduleField(spec.at, 'Absolute schedules require an "at" timestamp.'))
|
|
73
63
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
64
|
+
case 'relative': {
|
|
65
|
+
const delayMs = requireScheduleField(spec.delayMs, 'Relative schedules require "delayMs".')
|
|
66
|
+
return unsafeDateFrom(baseTime.getTime() + delayMs)
|
|
67
|
+
}
|
|
78
68
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
69
|
+
case 'cron': {
|
|
70
|
+
const cronExpression = requireScheduleField(spec.cron, 'Cron schedules require a "cron" expression.')
|
|
71
|
+
return computeNextCronDate(cronExpression, baseTime)
|
|
72
|
+
}
|
|
83
73
|
|
|
84
|
-
|
|
85
|
-
|
|
74
|
+
case 'monitoring': {
|
|
75
|
+
const intervalMs = requireScheduleField(spec.intervalMs, 'Monitoring schedules require "intervalMs".')
|
|
76
|
+
return unsafeDateFrom(baseTime.getTime() + intervalMs)
|
|
86
77
|
}
|
|
78
|
+
|
|
79
|
+
default:
|
|
80
|
+
throw new PlanSchedulerError({ message: 'Unsupported schedule type in schedule specification.' })
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const isPlanSchedulerError = Schema.is(PlanSchedulerError)
|
|
85
|
+
|
|
86
|
+
function computeNextFireAtEffect(spec: PlanScheduleSpec, baseTime?: Date): Effect.Effect<Date, PlanSchedulerError> {
|
|
87
|
+
return Effect.try({
|
|
88
|
+
try: () => computeNextFireAt(spec, baseTime),
|
|
89
|
+
catch: (cause) =>
|
|
90
|
+
isPlanSchedulerError(cause)
|
|
91
|
+
? cause
|
|
92
|
+
: new PlanSchedulerError({ message: 'Failed to compute the next fire time.', cause }),
|
|
87
93
|
})
|
|
94
|
+
}
|
|
88
95
|
|
|
89
|
-
export function makePlanSchedulerService(db: SurrealDBService) {
|
|
90
|
-
const loadPlanSchedulerQueue = () =>
|
|
91
|
-
|
|
96
|
+
export function makePlanSchedulerService(db: SurrealDBService, schedulerQueue: PlanSchedulerQueueRuntime) {
|
|
97
|
+
const loadPlanSchedulerQueue = (): Effect.Effect<PlanSchedulerQueueRuntime, PlanSchedulerError> =>
|
|
98
|
+
Effect.succeed(schedulerQueue)
|
|
92
99
|
|
|
93
100
|
const createScheduleEffect = (params: {
|
|
94
101
|
organizationId: RecordIdInput
|
|
@@ -143,13 +150,9 @@ export function makePlanSchedulerService(db: SurrealDBService) {
|
|
|
143
150
|
const isRecurring = schedule.scheduleSpec.type === 'cron' || schedule.scheduleSpec.type === 'monitoring'
|
|
144
151
|
const maxReached = schedule.scheduleSpec.maxFires !== undefined && newFireCount >= schedule.scheduleSpec.maxFires
|
|
145
152
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (isRecurring && !maxReached) {
|
|
150
|
-
nextFireAt = yield* computeNextFireAtEffect(schedule.scheduleSpec, now)
|
|
151
|
-
newStatus = 'active'
|
|
152
|
-
}
|
|
153
|
+
const isActive = isRecurring && !maxReached
|
|
154
|
+
const nextFireAt: Date | null = isActive ? yield* computeNextFireAtEffect(schedule.scheduleSpec, now) : null
|
|
155
|
+
const newStatus: 'active' | 'completed' = isActive ? 'active' : 'completed'
|
|
153
156
|
|
|
154
157
|
yield* effectTryPromise(
|
|
155
158
|
() =>
|
|
@@ -167,7 +170,6 @@ export function makePlanSchedulerService(db: SurrealDBService) {
|
|
|
167
170
|
'Failed to update fired schedule.',
|
|
168
171
|
)
|
|
169
172
|
|
|
170
|
-
let shouldRecoverDeadlineChecks = false
|
|
171
173
|
if (newStatus === 'active') {
|
|
172
174
|
if (!nextFireAt) {
|
|
173
175
|
return yield* new PlanSchedulerError({ message: 'Recurring schedules must resolve a next fire time.' })
|
|
@@ -185,6 +187,7 @@ export function makePlanSchedulerService(db: SurrealDBService) {
|
|
|
185
187
|
|
|
186
188
|
const runId = schedule.runId
|
|
187
189
|
const nodeId = schedule.nodeId
|
|
190
|
+
const promotedNode = Boolean(runId && nodeId)
|
|
188
191
|
if (runId && nodeId) {
|
|
189
192
|
yield* effectTryPromise(
|
|
190
193
|
() =>
|
|
@@ -195,26 +198,29 @@ export function makePlanSchedulerService(db: SurrealDBService) {
|
|
|
195
198
|
}),
|
|
196
199
|
'Failed to promote delayed plan node.',
|
|
197
200
|
)
|
|
198
|
-
shouldRecoverDeadlineChecks = true
|
|
199
201
|
}
|
|
200
202
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
(
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
203
|
+
const advancedCycle =
|
|
204
|
+
schedule.planSpecId && !schedule.runId
|
|
205
|
+
? yield* effectTryPromise(
|
|
206
|
+
() =>
|
|
207
|
+
db.findOne(
|
|
208
|
+
TABLES.PLAN_CYCLE,
|
|
209
|
+
{ scheduleId: ensureRecordId(schedule.id, TABLES.PLAN_SCHEDULE) },
|
|
210
|
+
PlanCycleRecordSchema,
|
|
211
|
+
),
|
|
212
|
+
'Failed to load plan cycle for schedule.',
|
|
213
|
+
).pipe(
|
|
214
|
+
Effect.tap((cycle) =>
|
|
215
|
+
cycle
|
|
216
|
+
? effectTryPromise(() => runtimeDeps.advanceCycle(cycle.id), 'Failed to advance plan cycle.')
|
|
217
|
+
: Effect.void,
|
|
218
|
+
),
|
|
219
|
+
Effect.map((cycle) => cycle !== null),
|
|
220
|
+
)
|
|
221
|
+
: false
|
|
216
222
|
|
|
217
|
-
if (
|
|
223
|
+
if (promotedNode || advancedCycle) {
|
|
218
224
|
yield* effectTryPromise(() => runtimeDeps.recoverDeadlineChecks(), 'Failed to recover deadline checks.')
|
|
219
225
|
}
|
|
220
226
|
})
|
|
@@ -357,7 +363,7 @@ export function makePlanSchedulerService(db: SurrealDBService) {
|
|
|
357
363
|
return {
|
|
358
364
|
createSchedule: createScheduleEffect,
|
|
359
365
|
computeNextFireAt(spec: PlanScheduleSpec, baseTime: Date = nowDate()): Date {
|
|
360
|
-
return
|
|
366
|
+
return computeNextFireAt(spec, baseTime)
|
|
361
367
|
},
|
|
362
368
|
/** Called by the BullMQ worker when a fire-schedule job executes. */
|
|
363
369
|
fireScheduleById: fireScheduleByIdEffect,
|
|
@@ -374,12 +380,13 @@ export function makePlanSchedulerService(db: SurrealDBService) {
|
|
|
374
380
|
export class PlanSchedulerServiceTag extends Context.Service<
|
|
375
381
|
PlanSchedulerServiceTag,
|
|
376
382
|
ReturnType<typeof makePlanSchedulerService>
|
|
377
|
-
>()('PlanSchedulerService') {}
|
|
383
|
+
>()('@lota-sdk/core/PlanSchedulerService') {}
|
|
378
384
|
|
|
379
385
|
export const PlanSchedulerServiceLive = Layer.effect(
|
|
380
386
|
PlanSchedulerServiceTag,
|
|
381
387
|
Effect.gen(function* () {
|
|
382
388
|
const db = yield* DatabaseServiceTag
|
|
383
|
-
|
|
389
|
+
const queues = yield* LotaQueuesServiceTag
|
|
390
|
+
return makePlanSchedulerService(db, queues.planScheduler)
|
|
384
391
|
}),
|
|
385
392
|
)
|
|
@@ -212,7 +212,7 @@ export function makePlanTemplateService(deps: PlanTemplateDeps) {
|
|
|
212
212
|
export class PlanTemplateServiceTag extends Context.Service<
|
|
213
213
|
PlanTemplateServiceTag,
|
|
214
214
|
ReturnType<typeof makePlanTemplateService>
|
|
215
|
-
>()('PlanTemplateService') {}
|
|
215
|
+
>()('@lota-sdk/core/PlanTemplateService') {}
|
|
216
216
|
|
|
217
217
|
export const PlanTemplateServiceLive = Layer.effect(
|
|
218
218
|
PlanTemplateServiceTag,
|
|
@@ -23,11 +23,14 @@ export function withTransactionAndEventsEffect<T, E, R>(params: {
|
|
|
23
23
|
(error) => new PlanTransactionEventsError({ message: 'Failed to run plan transaction.', cause: error }),
|
|
24
24
|
),
|
|
25
25
|
)
|
|
26
|
-
yield*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
yield* params.planEventDeliveryService
|
|
27
|
+
.dispatchEvents(emittedEvents)
|
|
28
|
+
.pipe(
|
|
29
|
+
Effect.mapError(
|
|
30
|
+
(error) =>
|
|
31
|
+
new PlanTransactionEventsError({ message: 'Failed to dispatch plan transaction events.', cause: error }),
|
|
32
|
+
),
|
|
33
|
+
)
|
|
31
34
|
return result
|
|
32
35
|
})
|
|
33
36
|
}
|
|
@@ -897,7 +897,7 @@ export function makePlanValidatorService(planCoordinationService: ReturnType<typ
|
|
|
897
897
|
export class PlanValidatorServiceTag extends Context.Service<
|
|
898
898
|
PlanValidatorServiceTag,
|
|
899
899
|
ReturnType<typeof makePlanValidatorService>
|
|
900
|
-
>()('PlanValidatorService') {}
|
|
900
|
+
>()('@lota-sdk/core/PlanValidatorService') {}
|
|
901
901
|
|
|
902
902
|
export const PlanValidatorServiceLive = Layer.effect(
|
|
903
903
|
PlanValidatorServiceTag,
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { Context, Effect, Layer, Schema } from 'effect'
|
|
2
2
|
|
|
3
|
+
import { ServiceError } from '../../effect/errors'
|
|
4
|
+
import { makeEffectTryPromiseWithMessage } from '../../effect/helpers'
|
|
3
5
|
import { RedisServiceTag } from '../../effect/services'
|
|
4
6
|
import { toValidationError } from '../../effect/zod'
|
|
5
7
|
import type { RedisConnectionManager } from '../../redis/connection'
|
|
6
8
|
import { nowEpochMillis } from '../../utils/date-time'
|
|
7
9
|
|
|
10
|
+
const tryWorkspacePromise = makeEffectTryPromiseWithMessage((message, cause) => new ServiceError({ message, cause }))
|
|
11
|
+
|
|
8
12
|
const PlanWorkspaceEntrySchema = Schema.Struct({
|
|
9
13
|
value: Schema.Unknown,
|
|
10
14
|
version: Schema.Number,
|
|
@@ -29,10 +33,9 @@ function parsePlanWorkspaceEntryEffect(
|
|
|
29
33
|
fieldKey: string,
|
|
30
34
|
raw: string,
|
|
31
35
|
): Effect.Effect<PlanWorkspaceEntry, ReturnType<typeof toValidationError>> {
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
})
|
|
36
|
+
return Schema.decodeUnknownEffect(PlanWorkspaceEntryJsonSchema)(raw).pipe(
|
|
37
|
+
Effect.mapError((error) => toValidationError(error, `Invalid plan workspace entry JSON for "${fieldKey}"`)),
|
|
38
|
+
)
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
export function makePlanWorkspaceService(redis: RedisConnectionManager) {
|
|
@@ -56,7 +59,10 @@ export function makePlanWorkspaceService(redis: RedisConnectionManager) {
|
|
|
56
59
|
timestamp: nowEpochMillis(),
|
|
57
60
|
}
|
|
58
61
|
const serialized = yield* Schema.encodeEffect(PlanWorkspaceEntryJsonSchema)(entry)
|
|
59
|
-
yield*
|
|
62
|
+
yield* tryWorkspacePromise(
|
|
63
|
+
() => conn.hset(hashKey, fieldKey, serialized),
|
|
64
|
+
'Failed to write plan workspace entry.',
|
|
65
|
+
)
|
|
60
66
|
})
|
|
61
67
|
|
|
62
68
|
const snapshotReadEffect = (params: { runId: string; readerNodeId: string; snapshotSequence?: number }) =>
|
|
@@ -64,7 +70,7 @@ export function makePlanWorkspaceService(redis: RedisConnectionManager) {
|
|
|
64
70
|
const conn = redis.getConnection()
|
|
65
71
|
const hashKey = `${PLAN_WORKSPACE_KEY_PREFIX}${params.runId}`
|
|
66
72
|
const nodePrefix = `${params.readerNodeId}:`
|
|
67
|
-
const all = yield*
|
|
73
|
+
const all = yield* tryWorkspacePromise(() => conn.hgetall(hashKey), 'Failed to read plan workspace snapshot.')
|
|
68
74
|
const result: Record<string, PlanWorkspaceEntry> = {}
|
|
69
75
|
for (const [fieldKey, raw] of Object.entries(all)) {
|
|
70
76
|
if (!fieldKey.startsWith(nodePrefix)) continue
|
|
@@ -83,11 +89,11 @@ export function makePlanWorkspaceService(redis: RedisConnectionManager) {
|
|
|
83
89
|
const hashKey = `${PLAN_WORKSPACE_KEY_PREFIX}${params.runId}`
|
|
84
90
|
const key = params.key
|
|
85
91
|
if (key !== undefined) {
|
|
86
|
-
const raw = yield*
|
|
92
|
+
const raw = yield* tryWorkspacePromise(() => conn.hget(hashKey, key), 'Failed to read plan workspace entry.')
|
|
87
93
|
if (!raw) return {}
|
|
88
94
|
return { [key]: yield* parsePlanWorkspaceEntryEffect(key, raw) }
|
|
89
95
|
}
|
|
90
|
-
const all = yield*
|
|
96
|
+
const all = yield* tryWorkspacePromise(() => conn.hgetall(hashKey), 'Failed to read plan workspace entries.')
|
|
91
97
|
const result: Record<string, PlanWorkspaceEntry> = {}
|
|
92
98
|
for (const [k, v] of Object.entries(all)) {
|
|
93
99
|
result[k] = yield* parsePlanWorkspaceEntryEffect(k, v)
|
|
@@ -97,10 +103,10 @@ export function makePlanWorkspaceService(redis: RedisConnectionManager) {
|
|
|
97
103
|
|
|
98
104
|
const cleanupEffect = (runId: string) =>
|
|
99
105
|
Effect.asVoid(
|
|
100
|
-
|
|
106
|
+
tryWorkspacePromise(() => {
|
|
101
107
|
const conn = redis.getConnection()
|
|
102
108
|
return conn.del(`${PLAN_WORKSPACE_KEY_PREFIX}${runId}`)
|
|
103
|
-
}),
|
|
109
|
+
}, 'Failed to clean up plan workspace.'),
|
|
104
110
|
)
|
|
105
111
|
|
|
106
112
|
return {
|
|
@@ -114,7 +120,7 @@ export function makePlanWorkspaceService(redis: RedisConnectionManager) {
|
|
|
114
120
|
export class PlanWorkspaceServiceTag extends Context.Service<
|
|
115
121
|
PlanWorkspaceServiceTag,
|
|
116
122
|
ReturnType<typeof makePlanWorkspaceService>
|
|
117
|
-
>()('PlanWorkspaceService') {}
|
|
123
|
+
>()('@lota-sdk/core/PlanWorkspaceService') {}
|
|
118
124
|
|
|
119
125
|
export const PlanWorkspaceServiceLive = Layer.effect(
|
|
120
126
|
PlanWorkspaceServiceTag,
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import type { OwnershipDispatchContext, PlanNodeSpec, PluginPlanNodeOwner } from '@lota-sdk/shared'
|
|
2
2
|
import { Context, Effect, Layer } from 'effect'
|
|
3
3
|
|
|
4
|
-
import { BadRequestError } from '../effect/errors'
|
|
4
|
+
import { BadRequestError, ServiceError } from '../effect/errors'
|
|
5
|
+
import { makeEffectTryPromiseWithMessage } from '../effect/helpers'
|
|
5
6
|
import { RuntimeConfigServiceTag } from '../effect/services'
|
|
7
|
+
|
|
8
|
+
const tryPluginExecutorPromise = makeEffectTryPromiseWithMessage(
|
|
9
|
+
(message, cause) => new ServiceError({ message, cause }),
|
|
10
|
+
)
|
|
6
11
|
import type { LotaPlugin, PluginNodeExecutionParams } from '../runtime/plugin-types'
|
|
7
12
|
import type { ResolvedLotaRuntimeConfig } from '../runtime/runtime-config'
|
|
8
13
|
import type { PlanValidationIssueInput } from './plan/plan-validator.service'
|
|
@@ -82,28 +87,28 @@ export function makePluginExecutorService(config: ResolvedLotaRuntimeConfig) {
|
|
|
82
87
|
return []
|
|
83
88
|
},
|
|
84
89
|
|
|
85
|
-
executeNode(params: {
|
|
90
|
+
executeNode: Effect.fn('PluginExecutor.executeNode')(function* (params: {
|
|
86
91
|
nodeSpec: PlanNodeSpec
|
|
87
92
|
resolvedInput: Record<string, unknown>
|
|
88
93
|
context: OwnershipDispatchContext
|
|
89
94
|
}) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
95
|
+
const owner = params.nodeSpec.owner
|
|
96
|
+
if (!isPluginOwner(owner)) {
|
|
97
|
+
return yield* new BadRequestError({
|
|
98
|
+
message: `PluginExecutor cannot execute owner type "${owner.executorType}".`,
|
|
99
|
+
})
|
|
100
|
+
}
|
|
97
101
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
const plugin = getPluginRuntime()[owner.ref]
|
|
103
|
+
const nodeExecutor = plugin?.nodeExecutor
|
|
104
|
+
if (!plugin || !nodeExecutor || !nodeExecutor.supportedOperations.includes(owner.operation)) {
|
|
105
|
+
return yield* new BadRequestError({
|
|
106
|
+
message: `Plugin executor ${owner.ref}.${owner.operation} is not registered.`,
|
|
107
|
+
})
|
|
108
|
+
}
|
|
105
109
|
|
|
106
|
-
|
|
110
|
+
return yield* tryPluginExecutorPromise(
|
|
111
|
+
() =>
|
|
107
112
|
nodeExecutor.executeNode(
|
|
108
113
|
buildPluginExecutionParams({
|
|
109
114
|
owner,
|
|
@@ -112,16 +117,16 @@ export function makePluginExecutorService(config: ResolvedLotaRuntimeConfig) {
|
|
|
112
117
|
context: params.context,
|
|
113
118
|
}),
|
|
114
119
|
),
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
},
|
|
120
|
+
`Plugin executor "${owner.ref}.${owner.operation}" failed.`,
|
|
121
|
+
).pipe(Effect.withSpan('PluginExecutor.invoke'))
|
|
122
|
+
}),
|
|
118
123
|
}
|
|
119
124
|
}
|
|
120
125
|
|
|
121
126
|
export class PluginExecutorServiceTag extends Context.Service<
|
|
122
127
|
PluginExecutorServiceTag,
|
|
123
128
|
ReturnType<typeof makePluginExecutorService>
|
|
124
|
-
>()('PluginExecutorService') {}
|
|
129
|
+
>()('@lota-sdk/core/PluginExecutorService') {}
|
|
125
130
|
|
|
126
131
|
export const PluginExecutorServiceLive = Layer.effect(
|
|
127
132
|
PluginExecutorServiceTag,
|
|
@@ -139,7 +139,7 @@ export function makeQualityMetricsService(db: SurrealDBService) {
|
|
|
139
139
|
export class QualityMetricsServiceTag extends Context.Service<
|
|
140
140
|
QualityMetricsServiceTag,
|
|
141
141
|
ReturnType<typeof makeQualityMetricsService>
|
|
142
|
-
>()('QualityMetricsService') {}
|
|
142
|
+
>()('@lota-sdk/core/QualityMetricsService') {}
|
|
143
143
|
|
|
144
144
|
export const QualityMetricsServiceLive = Layer.effect(
|
|
145
145
|
QualityMetricsServiceTag,
|
|
@@ -14,6 +14,7 @@ import type { SurrealDBService } from '../db/service'
|
|
|
14
14
|
import { TABLES } from '../db/tables'
|
|
15
15
|
import { isRetriableTransactionConflict } from '../db/transaction-conflict'
|
|
16
16
|
import { BadRequestError, DatabaseError } from '../effect/errors'
|
|
17
|
+
import { makeEffectTryPromiseWithMessage } from '../effect/helpers'
|
|
17
18
|
import { DatabaseServiceTag } from '../effect/services'
|
|
18
19
|
import { createDeterministicRecordId } from '../utils/crypto'
|
|
19
20
|
import { nowDate, unsafeDateFrom } from '../utils/date-time'
|
|
@@ -184,25 +185,15 @@ function getQueuedStatus(job: TrackedBullJobLike): QueueJobStatus {
|
|
|
184
185
|
return typeof delay === 'number' && delay > 0 ? 'delayed' : 'waiting'
|
|
185
186
|
}
|
|
186
187
|
|
|
188
|
+
const effectTryQueueJobPersistence = makeEffectTryPromiseWithMessage(
|
|
189
|
+
(message, cause) => new DatabaseError({ message, cause }),
|
|
190
|
+
)
|
|
191
|
+
|
|
187
192
|
function tryQueueJobPersistence<A>(
|
|
188
193
|
message: string,
|
|
189
|
-
|
|
194
|
+
evaluate: () => PromiseLike<A> | Effect.Effect<A, unknown>,
|
|
190
195
|
): Effect.Effect<A, DatabaseError> {
|
|
191
|
-
return
|
|
192
|
-
try {
|
|
193
|
-
const value = thunk()
|
|
194
|
-
if (Effect.isEffect(value)) {
|
|
195
|
-
return value.pipe(Effect.mapError((cause) => new DatabaseError({ message, cause })))
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return Effect.tryPromise({
|
|
199
|
-
try: () => Promise.resolve(value),
|
|
200
|
-
catch: (cause: unknown) => new DatabaseError({ message, cause }),
|
|
201
|
-
})
|
|
202
|
-
} catch (cause) {
|
|
203
|
-
return Effect.fail(new DatabaseError({ message, cause }))
|
|
204
|
-
}
|
|
205
|
-
})
|
|
196
|
+
return effectTryQueueJobPersistence(evaluate, message)
|
|
206
197
|
}
|
|
207
198
|
|
|
208
199
|
function withPersistenceRetry<T>(work: Effect.Effect<T, DatabaseError>): Effect.Effect<T, DatabaseError> {
|
|
@@ -456,7 +447,7 @@ export function makeQueueJobService(db: SurrealDBService) {
|
|
|
456
447
|
}
|
|
457
448
|
|
|
458
449
|
export class QueueJobServiceTag extends Context.Service<QueueJobServiceTag, ReturnType<typeof makeQueueJobService>>()(
|
|
459
|
-
'QueueJobService',
|
|
450
|
+
'@lota-sdk/core/QueueJobService',
|
|
460
451
|
) {}
|
|
461
452
|
|
|
462
453
|
export const QueueJobServiceLive = Layer.effect(
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from 'effect'
|
|
2
2
|
|
|
3
|
+
import type { ResolvedAgentConfig } from '../config/agent-defaults'
|
|
4
|
+
import { ServiceError } from '../effect/errors'
|
|
5
|
+
import { makeEffectTryPromiseWithMessage } from '../effect/helpers'
|
|
6
|
+
import { AgentConfigServiceTag } from '../effect/services'
|
|
3
7
|
import type { HelperModelRuntime } from '../runtime/helper-model'
|
|
4
8
|
import { HelperModelTag } from '../runtime/helper-model'
|
|
5
9
|
import { normalizeTitle } from '../runtime/title-helpers'
|
|
@@ -12,6 +16,10 @@ import { RecentActivityServiceTag } from './recent-activity.service'
|
|
|
12
16
|
|
|
13
17
|
const RECENT_ACTIVITY_TITLE_TIMEOUT_MS = 60_000
|
|
14
18
|
|
|
19
|
+
const tryRecentActivityTitlePromise = makeEffectTryPromiseWithMessage(
|
|
20
|
+
(message, cause) => new ServiceError({ message, cause }),
|
|
21
|
+
)
|
|
22
|
+
|
|
15
23
|
function buildRefinementPromptInput(
|
|
16
24
|
candidate: {
|
|
17
25
|
id: string
|
|
@@ -39,6 +47,7 @@ function buildRefinementPromptInput(
|
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
export function makeRecentActivityTitleService(
|
|
50
|
+
agentConfig: ResolvedAgentConfig,
|
|
42
51
|
recentActivityService: ReturnType<typeof makeRecentActivityService>,
|
|
43
52
|
helperModelRuntime: HelperModelRuntime,
|
|
44
53
|
) {
|
|
@@ -55,14 +64,16 @@ export function makeRecentActivityTitleService(
|
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
const refinedTitle = normalizeTitle(
|
|
58
|
-
yield*
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
yield* tryRecentActivityTitlePromise(
|
|
68
|
+
() =>
|
|
69
|
+
helperModelRuntime.generateHelperText({
|
|
70
|
+
tag: 'recent-activity-title-refinement',
|
|
71
|
+
createAgent: (options) => createRecentActivityTitleRefinerAgent(agentConfig, options),
|
|
72
|
+
defaultSystemPrompt: RECENT_ACTIVITY_TITLE_REFINER_PROMPT,
|
|
73
|
+
timeoutMs: RECENT_ACTIVITY_TITLE_TIMEOUT_MS,
|
|
74
|
+
messages: [{ role: 'user', content: promptInput }],
|
|
75
|
+
}),
|
|
76
|
+
'Failed to generate recent activity title refinement.',
|
|
66
77
|
),
|
|
67
78
|
)
|
|
68
79
|
if (
|
|
@@ -84,13 +95,14 @@ export function makeRecentActivityTitleService(
|
|
|
84
95
|
export class RecentActivityTitleServiceTag extends Context.Service<
|
|
85
96
|
RecentActivityTitleServiceTag,
|
|
86
97
|
ReturnType<typeof makeRecentActivityTitleService>
|
|
87
|
-
>()('RecentActivityTitleService') {}
|
|
98
|
+
>()('@lota-sdk/core/RecentActivityTitleService') {}
|
|
88
99
|
|
|
89
100
|
export const RecentActivityTitleServiceLive = Layer.effect(
|
|
90
101
|
RecentActivityTitleServiceTag,
|
|
91
102
|
Effect.gen(function* () {
|
|
103
|
+
const agentConfig = yield* AgentConfigServiceTag
|
|
92
104
|
const recentActivityService = yield* RecentActivityServiceTag
|
|
93
105
|
const helperModelRuntime = yield* HelperModelTag
|
|
94
|
-
return makeRecentActivityTitleService(recentActivityService, helperModelRuntime)
|
|
106
|
+
return makeRecentActivityTitleService(agentConfig, recentActivityService, helperModelRuntime)
|
|
95
107
|
}),
|
|
96
108
|
)
|
|
@@ -387,7 +387,7 @@ export function makeRecentActivityService(db: SurrealDBService) {
|
|
|
387
387
|
export class RecentActivityServiceTag extends Context.Service<
|
|
388
388
|
RecentActivityServiceTag,
|
|
389
389
|
ReturnType<typeof makeRecentActivityService>
|
|
390
|
-
>()('RecentActivityService') {}
|
|
390
|
+
>()('@lota-sdk/core/RecentActivityService') {}
|
|
391
391
|
|
|
392
392
|
export const RecentActivityServiceLive = Layer.effect(
|
|
393
393
|
RecentActivityServiceTag,
|