@cuylabs/agent-core 0.8.0 → 0.9.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/dist/{builder-UpOWQMW3.d.ts → builder-BgZ_j4Vs.d.ts} +2 -1
- package/dist/{chunk-RZITT45F.js → chunk-4QFNWPIF.js} +4 -4
- package/dist/{chunk-BFM2YHNM.js → chunk-5ARZJWD2.js} +74 -37
- package/dist/{chunk-KUVSERLJ.js → chunk-DXFBQMXP.js} +5 -2
- package/dist/{chunk-CAA7FHIH.js → chunk-EKR6PKXU.js} +0 -100
- package/dist/{chunk-IVUJDISU.js → chunk-GFTW23FV.js} +5 -14
- package/dist/{chunk-7VKQ4WPB.js → chunk-H3FUYU52.js} +11 -3
- package/dist/chunk-I6PKJ7XQ.js +292 -0
- package/dist/chunk-IYWQOJMQ.js +102 -0
- package/dist/{chunk-4BDA7DQY.js → chunk-J4QDGZIA.js} +19 -3
- package/dist/{chunk-7MUFEN4K.js → chunk-JLXG2SH7.js} +349 -3
- package/dist/{chunk-YSLSEQ6B.js → chunk-MAZ5DY5B.js} +18 -30
- package/dist/{chunk-P6YF7USR.js → chunk-MHKK374K.js} +12 -11
- package/dist/{chunk-VBWWUHWI.js → chunk-OFDKHNCX.js} +4 -1
- package/dist/{chunk-YUUJK53A.js → chunk-RKEW5WXI.js} +1 -1
- package/dist/{chunk-LRHOS4ZN.js → chunk-SPILYYDF.js} +3 -2
- package/dist/{chunk-RFEKJKTO.js → chunk-UDCZ673N.js} +321 -275
- package/dist/{chunk-BDBZ3SLK.js → chunk-UHCJEM2E.js} +39 -2
- package/dist/chunk-WGZAPU6N.js +929 -0
- package/dist/{chunk-N6HWIEEA.js → chunk-WKHDSSXG.js} +140 -23
- package/dist/index-BCqEGzBj.d.ts +251 -0
- package/dist/{index-CWSchSql.d.ts → index-DQuTZ8xL.d.ts} +290 -13
- package/dist/index.d.ts +23 -29
- package/dist/index.js +776 -490
- package/dist/{errors → inference/errors}/index.d.ts +2 -2
- package/dist/{errors → inference/errors}/index.js +1 -1
- package/dist/inference/index.d.ts +10 -9
- package/dist/inference/index.js +34 -8
- package/dist/middleware/index.d.ts +5 -4
- package/dist/middleware/index.js +3 -3
- package/dist/models/index.d.ts +18 -16
- package/dist/models/index.js +47 -11
- package/dist/models/reasoning/index.d.ts +4 -0
- package/dist/{reasoning → models/reasoning}/index.js +2 -3
- package/dist/plugin/index.d.ts +414 -0
- package/dist/plugin/index.js +32 -0
- package/dist/presets/index.d.ts +3 -3
- package/dist/presets/index.js +7 -5
- package/dist/prompt/index.d.ts +6 -5
- package/dist/prompt/index.js +3 -2
- package/dist/runner-CI-XeR16.d.ts +91 -0
- package/dist/runtime/index.d.ts +7 -6
- package/dist/runtime/index.js +6 -7
- package/dist/safety/index.d.ts +1 -1
- package/dist/safety/index.js +1 -1
- package/dist/{session-manager-B_CWGTsl.d.ts → session-manager-KbYt2WUh.d.ts} +8 -0
- package/dist/signal/index.js +1 -1
- package/dist/skill/index.d.ts +2 -2
- package/dist/skill/index.js +3 -3
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.js +1 -1
- package/dist/sub-agent/index.d.ts +10 -9
- package/dist/sub-agent/index.js +21 -4
- package/dist/tool/index.d.ts +19 -5
- package/dist/tool/index.js +2 -2
- package/dist/{tool-BHbyUAy3.d.ts → tool-CZWN3KbO.d.ts} +1 -10
- package/dist/{tool-DLXAR9Ce.d.ts → tool-DkhSCV2Y.d.ts} +1 -1
- package/dist/tracking/index.d.ts +1 -1
- package/dist/tracking/index.js +1 -1
- package/dist/{types-KKDrdU9Y.d.ts → types-BlOKk-Bb.d.ts} +9 -4
- package/dist/{types-BnpEOYV-.d.ts → types-BlZwmnuW.d.ts} +1 -1
- package/dist/{runner-e2YRcUoX.d.ts → types-DTSkxakL.d.ts} +3 -138
- package/dist/{types-QKHHQLLq.d.ts → types-DmDwi2zI.d.ts} +7 -4
- package/package.json +15 -9
- package/dist/chunk-DWYX7ASF.js +0 -26
- package/dist/chunk-SQU2AJHO.js +0 -305
- package/dist/reasoning/index.d.ts +0 -116
- package/dist/types-QA4WhEfz.d.ts +0 -138
package/dist/index.js
CHANGED
|
@@ -1,35 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FileStorage,
|
|
3
|
-
MemoryStorage,
|
|
4
|
-
STORAGE_VERSION,
|
|
5
|
-
SessionManager,
|
|
6
|
-
buildEntryPath,
|
|
7
|
-
buildMessagesFromEntries,
|
|
8
|
-
configureDefaultSessionManager,
|
|
9
|
-
createMessageEntry,
|
|
10
|
-
createMetadataEntry,
|
|
11
|
-
deserializeMessage,
|
|
12
|
-
extractSessionInfo,
|
|
13
|
-
generateEntryId,
|
|
14
|
-
getDataDir,
|
|
15
|
-
getDefaultSessionManager,
|
|
16
|
-
getGitRootHash,
|
|
17
|
-
getLeafId,
|
|
18
|
-
getProjectId,
|
|
19
|
-
getProjectSessionsDir,
|
|
20
|
-
getSessionsDir,
|
|
21
|
-
parseJSONL,
|
|
22
|
-
serializeMessage,
|
|
23
|
-
toJSONL,
|
|
24
|
-
toJSONLBatch
|
|
25
|
-
} from "./chunk-BDBZ3SLK.js";
|
|
26
1
|
import {
|
|
27
2
|
DEFAULT_MAX_CONCURRENT,
|
|
28
3
|
DEFAULT_MAX_SPAWN_DEPTH,
|
|
29
4
|
DEFAULT_SESSION_TITLE_PREFIX,
|
|
30
5
|
SubAgentTracker,
|
|
31
|
-
createSubAgentTools
|
|
32
|
-
|
|
6
|
+
createSubAgentTools,
|
|
7
|
+
discoverAgentProfiles,
|
|
8
|
+
getProjectAgentsDir,
|
|
9
|
+
getUserAgentsDir,
|
|
10
|
+
isMarkdownProfile,
|
|
11
|
+
parseAgentFrontmatter,
|
|
12
|
+
parseMarkdownAgent,
|
|
13
|
+
parseToolSpec,
|
|
14
|
+
toAgentProfile
|
|
15
|
+
} from "./chunk-JLXG2SH7.js";
|
|
33
16
|
import {
|
|
34
17
|
ToolRegistry,
|
|
35
18
|
defaultRegistry
|
|
@@ -39,21 +22,23 @@ import {
|
|
|
39
22
|
clearCheckpoints,
|
|
40
23
|
createCheckpointManager,
|
|
41
24
|
createTurnTracker
|
|
42
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-OFDKHNCX.js";
|
|
43
26
|
import {
|
|
44
|
-
Presets,
|
|
45
27
|
applyPreset,
|
|
28
|
+
createPreset,
|
|
29
|
+
filterTools,
|
|
30
|
+
mergePresets
|
|
31
|
+
} from "./chunk-IYWQOJMQ.js";
|
|
32
|
+
import {
|
|
33
|
+
Presets,
|
|
46
34
|
careful,
|
|
47
35
|
code,
|
|
48
|
-
createPreset,
|
|
49
36
|
explore,
|
|
50
|
-
filterTools,
|
|
51
|
-
mergePresets,
|
|
52
37
|
plan,
|
|
53
38
|
quick,
|
|
54
39
|
review,
|
|
55
40
|
watch
|
|
56
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-EKR6PKXU.js";
|
|
57
42
|
import {
|
|
58
43
|
DEFAULT_INSTRUCTION_PATTERNS,
|
|
59
44
|
DEFAULT_MAX_DEPTH,
|
|
@@ -75,7 +60,7 @@ import {
|
|
|
75
60
|
getTemplate,
|
|
76
61
|
loadGlobalInstructions,
|
|
77
62
|
summarizeEnvironment
|
|
78
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-GFTW23FV.js";
|
|
79
64
|
import {
|
|
80
65
|
AgentTurnEngine,
|
|
81
66
|
ContextOverflowError,
|
|
@@ -108,15 +93,15 @@ import {
|
|
|
108
93
|
runToolBatch,
|
|
109
94
|
snapshotAgentWorkflowMessage,
|
|
110
95
|
snapshotAgentWorkflowMessages
|
|
111
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-J4QDGZIA.js";
|
|
112
97
|
import {
|
|
113
98
|
LocalSignal
|
|
114
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-DXFBQMXP.js";
|
|
115
100
|
import {
|
|
116
101
|
createSkillResourceTool,
|
|
117
102
|
createSkillTool,
|
|
118
103
|
createSkillTools
|
|
119
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-RKEW5WXI.js";
|
|
120
105
|
import {
|
|
121
106
|
MAX_BYTES,
|
|
122
107
|
MAX_LINES,
|
|
@@ -127,7 +112,7 @@ import {
|
|
|
127
112
|
formatSize,
|
|
128
113
|
normalizeToolReplayPolicy,
|
|
129
114
|
truncateOutput
|
|
130
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-MHKK374K.js";
|
|
131
116
|
import {
|
|
132
117
|
DEFAULT_EXTERNAL_DIRS,
|
|
133
118
|
DEFAULT_MAX_SCAN_DEPTH,
|
|
@@ -142,7 +127,32 @@ import {
|
|
|
142
127
|
loadSkillContent,
|
|
143
128
|
loadSkillMetadata,
|
|
144
129
|
parseFrontmatter
|
|
145
|
-
} from "./chunk-
|
|
130
|
+
} from "./chunk-SPILYYDF.js";
|
|
131
|
+
import {
|
|
132
|
+
FileStorage,
|
|
133
|
+
MemoryStorage,
|
|
134
|
+
STORAGE_VERSION,
|
|
135
|
+
SessionManager,
|
|
136
|
+
buildEntryPath,
|
|
137
|
+
buildMessagesFromEntries,
|
|
138
|
+
configureDefaultSessionManager,
|
|
139
|
+
createMessageEntry,
|
|
140
|
+
createMetadataEntry,
|
|
141
|
+
deserializeMessage,
|
|
142
|
+
extractSessionInfo,
|
|
143
|
+
generateEntryId,
|
|
144
|
+
getDataDir,
|
|
145
|
+
getDefaultSessionManager,
|
|
146
|
+
getGitRootHash,
|
|
147
|
+
getLeafId,
|
|
148
|
+
getProjectId,
|
|
149
|
+
getProjectSessionsDir,
|
|
150
|
+
getSessionsDir,
|
|
151
|
+
parseJSONL,
|
|
152
|
+
serializeMessage,
|
|
153
|
+
toJSONL,
|
|
154
|
+
toJSONLBatch
|
|
155
|
+
} from "./chunk-UHCJEM2E.js";
|
|
146
156
|
import {
|
|
147
157
|
ContextManager,
|
|
148
158
|
DEFAULT_CONTEXT_LIMITS,
|
|
@@ -177,35 +187,23 @@ import {
|
|
|
177
187
|
streamOnce,
|
|
178
188
|
streamStep,
|
|
179
189
|
withRetry
|
|
180
|
-
} from "./chunk-
|
|
190
|
+
} from "./chunk-WKHDSSXG.js";
|
|
181
191
|
import {
|
|
182
192
|
executeAgentToolCall
|
|
183
|
-
} from "./chunk-
|
|
193
|
+
} from "./chunk-H3FUYU52.js";
|
|
184
194
|
import {
|
|
185
195
|
extractFilePathsFromArgs,
|
|
186
196
|
shouldCaptureBaseline,
|
|
187
197
|
withFileTracking
|
|
188
198
|
} from "./chunk-VEKUXUVF.js";
|
|
189
199
|
import {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
buildOpenAIOptions,
|
|
198
|
-
buildOpenRouterOptions,
|
|
199
|
-
buildReasoningOptions,
|
|
200
|
-
buildReasoningOptionsSync,
|
|
201
|
-
buildXAIOptions,
|
|
202
|
-
getProviderOptionsKey,
|
|
203
|
-
getReasoningConfig,
|
|
204
|
-
getReasoningConfigSync,
|
|
205
|
-
shouldIncludeReasoningSummary,
|
|
206
|
-
supportsReasoning,
|
|
207
|
-
supportsReasoningSync
|
|
208
|
-
} from "./chunk-SQU2AJHO.js";
|
|
200
|
+
LLMError,
|
|
201
|
+
getErrorCategory,
|
|
202
|
+
getRetryDelay,
|
|
203
|
+
isRetryable,
|
|
204
|
+
isRetryableCategory,
|
|
205
|
+
parseRetryDelay
|
|
206
|
+
} from "./chunk-4QFNWPIF.js";
|
|
209
207
|
import {
|
|
210
208
|
createScope,
|
|
211
209
|
currentScope,
|
|
@@ -214,14 +212,6 @@ import {
|
|
|
214
212
|
streamWithinScope,
|
|
215
213
|
withinScope
|
|
216
214
|
} from "./chunk-N7P4PN3O.js";
|
|
217
|
-
import {
|
|
218
|
-
LLMError,
|
|
219
|
-
getErrorCategory,
|
|
220
|
-
getRetryDelay,
|
|
221
|
-
isRetryable,
|
|
222
|
-
isRetryableCategory,
|
|
223
|
-
parseRetryDelay
|
|
224
|
-
} from "./chunk-RZITT45F.js";
|
|
225
215
|
import {
|
|
226
216
|
createMCPManager,
|
|
227
217
|
defineServer,
|
|
@@ -235,39 +225,187 @@ import {
|
|
|
235
225
|
createTelemetryConfig,
|
|
236
226
|
otelMiddleware,
|
|
237
227
|
promptCacheMiddleware
|
|
238
|
-
} from "./chunk-
|
|
228
|
+
} from "./chunk-MAZ5DY5B.js";
|
|
239
229
|
import {
|
|
240
230
|
ApprovalDeniedError,
|
|
241
231
|
ApprovalTimeoutError,
|
|
242
232
|
createApprovalHandler,
|
|
243
233
|
getToolRisk
|
|
244
|
-
} from "./chunk-
|
|
234
|
+
} from "./chunk-5ARZJWD2.js";
|
|
245
235
|
import {
|
|
246
236
|
CacheCapabilitySource,
|
|
247
237
|
CapabilityCache,
|
|
248
|
-
|
|
238
|
+
EXTENDED_LEVELS,
|
|
239
|
+
FIXED_LEVELS,
|
|
249
240
|
ModelCapabilityResolver,
|
|
250
|
-
PatternCapabilitySource,
|
|
251
241
|
RemoteCapabilityFetcher,
|
|
252
242
|
RemoteCapabilitySource,
|
|
253
|
-
|
|
243
|
+
STANDARD_LEVELS,
|
|
254
244
|
applyCapabilityOverride,
|
|
245
|
+
buildAnthropicOptions,
|
|
246
|
+
buildBedrockOptions,
|
|
247
|
+
buildGoogleOptions,
|
|
248
|
+
buildGroqOptions,
|
|
249
|
+
buildOpenAIOptions,
|
|
250
|
+
buildOpenRouterOptions,
|
|
251
|
+
buildReasoningOptions,
|
|
252
|
+
buildReasoningOptionsSync,
|
|
253
|
+
buildXAIOptions,
|
|
255
254
|
configureResolver,
|
|
256
255
|
createResolver,
|
|
257
|
-
extractModelId,
|
|
258
|
-
extractProvider,
|
|
259
256
|
findCapabilityOverride,
|
|
260
257
|
getDefaultResolver,
|
|
261
258
|
getNetworkStatus,
|
|
259
|
+
getProviderOptionsKey,
|
|
260
|
+
getReasoningConfig,
|
|
261
|
+
getReasoningConfigSync,
|
|
262
|
+
shouldIncludeReasoningSummary,
|
|
263
|
+
supportsReasoning,
|
|
264
|
+
supportsReasoningSync
|
|
265
|
+
} from "./chunk-UDCZ673N.js";
|
|
266
|
+
import {
|
|
267
|
+
DEFAULT_RESOLVER_OPTIONS,
|
|
268
|
+
PatternCapabilitySource,
|
|
269
|
+
SourcePriority,
|
|
270
|
+
extractModelId,
|
|
271
|
+
extractProvider,
|
|
272
|
+
getModelId,
|
|
262
273
|
getProviderCompatibility,
|
|
274
|
+
getProviderId,
|
|
263
275
|
inferContextWindow,
|
|
264
276
|
inferProvider,
|
|
265
277
|
likelySupportsReasoning
|
|
266
|
-
} from "./chunk-
|
|
278
|
+
} from "./chunk-I6PKJ7XQ.js";
|
|
267
279
|
import {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
280
|
+
LayeredSettings,
|
|
281
|
+
NullSettings,
|
|
282
|
+
PluginEventBus,
|
|
283
|
+
PluginRegistry,
|
|
284
|
+
StaticSettings,
|
|
285
|
+
ValidatedSettings,
|
|
286
|
+
definePlugin,
|
|
287
|
+
discoverPlugins,
|
|
288
|
+
getPluginLoader,
|
|
289
|
+
isDefinedPlugin,
|
|
290
|
+
loadPluginModule,
|
|
291
|
+
resetFrameworkAliases,
|
|
292
|
+
resetPluginLoader,
|
|
293
|
+
resolveFrameworkAliases
|
|
294
|
+
} from "./chunk-WGZAPU6N.js";
|
|
295
|
+
|
|
296
|
+
// src/agent/intervention.ts
|
|
297
|
+
var InterventionController = class {
|
|
298
|
+
/** Immediate interventions — applied at the next step boundary */
|
|
299
|
+
immediate = [];
|
|
300
|
+
/** Deferred messages — held until the turn completes */
|
|
301
|
+
deferred = [];
|
|
302
|
+
/**
|
|
303
|
+
* Callback fired when an intervention is wired into a step.
|
|
304
|
+
* Set by the Agent before starting a chat turn, cleared after.
|
|
305
|
+
*/
|
|
306
|
+
onApplied;
|
|
307
|
+
// ---------------------------------------------------------------------------
|
|
308
|
+
// Immediate interventions (mid-turn redirect)
|
|
309
|
+
// ---------------------------------------------------------------------------
|
|
310
|
+
/**
|
|
311
|
+
* Inject a message at the next LLM step boundary.
|
|
312
|
+
*
|
|
313
|
+
* The message is appended as a user message to the conversation
|
|
314
|
+
* before the next LLM call in the current multi-step turn. The
|
|
315
|
+
* LLM will see it and can adjust its behavior accordingly.
|
|
316
|
+
*
|
|
317
|
+
* Safe to call from any async context while `chat()` is running.
|
|
318
|
+
* If called when no turn is active, the message will be picked up
|
|
319
|
+
* by the first step of the next `chat()` call.
|
|
320
|
+
*
|
|
321
|
+
* @param message - The user message to inject
|
|
322
|
+
* @returns Intervention ID for tracking
|
|
323
|
+
*/
|
|
324
|
+
intervene(message) {
|
|
325
|
+
const id = crypto.randomUUID();
|
|
326
|
+
this.immediate.push(
|
|
327
|
+
Object.freeze({ id, message, createdAt: /* @__PURE__ */ new Date() })
|
|
328
|
+
);
|
|
329
|
+
return id;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Drain and return all pending immediate interventions.
|
|
333
|
+
* The internal queue is cleared atomically.
|
|
334
|
+
*
|
|
335
|
+
* @internal Called by the LLM stream's `prepareStep` hook
|
|
336
|
+
*/
|
|
337
|
+
drainImmediate() {
|
|
338
|
+
if (this.immediate.length === 0) return [];
|
|
339
|
+
return this.immediate.splice(0);
|
|
340
|
+
}
|
|
341
|
+
/** Adopt existing immediate interventions without changing their IDs. */
|
|
342
|
+
adoptImmediate(items) {
|
|
343
|
+
if (items.length === 0) return;
|
|
344
|
+
this.immediate.push(...items);
|
|
345
|
+
}
|
|
346
|
+
/** Whether there are pending immediate interventions */
|
|
347
|
+
get hasPending() {
|
|
348
|
+
return this.immediate.length > 0;
|
|
349
|
+
}
|
|
350
|
+
/** Number of pending immediate interventions */
|
|
351
|
+
get pendingCount() {
|
|
352
|
+
return this.immediate.length;
|
|
353
|
+
}
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// Deferred messages (after-turn follow-ups)
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
/**
|
|
358
|
+
* Queue a message for after the current turn completes.
|
|
359
|
+
*
|
|
360
|
+
* Unlike `intervene()`, this does **not** inject mid-turn. The
|
|
361
|
+
* message is held and available via `drainDeferred()` after
|
|
362
|
+
* `chat()` finishes. The consumer decides whether to send it
|
|
363
|
+
* as a new turn.
|
|
364
|
+
*
|
|
365
|
+
* @param message - The message to queue
|
|
366
|
+
* @returns Intervention ID for tracking
|
|
367
|
+
*/
|
|
368
|
+
queueNext(message) {
|
|
369
|
+
const id = crypto.randomUUID();
|
|
370
|
+
this.deferred.push(
|
|
371
|
+
Object.freeze({ id, message, createdAt: /* @__PURE__ */ new Date() })
|
|
372
|
+
);
|
|
373
|
+
return id;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Drain and return all deferred messages.
|
|
377
|
+
* The internal queue is cleared atomically.
|
|
378
|
+
*/
|
|
379
|
+
drainDeferred() {
|
|
380
|
+
if (this.deferred.length === 0) return [];
|
|
381
|
+
return this.deferred.splice(0);
|
|
382
|
+
}
|
|
383
|
+
/** Adopt existing deferred interventions without changing their IDs. */
|
|
384
|
+
adoptDeferred(items) {
|
|
385
|
+
if (items.length === 0) return;
|
|
386
|
+
this.deferred.push(...items);
|
|
387
|
+
}
|
|
388
|
+
/** Whether there are deferred messages */
|
|
389
|
+
get hasDeferred() {
|
|
390
|
+
return this.deferred.length > 0;
|
|
391
|
+
}
|
|
392
|
+
/** Number of deferred messages */
|
|
393
|
+
get deferredCount() {
|
|
394
|
+
return this.deferred.length;
|
|
395
|
+
}
|
|
396
|
+
// ---------------------------------------------------------------------------
|
|
397
|
+
// Housekeeping
|
|
398
|
+
// ---------------------------------------------------------------------------
|
|
399
|
+
/** Clear all queues (immediate + deferred) */
|
|
400
|
+
clear() {
|
|
401
|
+
this.immediate.length = 0;
|
|
402
|
+
this.deferred.length = 0;
|
|
403
|
+
}
|
|
404
|
+
/** Reset the controller for a new turn (clears onApplied, keeps queues) */
|
|
405
|
+
resetCallbacks() {
|
|
406
|
+
this.onApplied = void 0;
|
|
407
|
+
}
|
|
408
|
+
};
|
|
271
409
|
|
|
272
410
|
// src/agent/chat-loop/commit.ts
|
|
273
411
|
function createChatLoopCommitBatchApplier(params) {
|
|
@@ -288,14 +426,240 @@ function createChatLoopCommitBatchApplier(params) {
|
|
|
288
426
|
};
|
|
289
427
|
}
|
|
290
428
|
|
|
429
|
+
// src/agent/session.ts
|
|
430
|
+
async function ensureSessionLoaded(options) {
|
|
431
|
+
const { sessionId, sessions, cwd } = options;
|
|
432
|
+
if (sessions.getSessionId() === sessionId) {
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const exists = await sessions.sessionExists(sessionId);
|
|
436
|
+
if (exists) {
|
|
437
|
+
await sessions.load(sessionId);
|
|
438
|
+
} else {
|
|
439
|
+
await sessions.create({ id: sessionId, cwd });
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
async function repairOrphanedToolCalls(sessions) {
|
|
443
|
+
const messages = sessions.getMessages();
|
|
444
|
+
const pendingCallIds = /* @__PURE__ */ new Map();
|
|
445
|
+
for (const message of messages) {
|
|
446
|
+
if (message.role === "assistant" && message.toolCalls) {
|
|
447
|
+
for (const toolCall of message.toolCalls) {
|
|
448
|
+
pendingCallIds.set(toolCall.toolCallId, { toolName: toolCall.toolName });
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (message.role === "tool" && message.toolCallId) {
|
|
452
|
+
pendingCallIds.delete(message.toolCallId);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
for (const [toolCallId, { toolName }] of pendingCallIds) {
|
|
456
|
+
const toolMessage = {
|
|
457
|
+
id: crypto.randomUUID(),
|
|
458
|
+
role: "tool",
|
|
459
|
+
content: "Error: tool execution failed (result was not recorded)",
|
|
460
|
+
toolCallId,
|
|
461
|
+
toolName,
|
|
462
|
+
result: "Error: tool execution failed (result was not recorded)",
|
|
463
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
464
|
+
};
|
|
465
|
+
await sessions.addMessage(toolMessage);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
async function createSubAgentRunSession(options) {
|
|
469
|
+
const sessionId = options.parentSessionId ? `${options.parentSessionId}:sub:${crypto.randomUUID().slice(0, 8)}` : `sub:${crypto.randomUUID().slice(0, 8)}`;
|
|
470
|
+
await options.sessions.create({
|
|
471
|
+
id: sessionId,
|
|
472
|
+
cwd: options.cwd,
|
|
473
|
+
title: options.title ?? "Sub-agent task",
|
|
474
|
+
parentSessionId: options.parentSessionId
|
|
475
|
+
});
|
|
476
|
+
return sessionId;
|
|
477
|
+
}
|
|
478
|
+
function getVisibleSessionMessages(sessions) {
|
|
479
|
+
const leafId = sessions.getLeafId();
|
|
480
|
+
if (!leafId) {
|
|
481
|
+
return [];
|
|
482
|
+
}
|
|
483
|
+
const path = buildEntryPath(
|
|
484
|
+
sessions.getEntries(),
|
|
485
|
+
leafId
|
|
486
|
+
);
|
|
487
|
+
const visible = [];
|
|
488
|
+
let skipUntilId;
|
|
489
|
+
for (const entry of path) {
|
|
490
|
+
if (entry.type === "compaction") {
|
|
491
|
+
visible.push({
|
|
492
|
+
message: {
|
|
493
|
+
id: entry.id,
|
|
494
|
+
role: "system",
|
|
495
|
+
content: `## Previous Conversation Summary
|
|
496
|
+
|
|
497
|
+
${entry.summary}`,
|
|
498
|
+
createdAt: new Date(entry.timestamp)
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
skipUntilId = entry.firstKeptEntryId;
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
if (skipUntilId && entry.id !== skipUntilId) {
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
if (entry.id === skipUntilId) {
|
|
508
|
+
skipUntilId = void 0;
|
|
509
|
+
}
|
|
510
|
+
if (entry.type === "message") {
|
|
511
|
+
visible.push({
|
|
512
|
+
message: deserializeMessage(entry.message)
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return visible;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// src/agent/runtime-config.ts
|
|
520
|
+
function createAgentToolRecord(tools) {
|
|
521
|
+
const toolRecord = {};
|
|
522
|
+
for (const [id, tool] of tools) {
|
|
523
|
+
toolRecord[id] = tool;
|
|
524
|
+
}
|
|
525
|
+
return toolRecord;
|
|
526
|
+
}
|
|
527
|
+
function getAgentContextStats(contextManager, messages) {
|
|
528
|
+
return contextManager.getStats(messages);
|
|
529
|
+
}
|
|
530
|
+
function buildFallbackCompactionSummary(messages) {
|
|
531
|
+
const excerpt = messages.map((message) => {
|
|
532
|
+
const role = message.role.toUpperCase();
|
|
533
|
+
const content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
|
|
534
|
+
return `[${role}] ${content}`;
|
|
535
|
+
}).join("\n\n");
|
|
536
|
+
const trimmed = excerpt.length > 8e3 ? `${excerpt.slice(0, 8e3)}
|
|
537
|
+
|
|
538
|
+
...[truncated during compaction]` : excerpt;
|
|
539
|
+
return trimmed.length > 0 ? trimmed : "Earlier conversation context was compacted.";
|
|
540
|
+
}
|
|
541
|
+
async function compactAgentContext(options) {
|
|
542
|
+
const { contextManager, sessions } = options;
|
|
543
|
+
const visibleMessages = getVisibleSessionMessages(sessions);
|
|
544
|
+
const messages = visibleMessages.map((item) => item.message);
|
|
545
|
+
if (!contextManager.shouldPrune(messages)) {
|
|
546
|
+
return {
|
|
547
|
+
removedCount: 0,
|
|
548
|
+
tokensRemoved: 0,
|
|
549
|
+
summarized: false,
|
|
550
|
+
summary: void 0
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
const tokensBefore = estimateConversationTokens(messages);
|
|
554
|
+
let removedCount = 0;
|
|
555
|
+
let summarized = false;
|
|
556
|
+
let summary;
|
|
557
|
+
try {
|
|
558
|
+
const result = await contextManager.prune(messages);
|
|
559
|
+
removedCount = result.removedCount;
|
|
560
|
+
summarized = result.summarized;
|
|
561
|
+
summary = result.summary;
|
|
562
|
+
} catch {
|
|
563
|
+
}
|
|
564
|
+
if (removedCount === 0) {
|
|
565
|
+
removedCount = findCutPoint(
|
|
566
|
+
messages,
|
|
567
|
+
contextManager.getLimits().protectedTokens
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
if (removedCount === 0) {
|
|
571
|
+
return {
|
|
572
|
+
removedCount: 0,
|
|
573
|
+
tokensRemoved: 0,
|
|
574
|
+
summarized: false,
|
|
575
|
+
summary: void 0
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
const summaryText = summary ?? buildFallbackCompactionSummary(messages.slice(0, removedCount));
|
|
579
|
+
const keptMessages = messages.slice(removedCount);
|
|
580
|
+
const persistedMessages = [
|
|
581
|
+
{
|
|
582
|
+
id: "compaction-preview",
|
|
583
|
+
role: "system",
|
|
584
|
+
content: `## Previous Conversation Summary
|
|
585
|
+
|
|
586
|
+
${summaryText}`,
|
|
587
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
588
|
+
},
|
|
589
|
+
...keptMessages
|
|
590
|
+
];
|
|
591
|
+
const tokensAfter = estimateConversationTokens(persistedMessages);
|
|
592
|
+
await sessions.replaceWithCompaction({
|
|
593
|
+
summary: summaryText,
|
|
594
|
+
messages: keptMessages,
|
|
595
|
+
tokensBefore,
|
|
596
|
+
tokensAfter
|
|
597
|
+
});
|
|
598
|
+
return {
|
|
599
|
+
removedCount,
|
|
600
|
+
tokensRemoved: Math.max(0, tokensBefore - tokensAfter),
|
|
601
|
+
summarized,
|
|
602
|
+
summary: summaryText
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
async function buildAgentSystemPrompts(options) {
|
|
606
|
+
const {
|
|
607
|
+
config,
|
|
608
|
+
toolIds,
|
|
609
|
+
sessionId,
|
|
610
|
+
override,
|
|
611
|
+
promptBuilder,
|
|
612
|
+
middlewareRunner
|
|
613
|
+
} = options;
|
|
614
|
+
if (promptBuilder) {
|
|
615
|
+
const composedPrompt = await promptBuilder.build(
|
|
616
|
+
{
|
|
617
|
+
cwd: config.cwd,
|
|
618
|
+
model: config.model,
|
|
619
|
+
toolNames: toolIds,
|
|
620
|
+
...override ? { override } : {},
|
|
621
|
+
sessionId
|
|
622
|
+
},
|
|
623
|
+
middlewareRunner
|
|
624
|
+
);
|
|
625
|
+
return [composedPrompt];
|
|
626
|
+
}
|
|
627
|
+
const prompts = [config.systemPrompt];
|
|
628
|
+
if (override) {
|
|
629
|
+
prompts.push(override);
|
|
630
|
+
}
|
|
631
|
+
return prompts;
|
|
632
|
+
}
|
|
633
|
+
function createAgentTurnRuntimeConfig(options) {
|
|
634
|
+
const { config, telemetrySettings } = options;
|
|
635
|
+
return {
|
|
636
|
+
model: config.model,
|
|
637
|
+
cwd: config.cwd,
|
|
638
|
+
...config.temperature !== void 0 ? { temperature: config.temperature } : {},
|
|
639
|
+
...config.topP !== void 0 ? { topP: config.topP } : {},
|
|
640
|
+
...config.maxOutputTokens !== void 0 ? { maxOutputTokens: config.maxOutputTokens } : {},
|
|
641
|
+
maxSteps: config.maxSteps,
|
|
642
|
+
...config.doomLoopThreshold !== void 0 ? { doomLoopThreshold: config.doomLoopThreshold } : {},
|
|
643
|
+
...config.enforceDoomLoop !== void 0 ? { enforceDoomLoop: config.enforceDoomLoop } : {},
|
|
644
|
+
...config.onDoomLoop ? { onDoomLoop: config.onDoomLoop } : {},
|
|
645
|
+
...config.contextWindow !== void 0 ? { contextWindow: config.contextWindow } : {},
|
|
646
|
+
...config.streamProvider ? { streamProvider: config.streamProvider } : {},
|
|
647
|
+
...telemetrySettings ? { telemetry: telemetrySettings } : {}
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
291
651
|
// src/agent/chat-loop/compaction.ts
|
|
292
652
|
async function runAutoCompaction(params) {
|
|
293
|
-
const { contextManager,
|
|
653
|
+
const { contextManager, sessions } = params;
|
|
654
|
+
const messages = sessions.getMessages();
|
|
294
655
|
if (!contextManager.shouldPrune(messages)) {
|
|
295
656
|
return [];
|
|
296
657
|
}
|
|
297
658
|
const events = [{ type: "status", status: "processing" }];
|
|
298
|
-
const pruneResult = await
|
|
659
|
+
const pruneResult = await compactAgentContext({
|
|
660
|
+
contextManager,
|
|
661
|
+
sessions
|
|
662
|
+
});
|
|
299
663
|
if (pruneResult.removedCount > 0 || pruneResult.summarized) {
|
|
300
664
|
const limits = contextManager.getLimits();
|
|
301
665
|
events.push({
|
|
@@ -309,32 +673,14 @@ async function runAutoCompaction(params) {
|
|
|
309
673
|
|
|
310
674
|
// src/agent/chat-loop/prompts.ts
|
|
311
675
|
async function buildChatSystemPrompts(params) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
if (promptBuilder) {
|
|
321
|
-
const composedPrompt = await promptBuilder.build(
|
|
322
|
-
{
|
|
323
|
-
cwd: config.cwd,
|
|
324
|
-
model: config.model,
|
|
325
|
-
toolNames: Object.keys(tools),
|
|
326
|
-
override: systemOverride,
|
|
327
|
-
sessionId
|
|
328
|
-
},
|
|
329
|
-
middlewareRunner
|
|
330
|
-
);
|
|
331
|
-
return [composedPrompt];
|
|
332
|
-
}
|
|
333
|
-
const prompts = [config.systemPrompt];
|
|
334
|
-
if (systemOverride) {
|
|
335
|
-
prompts.push(systemOverride);
|
|
336
|
-
}
|
|
337
|
-
return prompts;
|
|
676
|
+
return buildAgentSystemPrompts({
|
|
677
|
+
config: params.config,
|
|
678
|
+
toolIds: Object.keys(params.tools),
|
|
679
|
+
sessionId: params.sessionId,
|
|
680
|
+
override: params.systemOverride,
|
|
681
|
+
promptBuilder: params.promptBuilder,
|
|
682
|
+
middlewareRunner: params.middlewareRunner
|
|
683
|
+
});
|
|
338
684
|
}
|
|
339
685
|
|
|
340
686
|
// src/agent/chat-loop/usage.ts
|
|
@@ -483,7 +829,7 @@ async function* runChatLoop(deps) {
|
|
|
483
829
|
if (config.compaction?.auto !== false) {
|
|
484
830
|
const compactionEvents = await runAutoCompaction({
|
|
485
831
|
contextManager,
|
|
486
|
-
|
|
832
|
+
sessions
|
|
487
833
|
});
|
|
488
834
|
for (const event of compactionEvents) {
|
|
489
835
|
yield event;
|
|
@@ -513,6 +859,12 @@ async function* runChatLoop(deps) {
|
|
|
513
859
|
};
|
|
514
860
|
} catch (error) {
|
|
515
861
|
chatError = error instanceof Error ? error : new Error(String(error));
|
|
862
|
+
const statusEvent = { type: "status", status: "error" };
|
|
863
|
+
middlewareRunner.emitEvent(statusEvent);
|
|
864
|
+
yield statusEvent;
|
|
865
|
+
const errorEvent = { type: "error", error: chatError };
|
|
866
|
+
middlewareRunner.emitEvent(errorEvent);
|
|
867
|
+
yield errorEvent;
|
|
516
868
|
throw error;
|
|
517
869
|
} finally {
|
|
518
870
|
setIsStreaming(false);
|
|
@@ -552,255 +904,100 @@ function resolveChildPromptConfig(options) {
|
|
|
552
904
|
if (promptBuilder) {
|
|
553
905
|
return { prompt: parentPromptConfig ?? {} };
|
|
554
906
|
}
|
|
555
|
-
return { systemPrompt: parentSystemPrompt };
|
|
556
|
-
}
|
|
557
|
-
function resolveForkMiddleware(options, middlewareRunner) {
|
|
558
|
-
if (options.middleware) {
|
|
559
|
-
return options.middleware;
|
|
560
|
-
}
|
|
561
|
-
if (options.additionalMiddleware) {
|
|
562
|
-
return [
|
|
563
|
-
...middlewareRunner.getMiddleware(),
|
|
564
|
-
...options.additionalMiddleware
|
|
565
|
-
];
|
|
566
|
-
}
|
|
567
|
-
return [...middlewareRunner.getMiddleware()];
|
|
568
|
-
}
|
|
569
|
-
function createForkedAgentConfig(options) {
|
|
570
|
-
const {
|
|
571
|
-
forkOptions,
|
|
572
|
-
parentConfig,
|
|
573
|
-
parentTools,
|
|
574
|
-
reasoningLevel,
|
|
575
|
-
host,
|
|
576
|
-
sessions,
|
|
577
|
-
mcpManager,
|
|
578
|
-
middlewareRunner,
|
|
579
|
-
promptBuilder
|
|
580
|
-
} = options;
|
|
581
|
-
const tools = forkOptions.tools ?? parentTools;
|
|
582
|
-
const childPrompt = resolveChildPromptConfig({
|
|
583
|
-
forkOptions,
|
|
584
|
-
promptBuilder,
|
|
585
|
-
parentPromptConfig: parentConfig.prompt,
|
|
586
|
-
parentSystemPrompt: parentConfig.systemPrompt
|
|
587
|
-
});
|
|
588
|
-
return {
|
|
589
|
-
model: forkOptions.model ?? parentConfig.model,
|
|
590
|
-
cwd: parentConfig.cwd,
|
|
591
|
-
host,
|
|
592
|
-
maxOutputTokens: parentConfig.maxOutputTokens,
|
|
593
|
-
maxSteps: forkOptions.maxSteps ?? parentConfig.maxSteps,
|
|
594
|
-
temperature: forkOptions.temperature ?? parentConfig.temperature,
|
|
595
|
-
topP: parentConfig.topP,
|
|
596
|
-
reasoningLevel: forkOptions.reasoningLevel ?? reasoningLevel,
|
|
597
|
-
...childPrompt,
|
|
598
|
-
sessionManager: new SessionManager(sessions.getStorage()),
|
|
599
|
-
tools,
|
|
600
|
-
onDoomLoop: parentConfig.onDoomLoop,
|
|
601
|
-
enforceDoomLoop: parentConfig.enforceDoomLoop,
|
|
602
|
-
doomLoopThreshold: parentConfig.doomLoopThreshold,
|
|
603
|
-
compaction: parentConfig.compaction,
|
|
604
|
-
contextWindow: parentConfig.contextWindow,
|
|
605
|
-
mcp: mcpManager,
|
|
606
|
-
middleware: resolveForkMiddleware(forkOptions, middlewareRunner)
|
|
607
|
-
};
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
// src/agent/mcp-bridge.ts
|
|
611
|
-
async function ensureMcpTools(state) {
|
|
612
|
-
if (!state.manager) {
|
|
613
|
-
return { connected: false, cachedTools: void 0 };
|
|
614
|
-
}
|
|
615
|
-
if (state.connected && state.cachedTools) {
|
|
616
|
-
return {
|
|
617
|
-
connected: state.connected,
|
|
618
|
-
cachedTools: state.cachedTools
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
const statuses = await state.manager.connect();
|
|
622
|
-
let connectedCount = 0;
|
|
623
|
-
for (const [name, status] of statuses) {
|
|
624
|
-
if (status.status === "connected") {
|
|
625
|
-
connectedCount++;
|
|
626
|
-
} else if (status.status === "error") {
|
|
627
|
-
console.warn(`[mcp] Failed to connect to ${name}: ${status.error}`);
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
if (connectedCount === 0 && statuses.size > 0) {
|
|
631
|
-
console.warn("[mcp] No MCP servers connected successfully");
|
|
632
|
-
}
|
|
633
|
-
const cachedTools = await state.manager.getTools();
|
|
634
|
-
return {
|
|
635
|
-
connected: true,
|
|
636
|
-
cachedTools
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
async function closeMcpManager(manager) {
|
|
640
|
-
if (manager) {
|
|
641
|
-
await manager.close();
|
|
642
|
-
}
|
|
643
|
-
return {
|
|
644
|
-
connected: false,
|
|
645
|
-
cachedTools: void 0
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
// src/agent/session.ts
|
|
650
|
-
async function ensureSessionLoaded(options) {
|
|
651
|
-
const { sessionId, sessions, loadedSessions, cwd } = options;
|
|
652
|
-
if (loadedSessions.has(sessionId) && sessions.getSessionId() === sessionId) {
|
|
653
|
-
return;
|
|
654
|
-
}
|
|
655
|
-
const exists = await sessions.sessionExists(sessionId);
|
|
656
|
-
if (exists) {
|
|
657
|
-
await sessions.load(sessionId);
|
|
658
|
-
} else {
|
|
659
|
-
await sessions.create({ id: sessionId, cwd });
|
|
660
|
-
}
|
|
661
|
-
loadedSessions.add(sessionId);
|
|
662
|
-
}
|
|
663
|
-
async function repairOrphanedToolCalls(sessions) {
|
|
664
|
-
const messages = sessions.getMessages();
|
|
665
|
-
const pendingCallIds = /* @__PURE__ */ new Map();
|
|
666
|
-
for (const message of messages) {
|
|
667
|
-
if (message.role === "assistant" && message.toolCalls) {
|
|
668
|
-
for (const toolCall of message.toolCalls) {
|
|
669
|
-
pendingCallIds.set(toolCall.toolCallId, { toolName: toolCall.toolName });
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
if (message.role === "tool" && message.toolCallId) {
|
|
673
|
-
pendingCallIds.delete(message.toolCallId);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
for (const [toolCallId, { toolName }] of pendingCallIds) {
|
|
677
|
-
const toolMessage = {
|
|
678
|
-
id: crypto.randomUUID(),
|
|
679
|
-
role: "tool",
|
|
680
|
-
content: "Error: tool execution failed (result was not recorded)",
|
|
681
|
-
toolCallId,
|
|
682
|
-
toolName,
|
|
683
|
-
result: "Error: tool execution failed (result was not recorded)",
|
|
684
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
685
|
-
};
|
|
686
|
-
await sessions.addMessage(toolMessage);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
async function createSubAgentRunSession(options) {
|
|
690
|
-
const sessionId = options.parentSessionId ? `${options.parentSessionId}:sub:${crypto.randomUUID().slice(0, 8)}` : `sub:${crypto.randomUUID().slice(0, 8)}`;
|
|
691
|
-
await options.sessions.create({
|
|
692
|
-
id: sessionId,
|
|
693
|
-
cwd: options.cwd,
|
|
694
|
-
title: options.title ?? "Sub-agent task",
|
|
695
|
-
parentSessionId: options.parentSessionId
|
|
696
|
-
});
|
|
697
|
-
options.loadedSessions.add(sessionId);
|
|
698
|
-
return sessionId;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
// src/agent/intervention.ts
|
|
702
|
-
var InterventionController = class {
|
|
703
|
-
/** Immediate interventions — applied at the next step boundary */
|
|
704
|
-
immediate = [];
|
|
705
|
-
/** Deferred messages — held until the turn completes */
|
|
706
|
-
deferred = [];
|
|
707
|
-
/**
|
|
708
|
-
* Callback fired when an intervention is wired into a step.
|
|
709
|
-
* Set by the Agent before starting a chat turn, cleared after.
|
|
710
|
-
*/
|
|
711
|
-
onApplied;
|
|
712
|
-
// ---------------------------------------------------------------------------
|
|
713
|
-
// Immediate interventions (mid-turn redirect)
|
|
714
|
-
// ---------------------------------------------------------------------------
|
|
715
|
-
/**
|
|
716
|
-
* Inject a message at the next LLM step boundary.
|
|
717
|
-
*
|
|
718
|
-
* The message is appended as a user message to the conversation
|
|
719
|
-
* before the next LLM call in the current multi-step turn. The
|
|
720
|
-
* LLM will see it and can adjust its behavior accordingly.
|
|
721
|
-
*
|
|
722
|
-
* Safe to call from any async context while `chat()` is running.
|
|
723
|
-
* If called when no turn is active, the message will be picked up
|
|
724
|
-
* by the first step of the next `chat()` call.
|
|
725
|
-
*
|
|
726
|
-
* @param message - The user message to inject
|
|
727
|
-
* @returns Intervention ID for tracking
|
|
728
|
-
*/
|
|
729
|
-
intervene(message) {
|
|
730
|
-
const id = crypto.randomUUID();
|
|
731
|
-
this.immediate.push(
|
|
732
|
-
Object.freeze({ id, message, createdAt: /* @__PURE__ */ new Date() })
|
|
733
|
-
);
|
|
734
|
-
return id;
|
|
735
|
-
}
|
|
736
|
-
/**
|
|
737
|
-
* Drain and return all pending immediate interventions.
|
|
738
|
-
* The internal queue is cleared atomically.
|
|
739
|
-
*
|
|
740
|
-
* @internal Called by the LLM stream's `prepareStep` hook
|
|
741
|
-
*/
|
|
742
|
-
drainImmediate() {
|
|
743
|
-
if (this.immediate.length === 0) return [];
|
|
744
|
-
return this.immediate.splice(0);
|
|
745
|
-
}
|
|
746
|
-
/** Whether there are pending immediate interventions */
|
|
747
|
-
get hasPending() {
|
|
748
|
-
return this.immediate.length > 0;
|
|
749
|
-
}
|
|
750
|
-
/** Number of pending immediate interventions */
|
|
751
|
-
get pendingCount() {
|
|
752
|
-
return this.immediate.length;
|
|
907
|
+
return { systemPrompt: parentSystemPrompt };
|
|
908
|
+
}
|
|
909
|
+
function resolveForkMiddleware(options, middlewareRunner) {
|
|
910
|
+
if (options.middleware) {
|
|
911
|
+
return options.middleware;
|
|
753
912
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
*
|
|
760
|
-
* Unlike `intervene()`, this does **not** inject mid-turn. The
|
|
761
|
-
* message is held and available via `drainDeferred()` after
|
|
762
|
-
* `chat()` finishes. The consumer decides whether to send it
|
|
763
|
-
* as a new turn.
|
|
764
|
-
*
|
|
765
|
-
* @param message - The message to queue
|
|
766
|
-
* @returns Intervention ID for tracking
|
|
767
|
-
*/
|
|
768
|
-
queueNext(message) {
|
|
769
|
-
const id = crypto.randomUUID();
|
|
770
|
-
this.deferred.push(
|
|
771
|
-
Object.freeze({ id, message, createdAt: /* @__PURE__ */ new Date() })
|
|
772
|
-
);
|
|
773
|
-
return id;
|
|
913
|
+
if (options.additionalMiddleware) {
|
|
914
|
+
return [
|
|
915
|
+
...middlewareRunner.getMiddleware(),
|
|
916
|
+
...options.additionalMiddleware
|
|
917
|
+
];
|
|
774
918
|
}
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
919
|
+
return [...middlewareRunner.getMiddleware()];
|
|
920
|
+
}
|
|
921
|
+
function createForkedAgentConfig(options) {
|
|
922
|
+
const {
|
|
923
|
+
forkOptions,
|
|
924
|
+
parentConfig,
|
|
925
|
+
parentTools,
|
|
926
|
+
reasoningLevel,
|
|
927
|
+
host,
|
|
928
|
+
ownsHost,
|
|
929
|
+
sessions,
|
|
930
|
+
mcpManager,
|
|
931
|
+
middlewareRunner,
|
|
932
|
+
promptBuilder
|
|
933
|
+
} = options;
|
|
934
|
+
const tools = forkOptions.tools ?? parentTools;
|
|
935
|
+
const childPrompt = resolveChildPromptConfig({
|
|
936
|
+
forkOptions,
|
|
937
|
+
promptBuilder,
|
|
938
|
+
parentPromptConfig: parentConfig.prompt,
|
|
939
|
+
parentSystemPrompt: parentConfig.systemPrompt
|
|
940
|
+
});
|
|
941
|
+
return {
|
|
942
|
+
model: forkOptions.model ?? parentConfig.model,
|
|
943
|
+
cwd: parentConfig.cwd,
|
|
944
|
+
...ownsHost ? {} : { host },
|
|
945
|
+
maxOutputTokens: parentConfig.maxOutputTokens,
|
|
946
|
+
maxSteps: forkOptions.maxSteps ?? parentConfig.maxSteps,
|
|
947
|
+
temperature: forkOptions.temperature ?? parentConfig.temperature,
|
|
948
|
+
topP: parentConfig.topP,
|
|
949
|
+
reasoningLevel: forkOptions.reasoningLevel ?? reasoningLevel,
|
|
950
|
+
...childPrompt,
|
|
951
|
+
sessionManager: new SessionManager(sessions.getStorage()),
|
|
952
|
+
tools,
|
|
953
|
+
onDoomLoop: parentConfig.onDoomLoop,
|
|
954
|
+
enforceDoomLoop: parentConfig.enforceDoomLoop,
|
|
955
|
+
doomLoopThreshold: parentConfig.doomLoopThreshold,
|
|
956
|
+
compaction: parentConfig.compaction,
|
|
957
|
+
contextWindow: parentConfig.contextWindow,
|
|
958
|
+
mcp: mcpManager,
|
|
959
|
+
middleware: resolveForkMiddleware(forkOptions, middlewareRunner)
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// src/agent/mcp-bridge.ts
|
|
964
|
+
async function ensureMcpTools(state) {
|
|
965
|
+
if (!state.manager) {
|
|
966
|
+
return { connected: false, cachedTools: void 0 };
|
|
782
967
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
968
|
+
if (state.connected && state.cachedTools) {
|
|
969
|
+
return {
|
|
970
|
+
connected: state.connected,
|
|
971
|
+
cachedTools: state.cachedTools
|
|
972
|
+
};
|
|
786
973
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
974
|
+
const statuses = await state.manager.connect();
|
|
975
|
+
let connectedCount = 0;
|
|
976
|
+
for (const [name, status] of statuses) {
|
|
977
|
+
if (status.status === "connected") {
|
|
978
|
+
connectedCount++;
|
|
979
|
+
} else if (status.status === "error") {
|
|
980
|
+
console.warn(`[mcp] Failed to connect to ${name}: ${status.error}`);
|
|
981
|
+
}
|
|
790
982
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
// ---------------------------------------------------------------------------
|
|
794
|
-
/** Clear all queues (immediate + deferred) */
|
|
795
|
-
clear() {
|
|
796
|
-
this.immediate.length = 0;
|
|
797
|
-
this.deferred.length = 0;
|
|
983
|
+
if (connectedCount === 0 && statuses.size > 0) {
|
|
984
|
+
console.warn("[mcp] No MCP servers connected successfully");
|
|
798
985
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
986
|
+
const cachedTools = await state.manager.getTools();
|
|
987
|
+
return {
|
|
988
|
+
connected: true,
|
|
989
|
+
cachedTools
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
async function closeMcpManager(manager) {
|
|
993
|
+
if (manager) {
|
|
994
|
+
await manager.close();
|
|
802
995
|
}
|
|
803
|
-
|
|
996
|
+
return {
|
|
997
|
+
connected: false,
|
|
998
|
+
cachedTools: void 0
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
804
1001
|
|
|
805
1002
|
// src/agent/stream-provider.ts
|
|
806
1003
|
var DEFAULT_CUSTOM_STREAM_MODELS = [
|
|
@@ -808,7 +1005,7 @@ var DEFAULT_CUSTOM_STREAM_MODELS = [
|
|
|
808
1005
|
"computer-use-preview-2025-03-11"
|
|
809
1006
|
];
|
|
810
1007
|
function needsCustomStreamProvider(model, customPatterns) {
|
|
811
|
-
const modelId =
|
|
1008
|
+
const modelId = extractModelId(model);
|
|
812
1009
|
if (!modelId || modelId === "[object Object]") return false;
|
|
813
1010
|
const patterns = customPatterns ?? DEFAULT_CUSTOM_STREAM_MODELS;
|
|
814
1011
|
return patterns.some((pattern) => modelId.includes(pattern));
|
|
@@ -824,7 +1021,7 @@ function autoDetectStreamProvider(model, tools, explicitProvider) {
|
|
|
824
1021
|
const enhancedTools = tools;
|
|
825
1022
|
const customPatterns = enhancedTools.__customStreamModels;
|
|
826
1023
|
if (needsCustomStreamProvider(model, customPatterns) && hasStreamProviderFactory(enhancedTools)) {
|
|
827
|
-
const modelId =
|
|
1024
|
+
const modelId = extractModelId(model);
|
|
828
1025
|
if (modelId) {
|
|
829
1026
|
const streamConfig = {
|
|
830
1027
|
apiKey: process.env.OPENAI_API_KEY,
|
|
@@ -900,24 +1097,39 @@ function createAgentState(config) {
|
|
|
900
1097
|
}
|
|
901
1098
|
function createAgentContextManager(config) {
|
|
902
1099
|
const compactionConfig = config.compaction ?? {};
|
|
903
|
-
const modelId =
|
|
1100
|
+
const modelId = extractModelId(config.model);
|
|
904
1101
|
const inferredWindow = inferContextWindow(modelId);
|
|
905
1102
|
const contextWindow = config.contextWindow ?? inferredWindow ?? DEFAULT_CONTEXT_LIMITS.contextWindow;
|
|
906
|
-
const reserveTokens = Math.min(
|
|
907
|
-
32e3,
|
|
908
|
-
Math.max(8e3, Math.round(contextWindow * 0.12))
|
|
909
|
-
);
|
|
910
1103
|
return new ContextManager({
|
|
911
1104
|
limits: {
|
|
912
1105
|
contextWindow,
|
|
913
|
-
|
|
914
|
-
protectedTokens: compactionConfig.protectedTokens ?? DEFAULT_CONTEXT_LIMITS.protectedTokens,
|
|
915
|
-
pruneMinimum: compactionConfig.pruneMinimum ?? DEFAULT_CONTEXT_LIMITS.pruneMinimum
|
|
1106
|
+
...resolveAgentContextLimits(contextWindow, compactionConfig)
|
|
916
1107
|
},
|
|
917
1108
|
model: compactionConfig.summaryModel ?? config.model,
|
|
918
1109
|
summaryPrompt: compactionConfig.summaryPrompt
|
|
919
1110
|
});
|
|
920
1111
|
}
|
|
1112
|
+
function resolveAgentContextLimits(contextWindow, compactionConfig = {}) {
|
|
1113
|
+
const proportionalReserve = Math.round(contextWindow * 0.12);
|
|
1114
|
+
const reserveTokens = contextWindow >= 64e3 ? Math.min(32e3, Math.max(8e3, proportionalReserve)) : Math.min(
|
|
1115
|
+
Math.max(1024, Math.round(contextWindow * 0.25)),
|
|
1116
|
+
Math.max(512, proportionalReserve)
|
|
1117
|
+
);
|
|
1118
|
+
const usableWindow = Math.max(512, contextWindow - reserveTokens);
|
|
1119
|
+
const requestedProtected = compactionConfig.protectedTokens ?? DEFAULT_CONTEXT_LIMITS.protectedTokens;
|
|
1120
|
+
const requestedPruneMinimum = compactionConfig.pruneMinimum ?? DEFAULT_CONTEXT_LIMITS.pruneMinimum;
|
|
1121
|
+
return {
|
|
1122
|
+
reserveTokens,
|
|
1123
|
+
protectedTokens: Math.min(
|
|
1124
|
+
requestedProtected,
|
|
1125
|
+
Math.max(512, Math.round(usableWindow * 0.6))
|
|
1126
|
+
),
|
|
1127
|
+
pruneMinimum: Math.min(
|
|
1128
|
+
requestedPruneMinimum,
|
|
1129
|
+
Math.max(256, Math.round(usableWindow * 0.5))
|
|
1130
|
+
)
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
921
1133
|
function createMiddlewareSetup(input, config) {
|
|
922
1134
|
let effectiveMiddleware = input.middleware;
|
|
923
1135
|
let telemetrySettings;
|
|
@@ -962,78 +1174,13 @@ function createAgentSetup(input) {
|
|
|
962
1174
|
...promptBuilder ? { promptBuilder } : {},
|
|
963
1175
|
interventionCtrl: new InterventionController(),
|
|
964
1176
|
host: input.host ?? localHost(config.cwd),
|
|
1177
|
+
ownsHost: input.host === void 0,
|
|
965
1178
|
middlewareRunner: middlewareSetup.middlewareRunner,
|
|
966
1179
|
...middlewareSetup.telemetrySettings ? { telemetrySettings: middlewareSetup.telemetrySettings } : {},
|
|
967
1180
|
...middlewareSetup.tracingShutdown ? { tracingShutdown: middlewareSetup.tracingShutdown } : {}
|
|
968
1181
|
};
|
|
969
1182
|
}
|
|
970
1183
|
|
|
971
|
-
// src/agent/runtime-config.ts
|
|
972
|
-
function createAgentToolRecord(tools) {
|
|
973
|
-
const toolRecord = {};
|
|
974
|
-
for (const [id, tool] of tools) {
|
|
975
|
-
toolRecord[id] = tool;
|
|
976
|
-
}
|
|
977
|
-
return toolRecord;
|
|
978
|
-
}
|
|
979
|
-
function getAgentContextStats(contextManager, messages) {
|
|
980
|
-
return contextManager.getStats(messages);
|
|
981
|
-
}
|
|
982
|
-
async function compactAgentContext(contextManager, messages) {
|
|
983
|
-
const result = await contextManager.prune(messages);
|
|
984
|
-
return {
|
|
985
|
-
removedCount: result.removedCount,
|
|
986
|
-
tokensRemoved: result.tokensRemoved,
|
|
987
|
-
summarized: result.summarized,
|
|
988
|
-
summary: result.summary
|
|
989
|
-
};
|
|
990
|
-
}
|
|
991
|
-
async function buildAgentSystemPrompts(options) {
|
|
992
|
-
const {
|
|
993
|
-
config,
|
|
994
|
-
toolIds,
|
|
995
|
-
sessionId,
|
|
996
|
-
override,
|
|
997
|
-
promptBuilder,
|
|
998
|
-
middlewareRunner
|
|
999
|
-
} = options;
|
|
1000
|
-
if (promptBuilder) {
|
|
1001
|
-
const composedPrompt = await promptBuilder.build(
|
|
1002
|
-
{
|
|
1003
|
-
cwd: config.cwd,
|
|
1004
|
-
model: config.model,
|
|
1005
|
-
toolNames: toolIds,
|
|
1006
|
-
...override ? { override } : {},
|
|
1007
|
-
sessionId
|
|
1008
|
-
},
|
|
1009
|
-
middlewareRunner
|
|
1010
|
-
);
|
|
1011
|
-
return [composedPrompt];
|
|
1012
|
-
}
|
|
1013
|
-
const prompts = [config.systemPrompt];
|
|
1014
|
-
if (override) {
|
|
1015
|
-
prompts.push(override);
|
|
1016
|
-
}
|
|
1017
|
-
return prompts;
|
|
1018
|
-
}
|
|
1019
|
-
function createAgentTurnRuntimeConfig(options) {
|
|
1020
|
-
const { config, telemetrySettings } = options;
|
|
1021
|
-
return {
|
|
1022
|
-
model: config.model,
|
|
1023
|
-
cwd: config.cwd,
|
|
1024
|
-
...config.temperature !== void 0 ? { temperature: config.temperature } : {},
|
|
1025
|
-
...config.topP !== void 0 ? { topP: config.topP } : {},
|
|
1026
|
-
...config.maxOutputTokens !== void 0 ? { maxOutputTokens: config.maxOutputTokens } : {},
|
|
1027
|
-
maxSteps: config.maxSteps,
|
|
1028
|
-
...config.doomLoopThreshold !== void 0 ? { doomLoopThreshold: config.doomLoopThreshold } : {},
|
|
1029
|
-
...config.enforceDoomLoop !== void 0 ? { enforceDoomLoop: config.enforceDoomLoop } : {},
|
|
1030
|
-
...config.onDoomLoop ? { onDoomLoop: config.onDoomLoop } : {},
|
|
1031
|
-
...config.contextWindow !== void 0 ? { contextWindow: config.contextWindow } : {},
|
|
1032
|
-
...config.streamProvider ? { streamProvider: config.streamProvider } : {},
|
|
1033
|
-
...telemetrySettings ? { telemetry: telemetrySettings } : {}
|
|
1034
|
-
};
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
1184
|
// src/agent/instance.ts
|
|
1038
1185
|
function createAgent(config) {
|
|
1039
1186
|
return new Agent(config);
|
|
@@ -1042,7 +1189,6 @@ var Agent = class _Agent {
|
|
|
1042
1189
|
config;
|
|
1043
1190
|
tools;
|
|
1044
1191
|
sessions;
|
|
1045
|
-
loadedSessions = /* @__PURE__ */ new Set();
|
|
1046
1192
|
state;
|
|
1047
1193
|
/** Context manager for overflow detection and compaction */
|
|
1048
1194
|
contextManager;
|
|
@@ -1066,6 +1212,8 @@ var Agent = class _Agent {
|
|
|
1066
1212
|
interventionCtrl;
|
|
1067
1213
|
/** Execution environment for tool operations */
|
|
1068
1214
|
host;
|
|
1215
|
+
/** Whether the agent owns the host and can safely recreate it on cwd changes */
|
|
1216
|
+
ownsHost;
|
|
1069
1217
|
/** Middleware runner for lifecycle hooks */
|
|
1070
1218
|
middlewareRunner;
|
|
1071
1219
|
/** AI SDK telemetry settings (auto-created from `tracing` config) */
|
|
@@ -1074,6 +1222,12 @@ var Agent = class _Agent {
|
|
|
1074
1222
|
tracingShutdown;
|
|
1075
1223
|
/** Multi-consumer event dispatch */
|
|
1076
1224
|
_signal;
|
|
1225
|
+
/** Number of active turns across all sessions */
|
|
1226
|
+
activeTurnCount = 0;
|
|
1227
|
+
/** Active turn intervention controllers, keyed by turn id */
|
|
1228
|
+
activeTurns = /* @__PURE__ */ new Map();
|
|
1229
|
+
/** Per-session turn queue to prevent concurrent writes to the same history */
|
|
1230
|
+
sessionLocks = /* @__PURE__ */ new Map();
|
|
1077
1231
|
constructor(config) {
|
|
1078
1232
|
const setup = createAgentSetup(config);
|
|
1079
1233
|
this.config = setup.config;
|
|
@@ -1086,6 +1240,7 @@ var Agent = class _Agent {
|
|
|
1086
1240
|
this.promptBuilder = setup.promptBuilder;
|
|
1087
1241
|
this.interventionCtrl = setup.interventionCtrl;
|
|
1088
1242
|
this.host = setup.host;
|
|
1243
|
+
this.ownsHost = setup.ownsHost;
|
|
1089
1244
|
this.middlewareRunner = setup.middlewareRunner;
|
|
1090
1245
|
this.telemetrySettings = setup.telemetrySettings;
|
|
1091
1246
|
this.tracingShutdown = setup.tracingShutdown;
|
|
@@ -1119,7 +1274,7 @@ var Agent = class _Agent {
|
|
|
1119
1274
|
}
|
|
1120
1275
|
/** Is currently streaming */
|
|
1121
1276
|
get isStreaming() {
|
|
1122
|
-
return this.
|
|
1277
|
+
return this.activeTurnCount > 0;
|
|
1123
1278
|
}
|
|
1124
1279
|
/** Current reasoning level */
|
|
1125
1280
|
get reasoningLevel() {
|
|
@@ -1162,6 +1317,74 @@ var Agent = class _Agent {
|
|
|
1162
1317
|
}
|
|
1163
1318
|
}
|
|
1164
1319
|
}
|
|
1320
|
+
resetPromptScopedTools() {
|
|
1321
|
+
this.tools.delete("skill");
|
|
1322
|
+
this.tools.delete("skill_resource");
|
|
1323
|
+
this.skillToolsResolved = false;
|
|
1324
|
+
}
|
|
1325
|
+
createSessionManager() {
|
|
1326
|
+
return new SessionManager(this.sessions.getStorage());
|
|
1327
|
+
}
|
|
1328
|
+
async acquireSessionLock(sessionId) {
|
|
1329
|
+
const previous = this.sessionLocks.get(sessionId) ?? Promise.resolve();
|
|
1330
|
+
let releaseLock;
|
|
1331
|
+
const current = new Promise((resolve) => {
|
|
1332
|
+
releaseLock = resolve;
|
|
1333
|
+
});
|
|
1334
|
+
const chain = previous.catch(() => void 0).then(() => current);
|
|
1335
|
+
this.sessionLocks.set(sessionId, chain);
|
|
1336
|
+
await previous.catch(() => void 0);
|
|
1337
|
+
let released = false;
|
|
1338
|
+
return () => {
|
|
1339
|
+
if (released) return;
|
|
1340
|
+
released = true;
|
|
1341
|
+
releaseLock();
|
|
1342
|
+
if (this.sessionLocks.get(sessionId) === chain) {
|
|
1343
|
+
this.sessionLocks.delete(sessionId);
|
|
1344
|
+
}
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
getActiveInterventionController() {
|
|
1348
|
+
const active = Array.from(this.activeTurns.values());
|
|
1349
|
+
if (active.length === 0) {
|
|
1350
|
+
return void 0;
|
|
1351
|
+
}
|
|
1352
|
+
if (active.length > 1) {
|
|
1353
|
+
throw new Error(
|
|
1354
|
+
"Interventions are ambiguous while multiple agent turns are active. Use separate Agent instances or wait for one turn to finish."
|
|
1355
|
+
);
|
|
1356
|
+
}
|
|
1357
|
+
return active[0].interventionCtrl;
|
|
1358
|
+
}
|
|
1359
|
+
getInterventionControllerForTurn() {
|
|
1360
|
+
const activeController = this.getActiveInterventionController();
|
|
1361
|
+
return activeController ?? this.interventionCtrl;
|
|
1362
|
+
}
|
|
1363
|
+
createTurnInterventionController() {
|
|
1364
|
+
return this.activeTurns.size === 0 ? this.interventionCtrl : new InterventionController();
|
|
1365
|
+
}
|
|
1366
|
+
releaseTurnInterventions(controller) {
|
|
1367
|
+
if (controller === this.interventionCtrl) {
|
|
1368
|
+
controller.resetCallbacks();
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
this.interventionCtrl.adoptImmediate(controller.drainImmediate());
|
|
1372
|
+
this.interventionCtrl.adoptDeferred(controller.drainDeferred());
|
|
1373
|
+
controller.resetCallbacks();
|
|
1374
|
+
}
|
|
1375
|
+
syncStreamingState(active) {
|
|
1376
|
+
this.activeTurnCount = Math.max(
|
|
1377
|
+
0,
|
|
1378
|
+
this.activeTurnCount + (active ? 1 : -1)
|
|
1379
|
+
);
|
|
1380
|
+
this.state.isStreaming = this.activeTurnCount > 0;
|
|
1381
|
+
}
|
|
1382
|
+
async syncSessionView(sessionId) {
|
|
1383
|
+
if (!await this.sessions.sessionExists(sessionId)) {
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
await this.sessions.load(sessionId);
|
|
1387
|
+
}
|
|
1165
1388
|
/**
|
|
1166
1389
|
* Ensure MCP is connected and return tools
|
|
1167
1390
|
* Lazy initialization - only connects on first use
|
|
@@ -1185,8 +1408,8 @@ var Agent = class _Agent {
|
|
|
1185
1408
|
* `MissingToolResultsError`. This method detects orphaned tool-call IDs
|
|
1186
1409
|
* and adds placeholder `tool` messages so the history is valid again.
|
|
1187
1410
|
*/
|
|
1188
|
-
async repairOrphanedToolCalls() {
|
|
1189
|
-
await repairOrphanedToolCalls(
|
|
1411
|
+
async repairOrphanedToolCalls(sessions) {
|
|
1412
|
+
await repairOrphanedToolCalls(sessions);
|
|
1190
1413
|
}
|
|
1191
1414
|
/**
|
|
1192
1415
|
* Convert internal {@link Message} array to Vercel AI SDK {@link ModelMessage} format.
|
|
@@ -1212,52 +1435,75 @@ var Agent = class _Agent {
|
|
|
1212
1435
|
* @yields {AgentEvent} Events as they occur during processing
|
|
1213
1436
|
*/
|
|
1214
1437
|
async *chat(sessionId, message, options) {
|
|
1215
|
-
await this.
|
|
1216
|
-
|
|
1217
|
-
const abort = options?.abort ?? new AbortController().signal;
|
|
1438
|
+
const releaseSessionLock = await this.acquireSessionLock(sessionId);
|
|
1439
|
+
const sessions = this.createSessionManager();
|
|
1218
1440
|
const turnId = `${sessionId}-turn-${++this.turnCounter}`;
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
abort
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1441
|
+
let turnTracker;
|
|
1442
|
+
let interventionCtrl = this.interventionCtrl;
|
|
1443
|
+
let streamingStateActive = false;
|
|
1444
|
+
let turnRegistered = false;
|
|
1445
|
+
try {
|
|
1446
|
+
await this.ensureSkillTools();
|
|
1447
|
+
const abort = options?.abort ?? new AbortController().signal;
|
|
1448
|
+
turnTracker = createTurnTracker({ cwd: this.config.cwd });
|
|
1449
|
+
interventionCtrl = this.createTurnInterventionController();
|
|
1450
|
+
this.activeTurns.set(turnId, { sessionId, interventionCtrl });
|
|
1451
|
+
turnRegistered = true;
|
|
1452
|
+
await ensureSessionLoaded({
|
|
1453
|
+
sessionId,
|
|
1454
|
+
sessions,
|
|
1455
|
+
cwd: this.config.cwd
|
|
1456
|
+
});
|
|
1457
|
+
turnTracker.startTurn(turnId);
|
|
1458
|
+
await this.repairOrphanedToolCalls(sessions);
|
|
1459
|
+
const mcpTools = await this.ensureMCPConnected();
|
|
1460
|
+
const loop = runChatLoop({
|
|
1461
|
+
sessionId,
|
|
1462
|
+
message,
|
|
1463
|
+
abort,
|
|
1464
|
+
systemOverride: options?.system,
|
|
1465
|
+
sessions,
|
|
1466
|
+
tools: createAgentToolRecord(this.tools),
|
|
1467
|
+
config: this.config,
|
|
1468
|
+
turnTracker,
|
|
1469
|
+
interventionCtrl,
|
|
1470
|
+
middlewareRunner: this.middlewareRunner,
|
|
1471
|
+
contextManager: this.contextManager,
|
|
1472
|
+
rememberedDoomLoopTools: this.rememberedDoomLoopTools,
|
|
1473
|
+
reasoningLevel: this.state.reasoningLevel,
|
|
1474
|
+
promptBuilder: this.promptBuilder,
|
|
1475
|
+
host: this.host,
|
|
1476
|
+
mcpTools,
|
|
1477
|
+
telemetrySettings: this.telemetrySettings,
|
|
1478
|
+
toModelMessages: this.toModelMessages.bind(this),
|
|
1479
|
+
setIsStreaming: (value) => {
|
|
1480
|
+
if (value === streamingStateActive) return;
|
|
1481
|
+
streamingStateActive = value;
|
|
1482
|
+
this.syncStreamingState(value);
|
|
1483
|
+
}
|
|
1484
|
+
});
|
|
1485
|
+
for await (const event of loop) {
|
|
1486
|
+
this._signal.emit(event);
|
|
1487
|
+
yield event;
|
|
1488
|
+
}
|
|
1489
|
+
} finally {
|
|
1490
|
+
try {
|
|
1491
|
+
if (streamingStateActive) {
|
|
1492
|
+
this.syncStreamingState(false);
|
|
1493
|
+
}
|
|
1494
|
+
if (turnRegistered) {
|
|
1495
|
+
this.activeTurns.delete(turnId);
|
|
1496
|
+
}
|
|
1497
|
+
this.releaseTurnInterventions(interventionCtrl);
|
|
1498
|
+
if (turnRegistered && turnTracker) {
|
|
1499
|
+
this.turnTracker = turnTracker;
|
|
1500
|
+
}
|
|
1501
|
+
await this.syncSessionView(sessionId);
|
|
1502
|
+
} finally {
|
|
1503
|
+
releaseSessionLock();
|
|
1243
1504
|
}
|
|
1244
|
-
});
|
|
1245
|
-
for await (const event of loop) {
|
|
1246
|
-
this._signal.emit(event);
|
|
1247
|
-
yield event;
|
|
1248
1505
|
}
|
|
1249
1506
|
}
|
|
1250
|
-
/**
|
|
1251
|
-
* Ensure a session is loaded or created
|
|
1252
|
-
*/
|
|
1253
|
-
async ensureSession(sessionId) {
|
|
1254
|
-
await ensureSessionLoaded({
|
|
1255
|
-
sessionId,
|
|
1256
|
-
sessions: this.sessions,
|
|
1257
|
-
loadedSessions: this.loadedSessions,
|
|
1258
|
-
cwd: this.config.cwd
|
|
1259
|
-
});
|
|
1260
|
-
}
|
|
1261
1507
|
/**
|
|
1262
1508
|
* Send a message and wait for the complete response (non-streaming).
|
|
1263
1509
|
*
|
|
@@ -1332,7 +1578,6 @@ var Agent = class _Agent {
|
|
|
1332
1578
|
}
|
|
1333
1579
|
/** Delete a session */
|
|
1334
1580
|
async deleteSession(sessionId) {
|
|
1335
|
-
this.loadedSessions.delete(sessionId);
|
|
1336
1581
|
return this.sessions.deleteSession(sessionId);
|
|
1337
1582
|
}
|
|
1338
1583
|
/** List all sessions */
|
|
@@ -1382,10 +1627,10 @@ var Agent = class _Agent {
|
|
|
1382
1627
|
* @returns Pruning result with details about what was removed/summarized
|
|
1383
1628
|
*/
|
|
1384
1629
|
async compactContext() {
|
|
1385
|
-
return await compactAgentContext(
|
|
1386
|
-
this.contextManager,
|
|
1387
|
-
this.sessions
|
|
1388
|
-
);
|
|
1630
|
+
return await compactAgentContext({
|
|
1631
|
+
contextManager: this.contextManager,
|
|
1632
|
+
sessions: this.sessions
|
|
1633
|
+
});
|
|
1389
1634
|
}
|
|
1390
1635
|
/**
|
|
1391
1636
|
* Clear remembered doom loop tools.
|
|
@@ -1415,6 +1660,8 @@ var Agent = class _Agent {
|
|
|
1415
1660
|
*
|
|
1416
1661
|
* If called when no turn is active, the message will be picked up
|
|
1417
1662
|
* by the first step of the next `chat()` call.
|
|
1663
|
+
* If multiple turns are active concurrently, this throws because the
|
|
1664
|
+
* target turn would be ambiguous.
|
|
1418
1665
|
*
|
|
1419
1666
|
* @param message - The user message to inject mid-turn
|
|
1420
1667
|
* @returns Intervention ID for tracking
|
|
@@ -1436,7 +1683,7 @@ var Agent = class _Agent {
|
|
|
1436
1683
|
* ```
|
|
1437
1684
|
*/
|
|
1438
1685
|
intervene(message) {
|
|
1439
|
-
return this.
|
|
1686
|
+
return this.getInterventionControllerForTurn().intervene(message);
|
|
1440
1687
|
}
|
|
1441
1688
|
/**
|
|
1442
1689
|
* Queue a message for after the current turn completes.
|
|
@@ -1446,6 +1693,9 @@ var Agent = class _Agent {
|
|
|
1446
1693
|
* `chat()` finishes. The consumer decides whether to send it as a
|
|
1447
1694
|
* new turn.
|
|
1448
1695
|
*
|
|
1696
|
+
* If multiple turns are active concurrently, this throws because the
|
|
1697
|
+
* target turn would be ambiguous.
|
|
1698
|
+
*
|
|
1449
1699
|
* @param message - The message to queue
|
|
1450
1700
|
* @returns Intervention ID for tracking
|
|
1451
1701
|
*
|
|
@@ -1468,15 +1718,15 @@ var Agent = class _Agent {
|
|
|
1468
1718
|
* ```
|
|
1469
1719
|
*/
|
|
1470
1720
|
queueNext(message) {
|
|
1471
|
-
return this.
|
|
1721
|
+
return this.getInterventionControllerForTurn().queueNext(message);
|
|
1472
1722
|
}
|
|
1473
1723
|
/** Whether there are deferred messages queued for after the turn */
|
|
1474
1724
|
hasQueuedNext() {
|
|
1475
|
-
return this.
|
|
1725
|
+
return this.getInterventionControllerForTurn().hasDeferred;
|
|
1476
1726
|
}
|
|
1477
1727
|
/** Drain and return all deferred messages (clears the queue) */
|
|
1478
1728
|
drainQueuedNext() {
|
|
1479
|
-
return this.
|
|
1729
|
+
return this.getInterventionControllerForTurn().drainDeferred();
|
|
1480
1730
|
}
|
|
1481
1731
|
/**
|
|
1482
1732
|
* Get the raw intervention controller for advanced use cases.
|
|
@@ -1488,7 +1738,7 @@ var Agent = class _Agent {
|
|
|
1488
1738
|
* @internal
|
|
1489
1739
|
*/
|
|
1490
1740
|
getInterventionController() {
|
|
1491
|
-
return this.
|
|
1741
|
+
return this.getInterventionControllerForTurn();
|
|
1492
1742
|
}
|
|
1493
1743
|
// ============================================================================
|
|
1494
1744
|
// Turn Tracking
|
|
@@ -1565,26 +1815,37 @@ var Agent = class _Agent {
|
|
|
1565
1815
|
this.config.systemPrompt = prompt;
|
|
1566
1816
|
this.state.systemPrompt = prompt;
|
|
1567
1817
|
this.promptBuilder = void 0;
|
|
1818
|
+
this.resetPromptScopedTools();
|
|
1568
1819
|
}
|
|
1569
1820
|
/** Update working directory */
|
|
1570
1821
|
setCwd(cwd) {
|
|
1571
1822
|
this.config.cwd = cwd;
|
|
1572
1823
|
this.state.cwd = cwd;
|
|
1824
|
+
this.turnTracker = createTurnTracker({ cwd });
|
|
1825
|
+
if (this.ownsHost) {
|
|
1826
|
+
this.host = localHost(cwd);
|
|
1827
|
+
}
|
|
1828
|
+
this.resetPromptScopedTools();
|
|
1573
1829
|
this.promptBuilder?.clearCache();
|
|
1574
1830
|
}
|
|
1575
1831
|
/** Update model */
|
|
1576
1832
|
setModel(model) {
|
|
1577
1833
|
this.config.model = model;
|
|
1578
1834
|
this.state.model = model;
|
|
1835
|
+
if (this.config.compaction?.summaryModel === void 0) {
|
|
1836
|
+
this.contextManager.setModel(model);
|
|
1837
|
+
}
|
|
1579
1838
|
if (this.config.contextWindow === void 0) {
|
|
1580
|
-
const modelId =
|
|
1839
|
+
const modelId = extractModelId(model);
|
|
1581
1840
|
const inferred = inferContextWindow(modelId);
|
|
1582
1841
|
if (inferred) {
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1842
|
+
this.contextManager.setLimits({
|
|
1843
|
+
contextWindow: inferred,
|
|
1844
|
+
...resolveAgentContextLimits(
|
|
1845
|
+
inferred,
|
|
1846
|
+
this.config.compaction
|
|
1847
|
+
)
|
|
1848
|
+
});
|
|
1588
1849
|
}
|
|
1589
1850
|
}
|
|
1590
1851
|
}
|
|
@@ -1624,6 +1885,7 @@ var Agent = class _Agent {
|
|
|
1624
1885
|
* runtimes can start durable turns without duplicating prompt assembly.
|
|
1625
1886
|
*/
|
|
1626
1887
|
async buildSystemPrompts(sessionId, override) {
|
|
1888
|
+
await this.ensureSkillTools();
|
|
1627
1889
|
return await buildAgentSystemPrompts({
|
|
1628
1890
|
config: this.config,
|
|
1629
1891
|
toolIds: Array.from(this.tools.keys()),
|
|
@@ -1699,6 +1961,7 @@ var Agent = class _Agent {
|
|
|
1699
1961
|
parentTools: Array.from(this.tools.values()),
|
|
1700
1962
|
reasoningLevel: this.state.reasoningLevel,
|
|
1701
1963
|
host: this.host,
|
|
1964
|
+
ownsHost: this.ownsHost,
|
|
1702
1965
|
sessions: this.sessions,
|
|
1703
1966
|
mcpManager: this.mcpManager,
|
|
1704
1967
|
middlewareRunner: this.middlewareRunner,
|
|
@@ -1750,9 +2013,9 @@ var Agent = class _Agent {
|
|
|
1750
2013
|
* ```
|
|
1751
2014
|
*/
|
|
1752
2015
|
async run(options) {
|
|
2016
|
+
const sessions = this.createSessionManager();
|
|
1753
2017
|
const sessionId = await createSubAgentRunSession({
|
|
1754
|
-
sessions
|
|
1755
|
-
loadedSessions: this.loadedSessions,
|
|
2018
|
+
sessions,
|
|
1756
2019
|
cwd: this.config.cwd,
|
|
1757
2020
|
parentSessionId: options.parentSessionId,
|
|
1758
2021
|
title: options.title
|
|
@@ -1821,6 +2084,7 @@ async function runConcurrent(tasks, options) {
|
|
|
1821
2084
|
let currentIndex = 0;
|
|
1822
2085
|
async function runNext() {
|
|
1823
2086
|
while (currentIndex < tasks.length) {
|
|
2087
|
+
if (options?.abort?.aborted) break;
|
|
1824
2088
|
const index = currentIndex++;
|
|
1825
2089
|
const task = tasks[index];
|
|
1826
2090
|
results[index] = await task.agent.run({
|
|
@@ -1871,12 +2135,14 @@ export {
|
|
|
1871
2135
|
InterventionController,
|
|
1872
2136
|
LLM,
|
|
1873
2137
|
LLMError,
|
|
2138
|
+
LayeredSettings,
|
|
1874
2139
|
LocalSignal,
|
|
1875
2140
|
MAX_BYTES,
|
|
1876
2141
|
MAX_LINES,
|
|
1877
2142
|
MemoryStorage,
|
|
1878
2143
|
MiddlewareRunner,
|
|
1879
2144
|
ModelCapabilityResolver,
|
|
2145
|
+
NullSettings,
|
|
1880
2146
|
OUTPUT_TOKEN_MAX,
|
|
1881
2147
|
PRIORITY_BASE,
|
|
1882
2148
|
PRIORITY_CUSTOM,
|
|
@@ -1886,6 +2152,8 @@ export {
|
|
|
1886
2152
|
PRIORITY_SKILLS,
|
|
1887
2153
|
PRUNE_PROTECTED_TOOLS,
|
|
1888
2154
|
PatternCapabilitySource,
|
|
2155
|
+
PluginEventBus,
|
|
2156
|
+
PluginRegistry,
|
|
1889
2157
|
Presets,
|
|
1890
2158
|
PromptBuilder,
|
|
1891
2159
|
RemoteCapabilityFetcher,
|
|
@@ -1896,12 +2164,14 @@ export {
|
|
|
1896
2164
|
SessionManager,
|
|
1897
2165
|
SkillRegistry,
|
|
1898
2166
|
SourcePriority,
|
|
2167
|
+
StaticSettings,
|
|
1899
2168
|
SubAgentTracker,
|
|
1900
2169
|
TRUNCATE_DIR,
|
|
1901
2170
|
TRUNCATE_GLOB,
|
|
1902
2171
|
Tool,
|
|
1903
2172
|
ToolRegistry,
|
|
1904
2173
|
TurnChangeTracker,
|
|
2174
|
+
ValidatedSettings,
|
|
1905
2175
|
advanceAgentTurnState,
|
|
1906
2176
|
applyAgentWorkflowCommitResult,
|
|
1907
2177
|
applyAgentWorkflowModelStepResult,
|
|
@@ -1960,11 +2230,14 @@ export {
|
|
|
1960
2230
|
currentScope,
|
|
1961
2231
|
defaultAgentTaskCheckpointStrategy,
|
|
1962
2232
|
defaultRegistry,
|
|
2233
|
+
definePlugin,
|
|
1963
2234
|
defineServer,
|
|
1964
2235
|
defineTool,
|
|
1965
2236
|
deserializeMessage,
|
|
1966
2237
|
detectModelFamily,
|
|
2238
|
+
discoverAgentProfiles,
|
|
1967
2239
|
discoverInstructions,
|
|
2240
|
+
discoverPlugins,
|
|
1968
2241
|
discoverSkills,
|
|
1969
2242
|
dockerHost,
|
|
1970
2243
|
emptySkillRegistry,
|
|
@@ -1997,6 +2270,8 @@ export {
|
|
|
1997
2270
|
getLeafId,
|
|
1998
2271
|
getModelId,
|
|
1999
2272
|
getNetworkStatus,
|
|
2273
|
+
getPluginLoader,
|
|
2274
|
+
getProjectAgentsDir,
|
|
2000
2275
|
getProjectId,
|
|
2001
2276
|
getProjectSessionsDir,
|
|
2002
2277
|
getProviderCompatibility,
|
|
@@ -2008,16 +2283,20 @@ export {
|
|
|
2008
2283
|
getSessionsDir,
|
|
2009
2284
|
getTemplate,
|
|
2010
2285
|
getToolRisk,
|
|
2286
|
+
getUserAgentsDir,
|
|
2011
2287
|
hasStreamProviderFactory,
|
|
2012
2288
|
httpServer,
|
|
2013
2289
|
inferContextWindow,
|
|
2014
2290
|
inferProvider,
|
|
2015
2291
|
inferResourceType,
|
|
2016
2292
|
isContextOverflowing,
|
|
2293
|
+
isDefinedPlugin,
|
|
2294
|
+
isMarkdownProfile,
|
|
2017
2295
|
isRetryable,
|
|
2018
2296
|
isRetryableCategory,
|
|
2019
2297
|
likelySupportsReasoning,
|
|
2020
2298
|
loadGlobalInstructions,
|
|
2299
|
+
loadPluginModule,
|
|
2021
2300
|
loadResourceContent,
|
|
2022
2301
|
loadSkillContent,
|
|
2023
2302
|
loadSkillMetadata,
|
|
@@ -2026,9 +2305,12 @@ export {
|
|
|
2026
2305
|
needsCustomStreamProvider,
|
|
2027
2306
|
normalizeToolReplayPolicy,
|
|
2028
2307
|
otelMiddleware,
|
|
2308
|
+
parseAgentFrontmatter,
|
|
2029
2309
|
parseFrontmatter,
|
|
2030
2310
|
parseJSONL,
|
|
2311
|
+
parseMarkdownAgent,
|
|
2031
2312
|
parseRetryDelay,
|
|
2313
|
+
parseToolSpec,
|
|
2032
2314
|
plan,
|
|
2033
2315
|
planNextAgentWorkflowOperation,
|
|
2034
2316
|
prepareModelStep,
|
|
@@ -2039,6 +2321,9 @@ export {
|
|
|
2039
2321
|
pruneToolResults,
|
|
2040
2322
|
quick,
|
|
2041
2323
|
recordAgentWorkflowReplayDecision,
|
|
2324
|
+
resetFrameworkAliases,
|
|
2325
|
+
resetPluginLoader,
|
|
2326
|
+
resolveFrameworkAliases,
|
|
2042
2327
|
restoreAgentWorkflowMessage,
|
|
2043
2328
|
restoreAgentWorkflowMessages,
|
|
2044
2329
|
restoreScope,
|
|
@@ -2064,6 +2349,7 @@ export {
|
|
|
2064
2349
|
summarizeEnvironment,
|
|
2065
2350
|
supportsReasoning,
|
|
2066
2351
|
supportsReasoningSync,
|
|
2352
|
+
toAgentProfile,
|
|
2067
2353
|
toJSONL,
|
|
2068
2354
|
toJSONLBatch,
|
|
2069
2355
|
truncateOutput,
|