aiden-runtime 4.8.1 → 4.9.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 +88 -1
- package/dist/cli/v4/aidenCLI.js +35 -4
- package/dist/cli/v4/chatSession.js +34 -9
- package/dist/cli/v4/commands/daemon.js +47 -2
- package/dist/cli/v4/commands/daemonDoctor.js +212 -0
- package/dist/cli/v4/commands/daemonStatus.js +1 -1
- package/dist/cli/v4/commands/help.js +2 -0
- package/dist/cli/v4/commands/hooks.js +428 -0
- package/dist/cli/v4/commands/index.js +5 -1
- package/dist/cli/v4/commands/mcp.js +89 -1
- package/dist/cli/v4/commands/mcpClientInstall.js +359 -0
- package/dist/cli/v4/commands/memory.js +702 -0
- package/dist/cli/v4/commands/recovery.js +1 -1
- package/dist/cli/v4/commands/skin.js +7 -0
- package/dist/cli/v4/commands/theme.js +217 -0
- package/dist/cli/v4/commands/trigger.js +1 -1
- package/dist/cli/v4/design/tokens.js +52 -4
- package/dist/cli/v4/display.js +39 -26
- package/dist/cli/v4/replyRenderer.js +6 -5
- package/dist/cli/v4/skinEngine.js +67 -0
- package/dist/core/v4/aidenAgent.js +45 -2
- package/dist/core/v4/daemon/api/runs.js +131 -0
- package/dist/core/v4/daemon/bootstrap.js +368 -13
- package/dist/core/v4/daemon/db/migrations.js +169 -0
- package/dist/core/v4/daemon/idempotency/runIdempotencyStore.js +128 -0
- package/dist/core/v4/daemon/incarnationStore.js +47 -0
- package/dist/core/v4/daemon/runs/attemptStore.js +67 -0
- package/dist/core/v4/daemon/runs/reclaim.js +88 -0
- package/dist/core/v4/daemon/runs/retryPolicy.js +73 -0
- package/dist/core/v4/daemon/runs/runWithRetry.js +80 -0
- package/dist/core/v4/daemon/runs/stuckAttemptWatchdog.js +72 -0
- package/dist/core/v4/daemon/spans/spanHelpers.js +272 -0
- package/dist/core/v4/daemon/spans/spanStore.js +113 -0
- package/dist/core/v4/daemon/triggerBus.js +50 -19
- package/dist/core/v4/hooks/auditQuery.js +67 -0
- package/dist/core/v4/hooks/dispatcher.js +286 -0
- package/dist/core/v4/hooks/index.js +46 -0
- package/dist/core/v4/hooks/lifecycle.js +27 -0
- package/dist/core/v4/hooks/manifest.js +142 -0
- package/dist/core/v4/hooks/registry.js +149 -0
- package/dist/core/v4/hooks/runtime/subprocessRunner.js +188 -0
- package/dist/core/v4/hooks/toolHookGate.js +76 -0
- package/dist/core/v4/hooks/trust.js +14 -0
- package/dist/core/v4/identity/contextManager.js +83 -0
- package/dist/core/v4/identity/daemonId.js +85 -0
- package/dist/core/v4/identity/enforcement.js +103 -0
- package/dist/core/v4/identity/executionContext.js +153 -0
- package/dist/core/v4/identity/hookExecution.js +62 -0
- package/dist/core/v4/identity/httpContext.js +68 -0
- package/dist/core/v4/identity/ids.js +185 -0
- package/dist/core/v4/identity/index.js +60 -0
- package/dist/core/v4/identity/subprocessContext.js +98 -0
- package/dist/core/v4/identity/traceparent.js +114 -0
- package/dist/core/v4/logger/index.js +3 -1
- package/dist/core/v4/logger/logger.js +28 -1
- package/dist/core/v4/logger/redact.js +149 -0
- package/dist/core/v4/logger/sinks/fileSink.js +13 -0
- package/dist/core/v4/logger/sinks/stdSink.js +19 -1
- package/dist/core/v4/mcp/install/backup.js +78 -0
- package/dist/core/v4/mcp/install/clientPaths.js +90 -0
- package/dist/core/v4/mcp/install/clients.js +203 -0
- package/dist/core/v4/mcp/install/healthCheck.js +83 -0
- package/dist/core/v4/mcp/install/jsoncMerge.js +174 -0
- package/dist/core/v4/mcp/install/profiles.js +109 -0
- package/dist/core/v4/mcp/install/wslDetect.js +62 -0
- package/dist/core/v4/memory/namespaceRegistry.js +117 -0
- package/dist/core/v4/memory/projectRoot.js +76 -0
- package/dist/core/v4/memory/reviewer/index.js +162 -0
- package/dist/core/v4/memory/reviewer/pendingStore.js +136 -0
- package/dist/core/v4/memory/reviewer/prompt.js +105 -0
- package/dist/core/v4/memory/reviewer/skipRules.js +92 -0
- package/dist/core/v4/memoryManager.js +57 -10
- package/dist/core/v4/paths.js +2 -0
- package/dist/core/v4/subagent/spawnSubAgent.js +20 -7
- package/dist/core/v4/theme/bundledThemes.js +106 -0
- package/dist/core/v4/theme/themeLoader.js +160 -0
- package/dist/core/v4/theme/themeRegistry.js +97 -0
- package/dist/core/v4/theme/themeWatcher.js +95 -0
- package/dist/core/v4/toolRegistry.js +71 -8
- package/dist/moat/approvalEngine.js +4 -0
- package/dist/moat/memoryGuard.js +8 -1
- package/dist/providers/v4/anthropicAdapter.js +10 -4
- package/dist/tools/v4/backends/local.js +19 -2
- package/dist/tools/v4/sessions/recallSession.js +6 -1
- package/package.json +3 -1
- package/plugins/aiden-plugin-chatgpt-plus/index.js +10 -1
- package/themes/default.yaml +52 -0
- package/themes/dracula.yaml +32 -0
- package/themes/light.yaml +32 -0
- package/themes/monochrome.yaml +31 -0
- package/themes/tokyo-night.yaml +32 -0
- package/dist/core/pluginSystem.js +0 -121
- package/dist/tools/v4/ui/_uiSmokeTool.js +0 -60
|
@@ -0,0 +1,95 @@
|
|
|
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
|
+
* core/v4/theme/themeWatcher.ts — v4.9.0 Slice 1a.
|
|
10
|
+
*
|
|
11
|
+
* chokidar-backed file watcher for `~/.aiden/theme.yaml`. On change
|
|
12
|
+
* (debounced 200ms to avoid mid-save partial reads), re-parses the
|
|
13
|
+
* file and applies it via the ThemeRegistry. Self-contained — caller
|
|
14
|
+
* just calls `startThemeWatcher(path)` once at REPL start and
|
|
15
|
+
* `stopThemeWatcher()` on quit.
|
|
16
|
+
*/
|
|
17
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.startThemeWatcher = startThemeWatcher;
|
|
22
|
+
exports.stopThemeWatcher = stopThemeWatcher;
|
|
23
|
+
exports._isWatcherActive = _isWatcherActive;
|
|
24
|
+
const chokidar_1 = __importDefault(require("chokidar"));
|
|
25
|
+
const node_fs_1 = require("node:fs");
|
|
26
|
+
const themeLoader_1 = require("./themeLoader");
|
|
27
|
+
const themeRegistry_1 = require("./themeRegistry");
|
|
28
|
+
const DEBOUNCE_MS = 200;
|
|
29
|
+
let active = null;
|
|
30
|
+
/**
|
|
31
|
+
* Start watching the theme file. If the file already exists at start,
|
|
32
|
+
* applies it immediately (so the first paint reflects the user's
|
|
33
|
+
* choice). Idempotent — calling twice replaces the previous watcher.
|
|
34
|
+
*/
|
|
35
|
+
function startThemeWatcher(themePath, opts = {}) {
|
|
36
|
+
stopThemeWatcher();
|
|
37
|
+
const debounceMs = opts.debounceMs ?? DEBOUNCE_MS;
|
|
38
|
+
const onWarn = opts.onWarn ?? ((m) => console.warn(`[theme] ${m}`));
|
|
39
|
+
// Apply on first-existence so the REPL boots into the user's theme.
|
|
40
|
+
if ((0, node_fs_1.existsSync)(themePath)) {
|
|
41
|
+
const { parsed, warnings } = (0, themeLoader_1.loadThemeFile)(themePath);
|
|
42
|
+
for (const w of warnings)
|
|
43
|
+
onWarn(w);
|
|
44
|
+
if (parsed)
|
|
45
|
+
(0, themeRegistry_1.applyTheme)(parsed, themePath);
|
|
46
|
+
}
|
|
47
|
+
const watcher = chokidar_1.default.watch(themePath, {
|
|
48
|
+
persistent: true,
|
|
49
|
+
awaitWriteFinish: { stabilityThreshold: debounceMs, pollInterval: 50 },
|
|
50
|
+
ignoreInitial: true,
|
|
51
|
+
});
|
|
52
|
+
const state = {
|
|
53
|
+
watcher,
|
|
54
|
+
debounceTimer: null,
|
|
55
|
+
themePath,
|
|
56
|
+
onWarn,
|
|
57
|
+
};
|
|
58
|
+
const reload = () => {
|
|
59
|
+
if (state.debounceTimer)
|
|
60
|
+
clearTimeout(state.debounceTimer);
|
|
61
|
+
state.debounceTimer = setTimeout(() => {
|
|
62
|
+
state.debounceTimer = null;
|
|
63
|
+
if (!(0, node_fs_1.existsSync)(themePath)) {
|
|
64
|
+
(0, themeRegistry_1.resetToDefault)();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const { parsed, warnings } = (0, themeLoader_1.loadThemeFile)(themePath);
|
|
68
|
+
for (const w of warnings)
|
|
69
|
+
onWarn(w);
|
|
70
|
+
if (parsed)
|
|
71
|
+
(0, themeRegistry_1.applyTheme)(parsed, themePath);
|
|
72
|
+
}, debounceMs);
|
|
73
|
+
};
|
|
74
|
+
watcher.on('add', reload);
|
|
75
|
+
watcher.on('change', reload);
|
|
76
|
+
watcher.on('unlink', () => {
|
|
77
|
+
if (state.debounceTimer)
|
|
78
|
+
clearTimeout(state.debounceTimer);
|
|
79
|
+
state.debounceTimer = null;
|
|
80
|
+
(0, themeRegistry_1.resetToDefault)();
|
|
81
|
+
});
|
|
82
|
+
watcher.on('error', (err) => onWarn(`watcher error: ${err.message}`));
|
|
83
|
+
active = state;
|
|
84
|
+
}
|
|
85
|
+
/** Stop the active watcher. No-op when none is running. */
|
|
86
|
+
function stopThemeWatcher() {
|
|
87
|
+
if (!active)
|
|
88
|
+
return;
|
|
89
|
+
if (active.debounceTimer)
|
|
90
|
+
clearTimeout(active.debounceTimer);
|
|
91
|
+
void active.watcher.close();
|
|
92
|
+
active = null;
|
|
93
|
+
}
|
|
94
|
+
/** Test helper. */
|
|
95
|
+
function _isWatcherActive() { return active !== null; }
|
|
@@ -186,15 +186,40 @@ class ToolRegistry {
|
|
|
186
186
|
};
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
+
// v4.9.0 Slice 6 — wrap the handler call in a tool span when the
|
|
190
|
+
// daemon foundation is up AND an ExecutionContext is active. NOOP
|
|
191
|
+
// outside daemon mode or outside a runWithContext frame. Lazy
|
|
192
|
+
// require avoids pulling daemon code into the v4 core import
|
|
193
|
+
// graph at module load (would break headless / cli-test imports
|
|
194
|
+
// that don't open a DB).
|
|
195
|
+
//
|
|
196
|
+
// v4.9.0 Slice 12a Phase 3 — inside the tool span, fire
|
|
197
|
+
// `tool.call.pre` + `tool.call.post` hooks via `runToolWithHooks`.
|
|
198
|
+
// Mandatory pre-hook blocks surface as HookBlockedError, caught
|
|
199
|
+
// by the outer try/catch and mapped to a structured error result.
|
|
200
|
+
const dispatch = async (a) => handler.execute(a, context);
|
|
201
|
+
let result;
|
|
189
202
|
try {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
203
|
+
const sliced = sliceSpanShim();
|
|
204
|
+
if (sliced && sliced.db && sliced.hasContext()) {
|
|
205
|
+
const sideEffect = sliced.classifySideEffect(handler);
|
|
206
|
+
const inputFp = sliced.fingerprint(args);
|
|
207
|
+
result = await sliced.withToolSpan(sliced.db, { toolName: call.name, inputFingerprint: inputFp, sideEffectClass: sideEffect }, async (childCtx) => sliced.runToolWithHooks({
|
|
208
|
+
db: sliced.db,
|
|
209
|
+
toolName: call.name,
|
|
210
|
+
toolCallId: call.id,
|
|
211
|
+
args,
|
|
212
|
+
ctx: {
|
|
213
|
+
runId: childCtx.runId,
|
|
214
|
+
traceId: childCtx.traceId,
|
|
215
|
+
spanId: childCtx.spanId,
|
|
216
|
+
parentSpanId: childCtx.parentSpanId,
|
|
217
|
+
},
|
|
218
|
+
}, dispatch));
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
result = await dispatch(args);
|
|
222
|
+
}
|
|
198
223
|
const inner = result;
|
|
199
224
|
const out = { id: call.id, name: call.name, result };
|
|
200
225
|
if (typeof inner?.degraded === 'boolean' && inner.degraded) {
|
|
@@ -206,6 +231,17 @@ class ToolRegistry {
|
|
|
206
231
|
return out;
|
|
207
232
|
}
|
|
208
233
|
catch (err) {
|
|
234
|
+
// v4.9.0 Slice 12a — hook blocks surface as a structured
|
|
235
|
+
// rejection so the model gets the hook's `reason` / `model_message`
|
|
236
|
+
// verbatim instead of a bare exception string.
|
|
237
|
+
if (err instanceof toolHookGate_1.HookBlockedError) {
|
|
238
|
+
return {
|
|
239
|
+
id: call.id,
|
|
240
|
+
name: call.name,
|
|
241
|
+
result: null,
|
|
242
|
+
error: err.modelMessage ?? err.message,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
209
245
|
const message = err instanceof Error ? err.message : String(err);
|
|
210
246
|
return { id: call.id, name: call.name, result: null, error: message };
|
|
211
247
|
}
|
|
@@ -213,3 +249,30 @@ class ToolRegistry {
|
|
|
213
249
|
}
|
|
214
250
|
}
|
|
215
251
|
exports.ToolRegistry = ToolRegistry;
|
|
252
|
+
// v4.9.0 Slice 6 — static imports for the span-shim bridge. Earlier
|
|
253
|
+
// attempts used lazy `require()` to keep daemon code out of the import
|
|
254
|
+
// graph when the test harness doesn't compile it; that path broke
|
|
255
|
+
// under vite-node which doesn't intercept CJS require for `.ts`
|
|
256
|
+
// targets. Static ESM imports work in both vitest + production builds.
|
|
257
|
+
const bootstrap_1 = require("./daemon/bootstrap");
|
|
258
|
+
const spanHelpers_1 = require("./daemon/spans/spanHelpers");
|
|
259
|
+
const identity_1 = require("./identity");
|
|
260
|
+
const toolHookGate_1 = require("./hooks/toolHookGate");
|
|
261
|
+
function classifySideEffectForHandler(h) {
|
|
262
|
+
if (h.riskTier === 'dangerous')
|
|
263
|
+
return 'destructive';
|
|
264
|
+
if (h.mutates === false)
|
|
265
|
+
return 'read';
|
|
266
|
+
if (h.mutates === true)
|
|
267
|
+
return 'mutating';
|
|
268
|
+
return 'read';
|
|
269
|
+
}
|
|
270
|
+
const _toolSpanShim = {
|
|
271
|
+
get db() { return (0, bootstrap_1.getCurrentDaemonDb)(); },
|
|
272
|
+
hasContext: () => (0, identity_1.currentContext)() !== undefined,
|
|
273
|
+
classifySideEffect: classifySideEffectForHandler,
|
|
274
|
+
fingerprint: spanHelpers_1.shortInputFingerprint,
|
|
275
|
+
withToolSpan: spanHelpers_1.withToolSpan,
|
|
276
|
+
runToolWithHooks: toolHookGate_1.runToolWithHooks,
|
|
277
|
+
};
|
|
278
|
+
function sliceSpanShim() { return _toolSpanShim; }
|
|
@@ -180,6 +180,10 @@ class ApprovalEngine {
|
|
|
180
180
|
* categories are always allowed without consulting any callback.
|
|
181
181
|
*/
|
|
182
182
|
async checkApproval(req) {
|
|
183
|
+
// v4.9.0 Slice 12b — fire `approval.requested` for any gated call.
|
|
184
|
+
// Read-category short-circuits below; we still fire so observers
|
|
185
|
+
// see ALL approval requests (not just the ones that prompt).
|
|
186
|
+
this.callbacks.onRequested?.(req);
|
|
183
187
|
if (req.category === 'read') {
|
|
184
188
|
this.callbacks.onDecision?.(req, 'allow');
|
|
185
189
|
return true;
|
package/dist/moat/memoryGuard.js
CHANGED
|
@@ -212,7 +212,14 @@ class MemoryGuard {
|
|
|
212
212
|
}
|
|
213
213
|
exports.MemoryGuard = MemoryGuard;
|
|
214
214
|
function pickFile(snap, file) {
|
|
215
|
-
|
|
215
|
+
// v4.9.0 Slice 11 — legacy back-compat for 'memory' / 'user' direct
|
|
216
|
+
// reads (Phase 9 + Honesty Enforcement still consult these); new
|
|
217
|
+
// namespaces flow through the generalized `files` map.
|
|
218
|
+
if (file === 'user' && snap.userMd !== undefined)
|
|
219
|
+
return snap.userMd;
|
|
220
|
+
if (file === 'memory' && snap.memoryMd !== undefined)
|
|
221
|
+
return snap.memoryMd;
|
|
222
|
+
return snap.files?.[file]?.content ?? '';
|
|
216
223
|
}
|
|
217
224
|
/**
|
|
218
225
|
* Phase v4.1.2-bug-X: section-aware containment check.
|
|
@@ -92,14 +92,14 @@ class AnthropicAdapter {
|
|
|
92
92
|
// ── Public: non-streaming ────────────────────────────────────────────────
|
|
93
93
|
async call(input) {
|
|
94
94
|
const body = this.buildBody(input, /* streaming */ false);
|
|
95
|
-
const reply = await this.dispatch(body, /* streaming */ false, input.signal);
|
|
95
|
+
const reply = await this.dispatch(body, /* streaming */ false, input.signal, input.headers);
|
|
96
96
|
const json = (await reply.json());
|
|
97
97
|
return decodeResponse(json);
|
|
98
98
|
}
|
|
99
99
|
// ── Public: streaming ────────────────────────────────────────────────────
|
|
100
100
|
async *callStream(input) {
|
|
101
101
|
const body = this.buildBody(input, /* streaming */ true);
|
|
102
|
-
const reply = await this.dispatch(body, /* streaming */ true, input.signal);
|
|
102
|
+
const reply = await this.dispatch(body, /* streaming */ true, input.signal, input.headers);
|
|
103
103
|
if (!reply.body) {
|
|
104
104
|
// Server promised SSE but gave us nothing — fall through to a synthetic
|
|
105
105
|
// empty done event so the agent loop terminates rather than hangs.
|
|
@@ -163,11 +163,17 @@ class AnthropicAdapter {
|
|
|
163
163
|
// beta flags, or per-deployment routing tags without forking the adapter.
|
|
164
164
|
return { ...headers, ...this.extraHeaders };
|
|
165
165
|
}
|
|
166
|
-
async dispatch(body, streaming, externalSignal) {
|
|
166
|
+
async dispatch(body, streaming, externalSignal, outboundHeaders) {
|
|
167
167
|
// Resolved once per process via the userAgent module's cache, so paying
|
|
168
168
|
// for the version detection here is cheap on every retry/turn.
|
|
169
169
|
const userAgent = await (0, userAgent_1.getClaudeCliUserAgent)();
|
|
170
|
-
|
|
170
|
+
// v4.9.0 Slice 7 — merge caller-supplied outbound headers (e.g.
|
|
171
|
+
// `traceparent`, `X-Aiden-Run-Id`) below the adapter's defaults so
|
|
172
|
+
// they can't override `Authorization` / `anthropic-version` etc.,
|
|
173
|
+
// but above `extraHeaders` so a deliberate per-deployment override
|
|
174
|
+
// still wins.
|
|
175
|
+
const base = this.buildHeaders(streaming, userAgent);
|
|
176
|
+
const headers = outboundHeaders ? { ...outboundHeaders, ...base } : base;
|
|
171
177
|
const serialised = JSON.stringify(body);
|
|
172
178
|
const totalTries = this.maxRetries + 1;
|
|
173
179
|
let lastErr = null;
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
exports.localBackendExecute = localBackendExecute;
|
|
22
22
|
const node_child_process_1 = require("node:child_process");
|
|
23
|
+
// v4.9.0 Slice 7 — propagate ExecutionContext into the child via env.
|
|
24
|
+
const identity_1 = require("../../../core/v4/identity");
|
|
23
25
|
const DEFAULT_TIMEOUT = 30000;
|
|
24
26
|
async function localBackendExecute(args, cb = {}) {
|
|
25
27
|
const command = args.command.trim();
|
|
@@ -38,14 +40,29 @@ async function localBackendExecute(args, cb = {}) {
|
|
|
38
40
|
const timeoutMs = args.timeoutMs ?? DEFAULT_TIMEOUT;
|
|
39
41
|
const capture = args.captureOutput ?? true;
|
|
40
42
|
return new Promise((resolve) => {
|
|
43
|
+
// v4.9.0 Slice 7 — when running inside a `runWithContext` frame,
|
|
44
|
+
// stamp AIDEN_* env vars so the child process can reconstitute
|
|
45
|
+
// the same daemon/incarnation/run/trace correlation chain via
|
|
46
|
+
// `readContextFromEnv(process.env)`. Outside a context frame, the
|
|
47
|
+
// env spread is unchanged.
|
|
48
|
+
const ambient = (0, identity_1.currentContext)();
|
|
49
|
+
let baseEnv;
|
|
50
|
+
if (ambient) {
|
|
51
|
+
baseEnv = (0, identity_1.spawnEnvWithContext)(ambient, process.env);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// v4.9.0 Slice 8 — report through the enforcement layer.
|
|
55
|
+
(0, identity_1.reportMissingContext)('subprocess', 'shellExec');
|
|
56
|
+
baseEnv = process.env;
|
|
57
|
+
}
|
|
41
58
|
const child = isWin
|
|
42
59
|
? (0, node_child_process_1.spawn)('powershell.exe', ['-NoProfile', '-Command', command], {
|
|
43
60
|
cwd: args.cwd,
|
|
44
|
-
env: { ...
|
|
61
|
+
env: { ...baseEnv, ...(args.env ?? {}) },
|
|
45
62
|
})
|
|
46
63
|
: (0, node_child_process_1.spawn)('bash', ['-lc', command], {
|
|
47
64
|
cwd: args.cwd,
|
|
48
|
-
env: { ...
|
|
65
|
+
env: { ...baseEnv, ...(args.env ?? {}) },
|
|
49
66
|
});
|
|
50
67
|
let stdout = '';
|
|
51
68
|
let stderr = '';
|
|
@@ -86,7 +86,10 @@ exports.recallSessionTool = {
|
|
|
86
86
|
error: 'recall_session requires resolved aiden paths',
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
|
-
|
|
89
|
+
// v4.9.0 Slice 9 — paths hygiene: use centralised distillationsDir
|
|
90
|
+
// when present (added in Slice 9); fall back to the legacy ad-hoc
|
|
91
|
+
// reconstruction so externally-mocked `ctx.paths` objects keep working.
|
|
92
|
+
const dir = ctx.paths.distillationsDir ?? node_path_1.default.join(ctx.paths.root, 'distillations');
|
|
90
93
|
// Read everything off disk first. Each failure (malformed JSON,
|
|
91
94
|
// EACCES on individual files) is skipped silently; the diagnostic
|
|
92
95
|
// for "files exist but couldn't be read" is the gap between
|
|
@@ -169,6 +172,8 @@ exports.recallSessionTool = {
|
|
|
169
172
|
// register recall_session with the slice3 SubsystemHealthRegistry
|
|
170
173
|
// pass this helper to the tracker so they get health snapshots without
|
|
171
174
|
// hard-coding the path in two places.
|
|
175
|
+
// v4.9.0 Slice 9 — kept for back-compat; mirrors `paths.distillationsDir`
|
|
176
|
+
// without requiring the full AidenPaths object.
|
|
172
177
|
function getDistillationsDir(rootDir) {
|
|
173
178
|
return node_path_1.default.join(rootDir, 'distillations');
|
|
174
179
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiden-runtime",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.9.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"dist/",
|
|
44
44
|
"config/",
|
|
45
45
|
"skills/",
|
|
46
|
+
"themes/",
|
|
46
47
|
"plugins/aiden-plugin-cdp-browser/",
|
|
47
48
|
"plugins/aiden-plugin-claude-pro/",
|
|
48
49
|
"plugins/aiden-plugin-chatgpt-plus/",
|
|
@@ -256,6 +257,7 @@
|
|
|
256
257
|
"imap-simple": "^5.1.0",
|
|
257
258
|
"js-tiktoken": "^1.0.21",
|
|
258
259
|
"js-yaml": "^4.1.1",
|
|
260
|
+
"jsonc-parser": "^3.3.1",
|
|
259
261
|
"kleur": "^4.1.5",
|
|
260
262
|
"lru-cache": "^10.0.0",
|
|
261
263
|
"mailparser": "^3.9.8",
|
|
@@ -37,7 +37,16 @@ const CHATGPT_PLUS = {
|
|
|
37
37
|
displayName: 'ChatGPT Plus',
|
|
38
38
|
description:
|
|
39
39
|
'Sign in with your ChatGPT Plus subscription. Uses your existing ChatGPT login — no API key needed. Inference is routed through the Codex Responses API.',
|
|
40
|
-
defaultModels:
|
|
40
|
+
// v4.9.0 — `defaultModels[0]` is what `setupWizard.ts:810` picks
|
|
41
|
+
// as a new ChatGPT-Plus user's first model. The Codex OAuth backend
|
|
42
|
+
// rejects `gpt-5` outright with a 400 ("not supported when using
|
|
43
|
+
// Codex with a ChatGPT account") for new accounts; `gpt-5.5` is the
|
|
44
|
+
// first non-codex slug in the registry's modelIds and works
|
|
45
|
+
// reliably. `gpt-5` stays in the array so users who specifically
|
|
46
|
+
// want it can still see it in /model. `gpt-5-mini` was removed —
|
|
47
|
+
// it's a direct OpenAI API name and is NOT valid on the Codex OAuth
|
|
48
|
+
// endpoint (see providers/v4/registry.ts:117–119).
|
|
49
|
+
defaultModels: ['gpt-5.5', 'gpt-5'],
|
|
41
50
|
|
|
42
51
|
clientId: 'app_EMoamEEZ73f0CkXaXp7hrann',
|
|
43
52
|
issuer: 'https://auth.openai.com',
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Aiden Theme — Default
|
|
2
|
+
# This is the bundled default theme. To customise, copy this file to
|
|
3
|
+
# ~/.aiden/theme.yaml and edit any field. Aiden hot-reloads on save.
|
|
4
|
+
# Bad values warn + fall back per-field; the theme system never crashes
|
|
5
|
+
# Aiden on a typo. Slash commands: /theme reload, /theme reset, /theme edit.
|
|
6
|
+
|
|
7
|
+
name: "default"
|
|
8
|
+
description: "Aiden's signature brand-orange theme on a dark terminal."
|
|
9
|
+
|
|
10
|
+
# ── Colors — hex strings ───────────────────────────────────────────────
|
|
11
|
+
colors:
|
|
12
|
+
brand:
|
|
13
|
+
primary: "#FF6B35" # signature brand orange
|
|
14
|
+
muted: "#7a3119" # 30%-luma brand for borders + dim brand surfaces
|
|
15
|
+
content:
|
|
16
|
+
primary: "#e8ebf0" # brightest text — replies, headings on dark bg
|
|
17
|
+
secondary: "#b8a89a" # warm muted — gutter, secondary detail
|
|
18
|
+
tertiary: "#6a6a6a" # captions, deprecated rows, dim status
|
|
19
|
+
semantic:
|
|
20
|
+
success: "#7fc28b"
|
|
21
|
+
warn: "#e0a040"
|
|
22
|
+
error: "#e05a5a"
|
|
23
|
+
info: "#7da7c7"
|
|
24
|
+
metrics:
|
|
25
|
+
model: "#9cdcfe" # status bar — model name (cyan)
|
|
26
|
+
tokens: "#e0a040" # status bar — token ratio (amber)
|
|
27
|
+
turnCount: "#a48be0" # status bar — turn counter (purple)
|
|
28
|
+
timer: "#7fc28b" # status bar — per-turn elapsed (teal/green)
|
|
29
|
+
surface:
|
|
30
|
+
bg: "#0d0e10"
|
|
31
|
+
elevated: "#16181b"
|
|
32
|
+
border: "#2a2a2a"
|
|
33
|
+
divider: "#3a3a3a"
|
|
34
|
+
|
|
35
|
+
# ── Glyphs ─────────────────────────────────────────────────────────────
|
|
36
|
+
glyphs:
|
|
37
|
+
panel:
|
|
38
|
+
bar: "│" # left-edge bar on /help, approval, Aiden reply chrome
|
|
39
|
+
trail:
|
|
40
|
+
gutter: "┊" # tool-trail row gutter
|
|
41
|
+
status:
|
|
42
|
+
triangle: "▲" # user-prompt prefix + brand mark
|
|
43
|
+
dot: "●"
|
|
44
|
+
dotOpen: "○"
|
|
45
|
+
sep: "│" # status footer column separator
|
|
46
|
+
timer: "⌛"
|
|
47
|
+
bar:
|
|
48
|
+
filled: "●" # context-bar filled cell
|
|
49
|
+
empty: "○" # context-bar empty cell
|
|
50
|
+
shimmer:
|
|
51
|
+
block: "█" # activity-indicator sliding block
|
|
52
|
+
track: "─" # activity-indicator track
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Aiden Theme — Dracula
|
|
2
|
+
# Palette inspired by the public Dracula theme by Zeno Rocha
|
|
3
|
+
# (draculatheme.com). High-contrast dark with vivid accents, widely
|
|
4
|
+
# re-implemented across editors and terminals. Hex values are the
|
|
5
|
+
# public palette. Glyphs unchanged from default.
|
|
6
|
+
|
|
7
|
+
name: "dracula"
|
|
8
|
+
description: "Inspired by Dracula (draculatheme.com). High-contrast dark with vivid accents."
|
|
9
|
+
|
|
10
|
+
colors:
|
|
11
|
+
brand:
|
|
12
|
+
primary: "#FF79C6"
|
|
13
|
+
muted: "#BD7AA3"
|
|
14
|
+
content:
|
|
15
|
+
primary: "#F8F8F2"
|
|
16
|
+
secondary: "#BFBFBF"
|
|
17
|
+
tertiary: "#6272A4"
|
|
18
|
+
semantic:
|
|
19
|
+
success: "#50FA7B"
|
|
20
|
+
warn: "#F1FA8C"
|
|
21
|
+
error: "#FF5555"
|
|
22
|
+
info: "#8BE9FD"
|
|
23
|
+
metrics:
|
|
24
|
+
model: "#8BE9FD"
|
|
25
|
+
tokens: "#F1FA8C"
|
|
26
|
+
timer: "#8BE9FD"
|
|
27
|
+
turnCount: "#BD93F9"
|
|
28
|
+
surface:
|
|
29
|
+
bg: "#282A36"
|
|
30
|
+
elevated: "#21222C"
|
|
31
|
+
border: "#44475A"
|
|
32
|
+
divider: "#1E1F29"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Aiden Theme — Light
|
|
2
|
+
# Dark text on light terminal background. Brand orange retained as the
|
|
3
|
+
# single warm accent. For users on light-theme terminals (Apple Terminal
|
|
4
|
+
# default profile, Windows Terminal Light, light VS Code integrated, etc.).
|
|
5
|
+
# Glyphs unchanged from default.
|
|
6
|
+
|
|
7
|
+
name: "light"
|
|
8
|
+
description: "Light terminal. Dark text on light background. Brand orange accent."
|
|
9
|
+
|
|
10
|
+
colors:
|
|
11
|
+
brand:
|
|
12
|
+
primary: "#D9531E"
|
|
13
|
+
muted: "#A03D0E"
|
|
14
|
+
content:
|
|
15
|
+
primary: "#1A1A1A"
|
|
16
|
+
secondary: "#555555"
|
|
17
|
+
tertiary: "#888888"
|
|
18
|
+
semantic:
|
|
19
|
+
success: "#2E8B2E"
|
|
20
|
+
warn: "#B8860B"
|
|
21
|
+
error: "#C8202C"
|
|
22
|
+
info: "#1F5FA8"
|
|
23
|
+
metrics:
|
|
24
|
+
model: "#1F5FA8"
|
|
25
|
+
tokens: "#B8860B"
|
|
26
|
+
timer: "#1F5FA8"
|
|
27
|
+
turnCount: "#7B3FBF"
|
|
28
|
+
surface:
|
|
29
|
+
bg: "#F8F8F8"
|
|
30
|
+
elevated: "#EFEFEF"
|
|
31
|
+
border: "#D0D0D0"
|
|
32
|
+
divider: "#E5E5E5"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Aiden Theme — Monochrome
|
|
2
|
+
# Pure greyscale. Two semantic accents (error red + success green) are
|
|
3
|
+
# retained for readability of state signals. Everything else greyscale.
|
|
4
|
+
# Glyphs unchanged from default — themes change colors, not shapes.
|
|
5
|
+
|
|
6
|
+
name: "monochrome"
|
|
7
|
+
description: "Pure greyscale. Semantic accents retained for error/success readability."
|
|
8
|
+
|
|
9
|
+
colors:
|
|
10
|
+
brand:
|
|
11
|
+
primary: "#C8CCD4"
|
|
12
|
+
muted: "#888888"
|
|
13
|
+
content:
|
|
14
|
+
primary: "#C8CCD4"
|
|
15
|
+
secondary: "#888888"
|
|
16
|
+
tertiary: "#555555"
|
|
17
|
+
semantic:
|
|
18
|
+
success: "#7DC97D"
|
|
19
|
+
warn: "#999999"
|
|
20
|
+
error: "#D97777"
|
|
21
|
+
info: "#AAAAAA"
|
|
22
|
+
metrics:
|
|
23
|
+
model: "#AAAAAA"
|
|
24
|
+
tokens: "#AAAAAA"
|
|
25
|
+
timer: "#888888"
|
|
26
|
+
turnCount: "#BBBBBB"
|
|
27
|
+
surface:
|
|
28
|
+
bg: "#0A0A0A"
|
|
29
|
+
elevated: "#1A1A1A"
|
|
30
|
+
border: "#444444"
|
|
31
|
+
divider: "#3A3A3A"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Aiden Theme — Tokyo Night
|
|
2
|
+
# Palette inspired by the public Tokyo Night theme by Folke Lemaitre
|
|
3
|
+
# (folke/tokyonight.nvim). Cool nocturnal palette widely re-implemented
|
|
4
|
+
# across editors and terminals. Hex values are the public palette.
|
|
5
|
+
# Glyphs unchanged from default.
|
|
6
|
+
|
|
7
|
+
name: "tokyo-night"
|
|
8
|
+
description: "Inspired by Tokyo Night (folke/tokyonight.nvim). Cool nocturnal palette."
|
|
9
|
+
|
|
10
|
+
colors:
|
|
11
|
+
brand:
|
|
12
|
+
primary: "#7AA2F7"
|
|
13
|
+
muted: "#3D59A1"
|
|
14
|
+
content:
|
|
15
|
+
primary: "#C0CAF5"
|
|
16
|
+
secondary: "#9AA5CE"
|
|
17
|
+
tertiary: "#565F89"
|
|
18
|
+
semantic:
|
|
19
|
+
success: "#9ECE6A"
|
|
20
|
+
warn: "#E0AF68"
|
|
21
|
+
error: "#F7768E"
|
|
22
|
+
info: "#7DCFFF"
|
|
23
|
+
metrics:
|
|
24
|
+
model: "#7DCFFF"
|
|
25
|
+
tokens: "#E0AF68"
|
|
26
|
+
timer: "#7DCFFF"
|
|
27
|
+
turnCount: "#BB9AF7"
|
|
28
|
+
surface:
|
|
29
|
+
bg: "#1A1B26"
|
|
30
|
+
elevated: "#24283B"
|
|
31
|
+
border: "#3B4261"
|
|
32
|
+
divider: "#1F2335"
|