@lota-sdk/core 0.1.16 → 0.1.18
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 +6 -3
- package/src/ai/definitions.ts +1 -1
- package/src/ai/embedding-cache.ts +2 -4
- package/src/{bifrost/bifrost.ts → ai-gateway/ai-gateway.ts} +115 -79
- package/src/ai-gateway/cache-headers.ts +8 -0
- package/src/ai-gateway/index.ts +2 -0
- package/src/config/model-constants.ts +1 -1
- package/src/create-runtime.ts +26 -1
- package/src/db/memory-store.helpers.ts +1 -3
- package/src/db/schema-fingerprint.ts +1 -3
- package/src/embeddings/provider.ts +2 -2
- package/src/index.ts +1 -1
- package/src/queues/document-processor.queue.ts +2 -4
- package/src/queues/post-chat-memory.queue.ts +8 -2
- package/src/queues/recent-activity-title-refinement.queue.ts +1 -1
- package/src/queues/skill-extraction.queue.ts +1 -1
- package/src/queues/workstream-title-generation.queue.ts +1 -1
- package/src/redis/redis-lease-lock.ts +1 -2
- package/src/runtime/agent-runtime-policy.ts +3 -14
- package/src/runtime/context-compaction.ts +2 -4
- package/src/runtime/index.ts +1 -1
- package/src/runtime/runtime-config.ts +87 -7
- package/src/runtime/runtime-extensions.ts +0 -1
- package/src/runtime/social-chat.ts +752 -0
- package/src/runtime/team-consultation-orchestrator.ts +0 -4
- package/src/services/agent-executor.service.ts +0 -1
- package/src/services/document-chunk.service.ts +1 -3
- package/src/services/index.ts +1 -0
- package/src/services/memory.service.ts +7 -2
- package/src/services/recent-activity.service.ts +1 -3
- package/src/services/social-chat-history.service.ts +197 -0
- package/src/services/workstream-message.service.ts +1 -3
- package/src/services/workstream-turn-preparation.service.ts +0 -23
- package/src/system-agents/context-compaction.agent.ts +4 -2
- package/src/system-agents/delegated-agent-factory.ts +3 -0
- package/src/system-agents/memory-reranker.agent.ts +5 -3
- package/src/system-agents/memory.agent.ts +4 -2
- package/src/system-agents/recent-activity-title-refiner.agent.ts +4 -2
- package/src/system-agents/regular-chat-memory-digest.agent.ts +4 -2
- package/src/system-agents/skill-extractor.agent.ts +4 -2
- package/src/system-agents/skill-manager.agent.ts +4 -2
- package/src/system-agents/title-generator.agent.ts +4 -2
- package/src/tools/research-topic.tool.ts +4 -2
- package/src/tools/team-think.tool.ts +0 -3
- package/src/workers/regular-chat-memory-digest.helpers.ts +1 -1
- package/src/workers/regular-chat-memory-digest.runner.ts +43 -10
- package/src/workers/skill-extraction.runner.ts +25 -5
- package/src/workers/utils/repo-structure-extractor.ts +2 -2
- package/src/workers/utils/workstream-message-query.ts +3 -5
- package/src/bifrost/index.ts +0 -1
- package/src/runtime/workstream-routing-policy.ts +0 -267
|
@@ -9,7 +9,6 @@ import type { ReadableUploadMetadataLike } from './chat-attachments'
|
|
|
9
9
|
import type { RepoSectionName } from './indexed-repositories-policy'
|
|
10
10
|
import { buildTeamConsultationFailureMessage } from './team-consultation-prompts'
|
|
11
11
|
import { extractMessageText } from './workstream-chat-helpers'
|
|
12
|
-
import type { ReasoningProfileName } from './workstream-routing-policy'
|
|
13
12
|
|
|
14
13
|
export type DefaultRepoSections = RepoSectionName[]
|
|
15
14
|
const TEAM_CONSULTATION_TIMEOUT_MS = 90_000
|
|
@@ -66,7 +65,6 @@ export interface TeamConsultationParticipantRunner {
|
|
|
66
65
|
agentId: string,
|
|
67
66
|
params: {
|
|
68
67
|
task: string
|
|
69
|
-
reasoningProfile: ReasoningProfileName
|
|
70
68
|
systemWorkspaceDetails?: string
|
|
71
69
|
preSeededMemoriesSection?: string
|
|
72
70
|
retrievedKnowledgeSection?: string
|
|
@@ -90,7 +88,6 @@ export interface CreateConsultTeamToolParams {
|
|
|
90
88
|
latestUserMessageId: string
|
|
91
89
|
availableUploads: ReadableUploadMetadataLike[]
|
|
92
90
|
defaultRepoSectionsByAgent: Record<string, DefaultRepoSections | undefined>
|
|
93
|
-
reasoningProfile: 'fast' | 'standard' | 'deep'
|
|
94
91
|
systemWorkspaceDetails?: string
|
|
95
92
|
getPreSeededMemoriesSection: (agentId: string) => Promise<string | undefined>
|
|
96
93
|
retrievedKnowledgeSection?: string
|
|
@@ -135,7 +132,6 @@ export function createConsultTeamTool(params: CreateConsultTeamToolParams) {
|
|
|
135
132
|
try {
|
|
136
133
|
const { agent, observer } = await params.participantRunner.buildParticipantAgent(agentId, {
|
|
137
134
|
task,
|
|
138
|
-
reasoningProfile: params.reasoningProfile,
|
|
139
135
|
systemWorkspaceDetails: params.systemWorkspaceDetails,
|
|
140
136
|
preSeededMemoriesSection: await params.getPreSeededMemoriesSection(agentId),
|
|
141
137
|
retrievedKnowledgeSection: params.retrievedKnowledgeSection,
|
|
@@ -146,7 +146,6 @@ class AgentExecutorService {
|
|
|
146
146
|
mode: dispatchMode,
|
|
147
147
|
onboardingActive: false,
|
|
148
148
|
linearInstalled: Boolean(linearInstallation),
|
|
149
|
-
reasoningProfile: 'standard',
|
|
150
149
|
additionalInstructionSections: [
|
|
151
150
|
buildOwnershipDispatchContextSection({
|
|
152
151
|
node: params.nodeSpec,
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto'
|
|
2
|
-
|
|
3
1
|
import { chunkMarkdownDocument, chunkPagedDocument, chunkPlainTextDocument } from '../document/org-document-chunking'
|
|
4
2
|
import type { ParsedDocumentChunk } from '../document/org-document-chunking'
|
|
5
3
|
import { getDefaultEmbeddings } from '../embeddings/provider'
|
|
@@ -56,7 +54,7 @@ export class DocumentChunkService {
|
|
|
56
54
|
}
|
|
57
55
|
|
|
58
56
|
hashContent(content: string): string {
|
|
59
|
-
return
|
|
57
|
+
return new Bun.CryptoHasher('sha256').update(content).digest('hex')
|
|
60
58
|
}
|
|
61
59
|
|
|
62
60
|
// Uses 4 chars/token (conservative estimate for document content which tends
|
package/src/services/index.ts
CHANGED
|
@@ -30,6 +30,7 @@ export * from './plugin-executor.service'
|
|
|
30
30
|
export * from './recent-activity-title.service'
|
|
31
31
|
export * from './recent-activity.service'
|
|
32
32
|
export * from './skill-resolver.service'
|
|
33
|
+
export * from './social-chat-history.service'
|
|
33
34
|
export * from './system-executor.service'
|
|
34
35
|
export * from './user.service'
|
|
35
36
|
export * from './workstream-message.service'
|
|
@@ -722,6 +722,8 @@ class MemoryService {
|
|
|
722
722
|
input,
|
|
723
723
|
output,
|
|
724
724
|
sourceId,
|
|
725
|
+
source = 'chat',
|
|
726
|
+
sourceMetadata,
|
|
725
727
|
onboardStatus,
|
|
726
728
|
agentName,
|
|
727
729
|
historyMessages = [],
|
|
@@ -733,6 +735,8 @@ class MemoryService {
|
|
|
733
735
|
input: string
|
|
734
736
|
output: string
|
|
735
737
|
sourceId?: string
|
|
738
|
+
source?: string
|
|
739
|
+
sourceMetadata?: Record<string, unknown>
|
|
736
740
|
onboardStatus?: string
|
|
737
741
|
agentName?: string
|
|
738
742
|
historyMessages?: Array<{ role: 'user' | 'agent'; content: string; agentName?: string }>
|
|
@@ -789,7 +793,7 @@ class MemoryService {
|
|
|
789
793
|
scopeId: orgScopeId,
|
|
790
794
|
memoryType: ORG_MEMORY_TYPE,
|
|
791
795
|
...(typeof assessedImportance === 'number' ? { importance: assessedImportance } : {}),
|
|
792
|
-
metadata: { orgId, source
|
|
796
|
+
metadata: { orgId, source, ...(sourceId ? { sourceId } : {}), ...sourceMetadata, ...assessmentMetadata },
|
|
793
797
|
},
|
|
794
798
|
]
|
|
795
799
|
|
|
@@ -803,8 +807,9 @@ class MemoryService {
|
|
|
803
807
|
orgId,
|
|
804
808
|
agentName: scopedAgentName,
|
|
805
809
|
memoryScope: 'agent',
|
|
806
|
-
source
|
|
810
|
+
source,
|
|
807
811
|
...(sourceId ? { sourceId } : {}),
|
|
812
|
+
...sourceMetadata,
|
|
808
813
|
...assessmentMetadata,
|
|
809
814
|
},
|
|
810
815
|
})
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto'
|
|
2
|
-
|
|
3
1
|
import {
|
|
4
2
|
RecentActivityDeepLinkSchema,
|
|
5
3
|
RecentActivityEventInputSchema,
|
|
@@ -70,7 +68,7 @@ type RecentActivityEventRow = z.infer<typeof RecentActivityEventRowSchema>
|
|
|
70
68
|
type RecentActivityRow = z.infer<typeof RecentActivityRowSchema>
|
|
71
69
|
|
|
72
70
|
function buildDeterministicRecordId(table: string, key: string): RecordId {
|
|
73
|
-
const digest =
|
|
71
|
+
const digest = new Bun.CryptoHasher('sha256').update(key).digest('hex')
|
|
74
72
|
return new RecordId(table, digest)
|
|
75
73
|
}
|
|
76
74
|
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { getRedisConnection } from '../redis'
|
|
4
|
+
import type { LotaRuntimeBackgroundCursor, LotaRuntimeBackgroundCursorKind } from '../runtime/runtime-extensions'
|
|
5
|
+
|
|
6
|
+
const DEFAULT_SOCIAL_CHAT_HISTORY_PREFIX = 'lota:social:history'
|
|
7
|
+
|
|
8
|
+
const SocialChatMessageRoleSchema = z.enum(['user', 'assistant'])
|
|
9
|
+
const SocialChatSourceSchema = z.literal('social')
|
|
10
|
+
const SocialChatPlatformSchema = z.literal('slack')
|
|
11
|
+
|
|
12
|
+
const SocialChatHistoryMessageSchema = z.object({
|
|
13
|
+
source: SocialChatSourceSchema,
|
|
14
|
+
sourceId: z.string().trim().min(1),
|
|
15
|
+
platform: SocialChatPlatformSchema,
|
|
16
|
+
workspaceId: z.string().trim().min(1),
|
|
17
|
+
channelId: z.string().trim().min(1),
|
|
18
|
+
threadId: z.string().trim().min(1),
|
|
19
|
+
messageId: z.string().trim().min(1),
|
|
20
|
+
role: SocialChatMessageRoleSchema,
|
|
21
|
+
parts: z.array(z.record(z.string(), z.unknown())),
|
|
22
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
23
|
+
cursor: z.object({ createdAt: z.coerce.date(), id: z.string().trim().min(1) }),
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
export type SocialChatHistoryMessage = z.infer<typeof SocialChatHistoryMessageSchema>
|
|
27
|
+
|
|
28
|
+
let socialChatHistoryPrefix = DEFAULT_SOCIAL_CHAT_HISTORY_PREFIX
|
|
29
|
+
|
|
30
|
+
function trimConfiguredPrefix(value: string | undefined): string {
|
|
31
|
+
const normalized = value?.trim()
|
|
32
|
+
return normalized && normalized.length > 0 ? normalized : DEFAULT_SOCIAL_CHAT_HISTORY_PREFIX
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function compareCursorOrder(left: LotaRuntimeBackgroundCursor, right: LotaRuntimeBackgroundCursor): number {
|
|
36
|
+
const timeDiff = left.createdAt.getTime() - right.createdAt.getTime()
|
|
37
|
+
if (timeDiff !== 0) return timeDiff
|
|
38
|
+
return left.id.localeCompare(right.id)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class SocialChatHistoryService {
|
|
42
|
+
configure(params?: { keyPrefix?: string }): void {
|
|
43
|
+
socialChatHistoryPrefix = trimConfiguredPrefix(params?.keyPrefix)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private messageStorageKey(message: {
|
|
47
|
+
platform: 'slack'
|
|
48
|
+
workspaceId: string
|
|
49
|
+
threadId: string
|
|
50
|
+
messageId: string
|
|
51
|
+
}): string {
|
|
52
|
+
return `${socialChatHistoryPrefix}:message:${message.platform}:${message.workspaceId}:${message.threadId}:${message.messageId}`
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private threadIndexKey(workspaceId: string, threadId: string): string {
|
|
56
|
+
return `${socialChatHistoryPrefix}:thread:${workspaceId}:${threadId}`
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private workspaceIndexKey(workspaceId: string): string {
|
|
60
|
+
return `${socialChatHistoryPrefix}:workspace:${workspaceId}`
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private cursorKey(kind: LotaRuntimeBackgroundCursorKind, workspaceId: string): string {
|
|
64
|
+
return `${socialChatHistoryPrefix}:cursor:${kind}:${workspaceId}`
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private serializeMessage(message: SocialChatHistoryMessage): string {
|
|
68
|
+
return JSON.stringify({
|
|
69
|
+
...message,
|
|
70
|
+
cursor: { ...message.cursor, createdAt: message.cursor.createdAt.toISOString() },
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private parseStoredMessage(value: string | null): SocialChatHistoryMessage | null {
|
|
75
|
+
if (!value) return null
|
|
76
|
+
try {
|
|
77
|
+
const parsed = SocialChatHistoryMessageSchema.safeParse(JSON.parse(value))
|
|
78
|
+
return parsed.success ? parsed.data : null
|
|
79
|
+
} catch {
|
|
80
|
+
return null
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private serializeCursor(cursor: LotaRuntimeBackgroundCursor): string {
|
|
85
|
+
return JSON.stringify({ ...cursor, createdAt: cursor.createdAt.toISOString() })
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private parseCursor(value: string | null): LotaRuntimeBackgroundCursor | null {
|
|
89
|
+
if (!value) return null
|
|
90
|
+
try {
|
|
91
|
+
const parsed = z.object({ createdAt: z.coerce.date(), id: z.string().trim().min(1) }).safeParse(JSON.parse(value))
|
|
92
|
+
return parsed.success ? parsed.data : null
|
|
93
|
+
} catch {
|
|
94
|
+
return null
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async upsertMessages(messages: SocialChatHistoryMessage[]): Promise<SocialChatHistoryMessage[]> {
|
|
99
|
+
if (messages.length === 0) return []
|
|
100
|
+
|
|
101
|
+
const redis = getRedisConnection()
|
|
102
|
+
const normalizedMessages = messages.map((message) => SocialChatHistoryMessageSchema.parse(message))
|
|
103
|
+
const multi = redis.multi()
|
|
104
|
+
|
|
105
|
+
for (const message of normalizedMessages) {
|
|
106
|
+
const storageKey = this.messageStorageKey(message)
|
|
107
|
+
const score = message.cursor.createdAt.getTime()
|
|
108
|
+
multi.set(storageKey, this.serializeMessage(message))
|
|
109
|
+
multi.zadd(this.threadIndexKey(message.workspaceId, message.threadId), score, storageKey)
|
|
110
|
+
multi.zadd(this.workspaceIndexKey(message.workspaceId), score, storageKey)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await multi.exec()
|
|
114
|
+
return normalizedMessages
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async listThreadMessages(params: { workspaceId: string; threadId: string }): Promise<SocialChatHistoryMessage[]> {
|
|
118
|
+
const redis = getRedisConnection()
|
|
119
|
+
const storageKeys = await redis.zrange(this.threadIndexKey(params.workspaceId, params.threadId), 0, -1)
|
|
120
|
+
if (storageKeys.length === 0) return []
|
|
121
|
+
|
|
122
|
+
const storedValues = await redis.mget(storageKeys)
|
|
123
|
+
return storedValues
|
|
124
|
+
.map((value) => this.parseStoredMessage(value))
|
|
125
|
+
.filter((message): message is SocialChatHistoryMessage => message !== null)
|
|
126
|
+
.sort((left, right) => compareCursorOrder(left.cursor, right.cursor))
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async listWorkspaceMessages(params: {
|
|
130
|
+
workspaceId: string
|
|
131
|
+
cursor: LotaRuntimeBackgroundCursor | null
|
|
132
|
+
onboardingCutoff: Date | null
|
|
133
|
+
}): Promise<SocialChatHistoryMessage[]> {
|
|
134
|
+
const redis = getRedisConnection()
|
|
135
|
+
const indexKey = this.workspaceIndexKey(params.workspaceId)
|
|
136
|
+
const scoreStart =
|
|
137
|
+
params.cursor?.createdAt.getTime() ??
|
|
138
|
+
(params.onboardingCutoff ? params.onboardingCutoff.getTime() : Number.NEGATIVE_INFINITY)
|
|
139
|
+
const storageKeys =
|
|
140
|
+
params.cursor || params.onboardingCutoff
|
|
141
|
+
? await redis.zrangebyscore(indexKey, scoreStart, '+inf')
|
|
142
|
+
: await redis.zrange(indexKey, 0, -1)
|
|
143
|
+
|
|
144
|
+
if (storageKeys.length === 0) return []
|
|
145
|
+
|
|
146
|
+
const storedValues = await redis.mget(storageKeys)
|
|
147
|
+
return storedValues
|
|
148
|
+
.map((value) => this.parseStoredMessage(value))
|
|
149
|
+
.filter((message): message is SocialChatHistoryMessage => message !== null)
|
|
150
|
+
.filter((message) => {
|
|
151
|
+
if (params.cursor) {
|
|
152
|
+
return compareCursorOrder(message.cursor, params.cursor) > 0
|
|
153
|
+
}
|
|
154
|
+
if (params.onboardingCutoff) {
|
|
155
|
+
return message.cursor.createdAt.getTime() > params.onboardingCutoff.getTime()
|
|
156
|
+
}
|
|
157
|
+
return true
|
|
158
|
+
})
|
|
159
|
+
.sort((left, right) => compareCursorOrder(left.cursor, right.cursor))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async hasWorkspaceMessages(params: {
|
|
163
|
+
workspaceId: string
|
|
164
|
+
cursor: LotaRuntimeBackgroundCursor | null
|
|
165
|
+
onboardingCutoff: Date | null
|
|
166
|
+
}): Promise<boolean> {
|
|
167
|
+
const messages = await this.listWorkspaceMessages({
|
|
168
|
+
workspaceId: params.workspaceId,
|
|
169
|
+
cursor: params.cursor,
|
|
170
|
+
onboardingCutoff: params.onboardingCutoff,
|
|
171
|
+
})
|
|
172
|
+
return messages.length > 0
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async getBackgroundCursor(
|
|
176
|
+
kind: LotaRuntimeBackgroundCursorKind,
|
|
177
|
+
workspaceId: string,
|
|
178
|
+
): Promise<LotaRuntimeBackgroundCursor | null> {
|
|
179
|
+
const redis = getRedisConnection()
|
|
180
|
+
return this.parseCursor(await redis.get(this.cursorKey(kind, workspaceId)))
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async setBackgroundCursor(
|
|
184
|
+
kind: LotaRuntimeBackgroundCursorKind,
|
|
185
|
+
workspaceId: string,
|
|
186
|
+
cursor: LotaRuntimeBackgroundCursor,
|
|
187
|
+
): Promise<void> {
|
|
188
|
+
const redis = getRedisConnection()
|
|
189
|
+
await redis.set(this.cursorKey(kind, workspaceId), this.serializeCursor(cursor))
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export const socialChatHistoryService = new SocialChatHistoryService()
|
|
194
|
+
|
|
195
|
+
export function configureSocialChatHistory(params?: { keyPrefix?: string }): void {
|
|
196
|
+
socialChatHistoryService.configure(params)
|
|
197
|
+
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto'
|
|
2
|
-
|
|
3
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'
|
|
@@ -30,7 +28,7 @@ function toMessageId(value: string | RecordIdRef): string {
|
|
|
30
28
|
*/
|
|
31
29
|
function toWorkstreamMessageRowId(workstreamId: RecordIdRef, messageId: string): RecordId {
|
|
32
30
|
const workstreamStr = recordIdToString(workstreamId, TABLES.WORKSTREAM)
|
|
33
|
-
const digest =
|
|
31
|
+
const digest = new Bun.CryptoHasher('sha256').update(`${workstreamStr}\0${messageId}`).digest('hex').slice(0, 32)
|
|
34
32
|
return new RecordId(TABLES.WORKSTREAM_MESSAGE, digest)
|
|
35
33
|
}
|
|
36
34
|
|
|
@@ -69,11 +69,6 @@ import {
|
|
|
69
69
|
toHistoryMessages,
|
|
70
70
|
toOptionalTrimmedString,
|
|
71
71
|
} from '../runtime/workstream-chat-helpers'
|
|
72
|
-
import {
|
|
73
|
-
classifyHighImpactResponse,
|
|
74
|
-
classifyPolicyClasses,
|
|
75
|
-
resolveReasoningProfile,
|
|
76
|
-
} from '../runtime/workstream-routing-policy'
|
|
77
72
|
import type { WorkstreamState } from '../runtime/workstream-state'
|
|
78
73
|
import { chatRunRegistry } from '../services/chat-run-registry.service'
|
|
79
74
|
import type { NormalizedWorkstream, WorkstreamRecord } from '../services/workstream.types'
|
|
@@ -274,7 +269,6 @@ interface StreamAgentResponseContext {
|
|
|
274
269
|
onboardingActive: boolean
|
|
275
270
|
linearInstalled: boolean
|
|
276
271
|
githubInstalled: boolean
|
|
277
|
-
reasoningProfileName: string
|
|
278
272
|
buildContextResult: Record<string, unknown> | null
|
|
279
273
|
getExecutionPlanInstructionSections: () => Promise<string[] | undefined>
|
|
280
274
|
getPreSeededMemoriesSection: (agentId: string) => Promise<string | undefined>
|
|
@@ -324,7 +318,6 @@ async function streamAgentResponse(
|
|
|
324
318
|
onboardingActive: ctx.onboardingActive,
|
|
325
319
|
linearInstalled: ctx.linearInstalled,
|
|
326
320
|
githubInstalled: ctx.githubInstalled,
|
|
327
|
-
reasoningProfile: ctx.reasoningProfileName,
|
|
328
321
|
skills: streamParams.skills,
|
|
329
322
|
additionalInstructionSections: streamParams.additionalInstructionSections,
|
|
330
323
|
context: ctx.buildContextResult,
|
|
@@ -345,7 +338,6 @@ async function streamAgentResponse(
|
|
|
345
338
|
skills: streamParams.skills,
|
|
346
339
|
onboardingActive: ctx.onboardingActive,
|
|
347
340
|
linearInstalled: ctx.linearInstalled,
|
|
348
|
-
reasoningProfile: ctx.reasoningProfileName,
|
|
349
341
|
systemWorkspaceDetails: ctx.promptContext.systemWorkspaceDetails,
|
|
350
342
|
preSeededMemoriesSection,
|
|
351
343
|
retrievedKnowledgeSection: ctx.retrievedKnowledgeSection,
|
|
@@ -753,15 +745,6 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
753
745
|
'getInstallationForOrganization',
|
|
754
746
|
])
|
|
755
747
|
|
|
756
|
-
const highImpactAssessment = classifyHighImpactResponse({ message: messageText })
|
|
757
|
-
const policyAssessment = classifyPolicyClasses({ message: messageText })
|
|
758
|
-
const reasoningProfile = resolveReasoningProfile({
|
|
759
|
-
message: messageText,
|
|
760
|
-
forceDeep: highImpactAssessment.classes.length > 0 || policyAssessment.classes.length > 0,
|
|
761
|
-
explicitProfile: onboardingActive ? 'standard' : undefined,
|
|
762
|
-
})
|
|
763
|
-
timer.step('reasoning-classification')
|
|
764
|
-
|
|
765
748
|
const [linearInstallation, githubInstallation, indexedRepoContext, recentDomainEvents, promptSummary] =
|
|
766
749
|
await Promise.all([
|
|
767
750
|
getLinearInstallationByOrgId ? (getLinearInstallationByOrgId(orgRef) as Promise<unknown>) : Promise.resolve(null),
|
|
@@ -968,9 +951,6 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
968
951
|
const buildAgentMetadataPatch = (agentId: string, agentName: string): NonNullable<MessageMetadata> => ({
|
|
969
952
|
agentId,
|
|
970
953
|
agentName,
|
|
971
|
-
reasoningProfile: reasoningProfile.name,
|
|
972
|
-
highImpactClasses: highImpactAssessment.classes,
|
|
973
|
-
policyClasses: policyAssessment.classes,
|
|
974
954
|
semanticTerminationReason: 'none',
|
|
975
955
|
})
|
|
976
956
|
|
|
@@ -1007,7 +987,6 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1007
987
|
onboardingActive,
|
|
1008
988
|
linearInstalled,
|
|
1009
989
|
githubInstalled,
|
|
1010
|
-
reasoningProfileName: reasoningProfile.name,
|
|
1011
990
|
buildContextResult,
|
|
1012
991
|
getExecutionPlanInstructionSections,
|
|
1013
992
|
getPreSeededMemoriesSection,
|
|
@@ -1137,7 +1116,6 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1137
1116
|
mode: 'fixedWorkstreamMode',
|
|
1138
1117
|
onboardingActive,
|
|
1139
1118
|
linearInstalled,
|
|
1140
|
-
reasoningProfile: reasoningProfile.name,
|
|
1141
1119
|
systemWorkspaceDetails: promptContext.systemWorkspaceDetails,
|
|
1142
1120
|
preSeededMemoriesSection: specialistPreSeededMemories,
|
|
1143
1121
|
retrievedKnowledgeSection,
|
|
@@ -1234,7 +1212,6 @@ export async function prepareWorkstreamRunCore(params: WorkstreamRunCoreParams):
|
|
|
1234
1212
|
availableUploads: listReadableUploads(),
|
|
1235
1213
|
provideRepoTool: indexedRepoContext.provideRepoTool,
|
|
1236
1214
|
defaultRepoSectionsByAgent: indexedRepoContext.defaultSectionsByAgent as never,
|
|
1237
|
-
reasoningProfile: reasoningProfile.name,
|
|
1238
1215
|
systemWorkspaceDetails: promptContext.systemWorkspaceDetails,
|
|
1239
1216
|
getPreSeededMemoriesSection,
|
|
1240
1217
|
retrievedKnowledgeSection,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ToolLoopAgent } from 'ai'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { aiGatewayOpenRouterResponseHealingModel } from '../ai-gateway/ai-gateway'
|
|
4
|
+
import { buildAiGatewayCacheHeaders } from '../ai-gateway/cache-headers'
|
|
4
5
|
import {
|
|
5
6
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
6
7
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
@@ -39,7 +40,8 @@ Return valid data for:
|
|
|
39
40
|
export function createContextCompactionAgent(options: CreateHelperToolLoopAgentOptions) {
|
|
40
41
|
return new ToolLoopAgent({
|
|
41
42
|
id: 'context-compaction',
|
|
42
|
-
model:
|
|
43
|
+
model: aiGatewayOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
44
|
+
headers: buildAiGatewayCacheHeaders('context-compaction'),
|
|
43
45
|
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
44
46
|
...resolveHelperAgentOptions(options, { instructions: CONTEXT_COMPACTION_PROMPT }),
|
|
45
47
|
})
|
|
@@ -17,6 +17,7 @@ interface DelegatedAgentDefinition {
|
|
|
17
17
|
providerOptions?: AgentProviderOptions
|
|
18
18
|
instructions: string
|
|
19
19
|
tools?: ToolSet
|
|
20
|
+
headers?: Record<string, string>
|
|
20
21
|
maxSteps?: number
|
|
21
22
|
maxOutputTokens?: number
|
|
22
23
|
temperature?: number
|
|
@@ -165,6 +166,7 @@ export function createDelegatedAgentTool(definition: DelegatedAgentDefinition):
|
|
|
165
166
|
id: definition.id,
|
|
166
167
|
model: resolveAgentModel(definition.model),
|
|
167
168
|
...(definition.providerOptions ? { providerOptions: definition.providerOptions } : {}),
|
|
169
|
+
...(definition.headers ? { headers: definition.headers } : {}),
|
|
168
170
|
instructions: buildDelegatedAgentInstructions(definition.instructions, agentTools),
|
|
169
171
|
tools: agentTools,
|
|
170
172
|
maxOutputTokens: definition.maxOutputTokens ?? DEFAULT_DELEGATED_AGENT_MAX_OUTPUT_TOKENS,
|
|
@@ -206,6 +208,7 @@ export function createDelegatedAgentToolWithContext<TContext>(
|
|
|
206
208
|
id: definition.id,
|
|
207
209
|
model: resolveAgentModel(definition.model),
|
|
208
210
|
...(definition.providerOptions ? { providerOptions: definition.providerOptions } : {}),
|
|
211
|
+
...(definition.headers ? { headers: definition.headers } : {}),
|
|
209
212
|
instructions: buildDelegatedAgentInstructions(definition.instructions, agentTools),
|
|
210
213
|
tools: agentTools,
|
|
211
214
|
maxOutputTokens: definition.maxOutputTokens ?? DEFAULT_DELEGATED_AGENT_MAX_OUTPUT_TOKENS,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ToolLoopAgent } from 'ai'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { aiGatewayOpenRouterResponseHealingModel } from '../ai-gateway/ai-gateway'
|
|
4
|
+
import { buildAiGatewayCacheHeaders } from '../ai-gateway/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:
|
|
35
|
+
model: aiGatewayOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
36
|
+
headers: buildAiGatewayCacheHeaders('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
|
-
import {
|
|
3
|
+
import { aiGatewayOpenRouterResponseHealingModel } from '../ai-gateway/ai-gateway'
|
|
4
|
+
import { buildAiGatewayCacheHeaders } from '../ai-gateway/cache-headers'
|
|
4
5
|
import {
|
|
5
6
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
6
7
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
@@ -51,7 +52,8 @@ Return only the schema fields with no extra formatting.
|
|
|
51
52
|
export function createOrgMemoryAgent(options: CreateHelperToolLoopAgentOptions) {
|
|
52
53
|
return new ToolLoopAgent({
|
|
53
54
|
id: 'org-memory',
|
|
54
|
-
model:
|
|
55
|
+
model: aiGatewayOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
56
|
+
headers: buildAiGatewayCacheHeaders('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
|
-
import {
|
|
3
|
+
import { aiGatewayModel } from '../ai-gateway/ai-gateway'
|
|
4
|
+
import { buildAiGatewayCacheHeaders } from '../ai-gateway/cache-headers'
|
|
4
5
|
import { getLeadAgentDisplayName } from '../config/agent-defaults'
|
|
5
6
|
import {
|
|
6
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
@@ -78,7 +79,8 @@ Return only the title text. No quotes, labels, JSON, markdown, or explanation.
|
|
|
78
79
|
export function createRecentActivityTitleRefinerAgent(options: CreateHelperToolLoopAgentOptions) {
|
|
79
80
|
return new ToolLoopAgent({
|
|
80
81
|
id: 'recent-activity-title-refiner',
|
|
81
|
-
model:
|
|
82
|
+
model: aiGatewayModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
83
|
+
headers: buildAiGatewayCacheHeaders('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
|
-
import {
|
|
3
|
+
import { aiGatewayOpenRouterResponseHealingModel } from '../ai-gateway/ai-gateway'
|
|
4
|
+
import { buildAiGatewayCacheHeaders } from '../ai-gateway/cache-headers'
|
|
4
5
|
import {
|
|
5
6
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
6
7
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
@@ -65,7 +66,8 @@ Return only schema fields.
|
|
|
65
66
|
export function createRegularChatMemoryDigestAgent(options: CreateHelperToolLoopAgentOptions) {
|
|
66
67
|
return new ToolLoopAgent({
|
|
67
68
|
id: 'regular-chat-memory-digest',
|
|
68
|
-
model:
|
|
69
|
+
model: aiGatewayOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
70
|
+
headers: buildAiGatewayCacheHeaders('regular-chat-memory-digest'),
|
|
69
71
|
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
70
72
|
...resolveHelperAgentOptions(options, {
|
|
71
73
|
instructions: regularChatMemoryDigestPrompt,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ToolLoopAgent } from 'ai'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { aiGatewayOpenRouterResponseHealingModel } from '../ai-gateway/ai-gateway'
|
|
5
|
+
import { buildAiGatewayCacheHeaders } from '../ai-gateway/cache-headers'
|
|
5
6
|
import {
|
|
6
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
7
8
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
@@ -78,7 +79,8 @@ export type SkillCandidate = z.infer<typeof SkillCandidateSchema>
|
|
|
78
79
|
export function createSkillExtractorAgent(options: CreateHelperToolLoopAgentOptions) {
|
|
79
80
|
return new ToolLoopAgent({
|
|
80
81
|
id: 'skill-extractor',
|
|
81
|
-
model:
|
|
82
|
+
model: aiGatewayOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
83
|
+
headers: buildAiGatewayCacheHeaders('skill-extractor'),
|
|
82
84
|
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
83
85
|
...resolveHelperAgentOptions(options, {
|
|
84
86
|
instructions: skillExtractorPrompt,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ToolLoopAgent } from 'ai'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { aiGatewayOpenRouterResponseHealingModel } from '../ai-gateway/ai-gateway'
|
|
5
|
+
import { buildAiGatewayCacheHeaders } from '../ai-gateway/cache-headers'
|
|
5
6
|
import {
|
|
6
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
7
8
|
OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
@@ -68,7 +69,8 @@ export const SkillManagerOutputSchema = z.object({
|
|
|
68
69
|
export function createSkillManagerAgent(options: CreateHelperToolLoopAgentOptions) {
|
|
69
70
|
return new ToolLoopAgent({
|
|
70
71
|
id: 'skill-manager',
|
|
71
|
-
model:
|
|
72
|
+
model: aiGatewayOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
73
|
+
headers: buildAiGatewayCacheHeaders('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
|
-
import {
|
|
3
|
+
import { aiGatewayModel } from '../ai-gateway/ai-gateway'
|
|
4
|
+
import { buildAiGatewayCacheHeaders } from '../ai-gateway/cache-headers'
|
|
4
5
|
import {
|
|
5
6
|
OPENROUTER_FAST_REASONING_MODEL_ID,
|
|
6
7
|
OPENROUTER_MINIMAL_REASONING_PROVIDER_OPTIONS,
|
|
@@ -32,7 +33,8 @@ Return only the title text. No quotes, no labels, no explanation.
|
|
|
32
33
|
export function createWorkstreamTitleGeneratorAgent(options: CreateHelperToolLoopAgentOptions) {
|
|
33
34
|
return new ToolLoopAgent({
|
|
34
35
|
id: 'workstream-title-generator',
|
|
35
|
-
model:
|
|
36
|
+
model: aiGatewayModel(OPENROUTER_FAST_REASONING_MODEL_ID),
|
|
37
|
+
headers: buildAiGatewayCacheHeaders('workstream-title-generator'),
|
|
36
38
|
providerOptions: OPENROUTER_MINIMAL_REASONING_PROVIDER_OPTIONS,
|
|
37
39
|
...resolveHelperAgentOptions(options, {
|
|
38
40
|
instructions: WORKSTREAM_TITLE_GENERATOR_PROMPT,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { aiGatewayChatModel } from '../ai-gateway/ai-gateway'
|
|
2
|
+
import { buildAiGatewayCacheHeaders } from '../ai-gateway/cache-headers'
|
|
2
3
|
import {
|
|
3
4
|
OPENROUTER_MEDIUM_REASONING_PROVIDER_OPTIONS,
|
|
4
5
|
OPENROUTER_WEB_RESEARCH_MODEL_ID,
|
|
@@ -12,8 +13,9 @@ export const researchTopicTool = createDelegatedAgentTool({
|
|
|
12
13
|
id: 'researchTopic',
|
|
13
14
|
description:
|
|
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
|
-
model: () =>
|
|
16
|
+
model: () => aiGatewayChatModel(OPENROUTER_WEB_RESEARCH_MODEL_ID),
|
|
16
17
|
providerOptions: OPENROUTER_MEDIUM_REASONING_PROVIDER_OPTIONS,
|
|
18
|
+
headers: buildAiGatewayCacheHeaders('researchTopic'),
|
|
17
19
|
instructions: RESEARCHER_PROMPT,
|
|
18
20
|
tools: { searchWeb: searchWebTool.create(), fetchWebpage: fetchWebpageTool.create() },
|
|
19
21
|
})
|
|
@@ -40,7 +40,6 @@ export function createTeamThinkTool(params: {
|
|
|
40
40
|
availableUploads: ReadableUploadMetadata[]
|
|
41
41
|
provideRepoTool: boolean
|
|
42
42
|
defaultRepoSectionsByAgent: Record<string, DefaultRepoSections | undefined>
|
|
43
|
-
reasoningProfile: 'fast' | 'standard' | 'deep'
|
|
44
43
|
systemWorkspaceDetails?: string
|
|
45
44
|
getPreSeededMemoriesSection: (agentId: string) => Promise<string | undefined>
|
|
46
45
|
retrievedKnowledgeSection?: string
|
|
@@ -59,7 +58,6 @@ export function createTeamThinkTool(params: {
|
|
|
59
58
|
mode: 'fixedWorkstreamMode',
|
|
60
59
|
onboardingActive: false,
|
|
61
60
|
linearInstalled: false,
|
|
62
|
-
reasoningProfile: 'fast',
|
|
63
61
|
systemWorkspaceDetails: runParams.systemWorkspaceDetails,
|
|
64
62
|
preSeededMemoriesSection: runParams.preSeededMemoriesSection,
|
|
65
63
|
retrievedKnowledgeSection: runParams.retrievedKnowledgeSection,
|
|
@@ -116,7 +114,6 @@ export function createTeamThinkTool(params: {
|
|
|
116
114
|
latestUserMessageId: params.latestUserMessageId,
|
|
117
115
|
availableUploads: params.availableUploads,
|
|
118
116
|
defaultRepoSectionsByAgent: params.defaultRepoSectionsByAgent,
|
|
119
|
-
reasoningProfile: params.reasoningProfile,
|
|
120
117
|
systemWorkspaceDetails: params.systemWorkspaceDetails,
|
|
121
118
|
getPreSeededMemoriesSection: params.getPreSeededMemoriesSection,
|
|
122
119
|
retrievedKnowledgeSection: params.retrievedKnowledgeSection,
|
|
@@ -2,7 +2,7 @@ import { isAgentName } from '../config/agent-defaults'
|
|
|
2
2
|
import { compactWhitespace } from '../utils/string'
|
|
3
3
|
|
|
4
4
|
interface DigestMessageForTranscript {
|
|
5
|
-
source: 'workstream'
|
|
5
|
+
source: 'workstream' | 'social'
|
|
6
6
|
sourceId: string
|
|
7
7
|
role: 'system' | 'user' | 'assistant'
|
|
8
8
|
parts: Array<Record<string, unknown>>
|