@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lota-sdk/core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@ai-sdk/openai": "^3.0.53",
|
|
32
32
|
"@chat-adapter/slack": "^4.26.0",
|
|
33
33
|
"@chat-adapter/state-ioredis": "^4.26.0",
|
|
34
|
-
"@lota-sdk/shared": "0.4.
|
|
34
|
+
"@lota-sdk/shared": "0.4.10",
|
|
35
35
|
"@mendable/firecrawl-js": "^4.18.3",
|
|
36
36
|
"@surrealdb/node": "^3.0.3",
|
|
37
37
|
"ai": "^6.0.167",
|
|
@@ -107,7 +107,9 @@ export class EmbeddingCache {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
export class EmbeddingCacheTag extends Context.Service<EmbeddingCacheTag, EmbeddingCache>()(
|
|
110
|
+
export class EmbeddingCacheTag extends Context.Service<EmbeddingCacheTag, EmbeddingCache>()(
|
|
111
|
+
'@lota-sdk/core/EmbeddingCache',
|
|
112
|
+
) {}
|
|
111
113
|
|
|
112
114
|
export const EmbeddingCacheLive = Layer.effect(
|
|
113
115
|
EmbeddingCacheTag,
|
|
@@ -6,7 +6,7 @@ import { Cause, Clock, Context, Duration, Effect, ExecutionPlan, Fiber, Layer, S
|
|
|
6
6
|
|
|
7
7
|
import { DEFAULT_AI_GATEWAY_URL } from '../config/constants'
|
|
8
8
|
import { AiGenerationError, ConfigurationError } from '../effect/errors'
|
|
9
|
-
import {
|
|
9
|
+
import { resolveLotaService } from '../effect/runtime'
|
|
10
10
|
import { RuntimeConfigServiceTag } from '../effect/services'
|
|
11
11
|
import { getDirectOpenRouterProvider, normalizeDirectOpenRouterModelId } from '../openrouter/direct-provider'
|
|
12
12
|
import { isRecord, readString } from '../utils/string'
|
|
@@ -28,12 +28,12 @@ type AiGatewayAttemptResult<A> = { source: string; result: A }
|
|
|
28
28
|
class AiGatewayGenerateAttempt extends Context.Service<
|
|
29
29
|
AiGatewayGenerateAttempt,
|
|
30
30
|
{ readonly execute: Effect.Effect<AiGatewayAttemptResult<AiGatewayGenerateResult>, AiGenerationError> }
|
|
31
|
-
>()('AiGatewayGenerateAttempt') {}
|
|
31
|
+
>()('@lota-sdk/core/internal/AiGatewayGenerateAttempt') {}
|
|
32
32
|
|
|
33
33
|
class AiGatewayStreamAttempt extends Context.Service<
|
|
34
34
|
AiGatewayStreamAttempt,
|
|
35
35
|
{ readonly execute: Effect.Effect<AiGatewayAttemptResult<AiGatewayStreamResult>, AiGenerationError> }
|
|
36
|
-
>()('AiGatewayStreamAttempt') {}
|
|
36
|
+
>()('@lota-sdk/core/internal/AiGatewayStreamAttempt') {}
|
|
37
37
|
|
|
38
38
|
const EXPECTED_GATEWAY_KEY_PREFIX = 'sk-bf-'
|
|
39
39
|
const AI_GATEWAY_VIRTUAL_KEY_HEADER = 'x-bf-vk'
|
|
@@ -69,6 +69,10 @@ const RETRYABLE_NETWORK_ERROR_PATTERNS = [
|
|
|
69
69
|
/timed out/i,
|
|
70
70
|
]
|
|
71
71
|
|
|
72
|
+
function isAiGenerationError(error: unknown): error is AiGenerationError {
|
|
73
|
+
return isRecord(error) && error._tag === 'AiGenerationError'
|
|
74
|
+
}
|
|
75
|
+
|
|
72
76
|
function getNumericField(value: Record<string, unknown>, key: string): number | null {
|
|
73
77
|
const field = value[key]
|
|
74
78
|
if (typeof field === 'number' && Number.isFinite(field)) return field
|
|
@@ -156,7 +160,7 @@ function stringifyProviderField(value: unknown, maxLength: number): string | und
|
|
|
156
160
|
}
|
|
157
161
|
|
|
158
162
|
function classifyAiGatewayError(source: string, error: unknown): AiGenerationError {
|
|
159
|
-
if (error
|
|
163
|
+
if (isAiGenerationError(error)) {
|
|
160
164
|
return error
|
|
161
165
|
}
|
|
162
166
|
|
|
@@ -465,7 +469,7 @@ function normalizeAiGatewayUrl(value: string): string {
|
|
|
465
469
|
export class AiGatewayTag extends Context.Service<
|
|
466
470
|
AiGatewayTag,
|
|
467
471
|
{ readonly semaphore: Semaphore.Semaphore; readonly provider: ReturnType<typeof createOpenAI> }
|
|
468
|
-
>()('AiGateway') {}
|
|
472
|
+
>()('@lota-sdk/core/AiGateway') {}
|
|
469
473
|
|
|
470
474
|
export const AiGatewayLive = Layer.effect(
|
|
471
475
|
AiGatewayTag,
|
|
@@ -487,12 +491,30 @@ export const AiGatewayLive = Layer.effect(
|
|
|
487
491
|
}),
|
|
488
492
|
)
|
|
489
493
|
|
|
490
|
-
|
|
491
|
-
|
|
494
|
+
type AiGatewayRuntimeConfig = Context.Service.Shape<typeof RuntimeConfigServiceTag>
|
|
495
|
+
|
|
496
|
+
let currentAiGateway: AiGatewayTag['Service'] | null = null
|
|
497
|
+
let currentAiGatewayRuntimeConfig: AiGatewayRuntimeConfig | null = null
|
|
498
|
+
|
|
499
|
+
export function configureAiGatewayRuntimeAccessors(params: {
|
|
500
|
+
aiGateway: AiGatewayTag['Service']
|
|
501
|
+
runtimeConfig: AiGatewayRuntimeConfig
|
|
502
|
+
}): void {
|
|
503
|
+
currentAiGateway = params.aiGateway
|
|
504
|
+
currentAiGatewayRuntimeConfig = params.runtimeConfig
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export function clearAiGatewayRuntimeAccessors(): void {
|
|
508
|
+
currentAiGateway = null
|
|
509
|
+
currentAiGatewayRuntimeConfig = null
|
|
492
510
|
}
|
|
493
511
|
|
|
494
512
|
function getAiGateway(): AiGatewayTag['Service'] {
|
|
495
|
-
return
|
|
513
|
+
return currentAiGateway ?? resolveLotaService(AiGatewayTag)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function getAiGatewayRuntimeConfig(): AiGatewayRuntimeConfig {
|
|
517
|
+
return currentAiGatewayRuntimeConfig ?? resolveLotaService(RuntimeConfigServiceTag)
|
|
496
518
|
}
|
|
497
519
|
|
|
498
520
|
function withAiGatewayConcurrency<A>(effect: Effect.Effect<A, AiGenerationError>): Effect.Effect<A, AiGenerationError> {
|
|
@@ -508,6 +530,11 @@ function withAiGatewayStreamConcurrency(
|
|
|
508
530
|
const currentContext = yield* Effect.context<never>()
|
|
509
531
|
yield* semaphore.take(1)
|
|
510
532
|
|
|
533
|
+
// NOTE: manual release intentional — permit outlives Effect scope for the
|
|
534
|
+
// stream lifetime. The stream consumer drains asynchronously after this
|
|
535
|
+
// Effect resolves; the permit is released by either the idle-timeout
|
|
536
|
+
// finalize callback or the error path below. The `released` guard makes
|
|
537
|
+
// the release idempotent across those paths.
|
|
511
538
|
let released = false
|
|
512
539
|
const release = () => {
|
|
513
540
|
if (released) return
|
|
@@ -517,6 +544,7 @@ function withAiGatewayStreamConcurrency(
|
|
|
517
544
|
|
|
518
545
|
const attempt = yield* restore(effect).pipe(
|
|
519
546
|
Effect.catchTag('AiGenerationError', (error) => Effect.sync(release).pipe(Effect.andThen(Effect.fail(error)))),
|
|
547
|
+
Effect.onInterrupt(() => Effect.sync(release)),
|
|
520
548
|
)
|
|
521
549
|
|
|
522
550
|
return {
|
|
@@ -611,12 +639,12 @@ function isOpenRouterModel(modelId: string): boolean {
|
|
|
611
639
|
}
|
|
612
640
|
|
|
613
641
|
function hasDirectOpenRouterFallback(modelId: string): boolean {
|
|
614
|
-
const config =
|
|
642
|
+
const config = getAiGatewayRuntimeConfig()
|
|
615
643
|
return isOpenRouterModel(modelId) && Boolean(config.aiGateway.openRouterApiKey?.trim())
|
|
616
644
|
}
|
|
617
645
|
|
|
618
646
|
function getDirectOpenRouterChatModel(modelId: string): AiGatewayLanguageModel {
|
|
619
|
-
const config =
|
|
647
|
+
const config = getAiGatewayRuntimeConfig()
|
|
620
648
|
return getDirectOpenRouterProvider(config.aiGateway.openRouterApiKey).chat(normalizeDirectOpenRouterModelId(modelId))
|
|
621
649
|
}
|
|
622
650
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { ToolSet } from 'ai'
|
|
2
|
-
import { Effect } from 'effect'
|
|
3
2
|
|
|
4
3
|
import { ConfigurationError } from '../effect/errors'
|
|
5
|
-
import {
|
|
4
|
+
import { resolveLotaService } from '../effect/runtime'
|
|
6
5
|
import { AgentConfigServiceTag, AgentFactoryServiceTag } from '../effect/services'
|
|
7
6
|
import type {
|
|
8
7
|
AgentFactory,
|
|
@@ -131,12 +130,28 @@ export interface CoreThreadProfile {
|
|
|
131
130
|
instructions: string
|
|
132
131
|
}
|
|
133
132
|
|
|
133
|
+
let currentResolvedAgentConfig: ResolvedAgentConfig | null = null
|
|
134
|
+
let currentResolvedAgentFactoryConfig: ResolvedAgentFactoryConfig | null = null
|
|
135
|
+
|
|
136
|
+
export function configureAgentRuntimeDefaults(params: {
|
|
137
|
+
agentConfig: ResolvedAgentConfig
|
|
138
|
+
agentFactoryConfig: ResolvedAgentFactoryConfig
|
|
139
|
+
}): void {
|
|
140
|
+
currentResolvedAgentConfig = params.agentConfig
|
|
141
|
+
currentResolvedAgentFactoryConfig = params.agentFactoryConfig
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function clearAgentRuntimeDefaults(): void {
|
|
145
|
+
currentResolvedAgentConfig = null
|
|
146
|
+
currentResolvedAgentFactoryConfig = null
|
|
147
|
+
}
|
|
148
|
+
|
|
134
149
|
function resolveAgentConfigFromRuntime(): ResolvedAgentConfig {
|
|
135
|
-
return
|
|
150
|
+
return currentResolvedAgentConfig ?? resolveLotaService(AgentConfigServiceTag)
|
|
136
151
|
}
|
|
137
152
|
|
|
138
153
|
function resolveAgentFactoryConfigFromRuntime(): ResolvedAgentFactoryConfig {
|
|
139
|
-
return
|
|
154
|
+
return currentResolvedAgentFactoryConfig ?? resolveLotaService(AgentFactoryServiceTag)
|
|
140
155
|
}
|
|
141
156
|
|
|
142
157
|
export function getResolvedAgentConfig(): ResolvedAgentConfig {
|
|
@@ -220,18 +235,16 @@ export interface AgentMentionMatch {
|
|
|
220
235
|
length: number
|
|
221
236
|
}
|
|
222
237
|
|
|
223
|
-
export function extractAgentMentions(
|
|
224
|
-
message: string,
|
|
225
|
-
agentConfig: ResolvedAgentConfig = resolveAgentConfigFromRuntime(),
|
|
226
|
-
): AgentMentionMatch[] {
|
|
238
|
+
export function extractAgentMentions(message: string, agentConfig?: ResolvedAgentConfig): AgentMentionMatch[] {
|
|
227
239
|
const matches: AgentMentionMatch[] = []
|
|
228
240
|
if (!message.trim()) return matches
|
|
229
241
|
|
|
242
|
+
const resolvedConfig = agentConfig ?? resolveAgentConfigFromRuntime()
|
|
230
243
|
const regex = new RegExp(AGENT_MENTION_REGEX)
|
|
231
244
|
for (const rawMatch of message.matchAll(regex)) {
|
|
232
245
|
const prefix = rawMatch[1]
|
|
233
246
|
const rawAgent = rawMatch[2].toLowerCase()
|
|
234
|
-
if (!
|
|
247
|
+
if (!resolvedConfig.rosterSet.has(rawAgent)) continue
|
|
235
248
|
|
|
236
249
|
const index = rawMatch.index + prefix.length
|
|
237
250
|
matches.push({ agent: rawAgent, mention: `@${rawAgent}`, index, length: rawAgent.length + 1 })
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import type { ChatMode, CreateRoutedAgentOptions } from '@lota-sdk/shared'
|
|
1
2
|
import type { ToolLoopAgent, ToolSet } from 'ai'
|
|
2
3
|
|
|
3
4
|
import type { RecordIdRef } from '../db/record-id'
|
|
4
5
|
import type { AgentRuntimeConfig, AgentRuntimeRuleOptions } from '../runtime/agent-runtime-policy'
|
|
5
|
-
import type { ChatMode, CreateRoutedAgentOptions } from '../runtime/agent-types'
|
|
6
6
|
|
|
7
7
|
export interface AgentToolBuilderParams {
|
|
8
8
|
agentId: string
|
|
@@ -12,7 +12,7 @@ const DEFAULT_CONFIG: BackgroundProcessingConfig = {
|
|
|
12
12
|
memoryConsolidationFrequency: 10,
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const resolvedConfig: BackgroundProcessingConfig = { ...DEFAULT_CONFIG }
|
|
16
16
|
|
|
17
17
|
export function getBackgroundProcessingConfig(): BackgroundProcessingConfig {
|
|
18
18
|
return resolvedConfig
|
package/src/config/index.ts
CHANGED
package/src/config/logger.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Effect, Logger, References } from 'effect'
|
|
2
2
|
|
|
3
|
+
import { getOptionalCurrentRuntime } from '../effect/runtime-ref'
|
|
4
|
+
|
|
3
5
|
const LOG_CATEGORY = 'lota-sdk'
|
|
4
6
|
|
|
5
7
|
export type LotaLogLevel = 'trace' | 'debug' | 'info' | 'warning' | 'error' | 'fatal'
|
|
@@ -44,6 +46,10 @@ function readEnvLogLevel(): LotaLogLevel | null {
|
|
|
44
46
|
return resolveLotaLogLevel(value)
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
// Module-level cache: loggers expose a sync `.info(...)` API that must work
|
|
50
|
+
// from both Effect and non-Effect call sites, so the level cannot live in
|
|
51
|
+
// Effect.Config (which requires Effect context to read). `configureLotaLogger`
|
|
52
|
+
// is called once from `buildInfrastructureLayer` with the resolved value.
|
|
47
53
|
let configuredLogLevel: LotaLogLevel = readEnvLogLevel() ?? 'info'
|
|
48
54
|
|
|
49
55
|
export function configureLotaLogger(logLevel: LotaLogLevel = 'info'): void {
|
|
@@ -222,19 +228,17 @@ function emitConsoleFallback(
|
|
|
222
228
|
level: LotaLogLevel,
|
|
223
229
|
category: readonly string[],
|
|
224
230
|
message: string,
|
|
225
|
-
|
|
231
|
+
annotations: Record<string, unknown>,
|
|
226
232
|
): void {
|
|
227
|
-
if (!shouldLog(level)) return
|
|
228
|
-
|
|
229
233
|
const formattedMessage = `[${category.join(':')}] ${message}`
|
|
230
|
-
const context = buildLogContext(fields)
|
|
231
234
|
const sink = getConsoleMethod(level)
|
|
232
|
-
|
|
235
|
+
const { lotaLogger: _lotaLogger, ...rest } = annotations
|
|
236
|
+
if (Object.keys(rest).length === 0) {
|
|
233
237
|
sink(formattedMessage)
|
|
234
238
|
return
|
|
235
239
|
}
|
|
236
240
|
|
|
237
|
-
sink(formattedMessage,
|
|
241
|
+
sink(formattedMessage, rest)
|
|
238
242
|
}
|
|
239
243
|
|
|
240
244
|
function emit(level: LotaLogLevel, category: readonly string[], message: string, fields?: LogFields): void {
|
|
@@ -244,8 +248,17 @@ function emit(level: LotaLogLevel, category: readonly string[], message: string,
|
|
|
244
248
|
const annotations = { lotaLogger: category.join(':'), ...buildLogContext(fields) }
|
|
245
249
|
const effect = getLogEffect(level, formattedMessage).pipe(Effect.annotateLogs(annotations))
|
|
246
250
|
|
|
251
|
+
// Route through the seated managed runtime so log timestamps stay on the
|
|
252
|
+
// caller's fiber and inherit its span/log annotations. Pre-bootstrap (no
|
|
253
|
+
// runtime seated) uses the standalone Effect logger so output stays
|
|
254
|
+
// consistent with post-bootstrap formatting.
|
|
255
|
+
const runtime = getOptionalCurrentRuntime()
|
|
247
256
|
try {
|
|
248
|
-
|
|
257
|
+
if (runtime) {
|
|
258
|
+
runtime.runFork(effect)
|
|
259
|
+
} else {
|
|
260
|
+
runStandaloneLogEffect(effect)
|
|
261
|
+
}
|
|
249
262
|
} catch {
|
|
250
263
|
emitConsoleFallback(level, category, formattedMessage, annotations)
|
|
251
264
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { getCurrentRuntime } from '../effect/runtime-ref'
|
|
1
|
+
import { resolveLotaService } from '../effect/runtime'
|
|
4
2
|
import { ThreadConfigServiceTag } from '../effect/services'
|
|
5
3
|
|
|
6
4
|
export interface ThreadBootstrapWelcomeConfig {
|
|
@@ -30,6 +28,16 @@ interface ResolvedThreadBootstrapConfig {
|
|
|
30
28
|
|
|
31
29
|
export type { ResolvedThreadBootstrapConfig }
|
|
32
30
|
|
|
31
|
+
let currentThreadBootstrapConfig: ResolvedThreadBootstrapConfig | null = null
|
|
32
|
+
|
|
33
|
+
export function configureThreadRuntimeDefaults(config: ResolvedThreadBootstrapConfig): void {
|
|
34
|
+
currentThreadBootstrapConfig = config
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function clearThreadRuntimeDefaults(): void {
|
|
38
|
+
currentThreadBootstrapConfig = null
|
|
39
|
+
}
|
|
40
|
+
|
|
33
41
|
function normalizeThreadAgentIds(values: readonly string[]): readonly string[] {
|
|
34
42
|
const seen = new Set<string>()
|
|
35
43
|
const deduped: string[] = []
|
|
@@ -73,7 +81,7 @@ export function resolveThreadConfig(params: {
|
|
|
73
81
|
}
|
|
74
82
|
|
|
75
83
|
export function getThreadBootstrapConfig(): ResolvedThreadBootstrapConfig {
|
|
76
|
-
return
|
|
84
|
+
return currentThreadBootstrapConfig ?? resolveLotaService(ThreadConfigServiceTag)
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
export function resolveOnboardingOwnerAgentId(
|