@meet-ai/cli 0.0.35 → 0.0.36
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 +1155 -276
- package/package.json +2 -1
- package/README.md +0 -114
package/dist/index.js
CHANGED
|
@@ -14390,6 +14390,100 @@ var init_zod = __esm(() => {
|
|
|
14390
14390
|
init_external();
|
|
14391
14391
|
});
|
|
14392
14392
|
|
|
14393
|
+
// src/lib/codex.ts
|
|
14394
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
14395
|
+
import { homedir } from "node:os";
|
|
14396
|
+
import { dirname, join, resolve } from "node:path";
|
|
14397
|
+
function getCodexHome(options) {
|
|
14398
|
+
if (options?.codexHome)
|
|
14399
|
+
return options.codexHome;
|
|
14400
|
+
if (options?.env?.CODEX_HOME)
|
|
14401
|
+
return options.env.CODEX_HOME;
|
|
14402
|
+
if (process.env.CODEX_HOME)
|
|
14403
|
+
return process.env.CODEX_HOME;
|
|
14404
|
+
if (process.env.MEET_AI_CODEX_STATE_DIR)
|
|
14405
|
+
return process.env.MEET_AI_CODEX_STATE_DIR;
|
|
14406
|
+
return join(homedir(), ".codex");
|
|
14407
|
+
}
|
|
14408
|
+
function getCodexConfigPaths(options) {
|
|
14409
|
+
const home = getCodexHome(options);
|
|
14410
|
+
return [
|
|
14411
|
+
resolve(".codex/config.json"),
|
|
14412
|
+
resolve(".codex/config.toml"),
|
|
14413
|
+
join(home, "config.json"),
|
|
14414
|
+
join(home, "config.toml")
|
|
14415
|
+
];
|
|
14416
|
+
}
|
|
14417
|
+
function parseCodexTomlEnv(path) {
|
|
14418
|
+
if (!existsSync(path))
|
|
14419
|
+
return null;
|
|
14420
|
+
const env = {};
|
|
14421
|
+
let inEnvSection = false;
|
|
14422
|
+
for (const line of readFileSync(path, "utf-8").split(/\r?\n/)) {
|
|
14423
|
+
const trimmed = line.trim();
|
|
14424
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
14425
|
+
continue;
|
|
14426
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
14427
|
+
inEnvSection = trimmed === "[env]";
|
|
14428
|
+
continue;
|
|
14429
|
+
}
|
|
14430
|
+
if (!inEnvSection)
|
|
14431
|
+
continue;
|
|
14432
|
+
const match = trimmed.match(/^([A-Z0-9_]+)\s*=\s*"([^"]*)"$/);
|
|
14433
|
+
if (!match)
|
|
14434
|
+
continue;
|
|
14435
|
+
env[match[1]] = match[2];
|
|
14436
|
+
}
|
|
14437
|
+
return Object.keys(env).length > 0 ? env : null;
|
|
14438
|
+
}
|
|
14439
|
+
function readCodexConfigEnv(options) {
|
|
14440
|
+
for (const path of getCodexConfigPaths(options)) {
|
|
14441
|
+
if (!existsSync(path))
|
|
14442
|
+
continue;
|
|
14443
|
+
if (path.endsWith(".json")) {
|
|
14444
|
+
try {
|
|
14445
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
14446
|
+
if (parsed.env && Object.keys(parsed.env).length > 0) {
|
|
14447
|
+
return parsed.env;
|
|
14448
|
+
}
|
|
14449
|
+
} catch {
|
|
14450
|
+
continue;
|
|
14451
|
+
}
|
|
14452
|
+
continue;
|
|
14453
|
+
}
|
|
14454
|
+
const env = parseCodexTomlEnv(path);
|
|
14455
|
+
if (env)
|
|
14456
|
+
return env;
|
|
14457
|
+
}
|
|
14458
|
+
return null;
|
|
14459
|
+
}
|
|
14460
|
+
function getInboxPath(sessionId, options) {
|
|
14461
|
+
return join(getCodexHome(options), "meet-ai", "inbox", `${sessionId}.json`);
|
|
14462
|
+
}
|
|
14463
|
+
function appendCodexInboxEntry(sessionId, entry, options) {
|
|
14464
|
+
const path = getInboxPath(sessionId, options);
|
|
14465
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
14466
|
+
let entries = [];
|
|
14467
|
+
try {
|
|
14468
|
+
entries = JSON.parse(readFileSync(path, "utf-8"));
|
|
14469
|
+
} catch {
|
|
14470
|
+
entries = [];
|
|
14471
|
+
}
|
|
14472
|
+
entries.push(entry);
|
|
14473
|
+
writeFileSync(path, `${JSON.stringify(entries, null, 2)}
|
|
14474
|
+
`);
|
|
14475
|
+
return path;
|
|
14476
|
+
}
|
|
14477
|
+
var init_codex = () => {};
|
|
14478
|
+
|
|
14479
|
+
// src/runtime.ts
|
|
14480
|
+
function getMeetAiRuntime(env = process.env) {
|
|
14481
|
+
const raw = env.MEET_AI_RUNTIME?.trim().toLowerCase();
|
|
14482
|
+
if (raw === "codex")
|
|
14483
|
+
return "codex";
|
|
14484
|
+
return "claude";
|
|
14485
|
+
}
|
|
14486
|
+
|
|
14393
14487
|
// src/config.ts
|
|
14394
14488
|
var exports_config = {};
|
|
14395
14489
|
__export(exports_config, {
|
|
@@ -14397,15 +14491,15 @@ __export(exports_config, {
|
|
|
14397
14491
|
getMeetAiConfig: () => getMeetAiConfig,
|
|
14398
14492
|
configSchema: () => configSchema
|
|
14399
14493
|
});
|
|
14400
|
-
import { readFileSync, existsSync } from "node:fs";
|
|
14401
|
-
import { join, resolve } from "node:path";
|
|
14402
|
-
import { homedir } from "node:os";
|
|
14494
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "node:fs";
|
|
14495
|
+
import { join as join2, resolve as resolve2 } from "node:path";
|
|
14496
|
+
import { homedir as homedir2 } from "node:os";
|
|
14403
14497
|
function loadSettingsFromPath(path) {
|
|
14404
14498
|
try {
|
|
14405
|
-
if (!
|
|
14499
|
+
if (!existsSync2(path)) {
|
|
14406
14500
|
return null;
|
|
14407
14501
|
}
|
|
14408
|
-
const content =
|
|
14502
|
+
const content = readFileSync2(path, "utf-8");
|
|
14409
14503
|
return JSON.parse(content);
|
|
14410
14504
|
} catch {
|
|
14411
14505
|
return null;
|
|
@@ -14418,7 +14512,16 @@ function resolveRawConfig(opts) {
|
|
|
14418
14512
|
key: process.env.MEET_AI_KEY
|
|
14419
14513
|
};
|
|
14420
14514
|
}
|
|
14421
|
-
|
|
14515
|
+
if (getMeetAiRuntime() === "codex") {
|
|
14516
|
+
const codexEnv = readCodexConfigEnv({ codexHome: opts?.codexHome });
|
|
14517
|
+
if (codexEnv?.MEET_AI_URL) {
|
|
14518
|
+
return {
|
|
14519
|
+
url: codexEnv.MEET_AI_URL,
|
|
14520
|
+
key: codexEnv.MEET_AI_KEY
|
|
14521
|
+
};
|
|
14522
|
+
}
|
|
14523
|
+
}
|
|
14524
|
+
const projectSettingsPath = opts?.projectSettingsPath ?? resolve2("./.claude/settings.json");
|
|
14422
14525
|
const projectSettings = loadSettingsFromPath(projectSettingsPath);
|
|
14423
14526
|
if (projectSettings?.env?.MEET_AI_URL) {
|
|
14424
14527
|
return {
|
|
@@ -14426,7 +14529,7 @@ function resolveRawConfig(opts) {
|
|
|
14426
14529
|
key: projectSettings.env.MEET_AI_KEY
|
|
14427
14530
|
};
|
|
14428
14531
|
}
|
|
14429
|
-
const userSettingsPath =
|
|
14532
|
+
const userSettingsPath = join2(opts?.homeDir ?? homedir2(), ".claude/settings.json");
|
|
14430
14533
|
const userSettings = loadSettingsFromPath(userSettingsPath);
|
|
14431
14534
|
if (userSettings?.env?.MEET_AI_URL) {
|
|
14432
14535
|
return {
|
|
@@ -14450,6 +14553,7 @@ function getMeetAiConfig(opts) {
|
|
|
14450
14553
|
var configSchema;
|
|
14451
14554
|
var init_config = __esm(() => {
|
|
14452
14555
|
init_zod();
|
|
14556
|
+
init_codex();
|
|
14453
14557
|
configSchema = exports_external.object({
|
|
14454
14558
|
url: exports_external.string().url("MEET_AI_URL must be a valid URL"),
|
|
14455
14559
|
key: exports_external.string().optional()
|
|
@@ -14483,7 +14587,7 @@ async function withRetry(fn, options) {
|
|
|
14483
14587
|
delay_ms: delay,
|
|
14484
14588
|
error: lastError.message
|
|
14485
14589
|
}));
|
|
14486
|
-
await new Promise((
|
|
14590
|
+
await new Promise((resolve3) => setTimeout(resolve3, delay));
|
|
14487
14591
|
}
|
|
14488
14592
|
}
|
|
14489
14593
|
throw lastError;
|
|
@@ -14583,6 +14687,18 @@ class HttpTransport {
|
|
|
14583
14687
|
}
|
|
14584
14688
|
}
|
|
14585
14689
|
|
|
14690
|
+
// src/coding-agents.ts
|
|
14691
|
+
function isCodingAgentId(value) {
|
|
14692
|
+
return CODING_AGENT_DEFINITIONS.some((agent) => agent.id === value);
|
|
14693
|
+
}
|
|
14694
|
+
var CODING_AGENT_DEFINITIONS;
|
|
14695
|
+
var init_coding_agents = __esm(() => {
|
|
14696
|
+
CODING_AGENT_DEFINITIONS = [
|
|
14697
|
+
{ id: "claude", label: "Claude Code" },
|
|
14698
|
+
{ id: "codex", label: "Codex" }
|
|
14699
|
+
];
|
|
14700
|
+
});
|
|
14701
|
+
|
|
14586
14702
|
// src/domain/adapters/ConnectionAdapter.ts
|
|
14587
14703
|
function wsLog(data) {
|
|
14588
14704
|
const json2 = JSON.stringify({ ...data, ts: new Date().toISOString() });
|
|
@@ -14754,7 +14870,8 @@ class ConnectionAdapter {
|
|
|
14754
14870
|
options?.onRoomCreated?.(data.id, data.name);
|
|
14755
14871
|
}
|
|
14756
14872
|
if (data.type === "spawn_request" && data.room_name) {
|
|
14757
|
-
|
|
14873
|
+
const codingAgent = typeof data.coding_agent === "string" && isCodingAgentId(data.coding_agent) ? data.coding_agent : "claude";
|
|
14874
|
+
options?.onSpawnRequest?.({ roomName: data.room_name, codingAgent });
|
|
14758
14875
|
}
|
|
14759
14876
|
} catch {}
|
|
14760
14877
|
};
|
|
@@ -14775,31 +14892,34 @@ class ConnectionAdapter {
|
|
|
14775
14892
|
return this.transport.postJson("/api/keys");
|
|
14776
14893
|
}
|
|
14777
14894
|
}
|
|
14895
|
+
var init_ConnectionAdapter = __esm(() => {
|
|
14896
|
+
init_coding_agents();
|
|
14897
|
+
});
|
|
14778
14898
|
|
|
14779
14899
|
// src/domain/adapters/FileSystemAdapter.ts
|
|
14780
14900
|
import {
|
|
14781
|
-
readFileSync as
|
|
14782
|
-
writeFileSync,
|
|
14783
|
-
mkdirSync,
|
|
14784
|
-
existsSync as
|
|
14785
|
-
statSync
|
|
14901
|
+
readFileSync as readFileSync3,
|
|
14902
|
+
writeFileSync as writeFileSync2,
|
|
14903
|
+
mkdirSync as mkdirSync2,
|
|
14904
|
+
existsSync as existsSync3,
|
|
14905
|
+
statSync as statSync2
|
|
14786
14906
|
} from "node:fs";
|
|
14787
14907
|
|
|
14788
14908
|
class FileSystemAdapter {
|
|
14789
14909
|
readFileSync(path, encoding) {
|
|
14790
|
-
return
|
|
14910
|
+
return readFileSync3(path, encoding);
|
|
14791
14911
|
}
|
|
14792
14912
|
writeFileSync(path, data, encoding) {
|
|
14793
|
-
|
|
14913
|
+
writeFileSync2(path, data, encoding);
|
|
14794
14914
|
}
|
|
14795
14915
|
mkdirSync(path, opts) {
|
|
14796
|
-
|
|
14916
|
+
mkdirSync2(path, opts);
|
|
14797
14917
|
}
|
|
14798
14918
|
existsSync(path) {
|
|
14799
|
-
return
|
|
14919
|
+
return existsSync3(path);
|
|
14800
14920
|
}
|
|
14801
14921
|
statSync(path) {
|
|
14802
|
-
const stat =
|
|
14922
|
+
const stat = statSync2(path);
|
|
14803
14923
|
return { mtimeMs: stat.mtimeMs, size: stat.size };
|
|
14804
14924
|
}
|
|
14805
14925
|
}
|
|
@@ -14979,7 +15099,7 @@ class SendTerminalData {
|
|
|
14979
15099
|
}
|
|
14980
15100
|
|
|
14981
15101
|
// src/domain/services/InboxRouter.ts
|
|
14982
|
-
import { dirname } from "node:path";
|
|
15102
|
+
import { dirname as dirname2 } from "node:path";
|
|
14983
15103
|
|
|
14984
15104
|
class InboxRouter {
|
|
14985
15105
|
fs;
|
|
@@ -15002,7 +15122,7 @@ class InboxRouter {
|
|
|
15002
15122
|
for (const target of targets) {
|
|
15003
15123
|
this.appendToInbox(`${opts.inboxDir}/${target}.json`, entry);
|
|
15004
15124
|
}
|
|
15005
|
-
} else if (opts.
|
|
15125
|
+
} else if (opts.defaultInboxPath) {
|
|
15006
15126
|
this.appendToInbox(opts.defaultInboxPath, entry);
|
|
15007
15127
|
}
|
|
15008
15128
|
}
|
|
@@ -15022,7 +15142,7 @@ class InboxRouter {
|
|
|
15022
15142
|
}
|
|
15023
15143
|
}
|
|
15024
15144
|
appendToInbox(path, entry) {
|
|
15025
|
-
this.fs.mkdirSync(
|
|
15145
|
+
this.fs.mkdirSync(dirname2(path), { recursive: true });
|
|
15026
15146
|
let messages = [];
|
|
15027
15147
|
try {
|
|
15028
15148
|
messages = JSON.parse(this.fs.readFileSync(path, "utf-8"));
|
|
@@ -15150,12 +15270,12 @@ __export(exports_bootstrap, {
|
|
|
15150
15270
|
});
|
|
15151
15271
|
function cleanupOldAttachments() {
|
|
15152
15272
|
try {
|
|
15153
|
-
const { readdirSync, statSync:
|
|
15273
|
+
const { readdirSync: readdirSync2, statSync: statSync3, unlinkSync } = __require("node:fs");
|
|
15154
15274
|
const now = Date.now();
|
|
15155
|
-
for (const entry of
|
|
15275
|
+
for (const entry of readdirSync2(ATTACHMENTS_DIR)) {
|
|
15156
15276
|
try {
|
|
15157
15277
|
const filePath = `${ATTACHMENTS_DIR}/${entry}`;
|
|
15158
|
-
const mtime =
|
|
15278
|
+
const mtime = statSync3(filePath).mtimeMs;
|
|
15159
15279
|
if (now - mtime > MAX_AGE_MS) {
|
|
15160
15280
|
unlinkSync(filePath);
|
|
15161
15281
|
}
|
|
@@ -15211,12 +15331,12 @@ function getClient() {
|
|
|
15211
15331
|
downloadAttachment: async (attachmentId) => {
|
|
15212
15332
|
cleanupOldAttachments();
|
|
15213
15333
|
const response = await c.downloadAttachment.execute(attachmentId);
|
|
15214
|
-
const { mkdirSync:
|
|
15215
|
-
|
|
15334
|
+
const { mkdirSync: mkdirSync3, writeFileSync: writeFileSync3 } = await import("node:fs");
|
|
15335
|
+
mkdirSync3(ATTACHMENTS_DIR, { recursive: true });
|
|
15216
15336
|
const safeId = attachmentId.replace(/[^a-zA-Z0-9_-]/g, "") || "unknown";
|
|
15217
15337
|
const localPath = `${ATTACHMENTS_DIR}/${safeId}.bin`;
|
|
15218
15338
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
15219
|
-
|
|
15339
|
+
writeFileSync3(localPath, buffer);
|
|
15220
15340
|
return localPath;
|
|
15221
15341
|
},
|
|
15222
15342
|
listenLobby: (options) => c.listenLobby.execute(options),
|
|
@@ -15228,6 +15348,7 @@ function getClient() {
|
|
|
15228
15348
|
var ATTACHMENTS_DIR = "/tmp/meet-ai-attachments", MAX_AGE_MS, container = null;
|
|
15229
15349
|
var init_bootstrap = __esm(() => {
|
|
15230
15350
|
init_config();
|
|
15351
|
+
init_ConnectionAdapter();
|
|
15231
15352
|
init_FileSystemAdapter();
|
|
15232
15353
|
init_MessageRepository();
|
|
15233
15354
|
init_RoomRepository();
|
|
@@ -15643,29 +15764,28 @@ var init_command5 = __esm(() => {
|
|
|
15643
15764
|
});
|
|
15644
15765
|
});
|
|
15645
15766
|
|
|
15767
|
+
// src/inbox-router.ts
|
|
15768
|
+
var IDLE_CHECK_INTERVAL_MS = 60000, IDLE_THRESHOLD_MS2;
|
|
15769
|
+
var init_inbox_router = __esm(() => {
|
|
15770
|
+
IDLE_THRESHOLD_MS2 = 5 * 60 * 1000;
|
|
15771
|
+
});
|
|
15772
|
+
|
|
15646
15773
|
// src/commands/listen/schema.ts
|
|
15647
15774
|
var ListenInput;
|
|
15648
15775
|
var init_schema6 = __esm(() => {
|
|
15649
15776
|
init_zod();
|
|
15650
15777
|
ListenInput = exports_external.object({
|
|
15651
|
-
roomId: exports_external.
|
|
15778
|
+
roomId: exports_external.uuid({ error: "Room ID must be a valid uuid" }),
|
|
15652
15779
|
exclude: exports_external.string().optional(),
|
|
15653
15780
|
senderType: exports_external.string().optional(),
|
|
15654
15781
|
team: exports_external.string().optional(),
|
|
15655
|
-
inbox: exports_external.string().optional()
|
|
15656
|
-
stdinPane: exports_external.string().optional()
|
|
15782
|
+
inbox: exports_external.string().optional()
|
|
15657
15783
|
}).refine((data) => !(data.inbox && !data.team), {
|
|
15658
15784
|
message: "--inbox requires --team",
|
|
15659
15785
|
path: ["inbox"]
|
|
15660
15786
|
});
|
|
15661
15787
|
});
|
|
15662
15788
|
|
|
15663
|
-
// src/inbox-router.ts
|
|
15664
|
-
var IDLE_CHECK_INTERVAL_MS = 60000, IDLE_THRESHOLD_MS2;
|
|
15665
|
-
var init_inbox_router = __esm(() => {
|
|
15666
|
-
IDLE_THRESHOLD_MS2 = 5 * 60 * 1000;
|
|
15667
|
-
});
|
|
15668
|
-
|
|
15669
15789
|
// src/lib/tmux-client.ts
|
|
15670
15790
|
import { execFileSync, execFile as execFileCb } from "node:child_process";
|
|
15671
15791
|
function validateSessionName(name) {
|
|
@@ -15696,6 +15816,9 @@ class TmuxClient {
|
|
|
15696
15816
|
timeout: 5000,
|
|
15697
15817
|
stdio: ["pipe", "pipe", "pipe"]
|
|
15698
15818
|
}).trim();
|
|
15819
|
+
if (!result) {
|
|
15820
|
+
return { available: false, version: null, error: "tmux returned an empty version string" };
|
|
15821
|
+
}
|
|
15699
15822
|
return { available: true, version: result };
|
|
15700
15823
|
} catch (error48) {
|
|
15701
15824
|
return {
|
|
@@ -15707,11 +15830,7 @@ class TmuxClient {
|
|
|
15707
15830
|
}
|
|
15708
15831
|
newSession(name, commandArgs, env) {
|
|
15709
15832
|
validateSessionName(name);
|
|
15710
|
-
|
|
15711
|
-
for (const [key, value] of Object.entries(env)) {
|
|
15712
|
-
this.exec(["-L", this.server, "set-environment", "-g", key, value]);
|
|
15713
|
-
}
|
|
15714
|
-
}
|
|
15833
|
+
const envArgs = env ? ["env", ...Object.entries(env).map(([key, value]) => `${key}=${value}`)] : [];
|
|
15715
15834
|
const args = [
|
|
15716
15835
|
"-L",
|
|
15717
15836
|
this.server,
|
|
@@ -15724,14 +15843,10 @@ class TmuxClient {
|
|
|
15724
15843
|
"-y",
|
|
15725
15844
|
"40",
|
|
15726
15845
|
"--",
|
|
15846
|
+
...envArgs,
|
|
15727
15847
|
...commandArgs
|
|
15728
15848
|
];
|
|
15729
15849
|
const result = this.exec(args);
|
|
15730
|
-
if (env) {
|
|
15731
|
-
for (const key of Object.keys(env)) {
|
|
15732
|
-
this.exec(["-L", this.server, "set-environment", "-g", "-u", key]);
|
|
15733
|
-
}
|
|
15734
|
-
}
|
|
15735
15850
|
if (!result.ok)
|
|
15736
15851
|
return result;
|
|
15737
15852
|
this.exec(["-L", this.server, "set-option", "-t", name, "remain-on-exit", "on"]);
|
|
@@ -15771,13 +15886,13 @@ class TmuxClient {
|
|
|
15771
15886
|
"-F",
|
|
15772
15887
|
"#{pane_id}\t#{session_name}\t#{pane_title}\t#{pane_current_command}"
|
|
15773
15888
|
];
|
|
15774
|
-
return new Promise((
|
|
15889
|
+
return new Promise((resolve3) => {
|
|
15775
15890
|
execFileCb("tmux", args, { encoding: "utf8", timeout: 5000 }, (error48, stdout) => {
|
|
15776
15891
|
if (error48) {
|
|
15777
|
-
|
|
15892
|
+
resolve3([]);
|
|
15778
15893
|
return;
|
|
15779
15894
|
}
|
|
15780
|
-
|
|
15895
|
+
resolve3(stdout.trim().split(`
|
|
15781
15896
|
`).filter((line) => line.trim()).map((line) => {
|
|
15782
15897
|
const [paneId, sessionName, title, command] = line.split("\t");
|
|
15783
15898
|
return { paneId: paneId ?? "", sessionName: sessionName ?? "", title: title ?? "", command: command ?? "" };
|
|
@@ -15830,10 +15945,10 @@ class TmuxClient {
|
|
|
15830
15945
|
if (lines > 0) {
|
|
15831
15946
|
args.push("-S", `-${lines}`);
|
|
15832
15947
|
}
|
|
15833
|
-
return new Promise((
|
|
15948
|
+
return new Promise((resolve3) => {
|
|
15834
15949
|
execFileCb("tmux", args, { encoding: "utf8", timeout: 5000 }, (error48, stdout) => {
|
|
15835
15950
|
if (error48) {
|
|
15836
|
-
|
|
15951
|
+
resolve3([]);
|
|
15837
15952
|
return;
|
|
15838
15953
|
}
|
|
15839
15954
|
const result = stdout.split(`
|
|
@@ -15841,7 +15956,7 @@ class TmuxClient {
|
|
|
15841
15956
|
while (result.length > 0 && result[result.length - 1] === "") {
|
|
15842
15957
|
result.pop();
|
|
15843
15958
|
}
|
|
15844
|
-
|
|
15959
|
+
resolve3(result);
|
|
15845
15960
|
});
|
|
15846
15961
|
});
|
|
15847
15962
|
}
|
|
@@ -15885,16 +16000,12 @@ var init_tmux_client = __esm(() => {
|
|
|
15885
16000
|
SESSION_NAME_RE = /^[a-zA-Z0-9_-]+$/;
|
|
15886
16001
|
});
|
|
15887
16002
|
|
|
15888
|
-
// src/commands/listen/
|
|
15889
|
-
function
|
|
15890
|
-
const
|
|
15891
|
-
const { roomId, exclude, senderType, team, inbox, stdinPane } = parsed;
|
|
15892
|
-
const inboxDir = team ? `${process.env.HOME}/.claude/teams/${team}/inboxes` : null;
|
|
15893
|
-
const defaultInboxPath = inboxDir && inbox ? `${inboxDir}/${inbox}.json` : null;
|
|
15894
|
-
const teamDir = team ? `${process.env.HOME}/.claude/teams/${team}` : null;
|
|
16003
|
+
// src/commands/listen/shared.ts
|
|
16004
|
+
function createTerminalControlHandler(input) {
|
|
16005
|
+
const { client, roomId, teamDir } = input;
|
|
15895
16006
|
const tmuxClient = new TmuxClient({ server: "meet-ai", scrollback: 50000 });
|
|
15896
16007
|
let terminalInterval = null;
|
|
15897
|
-
|
|
16008
|
+
function handle(msg) {
|
|
15898
16009
|
if (msg.type === "terminal_resize") {
|
|
15899
16010
|
const cols = msg.cols;
|
|
15900
16011
|
if (typeof cols === "number" && cols > 0) {
|
|
@@ -15906,7 +16017,7 @@ function listen(client, input, inboxRouter) {
|
|
|
15906
16017
|
}
|
|
15907
16018
|
});
|
|
15908
16019
|
}
|
|
15909
|
-
return;
|
|
16020
|
+
return true;
|
|
15910
16021
|
}
|
|
15911
16022
|
if (msg.type === "terminal_subscribe") {
|
|
15912
16023
|
const roomPrefix = roomId.slice(0, 8);
|
|
@@ -15959,29 +16070,61 @@ function listen(client, input, inboxRouter) {
|
|
|
15959
16070
|
await client.sendTerminalData(roomId, payload);
|
|
15960
16071
|
} catch {}
|
|
15961
16072
|
}, TERMINAL_POLL_MS);
|
|
15962
|
-
return;
|
|
16073
|
+
return true;
|
|
15963
16074
|
}
|
|
15964
16075
|
if (msg.type === "terminal_unsubscribe") {
|
|
15965
16076
|
if (terminalInterval) {
|
|
15966
16077
|
clearInterval(terminalInterval);
|
|
15967
16078
|
terminalInterval = null;
|
|
15968
16079
|
}
|
|
15969
|
-
return;
|
|
16080
|
+
return true;
|
|
15970
16081
|
}
|
|
15971
16082
|
if (msg.type === "terminal_data") {
|
|
15972
|
-
return;
|
|
16083
|
+
return true;
|
|
16084
|
+
}
|
|
16085
|
+
return false;
|
|
16086
|
+
}
|
|
16087
|
+
function shutdown() {
|
|
16088
|
+
if (terminalInterval) {
|
|
16089
|
+
clearInterval(terminalInterval);
|
|
16090
|
+
terminalInterval = null;
|
|
15973
16091
|
}
|
|
15974
|
-
|
|
16092
|
+
}
|
|
16093
|
+
return { handle, shutdown };
|
|
16094
|
+
}
|
|
16095
|
+
var init_shared = __esm(() => {
|
|
16096
|
+
init_tmux_client();
|
|
16097
|
+
});
|
|
16098
|
+
|
|
16099
|
+
// src/commands/listen/listen-claude.ts
|
|
16100
|
+
function listenClaude(client, input, inboxRouter) {
|
|
16101
|
+
const parsed = ListenInput.parse(input);
|
|
16102
|
+
const { roomId, exclude, senderType, team, inbox } = parsed;
|
|
16103
|
+
const inboxDir = team ? `${process.env.HOME}/.claude/teams/${team}/inboxes` : null;
|
|
16104
|
+
const defaultInboxPath = inboxDir && inbox ? `${inboxDir}/${inbox}.json` : null;
|
|
16105
|
+
const teamDir = team ? `${process.env.HOME}/.claude/teams/${team}` : undefined;
|
|
16106
|
+
const terminal = createTerminalControlHandler({ client, roomId, teamDir, inboxRouter });
|
|
16107
|
+
const onMessage = (msg) => {
|
|
16108
|
+
if (terminal.handle(msg))
|
|
16109
|
+
return;
|
|
16110
|
+
if (msg.id && msg.room_id && (msg.attachment_count ?? 0) > 0) {
|
|
15975
16111
|
downloadMessageAttachments(client, msg.room_id, msg.id).then((paths) => {
|
|
15976
16112
|
const output = paths.length ? { ...msg, attachments: paths } : msg;
|
|
15977
16113
|
console.log(JSON.stringify(output));
|
|
15978
|
-
if (inboxDir && teamDir && inboxRouter)
|
|
15979
|
-
inboxRouter.route(msg, {
|
|
16114
|
+
if (inboxDir && teamDir && inboxRouter) {
|
|
16115
|
+
inboxRouter.route(msg, {
|
|
16116
|
+
inboxDir,
|
|
16117
|
+
defaultInboxPath,
|
|
16118
|
+
teamDir,
|
|
16119
|
+
attachmentPaths: paths
|
|
16120
|
+
});
|
|
16121
|
+
}
|
|
15980
16122
|
});
|
|
15981
|
-
|
|
15982
|
-
|
|
15983
|
-
|
|
15984
|
-
|
|
16123
|
+
return;
|
|
16124
|
+
}
|
|
16125
|
+
console.log(JSON.stringify(msg));
|
|
16126
|
+
if (inboxDir && teamDir && inboxRouter) {
|
|
16127
|
+
inboxRouter.route(msg, { inboxDir, defaultInboxPath, teamDir });
|
|
15985
16128
|
}
|
|
15986
16129
|
};
|
|
15987
16130
|
const ws = client.listen(roomId, { exclude, senderType, onMessage });
|
|
@@ -15990,7 +16133,13 @@ function listen(client, input, inboxRouter) {
|
|
|
15990
16133
|
if (inboxDir && inbox && teamDir && inboxRouter) {
|
|
15991
16134
|
let scheduleIdleCheck = function() {
|
|
15992
16135
|
idleCheckTimeout = setTimeout(() => {
|
|
15993
|
-
inboxRouter.checkIdle({
|
|
16136
|
+
inboxRouter.checkIdle({
|
|
16137
|
+
inboxDir,
|
|
16138
|
+
teamDir,
|
|
16139
|
+
inbox,
|
|
16140
|
+
defaultInboxPath: defaultInboxPath ?? null,
|
|
16141
|
+
notified: idleNotified
|
|
16142
|
+
});
|
|
15994
16143
|
scheduleIdleCheck();
|
|
15995
16144
|
}, IDLE_CHECK_INTERVAL_MS);
|
|
15996
16145
|
};
|
|
@@ -15999,10 +16148,621 @@ function listen(client, input, inboxRouter) {
|
|
|
15999
16148
|
function shutdown() {
|
|
16000
16149
|
if (idleCheckTimeout)
|
|
16001
16150
|
clearTimeout(idleCheckTimeout);
|
|
16002
|
-
|
|
16003
|
-
|
|
16004
|
-
|
|
16151
|
+
terminal.shutdown();
|
|
16152
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
16153
|
+
ws.close(1000, "client shutdown");
|
|
16154
|
+
}
|
|
16155
|
+
process.exit(0);
|
|
16156
|
+
}
|
|
16157
|
+
process.on("SIGINT", shutdown);
|
|
16158
|
+
process.on("SIGTERM", shutdown);
|
|
16159
|
+
process.on("SIGHUP", shutdown);
|
|
16160
|
+
return ws;
|
|
16161
|
+
}
|
|
16162
|
+
var init_listen_claude = __esm(() => {
|
|
16163
|
+
init_inbox_router();
|
|
16164
|
+
init_schema6();
|
|
16165
|
+
init_shared();
|
|
16166
|
+
});
|
|
16167
|
+
|
|
16168
|
+
// src/lib/codex-app-server.ts
|
|
16169
|
+
import {
|
|
16170
|
+
spawn
|
|
16171
|
+
} from "node:child_process";
|
|
16172
|
+
import { stderr } from "node:process";
|
|
16173
|
+
import { createInterface } from "node:readline";
|
|
16174
|
+
function isObject2(value) {
|
|
16175
|
+
return typeof value === "object" && value !== null;
|
|
16176
|
+
}
|
|
16177
|
+
function isJsonRpcResponse(value) {
|
|
16178
|
+
return isObject2(value) && "id" in value && (("result" in value) || ("error" in value));
|
|
16179
|
+
}
|
|
16180
|
+
function isJsonRpcServerRequest(value) {
|
|
16181
|
+
return isObject2(value) && typeof value.method === "string" && "id" in value && !("result" in value) && !("error" in value);
|
|
16182
|
+
}
|
|
16183
|
+
function isJsonRpcNotification(value) {
|
|
16184
|
+
return isObject2(value) && typeof value.method === "string" && !("id" in value);
|
|
16185
|
+
}
|
|
16186
|
+
function toErrorMessage(error48) {
|
|
16187
|
+
if (error48 instanceof Error)
|
|
16188
|
+
return error48.message;
|
|
16189
|
+
return String(error48);
|
|
16190
|
+
}
|
|
16191
|
+
function formatRoomMessageForCodex(input) {
|
|
16192
|
+
const lines = [
|
|
16193
|
+
`New message from meet-ai sender "${input.sender}" at ${input.timestamp ?? new Date().toISOString()}:`,
|
|
16194
|
+
"",
|
|
16195
|
+
input.content
|
|
16196
|
+
];
|
|
16197
|
+
if (input.attachments?.length) {
|
|
16198
|
+
lines.push("", `Attachments: ${input.attachments.join(", ")}`);
|
|
16199
|
+
}
|
|
16200
|
+
return lines.join(`
|
|
16201
|
+
`);
|
|
16202
|
+
}
|
|
16203
|
+
function maybeActiveTurnId(thread) {
|
|
16204
|
+
if (!thread || !Array.isArray(thread.turns))
|
|
16205
|
+
return null;
|
|
16206
|
+
for (let index = thread.turns.length - 1;index >= 0; index -= 1) {
|
|
16207
|
+
const turn = thread.turns[index];
|
|
16208
|
+
if (turn?.status === "inProgress" && typeof turn.id === "string") {
|
|
16209
|
+
return turn.id;
|
|
16210
|
+
}
|
|
16211
|
+
}
|
|
16212
|
+
return null;
|
|
16213
|
+
}
|
|
16214
|
+
function isSteerPreconditionError(error48) {
|
|
16215
|
+
if (!isObject2(error48))
|
|
16216
|
+
return false;
|
|
16217
|
+
const message = typeof error48.message === "string" ? error48.message.toLowerCase() : "";
|
|
16218
|
+
return message.includes("expected") || message.includes("active turn") || message.includes("precondition");
|
|
16219
|
+
}
|
|
16220
|
+
function isAgentMessageDeltaNotification(params) {
|
|
16221
|
+
return isObject2(params) && typeof params.threadId === "string" && typeof params.turnId === "string" && typeof params.itemId === "string" && typeof params.delta === "string";
|
|
16222
|
+
}
|
|
16223
|
+
function extractAgentMessageDelta(params) {
|
|
16224
|
+
if (!isAgentMessageDeltaNotification(params)) {
|
|
16225
|
+
return { itemId: null, turnId: null, text: null };
|
|
16226
|
+
}
|
|
16227
|
+
return {
|
|
16228
|
+
itemId: params.itemId,
|
|
16229
|
+
turnId: params.turnId,
|
|
16230
|
+
text: params.delta
|
|
16231
|
+
};
|
|
16232
|
+
}
|
|
16233
|
+
function isItemCompletedNotification(params) {
|
|
16234
|
+
return isObject2(params) && typeof params.threadId === "string" && typeof params.turnId === "string" && isObject2(params.item) && typeof params.item.type === "string" && typeof params.item.id === "string";
|
|
16235
|
+
}
|
|
16236
|
+
function extractCompletedAgentMessage(params) {
|
|
16237
|
+
if (!isItemCompletedNotification(params))
|
|
16238
|
+
return null;
|
|
16239
|
+
if (params.item.type !== "agentMessage")
|
|
16240
|
+
return null;
|
|
16241
|
+
return {
|
|
16242
|
+
itemId: params.item.id,
|
|
16243
|
+
turnId: params.turnId,
|
|
16244
|
+
text: params.item.text
|
|
16245
|
+
};
|
|
16246
|
+
}
|
|
16247
|
+
function isThreadStartedNotification(params) {
|
|
16248
|
+
return isObject2(params) && isObject2(params.thread) && typeof params.thread.id === "string";
|
|
16249
|
+
}
|
|
16250
|
+
function isTurnStartedNotification(params) {
|
|
16251
|
+
return isObject2(params) && typeof params.threadId === "string" && isObject2(params.turn) && typeof params.turn.id === "string";
|
|
16252
|
+
}
|
|
16253
|
+
function isTurnCompletedNotification(params) {
|
|
16254
|
+
return isObject2(params) && typeof params.threadId === "string" && isObject2(params.turn) && typeof params.turn.id === "string";
|
|
16255
|
+
}
|
|
16256
|
+
|
|
16257
|
+
class CodexAppServerBridge {
|
|
16258
|
+
threadId;
|
|
16259
|
+
cwd;
|
|
16260
|
+
codexBin;
|
|
16261
|
+
clientName;
|
|
16262
|
+
clientTitle;
|
|
16263
|
+
clientVersion;
|
|
16264
|
+
experimentalApi;
|
|
16265
|
+
env;
|
|
16266
|
+
spawnFn;
|
|
16267
|
+
stderrStream;
|
|
16268
|
+
child = null;
|
|
16269
|
+
stdoutReader = null;
|
|
16270
|
+
readyPromise = null;
|
|
16271
|
+
pendingRequests = new Map;
|
|
16272
|
+
nextRequestId = 1;
|
|
16273
|
+
activeTurnId = null;
|
|
16274
|
+
injectionQueue = Promise.resolve();
|
|
16275
|
+
eventHandler = null;
|
|
16276
|
+
constructor(options) {
|
|
16277
|
+
this.threadId = options.threadId ?? null;
|
|
16278
|
+
this.cwd = options.cwd;
|
|
16279
|
+
this.codexBin = options.codexBin ?? options.env?.MEET_AI_CODEX_PATH ?? process.env.MEET_AI_CODEX_PATH ?? "codex";
|
|
16280
|
+
this.clientName = options.clientName ?? "meet_ai";
|
|
16281
|
+
this.clientTitle = options.clientTitle ?? "meet-ai CLI";
|
|
16282
|
+
this.clientVersion = options.clientVersion ?? "0.0.0";
|
|
16283
|
+
this.experimentalApi = options.experimentalApi ?? false;
|
|
16284
|
+
this.env = options.env ?? process.env;
|
|
16285
|
+
this.spawnFn = options.spawnFn ?? spawn;
|
|
16286
|
+
this.stderrStream = options.stderr ?? stderr;
|
|
16287
|
+
}
|
|
16288
|
+
async start() {
|
|
16289
|
+
if (!this.readyPromise) {
|
|
16290
|
+
this.readyPromise = this.startInternal().catch((error48) => {
|
|
16291
|
+
this.readyPromise = null;
|
|
16292
|
+
throw error48;
|
|
16293
|
+
});
|
|
16294
|
+
}
|
|
16295
|
+
return this.readyPromise;
|
|
16296
|
+
}
|
|
16297
|
+
async injectText(input) {
|
|
16298
|
+
const text = formatRoomMessageForCodex(input);
|
|
16299
|
+
return this.injectPrompt(text);
|
|
16300
|
+
}
|
|
16301
|
+
async injectPrompt(text) {
|
|
16302
|
+
return this.enqueue(async () => {
|
|
16303
|
+
await this.start();
|
|
16304
|
+
const payload = [{ type: "text", text, text_elements: [] }];
|
|
16305
|
+
const threadId = this.threadId;
|
|
16306
|
+
if (!threadId) {
|
|
16307
|
+
throw new Error("Codex app-server bridge does not have an active thread");
|
|
16308
|
+
}
|
|
16309
|
+
if (this.activeTurnId) {
|
|
16310
|
+
try {
|
|
16311
|
+
const result2 = await this.request("turn/steer", {
|
|
16312
|
+
threadId,
|
|
16313
|
+
input: payload,
|
|
16314
|
+
expectedTurnId: this.activeTurnId
|
|
16315
|
+
});
|
|
16316
|
+
this.activeTurnId = result2.turnId;
|
|
16317
|
+
return { mode: "steer", threadId, turnId: result2.turnId };
|
|
16318
|
+
} catch (error48) {
|
|
16319
|
+
if (!isSteerPreconditionError(error48))
|
|
16320
|
+
throw error48;
|
|
16321
|
+
this.activeTurnId = null;
|
|
16322
|
+
}
|
|
16323
|
+
}
|
|
16324
|
+
const result = await this.request("turn/start", {
|
|
16325
|
+
threadId,
|
|
16326
|
+
input: payload
|
|
16327
|
+
});
|
|
16328
|
+
this.activeTurnId = result.turn.id;
|
|
16329
|
+
return { mode: "start", threadId, turnId: result.turn.id };
|
|
16330
|
+
});
|
|
16331
|
+
}
|
|
16332
|
+
getThreadId() {
|
|
16333
|
+
return this.threadId;
|
|
16334
|
+
}
|
|
16335
|
+
async close() {
|
|
16336
|
+
this.readyPromise = null;
|
|
16337
|
+
this.activeTurnId = null;
|
|
16338
|
+
if (this.stdoutReader) {
|
|
16339
|
+
this.stdoutReader.close();
|
|
16340
|
+
this.stdoutReader = null;
|
|
16341
|
+
}
|
|
16342
|
+
const child = this.child;
|
|
16343
|
+
this.child = null;
|
|
16344
|
+
if (!child)
|
|
16345
|
+
return;
|
|
16346
|
+
for (const pending of this.pendingRequests.values()) {
|
|
16347
|
+
pending.reject(new Error("Codex app-server bridge closed"));
|
|
16348
|
+
}
|
|
16349
|
+
this.pendingRequests.clear();
|
|
16350
|
+
child.kill();
|
|
16351
|
+
}
|
|
16352
|
+
setEventHandler(handler) {
|
|
16353
|
+
this.eventHandler = handler;
|
|
16354
|
+
}
|
|
16355
|
+
enqueue(fn) {
|
|
16356
|
+
const next = this.injectionQueue.then(fn, fn);
|
|
16357
|
+
this.injectionQueue = next.catch(() => {
|
|
16358
|
+
return;
|
|
16359
|
+
});
|
|
16360
|
+
return next;
|
|
16361
|
+
}
|
|
16362
|
+
async startInternal() {
|
|
16363
|
+
const child = this.spawnFn(this.codexBin, [
|
|
16364
|
+
"app-server",
|
|
16365
|
+
"--enable",
|
|
16366
|
+
"multi_agent",
|
|
16367
|
+
"--enable",
|
|
16368
|
+
"memories",
|
|
16369
|
+
"--enable",
|
|
16370
|
+
"realtime_conversation",
|
|
16371
|
+
"-c",
|
|
16372
|
+
'sandbox_mode="workspace-write"',
|
|
16373
|
+
"-c",
|
|
16374
|
+
"sandbox_workspace_write.network_access=true",
|
|
16375
|
+
"-c",
|
|
16376
|
+
'web_search="live"',
|
|
16377
|
+
"--listen",
|
|
16378
|
+
"stdio://"
|
|
16379
|
+
], {
|
|
16380
|
+
cwd: this.cwd,
|
|
16381
|
+
env: this.env,
|
|
16382
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
16383
|
+
});
|
|
16384
|
+
this.child = child;
|
|
16385
|
+
this.stdoutReader = createInterface({ input: child.stdout });
|
|
16386
|
+
this.stdoutReader.on("line", (line) => {
|
|
16387
|
+
this.handleLine(line);
|
|
16388
|
+
});
|
|
16389
|
+
child.stderr.on("data", (chunk) => {
|
|
16390
|
+
this.stderrStream.write(chunk);
|
|
16391
|
+
});
|
|
16392
|
+
child.on("exit", (_code, signal) => {
|
|
16393
|
+
const reason = new Error(`codex app-server exited${signal ? ` with signal ${signal}` : ""}`);
|
|
16394
|
+
for (const pending of this.pendingRequests.values()) {
|
|
16395
|
+
pending.reject(reason);
|
|
16396
|
+
}
|
|
16397
|
+
this.pendingRequests.clear();
|
|
16398
|
+
this.child = null;
|
|
16399
|
+
this.stdoutReader = null;
|
|
16400
|
+
this.readyPromise = null;
|
|
16401
|
+
});
|
|
16402
|
+
await this.request("initialize", {
|
|
16403
|
+
clientInfo: {
|
|
16404
|
+
name: this.clientName,
|
|
16405
|
+
title: this.clientTitle,
|
|
16406
|
+
version: this.clientVersion
|
|
16407
|
+
},
|
|
16408
|
+
capabilities: {
|
|
16409
|
+
experimentalApi: this.experimentalApi
|
|
16410
|
+
}
|
|
16411
|
+
});
|
|
16412
|
+
this.notify("initialized");
|
|
16413
|
+
if (this.threadId) {
|
|
16414
|
+
const resumeParams = {
|
|
16415
|
+
threadId: this.threadId,
|
|
16416
|
+
persistExtendedHistory: this.experimentalApi
|
|
16417
|
+
};
|
|
16418
|
+
try {
|
|
16419
|
+
const resumeResult = await this.request("thread/resume", resumeParams);
|
|
16420
|
+
this.threadId = typeof resumeResult.thread?.id === "string" ? resumeResult.thread.id : this.threadId;
|
|
16421
|
+
this.activeTurnId = maybeActiveTurnId(resumeResult.thread);
|
|
16422
|
+
return;
|
|
16423
|
+
} catch {
|
|
16424
|
+
this.stderrStream.write(`meet-ai: codex app-server could not resume thread ${this.threadId}, starting fresh
|
|
16425
|
+
`);
|
|
16426
|
+
this.threadId = null;
|
|
16427
|
+
this.activeTurnId = null;
|
|
16428
|
+
}
|
|
16429
|
+
}
|
|
16430
|
+
const startResult = await this.request("thread/start", {
|
|
16431
|
+
cwd: this.cwd,
|
|
16432
|
+
experimentalRawEvents: false,
|
|
16433
|
+
persistExtendedHistory: this.experimentalApi
|
|
16434
|
+
});
|
|
16435
|
+
this.threadId = typeof startResult.thread?.id === "string" ? startResult.thread.id : null;
|
|
16436
|
+
this.activeTurnId = maybeActiveTurnId(startResult.thread);
|
|
16437
|
+
}
|
|
16438
|
+
async handleLine(line) {
|
|
16439
|
+
const trimmed = line.trim();
|
|
16440
|
+
if (!trimmed)
|
|
16441
|
+
return;
|
|
16442
|
+
let message;
|
|
16443
|
+
try {
|
|
16444
|
+
message = JSON.parse(trimmed);
|
|
16445
|
+
} catch {
|
|
16446
|
+
this.stderrStream.write(`meet-ai: failed to parse codex app-server line: ${trimmed}
|
|
16447
|
+
`);
|
|
16448
|
+
return;
|
|
16449
|
+
}
|
|
16450
|
+
if (isJsonRpcResponse(message)) {
|
|
16451
|
+
const pending = this.pendingRequests.get(message.id);
|
|
16452
|
+
if (!pending)
|
|
16453
|
+
return;
|
|
16454
|
+
this.pendingRequests.delete(message.id);
|
|
16455
|
+
if (message.error) {
|
|
16456
|
+
pending.reject(new Error(message.error.message ?? "Unknown app-server error"));
|
|
16457
|
+
return;
|
|
16458
|
+
}
|
|
16459
|
+
pending.resolve(message.result);
|
|
16460
|
+
return;
|
|
16461
|
+
}
|
|
16462
|
+
if (isJsonRpcServerRequest(message)) {
|
|
16463
|
+
this.respondToServerRequest(message);
|
|
16464
|
+
return;
|
|
16465
|
+
}
|
|
16466
|
+
if (isJsonRpcNotification(message)) {
|
|
16467
|
+
this.handleNotification(message);
|
|
16468
|
+
}
|
|
16469
|
+
}
|
|
16470
|
+
handleNotification(message) {
|
|
16471
|
+
if (message.method === "thread/started") {
|
|
16472
|
+
if (isThreadStartedNotification(message.params))
|
|
16473
|
+
this.threadId = message.params.thread.id;
|
|
16474
|
+
return;
|
|
16475
|
+
}
|
|
16476
|
+
if (message.method === "turn/started") {
|
|
16477
|
+
if (isTurnStartedNotification(message.params) && message.params.threadId === this.threadId) {
|
|
16478
|
+
this.activeTurnId = message.params.turn.id;
|
|
16479
|
+
}
|
|
16480
|
+
return;
|
|
16481
|
+
}
|
|
16482
|
+
if (message.method === "turn/completed") {
|
|
16483
|
+
if (isTurnCompletedNotification(message.params) && message.params.threadId === this.threadId && message.params.turn.id === this.activeTurnId) {
|
|
16484
|
+
this.activeTurnId = null;
|
|
16485
|
+
}
|
|
16486
|
+
this.emitEvent({
|
|
16487
|
+
type: "turn_completed",
|
|
16488
|
+
turnId: isTurnCompletedNotification(message.params) ? message.params.turn.id : null
|
|
16489
|
+
});
|
|
16490
|
+
return;
|
|
16491
|
+
}
|
|
16492
|
+
if (message.method === "item/agentMessage/delta") {
|
|
16493
|
+
const event = extractAgentMessageDelta(message.params);
|
|
16494
|
+
if (event.text) {
|
|
16495
|
+
this.emitEvent({
|
|
16496
|
+
type: "agent_message_delta",
|
|
16497
|
+
itemId: event.itemId,
|
|
16498
|
+
turnId: event.turnId,
|
|
16499
|
+
text: event.text
|
|
16500
|
+
});
|
|
16501
|
+
}
|
|
16502
|
+
return;
|
|
16503
|
+
}
|
|
16504
|
+
if (message.method === "item/completed") {
|
|
16505
|
+
const event = extractCompletedAgentMessage(message.params);
|
|
16506
|
+
if (event?.text) {
|
|
16507
|
+
this.emitEvent({
|
|
16508
|
+
type: "agent_message_completed",
|
|
16509
|
+
itemId: event.itemId,
|
|
16510
|
+
turnId: event.turnId,
|
|
16511
|
+
text: event.text
|
|
16512
|
+
});
|
|
16513
|
+
}
|
|
16514
|
+
}
|
|
16515
|
+
}
|
|
16516
|
+
emitEvent(event) {
|
|
16517
|
+
if (!this.eventHandler)
|
|
16518
|
+
return;
|
|
16519
|
+
try {
|
|
16520
|
+
this.eventHandler(event);
|
|
16521
|
+
} catch (error48) {
|
|
16522
|
+
this.stderrStream.write(`meet-ai: codex app-server event handler failed: ${toErrorMessage(error48)}
|
|
16523
|
+
`);
|
|
16524
|
+
}
|
|
16525
|
+
}
|
|
16526
|
+
respondToServerRequest(message) {
|
|
16527
|
+
switch (message.method) {
|
|
16528
|
+
case "item/commandExecution/requestApproval": {
|
|
16529
|
+
this.stderrStream.write(`meet-ai: auto-resolving unsupported codex app-server request ${message.method}
|
|
16530
|
+
`);
|
|
16531
|
+
this.writeMessage({ id: message.id, result: { decision: "decline" } });
|
|
16532
|
+
return;
|
|
16533
|
+
}
|
|
16534
|
+
case "item/fileChange/requestApproval": {
|
|
16535
|
+
this.stderrStream.write(`meet-ai: auto-resolving unsupported codex app-server request ${message.method}
|
|
16536
|
+
`);
|
|
16537
|
+
this.writeMessage({ id: message.id, result: { decision: "decline" } });
|
|
16538
|
+
return;
|
|
16539
|
+
}
|
|
16540
|
+
case "item/tool/requestUserInput": {
|
|
16541
|
+
this.stderrStream.write(`meet-ai: auto-resolving unsupported codex app-server request ${message.method}
|
|
16542
|
+
`);
|
|
16543
|
+
this.writeMessage({ id: message.id, result: { answers: {} } });
|
|
16544
|
+
return;
|
|
16545
|
+
}
|
|
16546
|
+
case "mcpServer/elicitation/request": {
|
|
16547
|
+
this.stderrStream.write(`meet-ai: auto-resolving unsupported codex app-server request ${message.method}
|
|
16548
|
+
`);
|
|
16549
|
+
this.writeMessage({ id: message.id, result: { action: "cancel", content: null } });
|
|
16550
|
+
return;
|
|
16551
|
+
}
|
|
16552
|
+
case "applyPatchApproval": {
|
|
16553
|
+
this.stderrStream.write(`meet-ai: auto-resolving unsupported codex app-server request ${message.method}
|
|
16554
|
+
`);
|
|
16555
|
+
this.writeMessage({ id: message.id, result: { decision: "denied" } });
|
|
16556
|
+
return;
|
|
16557
|
+
}
|
|
16558
|
+
case "execCommandApproval": {
|
|
16559
|
+
this.stderrStream.write(`meet-ai: auto-resolving unsupported codex app-server request ${message.method}
|
|
16560
|
+
`);
|
|
16561
|
+
this.writeMessage({ id: message.id, result: { decision: "denied" } });
|
|
16562
|
+
return;
|
|
16563
|
+
}
|
|
16564
|
+
default: {
|
|
16565
|
+
this.stderrStream.write(`meet-ai: rejecting unsupported codex app-server request ${message.method}
|
|
16566
|
+
`);
|
|
16567
|
+
this.writeMessage({
|
|
16568
|
+
id: message.id,
|
|
16569
|
+
error: {
|
|
16570
|
+
message: `meet-ai app-server bridge does not support ${message.method}`
|
|
16571
|
+
}
|
|
16572
|
+
});
|
|
16573
|
+
}
|
|
16574
|
+
}
|
|
16575
|
+
}
|
|
16576
|
+
notify(method, params) {
|
|
16577
|
+
this.writeMessage(params === undefined ? { method } : { method, params });
|
|
16578
|
+
}
|
|
16579
|
+
request(method, params) {
|
|
16580
|
+
const id = this.nextRequestId++;
|
|
16581
|
+
return new Promise((resolve3, reject) => {
|
|
16582
|
+
this.pendingRequests.set(id, { resolve: resolve3, reject });
|
|
16583
|
+
try {
|
|
16584
|
+
this.writeMessage(params === undefined ? { method, id } : { method, id, params });
|
|
16585
|
+
} catch (error48) {
|
|
16586
|
+
this.pendingRequests.delete(id);
|
|
16587
|
+
reject(error48);
|
|
16588
|
+
}
|
|
16589
|
+
});
|
|
16590
|
+
}
|
|
16591
|
+
writeMessage(message) {
|
|
16592
|
+
const child = this.child;
|
|
16593
|
+
if (!child) {
|
|
16594
|
+
throw new Error("Codex app-server bridge is not connected");
|
|
16595
|
+
}
|
|
16596
|
+
child.stdin.write(`${JSON.stringify(message)}
|
|
16597
|
+
`);
|
|
16598
|
+
}
|
|
16599
|
+
}
|
|
16600
|
+
function createCodexAppServerBridge(options) {
|
|
16601
|
+
return new CodexAppServerBridge(options);
|
|
16602
|
+
}
|
|
16603
|
+
function describeCodexAppServerError(error48) {
|
|
16604
|
+
return `meet-ai: failed to inject message into Codex via app-server: ${toErrorMessage(error48)}`;
|
|
16605
|
+
}
|
|
16606
|
+
var init_codex_app_server = () => {};
|
|
16607
|
+
|
|
16608
|
+
// src/commands/listen/listen-codex.ts
|
|
16609
|
+
function formatCodexListenOutput(msg) {
|
|
16610
|
+
const lines = [
|
|
16611
|
+
`[meet-ai] ${msg.sender} ${msg.created_at ?? new Date().toISOString()}`,
|
|
16612
|
+
msg.content
|
|
16613
|
+
];
|
|
16614
|
+
if (msg.attachments?.length) {
|
|
16615
|
+
lines.push(`attachments: ${msg.attachments.join(", ")}`);
|
|
16616
|
+
}
|
|
16617
|
+
return `${lines.join(`
|
|
16618
|
+
`)}
|
|
16619
|
+
`;
|
|
16620
|
+
}
|
|
16621
|
+
function formatCodexInjectionOutput(result) {
|
|
16622
|
+
return `[meet-ai->codex] ${result.mode} ${result.turnId}
|
|
16623
|
+
`;
|
|
16624
|
+
}
|
|
16625
|
+
function isTruthyEnv(value) {
|
|
16626
|
+
if (!value)
|
|
16627
|
+
return false;
|
|
16628
|
+
const normalized = value.trim().toLowerCase();
|
|
16629
|
+
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
|
|
16630
|
+
}
|
|
16631
|
+
function normalizeFinalText(value) {
|
|
16632
|
+
return value.replace(/\r\n/g, `
|
|
16633
|
+
`).trim();
|
|
16634
|
+
}
|
|
16635
|
+
function makeMessageKey(event) {
|
|
16636
|
+
return event.itemId ?? event.turnId ?? "unknown";
|
|
16637
|
+
}
|
|
16638
|
+
function listenCodex(client, input, codexBridgeOverride) {
|
|
16639
|
+
const parsed = ListenInput.parse(input);
|
|
16640
|
+
const { roomId, exclude, senderType, team, inbox } = parsed;
|
|
16641
|
+
let shutdownStarted = false;
|
|
16642
|
+
if (team || inbox) {
|
|
16643
|
+
const flags = [team ? "--team" : null, inbox ? "--inbox" : null].filter(Boolean).join(", ");
|
|
16644
|
+
throw new Error(`Codex listen does not support Claude inbox routing flags (${flags}). Run meet-ai listen without Claude-specific routing options.`);
|
|
16645
|
+
}
|
|
16646
|
+
const terminal = createTerminalControlHandler({ client, roomId });
|
|
16647
|
+
const codexBridge = codexBridgeOverride ?? createCodexAppServerBridge({
|
|
16648
|
+
threadId: null,
|
|
16649
|
+
cwd: process.cwd(),
|
|
16650
|
+
experimentalApi: isTruthyEnv(process.env.MEET_AI_CODEX_APP_SERVER_EXPERIMENTAL)
|
|
16651
|
+
});
|
|
16652
|
+
const bootstrapPrompt = process.env.MEET_AI_CODEX_BOOTSTRAP_PROMPT?.trim();
|
|
16653
|
+
const codexSender = process.env.MEET_AI_AGENT_NAME?.trim() || "codex";
|
|
16654
|
+
const messageState = new Map;
|
|
16655
|
+
let publishQueue = Promise.resolve();
|
|
16656
|
+
const enqueuePublish = (task) => {
|
|
16657
|
+
publishQueue = publishQueue.then(task, task).catch((error48) => {
|
|
16658
|
+
console.error(`meet-ai: failed to publish Codex output to room: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
16659
|
+
});
|
|
16660
|
+
};
|
|
16661
|
+
const publishBufferedMessage = (key) => {
|
|
16662
|
+
const state = messageState.get(key);
|
|
16663
|
+
const text = normalizeFinalText(state?.text ?? "");
|
|
16664
|
+
if (!state || state.sent || state.sending || !text)
|
|
16665
|
+
return;
|
|
16666
|
+
state.sending = true;
|
|
16667
|
+
enqueuePublish(async () => {
|
|
16668
|
+
try {
|
|
16669
|
+
await client.sendMessage(roomId, codexSender, text);
|
|
16670
|
+
state.sent = true;
|
|
16671
|
+
} finally {
|
|
16672
|
+
state.sending = false;
|
|
16673
|
+
}
|
|
16674
|
+
});
|
|
16675
|
+
};
|
|
16676
|
+
const mergeEventText = (event) => {
|
|
16677
|
+
const key = makeMessageKey(event);
|
|
16678
|
+
const nextText = event.text.replace(/\r\n/g, `
|
|
16679
|
+
`);
|
|
16680
|
+
if (!nextText)
|
|
16681
|
+
return;
|
|
16682
|
+
const existing = messageState.get(key);
|
|
16683
|
+
if (!existing) {
|
|
16684
|
+
messageState.set(key, { turnId: event.turnId, text: nextText, sent: false, sending: false });
|
|
16685
|
+
return;
|
|
16686
|
+
}
|
|
16687
|
+
existing.turnId = event.turnId ?? existing.turnId;
|
|
16688
|
+
if (event.type === "agent_message_completed") {
|
|
16689
|
+
existing.text = nextText;
|
|
16690
|
+
return;
|
|
16691
|
+
}
|
|
16692
|
+
existing.text += nextText;
|
|
16693
|
+
};
|
|
16694
|
+
codexBridge.setEventHandler((event) => {
|
|
16695
|
+
if (event.type === "agent_message_delta" || event.type === "agent_message_completed") {
|
|
16696
|
+
mergeEventText(event);
|
|
16697
|
+
if (event.type === "agent_message_completed") {
|
|
16698
|
+
publishBufferedMessage(makeMessageKey(event));
|
|
16699
|
+
}
|
|
16700
|
+
return;
|
|
16701
|
+
}
|
|
16702
|
+
if (event.type === "turn_completed") {
|
|
16703
|
+
for (const [key, state] of messageState.entries()) {
|
|
16704
|
+
if (state.turnId === event.turnId || !event.turnId && !state.sent) {
|
|
16705
|
+
publishBufferedMessage(key);
|
|
16706
|
+
}
|
|
16707
|
+
}
|
|
16708
|
+
}
|
|
16709
|
+
});
|
|
16710
|
+
const injectMessage = (message) => {
|
|
16711
|
+
codexBridge.injectText({
|
|
16712
|
+
sender: message.sender,
|
|
16713
|
+
content: message.content,
|
|
16714
|
+
timestamp: new Date().toISOString(),
|
|
16715
|
+
attachments: message.attachments
|
|
16716
|
+
}).then((result) => {
|
|
16717
|
+
appendCodexInboxEntry(result.threadId, {
|
|
16718
|
+
from: `meet-ai:${message.sender}`,
|
|
16719
|
+
text: message.content,
|
|
16720
|
+
timestamp: new Date().toISOString(),
|
|
16721
|
+
read: false,
|
|
16722
|
+
...message.attachments?.length ? { attachments: message.attachments } : {}
|
|
16723
|
+
});
|
|
16724
|
+
console.log(formatCodexInjectionOutput(result));
|
|
16725
|
+
}).catch((error48) => {
|
|
16726
|
+
console.error(describeCodexAppServerError(error48));
|
|
16727
|
+
});
|
|
16728
|
+
};
|
|
16729
|
+
const onMessage = (msg) => {
|
|
16730
|
+
if (terminal.handle(msg))
|
|
16731
|
+
return;
|
|
16732
|
+
if (msg.id && msg.room_id && (msg.attachment_count ?? 0) > 0) {
|
|
16733
|
+
downloadMessageAttachments(client, msg.room_id, msg.id).then((paths) => {
|
|
16734
|
+
const output = paths.length ? { ...msg, attachments: paths } : msg;
|
|
16735
|
+
console.log(formatCodexListenOutput(output));
|
|
16736
|
+
injectMessage({
|
|
16737
|
+
sender: msg.sender,
|
|
16738
|
+
content: msg.content,
|
|
16739
|
+
attachments: paths
|
|
16740
|
+
});
|
|
16741
|
+
});
|
|
16742
|
+
return;
|
|
16005
16743
|
}
|
|
16744
|
+
console.log(formatCodexListenOutput(msg));
|
|
16745
|
+
injectMessage({
|
|
16746
|
+
sender: msg.sender,
|
|
16747
|
+
content: msg.content
|
|
16748
|
+
});
|
|
16749
|
+
};
|
|
16750
|
+
const ws = client.listen(roomId, { exclude, senderType, onMessage });
|
|
16751
|
+
if (bootstrapPrompt) {
|
|
16752
|
+
const bootstrapRequest = codexBridge.injectPrompt(bootstrapPrompt);
|
|
16753
|
+
bootstrapRequest.then((result) => {
|
|
16754
|
+
console.log(formatCodexInjectionOutput(result));
|
|
16755
|
+
}).catch((error48) => {
|
|
16756
|
+
console.error(describeCodexAppServerError(error48));
|
|
16757
|
+
});
|
|
16758
|
+
}
|
|
16759
|
+
function shutdown() {
|
|
16760
|
+
if (shutdownStarted)
|
|
16761
|
+
return;
|
|
16762
|
+
shutdownStarted = true;
|
|
16763
|
+
terminal.shutdown();
|
|
16764
|
+
codexBridge.setEventHandler(null);
|
|
16765
|
+
codexBridge.close();
|
|
16006
16766
|
if (ws.readyState === WebSocket.OPEN) {
|
|
16007
16767
|
ws.close(1000, "client shutdown");
|
|
16008
16768
|
}
|
|
@@ -16013,10 +16773,11 @@ function listen(client, input, inboxRouter) {
|
|
|
16013
16773
|
process.on("SIGHUP", shutdown);
|
|
16014
16774
|
return ws;
|
|
16015
16775
|
}
|
|
16016
|
-
var
|
|
16776
|
+
var init_listen_codex = __esm(() => {
|
|
16777
|
+
init_codex();
|
|
16778
|
+
init_codex_app_server();
|
|
16017
16779
|
init_schema6();
|
|
16018
|
-
|
|
16019
|
-
init_tmux_client();
|
|
16780
|
+
init_shared();
|
|
16020
16781
|
});
|
|
16021
16782
|
|
|
16022
16783
|
// src/commands/listen/command.ts
|
|
@@ -16026,10 +16787,11 @@ __export(exports_command6, {
|
|
|
16026
16787
|
});
|
|
16027
16788
|
var command_default6;
|
|
16028
16789
|
var init_command6 = __esm(() => {
|
|
16029
|
-
init_dist();
|
|
16030
16790
|
init_bootstrap();
|
|
16031
|
-
init_usecase6();
|
|
16032
16791
|
init_output();
|
|
16792
|
+
init_dist();
|
|
16793
|
+
init_listen_claude();
|
|
16794
|
+
init_listen_codex();
|
|
16033
16795
|
command_default6 = defineCommand({
|
|
16034
16796
|
meta: {
|
|
16035
16797
|
name: "listen",
|
|
@@ -16060,25 +16822,24 @@ var init_command6 = __esm(() => {
|
|
|
16060
16822
|
type: "string",
|
|
16061
16823
|
alias: "i",
|
|
16062
16824
|
description: "Inbox name for routing (requires --team)"
|
|
16063
|
-
},
|
|
16064
|
-
"stdin-pane": {
|
|
16065
|
-
type: "string",
|
|
16066
|
-
alias: "s",
|
|
16067
|
-
description: "tmux pane ID to inject non-@mention messages into via send-keys"
|
|
16068
16825
|
}
|
|
16069
16826
|
},
|
|
16070
16827
|
run({ args }) {
|
|
16071
16828
|
try {
|
|
16072
16829
|
const client = getClient();
|
|
16073
16830
|
const container2 = getContainer();
|
|
16074
|
-
|
|
16831
|
+
const input = {
|
|
16075
16832
|
roomId: args.roomId,
|
|
16076
16833
|
exclude: args.exclude,
|
|
16077
16834
|
senderType: args["sender-type"],
|
|
16078
16835
|
team: args.team,
|
|
16079
|
-
inbox: args.inbox
|
|
16080
|
-
|
|
16081
|
-
|
|
16836
|
+
inbox: args.inbox
|
|
16837
|
+
};
|
|
16838
|
+
if (getMeetAiRuntime() === "codex") {
|
|
16839
|
+
listenCodex(client, input);
|
|
16840
|
+
return;
|
|
16841
|
+
}
|
|
16842
|
+
listenClaude(client, input, container2.inboxRouter);
|
|
16082
16843
|
} catch (error48) {
|
|
16083
16844
|
err(error48 instanceof Error ? error48.message : String(error48));
|
|
16084
16845
|
process.exit(1);
|
|
@@ -16110,7 +16871,7 @@ async function sendTeamInfo(client, input) {
|
|
|
16110
16871
|
await client.sendTeamInfo(parsed.roomId, parsed.payload);
|
|
16111
16872
|
ok("Team info sent");
|
|
16112
16873
|
}
|
|
16113
|
-
var
|
|
16874
|
+
var init_usecase6 = __esm(() => {
|
|
16114
16875
|
init_schema7();
|
|
16115
16876
|
init_output();
|
|
16116
16877
|
});
|
|
@@ -16124,7 +16885,7 @@ var command_default7;
|
|
|
16124
16885
|
var init_command7 = __esm(() => {
|
|
16125
16886
|
init_dist();
|
|
16126
16887
|
init_bootstrap();
|
|
16127
|
-
|
|
16888
|
+
init_usecase6();
|
|
16128
16889
|
init_output();
|
|
16129
16890
|
command_default7 = defineCommand({
|
|
16130
16891
|
meta: {
|
|
@@ -16178,7 +16939,7 @@ async function sendTasks(client, input) {
|
|
|
16178
16939
|
await client.sendTasks(parsed.roomId, parsed.payload);
|
|
16179
16940
|
ok("Tasks info sent");
|
|
16180
16941
|
}
|
|
16181
|
-
var
|
|
16942
|
+
var init_usecase7 = __esm(() => {
|
|
16182
16943
|
init_schema8();
|
|
16183
16944
|
init_output();
|
|
16184
16945
|
});
|
|
@@ -16192,7 +16953,7 @@ var command_default8;
|
|
|
16192
16953
|
var init_command8 = __esm(() => {
|
|
16193
16954
|
init_dist();
|
|
16194
16955
|
init_bootstrap();
|
|
16195
|
-
|
|
16956
|
+
init_usecase7();
|
|
16196
16957
|
init_output();
|
|
16197
16958
|
command_default8 = defineCommand({
|
|
16198
16959
|
meta: {
|
|
@@ -16239,7 +17000,7 @@ async function downloadAttachment(client, input) {
|
|
|
16239
17000
|
ok(localPath);
|
|
16240
17001
|
return localPath;
|
|
16241
17002
|
}
|
|
16242
|
-
var
|
|
17003
|
+
var init_usecase8 = __esm(() => {
|
|
16243
17004
|
init_schema9();
|
|
16244
17005
|
init_output();
|
|
16245
17006
|
});
|
|
@@ -16253,7 +17014,7 @@ var command_default9;
|
|
|
16253
17014
|
var init_command9 = __esm(() => {
|
|
16254
17015
|
init_dist();
|
|
16255
17016
|
init_bootstrap();
|
|
16256
|
-
|
|
17017
|
+
init_usecase8();
|
|
16257
17018
|
init_output();
|
|
16258
17019
|
command_default9 = defineCommand({
|
|
16259
17020
|
meta: {
|
|
@@ -16316,12 +17077,12 @@ var init_command10 = __esm(() => {
|
|
|
16316
17077
|
});
|
|
16317
17078
|
|
|
16318
17079
|
// src/lib/hooks/find-room.ts
|
|
16319
|
-
import { readdirSync, readFileSync as
|
|
16320
|
-
import { join as
|
|
16321
|
-
import { createInterface } from "node:readline";
|
|
17080
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3, createReadStream } from "node:fs";
|
|
17081
|
+
import { join as join3 } from "node:path";
|
|
17082
|
+
import { createInterface as createInterface2 } from "node:readline";
|
|
16322
17083
|
async function extractTeamName(transcriptPath) {
|
|
16323
17084
|
try {
|
|
16324
|
-
const rl =
|
|
17085
|
+
const rl = createInterface2({
|
|
16325
17086
|
input: createReadStream(transcriptPath, "utf-8"),
|
|
16326
17087
|
crlfDelay: Infinity
|
|
16327
17088
|
});
|
|
@@ -16349,7 +17110,7 @@ function registerSession(filePath, data, sessionId) {
|
|
|
16349
17110
|
}
|
|
16350
17111
|
data.session_ids = ids;
|
|
16351
17112
|
try {
|
|
16352
|
-
|
|
17113
|
+
writeFileSync3(filePath, JSON.stringify(data));
|
|
16353
17114
|
} catch {}
|
|
16354
17115
|
}
|
|
16355
17116
|
async function findRoom(sessionId, teamsDir, transcriptPath) {
|
|
@@ -16357,9 +17118,9 @@ async function findRoom(sessionId, teamsDir, transcriptPath) {
|
|
|
16357
17118
|
if (transcriptPath) {
|
|
16358
17119
|
const teamName = await extractTeamName(transcriptPath);
|
|
16359
17120
|
if (teamName) {
|
|
16360
|
-
const filePath =
|
|
17121
|
+
const filePath = join3(dir, teamName, "meet-ai.json");
|
|
16361
17122
|
try {
|
|
16362
|
-
const raw =
|
|
17123
|
+
const raw = readFileSync4(filePath, "utf-8");
|
|
16363
17124
|
const data = JSON.parse(raw);
|
|
16364
17125
|
registerSession(filePath, data, sessionId);
|
|
16365
17126
|
if (data.room_id)
|
|
@@ -16369,14 +17130,14 @@ async function findRoom(sessionId, teamsDir, transcriptPath) {
|
|
|
16369
17130
|
}
|
|
16370
17131
|
let entries;
|
|
16371
17132
|
try {
|
|
16372
|
-
entries =
|
|
17133
|
+
entries = readdirSync2(dir);
|
|
16373
17134
|
} catch {
|
|
16374
17135
|
return null;
|
|
16375
17136
|
}
|
|
16376
17137
|
for (const entry of entries) {
|
|
16377
|
-
const filePath =
|
|
17138
|
+
const filePath = join3(dir, entry, "meet-ai.json");
|
|
16378
17139
|
try {
|
|
16379
|
-
const raw =
|
|
17140
|
+
const raw = readFileSync4(filePath, "utf-8");
|
|
16380
17141
|
const data = JSON.parse(raw);
|
|
16381
17142
|
const knownIds = data.session_ids ?? [data.session_id];
|
|
16382
17143
|
if (knownIds.includes(sessionId) || data.session_id === sessionId) {
|
|
@@ -16539,17 +17300,17 @@ var init_cookie = __esm(() => {
|
|
|
16539
17300
|
var init_fetch_result_please = () => {};
|
|
16540
17301
|
|
|
16541
17302
|
// ../../node_modules/.bun/hono@4.11.8/node_modules/hono/dist/client/utils.js
|
|
16542
|
-
function
|
|
17303
|
+
function isObject3(item) {
|
|
16543
17304
|
return typeof item === "object" && item !== null && !Array.isArray(item);
|
|
16544
17305
|
}
|
|
16545
17306
|
function deepMerge(target, source) {
|
|
16546
|
-
if (!
|
|
17307
|
+
if (!isObject3(target) && !isObject3(source)) {
|
|
16547
17308
|
return source;
|
|
16548
17309
|
}
|
|
16549
17310
|
const merged = { ...target };
|
|
16550
17311
|
for (const key in source) {
|
|
16551
17312
|
const value = source[key];
|
|
16552
|
-
if (
|
|
17313
|
+
if (isObject3(merged[key]) && isObject3(value)) {
|
|
16553
17314
|
merged[key] = deepMerge(merged[key], value);
|
|
16554
17315
|
} else {
|
|
16555
17316
|
merged[key] = value;
|
|
@@ -16829,23 +17590,23 @@ var init_hooks = __esm(() => {
|
|
|
16829
17590
|
});
|
|
16830
17591
|
|
|
16831
17592
|
// src/commands/hook/log-tool-use/usecase.ts
|
|
16832
|
-
import { readFileSync as
|
|
17593
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, statSync as statSync3, rmSync } from "node:fs";
|
|
16833
17594
|
function getOrCreateParentId(sessionId) {
|
|
16834
17595
|
const path = `/tmp/meet-ai-hook-${sessionId}.msgid`;
|
|
16835
17596
|
try {
|
|
16836
|
-
const mtime =
|
|
17597
|
+
const mtime = statSync3(path).mtimeMs;
|
|
16837
17598
|
if (Date.now() - mtime > PARENT_MSG_TTL_SEC * 1000) {
|
|
16838
17599
|
rmSync(path, { force: true });
|
|
16839
17600
|
return null;
|
|
16840
17601
|
}
|
|
16841
|
-
return
|
|
17602
|
+
return readFileSync5(path, "utf-8").trim() || null;
|
|
16842
17603
|
} catch {
|
|
16843
17604
|
return null;
|
|
16844
17605
|
}
|
|
16845
17606
|
}
|
|
16846
17607
|
function saveParentId(sessionId, msgId) {
|
|
16847
17608
|
try {
|
|
16848
|
-
|
|
17609
|
+
writeFileSync4(`/tmp/meet-ai-hook-${sessionId}.msgid`, msgId);
|
|
16849
17610
|
} catch {}
|
|
16850
17611
|
}
|
|
16851
17612
|
async function processHookInput(rawInput, teamsDir) {
|
|
@@ -16949,7 +17710,7 @@ async function processHookInput(rawInput, teamsDir) {
|
|
|
16949
17710
|
return "sent";
|
|
16950
17711
|
}
|
|
16951
17712
|
var PARENT_MSG_TTL_SEC = 120;
|
|
16952
|
-
var
|
|
17713
|
+
var init_usecase9 = __esm(() => {
|
|
16953
17714
|
init_hooks();
|
|
16954
17715
|
});
|
|
16955
17716
|
|
|
@@ -16961,7 +17722,7 @@ __export(exports_command11, {
|
|
|
16961
17722
|
var command_default11;
|
|
16962
17723
|
var init_command11 = __esm(() => {
|
|
16963
17724
|
init_dist();
|
|
16964
|
-
|
|
17725
|
+
init_usecase9();
|
|
16965
17726
|
command_default11 = defineCommand({
|
|
16966
17727
|
meta: {
|
|
16967
17728
|
name: "log-tool-use",
|
|
@@ -17126,7 +17887,7 @@ async function processPlanReview(rawInput, teamsDir) {
|
|
|
17126
17887
|
}
|
|
17127
17888
|
}
|
|
17128
17889
|
var POLL_INTERVAL_MS = 2000, POLL_TIMEOUT_MS = 2592000000;
|
|
17129
|
-
var
|
|
17890
|
+
var init_usecase10 = __esm(() => {
|
|
17130
17891
|
init_client3();
|
|
17131
17892
|
init_find_room();
|
|
17132
17893
|
});
|
|
@@ -17150,7 +17911,7 @@ var init_command12 = __esm(() => {
|
|
|
17150
17911
|
for await (const chunk of process.stdin) {
|
|
17151
17912
|
input += chunk;
|
|
17152
17913
|
}
|
|
17153
|
-
const { processPlanReview: processPlanReview2 } = await Promise.resolve().then(() => (
|
|
17914
|
+
const { processPlanReview: processPlanReview2 } = await Promise.resolve().then(() => (init_usecase10(), exports_usecase));
|
|
17154
17915
|
await processPlanReview2(input);
|
|
17155
17916
|
} catch (error48) {
|
|
17156
17917
|
process.stderr.write(`[plan-review] fatal: ${error48}
|
|
@@ -17222,7 +17983,7 @@ async function pollForAnswer(client, roomId, reviewId, pollInterval = POLL_INTER
|
|
|
17222
17983
|
process.stderr.write(`[question-review] poll error: ${error48}
|
|
17223
17984
|
`);
|
|
17224
17985
|
}
|
|
17225
|
-
await new Promise((
|
|
17986
|
+
await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
|
|
17226
17987
|
}
|
|
17227
17988
|
return null;
|
|
17228
17989
|
}
|
|
@@ -17322,7 +18083,7 @@ async function processQuestionReview(rawInput, teamsDir, opts) {
|
|
|
17322
18083
|
}
|
|
17323
18084
|
}
|
|
17324
18085
|
var POLL_INTERVAL_MS2 = 2000, POLL_TIMEOUT_MS2 = 1800000;
|
|
17325
|
-
var
|
|
18086
|
+
var init_usecase11 = __esm(() => {
|
|
17326
18087
|
init_client3();
|
|
17327
18088
|
init_find_room();
|
|
17328
18089
|
});
|
|
@@ -17335,7 +18096,7 @@ __export(exports_command13, {
|
|
|
17335
18096
|
var command_default13;
|
|
17336
18097
|
var init_command13 = __esm(() => {
|
|
17337
18098
|
init_dist();
|
|
17338
|
-
|
|
18099
|
+
init_usecase11();
|
|
17339
18100
|
command_default13 = defineCommand({
|
|
17340
18101
|
meta: {
|
|
17341
18102
|
name: "question-review",
|
|
@@ -17414,7 +18175,7 @@ async function pollForDecision2(client, roomId, reviewId, pollInterval = POLL_IN
|
|
|
17414
18175
|
process.stderr.write(`[permission-review] poll error: ${error48}
|
|
17415
18176
|
`);
|
|
17416
18177
|
}
|
|
17417
|
-
await new Promise((
|
|
18178
|
+
await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
|
|
17418
18179
|
}
|
|
17419
18180
|
return null;
|
|
17420
18181
|
}
|
|
@@ -17520,7 +18281,7 @@ async function processPermissionReview(rawInput, teamsDir, opts) {
|
|
|
17520
18281
|
}
|
|
17521
18282
|
}
|
|
17522
18283
|
var POLL_INTERVAL_MS3 = 2000, POLL_TIMEOUT_MS3 = 1800000;
|
|
17523
|
-
var
|
|
18284
|
+
var init_usecase12 = __esm(() => {
|
|
17524
18285
|
init_client3();
|
|
17525
18286
|
init_find_room();
|
|
17526
18287
|
});
|
|
@@ -17533,7 +18294,7 @@ __export(exports_command14, {
|
|
|
17533
18294
|
var command_default14;
|
|
17534
18295
|
var init_command14 = __esm(() => {
|
|
17535
18296
|
init_dist();
|
|
17536
|
-
|
|
18297
|
+
init_usecase12();
|
|
17537
18298
|
command_default14 = defineCommand({
|
|
17538
18299
|
meta: {
|
|
17539
18300
|
name: "permission-review",
|
|
@@ -17578,21 +18339,21 @@ var init_command15 = __esm(() => {
|
|
|
17578
18339
|
});
|
|
17579
18340
|
|
|
17580
18341
|
// src/commands/setup-hooks/usecase.ts
|
|
17581
|
-
import { existsSync as
|
|
18342
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
17582
18343
|
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
17583
|
-
import { homedir as
|
|
17584
|
-
import { resolve as
|
|
18344
|
+
import { homedir as homedir3 } from "node:os";
|
|
18345
|
+
import { resolve as resolve3, dirname as dirname3 } from "node:path";
|
|
17585
18346
|
function isMeetAiHook(entry) {
|
|
17586
18347
|
return entry.hooks?.some((h) => typeof h.command === "string" && h.command.startsWith("meet-ai hook ")) ?? false;
|
|
17587
18348
|
}
|
|
17588
18349
|
function getSettingsPath(project) {
|
|
17589
18350
|
if (project) {
|
|
17590
|
-
return
|
|
18351
|
+
return resolve3(process.cwd(), ".claude", "settings.json");
|
|
17591
18352
|
}
|
|
17592
|
-
return
|
|
18353
|
+
return resolve3(homedir3(), ".claude", "settings.json");
|
|
17593
18354
|
}
|
|
17594
18355
|
async function readSettings(path) {
|
|
17595
|
-
if (!
|
|
18356
|
+
if (!existsSync4(path)) {
|
|
17596
18357
|
return {};
|
|
17597
18358
|
}
|
|
17598
18359
|
const raw = await readFile(path, "utf-8");
|
|
@@ -17674,7 +18435,7 @@ async function setupHooks(options) {
|
|
|
17674
18435
|
if (Object.keys(cleaned).length === 0) {
|
|
17675
18436
|
delete updated.hooks;
|
|
17676
18437
|
}
|
|
17677
|
-
await mkdir(
|
|
18438
|
+
await mkdir(dirname3(settingsPath), { recursive: true });
|
|
17678
18439
|
await writeFile(settingsPath, `${JSON.stringify(updated, null, 2)}
|
|
17679
18440
|
`);
|
|
17680
18441
|
for (const r of removed) {
|
|
@@ -17691,7 +18452,7 @@ async function setupHooks(options) {
|
|
|
17691
18452
|
return;
|
|
17692
18453
|
}
|
|
17693
18454
|
const updated = { ...settings, hooks: merged };
|
|
17694
|
-
await mkdir(
|
|
18455
|
+
await mkdir(dirname3(settingsPath), { recursive: true });
|
|
17695
18456
|
await writeFile(settingsPath, `${JSON.stringify(updated, null, 2)}
|
|
17696
18457
|
`);
|
|
17697
18458
|
for (const a of added) {
|
|
@@ -17701,7 +18462,7 @@ async function setupHooks(options) {
|
|
|
17701
18462
|
}
|
|
17702
18463
|
}
|
|
17703
18464
|
var import_picocolors2, MEET_AI_HOOKS;
|
|
17704
|
-
var
|
|
18465
|
+
var init_usecase13 = __esm(() => {
|
|
17705
18466
|
init_output();
|
|
17706
18467
|
import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
17707
18468
|
MEET_AI_HOOKS = {
|
|
@@ -17760,7 +18521,7 @@ __export(exports_command16, {
|
|
|
17760
18521
|
var command_default16;
|
|
17761
18522
|
var init_command16 = __esm(() => {
|
|
17762
18523
|
init_dist();
|
|
17763
|
-
|
|
18524
|
+
init_usecase13();
|
|
17764
18525
|
init_output();
|
|
17765
18526
|
command_default16 = defineCommand({
|
|
17766
18527
|
meta: {
|
|
@@ -17800,10 +18561,10 @@ var init_command16 = __esm(() => {
|
|
|
17800
18561
|
});
|
|
17801
18562
|
|
|
17802
18563
|
// src/commands/list-commands/usecase.ts
|
|
17803
|
-
import { existsSync as
|
|
18564
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
17804
18565
|
import { readFile as readFile2, readdir } from "node:fs/promises";
|
|
17805
|
-
import { homedir as
|
|
17806
|
-
import { join as
|
|
18566
|
+
import { homedir as homedir4 } from "node:os";
|
|
18567
|
+
import { join as join4, resolve as resolve4 } from "node:path";
|
|
17807
18568
|
function parseYamlFrontmatter(content) {
|
|
17808
18569
|
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
17809
18570
|
if (!match)
|
|
@@ -17819,8 +18580,8 @@ function parseYamlFrontmatter(content) {
|
|
|
17819
18580
|
};
|
|
17820
18581
|
}
|
|
17821
18582
|
async function readSkillsFromDir(baseDir, source, scope) {
|
|
17822
|
-
const skillsDir =
|
|
17823
|
-
if (!
|
|
18583
|
+
const skillsDir = join4(baseDir, "skills");
|
|
18584
|
+
if (!existsSync5(skillsDir))
|
|
17824
18585
|
return [];
|
|
17825
18586
|
let entries;
|
|
17826
18587
|
try {
|
|
@@ -17830,8 +18591,8 @@ async function readSkillsFromDir(baseDir, source, scope) {
|
|
|
17830
18591
|
}
|
|
17831
18592
|
const results = [];
|
|
17832
18593
|
for (const entry of entries) {
|
|
17833
|
-
const skillFile =
|
|
17834
|
-
if (!
|
|
18594
|
+
const skillFile = join4(skillsDir, entry, "SKILL.md");
|
|
18595
|
+
if (!existsSync5(skillFile))
|
|
17835
18596
|
continue;
|
|
17836
18597
|
try {
|
|
17837
18598
|
const content = await readFile2(skillFile, "utf-8");
|
|
@@ -17854,7 +18615,7 @@ async function readSkillsFromDir(baseDir, source, scope) {
|
|
|
17854
18615
|
return results;
|
|
17855
18616
|
}
|
|
17856
18617
|
async function readCommandsFromDir(commandsDir, source, scope) {
|
|
17857
|
-
if (!
|
|
18618
|
+
if (!existsSync5(commandsDir))
|
|
17858
18619
|
return [];
|
|
17859
18620
|
const results = [];
|
|
17860
18621
|
async function scanDir(dir) {
|
|
@@ -17865,7 +18626,7 @@ async function readCommandsFromDir(commandsDir, source, scope) {
|
|
|
17865
18626
|
return;
|
|
17866
18627
|
}
|
|
17867
18628
|
for (const entry of entries) {
|
|
17868
|
-
const fullPath =
|
|
18629
|
+
const fullPath = join4(dir, entry.name);
|
|
17869
18630
|
if (entry.isDirectory()) {
|
|
17870
18631
|
await scanDir(fullPath);
|
|
17871
18632
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -17892,7 +18653,7 @@ async function readCommandsFromDir(commandsDir, source, scope) {
|
|
|
17892
18653
|
return results;
|
|
17893
18654
|
}
|
|
17894
18655
|
async function readSettings2(settingsPath) {
|
|
17895
|
-
if (!
|
|
18656
|
+
if (!existsSync5(settingsPath))
|
|
17896
18657
|
return {};
|
|
17897
18658
|
try {
|
|
17898
18659
|
const raw = await readFile2(settingsPath, "utf-8");
|
|
@@ -17902,7 +18663,7 @@ async function readSettings2(settingsPath) {
|
|
|
17902
18663
|
}
|
|
17903
18664
|
}
|
|
17904
18665
|
async function readInstalledPlugins(pluginsFile) {
|
|
17905
|
-
if (!
|
|
18666
|
+
if (!existsSync5(pluginsFile))
|
|
17906
18667
|
return {};
|
|
17907
18668
|
try {
|
|
17908
18669
|
const raw = await readFile2(pluginsFile, "utf-8");
|
|
@@ -17913,17 +18674,17 @@ async function readInstalledPlugins(pluginsFile) {
|
|
|
17913
18674
|
}
|
|
17914
18675
|
}
|
|
17915
18676
|
async function listCommands(options) {
|
|
17916
|
-
const projectPath =
|
|
17917
|
-
const userClaudeDir = options._userClaudeDir ??
|
|
17918
|
-
const pluginsFile = options._pluginsFile ??
|
|
18677
|
+
const projectPath = resolve4(options.projectPath ?? process.cwd());
|
|
18678
|
+
const userClaudeDir = options._userClaudeDir ?? join4(homedir4(), ".claude");
|
|
18679
|
+
const pluginsFile = options._pluginsFile ?? join4(homedir4(), ".claude", "plugins", "installed_plugins.json");
|
|
17919
18680
|
const results = [];
|
|
17920
18681
|
const userSkills = await readSkillsFromDir(userClaudeDir, "standalone", "user");
|
|
17921
18682
|
results.push(...userSkills);
|
|
17922
|
-
const projectClaudeDir =
|
|
18683
|
+
const projectClaudeDir = join4(projectPath, ".claude");
|
|
17923
18684
|
const projectSkills = await readSkillsFromDir(projectClaudeDir, "standalone", "project");
|
|
17924
18685
|
results.push(...projectSkills);
|
|
17925
|
-
const userSettings = await readSettings2(
|
|
17926
|
-
const projectSettings = await readSettings2(
|
|
18686
|
+
const userSettings = await readSettings2(join4(userClaudeDir, "settings.json"));
|
|
18687
|
+
const projectSettings = await readSettings2(join4(projectClaudeDir, "settings.json"));
|
|
17927
18688
|
const userEnabled = userSettings.enabledPlugins ?? {};
|
|
17928
18689
|
const projectEnabled = projectSettings.enabledPlugins ?? {};
|
|
17929
18690
|
const enabledPlugins = new Map;
|
|
@@ -17941,7 +18702,7 @@ async function listCommands(options) {
|
|
|
17941
18702
|
continue;
|
|
17942
18703
|
const { installPath } = installations[0];
|
|
17943
18704
|
const source = `plugin:${scopeName}`;
|
|
17944
|
-
const pluginCommands = await readCommandsFromDir(
|
|
18705
|
+
const pluginCommands = await readCommandsFromDir(join4(installPath, "commands"), source, pluginScope);
|
|
17945
18706
|
results.push(...pluginCommands);
|
|
17946
18707
|
const pluginSkills = await readSkillsFromDir(installPath, source, pluginScope);
|
|
17947
18708
|
results.push(...pluginSkills);
|
|
@@ -17949,7 +18710,7 @@ async function listCommands(options) {
|
|
|
17949
18710
|
}
|
|
17950
18711
|
return results;
|
|
17951
18712
|
}
|
|
17952
|
-
var
|
|
18713
|
+
var init_usecase14 = () => {};
|
|
17953
18714
|
|
|
17954
18715
|
// src/commands/list-commands/command.ts
|
|
17955
18716
|
var exports_command17 = {};
|
|
@@ -17959,7 +18720,7 @@ __export(exports_command17, {
|
|
|
17959
18720
|
var command_default17;
|
|
17960
18721
|
var init_command17 = __esm(() => {
|
|
17961
18722
|
init_dist();
|
|
17962
|
-
|
|
18723
|
+
init_usecase14();
|
|
17963
18724
|
init_output();
|
|
17964
18725
|
command_default17 = defineCommand({
|
|
17965
18726
|
meta: {
|
|
@@ -17993,8 +18754,8 @@ async function sendCommands(client, input) {
|
|
|
17993
18754
|
await client.sendCommands(input.roomId, payload);
|
|
17994
18755
|
ok("Commands sent");
|
|
17995
18756
|
}
|
|
17996
|
-
var
|
|
17997
|
-
|
|
18757
|
+
var init_usecase15 = __esm(() => {
|
|
18758
|
+
init_usecase14();
|
|
17998
18759
|
init_output();
|
|
17999
18760
|
});
|
|
18000
18761
|
|
|
@@ -18007,7 +18768,7 @@ var command_default18;
|
|
|
18007
18768
|
var init_command18 = __esm(() => {
|
|
18008
18769
|
init_dist();
|
|
18009
18770
|
init_bootstrap();
|
|
18010
|
-
|
|
18771
|
+
init_usecase15();
|
|
18011
18772
|
init_output();
|
|
18012
18773
|
command_default18 = defineCommand({
|
|
18013
18774
|
meta: {
|
|
@@ -18398,14 +19159,14 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
18398
19159
|
prevActScopeDepth !== actScopeDepth - 1 && console.error("You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. ");
|
|
18399
19160
|
actScopeDepth = prevActScopeDepth;
|
|
18400
19161
|
}
|
|
18401
|
-
function recursivelyFlushAsyncActWork(returnValue,
|
|
19162
|
+
function recursivelyFlushAsyncActWork(returnValue, resolve5, reject) {
|
|
18402
19163
|
var queue = ReactSharedInternals.actQueue;
|
|
18403
19164
|
if (queue !== null)
|
|
18404
19165
|
if (queue.length !== 0)
|
|
18405
19166
|
try {
|
|
18406
19167
|
flushActQueue(queue);
|
|
18407
19168
|
enqueueTask(function() {
|
|
18408
|
-
return recursivelyFlushAsyncActWork(returnValue,
|
|
19169
|
+
return recursivelyFlushAsyncActWork(returnValue, resolve5, reject);
|
|
18409
19170
|
});
|
|
18410
19171
|
return;
|
|
18411
19172
|
} catch (error48) {
|
|
@@ -18413,7 +19174,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
18413
19174
|
}
|
|
18414
19175
|
else
|
|
18415
19176
|
ReactSharedInternals.actQueue = null;
|
|
18416
|
-
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) :
|
|
19177
|
+
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) : resolve5(returnValue);
|
|
18417
19178
|
}
|
|
18418
19179
|
function flushActQueue(queue) {
|
|
18419
19180
|
if (!isFlushing) {
|
|
@@ -18589,14 +19350,14 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
18589
19350
|
didAwaitActCall || didWarnNoAwaitAct || (didWarnNoAwaitAct = true, console.error("You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);"));
|
|
18590
19351
|
});
|
|
18591
19352
|
return {
|
|
18592
|
-
then: function(
|
|
19353
|
+
then: function(resolve5, reject) {
|
|
18593
19354
|
didAwaitActCall = true;
|
|
18594
19355
|
thenable.then(function(returnValue) {
|
|
18595
19356
|
popActScope(prevActQueue, prevActScopeDepth);
|
|
18596
19357
|
if (prevActScopeDepth === 0) {
|
|
18597
19358
|
try {
|
|
18598
19359
|
flushActQueue(queue), enqueueTask(function() {
|
|
18599
|
-
return recursivelyFlushAsyncActWork(returnValue,
|
|
19360
|
+
return recursivelyFlushAsyncActWork(returnValue, resolve5, reject);
|
|
18600
19361
|
});
|
|
18601
19362
|
} catch (error$0) {
|
|
18602
19363
|
ReactSharedInternals.thrownErrors.push(error$0);
|
|
@@ -18607,7 +19368,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
18607
19368
|
reject(_thrownError);
|
|
18608
19369
|
}
|
|
18609
19370
|
} else
|
|
18610
|
-
|
|
19371
|
+
resolve5(returnValue);
|
|
18611
19372
|
}, function(error48) {
|
|
18612
19373
|
popActScope(prevActQueue, prevActScopeDepth);
|
|
18613
19374
|
0 < ReactSharedInternals.thrownErrors.length ? (error48 = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(error48)) : reject(error48);
|
|
@@ -18623,11 +19384,11 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
18623
19384
|
if (0 < ReactSharedInternals.thrownErrors.length)
|
|
18624
19385
|
throw callback = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, callback;
|
|
18625
19386
|
return {
|
|
18626
|
-
then: function(
|
|
19387
|
+
then: function(resolve5, reject) {
|
|
18627
19388
|
didAwaitActCall = true;
|
|
18628
19389
|
prevActScopeDepth === 0 ? (ReactSharedInternals.actQueue = queue, enqueueTask(function() {
|
|
18629
|
-
return recursivelyFlushAsyncActWork(returnValue$jscomp$0,
|
|
18630
|
-
})) :
|
|
19390
|
+
return recursivelyFlushAsyncActWork(returnValue$jscomp$0, resolve5, reject);
|
|
19391
|
+
})) : resolve5(returnValue$jscomp$0);
|
|
18631
19392
|
}
|
|
18632
19393
|
};
|
|
18633
19394
|
};
|
|
@@ -19410,14 +20171,14 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
19410
20171
|
import { PassThrough } from "node:stream";
|
|
19411
20172
|
var consoleMethods, originalMethods, patchConsole = (callback) => {
|
|
19412
20173
|
const stdout = new PassThrough;
|
|
19413
|
-
const
|
|
20174
|
+
const stderr2 = new PassThrough;
|
|
19414
20175
|
stdout.write = (data) => {
|
|
19415
20176
|
callback("stdout", data);
|
|
19416
20177
|
};
|
|
19417
|
-
|
|
20178
|
+
stderr2.write = (data) => {
|
|
19418
20179
|
callback("stderr", data);
|
|
19419
20180
|
};
|
|
19420
|
-
const internalConsole = new console.Console(stdout,
|
|
20181
|
+
const internalConsole = new console.Console(stdout, stderr2);
|
|
19421
20182
|
for (const method of consoleMethods) {
|
|
19422
20183
|
originalMethods[method] = console[method];
|
|
19423
20184
|
console[method] = internalConsole[method];
|
|
@@ -21614,12 +22375,12 @@ import { execFileSync as execFileSync2 } from "node:child_process";
|
|
|
21614
22375
|
import fs from "node:fs";
|
|
21615
22376
|
import tty from "node:tty";
|
|
21616
22377
|
function terminalSize() {
|
|
21617
|
-
const { env: env2, stdout, stderr } = process4;
|
|
22378
|
+
const { env: env2, stdout, stderr: stderr2 } = process4;
|
|
21618
22379
|
if (stdout?.columns && stdout?.rows) {
|
|
21619
22380
|
return create(stdout.columns, stdout.rows);
|
|
21620
22381
|
}
|
|
21621
|
-
if (
|
|
21622
|
-
return create(
|
|
22382
|
+
if (stderr2?.columns && stderr2?.rows) {
|
|
22383
|
+
return create(stderr2.columns, stderr2.rows);
|
|
21623
22384
|
}
|
|
21624
22385
|
if (env2.COLUMNS && env2.LINES) {
|
|
21625
22386
|
return create(env2.COLUMNS, env2.LINES);
|
|
@@ -24124,8 +24885,8 @@ It can also happen if the client has a browser extension installed which messes
|
|
|
24124
24885
|
currentEntangledActionThenable = {
|
|
24125
24886
|
status: "pending",
|
|
24126
24887
|
value: undefined,
|
|
24127
|
-
then: function(
|
|
24128
|
-
entangledListeners.push(
|
|
24888
|
+
then: function(resolve5) {
|
|
24889
|
+
entangledListeners.push(resolve5);
|
|
24129
24890
|
}
|
|
24130
24891
|
};
|
|
24131
24892
|
}
|
|
@@ -24149,8 +24910,8 @@ It can also happen if the client has a browser extension installed which messes
|
|
|
24149
24910
|
status: "pending",
|
|
24150
24911
|
value: null,
|
|
24151
24912
|
reason: null,
|
|
24152
|
-
then: function(
|
|
24153
|
-
listeners.push(
|
|
24913
|
+
then: function(resolve5) {
|
|
24914
|
+
listeners.push(resolve5);
|
|
24154
24915
|
}
|
|
24155
24916
|
};
|
|
24156
24917
|
thenable.then(function() {
|
|
@@ -50940,7 +51701,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
|
|
|
50940
51701
|
ws.onmessage = handleMessage;
|
|
50941
51702
|
ws.onopen = function() {
|
|
50942
51703
|
bridge = new src_bridge({
|
|
50943
|
-
listen: function
|
|
51704
|
+
listen: function listen(fn) {
|
|
50944
51705
|
messageListeners.push(fn);
|
|
50945
51706
|
return function() {
|
|
50946
51707
|
var index = messageListeners.indexOf(fn);
|
|
@@ -51073,7 +51834,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
|
|
|
51073
51834
|
return;
|
|
51074
51835
|
}
|
|
51075
51836
|
var wall = {
|
|
51076
|
-
listen: function
|
|
51837
|
+
listen: function listen(fn) {
|
|
51077
51838
|
onSubscribe(fn);
|
|
51078
51839
|
return function() {
|
|
51079
51840
|
onUnsubscribe(fn);
|
|
@@ -53829,7 +54590,7 @@ var init_ErrorBoundary = __esm(() => {
|
|
|
53829
54590
|
// ../../node_modules/.bun/ink@6.8.0+b7580ee3b5d80903/node_modules/ink/build/components/App.js
|
|
53830
54591
|
import { EventEmitter as EventEmitter2 } from "node:events";
|
|
53831
54592
|
import process12 from "node:process";
|
|
53832
|
-
function App({ children, stdin, stdout, stderr, writeToStdout, writeToStderr, exitOnCtrlC, onExit, setCursorPosition }) {
|
|
54593
|
+
function App({ children, stdin, stdout, stderr: stderr2, writeToStdout, writeToStderr, exitOnCtrlC, onExit, setCursorPosition }) {
|
|
53833
54594
|
const [isFocusEnabled, setIsFocusEnabled] = import_react14.useState(true);
|
|
53834
54595
|
const [activeFocusId, setActiveFocusId] = import_react14.useState(undefined);
|
|
53835
54596
|
const [, setFocusables] = import_react14.useState([]);
|
|
@@ -54101,9 +54862,9 @@ Read about how to prevent this error on https://github.com/vadimdemedes/ink/#isr
|
|
|
54101
54862
|
write: writeToStdout
|
|
54102
54863
|
}), [stdout, writeToStdout]);
|
|
54103
54864
|
const stderrContextValue = import_react14.useMemo(() => ({
|
|
54104
|
-
stderr,
|
|
54865
|
+
stderr: stderr2,
|
|
54105
54866
|
write: writeToStderr
|
|
54106
|
-
}), [
|
|
54867
|
+
}), [stderr2, writeToStderr]);
|
|
54107
54868
|
const cursorContextValue = import_react14.useMemo(() => ({
|
|
54108
54869
|
setCursorPosition
|
|
54109
54870
|
}), [setCursorPosition]);
|
|
@@ -54557,8 +55318,8 @@ class Ink {
|
|
|
54557
55318
|
}
|
|
54558
55319
|
}
|
|
54559
55320
|
async waitUntilExit() {
|
|
54560
|
-
this.exitPromise ||= new Promise((
|
|
54561
|
-
this.resolveExitPromise =
|
|
55321
|
+
this.exitPromise ||= new Promise((resolve5, reject) => {
|
|
55322
|
+
this.resolveExitPromise = resolve5;
|
|
54562
55323
|
this.rejectExitPromise = reject;
|
|
54563
55324
|
});
|
|
54564
55325
|
if (!this.beforeExitHandler) {
|
|
@@ -55394,13 +56155,88 @@ var init_build2 = __esm(async () => {
|
|
|
55394
56155
|
]);
|
|
55395
56156
|
});
|
|
55396
56157
|
|
|
56158
|
+
// src/spawner.ts
|
|
56159
|
+
import { execSync } from "node:child_process";
|
|
56160
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
56161
|
+
import { homedir as homedir5, platform as platform2 } from "node:os";
|
|
56162
|
+
import { join as join5 } from "node:path";
|
|
56163
|
+
function findBinary(binaryName, envVarName, commonPaths) {
|
|
56164
|
+
try {
|
|
56165
|
+
const command = platform2() === "win32" ? `where ${binaryName}` : `which ${binaryName}`;
|
|
56166
|
+
const result = execSync(command, { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }).trim();
|
|
56167
|
+
const binaryPath = result.split(`
|
|
56168
|
+
`)[0].trim();
|
|
56169
|
+
if (binaryPath && existsSync7(binaryPath)) {
|
|
56170
|
+
return binaryPath;
|
|
56171
|
+
}
|
|
56172
|
+
} catch {}
|
|
56173
|
+
const envPath = process.env[envVarName];
|
|
56174
|
+
if (envPath && existsSync7(envPath)) {
|
|
56175
|
+
return envPath;
|
|
56176
|
+
}
|
|
56177
|
+
for (const path of commonPaths) {
|
|
56178
|
+
if (existsSync7(path)) {
|
|
56179
|
+
return path;
|
|
56180
|
+
}
|
|
56181
|
+
}
|
|
56182
|
+
throw new Error(`${binaryName} is not installed`);
|
|
56183
|
+
}
|
|
56184
|
+
function findClaudeCli() {
|
|
56185
|
+
const home = homedir5();
|
|
56186
|
+
try {
|
|
56187
|
+
return findBinary("claude", "MEET_AI_CLAUDE_PATH", [
|
|
56188
|
+
join5(home, ".bun", "bin", "claude"),
|
|
56189
|
+
"/opt/homebrew/bin/claude",
|
|
56190
|
+
"/usr/local/bin/claude",
|
|
56191
|
+
join5(home, ".local", "bin", "claude")
|
|
56192
|
+
]);
|
|
56193
|
+
} catch {
|
|
56194
|
+
throw new Error(`
|
|
56195
|
+
Claude Code is not installed
|
|
56196
|
+
|
|
56197
|
+
Please install Claude Code:
|
|
56198
|
+
bun add -g @anthropic-ai/claude-code
|
|
56199
|
+
|
|
56200
|
+
Or set MEET_AI_CLAUDE_PATH to the Claude Code CLI path.
|
|
56201
|
+
`.trim());
|
|
56202
|
+
}
|
|
56203
|
+
}
|
|
56204
|
+
function findCodexCli() {
|
|
56205
|
+
const home = homedir5();
|
|
56206
|
+
try {
|
|
56207
|
+
return findBinary("codex", "MEET_AI_CODEX_PATH", [
|
|
56208
|
+
join5(home, ".bun", "bin", "codex"),
|
|
56209
|
+
"/opt/homebrew/bin/codex",
|
|
56210
|
+
"/usr/local/bin/codex",
|
|
56211
|
+
join5(home, ".local", "bin", "codex")
|
|
56212
|
+
]);
|
|
56213
|
+
} catch {
|
|
56214
|
+
throw new Error(`
|
|
56215
|
+
Codex CLI is not installed
|
|
56216
|
+
|
|
56217
|
+
Please install Codex:
|
|
56218
|
+
npm install -g @openai/codex
|
|
56219
|
+
|
|
56220
|
+
Or set MEET_AI_CODEX_PATH to the Codex CLI path.
|
|
56221
|
+
`.trim());
|
|
56222
|
+
}
|
|
56223
|
+
}
|
|
56224
|
+
var init_spawner = () => {};
|
|
56225
|
+
|
|
55397
56226
|
// src/lib/process-manager.ts
|
|
55398
|
-
import {
|
|
55399
|
-
import { homedir as
|
|
55400
|
-
import {
|
|
56227
|
+
import { existsSync as existsSync8, lstatSync, mkdirSync as mkdirSync3, readFileSync as readFileSync7, renameSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
56228
|
+
import { homedir as homedir6 } from "node:os";
|
|
56229
|
+
import { fileURLToPath } from "node:url";
|
|
56230
|
+
import { join as join6 } from "node:path";
|
|
56231
|
+
function getRegistryDir() {
|
|
56232
|
+
return join6(process.env.HOME ?? homedir6(), ".meet-ai");
|
|
56233
|
+
}
|
|
56234
|
+
function getRegistryPath() {
|
|
56235
|
+
return join6(getRegistryDir(), "sessions.json");
|
|
56236
|
+
}
|
|
55401
56237
|
function readRegistry() {
|
|
55402
56238
|
try {
|
|
55403
|
-
const data =
|
|
56239
|
+
const data = readFileSync7(getRegistryPath(), "utf8");
|
|
55404
56240
|
const parsed = exports_external.array(SessionEntrySchema).safeParse(JSON.parse(data));
|
|
55405
56241
|
return parsed.success ? parsed.data : [];
|
|
55406
56242
|
} catch {
|
|
@@ -55408,17 +56244,18 @@ function readRegistry() {
|
|
|
55408
56244
|
}
|
|
55409
56245
|
}
|
|
55410
56246
|
function writeRegistry(entries) {
|
|
55411
|
-
|
|
56247
|
+
const registryDir = getRegistryDir();
|
|
56248
|
+
mkdirSync3(registryDir, { recursive: true, mode: 448 });
|
|
55412
56249
|
try {
|
|
55413
|
-
const stat = lstatSync(
|
|
56250
|
+
const stat = lstatSync(registryDir);
|
|
55414
56251
|
if (!stat.isDirectory())
|
|
55415
56252
|
return;
|
|
55416
56253
|
} catch {
|
|
55417
56254
|
return;
|
|
55418
56255
|
}
|
|
55419
|
-
const tmpPath =
|
|
55420
|
-
|
|
55421
|
-
renameSync(tmpPath,
|
|
56256
|
+
const tmpPath = join6(registryDir, `sessions.${process.pid}.${Date.now()}.tmp`);
|
|
56257
|
+
writeFileSync5(tmpPath, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
56258
|
+
renameSync(tmpPath, getRegistryPath());
|
|
55422
56259
|
}
|
|
55423
56260
|
function addToRegistry(entry) {
|
|
55424
56261
|
const entries = readRegistry();
|
|
@@ -55433,6 +56270,17 @@ function removeFromRegistry(sessionName) {
|
|
|
55433
56270
|
const entries = readRegistry().filter((e) => e.sessionName !== sessionName);
|
|
55434
56271
|
writeRegistry(entries);
|
|
55435
56272
|
}
|
|
56273
|
+
function resolveSelfCliCommand() {
|
|
56274
|
+
const sourceEntry = fileURLToPath(new URL("../index.ts", import.meta.url));
|
|
56275
|
+
if (existsSync8(sourceEntry) && typeof Bun !== "undefined") {
|
|
56276
|
+
return [process.execPath, "run", sourceEntry];
|
|
56277
|
+
}
|
|
56278
|
+
const builtEntry = fileURLToPath(new URL("../index.js", import.meta.url));
|
|
56279
|
+
if (existsSync8(builtEntry)) {
|
|
56280
|
+
return [process.execPath, builtEntry];
|
|
56281
|
+
}
|
|
56282
|
+
return ["meet-ai"];
|
|
56283
|
+
}
|
|
55436
56284
|
|
|
55437
56285
|
class ProcessManager {
|
|
55438
56286
|
teams = new Map;
|
|
@@ -55446,11 +56294,12 @@ class ProcessManager {
|
|
|
55446
56294
|
sessionName(roomId) {
|
|
55447
56295
|
return `mai-${roomId}`;
|
|
55448
56296
|
}
|
|
55449
|
-
spawn(roomId, roomName) {
|
|
56297
|
+
spawn(roomId, roomName, codingAgent = "claude") {
|
|
55450
56298
|
const sessionName = this.sessionName(roomId);
|
|
55451
56299
|
const team = {
|
|
55452
56300
|
roomId,
|
|
55453
56301
|
roomName,
|
|
56302
|
+
codingAgent,
|
|
55454
56303
|
sessionName,
|
|
55455
56304
|
status: "starting",
|
|
55456
56305
|
exitCode: null,
|
|
@@ -55461,22 +56310,24 @@ class ProcessManager {
|
|
|
55461
56310
|
this.spawned++;
|
|
55462
56311
|
if (this.opts.dryRun)
|
|
55463
56312
|
return team;
|
|
55464
|
-
const fullPrompt = [
|
|
55465
|
-
`ROOM_ID: ${roomId}`,
|
|
55466
|
-
"",
|
|
55467
|
-
"You are a team lead. IMMEDIATELY:",
|
|
55468
|
-
"1. Start agent-team to start accepting commands from Meet AI",
|
|
55469
|
-
"2. Connect to the meet-ai room using the /meet-ai skill",
|
|
55470
|
-
"3. Just send a welcome message to the room, do not perform any work yet."
|
|
55471
|
-
].join(`
|
|
56313
|
+
const fullPrompt = [`ROOM_ID: ${roomId}`, "", ...this.buildPromptLines(codingAgent)].join(`
|
|
55472
56314
|
`);
|
|
55473
|
-
const
|
|
55474
|
-
|
|
55475
|
-
"
|
|
55476
|
-
|
|
55477
|
-
|
|
55478
|
-
|
|
55479
|
-
|
|
56315
|
+
const agentBinary = this.opts.agentBinaries[codingAgent];
|
|
56316
|
+
if (!agentBinary) {
|
|
56317
|
+
team.status = "error";
|
|
56318
|
+
team.lines.push(`[error] No CLI binary configured for coding agent: ${codingAgent}`);
|
|
56319
|
+
this.opts.onStatusChange?.(roomId, "error");
|
|
56320
|
+
return team;
|
|
56321
|
+
}
|
|
56322
|
+
const commandArgs = codingAgent === "codex" ? this.buildCodexListenCommandArgs(roomId) : [agentBinary, ...this.buildClaudeCommandArgs(fullPrompt)];
|
|
56323
|
+
const sessionEnv = {
|
|
56324
|
+
DISABLE_AUTOUPDATER: "1",
|
|
56325
|
+
MEET_AI_RUNTIME: codingAgent
|
|
56326
|
+
};
|
|
56327
|
+
if (codingAgent === "codex") {
|
|
56328
|
+
sessionEnv.MEET_AI_CODEX_PATH = agentBinary;
|
|
56329
|
+
sessionEnv.MEET_AI_CODEX_BOOTSTRAP_PROMPT = fullPrompt;
|
|
56330
|
+
}
|
|
55480
56331
|
for (const key of ENV_ALLOWLIST) {
|
|
55481
56332
|
const value = process.env[key];
|
|
55482
56333
|
if (value)
|
|
@@ -55485,15 +56336,21 @@ class ProcessManager {
|
|
|
55485
56336
|
if (this.opts.env)
|
|
55486
56337
|
Object.assign(sessionEnv, this.opts.env);
|
|
55487
56338
|
if (this.opts.debug) {
|
|
55488
|
-
team.lines.push(`[debug]
|
|
56339
|
+
team.lines.push(`[debug] AGENT: ${codingAgent}`);
|
|
56340
|
+
team.lines.push(`[debug] CMD: ${commandArgs.join(" ").slice(0, 200)}`);
|
|
55489
56341
|
team.lines.push(`[debug] ENV: ${Object.keys(sessionEnv).join(", ")}`);
|
|
55490
56342
|
}
|
|
55491
|
-
const commandArgs = [this.opts.claudePath, ...claudeArgs];
|
|
55492
56343
|
const result = this.tmux.newSession(sessionName, commandArgs, sessionEnv);
|
|
55493
56344
|
if (result.ok) {
|
|
55494
56345
|
team.status = "running";
|
|
55495
56346
|
this.opts.onStatusChange?.(roomId, "running");
|
|
55496
|
-
addToRegistry({
|
|
56347
|
+
addToRegistry({
|
|
56348
|
+
sessionName,
|
|
56349
|
+
roomId,
|
|
56350
|
+
roomName,
|
|
56351
|
+
codingAgent,
|
|
56352
|
+
createdAt: new Date().toISOString()
|
|
56353
|
+
});
|
|
55497
56354
|
} else {
|
|
55498
56355
|
team.status = "error";
|
|
55499
56356
|
team.lines.push(`[error] tmux: ${result.error}`);
|
|
@@ -55505,6 +56362,7 @@ class ProcessManager {
|
|
|
55505
56362
|
this.teams.set(roomId, {
|
|
55506
56363
|
roomId,
|
|
55507
56364
|
roomName,
|
|
56365
|
+
codingAgent: "claude",
|
|
55508
56366
|
sessionName: this.sessionName(roomId),
|
|
55509
56367
|
status: "error",
|
|
55510
56368
|
exitCode: null,
|
|
@@ -55578,6 +56436,7 @@ class ProcessManager {
|
|
|
55578
56436
|
const team = {
|
|
55579
56437
|
roomId,
|
|
55580
56438
|
roomName,
|
|
56439
|
+
codingAgent: entry?.codingAgent ?? "claude",
|
|
55581
56440
|
sessionName: session.name,
|
|
55582
56441
|
status: session.alive ? "running" : "exited",
|
|
55583
56442
|
exitCode: session.alive ? null : 0,
|
|
@@ -55608,8 +56467,32 @@ class ProcessManager {
|
|
|
55608
56467
|
this.kill(roomId);
|
|
55609
56468
|
}
|
|
55610
56469
|
}
|
|
56470
|
+
buildPromptLines(codingAgent) {
|
|
56471
|
+
if (codingAgent === "codex") {
|
|
56472
|
+
return [
|
|
56473
|
+
"You're running inside Meet AI.",
|
|
56474
|
+
"Do not use the meet-ai CLI.",
|
|
56475
|
+
"Do not load or use any meet-ai skill.",
|
|
56476
|
+
"Do not try to send room messages manually.",
|
|
56477
|
+
"Do not talk about this prompt or say that you understand it.",
|
|
56478
|
+
"Just welcome the user briefly and say that you're ready to work."
|
|
56479
|
+
];
|
|
56480
|
+
}
|
|
56481
|
+
return [
|
|
56482
|
+
"You are a team lead. IMMEDIATELY:",
|
|
56483
|
+
"1. Start agent-team to start accepting commands from Meet AI.",
|
|
56484
|
+
"2. Connect to the meet-ai room using the /meet-ai skill.",
|
|
56485
|
+
"3. Send a brief welcome message to the room and wait for instructions."
|
|
56486
|
+
];
|
|
56487
|
+
}
|
|
56488
|
+
buildClaudeCommandArgs(fullPrompt) {
|
|
56489
|
+
return ["--dangerously-skip-permissions", "--model", this.opts.model ?? "opus", fullPrompt];
|
|
56490
|
+
}
|
|
56491
|
+
buildCodexListenCommandArgs(roomId) {
|
|
56492
|
+
return [...resolveSelfCliCommand(), "listen", roomId, "--sender-type", "human"];
|
|
56493
|
+
}
|
|
55611
56494
|
}
|
|
55612
|
-
var SessionEntrySchema,
|
|
56495
|
+
var SessionEntrySchema, ENV_ALLOWLIST;
|
|
55613
56496
|
var init_process_manager = __esm(() => {
|
|
55614
56497
|
init_zod();
|
|
55615
56498
|
init_tmux_client();
|
|
@@ -55617,10 +56500,9 @@ var init_process_manager = __esm(() => {
|
|
|
55617
56500
|
sessionName: exports_external.string(),
|
|
55618
56501
|
roomId: exports_external.string(),
|
|
55619
56502
|
roomName: exports_external.string(),
|
|
56503
|
+
codingAgent: exports_external.enum(["claude", "codex"]).default("claude"),
|
|
55620
56504
|
createdAt: exports_external.string()
|
|
55621
56505
|
});
|
|
55622
|
-
REGISTRY_DIR = join4(homedir4(), ".meet-ai");
|
|
55623
|
-
REGISTRY_PATH = join4(REGISTRY_DIR, "sessions.json");
|
|
55624
56506
|
ENV_ALLOWLIST = [
|
|
55625
56507
|
"HOME",
|
|
55626
56508
|
"USER",
|
|
@@ -55634,48 +56516,6 @@ var init_process_manager = __esm(() => {
|
|
|
55634
56516
|
];
|
|
55635
56517
|
});
|
|
55636
56518
|
|
|
55637
|
-
// src/spawner.ts
|
|
55638
|
-
import { execSync } from "node:child_process";
|
|
55639
|
-
import { existsSync as existsSync6 } from "node:fs";
|
|
55640
|
-
import { homedir as homedir5, platform as platform2 } from "node:os";
|
|
55641
|
-
import { join as join5 } from "node:path";
|
|
55642
|
-
function findClaudeCli() {
|
|
55643
|
-
try {
|
|
55644
|
-
const command = platform2() === "win32" ? "where claude" : "which claude";
|
|
55645
|
-
const result = execSync(command, { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }).trim();
|
|
55646
|
-
const claudePath = result.split(`
|
|
55647
|
-
`)[0].trim();
|
|
55648
|
-
if (claudePath && existsSync6(claudePath)) {
|
|
55649
|
-
return claudePath;
|
|
55650
|
-
}
|
|
55651
|
-
} catch {}
|
|
55652
|
-
const envPath = process.env.MEET_AI_CLAUDE_PATH;
|
|
55653
|
-
if (envPath && existsSync6(envPath)) {
|
|
55654
|
-
return envPath;
|
|
55655
|
-
}
|
|
55656
|
-
const home = homedir5();
|
|
55657
|
-
const commonPaths = [
|
|
55658
|
-
join5(home, ".bun", "bin", "claude"),
|
|
55659
|
-
"/opt/homebrew/bin/claude",
|
|
55660
|
-
"/usr/local/bin/claude",
|
|
55661
|
-
join5(home, ".local", "bin", "claude")
|
|
55662
|
-
];
|
|
55663
|
-
for (const path of commonPaths) {
|
|
55664
|
-
if (existsSync6(path)) {
|
|
55665
|
-
return path;
|
|
55666
|
-
}
|
|
55667
|
-
}
|
|
55668
|
-
throw new Error(`
|
|
55669
|
-
Claude Code is not installed
|
|
55670
|
-
|
|
55671
|
-
Please install Claude Code:
|
|
55672
|
-
bun add -g @anthropic-ai/claude-code
|
|
55673
|
-
|
|
55674
|
-
Or set MEET_AI_CLAUDE_PATH to the Claude Code CLI path.
|
|
55675
|
-
`.trim());
|
|
55676
|
-
}
|
|
55677
|
-
var init_spawner = () => {};
|
|
55678
|
-
|
|
55679
56519
|
// ../../node_modules/.bun/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
|
55680
56520
|
var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
|
|
55681
56521
|
var React11 = __toESM(require_react());
|
|
@@ -56367,16 +57207,25 @@ var init_dashboard = __esm(async () => {
|
|
|
56367
57207
|
});
|
|
56368
57208
|
|
|
56369
57209
|
// src/tui/spawn-dialog.tsx
|
|
56370
|
-
function SpawnDialog({ onSubmit, onCancel }) {
|
|
57210
|
+
function SpawnDialog({ codingAgents, onSubmit, onCancel }) {
|
|
56371
57211
|
const [roomName, setRoomName] = import_react29.useState("");
|
|
56372
57212
|
const [cursor, setCursor] = import_react29.useState(0);
|
|
57213
|
+
const [selectedAgentIndex, setSelectedAgentIndex] = import_react29.useState(0);
|
|
56373
57214
|
use_input_default((input, key) => {
|
|
56374
57215
|
if (key.escape) {
|
|
56375
57216
|
onCancel();
|
|
56376
57217
|
return;
|
|
56377
57218
|
}
|
|
56378
57219
|
if (key.return && roomName.trim()) {
|
|
56379
|
-
onSubmit(roomName.trim());
|
|
57220
|
+
onSubmit(roomName.trim(), codingAgents[selectedAgentIndex]?.id ?? "claude");
|
|
57221
|
+
return;
|
|
57222
|
+
}
|
|
57223
|
+
if (key.upArrow) {
|
|
57224
|
+
setSelectedAgentIndex((current) => Math.max(0, current - 1));
|
|
57225
|
+
return;
|
|
57226
|
+
}
|
|
57227
|
+
if (key.downArrow) {
|
|
57228
|
+
setSelectedAgentIndex((current) => Math.min(codingAgents.length - 1, current + 1));
|
|
56380
57229
|
return;
|
|
56381
57230
|
}
|
|
56382
57231
|
if (key.leftArrow) {
|
|
@@ -56394,7 +57243,7 @@ function SpawnDialog({ onSubmit, onCancel }) {
|
|
|
56394
57243
|
}
|
|
56395
57244
|
return;
|
|
56396
57245
|
}
|
|
56397
|
-
if (input && !key.ctrl && !key.meta
|
|
57246
|
+
if (input && !key.ctrl && !key.meta) {
|
|
56398
57247
|
setRoomName((v) => v.slice(0, cursor) + input + v.slice(cursor));
|
|
56399
57248
|
setCursor((c) => c + input.length);
|
|
56400
57249
|
}
|
|
@@ -56432,7 +57281,21 @@ function SpawnDialog({ onSubmit, onCancel }) {
|
|
|
56432
57281
|
children: after
|
|
56433
57282
|
}, undefined, false, undefined, this)
|
|
56434
57283
|
]
|
|
56435
|
-
}, undefined, true, undefined, this)
|
|
57284
|
+
}, undefined, true, undefined, this),
|
|
57285
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
57286
|
+
children: [
|
|
57287
|
+
"Agent:",
|
|
57288
|
+
" ",
|
|
57289
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
57290
|
+
color: "yellow",
|
|
57291
|
+
children: codingAgents[selectedAgentIndex]?.label ?? "Claude Code"
|
|
57292
|
+
}, undefined, false, undefined, this)
|
|
57293
|
+
]
|
|
57294
|
+
}, undefined, true, undefined, this),
|
|
57295
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
57296
|
+
dimColor: true,
|
|
57297
|
+
children: "Use ←/→ to edit the room name, ↑/↓ to choose the coding agent, Enter to spawn."
|
|
57298
|
+
}, undefined, false, undefined, this)
|
|
56436
57299
|
]
|
|
56437
57300
|
}, undefined, true, undefined, this);
|
|
56438
57301
|
}
|
|
@@ -56580,7 +57443,7 @@ var init_status_bar = __esm(async () => {
|
|
|
56580
57443
|
});
|
|
56581
57444
|
|
|
56582
57445
|
// src/tui/app.tsx
|
|
56583
|
-
function AppInner({ processManager, client, onAttach, onDetach }) {
|
|
57446
|
+
function AppInner({ processManager, client, codingAgents, onAttach, onDetach }) {
|
|
56584
57447
|
const { exit } = use_app_default();
|
|
56585
57448
|
const { stdout } = use_stdout_default();
|
|
56586
57449
|
const { setRawMode } = use_stdin_default();
|
|
@@ -56590,7 +57453,7 @@ function AppInner({ processManager, client, onAttach, onDetach }) {
|
|
|
56590
57453
|
const [killTargetId, setKillTargetId] = import_react30.useState(null);
|
|
56591
57454
|
const [, setRenderTick] = import_react30.useState(0);
|
|
56592
57455
|
const terminalHeight = stdout?.rows ?? 24;
|
|
56593
|
-
const bottomHeight = showSpawn ?
|
|
57456
|
+
const bottomHeight = showSpawn ? 6 : killTargetId ? 1 : 1;
|
|
56594
57457
|
const dashboardHeight = terminalHeight - bottomHeight;
|
|
56595
57458
|
const focusedRoomRef = import_react30.useRef(null);
|
|
56596
57459
|
const focusedTeam = teams[focusedIndex];
|
|
@@ -56605,10 +57468,10 @@ function AppInner({ processManager, client, onAttach, onDetach }) {
|
|
|
56605
57468
|
return [...current];
|
|
56606
57469
|
});
|
|
56607
57470
|
}, [processManager]);
|
|
56608
|
-
const handleSpawn = import_react30.useCallback(async (roomName) => {
|
|
57471
|
+
const handleSpawn = import_react30.useCallback(async (roomName, codingAgent) => {
|
|
56609
57472
|
try {
|
|
56610
57473
|
const room = await client.createRoom(roomName);
|
|
56611
|
-
processManager.spawn(room.id, roomName);
|
|
57474
|
+
processManager.spawn(room.id, roomName, codingAgent);
|
|
56612
57475
|
refreshTeams();
|
|
56613
57476
|
} catch (error48) {
|
|
56614
57477
|
const msg = error48 instanceof Error ? error48.message : String(error48);
|
|
@@ -56726,9 +57589,10 @@ function AppInner({ processManager, client, onAttach, onDetach }) {
|
|
|
56726
57589
|
}, undefined, false, undefined, this)
|
|
56727
57590
|
]
|
|
56728
57591
|
}, undefined, true, undefined, this) : showSpawn ? /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(SpawnDialog, {
|
|
56729
|
-
|
|
57592
|
+
codingAgents: [...codingAgents],
|
|
57593
|
+
onSubmit: (roomName, codingAgent) => {
|
|
56730
57594
|
setShowSpawn(false);
|
|
56731
|
-
handleSpawn(
|
|
57595
|
+
handleSpawn(roomName, codingAgent);
|
|
56732
57596
|
},
|
|
56733
57597
|
onCancel: () => setShowSpawn(false)
|
|
56734
57598
|
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(StatusBar, {
|
|
@@ -56804,9 +57668,21 @@ async function startDashboard(client, config2, options) {
|
|
|
56804
57668
|
console.error(`tmux >= 3.2 required, found ${check3.version}`);
|
|
56805
57669
|
process.exit(1);
|
|
56806
57670
|
}
|
|
56807
|
-
const
|
|
57671
|
+
const agentBinaries = {};
|
|
57672
|
+
try {
|
|
57673
|
+
agentBinaries.claude = findClaudeCli();
|
|
57674
|
+
} catch {}
|
|
57675
|
+
try {
|
|
57676
|
+
agentBinaries.codex = findCodexCli();
|
|
57677
|
+
} catch {}
|
|
57678
|
+
const availableCodingAgents = CODING_AGENT_DEFINITIONS.filter((agent) => Boolean(agentBinaries[agent.id]));
|
|
57679
|
+
if (availableCodingAgents.length === 0) {
|
|
57680
|
+
console.error("No supported coding agent CLI was found.");
|
|
57681
|
+
console.error("Install Claude Code or Codex, or set MEET_AI_CLAUDE_PATH / MEET_AI_CODEX_PATH.");
|
|
57682
|
+
process.exit(1);
|
|
57683
|
+
}
|
|
56808
57684
|
const processManager = new ProcessManager({
|
|
56809
|
-
|
|
57685
|
+
agentBinaries,
|
|
56810
57686
|
debug: options?.debug,
|
|
56811
57687
|
tmux,
|
|
56812
57688
|
env: {
|
|
@@ -56830,15 +57706,16 @@ async function startDashboard(client, config2, options) {
|
|
|
56830
57706
|
try {
|
|
56831
57707
|
lobbyWs = client.listenLobby({
|
|
56832
57708
|
silent: true,
|
|
56833
|
-
onSpawnRequest: async (roomName) => {
|
|
56834
|
-
|
|
57709
|
+
onSpawnRequest: async ({ roomName, codingAgent }) => {
|
|
57710
|
+
const key = `${roomName}:${codingAgent}`;
|
|
57711
|
+
if (pendingSpawns.has(key))
|
|
56835
57712
|
return;
|
|
56836
|
-
pendingSpawns.add(
|
|
57713
|
+
pendingSpawns.add(key);
|
|
56837
57714
|
try {
|
|
56838
57715
|
const room = await client.createRoom(roomName);
|
|
56839
|
-
processManager.spawn(room.id, roomName);
|
|
57716
|
+
processManager.spawn(room.id, roomName, codingAgent);
|
|
56840
57717
|
} finally {
|
|
56841
|
-
pendingSpawns.delete(
|
|
57718
|
+
pendingSpawns.delete(key);
|
|
56842
57719
|
}
|
|
56843
57720
|
}
|
|
56844
57721
|
});
|
|
@@ -56854,6 +57731,7 @@ async function startDashboard(client, config2, options) {
|
|
|
56854
57731
|
const element = import_react31.default.createElement(App2, {
|
|
56855
57732
|
processManager,
|
|
56856
57733
|
client,
|
|
57734
|
+
codingAgents: availableCodingAgents,
|
|
56857
57735
|
onAttach: () => {
|
|
56858
57736
|
lobbyWs?.close();
|
|
56859
57737
|
lobbyWs = null;
|
|
@@ -56867,10 +57745,11 @@ async function startDashboard(client, config2, options) {
|
|
|
56867
57745
|
cleanup();
|
|
56868
57746
|
}
|
|
56869
57747
|
var import_react31;
|
|
56870
|
-
var
|
|
57748
|
+
var init_usecase16 = __esm(async () => {
|
|
57749
|
+
init_coding_agents();
|
|
57750
|
+
init_spawner();
|
|
56871
57751
|
init_process_manager();
|
|
56872
57752
|
init_tmux_client();
|
|
56873
|
-
init_spawner();
|
|
56874
57753
|
await __promiseAll([
|
|
56875
57754
|
init_build2(),
|
|
56876
57755
|
init_app()
|
|
@@ -56881,7 +57760,7 @@ var init_usecase17 = __esm(async () => {
|
|
|
56881
57760
|
// src/index.ts
|
|
56882
57761
|
init_dist();
|
|
56883
57762
|
// package.json
|
|
56884
|
-
var version = "0.0.
|
|
57763
|
+
var version = "0.0.36";
|
|
56885
57764
|
|
|
56886
57765
|
// src/index.ts
|
|
56887
57766
|
init_output();
|
|
@@ -56921,7 +57800,7 @@ var main = defineCommand({
|
|
|
56921
57800
|
try {
|
|
56922
57801
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
|
|
56923
57802
|
const { getMeetAiConfig: getMeetAiConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
56924
|
-
const { startDashboard: startDashboard2 } = await
|
|
57803
|
+
const { startDashboard: startDashboard2 } = await init_usecase16().then(() => exports_usecase2);
|
|
56925
57804
|
const client = getClient2();
|
|
56926
57805
|
const config2 = getMeetAiConfig2();
|
|
56927
57806
|
await startDashboard2(client, config2, { debug: args.debug });
|