@lota-sdk/core 0.4.10 → 0.4.12
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 +3 -3
- package/src/ai-gateway/ai-gateway.ts +214 -98
- package/src/ai-gateway/index.ts +16 -1
- package/src/config/agent-defaults.ts +4 -120
- package/src/config/logger.ts +18 -34
- package/src/config/model-constants.ts +1 -0
- package/src/config/thread-defaults.ts +1 -18
- package/src/create-runtime.ts +90 -28
- package/src/db/base.service.ts +30 -38
- package/src/db/service.ts +489 -545
- package/src/effect/index.ts +0 -2
- package/src/effect/layers.ts +6 -13
- package/src/embeddings/provider.ts +2 -7
- package/src/index.ts +4 -5
- package/src/queues/autonomous-job.queue.ts +159 -113
- package/src/queues/context-compaction.queue.ts +39 -25
- package/src/queues/delayed-node-promotion.queue.ts +56 -29
- package/src/queues/document-processor.queue.ts +5 -3
- package/src/queues/index.ts +1 -0
- package/src/queues/memory-consolidation.queue.ts +79 -53
- package/src/queues/organization-learning.queue.ts +63 -39
- package/src/queues/plan-agent-heartbeat.queue.ts +104 -79
- package/src/queues/plan-scheduler.queue.ts +100 -84
- package/src/queues/post-chat-memory.queue.ts +55 -33
- package/src/queues/queue-factory.ts +40 -41
- package/src/queues/queues.service.ts +61 -0
- package/src/queues/title-generation.queue.ts +42 -31
- package/src/redis/org-memory-lock.ts +24 -9
- package/src/redis/redis-lease-lock.ts +8 -1
- package/src/runtime/agent-identity-overrides.ts +7 -3
- package/src/runtime/agent-runtime-policy.ts +9 -4
- package/src/runtime/agent-stream-helpers.ts +9 -4
- package/src/runtime/context-compaction/context-compaction-runtime.ts +28 -32
- package/src/runtime/context-compaction/context-compaction.ts +9 -7
- package/src/runtime/domain-layer.ts +15 -4
- package/src/runtime/execution-plan-visibility.ts +5 -2
- package/src/runtime/graph-designer.ts +0 -22
- package/src/runtime/index.ts +2 -0
- package/src/runtime/indexed-repositories-policy.ts +2 -6
- package/src/runtime/live-turn-trace.ts +344 -0
- package/src/runtime/plugin-resolution.ts +29 -12
- package/src/runtime/post-turn-side-effects.ts +139 -141
- package/src/runtime/runtime-config.ts +0 -6
- package/src/runtime/runtime-extensions.ts +0 -54
- package/src/runtime/runtime-lifecycle.ts +4 -4
- package/src/runtime/runtime-services.ts +125 -53
- package/src/runtime/runtime-worker-registry.ts +113 -30
- package/src/runtime/social-chat/social-chat-agent-runner.ts +6 -3
- package/src/runtime/social-chat/social-chat-history.ts +3 -1
- package/src/runtime/social-chat/social-chat.ts +35 -20
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +6 -5
- package/src/runtime/team-consultation/team-consultation-prompts.ts +11 -6
- package/src/runtime/thread-chat-helpers.ts +18 -9
- package/src/runtime/thread-turn-context.ts +7 -47
- package/src/runtime/turn-lifecycle.ts +6 -14
- package/src/services/agent-activity.service.ts +168 -175
- package/src/services/agent-executor.service.ts +35 -16
- package/src/services/attachment.service.ts +4 -70
- package/src/services/autonomous-job.service.ts +53 -61
- package/src/services/context-compaction.service.ts +7 -9
- package/src/services/execution-plan/execution-plan-graph.ts +106 -115
- package/src/services/execution-plan/execution-plan-schedule.ts +1 -15
- package/src/services/execution-plan/execution-plan.service.ts +67 -50
- package/src/services/global-orchestrator.service.ts +18 -7
- package/src/services/graph-full-routing.ts +7 -6
- package/src/services/memory/memory-conversation.ts +10 -5
- package/src/services/memory/memory.service.ts +11 -8
- package/src/services/ownership-dispatcher.service.ts +16 -5
- package/src/services/plan/plan-agent-heartbeat.service.ts +29 -15
- package/src/services/plan/plan-agent-query.service.ts +12 -8
- package/src/services/plan/plan-completion-side-effects.ts +93 -101
- package/src/services/plan/plan-cycle.service.ts +7 -45
- package/src/services/plan/plan-deadline.service.ts +28 -17
- package/src/services/plan/plan-event-delivery.service.ts +47 -40
- package/src/services/plan/plan-executor-context.ts +2 -0
- package/src/services/plan/plan-executor-graph.ts +366 -391
- package/src/services/plan/plan-executor.service.ts +13 -91
- package/src/services/plan/plan-scheduler.service.ts +62 -49
- package/src/services/plan/plan-transaction-events.ts +1 -1
- package/src/services/recent-activity-title.service.ts +6 -2
- package/src/services/thread/thread-bootstrap.ts +11 -9
- package/src/services/thread/thread-message.service.ts +6 -5
- package/src/services/thread/thread-turn-execution.ts +86 -82
- package/src/services/thread/thread-turn-preparation.service.ts +92 -45
- package/src/services/thread/thread-turn-streaming.ts +60 -28
- package/src/services/thread/thread-turn.ts +212 -46
- package/src/services/thread/thread.service.ts +21 -6
- package/src/system-agents/recent-activity-title-refiner.agent.ts +8 -5
- package/src/system-agents/thread-router.agent.ts +23 -20
- package/src/tools/execution-plan.tool.ts +8 -3
- package/src/tools/fetch-webpage.tool.ts +10 -9
- package/src/tools/firecrawl-client.ts +0 -15
- package/src/tools/remember-memory.tool.ts +3 -6
- package/src/tools/research-topic.tool.ts +12 -3
- package/src/tools/search-web.tool.ts +10 -9
- package/src/tools/search.tool.ts +4 -5
- package/src/tools/team-think.tool.ts +139 -121
- package/src/workers/bootstrap.ts +9 -10
- package/src/workers/memory-consolidation.worker.ts +4 -1
- package/src/workers/organization-learning.worker.ts +15 -2
- package/src/workers/regular-chat-memory-digest.helpers.ts +3 -4
- package/src/workers/regular-chat-memory-digest.runner.ts +21 -14
- package/src/workers/skill-extraction.runner.ts +13 -15
- package/src/workers/worker-utils.ts +6 -18
- package/src/effect/awaitable-effect.ts +0 -96
- package/src/effect/runtime-ref.ts +0 -25
- package/src/effect/runtime.ts +0 -46
- package/src/redis/runtime-connection.ts +0 -20
- package/src/runtime/runtime-accessors.ts +0 -92
- package/src/runtime/runtime-token.ts +0 -47
|
@@ -4,12 +4,7 @@ import { z } from 'zod'
|
|
|
4
4
|
|
|
5
5
|
import { aiGatewayChatModel } from '../ai-gateway/ai-gateway'
|
|
6
6
|
import { buildAiGatewayDirectCacheHeaders } from '../ai-gateway/cache-headers'
|
|
7
|
-
import {
|
|
8
|
-
getAgentDescriptions,
|
|
9
|
-
getAgentDisplayNames,
|
|
10
|
-
getAgentShortDisplayNames,
|
|
11
|
-
getRouterModelId,
|
|
12
|
-
} from '../config/agent-defaults'
|
|
7
|
+
import type { ResolvedAgentConfig } from '../config/agent-defaults'
|
|
13
8
|
import { chatLogger } from '../config/logger'
|
|
14
9
|
import type { ValidationError } from '../effect/errors'
|
|
15
10
|
import { AiGenerationError } from '../effect/errors'
|
|
@@ -28,6 +23,7 @@ export type RouterTriageResult = z.infer<typeof TriageResultSchema>
|
|
|
28
23
|
export type RouterCheckResult = { done: true } | RouterCheckContinueResult
|
|
29
24
|
|
|
30
25
|
interface RouterDisplayOptions {
|
|
26
|
+
agentConfig: ResolvedAgentConfig
|
|
31
27
|
displayNamesById?: Partial<Record<string, string>>
|
|
32
28
|
shortDisplayNamesById?: Partial<Record<string, string>>
|
|
33
29
|
routingAliasesByAgentId?: Partial<Record<string, string[]>>
|
|
@@ -44,26 +40,26 @@ function readStringArrayOverride(
|
|
|
44
40
|
return record && Object.hasOwn(record, key) ? record[key] : undefined
|
|
45
41
|
}
|
|
46
42
|
|
|
47
|
-
function readDisplayName(agentId: string, options
|
|
48
|
-
const override = readStringOverride(options
|
|
43
|
+
function readDisplayName(agentId: string, options: RouterDisplayOptions): string {
|
|
44
|
+
const override = readStringOverride(options.displayNamesById, agentId)
|
|
49
45
|
if (override !== undefined) {
|
|
50
46
|
return override
|
|
51
47
|
}
|
|
52
48
|
|
|
53
|
-
return
|
|
49
|
+
return options.agentConfig.displayNames[agentId] ?? agentId
|
|
54
50
|
}
|
|
55
51
|
|
|
56
|
-
function readShortDisplayName(agentId: string, options
|
|
57
|
-
const override = readStringOverride(options
|
|
52
|
+
function readShortDisplayName(agentId: string, options: RouterDisplayOptions): string {
|
|
53
|
+
const override = readStringOverride(options.shortDisplayNamesById, agentId)
|
|
58
54
|
if (override !== undefined) {
|
|
59
55
|
return override
|
|
60
56
|
}
|
|
61
57
|
|
|
62
|
-
return
|
|
58
|
+
return options.agentConfig.shortDisplayNames[agentId] ?? readDisplayName(agentId, options)
|
|
63
59
|
}
|
|
64
60
|
|
|
65
|
-
function buildMembersDescription(members: readonly string[], options
|
|
66
|
-
const agentDescriptions =
|
|
61
|
+
function buildMembersDescription(members: readonly string[], options: RouterDisplayOptions): string {
|
|
62
|
+
const agentDescriptions = options.agentConfig.descriptions
|
|
67
63
|
return members
|
|
68
64
|
.map((id) => {
|
|
69
65
|
const display = readDisplayName(id, options)
|
|
@@ -77,7 +73,7 @@ function escapeRegex(value: string): string {
|
|
|
77
73
|
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
78
74
|
}
|
|
79
75
|
|
|
80
|
-
function buildExplicitAgentRoutingContext(agentId: string, options
|
|
76
|
+
function buildExplicitAgentRoutingContext(agentId: string, options: RouterDisplayOptions): string {
|
|
81
77
|
const displayName = readDisplayName(agentId, options)
|
|
82
78
|
return `Respond directly to the part of the user's request explicitly addressed to ${displayName}.`
|
|
83
79
|
}
|
|
@@ -85,16 +81,16 @@ function buildExplicitAgentRoutingContext(agentId: string, options?: RouterDispl
|
|
|
85
81
|
function extractExplicitAgentTargets(
|
|
86
82
|
messageText: string,
|
|
87
83
|
members: readonly string[],
|
|
88
|
-
options
|
|
84
|
+
options: RouterDisplayOptions,
|
|
89
85
|
): string[] {
|
|
90
86
|
const normalizedMessage = messageText.trim()
|
|
91
87
|
if (!normalizedMessage) return []
|
|
92
88
|
|
|
93
89
|
const memberSet = new Set(members)
|
|
94
90
|
const aliases = new Map<string, string>()
|
|
95
|
-
const defaultDisplayNames = options
|
|
91
|
+
const defaultDisplayNames = options.displayNamesById === undefined ? options.agentConfig.displayNames : undefined
|
|
96
92
|
const defaultShortDisplayNames =
|
|
97
|
-
options
|
|
93
|
+
options.shortDisplayNamesById === undefined ? options.agentConfig.shortDisplayNames : undefined
|
|
98
94
|
|
|
99
95
|
for (const member of members) {
|
|
100
96
|
for (const rawAlias of [
|
|
@@ -103,7 +99,7 @@ function extractExplicitAgentTargets(
|
|
|
103
99
|
defaultShortDisplayNames?.[member],
|
|
104
100
|
readDisplayName(member, options),
|
|
105
101
|
readShortDisplayName(member, options),
|
|
106
|
-
...(readStringArrayOverride(options
|
|
102
|
+
...(readStringArrayOverride(options.routingAliasesByAgentId, member) ?? []),
|
|
107
103
|
]) {
|
|
108
104
|
if (typeof rawAlias !== 'string') continue
|
|
109
105
|
const alias = rawAlias.trim().toLowerCase()
|
|
@@ -173,12 +169,13 @@ function toRouterGenerationError(label: 'triage' | 'check', error: unknown): AiG
|
|
|
173
169
|
}
|
|
174
170
|
|
|
175
171
|
function generateRouterObjectEffect<TSchema extends z.ZodTypeAny>(params: {
|
|
172
|
+
agentConfig: ResolvedAgentConfig
|
|
176
173
|
schema: TSchema
|
|
177
174
|
system: string
|
|
178
175
|
prompt: string
|
|
179
176
|
label: 'triage' | 'check'
|
|
180
177
|
}): Effect.Effect<z.infer<TSchema> | null, never> {
|
|
181
|
-
const modelId =
|
|
178
|
+
const modelId = params.agentConfig.routerModelId ?? 'openrouter/openai/gpt-5.4-nano'
|
|
182
179
|
|
|
183
180
|
return Effect.tryPromise({
|
|
184
181
|
try: () =>
|
|
@@ -219,6 +216,7 @@ function generateRouterObjectEffect<TSchema extends z.ZodTypeAny>(params: {
|
|
|
219
216
|
}
|
|
220
217
|
|
|
221
218
|
export function triageThreadMessage(params: {
|
|
219
|
+
agentConfig: ResolvedAgentConfig
|
|
222
220
|
threadTitle: string
|
|
223
221
|
members: readonly string[]
|
|
224
222
|
messageText: string
|
|
@@ -230,6 +228,7 @@ export function triageThreadMessage(params: {
|
|
|
230
228
|
return Effect.runPromise(
|
|
231
229
|
Effect.gen(function* () {
|
|
232
230
|
const displayOptions: RouterDisplayOptions = {
|
|
231
|
+
agentConfig: params.agentConfig,
|
|
233
232
|
displayNamesById: params.displayNamesById,
|
|
234
233
|
shortDisplayNamesById: params.shortDisplayNamesById,
|
|
235
234
|
routingAliasesByAgentId: params.routingAliasesByAgentId,
|
|
@@ -254,6 +253,7 @@ export function triageThreadMessage(params: {
|
|
|
254
253
|
.join('\n\n')
|
|
255
254
|
|
|
256
255
|
const parsed = yield* generateRouterObjectEffect({
|
|
256
|
+
agentConfig: params.agentConfig,
|
|
257
257
|
schema: TriageResultSchema,
|
|
258
258
|
system: TRIAGE_SYSTEM_PROMPT,
|
|
259
259
|
prompt,
|
|
@@ -279,6 +279,7 @@ export function triageThreadMessage(params: {
|
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
export function checkForNextAgent(params: {
|
|
282
|
+
agentConfig: ResolvedAgentConfig
|
|
282
283
|
threadTitle: string
|
|
283
284
|
members: readonly string[]
|
|
284
285
|
messageText: string
|
|
@@ -291,6 +292,7 @@ export function checkForNextAgent(params: {
|
|
|
291
292
|
return Effect.runPromise(
|
|
292
293
|
Effect.gen(function* () {
|
|
293
294
|
const displayOptions: RouterDisplayOptions = {
|
|
295
|
+
agentConfig: params.agentConfig,
|
|
294
296
|
displayNamesById: params.displayNamesById,
|
|
295
297
|
shortDisplayNamesById: params.shortDisplayNamesById,
|
|
296
298
|
routingAliasesByAgentId: params.routingAliasesByAgentId,
|
|
@@ -320,6 +322,7 @@ export function checkForNextAgent(params: {
|
|
|
320
322
|
].join('\n\n')
|
|
321
323
|
|
|
322
324
|
const parsed = yield* generateRouterObjectEffect({
|
|
325
|
+
agentConfig: params.agentConfig,
|
|
323
326
|
schema: CheckResultObjectSchema,
|
|
324
327
|
system: CHECK_SYSTEM_PROMPT,
|
|
325
328
|
prompt,
|
|
@@ -49,6 +49,8 @@ type ExecutionPlanExecutionPlanService = NoContextService<
|
|
|
49
49
|
|
|
50
50
|
type ExecutionPlanToolValidationError = ReturnType<typeof toValidationError>
|
|
51
51
|
|
|
52
|
+
export type ExecutionPlanToolRunPromise = <A, E>(effect: Effect.Effect<A, E, never>) => Promise<A>
|
|
53
|
+
|
|
52
54
|
export function createExecutionPlanTool(params: {
|
|
53
55
|
orgId: RecordIdRef
|
|
54
56
|
userId: RecordIdRef
|
|
@@ -56,6 +58,7 @@ export function createExecutionPlanTool(params: {
|
|
|
56
58
|
agentId: string
|
|
57
59
|
executionPlanService: ExecutionPlanExecutionPlanService
|
|
58
60
|
threadService: ExecutionPlanThreadService
|
|
61
|
+
runPromise: ExecutionPlanToolRunPromise
|
|
59
62
|
onPlanChanged?: () => void
|
|
60
63
|
validateInlinePlan?: (draft: ReturnType<typeof expandAgentPlanDraft>) => void
|
|
61
64
|
}) {
|
|
@@ -64,7 +67,7 @@ export function createExecutionPlanTool(params: {
|
|
|
64
67
|
'Manage execution plans. Actions: create (inline, 1-2 nodes), create-project (dedicated project thread, 3+ nodes), replace (swap active plan), resume (resume interrupted plan), update-node (submit result for a specific node).',
|
|
65
68
|
inputSchema: ExecutionPlanArgsSchema,
|
|
66
69
|
execute: (input) =>
|
|
67
|
-
|
|
70
|
+
params.runPromise(
|
|
68
71
|
Effect.gen(function* () {
|
|
69
72
|
const parsed = yield* parseExecutionPlanArgsEffect(input)
|
|
70
73
|
|
|
@@ -262,13 +265,14 @@ function extractAgentPlanDraftEffect(
|
|
|
262
265
|
export function createExecutionPlanQueryTool(params: {
|
|
263
266
|
threadId: RecordIdRef
|
|
264
267
|
executionPlanService: Pick<ExecutionPlanExecutionPlanService, 'listActivePlanSummaries' | 'getActivePlanToolResult'>
|
|
268
|
+
runPromise: ExecutionPlanToolRunPromise
|
|
265
269
|
}) {
|
|
266
270
|
return tool({
|
|
267
271
|
description:
|
|
268
272
|
'Query execution plans. Omit runId to list all active plans. Provide runId to load a specific plan run.',
|
|
269
273
|
inputSchema: ExecutionPlanQueryArgsSchema,
|
|
270
274
|
execute: (input) =>
|
|
271
|
-
|
|
275
|
+
params.runPromise(
|
|
272
276
|
Effect.gen(function* () {
|
|
273
277
|
if (!input.runId) {
|
|
274
278
|
return yield* params.executionPlanService.listActivePlanSummaries(params.threadId)
|
|
@@ -291,6 +295,7 @@ export function createSubmitExecutionNodeResultTool(params: {
|
|
|
291
295
|
threadId: RecordIdRef
|
|
292
296
|
agentId: string
|
|
293
297
|
executionPlanService: Pick<ExecutionPlanExecutionPlanService, 'submitNodeResult'>
|
|
298
|
+
runPromise: ExecutionPlanToolRunPromise
|
|
294
299
|
onPlanChanged?: () => void
|
|
295
300
|
}) {
|
|
296
301
|
return tool({
|
|
@@ -298,7 +303,7 @@ export function createSubmitExecutionNodeResultTool(params: {
|
|
|
298
303
|
'Submit the result for the currently running execution node. The executor validates outputs, artifacts, and completion checks before advancing the run.',
|
|
299
304
|
inputSchema: SubmitExecutionNodeResultArgsSchema,
|
|
300
305
|
execute: (input) =>
|
|
301
|
-
|
|
306
|
+
params.runPromise(
|
|
302
307
|
Effect.gen(function* () {
|
|
303
308
|
const result = yield* params.executionPlanService.submitNodeResult({
|
|
304
309
|
threadId: params.threadId,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type Firecrawl from '@mendable/firecrawl-js'
|
|
1
2
|
import { tool } from 'ai'
|
|
2
3
|
import { Effect, Schema } from 'effect'
|
|
3
4
|
import { z } from 'zod'
|
|
@@ -6,10 +7,13 @@ import type { ToolDefinition } from '../ai/definitions'
|
|
|
6
7
|
import { withTimeout } from '../utils/async'
|
|
7
8
|
import { nowIsoDateTimeString } from '../utils/date-time'
|
|
8
9
|
import { readStringField, truncateOptionalText } from '../utils/string'
|
|
9
|
-
import { getFirecrawlClient } from './firecrawl-client'
|
|
10
10
|
import type { WebCitation } from './tool-contracts'
|
|
11
11
|
import { toRecord, WEB_TOOL_TIMEOUT_MS } from './web-tool-shared'
|
|
12
12
|
|
|
13
|
+
export interface FetchWebpageToolContext {
|
|
14
|
+
firecrawl: Firecrawl
|
|
15
|
+
}
|
|
16
|
+
|
|
13
17
|
class FetchWebpageToolError extends Schema.TaggedErrorClass<FetchWebpageToolError>()(
|
|
14
18
|
'@lota-sdk/core/FetchWebpageToolError',
|
|
15
19
|
{ message: Schema.String, cause: Schema.optional(Schema.Defect) },
|
|
@@ -98,7 +102,7 @@ function buildFetchCitations(url: string, document: unknown): WebCitation[] {
|
|
|
98
102
|
|
|
99
103
|
export const fetchWebpageTool = {
|
|
100
104
|
name: 'fetchWebpage',
|
|
101
|
-
create: () =>
|
|
105
|
+
create: ({ firecrawl }: FetchWebpageToolContext) =>
|
|
102
106
|
tool({
|
|
103
107
|
description: 'Retrieve and parse a single webpage.',
|
|
104
108
|
inputSchema: z
|
|
@@ -119,10 +123,8 @@ export const fetchWebpageTool = {
|
|
|
119
123
|
formats?: z.infer<typeof FormatSchema>[]
|
|
120
124
|
onlyMainContent?: boolean
|
|
121
125
|
maxAge?: number
|
|
122
|
-
}) =>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return Effect.runPromise(
|
|
126
|
+
}) =>
|
|
127
|
+
Effect.runPromise(
|
|
126
128
|
Effect.gen(function* () {
|
|
127
129
|
const result = yield* Effect.tryPromise({
|
|
128
130
|
try: () =>
|
|
@@ -139,7 +141,6 @@ export const fetchWebpageTool = {
|
|
|
139
141
|
})
|
|
140
142
|
return { url, document: summarizeDocument(url, result), citations: buildFetchCitations(url, result) }
|
|
141
143
|
}).pipe(Effect.withSpan('tool.fetchWebpage.execute')),
|
|
142
|
-
)
|
|
143
|
-
},
|
|
144
|
+
),
|
|
144
145
|
}),
|
|
145
|
-
} as const satisfies ToolDefinition<
|
|
146
|
+
} as const satisfies ToolDefinition<FetchWebpageToolContext>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Firecrawl from '@mendable/firecrawl-js'
|
|
2
2
|
import { Context, Effect, Layer } from 'effect'
|
|
3
3
|
|
|
4
|
-
import { resolveLotaService } from '../effect/runtime'
|
|
5
4
|
import { RuntimeConfigServiceTag } from '../effect/services'
|
|
6
5
|
|
|
7
6
|
export class FirecrawlTag extends Context.Service<FirecrawlTag, Firecrawl>()('@lota-sdk/core/Firecrawl') {}
|
|
@@ -16,17 +15,3 @@ export const FirecrawlLive = Layer.effect(
|
|
|
16
15
|
})
|
|
17
16
|
}),
|
|
18
17
|
)
|
|
19
|
-
|
|
20
|
-
let currentFirecrawlClient: Firecrawl | null = null
|
|
21
|
-
|
|
22
|
-
export function configureFirecrawlClient(client: Firecrawl): void {
|
|
23
|
-
currentFirecrawlClient = client
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function clearFirecrawlClient(): void {
|
|
27
|
-
currentFirecrawlClient = null
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function getFirecrawlClient(): Firecrawl {
|
|
31
|
-
return currentFirecrawlClient ?? resolveLotaService(FirecrawlTag)
|
|
32
|
-
}
|
|
@@ -5,7 +5,6 @@ import { z } from 'zod'
|
|
|
5
5
|
import type { RecordIdRef } from '../db/record-id'
|
|
6
6
|
import { recordIdToString } from '../db/record-id'
|
|
7
7
|
import { TABLES } from '../db/tables'
|
|
8
|
-
import type { MaybeAwaitableService } from '../effect/awaitable-effect'
|
|
9
8
|
import type { createMemoryService } from '../services/memory/memory.service'
|
|
10
9
|
import { safeEnqueue } from '../utils/async'
|
|
11
10
|
|
|
@@ -16,11 +15,9 @@ const RememberMemoryInputSchema = z
|
|
|
16
15
|
})
|
|
17
16
|
.strict()
|
|
18
17
|
|
|
19
|
-
type RememberMemoryService =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
'assessMemoryCandidate' | 'createOrganizationMemory' | 'createAgentMemory'
|
|
23
|
-
>
|
|
18
|
+
type RememberMemoryService = Pick<
|
|
19
|
+
ReturnType<typeof createMemoryService>,
|
|
20
|
+
'assessMemoryCandidate' | 'createOrganizationMemory' | 'createAgentMemory'
|
|
24
21
|
>
|
|
25
22
|
|
|
26
23
|
export function createRememberMemoryTool({
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
import type Firecrawl from '@mendable/firecrawl-js'
|
|
2
|
+
|
|
1
3
|
import { aiGatewayChatModel } from '../ai-gateway/ai-gateway'
|
|
2
4
|
import { buildAiGatewayStrictSemanticCacheHeaders } from '../ai-gateway/cache-headers'
|
|
3
5
|
import {
|
|
4
6
|
OPENROUTER_FAST_REASONING_MODEL_ID,
|
|
5
7
|
OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS,
|
|
6
8
|
} from '../config/model-constants'
|
|
7
|
-
import {
|
|
9
|
+
import { createDelegatedAgentToolWithContext } from '../system-agents/delegated-agent-factory'
|
|
8
10
|
import { RESEARCHER_PROMPT } from '../system-agents/researcher.agent'
|
|
9
11
|
import { fetchWebpageTool } from './fetch-webpage.tool'
|
|
10
12
|
import { searchWebTool } from './search-web.tool'
|
|
11
13
|
|
|
12
|
-
export
|
|
14
|
+
export interface ResearchTopicToolContext {
|
|
15
|
+
firecrawl: Firecrawl
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const researchTopicTool = createDelegatedAgentToolWithContext<ResearchTopicToolContext>({
|
|
13
19
|
id: 'researchTopic',
|
|
14
20
|
description:
|
|
15
21
|
'Delegate a research task to a dedicated research agent that searches the web, fetches pages, and returns a synthesized markdown report.',
|
|
@@ -17,6 +23,9 @@ export const researchTopicTool = createDelegatedAgentTool({
|
|
|
17
23
|
providerOptions: OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS,
|
|
18
24
|
headers: buildAiGatewayStrictSemanticCacheHeaders('researchTopic'),
|
|
19
25
|
instructions: RESEARCHER_PROMPT,
|
|
20
|
-
|
|
26
|
+
createTools: ({ firecrawl }) => ({
|
|
27
|
+
searchWeb: searchWebTool.create({ firecrawl }),
|
|
28
|
+
fetchWebpage: fetchWebpageTool.create({ firecrawl }),
|
|
29
|
+
}),
|
|
21
30
|
maxSteps: 6,
|
|
22
31
|
})
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type Firecrawl from '@mendable/firecrawl-js'
|
|
1
2
|
import { tool } from 'ai'
|
|
2
3
|
import { Effect, Schema } from 'effect'
|
|
3
4
|
import { z } from 'zod'
|
|
@@ -6,10 +7,13 @@ import type { ToolDefinition } from '../ai/definitions'
|
|
|
6
7
|
import { withTimeout } from '../utils/async'
|
|
7
8
|
import { nowIsoDateTimeString } from '../utils/date-time'
|
|
8
9
|
import { readStringField, truncateOptionalText } from '../utils/string'
|
|
9
|
-
import { getFirecrawlClient } from './firecrawl-client'
|
|
10
10
|
import type { WebCitation } from './tool-contracts'
|
|
11
11
|
import { toRecord, WEB_TOOL_TIMEOUT_MS } from './web-tool-shared'
|
|
12
12
|
|
|
13
|
+
export interface SearchWebToolContext {
|
|
14
|
+
firecrawl: Firecrawl
|
|
15
|
+
}
|
|
16
|
+
|
|
13
17
|
class SearchWebToolError extends Schema.TaggedErrorClass<SearchWebToolError>()('@lota-sdk/core/SearchWebToolError', {
|
|
14
18
|
message: Schema.String,
|
|
15
19
|
cause: Schema.optional(Schema.Defect),
|
|
@@ -135,7 +139,7 @@ function buildWebCitations(results: { web?: unknown[]; news?: unknown[]; images?
|
|
|
135
139
|
|
|
136
140
|
export const searchWebTool = {
|
|
137
141
|
name: 'searchWeb',
|
|
138
|
-
create: () =>
|
|
142
|
+
create: ({ firecrawl }: SearchWebToolContext) =>
|
|
139
143
|
tool({
|
|
140
144
|
description: 'Search the web for real-time information.',
|
|
141
145
|
inputSchema: z
|
|
@@ -159,10 +163,8 @@ export const searchWebTool = {
|
|
|
159
163
|
sources?: ('web' | 'news' | 'images')[]
|
|
160
164
|
location?: string
|
|
161
165
|
tbs?: string
|
|
162
|
-
}) =>
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return Effect.runPromise(
|
|
166
|
+
}) =>
|
|
167
|
+
Effect.runPromise(
|
|
166
168
|
Effect.gen(function* () {
|
|
167
169
|
const results = yield* Effect.tryPromise({
|
|
168
170
|
try: () =>
|
|
@@ -183,7 +185,6 @@ export const searchWebTool = {
|
|
|
183
185
|
citations: buildWebCitations(results),
|
|
184
186
|
}
|
|
185
187
|
}).pipe(Effect.withSpan('tool.searchWeb.execute')),
|
|
186
|
-
)
|
|
187
|
-
},
|
|
188
|
+
),
|
|
188
189
|
}),
|
|
189
|
-
} as const satisfies ToolDefinition<
|
|
190
|
+
} as const satisfies ToolDefinition<SearchWebToolContext>
|
package/src/tools/search.tool.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { tool } from 'ai'
|
|
|
2
2
|
import { Effect } from 'effect'
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
|
|
5
|
+
import type { ResolvedAgentConfig } from '../config/agent-defaults'
|
|
5
6
|
import { isAgentName } from '../config/agent-defaults'
|
|
6
7
|
import type { RecordIdRef } from '../db/record-id'
|
|
7
|
-
import type { MaybeAwaitableService } from '../effect/awaitable-effect'
|
|
8
8
|
import type { createMemoryService } from '../services/memory/memory.service'
|
|
9
9
|
import type { makeThreadMessageService } from '../services/thread/thread-message.service'
|
|
10
10
|
|
|
@@ -12,12 +12,11 @@ const CONVERSATION_SEARCH_RESULT_LIMIT = 20
|
|
|
12
12
|
const MemorySearchInputSchema = z.object({ query: z.string().min(1) }).strict()
|
|
13
13
|
const ConversationSearchInputSchema = z.object({ query: z.string().min(1), type: z.enum(['user', 'agent']) }).strict()
|
|
14
14
|
|
|
15
|
-
type MemorySearchService =
|
|
16
|
-
Pick<ReturnType<typeof createMemoryService>, 'searchAllMemoriesBatched'>
|
|
17
|
-
>
|
|
15
|
+
type MemorySearchService = Pick<ReturnType<typeof createMemoryService>, 'searchAllMemoriesBatched'>
|
|
18
16
|
type ConversationSearchService = Pick<ReturnType<typeof makeThreadMessageService>, 'searchMessagesEffect'>
|
|
19
17
|
|
|
20
18
|
export function createMemorySearchTool(
|
|
19
|
+
agentConfig: ResolvedAgentConfig,
|
|
21
20
|
orgIdString: string,
|
|
22
21
|
memoryService: MemorySearchService,
|
|
23
22
|
agentName?: string,
|
|
@@ -32,7 +31,7 @@ export function createMemorySearchTool(
|
|
|
32
31
|
const normalizedQuery = query.trim()
|
|
33
32
|
const retrieval = yield* memoryService.searchAllMemoriesBatched({
|
|
34
33
|
orgId: orgIdString,
|
|
35
|
-
agentName: isAgentName(agentName) ? agentName : undefined,
|
|
34
|
+
agentName: isAgentName(agentConfig, agentName) ? agentName : undefined,
|
|
36
35
|
query: normalizedQuery,
|
|
37
36
|
...(typeof options?.fastMode === 'boolean' ? { fastMode: options.fastMode } : {}),
|
|
38
37
|
...(typeof options?.allowMultiScopeRerank === 'boolean'
|