@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.
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/dist/agent.js +2604 -0
- package/dist/agent.js.map +1 -0
- package/dist/anton/controller.js +341 -0
- package/dist/anton/controller.js.map +1 -0
- package/dist/anton/lock.js +110 -0
- package/dist/anton/lock.js.map +1 -0
- package/dist/anton/parser.js +303 -0
- package/dist/anton/parser.js.map +1 -0
- package/dist/anton/prompt.js +203 -0
- package/dist/anton/prompt.js.map +1 -0
- package/dist/anton/reporter.js +119 -0
- package/dist/anton/reporter.js.map +1 -0
- package/dist/anton/session.js +51 -0
- package/dist/anton/session.js.map +1 -0
- package/dist/anton/types.js +7 -0
- package/dist/anton/types.js.map +1 -0
- package/dist/anton/verifier.js +263 -0
- package/dist/anton/verifier.js.map +1 -0
- package/dist/bench/compare.js +239 -0
- package/dist/bench/compare.js.map +1 -0
- package/dist/bench/debug_hooks.js +17 -0
- package/dist/bench/debug_hooks.js.map +1 -0
- package/dist/bench/json_extract.js +22 -0
- package/dist/bench/json_extract.js.map +1 -0
- package/dist/bench/openclaw.js +86 -0
- package/dist/bench/openclaw.js.map +1 -0
- package/dist/bench/report.js +116 -0
- package/dist/bench/report.js.map +1 -0
- package/dist/bench/runner.js +312 -0
- package/dist/bench/runner.js.map +1 -0
- package/dist/bench/types.js +2 -0
- package/dist/bench/types.js.map +1 -0
- package/dist/bot/commands.js +444 -0
- package/dist/bot/commands.js.map +1 -0
- package/dist/bot/confirm-discord.js +133 -0
- package/dist/bot/confirm-discord.js.map +1 -0
- package/dist/bot/confirm-telegram.js +290 -0
- package/dist/bot/confirm-telegram.js.map +1 -0
- package/dist/bot/discord.js +826 -0
- package/dist/bot/discord.js.map +1 -0
- package/dist/bot/format.js +210 -0
- package/dist/bot/format.js.map +1 -0
- package/dist/bot/session-manager.js +270 -0
- package/dist/bot/session-manager.js.map +1 -0
- package/dist/bot/telegram.js +678 -0
- package/dist/bot/telegram.js.map +1 -0
- package/dist/cli/agent-turn.js +45 -0
- package/dist/cli/agent-turn.js.map +1 -0
- package/dist/cli/args.js +236 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/bot.js +252 -0
- package/dist/cli/bot.js.map +1 -0
- package/dist/cli/build-repl-context.js +365 -0
- package/dist/cli/build-repl-context.js.map +1 -0
- package/dist/cli/command-registry.js +20 -0
- package/dist/cli/command-registry.js.map +1 -0
- package/dist/cli/commands/anton.js +271 -0
- package/dist/cli/commands/anton.js.map +1 -0
- package/dist/cli/commands/editing.js +328 -0
- package/dist/cli/commands/editing.js.map +1 -0
- package/dist/cli/commands/model.js +274 -0
- package/dist/cli/commands/model.js.map +1 -0
- package/dist/cli/commands/project.js +255 -0
- package/dist/cli/commands/project.js.map +1 -0
- package/dist/cli/commands/runtime.js +63 -0
- package/dist/cli/commands/runtime.js.map +1 -0
- package/dist/cli/commands/session.js +281 -0
- package/dist/cli/commands/session.js.map +1 -0
- package/dist/cli/commands/tools.js +126 -0
- package/dist/cli/commands/tools.js.map +1 -0
- package/dist/cli/commands/trifecta.js +221 -0
- package/dist/cli/commands/trifecta.js.map +1 -0
- package/dist/cli/commands/tui.js +17 -0
- package/dist/cli/commands/tui.js.map +1 -0
- package/dist/cli/init.js +222 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/input.js +360 -0
- package/dist/cli/input.js.map +1 -0
- package/dist/cli/oneshot.js +254 -0
- package/dist/cli/oneshot.js.map +1 -0
- package/dist/cli/repl-context.js +2 -0
- package/dist/cli/repl-context.js.map +1 -0
- package/dist/cli/runtime-cmds.js +811 -0
- package/dist/cli/runtime-cmds.js.map +1 -0
- package/dist/cli/service.js +145 -0
- package/dist/cli/service.js.map +1 -0
- package/dist/cli/session-state.js +130 -0
- package/dist/cli/session-state.js.map +1 -0
- package/dist/cli/setup.js +815 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/shell.js +79 -0
- package/dist/cli/shell.js.map +1 -0
- package/dist/cli/status.js +392 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/watch.js +33 -0
- package/dist/cli/watch.js.map +1 -0
- package/dist/client.js +676 -0
- package/dist/client.js.map +1 -0
- package/dist/commands.js +194 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.js +507 -0
- package/dist/config.js.map +1 -0
- package/dist/confirm/auto.js +13 -0
- package/dist/confirm/auto.js.map +1 -0
- package/dist/confirm/headless.js +41 -0
- package/dist/confirm/headless.js.map +1 -0
- package/dist/confirm/terminal.js +90 -0
- package/dist/confirm/terminal.js.map +1 -0
- package/dist/context.js +49 -0
- package/dist/context.js.map +1 -0
- package/dist/git.js +136 -0
- package/dist/git.js.map +1 -0
- package/dist/harnesses.js +171 -0
- package/dist/harnesses.js.map +1 -0
- package/dist/history.js +139 -0
- package/dist/history.js.map +1 -0
- package/dist/index.js +700 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer.js +374 -0
- package/dist/indexer.js.map +1 -0
- package/dist/jsonrpc.js +76 -0
- package/dist/jsonrpc.js.map +1 -0
- package/dist/lens.js +525 -0
- package/dist/lens.js.map +1 -0
- package/dist/lsp.js +605 -0
- package/dist/lsp.js.map +1 -0
- package/dist/markdown.js +275 -0
- package/dist/markdown.js.map +1 -0
- package/dist/mcp.js +554 -0
- package/dist/mcp.js.map +1 -0
- package/dist/recovery.js +178 -0
- package/dist/recovery.js.map +1 -0
- package/dist/replay.js +132 -0
- package/dist/replay.js.map +1 -0
- package/dist/replay_cli.js +24 -0
- package/dist/replay_cli.js.map +1 -0
- package/dist/runtime/executor.js +418 -0
- package/dist/runtime/executor.js.map +1 -0
- package/dist/runtime/planner.js +197 -0
- package/dist/runtime/planner.js.map +1 -0
- package/dist/runtime/store.js +289 -0
- package/dist/runtime/store.js.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/safety.js +446 -0
- package/dist/safety.js.map +1 -0
- package/dist/spinner.js +224 -0
- package/dist/spinner.js.map +1 -0
- package/dist/sys/context.js +124 -0
- package/dist/sys/context.js.map +1 -0
- package/dist/sys/snapshot.sh +97 -0
- package/dist/term.js +61 -0
- package/dist/term.js.map +1 -0
- package/dist/themes.js +135 -0
- package/dist/themes.js.map +1 -0
- package/dist/tools.js +1114 -0
- package/dist/tools.js.map +1 -0
- package/dist/tui/branch-picker.js +65 -0
- package/dist/tui/branch-picker.js.map +1 -0
- package/dist/tui/command-handler.js +108 -0
- package/dist/tui/command-handler.js.map +1 -0
- package/dist/tui/confirm.js +90 -0
- package/dist/tui/confirm.js.map +1 -0
- package/dist/tui/controller.js +463 -0
- package/dist/tui/controller.js.map +1 -0
- package/dist/tui/event-bridge.js +44 -0
- package/dist/tui/event-bridge.js.map +1 -0
- package/dist/tui/events.js +2 -0
- package/dist/tui/events.js.map +1 -0
- package/dist/tui/keymap.js +144 -0
- package/dist/tui/keymap.js.map +1 -0
- package/dist/tui/layout.js +11 -0
- package/dist/tui/layout.js.map +1 -0
- package/dist/tui/render.js +186 -0
- package/dist/tui/render.js.map +1 -0
- package/dist/tui/screen.js +48 -0
- package/dist/tui/screen.js.map +1 -0
- package/dist/tui/state.js +167 -0
- package/dist/tui/state.js.map +1 -0
- package/dist/tui/theme.js +70 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/types.js +2 -0
- package/dist/tui/types.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/upgrade.js +412 -0
- package/dist/upgrade.js.map +1 -0
- package/dist/utils.js +87 -0
- package/dist/utils.js.map +1 -0
- package/dist/vault.js +520 -0
- package/dist/vault.js.map +1 -0
- package/dist/vim.js +160 -0
- package/dist/vim.js.map +1 -0
- package/package.json +67 -0
- 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 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tui/types.ts"],"names":[],"mappings":""}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/upgrade.js
ADDED
|
@@ -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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"}
|