@cybedefend/vibedefend 1.3.2 → 1.4.1

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 (41) hide show
  1. package/README.md +32 -5
  2. package/dist/api/projects.js +158 -0
  3. package/dist/api/projects.js.map +1 -0
  4. package/dist/clients/claude-code.js +16 -1
  5. package/dist/clients/claude-code.js.map +1 -1
  6. package/dist/config.js +2 -0
  7. package/dist/config.js.map +1 -1
  8. package/dist/custom-regions.js +5 -0
  9. package/dist/custom-regions.js.map +1 -1
  10. package/dist/endpoints.js +59 -0
  11. package/dist/endpoints.js.map +1 -0
  12. package/dist/git.js +103 -0
  13. package/dist/git.js.map +1 -0
  14. package/dist/hook-runner.js +548 -277
  15. package/dist/hooks/runtime/fetch-rules.js +5 -3
  16. package/dist/hooks/runtime/fetch-rules.js.map +1 -1
  17. package/dist/hooks/runtime/judge-injection.js +65 -0
  18. package/dist/hooks/runtime/judge-injection.js.map +1 -0
  19. package/dist/hooks/runtime/repo-link-cache.js +116 -0
  20. package/dist/hooks/runtime/repo-link-cache.js.map +1 -0
  21. package/dist/hooks/runtime/resolve.js +79 -0
  22. package/dist/hooks/runtime/resolve.js.map +1 -1
  23. package/dist/hooks/runtime/session-start.js +5 -3
  24. package/dist/hooks/runtime/session-start.js.map +1 -1
  25. package/dist/hooks/runtime/user-prompt-submit.js +10 -7
  26. package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
  27. package/dist/index.js +40 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/install.js +142 -88
  30. package/dist/install.js.map +1 -1
  31. package/dist/link.js +325 -0
  32. package/dist/link.js.map +1 -0
  33. package/dist/login.js +2 -23
  34. package/dist/login.js.map +1 -1
  35. package/dist/logout.js +87 -0
  36. package/dist/logout.js.map +1 -0
  37. package/dist/org-gate.js +110 -0
  38. package/dist/org-gate.js.map +1 -0
  39. package/dist/prompts.js +5 -7
  40. package/dist/prompts.js.map +1 -1
  41. package/package.json +1 -1
@@ -269,16 +269,16 @@ var require_re2 = __commonJS({
269
269
  if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) {
270
270
  return UTF8Decoder.decode(heap.subarray(idx, endPtr));
271
271
  } else {
272
- var str = "";
272
+ var str2 = "";
273
273
  while (idx < endPtr) {
274
274
  var u0 = heap[idx++];
275
275
  if (!(u0 & 128)) {
276
- str += String.fromCharCode(u0);
276
+ str2 += String.fromCharCode(u0);
277
277
  continue;
278
278
  }
279
279
  var u1 = heap[idx++] & 63;
280
280
  if ((u0 & 224) == 192) {
281
- str += String.fromCharCode((u0 & 31) << 6 | u1);
281
+ str2 += String.fromCharCode((u0 & 31) << 6 | u1);
282
282
  continue;
283
283
  }
284
284
  var u2 = heap[idx++] & 63;
@@ -289,27 +289,27 @@ var require_re2 = __commonJS({
289
289
  u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heap[idx++] & 63;
290
290
  }
291
291
  if (u0 < 65536) {
292
- str += String.fromCharCode(u0);
292
+ str2 += String.fromCharCode(u0);
293
293
  } else {
294
294
  var ch = u0 - 65536;
295
- str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
295
+ str2 += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
296
296
  }
297
297
  }
298
298
  }
299
- return str;
299
+ return str2;
300
300
  }
301
301
  function UTF8ToString(ptr, maxBytesToRead) {
302
302
  return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
303
303
  }
304
- function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
304
+ function stringToUTF8Array(str2, heap, outIdx, maxBytesToWrite) {
305
305
  if (!(maxBytesToWrite > 0))
306
306
  return 0;
307
307
  var startIdx = outIdx;
308
308
  var endIdx = outIdx + maxBytesToWrite - 1;
309
- for (var i = 0; i < str.length; ++i) {
310
- var u = str.charCodeAt(i);
309
+ for (var i = 0; i < str2.length; ++i) {
310
+ var u = str2.charCodeAt(i);
311
311
  if (u >= 55296 && u <= 57343) {
312
- var u1 = str.charCodeAt(++i);
312
+ var u1 = str2.charCodeAt(++i);
313
313
  u = 65536 + ((u & 1023) << 10) | u1 & 1023;
314
314
  }
315
315
  if (u <= 127) {
@@ -336,15 +336,15 @@ var require_re2 = __commonJS({
336
336
  heap[outIdx] = 0;
337
337
  return outIdx - startIdx;
338
338
  }
339
- function stringToUTF8(str, outPtr, maxBytesToWrite) {
339
+ function stringToUTF8(str2, outPtr, maxBytesToWrite) {
340
340
  assert(typeof maxBytesToWrite == "number", "stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");
341
- return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
341
+ return stringToUTF8Array(str2, HEAPU8, outPtr, maxBytesToWrite);
342
342
  }
343
- function lengthBytesUTF8(str) {
343
+ function lengthBytesUTF8(str2) {
344
344
  var len = 0;
345
- for (var i = 0; i < str.length; ++i) {
346
- var u = str.charCodeAt(i);
347
- if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;
345
+ for (var i = 0; i < str2.length; ++i) {
346
+ var u = str2.charCodeAt(i);
347
+ if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str2.charCodeAt(++i) & 1023;
348
348
  if (u <= 127) ++len;
349
349
  else if (u <= 2047) len += 2;
350
350
  else if (u <= 65535) len += 3;
@@ -363,16 +363,16 @@ var require_re2 = __commonJS({
363
363
  if (endPtr - ptr > 32 && UTF16Decoder) {
364
364
  return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));
365
365
  } else {
366
- var str = "";
366
+ var str2 = "";
367
367
  for (var i = 0; !(i >= maxBytesToRead / 2); ++i) {
368
368
  var codeUnit = HEAP16[ptr + i * 2 >> 1];
369
369
  if (codeUnit == 0) break;
370
- str += String.fromCharCode(codeUnit);
370
+ str2 += String.fromCharCode(codeUnit);
371
371
  }
372
- return str;
372
+ return str2;
373
373
  }
374
374
  }
375
- function stringToUTF16(str, outPtr, maxBytesToWrite) {
375
+ function stringToUTF16(str2, outPtr, maxBytesToWrite) {
376
376
  assert(outPtr % 2 == 0, "Pointer passed to stringToUTF16 must be aligned to two bytes!");
377
377
  assert(typeof maxBytesToWrite == "number", "stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");
378
378
  if (maxBytesToWrite === void 0) {
@@ -381,36 +381,36 @@ var require_re2 = __commonJS({
381
381
  if (maxBytesToWrite < 2) return 0;
382
382
  maxBytesToWrite -= 2;
383
383
  var startPtr = outPtr;
384
- var numCharsToWrite = maxBytesToWrite < str.length * 2 ? maxBytesToWrite / 2 : str.length;
384
+ var numCharsToWrite = maxBytesToWrite < str2.length * 2 ? maxBytesToWrite / 2 : str2.length;
385
385
  for (var i = 0; i < numCharsToWrite; ++i) {
386
- var codeUnit = str.charCodeAt(i);
386
+ var codeUnit = str2.charCodeAt(i);
387
387
  HEAP16[outPtr >> 1] = codeUnit;
388
388
  outPtr += 2;
389
389
  }
390
390
  HEAP16[outPtr >> 1] = 0;
391
391
  return outPtr - startPtr;
392
392
  }
393
- function lengthBytesUTF16(str) {
394
- return str.length * 2;
393
+ function lengthBytesUTF16(str2) {
394
+ return str2.length * 2;
395
395
  }
396
396
  function UTF32ToString(ptr, maxBytesToRead) {
397
397
  assert(ptr % 4 == 0, "Pointer passed to UTF32ToString must be aligned to four bytes!");
398
398
  var i = 0;
399
- var str = "";
399
+ var str2 = "";
400
400
  while (!(i >= maxBytesToRead / 4)) {
401
401
  var utf32 = HEAP32[ptr + i * 4 >> 2];
402
402
  if (utf32 == 0) break;
403
403
  ++i;
404
404
  if (utf32 >= 65536) {
405
405
  var ch = utf32 - 65536;
406
- str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
406
+ str2 += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
407
407
  } else {
408
- str += String.fromCharCode(utf32);
408
+ str2 += String.fromCharCode(utf32);
409
409
  }
410
410
  }
411
- return str;
411
+ return str2;
412
412
  }
413
- function stringToUTF32(str, outPtr, maxBytesToWrite) {
413
+ function stringToUTF32(str2, outPtr, maxBytesToWrite) {
414
414
  assert(outPtr % 4 == 0, "Pointer passed to stringToUTF32 must be aligned to four bytes!");
415
415
  assert(typeof maxBytesToWrite == "number", "stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");
416
416
  if (maxBytesToWrite === void 0) {
@@ -419,10 +419,10 @@ var require_re2 = __commonJS({
419
419
  if (maxBytesToWrite < 4) return 0;
420
420
  var startPtr = outPtr;
421
421
  var endPtr = startPtr + maxBytesToWrite - 4;
422
- for (var i = 0; i < str.length; ++i) {
423
- var codeUnit = str.charCodeAt(i);
422
+ for (var i = 0; i < str2.length; ++i) {
423
+ var codeUnit = str2.charCodeAt(i);
424
424
  if (codeUnit >= 55296 && codeUnit <= 57343) {
425
- var trailSurrogate = str.charCodeAt(++i);
425
+ var trailSurrogate = str2.charCodeAt(++i);
426
426
  codeUnit = 65536 + ((codeUnit & 1023) << 10) | trailSurrogate & 1023;
427
427
  }
428
428
  HEAP32[outPtr >> 2] = codeUnit;
@@ -432,10 +432,10 @@ var require_re2 = __commonJS({
432
432
  HEAP32[outPtr >> 2] = 0;
433
433
  return outPtr - startPtr;
434
434
  }
435
- function lengthBytesUTF32(str) {
435
+ function lengthBytesUTF32(str2) {
436
436
  var len = 0;
437
- for (var i = 0; i < str.length; ++i) {
438
- var codeUnit = str.charCodeAt(i);
437
+ for (var i = 0; i < str2.length; ++i) {
438
+ var codeUnit = str2.charCodeAt(i);
439
439
  if (codeUnit >= 55296 && codeUnit <= 57343) ++i;
440
440
  len += 4;
441
441
  }
@@ -445,10 +445,10 @@ var require_re2 = __commonJS({
445
445
  assert(array.length >= 0, "writeArrayToMemory array must have a length (should be an array or typed array)");
446
446
  HEAP8.set(array, buffer2);
447
447
  }
448
- function writeAsciiToMemory(str, buffer2, dontAddNull) {
449
- for (var i = 0; i < str.length; ++i) {
450
- assert(str.charCodeAt(i) === str.charCodeAt(i) & 255);
451
- HEAP8[buffer2++ >> 0] = str.charCodeAt(i);
448
+ function writeAsciiToMemory(str2, buffer2, dontAddNull) {
449
+ for (var i = 0; i < str2.length; ++i) {
450
+ assert(str2.charCodeAt(i) === str2.charCodeAt(i) & 255);
451
+ HEAP8[buffer2++ >> 0] = str2.charCodeAt(i);
452
452
  }
453
453
  if (!dontAddNull) HEAP8[buffer2 >> 0] = 0;
454
454
  }
@@ -677,8 +677,8 @@ var require_re2 = __commonJS({
677
677
  };
678
678
  Module["FS_createDataFile"] = FS.createDataFile;
679
679
  Module["FS_createPreloadedFile"] = FS.createPreloadedFile;
680
- function hasPrefix(str, prefix) {
681
- return String.prototype.startsWith ? str.startsWith(prefix) : str.indexOf(prefix) === 0;
680
+ function hasPrefix(str2, prefix) {
681
+ return String.prototype.startsWith ? str2.startsWith(prefix) : str2.indexOf(prefix) === 0;
682
682
  }
683
683
  var dataURIPrefix = "data:application/octet-stream;base64,";
684
684
  function isDataURI(filename) {
@@ -770,9 +770,9 @@ var require_re2 = __commonJS({
770
770
  module2 = new WebAssembly.Module(binary);
771
771
  instance = new WebAssembly.Instance(module2, info);
772
772
  } catch (e) {
773
- var str = e.toString();
774
- err("failed to compile wasm module: " + str);
775
- if (str.indexOf("imported Memory") >= 0 || str.indexOf("memory import") >= 0) {
773
+ var str2 = e.toString();
774
+ err("failed to compile wasm module: " + str2);
775
+ if (str2.indexOf("imported Memory") >= 0 || str2.indexOf("memory import") >= 0) {
776
776
  err("Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time).");
777
777
  }
778
778
  throw e;
@@ -2132,7 +2132,7 @@ var require_re2 = __commonJS({
2132
2132
  name,
2133
2133
  "fromWireType": function(value) {
2134
2134
  var length = HEAPU32[value >> 2];
2135
- var str;
2135
+ var str2;
2136
2136
  if (stdStringIsUTF8) {
2137
2137
  var decodeStartPtr = value + 4;
2138
2138
  for (var i = 0; i <= length; ++i) {
@@ -2140,11 +2140,11 @@ var require_re2 = __commonJS({
2140
2140
  if (i == length || HEAPU8[currentBytePtr] == 0) {
2141
2141
  var maxRead = currentBytePtr - decodeStartPtr;
2142
2142
  var stringSegment = UTF8ToString(decodeStartPtr, maxRead);
2143
- if (str === void 0) {
2144
- str = stringSegment;
2143
+ if (str2 === void 0) {
2144
+ str2 = stringSegment;
2145
2145
  } else {
2146
- str += String.fromCharCode(0);
2147
- str += stringSegment;
2146
+ str2 += String.fromCharCode(0);
2147
+ str2 += stringSegment;
2148
2148
  }
2149
2149
  decodeStartPtr = currentBytePtr + 1;
2150
2150
  }
@@ -2154,10 +2154,10 @@ var require_re2 = __commonJS({
2154
2154
  for (var i = 0; i < length; ++i) {
2155
2155
  a[i] = String.fromCharCode(HEAPU8[value + 4 + i]);
2156
2156
  }
2157
- str = a.join("");
2157
+ str2 = a.join("");
2158
2158
  }
2159
2159
  _free(value);
2160
- return str;
2160
+ return str2;
2161
2161
  },
2162
2162
  "toWireType": function(destructors, value) {
2163
2163
  if (value instanceof ArrayBuffer) {
@@ -2235,24 +2235,24 @@ var require_re2 = __commonJS({
2235
2235
  "fromWireType": function(value) {
2236
2236
  var length = HEAPU32[value >> 2];
2237
2237
  var HEAP2 = getHeap();
2238
- var str;
2238
+ var str2;
2239
2239
  var decodeStartPtr = value + 4;
2240
2240
  for (var i = 0; i <= length; ++i) {
2241
2241
  var currentBytePtr = value + 4 + i * charSize;
2242
2242
  if (i == length || HEAP2[currentBytePtr >> shift] == 0) {
2243
2243
  var maxReadBytes = currentBytePtr - decodeStartPtr;
2244
2244
  var stringSegment = decodeString(decodeStartPtr, maxReadBytes);
2245
- if (str === void 0) {
2246
- str = stringSegment;
2245
+ if (str2 === void 0) {
2246
+ str2 = stringSegment;
2247
2247
  } else {
2248
- str += String.fromCharCode(0);
2249
- str += stringSegment;
2248
+ str2 += String.fromCharCode(0);
2249
+ str2 += stringSegment;
2250
2250
  }
2251
2251
  decodeStartPtr = currentBytePtr + charSize;
2252
2252
  }
2253
2253
  }
2254
2254
  _free(value);
2255
- return str;
2255
+ return str2;
2256
2256
  },
2257
2257
  "toWireType": function(destructors, value) {
2258
2258
  if (!(typeof value === "string")) {
@@ -2592,11 +2592,11 @@ var require_re2 = __commonJS({
2592
2592
  var WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
2593
2593
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
2594
2594
  function leadingSomething(value, digits, character) {
2595
- var str = typeof value === "number" ? value.toString() : value || "";
2596
- while (str.length < digits) {
2597
- str = character[0] + str;
2595
+ var str2 = typeof value === "number" ? value.toString() : value || "";
2596
+ while (str2.length < digits) {
2597
+ str2 = character[0] + str2;
2598
2598
  }
2599
- return str;
2599
+ return str2;
2600
2600
  }
2601
2601
  function leadingNulls(value, digits) {
2602
2602
  return leadingSomething(value, digits, "0");
@@ -4502,7 +4502,7 @@ function extractToolInputShape(input, client) {
4502
4502
 
4503
4503
  // src/hooks/runtime/resolve.ts
4504
4504
  import { execFileSync as execFileSync2 } from "node:child_process";
4505
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
4505
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
4506
4506
 
4507
4507
  // src/auth/auth-store.ts
4508
4508
  import { execFileSync } from "node:child_process";
@@ -4742,6 +4742,325 @@ async function doRefresh(mcpName, stored) {
4742
4742
  }
4743
4743
  }
4744
4744
 
4745
+ // src/git.ts
4746
+ import { spawnSync } from "node:child_process";
4747
+ function parseRemoteUrl(url) {
4748
+ const trimmed = url.trim();
4749
+ if (trimmed.length === 0) return null;
4750
+ let host;
4751
+ let rawPath;
4752
+ if (trimmed.includes("://")) {
4753
+ let parsed;
4754
+ try {
4755
+ parsed = new URL(trimmed);
4756
+ } catch {
4757
+ return null;
4758
+ }
4759
+ if (!parsed.hostname) return null;
4760
+ host = parsed.hostname;
4761
+ rawPath = parsed.pathname;
4762
+ } else {
4763
+ const scpMatch = /^(?:[^@\s]+@)?([^:\s/]+):(.+)$/.exec(trimmed);
4764
+ if (!scpMatch) return null;
4765
+ host = scpMatch[1].toLowerCase();
4766
+ rawPath = scpMatch[2];
4767
+ }
4768
+ const slug = rawPath.replace(/^\/+/, "").replace(/\/+$/, "").replace(/\.git$/i, "");
4769
+ if (slug.length === 0) return null;
4770
+ return { provider: detectProvider(host), host, slug };
4771
+ }
4772
+ function detectProvider(host) {
4773
+ const lower = host.toLowerCase();
4774
+ if (lower.includes("github")) return "github";
4775
+ if (lower.includes("gitlab")) return "gitlab";
4776
+ return null;
4777
+ }
4778
+ var GIT_REMOTE_TIMEOUT_MS = 3e3;
4779
+ function getOriginRemote(cwd, deps = {}) {
4780
+ const execImpl = deps.execImpl ?? defaultExecImpl;
4781
+ const result = execImpl("git", ["remote", "get-url", "origin"], {
4782
+ cwd,
4783
+ timeoutMs: GIT_REMOTE_TIMEOUT_MS
4784
+ });
4785
+ if (result.status !== 0) return null;
4786
+ const url = result.stdout.trim();
4787
+ return url.length > 0 ? url : null;
4788
+ }
4789
+ function defaultExecImpl(cmd, args, opts) {
4790
+ const result = spawnSync(cmd, args, {
4791
+ cwd: opts.cwd,
4792
+ encoding: "utf8",
4793
+ timeout: opts.timeoutMs,
4794
+ stdio: ["ignore", "pipe", "ignore"],
4795
+ windowsHide: true
4796
+ });
4797
+ return { status: result.status, stdout: result.stdout ?? "" };
4798
+ }
4799
+
4800
+ // src/api/projects.ts
4801
+ var RESOLVE_TIMEOUT_MS = 4e3;
4802
+ function unwrap(body) {
4803
+ if (!body || typeof body !== "object") return {};
4804
+ const root = body;
4805
+ const data = root.data;
4806
+ return data ?? root;
4807
+ }
4808
+ function str(v) {
4809
+ return typeof v === "string" ? v : v == null ? "" : String(v);
4810
+ }
4811
+ async function resolveProjectByRepository(apiBase, token, q, deps = {}) {
4812
+ const f = deps.fetchImpl ?? globalThis.fetch;
4813
+ const params = new URLSearchParams({ provider: q.provider, slug: q.slug });
4814
+ if (q.host) params.set("host", q.host);
4815
+ const url = `${apiBase}/user/projects/resolve?${params.toString()}`;
4816
+ let res;
4817
+ try {
4818
+ res = await f(url, {
4819
+ method: "GET",
4820
+ headers: { Authorization: `Bearer ${token}` },
4821
+ signal: AbortSignal.timeout(deps.timeoutMs ?? RESOLVE_TIMEOUT_MS)
4822
+ });
4823
+ } catch {
4824
+ return null;
4825
+ }
4826
+ if (!res.ok) return null;
4827
+ let body;
4828
+ try {
4829
+ body = await res.json();
4830
+ } catch {
4831
+ return null;
4832
+ }
4833
+ const data = unwrap(body);
4834
+ const rawMatches = Array.isArray(data.matches) ? data.matches : [];
4835
+ return rawMatches.map((raw) => {
4836
+ const m = raw ?? {};
4837
+ return {
4838
+ projectId: str(m.projectId),
4839
+ organizationId: str(m.organizationId),
4840
+ projectName: str(m.projectName),
4841
+ provider: str(m.provider),
4842
+ repository: str(m.repository),
4843
+ // Missing → enabled (default-on). Only an explicit `false` disables.
4844
+ vibedefendEnabled: m.vibedefendEnabled !== false
4845
+ };
4846
+ });
4847
+ }
4848
+
4849
+ // src/hooks/runtime/repo-link-cache.ts
4850
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
4851
+ import { dirname as dirname2 } from "node:path";
4852
+
4853
+ // src/utils.ts
4854
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
4855
+ import { dirname, join as join2 } from "node:path";
4856
+ import { homedir as homedir2, platform } from "node:os";
4857
+
4858
+ // node_modules/.pnpm/kleur@4.1.5/node_modules/kleur/index.mjs
4859
+ var FORCE_COLOR;
4860
+ var NODE_DISABLE_COLORS;
4861
+ var NO_COLOR;
4862
+ var TERM;
4863
+ var isTTY = true;
4864
+ if (typeof process !== "undefined") {
4865
+ ({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env || {});
4866
+ isTTY = process.stdout && process.stdout.isTTY;
4867
+ }
4868
+ var $ = {
4869
+ enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== "dumb" && (FORCE_COLOR != null && FORCE_COLOR !== "0" || isTTY),
4870
+ // modifiers
4871
+ reset: init(0, 0),
4872
+ bold: init(1, 22),
4873
+ dim: init(2, 22),
4874
+ italic: init(3, 23),
4875
+ underline: init(4, 24),
4876
+ inverse: init(7, 27),
4877
+ hidden: init(8, 28),
4878
+ strikethrough: init(9, 29),
4879
+ // colors
4880
+ black: init(30, 39),
4881
+ red: init(31, 39),
4882
+ green: init(32, 39),
4883
+ yellow: init(33, 39),
4884
+ blue: init(34, 39),
4885
+ magenta: init(35, 39),
4886
+ cyan: init(36, 39),
4887
+ white: init(37, 39),
4888
+ gray: init(90, 39),
4889
+ grey: init(90, 39),
4890
+ // background colors
4891
+ bgBlack: init(40, 49),
4892
+ bgRed: init(41, 49),
4893
+ bgGreen: init(42, 49),
4894
+ bgYellow: init(43, 49),
4895
+ bgBlue: init(44, 49),
4896
+ bgMagenta: init(45, 49),
4897
+ bgCyan: init(46, 49),
4898
+ bgWhite: init(47, 49)
4899
+ };
4900
+ function run(arr, str2) {
4901
+ let i = 0, tmp, beg = "", end = "";
4902
+ for (; i < arr.length; i++) {
4903
+ tmp = arr[i];
4904
+ beg += tmp.open;
4905
+ end += tmp.close;
4906
+ if (!!~str2.indexOf(tmp.close)) {
4907
+ str2 = str2.replace(tmp.rgx, tmp.close + tmp.open);
4908
+ }
4909
+ }
4910
+ return beg + str2 + end;
4911
+ }
4912
+ function chain(has, keys) {
4913
+ let ctx = { has, keys };
4914
+ ctx.reset = $.reset.bind(ctx);
4915
+ ctx.bold = $.bold.bind(ctx);
4916
+ ctx.dim = $.dim.bind(ctx);
4917
+ ctx.italic = $.italic.bind(ctx);
4918
+ ctx.underline = $.underline.bind(ctx);
4919
+ ctx.inverse = $.inverse.bind(ctx);
4920
+ ctx.hidden = $.hidden.bind(ctx);
4921
+ ctx.strikethrough = $.strikethrough.bind(ctx);
4922
+ ctx.black = $.black.bind(ctx);
4923
+ ctx.red = $.red.bind(ctx);
4924
+ ctx.green = $.green.bind(ctx);
4925
+ ctx.yellow = $.yellow.bind(ctx);
4926
+ ctx.blue = $.blue.bind(ctx);
4927
+ ctx.magenta = $.magenta.bind(ctx);
4928
+ ctx.cyan = $.cyan.bind(ctx);
4929
+ ctx.white = $.white.bind(ctx);
4930
+ ctx.gray = $.gray.bind(ctx);
4931
+ ctx.grey = $.grey.bind(ctx);
4932
+ ctx.bgBlack = $.bgBlack.bind(ctx);
4933
+ ctx.bgRed = $.bgRed.bind(ctx);
4934
+ ctx.bgGreen = $.bgGreen.bind(ctx);
4935
+ ctx.bgYellow = $.bgYellow.bind(ctx);
4936
+ ctx.bgBlue = $.bgBlue.bind(ctx);
4937
+ ctx.bgMagenta = $.bgMagenta.bind(ctx);
4938
+ ctx.bgCyan = $.bgCyan.bind(ctx);
4939
+ ctx.bgWhite = $.bgWhite.bind(ctx);
4940
+ return ctx;
4941
+ }
4942
+ function init(open, close) {
4943
+ let blk = {
4944
+ open: `\x1B[${open}m`,
4945
+ close: `\x1B[${close}m`,
4946
+ rgx: new RegExp(`\\x1b\\[${close}m`, "g")
4947
+ };
4948
+ return function(txt) {
4949
+ if (this !== void 0 && this.has !== void 0) {
4950
+ !!~this.has.indexOf(open) || (this.has.push(open), this.keys.push(blk));
4951
+ return txt === void 0 ? this : $.enabled ? run(this.keys, txt + "") : txt + "";
4952
+ }
4953
+ return txt === void 0 ? chain([open], [blk]) : $.enabled ? run([blk], txt + "") : txt + "";
4954
+ };
4955
+ }
4956
+
4957
+ // src/utils.ts
4958
+ function home(...parts) {
4959
+ return join2(homedir2(), ...parts);
4960
+ }
4961
+ function ensureDirFor(filePath) {
4962
+ const dir = dirname(filePath);
4963
+ if (!existsSync2(dir)) mkdirSync2(dir, { recursive: true });
4964
+ }
4965
+
4966
+ // src/hooks/runtime/repo-link-cache.ts
4967
+ var POSITIVE_TTL_MS = 24 * 60 * 60 * 1e3;
4968
+ var NEGATIVE_TTL_MS = 15 * 60 * 1e3;
4969
+ function repoLinkCachePath() {
4970
+ return home(".cybedefend", "repo-links.json");
4971
+ }
4972
+ function pathOf(deps) {
4973
+ return deps.cachePath ?? repoLinkCachePath();
4974
+ }
4975
+ function readRepoLinkCache(deps = {}) {
4976
+ const p = pathOf(deps);
4977
+ if (!existsSync3(p)) return {};
4978
+ try {
4979
+ const raw = readFileSync3(p, "utf8");
4980
+ if (!raw.trim()) return {};
4981
+ const parsed = JSON.parse(raw);
4982
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
4983
+ return parsed;
4984
+ }
4985
+ return {};
4986
+ } catch {
4987
+ return {};
4988
+ }
4989
+ }
4990
+ function getCachedRepoLink(key, deps = {}) {
4991
+ const now = deps.now ?? Date.now;
4992
+ const entry = readRepoLinkCache(deps)[key];
4993
+ if (!entry || typeof entry !== "object") return { kind: "miss" };
4994
+ const resolvedAt = entry.resolvedAt;
4995
+ if (typeof resolvedAt !== "number") return { kind: "miss" };
4996
+ const age = now() - resolvedAt;
4997
+ if (age < 0) return { kind: "miss" };
4998
+ if (entry.negative === true) {
4999
+ return age < NEGATIVE_TTL_MS ? { kind: "negative" } : { kind: "miss" };
5000
+ }
5001
+ const pos = entry;
5002
+ if (typeof pos.projectId !== "string" || pos.projectId.length === 0) {
5003
+ return { kind: "miss" };
5004
+ }
5005
+ if (age < POSITIVE_TTL_MS) {
5006
+ return {
5007
+ kind: "positive",
5008
+ projectId: pos.projectId,
5009
+ // Missing → treated as enabled; only explicit `false` disables.
5010
+ vibedefendEnabled: pos.vibedefendEnabled !== false
5011
+ };
5012
+ }
5013
+ return { kind: "miss" };
5014
+ }
5015
+ function writeCachedRepoLink(key, entry, deps = {}) {
5016
+ const now = deps.now ?? Date.now;
5017
+ try {
5018
+ const map = readRepoLinkCache(deps);
5019
+ map[key] = "negative" in entry ? { negative: true, resolvedAt: now() } : {
5020
+ projectId: entry.projectId,
5021
+ vibedefendEnabled: entry.vibedefendEnabled,
5022
+ resolvedAt: now()
5023
+ };
5024
+ const p = pathOf(deps);
5025
+ const dir = dirname2(p);
5026
+ if (!existsSync3(dir)) mkdirSync3(dir, { recursive: true });
5027
+ writeFileSync3(p, JSON.stringify(map, null, 2) + "\n");
5028
+ } catch {
5029
+ }
5030
+ }
5031
+
5032
+ // src/hooks/runtime/config.ts
5033
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
5034
+ import { homedir as homedir3 } from "node:os";
5035
+ import { join as join3 } from "node:path";
5036
+ function runtimeConfigPath() {
5037
+ return join3(homedir3(), ".cybedefend", "runtime-config.json");
5038
+ }
5039
+ function loadRuntimeConfig(path) {
5040
+ const p = path ?? runtimeConfigPath();
5041
+ if (!existsSync4(p)) return null;
5042
+ try {
5043
+ const raw = readFileSync4(p, "utf8");
5044
+ return JSON.parse(raw);
5045
+ } catch {
5046
+ return null;
5047
+ }
5048
+ }
5049
+ async function readStdinJson() {
5050
+ const chunks = [];
5051
+ for await (const chunk of process.stdin) {
5052
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
5053
+ }
5054
+ const raw = Buffer.concat(chunks).toString("utf8");
5055
+ if (!raw.trim()) return {};
5056
+ try {
5057
+ const parsed = JSON.parse(raw);
5058
+ return typeof parsed === "object" && parsed !== null ? parsed : {};
5059
+ } catch {
5060
+ return {};
5061
+ }
5062
+ }
5063
+
4745
5064
  // src/hooks/runtime/resolve.ts
4746
5065
  function resolveProjectId(cwd = process.cwd()) {
4747
5066
  const envProjectId = process.env.CYBEDEFEND_PROJECT_ID;
@@ -4749,9 +5068,9 @@ function resolveProjectId(cwd = process.cwd()) {
4749
5068
  return { projectId: envProjectId, apiBase: null };
4750
5069
  }
4751
5070
  const configPath = `${cwd}/.cybedefend/config.json`;
4752
- if (existsSync2(configPath)) {
5071
+ if (existsSync5(configPath)) {
4753
5072
  try {
4754
- const raw = readFileSync2(configPath, "utf8");
5073
+ const raw = readFileSync5(configPath, "utf8");
4755
5074
  const cfg = JSON.parse(raw);
4756
5075
  return {
4757
5076
  projectId: cfg.projectId ?? null,
@@ -4865,6 +5184,54 @@ async function resolveTokenWithRefresh(mcpName, deps = {}) {
4865
5184
  }
4866
5185
  return resolveTokenFn(mcpName);
4867
5186
  }
5187
+ var RESOLVE_API_TIMEOUT_MS = 4e3;
5188
+ async function resolveProjectIdWithApi(cwd = process.cwd(), deps = {}) {
5189
+ const resolveSync = deps.resolveSync ?? resolveProjectId;
5190
+ const base = resolveSync(cwd);
5191
+ if (base.projectId) return base;
5192
+ try {
5193
+ const getOrigin = deps.getOrigin ?? getOriginRemote;
5194
+ const originUrl = getOrigin(cwd);
5195
+ if (!originUrl) return base;
5196
+ const remote = parseRemoteUrl(originUrl);
5197
+ if (!remote || remote.provider === null) return base;
5198
+ const key = `${remote.provider}:${remote.host}:${remote.slug}`;
5199
+ const cached = getCachedRepoLink(key, deps.cacheDeps);
5200
+ if (cached.kind === "positive") {
5201
+ return { projectId: cached.projectId, apiBase: base.apiBase };
5202
+ }
5203
+ if (cached.kind === "negative") {
5204
+ return base;
5205
+ }
5206
+ const config = (deps.loadConfig ?? loadRuntimeConfig)();
5207
+ if (!config) return base;
5208
+ const apiBase = base.apiBase ?? config.region.apiBase;
5209
+ const resolveTokenFn = deps.resolveTokenFn ?? resolveTokenWithRefresh;
5210
+ const token = await resolveTokenFn(config.region.mcpName);
5211
+ if (!token) return base;
5212
+ const resolveByRepo = deps.resolveByRepo ?? resolveProjectByRepository;
5213
+ const matches = await resolveByRepo(
5214
+ apiBase,
5215
+ token,
5216
+ { provider: remote.provider, slug: remote.slug, host: remote.host },
5217
+ { timeoutMs: deps.timeoutMs ?? RESOLVE_API_TIMEOUT_MS }
5218
+ );
5219
+ if (matches === null) return base;
5220
+ if (matches.length === 1 && matches[0].vibedefendEnabled !== false) {
5221
+ const m = matches[0];
5222
+ writeCachedRepoLink(
5223
+ key,
5224
+ { projectId: m.projectId, vibedefendEnabled: m.vibedefendEnabled },
5225
+ deps.cacheDeps
5226
+ );
5227
+ return { projectId: m.projectId, apiBase: base.apiBase };
5228
+ }
5229
+ writeCachedRepoLink(key, { negative: true }, deps.cacheDeps);
5230
+ return base;
5231
+ } catch {
5232
+ return base;
5233
+ }
5234
+ }
4868
5235
 
4869
5236
  // src/hooks/runtime/api.ts
4870
5237
  var DEFAULT_TIMEOUT_MS = 1e4;
@@ -5006,38 +5373,6 @@ function emitStop(body, client, reason) {
5006
5373
  emit(body, client);
5007
5374
  }
5008
5375
 
5009
- // src/hooks/runtime/config.ts
5010
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
5011
- import { homedir as homedir2 } from "node:os";
5012
- import { join as join2 } from "node:path";
5013
- function runtimeConfigPath() {
5014
- return join2(homedir2(), ".cybedefend", "runtime-config.json");
5015
- }
5016
- function loadRuntimeConfig(path) {
5017
- const p = path ?? runtimeConfigPath();
5018
- if (!existsSync3(p)) return null;
5019
- try {
5020
- const raw = readFileSync3(p, "utf8");
5021
- return JSON.parse(raw);
5022
- } catch {
5023
- return null;
5024
- }
5025
- }
5026
- async function readStdinJson() {
5027
- const chunks = [];
5028
- for await (const chunk of process.stdin) {
5029
- chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
5030
- }
5031
- const raw = Buffer.concat(chunks).toString("utf8");
5032
- if (!raw.trim()) return {};
5033
- try {
5034
- const parsed = JSON.parse(raw);
5035
- return typeof parsed === "object" && parsed !== null ? parsed : {};
5036
- } catch {
5037
- return {};
5038
- }
5039
- }
5040
-
5041
5376
  // src/hooks/runtime/fetch-rules.ts
5042
5377
  var INTERESTED_TOOLS = /* @__PURE__ */ new Set([
5043
5378
  "Edit",
@@ -5048,7 +5383,7 @@ var INTERESTED_TOOLS = /* @__PURE__ */ new Set([
5048
5383
  async function fetchRulesHook(deps = {}) {
5049
5384
  const readStdin = deps.readStdin ?? readStdinJson;
5050
5385
  const loadConfig = deps.loadConfig ?? loadRuntimeConfig;
5051
- const resolveProject = deps.resolveProject ?? resolveProjectId;
5386
+ const resolveProject = deps.resolveProject ?? resolveProjectIdWithApi;
5052
5387
  const resolveTok = deps.resolveTokenFn ?? resolveToken;
5053
5388
  const fetchRules = deps.fetchRulesFn ?? fetchBusinessRules;
5054
5389
  const fetchSecRules = deps.fetchSecurityRulesFn ?? fetchSecurityRules;
@@ -5059,7 +5394,7 @@ async function fetchRulesHook(deps = {}) {
5059
5394
  if (!event.filePath) return;
5060
5395
  const config = loadConfig();
5061
5396
  if (!config) return;
5062
- const { projectId, apiBase: configApiBase } = resolveProject();
5397
+ const { projectId, apiBase: configApiBase } = await resolveProject();
5063
5398
  if (!projectId) return;
5064
5399
  const apiBase = process.env.CYBEDEFEND_API_BASE ?? configApiBase ?? config.region.apiBase;
5065
5400
  const token = resolveTok(config.region.mcpName);
@@ -5152,119 +5487,10 @@ function composeSecurityBody(markdown, total, filePath) {
5152
5487
 
5153
5488
  // src/hooks/runtime/self-update-check.ts
5154
5489
  import { spawn } from "node:child_process";
5155
- import { existsSync as existsSync6, readFileSync as readFileSync5, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
5156
- import { homedir as homedir3 } from "node:os";
5490
+ import { existsSync as existsSync7, readFileSync as readFileSync6, rmSync, writeFileSync as writeFileSync4 } from "node:fs";
5491
+ import { homedir as homedir4 } from "node:os";
5157
5492
  import { join as join4 } from "node:path";
5158
5493
 
5159
- // src/utils.ts
5160
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "node:fs";
5161
- import { dirname, join as join3 } from "node:path";
5162
-
5163
- // node_modules/.pnpm/kleur@4.1.5/node_modules/kleur/index.mjs
5164
- var FORCE_COLOR;
5165
- var NODE_DISABLE_COLORS;
5166
- var NO_COLOR;
5167
- var TERM;
5168
- var isTTY = true;
5169
- if (typeof process !== "undefined") {
5170
- ({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env || {});
5171
- isTTY = process.stdout && process.stdout.isTTY;
5172
- }
5173
- var $ = {
5174
- enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== "dumb" && (FORCE_COLOR != null && FORCE_COLOR !== "0" || isTTY),
5175
- // modifiers
5176
- reset: init(0, 0),
5177
- bold: init(1, 22),
5178
- dim: init(2, 22),
5179
- italic: init(3, 23),
5180
- underline: init(4, 24),
5181
- inverse: init(7, 27),
5182
- hidden: init(8, 28),
5183
- strikethrough: init(9, 29),
5184
- // colors
5185
- black: init(30, 39),
5186
- red: init(31, 39),
5187
- green: init(32, 39),
5188
- yellow: init(33, 39),
5189
- blue: init(34, 39),
5190
- magenta: init(35, 39),
5191
- cyan: init(36, 39),
5192
- white: init(37, 39),
5193
- gray: init(90, 39),
5194
- grey: init(90, 39),
5195
- // background colors
5196
- bgBlack: init(40, 49),
5197
- bgRed: init(41, 49),
5198
- bgGreen: init(42, 49),
5199
- bgYellow: init(43, 49),
5200
- bgBlue: init(44, 49),
5201
- bgMagenta: init(45, 49),
5202
- bgCyan: init(46, 49),
5203
- bgWhite: init(47, 49)
5204
- };
5205
- function run(arr, str) {
5206
- let i = 0, tmp, beg = "", end = "";
5207
- for (; i < arr.length; i++) {
5208
- tmp = arr[i];
5209
- beg += tmp.open;
5210
- end += tmp.close;
5211
- if (!!~str.indexOf(tmp.close)) {
5212
- str = str.replace(tmp.rgx, tmp.close + tmp.open);
5213
- }
5214
- }
5215
- return beg + str + end;
5216
- }
5217
- function chain(has, keys) {
5218
- let ctx = { has, keys };
5219
- ctx.reset = $.reset.bind(ctx);
5220
- ctx.bold = $.bold.bind(ctx);
5221
- ctx.dim = $.dim.bind(ctx);
5222
- ctx.italic = $.italic.bind(ctx);
5223
- ctx.underline = $.underline.bind(ctx);
5224
- ctx.inverse = $.inverse.bind(ctx);
5225
- ctx.hidden = $.hidden.bind(ctx);
5226
- ctx.strikethrough = $.strikethrough.bind(ctx);
5227
- ctx.black = $.black.bind(ctx);
5228
- ctx.red = $.red.bind(ctx);
5229
- ctx.green = $.green.bind(ctx);
5230
- ctx.yellow = $.yellow.bind(ctx);
5231
- ctx.blue = $.blue.bind(ctx);
5232
- ctx.magenta = $.magenta.bind(ctx);
5233
- ctx.cyan = $.cyan.bind(ctx);
5234
- ctx.white = $.white.bind(ctx);
5235
- ctx.gray = $.gray.bind(ctx);
5236
- ctx.grey = $.grey.bind(ctx);
5237
- ctx.bgBlack = $.bgBlack.bind(ctx);
5238
- ctx.bgRed = $.bgRed.bind(ctx);
5239
- ctx.bgGreen = $.bgGreen.bind(ctx);
5240
- ctx.bgYellow = $.bgYellow.bind(ctx);
5241
- ctx.bgBlue = $.bgBlue.bind(ctx);
5242
- ctx.bgMagenta = $.bgMagenta.bind(ctx);
5243
- ctx.bgCyan = $.bgCyan.bind(ctx);
5244
- ctx.bgWhite = $.bgWhite.bind(ctx);
5245
- return ctx;
5246
- }
5247
- function init(open, close) {
5248
- let blk = {
5249
- open: `\x1B[${open}m`,
5250
- close: `\x1B[${close}m`,
5251
- rgx: new RegExp(`\\x1b\\[${close}m`, "g")
5252
- };
5253
- return function(txt) {
5254
- if (this !== void 0 && this.has !== void 0) {
5255
- !!~this.has.indexOf(open) || (this.has.push(open), this.keys.push(blk));
5256
- return txt === void 0 ? this : $.enabled ? run(this.keys, txt + "") : txt + "";
5257
- }
5258
- return txt === void 0 ? chain([open], [blk]) : $.enabled ? run([blk], txt + "") : txt + "";
5259
- };
5260
- }
5261
-
5262
- // src/utils.ts
5263
- function ensureDirFor(filePath) {
5264
- const dir = dirname(filePath);
5265
- if (!existsSync4(dir)) mkdirSync2(dir, { recursive: true });
5266
- }
5267
-
5268
5494
  // src/hooks/runtime/semver.ts
5269
5495
  function parseVersion(input) {
5270
5496
  const cleaned = input.trim().replace(/^v/i, "");
@@ -5291,7 +5517,7 @@ function isNewer(latest, current) {
5291
5517
 
5292
5518
  // src/self-update.ts
5293
5519
  import { fileURLToPath } from "node:url";
5294
- import { existsSync as existsSync5, realpathSync } from "node:fs";
5520
+ import { existsSync as existsSync6, realpathSync } from "node:fs";
5295
5521
  var GLOBAL_MODES = /* @__PURE__ */ new Set([
5296
5522
  "npm-global",
5297
5523
  "pnpm-global",
@@ -5318,7 +5544,7 @@ function detectInstallMode(scriptPath) {
5318
5544
  }
5319
5545
  function resolveScriptPath() {
5320
5546
  const fromArgv = process.argv[1];
5321
- if (fromArgv && existsSync5(fromArgv)) {
5547
+ if (fromArgv && existsSync6(fromArgv)) {
5322
5548
  try {
5323
5549
  return realpathSync(fromArgv);
5324
5550
  } catch {
@@ -5335,7 +5561,7 @@ var THROTTLE_MS = 24 * 60 * 60 * 1e3;
5335
5561
  var FETCH_TIMEOUT_MS = 3e3;
5336
5562
  async function selfUpdateCheck(deps) {
5337
5563
  const now = deps.now ?? (() => Date.now());
5338
- const dir = deps.cybeDir ?? join4(process.env.CYBEDEFEND_HOME ?? homedir3(), ".cybedefend");
5564
+ const dir = deps.cybeDir ?? join4(process.env.CYBEDEFEND_HOME ?? homedir4(), ".cybedefend");
5339
5565
  const throttlePath = join4(dir, "update-check.json");
5340
5566
  const logPath = join4(dir, "last-update.log");
5341
5567
  const installMode = deps.installMode ?? (deps.runnerSource ? detectInstallMode(deps.runnerSource) : detectInstallMode(resolveScriptPath()));
@@ -5370,8 +5596,8 @@ function applyOrNotify(deps, installMode, latest, logPath) {
5370
5596
  }
5371
5597
  function readThrottle(path) {
5372
5598
  try {
5373
- if (!existsSync6(path)) return null;
5374
- const data = JSON.parse(readFileSync5(path, "utf8"));
5599
+ if (!existsSync7(path)) return null;
5600
+ const data = JSON.parse(readFileSync6(path, "utf8"));
5375
5601
  if (typeof data.lastCheckedAt !== "number") return null;
5376
5602
  return { lastCheckedAt: data.lastCheckedAt };
5377
5603
  } catch {
@@ -5381,16 +5607,16 @@ function readThrottle(path) {
5381
5607
  function writeThrottle(path, throttle) {
5382
5608
  try {
5383
5609
  ensureDirFor(path);
5384
- writeFileSync3(path, JSON.stringify(throttle) + "\n");
5610
+ writeFileSync4(path, JSON.stringify(throttle) + "\n");
5385
5611
  } catch {
5386
5612
  }
5387
5613
  }
5388
5614
  function takeUpdateLogNotice(logPath) {
5389
5615
  try {
5390
- if (!existsSync6(logPath)) return null;
5616
+ if (!existsSync7(logPath)) return null;
5391
5617
  let parsed = {};
5392
5618
  try {
5393
- parsed = JSON.parse(readFileSync5(logPath, "utf8"));
5619
+ parsed = JSON.parse(readFileSync6(logPath, "utf8"));
5394
5620
  } catch {
5395
5621
  parsed = {};
5396
5622
  }
@@ -5464,18 +5690,18 @@ function pmCommand(mode, spec) {
5464
5690
  }
5465
5691
 
5466
5692
  // src/version.ts
5467
- import { readFileSync as readFileSync6 } from "node:fs";
5693
+ import { readFileSync as readFileSync7 } from "node:fs";
5468
5694
  import { fileURLToPath as fileURLToPath2 } from "node:url";
5469
- import { dirname as dirname2, join as join5 } from "node:path";
5695
+ import { dirname as dirname3, join as join5 } from "node:path";
5470
5696
  var PKG_NAME = "@cybedefend/vibedefend";
5471
5697
  function defaultPkgPath() {
5472
- return join5(dirname2(fileURLToPath2(import.meta.url)), "..", "package.json");
5698
+ return join5(dirname3(fileURLToPath2(import.meta.url)), "..", "package.json");
5473
5699
  }
5474
5700
  function readPackageMeta(opts = {}) {
5475
5701
  if (typeof opts.bakedVersion === "string" && opts.bakedVersion.length > 0) {
5476
5702
  return { name: PKG_NAME, version: opts.bakedVersion };
5477
5703
  }
5478
- const readFile = opts.readFile ?? ((p) => readFileSync6(p, "utf8"));
5704
+ const readFile = opts.readFile ?? ((p) => readFileSync7(p, "utf8"));
5479
5705
  const pkgPath = opts.pkgPath ?? defaultPkgPath();
5480
5706
  try {
5481
5707
  return JSON.parse(readFile(pkgPath));
@@ -5484,14 +5710,14 @@ function readPackageMeta(opts = {}) {
5484
5710
  }
5485
5711
  }
5486
5712
  var pkg = readPackageMeta({
5487
- bakedVersion: true ? "1.3.2" : void 0
5713
+ bakedVersion: true ? "1.4.1" : void 0
5488
5714
  });
5489
5715
 
5490
5716
  // src/hooks/runtime/session-start.ts
5491
5717
  async function sessionStartHook(deps = {}) {
5492
5718
  const readStdin = deps.readStdin ?? readStdinJson;
5493
5719
  const loadConfig = deps.loadConfig ?? loadRuntimeConfig;
5494
- const resolveProject = deps.resolveProject ?? resolveProjectId;
5720
+ const resolveProject = deps.resolveProject ?? resolveProjectIdWithApi;
5495
5721
  const resolveTok = deps.resolveTokenFn ?? resolveToken;
5496
5722
  const fetchProposals = deps.fetchProposalsFn ?? fetchProposalsCount;
5497
5723
  const selfUpdateCheckFn = deps.selfUpdateCheckFn ?? selfUpdateCheck;
@@ -5500,7 +5726,7 @@ async function sessionStartHook(deps = {}) {
5500
5726
  const event = sniff(stdin);
5501
5727
  const config = loadConfig();
5502
5728
  if (!config) return;
5503
- const { projectId, apiBase: configApiBase } = resolveProject();
5729
+ const { projectId, apiBase: configApiBase } = await resolveProject();
5504
5730
  if (!projectId) return;
5505
5731
  const apiBase = process.env.CYBEDEFEND_API_BASE ?? configApiBase ?? config.region.apiBase;
5506
5732
  if (process.env.CYBEDEFEND_DRY_RUN === "1") {
@@ -5586,7 +5812,7 @@ async function sessionStartHook(deps = {}) {
5586
5812
  }
5587
5813
 
5588
5814
  // src/hooks/runtime/session-review.ts
5589
- import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
5815
+ import { existsSync as existsSync8, readFileSync as readFileSync8 } from "node:fs";
5590
5816
  var COUNTED_TOOLS = /* @__PURE__ */ new Set([
5591
5817
  "Edit",
5592
5818
  "Write",
@@ -5664,9 +5890,9 @@ function loadTranscript(stdin, readFile) {
5664
5890
  return out;
5665
5891
  }
5666
5892
  function defaultReadTranscript(path) {
5667
- if (!existsSync7(path)) return null;
5893
+ if (!existsSync8(path)) return null;
5668
5894
  try {
5669
- return readFileSync7(path, "utf8");
5895
+ return readFileSync8(path, "utf8");
5670
5896
  } catch {
5671
5897
  return null;
5672
5898
  }
@@ -5924,19 +6150,19 @@ async function preCompactHook(deps = {}) {
5924
6150
  }
5925
6151
 
5926
6152
  // src/hooks/runtime/user-prompt-submit.ts
5927
- import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "node:fs";
5928
- import { homedir as homedir4 } from "node:os";
6153
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "node:fs";
6154
+ import { homedir as homedir5 } from "node:os";
5929
6155
  import { join as join6 } from "node:path";
5930
6156
  var SESSIONS_CAP = 100;
5931
6157
  function defaultSessionsFile() {
5932
- const dir = process.env.CYBEDEFEND_BASELINE_DIR ?? join6(homedir4(), ".cybedefend");
6158
+ const dir = process.env.CYBEDEFEND_BASELINE_DIR ?? join6(homedir5(), ".cybedefend");
5933
6159
  return join6(dir, "user-prompt-seen-sessions.json");
5934
6160
  }
5935
6161
  function defaultSessionTracker(file = defaultSessionsFile()) {
5936
6162
  function load() {
5937
- if (!existsSync8(file)) return [];
6163
+ if (!existsSync9(file)) return [];
5938
6164
  try {
5939
- const raw = readFileSync8(file, "utf8");
6165
+ const raw = readFileSync9(file, "utf8");
5940
6166
  const data = JSON.parse(raw);
5941
6167
  if (!Array.isArray(data.sessions)) return [];
5942
6168
  return data.sessions.filter((s) => typeof s === "string");
@@ -5953,8 +6179,8 @@ function defaultSessionTracker(file = defaultSessionsFile()) {
5953
6179
  if (existing.includes(sessionId)) return;
5954
6180
  const next = [...existing, sessionId].slice(-SESSIONS_CAP);
5955
6181
  try {
5956
- mkdirSync3(join6(file, ".."), { recursive: true });
5957
- writeFileSync4(file, JSON.stringify({ sessions: next }), "utf8");
6182
+ mkdirSync4(join6(file, ".."), { recursive: true });
6183
+ writeFileSync5(file, JSON.stringify({ sessions: next }), "utf8");
5958
6184
  } catch {
5959
6185
  }
5960
6186
  }
@@ -5963,7 +6189,7 @@ function defaultSessionTracker(file = defaultSessionsFile()) {
5963
6189
  async function userPromptSubmitHook(deps = {}) {
5964
6190
  const readStdin = deps.readStdin ?? readStdinJson;
5965
6191
  const loadConfig = deps.loadConfig ?? loadRuntimeConfig;
5966
- const resolveProject = deps.resolveProject ?? resolveProjectId;
6192
+ const resolveProject = deps.resolveProject ?? resolveProjectIdWithApi;
5967
6193
  const resolveTok = deps.resolveTokenFn ?? resolveToken;
5968
6194
  const fetchProposals = deps.fetchProposalsFn ?? fetchProposalsCount;
5969
6195
  const emitFn = deps.emitFn ?? emit;
@@ -5976,7 +6202,7 @@ async function userPromptSubmitHook(deps = {}) {
5976
6202
  }
5977
6203
  const config = loadConfig();
5978
6204
  if (!config) return;
5979
- const { projectId, apiBase: configApiBase } = resolveProject();
6205
+ const { projectId, apiBase: configApiBase } = await resolveProject();
5980
6206
  if (!projectId) return;
5981
6207
  const apiBase = process.env.CYBEDEFEND_API_BASE ?? configApiBase ?? config.region.apiBase;
5982
6208
  const token = resolveTok(config.region.mcpName);
@@ -6873,12 +7099,12 @@ function nearMiss(req, rule) {
6873
7099
  }
6874
7100
 
6875
7101
  // src/hooks/runtime/guard-rules-cache.ts
6876
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync9, mkdirSync as mkdirSync4 } from "node:fs";
6877
- import { dirname as dirname3 } from "node:path";
6878
- import { homedir as homedir5 } from "node:os";
7102
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, existsSync as existsSync10, mkdirSync as mkdirSync5 } from "node:fs";
7103
+ import { dirname as dirname4 } from "node:path";
7104
+ import { homedir as homedir6 } from "node:os";
6879
7105
  import { join as join7 } from "node:path";
6880
7106
  var DEFAULT_CACHE_FILE = join7(
6881
- homedir5(),
7107
+ homedir6(),
6882
7108
  ".cybedefend",
6883
7109
  "guards-cache.json"
6884
7110
  );
@@ -6976,9 +7202,9 @@ function makeGuardRulesCache(opts) {
6976
7202
  }
6977
7203
  }
6978
7204
  function readCache(projectId) {
6979
- if (!existsSync9(cacheFile)) return null;
7205
+ if (!existsSync10(cacheFile)) return null;
6980
7206
  try {
6981
- const raw = readFileSync9(cacheFile, "utf8");
7207
+ const raw = readFileSync10(cacheFile, "utf8");
6982
7208
  const data = JSON.parse(raw);
6983
7209
  if (data.projectId !== projectId) return null;
6984
7210
  return data;
@@ -6989,16 +7215,16 @@ function makeGuardRulesCache(opts) {
6989
7215
  function writeCache(entry) {
6990
7216
  try {
6991
7217
  ensureDirFor2(cacheFile);
6992
- writeFileSync5(cacheFile, JSON.stringify(entry), "utf8");
7218
+ writeFileSync6(cacheFile, JSON.stringify(entry), "utf8");
6993
7219
  } catch {
6994
7220
  }
6995
7221
  }
6996
7222
  return { refreshIfStale };
6997
7223
  }
6998
7224
  function ensureDirFor2(filePath) {
6999
- const dir = dirname3(filePath);
7000
- if (!existsSync9(dir)) {
7001
- mkdirSync4(dir, { recursive: true });
7225
+ const dir = dirname4(filePath);
7226
+ if (!existsSync10(dir)) {
7227
+ mkdirSync5(dir, { recursive: true });
7002
7228
  }
7003
7229
  }
7004
7230
  var DEFAULT_TIMEOUT_MS2 = 8e3;
@@ -7081,12 +7307,49 @@ async function callJudge(input, opts = {}) {
7081
7307
  }
7082
7308
  }
7083
7309
 
7310
+ // src/hooks/runtime/judge-injection.ts
7311
+ var SEP_RUN = /[.\-_/\\+,;\s]+/g;
7312
+ var SIGNALS = [
7313
+ // A1a — verdict assignment with '=': decision=allow, answer=allow
7314
+ /\b(decision|verdict|veredict|answer|result|output|response)\s*=\s*["']?(allow|block|approve|permit)\b/,
7315
+ // A1b — verdict with a space separator (covers decision.allow / -allow / _allow)
7316
+ /\b(decision|verdict)\s+["']?(allow|block)\b/,
7317
+ // A2 — literal JSON verdict shape: {"decision":"allow"}
7318
+ /["'](decision|verdict)["']\s*:\s*["'](allow|block)["']/,
7319
+ // A3 — imperative verdict directive: reply allow, respond with allow
7320
+ /\b(reply|respond|answer|say)\s+(with\s+|the\s+)?["']?(allow|block)\b/,
7321
+ // A4 — permission imperative: you may allow this
7322
+ /\byou\s+(must|should|may|can|are\s+to|need\s+to)\s+(allow|permit|approve|unblock)\b/,
7323
+ // A5 — mark-as-safe / do-not-block
7324
+ /\bmark(ed)?\s+(this|it)\s+(as\s+)?(safe|allowed|authori[sz]ed|approved)\b/,
7325
+ /\bdo\s*not\s+block\b/,
7326
+ /\bdon'?t\s+block\b/,
7327
+ // A6 — "let it/this pass|through|proceed" (the reported "laisse passer")
7328
+ /\blet\s+(it|this|the)\s+(command\s+|action\s+|tool\s+)?(pass|through|proceed)\b/,
7329
+ // B — rule/guard nullification: strong verbs + the control-object noun
7330
+ /\b(ignore|disregard|override|bypass|circumvent|nullify)\s+(the\s+|this\s+|all\s+|any\s+|previous\s+|above\s+|prior\s+)*(rule|rules|instruction|instructions|deny|denial|denies|policy|policies|check|checks|guard|guards|guardrail|guardrails|restriction|restrictions)\b/,
7331
+ // C — role/meta break-in
7332
+ /\b(you\s+are|as)\s+(the\s+|a\s+)?(security\s+)?(judge|reviewer|approver|arbiter)\b/,
7333
+ /\bnew\s+instructions?\b/,
7334
+ /<\s*\/?\s*(system|assistant|user|developer|tool)\b/
7335
+ ];
7336
+ function normalize(text) {
7337
+ const folded = text.normalize("NFKC").toLowerCase();
7338
+ return folded.replace(SEP_RUN, " ").trim();
7339
+ }
7340
+ function detectPromptInjection(text) {
7341
+ if (!text) return false;
7342
+ const normalized = normalize(String(text));
7343
+ if (!normalized) return false;
7344
+ return SIGNALS.some((sig) => sig.test(normalized));
7345
+ }
7346
+
7084
7347
  // src/hooks/runtime/judge-cache.ts
7085
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, existsSync as existsSync10, mkdirSync as mkdirSync5 } from "node:fs";
7086
- import { dirname as dirname4, join as join8 } from "node:path";
7087
- import { homedir as homedir6 } from "node:os";
7348
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, existsSync as existsSync11, mkdirSync as mkdirSync6 } from "node:fs";
7349
+ import { dirname as dirname5, join as join8 } from "node:path";
7350
+ import { homedir as homedir7 } from "node:os";
7088
7351
  var DEFAULT_JUDGE_CACHE_FILE = join8(
7089
- homedir6(),
7352
+ homedir7(),
7090
7353
  ".cybedefend",
7091
7354
  "guards-judge-cache.json"
7092
7355
  );
@@ -7096,9 +7359,9 @@ function makeJudgeCache(opts = {}) {
7096
7359
  const ttlMs = opts.ttlMs ?? DEFAULT_JUDGE_TTL_MS;
7097
7360
  const now = opts.now ?? (() => Date.now());
7098
7361
  function readAll() {
7099
- if (!existsSync10(cacheFile)) return {};
7362
+ if (!existsSync11(cacheFile)) return {};
7100
7363
  try {
7101
- return JSON.parse(readFileSync10(cacheFile, "utf8"));
7364
+ return JSON.parse(readFileSync11(cacheFile, "utf8"));
7102
7365
  } catch {
7103
7366
  return {};
7104
7367
  }
@@ -7118,36 +7381,36 @@ function makeJudgeCache(opts = {}) {
7118
7381
  }
7119
7382
  all[key] = { res, at: t };
7120
7383
  ensureDirFor3(cacheFile);
7121
- writeFileSync6(cacheFile, JSON.stringify(all), "utf8");
7384
+ writeFileSync7(cacheFile, JSON.stringify(all), "utf8");
7122
7385
  } catch {
7123
7386
  }
7124
7387
  }
7125
7388
  return { get, set };
7126
7389
  }
7127
7390
  function ensureDirFor3(filePath) {
7128
- const dir = dirname4(filePath);
7129
- if (!existsSync10(dir)) {
7130
- mkdirSync5(dir, { recursive: true });
7391
+ const dir = dirname5(filePath);
7392
+ if (!existsSync11(dir)) {
7393
+ mkdirSync6(dir, { recursive: true });
7131
7394
  }
7132
7395
  }
7133
7396
 
7134
7397
  // src/hooks/runtime/guard-check.ts
7135
- import { homedir as homedir8 } from "node:os";
7398
+ import { homedir as homedir9 } from "node:os";
7136
7399
  import { join as join10 } from "node:path";
7137
7400
 
7138
7401
  // src/hooks/runtime/guard-violations-buffer.ts
7139
7402
  import {
7140
7403
  appendFileSync,
7141
- existsSync as existsSync11,
7142
- readFileSync as readFileSync11,
7143
- writeFileSync as writeFileSync7,
7144
- mkdirSync as mkdirSync6
7404
+ existsSync as existsSync12,
7405
+ readFileSync as readFileSync12,
7406
+ writeFileSync as writeFileSync8,
7407
+ mkdirSync as mkdirSync7
7145
7408
  } from "node:fs";
7146
- import { dirname as dirname5 } from "node:path";
7147
- import { homedir as homedir7 } from "node:os";
7409
+ import { dirname as dirname6 } from "node:path";
7410
+ import { homedir as homedir8 } from "node:os";
7148
7411
  import { join as join9 } from "node:path";
7149
7412
  var DEFAULT_BUFFER_FILE = join9(
7150
- homedir7(),
7413
+ homedir8(),
7151
7414
  ".cybedefend",
7152
7415
  "guards-violations-buffer.jsonl"
7153
7416
  );
@@ -7166,10 +7429,10 @@ function makeViolationsBuffer(opts = {}) {
7166
7429
  }
7167
7430
  }
7168
7431
  async function flushViolations2(ctx, postFn) {
7169
- if (!existsSync11(bufferFile)) return;
7432
+ if (!existsSync12(bufferFile)) return;
7170
7433
  let content;
7171
7434
  try {
7172
- content = readFileSync11(bufferFile, "utf8").trim();
7435
+ content = readFileSync12(bufferFile, "utf8").trim();
7173
7436
  } catch {
7174
7437
  return;
7175
7438
  }
@@ -7188,7 +7451,7 @@ function makeViolationsBuffer(opts = {}) {
7188
7451
  }
7189
7452
  if (records.length === 0) {
7190
7453
  try {
7191
- writeFileSync7(bufferFile, "", "utf8");
7454
+ writeFileSync8(bufferFile, "", "utf8");
7192
7455
  } catch {
7193
7456
  }
7194
7457
  return;
@@ -7218,10 +7481,10 @@ function makeViolationsBuffer(opts = {}) {
7218
7481
  }
7219
7482
  try {
7220
7483
  if (failed.length === 0) {
7221
- writeFileSync7(bufferFile, "", "utf8");
7484
+ writeFileSync8(bufferFile, "", "utf8");
7222
7485
  } else {
7223
7486
  const serialised = failed.map((r) => JSON.stringify(r)).join("\n") + "\n";
7224
- writeFileSync7(bufferFile, serialised, "utf8");
7487
+ writeFileSync8(bufferFile, serialised, "utf8");
7225
7488
  }
7226
7489
  } catch {
7227
7490
  }
@@ -7229,9 +7492,9 @@ function makeViolationsBuffer(opts = {}) {
7229
7492
  return { bufferViolation: bufferViolation2, flushViolations: flushViolations2 };
7230
7493
  }
7231
7494
  function ensureDirFor4(filePath) {
7232
- const dir = dirname5(filePath);
7233
- if (!existsSync11(dir)) {
7234
- mkdirSync6(dir, { recursive: true });
7495
+ const dir = dirname6(filePath);
7496
+ if (!existsSync12(dir)) {
7497
+ mkdirSync7(dir, { recursive: true });
7235
7498
  }
7236
7499
  }
7237
7500
  var _defaultBuffer = makeViolationsBuffer();
@@ -7241,7 +7504,7 @@ var flushViolations = _defaultBuffer.flushViolations.bind(_defaultBuffer);
7241
7504
  // src/hooks/runtime/guard-check.ts
7242
7505
  function normalizeToolName(tool) {
7243
7506
  if (!tool) return "";
7244
- const t = tool.trim();
7507
+ const t = (tool.split(/[\r\n]/, 1)[0] ?? "").trim();
7245
7508
  if (/^(read|read_file|cat)$/i.test(t)) return "Read";
7246
7509
  if (/^(write|create_file|new_file)$/i.test(t)) return "Write";
7247
7510
  if (/^(edit|apply_patch|str_replace_editor)$/i.test(t)) return "Edit";
@@ -7257,10 +7520,10 @@ function appendDebugLog(entry) {
7257
7520
  try {
7258
7521
  const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? "";
7259
7522
  if (!homeDir) return;
7260
- const { mkdirSync: mkdirSync7, appendFileSync: appendFileSync2 } = __require("node:fs");
7523
+ const { mkdirSync: mkdirSync8, appendFileSync: appendFileSync2 } = __require("node:fs");
7261
7524
  const { join: join11 } = __require("node:path");
7262
7525
  const dir = join11(homeDir, ".cybedefend");
7263
- mkdirSync7(dir, { recursive: true });
7526
+ mkdirSync8(dir, { recursive: true });
7264
7527
  appendFileSync2(join11(dir, "hook-debug.log"), entry + "\n", "utf8");
7265
7528
  } catch {
7266
7529
  }
@@ -7450,6 +7713,14 @@ async function runJudgeStep(args) {
7450
7713
  if (decision.maxSeverity === "critical") return void 0;
7451
7714
  if (llmJudgeHint?.enabled === false) return void 0;
7452
7715
  const targetStr = stringifyTarget(request.target);
7716
+ const injectionSurface = [
7717
+ targetStr,
7718
+ request.tool,
7719
+ ...llmRules.flatMap((r) => [r.name ?? "", r.description ?? ""])
7720
+ ].join("\n");
7721
+ if (detectPromptInjection(injectionSurface)) {
7722
+ return { engine: "llm", outcome: "injection_blocked" };
7723
+ }
7453
7724
  const actionHash = hashTarget(targetStr);
7454
7725
  const ruleIds = llmRules.map((r) => r.id).sort().join(",");
7455
7726
  const cacheKey = `${actionHash}|${ruleIds}|confirm`;
@@ -7718,7 +7989,7 @@ function emitAgentMessage(verdict, message) {
7718
7989
  }
7719
7990
  function makeProductionJudgeDeps() {
7720
7991
  const cache = makeJudgeCache();
7721
- const warnDir = process.env.CYBEDEFEND_BASELINE_DIR ?? join10(homedir8(), ".cybedefend");
7992
+ const warnDir = process.env.CYBEDEFEND_BASELINE_DIR ?? join10(homedir9(), ".cybedefend");
7722
7993
  const warnTracker = defaultSessionTracker(
7723
7994
  join10(warnDir, "guards-judge-warned-sessions.json")
7724
7995
  );
@@ -7742,7 +8013,7 @@ async function runPreToolUseGuard() {
7742
8013
  const envelope = await readStdinJson();
7743
8014
  const config = loadRuntimeConfig();
7744
8015
  if (!config) return 0;
7745
- const { projectId, apiBase: configApiBase } = resolveProjectId();
8016
+ const { projectId, apiBase: configApiBase } = await resolveProjectIdWithApi();
7746
8017
  if (!projectId) return 0;
7747
8018
  const apiBaseResolved = process.env.CYBEDEFEND_API_BASE ?? configApiBase ?? config.region.apiBase;
7748
8019
  const token = await resolveTokenWithRefresh(config.region.mcpName);