aiden-runtime 4.6.0 → 4.7.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 +488 -265
- package/dist/cli/v4/aidenCLI.js +26 -1
- package/dist/cli/v4/chatSession.js +13 -0
- package/dist/cli/v4/commands/help.js +2 -0
- package/dist/cli/v4/commands/index.js +6 -1
- package/dist/cli/v4/commands/walkthrough.js +140 -0
- package/dist/cli/v4/daemonAgentBuilder.js +12 -4
- package/dist/cli/v4/onboarding/disclaimer.js +162 -0
- package/dist/cli/v4/onboarding/loading.js +208 -0
- package/dist/cli/v4/onboarding/providerPicker.js +126 -0
- package/dist/cli/v4/onboarding/successScreen.js +68 -0
- package/dist/cli/v4/repl/firstRunHint.js +107 -0
- package/dist/cli/v4/setupWizard.js +201 -31
- package/dist/core/v4/aidenAgent.js +19 -14
- package/dist/core/v4/providers/modelFetch.js +179 -0
- package/dist/core/v4/providers/probe.js +275 -0
- package/dist/core/v4/sandboxFs.js +1 -1
- package/dist/core/v4/subagent/childBuilder.js +12 -4
- package/dist/core/v4/ui/banner.js +133 -0
- package/dist/core/v4/ui/theme.js +164 -0
- package/dist/core/version.js +1 -1
- package/dist/moat/honestyEnforcement.js +143 -241
- package/dist/tools/v4/ui/_uiSmokeTool.js +60 -0
- package/package.json +10 -4
|
@@ -0,0 +1,133 @@
|
|
|
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/ui/banner.ts — ONB1 slice 2 (v4.7 onboarding rework).
|
|
10
|
+
*
|
|
11
|
+
* Auto-width banner block builder used by the disclaimer + success
|
|
12
|
+
* screens. Re-uses the existing ANSI-Shadow AIDEN ASCII art shipped
|
|
13
|
+
* in cli/v4/display.ts (constant `AIDEN_BANNER`) but composes it
|
|
14
|
+
* inside a centred panel with tagline, version, and credit lines —
|
|
15
|
+
* with no dependency on the skin engine.
|
|
16
|
+
*
|
|
17
|
+
* Layout @ ≥80 cols:
|
|
18
|
+
*
|
|
19
|
+
* ╔══════════════════════════════════════════════════════════════╗
|
|
20
|
+
* ║ ║
|
|
21
|
+
* ║ ▀▀▀█▀▀ ▀▀█ ▀▀█▀▀ ▄▄▄▄ ▄▄▄ ║
|
|
22
|
+
* ║ █ █▄▄▄█ █ █ █ █ ║
|
|
23
|
+
* ║ ...AIDEN ASCII (block style, brand orange) ║
|
|
24
|
+
* ║ ║
|
|
25
|
+
* ╚══════════════════════════════════════════════════════════════╝
|
|
26
|
+
*
|
|
27
|
+
* Autonomous AI Engine · Local-first · v4.6.0
|
|
28
|
+
*
|
|
29
|
+
* Built solo · By Taracod · White Lotus
|
|
30
|
+
*
|
|
31
|
+
* Narrow (<60 cols): collapses to a single-line title.
|
|
32
|
+
*
|
|
33
|
+
* Pure renderer — returns the composed string. Callers own the write.
|
|
34
|
+
* No stateful spinners / inquirer prompts here.
|
|
35
|
+
*/
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.renderBanner = renderBanner;
|
|
38
|
+
exports.renderTitleLine = renderTitleLine;
|
|
39
|
+
exports.bannerDiagnostic = bannerDiagnostic;
|
|
40
|
+
const theme_1 = require("./theme");
|
|
41
|
+
/**
|
|
42
|
+
* The block-style AIDEN ASCII. Copied from cli/v4/display.ts so this
|
|
43
|
+
* module has zero coupling to the skin-engine display surface. 6 rows,
|
|
44
|
+
* widest row = 36 cells.
|
|
45
|
+
*/
|
|
46
|
+
const AIDEN_ART = String.raw `
|
|
47
|
+
█████╗ ██╗██████╗ ███████╗███╗ ██╗
|
|
48
|
+
██╔══██╗██║██╔══██╗██╔════╝████╗ ██║
|
|
49
|
+
███████║██║██║ ██║█████╗ ██╔██╗ ██║
|
|
50
|
+
██╔══██║██║██║ ██║██╔══╝ ██║╚██╗██║
|
|
51
|
+
██║ ██║██║██████╔╝███████╗██║ ╚████║
|
|
52
|
+
╚═╝ ╚═╝╚═╝╚═════╝ ╚══════╝╚═╝ ╚═══╝
|
|
53
|
+
`.trim().split('\n');
|
|
54
|
+
const ART_WIDTH = 36;
|
|
55
|
+
/** Pad `s` to length `n` with spaces on the right. ANSI-safe-ish — */
|
|
56
|
+
/** assumes the caller has not yet wrapped colour codes around the */
|
|
57
|
+
/** padded segment. */
|
|
58
|
+
function rpad(s, n) {
|
|
59
|
+
const len = s.length;
|
|
60
|
+
if (len >= n)
|
|
61
|
+
return s;
|
|
62
|
+
return s + ' '.repeat(n - len);
|
|
63
|
+
}
|
|
64
|
+
/** Centre `s` within width `w` (no colour codes in `s`). */
|
|
65
|
+
function centre(s, w) {
|
|
66
|
+
if (s.length >= w)
|
|
67
|
+
return s;
|
|
68
|
+
const total = w - s.length;
|
|
69
|
+
const left = Math.floor(total / 2);
|
|
70
|
+
return ' '.repeat(left) + s + ' '.repeat(total - left);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build the framed banner block as a single string with trailing
|
|
74
|
+
* newline. Truecolor → 256 → 16 / mono all handled by `theme.c.*`.
|
|
75
|
+
*/
|
|
76
|
+
function renderBanner(opts) {
|
|
77
|
+
const w = Math.max(40, Math.min(opts.width ?? (0, theme_1.termWidth)(), 80));
|
|
78
|
+
const narrow = w < 60;
|
|
79
|
+
const tagline = opts.tagline ?? 'Autonomous AI Engine';
|
|
80
|
+
const credits = opts.credits ?? 'Built solo · By Taracod · White Lotus';
|
|
81
|
+
const versionLine = `${tagline} · Local-first · v${opts.version}`;
|
|
82
|
+
// Narrow layout: single-line title + tagline + credits.
|
|
83
|
+
if (narrow) {
|
|
84
|
+
const out = [];
|
|
85
|
+
out.push('');
|
|
86
|
+
out.push(centre(theme_1.c.primary('A I D E N'), w));
|
|
87
|
+
out.push('');
|
|
88
|
+
out.push(centre(theme_1.c.muted(versionLine), w));
|
|
89
|
+
out.push(centre(theme_1.c.muted(credits), w));
|
|
90
|
+
out.push('');
|
|
91
|
+
return out.join('\n') + '\n';
|
|
92
|
+
}
|
|
93
|
+
// Wide layout: framed panel with ASCII art inside, taglines below.
|
|
94
|
+
const inner = w - 2;
|
|
95
|
+
const artPad = Math.max(0, Math.floor((inner - ART_WIDTH) / 2));
|
|
96
|
+
const framed = opts.framed !== false;
|
|
97
|
+
const horiz = '═'.repeat(inner);
|
|
98
|
+
const top = framed ? theme_1.c.rule(`╔${horiz}╗`) : '';
|
|
99
|
+
const bottom = framed ? theme_1.c.rule(`╚${horiz}╝`) : '';
|
|
100
|
+
const blank = framed
|
|
101
|
+
? `${theme_1.c.rule('║')}${' '.repeat(inner)}${theme_1.c.rule('║')}`
|
|
102
|
+
: ' '.repeat(w);
|
|
103
|
+
const lines = [];
|
|
104
|
+
lines.push('');
|
|
105
|
+
if (framed)
|
|
106
|
+
lines.push(top);
|
|
107
|
+
lines.push(blank);
|
|
108
|
+
for (const row of AIDEN_ART) {
|
|
109
|
+
const padded = rpad(' '.repeat(artPad) + row, inner);
|
|
110
|
+
const coloured = theme_1.c.primary(padded);
|
|
111
|
+
lines.push(framed ? `${theme_1.c.rule('║')}${coloured}${theme_1.c.rule('║')}` : ` ${coloured}`);
|
|
112
|
+
}
|
|
113
|
+
lines.push(blank);
|
|
114
|
+
if (framed)
|
|
115
|
+
lines.push(bottom);
|
|
116
|
+
lines.push('');
|
|
117
|
+
lines.push(' ' + (0, theme_1.dim)(theme_1.c.muted(versionLine)));
|
|
118
|
+
lines.push('');
|
|
119
|
+
lines.push(' ' + (0, theme_1.dim)(theme_1.c.muted(credits)));
|
|
120
|
+
lines.push('');
|
|
121
|
+
return lines.join('\n') + '\n';
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Single-line title for use inside slash-command hints / tour pages
|
|
125
|
+
* where the full banner would be too tall. Bright primary + version.
|
|
126
|
+
*/
|
|
127
|
+
function renderTitleLine(version) {
|
|
128
|
+
return `${theme_1.c.primary('AIDEN')} ${theme_1.c.muted(`v${version}`)}`;
|
|
129
|
+
}
|
|
130
|
+
/** Diagnostic — exposes detected depth for smoke tests. */
|
|
131
|
+
function bannerDiagnostic() {
|
|
132
|
+
return { width: (0, theme_1.termWidth)(), depth: (0, theme_1.getColorDepth)() };
|
|
133
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
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/ui/theme.ts — ONB1 (v4.7 onboarding rework).
|
|
10
|
+
*
|
|
11
|
+
* Self-contained theme module for the redesigned first-run experience.
|
|
12
|
+
* Lives alongside, NOT instead of, the existing skin engine
|
|
13
|
+
* (cli/v4/skinEngine.ts). The skin engine drives the REPL / boot card
|
|
14
|
+
* / every post-onboarding surface; this theme drives only the
|
|
15
|
+
* onboarding screens (slices 1–10 of dispatch ONB1).
|
|
16
|
+
*
|
|
17
|
+
* Why a separate module:
|
|
18
|
+
* - Onboarding palette is specified to a different muted/text spec
|
|
19
|
+
* than the existing skin (e.g. cool-grey #71717A vs warm-tan
|
|
20
|
+
* #B8A89A). Swapping the skin would re-paint every chat turn the
|
|
21
|
+
* user sees afterwards, surprising the eye on the *second* boot.
|
|
22
|
+
* - Onboarding is a single-shot surface — no per-user customisation,
|
|
23
|
+
* no YAML loader, no `monochrome`/`light` variants needed beyond
|
|
24
|
+
* graceful colour-depth degradation.
|
|
25
|
+
*
|
|
26
|
+
* Truecolor → 256 → 16 detection runs once at module load and is
|
|
27
|
+
* cached. Set `AIDEN_FORCE_COLOR_DEPTH=truecolor|256|16|none` to
|
|
28
|
+
* override (smoke tests rely on this).
|
|
29
|
+
*/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.SEP_LIGHT = exports.SEP_HEAVY = exports.dim = exports.italic = exports.bold = exports.c = exports.PALETTE = void 0;
|
|
32
|
+
exports.getColorDepth = getColorDepth;
|
|
33
|
+
exports.paint = paint;
|
|
34
|
+
exports.separator = separator;
|
|
35
|
+
exports.termWidth = termWidth;
|
|
36
|
+
/**
|
|
37
|
+
* The 8-colour onboarding palette. Hex strings are the source of
|
|
38
|
+
* truth; the emit functions below convert per detected depth.
|
|
39
|
+
*/
|
|
40
|
+
exports.PALETTE = {
|
|
41
|
+
primary: '#FF6B35', // brand orange — Aiden hero
|
|
42
|
+
accent: '#FFB088', // light orange — highlights
|
|
43
|
+
success: '#4ADE80', // green checkmarks
|
|
44
|
+
warning: '#FBBF24', // amber warnings
|
|
45
|
+
error: '#EF4444', // red errors
|
|
46
|
+
text: '#F5F5F5', // bright white — headers/titles
|
|
47
|
+
muted: '#71717A', // dim grey — secondary text/hints
|
|
48
|
+
rule: '#27272A', // dark grey — separators
|
|
49
|
+
};
|
|
50
|
+
/** Parse a `#RRGGBB` hex string into [r,g,b]. */
|
|
51
|
+
function hexToRgb(hex) {
|
|
52
|
+
const m = /^#?([0-9a-fA-F]{6})$/.exec(hex);
|
|
53
|
+
if (!m)
|
|
54
|
+
return [255, 255, 255];
|
|
55
|
+
const n = parseInt(m[1], 16);
|
|
56
|
+
return [(n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Map a 24-bit RGB triple to the closest xterm-256 colour index.
|
|
60
|
+
* Uses the standard 6×6×6 cube + grey-ramp approximation.
|
|
61
|
+
*/
|
|
62
|
+
function rgbTo256(r, g, b) {
|
|
63
|
+
// Grey-ramp fast path: when r==g==b within 8, prefer the 24-step ramp.
|
|
64
|
+
if (Math.abs(r - g) < 8 && Math.abs(g - b) < 8) {
|
|
65
|
+
if (r < 8)
|
|
66
|
+
return 16;
|
|
67
|
+
if (r > 248)
|
|
68
|
+
return 231;
|
|
69
|
+
return Math.round(((r - 8) / 247) * 24) + 232;
|
|
70
|
+
}
|
|
71
|
+
const q = (v) => Math.round(v / 51);
|
|
72
|
+
return 16 + 36 * q(r) + 6 * q(g) + q(b);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Map a 24-bit RGB triple to a low-fidelity 16-colour ANSI code
|
|
76
|
+
* (30–37 / 90–97). Picks the closest of the 16 standard slots.
|
|
77
|
+
*/
|
|
78
|
+
function rgbTo16(r, g, b) {
|
|
79
|
+
const STD = [
|
|
80
|
+
[30, 0, 0, 0], [31, 205, 49, 49], [32, 13, 188, 121], [33, 229, 229, 16],
|
|
81
|
+
[34, 36, 114, 200], [35, 188, 63, 188], [36, 17, 168, 205], [37, 229, 229, 229],
|
|
82
|
+
[90, 102, 102, 102], [91, 241, 76, 76], [92, 35, 209, 139], [93, 245, 245, 67],
|
|
83
|
+
[94, 59, 142, 234], [95, 214, 112, 214], [96, 41, 184, 219], [97, 229, 229, 229],
|
|
84
|
+
];
|
|
85
|
+
let best = STD[0];
|
|
86
|
+
let bestDist = Infinity;
|
|
87
|
+
for (const cand of STD) {
|
|
88
|
+
const [, cr, cg, cb] = cand;
|
|
89
|
+
const d = (r - cr) ** 2 + (g - cg) ** 2 + (b - cb) ** 2;
|
|
90
|
+
if (d < bestDist) {
|
|
91
|
+
bestDist = d;
|
|
92
|
+
best = cand;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return best[0];
|
|
96
|
+
}
|
|
97
|
+
/** Detect the terminal's effective colour depth. Cached at module load. */
|
|
98
|
+
function detectColorDepth() {
|
|
99
|
+
const forced = process.env.AIDEN_FORCE_COLOR_DEPTH?.toLowerCase();
|
|
100
|
+
if (forced === 'truecolor' || forced === '256' || forced === '16' || forced === 'none') {
|
|
101
|
+
return forced;
|
|
102
|
+
}
|
|
103
|
+
if (process.env.NO_COLOR && process.env.NO_COLOR !== '')
|
|
104
|
+
return 'none';
|
|
105
|
+
if (!process.stdout.isTTY)
|
|
106
|
+
return 'none';
|
|
107
|
+
const ct = (process.env.COLORTERM ?? '').toLowerCase();
|
|
108
|
+
if (ct === 'truecolor' || ct === '24bit')
|
|
109
|
+
return 'truecolor';
|
|
110
|
+
const term = (process.env.TERM ?? '').toLowerCase();
|
|
111
|
+
if (term.includes('256'))
|
|
112
|
+
return '256';
|
|
113
|
+
if (term === 'dumb' || term === '')
|
|
114
|
+
return 'none';
|
|
115
|
+
return '16';
|
|
116
|
+
}
|
|
117
|
+
const COLOR_DEPTH = detectColorDepth();
|
|
118
|
+
/** Public: report the depth (smoke tests + diagnostics). */
|
|
119
|
+
function getColorDepth() { return COLOR_DEPTH; }
|
|
120
|
+
/** Wrap `text` in the SGR sequence for `kind`, degrading per depth. */
|
|
121
|
+
function paint(text, kind) {
|
|
122
|
+
if (COLOR_DEPTH === 'none')
|
|
123
|
+
return text;
|
|
124
|
+
const [r, g, b] = hexToRgb(exports.PALETTE[kind]);
|
|
125
|
+
if (COLOR_DEPTH === 'truecolor')
|
|
126
|
+
return `\x1b[38;2;${r};${g};${b}m${text}\x1b[39m`;
|
|
127
|
+
if (COLOR_DEPTH === '256')
|
|
128
|
+
return `\x1b[38;5;${rgbTo256(r, g, b)}m${text}\x1b[39m`;
|
|
129
|
+
return `\x1b[${rgbTo16(r, g, b)}m${text}\x1b[39m`;
|
|
130
|
+
}
|
|
131
|
+
/** Convenience helpers — one per palette key. */
|
|
132
|
+
exports.c = {
|
|
133
|
+
primary: (s) => paint(s, 'primary'),
|
|
134
|
+
accent: (s) => paint(s, 'accent'),
|
|
135
|
+
success: (s) => paint(s, 'success'),
|
|
136
|
+
warning: (s) => paint(s, 'warning'),
|
|
137
|
+
error: (s) => paint(s, 'error'),
|
|
138
|
+
text: (s) => paint(s, 'text'),
|
|
139
|
+
muted: (s) => paint(s, 'muted'),
|
|
140
|
+
rule: (s) => paint(s, 'rule'),
|
|
141
|
+
};
|
|
142
|
+
/** SGR helpers for emphasis. Italic gracefully degrades when unsupported. */
|
|
143
|
+
const bold = (s) => (COLOR_DEPTH === 'none' ? s : `\x1b[1m${s}\x1b[22m`);
|
|
144
|
+
exports.bold = bold;
|
|
145
|
+
const italic = (s) => (COLOR_DEPTH === 'none' ? s : `\x1b[3m${s}\x1b[23m`);
|
|
146
|
+
exports.italic = italic;
|
|
147
|
+
const dim = (s) => (COLOR_DEPTH === 'none' ? s : `\x1b[2m${s}\x1b[22m`);
|
|
148
|
+
exports.dim = dim;
|
|
149
|
+
/**
|
|
150
|
+
* Common ornaments — single source so onboarding screens share rhythm.
|
|
151
|
+
*/
|
|
152
|
+
exports.SEP_HEAVY = '━';
|
|
153
|
+
exports.SEP_LIGHT = '─';
|
|
154
|
+
/** Render a full-width separator in RULE colour, optionally heavy. */
|
|
155
|
+
function separator(width, heavy = true) {
|
|
156
|
+
const w = Math.max(8, Math.min(width, 100));
|
|
157
|
+
const ch = heavy ? exports.SEP_HEAVY : exports.SEP_LIGHT;
|
|
158
|
+
return exports.c.rule(ch.repeat(w));
|
|
159
|
+
}
|
|
160
|
+
/** Effective terminal width clamped to a sane band. */
|
|
161
|
+
function termWidth() {
|
|
162
|
+
const raw = process.stdout.columns ?? 80;
|
|
163
|
+
return Math.max(40, Math.min(raw, 100));
|
|
164
|
+
}
|
package/dist/core/version.js
CHANGED