@robota-sdk/agent-sdk 3.0.0-beta.61 → 3.0.0-beta.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node/index.cjs +1201 -336
- package/dist/node/index.d.cts +315 -20
- package/dist/node/index.d.ts +315 -20
- package/dist/node/index.js +1182 -338
- package/package.json +6 -5
package/dist/node/index.cjs
CHANGED
|
@@ -47,6 +47,7 @@ __export(index_exports, {
|
|
|
47
47
|
DEFAULT_AUTO_COMPACT_THRESHOLD: () => DEFAULT_AUTO_COMPACT_THRESHOLD,
|
|
48
48
|
DEFAULT_BACKGROUND_TASK_LOG_PAGE_SIZE: () => import_agent_runtime4.DEFAULT_BACKGROUND_TASK_LOG_PAGE_SIZE,
|
|
49
49
|
DEFAULT_STATUS_LINE_COMMAND_SETTINGS: () => DEFAULT_STATUS_LINE_COMMAND_SETTINGS,
|
|
50
|
+
EXECUTION_ORIGIN_METADATA_KEYS: () => EXECUTION_ORIGIN_METADATA_KEYS,
|
|
50
51
|
EXIT_COMMAND_DESCRIPTION: () => EXIT_COMMAND_DESCRIPTION,
|
|
51
52
|
EditCheckpointStore: () => EditCheckpointStore,
|
|
52
53
|
HELP_COMMAND_DESCRIPTION: () => HELP_COMMAND_DESCRIPTION,
|
|
@@ -82,11 +83,14 @@ __export(index_exports, {
|
|
|
82
83
|
STATUSLINE_COMMAND_ARGUMENT_HINT: () => STATUSLINE_COMMAND_ARGUMENT_HINT,
|
|
83
84
|
STATUSLINE_COMMAND_DESCRIPTION: () => STATUSLINE_COMMAND_DESCRIPTION,
|
|
84
85
|
SkillCommandSource: () => SkillCommandSource,
|
|
85
|
-
SubagentManager: () =>
|
|
86
|
+
SubagentManager: () => import_agent_runtime8.SubagentManager,
|
|
86
87
|
SystemCommandExecutor: () => SystemCommandExecutor,
|
|
88
|
+
USER_LOCAL_MEMORY_CATEGORIES: () => USER_LOCAL_MEMORY_CATEGORIES,
|
|
89
|
+
USER_LOCAL_STORAGE_CATEGORIES: () => USER_LOCAL_STORAGE_CATEGORIES,
|
|
90
|
+
USER_LOCAL_STORAGE_CATEGORY_DEFINITIONS: () => USER_LOCAL_STORAGE_CATEGORY_DEFINITIONS,
|
|
87
91
|
VALIDATE_SESSION_COMMAND_DESCRIPTION: () => VALIDATE_SESSION_COMMAND_DESCRIPTION,
|
|
88
92
|
VALID_PERMISSION_MODES: () => VALID_PERMISSION_MODES,
|
|
89
|
-
WorktreeSubagentRunner: () =>
|
|
93
|
+
WorktreeSubagentRunner: () => import_agent_runtime9.WorktreeSubagentRunner,
|
|
90
94
|
addCommandContextReference: () => addCommandContextReference,
|
|
91
95
|
appendPrefixedLogLines: () => import_agent_runtime4.appendPrefixedLogLines,
|
|
92
96
|
assembleSubagentPrompt: () => assembleSubagentPrompt,
|
|
@@ -108,7 +112,9 @@ __export(index_exports, {
|
|
|
108
112
|
closeCommandBackgroundTask: () => closeCommandBackgroundTask,
|
|
109
113
|
compactCommandContext: () => compactCommandContext,
|
|
110
114
|
createAgentTool: () => createAgentTool,
|
|
115
|
+
createBackgroundGroupExecutionEntryId: () => createBackgroundGroupExecutionEntryId,
|
|
111
116
|
createBackgroundProcessTool: () => createBackgroundProcessTool,
|
|
117
|
+
createBackgroundTaskExecutionEntryId: () => createBackgroundTaskExecutionEntryId,
|
|
112
118
|
createBackgroundTaskLogPage: () => import_agent_runtime4.createBackgroundTaskLogPage,
|
|
113
119
|
createBuiltinCommandModule: () => createBuiltinCommandModule,
|
|
114
120
|
createCommandExecutionTool: () => createCommandExecutionTool,
|
|
@@ -117,7 +123,13 @@ __export(index_exports, {
|
|
|
117
123
|
createCommandProjectMemoryStore: () => createCommandProjectMemoryStore,
|
|
118
124
|
createContextReferenceItem: () => createContextReferenceItem,
|
|
119
125
|
createDefaultTools: () => createDefaultTools,
|
|
126
|
+
createExecutionOriginMetadata: () => createExecutionOriginMetadata,
|
|
127
|
+
createExecutionWorkspaceSnapshot: () => createExecutionWorkspaceSnapshot,
|
|
128
|
+
createExecutionWorkspaceTaskSpawner: () => createExecutionWorkspaceTaskSpawner,
|
|
120
129
|
createLimitedOutputCapture: () => import_agent_runtime4.createLimitedOutputCapture,
|
|
130
|
+
createLineDetailPage: () => createLineDetailPage,
|
|
131
|
+
createMainThreadDetailPage: () => createMainThreadDetailPage,
|
|
132
|
+
createMainThreadExecutionEntryId: () => createMainThreadExecutionEntryId,
|
|
121
133
|
createModelCommandToolProjection: () => createModelCommandToolProjection,
|
|
122
134
|
createPluginRegistryReloadRequestedEffect: () => createPluginRegistryReloadRequestedEffect,
|
|
123
135
|
createPluginTuiRequestedEffect: () => createPluginTuiRequestedEffect,
|
|
@@ -133,8 +145,10 @@ __export(index_exports, {
|
|
|
133
145
|
createSubagentLogger: () => createSubagentLogger,
|
|
134
146
|
createSubagentSession: () => createSubagentSession,
|
|
135
147
|
createSystemCommands: () => createSystemCommands,
|
|
136
|
-
createWorktreeSubagentRunner: () =>
|
|
148
|
+
createWorktreeSubagentRunner: () => import_agent_runtime9.createWorktreeSubagentRunner,
|
|
137
149
|
deleteProviderProfile: () => deleteProviderProfile,
|
|
150
|
+
deleteUserLocalMemoryItem: () => deleteUserLocalMemoryItem,
|
|
151
|
+
disableUserLocalMemoryItem: () => disableUserLocalMemoryItem,
|
|
138
152
|
discoverTaskFiles: () => discoverTaskFiles,
|
|
139
153
|
evaluateReversibleToolSafety: () => evaluateReversibleToolSafety,
|
|
140
154
|
executeSkill: () => executeSkill,
|
|
@@ -164,6 +178,8 @@ __export(index_exports, {
|
|
|
164
178
|
hasSensitiveCommandMemoryContent: () => hasSensitiveCommandMemoryContent,
|
|
165
179
|
hasUsableSecretReference: () => hasUsableSecretReference,
|
|
166
180
|
inspectCommandEditCheckpoint: () => inspectCommandEditCheckpoint,
|
|
181
|
+
inspectUserLocalMemoryItem: () => inspectUserLocalMemoryItem,
|
|
182
|
+
inspectUserLocalStorage: () => inspectUserLocalStorage,
|
|
167
183
|
isCommandMemoryType: () => isCommandMemoryType,
|
|
168
184
|
isEnvReference: () => isEnvReference,
|
|
169
185
|
isMemoryType: () => isMemoryType,
|
|
@@ -177,10 +193,12 @@ __export(index_exports, {
|
|
|
177
193
|
listCommandSessionAllowedTools: () => listCommandSessionAllowedTools,
|
|
178
194
|
listCommandUsedMemoryReferences: () => listCommandUsedMemoryReferences,
|
|
179
195
|
listResumableSessionSummaries: () => listResumableSessionSummaries,
|
|
196
|
+
listUserLocalMemoryItems: () => listUserLocalMemoryItems,
|
|
180
197
|
loadTaskContext: () => loadTaskContext,
|
|
181
198
|
mergeProviderPatch: () => mergeProviderPatch,
|
|
182
199
|
normalizeModelCommandName: () => normalizeModelCommandName,
|
|
183
200
|
parseCommandBackgroundLogCursor: () => parseCommandBackgroundLogCursor,
|
|
201
|
+
parseExecutionWorkspaceEntryId: () => parseExecutionWorkspaceEntryId,
|
|
184
202
|
parseFrontmatter: () => parseFrontmatter,
|
|
185
203
|
parseLanguageArgument: () => parseLanguageArgument,
|
|
186
204
|
parsePermissionModeArgument: () => parsePermissionModeArgument,
|
|
@@ -200,6 +218,7 @@ __export(index_exports, {
|
|
|
200
218
|
readCommandPermissionsState: () => readCommandPermissionsState,
|
|
201
219
|
readCommandSessionInfo: () => readCommandSessionInfo,
|
|
202
220
|
readCurrentGitBranch: () => readCurrentGitBranch,
|
|
221
|
+
readEnabledUserLocalMemoryItem: () => readEnabledUserLocalMemoryItem,
|
|
203
222
|
recordCommandMemoryEvent: () => recordCommandMemoryEvent,
|
|
204
223
|
removeCommandContextReference: () => removeCommandContextReference,
|
|
205
224
|
removeContextReference: () => removeContextReference,
|
|
@@ -215,6 +234,7 @@ __export(index_exports, {
|
|
|
215
234
|
resolveProviderSetupSelection: () => resolveProviderSetupSelection,
|
|
216
235
|
resolveSessionIdByIdOrName: () => resolveSessionIdByIdOrName,
|
|
217
236
|
resolveSubagentLogDir: () => resolveSubagentLogDir,
|
|
237
|
+
resolveUserLocalStorageRoot: () => resolveUserLocalStorageRoot,
|
|
218
238
|
restoreCommandEditCheckpoint: () => restoreCommandEditCheckpoint,
|
|
219
239
|
retrieveAgentToolDeps: () => retrieveAgentToolDeps,
|
|
220
240
|
rollbackCommandEditCheckpoint: () => rollbackCommandEditCheckpoint,
|
|
@@ -223,6 +243,7 @@ __export(index_exports, {
|
|
|
223
243
|
selectRelevantTasks: () => selectRelevantTasks,
|
|
224
244
|
setCommandAutoCompactThreshold: () => setCommandAutoCompactThreshold,
|
|
225
245
|
setCurrentProvider: () => setCurrentProvider,
|
|
246
|
+
setUserLocalMemoryItem: () => setUserLocalMemoryItem,
|
|
226
247
|
storeAgentToolDeps: () => storeAgentToolDeps,
|
|
227
248
|
submitProviderSetupValue: () => submitProviderSetupValue,
|
|
228
249
|
substituteVariables: () => substituteVariables,
|
|
@@ -785,17 +806,17 @@ async function compactCommandContext(context, instructions) {
|
|
|
785
806
|
function listCommandContextReferences(context) {
|
|
786
807
|
return context.listContextReferences?.() ?? [];
|
|
787
808
|
}
|
|
788
|
-
async function addCommandContextReference(context,
|
|
809
|
+
async function addCommandContextReference(context, path3) {
|
|
789
810
|
if (!context.addContextReference) {
|
|
790
811
|
return {
|
|
791
812
|
evicted: [],
|
|
792
813
|
diagnostics: ["Command host does not support context reference additions."]
|
|
793
814
|
};
|
|
794
815
|
}
|
|
795
|
-
return context.addContextReference(
|
|
816
|
+
return context.addContextReference(path3);
|
|
796
817
|
}
|
|
797
|
-
function removeCommandContextReference(context,
|
|
798
|
-
return context.removeContextReference?.(
|
|
818
|
+
function removeCommandContextReference(context, path3) {
|
|
819
|
+
return context.removeContextReference?.(path3) ?? {};
|
|
799
820
|
}
|
|
800
821
|
function clearCommandContextReferences(context) {
|
|
801
822
|
return context.clearContextReferences?.() ?? { removed: [] };
|
|
@@ -1694,17 +1715,17 @@ var ProjectMemoryStore = class {
|
|
|
1694
1715
|
return (0, import_path.join)(memoryRoot2(this.cwd), TOPICS_DIRNAME);
|
|
1695
1716
|
}
|
|
1696
1717
|
loadStartupMemory() {
|
|
1697
|
-
const
|
|
1698
|
-
if (!(0, import_fs.existsSync)(
|
|
1699
|
-
return { content: "", path, lineCount: 0, truncated: false };
|
|
1718
|
+
const path3 = this.getIndexPath();
|
|
1719
|
+
if (!(0, import_fs.existsSync)(path3)) {
|
|
1720
|
+
return { content: "", path: path3, lineCount: 0, truncated: false };
|
|
1700
1721
|
}
|
|
1701
|
-
const raw = (0, import_fs.readFileSync)(
|
|
1722
|
+
const raw = (0, import_fs.readFileSync)(path3, "utf8");
|
|
1702
1723
|
const byBytes = truncateToUtf8Bytes(raw, MEMORY_INDEX_MAX_BYTES);
|
|
1703
1724
|
const byteTruncated = Buffer.byteLength(raw, "utf8") > MEMORY_INDEX_MAX_BYTES;
|
|
1704
1725
|
const byLines = limitLines(byBytes, MEMORY_INDEX_MAX_LINES);
|
|
1705
1726
|
return {
|
|
1706
1727
|
content: byLines.content,
|
|
1707
|
-
path,
|
|
1728
|
+
path: path3,
|
|
1708
1729
|
lineCount: byLines.content.length === 0 ? 0 : byLines.content.split(/\r?\n/).length,
|
|
1709
1730
|
truncated: byteTruncated || byLines.truncated
|
|
1710
1731
|
};
|
|
@@ -1723,9 +1744,9 @@ var ProjectMemoryStore = class {
|
|
|
1723
1744
|
}
|
|
1724
1745
|
readTopic(topic) {
|
|
1725
1746
|
const normalized = sanitizeTopic(topic);
|
|
1726
|
-
const
|
|
1727
|
-
if (!(0, import_fs.existsSync)(
|
|
1728
|
-
return (0, import_fs.readFileSync)(
|
|
1747
|
+
const path3 = (0, import_path.join)(this.getTopicsPath(), `${normalized}${TOPIC_EXTENSION}`);
|
|
1748
|
+
if (!(0, import_fs.existsSync)(path3)) return "";
|
|
1749
|
+
return (0, import_fs.readFileSync)(path3, "utf8").trimEnd();
|
|
1729
1750
|
}
|
|
1730
1751
|
append(input) {
|
|
1731
1752
|
const topic = sanitizeTopic(input.topic);
|
|
@@ -2199,7 +2220,7 @@ function getBuiltInAgent(name) {
|
|
|
2199
2220
|
// src/tools/agent-tool.ts
|
|
2200
2221
|
var import_zod2 = require("zod");
|
|
2201
2222
|
var import_agent_tools2 = require("@robota-sdk/agent-tools");
|
|
2202
|
-
var
|
|
2223
|
+
var import_agent_runtime6 = require("@robota-sdk/agent-runtime");
|
|
2203
2224
|
|
|
2204
2225
|
// src/subagents/in-process-subagent-runner.ts
|
|
2205
2226
|
function resolveAgentDefinition(agentType, customRegistry) {
|
|
@@ -2283,6 +2304,506 @@ function createInProcessSubagentRunner(deps) {
|
|
|
2283
2304
|
};
|
|
2284
2305
|
}
|
|
2285
2306
|
|
|
2307
|
+
// src/background-tasks/index.ts
|
|
2308
|
+
var import_agent_runtime3 = require("@robota-sdk/agent-runtime");
|
|
2309
|
+
|
|
2310
|
+
// src/background-tasks/background-job-orchestrator.ts
|
|
2311
|
+
var import_agent_runtime = require("@robota-sdk/agent-runtime");
|
|
2312
|
+
var DEFAULT_SUMMARY_LENGTH = 1e3;
|
|
2313
|
+
var BackgroundJobOrchestrator = class {
|
|
2314
|
+
manager;
|
|
2315
|
+
now;
|
|
2316
|
+
idFactory;
|
|
2317
|
+
unsubscribeManager;
|
|
2318
|
+
listeners = /* @__PURE__ */ new Set();
|
|
2319
|
+
groups = /* @__PURE__ */ new Map();
|
|
2320
|
+
sequence = 0;
|
|
2321
|
+
constructor(options) {
|
|
2322
|
+
this.manager = options.manager;
|
|
2323
|
+
this.now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
2324
|
+
this.idFactory = options.idFactory ?? (() => this.nextGroupId());
|
|
2325
|
+
this.sequence = options.initialGroups?.length ?? 0;
|
|
2326
|
+
for (const group of options.initialGroups ?? []) this.restoreGroup(group);
|
|
2327
|
+
this.unsubscribeManager = this.manager.subscribe((event) => this.handleTaskEvent(event));
|
|
2328
|
+
}
|
|
2329
|
+
createGroup(request) {
|
|
2330
|
+
const now = this.now();
|
|
2331
|
+
const state = {
|
|
2332
|
+
id: this.idFactory(request),
|
|
2333
|
+
parentSessionId: request.parentSessionId,
|
|
2334
|
+
waitPolicy: request.waitPolicy,
|
|
2335
|
+
taskIds: [...request.taskIds],
|
|
2336
|
+
status: "running",
|
|
2337
|
+
createdAt: now,
|
|
2338
|
+
updatedAt: now,
|
|
2339
|
+
results: [],
|
|
2340
|
+
...request.label ? { label: request.label } : {}
|
|
2341
|
+
};
|
|
2342
|
+
const record = this.createRecord(state);
|
|
2343
|
+
this.groups.set(state.id, record);
|
|
2344
|
+
this.captureExistingTerminalTasks(record);
|
|
2345
|
+
this.emit({ type: "background_job_group_created", group: cloneGroup(record.state) });
|
|
2346
|
+
this.evaluateCompletion(record);
|
|
2347
|
+
return cloneGroup(record.state);
|
|
2348
|
+
}
|
|
2349
|
+
listGroups() {
|
|
2350
|
+
return [...this.groups.values()].map((record) => cloneGroup(record.state));
|
|
2351
|
+
}
|
|
2352
|
+
getGroup(groupId) {
|
|
2353
|
+
const record = this.groups.get(groupId);
|
|
2354
|
+
return record ? cloneGroup(record.state) : void 0;
|
|
2355
|
+
}
|
|
2356
|
+
waitGroup(groupId) {
|
|
2357
|
+
const record = this.groups.get(groupId);
|
|
2358
|
+
if (!record) return Promise.reject(new Error(`Unknown background job group: ${groupId}`));
|
|
2359
|
+
return record.completion;
|
|
2360
|
+
}
|
|
2361
|
+
subscribe(listener) {
|
|
2362
|
+
this.listeners.add(listener);
|
|
2363
|
+
return () => {
|
|
2364
|
+
this.listeners.delete(listener);
|
|
2365
|
+
};
|
|
2366
|
+
}
|
|
2367
|
+
dispose() {
|
|
2368
|
+
this.unsubscribeManager();
|
|
2369
|
+
this.listeners.clear();
|
|
2370
|
+
}
|
|
2371
|
+
nextGroupId() {
|
|
2372
|
+
this.sequence += 1;
|
|
2373
|
+
return `group_${this.sequence}`;
|
|
2374
|
+
}
|
|
2375
|
+
restoreGroup(group) {
|
|
2376
|
+
const record = this.createRecord(cloneGroup(group));
|
|
2377
|
+
this.groups.set(group.id, record);
|
|
2378
|
+
if (group.status === "completed") record.resolve(cloneGroup(group));
|
|
2379
|
+
}
|
|
2380
|
+
createRecord(state) {
|
|
2381
|
+
let resolveGroup = () => {
|
|
2382
|
+
};
|
|
2383
|
+
const completion = new Promise((resolve6) => {
|
|
2384
|
+
resolveGroup = resolve6;
|
|
2385
|
+
});
|
|
2386
|
+
return { state, completion, resolve: resolveGroup };
|
|
2387
|
+
}
|
|
2388
|
+
captureExistingTerminalTasks(record) {
|
|
2389
|
+
for (const taskId of record.state.taskIds) {
|
|
2390
|
+
const task = this.manager.get(taskId);
|
|
2391
|
+
if (task && (0, import_agent_runtime.isTerminalBackgroundTaskStatus)(task.status)) this.captureTask(record, task);
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
handleTaskEvent(event) {
|
|
2395
|
+
const task = getTerminalTask(event);
|
|
2396
|
+
if (!task) return;
|
|
2397
|
+
for (const record of this.groups.values()) {
|
|
2398
|
+
if (!record.state.taskIds.includes(task.id)) continue;
|
|
2399
|
+
if (!this.captureTask(record, task)) continue;
|
|
2400
|
+
if (record.state.status === "running") this.evaluateCompletion(record);
|
|
2401
|
+
else this.emit({ type: "background_job_group_updated", group: cloneGroup(record.state) });
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
captureTask(record, task) {
|
|
2405
|
+
if (record.state.results.some((result) => result.taskId === task.id)) return false;
|
|
2406
|
+
record.state.results = [...record.state.results, createResultEnvelope(task)];
|
|
2407
|
+
record.state.updatedAt = this.now();
|
|
2408
|
+
return true;
|
|
2409
|
+
}
|
|
2410
|
+
evaluateCompletion(record) {
|
|
2411
|
+
if (record.state.status === "completed") return;
|
|
2412
|
+
if (!shouldComplete(record.state)) {
|
|
2413
|
+
this.emit({ type: "background_job_group_updated", group: cloneGroup(record.state) });
|
|
2414
|
+
return;
|
|
2415
|
+
}
|
|
2416
|
+
const now = this.now();
|
|
2417
|
+
record.state.status = "completed";
|
|
2418
|
+
record.state.completedAt = now;
|
|
2419
|
+
record.state.updatedAt = now;
|
|
2420
|
+
const completed = cloneGroup(record.state);
|
|
2421
|
+
record.resolve(completed);
|
|
2422
|
+
this.emit({ type: "background_job_group_completed", group: completed });
|
|
2423
|
+
}
|
|
2424
|
+
emit(event) {
|
|
2425
|
+
for (const listener of this.listeners) listener(event);
|
|
2426
|
+
}
|
|
2427
|
+
};
|
|
2428
|
+
function getTerminalTask(event) {
|
|
2429
|
+
if (event.type === "background_task_completed" || event.type === "background_task_failed" || event.type === "background_task_cancelled") {
|
|
2430
|
+
return event.task;
|
|
2431
|
+
}
|
|
2432
|
+
return void 0;
|
|
2433
|
+
}
|
|
2434
|
+
function shouldComplete(group) {
|
|
2435
|
+
if (group.waitPolicy === "manual") return false;
|
|
2436
|
+
if (group.waitPolicy === "wait_any") return group.results.length > 0;
|
|
2437
|
+
return group.taskIds.every((taskId) => group.results.some((result) => result.taskId === taskId));
|
|
2438
|
+
}
|
|
2439
|
+
function createResultEnvelope(task) {
|
|
2440
|
+
return {
|
|
2441
|
+
taskId: task.id,
|
|
2442
|
+
label: task.label,
|
|
2443
|
+
status: task.status,
|
|
2444
|
+
...task.result?.output ? { summary: summarizeOutput(task.result.output) } : {},
|
|
2445
|
+
...task.transcriptPath || task.logPath ? { outputRef: task.transcriptPath ?? task.logPath } : {},
|
|
2446
|
+
...task.error ? { error: { ...task.error } } : {},
|
|
2447
|
+
...task.startedAt ? { startedAt: task.startedAt } : {},
|
|
2448
|
+
...task.completedAt ? { completedAt: task.completedAt } : {}
|
|
2449
|
+
};
|
|
2450
|
+
}
|
|
2451
|
+
function summarizeOutput(output) {
|
|
2452
|
+
const trimmed = output.trim();
|
|
2453
|
+
if (trimmed.length <= DEFAULT_SUMMARY_LENGTH) return trimmed;
|
|
2454
|
+
return `${trimmed.slice(0, DEFAULT_SUMMARY_LENGTH)}...`;
|
|
2455
|
+
}
|
|
2456
|
+
function summarizeBackgroundJobGroup(group) {
|
|
2457
|
+
const completed = countResults(group, "completed");
|
|
2458
|
+
const failed = countResults(group, "failed");
|
|
2459
|
+
const cancelled = countResults(group, "cancelled");
|
|
2460
|
+
return {
|
|
2461
|
+
groupId: group.id,
|
|
2462
|
+
status: group.status,
|
|
2463
|
+
total: group.taskIds.length,
|
|
2464
|
+
completed,
|
|
2465
|
+
failed,
|
|
2466
|
+
cancelled,
|
|
2467
|
+
pending: Math.max(group.taskIds.length - group.results.length, 0),
|
|
2468
|
+
lines: group.results.map((result) => formatResultLine(result))
|
|
2469
|
+
};
|
|
2470
|
+
}
|
|
2471
|
+
function countResults(group, status) {
|
|
2472
|
+
return group.results.filter((result) => result.status === status).length;
|
|
2473
|
+
}
|
|
2474
|
+
function formatResultLine(result) {
|
|
2475
|
+
const detail = normalizeResultDetail(result);
|
|
2476
|
+
const output = result.outputRef && result.summary ? ` (output: ${result.outputRef})` : "";
|
|
2477
|
+
return `[${result.status}] ${result.label} ${result.taskId}: ${detail}${output}`;
|
|
2478
|
+
}
|
|
2479
|
+
function normalizeResultDetail(result) {
|
|
2480
|
+
const detail = result.error?.message ?? result.summary ?? "";
|
|
2481
|
+
const normalized = detail.replace(/\s+/g, " ").trim();
|
|
2482
|
+
return normalized.length > 0 ? normalized : "(no summary)";
|
|
2483
|
+
}
|
|
2484
|
+
function cloneGroup(group) {
|
|
2485
|
+
return {
|
|
2486
|
+
...group,
|
|
2487
|
+
taskIds: [...group.taskIds],
|
|
2488
|
+
results: group.results.map((result) => ({
|
|
2489
|
+
...result,
|
|
2490
|
+
...result.error ? { error: { ...result.error } } : {}
|
|
2491
|
+
}))
|
|
2492
|
+
};
|
|
2493
|
+
}
|
|
2494
|
+
|
|
2495
|
+
// src/background-tasks/execution-workspace-projection.ts
|
|
2496
|
+
var import_agent_runtime2 = require("@robota-sdk/agent-runtime");
|
|
2497
|
+
|
|
2498
|
+
// src/background-tasks/execution-workspace-types.ts
|
|
2499
|
+
var MAIN_THREAD_ENTRY_PREFIX = "main";
|
|
2500
|
+
var BACKGROUND_TASK_ENTRY_PREFIX = "task";
|
|
2501
|
+
var BACKGROUND_GROUP_ENTRY_PREFIX = "group";
|
|
2502
|
+
var ENTRY_ID_SEPARATOR = ":";
|
|
2503
|
+
var EXECUTION_ORIGIN_METADATA_KEYS = {
|
|
2504
|
+
kind: "executionOriginKind",
|
|
2505
|
+
sessionId: "executionOriginSessionId",
|
|
2506
|
+
turnId: "executionOriginTurnId",
|
|
2507
|
+
commandName: "executionOriginCommandName",
|
|
2508
|
+
toolCallId: "executionOriginToolCallId",
|
|
2509
|
+
skillId: "executionOriginSkillId",
|
|
2510
|
+
label: "executionOriginLabel"
|
|
2511
|
+
};
|
|
2512
|
+
function createMainThreadExecutionEntryId(sessionId) {
|
|
2513
|
+
return [MAIN_THREAD_ENTRY_PREFIX, sessionId].join(ENTRY_ID_SEPARATOR);
|
|
2514
|
+
}
|
|
2515
|
+
function createBackgroundTaskExecutionEntryId(taskId) {
|
|
2516
|
+
return [BACKGROUND_TASK_ENTRY_PREFIX, taskId].join(ENTRY_ID_SEPARATOR);
|
|
2517
|
+
}
|
|
2518
|
+
function createBackgroundGroupExecutionEntryId(groupId) {
|
|
2519
|
+
return [BACKGROUND_GROUP_ENTRY_PREFIX, groupId].join(ENTRY_ID_SEPARATOR);
|
|
2520
|
+
}
|
|
2521
|
+
function parseExecutionWorkspaceEntryId(entryId) {
|
|
2522
|
+
const [prefix, sourceId] = entryId.split(ENTRY_ID_SEPARATOR, 2);
|
|
2523
|
+
if (!sourceId) return void 0;
|
|
2524
|
+
if (prefix === MAIN_THREAD_ENTRY_PREFIX) return { kind: "main_thread", sourceId };
|
|
2525
|
+
if (prefix === BACKGROUND_TASK_ENTRY_PREFIX) return { kind: "background_task", sourceId };
|
|
2526
|
+
if (prefix === BACKGROUND_GROUP_ENTRY_PREFIX) return { kind: "background_group", sourceId };
|
|
2527
|
+
return void 0;
|
|
2528
|
+
}
|
|
2529
|
+
function createExecutionOriginMetadata(origin) {
|
|
2530
|
+
return {
|
|
2531
|
+
[EXECUTION_ORIGIN_METADATA_KEYS.kind]: origin.kind,
|
|
2532
|
+
[EXECUTION_ORIGIN_METADATA_KEYS.sessionId]: origin.sessionId,
|
|
2533
|
+
...origin.turnId ? { [EXECUTION_ORIGIN_METADATA_KEYS.turnId]: origin.turnId } : {},
|
|
2534
|
+
...origin.commandName ? { [EXECUTION_ORIGIN_METADATA_KEYS.commandName]: origin.commandName } : {},
|
|
2535
|
+
...origin.toolCallId ? { [EXECUTION_ORIGIN_METADATA_KEYS.toolCallId]: origin.toolCallId } : {},
|
|
2536
|
+
...origin.skillId ? { [EXECUTION_ORIGIN_METADATA_KEYS.skillId]: origin.skillId } : {},
|
|
2537
|
+
...origin.label ? { [EXECUTION_ORIGIN_METADATA_KEYS.label]: origin.label } : {}
|
|
2538
|
+
};
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
// src/background-tasks/execution-workspace-projection.ts
|
|
2542
|
+
var PREVIEW_MAX_LENGTH = 120;
|
|
2543
|
+
var SUCCESS_EXIT_CODE = 0;
|
|
2544
|
+
function createExecutionWorkspaceSnapshot(input) {
|
|
2545
|
+
const taskGroupIds = createTaskGroupIdMap(input.groups);
|
|
2546
|
+
const entries = [
|
|
2547
|
+
createMainThreadEntry(input.mainThread),
|
|
2548
|
+
...sortGroups(input.groups).map((group) => createBackgroundGroupEntry(group)),
|
|
2549
|
+
...sortTasks(input.tasks).map(
|
|
2550
|
+
(task) => createBackgroundTaskEntry(task, taskGroupIds.get(task.id))
|
|
2551
|
+
)
|
|
2552
|
+
].filter((entry) => matchesExecutionWorkspaceFilter(entry, input.filter));
|
|
2553
|
+
return {
|
|
2554
|
+
sessionId: input.sessionId,
|
|
2555
|
+
selectedEntryId: input.selectedEntryId ?? entries.find((entry) => entry.kind === "main_thread")?.id ?? createMainThreadExecutionEntryId(input.sessionId),
|
|
2556
|
+
updatedAt: entries[0]?.updatedAt ?? input.mainThread.updatedAt,
|
|
2557
|
+
entries
|
|
2558
|
+
};
|
|
2559
|
+
}
|
|
2560
|
+
function createMainThreadEntry(input) {
|
|
2561
|
+
return {
|
|
2562
|
+
id: createMainThreadExecutionEntryId(input.sessionId),
|
|
2563
|
+
sourceId: input.sessionId,
|
|
2564
|
+
kind: "main_thread",
|
|
2565
|
+
origin: { kind: "user_prompt", sessionId: input.sessionId },
|
|
2566
|
+
status: input.isExecuting ? "active" : "idle",
|
|
2567
|
+
title: "Main thread",
|
|
2568
|
+
subtitle: input.hasPendingPrompt ? "prompt queued" : `${input.historyLength} history entries`,
|
|
2569
|
+
preview: trimPreview(input.preview),
|
|
2570
|
+
unread: false,
|
|
2571
|
+
attention: "none",
|
|
2572
|
+
visibility: "default",
|
|
2573
|
+
updatedAt: input.updatedAt,
|
|
2574
|
+
controls: ["select"]
|
|
2575
|
+
};
|
|
2576
|
+
}
|
|
2577
|
+
function createBackgroundTaskEntry(state, groupId) {
|
|
2578
|
+
return {
|
|
2579
|
+
id: createBackgroundTaskExecutionEntryId(state.id),
|
|
2580
|
+
sourceId: state.id,
|
|
2581
|
+
kind: "background_task",
|
|
2582
|
+
parentId: state.parentTaskId ? createBackgroundTaskExecutionEntryId(state.parentTaskId) : createMainThreadExecutionEntryId(state.parentSessionId),
|
|
2583
|
+
...groupId ? { groupId: createBackgroundGroupExecutionEntryId(groupId) } : {},
|
|
2584
|
+
origin: readExecutionOrigin(state.metadata, {
|
|
2585
|
+
kind: "system",
|
|
2586
|
+
sessionId: state.parentSessionId
|
|
2587
|
+
}),
|
|
2588
|
+
taskKind: state.kind,
|
|
2589
|
+
status: state.status,
|
|
2590
|
+
title: state.label,
|
|
2591
|
+
subtitle: createTaskSubtitle(state),
|
|
2592
|
+
preview: createTaskPreview(state),
|
|
2593
|
+
currentAction: state.currentAction,
|
|
2594
|
+
unread: state.unread,
|
|
2595
|
+
attention: createTaskAttention(state),
|
|
2596
|
+
visibility: createTaskVisibility(state),
|
|
2597
|
+
updatedAt: state.lastActivityAt ?? state.updatedAt,
|
|
2598
|
+
controls: createTaskControls(state)
|
|
2599
|
+
};
|
|
2600
|
+
}
|
|
2601
|
+
function createBackgroundGroupEntry(group) {
|
|
2602
|
+
const preview = trimPreview(
|
|
2603
|
+
group.results.map((result) => result.summary ?? result.error?.message).join(" ")
|
|
2604
|
+
);
|
|
2605
|
+
return {
|
|
2606
|
+
id: createBackgroundGroupExecutionEntryId(group.id),
|
|
2607
|
+
sourceId: group.id,
|
|
2608
|
+
kind: "background_group",
|
|
2609
|
+
parentId: createMainThreadExecutionEntryId(group.parentSessionId),
|
|
2610
|
+
origin: { kind: "system", sessionId: group.parentSessionId, label: group.label },
|
|
2611
|
+
status: group.status,
|
|
2612
|
+
title: group.label ?? group.id,
|
|
2613
|
+
subtitle: `${group.results.length}/${group.taskIds.length} tasks`,
|
|
2614
|
+
preview,
|
|
2615
|
+
unread: false,
|
|
2616
|
+
attention: createGroupAttention(group),
|
|
2617
|
+
visibility: group.status === "completed" ? "collapsed" : "default",
|
|
2618
|
+
updatedAt: group.updatedAt,
|
|
2619
|
+
controls: group.status === "running" ? ["select", "wait"] : ["select"]
|
|
2620
|
+
};
|
|
2621
|
+
}
|
|
2622
|
+
function readExecutionOrigin(metadata, fallback) {
|
|
2623
|
+
const kind = toExecutionOriginKind(metadata?.[EXECUTION_ORIGIN_METADATA_KEYS.kind]);
|
|
2624
|
+
const sessionId = toStringValue(metadata?.[EXECUTION_ORIGIN_METADATA_KEYS.sessionId]);
|
|
2625
|
+
return {
|
|
2626
|
+
kind: kind ?? fallback.kind,
|
|
2627
|
+
sessionId: sessionId ?? fallback.sessionId,
|
|
2628
|
+
turnId: toStringValue(metadata?.[EXECUTION_ORIGIN_METADATA_KEYS.turnId]) ?? fallback.turnId,
|
|
2629
|
+
commandName: toStringValue(metadata?.[EXECUTION_ORIGIN_METADATA_KEYS.commandName]) ?? fallback.commandName,
|
|
2630
|
+
toolCallId: toStringValue(metadata?.[EXECUTION_ORIGIN_METADATA_KEYS.toolCallId]) ?? fallback.toolCallId,
|
|
2631
|
+
skillId: toStringValue(metadata?.[EXECUTION_ORIGIN_METADATA_KEYS.skillId]) ?? fallback.skillId,
|
|
2632
|
+
label: toStringValue(metadata?.[EXECUTION_ORIGIN_METADATA_KEYS.label]) ?? fallback.label
|
|
2633
|
+
};
|
|
2634
|
+
}
|
|
2635
|
+
function createTaskGroupIdMap(groups) {
|
|
2636
|
+
return new Map(groups.flatMap((group) => group.taskIds.map((taskId) => [taskId, group.id])));
|
|
2637
|
+
}
|
|
2638
|
+
function createTaskControls(state) {
|
|
2639
|
+
const controls = ["select"];
|
|
2640
|
+
if ((0, import_agent_runtime2.isTerminalBackgroundTaskStatus)(state.status)) controls.push("close");
|
|
2641
|
+
else controls.push("cancel");
|
|
2642
|
+
if (state.logPath || state.transcriptPath) controls.push("read_log");
|
|
2643
|
+
return controls;
|
|
2644
|
+
}
|
|
2645
|
+
function createTaskSubtitle(state) {
|
|
2646
|
+
if (state.kind === "agent") return state.agentType ?? state.cwd;
|
|
2647
|
+
return state.cwd;
|
|
2648
|
+
}
|
|
2649
|
+
function createTaskPreview(state) {
|
|
2650
|
+
if (state.status === "failed") return trimPreview(state.error?.message);
|
|
2651
|
+
if (state.status === "completed") return trimPreview(state.result?.output);
|
|
2652
|
+
return trimPreview(state.promptPreview ?? state.commandPreview);
|
|
2653
|
+
}
|
|
2654
|
+
function createTaskAttention(state) {
|
|
2655
|
+
if (state.status === "failed") return "failed";
|
|
2656
|
+
if (state.status === "waiting_permission") return "permission";
|
|
2657
|
+
if (state.unread) return "unread";
|
|
2658
|
+
if (state.status === "completed") return "completed";
|
|
2659
|
+
return "none";
|
|
2660
|
+
}
|
|
2661
|
+
function createTaskVisibility(state) {
|
|
2662
|
+
if (state.status === "completed" && !state.unread && !state.error && (state.result?.exitCode ?? SUCCESS_EXIT_CODE) === SUCCESS_EXIT_CODE && !state.result?.signalCode && !state.worktreePath && !state.branchName) {
|
|
2663
|
+
return "collapsed";
|
|
2664
|
+
}
|
|
2665
|
+
return "default";
|
|
2666
|
+
}
|
|
2667
|
+
function createGroupAttention(group) {
|
|
2668
|
+
if (group.results.some((result) => result.status === "failed")) return "failed";
|
|
2669
|
+
if (group.status === "completed") return "completed";
|
|
2670
|
+
return "none";
|
|
2671
|
+
}
|
|
2672
|
+
function matchesExecutionWorkspaceFilter(entry, filter) {
|
|
2673
|
+
if (!filter) return true;
|
|
2674
|
+
if (filter.includeMainThread === false && entry.kind === "main_thread") return false;
|
|
2675
|
+
if (filter.kinds && !filter.kinds.includes(entry.kind)) return false;
|
|
2676
|
+
if (filter.visibility && !filter.visibility.includes(entry.visibility)) return false;
|
|
2677
|
+
return true;
|
|
2678
|
+
}
|
|
2679
|
+
function sortTasks(tasks) {
|
|
2680
|
+
return [...tasks].sort(
|
|
2681
|
+
(left, right) => (right.lastActivityAt ?? right.updatedAt).localeCompare(left.lastActivityAt ?? left.updatedAt)
|
|
2682
|
+
);
|
|
2683
|
+
}
|
|
2684
|
+
function sortGroups(groups) {
|
|
2685
|
+
return [...groups].sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
2686
|
+
}
|
|
2687
|
+
function trimPreview(value) {
|
|
2688
|
+
const normalized = value?.trim().replace(/\s+/g, " ");
|
|
2689
|
+
if (!normalized) return void 0;
|
|
2690
|
+
return normalized.length > PREVIEW_MAX_LENGTH ? `${normalized.slice(0, PREVIEW_MAX_LENGTH)}...` : normalized;
|
|
2691
|
+
}
|
|
2692
|
+
function toStringValue(value) {
|
|
2693
|
+
return typeof value === "string" ? value : void 0;
|
|
2694
|
+
}
|
|
2695
|
+
function toExecutionOriginKind(value) {
|
|
2696
|
+
if (value === "user_prompt" || value === "slash_command" || value === "model_command" || value === "tool_call" || value === "skill" || value === "transport" || value === "system") {
|
|
2697
|
+
return value;
|
|
2698
|
+
}
|
|
2699
|
+
return void 0;
|
|
2700
|
+
}
|
|
2701
|
+
|
|
2702
|
+
// src/background-tasks/execution-workspace-detail.ts
|
|
2703
|
+
var EXECUTION_DETAIL_PAGE_SIZE = 80;
|
|
2704
|
+
function createMainThreadDetailPage(input) {
|
|
2705
|
+
const offset = normalizeOffset(input.cursor?.offset);
|
|
2706
|
+
const page = input.history.slice(offset, offset + EXECUTION_DETAIL_PAGE_SIZE);
|
|
2707
|
+
const records = page.map((entry) => ({
|
|
2708
|
+
id: entry.id,
|
|
2709
|
+
kind: entry.category === "chat" ? "message" : "progress",
|
|
2710
|
+
text: formatHistoryEntry(entry),
|
|
2711
|
+
timestamp: entry.timestamp.toISOString(),
|
|
2712
|
+
sourceId: entry.type
|
|
2713
|
+
}));
|
|
2714
|
+
return {
|
|
2715
|
+
entryId: input.entryId,
|
|
2716
|
+
...input.cursor ? { cursor: input.cursor } : {},
|
|
2717
|
+
...offset + page.length < input.history.length ? { nextCursor: { offset: offset + page.length } } : {},
|
|
2718
|
+
records
|
|
2719
|
+
};
|
|
2720
|
+
}
|
|
2721
|
+
function createLineDetailPage(input) {
|
|
2722
|
+
const offset = input.cursor?.offset ?? 0;
|
|
2723
|
+
const records = input.lines.map((line, index) => ({
|
|
2724
|
+
id: `${input.entryId}:${offset}:${index}`,
|
|
2725
|
+
kind: input.kind ?? "process_output",
|
|
2726
|
+
text: line
|
|
2727
|
+
}));
|
|
2728
|
+
return {
|
|
2729
|
+
entryId: input.entryId,
|
|
2730
|
+
...input.cursor ? { cursor: input.cursor } : {},
|
|
2731
|
+
...input.nextCursor ? { nextCursor: input.nextCursor } : {},
|
|
2732
|
+
records
|
|
2733
|
+
};
|
|
2734
|
+
}
|
|
2735
|
+
function normalizeOffset(offset) {
|
|
2736
|
+
return typeof offset === "number" && Number.isFinite(offset) && offset > 0 ? Math.floor(offset) : 0;
|
|
2737
|
+
}
|
|
2738
|
+
function formatHistoryEntry(entry) {
|
|
2739
|
+
if (typeof entry.data === "string") return entry.data;
|
|
2740
|
+
return entry.type;
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
// src/background-tasks/execution-workspace-spawner.ts
|
|
2744
|
+
function createExecutionWorkspaceTaskSpawner(options) {
|
|
2745
|
+
return {
|
|
2746
|
+
spawnAgent: (request) => options.manager.spawn(createAgentRequest(options, request)),
|
|
2747
|
+
spawnProcess: (request) => options.manager.spawn(createProcessRequest(options, request)),
|
|
2748
|
+
createGroup: (request) => options.groupOrchestrator.createGroup({
|
|
2749
|
+
parentSessionId: options.sessionId,
|
|
2750
|
+
waitPolicy: request.waitPolicy,
|
|
2751
|
+
taskIds: [...request.taskIds],
|
|
2752
|
+
label: request.label
|
|
2753
|
+
})
|
|
2754
|
+
};
|
|
2755
|
+
}
|
|
2756
|
+
function createAgentRequest(options, request) {
|
|
2757
|
+
return {
|
|
2758
|
+
kind: "agent",
|
|
2759
|
+
label: request.label,
|
|
2760
|
+
mode: request.mode ?? "background",
|
|
2761
|
+
parentSessionId: options.sessionId,
|
|
2762
|
+
parentTaskId: request.parentTaskId,
|
|
2763
|
+
depth: request.depth ?? 1,
|
|
2764
|
+
cwd: request.cwd ?? options.cwd,
|
|
2765
|
+
agentType: request.agentType,
|
|
2766
|
+
prompt: request.prompt,
|
|
2767
|
+
model: request.model,
|
|
2768
|
+
isolation: request.isolation,
|
|
2769
|
+
allowedTools: request.allowedTools ? [...request.allowedTools] : void 0,
|
|
2770
|
+
disallowedTools: request.disallowedTools ? [...request.disallowedTools] : void 0,
|
|
2771
|
+
permissionPolicy: request.permissionPolicy ?? "inherit-allowlist",
|
|
2772
|
+
timeoutMs: request.timeoutMs,
|
|
2773
|
+
idleTimeoutMs: request.idleTimeoutMs,
|
|
2774
|
+
maxRuntimeMs: request.maxRuntimeMs,
|
|
2775
|
+
outputLimitBytes: request.outputLimitBytes,
|
|
2776
|
+
maxTextDeltas: request.maxTextDeltas,
|
|
2777
|
+
repetitionWindow: request.repetitionWindow,
|
|
2778
|
+
repetitionThreshold: request.repetitionThreshold,
|
|
2779
|
+
metadata: createExecutionOriginMetadata(options.origin)
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
2782
|
+
function createProcessRequest(options, request) {
|
|
2783
|
+
return {
|
|
2784
|
+
kind: "process",
|
|
2785
|
+
label: request.label ?? request.command,
|
|
2786
|
+
mode: request.mode ?? "background",
|
|
2787
|
+
parentSessionId: options.sessionId,
|
|
2788
|
+
parentTaskId: request.parentTaskId,
|
|
2789
|
+
depth: request.depth ?? 0,
|
|
2790
|
+
cwd: request.cwd ?? options.cwd,
|
|
2791
|
+
command: request.command,
|
|
2792
|
+
shell: request.shell,
|
|
2793
|
+
env: request.env,
|
|
2794
|
+
stdin: request.stdin,
|
|
2795
|
+
timeoutMs: request.timeoutMs,
|
|
2796
|
+
idleTimeoutMs: request.idleTimeoutMs,
|
|
2797
|
+
maxRuntimeMs: request.maxRuntimeMs,
|
|
2798
|
+
outputLimitBytes: request.outputLimitBytes,
|
|
2799
|
+
metadata: createExecutionOriginMetadata(options.origin)
|
|
2800
|
+
};
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2803
|
+
// src/background-tasks/index.ts
|
|
2804
|
+
var import_agent_runtime4 = require("@robota-sdk/agent-runtime");
|
|
2805
|
+
var import_agent_runtime5 = require("@robota-sdk/agent-runtime");
|
|
2806
|
+
|
|
2286
2807
|
// src/tools/agent-tool-batch.ts
|
|
2287
2808
|
function stringifyAgentBatchResult(input) {
|
|
2288
2809
|
const successfulJobs = input.jobs.filter((job) => job.success);
|
|
@@ -2463,7 +2984,7 @@ function resolveAgentDefinition2(agentType, customRegistry) {
|
|
|
2463
2984
|
return void 0;
|
|
2464
2985
|
}
|
|
2465
2986
|
function createSubagentManager(deps) {
|
|
2466
|
-
return deps.subagentManager ?? new
|
|
2987
|
+
return deps.subagentManager ?? new import_agent_runtime6.SubagentManager({
|
|
2467
2988
|
runner: createInProcessSubagentRunner(deps)
|
|
2468
2989
|
});
|
|
2469
2990
|
}
|
|
@@ -2477,7 +2998,12 @@ function createSpawnRequest(args, agentType, agentDef, deps, label = agentDef.na
|
|
|
2477
2998
|
cwd: deps.cwd ?? process.cwd(),
|
|
2478
2999
|
prompt: args.prompt,
|
|
2479
3000
|
model: args.model,
|
|
2480
|
-
isolation: args.isolation
|
|
3001
|
+
isolation: args.isolation,
|
|
3002
|
+
metadata: createExecutionOriginMetadata({
|
|
3003
|
+
kind: "tool_call",
|
|
3004
|
+
sessionId: deps.parentSessionId ?? "unknown-session",
|
|
3005
|
+
label
|
|
3006
|
+
})
|
|
2481
3007
|
};
|
|
2482
3008
|
}
|
|
2483
3009
|
function stringifyUnknownAgentType(agentType) {
|
|
@@ -2544,250 +3070,58 @@ function stringifyAgentError(message, agentId) {
|
|
|
2544
3070
|
}
|
|
2545
3071
|
});
|
|
2546
3072
|
}
|
|
2547
|
-
async function runManagedAgent(args, deps, manager) {
|
|
2548
|
-
if (typeof args.prompt !== "string" || args.prompt.length === 0) {
|
|
2549
|
-
return stringifyAgentError("prompt is required when jobs is omitted");
|
|
2550
|
-
}
|
|
2551
|
-
const singleArgs = { ...args, prompt: args.prompt };
|
|
2552
|
-
const agentType = args.subagent_type ?? "general-purpose";
|
|
2553
|
-
const agentDef = resolveAgentDefinition2(agentType, deps.customAgentRegistry);
|
|
2554
|
-
if (!agentDef) {
|
|
2555
|
-
return stringifyUnknownAgentType(agentType);
|
|
2556
|
-
}
|
|
2557
|
-
let agentId;
|
|
2558
|
-
try {
|
|
2559
|
-
const state = await manager.spawn(createSpawnRequest(singleArgs, agentType, agentDef, deps));
|
|
2560
|
-
agentId = state.id;
|
|
2561
|
-
const response = await manager.wait(state.id);
|
|
2562
|
-
return stringifyAgentSuccess(response);
|
|
2563
|
-
} catch (err) {
|
|
2564
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
2565
|
-
return stringifyAgentError(message, agentId);
|
|
2566
|
-
}
|
|
2567
|
-
}
|
|
2568
|
-
function createAgentTool(deps) {
|
|
2569
|
-
const manager = createSubagentManager(deps);
|
|
2570
|
-
return (0, import_agent_tools2.createZodFunctionTool)(
|
|
2571
|
-
"Agent",
|
|
2572
|
-
AGENT_TOOL_DESCRIPTION,
|
|
2573
|
-
asZodSchema2(AgentSchema),
|
|
2574
|
-
async (params) => {
|
|
2575
|
-
const args = params;
|
|
2576
|
-
if (Array.isArray(args.jobs) && args.jobs.length > 0) {
|
|
2577
|
-
return runManagedAgentBatch({
|
|
2578
|
-
jobs: args.jobs,
|
|
2579
|
-
deps,
|
|
2580
|
-
manager,
|
|
2581
|
-
resolveAgentDefinition: resolveAgentDefinition2,
|
|
2582
|
-
createSpawnRequest
|
|
2583
|
-
});
|
|
2584
|
-
}
|
|
2585
|
-
return runManagedAgent(
|
|
2586
|
-
{
|
|
2587
|
-
prompt: args.prompt,
|
|
2588
|
-
...args.subagent_type !== void 0 ? { subagent_type: args.subagent_type } : {},
|
|
2589
|
-
...args.model !== void 0 ? { model: args.model } : {},
|
|
2590
|
-
...args.isolation !== void 0 ? { isolation: args.isolation } : {}
|
|
2591
|
-
},
|
|
2592
|
-
deps,
|
|
2593
|
-
manager
|
|
2594
|
-
);
|
|
2595
|
-
}
|
|
2596
|
-
);
|
|
2597
|
-
}
|
|
2598
|
-
|
|
2599
|
-
// src/background-tasks/index.ts
|
|
2600
|
-
var import_agent_runtime3 = require("@robota-sdk/agent-runtime");
|
|
2601
|
-
|
|
2602
|
-
// src/background-tasks/background-job-orchestrator.ts
|
|
2603
|
-
var import_agent_runtime2 = require("@robota-sdk/agent-runtime");
|
|
2604
|
-
var DEFAULT_SUMMARY_LENGTH = 1e3;
|
|
2605
|
-
var BackgroundJobOrchestrator = class {
|
|
2606
|
-
manager;
|
|
2607
|
-
now;
|
|
2608
|
-
idFactory;
|
|
2609
|
-
unsubscribeManager;
|
|
2610
|
-
listeners = /* @__PURE__ */ new Set();
|
|
2611
|
-
groups = /* @__PURE__ */ new Map();
|
|
2612
|
-
sequence = 0;
|
|
2613
|
-
constructor(options) {
|
|
2614
|
-
this.manager = options.manager;
|
|
2615
|
-
this.now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
2616
|
-
this.idFactory = options.idFactory ?? (() => this.nextGroupId());
|
|
2617
|
-
this.sequence = options.initialGroups?.length ?? 0;
|
|
2618
|
-
for (const group of options.initialGroups ?? []) this.restoreGroup(group);
|
|
2619
|
-
this.unsubscribeManager = this.manager.subscribe((event) => this.handleTaskEvent(event));
|
|
2620
|
-
}
|
|
2621
|
-
createGroup(request) {
|
|
2622
|
-
const now = this.now();
|
|
2623
|
-
const state = {
|
|
2624
|
-
id: this.idFactory(request),
|
|
2625
|
-
parentSessionId: request.parentSessionId,
|
|
2626
|
-
waitPolicy: request.waitPolicy,
|
|
2627
|
-
taskIds: [...request.taskIds],
|
|
2628
|
-
status: "running",
|
|
2629
|
-
createdAt: now,
|
|
2630
|
-
updatedAt: now,
|
|
2631
|
-
results: [],
|
|
2632
|
-
...request.label ? { label: request.label } : {}
|
|
2633
|
-
};
|
|
2634
|
-
const record = this.createRecord(state);
|
|
2635
|
-
this.groups.set(state.id, record);
|
|
2636
|
-
this.captureExistingTerminalTasks(record);
|
|
2637
|
-
this.emit({ type: "background_job_group_created", group: cloneGroup(record.state) });
|
|
2638
|
-
this.evaluateCompletion(record);
|
|
2639
|
-
return cloneGroup(record.state);
|
|
2640
|
-
}
|
|
2641
|
-
listGroups() {
|
|
2642
|
-
return [...this.groups.values()].map((record) => cloneGroup(record.state));
|
|
2643
|
-
}
|
|
2644
|
-
getGroup(groupId) {
|
|
2645
|
-
const record = this.groups.get(groupId);
|
|
2646
|
-
return record ? cloneGroup(record.state) : void 0;
|
|
2647
|
-
}
|
|
2648
|
-
waitGroup(groupId) {
|
|
2649
|
-
const record = this.groups.get(groupId);
|
|
2650
|
-
if (!record) return Promise.reject(new Error(`Unknown background job group: ${groupId}`));
|
|
2651
|
-
return record.completion;
|
|
2652
|
-
}
|
|
2653
|
-
subscribe(listener) {
|
|
2654
|
-
this.listeners.add(listener);
|
|
2655
|
-
return () => {
|
|
2656
|
-
this.listeners.delete(listener);
|
|
2657
|
-
};
|
|
2658
|
-
}
|
|
2659
|
-
dispose() {
|
|
2660
|
-
this.unsubscribeManager();
|
|
2661
|
-
this.listeners.clear();
|
|
2662
|
-
}
|
|
2663
|
-
nextGroupId() {
|
|
2664
|
-
this.sequence += 1;
|
|
2665
|
-
return `group_${this.sequence}`;
|
|
2666
|
-
}
|
|
2667
|
-
restoreGroup(group) {
|
|
2668
|
-
const record = this.createRecord(cloneGroup(group));
|
|
2669
|
-
this.groups.set(group.id, record);
|
|
2670
|
-
if (group.status === "completed") record.resolve(cloneGroup(group));
|
|
2671
|
-
}
|
|
2672
|
-
createRecord(state) {
|
|
2673
|
-
let resolveGroup = () => {
|
|
2674
|
-
};
|
|
2675
|
-
const completion = new Promise((resolve6) => {
|
|
2676
|
-
resolveGroup = resolve6;
|
|
2677
|
-
});
|
|
2678
|
-
return { state, completion, resolve: resolveGroup };
|
|
2679
|
-
}
|
|
2680
|
-
captureExistingTerminalTasks(record) {
|
|
2681
|
-
for (const taskId of record.state.taskIds) {
|
|
2682
|
-
const task = this.manager.get(taskId);
|
|
2683
|
-
if (task && (0, import_agent_runtime2.isTerminalBackgroundTaskStatus)(task.status)) this.captureTask(record, task);
|
|
2684
|
-
}
|
|
2685
|
-
}
|
|
2686
|
-
handleTaskEvent(event) {
|
|
2687
|
-
const task = getTerminalTask(event);
|
|
2688
|
-
if (!task) return;
|
|
2689
|
-
for (const record of this.groups.values()) {
|
|
2690
|
-
if (!record.state.taskIds.includes(task.id)) continue;
|
|
2691
|
-
if (!this.captureTask(record, task)) continue;
|
|
2692
|
-
if (record.state.status === "running") this.evaluateCompletion(record);
|
|
2693
|
-
else this.emit({ type: "background_job_group_updated", group: cloneGroup(record.state) });
|
|
2694
|
-
}
|
|
2695
|
-
}
|
|
2696
|
-
captureTask(record, task) {
|
|
2697
|
-
if (record.state.results.some((result) => result.taskId === task.id)) return false;
|
|
2698
|
-
record.state.results = [...record.state.results, createResultEnvelope(task)];
|
|
2699
|
-
record.state.updatedAt = this.now();
|
|
2700
|
-
return true;
|
|
2701
|
-
}
|
|
2702
|
-
evaluateCompletion(record) {
|
|
2703
|
-
if (record.state.status === "completed") return;
|
|
2704
|
-
if (!shouldComplete(record.state)) {
|
|
2705
|
-
this.emit({ type: "background_job_group_updated", group: cloneGroup(record.state) });
|
|
2706
|
-
return;
|
|
2707
|
-
}
|
|
2708
|
-
const now = this.now();
|
|
2709
|
-
record.state.status = "completed";
|
|
2710
|
-
record.state.completedAt = now;
|
|
2711
|
-
record.state.updatedAt = now;
|
|
2712
|
-
const completed = cloneGroup(record.state);
|
|
2713
|
-
record.resolve(completed);
|
|
2714
|
-
this.emit({ type: "background_job_group_completed", group: completed });
|
|
2715
|
-
}
|
|
2716
|
-
emit(event) {
|
|
2717
|
-
for (const listener of this.listeners) listener(event);
|
|
2718
|
-
}
|
|
2719
|
-
};
|
|
2720
|
-
function getTerminalTask(event) {
|
|
2721
|
-
if (event.type === "background_task_completed" || event.type === "background_task_failed" || event.type === "background_task_cancelled") {
|
|
2722
|
-
return event.task;
|
|
2723
|
-
}
|
|
2724
|
-
return void 0;
|
|
2725
|
-
}
|
|
2726
|
-
function shouldComplete(group) {
|
|
2727
|
-
if (group.waitPolicy === "manual") return false;
|
|
2728
|
-
if (group.waitPolicy === "wait_any") return group.results.length > 0;
|
|
2729
|
-
return group.taskIds.every((taskId) => group.results.some((result) => result.taskId === taskId));
|
|
2730
|
-
}
|
|
2731
|
-
function createResultEnvelope(task) {
|
|
2732
|
-
return {
|
|
2733
|
-
taskId: task.id,
|
|
2734
|
-
label: task.label,
|
|
2735
|
-
status: task.status,
|
|
2736
|
-
...task.result?.output ? { summary: summarizeOutput(task.result.output) } : {},
|
|
2737
|
-
...task.transcriptPath || task.logPath ? { outputRef: task.transcriptPath ?? task.logPath } : {},
|
|
2738
|
-
...task.error ? { error: { ...task.error } } : {},
|
|
2739
|
-
...task.startedAt ? { startedAt: task.startedAt } : {},
|
|
2740
|
-
...task.completedAt ? { completedAt: task.completedAt } : {}
|
|
2741
|
-
};
|
|
2742
|
-
}
|
|
2743
|
-
function summarizeOutput(output) {
|
|
2744
|
-
const trimmed = output.trim();
|
|
2745
|
-
if (trimmed.length <= DEFAULT_SUMMARY_LENGTH) return trimmed;
|
|
2746
|
-
return `${trimmed.slice(0, DEFAULT_SUMMARY_LENGTH)}...`;
|
|
2747
|
-
}
|
|
2748
|
-
function summarizeBackgroundJobGroup(group) {
|
|
2749
|
-
const completed = countResults(group, "completed");
|
|
2750
|
-
const failed = countResults(group, "failed");
|
|
2751
|
-
const cancelled = countResults(group, "cancelled");
|
|
2752
|
-
return {
|
|
2753
|
-
groupId: group.id,
|
|
2754
|
-
status: group.status,
|
|
2755
|
-
total: group.taskIds.length,
|
|
2756
|
-
completed,
|
|
2757
|
-
failed,
|
|
2758
|
-
cancelled,
|
|
2759
|
-
pending: Math.max(group.taskIds.length - group.results.length, 0),
|
|
2760
|
-
lines: group.results.map((result) => formatResultLine(result))
|
|
2761
|
-
};
|
|
2762
|
-
}
|
|
2763
|
-
function countResults(group, status) {
|
|
2764
|
-
return group.results.filter((result) => result.status === status).length;
|
|
2765
|
-
}
|
|
2766
|
-
function formatResultLine(result) {
|
|
2767
|
-
const detail = normalizeResultDetail(result);
|
|
2768
|
-
const output = result.outputRef && result.summary ? ` (output: ${result.outputRef})` : "";
|
|
2769
|
-
return `[${result.status}] ${result.label} ${result.taskId}: ${detail}${output}`;
|
|
2770
|
-
}
|
|
2771
|
-
function normalizeResultDetail(result) {
|
|
2772
|
-
const detail = result.error?.message ?? result.summary ?? "";
|
|
2773
|
-
const normalized = detail.replace(/\s+/g, " ").trim();
|
|
2774
|
-
return normalized.length > 0 ? normalized : "(no summary)";
|
|
3073
|
+
async function runManagedAgent(args, deps, manager) {
|
|
3074
|
+
if (typeof args.prompt !== "string" || args.prompt.length === 0) {
|
|
3075
|
+
return stringifyAgentError("prompt is required when jobs is omitted");
|
|
3076
|
+
}
|
|
3077
|
+
const singleArgs = { ...args, prompt: args.prompt };
|
|
3078
|
+
const agentType = args.subagent_type ?? "general-purpose";
|
|
3079
|
+
const agentDef = resolveAgentDefinition2(agentType, deps.customAgentRegistry);
|
|
3080
|
+
if (!agentDef) {
|
|
3081
|
+
return stringifyUnknownAgentType(agentType);
|
|
3082
|
+
}
|
|
3083
|
+
let agentId;
|
|
3084
|
+
try {
|
|
3085
|
+
const state = await manager.spawn(createSpawnRequest(singleArgs, agentType, agentDef, deps));
|
|
3086
|
+
agentId = state.id;
|
|
3087
|
+
const response = await manager.wait(state.id);
|
|
3088
|
+
return stringifyAgentSuccess(response);
|
|
3089
|
+
} catch (err) {
|
|
3090
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3091
|
+
return stringifyAgentError(message, agentId);
|
|
3092
|
+
}
|
|
2775
3093
|
}
|
|
2776
|
-
function
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
3094
|
+
function createAgentTool(deps) {
|
|
3095
|
+
const manager = createSubagentManager(deps);
|
|
3096
|
+
return (0, import_agent_tools2.createZodFunctionTool)(
|
|
3097
|
+
"Agent",
|
|
3098
|
+
AGENT_TOOL_DESCRIPTION,
|
|
3099
|
+
asZodSchema2(AgentSchema),
|
|
3100
|
+
async (params) => {
|
|
3101
|
+
const args = params;
|
|
3102
|
+
if (Array.isArray(args.jobs) && args.jobs.length > 0) {
|
|
3103
|
+
return runManagedAgentBatch({
|
|
3104
|
+
jobs: args.jobs,
|
|
3105
|
+
deps,
|
|
3106
|
+
manager,
|
|
3107
|
+
resolveAgentDefinition: resolveAgentDefinition2,
|
|
3108
|
+
createSpawnRequest
|
|
3109
|
+
});
|
|
3110
|
+
}
|
|
3111
|
+
return runManagedAgent(
|
|
3112
|
+
{
|
|
3113
|
+
prompt: args.prompt,
|
|
3114
|
+
...args.subagent_type !== void 0 ? { subagent_type: args.subagent_type } : {},
|
|
3115
|
+
...args.model !== void 0 ? { model: args.model } : {},
|
|
3116
|
+
...args.isolation !== void 0 ? { isolation: args.isolation } : {}
|
|
3117
|
+
},
|
|
3118
|
+
deps,
|
|
3119
|
+
manager
|
|
3120
|
+
);
|
|
3121
|
+
}
|
|
3122
|
+
);
|
|
2785
3123
|
}
|
|
2786
3124
|
|
|
2787
|
-
// src/background-tasks/index.ts
|
|
2788
|
-
var import_agent_runtime4 = require("@robota-sdk/agent-runtime");
|
|
2789
|
-
var import_agent_runtime5 = require("@robota-sdk/agent-runtime");
|
|
2790
|
-
|
|
2791
3125
|
// src/background-tasks/session-background-store.ts
|
|
2792
3126
|
var sessionBackgroundTaskManagers = /* @__PURE__ */ new WeakMap();
|
|
2793
3127
|
function storeSessionBackgroundTaskManager(key, manager) {
|
|
@@ -3647,6 +3981,10 @@ var MarketplaceSourceSchema = import_zod3.z.object({
|
|
|
3647
3981
|
});
|
|
3648
3982
|
var ExtraKnownMarketplacesSchema = import_zod3.z.record(MarketplaceSourceSchema).optional().catch(void 0);
|
|
3649
3983
|
var AutoCompactThresholdSchema = import_zod3.z.union([import_zod3.z.number().gt(0).lte(1), import_zod3.z.literal(false)]).optional();
|
|
3984
|
+
var TransportSettingsSchema = import_zod3.z.object({
|
|
3985
|
+
enabled: import_zod3.z.boolean().optional(),
|
|
3986
|
+
options: import_zod3.z.record(UniversalValueSchema).optional()
|
|
3987
|
+
});
|
|
3650
3988
|
var SettingsSchema = import_zod3.z.object({
|
|
3651
3989
|
/** Trust level used when no --permission-mode flag is given */
|
|
3652
3990
|
defaultTrustLevel: import_zod3.z.enum(["safe", "moderate", "full"]).optional(),
|
|
@@ -3666,7 +4004,9 @@ var SettingsSchema = import_zod3.z.object({
|
|
|
3666
4004
|
/** Extra marketplace URLs for BundlePlugin discovery */
|
|
3667
4005
|
extraKnownMarketplaces: ExtraKnownMarketplacesSchema,
|
|
3668
4006
|
/** Auto-compact threshold as a 0-1 fraction. Set false to disable automatic compaction. */
|
|
3669
|
-
autoCompactThreshold: AutoCompactThresholdSchema
|
|
4007
|
+
autoCompactThreshold: AutoCompactThresholdSchema,
|
|
4008
|
+
/** Transport enable/disable + options: transport name -> config */
|
|
4009
|
+
transports: import_zod3.z.record(TransportSettingsSchema).optional()
|
|
3670
4010
|
});
|
|
3671
4011
|
|
|
3672
4012
|
// src/config/config-loader.ts
|
|
@@ -3769,7 +4109,12 @@ function resolveProvider(merged) {
|
|
|
3769
4109
|
if (merged.currentProvider !== void 0) {
|
|
3770
4110
|
return resolveActiveProviderProfile2(merged);
|
|
3771
4111
|
}
|
|
3772
|
-
|
|
4112
|
+
if (merged.provider !== void 0) {
|
|
4113
|
+
throw new Error(
|
|
4114
|
+
'Legacy flat "provider" settings are not supported. Migrate to "currentProvider" + "providers" format.'
|
|
4115
|
+
);
|
|
4116
|
+
}
|
|
4117
|
+
return { ...DEFAULTS.provider };
|
|
3773
4118
|
}
|
|
3774
4119
|
function resolveActiveProviderProfile2(merged) {
|
|
3775
4120
|
const currentProvider = merged.currentProvider;
|
|
@@ -3792,16 +4137,6 @@ function resolveActiveProviderProfile2(merged) {
|
|
|
3792
4137
|
...profile.options !== void 0 && { options: profile.options }
|
|
3793
4138
|
};
|
|
3794
4139
|
}
|
|
3795
|
-
function resolveLegacyProvider(merged) {
|
|
3796
|
-
return {
|
|
3797
|
-
name: merged.provider?.name ?? DEFAULTS.provider.name,
|
|
3798
|
-
model: merged.provider?.model ?? DEFAULTS.provider.model,
|
|
3799
|
-
apiKey: merged.provider?.apiKey ?? DEFAULTS.provider.apiKey,
|
|
3800
|
-
...merged.provider?.baseURL !== void 0 && { baseURL: merged.provider.baseURL },
|
|
3801
|
-
...merged.provider?.timeout !== void 0 && { timeout: merged.provider.timeout },
|
|
3802
|
-
...merged.provider?.options !== void 0 && { options: merged.provider.options }
|
|
3803
|
-
};
|
|
3804
|
-
}
|
|
3805
4140
|
function toResolvedConfig(merged) {
|
|
3806
4141
|
return {
|
|
3807
4142
|
defaultTrustLevel: merged.defaultTrustLevel ?? DEFAULTS.defaultTrustLevel,
|
|
@@ -3845,10 +4180,10 @@ async function loadConfig(cwd) {
|
|
|
3845
4180
|
rawEntries.push({ raw, path: filePath });
|
|
3846
4181
|
}
|
|
3847
4182
|
}
|
|
3848
|
-
const parsedLayers = rawEntries.map(({ raw, path }) => {
|
|
4183
|
+
const parsedLayers = rawEntries.map(({ raw, path: path3 }) => {
|
|
3849
4184
|
const result = SettingsSchema.safeParse(raw);
|
|
3850
4185
|
if (!result.success) {
|
|
3851
|
-
throw new Error(`Invalid settings in ${
|
|
4186
|
+
throw new Error(`Invalid settings in ${path3}: ${result.error.message}`);
|
|
3852
4187
|
}
|
|
3853
4188
|
return resolveEnvRefs(result.data);
|
|
3854
4189
|
});
|
|
@@ -4212,7 +4547,8 @@ async function startBackgroundProcess(args, deps) {
|
|
|
4212
4547
|
command: args.command,
|
|
4213
4548
|
stdin: args.stdin,
|
|
4214
4549
|
timeoutMs: args.timeout ?? DEFAULT_PROCESS_TIMEOUT_MS,
|
|
4215
|
-
outputLimitBytes: args.outputLimitBytes
|
|
4550
|
+
outputLimitBytes: args.outputLimitBytes,
|
|
4551
|
+
metadata: deps.metadata
|
|
4216
4552
|
});
|
|
4217
4553
|
return stringifyStarted(state.id, state.status, args.command);
|
|
4218
4554
|
} catch (error) {
|
|
@@ -4469,7 +4805,7 @@ function createBlockedResult(report) {
|
|
|
4469
4805
|
}
|
|
4470
4806
|
|
|
4471
4807
|
// src/assembly/create-session.ts
|
|
4472
|
-
var
|
|
4808
|
+
var import_agent_runtime7 = require("@robota-sdk/agent-runtime");
|
|
4473
4809
|
|
|
4474
4810
|
// src/agents/agent-definition-loader.ts
|
|
4475
4811
|
var import_node_fs4 = require("fs");
|
|
@@ -4722,7 +5058,7 @@ function createSession(options) {
|
|
|
4722
5058
|
customAgentRegistry: (name) => agentLoader.getAgent(name),
|
|
4723
5059
|
agentDefinitions
|
|
4724
5060
|
};
|
|
4725
|
-
const subagentManager = new
|
|
5061
|
+
const subagentManager = new import_agent_runtime7.SubagentManager({
|
|
4726
5062
|
runner: (options.subagentRunnerFactory ?? createInProcessSubagentRunner)(agentToolDeps),
|
|
4727
5063
|
backgroundTaskRunners: options.backgroundTaskRunners
|
|
4728
5064
|
});
|
|
@@ -4730,7 +5066,7 @@ function createSession(options) {
|
|
|
4730
5066
|
backgroundTaskManager = subagentManager.getBackgroundTaskManager();
|
|
4731
5067
|
agentToolDeps.backgroundTaskManager = backgroundTaskManager;
|
|
4732
5068
|
} else {
|
|
4733
|
-
backgroundTaskManager = new
|
|
5069
|
+
backgroundTaskManager = new import_agent_runtime7.BackgroundTaskManager({
|
|
4734
5070
|
runners: options.backgroundTaskRunners ?? []
|
|
4735
5071
|
});
|
|
4736
5072
|
}
|
|
@@ -4755,7 +5091,12 @@ function createSession(options) {
|
|
|
4755
5091
|
backgroundProcessToolDeps = {
|
|
4756
5092
|
backgroundTaskManager,
|
|
4757
5093
|
cwd,
|
|
4758
|
-
parentSessionId: sessionId
|
|
5094
|
+
parentSessionId: sessionId,
|
|
5095
|
+
metadata: createExecutionOriginMetadata({
|
|
5096
|
+
kind: "tool_call",
|
|
5097
|
+
sessionId,
|
|
5098
|
+
label: "BackgroundProcess"
|
|
5099
|
+
})
|
|
4759
5100
|
};
|
|
4760
5101
|
tools.push(createBackgroundProcessTool(backgroundProcessToolDeps));
|
|
4761
5102
|
}
|
|
@@ -5031,7 +5372,7 @@ function formatTaskContext(tasks) {
|
|
|
5031
5372
|
}
|
|
5032
5373
|
function loadTaskContext(cwd, options = {}) {
|
|
5033
5374
|
const currentBranch = options.currentBranch ?? readCurrentGitBranch(cwd);
|
|
5034
|
-
const tasks = discoverTaskFiles(cwd).map((
|
|
5375
|
+
const tasks = discoverTaskFiles(cwd).map((path3) => parseTaskFile(path3, cwd));
|
|
5035
5376
|
return formatTaskContext(selectRelevantTasks(tasks, { ...options, currentBranch }));
|
|
5036
5377
|
}
|
|
5037
5378
|
function updateTaskFileStatus(taskPath, status, options = {}) {
|
|
@@ -5378,15 +5719,11 @@ var BundlePluginLoader = class {
|
|
|
5378
5719
|
}
|
|
5379
5720
|
return results;
|
|
5380
5721
|
}
|
|
5381
|
-
/** Read and validate a plugin.json manifest. Returns null
|
|
5382
|
-
readManifest(
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
return validateManifest(data);
|
|
5387
|
-
} catch {
|
|
5388
|
-
return null;
|
|
5389
|
-
}
|
|
5722
|
+
/** Read and validate a plugin.json manifest. Returns null if the manifest structure is invalid. */
|
|
5723
|
+
readManifest(path3) {
|
|
5724
|
+
const raw = (0, import_node_fs9.readFileSync)(path3, "utf-8");
|
|
5725
|
+
const data = JSON.parse(raw);
|
|
5726
|
+
return validateManifest(data);
|
|
5390
5727
|
}
|
|
5391
5728
|
/**
|
|
5392
5729
|
* Check if a plugin is explicitly disabled.
|
|
@@ -5462,40 +5799,26 @@ var BundlePluginLoader = class {
|
|
|
5462
5799
|
loadHooks(pluginDir) {
|
|
5463
5800
|
const hooksPath = (0, import_node_path11.join)(pluginDir, "hooks", "hooks.json");
|
|
5464
5801
|
if (!(0, import_node_fs9.existsSync)(hooksPath)) return {};
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
return data;
|
|
5470
|
-
}
|
|
5471
|
-
return {};
|
|
5472
|
-
} catch {
|
|
5473
|
-
return {};
|
|
5802
|
+
const raw = (0, import_node_fs9.readFileSync)(hooksPath, "utf-8");
|
|
5803
|
+
const data = JSON.parse(raw);
|
|
5804
|
+
if (typeof data === "object" && data !== null) {
|
|
5805
|
+
return data;
|
|
5474
5806
|
}
|
|
5807
|
+
return {};
|
|
5475
5808
|
}
|
|
5476
|
-
/** Load MCP server configuration
|
|
5809
|
+
/** Load MCP server configuration from `.mcp.json` at the plugin root if present. */
|
|
5477
5810
|
loadMcpConfig(pluginDir) {
|
|
5478
|
-
const
|
|
5479
|
-
const fallbackPath = (0, import_node_path11.join)(pluginDir, ".claude-plugin", "mcp.json");
|
|
5480
|
-
const mcpPath = (0, import_node_fs9.existsSync)(primaryPath) ? primaryPath : fallbackPath;
|
|
5811
|
+
const mcpPath = (0, import_node_path11.join)(pluginDir, ".mcp.json");
|
|
5481
5812
|
if (!(0, import_node_fs9.existsSync)(mcpPath)) return void 0;
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
return JSON.parse(raw);
|
|
5485
|
-
} catch {
|
|
5486
|
-
return void 0;
|
|
5487
|
-
}
|
|
5813
|
+
const raw = (0, import_node_fs9.readFileSync)(mcpPath, "utf-8");
|
|
5814
|
+
return JSON.parse(raw);
|
|
5488
5815
|
}
|
|
5489
5816
|
/** Load agent definitions from agents/ directory if present. */
|
|
5490
5817
|
loadAgents(pluginDir) {
|
|
5491
5818
|
const agentsDir = (0, import_node_path11.join)(pluginDir, "agents");
|
|
5492
5819
|
if (!(0, import_node_fs9.existsSync)(agentsDir)) return [];
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
return entries.filter((e) => e.isDirectory() || e.name.endsWith(".md")).map((e) => e.name.replace(/\.md$/, ""));
|
|
5496
|
-
} catch {
|
|
5497
|
-
return [];
|
|
5498
|
-
}
|
|
5820
|
+
const entries = (0, import_node_fs9.readdirSync)(agentsDir, { withFileTypes: true });
|
|
5821
|
+
return entries.filter((e) => e.isDirectory() || e.name.endsWith(".md")).map((e) => e.name.replace(/\.md$/, ""));
|
|
5499
5822
|
}
|
|
5500
5823
|
};
|
|
5501
5824
|
|
|
@@ -5939,8 +6262,8 @@ var MarketplaceClient = class {
|
|
|
5939
6262
|
}
|
|
5940
6263
|
}
|
|
5941
6264
|
/** Read and parse a marketplace.json from a file path. */
|
|
5942
|
-
readManifestFromPath(
|
|
5943
|
-
const raw = (0, import_node_fs12.readFileSync)(
|
|
6265
|
+
readManifestFromPath(path3) {
|
|
6266
|
+
const raw = (0, import_node_fs12.readFileSync)(path3, "utf-8");
|
|
5944
6267
|
const data = JSON.parse(raw);
|
|
5945
6268
|
if (typeof data !== "object" || data === null) {
|
|
5946
6269
|
throw new Error("Invalid marketplace manifest: not an object");
|
|
@@ -6032,18 +6355,18 @@ async function createInteractiveSession(options) {
|
|
|
6032
6355
|
options.bare ? Promise.resolve({ agentsMd: "", claudeMd: "" }) : loadContext(cwd),
|
|
6033
6356
|
options.bare ? Promise.resolve({ type: "unknown", language: "unknown" }) : detectProject(cwd)
|
|
6034
6357
|
]);
|
|
6358
|
+
let mergedConfig = options.language ? { ...config, language: options.language } : config;
|
|
6035
6359
|
const pluginsDir = (0, import_node_path16.join)((0, import_node_os5.homedir)(), ".robota", "plugins");
|
|
6036
6360
|
const pluginLoader = new BundlePluginLoader(pluginsDir);
|
|
6037
|
-
let mergedConfig = config;
|
|
6038
6361
|
if (!options.bare) {
|
|
6039
6362
|
try {
|
|
6040
6363
|
const plugins = pluginLoader.loadPluginsSync();
|
|
6041
6364
|
if (plugins.length > 0) {
|
|
6042
6365
|
const pluginHooks = mergePluginHooks(plugins);
|
|
6043
6366
|
mergedConfig = {
|
|
6044
|
-
...
|
|
6367
|
+
...mergedConfig,
|
|
6045
6368
|
hooks: mergeHooksIntoConfig(
|
|
6046
|
-
|
|
6369
|
+
mergedConfig.hooks,
|
|
6047
6370
|
pluginHooks
|
|
6048
6371
|
)
|
|
6049
6372
|
};
|
|
@@ -6211,8 +6534,8 @@ function isRestoredTerminalStatus(status) {
|
|
|
6211
6534
|
}
|
|
6212
6535
|
|
|
6213
6536
|
// src/interactive/interactive-session-context-references.ts
|
|
6214
|
-
async function addInteractiveContextReference(references,
|
|
6215
|
-
const result = await resolvePromptFileReferencePaths([
|
|
6537
|
+
async function addInteractiveContextReference(references, path3, cwd) {
|
|
6538
|
+
const result = await resolvePromptFileReferencePaths([path3], {
|
|
6216
6539
|
cwd,
|
|
6217
6540
|
reason: "manual"
|
|
6218
6541
|
});
|
|
@@ -6305,9 +6628,9 @@ function toInspectionPlan(manifests) {
|
|
|
6305
6628
|
fileCount: manifests.reduce((count, manifest) => count + manifest.fileCount, 0)
|
|
6306
6629
|
};
|
|
6307
6630
|
}
|
|
6308
|
-
function statSafe(
|
|
6631
|
+
function statSafe(path3) {
|
|
6309
6632
|
try {
|
|
6310
|
-
return (0, import_node_fs13.statSync)(
|
|
6633
|
+
return (0, import_node_fs13.statSync)(path3);
|
|
6311
6634
|
} catch {
|
|
6312
6635
|
return void 0;
|
|
6313
6636
|
}
|
|
@@ -6478,10 +6801,10 @@ var EditCheckpointStore = class {
|
|
|
6478
6801
|
}
|
|
6479
6802
|
async writeManifest(dir, manifest) {
|
|
6480
6803
|
await (0, import_promises2.mkdir)(dir, { recursive: true });
|
|
6481
|
-
const
|
|
6482
|
-
const tmp = `${
|
|
6804
|
+
const path3 = (0, import_node_path18.join)(dir, MANIFEST_FILE);
|
|
6805
|
+
const tmp = `${path3}.tmp`;
|
|
6483
6806
|
await (0, import_promises2.writeFile)(tmp, JSON.stringify(manifest, null, 2), "utf8");
|
|
6484
|
-
await (0, import_promises2.rename)(tmp,
|
|
6807
|
+
await (0, import_promises2.rename)(tmp, path3);
|
|
6485
6808
|
}
|
|
6486
6809
|
sessionDir(sessionId) {
|
|
6487
6810
|
return (0, import_node_path18.join)(this.rootDir, safePathSegment(sessionId));
|
|
@@ -6507,9 +6830,9 @@ function isInside(parent, child) {
|
|
|
6507
6830
|
const rel = (0, import_node_path18.relative)(parent, child);
|
|
6508
6831
|
return rel.length === 0 || !rel.startsWith("..") && !rel.startsWith("/");
|
|
6509
6832
|
}
|
|
6510
|
-
async function pathExists(
|
|
6833
|
+
async function pathExists(path3) {
|
|
6511
6834
|
try {
|
|
6512
|
-
await (0, import_promises2.access)(
|
|
6835
|
+
await (0, import_promises2.access)(path3, import_node_fs14.constants.F_OK);
|
|
6513
6836
|
return true;
|
|
6514
6837
|
} catch {
|
|
6515
6838
|
return false;
|
|
@@ -6522,9 +6845,9 @@ function readDirSyncSafe(dir) {
|
|
|
6522
6845
|
return [];
|
|
6523
6846
|
}
|
|
6524
6847
|
}
|
|
6525
|
-
function readJsonManifest(
|
|
6848
|
+
function readJsonManifest(path3) {
|
|
6526
6849
|
try {
|
|
6527
|
-
const raw = (0, import_node_fs14.readFileSync)(
|
|
6850
|
+
const raw = (0, import_node_fs14.readFileSync)(path3, "utf8");
|
|
6528
6851
|
return JSON.parse(raw);
|
|
6529
6852
|
} catch {
|
|
6530
6853
|
return void 0;
|
|
@@ -6547,6 +6870,11 @@ function getQualifiedSkillName(rawInput) {
|
|
|
6547
6870
|
const firstToken = rawInput.slice(1).trim().split(/\s+/)[0];
|
|
6548
6871
|
return firstToken && firstToken.length > 0 ? firstToken : void 0;
|
|
6549
6872
|
}
|
|
6873
|
+
function getBackgroundTaskEventEntryId(event) {
|
|
6874
|
+
if ("task" in event) return createBackgroundTaskExecutionEntryId(event.task.id);
|
|
6875
|
+
if ("taskId" in event) return createBackgroundTaskExecutionEntryId(event.taskId);
|
|
6876
|
+
return void 0;
|
|
6877
|
+
}
|
|
6550
6878
|
var InteractiveSession = class {
|
|
6551
6879
|
session = null;
|
|
6552
6880
|
commandExecutor;
|
|
@@ -6664,6 +6992,7 @@ var InteractiveSession = class {
|
|
|
6664
6992
|
bare: options.bare,
|
|
6665
6993
|
allowedTools: options.allowedTools,
|
|
6666
6994
|
appendSystemPrompt: options.appendSystemPrompt,
|
|
6995
|
+
language: options.language,
|
|
6667
6996
|
backgroundTaskRunners: options.backgroundTaskRunners,
|
|
6668
6997
|
subagentRunnerFactory: options.subagentRunnerFactory,
|
|
6669
6998
|
...options.commandModules ? { commandModules: options.commandModules } : {},
|
|
@@ -6695,6 +7024,9 @@ var InteractiveSession = class {
|
|
|
6695
7024
|
throw new Error("InteractiveSession not initialized. Call submit() or await initialization.");
|
|
6696
7025
|
return this.session;
|
|
6697
7026
|
}
|
|
7027
|
+
get sessionId() {
|
|
7028
|
+
return this.session?.getSessionId() ?? "";
|
|
7029
|
+
}
|
|
6698
7030
|
on(event, handler) {
|
|
6699
7031
|
if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
6700
7032
|
this.listeners.get(event).add(handler);
|
|
@@ -6906,6 +7238,9 @@ var InteractiveSession = class {
|
|
|
6906
7238
|
getActiveTools() {
|
|
6907
7239
|
return this.activeTools;
|
|
6908
7240
|
}
|
|
7241
|
+
get isInitialized() {
|
|
7242
|
+
return this.initialized;
|
|
7243
|
+
}
|
|
6909
7244
|
getContextState() {
|
|
6910
7245
|
return this.getSessionOrThrow().getContextState();
|
|
6911
7246
|
}
|
|
@@ -6990,18 +7325,18 @@ var InteractiveSession = class {
|
|
|
6990
7325
|
listContextReferences() {
|
|
6991
7326
|
return [...this.contextReferences];
|
|
6992
7327
|
}
|
|
6993
|
-
async addContextReference(
|
|
7328
|
+
async addContextReference(path3) {
|
|
6994
7329
|
const { references, result } = await addInteractiveContextReference(
|
|
6995
7330
|
this.contextReferences,
|
|
6996
|
-
|
|
7331
|
+
path3,
|
|
6997
7332
|
this.getCwd()
|
|
6998
7333
|
);
|
|
6999
7334
|
this.contextReferences = references;
|
|
7000
7335
|
this.persistCurrentSession();
|
|
7001
7336
|
return result;
|
|
7002
7337
|
}
|
|
7003
|
-
removeContextReference(
|
|
7004
|
-
const result = removeContextReference(this.contextReferences,
|
|
7338
|
+
removeContextReference(path3) {
|
|
7339
|
+
const result = removeContextReference(this.contextReferences, path3);
|
|
7005
7340
|
this.contextReferences = result.references;
|
|
7006
7341
|
this.persistCurrentSession();
|
|
7007
7342
|
return result.result;
|
|
@@ -7051,6 +7386,53 @@ var InteractiveSession = class {
|
|
|
7051
7386
|
await this.ensureInitialized();
|
|
7052
7387
|
return this.getBackgroundJobOrchestratorOrThrow().waitGroup(groupId);
|
|
7053
7388
|
}
|
|
7389
|
+
getExecutionWorkspaceSnapshot(options = {}) {
|
|
7390
|
+
const session = this.getSessionOrThrow();
|
|
7391
|
+
const sessionId = session.getSessionId();
|
|
7392
|
+
return createExecutionWorkspaceSnapshot({
|
|
7393
|
+
sessionId,
|
|
7394
|
+
mainThread: {
|
|
7395
|
+
sessionId,
|
|
7396
|
+
isExecuting: this.executing,
|
|
7397
|
+
hasPendingPrompt: this.pendingPrompt !== null,
|
|
7398
|
+
historyLength: this.history.length,
|
|
7399
|
+
updatedAt: this.getMainThreadUpdatedAt(),
|
|
7400
|
+
preview: this.getMainThreadPreview()
|
|
7401
|
+
},
|
|
7402
|
+
tasks: this.getBackgroundTaskSnapshots(),
|
|
7403
|
+
groups: this.getBackgroundJobGroupSnapshots(),
|
|
7404
|
+
selectedEntryId: options.selectedEntryId,
|
|
7405
|
+
filter: options.filter
|
|
7406
|
+
});
|
|
7407
|
+
}
|
|
7408
|
+
listExecutionWorkspaceEntries(filter) {
|
|
7409
|
+
return [...this.getExecutionWorkspaceSnapshot({ filter }).entries];
|
|
7410
|
+
}
|
|
7411
|
+
getExecutionWorkspaceEntry(entryId) {
|
|
7412
|
+
return this.getExecutionWorkspaceSnapshot().entries.find((entry) => entry.id === entryId);
|
|
7413
|
+
}
|
|
7414
|
+
async readExecutionWorkspaceDetail(entryId, cursor) {
|
|
7415
|
+
await this.ensureInitialized();
|
|
7416
|
+
const entryRef = parseExecutionWorkspaceEntryId(entryId);
|
|
7417
|
+
if (!entryRef) throw new Error(`Unknown execution workspace entry: ${entryId}`);
|
|
7418
|
+
if (entryRef.kind === "main_thread") {
|
|
7419
|
+
return createMainThreadDetailPage({ entryId, history: this.history, cursor });
|
|
7420
|
+
}
|
|
7421
|
+
if (entryRef.kind === "background_group") {
|
|
7422
|
+
return this.readBackgroundGroupDetail(entryId, entryRef.sourceId);
|
|
7423
|
+
}
|
|
7424
|
+
return this.readBackgroundTaskDetail(entryId, entryRef.sourceId, cursor);
|
|
7425
|
+
}
|
|
7426
|
+
createExecutionWorkspaceTaskSpawner(origin) {
|
|
7427
|
+
const sessionId = this.getSessionOrThrow().getSessionId();
|
|
7428
|
+
return createExecutionWorkspaceTaskSpawner({
|
|
7429
|
+
manager: this.getBackgroundTaskManagerOrThrow(),
|
|
7430
|
+
groupOrchestrator: this.getBackgroundJobOrchestratorOrThrow(),
|
|
7431
|
+
sessionId,
|
|
7432
|
+
cwd: this.getCwd(),
|
|
7433
|
+
origin: { ...origin, sessionId: origin.sessionId || sessionId }
|
|
7434
|
+
});
|
|
7435
|
+
}
|
|
7054
7436
|
listAgentDefinitions() {
|
|
7055
7437
|
const deps = retrieveAgentToolDeps(this.getSessionOrThrow());
|
|
7056
7438
|
return (deps?.agentDefinitions ?? []).map((agent) => ({
|
|
@@ -7065,10 +7447,11 @@ var InteractiveSession = class {
|
|
|
7065
7447
|
await this.ensureInitialized();
|
|
7066
7448
|
const deps = this.getAgentToolDepsOrThrow();
|
|
7067
7449
|
const definition = this.resolveAgentDefinition(input.agentType, deps);
|
|
7450
|
+
const sessionId = this.getSessionOrThrow().getSessionId();
|
|
7068
7451
|
return this.getSubagentManagerOrThrow().spawn({
|
|
7069
7452
|
type: input.agentType,
|
|
7070
7453
|
label: input.label,
|
|
7071
|
-
parentSessionId:
|
|
7454
|
+
parentSessionId: sessionId,
|
|
7072
7455
|
mode: input.mode,
|
|
7073
7456
|
depth: (deps.subagentDepth ?? 0) + 1,
|
|
7074
7457
|
cwd: deps.cwd ?? this.cwd ?? process.cwd(),
|
|
@@ -7076,7 +7459,13 @@ var InteractiveSession = class {
|
|
|
7076
7459
|
model: input.model ?? definition.model,
|
|
7077
7460
|
isolation: input.isolation,
|
|
7078
7461
|
allowedTools: definition.tools,
|
|
7079
|
-
disallowedTools: definition.disallowedTools
|
|
7462
|
+
disallowedTools: definition.disallowedTools,
|
|
7463
|
+
metadata: createExecutionOriginMetadata({
|
|
7464
|
+
kind: this.commandInvocationSource === "model" ? "model_command" : "slash_command",
|
|
7465
|
+
sessionId,
|
|
7466
|
+
commandName: "agent",
|
|
7467
|
+
label: input.label
|
|
7468
|
+
})
|
|
7080
7469
|
});
|
|
7081
7470
|
}
|
|
7082
7471
|
async waitAgentJob(jobId) {
|
|
@@ -7179,6 +7568,51 @@ var InteractiveSession = class {
|
|
|
7179
7568
|
this.finishForkSkillExecution();
|
|
7180
7569
|
}
|
|
7181
7570
|
}
|
|
7571
|
+
async readBackgroundTaskDetail(entryId, taskId, cursor) {
|
|
7572
|
+
const task = this.getBackgroundTaskManagerOrThrow().get(taskId);
|
|
7573
|
+
if (!task) throw new Error(`Unknown background task: ${taskId}`);
|
|
7574
|
+
if (task.logPath || task.transcriptPath) {
|
|
7575
|
+
const page = await this.getBackgroundTaskManagerOrThrow().readLog(taskId, cursor);
|
|
7576
|
+
return createLineDetailPage({
|
|
7577
|
+
entryId,
|
|
7578
|
+
lines: page.lines,
|
|
7579
|
+
cursor: page.cursor,
|
|
7580
|
+
nextCursor: page.nextCursor,
|
|
7581
|
+
kind: task.kind === "process" ? "process_output" : "progress"
|
|
7582
|
+
});
|
|
7583
|
+
}
|
|
7584
|
+
const detailKind = task.status === "failed" ? "error" : task.status === "completed" ? "result" : "progress";
|
|
7585
|
+
const text = task.error?.message ?? task.result?.output ?? task.currentAction ?? task.promptPreview ?? task.commandPreview ?? task.status;
|
|
7586
|
+
return createLineDetailPage({ entryId, lines: [text], cursor, kind: detailKind });
|
|
7587
|
+
}
|
|
7588
|
+
readBackgroundGroupDetail(entryId, groupId) {
|
|
7589
|
+
const group = this.getBackgroundJobOrchestratorOrThrow().getGroup(groupId);
|
|
7590
|
+
if (!group) throw new Error(`Unknown background job group: ${groupId}`);
|
|
7591
|
+
const summary = summarizeBackgroundJobGroup(group);
|
|
7592
|
+
return createLineDetailPage({
|
|
7593
|
+
entryId,
|
|
7594
|
+
lines: summary.lines,
|
|
7595
|
+
kind: "group_summary"
|
|
7596
|
+
});
|
|
7597
|
+
}
|
|
7598
|
+
getMainThreadUpdatedAt() {
|
|
7599
|
+
return this.history.at(-1)?.timestamp.toISOString() ?? (/* @__PURE__ */ new Date(0)).toISOString();
|
|
7600
|
+
}
|
|
7601
|
+
getMainThreadPreview() {
|
|
7602
|
+
if (this.streamingText.trim().length > 0) return this.streamingText;
|
|
7603
|
+
const latest = this.history.at(-1);
|
|
7604
|
+
if (!latest) return void 0;
|
|
7605
|
+
return latest.type;
|
|
7606
|
+
}
|
|
7607
|
+
emitExecutionWorkspaceUpdated(cause, entryId) {
|
|
7608
|
+
if (!this.session) return;
|
|
7609
|
+
this.emit("execution_workspace_event", {
|
|
7610
|
+
type: "execution_workspace_updated",
|
|
7611
|
+
cause,
|
|
7612
|
+
...entryId ? { entryId } : {},
|
|
7613
|
+
snapshot: this.getExecutionWorkspaceSnapshot()
|
|
7614
|
+
});
|
|
7615
|
+
}
|
|
7182
7616
|
getBackgroundTaskManagerOrThrow() {
|
|
7183
7617
|
const manager = this.getBackgroundTaskManager();
|
|
7184
7618
|
if (!manager) {
|
|
@@ -7244,11 +7678,16 @@ var InteractiveSession = class {
|
|
|
7244
7678
|
this.backgroundTasks = this.getBackgroundTaskSnapshots();
|
|
7245
7679
|
this.backgroundTaskEvents.push(event);
|
|
7246
7680
|
this.persistCurrentSession();
|
|
7681
|
+
this.emitExecutionWorkspaceUpdated("background_task", getBackgroundTaskEventEntryId(event));
|
|
7247
7682
|
}
|
|
7248
7683
|
recordBackgroundJobGroupEvent(event) {
|
|
7249
7684
|
this.backgroundJobGroups = this.getBackgroundJobGroupSnapshots();
|
|
7250
7685
|
this.backgroundJobGroupEvents.push(event);
|
|
7251
7686
|
this.persistCurrentSession();
|
|
7687
|
+
this.emitExecutionWorkspaceUpdated(
|
|
7688
|
+
"background_group",
|
|
7689
|
+
createBackgroundGroupExecutionEntryId(event.group.id)
|
|
7690
|
+
);
|
|
7252
7691
|
}
|
|
7253
7692
|
getBackgroundTaskSnapshots() {
|
|
7254
7693
|
try {
|
|
@@ -7312,10 +7751,12 @@ var InteractiveSession = class {
|
|
|
7312
7751
|
this.clearStreaming();
|
|
7313
7752
|
this.emit("thinking", true);
|
|
7314
7753
|
this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createUserMessage)(displayInput)));
|
|
7754
|
+
this.emitExecutionWorkspaceUpdated("main_thread");
|
|
7315
7755
|
}
|
|
7316
7756
|
finishForkSkillExecution() {
|
|
7317
7757
|
this.executing = false;
|
|
7318
7758
|
this.emit("thinking", false);
|
|
7759
|
+
this.emitExecutionWorkspaceUpdated("main_thread");
|
|
7319
7760
|
this.persistCurrentSession();
|
|
7320
7761
|
if (!this.shuttingDown && this.pendingPrompt) {
|
|
7321
7762
|
const queued = this.pendingPrompt;
|
|
@@ -7385,6 +7826,7 @@ var InteractiveSession = class {
|
|
|
7385
7826
|
this.executing = true;
|
|
7386
7827
|
this.clearStreaming();
|
|
7387
7828
|
this.emit("thinking", true);
|
|
7829
|
+
this.emitExecutionWorkspaceUpdated("main_thread");
|
|
7388
7830
|
try {
|
|
7389
7831
|
const result = await this.commandExecutor.executeCommand(command, this, args);
|
|
7390
7832
|
this.emit("context_update", this.getContextState());
|
|
@@ -7398,6 +7840,7 @@ var InteractiveSession = class {
|
|
|
7398
7840
|
} finally {
|
|
7399
7841
|
this.executing = false;
|
|
7400
7842
|
this.emit("thinking", false);
|
|
7843
|
+
this.emitExecutionWorkspaceUpdated("main_thread");
|
|
7401
7844
|
this.persistCurrentSession();
|
|
7402
7845
|
if (!this.shuttingDown && this.pendingPrompt) {
|
|
7403
7846
|
const queued = this.pendingPrompt;
|
|
@@ -7411,8 +7854,10 @@ var InteractiveSession = class {
|
|
|
7411
7854
|
async executePrompt(input, displayInput, rawInput) {
|
|
7412
7855
|
this.executing = true;
|
|
7413
7856
|
this.clearStreaming();
|
|
7857
|
+
this.emit("user_message", displayInput ?? input);
|
|
7414
7858
|
this.emit("thinking", true);
|
|
7415
7859
|
this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createUserMessage)(displayInput ?? input)));
|
|
7860
|
+
this.emitExecutionWorkspaceUpdated("main_thread");
|
|
7416
7861
|
const historyBefore = this.getSessionOrThrow().getHistory().length;
|
|
7417
7862
|
this.usedMemoryReferences = [];
|
|
7418
7863
|
try {
|
|
@@ -7474,6 +7919,7 @@ var InteractiveSession = class {
|
|
|
7474
7919
|
await this.finalizeEditCheckpointTurn();
|
|
7475
7920
|
this.executing = false;
|
|
7476
7921
|
this.emit("thinking", false);
|
|
7922
|
+
this.emitExecutionWorkspaceUpdated("main_thread");
|
|
7477
7923
|
this.persistCurrentSession();
|
|
7478
7924
|
if (!this.shuttingDown && this.pendingPrompt) {
|
|
7479
7925
|
const queued = this.pendingPrompt;
|
|
@@ -7768,6 +8214,404 @@ function createQuery(options) {
|
|
|
7768
8214
|
};
|
|
7769
8215
|
}
|
|
7770
8216
|
|
|
8217
|
+
// src/user-local/storage.ts
|
|
8218
|
+
var import_node_fs16 = require("fs");
|
|
8219
|
+
var import_node_os6 = require("os");
|
|
8220
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
8221
|
+
var USER_LOCAL_STORAGE_CATEGORIES = [
|
|
8222
|
+
"preferences",
|
|
8223
|
+
"view-state",
|
|
8224
|
+
"memory-projections",
|
|
8225
|
+
"task-associations",
|
|
8226
|
+
"workflow-metadata",
|
|
8227
|
+
"inspection-index"
|
|
8228
|
+
];
|
|
8229
|
+
var USER_LOCAL_STORAGE_CATEGORY_DEFINITIONS = [
|
|
8230
|
+
{
|
|
8231
|
+
category: "preferences",
|
|
8232
|
+
purpose: "User-local UI and display preferences.",
|
|
8233
|
+
mayExecuteCommands: false
|
|
8234
|
+
},
|
|
8235
|
+
{
|
|
8236
|
+
category: "view-state",
|
|
8237
|
+
purpose: "Last selected panels, filters, and navigation state.",
|
|
8238
|
+
mayExecuteCommands: false
|
|
8239
|
+
},
|
|
8240
|
+
{
|
|
8241
|
+
category: "memory-projections",
|
|
8242
|
+
purpose: "Inspectable local memory item projections and user choices.",
|
|
8243
|
+
mayExecuteCommands: false
|
|
8244
|
+
},
|
|
8245
|
+
{
|
|
8246
|
+
category: "task-associations",
|
|
8247
|
+
purpose: "User-local associations between sessions, tasks, and background items.",
|
|
8248
|
+
mayExecuteCommands: false
|
|
8249
|
+
},
|
|
8250
|
+
{
|
|
8251
|
+
category: "workflow-metadata",
|
|
8252
|
+
purpose: "Transparent workflow metadata that is not repo-owned.",
|
|
8253
|
+
mayExecuteCommands: false
|
|
8254
|
+
},
|
|
8255
|
+
{
|
|
8256
|
+
category: "inspection-index",
|
|
8257
|
+
purpose: "Category and item summaries for user inspection and deletion.",
|
|
8258
|
+
mayExecuteCommands: false
|
|
8259
|
+
}
|
|
8260
|
+
];
|
|
8261
|
+
function formatIsoDate(date) {
|
|
8262
|
+
return date.toISOString();
|
|
8263
|
+
}
|
|
8264
|
+
function assertAbsolutePath(name, value) {
|
|
8265
|
+
if (value.trim().length === 0) {
|
|
8266
|
+
throw new Error(`${name} must not be empty.`);
|
|
8267
|
+
}
|
|
8268
|
+
if (!import_node_path20.default.isAbsolute(value)) {
|
|
8269
|
+
throw new Error(`${name} must be an absolute path: ${value}`);
|
|
8270
|
+
}
|
|
8271
|
+
}
|
|
8272
|
+
function resolveDefaultHomeDir() {
|
|
8273
|
+
return process.env.HOME ?? (0, import_node_os6.homedir)();
|
|
8274
|
+
}
|
|
8275
|
+
function isEqualOrInside(parentPath, candidatePath) {
|
|
8276
|
+
const relative4 = import_node_path20.default.relative(parentPath, candidatePath);
|
|
8277
|
+
return relative4 === "" || !relative4.startsWith("..") && !import_node_path20.default.isAbsolute(relative4);
|
|
8278
|
+
}
|
|
8279
|
+
async function resolveForComparison(absPath) {
|
|
8280
|
+
let current = absPath;
|
|
8281
|
+
while (import_node_path20.default.dirname(current) !== current) {
|
|
8282
|
+
try {
|
|
8283
|
+
const realCurrent = await import_node_fs16.promises.realpath(current);
|
|
8284
|
+
const relativeMissingPath = import_node_path20.default.relative(current, absPath);
|
|
8285
|
+
return import_node_path20.default.resolve(realCurrent, relativeMissingPath);
|
|
8286
|
+
} catch {
|
|
8287
|
+
current = import_node_path20.default.dirname(current);
|
|
8288
|
+
}
|
|
8289
|
+
}
|
|
8290
|
+
try {
|
|
8291
|
+
return await import_node_fs16.promises.realpath(current);
|
|
8292
|
+
} catch {
|
|
8293
|
+
return import_node_path20.default.resolve(absPath);
|
|
8294
|
+
}
|
|
8295
|
+
}
|
|
8296
|
+
async function resolveUserLocalStorageRoot(options) {
|
|
8297
|
+
const activeRepositoryRoot = import_node_path20.default.resolve(options.activeRepositoryRoot);
|
|
8298
|
+
assertAbsolutePath("activeRepositoryRoot", activeRepositoryRoot);
|
|
8299
|
+
const candidateRoot = options.storageRoot !== void 0 ? options.storageRoot : import_node_path20.default.join(options.homeDir ?? resolveDefaultHomeDir(), ".robota");
|
|
8300
|
+
assertAbsolutePath("userLocalStorageRoot", candidateRoot);
|
|
8301
|
+
const resolvedRoot = import_node_path20.default.resolve(candidateRoot);
|
|
8302
|
+
const comparableRoot = await resolveForComparison(resolvedRoot);
|
|
8303
|
+
const comparableRepositoryRoot = await resolveForComparison(activeRepositoryRoot);
|
|
8304
|
+
if (isEqualOrInside(comparableRepositoryRoot, comparableRoot)) {
|
|
8305
|
+
throw new Error(
|
|
8306
|
+
`User-local storage root must be outside the active repository: ${resolvedRoot}`
|
|
8307
|
+
);
|
|
8308
|
+
}
|
|
8309
|
+
return resolvedRoot;
|
|
8310
|
+
}
|
|
8311
|
+
function resolveCategoryLocation(root, category) {
|
|
8312
|
+
return import_node_path20.default.join(root, category);
|
|
8313
|
+
}
|
|
8314
|
+
async function listItemSummaries(root, category) {
|
|
8315
|
+
const storageLocation = resolveCategoryLocation(root, category);
|
|
8316
|
+
let entries;
|
|
8317
|
+
try {
|
|
8318
|
+
entries = await import_node_fs16.promises.readdir(storageLocation, { withFileTypes: true });
|
|
8319
|
+
} catch {
|
|
8320
|
+
return [];
|
|
8321
|
+
}
|
|
8322
|
+
const summaries = await Promise.all(
|
|
8323
|
+
entries.map(async (entry) => {
|
|
8324
|
+
const itemLocation = import_node_path20.default.join(storageLocation, entry.name);
|
|
8325
|
+
const stats = await import_node_fs16.promises.stat(itemLocation);
|
|
8326
|
+
const key = entry.name;
|
|
8327
|
+
return {
|
|
8328
|
+
root,
|
|
8329
|
+
category,
|
|
8330
|
+
key,
|
|
8331
|
+
summary: `${category}/${key}`,
|
|
8332
|
+
source: "user-local-storage",
|
|
8333
|
+
scope: "user",
|
|
8334
|
+
storageLocation: itemLocation,
|
|
8335
|
+
createdAt: formatIsoDate(stats.birthtime),
|
|
8336
|
+
lastUsedAt: formatIsoDate(stats.mtime),
|
|
8337
|
+
enabled: true,
|
|
8338
|
+
deleteAvailable: true,
|
|
8339
|
+
disableAvailable: false
|
|
8340
|
+
};
|
|
8341
|
+
})
|
|
8342
|
+
);
|
|
8343
|
+
return summaries.sort((left, right) => left.key.localeCompare(right.key));
|
|
8344
|
+
}
|
|
8345
|
+
async function inspectUserLocalStorage(options) {
|
|
8346
|
+
const root = await resolveUserLocalStorageRoot(options);
|
|
8347
|
+
const activeRepositoryRoot = import_node_path20.default.resolve(options.activeRepositoryRoot);
|
|
8348
|
+
const createDirectories = options.createDirectories ?? true;
|
|
8349
|
+
if (createDirectories) {
|
|
8350
|
+
await import_node_fs16.promises.mkdir(root, { recursive: true });
|
|
8351
|
+
}
|
|
8352
|
+
const categories = await Promise.all(
|
|
8353
|
+
USER_LOCAL_STORAGE_CATEGORY_DEFINITIONS.map(
|
|
8354
|
+
async (definition) => {
|
|
8355
|
+
const storageLocation = resolveCategoryLocation(root, definition.category);
|
|
8356
|
+
if (createDirectories) {
|
|
8357
|
+
await import_node_fs16.promises.mkdir(storageLocation, { recursive: true });
|
|
8358
|
+
}
|
|
8359
|
+
const items = await listItemSummaries(root, definition.category);
|
|
8360
|
+
return {
|
|
8361
|
+
category: definition.category,
|
|
8362
|
+
purpose: definition.purpose,
|
|
8363
|
+
mayExecuteCommands: definition.mayExecuteCommands,
|
|
8364
|
+
storageLocation,
|
|
8365
|
+
itemCount: items.length,
|
|
8366
|
+
items
|
|
8367
|
+
};
|
|
8368
|
+
}
|
|
8369
|
+
)
|
|
8370
|
+
);
|
|
8371
|
+
return {
|
|
8372
|
+
root,
|
|
8373
|
+
activeRepositoryRoot,
|
|
8374
|
+
categories,
|
|
8375
|
+
generatedAt: formatIsoDate((options.now ?? (() => /* @__PURE__ */ new Date()))())
|
|
8376
|
+
};
|
|
8377
|
+
}
|
|
8378
|
+
|
|
8379
|
+
// src/user-local/memory.ts
|
|
8380
|
+
var import_node_fs17 = require("fs");
|
|
8381
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
8382
|
+
|
|
8383
|
+
// src/user-local/memory-types.ts
|
|
8384
|
+
var USER_LOCAL_MEMORY_CATEGORIES = [
|
|
8385
|
+
"view-preference",
|
|
8386
|
+
"last-visible-cwd",
|
|
8387
|
+
"background-selection",
|
|
8388
|
+
"task-association",
|
|
8389
|
+
"display-preference",
|
|
8390
|
+
"inspection-choice"
|
|
8391
|
+
];
|
|
8392
|
+
|
|
8393
|
+
// src/user-local/memory.ts
|
|
8394
|
+
var MEMORY_STORAGE_CATEGORY = "memory-projections";
|
|
8395
|
+
var FILE_EXTENSION = ".json";
|
|
8396
|
+
var MEMORY_SCHEMA_VERSION = 1;
|
|
8397
|
+
var MAX_SEGMENT_LENGTH = 80;
|
|
8398
|
+
var MAX_SUMMARY_LENGTH = 240;
|
|
8399
|
+
var MAX_SOURCE_LENGTH = 80;
|
|
8400
|
+
var MAX_SCOPE_LENGTH = 120;
|
|
8401
|
+
var MAX_VALUE_SUMMARY_LENGTH = 240;
|
|
8402
|
+
var DEFAULT_SCOPE = "user";
|
|
8403
|
+
var SAFE_SEGMENT_PATTERN = /^[a-z0-9][a-z0-9._-]*$/u;
|
|
8404
|
+
var DISPLAY_NAVIGATION_RULES = {
|
|
8405
|
+
"view-preference": "May affect UI panel, filter, density, or sorting display/navigation only.",
|
|
8406
|
+
"last-visible-cwd": "May display or preselect an already visible workspace context only.",
|
|
8407
|
+
"background-selection": "May restore the selected background entry in local UI only.",
|
|
8408
|
+
"task-association": "May group visible tasks by a local association only.",
|
|
8409
|
+
"display-preference": "May affect local text wrapping, compactness, or visibility only.",
|
|
8410
|
+
"inspection-choice": "May affect inspection display choices only."
|
|
8411
|
+
};
|
|
8412
|
+
function formatIsoDate2(date) {
|
|
8413
|
+
return date.toISOString();
|
|
8414
|
+
}
|
|
8415
|
+
function isUserLocalMemoryCategory(value) {
|
|
8416
|
+
return USER_LOCAL_MEMORY_CATEGORIES.includes(value);
|
|
8417
|
+
}
|
|
8418
|
+
function assertUserLocalMemoryCategory(value) {
|
|
8419
|
+
if (!isUserLocalMemoryCategory(value)) {
|
|
8420
|
+
throw new Error(`Unsupported user-local memory category: ${value}`);
|
|
8421
|
+
}
|
|
8422
|
+
return value;
|
|
8423
|
+
}
|
|
8424
|
+
function assertSafeSegment(name, value) {
|
|
8425
|
+
const trimmed = value.trim();
|
|
8426
|
+
if (trimmed.length === 0) {
|
|
8427
|
+
throw new Error(`${name} must not be empty.`);
|
|
8428
|
+
}
|
|
8429
|
+
if (trimmed.length > MAX_SEGMENT_LENGTH || !SAFE_SEGMENT_PATTERN.test(trimmed)) {
|
|
8430
|
+
throw new Error(
|
|
8431
|
+
`${name} must use lowercase letters, numbers, dots, underscores, or hyphens: ${value}`
|
|
8432
|
+
);
|
|
8433
|
+
}
|
|
8434
|
+
return trimmed;
|
|
8435
|
+
}
|
|
8436
|
+
function boundedText(name, value, maxLength) {
|
|
8437
|
+
const normalized = value.trim().replace(/\s+/g, " ");
|
|
8438
|
+
if (normalized.length === 0) {
|
|
8439
|
+
throw new Error(`${name} must not be empty.`);
|
|
8440
|
+
}
|
|
8441
|
+
if (normalized.length > maxLength) {
|
|
8442
|
+
return normalized.slice(0, maxLength);
|
|
8443
|
+
}
|
|
8444
|
+
return normalized;
|
|
8445
|
+
}
|
|
8446
|
+
function summarizeValue(value) {
|
|
8447
|
+
return boundedText("value", value, MAX_VALUE_SUMMARY_LENGTH);
|
|
8448
|
+
}
|
|
8449
|
+
function memoryFileName(category, key) {
|
|
8450
|
+
return `${category}__${key}${FILE_EXTENSION}`;
|
|
8451
|
+
}
|
|
8452
|
+
async function resolveMemoryRoot(options) {
|
|
8453
|
+
const root = await resolveUserLocalStorageRoot(options);
|
|
8454
|
+
return {
|
|
8455
|
+
root,
|
|
8456
|
+
memoryRoot: import_node_path21.default.join(root, MEMORY_STORAGE_CATEGORY)
|
|
8457
|
+
};
|
|
8458
|
+
}
|
|
8459
|
+
function parseMemoryRecord(raw, storageLocation) {
|
|
8460
|
+
const record = JSON.parse(raw);
|
|
8461
|
+
const category = readString(record, "category");
|
|
8462
|
+
const schemaVersion = record["schemaVersion"];
|
|
8463
|
+
if (schemaVersion !== MEMORY_SCHEMA_VERSION) {
|
|
8464
|
+
throw new Error(`Unsupported user-local memory schema at ${storageLocation}`);
|
|
8465
|
+
}
|
|
8466
|
+
return {
|
|
8467
|
+
schemaVersion: MEMORY_SCHEMA_VERSION,
|
|
8468
|
+
category: assertUserLocalMemoryCategory(category),
|
|
8469
|
+
key: readString(record, "key"),
|
|
8470
|
+
value: readString(record, "value"),
|
|
8471
|
+
summary: readString(record, "summary"),
|
|
8472
|
+
source: readString(record, "source"),
|
|
8473
|
+
scope: readString(record, "scope"),
|
|
8474
|
+
createdAt: readString(record, "createdAt"),
|
|
8475
|
+
lastUsedAt: readString(record, "lastUsedAt"),
|
|
8476
|
+
enabled: readBoolean(record, "enabled")
|
|
8477
|
+
};
|
|
8478
|
+
}
|
|
8479
|
+
function readString(record, key) {
|
|
8480
|
+
const value = record[key];
|
|
8481
|
+
if (typeof value !== "string") {
|
|
8482
|
+
throw new Error(`Invalid user-local memory field: ${key}`);
|
|
8483
|
+
}
|
|
8484
|
+
return value;
|
|
8485
|
+
}
|
|
8486
|
+
function readBoolean(record, key) {
|
|
8487
|
+
const value = record[key];
|
|
8488
|
+
if (typeof value !== "boolean") {
|
|
8489
|
+
throw new Error(`Invalid user-local memory field: ${key}`);
|
|
8490
|
+
}
|
|
8491
|
+
return value;
|
|
8492
|
+
}
|
|
8493
|
+
function projectMemoryItem(root, storageLocation, item) {
|
|
8494
|
+
return {
|
|
8495
|
+
root,
|
|
8496
|
+
category: item.category,
|
|
8497
|
+
key: item.key,
|
|
8498
|
+
summary: item.summary,
|
|
8499
|
+
valueSummary: summarizeValue(item.value),
|
|
8500
|
+
source: item.source,
|
|
8501
|
+
scope: item.scope,
|
|
8502
|
+
storageLocation,
|
|
8503
|
+
createdAt: item.createdAt,
|
|
8504
|
+
lastUsedAt: item.lastUsedAt,
|
|
8505
|
+
enabled: item.enabled,
|
|
8506
|
+
displayNavigationRule: DISPLAY_NAVIGATION_RULES[item.category],
|
|
8507
|
+
commandExecutionEffect: "none",
|
|
8508
|
+
deleteAvailable: true,
|
|
8509
|
+
disableAvailable: true
|
|
8510
|
+
};
|
|
8511
|
+
}
|
|
8512
|
+
async function readMemoryFile(root, storageLocation) {
|
|
8513
|
+
return projectMemoryItem(
|
|
8514
|
+
root,
|
|
8515
|
+
storageLocation,
|
|
8516
|
+
parseMemoryRecord(await import_node_fs17.promises.readFile(storageLocation, "utf8"), storageLocation)
|
|
8517
|
+
);
|
|
8518
|
+
}
|
|
8519
|
+
async function resolveMemoryFile(options) {
|
|
8520
|
+
const category = assertUserLocalMemoryCategory(options.category);
|
|
8521
|
+
const key = assertSafeSegment("key", options.key);
|
|
8522
|
+
const { root, memoryRoot: memoryRoot3 } = await resolveMemoryRoot(options);
|
|
8523
|
+
return {
|
|
8524
|
+
root,
|
|
8525
|
+
storageLocation: import_node_path21.default.join(memoryRoot3, memoryFileName(category, key))
|
|
8526
|
+
};
|
|
8527
|
+
}
|
|
8528
|
+
async function setUserLocalMemoryItem(options) {
|
|
8529
|
+
const category = assertUserLocalMemoryCategory(options.category);
|
|
8530
|
+
const key = assertSafeSegment("key", options.key);
|
|
8531
|
+
const summary = boundedText("summary", options.summary, MAX_SUMMARY_LENGTH);
|
|
8532
|
+
const source = boundedText("source", options.source, MAX_SOURCE_LENGTH);
|
|
8533
|
+
const scope = boundedText("scope", options.scope ?? DEFAULT_SCOPE, MAX_SCOPE_LENGTH);
|
|
8534
|
+
const value = summarizeValue(options.value);
|
|
8535
|
+
const now = formatIsoDate2((options.now ?? (() => /* @__PURE__ */ new Date()))());
|
|
8536
|
+
const { root, memoryRoot: memoryRoot3 } = await resolveMemoryRoot(options);
|
|
8537
|
+
const storageLocation = import_node_path21.default.join(memoryRoot3, memoryFileName(category, key));
|
|
8538
|
+
let createdAt = now;
|
|
8539
|
+
try {
|
|
8540
|
+
const existing = parseMemoryRecord(await import_node_fs17.promises.readFile(storageLocation, "utf8"), storageLocation);
|
|
8541
|
+
createdAt = existing.createdAt;
|
|
8542
|
+
} catch (error) {
|
|
8543
|
+
if (error instanceof Error && error.message.includes("ENOENT")) {
|
|
8544
|
+
createdAt = now;
|
|
8545
|
+
} else {
|
|
8546
|
+
throw error;
|
|
8547
|
+
}
|
|
8548
|
+
}
|
|
8549
|
+
const item = {
|
|
8550
|
+
schemaVersion: MEMORY_SCHEMA_VERSION,
|
|
8551
|
+
category,
|
|
8552
|
+
key,
|
|
8553
|
+
value,
|
|
8554
|
+
summary,
|
|
8555
|
+
source,
|
|
8556
|
+
scope,
|
|
8557
|
+
createdAt,
|
|
8558
|
+
lastUsedAt: now,
|
|
8559
|
+
enabled: true
|
|
8560
|
+
};
|
|
8561
|
+
await import_node_fs17.promises.mkdir(memoryRoot3, { recursive: true });
|
|
8562
|
+
await import_node_fs17.promises.writeFile(storageLocation, `${JSON.stringify(item, null, 2)}
|
|
8563
|
+
`, "utf8");
|
|
8564
|
+
return projectMemoryItem(root, storageLocation, item);
|
|
8565
|
+
}
|
|
8566
|
+
async function listUserLocalMemoryItems(options) {
|
|
8567
|
+
const { root, memoryRoot: memoryRoot3 } = await resolveMemoryRoot(options);
|
|
8568
|
+
let entries;
|
|
8569
|
+
try {
|
|
8570
|
+
entries = await import_node_fs17.promises.readdir(memoryRoot3, { withFileTypes: true });
|
|
8571
|
+
} catch {
|
|
8572
|
+
entries = [];
|
|
8573
|
+
}
|
|
8574
|
+
const items = await Promise.all(
|
|
8575
|
+
entries.filter((entry) => entry.isFile() && entry.name.endsWith(FILE_EXTENSION)).map((entry) => readMemoryFile(root, import_node_path21.default.join(memoryRoot3, entry.name)))
|
|
8576
|
+
);
|
|
8577
|
+
return {
|
|
8578
|
+
root,
|
|
8579
|
+
activeRepositoryRoot: import_node_path21.default.resolve(options.activeRepositoryRoot),
|
|
8580
|
+
items: items.sort(
|
|
8581
|
+
(left, right) => `${left.category}/${left.key}`.localeCompare(`${right.category}/${right.key}`)
|
|
8582
|
+
)
|
|
8583
|
+
};
|
|
8584
|
+
}
|
|
8585
|
+
async function inspectUserLocalMemoryItem(options) {
|
|
8586
|
+
const { root, storageLocation } = await resolveMemoryFile(options);
|
|
8587
|
+
return readMemoryFile(root, storageLocation);
|
|
8588
|
+
}
|
|
8589
|
+
async function disableUserLocalMemoryItem(options) {
|
|
8590
|
+
const { root, storageLocation } = await resolveMemoryFile(options);
|
|
8591
|
+
const existing = parseMemoryRecord(await import_node_fs17.promises.readFile(storageLocation, "utf8"), storageLocation);
|
|
8592
|
+
const disabled = {
|
|
8593
|
+
...existing,
|
|
8594
|
+
enabled: false,
|
|
8595
|
+
lastUsedAt: formatIsoDate2((options.now ?? (() => /* @__PURE__ */ new Date()))())
|
|
8596
|
+
};
|
|
8597
|
+
await import_node_fs17.promises.writeFile(storageLocation, `${JSON.stringify(disabled, null, 2)}
|
|
8598
|
+
`, "utf8");
|
|
8599
|
+
return projectMemoryItem(root, storageLocation, disabled);
|
|
8600
|
+
}
|
|
8601
|
+
async function deleteUserLocalMemoryItem(options) {
|
|
8602
|
+
const { storageLocation } = await resolveMemoryFile(options);
|
|
8603
|
+
await import_node_fs17.promises.rm(storageLocation);
|
|
8604
|
+
return {
|
|
8605
|
+
category: options.category,
|
|
8606
|
+
key: options.key,
|
|
8607
|
+
deleted: true
|
|
8608
|
+
};
|
|
8609
|
+
}
|
|
8610
|
+
async function readEnabledUserLocalMemoryItem(options) {
|
|
8611
|
+
const item = await inspectUserLocalMemoryItem(options);
|
|
8612
|
+
return item.enabled ? item : null;
|
|
8613
|
+
}
|
|
8614
|
+
|
|
7771
8615
|
// src/self-hosting/self-hosting-verification.ts
|
|
7772
8616
|
var DEFAULT_BASE_REF = "origin/develop";
|
|
7773
8617
|
var PACKAGE_VERIFY_COMMANDS = ["test", "typecheck", "build"];
|
|
@@ -7946,8 +8790,8 @@ function createCommandExecutionTool(deps) {
|
|
|
7946
8790
|
}
|
|
7947
8791
|
|
|
7948
8792
|
// src/subagents/index.ts
|
|
7949
|
-
var import_agent_runtime7 = require("@robota-sdk/agent-runtime");
|
|
7950
8793
|
var import_agent_runtime8 = require("@robota-sdk/agent-runtime");
|
|
8794
|
+
var import_agent_runtime9 = require("@robota-sdk/agent-runtime");
|
|
7951
8795
|
|
|
7952
8796
|
// src/permissions/permission-prompt.ts
|
|
7953
8797
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
@@ -7987,6 +8831,7 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
7987
8831
|
DEFAULT_AUTO_COMPACT_THRESHOLD,
|
|
7988
8832
|
DEFAULT_BACKGROUND_TASK_LOG_PAGE_SIZE,
|
|
7989
8833
|
DEFAULT_STATUS_LINE_COMMAND_SETTINGS,
|
|
8834
|
+
EXECUTION_ORIGIN_METADATA_KEYS,
|
|
7990
8835
|
EXIT_COMMAND_DESCRIPTION,
|
|
7991
8836
|
EditCheckpointStore,
|
|
7992
8837
|
HELP_COMMAND_DESCRIPTION,
|
|
@@ -8024,6 +8869,9 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
8024
8869
|
SkillCommandSource,
|
|
8025
8870
|
SubagentManager,
|
|
8026
8871
|
SystemCommandExecutor,
|
|
8872
|
+
USER_LOCAL_MEMORY_CATEGORIES,
|
|
8873
|
+
USER_LOCAL_STORAGE_CATEGORIES,
|
|
8874
|
+
USER_LOCAL_STORAGE_CATEGORY_DEFINITIONS,
|
|
8027
8875
|
VALIDATE_SESSION_COMMAND_DESCRIPTION,
|
|
8028
8876
|
VALID_PERMISSION_MODES,
|
|
8029
8877
|
WorktreeSubagentRunner,
|
|
@@ -8048,7 +8896,9 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
8048
8896
|
closeCommandBackgroundTask,
|
|
8049
8897
|
compactCommandContext,
|
|
8050
8898
|
createAgentTool,
|
|
8899
|
+
createBackgroundGroupExecutionEntryId,
|
|
8051
8900
|
createBackgroundProcessTool,
|
|
8901
|
+
createBackgroundTaskExecutionEntryId,
|
|
8052
8902
|
createBackgroundTaskLogPage,
|
|
8053
8903
|
createBuiltinCommandModule,
|
|
8054
8904
|
createCommandExecutionTool,
|
|
@@ -8057,7 +8907,13 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
8057
8907
|
createCommandProjectMemoryStore,
|
|
8058
8908
|
createContextReferenceItem,
|
|
8059
8909
|
createDefaultTools,
|
|
8910
|
+
createExecutionOriginMetadata,
|
|
8911
|
+
createExecutionWorkspaceSnapshot,
|
|
8912
|
+
createExecutionWorkspaceTaskSpawner,
|
|
8060
8913
|
createLimitedOutputCapture,
|
|
8914
|
+
createLineDetailPage,
|
|
8915
|
+
createMainThreadDetailPage,
|
|
8916
|
+
createMainThreadExecutionEntryId,
|
|
8061
8917
|
createModelCommandToolProjection,
|
|
8062
8918
|
createPluginRegistryReloadRequestedEffect,
|
|
8063
8919
|
createPluginTuiRequestedEffect,
|
|
@@ -8075,6 +8931,8 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
8075
8931
|
createSystemCommands,
|
|
8076
8932
|
createWorktreeSubagentRunner,
|
|
8077
8933
|
deleteProviderProfile,
|
|
8934
|
+
deleteUserLocalMemoryItem,
|
|
8935
|
+
disableUserLocalMemoryItem,
|
|
8078
8936
|
discoverTaskFiles,
|
|
8079
8937
|
evaluateReversibleToolSafety,
|
|
8080
8938
|
executeSkill,
|
|
@@ -8104,6 +8962,8 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
8104
8962
|
hasSensitiveCommandMemoryContent,
|
|
8105
8963
|
hasUsableSecretReference,
|
|
8106
8964
|
inspectCommandEditCheckpoint,
|
|
8965
|
+
inspectUserLocalMemoryItem,
|
|
8966
|
+
inspectUserLocalStorage,
|
|
8107
8967
|
isCommandMemoryType,
|
|
8108
8968
|
isEnvReference,
|
|
8109
8969
|
isMemoryType,
|
|
@@ -8117,10 +8977,12 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
8117
8977
|
listCommandSessionAllowedTools,
|
|
8118
8978
|
listCommandUsedMemoryReferences,
|
|
8119
8979
|
listResumableSessionSummaries,
|
|
8980
|
+
listUserLocalMemoryItems,
|
|
8120
8981
|
loadTaskContext,
|
|
8121
8982
|
mergeProviderPatch,
|
|
8122
8983
|
normalizeModelCommandName,
|
|
8123
8984
|
parseCommandBackgroundLogCursor,
|
|
8985
|
+
parseExecutionWorkspaceEntryId,
|
|
8124
8986
|
parseFrontmatter,
|
|
8125
8987
|
parseLanguageArgument,
|
|
8126
8988
|
parsePermissionModeArgument,
|
|
@@ -8140,6 +9002,7 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
8140
9002
|
readCommandPermissionsState,
|
|
8141
9003
|
readCommandSessionInfo,
|
|
8142
9004
|
readCurrentGitBranch,
|
|
9005
|
+
readEnabledUserLocalMemoryItem,
|
|
8143
9006
|
recordCommandMemoryEvent,
|
|
8144
9007
|
removeCommandContextReference,
|
|
8145
9008
|
removeContextReference,
|
|
@@ -8155,6 +9018,7 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
8155
9018
|
resolveProviderSetupSelection,
|
|
8156
9019
|
resolveSessionIdByIdOrName,
|
|
8157
9020
|
resolveSubagentLogDir,
|
|
9021
|
+
resolveUserLocalStorageRoot,
|
|
8158
9022
|
restoreCommandEditCheckpoint,
|
|
8159
9023
|
retrieveAgentToolDeps,
|
|
8160
9024
|
rollbackCommandEditCheckpoint,
|
|
@@ -8163,6 +9027,7 @@ async function promptForApproval(terminal, toolName, toolArgs) {
|
|
|
8163
9027
|
selectRelevantTasks,
|
|
8164
9028
|
setCommandAutoCompactThreshold,
|
|
8165
9029
|
setCurrentProvider,
|
|
9030
|
+
setUserLocalMemoryItem,
|
|
8166
9031
|
storeAgentToolDeps,
|
|
8167
9032
|
submitProviderSetupValue,
|
|
8168
9033
|
substituteVariables,
|