@lota-sdk/core 0.1.15 → 0.1.17
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/infrastructure/schema/00_identity.surql +0 -2
- package/infrastructure/schema/01_memory.surql +1 -1
- package/infrastructure/schema/02_execution_plan.surql +62 -1
- package/infrastructure/schema/03_learned_skill.surql +1 -1
- package/infrastructure/schema/06_playbook.surql +25 -0
- package/infrastructure/schema/07_institutional_memory.surql +13 -0
- package/infrastructure/schema/08_quality_metrics.surql +17 -0
- package/package.json +12 -8
- package/src/ai/definitions.ts +81 -3
- package/src/ai/embedding-cache.ts +2 -4
- package/src/ai/index.ts +0 -2
- package/src/bifrost/bifrost.ts +2 -7
- package/src/bifrost/cache-headers.ts +8 -0
- package/src/bifrost/index.ts +1 -0
- package/src/config/agent-defaults.ts +31 -21
- package/src/config/agent-types.ts +11 -0
- package/src/config/constants.ts +2 -14
- package/src/config/debug-logger.ts +5 -1
- package/src/config/index.ts +3 -0
- package/src/config/model-constants.ts +16 -34
- package/src/config/search.ts +1 -15
- package/src/create-runtime.ts +269 -178
- package/src/db/cursor-pagination.ts +3 -6
- package/src/db/index.ts +2 -0
- package/src/db/memory-store.helpers.ts +1 -3
- package/src/db/memory-store.rows.ts +7 -7
- package/src/db/memory-store.ts +14 -18
- package/src/db/memory.ts +13 -13
- package/src/db/schema-fingerprint.ts +1 -3
- package/src/db/service.ts +153 -79
- package/src/db/startup.ts +6 -10
- package/src/db/surreal-mutation.ts +43 -0
- package/src/db/tables.ts +7 -0
- package/src/db/workstream-message-row.ts +15 -0
- package/src/embeddings/provider.ts +1 -1
- package/src/queues/context-compaction.queue.ts +15 -46
- package/src/queues/delayed-node-promotion.queue.ts +41 -0
- package/src/queues/document-processor.queue.ts +2 -4
- package/src/queues/index.ts +3 -0
- package/src/queues/memory-consolidation.queue.ts +16 -51
- package/src/queues/plan-scheduler.queue.ts +97 -0
- package/src/queues/post-chat-memory.queue.ts +20 -55
- package/src/queues/queue-factory.ts +100 -0
- package/src/queues/recent-activity-title-refinement.queue.ts +15 -50
- package/src/queues/regular-chat-memory-digest.queue.ts +16 -52
- package/src/queues/skill-extraction.queue.ts +15 -47
- package/src/queues/workstream-title-generation.queue.ts +15 -47
- package/src/redis/connection.ts +6 -0
- package/src/redis/index.ts +1 -1
- package/src/redis/redis-lease-lock.ts +1 -2
- package/src/redis/stream-context.ts +11 -0
- package/src/runtime/agent-runtime-policy.ts +109 -35
- package/src/runtime/approval-continuation.ts +12 -6
- package/src/runtime/context-compaction-runtime.ts +1 -1
- package/src/runtime/context-compaction.ts +24 -64
- package/src/runtime/execution-plan.ts +22 -18
- package/src/runtime/graph-designer.ts +15 -0
- package/src/runtime/helper-model.ts +9 -197
- package/src/runtime/index.ts +3 -1
- package/src/runtime/llm-content.ts +1 -1
- package/src/runtime/memory-block.ts +9 -11
- package/src/runtime/memory-pipeline.ts +6 -9
- package/src/runtime/plugin-resolution.ts +35 -0
- package/src/runtime/plugin-types.ts +72 -0
- package/src/runtime/retrieval-adapters.ts +1 -1
- package/src/runtime/runtime-config.ts +111 -14
- package/src/runtime/runtime-extensions.ts +2 -3
- package/src/runtime/runtime-worker-registry.ts +6 -0
- package/src/runtime/social-chat.ts +752 -0
- package/src/runtime/team-consultation-orchestrator.ts +45 -32
- package/src/runtime/team-consultation-prompts.ts +11 -2
- package/src/runtime/title-helpers.ts +2 -4
- package/src/runtime/workstream-chat-helpers.ts +1 -1
- package/src/services/adaptive-playbook.service.ts +152 -0
- package/src/services/agent-executor.service.ts +292 -0
- package/src/services/artifact-provenance.service.ts +172 -0
- package/src/services/attachment.service.ts +6 -11
- package/src/services/context-compaction.service.ts +72 -55
- package/src/services/context-enrichment.service.ts +33 -0
- package/src/services/coordination-registry.service.ts +117 -0
- package/src/services/document-chunk.service.ts +2 -4
- package/src/services/domain-agent-executor.service.ts +71 -0
- package/src/services/execution-plan.service.ts +269 -50
- package/src/services/feedback-loop.service.ts +96 -0
- package/src/services/global-orchestrator.service.ts +148 -0
- package/src/services/index.ts +27 -0
- package/src/services/institutional-memory.service.ts +145 -0
- package/src/services/learned-skill.service.ts +24 -5
- package/src/services/memory-assessment.service.ts +3 -2
- package/src/services/memory-utils.ts +3 -8
- package/src/services/memory.service.ts +49 -61
- package/src/services/monitoring-window.service.ts +86 -0
- package/src/services/mutating-approval.service.ts +1 -1
- package/src/services/node-workspace.service.ts +155 -0
- package/src/services/notification.service.ts +39 -0
- package/src/services/organization-member.service.ts +11 -4
- package/src/services/organization.service.ts +5 -5
- package/src/services/ownership-dispatcher.service.ts +403 -0
- package/src/services/plan-approval.service.ts +1 -1
- package/src/services/plan-builder.service.ts +1 -0
- package/src/services/plan-checkpoint.service.ts +30 -2
- package/src/services/plan-compiler.service.ts +5 -0
- package/src/services/plan-coordination.service.ts +152 -0
- package/src/services/plan-cycle.service.ts +284 -0
- package/src/services/plan-deadline.service.ts +287 -0
- package/src/services/plan-executor.service.ts +384 -40
- package/src/services/plan-run.service.ts +41 -7
- package/src/services/plan-scheduler.service.ts +240 -0
- package/src/services/plan-template.service.ts +117 -0
- package/src/services/plan-validator.service.ts +84 -2
- package/src/services/plan-workspace.service.ts +83 -0
- package/src/services/playbook-registry.service.ts +67 -0
- package/src/services/plugin-executor.service.ts +103 -0
- package/src/services/quality-metrics.service.ts +132 -0
- package/src/services/recent-activity.service.ts +28 -34
- package/src/services/skill-resolver.service.ts +19 -0
- package/src/services/social-chat-history.service.ts +197 -0
- package/src/services/system-executor.service.ts +105 -0
- package/src/services/workstream-message.service.ts +13 -37
- package/src/services/workstream-plan-registry.service.ts +22 -0
- package/src/services/workstream-title.service.ts +3 -1
- package/src/services/workstream-turn-preparation.service.ts +34 -89
- package/src/services/workstream.service.ts +33 -55
- package/src/services/workstream.types.ts +9 -9
- package/src/services/write-intent-validator.service.ts +81 -0
- package/src/storage/attachment-parser.ts +1 -1
- package/src/storage/attachment-utils.ts +1 -1
- package/src/storage/generated-document-storage.service.ts +3 -2
- package/src/system-agents/context-compaction.agent.ts +2 -0
- package/src/system-agents/delegated-agent-factory.ts +5 -0
- package/src/system-agents/memory-reranker.agent.ts +4 -2
- package/src/system-agents/memory.agent.ts +2 -0
- package/src/system-agents/recent-activity-title-refiner.agent.ts +2 -0
- package/src/system-agents/regular-chat-memory-digest.agent.ts +2 -0
- package/src/system-agents/skill-extractor.agent.ts +2 -0
- package/src/system-agents/skill-manager.agent.ts +2 -0
- package/src/system-agents/title-generator.agent.ts +2 -0
- package/src/tools/execution-plan.tool.ts +17 -23
- package/src/tools/index.ts +0 -1
- package/src/tools/research-topic.tool.ts +2 -0
- package/src/tools/team-think.tool.ts +5 -6
- package/src/utils/async.ts +2 -1
- package/src/utils/date-time.ts +4 -32
- package/src/utils/env.ts +8 -0
- package/src/utils/errors.ts +42 -10
- package/src/utils/index.ts +9 -0
- package/src/utils/string.ts +114 -1
- package/src/workers/index.ts +1 -0
- package/src/workers/regular-chat-memory-digest.helpers.ts +1 -1
- package/src/workers/regular-chat-memory-digest.runner.ts +45 -12
- package/src/workers/skill-extraction.runner.ts +26 -6
- package/src/workers/utils/file-section-chunker.ts +2 -1
- package/src/workers/utils/repo-structure-extractor.ts +2 -2
- package/src/workers/utils/repomix-file-sections.ts +2 -2
- package/src/workers/utils/sandbox-error.ts +11 -2
- package/src/workers/utils/workstream-message-query.ts +14 -25
- package/src/workers/worker-utils.ts +2 -2
- package/src/runtime/workstream-routing-policy.ts +0 -267
- package/src/tools/log-hello-world.tool.ts +0 -17
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { OwnershipDispatchContext, PlanNodeResult, PlanNodeSpec, SystemPlanNodeOwner } from '@lota-sdk/shared'
|
|
2
|
+
|
|
3
|
+
import type { SystemNodeExecutor, PluginNodeExecutionParams } from '../runtime/plugin-types'
|
|
4
|
+
import { getRuntimeConfig } from '../runtime/runtime-config'
|
|
5
|
+
import type { PlanValidationIssueInput } from './plan-validator.service'
|
|
6
|
+
|
|
7
|
+
const BUILT_IN_SYSTEM_EXECUTORS = Object.freeze({
|
|
8
|
+
'plan-runtime': {
|
|
9
|
+
supportedOperations: ['echo-input'],
|
|
10
|
+
async executeNode(params: PluginNodeExecutionParams): Promise<PlanNodeResult> {
|
|
11
|
+
return { structuredOutput: structuredClone(params.inputs), artifacts: [] }
|
|
12
|
+
},
|
|
13
|
+
} satisfies SystemNodeExecutor,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
export function getBuiltInSystemExecutors(): Record<string, SystemNodeExecutor> {
|
|
17
|
+
return Object.fromEntries(Object.entries(BUILT_IN_SYSTEM_EXECUTORS))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getSystemExecutors() {
|
|
21
|
+
return (getRuntimeConfig().systemExecutors ?? getBuiltInSystemExecutors()) as Record<
|
|
22
|
+
string,
|
|
23
|
+
SystemNodeExecutor | undefined
|
|
24
|
+
>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function buildSystemExecutionParams(params: {
|
|
28
|
+
owner: SystemPlanNodeOwner
|
|
29
|
+
nodeSpec: PlanNodeSpec
|
|
30
|
+
resolvedInput: Record<string, unknown>
|
|
31
|
+
context: OwnershipDispatchContext
|
|
32
|
+
}): PluginNodeExecutionParams {
|
|
33
|
+
return {
|
|
34
|
+
operation: params.owner.operation,
|
|
35
|
+
nodeSpec: params.nodeSpec,
|
|
36
|
+
inputs: params.resolvedInput,
|
|
37
|
+
context: {
|
|
38
|
+
organizationId: params.context.organizationId,
|
|
39
|
+
workstreamId: params.context.workstreamId,
|
|
40
|
+
planId: params.context.planId,
|
|
41
|
+
nodeId: params.context.nodeId,
|
|
42
|
+
...(params.context.userId ? { userId: params.context.userId } : {}),
|
|
43
|
+
...(params.context.userName ? { userName: params.context.userName } : {}),
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
class SystemExecutorService {
|
|
49
|
+
validateOwner(owner: SystemPlanNodeOwner, nodeId: string): PlanValidationIssueInput[] {
|
|
50
|
+
const executor = getSystemExecutors()[owner.ref]
|
|
51
|
+
if (!executor) {
|
|
52
|
+
return [
|
|
53
|
+
{
|
|
54
|
+
severity: 'blocking',
|
|
55
|
+
code: 'system_executor_missing',
|
|
56
|
+
message: `Node "${nodeId}" references unknown system executor "${owner.ref}".`,
|
|
57
|
+
nodeId,
|
|
58
|
+
detail: { systemRef: owner.ref },
|
|
59
|
+
},
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!executor.supportedOperations.includes(owner.operation)) {
|
|
64
|
+
return [
|
|
65
|
+
{
|
|
66
|
+
severity: 'blocking',
|
|
67
|
+
code: 'system_operation_missing',
|
|
68
|
+
message: `System executor "${owner.ref}" does not support operation "${owner.operation}".`,
|
|
69
|
+
nodeId,
|
|
70
|
+
detail: { systemRef: owner.ref, operation: owner.operation },
|
|
71
|
+
},
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return []
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async executeNode(params: {
|
|
79
|
+
nodeSpec: PlanNodeSpec
|
|
80
|
+
resolvedInput: Record<string, unknown>
|
|
81
|
+
context: OwnershipDispatchContext
|
|
82
|
+
}): Promise<PlanNodeResult> {
|
|
83
|
+
if (params.nodeSpec.owner.executorType !== 'system') {
|
|
84
|
+
throw new Error(`SystemExecutor cannot execute owner type "${params.nodeSpec.owner.executorType}".`)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const executor = getSystemExecutors()[params.nodeSpec.owner.ref]
|
|
88
|
+
if (!executor || !executor.supportedOperations.includes(params.nodeSpec.owner.operation)) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`System executor ${params.nodeSpec.owner.ref}.${params.nodeSpec.owner.operation} is not registered.`,
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return executor.executeNode(
|
|
95
|
+
buildSystemExecutionParams({
|
|
96
|
+
owner: params.nodeSpec.owner,
|
|
97
|
+
nodeSpec: params.nodeSpec,
|
|
98
|
+
resolvedInput: params.resolvedInput,
|
|
99
|
+
context: params.context,
|
|
100
|
+
}),
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const systemExecutorService = new SystemExecutorService()
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { parseRowMetadata, toTimestamp, withCreatedAtMetadata } from '@lota-sdk/shared'
|
|
1
|
+
import { parseRowMetadata, recordIdSchema, requireTimestamp, withCreatedAtMetadata } from '@lota-sdk/shared'
|
|
4
2
|
import type { ChatMessage } from '@lota-sdk/shared'
|
|
5
3
|
import { RecordId, surql } from 'surrealdb'
|
|
6
4
|
import { z } from 'zod'
|
|
@@ -12,24 +10,10 @@ import { recordIdToString } from '../db/record-id'
|
|
|
12
10
|
import type { RecordIdRef } from '../db/record-id'
|
|
13
11
|
import { databaseService } from '../db/service'
|
|
14
12
|
import { TABLES } from '../db/tables'
|
|
13
|
+
import { WorkstreamMessageRowSchema } from '../db/workstream-message-row'
|
|
14
|
+
import type { WorkstreamMessageRow } from '../db/workstream-message-row'
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
id: z.unknown(),
|
|
18
|
-
workstreamId: z.unknown(),
|
|
19
|
-
messageId: z.string(),
|
|
20
|
-
role: z.enum(['system', 'user', 'assistant']),
|
|
21
|
-
parts: z.array(z.record(z.string(), z.unknown())).optional(),
|
|
22
|
-
metadata: z.record(z.string(), z.unknown()).nullish(),
|
|
23
|
-
createdAt: z.union([z.date(), z.string(), z.number()]),
|
|
24
|
-
updatedAt: z.union([z.date(), z.string(), z.number()]).optional(),
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
type WorkstreamMessageRow = z.infer<typeof WorkstreamMessageRowSchema>
|
|
28
|
-
|
|
29
|
-
const WorkstreamMessageExistingRowSchema = z.object({
|
|
30
|
-
id: z.unknown(),
|
|
31
|
-
createdAt: z.union([z.date(), z.string(), z.number()]),
|
|
32
|
-
})
|
|
16
|
+
const WorkstreamMessageExistingRowSchema = z.object({ id: recordIdSchema, createdAt: z.coerce.date() })
|
|
33
17
|
|
|
34
18
|
function toMessageId(value: string | RecordIdRef): string {
|
|
35
19
|
return recordIdToString(value, TABLES.WORKSTREAM_MESSAGE)
|
|
@@ -44,15 +28,15 @@ function toMessageId(value: string | RecordIdRef): string {
|
|
|
44
28
|
*/
|
|
45
29
|
function toWorkstreamMessageRowId(workstreamId: RecordIdRef, messageId: string): RecordId {
|
|
46
30
|
const workstreamStr = recordIdToString(workstreamId, TABLES.WORKSTREAM)
|
|
47
|
-
const digest =
|
|
31
|
+
const digest = new Bun.CryptoHasher('sha256').update(`${workstreamStr}\0${messageId}`).digest('hex').slice(0, 32)
|
|
48
32
|
return new RecordId(TABLES.WORKSTREAM_MESSAGE, digest)
|
|
49
33
|
}
|
|
50
34
|
|
|
51
35
|
function toChatMessage(row: WorkstreamMessageRow): ChatMessage {
|
|
52
|
-
const rowCreatedAt =
|
|
36
|
+
const rowCreatedAt = requireTimestamp(row.createdAt)
|
|
53
37
|
const metadata = withCreatedAtMetadata(parseRowMetadata(row.metadata), rowCreatedAt)
|
|
54
38
|
|
|
55
|
-
return { id: row.messageId, role: row.role, parts:
|
|
39
|
+
return { id: row.messageId, role: row.role, parts: row.parts as ChatMessage['parts'], metadata }
|
|
56
40
|
}
|
|
57
41
|
|
|
58
42
|
const workstreamPaginationConfig: CursorPaginationConfig = {
|
|
@@ -102,9 +86,7 @@ class WorkstreamMessageService {
|
|
|
102
86
|
WorkstreamMessageExistingRowSchema,
|
|
103
87
|
)
|
|
104
88
|
const persistedCreatedAt =
|
|
105
|
-
existingRow === null
|
|
106
|
-
? (toTimestamp(message.metadata?.createdAt) ?? Date.now())
|
|
107
|
-
: (toTimestamp(existingRow.createdAt) ?? Date.now())
|
|
89
|
+
existingRow === null ? requireTimestamp(message.metadata?.createdAt) : requireTimestamp(existingRow.createdAt)
|
|
108
90
|
const metadata = withCreatedAtMetadata({ ...message.metadata, createdAt: persistedCreatedAt })
|
|
109
91
|
|
|
110
92
|
await databaseService.upsert(
|
|
@@ -116,9 +98,7 @@ class WorkstreamMessageService {
|
|
|
116
98
|
role,
|
|
117
99
|
parts,
|
|
118
100
|
metadata,
|
|
119
|
-
createdAt: existingRow
|
|
120
|
-
? new Date(toTimestamp(existingRow.createdAt) ?? Date.now())
|
|
121
|
-
: new Date(persistedCreatedAt),
|
|
101
|
+
createdAt: existingRow ? existingRow.createdAt : new Date(persistedCreatedAt),
|
|
122
102
|
},
|
|
123
103
|
WorkstreamMessageRowSchema,
|
|
124
104
|
{ mutation: 'content' },
|
|
@@ -152,7 +132,7 @@ class WorkstreamMessageService {
|
|
|
152
132
|
async listMessagesAfterCursor(workstreamId: RecordIdRef, afterMessageId?: string): Promise<ChatMessage[]> {
|
|
153
133
|
const cursorMessageId = afterMessageId?.trim()
|
|
154
134
|
if (!cursorMessageId) {
|
|
155
|
-
return
|
|
135
|
+
return this.listMessages(workstreamId)
|
|
156
136
|
}
|
|
157
137
|
|
|
158
138
|
const cursorRow = await databaseService.findOne(
|
|
@@ -165,7 +145,7 @@ class WorkstreamMessageService {
|
|
|
165
145
|
throw new Error(`Workstream cursor message not found: ${cursorMessageId}`)
|
|
166
146
|
}
|
|
167
147
|
|
|
168
|
-
const cursorCreatedAt =
|
|
148
|
+
const cursorCreatedAt = cursorRow.createdAt
|
|
169
149
|
const cursorId = toWorkstreamMessageRowId(workstreamId, cursorMessageId)
|
|
170
150
|
const rows = await databaseService.query<unknown>(surql`
|
|
171
151
|
SELECT * FROM workstreamMessage
|
|
@@ -209,7 +189,7 @@ class WorkstreamMessageService {
|
|
|
209
189
|
.map((message) => ({
|
|
210
190
|
id: message.id,
|
|
211
191
|
role: message.role as 'user' | 'assistant',
|
|
212
|
-
createdAt: new Date(
|
|
192
|
+
createdAt: new Date(requireTimestamp(message.metadata?.createdAt)).toISOString(),
|
|
213
193
|
content: message.parts
|
|
214
194
|
.flatMap((part) => (part.type === 'text' && typeof part.text === 'string' ? [part.text] : []))
|
|
215
195
|
.join('\n')
|
|
@@ -245,7 +225,7 @@ class WorkstreamMessageService {
|
|
|
245
225
|
id: toMessageId(params.messageId),
|
|
246
226
|
role: 'assistant',
|
|
247
227
|
parts: params.parts,
|
|
248
|
-
metadata: withCreatedAtMetadata(params.metadata),
|
|
228
|
+
metadata: withCreatedAtMetadata(params.metadata, Date.now()),
|
|
249
229
|
}
|
|
250
230
|
|
|
251
231
|
await this.upsertMessages({ workstreamId: params.workstreamId, messages: [message] })
|
|
@@ -283,10 +263,6 @@ class WorkstreamMessageService {
|
|
|
283
263
|
],
|
|
284
264
|
})
|
|
285
265
|
}
|
|
286
|
-
|
|
287
|
-
async listAllMessages(workstreamId: RecordIdRef): Promise<ChatMessage[]> {
|
|
288
|
-
return await this.listMessages(workstreamId)
|
|
289
|
-
}
|
|
290
266
|
}
|
|
291
267
|
|
|
292
268
|
export const workstreamMessageService = new WorkstreamMessageService()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PlanRunRecord, SerializableExecutionPlan } from '@lota-sdk/shared'
|
|
2
|
+
|
|
3
|
+
import type { RecordIdInput } from '../db/record-id'
|
|
4
|
+
import { planRunService } from './plan-run.service'
|
|
5
|
+
|
|
6
|
+
class WorkstreamPlanRegistryService {
|
|
7
|
+
async listActiveRuns(workstreamId: RecordIdInput): Promise<PlanRunRecord[]> {
|
|
8
|
+
return planRunService.getActiveRunRecords(workstreamId)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async countActiveRuns(workstreamId: RecordIdInput): Promise<number> {
|
|
12
|
+
const runs = await this.listActiveRuns(workstreamId)
|
|
13
|
+
return runs.length
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async listActivePlans(workstreamId: RecordIdInput): Promise<SerializableExecutionPlan[]> {
|
|
17
|
+
const runs = await this.listActiveRuns(workstreamId)
|
|
18
|
+
return Promise.all(runs.map((run) => planRunService.toSerializablePlan(run)))
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const workstreamPlanRegistryService = new WorkstreamPlanRegistryService()
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
} from '../system-agents/title-generator.agent'
|
|
11
11
|
import { workstreamService } from './workstream.service'
|
|
12
12
|
|
|
13
|
+
const WORKSTREAM_TITLE_TIMEOUT_MS = 5_000
|
|
14
|
+
|
|
13
15
|
class WorkstreamTitleService {
|
|
14
16
|
helperRuntime = createHelperModelRuntime()
|
|
15
17
|
|
|
@@ -21,7 +23,7 @@ class WorkstreamTitleService {
|
|
|
21
23
|
tag: 'workstream-title',
|
|
22
24
|
createAgent: createWorkstreamTitleGeneratorAgent,
|
|
23
25
|
defaultSystemPrompt: WORKSTREAM_TITLE_GENERATOR_PROMPT,
|
|
24
|
-
timeoutMs:
|
|
26
|
+
timeoutMs: WORKSTREAM_TITLE_TIMEOUT_MS,
|
|
25
27
|
messages: [{ role: 'user', content: sourceText }],
|
|
26
28
|
}),
|
|
27
29
|
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
WORKSTREAM,
|
|
2
3
|
baseChatMessageSchema,
|
|
3
4
|
CONSULT_SPECIALIST_TOOL_NAME,
|
|
4
5
|
CONSULT_TEAM_TOOL_NAME,
|
|
@@ -10,7 +11,7 @@ import {
|
|
|
10
11
|
} from '@lota-sdk/shared'
|
|
11
12
|
import type { ChatMessage, MessageMetadata } from '@lota-sdk/shared'
|
|
12
13
|
import { convertToModelMessages, readUIMessageStream, stepCountIs, tool as createTool, validateUIMessages } from 'ai'
|
|
13
|
-
import type { PrepareStepFunction, StopCondition, ToolSet, UIMessageStreamWriter } from 'ai'
|
|
14
|
+
import type { PrepareStepFunction, StopCondition, ToolLoopAgent, ToolSet, UIMessageStreamWriter } from 'ai'
|
|
14
15
|
import type { z } from 'zod'
|
|
15
16
|
|
|
16
17
|
import type { CoreWorkstreamProfile } from '../config/agent-defaults'
|
|
@@ -21,7 +22,6 @@ import {
|
|
|
21
22
|
getLeadAgentId,
|
|
22
23
|
getCoreWorkstreamProfile,
|
|
23
24
|
getAgentRuntimeConfig,
|
|
24
|
-
pluginRuntime,
|
|
25
25
|
} from '../config/agent-defaults'
|
|
26
26
|
import { lotaDebugLogger } from '../config/debug-logger'
|
|
27
27
|
import { aiLogger } from '../config/logger'
|
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
shouldEnqueueOnboardingPostChatMemory,
|
|
56
56
|
shouldEnqueueRegularDigestForWorkstream,
|
|
57
57
|
} from '../runtime/memory-digest-policy'
|
|
58
|
+
import { buildIndexedRepositoriesContext, getPluginService } from '../runtime/plugin-resolution'
|
|
58
59
|
import { getRuntimeAdapters, getToolProviders, getTurnHooks } from '../runtime/runtime-extensions'
|
|
59
60
|
import { shouldEnqueueSkillExtraction } from '../runtime/skill-extraction-policy'
|
|
60
61
|
import { finalizeTurnRun } from '../runtime/turn-lifecycle'
|
|
@@ -68,11 +69,6 @@ import {
|
|
|
68
69
|
toHistoryMessages,
|
|
69
70
|
toOptionalTrimmedString,
|
|
70
71
|
} from '../runtime/workstream-chat-helpers'
|
|
71
|
-
import {
|
|
72
|
-
classifyHighImpactResponse,
|
|
73
|
-
classifyPolicyClasses,
|
|
74
|
-
resolveReasoningProfile,
|
|
75
|
-
} from '../runtime/workstream-routing-policy'
|
|
76
72
|
import type { WorkstreamState } from '../runtime/workstream-state'
|
|
77
73
|
import { chatRunRegistry } from '../services/chat-run-registry.service'
|
|
78
74
|
import type { NormalizedWorkstream, WorkstreamRecord } from '../services/workstream.types'
|
|
@@ -86,12 +82,11 @@ import { contextCompactionRuntime } from './context-compaction-runtime.singleton
|
|
|
86
82
|
import { executionPlanService } from './execution-plan.service'
|
|
87
83
|
import { learnedSkillService } from './learned-skill.service'
|
|
88
84
|
import { memoryService } from './memory.service'
|
|
85
|
+
import { planRunService } from './plan-run.service'
|
|
89
86
|
import { recentActivityService } from './recent-activity.service'
|
|
90
87
|
import { workstreamMessageService } from './workstream-message.service'
|
|
91
88
|
import { workstreamService } from './workstream.service'
|
|
92
89
|
|
|
93
|
-
type AgentRuntimeConfig = Record<string, unknown>
|
|
94
|
-
type AgentFactory = Record<string, (...args: unknown[]) => Record<string, (...args: unknown[]) => unknown>>
|
|
95
90
|
type ChatStreamChunk = Parameters<UIMessageStreamWriter<ChatMessage>['write']>[0]
|
|
96
91
|
|
|
97
92
|
interface UIMessageStreamResult {
|
|
@@ -106,45 +101,8 @@ function hasUIMessageStream(value: unknown): value is UIMessageStreamResult {
|
|
|
106
101
|
)
|
|
107
102
|
}
|
|
108
103
|
|
|
109
|
-
function getPluginService(path: string[]): ((...args: unknown[]) => unknown) | undefined {
|
|
110
|
-
let current: unknown = pluginRuntime
|
|
111
|
-
let owner: unknown = undefined
|
|
112
|
-
for (const key of path) {
|
|
113
|
-
if (current === null || current === undefined || typeof current !== 'object') return undefined
|
|
114
|
-
owner = current
|
|
115
|
-
current = (current as Record<string, unknown>)[key]
|
|
116
|
-
}
|
|
117
|
-
if (typeof current !== 'function') {
|
|
118
|
-
return undefined
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return owner && typeof owner === 'object'
|
|
122
|
-
? (current as (...args: unknown[]) => unknown).bind(owner)
|
|
123
|
-
: (current as (...args: unknown[]) => unknown)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async function buildIndexedRepositoriesContext(
|
|
127
|
-
workspaceId: string,
|
|
128
|
-
): Promise<{ provideRepoTool: boolean; defaultSectionsByAgent: Record<string, unknown>; context: string }> {
|
|
129
|
-
const buildContext = getRuntimeAdapters().workstream?.buildIndexedRepositoriesContext
|
|
130
|
-
if (!buildContext) {
|
|
131
|
-
return { provideRepoTool: false, defaultSectionsByAgent: {}, context: '' }
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const context = await buildContext(workspaceId)
|
|
135
|
-
return {
|
|
136
|
-
provideRepoTool: context.provideRepoTool,
|
|
137
|
-
defaultSectionsByAgent: context.defaultSectionsByAgent,
|
|
138
|
-
context: context.context ?? '',
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
104
|
const PRESEEDED_MEMORY_LOOKUP_LIMIT = 3
|
|
143
105
|
|
|
144
|
-
function parsePersistedWorkstreamState(value: unknown): WorkstreamState | null {
|
|
145
|
-
return parseWorkstreamState(value)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
106
|
function stripExecutionPlanFieldsFromWorkstreamState(
|
|
149
107
|
state: WorkstreamState | null | undefined,
|
|
150
108
|
hasExecutionPlan: boolean,
|
|
@@ -155,7 +113,7 @@ function stripExecutionPlanFieldsFromWorkstreamState(
|
|
|
155
113
|
}
|
|
156
114
|
|
|
157
115
|
async function waitForWorkstreamCompactionIfNeeded(workstreamId: RecordIdRef): Promise<WorkstreamRecord> {
|
|
158
|
-
return
|
|
116
|
+
return waitForCompactionIfNeeded({
|
|
159
117
|
entityId: recordIdToString(workstreamId, TABLES.WORKSTREAM),
|
|
160
118
|
entityLabel: 'Workstream',
|
|
161
119
|
loadEntity: () => workstreamService.getById(workstreamId),
|
|
@@ -311,7 +269,6 @@ interface StreamAgentResponseContext {
|
|
|
311
269
|
onboardingActive: boolean
|
|
312
270
|
linearInstalled: boolean
|
|
313
271
|
githubInstalled: boolean
|
|
314
|
-
reasoningProfileName: string
|
|
315
272
|
buildContextResult: Record<string, unknown> | null
|
|
316
273
|
getExecutionPlanInstructionSections: () => Promise<string[] | undefined>
|
|
317
274
|
getPreSeededMemoriesSection: (agentId: string) => Promise<string | undefined>
|
|
@@ -361,7 +318,6 @@ async function streamAgentResponse(
|
|
|
361
318
|
onboardingActive: ctx.onboardingActive,
|
|
362
319
|
linearInstalled: ctx.linearInstalled,
|
|
363
320
|
githubInstalled: ctx.githubInstalled,
|
|
364
|
-
reasoningProfile: ctx.reasoningProfileName,
|
|
365
321
|
skills: streamParams.skills,
|
|
366
322
|
additionalInstructionSections: streamParams.additionalInstructionSections,
|
|
367
323
|
context: ctx.buildContextResult,
|
|
@@ -382,7 +338,6 @@ async function streamAgentResponse(
|
|
|
382
338
|
skills: streamParams.skills,
|
|
383
339
|
onboardingActive: ctx.onboardingActive,
|
|
384
340
|
linearInstalled: ctx.linearInstalled,
|
|
385
|
-
reasoningProfile: ctx.reasoningProfileName,
|
|
386
341
|
systemWorkspaceDetails: ctx.promptContext.systemWorkspaceDetails,
|
|
387
342
|
preSeededMemoriesSection,
|
|
388
343
|
retrievedKnowledgeSection: ctx.retrievedKnowledgeSection,
|
|
@@ -397,18 +352,18 @@ async function streamAgentResponse(
|
|
|
397
352
|
optionalInstructionSection(agentResolution?.extraInstructions),
|
|
398
353
|
),
|
|
399
354
|
context: ctx.buildContextResult,
|
|
400
|
-
}) as
|
|
355
|
+
}) as Record<string, unknown>
|
|
401
356
|
agentTimer.step('build-agent-config')
|
|
402
357
|
const modelMessages = await convertToModelMessages(streamParams.messages, { ignoreIncompleteToolCalls: true })
|
|
403
358
|
agentTimer.step('convert-model-messages')
|
|
404
|
-
const agent =
|
|
359
|
+
const agent = createAgent[config.id as string]({
|
|
405
360
|
mode: streamParams.mode,
|
|
406
361
|
tools: streamParams.tools,
|
|
407
362
|
extraInstructions: config.extraInstructions,
|
|
408
363
|
stopWhen: (agentResolution?.stopWhen as StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined) ??
|
|
409
364
|
streamParams.stopWhen ?? [stepCountIs(config.maxSteps as number)],
|
|
410
365
|
prepareStep: (agentResolution?.prepareStep as PrepareStepFunction<ToolSet> | undefined) ?? streamParams.prepareStep,
|
|
411
|
-
})
|
|
366
|
+
}) as ToolLoopAgent<never, ToolSet>
|
|
412
367
|
const agentAbortSignal = streamParams.abortSignal ?? ctx.runAbortSignal
|
|
413
368
|
agentTimer.step('agent-construction')
|
|
414
369
|
|
|
@@ -443,7 +398,7 @@ async function streamAgentResponse(
|
|
|
443
398
|
sendSources: true,
|
|
444
399
|
messageMetadata: createAgentMessageMetadata({ agentId: resolvedAgentId, agentName: config.displayName as string }),
|
|
445
400
|
onFinish: ({ responseMessage: finishedResponseMessage }: { responseMessage: ChatMessage }) => {
|
|
446
|
-
responseMessage = withMessageCreatedAt(finishedResponseMessage)
|
|
401
|
+
responseMessage = withMessageCreatedAt(finishedResponseMessage, Date.now())
|
|
447
402
|
resolveFinishedStream()
|
|
448
403
|
},
|
|
449
404
|
}) as ReadableStream<ChatStreamChunk>
|
|
@@ -474,7 +429,7 @@ async function streamAgentResponse(
|
|
|
474
429
|
}
|
|
475
430
|
|
|
476
431
|
for (const toolError of collectToolOutputErrors({ responseMessage: responseMessage })) {
|
|
477
|
-
aiLogger.
|
|
432
|
+
aiLogger.error`Tool execution failed (agent=${resolvedAgentId}, tool=${toolError.toolName}, toolCallId=${toolError.toolCallId}): ${toolError.errorText}`
|
|
478
433
|
}
|
|
479
434
|
|
|
480
435
|
return responseMessage
|
|
@@ -657,7 +612,7 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
657
612
|
const shouldProcessPostRunSideEffects =
|
|
658
613
|
params.kind === 'approvalContinuation' || params.kind === 'nativeToolApprovalTurn' || shouldPersistInputMessage
|
|
659
614
|
if (params.kind === 'userTurn') {
|
|
660
|
-
inputMessage = hydrateMessageFileUrls(withMessageCreatedAt(params.inputMessage))
|
|
615
|
+
inputMessage = hydrateMessageFileUrls(withMessageCreatedAt(params.inputMessage, Date.now()))
|
|
661
616
|
if (inputMessage.role !== 'user') {
|
|
662
617
|
throw new WorkstreamTurnError('Only user messages can be submitted to the workstream runtime.', 400)
|
|
663
618
|
}
|
|
@@ -691,7 +646,7 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
691
646
|
timer.step('persist-approval-message')
|
|
692
647
|
}
|
|
693
648
|
|
|
694
|
-
const initialWorkstreamState =
|
|
649
|
+
const initialWorkstreamState = parseWorkstreamState(workstreamRecord.state)
|
|
695
650
|
const persistedCompactionCursor = toOptionalTrimmedString(workstreamRecord.lastCompactedMessageId) ?? undefined
|
|
696
651
|
const persistedLiveHistoryPromise = workstreamMessageService.listMessagesAfterCursor(
|
|
697
652
|
workstreamRef,
|
|
@@ -703,10 +658,10 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
703
658
|
if (inputMessage) {
|
|
704
659
|
userMessage = {
|
|
705
660
|
...inputMessage,
|
|
706
|
-
id: inputMessage.id
|
|
661
|
+
id: inputMessage.id,
|
|
707
662
|
role: 'user',
|
|
708
663
|
parts: inputMessage.parts,
|
|
709
|
-
metadata: { ...inputMessage.metadata, createdAt: toTimestamp(inputMessage.metadata?.createdAt)
|
|
664
|
+
metadata: { ...inputMessage.metadata, createdAt: toTimestamp(inputMessage.metadata?.createdAt) },
|
|
710
665
|
}
|
|
711
666
|
}
|
|
712
667
|
|
|
@@ -758,6 +713,7 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
758
713
|
workstream.mode === 'group' &&
|
|
759
714
|
!workstream.core &&
|
|
760
715
|
workstreamRecord.nameGenerated !== true &&
|
|
716
|
+
workstreamRecord.title === WORKSTREAM.DEFAULT_TITLE &&
|
|
761
717
|
messageText.length > 0
|
|
762
718
|
) {
|
|
763
719
|
void safeEnqueue(
|
|
@@ -789,15 +745,6 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
789
745
|
'getInstallationForOrganization',
|
|
790
746
|
])
|
|
791
747
|
|
|
792
|
-
const highImpactAssessment = classifyHighImpactResponse({ message: messageText })
|
|
793
|
-
const policyAssessment = classifyPolicyClasses({ message: messageText })
|
|
794
|
-
const reasoningProfile = resolveReasoningProfile({
|
|
795
|
-
message: messageText,
|
|
796
|
-
forceDeep: highImpactAssessment.classes.length > 0 || policyAssessment.classes.length > 0,
|
|
797
|
-
explicitProfile: onboardingActive ? 'standard' : undefined,
|
|
798
|
-
})
|
|
799
|
-
timer.step('reasoning-classification')
|
|
800
|
-
|
|
801
748
|
const [linearInstallation, githubInstallation, indexedRepoContext, recentDomainEvents, promptSummary] =
|
|
802
749
|
await Promise.all([
|
|
803
750
|
getLinearInstallationByOrgId ? (getLinearInstallationByOrgId(orgRef) as Promise<unknown>) : Promise.resolve(null),
|
|
@@ -896,18 +843,21 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
896
843
|
let workstreamState = initialWorkstreamState
|
|
897
844
|
const executionPlanInstructionSectionCache = createExecutionPlanInstructionSectionCache({
|
|
898
845
|
disabled: onboardingActive,
|
|
899
|
-
|
|
846
|
+
loadPlans: async () => {
|
|
847
|
+
const runs = await planRunService.getActiveRunRecords(workstreamRef)
|
|
848
|
+
return Promise.all(runs.map((run) => planRunService.toSerializablePlan(run)))
|
|
849
|
+
},
|
|
900
850
|
})
|
|
901
|
-
const
|
|
851
|
+
const getExecutionPlans = async () => await executionPlanInstructionSectionCache.getPlans()
|
|
902
852
|
const getExecutionPlanInstructionSections = async (): Promise<string[] | undefined> =>
|
|
903
853
|
await executionPlanInstructionSectionCache.getSections()
|
|
904
854
|
const invalidateExecutionPlanInstructionSections = () => {
|
|
905
855
|
executionPlanInstructionSectionCache.invalidate()
|
|
906
856
|
}
|
|
907
857
|
const getWorkstreamStateSection = async (): Promise<string | undefined> => {
|
|
908
|
-
const
|
|
858
|
+
const executionPlans = await getExecutionPlans()
|
|
909
859
|
return contextCompactionRuntime.formatWorkstreamStateForPrompt(
|
|
910
|
-
stripExecutionPlanFieldsFromWorkstreamState(workstreamState,
|
|
860
|
+
stripExecutionPlanFieldsFromWorkstreamState(workstreamState, executionPlans.length > 0),
|
|
911
861
|
)
|
|
912
862
|
}
|
|
913
863
|
const respondedBy = recordIdToString(userRef, TABLES.USER)
|
|
@@ -1001,9 +951,6 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1001
951
|
const buildAgentMetadataPatch = (agentId: string, agentName: string): NonNullable<MessageMetadata> => ({
|
|
1002
952
|
agentId,
|
|
1003
953
|
agentName,
|
|
1004
|
-
reasoningProfile: reasoningProfile.name,
|
|
1005
|
-
highImpactClasses: highImpactAssessment.classes,
|
|
1006
|
-
policyClasses: policyAssessment.classes,
|
|
1007
954
|
semanticTerminationReason: 'none',
|
|
1008
955
|
})
|
|
1009
956
|
|
|
@@ -1018,10 +965,10 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1018
965
|
})
|
|
1019
966
|
|
|
1020
967
|
const commitAssistantResponse = async (response: ChatMessage, agentId: string, agentName: string) => {
|
|
1021
|
-
const committed = withMessageCreatedAt(
|
|
1022
|
-
...response,
|
|
1023
|
-
|
|
1024
|
-
|
|
968
|
+
const committed = withMessageCreatedAt(
|
|
969
|
+
{ ...response, metadata: { ...response.metadata, ...buildAgentMetadataPatch(agentId, agentName) } },
|
|
970
|
+
Date.now(),
|
|
971
|
+
)
|
|
1025
972
|
|
|
1026
973
|
await workstreamMessageService.upsertMessages({ workstreamId: workstreamRef, messages: [committed] })
|
|
1027
974
|
currentMessages = upsertChatHistoryMessage(currentMessages, committed)
|
|
@@ -1040,7 +987,6 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1040
987
|
onboardingActive,
|
|
1041
988
|
linearInstalled,
|
|
1042
989
|
githubInstalled,
|
|
1043
|
-
reasoningProfileName: reasoningProfile.name,
|
|
1044
990
|
buildContextResult,
|
|
1045
991
|
getExecutionPlanInstructionSections,
|
|
1046
992
|
getPreSeededMemoriesSection,
|
|
@@ -1063,6 +1009,7 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1063
1009
|
}): Promise<ChatMessage> => {
|
|
1064
1010
|
const visibleTimer = lotaDebugLogger.timer(`visible:${runParams.agentId}`)
|
|
1065
1011
|
let runMemoryBlock = memoryBlock
|
|
1012
|
+
const includeExecutionPlanTools = runParams.mode !== 'fixedWorkstreamMode' && !onboardingActive
|
|
1066
1013
|
const tools: ToolSet = {
|
|
1067
1014
|
...((await buildAgentTools({
|
|
1068
1015
|
agentId: runParams.agentId,
|
|
@@ -1084,7 +1031,7 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1084
1031
|
runMemoryBlock = value
|
|
1085
1032
|
},
|
|
1086
1033
|
availableUploads: listReadableUploads(runParams.extraMessages),
|
|
1087
|
-
includeExecutionPlanTools
|
|
1034
|
+
includeExecutionPlanTools,
|
|
1088
1035
|
onExecutionPlanChanged: invalidateExecutionPlanInstructionSections,
|
|
1089
1036
|
context: buildContextResult,
|
|
1090
1037
|
})) as ToolSet),
|
|
@@ -1107,7 +1054,7 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1107
1054
|
visibleTimer.step('stream-agent-response')
|
|
1108
1055
|
memoryBlock = runMemoryBlock
|
|
1109
1056
|
|
|
1110
|
-
return
|
|
1057
|
+
return commitAssistantResponse(
|
|
1111
1058
|
responseMessage,
|
|
1112
1059
|
runParams.agentId,
|
|
1113
1060
|
agentDisplayNames[runParams.agentId] ?? runParams.agentId,
|
|
@@ -1169,7 +1116,6 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1169
1116
|
mode: 'fixedWorkstreamMode',
|
|
1170
1117
|
onboardingActive,
|
|
1171
1118
|
linearInstalled,
|
|
1172
|
-
reasoningProfile: reasoningProfile.name,
|
|
1173
1119
|
systemWorkspaceDetails: promptContext.systemWorkspaceDetails,
|
|
1174
1120
|
preSeededMemoriesSection: specialistPreSeededMemories,
|
|
1175
1121
|
retrievedKnowledgeSection,
|
|
@@ -1182,14 +1128,14 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1182
1128
|
hookInstructionSections,
|
|
1183
1129
|
),
|
|
1184
1130
|
context: buildContextResult,
|
|
1185
|
-
}) as
|
|
1131
|
+
}) as Record<string, unknown>
|
|
1186
1132
|
const observer = createObserver(agentId)
|
|
1187
|
-
const agent =
|
|
1133
|
+
const agent = createAgent[specialistConfig.id as string]({
|
|
1188
1134
|
mode: 'fixedWorkstreamMode',
|
|
1189
1135
|
tools: { ...(specialistTools as ToolSet), ...toolProviders },
|
|
1190
1136
|
extraInstructions: specialistConfig.extraInstructions,
|
|
1191
1137
|
stopWhen: [stepCountIs(specialistConfig.maxSteps as number)],
|
|
1192
|
-
})
|
|
1138
|
+
}) as ToolLoopAgent<never, ToolSet>
|
|
1193
1139
|
const modelMessages = await convertToModelMessages(buildRunInputMessages([specialistTaskMessage]), {
|
|
1194
1140
|
ignoreIncompleteToolCalls: true,
|
|
1195
1141
|
})
|
|
@@ -1225,7 +1171,7 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1225
1171
|
}),
|
|
1226
1172
|
}) as ReadableStream<never>,
|
|
1227
1173
|
})) {
|
|
1228
|
-
finalMessage = withMessageCreatedAt(message)
|
|
1174
|
+
finalMessage = withMessageCreatedAt(message, Date.now())
|
|
1229
1175
|
yield finalMessage
|
|
1230
1176
|
}
|
|
1231
1177
|
|
|
@@ -1266,7 +1212,6 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1266
1212
|
availableUploads: listReadableUploads(),
|
|
1267
1213
|
provideRepoTool: indexedRepoContext.provideRepoTool,
|
|
1268
1214
|
defaultRepoSectionsByAgent: indexedRepoContext.defaultSectionsByAgent as never,
|
|
1269
|
-
reasoningProfile: reasoningProfile.name,
|
|
1270
1215
|
systemWorkspaceDetails: promptContext.systemWorkspaceDetails,
|
|
1271
1216
|
getPreSeededMemoriesSection,
|
|
1272
1217
|
retrievedKnowledgeSection,
|
|
@@ -1301,7 +1246,7 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1301
1246
|
} finally {
|
|
1302
1247
|
try {
|
|
1303
1248
|
const latestWorkstreamRecord = await workstreamService.getById(workstreamRef)
|
|
1304
|
-
const latestPersistedState =
|
|
1249
|
+
const latestPersistedState = parseWorkstreamState(latestWorkstreamRecord.state)
|
|
1305
1250
|
|
|
1306
1251
|
await finalizeTurnRun({
|
|
1307
1252
|
serverRunId,
|