@lota-sdk/core 0.4.7 → 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/model-constants.ts +1 -0
- package/src/config/thread-defaults.ts +33 -21
- package/src/create-runtime.ts +725 -383
- 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 -71
- package/src/index.ts +46 -1
- package/src/openrouter/direct-provider.ts +29 -0
- 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 +165 -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 -20
- 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 -844
- 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/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
|
@@ -9,12 +9,17 @@ import type {
|
|
|
9
9
|
} from '@lota-sdk/shared'
|
|
10
10
|
import { PlanNodeResultSubmissionSchema, WriteIntentSchema } from '@lota-sdk/shared'
|
|
11
11
|
import { stepCountIs, tool } from 'ai'
|
|
12
|
-
import type {
|
|
12
|
+
import type { ToolSet } from 'ai'
|
|
13
|
+
import { Context, Schema, Effect, Layer } from 'effect'
|
|
13
14
|
|
|
14
|
-
import {
|
|
15
|
+
import { getAgentRoster, getAgentRuntimeConfig, getResolvedAgentFactoryConfig } from '../config/agent-defaults'
|
|
15
16
|
import { ensureRecordId } from '../db/record-id'
|
|
16
|
-
import {
|
|
17
|
+
import type { SurrealDBService } from '../db/service'
|
|
17
18
|
import { TABLES } from '../db/tables'
|
|
19
|
+
import { BadRequestError, NotFoundError } from '../effect/errors'
|
|
20
|
+
import { runPromise } from '../effect/runtime'
|
|
21
|
+
import { DatabaseServiceTag } from '../effect/services'
|
|
22
|
+
import { toValidationError } from '../effect/zod'
|
|
18
23
|
import {
|
|
19
24
|
OWNERSHIP_DISPATCH_BLOCKED_TOOL_NAMES,
|
|
20
25
|
buildCompletionCheckStructuredOutputHints,
|
|
@@ -22,13 +27,24 @@ import {
|
|
|
22
27
|
buildOwnershipDispatchResponseGuard,
|
|
23
28
|
} from '../runtime/agent-runtime-policy'
|
|
24
29
|
import { mergeInstructionSections } from '../runtime/instruction-sections'
|
|
25
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
buildIndexedRepositoriesContext,
|
|
32
|
+
getGithubInstallationForOrganization,
|
|
33
|
+
getLinearInstallationByOrgId,
|
|
34
|
+
} from '../runtime/plugin-resolution'
|
|
26
35
|
import { getTurnHooks } from '../runtime/runtime-extensions'
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import type {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
36
|
+
import { readInstructionSections, readOptionalString } from '../runtime/thread-chat-helpers'
|
|
37
|
+
import { nowDate } from '../utils/date-time'
|
|
38
|
+
import type { makeNodeWorkspaceService } from './node-workspace.service'
|
|
39
|
+
import { NodeWorkspaceServiceTag } from './node-workspace.service'
|
|
40
|
+
import type { PlanValidationIssueInput } from './plan/plan-validator.service'
|
|
41
|
+
import { ThreadSchema } from './thread/thread.types'
|
|
42
|
+
import type { makeWriteIntentValidatorService } from './write-intent-validator.service'
|
|
43
|
+
import { WriteIntentValidatorServiceTag } from './write-intent-validator.service'
|
|
44
|
+
|
|
45
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
46
|
+
return typeof value === 'object' && value !== null
|
|
47
|
+
}
|
|
32
48
|
|
|
33
49
|
function applyToolPolicy(tools: ToolSet, nodeSpec: PlanNodeSpec): ToolSet {
|
|
34
50
|
const blockedToolNames = new Set([...OWNERSHIP_DISPATCH_BLOCKED_TOOL_NAMES, ...nodeSpec.toolPolicy.deny])
|
|
@@ -74,248 +90,344 @@ export function buildWriteIntentDispatchPrompt(nodeSpec: PlanNodeSpec): string {
|
|
|
74
90
|
|
|
75
91
|
const MAX_SELF_CORRECTION_RETRIES = 3
|
|
76
92
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
function validateOwner(agentId: string, nodeId: string): PlanValidationIssueInput[] {
|
|
94
|
+
if (!getAgentRoster().includes(agentId)) {
|
|
95
|
+
return [
|
|
96
|
+
{
|
|
97
|
+
severity: 'blocking',
|
|
98
|
+
code: 'agent_executor_missing',
|
|
99
|
+
message: `Node "${nodeId}" references unknown agent executor "${agentId}".`,
|
|
100
|
+
nodeId,
|
|
101
|
+
detail: { agentId },
|
|
102
|
+
},
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return []
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
class AgentExecutorError extends Schema.TaggedErrorClass<AgentExecutorError>()('AgentExecutorError', {
|
|
110
|
+
operation: Schema.String,
|
|
111
|
+
message: Schema.String,
|
|
112
|
+
cause: Schema.Defect,
|
|
113
|
+
}) {}
|
|
114
|
+
|
|
115
|
+
function tryAgentExecutorPromise<A>(
|
|
116
|
+
operation: string,
|
|
117
|
+
message: string,
|
|
118
|
+
thunk: () => PromiseLike<A> | A | Effect.Effect<A, unknown, never>,
|
|
119
|
+
): Effect.Effect<A, AgentExecutorError> {
|
|
120
|
+
return Effect.suspend(() => {
|
|
121
|
+
try {
|
|
122
|
+
const value = thunk()
|
|
123
|
+
if (Effect.isEffect(value)) {
|
|
124
|
+
return value.pipe(Effect.mapError((cause) => new AgentExecutorError({ operation, message, cause })))
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return Effect.tryPromise({
|
|
128
|
+
try: () => Promise.resolve(value),
|
|
129
|
+
catch: (cause) => new AgentExecutorError({ operation, message, cause }),
|
|
130
|
+
})
|
|
131
|
+
} catch (cause) {
|
|
132
|
+
return Effect.fail(new AgentExecutorError({ operation, message, cause }))
|
|
89
133
|
}
|
|
134
|
+
})
|
|
135
|
+
}
|
|
90
136
|
|
|
91
|
-
|
|
92
|
-
|
|
137
|
+
function isAgentExecutorOwner(
|
|
138
|
+
owner: PlanNodeSpec['owner'],
|
|
139
|
+
): owner is Extract<PlanNodeSpec['owner'], { executorType: 'agent' }> {
|
|
140
|
+
return owner.executorType === 'agent'
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function buildWriteIntentTool(params: {
|
|
144
|
+
nodeSpec: PlanNodeSpec
|
|
145
|
+
workspace: ReturnType<ReturnType<typeof makeNodeWorkspaceService>['initialize']>
|
|
146
|
+
writeIntentValidatorService: ReturnType<typeof makeWriteIntentValidatorService>
|
|
147
|
+
stageWrite: (intent: WriteIntent) => Effect.Effect<void, BadRequestError>
|
|
148
|
+
}) {
|
|
149
|
+
return tool({
|
|
150
|
+
description:
|
|
151
|
+
'Write a validated artifact or structured output field. Call this for each deliverable. If validation fails, correct your payload and try again.',
|
|
152
|
+
inputSchema: WriteIntentSchema,
|
|
153
|
+
execute: (intent: WriteIntent) =>
|
|
154
|
+
runPromise(
|
|
155
|
+
Effect.gen(function* () {
|
|
156
|
+
const correctionCount = params.workspace.sys.correctionCounts.get(intent.targetPath) ?? 0
|
|
157
|
+
|
|
158
|
+
const validation = params.writeIntentValidatorService.validate({
|
|
159
|
+
intent,
|
|
160
|
+
nodeSpec: params.nodeSpec,
|
|
161
|
+
schemaRegistry: params.workspace.ctx.schemaRegistry,
|
|
162
|
+
existingDeliverables: params.workspace.deliverables,
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
if (validation.issues.length > 0) {
|
|
166
|
+
if (correctionCount >= MAX_SELF_CORRECTION_RETRIES) {
|
|
167
|
+
return yield* new BadRequestError({
|
|
168
|
+
message: `Write validation failed for "${intent.targetPath}" after ${MAX_SELF_CORRECTION_RETRIES} retries: ${validation.issues.map((i) => i.message).join(', ')}`,
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
params.workspace.sys.correctionCounts.set(intent.targetPath, correctionCount + 1)
|
|
172
|
+
params.workspace.sys.writeLog.push({
|
|
173
|
+
targetPath: intent.targetPath,
|
|
174
|
+
action: intent.action,
|
|
175
|
+
timestamp: nowDate(),
|
|
176
|
+
result: 'rejected',
|
|
177
|
+
})
|
|
178
|
+
return {
|
|
179
|
+
status: 'validation_failed',
|
|
180
|
+
error: { targetPath: intent.targetPath, action: intent.action, issues: validation.issues },
|
|
181
|
+
hint: `Correct and re-emit. Attempt ${correctionCount + 1}/${MAX_SELF_CORRECTION_RETRIES}.`,
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
yield* params.stageWrite(intent)
|
|
186
|
+
return { status: 'accepted', message: `Write to "${intent.targetPath}" validated and staged.` }
|
|
187
|
+
}),
|
|
188
|
+
),
|
|
189
|
+
})
|
|
190
|
+
}
|
|
93
191
|
|
|
94
|
-
|
|
192
|
+
function createExecuteNode(deps: AgentExecutorDeps) {
|
|
193
|
+
return function executeNode(params: {
|
|
95
194
|
nodeSpec: PlanNodeSpec
|
|
96
195
|
resolvedInput: Record<string, unknown>
|
|
97
196
|
inputArtifacts: PlanArtifactSubmission[]
|
|
98
197
|
context: OwnershipDispatchContext
|
|
99
198
|
executionMode?: ExecutionMode
|
|
100
199
|
schemaRegistry?: PlanSchemaRegistry
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
200
|
+
}) {
|
|
201
|
+
return Effect.gen(function* () {
|
|
202
|
+
const owner = params.nodeSpec.owner
|
|
203
|
+
if (!isAgentExecutorOwner(owner)) {
|
|
204
|
+
return yield* new BadRequestError({
|
|
205
|
+
message: `AgentExecutor cannot execute owner type "${owner.executorType}".`,
|
|
206
|
+
})
|
|
207
|
+
}
|
|
105
208
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
209
|
+
const agentId = owner.ref
|
|
210
|
+
if (!getAgentRoster().includes(agentId)) {
|
|
211
|
+
return yield* new BadRequestError({ message: `Agent executor "${agentId}" is not registered.` })
|
|
212
|
+
}
|
|
110
213
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
214
|
+
const thread = yield* tryAgentExecutorPromise('load-thread', 'Failed to load dispatched thread.', () =>
|
|
215
|
+
deps.db.findOne(TABLES.THREAD, { id: ensureRecordId(params.context.threadId, TABLES.THREAD) }, ThreadSchema),
|
|
216
|
+
)
|
|
217
|
+
if (!thread) {
|
|
218
|
+
return yield* new NotFoundError({
|
|
219
|
+
resource: TABLES.THREAD,
|
|
220
|
+
message: `Thread ${params.context.threadId} not found for dispatched execution.`,
|
|
221
|
+
})
|
|
222
|
+
}
|
|
119
223
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
'
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
224
|
+
const organizationRef = ensureRecordId(params.context.organizationId, TABLES.ORGANIZATION)
|
|
225
|
+
const threadRef = ensureRecordId(params.context.threadId, TABLES.THREAD)
|
|
226
|
+
const userRefSource = params.context.userId ?? thread.userId
|
|
227
|
+
if (!userRefSource) {
|
|
228
|
+
return yield* new BadRequestError({
|
|
229
|
+
message: `Thread ${params.context.threadId} is missing a user context for dispatched execution.`,
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
const userRef = ensureRecordId(userRefSource, TABLES.USER)
|
|
233
|
+
const userName = params.context.userName ?? 'User'
|
|
234
|
+
const [linearInstallation, githubInstallation, indexedRepoContext] = yield* Effect.all([
|
|
235
|
+
tryAgentExecutorPromise(
|
|
236
|
+
'get-linear-installation',
|
|
237
|
+
`Failed to load Linear installation for org ${params.context.organizationId}.`,
|
|
238
|
+
() => getLinearInstallationByOrgId(organizationRef),
|
|
239
|
+
),
|
|
240
|
+
tryAgentExecutorPromise(
|
|
241
|
+
'get-github-installation',
|
|
242
|
+
`Failed to load GitHub installation for org ${params.context.organizationId}.`,
|
|
243
|
+
() => getGithubInstallationForOrganization(params.context.organizationId),
|
|
244
|
+
),
|
|
245
|
+
tryAgentExecutorPromise(
|
|
246
|
+
'build-indexed-repositories-context',
|
|
247
|
+
`Failed to build indexed repository context for org ${params.context.organizationId}.`,
|
|
248
|
+
() => buildIndexedRepositoriesContext(params.context.organizationId),
|
|
249
|
+
),
|
|
250
|
+
])
|
|
251
|
+
|
|
252
|
+
const mode = params.executionMode ?? 'linear'
|
|
253
|
+
const dispatchMode = thread.type === 'group' ? 'fixedThreadMode' : 'direct'
|
|
254
|
+
const dispatchInstructionSections = [
|
|
255
|
+
buildOwnershipDispatchContextSection({
|
|
256
|
+
node: params.nodeSpec,
|
|
257
|
+
resolvedInput: params.resolvedInput,
|
|
258
|
+
inputArtifacts: params.inputArtifacts,
|
|
259
|
+
upstreamHandoffs: params.context.upstreamHandoffs,
|
|
260
|
+
}),
|
|
261
|
+
]
|
|
262
|
+
|
|
263
|
+
const turnHooks = getTurnHooks()
|
|
264
|
+
const agentResolutionValue = yield* Effect.tryPromise(() =>
|
|
265
|
+
Promise.resolve(
|
|
266
|
+
turnHooks.resolveAgent?.({
|
|
267
|
+
agentId,
|
|
268
|
+
mode: dispatchMode,
|
|
269
|
+
thread,
|
|
270
|
+
threadRef,
|
|
271
|
+
orgRef: organizationRef,
|
|
272
|
+
userRef,
|
|
273
|
+
userName,
|
|
274
|
+
onboardingActive: false,
|
|
275
|
+
linearInstalled: Boolean(linearInstallation),
|
|
276
|
+
githubInstalled: Boolean(githubInstallation),
|
|
277
|
+
additionalInstructionSections: dispatchInstructionSections,
|
|
278
|
+
context: null,
|
|
279
|
+
}),
|
|
280
|
+
),
|
|
281
|
+
)
|
|
282
|
+
const agentResolution = isRecord(agentResolutionValue) ? agentResolutionValue : null
|
|
283
|
+
const resolvedAgentId = readOptionalString(agentResolution?.agentId) ?? agentId
|
|
284
|
+
const runtimeConfig = getAgentRuntimeConfig({
|
|
285
|
+
agentId: resolvedAgentId,
|
|
286
|
+
threadType: thread.type,
|
|
163
287
|
mode: dispatchMode,
|
|
164
|
-
thread,
|
|
165
|
-
threadRef,
|
|
166
|
-
orgRef: organizationRef,
|
|
167
|
-
userRef,
|
|
168
|
-
userName,
|
|
169
288
|
onboardingActive: false,
|
|
170
289
|
linearInstalled: Boolean(linearInstallation),
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const agentFactory = createAgent[resolvedAgentId] as ((...args: unknown[]) => unknown) | undefined
|
|
212
|
-
if (!agentFactory) {
|
|
213
|
-
throw new Error(`Agent factory "${resolvedAgentId}" is not registered.`)
|
|
214
|
-
}
|
|
290
|
+
additionalInstructionSections: mergeInstructionSections(
|
|
291
|
+
dispatchInstructionSections,
|
|
292
|
+
readInstructionSections(agentResolution?.additionalInstructionSections),
|
|
293
|
+
),
|
|
294
|
+
responseGuardSection: buildOwnershipDispatchResponseGuard({ node: params.nodeSpec, executionMode: mode }),
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
const agentFactoryConfig = getResolvedAgentFactoryConfig()
|
|
298
|
+
const rawTools = yield* tryAgentExecutorPromise(
|
|
299
|
+
'build-agent-tools',
|
|
300
|
+
`Failed to build agent tools for "${resolvedAgentId}".`,
|
|
301
|
+
() =>
|
|
302
|
+
Promise.resolve(
|
|
303
|
+
agentFactoryConfig.buildAgentTools({
|
|
304
|
+
agentId: resolvedAgentId,
|
|
305
|
+
orgId: organizationRef,
|
|
306
|
+
userId: userRef,
|
|
307
|
+
userName,
|
|
308
|
+
threadId: threadRef,
|
|
309
|
+
orgIdString: params.context.organizationId,
|
|
310
|
+
threadType: thread.type,
|
|
311
|
+
mode: dispatchMode,
|
|
312
|
+
linearInstalled: Boolean(linearInstallation),
|
|
313
|
+
onboardingActive: false,
|
|
314
|
+
githubInstalled: Boolean(githubInstallation),
|
|
315
|
+
provideRepoTool: indexedRepoContext.provideRepoTool,
|
|
316
|
+
defaultRepoSections: indexedRepoContext.defaultSectionsByAgent[resolvedAgentId],
|
|
317
|
+
memoryBlock: '',
|
|
318
|
+
onAppendMemoryBlock: () => undefined,
|
|
319
|
+
availableUploads: [],
|
|
320
|
+
includeExecutionPlanTools: false,
|
|
321
|
+
}),
|
|
322
|
+
),
|
|
323
|
+
)
|
|
324
|
+
const tools = applyToolPolicy(rawTools, params.nodeSpec)
|
|
325
|
+
|
|
326
|
+
const agentFactory = agentFactoryConfig.createAgent[resolvedAgentId]
|
|
327
|
+
if (!agentFactory) {
|
|
328
|
+
return yield* new BadRequestError({ message: `Agent factory "${resolvedAgentId}" is not registered.` })
|
|
329
|
+
}
|
|
215
330
|
|
|
216
|
-
|
|
331
|
+
const maxSteps = typeof runtimeConfig.maxSteps === 'number' ? runtimeConfig.maxSteps : 8
|
|
217
332
|
|
|
218
|
-
|
|
333
|
+
if (mode === 'linear') {
|
|
334
|
+
const agent = agentFactory({
|
|
335
|
+
mode: dispatchMode,
|
|
336
|
+
tools,
|
|
337
|
+
extraInstructions:
|
|
338
|
+
typeof runtimeConfig.extraInstructions === 'string' ? runtimeConfig.extraInstructions : undefined,
|
|
339
|
+
maxRetries: 1,
|
|
340
|
+
stopWhen: [stepCountIs(maxSteps)],
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
const result = yield* tryAgentExecutorPromise(
|
|
344
|
+
'generate-agent-dispatch',
|
|
345
|
+
`Agent "${resolvedAgentId}" failed to generate a dispatch result.`,
|
|
346
|
+
() => agent.generate({ prompt: buildDispatchPrompt(params.nodeSpec) }),
|
|
347
|
+
)
|
|
348
|
+
const outputCandidate = PlanNodeResultSubmissionSchema.safeParse(result.output)
|
|
349
|
+
if (outputCandidate.success) {
|
|
350
|
+
return outputCandidate.data
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return yield* toValidationError(
|
|
354
|
+
outputCandidate.error,
|
|
355
|
+
`Agent executor "${agentId}" returned an invalid node result`,
|
|
356
|
+
)
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const workspace = deps.nodeWorkspaceService.initialize({
|
|
360
|
+
nodeSpec: params.nodeSpec,
|
|
361
|
+
resolvedInput: params.resolvedInput,
|
|
362
|
+
inputArtifacts: params.inputArtifacts,
|
|
363
|
+
schemaRegistry: params.schemaRegistry ?? {},
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
const graphTools = {
|
|
367
|
+
...tools,
|
|
368
|
+
writeIntent: buildWriteIntentTool({
|
|
369
|
+
nodeSpec: params.nodeSpec,
|
|
370
|
+
workspace,
|
|
371
|
+
writeIntentValidatorService: deps.writeIntentValidatorService,
|
|
372
|
+
stageWrite: (intent) => deps.nodeWorkspaceService.stageWrite(workspace, intent, 'validated'),
|
|
373
|
+
}),
|
|
374
|
+
}
|
|
219
375
|
const agent = agentFactory({
|
|
220
376
|
mode: dispatchMode,
|
|
221
|
-
tools,
|
|
377
|
+
tools: graphTools,
|
|
222
378
|
extraInstructions:
|
|
223
379
|
typeof runtimeConfig.extraInstructions === 'string' ? runtimeConfig.extraInstructions : undefined,
|
|
224
380
|
maxRetries: 1,
|
|
225
381
|
stopWhen: [stepCountIs(maxSteps)],
|
|
226
|
-
})
|
|
227
|
-
|
|
228
|
-
const result = await agent.generate({ prompt: buildDispatchPrompt(params.nodeSpec) })
|
|
229
|
-
const outputCandidate = PlanNodeResultSubmissionSchema.safeParse(result.output)
|
|
230
|
-
if (outputCandidate.success) {
|
|
231
|
-
return outputCandidate.data
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
throw new Error(`Agent executor "${agentId}" returned an invalid node result.`)
|
|
235
|
-
}
|
|
382
|
+
})
|
|
236
383
|
|
|
237
|
-
|
|
384
|
+
yield* Effect.tryPromise(() => agent.generate({ prompt: buildWriteIntentDispatchPrompt(params.nodeSpec) }))
|
|
238
385
|
|
|
239
|
-
|
|
240
|
-
nodeSpec: params.nodeSpec,
|
|
241
|
-
resolvedInput: params.resolvedInput,
|
|
242
|
-
inputArtifacts: params.inputArtifacts,
|
|
243
|
-
schemaRegistry: params.schemaRegistry ?? {},
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
const writeIntentTool = tool({
|
|
247
|
-
description:
|
|
248
|
-
'Write a validated artifact or structured output field. Call this for each deliverable. If validation fails, correct your payload and try again.',
|
|
249
|
-
inputSchema: WriteIntentSchema,
|
|
250
|
-
execute: async (intent: WriteIntent) => {
|
|
251
|
-
const correctionCount = workspace.sys.correctionCounts.get(intent.targetPath) ?? 0
|
|
252
|
-
|
|
253
|
-
const validation = writeIntentValidatorService.validate({
|
|
254
|
-
intent,
|
|
255
|
-
nodeSpec: params.nodeSpec,
|
|
256
|
-
schemaRegistry: workspace.ctx.schemaRegistry,
|
|
257
|
-
existingDeliverables: workspace.deliverables,
|
|
258
|
-
})
|
|
386
|
+
const finalResult = yield* deps.nodeWorkspaceService.finalize(workspace)
|
|
259
387
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
workspace.sys.correctionCounts.set(intent.targetPath, correctionCount + 1)
|
|
267
|
-
workspace.sys.writeLog.push({
|
|
268
|
-
targetPath: intent.targetPath,
|
|
269
|
-
action: intent.action,
|
|
270
|
-
timestamp: new Date(),
|
|
271
|
-
result: 'rejected',
|
|
272
|
-
})
|
|
273
|
-
return {
|
|
274
|
-
status: 'validation_failed',
|
|
275
|
-
error: { targetPath: intent.targetPath, action: intent.action, issues: validation.issues },
|
|
276
|
-
hint: `Correct and re-emit. Attempt ${correctionCount + 1}/${MAX_SELF_CORRECTION_RETRIES}.`,
|
|
277
|
-
}
|
|
388
|
+
if (!finalResult.isComplete) {
|
|
389
|
+
const result: PlanNodeResult = {
|
|
390
|
+
structuredOutput: finalResult.structuredOutput,
|
|
391
|
+
artifacts: finalResult.artifacts,
|
|
392
|
+
notes: 'Execution incomplete: missing required deliverables or validation failures.',
|
|
278
393
|
}
|
|
394
|
+
deps.nodeWorkspaceService.cleanup(workspace)
|
|
395
|
+
return result
|
|
396
|
+
}
|
|
279
397
|
|
|
280
|
-
nodeWorkspaceService.stageWrite(workspace, intent, 'validated')
|
|
281
|
-
return { status: 'accepted', message: `Write to "${intent.targetPath}" validated and staged.` }
|
|
282
|
-
},
|
|
283
|
-
})
|
|
284
|
-
|
|
285
|
-
const graphTools = { ...tools, writeIntent: writeIntentTool }
|
|
286
|
-
|
|
287
|
-
const agent = agentFactory({
|
|
288
|
-
mode: dispatchMode,
|
|
289
|
-
tools: graphTools,
|
|
290
|
-
extraInstructions:
|
|
291
|
-
typeof runtimeConfig.extraInstructions === 'string' ? runtimeConfig.extraInstructions : undefined,
|
|
292
|
-
maxRetries: 1,
|
|
293
|
-
stopWhen: [stepCountIs(maxSteps)],
|
|
294
|
-
}) as ToolLoopAgent<never, ToolSet>
|
|
295
|
-
|
|
296
|
-
await agent.generate({ prompt: buildWriteIntentDispatchPrompt(params.nodeSpec) })
|
|
297
|
-
|
|
298
|
-
const finalResult = nodeWorkspaceService.finalize(workspace)
|
|
299
|
-
|
|
300
|
-
if (!finalResult.isComplete) {
|
|
301
398
|
const result: PlanNodeResult = {
|
|
302
399
|
structuredOutput: finalResult.structuredOutput,
|
|
303
400
|
artifacts: finalResult.artifacts,
|
|
304
|
-
notes:
|
|
401
|
+
notes: finalResult.notes,
|
|
305
402
|
}
|
|
306
|
-
|
|
403
|
+
|
|
404
|
+
deps.nodeWorkspaceService.cleanup(workspace)
|
|
307
405
|
return result
|
|
308
|
-
}
|
|
406
|
+
})
|
|
407
|
+
}
|
|
408
|
+
}
|
|
309
409
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
410
|
+
interface AgentExecutorDeps {
|
|
411
|
+
db: SurrealDBService
|
|
412
|
+
nodeWorkspaceService: ReturnType<typeof makeNodeWorkspaceService>
|
|
413
|
+
writeIntentValidatorService: ReturnType<typeof makeWriteIntentValidatorService>
|
|
414
|
+
}
|
|
315
415
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
}
|
|
416
|
+
export function makeAgentExecutorService(deps: AgentExecutorDeps) {
|
|
417
|
+
return { validateOwner, executeNode: createExecuteNode(deps) }
|
|
319
418
|
}
|
|
320
419
|
|
|
321
|
-
export
|
|
420
|
+
export class AgentExecutorServiceTag extends Context.Service<
|
|
421
|
+
AgentExecutorServiceTag,
|
|
422
|
+
ReturnType<typeof makeAgentExecutorService>
|
|
423
|
+
>()('AgentExecutorService') {}
|
|
424
|
+
|
|
425
|
+
export const AgentExecutorServiceLive = Layer.effect(
|
|
426
|
+
AgentExecutorServiceTag,
|
|
427
|
+
Effect.gen(function* () {
|
|
428
|
+
const db = yield* DatabaseServiceTag
|
|
429
|
+
const nodeWorkspaceService = yield* NodeWorkspaceServiceTag
|
|
430
|
+
const writeIntentValidatorService = yield* WriteIntentValidatorServiceTag
|
|
431
|
+
return makeAgentExecutorService({ db, nodeWorkspaceService, writeIntentValidatorService })
|
|
432
|
+
}),
|
|
433
|
+
)
|