aiden-runtime 4.9.1 → 4.9.3
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 +47 -1
- package/dist/cli/v4/aidenPrompt.js +12 -0
- package/dist/cli/v4/chatSession.js +41 -13
- package/dist/cli/v4/commands/channel.js +4 -6
- package/dist/cli/v4/commands/cron.js +6 -1
- package/dist/cli/v4/commands/daemonDoctor.js +5 -5
- package/dist/cli/v4/commands/daemonStatus.js +1 -1
- package/dist/cli/v4/commands/greeter.js +86 -0
- package/dist/cli/v4/commands/help.js +2 -0
- package/dist/cli/v4/commands/index.js +4 -0
- package/dist/cli/v4/commands/mcp.js +2 -2
- package/dist/cli/v4/commands/plugins.js +4 -6
- package/dist/cli/v4/commands/trigger.js +18 -18
- package/dist/cli/v4/confirmPrompt.js +67 -0
- package/dist/cli/v4/greeter/history.js +134 -0
- package/dist/cli/v4/greeter/index.js +147 -0
- package/dist/cli/v4/greeter/scan.js +140 -0
- package/dist/cli/v4/greeter/selectOffer.js +118 -0
- package/dist/cli/v4/greeter/templates.js +51 -0
- package/dist/cli/v4/greeter/types.js +23 -0
- package/dist/core/v4/daemon/db/migrations.js +398 -398
- package/dist/core/v4/daemon/idempotency/runIdempotencyStore.js +10 -10
- package/dist/core/v4/daemon/incarnationStore.js +9 -9
- package/dist/core/v4/daemon/runs/attemptStore.js +8 -8
- package/dist/core/v4/daemon/runs/reclaim.js +12 -12
- package/dist/core/v4/daemon/runs/stuckAttemptWatchdog.js +19 -19
- package/dist/core/v4/daemon/spans/spanStore.js +14 -14
- package/dist/core/v4/daemon/triggerBus.js +61 -61
- package/dist/core/v4/hooks/auditQuery.js +11 -11
- package/dist/core/v4/hooks/dispatcher.js +13 -13
- package/dist/core/v4/hooks/registry.js +8 -8
- package/dist/core/v4/mcp/transport.js +9 -9
- package/dist/core/v4/update/executeInstall.js +29 -18
- package/dist/core/v4/update/recoveryScript.js +70 -0
- package/dist/core/v4/util/spawnCommand.js +151 -0
- package/package.json +1 -1
- package/themes/default.yaml +52 -52
- package/themes/dracula.yaml +32 -32
- package/themes/light.yaml +32 -32
- package/themes/monochrome.yaml +31 -31
- package/themes/tokyo-night.yaml +32 -32
|
@@ -54,6 +54,8 @@ const node_os_1 = __importDefault(require("node:os"));
|
|
|
54
54
|
const depWarningFilter_1 = require("./depWarningFilter");
|
|
55
55
|
const platformInstructions_1 = require("./platformInstructions");
|
|
56
56
|
const progressBar_1 = require("../../../cli/v4/ui/progressBar");
|
|
57
|
+
const spawnCommand_1 = require("../util/spawnCommand");
|
|
58
|
+
const recoveryScript_1 = require("./recoveryScript");
|
|
57
59
|
/** 90 s wall-clock cap. Generous on cold caches / slow networks. */
|
|
58
60
|
exports.INSTALL_TIMEOUT_MS = 90000;
|
|
59
61
|
const DEFAULT_PACKAGE_SPEC = 'aiden-runtime@latest';
|
|
@@ -76,29 +78,38 @@ async function executeInstall(opts = {}) {
|
|
|
76
78
|
const onPhase = opts.onPhase ?? ((_p) => { });
|
|
77
79
|
return new Promise((resolve) => {
|
|
78
80
|
const args = ['install', '-g', packageSpec];
|
|
79
|
-
// v4.
|
|
80
|
-
// `
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
// shell either — on Windows we spawn `npm.cmd` explicitly (the
|
|
84
|
-
// shim that PATHEXT would otherwise resolve to); on POSIX we
|
|
85
|
-
// spawn `npm` directly. No user input flows into argv on either
|
|
86
|
-
// path so the prior shell-resolution wasn't load-bearing.
|
|
87
|
-
const cmd = platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
88
|
-
const spawnOpts = {
|
|
89
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
90
|
-
};
|
|
81
|
+
// v4.9.2 — route through the shared spawnCommand helper. On
|
|
82
|
+
// Windows it wraps `npm.cmd` through `cmd.exe /d /s /c` with
|
|
83
|
+
// escaped args (no shell:true → no argument injection; no plain
|
|
84
|
+
// .cmd spawn → no Node 20+ EINVAL). On Unix it's a direct spawn.
|
|
91
85
|
onPhase('spawning');
|
|
92
86
|
let child;
|
|
93
87
|
try {
|
|
94
|
-
|
|
88
|
+
const r = (0, spawnCommand_1.spawnCommand)('npm', args, {
|
|
89
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
90
|
+
platform,
|
|
91
|
+
spawnImpl: spawn,
|
|
92
|
+
});
|
|
93
|
+
child = r.child;
|
|
95
94
|
}
|
|
96
95
|
catch (err) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
// Synchronous spawn failure (helper crash, cmd.exe missing,
|
|
97
|
+
// invalid argv). Drop a recovery script the user can run by
|
|
98
|
+
// hand and report its path.
|
|
99
|
+
(async () => {
|
|
100
|
+
let recoveryPath = null;
|
|
101
|
+
try {
|
|
102
|
+
recoveryPath = await (0, recoveryScript_1.writeRecoveryScript)({ platform, home, packageSpec });
|
|
103
|
+
}
|
|
104
|
+
catch { /* best-effort */ }
|
|
105
|
+
resolve({
|
|
106
|
+
success: false,
|
|
107
|
+
error: `Could not launch npm: ${err.message}. ` +
|
|
108
|
+
(recoveryPath
|
|
109
|
+
? `A recovery script was written to ${recoveryPath} — run it to complete the install.`
|
|
110
|
+
: `Run \`npm install -g ${packageSpec}\` manually.`),
|
|
111
|
+
});
|
|
112
|
+
})();
|
|
102
113
|
return;
|
|
103
114
|
}
|
|
104
115
|
let stdoutBuf = '';
|
|
@@ -0,0 +1,70 @@
|
|
|
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/update/recoveryScript.ts — v4.9.2 SLICE 1.
|
|
10
|
+
*
|
|
11
|
+
* Fallback when spawnCommand() itself fails to launch npm (synchronous
|
|
12
|
+
* throw — invalid argv shape, cmd.exe missing, etc.). We write a small
|
|
13
|
+
* shell script the user can run by hand to complete the install and
|
|
14
|
+
* report its path in the failure message. Honest: we tried, we couldn't
|
|
15
|
+
* launch, here's the exact thing to type.
|
|
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.writeRecoveryScript = writeRecoveryScript;
|
|
22
|
+
const node_fs_1 = require("node:fs");
|
|
23
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
24
|
+
/**
|
|
25
|
+
* Write a recovery script under `~/.aiden/`:
|
|
26
|
+
* - Windows → update-recovery.ps1 (PowerShell)
|
|
27
|
+
* - Unix → update-recovery.sh (bash, +x)
|
|
28
|
+
*
|
|
29
|
+
* Returns the absolute path written. Creates `~/.aiden/` if missing.
|
|
30
|
+
*/
|
|
31
|
+
async function writeRecoveryScript(input) {
|
|
32
|
+
const aidenDir = node_path_1.default.join(input.home, '.aiden');
|
|
33
|
+
await node_fs_1.promises.mkdir(aidenDir, { recursive: true });
|
|
34
|
+
if (input.platform === 'win32') {
|
|
35
|
+
const p = node_path_1.default.join(aidenDir, 'update-recovery.ps1');
|
|
36
|
+
const body = [
|
|
37
|
+
'# Aiden v4.9.2 — install-recovery fallback.',
|
|
38
|
+
'# Run from PowerShell (right-click → "Run with PowerShell" if associated).',
|
|
39
|
+
`Write-Host "Installing ${input.packageSpec} via npm..."`,
|
|
40
|
+
`npm install -g ${input.packageSpec}`,
|
|
41
|
+
'if ($LASTEXITCODE -ne 0) {',
|
|
42
|
+
' Write-Host "If you saw EPERM/EACCES, retry from an Administrator PowerShell."',
|
|
43
|
+
' exit $LASTEXITCODE',
|
|
44
|
+
'}',
|
|
45
|
+
`Write-Host "Done. Type 'aiden' to launch the new version."`,
|
|
46
|
+
'',
|
|
47
|
+
].join('\r\n');
|
|
48
|
+
await node_fs_1.promises.writeFile(p, body, 'utf8');
|
|
49
|
+
return p;
|
|
50
|
+
}
|
|
51
|
+
const p = node_path_1.default.join(aidenDir, 'update-recovery.sh');
|
|
52
|
+
const body = [
|
|
53
|
+
'#!/usr/bin/env bash',
|
|
54
|
+
'# Aiden v4.9.2 — install-recovery fallback.',
|
|
55
|
+
'set -e',
|
|
56
|
+
`echo "Installing ${input.packageSpec} via npm..."`,
|
|
57
|
+
`if ! npm install -g ${input.packageSpec}; then`,
|
|
58
|
+
' echo "Install failed. If you saw EACCES, retry with: sudo $0"',
|
|
59
|
+
' exit 1',
|
|
60
|
+
'fi',
|
|
61
|
+
'echo "Done. Type \\"aiden\\" to launch the new version."',
|
|
62
|
+
'',
|
|
63
|
+
].join('\n');
|
|
64
|
+
await node_fs_1.promises.writeFile(p, body, 'utf8');
|
|
65
|
+
try {
|
|
66
|
+
await node_fs_1.promises.chmod(p, 0o755);
|
|
67
|
+
}
|
|
68
|
+
catch { /* noop on platforms that don't support chmod */ }
|
|
69
|
+
return p;
|
|
70
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
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/util/spawnCommand.ts — v4.9.2 SLICE 1.
|
|
10
|
+
*
|
|
11
|
+
* Cross-platform spawn helper that survives the Node 18.20+ / 20+
|
|
12
|
+
* Windows EINVAL trap on `.cmd` / `.bat` shims. Two surfaces consume it:
|
|
13
|
+
* - core/v4/update/executeInstall.ts (spawns `npm install -g …`)
|
|
14
|
+
* - core/v4/mcp/transport.ts (spawns user-configured MCP servers,
|
|
15
|
+
* typically `npx -y <server>`)
|
|
16
|
+
*
|
|
17
|
+
* Both previously called `spawn(cmd, args, { shell: false })` directly,
|
|
18
|
+
* which throws EINVAL on Windows when `cmd` resolves to `.cmd` / `.bat`.
|
|
19
|
+
* The naive fix — `shell: true` — would silently permit argument
|
|
20
|
+
* injection through MCP server config (user-supplied command line),
|
|
21
|
+
* so we route Windows shims through `cmd.exe /d /s /c <quoted>` with
|
|
22
|
+
* `windowsVerbatimArguments: true` and manual cmd-meta escaping.
|
|
23
|
+
*
|
|
24
|
+
* Returns the raw ChildProcess (not a callback abstraction): both
|
|
25
|
+
* consumers need the full duplex surface (stdin write, stdout/stderr
|
|
26
|
+
* stream, exit + error events, SIGTERM → SIGKILL escalation). The
|
|
27
|
+
* helper's value is resolving the EINVAL trap, not abstracting I/O.
|
|
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.resolveCommand = resolveCommand;
|
|
34
|
+
exports.escapeCmdArg = escapeCmdArg;
|
|
35
|
+
exports.spawnCommand = spawnCommand;
|
|
36
|
+
const node_child_process_1 = require("node:child_process");
|
|
37
|
+
const node_fs_1 = require("node:fs");
|
|
38
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a bare command name to an absolute disk path via PATH lookup.
|
|
41
|
+
* On Windows tries PATHEXT order (.cmd, .exe, .bat, .ps1). If `command`
|
|
42
|
+
* is already absolute or contains a path separator, returns it verbatim
|
|
43
|
+
* (still detects shim suffix). Returns null when no match — caller can
|
|
44
|
+
* still spawn the bare name and let node:child_process emit ENOENT.
|
|
45
|
+
*
|
|
46
|
+
* Implemented in pure Node (no `where` subprocess — that would face
|
|
47
|
+
* the same spawn problem).
|
|
48
|
+
*/
|
|
49
|
+
function resolveCommand(command, opts = {}) {
|
|
50
|
+
const platform = opts.platform ?? process.platform;
|
|
51
|
+
const env = opts.env ?? process.env;
|
|
52
|
+
const isWin = platform === 'win32';
|
|
53
|
+
// Already absolute or has a separator → trust the caller, just detect suffix.
|
|
54
|
+
if (node_path_1.default.isAbsolute(command) || command.includes('/') || command.includes('\\')) {
|
|
55
|
+
if (!(0, node_fs_1.existsSync)(command))
|
|
56
|
+
return null;
|
|
57
|
+
return { path: command, isShim: isWin && /\.(cmd|bat)$/i.test(command) };
|
|
58
|
+
}
|
|
59
|
+
const pathDirs = (env.PATH ?? env.Path ?? '').split(node_path_1.default.delimiter).filter(Boolean);
|
|
60
|
+
const pathExts = isWin
|
|
61
|
+
? (env.PATHEXT ?? '.CMD;.EXE;.BAT;.COM').split(';').filter(Boolean)
|
|
62
|
+
: [''];
|
|
63
|
+
for (const dir of pathDirs) {
|
|
64
|
+
for (const ext of pathExts) {
|
|
65
|
+
const candidate = node_path_1.default.join(dir, command + ext);
|
|
66
|
+
try {
|
|
67
|
+
if ((0, node_fs_1.existsSync)(candidate) && (0, node_fs_1.statSync)(candidate).isFile()) {
|
|
68
|
+
return { path: candidate, isShim: isWin && /\.(cmd|bat)$/i.test(candidate) };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch { /* permissions / ENOENT — keep walking */ }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Escape an argv element for cmd.exe /c invocation. Wraps in double
|
|
78
|
+
* quotes if the value contains whitespace or any cmd metachar (& | <
|
|
79
|
+
* > ( ) @ ^ "), doubling any embedded quotes. Used together with
|
|
80
|
+
* `windowsVerbatimArguments: true` so Node passes our quoted string
|
|
81
|
+
* straight through to cmd.exe without its own (broken-for-.cmd)
|
|
82
|
+
* quoting heuristics.
|
|
83
|
+
*
|
|
84
|
+
* Reference: cross-spawn / npm-cli use the same pattern; Node 20+
|
|
85
|
+
* refuses to do this for us when spawning .cmd files because the
|
|
86
|
+
* heuristics were the source of CVE-2024-27980.
|
|
87
|
+
*/
|
|
88
|
+
function escapeCmdArg(s) {
|
|
89
|
+
if (s.length === 0)
|
|
90
|
+
return '""';
|
|
91
|
+
// Conservative: any whitespace OR cmd metachar triggers quoting.
|
|
92
|
+
if (!/[\s&|<>()@^"]/.test(s))
|
|
93
|
+
return s;
|
|
94
|
+
// Double internal quotes (cmd.exe convention) and wrap.
|
|
95
|
+
return '"' + s.replace(/"/g, '""') + '"';
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Cross-platform spawn. See file header for the why.
|
|
99
|
+
*
|
|
100
|
+
* - Unix → spawn(cmd, args, { shell:false, ...opts })
|
|
101
|
+
* - Win + .cmd/.bat → spawn('cmd.exe', ['/d','/s','/c', quoted], {
|
|
102
|
+
* shell:false,
|
|
103
|
+
* windowsVerbatimArguments: true, ...opts })
|
|
104
|
+
* - Win + .exe / abs → spawn(cmd, args, { shell:false, ...opts })
|
|
105
|
+
* - Win + bare name → resolveCommand() picks; bucket by suffix.
|
|
106
|
+
*
|
|
107
|
+
* Never throws synchronously for "not found" — emits 'error' on the
|
|
108
|
+
* returned ChildProcess like plain spawn() does. May throw synchronously
|
|
109
|
+
* for the same reasons spawn() itself does (e.g. invalid argv types).
|
|
110
|
+
*/
|
|
111
|
+
function spawnCommand(command, args, opts = {}) {
|
|
112
|
+
const spawn = opts.spawnImpl ?? node_child_process_1.spawn;
|
|
113
|
+
const platform = opts.platform ?? process.platform;
|
|
114
|
+
const isWin = platform === 'win32';
|
|
115
|
+
const baseOpts = {
|
|
116
|
+
stdio: opts.stdio ?? ['pipe', 'pipe', 'pipe'],
|
|
117
|
+
env: opts.env,
|
|
118
|
+
cwd: opts.cwd,
|
|
119
|
+
shell: false,
|
|
120
|
+
};
|
|
121
|
+
if (!isWin) {
|
|
122
|
+
const child = spawn(command, args, baseOpts);
|
|
123
|
+
return { child, resolvedCmd: command, resolvedArgs: args, viaCmdExe: false };
|
|
124
|
+
}
|
|
125
|
+
// Windows: detect shim suffix.
|
|
126
|
+
const resolved = resolveCommand(command, { platform, env: opts.env });
|
|
127
|
+
const isShim = resolved
|
|
128
|
+
? resolved.isShim
|
|
129
|
+
: /\.(cmd|bat)$/i.test(command); // unresolved but caller passed .cmd explicitly
|
|
130
|
+
if (!isShim) {
|
|
131
|
+
const child = spawn(command, args, baseOpts);
|
|
132
|
+
return { child, resolvedCmd: command, resolvedArgs: args, viaCmdExe: false };
|
|
133
|
+
}
|
|
134
|
+
// Wrap through cmd.exe /d /s /c. Pass resolved path if we have it so
|
|
135
|
+
// we don't re-walk PATH; otherwise let cmd.exe resolve the bare name.
|
|
136
|
+
//
|
|
137
|
+
// cmd.exe /s rule: it strips a single pair of outer quotes from the
|
|
138
|
+
// command line and parses the remainder. We therefore wrap the entire
|
|
139
|
+
// escaped argv sequence in an OUTER quote pair on top of each
|
|
140
|
+
// individual arg's escapeCmdArg quoting. Otherwise a command path
|
|
141
|
+
// containing whitespace (e.g. "C:\Program Files\nodejs\npm.CMD")
|
|
142
|
+
// gets its inner quotes stripped, breaking on the first space.
|
|
143
|
+
const target = resolved?.path ?? command;
|
|
144
|
+
const line = '"' + [target, ...args].map(escapeCmdArg).join(' ') + '"';
|
|
145
|
+
const cmdArgs = ['/d', '/s', '/c', line];
|
|
146
|
+
const child = spawn('cmd.exe', cmdArgs, {
|
|
147
|
+
...baseOpts,
|
|
148
|
+
windowsVerbatimArguments: true,
|
|
149
|
+
});
|
|
150
|
+
return { child, resolvedCmd: 'cmd.exe', resolvedArgs: cmdArgs, viaCmdExe: true };
|
|
151
|
+
}
|
package/package.json
CHANGED
package/themes/default.yaml
CHANGED
|
@@ -1,52 +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
|
|
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
|
package/themes/dracula.yaml
CHANGED
|
@@ -1,32 +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"
|
|
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"
|
package/themes/light.yaml
CHANGED
|
@@ -1,32 +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"
|
|
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"
|
package/themes/monochrome.yaml
CHANGED
|
@@ -1,31 +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"
|
|
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"
|
package/themes/tokyo-night.yaml
CHANGED
|
@@ -1,32 +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"
|
|
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"
|