@meet-ai/cli 0.0.31 → 0.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +180 -20
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16040,10 +16040,57 @@ var init_command10 = __esm(() => {
16040
16040
  });
16041
16041
 
16042
16042
  // src/lib/hooks/find-room.ts
16043
- import { readdirSync, readFileSync as readFileSync3 } from "node:fs";
16043
+ import { readdirSync, readFileSync as readFileSync3, writeFileSync as writeFileSync2, createReadStream } from "node:fs";
16044
16044
  import { join as join2 } from "node:path";
16045
- function findRoomId(sessionId, teamsDir) {
16045
+ import { createInterface } from "node:readline";
16046
+ async function extractTeamName(transcriptPath) {
16047
+ try {
16048
+ const rl = createInterface({
16049
+ input: createReadStream(transcriptPath, "utf-8"),
16050
+ crlfDelay: Infinity
16051
+ });
16052
+ for await (const line of rl) {
16053
+ try {
16054
+ const obj = JSON.parse(line);
16055
+ if (obj.teamName) {
16056
+ rl.close();
16057
+ return obj.teamName;
16058
+ }
16059
+ } catch {
16060
+ continue;
16061
+ }
16062
+ }
16063
+ } catch {}
16064
+ return null;
16065
+ }
16066
+ function registerSession(filePath, data, sessionId) {
16067
+ const ids = data.session_ids ?? [data.session_id];
16068
+ if (!ids.includes(sessionId)) {
16069
+ ids.push(sessionId);
16070
+ }
16071
+ if (!ids.includes(data.session_id)) {
16072
+ ids.unshift(data.session_id);
16073
+ }
16074
+ data.session_ids = ids;
16075
+ try {
16076
+ writeFileSync2(filePath, JSON.stringify(data));
16077
+ } catch {}
16078
+ }
16079
+ async function findRoom(sessionId, teamsDir, transcriptPath) {
16046
16080
  const dir = teamsDir ?? `${process.env.HOME}/.claude/teams`;
16081
+ if (transcriptPath) {
16082
+ const teamName = await extractTeamName(transcriptPath);
16083
+ if (teamName) {
16084
+ const filePath = join2(dir, teamName, "meet-ai.json");
16085
+ try {
16086
+ const raw = readFileSync3(filePath, "utf-8");
16087
+ const data = JSON.parse(raw);
16088
+ registerSession(filePath, data, sessionId);
16089
+ if (data.room_id)
16090
+ return { roomId: data.room_id, teamName: data.team_name || teamName };
16091
+ } catch {}
16092
+ }
16093
+ }
16047
16094
  let entries;
16048
16095
  try {
16049
16096
  entries = readdirSync(dir);
@@ -16055,8 +16102,11 @@ function findRoomId(sessionId, teamsDir) {
16055
16102
  try {
16056
16103
  const raw = readFileSync3(filePath, "utf-8");
16057
16104
  const data = JSON.parse(raw);
16058
- if (data.session_id === sessionId) {
16059
- return data.room_id || null;
16105
+ const knownIds = data.session_ids ?? [data.session_id];
16106
+ if (knownIds.includes(sessionId) || data.session_id === sessionId) {
16107
+ if (data.room_id)
16108
+ return { roomId: data.room_id, teamName: data.team_name || entry };
16109
+ return null;
16060
16110
  }
16061
16111
  } catch {
16062
16112
  continue;
@@ -16064,6 +16114,10 @@ function findRoomId(sessionId, teamsDir) {
16064
16114
  }
16065
16115
  return null;
16066
16116
  }
16117
+ async function findRoomId(sessionId, teamsDir, transcriptPath) {
16118
+ const result = await findRoom(sessionId, teamsDir, transcriptPath);
16119
+ return result?.roomId ?? null;
16120
+ }
16067
16121
  var init_find_room = () => {};
16068
16122
 
16069
16123
  // src/lib/hooks/summarize.ts
@@ -16107,6 +16161,39 @@ function summarize(toolName, toolInput) {
16107
16161
  var truncate = (s, n) => s.slice(0, n);
16108
16162
  var init_summarize = () => {};
16109
16163
 
16164
+ // src/lib/hooks/format-diff.ts
16165
+ function shortPath(filePath) {
16166
+ const parts = filePath.replace(/\\/g, "/").split("/").filter(Boolean);
16167
+ return parts.slice(-3).join("/");
16168
+ }
16169
+ function formatDiff(filePath, hunks) {
16170
+ const display = shortPath(filePath);
16171
+ const diffLines = hunks.map((hunk) => {
16172
+ const header = `@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`;
16173
+ return `${header}
16174
+ ${hunk.lines.join(`
16175
+ `)}`;
16176
+ }).join(`
16177
+ `);
16178
+ return `[diff:${display}]
16179
+ --- a/${display}
16180
+ +++ b/${display}
16181
+ ${diffLines}`;
16182
+ }
16183
+ function formatWriteDiff(filePath, content) {
16184
+ const display = shortPath(filePath);
16185
+ const lines = content.split(`
16186
+ `);
16187
+ const header = `@@ -0,0 +1,${lines.length} @@`;
16188
+ const addedLines = lines.map((line) => `+${line}`).join(`
16189
+ `);
16190
+ return `[diff:${display}]
16191
+ --- /dev/null
16192
+ +++ b/${display}
16193
+ ${header}
16194
+ ${addedLines}`;
16195
+ }
16196
+
16110
16197
  // ../../node_modules/.bun/hono@4.11.8/node_modules/hono/dist/utils/url.js
16111
16198
  var init_url = () => {};
16112
16199
 
@@ -16432,6 +16519,14 @@ async function sendParentMessage(client, roomId) {
16432
16519
  return null;
16433
16520
  }
16434
16521
  }
16522
+ async function sendTeamMemberUpsert(client, roomId, teamName, member) {
16523
+ try {
16524
+ await client.api.rooms[":id"]["team-info"].members.$patch({
16525
+ param: { id: roomId },
16526
+ json: { team_name: teamName, member }
16527
+ });
16528
+ } catch {}
16529
+ }
16435
16530
  async function sendLogEntry(client, roomId, summary, messageId) {
16436
16531
  try {
16437
16532
  await client.api.rooms[":id"].logs.$post({
@@ -16458,7 +16553,7 @@ var init_hooks = __esm(() => {
16458
16553
  });
16459
16554
 
16460
16555
  // src/commands/hook/log-tool-use/usecase.ts
16461
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, statSync as statSync2, rmSync } from "node:fs";
16556
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, statSync as statSync2, rmSync } from "node:fs";
16462
16557
  function getOrCreateParentId(sessionId) {
16463
16558
  const path = `/tmp/meet-ai-hook-${sessionId}.msgid`;
16464
16559
  try {
@@ -16474,7 +16569,7 @@ function getOrCreateParentId(sessionId) {
16474
16569
  }
16475
16570
  function saveParentId(sessionId, msgId) {
16476
16571
  try {
16477
- writeFileSync2(`/tmp/meet-ai-hook-${sessionId}.msgid`, msgId);
16572
+ writeFileSync3(`/tmp/meet-ai-hook-${sessionId}.msgid`, msgId);
16478
16573
  } catch {}
16479
16574
  }
16480
16575
  async function processHookInput(rawInput, teamsDir) {
@@ -16484,24 +16579,89 @@ async function processHookInput(rawInput, teamsDir) {
16484
16579
  } catch {
16485
16580
  return "skip";
16486
16581
  }
16487
- const { session_id: sessionId, tool_name: toolName, tool_input: toolInput = {} } = input;
16582
+ const {
16583
+ session_id: sessionId,
16584
+ transcript_path: transcriptPath,
16585
+ tool_name: toolName,
16586
+ tool_input: toolInput = {},
16587
+ tool_response: toolResponse
16588
+ } = input;
16488
16589
  if (!sessionId || !toolName)
16489
16590
  return "skip";
16490
- if (toolName === "SendMessage")
16491
- return "skip";
16492
16591
  if (toolName === "Bash") {
16493
16592
  const cmd = typeof toolInput.command === "string" ? toolInput.command : "";
16494
16593
  if (cmd.startsWith("cd ") || cmd.startsWith("meet-ai "))
16495
16594
  return "skip";
16496
16595
  }
16497
- const roomId = findRoomId(sessionId, teamsDir);
16498
- if (!roomId)
16596
+ const room = await findRoom(sessionId, teamsDir, transcriptPath);
16597
+ if (!room)
16499
16598
  return "skip";
16599
+ const { roomId, teamName } = room;
16500
16600
  const url2 = process.env.MEET_AI_URL;
16501
16601
  const key = process.env.MEET_AI_KEY;
16502
16602
  if (!url2 || !key)
16503
16603
  return "skip";
16504
16604
  const client = createHookClient(url2, key);
16605
+ if (toolName === "Agent" && toolResponse) {
16606
+ const status = toolResponse.status;
16607
+ if (status === "teammate_spawned") {
16608
+ await sendTeamMemberUpsert(client, roomId, toolResponse.team_name, {
16609
+ teammate_id: toolResponse.teammate_id,
16610
+ name: toolResponse.name,
16611
+ color: toolResponse.color,
16612
+ role: toolResponse.agent_type || "teammate",
16613
+ model: toolResponse.model || "unknown",
16614
+ status: "active",
16615
+ joinedAt: Date.now()
16616
+ });
16617
+ }
16618
+ }
16619
+ if (toolName === "SendMessage") {
16620
+ const inputType = toolInput.type;
16621
+ const approve = toolInput.approve;
16622
+ if (inputType === "shutdown_response" && approve === true) {
16623
+ const requestId = toolInput.request_id;
16624
+ const agentName = requestId?.split("@")[1];
16625
+ if (agentName) {
16626
+ const teammateId = teamName ? `${agentName}@${teamName}` : agentName;
16627
+ await sendTeamMemberUpsert(client, roomId, teamName, {
16628
+ teammate_id: teammateId,
16629
+ name: agentName,
16630
+ color: "#555",
16631
+ role: "teammate",
16632
+ model: "unknown",
16633
+ status: "inactive",
16634
+ joinedAt: 0
16635
+ });
16636
+ }
16637
+ }
16638
+ return "skip";
16639
+ }
16640
+ if (toolName === "Edit" && toolResponse?.structuredPatch) {
16641
+ const hunks = toolResponse.structuredPatch;
16642
+ const filePath = typeof toolInput.file_path === "string" ? toolInput.file_path : "?";
16643
+ const diffContent = formatDiff(filePath, hunks);
16644
+ let parentId2 = getOrCreateParentId(sessionId);
16645
+ if (!parentId2) {
16646
+ parentId2 = await sendParentMessage(client, roomId);
16647
+ if (parentId2)
16648
+ saveParentId(sessionId, parentId2);
16649
+ }
16650
+ await sendLogEntry(client, roomId, diffContent, parentId2 ?? undefined);
16651
+ return "sent";
16652
+ }
16653
+ if (toolName === "Write" && typeof toolInput.content === "string") {
16654
+ const filePath = typeof toolInput.file_path === "string" ? toolInput.file_path : "?";
16655
+ const diffContent = formatWriteDiff(filePath, toolInput.content);
16656
+ let parentId2 = getOrCreateParentId(sessionId);
16657
+ if (!parentId2) {
16658
+ parentId2 = await sendParentMessage(client, roomId);
16659
+ if (parentId2)
16660
+ saveParentId(sessionId, parentId2);
16661
+ }
16662
+ await sendLogEntry(client, roomId, diffContent, parentId2 ?? undefined);
16663
+ return "sent";
16664
+ }
16505
16665
  const summary = summarize(toolName, toolInput);
16506
16666
  let parentId = getOrCreateParentId(sessionId);
16507
16667
  if (!parentId) {
@@ -16645,14 +16805,14 @@ async function processPlanReview(rawInput, teamsDir) {
16645
16805
  `);
16646
16806
  return;
16647
16807
  }
16648
- const { session_id: sessionId } = input;
16808
+ const { session_id: sessionId, transcript_path: transcriptPath } = input;
16649
16809
  if (!sessionId) {
16650
16810
  process.stderr.write(`[plan-review] missing session_id
16651
16811
  `);
16652
16812
  return;
16653
16813
  }
16654
16814
  const planContent = input.tool_input?.plan || "_Agent requested to exit plan mode without a plan._";
16655
- const roomId = findRoomId(sessionId, teamsDir);
16815
+ const roomId = await findRoomId(sessionId, teamsDir, transcriptPath);
16656
16816
  if (!roomId) {
16657
16817
  process.stderr.write(`[plan-review] no room found for session
16658
16818
  `);
@@ -16833,7 +16993,7 @@ async function processQuestionReview(rawInput, teamsDir, opts) {
16833
16993
  `);
16834
16994
  return;
16835
16995
  }
16836
- const { session_id: sessionId, hook_event_name: hookEventName, tool_input: toolInput } = input;
16996
+ const { session_id: sessionId, transcript_path: transcriptPath, hook_event_name: hookEventName, tool_input: toolInput } = input;
16837
16997
  if (!sessionId || !toolInput?.questions?.length) {
16838
16998
  process.stderr.write(`[question-review] missing session_id or questions
16839
16999
  `);
@@ -16841,7 +17001,7 @@ async function processQuestionReview(rawInput, teamsDir, opts) {
16841
17001
  }
16842
17002
  process.stderr.write(`[question-review] triggered by ${hookEventName} event
16843
17003
  `);
16844
- const roomId = findRoomId(sessionId, teamsDir);
17004
+ const roomId = await findRoomId(sessionId, teamsDir, transcriptPath);
16845
17005
  if (!roomId) {
16846
17006
  process.stderr.write(`[question-review] no room found for session
16847
17007
  `);
@@ -17030,7 +17190,7 @@ async function processPermissionReview(rawInput, teamsDir, opts) {
17030
17190
  `);
17031
17191
  return;
17032
17192
  }
17033
- const { session_id: sessionId, hook_event_name: hookEventName, tool_name: toolName, tool_input: toolInput } = input;
17193
+ const { session_id: sessionId, transcript_path: transcriptPath, hook_event_name: hookEventName, tool_name: toolName, tool_input: toolInput } = input;
17034
17194
  if (!sessionId || !toolName) {
17035
17195
  process.stderr.write(`[permission-review] missing session_id or tool_name
17036
17196
  `);
@@ -17044,7 +17204,7 @@ async function processPermissionReview(rawInput, teamsDir, opts) {
17044
17204
  }
17045
17205
  process.stderr.write(`[permission-review] triggered by ${hookEventName} for tool ${toolName}
17046
17206
  `);
17047
- const roomId = findRoomId(sessionId, teamsDir);
17207
+ const roomId = await findRoomId(sessionId, teamsDir, transcriptPath);
17048
17208
  if (!roomId) {
17049
17209
  process.stderr.write(`[permission-review] no room found for session
17050
17210
  `);
@@ -54959,7 +55119,7 @@ var init_build2 = __esm(async () => {
54959
55119
  });
54960
55120
 
54961
55121
  // src/lib/process-manager.ts
54962
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync3, renameSync, lstatSync } from "node:fs";
55122
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync, lstatSync } from "node:fs";
54963
55123
  import { homedir as homedir4 } from "node:os";
54964
55124
  import { join as join4 } from "node:path";
54965
55125
  function readRegistry() {
@@ -54981,7 +55141,7 @@ function writeRegistry(entries) {
54981
55141
  return;
54982
55142
  }
54983
55143
  const tmpPath = join4(REGISTRY_DIR, `sessions.${process.pid}.${Date.now()}.tmp`);
54984
- writeFileSync3(tmpPath, JSON.stringify(entries, null, 2), { mode: 384 });
55144
+ writeFileSync4(tmpPath, JSON.stringify(entries, null, 2), { mode: 384 });
54985
55145
  renameSync(tmpPath, REGISTRY_PATH);
54986
55146
  }
54987
55147
  function addToRegistry(entry) {
@@ -56448,7 +56608,7 @@ init_output();
56448
56608
  var main = defineCommand({
56449
56609
  meta: {
56450
56610
  name: "meet-ai",
56451
- version: "0.0.30",
56611
+ version: "0.0.33",
56452
56612
  description: "CLI for meet-ai chat rooms — create rooms, send messages, and stream via WebSocket"
56453
56613
  },
56454
56614
  args: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meet-ai/cli",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
4
4
  "description": "CLI for meet-ai chat rooms — create rooms, send messages, and stream via WebSocket",
5
5
  "keywords": [
6
6
  "chat",