@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
|
@@ -99,7 +99,7 @@ function requireDirectAgentId(agentId: string | undefined): string {
|
|
|
99
99
|
return agentId
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
function
|
|
102
|
+
function requireString(coreType: string | undefined): string {
|
|
103
103
|
if (!coreType) {
|
|
104
104
|
throw new Error('Core workstreams require a coreType')
|
|
105
105
|
}
|
|
@@ -174,7 +174,7 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
174
174
|
return options.title
|
|
175
175
|
}
|
|
176
176
|
if (core) {
|
|
177
|
-
return getCoreWorkstreamProfile(
|
|
177
|
+
return getCoreWorkstreamProfile(requireString(coreType)).config.title
|
|
178
178
|
}
|
|
179
179
|
if (mode === 'direct') {
|
|
180
180
|
return getAgentDisplayName(requireDirectAgentId(directAgentId))
|
|
@@ -220,7 +220,7 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
if (core) {
|
|
223
|
-
const resolvedCoreType =
|
|
223
|
+
const resolvedCoreType = requireString(coreType)
|
|
224
224
|
const coreProfile = getCoreWorkstreamProfile(resolvedCoreType)
|
|
225
225
|
const coreWorkstreamId = buildCoreWorkstreamId({ userId, orgId, coreType: resolvedCoreType })
|
|
226
226
|
const existing = await this.findById(coreWorkstreamId)
|
|
@@ -273,6 +273,7 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
273
273
|
core: false,
|
|
274
274
|
title,
|
|
275
275
|
status: 'regular',
|
|
276
|
+
nameGenerated: options?.title !== undefined && options.title !== WORKSTREAM.DEFAULT_TITLE,
|
|
276
277
|
})
|
|
277
278
|
|
|
278
279
|
return this.normalizeWorkstream(groupWorkstream)
|
|
@@ -294,7 +295,7 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
294
295
|
)
|
|
295
296
|
|
|
296
297
|
const hasStandardGroupWorkstream = existingWorkstreams.some(
|
|
297
|
-
(workstream) => workstream.mode === 'group' && workstream.core
|
|
298
|
+
(workstream) => workstream.mode === 'group' && !workstream.core,
|
|
298
299
|
)
|
|
299
300
|
const directWorkstreamsByAgent = new Map<string, WorkstreamRecord>()
|
|
300
301
|
const coreWorkstreamsByType = new Map<string, WorkstreamRecord>()
|
|
@@ -303,7 +304,7 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
303
304
|
directWorkstreamsByAgent.set(workstream.agentId, workstream)
|
|
304
305
|
}
|
|
305
306
|
for (const workstream of existingWorkstreams) {
|
|
306
|
-
if (workstream.mode !== 'group' || workstream.core
|
|
307
|
+
if (workstream.mode !== 'group' || !workstream.core) continue
|
|
307
308
|
if (typeof workstream.coreType !== 'string') continue
|
|
308
309
|
coreWorkstreamsByType.set(workstream.coreType, workstream)
|
|
309
310
|
}
|
|
@@ -457,14 +458,10 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
457
458
|
return this.normalizeWorkstream(workstream)
|
|
458
459
|
}
|
|
459
460
|
|
|
460
|
-
async getWorkstreamRecord(workstreamId: RecordIdRef): Promise<WorkstreamRecord> {
|
|
461
|
-
return await this.getById(workstreamId)
|
|
462
|
-
}
|
|
463
|
-
|
|
464
461
|
async updateTitle(workstreamId: RecordIdRef, title: string): Promise<NormalizedWorkstream> {
|
|
465
462
|
const existing = await this.getById(workstreamId)
|
|
466
463
|
this.assertMutableWorkstream(existing, 'rename')
|
|
467
|
-
const workstream = await this.update(workstreamId, { title })
|
|
464
|
+
const workstream = await this.update(workstreamId, { title, nameGenerated: true })
|
|
468
465
|
return this.normalizeWorkstream(workstream)
|
|
469
466
|
}
|
|
470
467
|
|
|
@@ -501,9 +498,8 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
501
498
|
}
|
|
502
499
|
|
|
503
500
|
async clearActiveRunIdIfMatches(workstreamId: RecordIdRef, runId: string): Promise<void> {
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
await this.setActiveRunId(workstreamId, null)
|
|
501
|
+
const workstreamRef = ensureRecordId(workstreamId, TABLES.WORKSTREAM)
|
|
502
|
+
await databaseService.query(surql`UPDATE ONLY ${workstreamRef} SET activeRunId = NONE WHERE activeRunId = ${runId}`)
|
|
507
503
|
}
|
|
508
504
|
|
|
509
505
|
async setActiveStreamId(workstreamId: RecordIdRef, streamId: string): Promise<void> {
|
|
@@ -523,13 +519,10 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
523
519
|
}
|
|
524
520
|
|
|
525
521
|
async clearActiveStreamIdIfMatches(workstreamId: RecordIdRef, streamId: string): Promise<void> {
|
|
526
|
-
const activeStreamId = await this.getActiveStreamId(workstreamId)
|
|
527
|
-
if (activeStreamId !== streamId) return
|
|
528
522
|
const workstreamRef = ensureRecordId(workstreamId, TABLES.WORKSTREAM)
|
|
529
|
-
await databaseService.query
|
|
530
|
-
UPDATE ONLY ${workstreamRef}
|
|
531
|
-
|
|
532
|
-
`)
|
|
523
|
+
await databaseService.query(
|
|
524
|
+
surql`UPDATE ONLY ${workstreamRef} SET activeStreamId = NONE WHERE activeStreamId = ${streamId}`,
|
|
525
|
+
)
|
|
533
526
|
}
|
|
534
527
|
|
|
535
528
|
async stopActiveRun(workstreamId: RecordIdRef): Promise<boolean> {
|
|
@@ -659,7 +652,7 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
659
652
|
throw new Error(`Invalid record id for table ${table}`)
|
|
660
653
|
}
|
|
661
654
|
|
|
662
|
-
return recordIdToString(id,
|
|
655
|
+
return recordIdToString(id, table)
|
|
663
656
|
}
|
|
664
657
|
|
|
665
658
|
formatMemoryBlockForPrompt(workstream: Pick<WorkstreamRecord, 'memoryBlock' | 'memoryBlockSummary'>): string {
|
|
@@ -670,7 +663,7 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
670
663
|
}
|
|
671
664
|
|
|
672
665
|
private getDefaultTitle(workstream: Pick<WorkstreamRecord, 'core' | 'coreType'>): string {
|
|
673
|
-
if (workstream.core
|
|
666
|
+
if (workstream.core && typeof workstream.coreType === 'string') {
|
|
674
667
|
return getCoreWorkstreamProfile(workstream.coreType).config.title
|
|
675
668
|
}
|
|
676
669
|
|
|
@@ -683,10 +676,10 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
683
676
|
? workstream.activeRunId
|
|
684
677
|
: null
|
|
685
678
|
const isCompacting = workstream.isCompacting === true
|
|
686
|
-
const mode =
|
|
687
|
-
const core = workstream.core
|
|
679
|
+
const mode = workstream.mode
|
|
680
|
+
const core = workstream.core
|
|
688
681
|
const coreType = core && typeof workstream.coreType === 'string' ? workstream.coreType : undefined
|
|
689
|
-
const status =
|
|
682
|
+
const status = workstream.status
|
|
690
683
|
return {
|
|
691
684
|
id: this.normalizeWorkstreamId(workstream.id),
|
|
692
685
|
userId: this.normalizeRecordIdString(workstream.userId, TABLES.USER),
|
|
@@ -694,7 +687,7 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
694
687
|
mode,
|
|
695
688
|
core,
|
|
696
689
|
...(coreType ? { coreType } : {}),
|
|
697
|
-
nameGenerated: workstream.nameGenerated
|
|
690
|
+
nameGenerated: workstream.nameGenerated,
|
|
698
691
|
isRunning: activeRunId !== null,
|
|
699
692
|
isCompacting,
|
|
700
693
|
...(isAgentName(workstream.agentId) ? { agentId: workstream.agentId } : {}),
|
|
@@ -706,35 +699,20 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
706
699
|
}
|
|
707
700
|
}
|
|
708
701
|
|
|
709
|
-
toPublicWorkstream(workstream: NormalizedWorkstream
|
|
710
|
-
const id = typeof workstream.id === 'string' ? workstream.id : this.normalizeWorkstreamId(workstream.id)
|
|
711
|
-
const createdAt = toIsoDateTimeString(workstream.createdAt)
|
|
712
|
-
const updatedAt = toIsoDateTimeString(workstream.updatedAt)
|
|
713
|
-
const activeRunId =
|
|
714
|
-
'activeRunId' in workstream &&
|
|
715
|
-
typeof workstream.activeRunId === 'string' &&
|
|
716
|
-
workstream.activeRunId.trim().length > 0
|
|
717
|
-
? workstream.activeRunId
|
|
718
|
-
: null
|
|
719
|
-
const isRunning = 'isRunning' in workstream ? workstream.isRunning : activeRunId !== null
|
|
720
|
-
const isCompacting = workstream.isCompacting === true
|
|
721
|
-
const mode = typeof workstream.mode === 'string' ? workstream.mode : 'group'
|
|
722
|
-
const core = workstream.core === true
|
|
723
|
-
const coreType = core && typeof workstream.coreType === 'string' ? workstream.coreType : undefined
|
|
724
|
-
const nameGenerated = 'nameGenerated' in workstream ? workstream.nameGenerated === true : false
|
|
702
|
+
toPublicWorkstream(workstream: NormalizedWorkstream) {
|
|
725
703
|
return {
|
|
726
|
-
id,
|
|
727
|
-
mode,
|
|
728
|
-
core,
|
|
729
|
-
...(coreType ? { coreType } : {}),
|
|
730
|
-
...(
|
|
731
|
-
title: workstream.title
|
|
732
|
-
status: workstream.status
|
|
733
|
-
nameGenerated,
|
|
734
|
-
isRunning,
|
|
735
|
-
isCompacting,
|
|
736
|
-
createdAt,
|
|
737
|
-
updatedAt,
|
|
704
|
+
id: workstream.id,
|
|
705
|
+
mode: workstream.mode,
|
|
706
|
+
core: workstream.core,
|
|
707
|
+
...(workstream.coreType ? { coreType: workstream.coreType } : {}),
|
|
708
|
+
...(workstream.agentId ? { agentId: workstream.agentId } : {}),
|
|
709
|
+
title: workstream.title,
|
|
710
|
+
status: workstream.status,
|
|
711
|
+
nameGenerated: workstream.nameGenerated,
|
|
712
|
+
isRunning: workstream.isRunning,
|
|
713
|
+
isCompacting: workstream.isCompacting,
|
|
714
|
+
createdAt: workstream.createdAt,
|
|
715
|
+
updatedAt: workstream.updatedAt,
|
|
738
716
|
}
|
|
739
717
|
}
|
|
740
718
|
|
|
@@ -745,7 +723,7 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
745
723
|
SET turnCount += 1
|
|
746
724
|
RETURN turnCount
|
|
747
725
|
`)
|
|
748
|
-
return result[0]
|
|
726
|
+
return result[0].turnCount
|
|
749
727
|
}
|
|
750
728
|
|
|
751
729
|
async persistGeneratedTitle(workstreamId: RecordIdRef, title: string): Promise<void> {
|
|
@@ -759,7 +737,7 @@ class WorkstreamService extends BaseService<typeof WorkstreamSchema> {
|
|
|
759
737
|
if (workstream.mode === 'direct') {
|
|
760
738
|
throw new Error(`Direct workstreams cannot be ${action}d`)
|
|
761
739
|
}
|
|
762
|
-
if (workstream.core
|
|
740
|
+
if (workstream.core) {
|
|
763
741
|
throw new Error(`Core workstreams cannot be ${action}d`)
|
|
764
742
|
}
|
|
765
743
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sdkWorkstreamStatusSchema } from '@lota-sdk/shared'
|
|
1
|
+
import { recordIdSchema, sdkWorkstreamStatusSchema } from '@lota-sdk/shared'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
|
|
4
4
|
const WorkstreamModeSchema = z.enum(['direct', 'group'])
|
|
@@ -23,27 +23,27 @@ export interface NormalizedWorkstream {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export const WorkstreamSchema = z.object({
|
|
26
|
-
id:
|
|
27
|
-
mode: WorkstreamModeSchema
|
|
28
|
-
core: z.boolean()
|
|
26
|
+
id: recordIdSchema,
|
|
27
|
+
mode: WorkstreamModeSchema,
|
|
28
|
+
core: z.boolean(),
|
|
29
29
|
coreType: CoreWorkstreamTypeSchema.nullish(),
|
|
30
30
|
agentId: z.string().nullish(),
|
|
31
31
|
title: z.string().nullish(),
|
|
32
|
-
status: sdkWorkstreamStatusSchema
|
|
32
|
+
status: sdkWorkstreamStatusSchema,
|
|
33
33
|
memoryBlock: z.string().nullish(),
|
|
34
34
|
memoryBlockSummary: z.string().nullish(),
|
|
35
35
|
activeRunId: z.string().nullish(),
|
|
36
36
|
activeStreamId: z.string().nullish(),
|
|
37
37
|
compactionSummary: z.string().nullish(),
|
|
38
38
|
lastCompactedMessageId: z.string().nullish(),
|
|
39
|
-
nameGenerated: z.boolean()
|
|
39
|
+
nameGenerated: z.boolean(), // Ideally `isNameGenerated`, but maps directly to SurrealDB column `nameGenerated`
|
|
40
40
|
isCompacting: z.boolean().optional(),
|
|
41
41
|
state: z.unknown().optional(),
|
|
42
|
-
turnCount: z.number().int()
|
|
42
|
+
turnCount: z.number().int(),
|
|
43
43
|
createdAt: z.coerce.date(),
|
|
44
44
|
updatedAt: z.coerce.date(),
|
|
45
|
-
userId:
|
|
46
|
-
organizationId:
|
|
45
|
+
userId: recordIdSchema,
|
|
46
|
+
organizationId: recordIdSchema,
|
|
47
47
|
})
|
|
48
48
|
|
|
49
49
|
export type WorkstreamRecord = z.infer<typeof WorkstreamSchema>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { PlanDataSchema, PlanNodeSpec, PlanSchemaRegistry, WriteIntent } from '@lota-sdk/shared'
|
|
2
|
+
|
|
3
|
+
import { validateSchemaValue } from './plan-validator.service'
|
|
4
|
+
|
|
5
|
+
export interface WriteValidationIssue {
|
|
6
|
+
code: string
|
|
7
|
+
message: string
|
|
8
|
+
path?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface WriteValidationResult {
|
|
12
|
+
status: 'pass' | 'fail'
|
|
13
|
+
issues: WriteValidationIssue[]
|
|
14
|
+
suggestion?: string
|
|
15
|
+
validatedAt: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class WriteIntentValidatorService {
|
|
19
|
+
validate(params: {
|
|
20
|
+
intent: WriteIntent
|
|
21
|
+
nodeSpec: PlanNodeSpec
|
|
22
|
+
schemaRegistry: PlanSchemaRegistry
|
|
23
|
+
existingDeliverables: Map<string, unknown>
|
|
24
|
+
}): WriteValidationResult {
|
|
25
|
+
const issues: WriteValidationIssue[] = []
|
|
26
|
+
const { intent, nodeSpec, schemaRegistry, existingDeliverables } = params
|
|
27
|
+
|
|
28
|
+
if (intent.targetPath.startsWith('structuredOutput')) {
|
|
29
|
+
if (nodeSpec.outputSchemaRef) {
|
|
30
|
+
const schema = schemaRegistry[nodeSpec.outputSchemaRef] as PlanDataSchema | undefined
|
|
31
|
+
if (schema) {
|
|
32
|
+
const schemaIssues = validateSchemaValue({ schema, value: intent.payload, path: intent.targetPath })
|
|
33
|
+
for (const message of schemaIssues) {
|
|
34
|
+
issues.push({ code: 'schema_validation_failed', message })
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return this.buildResult(issues)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const deliverable = nodeSpec.deliverables.find((d) => d.name === intent.targetPath)
|
|
42
|
+
if (!deliverable) {
|
|
43
|
+
issues.push({
|
|
44
|
+
code: 'unknown_deliverable',
|
|
45
|
+
message: `"${intent.targetPath}" does not match any declared deliverable.`,
|
|
46
|
+
})
|
|
47
|
+
return this.buildResult(issues)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (deliverable.schemaRef) {
|
|
51
|
+
const schema = schemaRegistry[deliverable.schemaRef] as PlanDataSchema | undefined
|
|
52
|
+
if (schema) {
|
|
53
|
+
const schemaIssues = validateSchemaValue({ schema, value: intent.payload, path: intent.targetPath })
|
|
54
|
+
for (const message of schemaIssues) {
|
|
55
|
+
issues.push({ code: 'schema_validation_failed', message })
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (intent.action === 'update' && !existingDeliverables.has(intent.targetPath)) {
|
|
61
|
+
issues.push({
|
|
62
|
+
code: 'update_target_not_found',
|
|
63
|
+
message: `Cannot update "${intent.targetPath}" — no prior write exists.`,
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return this.buildResult(issues)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private buildResult(issues: WriteValidationIssue[]): WriteValidationResult {
|
|
71
|
+
const hasFailed = issues.length > 0
|
|
72
|
+
return {
|
|
73
|
+
status: hasFailed ? 'fail' : 'pass',
|
|
74
|
+
issues,
|
|
75
|
+
...(hasFailed ? { suggestion: issues.map((i) => i.message).join('; ') } : {}),
|
|
76
|
+
validatedAt: new Date().toISOString(),
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const writeIntentValidatorService = new WriteIntentValidatorService()
|
|
@@ -64,7 +64,7 @@ export async function extractAttachmentText(file: File): Promise<string> {
|
|
|
64
64
|
return normalizeExtractedText((await extractPdfPages(file)).join('\n\n'))
|
|
65
65
|
}
|
|
66
66
|
if (isDocxAttachmentFile(file)) {
|
|
67
|
-
return
|
|
67
|
+
return extractDocxText(file)
|
|
68
68
|
}
|
|
69
69
|
return ''
|
|
70
70
|
}
|
|
@@ -3,7 +3,7 @@ function sanitizeFilename(name: string): string {
|
|
|
3
3
|
return ascii.replace(/[\\/:"*?<>|]+/g, '-').trim()
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
function toSafeSegment(value: string): string {
|
|
6
|
+
export function toSafeSegment(value: string): string {
|
|
7
7
|
const cleaned = value.replace(/[^a-zA-Z0-9._-]/g, '-')
|
|
8
8
|
return cleaned.length > 0 ? cleaned : 'unknown'
|
|
9
9
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { S3Client } from 'bun'
|
|
2
2
|
|
|
3
3
|
import { getRuntimeConfig } from '../runtime/runtime-config'
|
|
4
|
+
import { toSafeSegment } from './attachment-utils'
|
|
4
5
|
|
|
5
|
-
function
|
|
6
|
+
function toSafePathSegment(value: string): string {
|
|
6
7
|
return value
|
|
7
8
|
.trim()
|
|
8
9
|
.replace(/\\/g, '/')
|
|
@@ -18,7 +19,7 @@ function buildGeneratedDocumentStorageKey(params: {
|
|
|
18
19
|
}): string {
|
|
19
20
|
const safeOrganizationId = toSafeSegment(params.organizationId)
|
|
20
21
|
const safeNamespace = toSafeSegment(params.namespace)
|
|
21
|
-
const safeRelativePath =
|
|
22
|
+
const safeRelativePath = toSafePathSegment(params.relativePath)
|
|
22
23
|
return `${safeOrganizationId}/generated/${safeNamespace}/${safeRelativePath}`
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ToolLoopAgent } from 'ai'
|
|
2
2
|
|
|
3
3
|
import { bifrostOpenRouterResponseHealingModel } from '../bifrost/bifrost'
|
|
4
|
+
import { buildBifrostCacheHeaders } from '../bifrost/cache-headers'
|
|
4
5
|
import {
|
|
5
6
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
6
7
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
@@ -40,6 +41,7 @@ export function createContextCompactionAgent(options: CreateHelperToolLoopAgentO
|
|
|
40
41
|
return new ToolLoopAgent({
|
|
41
42
|
id: 'context-compaction',
|
|
42
43
|
model: bifrostOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
44
|
+
headers: buildBifrostCacheHeaders('context-compaction'),
|
|
43
45
|
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
44
46
|
...resolveHelperAgentOptions(options, { instructions: CONTEXT_COMPACTION_PROMPT }),
|
|
45
47
|
})
|
|
@@ -3,6 +3,7 @@ import type { ModelMessage, LanguageModel, ToolLoopAgentSettings, ToolSet } from
|
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
|
|
5
5
|
import type { ToolDefinition } from '../ai/definitions'
|
|
6
|
+
import { aiLogger } from '../config/logger'
|
|
6
7
|
import { isRecord } from '../utils/string'
|
|
7
8
|
import { assertSubstantiveAgentResult } from './agent-result'
|
|
8
9
|
|
|
@@ -16,6 +17,7 @@ interface DelegatedAgentDefinition {
|
|
|
16
17
|
providerOptions?: AgentProviderOptions
|
|
17
18
|
instructions: string
|
|
18
19
|
tools?: ToolSet
|
|
20
|
+
headers?: Record<string, string>
|
|
19
21
|
maxSteps?: number
|
|
20
22
|
maxOutputTokens?: number
|
|
21
23
|
temperature?: number
|
|
@@ -136,6 +138,7 @@ async function generateSubstantiveDelegatedAgentResult(params: {
|
|
|
136
138
|
try {
|
|
137
139
|
return assertSubstantiveAgentResult(result.text, params.label)
|
|
138
140
|
} catch (error) {
|
|
141
|
+
aiLogger.error`Delegated agent returned non-substantive result (label=${params.label}, attempt=${attempt + 1}, textLength=${result.text.length}, textPreview=${result.text.slice(0, 200)})`
|
|
139
142
|
lastError = error
|
|
140
143
|
if (params.abortSignal?.aborted) {
|
|
141
144
|
throw error
|
|
@@ -163,6 +166,7 @@ export function createDelegatedAgentTool(definition: DelegatedAgentDefinition):
|
|
|
163
166
|
id: definition.id,
|
|
164
167
|
model: resolveAgentModel(definition.model),
|
|
165
168
|
...(definition.providerOptions ? { providerOptions: definition.providerOptions } : {}),
|
|
169
|
+
...(definition.headers ? { headers: definition.headers } : {}),
|
|
166
170
|
instructions: buildDelegatedAgentInstructions(definition.instructions, agentTools),
|
|
167
171
|
tools: agentTools,
|
|
168
172
|
maxOutputTokens: definition.maxOutputTokens ?? DEFAULT_DELEGATED_AGENT_MAX_OUTPUT_TOKENS,
|
|
@@ -204,6 +208,7 @@ export function createDelegatedAgentToolWithContext<TContext>(
|
|
|
204
208
|
id: definition.id,
|
|
205
209
|
model: resolveAgentModel(definition.model),
|
|
206
210
|
...(definition.providerOptions ? { providerOptions: definition.providerOptions } : {}),
|
|
211
|
+
...(definition.headers ? { headers: definition.headers } : {}),
|
|
207
212
|
instructions: buildDelegatedAgentInstructions(definition.instructions, agentTools),
|
|
208
213
|
tools: agentTools,
|
|
209
214
|
maxOutputTokens: definition.maxOutputTokens ?? DEFAULT_DELEGATED_AGENT_MAX_OUTPUT_TOKENS,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ToolLoopAgent } from 'ai'
|
|
2
2
|
|
|
3
3
|
import { bifrostOpenRouterResponseHealingModel } from '../bifrost/bifrost'
|
|
4
|
+
import { buildBifrostCacheHeaders } from '../bifrost/cache-headers'
|
|
4
5
|
import {
|
|
5
6
|
OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS,
|
|
6
|
-
|
|
7
|
+
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
7
8
|
} from '../config/model-constants'
|
|
8
9
|
import type { CreateHelperToolLoopAgentOptions } from '../runtime/agent-types'
|
|
9
10
|
import { resolveHelperAgentOptions } from './helper-agent-options'
|
|
@@ -31,7 +32,8 @@ Set every item.relevance as a string; use empty string when no reason is needed.
|
|
|
31
32
|
export function createMemoryRerankerAgent(options: CreateHelperToolLoopAgentOptions) {
|
|
32
33
|
return new ToolLoopAgent({
|
|
33
34
|
id: 'memory-reranker',
|
|
34
|
-
model: bifrostOpenRouterResponseHealingModel(
|
|
35
|
+
model: bifrostOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
36
|
+
headers: buildBifrostCacheHeaders('memory-reranker'),
|
|
35
37
|
providerOptions: OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS,
|
|
36
38
|
...resolveHelperAgentOptions(options),
|
|
37
39
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ToolLoopAgent } from 'ai'
|
|
2
2
|
|
|
3
3
|
import { bifrostOpenRouterResponseHealingModel } from '../bifrost/bifrost'
|
|
4
|
+
import { buildBifrostCacheHeaders } from '../bifrost/cache-headers'
|
|
4
5
|
import {
|
|
5
6
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
6
7
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
@@ -52,6 +53,7 @@ export function createOrgMemoryAgent(options: CreateHelperToolLoopAgentOptions)
|
|
|
52
53
|
return new ToolLoopAgent({
|
|
53
54
|
id: 'org-memory',
|
|
54
55
|
model: bifrostOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
56
|
+
headers: buildBifrostCacheHeaders('org-memory'),
|
|
55
57
|
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
56
58
|
...resolveHelperAgentOptions(options),
|
|
57
59
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ToolLoopAgent } from 'ai'
|
|
2
2
|
|
|
3
3
|
import { bifrostModel } from '../bifrost/bifrost'
|
|
4
|
+
import { buildBifrostCacheHeaders } from '../bifrost/cache-headers'
|
|
4
5
|
import { getLeadAgentDisplayName } from '../config/agent-defaults'
|
|
5
6
|
import {
|
|
6
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
@@ -79,6 +80,7 @@ export function createRecentActivityTitleRefinerAgent(options: CreateHelperToolL
|
|
|
79
80
|
return new ToolLoopAgent({
|
|
80
81
|
id: 'recent-activity-title-refiner',
|
|
81
82
|
model: bifrostModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
83
|
+
headers: buildBifrostCacheHeaders('recent-activity-title-refiner'),
|
|
82
84
|
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
83
85
|
...resolveHelperAgentOptions(options, {
|
|
84
86
|
instructions: buildRecentActivityTitleRefinerPrompt(),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ToolLoopAgent } from 'ai'
|
|
2
2
|
|
|
3
3
|
import { bifrostOpenRouterResponseHealingModel } from '../bifrost/bifrost'
|
|
4
|
+
import { buildBifrostCacheHeaders } from '../bifrost/cache-headers'
|
|
4
5
|
import {
|
|
5
6
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
6
7
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
@@ -66,6 +67,7 @@ export function createRegularChatMemoryDigestAgent(options: CreateHelperToolLoop
|
|
|
66
67
|
return new ToolLoopAgent({
|
|
67
68
|
id: 'regular-chat-memory-digest',
|
|
68
69
|
model: bifrostOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
70
|
+
headers: buildBifrostCacheHeaders('regular-chat-memory-digest'),
|
|
69
71
|
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
70
72
|
...resolveHelperAgentOptions(options, {
|
|
71
73
|
instructions: regularChatMemoryDigestPrompt,
|
|
@@ -2,6 +2,7 @@ import { ToolLoopAgent } from 'ai'
|
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
|
|
4
4
|
import { bifrostOpenRouterResponseHealingModel } from '../bifrost/bifrost'
|
|
5
|
+
import { buildBifrostCacheHeaders } from '../bifrost/cache-headers'
|
|
5
6
|
import {
|
|
6
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
7
8
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
@@ -79,6 +80,7 @@ export function createSkillExtractorAgent(options: CreateHelperToolLoopAgentOpti
|
|
|
79
80
|
return new ToolLoopAgent({
|
|
80
81
|
id: 'skill-extractor',
|
|
81
82
|
model: bifrostOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
83
|
+
headers: buildBifrostCacheHeaders('skill-extractor'),
|
|
82
84
|
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
83
85
|
...resolveHelperAgentOptions(options, {
|
|
84
86
|
instructions: skillExtractorPrompt,
|
|
@@ -2,6 +2,7 @@ import { ToolLoopAgent } from 'ai'
|
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
|
|
4
4
|
import { bifrostOpenRouterResponseHealingModel } from '../bifrost/bifrost'
|
|
5
|
+
import { buildBifrostCacheHeaders } from '../bifrost/cache-headers'
|
|
5
6
|
import {
|
|
6
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
7
8
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
@@ -69,6 +70,7 @@ export function createSkillManagerAgent(options: CreateHelperToolLoopAgentOption
|
|
|
69
70
|
return new ToolLoopAgent({
|
|
70
71
|
id: 'skill-manager',
|
|
71
72
|
model: bifrostOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
73
|
+
headers: buildBifrostCacheHeaders('skill-manager'),
|
|
72
74
|
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
73
75
|
...resolveHelperAgentOptions(options, {
|
|
74
76
|
instructions: skillManagerPrompt,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ToolLoopAgent } from 'ai'
|
|
2
2
|
|
|
3
3
|
import { bifrostModel } from '../bifrost/bifrost'
|
|
4
|
+
import { buildBifrostCacheHeaders } from '../bifrost/cache-headers'
|
|
4
5
|
import {
|
|
5
6
|
OPENROUTER_FAST_REASONING_MODEL_ID,
|
|
6
7
|
OPENROUTER_MINIMAL_REASONING_PROVIDER_OPTIONS,
|
|
@@ -33,6 +34,7 @@ export function createWorkstreamTitleGeneratorAgent(options: CreateHelperToolLoo
|
|
|
33
34
|
return new ToolLoopAgent({
|
|
34
35
|
id: 'workstream-title-generator',
|
|
35
36
|
model: bifrostModel(OPENROUTER_FAST_REASONING_MODEL_ID),
|
|
37
|
+
headers: buildBifrostCacheHeaders('workstream-title-generator'),
|
|
36
38
|
providerOptions: OPENROUTER_MINIMAL_REASONING_PROVIDER_OPTIONS,
|
|
37
39
|
...resolveHelperAgentOptions(options, {
|
|
38
40
|
instructions: WORKSTREAM_TITLE_GENERATOR_PROMPT,
|
|
@@ -1,35 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CreateExecutionPlanArgsSchema,
|
|
3
3
|
GetActiveExecutionPlanArgsSchema,
|
|
4
|
+
ListExecutionPlansArgsSchema,
|
|
4
5
|
ResumeExecutionPlanRunArgsSchema,
|
|
5
6
|
ReplaceExecutionPlanArgsSchema,
|
|
6
7
|
SubmitExecutionNodeResultArgsSchema,
|
|
8
|
+
getLatestExecutionPlanResult,
|
|
7
9
|
} from '@lota-sdk/shared'
|
|
8
|
-
import type { ExecutionPlanToolResultData } from '@lota-sdk/shared'
|
|
9
10
|
import { tool } from 'ai'
|
|
10
11
|
|
|
11
12
|
import type { RecordIdRef } from '../db/record-id'
|
|
12
13
|
import { executionPlanService } from '../services/execution-plan.service'
|
|
13
14
|
|
|
14
|
-
function isExecutionPlanResult(value: unknown): value is ExecutionPlanToolResultData {
|
|
15
|
-
return value !== null && value !== undefined && typeof value === 'object' && 'hasPlan' in value
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function getLatestExecutionPlanToolResult(output: unknown): ExecutionPlanToolResultData | undefined {
|
|
19
|
-
if (isExecutionPlanResult(output)) {
|
|
20
|
-
return output
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (Array.isArray(output)) {
|
|
24
|
-
for (let index = output.length - 1; index >= 0; index -= 1) {
|
|
25
|
-
const candidate = getLatestExecutionPlanToolResult(output[index])
|
|
26
|
-
if (candidate) return candidate
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return undefined
|
|
31
|
-
}
|
|
32
|
-
|
|
33
15
|
export function createCreateExecutionPlanTool(params: {
|
|
34
16
|
orgId: RecordIdRef
|
|
35
17
|
workstreamId: RecordIdRef
|
|
@@ -45,6 +27,7 @@ export function createCreateExecutionPlanTool(params: {
|
|
|
45
27
|
organizationId: params.orgId,
|
|
46
28
|
workstreamId: params.workstreamId,
|
|
47
29
|
leadAgentId: params.agentId,
|
|
30
|
+
dispatchMode: 'deferred',
|
|
48
31
|
input,
|
|
49
32
|
})
|
|
50
33
|
params.onPlanChanged?.()
|
|
@@ -68,6 +51,7 @@ export function createReplaceExecutionPlanTool(params: {
|
|
|
68
51
|
organizationId: params.orgId,
|
|
69
52
|
workstreamId: params.workstreamId,
|
|
70
53
|
leadAgentId: params.agentId,
|
|
54
|
+
dispatchMode: 'deferred',
|
|
71
55
|
input,
|
|
72
56
|
})
|
|
73
57
|
params.onPlanChanged?.()
|
|
@@ -95,21 +79,31 @@ export function createSubmitExecutionNodeResultTool(params: {
|
|
|
95
79
|
return result
|
|
96
80
|
},
|
|
97
81
|
toModelOutput: ({ output }) => {
|
|
98
|
-
const result =
|
|
82
|
+
const result = getLatestExecutionPlanResult(output)
|
|
99
83
|
const summary = result?.message?.trim()
|
|
100
84
|
return { type: 'text', value: summary && summary.length > 0 ? summary : 'Execution node result submitted.' }
|
|
101
85
|
},
|
|
102
86
|
})
|
|
103
87
|
}
|
|
104
88
|
|
|
105
|
-
export function
|
|
89
|
+
export function createListExecutionPlansTool(params: { workstreamId: RecordIdRef }) {
|
|
90
|
+
return tool({
|
|
91
|
+
description:
|
|
92
|
+
'List all active execution plans for this workstream with summary info (title, status, objective, node counts). Use getExecutionPlanDetails to inspect a specific plan.',
|
|
93
|
+
inputSchema: ListExecutionPlansArgsSchema,
|
|
94
|
+
execute: async () => await executionPlanService.listActivePlanSummaries(params.workstreamId),
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function createGetExecutionPlanDetailsTool(params: { workstreamId: RecordIdRef }) {
|
|
106
99
|
return tool({
|
|
107
100
|
description:
|
|
108
|
-
'Load
|
|
101
|
+
'Load a specific execution run by runId, or the most recent active run if runId is omitted. Returns full graph state, node contracts, events, approvals, artifacts, and checkpoints.',
|
|
109
102
|
inputSchema: GetActiveExecutionPlanArgsSchema,
|
|
110
103
|
execute: async (input) =>
|
|
111
104
|
await executionPlanService.getActivePlanToolResult({
|
|
112
105
|
workstreamId: params.workstreamId,
|
|
106
|
+
runId: input.runId,
|
|
113
107
|
includeEvents: input.includeEvents,
|
|
114
108
|
includeArtifacts: input.includeArtifacts,
|
|
115
109
|
includeApprovals: input.includeApprovals,
|
package/src/tools/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { bifrostChatModel } from '../bifrost/bifrost'
|
|
2
|
+
import { buildBifrostCacheHeaders } from '../bifrost/cache-headers'
|
|
2
3
|
import {
|
|
3
4
|
OPENROUTER_MEDIUM_REASONING_PROVIDER_OPTIONS,
|
|
4
5
|
OPENROUTER_WEB_RESEARCH_MODEL_ID,
|
|
@@ -14,6 +15,7 @@ export const researchTopicTool = createDelegatedAgentTool({
|
|
|
14
15
|
'Delegate a research task to a dedicated research agent that searches the web, fetches pages, and returns a synthesized markdown report. Call multiple instances in parallel for broad research across different topics.',
|
|
15
16
|
model: () => bifrostChatModel(OPENROUTER_WEB_RESEARCH_MODEL_ID),
|
|
16
17
|
providerOptions: OPENROUTER_MEDIUM_REASONING_PROVIDER_OPTIONS,
|
|
18
|
+
headers: buildBifrostCacheHeaders('researchTopic'),
|
|
17
19
|
instructions: RESEARCHER_PROMPT,
|
|
18
20
|
tools: { searchWeb: searchWebTool.create(), fetchWebpage: fetchWebpageTool.create() },
|
|
19
21
|
})
|