aiden-runtime 4.6.0 → 4.6.1

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,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.6.1';
@@ -0,0 +1,60 @@
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
+ * tools/v4/ui/_uiSmokeTool.ts — v4.7 Slice 1 smoke harness.
10
+ *
11
+ * Internal tool used ONLY to verify the uiOnly dispatch seam from
12
+ * Slice 1 (ToolHandler.uiOnly + resolveUiOnly + onUiEvent +
13
+ * Display.renderUiEvent). NOT for end-user LLM workflows.
14
+ *
15
+ * Registered behind `AIDEN_UI_SMOKE=1` env flag in
16
+ * `tools/v4/index.ts::registerAllTools`. Will be deleted once
17
+ * Slice 2 lands the real ui_task_update / ui_task_done tools.
18
+ *
19
+ * When invoked, the agent's dispatch loop:
20
+ * - resolves uiOnly=true via the resolveUiOnly closure
21
+ * - fires runOptions.onUiEvent('_ui_smoke', args)
22
+ * - SKIPS execute() entirely
23
+ * - SKIPS turnToolMessages push + toolCallCount increment + verifier
24
+ *
25
+ * The handler's `execute` MUST never be called by the dispatch path
26
+ * when uiOnly is honoured. Throws if reached — that throw is a
27
+ * regression alarm.
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.uiSmokeTool = void 0;
31
+ exports.uiSmokeTool = {
32
+ schema: {
33
+ name: '_ui_smoke',
34
+ description: 'Internal smoke-test tool for the v4.7 uiOnly dispatch path. ' +
35
+ 'Renders a single debug line through the UI event seam. ' +
36
+ 'Does NOT round-trip back to the model. Only available when ' +
37
+ 'AIDEN_UI_SMOKE=1.',
38
+ inputSchema: {
39
+ type: 'object',
40
+ properties: {
41
+ message: {
42
+ type: 'string',
43
+ description: 'Free-text payload echoed in the rendered debug line.',
44
+ },
45
+ },
46
+ required: ['message'],
47
+ },
48
+ },
49
+ category: 'read',
50
+ mutates: false,
51
+ uiOnly: true,
52
+ execute() {
53
+ // Defensive — if `resolveUiOnly` is wired correctly, the
54
+ // dispatch loop short-circuits BEFORE reaching this body. A
55
+ // call here means the resolver returned false/undefined and
56
+ // the seam regressed. Throwing surfaces the regression at
57
+ // smoke time instead of silently behaving like a regular tool.
58
+ throw new Error('_ui_smoke.execute() should never be called — uiOnly dispatch path regressed');
59
+ },
60
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiden-runtime",
3
- "version": "4.6.0",
3
+ "version": "4.6.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },