@lota-sdk/core 0.2.3 → 0.3.0
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 +2 -2
- package/infrastructure/schema/00_thread.surql +75 -0
- package/infrastructure/schema/02_execution_plan.surql +10 -11
- package/infrastructure/schema/10_autonomous_job.surql +3 -3
- package/package.json +2 -2
- package/src/ai/definitions.ts +1 -1
- package/src/config/agent-defaults.ts +5 -5
- package/src/config/index.ts +1 -1
- package/src/config/thread-defaults.ts +72 -0
- package/src/create-runtime.ts +89 -93
- package/src/db/tables.ts +3 -3
- package/src/db/{workstream-message-row.ts → thread-message-row.ts} +3 -3
- package/src/queues/context-compaction.queue.ts +6 -6
- package/src/queues/plan-agent-heartbeat.queue.ts +3 -3
- package/src/queues/post-chat-memory.queue.ts +1 -1
- package/src/queues/title-generation.queue.ts +10 -13
- package/src/redis/index.ts +1 -1
- package/src/redis/stream-context.ts +1 -1
- package/src/runtime/agent-identity-overrides.ts +1 -1
- package/src/runtime/agent-runtime-policy.ts +19 -21
- package/src/runtime/chat-request-routing.ts +1 -1
- package/src/runtime/context-compaction-constants.ts +1 -1
- package/src/runtime/context-compaction.ts +1 -1
- package/src/runtime/execution-plan.ts +1 -1
- package/src/runtime/index.ts +1 -1
- package/src/runtime/memory-digest-policy.ts +1 -1
- package/src/runtime/plugin-types.ts +1 -1
- package/src/runtime/post-turn-side-effects.ts +35 -35
- package/src/runtime/runtime-config.ts +12 -12
- package/src/runtime/runtime-extensions.ts +11 -11
- package/src/runtime/social-chat-agent-runner.ts +3 -3
- package/src/runtime/social-chat-history.ts +1 -1
- package/src/runtime/social-chat.ts +6 -6
- package/src/runtime/team-consultation-orchestrator.ts +1 -1
- package/src/runtime/{workstream-chat-helpers.ts → thread-chat-helpers.ts} +7 -7
- package/src/runtime/{workstream-plan-turn.ts → thread-plan-turn.ts} +11 -17
- package/src/runtime/{workstream-turn-context.ts → thread-turn-context.ts} +10 -10
- package/src/services/agent-activity.service.ts +39 -44
- package/src/services/agent-executor.service.ts +17 -19
- package/src/services/attachment.service.ts +4 -8
- package/src/services/autonomous-job.service.ts +29 -28
- package/src/services/context-compaction.service.ts +19 -29
- package/src/services/execution-plan.service.ts +58 -70
- package/src/services/global-orchestrator.service.ts +5 -5
- package/src/services/index.ts +6 -6
- package/src/services/memory.service.ts +1 -1
- package/src/services/monitoring-window.service.ts +2 -2
- package/src/services/mutating-approval.service.ts +7 -10
- package/src/services/node-workspace.service.ts +8 -7
- package/src/services/notification.service.ts +1 -1
- package/src/services/organization.service.ts +9 -9
- package/src/services/ownership-dispatcher.service.ts +13 -19
- package/src/services/plan-agent-heartbeat.service.ts +13 -13
- package/src/services/plan-agent-query.service.ts +7 -7
- package/src/services/plan-artifact.service.ts +1 -2
- package/src/services/plan-coordination.service.ts +4 -4
- package/src/services/plan-cycle.service.ts +7 -7
- package/src/services/plan-deadline.service.ts +4 -4
- package/src/services/plan-event-delivery.service.ts +8 -12
- package/src/services/plan-executor.service.ts +16 -37
- package/src/services/plan-run-data.ts +27 -8
- package/src/services/plan-run.service.ts +7 -9
- package/src/services/plan-scheduler.service.ts +4 -4
- package/src/services/plan-template.service.ts +2 -2
- package/src/services/plan-validator.service.ts +0 -11
- package/src/services/plugin-executor.service.ts +1 -1
- package/src/services/queue-job.service.ts +1 -1
- package/src/services/recent-activity-title.service.ts +1 -1
- package/src/services/recent-activity.service.ts +4 -4
- package/src/services/system-executor.service.ts +2 -2
- package/src/services/{workstream-message.service.ts → thread-message.service.ts} +72 -76
- package/src/services/thread-plan-registry.service.ts +22 -0
- package/src/services/thread-title.service.ts +39 -0
- package/src/services/{workstream-turn-preparation.service.ts → thread-turn-preparation.service.ts} +131 -143
- package/src/services/{workstream-turn.ts → thread-turn.ts} +27 -31
- package/src/services/thread.service.ts +707 -0
- package/src/services/thread.types.ts +17 -0
- package/src/storage/attachment-storage.service.ts +4 -4
- package/src/system-agents/index.ts +1 -1
- package/src/system-agents/memory.agent.ts +1 -1
- package/src/system-agents/recent-activity-title-refiner.agent.ts +2 -2
- package/src/system-agents/regular-chat-memory-digest.agent.ts +1 -1
- package/src/system-agents/researcher.agent.ts +3 -3
- package/src/system-agents/{workstream-router.agent.ts → thread-router.agent.ts} +21 -21
- package/src/system-agents/title-generator.agent.ts +8 -8
- package/src/tools/execution-plan.tool.ts +39 -40
- package/src/tools/memory-block.tool.ts +4 -4
- package/src/tools/research-topic.tool.ts +1 -0
- package/src/tools/search-web.tool.ts +1 -1
- package/src/tools/search.tool.ts +4 -4
- package/src/tools/team-think.tool.ts +9 -9
- package/src/workers/regular-chat-memory-digest.helpers.ts +1 -1
- package/src/workers/regular-chat-memory-digest.runner.ts +43 -43
- package/src/workers/skill-extraction.runner.ts +9 -13
- package/src/workers/utils/{workstream-message-query.ts → thread-message-query.ts} +21 -21
- package/infrastructure/schema/00_workstream.surql +0 -64
- package/src/config/workstream-defaults.ts +0 -72
- package/src/services/workstream-plan-registry.service.ts +0 -22
- package/src/services/workstream-title.service.ts +0 -42
- package/src/services/workstream.service.ts +0 -803
- package/src/services/workstream.types.ts +0 -17
- /package/src/services/{workstream-constants.ts → thread-constants.ts} +0 -0
|
@@ -10,4 +10,4 @@ export const SUMMARY_ROLLUP_MAX_TOKENS = 80_000
|
|
|
10
10
|
export const CONTEXT_COMPACTION_INCLUDED_TOOL_NAMES = ['userQuestions', 'proceedInOnboarding'] as const
|
|
11
11
|
export const CONTEXT_COMPACTION_INCLUDED_TOOL_PREFIXES = ['linear'] as const
|
|
12
12
|
export const CONTEXT_WINDOW_TOKENS = 200_000
|
|
13
|
-
export const
|
|
13
|
+
export const THREAD_RAW_TAIL_MESSAGES = 6
|
|
@@ -198,7 +198,7 @@ export function buildContextCompactionPrompt(params: ContextCompactionPromptPara
|
|
|
198
198
|
export function buildMemoryBlockCompactionPrompt(params: MemoryBlockCompactionPromptParams): string {
|
|
199
199
|
return [
|
|
200
200
|
'<memory-block-compaction>',
|
|
201
|
-
'Produce a compact replacement summary for the
|
|
201
|
+
'Produce a compact replacement summary for the thread memory block.',
|
|
202
202
|
'Preserve constraints, commitments, unresolved risks, and ownership.',
|
|
203
203
|
'Blend the previous summary with the new raw entries into one updated summary.',
|
|
204
204
|
'Return plain text only.',
|
|
@@ -7,7 +7,7 @@ const EXECUTION_PLAN_AGENT_PROTOCOL_PROMPT = `<execution-plan-protocol>
|
|
|
7
7
|
- The active execution runs in <execution-plan-state> are a summary inventory only. They list runId and title, not node-level state.
|
|
8
8
|
- The runtime executor owns lifecycle truth. Do not claim node completion until the executor confirms.
|
|
9
9
|
- Do not invent or restate run/node lifecycle details that are not present in the prompt or tool results.
|
|
10
|
-
- During plan-triggered turns, use the dedicated result-submission tool.
|
|
10
|
+
- During plan-triggered turns, use the dedicated result-submission tool.
|
|
11
11
|
- Treat the active execution runs in <execution-plan-state> as authoritative for whether a plan already exists.
|
|
12
12
|
- If contracts or criteria materially change, replace the plan.
|
|
13
13
|
</execution-plan-protocol>`
|
package/src/runtime/index.ts
CHANGED
|
@@ -11,7 +11,7 @@ export function shouldEnqueueOnboardingPostChatMemory(params: {
|
|
|
11
11
|
return params.userMessageText.trim().length > 0 || params.hasAttachmentContext
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function
|
|
14
|
+
export function shouldEnqueueRegularDigestForThread(params: {
|
|
15
15
|
onboardingActive: boolean
|
|
16
16
|
turnCount?: number
|
|
17
17
|
}): boolean {
|
|
@@ -10,22 +10,22 @@ import {
|
|
|
10
10
|
shouldEnqueueMemoryConsolidation,
|
|
11
11
|
shouldEnqueueMemoryExtraction,
|
|
12
12
|
shouldEnqueueOnboardingPostChatMemory,
|
|
13
|
-
|
|
13
|
+
shouldEnqueueRegularDigestForThread,
|
|
14
14
|
} from '../runtime/memory-digest-policy'
|
|
15
15
|
import { getRuntimeAdapters } from '../runtime/runtime-extensions'
|
|
16
16
|
import { shouldEnqueueSkillExtraction } from '../runtime/skill-extraction-policy'
|
|
17
17
|
import {
|
|
18
|
-
|
|
18
|
+
appendPersistedThreadContextToHistoryMessages,
|
|
19
19
|
buildAgentHistoryMessages,
|
|
20
20
|
buildConversationSummary,
|
|
21
21
|
buildReadableUploadMetadataContext,
|
|
22
22
|
extractMessageText,
|
|
23
23
|
readOptionalString,
|
|
24
24
|
toHistoryMessages,
|
|
25
|
-
} from '../runtime/
|
|
25
|
+
} from '../runtime/thread-chat-helpers'
|
|
26
26
|
import { recentActivityService } from '../services/recent-activity.service'
|
|
27
|
-
import {
|
|
28
|
-
import type {
|
|
27
|
+
import { threadService } from '../services/thread.service'
|
|
28
|
+
import type { NormalizedThread, ThreadRecord } from '../services/thread.types'
|
|
29
29
|
import { safeEnqueue } from '../utils/async'
|
|
30
30
|
import { toIsoDateTimeString } from '../utils/date-time'
|
|
31
31
|
|
|
@@ -41,37 +41,37 @@ function resolveDisplayName(agentId: string, overrides?: Partial<Record<string,
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
function buildRecentActivityChatDeepLink(params: {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
thread: NormalizedThread
|
|
45
|
+
threadId: string
|
|
46
46
|
visibleAgentId: string
|
|
47
47
|
}): { route: string; search: Record<string, string> } {
|
|
48
|
-
if (params.
|
|
49
|
-
return { route: 'direct-
|
|
48
|
+
if (params.thread.type === 'default') {
|
|
49
|
+
return { route: 'direct-thread', search: { threadId: params.threadId, agentId: params.visibleAgentId } }
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
return { route: 'group-
|
|
52
|
+
return { route: 'group-thread', search: { threadId: params.threadId } }
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
function buildRecentActivityChatSystemTitle(params: {
|
|
56
|
-
|
|
56
|
+
thread: NormalizedThread
|
|
57
57
|
visibleAgentId: string
|
|
58
58
|
agentDisplayNamesById?: Partial<Record<string, string>>
|
|
59
59
|
}): string {
|
|
60
|
-
if (params.
|
|
60
|
+
if (params.thread.type === 'default') {
|
|
61
61
|
return `Conversation with ${resolveDisplayName(params.visibleAgentId, params.agentDisplayNamesById)}`
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
return params.
|
|
64
|
+
return params.thread.title.trim() || 'Thread update'
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
interface PostTurnSideEffectsParams {
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
thread: NormalizedThread
|
|
69
|
+
threadRef: RecordIdRef
|
|
70
70
|
orgRef: RecordIdRef
|
|
71
71
|
userRef: RecordIdRef
|
|
72
72
|
userName?: string | null
|
|
73
73
|
orgIdString: string
|
|
74
|
-
|
|
74
|
+
threadIdString: string
|
|
75
75
|
onboardingActive: boolean
|
|
76
76
|
workspace: unknown
|
|
77
77
|
allAssistantMessages: ChatMessage[]
|
|
@@ -85,19 +85,19 @@ interface PostTurnSideEffectsParams {
|
|
|
85
85
|
storageKey: string
|
|
86
86
|
}>
|
|
87
87
|
memoryBlock: string
|
|
88
|
-
|
|
88
|
+
visibleThreadAgentId: string | null | undefined
|
|
89
89
|
defaultLeadAgentId: string
|
|
90
|
-
|
|
90
|
+
latestThreadRecord: ThreadRecord
|
|
91
91
|
isUserTurn: boolean
|
|
92
92
|
agentDisplayNamesById?: Partial<Record<string, string>>
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
export async function runPostTurnSideEffects(params: PostTurnSideEffectsParams): Promise<void> {
|
|
96
96
|
const recentHistory = await params.loadRecentHistory()
|
|
97
|
-
const turnCount = await
|
|
97
|
+
const turnCount = await threadService.incrementTurnCount(params.threadRef)
|
|
98
98
|
const agentMessages = buildAgentHistoryMessages(params.allAssistantMessages)
|
|
99
|
-
const historyMessagesForMemory =
|
|
100
|
-
compactionSummary: params.
|
|
99
|
+
const historyMessagesForMemory = appendPersistedThreadContextToHistoryMessages(toHistoryMessages(recentHistory), {
|
|
100
|
+
compactionSummary: params.latestThreadRecord.compactionSummary,
|
|
101
101
|
})
|
|
102
102
|
|
|
103
103
|
const userMessageText = params.referenceUserMessage ? extractMessageText(params.referenceUserMessage).trim() : ''
|
|
@@ -120,7 +120,7 @@ export async function runPostTurnSideEffects(params: PostTurnSideEffectsParams):
|
|
|
120
120
|
() =>
|
|
121
121
|
enqueuePostChatMemory({
|
|
122
122
|
orgId: params.orgIdString,
|
|
123
|
-
|
|
123
|
+
threadId: params.threadIdString,
|
|
124
124
|
sourceId: params.referenceUserMessageId,
|
|
125
125
|
onboardStatus: readOptionalString((params.workspace as { onboardStatus?: unknown }).onboardStatus),
|
|
126
126
|
userMessage: memoryUserMessage,
|
|
@@ -139,7 +139,7 @@ export async function runPostTurnSideEffects(params: PostTurnSideEffectsParams):
|
|
|
139
139
|
assistantMessages: params.allAssistantMessages,
|
|
140
140
|
})
|
|
141
141
|
if (conversationSummary) {
|
|
142
|
-
const effectiveAgentId = params.
|
|
142
|
+
const effectiveAgentId = params.visibleThreadAgentId ?? params.defaultLeadAgentId
|
|
143
143
|
const recentActivityResult = await recentActivityService.recordEvent({
|
|
144
144
|
orgId: params.orgRef,
|
|
145
145
|
userId: params.userRef,
|
|
@@ -147,27 +147,27 @@ export async function runPostTurnSideEffects(params: PostTurnSideEffectsParams):
|
|
|
147
147
|
event: {
|
|
148
148
|
sourceEventId: `chat-turn:${params.referenceUserMessageId}`,
|
|
149
149
|
kind: 'chat.turn.completed',
|
|
150
|
-
targetKind: '
|
|
151
|
-
targetId: params.
|
|
152
|
-
mergeKey: `
|
|
150
|
+
targetKind: 'thread',
|
|
151
|
+
targetId: params.threadIdString,
|
|
152
|
+
mergeKey: `thread:${params.threadIdString}`,
|
|
153
153
|
title: buildRecentActivityChatSystemTitle({
|
|
154
|
-
|
|
154
|
+
thread: params.thread,
|
|
155
155
|
visibleAgentId: effectiveAgentId,
|
|
156
156
|
agentDisplayNamesById: params.agentDisplayNamesById,
|
|
157
157
|
}),
|
|
158
158
|
sourceLabel: resolveDisplayName(effectiveAgentId, params.agentDisplayNamesById),
|
|
159
159
|
deepLink: buildRecentActivityChatDeepLink({
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
thread: params.thread,
|
|
161
|
+
threadId: params.threadIdString,
|
|
162
162
|
visibleAgentId: effectiveAgentId,
|
|
163
163
|
}),
|
|
164
164
|
metadata: {
|
|
165
165
|
agentId: effectiveAgentId,
|
|
166
166
|
agentName: resolveDisplayName(effectiveAgentId, params.agentDisplayNamesById),
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
...(params.
|
|
167
|
+
threadId: params.threadIdString,
|
|
168
|
+
threadTitle: params.latestThreadRecord.title ?? params.thread.title,
|
|
169
|
+
threadType: params.thread.type,
|
|
170
|
+
...(params.thread.threadType ? { coreType: params.thread.threadType } : {}),
|
|
171
171
|
userMessageText,
|
|
172
172
|
assistantSummary: conversationSummary,
|
|
173
173
|
messageId: params.referenceUserMessageId,
|
|
@@ -186,7 +186,7 @@ export async function runPostTurnSideEffects(params: PostTurnSideEffectsParams):
|
|
|
186
186
|
|
|
187
187
|
await enqueuePostChatOrgAction({
|
|
188
188
|
orgId: params.orgIdString,
|
|
189
|
-
|
|
189
|
+
threadId: params.threadIdString,
|
|
190
190
|
sourceId: params.referenceUserMessageId,
|
|
191
191
|
sourceCreatedAt,
|
|
192
192
|
conversationSummary,
|
|
@@ -203,7 +203,7 @@ export async function runPostTurnSideEffects(params: PostTurnSideEffectsParams):
|
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
if (
|
|
206
|
+
if (shouldEnqueueRegularDigestForThread({ onboardingActive: params.onboardingActive, turnCount })) {
|
|
207
207
|
await safeEnqueue(() => enqueueRegularChatMemoryDigest({ orgId: params.orgIdString }), {
|
|
208
208
|
operationName: 'regular chat memory digest enqueue',
|
|
209
209
|
})
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { ToolSet } from 'ai'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type { CoreThreadProfile } from '../config/agent-defaults'
|
|
5
5
|
import type { AgentFactory, AgentRuntimeConfigProvider, AgentToolBuilder } from '../config/agent-types'
|
|
6
|
-
import type {
|
|
6
|
+
import type { LotaThreadConfig, ThreadBootstrapWelcomeConfig } from '../config/thread-defaults'
|
|
7
7
|
import type { RecordIdRef } from '../db/record-id'
|
|
8
8
|
import type { NotificationService } from '../services/notification.service'
|
|
9
9
|
import { isRecord } from '../utils/string'
|
|
@@ -144,21 +144,21 @@ function isSocialChatConfig(value: unknown): value is LotaRuntimeSocialChatConfi
|
|
|
144
144
|
return true
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
buildMessageText: z.custom<
|
|
147
|
+
const threadBootstrapWelcomeConfigSchema = z.object({
|
|
148
|
+
defaultAgentId: z.string().trim().min(1),
|
|
149
|
+
buildMessageText: z.custom<ThreadBootstrapWelcomeConfig['buildMessageText']>(isFunction, {
|
|
150
150
|
error: 'onboardingWelcome.buildMessageText must be a function',
|
|
151
151
|
}),
|
|
152
152
|
})
|
|
153
153
|
|
|
154
|
-
const
|
|
154
|
+
const threadConfigSchema = z.object({
|
|
155
155
|
bootstrap: z
|
|
156
156
|
.object({
|
|
157
157
|
onboardingDirectAgents: z.array(z.string().trim().min(1)).optional(),
|
|
158
158
|
completedDirectAgents: z.array(z.string().trim().min(1)).optional(),
|
|
159
159
|
coreTypesAfterOnboarding: z.array(z.string().trim().min(1)).optional(),
|
|
160
160
|
ensureDefaultGroupOnCompleted: z.boolean().optional(),
|
|
161
|
-
onboardingWelcome:
|
|
161
|
+
onboardingWelcome: threadBootstrapWelcomeConfigSchema.optional(),
|
|
162
162
|
})
|
|
163
163
|
.optional(),
|
|
164
164
|
})
|
|
@@ -178,9 +178,9 @@ const agentsConfigSchema = z
|
|
|
178
178
|
.optional(),
|
|
179
179
|
routerModelId: z.string().trim().min(1).optional(),
|
|
180
180
|
teamConsultParticipants: z.array(z.string().trim().min(1)),
|
|
181
|
-
|
|
182
|
-
.custom<(coreType: string) =>
|
|
183
|
-
error: 'agents.
|
|
181
|
+
getCoreThreadProfile: z
|
|
182
|
+
.custom<(coreType: string) => CoreThreadProfile>(isFunction, {
|
|
183
|
+
error: 'agents.getCoreThreadProfile must be a function',
|
|
184
184
|
})
|
|
185
185
|
.optional(),
|
|
186
186
|
createAgent: z
|
|
@@ -249,7 +249,7 @@ export const LotaRuntimeConfigSchema = z.object({
|
|
|
249
249
|
embeddingCacheTtlSeconds: z.coerce.number().int().positive().default(7200),
|
|
250
250
|
})
|
|
251
251
|
.default({ searchK: 6, embeddingCacheTtlSeconds: 7200 }),
|
|
252
|
-
|
|
252
|
+
threads: threadConfigSchema.default({}),
|
|
253
253
|
agents: agentsConfigSchema,
|
|
254
254
|
toolProviders: z.custom<Record<string, unknown>>(isToolProviderRecord).optional(),
|
|
255
255
|
extraSchemaFiles: z.array(z.custom<string | URL>(isStringOrUrl)).optional(),
|
|
@@ -319,4 +319,4 @@ export function parseWorkerBootstrapEnv(env: Record<string, string | undefined>)
|
|
|
319
319
|
return WORKER_BOOTSTRAP_ENV_SCHEMA.parse(env)
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
-
export type {
|
|
322
|
+
export type { LotaThreadConfig }
|
|
@@ -74,7 +74,7 @@ export interface LotaRuntimeTeamThinkToolsParams {
|
|
|
74
74
|
workspaceId: RecordIdRef
|
|
75
75
|
userId: RecordIdRef
|
|
76
76
|
workspaceIdString: string
|
|
77
|
-
|
|
77
|
+
threadId: RecordIdRef
|
|
78
78
|
githubInstalled: boolean
|
|
79
79
|
provideRepoTool: boolean
|
|
80
80
|
availableUploads: ReadableUploadMetadata[]
|
|
@@ -90,7 +90,7 @@ export interface LotaRuntimePlanEventEnvelope {
|
|
|
90
90
|
nodeSpec?: PlanNodeSpecRecord
|
|
91
91
|
nodeRun?: PlanNodeRunRecord
|
|
92
92
|
organizationId: string
|
|
93
|
-
|
|
93
|
+
threadId: string
|
|
94
94
|
runId: string
|
|
95
95
|
planSpecId: string
|
|
96
96
|
userId?: string
|
|
@@ -102,8 +102,8 @@ export interface LotaRuntimePlanEventAdapter {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
export interface BuildContextParams {
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
thread: unknown
|
|
106
|
+
threadRef: RecordIdRef
|
|
107
107
|
orgRef: RecordIdRef
|
|
108
108
|
userRef: RecordIdRef
|
|
109
109
|
userName?: string | null
|
|
@@ -123,15 +123,15 @@ export interface BuildContextParams {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
export interface AfterTurnParams {
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
thread: unknown
|
|
127
|
+
threadRef: RecordIdRef
|
|
128
128
|
orgRef: RecordIdRef
|
|
129
129
|
userRef: RecordIdRef
|
|
130
130
|
userName?: string | null
|
|
131
131
|
onboardingActive: boolean
|
|
132
132
|
referenceUserMessage: unknown
|
|
133
133
|
assistantMessages: unknown[]
|
|
134
|
-
|
|
134
|
+
latestThreadRecord: unknown
|
|
135
135
|
context: Record<string, unknown> | null
|
|
136
136
|
[key: string]: unknown
|
|
137
137
|
}
|
|
@@ -139,8 +139,8 @@ export interface AfterTurnParams {
|
|
|
139
139
|
export interface ResolveAgentParams {
|
|
140
140
|
agentId: string
|
|
141
141
|
mode: string
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
thread: unknown
|
|
143
|
+
threadRef: RecordIdRef
|
|
144
144
|
orgRef: RecordIdRef
|
|
145
145
|
userRef: RecordIdRef
|
|
146
146
|
userName?: string | null
|
|
@@ -154,8 +154,8 @@ export interface ResolveAgentParams {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
export interface BuildExtraInstructionSectionsParams {
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
thread: unknown
|
|
158
|
+
threadRef: RecordIdRef
|
|
159
159
|
orgRef: RecordIdRef
|
|
160
160
|
userRef: RecordIdRef
|
|
161
161
|
userName?: string | null
|
|
@@ -59,8 +59,8 @@ export function withLoggedSocialToolSet(
|
|
|
59
59
|
|
|
60
60
|
export async function runSocialAgentTurn(params: {
|
|
61
61
|
agentId: string
|
|
62
|
-
mode: '
|
|
63
|
-
|
|
62
|
+
mode: 'fixedThreadMode' | 'threadMode'
|
|
63
|
+
threadType: 'group'
|
|
64
64
|
onboardingActive: boolean
|
|
65
65
|
linearInstalled: boolean
|
|
66
66
|
systemWorkspaceDetails?: string
|
|
@@ -75,7 +75,7 @@ export async function runSocialAgentTurn(params: {
|
|
|
75
75
|
}): Promise<{ text: string; displayName: string }> {
|
|
76
76
|
const runtimeConfig = getAgentRuntimeConfig({
|
|
77
77
|
agentId: params.agentId,
|
|
78
|
-
|
|
78
|
+
threadType: params.threadType,
|
|
79
79
|
mode: params.mode,
|
|
80
80
|
onboardingActive: params.onboardingActive,
|
|
81
81
|
linearInstalled: params.linearInstalled,
|
|
@@ -2,7 +2,7 @@ import { stripSlackToolExecutionNoticeMarkdown } from '@lota-sdk/shared'
|
|
|
2
2
|
import type { Message, Thread } from 'chat'
|
|
3
3
|
|
|
4
4
|
import type { SocialChatHistoryMessage } from '../services/social-chat-history.service'
|
|
5
|
-
import { toHistoryMessages, toOptionalTrimmedString } from './
|
|
5
|
+
import { toHistoryMessages, toOptionalTrimmedString } from './thread-chat-helpers'
|
|
6
6
|
|
|
7
7
|
export function readSlackAuthorName(message: Message): string | undefined {
|
|
8
8
|
return (
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
extractMessageText,
|
|
49
49
|
toHistoryMessages,
|
|
50
50
|
toOptionalTrimmedString,
|
|
51
|
-
} from './
|
|
51
|
+
} from './thread-chat-helpers'
|
|
52
52
|
|
|
53
53
|
const DEFAULT_SOCIAL_CHAT_AGENT_ID = 'socialChat'
|
|
54
54
|
const DEFAULT_SOCIAL_CHAT_AGENT_DISPLAY_NAME = 'Lota'
|
|
@@ -362,8 +362,8 @@ export function createSocialChatRuntime(params: {
|
|
|
362
362
|
|
|
363
363
|
return await runSocialAgentTurn({
|
|
364
364
|
agentId,
|
|
365
|
-
mode: '
|
|
366
|
-
|
|
365
|
+
mode: 'fixedThreadMode',
|
|
366
|
+
threadType: 'group',
|
|
367
367
|
onboardingActive: lifecycleState?.bootstrapActive ?? false,
|
|
368
368
|
linearInstalled: false,
|
|
369
369
|
systemWorkspaceDetails: promptContext.systemWorkspaceDetails,
|
|
@@ -407,8 +407,8 @@ export function createSocialChatRuntime(params: {
|
|
|
407
407
|
aiLogger.info`Slack social-chat generating reply: channelId=${messageContext.channelId}, threadId=${messageContext.threadId}`
|
|
408
408
|
const leadRun = await runSocialAgentTurn({
|
|
409
409
|
agentId: socialAgentId,
|
|
410
|
-
mode: '
|
|
411
|
-
|
|
410
|
+
mode: 'threadMode',
|
|
411
|
+
threadType: 'group',
|
|
412
412
|
onboardingActive: lifecycleState?.bootstrapActive ?? false,
|
|
413
413
|
linearInstalled: false,
|
|
414
414
|
systemWorkspaceDetails: promptContext.systemWorkspaceDetails,
|
|
@@ -453,7 +453,7 @@ export function createSocialChatRuntime(params: {
|
|
|
453
453
|
enqueuePostChatMemory(
|
|
454
454
|
{
|
|
455
455
|
orgId: workspaceIdString,
|
|
456
|
-
|
|
456
|
+
threadId: `social:slack:${messageContext.threadId}`,
|
|
457
457
|
sourceId: createSocialChatCursorId({
|
|
458
458
|
workspaceId: workspaceIdString,
|
|
459
459
|
threadId: messageContext.threadId,
|
|
@@ -8,7 +8,7 @@ import { buildModelInputMessagesWithUploadMetadata, buildReadableUploadMetadataT
|
|
|
8
8
|
import type { ReadableUploadMetadataLike } from './chat-attachments'
|
|
9
9
|
import type { RepoSectionName } from './indexed-repositories-policy'
|
|
10
10
|
import { buildTeamConsultationFailureMessage } from './team-consultation-prompts'
|
|
11
|
-
import { extractMessageText } from './
|
|
11
|
+
import { extractMessageText } from './thread-chat-helpers'
|
|
12
12
|
|
|
13
13
|
export type DefaultRepoSections = RepoSectionName[]
|
|
14
14
|
const TEAM_CONSULTATION_TIMEOUT_MS = 90_000
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { agentDisplayNames, resolveAgentNameAlias } from '../config/agent-defaults'
|
|
2
2
|
import type { ChatMessageLike, ReadableUploadMetadataLike } from './chat-types'
|
|
3
3
|
|
|
4
|
-
export interface
|
|
4
|
+
export interface ThreadHistoryMessage {
|
|
5
5
|
role: 'user' | 'agent'
|
|
6
6
|
content: string
|
|
7
7
|
agentName?: string
|
|
@@ -42,9 +42,9 @@ export function extractMessageText(message: ChatMessageLike): string {
|
|
|
42
42
|
.trim()
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export function toHistoryMessages(messages: ChatMessageLike[], maxItems = 24):
|
|
45
|
+
export function toHistoryMessages(messages: ChatMessageLike[], maxItems = 24): ThreadHistoryMessage[] {
|
|
46
46
|
return messages
|
|
47
|
-
.map((message):
|
|
47
|
+
.map((message): ThreadHistoryMessage | null => {
|
|
48
48
|
const content = extractMessageText(message)
|
|
49
49
|
if (!content) return null
|
|
50
50
|
|
|
@@ -57,7 +57,7 @@ export function toHistoryMessages(messages: ChatMessageLike[], maxItems = 24): W
|
|
|
57
57
|
}
|
|
58
58
|
return null
|
|
59
59
|
})
|
|
60
|
-
.filter((message): message is
|
|
60
|
+
.filter((message): message is ThreadHistoryMessage => message !== null)
|
|
61
61
|
.slice(-maxItems)
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -86,10 +86,10 @@ export function buildAgentHistoryMessages(messages: ChatMessageLike[]): Array<{
|
|
|
86
86
|
.map((message) => ({ content: message.content, ...(message.agentName ? { agentName: message.agentName } : {}) }))
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
export function
|
|
90
|
-
historyMessages:
|
|
89
|
+
export function appendPersistedThreadContextToHistoryMessages(
|
|
90
|
+
historyMessages: ThreadHistoryMessage[],
|
|
91
91
|
params: { compactionSummary?: string | null },
|
|
92
|
-
):
|
|
92
|
+
): ThreadHistoryMessage[] {
|
|
93
93
|
const nextHistoryMessages = [...historyMessages]
|
|
94
94
|
const compactionSummary = typeof params.compactionSummary === 'string' ? params.compactionSummary.trim() : ''
|
|
95
95
|
if (compactionSummary) {
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { SUBMIT_PLAN_TURN_RESULT_TOOL_NAME, withMessageCreatedAt } from '@lota-sdk/shared'
|
|
2
|
-
import type {
|
|
3
|
-
ChatMessage,
|
|
4
|
-
PlanArtifactSubmission,
|
|
5
|
-
PlanNodeHandoffContext,
|
|
6
|
-
PlanNodeRunRecord,
|
|
7
|
-
PlanNodeSpecRecord,
|
|
8
|
-
} from '@lota-sdk/shared'
|
|
2
|
+
import type { ChatMessage, PlanArtifactSubmission, PlanNodeRunRecord, PlanNodeSpecRecord } from '@lota-sdk/shared'
|
|
9
3
|
|
|
10
4
|
import { buildCompletionCheckStructuredOutputHints } from './agent-runtime-policy'
|
|
11
5
|
import { mergeInstructionSections } from './instruction-sections'
|
|
@@ -15,10 +9,10 @@ export interface PlanTurnUpstreamHandoff {
|
|
|
15
9
|
label: string
|
|
16
10
|
ownerRef: string
|
|
17
11
|
ownerType: PlanNodeSpecRecord['owner']['executorType']
|
|
18
|
-
|
|
12
|
+
summary?: string
|
|
19
13
|
}
|
|
20
14
|
|
|
21
|
-
export interface
|
|
15
|
+
export interface ThreadPlanTurnContext {
|
|
22
16
|
runId: string
|
|
23
17
|
nodeId: string
|
|
24
18
|
planTitle: string
|
|
@@ -29,7 +23,7 @@ export interface WorkstreamPlanTurnContext {
|
|
|
29
23
|
upstreamHandoffs: PlanTurnUpstreamHandoff[]
|
|
30
24
|
}
|
|
31
25
|
|
|
32
|
-
function buildPlanTurnExecutionSection(planTurn:
|
|
26
|
+
function buildPlanTurnExecutionSection(planTurn: ThreadPlanTurnContext): string {
|
|
33
27
|
const requiredDeliverables = planTurn.nodeSpec.deliverables.filter((deliverable) => deliverable.required)
|
|
34
28
|
const completionCheckOutputHints = buildCompletionCheckStructuredOutputHints(planTurn.nodeSpec)
|
|
35
29
|
const payload = {
|
|
@@ -55,11 +49,11 @@ function buildPlanTurnExecutionSection(planTurn: WorkstreamPlanTurnContext): str
|
|
|
55
49
|
return [
|
|
56
50
|
'<plan-turn-execution>',
|
|
57
51
|
`Complete node "${planTurn.nodeSpec.label}" for plan "${planTurn.planTitle}".`,
|
|
58
|
-
'Use only the node contract, resolved input, input artifacts, and upstream
|
|
52
|
+
'Use only the node contract, resolved input, input artifacts, and upstream summaries.',
|
|
59
53
|
'Before submitting, satisfy every required deliverable, success criterion, and completion check.',
|
|
60
54
|
`Call ${SUBMIT_PLAN_TURN_RESULT_TOOL_NAME} exactly once when done.`,
|
|
61
55
|
`Required artifacts: ${requiredDeliverables.length > 0 ? requiredDeliverables.map((d) => d.name).join(', ') : 'none'}.`,
|
|
62
|
-
'
|
|
56
|
+
'notes is required. Include a concise summary of what was done, key decisions, and any context downstream nodes need.',
|
|
63
57
|
...(completionCheckOutputHints.length > 0
|
|
64
58
|
? ['Structured output fields required by completion checks:', ...completionCheckOutputHints]
|
|
65
59
|
: []),
|
|
@@ -81,7 +75,7 @@ function buildUpstreamHandoffSection(upstreamHandoffs: PlanTurnUpstreamHandoff[]
|
|
|
81
75
|
label: handoff.label,
|
|
82
76
|
ownerRef: handoff.ownerRef,
|
|
83
77
|
ownerType: handoff.ownerType,
|
|
84
|
-
|
|
78
|
+
...(handoff.summary ? { summary: handoff.summary } : {}),
|
|
85
79
|
})),
|
|
86
80
|
null,
|
|
87
81
|
2,
|
|
@@ -90,7 +84,7 @@ function buildUpstreamHandoffSection(upstreamHandoffs: PlanTurnUpstreamHandoff[]
|
|
|
90
84
|
].join('\n')
|
|
91
85
|
}
|
|
92
86
|
|
|
93
|
-
export function buildPlanTurnInstructionSections(planTurn:
|
|
87
|
+
export function buildPlanTurnInstructionSections(planTurn: ThreadPlanTurnContext): string[] {
|
|
94
88
|
const upstreamHandoffSection = buildUpstreamHandoffSection(planTurn.upstreamHandoffs)
|
|
95
89
|
return (
|
|
96
90
|
mergeInstructionSections(
|
|
@@ -100,7 +94,7 @@ export function buildPlanTurnInstructionSections(planTurn: WorkstreamPlanTurnCon
|
|
|
100
94
|
)
|
|
101
95
|
}
|
|
102
96
|
|
|
103
|
-
export function buildPlanTurnSubmitToolDescription(planTurn:
|
|
97
|
+
export function buildPlanTurnSubmitToolDescription(planTurn: ThreadPlanTurnContext): string {
|
|
104
98
|
const requiredArtifacts =
|
|
105
99
|
planTurn.nodeSpec.deliverables
|
|
106
100
|
.filter((deliverable) => deliverable.required)
|
|
@@ -114,11 +108,11 @@ export function buildPlanTurnSubmitToolDescription(planTurn: WorkstreamPlanTurnC
|
|
|
114
108
|
`Structured output: ${
|
|
115
109
|
planTurn.nodeSpec.outputSchemaRef ? `must satisfy ${planTurn.nodeSpec.outputSchemaRef}` : 'optional'
|
|
116
110
|
}.`,
|
|
117
|
-
'Do not submit partial results.
|
|
111
|
+
'Do not submit partial results. notes is required — include a concise summary for downstream nodes.',
|
|
118
112
|
].join(' ')
|
|
119
113
|
}
|
|
120
114
|
|
|
121
|
-
export function buildPlanTurnPromptMessage(planTurn:
|
|
115
|
+
export function buildPlanTurnPromptMessage(planTurn: ThreadPlanTurnContext): ChatMessage {
|
|
122
116
|
return withMessageCreatedAt(
|
|
123
117
|
{
|
|
124
118
|
id: Bun.randomUUIDv7(),
|
|
@@ -8,13 +8,13 @@ import type {
|
|
|
8
8
|
LotaRuntimeWorkspaceProjectionState,
|
|
9
9
|
LotaRuntimeWorkspaceProvider,
|
|
10
10
|
} from './runtime-extensions'
|
|
11
|
-
import { asRecord, readInstructionSections, readOptionalString } from './
|
|
11
|
+
import { asRecord, readInstructionSections, readOptionalString } from './thread-chat-helpers'
|
|
12
12
|
|
|
13
13
|
function readOptionalBoolean(value: unknown): boolean | undefined {
|
|
14
14
|
return typeof value === 'boolean' ? value : undefined
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
interface
|
|
17
|
+
interface AssembledThreadTurnContext {
|
|
18
18
|
workspace: Record<string, unknown>
|
|
19
19
|
workspaceLifecycleState: LotaRuntimeWorkspaceLifecycleState | undefined
|
|
20
20
|
workspaceProfileState: LotaRuntimeWorkspaceProjectionState | undefined
|
|
@@ -28,9 +28,9 @@ interface AssembledWorkstreamTurnContext {
|
|
|
28
28
|
hookInstructionSections: string[]
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
export async function
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
export async function assembleThreadTurnContext(params: {
|
|
32
|
+
thread: unknown
|
|
33
|
+
threadRef: RecordIdRef
|
|
34
34
|
orgRef: RecordIdRef
|
|
35
35
|
userRef: RecordIdRef
|
|
36
36
|
userName?: string | null
|
|
@@ -41,7 +41,7 @@ export async function assembleWorkstreamTurnContext(params: {
|
|
|
41
41
|
workspaceProvider?: LotaRuntimeWorkspaceProvider
|
|
42
42
|
turnHooks: LotaRuntimeTurnHooks
|
|
43
43
|
onStep?: (name: string) => void
|
|
44
|
-
}): Promise<
|
|
44
|
+
}): Promise<AssembledThreadTurnContext> {
|
|
45
45
|
const workspace = await params.workspacePromise
|
|
46
46
|
params.onStep?.('fetch-workspace')
|
|
47
47
|
|
|
@@ -104,8 +104,8 @@ export async function assembleWorkstreamTurnContext(params: {
|
|
|
104
104
|
|
|
105
105
|
const buildContextResult = asRecord(
|
|
106
106
|
await params.turnHooks.buildContext?.({
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
thread: params.thread,
|
|
108
|
+
threadRef: params.threadRef,
|
|
109
109
|
orgRef: params.orgRef,
|
|
110
110
|
userRef: params.userRef,
|
|
111
111
|
userName: params.userName,
|
|
@@ -144,8 +144,8 @@ export async function assembleWorkstreamTurnContext(params: {
|
|
|
144
144
|
|
|
145
145
|
const hookInstructionSections = readInstructionSections(
|
|
146
146
|
await params.turnHooks.buildExtraInstructionSections?.({
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
thread: params.thread,
|
|
148
|
+
threadRef: params.threadRef,
|
|
149
149
|
orgRef: params.orgRef,
|
|
150
150
|
userRef: params.userRef,
|
|
151
151
|
userName: params.userName,
|