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.
- package/dist/agents-EHLYBJLK.cjs +10 -0
- package/dist/{agents-7GZ2VBYU.js → agents-OJWYZN6X.js} +1 -0
- package/dist/agents-new-7VPASCBV.cjs +10 -0
- package/dist/{agents-new-VALZG4B5.js → agents-new-WQLJOXSS.js} +1 -0
- package/dist/chunk-27JNK5TE.cjs +252 -0
- package/dist/chunk-3Y6G5DUX.cjs +105 -0
- package/dist/chunk-4AMTDSQ3.cjs +30 -0
- package/dist/{chunk-KZ4QOKII.js → chunk-6MCXWSR3.js} +2 -2
- package/dist/chunk-7RRX7H2X.cjs +104 -0
- package/dist/chunk-AD4O67ZA.cjs +93 -0
- package/dist/chunk-AL4Z4WKG.cjs +59 -0
- package/dist/chunk-BEIG7V7Q.cjs +51 -0
- package/dist/chunk-C3IFF3EH.cjs +373 -0
- package/dist/chunk-DD2YPHP5.cjs +133 -0
- package/dist/chunk-FFA4LDAO.cjs +55 -0
- package/dist/chunk-G7SYGATA.cjs +197 -0
- package/dist/chunk-IHJDYAYJ.cjs +77 -0
- package/dist/chunk-JBKP2CLA.cjs +364 -0
- package/dist/chunk-JSBRDJBE.js +30 -0
- package/dist/chunk-KNLBEUAV.cjs +57 -0
- package/dist/chunk-M4LKQQHU.cjs +168 -0
- package/dist/chunk-M7RVTUWE.cjs +145 -0
- package/dist/chunk-MFK6HE47.cjs +33 -0
- package/dist/chunk-N254NRHT.cjs +30 -0
- package/dist/chunk-QCMC2WOC.cjs +1135 -0
- package/dist/chunk-RDEROLKA.cjs +79 -0
- package/dist/chunk-RYY5I7QN.cjs +49 -0
- package/dist/chunk-V5MTBGM4.cjs +20 -0
- package/dist/chunk-VMMGT42E.cjs +60 -0
- package/dist/chunk-WBDPILKI.cjs +19 -0
- package/dist/chunk-XT4OSHSB.cjs +20 -0
- package/dist/chunk-Z4J4W6YQ.cjs +339 -0
- package/dist/chunk-Z6SGIQWH.cjs +191 -0
- package/dist/chunk-ZTA2ASFW.cjs +304 -0
- package/dist/completion-AMEZDTFT.cjs +11 -0
- package/dist/{completion-Y42FKDT3.js → completion-HR3ZT55J.js} +1 -0
- package/dist/{export-WJ5P6E5Z.js → export-MYBJZD3H.js} +1 -0
- package/dist/export-ULYYSO5V.cjs +9 -0
- package/dist/{feedback-RJNBUBDQ.js → feedback-3THCLEBE.js} +1 -0
- package/dist/feedback-PATTKRH5.cjs +10 -0
- package/dist/{formatters-UG6VZJJ5.js → formatters-3POW3KMP.js} +1 -0
- package/dist/formatters-UMUJYWV5.cjs +9 -0
- package/dist/help-2PR7P4UJ.cjs +11 -0
- package/dist/{help-PKC6QCNG.js → help-AW4QPGIW.js} +1 -0
- package/dist/index.cjs +3579 -6515
- package/dist/index.js +1735 -62
- package/dist/{init-DML7AOII.js → init-HAQKREMF.js} +1 -0
- package/dist/init-OLSCW7ZC.cjs +9 -0
- package/dist/lint-D5UOJWIK.cjs +9 -0
- package/dist/{lint-TA2ZHVLM.js → lint-NJPZWVN2.js} +1 -0
- package/dist/{login-MBMAXHG6.js → login-QJROML5I.js} +1 -0
- package/dist/login-X66DSV75.cjs +12 -0
- package/dist/logout-3Z7R3F7J.cjs +12 -0
- package/dist/{logout-VI6YMV7P.js → logout-RJ5OAXRI.js} +1 -0
- package/dist/memory-77SWEZYB.cjs +9 -0
- package/dist/{memory-4GSP7NKV.js → memory-F3V5FW6W.js} +1 -0
- package/dist/model-B2PE6XFS.cjs +9 -0
- package/dist/{model-HKEFSH5E.js → model-JC53RT7A.js} +1 -0
- package/dist/{new-EEZC4XXV.js → new-356ITOM7.js} +1 -0
- package/dist/new-J3ABPMW4.cjs +9 -0
- package/dist/{permissions-XJKYKDBG.js → permissions-CYW62ZK3.js} +1 -0
- package/dist/permissions-NOC5DMOH.cjs +9 -0
- package/dist/{quit-RSYIERO5.js → quit-2QWJ75GZ.js} +1 -0
- package/dist/quit-DQ57J67A.cjs +9 -0
- package/dist/resume-43XMN4CL.cjs +9 -0
- package/dist/{resume-2NERFSTD.js → resume-GA7YZJSO.js} +1 -0
- package/dist/session-BSU2L5UI.cjs +9 -0
- package/dist/{session-H5QWKE5E.js → session-SZMRN5KG.js} +1 -0
- package/dist/sessions-CVOZGTKR.cjs +9 -0
- package/dist/{sessions-4KXIT76T.js → sessions-OJ4DRK3P.js} +1 -0
- package/dist/{skills-POKNCIQV.js → skills-HF4SAF5O.js} +1 -0
- package/dist/skills-U6J6DFLK.cjs +11 -0
- package/dist/{skills-new-5VCNKQDP.js → skills-new-QDTNEG3R.js} +1 -0
- package/dist/skills-new-UPVBHIF2.cjs +10 -0
- package/dist/status-GR73LEEN.cjs +9 -0
- package/dist/{status-XQSGXTHN.js → status-SLYYTKXD.js} +2 -1
- package/dist/{theme-B5QZLGKP.js → theme-THMQ5AIN.js} +1 -0
- package/dist/theme-YDANJLZR.cjs +13 -0
- package/dist/{undo-7QJBXARS.js → undo-3Q44LSVS.js} +1 -0
- package/dist/undo-WF5HB5VU.cjs +9 -0
- 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
|
+
*/
|