@lota-sdk/core 0.4.8 → 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 +11 -12
- package/src/ai/embedding-cache.ts +96 -22
- package/src/ai-gateway/ai-gateway.ts +766 -223
- package/src/config/agent-defaults.ts +189 -75
- package/src/config/agent-types.ts +54 -4
- package/src/config/background-processing.ts +1 -1
- package/src/config/constants.ts +8 -2
- package/src/config/index.ts +0 -1
- package/src/config/logger.ts +299 -19
- package/src/config/thread-defaults.ts +40 -20
- package/src/create-runtime.ts +200 -449
- package/src/db/base.service.ts +52 -28
- package/src/db/cursor-pagination.ts +71 -30
- package/src/db/memory-query-builder.ts +2 -1
- package/src/db/memory-store.helpers.ts +4 -7
- package/src/db/memory-store.ts +868 -601
- package/src/db/memory.ts +396 -280
- package/src/db/record-id.ts +32 -10
- package/src/db/schema-fingerprint.ts +30 -12
- package/src/db/service-normalization.ts +288 -0
- package/src/db/service.ts +912 -779
- package/src/db/startup.ts +153 -68
- package/src/db/transaction-conflict.ts +15 -0
- package/src/effect/awaitable-effect.ts +96 -0
- package/src/effect/errors.ts +121 -0
- package/src/effect/helpers.ts +123 -0
- package/src/effect/index.ts +24 -0
- package/src/effect/layers.ts +238 -0
- package/src/effect/runtime-ref.ts +25 -0
- package/src/effect/runtime.ts +46 -0
- package/src/effect/services.ts +61 -0
- package/src/effect/zod.ts +43 -0
- package/src/embeddings/provider.ts +128 -83
- package/src/index.ts +48 -1
- package/src/openrouter/direct-provider.ts +11 -35
- package/src/queues/autonomous-job.queue.ts +117 -73
- package/src/queues/context-compaction.queue.ts +50 -17
- package/src/queues/delayed-node-promotion.queue.ts +46 -17
- 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 +26 -4
- package/src/queues/plan-agent-heartbeat.queue.ts +71 -24
- package/src/queues/plan-scheduler.queue.ts +97 -33
- package/src/queues/post-chat-memory.queue.ts +56 -26
- package/src/queues/queue-factory.ts +227 -59
- package/src/queues/standalone-worker.ts +39 -0
- package/src/queues/title-generation.queue.ts +45 -11
- package/src/redis/connection.ts +182 -113
- 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 +20 -0
- package/src/redis/stream-context.ts +92 -46
- package/src/runtime/agent-identity-overrides.ts +2 -2
- package/src/runtime/agent-runtime-policy.ts +5 -2
- package/src/runtime/agent-stream-helpers.ts +24 -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} +161 -94
- package/src/runtime/domain-layer.ts +192 -0
- package/src/runtime/execution-plan-visibility.ts +2 -2
- package/src/runtime/execution-plan.ts +42 -15
- package/src/runtime/graph-designer.ts +16 -4
- package/src/runtime/helper-model.ts +139 -48
- package/src/runtime/index.ts +7 -8
- package/src/runtime/indexed-repositories-policy.ts +3 -3
- package/src/runtime/{memory-block.ts → memory/memory-block.ts} +50 -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} +54 -67
- package/src/runtime/{memory-prompts-fact.ts → memory/memory-prompts-fact.ts} +2 -2
- package/src/runtime/memory/memory-scope.ts +53 -0
- package/src/runtime/plugin-resolution.ts +124 -25
- package/src/runtime/plugin-types.ts +9 -1
- package/src/runtime/post-turn-side-effects.ts +177 -130
- package/src/runtime/retrieval-adapters.ts +40 -6
- package/src/runtime/runtime-accessors.ts +92 -0
- package/src/runtime/runtime-config.ts +150 -61
- package/src/runtime/runtime-extensions.ts +23 -25
- 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 +159 -0
- package/src/runtime/{social-chat-history.ts → social-chat/social-chat-history.ts} +51 -20
- package/src/runtime/social-chat/social-chat.ts +630 -0
- package/src/runtime/specialist-runner.ts +36 -10
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +433 -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 +183 -111
- package/src/runtime/turn-lifecycle.ts +93 -27
- package/src/services/agent-activity.service.ts +287 -203
- package/src/services/agent-executor.service.ts +253 -149
- package/src/services/artifact.service.ts +231 -149
- package/src/services/attachment.service.ts +171 -115
- package/src/services/autonomous-job.service.ts +890 -491
- package/src/services/background-work.service.ts +54 -0
- package/src/services/chat-run-registry.service.ts +13 -1
- package/src/services/context-compaction.service.ts +136 -86
- package/src/services/document-chunk.service.ts +151 -88
- 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 +278 -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 +101 -168
- package/src/services/graph-full-routing.ts +193 -0
- package/src/services/index.ts +19 -21
- package/src/services/institutional-memory.service.ts +213 -125
- package/src/services/learned-skill.service.ts +368 -260
- package/src/services/memory/memory-conversation.ts +95 -0
- package/src/services/memory/memory-errors.ts +27 -0
- package/src/services/memory/memory-org-memory.ts +50 -0
- package/src/services/memory/memory-preseeded.ts +86 -0
- package/src/services/memory/memory-rerank.ts +297 -0
- package/src/services/{memory-utils.ts → memory/memory-utils.ts} +6 -5
- package/src/services/memory/memory.service.ts +674 -0
- package/src/services/memory/rerank.service.ts +201 -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 +29 -16
- package/src/services/organization-member.service.ts +120 -66
- package/src/services/organization.service.ts +153 -77
- package/src/services/ownership-dispatcher.service.ts +456 -263
- 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-approval.service.ts → plan/plan-approval.service.ts} +45 -22
- 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 +169 -0
- package/src/services/plan/plan-coordination.service.ts +181 -0
- package/src/services/plan/plan-cycle.service.ts +405 -0
- package/src/services/plan/plan-deadline.service.ts +533 -0
- package/src/services/plan/plan-event-delivery.service.ts +266 -0
- package/src/services/plan/plan-executor-context.ts +35 -0
- package/src/services/plan/plan-executor-graph.ts +522 -0
- package/src/services/plan/plan-executor-helpers.ts +307 -0
- package/src/services/plan/plan-executor-persistence.ts +209 -0
- package/src/services/plan/plan-executor.service.ts +1737 -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 +637 -0
- package/src/services/plan/plan-scheduler.service.ts +379 -0
- package/src/services/plan/plan-template.service.ts +224 -0
- package/src/services/plan/plan-transaction-events.ts +36 -0
- package/src/services/plan/plan-validator.service.ts +907 -0
- package/src/services/plan/plan-workspace.service.ts +131 -0
- package/src/services/plugin-executor.service.ts +102 -68
- package/src/services/quality-metrics.service.ts +112 -94
- package/src/services/queue-job.service.ts +288 -231
- package/src/services/recent-activity-title.service.ts +73 -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 +190 -122
- package/src/services/system-executor.service.ts +96 -61
- package/src/services/thread/thread-active-run.ts +203 -0
- package/src/services/thread/thread-bootstrap.ts +385 -0
- package/src/services/thread/thread-listing.ts +199 -0
- package/src/services/thread/thread-memory-block.ts +130 -0
- package/src/services/thread/thread-message.service.ts +379 -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 +1148 -0
- package/src/services/thread/thread-turn-streaming.ts +403 -0
- package/src/services/thread/thread-turn-tracing.ts +35 -0
- package/src/services/thread/thread-turn.ts +376 -0
- package/src/services/thread/thread.service.ts +344 -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 +334 -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 +3 -3
- package/src/system-agents/delegated-agent-factory.ts +159 -90
- package/src/system-agents/helper-agent-options.ts +1 -1
- package/src/system-agents/memory-reranker.agent.ts +3 -3
- package/src/system-agents/memory.agent.ts +3 -3
- package/src/system-agents/recent-activity-title-refiner.agent.ts +3 -3
- package/src/system-agents/regular-chat-memory-digest.agent.ts +3 -3
- package/src/system-agents/skill-extractor.agent.ts +3 -3
- package/src/system-agents/skill-manager.agent.ts +3 -3
- package/src/system-agents/thread-router.agent.ts +157 -113
- package/src/system-agents/title-generator.agent.ts +3 -3
- package/src/tools/execution-plan.tool.ts +241 -171
- package/src/tools/fetch-webpage.tool.ts +29 -18
- package/src/tools/firecrawl-client.ts +26 -6
- package/src/tools/index.ts +1 -0
- package/src/tools/memory-block.tool.ts +14 -6
- package/src/tools/plan-approval.tool.ts +57 -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 +33 -22
- package/src/tools/search.tool.ts +41 -29
- package/src/tools/team-think.tool.ts +125 -84
- package/src/tools/user-questions.tool.ts +4 -3
- package/src/tools/web-tool-shared.ts +6 -0
- package/src/utils/async.ts +25 -22
- package/src/utils/crypto.ts +21 -0
- package/src/utils/date-time.ts +40 -1
- package/src/utils/errors.ts +111 -20
- 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 +164 -52
- 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 +185 -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 +74 -31
- package/src/config/debug-logger.ts +0 -47
- package/src/config/search.ts +0 -3
- package/src/redis/connection-accessor.ts +0 -26
- package/src/runtime/agent-types.ts +0 -1
- package/src/runtime/context-compaction-runtime.ts +0 -87
- package/src/runtime/memory-scope.ts +0 -43
- 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-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,232 +13,302 @@ 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
|
-
|
|
23
|
-
type
|
|
24
|
-
|
|
25
|
-
type
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
| '
|
|
33
|
-
| 'getActivePlansForThread'
|
|
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'
|
|
26
|
+
|
|
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'>
|
|
34
35
|
>
|
|
35
36
|
|
|
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
|
+
>
|
|
48
|
+
>
|
|
49
|
+
|
|
50
|
+
type ExecutionPlanToolValidationError = ReturnType<typeof toValidationError>
|
|
51
|
+
|
|
36
52
|
export function createExecutionPlanTool(params: {
|
|
37
53
|
orgId: RecordIdRef
|
|
38
54
|
userId: RecordIdRef
|
|
39
55
|
threadId: RecordIdRef
|
|
40
56
|
agentId: string
|
|
41
|
-
executionPlanService
|
|
42
|
-
threadService
|
|
57
|
+
executionPlanService: ExecutionPlanExecutionPlanService
|
|
58
|
+
threadService: ExecutionPlanThreadService
|
|
43
59
|
onPlanChanged?: () => void
|
|
44
60
|
validateInlinePlan?: (draft: ReturnType<typeof expandAgentPlanDraft>) => void
|
|
45
61
|
}) {
|
|
46
|
-
const resolvedEpService = params.executionPlanService ?? executionPlanService
|
|
47
|
-
const resolvedWsService = params.threadService ?? threadService
|
|
48
|
-
|
|
49
62
|
return tool({
|
|
50
63
|
description:
|
|
51
64
|
'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
65
|
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
|
-
|
|
66
|
+
execute: (input) =>
|
|
67
|
+
Effect.runPromise(
|
|
68
|
+
Effect.gen(function* () {
|
|
69
|
+
const parsed = yield* parseExecutionPlanArgsEffect(input)
|
|
70
|
+
|
|
71
|
+
switch (parsed.action) {
|
|
72
|
+
case 'create': {
|
|
73
|
+
const draft = yield* extractAgentPlanDraftEffect(parsed)
|
|
74
|
+
params.validateInlinePlan?.(draft)
|
|
75
|
+
const targetThreadId = parsed.targetThreadId ?? params.threadId
|
|
76
|
+
const isCrossThreadTarget =
|
|
77
|
+
recordIdToString(targetThreadId, TABLES.THREAD) !== recordIdToString(params.threadId, TABLES.THREAD)
|
|
78
|
+
const result = yield* params.executionPlanService.createPlan({
|
|
79
|
+
organizationId: params.orgId,
|
|
80
|
+
threadId: targetThreadId,
|
|
81
|
+
...(isCrossThreadTarget ? { sourceThreadId: params.threadId } : {}),
|
|
82
|
+
leadAgentId: params.agentId,
|
|
83
|
+
createdByAgentId: params.agentId,
|
|
84
|
+
requireApproval: parsed.requireApproval ?? isCrossThreadTarget,
|
|
85
|
+
input: draft,
|
|
86
|
+
})
|
|
87
|
+
params.onPlanChanged?.()
|
|
88
|
+
return result
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
case 'create-project': {
|
|
92
|
+
const draft = yield* extractAgentPlanDraftEffect(parsed)
|
|
93
|
+
let createdThreadId: string | null = null
|
|
94
|
+
|
|
95
|
+
const cleanupLeakedThread = (threadId: string) =>
|
|
96
|
+
params.threadService.deleteThread(threadId).pipe(
|
|
97
|
+
Effect.catch((cleanupError: unknown) =>
|
|
98
|
+
Effect.sync(() => {
|
|
99
|
+
serverLogger.warn`Failed to clean up leaked execution-plan project thread ${threadId}: ${cleanupError}`
|
|
100
|
+
}),
|
|
101
|
+
),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const projectEffect = Effect.gen(function* () {
|
|
105
|
+
const projectTitle = parsed.projectTitle
|
|
106
|
+
const targetThreadId = parsed.targetThreadId
|
|
107
|
+
const targetThread = targetThreadId
|
|
108
|
+
? yield* params.threadService.getThread(targetThreadId)
|
|
109
|
+
: yield* (() => {
|
|
110
|
+
if (!projectTitle) {
|
|
111
|
+
return new BadRequestError({
|
|
112
|
+
message: 'projectTitle is required when action is "create-project".',
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return params.threadService.createThread({
|
|
117
|
+
userId: params.userId,
|
|
118
|
+
organizationId: params.orgId,
|
|
119
|
+
title: projectTitle,
|
|
120
|
+
type: 'group',
|
|
121
|
+
})
|
|
122
|
+
})()
|
|
123
|
+
|
|
124
|
+
if (!parsed.targetThreadId) {
|
|
125
|
+
createdThreadId = targetThread.id
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (targetThread.organizationId !== recordIdToString(params.orgId, TABLES.ORGANIZATION)) {
|
|
129
|
+
return yield* new ForbiddenError({ message: 'Target thread belongs to a different organization.' })
|
|
130
|
+
}
|
|
131
|
+
if (targetThread.userId !== recordIdToString(params.userId, TABLES.USER)) {
|
|
132
|
+
return yield* new ForbiddenError({ message: 'Target thread belongs to a different user.' })
|
|
83
133
|
}
|
|
84
134
|
|
|
85
|
-
|
|
86
|
-
|
|
135
|
+
const existingPlans = yield* params.executionPlanService.getActivePlansForThread(targetThread.id)
|
|
136
|
+
if (targetThread.type !== 'thread' && existingPlans.length > 0) {
|
|
137
|
+
return yield* new ConflictError({
|
|
138
|
+
message:
|
|
139
|
+
'This thread already has an active execution plan. Use action "replace" or target a core thread.',
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const created = yield* params.executionPlanService.createPlan({
|
|
87
144
|
organizationId: params.orgId,
|
|
88
|
-
|
|
89
|
-
|
|
145
|
+
threadId: targetThread.id,
|
|
146
|
+
sourceThreadId: params.threadId,
|
|
147
|
+
leadAgentId: params.agentId,
|
|
148
|
+
createdByAgentId: params.agentId,
|
|
149
|
+
requireApproval: parsed.requireApproval ?? true,
|
|
150
|
+
input: draft,
|
|
90
151
|
})
|
|
91
|
-
})()
|
|
92
152
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
'This thread already has an active execution plan. Use action "replace" or target a core thread.',
|
|
104
|
-
)
|
|
105
|
-
}
|
|
153
|
+
const result = {
|
|
154
|
+
...created,
|
|
155
|
+
runId: created.plan?.runId ?? '',
|
|
156
|
+
threadId: targetThread.id,
|
|
157
|
+
threadTitle: targetThread.title,
|
|
158
|
+
createdThread: createdThreadId !== null,
|
|
159
|
+
} satisfies CreateProjectWithPlanResultData
|
|
160
|
+
params.onPlanChanged?.()
|
|
161
|
+
return result
|
|
162
|
+
}).pipe(Effect.tapError(() => (createdThreadId ? cleanupLeakedThread(createdThreadId) : Effect.void)))
|
|
106
163
|
|
|
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(() => {})
|
|
164
|
+
return yield* projectEffect
|
|
128
165
|
}
|
|
129
|
-
throw error
|
|
130
|
-
}
|
|
131
|
-
break
|
|
132
|
-
}
|
|
133
166
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
})
|
|
152
|
-
break
|
|
167
|
+
case 'replace': {
|
|
168
|
+
const draft = yield* extractAgentPlanDraftEffect(parsed)
|
|
169
|
+
const result = yield* params.executionPlanService.replacePlan({
|
|
170
|
+
organizationId: params.orgId,
|
|
171
|
+
threadId: params.threadId,
|
|
172
|
+
leadAgentId: params.agentId,
|
|
173
|
+
createdByAgentId: params.agentId,
|
|
174
|
+
input: {
|
|
175
|
+
runId: parsed.runId,
|
|
176
|
+
reason: parsed.reason,
|
|
177
|
+
requireApproval: parsed.requireApproval,
|
|
178
|
+
...draft,
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
params.onPlanChanged?.()
|
|
182
|
+
return result
|
|
183
|
+
}
|
|
153
184
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
},
|
|
164
|
-
})
|
|
165
|
-
break
|
|
166
|
-
}
|
|
185
|
+
case 'resume': {
|
|
186
|
+
const result = yield* params.executionPlanService.resumeRun({
|
|
187
|
+
threadId: params.threadId,
|
|
188
|
+
emittedBy: params.agentId,
|
|
189
|
+
input: { runId: parsed.runId },
|
|
190
|
+
})
|
|
191
|
+
params.onPlanChanged?.()
|
|
192
|
+
return result
|
|
193
|
+
}
|
|
167
194
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
195
|
+
case 'update-node': {
|
|
196
|
+
const result = yield* params.executionPlanService.submitNodeResult({
|
|
197
|
+
threadId: params.threadId,
|
|
198
|
+
emittedBy: params.agentId,
|
|
199
|
+
input: {
|
|
200
|
+
runId: parsed.runId,
|
|
201
|
+
nodeId: parsed.node.id,
|
|
202
|
+
notes: parsed.node.latestNotes,
|
|
203
|
+
artifacts: parsed.node.deliverables ?? [],
|
|
204
|
+
},
|
|
205
|
+
})
|
|
206
|
+
params.onPlanChanged?.()
|
|
207
|
+
return result
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}).pipe(Effect.withSpan('tool.executionPlan.execute')),
|
|
211
|
+
),
|
|
171
212
|
})
|
|
172
213
|
}
|
|
173
214
|
|
|
174
|
-
function
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
215
|
+
function parseExecutionPlanArgsEffect(
|
|
216
|
+
input: unknown,
|
|
217
|
+
): Effect.Effect<ExecutionPlanArgs, ExecutionPlanToolValidationError> {
|
|
218
|
+
return Effect.gen(function* () {
|
|
219
|
+
const parsedArgs = ExecutionPlanArgsSchema.safeParse(input)
|
|
220
|
+
if (!parsedArgs.success) {
|
|
221
|
+
return yield* toValidationError(parsedArgs.error, 'Invalid execution plan tool input')
|
|
222
|
+
}
|
|
223
|
+
const parsed = parsedArgs.data
|
|
224
|
+
|
|
225
|
+
const parseAction = <T>(result: { success: true; data: T } | { success: false; error: unknown }) =>
|
|
226
|
+
result.success
|
|
227
|
+
? Effect.succeed(result.data)
|
|
228
|
+
: Effect.fail(toValidationError(result.error, 'Invalid execution plan action input'))
|
|
229
|
+
|
|
230
|
+
switch (parsed.action) {
|
|
231
|
+
case 'create':
|
|
232
|
+
return yield* parseAction(ExecutionPlanCreateArgsSchema.safeParse(parsed))
|
|
233
|
+
case 'create-project':
|
|
234
|
+
return yield* parseAction(ExecutionPlanCreateProjectArgsSchema.safeParse(parsed))
|
|
235
|
+
case 'replace':
|
|
236
|
+
return yield* parseAction(ExecutionPlanReplaceArgsSchema.safeParse(parsed))
|
|
237
|
+
case 'resume':
|
|
238
|
+
return yield* parseAction(ExecutionPlanResumeArgsSchema.safeParse(parsed))
|
|
239
|
+
case 'update-node':
|
|
240
|
+
return yield* parseAction(ExecutionPlanUpdateNodeArgsSchema.safeParse(parsed))
|
|
241
|
+
}
|
|
242
|
+
})
|
|
189
243
|
}
|
|
190
244
|
|
|
191
|
-
function
|
|
192
|
-
|
|
193
|
-
|
|
245
|
+
function extractAgentPlanDraftEffect(
|
|
246
|
+
input: Extract<ExecutionPlanArgs, { action: 'create' | 'create-project' | 'replace' }>,
|
|
247
|
+
): Effect.Effect<ReturnType<typeof expandAgentPlanDraft>, ExecutionPlanToolValidationError> {
|
|
248
|
+
return Effect.gen(function* () {
|
|
249
|
+
const parsedDraft = AgentPlanDraftSchema.safeParse({
|
|
194
250
|
title: input.title,
|
|
195
251
|
objective: input.objective,
|
|
196
252
|
nodes: input.nodes,
|
|
197
253
|
edges: input.edges,
|
|
198
|
-
})
|
|
199
|
-
|
|
254
|
+
})
|
|
255
|
+
if (!parsedDraft.success) {
|
|
256
|
+
return yield* toValidationError(parsedDraft.error, 'Invalid execution plan draft')
|
|
257
|
+
}
|
|
258
|
+
return expandAgentPlanDraft(parsedDraft.data)
|
|
259
|
+
})
|
|
200
260
|
}
|
|
201
261
|
|
|
202
|
-
export function createExecutionPlanQueryTool(params: {
|
|
262
|
+
export function createExecutionPlanQueryTool(params: {
|
|
263
|
+
threadId: RecordIdRef
|
|
264
|
+
executionPlanService: Pick<ExecutionPlanExecutionPlanService, 'listActivePlanSummaries' | 'getActivePlanToolResult'>
|
|
265
|
+
}) {
|
|
203
266
|
return tool({
|
|
204
267
|
description:
|
|
205
268
|
'Query execution plans. Omit runId to list all active plans. Provide runId to load a specific plan run.',
|
|
206
269
|
inputSchema: ExecutionPlanQueryArgsSchema,
|
|
207
|
-
execute:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
270
|
+
execute: (input) =>
|
|
271
|
+
Effect.runPromise(
|
|
272
|
+
Effect.gen(function* () {
|
|
273
|
+
if (!input.runId) {
|
|
274
|
+
return yield* params.executionPlanService.listActivePlanSummaries(params.threadId)
|
|
275
|
+
}
|
|
276
|
+
return yield* params.executionPlanService.getActivePlanToolResult({
|
|
277
|
+
threadId: params.threadId,
|
|
278
|
+
runId: input.runId,
|
|
279
|
+
includeEvents: input.includeEvents,
|
|
280
|
+
includeArtifacts: input.includeArtifacts,
|
|
281
|
+
includeApprovals: input.includeApprovals,
|
|
282
|
+
includeCheckpoints: input.includeCheckpoints,
|
|
283
|
+
includeValidationIssues: input.includeValidationIssues,
|
|
284
|
+
})
|
|
285
|
+
}).pipe(Effect.withSpan('tool.executionPlanQuery.execute')),
|
|
286
|
+
),
|
|
221
287
|
})
|
|
222
288
|
}
|
|
223
289
|
|
|
224
290
|
export function createSubmitExecutionNodeResultTool(params: {
|
|
225
291
|
threadId: RecordIdRef
|
|
226
292
|
agentId: string
|
|
293
|
+
executionPlanService: Pick<ExecutionPlanExecutionPlanService, 'submitNodeResult'>
|
|
227
294
|
onPlanChanged?: () => void
|
|
228
295
|
}) {
|
|
229
296
|
return tool({
|
|
230
297
|
description:
|
|
231
298
|
'Submit the result for the currently running execution node. The executor validates outputs, artifacts, and completion checks before advancing the run.',
|
|
232
299
|
inputSchema: SubmitExecutionNodeResultArgsSchema,
|
|
233
|
-
execute:
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
300
|
+
execute: (input) =>
|
|
301
|
+
Effect.runPromise(
|
|
302
|
+
Effect.gen(function* () {
|
|
303
|
+
const result = yield* params.executionPlanService.submitNodeResult({
|
|
304
|
+
threadId: params.threadId,
|
|
305
|
+
emittedBy: params.agentId,
|
|
306
|
+
input,
|
|
307
|
+
})
|
|
308
|
+
params.onPlanChanged?.()
|
|
309
|
+
return result
|
|
310
|
+
}).pipe(Effect.withSpan('tool.submitExecutionNodeResult.execute')),
|
|
311
|
+
),
|
|
242
312
|
toModelOutput: ({ output }) => {
|
|
243
313
|
const result = getLatestExecutionPlanResult(output)
|
|
244
314
|
const summary = result?.message?.trim()
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { tool } from 'ai'
|
|
2
|
+
import { Effect, Schema } 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'
|
|
12
|
+
|
|
13
|
+
class FetchWebpageToolError extends Schema.TaggedErrorClass<FetchWebpageToolError>()(
|
|
14
|
+
'@lota-sdk/core/FetchWebpageToolError',
|
|
15
|
+
{ message: Schema.String, cause: Schema.optional(Schema.Defect) },
|
|
16
|
+
) {}
|
|
9
17
|
|
|
10
|
-
const TOOL_TIMEOUT_MS = 30_000
|
|
11
18
|
const FormatSchema = z.enum(['markdown', 'html', 'rawHtml', 'links', 'images', 'screenshot', 'summary'])
|
|
12
19
|
const MAX_MARKDOWN_CHARS = 6_000
|
|
13
20
|
const MAX_SUMMARY_CHARS = 1_200
|
|
14
21
|
const MAX_LINKS = 25
|
|
15
22
|
const MAX_IMAGES = 10
|
|
16
23
|
|
|
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
24
|
function readStringList(record: Record<string, unknown>, key: string, maxItems: number): string[] {
|
|
23
25
|
const value = record[key]
|
|
24
26
|
if (!Array.isArray(value)) return []
|
|
@@ -91,7 +93,7 @@ function buildFetchCitations(url: string, document: unknown): WebCitation[] {
|
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
return [{ source: 'web', sourceId, retrievedAt:
|
|
96
|
+
return [{ source: 'web', sourceId, retrievedAt: nowIsoDateTimeString() }]
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
export const fetchWebpageTool = {
|
|
@@ -107,7 +109,7 @@ export const fetchWebpageTool = {
|
|
|
107
109
|
maxAge: z.number().int().min(1).optional(),
|
|
108
110
|
})
|
|
109
111
|
.strict(),
|
|
110
|
-
execute:
|
|
112
|
+
execute: ({
|
|
111
113
|
url,
|
|
112
114
|
formats,
|
|
113
115
|
onlyMainContent,
|
|
@@ -118,17 +120,26 @@ export const fetchWebpageTool = {
|
|
|
118
120
|
onlyMainContent?: boolean
|
|
119
121
|
maxAge?: number
|
|
120
122
|
}) => {
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
const firecrawl = getFirecrawlClient()
|
|
124
|
+
|
|
125
|
+
return Effect.runPromise(
|
|
126
|
+
Effect.gen(function* () {
|
|
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
|
+
})
|
|
140
|
+
return { url, document: summarizeDocument(url, result), citations: buildFetchCitations(url, result) }
|
|
141
|
+
}).pipe(Effect.withSpan('tool.fetchWebpage.execute')),
|
|
129
142
|
)
|
|
130
|
-
|
|
131
|
-
return { url, document: summarizeDocument(url, result), citations: buildFetchCitations(url, result) }
|
|
132
143
|
},
|
|
133
144
|
}),
|
|
134
145
|
} as const satisfies ToolDefinition<void>
|
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
import Firecrawl from '@mendable/firecrawl-js'
|
|
2
|
+
import { Context, Effect, Layer } from 'effect'
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import { resolveLotaService } from '../effect/runtime'
|
|
5
|
+
import { RuntimeConfigServiceTag } from '../effect/services'
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
export class FirecrawlTag extends Context.Service<FirecrawlTag, Firecrawl>()('@lota-sdk/core/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
|
+
)
|
|
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
|
+
}
|
|
6
29
|
|
|
7
30
|
export function getFirecrawlClient(): Firecrawl {
|
|
8
|
-
|
|
9
|
-
_firecrawlClient = new Firecrawl({ apiKey: getRuntimeConfig().firecrawl.apiKey })
|
|
10
|
-
}
|
|
11
|
-
return _firecrawlClient
|
|
31
|
+
return currentFirecrawlClient ?? resolveLotaService(FirecrawlTag)
|
|
12
32
|
}
|
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
|
|