@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.
Files changed (102) hide show
  1. package/infrastructure/schema/00_identity.surql +2 -2
  2. package/infrastructure/schema/00_thread.surql +75 -0
  3. package/infrastructure/schema/02_execution_plan.surql +10 -11
  4. package/infrastructure/schema/10_autonomous_job.surql +3 -3
  5. package/package.json +2 -2
  6. package/src/ai/definitions.ts +1 -1
  7. package/src/config/agent-defaults.ts +5 -5
  8. package/src/config/index.ts +1 -1
  9. package/src/config/thread-defaults.ts +72 -0
  10. package/src/create-runtime.ts +89 -93
  11. package/src/db/tables.ts +3 -3
  12. package/src/db/{workstream-message-row.ts → thread-message-row.ts} +3 -3
  13. package/src/queues/context-compaction.queue.ts +6 -6
  14. package/src/queues/plan-agent-heartbeat.queue.ts +3 -3
  15. package/src/queues/post-chat-memory.queue.ts +1 -1
  16. package/src/queues/title-generation.queue.ts +10 -13
  17. package/src/redis/index.ts +1 -1
  18. package/src/redis/stream-context.ts +1 -1
  19. package/src/runtime/agent-identity-overrides.ts +1 -1
  20. package/src/runtime/agent-runtime-policy.ts +19 -21
  21. package/src/runtime/chat-request-routing.ts +1 -1
  22. package/src/runtime/context-compaction-constants.ts +1 -1
  23. package/src/runtime/context-compaction.ts +1 -1
  24. package/src/runtime/execution-plan.ts +1 -1
  25. package/src/runtime/index.ts +1 -1
  26. package/src/runtime/memory-digest-policy.ts +1 -1
  27. package/src/runtime/plugin-types.ts +1 -1
  28. package/src/runtime/post-turn-side-effects.ts +35 -35
  29. package/src/runtime/runtime-config.ts +12 -12
  30. package/src/runtime/runtime-extensions.ts +11 -11
  31. package/src/runtime/social-chat-agent-runner.ts +3 -3
  32. package/src/runtime/social-chat-history.ts +1 -1
  33. package/src/runtime/social-chat.ts +6 -6
  34. package/src/runtime/team-consultation-orchestrator.ts +1 -1
  35. package/src/runtime/{workstream-chat-helpers.ts → thread-chat-helpers.ts} +7 -7
  36. package/src/runtime/{workstream-plan-turn.ts → thread-plan-turn.ts} +11 -17
  37. package/src/runtime/{workstream-turn-context.ts → thread-turn-context.ts} +10 -10
  38. package/src/services/agent-activity.service.ts +39 -44
  39. package/src/services/agent-executor.service.ts +17 -19
  40. package/src/services/attachment.service.ts +4 -8
  41. package/src/services/autonomous-job.service.ts +29 -28
  42. package/src/services/context-compaction.service.ts +19 -29
  43. package/src/services/execution-plan.service.ts +58 -70
  44. package/src/services/global-orchestrator.service.ts +5 -5
  45. package/src/services/index.ts +6 -6
  46. package/src/services/memory.service.ts +1 -1
  47. package/src/services/monitoring-window.service.ts +2 -2
  48. package/src/services/mutating-approval.service.ts +7 -10
  49. package/src/services/node-workspace.service.ts +8 -7
  50. package/src/services/notification.service.ts +1 -1
  51. package/src/services/organization.service.ts +9 -9
  52. package/src/services/ownership-dispatcher.service.ts +13 -19
  53. package/src/services/plan-agent-heartbeat.service.ts +13 -13
  54. package/src/services/plan-agent-query.service.ts +7 -7
  55. package/src/services/plan-artifact.service.ts +1 -2
  56. package/src/services/plan-coordination.service.ts +4 -4
  57. package/src/services/plan-cycle.service.ts +7 -7
  58. package/src/services/plan-deadline.service.ts +4 -4
  59. package/src/services/plan-event-delivery.service.ts +8 -12
  60. package/src/services/plan-executor.service.ts +16 -37
  61. package/src/services/plan-run-data.ts +27 -8
  62. package/src/services/plan-run.service.ts +7 -9
  63. package/src/services/plan-scheduler.service.ts +4 -4
  64. package/src/services/plan-template.service.ts +2 -2
  65. package/src/services/plan-validator.service.ts +0 -11
  66. package/src/services/plugin-executor.service.ts +1 -1
  67. package/src/services/queue-job.service.ts +1 -1
  68. package/src/services/recent-activity-title.service.ts +1 -1
  69. package/src/services/recent-activity.service.ts +4 -4
  70. package/src/services/system-executor.service.ts +2 -2
  71. package/src/services/{workstream-message.service.ts → thread-message.service.ts} +72 -76
  72. package/src/services/thread-plan-registry.service.ts +22 -0
  73. package/src/services/thread-title.service.ts +39 -0
  74. package/src/services/{workstream-turn-preparation.service.ts → thread-turn-preparation.service.ts} +131 -143
  75. package/src/services/{workstream-turn.ts → thread-turn.ts} +27 -31
  76. package/src/services/thread.service.ts +707 -0
  77. package/src/services/thread.types.ts +17 -0
  78. package/src/storage/attachment-storage.service.ts +4 -4
  79. package/src/system-agents/index.ts +1 -1
  80. package/src/system-agents/memory.agent.ts +1 -1
  81. package/src/system-agents/recent-activity-title-refiner.agent.ts +2 -2
  82. package/src/system-agents/regular-chat-memory-digest.agent.ts +1 -1
  83. package/src/system-agents/researcher.agent.ts +3 -3
  84. package/src/system-agents/{workstream-router.agent.ts → thread-router.agent.ts} +21 -21
  85. package/src/system-agents/title-generator.agent.ts +8 -8
  86. package/src/tools/execution-plan.tool.ts +39 -40
  87. package/src/tools/memory-block.tool.ts +4 -4
  88. package/src/tools/research-topic.tool.ts +1 -0
  89. package/src/tools/search-web.tool.ts +1 -1
  90. package/src/tools/search.tool.ts +4 -4
  91. package/src/tools/team-think.tool.ts +9 -9
  92. package/src/workers/regular-chat-memory-digest.helpers.ts +1 -1
  93. package/src/workers/regular-chat-memory-digest.runner.ts +43 -43
  94. package/src/workers/skill-extraction.runner.ts +9 -13
  95. package/src/workers/utils/{workstream-message-query.ts → thread-message-query.ts} +21 -21
  96. package/infrastructure/schema/00_workstream.surql +0 -64
  97. package/src/config/workstream-defaults.ts +0 -72
  98. package/src/services/workstream-plan-registry.service.ts +0 -22
  99. package/src/services/workstream-title.service.ts +0 -42
  100. package/src/services/workstream.service.ts +0 -803
  101. package/src/services/workstream.types.ts +0 -17
  102. /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 WORKSTREAM_RAW_TAIL_MESSAGES = 6
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 workstream memory block.',
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. Include handoffContext.
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>`
@@ -24,4 +24,4 @@ export * from './social-chat'
24
24
  export * from './team-consultation-orchestrator'
25
25
  export * from './team-consultation-prompts'
26
26
  export * from './turn-lifecycle'
27
- export * from './workstream-chat-helpers'
27
+ export * from './thread-chat-helpers'
@@ -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 shouldEnqueueRegularDigestForWorkstream(params: {
14
+ export function shouldEnqueueRegularDigestForThread(params: {
15
15
  onboardingActive: boolean
16
16
  turnCount?: number
17
17
  }): boolean {
@@ -9,7 +9,7 @@ export interface LotaPluginContributions {
9
9
 
10
10
  export interface PluginNodeExecutorContext {
11
11
  organizationId: string
12
- workstreamId: string
12
+ threadId: string
13
13
  planId: string
14
14
  nodeId: string
15
15
  userId?: RecordIdRef
@@ -10,22 +10,22 @@ import {
10
10
  shouldEnqueueMemoryConsolidation,
11
11
  shouldEnqueueMemoryExtraction,
12
12
  shouldEnqueueOnboardingPostChatMemory,
13
- shouldEnqueueRegularDigestForWorkstream,
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
- appendPersistedWorkstreamContextToHistoryMessages,
18
+ appendPersistedThreadContextToHistoryMessages,
19
19
  buildAgentHistoryMessages,
20
20
  buildConversationSummary,
21
21
  buildReadableUploadMetadataContext,
22
22
  extractMessageText,
23
23
  readOptionalString,
24
24
  toHistoryMessages,
25
- } from '../runtime/workstream-chat-helpers'
25
+ } from '../runtime/thread-chat-helpers'
26
26
  import { recentActivityService } from '../services/recent-activity.service'
27
- import { workstreamService } from '../services/workstream.service'
28
- import type { NormalizedWorkstream, WorkstreamRecord } from '../services/workstream.types'
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
- workstream: NormalizedWorkstream
45
- workstreamId: string
44
+ thread: NormalizedThread
45
+ threadId: string
46
46
  visibleAgentId: string
47
47
  }): { route: string; search: Record<string, string> } {
48
- if (params.workstream.mode === 'direct') {
49
- return { route: 'direct-workstream', search: { workstreamId: params.workstreamId, agentId: params.visibleAgentId } }
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-workstream', search: { workstreamId: params.workstreamId } }
52
+ return { route: 'group-thread', search: { threadId: params.threadId } }
53
53
  }
54
54
 
55
55
  function buildRecentActivityChatSystemTitle(params: {
56
- workstream: NormalizedWorkstream
56
+ thread: NormalizedThread
57
57
  visibleAgentId: string
58
58
  agentDisplayNamesById?: Partial<Record<string, string>>
59
59
  }): string {
60
- if (params.workstream.mode === 'direct') {
60
+ if (params.thread.type === 'default') {
61
61
  return `Conversation with ${resolveDisplayName(params.visibleAgentId, params.agentDisplayNamesById)}`
62
62
  }
63
63
 
64
- return params.workstream.title.trim() || 'Workstream update'
64
+ return params.thread.title.trim() || 'Thread update'
65
65
  }
66
66
 
67
67
  interface PostTurnSideEffectsParams {
68
- workstream: NormalizedWorkstream
69
- workstreamRef: RecordIdRef
68
+ thread: NormalizedThread
69
+ threadRef: RecordIdRef
70
70
  orgRef: RecordIdRef
71
71
  userRef: RecordIdRef
72
72
  userName?: string | null
73
73
  orgIdString: string
74
- workstreamIdString: string
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
- visibleWorkstreamAgentId: string | null | undefined
88
+ visibleThreadAgentId: string | null | undefined
89
89
  defaultLeadAgentId: string
90
- latestWorkstreamRecord: WorkstreamRecord
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 workstreamService.incrementTurnCount(params.workstreamRef)
97
+ const turnCount = await threadService.incrementTurnCount(params.threadRef)
98
98
  const agentMessages = buildAgentHistoryMessages(params.allAssistantMessages)
99
- const historyMessagesForMemory = appendPersistedWorkstreamContextToHistoryMessages(toHistoryMessages(recentHistory), {
100
- compactionSummary: params.latestWorkstreamRecord.compactionSummary,
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
- workstreamId: params.workstreamIdString,
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.visibleWorkstreamAgentId ?? params.defaultLeadAgentId
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: 'workstream',
151
- targetId: params.workstreamIdString,
152
- mergeKey: `workstream:${params.workstreamIdString}`,
150
+ targetKind: 'thread',
151
+ targetId: params.threadIdString,
152
+ mergeKey: `thread:${params.threadIdString}`,
153
153
  title: buildRecentActivityChatSystemTitle({
154
- workstream: params.workstream,
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
- workstream: params.workstream,
161
- workstreamId: params.workstreamIdString,
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
- workstreamId: params.workstreamIdString,
168
- workstreamTitle: params.latestWorkstreamRecord.title ?? params.workstream.title,
169
- workstreamMode: params.workstream.mode,
170
- ...(params.workstream.coreType ? { coreType: params.workstream.coreType } : {}),
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
- workstreamId: params.workstreamIdString,
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 (shouldEnqueueRegularDigestForWorkstream({ onboardingActive: params.onboardingActive, turnCount })) {
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 { CoreWorkstreamProfile } from '../config/agent-defaults'
4
+ import type { CoreThreadProfile } from '../config/agent-defaults'
5
5
  import type { AgentFactory, AgentRuntimeConfigProvider, AgentToolBuilder } from '../config/agent-types'
6
- import type { LotaWorkstreamConfig, WorkstreamBootstrapWelcomeConfig } from '../config/workstream-defaults'
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 workstreamBootstrapWelcomeConfigSchema = z.object({
148
- directAgentId: z.string().trim().min(1),
149
- buildMessageText: z.custom<WorkstreamBootstrapWelcomeConfig['buildMessageText']>(isFunction, {
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 workstreamConfigSchema = z.object({
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: workstreamBootstrapWelcomeConfigSchema.optional(),
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
- getCoreWorkstreamProfile: z
182
- .custom<(coreType: string) => CoreWorkstreamProfile>(isFunction, {
183
- error: 'agents.getCoreWorkstreamProfile must be a function',
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
- workstreams: workstreamConfigSchema.default({}),
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 { LotaWorkstreamConfig }
322
+ export type { LotaThreadConfig }
@@ -74,7 +74,7 @@ export interface LotaRuntimeTeamThinkToolsParams {
74
74
  workspaceId: RecordIdRef
75
75
  userId: RecordIdRef
76
76
  workspaceIdString: string
77
- workstreamId: RecordIdRef
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
- workstreamId: string
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
- workstream: unknown
106
- workstreamRef: RecordIdRef
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
- workstream: unknown
127
- workstreamRef: RecordIdRef
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
- latestWorkstreamRecord: unknown
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
- workstream: unknown
143
- workstreamRef: RecordIdRef
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
- workstream: unknown
158
- workstreamRef: RecordIdRef
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: 'fixedWorkstreamMode' | 'workstreamMode'
63
- workstreamMode: 'group'
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
- workstreamMode: params.workstreamMode,
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 './workstream-chat-helpers'
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 './workstream-chat-helpers'
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: 'fixedWorkstreamMode',
366
- workstreamMode: 'group',
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: 'workstreamMode',
411
- workstreamMode: 'group',
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
- workstreamId: `social:slack:${messageContext.threadId}`,
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 './workstream-chat-helpers'
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 WorkstreamHistoryMessage {
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): WorkstreamHistoryMessage[] {
45
+ export function toHistoryMessages(messages: ChatMessageLike[], maxItems = 24): ThreadHistoryMessage[] {
46
46
  return messages
47
- .map((message): WorkstreamHistoryMessage | null => {
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 WorkstreamHistoryMessage => message !== null)
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 appendPersistedWorkstreamContextToHistoryMessages(
90
- historyMessages: WorkstreamHistoryMessage[],
89
+ export function appendPersistedThreadContextToHistoryMessages(
90
+ historyMessages: ThreadHistoryMessage[],
91
91
  params: { compactionSummary?: string | null },
92
- ): WorkstreamHistoryMessage[] {
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
- handoffContext: PlanNodeHandoffContext
12
+ summary?: string
19
13
  }
20
14
 
21
- export interface WorkstreamPlanTurnContext {
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: WorkstreamPlanTurnContext): string {
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 handoff context.',
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
- 'Include notes with a concise completion summary. Include handoffContext with summary, key decisions, open questions, risks, and recommendations for downstream nodes.',
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
- handoffContext: handoff.handoffContext,
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: WorkstreamPlanTurnContext): string[] {
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: WorkstreamPlanTurnContext): string {
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. Include durable handoffContext for downstream nodes.',
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: WorkstreamPlanTurnContext): ChatMessage {
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 './workstream-chat-helpers'
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 AssembledWorkstreamTurnContext {
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 assembleWorkstreamTurnContext(params: {
32
- workstream: unknown
33
- workstreamRef: RecordIdRef
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<AssembledWorkstreamTurnContext> {
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
- workstream: params.workstream,
108
- workstreamRef: params.workstreamRef,
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
- workstream: params.workstream,
148
- workstreamRef: params.workstreamRef,
147
+ thread: params.thread,
148
+ threadRef: params.threadRef,
149
149
  orgRef: params.orgRef,
150
150
  userRef: params.userRef,
151
151
  userName: params.userName,