@cybedefend/vibedefend 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -12
- package/dist/clients/antigravity.js +327 -0
- package/dist/clients/antigravity.js.map +1 -0
- package/dist/clients/registry.js +2 -0
- package/dist/clients/registry.js.map +1 -1
- package/dist/hook-runner.js +902 -227
- package/dist/hooks/install.js +1 -1
- package/dist/hooks/install.js.map +1 -1
- package/dist/hooks/runtime/antigravity-session.js +400 -0
- package/dist/hooks/runtime/antigravity-session.js.map +1 -0
- package/dist/hooks/runtime/emit.js +206 -0
- package/dist/hooks/runtime/emit.js.map +1 -1
- package/dist/hooks/runtime/exit-deadlock-guard.js +46 -0
- package/dist/hooks/runtime/exit-deadlock-guard.js.map +1 -0
- package/dist/hooks/runtime/fetch-rules.js +39 -3
- package/dist/hooks/runtime/fetch-rules.js.map +1 -1
- package/dist/hooks/runtime/pre-invocation.js +45 -0
- package/dist/hooks/runtime/pre-invocation.js.map +1 -0
- package/dist/hooks/runtime/runner-args.js +12 -0
- package/dist/hooks/runtime/runner-args.js.map +1 -0
- package/dist/hooks/runtime/session-activation.js +10 -4
- package/dist/hooks/runtime/session-activation.js.map +1 -1
- package/dist/hooks/runtime/session-review.js +42 -0
- package/dist/hooks/runtime/session-review.js.map +1 -1
- package/dist/hooks/runtime/session-start.js +21 -1
- package/dist/hooks/runtime/session-start.js.map +1 -1
- package/dist/hooks/runtime/sniff.js +325 -70
- package/dist/hooks/runtime/sniff.js.map +1 -1
- package/dist/hooks/runtime/work-dir.js +3 -0
- package/dist/hooks/runtime/work-dir.js.map +1 -1
- package/dist/hooks/shim.js +102 -5
- package/dist/hooks/shim.js.map +1 -1
- package/dist/json-file.js +6 -3
- package/dist/json-file.js.map +1 -1
- package/dist/shim.js +53 -3
- package/dist/utils.js +9 -0
- package/dist/utils.js.map +1 -1
- package/package.json +3 -2
package/dist/hook-runner.js
CHANGED
|
@@ -4630,6 +4630,34 @@ var require_re22 = __commonJS({
|
|
|
4630
4630
|
}
|
|
4631
4631
|
});
|
|
4632
4632
|
|
|
4633
|
+
// src/hooks/runtime/exit-deadlock-guard.ts
|
|
4634
|
+
import { setFlagsFromString } from "node:v8";
|
|
4635
|
+
|
|
4636
|
+
// src/hooks/runtime/runner-args.ts
|
|
4637
|
+
function parseRunnerArgs(argv) {
|
|
4638
|
+
const subcommand = argv[0] ?? "";
|
|
4639
|
+
let client = null;
|
|
4640
|
+
for (let i = 1; i < argv.length - 1; i++) {
|
|
4641
|
+
if (argv[i] === "--client" && argv[i + 1] === "antigravity") {
|
|
4642
|
+
client = "antigravity";
|
|
4643
|
+
break;
|
|
4644
|
+
}
|
|
4645
|
+
}
|
|
4646
|
+
return { subcommand, client };
|
|
4647
|
+
}
|
|
4648
|
+
|
|
4649
|
+
// src/hooks/runtime/exit-deadlock-guard.ts
|
|
4650
|
+
function exitDeadlockFlags(argv) {
|
|
4651
|
+
if (parseRunnerArgs(argv).client !== "antigravity") return [];
|
|
4652
|
+
return ["--no-concurrent-sparkplug", "--no-maglev"];
|
|
4653
|
+
}
|
|
4654
|
+
for (const flag of exitDeadlockFlags(process.argv.slice(2))) {
|
|
4655
|
+
try {
|
|
4656
|
+
setFlagsFromString(flag);
|
|
4657
|
+
} catch {
|
|
4658
|
+
}
|
|
4659
|
+
}
|
|
4660
|
+
|
|
4633
4661
|
// src/hooks/runtime/sniff.ts
|
|
4634
4662
|
import { homedir } from "node:os";
|
|
4635
4663
|
import { isAbsolute, resolve as resolvePath } from "node:path";
|
|
@@ -4869,65 +4897,205 @@ function filePathFromPatch(patch) {
|
|
|
4869
4897
|
}
|
|
4870
4898
|
return "";
|
|
4871
4899
|
}
|
|
4872
|
-
function
|
|
4873
|
-
if (!Array.isArray(
|
|
4874
|
-
return
|
|
4900
|
+
function joinStringField(entries, field) {
|
|
4901
|
+
if (!Array.isArray(entries)) return "";
|
|
4902
|
+
return entries.map((e) => {
|
|
4903
|
+
if (typeof e !== "object" || e === null) return "";
|
|
4904
|
+
const value = e[field];
|
|
4905
|
+
return typeof value === "string" ? value : "";
|
|
4906
|
+
}).filter((s) => s.length > 0).join("\n---\n");
|
|
4907
|
+
}
|
|
4908
|
+
function isAntigravityEnvelope(input2) {
|
|
4909
|
+
return typeof input2.conversationId === "string" && Array.isArray(input2.workspacePaths);
|
|
4910
|
+
}
|
|
4911
|
+
var ANTIGRAVITY_PATH_ARGS = [
|
|
4912
|
+
"TargetFile",
|
|
4913
|
+
"AbsolutePath",
|
|
4914
|
+
"Path",
|
|
4915
|
+
"FilePath",
|
|
4916
|
+
"file_path",
|
|
4917
|
+
"path"
|
|
4918
|
+
];
|
|
4919
|
+
var ANTIGRAVITY_OWN_PATH_ARG = /* @__PURE__ */ new Map([
|
|
4920
|
+
["write_to_file", "TargetFile"],
|
|
4921
|
+
["replace_file_content", "TargetFile"],
|
|
4922
|
+
["multi_replace_file_content", "TargetFile"],
|
|
4923
|
+
["view_file", "AbsolutePath"],
|
|
4924
|
+
["write_file", "Path"],
|
|
4925
|
+
["edit_file", "Path"],
|
|
4926
|
+
["read_file", "Path"]
|
|
4927
|
+
]);
|
|
4928
|
+
function antigravityFilePathArg(toolName, args) {
|
|
4929
|
+
const own2 = ANTIGRAVITY_OWN_PATH_ARG.get(toolName);
|
|
4930
|
+
for (const key of own2 === void 0 ? ANTIGRAVITY_PATH_ARGS : [own2, ...ANTIGRAVITY_PATH_ARGS]) {
|
|
4931
|
+
const value = args[key];
|
|
4932
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
4933
|
+
}
|
|
4934
|
+
return "";
|
|
4875
4935
|
}
|
|
4876
|
-
|
|
4877
|
-
|
|
4936
|
+
var ANTIGRAVITY_KNOWN_TOOLS = /* @__PURE__ */ new Set([
|
|
4937
|
+
...ANTIGRAVITY_OWN_PATH_ARG.keys(),
|
|
4938
|
+
"run_command",
|
|
4939
|
+
"read_url_content",
|
|
4940
|
+
"call_mcp_tool"
|
|
4941
|
+
]);
|
|
4942
|
+
var ANTIGRAVITY_CONTENT_KEY_RE = /content|replacement|chunk|edit|patch|diff/i;
|
|
4943
|
+
function classifyUnknownAntigravityTool(args) {
|
|
4944
|
+
const pathKeys = new Set(ANTIGRAVITY_PATH_ARGS);
|
|
4945
|
+
for (const key of Object.keys(args)) {
|
|
4946
|
+
if (pathKeys.has(key)) continue;
|
|
4947
|
+
if (ANTIGRAVITY_CONTENT_KEY_RE.test(key)) return "Write";
|
|
4948
|
+
}
|
|
4949
|
+
return "Read";
|
|
4950
|
+
}
|
|
4951
|
+
function unknownAntigravityContent(args) {
|
|
4952
|
+
const pathKeys = new Set(ANTIGRAVITY_PATH_ARGS);
|
|
4953
|
+
for (const key of Object.keys(args)) {
|
|
4954
|
+
if (pathKeys.has(key)) continue;
|
|
4955
|
+
if (!ANTIGRAVITY_CONTENT_KEY_RE.test(key)) continue;
|
|
4956
|
+
const value = args[key];
|
|
4957
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
4958
|
+
}
|
|
4959
|
+
return "";
|
|
4878
4960
|
}
|
|
4879
|
-
function
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
const
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
let toolName = action;
|
|
4888
|
-
if (action === "pre_write_code" || action === "post_write_code") {
|
|
4889
|
-
toolName = "Write";
|
|
4890
|
-
} else if (action === "pre_read_code" || action === "post_read_code") {
|
|
4891
|
-
toolName = "Read";
|
|
4961
|
+
function antigravityAllPathArgs(args) {
|
|
4962
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4963
|
+
const out = [];
|
|
4964
|
+
for (const key of ANTIGRAVITY_PATH_ARGS) {
|
|
4965
|
+
const value = args[key];
|
|
4966
|
+
if (typeof value === "string" && value.length > 0 && !seen.has(value)) {
|
|
4967
|
+
seen.add(value);
|
|
4968
|
+
out.push(value);
|
|
4892
4969
|
}
|
|
4970
|
+
}
|
|
4971
|
+
return out;
|
|
4972
|
+
}
|
|
4973
|
+
function resolveAntigravityTargetFile(value, w) {
|
|
4974
|
+
return value.length > 0 ? resolveWriteTarget(w, value) : "";
|
|
4975
|
+
}
|
|
4976
|
+
function stringArg(value) {
|
|
4977
|
+
return typeof value === "string" ? value : "";
|
|
4978
|
+
}
|
|
4979
|
+
function extractAntigravityShape(input2) {
|
|
4980
|
+
const workspacePaths = Array.isArray(input2.workspacePaths) ? input2.workspacePaths : [];
|
|
4981
|
+
const w = workspacePaths.find(
|
|
4982
|
+
(p) => typeof p === "string" && p.length > 0
|
|
4983
|
+
) ?? process.cwd();
|
|
4984
|
+
const toolCall = typeof input2.toolCall === "object" && input2.toolCall !== null ? input2.toolCall : void 0;
|
|
4985
|
+
if (toolCall === void 0) {
|
|
4893
4986
|
return {
|
|
4894
|
-
client: "
|
|
4895
|
-
toolName,
|
|
4896
|
-
filePath,
|
|
4897
|
-
filePaths:
|
|
4898
|
-
newContent,
|
|
4987
|
+
client: "antigravity",
|
|
4988
|
+
toolName: "",
|
|
4989
|
+
filePath: "",
|
|
4990
|
+
filePaths: [],
|
|
4991
|
+
newContent: "",
|
|
4899
4992
|
raw: input2
|
|
4900
4993
|
};
|
|
4901
4994
|
}
|
|
4902
|
-
|
|
4903
|
-
|
|
4995
|
+
const name = typeof toolCall.name === "string" ? toolCall.name : "";
|
|
4996
|
+
const args = toolCall.args ?? {};
|
|
4997
|
+
let toolName = name;
|
|
4998
|
+
let filePath = resolveAntigravityTargetFile(antigravityFilePathArg(name, args), w);
|
|
4999
|
+
let filePaths = [];
|
|
5000
|
+
let newContent = "";
|
|
5001
|
+
switch (name) {
|
|
5002
|
+
case "write_to_file":
|
|
5003
|
+
toolName = "Write";
|
|
5004
|
+
newContent = stringArg(args.CodeContent);
|
|
5005
|
+
break;
|
|
5006
|
+
case "write_file":
|
|
5007
|
+
toolName = "Write";
|
|
5008
|
+
newContent = stringArg(args.Content);
|
|
5009
|
+
break;
|
|
5010
|
+
case "replace_file_content":
|
|
5011
|
+
toolName = "Edit";
|
|
5012
|
+
newContent = stringArg(args.ReplacementContent);
|
|
5013
|
+
break;
|
|
5014
|
+
case "edit_file":
|
|
5015
|
+
toolName = "Edit";
|
|
5016
|
+
newContent = stringArg(args.Replacement);
|
|
5017
|
+
break;
|
|
5018
|
+
case "multi_replace_file_content":
|
|
5019
|
+
toolName = "MultiEdit";
|
|
5020
|
+
newContent = joinStringField(args.ReplacementChunks, "ReplacementContent");
|
|
5021
|
+
break;
|
|
5022
|
+
case "run_command": {
|
|
5023
|
+
toolName = "Bash";
|
|
5024
|
+
const command = typeof args.CommandLine === "string" ? args.CommandLine : "";
|
|
5025
|
+
newContent = command;
|
|
5026
|
+
const cwd = typeof args.Cwd === "string" && args.Cwd.length > 0 ? args.Cwd : w;
|
|
5027
|
+
filePaths = extractShellWriteTargets(command).map(
|
|
5028
|
+
(t) => resolveWriteTarget(cwd, t)
|
|
5029
|
+
);
|
|
5030
|
+
filePath = filePaths[0] ?? "";
|
|
5031
|
+
break;
|
|
5032
|
+
}
|
|
5033
|
+
default:
|
|
5034
|
+
if (name && filePath && !ANTIGRAVITY_KNOWN_TOOLS.has(name)) {
|
|
5035
|
+
if (classifyUnknownAntigravityTool(args) === "Write") {
|
|
5036
|
+
toolName = "Write";
|
|
5037
|
+
newContent = unknownAntigravityContent(args);
|
|
5038
|
+
}
|
|
5039
|
+
}
|
|
5040
|
+
break;
|
|
4904
5041
|
}
|
|
5042
|
+
if (filePaths.length === 0 && filePath) filePaths = [filePath];
|
|
5043
|
+
return { client: "antigravity", toolName, filePath, filePaths, newContent, raw: input2 };
|
|
5044
|
+
}
|
|
5045
|
+
function detectClient(input2) {
|
|
5046
|
+
if (isAntigravityEnvelope(input2)) return "antigravity";
|
|
5047
|
+
if (typeof input2.agent_action_name === "string") return "windsurf";
|
|
5048
|
+
if ("hookEventName" in input2) return "vscode";
|
|
4905
5049
|
if ("hook_event_name" in input2) {
|
|
4906
5050
|
const evt = typeof input2.hook_event_name === "string" ? input2.hook_event_name : "";
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
5051
|
+
if (/^[a-z]/.test(evt)) return "cursor";
|
|
5052
|
+
const toolName = typeof input2.tool_name === "string" ? input2.tool_name : "";
|
|
5053
|
+
if (toolName === "apply_patch" || "turn_id" in input2) return "codex";
|
|
5054
|
+
if (hasIsoTimestamp(input2)) return "vscode";
|
|
5055
|
+
return "claude-code";
|
|
5056
|
+
}
|
|
5057
|
+
return "unknown";
|
|
5058
|
+
}
|
|
5059
|
+
function extractWindsurfShape(input2) {
|
|
5060
|
+
const action = input2.agent_action_name;
|
|
5061
|
+
const toolInfo = input2.tool_info ?? {};
|
|
5062
|
+
const filePath = typeof toolInfo.file_path === "string" ? toolInfo.file_path : "";
|
|
5063
|
+
const newContent = joinStringField(toolInfo.edits, "new_string");
|
|
5064
|
+
let toolName = action;
|
|
5065
|
+
if (action === "pre_write_code" || action === "post_write_code") {
|
|
5066
|
+
toolName = "Write";
|
|
5067
|
+
} else if (action === "pre_read_code" || action === "post_read_code") {
|
|
5068
|
+
toolName = "Read";
|
|
4921
5069
|
}
|
|
4922
5070
|
return {
|
|
4923
|
-
client: "
|
|
4924
|
-
toolName
|
|
4925
|
-
filePath
|
|
4926
|
-
filePaths: [],
|
|
4927
|
-
newContent
|
|
5071
|
+
client: "windsurf",
|
|
5072
|
+
toolName,
|
|
5073
|
+
filePath,
|
|
5074
|
+
filePaths: filePath ? [filePath] : [],
|
|
5075
|
+
newContent,
|
|
4928
5076
|
raw: input2
|
|
4929
5077
|
};
|
|
4930
5078
|
}
|
|
5079
|
+
function sniff(input2) {
|
|
5080
|
+
const client = detectClient(input2);
|
|
5081
|
+
switch (client) {
|
|
5082
|
+
case "antigravity":
|
|
5083
|
+
return extractAntigravityShape(input2);
|
|
5084
|
+
case "windsurf":
|
|
5085
|
+
return extractWindsurfShape(input2);
|
|
5086
|
+
case "unknown":
|
|
5087
|
+
return {
|
|
5088
|
+
client: "unknown",
|
|
5089
|
+
toolName: "",
|
|
5090
|
+
filePath: "",
|
|
5091
|
+
filePaths: [],
|
|
5092
|
+
newContent: "",
|
|
5093
|
+
raw: input2
|
|
5094
|
+
};
|
|
5095
|
+
default:
|
|
5096
|
+
return extractToolInputShape(input2, client);
|
|
5097
|
+
}
|
|
5098
|
+
}
|
|
4931
5099
|
function hasIsoTimestamp(input2) {
|
|
4932
5100
|
return typeof input2.timestamp === "string" && /^\d{4}-\d{2}-\d{2}T/.test(input2.timestamp);
|
|
4933
5101
|
}
|
|
@@ -4955,9 +5123,7 @@ function extractToolInputShape(input2, client) {
|
|
|
4955
5123
|
newContent = typeof toolInput.new_string === "string" ? toolInput.new_string : "";
|
|
4956
5124
|
break;
|
|
4957
5125
|
case "MultiEdit":
|
|
4958
|
-
newContent =
|
|
4959
|
-
toolInput.edits
|
|
4960
|
-
);
|
|
5126
|
+
newContent = joinStringField(toolInput.edits, "new_string");
|
|
4961
5127
|
break;
|
|
4962
5128
|
case "apply_patch": {
|
|
4963
5129
|
const patch = typeof toolInput.patch === "string" ? toolInput.patch : typeof toolInput.command === "string" ? toolInput.command : "";
|
|
@@ -6184,9 +6350,15 @@ import { dirname as dirname4, isAbsolute as isAbsolute2, join as join6, resolve
|
|
|
6184
6350
|
import { fileURLToPath } from "node:url";
|
|
6185
6351
|
|
|
6186
6352
|
// src/hooks/runtime/emit.ts
|
|
6353
|
+
import { writeSync } from "node:fs";
|
|
6187
6354
|
var ENVELOPE_CLIENTS = {
|
|
6188
6355
|
SessionStart: /* @__PURE__ */ new Set(["codex"]),
|
|
6189
|
-
PreToolUse: /* @__PURE__ */ new Set(["claude-code", "codex", "vscode"])
|
|
6356
|
+
PreToolUse: /* @__PURE__ */ new Set(["claude-code", "codex", "vscode"]),
|
|
6357
|
+
// Antigravity never reaches this generic envelope: it has its own shapes
|
|
6358
|
+
// per event, handled in `emitAntigravityContext` below. Kept as an empty
|
|
6359
|
+
// set (rather than omitted) so `ENVELOPE_CLIENTS[hookEventName]` stays a
|
|
6360
|
+
// total function over `ContextHookEvent`.
|
|
6361
|
+
PreInvocation: /* @__PURE__ */ new Set()
|
|
6190
6362
|
};
|
|
6191
6363
|
var NO_MODEL_CHANNEL = {
|
|
6192
6364
|
PreToolUse: /* @__PURE__ */ new Set(["cursor"]),
|
|
@@ -6195,14 +6367,71 @@ var NO_MODEL_CHANNEL = {
|
|
|
6195
6367
|
function hasModelChannel(client, event) {
|
|
6196
6368
|
return !NO_MODEL_CHANNEL[event]?.has(client);
|
|
6197
6369
|
}
|
|
6370
|
+
var antigravityWritten = false;
|
|
6371
|
+
function writeStdoutSync(text) {
|
|
6372
|
+
const buf = Buffer.from(text, "utf8");
|
|
6373
|
+
const deadline = Date.now() + 2e3;
|
|
6374
|
+
let pause;
|
|
6375
|
+
let offset = 0;
|
|
6376
|
+
while (offset < buf.length) {
|
|
6377
|
+
let written = 0;
|
|
6378
|
+
try {
|
|
6379
|
+
written = writeSync(1, buf, offset, buf.length - offset);
|
|
6380
|
+
} catch (e) {
|
|
6381
|
+
if (e?.code !== "EAGAIN") return;
|
|
6382
|
+
}
|
|
6383
|
+
offset += written;
|
|
6384
|
+
if (written > 0) continue;
|
|
6385
|
+
if (Date.now() >= deadline) return;
|
|
6386
|
+
pause ??= new Int32Array(new SharedArrayBuffer(4));
|
|
6387
|
+
Atomics.wait(pause, 0, 0, 5);
|
|
6388
|
+
}
|
|
6389
|
+
}
|
|
6390
|
+
var antigravityWriter = writeStdoutSync;
|
|
6391
|
+
function writeAntigravityPayload(payload) {
|
|
6392
|
+
if (antigravityWritten) return;
|
|
6393
|
+
antigravityWritten = true;
|
|
6394
|
+
antigravityWriter(JSON.stringify(payload) + "\n");
|
|
6395
|
+
}
|
|
6396
|
+
function emitAntigravityDecision(decision, reason) {
|
|
6397
|
+
writeAntigravityPayload({ decision, ...reason ? { reason } : {} });
|
|
6398
|
+
}
|
|
6399
|
+
var PRE_TOOL_USE_SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
6400
|
+
"fetch-rules",
|
|
6401
|
+
"guard-check",
|
|
6402
|
+
"pre-tool-use",
|
|
6403
|
+
"PreToolUse"
|
|
6404
|
+
]);
|
|
6405
|
+
function finishAntigravityRun(subcommand) {
|
|
6406
|
+
const payload = PRE_TOOL_USE_SUBCOMMANDS.has(subcommand) ? { decision: "allow" } : {};
|
|
6407
|
+
writeAntigravityPayload(payload);
|
|
6408
|
+
}
|
|
6409
|
+
function emitAntigravityContext(body, hookEventName) {
|
|
6410
|
+
if (hookEventName === "PreToolUse") return;
|
|
6411
|
+
if (hookEventName === "SessionStart") {
|
|
6412
|
+
writeAntigravityPayload({
|
|
6413
|
+
injectSteps: [{ systemMessage: { systemMessage: body } }]
|
|
6414
|
+
});
|
|
6415
|
+
return;
|
|
6416
|
+
}
|
|
6417
|
+
writeAntigravityPayload({ injectSteps: [{ ephemeralMessage: body }] });
|
|
6418
|
+
}
|
|
6198
6419
|
function emit(body, client) {
|
|
6199
6420
|
if (!body) return;
|
|
6421
|
+
if (client === "antigravity") {
|
|
6422
|
+
writeAntigravityPayload({ injectSteps: [{ ephemeralMessage: body }] });
|
|
6423
|
+
return;
|
|
6424
|
+
}
|
|
6200
6425
|
if (client === "cursor") return;
|
|
6201
6426
|
process.stdout.write(body);
|
|
6202
6427
|
if (!body.endsWith("\n")) process.stdout.write("\n");
|
|
6203
6428
|
}
|
|
6204
6429
|
function emitContext(body, client, hookEventName) {
|
|
6205
6430
|
if (!body) return;
|
|
6431
|
+
if (client === "antigravity") {
|
|
6432
|
+
emitAntigravityContext(body, hookEventName);
|
|
6433
|
+
return;
|
|
6434
|
+
}
|
|
6206
6435
|
if (!hasModelChannel(client, hookEventName)) return;
|
|
6207
6436
|
if (client === "cursor" && hookEventName === "SessionStart") {
|
|
6208
6437
|
writeJson({ additional_context: body });
|
|
@@ -6262,6 +6491,9 @@ function emitStop(body, client, reason) {
|
|
|
6262
6491
|
case "cursor":
|
|
6263
6492
|
writeJson({ followup_message: body });
|
|
6264
6493
|
return;
|
|
6494
|
+
case "antigravity":
|
|
6495
|
+
writeAntigravityPayload({ decision: "continue", reason: body });
|
|
6496
|
+
return;
|
|
6265
6497
|
default:
|
|
6266
6498
|
emit(body, client);
|
|
6267
6499
|
}
|
|
@@ -6330,7 +6562,7 @@ function defaultInactiveSessionStore(file2 = defaultStoreFile(), now = Date.now)
|
|
|
6330
6562
|
};
|
|
6331
6563
|
}
|
|
6332
6564
|
function sessionIdOf(stdin) {
|
|
6333
|
-
for (const key of ["session_id", "sessionId", "conversation_id", "trajectory_id"]) {
|
|
6565
|
+
for (const key of ["session_id", "sessionId", "conversation_id", "trajectory_id", "conversationId"]) {
|
|
6334
6566
|
const v = stdin[key];
|
|
6335
6567
|
if (typeof v === "string" && v.length > 0) return v;
|
|
6336
6568
|
}
|
|
@@ -6343,6 +6575,9 @@ function sessionFolderOf(stdin, client, env = process.env) {
|
|
|
6343
6575
|
if (Array.isArray(roots)) candidates.push(roots[0]);
|
|
6344
6576
|
candidates.push(env.CURSOR_PROJECT_DIR);
|
|
6345
6577
|
}
|
|
6578
|
+
if (client === "antigravity" && Array.isArray(stdin.workspacePaths)) {
|
|
6579
|
+
candidates.push(...stdin.workspacePaths);
|
|
6580
|
+
}
|
|
6346
6581
|
candidates.push(stdin.cwd);
|
|
6347
6582
|
for (const c of candidates) {
|
|
6348
6583
|
const folder = absoluteFolder(c);
|
|
@@ -6453,10 +6688,260 @@ function projectDirForFile(file2, workDir) {
|
|
|
6453
6688
|
return fileRoot;
|
|
6454
6689
|
}
|
|
6455
6690
|
|
|
6691
|
+
// src/hooks/runtime/antigravity-session.ts
|
|
6692
|
+
import {
|
|
6693
|
+
appendFileSync,
|
|
6694
|
+
closeSync,
|
|
6695
|
+
constants,
|
|
6696
|
+
lstatSync,
|
|
6697
|
+
mkdirSync as mkdirSync6,
|
|
6698
|
+
openSync,
|
|
6699
|
+
readdirSync,
|
|
6700
|
+
readFileSync as readFileSync9,
|
|
6701
|
+
renameSync,
|
|
6702
|
+
rmSync,
|
|
6703
|
+
unlinkSync,
|
|
6704
|
+
utimesSync,
|
|
6705
|
+
writeFileSync as writeFileSync6,
|
|
6706
|
+
writeSync as writeSync2
|
|
6707
|
+
} from "node:fs";
|
|
6708
|
+
import { createHash as createHash2, randomBytes } from "node:crypto";
|
|
6709
|
+
import { homedir as homedir8 } from "node:os";
|
|
6710
|
+
import { join as join8 } from "node:path";
|
|
6711
|
+
var MAX_STASHED_CONTEXTS = 20;
|
|
6712
|
+
var DEFAULT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
6713
|
+
var STASH_NAME_RE = /^\d+-[0-9a-f]{8}\.md$/;
|
|
6714
|
+
var DIR_MODE = 448;
|
|
6715
|
+
var FILE_MODE = 384;
|
|
6716
|
+
function conversationKey(raw) {
|
|
6717
|
+
const id = raw.conversationId;
|
|
6718
|
+
if (typeof id !== "string" || id.length === 0 || id.length > 256) return null;
|
|
6719
|
+
return createHash2("sha256").update(id).digest("hex").slice(0, 32);
|
|
6720
|
+
}
|
|
6721
|
+
function antigravityStateDir() {
|
|
6722
|
+
return join8(homedir8(), ".cybedefend", "antigravity");
|
|
6723
|
+
}
|
|
6724
|
+
function keyDir(key, dir) {
|
|
6725
|
+
return join8(dir, key);
|
|
6726
|
+
}
|
|
6727
|
+
function isFinalStashName(name) {
|
|
6728
|
+
return STASH_NAME_RE.test(name);
|
|
6729
|
+
}
|
|
6730
|
+
function isUnsafePath(path) {
|
|
6731
|
+
try {
|
|
6732
|
+
return !lstatSync(path).isDirectory();
|
|
6733
|
+
} catch {
|
|
6734
|
+
return false;
|
|
6735
|
+
}
|
|
6736
|
+
}
|
|
6737
|
+
function isUnsafeFilePath(path) {
|
|
6738
|
+
try {
|
|
6739
|
+
return !lstatSync(path).isFile();
|
|
6740
|
+
} catch {
|
|
6741
|
+
return false;
|
|
6742
|
+
}
|
|
6743
|
+
}
|
|
6744
|
+
var NOFOLLOW_SUPPORTED = typeof constants.O_NOFOLLOW === "number";
|
|
6745
|
+
function appendLedgerLine(path, line) {
|
|
6746
|
+
if (NOFOLLOW_SUPPORTED) {
|
|
6747
|
+
const fd = openSync(
|
|
6748
|
+
path,
|
|
6749
|
+
constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW,
|
|
6750
|
+
FILE_MODE
|
|
6751
|
+
);
|
|
6752
|
+
try {
|
|
6753
|
+
writeSync2(fd, line, null, "utf8");
|
|
6754
|
+
} finally {
|
|
6755
|
+
closeSync(fd);
|
|
6756
|
+
}
|
|
6757
|
+
return;
|
|
6758
|
+
}
|
|
6759
|
+
if (isUnsafeFilePath(path)) return;
|
|
6760
|
+
appendFileSync(path, line, { mode: FILE_MODE });
|
|
6761
|
+
}
|
|
6762
|
+
function writeMarkerFile(path, content) {
|
|
6763
|
+
if (NOFOLLOW_SUPPORTED) {
|
|
6764
|
+
const fd = openSync(
|
|
6765
|
+
path,
|
|
6766
|
+
constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_NOFOLLOW,
|
|
6767
|
+
FILE_MODE
|
|
6768
|
+
);
|
|
6769
|
+
try {
|
|
6770
|
+
writeSync2(fd, content, null, "utf8");
|
|
6771
|
+
} finally {
|
|
6772
|
+
closeSync(fd);
|
|
6773
|
+
}
|
|
6774
|
+
return;
|
|
6775
|
+
}
|
|
6776
|
+
if (isUnsafeFilePath(path)) return;
|
|
6777
|
+
writeFileSync6(path, content, { mode: FILE_MODE });
|
|
6778
|
+
}
|
|
6779
|
+
function ensureRealDir(path) {
|
|
6780
|
+
if (isUnsafePath(path)) return false;
|
|
6781
|
+
mkdirSync6(path, { recursive: true, mode: DIR_MODE });
|
|
6782
|
+
return true;
|
|
6783
|
+
}
|
|
6784
|
+
function ensureLiveKeyDir(key, dir, now) {
|
|
6785
|
+
const kd = keyDir(key, dir);
|
|
6786
|
+
if (!ensureRealDir(kd)) return null;
|
|
6787
|
+
try {
|
|
6788
|
+
const t = new Date(now);
|
|
6789
|
+
utimesSync(kd, t, t);
|
|
6790
|
+
} catch {
|
|
6791
|
+
}
|
|
6792
|
+
return kd;
|
|
6793
|
+
}
|
|
6794
|
+
function stashContext(key, body, dir = antigravityStateDir()) {
|
|
6795
|
+
let tmpPath;
|
|
6796
|
+
try {
|
|
6797
|
+
const now = Date.now();
|
|
6798
|
+
const kd = ensureLiveKeyDir(key, dir, now);
|
|
6799
|
+
if (!kd) return;
|
|
6800
|
+
const contextDir = join8(kd, "context");
|
|
6801
|
+
if (!ensureRealDir(contextDir)) return;
|
|
6802
|
+
const suffix = randomBytes(4).toString("hex");
|
|
6803
|
+
tmpPath = join8(contextDir, `.${now}-${suffix}.tmp`);
|
|
6804
|
+
writeFileSync6(tmpPath, body, { mode: FILE_MODE, flag: "wx" });
|
|
6805
|
+
const finalPath = join8(contextDir, `${now}-${suffix}.md`);
|
|
6806
|
+
renameSync(tmpPath, finalPath);
|
|
6807
|
+
tmpPath = void 0;
|
|
6808
|
+
const kept = readdirSync(contextDir).filter(isFinalStashName).sort();
|
|
6809
|
+
const excess = kept.length - MAX_STASHED_CONTEXTS;
|
|
6810
|
+
if (excess > 0) {
|
|
6811
|
+
for (const stale of kept.slice(0, excess)) {
|
|
6812
|
+
try {
|
|
6813
|
+
unlinkSync(join8(contextDir, stale));
|
|
6814
|
+
} catch {
|
|
6815
|
+
}
|
|
6816
|
+
}
|
|
6817
|
+
}
|
|
6818
|
+
} catch {
|
|
6819
|
+
if (tmpPath) {
|
|
6820
|
+
try {
|
|
6821
|
+
unlinkSync(tmpPath);
|
|
6822
|
+
} catch {
|
|
6823
|
+
}
|
|
6824
|
+
}
|
|
6825
|
+
}
|
|
6826
|
+
}
|
|
6827
|
+
function drainContext(key, dir = antigravityStateDir()) {
|
|
6828
|
+
try {
|
|
6829
|
+
const kd = keyDir(key, dir);
|
|
6830
|
+
if (isUnsafePath(kd)) return [];
|
|
6831
|
+
const contextDir = join8(kd, "context");
|
|
6832
|
+
if (isUnsafePath(contextDir)) return [];
|
|
6833
|
+
const entries = readdirSync(contextDir).filter(isFinalStashName).sort();
|
|
6834
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6835
|
+
const bodies = [];
|
|
6836
|
+
for (const name of entries) {
|
|
6837
|
+
const filePath = join8(contextDir, name);
|
|
6838
|
+
try {
|
|
6839
|
+
const body = readFileSync9(filePath, "utf8");
|
|
6840
|
+
if (!seen.has(body)) {
|
|
6841
|
+
seen.add(body);
|
|
6842
|
+
bodies.push(body);
|
|
6843
|
+
}
|
|
6844
|
+
} catch {
|
|
6845
|
+
}
|
|
6846
|
+
try {
|
|
6847
|
+
unlinkSync(filePath);
|
|
6848
|
+
} catch {
|
|
6849
|
+
}
|
|
6850
|
+
}
|
|
6851
|
+
return bodies;
|
|
6852
|
+
} catch {
|
|
6853
|
+
return [];
|
|
6854
|
+
}
|
|
6855
|
+
}
|
|
6856
|
+
function recordEdit(key, file2, dir = antigravityStateDir()) {
|
|
6857
|
+
try {
|
|
6858
|
+
const now = Date.now();
|
|
6859
|
+
const kd = ensureLiveKeyDir(key, dir, now);
|
|
6860
|
+
if (!kd) return;
|
|
6861
|
+
appendLedgerLine(join8(kd, "edits.jsonl"), JSON.stringify({ f: file2 }) + "\n");
|
|
6862
|
+
} catch {
|
|
6863
|
+
}
|
|
6864
|
+
}
|
|
6865
|
+
function readEdits(key, dir = antigravityStateDir()) {
|
|
6866
|
+
try {
|
|
6867
|
+
const kd = keyDir(key, dir);
|
|
6868
|
+
if (isUnsafePath(kd)) return { count: 0, files: [] };
|
|
6869
|
+
const editsPath = join8(kd, "edits.jsonl");
|
|
6870
|
+
if (isUnsafeFilePath(editsPath)) return { count: 0, files: [] };
|
|
6871
|
+
const content = readFileSync9(editsPath, "utf8");
|
|
6872
|
+
let count = 0;
|
|
6873
|
+
const files = [];
|
|
6874
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6875
|
+
for (const line of content.split("\n")) {
|
|
6876
|
+
const trimmed = line.trim();
|
|
6877
|
+
if (!trimmed) continue;
|
|
6878
|
+
let parsed;
|
|
6879
|
+
try {
|
|
6880
|
+
parsed = JSON.parse(trimmed);
|
|
6881
|
+
} catch {
|
|
6882
|
+
continue;
|
|
6883
|
+
}
|
|
6884
|
+
if (typeof parsed.f !== "string") continue;
|
|
6885
|
+
count++;
|
|
6886
|
+
if (!seen.has(parsed.f)) {
|
|
6887
|
+
seen.add(parsed.f);
|
|
6888
|
+
files.push(parsed.f);
|
|
6889
|
+
}
|
|
6890
|
+
}
|
|
6891
|
+
return { count, files };
|
|
6892
|
+
} catch {
|
|
6893
|
+
return { count: 0, files: [] };
|
|
6894
|
+
}
|
|
6895
|
+
}
|
|
6896
|
+
function markReviewed(key, dir = antigravityStateDir()) {
|
|
6897
|
+
try {
|
|
6898
|
+
const now = Date.now();
|
|
6899
|
+
const kd = ensureLiveKeyDir(key, dir, now);
|
|
6900
|
+
if (!kd) return;
|
|
6901
|
+
writeMarkerFile(join8(kd, "reviewed"), String(now));
|
|
6902
|
+
} catch {
|
|
6903
|
+
}
|
|
6904
|
+
}
|
|
6905
|
+
function isReviewed(key, dir = antigravityStateDir()) {
|
|
6906
|
+
try {
|
|
6907
|
+
const kd = keyDir(key, dir);
|
|
6908
|
+
if (isUnsafePath(kd)) return false;
|
|
6909
|
+
return lstatSync(join8(kd, "reviewed")).isFile();
|
|
6910
|
+
} catch {
|
|
6911
|
+
return false;
|
|
6912
|
+
}
|
|
6913
|
+
}
|
|
6914
|
+
function pruneStale(dir = antigravityStateDir(), now = Date.now(), maxAgeMs = DEFAULT_MAX_AGE_MS) {
|
|
6915
|
+
try {
|
|
6916
|
+
const entries = readdirSync(dir);
|
|
6917
|
+
for (const name of entries) {
|
|
6918
|
+
const entryPath = join8(dir, name);
|
|
6919
|
+
try {
|
|
6920
|
+
const { mtimeMs } = lstatSync(entryPath);
|
|
6921
|
+
if (now - mtimeMs > maxAgeMs) {
|
|
6922
|
+
rmSync(entryPath, { recursive: true, force: true });
|
|
6923
|
+
}
|
|
6924
|
+
} catch {
|
|
6925
|
+
}
|
|
6926
|
+
}
|
|
6927
|
+
} catch {
|
|
6928
|
+
}
|
|
6929
|
+
}
|
|
6930
|
+
|
|
6456
6931
|
// src/hooks/runtime/fetch-rules.ts
|
|
6457
6932
|
function emitPreToolUseContext(body, client) {
|
|
6458
6933
|
emitContext(body, client, "PreToolUse");
|
|
6459
6934
|
}
|
|
6935
|
+
function defaultEmit(stdin, stateDir) {
|
|
6936
|
+
return (body, client) => {
|
|
6937
|
+
if (client === "antigravity") {
|
|
6938
|
+
const key = conversationKey(stdin);
|
|
6939
|
+
if (key) stashContext(key, body, stateDir);
|
|
6940
|
+
return;
|
|
6941
|
+
}
|
|
6942
|
+
emitPreToolUseContext(body, client);
|
|
6943
|
+
};
|
|
6944
|
+
}
|
|
6460
6945
|
var INTERESTED_TOOLS = /* @__PURE__ */ new Set([
|
|
6461
6946
|
"Edit",
|
|
6462
6947
|
"Write",
|
|
@@ -6471,13 +6956,17 @@ async function fetchRulesHook(deps = {}) {
|
|
|
6471
6956
|
const resolveTok = deps.resolveTokenFn ?? resolveToken;
|
|
6472
6957
|
const fetchRules = deps.fetchRulesFn ?? fetchBusinessRules;
|
|
6473
6958
|
const fetchSecRules = deps.fetchSecurityRulesFn ?? fetchSecurityRules;
|
|
6474
|
-
const emitFn = deps.emitFn ?? emitPreToolUseContext;
|
|
6475
6959
|
const usageNotifier = deps.usageNotifier ?? makeUsageNotifier();
|
|
6476
6960
|
const stdin = await readStdin();
|
|
6477
6961
|
const event = sniff(stdin);
|
|
6962
|
+
const emitFn = deps.emitFn ?? defaultEmit(stdin, deps.antigravityStateDir);
|
|
6478
6963
|
if (!INTERESTED_TOOLS.has(event.toolName)) return;
|
|
6479
6964
|
if (!event.filePath) return;
|
|
6480
6965
|
if (!hasModelChannel(event.client, "PreToolUse")) return;
|
|
6966
|
+
if (event.client === "antigravity" && (event.toolName === "Write" || event.toolName === "Edit" || event.toolName === "MultiEdit")) {
|
|
6967
|
+
const key = conversationKey(stdin);
|
|
6968
|
+
if (key) recordEdit(key, event.filePath, deps.antigravityStateDir);
|
|
6969
|
+
}
|
|
6481
6970
|
const config2 = loadConfig();
|
|
6482
6971
|
if (!config2) return;
|
|
6483
6972
|
const folder = sessionFolderOf(stdin, event.client);
|
|
@@ -6626,9 +7115,9 @@ var DIRECT_PROPOSE_DIRECTIVES = {
|
|
|
6626
7115
|
|
|
6627
7116
|
// src/hooks/runtime/self-update-check.ts
|
|
6628
7117
|
import { spawn } from "node:child_process";
|
|
6629
|
-
import { existsSync as existsSync11, readFileSync as
|
|
6630
|
-
import { homedir as
|
|
6631
|
-
import { join as
|
|
7118
|
+
import { existsSync as existsSync11, readFileSync as readFileSync10, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
7119
|
+
import { homedir as homedir9 } from "node:os";
|
|
7120
|
+
import { join as join9 } from "node:path";
|
|
6632
7121
|
|
|
6633
7122
|
// src/hooks/runtime/semver.ts
|
|
6634
7123
|
function parseVersion(input2) {
|
|
@@ -6706,9 +7195,9 @@ function isValidRegistryVersion(value) {
|
|
|
6706
7195
|
}
|
|
6707
7196
|
async function selfUpdateCheck(deps) {
|
|
6708
7197
|
const now = deps.now ?? (() => Date.now());
|
|
6709
|
-
const dir = deps.cybeDir ??
|
|
6710
|
-
const throttlePath =
|
|
6711
|
-
const logPath =
|
|
7198
|
+
const dir = deps.cybeDir ?? join9(process.env.CYBEDEFEND_HOME ?? homedir9(), ".cybedefend");
|
|
7199
|
+
const throttlePath = join9(dir, "update-check.json");
|
|
7200
|
+
const logPath = join9(dir, "last-update.log");
|
|
6712
7201
|
const installMode = deps.installMode ?? (deps.runnerSource ? detectInstallMode(deps.runnerSource) : detectInstallMode(resolveScriptPath()));
|
|
6713
7202
|
const priorFailure = takeUpdateLogNotice(logPath);
|
|
6714
7203
|
const throttle = readThrottle(throttlePath);
|
|
@@ -6742,7 +7231,7 @@ function applyOrNotify(deps, installMode, latest, logPath) {
|
|
|
6742
7231
|
function readThrottle(path) {
|
|
6743
7232
|
try {
|
|
6744
7233
|
if (!existsSync11(path)) return null;
|
|
6745
|
-
const data = JSON.parse(
|
|
7234
|
+
const data = JSON.parse(readFileSync10(path, "utf8"));
|
|
6746
7235
|
if (typeof data.lastCheckedAt !== "number") return null;
|
|
6747
7236
|
return { lastCheckedAt: data.lastCheckedAt };
|
|
6748
7237
|
} catch {
|
|
@@ -6752,7 +7241,7 @@ function readThrottle(path) {
|
|
|
6752
7241
|
function writeThrottle(path, throttle) {
|
|
6753
7242
|
try {
|
|
6754
7243
|
ensureDirFor(path);
|
|
6755
|
-
|
|
7244
|
+
writeFileSync7(path, JSON.stringify(throttle) + "\n");
|
|
6756
7245
|
} catch {
|
|
6757
7246
|
}
|
|
6758
7247
|
}
|
|
@@ -6761,11 +7250,11 @@ function takeUpdateLogNotice(logPath) {
|
|
|
6761
7250
|
if (!existsSync11(logPath)) return null;
|
|
6762
7251
|
let parsed = {};
|
|
6763
7252
|
try {
|
|
6764
|
-
parsed = JSON.parse(
|
|
7253
|
+
parsed = JSON.parse(readFileSync10(logPath, "utf8"));
|
|
6765
7254
|
} catch {
|
|
6766
7255
|
parsed = {};
|
|
6767
7256
|
}
|
|
6768
|
-
|
|
7257
|
+
rmSync2(logPath, { force: true });
|
|
6769
7258
|
if (typeof parsed.exitCode === "number" && parsed.exitCode !== 0) {
|
|
6770
7259
|
return `\u26A0 vibedefend: last auto-update to ${parsed.to ?? "latest"} failed (exit ${parsed.exitCode}) \u2014 run \`vibedefend update --self\`.`;
|
|
6771
7260
|
}
|
|
@@ -6836,18 +7325,18 @@ function pmCommand(mode, spec) {
|
|
|
6836
7325
|
|
|
6837
7326
|
// src/hooks/runtime/hook-refresh-trigger.ts
|
|
6838
7327
|
import { spawn as spawn2 } from "node:child_process";
|
|
6839
|
-
import { existsSync as existsSync12, readFileSync as
|
|
6840
|
-
import { homedir as
|
|
6841
|
-
import { dirname as dirname6, join as
|
|
7328
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "node:fs";
|
|
7329
|
+
import { homedir as homedir10 } from "node:os";
|
|
7330
|
+
import { dirname as dirname6, join as join10 } from "node:path";
|
|
6842
7331
|
function maybeRefreshStaleWiring(deps) {
|
|
6843
7332
|
try {
|
|
6844
7333
|
const { config: config2, runnerVersion } = deps;
|
|
6845
7334
|
if (!config2.runnerSource || config2.installedVersion === runnerVersion) {
|
|
6846
7335
|
return false;
|
|
6847
7336
|
}
|
|
6848
|
-
const cliEntry =
|
|
7337
|
+
const cliEntry = join10(dirname6(dirname6(config2.runnerSource)), "bin", "vibedefend.js");
|
|
6849
7338
|
if (!(deps.exists ?? existsSync12)(cliEntry)) return false;
|
|
6850
|
-
const markerPath = deps.markerPath ??
|
|
7339
|
+
const markerPath = deps.markerPath ?? join10(process.env.CYBEDEFEND_HOME ?? homedir10(), ".cybedefend", "hook-refresh.json");
|
|
6851
7340
|
if (readMarkerVersion(markerPath) === runnerVersion) return false;
|
|
6852
7341
|
(deps.spawnRefresh ?? defaultSpawnRefresh)(cliEntry);
|
|
6853
7342
|
writeMarker(markerPath, runnerVersion);
|
|
@@ -6859,7 +7348,7 @@ function maybeRefreshStaleWiring(deps) {
|
|
|
6859
7348
|
function readMarkerVersion(path) {
|
|
6860
7349
|
try {
|
|
6861
7350
|
if (!existsSync12(path)) return null;
|
|
6862
|
-
const data = JSON.parse(
|
|
7351
|
+
const data = JSON.parse(readFileSync11(path, "utf8"));
|
|
6863
7352
|
return typeof data.version === "string" ? data.version : null;
|
|
6864
7353
|
} catch {
|
|
6865
7354
|
return null;
|
|
@@ -6868,7 +7357,7 @@ function readMarkerVersion(path) {
|
|
|
6868
7357
|
function writeMarker(path, version2) {
|
|
6869
7358
|
try {
|
|
6870
7359
|
ensureDirFor(path);
|
|
6871
|
-
|
|
7360
|
+
writeFileSync8(path, JSON.stringify({ version: version2, spawnedAt: Date.now() }) + "\n");
|
|
6872
7361
|
} catch {
|
|
6873
7362
|
}
|
|
6874
7363
|
}
|
|
@@ -6882,18 +7371,18 @@ function defaultSpawnRefresh(cliEntry) {
|
|
|
6882
7371
|
}
|
|
6883
7372
|
|
|
6884
7373
|
// src/version.ts
|
|
6885
|
-
import { readFileSync as
|
|
7374
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
6886
7375
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6887
|
-
import { dirname as dirname7, join as
|
|
7376
|
+
import { dirname as dirname7, join as join11 } from "node:path";
|
|
6888
7377
|
var PKG_NAME = "@cybedefend/vibedefend";
|
|
6889
7378
|
function defaultPkgPath() {
|
|
6890
|
-
return
|
|
7379
|
+
return join11(dirname7(fileURLToPath3(import.meta.url)), "..", "package.json");
|
|
6891
7380
|
}
|
|
6892
7381
|
function readPackageMeta(opts = {}) {
|
|
6893
7382
|
if (typeof opts.bakedVersion === "string" && opts.bakedVersion.length > 0) {
|
|
6894
7383
|
return { name: PKG_NAME, version: opts.bakedVersion };
|
|
6895
7384
|
}
|
|
6896
|
-
const readFile = opts.readFile ?? ((p) =>
|
|
7385
|
+
const readFile = opts.readFile ?? ((p) => readFileSync12(p, "utf8"));
|
|
6897
7386
|
const pkgPath = opts.pkgPath ?? defaultPkgPath();
|
|
6898
7387
|
try {
|
|
6899
7388
|
return JSON.parse(readFile(pkgPath));
|
|
@@ -6902,7 +7391,7 @@ function readPackageMeta(opts = {}) {
|
|
|
6902
7391
|
}
|
|
6903
7392
|
}
|
|
6904
7393
|
var pkg = readPackageMeta({
|
|
6905
|
-
bakedVersion: true ? "1.
|
|
7394
|
+
bakedVersion: true ? "1.8.0" : void 0
|
|
6906
7395
|
});
|
|
6907
7396
|
|
|
6908
7397
|
// src/hooks/runtime/session-start.ts
|
|
@@ -6946,6 +7435,9 @@ async function sessionStartHook(deps = {}) {
|
|
|
6946
7435
|
}
|
|
6947
7436
|
if (sessionId) sessionStore.clear(sessionId);
|
|
6948
7437
|
const apiBase = process.env.CYBEDEFEND_API_BASE ?? configApiBase ?? config2.region.apiBase;
|
|
7438
|
+
if (event.client === "antigravity") {
|
|
7439
|
+
pruneStale(deps.antigravityStateDir);
|
|
7440
|
+
}
|
|
6949
7441
|
if (process.env.CYBEDEFEND_DRY_RUN === "1") {
|
|
6950
7442
|
emitFn(
|
|
6951
7443
|
`## CybeDefend session bootstrap (dry-run, client=${event.client})
|
|
@@ -6998,7 +7490,12 @@ async function sessionStartHook(deps = {}) {
|
|
|
6998
7490
|
" **before responding to the user request.**"
|
|
6999
7491
|
);
|
|
7000
7492
|
}
|
|
7001
|
-
const HARD_ENFORCEMENT_CLIENTS = /* @__PURE__ */ new Set([
|
|
7493
|
+
const HARD_ENFORCEMENT_CLIENTS = /* @__PURE__ */ new Set([
|
|
7494
|
+
"claude-code",
|
|
7495
|
+
"codex",
|
|
7496
|
+
"cursor",
|
|
7497
|
+
"antigravity"
|
|
7498
|
+
]);
|
|
7002
7499
|
lines.push("");
|
|
7003
7500
|
if (HARD_ENFORCEMENT_CLIENTS.has(event.client)) {
|
|
7004
7501
|
lines.push(
|
|
@@ -7036,23 +7533,23 @@ async function sessionStartHook(deps = {}) {
|
|
|
7036
7533
|
}
|
|
7037
7534
|
|
|
7038
7535
|
// src/hooks/runtime/session-review.ts
|
|
7039
|
-
import { existsSync as existsSync14, readFileSync as
|
|
7536
|
+
import { existsSync as existsSync14, readFileSync as readFileSync14 } from "node:fs";
|
|
7040
7537
|
|
|
7041
7538
|
// src/hooks/runtime/review-sessions.ts
|
|
7042
|
-
import { existsSync as existsSync13, mkdirSync as
|
|
7043
|
-
import { homedir as
|
|
7044
|
-
import { dirname as dirname8, join as
|
|
7539
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
|
|
7540
|
+
import { homedir as homedir11 } from "node:os";
|
|
7541
|
+
import { dirname as dirname8, join as join12 } from "node:path";
|
|
7045
7542
|
var SESSIONS_CAP2 = 200;
|
|
7046
7543
|
function defaultStoreFile2() {
|
|
7047
|
-
const dir = process.env.CYBEDEFEND_BASELINE_DIR ??
|
|
7048
|
-
return
|
|
7544
|
+
const dir = process.env.CYBEDEFEND_BASELINE_DIR ?? join12(homedir11(), ".cybedefend");
|
|
7545
|
+
return join12(dir, "review-sessions.json");
|
|
7049
7546
|
}
|
|
7050
7547
|
var isCount = (n) => typeof n === "number" && Number.isInteger(n) && n >= 0;
|
|
7051
7548
|
function defaultReviewSessionStore(file2 = defaultStoreFile2(), now = Date.now) {
|
|
7052
7549
|
function load2() {
|
|
7053
7550
|
if (!existsSync13(file2)) return {};
|
|
7054
7551
|
try {
|
|
7055
|
-
const parsed = JSON.parse(
|
|
7552
|
+
const parsed = JSON.parse(readFileSync13(file2, "utf8"));
|
|
7056
7553
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
7057
7554
|
} catch {
|
|
7058
7555
|
return {};
|
|
@@ -7060,8 +7557,8 @@ function defaultReviewSessionStore(file2 = defaultStoreFile2(), now = Date.now)
|
|
|
7060
7557
|
}
|
|
7061
7558
|
function save(map2) {
|
|
7062
7559
|
try {
|
|
7063
|
-
|
|
7064
|
-
|
|
7560
|
+
mkdirSync7(dirname8(file2), { recursive: true });
|
|
7561
|
+
writeFileSync9(file2, JSON.stringify(map2) + "\n", "utf8");
|
|
7065
7562
|
} catch {
|
|
7066
7563
|
}
|
|
7067
7564
|
}
|
|
@@ -7171,6 +7668,32 @@ async function sessionReviewHook(deps = {}) {
|
|
|
7171
7668
|
const config2 = loadConfig();
|
|
7172
7669
|
if (!config2) return;
|
|
7173
7670
|
if (!config2.hooks.enableSessionReview) return;
|
|
7671
|
+
if (event.client === "antigravity") {
|
|
7672
|
+
const key = conversationKey(stdin);
|
|
7673
|
+
const stateDir = deps.antigravityStateDir;
|
|
7674
|
+
if (!key || isReviewed(key, stateDir)) return;
|
|
7675
|
+
let { count, files } = readEdits(key, stateDir);
|
|
7676
|
+
if (process.env.CYBEDEFEND_DRY_RUN === "1") {
|
|
7677
|
+
count = parseInt(process.env.CYBEDEFEND_DRY_RUN_EDITS ?? "5", 10);
|
|
7678
|
+
}
|
|
7679
|
+
if (count === 0) return;
|
|
7680
|
+
if (count < resolveReviewThreshold(config2)) return;
|
|
7681
|
+
const folder2 = sessionFolderOf(stdin, "antigravity");
|
|
7682
|
+
if (isSessionInactive(stdin, { store: deps.sessionStore, cwd: folder2 })) return;
|
|
7683
|
+
const { projectId: projectId2 } = await (deps.resolveProject ?? resolveProjectIdWithApi)(folder2);
|
|
7684
|
+
if (!projectId2) return;
|
|
7685
|
+
const proposalMode2 = resolveProposalMode(config2);
|
|
7686
|
+
let body2 = composeReviewBody(count, "antigravity", "", proposalMode2);
|
|
7687
|
+
const withDiffScan2 = config2.hooks.enableDiffScan !== false;
|
|
7688
|
+
if (withDiffScan2) {
|
|
7689
|
+
body2 += "\n" + composeDiffScanBody(
|
|
7690
|
+
files.slice(0, CHANGED_FILES_MAX).map((f) => relativizePath(f, folder2))
|
|
7691
|
+
);
|
|
7692
|
+
}
|
|
7693
|
+
emitFn(body2, "antigravity", composeStopReason(withDiffScan2, proposalMode2));
|
|
7694
|
+
markReviewed(key, stateDir);
|
|
7695
|
+
return;
|
|
7696
|
+
}
|
|
7174
7697
|
const transcript = loadTranscript(stdin, readTranscriptFile);
|
|
7175
7698
|
const sessionId = sessionIdOf(stdin);
|
|
7176
7699
|
const store = sessionId ? deps.reviewStore ?? defaultReviewSessionStore() : null;
|
|
@@ -7247,7 +7770,7 @@ function loadTranscript(stdin, readFile) {
|
|
|
7247
7770
|
function defaultReadTranscript(path) {
|
|
7248
7771
|
if (!existsSync14(path)) return null;
|
|
7249
7772
|
try {
|
|
7250
|
-
return
|
|
7773
|
+
return readFileSync14(path, "utf8");
|
|
7251
7774
|
} catch {
|
|
7252
7775
|
return null;
|
|
7253
7776
|
}
|
|
@@ -7515,19 +8038,19 @@ async function preCompactHook(deps = {}) {
|
|
|
7515
8038
|
}
|
|
7516
8039
|
|
|
7517
8040
|
// src/hooks/runtime/user-prompt-submit.ts
|
|
7518
|
-
import { existsSync as existsSync15, mkdirSync as
|
|
7519
|
-
import { homedir as
|
|
7520
|
-
import { join as
|
|
8041
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync8, readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "node:fs";
|
|
8042
|
+
import { homedir as homedir12 } from "node:os";
|
|
8043
|
+
import { join as join13 } from "node:path";
|
|
7521
8044
|
var SESSIONS_CAP3 = 100;
|
|
7522
8045
|
function defaultSessionsFile() {
|
|
7523
|
-
const dir = process.env.CYBEDEFEND_BASELINE_DIR ??
|
|
7524
|
-
return
|
|
8046
|
+
const dir = process.env.CYBEDEFEND_BASELINE_DIR ?? join13(homedir12(), ".cybedefend");
|
|
8047
|
+
return join13(dir, "user-prompt-seen-sessions.json");
|
|
7525
8048
|
}
|
|
7526
8049
|
function defaultSessionTracker(file2 = defaultSessionsFile()) {
|
|
7527
8050
|
function load2() {
|
|
7528
8051
|
if (!existsSync15(file2)) return [];
|
|
7529
8052
|
try {
|
|
7530
|
-
const raw =
|
|
8053
|
+
const raw = readFileSync15(file2, "utf8");
|
|
7531
8054
|
const data = JSON.parse(raw);
|
|
7532
8055
|
if (!Array.isArray(data.sessions)) return [];
|
|
7533
8056
|
return data.sessions.filter((s) => typeof s === "string");
|
|
@@ -7544,8 +8067,8 @@ function defaultSessionTracker(file2 = defaultSessionsFile()) {
|
|
|
7544
8067
|
if (existing.includes(sessionId)) return;
|
|
7545
8068
|
const next = [...existing, sessionId].slice(-SESSIONS_CAP3);
|
|
7546
8069
|
try {
|
|
7547
|
-
|
|
7548
|
-
|
|
8070
|
+
mkdirSync8(join13(file2, ".."), { recursive: true });
|
|
8071
|
+
writeFileSync10(file2, JSON.stringify({ sessions: next }), "utf8");
|
|
7549
8072
|
} catch {
|
|
7550
8073
|
}
|
|
7551
8074
|
}
|
|
@@ -7633,6 +8156,20 @@ async function userPromptSubmitHook(deps = {}) {
|
|
|
7633
8156
|
}
|
|
7634
8157
|
}
|
|
7635
8158
|
|
|
8159
|
+
// src/hooks/runtime/pre-invocation.ts
|
|
8160
|
+
var STASH_SEPARATOR = "\n\n---\n\n";
|
|
8161
|
+
async function preInvocationHook(deps = {}) {
|
|
8162
|
+
const readStdin = deps.readStdin ?? readStdinJson;
|
|
8163
|
+
const stdin = await readStdin();
|
|
8164
|
+
if (!isAntigravityEnvelope(stdin)) return;
|
|
8165
|
+
const key = conversationKey(stdin);
|
|
8166
|
+
if (!key) return;
|
|
8167
|
+
const dir = deps.stateDir ?? antigravityStateDir();
|
|
8168
|
+
const bodies = drainContext(key, dir);
|
|
8169
|
+
if (bodies.length === 0) return;
|
|
8170
|
+
emitContext(bodies.join(STASH_SEPARATOR), "antigravity", "PreInvocation");
|
|
8171
|
+
}
|
|
8172
|
+
|
|
7636
8173
|
// src/guards-evaluator/glob.ts
|
|
7637
8174
|
function expandHome(pattern, homeDir) {
|
|
7638
8175
|
if (pattern === "~") return homeDir;
|
|
@@ -8364,7 +8901,7 @@ function buildCommandViews(raw) {
|
|
|
8364
8901
|
}
|
|
8365
8902
|
|
|
8366
8903
|
// src/guards-evaluator/redact.ts
|
|
8367
|
-
import { createHash as
|
|
8904
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
8368
8905
|
var REDACTED = "[REDACTED]";
|
|
8369
8906
|
var PATTERNS = [
|
|
8370
8907
|
// 1. JWT — three base64url segments separated by dots
|
|
@@ -8476,7 +9013,7 @@ function redactScriptText(text) {
|
|
|
8476
9013
|
return redactTarget(masked, Number.MAX_SAFE_INTEGER);
|
|
8477
9014
|
}
|
|
8478
9015
|
function hashTarget(text) {
|
|
8479
|
-
return
|
|
9016
|
+
return createHash3("sha256").update(text, "utf8").digest("hex");
|
|
8480
9017
|
}
|
|
8481
9018
|
|
|
8482
9019
|
// src/guards-evaluator/evaluate.ts
|
|
@@ -11093,15 +11630,15 @@ function resolveCandidatePaths(rawPath, opts) {
|
|
|
11093
11630
|
// src/hooks/runtime/session-writes.ts
|
|
11094
11631
|
import {
|
|
11095
11632
|
existsSync as existsSync17,
|
|
11096
|
-
mkdirSync as
|
|
11097
|
-
readFileSync as
|
|
11098
|
-
renameSync,
|
|
11633
|
+
mkdirSync as mkdirSync9,
|
|
11634
|
+
readFileSync as readFileSync17,
|
|
11635
|
+
renameSync as renameSync2,
|
|
11099
11636
|
rmdirSync,
|
|
11100
11637
|
statSync as statSync3,
|
|
11101
|
-
writeFileSync as
|
|
11638
|
+
writeFileSync as writeFileSync11
|
|
11102
11639
|
} from "node:fs";
|
|
11103
|
-
import { homedir as
|
|
11104
|
-
import { join as
|
|
11640
|
+
import { homedir as homedir13 } from "node:os";
|
|
11641
|
+
import { join as join14, posix } from "node:path";
|
|
11105
11642
|
var DEFAULT_MAX_PATHS = 500;
|
|
11106
11643
|
var DEFAULT_SESSION_WRITES_TTL_MS = 4 * 60 * 60 * 1e3;
|
|
11107
11644
|
var SESSION_WRITES_FILE = "guards-session-writes.json";
|
|
@@ -11115,7 +11652,7 @@ function withLock(lockDir, fn) {
|
|
|
11115
11652
|
let held = false;
|
|
11116
11653
|
while (!held) {
|
|
11117
11654
|
try {
|
|
11118
|
-
|
|
11655
|
+
mkdirSync9(lockDir);
|
|
11119
11656
|
held = true;
|
|
11120
11657
|
} catch {
|
|
11121
11658
|
try {
|
|
@@ -11142,7 +11679,7 @@ function withLock(lockDir, fn) {
|
|
|
11142
11679
|
}
|
|
11143
11680
|
}
|
|
11144
11681
|
function defaultDir() {
|
|
11145
|
-
return process.env.CYBEDEFEND_BASELINE_DIR ??
|
|
11682
|
+
return process.env.CYBEDEFEND_BASELINE_DIR ?? join14(homedir13(), ".cybedefend");
|
|
11146
11683
|
}
|
|
11147
11684
|
function normalizePath(p) {
|
|
11148
11685
|
if (typeof p !== "string") return "";
|
|
@@ -11177,14 +11714,14 @@ function coerce(raw) {
|
|
|
11177
11714
|
}
|
|
11178
11715
|
function makeSessionWritesStore(opts = {}) {
|
|
11179
11716
|
const dir = opts.dir ?? defaultDir();
|
|
11180
|
-
const file2 =
|
|
11717
|
+
const file2 = join14(dir, SESSION_WRITES_FILE);
|
|
11181
11718
|
const now = opts.now ?? (() => Date.now());
|
|
11182
11719
|
const maxPaths = typeof opts.maxPaths === "number" && opts.maxPaths > 0 ? Math.floor(opts.maxPaths) : DEFAULT_MAX_PATHS;
|
|
11183
11720
|
const ttlMs = typeof opts.ttlMs === "number" && opts.ttlMs > 0 ? opts.ttlMs : DEFAULT_SESSION_WRITES_TTL_MS;
|
|
11184
11721
|
function readAll() {
|
|
11185
11722
|
if (!existsSync17(file2)) return {};
|
|
11186
11723
|
try {
|
|
11187
|
-
return coerce(JSON.parse(
|
|
11724
|
+
return coerce(JSON.parse(readFileSync17(file2, "utf8")));
|
|
11188
11725
|
} catch {
|
|
11189
11726
|
return {};
|
|
11190
11727
|
}
|
|
@@ -11199,10 +11736,10 @@ function makeSessionWritesStore(opts = {}) {
|
|
|
11199
11736
|
}
|
|
11200
11737
|
function writeAll(all) {
|
|
11201
11738
|
try {
|
|
11202
|
-
if (!existsSync17(dir))
|
|
11739
|
+
if (!existsSync17(dir)) mkdirSync9(dir, { recursive: true });
|
|
11203
11740
|
const tmp = `${file2}.${process.pid}.tmp`;
|
|
11204
|
-
|
|
11205
|
-
|
|
11741
|
+
writeFileSync11(tmp, JSON.stringify(all), "utf8");
|
|
11742
|
+
renameSync2(tmp, file2);
|
|
11206
11743
|
} catch {
|
|
11207
11744
|
}
|
|
11208
11745
|
}
|
|
@@ -11212,7 +11749,7 @@ function makeSessionWritesStore(opts = {}) {
|
|
|
11212
11749
|
const usable = paths.filter(isUsable);
|
|
11213
11750
|
if (usable.length === 0) return;
|
|
11214
11751
|
try {
|
|
11215
|
-
if (!existsSync17(dir))
|
|
11752
|
+
if (!existsSync17(dir)) mkdirSync9(dir, { recursive: true });
|
|
11216
11753
|
withLock(`${file2}.lock`, () => {
|
|
11217
11754
|
const t = now();
|
|
11218
11755
|
const all = pruneExpired(readAll(), t);
|
|
@@ -11528,10 +12065,10 @@ function nearMiss(req, rule) {
|
|
|
11528
12065
|
import { isAbsolute as isAbsolute6, resolve as resolvePath4 } from "node:path";
|
|
11529
12066
|
|
|
11530
12067
|
// src/hooks/runtime/guard-rules-cache.ts
|
|
11531
|
-
import { readFileSync as
|
|
12068
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync12, existsSync as existsSync18, mkdirSync as mkdirSync10 } from "node:fs";
|
|
11532
12069
|
import { dirname as dirname9 } from "node:path";
|
|
11533
|
-
import { homedir as
|
|
11534
|
-
import { join as
|
|
12070
|
+
import { homedir as homedir14 } from "node:os";
|
|
12071
|
+
import { join as join15 } from "node:path";
|
|
11535
12072
|
|
|
11536
12073
|
// node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/external.js
|
|
11537
12074
|
var external_exports = {};
|
|
@@ -31338,7 +31875,7 @@ function retryAfterOf(e) {
|
|
|
31338
31875
|
}
|
|
31339
31876
|
|
|
31340
31877
|
// src/hooks/runtime/retry-policy.ts
|
|
31341
|
-
import { createHash as
|
|
31878
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
31342
31879
|
var UNAUTHORIZED_BACKOFF_MS = [
|
|
31343
31880
|
6e4,
|
|
31344
31881
|
5 * 6e4,
|
|
@@ -31364,12 +31901,12 @@ function unauthorizedBackoffMs(consecutive) {
|
|
|
31364
31901
|
return UNAUTHORIZED_BACKOFF_MS[index];
|
|
31365
31902
|
}
|
|
31366
31903
|
function tokenFingerprint(token) {
|
|
31367
|
-
return
|
|
31904
|
+
return createHash4("sha256").update(token).digest("hex").slice(0, 16);
|
|
31368
31905
|
}
|
|
31369
31906
|
|
|
31370
31907
|
// src/hooks/runtime/guard-rules-cache.ts
|
|
31371
|
-
var DEFAULT_CACHE_FILE =
|
|
31372
|
-
|
|
31908
|
+
var DEFAULT_CACHE_FILE = join15(
|
|
31909
|
+
homedir14(),
|
|
31373
31910
|
".cybedefend",
|
|
31374
31911
|
"guards-cache.json"
|
|
31375
31912
|
);
|
|
@@ -31444,7 +31981,7 @@ function reportDroppedRules(dropped) {
|
|
|
31444
31981
|
}
|
|
31445
31982
|
function makeGuardRulesCache(opts) {
|
|
31446
31983
|
const cacheFile = opts.cacheFile ?? DEFAULT_CACHE_FILE;
|
|
31447
|
-
const failuresFile = opts.failuresFile ??
|
|
31984
|
+
const failuresFile = opts.failuresFile ?? join15(dirname9(cacheFile), "guards-cache-failures.json");
|
|
31448
31985
|
const staleSec = opts.staleSec ?? DEFAULT_STALE_SEC;
|
|
31449
31986
|
const fetchFn = opts.fetchFn;
|
|
31450
31987
|
const clock = opts.now ?? Date.now;
|
|
@@ -31549,7 +32086,7 @@ function makeGuardRulesCache(opts) {
|
|
|
31549
32086
|
function readCache(projectId) {
|
|
31550
32087
|
if (!existsSync18(cacheFile)) return null;
|
|
31551
32088
|
try {
|
|
31552
|
-
const raw =
|
|
32089
|
+
const raw = readFileSync18(cacheFile, "utf8");
|
|
31553
32090
|
const data = JSON.parse(raw);
|
|
31554
32091
|
if (data.projectId !== projectId) return null;
|
|
31555
32092
|
return data;
|
|
@@ -31560,7 +32097,7 @@ function makeGuardRulesCache(opts) {
|
|
|
31560
32097
|
function readFailures() {
|
|
31561
32098
|
try {
|
|
31562
32099
|
if (!existsSync18(failuresFile)) return {};
|
|
31563
|
-
const parsed = JSON.parse(
|
|
32100
|
+
const parsed = JSON.parse(readFileSync18(failuresFile, "utf8"));
|
|
31564
32101
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
31565
32102
|
return {};
|
|
31566
32103
|
}
|
|
@@ -31582,7 +32119,7 @@ function makeGuardRulesCache(opts) {
|
|
|
31582
32119
|
if (now - f.at > FAILURE_RETENTION_MS) delete failures[projectId];
|
|
31583
32120
|
}
|
|
31584
32121
|
ensureDirFor2(failuresFile);
|
|
31585
|
-
|
|
32122
|
+
writeFileSync12(failuresFile, JSON.stringify(failures), "utf8");
|
|
31586
32123
|
} catch {
|
|
31587
32124
|
}
|
|
31588
32125
|
}
|
|
@@ -31593,7 +32130,7 @@ function makeGuardRulesCache(opts) {
|
|
|
31593
32130
|
function writeCache(entry) {
|
|
31594
32131
|
try {
|
|
31595
32132
|
ensureDirFor2(cacheFile);
|
|
31596
|
-
|
|
32133
|
+
writeFileSync12(cacheFile, JSON.stringify(entry), "utf8");
|
|
31597
32134
|
} catch {
|
|
31598
32135
|
}
|
|
31599
32136
|
}
|
|
@@ -31602,7 +32139,7 @@ function makeGuardRulesCache(opts) {
|
|
|
31602
32139
|
function ensureDirFor2(filePath) {
|
|
31603
32140
|
const dir = dirname9(filePath);
|
|
31604
32141
|
if (!existsSync18(dir)) {
|
|
31605
|
-
|
|
32142
|
+
mkdirSync10(dir, { recursive: true });
|
|
31606
32143
|
}
|
|
31607
32144
|
}
|
|
31608
32145
|
var DEFAULT_TIMEOUT_MS2 = 8e3;
|
|
@@ -31742,11 +32279,11 @@ function detectPromptInjection(text) {
|
|
|
31742
32279
|
}
|
|
31743
32280
|
|
|
31744
32281
|
// src/hooks/runtime/judge-cache.ts
|
|
31745
|
-
import { readFileSync as
|
|
31746
|
-
import { dirname as dirname10, join as
|
|
31747
|
-
import { homedir as
|
|
31748
|
-
var DEFAULT_JUDGE_CACHE_FILE =
|
|
31749
|
-
|
|
32282
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync13, existsSync as existsSync19, mkdirSync as mkdirSync11 } from "node:fs";
|
|
32283
|
+
import { dirname as dirname10, join as join16 } from "node:path";
|
|
32284
|
+
import { homedir as homedir15 } from "node:os";
|
|
32285
|
+
var DEFAULT_JUDGE_CACHE_FILE = join16(
|
|
32286
|
+
homedir15(),
|
|
31750
32287
|
".cybedefend",
|
|
31751
32288
|
"guards-judge-cache.json"
|
|
31752
32289
|
);
|
|
@@ -31759,7 +32296,7 @@ function makeJudgeCache(opts = {}) {
|
|
|
31759
32296
|
function readAll() {
|
|
31760
32297
|
if (!existsSync19(cacheFile)) return {};
|
|
31761
32298
|
try {
|
|
31762
|
-
return JSON.parse(
|
|
32299
|
+
return JSON.parse(readFileSync19(cacheFile, "utf8"));
|
|
31763
32300
|
} catch {
|
|
31764
32301
|
return {};
|
|
31765
32302
|
}
|
|
@@ -31783,7 +32320,7 @@ function makeJudgeCache(opts = {}) {
|
|
|
31783
32320
|
for (const k of keys.slice(0, Math.max(0, keys.length - maxEntries))) delete all[k];
|
|
31784
32321
|
}
|
|
31785
32322
|
ensureDirFor3(cacheFile);
|
|
31786
|
-
|
|
32323
|
+
writeFileSync13(cacheFile, JSON.stringify(all), "utf8");
|
|
31787
32324
|
} catch {
|
|
31788
32325
|
}
|
|
31789
32326
|
}
|
|
@@ -31792,34 +32329,34 @@ function makeJudgeCache(opts = {}) {
|
|
|
31792
32329
|
function ensureDirFor3(filePath) {
|
|
31793
32330
|
const dir = dirname10(filePath);
|
|
31794
32331
|
if (!existsSync19(dir)) {
|
|
31795
|
-
|
|
32332
|
+
mkdirSync11(dir, { recursive: true });
|
|
31796
32333
|
}
|
|
31797
32334
|
}
|
|
31798
32335
|
|
|
31799
32336
|
// src/hooks/runtime/guard-check.ts
|
|
31800
32337
|
import { spawn as spawn3 } from "node:child_process";
|
|
31801
|
-
import { homedir as
|
|
31802
|
-
import { join as
|
|
32338
|
+
import { homedir as homedir18 } from "node:os";
|
|
32339
|
+
import { join as join19 } from "node:path";
|
|
31803
32340
|
|
|
31804
32341
|
// src/hooks/runtime/guard-violations-buffer.ts
|
|
31805
32342
|
import {
|
|
31806
|
-
appendFileSync,
|
|
31807
|
-
closeSync as
|
|
32343
|
+
appendFileSync as appendFileSync2,
|
|
32344
|
+
closeSync as closeSync3,
|
|
31808
32345
|
existsSync as existsSync20,
|
|
31809
|
-
openSync as
|
|
31810
|
-
readFileSync as
|
|
31811
|
-
writeFileSync as
|
|
31812
|
-
writeSync,
|
|
31813
|
-
mkdirSync as
|
|
31814
|
-
rmSync as
|
|
32346
|
+
openSync as openSync3,
|
|
32347
|
+
readFileSync as readFileSync20,
|
|
32348
|
+
writeFileSync as writeFileSync14,
|
|
32349
|
+
writeSync as writeSync3,
|
|
32350
|
+
mkdirSync as mkdirSync12,
|
|
32351
|
+
rmSync as rmSync3,
|
|
31815
32352
|
statSync as statSync4,
|
|
31816
|
-
utimesSync
|
|
32353
|
+
utimesSync as utimesSync2
|
|
31817
32354
|
} from "node:fs";
|
|
31818
32355
|
import { dirname as dirname11 } from "node:path";
|
|
31819
|
-
import { homedir as
|
|
31820
|
-
import { join as
|
|
31821
|
-
var DEFAULT_BUFFER_FILE =
|
|
31822
|
-
|
|
32356
|
+
import { homedir as homedir16 } from "node:os";
|
|
32357
|
+
import { join as join17 } from "node:path";
|
|
32358
|
+
var DEFAULT_BUFFER_FILE = join17(
|
|
32359
|
+
homedir16(),
|
|
31823
32360
|
".cybedefend",
|
|
31824
32361
|
"guards-violations-buffer.jsonl"
|
|
31825
32362
|
);
|
|
@@ -31830,8 +32367,8 @@ var MAX_RECORD_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
31830
32367
|
var FLUSH_LOCK_STALE_MS = 6e4;
|
|
31831
32368
|
function makeViolationsBuffer(opts = {}) {
|
|
31832
32369
|
const bufferFile = opts.bufferFile ?? DEFAULT_BUFFER_FILE;
|
|
31833
|
-
const holdsFile = opts.holdsFile ??
|
|
31834
|
-
const lockFile = opts.lockFile ??
|
|
32370
|
+
const holdsFile = opts.holdsFile ?? join17(dirname11(bufferFile), "guards-violations-holds.json");
|
|
32371
|
+
const lockFile = opts.lockFile ?? join17(dirname11(bufferFile), "guards-violations-flush.lock");
|
|
31835
32372
|
const now = opts.now ?? Date.now;
|
|
31836
32373
|
function bufferViolation2(ctx, v) {
|
|
31837
32374
|
const record2 = {
|
|
@@ -31841,7 +32378,7 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
31841
32378
|
};
|
|
31842
32379
|
try {
|
|
31843
32380
|
ensureDirFor4(bufferFile);
|
|
31844
|
-
|
|
32381
|
+
appendFileSync2(bufferFile, JSON.stringify(record2) + "\n", "utf8");
|
|
31845
32382
|
} catch {
|
|
31846
32383
|
}
|
|
31847
32384
|
}
|
|
@@ -31923,7 +32460,7 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
31923
32460
|
writeHolds(holds);
|
|
31924
32461
|
try {
|
|
31925
32462
|
const serialised = failed.map((r) => JSON.stringify(r) + "\n").join("");
|
|
31926
|
-
|
|
32463
|
+
writeFileSync14(bufferFile, serialised + appendedSince(snapshot.bytes), "utf8");
|
|
31927
32464
|
} catch {
|
|
31928
32465
|
}
|
|
31929
32466
|
}
|
|
@@ -31945,7 +32482,7 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
31945
32482
|
}
|
|
31946
32483
|
function readBuffer() {
|
|
31947
32484
|
try {
|
|
31948
|
-
const raw =
|
|
32485
|
+
const raw = readFileSync20(bufferFile);
|
|
31949
32486
|
return { content: raw.toString("utf8"), bytes: raw.length };
|
|
31950
32487
|
} catch {
|
|
31951
32488
|
return null;
|
|
@@ -31953,7 +32490,7 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
31953
32490
|
}
|
|
31954
32491
|
function appendedSince(bytes) {
|
|
31955
32492
|
try {
|
|
31956
|
-
const raw =
|
|
32493
|
+
const raw = readFileSync20(bufferFile);
|
|
31957
32494
|
return raw.length > bytes ? raw.subarray(bytes).toString("utf8") : "";
|
|
31958
32495
|
} catch {
|
|
31959
32496
|
return "";
|
|
@@ -31967,18 +32504,18 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
31967
32504
|
}
|
|
31968
32505
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
31969
32506
|
try {
|
|
31970
|
-
const fd =
|
|
32507
|
+
const fd = openSync3(lockFile, "wx");
|
|
31971
32508
|
try {
|
|
31972
|
-
|
|
32509
|
+
writeSync3(fd, String(process.pid));
|
|
31973
32510
|
} finally {
|
|
31974
|
-
|
|
32511
|
+
closeSync3(fd);
|
|
31975
32512
|
}
|
|
31976
32513
|
return true;
|
|
31977
32514
|
} catch (e) {
|
|
31978
32515
|
if (e.code !== "EEXIST") return false;
|
|
31979
32516
|
if (!lockIsStale()) return false;
|
|
31980
32517
|
try {
|
|
31981
|
-
|
|
32518
|
+
rmSync3(lockFile, { force: true });
|
|
31982
32519
|
} catch {
|
|
31983
32520
|
return false;
|
|
31984
32521
|
}
|
|
@@ -31996,26 +32533,26 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
31996
32533
|
function touchLock() {
|
|
31997
32534
|
try {
|
|
31998
32535
|
const t = /* @__PURE__ */ new Date();
|
|
31999
|
-
|
|
32536
|
+
utimesSync2(lockFile, t, t);
|
|
32000
32537
|
} catch {
|
|
32001
32538
|
}
|
|
32002
32539
|
}
|
|
32003
32540
|
function releaseLock() {
|
|
32004
32541
|
try {
|
|
32005
|
-
|
|
32542
|
+
rmSync3(lockFile, { force: true });
|
|
32006
32543
|
} catch {
|
|
32007
32544
|
}
|
|
32008
32545
|
}
|
|
32009
32546
|
function liftHolds() {
|
|
32010
32547
|
try {
|
|
32011
|
-
|
|
32548
|
+
rmSync3(holdsFile, { force: true });
|
|
32012
32549
|
} catch {
|
|
32013
32550
|
}
|
|
32014
32551
|
}
|
|
32015
32552
|
function readHolds() {
|
|
32016
32553
|
try {
|
|
32017
32554
|
if (!existsSync20(holdsFile)) return {};
|
|
32018
|
-
const parsed = JSON.parse(
|
|
32555
|
+
const parsed = JSON.parse(readFileSync20(holdsFile, "utf8"));
|
|
32019
32556
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
32020
32557
|
return {};
|
|
32021
32558
|
}
|
|
@@ -32040,11 +32577,11 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
32040
32577
|
function writeHolds(holds) {
|
|
32041
32578
|
try {
|
|
32042
32579
|
if (Object.keys(holds).length === 0) {
|
|
32043
|
-
|
|
32580
|
+
rmSync3(holdsFile, { force: true });
|
|
32044
32581
|
return;
|
|
32045
32582
|
}
|
|
32046
32583
|
ensureDirFor4(holdsFile);
|
|
32047
|
-
|
|
32584
|
+
writeFileSync14(holdsFile, JSON.stringify(holds), "utf8");
|
|
32048
32585
|
} catch {
|
|
32049
32586
|
}
|
|
32050
32587
|
}
|
|
@@ -32077,7 +32614,7 @@ function capRecords(records, now) {
|
|
|
32077
32614
|
function ensureDirFor4(filePath) {
|
|
32078
32615
|
const dir = dirname11(filePath);
|
|
32079
32616
|
if (!existsSync20(dir)) {
|
|
32080
|
-
|
|
32617
|
+
mkdirSync12(dir, { recursive: true });
|
|
32081
32618
|
}
|
|
32082
32619
|
}
|
|
32083
32620
|
var _defaultBuffer = makeViolationsBuffer();
|
|
@@ -32086,9 +32623,9 @@ var flushViolations = _defaultBuffer.flushViolations.bind(_defaultBuffer);
|
|
|
32086
32623
|
var liftViolationHolds = _defaultBuffer.liftHolds.bind(_defaultBuffer);
|
|
32087
32624
|
|
|
32088
32625
|
// src/hooks/runtime/unmapped-tools.ts
|
|
32089
|
-
import { existsSync as existsSync21, mkdirSync as
|
|
32090
|
-
import { dirname as dirname12, join as
|
|
32091
|
-
import { homedir as
|
|
32626
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync15 } from "node:fs";
|
|
32627
|
+
import { dirname as dirname12, join as join18 } from "node:path";
|
|
32628
|
+
import { homedir as homedir17 } from "node:os";
|
|
32092
32629
|
var TARGETLESS_TOOL_RE = /^(?:ToolSearch|TodoRead|TodoWrite|Task|Agent|AskUserQuestion|Skill|SlashCommand|EnterPlanMode|ExitPlanMode|EnterWorktree|ExitWorktree|BashOutput|KillShell|KillBash|Monitor|ListMcpResourcesTool|ReadMcpResourceTool|ReadMcpResourceDirTool|ScheduleWakeup|PushNotification|CronCreate|CronDelete|CronList|SendMessage|ListAgents|TaskOutput|TaskStop|ReportFindings|Workflow)$/;
|
|
32093
32630
|
var OWN_MCP_TOOL_RE = /^mcp__cybedefend(?:-[A-Za-z0-9_-]+)?__/;
|
|
32094
32631
|
function isTargetlessTool(tool) {
|
|
@@ -32100,13 +32637,13 @@ function strictUnmappedPolicy() {
|
|
|
32100
32637
|
}
|
|
32101
32638
|
var MAX_TOOLS = 200;
|
|
32102
32639
|
function defaultUnmappedToolsFile() {
|
|
32103
|
-
const dir = process.env.CYBEDEFEND_BASELINE_DIR ??
|
|
32104
|
-
return
|
|
32640
|
+
const dir = process.env.CYBEDEFEND_BASELINE_DIR ?? join18(homedir17(), ".cybedefend");
|
|
32641
|
+
return join18(dir, "guards-unmapped-tools.json");
|
|
32105
32642
|
}
|
|
32106
32643
|
function load(file2) {
|
|
32107
32644
|
try {
|
|
32108
32645
|
if (!existsSync21(file2)) return { tools: {} };
|
|
32109
|
-
const parsed = JSON.parse(
|
|
32646
|
+
const parsed = JSON.parse(readFileSync21(file2, "utf8"));
|
|
32110
32647
|
if (!parsed || typeof parsed !== "object" || typeof parsed.tools !== "object" || !parsed.tools) {
|
|
32111
32648
|
return { tools: {} };
|
|
32112
32649
|
}
|
|
@@ -32130,8 +32667,8 @@ function makeUnmappedToolTelemetry(file2 = defaultUnmappedToolsFile()) {
|
|
|
32130
32667
|
if (names.length > MAX_TOOLS) {
|
|
32131
32668
|
names.sort((a, b) => data.tools[a].lastSeen.localeCompare(data.tools[b].lastSeen)).slice(0, names.length - MAX_TOOLS).forEach((n) => delete data.tools[n]);
|
|
32132
32669
|
}
|
|
32133
|
-
|
|
32134
|
-
|
|
32670
|
+
mkdirSync13(dirname12(file2), { recursive: true });
|
|
32671
|
+
writeFileSync15(file2, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
32135
32672
|
} catch {
|
|
32136
32673
|
}
|
|
32137
32674
|
}
|
|
@@ -32171,9 +32708,16 @@ function extractWriteTargets(req, rawCommand) {
|
|
|
32171
32708
|
}
|
|
32172
32709
|
return [];
|
|
32173
32710
|
}
|
|
32174
|
-
function normalizeToolName(tool) {
|
|
32711
|
+
function normalizeToolName(tool, client) {
|
|
32175
32712
|
if (!tool) return "";
|
|
32176
32713
|
const t = (tool.split(/[\r\n]/, 1)[0] ?? "").trim();
|
|
32714
|
+
if (client === "antigravity") {
|
|
32715
|
+
if (/^view_file$/i.test(t)) return "Read";
|
|
32716
|
+
if (/^(write_to_file|write_file)$/i.test(t)) return "Write";
|
|
32717
|
+
if (/^(replace_file_content|edit_file)$/i.test(t)) return "Edit";
|
|
32718
|
+
if (/^multi_replace_file_content$/i.test(t)) return "MultiEdit";
|
|
32719
|
+
if (/^read_url_content$/i.test(t)) return "WebFetch";
|
|
32720
|
+
}
|
|
32177
32721
|
if (/^(read|read_file|cat)$/i.test(t)) return "Read";
|
|
32178
32722
|
if (/^(write|create_file|new_file)$/i.test(t)) return "Write";
|
|
32179
32723
|
if (/^(edit|apply_patch|str_replace_editor)$/i.test(t)) return "Edit";
|
|
@@ -32189,11 +32733,11 @@ function appendDebugLog(entry) {
|
|
|
32189
32733
|
try {
|
|
32190
32734
|
const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
32191
32735
|
if (!homeDir) return;
|
|
32192
|
-
const { mkdirSync:
|
|
32193
|
-
const { join:
|
|
32194
|
-
const dir =
|
|
32195
|
-
|
|
32196
|
-
|
|
32736
|
+
const { mkdirSync: mkdirSync14, appendFileSync: appendFileSync3 } = __require("node:fs");
|
|
32737
|
+
const { join: join20 } = __require("node:path");
|
|
32738
|
+
const dir = join20(homeDir, ".cybedefend");
|
|
32739
|
+
mkdirSync14(dir, { recursive: true });
|
|
32740
|
+
appendFileSync3(join20(dir, "hook-debug.log"), entry + "\n", "utf8");
|
|
32197
32741
|
} catch {
|
|
32198
32742
|
}
|
|
32199
32743
|
}
|
|
@@ -32208,9 +32752,63 @@ function debugLog(entry) {
|
|
|
32208
32752
|
}
|
|
32209
32753
|
}
|
|
32210
32754
|
var UNNAMED_TOOL = "<unnamed>";
|
|
32755
|
+
function sniffCaller(envelope) {
|
|
32756
|
+
try {
|
|
32757
|
+
return sniff(envelope);
|
|
32758
|
+
} catch {
|
|
32759
|
+
}
|
|
32760
|
+
let client = "unknown";
|
|
32761
|
+
try {
|
|
32762
|
+
client = detectClient(envelope);
|
|
32763
|
+
} catch {
|
|
32764
|
+
}
|
|
32765
|
+
const rawTool = client === "antigravity" && isRecord(envelope.toolCall) ? envelope.toolCall.name : envelope?.tool_name;
|
|
32766
|
+
return {
|
|
32767
|
+
client,
|
|
32768
|
+
toolName: typeof rawTool === "string" ? rawTool : "",
|
|
32769
|
+
filePath: "",
|
|
32770
|
+
filePaths: [],
|
|
32771
|
+
newContent: "",
|
|
32772
|
+
raw: envelope
|
|
32773
|
+
};
|
|
32774
|
+
}
|
|
32211
32775
|
function argvToCommandLine(argv) {
|
|
32212
32776
|
return argv.map((a) => /^[A-Za-z0-9_./=:@%+,-]+$/.test(a) ? a : `'${a.replace(/'/g, "'\\''")}'`).join(" ");
|
|
32213
32777
|
}
|
|
32778
|
+
var MCP_SERVER_NAME_RE = /^[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*$/;
|
|
32779
|
+
var MCP_SERVER_NAME_MAX = 64;
|
|
32780
|
+
var MCP_TOOL_NAME_RE = /^[A-Za-z0-9]+(?:[-_.][A-Za-z0-9]+)*$/;
|
|
32781
|
+
var MCP_TOOL_NAME_MAX = 128;
|
|
32782
|
+
function isRecord(v) {
|
|
32783
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
32784
|
+
}
|
|
32785
|
+
function readAntigravityCall(envelope) {
|
|
32786
|
+
const toolCall = isRecord(envelope.toolCall) ? envelope.toolCall : {};
|
|
32787
|
+
const args = isRecord(toolCall.args) ? toolCall.args : {};
|
|
32788
|
+
const str3 = (v) => typeof v === "string" ? v : void 0;
|
|
32789
|
+
const name = str3(toolCall.name);
|
|
32790
|
+
let tool = name;
|
|
32791
|
+
const server = str3(args.ServerName);
|
|
32792
|
+
const mcpTool = str3(args.ToolName);
|
|
32793
|
+
if (tool === "call_mcp_tool" && server !== void 0 && mcpTool !== void 0 && server.length <= MCP_SERVER_NAME_MAX && MCP_SERVER_NAME_RE.test(server) && mcpTool.length <= MCP_TOOL_NAME_MAX && MCP_TOOL_NAME_RE.test(mcpTool)) {
|
|
32794
|
+
tool = `mcp__${server}__${mcpTool}`;
|
|
32795
|
+
}
|
|
32796
|
+
const params = {};
|
|
32797
|
+
const filePath = antigravityFilePathArg(name ?? "", args);
|
|
32798
|
+
if (filePath) params.file_path = filePath;
|
|
32799
|
+
const command = str3(args.CommandLine);
|
|
32800
|
+
if (command !== void 0) params.command = command;
|
|
32801
|
+
const url2 = str3(args.Url);
|
|
32802
|
+
if (url2 !== void 0) params.url = url2;
|
|
32803
|
+
let classifiedTool;
|
|
32804
|
+
let extraFilePaths = [];
|
|
32805
|
+
if (name !== void 0 && filePath && !ANTIGRAVITY_KNOWN_TOOLS.has(name)) {
|
|
32806
|
+
classifiedTool = classifyUnknownAntigravityTool(args);
|
|
32807
|
+
extraFilePaths = antigravityAllPathArgs(args).filter((p) => p !== filePath);
|
|
32808
|
+
}
|
|
32809
|
+
const cwd = typeof args.Cwd === "string" && args.Cwd.length > 0 ? args.Cwd : sessionFolderOf(envelope, "antigravity");
|
|
32810
|
+
return { tool, classifiedTool, params, extraFilePaths, cwd, argKeys: Object.keys(args) };
|
|
32811
|
+
}
|
|
32214
32812
|
function commandField(params) {
|
|
32215
32813
|
const v = params.command;
|
|
32216
32814
|
if (typeof v === "string") return v;
|
|
@@ -32219,40 +32817,54 @@ function commandField(params) {
|
|
|
32219
32817
|
}
|
|
32220
32818
|
return null;
|
|
32221
32819
|
}
|
|
32222
|
-
function
|
|
32223
|
-
const
|
|
32224
|
-
|
|
32820
|
+
function fileMapping(agent, tool, params, homeDir, cwd, rawTool, extraFilePaths) {
|
|
32821
|
+
const filePath = typeof params.file_path === "string" ? params.file_path : typeof params.path === "string" ? params.path : null;
|
|
32822
|
+
if (!filePath) return { kind: "unmapped", tool: rawTool ?? UNNAMED_TOOL };
|
|
32823
|
+
const request = {
|
|
32824
|
+
agent,
|
|
32825
|
+
tool,
|
|
32826
|
+
target: { type: "file", path: filePath },
|
|
32827
|
+
homeDir,
|
|
32828
|
+
cwd
|
|
32829
|
+
};
|
|
32830
|
+
if (extraFilePaths.length === 0) return { kind: "mapped", request };
|
|
32831
|
+
return {
|
|
32832
|
+
kind: "mapped",
|
|
32833
|
+
request,
|
|
32834
|
+
additionalRequests: extraFilePaths.map((path) => ({
|
|
32835
|
+
agent,
|
|
32836
|
+
tool,
|
|
32837
|
+
target: { type: "file", path },
|
|
32838
|
+
homeDir,
|
|
32839
|
+
cwd
|
|
32840
|
+
}))
|
|
32841
|
+
};
|
|
32842
|
+
}
|
|
32843
|
+
function mapEnvelope(envelope, agent = sniffCaller(envelope).client) {
|
|
32844
|
+
const antigravity = agent === "antigravity" ? readAntigravityCall(envelope) : null;
|
|
32845
|
+
const rawTool = antigravity ? antigravity.tool : typeof envelope.tool_name === "string" ? envelope.tool_name : typeof envelope.tool === "string" ? envelope.tool : void 0;
|
|
32846
|
+
const params = antigravity ? antigravity.params : envelope.tool_input ?? envelope.params ?? envelope.input ?? {};
|
|
32847
|
+
const loggedKeys = antigravity ? antigravity.argKeys : Object.keys(params);
|
|
32225
32848
|
debugLog({
|
|
32226
32849
|
event: "pre_map",
|
|
32227
32850
|
raw_tool_name: rawTool ?? null,
|
|
32228
32851
|
has_tool_input: "tool_input" in envelope,
|
|
32229
32852
|
has_params: "params" in envelope,
|
|
32230
|
-
param_keys:
|
|
32853
|
+
param_keys: loggedKeys.slice(0, 12)
|
|
32231
32854
|
});
|
|
32232
32855
|
const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? "/";
|
|
32233
|
-
const cwd = process.cwd();
|
|
32234
|
-
const tool = normalizeToolName(rawTool);
|
|
32856
|
+
const cwd = antigravity ? antigravity.cwd : process.cwd();
|
|
32857
|
+
const tool = antigravity?.classifiedTool ?? normalizeToolName(rawTool, agent);
|
|
32858
|
+
const extraFilePaths = antigravity?.extraFilePaths ?? [];
|
|
32235
32859
|
switch (tool) {
|
|
32236
32860
|
case "Read":
|
|
32237
32861
|
case "Glob":
|
|
32238
|
-
case "Grep":
|
|
32239
|
-
|
|
32240
|
-
if (!filePath) return { kind: "unmapped", tool: rawTool ?? UNNAMED_TOOL };
|
|
32241
|
-
return {
|
|
32242
|
-
kind: "mapped",
|
|
32243
|
-
request: { agent, tool, target: { type: "file", path: filePath }, homeDir, cwd }
|
|
32244
|
-
};
|
|
32245
|
-
}
|
|
32862
|
+
case "Grep":
|
|
32863
|
+
return fileMapping(agent, tool, params, homeDir, cwd, rawTool, extraFilePaths);
|
|
32246
32864
|
case "Write":
|
|
32247
32865
|
case "Edit":
|
|
32248
|
-
case "MultiEdit":
|
|
32249
|
-
|
|
32250
|
-
if (!filePath) return { kind: "unmapped", tool: rawTool ?? UNNAMED_TOOL };
|
|
32251
|
-
return {
|
|
32252
|
-
kind: "mapped",
|
|
32253
|
-
request: { agent, tool, target: { type: "file", path: filePath }, homeDir, cwd }
|
|
32254
|
-
};
|
|
32255
|
-
}
|
|
32866
|
+
case "MultiEdit":
|
|
32867
|
+
return fileMapping(agent, tool, params, homeDir, cwd, rawTool, extraFilePaths);
|
|
32256
32868
|
case "Bash": {
|
|
32257
32869
|
const command = commandField(params);
|
|
32258
32870
|
if (!command) return { kind: "unmapped", tool: rawTool ?? UNNAMED_TOOL };
|
|
@@ -32334,7 +32946,7 @@ function mapEnvelope(envelope, agent = sniff(envelope).client) {
|
|
|
32334
32946
|
JSON.stringify({
|
|
32335
32947
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32336
32948
|
tool_name: rawTool ?? null,
|
|
32337
|
-
params_keys:
|
|
32949
|
+
params_keys: loggedKeys
|
|
32338
32950
|
})
|
|
32339
32951
|
);
|
|
32340
32952
|
return { kind: "unmapped", tool: rawTool ?? UNNAMED_TOOL };
|
|
@@ -32383,6 +32995,9 @@ function stringifyTarget(t) {
|
|
|
32383
32995
|
return `git ${t.subcommand}`;
|
|
32384
32996
|
}
|
|
32385
32997
|
}
|
|
32998
|
+
function verdictRank(v) {
|
|
32999
|
+
return v === "deny" ? 2 : v === "warn" ? 1 : 0;
|
|
33000
|
+
}
|
|
32386
33001
|
async function consultJudge(judge, sessionId, cacheKey, input2, cache = { get: (k) => judge.cacheGet(k), set: (k, r) => judge.cacheSet(k, r) }) {
|
|
32387
33002
|
const cached2 = cache.get(cacheKey);
|
|
32388
33003
|
if (cached2) return { kind: "result", res: cached2 };
|
|
@@ -32601,6 +33216,14 @@ ${JSON.stringify(payload)}` : targetStr);
|
|
|
32601
33216
|
}
|
|
32602
33217
|
return { engine: "llm", outcome: "confirmed", model: res.model };
|
|
32603
33218
|
}
|
|
33219
|
+
var SESSION_ID_MAX = 128;
|
|
33220
|
+
function antigravitySessionId(envelope) {
|
|
33221
|
+
const id = envelope.conversationId;
|
|
33222
|
+
return typeof id === "string" && id.length > 0 && id.length <= SESSION_ID_MAX ? id : void 0;
|
|
33223
|
+
}
|
|
33224
|
+
function denyExitCode(client) {
|
|
33225
|
+
return client === "antigravity" ? 0 : 2;
|
|
33226
|
+
}
|
|
32604
33227
|
async function runCatchJudgeStep(args) {
|
|
32605
33228
|
const {
|
|
32606
33229
|
judge,
|
|
@@ -32660,7 +33283,7 @@ async function runCatchJudgeStep(args) {
|
|
|
32660
33283
|
message
|
|
32661
33284
|
};
|
|
32662
33285
|
}
|
|
32663
|
-
function emitUnverifiedBanner(reason) {
|
|
33286
|
+
function emitUnverifiedBanner(reason, client) {
|
|
32664
33287
|
const banner = [
|
|
32665
33288
|
"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588",
|
|
32666
33289
|
"\u2588 VibeDefend Action Guards \u2014 UNVERIFIED \u2588",
|
|
@@ -32678,7 +33301,7 @@ function emitUnverifiedBanner(reason) {
|
|
|
32678
33301
|
].join("\n") + "\n";
|
|
32679
33302
|
process.stderr.write(banner);
|
|
32680
33303
|
const isCodex = typeof process.env.CODEX_SANDBOX !== "undefined" || typeof process.env.CODEX_AGENT !== "undefined";
|
|
32681
|
-
if (isCodex) {
|
|
33304
|
+
if (isCodex && client !== "antigravity") {
|
|
32682
33305
|
try {
|
|
32683
33306
|
const ctx = JSON.stringify({
|
|
32684
33307
|
additionalContext: `VibeDefend Action Guards UNVERIFIED \u2014 ${reason} Tool call allowed WITHOUT enforcement. Run \`vibedefend login\` to restore protection.`
|
|
@@ -32688,8 +33311,10 @@ function emitUnverifiedBanner(reason) {
|
|
|
32688
33311
|
}
|
|
32689
33312
|
}
|
|
32690
33313
|
}
|
|
32691
|
-
function sessionIdOf3(envelope) {
|
|
32692
|
-
|
|
33314
|
+
function sessionIdOf3(envelope, client) {
|
|
33315
|
+
if (typeof envelope.session_id === "string") return envelope.session_id;
|
|
33316
|
+
if (typeof envelope.sessionId === "string") return envelope.sessionId;
|
|
33317
|
+
return client === "antigravity" ? antigravitySessionId(envelope) : void 0;
|
|
32693
33318
|
}
|
|
32694
33319
|
async function runPreToolUseGuardWith(opts) {
|
|
32695
33320
|
const {
|
|
@@ -32702,21 +33327,22 @@ async function runPreToolUseGuardWith(opts) {
|
|
|
32702
33327
|
if (!projectContext) return 0;
|
|
32703
33328
|
if (rulesOutcome.kind === "unavailable") {
|
|
32704
33329
|
emitUnverifiedBanner(
|
|
32705
|
-
`Policy engine unreachable: ${rulesOutcome.reason}
|
|
33330
|
+
`Policy engine unreachable: ${rulesOutcome.reason}`,
|
|
33331
|
+
sniffCaller(stdinEnvelope).client
|
|
32706
33332
|
);
|
|
32707
33333
|
return 0;
|
|
32708
33334
|
}
|
|
32709
33335
|
if (rulesOutcome.kind === "blocked") {
|
|
32710
33336
|
const sentence = opts.usageNotifier?.notifyBlock(
|
|
32711
|
-
sessionIdOf3(stdinEnvelope),
|
|
33337
|
+
sessionIdOf3(stdinEnvelope, sniffCaller(stdinEnvelope).client),
|
|
32712
33338
|
rulesOutcome.block
|
|
32713
33339
|
);
|
|
32714
|
-
if (sentence) emitAgentMessage("warn", sentence);
|
|
33340
|
+
if (sentence) emitAgentMessage("warn", sentence, sniffCaller(stdinEnvelope).client);
|
|
32715
33341
|
return 0;
|
|
32716
33342
|
}
|
|
32717
33343
|
const rules = rulesOutcome.rules;
|
|
32718
|
-
const caller =
|
|
32719
|
-
const sessionId = sessionIdOf3(stdinEnvelope);
|
|
33344
|
+
const caller = sniffCaller(stdinEnvelope);
|
|
33345
|
+
const sessionId = sessionIdOf3(stdinEnvelope, caller.client);
|
|
32720
33346
|
const mapping = mapEnvelope(stdinEnvelope, caller.client);
|
|
32721
33347
|
if (mapping.kind === "targetless") return 0;
|
|
32722
33348
|
if (mapping.kind === "unmapped") {
|
|
@@ -32731,9 +33357,10 @@ async function runPreToolUseGuardWith(opts) {
|
|
|
32731
33357
|
if (strictUnmappedPolicy()) {
|
|
32732
33358
|
emitAgentMessage(
|
|
32733
33359
|
"deny",
|
|
32734
|
-
`Tool "${mapping.tool}" is not evaluated by Action Guards and CYBEDEFEND_GUARDS_STRICT is on \u2014 blocked (strict mode)
|
|
33360
|
+
`Tool "${mapping.tool}" is not evaluated by Action Guards and CYBEDEFEND_GUARDS_STRICT is on \u2014 blocked (strict mode).`,
|
|
33361
|
+
caller.client
|
|
32735
33362
|
);
|
|
32736
|
-
return
|
|
33363
|
+
return denyExitCode(caller.client);
|
|
32737
33364
|
}
|
|
32738
33365
|
if (opts.unmapped.noticeOnce(sessionId, mapping.tool)) {
|
|
32739
33366
|
process.stderr.write(
|
|
@@ -32744,12 +33371,24 @@ async function runPreToolUseGuardWith(opts) {
|
|
|
32744
33371
|
return 0;
|
|
32745
33372
|
}
|
|
32746
33373
|
const partial2 = mapping.request;
|
|
32747
|
-
|
|
33374
|
+
let guardRequest = {
|
|
32748
33375
|
...partial2,
|
|
32749
33376
|
projectId: projectContext.projectId,
|
|
32750
33377
|
sessionId
|
|
32751
33378
|
};
|
|
32752
33379
|
let decision = evaluateFn(rules, guardRequest);
|
|
33380
|
+
for (const extra of mapping.additionalRequests ?? []) {
|
|
33381
|
+
const extraRequest = {
|
|
33382
|
+
...extra,
|
|
33383
|
+
projectId: projectContext.projectId,
|
|
33384
|
+
sessionId
|
|
33385
|
+
};
|
|
33386
|
+
const extraDecision = evaluateFn(rules, extraRequest);
|
|
33387
|
+
if (verdictRank(extraDecision.verdict) > verdictRank(decision.verdict)) {
|
|
33388
|
+
decision = extraDecision;
|
|
33389
|
+
guardRequest = extraRequest;
|
|
33390
|
+
}
|
|
33391
|
+
}
|
|
32753
33392
|
let hardenedTier = "small";
|
|
32754
33393
|
let hardenedScripts = [];
|
|
32755
33394
|
if (opts.hardenedCommandAnalysis && opts.sessionWrites && guardRequest.target.type === "file" && (guardRequest.tool === "Write" || guardRequest.tool === "Edit" || guardRequest.tool === "MultiEdit")) {
|
|
@@ -32904,20 +33543,28 @@ async function runPreToolUseGuardWith(opts) {
|
|
|
32904
33543
|
matched_rule_ids: decision.matchedRuleIds
|
|
32905
33544
|
});
|
|
32906
33545
|
if (decision.verdict === "deny") {
|
|
32907
|
-
emitAgentMessage("deny", decision.message ?? "Action blocked.");
|
|
32908
|
-
return
|
|
33546
|
+
emitAgentMessage("deny", decision.message ?? "Action blocked.", caller.client);
|
|
33547
|
+
return denyExitCode(caller.client);
|
|
32909
33548
|
}
|
|
32910
33549
|
if (decision.verdict === "warn") {
|
|
32911
|
-
emitAgentMessage("warn", decision.message ?? "Action flagged.");
|
|
33550
|
+
emitAgentMessage("warn", decision.message ?? "Action flagged.", caller.client);
|
|
32912
33551
|
return 0;
|
|
32913
33552
|
}
|
|
32914
33553
|
return 0;
|
|
32915
33554
|
}
|
|
32916
|
-
|
|
33555
|
+
var ANTIGRAVITY_DECISIONS = {
|
|
33556
|
+
deny: "deny",
|
|
33557
|
+
warn: "allow"
|
|
33558
|
+
};
|
|
33559
|
+
function emitAgentMessage(verdict, message, client) {
|
|
32917
33560
|
const tag = verdict === "deny" ? "Action Guards" : "Action Guards \xB7 WARN";
|
|
32918
33561
|
const fullMessage = `[VibeDefend ${tag}] ${message}`;
|
|
32919
33562
|
process.stderr.write(fullMessage + "\n");
|
|
32920
33563
|
try {
|
|
33564
|
+
if (client === "antigravity") {
|
|
33565
|
+
emitAntigravityDecision(ANTIGRAVITY_DECISIONS[verdict], fullMessage);
|
|
33566
|
+
return;
|
|
33567
|
+
}
|
|
32921
33568
|
const payload = verdict === "deny" ? {
|
|
32922
33569
|
// Claude Code legacy — the call, not the agent, is stopped.
|
|
32923
33570
|
decision: "block",
|
|
@@ -32950,17 +33597,17 @@ function emitAgentMessage(verdict, message) {
|
|
|
32950
33597
|
}
|
|
32951
33598
|
function makeProductionJudgeDeps() {
|
|
32952
33599
|
const cache = makeJudgeCache();
|
|
32953
|
-
const warnDir = process.env.CYBEDEFEND_BASELINE_DIR ??
|
|
33600
|
+
const warnDir = process.env.CYBEDEFEND_BASELINE_DIR ?? join19(homedir18(), ".cybedefend");
|
|
32954
33601
|
const scriptCache = makeJudgeCache({
|
|
32955
|
-
cacheFile:
|
|
33602
|
+
cacheFile: join19(warnDir, "guards-judge-script-cache.json"),
|
|
32956
33603
|
ttlMs: SCRIPT_VERDICT_TTL_MS,
|
|
32957
33604
|
maxEntries: SCRIPT_VERDICT_MAX_ENTRIES
|
|
32958
33605
|
});
|
|
32959
33606
|
const warnTracker = defaultSessionTracker(
|
|
32960
|
-
|
|
33607
|
+
join19(warnDir, "guards-judge-warned-sessions.json")
|
|
32961
33608
|
);
|
|
32962
33609
|
const blockedTracker = defaultSessionTracker(
|
|
32963
|
-
|
|
33610
|
+
join19(warnDir, "guards-judge-blocked-sessions.json")
|
|
32964
33611
|
);
|
|
32965
33612
|
return {
|
|
32966
33613
|
usage: {
|
|
@@ -32988,8 +33635,8 @@ function makeProductionJudgeDeps() {
|
|
|
32988
33635
|
}
|
|
32989
33636
|
function makeProductionUnmappedDeps() {
|
|
32990
33637
|
const telemetry = makeUnmappedToolTelemetry();
|
|
32991
|
-
const dir = process.env.CYBEDEFEND_BASELINE_DIR ??
|
|
32992
|
-
const tracker = defaultSessionTracker(
|
|
33638
|
+
const dir = process.env.CYBEDEFEND_BASELINE_DIR ?? join19(homedir18(), ".cybedefend");
|
|
33639
|
+
const tracker = defaultSessionTracker(join19(dir, "guards-unmapped-notified.json"));
|
|
32993
33640
|
return {
|
|
32994
33641
|
record: telemetry.record,
|
|
32995
33642
|
noticeOnce: (sessionId, tool) => {
|
|
@@ -33043,7 +33690,8 @@ async function runPreToolUseGuard() {
|
|
|
33043
33690
|
});
|
|
33044
33691
|
if (!token && rulesOutcome.kind === "unavailable") {
|
|
33045
33692
|
emitUnverifiedBanner(
|
|
33046
|
-
"Not authenticated \u2014 run `vibedefend login` to restore Action Guards."
|
|
33693
|
+
"Not authenticated \u2014 run `vibedefend login` to restore Action Guards.",
|
|
33694
|
+
sniffCaller(envelope).client
|
|
33047
33695
|
);
|
|
33048
33696
|
return 0;
|
|
33049
33697
|
}
|
|
@@ -33080,7 +33728,7 @@ async function runPreToolUseGuard() {
|
|
|
33080
33728
|
scriptJudge: process.env.CYBEDEFEND_HARDENED_ANALYSIS !== "0" && process.env.CYBEDEFEND_SCRIPT_JUDGE !== "0",
|
|
33081
33729
|
// Level 1 — real script reader + per-session write memory.
|
|
33082
33730
|
scriptResolver: process.env.CYBEDEFEND_HARDENED_ANALYSIS !== "0" ? (command, cwd) => resolveExecutedScript(command, { cwd }) : void 0,
|
|
33083
|
-
sessionWrites: process.env.CYBEDEFEND_HARDENED_ANALYSIS !== "0" ? makeSessionWritesPort(sessionIdOf3(envelope)) : void 0,
|
|
33731
|
+
sessionWrites: process.env.CYBEDEFEND_HARDENED_ANALYSIS !== "0" ? makeSessionWritesPort(sessionIdOf3(envelope, sniffCaller(envelope).client)) : void 0,
|
|
33084
33732
|
resolvePaths: process.env.CYBEDEFEND_HARDENED_ANALYSIS !== "0" ? (rawPath, cwd, homeDir) => resolveCandidatePaths(rawPath, { cwd, homeDir }) : void 0,
|
|
33085
33733
|
// The refusal sentence goes out through the agent-message channels
|
|
33086
33734
|
// (stderr included), so this notifier itself writes nothing.
|
|
@@ -33177,7 +33825,31 @@ function toApiViolation(r) {
|
|
|
33177
33825
|
|
|
33178
33826
|
// src/hooks/runtime/index.ts
|
|
33179
33827
|
async function main() {
|
|
33180
|
-
const subcommand = process.argv
|
|
33828
|
+
const { subcommand, client } = parseRunnerArgs(process.argv.slice(2));
|
|
33829
|
+
const isAntigravity = client === "antigravity";
|
|
33830
|
+
const finish = (code) => {
|
|
33831
|
+
if (isAntigravity) {
|
|
33832
|
+
finishAntigravityRun(subcommand);
|
|
33833
|
+
process.exit(0);
|
|
33834
|
+
}
|
|
33835
|
+
process.exit(code);
|
|
33836
|
+
};
|
|
33837
|
+
if (isAntigravity) {
|
|
33838
|
+
let crashed = false;
|
|
33839
|
+
const onCrash = (e) => {
|
|
33840
|
+
if (crashed) return;
|
|
33841
|
+
crashed = true;
|
|
33842
|
+
try {
|
|
33843
|
+
const msg = e instanceof Error ? e.stack || e.message : String(e);
|
|
33844
|
+
process.stderr.write(`[vibedefend hook] ${subcommand}: ${msg}
|
|
33845
|
+
`);
|
|
33846
|
+
} catch {
|
|
33847
|
+
}
|
|
33848
|
+
finish(0);
|
|
33849
|
+
};
|
|
33850
|
+
process.on("uncaughtException", onCrash);
|
|
33851
|
+
process.on("unhandledRejection", onCrash);
|
|
33852
|
+
}
|
|
33181
33853
|
try {
|
|
33182
33854
|
switch (subcommand) {
|
|
33183
33855
|
case "fetch-rules":
|
|
@@ -33195,6 +33867,9 @@ async function main() {
|
|
|
33195
33867
|
case "user-prompt-submit":
|
|
33196
33868
|
await userPromptSubmitHook();
|
|
33197
33869
|
break;
|
|
33870
|
+
case "pre-invocation":
|
|
33871
|
+
await preInvocationHook();
|
|
33872
|
+
break;
|
|
33198
33873
|
case "flush-violations":
|
|
33199
33874
|
await runViolationsFlush();
|
|
33200
33875
|
break;
|
|
@@ -33202,21 +33877,21 @@ async function main() {
|
|
|
33202
33877
|
case "pre-tool-use":
|
|
33203
33878
|
case "PreToolUse": {
|
|
33204
33879
|
const code = await runPreToolUseGuard();
|
|
33205
|
-
|
|
33880
|
+
finish(code);
|
|
33206
33881
|
return;
|
|
33207
33882
|
}
|
|
33208
33883
|
case "":
|
|
33209
33884
|
case "--help":
|
|
33210
33885
|
case "-h":
|
|
33211
33886
|
process.stderr.write(
|
|
33212
|
-
"Usage: hook-runner.js <fetch-rules|session-start|session-review|pre-compact|user-prompt-submit|guard-check
|
|
33887
|
+
"Usage: hook-runner.js <fetch-rules|session-start|session-review|pre-compact|user-prompt-submit|pre-invocation|guard-check> [--client antigravity]\n"
|
|
33213
33888
|
);
|
|
33214
|
-
|
|
33889
|
+
finish(subcommand === "" ? 1 : 0);
|
|
33215
33890
|
return;
|
|
33216
33891
|
default:
|
|
33217
33892
|
process.stderr.write(`Unknown subcommand: ${subcommand}
|
|
33218
33893
|
`);
|
|
33219
|
-
|
|
33894
|
+
finish(1);
|
|
33220
33895
|
return;
|
|
33221
33896
|
}
|
|
33222
33897
|
} catch (e) {
|
|
@@ -33224,6 +33899,6 @@ async function main() {
|
|
|
33224
33899
|
process.stderr.write(`[vibedefend hook] ${subcommand}: ${msg}
|
|
33225
33900
|
`);
|
|
33226
33901
|
}
|
|
33227
|
-
|
|
33902
|
+
finish(0);
|
|
33228
33903
|
}
|
|
33229
33904
|
main();
|