@lota-sdk/core 0.1.8 → 0.1.11
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_workstream.surql +2 -1
- package/infrastructure/schema/02_execution_plan.surql +202 -52
- package/package.json +4 -2
- package/src/bifrost/bifrost.ts +94 -25
- package/src/config/model-constants.ts +8 -6
- package/src/db/memory-store.ts +3 -71
- package/src/db/service.ts +42 -2
- package/src/db/tables.ts +9 -2
- package/src/embeddings/provider.ts +92 -21
- package/src/index.ts +6 -0
- package/src/redis/stream-context.ts +44 -0
- package/src/runtime/approval-continuation.ts +59 -0
- package/src/runtime/chat-request-routing.ts +5 -1
- package/src/runtime/execution-plan.ts +21 -14
- package/src/runtime/turn-lifecycle.ts +14 -6
- package/src/runtime/workstream-chat-helpers.ts +5 -5
- package/src/services/context-compaction.service.ts +6 -2
- package/src/services/document-chunk.service.ts +2 -2
- package/src/services/execution-plan.service.ts +579 -786
- package/src/services/learned-skill.service.ts +2 -2
- package/src/services/plan-approval.service.ts +83 -0
- package/src/services/plan-artifact.service.ts +45 -0
- package/src/services/plan-builder.service.ts +61 -0
- package/src/services/plan-checkpoint.service.ts +53 -0
- package/src/services/plan-compiler.service.ts +81 -0
- package/src/services/plan-executor.service.ts +1623 -0
- package/src/services/plan-run.service.ts +422 -0
- package/src/services/plan-validator.service.ts +760 -0
- package/src/services/workstream-turn-preparation.ts +70 -196
- package/src/services/workstream-turn.ts +12 -0
- package/src/services/workstream.service.ts +24 -182
- package/src/services/workstream.types.ts +2 -65
- package/src/system-agents/title-generator.agent.ts +2 -2
- package/src/tools/execution-plan.tool.ts +20 -46
- package/src/tools/log-hello-world.tool.ts +17 -0
- package/src/workers/skill-extraction.runner.ts +2 -2
- package/src/services/workstream-change-tracker.service.ts +0 -313
- package/src/system-agents/workstream-tracker.agent.ts +0 -58
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
|
|
3
|
-
import { aiLogger } from '../config/logger'
|
|
4
|
-
import type { RecordIdRef } from '../db/record-id'
|
|
5
|
-
import { mergeStateDelta } from '../runtime/context-compaction'
|
|
6
|
-
import { createHelperModelRuntime, extractJsonObjectCandidates } from '../runtime/helper-model'
|
|
7
|
-
import { toOptionalTrimmedString } from '../runtime/workstream-chat-helpers'
|
|
8
|
-
import {
|
|
9
|
-
StructuredWorkstreamStateDeltaSchema,
|
|
10
|
-
createEmptyStructuredWorkstreamStateDelta,
|
|
11
|
-
createEmptyWorkstreamState,
|
|
12
|
-
parseStructuredWorkstreamStateDelta,
|
|
13
|
-
} from '../runtime/workstream-state'
|
|
14
|
-
import type { WorkstreamState, WorkstreamStateDelta } from '../runtime/workstream-state'
|
|
15
|
-
import { createWorkstreamTrackerAgent } from '../system-agents/workstream-tracker.agent'
|
|
16
|
-
import { compactWhitespace, isRecord, truncateText } from '../utils/string'
|
|
17
|
-
import { workstreamService } from './workstream.service'
|
|
18
|
-
|
|
19
|
-
const helperModelRuntime = createHelperModelRuntime()
|
|
20
|
-
|
|
21
|
-
const TrackerOutputSchema = z.object({
|
|
22
|
-
summary: z.string().trim().min(1).max(1_200),
|
|
23
|
-
stateDelta: StructuredWorkstreamStateDeltaSchema,
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
type TrackerMessage = { label: string; text: string }
|
|
27
|
-
|
|
28
|
-
const TRACKER_JSON_WRAPPER_KEYS = ['output', 'result', 'data'] as const
|
|
29
|
-
const TRACKER_SUMMARY_KEYS = ['summary', 'chatSummary', 'summaryText', 'sidebarSummary', 'message'] as const
|
|
30
|
-
const TRACKER_STATE_DELTA_KEYS = ['stateDelta', 'delta', 'workstreamStateDelta', 'trackerStateDelta', 'state'] as const
|
|
31
|
-
const TRACKER_FALLBACK_SECTION_PREFIX =
|
|
32
|
-
/^(?:#{1,6}\s*)?(?:\*\*)?(?:state delta|current plan|new decisions|resolved questions|new questions|new constraints|new risks|task updates|artifacts|agent note|conflicts|approved by|approved at|approval message id|approval note)(?:\*\*)?\s*:?\s*/i
|
|
33
|
-
|
|
34
|
-
function renderMessages(messages: TrackerMessage[]): string {
|
|
35
|
-
if (messages.length === 0) return '- None'
|
|
36
|
-
return messages
|
|
37
|
-
.map((message, index) => `### Message ${index + 1}\n- Actor: ${message.label}\n- Content: ${message.text}`)
|
|
38
|
-
.join('\n\n')
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function getRecordStringField(record: Record<string, unknown>, keys: readonly string[]): string | null {
|
|
42
|
-
for (const key of keys) {
|
|
43
|
-
const field = toOptionalTrimmedString(typeof record[key] === 'string' ? record[key] : null)
|
|
44
|
-
if (field) return field
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return null
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function getTrackerJsonObjects(value: unknown): Record<string, unknown>[] {
|
|
51
|
-
if (!isRecord(value)) return []
|
|
52
|
-
|
|
53
|
-
const candidates: Record<string, unknown>[] = [value]
|
|
54
|
-
for (const key of TRACKER_JSON_WRAPPER_KEYS) {
|
|
55
|
-
const nested = value[key]
|
|
56
|
-
if (isRecord(nested)) {
|
|
57
|
-
candidates.push(nested)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return candidates
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function parseTrackerJsonFallback(text: string): z.infer<typeof TrackerOutputSchema> | null {
|
|
65
|
-
for (const candidateText of extractJsonObjectCandidates(text)) {
|
|
66
|
-
let parsedJson: unknown
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
parsedJson = JSON.parse(candidateText) as unknown
|
|
70
|
-
} catch {
|
|
71
|
-
continue
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
for (const candidate of getTrackerJsonObjects(parsedJson)) {
|
|
75
|
-
const summary = getRecordStringField(candidate, TRACKER_SUMMARY_KEYS)
|
|
76
|
-
if (!summary) continue
|
|
77
|
-
|
|
78
|
-
const stateDeltaValue = TRACKER_STATE_DELTA_KEYS.map((key) => candidate[key]).find((value) => value !== undefined)
|
|
79
|
-
const parsedStateDelta = StructuredWorkstreamStateDeltaSchema.safeParse(stateDeltaValue)
|
|
80
|
-
|
|
81
|
-
return {
|
|
82
|
-
summary: truncateText(summary, 1_200),
|
|
83
|
-
stateDelta: parsedStateDelta.success ? parsedStateDelta.data : createEmptyStructuredWorkstreamStateDelta(),
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return null
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function extractTrackerFallbackSummary(text: string): string | null {
|
|
92
|
-
const normalized = text.replace(/\r/g, '').trim()
|
|
93
|
-
if (!normalized) return null
|
|
94
|
-
|
|
95
|
-
const summaryLineMatch = normalized.match(/(?:^|\n)(?:#{1,6}\s*)?(?:\*\*)?summary(?:\*\*)?\s*:?\s*(.+?)(?=\n|$)/i)
|
|
96
|
-
const summaryLine = summaryLineMatch?.[1]?.trim()
|
|
97
|
-
if (summaryLine && !summaryLine.startsWith('{') && !summaryLine.startsWith('```')) {
|
|
98
|
-
return truncateText(summaryLine, 1_200)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const summarySectionMatch = normalized.match(
|
|
102
|
-
/(?:^|\n)(?:#{1,6}\s*)?(?:\*\*)?summary(?:\*\*)?\s*:?\s*\n([\s\S]*?)(?=\n(?:#{1,6}\s*)?(?:\*\*)?(?:state delta|summary)(?:\*\*)?\s*:?\s*\n|$)/i,
|
|
103
|
-
)
|
|
104
|
-
const summarySource = summarySectionMatch?.[1]?.trim() || normalized
|
|
105
|
-
const paragraphs = summarySource
|
|
106
|
-
.split(/\n\s*\n/)
|
|
107
|
-
.map((paragraph) => paragraph.trim())
|
|
108
|
-
.filter((paragraph) => paragraph.length > 0)
|
|
109
|
-
|
|
110
|
-
for (const paragraph of paragraphs) {
|
|
111
|
-
const candidate = paragraph.replace(/^(?:#{1,6}\s*)?(?:\*\*)?summary(?:\*\*)?\s*:?\s*/i, '').trim()
|
|
112
|
-
if (
|
|
113
|
-
!candidate ||
|
|
114
|
-
candidate.startsWith('{') ||
|
|
115
|
-
candidate.startsWith('```') ||
|
|
116
|
-
TRACKER_FALLBACK_SECTION_PREFIX.test(candidate)
|
|
117
|
-
) {
|
|
118
|
-
continue
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return truncateText(candidate, 1_200)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return null
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function parseTrackerTextFallback(text: string): z.infer<typeof TrackerOutputSchema> | null {
|
|
128
|
-
const jsonFallback = parseTrackerJsonFallback(text)
|
|
129
|
-
if (jsonFallback) {
|
|
130
|
-
return jsonFallback
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const summary = extractTrackerFallbackSummary(text)
|
|
134
|
-
if (!summary) return null
|
|
135
|
-
|
|
136
|
-
return { summary, stateDelta: createEmptyStructuredWorkstreamStateDelta() }
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function extractHeuristicSummaryCandidate(text: string | null | undefined): string | null {
|
|
140
|
-
const normalized = compactWhitespace(toOptionalTrimmedString(text) ?? '')
|
|
141
|
-
if (!normalized) return null
|
|
142
|
-
|
|
143
|
-
const match = /^(.+?[.!?])(?:\s|$)/.exec(normalized)
|
|
144
|
-
const candidate = match ? String(match[1]) : normalized
|
|
145
|
-
return truncateText(candidate, 1_200)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export function buildHeuristicTrackerSummary(params: {
|
|
149
|
-
previousSummary: string | null
|
|
150
|
-
userMessageText: string | null
|
|
151
|
-
assistantMessages: TrackerMessage[]
|
|
152
|
-
}): string | null {
|
|
153
|
-
for (const message of params.assistantMessages) {
|
|
154
|
-
const summary = extractHeuristicSummaryCandidate(message.text)
|
|
155
|
-
if (summary) {
|
|
156
|
-
return summary
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const userSummary = extractHeuristicSummaryCandidate(params.userMessageText)
|
|
161
|
-
if (userSummary) {
|
|
162
|
-
return truncateText(`User request: ${userSummary}`, 1_200)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return extractHeuristicSummaryCandidate(params.previousSummary)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function formatTrackerPrompt(params: {
|
|
169
|
-
title: string
|
|
170
|
-
mode: 'direct' | 'group'
|
|
171
|
-
coreType?: string
|
|
172
|
-
visibleAgentId?: string
|
|
173
|
-
hasActiveExecutionPlan: boolean
|
|
174
|
-
previousSummary: string | null
|
|
175
|
-
existingState: WorkstreamState
|
|
176
|
-
userMessageText: string | null
|
|
177
|
-
assistantMessages: TrackerMessage[]
|
|
178
|
-
}): string {
|
|
179
|
-
return [
|
|
180
|
-
'# Workstream Turn',
|
|
181
|
-
'',
|
|
182
|
-
`- Title: ${params.title}`,
|
|
183
|
-
`- Mode: ${params.mode}`,
|
|
184
|
-
`- Visible agent: ${params.visibleAgentId ?? 'none'}`,
|
|
185
|
-
`- Active execution plan: ${params.hasActiveExecutionPlan ? 'yes' : 'no'}`,
|
|
186
|
-
...(params.coreType ? [`- Core type: ${params.coreType}`] : []),
|
|
187
|
-
'',
|
|
188
|
-
'## Previous Summary',
|
|
189
|
-
params.previousSummary ?? 'None',
|
|
190
|
-
'',
|
|
191
|
-
'## Existing State',
|
|
192
|
-
JSON.stringify(params.existingState),
|
|
193
|
-
'',
|
|
194
|
-
'## User Message',
|
|
195
|
-
params.userMessageText ?? 'None',
|
|
196
|
-
'',
|
|
197
|
-
'## Assistant Messages',
|
|
198
|
-
renderMessages(params.assistantMessages),
|
|
199
|
-
...(params.hasActiveExecutionPlan
|
|
200
|
-
? [
|
|
201
|
-
'',
|
|
202
|
-
'## Tracker Constraint',
|
|
203
|
-
'An active execution plan exists. Do not update currentPlan or taskUpdates. Track only decisions, questions, risks, artifacts, approvals, and agent notes.',
|
|
204
|
-
]
|
|
205
|
-
: []),
|
|
206
|
-
].join('\n')
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export function applyTrackedStateDelta(params: {
|
|
210
|
-
existingState: WorkstreamState
|
|
211
|
-
delta: WorkstreamStateDelta
|
|
212
|
-
hasActiveExecutionPlan: boolean
|
|
213
|
-
now: () => number
|
|
214
|
-
}): WorkstreamState {
|
|
215
|
-
const mergedState = mergeStateDelta(params.existingState, params.delta, params.now)
|
|
216
|
-
if (!params.hasActiveExecutionPlan) {
|
|
217
|
-
return mergedState
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return { ...mergedState, currentPlan: null, tasks: [] }
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export async function updateWorkstreamChangeTracker(params: {
|
|
224
|
-
workstreamId: RecordIdRef
|
|
225
|
-
title: string
|
|
226
|
-
mode: 'direct' | 'group'
|
|
227
|
-
coreType?: string
|
|
228
|
-
visibleAgentId?: string
|
|
229
|
-
hasActiveExecutionPlan: boolean
|
|
230
|
-
previousSummary: string | null
|
|
231
|
-
existingState: WorkstreamState | null
|
|
232
|
-
userMessageText: string | null
|
|
233
|
-
assistantMessages: TrackerMessage[]
|
|
234
|
-
}): Promise<boolean> {
|
|
235
|
-
const assistantMessages = params.assistantMessages
|
|
236
|
-
.map((message) => ({
|
|
237
|
-
label: toOptionalTrimmedString(message.label) ?? 'Assistant',
|
|
238
|
-
text: truncateText(message.text.trim(), 2_400),
|
|
239
|
-
}))
|
|
240
|
-
.filter((message) => message.text.length > 0)
|
|
241
|
-
.slice(0, 6)
|
|
242
|
-
|
|
243
|
-
if (!toOptionalTrimmedString(params.userMessageText) && assistantMessages.length === 0) {
|
|
244
|
-
return false
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const existingState = params.existingState ?? createEmptyWorkstreamState()
|
|
248
|
-
|
|
249
|
-
try {
|
|
250
|
-
const output = await helperModelRuntime.generateHelperStructured({
|
|
251
|
-
tag: 'workstream-change-tracker',
|
|
252
|
-
createAgent: createWorkstreamTrackerAgent,
|
|
253
|
-
schema: TrackerOutputSchema,
|
|
254
|
-
maxOutputTokens: 1_400,
|
|
255
|
-
textFallbackParser: parseTrackerTextFallback,
|
|
256
|
-
messages: [
|
|
257
|
-
{
|
|
258
|
-
role: 'user',
|
|
259
|
-
content: formatTrackerPrompt({
|
|
260
|
-
title: params.title,
|
|
261
|
-
mode: params.mode,
|
|
262
|
-
...(params.coreType ? { coreType: params.coreType } : {}),
|
|
263
|
-
...(params.visibleAgentId ? { visibleAgentId: params.visibleAgentId } : {}),
|
|
264
|
-
hasActiveExecutionPlan: params.hasActiveExecutionPlan,
|
|
265
|
-
previousSummary: params.previousSummary,
|
|
266
|
-
existingState,
|
|
267
|
-
userMessageText: toOptionalTrimmedString(params.userMessageText),
|
|
268
|
-
assistantMessages,
|
|
269
|
-
}),
|
|
270
|
-
},
|
|
271
|
-
],
|
|
272
|
-
})
|
|
273
|
-
|
|
274
|
-
const sparseStateDelta = parseStructuredWorkstreamStateDelta(output.stateDelta)
|
|
275
|
-
const nextState = applyTrackedStateDelta({
|
|
276
|
-
existingState,
|
|
277
|
-
delta: sparseStateDelta,
|
|
278
|
-
hasActiveExecutionPlan: params.hasActiveExecutionPlan,
|
|
279
|
-
now: () => Date.now(),
|
|
280
|
-
})
|
|
281
|
-
await workstreamService.persistChangeTracker(params.workstreamId, { chatSummary: output.summary, state: nextState })
|
|
282
|
-
return true
|
|
283
|
-
} catch (error) {
|
|
284
|
-
const fallbackSummary = buildHeuristicTrackerSummary({
|
|
285
|
-
previousSummary: params.previousSummary,
|
|
286
|
-
userMessageText: toOptionalTrimmedString(params.userMessageText),
|
|
287
|
-
assistantMessages,
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
if (!fallbackSummary) {
|
|
291
|
-
aiLogger.warn`Workstream change tracker update failed: ${error}`
|
|
292
|
-
return false
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
try {
|
|
296
|
-
const nextState = applyTrackedStateDelta({
|
|
297
|
-
existingState,
|
|
298
|
-
delta: {},
|
|
299
|
-
hasActiveExecutionPlan: params.hasActiveExecutionPlan,
|
|
300
|
-
now: () => Date.now(),
|
|
301
|
-
})
|
|
302
|
-
await workstreamService.persistChangeTracker(params.workstreamId, {
|
|
303
|
-
chatSummary: fallbackSummary,
|
|
304
|
-
state: nextState,
|
|
305
|
-
})
|
|
306
|
-
aiLogger.info`Workstream change tracker used heuristic fallback after helper failure`
|
|
307
|
-
return true
|
|
308
|
-
} catch (persistError) {
|
|
309
|
-
aiLogger.warn`Workstream change tracker update failed: ${error}; fallback_persist=${persistError}`
|
|
310
|
-
return false
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { ToolLoopAgent } from 'ai'
|
|
2
|
-
|
|
3
|
-
import { bifrostOpenRouterResponseHealingModel } from '../bifrost/bifrost'
|
|
4
|
-
import {
|
|
5
|
-
OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS,
|
|
6
|
-
OPENROUTER_STRUCTURED_REASONING_MODEL_ID,
|
|
7
|
-
} from '../config/model-constants'
|
|
8
|
-
import type { CreateHelperToolLoopAgentOptions } from '../runtime/agent-types'
|
|
9
|
-
import { resolveHelperAgentOptions } from './helper-agent-options'
|
|
10
|
-
|
|
11
|
-
const WORKSTREAM_TRACKER_PROMPT = `<agent-instructions>
|
|
12
|
-
You are the **Workstream Tracker**.
|
|
13
|
-
|
|
14
|
-
<task>
|
|
15
|
-
Convert one completed workstream turn into:
|
|
16
|
-
- a concise change-tracker summary for the right sidebar
|
|
17
|
-
- a structured workstream state delta containing only the updates implied by this turn
|
|
18
|
-
</task>
|
|
19
|
-
|
|
20
|
-
<rules>
|
|
21
|
-
- Use only the provided turn evidence and prior state.
|
|
22
|
-
- Keep the summary short, concrete, and focused on what changed or what is blocked now.
|
|
23
|
-
- Prefer durable tracker items over prose: tasks, decisions, questions, risks, artifacts, and agent notes.
|
|
24
|
-
- Do not duplicate existing state unless this turn meaningfully changed it.
|
|
25
|
-
- Never invent analytics, repository facts, customer signals, or business decisions that were not stated.
|
|
26
|
-
</rules>
|
|
27
|
-
|
|
28
|
-
<state-guidance>
|
|
29
|
-
- Use taskUpdates for concrete next steps, ongoing work, completed work, or blocked work.
|
|
30
|
-
- When the turn includes concrete tool work or operational execution, capture that work as taskUpdates even if it was
|
|
31
|
-
completed in the same turn.
|
|
32
|
-
- For website inspection or plugin refresh flows, prefer task titles that describe the executed step clearly, such as
|
|
33
|
-
refreshing website intelligence, overwriting artifacts, or reviewing evidence gaps.
|
|
34
|
-
- If an owner is not explicit, default the task owner to the visible lead agent for the workstream.
|
|
35
|
-
- Use newDecisions only when a clear decision or tradeoff was made.
|
|
36
|
-
- Use newQuestions only for unresolved questions that matter for progress.
|
|
37
|
-
- Use newRisks only for concrete execution or business risks surfaced in this turn.
|
|
38
|
-
- Use agentNote for the main contribution from the lead agent when it is worth retaining.
|
|
39
|
-
- Keep the delta compact. A noisy tracker is worse than a sparse tracker.
|
|
40
|
-
</state-guidance>
|
|
41
|
-
|
|
42
|
-
<output>
|
|
43
|
-
The caller enforces a structured schema.
|
|
44
|
-
- Return every stateDelta field.
|
|
45
|
-
- Use empty arrays for unchanged list fields.
|
|
46
|
-
- Use null for unchanged nullable fields.
|
|
47
|
-
- For currentPlan, use \`{"action":"unchanged","text":null}\` when nothing changed, \`{"action":"clear","text":null}\` to clear it, and \`{"action":"set","text":"..."}\` to replace it.
|
|
48
|
-
</output>
|
|
49
|
-
</agent-instructions>`
|
|
50
|
-
|
|
51
|
-
export function createWorkstreamTrackerAgent(options: CreateHelperToolLoopAgentOptions) {
|
|
52
|
-
return new ToolLoopAgent({
|
|
53
|
-
id: 'workstream-tracker',
|
|
54
|
-
model: bifrostOpenRouterResponseHealingModel(OPENROUTER_STRUCTURED_REASONING_MODEL_ID),
|
|
55
|
-
providerOptions: OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS,
|
|
56
|
-
...resolveHelperAgentOptions(options, { instructions: WORKSTREAM_TRACKER_PROMPT }),
|
|
57
|
-
})
|
|
58
|
-
}
|