autohand-cli 0.6.3 → 0.6.4

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 (81) hide show
  1. package/dist/agents-EHLYBJLK.cjs +10 -0
  2. package/dist/{agents-7GZ2VBYU.js → agents-OJWYZN6X.js} +1 -0
  3. package/dist/agents-new-7VPASCBV.cjs +10 -0
  4. package/dist/{agents-new-VALZG4B5.js → agents-new-WQLJOXSS.js} +1 -0
  5. package/dist/chunk-27JNK5TE.cjs +252 -0
  6. package/dist/chunk-3Y6G5DUX.cjs +105 -0
  7. package/dist/chunk-4AMTDSQ3.cjs +30 -0
  8. package/dist/{chunk-KZ4QOKII.js → chunk-6MCXWSR3.js} +2 -2
  9. package/dist/chunk-7RRX7H2X.cjs +104 -0
  10. package/dist/chunk-AD4O67ZA.cjs +93 -0
  11. package/dist/chunk-AL4Z4WKG.cjs +59 -0
  12. package/dist/chunk-BEIG7V7Q.cjs +51 -0
  13. package/dist/chunk-C3IFF3EH.cjs +373 -0
  14. package/dist/chunk-DD2YPHP5.cjs +133 -0
  15. package/dist/chunk-FFA4LDAO.cjs +55 -0
  16. package/dist/chunk-G7SYGATA.cjs +197 -0
  17. package/dist/chunk-IHJDYAYJ.cjs +77 -0
  18. package/dist/chunk-JBKP2CLA.cjs +364 -0
  19. package/dist/chunk-JSBRDJBE.js +30 -0
  20. package/dist/chunk-KNLBEUAV.cjs +57 -0
  21. package/dist/chunk-M4LKQQHU.cjs +168 -0
  22. package/dist/chunk-M7RVTUWE.cjs +145 -0
  23. package/dist/chunk-MFK6HE47.cjs +33 -0
  24. package/dist/chunk-N254NRHT.cjs +30 -0
  25. package/dist/chunk-QCMC2WOC.cjs +1135 -0
  26. package/dist/chunk-RDEROLKA.cjs +79 -0
  27. package/dist/chunk-RYY5I7QN.cjs +49 -0
  28. package/dist/chunk-V5MTBGM4.cjs +20 -0
  29. package/dist/chunk-VMMGT42E.cjs +60 -0
  30. package/dist/chunk-WBDPILKI.cjs +19 -0
  31. package/dist/chunk-XT4OSHSB.cjs +20 -0
  32. package/dist/chunk-Z4J4W6YQ.cjs +339 -0
  33. package/dist/chunk-Z6SGIQWH.cjs +191 -0
  34. package/dist/chunk-ZTA2ASFW.cjs +304 -0
  35. package/dist/completion-AMEZDTFT.cjs +11 -0
  36. package/dist/{completion-Y42FKDT3.js → completion-HR3ZT55J.js} +1 -0
  37. package/dist/{export-WJ5P6E5Z.js → export-MYBJZD3H.js} +1 -0
  38. package/dist/export-ULYYSO5V.cjs +9 -0
  39. package/dist/{feedback-RJNBUBDQ.js → feedback-3THCLEBE.js} +1 -0
  40. package/dist/feedback-PATTKRH5.cjs +10 -0
  41. package/dist/{formatters-UG6VZJJ5.js → formatters-3POW3KMP.js} +1 -0
  42. package/dist/formatters-UMUJYWV5.cjs +9 -0
  43. package/dist/help-2PR7P4UJ.cjs +11 -0
  44. package/dist/{help-PKC6QCNG.js → help-AW4QPGIW.js} +1 -0
  45. package/dist/index.cjs +3579 -6515
  46. package/dist/index.js +1735 -62
  47. package/dist/{init-DML7AOII.js → init-HAQKREMF.js} +1 -0
  48. package/dist/init-OLSCW7ZC.cjs +9 -0
  49. package/dist/lint-D5UOJWIK.cjs +9 -0
  50. package/dist/{lint-TA2ZHVLM.js → lint-NJPZWVN2.js} +1 -0
  51. package/dist/{login-MBMAXHG6.js → login-QJROML5I.js} +1 -0
  52. package/dist/login-X66DSV75.cjs +12 -0
  53. package/dist/logout-3Z7R3F7J.cjs +12 -0
  54. package/dist/{logout-VI6YMV7P.js → logout-RJ5OAXRI.js} +1 -0
  55. package/dist/memory-77SWEZYB.cjs +9 -0
  56. package/dist/{memory-4GSP7NKV.js → memory-F3V5FW6W.js} +1 -0
  57. package/dist/model-B2PE6XFS.cjs +9 -0
  58. package/dist/{model-HKEFSH5E.js → model-JC53RT7A.js} +1 -0
  59. package/dist/{new-EEZC4XXV.js → new-356ITOM7.js} +1 -0
  60. package/dist/new-J3ABPMW4.cjs +9 -0
  61. package/dist/{permissions-XJKYKDBG.js → permissions-CYW62ZK3.js} +1 -0
  62. package/dist/permissions-NOC5DMOH.cjs +9 -0
  63. package/dist/{quit-RSYIERO5.js → quit-2QWJ75GZ.js} +1 -0
  64. package/dist/quit-DQ57J67A.cjs +9 -0
  65. package/dist/resume-43XMN4CL.cjs +9 -0
  66. package/dist/{resume-2NERFSTD.js → resume-GA7YZJSO.js} +1 -0
  67. package/dist/session-BSU2L5UI.cjs +9 -0
  68. package/dist/{session-H5QWKE5E.js → session-SZMRN5KG.js} +1 -0
  69. package/dist/sessions-CVOZGTKR.cjs +9 -0
  70. package/dist/{sessions-4KXIT76T.js → sessions-OJ4DRK3P.js} +1 -0
  71. package/dist/{skills-POKNCIQV.js → skills-HF4SAF5O.js} +1 -0
  72. package/dist/skills-U6J6DFLK.cjs +11 -0
  73. package/dist/{skills-new-5VCNKQDP.js → skills-new-QDTNEG3R.js} +1 -0
  74. package/dist/skills-new-UPVBHIF2.cjs +10 -0
  75. package/dist/status-GR73LEEN.cjs +9 -0
  76. package/dist/{status-XQSGXTHN.js → status-SLYYTKXD.js} +2 -1
  77. package/dist/{theme-B5QZLGKP.js → theme-THMQ5AIN.js} +1 -0
  78. package/dist/theme-YDANJLZR.cjs +13 -0
  79. package/dist/{undo-7QJBXARS.js → undo-3Q44LSVS.js} +1 -0
  80. package/dist/undo-WF5HB5VU.cjs +9 -0
  81. package/package.json +2 -2
@@ -0,0 +1,79 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+ var _chunkIHJDYAYJcjs = require('./chunk-IHJDYAYJ.cjs');
4
+
5
+ // src/commands/feedback.ts
6
+ var _fsextra = require('fs-extra'); var _fsextra2 = _interopRequireDefault(_fsextra);
7
+ var _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk);
8
+ var _enquirer = require('enquirer'); var _enquirer2 = _interopRequireDefault(_enquirer);
9
+ var metadata = {
10
+ command: "/feedback",
11
+ description: "share feedback with environment details",
12
+ implemented: true
13
+ };
14
+ async function feedback(_ctx) {
15
+ const answer = await _enquirer2.default.prompt([
16
+ {
17
+ type: "input",
18
+ name: "feedback",
19
+ message: "What worked? What broke?"
20
+ }
21
+ ]);
22
+ if (!_optionalChain([answer, 'access', _ => _.feedback, 'optionalAccess', _2 => _2.trim, 'call', _3 => _3()])) {
23
+ console.log(_chalk2.default.gray("Feedback discarded (empty)."));
24
+ return null;
25
+ }
26
+ const now = (/* @__PURE__ */ new Date()).toISOString();
27
+ const runtimeError = getLastRuntimeError();
28
+ const payload = {
29
+ timestamp: now,
30
+ feedback: answer.feedback.trim(),
31
+ env: {
32
+ platform: `${process.platform}-${process.arch}`,
33
+ node: process.version,
34
+ bun: _optionalChain([process, 'access', _4 => _4.versions, 'optionalAccess', _5 => _5.bun]),
35
+ cwd: process.cwd(),
36
+ shell: process.env.SHELL
37
+ },
38
+ runtimeError: runtimeError ? formatError(runtimeError) : null
39
+ };
40
+ try {
41
+ const feedbackPath = _chunkIHJDYAYJcjs.AUTOHAND_FILES.feedbackLog;
42
+ await _fsextra2.default.ensureFile(feedbackPath);
43
+ await _fsextra2.default.appendFile(feedbackPath, JSON.stringify(payload) + "\n", "utf8");
44
+ console.log(_chalk2.default.green("Feedback recorded."));
45
+ console.log(_chalk2.default.gray(`Saved to ${feedbackPath}`));
46
+ } catch (error) {
47
+ console.error(_chalk2.default.red(`Failed to save feedback: ${error.message}`));
48
+ }
49
+ if (runtimeError) {
50
+ console.log(_chalk2.default.yellow("Detected a recent runtime error; included in feedback payload."));
51
+ }
52
+ return null;
53
+ }
54
+ function getLastRuntimeError() {
55
+ const globalAny = globalThis;
56
+ return _nullishCoalesce(globalAny.__autohandLastError, () => ( null));
57
+ }
58
+ function formatError(err) {
59
+ if (!err) return {};
60
+ if (err instanceof Error) {
61
+ return { message: err.message, stack: err.stack };
62
+ }
63
+ if (typeof err === "object") {
64
+ const message = "message" in err ? String(err.message) : void 0;
65
+ const stack = "stack" in err ? String(err.stack) : void 0;
66
+ return { message, stack };
67
+ }
68
+ return { message: String(err) };
69
+ }
70
+
71
+
72
+
73
+
74
+ exports.metadata = metadata; exports.feedback = feedback;
75
+ /**
76
+ * @license
77
+ * Copyright 2025 Autohand AI LLC
78
+ * SPDX-License-Identifier: Apache-2.0
79
+ */
@@ -0,0 +1,49 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// src/commands/resume.ts
2
+ var _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk);
3
+ var metadata = {
4
+ command: "/resume",
5
+ description: "resume a previous session",
6
+ implemented: true
7
+ };
8
+ async function resume(ctx) {
9
+ const sessionId = ctx.args[0];
10
+ if (!sessionId) {
11
+ console.log(_chalk2.default.red("Usage: /resume <session-id>"));
12
+ console.log(_chalk2.default.gray("Use /sessions to list available sessions"));
13
+ return null;
14
+ }
15
+ try {
16
+ const session = await ctx.sessionManager.loadSession(sessionId);
17
+ const messages = session.getMessages();
18
+ console.log(_chalk2.default.cyan(`
19
+ \u{1F4C2} Resuming session ${sessionId}`));
20
+ console.log(_chalk2.default.gray(` Project: ${session.metadata.projectPath}`));
21
+ console.log(_chalk2.default.gray(` Started: ${new Date(session.metadata.createdAt).toLocaleString()}`));
22
+ console.log(_chalk2.default.gray(` Messages: ${messages.length}`));
23
+ console.log();
24
+ if (messages.length > 0) {
25
+ console.log(_chalk2.default.cyan("Recent conversation:"));
26
+ const recentMessages = messages.slice(-3);
27
+ for (const msg of recentMessages) {
28
+ const role = msg.role === "user" ? _chalk2.default.green("You") : _chalk2.default.blue("Assistant");
29
+ const preview = msg.content.slice(0, 80) + (msg.content.length > 80 ? "..." : "");
30
+ console.log(`${role}: ${_chalk2.default.gray(preview)}`);
31
+ }
32
+ console.log();
33
+ }
34
+ return "SESSION_RESUMED";
35
+ } catch (error) {
36
+ console.error(_chalk2.default.red(`Failed to resume session: ${error.message}`));
37
+ return null;
38
+ }
39
+ }
40
+
41
+
42
+
43
+
44
+ exports.metadata = metadata; exports.resume = resume;
45
+ /**
46
+ * @license
47
+ * Copyright 2025 Autohand AI LLC
48
+ * SPDX-License-Identifier: Apache-2.0
49
+ */
@@ -0,0 +1,20 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/commands/init.ts
2
+ async function init(ctx) {
3
+ await ctx.createAgentsFile();
4
+ return null;
5
+ }
6
+ var metadata = {
7
+ command: "/init",
8
+ description: "create an AGENTS.md file with instructions for Autohand",
9
+ implemented: true
10
+ };
11
+
12
+
13
+
14
+
15
+ exports.init = init; exports.metadata = metadata;
16
+ /**
17
+ * @license
18
+ * Copyright 2025 Autohand AI LLC
19
+ * SPDX-License-Identifier: Apache-2.0
20
+ */
@@ -0,0 +1,60 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/commands/sessions.ts
2
+ var _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk);
3
+ var metadata = {
4
+ command: "/sessions",
5
+ description: "list all sessions",
6
+ implemented: true
7
+ };
8
+ async function sessions(ctx) {
9
+ const projectFilter = ctx.args.includes("--project") ? ctx.args[ctx.args.indexOf("--project") + 1] : void 0;
10
+ try {
11
+ const allSessions = await ctx.sessionManager.listSessions(
12
+ projectFilter ? { project: projectFilter } : void 0
13
+ );
14
+ if (allSessions.length === 0) {
15
+ console.log(_chalk2.default.gray("No sessions found."));
16
+ return null;
17
+ }
18
+ console.log(_chalk2.default.cyan(`
19
+ Sessions${projectFilter ? ` for ${projectFilter}` : ""}:
20
+ `));
21
+ console.log(
22
+ _chalk2.default.bold(
23
+ " ID".padEnd(25) + "Created".padEnd(20) + "Messages".padEnd(12) + "Summary"
24
+ )
25
+ );
26
+ console.log(_chalk2.default.gray("\u2500".repeat(80)));
27
+ for (const session of allSessions.slice(0, 20)) {
28
+ const id = session.sessionId.padEnd(24);
29
+ const created = new Date(session.createdAt).toLocaleString("en-US", {
30
+ month: "short",
31
+ day: "numeric",
32
+ hour: "numeric",
33
+ minute: "2-digit"
34
+ }).padEnd(19);
35
+ const messages = session.messageCount.toString().padEnd(11);
36
+ const summary = _optionalChain([session, 'access', _ => _.summary, 'optionalAccess', _2 => _2.slice, 'call', _3 => _3(0, 40)]) || _chalk2.default.gray("No summary");
37
+ console.log(` ${_chalk2.default.cyan(id)}${created}${messages}${summary}`);
38
+ }
39
+ if (allSessions.length > 20) {
40
+ console.log(_chalk2.default.gray(`
41
+ ... and ${allSessions.length - 20} more sessions`));
42
+ }
43
+ console.log(_chalk2.default.gray(`
44
+ Use ${_chalk2.default.white("/resume <id>")} to continue a session`));
45
+ return null;
46
+ } catch (error) {
47
+ console.error(_chalk2.default.red(`Failed to list sessions: ${error.message}`));
48
+ return null;
49
+ }
50
+ }
51
+
52
+
53
+
54
+
55
+ exports.metadata = metadata; exports.sessions = sessions;
56
+ /**
57
+ * @license
58
+ * Copyright 2025 Autohand AI LLC
59
+ * SPDX-License-Identifier: Apache-2.0
60
+ */
@@ -0,0 +1,19 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/commands/quit.ts
2
+ async function quit() {
3
+ return "/quit";
4
+ }
5
+ var metadata = {
6
+ command: "/quit",
7
+ description: "end the current Autohand session",
8
+ implemented: true
9
+ };
10
+
11
+
12
+
13
+
14
+ exports.quit = quit; exports.metadata = metadata;
15
+ /**
16
+ * @license
17
+ * Copyright 2025 Autohand AI LLC
18
+ * SPDX-License-Identifier: Apache-2.0
19
+ */
@@ -0,0 +1,20 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/commands/model.ts
2
+ async function model(ctx) {
3
+ await ctx.promptModelSelection();
4
+ return null;
5
+ }
6
+ var metadata = {
7
+ command: "/model",
8
+ description: "choose what model and reasoning effort to use",
9
+ implemented: true
10
+ };
11
+
12
+
13
+
14
+
15
+ exports.model = model; exports.metadata = metadata;
16
+ /**
17
+ * @license
18
+ * Copyright 2025 Autohand AI LLC
19
+ * SPDX-License-Identifier: Apache-2.0
20
+ */
@@ -0,0 +1,339 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/commands/formatters.ts
2
+ var _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk);
3
+
4
+ // src/actions/formatters.ts
5
+ var _child_process = require('child_process');
6
+ var _path = require('path'); var _path2 = _interopRequireDefault(_path);
7
+ var EXTERNAL_FORMATTERS = {
8
+ prettier: {
9
+ name: "prettier",
10
+ command: "prettier",
11
+ extensions: [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".json", ".css", ".scss", ".less", ".html", ".md", ".yaml", ".yml", ".graphql"],
12
+ description: "Opinionated code formatter for JavaScript, TypeScript, CSS, and more",
13
+ checkCmd: ["prettier", "--version"]
14
+ },
15
+ black: {
16
+ name: "black",
17
+ command: "black",
18
+ extensions: [".py", ".pyi"],
19
+ description: "The uncompromising Python code formatter",
20
+ checkCmd: ["black", "--version"]
21
+ },
22
+ rustfmt: {
23
+ name: "rustfmt",
24
+ command: "rustfmt",
25
+ extensions: [".rs"],
26
+ description: "Format Rust code according to style guidelines",
27
+ checkCmd: ["rustfmt", "--version"]
28
+ },
29
+ gofmt: {
30
+ name: "gofmt",
31
+ command: "gofmt",
32
+ extensions: [".go"],
33
+ description: "Format Go source code",
34
+ checkCmd: ["gofmt", "-h"]
35
+ },
36
+ clangformat: {
37
+ name: "clang-format",
38
+ command: "clang-format",
39
+ extensions: [".c", ".cpp", ".h", ".hpp", ".cc", ".cxx"],
40
+ description: "Format C/C++ code",
41
+ checkCmd: ["clang-format", "--version"]
42
+ },
43
+ shfmt: {
44
+ name: "shfmt",
45
+ command: "shfmt",
46
+ extensions: [".sh", ".bash"],
47
+ description: "Format shell scripts",
48
+ checkCmd: ["shfmt", "--version"]
49
+ },
50
+ sqlformat: {
51
+ name: "sqlformat",
52
+ command: "sqlformat",
53
+ extensions: [".sql"],
54
+ description: "Format SQL files",
55
+ checkCmd: ["sqlformat", "--version"]
56
+ },
57
+ xmllint: {
58
+ name: "xmllint",
59
+ command: "xmllint",
60
+ extensions: [".xml", ".xsl", ".xslt"],
61
+ description: "Format XML files",
62
+ checkCmd: ["xmllint", "--version"]
63
+ }
64
+ };
65
+ async function isCommandAvailable(command) {
66
+ return new Promise((resolve) => {
67
+ const proc = _child_process.spawn.call(void 0, command, ["--version"], {
68
+ stdio: "ignore",
69
+ shell: process.platform === "win32"
70
+ });
71
+ proc.on("error", () => resolve(false));
72
+ proc.on("close", (code) => resolve(code === 0));
73
+ setTimeout(() => {
74
+ proc.kill();
75
+ resolve(false);
76
+ }, 2e3);
77
+ });
78
+ }
79
+ async function runExternalFormatter(command, args, input, cwd) {
80
+ return new Promise((resolve) => {
81
+ const proc = _child_process.spawn.call(void 0, command, args, {
82
+ cwd,
83
+ shell: process.platform === "win32",
84
+ stdio: ["pipe", "pipe", "pipe"]
85
+ });
86
+ let stdout = "";
87
+ let stderr = "";
88
+ proc.stdout.on("data", (data) => {
89
+ stdout += data.toString();
90
+ });
91
+ proc.stderr.on("data", (data) => {
92
+ stderr += data.toString();
93
+ });
94
+ proc.on("error", (err) => {
95
+ resolve({
96
+ success: false,
97
+ output: input,
98
+ error: `Failed to run ${command}: ${err.message}`
99
+ });
100
+ });
101
+ proc.on("close", (code) => {
102
+ if (code === 0) {
103
+ resolve({ success: true, output: stdout || input });
104
+ } else {
105
+ resolve({
106
+ success: false,
107
+ output: input,
108
+ error: stderr || `${command} exited with code ${code}`
109
+ });
110
+ }
111
+ });
112
+ proc.stdin.write(input);
113
+ proc.stdin.end();
114
+ setTimeout(() => {
115
+ proc.kill();
116
+ resolve({
117
+ success: false,
118
+ output: input,
119
+ error: `${command} timed out after 30 seconds`
120
+ });
121
+ }, 3e4);
122
+ });
123
+ }
124
+ async function formatWithPrettier(contents, file, workspaceRoot) {
125
+ const ext = _path2.default.extname(file);
126
+ const parser = getPrettierParser(ext);
127
+ const result = await runExternalFormatter(
128
+ "prettier",
129
+ ["--stdin-filepath", file, ...parser ? ["--parser", parser] : []],
130
+ contents,
131
+ workspaceRoot
132
+ );
133
+ if (!result.success) {
134
+ throw new Error(result.error || "Prettier formatting failed");
135
+ }
136
+ return result.output;
137
+ }
138
+ function getPrettierParser(ext) {
139
+ const parserMap = {
140
+ ".js": "babel",
141
+ ".jsx": "babel",
142
+ ".ts": "typescript",
143
+ ".tsx": "typescript",
144
+ ".mjs": "babel",
145
+ ".cjs": "babel",
146
+ ".json": "json",
147
+ ".css": "css",
148
+ ".scss": "scss",
149
+ ".less": "less",
150
+ ".html": "html",
151
+ ".md": "markdown",
152
+ ".yaml": "yaml",
153
+ ".yml": "yaml",
154
+ ".graphql": "graphql"
155
+ };
156
+ return parserMap[ext] || null;
157
+ }
158
+ async function formatWithBlack(contents, file, workspaceRoot) {
159
+ const result = await runExternalFormatter(
160
+ "black",
161
+ ["-", "--quiet"],
162
+ contents,
163
+ workspaceRoot
164
+ );
165
+ if (!result.success) {
166
+ throw new Error(result.error || "Black formatting failed");
167
+ }
168
+ return result.output;
169
+ }
170
+ async function formatWithRustfmt(contents, file, workspaceRoot) {
171
+ const result = await runExternalFormatter(
172
+ "rustfmt",
173
+ ["--emit", "stdout"],
174
+ contents,
175
+ workspaceRoot
176
+ );
177
+ if (!result.success) {
178
+ throw new Error(result.error || "rustfmt formatting failed");
179
+ }
180
+ return result.output;
181
+ }
182
+ async function formatWithGofmt(contents, file, workspaceRoot) {
183
+ const result = await runExternalFormatter(
184
+ "gofmt",
185
+ [],
186
+ contents,
187
+ workspaceRoot
188
+ );
189
+ if (!result.success) {
190
+ throw new Error(result.error || "gofmt formatting failed");
191
+ }
192
+ return result.output;
193
+ }
194
+ async function formatWithClangFormat(contents, file, workspaceRoot) {
195
+ const result = await runExternalFormatter(
196
+ "clang-format",
197
+ [`--assume-filename=${file}`],
198
+ contents,
199
+ workspaceRoot
200
+ );
201
+ if (!result.success) {
202
+ throw new Error(result.error || "clang-format formatting failed");
203
+ }
204
+ return result.output;
205
+ }
206
+ async function formatWithShfmt(contents, file, workspaceRoot) {
207
+ const result = await runExternalFormatter(
208
+ "shfmt",
209
+ ["-i", "2"],
210
+ // 2-space indent
211
+ contents,
212
+ workspaceRoot
213
+ );
214
+ if (!result.success) {
215
+ throw new Error(result.error || "shfmt formatting failed");
216
+ }
217
+ return result.output;
218
+ }
219
+ var builtinFormatters = {
220
+ json: async (contents) => {
221
+ const parsed = JSON.parse(contents);
222
+ return JSON.stringify(parsed, null, 2) + "\n";
223
+ },
224
+ trim: async (contents) => contents.trim() + "\n",
225
+ "normalize-newlines": async (contents) => {
226
+ return contents.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
227
+ },
228
+ "trailing-newline": async (contents) => {
229
+ return contents.endsWith("\n") ? contents : contents + "\n";
230
+ },
231
+ "remove-trailing-whitespace": async (contents) => {
232
+ return contents.split("\n").map((line) => line.trimEnd()).join("\n");
233
+ }
234
+ };
235
+ var externalFormatters = {
236
+ prettier: formatWithPrettier,
237
+ black: formatWithBlack,
238
+ rustfmt: formatWithRustfmt,
239
+ gofmt: formatWithGofmt,
240
+ "clang-format": formatWithClangFormat,
241
+ clangformat: formatWithClangFormat,
242
+ shfmt: formatWithShfmt
243
+ };
244
+ async function checkAvailableFormatters() {
245
+ const results = {};
246
+ for (const name of Object.keys(builtinFormatters)) {
247
+ results[name] = true;
248
+ }
249
+ const checks = Object.entries(EXTERNAL_FORMATTERS).map(async ([name, info]) => {
250
+ const available = await isCommandAvailable(info.command);
251
+ results[name] = available;
252
+ });
253
+ await Promise.all(checks);
254
+ return results;
255
+ }
256
+ async function listFormatters() {
257
+ const available = await checkAvailableFormatters();
258
+ const formatters = [
259
+ // Built-in formatters
260
+ { name: "json", command: "built-in", extensions: [".json"], description: "Format JSON with 2-space indent", checkCmd: [], installed: true },
261
+ { name: "trim", command: "built-in", extensions: ["*"], description: "Trim whitespace and ensure trailing newline", checkCmd: [], installed: true },
262
+ { name: "normalize-newlines", command: "built-in", extensions: ["*"], description: "Convert all line endings to LF", checkCmd: [], installed: true },
263
+ { name: "trailing-newline", command: "built-in", extensions: ["*"], description: "Ensure file ends with newline", checkCmd: [], installed: true },
264
+ { name: "remove-trailing-whitespace", command: "built-in", extensions: ["*"], description: "Remove trailing whitespace from lines", checkCmd: [], installed: true },
265
+ // External formatters
266
+ ...Object.entries(EXTERNAL_FORMATTERS).map(([name, info]) => ({
267
+ ...info,
268
+ installed: _nullishCoalesce(available[name], () => ( false))
269
+ }))
270
+ ];
271
+ return formatters;
272
+ }
273
+ async function applyFormatter(name, contents, file, workspaceRoot) {
274
+ const builtin = builtinFormatters[name];
275
+ if (builtin) {
276
+ return builtin(contents, file, workspaceRoot);
277
+ }
278
+ const external = externalFormatters[name];
279
+ if (external) {
280
+ return external(contents, file, workspaceRoot);
281
+ }
282
+ throw new Error(`Formatter "${name}" is not available. Run /formatters to see available formatters.`);
283
+ }
284
+
285
+ // src/commands/formatters.ts
286
+ var metadata = {
287
+ command: "/formatters",
288
+ description: "List available code formatters",
289
+ implemented: true
290
+ };
291
+ async function execute() {
292
+ console.log();
293
+ console.log(_chalk2.default.cyan.bold("Available Code Formatters"));
294
+ console.log(_chalk2.default.gray("\u2500".repeat(60)));
295
+ console.log();
296
+ const formatters = await listFormatters();
297
+ const builtIn = formatters.filter((f) => f.command === "built-in");
298
+ const external = formatters.filter((f) => f.command !== "built-in");
299
+ console.log(_chalk2.default.yellow.bold("Built-in Formatters (always available):"));
300
+ console.log();
301
+ for (const f of builtIn) {
302
+ console.log(` ${_chalk2.default.green("\u2713")} ${_chalk2.default.white.bold(f.name)}`);
303
+ console.log(` ${_chalk2.default.gray(f.description)}`);
304
+ console.log(` ${_chalk2.default.gray("Extensions:")} ${f.extensions.join(", ")}`);
305
+ console.log();
306
+ }
307
+ console.log(_chalk2.default.yellow.bold("External Formatters:"));
308
+ console.log();
309
+ for (const f of external) {
310
+ const status = f.installed ? _chalk2.default.green("\u2713 installed") : _chalk2.default.red("\u2717 not found");
311
+ console.log(` ${f.installed ? _chalk2.default.green("\u2713") : _chalk2.default.red("\u2717")} ${_chalk2.default.white.bold(f.name)} ${_chalk2.default.gray(`(${f.command})`)} - ${status}`);
312
+ console.log(` ${_chalk2.default.gray(f.description)}`);
313
+ console.log(` ${_chalk2.default.gray("Extensions:")} ${f.extensions.join(", ")}`);
314
+ console.log();
315
+ }
316
+ console.log(_chalk2.default.gray("\u2500".repeat(60)));
317
+ console.log(_chalk2.default.gray("Usage: The agent can use format_file action with any installed formatter."));
318
+ console.log(_chalk2.default.gray("Install missing formatters via your package manager (npm, pip, cargo, etc.)"));
319
+ console.log();
320
+ }
321
+
322
+
323
+
324
+
325
+
326
+ exports.applyFormatter = applyFormatter; exports.metadata = metadata; exports.execute = execute;
327
+ /**
328
+ * @license
329
+ * Copyright 2025 Autohand AI LLC
330
+ * SPDX-License-Identifier: Apache-2.0
331
+ *
332
+ * Code Formatters
333
+ * Supports prettier, black, rustfmt, gofmt, and more
334
+ */
335
+ /**
336
+ * @license
337
+ * Copyright 2025 Autohand AI LLC
338
+ * SPDX-License-Identifier: Apache-2.0
339
+ */