autohand-cli 0.6.0 → 0.6.2

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 (136) hide show
  1. package/dist/agents-32JB7KMB.js +9 -0
  2. package/dist/agents-3K6PHXQ6.js +9 -0
  3. package/dist/agents-A7AUMVQD.js +8 -0
  4. package/dist/agents-AHFECO5Q.js +9 -0
  5. package/dist/agents-DQFYBMJG.js +8 -0
  6. package/dist/agents-GX6L7BXZ.js +9 -0
  7. package/dist/agents-IWJJ7YJM.js +8 -0
  8. package/dist/agents-J2QLDVOP.js +9 -0
  9. package/dist/agents-OWTSY74S.js +9 -0
  10. package/dist/agents-RB34F4XE.js +9 -0
  11. package/dist/agents-XL27P67O.js +9 -0
  12. package/dist/agents-new-5I3B2W2I.js +9 -0
  13. package/dist/agents-new-CHV2AV34.js +9 -0
  14. package/dist/agents-new-F6F2VMDB.js +9 -0
  15. package/dist/agents-new-FDMUH7NL.js +9 -0
  16. package/dist/agents-new-GBF6JJIA.js +9 -0
  17. package/dist/agents-new-GCZEY4TE.js +8 -0
  18. package/dist/agents-new-OCIB72NU.js +9 -0
  19. package/dist/agents-new-PQGD47BZ.js +9 -0
  20. package/dist/agents-new-V6BNVJAB.js +9 -0
  21. package/dist/agents-new-WQUEZ2XH.js +8 -0
  22. package/dist/chunk-2DEJU7WQ.js +373 -0
  23. package/dist/chunk-2EPIFDFM.js +68 -0
  24. package/dist/chunk-2FUWKZFN.js +68 -0
  25. package/dist/chunk-2HIILNYH.js +197 -0
  26. package/dist/chunk-2QAL3HH4.js +79 -0
  27. package/dist/chunk-3FRM7HJY.js +57 -0
  28. package/dist/chunk-4LDR3Y3A.js +79 -0
  29. package/dist/{chunk-6PYYLBNT.js → chunk-4LLTISFP.js} +1 -1
  30. package/dist/chunk-4UISIRMD.js +288 -0
  31. package/dist/chunk-4VWPX2X3.js +131 -0
  32. package/dist/chunk-7FMMKTRG.js +64 -0
  33. package/dist/chunk-7MFSCH7E.js +382 -0
  34. package/dist/chunk-7TV5KURP.js +79 -0
  35. package/dist/chunk-7WBK33MM.js +57 -0
  36. package/dist/chunk-7XN6PAKV.js +79 -0
  37. package/dist/chunk-A7HRTONQ.js +382 -0
  38. package/dist/chunk-ALMJANSA.js +197 -0
  39. package/dist/chunk-CD7GNBIE.js +288 -0
  40. package/dist/chunk-CV3LEQRD.js +57 -0
  41. package/dist/chunk-DAHMHLM6.js +102 -0
  42. package/dist/chunk-DAMLAWGE.js +68 -0
  43. package/dist/chunk-F4YPGOQJ.js +105 -0
  44. package/dist/chunk-FQDXFNOI.js +57 -0
  45. package/dist/chunk-FQI7EJY2.js +105 -0
  46. package/dist/chunk-GAJCZDZ5.js +286 -0
  47. package/dist/chunk-GEOP77H3.js +79 -0
  48. package/dist/chunk-GRX3IQHC.js +131 -0
  49. package/dist/chunk-GX24PC3L.js +288 -0
  50. package/dist/chunk-H53NQAC2.js +131 -0
  51. package/dist/chunk-HJYISR7Y.js +382 -0
  52. package/dist/chunk-HLSI4HQM.js +105 -0
  53. package/dist/chunk-IAOMCEYU.js +68 -0
  54. package/dist/chunk-J7RENRJG.js +382 -0
  55. package/dist/chunk-JUDX6E53.js +105 -0
  56. package/dist/chunk-JZQKOM7X.js +382 -0
  57. package/dist/chunk-K75NWR5V.js +108 -0
  58. package/dist/chunk-KCMWJB53.js +288 -0
  59. package/dist/chunk-KERHTHMK.js +302 -0
  60. package/dist/chunk-KJ4M6KAK.js +57 -0
  61. package/dist/chunk-L3JXU574.js +77 -0
  62. package/dist/chunk-LR2XPUPT.js +236 -0
  63. package/dist/chunk-MCWNGAZG.js +198 -0
  64. package/dist/chunk-MQTBFYEG.js +288 -0
  65. package/dist/chunk-NCUJWSGP.js +287 -0
  66. package/dist/chunk-NWEUBPSG.js +79 -0
  67. package/dist/chunk-OJ5EBWOQ.js +232 -0
  68. package/dist/chunk-PKQZWNS2.js +131 -0
  69. package/dist/chunk-PQJIQBQ5.js +57 -0
  70. package/dist/chunk-PX5AGAEX.js +105 -0
  71. package/dist/chunk-Q7HX4VZD.js +197 -0
  72. package/dist/chunk-QE5RKNVN.js +30 -0
  73. package/dist/chunk-QLVXFPE3.js +145 -0
  74. package/dist/chunk-QUC577LO.js +79 -0
  75. package/dist/chunk-RAL2W5UX.js +55 -0
  76. package/dist/chunk-RANNBYFJ.js +105 -0
  77. package/dist/chunk-RCSSFUGL.js +131 -0
  78. package/dist/chunk-RUQVXU6K.js +131 -0
  79. package/dist/chunk-RZ7TASUI.js +57 -0
  80. package/dist/chunk-SN7D2PJO.js +68 -0
  81. package/dist/chunk-T4WQUJAE.js +79 -0
  82. package/dist/chunk-U2Z5BABG.js +57 -0
  83. package/dist/chunk-UHC4DIK5.js +105 -0
  84. package/dist/chunk-UNS4S6J3.js +197 -0
  85. package/dist/chunk-UW2LYWIM.js +131 -0
  86. package/dist/chunk-VRCQBFSX.js +102 -0
  87. package/dist/chunk-W76N6IZV.js +197 -0
  88. package/dist/chunk-WTEZYXD2.js +67 -0
  89. package/dist/chunk-X7EWON4T.js +105 -0
  90. package/dist/chunk-XARAKKJ4.js +197 -0
  91. package/dist/chunk-Y6JDGDEE.js +197 -0
  92. package/dist/chunk-Y7FSNXMR.js +382 -0
  93. package/dist/chunk-YPZMUIB5.js +50 -0
  94. package/dist/chunk-ZMDUVLR4.js +148 -0
  95. package/dist/chunk-ZRFAICDG.js +382 -0
  96. package/dist/export-HEFUNSR4.js +8 -0
  97. package/dist/feedback-3U2WYQK6.js +9 -0
  98. package/dist/feedback-5IIX372K.js +9 -0
  99. package/dist/feedback-6S6DWGIU.js +9 -0
  100. package/dist/feedback-7DEOY2AP.js +9 -0
  101. package/dist/feedback-BBQT42R6.js +9 -0
  102. package/dist/feedback-CGCSAWQT.js +9 -0
  103. package/dist/feedback-NEDFOKMA.js +9 -0
  104. package/dist/feedback-OXGGJVNA.js +9 -0
  105. package/dist/feedback-ZJECE2FS.js +8 -0
  106. package/dist/help-NQUZ7TNJ.js +10 -0
  107. package/dist/index.cjs +16 -2
  108. package/dist/index.js +2 -2
  109. package/dist/login-D53NQ7UY.js +10 -0
  110. package/dist/login-GPXDNB2F.js +10 -0
  111. package/dist/login-HDF4GSTP.js +10 -0
  112. package/dist/login-SDAZTJAK.js +10 -0
  113. package/dist/login-SM6LEDDA.js +10 -0
  114. package/dist/login-TDI7HBRZ.js +10 -0
  115. package/dist/login-Y7XXSNOZ.js +10 -0
  116. package/dist/logout-32RNT7G2.js +10 -0
  117. package/dist/logout-43W7N6JU.js +10 -0
  118. package/dist/logout-BMHTSXIY.js +10 -0
  119. package/dist/logout-JNNJJYYL.js +10 -0
  120. package/dist/logout-LW42QASH.js +10 -0
  121. package/dist/logout-QLWM6P26.js +10 -0
  122. package/dist/logout-TL7GLGWU.js +10 -0
  123. package/dist/memory-GVYG653L.js +8 -0
  124. package/dist/new-MCN36AOD.js +8 -0
  125. package/dist/{status-RNUAXIRO.js → status-DCVSUWZG.js} +1 -1
  126. package/dist/status-F6TQOCON.js +8 -0
  127. package/dist/status-IT5CYW37.js +8 -0
  128. package/dist/status-MRJOSVE3.js +8 -0
  129. package/dist/status-MWFV2DZG.js +8 -0
  130. package/dist/status-N3PMJRSB.js +8 -0
  131. package/dist/status-NK7YSBXZ.js +8 -0
  132. package/dist/status-QLQ5ZKJ3.js +8 -0
  133. package/dist/status-SQEFMII5.js +8 -0
  134. package/dist/status-U33PEUBO.js +8 -0
  135. package/dist/status-XAJH67SE.js +8 -0
  136. package/package.json +16 -2
@@ -0,0 +1,288 @@
1
+ // src/commands/status.ts
2
+ import chalk from "chalk";
3
+ import readline from "readline";
4
+
5
+ // package.json
6
+ var package_default = {
7
+ name: "autohand-cli",
8
+ version: "0.5.1",
9
+ description: "Autohand interactive coding agent CLI powered by LLMs.",
10
+ type: "module",
11
+ bin: {
12
+ autohand: "dist/index.js"
13
+ },
14
+ main: "dist/index.js",
15
+ files: [
16
+ "dist"
17
+ ],
18
+ scripts: {
19
+ go: 'bun run build && ./install-local.sh && echo "COMPLETED"',
20
+ build: "tsup src/index.ts --format esm,cjs --dts",
21
+ dev: "tsx src/index.ts",
22
+ typecheck: "tsc --noEmit",
23
+ lint: "eslint .",
24
+ test: "vitest run",
25
+ start: "node dist/index.js",
26
+ "compile:macos-arm64": "bun build ./src/index.ts --compile --target=bun-darwin-arm64 --outfile ./binaries/autohand-macos-arm64",
27
+ "compile:macos-x64": "bun build ./src/index.ts --compile --target=bun-darwin-x64 --outfile ./binaries/autohand-macos-x64",
28
+ "compile:linux-x64": "bun build ./src/index.ts --compile --target=bun-linux-x64 --outfile ./binaries/autohand-linux-x64",
29
+ "compile:linux-arm64": "bun build ./src/index.ts --compile --target=bun-linux-arm64 --outfile ./binaries/autohand-linux-arm64",
30
+ "compile:windows-x64": "bun build ./src/index.ts --compile --target=bun-windows-x64 --outfile ./binaries/autohand-windows-x64.exe",
31
+ "compile:all": "bun run compile:macos-arm64 && bun run compile:macos-x64 && bun run compile:linux-x64 && bun run compile:linux-arm64 && bun run compile:windows-x64",
32
+ link: "bun link"
33
+ },
34
+ keywords: [
35
+ "cli",
36
+ "llm",
37
+ "agent",
38
+ "autohand"
39
+ ],
40
+ engines: {
41
+ node: ">=18.17.0"
42
+ },
43
+ dependencies: {
44
+ chalk: "^5.6.2",
45
+ commander: "^14.0.2",
46
+ diff: "^8.0.2",
47
+ dotenv: "^17.2.3",
48
+ enquirer: "^2.4.1",
49
+ "fs-extra": "^11.3.2",
50
+ ignore: "^5.3.1",
51
+ ink: "^4.4.1",
52
+ open: "^10.1.0",
53
+ ora: "^9.0.0",
54
+ react: "^18.2.0",
55
+ "terminal-link": "^3.0.0",
56
+ yaml: "^2.8.2",
57
+ zod: "^4.1.12"
58
+ },
59
+ devDependencies: {
60
+ "@types/diff": "^8.0.0",
61
+ "@types/fs-extra": "^11.0.4",
62
+ "@types/node": "^24.10.1",
63
+ "@types/react": "^18.3.3",
64
+ "@types/terminal-link": "^1.2.0",
65
+ "@typescript-eslint/eslint-plugin": "^8.48.1",
66
+ "@typescript-eslint/parser": "^8.48.1",
67
+ eslint: "^9.39.1",
68
+ "react-devtools-core": "^7.0.1",
69
+ tsup: "^8.5.1",
70
+ tsx: "^4.20.6",
71
+ typescript: "^5.9.3",
72
+ vitest: "^1.6.0"
73
+ }
74
+ };
75
+
76
+ // src/commands/status.ts
77
+ var metadata = {
78
+ command: "/status",
79
+ description: "Show Autohand status including version, model, API connectivity, and usage",
80
+ implemented: true
81
+ };
82
+ async function status(ctx) {
83
+ const data = await gatherStatusData(ctx);
84
+ await renderStatusUI(data);
85
+ return null;
86
+ }
87
+ async function gatherStatusData(ctx) {
88
+ const currentSession = ctx.sessionManager.getCurrentSession();
89
+ const allSessions = await ctx.sessionManager.listSessions();
90
+ let apiConnected = false;
91
+ try {
92
+ apiConnected = await ctx.llm.isAvailable();
93
+ } catch {
94
+ apiConnected = false;
95
+ }
96
+ return {
97
+ version: package_default.version,
98
+ sessionId: currentSession?.metadata.sessionId ?? null,
99
+ cwd: ctx.workspaceRoot,
100
+ provider: ctx.provider ?? "openrouter",
101
+ model: ctx.model,
102
+ apiConnected,
103
+ sessionsCount: allSessions.length,
104
+ contextPercentLeft: ctx.getContextPercentLeft?.() ?? 100,
105
+ totalTokensUsed: ctx.getTotalTokensUsed?.() ?? 0,
106
+ config: ctx.config
107
+ };
108
+ }
109
+ function renderStatusUI(data) {
110
+ return new Promise((resolve) => {
111
+ const tabs = ["Status", "Config", "Usage"];
112
+ let currentTab = 0;
113
+ const input = process.stdin;
114
+ const isTTY = input.isTTY;
115
+ const wasRaw = input.isRaw;
116
+ const wasPaused = typeof input.isPaused === "function" ? input.isPaused() : false;
117
+ if (wasPaused && typeof input.resume === "function") {
118
+ input.resume();
119
+ }
120
+ if (isTTY) {
121
+ readline.emitKeypressEvents(input);
122
+ if (!wasRaw && typeof input.setRawMode === "function") {
123
+ input.setRawMode(true);
124
+ }
125
+ if (typeof input.setEncoding === "function") {
126
+ input.setEncoding("utf8");
127
+ }
128
+ }
129
+ const render = () => {
130
+ process.stdout.write("\x1B[2J\x1B[H");
131
+ renderTabHeader(tabs, currentTab);
132
+ renderTabContent(tabs[currentTab], data);
133
+ console.log(chalk.gray("\nEsc to exit"));
134
+ };
135
+ let buffer = "";
136
+ const handler = (chunk) => {
137
+ buffer += typeof chunk === "string" ? chunk : chunk.toString("utf8");
138
+ const processNext = () => {
139
+ if (!buffer.length) {
140
+ return false;
141
+ }
142
+ const first = buffer[0];
143
+ if (first === "\x1B") {
144
+ if (buffer.length === 1) {
145
+ return false;
146
+ }
147
+ if (buffer[1] === "[") {
148
+ if (buffer.length < 3) {
149
+ return false;
150
+ }
151
+ const seq = buffer.slice(0, 3);
152
+ buffer = buffer.slice(3);
153
+ handleSequence(seq);
154
+ return true;
155
+ }
156
+ buffer = buffer.slice(1);
157
+ handleSequence("\x1B");
158
+ return true;
159
+ }
160
+ buffer = buffer.slice(1);
161
+ handleSequence(first);
162
+ return true;
163
+ };
164
+ while (processNext()) {
165
+ }
166
+ };
167
+ const handleSequence = (sequence) => {
168
+ switch (sequence) {
169
+ case "\x1B":
170
+ // ESC
171
+ case "":
172
+ cleanup();
173
+ resolve();
174
+ return;
175
+ case " ":
176
+ // Tab
177
+ case "\x1B[C":
178
+ currentTab = (currentTab + 1) % tabs.length;
179
+ render();
180
+ return;
181
+ case "\x1B[Z":
182
+ // Shift+Tab
183
+ case "\x1B[D":
184
+ currentTab = (currentTab - 1 + tabs.length) % tabs.length;
185
+ render();
186
+ return;
187
+ default:
188
+ return;
189
+ }
190
+ };
191
+ const cleanup = () => {
192
+ input.off("data", handler);
193
+ if (isTTY && !wasRaw && typeof input.setRawMode === "function") {
194
+ input.setRawMode(false);
195
+ }
196
+ if (wasPaused && typeof input.pause === "function") {
197
+ input.pause();
198
+ }
199
+ process.stdout.write("\x1B[2J\x1B[H");
200
+ };
201
+ input.on("data", handler);
202
+ render();
203
+ });
204
+ }
205
+ function renderTabHeader(tabs, currentIndex) {
206
+ const header = tabs.map((tab, i) => {
207
+ return i === currentIndex ? chalk.bgWhite.black(` ${tab} `) : chalk.gray(` ${tab} `);
208
+ }).join(" ");
209
+ console.log(`Settings: ${header} ${chalk.gray("(tab to cycle)")}
210
+ `);
211
+ }
212
+ function renderTabContent(tab, data) {
213
+ switch (tab) {
214
+ case "Status":
215
+ renderStatusTab(data);
216
+ break;
217
+ case "Config":
218
+ renderConfigTab(data);
219
+ break;
220
+ case "Usage":
221
+ renderUsageTab(data);
222
+ break;
223
+ }
224
+ }
225
+ function renderStatusTab(data) {
226
+ console.log(chalk.bold("Version:"), data.version);
227
+ console.log(chalk.bold("Session ID:"), data.sessionId ?? chalk.gray("none"));
228
+ console.log(chalk.bold("cwd:"), data.cwd);
229
+ console.log(chalk.bold("Provider:"), data.provider);
230
+ console.log(chalk.bold("Model:"), data.model);
231
+ console.log();
232
+ console.log(
233
+ chalk.bold("API Status:"),
234
+ data.apiConnected ? chalk.green("Connected") : chalk.red("Disconnected")
235
+ );
236
+ console.log(chalk.bold("Sessions:"), `${data.sessionsCount} total`);
237
+ console.log(chalk.bold("Memory:"), "user (~/.autohand/memory/), project (.autohand/memory/)");
238
+ }
239
+ function renderConfigTab(data) {
240
+ const config = data.config;
241
+ console.log(chalk.bold("Autohand preferences\n"));
242
+ const settings = [
243
+ ["Theme", config?.ui?.theme ?? "dark"],
244
+ ["Auto-confirm", config?.ui?.autoConfirm ? "true" : "false"],
245
+ ["Show thinking", config?.ui?.showThinking !== false ? "true" : "false"],
246
+ ["Show completion notification", config?.ui?.showCompletionNotification !== false ? "true" : "false"],
247
+ ["Permission mode", config?.permissions?.mode ?? "interactive"],
248
+ ["Telemetry", config?.telemetry?.enabled !== false ? "true" : "false"],
249
+ ["Network retries", String(config?.network?.maxRetries ?? 3)],
250
+ ["Network timeout", `${config?.network?.timeout ?? 3e4}ms`]
251
+ ];
252
+ for (const [name, value] of settings) {
253
+ console.log(` ${chalk.cyan(name.padEnd(30))} ${value}`);
254
+ }
255
+ }
256
+ function renderUsageTab(data) {
257
+ const contextUsed = 100 - data.contextPercentLeft;
258
+ console.log(chalk.bold("Current session\n"));
259
+ renderProgressBar("Context used", contextUsed, 100);
260
+ console.log();
261
+ console.log(chalk.bold("Tokens used:"), formatTokens(data.totalTokensUsed));
262
+ }
263
+ function renderProgressBar(label, value, max) {
264
+ const width = 30;
265
+ const filled = Math.round(value / max * width);
266
+ const empty = width - filled;
267
+ const bar = chalk.cyan("\u2588".repeat(filled)) + chalk.gray("\u2591".repeat(empty));
268
+ const percent = Math.round(value / max * 100);
269
+ console.log(label);
270
+ console.log(`${bar} ${percent}% used`);
271
+ }
272
+ function formatTokens(tokens) {
273
+ if (tokens >= 1e3) {
274
+ return `${(tokens / 1e3).toFixed(1)}k tokens`;
275
+ }
276
+ return `${tokens} tokens`;
277
+ }
278
+
279
+ export {
280
+ package_default,
281
+ metadata,
282
+ status
283
+ };
284
+ /**
285
+ * @license
286
+ * Copyright 2025 Autohand AI LLC
287
+ * SPDX-License-Identifier: Apache-2.0
288
+ */
@@ -0,0 +1,57 @@
1
+ // src/commands/memory.ts
2
+ import chalk from "chalk";
3
+ async function memory(ctx) {
4
+ const { project, user } = await ctx.memoryManager.listAll();
5
+ console.log();
6
+ console.log(chalk.bold.cyan("Stored Memories"));
7
+ console.log(chalk.gray("\u2500".repeat(50)));
8
+ if (project.length === 0 && user.length === 0) {
9
+ console.log(chalk.gray("No memories stored yet."));
10
+ console.log();
11
+ console.log(chalk.gray("Tip: Type # followed by text to store a memory."));
12
+ console.log(chalk.gray("Example: # Always use TypeScript strict mode"));
13
+ return null;
14
+ }
15
+ if (project.length > 0) {
16
+ console.log();
17
+ console.log(chalk.bold.yellow("Project Memories") + chalk.gray(" (.autohand/memory/)"));
18
+ console.log();
19
+ for (const entry of project) {
20
+ const date = new Date(entry.updatedAt).toLocaleDateString();
21
+ const tags = entry.tags?.length ? chalk.cyan(` [${entry.tags.join(", ")}]`) : "";
22
+ console.log(chalk.white(` ${entry.content}`));
23
+ console.log(chalk.gray(` ID: ${entry.id} | Updated: ${date}${tags}`));
24
+ console.log();
25
+ }
26
+ }
27
+ if (user.length > 0) {
28
+ console.log();
29
+ console.log(chalk.bold.magenta("User Memories") + chalk.gray(" (~/.autohand-cli/memory/)"));
30
+ console.log();
31
+ for (const entry of user) {
32
+ const date = new Date(entry.updatedAt).toLocaleDateString();
33
+ const tags = entry.tags?.length ? chalk.cyan(` [${entry.tags.join(", ")}]`) : "";
34
+ console.log(chalk.white(` ${entry.content}`));
35
+ console.log(chalk.gray(` ID: ${entry.id} | Updated: ${date}${tags}`));
36
+ console.log();
37
+ }
38
+ }
39
+ console.log(chalk.gray("\u2500".repeat(50)));
40
+ console.log(chalk.gray(`Total: ${project.length} project, ${user.length} user memories`));
41
+ return null;
42
+ }
43
+ var metadata = {
44
+ command: "/memory",
45
+ description: "view stored project and user memories",
46
+ implemented: true
47
+ };
48
+
49
+ export {
50
+ memory,
51
+ metadata
52
+ };
53
+ /**
54
+ * @license
55
+ * Copyright 2025 Autohand AI LLC
56
+ * SPDX-License-Identifier: Apache-2.0
57
+ */
@@ -0,0 +1,102 @@
1
+ // src/commands/agents-new.ts
2
+ import os from "os";
3
+ import path from "path";
4
+ import fs from "fs-extra";
5
+ import chalk from "chalk";
6
+ import enquirer from "enquirer";
7
+ var metadata = {
8
+ command: "/agents new",
9
+ description: "create a new sub-agent from a description",
10
+ implemented: true,
11
+ prd: "prd/sub_agents_architecture.md"
12
+ };
13
+ async function createAgent(ctx) {
14
+ const answers = await enquirer.prompt([
15
+ {
16
+ type: "input",
17
+ name: "name",
18
+ message: "Agent name (e.g., Researcher, QA Tester)",
19
+ validate: (val) => typeof val === "string" && val.trim() ? true : "Name is required"
20
+ },
21
+ {
22
+ type: "input",
23
+ name: "description",
24
+ message: "Briefly describe what the agent should do"
25
+ }
26
+ ]);
27
+ const name = answers.name.trim();
28
+ const description = answers.description.trim();
29
+ if (!name) {
30
+ console.log(chalk.gray("Canceled: no name provided."));
31
+ return null;
32
+ }
33
+ const filename = await ensureUniqueFilename(name);
34
+ const filePath = path.join(getAgentsDir(), filename);
35
+ const prompt = buildPrompt(name, description);
36
+ let content;
37
+ try {
38
+ const completion = await ctx.llm.complete({
39
+ messages: [
40
+ {
41
+ role: "system",
42
+ content: "You generate concise markdown definitions for sub-agents. Output only markdown with no code fences. Keep it short but complete."
43
+ },
44
+ { role: "user", content: prompt }
45
+ ],
46
+ maxTokens: 600
47
+ });
48
+ content = completion.content.trim();
49
+ } catch (error) {
50
+ console.error(chalk.red(`Failed to generate agent: ${error.message}`));
51
+ return null;
52
+ }
53
+ try {
54
+ await fs.ensureDir(getAgentsDir());
55
+ await fs.writeFile(filePath, content + "\n", "utf8");
56
+ console.log(chalk.green(`Saved new agent to ${filePath}`));
57
+ } catch (error) {
58
+ console.error(chalk.red(`Failed to save agent: ${error.message}`));
59
+ return null;
60
+ }
61
+ return null;
62
+ }
63
+ function buildPrompt(name, description) {
64
+ return [
65
+ `Create a sub-agent markdown file for "${name}".`,
66
+ description ? `Agent description: ${description}` : "",
67
+ "Structure it as:",
68
+ "# <Name>",
69
+ "## Purpose",
70
+ "## Operating Mode (bullet list)",
71
+ "## Tools (bullet list; mention existing CLI tools and constraints briefly)",
72
+ "## Output Contract (what to return to main agent)",
73
+ "Be concise, 120-160 words total."
74
+ ].filter(Boolean).join("\n");
75
+ }
76
+ function getAgentsDir() {
77
+ return path.join(os.homedir(), ".autohand-cli", "agents");
78
+ }
79
+ function slugify(input) {
80
+ return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "agent";
81
+ }
82
+ async function ensureUniqueFilename(name) {
83
+ const base = slugify(name);
84
+ const dir = getAgentsDir();
85
+ let candidate = `${base}.md`;
86
+ let counter = 1;
87
+ while (await fs.pathExists(path.join(dir, candidate))) {
88
+ candidate = `${base}-${counter}.md`;
89
+ counter += 1;
90
+ }
91
+ return candidate;
92
+ }
93
+
94
+ export {
95
+ metadata,
96
+ createAgent
97
+ };
98
+ /**
99
+ * @license
100
+ * Copyright 2025 Autohand AI LLC
101
+ * SPDX-License-Identifier: Apache-2.0
102
+ */
@@ -0,0 +1,68 @@
1
+ // src/constants.ts
2
+ import os from "os";
3
+ import path from "path";
4
+ var AUTOHAND_HOME = process.env.AUTOHAND_HOME || path.join(os.homedir(), ".autohand");
5
+ var AUTOHAND_PATHS = {
6
+ /** Configuration files (config.json, config.yaml, config.yml) */
7
+ config: AUTOHAND_HOME,
8
+ /** Session data storage */
9
+ sessions: path.join(AUTOHAND_HOME, "sessions"),
10
+ /** Project knowledge base */
11
+ projects: path.join(AUTOHAND_HOME, "projects"),
12
+ /** User-level memory */
13
+ memory: path.join(AUTOHAND_HOME, "memory"),
14
+ /** Feedback state and responses */
15
+ feedback: path.join(AUTOHAND_HOME, "feedback"),
16
+ /** Telemetry data */
17
+ telemetry: path.join(AUTOHAND_HOME, "telemetry"),
18
+ /** Custom commands */
19
+ commands: path.join(AUTOHAND_HOME, "commands"),
20
+ /** Agent definitions */
21
+ agents: path.join(AUTOHAND_HOME, "agents"),
22
+ /** Custom tools */
23
+ tools: path.join(AUTOHAND_HOME, "tools")
24
+ };
25
+ var AUTOHAND_FILES = {
26
+ /** Main config file */
27
+ configJson: path.join(AUTOHAND_HOME, "config.json"),
28
+ configYaml: path.join(AUTOHAND_HOME, "config.yaml"),
29
+ configYml: path.join(AUTOHAND_HOME, "config.yml"),
30
+ /** Device ID for telemetry */
31
+ deviceId: path.join(AUTOHAND_HOME, "device-id"),
32
+ /** Error log */
33
+ errorLog: path.join(AUTOHAND_HOME, "error.log"),
34
+ /** Feedback log */
35
+ feedbackLog: path.join(AUTOHAND_HOME, "feedback.log"),
36
+ /** Telemetry queue */
37
+ telemetryQueue: path.join(AUTOHAND_PATHS.telemetry, "queue.json"),
38
+ /** Session sync queue */
39
+ sessionSyncQueue: path.join(AUTOHAND_PATHS.telemetry, "session-sync-queue.json")
40
+ };
41
+ var PROJECT_DIR_NAME = ".autohand";
42
+ var AUTH_CONFIG = {
43
+ /** Base URL for the authentication API */
44
+ apiBaseUrl: "https://e3fe87a1.autohand-web.pages.dev/api/auth",
45
+ /** URL where users authorize CLI devices */
46
+ authorizationUrl: "https://e3fe87a1.autohand-web.pages.dev/cli-auth",
47
+ /** Polling interval in milliseconds */
48
+ pollInterval: 2e3,
49
+ /** Timeout for device authorization in milliseconds (5 minutes) */
50
+ authTimeout: 5 * 60 * 1e3,
51
+ /** CLI session expiry in days */
52
+ sessionExpiryDays: 30
53
+ };
54
+
55
+ export {
56
+ AUTOHAND_HOME,
57
+ AUTOHAND_PATHS,
58
+ AUTOHAND_FILES,
59
+ PROJECT_DIR_NAME,
60
+ AUTH_CONFIG
61
+ };
62
+ /**
63
+ * @license
64
+ * Copyright 2025 Autohand AI LLC
65
+ * SPDX-License-Identifier: Apache-2.0
66
+ *
67
+ * Centralized constants for Autohand CLI
68
+ */
@@ -0,0 +1,105 @@
1
+ import {
2
+ AUTOHAND_PATHS
3
+ } from "./chunk-IAOMCEYU.js";
4
+
5
+ // src/commands/agents-new.ts
6
+ import path from "path";
7
+ import fs from "fs-extra";
8
+ import chalk from "chalk";
9
+ import enquirer from "enquirer";
10
+ var metadata = {
11
+ command: "/agents new",
12
+ description: "create a new sub-agent from a description",
13
+ implemented: true,
14
+ prd: "prd/sub_agents_architecture.md"
15
+ };
16
+ async function createAgent(ctx) {
17
+ const answers = await enquirer.prompt([
18
+ {
19
+ type: "input",
20
+ name: "name",
21
+ message: "Agent name (e.g., Researcher, QA Tester)",
22
+ validate: (val) => typeof val === "string" && val.trim() ? true : "Name is required"
23
+ },
24
+ {
25
+ type: "input",
26
+ name: "description",
27
+ message: "Briefly describe what the agent should do"
28
+ }
29
+ ]);
30
+ const name = answers.name.trim();
31
+ const description = answers.description.trim();
32
+ if (!name) {
33
+ console.log(chalk.gray("Canceled: no name provided."));
34
+ return null;
35
+ }
36
+ const filename = await ensureUniqueFilename(name);
37
+ const filePath = path.join(getAgentsDir(), filename);
38
+ const prompt = buildPrompt(name, description);
39
+ let content;
40
+ try {
41
+ const completion = await ctx.llm.complete({
42
+ messages: [
43
+ {
44
+ role: "system",
45
+ content: "You generate concise markdown definitions for sub-agents. Output only markdown with no code fences. Keep it short but complete."
46
+ },
47
+ { role: "user", content: prompt }
48
+ ],
49
+ maxTokens: 600
50
+ });
51
+ content = completion.content.trim();
52
+ } catch (error) {
53
+ console.error(chalk.red(`Failed to generate agent: ${error.message}`));
54
+ return null;
55
+ }
56
+ try {
57
+ await fs.ensureDir(getAgentsDir());
58
+ await fs.writeFile(filePath, content + "\n", "utf8");
59
+ console.log(chalk.green(`Saved new agent to ${filePath}`));
60
+ } catch (error) {
61
+ console.error(chalk.red(`Failed to save agent: ${error.message}`));
62
+ return null;
63
+ }
64
+ return null;
65
+ }
66
+ function buildPrompt(name, description) {
67
+ return [
68
+ `Create a sub-agent markdown file for "${name}".`,
69
+ description ? `Agent description: ${description}` : "",
70
+ "Structure it as:",
71
+ "# <Name>",
72
+ "## Purpose",
73
+ "## Operating Mode (bullet list)",
74
+ "## Tools (bullet list; mention existing CLI tools and constraints briefly)",
75
+ "## Output Contract (what to return to main agent)",
76
+ "Be concise, 120-160 words total."
77
+ ].filter(Boolean).join("\n");
78
+ }
79
+ function getAgentsDir() {
80
+ return AUTOHAND_PATHS.agents;
81
+ }
82
+ function slugify(input) {
83
+ return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "agent";
84
+ }
85
+ async function ensureUniqueFilename(name) {
86
+ const base = slugify(name);
87
+ const dir = getAgentsDir();
88
+ let candidate = `${base}.md`;
89
+ let counter = 1;
90
+ while (await fs.pathExists(path.join(dir, candidate))) {
91
+ candidate = `${base}-${counter}.md`;
92
+ counter += 1;
93
+ }
94
+ return candidate;
95
+ }
96
+
97
+ export {
98
+ metadata,
99
+ createAgent
100
+ };
101
+ /**
102
+ * @license
103
+ * Copyright 2025 Autohand AI LLC
104
+ * SPDX-License-Identifier: Apache-2.0
105
+ */
@@ -0,0 +1,57 @@
1
+ import {
2
+ getAuthClient,
3
+ saveConfig
4
+ } from "./chunk-JZQKOM7X.js";
5
+
6
+ // src/commands/logout.ts
7
+ import chalk from "chalk";
8
+ import enquirer from "enquirer";
9
+ var metadata = {
10
+ command: "/logout",
11
+ description: "sign out of your Autohand account",
12
+ implemented: true
13
+ };
14
+ async function logout(ctx) {
15
+ const config = ctx.config;
16
+ if (!config?.auth?.token) {
17
+ console.log(chalk.yellow("You are not currently logged in."));
18
+ console.log(chalk.gray("Use /login to sign in to your Autohand account."));
19
+ return null;
20
+ }
21
+ const userName = config.auth.user?.name || config.auth.user?.email || "user";
22
+ const { confirm } = await enquirer.prompt({
23
+ type: "confirm",
24
+ name: "confirm",
25
+ message: `Log out from ${chalk.cyan(userName)}?`,
26
+ initial: true
27
+ });
28
+ if (!confirm) {
29
+ console.log(chalk.gray("Logout cancelled."));
30
+ return null;
31
+ }
32
+ const authClient = getAuthClient();
33
+ try {
34
+ await authClient.logout(config.auth.token);
35
+ } catch {
36
+ }
37
+ const updatedConfig = {
38
+ ...config,
39
+ auth: void 0
40
+ };
41
+ await saveConfig(updatedConfig);
42
+ console.log();
43
+ console.log(chalk.green("Successfully logged out."));
44
+ console.log(chalk.gray("Your local session has been cleared."));
45
+ console.log();
46
+ return null;
47
+ }
48
+
49
+ export {
50
+ metadata,
51
+ logout
52
+ };
53
+ /**
54
+ * @license
55
+ * Copyright 2025 Autohand AI LLC
56
+ * SPDX-License-Identifier: Apache-2.0
57
+ */