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.
@@ -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
+ }
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // AUTO-GENERATED by scripts/inject-version.js — do not edit by hand
5
- exports.VERSION = '4.6.0';
5
+ exports.VERSION = '4.7.0';