@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
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
import { ConsultTeamArgsSchema, withMessageCreatedAt } from '@lota-sdk/shared'
|
|
2
|
+
import type { ChatMessage, ConsultTeamResultData } from '@lota-sdk/shared'
|
|
3
|
+
import { convertToModelMessages, tool as createTool } from 'ai'
|
|
4
|
+
import { Schema, Effect, Fiber, Queue, Ref } from 'effect'
|
|
5
|
+
|
|
6
|
+
import { getAgentDisplayNames, getTeamConsultParticipants } from '../../config/agent-defaults'
|
|
7
|
+
import { nowEpochMillis } from '../../utils/date-time'
|
|
8
|
+
import { createTimedAbortSignal } from '../agent-stream-helpers'
|
|
9
|
+
import { buildModelInputMessagesWithUploadMetadata, buildReadableUploadMetadataText } from '../chat-attachments'
|
|
10
|
+
import type { ReadableUploadMetadataLike } from '../chat-attachments'
|
|
11
|
+
import type { RepoSectionName } from '../indexed-repositories-policy'
|
|
12
|
+
import { extractMessageText } from '../thread-chat-helpers'
|
|
13
|
+
import { buildTeamConsultationFailureMessage } from './team-consultation-prompts'
|
|
14
|
+
|
|
15
|
+
export type DefaultRepoSections = RepoSectionName[]
|
|
16
|
+
const TEAM_CONSULTATION_TIMEOUT_MS = 90_000
|
|
17
|
+
|
|
18
|
+
class TeamConsultationError extends Schema.TaggedErrorClass<TeamConsultationError>()('TeamConsultationError', {
|
|
19
|
+
message: Schema.String,
|
|
20
|
+
cause: Schema.optional(Schema.Defect),
|
|
21
|
+
}) {}
|
|
22
|
+
|
|
23
|
+
function buildSnapshot(responses: ConsultTeamResultData['responses']): ConsultTeamResultData {
|
|
24
|
+
return { responses: responses.map((response) => ({ ...response })) }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getConsultTeamOutput(output: unknown): ConsultTeamResultData | undefined {
|
|
28
|
+
if (output && typeof output === 'object' && Array.isArray((output as { responses?: unknown }).responses)) {
|
|
29
|
+
return output as ConsultTeamResultData
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (Array.isArray(output)) {
|
|
33
|
+
for (let index = output.length - 1; index >= 0; index -= 1) {
|
|
34
|
+
const candidate = getConsultTeamOutput(output[index])
|
|
35
|
+
if (candidate) return candidate
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return undefined
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function findLastUserMessage(
|
|
43
|
+
messages: ChatMessage[],
|
|
44
|
+
predicate: (message: ChatMessage) => boolean,
|
|
45
|
+
): ChatMessage | null {
|
|
46
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
47
|
+
const message = messages[index]
|
|
48
|
+
if (predicate(message)) {
|
|
49
|
+
return message
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function selectTeamConsultationContextMessages(messages: ChatMessage[], latestUserMessageId: string): ChatMessage[] {
|
|
57
|
+
const latestUserMessage =
|
|
58
|
+
findLastUserMessage(messages, (message) => message.id === latestUserMessageId && message.role === 'user') ??
|
|
59
|
+
findLastUserMessage(messages, (message) => message.role === 'user')
|
|
60
|
+
|
|
61
|
+
return latestUserMessage ? [latestUserMessage] : []
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
interface ParticipantObserver {
|
|
65
|
+
run<T>(fn: () => T | Promise<T>): Promise<T>
|
|
66
|
+
recordError?: (error: unknown) => void
|
|
67
|
+
recordAbort?: (error: unknown) => void
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface TeamConsultationParticipantRunner {
|
|
71
|
+
buildParticipantAgent(
|
|
72
|
+
agentId: string,
|
|
73
|
+
params: {
|
|
74
|
+
task: string
|
|
75
|
+
systemWorkspaceDetails?: string
|
|
76
|
+
preSeededMemoriesSection?: string
|
|
77
|
+
retrievedKnowledgeSection?: string
|
|
78
|
+
},
|
|
79
|
+
): Promise<{
|
|
80
|
+
agent: {
|
|
81
|
+
generate(params: Record<string, unknown>): Promise<{ text: string }>
|
|
82
|
+
stream(
|
|
83
|
+
params: Record<string, unknown>,
|
|
84
|
+
): Promise<{
|
|
85
|
+
consumeStream(): unknown
|
|
86
|
+
toUIMessageStream(options: Record<string, unknown>): ReadableStream<unknown>
|
|
87
|
+
}>
|
|
88
|
+
}
|
|
89
|
+
observer: ParticipantObserver
|
|
90
|
+
}>
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface CreateConsultTeamToolParams {
|
|
94
|
+
historyMessages: ChatMessage[]
|
|
95
|
+
latestUserMessageId: string
|
|
96
|
+
availableUploads: ReadableUploadMetadataLike[]
|
|
97
|
+
defaultRepoSectionsByAgent: Record<string, DefaultRepoSections | undefined>
|
|
98
|
+
systemWorkspaceDetails?: string
|
|
99
|
+
getPreSeededMemoriesSection: (agentId: string) => Promise<string | undefined>
|
|
100
|
+
retrievedKnowledgeSection?: string
|
|
101
|
+
displayNamesById?: Partial<Record<string, string>>
|
|
102
|
+
abortSignal: AbortSignal
|
|
103
|
+
participantRunner: TeamConsultationParticipantRunner
|
|
104
|
+
onReadError?: (agentId: string, error: unknown) => void
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Sentinel pushed into the snapshot queue to signal that all workers are done. */
|
|
108
|
+
const DONE = Symbol('done')
|
|
109
|
+
|
|
110
|
+
type ConsultTeamSnapshotItem = ConsultTeamResultData | typeof DONE
|
|
111
|
+
|
|
112
|
+
interface ConsultTeamStreamResources {
|
|
113
|
+
snapshotQueue: Queue.Queue<ConsultTeamSnapshotItem>
|
|
114
|
+
workerFiber: Fiber.Fiber<unknown, unknown>
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
type TeamConsultationResourcesError = TeamConsultationError
|
|
118
|
+
|
|
119
|
+
function createConsultTeamStreamResources(params: {
|
|
120
|
+
task: string
|
|
121
|
+
uploadMetadataText: string
|
|
122
|
+
teamConsultParticipants: readonly string[]
|
|
123
|
+
resolveDisplayName: (agentId: string) => string
|
|
124
|
+
historyMessages: ChatMessage[]
|
|
125
|
+
latestUserMessageId: string
|
|
126
|
+
availableUploads: ReadableUploadMetadataLike[]
|
|
127
|
+
systemWorkspaceDetails?: string
|
|
128
|
+
getPreSeededMemoriesSection: (agentId: string) => Promise<string | undefined>
|
|
129
|
+
retrievedKnowledgeSection?: string
|
|
130
|
+
abortSignal: AbortSignal
|
|
131
|
+
participantRunner: TeamConsultationParticipantRunner
|
|
132
|
+
onReadError?: (agentId: string, error: unknown) => void
|
|
133
|
+
}): Effect.Effect<ConsultTeamStreamResources, TeamConsultationError> {
|
|
134
|
+
return Effect.gen(function* () {
|
|
135
|
+
const initialResponses: ConsultTeamResultData['responses'] = params.teamConsultParticipants.map((agentId) => ({
|
|
136
|
+
agentId,
|
|
137
|
+
agentName: params.resolveDisplayName(agentId),
|
|
138
|
+
status: 'running',
|
|
139
|
+
}))
|
|
140
|
+
|
|
141
|
+
const snapshotQueue = yield* Queue.bounded<ConsultTeamSnapshotItem>(params.teamConsultParticipants.length + 2)
|
|
142
|
+
const responsesRef = yield* Ref.make([...initialResponses])
|
|
143
|
+
|
|
144
|
+
const pushSnapshot = Effect.flatMap(Ref.get(responsesRef), (current) =>
|
|
145
|
+
Queue.offer(snapshotQueue, buildSnapshot(current)),
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
const runParticipantEffect = (agentId: string, index: number) => {
|
|
149
|
+
const agentName = params.resolveDisplayName(agentId)
|
|
150
|
+
const timedAbort = createTimedAbortSignal(params.abortSignal, TEAM_CONSULTATION_TIMEOUT_MS)
|
|
151
|
+
const toTeamConsultationError = (message: string, cause?: unknown) =>
|
|
152
|
+
new TeamConsultationError({ message, cause })
|
|
153
|
+
|
|
154
|
+
const generateAndRecord = Effect.gen(function* () {
|
|
155
|
+
const preSeededMemoriesSection = yield* Effect.tryPromise({
|
|
156
|
+
try: () => params.getPreSeededMemoriesSection(agentId),
|
|
157
|
+
catch: (error) => toTeamConsultationError(`Failed to load pre-seeded memories for ${agentName}.`, error),
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
const { agent, observer } = yield* Effect.tryPromise({
|
|
161
|
+
try: () =>
|
|
162
|
+
params.participantRunner.buildParticipantAgent(agentId, {
|
|
163
|
+
task: params.task,
|
|
164
|
+
systemWorkspaceDetails: params.systemWorkspaceDetails,
|
|
165
|
+
preSeededMemoriesSection,
|
|
166
|
+
retrievedKnowledgeSection: params.retrievedKnowledgeSection,
|
|
167
|
+
}),
|
|
168
|
+
catch: (error) => toTeamConsultationError(`Failed to build team participant agent for ${agentName}.`, error),
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
const modelMessages = yield* Effect.tryPromise({
|
|
172
|
+
try: () =>
|
|
173
|
+
convertToModelMessages(
|
|
174
|
+
buildModelInputMessagesWithUploadMetadata({
|
|
175
|
+
messages: selectTeamConsultationContextMessages(params.historyMessages, params.latestUserMessageId),
|
|
176
|
+
latestUserMessageId: params.latestUserMessageId,
|
|
177
|
+
uploadMetadataText: params.uploadMetadataText,
|
|
178
|
+
}),
|
|
179
|
+
{ ignoreIncompleteToolCalls: true },
|
|
180
|
+
),
|
|
181
|
+
catch: (error) => toTeamConsultationError(`Failed to build model messages for ${agentName}.`, error),
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
const result = yield* Effect.tryPromise({
|
|
185
|
+
try: () =>
|
|
186
|
+
observer.run(() =>
|
|
187
|
+
agent.generate({
|
|
188
|
+
messages: modelMessages,
|
|
189
|
+
abortSignal: timedAbort.signal,
|
|
190
|
+
timeout: TEAM_CONSULTATION_TIMEOUT_MS,
|
|
191
|
+
}),
|
|
192
|
+
),
|
|
193
|
+
catch: (error) => {
|
|
194
|
+
if (params.abortSignal.aborted || timedAbort.signal.aborted) {
|
|
195
|
+
observer.recordAbort?.(error)
|
|
196
|
+
} else {
|
|
197
|
+
observer.recordError?.(error)
|
|
198
|
+
}
|
|
199
|
+
return toTeamConsultationError(`Team participant ${agentName} failed.`, error)
|
|
200
|
+
},
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
const responseText = result.text.trim()
|
|
204
|
+
if (!responseText) {
|
|
205
|
+
return yield* new TeamConsultationError({
|
|
206
|
+
message: `Team participant ${agentName} did not produce a response.`,
|
|
207
|
+
})
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const message = withMessageCreatedAt(
|
|
211
|
+
{
|
|
212
|
+
id: Bun.randomUUIDv7(),
|
|
213
|
+
role: 'assistant',
|
|
214
|
+
parts: [{ type: 'text', text: responseText }],
|
|
215
|
+
metadata: { agentId, agentName },
|
|
216
|
+
} satisfies ChatMessage,
|
|
217
|
+
nowEpochMillis(),
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
yield* Ref.update(responsesRef, (prev) => {
|
|
221
|
+
const next = [...prev]
|
|
222
|
+
next[index] = {
|
|
223
|
+
agentId,
|
|
224
|
+
agentName,
|
|
225
|
+
status: 'complete',
|
|
226
|
+
summary: extractMessageText(message).trim() || undefined,
|
|
227
|
+
message,
|
|
228
|
+
}
|
|
229
|
+
return next
|
|
230
|
+
})
|
|
231
|
+
yield* pushSnapshot
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
return generateAndRecord.pipe(
|
|
235
|
+
Effect.catch((error) => {
|
|
236
|
+
// Parent abort is fatal — re-fail so structured concurrency interrupts siblings.
|
|
237
|
+
if (params.abortSignal.aborted) {
|
|
238
|
+
return Effect.fail(error)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return Ref.update(responsesRef, (prev) => {
|
|
242
|
+
const next = [...prev]
|
|
243
|
+
next[index] = {
|
|
244
|
+
agentId,
|
|
245
|
+
agentName,
|
|
246
|
+
status: 'error',
|
|
247
|
+
error: buildTeamConsultationFailureMessage(
|
|
248
|
+
agentName,
|
|
249
|
+
TEAM_CONSULTATION_TIMEOUT_MS,
|
|
250
|
+
timedAbort.didTimeout(),
|
|
251
|
+
error,
|
|
252
|
+
),
|
|
253
|
+
}
|
|
254
|
+
return next
|
|
255
|
+
}).pipe(Effect.andThen(pushSnapshot))
|
|
256
|
+
}),
|
|
257
|
+
Effect.ensuring(Effect.sync(() => timedAbort.dispose())),
|
|
258
|
+
)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const workersEffect = Effect.forEach(
|
|
262
|
+
params.teamConsultParticipants,
|
|
263
|
+
(agentId, index) => runParticipantEffect(agentId, index),
|
|
264
|
+
{ concurrency: 'unbounded' },
|
|
265
|
+
).pipe(Effect.ensuring(Queue.offer(snapshotQueue, DONE)))
|
|
266
|
+
|
|
267
|
+
yield* pushSnapshot
|
|
268
|
+
const workerFiber = yield* Effect.forkChild(workersEffect)
|
|
269
|
+
|
|
270
|
+
return { snapshotQueue, workerFiber }
|
|
271
|
+
})
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
class ConsultTeamSnapshotIterable implements AsyncIterableIterator<ConsultTeamResultData> {
|
|
275
|
+
private readonly initPromise: Promise<ConsultTeamStreamResources>
|
|
276
|
+
private closed = false
|
|
277
|
+
private completed = false
|
|
278
|
+
|
|
279
|
+
constructor(params: CreateConsultTeamToolParams, task: string) {
|
|
280
|
+
const teamConsultParticipants = getTeamConsultParticipants()
|
|
281
|
+
const uploadMetadataText = buildReadableUploadMetadataText(params.availableUploads)
|
|
282
|
+
const agentDisplayNames = getAgentDisplayNames()
|
|
283
|
+
const resolveDisplayName = (agentId: string) => {
|
|
284
|
+
if (params.displayNamesById && Object.hasOwn(params.displayNamesById, agentId)) {
|
|
285
|
+
const override = params.displayNamesById[agentId]
|
|
286
|
+
if (override !== undefined) {
|
|
287
|
+
return override
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return agentDisplayNames[agentId] ?? agentId
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
this.initPromise = Effect.runPromise(
|
|
295
|
+
createConsultTeamStreamResources({
|
|
296
|
+
task,
|
|
297
|
+
uploadMetadataText,
|
|
298
|
+
teamConsultParticipants,
|
|
299
|
+
resolveDisplayName,
|
|
300
|
+
historyMessages: params.historyMessages,
|
|
301
|
+
latestUserMessageId: params.latestUserMessageId,
|
|
302
|
+
availableUploads: params.availableUploads,
|
|
303
|
+
systemWorkspaceDetails: params.systemWorkspaceDetails,
|
|
304
|
+
getPreSeededMemoriesSection: params.getPreSeededMemoriesSection,
|
|
305
|
+
retrievedKnowledgeSection: params.retrievedKnowledgeSection,
|
|
306
|
+
abortSignal: params.abortSignal,
|
|
307
|
+
participantRunner: params.participantRunner,
|
|
308
|
+
onReadError: params.onReadError,
|
|
309
|
+
}),
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private initResourcesEffect(): Effect.Effect<ConsultTeamStreamResources, TeamConsultationResourcesError> {
|
|
314
|
+
return Effect.tryPromise({
|
|
315
|
+
try: () => this.initPromise,
|
|
316
|
+
catch: (error) =>
|
|
317
|
+
new TeamConsultationError({ message: 'Failed to initialize team consultation stream.', cause: error }),
|
|
318
|
+
})
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
private cleanupEffect(
|
|
322
|
+
snapshotQueue: Queue.Queue<ConsultTeamSnapshotItem>,
|
|
323
|
+
workerFiber: Fiber.Fiber<unknown, unknown>,
|
|
324
|
+
): Effect.Effect<void, never> {
|
|
325
|
+
return Effect.andThen(Fiber.interrupt(workerFiber), Queue.shutdown(snapshotQueue))
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<ConsultTeamResultData> {
|
|
329
|
+
return this
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
next(): Promise<IteratorResult<ConsultTeamResultData>> {
|
|
333
|
+
if (this.closed) {
|
|
334
|
+
return Promise.resolve({ done: true, value: undefined as never })
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return Effect.runPromise(
|
|
338
|
+
Effect.gen(
|
|
339
|
+
function* (this: ConsultTeamSnapshotIterable) {
|
|
340
|
+
const { snapshotQueue, workerFiber } = yield* this.initResourcesEffect()
|
|
341
|
+
|
|
342
|
+
if (this.completed) {
|
|
343
|
+
return { done: true, value: undefined as never }
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const item = yield* Queue.take(snapshotQueue)
|
|
347
|
+
if (item === DONE) {
|
|
348
|
+
this.completed = true
|
|
349
|
+
yield* this.cleanupEffect(snapshotQueue, workerFiber)
|
|
350
|
+
return { done: true, value: undefined as never }
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return { done: false, value: item }
|
|
354
|
+
}.bind(this),
|
|
355
|
+
),
|
|
356
|
+
)
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return(): Promise<IteratorResult<ConsultTeamResultData>> {
|
|
360
|
+
this.closed = true
|
|
361
|
+
return Effect.runPromise(
|
|
362
|
+
Effect.gen(
|
|
363
|
+
function* (this: ConsultTeamSnapshotIterable) {
|
|
364
|
+
const { snapshotQueue, workerFiber } = yield* this.initResourcesEffect()
|
|
365
|
+
yield* this.cleanupEffect(snapshotQueue, workerFiber)
|
|
366
|
+
return { done: true, value: undefined as never }
|
|
367
|
+
}.bind(this),
|
|
368
|
+
),
|
|
369
|
+
)
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
throw(error: unknown): Promise<never> {
|
|
373
|
+
this.closed = true
|
|
374
|
+
return Effect.runPromise(
|
|
375
|
+
Effect.gen(
|
|
376
|
+
function* (this: ConsultTeamSnapshotIterable) {
|
|
377
|
+
const { snapshotQueue, workerFiber } = yield* this.initResourcesEffect()
|
|
378
|
+
yield* this.cleanupEffect(snapshotQueue, workerFiber)
|
|
379
|
+
return yield* Effect.fail(error as never)
|
|
380
|
+
}.bind(this),
|
|
381
|
+
),
|
|
382
|
+
)
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export function createConsultTeamTool(params: CreateConsultTeamToolParams) {
|
|
387
|
+
const teamConsultParticipants = getTeamConsultParticipants()
|
|
388
|
+
const agentDisplayNames = getAgentDisplayNames()
|
|
389
|
+
const resolveDisplayName = (agentId: string) => {
|
|
390
|
+
if (params.displayNamesById && Object.hasOwn(params.displayNamesById, agentId)) {
|
|
391
|
+
const override = params.displayNamesById[agentId]
|
|
392
|
+
if (override !== undefined) {
|
|
393
|
+
return override
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return agentDisplayNames[agentId] ?? agentId
|
|
398
|
+
}
|
|
399
|
+
const participantNames = teamConsultParticipants
|
|
400
|
+
.map((agentId) => resolveDisplayName(agentId))
|
|
401
|
+
.filter((value) => value.trim().length > 0)
|
|
402
|
+
const participantSummary =
|
|
403
|
+
participantNames.length > 0 ? participantNames.join(', ') : 'the configured specialist participants'
|
|
404
|
+
|
|
405
|
+
return createTool({
|
|
406
|
+
description: `Consult the specialist team in parallel before replying. Use this when the answer benefits from structured input across ${participantSummary}.`,
|
|
407
|
+
inputSchema: ConsultTeamArgsSchema,
|
|
408
|
+
execute: ({ task }) => new ConsultTeamSnapshotIterable(params, task),
|
|
409
|
+
toModelOutput: ({ output }) => {
|
|
410
|
+
const result = getConsultTeamOutput(output)
|
|
411
|
+
const summaryLines =
|
|
412
|
+
result?.responses
|
|
413
|
+
.map((response) => {
|
|
414
|
+
const summary =
|
|
415
|
+
typeof response.error === 'string' && response.error.trim().length > 0
|
|
416
|
+
? response.error.trim()
|
|
417
|
+
: typeof response.summary === 'string' && response.summary.trim().length > 0
|
|
418
|
+
? response.summary.trim()
|
|
419
|
+
: 'No response.'
|
|
420
|
+
return `${response.agentName}: ${summary}`
|
|
421
|
+
})
|
|
422
|
+
.join('\n') ?? 'Team consultation completed.'
|
|
423
|
+
|
|
424
|
+
return { type: 'text', value: summaryLines }
|
|
425
|
+
},
|
|
426
|
+
})
|
|
427
|
+
}
|
package/src/runtime/{team-consultation-prompts.ts → team-consultation/team-consultation-prompts.ts}
RENAMED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getAgentDisplayNames, getLeadAgentDisplayName } from '../../config/agent-defaults'
|
|
2
|
+
|
|
3
|
+
function resolveDisplayName(agentId: string): string {
|
|
4
|
+
return getAgentDisplayNames()[agentId] ?? agentId
|
|
5
|
+
}
|
|
2
6
|
|
|
3
7
|
export function buildTeamConsultationResponseGuard(params: { agentId: string; task: string }) {
|
|
4
|
-
const agentName =
|
|
8
|
+
const agentName = resolveDisplayName(params.agentId)
|
|
5
9
|
const leadAgentDisplayName = getLeadAgentDisplayName()
|
|
6
10
|
const mentorConstraint =
|
|
7
11
|
params.agentId === 'mentor'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { toTimestamp } from '@lota-sdk/shared'
|
|
2
2
|
import type { ChatMessage } from '@lota-sdk/shared'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { getAgentDisplayNames, resolveAgentNameAlias } from '../config/agent-defaults'
|
|
5
5
|
import type { ChatMessageLike, ReadableUploadMetadataLike } from './chat-types'
|
|
6
6
|
|
|
7
7
|
export interface ThreadHistoryMessage {
|
|
@@ -35,7 +35,7 @@ function getAgentName(message: ChatMessageLike): string | undefined {
|
|
|
35
35
|
const value = (metadata as Record<string, unknown>).agentName
|
|
36
36
|
if (typeof value !== 'string' || !value.trim()) return undefined
|
|
37
37
|
const resolvedAgentName = resolveAgentNameAlias(value)
|
|
38
|
-
return resolvedAgentName ? (
|
|
38
|
+
return resolvedAgentName ? (getAgentDisplayNames()[resolvedAgentName] ?? value.trim()) : value.trim()
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export function extractMessageText(message: ChatMessageLike): string {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SUBMIT_PLAN_TURN_RESULT_TOOL_NAME, withMessageCreatedAt } from '@lota-sdk/shared'
|
|
2
2
|
import type { ChatMessage, PlanArtifactSubmission, PlanNodeRunRecord, PlanNodeSpecRecord } from '@lota-sdk/shared'
|
|
3
3
|
|
|
4
|
+
import { nowEpochMillis } from '../utils/date-time'
|
|
4
5
|
import { buildCompletionCheckStructuredOutputHints } from './agent-runtime-policy'
|
|
5
6
|
import { mergeInstructionSections } from './instruction-sections'
|
|
6
7
|
|
|
@@ -125,6 +126,6 @@ export function buildPlanTurnPromptMessage(planTurn: ThreadPlanTurnContext): Cha
|
|
|
125
126
|
],
|
|
126
127
|
metadata: { trigger: 'plan-turn', planRunId: planTurn.runId, planNodeId: planTurn.nodeId },
|
|
127
128
|
},
|
|
128
|
-
|
|
129
|
+
nowEpochMillis(),
|
|
129
130
|
)
|
|
130
131
|
}
|