@lota-sdk/core 0.4.9 → 0.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/ai/embedding-cache.ts +3 -1
- package/src/ai-gateway/ai-gateway.ts +38 -10
- package/src/config/agent-defaults.ts +22 -9
- package/src/config/agent-types.ts +1 -1
- package/src/config/background-processing.ts +1 -1
- package/src/config/index.ts +0 -1
- package/src/config/logger.ts +20 -7
- package/src/config/thread-defaults.ts +12 -4
- package/src/create-runtime.ts +69 -656
- package/src/db/memory-query-builder.ts +2 -1
- package/src/db/memory-store.ts +29 -20
- package/src/db/memory.ts +188 -195
- package/src/db/service-normalization.ts +97 -64
- package/src/db/service.ts +706 -538
- package/src/db/startup.ts +30 -19
- package/src/effect/awaitable-effect.ts +46 -37
- package/src/effect/helpers.ts +30 -5
- package/src/effect/index.ts +7 -5
- package/src/effect/layers.ts +82 -72
- package/src/effect/runtime.ts +18 -3
- package/src/effect/services.ts +15 -11
- package/src/embeddings/provider.ts +65 -66
- package/src/index.ts +13 -11
- package/src/queues/autonomous-job.queue.ts +59 -71
- package/src/queues/context-compaction.queue.ts +6 -18
- package/src/queues/delayed-node-promotion.queue.ts +9 -17
- package/src/queues/organization-learning.queue.ts +17 -4
- package/src/queues/plan-agent-heartbeat.queue.ts +23 -20
- package/src/queues/plan-scheduler.queue.ts +6 -18
- package/src/queues/post-chat-memory.queue.ts +6 -18
- package/src/queues/queue-factory.ts +128 -50
- package/src/queues/title-generation.queue.ts +6 -17
- package/src/redis/connection.ts +181 -164
- package/src/redis/runtime-connection.ts +13 -3
- package/src/redis/stream-context.ts +17 -9
- package/src/runtime/agent-runtime-policy.ts +1 -1
- package/src/runtime/agent-stream-helpers.ts +15 -11
- package/src/runtime/chat-run-orchestration.ts +1 -1
- package/src/runtime/context-compaction/context-compaction-runtime.ts +1 -1
- package/src/runtime/context-compaction/context-compaction.ts +126 -82
- package/src/runtime/domain-layer.ts +192 -0
- package/src/runtime/graph-designer.ts +15 -7
- package/src/runtime/helper-model.ts +8 -4
- package/src/runtime/index.ts +0 -1
- package/src/runtime/memory/memory-block.ts +19 -9
- package/src/runtime/memory/memory-pipeline.ts +53 -66
- package/src/runtime/memory/memory-scope.ts +33 -29
- package/src/runtime/plugin-resolution.ts +33 -54
- package/src/runtime/post-turn-side-effects.ts +6 -26
- package/src/runtime/retrieval-adapters.ts +4 -4
- package/src/runtime/runtime-accessors.ts +92 -0
- package/src/runtime/runtime-config.ts +3 -3
- package/src/runtime/runtime-extensions.ts +20 -9
- package/src/runtime/runtime-lifecycle.ts +124 -0
- package/src/runtime/runtime-services.ts +386 -0
- package/src/runtime/runtime-token.ts +47 -0
- package/src/runtime/social-chat/social-chat-agent-runner.ts +7 -5
- package/src/runtime/social-chat/social-chat-history.ts +21 -12
- package/src/runtime/social-chat/social-chat.ts +401 -365
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +58 -52
- package/src/runtime/thread-turn-context.ts +21 -27
- package/src/services/agent-activity.service.ts +1 -1
- package/src/services/agent-executor.service.ts +179 -187
- package/src/services/artifact.service.ts +10 -5
- package/src/services/attachment.service.ts +35 -1
- package/src/services/autonomous-job.service.ts +58 -56
- package/src/services/background-work.service.ts +54 -0
- package/src/services/chat-run-registry.service.ts +3 -1
- package/src/services/context-compaction.service.ts +1 -1
- package/src/services/document-chunk.service.ts +8 -17
- package/src/services/execution-plan/execution-plan-graph.ts +74 -52
- package/src/services/execution-plan/execution-plan.service.ts +1 -1
- package/src/services/feedback-loop.service.ts +1 -1
- package/src/services/global-orchestrator.service.ts +33 -10
- package/src/services/graph-full-routing.ts +44 -33
- package/src/services/index.ts +1 -0
- package/src/services/institutional-memory.service.ts +8 -17
- package/src/services/learned-skill.service.ts +38 -35
- package/src/services/memory/memory-errors.ts +27 -0
- package/src/services/memory/memory-org-memory.ts +14 -3
- package/src/services/memory/memory-preseeded.ts +10 -4
- package/src/services/memory/memory-utils.ts +2 -1
- package/src/services/memory/memory.service.ts +26 -44
- package/src/services/memory/rerank.service.ts +3 -11
- package/src/services/monitoring-window.service.ts +1 -1
- package/src/services/mutating-approval.service.ts +1 -1
- package/src/services/node-workspace.service.ts +2 -2
- package/src/services/notification.service.ts +16 -4
- package/src/services/organization-member.service.ts +1 -1
- package/src/services/organization.service.ts +34 -51
- package/src/services/ownership-dispatcher.service.ts +132 -90
- package/src/services/plan/plan-agent-heartbeat.service.ts +1 -1
- package/src/services/plan/plan-agent-query.service.ts +1 -1
- package/src/services/plan/plan-approval.service.ts +52 -48
- package/src/services/plan/plan-artifact.service.ts +2 -2
- package/src/services/plan/plan-builder.service.ts +2 -2
- package/src/services/plan/plan-checkpoint.service.ts +1 -1
- package/src/services/plan/plan-compiler.service.ts +1 -1
- package/src/services/plan/plan-completion-side-effects.ts +18 -24
- package/src/services/plan/plan-coordination.service.ts +1 -1
- package/src/services/plan/plan-cycle.service.ts +171 -164
- package/src/services/plan/plan-deadline.service.ts +290 -304
- package/src/services/plan/plan-event-delivery.service.ts +44 -39
- package/src/services/plan/plan-executor-graph.ts +114 -67
- package/src/services/plan/plan-executor-helpers.ts +60 -75
- package/src/services/plan/plan-executor.service.ts +550 -467
- package/src/services/plan/plan-run.service.ts +12 -19
- package/src/services/plan/plan-scheduler.service.ts +27 -33
- package/src/services/plan/plan-template.service.ts +1 -1
- package/src/services/plan/plan-transaction-events.ts +8 -5
- package/src/services/plan/plan-validator.service.ts +1 -1
- package/src/services/plan/plan-workspace.service.ts +17 -11
- package/src/services/plugin-executor.service.ts +26 -21
- package/src/services/quality-metrics.service.ts +1 -1
- package/src/services/queue-job.service.ts +8 -17
- package/src/services/recent-activity-title.service.ts +17 -9
- package/src/services/recent-activity.service.ts +1 -1
- package/src/services/skill-resolver.service.ts +1 -1
- package/src/services/social-chat-history.service.ts +37 -20
- package/src/services/system-executor.service.ts +25 -20
- package/src/services/thread/thread-bootstrap.ts +26 -10
- package/src/services/thread/thread-listing.ts +2 -1
- package/src/services/thread/thread-memory-block.ts +18 -5
- package/src/services/thread/thread-message.service.ts +24 -8
- package/src/services/thread/thread-title.service.ts +1 -1
- package/src/services/thread/thread-turn-execution.ts +1 -1
- package/src/services/thread/thread-turn-preparation.service.ts +18 -16
- package/src/services/thread/thread-turn-streaming.ts +12 -11
- package/src/services/thread/thread-turn.ts +43 -10
- package/src/services/thread/thread.service.ts +11 -2
- package/src/services/user.service.ts +1 -1
- package/src/services/write-intent-validator.service.ts +1 -1
- package/src/storage/attachment-storage.service.ts +7 -4
- package/src/storage/generated-document-storage.service.ts +1 -1
- package/src/system-agents/context-compaction.agent.ts +1 -1
- package/src/system-agents/helper-agent-options.ts +1 -1
- package/src/system-agents/memory-reranker.agent.ts +1 -1
- package/src/system-agents/memory.agent.ts +1 -1
- package/src/system-agents/recent-activity-title-refiner.agent.ts +1 -1
- package/src/system-agents/regular-chat-memory-digest.agent.ts +1 -1
- package/src/system-agents/skill-extractor.agent.ts +1 -1
- package/src/system-agents/skill-manager.agent.ts +1 -1
- package/src/system-agents/title-generator.agent.ts +1 -1
- package/src/tools/execution-plan.tool.ts +28 -17
- package/src/tools/fetch-webpage.tool.ts +20 -13
- package/src/tools/firecrawl-client.ts +13 -3
- package/src/tools/plan-approval.tool.ts +9 -1
- package/src/tools/search-web.tool.ts +16 -9
- package/src/tools/team-think.tool.ts +2 -2
- package/src/utils/async.ts +15 -6
- package/src/utils/errors.ts +27 -15
- package/src/workers/bootstrap.ts +25 -48
- package/src/workers/organization-learning.worker.ts +1 -1
- package/src/workers/regular-chat-memory-digest.runner.ts +25 -15
- package/src/workers/worker-utils.ts +20 -2
- package/src/config/search.ts +0 -3
- package/src/runtime/agent-types.ts +0 -1
|
@@ -107,11 +107,14 @@ export function makeAttachmentStorageService(config: ResolvedLotaRuntimeConfig)
|
|
|
107
107
|
storageKey: string
|
|
108
108
|
orgId: string
|
|
109
109
|
userId: string
|
|
110
|
-
}): void {
|
|
110
|
+
}): Effect.Effect<void, ForbiddenError> {
|
|
111
111
|
const storagePrefix = buildUploadStoragePrefix({ orgId, userId })
|
|
112
112
|
if (!storageKey.startsWith(storagePrefix)) {
|
|
113
|
-
|
|
113
|
+
return Effect.fail(
|
|
114
|
+
new ForbiddenError({ message: 'Upload does not belong to the current organization/user scope.' }),
|
|
115
|
+
)
|
|
114
116
|
}
|
|
117
|
+
return Effect.void
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
function writeOrganizationDocumentEffect({
|
|
@@ -284,7 +287,7 @@ export function makeAttachmentStorageService(config: ResolvedLotaRuntimeConfig)
|
|
|
284
287
|
pagesPerPart?: number
|
|
285
288
|
}) {
|
|
286
289
|
return Effect.gen(function* () {
|
|
287
|
-
assertUploadOwnership({ storageKey: upload.storageKey, orgId, userId })
|
|
290
|
+
yield* assertUploadOwnership({ storageKey: upload.storageKey, orgId, userId })
|
|
288
291
|
|
|
289
292
|
const parsed = yield* extractStoredAttachmentPagesEffect({
|
|
290
293
|
storageKey: upload.storageKey,
|
|
@@ -437,7 +440,7 @@ export function makeAttachmentStorageService(config: ResolvedLotaRuntimeConfig)
|
|
|
437
440
|
export class AttachmentStorageServiceTag extends Context.Service<
|
|
438
441
|
AttachmentStorageServiceTag,
|
|
439
442
|
ReturnType<typeof makeAttachmentStorageService>
|
|
440
|
-
>()('AttachmentStorageService') {}
|
|
443
|
+
>()('@lota-sdk/core/AttachmentStorageService') {}
|
|
441
444
|
|
|
442
445
|
export const AttachmentStorageServiceLive = Layer.effect(
|
|
443
446
|
AttachmentStorageServiceTag,
|
|
@@ -86,7 +86,7 @@ export function makeGeneratedDocumentStorageService(config: ResolvedLotaRuntimeC
|
|
|
86
86
|
export class GeneratedDocumentStorageServiceTag extends Context.Service<
|
|
87
87
|
GeneratedDocumentStorageServiceTag,
|
|
88
88
|
ReturnType<typeof makeGeneratedDocumentStorageService>
|
|
89
|
-
>()('GeneratedDocumentStorageService') {}
|
|
89
|
+
>()('@lota-sdk/core/GeneratedDocumentStorageService') {}
|
|
90
90
|
|
|
91
91
|
export const GeneratedDocumentStorageServiceLive = Layer.effect(
|
|
92
92
|
GeneratedDocumentStorageServiceTag,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
1
2
|
import { ToolLoopAgent } from 'ai'
|
|
2
3
|
|
|
3
4
|
import { aiGatewayChatModel } from '../ai-gateway/ai-gateway'
|
|
@@ -6,7 +7,6 @@ import {
|
|
|
6
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
7
8
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
8
9
|
} from '../config/model-constants'
|
|
9
|
-
import type { CreateHelperToolLoopAgentOptions } from '../runtime/agent-types'
|
|
10
10
|
import { resolveHelperAgentOptions } from './helper-agent-options'
|
|
11
11
|
|
|
12
12
|
const CONTEXT_COMPACTION_PROMPT = `<agent-instructions>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
1
2
|
import { ToolLoopAgent } from 'ai'
|
|
2
3
|
|
|
3
4
|
import { aiGatewayChatModel } from '../ai-gateway/ai-gateway'
|
|
@@ -6,7 +7,6 @@ import {
|
|
|
6
7
|
OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS,
|
|
7
8
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
8
9
|
} from '../config/model-constants'
|
|
9
|
-
import type { CreateHelperToolLoopAgentOptions } from '../runtime/agent-types'
|
|
10
10
|
import { resolveHelperAgentOptions } from './helper-agent-options'
|
|
11
11
|
|
|
12
12
|
export const MEMORY_RERANKER_PROMPT = `<agent-instructions>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
1
2
|
import { ToolLoopAgent } from 'ai'
|
|
2
3
|
|
|
3
4
|
import { aiGatewayChatModel } from '../ai-gateway/ai-gateway'
|
|
@@ -6,7 +7,6 @@ import {
|
|
|
6
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
7
8
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
8
9
|
} from '../config/model-constants'
|
|
9
|
-
import type { CreateHelperToolLoopAgentOptions } from '../runtime/agent-types'
|
|
10
10
|
import { resolveHelperAgentOptions } from './helper-agent-options'
|
|
11
11
|
|
|
12
12
|
export const ORG_MEMORY_PROMPT = `<agent-instructions>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
1
2
|
import { ToolLoopAgent } from 'ai'
|
|
2
3
|
|
|
3
4
|
import { aiGatewayChatModel } from '../ai-gateway/ai-gateway'
|
|
@@ -7,7 +8,6 @@ import {
|
|
|
7
8
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
8
9
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
9
10
|
} from '../config/model-constants'
|
|
10
|
-
import type { CreateHelperToolLoopAgentOptions } from '../runtime/agent-types'
|
|
11
11
|
import { resolveHelperAgentOptions } from './helper-agent-options'
|
|
12
12
|
|
|
13
13
|
const RECENT_ACTIVITY_TITLE_MAX_TOKENS = 256
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
1
2
|
import { ToolLoopAgent } from 'ai'
|
|
2
3
|
|
|
3
4
|
import { aiGatewayChatModel } from '../ai-gateway/ai-gateway'
|
|
@@ -6,7 +7,6 @@ import {
|
|
|
6
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
7
8
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
8
9
|
} from '../config/model-constants'
|
|
9
|
-
import type { CreateHelperToolLoopAgentOptions } from '../runtime/agent-types'
|
|
10
10
|
import { resolveHelperAgentOptions } from './helper-agent-options'
|
|
11
11
|
|
|
12
12
|
const REGULAR_CHAT_MEMORY_DIGEST_MAX_TOKENS = 8_192
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
1
2
|
import { ToolLoopAgent } from 'ai'
|
|
2
3
|
import { z } from 'zod'
|
|
3
4
|
|
|
@@ -7,7 +8,6 @@ import {
|
|
|
7
8
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
8
9
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
9
10
|
} from '../config/model-constants'
|
|
10
|
-
import type { CreateHelperToolLoopAgentOptions } from '../runtime/agent-types'
|
|
11
11
|
import { resolveHelperAgentOptions } from './helper-agent-options'
|
|
12
12
|
|
|
13
13
|
const SKILL_EXTRACTOR_MAX_TOKENS = 8_192
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
1
2
|
import { ToolLoopAgent } from 'ai'
|
|
2
3
|
import { z } from 'zod'
|
|
3
4
|
|
|
@@ -7,7 +8,6 @@ import {
|
|
|
7
8
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
8
9
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
9
10
|
} from '../config/model-constants'
|
|
10
|
-
import type { CreateHelperToolLoopAgentOptions } from '../runtime/agent-types'
|
|
11
11
|
import { resolveHelperAgentOptions } from './helper-agent-options'
|
|
12
12
|
|
|
13
13
|
const SKILL_MANAGER_MAX_TOKENS = 4_096
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
1
2
|
import { ToolLoopAgent } from 'ai'
|
|
2
3
|
|
|
3
4
|
import { aiGatewayChatModel } from '../ai-gateway/ai-gateway'
|
|
@@ -6,7 +7,6 @@ import {
|
|
|
6
7
|
OPENROUTER_FAST_REASONING_MODEL_ID,
|
|
7
8
|
OPENROUTER_MINIMAL_REASONING_PROVIDER_OPTIONS,
|
|
8
9
|
} from '../config/model-constants'
|
|
9
|
-
import type { CreateHelperToolLoopAgentOptions } from '../runtime/agent-types'
|
|
10
10
|
import { resolveHelperAgentOptions } from './helper-agent-options'
|
|
11
11
|
|
|
12
12
|
const THREAD_TITLE_MAX_TOKENS = 512
|
|
@@ -24,22 +24,31 @@ import { toValidationError } from '../effect/zod'
|
|
|
24
24
|
import type { makeExecutionPlanService } from '../services/execution-plan/execution-plan.service'
|
|
25
25
|
import type { makeThreadService } from '../services/thread/thread.service'
|
|
26
26
|
|
|
27
|
-
type
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
type NoContextService<TService> = {
|
|
28
|
+
[K in keyof TService]: TService[K] extends (...args: infer TArgs) => Effect.Effect<infer A, infer E, unknown>
|
|
29
|
+
? (...args: TArgs) => Effect.Effect<A, E, never>
|
|
30
|
+
: TService[K]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type ExecutionPlanThreadService = NoContextService<
|
|
34
|
+
Pick<ReturnType<typeof makeThreadService>, 'createThread' | 'deleteThread' | 'getThread'>
|
|
30
35
|
>
|
|
31
36
|
|
|
32
|
-
type ExecutionPlanExecutionPlanService =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
type ExecutionPlanExecutionPlanService = NoContextService<
|
|
38
|
+
Pick<
|
|
39
|
+
ReturnType<typeof makeExecutionPlanService>,
|
|
40
|
+
| 'createPlan'
|
|
41
|
+
| 'replacePlan'
|
|
42
|
+
| 'resumeRun'
|
|
43
|
+
| 'submitNodeResult'
|
|
44
|
+
| 'listActivePlanSummaries'
|
|
45
|
+
| 'getActivePlanToolResult'
|
|
46
|
+
| 'getActivePlansForThread'
|
|
47
|
+
>
|
|
41
48
|
>
|
|
42
49
|
|
|
50
|
+
type ExecutionPlanToolValidationError = ReturnType<typeof toValidationError>
|
|
51
|
+
|
|
43
52
|
export function createExecutionPlanTool(params: {
|
|
44
53
|
orgId: RecordIdRef
|
|
45
54
|
userId: RecordIdRef
|
|
@@ -198,12 +207,14 @@ export function createExecutionPlanTool(params: {
|
|
|
198
207
|
return result
|
|
199
208
|
}
|
|
200
209
|
}
|
|
201
|
-
}),
|
|
210
|
+
}).pipe(Effect.withSpan('tool.executionPlan.execute')),
|
|
202
211
|
),
|
|
203
212
|
})
|
|
204
213
|
}
|
|
205
214
|
|
|
206
|
-
function parseExecutionPlanArgsEffect(
|
|
215
|
+
function parseExecutionPlanArgsEffect(
|
|
216
|
+
input: unknown,
|
|
217
|
+
): Effect.Effect<ExecutionPlanArgs, ExecutionPlanToolValidationError> {
|
|
207
218
|
return Effect.gen(function* () {
|
|
208
219
|
const parsedArgs = ExecutionPlanArgsSchema.safeParse(input)
|
|
209
220
|
if (!parsedArgs.success) {
|
|
@@ -233,7 +244,7 @@ function parseExecutionPlanArgsEffect(input: unknown) {
|
|
|
233
244
|
|
|
234
245
|
function extractAgentPlanDraftEffect(
|
|
235
246
|
input: Extract<ExecutionPlanArgs, { action: 'create' | 'create-project' | 'replace' }>,
|
|
236
|
-
) {
|
|
247
|
+
): Effect.Effect<ReturnType<typeof expandAgentPlanDraft>, ExecutionPlanToolValidationError> {
|
|
237
248
|
return Effect.gen(function* () {
|
|
238
249
|
const parsedDraft = AgentPlanDraftSchema.safeParse({
|
|
239
250
|
title: input.title,
|
|
@@ -271,7 +282,7 @@ export function createExecutionPlanQueryTool(params: {
|
|
|
271
282
|
includeCheckpoints: input.includeCheckpoints,
|
|
272
283
|
includeValidationIssues: input.includeValidationIssues,
|
|
273
284
|
})
|
|
274
|
-
}),
|
|
285
|
+
}).pipe(Effect.withSpan('tool.executionPlanQuery.execute')),
|
|
275
286
|
),
|
|
276
287
|
})
|
|
277
288
|
}
|
|
@@ -296,7 +307,7 @@ export function createSubmitExecutionNodeResultTool(params: {
|
|
|
296
307
|
})
|
|
297
308
|
params.onPlanChanged?.()
|
|
298
309
|
return result
|
|
299
|
-
}),
|
|
310
|
+
}).pipe(Effect.withSpan('tool.submitExecutionNodeResult.execute')),
|
|
300
311
|
),
|
|
301
312
|
toModelOutput: ({ output }) => {
|
|
302
313
|
const result = getLatestExecutionPlanResult(output)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { tool } from 'ai'
|
|
2
|
-
import { Effect } from 'effect'
|
|
2
|
+
import { Effect, Schema } from 'effect'
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
|
|
5
5
|
import type { ToolDefinition } from '../ai/definitions'
|
|
@@ -10,6 +10,11 @@ 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
|
+
class FetchWebpageToolError extends Schema.TaggedErrorClass<FetchWebpageToolError>()(
|
|
14
|
+
'@lota-sdk/core/FetchWebpageToolError',
|
|
15
|
+
{ message: Schema.String, cause: Schema.optional(Schema.Defect) },
|
|
16
|
+
) {}
|
|
17
|
+
|
|
13
18
|
const FormatSchema = z.enum(['markdown', 'html', 'rawHtml', 'links', 'images', 'screenshot', 'summary'])
|
|
14
19
|
const MAX_MARKDOWN_CHARS = 6_000
|
|
15
20
|
const MAX_SUMMARY_CHARS = 1_200
|
|
@@ -119,19 +124,21 @@ export const fetchWebpageTool = {
|
|
|
119
124
|
|
|
120
125
|
return Effect.runPromise(
|
|
121
126
|
Effect.gen(function* () {
|
|
122
|
-
const result = yield* Effect.tryPromise(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
127
|
+
const result = yield* Effect.tryPromise({
|
|
128
|
+
try: () =>
|
|
129
|
+
withTimeout(
|
|
130
|
+
firecrawl.scrape(url, {
|
|
131
|
+
formats: formats?.length ? formats : ['markdown'],
|
|
132
|
+
onlyMainContent: onlyMainContent ?? true,
|
|
133
|
+
maxAge,
|
|
134
|
+
}),
|
|
135
|
+
WEB_TOOL_TIMEOUT_MS,
|
|
136
|
+
'Webpage fetch',
|
|
137
|
+
),
|
|
138
|
+
catch: (cause) => new FetchWebpageToolError({ message: `Webpage fetch failed for ${url}.`, cause }),
|
|
139
|
+
})
|
|
133
140
|
return { url, document: summarizeDocument(url, result), citations: buildFetchCitations(url, result) }
|
|
134
|
-
}),
|
|
141
|
+
}).pipe(Effect.withSpan('tool.fetchWebpage.execute')),
|
|
135
142
|
)
|
|
136
143
|
},
|
|
137
144
|
}),
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import Firecrawl from '@mendable/firecrawl-js'
|
|
2
2
|
import { Context, Effect, Layer } from 'effect'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { resolveLotaService } from '../effect/runtime'
|
|
5
5
|
import { RuntimeConfigServiceTag } from '../effect/services'
|
|
6
6
|
|
|
7
|
-
export class FirecrawlTag extends Context.Service<FirecrawlTag, Firecrawl>()('Firecrawl') {}
|
|
7
|
+
export class FirecrawlTag extends Context.Service<FirecrawlTag, Firecrawl>()('@lota-sdk/core/Firecrawl') {}
|
|
8
8
|
|
|
9
9
|
export const FirecrawlLive = Layer.effect(
|
|
10
10
|
FirecrawlTag,
|
|
@@ -17,6 +17,16 @@ export const FirecrawlLive = Layer.effect(
|
|
|
17
17
|
}),
|
|
18
18
|
)
|
|
19
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
|
+
|
|
20
30
|
export function getFirecrawlClient(): Firecrawl {
|
|
21
|
-
return
|
|
31
|
+
return currentFirecrawlClient ?? resolveLotaService(FirecrawlTag)
|
|
22
32
|
}
|
|
@@ -6,7 +6,15 @@ import type { RecordIdRef } from '../db/record-id'
|
|
|
6
6
|
import type { makeExecutionPlanService } from '../services/execution-plan/execution-plan.service'
|
|
7
7
|
import { toToolPlanSummary } from '../services/plan/plan-run-data'
|
|
8
8
|
|
|
9
|
-
type
|
|
9
|
+
type NoContextService<TService> = {
|
|
10
|
+
[K in keyof TService]: TService[K] extends (...args: infer TArgs) => Effect.Effect<infer A, infer E, unknown>
|
|
11
|
+
? (...args: TArgs) => Effect.Effect<A, E, never>
|
|
12
|
+
: TService[K]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type PlanApprovalExecutionPlanService = NoContextService<
|
|
16
|
+
Pick<ReturnType<typeof makeExecutionPlanService>, 'approvePlan' | 'rejectPlan'>
|
|
17
|
+
>
|
|
10
18
|
|
|
11
19
|
export function createPlanApprovalTool(params: {
|
|
12
20
|
orgId: RecordIdRef
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { tool } from 'ai'
|
|
2
|
-
import { Effect } from 'effect'
|
|
2
|
+
import { Effect, Schema } from 'effect'
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
|
|
5
5
|
import type { ToolDefinition } from '../ai/definitions'
|
|
@@ -10,6 +10,11 @@ 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
|
+
class SearchWebToolError extends Schema.TaggedErrorClass<SearchWebToolError>()('@lota-sdk/core/SearchWebToolError', {
|
|
14
|
+
message: Schema.String,
|
|
15
|
+
cause: Schema.optional(Schema.Defect),
|
|
16
|
+
}) {}
|
|
17
|
+
|
|
13
18
|
const SourceSchema = z.enum(['web', 'news', 'images'])
|
|
14
19
|
const MAX_RESULTS_PER_SOURCE = 4
|
|
15
20
|
const MAX_SNIPPET_CHARS = 320
|
|
@@ -159,13 +164,15 @@ export const searchWebTool = {
|
|
|
159
164
|
|
|
160
165
|
return Effect.runPromise(
|
|
161
166
|
Effect.gen(function* () {
|
|
162
|
-
const results = yield* Effect.tryPromise(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
const results = yield* Effect.tryPromise({
|
|
168
|
+
try: () =>
|
|
169
|
+
withTimeout(
|
|
170
|
+
firecrawl.search(query, { limit, sources, location, tbs }),
|
|
171
|
+
WEB_TOOL_TIMEOUT_MS,
|
|
172
|
+
'Web search',
|
|
173
|
+
),
|
|
174
|
+
catch: (cause) => new SearchWebToolError({ message: 'Web search request failed.', cause }),
|
|
175
|
+
})
|
|
169
176
|
return {
|
|
170
177
|
query,
|
|
171
178
|
results: {
|
|
@@ -175,7 +182,7 @@ export const searchWebTool = {
|
|
|
175
182
|
},
|
|
176
183
|
citations: buildWebCitations(results),
|
|
177
184
|
}
|
|
178
|
-
}),
|
|
185
|
+
}).pipe(Effect.withSpan('tool.searchWeb.execute')),
|
|
179
186
|
)
|
|
180
187
|
},
|
|
181
188
|
}),
|
|
@@ -161,7 +161,7 @@ export function createTeamThinkTool(params: {
|
|
|
161
161
|
aiLogger.error`Team-think participant failed (${agentId}): ${error}`
|
|
162
162
|
},
|
|
163
163
|
recordAbort: (error: unknown) => {
|
|
164
|
-
aiLogger.
|
|
164
|
+
aiLogger.debug`Team-think participant aborted (${agentId}): ${
|
|
165
165
|
error instanceof Error ? error.message : String(error)
|
|
166
166
|
}`
|
|
167
167
|
},
|
|
@@ -170,7 +170,7 @@ export function createTeamThinkTool(params: {
|
|
|
170
170
|
agent: agent as Awaited<ReturnType<TeamConsultationParticipantRunner['buildParticipantAgent']>>['agent'],
|
|
171
171
|
observer,
|
|
172
172
|
}
|
|
173
|
-
}),
|
|
173
|
+
}).pipe(Effect.withSpan('tool.teamThink.buildParticipantAgent')),
|
|
174
174
|
)
|
|
175
175
|
},
|
|
176
176
|
}
|
package/src/utils/async.ts
CHANGED
|
@@ -1,24 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Cause, Duration, Effect, Exit, Schema } from 'effect'
|
|
2
2
|
|
|
3
3
|
import { serverLogger } from '../config/logger'
|
|
4
4
|
import { TimeoutError } from '../effect/errors'
|
|
5
|
-
import { getErrorMessage } from './errors'
|
|
5
|
+
import { getErrorMessage, toError } from './errors'
|
|
6
6
|
|
|
7
7
|
class TimedOperationError extends Schema.TaggedErrorClass<TimedOperationError>()('TimedOperationError', {
|
|
8
8
|
operation: Schema.String,
|
|
9
9
|
cause: Schema.Defect,
|
|
10
10
|
}) {}
|
|
11
11
|
|
|
12
|
+
function isTimedOperationError(error: unknown): error is TimedOperationError {
|
|
13
|
+
return typeof error === 'object' && error !== null && '_tag' in error && error._tag === 'TimedOperationError'
|
|
14
|
+
}
|
|
15
|
+
|
|
12
16
|
export function withTimeout<T>(promise: Promise<T>, ms: number, operation: string): Promise<T> {
|
|
13
17
|
return Effect.runPromise(
|
|
14
18
|
Effect.tryPromise({ try: () => promise, catch: (cause) => new TimedOperationError({ operation, cause }) }).pipe(
|
|
15
19
|
Effect.timeout(Duration.millis(ms)),
|
|
16
20
|
Effect.catchTag('TimeoutError', () => Effect.fail(new TimeoutError({ operation, ms }))),
|
|
17
|
-
Effect.
|
|
18
|
-
Effect.fail(error.cause instanceof Error ? error.cause : new Error(String(error.cause))),
|
|
19
|
-
),
|
|
21
|
+
Effect.exit,
|
|
20
22
|
),
|
|
21
|
-
)
|
|
23
|
+
).then((exit) => {
|
|
24
|
+
if (Exit.isSuccess(exit)) {
|
|
25
|
+
return exit.value
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const error = Cause.squash(exit.cause)
|
|
29
|
+
throw isTimedOperationError(error) ? toError(error.cause) : error
|
|
30
|
+
})
|
|
22
31
|
}
|
|
23
32
|
|
|
24
33
|
export function createSafeEnqueue(logger: { warn: (message: string) => void }) {
|
package/src/utils/errors.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { getErrorMessage } from '@lota-sdk/shared'
|
|
2
|
-
import { Match } from 'effect'
|
|
2
|
+
import { Data, Match } from 'effect'
|
|
3
3
|
|
|
4
4
|
import type { EffectError, ValidationIssue } from '../effect/errors'
|
|
5
5
|
import { BaseServicePersistenceError, isEffectError } from '../effect/errors'
|
|
@@ -19,18 +19,16 @@ export interface AppErrorResponse {
|
|
|
19
19
|
body: { error: { code: string; message: string } }
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export type AppErrorLike = Error & { code: string; statusCode: number; toResponse?: () =>
|
|
22
|
+
export type AppErrorLike = Error & { code: string; statusCode: number; toResponse?: () => unknown }
|
|
23
23
|
|
|
24
|
-
export class AppError extends Error
|
|
24
|
+
export class AppError extends Data.Error<{
|
|
25
|
+
readonly message: string
|
|
25
26
|
readonly code: string
|
|
26
27
|
readonly statusCode: number
|
|
27
|
-
|
|
28
|
+
}> {
|
|
28
29
|
constructor(message: string, code: string, statusCode: number) {
|
|
29
|
-
super(message)
|
|
30
|
+
super({ message, code, statusCode })
|
|
30
31
|
this.name = new.target.name
|
|
31
|
-
this.code = code
|
|
32
|
-
this.statusCode = statusCode
|
|
33
|
-
Object.setPrototypeOf(this, new.target.prototype)
|
|
34
32
|
}
|
|
35
33
|
|
|
36
34
|
toResponse(): AppErrorResponse {
|
|
@@ -99,16 +97,30 @@ export function isAppErrorLike(error: unknown): error is AppErrorLike {
|
|
|
99
97
|
return typeof candidate.code === 'string' && typeof candidate.statusCode === 'number'
|
|
100
98
|
}
|
|
101
99
|
|
|
100
|
+
function isAppErrorResponse(value: unknown): value is AppErrorResponse {
|
|
101
|
+
if (typeof value !== 'object' || value === null) {
|
|
102
|
+
return false
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const candidate = value as {
|
|
106
|
+
status?: unknown
|
|
107
|
+
body?: { error?: { code?: unknown; message?: unknown } | null } | null
|
|
108
|
+
}
|
|
109
|
+
return (
|
|
110
|
+
typeof candidate.status === 'number' &&
|
|
111
|
+
typeof candidate.body === 'object' &&
|
|
112
|
+
candidate.body !== null &&
|
|
113
|
+
typeof candidate.body.error === 'object' &&
|
|
114
|
+
candidate.body.error !== null &&
|
|
115
|
+
typeof candidate.body.error.code === 'string' &&
|
|
116
|
+
typeof candidate.body.error.message === 'string'
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
102
120
|
export function toAppErrorResponse(error: AppErrorLike): AppErrorResponse {
|
|
103
121
|
if (typeof error.toResponse === 'function') {
|
|
104
122
|
const response = error.toResponse()
|
|
105
|
-
if (
|
|
106
|
-
response &&
|
|
107
|
-
typeof response === 'object' &&
|
|
108
|
-
typeof response.status === 'number' &&
|
|
109
|
-
response.body &&
|
|
110
|
-
typeof response.body === 'object'
|
|
111
|
-
) {
|
|
123
|
+
if (isAppErrorResponse(response)) {
|
|
112
124
|
return response
|
|
113
125
|
}
|
|
114
126
|
}
|