@lovelybunch/cli 1.0.75-alpha.8 → 1.0.75
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/cli.js +5 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/events.js +3 -3
- package/dist/commands/events.js.map +1 -1
- package/dist/commands/implement.d.ts.map +1 -1
- package/dist/commands/implement.js +31 -25
- package/dist/commands/implement.js.map +1 -1
- package/dist/commands/init.js +2 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +23 -23
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/mail.d.ts +3 -0
- package/dist/commands/mail.d.ts.map +1 -0
- package/dist/commands/mail.js +274 -0
- package/dist/commands/mail.js.map +1 -0
- package/dist/commands/notify.d.ts +3 -0
- package/dist/commands/notify.d.ts.map +1 -0
- package/dist/commands/notify.js +36 -0
- package/dist/commands/notify.js.map +1 -0
- package/dist/commands/propose.js +18 -18
- package/dist/commands/propose.js.map +1 -1
- package/dist/commands/resource.d.ts.map +1 -1
- package/dist/commands/resource.js +96 -14
- package/dist/commands/resource.js.map +1 -1
- package/dist/commands/schema.js +2 -2
- package/dist/commands/schema.js.map +1 -1
- package/dist/commands/show.d.ts.map +1 -1
- package/dist/commands/show.js +33 -67
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/task.d.ts.map +1 -1
- package/dist/commands/task.js +87 -64
- package/dist/commands/task.js.map +1 -1
- package/package.json +4 -5
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { table } from 'table';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import { listMail, getMail, setMailStatus, replyToMail, addMailAction, } from '@lovelybunch/core';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Helpers
|
|
9
|
+
// ============================================================================
|
|
10
|
+
const VALID_FOLDERS = ['inbox', 'read', 'sent'];
|
|
11
|
+
function validateFolder(folder) {
|
|
12
|
+
const normalized = folder.toLowerCase();
|
|
13
|
+
if (!VALID_FOLDERS.includes(normalized)) {
|
|
14
|
+
throw new Error(`Invalid folder "${folder}". Must be one of: ${VALID_FOLDERS.join(', ')}`);
|
|
15
|
+
}
|
|
16
|
+
return normalized;
|
|
17
|
+
}
|
|
18
|
+
function truncate(str, maxLen) {
|
|
19
|
+
if (str.length <= maxLen)
|
|
20
|
+
return str;
|
|
21
|
+
return str.slice(0, maxLen - 1) + '…';
|
|
22
|
+
}
|
|
23
|
+
function formatDate(dateStr) {
|
|
24
|
+
if (!dateStr)
|
|
25
|
+
return '-';
|
|
26
|
+
try {
|
|
27
|
+
const date = new Date(dateStr);
|
|
28
|
+
return date.toLocaleDateString('en-US', {
|
|
29
|
+
month: 'short',
|
|
30
|
+
day: 'numeric',
|
|
31
|
+
hour: '2-digit',
|
|
32
|
+
minute: '2-digit',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return dateStr;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// Parent Command
|
|
41
|
+
// ============================================================================
|
|
42
|
+
export const mailCommand = new Command('mail')
|
|
43
|
+
.description('Manage emails')
|
|
44
|
+
.addHelpText('after', `
|
|
45
|
+
Examples:
|
|
46
|
+
${chalk.gray('# List emails in inbox (default)')}
|
|
47
|
+
nut mail list
|
|
48
|
+
nut mail list read
|
|
49
|
+
nut mail list sent
|
|
50
|
+
|
|
51
|
+
${chalk.gray('# View a specific email')}
|
|
52
|
+
nut mail get <id>
|
|
53
|
+
|
|
54
|
+
${chalk.gray('# Mark email as read or unread')}
|
|
55
|
+
nut mail set <id> --status read
|
|
56
|
+
nut mail set <id> --status unread
|
|
57
|
+
|
|
58
|
+
${chalk.gray('# Add an agent action summary to an email')}
|
|
59
|
+
nut mail action <id> "Summary of actions taken"
|
|
60
|
+
|
|
61
|
+
${chalk.gray('# Reply to an email')}
|
|
62
|
+
nut mail reply <id>
|
|
63
|
+
|
|
64
|
+
${chalk.gray('# Send an email (coming soon)')}
|
|
65
|
+
nut mail send
|
|
66
|
+
`);
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// mail list [folder]
|
|
69
|
+
// ============================================================================
|
|
70
|
+
mailCommand
|
|
71
|
+
.command('list')
|
|
72
|
+
.description('List emails in a folder (default: inbox)')
|
|
73
|
+
.argument('[folder]', 'Folder to list (inbox, read, sent)', 'inbox')
|
|
74
|
+
.option('--json', 'Output as JSON')
|
|
75
|
+
.action(async (folder, options) => {
|
|
76
|
+
const spinner = ora('Loading emails...').start();
|
|
77
|
+
try {
|
|
78
|
+
const validFolder = validateFolder(folder);
|
|
79
|
+
const messages = await listMail(validFolder);
|
|
80
|
+
spinner.stop();
|
|
81
|
+
if (options.json) {
|
|
82
|
+
console.log(JSON.stringify(messages, null, 2));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (messages.length === 0) {
|
|
86
|
+
console.log(chalk.gray(`No emails in ${validFolder}.`));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
console.log(chalk.bold(`\n📧 ${validFolder.charAt(0).toUpperCase() + validFolder.slice(1)} (${messages.length})\n`));
|
|
90
|
+
const tableData = [
|
|
91
|
+
[
|
|
92
|
+
chalk.bold('ID'),
|
|
93
|
+
chalk.bold('From'),
|
|
94
|
+
chalk.bold('Subject'),
|
|
95
|
+
chalk.bold('Date'),
|
|
96
|
+
],
|
|
97
|
+
...messages.map((msg) => [
|
|
98
|
+
chalk.cyan(truncate(msg.id, 20)),
|
|
99
|
+
truncate(msg.from, 30),
|
|
100
|
+
truncate(msg.subject, 40),
|
|
101
|
+
chalk.gray(formatDate(msg.receivedAt)),
|
|
102
|
+
]),
|
|
103
|
+
];
|
|
104
|
+
console.log(table(tableData, {
|
|
105
|
+
border: {
|
|
106
|
+
topBody: '',
|
|
107
|
+
topJoin: '',
|
|
108
|
+
topLeft: '',
|
|
109
|
+
topRight: '',
|
|
110
|
+
bottomBody: '',
|
|
111
|
+
bottomJoin: '',
|
|
112
|
+
bottomLeft: '',
|
|
113
|
+
bottomRight: '',
|
|
114
|
+
bodyLeft: '',
|
|
115
|
+
bodyRight: '',
|
|
116
|
+
bodyJoin: ' ',
|
|
117
|
+
joinBody: '',
|
|
118
|
+
joinLeft: '',
|
|
119
|
+
joinRight: '',
|
|
120
|
+
joinJoin: '',
|
|
121
|
+
},
|
|
122
|
+
drawHorizontalLine: () => false,
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
spinner.fail('Failed to list emails');
|
|
127
|
+
console.error(chalk.red('Error:'), error.message);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
// ============================================================================
|
|
132
|
+
// mail get <id>
|
|
133
|
+
// ============================================================================
|
|
134
|
+
mailCommand
|
|
135
|
+
.command('get')
|
|
136
|
+
.description('View a specific email')
|
|
137
|
+
.argument('<id>', 'Email ID')
|
|
138
|
+
.option('--json', 'Output as JSON')
|
|
139
|
+
.action(async (id, options) => {
|
|
140
|
+
const spinner = ora('Loading email...').start();
|
|
141
|
+
try {
|
|
142
|
+
const message = await getMail(id);
|
|
143
|
+
spinner.stop();
|
|
144
|
+
if (!message) {
|
|
145
|
+
console.error(chalk.red(`Email "${id}" not found.`));
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
if (options.json) {
|
|
149
|
+
console.log(JSON.stringify(message, null, 2));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
console.log('');
|
|
153
|
+
console.log(chalk.bold('Subject: ') + message.subject);
|
|
154
|
+
console.log(chalk.bold('From: ') + message.from);
|
|
155
|
+
console.log(chalk.bold('To: ') + message.to.join(', '));
|
|
156
|
+
if (message.cc.length > 0) {
|
|
157
|
+
console.log(chalk.bold('CC: ') + message.cc.join(', '));
|
|
158
|
+
}
|
|
159
|
+
console.log(chalk.bold('Date: ') + formatDate(message.receivedAt));
|
|
160
|
+
console.log(chalk.bold('Folder: ') + message.folder);
|
|
161
|
+
console.log(chalk.bold('ID: ') + chalk.gray(message.id));
|
|
162
|
+
if (message.attachments.length > 0) {
|
|
163
|
+
console.log(chalk.bold('Attach: ') + message.attachments.map(a => a.filename).join(', '));
|
|
164
|
+
}
|
|
165
|
+
console.log(chalk.gray('\n' + '─'.repeat(60) + '\n'));
|
|
166
|
+
console.log(message.content || chalk.gray('(no body)'));
|
|
167
|
+
console.log('');
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
spinner.fail('Failed to load email');
|
|
171
|
+
console.error(chalk.red('Error:'), error.message);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
// ============================================================================
|
|
176
|
+
// mail set <id> --status <read|unread>
|
|
177
|
+
// ============================================================================
|
|
178
|
+
mailCommand
|
|
179
|
+
.command('set')
|
|
180
|
+
.description('Set email status (read or unread)')
|
|
181
|
+
.argument('<id>', 'Email ID')
|
|
182
|
+
.requiredOption('-s, --status <status>', 'Status to set: "read" or "unread"')
|
|
183
|
+
.action(async (id, options) => {
|
|
184
|
+
const status = options.status.toLowerCase();
|
|
185
|
+
if (status !== 'read' && status !== 'unread') {
|
|
186
|
+
console.error(chalk.red('Error: --status must be "read" or "unread"'));
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
const spinner = ora(`Marking email as ${status}...`).start();
|
|
190
|
+
try {
|
|
191
|
+
const message = await setMailStatus(id, status);
|
|
192
|
+
spinner.succeed(chalk.green(`Email marked as ${status} (now in ${message.folder})`));
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
spinner.fail(`Failed to set email status`);
|
|
196
|
+
console.error(chalk.red('Error:'), error.message);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// mail reply <id>
|
|
202
|
+
// ============================================================================
|
|
203
|
+
mailCommand
|
|
204
|
+
.command('reply')
|
|
205
|
+
.description('Reply to an email')
|
|
206
|
+
.argument('<id>', 'Email ID to reply to')
|
|
207
|
+
.option('-m, --message <message>', 'Reply message (skips interactive prompt)')
|
|
208
|
+
.action(async (id, options) => {
|
|
209
|
+
try {
|
|
210
|
+
const original = await getMail(id);
|
|
211
|
+
if (!original) {
|
|
212
|
+
console.error(chalk.red(`Email "${id}" not found.`));
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
console.log('');
|
|
216
|
+
console.log(chalk.gray(`Replying to: ${original.subject}`));
|
|
217
|
+
console.log(chalk.gray(`From: ${original.from}`));
|
|
218
|
+
console.log('');
|
|
219
|
+
let replyContent = options.message;
|
|
220
|
+
if (!replyContent) {
|
|
221
|
+
const answers = await inquirer.prompt([
|
|
222
|
+
{
|
|
223
|
+
type: 'editor',
|
|
224
|
+
name: 'content',
|
|
225
|
+
message: 'Write your reply:',
|
|
226
|
+
},
|
|
227
|
+
]);
|
|
228
|
+
replyContent = answers.content;
|
|
229
|
+
}
|
|
230
|
+
if (!replyContent || replyContent.trim().length === 0) {
|
|
231
|
+
console.log(chalk.yellow('Reply cancelled (empty message).'));
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const spinner = ora('Sending reply...').start();
|
|
235
|
+
const reply = await replyToMail(id, { content: replyContent });
|
|
236
|
+
spinner.succeed(chalk.green(`Reply saved to sent folder (${reply.id})`));
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
console.error(chalk.red('Error:'), error.message);
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
// ============================================================================
|
|
244
|
+
// mail action <id> <message>
|
|
245
|
+
// ============================================================================
|
|
246
|
+
mailCommand
|
|
247
|
+
.command('action')
|
|
248
|
+
.description('Add an agent action summary to an email')
|
|
249
|
+
.argument('<id>', 'Email ID')
|
|
250
|
+
.argument('<message>', 'Action summary message')
|
|
251
|
+
.action(async (id, message) => {
|
|
252
|
+
const spinner = ora('Adding action to email...').start();
|
|
253
|
+
try {
|
|
254
|
+
const updated = await addMailAction(id, message);
|
|
255
|
+
spinner.succeed(chalk.green(`Action added to email "${id}" (${updated.folder})`));
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
spinner.fail('Failed to add action');
|
|
259
|
+
console.error(chalk.red('Error:'), error.message);
|
|
260
|
+
process.exit(1);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
// ============================================================================
|
|
264
|
+
// mail send
|
|
265
|
+
// ============================================================================
|
|
266
|
+
mailCommand
|
|
267
|
+
.command('send')
|
|
268
|
+
.description('Send an email (coming soon)')
|
|
269
|
+
.action(async () => {
|
|
270
|
+
console.log(chalk.yellow('\n📧 Send email is coming soon.\n'));
|
|
271
|
+
console.log(chalk.gray('This feature will allow you to compose and send emails directly from the CLI.'));
|
|
272
|
+
console.log(chalk.gray('Stay tuned for updates!\n'));
|
|
273
|
+
});
|
|
274
|
+
//# sourceMappingURL=mail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail.js","sourceRoot":"","sources":["../../src/commands/mail.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/commands/notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,aAAa,SASxB,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { getSlackService } from '@lovelybunch/core';
|
|
5
|
+
export const notifyCommand = new Command('notify')
|
|
6
|
+
.description('Send notifications to external services')
|
|
7
|
+
.addHelpText('after', `
|
|
8
|
+
Examples:
|
|
9
|
+
${chalk.gray('# Send a message to Slack')}
|
|
10
|
+
nut notify slack "Deployment to staging complete"
|
|
11
|
+
|
|
12
|
+
${chalk.gray('# Send with a title')}
|
|
13
|
+
nut notify slack "All systems operational" --title "Health Check"
|
|
14
|
+
`);
|
|
15
|
+
// nut notify slack <message>
|
|
16
|
+
notifyCommand
|
|
17
|
+
.command('slack')
|
|
18
|
+
.description('Send a message to the configured Slack channel')
|
|
19
|
+
.argument('<message>', 'Message text to send')
|
|
20
|
+
.option('-t, --title <title>', 'Optional bold title/heading for the message')
|
|
21
|
+
.action(async (message, options) => {
|
|
22
|
+
const spinner = ora('Sending Slack message...').start();
|
|
23
|
+
try {
|
|
24
|
+
const slackService = getSlackService();
|
|
25
|
+
await slackService.sendFreeformMessage(message, {
|
|
26
|
+
title: options.title,
|
|
27
|
+
});
|
|
28
|
+
spinner.succeed(chalk.green('Message sent to Slack'));
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
spinner.fail('Failed to send Slack message');
|
|
32
|
+
console.error(chalk.red('Error:'), error.message);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/commands/notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,yCAAyC,CAAC;KACtD,WAAW,CAAC,OAAO,EAAE;;IAEpB,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC;;;IAGvC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC;;CAEpC,CAAC,CAAC;AAEH,6BAA6B;AAC7B,aAAa;KACV,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,gDAAgD,CAAC;KAC7D,QAAQ,CAAC,WAAW,EAAE,sBAAsB,CAAC;KAC7C,MAAM,CAAC,qBAAqB,EAAE,6CAA6C,CAAC;KAC5E,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,OAA2B,EAAE,EAAE;IAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,0BAA0B,CAAC,CAAC,KAAK,EAAE,CAAC;IAExD,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;QACvC,MAAM,YAAY,CAAC,mBAAmB,CAAC,OAAO,EAAE;YAC9C,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC;QAEH,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
package/dist/commands/propose.js
CHANGED
|
@@ -3,7 +3,7 @@ import chalk from 'chalk';
|
|
|
3
3
|
import ora from 'ora';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
5
|
import { promises as fs } from 'fs';
|
|
6
|
-
import {
|
|
6
|
+
import { createTask } from '@lovelybunch/core';
|
|
7
7
|
import os from 'os';
|
|
8
8
|
const VALID_PRIORITIES = ['low', 'medium', 'high', 'critical'];
|
|
9
9
|
function parseTags(tagsString) {
|
|
@@ -32,18 +32,18 @@ function interpretEscapeSequences(str) {
|
|
|
32
32
|
.replace(/\\\\/g, '\\');
|
|
33
33
|
}
|
|
34
34
|
export const proposeCommand = new Command('propose')
|
|
35
|
-
.description('Create a new
|
|
36
|
-
.argument('<intent>', 'The intent of the
|
|
35
|
+
.description('Create a new task (deprecated: use "nut task create")')
|
|
36
|
+
.argument('<intent>', 'The intent of the task')
|
|
37
37
|
.option('--author <name>', 'Author name')
|
|
38
38
|
.option('--email <email>', 'Author email')
|
|
39
39
|
.option('--type <type>', 'Author type (human/agent)', 'human')
|
|
40
|
-
.option('--description <text>', 'Detailed description or context for the
|
|
40
|
+
.option('--description <text>', 'Detailed description or context for the task')
|
|
41
41
|
.option('--file <path>', 'Read description from a file')
|
|
42
42
|
.option('--tags <tags>', 'Comma-separated tags (e.g., "ui,feature,priority")')
|
|
43
43
|
.option('--priority <level>', 'Priority (low|medium|high|critical)')
|
|
44
44
|
.option('--spec <ref>', 'Product specification reference')
|
|
45
45
|
.action(async (intent, options) => {
|
|
46
|
-
const spinner = ora('Creating
|
|
46
|
+
const spinner = ora('Creating task...').start();
|
|
47
47
|
try {
|
|
48
48
|
// Get author information
|
|
49
49
|
spinner.stop();
|
|
@@ -90,9 +90,9 @@ export const proposeCommand = new Command('propose')
|
|
|
90
90
|
// Parse and validate options
|
|
91
91
|
const tags = parseTags(options.tags);
|
|
92
92
|
const priority = validatePriority(options.priority);
|
|
93
|
-
spinner.start('Creating
|
|
94
|
-
// Create the
|
|
95
|
-
const
|
|
93
|
+
spinner.start('Creating task...');
|
|
94
|
+
// Create the task (directly persisted to storage)
|
|
95
|
+
const task = await createTask({
|
|
96
96
|
intent,
|
|
97
97
|
content: content || intent, // Use intent as content if no description provided
|
|
98
98
|
author,
|
|
@@ -103,12 +103,12 @@ export const proposeCommand = new Command('propose')
|
|
|
103
103
|
},
|
|
104
104
|
productSpecRef: options.spec,
|
|
105
105
|
});
|
|
106
|
-
spinner.succeed(`
|
|
107
|
-
console.log('\n' + chalk.bold('
|
|
108
|
-
console.log(' ID: ' + chalk.cyan(
|
|
109
|
-
console.log(' Title: ' + chalk.white(
|
|
106
|
+
spinner.succeed(`Task created: ${chalk.cyan(task.id)}`);
|
|
107
|
+
console.log('\n' + chalk.bold('Task Details:'));
|
|
108
|
+
console.log(' ID: ' + chalk.cyan(task.id));
|
|
109
|
+
console.log(' Title: ' + chalk.white(task.title || task.intent));
|
|
110
110
|
console.log(' Author: ' + chalk.white(`${author.name} (${author.type})`));
|
|
111
|
-
console.log(' Status: ' + chalk.yellow(
|
|
111
|
+
console.log(' Status: ' + chalk.yellow(task.status));
|
|
112
112
|
if (priority) {
|
|
113
113
|
const priorityColors = {
|
|
114
114
|
low: chalk.gray,
|
|
@@ -127,14 +127,14 @@ export const proposeCommand = new Command('propose')
|
|
|
127
127
|
if (content) {
|
|
128
128
|
console.log(' Content: ' + chalk.gray(`${content.length} characters`));
|
|
129
129
|
}
|
|
130
|
-
console.log(' Created: ' + chalk.gray(
|
|
130
|
+
console.log(' Created: ' + chalk.gray(task.metadata.createdAt.toLocaleString()));
|
|
131
131
|
console.log('\n' + chalk.cyan('Next steps:'));
|
|
132
|
-
console.log(' • View
|
|
133
|
-
console.log(' • Add plan steps: ' + chalk.yellow(`nut
|
|
134
|
-
console.log(' • List all
|
|
132
|
+
console.log(' • View task details: ' + chalk.yellow(`nut show ${task.id}`));
|
|
133
|
+
console.log(' • Add plan steps: ' + chalk.yellow(`nut task step ${task.id}`));
|
|
134
|
+
console.log(' • List all tasks: ' + chalk.yellow('nut task list'));
|
|
135
135
|
}
|
|
136
136
|
catch (error) {
|
|
137
|
-
spinner.fail('Failed to create
|
|
137
|
+
spinner.fail('Failed to create task');
|
|
138
138
|
console.error(chalk.red('Error:'), error);
|
|
139
139
|
process.exit(1);
|
|
140
140
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"propose.js","sourceRoot":"","sources":["../../src/commands/propose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"propose.js","sourceRoot":"","sources":["../../src/commands/propose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAU,CAAC;AAGxE,SAAS,SAAS,CAAC,UAA8B;IAC/C,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,IAAI,GAAG,UAAU;SACpB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;SACtB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5C,CAAC;AAED,SAAS,gBAAgB,CAAC,QAA4B;IACpD,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChC,MAAM,UAAU,GAAG,QAAQ,CAAC,WAAW,EAAc,CAAC;IACtD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,sBAAsB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,wBAAwB,CAAC,GAAW;IAC3C,OAAO,GAAG;SACP,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;SACrB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;SACrB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,uDAAuD,CAAC;KACpE,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;KAC9C,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC;KACxC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC;KACzC,MAAM,CAAC,eAAe,EAAE,2BAA2B,EAAE,OAAO,CAAC;KAC7D,MAAM,CAAC,sBAAsB,EAAE,8CAA8C,CAAC;KAC9E,MAAM,CAAC,eAAe,EAAE,8BAA8B,CAAC;KACvD,MAAM,CAAC,eAAe,EAAE,oDAAoD,CAAC;KAC7E,MAAM,CAAC,oBAAoB,EAAE,qCAAqC,CAAC;KACnE,MAAM,CAAC,cAAc,EAAE,iCAAiC,CAAC;KACzD,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,OAAO,EAAE,EAAE;IACxC,MAAM,OAAO,GAAG,GAAG,CAAC,kBAAkB,CAAC,CAAC,KAAK,EAAE,CAAC;IAEhD,IAAI,CAAC;QACH,yBAAyB;QACzB,OAAO,CAAC,IAAI,EAAE,CAAC;QAEf,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YACvC;gBACE,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,cAAc;gBACvB,OAAO,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ;gBACjD,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM;aACtB;YACD;gBACE,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,eAAe;gBACxB,OAAO,EAAE,OAAO,CAAC,KAAK;gBACtB,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK;aACrB;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,GAAW;YACrB,IAAI,EAAE,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;YAClD,EAAE,EAAE,UAAU,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,IAAI,GAAG,UAAU,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,QAAQ;YACrF,IAAI,EAAE,UAAU,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ;YACjE,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK;SACzC,CAAC;QAEF,kEAAkE;QAClE,IAAI,OAA2B,CAAC;QAChC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,4BAA4B,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC;YAC7D,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;gBACrD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,CAAC;aAAM,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YAC/B,oEAAoE;YACpE,OAAO,GAAG,wBAAwB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1D,CAAC;QAED,6BAA6B;QAC7B,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAEpD,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAElC,kDAAkD;QAClD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC;YAC5B,MAAM;YACN,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,mDAAmD;YAC/E,MAAM;YACN,MAAM,EAAE,OAAO;YACf,QAAQ,EAAE;gBACR,IAAI;gBACJ,QAAQ;aACT;YACD,cAAc,EAAE,OAAO,CAAC,IAAI;SAC7B,CAAC,CAAC;QAEH,OAAO,CAAC,OAAO,CAAC,iBAAiB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAExD,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACxD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,cAAc,GAAyC;gBAC3D,GAAG,EAAE,KAAK,CAAC,IAAI;gBACf,MAAM,EAAE,KAAK,CAAC,IAAI;gBAClB,IAAI,EAAE,KAAK,CAAC,MAAM;gBAClB,QAAQ,EAAE,KAAK,CAAC,GAAG;aACpB,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,aAAa,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QAEnF,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,yBAAyB,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,KAAK,CAAC,MAAM,CAAC,iBAAiB,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACtC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/commands/resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/commands/resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2yCpC,QAAA,MAAM,QAAQ,SAEO,CAAC;AActB,OAAO,EAAE,QAAQ,IAAI,eAAe,EAAE,CAAC"}
|
|
@@ -798,10 +798,55 @@ Examples:
|
|
|
798
798
|
// ============================================================================
|
|
799
799
|
// Add Resource Command
|
|
800
800
|
// ============================================================================
|
|
801
|
+
/**
|
|
802
|
+
* Check if a string looks like a URL
|
|
803
|
+
*/
|
|
804
|
+
function isUrl(input) {
|
|
805
|
+
return /^https?:\/\//i.test(input);
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Download a URL to a temp file and return the temp path, filename, and MIME type.
|
|
809
|
+
* Caller is responsible for cleaning up the temp file/directory.
|
|
810
|
+
*/
|
|
811
|
+
async function downloadUrlToTemp(url) {
|
|
812
|
+
const response = await fetch(url);
|
|
813
|
+
if (!response.ok) {
|
|
814
|
+
throw new Error(`Failed to download ${url}: ${response.statusText}`);
|
|
815
|
+
}
|
|
816
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
817
|
+
const contentType = response.headers.get('content-type') || '';
|
|
818
|
+
// Derive a filename from the URL path, falling back to a timestamp-based name
|
|
819
|
+
const urlPath = new URL(url).pathname;
|
|
820
|
+
let fileName = path.basename(urlPath);
|
|
821
|
+
if (!fileName || fileName === '/' || !path.extname(fileName)) {
|
|
822
|
+
// Try to infer extension from content-type
|
|
823
|
+
const extMap = {
|
|
824
|
+
'image/png': '.png',
|
|
825
|
+
'image/jpeg': '.jpg',
|
|
826
|
+
'image/webp': '.webp',
|
|
827
|
+
'image/gif': '.gif',
|
|
828
|
+
'image/svg+xml': '.svg',
|
|
829
|
+
'audio/mpeg': '.mp3',
|
|
830
|
+
'audio/wav': '.wav',
|
|
831
|
+
'audio/ogg': '.ogg',
|
|
832
|
+
'video/mp4': '.mp4',
|
|
833
|
+
'video/webm': '.webm',
|
|
834
|
+
'application/pdf': '.pdf',
|
|
835
|
+
'application/json': '.json',
|
|
836
|
+
};
|
|
837
|
+
const ext = Object.entries(extMap).find(([ct]) => contentType.includes(ct))?.[1] || '.bin';
|
|
838
|
+
fileName = `downloaded-${Date.now()}${ext}`;
|
|
839
|
+
}
|
|
840
|
+
const mimeType = contentType.split(';')[0].trim() || getMimeType(fileName);
|
|
841
|
+
const tempDir = mkdtempSync(path.join(tmpdir(), 'coconut-add-'));
|
|
842
|
+
const tempFilePath = path.join(tempDir, fileName);
|
|
843
|
+
writeFileSync(tempFilePath, buffer);
|
|
844
|
+
return { tempDir, tempFilePath, fileName, mimeType };
|
|
845
|
+
}
|
|
801
846
|
const addResourceCommand = new Command('add')
|
|
802
|
-
.description('Upload a file to resources')
|
|
847
|
+
.description('Upload a file or URL to resources')
|
|
803
848
|
.alias('upload')
|
|
804
|
-
.argument('<file...>', 'File path(s) to upload')
|
|
849
|
+
.argument('<file...>', 'File path(s) or URL(s) to upload')
|
|
805
850
|
.option('-t, --tags <tags>', 'Comma-separated tags')
|
|
806
851
|
.option('-d, --description <text>', 'Description of the resource')
|
|
807
852
|
.option('--json', 'Output as JSON')
|
|
@@ -811,6 +856,7 @@ Examples:
|
|
|
811
856
|
$ nut resource add ./screenshot.png
|
|
812
857
|
$ nut resource upload ./logo.svg -t "branding, logo" -d "Company logo"
|
|
813
858
|
$ nut resource add ./image1.png ./image2.png -t "batch"
|
|
859
|
+
$ nut resource add https://example.com/photo.png
|
|
814
860
|
$ nut resource add ./data.json --json
|
|
815
861
|
`)
|
|
816
862
|
.action(async (files, options) => {
|
|
@@ -822,18 +868,42 @@ Examples:
|
|
|
822
868
|
}
|
|
823
869
|
const results = [];
|
|
824
870
|
for (const filePath of files) {
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
871
|
+
let localPath;
|
|
872
|
+
let fileName;
|
|
873
|
+
let mimeType;
|
|
874
|
+
let tempDir = null;
|
|
875
|
+
if (isUrl(filePath)) {
|
|
876
|
+
// ── URL: download to temp file first ──
|
|
877
|
+
const spinner = ora(`Downloading ${filePath}...`).start();
|
|
878
|
+
try {
|
|
879
|
+
const downloaded = await downloadUrlToTemp(filePath);
|
|
880
|
+
tempDir = downloaded.tempDir;
|
|
881
|
+
localPath = downloaded.tempFilePath;
|
|
882
|
+
fileName = downloaded.fileName;
|
|
883
|
+
mimeType = downloaded.mimeType;
|
|
884
|
+
spinner.succeed(`Downloaded ${chalk.cyan(fileName)}`);
|
|
885
|
+
}
|
|
886
|
+
catch (error) {
|
|
887
|
+
spinner.fail('Failed to download URL');
|
|
888
|
+
console.error(chalk.red(error instanceof Error ? error.message : 'Unknown error'));
|
|
889
|
+
process.exit(1);
|
|
890
|
+
}
|
|
830
891
|
}
|
|
831
|
-
|
|
892
|
+
else {
|
|
893
|
+
// ── Local file ──
|
|
894
|
+
localPath = path.resolve(filePath);
|
|
895
|
+
if (!existsSync(localPath)) {
|
|
896
|
+
console.error(chalk.red(`File not found: ${localPath}`));
|
|
897
|
+
process.exit(1);
|
|
898
|
+
}
|
|
899
|
+
fileName = path.basename(filePath);
|
|
900
|
+
mimeType = getMimeType(localPath);
|
|
901
|
+
}
|
|
902
|
+
const uploadSpinner = ora(`Uploading ${fileName}...`).start();
|
|
832
903
|
try {
|
|
833
904
|
const formData = new FormData();
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
formData.set('file', file, path.basename(filePath));
|
|
905
|
+
const file = fileFromSync(localPath, mimeType);
|
|
906
|
+
formData.set('file', file, fileName);
|
|
837
907
|
if (options.tags) {
|
|
838
908
|
formData.set('tags', options.tags);
|
|
839
909
|
}
|
|
@@ -847,13 +917,13 @@ Examples:
|
|
|
847
917
|
const result = await response.json();
|
|
848
918
|
if (!response.ok || !result.success || !result.data) {
|
|
849
919
|
const errorMessage = result.error?.message || 'Upload failed';
|
|
850
|
-
|
|
920
|
+
uploadSpinner.fail(`Failed to upload ${fileName}`);
|
|
851
921
|
console.error(chalk.red(errorMessage));
|
|
852
922
|
process.exit(1);
|
|
853
923
|
}
|
|
854
924
|
const resource = result.data;
|
|
855
925
|
results.push(resource);
|
|
856
|
-
|
|
926
|
+
uploadSpinner.succeed(`Uploaded ${chalk.cyan(resource.name)}`);
|
|
857
927
|
if (!options.json) {
|
|
858
928
|
console.log();
|
|
859
929
|
console.log(` ${chalk.gray('ID:')} ${resource.id}`);
|
|
@@ -875,10 +945,22 @@ Examples:
|
|
|
875
945
|
}
|
|
876
946
|
}
|
|
877
947
|
catch (error) {
|
|
878
|
-
|
|
948
|
+
uploadSpinner.fail(`Failed to upload ${fileName}`);
|
|
879
949
|
console.error(chalk.red(error instanceof Error ? error.message : 'Unknown error'));
|
|
880
950
|
process.exit(1);
|
|
881
951
|
}
|
|
952
|
+
finally {
|
|
953
|
+
// Clean up temp directory if we downloaded from a URL
|
|
954
|
+
if (tempDir) {
|
|
955
|
+
try {
|
|
956
|
+
unlinkSync(localPath);
|
|
957
|
+
fs.rmdir(tempDir).catch(() => { });
|
|
958
|
+
}
|
|
959
|
+
catch {
|
|
960
|
+
// Ignore cleanup errors
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
882
964
|
}
|
|
883
965
|
if (options.json) {
|
|
884
966
|
console.log(JSON.stringify(results.length === 1 ? results[0] : results, null, 2));
|