@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
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Match } from 'effect'
|
|
2
|
+
|
|
1
3
|
import { clampImportance, compactWhitespace } from '../../utils/string'
|
|
2
4
|
|
|
3
5
|
const SCORE_WEIGHTS = {
|
|
@@ -123,20 +125,17 @@ function scoreFact<T extends MemoryFactInput>(fact: T): number {
|
|
|
123
125
|
const durability = fact.durability ?? 'standard'
|
|
124
126
|
const type = fact.type ?? 'fact'
|
|
125
127
|
|
|
126
|
-
const durabilityWeight =
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
: type === 'preference'
|
|
138
|
-
? SCORE_WEIGHTS.type.preference
|
|
139
|
-
: SCORE_WEIGHTS.type.default
|
|
128
|
+
const durabilityWeight = Match.value(durability).pipe(
|
|
129
|
+
Match.when('core', () => SCORE_WEIGHTS.durability.core),
|
|
130
|
+
Match.when('standard', () => SCORE_WEIGHTS.durability.standard),
|
|
131
|
+
Match.orElse(() => SCORE_WEIGHTS.durability.weak),
|
|
132
|
+
)
|
|
133
|
+
const typeWeight = Match.value(type).pipe(
|
|
134
|
+
Match.when('decision', () => SCORE_WEIGHTS.type.decision),
|
|
135
|
+
Match.when('fact', () => SCORE_WEIGHTS.type.fact),
|
|
136
|
+
Match.when('preference', () => SCORE_WEIGHTS.type.preference),
|
|
137
|
+
Match.orElse(() => SCORE_WEIGHTS.type.default),
|
|
138
|
+
)
|
|
140
139
|
const lengthWeight =
|
|
141
140
|
Math.min(fact.content.length, SCORE_WEIGHTS.maxContentLength) / SCORE_WEIGHTS.maxContentLength / 10
|
|
142
141
|
|
|
@@ -340,61 +339,49 @@ export function compileMemoryUpdatesFromDelta(params: {
|
|
|
340
339
|
deleteSet.add(invalidateId)
|
|
341
340
|
}
|
|
342
341
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
342
|
+
const nextUpdates = Match.value(item.classification).pipe(
|
|
343
|
+
Match.when('duplicate', (): MemoryUpdateItemLike[] => {
|
|
344
|
+
const targetId = item.targetMemoryIds[0]
|
|
345
|
+
if (targetId) {
|
|
346
|
+
return [{ id: targetId, text: existingById.get(targetId) ?? item.fact, event: 'NONE' }]
|
|
347
|
+
}
|
|
348
|
+
return [{ id: `noop_${item.index}`, text: item.fact, event: 'NONE' }]
|
|
349
|
+
}),
|
|
350
|
+
Match.when('enriches', (): MemoryUpdateItemLike[] => {
|
|
351
|
+
const targetId = item.targetMemoryIds[0]
|
|
352
|
+
if (targetId) {
|
|
353
|
+
const relations = buildRelations(item, 'new').filter((relation) => relation.memoryId !== targetId)
|
|
354
|
+
return [
|
|
355
|
+
{
|
|
356
|
+
id: targetId,
|
|
357
|
+
text: item.fact,
|
|
358
|
+
event: 'UPDATE',
|
|
359
|
+
oldMemory: existingById.get(targetId),
|
|
360
|
+
...(relations.length > 0 ? { relatesTo: relations } : {}),
|
|
361
|
+
},
|
|
362
|
+
]
|
|
363
|
+
}
|
|
366
364
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
365
|
+
const addId = addIdByFactIndex.get(item.index) ?? nextAddId()
|
|
366
|
+
const relations = buildRelations(item, 'new')
|
|
367
|
+
return [{ id: addId, text: item.fact, event: 'ADD', ...(relations.length > 0 ? { relatesTo: relations } : {}) }]
|
|
368
|
+
}),
|
|
369
|
+
Match.whenOr('supersedes', 'contradicts', (classification): MemoryUpdateItemLike[] => {
|
|
370
|
+
const addId = addIdByFactIndex.get(item.index) ?? nextAddId()
|
|
371
|
+
const relations = buildRelations(item, classification)
|
|
372
|
+
return [{ id: addId, text: item.fact, event: 'ADD', ...(relations.length > 0 ? { relatesTo: relations } : {}) }]
|
|
373
|
+
}),
|
|
374
|
+
Match.when('new', (): MemoryUpdateItemLike[] => {
|
|
375
|
+
const addId = addIdByFactIndex.get(item.index) ?? nextAddId()
|
|
376
|
+
const relations = buildRelations(item, 'new')
|
|
377
|
+
return [{ id: addId, text: item.fact, event: 'ADD', ...(relations.length > 0 ? { relatesTo: relations } : {}) }]
|
|
378
|
+
}),
|
|
379
|
+
Match.exhaustive,
|
|
380
|
+
)
|
|
377
381
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const relations = buildRelations(item, item.classification)
|
|
381
|
-
updates.push({
|
|
382
|
-
id: addId,
|
|
383
|
-
text: item.fact,
|
|
384
|
-
event: 'ADD',
|
|
385
|
-
...(relations.length > 0 ? { relatesTo: relations } : {}),
|
|
386
|
-
})
|
|
387
|
-
continue
|
|
382
|
+
for (const update of nextUpdates) {
|
|
383
|
+
updates.push(update)
|
|
388
384
|
}
|
|
389
|
-
|
|
390
|
-
const addId = addIdByFactIndex.get(item.index) ?? nextAddId()
|
|
391
|
-
const relations = buildRelations(item, 'new')
|
|
392
|
-
updates.push({
|
|
393
|
-
id: addId,
|
|
394
|
-
text: item.fact,
|
|
395
|
-
event: 'ADD',
|
|
396
|
-
...(relations.length > 0 ? { relatesTo: relations } : {}),
|
|
397
|
-
})
|
|
398
385
|
}
|
|
399
386
|
|
|
400
387
|
const preservedRelationTargetIds = new Set<string>()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Schema } from 'effect'
|
|
1
|
+
import { Effect, Schema } from 'effect'
|
|
2
2
|
|
|
3
3
|
export const ORG_SCOPE_PREFIX = 'org'
|
|
4
4
|
|
|
@@ -9,41 +9,45 @@ export class MemoryScopeError extends Schema.TaggedErrorClass<MemoryScopeError>(
|
|
|
9
9
|
message: Schema.String,
|
|
10
10
|
}) {}
|
|
11
11
|
|
|
12
|
-
function stripRecordPrefix(id: string): string {
|
|
12
|
+
function stripRecordPrefix(id: string): Effect.Effect<string, MemoryScopeError> {
|
|
13
13
|
if (typeof id !== 'string' || id.length === 0) {
|
|
14
|
-
|
|
14
|
+
return Effect.fail(new MemoryScopeError({ message: 'id must be a non-empty string' }))
|
|
15
15
|
}
|
|
16
16
|
const [, ...rest] = id.split(':')
|
|
17
|
-
return rest.length > 0 ? rest.join(':') : id
|
|
17
|
+
return Effect.succeed(rest.length > 0 ? rest.join(':') : id)
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export function scopeId(prefix: string, id: string): string {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
20
|
+
export function scopeId(prefix: string, id: string): Effect.Effect<string, MemoryScopeError> {
|
|
21
|
+
return Effect.gen(function* () {
|
|
22
|
+
if (typeof prefix !== 'string' || prefix.length === 0) {
|
|
23
|
+
return yield* new MemoryScopeError({ message: 'prefix must be a non-empty string' })
|
|
24
|
+
}
|
|
25
|
+
if (!SCOPE_PREFIX_REGEX.test(prefix)) {
|
|
26
|
+
return yield* new MemoryScopeError({ message: `Invalid scope prefix: ${prefix}` })
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const stripped = yield* stripRecordPrefix(id)
|
|
30
|
+
const scoped = `${prefix}:${stripped}`
|
|
31
|
+
if (scoped.length > SCOPE_ID_MAX_LENGTH) {
|
|
32
|
+
return yield* new MemoryScopeError({ message: 'scopeId exceeds maximum length' })
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return scoped
|
|
36
|
+
})
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
export function agentScopeId(orgId: string, agentName: string): string {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
export function agentScopeId(orgId: string, agentName: string): Effect.Effect<string, MemoryScopeError> {
|
|
40
|
+
return Effect.gen(function* () {
|
|
41
|
+
if (typeof agentName !== 'string' || agentName.trim().length === 0) {
|
|
42
|
+
return yield* new MemoryScopeError({ message: 'agentName must be a non-empty string' })
|
|
43
|
+
}
|
|
44
|
+
const strippedOrgId = yield* stripRecordPrefix(orgId)
|
|
45
|
+
const scoped = `agent:${strippedOrgId}:${agentName.trim()}`
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
if (scoped.length > SCOPE_ID_MAX_LENGTH) {
|
|
48
|
+
return yield* new MemoryScopeError({ message: 'scopeId exceeds maximum length' })
|
|
49
|
+
}
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
return scoped
|
|
52
|
+
})
|
|
49
53
|
}
|
|
@@ -35,63 +35,42 @@ function readFunctionEffect(
|
|
|
35
35
|
return Effect.succeed(value as (...args: unknown[]) => PromiseLike<unknown>)
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
function configError(message: string): PluginResolutionError {
|
|
39
|
+
return new PluginResolutionError({ stage: 'configuration', message, cause: undefined })
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function requireRecord(value: unknown, message: string): Effect.Effect<Record<string, unknown>, PluginResolutionError> {
|
|
43
|
+
return isRecord(value) ? Effect.succeed(value) : Effect.fail(configError(message))
|
|
44
|
+
}
|
|
45
|
+
|
|
38
46
|
function resolvePluginServiceEffect(
|
|
39
47
|
pluginName: string,
|
|
40
48
|
serviceName: string,
|
|
41
49
|
methodName: string,
|
|
42
50
|
): Effect.Effect<(...args: unknown[]) => PromiseLike<unknown>, PluginResolutionError> {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (!isRecord(services)) {
|
|
67
|
-
return Effect.fail(
|
|
68
|
-
new PluginResolutionError({
|
|
69
|
-
stage: 'configuration',
|
|
70
|
-
message: `Plugin "${pluginName}" does not expose a services registry.`,
|
|
71
|
-
cause: undefined,
|
|
72
|
-
}),
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const service = services[serviceName]
|
|
77
|
-
if (!isRecord(service)) {
|
|
78
|
-
return Effect.fail(
|
|
79
|
-
new PluginResolutionError({
|
|
80
|
-
stage: 'configuration',
|
|
81
|
-
message: `Plugin "${pluginName}" service "${serviceName}" is not configured.`,
|
|
82
|
-
cause: undefined,
|
|
83
|
-
}),
|
|
84
|
-
)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return readFunctionEffect(
|
|
88
|
-
service[methodName],
|
|
89
|
-
`Plugin "${pluginName}" service "${serviceName}" is missing method "${methodName}".`,
|
|
90
|
-
).pipe(
|
|
91
|
-
Effect.map(
|
|
92
|
-
(method) =>
|
|
93
|
-
(...args: unknown[]) =>
|
|
94
|
-
Reflect.apply(method, service, args),
|
|
51
|
+
return Effect.fromNullishOr(getPluginRuntime()).pipe(
|
|
52
|
+
Effect.mapError(() => configError(`Plugin runtime is not configured. Missing "${pluginName}" integration.`)),
|
|
53
|
+
Effect.flatMap((pluginRuntime) =>
|
|
54
|
+
requireRecord(pluginRuntime[pluginName], `Plugin "${pluginName}" is not configured in the current runtime.`),
|
|
55
|
+
),
|
|
56
|
+
Effect.flatMap((plugin) =>
|
|
57
|
+
requireRecord(plugin.services, `Plugin "${pluginName}" does not expose a services registry.`),
|
|
58
|
+
),
|
|
59
|
+
Effect.flatMap((services) =>
|
|
60
|
+
requireRecord(services[serviceName], `Plugin "${pluginName}" service "${serviceName}" is not configured.`).pipe(
|
|
61
|
+
Effect.flatMap((service) =>
|
|
62
|
+
readFunctionEffect(
|
|
63
|
+
service[methodName],
|
|
64
|
+
`Plugin "${pluginName}" service "${serviceName}" is missing method "${methodName}".`,
|
|
65
|
+
).pipe(
|
|
66
|
+
Effect.map(
|
|
67
|
+
(method) =>
|
|
68
|
+
(...args: unknown[]) =>
|
|
69
|
+
Reflect.apply(method, service, args),
|
|
70
|
+
),
|
|
71
|
+
),
|
|
72
|
+
),
|
|
73
|
+
),
|
|
95
74
|
),
|
|
96
75
|
)
|
|
97
76
|
}
|
|
@@ -100,8 +79,8 @@ function tryResolvePluginServiceEffect(
|
|
|
100
79
|
pluginName: string,
|
|
101
80
|
serviceName: string,
|
|
102
81
|
methodName: string,
|
|
103
|
-
): Effect.Effect<((...args: unknown[]) => PromiseLike<unknown>) |
|
|
104
|
-
return Effect.catch(resolvePluginServiceEffect(pluginName, serviceName, methodName), () => Effect.
|
|
82
|
+
): Effect.Effect<((...args: unknown[]) => PromiseLike<unknown>) | void, never, never> {
|
|
83
|
+
return Effect.catch(resolvePluginServiceEffect(pluginName, serviceName, methodName), () => Effect.void)
|
|
105
84
|
}
|
|
106
85
|
|
|
107
86
|
export function getLinearInstallationByOrgId(organizationId: RecordIdRef): Promise<unknown> {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { ChatMessage } from '@lota-sdk/shared'
|
|
2
2
|
import { Schema, Effect } from 'effect'
|
|
3
|
-
import type { Context } from 'effect'
|
|
4
3
|
|
|
5
4
|
import type { ResolvedAgentConfig } from '../config/agent-defaults'
|
|
6
5
|
import type { RecordIdRef } from '../db/record-id'
|
|
7
|
-
import {
|
|
6
|
+
import { runPromise } from '../effect/runtime'
|
|
8
7
|
import { AgentConfigServiceTag, RuntimeAdaptersServiceTag } from '../effect/services'
|
|
9
8
|
import { enqueueMemoryConsolidation } from '../queues/memory-consolidation.queue'
|
|
10
9
|
import { enqueueRegularChatMemoryDigest, enqueueSkillExtraction } from '../queues/organization-learning.queue'
|
|
@@ -21,7 +20,6 @@ import {
|
|
|
21
20
|
shouldEnqueueOnboardingPostChatMemory,
|
|
22
21
|
shouldEnqueueRegularDigestForThread,
|
|
23
22
|
} from './memory/memory-digest-policy'
|
|
24
|
-
import type { LotaRuntimeAdapters } from './runtime-extensions'
|
|
25
23
|
import { shouldEnqueueSkillExtraction } from './skill-extraction-policy'
|
|
26
24
|
import {
|
|
27
25
|
appendPersistedThreadContextToHistoryMessages,
|
|
@@ -33,13 +31,6 @@ import {
|
|
|
33
31
|
toHistoryMessages,
|
|
34
32
|
} from './thread-chat-helpers'
|
|
35
33
|
|
|
36
|
-
interface PostTurnSideEffectsServices {
|
|
37
|
-
recentActivityService: Context.Service.Shape<typeof RecentActivityServiceTag>
|
|
38
|
-
threadService: Context.Service.Shape<typeof ThreadServiceTag>
|
|
39
|
-
agentConfig: ResolvedAgentConfig
|
|
40
|
-
runtimeAdapters: LotaRuntimeAdapters
|
|
41
|
-
}
|
|
42
|
-
|
|
43
34
|
class PostTurnSideEffectsError extends Schema.TaggedErrorClass<PostTurnSideEffectsError>()('PostTurnSideEffectsError', {
|
|
44
35
|
message: Schema.String,
|
|
45
36
|
cause: Schema.Defect,
|
|
@@ -55,20 +46,6 @@ function tryPostTurnSideEffect<A>(
|
|
|
55
46
|
})
|
|
56
47
|
}
|
|
57
48
|
|
|
58
|
-
function getPostTurnSideEffectsServices(): PostTurnSideEffectsServices {
|
|
59
|
-
const runtime = getCurrentRuntime()
|
|
60
|
-
return runtime.runSync(
|
|
61
|
-
Effect.gen(function* () {
|
|
62
|
-
return {
|
|
63
|
-
recentActivityService: yield* RecentActivityServiceTag,
|
|
64
|
-
threadService: yield* ThreadServiceTag,
|
|
65
|
-
agentConfig: yield* AgentConfigServiceTag,
|
|
66
|
-
runtimeAdapters: yield* RuntimeAdaptersServiceTag,
|
|
67
|
-
}
|
|
68
|
-
}),
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
49
|
function resolveDisplayName(
|
|
73
50
|
agentConfig: ResolvedAgentConfig,
|
|
74
51
|
agentId: string,
|
|
@@ -139,7 +116,10 @@ interface PostTurnSideEffectsParams {
|
|
|
139
116
|
|
|
140
117
|
const runPostTurnSideEffectsEffect = (params: PostTurnSideEffectsParams) =>
|
|
141
118
|
Effect.gen(function* () {
|
|
142
|
-
const
|
|
119
|
+
const recentActivityService = yield* RecentActivityServiceTag
|
|
120
|
+
const threadService = yield* ThreadServiceTag
|
|
121
|
+
const agentConfig: ResolvedAgentConfig = yield* AgentConfigServiceTag
|
|
122
|
+
const runtimeAdapters = yield* RuntimeAdaptersServiceTag
|
|
143
123
|
const recentHistory = yield* tryPostTurnSideEffect('Failed to load recent thread history.', () =>
|
|
144
124
|
params.loadRecentHistory(),
|
|
145
125
|
)
|
|
@@ -286,5 +266,5 @@ const runPostTurnSideEffectsEffect = (params: PostTurnSideEffectsParams) =>
|
|
|
286
266
|
})
|
|
287
267
|
|
|
288
268
|
export function runPostTurnSideEffects(params: PostTurnSideEffectsParams): Promise<void> {
|
|
289
|
-
return
|
|
269
|
+
return runPromise(runPostTurnSideEffectsEffect(params))
|
|
290
270
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Schema, Effect } from 'effect'
|
|
2
2
|
|
|
3
|
-
interface ScopedRetrievalTask<TCandidate> {
|
|
3
|
+
interface ScopedRetrievalTask<TCandidate, E = never> {
|
|
4
4
|
scopeTag: string
|
|
5
|
-
retrieve: () => PromiseLike<TCandidate[]> | Effect.Effect<TCandidate[],
|
|
5
|
+
retrieve: () => PromiseLike<TCandidate[]> | Effect.Effect<TCandidate[], E>
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
interface ScopedRetrievalResult<TCandidate> {
|
|
@@ -20,8 +20,8 @@ function toScopedRetrievalError(scopeTag: string, cause: unknown): ScopedRetriev
|
|
|
20
20
|
return new ScopedRetrievalError({ scopeTag, message: cause instanceof Error ? cause.message : String(cause), cause })
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export function executeScopedRetrieval<TCandidate>(
|
|
24
|
-
tasks: ScopedRetrievalTask<TCandidate>[],
|
|
23
|
+
export function executeScopedRetrieval<TCandidate, E>(
|
|
24
|
+
tasks: ScopedRetrievalTask<TCandidate, E>[],
|
|
25
25
|
): Effect.Effect<ScopedRetrievalResult<TCandidate>[], ScopedRetrievalError> {
|
|
26
26
|
return Effect.forEach(
|
|
27
27
|
tasks,
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installs and tears down the SDK's module-level runtime accessors.
|
|
3
|
+
*
|
|
4
|
+
* Several SDK modules expose `configure*`/`clear*` pairs so host code can read
|
|
5
|
+
* runtime-resolved services synchronously (AI gateway, agent defaults,
|
|
6
|
+
* firecrawl, graph designer, queue jobs, runtime extensions, redis, thread
|
|
7
|
+
* defaults). `createLotaRuntime` wires them once at boot and clears them on
|
|
8
|
+
* disconnect; this module keeps both phases in a single place so they stay
|
|
9
|
+
* symmetric.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { Context, ManagedRuntime } from 'effect'
|
|
13
|
+
import { Effect } from 'effect'
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
AiGatewayTag,
|
|
17
|
+
clearAiGatewayRuntimeAccessors,
|
|
18
|
+
configureAiGatewayRuntimeAccessors,
|
|
19
|
+
} from '../ai-gateway/ai-gateway'
|
|
20
|
+
import { clearAgentRuntimeDefaults, configureAgentRuntimeDefaults } from '../config/agent-defaults'
|
|
21
|
+
import { clearThreadRuntimeDefaults, configureThreadRuntimeDefaults } from '../config/thread-defaults'
|
|
22
|
+
import {
|
|
23
|
+
AgentConfigServiceTag,
|
|
24
|
+
AgentFactoryServiceTag,
|
|
25
|
+
RuntimeAdaptersServiceTag,
|
|
26
|
+
RuntimeWorkerExtensionsServiceTag,
|
|
27
|
+
ThreadConfigServiceTag,
|
|
28
|
+
ToolProvidersServiceTag,
|
|
29
|
+
TurnHooksServiceTag,
|
|
30
|
+
} from '../effect'
|
|
31
|
+
import type { RedisConnectionManager } from '../redis/connection'
|
|
32
|
+
import { clearRuntimeRedisManager, configureRuntimeRedisManager } from '../redis/runtime-connection'
|
|
33
|
+
import { QueueJobServiceTag } from '../services/queue-job.service'
|
|
34
|
+
import { FirecrawlTag, clearFirecrawlClient, configureFirecrawlClient } from '../tools/firecrawl-client'
|
|
35
|
+
import { clearQueueJobService, configureQueueJobService } from '../workers/worker-utils'
|
|
36
|
+
import { clearGraphDesigner, configureGraphDesigner } from './graph-designer'
|
|
37
|
+
import type { ResolvedLotaRuntimeConfig } from './runtime-config'
|
|
38
|
+
import { clearRuntimeExtensionsAccessors, configureRuntimeExtensionsAccessors } from './runtime-extensions'
|
|
39
|
+
|
|
40
|
+
// eslint-disable-next-line typescript-eslint/no-explicit-any -- ManagedRuntime is contravariant in R; `any` is the only valid wildcard
|
|
41
|
+
type SdkManagedRuntime = ManagedRuntime.ManagedRuntime<any, any>
|
|
42
|
+
|
|
43
|
+
interface ConfigureRuntimeAccessorsInput {
|
|
44
|
+
managedRuntime: SdkManagedRuntime
|
|
45
|
+
runtimeConfig: ResolvedLotaRuntimeConfig
|
|
46
|
+
redisManager: RedisConnectionManager
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Resolve every service the SDK exposes through module-level accessors and
|
|
51
|
+
* install them. Must be called after `setLotaSdkRuntime(managedRuntime)`.
|
|
52
|
+
*/
|
|
53
|
+
export function configureRuntimeModuleAccessors(input: ConfigureRuntimeAccessorsInput): void {
|
|
54
|
+
const { managedRuntime, runtimeConfig, redisManager } = input
|
|
55
|
+
const resolve = <I, T>(tag: Context.Key<I, T>): T =>
|
|
56
|
+
// We know every tag is provided by the managed runtime; the cast bridges
|
|
57
|
+
// the erased service-set carried by `SdkManagedRuntime`.
|
|
58
|
+
managedRuntime.runSync(Effect.service(tag) as Effect.Effect<T, never, never>)
|
|
59
|
+
|
|
60
|
+
configureAiGatewayRuntimeAccessors({ aiGateway: resolve(AiGatewayTag), runtimeConfig })
|
|
61
|
+
configureAgentRuntimeDefaults({
|
|
62
|
+
agentConfig: resolve(AgentConfigServiceTag),
|
|
63
|
+
agentFactoryConfig: resolve(AgentFactoryServiceTag),
|
|
64
|
+
})
|
|
65
|
+
configureThreadRuntimeDefaults(resolve(ThreadConfigServiceTag))
|
|
66
|
+
configureRuntimeExtensionsAccessors({
|
|
67
|
+
adapters: resolve(RuntimeAdaptersServiceTag),
|
|
68
|
+
turnHooks: resolve(TurnHooksServiceTag),
|
|
69
|
+
toolProviders: resolve(ToolProvidersServiceTag),
|
|
70
|
+
extraWorkers: resolve(RuntimeWorkerExtensionsServiceTag),
|
|
71
|
+
})
|
|
72
|
+
configureFirecrawlClient(resolve(FirecrawlTag))
|
|
73
|
+
configureQueueJobService(resolve(QueueJobServiceTag))
|
|
74
|
+
configureRuntimeRedisManager(redisManager)
|
|
75
|
+
configureGraphDesigner(runtimeConfig.graphDesigner)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Clears every module-level accessor installed by
|
|
80
|
+
* `configureRuntimeModuleAccessors`. Always safe to call (idempotent per clear
|
|
81
|
+
* function).
|
|
82
|
+
*/
|
|
83
|
+
export function clearRuntimeModuleAccessors(): void {
|
|
84
|
+
clearAiGatewayRuntimeAccessors()
|
|
85
|
+
clearAgentRuntimeDefaults()
|
|
86
|
+
clearFirecrawlClient()
|
|
87
|
+
clearGraphDesigner()
|
|
88
|
+
clearQueueJobService()
|
|
89
|
+
clearRuntimeExtensionsAccessors()
|
|
90
|
+
clearRuntimeRedisManager()
|
|
91
|
+
clearThreadRuntimeDefaults()
|
|
92
|
+
}
|
|
@@ -329,7 +329,7 @@ export function parseWorkerBootstrapEnv(env: Record<string, string | undefined>)
|
|
|
329
329
|
return WORKER_BOOTSTRAP_ENV_SCHEMA.parse(env)
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
-
const
|
|
332
|
+
export const lotaRuntimeEnvConfig = Config.all({
|
|
333
333
|
surrealdbUrl: Config.string('SURREALDB_URL'),
|
|
334
334
|
surrealdbNamespace: Config.string('SURREALDB_NAMESPACE'),
|
|
335
335
|
surrealdbUser: Config.string('SURREALDB_USER'),
|
|
@@ -369,7 +369,7 @@ export function loadLotaRuntimeConfigFromEnv(
|
|
|
369
369
|
overrides: LotaRuntimeEnvironmentOverrides,
|
|
370
370
|
options: { configProvider?: ConfigProvider.ConfigProvider } = {},
|
|
371
371
|
) {
|
|
372
|
-
return
|
|
372
|
+
return lotaRuntimeEnvConfig
|
|
373
373
|
.parse(options.configProvider ?? ConfigProvider.fromEnv())
|
|
374
374
|
.pipe(
|
|
375
375
|
Effect.map((env) =>
|
|
@@ -403,7 +403,7 @@ export function loadLotaRuntimeConfigFromEnv(
|
|
|
403
403
|
apiKey: Redacted.value(env.firecrawlApiKey),
|
|
404
404
|
...(Option.isSome(env.firecrawlApiBaseUrl) ? { apiBaseUrl: env.firecrawlApiBaseUrl.value } : {}),
|
|
405
405
|
},
|
|
406
|
-
logging: overrides.logging ?? { level:
|
|
406
|
+
logging: overrides.logging ?? { level: z.enum(logLevelValues).parse(env.logLevel) },
|
|
407
407
|
memory: {
|
|
408
408
|
searchK: env.memorySearchK,
|
|
409
409
|
rerankerStrategy: env.memoryRerankerStrategy as MemoryRerankerStrategy,
|
|
@@ -6,11 +6,9 @@ import type {
|
|
|
6
6
|
PlanSpecRecord,
|
|
7
7
|
} from '@lota-sdk/shared'
|
|
8
8
|
import type { ToolSet } from 'ai'
|
|
9
|
-
import { Effect } from 'effect'
|
|
10
|
-
import type { Context } from 'effect'
|
|
11
9
|
|
|
12
10
|
import type { RecordIdRef } from '../db/record-id'
|
|
13
|
-
import {
|
|
11
|
+
import { resolveLotaService } from '../effect/runtime'
|
|
14
12
|
import {
|
|
15
13
|
RuntimeAdaptersServiceTag,
|
|
16
14
|
RuntimeWorkerExtensionsServiceTag,
|
|
@@ -202,20 +200,33 @@ export interface LotaRuntimeAdapters {
|
|
|
202
200
|
withWorkspaceMemoryLock?: <T>(workspaceId: string, fn: () => Promise<T>) => Promise<T>
|
|
203
201
|
}
|
|
204
202
|
|
|
205
|
-
|
|
206
|
-
|
|
203
|
+
interface RuntimeExtensionsAccessors {
|
|
204
|
+
adapters: LotaRuntimeAdapters
|
|
205
|
+
turnHooks: LotaRuntimeTurnHooks
|
|
206
|
+
toolProviders: ToolSet
|
|
207
|
+
extraWorkers: LotaRuntimeWorkerExtensions
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
let runtimeExtensionsAccessors: RuntimeExtensionsAccessors | null = null
|
|
211
|
+
|
|
212
|
+
export function configureRuntimeExtensionsAccessors(accessors: RuntimeExtensionsAccessors): void {
|
|
213
|
+
runtimeExtensionsAccessors = accessors
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function clearRuntimeExtensionsAccessors(): void {
|
|
217
|
+
runtimeExtensionsAccessors = null
|
|
207
218
|
}
|
|
208
219
|
|
|
209
220
|
export function getRuntimeAdapters(): LotaRuntimeAdapters {
|
|
210
|
-
return
|
|
221
|
+
return runtimeExtensionsAccessors?.adapters ?? resolveLotaService(RuntimeAdaptersServiceTag)
|
|
211
222
|
}
|
|
212
223
|
|
|
213
224
|
export function getTurnHooks(): LotaRuntimeTurnHooks {
|
|
214
|
-
return
|
|
225
|
+
return runtimeExtensionsAccessors?.turnHooks ?? resolveLotaService(TurnHooksServiceTag)
|
|
215
226
|
}
|
|
216
227
|
|
|
217
228
|
export function getToolProviders(): ToolSet {
|
|
218
|
-
return
|
|
229
|
+
return runtimeExtensionsAccessors?.toolProviders ?? resolveLotaService(ToolProvidersServiceTag)
|
|
219
230
|
}
|
|
220
231
|
|
|
221
232
|
export function getConfiguredPluginDatabaseConnector(): (() => Promise<void>) | undefined {
|
|
@@ -223,7 +234,7 @@ export function getConfiguredPluginDatabaseConnector(): (() => Promise<void>) |
|
|
|
223
234
|
}
|
|
224
235
|
|
|
225
236
|
export function getExtraWorkers(): LotaRuntimeWorkerExtensions {
|
|
226
|
-
return
|
|
237
|
+
return runtimeExtensionsAccessors?.extraWorkers ?? resolveLotaService(RuntimeWorkerExtensionsServiceTag)
|
|
227
238
|
}
|
|
228
239
|
|
|
229
240
|
export function withConfiguredWorkspaceMemoryLock<T>(workspaceId: string, fn: () => Promise<T>): Promise<T> {
|