@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,281 @@
1
+ /**
2
+ * Session commands: /quit, /exit, /clear, /compact, /save, /load,
3
+ * /sessions, /conv, /history, /status, /help, /about.
4
+ */
5
+ import path from 'node:path';
6
+ import fs from 'node:fs/promises';
7
+ import { formatStatusLine } from '../status.js';
8
+ import { conversationBranchPath, isSafeBranchName, saveSessionFile, listSavedSessions, listConversationBranches, } from '../session-state.js';
9
+ import { err as errFmt } from '../../term.js';
10
+ export const sessionCommands = [
11
+ {
12
+ name: '/quit',
13
+ aliases: ['/exit'],
14
+ description: 'Exit the session',
15
+ async execute(ctx) {
16
+ await ctx.shutdown(0);
17
+ return true;
18
+ },
19
+ },
20
+ {
21
+ name: '/help',
22
+ description: 'Show available commands',
23
+ async execute(ctx) {
24
+ console.log(ctx.S.dim('Commands: ') +
25
+ '/help /quit /edit [seed text] /about /mode [code|sys] /status /stats /server /perf /offline [on|off|status] /system [edit|reset|tokens] /lsp [status] /mcp [desc|restart <name>|enable <tool>|disable <tool>] /statusbar on|off /approval [mode] /plan /step [on|off] /approve [N] /reject /history /clear /compact [topic|hard|dry] /init /git [/diff] /branch [name] /changes [--stat|--full|--since N|reset|<file>] /watch [off|status|<path...> [--max N]] /sessions /conv branch|branches|checkout|merge ... /cost /model <name> /capture on|off|last /index [run|status|stats|clear] /undo [path] /save <path> /load <path> /vault <query> /notes /note <key> <value> /checkpoints /rewind <id> /diff <id> /theme [name|list] /vim /commands /exit-shell' +
26
+ '\n' + ctx.S.dim('Shell: !<cmd> run once, !!<cmd> run + inject output, ! toggles shell mode') +
27
+ '\n' + ctx.S.dim('Templates: /fix /review /test /explain /refactor, plus custom markdown commands in ~/.config/idlehands/commands/'));
28
+ return true;
29
+ },
30
+ },
31
+ {
32
+ name: '/about',
33
+ description: 'Show version and system info',
34
+ async execute(ctx) {
35
+ const lines = [
36
+ `Idle Hands v${ctx.version}`,
37
+ `Model: ${ctx.session.model}`,
38
+ `Endpoint: ${ctx.config.endpoint}`,
39
+ `Harness: ${ctx.session.harness}`,
40
+ `Node: ${process.version}`,
41
+ `OS: ${process.platform} ${process.arch}`,
42
+ ];
43
+ console.log(lines.join('\n'));
44
+ return true;
45
+ },
46
+ },
47
+ {
48
+ name: '/status',
49
+ description: 'Show context usage',
50
+ async execute(ctx) {
51
+ ctx.lastStatusLine = formatStatusLine(ctx.session, ctx.config, ctx.S);
52
+ console.log(ctx.lastStatusLine);
53
+ return true;
54
+ },
55
+ },
56
+ {
57
+ name: '/history',
58
+ description: 'Show recent messages',
59
+ async execute(ctx) {
60
+ const tail = ctx.session.messages.slice(-20);
61
+ for (const m of tail) {
62
+ const head = m.role.toUpperCase().padEnd(9, ' ');
63
+ const c = m.content ?? '';
64
+ console.log(`${head}: ${String(c).slice(0, 400)}`);
65
+ }
66
+ return true;
67
+ },
68
+ },
69
+ {
70
+ name: '/clear',
71
+ description: 'Reset session',
72
+ async execute(ctx) {
73
+ ctx.session.reset();
74
+ console.log('Session cleared.');
75
+ return true;
76
+ },
77
+ },
78
+ {
79
+ name: '/compact',
80
+ description: 'Compact conversation history',
81
+ async execute(ctx, args) {
82
+ const hard = /^hard\b/i.test(args);
83
+ const dry = /^dry\b/i.test(args);
84
+ const topic = (!hard && !dry && args) ? args : undefined;
85
+ try {
86
+ const res = await ctx.session.compactHistory({ topic, hard, dry });
87
+ const modeTag = dry ? '[compact dry]' : '[compact]';
88
+ const summary = `${modeTag} ${res.beforeMessages} messages → ${res.afterMessages} messages | ~${res.freedTokens} tokens freed | ${res.archivedToolMessages} tool messages archived to Vault`;
89
+ console.log(summary);
90
+ if (!dry && res.droppedMessages > 0 && topic) {
91
+ console.log(ctx.S.dim(`[compact] topic focus preserved: "${topic}"`));
92
+ }
93
+ }
94
+ catch (e) {
95
+ console.error(errFmt(`COMPACT: ${e?.message ?? String(e)}`, ctx.S));
96
+ }
97
+ return true;
98
+ },
99
+ },
100
+ {
101
+ name: '/save',
102
+ description: 'Save session to file',
103
+ async execute(ctx, args) {
104
+ if (!args) {
105
+ console.log('Usage: /save <path>');
106
+ return true;
107
+ }
108
+ const outPath = path.resolve(ctx.config.dir, args);
109
+ const payload = {
110
+ savedAt: new Date().toISOString(),
111
+ model: ctx.session.model,
112
+ harness: ctx.session.harness,
113
+ contextWindow: ctx.session.contextWindow,
114
+ messages: ctx.session.messages,
115
+ };
116
+ await fs.writeFile(outPath, JSON.stringify(payload, null, 2) + '\n', 'utf8');
117
+ console.log(`Saved session to ${outPath}`);
118
+ return true;
119
+ },
120
+ },
121
+ {
122
+ name: '/load',
123
+ description: 'Load session from file',
124
+ async execute(ctx, args) {
125
+ if (!args) {
126
+ console.log('Usage: /load <path>');
127
+ return true;
128
+ }
129
+ const inPath = path.resolve(ctx.config.dir, args);
130
+ const raw = await fs.readFile(inPath, 'utf8');
131
+ const parsed = JSON.parse(raw);
132
+ if (!parsed?.messages || !Array.isArray(parsed.messages)) {
133
+ console.log('Invalid session file: missing messages[]');
134
+ return true;
135
+ }
136
+ ctx.session.restore(parsed.messages);
137
+ console.log(`Loaded session from ${inPath}`);
138
+ return true;
139
+ },
140
+ },
141
+ {
142
+ name: '/sessions',
143
+ description: 'List saved named sessions',
144
+ async execute(ctx) {
145
+ const rows = await listSavedSessions();
146
+ if (!rows.length) {
147
+ console.log('No saved named sessions.');
148
+ }
149
+ else {
150
+ for (const r of rows.slice(0, 30)) {
151
+ const when = new Date(r.ts).toLocaleString();
152
+ console.log(`${r.name} (${when})`);
153
+ }
154
+ }
155
+ return true;
156
+ },
157
+ },
158
+ {
159
+ name: '/conv',
160
+ description: 'Conversation branches',
161
+ async execute(ctx, args, line) {
162
+ const parts = line.split(/\s+/).filter(Boolean);
163
+ const sub = (parts[1] || '').toLowerCase();
164
+ if (!sub || sub === 'help') {
165
+ console.log('Usage: /conv branch <name> | /conv branches | /conv checkout <name> | /conv merge <name>');
166
+ return true;
167
+ }
168
+ if (sub === 'branch') {
169
+ const name = (parts[2] || '').trim();
170
+ if (!name) {
171
+ console.log('Usage: /conv branch <name>');
172
+ return true;
173
+ }
174
+ if (!isSafeBranchName(name)) {
175
+ console.log('Invalid branch name. Allowed: letters, numbers, dot, underscore, hyphen.');
176
+ return true;
177
+ }
178
+ const payload = {
179
+ savedAt: new Date().toISOString(),
180
+ name,
181
+ model: ctx.session.model,
182
+ harness: ctx.session.harness,
183
+ contextWindow: ctx.session.contextWindow,
184
+ messages: ctx.session.messages,
185
+ };
186
+ const filePath = conversationBranchPath(name);
187
+ await saveSessionFile(filePath, payload);
188
+ console.log(`[conv] saved branch '${name}' (${ctx.session.messages.length} messages)`);
189
+ return true;
190
+ }
191
+ if (sub === 'branches') {
192
+ const rows = await listConversationBranches();
193
+ if (!rows.length) {
194
+ console.log('No conversation branches saved.');
195
+ return true;
196
+ }
197
+ for (const r of rows.slice(0, 50)) {
198
+ const when = new Date(r.ts).toLocaleString();
199
+ console.log(`${r.name} (${when})`);
200
+ }
201
+ return true;
202
+ }
203
+ if (sub === 'checkout') {
204
+ const name = (parts[2] || '').trim();
205
+ if (!name) {
206
+ console.log('Usage: /conv checkout <name>');
207
+ return true;
208
+ }
209
+ if (!isSafeBranchName(name)) {
210
+ console.log('Invalid branch name.');
211
+ return true;
212
+ }
213
+ const filePath = conversationBranchPath(name);
214
+ const raw = await fs.readFile(filePath, 'utf8').catch(() => '');
215
+ if (!raw.trim()) {
216
+ console.log(`Conversation branch not found: ${name}`);
217
+ return true;
218
+ }
219
+ try {
220
+ const parsed = JSON.parse(raw);
221
+ const msgs = Array.isArray(parsed?.messages) ? parsed.messages : [];
222
+ if (msgs.length < 2 || msgs[0]?.role !== 'system') {
223
+ console.log(`Invalid conversation branch: ${name}`);
224
+ return true;
225
+ }
226
+ ctx.session.restore(msgs);
227
+ if (parsed?.model) {
228
+ try {
229
+ ctx.session.setModel(String(parsed.model));
230
+ }
231
+ catch { }
232
+ }
233
+ console.log(`[conv] checked out '${name}' (${msgs.length} messages)`);
234
+ }
235
+ catch (e) {
236
+ console.log(`Failed to load conversation branch '${name}': ${e?.message ?? e}`);
237
+ }
238
+ return true;
239
+ }
240
+ if (sub === 'merge') {
241
+ const name = (parts[2] || '').trim();
242
+ if (!name) {
243
+ console.log('Usage: /conv merge <name>');
244
+ return true;
245
+ }
246
+ if (!isSafeBranchName(name)) {
247
+ console.log('Invalid branch name.');
248
+ return true;
249
+ }
250
+ const filePath = conversationBranchPath(name);
251
+ const raw = await fs.readFile(filePath, 'utf8').catch(() => '');
252
+ if (!raw.trim()) {
253
+ console.log(`Conversation branch not found: ${name}`);
254
+ return true;
255
+ }
256
+ try {
257
+ const parsed = JSON.parse(raw);
258
+ const msgs = Array.isArray(parsed?.messages) ? parsed.messages : [];
259
+ if (!msgs.length) {
260
+ console.log(`Conversation branch '${name}' has no messages.`);
261
+ return true;
262
+ }
263
+ const toAppend = msgs.filter((m, idx) => !(idx === 0 && m?.role === 'system'));
264
+ if (!toAppend.length) {
265
+ console.log(`Conversation branch '${name}' has no mergeable messages.`);
266
+ return true;
267
+ }
268
+ ctx.session.restore([...ctx.session.messages, ...toAppend]);
269
+ console.log(`[conv] merged ${toAppend.length} message(s) from '${name}'`);
270
+ }
271
+ catch (e) {
272
+ console.log(`Failed to merge conversation branch '${name}': ${e?.message ?? e}`);
273
+ }
274
+ return true;
275
+ }
276
+ console.log('Usage: /conv branch <name> | /conv branches | /conv checkout <name> | /conv merge <name>');
277
+ return true;
278
+ },
279
+ },
280
+ ];
281
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/cli/commands/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Tool commands: /lsp, /mcp, /commands.
3
+ */
4
+ import { loadCustomCommands } from '../../commands.js';
5
+ import { projectDir } from '../../utils.js';
6
+ export const toolCommands = [
7
+ {
8
+ name: '/lsp',
9
+ description: 'LSP server status',
10
+ async execute(ctx, args) {
11
+ const sub = args.split(/\s+/)[0]?.toLowerCase() || '';
12
+ if (!sub || sub === 'status' || sub === 'list') {
13
+ const servers = ctx.session.listLspServers();
14
+ if (!servers.length) {
15
+ console.log('LSP: not configured (set lsp.enabled=true in config)');
16
+ }
17
+ else {
18
+ console.log(ctx.S.bold(`LSP servers (${servers.length}):`));
19
+ for (const s of servers) {
20
+ const state = s.running ? ctx.S.green('running') : ctx.S.red('stopped');
21
+ console.log(` ${s.language}: ${s.command} ${state}`);
22
+ }
23
+ }
24
+ }
25
+ else {
26
+ console.log('Usage: /lsp [status]');
27
+ }
28
+ return true;
29
+ },
30
+ },
31
+ {
32
+ name: '/mcp',
33
+ description: 'MCP server management',
34
+ async execute(ctx, args, line) {
35
+ const parts = args.split(/\s+/).filter(Boolean);
36
+ const sub = (parts[0] || '').toLowerCase();
37
+ if (!sub || sub === 'list' || sub === 'status') {
38
+ const servers = ctx.session.listMcpServers();
39
+ if (!servers.length) {
40
+ console.log('MCP: not configured');
41
+ return true;
42
+ }
43
+ console.log(ctx.S.bold(`MCP servers (${servers.length}):`));
44
+ for (const s of servers) {
45
+ const state = s.connected ? ctx.S.green('connected') : ctx.S.red('disconnected');
46
+ const suffix = s.error ? ctx.S.dim(` — ${s.error}`) : '';
47
+ console.log(`- ${s.name} (${s.transport}) ${state} | tools ${s.toolsEnabled}/${s.toolsTotal}${suffix}`);
48
+ }
49
+ const warnings = ctx.session.mcpWarnings();
50
+ for (const w of warnings)
51
+ console.log(ctx.S.dim(`[mcp] ${w}`));
52
+ return true;
53
+ }
54
+ if (sub === 'desc') {
55
+ const tools = ctx.session.listMcpTools({ includeDisabled: true });
56
+ if (!tools.length) {
57
+ console.log('MCP: no tools discovered');
58
+ return true;
59
+ }
60
+ console.log(ctx.S.bold(`MCP tools (${tools.length}):`));
61
+ for (const t of tools) {
62
+ const state = t.enabled ? ctx.S.green('enabled') : ctx.S.dim('disabled');
63
+ const ro = t.readOnly ? ctx.S.dim('ro') : ctx.S.dim('rw');
64
+ const desc = t.description ? ` — ${t.description}` : '';
65
+ console.log(`- ${t.name} [${t.server}] (${ro}, ~${t.estimatedTokens} tok) ${state}${desc}`);
66
+ }
67
+ return true;
68
+ }
69
+ if (sub === 'restart') {
70
+ const name = parts.slice(1).join(' ').trim();
71
+ if (!name) {
72
+ console.log('Usage: /mcp restart <name>');
73
+ return true;
74
+ }
75
+ const res = await ctx.session.restartMcpServer(name);
76
+ console.log(res.ok ? res.message : `MCP restart failed: ${res.message}`);
77
+ return true;
78
+ }
79
+ if (sub === 'enable') {
80
+ const tool = parts.slice(1).join(' ').trim();
81
+ if (!tool) {
82
+ console.log('Usage: /mcp enable <tool>');
83
+ return true;
84
+ }
85
+ const ok = ctx.session.enableMcpTool(tool);
86
+ console.log(ok ? `MCP tool enabled: ${tool}` : `Could not enable MCP tool: ${tool} (not found or exceeds budget)`);
87
+ return true;
88
+ }
89
+ if (sub === 'disable') {
90
+ const tool = parts.slice(1).join(' ').trim();
91
+ if (!tool) {
92
+ console.log('Usage: /mcp disable <tool>');
93
+ return true;
94
+ }
95
+ const ok = ctx.session.disableMcpTool(tool);
96
+ console.log(ok ? `MCP tool disabled: ${tool}` : `Could not disable MCP tool: ${tool}`);
97
+ return true;
98
+ }
99
+ console.log('Usage: /mcp [status|desc|restart <name>|enable <tool>|disable <tool>]');
100
+ return true;
101
+ },
102
+ },
103
+ {
104
+ name: '/commands',
105
+ description: 'Reload/list custom commands',
106
+ async execute(ctx) {
107
+ ctx.customCommands = await loadCustomCommands(projectDir(ctx.config));
108
+ if (!ctx.customCommands.size) {
109
+ console.log(ctx.S.dim('No custom commands found.'));
110
+ console.log(ctx.S.dim('Create command files in ~/.config/idlehands/commands/ or .idlehands/commands/'));
111
+ }
112
+ else {
113
+ console.log(ctx.S.bold(`Custom commands (${ctx.customCommands.size}):`));
114
+ const rows = [...ctx.customCommands.values()].sort((a, b) => a.key.localeCompare(b.key));
115
+ for (const cmd of rows) {
116
+ const cmdArgs = cmd.args.length ? ` ${cmd.args.map((a) => `<${a}>`).join(' ')}` : '';
117
+ const desc = cmd.description ? ` — ${cmd.description}` : '';
118
+ const src = cmd.source === 'project' ? 'project' : 'global';
119
+ console.log(` ${ctx.S.cyan(cmd.key)}${cmdArgs}${ctx.S.dim(` (${src})`)}${desc}`);
120
+ }
121
+ }
122
+ return true;
123
+ },
124
+ },
125
+ ];
126
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/cli/commands/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Trifecta commands: /vault, /notes, /note, /checkpoints, /rewind, /statusbar, /diff.
3
+ */
4
+ import fs from 'node:fs/promises';
5
+ import { atomicWrite, unifiedDiffFromBuffers } from '../../replay_cli.js';
6
+ import { colorizeUnifiedDiff, err as errFmt, warn as warnFmt } from '../../term.js';
7
+ export const trifectaCommands = [
8
+ {
9
+ name: '/vault',
10
+ description: 'Search vault',
11
+ async execute(ctx, args) {
12
+ if (!ctx.session.vault) {
13
+ console.log('Vault is disabled. Enable by removing --no-vault/--no-trifecta.');
14
+ return true;
15
+ }
16
+ if (!args) {
17
+ console.log('Usage: /vault <query>');
18
+ return true;
19
+ }
20
+ try {
21
+ const results = await ctx.session.vault.search(args, 20);
22
+ if (!results.length) {
23
+ console.log('No vault entries found.');
24
+ return true;
25
+ }
26
+ for (const r of results) {
27
+ const key = r.kind === 'note' ? r.key ?? 'note' : r.tool ?? 'tool';
28
+ const snippet = (r.value ?? r.snippet ?? '').replace(/\s+/g, ' ').slice(0, 220);
29
+ console.log(`${r.updatedAt} [${r.kind}] ${key}: ${snippet}`);
30
+ }
31
+ }
32
+ catch (e) {
33
+ console.error(errFmt(`VAULT: ${e?.message ?? String(e)}`, ctx.S));
34
+ }
35
+ return true;
36
+ },
37
+ },
38
+ {
39
+ name: '/notes',
40
+ description: 'List vault notes',
41
+ async execute(ctx) {
42
+ if (!ctx.session.vault) {
43
+ console.log('Vault is disabled. Enable by removing --no-vault/--no-trifecta.');
44
+ return true;
45
+ }
46
+ try {
47
+ const results = await ctx.session.vault.list(20);
48
+ if (!results.length) {
49
+ console.log('No vault notes yet.');
50
+ return true;
51
+ }
52
+ for (const r of results.filter((x) => x.kind === 'note')) {
53
+ const value = (r.value ?? '').replace(/\s+/g, ' ').slice(0, 220);
54
+ console.log(`${r.updatedAt} ${r.key}: ${value}`);
55
+ }
56
+ }
57
+ catch (e) {
58
+ console.error(errFmt(`NOTES: ${e?.message ?? String(e)}`, ctx.S));
59
+ }
60
+ return true;
61
+ },
62
+ },
63
+ {
64
+ name: '/note',
65
+ description: 'Save a vault note',
66
+ async execute(ctx, args) {
67
+ if (!ctx.session.vault) {
68
+ console.log('Vault is disabled. Enable by removing --no-vault/--no-trifecta.');
69
+ return true;
70
+ }
71
+ const idx = args.indexOf(' ');
72
+ if (!args || idx === -1) {
73
+ console.log('Usage: /note <key> <value>');
74
+ return true;
75
+ }
76
+ const key = args.slice(0, idx).trim();
77
+ const value = args.slice(idx + 1).trim();
78
+ if (!key || !value) {
79
+ console.log('Usage: /note <key> <value>');
80
+ return true;
81
+ }
82
+ try {
83
+ const id = await ctx.session.vault.note(key, value);
84
+ console.log(`vault note saved: ${id}`);
85
+ }
86
+ catch (e) {
87
+ console.error(errFmt(`NOTE: ${e?.message ?? String(e)}`, ctx.S));
88
+ }
89
+ return true;
90
+ },
91
+ },
92
+ {
93
+ name: '/checkpoints',
94
+ description: 'List replay checkpoints',
95
+ async execute(ctx) {
96
+ if (!ctx.session.replay) {
97
+ console.log('Replay is disabled. Enable by omitting --no-trifecta/--no-replay.');
98
+ return true;
99
+ }
100
+ try {
101
+ const cps = await ctx.session.replay.list(50);
102
+ if (!cps.length) {
103
+ console.log('No checkpoints yet.');
104
+ return true;
105
+ }
106
+ for (const c of cps) {
107
+ const note = c.note ? ` [${String(c.note).slice(0, 80)}]` : '';
108
+ console.log(`${c.id} ${c.op} ${c.filePath}${note}`);
109
+ }
110
+ }
111
+ catch (e) {
112
+ console.error(errFmt(`CHECKPOINTS: ${e?.message ?? String(e)}`, ctx.S));
113
+ }
114
+ return true;
115
+ },
116
+ },
117
+ {
118
+ name: '/rewind',
119
+ description: 'Rewind to checkpoint',
120
+ async execute(ctx, args) {
121
+ if (!ctx.session.replay) {
122
+ console.log('Replay is disabled. Enable by omitting --no-trifecta/--no-replay.');
123
+ return true;
124
+ }
125
+ if (!args) {
126
+ console.log('Usage: /rewind <checkpoint-id>');
127
+ return true;
128
+ }
129
+ try {
130
+ const { cp } = await ctx.session.replay.get(args);
131
+ const filePath = cp.filePath;
132
+ const msg = await ctx.session.replay.rewind(args, async () => {
133
+ try {
134
+ return await fs.readFile(filePath);
135
+ }
136
+ catch (e) {
137
+ if (e?.code === 'ENOENT')
138
+ return Buffer.alloc(0);
139
+ throw e;
140
+ }
141
+ }, async (buf) => await atomicWrite(filePath, buf));
142
+ console.log(msg);
143
+ }
144
+ catch (e) {
145
+ console.error(errFmt(`REWIND: ${e?.message ?? String(e)}`, ctx.S));
146
+ }
147
+ return true;
148
+ },
149
+ },
150
+ {
151
+ name: '/diff',
152
+ description: 'Show checkpoint diff',
153
+ async execute(ctx, args) {
154
+ if (!ctx.session.replay) {
155
+ console.log('Replay is disabled.');
156
+ return true;
157
+ }
158
+ if (!args) {
159
+ console.log('Usage: /diff <checkpoint-id>');
160
+ return true;
161
+ }
162
+ try {
163
+ const got = await ctx.session.replay.get(args);
164
+ const before = got.before.toString('utf8');
165
+ const after = (got.after ?? Buffer.from('')).toString('utf8');
166
+ if (before === after) {
167
+ console.log('No diff (before == after).');
168
+ }
169
+ else {
170
+ if (got.cp.note)
171
+ console.log(ctx.S.dim(`[structural note] ${got.cp.note}`));
172
+ const out = await unifiedDiffFromBuffers(got.before, got.after ?? Buffer.from(''));
173
+ if (out.trim())
174
+ console.log(colorizeUnifiedDiff(out.trimEnd(), ctx.S));
175
+ else {
176
+ console.log(ctx.S.dim('--- before'));
177
+ console.log(before.slice(0, 800));
178
+ console.log(ctx.S.dim('--- after'));
179
+ console.log(after.slice(0, 800));
180
+ console.log(warnFmt('[diff output truncated]', ctx.S));
181
+ }
182
+ }
183
+ }
184
+ catch (e) {
185
+ console.error(errFmt(`DIFF: ${e?.message ?? String(e)}`, ctx.S));
186
+ }
187
+ return true;
188
+ },
189
+ },
190
+ {
191
+ name: '/statusbar',
192
+ description: 'Toggle status bar',
193
+ async execute(ctx, args) {
194
+ const arg = args.toLowerCase();
195
+ if (!arg) {
196
+ console.log(`Status bar: ${ctx.statusBarEnabled ? 'on' : 'off'}`);
197
+ }
198
+ else if (arg === 'on') {
199
+ if (!ctx.statusBar.canUse()) {
200
+ console.log('Status bar not supported (requires TTY and terminal height >= 10 rows).');
201
+ }
202
+ else {
203
+ ctx.statusBarEnabled = true;
204
+ ctx.statusBar.setEnabled(true);
205
+ ctx.statusBar.render(ctx.lastStatusLine);
206
+ console.log('Status bar: on');
207
+ }
208
+ }
209
+ else if (arg === 'off') {
210
+ ctx.statusBarEnabled = false;
211
+ ctx.statusBar.setEnabled(false);
212
+ console.log('Status bar: off');
213
+ }
214
+ else {
215
+ console.log('Usage: /statusbar on|off');
216
+ }
217
+ return true;
218
+ },
219
+ },
220
+ ];
221
+ //# sourceMappingURL=trifecta.js.map