autohand-cli 0.7.4 → 0.7.6

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.
@@ -0,0 +1,613 @@
1
+ import {
2
+ package_default
3
+ } from "./chunk-5MCDN53U.js";
4
+ import {
5
+ AUTOHAND_PATHS
6
+ } from "./chunk-FUEL6BK7.js";
7
+
8
+ // src/commands/share.ts
9
+ import chalk from "chalk";
10
+ import enquirer from "enquirer";
11
+ import ora from "ora";
12
+
13
+ // src/share/costEstimator.ts
14
+ var DEFAULT_COST_PER_1K_TOKENS = 3e-3;
15
+ function estimateCost(totalTokens) {
16
+ if (totalTokens <= 0) return 0;
17
+ const cost = totalTokens / 1e3 * DEFAULT_COST_PER_1K_TOKENS;
18
+ return Math.round(cost * 1e4) / 1e4;
19
+ }
20
+ function formatCost(cost) {
21
+ if (cost < 0.01) {
22
+ if (cost === 0) return "$0.00";
23
+ return `$${cost.toFixed(4)}`;
24
+ }
25
+ return `$${cost.toFixed(2)}`;
26
+ }
27
+ function formatTokens(tokens) {
28
+ if (tokens >= 1e6) {
29
+ return `${(tokens / 1e6).toFixed(1)}M`;
30
+ }
31
+ if (tokens >= 1e3) {
32
+ return `${(tokens / 1e3).toFixed(1)}K`;
33
+ }
34
+ return tokens.toString();
35
+ }
36
+ function formatDuration(seconds) {
37
+ if (seconds < 60) {
38
+ return `${seconds}s`;
39
+ }
40
+ const minutes = Math.floor(seconds / 60);
41
+ const remainingSeconds = seconds % 60;
42
+ if (minutes < 60) {
43
+ if (remainingSeconds === 0) return `${minutes}m`;
44
+ return `${minutes}m ${remainingSeconds}s`;
45
+ }
46
+ const hours = Math.floor(minutes / 60);
47
+ const remainingMinutes = minutes % 60;
48
+ if (remainingMinutes === 0) return `${hours}h`;
49
+ return `${hours}h ${remainingMinutes}m`;
50
+ }
51
+
52
+ // src/share/sessionSerializer.ts
53
+ function extractToolUsage(messages) {
54
+ const toolCounts = /* @__PURE__ */ new Map();
55
+ for (const message of messages) {
56
+ if (message.role === "assistant" && message.toolCalls) {
57
+ for (const toolCall of message.toolCalls) {
58
+ const toolName = toolCall.function?.name || toolCall.name || "unknown";
59
+ const current = toolCounts.get(toolName) || { total: 0, success: 0 };
60
+ current.total++;
61
+ toolCounts.set(toolName, current);
62
+ }
63
+ }
64
+ if (message.role === "tool" && message.name) {
65
+ const current = toolCounts.get(message.name);
66
+ if (current) {
67
+ const isError = message.content.toLowerCase().includes("error") || message.content.toLowerCase().includes("failed");
68
+ if (!isError) {
69
+ current.success++;
70
+ }
71
+ }
72
+ }
73
+ }
74
+ const result = [];
75
+ for (const [name, counts] of toolCounts) {
76
+ result.push({
77
+ name,
78
+ count: counts.total,
79
+ successRate: counts.total > 0 ? counts.success / counts.total : void 0
80
+ });
81
+ }
82
+ return result.sort((a, b) => b.count - a.count);
83
+ }
84
+ function estimateTokensFromMessages(messages) {
85
+ let input = 0;
86
+ let output = 0;
87
+ for (const message of messages) {
88
+ const chars = message.content.length;
89
+ const tokens = Math.ceil(chars / 4);
90
+ if (message.role === "user" || message.role === "system") {
91
+ input += tokens;
92
+ } else {
93
+ output += tokens;
94
+ }
95
+ }
96
+ return {
97
+ total: input + output,
98
+ input,
99
+ output
100
+ };
101
+ }
102
+ function parseGitDiff(diffContent) {
103
+ if (!diffContent || diffContent.trim().length === 0) {
104
+ return void 0;
105
+ }
106
+ const lines = diffContent.split("\n");
107
+ const filesChanged = /* @__PURE__ */ new Set();
108
+ let linesAdded = 0;
109
+ let linesRemoved = 0;
110
+ for (const line of lines) {
111
+ if (line.startsWith("diff --git")) {
112
+ const match = line.match(/diff --git a\/(.+) b\/(.+)/);
113
+ if (match) {
114
+ filesChanged.add(match[2]);
115
+ }
116
+ } else if (line.startsWith("+") && !line.startsWith("+++")) {
117
+ linesAdded++;
118
+ } else if (line.startsWith("-") && !line.startsWith("---")) {
119
+ linesRemoved++;
120
+ }
121
+ }
122
+ if (filesChanged.size === 0 && linesAdded === 0 && linesRemoved === 0) {
123
+ return void 0;
124
+ }
125
+ return {
126
+ filesChanged: Array.from(filesChanged),
127
+ linesAdded,
128
+ linesRemoved,
129
+ diffContent
130
+ };
131
+ }
132
+ function calculateDuration(startedAt, endedAt) {
133
+ const start = new Date(startedAt).getTime();
134
+ const end = new Date(endedAt).getTime();
135
+ return Math.max(0, Math.floor((end - start) / 1e3));
136
+ }
137
+ function serializeSession(session, options) {
138
+ const messages = session.getMessages();
139
+ const { metadata: metadata2 } = session;
140
+ const endedAt = metadata2.closedAt || (/* @__PURE__ */ new Date()).toISOString();
141
+ const durationSeconds = calculateDuration(metadata2.createdAt, endedAt);
142
+ const sessionMetadata = {
143
+ sessionId: metadata2.sessionId,
144
+ projectName: metadata2.projectName,
145
+ model: options.model || metadata2.model,
146
+ provider: options.provider || "openrouter",
147
+ startedAt: metadata2.createdAt,
148
+ endedAt,
149
+ durationSeconds,
150
+ messageCount: messages.length,
151
+ status: metadata2.status,
152
+ summary: metadata2.summary
153
+ };
154
+ let usage;
155
+ if (options.totalTokens && options.totalTokens > 0) {
156
+ const inputTokens = Math.floor(options.totalTokens * 0.3);
157
+ const outputTokens = options.totalTokens - inputTokens;
158
+ usage = {
159
+ totalTokens: options.totalTokens,
160
+ inputTokens,
161
+ outputTokens,
162
+ estimatedCost: estimateCost(options.totalTokens)
163
+ };
164
+ } else {
165
+ const estimated = estimateTokensFromMessages(messages);
166
+ usage = {
167
+ totalTokens: estimated.total,
168
+ inputTokens: estimated.input,
169
+ outputTokens: estimated.output,
170
+ estimatedCost: estimateCost(estimated.total)
171
+ };
172
+ }
173
+ const toolUsage = extractToolUsage(messages);
174
+ const gitDiff = options.gitDiff ? parseGitDiff(options.gitDiff) : void 0;
175
+ const client = {
176
+ cliVersion: package_default.version,
177
+ platform: process.platform,
178
+ deviceId: options.deviceId
179
+ };
180
+ const sharedMessages = messages.map((msg) => ({
181
+ role: msg.role,
182
+ content: msg.content,
183
+ timestamp: msg.timestamp,
184
+ name: msg.name,
185
+ toolCalls: msg.toolCalls,
186
+ tool_call_id: msg.tool_call_id
187
+ }));
188
+ return {
189
+ metadata: sessionMetadata,
190
+ usage,
191
+ toolUsage,
192
+ gitDiff,
193
+ messages: sharedMessages,
194
+ visibility: options.visibility,
195
+ client,
196
+ userId: options.userId
197
+ };
198
+ }
199
+
200
+ // src/share/ShareApiClient.ts
201
+ import fs from "fs-extra";
202
+ import path from "path";
203
+ function getBaseUrl() {
204
+ return process.env.AUTOHAND_SHARE_URL || "https://autohand.link/api";
205
+ }
206
+ var DEFAULT_CONFIG = {
207
+ baseUrl: getBaseUrl(),
208
+ timeout: 3e4,
209
+ // 30s for large payloads
210
+ maxRetries: 3,
211
+ offlineQueue: true,
212
+ cliVersion: package_default.version
213
+ };
214
+ var ShareApiClient = class {
215
+ constructor(configOverrides) {
216
+ this.deviceId = null;
217
+ this.config = { ...DEFAULT_CONFIG, ...configOverrides };
218
+ const dataDir = path.join(AUTOHAND_PATHS.config, "share");
219
+ this.queuePath = path.join(dataDir, "queue.json");
220
+ this.deviceIdPath = path.join(AUTOHAND_PATHS.feedback, ".device-id");
221
+ }
222
+ // ============ Device ID ============
223
+ /**
224
+ * Get or create anonymous device identifier
225
+ * Shared with FeedbackApiClient for consistency
226
+ */
227
+ async getDeviceId() {
228
+ if (this.deviceId) return this.deviceId;
229
+ try {
230
+ if (await fs.pathExists(this.deviceIdPath)) {
231
+ this.deviceId = (await fs.readFile(this.deviceIdPath, "utf8")).trim();
232
+ return this.deviceId;
233
+ }
234
+ } catch {
235
+ }
236
+ this.deviceId = `anon_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
237
+ try {
238
+ await fs.ensureDir(path.dirname(this.deviceIdPath));
239
+ await fs.writeFile(this.deviceIdPath, this.deviceId);
240
+ } catch {
241
+ }
242
+ return this.deviceId;
243
+ }
244
+ // ============ Create Share ============
245
+ /**
246
+ * Upload a session to create a shareable link
247
+ */
248
+ async createShare(payload) {
249
+ try {
250
+ const response = await this.sendToApi("POST", "/share", payload);
251
+ if (response.success) {
252
+ this.flushQueue().catch(() => {
253
+ });
254
+ }
255
+ return response;
256
+ } catch (error) {
257
+ if (this.config.offlineQueue) {
258
+ await this.addToQueue(payload);
259
+ return {
260
+ success: false,
261
+ error: `Queued for retry: ${error.message}`
262
+ };
263
+ }
264
+ return {
265
+ success: false,
266
+ error: error.message
267
+ };
268
+ }
269
+ }
270
+ // ============ Delete Share ============
271
+ /**
272
+ * Delete a shared session (owner only)
273
+ */
274
+ async deleteShare(shareId) {
275
+ const deviceId = await this.getDeviceId();
276
+ try {
277
+ const response = await this.sendToApi(
278
+ "DELETE",
279
+ `/share/${shareId}`,
280
+ void 0,
281
+ { "X-Device-ID": deviceId }
282
+ );
283
+ return response;
284
+ } catch (error) {
285
+ return {
286
+ success: false,
287
+ error: error.message
288
+ };
289
+ }
290
+ }
291
+ // ============ API Communication ============
292
+ /**
293
+ * Send request to API endpoint
294
+ */
295
+ async sendToApi(method, endpoint, body, extraHeaders) {
296
+ const controller = new AbortController();
297
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
298
+ try {
299
+ const headers = {
300
+ "Content-Type": "application/json",
301
+ "X-CLI-Version": this.config.cliVersion,
302
+ ...extraHeaders
303
+ };
304
+ const response = await fetch(`${this.config.baseUrl}${endpoint}`, {
305
+ method,
306
+ headers,
307
+ body: body ? JSON.stringify(body) : void 0,
308
+ signal: controller.signal
309
+ });
310
+ clearTimeout(timeoutId);
311
+ if (!response.ok) {
312
+ const errorText = await response.text().catch(() => "Unknown error");
313
+ throw new Error(`API error: ${response.status} ${errorText}`);
314
+ }
315
+ const data = await response.json();
316
+ return data;
317
+ } catch (error) {
318
+ clearTimeout(timeoutId);
319
+ if (error.name === "AbortError") {
320
+ throw new Error("Request timeout");
321
+ }
322
+ throw error;
323
+ }
324
+ }
325
+ // ============ Offline Queue ============
326
+ /**
327
+ * Add share to offline queue
328
+ */
329
+ async addToQueue(payload) {
330
+ try {
331
+ let queue = [];
332
+ if (await fs.pathExists(this.queuePath)) {
333
+ queue = await fs.readJson(this.queuePath);
334
+ }
335
+ queue.push({
336
+ payload,
337
+ attempts: 0,
338
+ lastAttempt: (/* @__PURE__ */ new Date()).toISOString(),
339
+ id: `q_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`
340
+ });
341
+ if (queue.length > 10) {
342
+ queue = queue.slice(-10);
343
+ }
344
+ await fs.ensureDir(path.dirname(this.queuePath));
345
+ await fs.writeJson(this.queuePath, queue, { spaces: 2 });
346
+ } catch {
347
+ }
348
+ }
349
+ /**
350
+ * Attempt to flush queued shares
351
+ */
352
+ async flushQueue() {
353
+ let sent = 0;
354
+ let failed = 0;
355
+ try {
356
+ if (!await fs.pathExists(this.queuePath)) {
357
+ return { sent, failed };
358
+ }
359
+ const queue = await fs.readJson(this.queuePath);
360
+ const remaining = [];
361
+ for (const item of queue) {
362
+ if (item.attempts >= this.config.maxRetries) {
363
+ failed++;
364
+ continue;
365
+ }
366
+ try {
367
+ const response = await this.sendToApi("POST", "/share", item.payload);
368
+ if (response.success) {
369
+ sent++;
370
+ } else {
371
+ item.attempts++;
372
+ item.lastAttempt = (/* @__PURE__ */ new Date()).toISOString();
373
+ remaining.push(item);
374
+ failed++;
375
+ }
376
+ } catch {
377
+ item.attempts++;
378
+ item.lastAttempt = (/* @__PURE__ */ new Date()).toISOString();
379
+ remaining.push(item);
380
+ failed++;
381
+ }
382
+ }
383
+ if (remaining.length > 0) {
384
+ await fs.writeJson(this.queuePath, remaining, { spaces: 2 });
385
+ } else {
386
+ await fs.remove(this.queuePath);
387
+ }
388
+ } catch {
389
+ }
390
+ return { sent, failed };
391
+ }
392
+ /**
393
+ * Get queue status
394
+ */
395
+ async getQueueStatus() {
396
+ try {
397
+ if (!await fs.pathExists(this.queuePath)) {
398
+ return { pending: 0, oldestItem: null };
399
+ }
400
+ const queue = await fs.readJson(this.queuePath);
401
+ return {
402
+ pending: queue.length,
403
+ oldestItem: queue[0]?.lastAttempt || null
404
+ };
405
+ } catch {
406
+ return { pending: 0, oldestItem: null };
407
+ }
408
+ }
409
+ // ============ Health Check ============
410
+ /**
411
+ * Check if API is reachable
412
+ */
413
+ async healthCheck() {
414
+ try {
415
+ const controller = new AbortController();
416
+ const timeoutId = setTimeout(() => controller.abort(), 5e3);
417
+ const response = await fetch(`${this.config.baseUrl}/health`, {
418
+ method: "GET",
419
+ signal: controller.signal
420
+ });
421
+ clearTimeout(timeoutId);
422
+ return response.ok;
423
+ } catch {
424
+ return false;
425
+ }
426
+ }
427
+ };
428
+ var instance = null;
429
+ var instanceBaseUrl = null;
430
+ function getShareApiClient(config) {
431
+ const currentBaseUrl = config?.baseUrl || getBaseUrl();
432
+ if (instance && instanceBaseUrl !== currentBaseUrl) {
433
+ instance = null;
434
+ }
435
+ if (!instance) {
436
+ instance = new ShareApiClient(config);
437
+ instanceBaseUrl = currentBaseUrl;
438
+ }
439
+ return instance;
440
+ }
441
+
442
+ // src/commands/share.ts
443
+ function terminalLink(url, text) {
444
+ const displayText = text || url;
445
+ const OSC = "\x1B]8;;";
446
+ const ST = "\x1B\\";
447
+ return `${OSC}${url}${ST}${chalk.cyan.underline(displayText)}${OSC}${ST}`;
448
+ }
449
+ var metadata = {
450
+ command: "/share",
451
+ description: "Share current session via public URL",
452
+ implemented: true
453
+ };
454
+ async function execute(_args, context) {
455
+ if (context?.config?.share?.enabled === false) {
456
+ console.log(chalk.yellow("Session sharing is disabled."));
457
+ console.log(
458
+ chalk.gray("To enable, set share.enabled: true in your config file.")
459
+ );
460
+ return;
461
+ }
462
+ if (!context?.currentSession) {
463
+ console.log(chalk.yellow("No active session to share."));
464
+ console.log(
465
+ chalk.gray("Start a conversation first, then use /share to share it.")
466
+ );
467
+ return;
468
+ }
469
+ const session = context.currentSession;
470
+ const messages = session.getMessages();
471
+ if (messages.length === 0) {
472
+ console.log(chalk.yellow("Session has no messages to share."));
473
+ return;
474
+ }
475
+ const client = getShareApiClient();
476
+ const deviceId = await client.getDeviceId();
477
+ const totalTokens = context.getTotalTokensUsed?.() ?? 0;
478
+ const duration = calculateDuration2(session.metadata.createdAt);
479
+ console.log();
480
+ console.log(chalk.bold("Session Summary"));
481
+ console.log(chalk.gray("\u2500".repeat(40)));
482
+ console.log(` Project: ${chalk.cyan(session.metadata.projectName)}`);
483
+ console.log(` Model: ${chalk.cyan(context.model)}`);
484
+ console.log(` Messages: ${chalk.cyan(messages.length)}`);
485
+ console.log(` Tokens: ${chalk.cyan(formatTokens(totalTokens))}`);
486
+ console.log(
487
+ ` Est. Cost: ${chalk.green(formatCost(totalTokens / 1e3 * 3e-3))}`
488
+ );
489
+ console.log(` Duration: ${chalk.cyan(formatDuration(duration))}`);
490
+ console.log();
491
+ const { Select, Confirm } = enquirer;
492
+ const visibilityPrompt = new Select({
493
+ name: "visibility",
494
+ message: "Share visibility:",
495
+ choices: [
496
+ { name: "public", message: "Public - Anyone with the link can view" },
497
+ { name: "private", message: "Private - Requires one-time passcode" }
498
+ ]
499
+ });
500
+ let visibility;
501
+ try {
502
+ visibility = await visibilityPrompt.run();
503
+ } catch {
504
+ console.log(chalk.gray("Cancelled."));
505
+ return;
506
+ }
507
+ const confirmPrompt = new Confirm({
508
+ name: "confirm",
509
+ message: `Share this session as ${visibility}?`,
510
+ initial: true
511
+ });
512
+ let confirmed;
513
+ try {
514
+ confirmed = await confirmPrompt.run();
515
+ } catch {
516
+ console.log(chalk.gray("Cancelled."));
517
+ return;
518
+ }
519
+ if (!confirmed) {
520
+ console.log(chalk.gray("Cancelled."));
521
+ return;
522
+ }
523
+ console.log();
524
+ const spinner = ora("Uploading session...").start();
525
+ try {
526
+ const payload = serializeSession(session, {
527
+ model: context.model,
528
+ provider: context.provider,
529
+ totalTokens,
530
+ visibility,
531
+ deviceId
532
+ });
533
+ const response = await client.createShare(payload);
534
+ spinner.stop();
535
+ if (response.success && response.url) {
536
+ console.log();
537
+ console.log(chalk.green.bold("Session shared successfully!"));
538
+ console.log();
539
+ console.log(`${chalk.bold("URL:")} ${terminalLink(response.url)}`);
540
+ if (visibility === "private" && response.passcode) {
541
+ console.log();
542
+ console.log(`${chalk.bold("Passcode:")} ${chalk.yellow.bold(response.passcode)}`);
543
+ console.log(
544
+ chalk.gray(" Share this passcode with people who need access.")
545
+ );
546
+ }
547
+ console.log();
548
+ console.log(chalk.gray("Tip: Click the URL or copy it to share with others!"));
549
+ console.log();
550
+ } else {
551
+ console.log();
552
+ console.log(
553
+ chalk.red(`Failed to share: ${response.error || "Unknown error"}`)
554
+ );
555
+ console.log();
556
+ }
557
+ } catch (error) {
558
+ spinner.stop();
559
+ console.log();
560
+ console.log(chalk.red(`Failed to share: ${error.message}`));
561
+ console.log();
562
+ }
563
+ }
564
+ function calculateDuration2(startedAt) {
565
+ const start = new Date(startedAt).getTime();
566
+ const now = Date.now();
567
+ return Math.max(0, Math.floor((now - start) / 1e3));
568
+ }
569
+
570
+ export {
571
+ metadata,
572
+ execute
573
+ };
574
+ /**
575
+ * @license
576
+ * Copyright 2025 Autohand AI LLC
577
+ * SPDX-License-Identifier: Apache-2.0
578
+ *
579
+ * Cost Estimator
580
+ * Simplified token cost estimation for session sharing
581
+ */
582
+ /**
583
+ * @license
584
+ * Copyright 2025 Autohand AI LLC
585
+ * SPDX-License-Identifier: Apache-2.0
586
+ *
587
+ * Session Serializer
588
+ * Converts session data to ShareSessionPayload format
589
+ */
590
+ /**
591
+ * @license
592
+ * Copyright 2025 Autohand AI LLC
593
+ * SPDX-License-Identifier: Apache-2.0
594
+ *
595
+ * Share API Client
596
+ * Handles communication with autohand.link for session sharing
597
+ */
598
+ /**
599
+ * @license
600
+ * Copyright 2025 Autohand AI LLC
601
+ * SPDX-License-Identifier: Apache-2.0
602
+ *
603
+ * Share Module
604
+ * Session sharing functionality
605
+ */
606
+ /**
607
+ * @license
608
+ * Copyright 2025 Autohand AI LLC
609
+ * SPDX-License-Identifier: Apache-2.0
610
+ *
611
+ * /share Command
612
+ * Share current session via public URL
613
+ */
@@ -0,0 +1,102 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// package.json
2
+ var package_default = {
3
+ name: "autohand-cli",
4
+ version: "0.7.6",
5
+ license: "Apache-2.0",
6
+ description: "Autohand interactive coding agent CLI powered by LLMs.",
7
+ repository: {
8
+ type: "git",
9
+ url: "https://github.com/autohandai/code-cli.git"
10
+ },
11
+ homepage: "https://autohand.ai/cli/",
12
+ bugs: {
13
+ url: "https://github.com/autohandai/code-cli/issues"
14
+ },
15
+ type: "module",
16
+ bin: {
17
+ autohand: "dist/index.js"
18
+ },
19
+ main: "dist/index.js",
20
+ files: [
21
+ "dist"
22
+ ],
23
+ scripts: {
24
+ go: 'bun run build && ./install-local.sh && echo "COMPLETED"',
25
+ build: "tsup",
26
+ dev: "bun src/index.ts",
27
+ typecheck: "tsc --noEmit",
28
+ lint: "eslint .",
29
+ test: "vitest run",
30
+ start: "node dist/index.js",
31
+ "compile:macos-arm64": "bun build ./src/index.ts --compile --target=bun-darwin-arm64 --external react-devtools-core --outfile ./binaries/autohand-macos-arm64",
32
+ "compile:macos-x64": "bun build ./src/index.ts --compile --target=bun-darwin-x64 --external react-devtools-core --outfile ./binaries/autohand-macos-x64",
33
+ "compile:linux-x64": "bun build ./src/index.ts --compile --target=bun-linux-x64 --external react-devtools-core --outfile ./binaries/autohand-linux-x64",
34
+ "compile:linux-arm64": "bun build ./src/index.ts --compile --target=bun-linux-arm64 --external react-devtools-core --outfile ./binaries/autohand-linux-arm64",
35
+ "compile:windows-x64": "bun build ./src/index.ts --compile --target=bun-windows-x64 --external react-devtools-core --outfile ./binaries/autohand-windows-x64.exe",
36
+ "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",
37
+ link: "bun link"
38
+ },
39
+ keywords: [
40
+ "cli",
41
+ "llm",
42
+ "agent",
43
+ "autohand"
44
+ ],
45
+ engines: {
46
+ node: ">=18.17.0"
47
+ },
48
+ dependencies: {
49
+ chalk: "^5.6.2",
50
+ commander: "^14.0.2",
51
+ diff: "^8.0.2",
52
+ dotenv: "^17.2.3",
53
+ enquirer: "^2.4.1",
54
+ "fs-extra": "^11.3.2",
55
+ ignore: "^5.3.1",
56
+ ink: "^4.4.1",
57
+ "ink-spinner": "^5.0.0",
58
+ minimatch: "^10.1.1",
59
+ open: "^10.1.0",
60
+ ora: "^9.0.0",
61
+ react: "^18.2.0",
62
+ "react-devtools-core": "^7.0.1",
63
+ "terminal-link": "^3.0.0",
64
+ yaml: "^2.8.2",
65
+ zod: "^4.1.12"
66
+ },
67
+ devDependencies: {
68
+ "@types/diff": "^8.0.0",
69
+ "@types/fs-extra": "^11.0.4",
70
+ "@types/minimatch": "^6.0.0",
71
+ "@types/node": "^24.10.1",
72
+ "@types/react": "^18.3.3",
73
+ "@types/terminal-link": "^1.2.0",
74
+ "@typescript-eslint/eslint-plugin": "^8.48.1",
75
+ "@typescript-eslint/parser": "^8.48.1",
76
+ eslint: "^9.39.1",
77
+ memfs: "^4.51.1",
78
+ tsup: "^8.5.1",
79
+ tsx: "^4.20.6",
80
+ typescript: "^5.9.3",
81
+ vitest: "^1.6.0"
82
+ },
83
+ overrides: {
84
+ ink: {
85
+ "slice-ansi": {
86
+ "ansi-styles": "^6.2.1"
87
+ },
88
+ "wrap-ansi": {
89
+ "ansi-styles": "^6.2.1"
90
+ },
91
+ "cli-truncate": {
92
+ "slice-ansi": {
93
+ "ansi-styles": "^6.2.1"
94
+ }
95
+ }
96
+ }
97
+ }
98
+ };
99
+
100
+
101
+
102
+ exports.package_default = package_default;