@visorcraft/idlehands 0.9.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.
Files changed (197) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/dist/agent.js +2604 -0
  4. package/dist/agent.js.map +1 -0
  5. package/dist/anton/controller.js +341 -0
  6. package/dist/anton/controller.js.map +1 -0
  7. package/dist/anton/lock.js +110 -0
  8. package/dist/anton/lock.js.map +1 -0
  9. package/dist/anton/parser.js +303 -0
  10. package/dist/anton/parser.js.map +1 -0
  11. package/dist/anton/prompt.js +203 -0
  12. package/dist/anton/prompt.js.map +1 -0
  13. package/dist/anton/reporter.js +119 -0
  14. package/dist/anton/reporter.js.map +1 -0
  15. package/dist/anton/session.js +51 -0
  16. package/dist/anton/session.js.map +1 -0
  17. package/dist/anton/types.js +7 -0
  18. package/dist/anton/types.js.map +1 -0
  19. package/dist/anton/verifier.js +263 -0
  20. package/dist/anton/verifier.js.map +1 -0
  21. package/dist/bench/compare.js +239 -0
  22. package/dist/bench/compare.js.map +1 -0
  23. package/dist/bench/debug_hooks.js +17 -0
  24. package/dist/bench/debug_hooks.js.map +1 -0
  25. package/dist/bench/json_extract.js +22 -0
  26. package/dist/bench/json_extract.js.map +1 -0
  27. package/dist/bench/openclaw.js +86 -0
  28. package/dist/bench/openclaw.js.map +1 -0
  29. package/dist/bench/report.js +116 -0
  30. package/dist/bench/report.js.map +1 -0
  31. package/dist/bench/runner.js +312 -0
  32. package/dist/bench/runner.js.map +1 -0
  33. package/dist/bench/types.js +2 -0
  34. package/dist/bench/types.js.map +1 -0
  35. package/dist/bot/commands.js +444 -0
  36. package/dist/bot/commands.js.map +1 -0
  37. package/dist/bot/confirm-discord.js +133 -0
  38. package/dist/bot/confirm-discord.js.map +1 -0
  39. package/dist/bot/confirm-telegram.js +290 -0
  40. package/dist/bot/confirm-telegram.js.map +1 -0
  41. package/dist/bot/discord.js +826 -0
  42. package/dist/bot/discord.js.map +1 -0
  43. package/dist/bot/format.js +210 -0
  44. package/dist/bot/format.js.map +1 -0
  45. package/dist/bot/session-manager.js +270 -0
  46. package/dist/bot/session-manager.js.map +1 -0
  47. package/dist/bot/telegram.js +678 -0
  48. package/dist/bot/telegram.js.map +1 -0
  49. package/dist/cli/agent-turn.js +45 -0
  50. package/dist/cli/agent-turn.js.map +1 -0
  51. package/dist/cli/args.js +236 -0
  52. package/dist/cli/args.js.map +1 -0
  53. package/dist/cli/bot.js +252 -0
  54. package/dist/cli/bot.js.map +1 -0
  55. package/dist/cli/build-repl-context.js +365 -0
  56. package/dist/cli/build-repl-context.js.map +1 -0
  57. package/dist/cli/command-registry.js +20 -0
  58. package/dist/cli/command-registry.js.map +1 -0
  59. package/dist/cli/commands/anton.js +271 -0
  60. package/dist/cli/commands/anton.js.map +1 -0
  61. package/dist/cli/commands/editing.js +328 -0
  62. package/dist/cli/commands/editing.js.map +1 -0
  63. package/dist/cli/commands/model.js +274 -0
  64. package/dist/cli/commands/model.js.map +1 -0
  65. package/dist/cli/commands/project.js +255 -0
  66. package/dist/cli/commands/project.js.map +1 -0
  67. package/dist/cli/commands/runtime.js +63 -0
  68. package/dist/cli/commands/runtime.js.map +1 -0
  69. package/dist/cli/commands/session.js +281 -0
  70. package/dist/cli/commands/session.js.map +1 -0
  71. package/dist/cli/commands/tools.js +126 -0
  72. package/dist/cli/commands/tools.js.map +1 -0
  73. package/dist/cli/commands/trifecta.js +221 -0
  74. package/dist/cli/commands/trifecta.js.map +1 -0
  75. package/dist/cli/commands/tui.js +17 -0
  76. package/dist/cli/commands/tui.js.map +1 -0
  77. package/dist/cli/init.js +222 -0
  78. package/dist/cli/init.js.map +1 -0
  79. package/dist/cli/input.js +360 -0
  80. package/dist/cli/input.js.map +1 -0
  81. package/dist/cli/oneshot.js +254 -0
  82. package/dist/cli/oneshot.js.map +1 -0
  83. package/dist/cli/repl-context.js +2 -0
  84. package/dist/cli/repl-context.js.map +1 -0
  85. package/dist/cli/runtime-cmds.js +811 -0
  86. package/dist/cli/runtime-cmds.js.map +1 -0
  87. package/dist/cli/service.js +145 -0
  88. package/dist/cli/service.js.map +1 -0
  89. package/dist/cli/session-state.js +130 -0
  90. package/dist/cli/session-state.js.map +1 -0
  91. package/dist/cli/setup.js +815 -0
  92. package/dist/cli/setup.js.map +1 -0
  93. package/dist/cli/shell.js +79 -0
  94. package/dist/cli/shell.js.map +1 -0
  95. package/dist/cli/status.js +392 -0
  96. package/dist/cli/status.js.map +1 -0
  97. package/dist/cli/watch.js +33 -0
  98. package/dist/cli/watch.js.map +1 -0
  99. package/dist/client.js +676 -0
  100. package/dist/client.js.map +1 -0
  101. package/dist/commands.js +194 -0
  102. package/dist/commands.js.map +1 -0
  103. package/dist/config.js +507 -0
  104. package/dist/config.js.map +1 -0
  105. package/dist/confirm/auto.js +13 -0
  106. package/dist/confirm/auto.js.map +1 -0
  107. package/dist/confirm/headless.js +41 -0
  108. package/dist/confirm/headless.js.map +1 -0
  109. package/dist/confirm/terminal.js +90 -0
  110. package/dist/confirm/terminal.js.map +1 -0
  111. package/dist/context.js +49 -0
  112. package/dist/context.js.map +1 -0
  113. package/dist/git.js +136 -0
  114. package/dist/git.js.map +1 -0
  115. package/dist/harnesses.js +171 -0
  116. package/dist/harnesses.js.map +1 -0
  117. package/dist/history.js +139 -0
  118. package/dist/history.js.map +1 -0
  119. package/dist/index.js +700 -0
  120. package/dist/index.js.map +1 -0
  121. package/dist/indexer.js +374 -0
  122. package/dist/indexer.js.map +1 -0
  123. package/dist/jsonrpc.js +76 -0
  124. package/dist/jsonrpc.js.map +1 -0
  125. package/dist/lens.js +525 -0
  126. package/dist/lens.js.map +1 -0
  127. package/dist/lsp.js +605 -0
  128. package/dist/lsp.js.map +1 -0
  129. package/dist/markdown.js +275 -0
  130. package/dist/markdown.js.map +1 -0
  131. package/dist/mcp.js +554 -0
  132. package/dist/mcp.js.map +1 -0
  133. package/dist/recovery.js +178 -0
  134. package/dist/recovery.js.map +1 -0
  135. package/dist/replay.js +132 -0
  136. package/dist/replay.js.map +1 -0
  137. package/dist/replay_cli.js +24 -0
  138. package/dist/replay_cli.js.map +1 -0
  139. package/dist/runtime/executor.js +418 -0
  140. package/dist/runtime/executor.js.map +1 -0
  141. package/dist/runtime/planner.js +197 -0
  142. package/dist/runtime/planner.js.map +1 -0
  143. package/dist/runtime/store.js +289 -0
  144. package/dist/runtime/store.js.map +1 -0
  145. package/dist/runtime/types.js +2 -0
  146. package/dist/runtime/types.js.map +1 -0
  147. package/dist/safety.js +446 -0
  148. package/dist/safety.js.map +1 -0
  149. package/dist/spinner.js +224 -0
  150. package/dist/spinner.js.map +1 -0
  151. package/dist/sys/context.js +124 -0
  152. package/dist/sys/context.js.map +1 -0
  153. package/dist/sys/snapshot.sh +97 -0
  154. package/dist/term.js +61 -0
  155. package/dist/term.js.map +1 -0
  156. package/dist/themes.js +135 -0
  157. package/dist/themes.js.map +1 -0
  158. package/dist/tools.js +1114 -0
  159. package/dist/tools.js.map +1 -0
  160. package/dist/tui/branch-picker.js +65 -0
  161. package/dist/tui/branch-picker.js.map +1 -0
  162. package/dist/tui/command-handler.js +108 -0
  163. package/dist/tui/command-handler.js.map +1 -0
  164. package/dist/tui/confirm.js +90 -0
  165. package/dist/tui/confirm.js.map +1 -0
  166. package/dist/tui/controller.js +463 -0
  167. package/dist/tui/controller.js.map +1 -0
  168. package/dist/tui/event-bridge.js +44 -0
  169. package/dist/tui/event-bridge.js.map +1 -0
  170. package/dist/tui/events.js +2 -0
  171. package/dist/tui/events.js.map +1 -0
  172. package/dist/tui/keymap.js +144 -0
  173. package/dist/tui/keymap.js.map +1 -0
  174. package/dist/tui/layout.js +11 -0
  175. package/dist/tui/layout.js.map +1 -0
  176. package/dist/tui/render.js +186 -0
  177. package/dist/tui/render.js.map +1 -0
  178. package/dist/tui/screen.js +48 -0
  179. package/dist/tui/screen.js.map +1 -0
  180. package/dist/tui/state.js +167 -0
  181. package/dist/tui/state.js.map +1 -0
  182. package/dist/tui/theme.js +70 -0
  183. package/dist/tui/theme.js.map +1 -0
  184. package/dist/tui/types.js +2 -0
  185. package/dist/tui/types.js.map +1 -0
  186. package/dist/types.js +2 -0
  187. package/dist/types.js.map +1 -0
  188. package/dist/upgrade.js +412 -0
  189. package/dist/upgrade.js.map +1 -0
  190. package/dist/utils.js +87 -0
  191. package/dist/utils.js.map +1 -0
  192. package/dist/vault.js +520 -0
  193. package/dist/vault.js.map +1 -0
  194. package/dist/vim.js +160 -0
  195. package/dist/vim.js.map +1 -0
  196. package/package.json +67 -0
  197. package/src/sys/snapshot.sh +97 -0
@@ -0,0 +1,70 @@
1
+ /**
2
+ * TUI theme bridge — resolves the active theme into ANSI escape strings
3
+ * for use by the raw-ANSI renderer (render.ts).
4
+ *
5
+ * The main theme system (src/themes.ts) uses picocolors functions.
6
+ * TUI rendering uses raw escape codes for deterministic frame output.
7
+ * This module bridges the two: it resolves the theme name, then maps
8
+ * each slot to the corresponding ANSI SGR sequence.
9
+ */
10
+ /** ANSI SGR codes for each color slot. */
11
+ const ANSI = {
12
+ dim: '\x1b[2m',
13
+ bold: '\x1b[1m',
14
+ italic: '\x1b[3m',
15
+ underline: '\x1b[4m',
16
+ inverse: '\x1b[7m',
17
+ red: '\x1b[31m',
18
+ yellow: '\x1b[33m',
19
+ green: '\x1b[32m',
20
+ cyan: '\x1b[36m',
21
+ magenta: '\x1b[35m',
22
+ blue: '\x1b[34m',
23
+ white: '\x1b[37m',
24
+ gray: '\x1b[90m',
25
+ black: '\x1b[30m',
26
+ };
27
+ const PALETTES = {
28
+ default: {},
29
+ dark: {
30
+ cyan: 'bold+cyan',
31
+ magenta: 'bold+magenta',
32
+ blue: 'bold+blue',
33
+ },
34
+ light: {
35
+ dim: 'gray',
36
+ cyan: 'blue',
37
+ blue: 'cyan',
38
+ },
39
+ minimal: {
40
+ yellow: 'dim',
41
+ green: 'dim',
42
+ cyan: 'dim',
43
+ magenta: 'dim',
44
+ blue: 'dim',
45
+ },
46
+ hacker: {
47
+ bold: 'bold+green',
48
+ yellow: 'green',
49
+ cyan: 'green',
50
+ magenta: 'green',
51
+ blue: 'green',
52
+ },
53
+ };
54
+ const DEFAULTS = {
55
+ dim: 'dim', bold: 'bold', red: 'red', yellow: 'yellow',
56
+ green: 'green', cyan: 'cyan', magenta: 'magenta', blue: 'blue',
57
+ };
58
+ function resolveAnsi(spec) {
59
+ return spec.split('+').map(p => ANSI[p.trim()] ?? '').join('');
60
+ }
61
+ /** Resolve a theme name to concrete ANSI escape strings. */
62
+ export function resolveTuiTheme(name) {
63
+ const palette = PALETTES[name || 'default'] ?? PALETTES.default;
64
+ const colors = { reset: '\x1b[0m' };
65
+ for (const slot of Object.keys(DEFAULTS)) {
66
+ colors[slot] = resolveAnsi(palette[slot] ?? DEFAULTS[slot]);
67
+ }
68
+ return colors;
69
+ }
70
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/tui/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,0CAA0C;AAC1C,MAAM,IAAI,GAA2B;IACnC,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,SAAS;IAClB,GAAG,EAAE,UAAU;IACf,MAAM,EAAE,UAAU;IAClB,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,UAAU;IACnB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;CAClB,CAAC;AAQF,MAAM,QAAQ,GAA4B;IACxC,OAAO,EAAE,EAAE;IACX,IAAI,EAAE;QACJ,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,cAAc;QACvB,IAAI,EAAE,WAAW;KAClB;IACD,KAAK,EAAE;QACL,GAAG,EAAE,MAAM;QACX,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,MAAM;KACb;IACD,OAAO,EAAE;QACP,MAAM,EAAE,KAAK;QACb,KAAK,EAAE,KAAK;QACZ,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,KAAK;KACZ;IACD,MAAM,EAAE;QACN,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,OAAO;QACf,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,OAAO;KACd;CACF,CAAC;AAEF,MAAM,QAAQ,GAAmD;IAC/D,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ;IACtD,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM;CAC/D,CAAC;AAEF,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,eAAe,CAAC,IAAa;IAC3C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,OAAQ,CAAC;IACjE,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,SAAS,EAAe,CAAC;IACjD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAuC,EAAE,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tui/types.ts"],"names":[],"mappings":""}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,412 @@
1
+ /**
2
+ * Self-upgrade mechanism for Idle Hands.
3
+ *
4
+ * Supports two install sources:
5
+ * - "github" → GitHub Releases (visorcraft/idlehands)
6
+ * - "npm" → npmjs.org registry
7
+ *
8
+ * Install source is auto-detected on first run and stored in config.
9
+ * `--upgrade` pulls the latest from the detected source (fallback to the other).
10
+ * Daily auto-check: on REPL startup, check once per 24h if a newer version exists.
11
+ */
12
+ import { execSync } from 'node:child_process';
13
+ import { readFileSync } from 'node:fs';
14
+ import fs from 'node:fs/promises';
15
+ import path from 'node:path';
16
+ import os from 'node:os';
17
+ import { fetchWithTimeout as fetchWithTimeoutStrict, stateDir } from './utils.js';
18
+ const GITHUB_OWNER = 'visorcraft';
19
+ const GITHUB_REPO = 'idlehands';
20
+ const NPM_PACKAGE = 'idlehands';
21
+ const STATE_DIR = stateDir();
22
+ const UPDATE_CHECK_FILE = path.join(STATE_DIR, 'last-update-check.json');
23
+ const ROLLBACK_DIR = path.join(STATE_DIR, 'rollback');
24
+ /** Resolve a GitHub token from config, env, or gh CLI config. */
25
+ function resolveGitHubToken() {
26
+ // 1. Environment variable
27
+ const envToken = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
28
+ if (envToken)
29
+ return envToken;
30
+ // 2. gh CLI config (~/.config/gh/hosts.yml)
31
+ try {
32
+ const ghConfigPath = path.join(os.homedir(), '.config', 'gh', 'hosts.yml');
33
+ const raw = readFileSync(ghConfigPath, 'utf8');
34
+ // Simple YAML parse — look for oauth_token under github.com
35
+ // Format: github.com:\n users:\n <user>:\n oauth_token: <token>
36
+ // Or: github.com:\n oauth_token: <token>
37
+ const lines = raw.split('\n');
38
+ let inGithub = false;
39
+ for (const line of lines) {
40
+ if (line.match(/^github\.com:/)) {
41
+ inGithub = true;
42
+ continue;
43
+ }
44
+ if (inGithub && line.match(/^\S/))
45
+ break; // next top-level key
46
+ if (inGithub) {
47
+ const m = line.match(/oauth_token:\s*(.+)/);
48
+ if (m)
49
+ return m[1].trim();
50
+ }
51
+ }
52
+ }
53
+ catch { }
54
+ return null;
55
+ }
56
+ async function fetchWithTimeout(url, init, timeoutMs) {
57
+ try {
58
+ return await fetchWithTimeoutStrict(url, init, timeoutMs);
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
64
+ /** Compare two semver strings. Returns -1, 0, or 1. */
65
+ function compareSemver(a, b) {
66
+ const pa = a.replace(/^v/, '').split('.').map(Number);
67
+ const pb = b.replace(/^v/, '').split('.').map(Number);
68
+ for (let i = 0; i < 3; i++) {
69
+ const va = pa[i] ?? 0;
70
+ const vb = pb[i] ?? 0;
71
+ if (va < vb)
72
+ return -1;
73
+ if (va > vb)
74
+ return 1;
75
+ }
76
+ return 0;
77
+ }
78
+ /** Detect how idlehands was installed by examining the install path. */
79
+ export function detectInstallSource() {
80
+ try {
81
+ // If installed via npm, the resolved path will be inside a node_modules or npm global dir
82
+ const resolved = execSync('which idlehands 2>/dev/null || echo ""', { encoding: 'utf8' }).trim();
83
+ if (!resolved)
84
+ return 'unknown';
85
+ // npm global installs go through lib/node_modules
86
+ const npmGlobal = execSync('npm root -g 2>/dev/null || echo ""', { encoding: 'utf8' }).trim();
87
+ if (npmGlobal && resolved.includes('node_modules')) {
88
+ return 'npm';
89
+ }
90
+ // If the binary exists but isn't in node_modules, check if npm knows about it
91
+ try {
92
+ const list = execSync('npm ls -g idlehands --json 2>/dev/null', { encoding: 'utf8' });
93
+ const parsed = JSON.parse(list);
94
+ if (parsed?.dependencies?.idlehands)
95
+ return 'npm';
96
+ }
97
+ catch { }
98
+ return 'github';
99
+ }
100
+ catch {
101
+ return 'unknown';
102
+ }
103
+ }
104
+ /** Fetch the latest version from GitHub Releases API. */
105
+ async function getLatestGitHub(timeoutMs = 3000) {
106
+ try {
107
+ const url = `https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPO}/releases/latest`;
108
+ const headers = { 'Accept': 'application/vnd.github+json', 'User-Agent': 'idlehands-cli' };
109
+ const token = resolveGitHubToken();
110
+ if (token)
111
+ headers['Authorization'] = `token ${token}`;
112
+ const res = await fetchWithTimeout(url, { headers }, timeoutMs);
113
+ if (!res)
114
+ return null;
115
+ if (res.status === 404) {
116
+ console.log('[github] No releases published yet.');
117
+ return null;
118
+ }
119
+ if (!res.ok)
120
+ return null;
121
+ const data = await res.json();
122
+ return data?.tag_name?.replace(/^v/, '') ?? null;
123
+ }
124
+ catch {
125
+ return null;
126
+ }
127
+ }
128
+ /** Fetch the latest version from the npm registry. */
129
+ async function getLatestNpm(timeoutMs = 3000) {
130
+ try {
131
+ const res = await fetchWithTimeout(`https://registry.npmjs.org/${NPM_PACKAGE}/latest`, {
132
+ headers: { 'Accept': 'application/json', 'User-Agent': 'idlehands-cli' }
133
+ }, timeoutMs);
134
+ if (!res)
135
+ return null;
136
+ if (res.status === 404) {
137
+ console.log('[npm] Package not published yet.');
138
+ return null;
139
+ }
140
+ if (!res.ok)
141
+ return null;
142
+ const data = await res.json();
143
+ return data?.version ?? null;
144
+ }
145
+ catch {
146
+ return null;
147
+ }
148
+ }
149
+ /** Get the latest version, trying the preferred source first, then fallback. */
150
+ async function getLatestVersion(source, opts = {}) {
151
+ if (opts.offline)
152
+ return null;
153
+ const timeoutMs = opts.timeoutMs ?? 3000;
154
+ const tryGithub = async () => {
155
+ const v = await getLatestGitHub(timeoutMs);
156
+ return v ? { version: v, source: 'github' } : null;
157
+ };
158
+ const tryNpm = async () => {
159
+ const v = await getLatestNpm(timeoutMs);
160
+ return v ? { version: v, source: 'npm' } : null;
161
+ };
162
+ if (source === 'npm') {
163
+ return (await tryNpm()) ?? (await tryGithub());
164
+ }
165
+ // Default: github first
166
+ return (await tryGithub()) ?? (await tryNpm());
167
+ }
168
+ /** Check if an update is available. */
169
+ async function checkForUpdate(currentVersion, source, opts = {}) {
170
+ const result = await getLatestVersion(source, opts);
171
+ if (!result)
172
+ return null;
173
+ return {
174
+ current: currentVersion,
175
+ latest: result.version,
176
+ source: result.source,
177
+ updateAvailable: compareSemver(currentVersion, result.version) < 0
178
+ };
179
+ }
180
+ /** Daily update check — returns update info if check is due and update available. */
181
+ export async function dailyUpdateCheck(currentVersion, source, opts = {}) {
182
+ if (opts.offline)
183
+ return null;
184
+ try {
185
+ await fs.mkdir(STATE_DIR, { recursive: true });
186
+ // Check if we already checked today
187
+ try {
188
+ const raw = await fs.readFile(UPDATE_CHECK_FILE, 'utf8');
189
+ const data = JSON.parse(raw);
190
+ const lastCheck = new Date(data.timestamp).getTime();
191
+ const now = Date.now();
192
+ if (now - lastCheck < 24 * 60 * 60 * 1000) {
193
+ // Already checked within 24h — return cached result if update was available
194
+ if (data.updateAvailable && data.latest && compareSemver(currentVersion, data.latest) < 0) {
195
+ return {
196
+ current: currentVersion,
197
+ latest: data.latest,
198
+ source: data.source ?? source,
199
+ updateAvailable: true
200
+ };
201
+ }
202
+ return null;
203
+ }
204
+ }
205
+ catch { } // No file or parse error — proceed with check
206
+ const info = await checkForUpdate(currentVersion, source, opts);
207
+ // Cache the result
208
+ await fs.writeFile(UPDATE_CHECK_FILE, JSON.stringify({
209
+ timestamp: new Date().toISOString(),
210
+ latest: info?.latest ?? currentVersion,
211
+ source: info?.source ?? source,
212
+ updateAvailable: info?.updateAvailable ?? false
213
+ }, null, 2), 'utf8');
214
+ return info?.updateAvailable ? info : null;
215
+ }
216
+ catch {
217
+ return null; // Never crash on update check failure
218
+ }
219
+ }
220
+ /** Get the current npm global root for idlehands. */
221
+ function getNpmGlobalDir() {
222
+ try {
223
+ const root = execSync('npm root -g 2>/dev/null', { encoding: 'utf8' }).trim();
224
+ if (root)
225
+ return path.join(root, NPM_PACKAGE);
226
+ return null;
227
+ }
228
+ catch {
229
+ return null;
230
+ }
231
+ }
232
+ /**
233
+ * Backup the current installation before upgrade.
234
+ * Only 1 rollback version is retained.
235
+ */
236
+ async function backupForRollback(currentVersion, source) {
237
+ try {
238
+ const installDir = getNpmGlobalDir();
239
+ if (!installDir) {
240
+ console.warn('[rollback] cannot determine install directory; skipping backup');
241
+ return null;
242
+ }
243
+ // Check if install dir exists
244
+ try {
245
+ await fs.access(installDir);
246
+ }
247
+ catch {
248
+ console.warn('[rollback] install directory not found; skipping backup');
249
+ return null;
250
+ }
251
+ // Ensure rollback dir exists; wipe old backup (max 1 retained)
252
+ await fs.rm(ROLLBACK_DIR, { recursive: true, force: true });
253
+ await fs.mkdir(ROLLBACK_DIR, { recursive: true });
254
+ // Pack the current install into a tarball
255
+ const tgzName = `${NPM_PACKAGE}-${currentVersion}-rollback.tgz`;
256
+ const tgzPath = path.join(ROLLBACK_DIR, tgzName);
257
+ // Use npm pack from the install directory
258
+ execSync(`npm pack --pack-destination "${ROLLBACK_DIR}" 2>/dev/null`, {
259
+ cwd: installDir,
260
+ encoding: 'utf8',
261
+ timeout: 30_000
262
+ });
263
+ // npm pack outputs the filename; find it
264
+ const files = await fs.readdir(ROLLBACK_DIR);
265
+ const packed = files.find((f) => f.endsWith('.tgz'));
266
+ if (!packed)
267
+ throw new Error('npm pack produced no .tgz file');
268
+ // Rename to our convention
269
+ const packedPath = path.join(ROLLBACK_DIR, packed);
270
+ if (packedPath !== tgzPath) {
271
+ await fs.rename(packedPath, tgzPath);
272
+ }
273
+ // Write metadata
274
+ const info = {
275
+ version: currentVersion,
276
+ source,
277
+ backupPath: tgzPath,
278
+ timestamp: new Date().toISOString()
279
+ };
280
+ await fs.writeFile(path.join(ROLLBACK_DIR, 'rollback.json'), JSON.stringify(info, null, 2), 'utf8');
281
+ console.log(`[rollback] backed up v${currentVersion} to ${tgzPath}`);
282
+ return info;
283
+ }
284
+ catch (e) {
285
+ console.warn(`[rollback] backup failed (non-fatal): ${e?.message ?? String(e)}`);
286
+ return null;
287
+ }
288
+ }
289
+ /** Read rollback metadata, if available. */
290
+ async function getRollbackInfo() {
291
+ try {
292
+ const raw = await fs.readFile(path.join(ROLLBACK_DIR, 'rollback.json'), 'utf8');
293
+ const info = JSON.parse(raw);
294
+ // Verify tarball still exists
295
+ await fs.access(info.backupPath);
296
+ return info;
297
+ }
298
+ catch {
299
+ return null;
300
+ }
301
+ }
302
+ /** Perform rollback: install the backed-up version. */
303
+ export async function performRollback() {
304
+ const info = await getRollbackInfo();
305
+ if (!info) {
306
+ console.error('No rollback backup found. Run --upgrade first to create one.');
307
+ process.exit(1);
308
+ }
309
+ console.log(`Rolling back to v${info.version} (backed up ${info.timestamp})`);
310
+ console.log(`Installing from: ${info.backupPath}`);
311
+ try {
312
+ execSync(`npm install -g "${info.backupPath}"`, { stdio: 'inherit' });
313
+ console.log(`\n✓ Rolled back to v${info.version}`);
314
+ // Clean up rollback dir after successful rollback
315
+ await fs.rm(ROLLBACK_DIR, { recursive: true, force: true }).catch(() => { });
316
+ }
317
+ catch (e) {
318
+ console.error(`\n✗ Rollback failed: ${e?.message ?? String(e)}`);
319
+ console.error(`\nManual rollback: npm install -g "${info.backupPath}"`);
320
+ process.exit(1);
321
+ }
322
+ }
323
+ /** Perform the actual upgrade. */
324
+ export async function performUpgrade(currentVersion, source) {
325
+ console.log(`Current version: ${currentVersion}`);
326
+ console.log(`Install source: ${source}`);
327
+ console.log('Checking for updates...');
328
+ const info = await checkForUpdate(currentVersion, source);
329
+ if (!info) {
330
+ console.log('No releases found. Publish a release on GitHub or npm first.');
331
+ process.exit(1);
332
+ }
333
+ if (!info.updateAvailable) {
334
+ console.log(`Already on the latest version (${currentVersion}).`);
335
+ process.exit(0);
336
+ }
337
+ console.log(`Update available: ${currentVersion} → ${info.latest} (from ${info.source})`);
338
+ // Backup current installation for rollback (best-effort)
339
+ await backupForRollback(currentVersion, source);
340
+ console.log('Upgrading...\n');
341
+ try {
342
+ if (info.source === 'npm') {
343
+ // npm global install
344
+ execSync(`npm install -g ${NPM_PACKAGE}@latest`, { stdio: 'inherit' });
345
+ }
346
+ else {
347
+ // GitHub release — download tarball with auth (private repos), then install locally
348
+ const token = resolveGitHubToken();
349
+ // Find the asset download URL from the release
350
+ const releaseUrl = `https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPO}/releases/tags/v${info.latest}`;
351
+ const headers = { 'Accept': 'application/vnd.github+json', 'User-Agent': 'idlehands-cli' };
352
+ if (token)
353
+ headers['Authorization'] = `token ${token}`;
354
+ const releaseRes = await fetch(releaseUrl, { headers });
355
+ if (!releaseRes.ok)
356
+ throw new Error(`Failed to fetch release v${info.latest}: HTTP ${releaseRes.status}`);
357
+ const releaseData = await releaseRes.json();
358
+ const tgzName = `${NPM_PACKAGE}-${info.latest}.tgz`;
359
+ const asset = (releaseData.assets ?? []).find((a) => a.name === tgzName);
360
+ if (!asset)
361
+ throw new Error(`Release v${info.latest} has no asset named ${tgzName}`);
362
+ console.log(`Downloading: ${tgzName} (${(asset.size / 1024).toFixed(0)} KB)`);
363
+ // Download the asset binary
364
+ const dlHeaders = { 'Accept': 'application/octet-stream', 'User-Agent': 'idlehands-cli' };
365
+ if (token)
366
+ dlHeaders['Authorization'] = `token ${token}`;
367
+ const dlRes = await fetch(asset.url, { headers: dlHeaders });
368
+ if (!dlRes.ok)
369
+ throw new Error(`Failed to download asset: HTTP ${dlRes.status}`);
370
+ const tmpPath = path.join(os.tmpdir(), tgzName);
371
+ const buf = Buffer.from(await dlRes.arrayBuffer());
372
+ await fs.writeFile(tmpPath, buf);
373
+ console.log(`Saved to ${tmpPath}`);
374
+ execSync(`npm install -g ${tmpPath}`, { stdio: 'inherit' });
375
+ // Clean up
376
+ await fs.unlink(tmpPath).catch(() => { });
377
+ }
378
+ console.log(`\n✓ Upgraded to ${info.latest}`);
379
+ // Clear the update check cache so we don't nag
380
+ try {
381
+ await fs.unlink(UPDATE_CHECK_FILE);
382
+ }
383
+ catch { }
384
+ }
385
+ catch (e) {
386
+ console.error(`\n✗ Upgrade failed: ${e?.message ?? String(e)}`);
387
+ // Auto-rollback on failure
388
+ const rollbackInfo = await getRollbackInfo();
389
+ if (rollbackInfo) {
390
+ console.error('\nAttempting auto-rollback...');
391
+ try {
392
+ execSync(`npm install -g "${rollbackInfo.backupPath}"`, { stdio: 'inherit' });
393
+ console.error(`✓ Auto-rolled back to v${rollbackInfo.version}`);
394
+ }
395
+ catch (re) {
396
+ console.error(`✗ Auto-rollback also failed: ${re?.message ?? String(re)}`);
397
+ console.error(`\nManual rollback: npm install -g "${rollbackInfo.backupPath}"`);
398
+ }
399
+ }
400
+ else {
401
+ console.error('\nManual upgrade:');
402
+ if (info.source === 'npm') {
403
+ console.error(` npm install -g ${NPM_PACKAGE}@latest`);
404
+ }
405
+ else {
406
+ console.error(` npm install -g https://github.com/${GITHUB_OWNER}/${GITHUB_REPO}/releases/download/v${info.latest}/${NPM_PACKAGE}-${info.latest}.tgz`);
407
+ }
408
+ }
409
+ process.exit(1);
410
+ }
411
+ }
412
+ //# sourceMappingURL=upgrade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../src/upgrade.ts"],"names":[],"mappings":"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"}
package/dist/utils.js ADDED
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Shared utility functions.
3
+ *
4
+ * Avoids duplicate implementations scattered across modules.
5
+ */
6
+ import { readFileSync } from 'node:fs';
7
+ import { spawnSync } from 'node:child_process';
8
+ import path from 'node:path';
9
+ import os from 'node:os';
10
+ /** Package version read once at startup. Falls back to '0.0.0'. */
11
+ export const PKG_VERSION = (() => {
12
+ try {
13
+ return JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
14
+ }
15
+ catch {
16
+ return '0.0.0';
17
+ }
18
+ })();
19
+ /** Resolved absolute path to bash — avoids ENOENT under restricted environments. */
20
+ export const BASH_PATH = (() => {
21
+ try {
22
+ const r = spawnSync('which', ['bash'], { encoding: 'utf8', timeout: 1000 });
23
+ const p = r.stdout?.trim();
24
+ if (p && p.startsWith('/'))
25
+ return p;
26
+ }
27
+ catch { /* fallback */ }
28
+ return '/usr/bin/bash';
29
+ })();
30
+ /**
31
+ * Escape special regex metacharacters in a string so it can be used as a
32
+ * literal match inside a `new RegExp(...)` expression.
33
+ */
34
+ export function escapeRegex(s) {
35
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
36
+ }
37
+ /**
38
+ * Rough token estimate: ceil(charCount / 4).
39
+ * Good enough for budget math — not a real tokenizer.
40
+ */
41
+ export function estimateTokens(text) {
42
+ return Math.max(1, Math.ceil(text.length / 4));
43
+ }
44
+ /**
45
+ * XDG-compatible state directory for persistent app data.
46
+ * `~/.local/state/idlehands`
47
+ */
48
+ export function stateDir() {
49
+ const base = process.env.XDG_STATE_HOME || path.join(os.homedir(), '.local', 'state');
50
+ return path.join(base, 'idlehands');
51
+ }
52
+ /**
53
+ * XDG-compatible config directory.
54
+ * `~/.config/idlehands`
55
+ */
56
+ export function configDir() {
57
+ return path.join(os.homedir(), '.config', 'idlehands');
58
+ }
59
+ /**
60
+ * Resolve the project working directory.
61
+ * Uses `config.dir` when explicitly set, otherwise `process.cwd()`.
62
+ */
63
+ export function projectDir(config) {
64
+ return config.dir || process.cwd();
65
+ }
66
+ /**
67
+ * Escape a string for safe single-quoted shell passthrough.
68
+ * Wraps in single quotes, handles embedded single quotes.
69
+ */
70
+ export function shellEscape(s) {
71
+ return "'" + s.replace(/'/g, "'\\''") + "'";
72
+ }
73
+ /**
74
+ * Fetch with timeout using AbortController.
75
+ * Throws on network errors/timeouts (caller decides fallback behavior).
76
+ */
77
+ export async function fetchWithTimeout(url, init = {}, timeoutMs = 3000) {
78
+ const controller = new AbortController();
79
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
80
+ try {
81
+ return await fetch(url, { ...init, signal: controller.signal });
82
+ }
83
+ finally {
84
+ clearTimeout(timer);
85
+ }
86
+ }
87
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}