@cuylabs/agent-core 0.8.0 → 0.10.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/README.md +33 -17
- package/dist/chunk-2O4MCSQS.js +780 -0
- package/dist/chunk-2TTOLHBT.js +198 -0
- package/dist/chunk-5FMSGQVX.js +281 -0
- package/dist/chunk-5NVVNXPQ.js +288 -0
- package/dist/{chunk-CAA7FHIH.js → chunk-6HZBHFOL.js} +3 -103
- package/dist/chunk-CJI7PVS2.js +58 -0
- package/dist/{chunk-N6HWIEEA.js → chunk-CMYN2RCB.js} +278 -61
- package/dist/chunk-FII65CN7.js +117 -0
- package/dist/{chunk-IVUJDISU.js → chunk-GFTW23FV.js} +5 -14
- package/dist/chunk-I6PKJ7XQ.js +292 -0
- package/dist/{chunk-BDBZ3SLK.js → chunk-ICZ66572.js} +48 -4
- package/dist/chunk-KYLPMBHD.js +316 -0
- package/dist/chunk-MXAP4UG6.js +2956 -0
- package/dist/{chunk-RZITT45F.js → chunk-N3VX7FEE.js} +39 -6
- package/dist/{chunk-YSLSEQ6B.js → chunk-NDZWXCBZ.js} +218 -95
- package/dist/{chunk-P6YF7USR.js → chunk-Q742PSH3.js} +23 -38
- package/dist/chunk-QAL3OMI3.js +943 -0
- package/dist/{chunk-RFEKJKTO.js → chunk-RN6WZEUF.js} +330 -280
- package/dist/{chunk-ZXAKHMWH.js → chunk-ROTGCYDW.js} +22 -84
- package/dist/chunk-SPBFQXOT.js +0 -0
- package/dist/{chunk-LRHOS4ZN.js → chunk-SPILYYDF.js} +3 -2
- package/dist/chunk-SSFBF3US.js +602 -0
- package/dist/chunk-SZ2XBPTW.js +8 -0
- package/dist/chunk-T4UIX5D7.js +115 -0
- package/dist/chunk-TIHPYVAJ.js +102 -0
- package/dist/{chunk-YUUJK53A.js → chunk-TOTDGK3P.js} +1 -1
- package/dist/chunk-V4RFNEET.js +563 -0
- package/dist/chunk-VOUEJSW6.js +0 -0
- package/dist/{chunk-4BDA7DQY.js → chunk-WBPOZ7CL.js} +673 -273
- package/dist/chunk-X4VN4GIJ.js +185 -0
- package/dist/dispatch/index.d.ts +93 -0
- package/dist/dispatch/index.js +37 -0
- package/dist/events/index.d.ts +93 -0
- package/dist/events/index.js +6 -0
- package/dist/{runtime → execution}/index.d.ts +120 -34
- package/dist/{runtime → execution}/index.js +18 -13
- package/dist/index-BCqEGzBj.d.ts +251 -0
- package/dist/index.d.ts +490 -122
- package/dist/index.js +2104 -615
- 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 +16 -23
- package/dist/inference/index.js +45 -16
- package/dist/instance-BqV2D5pc.d.ts +5723 -0
- package/dist/logger/index.d.ts +50 -0
- package/dist/logger/index.js +11 -0
- package/dist/mcp/index.d.ts +5 -9
- package/dist/mcp/index.js +2 -3
- package/dist/middleware/index.d.ts +10 -149
- package/dist/middleware/index.js +11 -3
- package/dist/model-messages-B4nK9D1-.d.ts +13 -0
- package/dist/models/index.d.ts +23 -18
- package/dist/models/index.js +48 -11
- package/dist/models/reasoning/index.d.ts +4 -0
- package/dist/{reasoning → models/reasoning}/index.js +3 -3
- package/dist/plugin/index.d.ts +458 -0
- package/dist/plugin/index.js +32 -0
- package/dist/profiles/index.d.ts +55 -0
- package/dist/profiles/index.js +30 -0
- package/dist/prompt/index.d.ts +8 -12
- package/dist/prompt/index.js +3 -2
- package/dist/safety/index.d.ts +109 -14
- package/dist/safety/index.js +59 -3
- package/dist/sandbox/index.d.ts +81 -0
- package/dist/sandbox/index.js +1 -0
- package/dist/skill/index.d.ts +10 -8
- package/dist/skill/index.js +3 -3
- package/dist/storage/index.d.ts +12 -4
- package/dist/storage/index.js +1 -1
- package/dist/subagents/index.d.ts +177 -0
- package/dist/subagents/index.js +78 -0
- package/dist/team/index.d.ts +544 -0
- package/dist/team/index.js +41 -0
- package/dist/tool/host/index.d.ts +41 -0
- package/dist/tool/host/index.js +10 -0
- package/dist/tool/index.d.ts +125 -21
- package/dist/tool/index.js +20 -13
- package/dist/{types-VQgymC1N.d.ts → types-Bj_J8u_W.d.ts} +44 -64
- package/dist/{types-CHiPh8U2.d.ts → types-C_LCeYNg.d.ts} +7 -7
- package/dist/types-RSCv7nQ4.d.ts +59 -0
- package/package.json +58 -53
- package/dist/builder-UpOWQMW3.d.ts +0 -34
- package/dist/chunk-7MUFEN4K.js +0 -559
- package/dist/chunk-7VKQ4WPB.js +0 -73
- package/dist/chunk-BFM2YHNM.js +0 -222
- package/dist/chunk-DWYX7ASF.js +0 -26
- package/dist/chunk-KUVSERLJ.js +0 -50
- package/dist/chunk-N7P4PN3O.js +0 -84
- package/dist/chunk-SDSBEQXG.js +0 -157
- package/dist/chunk-SQU2AJHO.js +0 -305
- package/dist/chunk-VBWWUHWI.js +0 -724
- package/dist/chunk-VEKUXUVF.js +0 -41
- package/dist/chunk-VNQBHPCT.js +0 -398
- package/dist/chunk-WWYYNWEW.js +0 -259
- package/dist/context/index.d.ts +0 -259
- package/dist/context/index.js +0 -26
- package/dist/events-CE72w8W4.d.ts +0 -149
- package/dist/host/index.d.ts +0 -45
- package/dist/host/index.js +0 -8
- package/dist/index-CWSchSql.d.ts +0 -1058
- package/dist/messages-BYWGn8TY.d.ts +0 -110
- package/dist/presets/index.d.ts +0 -53
- package/dist/presets/index.js +0 -28
- package/dist/reasoning/index.d.ts +0 -116
- package/dist/registry-DwYqsQkX.d.ts +0 -164
- package/dist/runner-e2YRcUoX.d.ts +0 -786
- package/dist/scope/index.d.ts +0 -10
- package/dist/scope/index.js +0 -14
- package/dist/session-manager-B_CWGTsl.d.ts +0 -274
- package/dist/signal/index.d.ts +0 -28
- package/dist/signal/index.js +0 -6
- package/dist/sub-agent/index.d.ts +0 -23
- package/dist/sub-agent/index.js +0 -15
- package/dist/tool-BHbyUAy3.d.ts +0 -150
- package/dist/tool-DLXAR9Ce.d.ts +0 -145
- package/dist/tracker-DClqYqTj.d.ts +0 -96
- package/dist/tracking/index.d.ts +0 -111
- package/dist/tracking/index.js +0 -20
- package/dist/types-BfNpU8NS.d.ts +0 -270
- package/dist/types-BnpEOYV-.d.ts +0 -50
- package/dist/types-CQL-SvTn.d.ts +0 -29
- package/dist/types-CWm-7rvB.d.ts +0 -55
- package/dist/types-KKDrdU9Y.d.ts +0 -325
- package/dist/types-QA4WhEfz.d.ts +0 -138
- package/dist/types-QKHHQLLq.d.ts +0 -336
- package/dist/types-YuWV4ag7.d.ts +0 -72
package/dist/index.js
CHANGED
|
@@ -1,59 +1,101 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
2
|
+
DEFAULT_SUBAGENT_CONCURRENCY,
|
|
3
|
+
DEFAULT_SUBAGENT_DEPTH,
|
|
4
|
+
DEFAULT_SUBAGENT_SESSION_PREFIX,
|
|
5
|
+
LOCAL_SUBAGENT_BACKEND,
|
|
6
|
+
SUBAGENT_TOOL_IDS,
|
|
7
|
+
clearInstalledSubAgents,
|
|
8
|
+
configureSubAgents,
|
|
9
|
+
createCloseAgentTool,
|
|
10
|
+
createInvokeAgentTool,
|
|
11
|
+
createSubAgentTools,
|
|
12
|
+
createWaitAgentTool,
|
|
13
|
+
discoverSubAgentRoles,
|
|
14
|
+
formatAsyncSpawnedResult,
|
|
15
|
+
formatCancelledAgentResult,
|
|
16
|
+
formatCloseAlreadyResolvedResult,
|
|
17
|
+
formatCloseMissingAgentResult,
|
|
18
|
+
formatInvalidAgentTypeResult,
|
|
19
|
+
formatMissingAgentsResult,
|
|
20
|
+
formatSpawnBlockedResult,
|
|
21
|
+
formatSyncSubAgentErrorResult,
|
|
22
|
+
formatSyncSubAgentResult,
|
|
23
|
+
formatWaitErrorResult,
|
|
24
|
+
formatWaitResult,
|
|
25
|
+
formatWaitTimeoutResult,
|
|
26
|
+
getConfiguredSubAgents,
|
|
27
|
+
getInstalledSubAgentBackend,
|
|
28
|
+
getProjectSubAgentRolesDir,
|
|
29
|
+
getUserSubAgentRolesDir,
|
|
30
|
+
installLocalSubAgents,
|
|
31
|
+
installSubAgentTools,
|
|
32
|
+
isMarkdownSubAgentRole,
|
|
33
|
+
parseMarkdownSubAgentRole,
|
|
34
|
+
parseSubAgentRoleFrontmatter,
|
|
35
|
+
parseSubAgentToolSpec,
|
|
36
|
+
toSubAgentRole
|
|
37
|
+
} from "./chunk-2O4MCSQS.js";
|
|
26
38
|
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
InMemoryMailboxStore,
|
|
40
|
+
InMemoryTaskBoardStore,
|
|
41
|
+
Mailbox,
|
|
42
|
+
TERMINAL_STATUSES,
|
|
43
|
+
TaskBoard,
|
|
44
|
+
TaskConflictError,
|
|
45
|
+
TeamCoordinator,
|
|
46
|
+
addTokenUsage,
|
|
47
|
+
buildCoordinatorNotificationEvent,
|
|
48
|
+
buildCoordinatorSystemPrompt,
|
|
49
|
+
coordinatorToolDescriptions,
|
|
50
|
+
createTeamCoordinator,
|
|
51
|
+
evaluateCoordinatorRoundTransition,
|
|
52
|
+
formatCoordinatorRoundMessage,
|
|
53
|
+
formatCoordinatorTaskNotifications,
|
|
54
|
+
formatCoordinatorWorkerReports,
|
|
55
|
+
teamPermissionPolicy
|
|
56
|
+
} from "./chunk-MXAP4UG6.js";
|
|
33
57
|
import {
|
|
34
58
|
ToolRegistry,
|
|
59
|
+
createToolSearchTool,
|
|
35
60
|
defaultRegistry
|
|
36
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-KYLPMBHD.js";
|
|
37
62
|
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
63
|
+
ToolHostRegistry,
|
|
64
|
+
defaultToolHostRegistry,
|
|
65
|
+
localHost
|
|
66
|
+
} from "./chunk-X4VN4GIJ.js";
|
|
67
|
+
import {
|
|
68
|
+
LayeredSettings,
|
|
69
|
+
NullSettings,
|
|
70
|
+
PluginEventBus,
|
|
71
|
+
PluginRegistry,
|
|
72
|
+
StaticSettings,
|
|
73
|
+
ValidatedSettings,
|
|
74
|
+
definePlugin,
|
|
75
|
+
discoverPlugins,
|
|
76
|
+
getPluginLoader,
|
|
77
|
+
isDefinedPlugin,
|
|
78
|
+
loadPluginModule,
|
|
79
|
+
resetFrameworkAliases,
|
|
80
|
+
resetPluginLoader,
|
|
81
|
+
resolveFrameworkAliases
|
|
82
|
+
} from "./chunk-QAL3OMI3.js";
|
|
83
|
+
import {
|
|
84
|
+
applyProfile,
|
|
85
|
+
createProfile,
|
|
86
|
+
filterTools,
|
|
87
|
+
mergeProfiles
|
|
88
|
+
} from "./chunk-TIHPYVAJ.js";
|
|
43
89
|
import {
|
|
44
|
-
|
|
45
|
-
applyPreset,
|
|
90
|
+
Profiles,
|
|
46
91
|
careful,
|
|
47
92
|
code,
|
|
48
|
-
createPreset,
|
|
49
93
|
explore,
|
|
50
|
-
filterTools,
|
|
51
|
-
mergePresets,
|
|
52
94
|
plan,
|
|
53
95
|
quick,
|
|
54
96
|
review,
|
|
55
97
|
watch
|
|
56
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-6HZBHFOL.js";
|
|
57
99
|
import {
|
|
58
100
|
DEFAULT_INSTRUCTION_PATTERNS,
|
|
59
101
|
DEFAULT_MAX_DEPTH,
|
|
@@ -75,32 +117,121 @@ import {
|
|
|
75
117
|
getTemplate,
|
|
76
118
|
loadGlobalInstructions,
|
|
77
119
|
summarizeEnvironment
|
|
78
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-GFTW23FV.js";
|
|
121
|
+
import "./chunk-VOUEJSW6.js";
|
|
122
|
+
import {
|
|
123
|
+
createSkillResourceTool,
|
|
124
|
+
createSkillTool,
|
|
125
|
+
createSkillTools
|
|
126
|
+
} from "./chunk-TOTDGK3P.js";
|
|
127
|
+
import {
|
|
128
|
+
DEFAULT_EXTERNAL_DIRS,
|
|
129
|
+
DEFAULT_MAX_SCAN_DEPTH,
|
|
130
|
+
DEFAULT_SKILL_MAX_SIZE,
|
|
131
|
+
SKILL_FILENAME,
|
|
132
|
+
SkillRegistry,
|
|
133
|
+
createSkillRegistry,
|
|
134
|
+
discoverSkills,
|
|
135
|
+
emptySkillRegistry,
|
|
136
|
+
inferResourceType,
|
|
137
|
+
loadResourceContent,
|
|
138
|
+
loadSkillContent,
|
|
139
|
+
loadSkillMetadata,
|
|
140
|
+
parseFrontmatter
|
|
141
|
+
} from "./chunk-SPILYYDF.js";
|
|
142
|
+
import {
|
|
143
|
+
createCompositeDispatchTaskExecutor,
|
|
144
|
+
createDispatchExternalTaskControl,
|
|
145
|
+
createDispatchTaskExecutor,
|
|
146
|
+
createRuntimeDispatchExecutor,
|
|
147
|
+
createRuntimeDispatchTargets,
|
|
148
|
+
ensureNonEmpty,
|
|
149
|
+
mergeInspection
|
|
150
|
+
} from "./chunk-5FMSGQVX.js";
|
|
151
|
+
import {
|
|
152
|
+
DEFAULT_DISPATCH_TOOL_IDS,
|
|
153
|
+
DEFAULT_LOCAL_DISPATCH_CONCURRENCY,
|
|
154
|
+
DEFAULT_LOCAL_DISPATCH_DEPTH,
|
|
155
|
+
DEFAULT_LOCAL_DISPATCH_TITLE_PREFIX,
|
|
156
|
+
DISPATCH_STATES,
|
|
157
|
+
createDispatchTools,
|
|
158
|
+
createLocalDispatchRuntime,
|
|
159
|
+
createSubAgentRunSession,
|
|
160
|
+
ensureSessionLoaded,
|
|
161
|
+
getVisibleSessionMessages,
|
|
162
|
+
repairOrphanedToolCalls
|
|
163
|
+
} from "./chunk-SSFBF3US.js";
|
|
164
|
+
import {
|
|
165
|
+
sleep
|
|
166
|
+
} from "./chunk-SZ2XBPTW.js";
|
|
167
|
+
import {
|
|
168
|
+
MAX_BYTES,
|
|
169
|
+
MAX_LINES,
|
|
170
|
+
Tool,
|
|
171
|
+
normalizeToolReplayPolicy,
|
|
172
|
+
truncateOutput
|
|
173
|
+
} from "./chunk-Q742PSH3.js";
|
|
174
|
+
import {
|
|
175
|
+
FileStorage,
|
|
176
|
+
MemoryStorage,
|
|
177
|
+
STORAGE_VERSION,
|
|
178
|
+
SessionManager,
|
|
179
|
+
buildEntryPath,
|
|
180
|
+
buildMessagesFromEntries,
|
|
181
|
+
configureDefaultSessionManager,
|
|
182
|
+
createMessageEntry,
|
|
183
|
+
createMetadataEntry,
|
|
184
|
+
deserializeMessage,
|
|
185
|
+
extractSessionInfo,
|
|
186
|
+
generateEntryId,
|
|
187
|
+
getDataDir,
|
|
188
|
+
getDefaultSessionManager,
|
|
189
|
+
getGitRootHash,
|
|
190
|
+
getLeafId,
|
|
191
|
+
getProjectId,
|
|
192
|
+
getProjectSessionsDir,
|
|
193
|
+
getSessionsDir,
|
|
194
|
+
parseJSONL,
|
|
195
|
+
serializeMessage,
|
|
196
|
+
toJSONL,
|
|
197
|
+
toJSONLBatch
|
|
198
|
+
} from "./chunk-ICZ66572.js";
|
|
199
|
+
import {
|
|
200
|
+
createEventBus
|
|
201
|
+
} from "./chunk-2TTOLHBT.js";
|
|
79
202
|
import {
|
|
80
203
|
AgentTurnEngine,
|
|
204
|
+
ContextManager,
|
|
81
205
|
ContextOverflowError,
|
|
206
|
+
DEFAULT_CONTEXT_LIMITS,
|
|
82
207
|
DoomLoopError,
|
|
83
208
|
advanceAgentTurnState,
|
|
84
209
|
applyAgentWorkflowCommitResult,
|
|
85
210
|
applyAgentWorkflowModelStepResult,
|
|
86
211
|
applyAgentWorkflowToolBatchResult,
|
|
87
212
|
applyAgentWorkflowToolCallResult,
|
|
213
|
+
applyWorkflowInterventions,
|
|
88
214
|
cloneAgentWorkflowTurnState,
|
|
89
215
|
commitOutput,
|
|
90
216
|
commitStep,
|
|
91
|
-
convertAgentMessagesToModelMessages,
|
|
92
217
|
createAgentTaskRunner,
|
|
93
218
|
createAgentTurnEngine,
|
|
94
219
|
createAgentTurnState,
|
|
95
220
|
createAgentTurnStepCommitBatch,
|
|
96
221
|
createAgentWorkflowTurnState,
|
|
97
222
|
defaultAgentTaskCheckpointStrategy,
|
|
223
|
+
drainWorkflowInterventions,
|
|
224
|
+
estimateConversationTokens,
|
|
225
|
+
estimateMessageTokens,
|
|
226
|
+
estimateTokens,
|
|
98
227
|
failAgentTurnState,
|
|
99
228
|
failAgentWorkflowTurnState,
|
|
229
|
+
findCutPoint,
|
|
230
|
+
getUsableTokenLimit,
|
|
100
231
|
planNextAgentWorkflowOperation,
|
|
101
232
|
prepareModelStep,
|
|
102
233
|
processStepStream,
|
|
103
|
-
|
|
234
|
+
queueWorkflowFollowUps,
|
|
104
235
|
recordAgentWorkflowReplayDecision,
|
|
105
236
|
restoreAgentWorkflowMessage,
|
|
106
237
|
restoreAgentWorkflowMessages,
|
|
@@ -108,88 +239,52 @@ import {
|
|
|
108
239
|
runToolBatch,
|
|
109
240
|
snapshotAgentWorkflowMessage,
|
|
110
241
|
snapshotAgentWorkflowMessages
|
|
111
|
-
} from "./chunk-
|
|
112
|
-
import {
|
|
113
|
-
LocalSignal
|
|
114
|
-
} from "./chunk-KUVSERLJ.js";
|
|
115
|
-
import {
|
|
116
|
-
createSkillResourceTool,
|
|
117
|
-
createSkillTool,
|
|
118
|
-
createSkillTools
|
|
119
|
-
} from "./chunk-YUUJK53A.js";
|
|
242
|
+
} from "./chunk-WBPOZ7CL.js";
|
|
120
243
|
import {
|
|
121
|
-
MAX_BYTES,
|
|
122
|
-
MAX_LINES,
|
|
123
|
-
TRUNCATE_DIR,
|
|
124
|
-
TRUNCATE_GLOB,
|
|
125
|
-
Tool,
|
|
126
|
-
defineTool,
|
|
127
|
-
formatSize,
|
|
128
|
-
normalizeToolReplayPolicy,
|
|
129
|
-
truncateOutput
|
|
130
|
-
} from "./chunk-P6YF7USR.js";
|
|
131
|
-
import {
|
|
132
|
-
DEFAULT_EXTERNAL_DIRS,
|
|
133
|
-
DEFAULT_MAX_SCAN_DEPTH,
|
|
134
|
-
DEFAULT_SKILL_MAX_SIZE,
|
|
135
|
-
SKILL_FILENAME,
|
|
136
|
-
SkillRegistry,
|
|
137
|
-
createSkillRegistry,
|
|
138
|
-
discoverSkills,
|
|
139
|
-
emptySkillRegistry,
|
|
140
|
-
inferResourceType,
|
|
141
|
-
loadResourceContent,
|
|
142
|
-
loadSkillContent,
|
|
143
|
-
loadSkillMetadata,
|
|
144
|
-
parseFrontmatter
|
|
145
|
-
} from "./chunk-LRHOS4ZN.js";
|
|
146
|
-
import {
|
|
147
|
-
ContextManager,
|
|
148
|
-
DEFAULT_CONTEXT_LIMITS,
|
|
149
|
-
PRUNE_PROTECTED_TOOLS,
|
|
150
|
-
estimateConversationTokens,
|
|
151
|
-
estimateMessageTokens,
|
|
152
|
-
estimateTokens,
|
|
153
|
-
findCutPoint,
|
|
154
|
-
generateSummary,
|
|
155
|
-
isContextOverflowing,
|
|
156
|
-
pruneContext,
|
|
157
|
-
pruneToolResults,
|
|
158
|
-
shouldPruneContext
|
|
159
|
-
} from "./chunk-WWYYNWEW.js";
|
|
160
|
-
import {
|
|
161
|
-
dockerHost,
|
|
162
|
-
localHost
|
|
163
|
-
} from "./chunk-VNQBHPCT.js";
|
|
164
|
-
import {
|
|
165
|
-
DEFAULT_MAX_OUTPUT_TOKENS,
|
|
166
244
|
DEFAULT_RETRY_CONFIG,
|
|
167
245
|
Inference,
|
|
168
|
-
|
|
169
|
-
OUTPUT_TOKEN_MAX,
|
|
246
|
+
buildModelCallContext,
|
|
170
247
|
buildToolSet,
|
|
171
248
|
calculateDelay,
|
|
249
|
+
convertAgentMessagesToModelMessages,
|
|
172
250
|
createRetryHandler,
|
|
173
251
|
createRetryState,
|
|
174
252
|
shouldRetry,
|
|
175
|
-
sleep,
|
|
176
253
|
stream,
|
|
177
254
|
streamOnce,
|
|
178
255
|
streamStep,
|
|
179
256
|
withRetry
|
|
180
|
-
} from "./chunk-
|
|
181
|
-
import {
|
|
182
|
-
executeAgentToolCall
|
|
183
|
-
} from "./chunk-7VKQ4WPB.js";
|
|
257
|
+
} from "./chunk-CMYN2RCB.js";
|
|
184
258
|
import {
|
|
259
|
+
PRUNE_PROTECTED_TOOLS,
|
|
260
|
+
accumulateUsage,
|
|
261
|
+
currentScope,
|
|
262
|
+
executeAgentToolCall,
|
|
185
263
|
extractFilePathsFromArgs,
|
|
264
|
+
restoreScope,
|
|
186
265
|
shouldCaptureBaseline,
|
|
187
|
-
|
|
188
|
-
|
|
266
|
+
snapshotScope,
|
|
267
|
+
streamWithinScope,
|
|
268
|
+
withinScope
|
|
269
|
+
} from "./chunk-5NVVNXPQ.js";
|
|
270
|
+
import {
|
|
271
|
+
LLMError,
|
|
272
|
+
getErrorCategory,
|
|
273
|
+
getRetryDelay,
|
|
274
|
+
isRetryable,
|
|
275
|
+
isRetryableCategory,
|
|
276
|
+
parseRetryDelay
|
|
277
|
+
} from "./chunk-N3VX7FEE.js";
|
|
189
278
|
import {
|
|
279
|
+
CacheCapabilitySource,
|
|
280
|
+
CapabilityCache,
|
|
190
281
|
EXTENDED_LEVELS,
|
|
191
282
|
FIXED_LEVELS,
|
|
283
|
+
ModelCapabilityResolver,
|
|
284
|
+
RemoteCapabilityFetcher,
|
|
285
|
+
RemoteCapabilitySource,
|
|
192
286
|
STANDARD_LEVELS,
|
|
287
|
+
applyCapabilityOverride,
|
|
193
288
|
buildAnthropicOptions,
|
|
194
289
|
buildBedrockOptions,
|
|
195
290
|
buildGoogleOptions,
|
|
@@ -199,75 +294,717 @@ import {
|
|
|
199
294
|
buildReasoningOptions,
|
|
200
295
|
buildReasoningOptionsSync,
|
|
201
296
|
buildXAIOptions,
|
|
297
|
+
configureResolver,
|
|
298
|
+
createResolver,
|
|
299
|
+
findCapabilityOverride,
|
|
300
|
+
getDefaultResolver,
|
|
301
|
+
getNetworkStatus,
|
|
202
302
|
getProviderOptionsKey,
|
|
203
303
|
getReasoningConfig,
|
|
204
304
|
getReasoningConfigSync,
|
|
205
305
|
shouldIncludeReasoningSummary,
|
|
206
306
|
supportsReasoning,
|
|
207
307
|
supportsReasoningSync
|
|
208
|
-
} from "./chunk-
|
|
209
|
-
import
|
|
210
|
-
createScope,
|
|
211
|
-
currentScope,
|
|
212
|
-
restoreScope,
|
|
213
|
-
snapshotScope,
|
|
214
|
-
streamWithinScope,
|
|
215
|
-
withinScope
|
|
216
|
-
} from "./chunk-N7P4PN3O.js";
|
|
217
|
-
import {
|
|
218
|
-
LLMError,
|
|
219
|
-
getErrorCategory,
|
|
220
|
-
getRetryDelay,
|
|
221
|
-
isRetryable,
|
|
222
|
-
isRetryableCategory,
|
|
223
|
-
parseRetryDelay
|
|
224
|
-
} from "./chunk-RZITT45F.js";
|
|
308
|
+
} from "./chunk-RN6WZEUF.js";
|
|
309
|
+
import "./chunk-SPBFQXOT.js";
|
|
225
310
|
import {
|
|
226
311
|
createMCPManager,
|
|
227
|
-
defineServer,
|
|
228
312
|
httpServer,
|
|
229
313
|
sseServer,
|
|
230
314
|
stdioServer
|
|
231
|
-
} from "./chunk-
|
|
315
|
+
} from "./chunk-ROTGCYDW.js";
|
|
232
316
|
import {
|
|
233
317
|
MiddlewareRunner,
|
|
234
318
|
approvalMiddleware,
|
|
235
319
|
createTelemetryConfig,
|
|
320
|
+
isApprovalMiddleware,
|
|
236
321
|
otelMiddleware,
|
|
237
322
|
promptCacheMiddleware
|
|
238
|
-
} from "./chunk-
|
|
323
|
+
} from "./chunk-NDZWXCBZ.js";
|
|
239
324
|
import {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
325
|
+
DEFAULT_AGENT_NAME,
|
|
326
|
+
DEFAULT_MAX_STEPS,
|
|
327
|
+
DEFAULT_MAX_TOKENS,
|
|
328
|
+
DEFAULT_SYSTEM_PROMPT,
|
|
329
|
+
isBlockedModelCall,
|
|
330
|
+
resolveAgentDefaults,
|
|
331
|
+
sandboxDefaultsProvider
|
|
332
|
+
} from "./chunk-CJI7PVS2.js";
|
|
245
333
|
import {
|
|
246
|
-
CacheCapabilitySource,
|
|
247
|
-
CapabilityCache,
|
|
248
334
|
DEFAULT_RESOLVER_OPTIONS,
|
|
249
|
-
ModelCapabilityResolver,
|
|
250
335
|
PatternCapabilitySource,
|
|
251
|
-
RemoteCapabilityFetcher,
|
|
252
|
-
RemoteCapabilitySource,
|
|
253
336
|
SourcePriority,
|
|
254
|
-
applyCapabilityOverride,
|
|
255
|
-
configureResolver,
|
|
256
|
-
createResolver,
|
|
257
337
|
extractModelId,
|
|
258
338
|
extractProvider,
|
|
259
|
-
|
|
260
|
-
getDefaultResolver,
|
|
261
|
-
getNetworkStatus,
|
|
339
|
+
getModelId,
|
|
262
340
|
getProviderCompatibility,
|
|
341
|
+
getProviderId,
|
|
263
342
|
inferContextWindow,
|
|
264
343
|
inferProvider,
|
|
265
344
|
likelySupportsReasoning
|
|
266
|
-
} from "./chunk-
|
|
345
|
+
} from "./chunk-I6PKJ7XQ.js";
|
|
267
346
|
import {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
347
|
+
ApprovalDeniedError,
|
|
348
|
+
ApprovalTimeoutError,
|
|
349
|
+
allApprovalConditions,
|
|
350
|
+
anyApprovalConditions,
|
|
351
|
+
approvalRequestsOverlap,
|
|
352
|
+
buildApprovalRuleContext,
|
|
353
|
+
createApprovalCorrection,
|
|
354
|
+
createApprovalHandler,
|
|
355
|
+
createApprovalPolicyPreset,
|
|
356
|
+
createConditionalApprovalRule,
|
|
357
|
+
createDangerouslyAllowAllApprovalPolicy,
|
|
358
|
+
createHeadlessDenyApprovalPolicy,
|
|
359
|
+
createInteractiveApprovalPolicy,
|
|
360
|
+
createRememberedApprovalRules,
|
|
361
|
+
createRiskTierApprovalPolicy,
|
|
362
|
+
createThresholdApprovalRule,
|
|
363
|
+
createTrustedSessionApprovalPolicy,
|
|
364
|
+
formatApprovalDeniedReason,
|
|
365
|
+
getToolRisk,
|
|
366
|
+
matchApprovalArgValue,
|
|
367
|
+
matchApprovalNumericArg,
|
|
368
|
+
matchApprovalRisks,
|
|
369
|
+
matchApprovalSessions,
|
|
370
|
+
matchApprovalStringPrefixes,
|
|
371
|
+
normalizeApprovalCascadePolicy,
|
|
372
|
+
normalizeRememberScopes,
|
|
373
|
+
selectRememberScope,
|
|
374
|
+
shouldCascadeApprovalDecision
|
|
375
|
+
} from "./chunk-V4RFNEET.js";
|
|
376
|
+
import {
|
|
377
|
+
describeApprovalOperation,
|
|
378
|
+
extractApprovalPatterns,
|
|
379
|
+
getRequiredToolHost,
|
|
380
|
+
matchApprovalPattern,
|
|
381
|
+
requiresToolHost,
|
|
382
|
+
resolveCapability
|
|
383
|
+
} from "./chunk-FII65CN7.js";
|
|
384
|
+
import {
|
|
385
|
+
createConsoleLogger,
|
|
386
|
+
createFileLogger,
|
|
387
|
+
silentLogger
|
|
388
|
+
} from "./chunk-T4UIX5D7.js";
|
|
389
|
+
|
|
390
|
+
// src/tracking/turn-tracker/tracker.ts
|
|
391
|
+
import { spawn } from "child_process";
|
|
392
|
+
import { normalize, relative as relative2, resolve } from "path";
|
|
393
|
+
|
|
394
|
+
// src/tracking/turn-tracker/diff.ts
|
|
395
|
+
import { createHash } from "crypto";
|
|
396
|
+
import { mkdir, readFile, stat, unlink, writeFile } from "fs/promises";
|
|
397
|
+
import { dirname, relative } from "path";
|
|
398
|
+
async function captureTurnFileBaseline(absPath) {
|
|
399
|
+
try {
|
|
400
|
+
const content = await readFile(absPath, "utf-8");
|
|
401
|
+
const stats = await stat(absPath);
|
|
402
|
+
return {
|
|
403
|
+
path: absPath,
|
|
404
|
+
content,
|
|
405
|
+
mode: stats.mode,
|
|
406
|
+
hash: hashTurnTrackerContent(content),
|
|
407
|
+
capturedAt: /* @__PURE__ */ new Date()
|
|
408
|
+
};
|
|
409
|
+
} catch (error) {
|
|
410
|
+
if (error.code === "ENOENT") {
|
|
411
|
+
return {
|
|
412
|
+
path: absPath,
|
|
413
|
+
content: null,
|
|
414
|
+
mode: null,
|
|
415
|
+
hash: null,
|
|
416
|
+
capturedAt: /* @__PURE__ */ new Date()
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
throw error;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
async function restoreTurnTrackedFile(absPath, baseline) {
|
|
423
|
+
if (baseline.content === null) {
|
|
424
|
+
try {
|
|
425
|
+
await unlink(absPath);
|
|
426
|
+
} catch (error) {
|
|
427
|
+
if (error.code !== "ENOENT") {
|
|
428
|
+
throw error;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
await mkdir(dirname(absPath), { recursive: true });
|
|
434
|
+
await writeFile(absPath, baseline.content, {
|
|
435
|
+
mode: baseline.mode ?? void 0
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
async function computeTurnTrackerFileChange(options) {
|
|
439
|
+
const { cwd, absPath, baseline, preferGitDiff, canUseGitDiff } = options;
|
|
440
|
+
const relPath = relative(cwd, absPath);
|
|
441
|
+
const currentContent = await readTrackedFileContent(absPath);
|
|
442
|
+
let type;
|
|
443
|
+
if (baseline.content === null && currentContent === null) {
|
|
444
|
+
type = "unchanged";
|
|
445
|
+
} else if (baseline.content === null && currentContent !== null) {
|
|
446
|
+
type = "created";
|
|
447
|
+
} else if (baseline.content !== null && currentContent === null) {
|
|
448
|
+
type = "deleted";
|
|
449
|
+
} else if (baseline.content === currentContent) {
|
|
450
|
+
type = "unchanged";
|
|
451
|
+
} else {
|
|
452
|
+
type = "modified";
|
|
453
|
+
}
|
|
454
|
+
if (type === "unchanged") {
|
|
455
|
+
return { path: relPath, type, additions: 0, deletions: 0 };
|
|
456
|
+
}
|
|
457
|
+
const diff = await generateTurnTrackerDiff({
|
|
458
|
+
relPath,
|
|
459
|
+
oldContent: baseline.content,
|
|
460
|
+
newContent: currentContent,
|
|
461
|
+
preferGitDiff,
|
|
462
|
+
canUseGitDiff
|
|
463
|
+
});
|
|
464
|
+
const { additions, deletions } = countUnifiedDiffStats(diff);
|
|
465
|
+
return {
|
|
466
|
+
path: relPath,
|
|
467
|
+
type,
|
|
468
|
+
additions,
|
|
469
|
+
deletions,
|
|
470
|
+
diff
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
async function readTrackedFileContent(absPath) {
|
|
474
|
+
try {
|
|
475
|
+
return await readFile(absPath, "utf-8");
|
|
476
|
+
} catch (error) {
|
|
477
|
+
if (error.code === "ENOENT") {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
throw error;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
async function generateTurnTrackerDiff(options) {
|
|
484
|
+
const { relPath, oldContent, newContent, preferGitDiff, canUseGitDiff } = options;
|
|
485
|
+
const oldLines = (oldContent ?? "").split("\n");
|
|
486
|
+
const newLines = (newContent ?? "").split("\n");
|
|
487
|
+
if (preferGitDiff && canUseGitDiff) {
|
|
488
|
+
const gitDiff = await createGitStyleDiffPlaceholder();
|
|
489
|
+
if (gitDiff) {
|
|
490
|
+
return gitDiff;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return buildSimpleUnifiedDiff({
|
|
494
|
+
path: relPath,
|
|
495
|
+
oldLines,
|
|
496
|
+
newLines,
|
|
497
|
+
wasCreated: oldContent === null,
|
|
498
|
+
wasDeleted: newContent === null
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
function buildSimpleUnifiedDiff(options) {
|
|
502
|
+
const { path, oldLines, newLines, wasCreated, wasDeleted } = options;
|
|
503
|
+
const header = [
|
|
504
|
+
`--- a/${path}${wasCreated ? " (new file)" : ""}`,
|
|
505
|
+
`+++ b/${path}${wasDeleted ? " (deleted)" : ""}`
|
|
506
|
+
];
|
|
507
|
+
const hunks = [];
|
|
508
|
+
if (wasCreated) {
|
|
509
|
+
hunks.push(`@@ -0,0 +1,${newLines.length} @@`);
|
|
510
|
+
for (const line of newLines) {
|
|
511
|
+
hunks.push(`+${line}`);
|
|
512
|
+
}
|
|
513
|
+
} else if (wasDeleted) {
|
|
514
|
+
hunks.push(`@@ -1,${oldLines.length} +0,0 @@`);
|
|
515
|
+
for (const line of oldLines) {
|
|
516
|
+
hunks.push(`-${line}`);
|
|
517
|
+
}
|
|
518
|
+
} else {
|
|
519
|
+
hunks.push(`@@ -1,${oldLines.length} +1,${newLines.length} @@`);
|
|
520
|
+
for (const line of oldLines) {
|
|
521
|
+
hunks.push(`-${line}`);
|
|
522
|
+
}
|
|
523
|
+
for (const line of newLines) {
|
|
524
|
+
hunks.push(`+${line}`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
return [...header, ...hunks].join("\n");
|
|
528
|
+
}
|
|
529
|
+
function countUnifiedDiffStats(diff) {
|
|
530
|
+
let additions = 0;
|
|
531
|
+
let deletions = 0;
|
|
532
|
+
for (const line of diff.split("\n")) {
|
|
533
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
534
|
+
additions++;
|
|
535
|
+
} else if (line.startsWith("-") && !line.startsWith("---")) {
|
|
536
|
+
deletions++;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return { additions, deletions };
|
|
540
|
+
}
|
|
541
|
+
function hashTurnTrackerContent(content) {
|
|
542
|
+
return createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
543
|
+
}
|
|
544
|
+
async function createGitStyleDiffPlaceholder() {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// src/tracking/turn-tracker/tracker.ts
|
|
549
|
+
var TurnChangeTracker = class {
|
|
550
|
+
config;
|
|
551
|
+
currentTurn = null;
|
|
552
|
+
gitDetected = null;
|
|
553
|
+
log;
|
|
554
|
+
constructor(config, logger) {
|
|
555
|
+
this.config = {
|
|
556
|
+
cwd: resolve(config.cwd),
|
|
557
|
+
useGit: config.useGit ?? true,
|
|
558
|
+
maxTrackedFiles: config.maxTrackedFiles ?? 100
|
|
559
|
+
};
|
|
560
|
+
this.log = logger?.child("turn-tracker") ?? silentLogger;
|
|
561
|
+
}
|
|
562
|
+
startTurn(turnId) {
|
|
563
|
+
if (this.currentTurn && !this.currentTurn.completed) {
|
|
564
|
+
this.currentTurn.completed = true;
|
|
565
|
+
}
|
|
566
|
+
this.currentTurn = {
|
|
567
|
+
id: turnId,
|
|
568
|
+
startedAt: /* @__PURE__ */ new Date(),
|
|
569
|
+
baselines: /* @__PURE__ */ new Map(),
|
|
570
|
+
completed: false
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
async endTurn() {
|
|
574
|
+
if (!this.currentTurn) {
|
|
575
|
+
return {
|
|
576
|
+
turnId: "",
|
|
577
|
+
files: [],
|
|
578
|
+
totalTracked: 0,
|
|
579
|
+
additions: 0,
|
|
580
|
+
deletions: 0,
|
|
581
|
+
diff: null,
|
|
582
|
+
duration: 0
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
const turn = this.currentTurn;
|
|
586
|
+
turn.completed = true;
|
|
587
|
+
const files = [];
|
|
588
|
+
let additions = 0;
|
|
589
|
+
let deletions = 0;
|
|
590
|
+
const diffs = [];
|
|
591
|
+
for (const [absPath, baseline] of turn.baselines) {
|
|
592
|
+
const change = await this.computeFileChange(absPath, baseline);
|
|
593
|
+
files.push(change);
|
|
594
|
+
additions += change.additions;
|
|
595
|
+
deletions += change.deletions;
|
|
596
|
+
if (change.diff) {
|
|
597
|
+
diffs.push(change.diff);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
files.sort((left, right) => left.path.localeCompare(right.path));
|
|
601
|
+
return {
|
|
602
|
+
turnId: turn.id,
|
|
603
|
+
files,
|
|
604
|
+
totalTracked: turn.baselines.size,
|
|
605
|
+
additions,
|
|
606
|
+
deletions,
|
|
607
|
+
diff: diffs.length > 0 ? diffs.join("\n") : null,
|
|
608
|
+
duration: Date.now() - turn.startedAt.getTime()
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
isInTurn() {
|
|
612
|
+
return this.currentTurn !== null && !this.currentTurn.completed;
|
|
613
|
+
}
|
|
614
|
+
getCurrentTurnId() {
|
|
615
|
+
return this.currentTurn?.id ?? null;
|
|
616
|
+
}
|
|
617
|
+
async beforeWrite(filePath) {
|
|
618
|
+
if (!this.currentTurn || this.currentTurn.completed) {
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
const absPath = resolve(this.config.cwd, filePath);
|
|
622
|
+
const normalizedPath = normalize(absPath);
|
|
623
|
+
if (this.currentTurn.baselines.has(normalizedPath)) {
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
if (this.currentTurn.baselines.size >= this.config.maxTrackedFiles) {
|
|
627
|
+
this.log.warn(
|
|
628
|
+
`Max tracked files (${this.config.maxTrackedFiles}) reached, skipping: ${filePath}`
|
|
629
|
+
);
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
632
|
+
const baseline = await captureTurnFileBaseline(normalizedPath);
|
|
633
|
+
this.currentTurn.baselines.set(normalizedPath, baseline);
|
|
634
|
+
return true;
|
|
635
|
+
}
|
|
636
|
+
getTrackedFiles() {
|
|
637
|
+
if (!this.currentTurn) {
|
|
638
|
+
return [];
|
|
639
|
+
}
|
|
640
|
+
return Array.from(this.currentTurn.baselines.keys()).map(
|
|
641
|
+
(path) => relative2(this.config.cwd, path)
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
isTracking(filePath) {
|
|
645
|
+
if (!this.currentTurn) {
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
const absPath = resolve(this.config.cwd, filePath);
|
|
649
|
+
return this.currentTurn.baselines.has(normalize(absPath));
|
|
650
|
+
}
|
|
651
|
+
async getDiff() {
|
|
652
|
+
if (!this.currentTurn || this.currentTurn.baselines.size === 0) {
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
const diffs = [];
|
|
656
|
+
for (const [absPath, baseline] of this.currentTurn.baselines) {
|
|
657
|
+
const change = await this.computeFileChange(absPath, baseline);
|
|
658
|
+
if (change.diff) {
|
|
659
|
+
diffs.push(change.diff);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
return diffs.length > 0 ? diffs.join("\n") : null;
|
|
663
|
+
}
|
|
664
|
+
async getFileDiff(filePath) {
|
|
665
|
+
if (!this.currentTurn) {
|
|
666
|
+
return null;
|
|
667
|
+
}
|
|
668
|
+
const absPath = resolve(this.config.cwd, filePath);
|
|
669
|
+
const baseline = this.currentTurn.baselines.get(normalize(absPath));
|
|
670
|
+
if (!baseline) {
|
|
671
|
+
return null;
|
|
672
|
+
}
|
|
673
|
+
const change = await this.computeFileChange(absPath, baseline);
|
|
674
|
+
return change.diff ?? null;
|
|
675
|
+
}
|
|
676
|
+
async undoTurn() {
|
|
677
|
+
if (!this.currentTurn) {
|
|
678
|
+
return { restored: [], failed: [] };
|
|
679
|
+
}
|
|
680
|
+
const result = { restored: [], failed: [] };
|
|
681
|
+
for (const [absPath, baseline] of this.currentTurn.baselines) {
|
|
682
|
+
const relPath = relative2(this.config.cwd, absPath);
|
|
683
|
+
try {
|
|
684
|
+
await restoreTurnTrackedFile(absPath, baseline);
|
|
685
|
+
result.restored.push(relPath);
|
|
686
|
+
} catch (error) {
|
|
687
|
+
result.failed.push({
|
|
688
|
+
path: relPath,
|
|
689
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
return result;
|
|
694
|
+
}
|
|
695
|
+
async undoFiles(filePaths) {
|
|
696
|
+
if (!this.currentTurn) {
|
|
697
|
+
return { restored: [], failed: [] };
|
|
698
|
+
}
|
|
699
|
+
const result = { restored: [], failed: [] };
|
|
700
|
+
for (const filePath of filePaths) {
|
|
701
|
+
const absPath = resolve(this.config.cwd, filePath);
|
|
702
|
+
const normalizedPath = normalize(absPath);
|
|
703
|
+
const baseline = this.currentTurn.baselines.get(normalizedPath);
|
|
704
|
+
if (!baseline) {
|
|
705
|
+
result.failed.push({
|
|
706
|
+
path: filePath,
|
|
707
|
+
reason: "File not tracked in current turn"
|
|
708
|
+
});
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
try {
|
|
712
|
+
await restoreTurnTrackedFile(absPath, baseline);
|
|
713
|
+
result.restored.push(filePath);
|
|
714
|
+
} catch (error) {
|
|
715
|
+
result.failed.push({
|
|
716
|
+
path: filePath,
|
|
717
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return result;
|
|
722
|
+
}
|
|
723
|
+
async computeFileChange(absPath, baseline) {
|
|
724
|
+
return await computeTurnTrackerFileChange({
|
|
725
|
+
cwd: this.config.cwd,
|
|
726
|
+
absPath,
|
|
727
|
+
baseline,
|
|
728
|
+
preferGitDiff: this.config.useGit,
|
|
729
|
+
canUseGitDiff: await this.isInGitRepo()
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
async isInGitRepo() {
|
|
733
|
+
if (!this.config.useGit) {
|
|
734
|
+
return false;
|
|
735
|
+
}
|
|
736
|
+
if (this.gitDetected !== null) {
|
|
737
|
+
return this.gitDetected;
|
|
738
|
+
}
|
|
739
|
+
return await new Promise((resolvePromise) => {
|
|
740
|
+
const proc = spawn("git", ["rev-parse", "--git-dir"], {
|
|
741
|
+
cwd: this.config.cwd,
|
|
742
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
743
|
+
});
|
|
744
|
+
proc.on("close", (code2) => {
|
|
745
|
+
this.gitDetected = code2 === 0;
|
|
746
|
+
resolvePromise(this.gitDetected);
|
|
747
|
+
});
|
|
748
|
+
proc.on("error", () => {
|
|
749
|
+
this.gitDetected = false;
|
|
750
|
+
resolvePromise(false);
|
|
751
|
+
});
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
function createTurnTracker(config, logger) {
|
|
756
|
+
return new TurnChangeTracker(config, logger);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// src/intervention/intervention.ts
|
|
760
|
+
var InterventionController = class {
|
|
761
|
+
/** Immediate interventions — applied at the next step boundary */
|
|
762
|
+
immediate = [];
|
|
763
|
+
/** Deferred messages — held until the turn completes */
|
|
764
|
+
deferred = [];
|
|
765
|
+
/**
|
|
766
|
+
* Callback fired when an intervention is wired into a step.
|
|
767
|
+
* Set by the Agent before starting a chat turn, cleared after.
|
|
768
|
+
*/
|
|
769
|
+
onApplied;
|
|
770
|
+
/** Callback fired when a deferred follow-up is queued. */
|
|
771
|
+
onDeferredQueued;
|
|
772
|
+
// ---------------------------------------------------------------------------
|
|
773
|
+
// Immediate interventions (mid-turn redirect)
|
|
774
|
+
// ---------------------------------------------------------------------------
|
|
775
|
+
/**
|
|
776
|
+
* Inject a message at the next LLM step boundary.
|
|
777
|
+
*
|
|
778
|
+
* The message is appended as a user message to the conversation
|
|
779
|
+
* before the next LLM call in the current multi-step turn. The
|
|
780
|
+
* LLM will see it and can adjust its behavior accordingly.
|
|
781
|
+
*
|
|
782
|
+
* Safe to call from any async context while `chat()` is running.
|
|
783
|
+
* If called when no turn is active, the message will be picked up
|
|
784
|
+
* by the first step of the next `chat()` call.
|
|
785
|
+
*
|
|
786
|
+
* @param message - The user message to inject
|
|
787
|
+
* @returns Intervention ID for tracking
|
|
788
|
+
*/
|
|
789
|
+
intervene(message) {
|
|
790
|
+
const id = crypto.randomUUID();
|
|
791
|
+
this.immediate.push(
|
|
792
|
+
Object.freeze({ id, message, createdAt: /* @__PURE__ */ new Date() })
|
|
793
|
+
);
|
|
794
|
+
return id;
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Drain and return all pending immediate interventions.
|
|
798
|
+
* The internal queue is cleared atomically.
|
|
799
|
+
*
|
|
800
|
+
* @internal Called by the LLM stream's `prepareStep` hook
|
|
801
|
+
*/
|
|
802
|
+
drainImmediate() {
|
|
803
|
+
if (this.immediate.length === 0) return [];
|
|
804
|
+
return this.immediate.splice(0);
|
|
805
|
+
}
|
|
806
|
+
/** Adopt existing immediate interventions without changing their IDs. */
|
|
807
|
+
adoptImmediate(items) {
|
|
808
|
+
if (items.length === 0) return;
|
|
809
|
+
this.immediate.push(...items);
|
|
810
|
+
}
|
|
811
|
+
/** Whether there are pending immediate interventions */
|
|
812
|
+
get hasPending() {
|
|
813
|
+
return this.immediate.length > 0;
|
|
814
|
+
}
|
|
815
|
+
/** Number of pending immediate interventions */
|
|
816
|
+
get pendingCount() {
|
|
817
|
+
return this.immediate.length;
|
|
818
|
+
}
|
|
819
|
+
// ---------------------------------------------------------------------------
|
|
820
|
+
// Deferred messages (after-turn follow-ups)
|
|
821
|
+
// ---------------------------------------------------------------------------
|
|
822
|
+
/**
|
|
823
|
+
* Queue a message for after the current turn completes.
|
|
824
|
+
*
|
|
825
|
+
* Unlike `intervene()`, this does **not** inject mid-turn. The
|
|
826
|
+
* message is held and available via `drainDeferred()` after
|
|
827
|
+
* `chat()` finishes. The consumer decides whether to send it
|
|
828
|
+
* as a new turn.
|
|
829
|
+
*
|
|
830
|
+
* @param message - The message to queue
|
|
831
|
+
* @returns Intervention ID for tracking
|
|
832
|
+
*/
|
|
833
|
+
queueNext(message) {
|
|
834
|
+
const id = crypto.randomUUID();
|
|
835
|
+
const queued = Object.freeze({ id, message, createdAt: /* @__PURE__ */ new Date() });
|
|
836
|
+
this.deferred.push(queued);
|
|
837
|
+
this.onDeferredQueued?.(queued);
|
|
838
|
+
return id;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Drain and return all deferred messages.
|
|
842
|
+
* The internal queue is cleared atomically.
|
|
843
|
+
*/
|
|
844
|
+
drainDeferred() {
|
|
845
|
+
if (this.deferred.length === 0) return [];
|
|
846
|
+
return this.deferred.splice(0);
|
|
847
|
+
}
|
|
848
|
+
/** Adopt existing deferred interventions without changing their IDs. */
|
|
849
|
+
adoptDeferred(items) {
|
|
850
|
+
if (items.length === 0) return;
|
|
851
|
+
this.deferred.push(...items);
|
|
852
|
+
}
|
|
853
|
+
/** Whether there are deferred messages */
|
|
854
|
+
get hasDeferred() {
|
|
855
|
+
return this.deferred.length > 0;
|
|
856
|
+
}
|
|
857
|
+
/** Number of deferred messages */
|
|
858
|
+
get deferredCount() {
|
|
859
|
+
return this.deferred.length;
|
|
860
|
+
}
|
|
861
|
+
// ---------------------------------------------------------------------------
|
|
862
|
+
// Housekeeping
|
|
863
|
+
// ---------------------------------------------------------------------------
|
|
864
|
+
/** Clear all queues (immediate + deferred) */
|
|
865
|
+
clear() {
|
|
866
|
+
this.immediate.length = 0;
|
|
867
|
+
this.deferred.length = 0;
|
|
868
|
+
}
|
|
869
|
+
/** Reset the controller for a new turn (clears onApplied, keeps queues) */
|
|
870
|
+
resetCallbacks() {
|
|
871
|
+
this.onApplied = void 0;
|
|
872
|
+
this.onDeferredQueued = void 0;
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
|
|
876
|
+
// src/agent/runtime-config.ts
|
|
877
|
+
function createAgentToolRecord(tools) {
|
|
878
|
+
const toolRecord = {};
|
|
879
|
+
for (const [id, tool] of tools) {
|
|
880
|
+
toolRecord[id] = tool;
|
|
881
|
+
}
|
|
882
|
+
return toolRecord;
|
|
883
|
+
}
|
|
884
|
+
function buildFallbackCompactionSummary(messages) {
|
|
885
|
+
const excerpt = messages.map((message) => {
|
|
886
|
+
const role = message.role.toUpperCase();
|
|
887
|
+
const content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
|
|
888
|
+
return `[${role}] ${content}`;
|
|
889
|
+
}).join("\n\n");
|
|
890
|
+
const trimmed = excerpt.length > 8e3 ? `${excerpt.slice(0, 8e3)}
|
|
891
|
+
|
|
892
|
+
...[truncated during compaction]` : excerpt;
|
|
893
|
+
return trimmed.length > 0 ? trimmed : "Earlier conversation context was compacted.";
|
|
894
|
+
}
|
|
895
|
+
async function compactAgentContext(options) {
|
|
896
|
+
const { contextManager, sessions, logger } = options;
|
|
897
|
+
const log = logger ?? silentLogger;
|
|
898
|
+
const messages = getVisibleSessionMessages(sessions);
|
|
899
|
+
if (!contextManager.shouldPrune(messages)) {
|
|
900
|
+
return {
|
|
901
|
+
removedCount: 0,
|
|
902
|
+
tokensRemoved: 0,
|
|
903
|
+
summarized: false,
|
|
904
|
+
summary: void 0
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
const tokensBefore = estimateConversationTokens(messages);
|
|
908
|
+
let removedCount = 0;
|
|
909
|
+
let summarized = false;
|
|
910
|
+
let summary;
|
|
911
|
+
try {
|
|
912
|
+
const result = await contextManager.prune(messages);
|
|
913
|
+
removedCount = result.removedCount;
|
|
914
|
+
summarized = result.summarized;
|
|
915
|
+
summary = result.summary;
|
|
916
|
+
} catch (pruneError) {
|
|
917
|
+
log.warn("Context compaction LLM summarisation failed, using fallback", {
|
|
918
|
+
error: pruneError instanceof Error ? pruneError.message : String(pruneError)
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
if (removedCount === 0) {
|
|
922
|
+
removedCount = findCutPoint(
|
|
923
|
+
messages,
|
|
924
|
+
contextManager.getLimits().protectedTokens
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
if (removedCount === 0) {
|
|
928
|
+
return {
|
|
929
|
+
removedCount: 0,
|
|
930
|
+
tokensRemoved: 0,
|
|
931
|
+
summarized: false,
|
|
932
|
+
summary: void 0
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
const summaryText = summary ?? buildFallbackCompactionSummary(messages.slice(0, removedCount));
|
|
936
|
+
const keptMessages = messages.slice(removedCount);
|
|
937
|
+
const persistedMessages = [
|
|
938
|
+
{
|
|
939
|
+
id: "compaction-preview",
|
|
940
|
+
role: "system",
|
|
941
|
+
content: `## Previous Conversation Summary
|
|
942
|
+
|
|
943
|
+
${summaryText}`,
|
|
944
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
945
|
+
},
|
|
946
|
+
...keptMessages
|
|
947
|
+
];
|
|
948
|
+
const tokensAfter = estimateConversationTokens(persistedMessages);
|
|
949
|
+
await sessions.replaceWithCompaction({
|
|
950
|
+
summary: summaryText,
|
|
951
|
+
messages: keptMessages,
|
|
952
|
+
tokensBefore,
|
|
953
|
+
tokensAfter
|
|
954
|
+
});
|
|
955
|
+
return {
|
|
956
|
+
removedCount,
|
|
957
|
+
tokensRemoved: Math.max(0, tokensBefore - tokensAfter),
|
|
958
|
+
summarized,
|
|
959
|
+
summary: summaryText
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
async function buildAgentSystemPrompts(options) {
|
|
963
|
+
const {
|
|
964
|
+
config,
|
|
965
|
+
toolIds,
|
|
966
|
+
sessionId,
|
|
967
|
+
override,
|
|
968
|
+
promptBuilder,
|
|
969
|
+
middlewareRunner
|
|
970
|
+
} = options;
|
|
971
|
+
if (promptBuilder) {
|
|
972
|
+
const composedPrompt = await promptBuilder.build(
|
|
973
|
+
{
|
|
974
|
+
cwd: config.cwd,
|
|
975
|
+
model: config.model,
|
|
976
|
+
toolNames: toolIds,
|
|
977
|
+
...override ? { override } : {},
|
|
978
|
+
sessionId
|
|
979
|
+
},
|
|
980
|
+
middlewareRunner
|
|
981
|
+
);
|
|
982
|
+
return [composedPrompt];
|
|
983
|
+
}
|
|
984
|
+
const prompts = [config.systemPrompt];
|
|
985
|
+
if (override) {
|
|
986
|
+
prompts.push(override);
|
|
987
|
+
}
|
|
988
|
+
return prompts;
|
|
989
|
+
}
|
|
990
|
+
function createAgentTurnRuntimeConfig(options) {
|
|
991
|
+
const { config, telemetrySettings } = options;
|
|
992
|
+
return {
|
|
993
|
+
model: config.model,
|
|
994
|
+
cwd: config.cwd,
|
|
995
|
+
...config.temperature !== void 0 ? { temperature: config.temperature } : {},
|
|
996
|
+
...config.topP !== void 0 ? { topP: config.topP } : {},
|
|
997
|
+
...config.maxOutputTokens !== void 0 ? { maxOutputTokens: config.maxOutputTokens } : {},
|
|
998
|
+
maxSteps: config.maxSteps,
|
|
999
|
+
...config.doomLoopThreshold !== void 0 ? { doomLoopThreshold: config.doomLoopThreshold } : {},
|
|
1000
|
+
...config.enforceDoomLoop !== void 0 ? { enforceDoomLoop: config.enforceDoomLoop } : {},
|
|
1001
|
+
...config.onDoomLoop ? { onDoomLoop: config.onDoomLoop } : {},
|
|
1002
|
+
...config.contextWindow !== void 0 ? { contextWindow: config.contextWindow } : {},
|
|
1003
|
+
...options.reserveTokens !== void 0 ? { reserveTokens: options.reserveTokens } : {},
|
|
1004
|
+
...config.streamProvider ? { streamProvider: config.streamProvider } : {},
|
|
1005
|
+
...telemetrySettings ? { telemetry: telemetrySettings } : {}
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
271
1008
|
|
|
272
1009
|
// src/agent/chat-loop/commit.ts
|
|
273
1010
|
function createChatLoopCommitBatchApplier(params) {
|
|
@@ -290,18 +1027,29 @@ function createChatLoopCommitBatchApplier(params) {
|
|
|
290
1027
|
|
|
291
1028
|
// src/agent/chat-loop/compaction.ts
|
|
292
1029
|
async function runAutoCompaction(params) {
|
|
293
|
-
const { contextManager,
|
|
1030
|
+
const { contextManager, sessions, logger } = params;
|
|
1031
|
+
const messages = sessions.getMessages();
|
|
294
1032
|
if (!contextManager.shouldPrune(messages)) {
|
|
295
1033
|
return [];
|
|
296
1034
|
}
|
|
297
1035
|
const events = [{ type: "status", status: "processing" }];
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
1036
|
+
try {
|
|
1037
|
+
const pruneResult = await compactAgentContext({
|
|
1038
|
+
contextManager,
|
|
1039
|
+
sessions,
|
|
1040
|
+
logger
|
|
1041
|
+
});
|
|
1042
|
+
if (pruneResult.removedCount > 0 || pruneResult.summarized) {
|
|
1043
|
+
const limits = contextManager.getLimits();
|
|
1044
|
+
events.push({
|
|
1045
|
+
type: "context-overflow",
|
|
1046
|
+
inputTokens: estimateConversationTokens(messages),
|
|
1047
|
+
limit: getUsableTokenLimit(limits)
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
} catch (error) {
|
|
1051
|
+
logger?.warn("Auto-compaction failed, continuing without compaction", {
|
|
1052
|
+
error: error instanceof Error ? error.message : String(error)
|
|
305
1053
|
});
|
|
306
1054
|
}
|
|
307
1055
|
return events;
|
|
@@ -309,49 +1057,14 @@ async function runAutoCompaction(params) {
|
|
|
309
1057
|
|
|
310
1058
|
// src/agent/chat-loop/prompts.ts
|
|
311
1059
|
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;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// src/agent/chat-loop/usage.ts
|
|
341
|
-
function accumulateUsage(current, next) {
|
|
342
|
-
if (!next) return current;
|
|
343
|
-
if (!current) {
|
|
344
|
-
return {
|
|
345
|
-
inputTokens: next.inputTokens ?? 0,
|
|
346
|
-
outputTokens: next.outputTokens ?? 0,
|
|
347
|
-
totalTokens: next.totalTokens ?? 0
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
return {
|
|
351
|
-
inputTokens: (current.inputTokens ?? 0) + (next.inputTokens ?? 0),
|
|
352
|
-
outputTokens: (current.outputTokens ?? 0) + (next.outputTokens ?? 0),
|
|
353
|
-
totalTokens: (current.totalTokens ?? 0) + (next.totalTokens ?? 0)
|
|
354
|
-
};
|
|
1060
|
+
return buildAgentSystemPrompts({
|
|
1061
|
+
config: params.config,
|
|
1062
|
+
toolIds: Object.keys(params.tools),
|
|
1063
|
+
sessionId: params.sessionId,
|
|
1064
|
+
override: params.systemOverride,
|
|
1065
|
+
promptBuilder: params.promptBuilder,
|
|
1066
|
+
middlewareRunner: params.middlewareRunner
|
|
1067
|
+
});
|
|
355
1068
|
}
|
|
356
1069
|
|
|
357
1070
|
// src/agent/chat-loop/loop.ts
|
|
@@ -365,11 +1078,12 @@ async function* runChatLoop(deps) {
|
|
|
365
1078
|
(async function* () {
|
|
366
1079
|
const {
|
|
367
1080
|
sessionId,
|
|
1081
|
+
turnId,
|
|
368
1082
|
message,
|
|
369
1083
|
abort,
|
|
370
1084
|
systemOverride,
|
|
371
1085
|
sessions,
|
|
372
|
-
tools:
|
|
1086
|
+
tools: liveTools,
|
|
373
1087
|
config,
|
|
374
1088
|
turnTracker,
|
|
375
1089
|
interventionCtrl,
|
|
@@ -379,10 +1093,13 @@ async function* runChatLoop(deps) {
|
|
|
379
1093
|
reasoningLevel,
|
|
380
1094
|
promptBuilder,
|
|
381
1095
|
host,
|
|
1096
|
+
humanInputController,
|
|
382
1097
|
mcpTools,
|
|
383
1098
|
toModelMessages,
|
|
384
1099
|
setIsStreaming
|
|
385
1100
|
} = deps;
|
|
1101
|
+
let toolRecord = createAgentToolRecord(liveTools);
|
|
1102
|
+
const isPlanMode = deps.toolExecutionMode === "plan";
|
|
386
1103
|
const turnEngine = createAgentTurnEngine({
|
|
387
1104
|
sessionId,
|
|
388
1105
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -407,20 +1124,24 @@ async function* runChatLoop(deps) {
|
|
|
407
1124
|
let chatOutput;
|
|
408
1125
|
try {
|
|
409
1126
|
if (middlewareRunner.hasMiddleware) {
|
|
410
|
-
await middlewareRunner.runChatStart(sessionId, message
|
|
1127
|
+
await middlewareRunner.runChatStart(sessionId, message, {
|
|
1128
|
+
sessionId,
|
|
1129
|
+
turnId
|
|
1130
|
+
});
|
|
411
1131
|
}
|
|
412
|
-
const systemPrompts = await buildChatSystemPrompts({
|
|
413
|
-
promptBuilder,
|
|
414
|
-
middlewareRunner,
|
|
415
|
-
systemOverride,
|
|
416
|
-
sessionId,
|
|
417
|
-
config,
|
|
418
|
-
tools: toolRecord
|
|
419
|
-
});
|
|
420
1132
|
let step = 1;
|
|
421
1133
|
let finalStepText = "";
|
|
422
1134
|
let accumulatedUsage;
|
|
423
1135
|
while (step <= config.maxSteps) {
|
|
1136
|
+
toolRecord = createAgentToolRecord(liveTools);
|
|
1137
|
+
const systemPrompts = await buildChatSystemPrompts({
|
|
1138
|
+
promptBuilder,
|
|
1139
|
+
middlewareRunner,
|
|
1140
|
+
systemOverride,
|
|
1141
|
+
sessionId,
|
|
1142
|
+
config,
|
|
1143
|
+
tools: toolRecord
|
|
1144
|
+
});
|
|
424
1145
|
const preparedStep = prepareModelStep({
|
|
425
1146
|
sessionId,
|
|
426
1147
|
step,
|
|
@@ -432,10 +1153,12 @@ async function* runChatLoop(deps) {
|
|
|
432
1153
|
mcpTools,
|
|
433
1154
|
config,
|
|
434
1155
|
host,
|
|
1156
|
+
humanInputController,
|
|
435
1157
|
turnTracker,
|
|
436
1158
|
intervention: interventionCtrl,
|
|
437
1159
|
middleware: middlewareRunner,
|
|
438
|
-
reasoningLevel
|
|
1160
|
+
reasoningLevel,
|
|
1161
|
+
toolExecutionMode: deps.toolExecutionMode
|
|
439
1162
|
});
|
|
440
1163
|
const stepResult = yield* runModelStep({
|
|
441
1164
|
preparedStep,
|
|
@@ -448,6 +1171,7 @@ async function* runChatLoop(deps) {
|
|
|
448
1171
|
chatError = stepResult.error;
|
|
449
1172
|
return;
|
|
450
1173
|
}
|
|
1174
|
+
const planSnapshot = isPlanMode && stepResult.finishReason === "tool-calls" ? turnEngine.createStepCommitSnapshot() : void 0;
|
|
451
1175
|
yield* commitStep({
|
|
452
1176
|
step,
|
|
453
1177
|
finishReason: stepResult.finishReason,
|
|
@@ -468,6 +1192,31 @@ async function* runChatLoop(deps) {
|
|
|
468
1192
|
yield errorEvent;
|
|
469
1193
|
return;
|
|
470
1194
|
}
|
|
1195
|
+
if (isPlanMode && planSnapshot && planSnapshot.toolCalls.length > 0) {
|
|
1196
|
+
const batchResult = await runToolBatch({
|
|
1197
|
+
sessionId,
|
|
1198
|
+
snapshot: planSnapshot,
|
|
1199
|
+
tools: toolRecord,
|
|
1200
|
+
cwd: config.cwd,
|
|
1201
|
+
abort,
|
|
1202
|
+
host,
|
|
1203
|
+
humanInputController,
|
|
1204
|
+
turnTracker,
|
|
1205
|
+
middleware: middlewareRunner,
|
|
1206
|
+
intervention: interventionCtrl
|
|
1207
|
+
});
|
|
1208
|
+
for (const event of batchResult.events) {
|
|
1209
|
+
turnEngine.recordEvent(event, (/* @__PURE__ */ new Date()).toISOString());
|
|
1210
|
+
middlewareRunner.emitEvent(event);
|
|
1211
|
+
yield event;
|
|
1212
|
+
}
|
|
1213
|
+
yield* commitStep({
|
|
1214
|
+
step,
|
|
1215
|
+
finishReason: "tool-calls",
|
|
1216
|
+
turnEngine,
|
|
1217
|
+
applyCommitBatch
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
471
1220
|
step += 1;
|
|
472
1221
|
continue;
|
|
473
1222
|
}
|
|
@@ -483,7 +1232,8 @@ async function* runChatLoop(deps) {
|
|
|
483
1232
|
if (config.compaction?.auto !== false) {
|
|
484
1233
|
const compactionEvents = await runAutoCompaction({
|
|
485
1234
|
contextManager,
|
|
486
|
-
|
|
1235
|
+
sessions,
|
|
1236
|
+
logger: deps.logger
|
|
487
1237
|
});
|
|
488
1238
|
for (const event of compactionEvents) {
|
|
489
1239
|
yield event;
|
|
@@ -513,6 +1263,12 @@ async function* runChatLoop(deps) {
|
|
|
513
1263
|
};
|
|
514
1264
|
} catch (error) {
|
|
515
1265
|
chatError = error instanceof Error ? error : new Error(String(error));
|
|
1266
|
+
const statusEvent = { type: "status", status: "error" };
|
|
1267
|
+
middlewareRunner.emitEvent(statusEvent);
|
|
1268
|
+
yield statusEvent;
|
|
1269
|
+
const errorEvent = { type: "error", error: chatError };
|
|
1270
|
+
middlewareRunner.emitEvent(errorEvent);
|
|
1271
|
+
yield errorEvent;
|
|
516
1272
|
throw error;
|
|
517
1273
|
} finally {
|
|
518
1274
|
setIsStreaming(false);
|
|
@@ -522,6 +1278,9 @@ async function* runChatLoop(deps) {
|
|
|
522
1278
|
usage: chatUsage,
|
|
523
1279
|
error: chatError,
|
|
524
1280
|
output: chatOutput
|
|
1281
|
+
}, {
|
|
1282
|
+
sessionId,
|
|
1283
|
+
turnId
|
|
525
1284
|
});
|
|
526
1285
|
}
|
|
527
1286
|
}
|
|
@@ -531,10 +1290,10 @@ async function* runChatLoop(deps) {
|
|
|
531
1290
|
|
|
532
1291
|
// src/agent/fork.ts
|
|
533
1292
|
function resolveForkOptions(options, parentTools, systemPrompt) {
|
|
534
|
-
if (!options.
|
|
1293
|
+
if (!options.profile) {
|
|
535
1294
|
return options;
|
|
536
1295
|
}
|
|
537
|
-
const applied =
|
|
1296
|
+
const applied = applyProfile(options.profile, parentTools, systemPrompt);
|
|
538
1297
|
return {
|
|
539
1298
|
...applied,
|
|
540
1299
|
...options,
|
|
@@ -573,6 +1332,9 @@ function createForkedAgentConfig(options) {
|
|
|
573
1332
|
parentTools,
|
|
574
1333
|
reasoningLevel,
|
|
575
1334
|
host,
|
|
1335
|
+
sandbox,
|
|
1336
|
+
humanInputController,
|
|
1337
|
+
ownsHost,
|
|
576
1338
|
sessions,
|
|
577
1339
|
mcpManager,
|
|
578
1340
|
middlewareRunner,
|
|
@@ -588,7 +1350,8 @@ function createForkedAgentConfig(options) {
|
|
|
588
1350
|
return {
|
|
589
1351
|
model: forkOptions.model ?? parentConfig.model,
|
|
590
1352
|
cwd: parentConfig.cwd,
|
|
591
|
-
host,
|
|
1353
|
+
...ownsHost ? {} : sandbox !== void 0 ? { sandbox } : { host },
|
|
1354
|
+
...humanInputController ? { humanInput: humanInputController } : {},
|
|
592
1355
|
maxOutputTokens: parentConfig.maxOutputTokens,
|
|
593
1356
|
maxSteps: forkOptions.maxSteps ?? parentConfig.maxSteps,
|
|
594
1357
|
temperature: forkOptions.temperature ?? parentConfig.temperature,
|
|
@@ -608,7 +1371,7 @@ function createForkedAgentConfig(options) {
|
|
|
608
1371
|
}
|
|
609
1372
|
|
|
610
1373
|
// src/agent/mcp-bridge.ts
|
|
611
|
-
async function ensureMcpTools(state) {
|
|
1374
|
+
async function ensureMcpTools(state, logger) {
|
|
612
1375
|
if (!state.manager) {
|
|
613
1376
|
return { connected: false, cachedTools: void 0 };
|
|
614
1377
|
}
|
|
@@ -618,17 +1381,18 @@ async function ensureMcpTools(state) {
|
|
|
618
1381
|
cachedTools: state.cachedTools
|
|
619
1382
|
};
|
|
620
1383
|
}
|
|
1384
|
+
const log = logger.child("mcp");
|
|
621
1385
|
const statuses = await state.manager.connect();
|
|
622
1386
|
let connectedCount = 0;
|
|
623
1387
|
for (const [name, status] of statuses) {
|
|
624
1388
|
if (status.status === "connected") {
|
|
625
1389
|
connectedCount++;
|
|
626
1390
|
} else if (status.status === "error") {
|
|
627
|
-
|
|
1391
|
+
log.warn(`Failed to connect to ${name}: ${status.error}`);
|
|
628
1392
|
}
|
|
629
1393
|
}
|
|
630
1394
|
if (connectedCount === 0 && statuses.size > 0) {
|
|
631
|
-
|
|
1395
|
+
log.warn("No MCP servers connected successfully");
|
|
632
1396
|
}
|
|
633
1397
|
const cachedTools = await state.manager.getTools();
|
|
634
1398
|
return {
|
|
@@ -646,161 +1410,392 @@ async function closeMcpManager(manager) {
|
|
|
646
1410
|
};
|
|
647
1411
|
}
|
|
648
1412
|
|
|
649
|
-
// src/
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
1413
|
+
// src/signal/local.ts
|
|
1414
|
+
var LocalSignal = class {
|
|
1415
|
+
/** type → Set<handler> for typed subscriptions */
|
|
1416
|
+
typed = /* @__PURE__ */ new Map();
|
|
1417
|
+
/** handlers that receive every event */
|
|
1418
|
+
wildcard = /* @__PURE__ */ new Set();
|
|
1419
|
+
on(type, handler) {
|
|
1420
|
+
let set = this.typed.get(type);
|
|
1421
|
+
if (!set) {
|
|
1422
|
+
set = /* @__PURE__ */ new Set();
|
|
1423
|
+
this.typed.set(type, set);
|
|
1424
|
+
}
|
|
1425
|
+
const wrapped = (event) => {
|
|
1426
|
+
handler(event);
|
|
1427
|
+
};
|
|
1428
|
+
set.add(wrapped);
|
|
1429
|
+
return () => {
|
|
1430
|
+
set.delete(wrapped);
|
|
1431
|
+
if (set.size === 0) this.typed.delete(type);
|
|
1432
|
+
};
|
|
654
1433
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
1434
|
+
onAny(handler) {
|
|
1435
|
+
this.wildcard.add(handler);
|
|
1436
|
+
return () => {
|
|
1437
|
+
this.wildcard.delete(handler);
|
|
1438
|
+
};
|
|
660
1439
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
pendingCallIds.set(toolCall.toolCallId, { toolName: toolCall.toolName });
|
|
1440
|
+
emit(event) {
|
|
1441
|
+
const set = this.typed.get(event.type);
|
|
1442
|
+
if (set) {
|
|
1443
|
+
for (const fn of set) {
|
|
1444
|
+
try {
|
|
1445
|
+
fn(event);
|
|
1446
|
+
} catch {
|
|
1447
|
+
}
|
|
670
1448
|
}
|
|
671
1449
|
}
|
|
672
|
-
|
|
673
|
-
|
|
1450
|
+
for (const fn of this.wildcard) {
|
|
1451
|
+
try {
|
|
1452
|
+
fn(event);
|
|
1453
|
+
} catch {
|
|
1454
|
+
}
|
|
674
1455
|
}
|
|
675
1456
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
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);
|
|
1457
|
+
clear() {
|
|
1458
|
+
this.typed.clear();
|
|
1459
|
+
this.wildcard.clear();
|
|
687
1460
|
}
|
|
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
|
-
}
|
|
1461
|
+
};
|
|
700
1462
|
|
|
701
|
-
// src/
|
|
702
|
-
var
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
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);
|
|
1463
|
+
// src/human/controller.ts
|
|
1464
|
+
var HumanInputTimeoutError = class extends Error {
|
|
1465
|
+
constructor(timeoutMs) {
|
|
1466
|
+
super(`Human input request timed out after ${timeoutMs}ms`);
|
|
1467
|
+
this.name = "HumanInputTimeoutError";
|
|
745
1468
|
}
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
1469
|
+
};
|
|
1470
|
+
var HumanInputUnavailableError = class extends Error {
|
|
1471
|
+
constructor() {
|
|
1472
|
+
super("No human input controller configured");
|
|
1473
|
+
this.name = "HumanInputUnavailableError";
|
|
749
1474
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
1475
|
+
};
|
|
1476
|
+
function cloneRecord(record) {
|
|
1477
|
+
return structuredClone(record);
|
|
1478
|
+
}
|
|
1479
|
+
function normalizeStatuses(status) {
|
|
1480
|
+
if (!status) {
|
|
1481
|
+
return void 0;
|
|
753
1482
|
}
|
|
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;
|
|
1483
|
+
return new Set(Array.isArray(status) ? status : [status]);
|
|
1484
|
+
}
|
|
1485
|
+
function inferKind(input) {
|
|
1486
|
+
if (input.kind) {
|
|
1487
|
+
return input.kind;
|
|
774
1488
|
}
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
* The internal queue is cleared atomically.
|
|
778
|
-
*/
|
|
779
|
-
drainDeferred() {
|
|
780
|
-
if (this.deferred.length === 0) return [];
|
|
781
|
-
return this.deferred.splice(0);
|
|
1489
|
+
if (input.options && input.options.length > 0) {
|
|
1490
|
+
return "choice";
|
|
782
1491
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
1492
|
+
return "text";
|
|
1493
|
+
}
|
|
1494
|
+
function isHumanInputController(value) {
|
|
1495
|
+
if (!value || typeof value !== "object") {
|
|
1496
|
+
return false;
|
|
786
1497
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
1498
|
+
const candidate = value;
|
|
1499
|
+
return typeof candidate.request === "function" && typeof candidate.respondToRequest === "function" && typeof candidate.getRequest === "function" && typeof candidate.listRequests === "function" && typeof candidate.cancelAll === "function";
|
|
1500
|
+
}
|
|
1501
|
+
async function emitHumanInputEvent(context, event) {
|
|
1502
|
+
await context?.emitEvent?.(event);
|
|
1503
|
+
}
|
|
1504
|
+
function createHumanInputController(config = {}) {
|
|
1505
|
+
const timeout = config.timeout ?? 5 * 60 * 1e3;
|
|
1506
|
+
let requestCounter = 0;
|
|
1507
|
+
const pending = /* @__PURE__ */ new Map();
|
|
1508
|
+
async function request(sessionId, input, context = {}) {
|
|
1509
|
+
const requestPayload = {
|
|
1510
|
+
id: `human-input-${++requestCounter}-${Date.now()}`,
|
|
1511
|
+
sessionId,
|
|
1512
|
+
kind: inferKind(input),
|
|
1513
|
+
title: input.title,
|
|
1514
|
+
question: input.question,
|
|
1515
|
+
...input.options ? { options: input.options.map((option) => ({ ...option })) } : {},
|
|
1516
|
+
...input.allowMultiple !== void 0 ? { allowMultiple: input.allowMultiple } : {},
|
|
1517
|
+
...input.placeholder ? { placeholder: input.placeholder } : {},
|
|
1518
|
+
...input.confirmLabel ? { confirmLabel: input.confirmLabel } : {},
|
|
1519
|
+
...input.denyLabel ? { denyLabel: input.denyLabel } : {},
|
|
1520
|
+
...input.toolCallId ? { toolCallId: input.toolCallId } : {},
|
|
1521
|
+
timestamp: Date.now()
|
|
1522
|
+
};
|
|
1523
|
+
const record = {
|
|
1524
|
+
id: requestPayload.id,
|
|
1525
|
+
sessionId,
|
|
1526
|
+
request: structuredClone(requestPayload),
|
|
1527
|
+
status: "pending",
|
|
1528
|
+
createdAt: requestPayload.timestamp,
|
|
1529
|
+
updatedAt: requestPayload.timestamp
|
|
1530
|
+
};
|
|
1531
|
+
const responsePromise = new Promise((resolve2, reject) => {
|
|
1532
|
+
const timeoutId = setTimeout(() => {
|
|
1533
|
+
const current2 = pending.get(record.id);
|
|
1534
|
+
if (!current2) {
|
|
1535
|
+
return;
|
|
1536
|
+
}
|
|
1537
|
+
pending.delete(record.id);
|
|
1538
|
+
current2.record = {
|
|
1539
|
+
...current2.record,
|
|
1540
|
+
status: "timed-out",
|
|
1541
|
+
updatedAt: Date.now()
|
|
1542
|
+
};
|
|
1543
|
+
void emitHumanInputEvent(
|
|
1544
|
+
{ emitEvent: current2.emitEvent },
|
|
1545
|
+
{ type: "status", status: "processing" }
|
|
1546
|
+
);
|
|
1547
|
+
reject(new HumanInputTimeoutError(timeout));
|
|
1548
|
+
}, timeout);
|
|
1549
|
+
pending.set(record.id, {
|
|
1550
|
+
record,
|
|
1551
|
+
resolve: resolve2,
|
|
1552
|
+
reject,
|
|
1553
|
+
ready: Promise.resolve(),
|
|
1554
|
+
timeoutId,
|
|
1555
|
+
emitEvent: context.emitEvent
|
|
1556
|
+
});
|
|
1557
|
+
});
|
|
1558
|
+
const current = pending.get(record.id);
|
|
1559
|
+
if (current) {
|
|
1560
|
+
current.ready = (async () => {
|
|
1561
|
+
await emitHumanInputEvent(context, {
|
|
1562
|
+
type: "status",
|
|
1563
|
+
status: "waiting-input"
|
|
1564
|
+
});
|
|
1565
|
+
await emitHumanInputEvent(context, {
|
|
1566
|
+
type: "human-input-request",
|
|
1567
|
+
request: {
|
|
1568
|
+
id: requestPayload.id,
|
|
1569
|
+
kind: requestPayload.kind,
|
|
1570
|
+
title: requestPayload.title,
|
|
1571
|
+
question: requestPayload.question,
|
|
1572
|
+
...requestPayload.options ? { options: requestPayload.options } : {},
|
|
1573
|
+
...requestPayload.allowMultiple !== void 0 ? { allowMultiple: requestPayload.allowMultiple } : {},
|
|
1574
|
+
...requestPayload.placeholder ? { placeholder: requestPayload.placeholder } : {},
|
|
1575
|
+
...requestPayload.confirmLabel ? { confirmLabel: requestPayload.confirmLabel } : {},
|
|
1576
|
+
...requestPayload.denyLabel ? { denyLabel: requestPayload.denyLabel } : {}
|
|
1577
|
+
}
|
|
1578
|
+
});
|
|
1579
|
+
})();
|
|
1580
|
+
}
|
|
1581
|
+
if (config.onRequest) {
|
|
1582
|
+
void (async () => {
|
|
1583
|
+
try {
|
|
1584
|
+
await pending.get(record.id)?.ready;
|
|
1585
|
+
const response = await config.onRequest(requestPayload);
|
|
1586
|
+
await respondToRequest(record.id, response, context);
|
|
1587
|
+
} catch (error) {
|
|
1588
|
+
if (error instanceof HumanInputTimeoutError) {
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1591
|
+
const current2 = pending.get(record.id);
|
|
1592
|
+
if (!current2) {
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
pending.delete(record.id);
|
|
1596
|
+
clearTimeout(current2.timeoutId);
|
|
1597
|
+
current2.record = {
|
|
1598
|
+
...current2.record,
|
|
1599
|
+
status: "cancelled",
|
|
1600
|
+
updatedAt: Date.now()
|
|
1601
|
+
};
|
|
1602
|
+
current2.reject(
|
|
1603
|
+
error instanceof Error ? error : new Error(String(error))
|
|
1604
|
+
);
|
|
1605
|
+
await emitHumanInputEvent(
|
|
1606
|
+
{ emitEvent: current2.emitEvent },
|
|
1607
|
+
{ type: "status", status: "processing" }
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
})();
|
|
1611
|
+
}
|
|
1612
|
+
return await responsePromise;
|
|
790
1613
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
1614
|
+
async function respondToRequest(requestId, response, context = {}) {
|
|
1615
|
+
const current = pending.get(requestId);
|
|
1616
|
+
if (!current) {
|
|
1617
|
+
throw new Error(`Human input request not found: ${requestId}`);
|
|
1618
|
+
}
|
|
1619
|
+
await current.ready;
|
|
1620
|
+
pending.delete(requestId);
|
|
1621
|
+
clearTimeout(current.timeoutId);
|
|
1622
|
+
const respondedAt = Date.now();
|
|
1623
|
+
const next = {
|
|
1624
|
+
...current.record,
|
|
1625
|
+
status: "answered",
|
|
1626
|
+
updatedAt: respondedAt,
|
|
1627
|
+
respondedAt,
|
|
1628
|
+
response: structuredClone(response)
|
|
1629
|
+
};
|
|
1630
|
+
current.resolve(response);
|
|
1631
|
+
const emitEvent = context.emitEvent ?? current.emitEvent;
|
|
1632
|
+
await emitHumanInputEvent(
|
|
1633
|
+
{ emitEvent },
|
|
1634
|
+
{
|
|
1635
|
+
type: "human-input-resolved",
|
|
1636
|
+
id: requestId,
|
|
1637
|
+
response
|
|
1638
|
+
}
|
|
1639
|
+
);
|
|
1640
|
+
await emitHumanInputEvent(
|
|
1641
|
+
{ emitEvent },
|
|
1642
|
+
{ type: "status", status: "processing" }
|
|
1643
|
+
);
|
|
1644
|
+
return cloneRecord(next);
|
|
798
1645
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
1646
|
+
function getRequest(requestId) {
|
|
1647
|
+
const current = pending.get(requestId);
|
|
1648
|
+
return current ? cloneRecord(current.record) : void 0;
|
|
802
1649
|
}
|
|
803
|
-
}
|
|
1650
|
+
function listRequests(options = {}) {
|
|
1651
|
+
const statuses = normalizeStatuses(options.status);
|
|
1652
|
+
return [...pending.values()].map((entry) => cloneRecord(entry.record)).filter((record) => {
|
|
1653
|
+
if (options.sessionId && record.sessionId !== options.sessionId) {
|
|
1654
|
+
return false;
|
|
1655
|
+
}
|
|
1656
|
+
if (statuses && !statuses.has(record.status)) {
|
|
1657
|
+
return false;
|
|
1658
|
+
}
|
|
1659
|
+
return true;
|
|
1660
|
+
}).sort((left, right) => left.createdAt - right.createdAt);
|
|
1661
|
+
}
|
|
1662
|
+
function cancelAll(reason = "Cancelled") {
|
|
1663
|
+
for (const [requestId, current] of pending) {
|
|
1664
|
+
pending.delete(requestId);
|
|
1665
|
+
clearTimeout(current.timeoutId);
|
|
1666
|
+
current.record = {
|
|
1667
|
+
...current.record,
|
|
1668
|
+
status: "cancelled",
|
|
1669
|
+
updatedAt: Date.now()
|
|
1670
|
+
};
|
|
1671
|
+
current.reject(new Error(reason));
|
|
1672
|
+
void emitHumanInputEvent(
|
|
1673
|
+
{ emitEvent: current.emitEvent },
|
|
1674
|
+
{ type: "status", status: "processing" }
|
|
1675
|
+
);
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
return {
|
|
1679
|
+
get hasPendingRequests() {
|
|
1680
|
+
return pending.size > 0;
|
|
1681
|
+
},
|
|
1682
|
+
request,
|
|
1683
|
+
respondToRequest,
|
|
1684
|
+
getRequest,
|
|
1685
|
+
listRequests,
|
|
1686
|
+
cancelAll
|
|
1687
|
+
};
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
// src/human/handler.ts
|
|
1691
|
+
function createHumanInputHandler(config = {}) {
|
|
1692
|
+
return createHumanInputController(config);
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
// src/human/tool.ts
|
|
1696
|
+
import { z } from "zod";
|
|
1697
|
+
function createHumanInputTool(options = {}) {
|
|
1698
|
+
if (options.controller) {
|
|
1699
|
+
return createHumanInputToolWithController(options.controller, options);
|
|
1700
|
+
}
|
|
1701
|
+
if (options.onRequest || options.timeout !== void 0) {
|
|
1702
|
+
return createHumanInputToolWithController(
|
|
1703
|
+
createHumanInputController(options),
|
|
1704
|
+
options
|
|
1705
|
+
);
|
|
1706
|
+
}
|
|
1707
|
+
return createHumanInputToolWithController(void 0, options);
|
|
1708
|
+
}
|
|
1709
|
+
function createHumanInputToolWithController(controller, options = {}) {
|
|
1710
|
+
return Tool.define(
|
|
1711
|
+
options.name ?? "question",
|
|
1712
|
+
{
|
|
1713
|
+
description: options.description ?? "Ask a human for missing input, a decision, a confirmation, or a choice.",
|
|
1714
|
+
parameters: z.object({
|
|
1715
|
+
title: z.string().min(1).describe("Short heading for the request"),
|
|
1716
|
+
question: z.string().min(1).describe("What to ask the human"),
|
|
1717
|
+
kind: z.enum(["text", "confirm", "choice"]).optional(),
|
|
1718
|
+
options: z.array(
|
|
1719
|
+
z.object({
|
|
1720
|
+
label: z.string().min(1),
|
|
1721
|
+
value: z.string().optional(),
|
|
1722
|
+
description: z.string().optional()
|
|
1723
|
+
})
|
|
1724
|
+
).optional(),
|
|
1725
|
+
allowMultiple: z.boolean().optional(),
|
|
1726
|
+
placeholder: z.string().optional(),
|
|
1727
|
+
confirmLabel: z.string().optional(),
|
|
1728
|
+
denyLabel: z.string().optional()
|
|
1729
|
+
}),
|
|
1730
|
+
validate: (params) => {
|
|
1731
|
+
const kind = params.kind ?? (params.options?.length ? "choice" : "text");
|
|
1732
|
+
if (kind === "choice" && (!params.options || params.options.length === 0)) {
|
|
1733
|
+
return {
|
|
1734
|
+
ok: false,
|
|
1735
|
+
reason: "Choice requests must include at least one option."
|
|
1736
|
+
};
|
|
1737
|
+
}
|
|
1738
|
+
if (kind !== "choice" && params.allowMultiple) {
|
|
1739
|
+
return {
|
|
1740
|
+
ok: false,
|
|
1741
|
+
reason: "allowMultiple is only valid for choice requests."
|
|
1742
|
+
};
|
|
1743
|
+
}
|
|
1744
|
+
return { ok: true };
|
|
1745
|
+
},
|
|
1746
|
+
capabilities: {
|
|
1747
|
+
readOnly: true,
|
|
1748
|
+
riskLevel: "safe",
|
|
1749
|
+
parallelSafe: false,
|
|
1750
|
+
humanInput: true
|
|
1751
|
+
},
|
|
1752
|
+
replayPolicy: {
|
|
1753
|
+
mode: "manual",
|
|
1754
|
+
sideEffectLevel: "external",
|
|
1755
|
+
reason: "Depends on a human response before execution can continue."
|
|
1756
|
+
},
|
|
1757
|
+
execute: async (params, ctx) => {
|
|
1758
|
+
let response;
|
|
1759
|
+
try {
|
|
1760
|
+
const activeController = controller ?? ctx.humanInputController;
|
|
1761
|
+
if (!activeController) {
|
|
1762
|
+
throw new HumanInputUnavailableError();
|
|
1763
|
+
}
|
|
1764
|
+
response = await activeController.request(ctx.sessionID, {
|
|
1765
|
+
...params,
|
|
1766
|
+
toolCallId: typeof ctx.extra?.toolCallId === "string" ? ctx.extra.toolCallId : ctx.messageID
|
|
1767
|
+
}, {
|
|
1768
|
+
emitEvent: ctx.emitEvent
|
|
1769
|
+
});
|
|
1770
|
+
} catch (error) {
|
|
1771
|
+
if (error instanceof HumanInputUnavailableError) {
|
|
1772
|
+
throw error;
|
|
1773
|
+
}
|
|
1774
|
+
throw error;
|
|
1775
|
+
}
|
|
1776
|
+
return {
|
|
1777
|
+
title: params.title,
|
|
1778
|
+
output: response.text,
|
|
1779
|
+
metadata: { response }
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
},
|
|
1783
|
+
{
|
|
1784
|
+
replayPolicy: {
|
|
1785
|
+
mode: "manual",
|
|
1786
|
+
sideEffectLevel: "external",
|
|
1787
|
+
reason: "Depends on a human response before execution can continue."
|
|
1788
|
+
},
|
|
1789
|
+
capabilitiesHint: {
|
|
1790
|
+
readOnly: true,
|
|
1791
|
+
riskLevel: "safe",
|
|
1792
|
+
parallelSafe: false,
|
|
1793
|
+
humanInput: true
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
var createHumanInputToolWithHandler = createHumanInputToolWithController;
|
|
804
1799
|
|
|
805
1800
|
// src/agent/stream-provider.ts
|
|
806
1801
|
var DEFAULT_CUSTOM_STREAM_MODELS = [
|
|
@@ -808,7 +1803,7 @@ var DEFAULT_CUSTOM_STREAM_MODELS = [
|
|
|
808
1803
|
"computer-use-preview-2025-03-11"
|
|
809
1804
|
];
|
|
810
1805
|
function needsCustomStreamProvider(model, customPatterns) {
|
|
811
|
-
const modelId =
|
|
1806
|
+
const modelId = extractModelId(model);
|
|
812
1807
|
if (!modelId || modelId === "[object Object]") return false;
|
|
813
1808
|
const patterns = customPatterns ?? DEFAULT_CUSTOM_STREAM_MODELS;
|
|
814
1809
|
return patterns.some((pattern) => modelId.includes(pattern));
|
|
@@ -824,7 +1819,7 @@ function autoDetectStreamProvider(model, tools, explicitProvider) {
|
|
|
824
1819
|
const enhancedTools = tools;
|
|
825
1820
|
const customPatterns = enhancedTools.__customStreamModels;
|
|
826
1821
|
if (needsCustomStreamProvider(model, customPatterns) && hasStreamProviderFactory(enhancedTools)) {
|
|
827
|
-
const modelId =
|
|
1822
|
+
const modelId = extractModelId(model);
|
|
828
1823
|
if (modelId) {
|
|
829
1824
|
const streamConfig = {
|
|
830
1825
|
apiKey: process.env.OPENAI_API_KEY,
|
|
@@ -838,18 +1833,6 @@ function autoDetectStreamProvider(model, tools, explicitProvider) {
|
|
|
838
1833
|
return void 0;
|
|
839
1834
|
}
|
|
840
1835
|
|
|
841
|
-
// src/agent/defaults.ts
|
|
842
|
-
var DEFAULT_SYSTEM_PROMPT = `You are a capable AI assistant with access to tools.
|
|
843
|
-
|
|
844
|
-
Think step by step about what you need to do.
|
|
845
|
-
Use the available tools to accomplish tasks.
|
|
846
|
-
Verify your results after each action.
|
|
847
|
-
|
|
848
|
-
If a tool fails, try an alternative approach \u2014 do not give up after a single error.
|
|
849
|
-
Keep working until the task is fully resolved or you have exhausted all options.`;
|
|
850
|
-
var DEFAULT_MAX_STEPS = 50;
|
|
851
|
-
var DEFAULT_MAX_TOKENS = 32e3;
|
|
852
|
-
|
|
853
1836
|
// src/agent/setup.ts
|
|
854
1837
|
function createAgentPromptBuilder(config) {
|
|
855
1838
|
if (config.prompt !== void 0) {
|
|
@@ -866,14 +1849,24 @@ function createEffectiveAgentConfig(config) {
|
|
|
866
1849
|
config.tools,
|
|
867
1850
|
config.streamProvider
|
|
868
1851
|
);
|
|
1852
|
+
const resolvedCwd = config.cwd ?? config.sandbox?.metadata?.workingDirectory ?? process.cwd();
|
|
1853
|
+
const defaultsContext = {
|
|
1854
|
+
sandbox: config.sandbox,
|
|
1855
|
+
cwd: resolvedCwd,
|
|
1856
|
+
modelId: extractModelId(config.model)
|
|
1857
|
+
};
|
|
1858
|
+
const providers = [
|
|
1859
|
+
sandboxDefaultsProvider,
|
|
1860
|
+
...config.defaultsProviders ?? []
|
|
1861
|
+
];
|
|
1862
|
+
const defaults = resolveAgentDefaults(defaultsContext, providers);
|
|
869
1863
|
return {
|
|
870
|
-
systemPrompt: DEFAULT_SYSTEM_PROMPT,
|
|
871
|
-
cwd: process.cwd(),
|
|
872
|
-
reasoningLevel: "off",
|
|
873
1864
|
...config,
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
1865
|
+
systemPrompt: config.systemPrompt ?? defaults.systemPrompt,
|
|
1866
|
+
cwd: resolvedCwd,
|
|
1867
|
+
reasoningLevel: config.reasoningLevel ?? "off",
|
|
1868
|
+
maxSteps: config.maxSteps ?? defaults.maxSteps,
|
|
1869
|
+
maxOutputTokens: config.maxOutputTokens ?? defaults.maxOutputTokens,
|
|
877
1870
|
streamProvider: effectiveStreamProvider
|
|
878
1871
|
};
|
|
879
1872
|
}
|
|
@@ -892,148 +1885,139 @@ function resolveInitialReasoningLevel(config) {
|
|
|
892
1885
|
function createAgentState(config) {
|
|
893
1886
|
return {
|
|
894
1887
|
model: config.model,
|
|
895
|
-
systemPrompt: config.systemPrompt,
|
|
896
|
-
cwd: config.cwd,
|
|
897
|
-
isStreaming: false,
|
|
898
1888
|
reasoningLevel: resolveInitialReasoningLevel(config)
|
|
899
1889
|
};
|
|
900
1890
|
}
|
|
901
1891
|
function createAgentContextManager(config) {
|
|
902
1892
|
const compactionConfig = config.compaction ?? {};
|
|
903
|
-
const modelId =
|
|
1893
|
+
const modelId = extractModelId(config.model);
|
|
904
1894
|
const inferredWindow = inferContextWindow(modelId);
|
|
905
1895
|
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
1896
|
return new ContextManager({
|
|
911
1897
|
limits: {
|
|
912
1898
|
contextWindow,
|
|
913
|
-
|
|
914
|
-
protectedTokens: compactionConfig.protectedTokens ?? DEFAULT_CONTEXT_LIMITS.protectedTokens,
|
|
915
|
-
pruneMinimum: compactionConfig.pruneMinimum ?? DEFAULT_CONTEXT_LIMITS.pruneMinimum
|
|
1899
|
+
...resolveAgentContextLimits(contextWindow, compactionConfig)
|
|
916
1900
|
},
|
|
917
1901
|
model: compactionConfig.summaryModel ?? config.model,
|
|
918
1902
|
summaryPrompt: compactionConfig.summaryPrompt
|
|
919
1903
|
});
|
|
920
1904
|
}
|
|
1905
|
+
function resolveAgentContextLimits(contextWindow, compactionConfig = {}) {
|
|
1906
|
+
const proportionalReserve = Math.round(contextWindow * 0.12);
|
|
1907
|
+
const reserveTokens = contextWindow >= 64e3 ? Math.min(32e3, Math.max(8e3, proportionalReserve)) : Math.min(
|
|
1908
|
+
Math.max(1024, Math.round(contextWindow * 0.25)),
|
|
1909
|
+
Math.max(512, proportionalReserve)
|
|
1910
|
+
);
|
|
1911
|
+
const usableWindow = Math.max(512, getUsableTokenLimit({ contextWindow, reserveTokens }));
|
|
1912
|
+
const requestedProtected = compactionConfig.protectedTokens ?? DEFAULT_CONTEXT_LIMITS.protectedTokens;
|
|
1913
|
+
const requestedPruneMinimum = compactionConfig.pruneMinimum ?? DEFAULT_CONTEXT_LIMITS.pruneMinimum;
|
|
1914
|
+
return {
|
|
1915
|
+
reserveTokens,
|
|
1916
|
+
protectedTokens: Math.min(
|
|
1917
|
+
requestedProtected,
|
|
1918
|
+
Math.max(512, Math.round(usableWindow * 0.6))
|
|
1919
|
+
),
|
|
1920
|
+
pruneMinimum: Math.min(
|
|
1921
|
+
requestedPruneMinimum,
|
|
1922
|
+
Math.max(256, Math.round(usableWindow * 0.5))
|
|
1923
|
+
)
|
|
1924
|
+
};
|
|
1925
|
+
}
|
|
921
1926
|
function createMiddlewareSetup(input, config) {
|
|
922
|
-
|
|
1927
|
+
const inputMiddleware = [...input.middleware ?? []];
|
|
1928
|
+
const hasManualApprovalMiddleware = inputMiddleware.some(
|
|
1929
|
+
(mw) => isApprovalMiddleware(mw)
|
|
1930
|
+
);
|
|
1931
|
+
if (input.approval && hasManualApprovalMiddleware) {
|
|
1932
|
+
throw new Error(
|
|
1933
|
+
"createAgent() received both `approval` config and an explicit approval middleware. Use `approval` for the built-in sugar, or install `approvalMiddleware(...)` manually, but not both."
|
|
1934
|
+
);
|
|
1935
|
+
}
|
|
1936
|
+
let effectiveMiddleware = inputMiddleware;
|
|
923
1937
|
let telemetrySettings;
|
|
924
1938
|
let tracingShutdown;
|
|
1939
|
+
if (input.approval) {
|
|
1940
|
+
effectiveMiddleware.push(approvalMiddleware(input.approval));
|
|
1941
|
+
}
|
|
925
1942
|
if (input.tracing) {
|
|
926
|
-
const agentName = config.name ??
|
|
1943
|
+
const agentName = config.name ?? DEFAULT_AGENT_NAME;
|
|
927
1944
|
const telemetryResult = createTelemetryConfig({
|
|
1945
|
+
...input.tracing,
|
|
928
1946
|
agentName,
|
|
929
|
-
agentDescription: input.tracing.agentDescription,
|
|
930
|
-
recordInputs: input.tracing.recordInputs,
|
|
931
|
-
recordOutputs: input.tracing.recordOutputs,
|
|
932
|
-
emitToolSpans: input.tracing.emitToolSpans,
|
|
933
|
-
spanTimeoutMs: input.tracing.spanTimeoutMs,
|
|
934
|
-
spanProcessor: input.tracing.spanProcessor,
|
|
935
1947
|
serviceName: input.tracing.serviceName ?? agentName
|
|
936
1948
|
});
|
|
937
1949
|
effectiveMiddleware = [
|
|
938
1950
|
telemetryResult.middleware,
|
|
939
|
-
...
|
|
1951
|
+
...effectiveMiddleware
|
|
940
1952
|
];
|
|
941
1953
|
telemetrySettings = telemetryResult.telemetry;
|
|
942
1954
|
tracingShutdown = telemetryResult.shutdown;
|
|
943
1955
|
}
|
|
944
1956
|
return {
|
|
945
|
-
middlewareRunner: new MiddlewareRunner(effectiveMiddleware),
|
|
1957
|
+
middlewareRunner: new MiddlewareRunner(effectiveMiddleware, input.logger),
|
|
946
1958
|
...telemetrySettings ? { telemetrySettings } : {},
|
|
947
1959
|
...tracingShutdown ? { tracingShutdown } : {}
|
|
948
1960
|
};
|
|
949
1961
|
}
|
|
1962
|
+
function resolveHumanInputController(input) {
|
|
1963
|
+
if (!input.humanInput) {
|
|
1964
|
+
return {};
|
|
1965
|
+
}
|
|
1966
|
+
return {
|
|
1967
|
+
humanInputController: isHumanInputController(input.humanInput) ? input.humanInput : createHumanInputController(input.humanInput)
|
|
1968
|
+
};
|
|
1969
|
+
}
|
|
1970
|
+
function resolveExecutionEnvironment(input, config) {
|
|
1971
|
+
if (input.host !== void 0 && input.sandbox !== void 0 && input.host !== input.sandbox.host) {
|
|
1972
|
+
throw new Error(
|
|
1973
|
+
"createAgent() received both `host` and `sandbox`, but `sandbox.host` does not match the provided host. Pass only one execution input, or reuse the same host instance for both."
|
|
1974
|
+
);
|
|
1975
|
+
}
|
|
1976
|
+
if (input.host !== void 0) {
|
|
1977
|
+
return {
|
|
1978
|
+
host: input.host,
|
|
1979
|
+
...input.sandbox ? { sandbox: input.sandbox } : {},
|
|
1980
|
+
ownsHost: false
|
|
1981
|
+
};
|
|
1982
|
+
}
|
|
1983
|
+
if (input.sandbox !== void 0) {
|
|
1984
|
+
return {
|
|
1985
|
+
host: input.sandbox.host,
|
|
1986
|
+
sandbox: input.sandbox,
|
|
1987
|
+
ownsHost: false
|
|
1988
|
+
};
|
|
1989
|
+
}
|
|
1990
|
+
return {
|
|
1991
|
+
host: localHost(config.cwd),
|
|
1992
|
+
ownsHost: true
|
|
1993
|
+
};
|
|
1994
|
+
}
|
|
950
1995
|
function createAgentSetup(input) {
|
|
951
1996
|
const promptBuilder = createAgentPromptBuilder(input);
|
|
952
1997
|
const config = createEffectiveAgentConfig(input);
|
|
953
1998
|
const middlewareSetup = createMiddlewareSetup(input, config);
|
|
1999
|
+
const humanInputSetup = resolveHumanInputController(input);
|
|
2000
|
+
const executionEnvironment = resolveExecutionEnvironment(input, config);
|
|
2001
|
+
const logger = input.logger ?? silentLogger;
|
|
954
2002
|
return {
|
|
955
2003
|
config,
|
|
956
2004
|
tools: createToolMap(input.tools),
|
|
957
2005
|
sessions: input.sessionManager ?? getDefaultSessionManager(),
|
|
958
2006
|
state: createAgentState(config),
|
|
959
2007
|
contextManager: createAgentContextManager(config),
|
|
960
|
-
turnTracker: createTurnTracker({ cwd: config.cwd }),
|
|
2008
|
+
turnTracker: createTurnTracker({ cwd: config.cwd }, logger),
|
|
961
2009
|
...input.mcp ? { mcpManager: input.mcp } : {},
|
|
962
2010
|
...promptBuilder ? { promptBuilder } : {},
|
|
963
2011
|
interventionCtrl: new InterventionController(),
|
|
964
|
-
|
|
2012
|
+
...humanInputSetup,
|
|
2013
|
+
...executionEnvironment,
|
|
965
2014
|
middlewareRunner: middlewareSetup.middlewareRunner,
|
|
2015
|
+
logger,
|
|
966
2016
|
...middlewareSetup.telemetrySettings ? { telemetrySettings: middlewareSetup.telemetrySettings } : {},
|
|
967
2017
|
...middlewareSetup.tracingShutdown ? { tracingShutdown: middlewareSetup.tracingShutdown } : {}
|
|
968
2018
|
};
|
|
969
2019
|
}
|
|
970
2020
|
|
|
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
2021
|
// src/agent/instance.ts
|
|
1038
2022
|
function createAgent(config) {
|
|
1039
2023
|
return new Agent(config);
|
|
@@ -1042,7 +2026,6 @@ var Agent = class _Agent {
|
|
|
1042
2026
|
config;
|
|
1043
2027
|
tools;
|
|
1044
2028
|
sessions;
|
|
1045
|
-
loadedSessions = /* @__PURE__ */ new Set();
|
|
1046
2029
|
state;
|
|
1047
2030
|
/** Context manager for overflow detection and compaction */
|
|
1048
2031
|
contextManager;
|
|
@@ -1066,6 +2049,12 @@ var Agent = class _Agent {
|
|
|
1066
2049
|
interventionCtrl;
|
|
1067
2050
|
/** Execution environment for tool operations */
|
|
1068
2051
|
host;
|
|
2052
|
+
/** Managed sandbox session, when the agent was created from one */
|
|
2053
|
+
sandbox;
|
|
2054
|
+
/** Managed human-input controller for question-style tools */
|
|
2055
|
+
humanInputController;
|
|
2056
|
+
/** Whether the agent owns the host and can safely recreate it on cwd changes */
|
|
2057
|
+
ownsHost;
|
|
1069
2058
|
/** Middleware runner for lifecycle hooks */
|
|
1070
2059
|
middlewareRunner;
|
|
1071
2060
|
/** AI SDK telemetry settings (auto-created from `tracing` config) */
|
|
@@ -1074,6 +2063,14 @@ var Agent = class _Agent {
|
|
|
1074
2063
|
tracingShutdown;
|
|
1075
2064
|
/** Multi-consumer event dispatch */
|
|
1076
2065
|
_signal;
|
|
2066
|
+
/** Number of active turns across all sessions */
|
|
2067
|
+
activeTurnCount = 0;
|
|
2068
|
+
/** Active turn intervention controllers, keyed by turn id */
|
|
2069
|
+
activeTurns = /* @__PURE__ */ new Map();
|
|
2070
|
+
/** Per-session turn queue to prevent concurrent writes to the same history */
|
|
2071
|
+
sessionLocks = /* @__PURE__ */ new Map();
|
|
2072
|
+
/** Structured logger for diagnostic output */
|
|
2073
|
+
_logger;
|
|
1077
2074
|
constructor(config) {
|
|
1078
2075
|
const setup = createAgentSetup(config);
|
|
1079
2076
|
this.config = setup.config;
|
|
@@ -1086,7 +2083,11 @@ var Agent = class _Agent {
|
|
|
1086
2083
|
this.promptBuilder = setup.promptBuilder;
|
|
1087
2084
|
this.interventionCtrl = setup.interventionCtrl;
|
|
1088
2085
|
this.host = setup.host;
|
|
2086
|
+
this.sandbox = setup.sandbox;
|
|
2087
|
+
this.humanInputController = setup.humanInputController;
|
|
2088
|
+
this.ownsHost = setup.ownsHost;
|
|
1089
2089
|
this.middlewareRunner = setup.middlewareRunner;
|
|
2090
|
+
this._logger = setup.logger;
|
|
1090
2091
|
this.telemetrySettings = setup.telemetrySettings;
|
|
1091
2092
|
this.tracingShutdown = setup.tracingShutdown;
|
|
1092
2093
|
this._signal = config.signal ?? new LocalSignal();
|
|
@@ -1101,9 +2102,13 @@ var Agent = class _Agent {
|
|
|
1101
2102
|
get signal() {
|
|
1102
2103
|
return this._signal;
|
|
1103
2104
|
}
|
|
2105
|
+
/** Structured logger — silent by default, configurable via `createAgent({ logger })`. */
|
|
2106
|
+
get logger() {
|
|
2107
|
+
return this._logger;
|
|
2108
|
+
}
|
|
1104
2109
|
/** Agent name (identity for spans, Dapr workflows, etc.) */
|
|
1105
2110
|
get name() {
|
|
1106
|
-
return this.config.name ??
|
|
2111
|
+
return this.config.name ?? DEFAULT_AGENT_NAME;
|
|
1107
2112
|
}
|
|
1108
2113
|
/** Working directory for file operations */
|
|
1109
2114
|
get cwd() {
|
|
@@ -1119,7 +2124,7 @@ var Agent = class _Agent {
|
|
|
1119
2124
|
}
|
|
1120
2125
|
/** Is currently streaming */
|
|
1121
2126
|
get isStreaming() {
|
|
1122
|
-
return this.
|
|
2127
|
+
return this.activeTurnCount > 0;
|
|
1123
2128
|
}
|
|
1124
2129
|
/** Current reasoning level */
|
|
1125
2130
|
get reasoningLevel() {
|
|
@@ -1162,6 +2167,96 @@ var Agent = class _Agent {
|
|
|
1162
2167
|
}
|
|
1163
2168
|
}
|
|
1164
2169
|
}
|
|
2170
|
+
resetPromptScopedTools() {
|
|
2171
|
+
this.tools.delete("skill");
|
|
2172
|
+
this.tools.delete("skill_resource");
|
|
2173
|
+
this.skillToolsResolved = false;
|
|
2174
|
+
}
|
|
2175
|
+
createSessionManager() {
|
|
2176
|
+
return new SessionManager(this.sessions.getStorage());
|
|
2177
|
+
}
|
|
2178
|
+
async acquireSessionLock(sessionId) {
|
|
2179
|
+
const previous = this.sessionLocks.get(sessionId) ?? Promise.resolve();
|
|
2180
|
+
let releaseLock;
|
|
2181
|
+
const current = new Promise((resolve2) => {
|
|
2182
|
+
releaseLock = resolve2;
|
|
2183
|
+
});
|
|
2184
|
+
const chain = previous.catch(() => void 0).then(() => current);
|
|
2185
|
+
this.sessionLocks.set(sessionId, chain);
|
|
2186
|
+
await previous.catch(() => void 0);
|
|
2187
|
+
let released = false;
|
|
2188
|
+
return () => {
|
|
2189
|
+
if (released) return;
|
|
2190
|
+
released = true;
|
|
2191
|
+
releaseLock();
|
|
2192
|
+
if (this.sessionLocks.get(sessionId) === chain) {
|
|
2193
|
+
this.sessionLocks.delete(sessionId);
|
|
2194
|
+
}
|
|
2195
|
+
};
|
|
2196
|
+
}
|
|
2197
|
+
/**
|
|
2198
|
+
* Force-clear all pending session locks for a given session.
|
|
2199
|
+
*
|
|
2200
|
+
* This is an escape hatch for callers that manage sequencing
|
|
2201
|
+
* externally (e.g. the coordinator loop) and need to guarantee a
|
|
2202
|
+
* prior `chat()` generator's lock won't block the next call — even
|
|
2203
|
+
* if the generator's cleanup is stuck on a network read.
|
|
2204
|
+
*
|
|
2205
|
+
* **Only use when you are certain no concurrent `chat()` calls are
|
|
2206
|
+
* active on this session.**
|
|
2207
|
+
*/
|
|
2208
|
+
clearSessionLock(sessionId) {
|
|
2209
|
+
this.sessionLocks.delete(sessionId);
|
|
2210
|
+
}
|
|
2211
|
+
/**
|
|
2212
|
+
* Acquire the same per-session turn lock used by `chat()`.
|
|
2213
|
+
*
|
|
2214
|
+
* External durable runtimes can hold this lock across a workflow-backed
|
|
2215
|
+
* turn so direct `chat()` calls cannot interleave with the same session.
|
|
2216
|
+
*/
|
|
2217
|
+
async acquireSessionTurnLock(sessionId) {
|
|
2218
|
+
return await this.acquireSessionLock(sessionId);
|
|
2219
|
+
}
|
|
2220
|
+
getActiveInterventionController() {
|
|
2221
|
+
const active = Array.from(this.activeTurns.values());
|
|
2222
|
+
if (active.length === 0) {
|
|
2223
|
+
return void 0;
|
|
2224
|
+
}
|
|
2225
|
+
if (active.length > 1) {
|
|
2226
|
+
throw new Error(
|
|
2227
|
+
"Interventions are ambiguous while multiple agent turns are active. Use separate Agent instances or wait for one turn to finish."
|
|
2228
|
+
);
|
|
2229
|
+
}
|
|
2230
|
+
return active[0].interventionCtrl;
|
|
2231
|
+
}
|
|
2232
|
+
getInterventionControllerForTurn() {
|
|
2233
|
+
const activeController = this.getActiveInterventionController();
|
|
2234
|
+
return activeController ?? this.interventionCtrl;
|
|
2235
|
+
}
|
|
2236
|
+
createTurnInterventionController() {
|
|
2237
|
+
return this.activeTurns.size === 0 ? this.interventionCtrl : new InterventionController();
|
|
2238
|
+
}
|
|
2239
|
+
releaseTurnInterventions(controller) {
|
|
2240
|
+
if (controller === this.interventionCtrl) {
|
|
2241
|
+
controller.resetCallbacks();
|
|
2242
|
+
return;
|
|
2243
|
+
}
|
|
2244
|
+
this.interventionCtrl.adoptImmediate(controller.drainImmediate());
|
|
2245
|
+
this.interventionCtrl.adoptDeferred(controller.drainDeferred());
|
|
2246
|
+
controller.resetCallbacks();
|
|
2247
|
+
}
|
|
2248
|
+
syncStreamingState(active) {
|
|
2249
|
+
this.activeTurnCount = Math.max(
|
|
2250
|
+
0,
|
|
2251
|
+
this.activeTurnCount + (active ? 1 : -1)
|
|
2252
|
+
);
|
|
2253
|
+
}
|
|
2254
|
+
async syncSessionView(sessionId) {
|
|
2255
|
+
if (!await this.sessions.sessionExists(sessionId)) {
|
|
2256
|
+
return;
|
|
2257
|
+
}
|
|
2258
|
+
await this.sessions.load(sessionId);
|
|
2259
|
+
}
|
|
1165
2260
|
/**
|
|
1166
2261
|
* Ensure MCP is connected and return tools
|
|
1167
2262
|
* Lazy initialization - only connects on first use
|
|
@@ -1171,34 +2266,11 @@ var Agent = class _Agent {
|
|
|
1171
2266
|
manager: this.mcpManager,
|
|
1172
2267
|
connected: this.mcpConnected,
|
|
1173
2268
|
cachedTools: this.mcpToolsCache
|
|
1174
|
-
});
|
|
2269
|
+
}, this._logger);
|
|
1175
2270
|
this.mcpConnected = nextState.connected;
|
|
1176
2271
|
this.mcpToolsCache = nextState.cachedTools;
|
|
1177
2272
|
return nextState.cachedTools ?? {};
|
|
1178
2273
|
}
|
|
1179
|
-
/**
|
|
1180
|
-
* Repair session history by synthesising missing tool-result messages.
|
|
1181
|
-
*
|
|
1182
|
-
* When a tool `execute()` throws, the AI SDK emits `tool-error` instead
|
|
1183
|
-
* of `tool-result`. If the error event wasn't persisted (e.g. because
|
|
1184
|
-
* the fix above wasn't in place), subsequent turns will fail with
|
|
1185
|
-
* `MissingToolResultsError`. This method detects orphaned tool-call IDs
|
|
1186
|
-
* and adds placeholder `tool` messages so the history is valid again.
|
|
1187
|
-
*/
|
|
1188
|
-
async repairOrphanedToolCalls() {
|
|
1189
|
-
await repairOrphanedToolCalls(this.sessions);
|
|
1190
|
-
}
|
|
1191
|
-
/**
|
|
1192
|
-
* Convert internal {@link Message} array to Vercel AI SDK {@link ModelMessage} format.
|
|
1193
|
-
*
|
|
1194
|
-
* Handles the role-specific mappings:
|
|
1195
|
-
* - `user` / `system` → pass-through
|
|
1196
|
-
* - `assistant` with tool calls → `ToolCallPart[]` content
|
|
1197
|
-
* - `tool` → `tool-result` content part
|
|
1198
|
-
*/
|
|
1199
|
-
toModelMessages(messages) {
|
|
1200
|
-
return convertAgentMessagesToModelMessages(messages);
|
|
1201
|
-
}
|
|
1202
2274
|
/**
|
|
1203
2275
|
* Stream a chat response.
|
|
1204
2276
|
*
|
|
@@ -1212,52 +2284,79 @@ var Agent = class _Agent {
|
|
|
1212
2284
|
* @yields {AgentEvent} Events as they occur during processing
|
|
1213
2285
|
*/
|
|
1214
2286
|
async *chat(sessionId, message, options) {
|
|
1215
|
-
await this.
|
|
1216
|
-
|
|
1217
|
-
const abort = options?.abort ?? new AbortController().signal;
|
|
2287
|
+
const releaseSessionLock = await this.acquireSessionLock(sessionId);
|
|
2288
|
+
const sessions = this.createSessionManager();
|
|
1218
2289
|
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
|
-
|
|
2290
|
+
let turnTracker;
|
|
2291
|
+
let interventionCtrl = this.interventionCtrl;
|
|
2292
|
+
let streamingStateActive = false;
|
|
2293
|
+
let turnRegistered = false;
|
|
2294
|
+
try {
|
|
2295
|
+
await this.ensureSkillTools();
|
|
2296
|
+
const abort = options?.abort ?? new AbortController().signal;
|
|
2297
|
+
turnTracker = createTurnTracker({ cwd: this.config.cwd });
|
|
2298
|
+
interventionCtrl = this.createTurnInterventionController();
|
|
2299
|
+
this.activeTurns.set(turnId, { sessionId, interventionCtrl });
|
|
2300
|
+
turnRegistered = true;
|
|
2301
|
+
await ensureSessionLoaded({
|
|
2302
|
+
sessionId,
|
|
2303
|
+
sessions,
|
|
2304
|
+
cwd: this.config.cwd
|
|
2305
|
+
});
|
|
2306
|
+
turnTracker.startTurn(turnId);
|
|
2307
|
+
await repairOrphanedToolCalls(sessions);
|
|
2308
|
+
const mcpTools = await this.ensureMCPConnected();
|
|
2309
|
+
const loop = runChatLoop({
|
|
2310
|
+
sessionId,
|
|
2311
|
+
turnId,
|
|
2312
|
+
message,
|
|
2313
|
+
abort,
|
|
2314
|
+
systemOverride: options?.system,
|
|
2315
|
+
sessions,
|
|
2316
|
+
tools: this.tools,
|
|
2317
|
+
config: this.config,
|
|
2318
|
+
turnTracker,
|
|
2319
|
+
interventionCtrl,
|
|
2320
|
+
middlewareRunner: this.middlewareRunner,
|
|
2321
|
+
contextManager: this.contextManager,
|
|
2322
|
+
rememberedDoomLoopTools: this.rememberedDoomLoopTools,
|
|
2323
|
+
reasoningLevel: this.state.reasoningLevel,
|
|
2324
|
+
promptBuilder: this.promptBuilder,
|
|
2325
|
+
host: this.host,
|
|
2326
|
+
humanInputController: this.humanInputController,
|
|
2327
|
+
mcpTools,
|
|
2328
|
+
telemetrySettings: this.telemetrySettings,
|
|
2329
|
+
toModelMessages: convertAgentMessagesToModelMessages,
|
|
2330
|
+
setIsStreaming: (value) => {
|
|
2331
|
+
if (value === streamingStateActive) return;
|
|
2332
|
+
streamingStateActive = value;
|
|
2333
|
+
this.syncStreamingState(value);
|
|
2334
|
+
},
|
|
2335
|
+
toolExecutionMode: this.config.toolExecutionMode,
|
|
2336
|
+
logger: this._logger
|
|
2337
|
+
});
|
|
2338
|
+
for await (const event of loop) {
|
|
2339
|
+
this._signal.emit(event);
|
|
2340
|
+
yield event;
|
|
2341
|
+
}
|
|
2342
|
+
} finally {
|
|
2343
|
+
try {
|
|
2344
|
+
if (streamingStateActive) {
|
|
2345
|
+
this.syncStreamingState(false);
|
|
2346
|
+
}
|
|
2347
|
+
if (turnRegistered) {
|
|
2348
|
+
this.activeTurns.delete(turnId);
|
|
2349
|
+
}
|
|
2350
|
+
this.releaseTurnInterventions(interventionCtrl);
|
|
2351
|
+
if (turnRegistered && turnTracker) {
|
|
2352
|
+
this.turnTracker = turnTracker;
|
|
2353
|
+
}
|
|
2354
|
+
await this.syncSessionView(sessionId);
|
|
2355
|
+
} finally {
|
|
2356
|
+
releaseSessionLock();
|
|
1243
2357
|
}
|
|
1244
|
-
});
|
|
1245
|
-
for await (const event of loop) {
|
|
1246
|
-
this._signal.emit(event);
|
|
1247
|
-
yield event;
|
|
1248
2358
|
}
|
|
1249
2359
|
}
|
|
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
2360
|
/**
|
|
1262
2361
|
* Send a message and wait for the complete response (non-streaming).
|
|
1263
2362
|
*
|
|
@@ -1326,13 +2425,20 @@ var Agent = class _Agent {
|
|
|
1326
2425
|
getSessionContext() {
|
|
1327
2426
|
return this.sessions.getContext();
|
|
1328
2427
|
}
|
|
1329
|
-
/**
|
|
2428
|
+
/**
|
|
2429
|
+
* Get messages from current session.
|
|
2430
|
+
*
|
|
2431
|
+
* NOTE: during an active `chat()` turn, messages are accumulated in a
|
|
2432
|
+
* per-turn SessionManager and synced back after the turn completes.
|
|
2433
|
+
* Calling this mid-turn returns the shared view, which may lag behind
|
|
2434
|
+
* the in-progress turn. Use `send()` or consume the `chat()` generator
|
|
2435
|
+
* for real-time access to turn messages.
|
|
2436
|
+
*/
|
|
1330
2437
|
getMessages() {
|
|
1331
2438
|
return this.sessions.getMessages();
|
|
1332
2439
|
}
|
|
1333
2440
|
/** Delete a session */
|
|
1334
2441
|
async deleteSession(sessionId) {
|
|
1335
|
-
this.loadedSessions.delete(sessionId);
|
|
1336
2442
|
return this.sessions.deleteSession(sessionId);
|
|
1337
2443
|
}
|
|
1338
2444
|
/** List all sessions */
|
|
@@ -1368,8 +2474,7 @@ var Agent = class _Agent {
|
|
|
1368
2474
|
* ```
|
|
1369
2475
|
*/
|
|
1370
2476
|
getContextStats() {
|
|
1371
|
-
return
|
|
1372
|
-
this.contextManager,
|
|
2477
|
+
return this.contextManager.getStats(
|
|
1373
2478
|
this.sessions.getMessages()
|
|
1374
2479
|
);
|
|
1375
2480
|
}
|
|
@@ -1382,10 +2487,11 @@ var Agent = class _Agent {
|
|
|
1382
2487
|
* @returns Pruning result with details about what was removed/summarized
|
|
1383
2488
|
*/
|
|
1384
2489
|
async compactContext() {
|
|
1385
|
-
return await compactAgentContext(
|
|
1386
|
-
this.contextManager,
|
|
1387
|
-
this.sessions
|
|
1388
|
-
|
|
2490
|
+
return await compactAgentContext({
|
|
2491
|
+
contextManager: this.contextManager,
|
|
2492
|
+
sessions: this.sessions,
|
|
2493
|
+
logger: this._logger
|
|
2494
|
+
});
|
|
1389
2495
|
}
|
|
1390
2496
|
/**
|
|
1391
2497
|
* Clear remembered doom loop tools.
|
|
@@ -1415,6 +2521,8 @@ var Agent = class _Agent {
|
|
|
1415
2521
|
*
|
|
1416
2522
|
* If called when no turn is active, the message will be picked up
|
|
1417
2523
|
* by the first step of the next `chat()` call.
|
|
2524
|
+
* If multiple turns are active concurrently, this throws because the
|
|
2525
|
+
* target turn would be ambiguous.
|
|
1418
2526
|
*
|
|
1419
2527
|
* @param message - The user message to inject mid-turn
|
|
1420
2528
|
* @returns Intervention ID for tracking
|
|
@@ -1436,7 +2544,7 @@ var Agent = class _Agent {
|
|
|
1436
2544
|
* ```
|
|
1437
2545
|
*/
|
|
1438
2546
|
intervene(message) {
|
|
1439
|
-
return this.
|
|
2547
|
+
return this.getInterventionControllerForTurn().intervene(message);
|
|
1440
2548
|
}
|
|
1441
2549
|
/**
|
|
1442
2550
|
* Queue a message for after the current turn completes.
|
|
@@ -1446,6 +2554,9 @@ var Agent = class _Agent {
|
|
|
1446
2554
|
* `chat()` finishes. The consumer decides whether to send it as a
|
|
1447
2555
|
* new turn.
|
|
1448
2556
|
*
|
|
2557
|
+
* If multiple turns are active concurrently, this throws because the
|
|
2558
|
+
* target turn would be ambiguous.
|
|
2559
|
+
*
|
|
1449
2560
|
* @param message - The message to queue
|
|
1450
2561
|
* @returns Intervention ID for tracking
|
|
1451
2562
|
*
|
|
@@ -1468,15 +2579,15 @@ var Agent = class _Agent {
|
|
|
1468
2579
|
* ```
|
|
1469
2580
|
*/
|
|
1470
2581
|
queueNext(message) {
|
|
1471
|
-
return this.
|
|
2582
|
+
return this.getInterventionControllerForTurn().queueNext(message);
|
|
1472
2583
|
}
|
|
1473
2584
|
/** Whether there are deferred messages queued for after the turn */
|
|
1474
2585
|
hasQueuedNext() {
|
|
1475
|
-
return this.
|
|
2586
|
+
return this.getInterventionControllerForTurn().hasDeferred;
|
|
1476
2587
|
}
|
|
1477
2588
|
/** Drain and return all deferred messages (clears the queue) */
|
|
1478
2589
|
drainQueuedNext() {
|
|
1479
|
-
return this.
|
|
2590
|
+
return this.getInterventionControllerForTurn().drainDeferred();
|
|
1480
2591
|
}
|
|
1481
2592
|
/**
|
|
1482
2593
|
* Get the raw intervention controller for advanced use cases.
|
|
@@ -1488,7 +2599,7 @@ var Agent = class _Agent {
|
|
|
1488
2599
|
* @internal
|
|
1489
2600
|
*/
|
|
1490
2601
|
getInterventionController() {
|
|
1491
|
-
return this.
|
|
2602
|
+
return this.getInterventionControllerForTurn();
|
|
1492
2603
|
}
|
|
1493
2604
|
// ============================================================================
|
|
1494
2605
|
// Turn Tracking
|
|
@@ -1563,28 +2674,37 @@ var Agent = class _Agent {
|
|
|
1563
2674
|
*/
|
|
1564
2675
|
setSystemPrompt(prompt) {
|
|
1565
2676
|
this.config.systemPrompt = prompt;
|
|
1566
|
-
this.state.systemPrompt = prompt;
|
|
1567
2677
|
this.promptBuilder = void 0;
|
|
2678
|
+
this.resetPromptScopedTools();
|
|
1568
2679
|
}
|
|
1569
2680
|
/** Update working directory */
|
|
1570
2681
|
setCwd(cwd) {
|
|
1571
2682
|
this.config.cwd = cwd;
|
|
1572
|
-
this.
|
|
2683
|
+
this.turnTracker = createTurnTracker({ cwd });
|
|
2684
|
+
if (this.ownsHost) {
|
|
2685
|
+
this.host = localHost(cwd);
|
|
2686
|
+
}
|
|
2687
|
+
this.resetPromptScopedTools();
|
|
1573
2688
|
this.promptBuilder?.clearCache();
|
|
1574
2689
|
}
|
|
1575
2690
|
/** Update model */
|
|
1576
2691
|
setModel(model) {
|
|
1577
2692
|
this.config.model = model;
|
|
1578
2693
|
this.state.model = model;
|
|
2694
|
+
if (this.config.compaction?.summaryModel === void 0) {
|
|
2695
|
+
this.contextManager.setModel(model);
|
|
2696
|
+
}
|
|
1579
2697
|
if (this.config.contextWindow === void 0) {
|
|
1580
|
-
const modelId =
|
|
2698
|
+
const modelId = extractModelId(model);
|
|
1581
2699
|
const inferred = inferContextWindow(modelId);
|
|
1582
2700
|
if (inferred) {
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
2701
|
+
this.contextManager.setLimits({
|
|
2702
|
+
contextWindow: inferred,
|
|
2703
|
+
...resolveAgentContextLimits(
|
|
2704
|
+
inferred,
|
|
2705
|
+
this.config.compaction
|
|
2706
|
+
)
|
|
2707
|
+
});
|
|
1588
2708
|
}
|
|
1589
2709
|
}
|
|
1590
2710
|
}
|
|
@@ -1624,6 +2744,7 @@ var Agent = class _Agent {
|
|
|
1624
2744
|
* runtimes can start durable turns without duplicating prompt assembly.
|
|
1625
2745
|
*/
|
|
1626
2746
|
async buildSystemPrompts(sessionId, override) {
|
|
2747
|
+
await this.ensureSkillTools();
|
|
1627
2748
|
return await buildAgentSystemPrompts({
|
|
1628
2749
|
config: this.config,
|
|
1629
2750
|
toolIds: Array.from(this.tools.keys()),
|
|
@@ -1640,7 +2761,8 @@ var Agent = class _Agent {
|
|
|
1640
2761
|
getTurnRuntimeConfig() {
|
|
1641
2762
|
return createAgentTurnRuntimeConfig({
|
|
1642
2763
|
config: this.config,
|
|
1643
|
-
telemetrySettings: this.telemetrySettings
|
|
2764
|
+
telemetrySettings: this.telemetrySettings,
|
|
2765
|
+
reserveTokens: this.contextManager.getLimits().reserveTokens
|
|
1644
2766
|
});
|
|
1645
2767
|
}
|
|
1646
2768
|
/**
|
|
@@ -1649,6 +2771,26 @@ var Agent = class _Agent {
|
|
|
1649
2771
|
getHost() {
|
|
1650
2772
|
return this.host;
|
|
1651
2773
|
}
|
|
2774
|
+
/**
|
|
2775
|
+
* Get the configured sandbox session, if one was provided.
|
|
2776
|
+
*/
|
|
2777
|
+
getSandbox() {
|
|
2778
|
+
return this.sandbox;
|
|
2779
|
+
}
|
|
2780
|
+
/**
|
|
2781
|
+
* Get the configured human-input controller, if one was provided.
|
|
2782
|
+
*/
|
|
2783
|
+
getHumanInputController() {
|
|
2784
|
+
return this.humanInputController;
|
|
2785
|
+
}
|
|
2786
|
+
/**
|
|
2787
|
+
* Whether any registered tool advertises human-input semantics.
|
|
2788
|
+
*/
|
|
2789
|
+
hasHumanInputTools() {
|
|
2790
|
+
return [...this.tools.values()].some(
|
|
2791
|
+
(tool) => tool.capabilitiesHint?.humanInput === true
|
|
2792
|
+
);
|
|
2793
|
+
}
|
|
1652
2794
|
/**
|
|
1653
2795
|
* Get the configured middleware runner.
|
|
1654
2796
|
*
|
|
@@ -1658,6 +2800,18 @@ var Agent = class _Agent {
|
|
|
1658
2800
|
getMiddlewareRunner() {
|
|
1659
2801
|
return this.middlewareRunner;
|
|
1660
2802
|
}
|
|
2803
|
+
/**
|
|
2804
|
+
* Get the configured middleware stack.
|
|
2805
|
+
*/
|
|
2806
|
+
getMiddleware() {
|
|
2807
|
+
return this.middlewareRunner.getMiddleware();
|
|
2808
|
+
}
|
|
2809
|
+
/**
|
|
2810
|
+
* Ensure MCP is connected and return the current MCP tool set.
|
|
2811
|
+
*/
|
|
2812
|
+
async getMcpTools() {
|
|
2813
|
+
return await this.ensureMCPConnected();
|
|
2814
|
+
}
|
|
1661
2815
|
// ============================================================================
|
|
1662
2816
|
// Sub-Agents (Forking)
|
|
1663
2817
|
// ============================================================================
|
|
@@ -1699,6 +2853,9 @@ var Agent = class _Agent {
|
|
|
1699
2853
|
parentTools: Array.from(this.tools.values()),
|
|
1700
2854
|
reasoningLevel: this.state.reasoningLevel,
|
|
1701
2855
|
host: this.host,
|
|
2856
|
+
sandbox: this.sandbox,
|
|
2857
|
+
humanInputController: this.humanInputController,
|
|
2858
|
+
ownsHost: this.ownsHost,
|
|
1702
2859
|
sessions: this.sessions,
|
|
1703
2860
|
mcpManager: this.mcpManager,
|
|
1704
2861
|
middlewareRunner: this.middlewareRunner,
|
|
@@ -1707,29 +2864,29 @@ var Agent = class _Agent {
|
|
|
1707
2864
|
);
|
|
1708
2865
|
}
|
|
1709
2866
|
/**
|
|
1710
|
-
* Create a sub-agent with a
|
|
2867
|
+
* Create a sub-agent with a profile.
|
|
1711
2868
|
*
|
|
1712
|
-
* Convenience method that applies a
|
|
2869
|
+
* Convenience method that applies a profile and returns a forked agent.
|
|
1713
2870
|
*
|
|
1714
2871
|
* @example
|
|
1715
2872
|
* ```typescript
|
|
1716
|
-
* import {
|
|
2873
|
+
* import { Profiles } from "@cuylabs/agent-core";
|
|
1717
2874
|
*
|
|
1718
2875
|
* // Create an exploration sub-agent
|
|
1719
|
-
* const explorer = agent.
|
|
2876
|
+
* const explorer = agent.withProfile(Profiles.explore);
|
|
1720
2877
|
* const result = await explorer.run({
|
|
1721
2878
|
* message: "Find all API routes in this project",
|
|
1722
2879
|
* });
|
|
1723
2880
|
*
|
|
1724
2881
|
* // Create a careful review sub-agent
|
|
1725
|
-
* const reviewer = agent.
|
|
2882
|
+
* const reviewer = agent.withProfile(Profiles.review);
|
|
1726
2883
|
* const review = await reviewer.run({
|
|
1727
2884
|
* message: "Review src/auth.ts for security issues",
|
|
1728
2885
|
* });
|
|
1729
2886
|
* ```
|
|
1730
2887
|
*/
|
|
1731
|
-
|
|
1732
|
-
return this.fork({
|
|
2888
|
+
withProfile(profile) {
|
|
2889
|
+
return this.fork({ profile });
|
|
1733
2890
|
}
|
|
1734
2891
|
/**
|
|
1735
2892
|
* Run a task in an isolated sub-agent session.
|
|
@@ -1750,9 +2907,9 @@ var Agent = class _Agent {
|
|
|
1750
2907
|
* ```
|
|
1751
2908
|
*/
|
|
1752
2909
|
async run(options) {
|
|
2910
|
+
const sessions = this.createSessionManager();
|
|
1753
2911
|
const sessionId = await createSubAgentRunSession({
|
|
1754
|
-
sessions
|
|
1755
|
-
loadedSessions: this.loadedSessions,
|
|
2912
|
+
sessions,
|
|
1756
2913
|
cwd: this.config.cwd,
|
|
1757
2914
|
parentSessionId: options.parentSessionId,
|
|
1758
2915
|
title: options.title
|
|
@@ -1805,6 +2962,7 @@ var Agent = class _Agent {
|
|
|
1805
2962
|
*/
|
|
1806
2963
|
async close() {
|
|
1807
2964
|
this._signal.clear();
|
|
2965
|
+
this.humanInputController?.cancelAll("Agent closed");
|
|
1808
2966
|
if (this.tracingShutdown) {
|
|
1809
2967
|
await this.tracingShutdown();
|
|
1810
2968
|
}
|
|
@@ -1814,29 +2972,243 @@ var Agent = class _Agent {
|
|
|
1814
2972
|
}
|
|
1815
2973
|
};
|
|
1816
2974
|
|
|
1817
|
-
// src/agent/
|
|
1818
|
-
|
|
1819
|
-
const
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
2975
|
+
// src/agent/event-printer.ts
|
|
2976
|
+
function createEventPrinter(options = {}) {
|
|
2977
|
+
const {
|
|
2978
|
+
tools = true,
|
|
2979
|
+
reasoning = true,
|
|
2980
|
+
steps = false,
|
|
2981
|
+
safety = true,
|
|
2982
|
+
completion = true,
|
|
2983
|
+
team = false,
|
|
2984
|
+
stdout = process.stdout,
|
|
2985
|
+
stderr = process.stderr
|
|
2986
|
+
} = options;
|
|
2987
|
+
return (event) => {
|
|
2988
|
+
switch (event.type) {
|
|
2989
|
+
// ── Lifecycle ─────────────────────────────────────────────────
|
|
2990
|
+
case "status":
|
|
2991
|
+
if (steps) stderr.write(`\u23F3 Status \u2192 ${event.status}
|
|
2992
|
+
`);
|
|
2993
|
+
break;
|
|
2994
|
+
case "step-start":
|
|
2995
|
+
if (steps) stderr.write(`\u{1F4CD} Step ${event.step}/${event.maxSteps}
|
|
2996
|
+
`);
|
|
2997
|
+
break;
|
|
2998
|
+
case "step-finish":
|
|
2999
|
+
break;
|
|
3000
|
+
// silent by default
|
|
3001
|
+
case "turn-boundary":
|
|
3002
|
+
if (steps) stderr.write(`\u{1F9F1} Boundary \u2192 ${event.boundary}
|
|
3003
|
+
`);
|
|
3004
|
+
break;
|
|
3005
|
+
// ── Text streaming ────────────────────────────────────────────
|
|
3006
|
+
case "text-start":
|
|
3007
|
+
break;
|
|
3008
|
+
// cursor is already in place
|
|
3009
|
+
case "text-delta":
|
|
3010
|
+
stdout.write(event.text);
|
|
3011
|
+
break;
|
|
3012
|
+
case "text-end":
|
|
3013
|
+
stdout.write("\n");
|
|
3014
|
+
break;
|
|
3015
|
+
// ── Messages ──────────────────────────────────────────────────
|
|
3016
|
+
case "message":
|
|
3017
|
+
break;
|
|
3018
|
+
// too noisy for CLI output
|
|
3019
|
+
// ── Reasoning ─────────────────────────────────────────────────
|
|
3020
|
+
case "reasoning-start":
|
|
3021
|
+
if (reasoning) stderr.write("\u{1F4AD} ");
|
|
3022
|
+
break;
|
|
3023
|
+
case "reasoning-delta":
|
|
3024
|
+
if (reasoning) stderr.write(event.text);
|
|
3025
|
+
break;
|
|
3026
|
+
case "reasoning-end":
|
|
3027
|
+
if (reasoning) stderr.write("\n");
|
|
3028
|
+
break;
|
|
3029
|
+
// ── Tool execution ────────────────────────────────────────────
|
|
3030
|
+
case "tool-start":
|
|
3031
|
+
if (tools)
|
|
3032
|
+
stderr.write(
|
|
3033
|
+
`\u{1F527} ${event.toolName}(${JSON.stringify(event.input)})
|
|
3034
|
+
`
|
|
3035
|
+
);
|
|
3036
|
+
break;
|
|
3037
|
+
case "tool-result":
|
|
3038
|
+
if (tools)
|
|
3039
|
+
stderr.write(` \u2713 ${String(event.result).slice(0, 200)}
|
|
3040
|
+
`);
|
|
3041
|
+
break;
|
|
3042
|
+
case "tool-error":
|
|
3043
|
+
if (tools) stderr.write(` \u2717 ${event.error}
|
|
3044
|
+
`);
|
|
3045
|
+
break;
|
|
3046
|
+
// ── Approval / intervention ───────────────────────────────────
|
|
3047
|
+
case "approval-request":
|
|
3048
|
+
if (safety)
|
|
3049
|
+
stderr.write(
|
|
3050
|
+
`\u{1F6C2} Approval needed \u2192 ${event.request.tool} [${event.request.risk}]
|
|
3051
|
+
`
|
|
3052
|
+
);
|
|
3053
|
+
break;
|
|
3054
|
+
case "approval-resolved":
|
|
3055
|
+
if (safety)
|
|
3056
|
+
stderr.write(`\u{1F6C2} Approval ${event.id} \u2192 ${event.action}
|
|
3057
|
+
`);
|
|
3058
|
+
break;
|
|
3059
|
+
case "intervention-applied":
|
|
3060
|
+
if (safety)
|
|
3061
|
+
stderr.write(`\u270B Intervention \u2192 ${event.message}
|
|
3062
|
+
`);
|
|
3063
|
+
break;
|
|
3064
|
+
case "follow-up-queued":
|
|
3065
|
+
if (safety)
|
|
3066
|
+
stderr.write(`\u{1F4CC} Follow-up queued \u2192 ${event.message}
|
|
3067
|
+
`);
|
|
3068
|
+
break;
|
|
3069
|
+
// ── Safety ────────────────────────────────────────────────────
|
|
3070
|
+
case "doom-loop":
|
|
3071
|
+
if (safety)
|
|
3072
|
+
stderr.write(
|
|
3073
|
+
`\u26A0\uFE0F Doom loop: ${event.toolName} repeated ${event.repeatCount}x
|
|
3074
|
+
`
|
|
3075
|
+
);
|
|
3076
|
+
break;
|
|
3077
|
+
case "context-overflow":
|
|
3078
|
+
if (safety)
|
|
3079
|
+
stderr.write(
|
|
3080
|
+
`\u26A0\uFE0F Context overflow: ${event.inputTokens}/${event.limit} tokens
|
|
3081
|
+
`
|
|
3082
|
+
);
|
|
3083
|
+
break;
|
|
3084
|
+
case "turn-summary":
|
|
3085
|
+
if (safety)
|
|
3086
|
+
stderr.write(
|
|
3087
|
+
`\u{1F5C2}\uFE0F Turn summary \u2192 ${event.files.length} file(s), +${event.additions}/-${event.deletions}
|
|
3088
|
+
`
|
|
3089
|
+
);
|
|
3090
|
+
break;
|
|
3091
|
+
// ── Computer use ──────────────────────────────────────────────
|
|
3092
|
+
case "computer-call":
|
|
3093
|
+
if (tools)
|
|
3094
|
+
stderr.write(`\u{1F5A5}\uFE0F Computer action \u2192 ${event.callId}
|
|
3095
|
+
`);
|
|
3096
|
+
break;
|
|
3097
|
+
case "computer-result":
|
|
3098
|
+
if (tools)
|
|
3099
|
+
stderr.write(`\u{1F5A5}\uFE0F Computer result \u2192 ${event.callId}
|
|
3100
|
+
`);
|
|
3101
|
+
break;
|
|
3102
|
+
// ── Human input ───────────────────────────────────────────────
|
|
3103
|
+
case "human-input-request":
|
|
3104
|
+
if (safety)
|
|
3105
|
+
stderr.write(
|
|
3106
|
+
`\u2753 ${event.request.title}: ${event.request.question}
|
|
3107
|
+
`
|
|
3108
|
+
);
|
|
3109
|
+
break;
|
|
3110
|
+
case "human-input-resolved":
|
|
3111
|
+
break;
|
|
3112
|
+
// host handles display
|
|
3113
|
+
// ── Error & retry ─────────────────────────────────────────────
|
|
3114
|
+
case "retry":
|
|
3115
|
+
stderr.write(
|
|
3116
|
+
`\u{1F501} Retry ${event.attempt} in ${event.delayMs}ms
|
|
3117
|
+
`
|
|
3118
|
+
);
|
|
3119
|
+
break;
|
|
3120
|
+
case "error":
|
|
3121
|
+
stderr.write(`\u274C ${event.error.message}
|
|
3122
|
+
`);
|
|
3123
|
+
break;
|
|
3124
|
+
// ── Completion ────────────────────────────────────────────────
|
|
3125
|
+
case "complete":
|
|
3126
|
+
if (completion)
|
|
3127
|
+
stderr.write(
|
|
3128
|
+
`\u2705 Done \u2014 ${event.usage?.totalTokens ?? "?"} tokens
|
|
3129
|
+
`
|
|
3130
|
+
);
|
|
3131
|
+
break;
|
|
3132
|
+
// ── Team events ───────────────────────────────────────────────
|
|
3133
|
+
default:
|
|
3134
|
+
if (team && "type" in event && event.type.startsWith("team-")) {
|
|
3135
|
+
printTeamEvent(stderr, event);
|
|
3136
|
+
}
|
|
3137
|
+
break;
|
|
1832
3138
|
}
|
|
3139
|
+
};
|
|
3140
|
+
}
|
|
3141
|
+
function printTeamEvent(out, event) {
|
|
3142
|
+
switch (event.type) {
|
|
3143
|
+
case "team-started":
|
|
3144
|
+
out.write(`\u{1F3C1} Team started
|
|
3145
|
+
`);
|
|
3146
|
+
break;
|
|
3147
|
+
case "team-member-registered":
|
|
3148
|
+
out.write(
|
|
3149
|
+
` \u{1F464} ${event.member.id} (${event.member.role})
|
|
3150
|
+
`
|
|
3151
|
+
);
|
|
3152
|
+
break;
|
|
3153
|
+
case "team-task-completed":
|
|
3154
|
+
out.write(
|
|
3155
|
+
` \u2705 Task ${event.taskId} completed
|
|
3156
|
+
`
|
|
3157
|
+
);
|
|
3158
|
+
break;
|
|
3159
|
+
case "team-task-failed":
|
|
3160
|
+
out.write(
|
|
3161
|
+
` \u274C Task ${event.taskId} failed
|
|
3162
|
+
`
|
|
3163
|
+
);
|
|
3164
|
+
break;
|
|
3165
|
+
case "team-stopped":
|
|
3166
|
+
out.write(`\u{1F3C1} Team stopped
|
|
3167
|
+
`);
|
|
3168
|
+
break;
|
|
1833
3169
|
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
3170
|
+
}
|
|
3171
|
+
|
|
3172
|
+
// src/intervention/follow-up-policy.ts
|
|
3173
|
+
function normalizeFollowUpMode(mode) {
|
|
3174
|
+
return mode ?? "suggest";
|
|
3175
|
+
}
|
|
3176
|
+
function createQueuedFollowUpRecord(request, options = {}) {
|
|
3177
|
+
const createdAt = options.createdAt ?? new Date(request.timestamp).toISOString();
|
|
3178
|
+
return {
|
|
3179
|
+
id: request.id,
|
|
3180
|
+
sessionId: request.sessionId,
|
|
3181
|
+
message: request.message,
|
|
3182
|
+
createdAt,
|
|
3183
|
+
updatedAt: options.updatedAt ?? createdAt,
|
|
3184
|
+
mode: normalizeFollowUpMode(options.mode),
|
|
3185
|
+
status: "queued",
|
|
3186
|
+
...options.sourceTurnId ? { sourceTurnId: options.sourceTurnId } : {},
|
|
3187
|
+
...options.workflowInstanceId ? { workflowInstanceId: options.workflowInstanceId } : {}
|
|
3188
|
+
};
|
|
3189
|
+
}
|
|
3190
|
+
function resolveQueuedFollowUp(record, action, updatedAt) {
|
|
3191
|
+
return {
|
|
3192
|
+
...record,
|
|
3193
|
+
status: action === "accept" ? "accepted" : "discarded",
|
|
3194
|
+
updatedAt,
|
|
3195
|
+
decidedAt: updatedAt
|
|
3196
|
+
};
|
|
3197
|
+
}
|
|
3198
|
+
function markQueuedFollowUpApplied(record, updatedAt, seededTurnId) {
|
|
3199
|
+
return {
|
|
3200
|
+
...record,
|
|
3201
|
+
status: "applied",
|
|
3202
|
+
updatedAt,
|
|
3203
|
+
appliedAt: updatedAt,
|
|
3204
|
+
...seededTurnId ? { seededTurnId } : {}
|
|
3205
|
+
};
|
|
3206
|
+
}
|
|
3207
|
+
function canSeedQueuedFollowUp(record) {
|
|
3208
|
+
if (record.status === "accepted") {
|
|
3209
|
+
return true;
|
|
3210
|
+
}
|
|
3211
|
+
return record.status === "queued" && record.mode === "auto-run";
|
|
1840
3212
|
}
|
|
1841
3213
|
export {
|
|
1842
3214
|
Agent,
|
|
@@ -1847,37 +3219,49 @@ export {
|
|
|
1847
3219
|
CapabilityCache,
|
|
1848
3220
|
ContextManager,
|
|
1849
3221
|
ContextOverflowError,
|
|
3222
|
+
DEFAULT_AGENT_NAME,
|
|
1850
3223
|
DEFAULT_CONTEXT_LIMITS,
|
|
3224
|
+
DEFAULT_DISPATCH_TOOL_IDS,
|
|
1851
3225
|
DEFAULT_EXTERNAL_DIRS,
|
|
1852
3226
|
DEFAULT_INSTRUCTION_PATTERNS,
|
|
1853
|
-
|
|
3227
|
+
DEFAULT_LOCAL_DISPATCH_CONCURRENCY,
|
|
3228
|
+
DEFAULT_LOCAL_DISPATCH_DEPTH,
|
|
3229
|
+
DEFAULT_LOCAL_DISPATCH_TITLE_PREFIX,
|
|
1854
3230
|
DEFAULT_MAX_DEPTH,
|
|
1855
3231
|
DEFAULT_MAX_FILE_SIZE,
|
|
1856
|
-
DEFAULT_MAX_OUTPUT_TOKENS,
|
|
3232
|
+
DEFAULT_MAX_TOKENS as DEFAULT_MAX_OUTPUT_TOKENS,
|
|
1857
3233
|
DEFAULT_MAX_SCAN_DEPTH,
|
|
1858
|
-
DEFAULT_MAX_SPAWN_DEPTH,
|
|
1859
3234
|
DEFAULT_MAX_STEPS,
|
|
1860
3235
|
DEFAULT_MAX_TOKENS,
|
|
1861
3236
|
DEFAULT_RESOLVER_OPTIONS,
|
|
1862
3237
|
DEFAULT_RETRY_CONFIG,
|
|
1863
|
-
DEFAULT_SESSION_TITLE_PREFIX,
|
|
1864
3238
|
DEFAULT_SKILL_MAX_SIZE,
|
|
3239
|
+
DEFAULT_SUBAGENT_CONCURRENCY,
|
|
3240
|
+
DEFAULT_SUBAGENT_DEPTH,
|
|
3241
|
+
DEFAULT_SUBAGENT_SESSION_PREFIX,
|
|
1865
3242
|
DEFAULT_SYSTEM_PROMPT,
|
|
3243
|
+
DISPATCH_STATES,
|
|
1866
3244
|
DoomLoopError,
|
|
1867
3245
|
EXTENDED_LEVELS,
|
|
1868
3246
|
FIXED_LEVELS,
|
|
1869
3247
|
FileStorage,
|
|
3248
|
+
HumanInputTimeoutError,
|
|
3249
|
+
HumanInputUnavailableError,
|
|
3250
|
+
InMemoryMailboxStore,
|
|
3251
|
+
InMemoryTaskBoardStore,
|
|
1870
3252
|
Inference,
|
|
1871
3253
|
InterventionController,
|
|
1872
|
-
LLM,
|
|
1873
3254
|
LLMError,
|
|
3255
|
+
LOCAL_SUBAGENT_BACKEND,
|
|
3256
|
+
LayeredSettings,
|
|
1874
3257
|
LocalSignal,
|
|
1875
3258
|
MAX_BYTES,
|
|
1876
3259
|
MAX_LINES,
|
|
3260
|
+
Mailbox,
|
|
1877
3261
|
MemoryStorage,
|
|
1878
3262
|
MiddlewareRunner,
|
|
1879
3263
|
ModelCapabilityResolver,
|
|
1880
|
-
|
|
3264
|
+
NullSettings,
|
|
1881
3265
|
PRIORITY_BASE,
|
|
1882
3266
|
PRIORITY_CUSTOM,
|
|
1883
3267
|
PRIORITY_ENVIRONMENT,
|
|
@@ -1886,37 +3270,54 @@ export {
|
|
|
1886
3270
|
PRIORITY_SKILLS,
|
|
1887
3271
|
PRUNE_PROTECTED_TOOLS,
|
|
1888
3272
|
PatternCapabilitySource,
|
|
1889
|
-
|
|
3273
|
+
PluginEventBus,
|
|
3274
|
+
PluginRegistry,
|
|
3275
|
+
Profiles,
|
|
1890
3276
|
PromptBuilder,
|
|
1891
3277
|
RemoteCapabilityFetcher,
|
|
1892
3278
|
RemoteCapabilitySource,
|
|
1893
3279
|
SKILL_FILENAME,
|
|
1894
3280
|
STANDARD_LEVELS,
|
|
1895
3281
|
STORAGE_VERSION,
|
|
3282
|
+
SUBAGENT_TOOL_IDS,
|
|
1896
3283
|
SessionManager,
|
|
1897
3284
|
SkillRegistry,
|
|
1898
3285
|
SourcePriority,
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
3286
|
+
StaticSettings,
|
|
3287
|
+
TERMINAL_STATUSES,
|
|
3288
|
+
TaskBoard,
|
|
3289
|
+
TaskConflictError,
|
|
3290
|
+
TeamCoordinator,
|
|
1902
3291
|
Tool,
|
|
3292
|
+
ToolHostRegistry,
|
|
1903
3293
|
ToolRegistry,
|
|
1904
3294
|
TurnChangeTracker,
|
|
3295
|
+
ValidatedSettings,
|
|
3296
|
+
accumulateUsage,
|
|
3297
|
+
addTokenUsage,
|
|
1905
3298
|
advanceAgentTurnState,
|
|
3299
|
+
allApprovalConditions,
|
|
3300
|
+
anyApprovalConditions,
|
|
1906
3301
|
applyAgentWorkflowCommitResult,
|
|
1907
3302
|
applyAgentWorkflowModelStepResult,
|
|
1908
3303
|
applyAgentWorkflowToolBatchResult,
|
|
1909
3304
|
applyAgentWorkflowToolCallResult,
|
|
1910
3305
|
applyCapabilityOverride,
|
|
1911
|
-
|
|
3306
|
+
applyProfile,
|
|
3307
|
+
applyWorkflowInterventions,
|
|
1912
3308
|
approvalMiddleware,
|
|
3309
|
+
approvalRequestsOverlap,
|
|
1913
3310
|
autoDetectStreamProvider,
|
|
1914
3311
|
buildAnthropicOptions,
|
|
3312
|
+
buildApprovalRuleContext,
|
|
1915
3313
|
buildBedrockOptions,
|
|
3314
|
+
buildCoordinatorNotificationEvent,
|
|
3315
|
+
buildCoordinatorSystemPrompt,
|
|
1916
3316
|
buildEntryPath,
|
|
1917
3317
|
buildGoogleOptions,
|
|
1918
3318
|
buildGroqOptions,
|
|
1919
3319
|
buildMessagesFromEntries,
|
|
3320
|
+
buildModelCallContext,
|
|
1920
3321
|
buildOpenAIOptions,
|
|
1921
3322
|
buildOpenRouterOptions,
|
|
1922
3323
|
buildReasoningOptions,
|
|
@@ -1924,55 +3325,95 @@ export {
|
|
|
1924
3325
|
buildToolSet,
|
|
1925
3326
|
buildXAIOptions,
|
|
1926
3327
|
calculateDelay,
|
|
3328
|
+
canSeedQueuedFollowUp,
|
|
1927
3329
|
careful,
|
|
1928
|
-
|
|
3330
|
+
clearInstalledSubAgents,
|
|
1929
3331
|
cloneAgentWorkflowTurnState,
|
|
1930
3332
|
code,
|
|
1931
3333
|
commitOutput,
|
|
1932
3334
|
commitStep,
|
|
1933
3335
|
configureDefaultSessionManager,
|
|
1934
3336
|
configureResolver,
|
|
3337
|
+
configureSubAgents,
|
|
1935
3338
|
convertAgentMessagesToModelMessages,
|
|
3339
|
+
coordinatorToolDescriptions,
|
|
1936
3340
|
createAgent,
|
|
1937
3341
|
createAgentTaskRunner,
|
|
1938
3342
|
createAgentTurnEngine,
|
|
1939
3343
|
createAgentTurnState,
|
|
1940
3344
|
createAgentTurnStepCommitBatch,
|
|
1941
3345
|
createAgentWorkflowTurnState,
|
|
3346
|
+
createApprovalCorrection,
|
|
1942
3347
|
createApprovalHandler,
|
|
1943
|
-
|
|
3348
|
+
createApprovalPolicyPreset,
|
|
3349
|
+
createCloseAgentTool,
|
|
3350
|
+
createCompositeDispatchTaskExecutor,
|
|
3351
|
+
createConditionalApprovalRule,
|
|
3352
|
+
createConsoleLogger,
|
|
3353
|
+
createDangerouslyAllowAllApprovalPolicy,
|
|
3354
|
+
createDispatchExternalTaskControl,
|
|
3355
|
+
createDispatchTaskExecutor,
|
|
3356
|
+
createDispatchTools,
|
|
3357
|
+
createEventBus,
|
|
3358
|
+
createEventPrinter,
|
|
3359
|
+
createFileLogger,
|
|
3360
|
+
createHeadlessDenyApprovalPolicy,
|
|
3361
|
+
createHumanInputController,
|
|
3362
|
+
createHumanInputHandler,
|
|
3363
|
+
createHumanInputTool,
|
|
3364
|
+
createHumanInputToolWithController,
|
|
3365
|
+
createHumanInputToolWithHandler,
|
|
3366
|
+
createInteractiveApprovalPolicy,
|
|
3367
|
+
createInvokeAgentTool,
|
|
3368
|
+
createLocalDispatchRuntime,
|
|
1944
3369
|
createMCPManager,
|
|
1945
3370
|
createMessageEntry,
|
|
1946
3371
|
createMetadataEntry,
|
|
1947
|
-
|
|
3372
|
+
createProfile,
|
|
1948
3373
|
createPromptBuilder,
|
|
3374
|
+
createQueuedFollowUpRecord,
|
|
3375
|
+
createRememberedApprovalRules,
|
|
1949
3376
|
createResolver,
|
|
1950
3377
|
createRetryHandler,
|
|
1951
3378
|
createRetryState,
|
|
1952
|
-
|
|
3379
|
+
createRiskTierApprovalPolicy,
|
|
3380
|
+
createRuntimeDispatchExecutor,
|
|
3381
|
+
createRuntimeDispatchTargets,
|
|
1953
3382
|
createSkillRegistry,
|
|
1954
3383
|
createSkillResourceTool,
|
|
1955
3384
|
createSkillTool,
|
|
1956
3385
|
createSkillTools,
|
|
1957
3386
|
createSubAgentTools,
|
|
3387
|
+
createTeamCoordinator,
|
|
1958
3388
|
createTelemetryConfig,
|
|
3389
|
+
createThresholdApprovalRule,
|
|
3390
|
+
createToolSearchTool,
|
|
3391
|
+
createTrustedSessionApprovalPolicy,
|
|
1959
3392
|
createTurnTracker,
|
|
3393
|
+
createWaitAgentTool,
|
|
1960
3394
|
currentScope,
|
|
1961
3395
|
defaultAgentTaskCheckpointStrategy,
|
|
1962
3396
|
defaultRegistry,
|
|
1963
|
-
|
|
1964
|
-
|
|
3397
|
+
defaultToolHostRegistry,
|
|
3398
|
+
definePlugin,
|
|
3399
|
+
describeApprovalOperation,
|
|
1965
3400
|
deserializeMessage,
|
|
1966
3401
|
detectModelFamily,
|
|
1967
3402
|
discoverInstructions,
|
|
3403
|
+
discoverPlugins,
|
|
1968
3404
|
discoverSkills,
|
|
1969
|
-
|
|
3405
|
+
discoverSubAgentRoles,
|
|
3406
|
+
drainWorkflowInterventions,
|
|
1970
3407
|
emptySkillRegistry,
|
|
3408
|
+
ensureNonEmpty,
|
|
3409
|
+
ensureSessionLoaded,
|
|
1971
3410
|
estimateConversationTokens,
|
|
1972
3411
|
estimateMessageTokens,
|
|
1973
3412
|
estimateTokens,
|
|
3413
|
+
evaluateCoordinatorRoundTransition,
|
|
1974
3414
|
executeAgentToolCall,
|
|
1975
3415
|
explore,
|
|
3416
|
+
extractApprovalPatterns,
|
|
1976
3417
|
extractFilePathsFromArgs,
|
|
1977
3418
|
extractModelId,
|
|
1978
3419
|
extractProvider,
|
|
@@ -1982,76 +3423,123 @@ export {
|
|
|
1982
3423
|
filterTools,
|
|
1983
3424
|
findCapabilityOverride,
|
|
1984
3425
|
findCutPoint,
|
|
3426
|
+
formatApprovalDeniedReason,
|
|
3427
|
+
formatAsyncSpawnedResult,
|
|
3428
|
+
formatCancelledAgentResult,
|
|
3429
|
+
formatCloseAlreadyResolvedResult,
|
|
3430
|
+
formatCloseMissingAgentResult,
|
|
3431
|
+
formatCoordinatorRoundMessage,
|
|
3432
|
+
formatCoordinatorTaskNotifications,
|
|
3433
|
+
formatCoordinatorWorkerReports,
|
|
1985
3434
|
formatEnvironment,
|
|
1986
3435
|
formatInstructions,
|
|
1987
|
-
|
|
3436
|
+
formatInvalidAgentTypeResult,
|
|
3437
|
+
formatMissingAgentsResult,
|
|
3438
|
+
formatSpawnBlockedResult,
|
|
3439
|
+
formatSyncSubAgentErrorResult,
|
|
3440
|
+
formatSyncSubAgentResult,
|
|
3441
|
+
formatWaitErrorResult,
|
|
3442
|
+
formatWaitResult,
|
|
3443
|
+
formatWaitTimeoutResult,
|
|
1988
3444
|
gatherEnvironment,
|
|
1989
3445
|
generateEntryId,
|
|
1990
|
-
generateSummary,
|
|
1991
3446
|
getAvailableFamilies,
|
|
3447
|
+
getConfiguredSubAgents,
|
|
1992
3448
|
getDataDir,
|
|
1993
3449
|
getDefaultResolver,
|
|
1994
3450
|
getDefaultSessionManager,
|
|
1995
3451
|
getErrorCategory,
|
|
1996
3452
|
getGitRootHash,
|
|
3453
|
+
getInstalledSubAgentBackend,
|
|
1997
3454
|
getLeafId,
|
|
1998
3455
|
getModelId,
|
|
1999
3456
|
getNetworkStatus,
|
|
3457
|
+
getPluginLoader,
|
|
2000
3458
|
getProjectId,
|
|
2001
3459
|
getProjectSessionsDir,
|
|
3460
|
+
getProjectSubAgentRolesDir,
|
|
2002
3461
|
getProviderCompatibility,
|
|
2003
3462
|
getProviderId,
|
|
2004
3463
|
getProviderOptionsKey,
|
|
2005
3464
|
getReasoningConfig,
|
|
2006
3465
|
getReasoningConfigSync,
|
|
3466
|
+
getRequiredToolHost,
|
|
2007
3467
|
getRetryDelay,
|
|
2008
3468
|
getSessionsDir,
|
|
2009
3469
|
getTemplate,
|
|
2010
3470
|
getToolRisk,
|
|
2011
|
-
|
|
3471
|
+
getUsableTokenLimit,
|
|
3472
|
+
getUserSubAgentRolesDir,
|
|
2012
3473
|
httpServer,
|
|
2013
3474
|
inferContextWindow,
|
|
2014
3475
|
inferProvider,
|
|
2015
3476
|
inferResourceType,
|
|
2016
|
-
|
|
3477
|
+
installLocalSubAgents,
|
|
3478
|
+
installSubAgentTools,
|
|
3479
|
+
isApprovalMiddleware,
|
|
3480
|
+
isBlockedModelCall,
|
|
3481
|
+
isDefinedPlugin,
|
|
3482
|
+
isHumanInputController,
|
|
3483
|
+
isMarkdownSubAgentRole,
|
|
2017
3484
|
isRetryable,
|
|
2018
3485
|
isRetryableCategory,
|
|
2019
3486
|
likelySupportsReasoning,
|
|
2020
3487
|
loadGlobalInstructions,
|
|
3488
|
+
loadPluginModule,
|
|
2021
3489
|
loadResourceContent,
|
|
2022
3490
|
loadSkillContent,
|
|
2023
3491
|
loadSkillMetadata,
|
|
2024
3492
|
localHost,
|
|
2025
|
-
|
|
2026
|
-
|
|
3493
|
+
markQueuedFollowUpApplied,
|
|
3494
|
+
matchApprovalArgValue,
|
|
3495
|
+
matchApprovalNumericArg,
|
|
3496
|
+
matchApprovalPattern,
|
|
3497
|
+
matchApprovalRisks,
|
|
3498
|
+
matchApprovalSessions,
|
|
3499
|
+
matchApprovalStringPrefixes,
|
|
3500
|
+
mergeInspection,
|
|
3501
|
+
mergeProfiles,
|
|
3502
|
+
normalizeApprovalCascadePolicy,
|
|
3503
|
+
normalizeFollowUpMode,
|
|
3504
|
+
normalizeRememberScopes,
|
|
2027
3505
|
normalizeToolReplayPolicy,
|
|
2028
3506
|
otelMiddleware,
|
|
2029
3507
|
parseFrontmatter,
|
|
2030
3508
|
parseJSONL,
|
|
3509
|
+
parseMarkdownSubAgentRole,
|
|
2031
3510
|
parseRetryDelay,
|
|
3511
|
+
parseSubAgentRoleFrontmatter,
|
|
3512
|
+
parseSubAgentToolSpec,
|
|
2032
3513
|
plan,
|
|
2033
3514
|
planNextAgentWorkflowOperation,
|
|
2034
3515
|
prepareModelStep,
|
|
2035
3516
|
processStepStream,
|
|
2036
|
-
processStream,
|
|
2037
3517
|
promptCacheMiddleware,
|
|
2038
|
-
|
|
2039
|
-
pruneToolResults,
|
|
3518
|
+
queueWorkflowFollowUps,
|
|
2040
3519
|
quick,
|
|
2041
3520
|
recordAgentWorkflowReplayDecision,
|
|
3521
|
+
requiresToolHost,
|
|
3522
|
+
resetFrameworkAliases,
|
|
3523
|
+
resetPluginLoader,
|
|
3524
|
+
resolveAgentDefaults,
|
|
3525
|
+
resolveCapability,
|
|
3526
|
+
resolveFrameworkAliases,
|
|
3527
|
+
resolveQueuedFollowUp,
|
|
2042
3528
|
restoreAgentWorkflowMessage,
|
|
2043
3529
|
restoreAgentWorkflowMessages,
|
|
2044
3530
|
restoreScope,
|
|
2045
3531
|
review,
|
|
2046
3532
|
runChatLoop,
|
|
2047
|
-
runConcurrent,
|
|
2048
3533
|
runModelStep,
|
|
2049
3534
|
runToolBatch,
|
|
3535
|
+
sandboxDefaultsProvider,
|
|
3536
|
+
selectRememberScope,
|
|
2050
3537
|
serializeMessage,
|
|
2051
3538
|
shouldCaptureBaseline,
|
|
3539
|
+
shouldCascadeApprovalDecision,
|
|
2052
3540
|
shouldIncludeReasoningSummary,
|
|
2053
|
-
shouldPruneContext,
|
|
2054
3541
|
shouldRetry,
|
|
3542
|
+
silentLogger,
|
|
2055
3543
|
sleep,
|
|
2056
3544
|
snapshotAgentWorkflowMessage,
|
|
2057
3545
|
snapshotAgentWorkflowMessages,
|
|
@@ -2064,11 +3552,12 @@ export {
|
|
|
2064
3552
|
summarizeEnvironment,
|
|
2065
3553
|
supportsReasoning,
|
|
2066
3554
|
supportsReasoningSync,
|
|
3555
|
+
teamPermissionPolicy,
|
|
2067
3556
|
toJSONL,
|
|
2068
3557
|
toJSONLBatch,
|
|
3558
|
+
toSubAgentRole,
|
|
2069
3559
|
truncateOutput,
|
|
2070
3560
|
watch,
|
|
2071
|
-
withFileTracking,
|
|
2072
3561
|
withRetry,
|
|
2073
3562
|
withinScope
|
|
2074
3563
|
};
|