@lota-sdk/core 0.1.24 → 0.1.26
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 +2 -2
- package/src/ai/definitions.ts +5 -59
- package/src/ai-gateway/ai-gateway.ts +36 -28
- package/src/ai-gateway/cache-headers.ts +9 -0
- package/src/config/model-constants.ts +6 -2
- package/src/create-runtime.ts +1 -17
- package/src/db/memory-types.ts +13 -8
- package/src/db/memory.ts +74 -53
- package/src/queues/autonomous-job.queue.ts +1 -8
- package/src/queues/context-compaction.queue.ts +2 -2
- package/src/queues/index.ts +2 -6
- package/src/queues/organization-learning.queue.ts +78 -0
- package/src/queues/plan-agent-heartbeat.queue.ts +10 -16
- package/src/queues/title-generation.queue.ts +62 -0
- package/src/runtime/agent-prompt-context.ts +0 -18
- package/src/runtime/agent-runtime-policy.ts +9 -2
- package/src/runtime/context-compaction-constants.ts +4 -2
- package/src/runtime/context-compaction.ts +135 -118
- package/src/runtime/memory-pipeline.ts +70 -1
- package/src/runtime/memory-prompts-fact.ts +16 -0
- package/src/runtime/plugin-resolution.ts +3 -2
- package/src/runtime/plugin-types.ts +1 -42
- package/src/runtime/post-turn-side-effects.ts +212 -0
- package/src/runtime/runtime-config.ts +0 -13
- package/src/runtime/runtime-extensions.ts +10 -16
- package/src/runtime/runtime-worker-registry.ts +8 -19
- package/src/runtime/social-chat-agent-runner.ts +119 -0
- package/src/runtime/social-chat-history.ts +110 -0
- package/src/runtime/social-chat-prompts.ts +58 -0
- package/src/runtime/social-chat.ts +104 -340
- package/src/runtime/specialist-runner.ts +18 -0
- package/src/runtime/workstream-chat-helpers.ts +19 -0
- package/src/runtime/workstream-plan-turn.ts +195 -0
- package/src/runtime/workstream-state.ts +11 -8
- package/src/runtime/workstream-turn-context.ts +183 -0
- package/src/services/autonomous-job.service.ts +1 -8
- package/src/services/execution-plan.service.ts +205 -334
- package/src/services/index.ts +1 -4
- package/src/services/memory.service.ts +54 -44
- package/src/services/ownership-dispatcher.service.ts +2 -19
- package/src/services/plan-completion-side-effects.ts +80 -0
- package/src/services/plan-event-delivery.service.ts +1 -1
- package/src/services/plan-executor.service.ts +42 -190
- package/src/services/plan-node-spec.ts +60 -0
- package/src/services/plan-run-data.ts +88 -0
- package/src/services/plan-validator.service.ts +10 -8
- package/src/services/workstream-constants.ts +2 -0
- package/src/services/workstream-title.service.ts +1 -1
- package/src/services/workstream-turn-preparation.service.ts +208 -715
- package/src/services/workstream.service.ts +162 -192
- package/src/services/workstream.types.ts +12 -44
- package/src/system-agents/regular-chat-memory-digest.agent.ts +3 -0
- package/src/tools/execution-plan.tool.ts +7 -6
- package/src/tools/remember-memory.tool.ts +7 -10
- package/src/tools/research-topic.tool.ts +1 -1
- package/src/tools/team-think.tool.ts +1 -1
- package/src/tools/user-questions.tool.ts +1 -1
- package/src/utils/autonomous-job-ids.ts +7 -0
- package/src/workers/organization-learning.worker.ts +31 -0
- package/src/workers/regular-chat-memory-digest.runner.ts +9 -3
- package/src/workers/skill-extraction.runner.ts +2 -2
- package/src/queues/recent-activity-title-refinement.queue.ts +0 -30
- package/src/queues/regular-chat-memory-digest.config.ts +0 -12
- package/src/queues/regular-chat-memory-digest.queue.ts +0 -34
- package/src/queues/skill-extraction.config.ts +0 -9
- package/src/queues/skill-extraction.queue.ts +0 -27
- package/src/queues/workstream-title-generation.queue.ts +0 -33
- package/src/services/context-enrichment.service.ts +0 -33
- package/src/services/coordination-registry.service.ts +0 -117
- package/src/services/domain-agent-executor.service.ts +0 -71
- package/src/services/memory-assessment.service.ts +0 -44
- package/src/services/playbook-registry.service.ts +0 -67
- package/src/workers/regular-chat-memory-digest.worker.ts +0 -22
- package/src/workers/skill-extraction.worker.ts +0 -22
|
@@ -0,0 +1,195 @@
|
|
|
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'
|
|
9
|
+
|
|
10
|
+
import { buildCompletionCheckStructuredOutputHints } from './agent-runtime-policy'
|
|
11
|
+
import { mergeInstructionSections } from './instruction-sections'
|
|
12
|
+
|
|
13
|
+
export interface PlanTurnUpstreamHandoff {
|
|
14
|
+
nodeId: string
|
|
15
|
+
label: string
|
|
16
|
+
ownerRef: string
|
|
17
|
+
ownerType: PlanNodeSpecRecord['owner']['executorType']
|
|
18
|
+
handoffContext: PlanNodeHandoffContext
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface WorkstreamPlanTurnContext {
|
|
22
|
+
runId: string
|
|
23
|
+
nodeId: string
|
|
24
|
+
planTitle: string
|
|
25
|
+
nodeSpec: PlanNodeSpecRecord
|
|
26
|
+
nodeRun: PlanNodeRunRecord
|
|
27
|
+
resolvedInput: Record<string, unknown>
|
|
28
|
+
inputArtifacts: PlanArtifactSubmission[]
|
|
29
|
+
upstreamHandoffs: PlanTurnUpstreamHandoff[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function describePlanTurnDeliverable(deliverable: PlanNodeSpecRecord['deliverables'][number]): string {
|
|
33
|
+
return [
|
|
34
|
+
`- ${deliverable.name}`,
|
|
35
|
+
`kind=${deliverable.kind}`,
|
|
36
|
+
deliverable.required ? 'required' : 'optional',
|
|
37
|
+
deliverable.schemaRef ? `schemaRef=${deliverable.schemaRef}` : undefined,
|
|
38
|
+
deliverable.description ? `description=${deliverable.description}` : undefined,
|
|
39
|
+
]
|
|
40
|
+
.filter(Boolean)
|
|
41
|
+
.join(' | ')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function describePlanTurnCompletionCheck(check: PlanNodeSpecRecord['completionChecks'][number]): string {
|
|
45
|
+
return [
|
|
46
|
+
`- ${check.description}`,
|
|
47
|
+
`type=${check.type}`,
|
|
48
|
+
check.blocking ? 'blocking' : 'warning',
|
|
49
|
+
Object.keys(check.config).length > 0 ? `config=${JSON.stringify(check.config)}` : undefined,
|
|
50
|
+
]
|
|
51
|
+
.filter(Boolean)
|
|
52
|
+
.join(' | ')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function buildPlanTurnExecutionSection(planTurn: WorkstreamPlanTurnContext): string {
|
|
56
|
+
const payload = {
|
|
57
|
+
runId: planTurn.runId,
|
|
58
|
+
planTitle: planTurn.planTitle,
|
|
59
|
+
node: {
|
|
60
|
+
id: planTurn.nodeSpec.nodeId,
|
|
61
|
+
label: planTurn.nodeSpec.label,
|
|
62
|
+
owner: planTurn.nodeSpec.owner,
|
|
63
|
+
objective: planTurn.nodeSpec.objective,
|
|
64
|
+
instructions: planTurn.nodeSpec.instructions,
|
|
65
|
+
outputSchemaRef: planTurn.nodeSpec.outputSchemaRef ?? null,
|
|
66
|
+
deliverables: planTurn.nodeSpec.deliverables,
|
|
67
|
+
successCriteria: planTurn.nodeSpec.successCriteria,
|
|
68
|
+
completionChecks: planTurn.nodeSpec.completionChecks,
|
|
69
|
+
toolPolicy: planTurn.nodeSpec.toolPolicy,
|
|
70
|
+
contextPolicy: planTurn.nodeSpec.contextPolicy,
|
|
71
|
+
},
|
|
72
|
+
resolvedInput: planTurn.resolvedInput,
|
|
73
|
+
inputArtifacts: planTurn.inputArtifacts,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return [
|
|
77
|
+
'<plan-turn-execution>',
|
|
78
|
+
'The runtime has activated a visible execution-plan node inside this workstream.',
|
|
79
|
+
`Complete node "${planTurn.nodeSpec.label}" for plan "${planTurn.planTitle}".`,
|
|
80
|
+
'Use only the node contract, resolved input, input artifacts, and upstream handoff context provided here.',
|
|
81
|
+
'Do not ask the user for more input and do not rely on unstated external context.',
|
|
82
|
+
'Do not submit placeholders, partial work, or speculative outputs.',
|
|
83
|
+
'Before submitting, satisfy every required deliverable, success criterion, and completion check for this node.',
|
|
84
|
+
'Deliverables must use the exact artifact names and kinds declared in the node contract.',
|
|
85
|
+
'If a deliverable declares schemaRef, include the same schemaRef and a payload that satisfies that schema.',
|
|
86
|
+
'If outputSchemaRef is declared, structuredOutput must satisfy that schema before you submit.',
|
|
87
|
+
`When finished, call ${SUBMIT_PLAN_TURN_RESULT_TOOL_NAME} exactly once.`,
|
|
88
|
+
'Always include durable handoffContext for downstream nodes when you submit the final result.',
|
|
89
|
+
'Do not ask the user for confirmation and do not create or replace execution plans in this turn.',
|
|
90
|
+
JSON.stringify(payload, null, 2),
|
|
91
|
+
'</plan-turn-execution>',
|
|
92
|
+
].join('\n')
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function buildPlanTurnResultContractSection(planTurn: WorkstreamPlanTurnContext): string {
|
|
96
|
+
const requiredDeliverables = planTurn.nodeSpec.deliverables.filter((deliverable) => deliverable.required)
|
|
97
|
+
const completionCheckOutputHints = buildCompletionCheckStructuredOutputHints(planTurn.nodeSpec)
|
|
98
|
+
const deliverableLines =
|
|
99
|
+
planTurn.nodeSpec.deliverables.length > 0
|
|
100
|
+
? planTurn.nodeSpec.deliverables.map(describePlanTurnDeliverable)
|
|
101
|
+
: ['- none']
|
|
102
|
+
const completionCheckLines =
|
|
103
|
+
planTurn.nodeSpec.completionChecks.length > 0
|
|
104
|
+
? planTurn.nodeSpec.completionChecks.map(describePlanTurnCompletionCheck)
|
|
105
|
+
: ['- none']
|
|
106
|
+
|
|
107
|
+
return [
|
|
108
|
+
'<plan-turn-result-contract>',
|
|
109
|
+
`Call ${SUBMIT_PLAN_TURN_RESULT_TOOL_NAME} exactly once with a result object that passes node validation.`,
|
|
110
|
+
'Validation is strict. Missing required artifacts, schema mismatches, or failed completion checks will fail the node run.',
|
|
111
|
+
`Required artifacts: ${requiredDeliverables.length > 0 ? requiredDeliverables.map((deliverable) => deliverable.name).join(', ') : 'none'}`,
|
|
112
|
+
`Structured output: ${
|
|
113
|
+
planTurn.nodeSpec.outputSchemaRef
|
|
114
|
+
? `required and must match schema "${planTurn.nodeSpec.outputSchemaRef}"`
|
|
115
|
+
: 'optional unless needed by a completion check'
|
|
116
|
+
}`,
|
|
117
|
+
'Deliverables:',
|
|
118
|
+
...deliverableLines,
|
|
119
|
+
'Completion checks:',
|
|
120
|
+
...completionCheckLines,
|
|
121
|
+
...(completionCheckOutputHints.length > 0
|
|
122
|
+
? ['Structured output fields required by completion checks:', ...completionCheckOutputHints]
|
|
123
|
+
: []),
|
|
124
|
+
'Include notes with a concise completion summary grounded in the submitted artifacts and structuredOutput.',
|
|
125
|
+
'Always include handoffContext for downstream execution with a durable summary, key decisions, open questions, risks, recommendations, and references when relevant.',
|
|
126
|
+
'</plan-turn-result-contract>',
|
|
127
|
+
].join('\n')
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function buildUpstreamHandoffSection(upstreamHandoffs: PlanTurnUpstreamHandoff[]): string | undefined {
|
|
131
|
+
if (upstreamHandoffs.length === 0) {
|
|
132
|
+
return undefined
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return [
|
|
136
|
+
'<upstream-handoff>',
|
|
137
|
+
JSON.stringify(
|
|
138
|
+
upstreamHandoffs.map((handoff) => ({
|
|
139
|
+
nodeId: handoff.nodeId,
|
|
140
|
+
label: handoff.label,
|
|
141
|
+
ownerRef: handoff.ownerRef,
|
|
142
|
+
ownerType: handoff.ownerType,
|
|
143
|
+
handoffContext: handoff.handoffContext,
|
|
144
|
+
})),
|
|
145
|
+
null,
|
|
146
|
+
2,
|
|
147
|
+
),
|
|
148
|
+
'</upstream-handoff>',
|
|
149
|
+
].join('\n')
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function buildPlanTurnInstructionSections(planTurn: WorkstreamPlanTurnContext): string[] {
|
|
153
|
+
const upstreamHandoffSection = buildUpstreamHandoffSection(planTurn.upstreamHandoffs)
|
|
154
|
+
return (
|
|
155
|
+
mergeInstructionSections(
|
|
156
|
+
[buildPlanTurnExecutionSection(planTurn), buildPlanTurnResultContractSection(planTurn)],
|
|
157
|
+
upstreamHandoffSection ? [upstreamHandoffSection] : undefined,
|
|
158
|
+
) ?? []
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function buildPlanTurnSubmitToolDescription(planTurn: WorkstreamPlanTurnContext): string {
|
|
163
|
+
const requiredArtifacts =
|
|
164
|
+
planTurn.nodeSpec.deliverables
|
|
165
|
+
.filter((deliverable) => deliverable.required)
|
|
166
|
+
.map((deliverable) => `${deliverable.name} (${deliverable.kind})`)
|
|
167
|
+
.join(', ') || 'none'
|
|
168
|
+
|
|
169
|
+
return [
|
|
170
|
+
'Submit the final result for the active plan-triggered node turn.',
|
|
171
|
+
'Call this exactly once when the node output is complete.',
|
|
172
|
+
`Required artifacts: ${requiredArtifacts}.`,
|
|
173
|
+
`Structured output: ${
|
|
174
|
+
planTurn.nodeSpec.outputSchemaRef ? `must satisfy ${planTurn.nodeSpec.outputSchemaRef}` : 'optional'
|
|
175
|
+
}.`,
|
|
176
|
+
'Do not submit partial results. Include durable handoffContext for downstream nodes.',
|
|
177
|
+
].join(' ')
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function buildPlanTurnPromptMessage(planTurn: WorkstreamPlanTurnContext): ChatMessage {
|
|
181
|
+
return withMessageCreatedAt(
|
|
182
|
+
{
|
|
183
|
+
id: Bun.randomUUIDv7(),
|
|
184
|
+
role: 'user',
|
|
185
|
+
parts: [
|
|
186
|
+
{
|
|
187
|
+
type: 'text',
|
|
188
|
+
text: `Execute the active plan node "${planTurn.nodeSpec.label}" now and submit the result with ${SUBMIT_PLAN_TURN_RESULT_TOOL_NAME}.`,
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
metadata: { trigger: 'plan-turn', planRunId: planTurn.runId, planNodeId: planTurn.nodeId },
|
|
192
|
+
},
|
|
193
|
+
Date.now(),
|
|
194
|
+
)
|
|
195
|
+
}
|
|
@@ -116,10 +116,10 @@ export const WorkstreamStateDeltaSchema = z.object({
|
|
|
116
116
|
conflicts: z
|
|
117
117
|
.array(z.object({ newFact: z.string(), conflictsWith: z.string(), recommendation: z.string() }))
|
|
118
118
|
.optional(),
|
|
119
|
-
approvedBy: z.string().optional(),
|
|
120
|
-
approvedAt: z.number().int().optional(),
|
|
121
|
-
approvalMessageId: z.string().optional(),
|
|
122
|
-
approvalNote: z.string().optional(),
|
|
119
|
+
approvedBy: z.string().nullable().optional(),
|
|
120
|
+
approvedAt: z.number().int().nullable().optional(),
|
|
121
|
+
approvalMessageId: z.string().nullable().optional(),
|
|
122
|
+
approvalNote: z.string().nullable().optional(),
|
|
123
123
|
})
|
|
124
124
|
|
|
125
125
|
export type WorkstreamStateDelta = z.infer<typeof WorkstreamStateDeltaSchema>
|
|
@@ -194,6 +194,7 @@ export function createEmptyStructuredWorkstreamStateDelta(): StructuredWorkstrea
|
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
export function parseStructuredWorkstreamStateDelta(value: unknown): WorkstreamStateDelta {
|
|
197
|
+
const inputRecord = typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : null
|
|
197
198
|
const parsed = StructuredWorkstreamStateDeltaSchema.parse(value)
|
|
198
199
|
|
|
199
200
|
return {
|
|
@@ -221,10 +222,12 @@ export function parseStructuredWorkstreamStateDelta(value: unknown): WorkstreamS
|
|
|
221
222
|
...(parsed.artifacts.length > 0 ? { artifacts: parsed.artifacts } : {}),
|
|
222
223
|
...(parsed.agentNote ? { agentNote: parsed.agentNote } : {}),
|
|
223
224
|
...(parsed.conflicts.length > 0 ? { conflicts: parsed.conflicts } : {}),
|
|
224
|
-
...(
|
|
225
|
-
...(
|
|
226
|
-
...(
|
|
227
|
-
|
|
225
|
+
...(inputRecord && Object.hasOwn(inputRecord, 'approvedBy') ? { approvedBy: parsed.approvedBy } : {}),
|
|
226
|
+
...(inputRecord && Object.hasOwn(inputRecord, 'approvedAt') ? { approvedAt: parsed.approvedAt } : {}),
|
|
227
|
+
...(inputRecord && Object.hasOwn(inputRecord, 'approvalMessageId')
|
|
228
|
+
? { approvalMessageId: parsed.approvalMessageId }
|
|
229
|
+
: {}),
|
|
230
|
+
...(inputRecord && Object.hasOwn(inputRecord, 'approvalNote') ? { approvalNote: parsed.approvalNote } : {}),
|
|
228
231
|
}
|
|
229
232
|
}
|
|
230
233
|
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import type { RecordIdRef } from '../db/record-id'
|
|
2
|
+
import { buildAgentPromptContext } from './agent-prompt-context'
|
|
3
|
+
import { buildIndexedRepositoriesContext, getPluginService } from './plugin-resolution'
|
|
4
|
+
import type {
|
|
5
|
+
LotaRuntimeIndexedRepositoriesContext,
|
|
6
|
+
LotaRuntimeTurnHooks,
|
|
7
|
+
LotaRuntimeWorkspaceLifecycleState,
|
|
8
|
+
LotaRuntimeWorkspaceProjectionState,
|
|
9
|
+
LotaRuntimeWorkspaceProvider,
|
|
10
|
+
} from './runtime-extensions'
|
|
11
|
+
import { asRecord, readInstructionSections, readOptionalString } from './workstream-chat-helpers'
|
|
12
|
+
|
|
13
|
+
function readOptionalBoolean(value: unknown): boolean | undefined {
|
|
14
|
+
return typeof value === 'boolean' ? value : undefined
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface AssembledWorkstreamTurnContext {
|
|
18
|
+
workspace: Record<string, unknown>
|
|
19
|
+
workspaceLifecycleState: LotaRuntimeWorkspaceLifecycleState | undefined
|
|
20
|
+
workspaceProfileState: LotaRuntimeWorkspaceProjectionState | undefined
|
|
21
|
+
onboardingActive: boolean
|
|
22
|
+
linearInstalled: boolean
|
|
23
|
+
githubInstalled: boolean
|
|
24
|
+
indexedRepoContext: LotaRuntimeIndexedRepositoriesContext
|
|
25
|
+
promptContext: { systemWorkspaceDetails?: string }
|
|
26
|
+
retrievedKnowledgeSection: string | undefined
|
|
27
|
+
buildContextResult: Record<string, unknown> | null
|
|
28
|
+
hookInstructionSections: string[]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function assembleWorkstreamTurnContext(params: {
|
|
32
|
+
workstream: unknown
|
|
33
|
+
workstreamRef: RecordIdRef
|
|
34
|
+
orgRef: RecordIdRef
|
|
35
|
+
userRef: RecordIdRef
|
|
36
|
+
userName?: string | null
|
|
37
|
+
orgIdString: string
|
|
38
|
+
userIdString: string
|
|
39
|
+
messageText: string
|
|
40
|
+
workspacePromise: Promise<Record<string, unknown>>
|
|
41
|
+
workspaceProvider?: LotaRuntimeWorkspaceProvider
|
|
42
|
+
turnHooks: LotaRuntimeTurnHooks
|
|
43
|
+
onStep?: (name: string) => void
|
|
44
|
+
}): Promise<AssembledWorkstreamTurnContext> {
|
|
45
|
+
const workspace = await params.workspacePromise
|
|
46
|
+
params.onStep?.('fetch-workspace')
|
|
47
|
+
|
|
48
|
+
const [workspaceLifecycleState, workspaceProfileState] = await Promise.all([
|
|
49
|
+
params.workspaceProvider ? params.workspaceProvider.getLifecycleState?.(workspace) : Promise.resolve(undefined),
|
|
50
|
+
params.workspaceProvider
|
|
51
|
+
? params.workspaceProvider.readProfileProjectionState?.(workspace)
|
|
52
|
+
: Promise.resolve(undefined),
|
|
53
|
+
])
|
|
54
|
+
params.onStep?.('workspace-state')
|
|
55
|
+
|
|
56
|
+
const onboardingActive = workspaceLifecycleState?.bootstrapActive ?? false
|
|
57
|
+
const getLinearInstallationByOrgId = getPluginService([
|
|
58
|
+
'linear',
|
|
59
|
+
'services',
|
|
60
|
+
'linearService',
|
|
61
|
+
'getInstallationByOrgId',
|
|
62
|
+
])
|
|
63
|
+
const getGithubInstallationForOrganization = getPluginService([
|
|
64
|
+
'github',
|
|
65
|
+
'services',
|
|
66
|
+
'githubService',
|
|
67
|
+
'getInstallationForOrganization',
|
|
68
|
+
])
|
|
69
|
+
const [linearInstallation, githubInstallation, indexedRepoContext, recentDomainEvents, promptSummary] =
|
|
70
|
+
await Promise.all([
|
|
71
|
+
getLinearInstallationByOrgId
|
|
72
|
+
? (getLinearInstallationByOrgId(params.orgRef) as Promise<unknown>)
|
|
73
|
+
: Promise.resolve(null),
|
|
74
|
+
getGithubInstallationForOrganization
|
|
75
|
+
? (getGithubInstallationForOrganization(params.orgIdString) as Promise<unknown>)
|
|
76
|
+
: Promise.resolve(null),
|
|
77
|
+
buildIndexedRepositoriesContext(params.orgIdString),
|
|
78
|
+
params.workspaceProvider?.listRecentDomainEvents?.(params.orgRef, 5) ??
|
|
79
|
+
Promise.resolve([] as Array<Record<string, unknown>>),
|
|
80
|
+
params.workspaceProvider?.buildPromptSummary
|
|
81
|
+
? params.workspaceProvider.buildPromptSummary(params.orgRef).catch(() => undefined)
|
|
82
|
+
: Promise.resolve(undefined),
|
|
83
|
+
])
|
|
84
|
+
params.onStep?.('parallel-context-fetch(plugins+repos+events+summary)')
|
|
85
|
+
|
|
86
|
+
let linearInstalled = Boolean(linearInstallation)
|
|
87
|
+
let githubInstalled = Boolean(githubInstallation)
|
|
88
|
+
let promptContext = buildAgentPromptContext({
|
|
89
|
+
workspaceName:
|
|
90
|
+
workspaceProfileState?.workspaceName ?? readOptionalString((workspace as { name?: unknown }).name) ?? undefined,
|
|
91
|
+
summaryBlock: workspaceProfileState?.summaryBlock,
|
|
92
|
+
promptSummary,
|
|
93
|
+
userName: params.userName ?? undefined,
|
|
94
|
+
recentDomainEvents,
|
|
95
|
+
})
|
|
96
|
+
let retrievedKnowledgeSection: string | undefined =
|
|
97
|
+
onboardingActive || !params.messageText
|
|
98
|
+
? undefined
|
|
99
|
+
: await params.workspaceProvider?.buildRetrievedKnowledgeSection?.({
|
|
100
|
+
workspaceId: params.orgIdString,
|
|
101
|
+
userId: params.userIdString,
|
|
102
|
+
query: params.messageText,
|
|
103
|
+
})
|
|
104
|
+
params.onStep?.('rag-knowledge-retrieval')
|
|
105
|
+
|
|
106
|
+
const buildContextResult = asRecord(
|
|
107
|
+
await params.turnHooks.buildContext?.({
|
|
108
|
+
workstream: params.workstream,
|
|
109
|
+
workstreamRef: params.workstreamRef,
|
|
110
|
+
orgRef: params.orgRef,
|
|
111
|
+
userRef: params.userRef,
|
|
112
|
+
userName: params.userName,
|
|
113
|
+
workspace,
|
|
114
|
+
onboardingActive,
|
|
115
|
+
messageText: params.messageText,
|
|
116
|
+
linearInstalled,
|
|
117
|
+
githubInstalled,
|
|
118
|
+
indexedRepoContext,
|
|
119
|
+
promptContext,
|
|
120
|
+
workspaceLifecycleState,
|
|
121
|
+
workspaceProfileState,
|
|
122
|
+
promptSummary,
|
|
123
|
+
recentDomainEvents,
|
|
124
|
+
retrievedKnowledgeSection,
|
|
125
|
+
}),
|
|
126
|
+
)
|
|
127
|
+
params.onStep?.('hook:buildContext')
|
|
128
|
+
|
|
129
|
+
const buildContextPromptDetails = readOptionalString(buildContextResult?.systemWorkspaceDetails)
|
|
130
|
+
if (buildContextPromptDetails) {
|
|
131
|
+
promptContext = { systemWorkspaceDetails: buildContextPromptDetails }
|
|
132
|
+
}
|
|
133
|
+
const buildContextRetrievedKnowledge = readOptionalString(buildContextResult?.retrievedKnowledgeSection)
|
|
134
|
+
if (buildContextRetrievedKnowledge !== undefined) {
|
|
135
|
+
retrievedKnowledgeSection = buildContextRetrievedKnowledge
|
|
136
|
+
}
|
|
137
|
+
const buildContextLinearInstalled = readOptionalBoolean(buildContextResult?.linearInstalled)
|
|
138
|
+
if (buildContextLinearInstalled !== undefined) {
|
|
139
|
+
linearInstalled = buildContextLinearInstalled
|
|
140
|
+
}
|
|
141
|
+
const buildContextGithubInstalled = readOptionalBoolean(buildContextResult?.githubInstalled)
|
|
142
|
+
if (buildContextGithubInstalled !== undefined) {
|
|
143
|
+
githubInstalled = buildContextGithubInstalled
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const hookInstructionSections = readInstructionSections(
|
|
147
|
+
await params.turnHooks.buildExtraInstructionSections?.({
|
|
148
|
+
workstream: params.workstream,
|
|
149
|
+
workstreamRef: params.workstreamRef,
|
|
150
|
+
orgRef: params.orgRef,
|
|
151
|
+
userRef: params.userRef,
|
|
152
|
+
userName: params.userName,
|
|
153
|
+
workspace,
|
|
154
|
+
onboardingActive,
|
|
155
|
+
messageText: params.messageText,
|
|
156
|
+
linearInstalled,
|
|
157
|
+
githubInstalled,
|
|
158
|
+
indexedRepoContext,
|
|
159
|
+
promptContext,
|
|
160
|
+
workspaceLifecycleState,
|
|
161
|
+
workspaceProfileState,
|
|
162
|
+
promptSummary,
|
|
163
|
+
recentDomainEvents,
|
|
164
|
+
retrievedKnowledgeSection,
|
|
165
|
+
context: buildContextResult,
|
|
166
|
+
}),
|
|
167
|
+
)
|
|
168
|
+
params.onStep?.('hook:buildExtraInstructionSections')
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
workspace,
|
|
172
|
+
workspaceLifecycleState,
|
|
173
|
+
workspaceProfileState,
|
|
174
|
+
onboardingActive,
|
|
175
|
+
linearInstalled,
|
|
176
|
+
githubInstalled,
|
|
177
|
+
indexedRepoContext,
|
|
178
|
+
promptContext,
|
|
179
|
+
retrievedKnowledgeSection,
|
|
180
|
+
buildContextResult,
|
|
181
|
+
hookInstructionSections,
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -31,6 +31,7 @@ import { databaseService } from '../db/service'
|
|
|
31
31
|
import { TABLES } from '../db/tables'
|
|
32
32
|
import type { AutonomousJobQueuePayload } from '../queues/autonomous-job.queue'
|
|
33
33
|
import { extractMessageText } from '../runtime/workstream-chat-helpers'
|
|
34
|
+
import { buildAutonomousAtJobId, encodeBullmqId } from '../utils/autonomous-job-ids'
|
|
34
35
|
import { toIsoDateTimeString, toOptionalIsoDateTimeString } from '../utils/date-time'
|
|
35
36
|
import { compactRecord, compactWhitespace, stringifyUnknown, truncateText } from '../utils/string'
|
|
36
37
|
import { executionPlanService } from './execution-plan.service'
|
|
@@ -41,14 +42,6 @@ import { workstreamService } from './workstream.service'
|
|
|
41
42
|
|
|
42
43
|
const AUTONOMOUS_JOB_QUEUE_NAME = 'autonomous-job'
|
|
43
44
|
|
|
44
|
-
function encodeBullmqId(raw: string): string {
|
|
45
|
-
return Buffer.from(raw).toString('base64url')
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function buildAutonomousAtJobId(autonomousJobId: string): string {
|
|
49
|
-
return `autonomous-at-${encodeBullmqId(autonomousJobId)}`
|
|
50
|
-
}
|
|
51
|
-
|
|
52
45
|
function buildAutonomousManualJobId(autonomousJobId: string): string {
|
|
53
46
|
return `autonomous-manual-${encodeBullmqId(autonomousJobId)}-${Date.now()}`
|
|
54
47
|
}
|