@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
package/dist/vim.js ADDED
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Minimal vi-mode editing layer for the readline REPL (Phase 14b).
3
+ *
4
+ * Implements a small, predictable subset of vi keybindings:
5
+ * - Normal/Insert mode toggle
6
+ * - Movement: h, l, w, b, 0, $, ^
7
+ * - Editing: x, dd, i, a, A, I, o (appends newline placeholder)
8
+ * - Yank/Paste: yy, p
9
+ * - Mode switching: Escape → Normal, i/a/A/I → Insert
10
+ *
11
+ * Works alongside readline by intercepting keypress events
12
+ * in Normal mode and passing through in Insert mode.
13
+ */
14
+ export function createVimState() {
15
+ return { mode: 'insert', yankBuffer: '', pendingKey: '' };
16
+ }
17
+ /**
18
+ * Handle a keypress event in vim mode.
19
+ * Returns true if the key was consumed (should not propagate),
20
+ * false if it should propagate to readline normally.
21
+ */
22
+ export function handleVimKeypress(state, rl, ch, key) {
23
+ // Escape always switches to normal mode
24
+ if (key?.name === 'escape') {
25
+ state.mode = 'normal';
26
+ state.pendingKey = '';
27
+ return true;
28
+ }
29
+ // In insert mode, pass everything through except Escape
30
+ if (state.mode === 'insert') {
31
+ return false;
32
+ }
33
+ // --- Normal mode ---
34
+ const line = getLine(rl);
35
+ const cursor = getCursor(rl);
36
+ const k = ch ?? key?.sequence ?? key?.name ?? '';
37
+ // Multi-key commands
38
+ if (state.pendingKey) {
39
+ const combo = state.pendingKey + k;
40
+ state.pendingKey = '';
41
+ if (combo === 'dd') {
42
+ state.yankBuffer = line;
43
+ setLine(rl, '');
44
+ return true;
45
+ }
46
+ if (combo === 'yy') {
47
+ state.yankBuffer = line;
48
+ return true;
49
+ }
50
+ // Unknown combo — ignore
51
+ return true;
52
+ }
53
+ // Start of multi-key sequences
54
+ if (k === 'd' || k === 'y') {
55
+ state.pendingKey = k;
56
+ return true;
57
+ }
58
+ // Movement
59
+ if (k === 'h' || key?.name === 'left') {
60
+ if (cursor > 0)
61
+ setCursor(rl, cursor - 1);
62
+ return true;
63
+ }
64
+ if (k === 'l' || key?.name === 'right') {
65
+ if (cursor < line.length)
66
+ setCursor(rl, cursor + 1);
67
+ return true;
68
+ }
69
+ if (k === '0') {
70
+ setCursor(rl, 0);
71
+ return true;
72
+ }
73
+ if (k === '$') {
74
+ setCursor(rl, line.length);
75
+ return true;
76
+ }
77
+ if (k === '^') {
78
+ const m = line.match(/^\s*/);
79
+ setCursor(rl, m ? m[0].length : 0);
80
+ return true;
81
+ }
82
+ if (k === 'w') {
83
+ const after = line.slice(cursor);
84
+ const m = after.match(/^\S*\s*/);
85
+ const jump = m ? m[0].length : 0;
86
+ setCursor(rl, Math.min(cursor + (jump || 1), line.length));
87
+ return true;
88
+ }
89
+ if (k === 'b') {
90
+ const before = line.slice(0, cursor);
91
+ const m = before.match(/\s*\S*$/);
92
+ const jump = m ? m[0].length : 0;
93
+ setCursor(rl, Math.max(cursor - (jump || 1), 0));
94
+ return true;
95
+ }
96
+ // Editing
97
+ if (k === 'x') {
98
+ if (cursor < line.length) {
99
+ const newLine = line.slice(0, cursor) + line.slice(cursor + 1);
100
+ setLine(rl, newLine);
101
+ setCursor(rl, Math.min(cursor, newLine.length));
102
+ }
103
+ return true;
104
+ }
105
+ // Mode switches to insert
106
+ if (k === 'i') {
107
+ state.mode = 'insert';
108
+ return true;
109
+ }
110
+ if (k === 'a') {
111
+ state.mode = 'insert';
112
+ if (cursor < line.length)
113
+ setCursor(rl, cursor + 1);
114
+ return true;
115
+ }
116
+ if (k === 'A') {
117
+ state.mode = 'insert';
118
+ setCursor(rl, line.length);
119
+ return true;
120
+ }
121
+ if (k === 'I') {
122
+ state.mode = 'insert';
123
+ const m = line.match(/^\s*/);
124
+ setCursor(rl, m ? m[0].length : 0);
125
+ return true;
126
+ }
127
+ // Paste
128
+ if (k === 'p') {
129
+ if (state.yankBuffer) {
130
+ const newLine = line.slice(0, cursor + 1) + state.yankBuffer + line.slice(cursor + 1);
131
+ setLine(rl, newLine);
132
+ setCursor(rl, cursor + state.yankBuffer.length);
133
+ }
134
+ return true;
135
+ }
136
+ // Unknown normal-mode key — consume silently
137
+ return true;
138
+ }
139
+ // --- Internal readline manipulation ---
140
+ function getLine(rl) {
141
+ return String(rl.line ?? '');
142
+ }
143
+ function getCursor(rl) {
144
+ return rl.cursor ?? 0;
145
+ }
146
+ function setLine(rl, text) {
147
+ // Clear current line and rewrite
148
+ rl.write(null, { ctrl: true, name: 'u' });
149
+ if (text)
150
+ rl.write(text);
151
+ }
152
+ function setCursor(rl, pos) {
153
+ rl.cursor = Math.max(0, Math.min(pos, getLine(rl).length));
154
+ // Force readline to refresh the display
155
+ try {
156
+ rl._refreshLine?.();
157
+ }
158
+ catch { }
159
+ }
160
+ //# sourceMappingURL=vim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vim.js","sourceRoot":"","sources":["../src/vim.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@visorcraft/idlehands",
3
+ "version": "0.9.1",
4
+ "type": "module",
5
+ "description": "Local-first coding agent CLI for OpenAI-compatible endpoints",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/visorcraft/idlehands.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/visorcraft/idlehands/issues"
13
+ },
14
+ "homepage": "https://github.com/visorcraft/idlehands#readme",
15
+ "keywords": [
16
+ "llm",
17
+ "agent",
18
+ "cli",
19
+ "openai",
20
+ "local-llm",
21
+ "tool-calling"
22
+ ],
23
+ "bin": {
24
+ "idlehands": "dist/index.js"
25
+ },
26
+ "files": [
27
+ "dist/**",
28
+ "src/sys/snapshot.sh",
29
+ "README.md",
30
+ "LICENSE"
31
+ ],
32
+ "scripts": {
33
+ "build": "tsc -p tsconfig.json && chmod +x dist/index.js && cp src/sys/snapshot.sh dist/sys/snapshot.sh 2>/dev/null || true",
34
+ "prepack": "npm run build --silent",
35
+ "start": "node --enable-source-maps dist/index.js",
36
+ "dev": "tsc -p tsconfig.json -w",
37
+ "typecheck": "tsc -p tsconfig.json --noEmit",
38
+ "test": "IDLEHANDS_QUIET_WARNINGS=1 npm run build --silent && IDLEHANDS_QUIET_WARNINGS=1 node --test --test-concurrency=1 tests/*.test.ts tests/tui/*.test.ts",
39
+ "lint": "node -e \"console.log('no lint configured yet')\"",
40
+ "bench:build": "tsc -p tsconfig.json",
41
+ "bench:run": "node dist/bench/runner.js",
42
+ "bench:report": "node dist/bench/report.js",
43
+ "bench:compare": "node dist/bench/compare.js",
44
+ "bundle:mjs": "node scripts/bundle-mjs.mjs"
45
+ },
46
+ "engines": {
47
+ "node": ">=24"
48
+ },
49
+ "dependencies": {
50
+ "discord.js": "^14.23.2",
51
+ "grammy": "^1.40.0",
52
+ "picocolors": "^1.1.1",
53
+ "tree-sitter-wasms": "^0.1.13",
54
+ "web-tree-sitter": "^0.26.5"
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "^24.0.0",
58
+ "esbuild": "^0.25.9",
59
+ "typescript": "^5.9.3"
60
+ },
61
+ "overrides": {
62
+ "undici": "^6.23.0"
63
+ },
64
+ "optionalDependencies": {
65
+ "node-pty": "^1.1.0"
66
+ }
67
+ }
@@ -0,0 +1,97 @@
1
+ #!/bin/bash
2
+ # System context snapshot for Idle Hands (Phase 9)
3
+ # Usage: snapshot.sh [scope]
4
+ # Scope: all | services | network | disk | packages
5
+ # Target: <500 tokens for full scope, <100 tokens per individual scope, <2s to collect
6
+
7
+ set -euo pipefail
8
+ SCOPE="${1:-all}"
9
+
10
+ collect_os() {
11
+ echo "OS: $(cat /etc/os-release 2>/dev/null | grep '^PRETTY_NAME' | cut -d'"' -f2 || uname -s) ($(uname -m))"
12
+ echo "Kernel: $(uname -r)"
13
+ echo "Hostname: $(hostname)"
14
+ echo "Uptime: $(uptime -p 2>/dev/null | sed 's/^up //' || echo 'unknown')"
15
+ # CPU
16
+ local cpus
17
+ cpus=$(nproc 2>/dev/null || echo '?')
18
+ local model
19
+ model=$(grep -m1 'model name' /proc/cpuinfo 2>/dev/null | cut -d: -f2 | xargs || echo 'unknown')
20
+ echo "CPU: ${model} (${cpus} cores)"
21
+ # RAM
22
+ if command -v free &>/dev/null; then
23
+ local total avail
24
+ total=$(free -h | awk '/^Mem:/{print $2}')
25
+ avail=$(free -h | awk '/^Mem:/{print $7}')
26
+ echo "RAM: ${total} (${avail} available)"
27
+ fi
28
+ }
29
+
30
+ collect_disk() {
31
+ if command -v df &>/dev/null; then
32
+ echo "Disk:"
33
+ df -h --output=target,size,used,avail,pcent / /home 2>/dev/null | tail -n +2 | while read -r mount size used avail pct; do
34
+ echo " ${mount} ${pct} of ${size} (${avail} free)"
35
+ done
36
+ fi
37
+ }
38
+
39
+ collect_network() {
40
+ if command -v ip &>/dev/null; then
41
+ echo "Network:"
42
+ ip -br addr 2>/dev/null | grep -v '^lo ' | while read -r iface state addrs; do
43
+ echo " ${iface} ${state} ${addrs}"
44
+ done
45
+ fi
46
+ }
47
+
48
+ collect_services() {
49
+ if command -v systemctl &>/dev/null; then
50
+ echo "Services (active): $(systemctl list-units --state=active --type=service --no-legend --no-pager 2>/dev/null | awk '{print $1}' | sed 's/\.service$//' | head -20 | tr '\n' ', ' | sed 's/,$//')"
51
+ local failed
52
+ failed=$(systemctl list-units --state=failed --type=service --no-legend --no-pager 2>/dev/null | awk '{print $1}' | sed 's/\.service$//' | tr '\n' ', ' | sed 's/,$//')
53
+ echo "Services (failed): ${failed:-none}"
54
+ fi
55
+ }
56
+
57
+ collect_packages() {
58
+ if command -v apt &>/dev/null; then
59
+ local installed upgradable
60
+ installed=$(dpkg -l 2>/dev/null | grep -c '^ii' || echo '?')
61
+ upgradable=$(apt list --upgradable 2>/dev/null | grep -c 'upgradable' || echo '0')
62
+ echo "Packages (apt): ${installed} installed, ${upgradable} upgradable"
63
+ elif command -v dnf &>/dev/null; then
64
+ local installed
65
+ installed=$(dnf list installed 2>/dev/null | tail -n +2 | wc -l || echo '?')
66
+ echo "Packages (dnf): ${installed} installed"
67
+ elif command -v pacman &>/dev/null; then
68
+ local installed
69
+ installed=$(pacman -Q 2>/dev/null | wc -l || echo '?')
70
+ echo "Packages (pacman): ${installed} installed"
71
+ fi
72
+ # Last boot
73
+ if command -v who &>/dev/null; then
74
+ echo "Last boot: $(who -b 2>/dev/null | awk '{print $3, $4}' || echo 'unknown')"
75
+ fi
76
+ }
77
+
78
+ echo "[System context]"
79
+ case "$SCOPE" in
80
+ all)
81
+ collect_os
82
+ collect_disk
83
+ collect_network
84
+ collect_services
85
+ collect_packages
86
+ ;;
87
+ services) collect_services ;;
88
+ network) collect_network ;;
89
+ disk) collect_disk ;;
90
+ packages) collect_packages ;;
91
+ *)
92
+ echo "Unknown scope: $SCOPE"
93
+ echo "Valid scopes: all, services, network, disk, packages"
94
+ exit 1
95
+ ;;
96
+ esac
97
+ echo "[End system context]"