aiden-runtime 4.1.5 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +250 -847
- package/dist/api/server.js +32 -5
- package/dist/cli/v4/aidenCLI.js +351 -53
- package/dist/cli/v4/callbacks.js +170 -0
- package/dist/cli/v4/chatSession.js +138 -3
- package/dist/cli/v4/commands/_runtimeToggleHelpers.js +92 -0
- package/dist/cli/v4/commands/browserDepth.js +45 -0
- package/dist/cli/v4/commands/cron.js +264 -0
- package/dist/cli/v4/commands/daemon.js +541 -0
- package/dist/cli/v4/commands/daemonStatus.js +253 -0
- package/dist/cli/v4/commands/help.js +7 -0
- package/dist/cli/v4/commands/index.js +20 -1
- package/dist/cli/v4/commands/runs.js +203 -0
- package/dist/cli/v4/commands/sandbox.js +48 -0
- package/dist/cli/v4/commands/suggestions.js +68 -0
- package/dist/cli/v4/commands/tce.js +41 -0
- package/dist/cli/v4/commands/trigger.js +378 -0
- package/dist/cli/v4/commands/update.js +95 -3
- package/dist/cli/v4/daemonAgentBuilder.js +142 -0
- package/dist/cli/v4/defaultSoul.js +1 -1
- package/dist/cli/v4/display/capabilityCard.js +26 -0
- package/dist/cli/v4/display.js +18 -8
- package/dist/cli/v4/replyRenderer.js +31 -23
- package/dist/cli/v4/updateBootPrompt.js +170 -0
- package/dist/core/playwrightBridge.js +129 -0
- package/dist/core/v4/aidenAgent.js +308 -4
- package/dist/core/v4/browserState.js +436 -0
- package/dist/core/v4/checkpoint.js +79 -0
- package/dist/core/v4/daemon/bootstrap.js +604 -0
- package/dist/core/v4/daemon/cleanShutdown.js +154 -0
- package/dist/core/v4/daemon/cron/cronBridge.js +126 -0
- package/dist/core/v4/daemon/cron/cronEmitter.js +173 -0
- package/dist/core/v4/daemon/cron/migration.js +199 -0
- package/dist/core/v4/daemon/cron/misfirePolicy.js +115 -0
- package/dist/core/v4/daemon/daemonConfig.js +90 -0
- package/dist/core/v4/daemon/db/connection.js +106 -0
- package/dist/core/v4/daemon/db/migrations.js +296 -0
- package/dist/core/v4/daemon/db/schema/v1.spec.js +18 -0
- package/dist/core/v4/daemon/dispatcher/agentRunner.js +98 -0
- package/dist/core/v4/daemon/dispatcher/budgetGate.js +127 -0
- package/dist/core/v4/daemon/dispatcher/daemonApproval.js +113 -0
- package/dist/core/v4/daemon/dispatcher/dailyBudgetTracker.js +120 -0
- package/dist/core/v4/daemon/dispatcher/dispatcher.js +389 -0
- package/dist/core/v4/daemon/dispatcher/fireRateLimiter.js +113 -0
- package/dist/core/v4/daemon/dispatcher/index.js +53 -0
- package/dist/core/v4/daemon/dispatcher/promptTemplate.js +95 -0
- package/dist/core/v4/daemon/dispatcher/realAgentRunner.js +356 -0
- package/dist/core/v4/daemon/dispatcher/resolveModel.js +93 -0
- package/dist/core/v4/daemon/dispatcher/sessionId.js +93 -0
- package/dist/core/v4/daemon/drain.js +156 -0
- package/dist/core/v4/daemon/eventLoopLag.js +73 -0
- package/dist/core/v4/daemon/health.js +159 -0
- package/dist/core/v4/daemon/idempotencyStore.js +204 -0
- package/dist/core/v4/daemon/index.js +179 -0
- package/dist/core/v4/daemon/instanceTracker.js +99 -0
- package/dist/core/v4/daemon/resourceRegistry.js +150 -0
- package/dist/core/v4/daemon/restartCode.js +32 -0
- package/dist/core/v4/daemon/restartFailureCounter.js +77 -0
- package/dist/core/v4/daemon/runStore.js +114 -0
- package/dist/core/v4/daemon/runtimeLock.js +167 -0
- package/dist/core/v4/daemon/signals.js +50 -0
- package/dist/core/v4/daemon/supervisor.js +272 -0
- package/dist/core/v4/daemon/triggerBus.js +279 -0
- package/dist/core/v4/daemon/triggers/email/allowlist.js +70 -0
- package/dist/core/v4/daemon/triggers/email/automatedSender.js +78 -0
- package/dist/core/v4/daemon/triggers/email/bodyExtractor.js +0 -0
- package/dist/core/v4/daemon/triggers/email/emailSeenStore.js +99 -0
- package/dist/core/v4/daemon/triggers/email/emailSpec.js +107 -0
- package/dist/core/v4/daemon/triggers/email/imapConnection.js +211 -0
- package/dist/core/v4/daemon/triggers/email/index.js +332 -0
- package/dist/core/v4/daemon/triggers/email/seenUids.js +60 -0
- package/dist/core/v4/daemon/triggers/fileObservationsStore.js +93 -0
- package/dist/core/v4/daemon/triggers/fileWatcher.js +253 -0
- package/dist/core/v4/daemon/triggers/fileWatcherSpec.js +88 -0
- package/dist/core/v4/daemon/triggers/fsIdentity.js +42 -0
- package/dist/core/v4/daemon/triggers/globMatcher.js +100 -0
- package/dist/core/v4/daemon/triggers/reconcile.js +206 -0
- package/dist/core/v4/daemon/triggers/settleStat.js +81 -0
- package/dist/core/v4/daemon/triggers/webhook.js +376 -0
- package/dist/core/v4/daemon/triggers/webhookDeliveriesStore.js +109 -0
- package/dist/core/v4/daemon/triggers/webhookIdempotency.js +72 -0
- package/dist/core/v4/daemon/triggers/webhookRateLimit.js +56 -0
- package/dist/core/v4/daemon/triggers/webhookSpec.js +76 -0
- package/dist/core/v4/daemon/triggers/webhookVerifier.js +128 -0
- package/dist/core/v4/daemon/types.js +15 -0
- package/dist/core/v4/dockerSession.js +461 -0
- package/dist/core/v4/dryRun.js +117 -0
- package/dist/core/v4/failureClassifier.js +779 -0
- package/dist/core/v4/recoveryReport.js +449 -0
- package/dist/core/v4/runtimeToggles.js +187 -0
- package/dist/core/v4/sandboxConfig.js +285 -0
- package/dist/core/v4/sandboxFs.js +316 -0
- package/dist/core/v4/suggestionCatalog.js +41 -0
- package/dist/core/v4/suggestionEngine.js +210 -0
- package/dist/core/v4/toolRegistry.js +18 -0
- package/dist/core/v4/turnState.js +587 -0
- package/dist/core/v4/update/checkUpdate.js +63 -3
- package/dist/core/v4/update/installMethodDetect.js +115 -0
- package/dist/core/v4/update/registryClient.js +121 -0
- package/dist/core/v4/update/skipState.js +75 -0
- package/dist/core/v4/verifier.js +448 -0
- package/dist/core/version.js +1 -1
- package/dist/tools/v4/browser/_observer.js +224 -0
- package/dist/tools/v4/browser/browserBlocker.js +396 -0
- package/dist/tools/v4/browser/browserClick.js +18 -1
- package/dist/tools/v4/browser/browserClose.js +18 -1
- package/dist/tools/v4/browser/browserExtract.js +5 -1
- package/dist/tools/v4/browser/browserFill.js +17 -1
- package/dist/tools/v4/browser/browserGetUrl.js +5 -1
- package/dist/tools/v4/browser/browserNavigate.js +16 -1
- package/dist/tools/v4/browser/browserScreenshot.js +5 -1
- package/dist/tools/v4/browser/browserScroll.js +18 -1
- package/dist/tools/v4/browser/browserType.js +17 -1
- package/dist/tools/v4/browser/captchaCheck.js +5 -1
- package/dist/tools/v4/executeCode.js +1 -0
- package/dist/tools/v4/files/fileCopy.js +56 -2
- package/dist/tools/v4/files/fileDelete.js +38 -1
- package/dist/tools/v4/files/fileList.js +12 -1
- package/dist/tools/v4/files/fileMove.js +59 -2
- package/dist/tools/v4/files/filePatch.js +43 -1
- package/dist/tools/v4/files/fileRead.js +12 -1
- package/dist/tools/v4/files/fileWrite.js +41 -1
- package/dist/tools/v4/index.js +71 -58
- package/dist/tools/v4/memory/memoryAdd.js +14 -0
- package/dist/tools/v4/memory/memoryRemove.js +14 -0
- package/dist/tools/v4/memory/memoryReplace.js +15 -0
- package/dist/tools/v4/memory/sessionSummary.js +12 -0
- package/dist/tools/v4/process/processKill.js +19 -0
- package/dist/tools/v4/process/processList.js +1 -0
- package/dist/tools/v4/process/processLogRead.js +1 -0
- package/dist/tools/v4/process/processSpawn.js +13 -0
- package/dist/tools/v4/process/processWait.js +1 -0
- package/dist/tools/v4/sessions/recallSession.js +1 -0
- package/dist/tools/v4/sessions/sessionList.js +1 -0
- package/dist/tools/v4/sessions/sessionSearch.js +1 -0
- package/dist/tools/v4/skills/lookupToolSchema.js +2 -0
- package/dist/tools/v4/skills/skillManage.js +13 -0
- package/dist/tools/v4/skills/skillView.js +1 -0
- package/dist/tools/v4/skills/skillsList.js +1 -0
- package/dist/tools/v4/subagent/subagentFanout.js +1 -0
- package/dist/tools/v4/system/aidenSelfUpdate.js +16 -0
- package/dist/tools/v4/system/appClose.js +13 -0
- package/dist/tools/v4/system/appInput.js +13 -0
- package/dist/tools/v4/system/appLaunch.js +13 -0
- package/dist/tools/v4/system/clipboardRead.js +1 -0
- package/dist/tools/v4/system/clipboardWrite.js +14 -0
- package/dist/tools/v4/system/mediaKey.js +12 -0
- package/dist/tools/v4/system/mediaSessions.js +1 -0
- package/dist/tools/v4/system/mediaTransport.js +13 -0
- package/dist/tools/v4/system/naturalEvents.js +1 -0
- package/dist/tools/v4/system/nowPlaying.js +1 -0
- package/dist/tools/v4/system/osProcessList.js +1 -0
- package/dist/tools/v4/system/screenshot.js +1 -0
- package/dist/tools/v4/system/systemInfo.js +1 -0
- package/dist/tools/v4/system/volumeSet.js +17 -0
- package/dist/tools/v4/terminal/shellExec.js +81 -9
- package/dist/tools/v4/web/deepResearch.js +1 -0
- package/dist/tools/v4/web/openUrl.js +1 -0
- package/dist/tools/v4/web/webFetch.js +1 -0
- package/dist/tools/v4/web/webPage.js +1 -0
- package/dist/tools/v4/web/webSearch.js +1 -0
- package/dist/tools/v4/web/youtubeSearch.js +1 -0
- package/package.json +7 -1
|
@@ -0,0 +1,253 @@
|
|
|
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/daemonStatus.ts — v4.5 Phase 8a.
|
|
10
|
+
*
|
|
11
|
+
* `/daemon status` — read-only slash variant of `aiden daemon
|
|
12
|
+
* status` (the top-level Phase 4b CLI surface). Renders an inline
|
|
13
|
+
* summary inside the REPL without leaving the chat. Points users
|
|
14
|
+
* at `aiden daemon install|start|stop` for any mutation.
|
|
15
|
+
*
|
|
16
|
+
* Q-P8a-3(a) inline format — five lines max when running, two
|
|
17
|
+
* lines when disabled. Reads daemon.db directly so the slash
|
|
18
|
+
* command works regardless of whether the daemon is the same
|
|
19
|
+
* process as the REPL.
|
|
20
|
+
*/
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.daemonStatus = void 0;
|
|
26
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
27
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
28
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
29
|
+
const daemon_1 = require("../../../core/v4/daemon");
|
|
30
|
+
const paths_1 = require("../../../core/v4/paths");
|
|
31
|
+
exports.daemonStatus = {
|
|
32
|
+
name: 'daemon',
|
|
33
|
+
description: 'Show v4.5 daemon status (read-only). Use `aiden daemon` for lifecycle.',
|
|
34
|
+
category: 'system',
|
|
35
|
+
icon: '⚙',
|
|
36
|
+
handler: async (ctx) => {
|
|
37
|
+
const sub = (ctx.args[0] ?? 'status').toLowerCase();
|
|
38
|
+
if (sub !== 'status') {
|
|
39
|
+
ctx.display.printError('Usage: /daemon status\n' +
|
|
40
|
+
'For lifecycle commands (install / start / stop / restart / logs), use the top-level CLI:\n' +
|
|
41
|
+
' aiden daemon install\n' +
|
|
42
|
+
' aiden daemon start\n' +
|
|
43
|
+
' aiden daemon stop\n' +
|
|
44
|
+
' aiden daemon status\n' +
|
|
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
|
+
}
|
|
55
|
+
return {};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
// ── Snapshot collector ─────────────────────────────────────────────────────
|
|
59
|
+
function readSnapshot() {
|
|
60
|
+
const aidenRoot = (0, paths_1.resolveAidenRoot)();
|
|
61
|
+
const dbPath = (0, daemon_1.daemonDbPath)(aidenRoot);
|
|
62
|
+
const lockPath = (0, daemon_1.daemonRuntimeLockPath)(aidenRoot);
|
|
63
|
+
// ── Liveness via the in-process bootstrap handle first, then fall
|
|
64
|
+
// back to the runtime.lock PID check (covers the case where the
|
|
65
|
+
// daemon is another process and we're a REPL inspecting its db).
|
|
66
|
+
let running = false;
|
|
67
|
+
let instanceId = null;
|
|
68
|
+
let port = null;
|
|
69
|
+
let uptimeMs = null;
|
|
70
|
+
const handle = (0, daemon_1.getDaemonHandle)();
|
|
71
|
+
if (handle?.active && handle.instanceId) {
|
|
72
|
+
running = true;
|
|
73
|
+
instanceId = handle.instanceId;
|
|
74
|
+
port = (0, daemon_1.getDaemonConfig)().port;
|
|
75
|
+
if (handle.instanceTracker) {
|
|
76
|
+
// instanceTracker has a `getStartedAt` if exposed; otherwise
|
|
77
|
+
// derive from daemon_instances row below.
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!running && node_fs_1.default.existsSync(lockPath)) {
|
|
81
|
+
try {
|
|
82
|
+
const lines = node_fs_1.default.readFileSync(lockPath, 'utf-8').split(/\r?\n/);
|
|
83
|
+
// runtime.lock format: [0]=instanceId, [1]=pid, [2]=port (Phase 1).
|
|
84
|
+
const lockedInstance = lines[0] ?? '';
|
|
85
|
+
const lockedPid = Number.parseInt(lines[1] ?? '', 10);
|
|
86
|
+
const lockedPort = Number.parseInt(lines[2] ?? '', 10);
|
|
87
|
+
if (Number.isFinite(lockedPid) && pidAlive(lockedPid)) {
|
|
88
|
+
running = true;
|
|
89
|
+
instanceId = lockedInstance || null;
|
|
90
|
+
if (Number.isFinite(lockedPort))
|
|
91
|
+
port = lockedPort;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch { /* stale or unreadable */ }
|
|
95
|
+
}
|
|
96
|
+
if (!node_fs_1.default.existsSync(dbPath)) {
|
|
97
|
+
return {
|
|
98
|
+
running: false,
|
|
99
|
+
port: null,
|
|
100
|
+
instanceId: null,
|
|
101
|
+
uptimeMs: null,
|
|
102
|
+
triggerCounts: { file: 0, webhook: 0, email: 0, schedule: 0, manual: 0 },
|
|
103
|
+
recentRuns: [],
|
|
104
|
+
bus: { pending: 0, claimed: 0, deadLetter: 0 },
|
|
105
|
+
dailyBudget: null,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const db = (0, daemon_1.openDaemonDb)(dbPath);
|
|
109
|
+
// Uptime from the instance row when we have an instanceId.
|
|
110
|
+
if (running && instanceId) {
|
|
111
|
+
try {
|
|
112
|
+
const row = db
|
|
113
|
+
.prepare('SELECT started_at, last_heartbeat FROM daemon_instances WHERE instance_id = ?')
|
|
114
|
+
.get(instanceId);
|
|
115
|
+
if (row)
|
|
116
|
+
uptimeMs = Date.now() - row.started_at;
|
|
117
|
+
}
|
|
118
|
+
catch { /* noop */ }
|
|
119
|
+
}
|
|
120
|
+
// Trigger counts by source.
|
|
121
|
+
const triggerCounts = { file: 0, webhook: 0, email: 0, schedule: 0, manual: 0 };
|
|
122
|
+
try {
|
|
123
|
+
const rows = db.prepare(`SELECT source, COUNT(*) AS c FROM triggers WHERE enabled = 1 GROUP BY source`).all();
|
|
124
|
+
for (const r of rows) {
|
|
125
|
+
if (r.source in triggerCounts) {
|
|
126
|
+
triggerCounts[r.source] = r.c;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch { /* triggers table missing — schema v1 not applied */ }
|
|
131
|
+
// Recent runs (last 3).
|
|
132
|
+
const recentRuns = (() => {
|
|
133
|
+
try {
|
|
134
|
+
const rows = db.prepare(`SELECT id, status, finish_reason, started_at, completed_at FROM runs
|
|
135
|
+
ORDER BY id DESC LIMIT 3`).all();
|
|
136
|
+
return rows.map((r) => ({
|
|
137
|
+
id: r.id,
|
|
138
|
+
status: r.status,
|
|
139
|
+
finishReason: r.finish_reason,
|
|
140
|
+
durationMs: r.completed_at !== null ? r.completed_at - r.started_at : null,
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
})();
|
|
147
|
+
// Bus stats.
|
|
148
|
+
const bus = (() => {
|
|
149
|
+
try {
|
|
150
|
+
const rows = db.prepare(`SELECT status, COUNT(*) AS c FROM trigger_events GROUP BY status`).all();
|
|
151
|
+
const m = {};
|
|
152
|
+
for (const r of rows)
|
|
153
|
+
m[r.status] = r.c;
|
|
154
|
+
return {
|
|
155
|
+
pending: m.pending ?? 0,
|
|
156
|
+
claimed: m.claimed ?? 0,
|
|
157
|
+
deadLetter: m.dead_letter ?? 0,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return { pending: 0, claimed: 0, deadLetter: 0 };
|
|
162
|
+
}
|
|
163
|
+
})();
|
|
164
|
+
// Daily budget (piggybacked on idempotency_keys per Phase 7).
|
|
165
|
+
const dailyBudget = (() => {
|
|
166
|
+
const budgetRaw = process.env.AIDEN_DAEMON_DAILY_BUDGET;
|
|
167
|
+
if (!budgetRaw)
|
|
168
|
+
return null;
|
|
169
|
+
const budget = Number.parseInt(budgetRaw, 10);
|
|
170
|
+
if (!Number.isFinite(budget) || budget <= 0)
|
|
171
|
+
return null;
|
|
172
|
+
try {
|
|
173
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
174
|
+
const row = db.prepare(`SELECT response_json FROM idempotency_keys WHERE scope = ? AND key = ?`).get('daemon_budget', today);
|
|
175
|
+
let used = 0;
|
|
176
|
+
if (row) {
|
|
177
|
+
try {
|
|
178
|
+
const parsed = JSON.parse(row.response_json);
|
|
179
|
+
used = typeof parsed.used === 'number' ? parsed.used : 0;
|
|
180
|
+
}
|
|
181
|
+
catch { /* noop */ }
|
|
182
|
+
}
|
|
183
|
+
return { used, budget, exhausted: used >= budget };
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return { used: 0, budget, exhausted: false };
|
|
187
|
+
}
|
|
188
|
+
})();
|
|
189
|
+
return {
|
|
190
|
+
running,
|
|
191
|
+
port,
|
|
192
|
+
instanceId,
|
|
193
|
+
uptimeMs,
|
|
194
|
+
triggerCounts,
|
|
195
|
+
recentRuns,
|
|
196
|
+
bus,
|
|
197
|
+
dailyBudget,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
// ── Renderer ───────────────────────────────────────────────────────────────
|
|
201
|
+
function printSnapshot(s, ctx) {
|
|
202
|
+
if (!s.running) {
|
|
203
|
+
ctx.display.write('Daemon: disabled.\n');
|
|
204
|
+
ctx.display.write('To enable: `aiden daemon install` (systemd / launchd) or `AIDEN_DAEMON=1` before `aiden`.\n');
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const uptime = s.uptimeMs !== null ? formatUptime(s.uptimeMs) : 'unknown';
|
|
208
|
+
const instanceShort = s.instanceId ? s.instanceId.slice(0, 8) : '?';
|
|
209
|
+
ctx.display.write(`Daemon: running (port ${s.port ?? '?'}, instance ${instanceShort}, uptime ${uptime})\n`);
|
|
210
|
+
const tc = s.triggerCounts;
|
|
211
|
+
ctx.display.write(`Triggers: ${tc.file} file · ${tc.webhook} webhook · ${tc.email} email · ${tc.schedule} schedule\n`);
|
|
212
|
+
if (s.recentRuns.length === 0) {
|
|
213
|
+
ctx.display.write('Recent runs (last 3): (none)\n');
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
const parts = s.recentRuns.map((r) => {
|
|
217
|
+
const dur = r.durationMs !== null ? `(${(r.durationMs / 1000).toFixed(1)}s)` : '';
|
|
218
|
+
return `${r.status}${dur ? ' ' + dur : ''}`;
|
|
219
|
+
});
|
|
220
|
+
ctx.display.write(`Recent runs (last ${s.recentRuns.length}): ${parts.join(' · ')}\n`);
|
|
221
|
+
}
|
|
222
|
+
ctx.display.write(`Bus: ${s.bus.pending} pending · ${s.bus.claimed} claimed · ${s.bus.deadLetter} dead-letter\n`);
|
|
223
|
+
if (s.dailyBudget) {
|
|
224
|
+
const d = s.dailyBudget;
|
|
225
|
+
const exhaustedTag = d.exhausted ? ' EXHAUSTED' : '';
|
|
226
|
+
ctx.display.write(`Daily budget: ${d.used} / ${d.budget} tokens used (UTC ${new Date().toISOString().slice(0, 10)})${exhaustedTag}\n`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function formatUptime(ms) {
|
|
230
|
+
const s = Math.floor(ms / 1000);
|
|
231
|
+
const days = Math.floor(s / 86400);
|
|
232
|
+
const hours = Math.floor((s % 86400) / 3600);
|
|
233
|
+
const mins = Math.floor((s % 3600) / 60);
|
|
234
|
+
if (days > 0)
|
|
235
|
+
return `${days}d ${hours}h`;
|
|
236
|
+
if (hours > 0)
|
|
237
|
+
return `${hours}h ${mins}m`;
|
|
238
|
+
return `${mins}m ${s % 60}s`;
|
|
239
|
+
}
|
|
240
|
+
function pidAlive(pid) {
|
|
241
|
+
try {
|
|
242
|
+
process.kill(pid, 0);
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
catch (e) {
|
|
246
|
+
// ESRCH = no such process; EPERM = process exists but we lack
|
|
247
|
+
// permission to signal it (still counts as alive).
|
|
248
|
+
return e.code === 'EPERM';
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Keep unused-import linter happy.
|
|
252
|
+
void node_os_1.default;
|
|
253
|
+
void node_path_1.default;
|
|
@@ -58,6 +58,13 @@ exports.SUBSECTION_MAP = {
|
|
|
58
58
|
history: 'System',
|
|
59
59
|
// Phase v4.1.2-update — npm self-update for the running install.
|
|
60
60
|
update: 'System',
|
|
61
|
+
// v4.5 Phase 8a — subsystem live-flip slash commands.
|
|
62
|
+
sandbox: 'System',
|
|
63
|
+
tce: 'System',
|
|
64
|
+
'browser-depth': 'System',
|
|
65
|
+
daemon: 'System',
|
|
66
|
+
// v4.5 Phase 8b — contextual capability suggestions.
|
|
67
|
+
suggestions: 'System',
|
|
61
68
|
// ── Authentication ──
|
|
62
69
|
auth: 'Authentication',
|
|
63
70
|
// ── 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.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.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");
|
|
@@ -79,6 +79,18 @@ const reloadSoul_1 = require("./reloadSoul");
|
|
|
79
79
|
Object.defineProperty(exports, "reloadSoul", { enumerable: true, get: function () { return reloadSoul_1.reloadSoul; } });
|
|
80
80
|
const update_1 = require("./update");
|
|
81
81
|
Object.defineProperty(exports, "update", { enumerable: true, get: function () { return update_1.update; } });
|
|
82
|
+
// v4.5 Phase 8a — subsystem live-flip slash commands.
|
|
83
|
+
const sandbox_1 = require("./sandbox");
|
|
84
|
+
Object.defineProperty(exports, "sandbox", { enumerable: true, get: function () { return sandbox_1.sandbox; } });
|
|
85
|
+
const tce_1 = require("./tce");
|
|
86
|
+
Object.defineProperty(exports, "tce", { enumerable: true, get: function () { return tce_1.tce; } });
|
|
87
|
+
const browserDepth_1 = require("./browserDepth");
|
|
88
|
+
Object.defineProperty(exports, "browserDepth", { enumerable: true, get: function () { return browserDepth_1.browserDepth; } });
|
|
89
|
+
const daemonStatus_1 = require("./daemonStatus");
|
|
90
|
+
Object.defineProperty(exports, "daemonStatus", { enumerable: true, get: function () { return daemonStatus_1.daemonStatus; } });
|
|
91
|
+
// v4.5 Phase 8b — contextual capability suggestions toggle.
|
|
92
|
+
const suggestions_1 = require("./suggestions");
|
|
93
|
+
Object.defineProperty(exports, "suggestions", { enumerable: true, get: function () { return suggestions_1.suggestions; } });
|
|
82
94
|
/** All built-in system commands, in canonical order. */
|
|
83
95
|
exports.allCommands = [
|
|
84
96
|
help_1.help,
|
|
@@ -115,6 +127,13 @@ exports.allCommands = [
|
|
|
115
127
|
// probe + shared executeInstall executor (also wired into
|
|
116
128
|
// aiden_self_update tool for natural-language requests).
|
|
117
129
|
update_1.update,
|
|
130
|
+
// v4.5 Phase 8a — subsystem live-flip slash commands.
|
|
131
|
+
sandbox_1.sandbox,
|
|
132
|
+
tce_1.tce,
|
|
133
|
+
browserDepth_1.browserDepth,
|
|
134
|
+
daemonStatus_1.daemonStatus,
|
|
135
|
+
// v4.5 Phase 8b — contextual suggestions toggle.
|
|
136
|
+
suggestions_1.suggestions,
|
|
118
137
|
clear_1.clear,
|
|
119
138
|
quit_1.quit,
|
|
120
139
|
];
|
|
@@ -0,0 +1,203 @@
|
|
|
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/runs.ts — v4.5 Phase 6: `aiden runs` command set.
|
|
10
|
+
*
|
|
11
|
+
* Surfaces the daemon's `runs` + `run_events` tables (Phase 1
|
|
12
|
+
* runStore) so operators can inspect daemon-fired turn history
|
|
13
|
+
* outside the REPL.
|
|
14
|
+
*
|
|
15
|
+
* Subcommands:
|
|
16
|
+
* list — recent runs; optional --limit / --source / --status filters
|
|
17
|
+
* show — full run row + all run_events for one runId
|
|
18
|
+
* interrupt — request cancellation of a running turn (Q-P6-4a:
|
|
19
|
+
* SIGUSR1 + marker file pattern)
|
|
20
|
+
* stats — aggregate counts by status + mean duration
|
|
21
|
+
*
|
|
22
|
+
* The `interrupt` path writes
|
|
23
|
+
* `~/.aiden/daemon/interrupt-<runId>.req` and signals the daemon
|
|
24
|
+
* via SIGUSR1. The dispatcher polls the marker directory on each
|
|
25
|
+
* lease-renew tick (~60s) and cancels runs whose marker exists.
|
|
26
|
+
* This matches the existing SIGUSR1 → exit 75 restart contract
|
|
27
|
+
* and keeps cancellation signal-driven rather than DB-poll.
|
|
28
|
+
*/
|
|
29
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
30
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
31
|
+
};
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.runRunsSubcommand = runRunsSubcommand;
|
|
34
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
35
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
36
|
+
const daemon_1 = require("../../../core/v4/daemon");
|
|
37
|
+
const paths_1 = require("../../../core/v4/paths");
|
|
38
|
+
const noopOut = (s) => { process.stdout.write(s); };
|
|
39
|
+
const noopErr = (s) => { process.stderr.write(s); };
|
|
40
|
+
async function runRunsSubcommand(action, args, argv, opts = {}) {
|
|
41
|
+
const out = opts.writeOut ?? noopOut;
|
|
42
|
+
const err = opts.writeErr ?? noopErr;
|
|
43
|
+
const aidenRoot = (0, paths_1.resolveAidenRoot)();
|
|
44
|
+
const db = (0, daemon_1.openDaemonDb)((0, daemon_1.daemonDbPath)(aidenRoot));
|
|
45
|
+
const runStore = (0, daemon_1.createRunStore)({ db });
|
|
46
|
+
switch (action) {
|
|
47
|
+
case 'list': return cmdList(runStore, argv, out);
|
|
48
|
+
case 'show': return cmdShow(runStore, args[0], out, err);
|
|
49
|
+
case 'interrupt': return cmdInterrupt(args[0], aidenRoot, out, err);
|
|
50
|
+
case 'stats': return cmdStats(db, out);
|
|
51
|
+
default:
|
|
52
|
+
err(`Unknown runs action: ${action}\n`);
|
|
53
|
+
err('Actions: list, show <runId>, interrupt <runId>, stats\n');
|
|
54
|
+
return 2;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// ── list ──────────────────────────────────────────────────────────────────
|
|
58
|
+
function cmdList(runStore, argv, out) {
|
|
59
|
+
const allowedStatuses = new Set([
|
|
60
|
+
'queued', 'running', 'completed', 'failed', 'cancelled', 'interrupted',
|
|
61
|
+
]);
|
|
62
|
+
const status = argv.status && allowedStatuses.has(argv.status)
|
|
63
|
+
? argv.status
|
|
64
|
+
: undefined;
|
|
65
|
+
const rows = runStore.listRecent({
|
|
66
|
+
limit: argv.limit ?? 50,
|
|
67
|
+
status,
|
|
68
|
+
source: argv.source,
|
|
69
|
+
sessionIdPrefix: argv.trigger,
|
|
70
|
+
});
|
|
71
|
+
if (rows.length === 0) {
|
|
72
|
+
out('No runs match the filter.\n');
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
out(`${'runId'.padEnd(6)} ${'status'.padEnd(11)} ${'finish'.padEnd(11)} ${'started'.padEnd(20)} sessionId\n`);
|
|
76
|
+
for (const r of rows) {
|
|
77
|
+
const started = new Date(r.startedAt).toISOString().slice(0, 19) + 'Z';
|
|
78
|
+
const finish = r.finishReason ?? '-';
|
|
79
|
+
out(`${String(r.id).padEnd(6)} ${r.status.padEnd(11)} ${finish.padEnd(11)} ${started.padEnd(20)} ${r.sessionId}\n`);
|
|
80
|
+
}
|
|
81
|
+
out(`\n${rows.length} run${rows.length === 1 ? '' : 's'} shown\n`);
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
// ── show ──────────────────────────────────────────────────────────────────
|
|
85
|
+
function cmdShow(runStore, rawId, out, err) {
|
|
86
|
+
if (!rawId) {
|
|
87
|
+
err('runs show: runId required\n');
|
|
88
|
+
return 2;
|
|
89
|
+
}
|
|
90
|
+
const runId = Number.parseInt(rawId, 10);
|
|
91
|
+
if (!Number.isFinite(runId) || runId <= 0) {
|
|
92
|
+
err(`runs show: invalid runId: ${rawId}\n`);
|
|
93
|
+
return 2;
|
|
94
|
+
}
|
|
95
|
+
const row = runStore.get(runId);
|
|
96
|
+
if (!row) {
|
|
97
|
+
err(`runs show: not found: ${runId}\n`);
|
|
98
|
+
return 1;
|
|
99
|
+
}
|
|
100
|
+
const events = runStore.listEvents(runId, 500);
|
|
101
|
+
out(JSON.stringify({
|
|
102
|
+
run: row,
|
|
103
|
+
events: events.map((e) => ({
|
|
104
|
+
ts: new Date(e.ts).toISOString(),
|
|
105
|
+
kind: e.kind,
|
|
106
|
+
payload: safeParse(e.payload),
|
|
107
|
+
})),
|
|
108
|
+
}, null, 2) + '\n');
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
function safeParse(s) {
|
|
112
|
+
try {
|
|
113
|
+
return JSON.parse(s);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return s;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// ── interrupt ─────────────────────────────────────────────────────────────
|
|
120
|
+
function cmdInterrupt(rawId, aidenRoot, out, err) {
|
|
121
|
+
if (!rawId) {
|
|
122
|
+
err('runs interrupt: runId required\n');
|
|
123
|
+
return 2;
|
|
124
|
+
}
|
|
125
|
+
const runId = Number.parseInt(rawId, 10);
|
|
126
|
+
if (!Number.isFinite(runId) || runId <= 0) {
|
|
127
|
+
err(`runs interrupt: invalid runId: ${rawId}\n`);
|
|
128
|
+
return 2;
|
|
129
|
+
}
|
|
130
|
+
const markerDir = node_path_1.default.join(aidenRoot, 'daemon', 'interrupt');
|
|
131
|
+
try {
|
|
132
|
+
node_fs_1.default.mkdirSync(markerDir, { recursive: true });
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
err(`runs interrupt: failed to create marker dir: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
138
|
+
const markerPath = node_path_1.default.join(markerDir, `${runId}.req`);
|
|
139
|
+
try {
|
|
140
|
+
node_fs_1.default.writeFileSync(markerPath, JSON.stringify({ runId, requestedAt: Date.now() }));
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
err(`runs interrupt: failed to write marker: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
144
|
+
return 1;
|
|
145
|
+
}
|
|
146
|
+
// Best-effort SIGUSR1 to the daemon. If the daemon isn't running,
|
|
147
|
+
// the marker is still there for whoever boots next — they'll find
|
|
148
|
+
// the run in `interrupted` state via the boot crash-recovery pass.
|
|
149
|
+
const lockPath = (0, daemon_1.daemonRuntimeLockPath)(aidenRoot);
|
|
150
|
+
let pid = null;
|
|
151
|
+
try {
|
|
152
|
+
if (node_fs_1.default.existsSync(lockPath)) {
|
|
153
|
+
const lines = node_fs_1.default.readFileSync(lockPath, 'utf-8').split(/\r?\n/);
|
|
154
|
+
// runtime.lock format: line 0 = instanceId, line 1 = pid, line 2 = port
|
|
155
|
+
const candidate = Number.parseInt(lines[1] ?? '', 10);
|
|
156
|
+
if (Number.isFinite(candidate))
|
|
157
|
+
pid = candidate;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch { /* noop */ }
|
|
161
|
+
if (pid !== null && process.platform !== 'win32') {
|
|
162
|
+
try {
|
|
163
|
+
process.kill(pid, 'SIGUSR1');
|
|
164
|
+
}
|
|
165
|
+
catch { /* daemon may have died; marker still wins on next boot */ }
|
|
166
|
+
}
|
|
167
|
+
out(`runs interrupt: marker written at ${markerPath}\n`);
|
|
168
|
+
if (pid !== null && process.platform !== 'win32') {
|
|
169
|
+
out(`runs interrupt: SIGUSR1 sent to daemon pid=${pid}\n`);
|
|
170
|
+
}
|
|
171
|
+
else if (process.platform === 'win32') {
|
|
172
|
+
out('runs interrupt: SIGUSR1 not available on Windows — daemon picks up marker on next renew tick\n');
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
out('runs interrupt: no live daemon found — marker will be honoured on next boot\n');
|
|
176
|
+
}
|
|
177
|
+
return 0;
|
|
178
|
+
}
|
|
179
|
+
// ── stats ─────────────────────────────────────────────────────────────────
|
|
180
|
+
function cmdStats(db, out) {
|
|
181
|
+
const counts = db.prepare(`SELECT status, COUNT(*) AS c FROM runs GROUP BY status`).all();
|
|
182
|
+
const completed = db.prepare(`SELECT AVG(completed_at - started_at) AS mean,
|
|
183
|
+
MIN(completed_at - started_at) AS min,
|
|
184
|
+
MAX(completed_at - started_at) AS max,
|
|
185
|
+
COUNT(*) AS n
|
|
186
|
+
FROM runs
|
|
187
|
+
WHERE status = 'completed' AND completed_at IS NOT NULL`).get();
|
|
188
|
+
out('Run status counts:\n');
|
|
189
|
+
if (counts.length === 0) {
|
|
190
|
+
out(' (no runs recorded)\n');
|
|
191
|
+
}
|
|
192
|
+
for (const r of counts) {
|
|
193
|
+
out(` ${r.status.padEnd(12)} ${r.c}\n`);
|
|
194
|
+
}
|
|
195
|
+
if (completed.n > 0 && completed.mean !== null) {
|
|
196
|
+
out('\nCompleted-run duration (ms):\n');
|
|
197
|
+
out(` mean ${Math.round(completed.mean)}\n`);
|
|
198
|
+
out(` min ${completed.min}\n`);
|
|
199
|
+
out(` max ${completed.max}\n`);
|
|
200
|
+
out(` n ${completed.n}\n`);
|
|
201
|
+
}
|
|
202
|
+
return 0;
|
|
203
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
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/sandbox.ts — v4.5 Phase 8a.
|
|
10
|
+
*
|
|
11
|
+
* `/sandbox on|off|status` — flip the v4.4 execution sandbox
|
|
12
|
+
* (filesystem allow/deny + docker session backend + dryRun
|
|
13
|
+
* preflight) without restart. Persists to config.yaml
|
|
14
|
+
* (runtime_toggles.sandbox). Env var AIDEN_SANDBOX always wins
|
|
15
|
+
* over both — see runtimeToggles.ts for precedence rules.
|
|
16
|
+
*
|
|
17
|
+
* Q-P8a-4(a): /sandbox off flips silently. User explicitly typed
|
|
18
|
+
* the command and the status output makes the flip visible. The
|
|
19
|
+
* sandbox denylist (fs.sensitive_path) remains in effect for
|
|
20
|
+
* unmistakably dangerous paths regardless of the toggle —
|
|
21
|
+
* disabling the sandbox does NOT remove the always-on denylist.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.sandbox = void 0;
|
|
25
|
+
const _runtimeToggleHelpers_1 = require("./_runtimeToggleHelpers");
|
|
26
|
+
exports.sandbox = {
|
|
27
|
+
name: 'sandbox',
|
|
28
|
+
description: 'Toggle the v4.4 execution sandbox (file ACLs + docker tools).',
|
|
29
|
+
category: 'system',
|
|
30
|
+
icon: '🛡',
|
|
31
|
+
handler: async (ctx) => {
|
|
32
|
+
const sub = (0, _runtimeToggleHelpers_1.parseSubcommand)(ctx.args[0]);
|
|
33
|
+
if (sub === 'on') {
|
|
34
|
+
await (0, _runtimeToggleHelpers_1.flip)('sandbox', true, ctx);
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
if (sub === 'off') {
|
|
38
|
+
await (0, _runtimeToggleHelpers_1.flip)('sandbox', false, ctx);
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
if (sub === 'status') {
|
|
42
|
+
(0, _runtimeToggleHelpers_1.printStatus)('sandbox', ctx);
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
ctx.display.printError('Usage: /sandbox on|off|status');
|
|
46
|
+
return {};
|
|
47
|
+
},
|
|
48
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
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/suggestions.ts — v4.5 Phase 8b.
|
|
10
|
+
*
|
|
11
|
+
* `/suggestions on|off|status` — flip the contextual capability
|
|
12
|
+
* suggestions surfaced by the suggestionEngine (Phase 8b). Reuses
|
|
13
|
+
* the Phase 8a `_runtimeToggleHelpers` since 'suggestions' is now
|
|
14
|
+
* a fourth ToggleKey on the runtimeToggles singleton.
|
|
15
|
+
*
|
|
16
|
+
* /suggestions on — re-enable tips (default).
|
|
17
|
+
* /suggestions off — silence tips for this REPL + persist to
|
|
18
|
+
* config.yaml (runtime_toggles.suggestions
|
|
19
|
+
* = false). Subsequent boots stay quiet
|
|
20
|
+
* until /suggestions on flips it back.
|
|
21
|
+
* /suggestions status — single-line state with source +
|
|
22
|
+
* fired-this-session count + budget remaining.
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.suggestions = void 0;
|
|
26
|
+
const _runtimeToggleHelpers_1 = require("./_runtimeToggleHelpers");
|
|
27
|
+
const runtimeToggles_1 = require("../../../core/v4/runtimeToggles");
|
|
28
|
+
const suggestionEngine_1 = require("../../../core/v4/suggestionEngine");
|
|
29
|
+
exports.suggestions = {
|
|
30
|
+
name: 'suggestions',
|
|
31
|
+
description: 'Toggle contextual one-line capability tips.',
|
|
32
|
+
category: 'system',
|
|
33
|
+
icon: '💡',
|
|
34
|
+
handler: async (ctx) => {
|
|
35
|
+
const sub = (0, _runtimeToggleHelpers_1.parseSubcommand)(ctx.args[0]);
|
|
36
|
+
if (sub === 'on') {
|
|
37
|
+
await (0, _runtimeToggleHelpers_1.flip)('suggestions', true, ctx);
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
if (sub === 'off') {
|
|
41
|
+
await (0, _runtimeToggleHelpers_1.flip)('suggestions', false, ctx);
|
|
42
|
+
// Also session-dismiss so the in-process engine stops firing
|
|
43
|
+
// immediately, not just after the next REPL restart picks up
|
|
44
|
+
// the new config value.
|
|
45
|
+
try {
|
|
46
|
+
(0, suggestionEngine_1.getSuggestionEngine)().dismissAll();
|
|
47
|
+
}
|
|
48
|
+
catch { /* defensive */ }
|
|
49
|
+
return {};
|
|
50
|
+
}
|
|
51
|
+
if (sub === 'status') {
|
|
52
|
+
const tog = (0, runtimeToggles_1.getRuntimeToggles)().snapshot().suggestions;
|
|
53
|
+
const snap = (0, suggestionEngine_1.getSuggestionEngine)().snapshot();
|
|
54
|
+
const state = tog.value ? 'ON' : 'OFF';
|
|
55
|
+
const dismissTag = snap.dismissedSession && tog.value ? ' (dismissed this session)' : '';
|
|
56
|
+
ctx.display.write(`Suggestions: ${state} (source: ${tog.source})${dismissTag}\n`);
|
|
57
|
+
if (snap.firedSlots.length > 0) {
|
|
58
|
+
ctx.display.write(` fired this session: ${snap.firedSlots.join(', ')} · budget remaining: ${snap.budgetRemaining}\n`);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
ctx.display.write(` fired this session: (none) · budget remaining: ${snap.budgetRemaining}\n`);
|
|
62
|
+
}
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
ctx.display.printError('Usage: /suggestions on|off|status');
|
|
66
|
+
return {};
|
|
67
|
+
},
|
|
68
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
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/tce.ts — v4.5 Phase 8a.
|
|
10
|
+
*
|
|
11
|
+
* `/tce on|off|status` — flip the v4.2 Tool-Call Effort recovery
|
|
12
|
+
* pipeline (verifier + failure classifier + recovery report)
|
|
13
|
+
* without restart. Persists to config.yaml. Env var AIDEN_TCE
|
|
14
|
+
* always wins.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.tce = void 0;
|
|
18
|
+
const _runtimeToggleHelpers_1 = require("./_runtimeToggleHelpers");
|
|
19
|
+
exports.tce = {
|
|
20
|
+
name: 'tce',
|
|
21
|
+
description: 'Toggle the v4.2 Tool-Call Effort recovery pipeline.',
|
|
22
|
+
category: 'system',
|
|
23
|
+
icon: '🔁',
|
|
24
|
+
handler: async (ctx) => {
|
|
25
|
+
const sub = (0, _runtimeToggleHelpers_1.parseSubcommand)(ctx.args[0]);
|
|
26
|
+
if (sub === 'on') {
|
|
27
|
+
await (0, _runtimeToggleHelpers_1.flip)('tce', true, ctx);
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
if (sub === 'off') {
|
|
31
|
+
await (0, _runtimeToggleHelpers_1.flip)('tce', false, ctx);
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
if (sub === 'status') {
|
|
35
|
+
(0, _runtimeToggleHelpers_1.printStatus)('tce', ctx);
|
|
36
|
+
return {};
|
|
37
|
+
}
|
|
38
|
+
ctx.display.printError('Usage: /tce on|off|status');
|
|
39
|
+
return {};
|
|
40
|
+
},
|
|
41
|
+
};
|