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.
Files changed (163) hide show
  1. package/README.md +250 -847
  2. package/dist/api/server.js +32 -5
  3. package/dist/cli/v4/aidenCLI.js +351 -53
  4. package/dist/cli/v4/callbacks.js +170 -0
  5. package/dist/cli/v4/chatSession.js +138 -3
  6. package/dist/cli/v4/commands/_runtimeToggleHelpers.js +92 -0
  7. package/dist/cli/v4/commands/browserDepth.js +45 -0
  8. package/dist/cli/v4/commands/cron.js +264 -0
  9. package/dist/cli/v4/commands/daemon.js +541 -0
  10. package/dist/cli/v4/commands/daemonStatus.js +253 -0
  11. package/dist/cli/v4/commands/help.js +7 -0
  12. package/dist/cli/v4/commands/index.js +20 -1
  13. package/dist/cli/v4/commands/runs.js +203 -0
  14. package/dist/cli/v4/commands/sandbox.js +48 -0
  15. package/dist/cli/v4/commands/suggestions.js +68 -0
  16. package/dist/cli/v4/commands/tce.js +41 -0
  17. package/dist/cli/v4/commands/trigger.js +378 -0
  18. package/dist/cli/v4/commands/update.js +95 -3
  19. package/dist/cli/v4/daemonAgentBuilder.js +142 -0
  20. package/dist/cli/v4/defaultSoul.js +1 -1
  21. package/dist/cli/v4/display/capabilityCard.js +26 -0
  22. package/dist/cli/v4/display.js +18 -8
  23. package/dist/cli/v4/replyRenderer.js +31 -23
  24. package/dist/cli/v4/updateBootPrompt.js +170 -0
  25. package/dist/core/playwrightBridge.js +129 -0
  26. package/dist/core/v4/aidenAgent.js +308 -4
  27. package/dist/core/v4/browserState.js +436 -0
  28. package/dist/core/v4/checkpoint.js +79 -0
  29. package/dist/core/v4/daemon/bootstrap.js +604 -0
  30. package/dist/core/v4/daemon/cleanShutdown.js +154 -0
  31. package/dist/core/v4/daemon/cron/cronBridge.js +126 -0
  32. package/dist/core/v4/daemon/cron/cronEmitter.js +173 -0
  33. package/dist/core/v4/daemon/cron/migration.js +199 -0
  34. package/dist/core/v4/daemon/cron/misfirePolicy.js +115 -0
  35. package/dist/core/v4/daemon/daemonConfig.js +90 -0
  36. package/dist/core/v4/daemon/db/connection.js +106 -0
  37. package/dist/core/v4/daemon/db/migrations.js +296 -0
  38. package/dist/core/v4/daemon/db/schema/v1.spec.js +18 -0
  39. package/dist/core/v4/daemon/dispatcher/agentRunner.js +98 -0
  40. package/dist/core/v4/daemon/dispatcher/budgetGate.js +127 -0
  41. package/dist/core/v4/daemon/dispatcher/daemonApproval.js +113 -0
  42. package/dist/core/v4/daemon/dispatcher/dailyBudgetTracker.js +120 -0
  43. package/dist/core/v4/daemon/dispatcher/dispatcher.js +389 -0
  44. package/dist/core/v4/daemon/dispatcher/fireRateLimiter.js +113 -0
  45. package/dist/core/v4/daemon/dispatcher/index.js +53 -0
  46. package/dist/core/v4/daemon/dispatcher/promptTemplate.js +95 -0
  47. package/dist/core/v4/daemon/dispatcher/realAgentRunner.js +356 -0
  48. package/dist/core/v4/daemon/dispatcher/resolveModel.js +93 -0
  49. package/dist/core/v4/daemon/dispatcher/sessionId.js +93 -0
  50. package/dist/core/v4/daemon/drain.js +156 -0
  51. package/dist/core/v4/daemon/eventLoopLag.js +73 -0
  52. package/dist/core/v4/daemon/health.js +159 -0
  53. package/dist/core/v4/daemon/idempotencyStore.js +204 -0
  54. package/dist/core/v4/daemon/index.js +179 -0
  55. package/dist/core/v4/daemon/instanceTracker.js +99 -0
  56. package/dist/core/v4/daemon/resourceRegistry.js +150 -0
  57. package/dist/core/v4/daemon/restartCode.js +32 -0
  58. package/dist/core/v4/daemon/restartFailureCounter.js +77 -0
  59. package/dist/core/v4/daemon/runStore.js +114 -0
  60. package/dist/core/v4/daemon/runtimeLock.js +167 -0
  61. package/dist/core/v4/daemon/signals.js +50 -0
  62. package/dist/core/v4/daemon/supervisor.js +272 -0
  63. package/dist/core/v4/daemon/triggerBus.js +279 -0
  64. package/dist/core/v4/daemon/triggers/email/allowlist.js +70 -0
  65. package/dist/core/v4/daemon/triggers/email/automatedSender.js +78 -0
  66. package/dist/core/v4/daemon/triggers/email/bodyExtractor.js +0 -0
  67. package/dist/core/v4/daemon/triggers/email/emailSeenStore.js +99 -0
  68. package/dist/core/v4/daemon/triggers/email/emailSpec.js +107 -0
  69. package/dist/core/v4/daemon/triggers/email/imapConnection.js +211 -0
  70. package/dist/core/v4/daemon/triggers/email/index.js +332 -0
  71. package/dist/core/v4/daemon/triggers/email/seenUids.js +60 -0
  72. package/dist/core/v4/daemon/triggers/fileObservationsStore.js +93 -0
  73. package/dist/core/v4/daemon/triggers/fileWatcher.js +253 -0
  74. package/dist/core/v4/daemon/triggers/fileWatcherSpec.js +88 -0
  75. package/dist/core/v4/daemon/triggers/fsIdentity.js +42 -0
  76. package/dist/core/v4/daemon/triggers/globMatcher.js +100 -0
  77. package/dist/core/v4/daemon/triggers/reconcile.js +206 -0
  78. package/dist/core/v4/daemon/triggers/settleStat.js +81 -0
  79. package/dist/core/v4/daemon/triggers/webhook.js +376 -0
  80. package/dist/core/v4/daemon/triggers/webhookDeliveriesStore.js +109 -0
  81. package/dist/core/v4/daemon/triggers/webhookIdempotency.js +72 -0
  82. package/dist/core/v4/daemon/triggers/webhookRateLimit.js +56 -0
  83. package/dist/core/v4/daemon/triggers/webhookSpec.js +76 -0
  84. package/dist/core/v4/daemon/triggers/webhookVerifier.js +128 -0
  85. package/dist/core/v4/daemon/types.js +15 -0
  86. package/dist/core/v4/dockerSession.js +461 -0
  87. package/dist/core/v4/dryRun.js +117 -0
  88. package/dist/core/v4/failureClassifier.js +779 -0
  89. package/dist/core/v4/recoveryReport.js +449 -0
  90. package/dist/core/v4/runtimeToggles.js +187 -0
  91. package/dist/core/v4/sandboxConfig.js +285 -0
  92. package/dist/core/v4/sandboxFs.js +316 -0
  93. package/dist/core/v4/suggestionCatalog.js +41 -0
  94. package/dist/core/v4/suggestionEngine.js +210 -0
  95. package/dist/core/v4/toolRegistry.js +18 -0
  96. package/dist/core/v4/turnState.js +587 -0
  97. package/dist/core/v4/update/checkUpdate.js +63 -3
  98. package/dist/core/v4/update/installMethodDetect.js +115 -0
  99. package/dist/core/v4/update/registryClient.js +121 -0
  100. package/dist/core/v4/update/skipState.js +75 -0
  101. package/dist/core/v4/verifier.js +448 -0
  102. package/dist/core/version.js +1 -1
  103. package/dist/tools/v4/browser/_observer.js +224 -0
  104. package/dist/tools/v4/browser/browserBlocker.js +396 -0
  105. package/dist/tools/v4/browser/browserClick.js +18 -1
  106. package/dist/tools/v4/browser/browserClose.js +18 -1
  107. package/dist/tools/v4/browser/browserExtract.js +5 -1
  108. package/dist/tools/v4/browser/browserFill.js +17 -1
  109. package/dist/tools/v4/browser/browserGetUrl.js +5 -1
  110. package/dist/tools/v4/browser/browserNavigate.js +16 -1
  111. package/dist/tools/v4/browser/browserScreenshot.js +5 -1
  112. package/dist/tools/v4/browser/browserScroll.js +18 -1
  113. package/dist/tools/v4/browser/browserType.js +17 -1
  114. package/dist/tools/v4/browser/captchaCheck.js +5 -1
  115. package/dist/tools/v4/executeCode.js +1 -0
  116. package/dist/tools/v4/files/fileCopy.js +56 -2
  117. package/dist/tools/v4/files/fileDelete.js +38 -1
  118. package/dist/tools/v4/files/fileList.js +12 -1
  119. package/dist/tools/v4/files/fileMove.js +59 -2
  120. package/dist/tools/v4/files/filePatch.js +43 -1
  121. package/dist/tools/v4/files/fileRead.js +12 -1
  122. package/dist/tools/v4/files/fileWrite.js +41 -1
  123. package/dist/tools/v4/index.js +71 -58
  124. package/dist/tools/v4/memory/memoryAdd.js +14 -0
  125. package/dist/tools/v4/memory/memoryRemove.js +14 -0
  126. package/dist/tools/v4/memory/memoryReplace.js +15 -0
  127. package/dist/tools/v4/memory/sessionSummary.js +12 -0
  128. package/dist/tools/v4/process/processKill.js +19 -0
  129. package/dist/tools/v4/process/processList.js +1 -0
  130. package/dist/tools/v4/process/processLogRead.js +1 -0
  131. package/dist/tools/v4/process/processSpawn.js +13 -0
  132. package/dist/tools/v4/process/processWait.js +1 -0
  133. package/dist/tools/v4/sessions/recallSession.js +1 -0
  134. package/dist/tools/v4/sessions/sessionList.js +1 -0
  135. package/dist/tools/v4/sessions/sessionSearch.js +1 -0
  136. package/dist/tools/v4/skills/lookupToolSchema.js +2 -0
  137. package/dist/tools/v4/skills/skillManage.js +13 -0
  138. package/dist/tools/v4/skills/skillView.js +1 -0
  139. package/dist/tools/v4/skills/skillsList.js +1 -0
  140. package/dist/tools/v4/subagent/subagentFanout.js +1 -0
  141. package/dist/tools/v4/system/aidenSelfUpdate.js +16 -0
  142. package/dist/tools/v4/system/appClose.js +13 -0
  143. package/dist/tools/v4/system/appInput.js +13 -0
  144. package/dist/tools/v4/system/appLaunch.js +13 -0
  145. package/dist/tools/v4/system/clipboardRead.js +1 -0
  146. package/dist/tools/v4/system/clipboardWrite.js +14 -0
  147. package/dist/tools/v4/system/mediaKey.js +12 -0
  148. package/dist/tools/v4/system/mediaSessions.js +1 -0
  149. package/dist/tools/v4/system/mediaTransport.js +13 -0
  150. package/dist/tools/v4/system/naturalEvents.js +1 -0
  151. package/dist/tools/v4/system/nowPlaying.js +1 -0
  152. package/dist/tools/v4/system/osProcessList.js +1 -0
  153. package/dist/tools/v4/system/screenshot.js +1 -0
  154. package/dist/tools/v4/system/systemInfo.js +1 -0
  155. package/dist/tools/v4/system/volumeSet.js +17 -0
  156. package/dist/tools/v4/terminal/shellExec.js +81 -9
  157. package/dist/tools/v4/web/deepResearch.js +1 -0
  158. package/dist/tools/v4/web/openUrl.js +1 -0
  159. package/dist/tools/v4/web/webFetch.js +1 -0
  160. package/dist/tools/v4/web/webPage.js +1 -0
  161. package/dist/tools/v4/web/webSearch.js +1 -0
  162. package/dist/tools/v4/web/youtubeSearch.js +1 -0
  163. 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
+ };