@robota-sdk/agent-sdk 3.0.0-beta.59 → 3.0.0-beta.60
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 +8 -21
- package/dist/node/index.cjs +1690 -898
- package/dist/node/index.d.cts +738 -246
- package/dist/node/index.d.ts +738 -246
- package/dist/node/index.js +1487 -805
- package/package.json +5 -5
package/dist/node/index.cjs
CHANGED
|
@@ -30,7 +30,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
AUTO_COMPACT_THRESHOLD_SETTINGS_KEY: () => AUTO_COMPACT_THRESHOLD_SETTINGS_KEY,
|
|
33
34
|
AgentExecutor: () => AgentExecutor,
|
|
35
|
+
BACKGROUND_COMMAND_DESCRIPTION: () => BACKGROUND_COMMAND_DESCRIPTION,
|
|
36
|
+
BACKGROUND_COMMAND_USAGE: () => BACKGROUND_COMMAND_USAGE,
|
|
34
37
|
BUILT_IN_AGENTS: () => BUILT_IN_AGENTS,
|
|
35
38
|
BackgroundJobOrchestrator: () => BackgroundJobOrchestrator,
|
|
36
39
|
BackgroundTaskError: () => import_agent_runtime5.BackgroundTaskError,
|
|
@@ -38,71 +41,178 @@ __export(index_exports, {
|
|
|
38
41
|
BuiltinCommandSource: () => BuiltinCommandSource,
|
|
39
42
|
BundlePluginInstaller: () => BundlePluginInstaller,
|
|
40
43
|
BundlePluginLoader: () => BundlePluginLoader,
|
|
44
|
+
CLEAR_COMMAND_DESCRIPTION: () => CLEAR_COMMAND_DESCRIPTION,
|
|
45
|
+
COST_COMMAND_DESCRIPTION: () => COST_COMMAND_DESCRIPTION,
|
|
41
46
|
CommandRegistry: () => CommandRegistry,
|
|
47
|
+
DEFAULT_AUTO_COMPACT_THRESHOLD: () => DEFAULT_AUTO_COMPACT_THRESHOLD,
|
|
48
|
+
DEFAULT_STATUS_LINE_COMMAND_SETTINGS: () => DEFAULT_STATUS_LINE_COMMAND_SETTINGS,
|
|
49
|
+
EXIT_COMMAND_DESCRIPTION: () => EXIT_COMMAND_DESCRIPTION,
|
|
42
50
|
EditCheckpointStore: () => EditCheckpointStore,
|
|
51
|
+
HELP_COMMAND_DESCRIPTION: () => HELP_COMMAND_DESCRIPTION,
|
|
43
52
|
InteractiveSession: () => InteractiveSession,
|
|
53
|
+
LANGUAGE_COMMAND_ARGUMENT_HINT: () => LANGUAGE_COMMAND_ARGUMENT_HINT,
|
|
54
|
+
LANGUAGE_COMMAND_DESCRIPTION: () => LANGUAGE_COMMAND_DESCRIPTION,
|
|
55
|
+
MEMORY_COMMAND_ARGUMENT_HINT: () => MEMORY_COMMAND_ARGUMENT_HINT,
|
|
56
|
+
MEMORY_COMMAND_DESCRIPTION: () => MEMORY_COMMAND_DESCRIPTION,
|
|
57
|
+
MEMORY_COMMAND_USAGE: () => MEMORY_COMMAND_USAGE,
|
|
44
58
|
MEMORY_INDEX_MAX_BYTES: () => MEMORY_INDEX_MAX_BYTES,
|
|
45
59
|
MEMORY_INDEX_MAX_LINES: () => MEMORY_INDEX_MAX_LINES,
|
|
60
|
+
MODEL_COMMAND_ARGUMENT_HINT: () => MODEL_COMMAND_ARGUMENT_HINT,
|
|
61
|
+
MODEL_COMMAND_DESCRIPTION: () => MODEL_COMMAND_DESCRIPTION,
|
|
46
62
|
MarketplaceClient: () => MarketplaceClient,
|
|
63
|
+
PERMISSIONS_COMMAND_DESCRIPTION: () => PERMISSIONS_COMMAND_DESCRIPTION,
|
|
64
|
+
PERMISSION_MODE_ARGUMENT_HINT: () => PERMISSION_MODE_ARGUMENT_HINT,
|
|
65
|
+
PERMISSION_MODE_COMMAND_DESCRIPTION: () => PERMISSION_MODE_COMMAND_DESCRIPTION,
|
|
66
|
+
PLUGIN_COMMAND_ARGUMENT_HINT: () => PLUGIN_COMMAND_ARGUMENT_HINT,
|
|
67
|
+
PLUGIN_COMMAND_DESCRIPTION: () => PLUGIN_COMMAND_DESCRIPTION,
|
|
47
68
|
PluginCommandSource: () => PluginCommandSource,
|
|
48
69
|
PluginSettingsStore: () => PluginSettingsStore,
|
|
49
70
|
ProjectMemoryStore: () => ProjectMemoryStore,
|
|
50
71
|
PromptExecutor: () => PromptExecutor,
|
|
72
|
+
RECOMMENDED_RESPONSE_LANGUAGES: () => RECOMMENDED_RESPONSE_LANGUAGES,
|
|
73
|
+
RELOAD_PLUGINS_COMMAND_DESCRIPTION: () => RELOAD_PLUGINS_COMMAND_DESCRIPTION,
|
|
74
|
+
RENAME_COMMAND_DESCRIPTION: () => RENAME_COMMAND_DESCRIPTION,
|
|
75
|
+
RENAME_COMMAND_USAGE: () => RENAME_COMMAND_USAGE,
|
|
76
|
+
RESUME_COMMAND_DESCRIPTION: () => RESUME_COMMAND_DESCRIPTION,
|
|
77
|
+
REWIND_COMMAND_ARGUMENT_HINT: () => REWIND_COMMAND_ARGUMENT_HINT,
|
|
78
|
+
REWIND_COMMAND_DESCRIPTION: () => REWIND_COMMAND_DESCRIPTION,
|
|
79
|
+
STATUSLINE_COMMAND_ARGUMENT_HINT: () => STATUSLINE_COMMAND_ARGUMENT_HINT,
|
|
80
|
+
STATUSLINE_COMMAND_DESCRIPTION: () => STATUSLINE_COMMAND_DESCRIPTION,
|
|
51
81
|
SkillCommandSource: () => SkillCommandSource,
|
|
52
82
|
SubagentManager: () => import_agent_runtime7.SubagentManager,
|
|
53
83
|
SystemCommandExecutor: () => SystemCommandExecutor,
|
|
54
|
-
TRUST_TO_MODE: () =>
|
|
84
|
+
TRUST_TO_MODE: () => import_agent_core8.TRUST_TO_MODE,
|
|
85
|
+
VALID_PERMISSION_MODES: () => VALID_PERMISSION_MODES,
|
|
55
86
|
WorktreeSubagentRunner: () => import_agent_runtime8.WorktreeSubagentRunner,
|
|
56
87
|
assembleSubagentPrompt: () => assembleSubagentPrompt,
|
|
88
|
+
buildBackgroundCommandSubcommands: () => buildBackgroundCommandSubcommands,
|
|
89
|
+
buildLanguageCommandSubcommands: () => buildLanguageCommandSubcommands,
|
|
90
|
+
buildMemoryCommandSubcommands: () => buildMemoryCommandSubcommands,
|
|
91
|
+
buildModelCommandSubcommands: () => buildModelCommandSubcommands,
|
|
92
|
+
buildPermissionModeSubcommands: () => buildPermissionModeSubcommands,
|
|
93
|
+
buildPluginCommandSubcommands: () => buildPluginCommandSubcommands,
|
|
94
|
+
buildProviderProfile: () => buildProviderProfile,
|
|
95
|
+
buildProviderSetupPatch: () => buildProviderSetupPatch,
|
|
96
|
+
buildRewindCommandSubcommands: () => buildRewindCommandSubcommands,
|
|
57
97
|
buildSkillPrompt: () => buildSkillPrompt,
|
|
58
|
-
|
|
98
|
+
buildStatusLineCommandSubcommands: () => buildStatusLineCommandSubcommands,
|
|
99
|
+
cancelCommandBackgroundTask: () => cancelCommandBackgroundTask,
|
|
100
|
+
chatEntryToMessage: () => import_agent_core9.chatEntryToMessage,
|
|
101
|
+
clearConversationHistory: () => clearConversationHistory,
|
|
102
|
+
closeCommandBackgroundTask: () => closeCommandBackgroundTask,
|
|
103
|
+
compactCommandContext: () => compactCommandContext,
|
|
59
104
|
createAgentTool: () => createAgentTool,
|
|
60
105
|
createBackgroundProcessTool: () => createBackgroundProcessTool,
|
|
106
|
+
createBuiltinCommandModule: () => createBuiltinCommandModule,
|
|
61
107
|
createCommandExecutionTool: () => createCommandExecutionTool,
|
|
108
|
+
createCommandMemoryStores: () => createCommandMemoryStores,
|
|
109
|
+
createCommandPendingMemoryStore: () => createCommandPendingMemoryStore,
|
|
110
|
+
createCommandProjectMemoryStore: () => createCommandProjectMemoryStore,
|
|
62
111
|
createDefaultTools: () => createDefaultTools,
|
|
112
|
+
createPluginRegistryReloadRequestedEffect: () => createPluginRegistryReloadRequestedEffect,
|
|
113
|
+
createPluginTuiRequestedEffect: () => createPluginTuiRequestedEffect,
|
|
114
|
+
createProviderSetupFlow: () => createProviderSetupFlow,
|
|
63
115
|
createQuery: () => createQuery,
|
|
116
|
+
createSessionExitRequestedEffect: () => createSessionExitRequestedEffect,
|
|
117
|
+
createSessionPickerRequestedEffect: () => createSessionPickerRequestedEffect,
|
|
118
|
+
createSessionRenamedEffect: () => createSessionRenamedEffect,
|
|
64
119
|
createSubagentLogger: () => createSubagentLogger,
|
|
65
120
|
createSubagentSession: () => createSubagentSession,
|
|
66
121
|
createSystemCommands: () => createSystemCommands,
|
|
67
122
|
createWorktreeSubagentRunner: () => import_agent_runtime8.createWorktreeSubagentRunner,
|
|
68
123
|
discoverTaskFiles: () => discoverTaskFiles,
|
|
69
|
-
evaluatePermission: () =>
|
|
124
|
+
evaluatePermission: () => import_agent_core10.evaluatePermission,
|
|
125
|
+
evaluateReversibleToolSafety: () => evaluateReversibleToolSafety,
|
|
70
126
|
executeSkill: () => executeSkill,
|
|
127
|
+
formatCommandBackgroundTask: () => formatCommandBackgroundTask,
|
|
128
|
+
formatCommandBackgroundTaskList: () => formatCommandBackgroundTaskList,
|
|
129
|
+
formatCommandHelpMessage: () => formatCommandHelpMessage,
|
|
130
|
+
formatCommandPermissionsMessage: () => formatCommandPermissionsMessage,
|
|
131
|
+
formatEnvReference: () => formatEnvReference,
|
|
132
|
+
formatInvalidPermissionModeMessage: () => formatInvalidPermissionModeMessage,
|
|
133
|
+
formatLanguageUsageMessage: () => formatLanguageUsageMessage,
|
|
134
|
+
formatProviderSetupChoiceLabel: () => formatProviderSetupChoiceLabel,
|
|
135
|
+
formatProviderSetupPromptLabel: () => formatProviderSetupPromptLabel,
|
|
136
|
+
formatProviderSetupSelectionPrompt: () => formatProviderSetupSelectionPrompt,
|
|
71
137
|
formatTaskContext: () => formatTaskContext,
|
|
72
138
|
getBackgroundTaskTransitions: () => import_agent_runtime4.getBackgroundTaskTransitions,
|
|
73
139
|
getBuiltInAgent: () => getBuiltInAgent,
|
|
74
140
|
getForkWorkerSuffix: () => getForkWorkerSuffix,
|
|
75
|
-
getMessagesForAPI: () =>
|
|
141
|
+
getMessagesForAPI: () => import_agent_core9.getMessagesForAPI,
|
|
142
|
+
getProviderSetupStep: () => getProviderSetupStep,
|
|
76
143
|
getSubagentSuffix: () => getSubagentSuffix,
|
|
77
|
-
|
|
144
|
+
hasSensitiveCommandMemoryContent: () => hasSensitiveCommandMemoryContent,
|
|
145
|
+
hasUsableSecretReference: () => hasUsableSecretReference,
|
|
146
|
+
inspectCommandEditCheckpoint: () => inspectCommandEditCheckpoint,
|
|
147
|
+
isChatEntry: () => import_agent_core9.isChatEntry,
|
|
148
|
+
isCommandMemoryType: () => isCommandMemoryType,
|
|
149
|
+
isEnvReference: () => isEnvReference,
|
|
78
150
|
isMemoryType: () => isMemoryType,
|
|
151
|
+
isPermissionMode: () => isPermissionMode,
|
|
152
|
+
isStatusLineCommandSettingsPatch: () => isStatusLineCommandSettingsPatch,
|
|
79
153
|
isTerminalBackgroundTaskStatus: () => import_agent_runtime4.isTerminalBackgroundTaskStatus,
|
|
154
|
+
listCommandBackgroundTasks: () => listCommandBackgroundTasks,
|
|
155
|
+
listCommandEditCheckpoints: () => listCommandEditCheckpoints,
|
|
156
|
+
listCommandSessionAllowedTools: () => listCommandSessionAllowedTools,
|
|
157
|
+
listCommandUsedMemoryReferences: () => listCommandUsedMemoryReferences,
|
|
80
158
|
loadTaskContext: () => loadTaskContext,
|
|
81
|
-
|
|
159
|
+
mergeProviderPatch: () => mergeProviderPatch,
|
|
160
|
+
messageToHistoryEntry: () => import_agent_core9.messageToHistoryEntry,
|
|
161
|
+
parseCommandBackgroundLogCursor: () => parseCommandBackgroundLogCursor,
|
|
82
162
|
parseFrontmatter: () => parseFrontmatter,
|
|
163
|
+
parseLanguageArgument: () => parseLanguageArgument,
|
|
164
|
+
parsePermissionModeArgument: () => parsePermissionModeArgument,
|
|
165
|
+
parseSessionNameArgument: () => parseSessionNameArgument,
|
|
83
166
|
parseTaskFile: () => parseTaskFile,
|
|
84
167
|
planSelfHostingVerification: () => planSelfHostingVerification,
|
|
85
168
|
preprocessShellCommands: () => preprocessShellCommands,
|
|
169
|
+
probeProviderProfile: () => probeProviderProfile,
|
|
86
170
|
projectPaths: () => projectPaths,
|
|
87
171
|
promptForApproval: () => promptForApproval,
|
|
172
|
+
readAutoCompactThreshold: () => readAutoCompactThreshold,
|
|
173
|
+
readAutoCompactThresholdSource: () => readAutoCompactThresholdSource,
|
|
174
|
+
readCommandBackgroundTaskLog: () => readCommandBackgroundTaskLog,
|
|
175
|
+
readCommandContextState: () => readCommandContextState,
|
|
176
|
+
readCommandPermissionMode: () => readCommandPermissionMode,
|
|
177
|
+
readCommandPermissionsState: () => readCommandPermissionsState,
|
|
178
|
+
readCommandSessionInfo: () => readCommandSessionInfo,
|
|
88
179
|
readCurrentGitBranch: () => readCurrentGitBranch,
|
|
180
|
+
recordCommandMemoryEvent: () => recordCommandMemoryEvent,
|
|
181
|
+
resetAutoCompactThresholdSetting: () => resetAutoCompactThresholdSetting,
|
|
182
|
+
resolveEnvReference: () => resolveEnvReference,
|
|
183
|
+
resolvePermissionModeAdapter: () => resolvePermissionModeAdapter,
|
|
184
|
+
resolvePluginCommandAdapter: () => resolvePluginCommandAdapter,
|
|
185
|
+
resolveProviderSetupSelection: () => resolveProviderSetupSelection,
|
|
89
186
|
resolveSubagentLogDir: () => resolveSubagentLogDir,
|
|
187
|
+
restoreCommandEditCheckpoint: () => restoreCommandEditCheckpoint,
|
|
90
188
|
retrieveAgentToolDeps: () => retrieveAgentToolDeps,
|
|
91
|
-
|
|
189
|
+
rollbackCommandEditCheckpoint: () => rollbackCommandEditCheckpoint,
|
|
190
|
+
runHooks: () => import_agent_core11.runHooks,
|
|
191
|
+
runProviderSetupPromptFlow: () => runProviderSetupPromptFlow,
|
|
92
192
|
selectRelevantTasks: () => selectRelevantTasks,
|
|
193
|
+
setCommandAutoCompactThreshold: () => setCommandAutoCompactThreshold,
|
|
194
|
+
setCurrentProvider: () => setCurrentProvider,
|
|
93
195
|
storeAgentToolDeps: () => storeAgentToolDeps,
|
|
196
|
+
submitProviderSetupValue: () => submitProviderSetupValue,
|
|
94
197
|
substituteVariables: () => substituteVariables,
|
|
95
198
|
summarizeBackgroundJobGroup: () => summarizeBackgroundJobGroup,
|
|
199
|
+
testProviderProfileCommand: () => testProviderProfileCommand,
|
|
96
200
|
transitionBackgroundTaskStatus: () => import_agent_runtime4.transitionBackgroundTaskStatus,
|
|
97
201
|
transitionSelfHostingLoop: () => transitionSelfHostingLoop,
|
|
98
202
|
updateTaskFileStatus: () => updateTaskFileStatus,
|
|
203
|
+
upsertProviderProfile: () => upsertProviderProfile,
|
|
99
204
|
userPaths: () => userPaths,
|
|
100
|
-
|
|
205
|
+
validateProviderProfile: () => validateProviderProfile,
|
|
206
|
+
validateProviderSetupValue: () => validateProviderSetupValue,
|
|
207
|
+
wrapEditCheckpointTools: () => wrapEditCheckpointTools,
|
|
208
|
+
wrapReversibleExecutionTools: () => wrapReversibleExecutionTools,
|
|
209
|
+
writeAutoCompactThresholdSetting: () => writeAutoCompactThresholdSetting,
|
|
210
|
+
writeCommandPermissionMode: () => writeCommandPermissionMode
|
|
101
211
|
});
|
|
102
212
|
module.exports = __toCommonJS(index_exports);
|
|
103
213
|
|
|
104
214
|
// src/interactive/interactive-session.ts
|
|
105
|
-
var
|
|
215
|
+
var import_agent_core7 = require("@robota-sdk/agent-core");
|
|
106
216
|
|
|
107
217
|
// src/commands/capability-descriptors.ts
|
|
108
218
|
function inferKind(command) {
|
|
@@ -129,6 +239,12 @@ var CommandRegistry = class {
|
|
|
129
239
|
addSource(source) {
|
|
130
240
|
this.sources.push(source);
|
|
131
241
|
}
|
|
242
|
+
replaceSource(name, source) {
|
|
243
|
+
this.sources = this.sources.filter((candidate) => candidate.name !== name);
|
|
244
|
+
if (source !== void 0) {
|
|
245
|
+
this.sources.push(source);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
132
248
|
addModule(module2) {
|
|
133
249
|
for (const source of module2.commandSources ?? []) {
|
|
134
250
|
this.addSource(source);
|
|
@@ -169,138 +285,222 @@ var CommandRegistry = class {
|
|
|
169
285
|
}
|
|
170
286
|
};
|
|
171
287
|
|
|
288
|
+
// src/commands/system-command-executor.ts
|
|
289
|
+
var SystemCommandExecutor = class {
|
|
290
|
+
commands;
|
|
291
|
+
constructor(commands) {
|
|
292
|
+
this.commands = /* @__PURE__ */ new Map();
|
|
293
|
+
for (const cmd of commands ?? createSystemCommands()) {
|
|
294
|
+
this.commands.set(cmd.name, cmd);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/** Register an additional command. */
|
|
298
|
+
register(command) {
|
|
299
|
+
this.commands.set(command.name, command);
|
|
300
|
+
}
|
|
301
|
+
/** Execute a command by name. Returns null if command not found. */
|
|
302
|
+
async execute(name, session, args) {
|
|
303
|
+
const cmd = this.getCommand(name);
|
|
304
|
+
if (!cmd) return null;
|
|
305
|
+
return await this.executeCommand(cmd, session, args);
|
|
306
|
+
}
|
|
307
|
+
getCommand(name) {
|
|
308
|
+
return this.commands.get(name);
|
|
309
|
+
}
|
|
310
|
+
async executeCommand(command, session, args) {
|
|
311
|
+
return await command.execute(session, args);
|
|
312
|
+
}
|
|
313
|
+
/** List all registered commands. */
|
|
314
|
+
listCommands() {
|
|
315
|
+
return [...this.commands.values()];
|
|
316
|
+
}
|
|
317
|
+
listModelInvocableCommands() {
|
|
318
|
+
return this.listCommands().filter((command) => command.modelInvocable === true).map((command) => ({
|
|
319
|
+
name: `/${command.name}`,
|
|
320
|
+
kind: "builtin-command",
|
|
321
|
+
description: command.description,
|
|
322
|
+
userInvocable: command.userInvocable !== false,
|
|
323
|
+
modelInvocable: true,
|
|
324
|
+
...command.argumentHint ? { argumentHint: command.argumentHint } : {},
|
|
325
|
+
...command.safety ? { safety: command.safety } : {}
|
|
326
|
+
}));
|
|
327
|
+
}
|
|
328
|
+
isModelInvocable(name) {
|
|
329
|
+
return this.commands.get(name)?.modelInvocable === true;
|
|
330
|
+
}
|
|
331
|
+
async executeModelInvocable(name, session, args) {
|
|
332
|
+
if (!this.isModelInvocable(name)) return null;
|
|
333
|
+
return this.execute(name, session, args);
|
|
334
|
+
}
|
|
335
|
+
/** Check if a command exists. */
|
|
336
|
+
hasCommand(name) {
|
|
337
|
+
return this.commands.has(name);
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// src/commands/system-command.ts
|
|
342
|
+
function createSystemCommands() {
|
|
343
|
+
return [];
|
|
344
|
+
}
|
|
345
|
+
|
|
172
346
|
// src/commands/builtin-source.ts
|
|
347
|
+
function commandToPaletteEntry(command) {
|
|
348
|
+
return {
|
|
349
|
+
name: command.name,
|
|
350
|
+
description: command.description,
|
|
351
|
+
source: "builtin",
|
|
352
|
+
...command.subcommands ? { subcommands: [...command.subcommands] } : {},
|
|
353
|
+
...command.argumentHint ? { argumentHint: command.argumentHint } : {},
|
|
354
|
+
...command.modelInvocable !== void 0 ? { modelInvocable: command.modelInvocable } : {},
|
|
355
|
+
...command.userInvocable !== void 0 ? { userInvocable: command.userInvocable } : {},
|
|
356
|
+
...command.safety ? { safety: command.safety } : {}
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
var BuiltinCommandSource = class {
|
|
360
|
+
name = "builtin";
|
|
361
|
+
commands;
|
|
362
|
+
constructor(systemCommands = createSystemCommands()) {
|
|
363
|
+
this.commands = systemCommands.map(commandToPaletteEntry);
|
|
364
|
+
}
|
|
365
|
+
getCommands() {
|
|
366
|
+
return this.commands;
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
function createBuiltinCommandModule() {
|
|
370
|
+
const systemCommands = createSystemCommands();
|
|
371
|
+
return {
|
|
372
|
+
name: "sdk-builtin",
|
|
373
|
+
commandSources: [new BuiltinCommandSource(systemCommands)],
|
|
374
|
+
systemCommands
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// src/command-api/provider/provider-command-probe.ts
|
|
379
|
+
var import_agent_core2 = require("@robota-sdk/agent-core");
|
|
380
|
+
|
|
381
|
+
// src/command-api/provider/provider-settings.ts
|
|
173
382
|
var import_agent_core = require("@robota-sdk/agent-core");
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
383
|
+
|
|
384
|
+
// src/command-api/provider/provider-env-ref.ts
|
|
385
|
+
var ENV_REFERENCE_PREFIX = "$ENV:";
|
|
386
|
+
function isEnvReference(value) {
|
|
387
|
+
return value.startsWith(ENV_REFERENCE_PREFIX);
|
|
388
|
+
}
|
|
389
|
+
function formatEnvReference(name) {
|
|
390
|
+
return `${ENV_REFERENCE_PREFIX}${name}`;
|
|
391
|
+
}
|
|
392
|
+
function resolveEnvReference(value) {
|
|
393
|
+
if (!isEnvReference(value)) {
|
|
394
|
+
return value;
|
|
185
395
|
}
|
|
186
|
-
|
|
396
|
+
const envName = value.slice(ENV_REFERENCE_PREFIX.length).trim();
|
|
397
|
+
if (envName.length === 0) {
|
|
398
|
+
return void 0;
|
|
399
|
+
}
|
|
400
|
+
return process.env[envName];
|
|
187
401
|
}
|
|
188
|
-
function
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
{ name: "test", description: "Test provider profile", source: "builtin" }
|
|
194
|
-
];
|
|
402
|
+
function hasUsableSecretReference(value) {
|
|
403
|
+
if (value === void 0 || value.length === 0) {
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
return resolveEnvReference(value) !== void 0;
|
|
195
407
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
408
|
+
|
|
409
|
+
// src/command-api/provider/provider-settings.ts
|
|
410
|
+
function upsertProviderProfile(settings, profileName, profile) {
|
|
411
|
+
return {
|
|
412
|
+
...settings,
|
|
413
|
+
providers: {
|
|
414
|
+
...settings.providers ?? {},
|
|
415
|
+
[profileName]: profile
|
|
416
|
+
}
|
|
417
|
+
};
|
|
203
418
|
}
|
|
204
|
-
function
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
419
|
+
function setCurrentProvider(settings, profileName) {
|
|
420
|
+
if (!settings.providers?.[profileName]) {
|
|
421
|
+
throw new Error(`Provider profile "${profileName}" was not found`);
|
|
422
|
+
}
|
|
423
|
+
return {
|
|
424
|
+
...settings,
|
|
425
|
+
currentProvider: profileName
|
|
426
|
+
};
|
|
210
427
|
}
|
|
211
|
-
function
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
428
|
+
function validateProviderProfile(profileName, profile, options = {}) {
|
|
429
|
+
if (!profile.type) {
|
|
430
|
+
throw new Error(`Provider profile "${profileName}" is missing type`);
|
|
431
|
+
}
|
|
432
|
+
if (!profile.model) {
|
|
433
|
+
throw new Error(`Provider profile "${profileName}" is missing model`);
|
|
434
|
+
}
|
|
435
|
+
const definition = (0, import_agent_core.findProviderDefinition)(options.providerDefinitions ?? [], profile.type);
|
|
436
|
+
if (definition?.requiresApiKey === true && !hasUsableSecretReference(profile.apiKey ?? definition.defaults?.apiKey)) {
|
|
437
|
+
throw new Error(`Provider profile "${profileName}" is missing apiKey`);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
function buildProviderSetupPatch(input, options = {}) {
|
|
441
|
+
const profile = buildProviderProfile(input, options);
|
|
442
|
+
validateProviderProfile(input.profile, profile, options);
|
|
443
|
+
return {
|
|
444
|
+
...input.setCurrent && { currentProvider: input.profile },
|
|
445
|
+
providers: {
|
|
446
|
+
[input.profile]: profile
|
|
223
447
|
}
|
|
224
|
-
|
|
448
|
+
};
|
|
225
449
|
}
|
|
226
|
-
function
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
{ name: "acceptEdits", description: "Auto-approve file edits", source: "builtin" },
|
|
238
|
-
{ name: "bypassPermissions", description: "Skip all permission checks", source: "builtin" }
|
|
239
|
-
]
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
name: "model",
|
|
243
|
-
description: "Select AI model",
|
|
244
|
-
source: "builtin",
|
|
245
|
-
subcommands: buildModelSubcommands()
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
name: "language",
|
|
249
|
-
description: "Set response language",
|
|
250
|
-
source: "builtin",
|
|
251
|
-
subcommands: [
|
|
252
|
-
{ name: "ko", description: "Korean", source: "builtin" },
|
|
253
|
-
{ name: "en", description: "English", source: "builtin" },
|
|
254
|
-
{ name: "ja", description: "Japanese", source: "builtin" },
|
|
255
|
-
{ name: "zh", description: "Chinese", source: "builtin" }
|
|
256
|
-
]
|
|
257
|
-
},
|
|
258
|
-
{ name: "compact", description: "Compress context window", source: "builtin" },
|
|
259
|
-
{ name: "cost", description: "Show session info", source: "builtin" },
|
|
260
|
-
{ name: "context", description: "Context window info", source: "builtin" },
|
|
261
|
-
{ name: "permissions", description: "Permission rules", source: "builtin" },
|
|
262
|
-
{
|
|
263
|
-
name: "memory",
|
|
264
|
-
description: "Inspect, save, review, and audit project memory",
|
|
265
|
-
source: "builtin",
|
|
266
|
-
subcommands: buildMemorySubcommands()
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
name: "rewind",
|
|
270
|
-
description: "List and restore edit checkpoints",
|
|
271
|
-
source: "builtin",
|
|
272
|
-
subcommands: buildRewindSubcommands()
|
|
273
|
-
},
|
|
274
|
-
{
|
|
275
|
-
name: "provider",
|
|
276
|
-
description: "Manage provider profiles",
|
|
277
|
-
source: "builtin",
|
|
278
|
-
subcommands: buildProviderSubcommands()
|
|
279
|
-
},
|
|
280
|
-
{ name: "resume", description: "Resume a previous session", source: "builtin" },
|
|
281
|
-
{
|
|
282
|
-
name: "background",
|
|
283
|
-
description: "List and control background tasks",
|
|
284
|
-
source: "builtin",
|
|
285
|
-
subcommands: buildBackgroundSubcommands()
|
|
286
|
-
},
|
|
287
|
-
{ name: "rename", description: "Rename the current session", source: "builtin" },
|
|
288
|
-
{ name: "plugin", description: "Manage plugins", source: "builtin" },
|
|
289
|
-
{ name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
|
|
290
|
-
{ name: "reset", description: "Delete settings and exit", source: "builtin" },
|
|
291
|
-
{ name: "exit", description: "Exit CLI", source: "builtin" }
|
|
292
|
-
];
|
|
450
|
+
function buildProviderProfile(input, options = {}) {
|
|
451
|
+
const defaults = getProviderDefaults(input.type, options.providerDefinitions ?? []);
|
|
452
|
+
const apiKey = input.apiKeyEnv !== void 0 ? formatEnvReference(input.apiKeyEnv) : input.apiKey ?? defaults.apiKey;
|
|
453
|
+
const baseURL = input.baseURL ?? defaults.baseURL;
|
|
454
|
+
return {
|
|
455
|
+
type: input.type,
|
|
456
|
+
model: input.model ?? defaults.model,
|
|
457
|
+
...apiKey !== void 0 && { apiKey },
|
|
458
|
+
...baseURL !== void 0 && { baseURL },
|
|
459
|
+
...input.timeout !== void 0 && { timeout: input.timeout }
|
|
460
|
+
};
|
|
293
461
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
this.commands = createBuiltinCommands();
|
|
462
|
+
function mergeProviderPatch(settings, patch) {
|
|
463
|
+
const [profileName, profile] = Object.entries(patch.providers)[0] ?? [];
|
|
464
|
+
if (!profileName || !profile) {
|
|
465
|
+
return settings;
|
|
299
466
|
}
|
|
300
|
-
|
|
301
|
-
|
|
467
|
+
const withProfile = upsertProviderProfile(settings, profileName, profile);
|
|
468
|
+
return patch.currentProvider ? setCurrentProvider(withProfile, patch.currentProvider) : withProfile;
|
|
469
|
+
}
|
|
470
|
+
function getProviderDefaults(type, providerDefinitions) {
|
|
471
|
+
return (0, import_agent_core.findProviderDefinition)(providerDefinitions, type)?.defaults ?? {};
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// src/command-api/provider/provider-command-probe.ts
|
|
475
|
+
async function testProviderProfileCommand(currentProvider, providers, profileArg, options) {
|
|
476
|
+
const profileName = profileArg ?? currentProvider;
|
|
477
|
+
if (!profileName) {
|
|
478
|
+
return { message: "No provider profile selected.", success: false };
|
|
302
479
|
}
|
|
303
|
-
|
|
480
|
+
const profile = providers?.[profileName];
|
|
481
|
+
if (!profile) {
|
|
482
|
+
return { message: `Provider profile "${profileName}" was not found.`, success: false };
|
|
483
|
+
}
|
|
484
|
+
try {
|
|
485
|
+
validateProviderProfile(profileName, profile, {
|
|
486
|
+
providerDefinitions: options.providerDefinitions
|
|
487
|
+
});
|
|
488
|
+
} catch (error) {
|
|
489
|
+
return { message: error instanceof Error ? error.message : String(error), success: false };
|
|
490
|
+
}
|
|
491
|
+
const definition = profile.type ? (0, import_agent_core2.findProviderDefinition)(options.providerDefinitions, profile.type) : void 0;
|
|
492
|
+
const probe = definition?.probeProfile ?? probeProviderProfile;
|
|
493
|
+
const result = await probe(profile);
|
|
494
|
+
return {
|
|
495
|
+
message: result.ok ? `Provider "${profileName}" test passed: ${result.message}` : `Provider "${profileName}" test failed: ${result.message}; manual configuration can continue.`,
|
|
496
|
+
success: true,
|
|
497
|
+
data: { providerTest: { profile: profileName } }
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
async function probeProviderProfile(profile) {
|
|
501
|
+
void profile;
|
|
502
|
+
return { ok: true, message: "Profile fields are valid; no endpoint probe configured." };
|
|
503
|
+
}
|
|
304
504
|
|
|
305
505
|
// src/commands/skill-source.ts
|
|
306
506
|
var import_node_fs = require("fs");
|
|
@@ -455,66 +655,523 @@ var PluginCommandSource = class {
|
|
|
455
655
|
}
|
|
456
656
|
};
|
|
457
657
|
|
|
458
|
-
// src/
|
|
658
|
+
// src/command-api/context/context-command-api.ts
|
|
659
|
+
var import_agent_sessions = require("@robota-sdk/agent-sessions");
|
|
660
|
+
var DEFAULT_AUTO_COMPACT_THRESHOLD = import_agent_sessions.AUTO_COMPACT_THRESHOLD;
|
|
661
|
+
var AUTO_COMPACT_THRESHOLD_SETTINGS_KEY = "autoCompactThreshold";
|
|
662
|
+
function readCommandContextState(context) {
|
|
663
|
+
return context.getContextState();
|
|
664
|
+
}
|
|
665
|
+
function readAutoCompactThreshold(context) {
|
|
666
|
+
return context.getAutoCompactThreshold();
|
|
667
|
+
}
|
|
668
|
+
function readAutoCompactThresholdSource(context) {
|
|
669
|
+
return context.getAutoCompactThresholdSource?.() ?? "session";
|
|
670
|
+
}
|
|
671
|
+
function setCommandAutoCompactThreshold(context, threshold, source) {
|
|
672
|
+
if (context.setAutoCompactThreshold) {
|
|
673
|
+
context.setAutoCompactThreshold(threshold, source);
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
const session = context.getSession();
|
|
677
|
+
if (!session.setAutoCompactThreshold) {
|
|
678
|
+
throw new Error("Command host does not support changing auto-compact threshold.");
|
|
679
|
+
}
|
|
680
|
+
session.setAutoCompactThreshold(threshold);
|
|
681
|
+
}
|
|
682
|
+
function writeAutoCompactThresholdSetting(context, threshold) {
|
|
683
|
+
const settings = getSettingsAdapter(context);
|
|
684
|
+
if (!settings) return false;
|
|
685
|
+
settings.write({
|
|
686
|
+
...settings.read(),
|
|
687
|
+
[AUTO_COMPACT_THRESHOLD_SETTINGS_KEY]: threshold
|
|
688
|
+
});
|
|
689
|
+
return true;
|
|
690
|
+
}
|
|
691
|
+
function resetAutoCompactThresholdSetting(context) {
|
|
692
|
+
const settings = getSettingsAdapter(context);
|
|
693
|
+
if (!settings) return false;
|
|
694
|
+
const next = { ...settings.read() };
|
|
695
|
+
delete next[AUTO_COMPACT_THRESHOLD_SETTINGS_KEY];
|
|
696
|
+
settings.write(next);
|
|
697
|
+
return true;
|
|
698
|
+
}
|
|
699
|
+
async function compactCommandContext(context, instructions) {
|
|
700
|
+
const before = readCommandContextState(context);
|
|
701
|
+
await context.compactContext(instructions);
|
|
702
|
+
const after = readCommandContextState(context);
|
|
703
|
+
return { before, after };
|
|
704
|
+
}
|
|
705
|
+
function getSettingsAdapter(context) {
|
|
706
|
+
return context.getCommandHostAdapters?.().settings;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// src/command-api/provider/provider-setup-flow.ts
|
|
710
|
+
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
711
|
+
function createProviderSetupFlow(type, providerDefinitions) {
|
|
712
|
+
return {
|
|
713
|
+
type,
|
|
714
|
+
steps: getProviderSetupSteps(type, providerDefinitions),
|
|
715
|
+
stepIndex: 0,
|
|
716
|
+
values: {}
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
function formatProviderSetupSelectionPrompt(providerDefinitions) {
|
|
720
|
+
if (providerDefinitions.length === 0) {
|
|
721
|
+
return " No providers are available.";
|
|
722
|
+
}
|
|
723
|
+
const lines = [
|
|
724
|
+
" Select provider:",
|
|
725
|
+
...providerDefinitions.map(
|
|
726
|
+
(definition, index) => ` ${index + 1}. ${formatProviderSetupChoiceLabel(definition)}`
|
|
727
|
+
),
|
|
728
|
+
` Provider [1-${providerDefinitions.length}] (default: 1): `
|
|
729
|
+
];
|
|
730
|
+
return lines.join("\n");
|
|
731
|
+
}
|
|
732
|
+
function resolveProviderSetupSelection(rawValue, providerDefinitions) {
|
|
733
|
+
const value = rawValue.trim();
|
|
734
|
+
const selectedValue = value.length > 0 ? value : "1";
|
|
735
|
+
const index = parseProviderSelectionIndex(selectedValue);
|
|
736
|
+
if (index !== void 0) {
|
|
737
|
+
const definition2 = providerDefinitions[index];
|
|
738
|
+
if (definition2 !== void 0) {
|
|
739
|
+
return definition2.type;
|
|
740
|
+
}
|
|
741
|
+
throw new Error(
|
|
742
|
+
`Provider selection ${selectedValue} is out of range. Currently supported: ${(0, import_agent_core3.formatSupportedProviderTypes)(providerDefinitions)}`
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
const definition = (0, import_agent_core3.findProviderDefinition)(providerDefinitions, selectedValue);
|
|
746
|
+
if (definition === void 0) {
|
|
747
|
+
throw new Error(
|
|
748
|
+
`Unknown provider: ${selectedValue}. Currently supported: ${(0, import_agent_core3.formatSupportedProviderTypes)(providerDefinitions)}`
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
return definition.type;
|
|
752
|
+
}
|
|
753
|
+
function getProviderSetupStep(state) {
|
|
754
|
+
const step = state.steps[state.stepIndex];
|
|
755
|
+
if (step === void 0) {
|
|
756
|
+
throw new Error(`Provider setup step ${state.stepIndex} is out of range`);
|
|
757
|
+
}
|
|
758
|
+
return step;
|
|
759
|
+
}
|
|
760
|
+
function submitProviderSetupValue(state, rawValue) {
|
|
761
|
+
const step = getProviderSetupStep(state);
|
|
762
|
+
const value = rawValue.trim() || step.defaultValue || "";
|
|
763
|
+
const validationMessage = validateProviderSetupValue(step, value);
|
|
764
|
+
if (validationMessage !== void 0) {
|
|
765
|
+
return { status: "error", state, message: validationMessage };
|
|
766
|
+
}
|
|
767
|
+
const nextState = {
|
|
768
|
+
...state,
|
|
769
|
+
stepIndex: state.stepIndex + 1,
|
|
770
|
+
values: { ...state.values, [step.key]: value }
|
|
771
|
+
};
|
|
772
|
+
if (nextState.stepIndex < state.steps.length) {
|
|
773
|
+
return { status: "next", state: nextState };
|
|
774
|
+
}
|
|
775
|
+
return { status: "complete", input: buildProviderSetupInput(nextState) };
|
|
776
|
+
}
|
|
777
|
+
async function runProviderSetupPromptFlow(type, promptInput, providerDefinitions) {
|
|
778
|
+
let state = createProviderSetupFlow(type, providerDefinitions);
|
|
779
|
+
const stepCount = state.steps.length;
|
|
780
|
+
while (state.stepIndex < stepCount) {
|
|
781
|
+
const step = getProviderSetupStep(state);
|
|
782
|
+
const value = await promptInput(formatProviderSetupPromptLabel(step), step.masked === true);
|
|
783
|
+
const result = submitProviderSetupValue(state, value);
|
|
784
|
+
if (result.status === "complete") {
|
|
785
|
+
return result.input;
|
|
786
|
+
}
|
|
787
|
+
if (result.status === "error") {
|
|
788
|
+
throw new Error(result.message);
|
|
789
|
+
}
|
|
790
|
+
state = result.state;
|
|
791
|
+
}
|
|
792
|
+
throw new Error("Provider setup flow ended without completion");
|
|
793
|
+
}
|
|
794
|
+
function formatProviderSetupPromptLabel(step) {
|
|
795
|
+
const suffix = step.defaultValue !== void 0 ? ` (default: ${step.defaultValue})` : "";
|
|
796
|
+
return ` ${step.title}${suffix}: `;
|
|
797
|
+
}
|
|
798
|
+
function formatProviderSetupChoiceLabel(definition) {
|
|
799
|
+
const label = definition.displayName !== void 0 ? `${definition.displayName} (${definition.type})` : definition.type;
|
|
800
|
+
return definition.description !== void 0 ? `${label} - ${definition.description}` : label;
|
|
801
|
+
}
|
|
802
|
+
function parseProviderSelectionIndex(value) {
|
|
803
|
+
if (!/^\d+$/.test(value)) {
|
|
804
|
+
return void 0;
|
|
805
|
+
}
|
|
806
|
+
return Number(value) - 1;
|
|
807
|
+
}
|
|
808
|
+
function validateProviderSetupValue(step, value) {
|
|
809
|
+
if (step.required === true && value.length === 0) {
|
|
810
|
+
return "Required";
|
|
811
|
+
}
|
|
812
|
+
return void 0;
|
|
813
|
+
}
|
|
814
|
+
function getProviderSetupSteps(type, providerDefinitions) {
|
|
815
|
+
const definition = (0, import_agent_core3.findProviderDefinition)(providerDefinitions, type);
|
|
816
|
+
if (definition === void 0) {
|
|
817
|
+
throw new Error(
|
|
818
|
+
`Unknown provider: ${type}. Currently supported: ${(0, import_agent_core3.formatSupportedProviderTypes)(providerDefinitions)}`
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
if (definition.setupSteps !== void 0) {
|
|
822
|
+
return [...definition.setupSteps];
|
|
823
|
+
}
|
|
824
|
+
const steps = [
|
|
825
|
+
{
|
|
826
|
+
key: "model",
|
|
827
|
+
title: `${definition.type} model`,
|
|
828
|
+
defaultValue: definition.defaults?.model,
|
|
829
|
+
required: definition.defaults?.model === void 0
|
|
830
|
+
}
|
|
831
|
+
];
|
|
832
|
+
if (definition.defaults?.baseURL !== void 0) {
|
|
833
|
+
steps.unshift({
|
|
834
|
+
key: "baseURL",
|
|
835
|
+
title: `${definition.type} base URL`,
|
|
836
|
+
defaultValue: definition.defaults.baseURL
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
if (definition.requiresApiKey === true) {
|
|
840
|
+
steps.push({
|
|
841
|
+
key: "apiKey",
|
|
842
|
+
title: `${definition.type} API key`,
|
|
843
|
+
defaultValue: definition.defaults?.apiKey,
|
|
844
|
+
required: definition.defaults?.apiKey === void 0,
|
|
845
|
+
masked: true
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
return steps;
|
|
849
|
+
}
|
|
850
|
+
function buildProviderSetupInput(state) {
|
|
851
|
+
return {
|
|
852
|
+
profile: state.type,
|
|
853
|
+
type: state.type,
|
|
854
|
+
model: state.values.model,
|
|
855
|
+
apiKey: state.values.apiKey,
|
|
856
|
+
...state.values.baseURL !== void 0 && { baseURL: state.values.baseURL },
|
|
857
|
+
setCurrent: true
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// src/command-api/help/help-command-api.ts
|
|
862
|
+
var HELP_COMMAND_DESCRIPTION = "Show available commands";
|
|
863
|
+
var HELP_COMMAND_NAME_COLUMN_WIDTH = 16;
|
|
864
|
+
function readCommandList(context) {
|
|
865
|
+
return context.listCommands?.() ?? [];
|
|
866
|
+
}
|
|
867
|
+
function formatCommandHelpMessage(context) {
|
|
868
|
+
const commands = readCommandList(context);
|
|
869
|
+
return [
|
|
870
|
+
"Available commands:",
|
|
871
|
+
...commands.map(
|
|
872
|
+
(command) => ` ${command.name.padEnd(HELP_COMMAND_NAME_COLUMN_WIDTH)} \u2014 ${command.description}`
|
|
873
|
+
)
|
|
874
|
+
].join("\n");
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// src/command-api/background/background-command-api.ts
|
|
459
878
|
var DECIMAL_RADIX = 10;
|
|
460
|
-
|
|
461
|
-
|
|
879
|
+
var INLINE_METADATA_LIMIT = 160;
|
|
880
|
+
var BACKGROUND_COMMAND_DESCRIPTION = "List and control background tasks";
|
|
881
|
+
var BACKGROUND_COMMAND_USAGE = "Usage: background list | background read <task-id> [offset] | background cancel <task-id> | background close <task-id>";
|
|
882
|
+
function buildBackgroundCommandSubcommands() {
|
|
883
|
+
return [
|
|
884
|
+
{ name: "list", description: "List background tasks", source: "background" },
|
|
885
|
+
{ name: "read", description: "Read a background task log page", source: "background" },
|
|
886
|
+
{ name: "cancel", description: "Cancel a running background task", source: "background" },
|
|
887
|
+
{ name: "close", description: "Dismiss a terminal background task", source: "background" }
|
|
888
|
+
];
|
|
462
889
|
}
|
|
463
|
-
function
|
|
890
|
+
function formatCommandBackgroundTask(task) {
|
|
464
891
|
const preview = task.promptPreview ?? task.commandPreview ?? "";
|
|
465
892
|
const unread = task.unread ? " unread" : "";
|
|
466
893
|
const action = task.currentAction ? ` (${task.currentAction})` : "";
|
|
467
894
|
const timeout = task.timeoutReason ? ` timeout=${task.timeoutReason}` : "";
|
|
468
895
|
const activity = task.lastActivityAt ? ` lastActivityAt=${task.lastActivityAt}` : "";
|
|
896
|
+
const worktree = formatWorktreeMetadata(task);
|
|
469
897
|
const suffix = preview ? ` \u2014 ${preview}` : "";
|
|
470
|
-
return `${task.id} [${task.status}${unread}${timeout}${activity}] ${task.kind}:${task.label}${action}${suffix}`;
|
|
898
|
+
return `${task.id} [${task.status}${unread}${timeout}${activity}${worktree}] ${task.kind}:${task.label}${action}${suffix}`;
|
|
471
899
|
}
|
|
472
|
-
function
|
|
900
|
+
function formatCommandBackgroundTaskList(tasks) {
|
|
473
901
|
if (tasks.length === 0) return "No background tasks.";
|
|
474
|
-
return [
|
|
475
|
-
"
|
|
476
|
-
)
|
|
902
|
+
return [
|
|
903
|
+
"Background tasks:",
|
|
904
|
+
...tasks.map((task) => ` ${formatCommandBackgroundTask(task)}`)
|
|
905
|
+
].join("\n");
|
|
477
906
|
}
|
|
478
|
-
function
|
|
907
|
+
function parseCommandBackgroundLogCursor(value) {
|
|
479
908
|
if (!value) return void 0;
|
|
480
909
|
const offset = Number.parseInt(value, DECIMAL_RADIX);
|
|
481
910
|
return Number.isNaN(offset) ? void 0 : { offset };
|
|
482
911
|
}
|
|
483
|
-
|
|
484
|
-
const
|
|
485
|
-
if (
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
success: true,
|
|
490
|
-
data: { count: tasks.length }
|
|
491
|
-
};
|
|
912
|
+
function formatWorktreeMetadata(task) {
|
|
913
|
+
const segments = [];
|
|
914
|
+
if (task.worktreePath) segments.push(`worktree=${task.worktreePath}`);
|
|
915
|
+
if (task.branchName) segments.push(`branch=${task.branchName}`);
|
|
916
|
+
if (task.worktreeStatus) {
|
|
917
|
+
segments.push(`worktreeStatus="${formatInlineMetadata(task.worktreeStatus)}"`);
|
|
492
918
|
}
|
|
493
|
-
if (
|
|
494
|
-
|
|
495
|
-
message: "Usage: background list | background read <task-id> [offset] | background cancel <task-id> | background close <task-id>",
|
|
496
|
-
success: false
|
|
497
|
-
};
|
|
919
|
+
if (task.worktreeNextAction) {
|
|
920
|
+
segments.push(`next="${formatInlineMetadata(task.worktreeNextAction)}"`);
|
|
498
921
|
}
|
|
499
|
-
if (
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
922
|
+
if (segments.length === 0) return "";
|
|
923
|
+
return ` ${segments.join(" ")}`;
|
|
924
|
+
}
|
|
925
|
+
function formatInlineMetadata(value) {
|
|
926
|
+
const normalized = value.trim().replace(/\s+/g, " ");
|
|
927
|
+
return normalized.length > INLINE_METADATA_LIMIT ? `${normalized.slice(0, INLINE_METADATA_LIMIT)}...` : normalized;
|
|
928
|
+
}
|
|
929
|
+
function listCommandBackgroundTasks(context, filter) {
|
|
930
|
+
return context.listBackgroundTasks(filter);
|
|
931
|
+
}
|
|
932
|
+
function readCommandBackgroundTaskLog(context, taskId, cursor) {
|
|
933
|
+
return context.readBackgroundTaskLog(taskId, cursor);
|
|
934
|
+
}
|
|
935
|
+
function cancelCommandBackgroundTask(context, taskId, reason) {
|
|
936
|
+
return context.cancelBackgroundTask(taskId, reason);
|
|
937
|
+
}
|
|
938
|
+
function closeCommandBackgroundTask(context, taskId) {
|
|
939
|
+
return context.closeBackgroundTask(taskId);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// src/command-api/model/model-command-api.ts
|
|
943
|
+
var import_agent_core4 = require("@robota-sdk/agent-core");
|
|
944
|
+
var MODEL_COMMAND_DESCRIPTION = "Change AI model";
|
|
945
|
+
var MODEL_COMMAND_ARGUMENT_HINT = "<model-id>";
|
|
946
|
+
function buildModelCommandSubcommands(source = "model") {
|
|
947
|
+
const seen = /* @__PURE__ */ new Set();
|
|
948
|
+
const commands = [];
|
|
949
|
+
for (const model of Object.values(import_agent_core4.CLAUDE_MODELS)) {
|
|
950
|
+
if (seen.has(model.name)) continue;
|
|
951
|
+
seen.add(model.name);
|
|
952
|
+
commands.push({
|
|
953
|
+
name: model.id,
|
|
954
|
+
description: `${model.name} (${(0, import_agent_core4.formatTokenCount)(model.contextWindow).toUpperCase()})`,
|
|
955
|
+
source
|
|
956
|
+
});
|
|
508
957
|
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
958
|
+
return commands;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// src/command-api/language/language-command-api.ts
|
|
962
|
+
var LANGUAGE_COMMAND_DESCRIPTION = "Set response language";
|
|
963
|
+
var LANGUAGE_COMMAND_ARGUMENT_HINT = "<code>";
|
|
964
|
+
var RECOMMENDED_RESPONSE_LANGUAGES = [
|
|
965
|
+
{ code: "ko", description: "Korean" },
|
|
966
|
+
{ code: "en", description: "English" },
|
|
967
|
+
{ code: "ja", description: "Japanese" },
|
|
968
|
+
{ code: "zh", description: "Chinese" }
|
|
969
|
+
];
|
|
970
|
+
function buildLanguageCommandSubcommands(source = "language") {
|
|
971
|
+
return RECOMMENDED_RESPONSE_LANGUAGES.map((language) => ({
|
|
972
|
+
name: language.code,
|
|
973
|
+
description: language.description,
|
|
974
|
+
source
|
|
975
|
+
}));
|
|
976
|
+
}
|
|
977
|
+
function parseLanguageArgument(args) {
|
|
978
|
+
const language = args.trim().split(/\s+/)[0];
|
|
979
|
+
return language !== void 0 && language.length > 0 ? language : void 0;
|
|
980
|
+
}
|
|
981
|
+
function formatLanguageUsageMessage(commandName = "language") {
|
|
982
|
+
return `Usage: ${commandName} <code> (e.g., ko, en, ja, zh)`;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
// src/command-api/permissions/permission-mode-command-api.ts
|
|
986
|
+
var PERMISSION_MODE_COMMAND_DESCRIPTION = "Show/change permission mode";
|
|
987
|
+
var PERMISSION_MODE_ARGUMENT_HINT = "plan | default | acceptEdits | bypassPermissions";
|
|
988
|
+
var PERMISSIONS_COMMAND_DESCRIPTION = "Show permission rules";
|
|
989
|
+
var VALID_PERMISSION_MODES = [
|
|
990
|
+
"plan",
|
|
991
|
+
"default",
|
|
992
|
+
"acceptEdits",
|
|
993
|
+
"bypassPermissions"
|
|
994
|
+
];
|
|
995
|
+
function buildPermissionModeSubcommands(source = "mode") {
|
|
996
|
+
return [
|
|
997
|
+
{ name: "plan", description: "Plan only, no execution", source },
|
|
998
|
+
{ name: "default", description: "Ask before risky actions", source },
|
|
999
|
+
{ name: "acceptEdits", description: "Auto-approve file edits", source },
|
|
1000
|
+
{ name: "bypassPermissions", description: "Skip all permission checks", source }
|
|
1001
|
+
];
|
|
1002
|
+
}
|
|
1003
|
+
function parsePermissionModeArgument(args) {
|
|
1004
|
+
const mode = args.trim().split(/\s+/)[0];
|
|
1005
|
+
return mode !== void 0 && mode.length > 0 ? mode : void 0;
|
|
1006
|
+
}
|
|
1007
|
+
function isPermissionMode(value) {
|
|
1008
|
+
return VALID_PERMISSION_MODES.includes(value);
|
|
1009
|
+
}
|
|
1010
|
+
function formatInvalidPermissionModeMessage() {
|
|
1011
|
+
return `Invalid mode. Valid: ${VALID_PERMISSION_MODES.join(" | ")}`;
|
|
1012
|
+
}
|
|
1013
|
+
function resolvePermissionModeAdapter(context) {
|
|
1014
|
+
const adapter = context.getCommandHostAdapters?.().permissionMode;
|
|
1015
|
+
if (adapter !== void 0) {
|
|
1016
|
+
return adapter;
|
|
512
1017
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
1018
|
+
const runtime = context.getSession();
|
|
1019
|
+
return {
|
|
1020
|
+
getPermissionMode: () => runtime.getPermissionMode(),
|
|
1021
|
+
setPermissionMode: (mode) => runtime.setPermissionMode(mode),
|
|
1022
|
+
listSessionAllowedTools: () => runtime.getSessionAllowedTools()
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
function readCommandPermissionMode(context) {
|
|
1026
|
+
return resolvePermissionModeAdapter(context).getPermissionMode();
|
|
1027
|
+
}
|
|
1028
|
+
function writeCommandPermissionMode(context, mode) {
|
|
1029
|
+
resolvePermissionModeAdapter(context).setPermissionMode(mode);
|
|
1030
|
+
}
|
|
1031
|
+
function listCommandSessionAllowedTools(context) {
|
|
1032
|
+
return resolvePermissionModeAdapter(context).listSessionAllowedTools();
|
|
1033
|
+
}
|
|
1034
|
+
function readCommandPermissionsState(context) {
|
|
1035
|
+
return {
|
|
1036
|
+
mode: readCommandPermissionMode(context),
|
|
1037
|
+
sessionAllowed: listCommandSessionAllowedTools(context)
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
function formatCommandPermissionsMessage(state) {
|
|
1041
|
+
const lines = [`Permission mode: ${state.mode}`];
|
|
1042
|
+
if (state.sessionAllowed.length > 0) {
|
|
1043
|
+
lines.push(`Session-approved tools: ${state.sessionAllowed.join(", ")}`);
|
|
1044
|
+
} else {
|
|
1045
|
+
lines.push("No session-approved tools.");
|
|
516
1046
|
}
|
|
517
|
-
return
|
|
1047
|
+
return lines.join("\n");
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
// src/command-api/statusline/statusline-command-api.ts
|
|
1051
|
+
var STATUSLINE_COMMAND_DESCRIPTION = "Configure TUI status-line visibility and fields such as model, context, tokens, session, and git branch.";
|
|
1052
|
+
var STATUSLINE_COMMAND_ARGUMENT_HINT = "on | off | reset | git on | git off";
|
|
1053
|
+
var DEFAULT_STATUS_LINE_COMMAND_SETTINGS = {
|
|
1054
|
+
enabled: true,
|
|
1055
|
+
gitBranch: true
|
|
1056
|
+
};
|
|
1057
|
+
function buildStatusLineCommandSubcommands(source = "statusline") {
|
|
1058
|
+
return [
|
|
1059
|
+
{ name: "on", description: "Show the status line", source },
|
|
1060
|
+
{ name: "off", description: "Hide the status line", source },
|
|
1061
|
+
{ name: "reset", description: "Restore default status-line fields", source },
|
|
1062
|
+
{ name: "git", description: "Show or hide git branch field", source }
|
|
1063
|
+
];
|
|
1064
|
+
}
|
|
1065
|
+
function isStatusLineCommandSettingsPatch(value) {
|
|
1066
|
+
return (value.enabled === void 0 || typeof value.enabled === "boolean") && (value.gitBranch === void 0 || typeof value.gitBranch === "boolean");
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
// src/command-api/plugin/plugin-command-api.ts
|
|
1070
|
+
var PLUGIN_COMMAND_DESCRIPTION = "Manage plugins";
|
|
1071
|
+
var PLUGIN_COMMAND_ARGUMENT_HINT = "manage | install <name@marketplace> | uninstall <name@marketplace> | enable <name@marketplace> | disable <name@marketplace> | marketplace <action>";
|
|
1072
|
+
var RELOAD_PLUGINS_COMMAND_DESCRIPTION = "Reload all plugin resources";
|
|
1073
|
+
function createPluginTuiRequestedEffect() {
|
|
1074
|
+
return { type: "plugin-tui-requested" };
|
|
1075
|
+
}
|
|
1076
|
+
function createPluginRegistryReloadRequestedEffect() {
|
|
1077
|
+
return { type: "plugin-registry-reload-requested" };
|
|
1078
|
+
}
|
|
1079
|
+
function resolvePluginCommandAdapter(context) {
|
|
1080
|
+
return context.getCommandHostAdapters?.().plugin;
|
|
1081
|
+
}
|
|
1082
|
+
function buildPluginCommandSubcommands() {
|
|
1083
|
+
return [
|
|
1084
|
+
{ name: "manage", description: "Open plugin manager", source: "plugin-manager" },
|
|
1085
|
+
{ name: "install", description: "Install a plugin", source: "plugin-manager" },
|
|
1086
|
+
{ name: "uninstall", description: "Uninstall a plugin", source: "plugin-manager" },
|
|
1087
|
+
{ name: "enable", description: "Enable a plugin", source: "plugin-manager" },
|
|
1088
|
+
{ name: "disable", description: "Disable a plugin", source: "plugin-manager" },
|
|
1089
|
+
{
|
|
1090
|
+
name: "marketplace",
|
|
1091
|
+
description: "Manage plugin marketplaces",
|
|
1092
|
+
source: "plugin-manager",
|
|
1093
|
+
subcommands: [
|
|
1094
|
+
{ name: "add", description: "Add marketplace source", source: "plugin-manager" },
|
|
1095
|
+
{ name: "remove", description: "Remove marketplace source", source: "plugin-manager" },
|
|
1096
|
+
{ name: "update", description: "Update marketplace source", source: "plugin-manager" },
|
|
1097
|
+
{ name: "list", description: "List marketplace sources", source: "plugin-manager" }
|
|
1098
|
+
]
|
|
1099
|
+
}
|
|
1100
|
+
];
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
// src/command-api/session/session-command-api.ts
|
|
1104
|
+
var CLEAR_COMMAND_DESCRIPTION = "Clear conversation history";
|
|
1105
|
+
var RENAME_COMMAND_DESCRIPTION = "Rename the current session";
|
|
1106
|
+
var RENAME_COMMAND_USAGE = "Usage: rename <name>";
|
|
1107
|
+
var RESUME_COMMAND_DESCRIPTION = "Resume a previous session";
|
|
1108
|
+
var COST_COMMAND_DESCRIPTION = "Show session info";
|
|
1109
|
+
var EXIT_COMMAND_DESCRIPTION = "Exit CLI";
|
|
1110
|
+
function clearConversationHistory(context) {
|
|
1111
|
+
if (context.clearConversationHistory !== void 0) {
|
|
1112
|
+
context.clearConversationHistory();
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
context.getSession().clearHistory();
|
|
1116
|
+
}
|
|
1117
|
+
function parseSessionNameArgument(args) {
|
|
1118
|
+
const name = args.trim();
|
|
1119
|
+
return name.length > 0 ? name : void 0;
|
|
1120
|
+
}
|
|
1121
|
+
function createSessionRenamedEffect(name) {
|
|
1122
|
+
return { type: "session-renamed", name };
|
|
1123
|
+
}
|
|
1124
|
+
function createSessionPickerRequestedEffect() {
|
|
1125
|
+
return { type: "session-picker-requested" };
|
|
1126
|
+
}
|
|
1127
|
+
function createSessionExitRequestedEffect() {
|
|
1128
|
+
return { type: "session-exit-requested" };
|
|
1129
|
+
}
|
|
1130
|
+
function readCommandSessionInfo(context) {
|
|
1131
|
+
const session = context.getSession();
|
|
1132
|
+
return {
|
|
1133
|
+
sessionId: session.getSessionId(),
|
|
1134
|
+
messageCount: session.getMessageCount()
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
// src/command-api/checkpoint/rewind-command-api.ts
|
|
1139
|
+
var REWIND_COMMAND_DESCRIPTION = "List, inspect, restore, or rollback edit checkpoints.";
|
|
1140
|
+
var REWIND_COMMAND_ARGUMENT_HINT = "list | inspect CHECKPOINT_ID | restore CHECKPOINT_ID | code CHECKPOINT_ID | rollback CHECKPOINT_ID";
|
|
1141
|
+
function buildRewindCommandSubcommands(source = "rewind") {
|
|
1142
|
+
return [
|
|
1143
|
+
{ name: "list", description: "List edit checkpoints", source },
|
|
1144
|
+
{ name: "inspect", description: "Inspect captured files and restore plans", source },
|
|
1145
|
+
{ name: "restore", description: "Restore code to a checkpoint", source },
|
|
1146
|
+
{ name: "code", description: "Restore code to a checkpoint", source },
|
|
1147
|
+
{ name: "rollback", description: "Rollback code through a checkpoint", source }
|
|
1148
|
+
];
|
|
1149
|
+
}
|
|
1150
|
+
function listCommandEditCheckpoints(context) {
|
|
1151
|
+
return context.listEditCheckpoints();
|
|
1152
|
+
}
|
|
1153
|
+
function inspectCommandEditCheckpoint(context, checkpointId) {
|
|
1154
|
+
if (!context.inspectEditCheckpoint) {
|
|
1155
|
+
throw new Error("Checkpoint inspection is not available in this command host.");
|
|
1156
|
+
}
|
|
1157
|
+
return context.inspectEditCheckpoint(checkpointId);
|
|
1158
|
+
}
|
|
1159
|
+
function restoreCommandEditCheckpoint(context, checkpointId) {
|
|
1160
|
+
return context.restoreEditCheckpoint(checkpointId);
|
|
1161
|
+
}
|
|
1162
|
+
function rollbackCommandEditCheckpoint(context, checkpointId) {
|
|
1163
|
+
return context.rollbackEditCheckpoint(checkpointId);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
// src/memory/memory-policy-evaluator.ts
|
|
1167
|
+
var SENSITIVE_PATTERNS = [
|
|
1168
|
+
/\b(api[_-]?key|secret|token|password|private key)\b/i,
|
|
1169
|
+
/\b\d{3}-\d{2}-\d{4}\b/,
|
|
1170
|
+
/\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/,
|
|
1171
|
+
/주민등록|비밀번호|시크릿|토큰/u
|
|
1172
|
+
];
|
|
1173
|
+
function containsSensitiveMemoryContent(text) {
|
|
1174
|
+
return SENSITIVE_PATTERNS.some((pattern) => pattern.test(text));
|
|
518
1175
|
}
|
|
519
1176
|
|
|
520
1177
|
// src/memory/pending-memory-store.ts
|
|
@@ -642,595 +1299,118 @@ var ProjectMemoryStore = class {
|
|
|
642
1299
|
}
|
|
643
1300
|
getIndexPath() {
|
|
644
1301
|
return (0, import_path.join)(memoryRoot2(this.cwd), INDEX_FILENAME);
|
|
645
|
-
}
|
|
646
|
-
getTopicsPath() {
|
|
647
|
-
return (0, import_path.join)(memoryRoot2(this.cwd), TOPICS_DIRNAME);
|
|
648
|
-
}
|
|
649
|
-
loadStartupMemory() {
|
|
650
|
-
const path = this.getIndexPath();
|
|
651
|
-
if (!(0, import_fs.existsSync)(path)) {
|
|
652
|
-
return { content: "", path, lineCount: 0, truncated: false };
|
|
653
|
-
}
|
|
654
|
-
const raw = (0, import_fs.readFileSync)(path, "utf8");
|
|
655
|
-
const byBytes = truncateToUtf8Bytes(raw, MEMORY_INDEX_MAX_BYTES);
|
|
656
|
-
const byteTruncated = Buffer.byteLength(raw, "utf8") > MEMORY_INDEX_MAX_BYTES;
|
|
657
|
-
const byLines = limitLines(byBytes, MEMORY_INDEX_MAX_LINES);
|
|
658
|
-
return {
|
|
659
|
-
content: byLines.content,
|
|
660
|
-
path,
|
|
661
|
-
lineCount: byLines.content.length === 0 ? 0 : byLines.content.split(/\r?\n/).length,
|
|
662
|
-
truncated: byteTruncated || byLines.truncated
|
|
663
|
-
};
|
|
664
|
-
}
|
|
665
|
-
list() {
|
|
666
|
-
const topicsPath = this.getTopicsPath();
|
|
667
|
-
const topics = (0, import_fs.existsSync)(topicsPath) ? (0, import_fs.readdirSync)(topicsPath, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(TOPIC_EXTENSION)).map((entry) => ({
|
|
668
|
-
name: (0, import_path.basename)(entry.name, TOPIC_EXTENSION),
|
|
669
|
-
path: (0, import_path.join)(topicsPath, entry.name)
|
|
670
|
-
})).sort((a, b) => a.name.localeCompare(b.name)) : [];
|
|
671
|
-
return {
|
|
672
|
-
indexPath: this.getIndexPath(),
|
|
673
|
-
topicsPath,
|
|
674
|
-
topics
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
readTopic(topic) {
|
|
678
|
-
const normalized = sanitizeTopic(topic);
|
|
679
|
-
const path = (0, import_path.join)(this.getTopicsPath(), `${normalized}${TOPIC_EXTENSION}`);
|
|
680
|
-
if (!(0, import_fs.existsSync)(path)) return "";
|
|
681
|
-
return (0, import_fs.readFileSync)(path, "utf8").trimEnd();
|
|
682
|
-
}
|
|
683
|
-
append(input) {
|
|
684
|
-
const topic = sanitizeTopic(input.topic);
|
|
685
|
-
const root = memoryRoot2(this.cwd);
|
|
686
|
-
const topicsPath = this.getTopicsPath();
|
|
687
|
-
(0, import_fs.mkdirSync)(topicsPath, { recursive: true });
|
|
688
|
-
const indexPath = this.getIndexPath();
|
|
689
|
-
const topicPath = (0, import_path.join)(topicsPath, `${topic}${TOPIC_EXTENSION}`);
|
|
690
|
-
const entry = formatEntry(this.now(), input, topic);
|
|
691
|
-
const topicHeader = (0, import_fs.existsSync)(topicPath) ? "" : `# ${topic}
|
|
692
|
-
|
|
693
|
-
`;
|
|
694
|
-
const normalizedText = normalizeMemoryText(input.text);
|
|
695
|
-
if ((0, import_fs.existsSync)(topicPath) && (0, import_fs.readFileSync)(topicPath, "utf8").includes(`) ${normalizedText}`)) {
|
|
696
|
-
return { indexPath, topicPath, topic, deduplicated: true };
|
|
697
|
-
}
|
|
698
|
-
if (!(0, import_fs.existsSync)(indexPath)) {
|
|
699
|
-
(0, import_fs.mkdirSync)(root, { recursive: true });
|
|
700
|
-
(0, import_fs.writeFileSync)(indexPath, "# Project Memory\n\n", "utf8");
|
|
701
|
-
}
|
|
702
|
-
(0, import_fs.appendFileSync)(indexPath, `- ${entry}
|
|
703
|
-
`, "utf8");
|
|
704
|
-
(0, import_fs.appendFileSync)(topicPath, `${topicHeader}- ${entry}
|
|
705
|
-
`, "utf8");
|
|
706
|
-
return { indexPath, topicPath, topic, deduplicated: false };
|
|
707
|
-
}
|
|
708
|
-
};
|
|
709
|
-
|
|
710
|
-
// src/memory/memory-policy-evaluator.ts
|
|
711
|
-
var SENSITIVE_PATTERNS = [
|
|
712
|
-
/\b(api[_-]?key|secret|token|password|private key)\b/i,
|
|
713
|
-
/\b\d{3}-\d{2}-\d{4}\b/,
|
|
714
|
-
/\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/,
|
|
715
|
-
/주민등록|비밀번호|시크릿|토큰/u
|
|
716
|
-
];
|
|
717
|
-
function containsSensitiveMemoryContent(text) {
|
|
718
|
-
return SENSITIVE_PATTERNS.some((pattern) => pattern.test(text));
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
// src/commands/memory-command.ts
|
|
722
|
-
var SUBCOMMAND_INDEX = 0;
|
|
723
|
-
var TYPE_INDEX = 1;
|
|
724
|
-
var TOPIC_INDEX = 2;
|
|
725
|
-
var TEXT_START_INDEX = 3;
|
|
726
|
-
function usage() {
|
|
727
|
-
return {
|
|
728
|
-
message: "Usage: memory list | memory show [topic] | memory add <user|feedback|project|reference> <topic> <text> | memory pending | memory approve <id> | memory reject <id> | memory used",
|
|
729
|
-
success: false
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
function formatList(store) {
|
|
733
|
-
const summary = store.list();
|
|
734
|
-
const topics = summary.topics.length > 0 ? summary.topics.map((topic) => `- ${topic.name}: ${topic.path}`).join("\n") : "(none)";
|
|
735
|
-
return {
|
|
736
|
-
message: [
|
|
737
|
-
`Memory index: ${summary.indexPath}`,
|
|
738
|
-
`Topics directory: ${summary.topicsPath}`,
|
|
739
|
-
"Topics:",
|
|
740
|
-
topics
|
|
741
|
-
].join("\n"),
|
|
742
|
-
success: true,
|
|
743
|
-
data: {
|
|
744
|
-
indexPath: summary.indexPath,
|
|
745
|
-
topicsPath: summary.topicsPath,
|
|
746
|
-
topicCount: summary.topics.length
|
|
747
|
-
}
|
|
748
|
-
};
|
|
749
|
-
}
|
|
750
|
-
function formatShow(store, topic) {
|
|
751
|
-
if (!topic || topic === "index") {
|
|
752
|
-
const memory = store.loadStartupMemory();
|
|
753
|
-
return {
|
|
754
|
-
message: memory.content || "(empty memory index)",
|
|
755
|
-
success: true,
|
|
756
|
-
data: {
|
|
757
|
-
path: memory.path,
|
|
758
|
-
lineCount: memory.lineCount,
|
|
759
|
-
truncated: memory.truncated
|
|
760
|
-
}
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
|
-
const content = store.readTopic(topic);
|
|
764
|
-
return {
|
|
765
|
-
message: content || `(empty memory topic: ${topic})`,
|
|
766
|
-
success: true,
|
|
767
|
-
data: { topic }
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
function parseAdd(args) {
|
|
771
|
-
const type = args[TYPE_INDEX];
|
|
772
|
-
const topic = args[TOPIC_INDEX];
|
|
773
|
-
const text = args.slice(TEXT_START_INDEX).join(" ").trim();
|
|
774
|
-
if (!type || !isMemoryType(type) || !topic || text.length === 0) return void 0;
|
|
775
|
-
return { type, topic, text };
|
|
776
|
-
}
|
|
777
|
-
function formatPending(store) {
|
|
778
|
-
const records = store.list("pending");
|
|
779
|
-
const lines = records.length > 0 ? records.map(
|
|
780
|
-
(record) => `- ${record.id} ${record.type}/${record.topic} confidence=${record.confidence}: ${record.text}`
|
|
781
|
-
) : ["(no pending memory candidates)"];
|
|
782
|
-
return {
|
|
783
|
-
message: ["Pending memory candidates:", ...lines].join("\n"),
|
|
784
|
-
success: true,
|
|
785
|
-
data: { count: records.length }
|
|
786
|
-
};
|
|
787
|
-
}
|
|
788
|
-
function recordEvent(session, event) {
|
|
789
|
-
session.recordMemoryEvent({
|
|
790
|
-
...event,
|
|
791
|
-
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
792
|
-
});
|
|
793
|
-
}
|
|
794
|
-
function approvePending(session, pendingStore, memoryStore, id) {
|
|
795
|
-
if (!id) return usage();
|
|
796
|
-
try {
|
|
797
|
-
const approved = pendingStore.mark(id, "approved", "approved-by-user");
|
|
798
|
-
const saved = memoryStore.append(approved);
|
|
799
|
-
const record = pendingStore.mark(id, "saved", "approved-and-saved");
|
|
800
|
-
recordEvent(session, {
|
|
801
|
-
type: "memory_candidate_approved",
|
|
802
|
-
candidateId: record.id,
|
|
803
|
-
topic: record.topic,
|
|
804
|
-
reason: "approved-by-user"
|
|
805
|
-
});
|
|
806
|
-
recordEvent(session, {
|
|
807
|
-
type: "memory_candidate_saved",
|
|
808
|
-
candidateId: record.id,
|
|
809
|
-
topic: record.topic,
|
|
810
|
-
reason: saved.deduplicated ? "deduplicated" : "approved-and-saved"
|
|
811
|
-
});
|
|
812
|
-
return {
|
|
813
|
-
message: saved.deduplicated ? `Saved memory candidate ${id} was already present in ${saved.topicPath}` : `Saved memory candidate ${id} to ${saved.topicPath}`,
|
|
814
|
-
success: true,
|
|
815
|
-
data: {
|
|
816
|
-
id,
|
|
817
|
-
status: record.status,
|
|
818
|
-
topic: saved.topic,
|
|
819
|
-
topicPath: saved.topicPath,
|
|
820
|
-
deduplicated: saved.deduplicated
|
|
821
|
-
}
|
|
822
|
-
};
|
|
823
|
-
} catch (error) {
|
|
824
|
-
return {
|
|
825
|
-
message: error instanceof Error ? error.message : String(error),
|
|
826
|
-
success: false
|
|
827
|
-
};
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
function rejectPending(session, pendingStore, id) {
|
|
831
|
-
if (!id) return usage();
|
|
832
|
-
try {
|
|
833
|
-
const record = pendingStore.mark(id, "rejected", "rejected-by-user");
|
|
834
|
-
recordEvent(session, {
|
|
835
|
-
type: "memory_candidate_rejected",
|
|
836
|
-
candidateId: record.id,
|
|
837
|
-
topic: record.topic,
|
|
838
|
-
reason: "rejected-by-user"
|
|
839
|
-
});
|
|
840
|
-
return {
|
|
841
|
-
message: `Rejected memory candidate ${id}`,
|
|
842
|
-
success: true,
|
|
843
|
-
data: { id, status: record.status }
|
|
844
|
-
};
|
|
845
|
-
} catch (error) {
|
|
846
|
-
return {
|
|
847
|
-
message: error instanceof Error ? error.message : String(error),
|
|
848
|
-
success: false
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
function formatUsed(session) {
|
|
853
|
-
const references = session.getUsedMemoryReferences();
|
|
854
|
-
const lines = references.length > 0 ? references.map((reference) => {
|
|
855
|
-
const suffix = reference.truncated ? " truncated=true" : "";
|
|
856
|
-
return `- ${reference.topic} score=${reference.score}${suffix}: ${reference.path}`;
|
|
857
|
-
}) : ["(no memory used in current turn)"];
|
|
858
|
-
return {
|
|
859
|
-
message: ["Used memory references:", ...lines].join("\n"),
|
|
860
|
-
success: true,
|
|
861
|
-
data: { count: references.length, references }
|
|
862
|
-
};
|
|
863
|
-
}
|
|
864
|
-
function executeMemoryCommand(session, rawArgs) {
|
|
865
|
-
const args = rawArgs.trim().split(/\s+/).filter(Boolean);
|
|
866
|
-
const subcommand = args[SUBCOMMAND_INDEX] ?? "list";
|
|
867
|
-
const store = new ProjectMemoryStore(session.getCwd());
|
|
868
|
-
const pendingStore = new PendingMemoryStore(session.getCwd());
|
|
869
|
-
if (subcommand === "list") return formatList(store);
|
|
870
|
-
if (subcommand === "show") return formatShow(store, args[TYPE_INDEX]);
|
|
871
|
-
if (subcommand === "pending") return formatPending(pendingStore);
|
|
872
|
-
if (subcommand === "approve")
|
|
873
|
-
return approvePending(session, pendingStore, store, args[TYPE_INDEX]);
|
|
874
|
-
if (subcommand === "reject") return rejectPending(session, pendingStore, args[TYPE_INDEX]);
|
|
875
|
-
if (subcommand === "used") return formatUsed(session);
|
|
876
|
-
if (subcommand === "add") {
|
|
877
|
-
const input = parseAdd(args);
|
|
878
|
-
if (!input) return usage();
|
|
879
|
-
if (containsSensitiveMemoryContent(input.text)) {
|
|
880
|
-
return {
|
|
881
|
-
message: "Refusing to save sensitive memory content.",
|
|
882
|
-
success: false
|
|
883
|
-
};
|
|
1302
|
+
}
|
|
1303
|
+
getTopicsPath() {
|
|
1304
|
+
return (0, import_path.join)(memoryRoot2(this.cwd), TOPICS_DIRNAME);
|
|
1305
|
+
}
|
|
1306
|
+
loadStartupMemory() {
|
|
1307
|
+
const path = this.getIndexPath();
|
|
1308
|
+
if (!(0, import_fs.existsSync)(path)) {
|
|
1309
|
+
return { content: "", path, lineCount: 0, truncated: false };
|
|
884
1310
|
}
|
|
885
|
-
const
|
|
1311
|
+
const raw = (0, import_fs.readFileSync)(path, "utf8");
|
|
1312
|
+
const byBytes = truncateToUtf8Bytes(raw, MEMORY_INDEX_MAX_BYTES);
|
|
1313
|
+
const byteTruncated = Buffer.byteLength(raw, "utf8") > MEMORY_INDEX_MAX_BYTES;
|
|
1314
|
+
const byLines = limitLines(byBytes, MEMORY_INDEX_MAX_LINES);
|
|
886
1315
|
return {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
topicPath: result.topicPath,
|
|
892
|
-
topic: result.topic,
|
|
893
|
-
deduplicated: result.deduplicated
|
|
894
|
-
}
|
|
1316
|
+
content: byLines.content,
|
|
1317
|
+
path,
|
|
1318
|
+
lineCount: byLines.content.length === 0 ? 0 : byLines.content.split(/\r?\n/).length,
|
|
1319
|
+
truncated: byteTruncated || byLines.truncated
|
|
895
1320
|
};
|
|
896
1321
|
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
var PROMPT_PREVIEW_LENGTH = 120;
|
|
904
|
-
var ELLIPSIS_LENGTH = 3;
|
|
905
|
-
function usage2() {
|
|
906
|
-
return {
|
|
907
|
-
message: "Usage: rewind [list] | rewind restore <checkpoint-id> | rewind code <checkpoint-id>",
|
|
908
|
-
success: false
|
|
909
|
-
};
|
|
910
|
-
}
|
|
911
|
-
function formatPrompt(prompt) {
|
|
912
|
-
const compact = prompt.replace(/\s+/g, " ").trim();
|
|
913
|
-
if (compact.length <= PROMPT_PREVIEW_LENGTH) return compact;
|
|
914
|
-
return `${compact.slice(0, PROMPT_PREVIEW_LENGTH - ELLIPSIS_LENGTH)}...`;
|
|
915
|
-
}
|
|
916
|
-
function formatList2(checkpoints) {
|
|
917
|
-
const lines = checkpoints.length > 0 ? checkpoints.map(
|
|
918
|
-
(checkpoint) => `- ${checkpoint.id} files=${checkpoint.fileCount} ${checkpoint.createdAt} ${formatPrompt(
|
|
919
|
-
checkpoint.prompt
|
|
920
|
-
)}`
|
|
921
|
-
) : ["(no edit checkpoints)"];
|
|
922
|
-
return {
|
|
923
|
-
message: ["Edit checkpoints:", ...lines].join("\n"),
|
|
924
|
-
success: true,
|
|
925
|
-
data: { count: checkpoints.length, checkpoints: [...checkpoints] }
|
|
926
|
-
};
|
|
927
|
-
}
|
|
928
|
-
async function restore(session, checkpointId) {
|
|
929
|
-
if (!checkpointId) return usage2();
|
|
930
|
-
try {
|
|
931
|
-
const result = await session.restoreEditCheckpoint(checkpointId);
|
|
932
|
-
return {
|
|
933
|
-
message: [
|
|
934
|
-
`Restored code to ${result.target.id}.`,
|
|
935
|
-
`Restored files: ${result.restoredFileCount}`,
|
|
936
|
-
`Rolled back checkpoints: ${result.restoredCheckpointCount}`
|
|
937
|
-
].join("\n"),
|
|
938
|
-
success: true,
|
|
939
|
-
data: {
|
|
940
|
-
target: result.target,
|
|
941
|
-
restoredCheckpointCount: result.restoredCheckpointCount,
|
|
942
|
-
restoredFileCount: result.restoredFileCount,
|
|
943
|
-
removedCheckpointCount: result.removedCheckpointCount
|
|
944
|
-
}
|
|
945
|
-
};
|
|
946
|
-
} catch (error) {
|
|
1322
|
+
list() {
|
|
1323
|
+
const topicsPath = this.getTopicsPath();
|
|
1324
|
+
const topics = (0, import_fs.existsSync)(topicsPath) ? (0, import_fs.readdirSync)(topicsPath, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(TOPIC_EXTENSION)).map((entry) => ({
|
|
1325
|
+
name: (0, import_path.basename)(entry.name, TOPIC_EXTENSION),
|
|
1326
|
+
path: (0, import_path.join)(topicsPath, entry.name)
|
|
1327
|
+
})).sort((a, b) => a.name.localeCompare(b.name)) : [];
|
|
947
1328
|
return {
|
|
948
|
-
|
|
949
|
-
|
|
1329
|
+
indexPath: this.getIndexPath(),
|
|
1330
|
+
topicsPath,
|
|
1331
|
+
topics
|
|
950
1332
|
};
|
|
951
1333
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
return formatList2(session.listEditCheckpoints());
|
|
958
|
-
}
|
|
959
|
-
if (subcommand === "restore" || subcommand === "code") {
|
|
960
|
-
return restore(session, args[CHECKPOINT_ID_INDEX]);
|
|
1334
|
+
readTopic(topic) {
|
|
1335
|
+
const normalized = sanitizeTopic(topic);
|
|
1336
|
+
const path = (0, import_path.join)(this.getTopicsPath(), `${normalized}${TOPIC_EXTENSION}`);
|
|
1337
|
+
if (!(0, import_fs.existsSync)(path)) return "";
|
|
1338
|
+
return (0, import_fs.readFileSync)(path, "utf8").trimEnd();
|
|
961
1339
|
}
|
|
962
|
-
|
|
963
|
-
|
|
1340
|
+
append(input) {
|
|
1341
|
+
const topic = sanitizeTopic(input.topic);
|
|
1342
|
+
const root = memoryRoot2(this.cwd);
|
|
1343
|
+
const topicsPath = this.getTopicsPath();
|
|
1344
|
+
(0, import_fs.mkdirSync)(topicsPath, { recursive: true });
|
|
1345
|
+
const indexPath = this.getIndexPath();
|
|
1346
|
+
const topicPath = (0, import_path.join)(topicsPath, `${topic}${TOPIC_EXTENSION}`);
|
|
1347
|
+
const entry = formatEntry(this.now(), input, topic);
|
|
1348
|
+
const topicHeader = (0, import_fs.existsSync)(topicPath) ? "" : `# ${topic}
|
|
964
1349
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
this.commands = /* @__PURE__ */ new Map();
|
|
970
|
-
for (const cmd of commands ?? createSystemCommands()) {
|
|
971
|
-
this.commands.set(cmd.name, cmd);
|
|
1350
|
+
`;
|
|
1351
|
+
const normalizedText = normalizeMemoryText(input.text);
|
|
1352
|
+
if ((0, import_fs.existsSync)(topicPath) && (0, import_fs.readFileSync)(topicPath, "utf8").includes(`) ${normalizedText}`)) {
|
|
1353
|
+
return { indexPath, topicPath, topic, deduplicated: true };
|
|
972
1354
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
return await cmd.execute(session, args);
|
|
983
|
-
}
|
|
984
|
-
/** List all registered commands. */
|
|
985
|
-
listCommands() {
|
|
986
|
-
return [...this.commands.values()];
|
|
987
|
-
}
|
|
988
|
-
listModelInvocableCommands() {
|
|
989
|
-
return this.listCommands().filter((command) => command.modelInvocable === true).map((command) => ({
|
|
990
|
-
name: `/${command.name}`,
|
|
991
|
-
kind: "builtin-command",
|
|
992
|
-
description: command.description,
|
|
993
|
-
userInvocable: command.userInvocable !== false,
|
|
994
|
-
modelInvocable: true,
|
|
995
|
-
...command.argumentHint ? { argumentHint: command.argumentHint } : {},
|
|
996
|
-
...command.safety ? { safety: command.safety } : {}
|
|
997
|
-
}));
|
|
998
|
-
}
|
|
999
|
-
isModelInvocable(name) {
|
|
1000
|
-
return this.commands.get(name)?.modelInvocable === true;
|
|
1001
|
-
}
|
|
1002
|
-
async executeModelInvocable(name, session, args) {
|
|
1003
|
-
if (!this.isModelInvocable(name)) return null;
|
|
1004
|
-
return this.execute(name, session, args);
|
|
1005
|
-
}
|
|
1006
|
-
/** Check if a command exists. */
|
|
1007
|
-
hasCommand(name) {
|
|
1008
|
-
return this.commands.has(name);
|
|
1355
|
+
if (!(0, import_fs.existsSync)(indexPath)) {
|
|
1356
|
+
(0, import_fs.mkdirSync)(root, { recursive: true });
|
|
1357
|
+
(0, import_fs.writeFileSync)(indexPath, "# Project Memory\n\n", "utf8");
|
|
1358
|
+
}
|
|
1359
|
+
(0, import_fs.appendFileSync)(indexPath, `- ${entry}
|
|
1360
|
+
`, "utf8");
|
|
1361
|
+
(0, import_fs.appendFileSync)(topicPath, `${topicHeader}- ${entry}
|
|
1362
|
+
`, "utf8");
|
|
1363
|
+
return { indexPath, topicPath, topic, deduplicated: false };
|
|
1009
1364
|
}
|
|
1010
1365
|
};
|
|
1011
1366
|
|
|
1012
|
-
// src/
|
|
1013
|
-
var VALID_MODES = ["plan", "default", "acceptEdits", "bypassPermissions"];
|
|
1367
|
+
// src/command-api/memory/memory-command-api.ts
|
|
1014
1368
|
var MEMORY_COMMAND_DESCRIPTION = "Project memory command. Use it to inspect project memory when stored context may help, save durable preferences, project conventions, feedback, or references worth reusing across sessions, review pending candidates, and report memory provenance. Do not store secrets, credentials, or transient facts.";
|
|
1015
1369
|
var MEMORY_COMMAND_ARGUMENT_HINT = "list | show [topic] | add <user|feedback|project|reference> <topic> <text> | pending | approve <id> | reject <id> | used";
|
|
1016
|
-
|
|
1370
|
+
var MEMORY_COMMAND_USAGE = "Usage: memory list | memory show [topic] | memory add <user|feedback|project|reference> <topic> <text> | memory pending | memory approve <id> | memory reject <id> | memory used";
|
|
1371
|
+
function buildMemoryCommandSubcommands(source = "memory") {
|
|
1017
1372
|
return [
|
|
1373
|
+
{ name: "list", description: "List project memory topics", source },
|
|
1374
|
+
{ name: "show", description: "Show project memory index or a topic", source },
|
|
1375
|
+
{ name: "add", description: "Save durable project memory", source },
|
|
1376
|
+
{ name: "pending", description: "List pending memory candidates", source },
|
|
1377
|
+
{ name: "approve", description: "Approve a pending memory candidate", source },
|
|
1378
|
+
{ name: "reject", description: "Reject a pending memory candidate", source },
|
|
1018
1379
|
{
|
|
1019
|
-
name: "
|
|
1020
|
-
description: "Show
|
|
1021
|
-
|
|
1022
|
-
message: [
|
|
1023
|
-
"Available commands:",
|
|
1024
|
-
" help \u2014 Show this help",
|
|
1025
|
-
" clear \u2014 Clear conversation",
|
|
1026
|
-
" compact [instr] \u2014 Compact context (optional focus instructions)",
|
|
1027
|
-
" mode [m] \u2014 Show/change permission mode",
|
|
1028
|
-
" model <id> \u2014 Change AI model",
|
|
1029
|
-
" language <code> \u2014 Set response language (ko, en, ja, zh)",
|
|
1030
|
-
" cost \u2014 Show session info",
|
|
1031
|
-
" context \u2014 Context window info",
|
|
1032
|
-
" permissions \u2014 Permission rules",
|
|
1033
|
-
" memory \u2014 Manage project memory and pending candidates",
|
|
1034
|
-
" rewind \u2014 List or restore edit checkpoints",
|
|
1035
|
-
" provider \u2014 Provider profile status and switching",
|
|
1036
|
-
" resume \u2014 Resume a previous session",
|
|
1037
|
-
" background \u2014 List/cancel/close background tasks",
|
|
1038
|
-
" rename <name> \u2014 Rename the current session",
|
|
1039
|
-
" reset \u2014 Delete settings and exit"
|
|
1040
|
-
].join("\n"),
|
|
1041
|
-
success: true
|
|
1042
|
-
})
|
|
1043
|
-
},
|
|
1044
|
-
{
|
|
1045
|
-
name: "clear",
|
|
1046
|
-
description: "Clear conversation history",
|
|
1047
|
-
execute: (session, _args) => {
|
|
1048
|
-
const underlying = session.getSession();
|
|
1049
|
-
underlying.clearHistory();
|
|
1050
|
-
return { message: "Conversation cleared.", success: true };
|
|
1051
|
-
}
|
|
1052
|
-
},
|
|
1053
|
-
{
|
|
1054
|
-
name: "compact",
|
|
1055
|
-
description: "Compress context window",
|
|
1056
|
-
execute: async (session, args) => {
|
|
1057
|
-
const underlying = session.getSession();
|
|
1058
|
-
const instructions = args.trim() || void 0;
|
|
1059
|
-
const before = underlying.getContextState().usedPercentage;
|
|
1060
|
-
await underlying.compact(instructions);
|
|
1061
|
-
const after = underlying.getContextState().usedPercentage;
|
|
1062
|
-
return {
|
|
1063
|
-
message: `Context compacted: ${Math.round(before)}% -> ${Math.round(after)}%`,
|
|
1064
|
-
success: true,
|
|
1065
|
-
data: { before, after }
|
|
1066
|
-
};
|
|
1067
|
-
}
|
|
1068
|
-
},
|
|
1069
|
-
{
|
|
1070
|
-
name: "mode",
|
|
1071
|
-
description: "Show/change permission mode",
|
|
1072
|
-
execute: (session, args) => {
|
|
1073
|
-
const underlying = session.getSession();
|
|
1074
|
-
const arg = args.trim().split(/\s+/)[0];
|
|
1075
|
-
if (!arg) {
|
|
1076
|
-
return {
|
|
1077
|
-
message: `Current mode: ${underlying.getPermissionMode()}`,
|
|
1078
|
-
success: true,
|
|
1079
|
-
data: { mode: underlying.getPermissionMode() }
|
|
1080
|
-
};
|
|
1081
|
-
}
|
|
1082
|
-
if (VALID_MODES.includes(arg)) {
|
|
1083
|
-
underlying.setPermissionMode(arg);
|
|
1084
|
-
return {
|
|
1085
|
-
message: `Permission mode set to: ${arg}`,
|
|
1086
|
-
success: true,
|
|
1087
|
-
data: { mode: arg }
|
|
1088
|
-
};
|
|
1089
|
-
}
|
|
1090
|
-
return {
|
|
1091
|
-
message: `Invalid mode. Valid: ${VALID_MODES.join(" | ")}`,
|
|
1092
|
-
success: false
|
|
1093
|
-
};
|
|
1094
|
-
}
|
|
1095
|
-
},
|
|
1096
|
-
{
|
|
1097
|
-
name: "model",
|
|
1098
|
-
description: "Change AI model",
|
|
1099
|
-
execute: (_session, args) => {
|
|
1100
|
-
const modelId = args.trim().split(/\s+/)[0];
|
|
1101
|
-
if (!modelId) {
|
|
1102
|
-
return { message: "Usage: model <model-id>", success: false };
|
|
1103
|
-
}
|
|
1104
|
-
return {
|
|
1105
|
-
message: `Model change requested: ${modelId}`,
|
|
1106
|
-
success: true,
|
|
1107
|
-
data: { modelId }
|
|
1108
|
-
};
|
|
1109
|
-
}
|
|
1110
|
-
},
|
|
1111
|
-
{
|
|
1112
|
-
name: "language",
|
|
1113
|
-
description: "Set response language",
|
|
1114
|
-
execute: (_session, args) => {
|
|
1115
|
-
const lang = args.trim().split(/\s+/)[0];
|
|
1116
|
-
if (!lang) {
|
|
1117
|
-
return { message: "Usage: language <code> (e.g., ko, en, ja, zh)", success: false };
|
|
1118
|
-
}
|
|
1119
|
-
return {
|
|
1120
|
-
message: `Language set to "${lang}".`,
|
|
1121
|
-
success: true,
|
|
1122
|
-
data: { language: lang }
|
|
1123
|
-
};
|
|
1124
|
-
}
|
|
1125
|
-
},
|
|
1126
|
-
{
|
|
1127
|
-
name: "cost",
|
|
1128
|
-
description: "Show session info",
|
|
1129
|
-
execute: (session, _args) => {
|
|
1130
|
-
const underlying = session.getSession();
|
|
1131
|
-
const sessionId = underlying.getSessionId();
|
|
1132
|
-
const messageCount = underlying.getMessageCount();
|
|
1133
|
-
return {
|
|
1134
|
-
message: `Session: ${sessionId}
|
|
1135
|
-
Messages: ${messageCount}`,
|
|
1136
|
-
success: true,
|
|
1137
|
-
data: { sessionId, messageCount }
|
|
1138
|
-
};
|
|
1139
|
-
}
|
|
1140
|
-
},
|
|
1141
|
-
{
|
|
1142
|
-
name: "context",
|
|
1143
|
-
description: "Context window info",
|
|
1144
|
-
execute: (session, _args) => {
|
|
1145
|
-
const ctx = session.getContextState();
|
|
1146
|
-
return {
|
|
1147
|
-
message: `Context: ${ctx.usedTokens.toLocaleString()} / ${ctx.maxTokens.toLocaleString()} tokens (${Math.round(ctx.usedPercentage)}%)`,
|
|
1148
|
-
success: true,
|
|
1149
|
-
data: {
|
|
1150
|
-
usedTokens: ctx.usedTokens,
|
|
1151
|
-
maxTokens: ctx.maxTokens,
|
|
1152
|
-
percentage: ctx.usedPercentage
|
|
1153
|
-
}
|
|
1154
|
-
};
|
|
1155
|
-
}
|
|
1156
|
-
},
|
|
1157
|
-
{
|
|
1158
|
-
name: "permissions",
|
|
1159
|
-
description: "Show permission rules",
|
|
1160
|
-
execute: (session, _args) => {
|
|
1161
|
-
const underlying = session.getSession();
|
|
1162
|
-
const mode = underlying.getPermissionMode();
|
|
1163
|
-
const sessionAllowed = underlying.getSessionAllowedTools();
|
|
1164
|
-
const lines = [`Permission mode: ${mode}`];
|
|
1165
|
-
if (sessionAllowed.length > 0) {
|
|
1166
|
-
lines.push(`Session-approved tools: ${sessionAllowed.join(", ")}`);
|
|
1167
|
-
} else {
|
|
1168
|
-
lines.push("No session-approved tools.");
|
|
1169
|
-
}
|
|
1170
|
-
return {
|
|
1171
|
-
message: lines.join("\n"),
|
|
1172
|
-
success: true,
|
|
1173
|
-
data: { mode, sessionAllowed }
|
|
1174
|
-
};
|
|
1175
|
-
}
|
|
1176
|
-
},
|
|
1177
|
-
{
|
|
1178
|
-
name: "memory",
|
|
1179
|
-
description: MEMORY_COMMAND_DESCRIPTION,
|
|
1180
|
-
modelInvocable: true,
|
|
1181
|
-
argumentHint: MEMORY_COMMAND_ARGUMENT_HINT,
|
|
1182
|
-
safety: "write",
|
|
1183
|
-
execute: executeMemoryCommand
|
|
1184
|
-
},
|
|
1185
|
-
{
|
|
1186
|
-
name: "rewind",
|
|
1187
|
-
description: "List edit checkpoints or restore code to a previous checkpoint.",
|
|
1188
|
-
argumentHint: "list | restore CHECKPOINT_ID | code CHECKPOINT_ID",
|
|
1189
|
-
safety: "write",
|
|
1190
|
-
execute: executeRewindCommand
|
|
1191
|
-
},
|
|
1192
|
-
{
|
|
1193
|
-
name: "resume",
|
|
1194
|
-
description: "Resume a previous session",
|
|
1195
|
-
execute: (_session, _args) => ({
|
|
1196
|
-
message: "Opening session picker...",
|
|
1197
|
-
success: true,
|
|
1198
|
-
data: { triggerResumePicker: true }
|
|
1199
|
-
})
|
|
1200
|
-
},
|
|
1201
|
-
{
|
|
1202
|
-
name: "background",
|
|
1203
|
-
description: "List and control background tasks",
|
|
1204
|
-
execute: executeBackgroundCommand
|
|
1205
|
-
},
|
|
1206
|
-
{
|
|
1207
|
-
name: "rename",
|
|
1208
|
-
description: "Rename the current session",
|
|
1209
|
-
execute: (_session, args) => {
|
|
1210
|
-
const name = args.trim();
|
|
1211
|
-
if (!name) {
|
|
1212
|
-
return { message: "Usage: rename <name>", success: false };
|
|
1213
|
-
}
|
|
1214
|
-
return {
|
|
1215
|
-
message: `Session renamed to "${name}".`,
|
|
1216
|
-
success: true,
|
|
1217
|
-
data: { name }
|
|
1218
|
-
};
|
|
1219
|
-
}
|
|
1220
|
-
},
|
|
1221
|
-
{
|
|
1222
|
-
name: "reset",
|
|
1223
|
-
description: "Delete settings",
|
|
1224
|
-
execute: (_session, _args) => {
|
|
1225
|
-
return {
|
|
1226
|
-
message: "Reset requested.",
|
|
1227
|
-
success: true,
|
|
1228
|
-
data: { resetRequested: true }
|
|
1229
|
-
};
|
|
1230
|
-
}
|
|
1380
|
+
name: "used",
|
|
1381
|
+
description: "Show memory references used in the current turn",
|
|
1382
|
+
source
|
|
1231
1383
|
}
|
|
1232
1384
|
];
|
|
1233
1385
|
}
|
|
1386
|
+
function createCommandProjectMemoryStore(cwd, now) {
|
|
1387
|
+
return new ProjectMemoryStore(cwd, now);
|
|
1388
|
+
}
|
|
1389
|
+
function createCommandPendingMemoryStore(cwd, now) {
|
|
1390
|
+
return new PendingMemoryStore(cwd, now);
|
|
1391
|
+
}
|
|
1392
|
+
function createCommandMemoryStores(context, now) {
|
|
1393
|
+
const cwd = context.getCwd();
|
|
1394
|
+
return {
|
|
1395
|
+
project: createCommandProjectMemoryStore(cwd, now),
|
|
1396
|
+
pending: createCommandPendingMemoryStore(cwd, now)
|
|
1397
|
+
};
|
|
1398
|
+
}
|
|
1399
|
+
function isCommandMemoryType(value) {
|
|
1400
|
+
return isMemoryType(value);
|
|
1401
|
+
}
|
|
1402
|
+
function hasSensitiveCommandMemoryContent(text) {
|
|
1403
|
+
return containsSensitiveMemoryContent(text);
|
|
1404
|
+
}
|
|
1405
|
+
function listCommandUsedMemoryReferences(context) {
|
|
1406
|
+
return context.getUsedMemoryReferences();
|
|
1407
|
+
}
|
|
1408
|
+
function recordCommandMemoryEvent(context, event, now = () => /* @__PURE__ */ new Date()) {
|
|
1409
|
+
context.recordMemoryEvent({
|
|
1410
|
+
...event,
|
|
1411
|
+
at: now().toISOString()
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1234
1414
|
|
|
1235
1415
|
// src/utils/skill-prompt.ts
|
|
1236
1416
|
var import_node_child_process = require("child_process");
|
|
@@ -1330,7 +1510,7 @@ async function executeSkill(skill, args, callbacks, context) {
|
|
|
1330
1510
|
}
|
|
1331
1511
|
|
|
1332
1512
|
// src/assembly/create-subagent-session.ts
|
|
1333
|
-
var
|
|
1513
|
+
var import_agent_sessions2 = require("@robota-sdk/agent-sessions");
|
|
1334
1514
|
|
|
1335
1515
|
// src/assembly/subagent-prompts.ts
|
|
1336
1516
|
function getSubagentSuffix() {
|
|
@@ -1394,7 +1574,7 @@ function createSubagentSession(options) {
|
|
|
1394
1574
|
isForkWorker: options.isForkWorker ?? false
|
|
1395
1575
|
});
|
|
1396
1576
|
const provider = options.provider;
|
|
1397
|
-
return new
|
|
1577
|
+
return new import_agent_sessions2.Session({
|
|
1398
1578
|
tools,
|
|
1399
1579
|
provider,
|
|
1400
1580
|
systemMessage,
|
|
@@ -1561,15 +1741,149 @@ function createInProcessSubagentRunner(deps) {
|
|
|
1561
1741
|
};
|
|
1562
1742
|
}
|
|
1563
1743
|
|
|
1744
|
+
// src/tools/agent-tool-batch.ts
|
|
1745
|
+
function stringifyAgentBatchResult(input) {
|
|
1746
|
+
const successfulJobs = input.jobs.filter((job) => job.success);
|
|
1747
|
+
const agentIds = input.jobs.map((job) => job.agentId).filter((agentId) => typeof agentId === "string" && agentId.length > 0);
|
|
1748
|
+
const failedJobCount = input.jobs.filter((job) => !job.success).length;
|
|
1749
|
+
return JSON.stringify({
|
|
1750
|
+
success: input.jobs.every((job) => job.success),
|
|
1751
|
+
mode: "batch",
|
|
1752
|
+
output: successfulJobs.map((job) => job.output ?? "").filter(Boolean).join("\n\n"),
|
|
1753
|
+
groupId: input.groupId,
|
|
1754
|
+
requestedJobCount: input.requestedJobCount,
|
|
1755
|
+
startedJobCount: agentIds.length,
|
|
1756
|
+
failedJobCount,
|
|
1757
|
+
agentIds,
|
|
1758
|
+
jobs: input.jobs,
|
|
1759
|
+
provenance: {
|
|
1760
|
+
source: "agent-tool-batch",
|
|
1761
|
+
groupId: input.groupId,
|
|
1762
|
+
requestedJobCount: input.requestedJobCount,
|
|
1763
|
+
startedJobCount: agentIds.length,
|
|
1764
|
+
failedJobCount
|
|
1765
|
+
}
|
|
1766
|
+
});
|
|
1767
|
+
}
|
|
1768
|
+
function createBatchGroupId() {
|
|
1769
|
+
const idRadix = 36;
|
|
1770
|
+
const randomStartIndex = 2;
|
|
1771
|
+
const randomEndIndex = 10;
|
|
1772
|
+
return `agent_group_${Date.now()}_${Math.random().toString(idRadix).slice(randomStartIndex, randomEndIndex)}`;
|
|
1773
|
+
}
|
|
1774
|
+
function normalizeJobLabel(label, fallback) {
|
|
1775
|
+
const trimmed = label?.trim();
|
|
1776
|
+
return trimmed && trimmed.length > 0 ? trimmed : fallback;
|
|
1777
|
+
}
|
|
1778
|
+
function resolveBatchJob(job, index, input) {
|
|
1779
|
+
const agentType = job.subagent_type ?? "general-purpose";
|
|
1780
|
+
const agentDef = input.resolveAgentDefinition(agentType, input.deps.customAgentRegistry);
|
|
1781
|
+
const label = normalizeJobLabel(job.label, agentDef?.name ?? agentType);
|
|
1782
|
+
return { index, job, agentType, agentDef, label };
|
|
1783
|
+
}
|
|
1784
|
+
function isValidBatchJob(job) {
|
|
1785
|
+
return job.agentDef !== void 0;
|
|
1786
|
+
}
|
|
1787
|
+
function createUnknownAgentBatchResult(job, groupId) {
|
|
1788
|
+
return {
|
|
1789
|
+
index: job.index,
|
|
1790
|
+
success: false,
|
|
1791
|
+
groupId,
|
|
1792
|
+
label: job.label,
|
|
1793
|
+
subagent_type: job.agentType,
|
|
1794
|
+
prompt: job.job.prompt,
|
|
1795
|
+
error: `Unknown agent type: ${job.agentType}`
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
async function spawnBatchJob(job, input) {
|
|
1799
|
+
try {
|
|
1800
|
+
const state = await input.manager.spawn(
|
|
1801
|
+
input.createSpawnRequest(job.job, job.agentType, job.agentDef, input.deps, job.label)
|
|
1802
|
+
);
|
|
1803
|
+
return { ...job, agentId: state.id };
|
|
1804
|
+
} catch (error) {
|
|
1805
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1806
|
+
return { ...job, spawnError: message };
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
function createBatchSpawnErrorResult(job, groupId) {
|
|
1810
|
+
return {
|
|
1811
|
+
index: job.index,
|
|
1812
|
+
success: false,
|
|
1813
|
+
groupId,
|
|
1814
|
+
label: job.label,
|
|
1815
|
+
subagent_type: job.agentType,
|
|
1816
|
+
prompt: job.job.prompt,
|
|
1817
|
+
error: `Sub-agent error: ${job.spawnError ?? "missing agent id"}`
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
function createBatchSuccessResult(job, groupId, result) {
|
|
1821
|
+
return {
|
|
1822
|
+
index: job.index,
|
|
1823
|
+
success: true,
|
|
1824
|
+
groupId,
|
|
1825
|
+
label: job.label,
|
|
1826
|
+
agentId: result.jobId,
|
|
1827
|
+
subagent_type: job.agentType,
|
|
1828
|
+
prompt: job.job.prompt,
|
|
1829
|
+
output: result.output,
|
|
1830
|
+
metadata: result.metadata
|
|
1831
|
+
};
|
|
1832
|
+
}
|
|
1833
|
+
function createBatchWaitErrorResult(job, groupId, message) {
|
|
1834
|
+
return {
|
|
1835
|
+
index: job.index,
|
|
1836
|
+
success: false,
|
|
1837
|
+
groupId,
|
|
1838
|
+
label: job.label,
|
|
1839
|
+
agentId: job.agentId,
|
|
1840
|
+
subagent_type: job.agentType,
|
|
1841
|
+
prompt: job.job.prompt,
|
|
1842
|
+
error: `Sub-agent error: ${message}`
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
async function waitBatchJob(job, groupId, manager) {
|
|
1846
|
+
if (job.agentId === void 0) {
|
|
1847
|
+
return createBatchSpawnErrorResult(job, groupId);
|
|
1848
|
+
}
|
|
1849
|
+
try {
|
|
1850
|
+
const result = await manager.wait(job.agentId);
|
|
1851
|
+
return createBatchSuccessResult({ ...job, agentId: job.agentId }, groupId, result);
|
|
1852
|
+
} catch (error) {
|
|
1853
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1854
|
+
return createBatchWaitErrorResult({ ...job, agentId: job.agentId }, groupId, message);
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
async function runManagedAgentBatch(input) {
|
|
1858
|
+
const groupId = createBatchGroupId();
|
|
1859
|
+
const resolvedJobs = input.jobs.map((job, index) => resolveBatchJob(job, index, input));
|
|
1860
|
+
const invalidJobs = resolvedJobs.filter((job) => !isValidBatchJob(job)).map((job) => createUnknownAgentBatchResult(job, groupId));
|
|
1861
|
+
const startedJobs = await Promise.all(
|
|
1862
|
+
resolvedJobs.filter(isValidBatchJob).map((job) => spawnBatchJob(job, input))
|
|
1863
|
+
);
|
|
1864
|
+
const terminalJobs = await Promise.all(
|
|
1865
|
+
startedJobs.map((job) => waitBatchJob(job, groupId, input.manager))
|
|
1866
|
+
);
|
|
1867
|
+
const batchJobs = [...invalidJobs, ...terminalJobs].sort(
|
|
1868
|
+
(left, right) => left.index - right.index
|
|
1869
|
+
);
|
|
1870
|
+
return stringifyAgentBatchResult({
|
|
1871
|
+
groupId,
|
|
1872
|
+
requestedJobCount: input.jobs.length,
|
|
1873
|
+
jobs: batchJobs
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1564
1877
|
// src/tools/agent-tool.ts
|
|
1565
1878
|
var AGENT_TOOL_DESCRIPTION = [
|
|
1566
1879
|
"Creates delegated subagent jobs in isolated contexts.",
|
|
1567
1880
|
"Without jobs, one tool call creates one subagent job from prompt.",
|
|
1568
|
-
"For explicit multi-agent or parallel-agent requests, use one Agent tool call with jobs containing one entry per requested role.",
|
|
1881
|
+
"For explicit multi-agent or parallel-agent requests, use one Agent tool call with jobs containing one entry per requested role and a stable label for each role.",
|
|
1569
1882
|
"When the user explicitly asks to create, run, spawn, delegate to, or use agents/subagents, start the requested subagent job immediately.",
|
|
1570
1883
|
"Do not ask a follow-up question unless execution is impossible or unsafe.",
|
|
1571
1884
|
"Subagent jobs run as background tasks by default.",
|
|
1572
|
-
"The tool waits for a terminal result and returns completed, failed, or timed-out outcome data
|
|
1885
|
+
"The tool waits for a terminal result and returns completed, failed, or timed-out outcome data with structured requested/started job counts.",
|
|
1886
|
+
"After the tool returns, base user-facing claims on returned mode and counts; do not say parallel or multiple jobs started unless the result proves those jobs started.",
|
|
1573
1887
|
"Execution is represented by a real tool call and runtime background task event."
|
|
1574
1888
|
].join(" ");
|
|
1575
1889
|
function createAgentToolPromptDescription(agentDefinitions = []) {
|
|
@@ -1577,10 +1891,11 @@ function createAgentToolPromptDescription(agentDefinitions = []) {
|
|
|
1577
1891
|
return [
|
|
1578
1892
|
"Agent \u2014 creates isolated subagent jobs.",
|
|
1579
1893
|
"Without jobs, one Agent tool call corresponds to one subagent job.",
|
|
1580
|
-
"For explicit multi-agent or parallel-agent requests, use one Agent tool call with jobs containing one entry per requested role.",
|
|
1894
|
+
"For explicit multi-agent or parallel-agent requests, use one Agent tool call with jobs containing one entry per requested role and a stable label for each role.",
|
|
1581
1895
|
"When the user explicitly asks to create, run, spawn, delegate to, or use agents/subagents, start the requested subagent job immediately.",
|
|
1582
1896
|
"Do not ask a follow-up question unless execution is impossible or unsafe.",
|
|
1583
|
-
"The tool returns terminal result data.",
|
|
1897
|
+
"The tool returns terminal result data with mode, requestedJobCount, startedJobCount, failedJobCount, and provenance.",
|
|
1898
|
+
"After the tool returns, base user-facing claims on returned mode and counts; do not say parallel or multiple jobs started unless the result proves those jobs started.",
|
|
1584
1899
|
"Runtime mode is background.",
|
|
1585
1900
|
availableAgents
|
|
1586
1901
|
].join(" ").replace(/\s+/g, " ").trim();
|
|
@@ -1595,6 +1910,7 @@ var AgentSchema = import_zod.z.object({
|
|
|
1595
1910
|
isolation: import_zod.z.enum(["none", "worktree"]).optional().describe('Optional runtime isolation mode. "worktree" runs in a Git worktree.'),
|
|
1596
1911
|
jobs: import_zod.z.array(
|
|
1597
1912
|
import_zod.z.object({
|
|
1913
|
+
label: import_zod.z.string().optional().describe("Stable role label for this batch job"),
|
|
1598
1914
|
prompt: import_zod.z.string().describe("The task for this subagent to perform"),
|
|
1599
1915
|
subagent_type: import_zod.z.string().optional().describe("Agent type for this job"),
|
|
1600
1916
|
model: import_zod.z.string().optional().describe("Optional model override for this job"),
|
|
@@ -1623,10 +1939,10 @@ function createSubagentManager(deps) {
|
|
|
1623
1939
|
runner: createInProcessSubagentRunner(deps)
|
|
1624
1940
|
});
|
|
1625
1941
|
}
|
|
1626
|
-
function createSpawnRequest(args, agentType, agentDef, deps) {
|
|
1942
|
+
function createSpawnRequest(args, agentType, agentDef, deps, label = agentDef.name) {
|
|
1627
1943
|
return {
|
|
1628
1944
|
type: agentType,
|
|
1629
|
-
label
|
|
1945
|
+
label,
|
|
1630
1946
|
parentSessionId: deps.parentSessionId ?? "unknown-session",
|
|
1631
1947
|
mode: "background",
|
|
1632
1948
|
depth: deps.subagentDepth ?? 1,
|
|
@@ -1639,39 +1955,65 @@ function createSpawnRequest(args, agentType, agentDef, deps) {
|
|
|
1639
1955
|
function stringifyUnknownAgentType(agentType) {
|
|
1640
1956
|
return JSON.stringify({
|
|
1641
1957
|
success: false,
|
|
1958
|
+
mode: "single",
|
|
1959
|
+
requestedJobCount: 1,
|
|
1960
|
+
startedJobCount: 0,
|
|
1961
|
+
failedJobCount: 1,
|
|
1642
1962
|
output: "",
|
|
1643
|
-
error: `Unknown agent type: ${agentType}
|
|
1963
|
+
error: `Unknown agent type: ${agentType}`,
|
|
1964
|
+
provenance: {
|
|
1965
|
+
source: "agent-tool-single",
|
|
1966
|
+
requestedJobCount: 1,
|
|
1967
|
+
startedJobCount: 0,
|
|
1968
|
+
failedJobCount: 1
|
|
1969
|
+
}
|
|
1644
1970
|
});
|
|
1645
1971
|
}
|
|
1646
1972
|
function stringifyAgentSuccess(result) {
|
|
1647
1973
|
const worktreePath = result.metadata?.["worktreePath"];
|
|
1648
1974
|
const branchName = result.metadata?.["branchName"];
|
|
1975
|
+
const worktreeStatus = result.metadata?.["worktreeStatus"];
|
|
1976
|
+
const worktreeNextAction = result.metadata?.["worktreeNextAction"];
|
|
1649
1977
|
return JSON.stringify({
|
|
1650
1978
|
success: true,
|
|
1979
|
+
mode: "single",
|
|
1980
|
+
requestedJobCount: 1,
|
|
1981
|
+
startedJobCount: 1,
|
|
1982
|
+
failedJobCount: 0,
|
|
1651
1983
|
output: result.output,
|
|
1652
1984
|
agentId: result.jobId,
|
|
1985
|
+
agentIds: [result.jobId],
|
|
1986
|
+
provenance: {
|
|
1987
|
+
source: "agent-tool-single",
|
|
1988
|
+
requestedJobCount: 1,
|
|
1989
|
+
startedJobCount: 1,
|
|
1990
|
+
failedJobCount: 0
|
|
1991
|
+
},
|
|
1653
1992
|
metadata: result.metadata,
|
|
1654
1993
|
...typeof worktreePath === "string" ? { worktreePath } : {},
|
|
1655
|
-
...typeof branchName === "string" ? { branchName } : {}
|
|
1994
|
+
...typeof branchName === "string" ? { branchName } : {},
|
|
1995
|
+
...typeof worktreeStatus === "string" ? { worktreeStatus } : {},
|
|
1996
|
+
...typeof worktreeNextAction === "string" ? { worktreeNextAction } : {}
|
|
1656
1997
|
});
|
|
1657
1998
|
}
|
|
1658
1999
|
function stringifyAgentError(message, agentId) {
|
|
2000
|
+
const startedJobCount = agentId === void 0 ? 0 : 1;
|
|
1659
2001
|
return JSON.stringify({
|
|
1660
2002
|
success: false,
|
|
2003
|
+
mode: "single",
|
|
2004
|
+
requestedJobCount: 1,
|
|
2005
|
+
startedJobCount,
|
|
2006
|
+
failedJobCount: 1,
|
|
1661
2007
|
output: "",
|
|
1662
2008
|
error: `Sub-agent error: ${message}`,
|
|
1663
|
-
agentId
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
output: successfulJobs.map((job) => job.output ?? "").filter(Boolean).join("\n\n"),
|
|
1672
|
-
groupId: input.groupId,
|
|
1673
|
-
agentIds,
|
|
1674
|
-
jobs: input.jobs
|
|
2009
|
+
agentId,
|
|
2010
|
+
...agentId !== void 0 ? { agentIds: [agentId] } : {},
|
|
2011
|
+
provenance: {
|
|
2012
|
+
source: "agent-tool-single",
|
|
2013
|
+
requestedJobCount: 1,
|
|
2014
|
+
startedJobCount,
|
|
2015
|
+
failedJobCount: 1
|
|
2016
|
+
}
|
|
1675
2017
|
});
|
|
1676
2018
|
}
|
|
1677
2019
|
async function runManagedAgent(args, deps, manager) {
|
|
@@ -1695,75 +2037,6 @@ async function runManagedAgent(args, deps, manager) {
|
|
|
1695
2037
|
return stringifyAgentError(message, agentId);
|
|
1696
2038
|
}
|
|
1697
2039
|
}
|
|
1698
|
-
function createBatchGroupId() {
|
|
1699
|
-
return `agent_group_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
1700
|
-
}
|
|
1701
|
-
async function runManagedAgentBatch(jobs, deps, manager) {
|
|
1702
|
-
const groupId = createBatchGroupId();
|
|
1703
|
-
const resolvedJobs = jobs.map((job, index) => {
|
|
1704
|
-
const agentType = job.subagent_type ?? "general-purpose";
|
|
1705
|
-
const agentDef = resolveAgentDefinition2(agentType, deps.customAgentRegistry);
|
|
1706
|
-
return { index, job, agentType, agentDef };
|
|
1707
|
-
});
|
|
1708
|
-
const invalidJobs = resolvedJobs.filter((job) => job.agentDef === void 0).map((job) => ({
|
|
1709
|
-
index: job.index,
|
|
1710
|
-
success: false,
|
|
1711
|
-
subagent_type: job.agentType,
|
|
1712
|
-
error: `Unknown agent type: ${job.agentType}`
|
|
1713
|
-
}));
|
|
1714
|
-
const validJobs = resolvedJobs.filter(
|
|
1715
|
-
(job) => job.agentDef !== void 0
|
|
1716
|
-
);
|
|
1717
|
-
const startedJobs = await Promise.all(
|
|
1718
|
-
validJobs.map(async (job) => {
|
|
1719
|
-
try {
|
|
1720
|
-
const state = await manager.spawn(
|
|
1721
|
-
createSpawnRequest(job.job, job.agentType, job.agentDef, deps)
|
|
1722
|
-
);
|
|
1723
|
-
return { ...job, agentId: state.id, spawnError: void 0 };
|
|
1724
|
-
} catch (error) {
|
|
1725
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1726
|
-
return { ...job, agentId: void 0, spawnError: message };
|
|
1727
|
-
}
|
|
1728
|
-
})
|
|
1729
|
-
);
|
|
1730
|
-
const terminalJobs = await Promise.all(
|
|
1731
|
-
startedJobs.map(async (job) => {
|
|
1732
|
-
if (job.spawnError || !job.agentId) {
|
|
1733
|
-
return {
|
|
1734
|
-
index: job.index,
|
|
1735
|
-
success: false,
|
|
1736
|
-
subagent_type: job.agentType,
|
|
1737
|
-
error: `Sub-agent error: ${job.spawnError ?? "missing agent id"}`
|
|
1738
|
-
};
|
|
1739
|
-
}
|
|
1740
|
-
try {
|
|
1741
|
-
const result = await manager.wait(job.agentId);
|
|
1742
|
-
return {
|
|
1743
|
-
index: job.index,
|
|
1744
|
-
success: true,
|
|
1745
|
-
agentId: result.jobId,
|
|
1746
|
-
subagent_type: job.agentType,
|
|
1747
|
-
output: result.output,
|
|
1748
|
-
metadata: result.metadata
|
|
1749
|
-
};
|
|
1750
|
-
} catch (error) {
|
|
1751
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1752
|
-
return {
|
|
1753
|
-
index: job.index,
|
|
1754
|
-
success: false,
|
|
1755
|
-
agentId: job.agentId,
|
|
1756
|
-
subagent_type: job.agentType,
|
|
1757
|
-
error: `Sub-agent error: ${message}`
|
|
1758
|
-
};
|
|
1759
|
-
}
|
|
1760
|
-
})
|
|
1761
|
-
);
|
|
1762
|
-
const batchJobs = [...invalidJobs, ...terminalJobs].sort(
|
|
1763
|
-
(left, right) => left.index - right.index
|
|
1764
|
-
);
|
|
1765
|
-
return stringifyAgentBatchResult({ groupId, jobs: batchJobs });
|
|
1766
|
-
}
|
|
1767
2040
|
function createAgentTool(deps) {
|
|
1768
2041
|
const manager = createSubagentManager(deps);
|
|
1769
2042
|
return (0, import_agent_tools.createZodFunctionTool)(
|
|
@@ -1773,7 +2046,13 @@ function createAgentTool(deps) {
|
|
|
1773
2046
|
async (params) => {
|
|
1774
2047
|
const args = params;
|
|
1775
2048
|
if (Array.isArray(args.jobs) && args.jobs.length > 0) {
|
|
1776
|
-
return runManagedAgentBatch(
|
|
2049
|
+
return runManagedAgentBatch({
|
|
2050
|
+
jobs: args.jobs,
|
|
2051
|
+
deps,
|
|
2052
|
+
manager,
|
|
2053
|
+
resolveAgentDefinition: resolveAgentDefinition2,
|
|
2054
|
+
createSpawnRequest
|
|
2055
|
+
});
|
|
1777
2056
|
}
|
|
1778
2057
|
return runManagedAgent(
|
|
1779
2058
|
{
|
|
@@ -1992,7 +2271,7 @@ function retrieveSessionBackgroundTaskManager(key) {
|
|
|
1992
2271
|
|
|
1993
2272
|
// src/interactive/interactive-session-execution.ts
|
|
1994
2273
|
var import_node_crypto = require("crypto");
|
|
1995
|
-
var
|
|
2274
|
+
var import_agent_core5 = require("@robota-sdk/agent-core");
|
|
1996
2275
|
function isAbortError(err) {
|
|
1997
2276
|
return err instanceof DOMException && err.name === "AbortError" || err instanceof Error && (err.message.includes("aborted") || err.message.includes("abort"));
|
|
1998
2277
|
}
|
|
@@ -2010,13 +2289,13 @@ function extractToolSummaries(history, historyBefore) {
|
|
|
2010
2289
|
}
|
|
2011
2290
|
function buildResult(response, sessionHistory, interactiveHistory, historyBefore, contextState) {
|
|
2012
2291
|
const toolSummaries = extractToolSummaries(sessionHistory, historyBefore);
|
|
2013
|
-
const
|
|
2292
|
+
const usage = extractTurnUsage(sessionHistory, historyBefore, contextState);
|
|
2014
2293
|
return {
|
|
2015
2294
|
response,
|
|
2016
2295
|
history: interactiveHistory,
|
|
2017
2296
|
toolSummaries,
|
|
2018
2297
|
contextState,
|
|
2019
|
-
...
|
|
2298
|
+
...usage && { usage }
|
|
2020
2299
|
};
|
|
2021
2300
|
}
|
|
2022
2301
|
function buildInterruptedResult(sessionHistory, interactiveHistory, historyBefore, contextState) {
|
|
@@ -2026,22 +2305,22 @@ function buildInterruptedResult(sessionHistory, interactiveHistory, historyBefor
|
|
|
2026
2305
|
const msg = sessionHistory[i];
|
|
2027
2306
|
if (msg?.role === "assistant" && msg.content) parts.push(msg.content);
|
|
2028
2307
|
}
|
|
2029
|
-
const
|
|
2308
|
+
const usage = extractTurnUsage(sessionHistory, historyBefore, contextState);
|
|
2030
2309
|
return {
|
|
2031
2310
|
response: parts.join("\n\n"),
|
|
2032
2311
|
history: interactiveHistory,
|
|
2033
2312
|
toolSummaries,
|
|
2034
2313
|
contextState,
|
|
2035
|
-
...
|
|
2314
|
+
...usage && { usage }
|
|
2036
2315
|
};
|
|
2037
2316
|
}
|
|
2038
|
-
function createUsageSummaryEntry(
|
|
2317
|
+
function createUsageSummaryEntry(usage) {
|
|
2039
2318
|
return {
|
|
2040
2319
|
id: `usage_${(0, import_node_crypto.randomUUID)()}`,
|
|
2041
2320
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2042
2321
|
category: "event",
|
|
2043
2322
|
type: "usage-summary",
|
|
2044
|
-
data:
|
|
2323
|
+
data: usage
|
|
2045
2324
|
};
|
|
2046
2325
|
}
|
|
2047
2326
|
function extractTurnUsage(sessionHistory, historyBefore, contextState) {
|
|
@@ -2051,11 +2330,11 @@ function extractTurnUsage(sessionHistory, historyBefore, contextState) {
|
|
|
2051
2330
|
let foundUsage = false;
|
|
2052
2331
|
for (const message of turnMessages) {
|
|
2053
2332
|
if (message.role !== "assistant") continue;
|
|
2054
|
-
const
|
|
2055
|
-
if (!
|
|
2333
|
+
const usage = (0, import_agent_core5.collectAssistantUsageMetadata)(message);
|
|
2334
|
+
if (!usage) continue;
|
|
2056
2335
|
foundUsage = true;
|
|
2057
|
-
promptTokens +=
|
|
2058
|
-
completionTokens +=
|
|
2336
|
+
promptTokens += usage.inputTokens;
|
|
2337
|
+
completionTokens += usage.outputTokens;
|
|
2059
2338
|
}
|
|
2060
2339
|
if (!foundUsage) return void 0;
|
|
2061
2340
|
return {
|
|
@@ -2385,6 +2664,7 @@ var MarketplaceSourceSchema = import_zod2.z.object({
|
|
|
2385
2664
|
})
|
|
2386
2665
|
});
|
|
2387
2666
|
var ExtraKnownMarketplacesSchema = import_zod2.z.record(MarketplaceSourceSchema).optional().catch(void 0);
|
|
2667
|
+
var AutoCompactThresholdSchema = import_zod2.z.union([import_zod2.z.number().gt(0).lte(1), import_zod2.z.literal(false)]).optional();
|
|
2388
2668
|
var SettingsSchema = import_zod2.z.object({
|
|
2389
2669
|
/** Trust level used when no --permission-mode flag is given */
|
|
2390
2670
|
defaultTrustLevel: import_zod2.z.enum(["safe", "moderate", "full"]).optional(),
|
|
@@ -2402,7 +2682,9 @@ var SettingsSchema = import_zod2.z.object({
|
|
|
2402
2682
|
/** Plugin enablement map: plugin name -> enabled/disabled */
|
|
2403
2683
|
enabledPlugins: EnabledPluginsSchema,
|
|
2404
2684
|
/** Extra marketplace URLs for BundlePlugin discovery */
|
|
2405
|
-
extraKnownMarketplaces: ExtraKnownMarketplacesSchema
|
|
2685
|
+
extraKnownMarketplaces: ExtraKnownMarketplacesSchema,
|
|
2686
|
+
/** Auto-compact threshold as a 0-1 fraction. Set false to disable automatic compaction. */
|
|
2687
|
+
autoCompactThreshold: AutoCompactThresholdSchema
|
|
2406
2688
|
});
|
|
2407
2689
|
|
|
2408
2690
|
// src/config/config-loader.ts
|
|
@@ -2486,7 +2768,8 @@ function mergeSettings(layers) {
|
|
|
2486
2768
|
},
|
|
2487
2769
|
providers: merged.providers !== void 0 || layer.providers !== void 0 ? mergeProviders(merged.providers, layer.providers) : void 0,
|
|
2488
2770
|
enabledPlugins: merged.enabledPlugins !== void 0 || layer.enabledPlugins !== void 0 ? { ...merged.enabledPlugins ?? {}, ...layer.enabledPlugins ?? {} } : void 0,
|
|
2489
|
-
extraKnownMarketplaces: layer.extraKnownMarketplaces ?? merged.extraKnownMarketplaces
|
|
2771
|
+
extraKnownMarketplaces: layer.extraKnownMarketplaces ?? merged.extraKnownMarketplaces,
|
|
2772
|
+
autoCompactThreshold: layer.autoCompactThreshold ?? merged.autoCompactThreshold
|
|
2490
2773
|
};
|
|
2491
2774
|
}, {});
|
|
2492
2775
|
}
|
|
@@ -2540,7 +2823,8 @@ function toResolvedConfig(merged) {
|
|
|
2540
2823
|
env: merged.env ?? DEFAULTS.env,
|
|
2541
2824
|
hooks: merged.hooks ?? void 0,
|
|
2542
2825
|
enabledPlugins: merged.enabledPlugins ?? void 0,
|
|
2543
|
-
extraKnownMarketplaces: merged.extraKnownMarketplaces ?? void 0
|
|
2826
|
+
extraKnownMarketplaces: merged.extraKnownMarketplaces ?? void 0,
|
|
2827
|
+
autoCompactThreshold: merged.autoCompactThreshold
|
|
2544
2828
|
};
|
|
2545
2829
|
}
|
|
2546
2830
|
function getSettingsPaths(cwd) {
|
|
@@ -2688,7 +2972,7 @@ Respond with JSON: { "ok": boolean, "reason"?: string }`;
|
|
|
2688
2972
|
};
|
|
2689
2973
|
|
|
2690
2974
|
// src/assembly/create-session.ts
|
|
2691
|
-
var
|
|
2975
|
+
var import_agent_sessions3 = require("@robota-sdk/agent-sessions");
|
|
2692
2976
|
|
|
2693
2977
|
// src/context/system-prompt-composer.ts
|
|
2694
2978
|
function renderSection(section) {
|
|
@@ -2870,7 +3154,8 @@ var DEFAULT_TOOL_DESCRIPTIONS = [
|
|
|
2870
3154
|
"Edit \u2014 replace a string in a file",
|
|
2871
3155
|
"Glob \u2014 find files matching a pattern",
|
|
2872
3156
|
"Grep \u2014 search file contents with regex",
|
|
2873
|
-
"
|
|
3157
|
+
"WebFetch \u2014 fetch URL content as text",
|
|
3158
|
+
"WebSearch \u2014 search the internet through the configured local tool"
|
|
2874
3159
|
];
|
|
2875
3160
|
function createDefaultTools() {
|
|
2876
3161
|
return [
|
|
@@ -3036,6 +3321,200 @@ function extractFilePath(parameters) {
|
|
|
3036
3321
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
3037
3322
|
}
|
|
3038
3323
|
|
|
3324
|
+
// src/reversible-execution/reversible-execution-policy.ts
|
|
3325
|
+
var FILE_MUTATION_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit"]);
|
|
3326
|
+
var HOST_SHELL_TOOLS = /* @__PURE__ */ new Set(["Bash", "BackgroundProcess"]);
|
|
3327
|
+
var READ_ONLY_TOOLS = /* @__PURE__ */ new Set(["Read", "Glob", "Grep", "WebFetch", "WebSearch"]);
|
|
3328
|
+
function evaluateReversibleToolSafety(input) {
|
|
3329
|
+
const toolName = input.toolName;
|
|
3330
|
+
if (READ_ONLY_TOOLS.has(toolName)) {
|
|
3331
|
+
return {
|
|
3332
|
+
toolName,
|
|
3333
|
+
reversible: true,
|
|
3334
|
+
sideEffect: "none",
|
|
3335
|
+
rollbackLayer: "none",
|
|
3336
|
+
status: "read-only",
|
|
3337
|
+
message: `${toolName} does not mutate the local workspace.`
|
|
3338
|
+
};
|
|
3339
|
+
}
|
|
3340
|
+
if (FILE_MUTATION_TOOLS.has(toolName)) {
|
|
3341
|
+
if (input.context.checkpointAvailable) {
|
|
3342
|
+
return {
|
|
3343
|
+
toolName,
|
|
3344
|
+
reversible: true,
|
|
3345
|
+
sideEffect: "file-mutation",
|
|
3346
|
+
rollbackLayer: "edit-checkpoint",
|
|
3347
|
+
status: "reversible",
|
|
3348
|
+
message: `${toolName} is reversible through the active edit checkpoint.`
|
|
3349
|
+
};
|
|
3350
|
+
}
|
|
3351
|
+
return {
|
|
3352
|
+
toolName,
|
|
3353
|
+
reversible: false,
|
|
3354
|
+
sideEffect: "file-mutation",
|
|
3355
|
+
rollbackLayer: "none",
|
|
3356
|
+
status: "requires-checkpoint",
|
|
3357
|
+
message: `${toolName} requires an edit checkpoint before file mutation.`
|
|
3358
|
+
};
|
|
3359
|
+
}
|
|
3360
|
+
if (HOST_SHELL_TOOLS.has(toolName)) {
|
|
3361
|
+
return evaluateIsolatedSideEffect(toolName, "shell-process", input.context);
|
|
3362
|
+
}
|
|
3363
|
+
if (toolName === "Agent") {
|
|
3364
|
+
return evaluateAgentSafety(input.toolArgs, input.context);
|
|
3365
|
+
}
|
|
3366
|
+
return {
|
|
3367
|
+
toolName,
|
|
3368
|
+
reversible: false,
|
|
3369
|
+
sideEffect: "unknown",
|
|
3370
|
+
rollbackLayer: "none",
|
|
3371
|
+
status: "unknown",
|
|
3372
|
+
message: `${toolName} has no reversible execution contract.`
|
|
3373
|
+
};
|
|
3374
|
+
}
|
|
3375
|
+
function wrapReversibleExecutionTools(tools, options) {
|
|
3376
|
+
const safetyContext = {
|
|
3377
|
+
checkpointAvailable: options.checkpointAvailable,
|
|
3378
|
+
isolation: options.isolation ?? "none"
|
|
3379
|
+
};
|
|
3380
|
+
const enforceUntrackedSideEffects = options.enforceUntrackedSideEffects ?? true;
|
|
3381
|
+
return tools.map(
|
|
3382
|
+
(tool) => new ReversibleExecutionToolWrapper(tool, {
|
|
3383
|
+
safetyContext,
|
|
3384
|
+
enforceUntrackedSideEffects
|
|
3385
|
+
})
|
|
3386
|
+
);
|
|
3387
|
+
}
|
|
3388
|
+
var ReversibleExecutionToolWrapper = class {
|
|
3389
|
+
constructor(delegate, options) {
|
|
3390
|
+
this.delegate = delegate;
|
|
3391
|
+
this.options = options;
|
|
3392
|
+
this.schema = delegate.schema;
|
|
3393
|
+
}
|
|
3394
|
+
schema;
|
|
3395
|
+
setEventService(eventService) {
|
|
3396
|
+
this.delegate.setEventService(eventService);
|
|
3397
|
+
}
|
|
3398
|
+
async execute(parameters, context) {
|
|
3399
|
+
const report = evaluateReversibleToolSafety({
|
|
3400
|
+
toolName: this.getName(),
|
|
3401
|
+
toolArgs: toToolArgs(parameters),
|
|
3402
|
+
context: this.options.safetyContext
|
|
3403
|
+
});
|
|
3404
|
+
if (!report.reversible && this.options.enforceUntrackedSideEffects) {
|
|
3405
|
+
return createBlockedResult(report);
|
|
3406
|
+
}
|
|
3407
|
+
return this.delegate.execute(parameters, context);
|
|
3408
|
+
}
|
|
3409
|
+
validate(parameters) {
|
|
3410
|
+
return this.delegate.validate(parameters);
|
|
3411
|
+
}
|
|
3412
|
+
validateParameters(parameters) {
|
|
3413
|
+
return this.delegate.validateParameters(parameters);
|
|
3414
|
+
}
|
|
3415
|
+
getDescription() {
|
|
3416
|
+
return this.delegate.getDescription();
|
|
3417
|
+
}
|
|
3418
|
+
getName() {
|
|
3419
|
+
return this.delegate.getName();
|
|
3420
|
+
}
|
|
3421
|
+
};
|
|
3422
|
+
function evaluateIsolatedSideEffect(toolName, sideEffect, context) {
|
|
3423
|
+
if (context.isolation === "worktree") {
|
|
3424
|
+
return {
|
|
3425
|
+
toolName,
|
|
3426
|
+
reversible: true,
|
|
3427
|
+
sideEffect,
|
|
3428
|
+
rollbackLayer: "worktree",
|
|
3429
|
+
status: "reversible",
|
|
3430
|
+
message: `${toolName} side effects are contained in an isolated Git worktree.`
|
|
3431
|
+
};
|
|
3432
|
+
}
|
|
3433
|
+
if (context.isolation === "provider-sandbox") {
|
|
3434
|
+
return {
|
|
3435
|
+
toolName,
|
|
3436
|
+
reversible: true,
|
|
3437
|
+
sideEffect,
|
|
3438
|
+
rollbackLayer: "provider-sandbox",
|
|
3439
|
+
status: "reversible",
|
|
3440
|
+
message: `${toolName} side effects are contained in a provider sandbox snapshot.`
|
|
3441
|
+
};
|
|
3442
|
+
}
|
|
3443
|
+
return {
|
|
3444
|
+
toolName,
|
|
3445
|
+
reversible: false,
|
|
3446
|
+
sideEffect,
|
|
3447
|
+
rollbackLayer: "none",
|
|
3448
|
+
status: "requires-isolation",
|
|
3449
|
+
message: `${toolName} can create host shell side effects that edit checkpoints cannot restore; use worktree or provider sandbox isolation.`
|
|
3450
|
+
};
|
|
3451
|
+
}
|
|
3452
|
+
function evaluateAgentSafety(toolArgs, context) {
|
|
3453
|
+
if (context.isolation === "worktree" || context.isolation === "provider-sandbox") {
|
|
3454
|
+
return evaluateIsolatedSideEffect("Agent", "subagent", context);
|
|
3455
|
+
}
|
|
3456
|
+
if (agentRequestUsesWorktree(toolArgs)) {
|
|
3457
|
+
return {
|
|
3458
|
+
toolName: "Agent",
|
|
3459
|
+
reversible: true,
|
|
3460
|
+
sideEffect: "subagent",
|
|
3461
|
+
rollbackLayer: "worktree",
|
|
3462
|
+
status: "reversible",
|
|
3463
|
+
message: "Agent jobs request worktree isolation, so shell side effects stay outside the parent workspace."
|
|
3464
|
+
};
|
|
3465
|
+
}
|
|
3466
|
+
return {
|
|
3467
|
+
toolName: "Agent",
|
|
3468
|
+
reversible: false,
|
|
3469
|
+
sideEffect: "subagent",
|
|
3470
|
+
rollbackLayer: "none",
|
|
3471
|
+
status: "requires-isolation",
|
|
3472
|
+
message: "Agent jobs must request worktree isolation to be reversible in local-first mode."
|
|
3473
|
+
};
|
|
3474
|
+
}
|
|
3475
|
+
function agentRequestUsesWorktree(toolArgs) {
|
|
3476
|
+
if (!toolArgs) return false;
|
|
3477
|
+
const jobs = toolArgs.jobs;
|
|
3478
|
+
if (Array.isArray(jobs)) {
|
|
3479
|
+
return jobs.length > 0 && jobs.every((job) => {
|
|
3480
|
+
if (!isToolArgRecord(job)) return false;
|
|
3481
|
+
return readIsolation(job) === "worktree";
|
|
3482
|
+
});
|
|
3483
|
+
}
|
|
3484
|
+
return readIsolation(toolArgs) === "worktree";
|
|
3485
|
+
}
|
|
3486
|
+
function readIsolation(value) {
|
|
3487
|
+
const isolation = value["isolation"];
|
|
3488
|
+
return typeof isolation === "string" ? isolation : void 0;
|
|
3489
|
+
}
|
|
3490
|
+
function isToolArgRecord(value) {
|
|
3491
|
+
return value !== void 0 && typeof value === "object" && !Array.isArray(value);
|
|
3492
|
+
}
|
|
3493
|
+
function toToolArgs(parameters) {
|
|
3494
|
+
if (!parameters || typeof parameters !== "object" || Array.isArray(parameters)) return void 0;
|
|
3495
|
+
return parameters;
|
|
3496
|
+
}
|
|
3497
|
+
function createBlockedResult(report) {
|
|
3498
|
+
return {
|
|
3499
|
+
success: true,
|
|
3500
|
+
data: {
|
|
3501
|
+
success: false,
|
|
3502
|
+
output: "",
|
|
3503
|
+
error: report.message,
|
|
3504
|
+
reversibleSafety: {
|
|
3505
|
+
toolName: report.toolName,
|
|
3506
|
+
sideEffect: report.sideEffect,
|
|
3507
|
+
rollbackLayer: report.rollbackLayer,
|
|
3508
|
+
status: report.status
|
|
3509
|
+
}
|
|
3510
|
+
},
|
|
3511
|
+
metadata: {
|
|
3512
|
+
reversibleSafetyStatus: report.status,
|
|
3513
|
+
rollbackLayer: report.rollbackLayer
|
|
3514
|
+
}
|
|
3515
|
+
};
|
|
3516
|
+
}
|
|
3517
|
+
|
|
3039
3518
|
// src/assembly/create-session.ts
|
|
3040
3519
|
var import_agent_runtime6 = require("@robota-sdk/agent-runtime");
|
|
3041
3520
|
|
|
@@ -3155,7 +3634,7 @@ var AgentDefinitionLoader = class {
|
|
|
3155
3634
|
};
|
|
3156
3635
|
|
|
3157
3636
|
// src/assembly/background-task-hooks.ts
|
|
3158
|
-
var
|
|
3637
|
+
var import_agent_core6 = require("@robota-sdk/agent-core");
|
|
3159
3638
|
function getSubagentHookEvent(event) {
|
|
3160
3639
|
if (event.type === "background_task_started" && event.task.kind === "agent") {
|
|
3161
3640
|
return "SubagentStart";
|
|
@@ -3190,7 +3669,7 @@ function fireSubagentLifecycleHook(event, cwd, hooks, hookTypeExecutors) {
|
|
|
3190
3669
|
ROBOTA_AGENT_TYPE: event.task.agentType ?? event.task.label
|
|
3191
3670
|
}
|
|
3192
3671
|
};
|
|
3193
|
-
void (0,
|
|
3672
|
+
void (0, import_agent_core6.runHooks)(hooks, hookEventName, input, hookTypeExecutors).catch(() => void 0);
|
|
3194
3673
|
}
|
|
3195
3674
|
|
|
3196
3675
|
// src/assembly/create-session.ts
|
|
@@ -3207,7 +3686,11 @@ function createSession(options) {
|
|
|
3207
3686
|
const cwd = options.cwd ?? process.cwd();
|
|
3208
3687
|
const sessionId = options.sessionId ?? createSessionId();
|
|
3209
3688
|
const defaultTools = options.editCheckpointRecorder ? wrapEditCheckpointTools(createDefaultTools(), options.editCheckpointRecorder) : createDefaultTools();
|
|
3210
|
-
const
|
|
3689
|
+
const assembledTools = [...defaultTools, ...options.additionalTools ?? []];
|
|
3690
|
+
const tools = options.reversibleExecution ? wrapReversibleExecutionTools(assembledTools, {
|
|
3691
|
+
...options.reversibleExecution,
|
|
3692
|
+
checkpointAvailable: options.editCheckpointRecorder !== void 0
|
|
3693
|
+
}) : assembledTools;
|
|
3211
3694
|
if (options.modelCommandExecutor && options.isModelCommandInvocable) {
|
|
3212
3695
|
tools.push(
|
|
3213
3696
|
createCommandExecutionTool({
|
|
@@ -3346,7 +3829,8 @@ ${options.appendSystemPrompt}` : systemMessage;
|
|
|
3346
3829
|
allow: [...defaultAllow, ...options.config.permissions.allow ?? [], ...allowedToolPatterns],
|
|
3347
3830
|
deny: options.config.permissions.deny ?? []
|
|
3348
3831
|
};
|
|
3349
|
-
const
|
|
3832
|
+
const SessionWithAutoCompact = import_agent_sessions3.Session;
|
|
3833
|
+
const session = new SessionWithAutoCompact({
|
|
3350
3834
|
tools,
|
|
3351
3835
|
provider,
|
|
3352
3836
|
systemMessage: finalSystemMessage,
|
|
@@ -3366,7 +3850,9 @@ ${options.appendSystemPrompt}` : systemMessage;
|
|
|
3366
3850
|
onToolExecution: options.onToolExecution,
|
|
3367
3851
|
promptForApproval: options.promptForApproval,
|
|
3368
3852
|
onCompact: options.onCompact,
|
|
3853
|
+
onCompactEvent: options.onCompactEvent,
|
|
3369
3854
|
compactInstructions: options.compactInstructions ?? options.context.compactInstructions,
|
|
3855
|
+
autoCompactThreshold: options.autoCompactThreshold ?? options.config.autoCompactThreshold,
|
|
3370
3856
|
sessionLogger: options.sessionLogger,
|
|
3371
3857
|
hookTypeExecutors: hookTypeExecutors.length > 0 ? hookTypeExecutors : void 0
|
|
3372
3858
|
});
|
|
@@ -3389,18 +3875,18 @@ function logBackgroundTaskEvent(logger, sessionId, event) {
|
|
|
3389
3875
|
// src/assembly/subagent-logger.ts
|
|
3390
3876
|
var import_node_fs5 = require("fs");
|
|
3391
3877
|
var import_node_path4 = require("path");
|
|
3392
|
-
var
|
|
3878
|
+
var import_agent_sessions4 = require("@robota-sdk/agent-sessions");
|
|
3393
3879
|
function createSubagentLogger(parentSessionId, _agentId, baseLogsDir) {
|
|
3394
3880
|
const subagentDir = (0, import_node_path4.join)(baseLogsDir, parentSessionId, "subagents");
|
|
3395
3881
|
(0, import_node_fs5.mkdirSync)(subagentDir, { recursive: true });
|
|
3396
|
-
return new
|
|
3882
|
+
return new import_agent_sessions4.FileSessionLogger(subagentDir);
|
|
3397
3883
|
}
|
|
3398
3884
|
function resolveSubagentLogDir(parentSessionId, baseLogsDir) {
|
|
3399
3885
|
return (0, import_node_path4.join)(baseLogsDir, parentSessionId, "subagents");
|
|
3400
3886
|
}
|
|
3401
3887
|
|
|
3402
3888
|
// src/interactive/interactive-session-init.ts
|
|
3403
|
-
var
|
|
3889
|
+
var import_agent_sessions5 = require("@robota-sdk/agent-sessions");
|
|
3404
3890
|
|
|
3405
3891
|
// src/paths.ts
|
|
3406
3892
|
var import_node_path5 = require("path");
|
|
@@ -4617,11 +5103,12 @@ async function createInteractiveSession(options) {
|
|
|
4617
5103
|
permissionMode: options.permissionMode,
|
|
4618
5104
|
maxTurns: options.maxTurns,
|
|
4619
5105
|
terminal: NOOP_TERMINAL,
|
|
4620
|
-
sessionLogger: new
|
|
5106
|
+
sessionLogger: new import_agent_sessions5.FileSessionLogger(paths.logs),
|
|
4621
5107
|
permissionHandler: options.permissionHandler,
|
|
4622
5108
|
provider: options.provider,
|
|
4623
5109
|
onTextDelta: options.onTextDelta,
|
|
4624
5110
|
onContextUpdate: options.onContextUpdate,
|
|
5111
|
+
onCompactEvent: options.onCompactEvent,
|
|
4625
5112
|
onToolExecution: options.onToolExecution,
|
|
4626
5113
|
sessionId,
|
|
4627
5114
|
allowedTools: options.allowedTools,
|
|
@@ -4639,7 +5126,8 @@ async function createInteractiveSession(options) {
|
|
|
4639
5126
|
} : {},
|
|
4640
5127
|
modelCommandExecutor: options.modelCommandExecutor,
|
|
4641
5128
|
isModelCommandInvocable: options.isModelCommandInvocable,
|
|
4642
|
-
editCheckpointRecorder: options.editCheckpointRecorder
|
|
5129
|
+
editCheckpointRecorder: options.editCheckpointRecorder,
|
|
5130
|
+
reversibleExecution: options.reversibleExecution
|
|
4643
5131
|
});
|
|
4644
5132
|
}
|
|
4645
5133
|
function injectSavedMessage(session, msg) {
|
|
@@ -4736,8 +5224,60 @@ function isRestoredTerminalStatus(status) {
|
|
|
4736
5224
|
|
|
4737
5225
|
// src/checkpoints/edit-checkpoint-store.ts
|
|
4738
5226
|
var import_promises = require("fs/promises");
|
|
5227
|
+
var import_node_fs14 = require("fs");
|
|
5228
|
+
var import_node_path15 = require("path");
|
|
5229
|
+
|
|
5230
|
+
// src/checkpoints/edit-checkpoint-inspection.ts
|
|
4739
5231
|
var import_node_fs13 = require("fs");
|
|
4740
5232
|
var import_node_path14 = require("path");
|
|
5233
|
+
function buildEditCheckpointInspection(input) {
|
|
5234
|
+
const later = input.manifests.filter((manifest) => manifest.sequence > input.target.sequence);
|
|
5235
|
+
const rollbackRange = input.manifests.filter(
|
|
5236
|
+
(manifest) => manifest.sequence >= input.target.sequence
|
|
5237
|
+
);
|
|
5238
|
+
return {
|
|
5239
|
+
target: toSummary(input.target),
|
|
5240
|
+
capturedFiles: input.target.files.map((file) => {
|
|
5241
|
+
const snapshotPath = file.snapshotFile ? (0, import_node_path14.join)(input.checkpointDir(input.sessionId, input.target.id), file.snapshotFile) : void 0;
|
|
5242
|
+
const snapshotStats = snapshotPath ? statSafe(snapshotPath) : void 0;
|
|
5243
|
+
return {
|
|
5244
|
+
originalPath: file.originalPath,
|
|
5245
|
+
relativePath: (0, import_node_path14.relative)(input.cwd, file.originalPath),
|
|
5246
|
+
existed: file.existed,
|
|
5247
|
+
restoreAction: file.existed ? "restore-preimage" : "delete-created-file",
|
|
5248
|
+
snapshotAvailable: file.existed ? snapshotStats !== void 0 : false,
|
|
5249
|
+
...snapshotStats ? { snapshotSizeBytes: snapshotStats.size } : {}
|
|
5250
|
+
};
|
|
5251
|
+
}),
|
|
5252
|
+
restoreToCheckpoint: toInspectionPlan(later),
|
|
5253
|
+
rollbackThroughCheckpoint: toInspectionPlan(rollbackRange)
|
|
5254
|
+
};
|
|
5255
|
+
}
|
|
5256
|
+
function toSummary(manifest) {
|
|
5257
|
+
return {
|
|
5258
|
+
id: manifest.id,
|
|
5259
|
+
sessionId: manifest.sessionId,
|
|
5260
|
+
sequence: manifest.sequence,
|
|
5261
|
+
prompt: manifest.prompt,
|
|
5262
|
+
createdAt: manifest.createdAt,
|
|
5263
|
+
fileCount: manifest.fileCount
|
|
5264
|
+
};
|
|
5265
|
+
}
|
|
5266
|
+
function toInspectionPlan(manifests) {
|
|
5267
|
+
return {
|
|
5268
|
+
checkpointIds: manifests.map((manifest) => manifest.id),
|
|
5269
|
+
fileCount: manifests.reduce((count, manifest) => count + manifest.fileCount, 0)
|
|
5270
|
+
};
|
|
5271
|
+
}
|
|
5272
|
+
function statSafe(path) {
|
|
5273
|
+
try {
|
|
5274
|
+
return (0, import_node_fs13.statSync)(path);
|
|
5275
|
+
} catch {
|
|
5276
|
+
return void 0;
|
|
5277
|
+
}
|
|
5278
|
+
}
|
|
5279
|
+
|
|
5280
|
+
// src/checkpoints/edit-checkpoint-store.ts
|
|
4741
5281
|
var MANIFEST_FILE = "manifest.json";
|
|
4742
5282
|
var SNAPSHOT_DIR = "files";
|
|
4743
5283
|
var ID_PAD = 4;
|
|
@@ -4748,7 +5288,7 @@ var EditCheckpointStore = class {
|
|
|
4748
5288
|
now;
|
|
4749
5289
|
activeTurn = null;
|
|
4750
5290
|
constructor(options) {
|
|
4751
|
-
this.cwd = (0,
|
|
5291
|
+
this.cwd = (0, import_node_path15.resolve)(options.cwd);
|
|
4752
5292
|
this.rootDir = projectPaths(this.cwd).checkpoints;
|
|
4753
5293
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
4754
5294
|
}
|
|
@@ -4758,8 +5298,8 @@ var EditCheckpointStore = class {
|
|
|
4758
5298
|
}
|
|
4759
5299
|
const nextSequence = this.nextSequence(input.sessionId);
|
|
4760
5300
|
const id = `turn-${String(nextSequence).padStart(ID_PAD, "0")}`;
|
|
4761
|
-
const dir = (0,
|
|
4762
|
-
await (0, import_promises.mkdir)((0,
|
|
5301
|
+
const dir = (0, import_node_path15.join)(this.sessionDir(input.sessionId), id);
|
|
5302
|
+
await (0, import_promises.mkdir)((0, import_node_path15.join)(dir, SNAPSHOT_DIR), { recursive: true });
|
|
4763
5303
|
const manifest = {
|
|
4764
5304
|
version: 1,
|
|
4765
5305
|
id,
|
|
@@ -4775,11 +5315,11 @@ var EditCheckpointStore = class {
|
|
|
4775
5315
|
dir,
|
|
4776
5316
|
capturedPaths: /* @__PURE__ */ new Set()
|
|
4777
5317
|
};
|
|
4778
|
-
return
|
|
5318
|
+
return toSummary2(manifest);
|
|
4779
5319
|
}
|
|
4780
5320
|
async captureFile(filePath) {
|
|
4781
5321
|
if (!this.activeTurn) return;
|
|
4782
|
-
const originalPath = (0,
|
|
5322
|
+
const originalPath = (0, import_node_path15.resolve)(this.cwd, filePath);
|
|
4783
5323
|
if (this.activeTurn.capturedPaths.has(originalPath)) return;
|
|
4784
5324
|
if (isInside(this.rootDir, originalPath)) return;
|
|
4785
5325
|
const record = await this.createFileRecord(originalPath, this.activeTurn);
|
|
@@ -4792,10 +5332,24 @@ var EditCheckpointStore = class {
|
|
|
4792
5332
|
const active = this.activeTurn;
|
|
4793
5333
|
this.activeTurn = null;
|
|
4794
5334
|
await this.writeManifest(active.dir, active.manifest);
|
|
4795
|
-
return
|
|
5335
|
+
return toSummary2(active.manifest);
|
|
4796
5336
|
}
|
|
4797
5337
|
list(sessionId) {
|
|
4798
|
-
return this.loadManifests(sessionId).map(
|
|
5338
|
+
return this.loadManifests(sessionId).map(toSummary2);
|
|
5339
|
+
}
|
|
5340
|
+
inspect(sessionId, checkpointId) {
|
|
5341
|
+
const manifests = this.loadManifests(sessionId);
|
|
5342
|
+
const target = manifests.find((manifest) => manifest.id === checkpointId);
|
|
5343
|
+
if (!target) {
|
|
5344
|
+
throw new Error(`Unknown edit checkpoint: ${checkpointId}`);
|
|
5345
|
+
}
|
|
5346
|
+
return buildEditCheckpointInspection({
|
|
5347
|
+
cwd: this.cwd,
|
|
5348
|
+
sessionId,
|
|
5349
|
+
target,
|
|
5350
|
+
manifests,
|
|
5351
|
+
checkpointDir: (inputSessionId, inputCheckpointId) => this.checkpointDir(inputSessionId, inputCheckpointId)
|
|
5352
|
+
});
|
|
4799
5353
|
}
|
|
4800
5354
|
async restoreToCheckpoint(sessionId, checkpointId) {
|
|
4801
5355
|
const manifests = this.loadManifests(sessionId);
|
|
@@ -4815,12 +5369,36 @@ var EditCheckpointStore = class {
|
|
|
4815
5369
|
await (0, import_promises.rm)(this.checkpointDir(sessionId, manifest.id), { recursive: true, force: true });
|
|
4816
5370
|
}
|
|
4817
5371
|
return {
|
|
4818
|
-
target:
|
|
5372
|
+
target: toSummary2(target),
|
|
4819
5373
|
restoredCheckpointCount: later.length,
|
|
4820
5374
|
restoredFileCount,
|
|
4821
5375
|
removedCheckpointCount: later.length
|
|
4822
5376
|
};
|
|
4823
5377
|
}
|
|
5378
|
+
async rollbackThroughCheckpoint(sessionId, checkpointId) {
|
|
5379
|
+
const manifests = this.loadManifests(sessionId);
|
|
5380
|
+
const target = manifests.find((manifest) => manifest.id === checkpointId);
|
|
5381
|
+
if (!target) {
|
|
5382
|
+
throw new Error(`Unknown edit checkpoint: ${checkpointId}`);
|
|
5383
|
+
}
|
|
5384
|
+
const rollbackRange = manifests.filter((manifest) => manifest.sequence >= target.sequence).sort((a, b) => b.sequence - a.sequence);
|
|
5385
|
+
let restoredFileCount = 0;
|
|
5386
|
+
for (const manifest of rollbackRange) {
|
|
5387
|
+
for (const file of manifest.files) {
|
|
5388
|
+
await this.restoreFile(sessionId, manifest.id, file);
|
|
5389
|
+
restoredFileCount += 1;
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5392
|
+
for (const manifest of rollbackRange) {
|
|
5393
|
+
await (0, import_promises.rm)(this.checkpointDir(sessionId, manifest.id), { recursive: true, force: true });
|
|
5394
|
+
}
|
|
5395
|
+
return {
|
|
5396
|
+
target: toSummary2(target),
|
|
5397
|
+
restoredCheckpointCount: rollbackRange.length,
|
|
5398
|
+
restoredFileCount,
|
|
5399
|
+
removedCheckpointCount: rollbackRange.length
|
|
5400
|
+
};
|
|
5401
|
+
}
|
|
4824
5402
|
async createFileRecord(originalPath, active) {
|
|
4825
5403
|
const existed = await pathExists(originalPath);
|
|
4826
5404
|
if (!existed) {
|
|
@@ -4829,11 +5407,11 @@ var EditCheckpointStore = class {
|
|
|
4829
5407
|
existed: false
|
|
4830
5408
|
};
|
|
4831
5409
|
}
|
|
4832
|
-
const snapshotFile = (0,
|
|
5410
|
+
const snapshotFile = (0, import_node_path15.join)(
|
|
4833
5411
|
SNAPSHOT_DIR,
|
|
4834
5412
|
`${String(active.manifest.files.length + 1).padStart(SNAPSHOT_PAD, "0")}.content`
|
|
4835
5413
|
);
|
|
4836
|
-
await (0, import_promises.copyFile)(originalPath, (0,
|
|
5414
|
+
await (0, import_promises.copyFile)(originalPath, (0, import_node_path15.join)(active.dir, snapshotFile));
|
|
4837
5415
|
return {
|
|
4838
5416
|
originalPath,
|
|
4839
5417
|
existed: true,
|
|
@@ -4848,15 +5426,15 @@ var EditCheckpointStore = class {
|
|
|
4848
5426
|
if (!record.snapshotFile) {
|
|
4849
5427
|
throw new Error(`Checkpoint file record is missing a snapshot: ${record.originalPath}`);
|
|
4850
5428
|
}
|
|
4851
|
-
await (0, import_promises.mkdir)((0,
|
|
5429
|
+
await (0, import_promises.mkdir)((0, import_node_path15.dirname)(record.originalPath), { recursive: true });
|
|
4852
5430
|
await (0, import_promises.copyFile)(
|
|
4853
|
-
(0,
|
|
5431
|
+
(0, import_node_path15.join)(this.checkpointDir(sessionId, checkpointId), record.snapshotFile),
|
|
4854
5432
|
record.originalPath
|
|
4855
5433
|
);
|
|
4856
5434
|
}
|
|
4857
5435
|
loadManifests(sessionId) {
|
|
4858
5436
|
const dir = this.sessionDir(sessionId);
|
|
4859
|
-
return readDirSyncSafe(dir).map((entry) => (0,
|
|
5437
|
+
return readDirSyncSafe(dir).map((entry) => (0, import_node_path15.join)(dir, entry, MANIFEST_FILE)).map((manifestPath) => readJsonManifest(manifestPath)).filter((manifest) => manifest !== void 0).sort((a, b) => a.sequence - b.sequence);
|
|
4860
5438
|
}
|
|
4861
5439
|
nextSequence(sessionId) {
|
|
4862
5440
|
const last = this.list(sessionId).at(-1);
|
|
@@ -4864,19 +5442,19 @@ var EditCheckpointStore = class {
|
|
|
4864
5442
|
}
|
|
4865
5443
|
async writeManifest(dir, manifest) {
|
|
4866
5444
|
await (0, import_promises.mkdir)(dir, { recursive: true });
|
|
4867
|
-
const path = (0,
|
|
5445
|
+
const path = (0, import_node_path15.join)(dir, MANIFEST_FILE);
|
|
4868
5446
|
const tmp = `${path}.tmp`;
|
|
4869
5447
|
await (0, import_promises.writeFile)(tmp, JSON.stringify(manifest, null, 2), "utf8");
|
|
4870
5448
|
await (0, import_promises.rename)(tmp, path);
|
|
4871
5449
|
}
|
|
4872
5450
|
sessionDir(sessionId) {
|
|
4873
|
-
return (0,
|
|
5451
|
+
return (0, import_node_path15.join)(this.rootDir, safePathSegment(sessionId));
|
|
4874
5452
|
}
|
|
4875
5453
|
checkpointDir(sessionId, checkpointId) {
|
|
4876
|
-
return (0,
|
|
5454
|
+
return (0, import_node_path15.join)(this.sessionDir(sessionId), safePathSegment(checkpointId));
|
|
4877
5455
|
}
|
|
4878
5456
|
};
|
|
4879
|
-
function
|
|
5457
|
+
function toSummary2(manifest) {
|
|
4880
5458
|
return {
|
|
4881
5459
|
id: manifest.id,
|
|
4882
5460
|
sessionId: manifest.sessionId,
|
|
@@ -4890,12 +5468,12 @@ function safePathSegment(value) {
|
|
|
4890
5468
|
return value.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
4891
5469
|
}
|
|
4892
5470
|
function isInside(parent, child) {
|
|
4893
|
-
const rel = (0,
|
|
5471
|
+
const rel = (0, import_node_path15.relative)(parent, child);
|
|
4894
5472
|
return rel.length === 0 || !rel.startsWith("..") && !rel.startsWith("/");
|
|
4895
5473
|
}
|
|
4896
5474
|
async function pathExists(path) {
|
|
4897
5475
|
try {
|
|
4898
|
-
await (0, import_promises.access)(path,
|
|
5476
|
+
await (0, import_promises.access)(path, import_node_fs14.constants.F_OK);
|
|
4899
5477
|
return true;
|
|
4900
5478
|
} catch {
|
|
4901
5479
|
return false;
|
|
@@ -4903,14 +5481,14 @@ async function pathExists(path) {
|
|
|
4903
5481
|
}
|
|
4904
5482
|
function readDirSyncSafe(dir) {
|
|
4905
5483
|
try {
|
|
4906
|
-
return (0,
|
|
5484
|
+
return (0, import_node_fs14.readdirSync)(dir);
|
|
4907
5485
|
} catch {
|
|
4908
5486
|
return [];
|
|
4909
5487
|
}
|
|
4910
5488
|
}
|
|
4911
5489
|
function readJsonManifest(path) {
|
|
4912
5490
|
try {
|
|
4913
|
-
const raw = (0,
|
|
5491
|
+
const raw = (0, import_node_fs14.readFileSync)(path, "utf8");
|
|
4914
5492
|
return JSON.parse(raw);
|
|
4915
5493
|
} catch {
|
|
4916
5494
|
return void 0;
|
|
@@ -4949,14 +5527,19 @@ var InteractiveSession = class {
|
|
|
4949
5527
|
backgroundJobUnsubscribe = null;
|
|
4950
5528
|
backgroundJobOrchestrator = null;
|
|
4951
5529
|
commandModules;
|
|
5530
|
+
commandHostAdapters;
|
|
5531
|
+
autoCompactThresholdSource = "default";
|
|
4952
5532
|
shuttingDown = false;
|
|
4953
5533
|
shutdownPromise = null;
|
|
4954
5534
|
constructor(options) {
|
|
4955
|
-
|
|
4956
|
-
this.
|
|
4957
|
-
|
|
4958
|
-
...
|
|
4959
|
-
]
|
|
5535
|
+
const sdkBuiltinModule = createBuiltinCommandModule();
|
|
5536
|
+
this.commandModules = [
|
|
5537
|
+
sdkBuiltinModule,
|
|
5538
|
+
..."commandModules" in options ? options.commandModules ?? [] : []
|
|
5539
|
+
];
|
|
5540
|
+
this.commandExecutor = new SystemCommandExecutor(
|
|
5541
|
+
this.commandModules.flatMap((module2) => module2.systemCommands ?? [])
|
|
5542
|
+
);
|
|
4960
5543
|
this.sessionStore = options.sessionStore;
|
|
4961
5544
|
this.sessionName = options.sessionName;
|
|
4962
5545
|
this.cwd = ("cwd" in options ? options.cwd : void 0) ?? "";
|
|
@@ -4965,8 +5548,10 @@ var InteractiveSession = class {
|
|
|
4965
5548
|
}
|
|
4966
5549
|
this.resumeSessionId = options.resumeSessionId;
|
|
4967
5550
|
this.forkSession = options.forkSession ?? false;
|
|
5551
|
+
this.commandHostAdapters = "commandHostAdapters" in options ? options.commandHostAdapters : void 0;
|
|
4968
5552
|
if ("session" in options && options.session) {
|
|
4969
5553
|
this.session = options.session;
|
|
5554
|
+
this.autoCompactThresholdSource = "session";
|
|
4970
5555
|
this.initialized = true;
|
|
4971
5556
|
} else {
|
|
4972
5557
|
const stdOpts = options;
|
|
@@ -4993,7 +5578,8 @@ var InteractiveSession = class {
|
|
|
4993
5578
|
if (this.initialized) this.persistCurrentSession();
|
|
4994
5579
|
}
|
|
4995
5580
|
async initializeAsync(options) {
|
|
4996
|
-
const config = await loadConfig(options.cwd);
|
|
5581
|
+
const config = options.config ?? await loadConfig(options.cwd);
|
|
5582
|
+
this.autoCompactThresholdSource = config.autoCompactThreshold === void 0 ? "default" : "settings";
|
|
4997
5583
|
this.editCheckpointStore = new EditCheckpointStore({ cwd: options.cwd });
|
|
4998
5584
|
this.session = await createInteractiveSession({
|
|
4999
5585
|
cwd: options.cwd,
|
|
@@ -5006,6 +5592,7 @@ var InteractiveSession = class {
|
|
|
5006
5592
|
forkSession: this.forkSession,
|
|
5007
5593
|
onTextDelta: (delta) => this.handleTextDelta(delta),
|
|
5008
5594
|
onContextUpdate: (state) => this.emit("context_update", state),
|
|
5595
|
+
onCompactEvent: (event) => this.handleCompactEvent(event),
|
|
5009
5596
|
onToolExecution: (event) => this.handleToolExecution(event),
|
|
5010
5597
|
bare: options.bare,
|
|
5011
5598
|
allowedTools: options.allowedTools,
|
|
@@ -5014,6 +5601,7 @@ var InteractiveSession = class {
|
|
|
5014
5601
|
subagentRunnerFactory: options.subagentRunnerFactory,
|
|
5015
5602
|
...options.commandModules ? { commandModules: options.commandModules } : {},
|
|
5016
5603
|
editCheckpointRecorder: this.editCheckpointStore,
|
|
5604
|
+
...options.reversibleExecution ? { reversibleExecution: options.reversibleExecution } : {},
|
|
5017
5605
|
commandDescriptors: this.commandExecutor.listModelInvocableCommands(),
|
|
5018
5606
|
...this.commandExecutor.listModelInvocableCommands().length > 0 ? {
|
|
5019
5607
|
modelCommandExecutor: (command, args) => this.executeModelCommand(command, args),
|
|
@@ -5060,7 +5648,18 @@ var InteractiveSession = class {
|
|
|
5060
5648
|
}
|
|
5061
5649
|
async executeCommand(name, args) {
|
|
5062
5650
|
await this.ensureInitialized();
|
|
5063
|
-
|
|
5651
|
+
const command = this.commandExecutor.getCommand(name);
|
|
5652
|
+
if (!command) return null;
|
|
5653
|
+
if (this.executing) {
|
|
5654
|
+
return {
|
|
5655
|
+
success: false,
|
|
5656
|
+
message: "Another prompt or command is already running. Wait for it to finish."
|
|
5657
|
+
};
|
|
5658
|
+
}
|
|
5659
|
+
if (command.lifecycle === "blocking") {
|
|
5660
|
+
return this.executeForegroundCommand(command, args);
|
|
5661
|
+
}
|
|
5662
|
+
return this.commandExecutor.executeCommand(command, this, args);
|
|
5064
5663
|
}
|
|
5065
5664
|
async executeModelCommand(name, args) {
|
|
5066
5665
|
await this.ensureInitialized();
|
|
@@ -5153,6 +5752,30 @@ var InteractiveSession = class {
|
|
|
5153
5752
|
getContextState() {
|
|
5154
5753
|
return this.getSessionOrThrow().getContextState();
|
|
5155
5754
|
}
|
|
5755
|
+
getAutoCompactThreshold() {
|
|
5756
|
+
return this.getSessionOrThrow().getAutoCompactThreshold();
|
|
5757
|
+
}
|
|
5758
|
+
getAutoCompactThresholdSource() {
|
|
5759
|
+
return this.autoCompactThresholdSource;
|
|
5760
|
+
}
|
|
5761
|
+
setAutoCompactThreshold(threshold, source = "session") {
|
|
5762
|
+
this.getSessionOrThrow().setAutoCompactThreshold(threshold);
|
|
5763
|
+
this.autoCompactThresholdSource = source;
|
|
5764
|
+
this.emit("context_update", this.getContextState());
|
|
5765
|
+
this.persistCurrentSession();
|
|
5766
|
+
}
|
|
5767
|
+
getCommandHostAdapters() {
|
|
5768
|
+
return this.commandHostAdapters ?? {};
|
|
5769
|
+
}
|
|
5770
|
+
clearConversationHistory() {
|
|
5771
|
+
this.getSessionOrThrow().clearHistory();
|
|
5772
|
+
this.history = [];
|
|
5773
|
+
this.persistCurrentSession();
|
|
5774
|
+
this.emit("context_update", this.getContextState());
|
|
5775
|
+
}
|
|
5776
|
+
async compactContext(instructions) {
|
|
5777
|
+
await this.getSessionOrThrow().compact(instructions);
|
|
5778
|
+
}
|
|
5156
5779
|
getName() {
|
|
5157
5780
|
return this.sessionName;
|
|
5158
5781
|
}
|
|
@@ -5166,6 +5789,10 @@ var InteractiveSession = class {
|
|
|
5166
5789
|
const sessionId = this.getSessionOrThrow().getSessionId();
|
|
5167
5790
|
return this.getEditCheckpointStore().list(sessionId);
|
|
5168
5791
|
}
|
|
5792
|
+
inspectEditCheckpoint(checkpointId) {
|
|
5793
|
+
const sessionId = this.getSessionOrThrow().getSessionId();
|
|
5794
|
+
return this.getEditCheckpointStore().inspect(sessionId, checkpointId);
|
|
5795
|
+
}
|
|
5169
5796
|
async restoreEditCheckpoint(checkpointId) {
|
|
5170
5797
|
await this.ensureInitialized();
|
|
5171
5798
|
if (this.executing) {
|
|
@@ -5176,7 +5803,22 @@ var InteractiveSession = class {
|
|
|
5176
5803
|
checkpointId
|
|
5177
5804
|
);
|
|
5178
5805
|
this.history.push(
|
|
5179
|
-
(0,
|
|
5806
|
+
(0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createSystemMessage)(`Restored edit checkpoint: ${checkpointId}`))
|
|
5807
|
+
);
|
|
5808
|
+
this.persistCurrentSession();
|
|
5809
|
+
return result;
|
|
5810
|
+
}
|
|
5811
|
+
async rollbackEditCheckpoint(checkpointId) {
|
|
5812
|
+
await this.ensureInitialized();
|
|
5813
|
+
if (this.executing) {
|
|
5814
|
+
throw new Error("Cannot rollback edit checkpoint while a prompt is running.");
|
|
5815
|
+
}
|
|
5816
|
+
const result = await this.getEditCheckpointStore().rollbackThroughCheckpoint(
|
|
5817
|
+
this.getSessionOrThrow().getSessionId(),
|
|
5818
|
+
checkpointId
|
|
5819
|
+
);
|
|
5820
|
+
this.history.push(
|
|
5821
|
+
(0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createSystemMessage)(`Rolled back edit checkpoint: ${checkpointId}`))
|
|
5180
5822
|
);
|
|
5181
5823
|
this.persistCurrentSession();
|
|
5182
5824
|
return result;
|
|
@@ -5421,7 +6063,7 @@ var InteractiveSession = class {
|
|
|
5421
6063
|
this.executing = true;
|
|
5422
6064
|
this.clearStreaming();
|
|
5423
6065
|
this.emit("thinking", true);
|
|
5424
|
-
this.history.push((0,
|
|
6066
|
+
this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createUserMessage)(displayInput)));
|
|
5425
6067
|
}
|
|
5426
6068
|
finishForkSkillExecution() {
|
|
5427
6069
|
this.executing = false;
|
|
@@ -5436,7 +6078,7 @@ var InteractiveSession = class {
|
|
|
5436
6078
|
}
|
|
5437
6079
|
}
|
|
5438
6080
|
recordForkSkillError(err) {
|
|
5439
|
-
this.history.push((0,
|
|
6081
|
+
this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createSystemMessage)(`Error: ${err.message}`)));
|
|
5440
6082
|
this.emit("error", err);
|
|
5441
6083
|
}
|
|
5442
6084
|
resolveForkAgentDefinition(agentType, options) {
|
|
@@ -5485,15 +6127,42 @@ var InteractiveSession = class {
|
|
|
5485
6127
|
toolSummaries: [],
|
|
5486
6128
|
contextState: this.getContextState()
|
|
5487
6129
|
};
|
|
5488
|
-
this.history.push((0,
|
|
6130
|
+
this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createAssistantMessage)(result)));
|
|
5489
6131
|
this.emit("complete", executionResult);
|
|
5490
6132
|
this.emit("context_update", this.getContextState());
|
|
5491
6133
|
}
|
|
6134
|
+
async executeForegroundCommand(command, args) {
|
|
6135
|
+
this.executing = true;
|
|
6136
|
+
this.clearStreaming();
|
|
6137
|
+
this.emit("thinking", true);
|
|
6138
|
+
try {
|
|
6139
|
+
const result = await this.commandExecutor.executeCommand(command, this, args);
|
|
6140
|
+
this.emit("context_update", this.getContextState());
|
|
6141
|
+
return result;
|
|
6142
|
+
} catch (err) {
|
|
6143
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
6144
|
+
return {
|
|
6145
|
+
success: false,
|
|
6146
|
+
message: `Error: ${errMsg}`
|
|
6147
|
+
};
|
|
6148
|
+
} finally {
|
|
6149
|
+
this.executing = false;
|
|
6150
|
+
this.emit("thinking", false);
|
|
6151
|
+
this.persistCurrentSession();
|
|
6152
|
+
if (!this.shuttingDown && this.pendingPrompt) {
|
|
6153
|
+
const queued = this.pendingPrompt;
|
|
6154
|
+
const queuedDisplay = this.pendingDisplayInput;
|
|
6155
|
+
const queuedRaw = this.pendingRawInput;
|
|
6156
|
+
this.clearPendingQueue();
|
|
6157
|
+
setTimeout(() => this.executePrompt(queued, queuedDisplay, queuedRaw), 0);
|
|
6158
|
+
}
|
|
6159
|
+
}
|
|
6160
|
+
}
|
|
5492
6161
|
async executePrompt(input, displayInput, rawInput) {
|
|
5493
6162
|
this.executing = true;
|
|
5494
6163
|
this.clearStreaming();
|
|
5495
6164
|
this.emit("thinking", true);
|
|
5496
|
-
this.history.push((0,
|
|
6165
|
+
this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createUserMessage)(displayInput ?? input)));
|
|
5497
6166
|
const historyBefore = this.getSessionOrThrow().getHistory().length;
|
|
5498
6167
|
this.usedMemoryReferences = [];
|
|
5499
6168
|
try {
|
|
@@ -5509,7 +6178,7 @@ var InteractiveSession = class {
|
|
|
5509
6178
|
historyBefore,
|
|
5510
6179
|
this.getContextState()
|
|
5511
6180
|
);
|
|
5512
|
-
this.history.push((0,
|
|
6181
|
+
this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createAssistantMessage)(result.response)));
|
|
5513
6182
|
if (result.usage) this.history.push(createUsageSummaryEntry(result.usage));
|
|
5514
6183
|
this.emit("complete", result);
|
|
5515
6184
|
this.emit("context_update", this.getContextState());
|
|
@@ -5525,15 +6194,15 @@ var InteractiveSession = class {
|
|
|
5525
6194
|
pushToolSummaryToHistory({ activeTools: this.activeTools, history: this.history });
|
|
5526
6195
|
this.clearStreaming();
|
|
5527
6196
|
if (result.response)
|
|
5528
|
-
this.history.push((0,
|
|
6197
|
+
this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createAssistantMessage)(result.response)));
|
|
5529
6198
|
if (result.usage) this.history.push(createUsageSummaryEntry(result.usage));
|
|
5530
|
-
this.history.push((0,
|
|
6199
|
+
this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createSystemMessage)("Interrupted by user.")));
|
|
5531
6200
|
this.emit("interrupted", result);
|
|
5532
6201
|
} else {
|
|
5533
6202
|
pushToolSummaryToHistory({ activeTools: this.activeTools, history: this.history });
|
|
5534
6203
|
this.clearStreaming();
|
|
5535
6204
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
5536
|
-
this.history.push((0,
|
|
6205
|
+
this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createSystemMessage)(`Error: ${errMsg}`)));
|
|
5537
6206
|
this.emit("error", err instanceof Error ? err : new Error(errMsg));
|
|
5538
6207
|
}
|
|
5539
6208
|
} finally {
|
|
@@ -5570,7 +6239,7 @@ var InteractiveSession = class {
|
|
|
5570
6239
|
} catch (error) {
|
|
5571
6240
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
5572
6241
|
this.history.push(
|
|
5573
|
-
(0,
|
|
6242
|
+
(0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createSystemMessage)(`Checkpoint error: ${err.message}`))
|
|
5574
6243
|
);
|
|
5575
6244
|
this.emit("error", err);
|
|
5576
6245
|
}
|
|
@@ -5584,6 +6253,19 @@ var InteractiveSession = class {
|
|
|
5584
6253
|
}, STREAMING_FLUSH_INTERVAL_MS);
|
|
5585
6254
|
}
|
|
5586
6255
|
}
|
|
6256
|
+
handleCompactEvent(event) {
|
|
6257
|
+
if (event.trigger === "auto") {
|
|
6258
|
+
this.history.push(
|
|
6259
|
+
(0, import_agent_core7.messageToHistoryEntry)(
|
|
6260
|
+
(0, import_agent_core7.createSystemMessage)(
|
|
6261
|
+
`Auto compacted context: ${Math.round(event.before.usedPercentage)}% -> ${Math.round(event.after.usedPercentage)}%`
|
|
6262
|
+
)
|
|
6263
|
+
)
|
|
6264
|
+
);
|
|
6265
|
+
}
|
|
6266
|
+
this.emit("compact", event);
|
|
6267
|
+
this.emit("context_update", event.after);
|
|
6268
|
+
}
|
|
5587
6269
|
handleToolExecution(event) {
|
|
5588
6270
|
const streamingState = { activeTools: this.activeTools, history: this.history };
|
|
5589
6271
|
if (event.type === "start") {
|
|
@@ -5655,10 +6337,10 @@ function createQuery(options) {
|
|
|
5655
6337
|
}
|
|
5656
6338
|
|
|
5657
6339
|
// src/types.ts
|
|
5658
|
-
var
|
|
6340
|
+
var import_agent_core8 = require("@robota-sdk/agent-core");
|
|
5659
6341
|
|
|
5660
6342
|
// src/index.ts
|
|
5661
|
-
var
|
|
6343
|
+
var import_agent_core9 = require("@robota-sdk/agent-core");
|
|
5662
6344
|
|
|
5663
6345
|
// src/self-hosting/self-hosting-verification.ts
|
|
5664
6346
|
var DEFAULT_BASE_REF = "origin/develop";
|
|
@@ -5780,7 +6462,7 @@ var import_agent_runtime7 = require("@robota-sdk/agent-runtime");
|
|
|
5780
6462
|
var import_agent_runtime8 = require("@robota-sdk/agent-runtime");
|
|
5781
6463
|
|
|
5782
6464
|
// src/index.ts
|
|
5783
|
-
var
|
|
6465
|
+
var import_agent_core10 = require("@robota-sdk/agent-core");
|
|
5784
6466
|
|
|
5785
6467
|
// src/permissions/permission-prompt.ts
|
|
5786
6468
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
@@ -5803,10 +6485,13 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
5803
6485
|
}
|
|
5804
6486
|
|
|
5805
6487
|
// src/index.ts
|
|
5806
|
-
var
|
|
6488
|
+
var import_agent_core11 = require("@robota-sdk/agent-core");
|
|
5807
6489
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5808
6490
|
0 && (module.exports = {
|
|
6491
|
+
AUTO_COMPACT_THRESHOLD_SETTINGS_KEY,
|
|
5809
6492
|
AgentExecutor,
|
|
6493
|
+
BACKGROUND_COMMAND_DESCRIPTION,
|
|
6494
|
+
BACKGROUND_COMMAND_USAGE,
|
|
5810
6495
|
BUILT_IN_AGENTS,
|
|
5811
6496
|
BackgroundJobOrchestrator,
|
|
5812
6497
|
BackgroundTaskError,
|
|
@@ -5814,64 +6499,171 @@ var import_agent_core8 = require("@robota-sdk/agent-core");
|
|
|
5814
6499
|
BuiltinCommandSource,
|
|
5815
6500
|
BundlePluginInstaller,
|
|
5816
6501
|
BundlePluginLoader,
|
|
6502
|
+
CLEAR_COMMAND_DESCRIPTION,
|
|
6503
|
+
COST_COMMAND_DESCRIPTION,
|
|
5817
6504
|
CommandRegistry,
|
|
6505
|
+
DEFAULT_AUTO_COMPACT_THRESHOLD,
|
|
6506
|
+
DEFAULT_STATUS_LINE_COMMAND_SETTINGS,
|
|
6507
|
+
EXIT_COMMAND_DESCRIPTION,
|
|
5818
6508
|
EditCheckpointStore,
|
|
6509
|
+
HELP_COMMAND_DESCRIPTION,
|
|
5819
6510
|
InteractiveSession,
|
|
6511
|
+
LANGUAGE_COMMAND_ARGUMENT_HINT,
|
|
6512
|
+
LANGUAGE_COMMAND_DESCRIPTION,
|
|
6513
|
+
MEMORY_COMMAND_ARGUMENT_HINT,
|
|
6514
|
+
MEMORY_COMMAND_DESCRIPTION,
|
|
6515
|
+
MEMORY_COMMAND_USAGE,
|
|
5820
6516
|
MEMORY_INDEX_MAX_BYTES,
|
|
5821
6517
|
MEMORY_INDEX_MAX_LINES,
|
|
6518
|
+
MODEL_COMMAND_ARGUMENT_HINT,
|
|
6519
|
+
MODEL_COMMAND_DESCRIPTION,
|
|
5822
6520
|
MarketplaceClient,
|
|
6521
|
+
PERMISSIONS_COMMAND_DESCRIPTION,
|
|
6522
|
+
PERMISSION_MODE_ARGUMENT_HINT,
|
|
6523
|
+
PERMISSION_MODE_COMMAND_DESCRIPTION,
|
|
6524
|
+
PLUGIN_COMMAND_ARGUMENT_HINT,
|
|
6525
|
+
PLUGIN_COMMAND_DESCRIPTION,
|
|
5823
6526
|
PluginCommandSource,
|
|
5824
6527
|
PluginSettingsStore,
|
|
5825
6528
|
ProjectMemoryStore,
|
|
5826
6529
|
PromptExecutor,
|
|
6530
|
+
RECOMMENDED_RESPONSE_LANGUAGES,
|
|
6531
|
+
RELOAD_PLUGINS_COMMAND_DESCRIPTION,
|
|
6532
|
+
RENAME_COMMAND_DESCRIPTION,
|
|
6533
|
+
RENAME_COMMAND_USAGE,
|
|
6534
|
+
RESUME_COMMAND_DESCRIPTION,
|
|
6535
|
+
REWIND_COMMAND_ARGUMENT_HINT,
|
|
6536
|
+
REWIND_COMMAND_DESCRIPTION,
|
|
6537
|
+
STATUSLINE_COMMAND_ARGUMENT_HINT,
|
|
6538
|
+
STATUSLINE_COMMAND_DESCRIPTION,
|
|
5827
6539
|
SkillCommandSource,
|
|
5828
6540
|
SubagentManager,
|
|
5829
6541
|
SystemCommandExecutor,
|
|
5830
6542
|
TRUST_TO_MODE,
|
|
6543
|
+
VALID_PERMISSION_MODES,
|
|
5831
6544
|
WorktreeSubagentRunner,
|
|
5832
6545
|
assembleSubagentPrompt,
|
|
6546
|
+
buildBackgroundCommandSubcommands,
|
|
6547
|
+
buildLanguageCommandSubcommands,
|
|
6548
|
+
buildMemoryCommandSubcommands,
|
|
6549
|
+
buildModelCommandSubcommands,
|
|
6550
|
+
buildPermissionModeSubcommands,
|
|
6551
|
+
buildPluginCommandSubcommands,
|
|
6552
|
+
buildProviderProfile,
|
|
6553
|
+
buildProviderSetupPatch,
|
|
6554
|
+
buildRewindCommandSubcommands,
|
|
5833
6555
|
buildSkillPrompt,
|
|
6556
|
+
buildStatusLineCommandSubcommands,
|
|
6557
|
+
cancelCommandBackgroundTask,
|
|
5834
6558
|
chatEntryToMessage,
|
|
6559
|
+
clearConversationHistory,
|
|
6560
|
+
closeCommandBackgroundTask,
|
|
6561
|
+
compactCommandContext,
|
|
5835
6562
|
createAgentTool,
|
|
5836
6563
|
createBackgroundProcessTool,
|
|
6564
|
+
createBuiltinCommandModule,
|
|
5837
6565
|
createCommandExecutionTool,
|
|
6566
|
+
createCommandMemoryStores,
|
|
6567
|
+
createCommandPendingMemoryStore,
|
|
6568
|
+
createCommandProjectMemoryStore,
|
|
5838
6569
|
createDefaultTools,
|
|
6570
|
+
createPluginRegistryReloadRequestedEffect,
|
|
6571
|
+
createPluginTuiRequestedEffect,
|
|
6572
|
+
createProviderSetupFlow,
|
|
5839
6573
|
createQuery,
|
|
6574
|
+
createSessionExitRequestedEffect,
|
|
6575
|
+
createSessionPickerRequestedEffect,
|
|
6576
|
+
createSessionRenamedEffect,
|
|
5840
6577
|
createSubagentLogger,
|
|
5841
6578
|
createSubagentSession,
|
|
5842
6579
|
createSystemCommands,
|
|
5843
6580
|
createWorktreeSubagentRunner,
|
|
5844
6581
|
discoverTaskFiles,
|
|
5845
6582
|
evaluatePermission,
|
|
6583
|
+
evaluateReversibleToolSafety,
|
|
5846
6584
|
executeSkill,
|
|
6585
|
+
formatCommandBackgroundTask,
|
|
6586
|
+
formatCommandBackgroundTaskList,
|
|
6587
|
+
formatCommandHelpMessage,
|
|
6588
|
+
formatCommandPermissionsMessage,
|
|
6589
|
+
formatEnvReference,
|
|
6590
|
+
formatInvalidPermissionModeMessage,
|
|
6591
|
+
formatLanguageUsageMessage,
|
|
6592
|
+
formatProviderSetupChoiceLabel,
|
|
6593
|
+
formatProviderSetupPromptLabel,
|
|
6594
|
+
formatProviderSetupSelectionPrompt,
|
|
5847
6595
|
formatTaskContext,
|
|
5848
6596
|
getBackgroundTaskTransitions,
|
|
5849
6597
|
getBuiltInAgent,
|
|
5850
6598
|
getForkWorkerSuffix,
|
|
5851
6599
|
getMessagesForAPI,
|
|
6600
|
+
getProviderSetupStep,
|
|
5852
6601
|
getSubagentSuffix,
|
|
6602
|
+
hasSensitiveCommandMemoryContent,
|
|
6603
|
+
hasUsableSecretReference,
|
|
6604
|
+
inspectCommandEditCheckpoint,
|
|
5853
6605
|
isChatEntry,
|
|
6606
|
+
isCommandMemoryType,
|
|
6607
|
+
isEnvReference,
|
|
5854
6608
|
isMemoryType,
|
|
6609
|
+
isPermissionMode,
|
|
6610
|
+
isStatusLineCommandSettingsPatch,
|
|
5855
6611
|
isTerminalBackgroundTaskStatus,
|
|
6612
|
+
listCommandBackgroundTasks,
|
|
6613
|
+
listCommandEditCheckpoints,
|
|
6614
|
+
listCommandSessionAllowedTools,
|
|
6615
|
+
listCommandUsedMemoryReferences,
|
|
5856
6616
|
loadTaskContext,
|
|
6617
|
+
mergeProviderPatch,
|
|
5857
6618
|
messageToHistoryEntry,
|
|
6619
|
+
parseCommandBackgroundLogCursor,
|
|
5858
6620
|
parseFrontmatter,
|
|
6621
|
+
parseLanguageArgument,
|
|
6622
|
+
parsePermissionModeArgument,
|
|
6623
|
+
parseSessionNameArgument,
|
|
5859
6624
|
parseTaskFile,
|
|
5860
6625
|
planSelfHostingVerification,
|
|
5861
6626
|
preprocessShellCommands,
|
|
6627
|
+
probeProviderProfile,
|
|
5862
6628
|
projectPaths,
|
|
5863
6629
|
promptForApproval,
|
|
6630
|
+
readAutoCompactThreshold,
|
|
6631
|
+
readAutoCompactThresholdSource,
|
|
6632
|
+
readCommandBackgroundTaskLog,
|
|
6633
|
+
readCommandContextState,
|
|
6634
|
+
readCommandPermissionMode,
|
|
6635
|
+
readCommandPermissionsState,
|
|
6636
|
+
readCommandSessionInfo,
|
|
5864
6637
|
readCurrentGitBranch,
|
|
6638
|
+
recordCommandMemoryEvent,
|
|
6639
|
+
resetAutoCompactThresholdSetting,
|
|
6640
|
+
resolveEnvReference,
|
|
6641
|
+
resolvePermissionModeAdapter,
|
|
6642
|
+
resolvePluginCommandAdapter,
|
|
6643
|
+
resolveProviderSetupSelection,
|
|
5865
6644
|
resolveSubagentLogDir,
|
|
6645
|
+
restoreCommandEditCheckpoint,
|
|
5866
6646
|
retrieveAgentToolDeps,
|
|
6647
|
+
rollbackCommandEditCheckpoint,
|
|
5867
6648
|
runHooks,
|
|
6649
|
+
runProviderSetupPromptFlow,
|
|
5868
6650
|
selectRelevantTasks,
|
|
6651
|
+
setCommandAutoCompactThreshold,
|
|
6652
|
+
setCurrentProvider,
|
|
5869
6653
|
storeAgentToolDeps,
|
|
6654
|
+
submitProviderSetupValue,
|
|
5870
6655
|
substituteVariables,
|
|
5871
6656
|
summarizeBackgroundJobGroup,
|
|
6657
|
+
testProviderProfileCommand,
|
|
5872
6658
|
transitionBackgroundTaskStatus,
|
|
5873
6659
|
transitionSelfHostingLoop,
|
|
5874
6660
|
updateTaskFileStatus,
|
|
6661
|
+
upsertProviderProfile,
|
|
5875
6662
|
userPaths,
|
|
5876
|
-
|
|
6663
|
+
validateProviderProfile,
|
|
6664
|
+
validateProviderSetupValue,
|
|
6665
|
+
wrapEditCheckpointTools,
|
|
6666
|
+
wrapReversibleExecutionTools,
|
|
6667
|
+
writeAutoCompactThresholdSetting,
|
|
6668
|
+
writeCommandPermissionMode
|
|
5877
6669
|
});
|