aiden-runtime 4.5.0 → 4.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -2
- package/dist/cli/v4/aidenCLI.js +207 -100
- package/dist/cli/v4/chatSession.js +120 -0
- package/dist/cli/v4/commands/_runtimeToggleHelpers.js +2 -0
- package/dist/cli/v4/commands/fanout.js +42 -59
- package/dist/cli/v4/commands/help.js +8 -0
- package/dist/cli/v4/commands/index.js +21 -1
- package/dist/cli/v4/commands/mcp.js +80 -54
- package/dist/cli/v4/commands/plannerGuard.js +53 -0
- package/dist/cli/v4/commands/recovery.js +122 -0
- package/dist/cli/v4/commands/runs.js +22 -2
- package/dist/cli/v4/commands/spawnPause.js +93 -0
- package/dist/cli/v4/commands/walkthrough.js +140 -0
- package/dist/cli/v4/daemonAgentBuilder.js +4 -1
- package/dist/cli/v4/defaultSoul.js +1 -1
- package/dist/cli/v4/onboarding/disclaimer.js +162 -0
- package/dist/cli/v4/onboarding/loading.js +208 -0
- package/dist/cli/v4/onboarding/providerPicker.js +126 -0
- package/dist/cli/v4/onboarding/successScreen.js +68 -0
- package/dist/cli/v4/repl/firstRunHint.js +107 -0
- package/dist/cli/v4/setupWizard.js +201 -31
- package/dist/core/v4/aidenAgent.js +219 -1
- package/dist/core/v4/daemon/bootstrap.js +47 -0
- package/dist/core/v4/daemon/db/migrations.js +66 -0
- package/dist/core/v4/daemon/runStore.js +33 -3
- package/dist/core/v4/providerFallback.js +35 -2
- package/dist/core/v4/providers/modelFetch.js +179 -0
- package/dist/core/v4/providers/probe.js +275 -0
- package/dist/core/v4/runtimeToggles.js +30 -3
- package/dist/core/v4/selfimprovement/recoveryStore.js +307 -0
- package/dist/core/v4/selfimprovement/signatureBuilder.js +158 -0
- package/dist/core/v4/subagent/childBuilder.js +391 -0
- package/dist/core/v4/subagent/fanout.js +75 -51
- package/dist/core/v4/subagent/spawnPause.js +191 -0
- package/dist/core/v4/subagent/spawnSubAgent.js +310 -0
- package/dist/core/v4/toolRegistry.js +19 -3
- package/dist/core/v4/ui/banner.js +133 -0
- package/dist/core/v4/ui/theme.js +164 -0
- package/dist/core/version.js +1 -1
- package/dist/moat/plannerGuard.js +29 -0
- package/dist/providers/v4/anthropicAdapter.js +31 -3
- package/dist/providers/v4/chatCompletionsAdapter.js +26 -3
- package/dist/providers/v4/codexResponsesAdapter.js +25 -2
- package/dist/providers/v4/ollamaPromptToolsAdapter.js +57 -2
- package/dist/tools/v4/index.js +17 -3
- package/dist/tools/v4/skills/lookupToolSchema.js +6 -1
- package/dist/tools/v4/subagent/spawnSubAgentTool.js +334 -0
- package/dist/tools/v4/subagent/subagentFanout.js +53 -1
- package/dist/tools/v4/ui/_uiSmokeTool.js +60 -0
- package/package.json +7 -3
|
@@ -26,8 +26,6 @@
|
|
|
26
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
27
|
exports.parseFanoutArgs = parseFanoutArgs;
|
|
28
28
|
exports.runFanoutCli = runFanoutCli;
|
|
29
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
30
|
-
const fanout_1 = require("../../../core/v4/subagent/fanout");
|
|
31
29
|
function parseFanoutArgs(argv) {
|
|
32
30
|
const args = { positional: [] };
|
|
33
31
|
let i = 0;
|
|
@@ -172,65 +170,50 @@ async function runFanoutCli(argv, opts = {}) {
|
|
|
172
170
|
return 1;
|
|
173
171
|
}
|
|
174
172
|
}
|
|
175
|
-
// ── Dry-run path
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}))
|
|
201
|
-
: undefined,
|
|
202
|
-
n: args.n,
|
|
203
|
-
merge: args.merge,
|
|
204
|
-
providers,
|
|
205
|
-
runChild: async ({ index, prompt, provider }) => {
|
|
206
|
-
return `[dry-run child ${index} via ${provider.providerId}] echo: ${prompt}`;
|
|
207
|
-
},
|
|
208
|
-
aggregatorAdapter: stubAdapter,
|
|
209
|
-
aggregatorModel: { providerId: 'stub-a', modelId: 'fake-model' },
|
|
210
|
-
timeoutMs: args.timeoutMs,
|
|
173
|
+
// ── Dry-run path ─────────────────────────────────────────────
|
|
174
|
+
// v4.6 Phase 2Q — `runFanout` now routes children through
|
|
175
|
+
// `spawnSubAgent`, which needs real `SpawnSubAgentDeps`
|
|
176
|
+
// (toolRegistry, parentProvider, runStore, …). Pre-2Q the dry-run
|
|
177
|
+
// exercised Promise.all + abort + merge dispatch via simple stubs;
|
|
178
|
+
// post-refactor the equivalent coverage now lives in
|
|
179
|
+
// `tests/v4/subagent/fanout.behavioral.test.ts` (Slice 5).
|
|
180
|
+
//
|
|
181
|
+
// Dry-run therefore emits a synthetic snapshot — same observable
|
|
182
|
+
// shape (mode/n/merge/per-child rows) so the runtime smoke can
|
|
183
|
+
// still assert "the CLI subcommand parses + runs to exit 0
|
|
184
|
+
// against the built artifact" without booting a runtime.
|
|
185
|
+
const stubProviders = ['stub-a', 'stub-b'];
|
|
186
|
+
const childRows = [];
|
|
187
|
+
for (let i = 0; i < args.n; i += 1) {
|
|
188
|
+
const providerId = stubProviders[i % stubProviders.length];
|
|
189
|
+
const prompt = args.mode === 'partition'
|
|
190
|
+
? `Task ${i + 1} from CLI: ${args.query}`
|
|
191
|
+
: args.query;
|
|
192
|
+
childRows.push({
|
|
193
|
+
index: i,
|
|
194
|
+
providerId,
|
|
195
|
+
modelId: 'fake-model',
|
|
196
|
+
output: `[dry-run child ${i} via ${providerId}] echo: ${prompt}`,
|
|
197
|
+
elapsedMs: 0,
|
|
211
198
|
});
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
writeOut(`${result.merged ?? '(no merged output)'}\n`);
|
|
199
|
+
}
|
|
200
|
+
writeOut(`fanout dry-run\n`);
|
|
201
|
+
writeOut(` mode: ${args.mode}\n`);
|
|
202
|
+
writeOut(` n: ${args.n}\n`);
|
|
203
|
+
writeOut(` merge: ${args.merge}\n`);
|
|
204
|
+
writeOut(` query: ${args.query}\n`);
|
|
205
|
+
writeOut(` succeeded: ${args.n}/${args.n}\n`);
|
|
206
|
+
writeOut(` totalMs: 0\n`);
|
|
207
|
+
writeOut(` providers: ${childRows.map((r) => r.providerId).join(', ')}\n`);
|
|
208
|
+
writeOut(`\n--- merged ---\n`);
|
|
209
|
+
if (args.merge === 'all') {
|
|
210
|
+
for (const r of childRows) {
|
|
211
|
+
writeOut(`\n[${r.index}] ${r.providerId}:${r.modelId} (${r.elapsedMs}ms)\n`);
|
|
212
|
+
writeOut(`${r.output}\n`);
|
|
229
213
|
}
|
|
230
|
-
return 0;
|
|
231
214
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
return 1;
|
|
215
|
+
else {
|
|
216
|
+
writeOut(`[dry-run aggregator]\n`);
|
|
235
217
|
}
|
|
218
|
+
return 0;
|
|
236
219
|
}
|
|
@@ -65,6 +65,14 @@ exports.SUBSECTION_MAP = {
|
|
|
65
65
|
daemon: 'System',
|
|
66
66
|
// v4.5 Phase 8b — contextual capability suggestions.
|
|
67
67
|
suggestions: 'System',
|
|
68
|
+
// v4.6 Phase 2M — opt-in keyword-based tool narrower.
|
|
69
|
+
'planner-guard': 'System',
|
|
70
|
+
// v4.6 Phase 3A — operator kill-switch for sub-agent spawning.
|
|
71
|
+
'spawn-pause': 'System',
|
|
72
|
+
// v4.6 Phase 3b — self-improvement loop operator surface.
|
|
73
|
+
recovery: 'System',
|
|
74
|
+
// v4.6 ONB1 slice 10 — new-user guided tour.
|
|
75
|
+
walkthrough: 'System',
|
|
68
76
|
// ── Authentication ──
|
|
69
77
|
auth: 'Authentication',
|
|
70
78
|
// ── Help ──
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* and registers each on the global CommandRegistry at boot.
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.allCommands = exports.suggestions = exports.daemonStatus = exports.browserDepth = exports.tce = exports.sandbox = exports.update = exports.reloadSoul = exports.history = exports.show = exports.status = exports.voice = exports.channel = exports.setup = exports.cron = exports.doctor = exports.license = exports.auth = exports.plugins = exports.streaming = exports.debugPrompt = exports.identity = exports.providers = exports.quit = exports.clear = exports.verbose = exports.reasoning = exports.reloadMcp = exports.skills = exports.skin = exports.yolo = exports.usage = exports.compress = exports.title = exports.save = exports.personality = exports.model = exports.tools = exports.help = void 0;
|
|
15
|
+
exports.allCommands = exports.walkthrough = exports.recovery = exports.spawnPause = exports.plannerGuard = exports.suggestions = exports.daemonStatus = exports.browserDepth = exports.tce = exports.sandbox = exports.update = exports.reloadSoul = exports.history = exports.show = exports.status = exports.voice = exports.channel = exports.setup = exports.cron = exports.doctor = exports.license = exports.auth = exports.plugins = exports.streaming = exports.debugPrompt = exports.identity = exports.providers = exports.quit = exports.clear = exports.verbose = exports.reasoning = exports.reloadMcp = exports.skills = exports.skin = exports.yolo = exports.usage = exports.compress = exports.title = exports.save = exports.personality = exports.model = exports.tools = exports.help = void 0;
|
|
16
16
|
const help_1 = require("./help");
|
|
17
17
|
Object.defineProperty(exports, "help", { enumerable: true, get: function () { return help_1.help; } });
|
|
18
18
|
const tools_1 = require("./tools");
|
|
@@ -91,6 +91,18 @@ Object.defineProperty(exports, "daemonStatus", { enumerable: true, get: function
|
|
|
91
91
|
// v4.5 Phase 8b — contextual capability suggestions toggle.
|
|
92
92
|
const suggestions_1 = require("./suggestions");
|
|
93
93
|
Object.defineProperty(exports, "suggestions", { enumerable: true, get: function () { return suggestions_1.suggestions; } });
|
|
94
|
+
// v4.6 Phase 2M — opt-in keyword-based tool narrower (default OFF).
|
|
95
|
+
const plannerGuard_1 = require("./plannerGuard");
|
|
96
|
+
Object.defineProperty(exports, "plannerGuard", { enumerable: true, get: function () { return plannerGuard_1.plannerGuard; } });
|
|
97
|
+
// v4.6 Phase 3A — operator kill-switch for sub-agent spawning.
|
|
98
|
+
const spawnPause_1 = require("./spawnPause");
|
|
99
|
+
Object.defineProperty(exports, "spawnPause", { enumerable: true, get: function () { return spawnPause_1.spawnPause; } });
|
|
100
|
+
// v4.6 Phase 3b — self-improvement loop operator surface.
|
|
101
|
+
const recovery_1 = require("./recovery");
|
|
102
|
+
Object.defineProperty(exports, "recovery", { enumerable: true, get: function () { return recovery_1.recovery; } });
|
|
103
|
+
// ONB1 slice 10 — new-user guided tour.
|
|
104
|
+
const walkthrough_1 = require("./walkthrough");
|
|
105
|
+
Object.defineProperty(exports, "walkthrough", { enumerable: true, get: function () { return walkthrough_1.walkthrough; } });
|
|
94
106
|
/** All built-in system commands, in canonical order. */
|
|
95
107
|
exports.allCommands = [
|
|
96
108
|
help_1.help,
|
|
@@ -134,6 +146,14 @@ exports.allCommands = [
|
|
|
134
146
|
daemonStatus_1.daemonStatus,
|
|
135
147
|
// v4.5 Phase 8b — contextual suggestions toggle.
|
|
136
148
|
suggestions_1.suggestions,
|
|
149
|
+
// v4.6 Phase 2M — opt-in keyword-based tool narrower (default OFF).
|
|
150
|
+
plannerGuard_1.plannerGuard,
|
|
151
|
+
// v4.6 Phase 3A — operator kill-switch for sub-agent spawning.
|
|
152
|
+
spawnPause_1.spawnPause,
|
|
153
|
+
// v4.6 Phase 3b — self-improvement loop operator surface.
|
|
154
|
+
recovery_1.recovery,
|
|
155
|
+
// ONB1 slice 10 — new-user guided tour.
|
|
156
|
+
walkthrough_1.walkthrough,
|
|
137
157
|
clear_1.clear,
|
|
138
158
|
quit_1.quit,
|
|
139
159
|
];
|
|
@@ -32,10 +32,15 @@
|
|
|
32
32
|
* tools by default; opting in means the user accepted server-side
|
|
33
33
|
* execution risk at config time.
|
|
34
34
|
*/
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
exports.AIDEN_MCP_BUILD = void 0;
|
|
37
40
|
exports.runMcpSubcommand = runMcpSubcommand;
|
|
38
41
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
42
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
43
|
+
const node_crypto_1 = require("node:crypto");
|
|
39
44
|
const paths_1 = require("../../../core/v4/paths");
|
|
40
45
|
const toolRegistry_1 = require("../../../core/v4/toolRegistry");
|
|
41
46
|
const skillLoader_1 = require("../../../core/v4/skillLoader");
|
|
@@ -46,12 +51,26 @@ const processRegistry_1 = require("../../../core/v4/processRegistry");
|
|
|
46
51
|
const config_1 = require("../../../core/v4/config");
|
|
47
52
|
const providerFallback_1 = require("../../../core/v4/providerFallback");
|
|
48
53
|
const chatCompletionsAdapter_1 = require("../../../providers/v4/chatCompletionsAdapter");
|
|
49
|
-
const aidenAgent_1 = require("../../../core/v4/aidenAgent");
|
|
50
54
|
const factory_1 = require("../../../core/v4/logger/factory");
|
|
51
55
|
const index_1 = require("../../../tools/v4/index");
|
|
52
56
|
const envSources_1 = require("../envSources");
|
|
53
57
|
const credentialResolver_1 = require("../../../providers/v4/credentialResolver");
|
|
54
58
|
const runtimeResolver_1 = require("../../../providers/v4/runtimeResolver");
|
|
59
|
+
// v4.6 Phase 2R — MCP-mode subagent_fanout now routes children
|
|
60
|
+
// through the `spawnSubAgent` primitive (same as REPL after 2Q-A).
|
|
61
|
+
// The legacy `runChild` closure + RunChildArgs import are deleted
|
|
62
|
+
// per design doc §12.3 (2R cleanup). MCP needs its own daemon-db
|
|
63
|
+
// connection + instance id so child runs persist under
|
|
64
|
+
// `aiden runs list --include-children` for cross-runtime
|
|
65
|
+
// observability.
|
|
66
|
+
const daemon_1 = require("../../../core/v4/daemon");
|
|
67
|
+
const version_1 = require("../../../core/version");
|
|
68
|
+
// v4.6 Phase 3A — operator kill-switch. Initialised here so
|
|
69
|
+
// MCP-side `subagent_fanout` (and any future MCP-side
|
|
70
|
+
// `spawn_sub_agent` exposure) reads from the same marker file the
|
|
71
|
+
// REPL writes via /spawn-pause. Cross-process coordination is the
|
|
72
|
+
// whole point of the file-marker design.
|
|
73
|
+
const spawnPause_1 = require("../../../core/v4/subagent/spawnPause");
|
|
55
74
|
const stdioServer_1 = require("../../../core/v4/mcp/server/stdioServer");
|
|
56
75
|
Object.defineProperty(exports, "AIDEN_MCP_BUILD", { enumerable: true, get: function () { return stdioServer_1.AIDEN_MCP_BUILD; } });
|
|
57
76
|
const diagnostics_1 = require("../../../core/v4/mcp/server/diagnostics");
|
|
@@ -206,6 +225,43 @@ async function wireSubagentFanout(opts) {
|
|
|
206
225
|
}
|
|
207
226
|
}
|
|
208
227
|
const finalAdapter = wrapped;
|
|
228
|
+
// v4.6 Phase 2R — open a daemon-db connection + seed an MCP
|
|
229
|
+
// instance row so child sub-agent runs (spawned by
|
|
230
|
+
// subagent_fanout below) persist to the same `runs` table the
|
|
231
|
+
// REPL writes to. Operators can then see MCP-side fanout
|
|
232
|
+
// activity under `aiden runs list --include-children`. Same
|
|
233
|
+
// WAL-coexistence model as REPL — connection.ts caches per-path.
|
|
234
|
+
const mcpInstanceId = `mcp-${(0, node_crypto_1.randomUUID)().slice(0, 8)}`;
|
|
235
|
+
const mcpDb = (0, daemon_1.openDaemonDb)((0, daemon_1.daemonDbPath)(opts.paths.root));
|
|
236
|
+
mcpDb.prepare(`INSERT OR IGNORE INTO daemon_instances
|
|
237
|
+
(instance_id, pid, hostname, started_at, last_heartbeat, version)
|
|
238
|
+
VALUES (?, ?, ?, ?, ?, ?)`).run(mcpInstanceId, process.pid, node_os_1.default.hostname(), Date.now(), Date.now(), version_1.VERSION);
|
|
239
|
+
const mcpRunStore = (0, daemon_1.createRunStore)({ db: mcpDb });
|
|
240
|
+
// v4.6 Phase 3b — self-improvement loop singleton against the
|
|
241
|
+
// same daemon.db. MCP-side spawn_sub_agent / subagent_fanout
|
|
242
|
+
// dispatches now record failure occurrences + recoveries into
|
|
243
|
+
// the shared ledger, so operators see MCP failures alongside
|
|
244
|
+
// REPL failures in `aiden /recovery list` from a future REPL
|
|
245
|
+
// session.
|
|
246
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
247
|
+
const { initRecoveryStore } = require('../../../core/v4/selfimprovement/recoveryStore');
|
|
248
|
+
initRecoveryStore({ db: mcpDb });
|
|
249
|
+
// v4.6 Phase 3A — wire the pause singleton against the same
|
|
250
|
+
// `paths.root` the REPL uses. The fanout handler's pause-check
|
|
251
|
+
// reads through `getSpawnPause()`, so initing here makes MCP
|
|
252
|
+
// mode respect the operator's /spawn-pause state without any
|
|
253
|
+
// additional plumbing.
|
|
254
|
+
const mcpPauseState = (0, spawnPause_1.initSpawnPause)({ aidenHome: opts.paths.root });
|
|
255
|
+
if (mcpPauseState.isPaused()) {
|
|
256
|
+
const s = mcpPauseState.status();
|
|
257
|
+
const reasonSuffix = s.reason ? ` (reason: ${s.reason})` : '';
|
|
258
|
+
opts.logger.warn(`MCP boot: subagent_fanout is PAUSED${reasonSuffix}. ` +
|
|
259
|
+
'Operator must run /spawn-pause off in a REPL session to resume.', {
|
|
260
|
+
pausedAt: s.pausedAt ?? null,
|
|
261
|
+
pausedBy: s.pausedBy ?? null,
|
|
262
|
+
durationMs: s.durationMs ?? null,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
209
265
|
opts.registry.register((0, index_1.makeSubagentFanoutTool)({
|
|
210
266
|
logger: opts.logger,
|
|
211
267
|
resolveActiveModel: () => ({ providerId, modelId }),
|
|
@@ -224,70 +280,40 @@ async function wireSubagentFanout(opts) {
|
|
|
224
280
|
}
|
|
225
281
|
return [{ providerId, modelId }];
|
|
226
282
|
},
|
|
227
|
-
|
|
228
|
-
|
|
283
|
+
// v4.6 Phase 2R — `spawnDeps` mirrors the REPL wiring in
|
|
284
|
+
// `cli/v4/aidenCLI.ts` (2Q-A). The MCP-mode parentToolContext
|
|
285
|
+
// is intentionally lean: no approvalEngine (a server has no
|
|
286
|
+
// human at the REPL to prompt — children's mutating tools are
|
|
287
|
+
// gated by AIDEN_SUBAGENT_ALLOW_DESTRUCTIVE in childBuilder),
|
|
288
|
+
// no ssrfProtection/tirithScanner/memoryGuard (MCP's slim
|
|
289
|
+
// runtime never wired them — see header comment §9).
|
|
290
|
+
spawnDeps: {
|
|
291
|
+
toolRegistry: opts.registry,
|
|
292
|
+
parentToolContext: {
|
|
229
293
|
cwd: process.cwd(),
|
|
230
294
|
paths: opts.paths,
|
|
231
295
|
sessions: opts.sessionManager,
|
|
232
296
|
memory: opts.memoryManager,
|
|
233
297
|
skillLoader: opts.skillLoader,
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
process.env.AIDEN_SUBAGENT_ALLOW_DESTRUCTIVE === 'true';
|
|
242
|
-
const childToolNames = [];
|
|
243
|
-
for (const name of opts.registry.list()) {
|
|
244
|
-
const h = opts.registry.get(name);
|
|
245
|
-
if (!h)
|
|
246
|
-
continue;
|
|
247
|
-
if (h.mutates && !allowDestructive)
|
|
248
|
-
continue;
|
|
249
|
-
if (name === 'subagent_fanout')
|
|
250
|
-
continue;
|
|
251
|
-
childToolNames.push(name);
|
|
252
|
-
}
|
|
253
|
-
const childExecutor = opts.registry.buildExecutor(childCtx);
|
|
254
|
-
const childTools = childToolNames
|
|
255
|
-
.map((n) => opts.registry.get(n)?.schema)
|
|
256
|
-
.filter((s) => !!s);
|
|
257
|
-
// Per-child cloned FallbackAdapter — own rate-limit state.
|
|
258
|
-
const childProvider = finalAdapter instanceof providerFallback_1.FallbackAdapter
|
|
259
|
-
? finalAdapter.clone()
|
|
260
|
-
: finalAdapter;
|
|
261
|
-
const child = new aidenAgent_1.AidenAgent({
|
|
262
|
-
provider: childProvider,
|
|
263
|
-
tools: childTools,
|
|
264
|
-
toolExecutor: childExecutor,
|
|
265
|
-
maxTurns: childOpts.maxIterations,
|
|
266
|
-
providerId: childOpts.provider.providerId,
|
|
267
|
-
modelId: childOpts.provider.modelId,
|
|
268
|
-
// No promptBuilder — children get a brief system prompt
|
|
269
|
-
// (same lesson as v4.1-subagent.1: full SOUL.md makes
|
|
270
|
-
// trivial fanouts spend 30s+ on verbose self-introductions).
|
|
271
|
-
});
|
|
272
|
-
if (childOpts.signal.aborted) {
|
|
273
|
-
throw new Error('aborted before dispatch');
|
|
274
|
-
}
|
|
275
|
-
const roleLine = childOpts.role ? `Role: ${childOpts.role}. ` : '';
|
|
276
|
-
const childSystemPrompt = `You are one of N parallel subagents. ${roleLine}` +
|
|
277
|
-
`Answer the user's request concisely. Use available tools when ` +
|
|
278
|
-
`the answer requires real-world information you don't have memorized.`;
|
|
279
|
-
const history = [
|
|
280
|
-
{ role: 'system', content: childSystemPrompt },
|
|
281
|
-
{ role: 'user', content: childOpts.prompt },
|
|
282
|
-
];
|
|
283
|
-
const result = await child.runConversation(history);
|
|
284
|
-
return result.finalContent;
|
|
298
|
+
},
|
|
299
|
+
parentProvider: finalAdapter,
|
|
300
|
+
parentProviderId: providerId,
|
|
301
|
+
parentModelId: modelId,
|
|
302
|
+
runStore: mcpRunStore,
|
|
303
|
+
instanceId: mcpInstanceId,
|
|
304
|
+
logger: opts.logger,
|
|
285
305
|
},
|
|
306
|
+
// No resolveParentRunId / resolveParentSessionId for MCP — the
|
|
307
|
+
// MCP server doesn't run a turn loop with its own `runs` row;
|
|
308
|
+
// each tool invocation arrives discrete from the client. Child
|
|
309
|
+
// rows therefore have NULL spawned_from_run_id, which is the
|
|
310
|
+
// honest representation (no MCP-side parent to link to).
|
|
286
311
|
}));
|
|
287
312
|
opts.logger.info('subagent_fanout: wired (replaces stub) [mcp serve]', {
|
|
288
313
|
providerId,
|
|
289
314
|
modelId,
|
|
290
315
|
fallback: finalAdapter instanceof providerFallback_1.FallbackAdapter ? 'FallbackAdapter' : 'direct',
|
|
316
|
+
instanceId: mcpInstanceId,
|
|
291
317
|
});
|
|
292
318
|
}
|
|
293
319
|
async function runMcpSubcommand(action, opts = {}) {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Shiva Deore (Taracod).
|
|
4
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
5
|
+
*
|
|
6
|
+
* Aiden — local-first agent.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* cli/v4/commands/plannerGuard.ts — v4.6 Phase 2M.
|
|
10
|
+
*
|
|
11
|
+
* `/planner-guard on|off|status` — flip the keyword-based per-turn
|
|
12
|
+
* tool narrower (`moat/plannerGuard.ts`) live, no restart needed.
|
|
13
|
+
*
|
|
14
|
+
* Default: OFF. Smart models (GPT-5.5, Claude Sonnet 4.5+, Opus)
|
|
15
|
+
* select tools fine from the full catalog every turn, the way the
|
|
16
|
+
* reference multi-agent systems do. Per-turn narrowing was a
|
|
17
|
+
* v4.1-era workaround for smaller local models that got overwhelmed
|
|
18
|
+
* by 50+ tool schemas — opt in for that case via env (set
|
|
19
|
+
* `AIDEN_PLANNER_GUARD=1` at boot) or this slash command.
|
|
20
|
+
*
|
|
21
|
+
* Persists to `runtime_toggles.planner_guard` in config.yaml when
|
|
22
|
+
* a ConfigManager is wired (the normal REPL path). Env var
|
|
23
|
+
* `AIDEN_PLANNER_GUARD` always wins over both — see runtimeToggles.ts.
|
|
24
|
+
*
|
|
25
|
+
* Mirrors `/sandbox`, `/tce`, `/browser-depth`, `/suggestions`
|
|
26
|
+
* verbatim — same helpers, same output shape.
|
|
27
|
+
*/
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.plannerGuard = void 0;
|
|
30
|
+
const _runtimeToggleHelpers_1 = require("./_runtimeToggleHelpers");
|
|
31
|
+
exports.plannerGuard = {
|
|
32
|
+
name: 'planner-guard',
|
|
33
|
+
description: 'Toggle keyword-based per-turn tool narrowing (default OFF, opt-in).',
|
|
34
|
+
category: 'system',
|
|
35
|
+
icon: '🧭',
|
|
36
|
+
handler: async (ctx) => {
|
|
37
|
+
const sub = (0, _runtimeToggleHelpers_1.parseSubcommand)(ctx.args[0]);
|
|
38
|
+
if (sub === 'on') {
|
|
39
|
+
await (0, _runtimeToggleHelpers_1.flip)('planner_guard', true, ctx);
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
if (sub === 'off') {
|
|
43
|
+
await (0, _runtimeToggleHelpers_1.flip)('planner_guard', false, ctx);
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
46
|
+
if (sub === 'status') {
|
|
47
|
+
(0, _runtimeToggleHelpers_1.printStatus)('planner_guard', ctx);
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
ctx.display.printError('Usage: /planner-guard on|off|status');
|
|
51
|
+
return {};
|
|
52
|
+
},
|
|
53
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Shiva Deore (Taracod).
|
|
4
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
5
|
+
*
|
|
6
|
+
* Aiden — local-first agent.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* cli/v4/commands/recovery.ts — v4.6 Phase 3b.
|
|
10
|
+
*
|
|
11
|
+
* `/recovery list [limit]` — top N recurring failure patterns
|
|
12
|
+
* `/recovery show <signature>` — details for one signature + reports
|
|
13
|
+
* `/recovery clear <signature>` — operator says "fixed; stop counting"
|
|
14
|
+
*
|
|
15
|
+
* Backed by the v7 `failure_signatures` + `recovery_reports` tables
|
|
16
|
+
* via the `RecoveryStore` singleton (initialised at REPL/daemon/MCP
|
|
17
|
+
* boot). All three sub-actions degrade cleanly when the store isn't
|
|
18
|
+
* initialised — print a non-fatal error and return.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.recovery = void 0;
|
|
22
|
+
const recoveryStore_1 = require("../../../core/v4/selfimprovement/recoveryStore");
|
|
23
|
+
/** Format a wall-clock ms timestamp as a compact UTC label. */
|
|
24
|
+
function formatTs(ms) {
|
|
25
|
+
return new Date(ms).toISOString().slice(0, 19) + 'Z';
|
|
26
|
+
}
|
|
27
|
+
/** Right-pad to width; truncate with ellipsis when too long. */
|
|
28
|
+
function pad(value, width) {
|
|
29
|
+
const s = String(value);
|
|
30
|
+
if (s.length === width)
|
|
31
|
+
return s;
|
|
32
|
+
if (s.length < width)
|
|
33
|
+
return s + ' '.repeat(width - s.length);
|
|
34
|
+
return s.slice(0, Math.max(0, width - 1)) + '…';
|
|
35
|
+
}
|
|
36
|
+
exports.recovery = {
|
|
37
|
+
name: 'recovery',
|
|
38
|
+
description: 'Inspect recurring failure patterns + recoveries (v4.6 Phase 3b).',
|
|
39
|
+
category: 'system',
|
|
40
|
+
icon: '🩹',
|
|
41
|
+
handler: async (ctx) => {
|
|
42
|
+
const action = (ctx.args[0] ?? 'list').toLowerCase();
|
|
43
|
+
const store = (0, recoveryStore_1.getRecoveryStore)();
|
|
44
|
+
if (!store) {
|
|
45
|
+
ctx.display.printError('recovery: recovery store not initialised — daemon DB unavailable?');
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
if (action === 'list') {
|
|
49
|
+
const limitArg = ctx.args[1];
|
|
50
|
+
const parsed = limitArg !== undefined ? Number.parseInt(limitArg, 10) : NaN;
|
|
51
|
+
const limit = Number.isFinite(parsed) && parsed > 0 ? parsed : 10;
|
|
52
|
+
const rows = store.listTopFailures(limit);
|
|
53
|
+
if (rows.length === 0) {
|
|
54
|
+
ctx.display.write('No recurring failures recorded yet.\n');
|
|
55
|
+
ctx.display.dim(' TCE writes failure signatures on classify; recoveries on failure→success transition.');
|
|
56
|
+
return {};
|
|
57
|
+
}
|
|
58
|
+
ctx.display.write(`${pad('signature', 50)} ${pad('occur', 6)} ${pad('recov', 6)} last_strategy\n`);
|
|
59
|
+
for (const r of rows) {
|
|
60
|
+
ctx.display.write(`${pad(r.signature, 50)} ${pad(r.occurrences, 6)} ${pad(r.recoveredCount, 6)} ${r.lastRecoveryStrategy ?? '-'}\n`);
|
|
61
|
+
}
|
|
62
|
+
ctx.display.write(`\n${rows.length} signature${rows.length === 1 ? '' : 's'} shown\n`);
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
if (action === 'show') {
|
|
66
|
+
const sig = ctx.args[1];
|
|
67
|
+
if (!sig) {
|
|
68
|
+
ctx.display.printError('Usage: /recovery show <signature>');
|
|
69
|
+
return {};
|
|
70
|
+
}
|
|
71
|
+
const row = store.getBySignature(sig);
|
|
72
|
+
if (!row) {
|
|
73
|
+
ctx.display.printError(`recovery: signature not found: ${sig}`);
|
|
74
|
+
return {};
|
|
75
|
+
}
|
|
76
|
+
ctx.display.write(`signature: ${row.signature}\n`);
|
|
77
|
+
ctx.display.write(`tool_name: ${row.toolName}\n`);
|
|
78
|
+
ctx.display.write(`failure_category: ${row.failureCategory}\n`);
|
|
79
|
+
ctx.display.write(`occurrences: ${row.occurrences}\n`);
|
|
80
|
+
ctx.display.write(`recovered_count: ${row.recoveredCount}\n`);
|
|
81
|
+
ctx.display.write(`first_seen: ${formatTs(row.firstSeenAt)}\n`);
|
|
82
|
+
ctx.display.write(`last_seen: ${formatTs(row.lastSeenAt)}\n`);
|
|
83
|
+
const reports = store.listReportsForSignature(row.id, 20);
|
|
84
|
+
if (reports.length === 0) {
|
|
85
|
+
ctx.display.dim(' (no recovery reports yet for this signature)');
|
|
86
|
+
return {};
|
|
87
|
+
}
|
|
88
|
+
ctx.display.write(`\nrecovery reports (${reports.length}, newest first):\n`);
|
|
89
|
+
for (const r of reports) {
|
|
90
|
+
ctx.display.write(` [${formatTs(r.createdAt)}] strategy=${r.successfulStrategy}`);
|
|
91
|
+
if (r.failedAttempts !== undefined) {
|
|
92
|
+
ctx.display.write(` failed=${r.failedAttempts}`);
|
|
93
|
+
}
|
|
94
|
+
if (r.sessionId)
|
|
95
|
+
ctx.display.write(` session=${r.sessionId}`);
|
|
96
|
+
ctx.display.write('\n');
|
|
97
|
+
if (r.notes)
|
|
98
|
+
ctx.display.dim(` ${r.notes}`);
|
|
99
|
+
if (r.verification)
|
|
100
|
+
ctx.display.dim(` verified: ${r.verification}`);
|
|
101
|
+
}
|
|
102
|
+
return {};
|
|
103
|
+
}
|
|
104
|
+
if (action === 'clear') {
|
|
105
|
+
const sig = ctx.args[1];
|
|
106
|
+
if (!sig) {
|
|
107
|
+
ctx.display.printError('Usage: /recovery clear <signature>');
|
|
108
|
+
return {};
|
|
109
|
+
}
|
|
110
|
+
const ok = store.clearSignature(sig);
|
|
111
|
+
if (ok) {
|
|
112
|
+
ctx.display.write(`recovery: cleared signature ${sig}\n`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
ctx.display.printError(`recovery: signature not found: ${sig}`);
|
|
116
|
+
}
|
|
117
|
+
return {};
|
|
118
|
+
}
|
|
119
|
+
ctx.display.printError('Usage: /recovery list [limit] | show <signature> | clear <signature>');
|
|
120
|
+
return {};
|
|
121
|
+
},
|
|
122
|
+
};
|
|
@@ -62,11 +62,17 @@ function cmdList(runStore, argv, out) {
|
|
|
62
62
|
const status = argv.status && allowedStatuses.has(argv.status)
|
|
63
63
|
? argv.status
|
|
64
64
|
: undefined;
|
|
65
|
+
// v4.6 Phase 2Q-B — default `topLevelOnly: true` hides children.
|
|
66
|
+
// `--include-children` flag (parsed by the CLI argv layer into
|
|
67
|
+
// `includeChildren: true`) flips the predicate to drop the IS NULL
|
|
68
|
+
// filter so child rows appear inline with parents.
|
|
69
|
+
const includeChildren = argv.includeChildren === true;
|
|
65
70
|
const rows = runStore.listRecent({
|
|
66
71
|
limit: argv.limit ?? 50,
|
|
67
72
|
status,
|
|
68
73
|
source: argv.source,
|
|
69
74
|
sessionIdPrefix: argv.trigger,
|
|
75
|
+
topLevelOnly: !includeChildren,
|
|
70
76
|
});
|
|
71
77
|
if (rows.length === 0) {
|
|
72
78
|
out('No runs match the filter.\n');
|
|
@@ -76,9 +82,23 @@ function cmdList(runStore, argv, out) {
|
|
|
76
82
|
for (const r of rows) {
|
|
77
83
|
const started = new Date(r.startedAt).toISOString().slice(0, 19) + 'Z';
|
|
78
84
|
const finish = r.finishReason ?? '-';
|
|
79
|
-
|
|
85
|
+
// v4.6 Phase 2Q-B — child-count badge. Only relevant for the
|
|
86
|
+
// top-level view (when --include-children is OFF). Skipped on
|
|
87
|
+
// the flat view to avoid double-counting visual weight: in flat
|
|
88
|
+
// mode the children are already on screen as their own rows.
|
|
89
|
+
let badge = '';
|
|
90
|
+
if (!includeChildren) {
|
|
91
|
+
const { total, completed } = runStore.countChildren(r.id);
|
|
92
|
+
if (total > 0) {
|
|
93
|
+
badge = ` (${total} ${total === 1 ? 'child' : 'children'}, ${completed} OK)`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
out(`${String(r.id).padEnd(6)} ${r.status.padEnd(11)} ${finish.padEnd(11)} ${started.padEnd(20)} ${r.sessionId}${badge}\n`);
|
|
80
97
|
}
|
|
81
|
-
|
|
98
|
+
const hint = includeChildren
|
|
99
|
+
? ' (parents + sub-agent children)'
|
|
100
|
+
: ' (top-level; use --include-children for sub-agents)';
|
|
101
|
+
out(`\n${rows.length} run${rows.length === 1 ? '' : 's'} shown${hint}\n`);
|
|
82
102
|
return 0;
|
|
83
103
|
}
|
|
84
104
|
// ── show ──────────────────────────────────────────────────────────────────
|