@meet-ai/cli 0.0.18 → 0.0.19

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 +1359 -42
  2. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -519,7 +519,7 @@ var require_picocolors = __commonJS((exports, module) => {
519
519
  });
520
520
 
521
521
  // src/lib/output.ts
522
- var import_picocolors, ok = (msg) => console.log(import_picocolors.default.green(msg)), err = (msg) => console.error(import_picocolors.default.red(`error: ${msg}`));
522
+ var import_picocolors, ok = (msg) => console.log(import_picocolors.default.green(msg)), err = (msg) => console.error(import_picocolors.default.red(`error: ${msg}`)), info = (msg) => console.log(import_picocolors.default.cyan(msg));
523
523
  var init_output = __esm(() => {
524
524
  import_picocolors = __toESM(require_picocolors(), 1);
525
525
  });
@@ -15703,10 +15703,10 @@ var init_command10 = __esm(() => {
15703
15703
  // ../../node_modules/.bun/react@19.2.4/node_modules/react/cjs/react.development.js
15704
15704
  var require_react_development = __commonJS((exports, module) => {
15705
15705
  (function() {
15706
- function defineDeprecationWarning(methodName, info) {
15706
+ function defineDeprecationWarning(methodName, info2) {
15707
15707
  Object.defineProperty(Component.prototype, methodName, {
15708
15708
  get: function() {
15709
- console.warn("%s(...) is deprecated in plain JavaScript React classes. %s", info[0], info[1]);
15709
+ console.warn("%s(...) is deprecated in plain JavaScript React classes. %s", info2[0], info2[1]);
15710
15710
  }
15711
15711
  });
15712
15712
  }
@@ -20755,15 +20755,15 @@ var require_react_reconciler_development = __commonJS((exports, module) => {
20755
20755
  }
20756
20756
  function getStackByFiberInDevAndProd(workInProgress2) {
20757
20757
  try {
20758
- var info = "", previous = null;
20758
+ var info2 = "", previous = null;
20759
20759
  do {
20760
- info += describeFiber(workInProgress2, previous);
20760
+ info2 += describeFiber(workInProgress2, previous);
20761
20761
  var debugInfo = workInProgress2._debugInfo;
20762
20762
  if (debugInfo)
20763
20763
  for (var i = debugInfo.length - 1;0 <= i; i--) {
20764
20764
  var entry = debugInfo[i];
20765
20765
  if (typeof entry.name === "string") {
20766
- var JSCompiler_temp_const = info;
20766
+ var JSCompiler_temp_const = info2;
20767
20767
  a: {
20768
20768
  var { name, env: env2, debugLocation: location } = entry;
20769
20769
  if (location != null) {
@@ -20777,13 +20777,13 @@ var require_react_reconciler_development = __commonJS((exports, module) => {
20777
20777
  }
20778
20778
  JSCompiler_inline_result = describeBuiltInComponentFrame(name + (env2 ? " [" + env2 + "]" : ""));
20779
20779
  }
20780
- info = JSCompiler_temp_const + JSCompiler_inline_result;
20780
+ info2 = JSCompiler_temp_const + JSCompiler_inline_result;
20781
20781
  }
20782
20782
  }
20783
20783
  previous = workInProgress2;
20784
20784
  workInProgress2 = workInProgress2.return;
20785
20785
  } while (workInProgress2);
20786
- return info;
20786
+ return info2;
20787
20787
  } catch (x) {
20788
20788
  return `
20789
20789
  Error generating stack: ` + x.message + `
@@ -21151,31 +21151,31 @@ Error generating stack: ` + x.message + `
21151
21151
  return "";
21152
21152
  var workInProgress2 = current;
21153
21153
  try {
21154
- var info = "";
21154
+ var info2 = "";
21155
21155
  workInProgress2.tag === 6 && (workInProgress2 = workInProgress2.return);
21156
21156
  switch (workInProgress2.tag) {
21157
21157
  case 26:
21158
21158
  case 27:
21159
21159
  case 5:
21160
- info += describeBuiltInComponentFrame(workInProgress2.type);
21160
+ info2 += describeBuiltInComponentFrame(workInProgress2.type);
21161
21161
  break;
21162
21162
  case 13:
21163
- info += describeBuiltInComponentFrame("Suspense");
21163
+ info2 += describeBuiltInComponentFrame("Suspense");
21164
21164
  break;
21165
21165
  case 19:
21166
- info += describeBuiltInComponentFrame("SuspenseList");
21166
+ info2 += describeBuiltInComponentFrame("SuspenseList");
21167
21167
  break;
21168
21168
  case 31:
21169
- info += describeBuiltInComponentFrame("Activity");
21169
+ info2 += describeBuiltInComponentFrame("Activity");
21170
21170
  break;
21171
21171
  case 30:
21172
21172
  case 0:
21173
21173
  case 15:
21174
21174
  case 1:
21175
- workInProgress2._debugOwner || info !== "" || (info += describeFunctionComponentFrameWithoutLineNumber(workInProgress2.type));
21175
+ workInProgress2._debugOwner || info2 !== "" || (info2 += describeFunctionComponentFrameWithoutLineNumber(workInProgress2.type));
21176
21176
  break;
21177
21177
  case 11:
21178
- workInProgress2._debugOwner || info !== "" || (info += describeFunctionComponentFrameWithoutLineNumber(workInProgress2.type.render));
21178
+ workInProgress2._debugOwner || info2 !== "" || (info2 += describeFunctionComponentFrameWithoutLineNumber(workInProgress2.type.render));
21179
21179
  }
21180
21180
  for (;workInProgress2; )
21181
21181
  if (typeof workInProgress2.tag === "number") {
@@ -21184,16 +21184,16 @@ Error generating stack: ` + x.message + `
21184
21184
  var debugStack = fiber._debugStack;
21185
21185
  if (workInProgress2 && debugStack) {
21186
21186
  var formattedStack = formatOwnerStack(debugStack);
21187
- formattedStack !== "" && (info += `
21187
+ formattedStack !== "" && (info2 += `
21188
21188
  ` + formattedStack);
21189
21189
  }
21190
21190
  } else if (workInProgress2.debugStack != null) {
21191
21191
  var ownerStack = workInProgress2.debugStack;
21192
- (workInProgress2 = workInProgress2.owner) && ownerStack && (info += `
21192
+ (workInProgress2 = workInProgress2.owner) && ownerStack && (info2 += `
21193
21193
  ` + formatOwnerStack(ownerStack));
21194
21194
  } else
21195
21195
  break;
21196
- var JSCompiler_inline_result = info;
21196
+ var JSCompiler_inline_result = info2;
21197
21197
  } catch (x) {
21198
21198
  JSCompiler_inline_result = `
21199
21199
  Error generating stack: ` + x.message + `
@@ -34551,13 +34551,13 @@ var require_websocket_server = __commonJS((exports, module) => {
34551
34551
  }
34552
34552
  }
34553
34553
  if (this.options.verifyClient) {
34554
- const info = {
34554
+ const info2 = {
34555
34555
  origin: req.headers[`${version2 === 8 ? "sec-websocket-origin" : "origin"}`],
34556
34556
  secure: !!(req.socket.authorized || req.socket.encrypted),
34557
34557
  req
34558
34558
  };
34559
34559
  if (this.options.verifyClient.length === 2) {
34560
- this.options.verifyClient(info, (verified, code, message, headers) => {
34560
+ this.options.verifyClient(info2, (verified, code, message, headers) => {
34561
34561
  if (!verified) {
34562
34562
  return abortHandshake(socket, code || 401, message, headers);
34563
34563
  }
@@ -34565,7 +34565,7 @@ var require_websocket_server = __commonJS((exports, module) => {
34565
34565
  });
34566
34566
  return;
34567
34567
  }
34568
- if (!this.options.verifyClient(info))
34568
+ if (!this.options.verifyClient(info2))
34569
34569
  return abortHandshake(socket, 401);
34570
34570
  }
34571
34571
  this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
@@ -41539,7 +41539,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
41539
41539
  }
41540
41540
  function getOwnerStackByComponentInfoInDev(componentInfo) {
41541
41541
  try {
41542
- var info = "";
41542
+ var info2 = "";
41543
41543
  if (!componentInfo.owner && typeof componentInfo.name === "string") {
41544
41544
  return describeBuiltInComponentFrame(componentInfo.name);
41545
41545
  }
@@ -41549,14 +41549,14 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
41549
41549
  if (ownerStack != null) {
41550
41550
  owner = owner.owner;
41551
41551
  if (owner) {
41552
- info += `
41552
+ info2 += `
41553
41553
  ` + formatOwnerStack(ownerStack);
41554
41554
  }
41555
41555
  } else {
41556
41556
  break;
41557
41557
  }
41558
41558
  }
41559
- return info;
41559
+ return info2;
41560
41560
  } catch (x) {
41561
41561
  return `
41562
41562
  Error generating stack: ` + x.message + `
@@ -41819,22 +41819,22 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
41819
41819
  }
41820
41820
  function getStackByFiberInDevAndProd(workTagMap, workInProgress, currentDispatcherRef) {
41821
41821
  try {
41822
- var info = "";
41822
+ var info2 = "";
41823
41823
  var node = workInProgress;
41824
41824
  do {
41825
- info += describeFiber(workTagMap, node, currentDispatcherRef);
41825
+ info2 += describeFiber(workTagMap, node, currentDispatcherRef);
41826
41826
  var debugInfo = node._debugInfo;
41827
41827
  if (debugInfo) {
41828
41828
  for (var i = debugInfo.length - 1;i >= 0; i--) {
41829
41829
  var entry = debugInfo[i];
41830
41830
  if (typeof entry.name === "string") {
41831
- info += describeDebugInfoFrame(entry.name, entry.env);
41831
+ info2 += describeDebugInfoFrame(entry.name, entry.env);
41832
41832
  }
41833
41833
  }
41834
41834
  }
41835
41835
  node = node.return;
41836
41836
  } while (node);
41837
- return info;
41837
+ return info2;
41838
41838
  } catch (x) {
41839
41839
  return `
41840
41840
  Error generating stack: ` + x.message + `
@@ -41843,9 +41843,9 @@ Error generating stack: ` + x.message + `
41843
41843
  }
41844
41844
  function getSourceLocationByFiber(workTagMap, fiber, currentDispatcherRef) {
41845
41845
  try {
41846
- var info = describeFiber(workTagMap, fiber, currentDispatcherRef);
41847
- if (info !== "") {
41848
- return info.slice(1);
41846
+ var info2 = describeFiber(workTagMap, fiber, currentDispatcherRef);
41847
+ if (info2 !== "") {
41848
+ return info2.slice(1);
41849
41849
  }
41850
41850
  } catch (x) {
41851
41851
  console.error(x);
@@ -41861,7 +41861,7 @@ Error generating stack: ` + x.message + `
41861
41861
  function getOwnerStackByFiberInDev(workTagMap, workInProgress, currentDispatcherRef) {
41862
41862
  var { HostHoistable, HostSingleton, HostText, HostComponent, SuspenseComponent, SuspenseListComponent, ViewTransitionComponent, ActivityComponent } = workTagMap;
41863
41863
  try {
41864
- var info = "";
41864
+ var info2 = "";
41865
41865
  if (workInProgress.tag === HostText) {
41866
41866
  workInProgress = workInProgress.return;
41867
41867
  }
@@ -41869,19 +41869,19 @@ Error generating stack: ` + x.message + `
41869
41869
  case HostHoistable:
41870
41870
  case HostSingleton:
41871
41871
  case HostComponent:
41872
- info += describeBuiltInComponentFrame(workInProgress.type);
41872
+ info2 += describeBuiltInComponentFrame(workInProgress.type);
41873
41873
  break;
41874
41874
  case SuspenseComponent:
41875
- info += describeBuiltInComponentFrame("Suspense");
41875
+ info2 += describeBuiltInComponentFrame("Suspense");
41876
41876
  break;
41877
41877
  case SuspenseListComponent:
41878
- info += describeBuiltInComponentFrame("SuspenseList");
41878
+ info2 += describeBuiltInComponentFrame("SuspenseList");
41879
41879
  break;
41880
41880
  case ViewTransitionComponent:
41881
- info += describeBuiltInComponentFrame("ViewTransition");
41881
+ info2 += describeBuiltInComponentFrame("ViewTransition");
41882
41882
  break;
41883
41883
  case ActivityComponent:
41884
- info += describeBuiltInComponentFrame("Activity");
41884
+ info2 += describeBuiltInComponentFrame("Activity");
41885
41885
  break;
41886
41886
  }
41887
41887
  var owner = workInProgress;
@@ -41895,7 +41895,7 @@ Error generating stack: ` + x.message + `
41895
41895
  debugStack = formatOwnerStack(debugStack);
41896
41896
  }
41897
41897
  if (debugStack !== "") {
41898
- info += `
41898
+ info2 += `
41899
41899
  ` + debugStack;
41900
41900
  }
41901
41901
  }
@@ -41903,14 +41903,14 @@ Error generating stack: ` + x.message + `
41903
41903
  var ownerStack = owner.debugStack;
41904
41904
  owner = owner.owner;
41905
41905
  if (owner && ownerStack) {
41906
- info += `
41906
+ info2 += `
41907
41907
  ` + formatOwnerStack(ownerStack);
41908
41908
  }
41909
41909
  } else {
41910
41910
  break;
41911
41911
  }
41912
41912
  }
41913
- return info;
41913
+ return info2;
41914
41914
  } catch (x) {
41915
41915
  return `
41916
41916
  Error generating stack: ` + x.message + `
@@ -59652,13 +59652,1328 @@ var init_command11 = __esm(async () => {
59652
59652
  });
59653
59653
  });
59654
59654
 
59655
+ // src/lib/hooks/find-room.ts
59656
+ import { readdirSync, readFileSync as readFileSync4 } from "node:fs";
59657
+ import { join as join3 } from "node:path";
59658
+ function findRoomId(sessionId, teamsDir) {
59659
+ const dir = teamsDir ?? `${process.env.HOME}/.claude/teams`;
59660
+ let entries;
59661
+ try {
59662
+ entries = readdirSync(dir);
59663
+ } catch {
59664
+ return null;
59665
+ }
59666
+ for (const entry of entries) {
59667
+ const filePath = join3(dir, entry, "meet-ai.json");
59668
+ try {
59669
+ const raw = readFileSync4(filePath, "utf-8");
59670
+ const data = JSON.parse(raw);
59671
+ if (data.session_id === sessionId) {
59672
+ return data.room_id || null;
59673
+ }
59674
+ } catch {
59675
+ continue;
59676
+ }
59677
+ }
59678
+ return null;
59679
+ }
59680
+ var init_find_room = () => {};
59681
+
59682
+ // src/lib/hooks/summarize.ts
59683
+ import { basename } from "node:path";
59684
+ function summarize(toolName, toolInput) {
59685
+ const str = (key) => typeof toolInput[key] === "string" ? toolInput[key] : "";
59686
+ const file2 = (key) => basename(str(key)) || "?";
59687
+ switch (toolName) {
59688
+ case "Edit": {
59689
+ return `Edit: ${file2("file_path")}`;
59690
+ }
59691
+ case "Read": {
59692
+ return `Read: ${file2("file_path")}`;
59693
+ }
59694
+ case "Write": {
59695
+ return `Write: ${file2("file_path")}`;
59696
+ }
59697
+ case "Bash": {
59698
+ return `Bash: ${truncate(str("command"), 60)}`;
59699
+ }
59700
+ case "Grep": {
59701
+ return `Grep: "${str("pattern")}" in ${str("glob") || str("path")}`;
59702
+ }
59703
+ case "Glob": {
59704
+ return `Glob: ${str("pattern")}`;
59705
+ }
59706
+ case "Task": {
59707
+ return `Task: ${truncate(str("description"), 60)}`;
59708
+ }
59709
+ case "WebFetch": {
59710
+ return `WebFetch: ${str("url")}`;
59711
+ }
59712
+ case "WebSearch": {
59713
+ return `WebSearch: ${str("query")}`;
59714
+ }
59715
+ default: {
59716
+ return toolName;
59717
+ }
59718
+ }
59719
+ }
59720
+ var truncate = (s, n) => s.slice(0, n);
59721
+ var init_summarize = () => {};
59722
+
59723
+ // ../../node_modules/.bun/hono@4.11.8/node_modules/hono/dist/utils/url.js
59724
+ var init_url = () => {};
59725
+
59726
+ // ../../node_modules/.bun/hono@4.11.8/node_modules/hono/dist/utils/cookie.js
59727
+ var _serialize = (name, value, opt = {}) => {
59728
+ let cookie = `${name}=${value}`;
59729
+ if (name.startsWith("__Secure-") && !opt.secure) {
59730
+ throw new Error("__Secure- Cookie must have Secure attributes");
59731
+ }
59732
+ if (name.startsWith("__Host-")) {
59733
+ if (!opt.secure) {
59734
+ throw new Error("__Host- Cookie must have Secure attributes");
59735
+ }
59736
+ if (opt.path !== "/") {
59737
+ throw new Error('__Host- Cookie must have Path attributes with "/"');
59738
+ }
59739
+ if (opt.domain) {
59740
+ throw new Error("__Host- Cookie must not have Domain attributes");
59741
+ }
59742
+ }
59743
+ if (opt && typeof opt.maxAge === "number" && opt.maxAge >= 0) {
59744
+ if (opt.maxAge > 34560000) {
59745
+ throw new Error("Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration.");
59746
+ }
59747
+ cookie += `; Max-Age=${opt.maxAge | 0}`;
59748
+ }
59749
+ if (opt.domain && opt.prefix !== "host") {
59750
+ cookie += `; Domain=${opt.domain}`;
59751
+ }
59752
+ if (opt.path) {
59753
+ cookie += `; Path=${opt.path}`;
59754
+ }
59755
+ if (opt.expires) {
59756
+ if (opt.expires.getTime() - Date.now() > 34560000000) {
59757
+ throw new Error("Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future.");
59758
+ }
59759
+ cookie += `; Expires=${opt.expires.toUTCString()}`;
59760
+ }
59761
+ if (opt.httpOnly) {
59762
+ cookie += "; HttpOnly";
59763
+ }
59764
+ if (opt.secure) {
59765
+ cookie += "; Secure";
59766
+ }
59767
+ if (opt.sameSite) {
59768
+ cookie += `; SameSite=${opt.sameSite.charAt(0).toUpperCase() + opt.sameSite.slice(1)}`;
59769
+ }
59770
+ if (opt.priority) {
59771
+ cookie += `; Priority=${opt.priority.charAt(0).toUpperCase() + opt.priority.slice(1)}`;
59772
+ }
59773
+ if (opt.partitioned) {
59774
+ if (!opt.secure) {
59775
+ throw new Error("Partitioned Cookie must have Secure attributes");
59776
+ }
59777
+ cookie += "; Partitioned";
59778
+ }
59779
+ return cookie;
59780
+ }, serialize = (name, value, opt) => {
59781
+ value = encodeURIComponent(value);
59782
+ return _serialize(name, value, opt);
59783
+ };
59784
+ var init_cookie = __esm(() => {
59785
+ init_url();
59786
+ });
59787
+
59788
+ // ../../node_modules/.bun/hono@4.11.8/node_modules/hono/dist/client/fetch-result-please.js
59789
+ var init_fetch_result_please = () => {};
59790
+
59791
+ // ../../node_modules/.bun/hono@4.11.8/node_modules/hono/dist/client/utils.js
59792
+ function isObject2(item) {
59793
+ return typeof item === "object" && item !== null && !Array.isArray(item);
59794
+ }
59795
+ function deepMerge(target, source) {
59796
+ if (!isObject2(target) && !isObject2(source)) {
59797
+ return source;
59798
+ }
59799
+ const merged = { ...target };
59800
+ for (const key in source) {
59801
+ const value = source[key];
59802
+ if (isObject2(merged[key]) && isObject2(value)) {
59803
+ merged[key] = deepMerge(merged[key], value);
59804
+ } else {
59805
+ merged[key] = value;
59806
+ }
59807
+ }
59808
+ return merged;
59809
+ }
59810
+ var mergePath = (base2, path) => {
59811
+ base2 = base2.replace(/\/+$/, "");
59812
+ base2 = base2 + "/";
59813
+ path = path.replace(/^\/+/, "");
59814
+ return base2 + path;
59815
+ }, replaceUrlParam = (urlString, params) => {
59816
+ for (const [k, v] of Object.entries(params)) {
59817
+ const reg = new RegExp("/:" + k + "(?:{[^/]+})?\\??");
59818
+ urlString = urlString.replace(reg, v ? `/${v}` : "");
59819
+ }
59820
+ return urlString;
59821
+ }, buildSearchParams = (query) => {
59822
+ const searchParams = new URLSearchParams;
59823
+ for (const [k, v] of Object.entries(query)) {
59824
+ if (v === undefined) {
59825
+ continue;
59826
+ }
59827
+ if (Array.isArray(v)) {
59828
+ for (const v2 of v) {
59829
+ searchParams.append(k, v2);
59830
+ }
59831
+ } else {
59832
+ searchParams.set(k, v);
59833
+ }
59834
+ }
59835
+ return searchParams;
59836
+ }, replaceUrlProtocol = (urlString, protocol) => {
59837
+ switch (protocol) {
59838
+ case "ws":
59839
+ return urlString.replace(/^http/, "ws");
59840
+ case "http":
59841
+ return urlString.replace(/^ws/, "http");
59842
+ }
59843
+ }, removeIndexString = (urlString) => {
59844
+ if (/^https?:\/\/[^\/]+?\/index(?=\?|$)/.test(urlString)) {
59845
+ return urlString.replace(/\/index(?=\?|$)/, "/");
59846
+ }
59847
+ return urlString.replace(/\/index(?=\?|$)/, "");
59848
+ };
59849
+ var init_utils2 = __esm(() => {
59850
+ init_fetch_result_please();
59851
+ });
59852
+
59853
+ // ../../node_modules/.bun/hono@4.11.8/node_modules/hono/dist/client/client.js
59854
+ var createProxy = (callback, path) => {
59855
+ const proxy = new Proxy(() => {}, {
59856
+ get(_obj, key) {
59857
+ if (typeof key !== "string" || key === "then") {
59858
+ return;
59859
+ }
59860
+ return createProxy(callback, [...path, key]);
59861
+ },
59862
+ apply(_1, _2, args) {
59863
+ return callback({
59864
+ path,
59865
+ args
59866
+ });
59867
+ }
59868
+ });
59869
+ return proxy;
59870
+ }, ClientRequestImpl = class {
59871
+ url;
59872
+ method;
59873
+ buildSearchParams;
59874
+ queryParams = undefined;
59875
+ pathParams = {};
59876
+ rBody;
59877
+ cType = undefined;
59878
+ constructor(url2, method, options) {
59879
+ this.url = url2;
59880
+ this.method = method;
59881
+ this.buildSearchParams = options.buildSearchParams;
59882
+ }
59883
+ fetch = async (args, opt) => {
59884
+ if (args) {
59885
+ if (args.query) {
59886
+ this.queryParams = this.buildSearchParams(args.query);
59887
+ }
59888
+ if (args.form) {
59889
+ const form = new FormData;
59890
+ for (const [k, v] of Object.entries(args.form)) {
59891
+ if (Array.isArray(v)) {
59892
+ for (const v2 of v) {
59893
+ form.append(k, v2);
59894
+ }
59895
+ } else {
59896
+ form.append(k, v);
59897
+ }
59898
+ }
59899
+ this.rBody = form;
59900
+ }
59901
+ if (args.json) {
59902
+ this.rBody = JSON.stringify(args.json);
59903
+ this.cType = "application/json";
59904
+ }
59905
+ if (args.param) {
59906
+ this.pathParams = args.param;
59907
+ }
59908
+ }
59909
+ let methodUpperCase = this.method.toUpperCase();
59910
+ const headerValues = {
59911
+ ...args?.header,
59912
+ ...typeof opt?.headers === "function" ? await opt.headers() : opt?.headers
59913
+ };
59914
+ if (args?.cookie) {
59915
+ const cookies = [];
59916
+ for (const [key, value] of Object.entries(args.cookie)) {
59917
+ cookies.push(serialize(key, value, { path: "/" }));
59918
+ }
59919
+ headerValues["Cookie"] = cookies.join(",");
59920
+ }
59921
+ if (this.cType) {
59922
+ headerValues["Content-Type"] = this.cType;
59923
+ }
59924
+ const headers = new Headers(headerValues ?? undefined);
59925
+ let url2 = this.url;
59926
+ url2 = removeIndexString(url2);
59927
+ url2 = replaceUrlParam(url2, this.pathParams);
59928
+ if (this.queryParams) {
59929
+ url2 = url2 + "?" + this.queryParams.toString();
59930
+ }
59931
+ methodUpperCase = this.method.toUpperCase();
59932
+ const setBody = !(methodUpperCase === "GET" || methodUpperCase === "HEAD");
59933
+ return (opt?.fetch || fetch)(url2, {
59934
+ body: setBody ? this.rBody : undefined,
59935
+ method: methodUpperCase,
59936
+ headers,
59937
+ ...opt?.init
59938
+ });
59939
+ };
59940
+ }, hc = (baseUrl, options) => createProxy(function proxyCallback(opts) {
59941
+ const buildSearchParamsOption = options?.buildSearchParams ?? buildSearchParams;
59942
+ const parts = [...opts.path];
59943
+ const lastParts = parts.slice(-3).reverse();
59944
+ if (lastParts[0] === "toString") {
59945
+ if (lastParts[1] === "name") {
59946
+ return lastParts[2] || "";
59947
+ }
59948
+ return proxyCallback.toString();
59949
+ }
59950
+ if (lastParts[0] === "valueOf") {
59951
+ if (lastParts[1] === "name") {
59952
+ return lastParts[2] || "";
59953
+ }
59954
+ return proxyCallback;
59955
+ }
59956
+ let method = "";
59957
+ if (/^\$/.test(lastParts[0])) {
59958
+ const last = parts.pop();
59959
+ if (last) {
59960
+ method = last.replace(/^\$/, "");
59961
+ }
59962
+ }
59963
+ const path = parts.join("/");
59964
+ const url2 = mergePath(baseUrl, path);
59965
+ if (method === "url") {
59966
+ let result = url2;
59967
+ if (opts.args[0]) {
59968
+ if (opts.args[0].param) {
59969
+ result = replaceUrlParam(url2, opts.args[0].param);
59970
+ }
59971
+ if (opts.args[0].query) {
59972
+ result = result + "?" + buildSearchParamsOption(opts.args[0].query).toString();
59973
+ }
59974
+ }
59975
+ result = removeIndexString(result);
59976
+ return new URL(result);
59977
+ }
59978
+ if (method === "ws") {
59979
+ const webSocketUrl = replaceUrlProtocol(opts.args[0] && opts.args[0].param ? replaceUrlParam(url2, opts.args[0].param) : url2, "ws");
59980
+ const targetUrl = new URL(webSocketUrl);
59981
+ const queryParams = opts.args[0]?.query;
59982
+ if (queryParams) {
59983
+ Object.entries(queryParams).forEach(([key, value]) => {
59984
+ if (Array.isArray(value)) {
59985
+ value.forEach((item) => targetUrl.searchParams.append(key, item));
59986
+ } else {
59987
+ targetUrl.searchParams.set(key, value);
59988
+ }
59989
+ });
59990
+ }
59991
+ const establishWebSocket = (...args) => {
59992
+ if (options?.webSocket !== undefined && typeof options.webSocket === "function") {
59993
+ return options.webSocket(...args);
59994
+ }
59995
+ return new WebSocket(...args);
59996
+ };
59997
+ return establishWebSocket(targetUrl.toString());
59998
+ }
59999
+ const req = new ClientRequestImpl(url2, method, {
60000
+ buildSearchParams: buildSearchParamsOption
60001
+ });
60002
+ if (method) {
60003
+ options ??= {};
60004
+ const args = deepMerge(options, { ...opts.args[1] });
60005
+ return req.fetch(opts.args[0], args);
60006
+ }
60007
+ return req;
60008
+ }, []);
60009
+ var init_client2 = __esm(() => {
60010
+ init_cookie();
60011
+ init_utils2();
60012
+ });
60013
+
60014
+ // ../../node_modules/.bun/hono@4.11.8/node_modules/hono/dist/client/index.js
60015
+ var init_client3 = __esm(() => {
60016
+ init_client2();
60017
+ init_utils2();
60018
+ });
60019
+
60020
+ // src/lib/hooks/client.ts
60021
+ function createHookClient(url2, key) {
60022
+ return hc(url2, {
60023
+ headers: {
60024
+ "Content-Type": "application/json",
60025
+ Authorization: `Bearer ${key}`
60026
+ }
60027
+ });
60028
+ }
60029
+ async function sendParentMessage(client, roomId) {
60030
+ try {
60031
+ const res = await client.api.rooms[":id"].messages.$post({
60032
+ param: { id: roomId },
60033
+ json: {
60034
+ sender: HOOK_SENDER,
60035
+ content: "Agent activity",
60036
+ sender_type: "agent",
60037
+ color: HOOK_COLOR
60038
+ }
60039
+ });
60040
+ if (!res.ok)
60041
+ return null;
60042
+ const data = await res.json();
60043
+ return data.id;
60044
+ } catch {
60045
+ return null;
60046
+ }
60047
+ }
60048
+ async function sendLogEntry(client, roomId, summary, messageId) {
60049
+ try {
60050
+ await client.api.rooms[":id"].logs.$post({
60051
+ param: { id: roomId },
60052
+ json: {
60053
+ sender: HOOK_SENDER,
60054
+ content: summary,
60055
+ color: HOOK_COLOR,
60056
+ ...messageId ? { message_id: messageId } : {}
60057
+ }
60058
+ });
60059
+ } catch {}
60060
+ }
60061
+ var HOOK_COLOR = "#6b7280", HOOK_SENDER = "hook";
60062
+ var init_client4 = __esm(() => {
60063
+ init_client3();
60064
+ });
60065
+
60066
+ // src/lib/hooks/index.ts
60067
+ var init_hooks = __esm(() => {
60068
+ init_find_room();
60069
+ init_summarize();
60070
+ init_client4();
60071
+ });
60072
+
60073
+ // src/commands/hook/log-tool-use/usecase.ts
60074
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync2, statSync as statSync2, rmSync } from "node:fs";
60075
+ function getOrCreateParentId(sessionId) {
60076
+ const path = `/tmp/meet-ai-hook-${sessionId}.msgid`;
60077
+ try {
60078
+ const mtime = statSync2(path).mtimeMs;
60079
+ if (Date.now() - mtime > PARENT_MSG_TTL_SEC * 1000) {
60080
+ rmSync(path, { force: true });
60081
+ return null;
60082
+ }
60083
+ return readFileSync5(path, "utf-8").trim() || null;
60084
+ } catch {
60085
+ return null;
60086
+ }
60087
+ }
60088
+ function saveParentId(sessionId, msgId) {
60089
+ try {
60090
+ writeFileSync2(`/tmp/meet-ai-hook-${sessionId}.msgid`, msgId);
60091
+ } catch {}
60092
+ }
60093
+ async function processHookInput(rawInput, teamsDir) {
60094
+ let input;
60095
+ try {
60096
+ input = JSON.parse(rawInput);
60097
+ } catch {
60098
+ return "skip";
60099
+ }
60100
+ const { session_id: sessionId, tool_name: toolName, tool_input: toolInput = {} } = input;
60101
+ if (!sessionId || !toolName)
60102
+ return "skip";
60103
+ if (toolName === "SendMessage")
60104
+ return "skip";
60105
+ if (toolName === "Bash") {
60106
+ const cmd = typeof toolInput.command === "string" ? toolInput.command : "";
60107
+ if (cmd.startsWith("cd ") || cmd.startsWith("meet-ai "))
60108
+ return "skip";
60109
+ }
60110
+ const roomId = findRoomId(sessionId, teamsDir);
60111
+ if (!roomId)
60112
+ return "skip";
60113
+ const url2 = process.env.MEET_AI_URL;
60114
+ const key = process.env.MEET_AI_KEY;
60115
+ if (!url2 || !key)
60116
+ return "skip";
60117
+ const client = createHookClient(url2, key);
60118
+ const summary = summarize(toolName, toolInput);
60119
+ let parentId = getOrCreateParentId(sessionId);
60120
+ if (!parentId) {
60121
+ parentId = await sendParentMessage(client, roomId);
60122
+ if (parentId)
60123
+ saveParentId(sessionId, parentId);
60124
+ }
60125
+ await sendLogEntry(client, roomId, summary, parentId ?? undefined);
60126
+ return "sent";
60127
+ }
60128
+ var PARENT_MSG_TTL_SEC = 120;
60129
+ var init_usecase11 = __esm(() => {
60130
+ init_hooks();
60131
+ init_hooks();
60132
+ init_hooks();
60133
+ });
60134
+
60135
+ // src/commands/hook/log-tool-use/command.ts
60136
+ var exports_command12 = {};
60137
+ __export(exports_command12, {
60138
+ default: () => command_default12
60139
+ });
60140
+ var command_default12;
60141
+ var init_command12 = __esm(() => {
60142
+ init_dist();
60143
+ init_usecase11();
60144
+ command_default12 = defineCommand({
60145
+ meta: {
60146
+ name: "log-tool-use",
60147
+ description: "Hook: log tool use events to a chat room"
60148
+ },
60149
+ async run() {
60150
+ try {
60151
+ let input = "";
60152
+ for await (const chunk of process.stdin) {
60153
+ input += chunk;
60154
+ }
60155
+ await processHookInput(input);
60156
+ } catch {}
60157
+ process.exit(0);
60158
+ }
60159
+ });
60160
+ });
60161
+
60162
+ // src/commands/hook/plan-review/usecase.ts
60163
+ var exports_usecase2 = {};
60164
+ __export(exports_usecase2, {
60165
+ processPlanReview: () => processPlanReview
60166
+ });
60167
+ import { setTimeout as delay } from "node:timers/promises";
60168
+ async function createPlanReview(client, roomId, planContent) {
60169
+ try {
60170
+ const res = await client.api.rooms[":id"]["plan-reviews"].$post({
60171
+ param: { id: roomId },
60172
+ json: { plan_content: planContent }
60173
+ });
60174
+ if (!res.ok) {
60175
+ const text = await res.text();
60176
+ process.stderr.write(`[plan-review] create failed: ${res.status} ${text}
60177
+ `);
60178
+ return null;
60179
+ }
60180
+ return await res.json();
60181
+ } catch (error48) {
60182
+ process.stderr.write(`[plan-review] create error: ${error48}
60183
+ `);
60184
+ return null;
60185
+ }
60186
+ }
60187
+ async function pollForDecision(client, roomId, reviewId) {
60188
+ const deadline = Date.now() + POLL_TIMEOUT_MS;
60189
+ while (Date.now() < deadline) {
60190
+ try {
60191
+ const res = await client.api.rooms[":id"]["plan-reviews"][":reviewId"].$get({
60192
+ param: { id: roomId, reviewId }
60193
+ });
60194
+ if (res.ok) {
60195
+ const data = await res.json();
60196
+ if (data.status !== "pending") {
60197
+ return data;
60198
+ }
60199
+ }
60200
+ } catch (error48) {
60201
+ process.stderr.write(`[plan-review] poll error: ${error48}
60202
+ `);
60203
+ }
60204
+ await delay(POLL_INTERVAL_MS);
60205
+ }
60206
+ return null;
60207
+ }
60208
+ function getPromptsByMode(mode) {
60209
+ switch (mode) {
60210
+ case "acceptEdits": {
60211
+ return [
60212
+ { tool: "Bash", prompt: "install dependencies" },
60213
+ { tool: "Bash", prompt: "run tests" },
60214
+ { tool: "Bash", prompt: "run build" },
60215
+ { tool: "Bash", prompt: "run typecheck" },
60216
+ { tool: "Bash", prompt: "run linter" }
60217
+ ];
60218
+ }
60219
+ case "bypassPermissions": {
60220
+ return [{ tool: "Bash", prompt: "run any command" }];
60221
+ }
60222
+ default: {
60223
+ return;
60224
+ }
60225
+ }
60226
+ }
60227
+ function buildAllowOutput(permissionMode) {
60228
+ const allowedPrompts = getPromptsByMode(permissionMode);
60229
+ return {
60230
+ hookSpecificOutput: {
60231
+ hookEventName: "PermissionRequest",
60232
+ decision: allowedPrompts ? { behavior: "allow", allowedPrompts } : { behavior: "allow" }
60233
+ }
60234
+ };
60235
+ }
60236
+ function buildDenyOutput(feedback) {
60237
+ return {
60238
+ hookSpecificOutput: {
60239
+ hookEventName: "PermissionRequest",
60240
+ decision: {
60241
+ behavior: "deny",
60242
+ message: feedback
60243
+ }
60244
+ }
60245
+ };
60246
+ }
60247
+ async function expirePlanReview(client, roomId, reviewId) {
60248
+ try {
60249
+ await client.api.rooms[":id"]["plan-reviews"][":reviewId"].expire.$post({
60250
+ param: { id: roomId, reviewId }
60251
+ });
60252
+ } catch {}
60253
+ }
60254
+ async function processPlanReview(rawInput, teamsDir) {
60255
+ let input;
60256
+ try {
60257
+ input = JSON.parse(rawInput);
60258
+ } catch {
60259
+ process.stderr.write(`[plan-review] failed to parse stdin
60260
+ `);
60261
+ return;
60262
+ }
60263
+ const { session_id: sessionId } = input;
60264
+ if (!sessionId) {
60265
+ process.stderr.write(`[plan-review] missing session_id
60266
+ `);
60267
+ return;
60268
+ }
60269
+ const planContent = input.tool_input?.plan || "_Agent requested to exit plan mode without a plan._";
60270
+ const roomId = findRoomId(sessionId, teamsDir);
60271
+ if (!roomId) {
60272
+ process.stderr.write(`[plan-review] no room found for session
60273
+ `);
60274
+ return;
60275
+ }
60276
+ const url2 = process.env.MEET_AI_URL;
60277
+ const key = process.env.MEET_AI_KEY;
60278
+ if (!url2 || !key) {
60279
+ process.stderr.write(`[plan-review] MEET_AI_URL or MEET_AI_KEY not set
60280
+ `);
60281
+ return;
60282
+ }
60283
+ const client = createHookClient(url2, key);
60284
+ process.stderr.write(`[plan-review] sending plan to room ${roomId} via ${url2}
60285
+ `);
60286
+ const review = await createPlanReview(client, roomId, planContent);
60287
+ if (!review)
60288
+ return;
60289
+ process.stderr.write(`[plan-review] plan review created: ${review.id}, polling for decision...
60290
+ `);
60291
+ const decision = await pollForDecision(client, roomId, review.id);
60292
+ if (!decision) {
60293
+ process.stderr.write(`[plan-review] timed out waiting for decision
60294
+ `);
60295
+ await expirePlanReview(client, roomId, review.id);
60296
+ return;
60297
+ }
60298
+ process.stderr.write(`[plan-review] decision: ${decision.status}
60299
+ `);
60300
+ if (decision.status === "approved" || decision.status === "expired") {
60301
+ process.stdout.write(JSON.stringify(buildAllowOutput(decision.permission_mode)));
60302
+ } else if (decision.status === "denied") {
60303
+ const feedback = decision.feedback || "Plan was rejected. Please revise the plan based on the feedback.";
60304
+ process.stdout.write(JSON.stringify(buildDenyOutput(feedback)));
60305
+ }
60306
+ }
60307
+ var POLL_INTERVAL_MS = 2000, POLL_TIMEOUT_MS = 2592000000;
60308
+ var init_usecase12 = __esm(() => {
60309
+ init_client4();
60310
+ init_find_room();
60311
+ });
60312
+
60313
+ // src/commands/hook/plan-review/command.ts
60314
+ var exports_command13 = {};
60315
+ __export(exports_command13, {
60316
+ default: () => command_default13
60317
+ });
60318
+ var command_default13;
60319
+ var init_command13 = __esm(() => {
60320
+ init_dist();
60321
+ command_default13 = defineCommand({
60322
+ meta: {
60323
+ name: "plan-review",
60324
+ description: "Claude Code hook: send plan for review and poll for decision"
60325
+ },
60326
+ async run() {
60327
+ try {
60328
+ let input = "";
60329
+ for await (const chunk of process.stdin) {
60330
+ input += chunk;
60331
+ }
60332
+ const { processPlanReview: processPlanReview2 } = await Promise.resolve().then(() => (init_usecase12(), exports_usecase2));
60333
+ await processPlanReview2(input);
60334
+ } catch (error48) {
60335
+ process.stderr.write(`[plan-review] fatal: ${error48}
60336
+ `);
60337
+ }
60338
+ process.exit(0);
60339
+ }
60340
+ });
60341
+ });
60342
+
60343
+ // src/commands/hook/question-review/usecase.ts
60344
+ function formatQuestions(questions) {
60345
+ return questions.map((q) => {
60346
+ let text = `**${q.question}**
60347
+ `;
60348
+ for (let i = 0;i < q.options.length; i++) {
60349
+ const opt = q.options[i];
60350
+ text += `${i + 1}. **${opt.label}**`;
60351
+ if (opt.description)
60352
+ text += ` — ${opt.description}`;
60353
+ text += `
60354
+ `;
60355
+ }
60356
+ if (q.multiSelect) {
60357
+ text += `
60358
+ _Multiple choices allowed._`;
60359
+ }
60360
+ return text;
60361
+ }).join(`
60362
+
60363
+ `);
60364
+ }
60365
+ async function createQuestionReview(client, roomId, questions, formattedContent) {
60366
+ try {
60367
+ const res = await client.api.rooms[":id"]["question-reviews"].$post({
60368
+ param: { id: roomId },
60369
+ json: {
60370
+ questions_json: JSON.stringify(questions),
60371
+ formatted_content: formattedContent
60372
+ }
60373
+ });
60374
+ if (!res.ok) {
60375
+ const text = await res.text();
60376
+ process.stderr.write(`[question-review] create failed: ${res.status} ${text}
60377
+ `);
60378
+ return null;
60379
+ }
60380
+ return await res.json();
60381
+ } catch (error48) {
60382
+ process.stderr.write(`[question-review] create error: ${error48}
60383
+ `);
60384
+ return null;
60385
+ }
60386
+ }
60387
+ async function pollForAnswer(client, roomId, reviewId, pollInterval = POLL_INTERVAL_MS2, pollTimeout = POLL_TIMEOUT_MS2) {
60388
+ const deadline = Date.now() + pollTimeout;
60389
+ while (Date.now() < deadline) {
60390
+ try {
60391
+ const res = await client.api.rooms[":id"]["question-reviews"][":reviewId"].$get({
60392
+ param: { id: roomId, reviewId }
60393
+ });
60394
+ if (res.ok) {
60395
+ const data = await res.json();
60396
+ if (data.status !== "pending") {
60397
+ return data;
60398
+ }
60399
+ }
60400
+ } catch (error48) {
60401
+ process.stderr.write(`[question-review] poll error: ${error48}
60402
+ `);
60403
+ }
60404
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
60405
+ }
60406
+ return null;
60407
+ }
60408
+ function buildOutput(questions, answers) {
60409
+ return {
60410
+ hookSpecificOutput: {
60411
+ hookEventName: "PermissionRequest",
60412
+ decision: {
60413
+ behavior: "allow",
60414
+ updatedInput: {
60415
+ questions,
60416
+ answers
60417
+ }
60418
+ }
60419
+ }
60420
+ };
60421
+ }
60422
+ async function expireReview(client, roomId, reviewId) {
60423
+ try {
60424
+ await client.api.rooms[":id"]["question-reviews"][":reviewId"].expire.$post({
60425
+ param: { id: roomId, reviewId }
60426
+ });
60427
+ } catch {}
60428
+ }
60429
+ async function sendTimeoutMessage(client, roomId) {
60430
+ try {
60431
+ await client.api.rooms[":id"].messages.$post({
60432
+ param: { id: roomId },
60433
+ json: {
60434
+ sender: "hook",
60435
+ content: "_Question timed out — answer in terminal instead._",
60436
+ sender_type: "agent",
60437
+ color: "#f59e0b"
60438
+ }
60439
+ });
60440
+ } catch {}
60441
+ }
60442
+ async function processQuestionReview(rawInput, teamsDir, opts) {
60443
+ let input;
60444
+ try {
60445
+ input = JSON.parse(rawInput);
60446
+ } catch {
60447
+ process.stderr.write(`[question-review] failed to parse stdin
60448
+ `);
60449
+ return;
60450
+ }
60451
+ const { session_id: sessionId, hook_event_name: hookEventName, tool_input: toolInput } = input;
60452
+ if (!sessionId || !toolInput?.questions?.length) {
60453
+ process.stderr.write(`[question-review] missing session_id or questions
60454
+ `);
60455
+ return;
60456
+ }
60457
+ process.stderr.write(`[question-review] triggered by ${hookEventName} event
60458
+ `);
60459
+ const roomId = findRoomId(sessionId, teamsDir);
60460
+ if (!roomId) {
60461
+ process.stderr.write(`[question-review] no room found for session
60462
+ `);
60463
+ return;
60464
+ }
60465
+ const url2 = process.env.MEET_AI_URL;
60466
+ const key = process.env.MEET_AI_KEY;
60467
+ if (!url2 || !key) {
60468
+ process.stderr.write(`[question-review] MEET_AI_URL or MEET_AI_KEY not set
60469
+ `);
60470
+ return;
60471
+ }
60472
+ const client = createHookClient(url2, key);
60473
+ const formattedContent = formatQuestions(toolInput.questions);
60474
+ process.stderr.write(`[question-review] sending question to room ${roomId} via ${url2}
60475
+ `);
60476
+ const review = await createQuestionReview(client, roomId, toolInput.questions, formattedContent);
60477
+ if (!review)
60478
+ return;
60479
+ process.stderr.write(`[question-review] created: ${review.id}, polling for answer...
60480
+ `);
60481
+ const result = await pollForAnswer(client, roomId, review.id, opts?.pollInterval, opts?.pollTimeout);
60482
+ if (!result) {
60483
+ process.stderr.write(`[question-review] timed out waiting for answer
60484
+ `);
60485
+ await expireReview(client, roomId, review.id);
60486
+ await sendTimeoutMessage(client, roomId);
60487
+ return;
60488
+ }
60489
+ process.stderr.write(`[question-review] answer received: ${result.status}
60490
+ `);
60491
+ if (result.status === "answered" && result.answers_json) {
60492
+ let answers;
60493
+ try {
60494
+ answers = JSON.parse(result.answers_json);
60495
+ } catch (error48) {
60496
+ process.stderr.write(`[question-review] failed to parse answers_json: ${error48}
60497
+ `);
60498
+ return;
60499
+ }
60500
+ process.stdout.write(JSON.stringify(buildOutput(toolInput.questions, answers)));
60501
+ }
60502
+ }
60503
+ var POLL_INTERVAL_MS2 = 2000, POLL_TIMEOUT_MS2 = 1800000;
60504
+ var init_usecase13 = __esm(() => {
60505
+ init_client4();
60506
+ init_find_room();
60507
+ });
60508
+
60509
+ // src/commands/hook/question-review/command.ts
60510
+ var exports_command14 = {};
60511
+ __export(exports_command14, {
60512
+ default: () => command_default14
60513
+ });
60514
+ var command_default14;
60515
+ var init_command14 = __esm(() => {
60516
+ init_dist();
60517
+ init_usecase13();
60518
+ command_default14 = defineCommand({
60519
+ meta: {
60520
+ name: "question-review",
60521
+ description: "Handle Claude Code AskUser permission hook — routes questions to meet-ai room for review"
60522
+ },
60523
+ async run() {
60524
+ try {
60525
+ let input = "";
60526
+ for await (const chunk of process.stdin) {
60527
+ input += chunk;
60528
+ }
60529
+ await processQuestionReview(input);
60530
+ } catch (error48) {
60531
+ process.stderr.write(`[question-review] fatal: ${error48}
60532
+ `);
60533
+ }
60534
+ process.exit(0);
60535
+ }
60536
+ });
60537
+ });
60538
+
60539
+ // src/commands/hook/permission-review/usecase.ts
60540
+ function formatPermissionRequest(toolName, toolInput) {
60541
+ let text = `**Permission request: ${toolName}**
60542
+ `;
60543
+ if (toolInput) {
60544
+ const entries = Object.entries(toolInput);
60545
+ if (entries.length > 0) {
60546
+ for (const [key, value] of entries) {
60547
+ const valueStr = typeof value === "string" ? value : JSON.stringify(value);
60548
+ const truncated = valueStr.length > 200 ? valueStr.slice(0, 200) + "..." : valueStr;
60549
+ text += `
60550
+ **${key}:** \`${truncated}\``;
60551
+ }
60552
+ }
60553
+ }
60554
+ return text;
60555
+ }
60556
+ async function createPermissionReview(client, roomId, toolName, toolInput, formattedContent) {
60557
+ try {
60558
+ const res = await client.api.rooms[":id"]["permission-reviews"].$post({
60559
+ param: { id: roomId },
60560
+ json: {
60561
+ tool_name: toolName,
60562
+ tool_input_json: toolInput ? JSON.stringify(toolInput) : undefined,
60563
+ formatted_content: formattedContent
60564
+ }
60565
+ });
60566
+ if (!res.ok) {
60567
+ const text = await res.text();
60568
+ process.stderr.write(`[permission-review] create failed: ${res.status} ${text}
60569
+ `);
60570
+ return null;
60571
+ }
60572
+ return await res.json();
60573
+ } catch (error48) {
60574
+ process.stderr.write(`[permission-review] create error: ${error48}
60575
+ `);
60576
+ return null;
60577
+ }
60578
+ }
60579
+ async function pollForDecision2(client, roomId, reviewId, pollInterval = POLL_INTERVAL_MS3, pollTimeout = POLL_TIMEOUT_MS3) {
60580
+ const deadline = Date.now() + pollTimeout;
60581
+ while (Date.now() < deadline) {
60582
+ try {
60583
+ const res = await client.api.rooms[":id"]["permission-reviews"][":reviewId"].$get({
60584
+ param: { id: roomId, reviewId }
60585
+ });
60586
+ if (res.ok) {
60587
+ const data = await res.json();
60588
+ if (data.status !== "pending") {
60589
+ return data;
60590
+ }
60591
+ }
60592
+ } catch (error48) {
60593
+ process.stderr.write(`[permission-review] poll error: ${error48}
60594
+ `);
60595
+ }
60596
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
60597
+ }
60598
+ return null;
60599
+ }
60600
+ function buildAllowOutput2() {
60601
+ return {
60602
+ hookSpecificOutput: {
60603
+ hookEventName: "PermissionRequest",
60604
+ decision: { behavior: "allow" }
60605
+ }
60606
+ };
60607
+ }
60608
+ function buildDenyOutput2(message) {
60609
+ return {
60610
+ hookSpecificOutput: {
60611
+ hookEventName: "PermissionRequest",
60612
+ decision: {
60613
+ behavior: "deny",
60614
+ message
60615
+ }
60616
+ }
60617
+ };
60618
+ }
60619
+ async function expireReview2(client, roomId, reviewId) {
60620
+ try {
60621
+ await client.api.rooms[":id"]["permission-reviews"][":reviewId"].expire.$post({
60622
+ param: { id: roomId, reviewId }
60623
+ });
60624
+ } catch {}
60625
+ }
60626
+ async function sendTimeoutMessage2(client, roomId) {
60627
+ try {
60628
+ await client.api.rooms[":id"].messages.$post({
60629
+ param: { id: roomId },
60630
+ json: {
60631
+ sender: "hook",
60632
+ content: "_Permission request timed out — approve in terminal instead._",
60633
+ sender_type: "agent",
60634
+ color: "#f97316"
60635
+ }
60636
+ });
60637
+ } catch {}
60638
+ }
60639
+ async function processPermissionReview(rawInput, teamsDir, opts) {
60640
+ let input;
60641
+ try {
60642
+ input = JSON.parse(rawInput);
60643
+ } catch {
60644
+ process.stderr.write(`[permission-review] failed to parse stdin
60645
+ `);
60646
+ return;
60647
+ }
60648
+ const { session_id: sessionId, hook_event_name: hookEventName, tool_name: toolName, tool_input: toolInput } = input;
60649
+ if (!sessionId || !toolName) {
60650
+ process.stderr.write(`[permission-review] missing session_id or tool_name
60651
+ `);
60652
+ return;
60653
+ }
60654
+ const EXCLUDED_TOOLS = ["ExitPlanMode", "AskUserQuestion"];
60655
+ if (EXCLUDED_TOOLS.includes(toolName)) {
60656
+ process.stderr.write(`[permission-review] skipping ${toolName} — handled by dedicated hook
60657
+ `);
60658
+ return;
60659
+ }
60660
+ process.stderr.write(`[permission-review] triggered by ${hookEventName} for tool ${toolName}
60661
+ `);
60662
+ const roomId = findRoomId(sessionId, teamsDir);
60663
+ if (!roomId) {
60664
+ process.stderr.write(`[permission-review] no room found for session
60665
+ `);
60666
+ return;
60667
+ }
60668
+ const url2 = process.env.MEET_AI_URL;
60669
+ const key = process.env.MEET_AI_KEY;
60670
+ if (!url2 || !key) {
60671
+ process.stderr.write(`[permission-review] MEET_AI_URL or MEET_AI_KEY not set
60672
+ `);
60673
+ return;
60674
+ }
60675
+ const client = createHookClient(url2, key);
60676
+ const formattedContent = formatPermissionRequest(toolName, toolInput);
60677
+ process.stderr.write(`[permission-review] sending permission request to room ${roomId} via ${url2}
60678
+ `);
60679
+ const review = await createPermissionReview(client, roomId, toolName, toolInput, formattedContent);
60680
+ if (!review)
60681
+ return;
60682
+ process.stderr.write(`[permission-review] created: ${review.id}, polling for decision...
60683
+ `);
60684
+ const result = await pollForDecision2(client, roomId, review.id, opts?.pollInterval, opts?.pollTimeout);
60685
+ if (!result) {
60686
+ process.stderr.write(`[permission-review] timed out waiting for decision
60687
+ `);
60688
+ await expireReview2(client, roomId, review.id);
60689
+ await sendTimeoutMessage2(client, roomId);
60690
+ return;
60691
+ }
60692
+ process.stderr.write(`[permission-review] decision received: ${result.status}
60693
+ `);
60694
+ if (result.status === "approved") {
60695
+ process.stdout.write(JSON.stringify(buildAllowOutput2()));
60696
+ } else if (result.status === "denied") {
60697
+ const message = result.feedback || "Permission denied by user.";
60698
+ process.stdout.write(JSON.stringify(buildDenyOutput2(message)));
60699
+ }
60700
+ }
60701
+ var POLL_INTERVAL_MS3 = 2000, POLL_TIMEOUT_MS3 = 1800000;
60702
+ var init_usecase14 = __esm(() => {
60703
+ init_client4();
60704
+ init_find_room();
60705
+ });
60706
+
60707
+ // src/commands/hook/permission-review/command.ts
60708
+ var exports_command15 = {};
60709
+ __export(exports_command15, {
60710
+ default: () => command_default15
60711
+ });
60712
+ var command_default15;
60713
+ var init_command15 = __esm(() => {
60714
+ init_dist();
60715
+ init_usecase14();
60716
+ command_default15 = defineCommand({
60717
+ meta: {
60718
+ name: "permission-review",
60719
+ description: "Handle Claude Code PermissionRequest hook — routes tool permission requests to meet-ai room for review"
60720
+ },
60721
+ async run() {
60722
+ try {
60723
+ let input = "";
60724
+ for await (const chunk of process.stdin) {
60725
+ input += chunk;
60726
+ }
60727
+ await processPermissionReview(input);
60728
+ } catch (error48) {
60729
+ process.stderr.write(`[permission-review] fatal: ${error48}
60730
+ `);
60731
+ }
60732
+ process.exit(0);
60733
+ }
60734
+ });
60735
+ });
60736
+
60737
+ // src/commands/hook/command.ts
60738
+ var exports_command16 = {};
60739
+ __export(exports_command16, {
60740
+ default: () => command_default16
60741
+ });
60742
+ var command_default16;
60743
+ var init_command16 = __esm(() => {
60744
+ init_dist();
60745
+ command_default16 = defineCommand({
60746
+ meta: {
60747
+ name: "hook",
60748
+ description: "Claude Code hook subcommands"
60749
+ },
60750
+ subCommands: {
60751
+ "log-tool-use": () => Promise.resolve().then(() => (init_command12(), exports_command12)).then((m) => m.default),
60752
+ "plan-review": () => Promise.resolve().then(() => (init_command13(), exports_command13)).then((m) => m.default),
60753
+ "question-review": () => Promise.resolve().then(() => (init_command14(), exports_command14)).then((m) => m.default),
60754
+ "permission-review": () => Promise.resolve().then(() => (init_command15(), exports_command15)).then((m) => m.default)
60755
+ }
60756
+ });
60757
+ });
60758
+
60759
+ // src/commands/setup-hooks/usecase.ts
60760
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
60761
+ import { existsSync as existsSync4 } from "node:fs";
60762
+ import { resolve as resolve2, dirname as dirname2 } from "node:path";
60763
+ import { homedir as homedir3 } from "node:os";
60764
+ function isMeetAiHook(entry) {
60765
+ return entry.hooks?.some((h) => typeof h.command === "string" && h.command.startsWith("meet-ai hook ")) ?? false;
60766
+ }
60767
+ function getSettingsPath(project) {
60768
+ if (project) {
60769
+ return resolve2(process.cwd(), ".claude", "settings.json");
60770
+ }
60771
+ return resolve2(homedir3(), ".claude", "settings.json");
60772
+ }
60773
+ async function readSettings(path) {
60774
+ if (!existsSync4(path)) {
60775
+ return {};
60776
+ }
60777
+ const raw = await readFile(path, "utf-8");
60778
+ const trimmed = raw.trim();
60779
+ if (!trimmed)
60780
+ return {};
60781
+ try {
60782
+ return JSON.parse(trimmed);
60783
+ } catch {
60784
+ return {};
60785
+ }
60786
+ }
60787
+ function mergeHooks(existing) {
60788
+ const result = { ...existing };
60789
+ const added = [];
60790
+ for (const [event, matchers] of Object.entries(MEET_AI_HOOKS)) {
60791
+ if (!result[event]) {
60792
+ result[event] = [];
60793
+ }
60794
+ for (const newMatcher of matchers) {
60795
+ const existingIdx = result[event].findIndex((m) => m.matcher === newMatcher.matcher && isMeetAiHook(m));
60796
+ if (existingIdx >= 0) {
60797
+ result[event][existingIdx] = newMatcher;
60798
+ added.push(`updated ${event} [${newMatcher.matcher}]`);
60799
+ } else {
60800
+ result[event].push(newMatcher);
60801
+ added.push(`added ${event} [${newMatcher.matcher}]`);
60802
+ }
60803
+ }
60804
+ }
60805
+ return { merged: result, added };
60806
+ }
60807
+ function removeHooks(existing) {
60808
+ const result = {};
60809
+ const removed = [];
60810
+ for (const [event, matchers] of Object.entries(existing)) {
60811
+ const kept = matchers.filter((m) => {
60812
+ if (isMeetAiHook(m)) {
60813
+ removed.push(`removed ${event} [${m.matcher}]`);
60814
+ return false;
60815
+ }
60816
+ return true;
60817
+ });
60818
+ if (kept.length > 0) {
60819
+ result[event] = kept;
60820
+ }
60821
+ }
60822
+ return { cleaned: result, removed };
60823
+ }
60824
+ async function setupHooks(options) {
60825
+ const settingsPath = options._settingsPath ?? getSettingsPath(options.project);
60826
+ const settings = await readSettings(settingsPath);
60827
+ const existingHooks = settings.hooks ?? {};
60828
+ if (options.remove) {
60829
+ const { cleaned, removed } = removeHooks(existingHooks);
60830
+ if (removed.length === 0) {
60831
+ info("No meet-ai hooks found to remove.");
60832
+ return;
60833
+ }
60834
+ if (options.dryRun) {
60835
+ info(`Dry run — would modify ${settingsPath}:`);
60836
+ for (const r of removed) {
60837
+ console.log(import_picocolors2.default.yellow(` ${r}`));
60838
+ }
60839
+ return;
60840
+ }
60841
+ const updated = { ...settings, hooks: cleaned };
60842
+ if (Object.keys(cleaned).length === 0) {
60843
+ delete updated.hooks;
60844
+ }
60845
+ await mkdir(dirname2(settingsPath), { recursive: true });
60846
+ await writeFile(settingsPath, JSON.stringify(updated, null, 2) + `
60847
+ `);
60848
+ for (const r of removed) {
60849
+ console.log(import_picocolors2.default.yellow(` ${r}`));
60850
+ }
60851
+ ok(`Removed meet-ai hooks from ${settingsPath}`);
60852
+ } else {
60853
+ const { merged, added } = mergeHooks(existingHooks);
60854
+ if (options.dryRun) {
60855
+ info(`Dry run — would modify ${settingsPath}:`);
60856
+ for (const a of added) {
60857
+ console.log(import_picocolors2.default.green(` ${a}`));
60858
+ }
60859
+ return;
60860
+ }
60861
+ const updated = { ...settings, hooks: merged };
60862
+ await mkdir(dirname2(settingsPath), { recursive: true });
60863
+ await writeFile(settingsPath, JSON.stringify(updated, null, 2) + `
60864
+ `);
60865
+ for (const a of added) {
60866
+ console.log(import_picocolors2.default.green(` ${a}`));
60867
+ }
60868
+ ok(`Hooks written to ${settingsPath}`);
60869
+ }
60870
+ }
60871
+ var import_picocolors2, MEET_AI_HOOKS;
60872
+ var init_usecase15 = __esm(() => {
60873
+ init_output();
60874
+ import_picocolors2 = __toESM(require_picocolors(), 1);
60875
+ MEET_AI_HOOKS = {
60876
+ PostToolUse: [
60877
+ {
60878
+ matcher: ".*",
60879
+ hooks: [
60880
+ {
60881
+ type: "command",
60882
+ command: "meet-ai hook log-tool-use",
60883
+ timeout: 10
60884
+ }
60885
+ ]
60886
+ }
60887
+ ],
60888
+ PermissionRequest: [
60889
+ {
60890
+ matcher: "ExitPlanMode",
60891
+ hooks: [
60892
+ {
60893
+ type: "command",
60894
+ command: "meet-ai hook plan-review",
60895
+ timeout: 2592000
60896
+ }
60897
+ ]
60898
+ },
60899
+ {
60900
+ matcher: "AskUserQuestion",
60901
+ hooks: [
60902
+ {
60903
+ type: "command",
60904
+ command: "meet-ai hook question-review",
60905
+ timeout: 1800
60906
+ }
60907
+ ]
60908
+ },
60909
+ {
60910
+ matcher: ".*",
60911
+ hooks: [
60912
+ {
60913
+ type: "command",
60914
+ command: "meet-ai hook permission-review",
60915
+ timeout: 1800
60916
+ }
60917
+ ]
60918
+ }
60919
+ ]
60920
+ };
60921
+ });
60922
+
60923
+ // src/commands/setup-hooks/command.ts
60924
+ var exports_command17 = {};
60925
+ __export(exports_command17, {
60926
+ default: () => command_default17
60927
+ });
60928
+ var command_default17;
60929
+ var init_command17 = __esm(() => {
60930
+ init_dist();
60931
+ init_usecase15();
60932
+ init_output();
60933
+ command_default17 = defineCommand({
60934
+ meta: {
60935
+ name: "setup-hooks",
60936
+ description: "Configure Claude Code hooks for meet-ai in ~/.claude/settings.json"
60937
+ },
60938
+ args: {
60939
+ project: {
60940
+ type: "boolean",
60941
+ description: "Write to ./.claude/settings.json instead of ~/.claude/settings.json",
60942
+ default: false
60943
+ },
60944
+ "dry-run": {
60945
+ type: "boolean",
60946
+ description: "Print what would be written without actually writing",
60947
+ default: false
60948
+ },
60949
+ remove: {
60950
+ type: "boolean",
60951
+ description: "Remove meet-ai hooks from settings instead of adding them",
60952
+ default: false
60953
+ }
60954
+ },
60955
+ async run({ args }) {
60956
+ try {
60957
+ await setupHooks({
60958
+ project: args.project,
60959
+ dryRun: args["dry-run"],
60960
+ remove: args.remove
60961
+ });
60962
+ } catch (error48) {
60963
+ err(error48 instanceof Error ? error48.message : String(error48));
60964
+ process.exit(1);
60965
+ }
60966
+ }
60967
+ });
60968
+ });
60969
+
59655
60970
  // src/index.ts
59656
60971
  init_dist();
59657
60972
  init_output();
59658
60973
  var main = defineCommand({
59659
60974
  meta: {
59660
60975
  name: "meet-ai",
59661
- version: "0.0.18",
60976
+ version: "0.0.19",
59662
60977
  description: "CLI for meet-ai chat rooms — create rooms, send messages, and stream via WebSocket"
59663
60978
  },
59664
60979
  args: {
@@ -59679,7 +60994,9 @@ var main = defineCommand({
59679
60994
  "send-tasks": () => Promise.resolve().then(() => (init_command8(), exports_command8)).then((m) => m.default),
59680
60995
  "download-attachment": () => Promise.resolve().then(() => (init_command9(), exports_command9)).then((m) => m.default),
59681
60996
  "generate-key": () => Promise.resolve().then(() => (init_command10(), exports_command10)).then((m) => m.default),
59682
- dashboard: () => init_command11().then(() => exports_command11).then((m) => m.default)
60997
+ dashboard: () => init_command11().then(() => exports_command11).then((m) => m.default),
60998
+ hook: () => Promise.resolve().then(() => (init_command16(), exports_command16)).then((m) => m.default),
60999
+ "setup-hooks": () => Promise.resolve().then(() => (init_command17(), exports_command17)).then((m) => m.default)
59683
61000
  },
59684
61001
  async run({ args }) {
59685
61002
  const hasSubcommand = process.argv.length > 2;