@meet-ai/cli 0.0.9 → 0.0.11
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/index.js +282 -44
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19,22 +19,22 @@ async function withRetry(fn, options) {
|
|
|
19
19
|
const maxRetries = options?.maxRetries ?? 3;
|
|
20
20
|
const baseDelay = options?.baseDelay ?? 1000;
|
|
21
21
|
const shouldRetry = options?.shouldRetry ?? isRetryable;
|
|
22
|
-
let lastError;
|
|
22
|
+
let lastError = new Error("withRetry: no attempts made");
|
|
23
23
|
for (let attempt = 0;attempt <= maxRetries; attempt++) {
|
|
24
24
|
try {
|
|
25
25
|
return await fn();
|
|
26
|
-
} catch (
|
|
27
|
-
lastError =
|
|
28
|
-
if (attempt >= maxRetries || !shouldRetry(
|
|
29
|
-
throw
|
|
26
|
+
} catch (error) {
|
|
27
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
28
|
+
if (attempt >= maxRetries || !shouldRetry(error))
|
|
29
|
+
throw lastError;
|
|
30
30
|
const delay = baseDelay * 2 ** attempt;
|
|
31
31
|
console.error(JSON.stringify({
|
|
32
32
|
event: "retry",
|
|
33
33
|
attempt: attempt + 1,
|
|
34
34
|
delay_ms: delay,
|
|
35
|
-
error:
|
|
35
|
+
error: lastError.message
|
|
36
36
|
}));
|
|
37
|
-
await new Promise((
|
|
37
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
throw lastError;
|
|
@@ -43,7 +43,7 @@ var ATTACHMENTS_DIR = "/tmp/meet-ai-attachments";
|
|
|
43
43
|
var MAX_AGE_MS = 5 * 60 * 1000;
|
|
44
44
|
function cleanupOldAttachments() {
|
|
45
45
|
try {
|
|
46
|
-
const { readdirSync, statSync, unlinkSync } = __require("fs");
|
|
46
|
+
const { readdirSync, statSync, unlinkSync } = __require("node:fs");
|
|
47
47
|
const now = Date.now();
|
|
48
48
|
for (const entry of readdirSync(ATTACHMENTS_DIR)) {
|
|
49
49
|
try {
|
|
@@ -263,7 +263,7 @@ function createClient(baseUrl, apiKey) {
|
|
|
263
263
|
const err = await res.json().catch(() => ({}));
|
|
264
264
|
throw new Error(err.error ?? `HTTP ${res.status}`);
|
|
265
265
|
}
|
|
266
|
-
const { mkdirSync, writeFileSync } = await import("fs");
|
|
266
|
+
const { mkdirSync, writeFileSync } = await import("node:fs");
|
|
267
267
|
const dir = "/tmp/meet-ai-attachments";
|
|
268
268
|
mkdirSync(dir, { recursive: true });
|
|
269
269
|
const localPath = `${dir}/${attachmentId}-${filename}`;
|
|
@@ -281,13 +281,23 @@ function createClient(baseUrl, apiKey) {
|
|
|
281
281
|
throw new Error(err.error ?? `HTTP ${res.status}`);
|
|
282
282
|
}
|
|
283
283
|
return res.json();
|
|
284
|
+
},
|
|
285
|
+
async deleteRoom(roomId) {
|
|
286
|
+
const res = await fetch(`${baseUrl}/api/rooms/${roomId}`, {
|
|
287
|
+
method: "DELETE",
|
|
288
|
+
headers: headers()
|
|
289
|
+
});
|
|
290
|
+
if (!res.ok) {
|
|
291
|
+
const err = await res.json().catch(() => ({}));
|
|
292
|
+
throw new Error(err.error ?? `HTTP ${res.status}`);
|
|
293
|
+
}
|
|
284
294
|
}
|
|
285
295
|
};
|
|
286
296
|
}
|
|
287
297
|
|
|
288
298
|
// src/inbox-router.ts
|
|
289
|
-
import { readFileSync, writeFileSync, mkdirSync, statSync } from "fs";
|
|
290
|
-
import { dirname } from "path";
|
|
299
|
+
import { readFileSync, writeFileSync, mkdirSync, statSync } from "node:fs";
|
|
300
|
+
import { dirname } from "node:path";
|
|
291
301
|
var IDLE_CHECK_INTERVAL_MS = 60000;
|
|
292
302
|
var IDLE_THRESHOLD_MS = 5 * 60 * 1000;
|
|
293
303
|
function appendToInbox(path, entry) {
|
|
@@ -338,9 +348,115 @@ function checkIdleAgents(inboxDir, members, excludeAgent, notified, now = Date.n
|
|
|
338
348
|
return newlyIdle;
|
|
339
349
|
}
|
|
340
350
|
|
|
351
|
+
// src/config.ts
|
|
352
|
+
import { readFileSync as readFileSync2, existsSync } from "node:fs";
|
|
353
|
+
import { join, resolve } from "node:path";
|
|
354
|
+
import { homedir } from "node:os";
|
|
355
|
+
function loadSettingsFromPath(path) {
|
|
356
|
+
try {
|
|
357
|
+
if (!existsSync(path)) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
const content = readFileSync2(path, "utf-8");
|
|
361
|
+
return JSON.parse(content);
|
|
362
|
+
} catch {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function getMeetAiConfig() {
|
|
367
|
+
if (process.env.MEET_AI_URL) {
|
|
368
|
+
return {
|
|
369
|
+
url: process.env.MEET_AI_URL,
|
|
370
|
+
key: process.env.MEET_AI_KEY
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
const projectSettingsPath = resolve("./.claude/settings.json");
|
|
374
|
+
const projectSettings = loadSettingsFromPath(projectSettingsPath);
|
|
375
|
+
if (projectSettings?.env?.MEET_AI_URL) {
|
|
376
|
+
return {
|
|
377
|
+
url: projectSettings.env.MEET_AI_URL,
|
|
378
|
+
key: projectSettings.env.MEET_AI_KEY
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
const userSettingsPath = join(homedir(), ".claude/settings.json");
|
|
382
|
+
const userSettings = loadSettingsFromPath(userSettingsPath);
|
|
383
|
+
if (userSettings?.env?.MEET_AI_URL) {
|
|
384
|
+
return {
|
|
385
|
+
url: userSettings.env.MEET_AI_URL,
|
|
386
|
+
key: userSettings.env.MEET_AI_KEY
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
url: "https://meet-ai.cc",
|
|
391
|
+
key: undefined
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/spawner.ts
|
|
396
|
+
import { spawn, execSync } from "node:child_process";
|
|
397
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
398
|
+
import { join as join2 } from "node:path";
|
|
399
|
+
import { homedir as homedir2, platform } from "node:os";
|
|
400
|
+
function findClaudeCli() {
|
|
401
|
+
try {
|
|
402
|
+
const command = platform() === "win32" ? "where claude" : "which claude";
|
|
403
|
+
const result = execSync(command, { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }).trim();
|
|
404
|
+
const claudePath = result.split(`
|
|
405
|
+
`)[0].trim();
|
|
406
|
+
if (claudePath && existsSync2(claudePath)) {
|
|
407
|
+
return claudePath;
|
|
408
|
+
}
|
|
409
|
+
} catch {}
|
|
410
|
+
const envPath = process.env.MEET_AI_CLAUDE_PATH;
|
|
411
|
+
if (envPath && existsSync2(envPath)) {
|
|
412
|
+
return envPath;
|
|
413
|
+
}
|
|
414
|
+
const home = homedir2();
|
|
415
|
+
const commonPaths = [
|
|
416
|
+
join2(home, ".bun", "bin", "claude"),
|
|
417
|
+
"/opt/homebrew/bin/claude",
|
|
418
|
+
"/usr/local/bin/claude",
|
|
419
|
+
join2(home, ".local", "bin", "claude")
|
|
420
|
+
];
|
|
421
|
+
for (const path of commonPaths) {
|
|
422
|
+
if (existsSync2(path)) {
|
|
423
|
+
return path;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
throw new Error(`
|
|
427
|
+
Claude Code is not installed
|
|
428
|
+
|
|
429
|
+
Please install Claude Code:
|
|
430
|
+
npm install -g @anthropic-ai/claude-code
|
|
431
|
+
|
|
432
|
+
Or set MEET_AI_CLAUDE_PATH to the Claude Code CLI path.
|
|
433
|
+
`.trim());
|
|
434
|
+
}
|
|
435
|
+
async function spawnInteractive() {
|
|
436
|
+
const claudePath = findClaudeCli();
|
|
437
|
+
return new Promise((resolve2, reject) => {
|
|
438
|
+
const child = spawn(claudePath, [], {
|
|
439
|
+
stdio: "inherit",
|
|
440
|
+
env: {
|
|
441
|
+
...process.env,
|
|
442
|
+
DISABLE_AUTOUPDATER: "1"
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
child.on("exit", (code) => {
|
|
446
|
+
if (code === 0 || code === null) {
|
|
447
|
+
resolve2();
|
|
448
|
+
} else {
|
|
449
|
+
reject(new Error(`Claude exited with code ${code}`));
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
child.on("error", reject);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
|
|
341
456
|
// src/index.ts
|
|
342
|
-
var
|
|
343
|
-
var
|
|
457
|
+
var config = getMeetAiConfig();
|
|
458
|
+
var API_URL = config.url;
|
|
459
|
+
var API_KEY = config.key;
|
|
344
460
|
var client = createClient(API_URL, API_KEY);
|
|
345
461
|
var [command, ...args] = process.argv.slice(2);
|
|
346
462
|
async function downloadMessageAttachments(roomId, messageId) {
|
|
@@ -353,8 +469,8 @@ async function downloadMessageAttachments(roomId, messageId) {
|
|
|
353
469
|
try {
|
|
354
470
|
const localPath = await client.downloadAttachment(att.id, att.filename);
|
|
355
471
|
paths.push(localPath);
|
|
356
|
-
} catch (
|
|
357
|
-
console.error(JSON.stringify({ event: "attachment_download_error", attachmentId: att.id, error:
|
|
472
|
+
} catch (error) {
|
|
473
|
+
console.error(JSON.stringify({ event: "attachment_download_error", attachmentId: att.id, error: error instanceof Error ? error.message : String(error) }));
|
|
358
474
|
}
|
|
359
475
|
}
|
|
360
476
|
return paths;
|
|
@@ -375,24 +491,65 @@ function parseFlags(args2) {
|
|
|
375
491
|
}
|
|
376
492
|
return { positional, flags };
|
|
377
493
|
}
|
|
494
|
+
function rejectFlagLikeArgs(positional, usage) {
|
|
495
|
+
for (const arg of positional) {
|
|
496
|
+
if (arg.startsWith("--")) {
|
|
497
|
+
console.error(`Unknown flag: ${arg}`);
|
|
498
|
+
console.error(`Usage: ${usage}`);
|
|
499
|
+
process.exit(1);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
378
503
|
switch (command) {
|
|
379
504
|
case "create-room": {
|
|
380
|
-
|
|
505
|
+
if (args.includes("--help")) {
|
|
506
|
+
console.log("Usage: meet-ai create-room <room-name>");
|
|
507
|
+
process.exit(0);
|
|
508
|
+
}
|
|
509
|
+
const { positional, flags } = parseFlags(args);
|
|
510
|
+
const unknownFlags = Object.keys(flags);
|
|
511
|
+
if (unknownFlags.length > 0) {
|
|
512
|
+
console.error(`Unknown flag: --${unknownFlags[0]}`);
|
|
513
|
+
console.error("Usage: meet-ai create-room <room-name>");
|
|
514
|
+
process.exit(1);
|
|
515
|
+
}
|
|
516
|
+
rejectFlagLikeArgs(positional, "meet-ai create-room <room-name>");
|
|
517
|
+
const name = positional[0];
|
|
381
518
|
if (!name) {
|
|
382
|
-
console.error("Usage:
|
|
519
|
+
console.error("Usage: meet-ai create-room <room-name>");
|
|
383
520
|
process.exit(1);
|
|
384
521
|
}
|
|
385
522
|
const room = await client.createRoom(name);
|
|
386
523
|
console.log(`Room created: ${room.id} (${room.name})`);
|
|
387
524
|
break;
|
|
388
525
|
}
|
|
526
|
+
case "delete-room": {
|
|
527
|
+
if (args.includes("--help")) {
|
|
528
|
+
console.log("Usage: meet-ai delete-room <roomId>");
|
|
529
|
+
process.exit(0);
|
|
530
|
+
}
|
|
531
|
+
rejectFlagLikeArgs(args, "meet-ai delete-room <roomId>");
|
|
532
|
+
const roomId = args[0];
|
|
533
|
+
if (!roomId) {
|
|
534
|
+
console.error("Usage: meet-ai delete-room <roomId>");
|
|
535
|
+
process.exit(1);
|
|
536
|
+
}
|
|
537
|
+
await client.deleteRoom(roomId);
|
|
538
|
+
console.log(`Room deleted: ${roomId}`);
|
|
539
|
+
break;
|
|
540
|
+
}
|
|
389
541
|
case "send-message": {
|
|
542
|
+
if (args.includes("--help")) {
|
|
543
|
+
console.log("Usage: meet-ai send-message <roomId> <sender> <content> [--color <color>]");
|
|
544
|
+
process.exit(0);
|
|
545
|
+
}
|
|
390
546
|
const { positional: smPos, flags: smFlags } = parseFlags(args);
|
|
547
|
+
rejectFlagLikeArgs(smPos, "meet-ai send-message <roomId> <sender> <content> [--color <color>]");
|
|
391
548
|
const [roomId, sender, ...rest] = smPos;
|
|
392
549
|
const content = rest.join(" ").replace(/\\n/g, `
|
|
393
550
|
`);
|
|
394
551
|
if (!roomId || !sender || !content) {
|
|
395
|
-
console.error("Usage:
|
|
552
|
+
console.error("Usage: meet-ai send-message <roomId> <sender> <content> [--color <color>]");
|
|
396
553
|
process.exit(1);
|
|
397
554
|
}
|
|
398
555
|
const msg = await client.sendMessage(roomId, sender, content, smFlags.color);
|
|
@@ -400,10 +557,15 @@ switch (command) {
|
|
|
400
557
|
break;
|
|
401
558
|
}
|
|
402
559
|
case "poll": {
|
|
560
|
+
if (args.includes("--help")) {
|
|
561
|
+
console.log("Usage: meet-ai poll <roomId> [--after <messageId>] [--exclude <sender>] [--sender-type <type>]");
|
|
562
|
+
process.exit(0);
|
|
563
|
+
}
|
|
403
564
|
const { positional, flags } = parseFlags(args);
|
|
565
|
+
rejectFlagLikeArgs(positional, "meet-ai poll <roomId> [--after <messageId>] [--exclude <sender>] [--sender-type <type>]");
|
|
404
566
|
const roomId = positional[0];
|
|
405
567
|
if (!roomId) {
|
|
406
|
-
console.error("Usage:
|
|
568
|
+
console.error("Usage: meet-ai poll <roomId> [--after <messageId>] [--exclude <sender>] [--sender-type <type>]");
|
|
407
569
|
process.exit(1);
|
|
408
570
|
}
|
|
409
571
|
const messages = await client.getMessages(roomId, {
|
|
@@ -423,7 +585,7 @@ switch (command) {
|
|
|
423
585
|
if (!inboxDir)
|
|
424
586
|
return;
|
|
425
587
|
const entry = {
|
|
426
|
-
from:
|
|
588
|
+
from: `meet-ai:${msg.sender}`,
|
|
427
589
|
text: msg.content,
|
|
428
590
|
timestamp: new Date().toISOString(),
|
|
429
591
|
read: false
|
|
@@ -448,10 +610,15 @@ switch (command) {
|
|
|
448
610
|
}
|
|
449
611
|
process.exit(0);
|
|
450
612
|
};
|
|
613
|
+
if (args.includes("--help")) {
|
|
614
|
+
console.log("Usage: meet-ai listen <roomId> [--exclude <sender>] [--sender-type <type>] [--team <name> --inbox <agent>]");
|
|
615
|
+
process.exit(0);
|
|
616
|
+
}
|
|
451
617
|
const { positional, flags } = parseFlags(args);
|
|
618
|
+
rejectFlagLikeArgs(positional, "meet-ai listen <roomId> [--exclude <sender>] [--sender-type <type>] [--team <name> --inbox <agent>]");
|
|
452
619
|
const roomId = positional[0];
|
|
453
620
|
if (!roomId) {
|
|
454
|
-
console.error("Usage:
|
|
621
|
+
console.error("Usage: meet-ai listen <roomId> [--exclude <sender>] [--sender-type <type>] [--team <name> --inbox <agent>]");
|
|
455
622
|
process.exit(1);
|
|
456
623
|
}
|
|
457
624
|
const team = flags.team;
|
|
@@ -502,12 +669,17 @@ switch (command) {
|
|
|
502
669
|
break;
|
|
503
670
|
}
|
|
504
671
|
case "send-log": {
|
|
672
|
+
if (args.includes("--help")) {
|
|
673
|
+
console.log("Usage: meet-ai send-log <roomId> <sender> <content> [--color <color>] [--message-id <id>]");
|
|
674
|
+
process.exit(0);
|
|
675
|
+
}
|
|
505
676
|
const { positional: slPos, flags: slFlags } = parseFlags(args);
|
|
677
|
+
rejectFlagLikeArgs(slPos, "meet-ai send-log <roomId> <sender> <content> [--color <color>] [--message-id <id>]");
|
|
506
678
|
const [slRoomId, slSender, ...slRest] = slPos;
|
|
507
679
|
const slContent = slRest.join(" ").replace(/\\n/g, `
|
|
508
680
|
`);
|
|
509
681
|
if (!slRoomId || !slSender || !slContent) {
|
|
510
|
-
console.error("Usage:
|
|
682
|
+
console.error("Usage: meet-ai send-log <roomId> <sender> <content> [--color <color>] [--message-id <id>]");
|
|
511
683
|
process.exit(1);
|
|
512
684
|
}
|
|
513
685
|
const log = await client.sendLog(slRoomId, slSender, slContent, slFlags.color, slFlags["message-id"]);
|
|
@@ -515,25 +687,70 @@ switch (command) {
|
|
|
515
687
|
break;
|
|
516
688
|
}
|
|
517
689
|
case "send-team-info": {
|
|
518
|
-
|
|
690
|
+
if (args.includes("--help")) {
|
|
691
|
+
console.log(`Usage: meet-ai send-team-info <roomId> '<json>' [--team-name <name>]
|
|
692
|
+
|
|
693
|
+
Accepts two JSON formats:
|
|
694
|
+
|
|
695
|
+
1. Full format (passed through as-is):
|
|
696
|
+
'{"team_name":"my-team","members":[{"name":"agent1","role":"dev","status":"active","color":"#fff","model":"opus","joinedAt":1234567890}]}'
|
|
697
|
+
|
|
698
|
+
2. Members-only array (requires --team-name):
|
|
699
|
+
'[{"name":"agent1","role":"dev","status":"active","color":"#fff"}]' --team-name my-team
|
|
700
|
+
|
|
701
|
+
Missing fields get defaults: model="claude-opus-4-6", joinedAt=<now>`);
|
|
702
|
+
process.exit(0);
|
|
703
|
+
}
|
|
704
|
+
const { positional: tiPos, flags: tiFlags } = parseFlags(args);
|
|
705
|
+
rejectFlagLikeArgs(tiPos, "meet-ai send-team-info <roomId> '<json>' [--team-name <name>]");
|
|
706
|
+
const [tiRoomId, tiPayload] = tiPos;
|
|
519
707
|
if (!tiRoomId || !tiPayload) {
|
|
520
|
-
console.error("Usage:
|
|
708
|
+
console.error("Usage: meet-ai send-team-info <roomId> '<json>' [--team-name <name>]");
|
|
521
709
|
process.exit(1);
|
|
522
710
|
}
|
|
711
|
+
let tiParsed;
|
|
523
712
|
try {
|
|
524
|
-
JSON.parse(tiPayload);
|
|
713
|
+
tiParsed = JSON.parse(tiPayload);
|
|
525
714
|
} catch {
|
|
526
715
|
console.error("Error: payload must be valid JSON");
|
|
527
716
|
process.exit(1);
|
|
528
717
|
}
|
|
529
|
-
|
|
718
|
+
let tiBody;
|
|
719
|
+
if (Array.isArray(tiParsed)) {
|
|
720
|
+
const teamName = tiFlags["team-name"];
|
|
721
|
+
if (!teamName) {
|
|
722
|
+
console.error("Error: when passing a members array, --team-name is required");
|
|
723
|
+
console.error("Usage: meet-ai send-team-info <roomId> '[...]' --team-name <name>");
|
|
724
|
+
process.exit(1);
|
|
725
|
+
}
|
|
726
|
+
const now = Date.now();
|
|
727
|
+
tiBody = {
|
|
728
|
+
team_name: teamName,
|
|
729
|
+
members: tiParsed.map((m) => ({
|
|
730
|
+
model: "claude-opus-4-6",
|
|
731
|
+
joinedAt: now,
|
|
732
|
+
...m
|
|
733
|
+
}))
|
|
734
|
+
};
|
|
735
|
+
} else if (tiParsed && typeof tiParsed === "object" && "team_name" in tiParsed && "members" in tiParsed) {
|
|
736
|
+
tiBody = tiParsed;
|
|
737
|
+
} else {
|
|
738
|
+
console.error("Error: JSON must be either a members array or an object with { team_name, members }");
|
|
739
|
+
process.exit(1);
|
|
740
|
+
}
|
|
741
|
+
await client.sendTeamInfo(tiRoomId, JSON.stringify(tiBody));
|
|
530
742
|
console.log("Team info sent");
|
|
531
743
|
break;
|
|
532
744
|
}
|
|
533
745
|
case "send-tasks": {
|
|
746
|
+
if (args.includes("--help")) {
|
|
747
|
+
console.log("Usage: meet-ai send-tasks <roomId> '<json-payload>'");
|
|
748
|
+
process.exit(0);
|
|
749
|
+
}
|
|
750
|
+
rejectFlagLikeArgs(args, "meet-ai send-tasks <roomId> '<json-payload>'");
|
|
534
751
|
const [stRoomId, stPayload] = args;
|
|
535
752
|
if (!stRoomId || !stPayload) {
|
|
536
|
-
console.error("Usage:
|
|
753
|
+
console.error("Usage: meet-ai send-tasks <roomId> '<json-payload>'");
|
|
537
754
|
process.exit(1);
|
|
538
755
|
}
|
|
539
756
|
try {
|
|
@@ -547,9 +764,14 @@ switch (command) {
|
|
|
547
764
|
break;
|
|
548
765
|
}
|
|
549
766
|
case "download-attachment": {
|
|
767
|
+
if (args.includes("--help")) {
|
|
768
|
+
console.log("Usage: meet-ai download-attachment <attachmentId>");
|
|
769
|
+
process.exit(0);
|
|
770
|
+
}
|
|
771
|
+
rejectFlagLikeArgs(args, "meet-ai download-attachment <attachmentId>");
|
|
550
772
|
const attachmentId = args[0];
|
|
551
773
|
if (!attachmentId) {
|
|
552
|
-
console.error("Usage:
|
|
774
|
+
console.error("Usage: meet-ai download-attachment <attachmentId>");
|
|
553
775
|
process.exit(1);
|
|
554
776
|
}
|
|
555
777
|
try {
|
|
@@ -565,15 +787,15 @@ switch (command) {
|
|
|
565
787
|
const disposition = res.headers.get("Content-Disposition") || "";
|
|
566
788
|
const filenameMatch = disposition.match(/filename="(.+?)"/);
|
|
567
789
|
const filename = filenameMatch?.[1] || attachmentId;
|
|
568
|
-
const { mkdirSync: mkdirSync2, writeFileSync: writeFileSync2 } = await import("fs");
|
|
790
|
+
const { mkdirSync: mkdirSync2, writeFileSync: writeFileSync2 } = await import("node:fs");
|
|
569
791
|
const dir = "/tmp/meet-ai-attachments";
|
|
570
792
|
mkdirSync2(dir, { recursive: true });
|
|
571
793
|
const localPath = `${dir}/${attachmentId}-${filename}`;
|
|
572
794
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
573
795
|
writeFileSync2(localPath, buffer);
|
|
574
796
|
console.log(localPath);
|
|
575
|
-
} catch (
|
|
576
|
-
console.error(
|
|
797
|
+
} catch (error) {
|
|
798
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
577
799
|
process.exit(1);
|
|
578
800
|
}
|
|
579
801
|
break;
|
|
@@ -584,31 +806,47 @@ switch (command) {
|
|
|
584
806
|
console.log(`Prefix: ${result.prefix}`);
|
|
585
807
|
break;
|
|
586
808
|
}
|
|
587
|
-
default:
|
|
809
|
+
default: {
|
|
810
|
+
if (!command) {
|
|
811
|
+
console.log(`Starting Claude Code... (Press Ctrl+C to exit)
|
|
812
|
+
`);
|
|
813
|
+
await spawnInteractive();
|
|
814
|
+
break;
|
|
815
|
+
}
|
|
588
816
|
console.log(`meet-ai CLI
|
|
589
817
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
818
|
+
Usage:
|
|
819
|
+
meet-ai Start Claude Code interactively (default)
|
|
820
|
+
meet-ai <command> [options] Run a specific command
|
|
821
|
+
|
|
822
|
+
Configuration (in order of priority):
|
|
823
|
+
1. Environment variables:
|
|
824
|
+
MEET_AI_URL Server URL (default: https://meet-ai.cc)
|
|
825
|
+
MEET_AI_KEY API key for authentication
|
|
826
|
+
2. Project settings: ./.claude/settings.json
|
|
827
|
+
3. User settings: ~/.claude/settings.json
|
|
593
828
|
|
|
594
829
|
Commands:
|
|
595
|
-
create-room <name>
|
|
596
|
-
|
|
830
|
+
create-room <name> Create a new chat room
|
|
831
|
+
delete-room <roomId> Delete a room and all its messages
|
|
832
|
+
send-message <roomId> <sender> <content> Send a message to a room
|
|
597
833
|
--color <color> Set sender name color (e.g. #ff0000, red)
|
|
598
|
-
send-log <roomId> <sender> <content>
|
|
834
|
+
send-log <roomId> <sender> <content> Send a log entry to a room
|
|
599
835
|
--color <color> Set sender name color (e.g. #ff0000, red)
|
|
600
836
|
--message-id <id> Associate log with a parent message
|
|
601
|
-
poll <roomId> [options]
|
|
837
|
+
poll <roomId> [options] Fetch messages from a room
|
|
602
838
|
--after <id> Only messages after this ID
|
|
603
839
|
--exclude <sender> Exclude messages from sender
|
|
604
840
|
--sender-type <type> Filter by sender_type (human|agent)
|
|
605
|
-
listen <roomId> [options]
|
|
841
|
+
listen <roomId> [options] Stream messages via WebSocket
|
|
606
842
|
--exclude <sender> Exclude messages from sender
|
|
607
843
|
--sender-type <type> Filter by sender_type (human|agent)
|
|
608
844
|
--team <name> Write to Claude Code team inbox
|
|
609
845
|
--inbox <agent> Target agent inbox (requires --team)
|
|
610
|
-
download-attachment <attachmentId>
|
|
611
|
-
send-team-info <roomId> '<json>'
|
|
612
|
-
|
|
613
|
-
|
|
846
|
+
download-attachment <attachmentId> Download an attachment to /tmp
|
|
847
|
+
send-team-info <roomId> '<json>' [options] Send team info to a room
|
|
848
|
+
--team-name <name> Team name (required when passing members array)
|
|
849
|
+
send-tasks <roomId> '<json>' Send tasks info to a room
|
|
850
|
+
generate-key Generate a new API key`);
|
|
851
|
+
}
|
|
614
852
|
}
|