aiden-runtime 4.9.0 → 4.9.2
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 +1 -1
- package/dist/cli/v4/aidenCLI.js +2 -2
- package/dist/cli/v4/aidenPrompt.js +12 -0
- package/dist/cli/v4/chatSession.js +43 -17
- package/dist/cli/v4/commands/channel.js +4 -6
- package/dist/cli/v4/commands/cron.js +6 -1
- package/dist/cli/v4/commands/daemon.js +6 -1
- package/dist/cli/v4/commands/daemonDoctor.js +6 -6
- package/dist/cli/v4/commands/daemonStatus.js +46 -27
- package/dist/cli/v4/commands/help.js +3 -0
- package/dist/cli/v4/commands/hooks.js +39 -1
- package/dist/cli/v4/commands/hooksSlash.js +33 -0
- package/dist/cli/v4/commands/index.js +9 -1
- package/dist/cli/v4/commands/mcp.js +2 -2
- package/dist/cli/v4/commands/memory.js +6 -1
- package/dist/cli/v4/commands/memorySlash.js +38 -0
- package/dist/cli/v4/commands/plugins.js +4 -6
- package/dist/cli/v4/commands/trigger.js +18 -18
- package/dist/cli/v4/confirmPrompt.js +67 -0
- package/dist/cli/v4/ui/progressBar.js +179 -0
- package/dist/cli/v4/util/closestAction.js +48 -0
- package/dist/core/v4/daemon/db/migrations.js +398 -398
- package/dist/core/v4/daemon/idempotency/runIdempotencyStore.js +10 -10
- package/dist/core/v4/daemon/incarnationStore.js +9 -9
- package/dist/core/v4/daemon/runs/attemptStore.js +8 -8
- package/dist/core/v4/daemon/runs/reclaim.js +12 -12
- package/dist/core/v4/daemon/runs/stuckAttemptWatchdog.js +19 -19
- package/dist/core/v4/daemon/spans/spanStore.js +14 -14
- package/dist/core/v4/daemon/triggerBus.js +61 -61
- package/dist/core/v4/hooks/auditQuery.js +11 -11
- package/dist/core/v4/hooks/dispatcher.js +13 -13
- package/dist/core/v4/hooks/registry.js +8 -8
- package/dist/core/v4/mcp/transport.js +9 -9
- package/dist/core/v4/update/depWarningFilter.js +76 -0
- package/dist/core/v4/update/executeInstall.js +70 -53
- package/dist/core/v4/update/platformInstructions.js +128 -0
- package/dist/core/v4/update/recoveryScript.js +70 -0
- package/dist/core/v4/util/spawnCommand.js +151 -0
- package/package.json +1 -1
- package/themes/default.yaml +52 -52
- package/themes/dracula.yaml +32 -32
- package/themes/light.yaml +32 -32
- package/themes/monochrome.yaml +31 -31
- package/themes/tokyo-night.yaml +32 -32
package/README.md
CHANGED
|
@@ -94,7 +94,7 @@ Windows · Linux · WSL · macOS (API Mode)
|
|
|
94
94
|

|
|
95
95
|

|
|
96
96
|

|
|
97
|
-

|
|
98
98
|
|
|
99
99
|
</div>
|
|
100
100
|
|
package/dist/cli/v4/aidenCLI.js
CHANGED
|
@@ -568,7 +568,7 @@ async function main(argv, opts = {}) {
|
|
|
568
568
|
});
|
|
569
569
|
program
|
|
570
570
|
.command('voice [args...]')
|
|
571
|
-
.description('Voice diagnostics + one-shot TTS / transcribe
|
|
571
|
+
.description('Voice diagnostics + one-shot TTS / transcribe. ' +
|
|
572
572
|
'Usage: aiden voice doctor | tts "<text>" | transcribe <file>')
|
|
573
573
|
.allowUnknownOption()
|
|
574
574
|
.action(async (args) => {
|
|
@@ -611,7 +611,7 @@ async function main(argv, opts = {}) {
|
|
|
611
611
|
// v4.1 placeholders. (`tui` graduated to a real flag in Phase 15.)
|
|
612
612
|
program
|
|
613
613
|
.command('cron [args...]')
|
|
614
|
-
.description('Cron diagnostics + one-shot list / run
|
|
614
|
+
.description('Cron diagnostics + one-shot list / run. ' +
|
|
615
615
|
'Usage: aiden cron status | list | run <id>')
|
|
616
616
|
.allowUnknownOption()
|
|
617
617
|
.action(async (args) => {
|
|
@@ -291,6 +291,18 @@ exports.default = (0, core_1.createPrompt)((config, done) => {
|
|
|
291
291
|
line = `${message} ${theme.style.answer(value)}`;
|
|
292
292
|
}
|
|
293
293
|
else {
|
|
294
|
+
// v4.9.2 Slice 2 (commit 0d0668f1) attempted to fix cursor
|
|
295
|
+
// misalignment by post-pending cursorBackward(ghost.length).
|
|
296
|
+
// Live-REPL diagnostic proved the fix is structurally inert:
|
|
297
|
+
// @inquirer/core's screen-manager.js:56 appends an ABSOLUTE
|
|
298
|
+
// cursorTo(this.cursorPos.cols) AFTER our content, overriding
|
|
299
|
+
// any cursor-positioning escape we emit inline. The real fix
|
|
300
|
+
// requires either rendering the ghost via a side-channel post-
|
|
301
|
+
// render write or moving it out of the inline line entirely —
|
|
302
|
+
// both need the proper save/restore refactor scheduled for v4.10
|
|
303
|
+
// once the prompt has a real screen-manager-aware test harness.
|
|
304
|
+
// Reverted here so the shipped v4.9.2 doesn't carry a "fix" that
|
|
305
|
+
// doesn't fix anything. Bug D status: known, deferred.
|
|
294
306
|
const ghostStr = ghost ? dim(ghost) : '';
|
|
295
307
|
line = `${prefix} ${message}${value}${ghostStr}`;
|
|
296
308
|
}
|
|
@@ -82,6 +82,7 @@ const progressBar_1 = require("./display/progressBar");
|
|
|
82
82
|
const uiBuild_1 = require("./uiBuild");
|
|
83
83
|
const sessionSummaryGate_1 = require("./sessionSummaryGate");
|
|
84
84
|
const aidenPrompt_1 = __importDefault(require("./aidenPrompt"));
|
|
85
|
+
const confirmPrompt_1 = require("./confirmPrompt");
|
|
85
86
|
const historyStore_1 = require("./historyStore");
|
|
86
87
|
const modelMetadata_1 = require("../../core/v4/modelMetadata");
|
|
87
88
|
// v4.1.3-prebump: classify provider errors so the catch path can show
|
|
@@ -496,17 +497,21 @@ class ChatSession {
|
|
|
496
497
|
agent: this.opts.agent,
|
|
497
498
|
pluginLoader: this.opts.pluginLoader,
|
|
498
499
|
channelManager: this.opts.channelManager,
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
500
|
+
// v4.9.2 Slice 3 — UX-rebuilt confirmation primitive.
|
|
501
|
+
// The stdin/keypress mechanics worked correctly all along;
|
|
502
|
+
// users simply couldn't see the prompt was open. The
|
|
503
|
+
// extracted `runConfirm` helper now owns the canonical
|
|
504
|
+
// y/N hint, the warn-tinted '?' glyph, the
|
|
505
|
+
// suggestionsDisabled flag (so confirmations skip ghost-
|
|
506
|
+
// match against outer chat history), and the per-input
|
|
507
|
+
// honest cancellation message.
|
|
508
|
+
//
|
|
509
|
+
// Phase 17.1 anchor: the previous primitive read
|
|
510
|
+
// `this.opts.promptApi?` (undefined → silently returned
|
|
511
|
+
// false → "Grant cancelled" before user could type) —
|
|
512
|
+
// fixed by routing through the resolved local `promptApi`.
|
|
513
|
+
// That fix stands; Slice 3 adds the UX layer on top.
|
|
514
|
+
confirm: (msg) => (0, confirmPrompt_1.runConfirm)(msg, promptApi, this.opts.display),
|
|
510
515
|
// Phase 18: raw text prompt for /auth login OAuth code paste.
|
|
511
516
|
prompt: (msg) => promptApi.readLine(msg),
|
|
512
517
|
});
|
|
@@ -1656,6 +1661,10 @@ class ChatSession {
|
|
|
1656
1661
|
// .update_check.json cache so subsequent boots stay quiet until
|
|
1657
1662
|
// a newer release ships.
|
|
1658
1663
|
try {
|
|
1664
|
+
// v4.9.1 — modal sits BELOW the welcome banner with a blank
|
|
1665
|
+
// separator. Prevents the box from visually overlapping the
|
|
1666
|
+
// boot card on first-paint (smoke-reported regression).
|
|
1667
|
+
display.write('\n');
|
|
1659
1668
|
await this.maybeShowBootUpdatePrompt();
|
|
1660
1669
|
}
|
|
1661
1670
|
catch { /* never let the update prompt crash boot */ }
|
|
@@ -1713,13 +1722,24 @@ class ChatSession {
|
|
|
1713
1722
|
});
|
|
1714
1723
|
if (choice === 'install') {
|
|
1715
1724
|
if (method.inProcessInstallSupported) {
|
|
1716
|
-
|
|
1717
|
-
|
|
1725
|
+
// v4.9.1 — drive a live progress bar off the executor's
|
|
1726
|
+
// phase callback. The bar degrades cleanly on non-TTY, NO_COLOR,
|
|
1727
|
+
// and dumb terminals — see cli/v4/ui/progressBar.ts.
|
|
1728
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
1729
|
+
const pb = require('./ui/progressBar');
|
|
1730
|
+
const bar = pb.startProgressBar({
|
|
1731
|
+
label: `Installing aiden-runtime ${status.latest}...`,
|
|
1732
|
+
phases: ['spawning', 'resolving', 'downloading', 'extracting', 'verifying', 'installed'],
|
|
1733
|
+
});
|
|
1734
|
+
const result = await ei.executeInstall({
|
|
1735
|
+
packageSpec: `aiden-runtime@${status.latest}`,
|
|
1736
|
+
onPhase: (p) => { bar.setPhase(p); bar.setPercent(pb.npmInstallPhasePercent(p)); },
|
|
1737
|
+
});
|
|
1718
1738
|
if (result.success) {
|
|
1719
|
-
|
|
1720
|
-
this.opts.display.dim('Restart Aiden to apply: type /quit then re-run `aiden`.');
|
|
1739
|
+
bar.complete(`aiden-runtime ${result.installedVersion ?? status.latest} installed. Restart Aiden to apply: type /quit then re-run \`aiden\`.`);
|
|
1721
1740
|
}
|
|
1722
1741
|
else {
|
|
1742
|
+
bar.fail('Install failed.');
|
|
1723
1743
|
this.opts.display.warn(result.error ?? 'Install failed (no error message).');
|
|
1724
1744
|
}
|
|
1725
1745
|
}
|
|
@@ -2070,9 +2090,15 @@ function createDefaultPromptApi(opts = {}) {
|
|
|
2070
2090
|
// aidenPrompt component (ghost text + slash dropdown + history nav).
|
|
2071
2091
|
const useLegacyPrompt = (0, uiBuild_1.isNoUiMode)() || !opts.commands;
|
|
2072
2092
|
return {
|
|
2073
|
-
async readLine(prompt) {
|
|
2093
|
+
async readLine(prompt, readOpts) {
|
|
2074
2094
|
try {
|
|
2075
|
-
|
|
2095
|
+
// v4.9.2 Slice 3 — confirmation prompts (suggestionsDisabled)
|
|
2096
|
+
// always route through the legacy inquirer input path. No
|
|
2097
|
+
// ghost-text (would autocomplete from outer chat history —
|
|
2098
|
+
// wrong context for a y/n question), no slash dropdown
|
|
2099
|
+
// (irrelevant for confirmations). Inquirer's plain input is
|
|
2100
|
+
// the well-tested baseline for single-shot questions.
|
|
2101
|
+
if (readOpts?.suggestionsDisabled || useLegacyPrompt) {
|
|
2076
2102
|
return (await inq.input({ message: prompt, theme: promptTheme })) ?? '';
|
|
2077
2103
|
}
|
|
2078
2104
|
// Fetch history just-in-time so each read sees the latest
|
|
@@ -255,10 +255,9 @@ async function telegramRemove(ctx) {
|
|
|
255
255
|
return;
|
|
256
256
|
}
|
|
257
257
|
const proceed = await confirm('Remove the Telegram bot token? This stops polling.');
|
|
258
|
-
|
|
259
|
-
|
|
258
|
+
// v4.9.2 Slice 3 — confirm() now owns the rejection message.
|
|
259
|
+
if (!proceed)
|
|
260
260
|
return;
|
|
261
|
-
}
|
|
262
261
|
// Stop the live adapter first so polling actually halts even if the
|
|
263
262
|
// .env write fails for some reason.
|
|
264
263
|
const manager = ctx.channelManager;
|
|
@@ -297,10 +296,9 @@ async function telegramTakeover(ctx) {
|
|
|
297
296
|
const proceed = confirm
|
|
298
297
|
? await confirm('Take over Telegram polling? This will boot any other Aiden instance off the bot.')
|
|
299
298
|
: true;
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
// v4.9.2 Slice 3 — confirm() now owns the rejection message.
|
|
300
|
+
if (!proceed)
|
|
302
301
|
return;
|
|
303
|
-
}
|
|
304
302
|
const spinner = display.startSpinner('Reclaiming Telegram polling…');
|
|
305
303
|
let result;
|
|
306
304
|
try {
|
|
@@ -327,8 +327,13 @@ async function cmdRemove(ctx, args) {
|
|
|
327
327
|
else if (ctx.confirm) {
|
|
328
328
|
ok = await ctx.confirm(question);
|
|
329
329
|
}
|
|
330
|
+
// v4.9.2 Slice 3 — when ctx.confirm was the source, the primitive
|
|
331
|
+
// already printed a per-input rejection message. The ctx.prompt
|
|
332
|
+
// branch above does its own y/N parsing, so it still owns its own
|
|
333
|
+
// "Cancelled." line.
|
|
330
334
|
if (!ok) {
|
|
331
|
-
ctx.
|
|
335
|
+
if (ctx.prompt)
|
|
336
|
+
ctx.display.dim('Cancelled.');
|
|
332
337
|
return;
|
|
333
338
|
}
|
|
334
339
|
if ((0, cronManager_1.deleteJob)(job.id)) {
|
|
@@ -104,10 +104,15 @@ async function runDaemonSubcommand(action, args, opts = {}) {
|
|
|
104
104
|
writeErr: err,
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
|
-
default:
|
|
107
|
+
default: {
|
|
108
108
|
err(`Unknown daemon action: ${action}\n`);
|
|
109
|
+
const { closestAction } = await Promise.resolve().then(() => __importStar(require('../util/closestAction')));
|
|
110
|
+
const m = closestAction(action, ['install', 'uninstall', 'start', 'stop', 'restart', 'status', 'logs', 'doctor']);
|
|
111
|
+
if (m)
|
|
112
|
+
err(`Did you mean: ${m}?\n\n`);
|
|
109
113
|
err('Actions: install, uninstall, start, stop, restart, status, logs, doctor\n');
|
|
110
114
|
return 2;
|
|
115
|
+
}
|
|
111
116
|
}
|
|
112
117
|
}
|
|
113
118
|
const SYSTEMD_UNIT_NAME = 'aiden.service';
|
|
@@ -85,11 +85,11 @@ function collectDoctorChecks(rootDir) {
|
|
|
85
85
|
detail: `current=${ver} latest=${migrations_1.LATEST_SCHEMA_VERSION}`,
|
|
86
86
|
fixable: false });
|
|
87
87
|
// 3. Recent incarnation
|
|
88
|
-
const inc = db.prepare(`SELECT incarnation_id, started_at, ended_at, exit_reason FROM daemon_incarnations
|
|
88
|
+
const inc = db.prepare(`SELECT incarnation_id, started_at, ended_at, exit_reason FROM daemon_incarnations
|
|
89
89
|
ORDER BY started_at DESC LIMIT 1`).get();
|
|
90
90
|
if (!inc) {
|
|
91
91
|
checks.push({ name: 'recent incarnation', status: 'warn',
|
|
92
|
-
detail: 'no daemon_incarnations rows (daemon never
|
|
92
|
+
detail: 'no daemon_incarnations rows (daemon never started in this root)',
|
|
93
93
|
fixable: false });
|
|
94
94
|
}
|
|
95
95
|
else {
|
|
@@ -100,7 +100,7 @@ function collectDoctorChecks(rootDir) {
|
|
|
100
100
|
}
|
|
101
101
|
// 4. Recent crashes (24h)
|
|
102
102
|
const sinceIso = new Date(Date.now() - TWENTY_FOUR_HOURS_MS).toISOString();
|
|
103
|
-
const crashes = db.prepare(`SELECT COUNT(*) AS c FROM daemon_incarnations
|
|
103
|
+
const crashes = db.prepare(`SELECT COUNT(*) AS c FROM daemon_incarnations
|
|
104
104
|
WHERE exit_reason = 'crash' AND started_at > ?`).get(sinceIso);
|
|
105
105
|
checks.push({ name: 'recent crashes (24h)',
|
|
106
106
|
status: crashes.c === 0 ? 'ok' : crashes.c > 3 ? 'warn' : 'ok',
|
|
@@ -111,7 +111,7 @@ function collectDoctorChecks(rootDir) {
|
|
|
111
111
|
if (tableExists(db, 'run_attempts')) {
|
|
112
112
|
const currentInc = inc?.incarnation_id ?? '';
|
|
113
113
|
const cutoffIso = new Date(Date.now() - 30 * 60 * 1000).toISOString();
|
|
114
|
-
stuckAttempts = db.prepare(`SELECT COUNT(*) AS c FROM run_attempts
|
|
114
|
+
stuckAttempts = db.prepare(`SELECT COUNT(*) AS c FROM run_attempts
|
|
115
115
|
WHERE status='running' AND incarnation_id != ? AND started_at < ?`).get(currentInc, cutoffIso).c;
|
|
116
116
|
}
|
|
117
117
|
checks.push({ name: 'stuck attempts',
|
|
@@ -125,7 +125,7 @@ function collectDoctorChecks(rootDir) {
|
|
|
125
125
|
let orphanSpans = 0;
|
|
126
126
|
if (tableExists(db, 'spans')) {
|
|
127
127
|
const currentInc = inc?.incarnation_id ?? '';
|
|
128
|
-
orphanSpans = db.prepare(`SELECT COUNT(*) AS c FROM spans
|
|
128
|
+
orphanSpans = db.prepare(`SELECT COUNT(*) AS c FROM spans
|
|
129
129
|
WHERE status IS NULL AND ended_at IS NULL AND incarnation_id != ?`).get(currentInc).c;
|
|
130
130
|
}
|
|
131
131
|
checks.push({ name: 'orphan spans',
|
|
@@ -147,7 +147,7 @@ function collectDoctorChecks(rootDir) {
|
|
|
147
147
|
// 8. Stale-claimed trigger events
|
|
148
148
|
let staleClaimed = 0;
|
|
149
149
|
if (tableExists(db, 'trigger_events')) {
|
|
150
|
-
staleClaimed = db.prepare(`SELECT COUNT(*) AS c FROM trigger_events
|
|
150
|
+
staleClaimed = db.prepare(`SELECT COUNT(*) AS c FROM trigger_events
|
|
151
151
|
WHERE status='claimed' AND claim_expires_at IS NOT NULL AND claim_expires_at < ?`).get(Date.now()).c;
|
|
152
152
|
}
|
|
153
153
|
checks.push({ name: 'stale-claimed trigger events',
|
|
@@ -22,44 +22,63 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.daemonStatus = void 0;
|
|
25
|
+
exports.daemonStatus = exports.DAEMON_SHELL_ONLY = void 0;
|
|
26
|
+
exports.dispatchDaemonSlash = dispatchDaemonSlash;
|
|
26
27
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
27
28
|
const node_os_1 = __importDefault(require("node:os"));
|
|
28
29
|
const node_path_1 = __importDefault(require("node:path"));
|
|
29
|
-
const daemon_1 = require("
|
|
30
|
+
const daemon_1 = require("./daemon");
|
|
31
|
+
const daemon_2 = require("../../../core/v4/daemon");
|
|
30
32
|
const paths_1 = require("../../../core/v4/paths");
|
|
33
|
+
/**
|
|
34
|
+
* v4.9.1 amendment — `/daemon` defaults to `doctor` and routes
|
|
35
|
+
* `doctor` / `logs` to the existing `runDaemonSubcommand`. The pure-
|
|
36
|
+
* REPL `/daemon status` (in-process snapshot) stays inline. Lifecycle
|
|
37
|
+
* ops shell-hint — they need terminal control we can't grant inside chat.
|
|
38
|
+
*/
|
|
39
|
+
exports.DAEMON_SHELL_ONLY = new Set(['install', 'uninstall', 'start', 'stop', 'restart']);
|
|
40
|
+
async function dispatchDaemonSlash(opts) {
|
|
41
|
+
const a = (opts.action || 'doctor').toLowerCase();
|
|
42
|
+
if (exports.DAEMON_SHELL_ONLY.has(a)) {
|
|
43
|
+
opts.write(`⚠ /daemon ${a} not available inside chat (requires terminal control)\n`);
|
|
44
|
+
opts.write(' Quit (/quit) and run from shell:\n\n');
|
|
45
|
+
const tail = opts.args.length > 0 ? ' ' + opts.args.join(' ') : '';
|
|
46
|
+
opts.write(` aiden daemon ${a}${tail}\n`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (a === 'status' && opts.paintStatus) {
|
|
50
|
+
try {
|
|
51
|
+
opts.paintStatus();
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
opts.warn(`/daemon status: failed to read state (${e instanceof Error ? e.message : String(e)})`);
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
await opts.runDaemon(a, opts.args, { writeOut: opts.write, writeErr: opts.write });
|
|
59
|
+
}
|
|
31
60
|
exports.daemonStatus = {
|
|
32
61
|
name: 'daemon',
|
|
33
|
-
description: '
|
|
62
|
+
description: 'Daemon diagnostics (doctor / status / logs).',
|
|
34
63
|
category: 'system',
|
|
35
64
|
icon: '⚙',
|
|
36
65
|
handler: async (ctx) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
ctx.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
' aiden daemon logs');
|
|
46
|
-
return {};
|
|
47
|
-
}
|
|
48
|
-
try {
|
|
49
|
-
const snapshot = readSnapshot();
|
|
50
|
-
printSnapshot(snapshot, ctx);
|
|
51
|
-
}
|
|
52
|
-
catch (e) {
|
|
53
|
-
ctx.display.warn(`/daemon status: failed to read state (${e instanceof Error ? e.message : String(e)})`);
|
|
54
|
-
}
|
|
66
|
+
await dispatchDaemonSlash({
|
|
67
|
+
action: ctx.args[0] ?? 'doctor',
|
|
68
|
+
args: ctx.args.slice(1),
|
|
69
|
+
write: (s) => ctx.display.write(s),
|
|
70
|
+
warn: (s) => ctx.display.warn(s),
|
|
71
|
+
runDaemon: daemon_1.runDaemonSubcommand,
|
|
72
|
+
paintStatus: () => printSnapshot(readSnapshot(), ctx),
|
|
73
|
+
});
|
|
55
74
|
return {};
|
|
56
75
|
},
|
|
57
76
|
};
|
|
58
77
|
// ── Snapshot collector ─────────────────────────────────────────────────────
|
|
59
78
|
function readSnapshot() {
|
|
60
79
|
const aidenRoot = (0, paths_1.resolveAidenRoot)();
|
|
61
|
-
const dbPath = (0,
|
|
62
|
-
const lockPath = (0,
|
|
80
|
+
const dbPath = (0, daemon_2.daemonDbPath)(aidenRoot);
|
|
81
|
+
const lockPath = (0, daemon_2.daemonRuntimeLockPath)(aidenRoot);
|
|
63
82
|
// ── Liveness via the in-process bootstrap handle first, then fall
|
|
64
83
|
// back to the runtime.lock PID check (covers the case where the
|
|
65
84
|
// daemon is another process and we're a REPL inspecting its db).
|
|
@@ -67,11 +86,11 @@ function readSnapshot() {
|
|
|
67
86
|
let instanceId = null;
|
|
68
87
|
let port = null;
|
|
69
88
|
let uptimeMs = null;
|
|
70
|
-
const handle = (0,
|
|
89
|
+
const handle = (0, daemon_2.getDaemonHandle)();
|
|
71
90
|
if (handle?.active && handle.instanceId) {
|
|
72
91
|
running = true;
|
|
73
92
|
instanceId = handle.instanceId;
|
|
74
|
-
port = (0,
|
|
93
|
+
port = (0, daemon_2.getDaemonConfig)().port;
|
|
75
94
|
if (handle.instanceTracker) {
|
|
76
95
|
// instanceTracker has a `getStartedAt` if exposed; otherwise
|
|
77
96
|
// derive from daemon_instances row below.
|
|
@@ -105,7 +124,7 @@ function readSnapshot() {
|
|
|
105
124
|
dailyBudget: null,
|
|
106
125
|
};
|
|
107
126
|
}
|
|
108
|
-
const db = (0,
|
|
127
|
+
const db = (0, daemon_2.openDaemonDb)(dbPath);
|
|
109
128
|
// Uptime from the instance row when we have an instanceId.
|
|
110
129
|
if (running && instanceId) {
|
|
111
130
|
try {
|
|
@@ -131,7 +150,7 @@ function readSnapshot() {
|
|
|
131
150
|
// Recent runs (last 3).
|
|
132
151
|
const recentRuns = (() => {
|
|
133
152
|
try {
|
|
134
|
-
const rows = db.prepare(`SELECT id, status, finish_reason, started_at, completed_at FROM runs
|
|
153
|
+
const rows = db.prepare(`SELECT id, status, finish_reason, started_at, completed_at FROM runs
|
|
135
154
|
ORDER BY id DESC LIMIT 3`).all();
|
|
136
155
|
return rows.map((r) => ({
|
|
137
156
|
id: r.id,
|
|
@@ -76,6 +76,9 @@ exports.SUBSECTION_MAP = {
|
|
|
76
76
|
recovery: 'System',
|
|
77
77
|
// v4.6 ONB1 slice 10 — new-user guided tour.
|
|
78
78
|
walkthrough: 'System',
|
|
79
|
+
// v4.9.1 amendment — REPL surfaces for memory + hooks (daemon already mapped).
|
|
80
|
+
memory: 'System',
|
|
81
|
+
hooks: 'System',
|
|
79
82
|
// ── Authentication ──
|
|
80
83
|
auth: 'Authentication',
|
|
81
84
|
// ── Help ──
|
|
@@ -23,6 +23,39 @@
|
|
|
23
23
|
* directory and runs a rescan, but NEVER auto-trusts anything (trust
|
|
24
24
|
* remains an explicit, deliberate user action).
|
|
25
25
|
*/
|
|
26
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
29
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
30
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
31
|
+
}
|
|
32
|
+
Object.defineProperty(o, k2, desc);
|
|
33
|
+
}) : (function(o, m, k, k2) {
|
|
34
|
+
if (k2 === undefined) k2 = k;
|
|
35
|
+
o[k2] = m[k];
|
|
36
|
+
}));
|
|
37
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
38
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
39
|
+
}) : function(o, v) {
|
|
40
|
+
o["default"] = v;
|
|
41
|
+
});
|
|
42
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
43
|
+
var ownKeys = function(o) {
|
|
44
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
45
|
+
var ar = [];
|
|
46
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
47
|
+
return ar;
|
|
48
|
+
};
|
|
49
|
+
return ownKeys(o);
|
|
50
|
+
};
|
|
51
|
+
return function (mod) {
|
|
52
|
+
if (mod && mod.__esModule) return mod;
|
|
53
|
+
var result = {};
|
|
54
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
55
|
+
__setModuleDefault(result, mod);
|
|
56
|
+
return result;
|
|
57
|
+
};
|
|
58
|
+
})();
|
|
26
59
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
60
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
61
|
};
|
|
@@ -78,10 +111,15 @@ async function runHooksSubcommand(action, args, opts = {}) {
|
|
|
78
111
|
case 'audit': return await cmdAudit(ctx);
|
|
79
112
|
case '--help':
|
|
80
113
|
case 'help': return cmdHelp(out);
|
|
81
|
-
default:
|
|
114
|
+
default: {
|
|
82
115
|
err(`Unknown hooks action: ${effective}\n`);
|
|
116
|
+
const { closestAction } = await Promise.resolve().then(() => __importStar(require('../util/closestAction')));
|
|
117
|
+
const m = closestAction(effective, ['list', 'show', 'trust', 'revoke', 'rescan', 'test', 'doctor', 'audit']);
|
|
118
|
+
if (m)
|
|
119
|
+
err(`Did you mean: ${m}?\n\n`);
|
|
83
120
|
cmdHelp(err);
|
|
84
121
|
return 2;
|
|
122
|
+
}
|
|
85
123
|
}
|
|
86
124
|
}
|
|
87
125
|
finally {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hooks = exports.HOOKS_SHELL_ONLY = void 0;
|
|
4
|
+
exports.dispatchHooksSlash = dispatchHooksSlash;
|
|
5
|
+
const hooks_1 = require("./hooks");
|
|
6
|
+
/** Actions that need an interactive confirmation prompt. */
|
|
7
|
+
exports.HOOKS_SHELL_ONLY = new Set(['trust', 'revoke']);
|
|
8
|
+
async function dispatchHooksSlash(opts) {
|
|
9
|
+
const a = (opts.action || 'list').toLowerCase();
|
|
10
|
+
if (exports.HOOKS_SHELL_ONLY.has(a)) {
|
|
11
|
+
opts.write(`⚠ /hooks ${a} not available inside chat (needs confirmation prompt)\n`);
|
|
12
|
+
opts.write(' Quit (/quit) and run from shell:\n\n');
|
|
13
|
+
const tail = opts.args.length > 0 ? ' ' + opts.args.join(' ') : '';
|
|
14
|
+
opts.write(` aiden hooks ${a}${tail}\n`);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
await opts.runHooks(a, opts.args, { writeOut: opts.write, writeErr: opts.write });
|
|
18
|
+
}
|
|
19
|
+
exports.hooks = {
|
|
20
|
+
name: 'hooks',
|
|
21
|
+
description: 'Manage hooks (list / show / rescan / test / doctor / audit).',
|
|
22
|
+
category: 'system',
|
|
23
|
+
icon: '🪝',
|
|
24
|
+
handler: async (ctx) => {
|
|
25
|
+
await dispatchHooksSlash({
|
|
26
|
+
action: ctx.args[0] ?? 'list',
|
|
27
|
+
args: ctx.args.slice(1),
|
|
28
|
+
write: (s) => ctx.display.write(s),
|
|
29
|
+
runHooks: hooks_1.runHooksSubcommand,
|
|
30
|
+
});
|
|
31
|
+
return {};
|
|
32
|
+
},
|
|
33
|
+
};
|
|
@@ -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.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.theme = 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.hooks = exports.memory = 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.theme = 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");
|
|
@@ -106,6 +106,11 @@ Object.defineProperty(exports, "recovery", { enumerable: true, get: function ()
|
|
|
106
106
|
// ONB1 slice 10 — new-user guided tour.
|
|
107
107
|
const walkthrough_1 = require("./walkthrough");
|
|
108
108
|
Object.defineProperty(exports, "walkthrough", { enumerable: true, get: function () { return walkthrough_1.walkthrough; } });
|
|
109
|
+
// v4.9.1 amendment — REPL slash surfaces for memory + hooks (mirrors CLI).
|
|
110
|
+
const memorySlash_1 = require("./memorySlash");
|
|
111
|
+
Object.defineProperty(exports, "memory", { enumerable: true, get: function () { return memorySlash_1.memory; } });
|
|
112
|
+
const hooksSlash_1 = require("./hooksSlash");
|
|
113
|
+
Object.defineProperty(exports, "hooks", { enumerable: true, get: function () { return hooksSlash_1.hooks; } });
|
|
109
114
|
/** All built-in system commands, in canonical order. */
|
|
110
115
|
exports.allCommands = [
|
|
111
116
|
help_1.help,
|
|
@@ -158,6 +163,9 @@ exports.allCommands = [
|
|
|
158
163
|
recovery_1.recovery,
|
|
159
164
|
// ONB1 slice 10 — new-user guided tour.
|
|
160
165
|
walkthrough_1.walkthrough,
|
|
166
|
+
// v4.9.1 amendment — REPL slash surfaces mirroring CLI subcommands.
|
|
167
|
+
memorySlash_1.memory,
|
|
168
|
+
hooksSlash_1.hooks,
|
|
161
169
|
clear_1.clear,
|
|
162
170
|
quit_1.quit,
|
|
163
171
|
];
|
|
@@ -266,8 +266,8 @@ async function wireSubagentFanout(opts) {
|
|
|
266
266
|
// WAL-coexistence model as REPL — connection.ts caches per-path.
|
|
267
267
|
const mcpInstanceId = `mcp-${(0, node_crypto_1.randomUUID)().slice(0, 8)}`;
|
|
268
268
|
const mcpDb = (0, daemon_1.openDaemonDb)((0, daemon_1.daemonDbPath)(opts.paths.root));
|
|
269
|
-
mcpDb.prepare(`INSERT OR IGNORE INTO daemon_instances
|
|
270
|
-
(instance_id, pid, hostname, started_at, last_heartbeat, version)
|
|
269
|
+
mcpDb.prepare(`INSERT OR IGNORE INTO daemon_instances
|
|
270
|
+
(instance_id, pid, hostname, started_at, last_heartbeat, version)
|
|
271
271
|
VALUES (?, ?, ?, ?, ?, ?)`).run(mcpInstanceId, process.pid, node_os_1.default.hostname(), Date.now(), Date.now(), version_1.VERSION);
|
|
272
272
|
const mcpRunStore = (0, daemon_1.createRunStore)({ db: mcpDb });
|
|
273
273
|
// v4.6 Phase 3b — self-improvement loop singleton against the
|
|
@@ -155,10 +155,15 @@ async function runMemorySubcommand(action, args, opts = {}) {
|
|
|
155
155
|
case 'review': return cmdReview(args, paths, opts, out, err, json);
|
|
156
156
|
case '--help':
|
|
157
157
|
case 'help': return cmdHelp(out);
|
|
158
|
-
default:
|
|
158
|
+
default: {
|
|
159
159
|
err(`Unknown memory action: ${effective}\n`);
|
|
160
|
+
const { closestAction } = await Promise.resolve().then(() => __importStar(require('../util/closestAction')));
|
|
161
|
+
const m = closestAction(effective, ['list', 'show', 'add', 'remove', 'edit', 'backup', 'restore', 'diff', 'namespaces', 'pending', 'approve', 'reject', 'review']);
|
|
162
|
+
if (m)
|
|
163
|
+
err(`Did you mean: ${m}?\n\n`);
|
|
160
164
|
cmdHelp(err);
|
|
161
165
|
return 2;
|
|
166
|
+
}
|
|
162
167
|
}
|
|
163
168
|
}
|
|
164
169
|
function cmdHelp(write) {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.memory = exports.MEMORY_SHELL_ONLY = void 0;
|
|
4
|
+
exports.dispatchMemorySlash = dispatchMemorySlash;
|
|
5
|
+
const memory_1 = require("./memory");
|
|
6
|
+
/** Actions that need the full CLI surface (confirmation / destructive). */
|
|
7
|
+
exports.MEMORY_SHELL_ONLY = new Set(['remove', 'restore']);
|
|
8
|
+
/**
|
|
9
|
+
* Pure dispatch — exported for tests + reuse. Either prints a shell
|
|
10
|
+
* hint OR delegates to the provided `runMemory` runner. Side effects
|
|
11
|
+
* confined to the supplied `write` sink.
|
|
12
|
+
*/
|
|
13
|
+
async function dispatchMemorySlash(opts) {
|
|
14
|
+
const a = (opts.action || 'list').toLowerCase();
|
|
15
|
+
if (exports.MEMORY_SHELL_ONLY.has(a)) {
|
|
16
|
+
opts.write(`⚠ /memory ${a} not available inside chat (destructive operation)\n`);
|
|
17
|
+
opts.write(' Quit (/quit) and run from shell:\n\n');
|
|
18
|
+
const tail = opts.args.length > 0 ? ' ' + opts.args.join(' ') : '';
|
|
19
|
+
opts.write(` aiden memory ${a}${tail}\n`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
await opts.runMemory(a, opts.args, { writeOut: opts.write, writeErr: opts.write });
|
|
23
|
+
}
|
|
24
|
+
exports.memory = {
|
|
25
|
+
name: 'memory',
|
|
26
|
+
description: 'Manage memory (list / show / add / namespaces / pending / approve / review).',
|
|
27
|
+
category: 'system',
|
|
28
|
+
icon: '🧠',
|
|
29
|
+
handler: async (ctx) => {
|
|
30
|
+
await dispatchMemorySlash({
|
|
31
|
+
action: ctx.args[0] ?? 'list',
|
|
32
|
+
args: ctx.args.slice(1),
|
|
33
|
+
write: (s) => ctx.display.write(s),
|
|
34
|
+
runMemory: memory_1.runMemorySubcommand,
|
|
35
|
+
});
|
|
36
|
+
return {};
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -161,10 +161,9 @@ exports.plugins = {
|
|
|
161
161
|
ctx.display.write('\n');
|
|
162
162
|
const confirmFn = ctx.confirm ?? (async () => false);
|
|
163
163
|
const allow = await confirmFn(`Install ${manifest.name} with the listed permissions? [y/N] `);
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
// v4.9.2 Slice 3 — confirm() now owns the rejection message.
|
|
165
|
+
if (!allow)
|
|
166
166
|
return {};
|
|
167
|
-
}
|
|
168
167
|
// Copy into the user plugins dir.
|
|
169
168
|
const dst = node_path_1.default.join(ctx.paths.pluginsDir, manifest.name);
|
|
170
169
|
try {
|
|
@@ -258,10 +257,9 @@ exports.plugins = {
|
|
|
258
257
|
const allow = await confirmFn(isUpgrade
|
|
259
258
|
? `Grant the listed permissions (including ${newPerms.length} new)? [y/N] `
|
|
260
259
|
: `Grant the listed permissions? [y/N] `);
|
|
261
|
-
|
|
262
|
-
|
|
260
|
+
// v4.9.2 Slice 3 — confirm() now owns the rejection message.
|
|
261
|
+
if (!allow)
|
|
263
262
|
return {};
|
|
264
|
-
}
|
|
265
263
|
await (0, plugins_1.saveGrantedPermissions)(dir, entry.manifest.permissions);
|
|
266
264
|
// Reload so the new state takes effect.
|
|
267
265
|
await ctx.pluginLoader.teardown();
|