@lota-sdk/core 0.4.8 → 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.
- package/package.json +11 -12
- package/src/ai/embedding-cache.ts +94 -22
- package/src/ai-gateway/ai-gateway.ts +738 -223
- package/src/config/agent-defaults.ts +176 -75
- package/src/config/agent-types.ts +54 -4
- package/src/config/constants.ts +8 -2
- package/src/config/logger.ts +286 -19
- package/src/config/thread-defaults.ts +33 -21
- package/src/create-runtime.ts +725 -387
- package/src/db/base.service.ts +52 -28
- package/src/db/cursor-pagination.ts +71 -30
- package/src/db/memory-store.helpers.ts +4 -7
- package/src/db/memory-store.ts +856 -598
- package/src/db/memory.ts +398 -275
- package/src/db/record-id.ts +32 -10
- package/src/db/schema-fingerprint.ts +30 -12
- package/src/db/service-normalization.ts +255 -0
- package/src/db/service.ts +726 -761
- package/src/db/startup.ts +140 -66
- package/src/db/transaction-conflict.ts +15 -0
- package/src/effect/awaitable-effect.ts +87 -0
- package/src/effect/errors.ts +121 -0
- package/src/effect/helpers.ts +98 -0
- package/src/effect/index.ts +22 -0
- package/src/effect/layers.ts +228 -0
- package/src/effect/runtime-ref.ts +25 -0
- package/src/effect/runtime.ts +31 -0
- package/src/effect/services.ts +57 -0
- package/src/effect/zod.ts +43 -0
- package/src/embeddings/provider.ts +122 -76
- package/src/index.ts +46 -1
- package/src/openrouter/direct-provider.ts +11 -35
- package/src/queues/autonomous-job.queue.ts +130 -74
- package/src/queues/context-compaction.queue.ts +60 -15
- package/src/queues/delayed-node-promotion.queue.ts +52 -15
- package/src/queues/document-processor.queue.ts +52 -77
- package/src/queues/memory-consolidation.queue.ts +47 -32
- package/src/queues/organization-learning.queue.ts +13 -4
- package/src/queues/plan-agent-heartbeat.queue.ts +65 -21
- package/src/queues/plan-scheduler.queue.ts +107 -31
- package/src/queues/post-chat-memory.queue.ts +66 -24
- package/src/queues/queue-factory.ts +142 -52
- package/src/queues/standalone-worker.ts +39 -0
- package/src/queues/title-generation.queue.ts +54 -9
- package/src/redis/connection.ts +84 -32
- package/src/redis/index.ts +6 -8
- package/src/redis/org-memory-lock.ts +60 -27
- package/src/redis/redis-lease-lock.ts +200 -121
- package/src/redis/runtime-connection.ts +10 -0
- package/src/redis/stream-context.ts +84 -46
- package/src/runtime/agent-identity-overrides.ts +2 -2
- package/src/runtime/agent-runtime-policy.ts +4 -1
- package/src/runtime/agent-stream-helpers.ts +20 -9
- package/src/runtime/chat-run-orchestration.ts +102 -19
- package/src/runtime/chat-run-registry.ts +36 -2
- package/src/runtime/context-compaction/context-compaction-runtime.ts +107 -0
- package/src/runtime/{context-compaction.ts → context-compaction/context-compaction.ts} +114 -91
- package/src/runtime/execution-plan-visibility.ts +2 -2
- package/src/runtime/execution-plan.ts +42 -15
- package/src/runtime/graph-designer.ts +11 -7
- package/src/runtime/helper-model.ts +135 -48
- package/src/runtime/index.ts +7 -7
- package/src/runtime/indexed-repositories-policy.ts +3 -3
- package/src/runtime/{memory-block.ts → memory/memory-block.ts} +40 -36
- package/src/runtime/{memory-digest-policy.ts → memory/memory-digest-policy.ts} +1 -1
- package/src/runtime/{memory-pipeline.ts → memory/memory-pipeline.ts} +1 -1
- package/src/runtime/{memory-prompts-fact.ts → memory/memory-prompts-fact.ts} +2 -2
- package/src/runtime/{memory-scope.ts → memory/memory-scope.ts} +12 -6
- package/src/runtime/plugin-resolution.ts +144 -24
- package/src/runtime/plugin-types.ts +9 -1
- package/src/runtime/post-turn-side-effects.ts +197 -130
- package/src/runtime/retrieval-adapters.ts +38 -4
- package/src/runtime/runtime-config.ts +150 -61
- package/src/runtime/runtime-extensions.ts +21 -34
- package/src/runtime/social-chat/social-chat-agent-runner.ts +157 -0
- package/src/runtime/{social-chat-history.ts → social-chat/social-chat-history.ts} +42 -20
- package/src/runtime/social-chat/social-chat.ts +594 -0
- package/src/runtime/specialist-runner.ts +36 -10
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +427 -0
- package/src/runtime/{team-consultation-prompts.ts → team-consultation/team-consultation-prompts.ts} +6 -2
- package/src/runtime/thread-chat-helpers.ts +2 -2
- package/src/runtime/thread-plan-turn.ts +2 -1
- package/src/runtime/thread-turn-context.ts +172 -94
- package/src/runtime/turn-lifecycle.ts +93 -27
- package/src/services/agent-activity.service.ts +287 -203
- package/src/services/agent-executor.service.ts +329 -217
- package/src/services/artifact.service.ts +225 -148
- package/src/services/attachment.service.ts +137 -115
- package/src/services/autonomous-job.service.ts +888 -491
- package/src/services/chat-run-registry.service.ts +11 -1
- package/src/services/context-compaction.service.ts +136 -86
- package/src/services/document-chunk.service.ts +162 -90
- package/src/services/execution-plan/execution-plan-approval.ts +26 -0
- package/src/services/execution-plan/execution-plan-context.ts +29 -0
- package/src/services/execution-plan/execution-plan-graph.ts +256 -0
- package/src/services/execution-plan/execution-plan-schedule.ts +84 -0
- package/src/services/execution-plan/execution-plan-spec.ts +75 -0
- package/src/services/execution-plan/execution-plan.service.ts +1041 -0
- package/src/services/feedback-loop.service.ts +132 -76
- package/src/services/global-orchestrator.service.ts +80 -170
- package/src/services/graph-full-routing.ts +182 -0
- package/src/services/index.ts +18 -21
- package/src/services/institutional-memory.service.ts +220 -123
- package/src/services/learned-skill.service.ts +364 -259
- package/src/services/memory/memory-conversation.ts +95 -0
- package/src/services/memory/memory-org-memory.ts +39 -0
- package/src/services/memory/memory-preseeded.ts +80 -0
- package/src/services/memory/memory-rerank.ts +297 -0
- package/src/services/{memory-utils.ts → memory/memory-utils.ts} +5 -5
- package/src/services/memory/memory.service.ts +692 -0
- package/src/services/memory/rerank.service.ts +209 -0
- package/src/services/monitoring-window.service.ts +92 -70
- package/src/services/mutating-approval.service.ts +62 -53
- package/src/services/node-workspace.service.ts +141 -98
- package/src/services/notification.service.ts +17 -16
- package/src/services/organization-member.service.ts +120 -66
- package/src/services/organization.service.ts +144 -51
- package/src/services/ownership-dispatcher.service.ts +415 -264
- package/src/services/plan/plan-agent-heartbeat.service.ts +234 -0
- package/src/services/plan/plan-agent-query.service.ts +322 -0
- package/src/services/plan/plan-approval.service.ts +102 -0
- package/src/services/plan/plan-artifact.service.ts +60 -0
- package/src/services/plan/plan-builder.service.ts +76 -0
- package/src/services/plan/plan-checkpoint.service.ts +103 -0
- package/src/services/{plan-compiler.service.ts → plan/plan-compiler.service.ts} +26 -9
- package/src/services/plan/plan-completion-side-effects.ts +175 -0
- package/src/services/plan/plan-coordination.service.ts +181 -0
- package/src/services/plan/plan-cycle.service.ts +398 -0
- package/src/services/plan/plan-deadline.service.ts +547 -0
- package/src/services/plan/plan-event-delivery.service.ts +261 -0
- package/src/services/plan/plan-executor-context.ts +35 -0
- package/src/services/plan/plan-executor-graph.ts +475 -0
- package/src/services/plan/plan-executor-helpers.ts +322 -0
- package/src/services/plan/plan-executor-persistence.ts +209 -0
- package/src/services/plan/plan-executor.service.ts +1654 -0
- package/src/services/{plan-helpers.ts → plan/plan-helpers.ts} +1 -1
- package/src/services/{plan-run-data.ts → plan/plan-run-data.ts} +4 -4
- package/src/services/plan/plan-run-serialization.ts +15 -0
- package/src/services/plan/plan-run.service.ts +644 -0
- package/src/services/plan/plan-scheduler.service.ts +385 -0
- package/src/services/plan/plan-template.service.ts +224 -0
- package/src/services/plan/plan-transaction-events.ts +33 -0
- package/src/services/plan/plan-validator.service.ts +907 -0
- package/src/services/plan/plan-workspace.service.ts +125 -0
- package/src/services/plugin-executor.service.ts +97 -68
- package/src/services/quality-metrics.service.ts +112 -94
- package/src/services/queue-job.service.ts +296 -230
- package/src/services/recent-activity-title.service.ts +65 -36
- package/src/services/recent-activity.service.ts +274 -259
- package/src/services/skill-resolver.service.ts +38 -12
- package/src/services/social-chat-history.service.ts +176 -125
- package/src/services/system-executor.service.ts +91 -61
- package/src/services/thread/thread-active-run.ts +203 -0
- package/src/services/thread/thread-bootstrap.ts +369 -0
- package/src/services/thread/thread-listing.ts +198 -0
- package/src/services/thread/thread-memory-block.ts +117 -0
- package/src/services/thread/thread-message.service.ts +363 -0
- package/src/services/thread/thread-record-store.ts +155 -0
- package/src/services/thread/thread-title.service.ts +74 -0
- package/src/services/thread/thread-turn-execution.ts +280 -0
- package/src/services/thread/thread-turn-message-context.ts +73 -0
- package/src/services/thread/thread-turn-preparation.service.ts +1146 -0
- package/src/services/thread/thread-turn-streaming.ts +402 -0
- package/src/services/thread/thread-turn-tracing.ts +35 -0
- package/src/services/thread/thread-turn.ts +343 -0
- package/src/services/thread/thread.service.ts +335 -0
- package/src/services/user.service.ts +82 -32
- package/src/services/write-intent-validator.service.ts +63 -51
- package/src/storage/attachment-parser.ts +69 -27
- package/src/storage/attachment-storage.service.ts +331 -275
- package/src/storage/generated-document-storage.service.ts +66 -34
- package/src/system-agents/agent-result.ts +3 -1
- package/src/system-agents/context-compaction.agent.ts +2 -2
- package/src/system-agents/delegated-agent-factory.ts +159 -90
- package/src/system-agents/memory-reranker.agent.ts +2 -2
- package/src/system-agents/memory.agent.ts +2 -2
- package/src/system-agents/recent-activity-title-refiner.agent.ts +2 -2
- package/src/system-agents/regular-chat-memory-digest.agent.ts +2 -2
- package/src/system-agents/skill-extractor.agent.ts +2 -2
- package/src/system-agents/skill-manager.agent.ts +2 -2
- package/src/system-agents/thread-router.agent.ts +157 -113
- package/src/system-agents/title-generator.agent.ts +2 -2
- package/src/tools/execution-plan.tool.ts +220 -161
- package/src/tools/fetch-webpage.tool.ts +21 -17
- package/src/tools/firecrawl-client.ts +16 -6
- package/src/tools/index.ts +1 -0
- package/src/tools/memory-block.tool.ts +14 -6
- package/src/tools/plan-approval.tool.ts +49 -47
- package/src/tools/read-file-parts.tool.ts +44 -33
- package/src/tools/remember-memory.tool.ts +65 -45
- package/src/tools/search-web.tool.ts +26 -22
- package/src/tools/search.tool.ts +41 -29
- package/src/tools/team-think.tool.ts +124 -83
- package/src/tools/user-questions.tool.ts +4 -3
- package/src/tools/web-tool-shared.ts +6 -0
- package/src/utils/async.ts +17 -23
- package/src/utils/crypto.ts +21 -0
- package/src/utils/date-time.ts +40 -1
- package/src/utils/errors.ts +95 -16
- package/src/utils/hono-error-handler.ts +24 -39
- package/src/utils/index.ts +2 -1
- package/src/utils/null-proto-record.ts +41 -0
- package/src/utils/sse-keepalive.ts +124 -21
- package/src/workers/bootstrap.ts +186 -51
- package/src/workers/memory-consolidation.worker.ts +325 -237
- package/src/workers/organization-learning.worker.ts +50 -16
- package/src/workers/regular-chat-memory-digest.helpers.ts +28 -27
- package/src/workers/regular-chat-memory-digest.runner.ts +175 -114
- package/src/workers/skill-extraction.runner.ts +176 -93
- package/src/workers/utils/file-section-chunker.ts +8 -10
- package/src/workers/utils/repo-structure-extractor.ts +349 -260
- package/src/workers/utils/repomix-file-sections.ts +2 -2
- package/src/workers/utils/thread-message-query.ts +97 -38
- package/src/workers/worker-utils.ts +56 -31
- package/src/config/debug-logger.ts +0 -47
- package/src/redis/connection-accessor.ts +0 -26
- package/src/runtime/context-compaction-runtime.ts +0 -87
- package/src/runtime/social-chat-agent-runner.ts +0 -118
- package/src/runtime/social-chat.ts +0 -516
- package/src/runtime/team-consultation-orchestrator.ts +0 -272
- package/src/services/adaptive-playbook.service.ts +0 -152
- package/src/services/artifact-provenance.service.ts +0 -172
- package/src/services/chat-attachments.service.ts +0 -17
- package/src/services/context-compaction-runtime.singleton.ts +0 -13
- package/src/services/execution-plan.service.ts +0 -1118
- package/src/services/memory.service.ts +0 -914
- package/src/services/plan-agent-heartbeat.service.ts +0 -136
- package/src/services/plan-agent-query.service.ts +0 -267
- package/src/services/plan-approval.service.ts +0 -83
- package/src/services/plan-artifact.service.ts +0 -50
- package/src/services/plan-builder.service.ts +0 -67
- package/src/services/plan-checkpoint.service.ts +0 -81
- package/src/services/plan-completion-side-effects.ts +0 -80
- package/src/services/plan-coordination.service.ts +0 -157
- package/src/services/plan-cycle.service.ts +0 -284
- package/src/services/plan-deadline.service.ts +0 -430
- package/src/services/plan-event-delivery.service.ts +0 -166
- package/src/services/plan-executor.service.ts +0 -1950
- package/src/services/plan-run.service.ts +0 -515
- package/src/services/plan-scheduler.service.ts +0 -240
- package/src/services/plan-template.service.ts +0 -177
- package/src/services/plan-validator.service.ts +0 -818
- package/src/services/plan-workspace.service.ts +0 -83
- package/src/services/rerank.service.ts +0 -156
- package/src/services/thread-message.service.ts +0 -275
- package/src/services/thread-plan-registry.service.ts +0 -22
- package/src/services/thread-title.service.ts +0 -39
- package/src/services/thread-turn-preparation.service.ts +0 -1147
- package/src/services/thread-turn.ts +0 -172
- package/src/services/thread.service.ts +0 -869
- package/src/utils/env.ts +0 -8
- /package/src/runtime/{context-compaction-constants.ts → context-compaction/context-compaction-constants.ts} +0 -0
- /package/src/runtime/{memory-format.ts → memory/memory-format.ts} +0 -0
- /package/src/runtime/{memory-prompts-parse.ts → memory/memory-prompts-parse.ts} +0 -0
- /package/src/runtime/{memory-prompts-update.ts → memory/memory-prompts-update.ts} +0 -0
- /package/src/runtime/{social-chat-prompts.ts → social-chat/social-chat-prompts.ts} +0 -0
- /package/src/services/{plan-node-spec.ts → plan/plan-node-spec.ts} +0 -0
- /package/src/services/{thread-constants.ts → thread/thread-constants.ts} +0 -0
- /package/src/services/{thread.types.ts → thread/thread.types.ts} +0 -0
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { ToolSet } from 'ai'
|
|
2
|
+
import { Config, ConfigProvider, Effect, Option, Redacted } from 'effect'
|
|
2
3
|
import { z } from 'zod'
|
|
3
4
|
|
|
4
5
|
import type { CoreThreadProfile } from '../config/agent-defaults'
|
|
5
6
|
import type { AgentFactory, AgentRuntimeConfigProvider, AgentToolBuilder } from '../config/agent-types'
|
|
7
|
+
import { DEFAULT_AI_GATEWAY_URL } from '../config/constants'
|
|
6
8
|
import { OPENROUTER_FAST_RERANK_MODEL_ID } from '../config/model-constants'
|
|
7
9
|
import type { LotaThreadConfig, ThreadBootstrapWelcomeConfig } from '../config/thread-defaults'
|
|
8
10
|
import type { RecordIdRef } from '../db/record-id'
|
|
11
|
+
import { getCurrentRuntime } from '../effect/runtime-ref'
|
|
12
|
+
import { RuntimeConfigServiceTag } from '../effect/services'
|
|
9
13
|
import type { NotificationService } from '../services/notification.service'
|
|
10
14
|
import { isRecord } from '../utils/string'
|
|
11
15
|
import type { GraphDesigner } from './graph-designer'
|
|
@@ -14,6 +18,11 @@ import type { LotaRuntimeAdapters, LotaRuntimeTurnHooks } from './runtime-extens
|
|
|
14
18
|
import type { LotaRuntimeWorkerExtensions } from './runtime-worker-registry'
|
|
15
19
|
|
|
16
20
|
const logLevelValues = ['trace', 'debug', 'info', 'warning', 'error', 'fatal'] as const
|
|
21
|
+
const nonEmptyStringSchema = z.string().trim().min(1)
|
|
22
|
+
const stringRecordSchema = z.record(z.string(), z.string())
|
|
23
|
+
function objectRecordSchema<T extends object>() {
|
|
24
|
+
return z.custom<T>(isRecord)
|
|
25
|
+
}
|
|
17
26
|
|
|
18
27
|
function isStringOrUrl(value: unknown): value is string | URL {
|
|
19
28
|
return typeof value === 'string' || value instanceof URL
|
|
@@ -23,26 +32,14 @@ function isFunction(value: unknown): value is (...args: unknown[]) => unknown {
|
|
|
23
32
|
return typeof value === 'function'
|
|
24
33
|
}
|
|
25
34
|
|
|
26
|
-
function
|
|
27
|
-
return isRecord(value)
|
|
35
|
+
function isToolSet(value: unknown): value is ToolSet {
|
|
36
|
+
return isRecord(value)
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
function isAgentFactoryRegistry(value: unknown): value is AgentFactory {
|
|
31
40
|
return isRecord(value) && Object.values(value).every((entry) => typeof entry === 'function')
|
|
32
41
|
}
|
|
33
42
|
|
|
34
|
-
function isPluginRuntimeRecord(value: unknown): value is Record<string, LotaPlugin> {
|
|
35
|
-
return isRecord(value)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function isSystemExecutorRecord(value: unknown): value is Record<string, SystemNodeExecutor> {
|
|
39
|
-
return isRecord(value)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function isToolProviderRecord(value: unknown): value is Record<string, unknown> {
|
|
43
|
-
return isRecord(value)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
43
|
function isNotificationService(value: unknown): value is NotificationService {
|
|
47
44
|
return isRecord(value) && isFunction(value.notify) && isFunction(value.remind) && isFunction(value.escalate)
|
|
48
45
|
}
|
|
@@ -146,7 +143,7 @@ function isSocialChatConfig(value: unknown): value is LotaRuntimeSocialChatConfi
|
|
|
146
143
|
}
|
|
147
144
|
|
|
148
145
|
const threadBootstrapWelcomeConfigSchema = z.object({
|
|
149
|
-
defaultAgentId:
|
|
146
|
+
defaultAgentId: nonEmptyStringSchema,
|
|
150
147
|
buildMessageText: z.custom<ThreadBootstrapWelcomeConfig['buildMessageText']>(isFunction, {
|
|
151
148
|
error: 'onboardingWelcome.buildMessageText must be a function',
|
|
152
149
|
}),
|
|
@@ -156,9 +153,9 @@ const threadConfigSchema = z
|
|
|
156
153
|
.object({
|
|
157
154
|
bootstrap: z
|
|
158
155
|
.object({
|
|
159
|
-
onboardingDefaultAgents: z.array(
|
|
160
|
-
completedDefaultAgents: z.array(
|
|
161
|
-
threadTypesAfterOnboarding: z.array(
|
|
156
|
+
onboardingDefaultAgents: z.array(nonEmptyStringSchema).optional(),
|
|
157
|
+
completedDefaultAgents: z.array(nonEmptyStringSchema).optional(),
|
|
158
|
+
threadTypesAfterOnboarding: z.array(nonEmptyStringSchema).optional(),
|
|
162
159
|
ensureDefaultGroupOnCompleted: z.boolean().optional(),
|
|
163
160
|
onboardingWelcome: threadBootstrapWelcomeConfigSchema.optional(),
|
|
164
161
|
})
|
|
@@ -169,19 +166,13 @@ const threadConfigSchema = z
|
|
|
169
166
|
|
|
170
167
|
const agentsConfigSchema = z
|
|
171
168
|
.object({
|
|
172
|
-
roster: z.array(
|
|
173
|
-
leadAgentId:
|
|
174
|
-
displayNames:
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
.optional(),
|
|
180
|
-
descriptions: z
|
|
181
|
-
.custom<Record<string, string>>(isStringRecord, { error: 'agents.descriptions must be a string record' })
|
|
182
|
-
.optional(),
|
|
183
|
-
routerModelId: z.string().trim().min(1).optional(),
|
|
184
|
-
teamConsultParticipants: z.array(z.string().trim().min(1)),
|
|
169
|
+
roster: z.array(nonEmptyStringSchema).min(1),
|
|
170
|
+
leadAgentId: nonEmptyStringSchema,
|
|
171
|
+
displayNames: stringRecordSchema,
|
|
172
|
+
shortDisplayNames: stringRecordSchema.optional(),
|
|
173
|
+
descriptions: stringRecordSchema.optional(),
|
|
174
|
+
routerModelId: nonEmptyStringSchema.optional(),
|
|
175
|
+
teamConsultParticipants: z.array(nonEmptyStringSchema),
|
|
185
176
|
getCoreThreadProfile: z
|
|
186
177
|
.custom<(coreType: string) => CoreThreadProfile>(isFunction, {
|
|
187
178
|
error: 'agents.getCoreThreadProfile must be a function',
|
|
@@ -222,24 +213,25 @@ export type MemoryRerankerStrategy = z.infer<typeof MemoryRerankerStrategySchema
|
|
|
222
213
|
|
|
223
214
|
export const LotaRuntimeConfigSchema = z.object({
|
|
224
215
|
database: z.object({
|
|
225
|
-
url:
|
|
226
|
-
namespace:
|
|
227
|
-
username:
|
|
228
|
-
password:
|
|
216
|
+
url: nonEmptyStringSchema,
|
|
217
|
+
namespace: nonEmptyStringSchema,
|
|
218
|
+
username: nonEmptyStringSchema,
|
|
219
|
+
password: nonEmptyStringSchema,
|
|
229
220
|
}),
|
|
230
|
-
redis: z.object({ url:
|
|
221
|
+
redis: z.object({ url: nonEmptyStringSchema }),
|
|
231
222
|
aiGateway: z.object({
|
|
232
|
-
url:
|
|
233
|
-
key:
|
|
234
|
-
embeddingModel:
|
|
235
|
-
openRouterApiKey:
|
|
223
|
+
url: nonEmptyStringSchema,
|
|
224
|
+
key: nonEmptyStringSchema,
|
|
225
|
+
embeddingModel: nonEmptyStringSchema.default('openai/text-embedding-3-small'),
|
|
226
|
+
openRouterApiKey: nonEmptyStringSchema.optional(),
|
|
227
|
+
maxConcurrency: z.coerce.number().int().positive().default(8),
|
|
236
228
|
}),
|
|
237
229
|
s3: z.object({
|
|
238
|
-
endpoint:
|
|
239
|
-
bucket:
|
|
240
|
-
region:
|
|
241
|
-
accessKeyId:
|
|
242
|
-
secretAccessKey:
|
|
230
|
+
endpoint: nonEmptyStringSchema,
|
|
231
|
+
bucket: nonEmptyStringSchema,
|
|
232
|
+
region: nonEmptyStringSchema.default('garage'),
|
|
233
|
+
accessKeyId: nonEmptyStringSchema,
|
|
234
|
+
secretAccessKey: nonEmptyStringSchema,
|
|
243
235
|
attachmentUrlExpiresIn: z.coerce.number().positive().default(1800),
|
|
244
236
|
}),
|
|
245
237
|
firecrawl: z.object({
|
|
@@ -266,16 +258,25 @@ export const LotaRuntimeConfigSchema = z.object({
|
|
|
266
258
|
}),
|
|
267
259
|
threads: threadConfigSchema.default({}),
|
|
268
260
|
agents: agentsConfigSchema,
|
|
269
|
-
toolProviders: z.custom<
|
|
261
|
+
toolProviders: z.custom<ToolSet>(isToolSet, { error: 'toolProviders must be a tool registry object' }).optional(),
|
|
270
262
|
extraSchemaFiles: z.array(z.custom<string | URL>(isStringOrUrl)).optional(),
|
|
271
263
|
extraWorkers: z.custom<LotaRuntimeWorkerExtensions>(isWorkerExtensionRecord).optional(),
|
|
272
|
-
pluginRuntime:
|
|
273
|
-
systemExecutors:
|
|
264
|
+
pluginRuntime: objectRecordSchema<Record<string, LotaPlugin>>().optional(),
|
|
265
|
+
systemExecutors: objectRecordSchema<Record<string, SystemNodeExecutor>>().optional(),
|
|
274
266
|
notificationService: z.custom<NotificationService>(isNotificationService).optional(),
|
|
275
|
-
runtimeAdapters:
|
|
276
|
-
turnHooks:
|
|
267
|
+
runtimeAdapters: objectRecordSchema<LotaRuntimeAdapters>().optional(),
|
|
268
|
+
turnHooks: objectRecordSchema<LotaRuntimeTurnHooks>().optional(),
|
|
277
269
|
graphDesigner: z.custom<GraphDesigner>(isGraphDesigner).optional(),
|
|
278
270
|
socialChat: z.custom<LotaRuntimeSocialChatConfig>(isSocialChatConfig).optional(),
|
|
271
|
+
observability: z
|
|
272
|
+
.object({
|
|
273
|
+
otlpBaseUrl: nonEmptyStringSchema.optional(),
|
|
274
|
+
otlpHeaders: stringRecordSchema.optional(),
|
|
275
|
+
serviceName: nonEmptyStringSchema.default('lota-sdk'),
|
|
276
|
+
serviceVersion: nonEmptyStringSchema.optional(),
|
|
277
|
+
devToolsUrl: nonEmptyStringSchema.optional(),
|
|
278
|
+
})
|
|
279
|
+
.default({ serviceName: 'lota-sdk' }),
|
|
279
280
|
})
|
|
280
281
|
|
|
281
282
|
export type LotaRuntimeConfig = z.input<typeof LotaRuntimeConfigSchema>
|
|
@@ -301,6 +302,7 @@ export const LOTA_RUNTIME_ENV_KEYS = Object.freeze([
|
|
|
301
302
|
'AI_GATEWAY_KEY',
|
|
302
303
|
'AI_EMBEDDING_MODEL',
|
|
303
304
|
'OPENROUTER_API_KEY',
|
|
305
|
+
'AI_GATEWAY_MAX_CONCURRENCY',
|
|
304
306
|
'S3_ENDPOINT',
|
|
305
307
|
'S3_BUCKET',
|
|
306
308
|
'S3_REGION',
|
|
@@ -313,28 +315,115 @@ export const LOTA_RUNTIME_ENV_KEYS = Object.freeze([
|
|
|
313
315
|
'MEMORY_SEARCH_K',
|
|
314
316
|
'MEMORY_RERANKER_STRATEGY',
|
|
315
317
|
'MEMORY_RERANKER_MODEL_ID',
|
|
318
|
+
'OTLP_BASE_URL',
|
|
319
|
+
'OTLP_SERVICE_NAME',
|
|
320
|
+
'OTLP_SERVICE_VERSION',
|
|
321
|
+
'DEVTOOLS_URL',
|
|
316
322
|
])
|
|
317
323
|
|
|
318
|
-
let runtimeConfig: ResolvedLotaRuntimeConfig | null = null
|
|
319
|
-
|
|
320
324
|
export function parseLotaRuntimeConfig(config: LotaRuntimeConfig): ResolvedLotaRuntimeConfig {
|
|
321
325
|
return LotaRuntimeConfigSchema.parse(config)
|
|
322
326
|
}
|
|
323
327
|
|
|
324
|
-
export function
|
|
325
|
-
|
|
328
|
+
export function parseWorkerBootstrapEnv(env: Record<string, string | undefined>): WorkerBootstrapEnv {
|
|
329
|
+
return WORKER_BOOTSTRAP_ENV_SCHEMA.parse(env)
|
|
326
330
|
}
|
|
327
331
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
+
const runtimeEnvironmentConfig = Config.all({
|
|
333
|
+
surrealdbUrl: Config.string('SURREALDB_URL'),
|
|
334
|
+
surrealdbNamespace: Config.string('SURREALDB_NAMESPACE'),
|
|
335
|
+
surrealdbUser: Config.string('SURREALDB_USER'),
|
|
336
|
+
surrealdbPassword: Config.redacted('SURREALDB_PASSWORD'),
|
|
337
|
+
redisUrl: Config.string('REDIS_URL'),
|
|
338
|
+
aiGatewayUrl: Config.string('AI_GATEWAY_URL').pipe(Config.withDefault(DEFAULT_AI_GATEWAY_URL)),
|
|
339
|
+
aiGatewayKey: Config.redacted('AI_GATEWAY_KEY'),
|
|
340
|
+
aiEmbeddingModel: Config.string('AI_EMBEDDING_MODEL').pipe(Config.withDefault('openai/text-embedding-3-small')),
|
|
341
|
+
openRouterApiKey: Config.redacted('OPENROUTER_API_KEY').pipe(Config.option),
|
|
342
|
+
aiGatewayMaxConcurrency: Config.number('AI_GATEWAY_MAX_CONCURRENCY').pipe(Config.withDefault(8)),
|
|
343
|
+
s3Endpoint: Config.string('S3_ENDPOINT'),
|
|
344
|
+
s3Bucket: Config.string('S3_BUCKET'),
|
|
345
|
+
s3Region: Config.string('S3_REGION').pipe(Config.withDefault('garage')),
|
|
346
|
+
s3AccessKeyId: Config.redacted('S3_ACCESS_KEY_ID'),
|
|
347
|
+
s3SecretAccessKey: Config.redacted('S3_SECRET_ACCESS_KEY'),
|
|
348
|
+
attachmentUrlExpiresIn: Config.number('ATTACHMENT_URL_EXPIRES_IN').pipe(Config.withDefault(1800)),
|
|
349
|
+
firecrawlApiKey: Config.redacted('FIRECRAWL_API_KEY'),
|
|
350
|
+
firecrawlApiBaseUrl: Config.string('FIRECRAWL_API_BASE_URL').pipe(Config.option),
|
|
351
|
+
logLevel: Config.string('LOG_LEVEL').pipe(Config.withDefault('info')),
|
|
352
|
+
memorySearchK: Config.number('MEMORY_SEARCH_K').pipe(Config.withDefault(6)),
|
|
353
|
+
memoryRerankerStrategy: Config.string('MEMORY_RERANKER_STRATEGY').pipe(Config.withDefault('rerank')),
|
|
354
|
+
memoryRerankerModelId: Config.string('MEMORY_RERANKER_MODEL_ID').pipe(
|
|
355
|
+
Config.withDefault(OPENROUTER_FAST_RERANK_MODEL_ID),
|
|
356
|
+
),
|
|
357
|
+
otlpBaseUrl: Config.string('OTLP_BASE_URL').pipe(Config.option),
|
|
358
|
+
otlpServiceName: Config.string('OTLP_SERVICE_NAME').pipe(Config.withDefault('lota-sdk')),
|
|
359
|
+
otlpServiceVersion: Config.string('OTLP_SERVICE_VERSION').pipe(Config.option),
|
|
360
|
+
devToolsUrl: Config.string('DEVTOOLS_URL').pipe(Config.option),
|
|
361
|
+
})
|
|
332
362
|
|
|
333
|
-
|
|
363
|
+
export type LotaRuntimeEnvironmentOverrides = Omit<
|
|
364
|
+
LotaRuntimeConfig,
|
|
365
|
+
'database' | 'redis' | 'aiGateway' | 's3' | 'firecrawl' | 'logging' | 'memory'
|
|
366
|
+
> & { logging?: LotaRuntimeConfig['logging']; memory?: LotaRuntimeConfig['memory'] }
|
|
367
|
+
|
|
368
|
+
export function loadLotaRuntimeConfigFromEnv(
|
|
369
|
+
overrides: LotaRuntimeEnvironmentOverrides,
|
|
370
|
+
options: { configProvider?: ConfigProvider.ConfigProvider } = {},
|
|
371
|
+
) {
|
|
372
|
+
return runtimeEnvironmentConfig
|
|
373
|
+
.parse(options.configProvider ?? ConfigProvider.fromEnv())
|
|
374
|
+
.pipe(
|
|
375
|
+
Effect.map((env) =>
|
|
376
|
+
parseLotaRuntimeConfig({
|
|
377
|
+
...overrides,
|
|
378
|
+
database: {
|
|
379
|
+
url: env.surrealdbUrl,
|
|
380
|
+
namespace: env.surrealdbNamespace,
|
|
381
|
+
username: env.surrealdbUser,
|
|
382
|
+
password: Redacted.value(env.surrealdbPassword),
|
|
383
|
+
},
|
|
384
|
+
redis: { url: env.redisUrl },
|
|
385
|
+
aiGateway: {
|
|
386
|
+
url: env.aiGatewayUrl,
|
|
387
|
+
key: Redacted.value(env.aiGatewayKey),
|
|
388
|
+
embeddingModel: env.aiEmbeddingModel,
|
|
389
|
+
maxConcurrency: env.aiGatewayMaxConcurrency,
|
|
390
|
+
...(Option.isSome(env.openRouterApiKey)
|
|
391
|
+
? { openRouterApiKey: Redacted.value(env.openRouterApiKey.value) }
|
|
392
|
+
: {}),
|
|
393
|
+
},
|
|
394
|
+
s3: {
|
|
395
|
+
endpoint: env.s3Endpoint,
|
|
396
|
+
bucket: env.s3Bucket,
|
|
397
|
+
region: env.s3Region,
|
|
398
|
+
accessKeyId: Redacted.value(env.s3AccessKeyId),
|
|
399
|
+
secretAccessKey: Redacted.value(env.s3SecretAccessKey),
|
|
400
|
+
attachmentUrlExpiresIn: env.attachmentUrlExpiresIn,
|
|
401
|
+
},
|
|
402
|
+
firecrawl: {
|
|
403
|
+
apiKey: Redacted.value(env.firecrawlApiKey),
|
|
404
|
+
...(Option.isSome(env.firecrawlApiBaseUrl) ? { apiBaseUrl: env.firecrawlApiBaseUrl.value } : {}),
|
|
405
|
+
},
|
|
406
|
+
logging: overrides.logging ?? { level: env.logLevel as (typeof logLevelValues)[number] },
|
|
407
|
+
memory: {
|
|
408
|
+
searchK: env.memorySearchK,
|
|
409
|
+
rerankerStrategy: env.memoryRerankerStrategy as MemoryRerankerStrategy,
|
|
410
|
+
rerankerModelId: env.memoryRerankerModelId,
|
|
411
|
+
...overrides.memory,
|
|
412
|
+
},
|
|
413
|
+
observability: {
|
|
414
|
+
serviceName: env.otlpServiceName,
|
|
415
|
+
...(Option.isSome(env.otlpBaseUrl) ? { otlpBaseUrl: env.otlpBaseUrl.value } : {}),
|
|
416
|
+
...(Option.isSome(env.otlpServiceVersion) ? { serviceVersion: env.otlpServiceVersion.value } : {}),
|
|
417
|
+
...(Option.isSome(env.devToolsUrl) ? { devToolsUrl: env.devToolsUrl.value } : {}),
|
|
418
|
+
...overrides.observability,
|
|
419
|
+
},
|
|
420
|
+
}),
|
|
421
|
+
),
|
|
422
|
+
)
|
|
334
423
|
}
|
|
335
424
|
|
|
336
|
-
export function
|
|
337
|
-
return
|
|
425
|
+
export function getRuntimeConfig(): ResolvedLotaRuntimeConfig {
|
|
426
|
+
return getCurrentRuntime().runSync(Effect.service(RuntimeConfigServiceTag))
|
|
338
427
|
}
|
|
339
428
|
|
|
340
429
|
export type { LotaThreadConfig }
|
|
@@ -6,8 +6,17 @@ 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'
|
|
9
11
|
|
|
10
12
|
import type { RecordIdRef } from '../db/record-id'
|
|
13
|
+
import { getCurrentRuntime } from '../effect/runtime-ref'
|
|
14
|
+
import {
|
|
15
|
+
RuntimeAdaptersServiceTag,
|
|
16
|
+
RuntimeWorkerExtensionsServiceTag,
|
|
17
|
+
ToolProvidersServiceTag,
|
|
18
|
+
TurnHooksServiceTag,
|
|
19
|
+
} from '../effect/services'
|
|
11
20
|
import type { ReadableUploadMetadata } from '../storage/attachment-types'
|
|
12
21
|
import type { LotaRuntimeWorkerExtensions } from './runtime-worker-registry'
|
|
13
22
|
|
|
@@ -193,54 +202,32 @@ export interface LotaRuntimeAdapters {
|
|
|
193
202
|
withWorkspaceMemoryLock?: <T>(workspaceId: string, fn: () => Promise<T>) => Promise<T>
|
|
194
203
|
}
|
|
195
204
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
turnHooks: LotaRuntimeTurnHooks
|
|
199
|
-
toolProviders: ToolSet
|
|
200
|
-
extraWorkers: LotaRuntimeWorkerExtensions
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const EMPTY_TOOLS = {} as ToolSet
|
|
204
|
-
|
|
205
|
-
let runtimeExtensionsState: RuntimeExtensionsState = {
|
|
206
|
-
adapters: {},
|
|
207
|
-
turnHooks: {},
|
|
208
|
-
toolProviders: EMPTY_TOOLS,
|
|
209
|
-
extraWorkers: {},
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export function configureRuntimeExtensions(params: {
|
|
213
|
-
adapters?: LotaRuntimeAdapters
|
|
214
|
-
turnHooks?: LotaRuntimeTurnHooks
|
|
215
|
-
toolProviders?: ToolSet
|
|
216
|
-
extraWorkers?: LotaRuntimeWorkerExtensions
|
|
217
|
-
}): void {
|
|
218
|
-
runtimeExtensionsState = {
|
|
219
|
-
adapters: params.adapters ?? {},
|
|
220
|
-
turnHooks: params.turnHooks ?? {},
|
|
221
|
-
toolProviders: params.toolProviders ?? EMPTY_TOOLS,
|
|
222
|
-
extraWorkers: params.extraWorkers ?? {},
|
|
223
|
-
}
|
|
205
|
+
function resolveFromRuntime<I, T>(tag: Context.Key<I, T>): T {
|
|
206
|
+
return getCurrentRuntime().runSync(Effect.service(tag))
|
|
224
207
|
}
|
|
225
208
|
|
|
226
209
|
export function getRuntimeAdapters(): LotaRuntimeAdapters {
|
|
227
|
-
return
|
|
210
|
+
return resolveFromRuntime(RuntimeAdaptersServiceTag)
|
|
228
211
|
}
|
|
229
212
|
|
|
230
213
|
export function getTurnHooks(): LotaRuntimeTurnHooks {
|
|
231
|
-
return
|
|
214
|
+
return resolveFromRuntime(TurnHooksServiceTag)
|
|
232
215
|
}
|
|
233
216
|
|
|
234
217
|
export function getToolProviders(): ToolSet {
|
|
235
|
-
return
|
|
218
|
+
return resolveFromRuntime(ToolProvidersServiceTag)
|
|
236
219
|
}
|
|
237
220
|
|
|
238
221
|
export function getConfiguredPluginDatabaseConnector(): (() => Promise<void>) | undefined {
|
|
239
|
-
return
|
|
222
|
+
return getRuntimeAdapters().connectPluginDatabases
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function getExtraWorkers(): LotaRuntimeWorkerExtensions {
|
|
226
|
+
return resolveFromRuntime(RuntimeWorkerExtensionsServiceTag)
|
|
240
227
|
}
|
|
241
228
|
|
|
242
|
-
export
|
|
243
|
-
const adapter =
|
|
229
|
+
export function withConfiguredWorkspaceMemoryLock<T>(workspaceId: string, fn: () => Promise<T>): Promise<T> {
|
|
230
|
+
const adapter = getRuntimeAdapters().withWorkspaceMemoryLock
|
|
244
231
|
if (!adapter) {
|
|
245
232
|
return fn()
|
|
246
233
|
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { stepCountIs } from 'ai'
|
|
2
|
+
import type { ToolSet } from 'ai'
|
|
3
|
+
import { Schema, Effect } from 'effect'
|
|
4
|
+
|
|
5
|
+
import { getAgentRuntimeConfig, getResolvedAgentFactoryConfig } from '../../config/agent-defaults'
|
|
6
|
+
import { aiLogger } from '../../config/logger'
|
|
7
|
+
|
|
8
|
+
interface ExecutableToolDefinition {
|
|
9
|
+
execute: (...args: unknown[]) => Promise<unknown>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class SocialChatAgentRunnerError extends Schema.TaggedErrorClass<SocialChatAgentRunnerError>()(
|
|
13
|
+
'SocialChatAgentRunnerError',
|
|
14
|
+
{ message: Schema.String, cause: Schema.optional(Schema.Defect) },
|
|
15
|
+
) {}
|
|
16
|
+
|
|
17
|
+
const SOCIAL_CHAT_RETRIEVAL_TOOL_NAMES = [
|
|
18
|
+
'memorySearch',
|
|
19
|
+
'conversationSearch',
|
|
20
|
+
'queryKnowledge',
|
|
21
|
+
'researchTopic',
|
|
22
|
+
'searchWeb',
|
|
23
|
+
'fetchWebpage',
|
|
24
|
+
'inspectWebsite',
|
|
25
|
+
] as const
|
|
26
|
+
|
|
27
|
+
export function withLoggedSocialToolSet(
|
|
28
|
+
tools: ToolSet,
|
|
29
|
+
params: { agentId: string; channelId: string; threadId: string; executedToolNames: string[] },
|
|
30
|
+
): ToolSet {
|
|
31
|
+
return Object.fromEntries(
|
|
32
|
+
Object.entries(tools).map(([toolName, toolDefinition]) => {
|
|
33
|
+
if (
|
|
34
|
+
typeof toolDefinition !== 'object' ||
|
|
35
|
+
!('execute' in toolDefinition) ||
|
|
36
|
+
typeof toolDefinition.execute !== 'function'
|
|
37
|
+
) {
|
|
38
|
+
return [toolName, toolDefinition]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const executableTool = toolDefinition as typeof toolDefinition & ExecutableToolDefinition
|
|
42
|
+
return [
|
|
43
|
+
toolName,
|
|
44
|
+
{
|
|
45
|
+
...toolDefinition,
|
|
46
|
+
execute: (...args: unknown[]): Promise<unknown> =>
|
|
47
|
+
Effect.runPromise(
|
|
48
|
+
Effect.gen(function* () {
|
|
49
|
+
aiLogger.info`Slack social-chat tool start: agentId=${params.agentId}, tool=${toolName}, channelId=${params.channelId}, threadId=${params.threadId}`
|
|
50
|
+
const result: unknown = yield* Effect.tryPromise({
|
|
51
|
+
try: () => executableTool.execute(...args),
|
|
52
|
+
catch: (error: unknown) => new SocialChatAgentRunnerError({ message: String(error), cause: error }),
|
|
53
|
+
})
|
|
54
|
+
params.executedToolNames.push(toolName)
|
|
55
|
+
aiLogger.info`Slack social-chat tool finish: agentId=${params.agentId}, tool=${toolName}, channelId=${params.channelId}, threadId=${params.threadId}`
|
|
56
|
+
return result
|
|
57
|
+
}).pipe(
|
|
58
|
+
Effect.tapError((error) =>
|
|
59
|
+
Effect.sync(() => {
|
|
60
|
+
aiLogger.warn`Slack social-chat tool failed: agentId=${params.agentId}, tool=${toolName}, channelId=${params.channelId}, threadId=${params.threadId}, error=${error}`
|
|
61
|
+
}),
|
|
62
|
+
),
|
|
63
|
+
),
|
|
64
|
+
),
|
|
65
|
+
},
|
|
66
|
+
]
|
|
67
|
+
}),
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function runSocialAgentTurnEffect(params: {
|
|
72
|
+
agentId: string
|
|
73
|
+
mode: 'fixedThreadMode' | 'threadMode'
|
|
74
|
+
threadType: 'group'
|
|
75
|
+
onboardingActive: boolean
|
|
76
|
+
linearInstalled: boolean
|
|
77
|
+
systemWorkspaceDetails?: string
|
|
78
|
+
preSeededMemoriesSection?: string
|
|
79
|
+
retrievedKnowledgeSection?: string
|
|
80
|
+
learnedSkillsSection?: string
|
|
81
|
+
userMessageText?: string
|
|
82
|
+
additionalInstructionSections?: string[]
|
|
83
|
+
prompt: string
|
|
84
|
+
tools: ToolSet
|
|
85
|
+
abortSignal: AbortSignal
|
|
86
|
+
}): Effect.Effect<{ text: string; displayName: string }, SocialChatAgentRunnerError> {
|
|
87
|
+
return Effect.gen(function* () {
|
|
88
|
+
const runtimeConfig = getAgentRuntimeConfig({
|
|
89
|
+
agentId: params.agentId,
|
|
90
|
+
threadType: params.threadType,
|
|
91
|
+
mode: params.mode,
|
|
92
|
+
onboardingActive: params.onboardingActive,
|
|
93
|
+
linearInstalled: params.linearInstalled,
|
|
94
|
+
systemWorkspaceDetails: params.systemWorkspaceDetails,
|
|
95
|
+
preSeededMemoriesSection: params.preSeededMemoriesSection,
|
|
96
|
+
retrievedKnowledgeSection: params.retrievedKnowledgeSection,
|
|
97
|
+
learnedSkillsSection: params.learnedSkillsSection,
|
|
98
|
+
userMessageText: params.userMessageText,
|
|
99
|
+
ruleOptions: {
|
|
100
|
+
includeMemr3Rule: SOCIAL_CHAT_RETRIEVAL_TOOL_NAMES.some((toolName) => toolName in params.tools),
|
|
101
|
+
includeDomainReasoningFallbackRule: params.agentId === 'cpo' || params.agentId === 'mentor',
|
|
102
|
+
},
|
|
103
|
+
additionalInstructionSections: params.additionalInstructionSections,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
const agentFactoryEntry = getResolvedAgentFactoryConfig().createAgent[runtimeConfig.id]
|
|
107
|
+
if (typeof agentFactoryEntry !== 'function') {
|
|
108
|
+
return yield* new SocialChatAgentRunnerError({
|
|
109
|
+
message: `Social chat agent factory is not configured for ${runtimeConfig.id}`,
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
const agentFactory = agentFactoryEntry
|
|
113
|
+
|
|
114
|
+
const agent = agentFactory({
|
|
115
|
+
mode: params.mode,
|
|
116
|
+
tools: params.tools,
|
|
117
|
+
extraInstructions: runtimeConfig.extraInstructions,
|
|
118
|
+
stopWhen: [stepCountIs(runtimeConfig.maxSteps)],
|
|
119
|
+
})
|
|
120
|
+
const response = yield* Effect.promise(() =>
|
|
121
|
+
agent.generate({ prompt: params.prompt, abortSignal: params.abortSignal }),
|
|
122
|
+
)
|
|
123
|
+
const text = response.text.trim()
|
|
124
|
+
if (!text) {
|
|
125
|
+
return yield* new SocialChatAgentRunnerError({
|
|
126
|
+
message: `Social chat agent ${params.agentId} returned an empty response.`,
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
text,
|
|
132
|
+
displayName:
|
|
133
|
+
typeof runtimeConfig.displayName === 'string' && runtimeConfig.displayName.trim()
|
|
134
|
+
? runtimeConfig.displayName.trim()
|
|
135
|
+
: params.agentId,
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function runSocialAgentTurn(params: {
|
|
141
|
+
agentId: string
|
|
142
|
+
mode: 'fixedThreadMode' | 'threadMode'
|
|
143
|
+
threadType: 'group'
|
|
144
|
+
onboardingActive: boolean
|
|
145
|
+
linearInstalled: boolean
|
|
146
|
+
systemWorkspaceDetails?: string
|
|
147
|
+
preSeededMemoriesSection?: string
|
|
148
|
+
retrievedKnowledgeSection?: string
|
|
149
|
+
learnedSkillsSection?: string
|
|
150
|
+
userMessageText?: string
|
|
151
|
+
additionalInstructionSections?: string[]
|
|
152
|
+
prompt: string
|
|
153
|
+
tools: ToolSet
|
|
154
|
+
abortSignal: AbortSignal
|
|
155
|
+
}): Promise<{ text: string; displayName: string }> {
|
|
156
|
+
return Effect.runPromise(runSocialAgentTurnEffect(params))
|
|
157
|
+
}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { stripSlackToolExecutionNoticeMarkdown } from '@lota-sdk/shared'
|
|
2
2
|
import type { Message, Thread } from 'chat'
|
|
3
|
+
import { Schema, Effect } from 'effect'
|
|
3
4
|
|
|
4
|
-
import type {
|
|
5
|
-
|
|
5
|
+
import type {
|
|
6
|
+
SocialChatHistoryMessage,
|
|
7
|
+
SocialChatHistoryMetadata,
|
|
8
|
+
SocialChatHistoryPart,
|
|
9
|
+
} from '../../services/social-chat-history.service'
|
|
10
|
+
import { toHistoryMessages, toOptionalTrimmedString } from '../thread-chat-helpers'
|
|
11
|
+
|
|
12
|
+
class SocialChatHistoryError extends Schema.TaggedErrorClass<SocialChatHistoryError>()('SocialChatHistoryError', {
|
|
13
|
+
message: Schema.String,
|
|
14
|
+
cause: Schema.optional(Schema.Defect),
|
|
15
|
+
}) {}
|
|
6
16
|
|
|
7
17
|
export function readSlackAuthorName(message: Message): string | undefined {
|
|
8
18
|
return (
|
|
@@ -14,13 +24,9 @@ export function readSlackAuthorName(message: Message): string | undefined {
|
|
|
14
24
|
}
|
|
15
25
|
|
|
16
26
|
export function buildSocialChatThreadTranscript(
|
|
17
|
-
messages:
|
|
18
|
-
role: 'user' | 'assistant'
|
|
19
|
-
parts: Array<Record<string, unknown>>
|
|
20
|
-
metadata?: Record<string, unknown>
|
|
21
|
-
}>,
|
|
27
|
+
messages: ReadonlyArray<Pick<SocialChatHistoryMessage, 'role' | 'parts' | 'metadata'>>,
|
|
22
28
|
): string {
|
|
23
|
-
const historyMessages = toHistoryMessages(messages)
|
|
29
|
+
const historyMessages = toHistoryMessages([...messages])
|
|
24
30
|
if (historyMessages.length === 0) return 'No prior thread history.'
|
|
25
31
|
|
|
26
32
|
return historyMessages
|
|
@@ -58,11 +64,11 @@ export function normalizeSocialHistoryMessage(params: {
|
|
|
58
64
|
mediaType: attachment.mimeType ?? 'application/octet-stream',
|
|
59
65
|
sizeBytes: typeof attachment.size === 'number' ? attachment.size : null,
|
|
60
66
|
storageKey: attachment.url ?? 'external',
|
|
61
|
-
}))
|
|
67
|
+
})) satisfies SocialChatHistoryPart[]
|
|
62
68
|
const parts = [...(text ? [{ type: 'text', text }] : []), ...fileParts]
|
|
63
69
|
if (parts.length === 0) return null
|
|
64
70
|
|
|
65
|
-
const metadata:
|
|
71
|
+
const metadata: SocialChatHistoryMetadata = {
|
|
66
72
|
platform: 'slack',
|
|
67
73
|
channelId: params.channelId,
|
|
68
74
|
threadId: params.message.threadId,
|
|
@@ -97,14 +103,30 @@ export function normalizeSocialHistoryMessage(params: {
|
|
|
97
103
|
}
|
|
98
104
|
}
|
|
99
105
|
|
|
100
|
-
export
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
export function collectThreadMessages(thread: Thread, incomingMessage: Message): Promise<Message[]> {
|
|
107
|
+
return Effect.runPromise(
|
|
108
|
+
Effect.catch(
|
|
109
|
+
Effect.gen(function* () {
|
|
110
|
+
const collected: Message[] = []
|
|
111
|
+
const iterator = thread.allMessages[Symbol.asyncIterator]()
|
|
112
|
+
|
|
113
|
+
for (;;) {
|
|
114
|
+
const next = yield* Effect.tryPromise({
|
|
115
|
+
try: () => iterator.next(),
|
|
116
|
+
catch: (error: unknown) =>
|
|
117
|
+
new SocialChatHistoryError({ message: 'Failed to read thread messages', cause: error }),
|
|
118
|
+
})
|
|
119
|
+
if (next.done) break
|
|
120
|
+
collected.push(next.value)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return collected.length > 0
|
|
124
|
+
? collected
|
|
125
|
+
: thread.recentMessages.length > 0
|
|
126
|
+
? [...thread.recentMessages]
|
|
127
|
+
: [incomingMessage]
|
|
128
|
+
}),
|
|
129
|
+
() => Effect.succeed(thread.recentMessages.length > 0 ? [...thread.recentMessages] : [incomingMessage]),
|
|
130
|
+
),
|
|
131
|
+
)
|
|
110
132
|
}
|