@lota-sdk/core 0.4.7 → 0.4.9

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.
Files changed (259) hide show
  1. package/package.json +11 -12
  2. package/src/ai/embedding-cache.ts +94 -22
  3. package/src/ai-gateway/ai-gateway.ts +738 -223
  4. package/src/config/agent-defaults.ts +176 -75
  5. package/src/config/agent-types.ts +54 -4
  6. package/src/config/constants.ts +8 -2
  7. package/src/config/logger.ts +286 -19
  8. package/src/config/model-constants.ts +1 -0
  9. package/src/config/thread-defaults.ts +33 -21
  10. package/src/create-runtime.ts +725 -383
  11. package/src/db/base.service.ts +52 -28
  12. package/src/db/cursor-pagination.ts +71 -30
  13. package/src/db/memory-store.helpers.ts +4 -7
  14. package/src/db/memory-store.ts +856 -598
  15. package/src/db/memory.ts +398 -275
  16. package/src/db/record-id.ts +32 -10
  17. package/src/db/schema-fingerprint.ts +30 -12
  18. package/src/db/service-normalization.ts +255 -0
  19. package/src/db/service.ts +726 -761
  20. package/src/db/startup.ts +140 -66
  21. package/src/db/transaction-conflict.ts +15 -0
  22. package/src/effect/awaitable-effect.ts +87 -0
  23. package/src/effect/errors.ts +121 -0
  24. package/src/effect/helpers.ts +98 -0
  25. package/src/effect/index.ts +22 -0
  26. package/src/effect/layers.ts +228 -0
  27. package/src/effect/runtime-ref.ts +25 -0
  28. package/src/effect/runtime.ts +31 -0
  29. package/src/effect/services.ts +57 -0
  30. package/src/effect/zod.ts +43 -0
  31. package/src/embeddings/provider.ts +122 -71
  32. package/src/index.ts +46 -1
  33. package/src/openrouter/direct-provider.ts +29 -0
  34. package/src/queues/autonomous-job.queue.ts +130 -74
  35. package/src/queues/context-compaction.queue.ts +60 -15
  36. package/src/queues/delayed-node-promotion.queue.ts +52 -15
  37. package/src/queues/document-processor.queue.ts +52 -77
  38. package/src/queues/memory-consolidation.queue.ts +47 -32
  39. package/src/queues/organization-learning.queue.ts +13 -4
  40. package/src/queues/plan-agent-heartbeat.queue.ts +65 -21
  41. package/src/queues/plan-scheduler.queue.ts +107 -31
  42. package/src/queues/post-chat-memory.queue.ts +66 -24
  43. package/src/queues/queue-factory.ts +142 -52
  44. package/src/queues/standalone-worker.ts +39 -0
  45. package/src/queues/title-generation.queue.ts +54 -9
  46. package/src/redis/connection.ts +84 -32
  47. package/src/redis/index.ts +6 -8
  48. package/src/redis/org-memory-lock.ts +60 -27
  49. package/src/redis/redis-lease-lock.ts +200 -121
  50. package/src/redis/runtime-connection.ts +10 -0
  51. package/src/redis/stream-context.ts +84 -46
  52. package/src/runtime/agent-identity-overrides.ts +2 -2
  53. package/src/runtime/agent-runtime-policy.ts +4 -1
  54. package/src/runtime/agent-stream-helpers.ts +20 -9
  55. package/src/runtime/chat-run-orchestration.ts +102 -19
  56. package/src/runtime/chat-run-registry.ts +36 -2
  57. package/src/runtime/context-compaction/context-compaction-runtime.ts +107 -0
  58. package/src/runtime/{context-compaction.ts → context-compaction/context-compaction.ts} +114 -91
  59. package/src/runtime/execution-plan-visibility.ts +2 -2
  60. package/src/runtime/execution-plan.ts +42 -15
  61. package/src/runtime/graph-designer.ts +11 -7
  62. package/src/runtime/helper-model.ts +135 -48
  63. package/src/runtime/index.ts +7 -7
  64. package/src/runtime/indexed-repositories-policy.ts +3 -3
  65. package/src/runtime/{memory-block.ts → memory/memory-block.ts} +40 -36
  66. package/src/runtime/{memory-digest-policy.ts → memory/memory-digest-policy.ts} +1 -1
  67. package/src/runtime/{memory-pipeline.ts → memory/memory-pipeline.ts} +1 -1
  68. package/src/runtime/{memory-prompts-fact.ts → memory/memory-prompts-fact.ts} +2 -2
  69. package/src/runtime/{memory-scope.ts → memory/memory-scope.ts} +12 -6
  70. package/src/runtime/plugin-resolution.ts +144 -24
  71. package/src/runtime/plugin-types.ts +9 -1
  72. package/src/runtime/post-turn-side-effects.ts +197 -130
  73. package/src/runtime/retrieval-adapters.ts +38 -4
  74. package/src/runtime/runtime-config.ts +165 -61
  75. package/src/runtime/runtime-extensions.ts +21 -34
  76. package/src/runtime/social-chat/social-chat-agent-runner.ts +157 -0
  77. package/src/runtime/{social-chat-history.ts → social-chat/social-chat-history.ts} +42 -20
  78. package/src/runtime/social-chat/social-chat.ts +594 -0
  79. package/src/runtime/specialist-runner.ts +36 -10
  80. package/src/runtime/team-consultation/team-consultation-orchestrator.ts +427 -0
  81. package/src/runtime/{team-consultation-prompts.ts → team-consultation/team-consultation-prompts.ts} +6 -2
  82. package/src/runtime/thread-chat-helpers.ts +2 -2
  83. package/src/runtime/thread-plan-turn.ts +2 -1
  84. package/src/runtime/thread-turn-context.ts +172 -94
  85. package/src/runtime/turn-lifecycle.ts +93 -27
  86. package/src/services/agent-activity.service.ts +287 -203
  87. package/src/services/agent-executor.service.ts +329 -217
  88. package/src/services/artifact.service.ts +225 -148
  89. package/src/services/attachment.service.ts +137 -115
  90. package/src/services/autonomous-job.service.ts +888 -491
  91. package/src/services/chat-run-registry.service.ts +11 -1
  92. package/src/services/context-compaction.service.ts +136 -86
  93. package/src/services/document-chunk.service.ts +162 -90
  94. package/src/services/execution-plan/execution-plan-approval.ts +26 -0
  95. package/src/services/execution-plan/execution-plan-context.ts +29 -0
  96. package/src/services/execution-plan/execution-plan-graph.ts +256 -0
  97. package/src/services/execution-plan/execution-plan-schedule.ts +84 -0
  98. package/src/services/execution-plan/execution-plan-spec.ts +75 -0
  99. package/src/services/execution-plan/execution-plan.service.ts +1041 -0
  100. package/src/services/feedback-loop.service.ts +132 -76
  101. package/src/services/global-orchestrator.service.ts +80 -170
  102. package/src/services/graph-full-routing.ts +182 -0
  103. package/src/services/index.ts +18 -20
  104. package/src/services/institutional-memory.service.ts +220 -123
  105. package/src/services/learned-skill.service.ts +364 -259
  106. package/src/services/memory/memory-conversation.ts +95 -0
  107. package/src/services/memory/memory-org-memory.ts +39 -0
  108. package/src/services/memory/memory-preseeded.ts +80 -0
  109. package/src/services/memory/memory-rerank.ts +297 -0
  110. package/src/services/{memory-utils.ts → memory/memory-utils.ts} +5 -5
  111. package/src/services/memory/memory.service.ts +692 -0
  112. package/src/services/memory/rerank.service.ts +209 -0
  113. package/src/services/monitoring-window.service.ts +92 -70
  114. package/src/services/mutating-approval.service.ts +62 -53
  115. package/src/services/node-workspace.service.ts +141 -98
  116. package/src/services/notification.service.ts +17 -16
  117. package/src/services/organization-member.service.ts +120 -66
  118. package/src/services/organization.service.ts +144 -51
  119. package/src/services/ownership-dispatcher.service.ts +415 -264
  120. package/src/services/plan/plan-agent-heartbeat.service.ts +234 -0
  121. package/src/services/plan/plan-agent-query.service.ts +322 -0
  122. package/src/services/plan/plan-approval.service.ts +102 -0
  123. package/src/services/plan/plan-artifact.service.ts +60 -0
  124. package/src/services/plan/plan-builder.service.ts +76 -0
  125. package/src/services/plan/plan-checkpoint.service.ts +103 -0
  126. package/src/services/{plan-compiler.service.ts → plan/plan-compiler.service.ts} +26 -9
  127. package/src/services/plan/plan-completion-side-effects.ts +175 -0
  128. package/src/services/plan/plan-coordination.service.ts +181 -0
  129. package/src/services/plan/plan-cycle.service.ts +398 -0
  130. package/src/services/plan/plan-deadline.service.ts +547 -0
  131. package/src/services/plan/plan-event-delivery.service.ts +261 -0
  132. package/src/services/plan/plan-executor-context.ts +35 -0
  133. package/src/services/plan/plan-executor-graph.ts +475 -0
  134. package/src/services/plan/plan-executor-helpers.ts +322 -0
  135. package/src/services/plan/plan-executor-persistence.ts +209 -0
  136. package/src/services/plan/plan-executor.service.ts +1654 -0
  137. package/src/services/{plan-helpers.ts → plan/plan-helpers.ts} +1 -1
  138. package/src/services/{plan-run-data.ts → plan/plan-run-data.ts} +4 -4
  139. package/src/services/plan/plan-run-serialization.ts +15 -0
  140. package/src/services/plan/plan-run.service.ts +644 -0
  141. package/src/services/plan/plan-scheduler.service.ts +385 -0
  142. package/src/services/plan/plan-template.service.ts +224 -0
  143. package/src/services/plan/plan-transaction-events.ts +33 -0
  144. package/src/services/plan/plan-validator.service.ts +907 -0
  145. package/src/services/plan/plan-workspace.service.ts +125 -0
  146. package/src/services/plugin-executor.service.ts +97 -68
  147. package/src/services/quality-metrics.service.ts +112 -94
  148. package/src/services/queue-job.service.ts +296 -230
  149. package/src/services/recent-activity-title.service.ts +65 -36
  150. package/src/services/recent-activity.service.ts +274 -259
  151. package/src/services/skill-resolver.service.ts +38 -12
  152. package/src/services/social-chat-history.service.ts +176 -125
  153. package/src/services/system-executor.service.ts +91 -61
  154. package/src/services/thread/thread-active-run.ts +203 -0
  155. package/src/services/thread/thread-bootstrap.ts +369 -0
  156. package/src/services/thread/thread-listing.ts +198 -0
  157. package/src/services/thread/thread-memory-block.ts +117 -0
  158. package/src/services/thread/thread-message.service.ts +363 -0
  159. package/src/services/thread/thread-record-store.ts +155 -0
  160. package/src/services/thread/thread-title.service.ts +74 -0
  161. package/src/services/thread/thread-turn-execution.ts +280 -0
  162. package/src/services/thread/thread-turn-message-context.ts +73 -0
  163. package/src/services/thread/thread-turn-preparation.service.ts +1146 -0
  164. package/src/services/thread/thread-turn-streaming.ts +402 -0
  165. package/src/services/thread/thread-turn-tracing.ts +35 -0
  166. package/src/services/thread/thread-turn.ts +343 -0
  167. package/src/services/thread/thread.service.ts +335 -0
  168. package/src/services/user.service.ts +82 -32
  169. package/src/services/write-intent-validator.service.ts +63 -51
  170. package/src/storage/attachment-parser.ts +69 -27
  171. package/src/storage/attachment-storage.service.ts +331 -275
  172. package/src/storage/generated-document-storage.service.ts +66 -34
  173. package/src/system-agents/agent-result.ts +3 -1
  174. package/src/system-agents/context-compaction.agent.ts +2 -2
  175. package/src/system-agents/delegated-agent-factory.ts +159 -90
  176. package/src/system-agents/memory-reranker.agent.ts +2 -2
  177. package/src/system-agents/memory.agent.ts +2 -2
  178. package/src/system-agents/recent-activity-title-refiner.agent.ts +2 -2
  179. package/src/system-agents/regular-chat-memory-digest.agent.ts +2 -2
  180. package/src/system-agents/skill-extractor.agent.ts +2 -2
  181. package/src/system-agents/skill-manager.agent.ts +2 -2
  182. package/src/system-agents/thread-router.agent.ts +157 -113
  183. package/src/system-agents/title-generator.agent.ts +2 -2
  184. package/src/tools/execution-plan.tool.ts +220 -161
  185. package/src/tools/fetch-webpage.tool.ts +21 -17
  186. package/src/tools/firecrawl-client.ts +16 -6
  187. package/src/tools/index.ts +1 -0
  188. package/src/tools/memory-block.tool.ts +14 -6
  189. package/src/tools/plan-approval.tool.ts +49 -47
  190. package/src/tools/read-file-parts.tool.ts +44 -33
  191. package/src/tools/remember-memory.tool.ts +65 -45
  192. package/src/tools/search-web.tool.ts +26 -22
  193. package/src/tools/search.tool.ts +41 -29
  194. package/src/tools/team-think.tool.ts +124 -83
  195. package/src/tools/user-questions.tool.ts +4 -3
  196. package/src/tools/web-tool-shared.ts +6 -0
  197. package/src/utils/async.ts +17 -23
  198. package/src/utils/crypto.ts +21 -0
  199. package/src/utils/date-time.ts +40 -1
  200. package/src/utils/errors.ts +95 -16
  201. package/src/utils/hono-error-handler.ts +24 -39
  202. package/src/utils/index.ts +2 -1
  203. package/src/utils/null-proto-record.ts +41 -0
  204. package/src/utils/sse-keepalive.ts +124 -21
  205. package/src/workers/bootstrap.ts +186 -51
  206. package/src/workers/memory-consolidation.worker.ts +325 -237
  207. package/src/workers/organization-learning.worker.ts +50 -16
  208. package/src/workers/regular-chat-memory-digest.helpers.ts +28 -27
  209. package/src/workers/regular-chat-memory-digest.runner.ts +175 -114
  210. package/src/workers/skill-extraction.runner.ts +176 -93
  211. package/src/workers/utils/file-section-chunker.ts +8 -10
  212. package/src/workers/utils/repo-structure-extractor.ts +349 -260
  213. package/src/workers/utils/repomix-file-sections.ts +2 -2
  214. package/src/workers/utils/thread-message-query.ts +97 -38
  215. package/src/workers/worker-utils.ts +56 -31
  216. package/src/config/debug-logger.ts +0 -47
  217. package/src/redis/connection-accessor.ts +0 -26
  218. package/src/runtime/context-compaction-runtime.ts +0 -87
  219. package/src/runtime/social-chat-agent-runner.ts +0 -118
  220. package/src/runtime/social-chat.ts +0 -516
  221. package/src/runtime/team-consultation-orchestrator.ts +0 -272
  222. package/src/services/adaptive-playbook.service.ts +0 -152
  223. package/src/services/artifact-provenance.service.ts +0 -172
  224. package/src/services/chat-attachments.service.ts +0 -17
  225. package/src/services/context-compaction-runtime.singleton.ts +0 -13
  226. package/src/services/execution-plan.service.ts +0 -1118
  227. package/src/services/memory.service.ts +0 -844
  228. package/src/services/plan-agent-heartbeat.service.ts +0 -136
  229. package/src/services/plan-agent-query.service.ts +0 -267
  230. package/src/services/plan-approval.service.ts +0 -83
  231. package/src/services/plan-artifact.service.ts +0 -50
  232. package/src/services/plan-builder.service.ts +0 -67
  233. package/src/services/plan-checkpoint.service.ts +0 -81
  234. package/src/services/plan-completion-side-effects.ts +0 -80
  235. package/src/services/plan-coordination.service.ts +0 -157
  236. package/src/services/plan-cycle.service.ts +0 -284
  237. package/src/services/plan-deadline.service.ts +0 -430
  238. package/src/services/plan-event-delivery.service.ts +0 -166
  239. package/src/services/plan-executor.service.ts +0 -1950
  240. package/src/services/plan-run.service.ts +0 -515
  241. package/src/services/plan-scheduler.service.ts +0 -240
  242. package/src/services/plan-template.service.ts +0 -177
  243. package/src/services/plan-validator.service.ts +0 -818
  244. package/src/services/plan-workspace.service.ts +0 -83
  245. package/src/services/thread-message.service.ts +0 -275
  246. package/src/services/thread-plan-registry.service.ts +0 -22
  247. package/src/services/thread-title.service.ts +0 -39
  248. package/src/services/thread-turn-preparation.service.ts +0 -1147
  249. package/src/services/thread-turn.ts +0 -172
  250. package/src/services/thread.service.ts +0 -869
  251. package/src/utils/env.ts +0 -8
  252. /package/src/runtime/{context-compaction-constants.ts → context-compaction/context-compaction-constants.ts} +0 -0
  253. /package/src/runtime/{memory-format.ts → memory/memory-format.ts} +0 -0
  254. /package/src/runtime/{memory-prompts-parse.ts → memory/memory-prompts-parse.ts} +0 -0
  255. /package/src/runtime/{memory-prompts-update.ts → memory/memory-prompts-update.ts} +0 -0
  256. /package/src/runtime/{social-chat-prompts.ts → social-chat/social-chat-prompts.ts} +0 -0
  257. /package/src/services/{plan-node-spec.ts → plan/plan-node-spec.ts} +0 -0
  258. /package/src/services/{thread-constants.ts → thread/thread-constants.ts} +0 -0
  259. /package/src/services/{thread.types.ts → thread/thread.types.ts} +0 -0
@@ -1,27 +1,294 @@
1
- import type { LogLevel } from '@logtape/logtape'
2
- import { configure, getAnsiColorFormatter, getConsoleSink, getLogger as getLogTapeLogger } from '@logtape/logtape'
1
+ import { Effect, Logger, References } from 'effect'
3
2
 
4
3
  const LOG_CATEGORY = 'lota-sdk'
5
4
 
6
- export async function configureLotaLogger(logLevel: LogLevel = 'info'): Promise<void> {
7
- const formatter = getAnsiColorFormatter({ level: 'FULL' })
5
+ export type LotaLogLevel = 'trace' | 'debug' | 'info' | 'warning' | 'error' | 'fatal'
8
6
 
9
- await configure({
10
- reset: true,
11
- sinks: { console: getConsoleSink({ formatter }) },
12
- loggers: [
13
- { category: ['logtape', 'meta'], lowestLevel: 'warning', sinks: ['console'] },
14
- { category: ['server'], lowestLevel: logLevel, sinks: ['console'] },
15
- { category: [LOG_CATEGORY], lowestLevel: logLevel, sinks: ['console'] },
16
- { category: ['hono'], lowestLevel: logLevel, sinks: ['console'] },
17
- ],
18
- })
7
+ type LogFields = Record<string, unknown>
8
+ type LotaLogEffect = Effect.Effect<void, never, never>
9
+ type EffectLogLevel = 'Trace' | 'Debug' | 'Info' | 'Warn' | 'Error' | 'Fatal'
10
+
11
+ export interface LotaLoggerMethod {
12
+ (message: string, fields?: LogFields): void
13
+ (strings: TemplateStringsArray, ...values: Array<unknown>): void
14
+ }
15
+
16
+ export interface LotaLogger {
17
+ trace: LotaLoggerMethod
18
+ debug: LotaLoggerMethod
19
+ info: LotaLoggerMethod
20
+ warn: LotaLoggerMethod
21
+ error: LotaLoggerMethod
22
+ fatal: LotaLoggerMethod
23
+ }
24
+
25
+ const LOG_LEVEL_PRIORITY: Record<LotaLogLevel, number> = { trace: 0, debug: 1, info: 2, warning: 3, error: 4, fatal: 5 }
26
+
27
+ export function resolveLotaLogLevel(value: string | null | undefined): LotaLogLevel | null {
28
+ const normalized = value?.trim().toLowerCase()
29
+ switch (normalized) {
30
+ case 'trace':
31
+ case 'debug':
32
+ case 'info':
33
+ case 'warning':
34
+ case 'error':
35
+ case 'fatal':
36
+ return normalized
37
+ default:
38
+ return null
39
+ }
40
+ }
41
+
42
+ function readEnvLogLevel(): LotaLogLevel | null {
43
+ const value = Bun.env.LOG_LEVEL?.trim().toLowerCase()
44
+ return resolveLotaLogLevel(value)
45
+ }
46
+
47
+ let configuredLogLevel: LotaLogLevel = readEnvLogLevel() ?? 'info'
48
+
49
+ export function configureLotaLogger(logLevel: LotaLogLevel = 'info'): void {
50
+ configuredLogLevel = logLevel
51
+ }
52
+
53
+ export function getConfiguredLogLevel(): LotaLogLevel {
54
+ return configuredLogLevel
55
+ }
56
+
57
+ export function toEffectLogLevel(logLevel: LotaLogLevel): EffectLogLevel {
58
+ switch (logLevel) {
59
+ case 'trace':
60
+ return 'Trace'
61
+ case 'debug':
62
+ return 'Debug'
63
+ case 'info':
64
+ return 'Info'
65
+ case 'warning':
66
+ return 'Warn'
67
+ case 'error':
68
+ return 'Error'
69
+ case 'fatal':
70
+ return 'Fatal'
71
+ }
72
+ }
73
+
74
+ function shouldLog(level: LotaLogLevel): boolean {
75
+ return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[configuredLogLevel]
19
76
  }
20
77
 
21
- export function getLogger(category: readonly string[]) {
22
- return getLogTapeLogger([...category])
78
+ function isTemplateStringsArray(value: unknown): value is TemplateStringsArray {
79
+ return Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, 'raw')
23
80
  }
24
81
 
25
- export const serverLogger = getLogger([LOG_CATEGORY])
26
- export const chatLogger = getLogger([LOG_CATEGORY, 'chat'])
27
- export const aiLogger = getLogger([LOG_CATEGORY, 'ai'])
82
+ function describeObject(value: object): string {
83
+ return Object.prototype.toString.call(value)
84
+ }
85
+
86
+ function describeScalar(value: unknown): string {
87
+ if (value === null) return 'null'
88
+ if (value === undefined) return 'undefined'
89
+ if (typeof value === 'symbol') {
90
+ return value.description ? `Symbol(${value.description})` : 'Symbol'
91
+ }
92
+ if (typeof value === 'function') {
93
+ return `[Function ${value.name || 'anonymous'}]`
94
+ }
95
+
96
+ return JSON.stringify(value)
97
+ }
98
+
99
+ function normalizeJsonValue(value: unknown): unknown {
100
+ if (typeof value === 'bigint') return value.toString()
101
+ if (value instanceof Date) return value.toISOString()
102
+ if (value instanceof Error) {
103
+ return { name: value.name, message: value.message, stack: value.stack }
104
+ }
105
+ return value
106
+ }
107
+
108
+ function normalizeAnnotationValue(value: unknown): unknown {
109
+ if (value === null || value === undefined) return value
110
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value
111
+ if (typeof value === 'bigint') return value.toString()
112
+ if (value instanceof Date) return value.toISOString()
113
+ if (value instanceof Error) {
114
+ return { name: value.name, message: value.message, stack: value.stack }
115
+ }
116
+
117
+ try {
118
+ return JSON.parse(JSON.stringify(value, (_key, nestedValue) => normalizeJsonValue(nestedValue)))
119
+ } catch {
120
+ return typeof value === 'object' ? describeObject(value) : describeScalar(value)
121
+ }
122
+ }
123
+
124
+ function formatLogValue(value: unknown): string {
125
+ if (value instanceof Error) {
126
+ return `${value.name}: ${value.message}`
127
+ }
128
+ if (typeof value === 'string') return value
129
+ if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value)
130
+ if (value === null) return 'null'
131
+ if (value === undefined) return 'undefined'
132
+ if (value instanceof Date) return value.toISOString()
133
+
134
+ try {
135
+ return JSON.stringify(normalizeAnnotationValue(value))
136
+ } catch {
137
+ return typeof value === 'object' ? describeObject(value) : describeScalar(value)
138
+ }
139
+ }
140
+
141
+ function formatTemplate(strings: TemplateStringsArray, values: Array<unknown>): string {
142
+ let output = ''
143
+
144
+ for (let index = 0; index < strings.length; index++) {
145
+ output += strings[index]
146
+ if (index < values.length) {
147
+ output += formatLogValue(values[index])
148
+ }
149
+ }
150
+
151
+ return output
152
+ }
153
+
154
+ function applyFieldPlaceholders(message: string, fields?: LogFields): string {
155
+ if (!fields) return message
156
+
157
+ let output = message
158
+ for (const [key, value] of Object.entries(fields)) {
159
+ output = output.replaceAll(`{${key}}`, formatLogValue(value))
160
+ }
161
+ return output
162
+ }
163
+
164
+ function buildLogContext(fields?: LogFields): Record<string, unknown> {
165
+ const context: Record<string, unknown> = {}
166
+ if (!fields) {
167
+ return context
168
+ }
169
+
170
+ for (const [key, value] of Object.entries(fields)) {
171
+ if (value === undefined) continue
172
+ context[key] = normalizeAnnotationValue(value)
173
+ }
174
+
175
+ return context
176
+ }
177
+
178
+ function getConsoleMethod(level: LotaLogLevel): (...args: Array<unknown>) => void {
179
+ switch (level) {
180
+ case 'trace':
181
+ return console.trace
182
+ case 'debug':
183
+ return console.debug
184
+ case 'info':
185
+ return console.info
186
+ case 'warning':
187
+ return console.warn
188
+ case 'error':
189
+ return console.error
190
+ case 'fatal':
191
+ return console.error
192
+ }
193
+ }
194
+
195
+ function getLogEffect(level: LotaLogLevel, message: string): LotaLogEffect {
196
+ switch (level) {
197
+ case 'trace':
198
+ return Effect.logTrace(message)
199
+ case 'debug':
200
+ return Effect.logDebug(message)
201
+ case 'info':
202
+ return Effect.logInfo(message)
203
+ case 'warning':
204
+ return Effect.logWarning(message)
205
+ case 'error':
206
+ return Effect.logError(message)
207
+ case 'fatal':
208
+ return Effect.logFatal(message)
209
+ }
210
+ }
211
+
212
+ function runStandaloneLogEffect(effect: LotaLogEffect): void {
213
+ Effect.runSync(
214
+ effect.pipe(
215
+ Effect.provide(Logger.layer([Logger.consolePretty()])),
216
+ Effect.provideService(References.MinimumLogLevel, toEffectLogLevel(configuredLogLevel)),
217
+ ),
218
+ )
219
+ }
220
+
221
+ function emitConsoleFallback(
222
+ level: LotaLogLevel,
223
+ category: readonly string[],
224
+ message: string,
225
+ fields?: LogFields,
226
+ ): void {
227
+ if (!shouldLog(level)) return
228
+
229
+ const formattedMessage = `[${category.join(':')}] ${message}`
230
+ const context = buildLogContext(fields)
231
+ const sink = getConsoleMethod(level)
232
+ if (Object.keys(context).length === 0) {
233
+ sink(formattedMessage)
234
+ return
235
+ }
236
+
237
+ sink(formattedMessage, context)
238
+ }
239
+
240
+ function emit(level: LotaLogLevel, category: readonly string[], message: string, fields?: LogFields): void {
241
+ if (!shouldLog(level)) return
242
+
243
+ const formattedMessage = applyFieldPlaceholders(message, fields)
244
+ const annotations = { lotaLogger: category.join(':'), ...buildLogContext(fields) }
245
+ const effect = getLogEffect(level, formattedMessage).pipe(Effect.annotateLogs(annotations))
246
+
247
+ try {
248
+ runStandaloneLogEffect(effect)
249
+ } catch {
250
+ emitConsoleFallback(level, category, formattedMessage, annotations)
251
+ }
252
+ }
253
+
254
+ function createLoggerMethod(level: LotaLogLevel, category: readonly string[]): LotaLoggerMethod {
255
+ return (messageOrStrings: string | TemplateStringsArray, ...values: Array<unknown>) => {
256
+ if (isTemplateStringsArray(messageOrStrings)) {
257
+ emit(level, category, formatTemplate(messageOrStrings, values))
258
+ return
259
+ }
260
+
261
+ const [candidateFields] = values
262
+ const fields =
263
+ candidateFields && typeof candidateFields === 'object' && !Array.isArray(candidateFields)
264
+ ? (candidateFields as LogFields)
265
+ : undefined
266
+
267
+ emit(level, category, messageOrStrings, fields)
268
+ }
269
+ }
270
+
271
+ export function getLogger(category: readonly string[]): LotaLogger {
272
+ return {
273
+ trace: createLoggerMethod('trace', category),
274
+ debug: createLoggerMethod('debug', category),
275
+ info: createLoggerMethod('info', category),
276
+ warn: createLoggerMethod('warning', category),
277
+ error: createLoggerMethod('error', category),
278
+ fatal: createLoggerMethod('fatal', category),
279
+ }
280
+ }
281
+
282
+ export const serverLogger: LotaLogger = getLogger([LOG_CATEGORY])
283
+ export const chatLogger: LotaLogger = getLogger([LOG_CATEGORY, 'chat'])
284
+ export const aiLogger: LotaLogger = getLogger([LOG_CATEGORY, 'ai'])
285
+
286
+ export interface LotaLoggerSet {
287
+ server: LotaLogger
288
+ chat: LotaLogger
289
+ ai: LotaLogger
290
+ }
291
+
292
+ export function getLotaLoggers(): LotaLoggerSet {
293
+ return { server: serverLogger, chat: chatLogger, ai: aiLogger }
294
+ }
@@ -2,6 +2,7 @@ export {
2
2
  AI_GATEWAY_REASONING_SUMMARY_LEVEL,
3
3
  OPENAI_HIGH_REASONING_PROVIDER_OPTIONS,
4
4
  OPENAI_REASONING_MODEL_ID,
5
+ OPENROUTER_FAST_RERANK_MODEL_ID,
5
6
  OPENROUTER_FAST_REASONING_MODEL_ID,
6
7
  OPENROUTER_GEMINI_FLASH_MODEL_ID,
7
8
  OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
@@ -1,3 +1,8 @@
1
+ import { Effect } from 'effect'
2
+
3
+ import { getCurrentRuntime } from '../effect/runtime-ref'
4
+ import { ThreadConfigServiceTag } from '../effect/services'
5
+
1
6
  export interface ThreadBootstrapWelcomeConfig {
2
7
  defaultAgentId: string
3
8
  buildMessageText: (params: { userName?: string | null }) => string
@@ -23,16 +28,9 @@ interface ResolvedThreadBootstrapConfig {
23
28
  onboardingWelcome?: ThreadBootstrapWelcomeConfig
24
29
  }
25
30
 
26
- const DEFAULT_THREAD_BOOTSTRAP_CONFIG: ResolvedThreadBootstrapConfig = {
27
- onboardingDefaultAgents: [],
28
- completedDefaultAgents: [],
29
- threadTypesAfterOnboarding: [],
30
- ensureDefaultGroupOnCompleted: true,
31
- }
32
-
33
- let resolvedThreadBootstrapConfig: ResolvedThreadBootstrapConfig = DEFAULT_THREAD_BOOTSTRAP_CONFIG
31
+ export type { ResolvedThreadBootstrapConfig }
34
32
 
35
- function withDedupedStrings(values: readonly string[]): string[] {
33
+ function normalizeThreadAgentIds(values: readonly string[]): readonly string[] {
36
34
  const seen = new Set<string>()
37
35
  const deduped: string[] = []
38
36
 
@@ -46,27 +44,41 @@ function withDedupedStrings(values: readonly string[]): string[] {
46
44
  return deduped
47
45
  }
48
46
 
49
- export function configureThreads(params: { agentRoster: readonly string[]; config?: LotaThreadConfig }): void {
47
+ function resolveBootstrapAgentIds(
48
+ agentRoster: readonly string[],
49
+ onboardingAgents: readonly string[] | undefined,
50
+ welcomeAgentId: string | undefined,
51
+ ): readonly string[] {
52
+ return normalizeThreadAgentIds([...(onboardingAgents ?? agentRoster), ...(welcomeAgentId ? [welcomeAgentId] : [])])
53
+ }
54
+
55
+ export function resolveThreadConfig(params: {
56
+ agentRoster: readonly string[]
57
+ config?: LotaThreadConfig
58
+ }): ResolvedThreadBootstrapConfig {
50
59
  const bootstrap = params.config?.bootstrap
51
60
  const onboardingWelcome = bootstrap?.onboardingWelcome
52
- const onboardingDefaultAgents = withDedupedStrings([
53
- ...(bootstrap?.onboardingDefaultAgents ?? params.agentRoster),
54
- ...(onboardingWelcome ? [onboardingWelcome.defaultAgentId] : []),
55
- ])
56
61
 
57
- resolvedThreadBootstrapConfig = {
58
- onboardingDefaultAgents,
59
- completedDefaultAgents: withDedupedStrings(bootstrap?.completedDefaultAgents ?? params.agentRoster),
60
- threadTypesAfterOnboarding: withDedupedStrings(bootstrap?.threadTypesAfterOnboarding ?? []),
62
+ return {
63
+ onboardingDefaultAgents: resolveBootstrapAgentIds(
64
+ params.agentRoster,
65
+ bootstrap?.onboardingDefaultAgents,
66
+ onboardingWelcome?.defaultAgentId,
67
+ ),
68
+ completedDefaultAgents: normalizeThreadAgentIds(bootstrap?.completedDefaultAgents ?? params.agentRoster),
69
+ threadTypesAfterOnboarding: normalizeThreadAgentIds(bootstrap?.threadTypesAfterOnboarding ?? []),
61
70
  ensureDefaultGroupOnCompleted: bootstrap?.ensureDefaultGroupOnCompleted ?? true,
62
71
  ...(onboardingWelcome ? { onboardingWelcome } : {}),
63
72
  }
64
73
  }
65
74
 
66
75
  export function getThreadBootstrapConfig(): ResolvedThreadBootstrapConfig {
67
- return resolvedThreadBootstrapConfig
76
+ return getCurrentRuntime().runSync(Effect.service(ThreadConfigServiceTag))
68
77
  }
69
78
 
70
- export function resolveOnboardingOwnerAgentId(defaultLeadAgentId: string): string {
71
- return resolvedThreadBootstrapConfig.onboardingWelcome?.defaultAgentId ?? defaultLeadAgentId
79
+ export function resolveOnboardingOwnerAgentId(
80
+ defaultLeadAgentId: string,
81
+ config: ResolvedThreadBootstrapConfig = getThreadBootstrapConfig(),
82
+ ): string {
83
+ return config.onboardingWelcome?.defaultAgentId ?? defaultLeadAgentId
72
84
  }