@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
|
@@ -13,17 +13,24 @@ import {
|
|
|
13
13
|
} from '@lota-sdk/shared'
|
|
14
14
|
import type { CreateProjectWithPlanResultData, ExecutionPlanArgs } from '@lota-sdk/shared'
|
|
15
15
|
import { tool } from 'ai'
|
|
16
|
+
import { Effect } from 'effect'
|
|
16
17
|
|
|
18
|
+
import { serverLogger } from '../config/logger'
|
|
17
19
|
import type { RecordIdRef } from '../db/record-id'
|
|
18
20
|
import { recordIdToString } from '../db/record-id'
|
|
19
21
|
import { TABLES } from '../db/tables'
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
+
import { BadRequestError, ConflictError, ForbiddenError } from '../effect/errors'
|
|
23
|
+
import { toValidationError } from '../effect/zod'
|
|
24
|
+
import type { makeExecutionPlanService } from '../services/execution-plan/execution-plan.service'
|
|
25
|
+
import type { makeThreadService } from '../services/thread/thread.service'
|
|
22
26
|
|
|
23
|
-
type ExecutionPlanThreadService = Pick<
|
|
27
|
+
type ExecutionPlanThreadService = Pick<
|
|
28
|
+
ReturnType<typeof makeThreadService>,
|
|
29
|
+
'createThread' | 'deleteThread' | 'getThread'
|
|
30
|
+
>
|
|
24
31
|
|
|
25
32
|
type ExecutionPlanExecutionPlanService = Pick<
|
|
26
|
-
typeof
|
|
33
|
+
ReturnType<typeof makeExecutionPlanService>,
|
|
27
34
|
| 'createPlan'
|
|
28
35
|
| 'replacePlan'
|
|
29
36
|
| 'resumeRun'
|
|
@@ -38,207 +45,259 @@ export function createExecutionPlanTool(params: {
|
|
|
38
45
|
userId: RecordIdRef
|
|
39
46
|
threadId: RecordIdRef
|
|
40
47
|
agentId: string
|
|
41
|
-
executionPlanService
|
|
42
|
-
threadService
|
|
48
|
+
executionPlanService: ExecutionPlanExecutionPlanService
|
|
49
|
+
threadService: ExecutionPlanThreadService
|
|
43
50
|
onPlanChanged?: () => void
|
|
44
51
|
validateInlinePlan?: (draft: ReturnType<typeof expandAgentPlanDraft>) => void
|
|
45
52
|
}) {
|
|
46
|
-
const resolvedEpService = params.executionPlanService ?? executionPlanService
|
|
47
|
-
const resolvedWsService = params.threadService ?? threadService
|
|
48
|
-
|
|
49
53
|
return tool({
|
|
50
54
|
description:
|
|
51
55
|
'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).',
|
|
52
56
|
inputSchema: ExecutionPlanArgsSchema,
|
|
53
|
-
execute:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
57
|
+
execute: (input) =>
|
|
58
|
+
Effect.runPromise(
|
|
59
|
+
Effect.gen(function* () {
|
|
60
|
+
const parsed = yield* parseExecutionPlanArgsEffect(input)
|
|
61
|
+
|
|
62
|
+
switch (parsed.action) {
|
|
63
|
+
case 'create': {
|
|
64
|
+
const draft = yield* extractAgentPlanDraftEffect(parsed)
|
|
65
|
+
params.validateInlinePlan?.(draft)
|
|
66
|
+
const targetThreadId = parsed.targetThreadId ?? params.threadId
|
|
67
|
+
const isCrossThreadTarget =
|
|
68
|
+
recordIdToString(targetThreadId, TABLES.THREAD) !== recordIdToString(params.threadId, TABLES.THREAD)
|
|
69
|
+
const result = yield* params.executionPlanService.createPlan({
|
|
70
|
+
organizationId: params.orgId,
|
|
71
|
+
threadId: targetThreadId,
|
|
72
|
+
...(isCrossThreadTarget ? { sourceThreadId: params.threadId } : {}),
|
|
73
|
+
leadAgentId: params.agentId,
|
|
74
|
+
createdByAgentId: params.agentId,
|
|
75
|
+
requireApproval: parsed.requireApproval ?? isCrossThreadTarget,
|
|
76
|
+
input: draft,
|
|
77
|
+
})
|
|
78
|
+
params.onPlanChanged?.()
|
|
79
|
+
return result
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
case 'create-project': {
|
|
83
|
+
const draft = yield* extractAgentPlanDraftEffect(parsed)
|
|
84
|
+
let createdThreadId: string | null = null
|
|
85
|
+
|
|
86
|
+
const cleanupLeakedThread = (threadId: string) =>
|
|
87
|
+
params.threadService.deleteThread(threadId).pipe(
|
|
88
|
+
Effect.catch((cleanupError: unknown) =>
|
|
89
|
+
Effect.sync(() => {
|
|
90
|
+
serverLogger.warn`Failed to clean up leaked execution-plan project thread ${threadId}: ${cleanupError}`
|
|
91
|
+
}),
|
|
92
|
+
),
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
const projectEffect = Effect.gen(function* () {
|
|
96
|
+
const projectTitle = parsed.projectTitle
|
|
97
|
+
const targetThreadId = parsed.targetThreadId
|
|
98
|
+
const targetThread = targetThreadId
|
|
99
|
+
? yield* params.threadService.getThread(targetThreadId)
|
|
100
|
+
: yield* (() => {
|
|
101
|
+
if (!projectTitle) {
|
|
102
|
+
return new BadRequestError({
|
|
103
|
+
message: 'projectTitle is required when action is "create-project".',
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return params.threadService.createThread({
|
|
108
|
+
userId: params.userId,
|
|
109
|
+
organizationId: params.orgId,
|
|
110
|
+
title: projectTitle,
|
|
111
|
+
type: 'group',
|
|
112
|
+
})
|
|
113
|
+
})()
|
|
114
|
+
|
|
115
|
+
if (!parsed.targetThreadId) {
|
|
116
|
+
createdThreadId = targetThread.id
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (targetThread.organizationId !== recordIdToString(params.orgId, TABLES.ORGANIZATION)) {
|
|
120
|
+
return yield* new ForbiddenError({ message: 'Target thread belongs to a different organization.' })
|
|
121
|
+
}
|
|
122
|
+
if (targetThread.userId !== recordIdToString(params.userId, TABLES.USER)) {
|
|
123
|
+
return yield* new ForbiddenError({ message: 'Target thread belongs to a different user.' })
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const existingPlans = yield* params.executionPlanService.getActivePlansForThread(targetThread.id)
|
|
127
|
+
if (targetThread.type !== 'thread' && existingPlans.length > 0) {
|
|
128
|
+
return yield* new ConflictError({
|
|
129
|
+
message:
|
|
130
|
+
'This thread already has an active execution plan. Use action "replace" or target a core thread.',
|
|
131
|
+
})
|
|
83
132
|
}
|
|
84
133
|
|
|
85
|
-
|
|
86
|
-
userId: params.userId,
|
|
134
|
+
const created = yield* params.executionPlanService.createPlan({
|
|
87
135
|
organizationId: params.orgId,
|
|
88
|
-
|
|
89
|
-
|
|
136
|
+
threadId: targetThread.id,
|
|
137
|
+
sourceThreadId: params.threadId,
|
|
138
|
+
leadAgentId: params.agentId,
|
|
139
|
+
createdByAgentId: params.agentId,
|
|
140
|
+
requireApproval: parsed.requireApproval ?? true,
|
|
141
|
+
input: draft,
|
|
90
142
|
})
|
|
91
|
-
})()
|
|
92
|
-
|
|
93
|
-
if (targetThread.organizationId !== recordIdToString(params.orgId, TABLES.ORGANIZATION)) {
|
|
94
|
-
throw new Error('Target thread belongs to a different organization.')
|
|
95
|
-
}
|
|
96
|
-
if (targetThread.userId !== recordIdToString(params.userId, TABLES.USER)) {
|
|
97
|
-
throw new Error('Target thread belongs to a different user.')
|
|
98
|
-
}
|
|
99
143
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
144
|
+
const result = {
|
|
145
|
+
...created,
|
|
146
|
+
runId: created.plan?.runId ?? '',
|
|
147
|
+
threadId: targetThread.id,
|
|
148
|
+
threadTitle: targetThread.title,
|
|
149
|
+
createdThread: createdThreadId !== null,
|
|
150
|
+
} satisfies CreateProjectWithPlanResultData
|
|
151
|
+
params.onPlanChanged?.()
|
|
152
|
+
return result
|
|
153
|
+
}).pipe(Effect.tapError(() => (createdThreadId ? cleanupLeakedThread(createdThreadId) : Effect.void)))
|
|
106
154
|
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
const created = await resolvedEpService.createPlan({
|
|
110
|
-
organizationId: params.orgId,
|
|
111
|
-
threadId: targetThread.id,
|
|
112
|
-
sourceThreadId: params.threadId,
|
|
113
|
-
leadAgentId: params.agentId,
|
|
114
|
-
createdByAgentId: params.agentId,
|
|
115
|
-
requireApproval: parsed.requireApproval ?? true,
|
|
116
|
-
input: draft,
|
|
117
|
-
})
|
|
118
|
-
result = {
|
|
119
|
-
...created,
|
|
120
|
-
runId: created.plan?.runId ?? '',
|
|
121
|
-
threadId: targetThread.id,
|
|
122
|
-
threadTitle: targetThread.title,
|
|
123
|
-
createdThread,
|
|
124
|
-
} satisfies CreateProjectWithPlanResultData
|
|
125
|
-
} catch (error) {
|
|
126
|
-
if (createdThread) {
|
|
127
|
-
await resolvedWsService.deleteThread(targetThread.id).catch(() => {})
|
|
155
|
+
return yield* projectEffect
|
|
128
156
|
}
|
|
129
|
-
throw error
|
|
130
|
-
}
|
|
131
|
-
break
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
case 'replace': {
|
|
135
|
-
const draft = extractAgentPlanDraft(parsed)
|
|
136
|
-
result = await resolvedEpService.replacePlan({
|
|
137
|
-
organizationId: params.orgId,
|
|
138
|
-
threadId: params.threadId,
|
|
139
|
-
leadAgentId: params.agentId,
|
|
140
|
-
createdByAgentId: params.agentId,
|
|
141
|
-
input: { runId: parsed.runId, reason: parsed.reason, requireApproval: parsed.requireApproval, ...draft },
|
|
142
|
-
})
|
|
143
|
-
break
|
|
144
|
-
}
|
|
145
157
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
158
|
+
case 'replace': {
|
|
159
|
+
const draft = yield* extractAgentPlanDraftEffect(parsed)
|
|
160
|
+
const result = yield* params.executionPlanService.replacePlan({
|
|
161
|
+
organizationId: params.orgId,
|
|
162
|
+
threadId: params.threadId,
|
|
163
|
+
leadAgentId: params.agentId,
|
|
164
|
+
createdByAgentId: params.agentId,
|
|
165
|
+
input: {
|
|
166
|
+
runId: parsed.runId,
|
|
167
|
+
reason: parsed.reason,
|
|
168
|
+
requireApproval: parsed.requireApproval,
|
|
169
|
+
...draft,
|
|
170
|
+
},
|
|
171
|
+
})
|
|
172
|
+
params.onPlanChanged?.()
|
|
173
|
+
return result
|
|
174
|
+
}
|
|
153
175
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
},
|
|
164
|
-
})
|
|
165
|
-
break
|
|
166
|
-
}
|
|
176
|
+
case 'resume': {
|
|
177
|
+
const result = yield* params.executionPlanService.resumeRun({
|
|
178
|
+
threadId: params.threadId,
|
|
179
|
+
emittedBy: params.agentId,
|
|
180
|
+
input: { runId: parsed.runId },
|
|
181
|
+
})
|
|
182
|
+
params.onPlanChanged?.()
|
|
183
|
+
return result
|
|
184
|
+
}
|
|
167
185
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
186
|
+
case 'update-node': {
|
|
187
|
+
const result = yield* params.executionPlanService.submitNodeResult({
|
|
188
|
+
threadId: params.threadId,
|
|
189
|
+
emittedBy: params.agentId,
|
|
190
|
+
input: {
|
|
191
|
+
runId: parsed.runId,
|
|
192
|
+
nodeId: parsed.node.id,
|
|
193
|
+
notes: parsed.node.latestNotes,
|
|
194
|
+
artifacts: parsed.node.deliverables ?? [],
|
|
195
|
+
},
|
|
196
|
+
})
|
|
197
|
+
params.onPlanChanged?.()
|
|
198
|
+
return result
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}),
|
|
202
|
+
),
|
|
171
203
|
})
|
|
172
204
|
}
|
|
173
205
|
|
|
174
|
-
function
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
206
|
+
function parseExecutionPlanArgsEffect(input: unknown) {
|
|
207
|
+
return Effect.gen(function* () {
|
|
208
|
+
const parsedArgs = ExecutionPlanArgsSchema.safeParse(input)
|
|
209
|
+
if (!parsedArgs.success) {
|
|
210
|
+
return yield* toValidationError(parsedArgs.error, 'Invalid execution plan tool input')
|
|
211
|
+
}
|
|
212
|
+
const parsed = parsedArgs.data
|
|
213
|
+
|
|
214
|
+
const parseAction = <T>(result: { success: true; data: T } | { success: false; error: unknown }) =>
|
|
215
|
+
result.success
|
|
216
|
+
? Effect.succeed(result.data)
|
|
217
|
+
: Effect.fail(toValidationError(result.error, 'Invalid execution plan action input'))
|
|
218
|
+
|
|
219
|
+
switch (parsed.action) {
|
|
220
|
+
case 'create':
|
|
221
|
+
return yield* parseAction(ExecutionPlanCreateArgsSchema.safeParse(parsed))
|
|
222
|
+
case 'create-project':
|
|
223
|
+
return yield* parseAction(ExecutionPlanCreateProjectArgsSchema.safeParse(parsed))
|
|
224
|
+
case 'replace':
|
|
225
|
+
return yield* parseAction(ExecutionPlanReplaceArgsSchema.safeParse(parsed))
|
|
226
|
+
case 'resume':
|
|
227
|
+
return yield* parseAction(ExecutionPlanResumeArgsSchema.safeParse(parsed))
|
|
228
|
+
case 'update-node':
|
|
229
|
+
return yield* parseAction(ExecutionPlanUpdateNodeArgsSchema.safeParse(parsed))
|
|
230
|
+
}
|
|
231
|
+
})
|
|
189
232
|
}
|
|
190
233
|
|
|
191
|
-
function
|
|
192
|
-
|
|
193
|
-
|
|
234
|
+
function extractAgentPlanDraftEffect(
|
|
235
|
+
input: Extract<ExecutionPlanArgs, { action: 'create' | 'create-project' | 'replace' }>,
|
|
236
|
+
) {
|
|
237
|
+
return Effect.gen(function* () {
|
|
238
|
+
const parsedDraft = AgentPlanDraftSchema.safeParse({
|
|
194
239
|
title: input.title,
|
|
195
240
|
objective: input.objective,
|
|
196
241
|
nodes: input.nodes,
|
|
197
242
|
edges: input.edges,
|
|
198
|
-
})
|
|
199
|
-
|
|
243
|
+
})
|
|
244
|
+
if (!parsedDraft.success) {
|
|
245
|
+
return yield* toValidationError(parsedDraft.error, 'Invalid execution plan draft')
|
|
246
|
+
}
|
|
247
|
+
return expandAgentPlanDraft(parsedDraft.data)
|
|
248
|
+
})
|
|
200
249
|
}
|
|
201
250
|
|
|
202
|
-
export function createExecutionPlanQueryTool(params: {
|
|
251
|
+
export function createExecutionPlanQueryTool(params: {
|
|
252
|
+
threadId: RecordIdRef
|
|
253
|
+
executionPlanService: Pick<ExecutionPlanExecutionPlanService, 'listActivePlanSummaries' | 'getActivePlanToolResult'>
|
|
254
|
+
}) {
|
|
203
255
|
return tool({
|
|
204
256
|
description:
|
|
205
257
|
'Query execution plans. Omit runId to list all active plans. Provide runId to load a specific plan run.',
|
|
206
258
|
inputSchema: ExecutionPlanQueryArgsSchema,
|
|
207
|
-
execute:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
259
|
+
execute: (input) =>
|
|
260
|
+
Effect.runPromise(
|
|
261
|
+
Effect.gen(function* () {
|
|
262
|
+
if (!input.runId) {
|
|
263
|
+
return yield* params.executionPlanService.listActivePlanSummaries(params.threadId)
|
|
264
|
+
}
|
|
265
|
+
return yield* params.executionPlanService.getActivePlanToolResult({
|
|
266
|
+
threadId: params.threadId,
|
|
267
|
+
runId: input.runId,
|
|
268
|
+
includeEvents: input.includeEvents,
|
|
269
|
+
includeArtifacts: input.includeArtifacts,
|
|
270
|
+
includeApprovals: input.includeApprovals,
|
|
271
|
+
includeCheckpoints: input.includeCheckpoints,
|
|
272
|
+
includeValidationIssues: input.includeValidationIssues,
|
|
273
|
+
})
|
|
274
|
+
}),
|
|
275
|
+
),
|
|
221
276
|
})
|
|
222
277
|
}
|
|
223
278
|
|
|
224
279
|
export function createSubmitExecutionNodeResultTool(params: {
|
|
225
280
|
threadId: RecordIdRef
|
|
226
281
|
agentId: string
|
|
282
|
+
executionPlanService: Pick<ExecutionPlanExecutionPlanService, 'submitNodeResult'>
|
|
227
283
|
onPlanChanged?: () => void
|
|
228
284
|
}) {
|
|
229
285
|
return tool({
|
|
230
286
|
description:
|
|
231
287
|
'Submit the result for the currently running execution node. The executor validates outputs, artifacts, and completion checks before advancing the run.',
|
|
232
288
|
inputSchema: SubmitExecutionNodeResultArgsSchema,
|
|
233
|
-
execute:
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
289
|
+
execute: (input) =>
|
|
290
|
+
Effect.runPromise(
|
|
291
|
+
Effect.gen(function* () {
|
|
292
|
+
const result = yield* params.executionPlanService.submitNodeResult({
|
|
293
|
+
threadId: params.threadId,
|
|
294
|
+
emittedBy: params.agentId,
|
|
295
|
+
input,
|
|
296
|
+
})
|
|
297
|
+
params.onPlanChanged?.()
|
|
298
|
+
return result
|
|
299
|
+
}),
|
|
300
|
+
),
|
|
242
301
|
toModelOutput: ({ output }) => {
|
|
243
302
|
const result = getLatestExecutionPlanResult(output)
|
|
244
303
|
const summary = result?.message?.trim()
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
import { tool } from 'ai'
|
|
2
|
+
import { Effect } from 'effect'
|
|
2
3
|
import { z } from 'zod'
|
|
3
4
|
|
|
4
5
|
import type { ToolDefinition } from '../ai/definitions'
|
|
5
6
|
import { withTimeout } from '../utils/async'
|
|
7
|
+
import { nowIsoDateTimeString } from '../utils/date-time'
|
|
6
8
|
import { readStringField, truncateOptionalText } from '../utils/string'
|
|
7
9
|
import { getFirecrawlClient } from './firecrawl-client'
|
|
8
10
|
import type { WebCitation } from './tool-contracts'
|
|
11
|
+
import { toRecord, WEB_TOOL_TIMEOUT_MS } from './web-tool-shared'
|
|
9
12
|
|
|
10
|
-
const TOOL_TIMEOUT_MS = 30_000
|
|
11
13
|
const FormatSchema = z.enum(['markdown', 'html', 'rawHtml', 'links', 'images', 'screenshot', 'summary'])
|
|
12
14
|
const MAX_MARKDOWN_CHARS = 6_000
|
|
13
15
|
const MAX_SUMMARY_CHARS = 1_200
|
|
14
16
|
const MAX_LINKS = 25
|
|
15
17
|
const MAX_IMAGES = 10
|
|
16
18
|
|
|
17
|
-
function toRecord(value: unknown): Record<string, unknown> | null {
|
|
18
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) return null
|
|
19
|
-
return value as Record<string, unknown>
|
|
20
|
-
}
|
|
21
|
-
|
|
22
19
|
function readStringList(record: Record<string, unknown>, key: string, maxItems: number): string[] {
|
|
23
20
|
const value = record[key]
|
|
24
21
|
if (!Array.isArray(value)) return []
|
|
@@ -91,7 +88,7 @@ function buildFetchCitations(url: string, document: unknown): WebCitation[] {
|
|
|
91
88
|
}
|
|
92
89
|
}
|
|
93
90
|
|
|
94
|
-
return [{ source: 'web', sourceId, retrievedAt:
|
|
91
|
+
return [{ source: 'web', sourceId, retrievedAt: nowIsoDateTimeString() }]
|
|
95
92
|
}
|
|
96
93
|
|
|
97
94
|
export const fetchWebpageTool = {
|
|
@@ -107,7 +104,7 @@ export const fetchWebpageTool = {
|
|
|
107
104
|
maxAge: z.number().int().min(1).optional(),
|
|
108
105
|
})
|
|
109
106
|
.strict(),
|
|
110
|
-
execute:
|
|
107
|
+
execute: ({
|
|
111
108
|
url,
|
|
112
109
|
formats,
|
|
113
110
|
onlyMainContent,
|
|
@@ -118,17 +115,24 @@ export const fetchWebpageTool = {
|
|
|
118
115
|
onlyMainContent?: boolean
|
|
119
116
|
maxAge?: number
|
|
120
117
|
}) => {
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
118
|
+
const firecrawl = getFirecrawlClient()
|
|
119
|
+
|
|
120
|
+
return Effect.runPromise(
|
|
121
|
+
Effect.gen(function* () {
|
|
122
|
+
const result = yield* Effect.tryPromise(() =>
|
|
123
|
+
withTimeout(
|
|
124
|
+
firecrawl.scrape(url, {
|
|
125
|
+
formats: formats?.length ? formats : ['markdown'],
|
|
126
|
+
onlyMainContent: onlyMainContent ?? true,
|
|
127
|
+
maxAge,
|
|
128
|
+
}),
|
|
129
|
+
WEB_TOOL_TIMEOUT_MS,
|
|
130
|
+
'Webpage fetch',
|
|
131
|
+
),
|
|
132
|
+
)
|
|
133
|
+
return { url, document: summarizeDocument(url, result), citations: buildFetchCitations(url, result) }
|
|
126
134
|
}),
|
|
127
|
-
TOOL_TIMEOUT_MS,
|
|
128
|
-
'Webpage fetch',
|
|
129
135
|
)
|
|
130
|
-
|
|
131
|
-
return { url, document: summarizeDocument(url, result), citations: buildFetchCitations(url, result) }
|
|
132
136
|
},
|
|
133
137
|
}),
|
|
134
138
|
} as const satisfies ToolDefinition<void>
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import Firecrawl from '@mendable/firecrawl-js'
|
|
2
|
+
import { Context, Effect, Layer } from 'effect'
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import { getCurrentRuntime } from '../effect/runtime-ref'
|
|
5
|
+
import { RuntimeConfigServiceTag } from '../effect/services'
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
export class FirecrawlTag extends Context.Service<FirecrawlTag, Firecrawl>()('Firecrawl') {}
|
|
8
|
+
|
|
9
|
+
export const FirecrawlLive = Layer.effect(
|
|
10
|
+
FirecrawlTag,
|
|
11
|
+
Effect.gen(function* () {
|
|
12
|
+
const config = yield* RuntimeConfigServiceTag
|
|
13
|
+
return new Firecrawl({
|
|
14
|
+
apiKey: config.firecrawl.apiKey,
|
|
15
|
+
...(config.firecrawl.apiBaseUrl ? { apiUrl: config.firecrawl.apiBaseUrl } : {}),
|
|
16
|
+
})
|
|
17
|
+
}),
|
|
18
|
+
)
|
|
6
19
|
|
|
7
20
|
export function getFirecrawlClient(): Firecrawl {
|
|
8
|
-
|
|
9
|
-
_firecrawlClient = new Firecrawl({ apiKey: getRuntimeConfig().firecrawl.apiKey })
|
|
10
|
-
}
|
|
11
|
-
return _firecrawlClient
|
|
21
|
+
return getCurrentRuntime().runSync(Effect.service(FirecrawlTag))
|
|
12
22
|
}
|
package/src/tools/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { tool } from 'ai'
|
|
2
|
+
import { Effect } from 'effect'
|
|
2
3
|
import { z } from 'zod'
|
|
3
4
|
|
|
4
5
|
import type { RecordIdRef } from '../db/record-id'
|
|
@@ -7,18 +8,22 @@ import {
|
|
|
7
8
|
normalizeMemoryBlockEntry,
|
|
8
9
|
prepareMemoryBlockAppend,
|
|
9
10
|
validateMemoryBlockEntry,
|
|
10
|
-
} from '../runtime/memory-block'
|
|
11
|
-
import {
|
|
11
|
+
} from '../runtime/memory/memory-block'
|
|
12
|
+
import type { makeThreadService } from '../services/thread/thread.service'
|
|
12
13
|
import { safeEnqueue } from '../utils/async'
|
|
13
14
|
|
|
15
|
+
type MemoryBlockThreadService = Pick<ReturnType<typeof makeThreadService>, 'appendMemoryBlock'>
|
|
16
|
+
|
|
14
17
|
export function createMemoryBlockTool({
|
|
15
18
|
threadId,
|
|
16
19
|
agentLabel,
|
|
20
|
+
threadService,
|
|
17
21
|
getCurrentBlock,
|
|
18
22
|
onAppend,
|
|
19
23
|
}: {
|
|
20
24
|
threadId: RecordIdRef
|
|
21
25
|
agentLabel: string
|
|
26
|
+
threadService: MemoryBlockThreadService
|
|
22
27
|
getCurrentBlock?: () => string
|
|
23
28
|
onAppend?: (value: string) => void
|
|
24
29
|
}) {
|
|
@@ -42,10 +47,13 @@ export function createMemoryBlockTool({
|
|
|
42
47
|
onAppend?.(prepared.optimisticBlock)
|
|
43
48
|
|
|
44
49
|
void safeEnqueue(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
() =>
|
|
51
|
+
Effect.runPromise(
|
|
52
|
+
Effect.gen(function* () {
|
|
53
|
+
const updated = yield* threadService.appendMemoryBlock(threadId, prepared.formatted)
|
|
54
|
+
onAppend?.(updated)
|
|
55
|
+
}),
|
|
56
|
+
),
|
|
49
57
|
{ operationName: 'append memory block entry', logPrefix: 'Background memoryBlockAppend task failed' },
|
|
50
58
|
)
|
|
51
59
|
|