@cybedefend/vibedefend 1.4.7 → 1.5.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 +10 -0
- package/dist/hook-runner.js +319 -114
- package/dist/hooks/runtime/emit.js +40 -0
- package/dist/hooks/runtime/emit.js.map +1 -1
- package/dist/hooks/runtime/fetch-rules.js +6 -1
- package/dist/hooks/runtime/fetch-rules.js.map +1 -1
- package/dist/hooks/runtime/pre-compact.js +9 -0
- package/dist/hooks/runtime/pre-compact.js.map +1 -1
- package/dist/hooks/runtime/resolve.js +18 -9
- package/dist/hooks/runtime/resolve.js.map +1 -1
- package/dist/hooks/runtime/session-activation.js +222 -0
- package/dist/hooks/runtime/session-activation.js.map +1 -0
- package/dist/hooks/runtime/session-review.js +13 -3
- package/dist/hooks/runtime/session-review.js.map +1 -1
- package/dist/hooks/runtime/session-start.js +33 -3
- package/dist/hooks/runtime/session-start.js.map +1 -1
- package/dist/hooks/runtime/user-prompt-submit.js +6 -1
- package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
- package/dist/login.js +22 -3
- package/dist/login.js.map +1 -1
- package/package.json +1 -1
package/dist/hook-runner.js
CHANGED
|
@@ -5764,26 +5764,34 @@ async function resolveProjectIdWithApi(cwd = process.cwd(), deps = {}) {
|
|
|
5764
5764
|
const resolveSync = deps.resolveSync ?? resolveProjectId;
|
|
5765
5765
|
const base = resolveSync(cwd);
|
|
5766
5766
|
if (base.projectId) return base;
|
|
5767
|
+
let repository;
|
|
5768
|
+
const none = (inactiveReason) => ({
|
|
5769
|
+
...base,
|
|
5770
|
+
inactiveReason,
|
|
5771
|
+
...repository ? { repository } : {}
|
|
5772
|
+
});
|
|
5767
5773
|
try {
|
|
5768
5774
|
const getOrigin = deps.getOrigin ?? getOriginRemote;
|
|
5769
5775
|
const originUrl = getOrigin(cwd);
|
|
5770
|
-
if (!originUrl) return
|
|
5776
|
+
if (!originUrl) return none("no-git-origin");
|
|
5771
5777
|
const remote = parseRemoteUrl(originUrl);
|
|
5772
|
-
if (!remote
|
|
5778
|
+
if (!remote) return none("unsupported-remote");
|
|
5779
|
+
repository = `${remote.host}/${remote.slug}`;
|
|
5780
|
+
if (remote.provider === null) return none("unsupported-remote");
|
|
5773
5781
|
const key = `${remote.provider}:${remote.host}:${remote.slug}`;
|
|
5774
5782
|
const cached = getCachedRepoLink(key, deps.cacheDeps);
|
|
5775
5783
|
if (cached.kind === "positive") {
|
|
5776
5784
|
return { projectId: cached.projectId, apiBase: base.apiBase };
|
|
5777
5785
|
}
|
|
5778
5786
|
if (cached.kind === "negative") {
|
|
5779
|
-
return
|
|
5787
|
+
return none("no-linked-project");
|
|
5780
5788
|
}
|
|
5781
5789
|
const config = (deps.loadConfig ?? loadRuntimeConfig)();
|
|
5782
|
-
if (!config) return
|
|
5790
|
+
if (!config) return none("lookup-failed");
|
|
5783
5791
|
const apiBase = base.apiBase ?? config.region.apiBase;
|
|
5784
5792
|
const resolveTokenFn = deps.resolveTokenFn ?? resolveTokenWithRefresh;
|
|
5785
5793
|
const token = await resolveTokenFn(config.region.mcpName);
|
|
5786
|
-
if (!token) return
|
|
5794
|
+
if (!token) return none("not-signed-in");
|
|
5787
5795
|
const resolveByRepo = deps.resolveByRepo ?? resolveProjectByRepository;
|
|
5788
5796
|
const matches = await resolveByRepo(
|
|
5789
5797
|
apiBase,
|
|
@@ -5791,7 +5799,7 @@ async function resolveProjectIdWithApi(cwd = process.cwd(), deps = {}) {
|
|
|
5791
5799
|
{ provider: remote.provider, slug: remote.slug, host: remote.host },
|
|
5792
5800
|
{ timeoutMs: deps.timeoutMs ?? RESOLVE_API_TIMEOUT_MS }
|
|
5793
5801
|
);
|
|
5794
|
-
if (matches === null) return
|
|
5802
|
+
if (matches === null) return none("lookup-failed");
|
|
5795
5803
|
if (matches.length === 1 && matches[0].vibedefendEnabled !== false) {
|
|
5796
5804
|
const m = matches[0];
|
|
5797
5805
|
writeCachedRepoLink(
|
|
@@ -5802,9 +5810,9 @@ async function resolveProjectIdWithApi(cwd = process.cwd(), deps = {}) {
|
|
|
5802
5810
|
return { projectId: m.projectId, apiBase: base.apiBase };
|
|
5803
5811
|
}
|
|
5804
5812
|
writeCachedRepoLink(key, { negative: true }, deps.cacheDeps);
|
|
5805
|
-
return
|
|
5813
|
+
return none("no-linked-project");
|
|
5806
5814
|
} catch {
|
|
5807
|
-
return
|
|
5815
|
+
return none("lookup-failed");
|
|
5808
5816
|
}
|
|
5809
5817
|
}
|
|
5810
5818
|
|
|
@@ -6064,6 +6072,12 @@ async function fetchProposalsCount(opts) {
|
|
|
6064
6072
|
return { total, raw: body };
|
|
6065
6073
|
}
|
|
6066
6074
|
|
|
6075
|
+
// src/hooks/runtime/session-activation.ts
|
|
6076
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
|
|
6077
|
+
import { homedir as homedir7 } from "node:os";
|
|
6078
|
+
import { dirname as dirname4, isAbsolute as isAbsolute2, join as join6, resolve as resolvePath2 } from "node:path";
|
|
6079
|
+
import { fileURLToPath } from "node:url";
|
|
6080
|
+
|
|
6067
6081
|
// src/hooks/runtime/emit.ts
|
|
6068
6082
|
var ENVELOPE_CLIENTS = {
|
|
6069
6083
|
SessionStart: /* @__PURE__ */ new Set(["codex"]),
|
|
@@ -6084,6 +6098,10 @@ function emit(body, client) {
|
|
|
6084
6098
|
}
|
|
6085
6099
|
function emitContext(body, client, hookEventName) {
|
|
6086
6100
|
if (!body) return;
|
|
6101
|
+
if (client === "cursor" && hookEventName === "SessionStart") {
|
|
6102
|
+
process.stdout.write(JSON.stringify({ additional_context: body }) + "\n");
|
|
6103
|
+
return;
|
|
6104
|
+
}
|
|
6087
6105
|
if (ENVELOPE_CLIENTS[hookEventName].has(client)) {
|
|
6088
6106
|
const payload = JSON.stringify({
|
|
6089
6107
|
hookSpecificOutput: {
|
|
@@ -6096,6 +6114,25 @@ function emitContext(body, client, hookEventName) {
|
|
|
6096
6114
|
}
|
|
6097
6115
|
emit(body, client);
|
|
6098
6116
|
}
|
|
6117
|
+
var SYSTEM_MESSAGE_CLIENTS = /* @__PURE__ */ new Set([
|
|
6118
|
+
"claude-code",
|
|
6119
|
+
"codex"
|
|
6120
|
+
]);
|
|
6121
|
+
function emitSessionNotice(notice, client) {
|
|
6122
|
+
if (SYSTEM_MESSAGE_CLIENTS.has(client)) {
|
|
6123
|
+
process.stdout.write(
|
|
6124
|
+
JSON.stringify({
|
|
6125
|
+
systemMessage: notice.userMessage,
|
|
6126
|
+
hookSpecificOutput: {
|
|
6127
|
+
hookEventName: "SessionStart",
|
|
6128
|
+
additionalContext: notice.modelContext
|
|
6129
|
+
}
|
|
6130
|
+
}) + "\n"
|
|
6131
|
+
);
|
|
6132
|
+
return;
|
|
6133
|
+
}
|
|
6134
|
+
emitContext(notice.modelContext, client, "SessionStart");
|
|
6135
|
+
}
|
|
6099
6136
|
function emitStop(body, client, reason) {
|
|
6100
6137
|
if (!body) return;
|
|
6101
6138
|
if (client === "claude-code") {
|
|
@@ -6110,6 +6147,143 @@ function emitStop(body, client, reason) {
|
|
|
6110
6147
|
emit(body, client);
|
|
6111
6148
|
}
|
|
6112
6149
|
|
|
6150
|
+
// src/hooks/runtime/session-activation.ts
|
|
6151
|
+
var SETTLED_REASONS = /* @__PURE__ */ new Set([
|
|
6152
|
+
"no-git-origin",
|
|
6153
|
+
"unsupported-remote",
|
|
6154
|
+
"no-linked-project"
|
|
6155
|
+
]);
|
|
6156
|
+
function isSettledReason(reason) {
|
|
6157
|
+
return SETTLED_REASONS.has(reason);
|
|
6158
|
+
}
|
|
6159
|
+
var SESSIONS_CAP = 200;
|
|
6160
|
+
function defaultStoreFile() {
|
|
6161
|
+
const dir = process.env.CYBEDEFEND_BASELINE_DIR ?? join6(homedir7(), ".cybedefend");
|
|
6162
|
+
return join6(dir, "inactive-sessions.json");
|
|
6163
|
+
}
|
|
6164
|
+
function defaultInactiveSessionStore(file = defaultStoreFile(), now = Date.now) {
|
|
6165
|
+
function load() {
|
|
6166
|
+
if (!existsSync8(file)) return {};
|
|
6167
|
+
try {
|
|
6168
|
+
const parsed = JSON.parse(readFileSync7(file, "utf8"));
|
|
6169
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
6170
|
+
} catch {
|
|
6171
|
+
return {};
|
|
6172
|
+
}
|
|
6173
|
+
}
|
|
6174
|
+
function save(map) {
|
|
6175
|
+
try {
|
|
6176
|
+
mkdirSync5(dirname4(file), { recursive: true });
|
|
6177
|
+
writeFileSync4(file, JSON.stringify(map) + "\n", "utf8");
|
|
6178
|
+
} catch {
|
|
6179
|
+
}
|
|
6180
|
+
}
|
|
6181
|
+
return {
|
|
6182
|
+
get(sessionId) {
|
|
6183
|
+
const rec = load()[sessionId];
|
|
6184
|
+
if (!rec || typeof rec !== "object" || typeof rec.cwd !== "string" || typeof rec.reason !== "string") {
|
|
6185
|
+
return null;
|
|
6186
|
+
}
|
|
6187
|
+
return rec;
|
|
6188
|
+
},
|
|
6189
|
+
mark(sessionId, record) {
|
|
6190
|
+
const map = load();
|
|
6191
|
+
map[sessionId] = { ...record, at: now() };
|
|
6192
|
+
const entries = Object.entries(map);
|
|
6193
|
+
if (entries.length > SESSIONS_CAP) {
|
|
6194
|
+
entries.sort(([, a], [, b]) => (a.at ?? 0) - (b.at ?? 0));
|
|
6195
|
+
save(Object.fromEntries(entries.slice(-SESSIONS_CAP)));
|
|
6196
|
+
return;
|
|
6197
|
+
}
|
|
6198
|
+
save(map);
|
|
6199
|
+
},
|
|
6200
|
+
clear(sessionId) {
|
|
6201
|
+
const map = load();
|
|
6202
|
+
if (!(sessionId in map)) return;
|
|
6203
|
+
delete map[sessionId];
|
|
6204
|
+
save(map);
|
|
6205
|
+
}
|
|
6206
|
+
};
|
|
6207
|
+
}
|
|
6208
|
+
function sessionIdOf(stdin) {
|
|
6209
|
+
for (const key of ["session_id", "sessionId", "conversation_id", "trajectory_id"]) {
|
|
6210
|
+
const v = stdin[key];
|
|
6211
|
+
if (typeof v === "string" && v.length > 0) return v;
|
|
6212
|
+
}
|
|
6213
|
+
return null;
|
|
6214
|
+
}
|
|
6215
|
+
function sessionFolderOf(stdin, client, env = process.env) {
|
|
6216
|
+
const candidates = [];
|
|
6217
|
+
if (client === "cursor") {
|
|
6218
|
+
const roots = stdin.workspace_roots;
|
|
6219
|
+
if (Array.isArray(roots)) candidates.push(roots[0]);
|
|
6220
|
+
candidates.push(env.CURSOR_PROJECT_DIR);
|
|
6221
|
+
}
|
|
6222
|
+
candidates.push(stdin.cwd);
|
|
6223
|
+
for (const c of candidates) {
|
|
6224
|
+
const folder = absoluteFolder(c);
|
|
6225
|
+
if (folder) return folder;
|
|
6226
|
+
}
|
|
6227
|
+
return process.cwd();
|
|
6228
|
+
}
|
|
6229
|
+
function absoluteFolder(value) {
|
|
6230
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
6231
|
+
let p = value;
|
|
6232
|
+
if (p.startsWith("file://")) {
|
|
6233
|
+
try {
|
|
6234
|
+
p = fileURLToPath(p);
|
|
6235
|
+
} catch {
|
|
6236
|
+
return null;
|
|
6237
|
+
}
|
|
6238
|
+
}
|
|
6239
|
+
return isAbsolute2(p) ? resolvePath2(p) : null;
|
|
6240
|
+
}
|
|
6241
|
+
function isSessionInactive(stdin, deps = {}) {
|
|
6242
|
+
try {
|
|
6243
|
+
const sessionId = sessionIdOf(stdin);
|
|
6244
|
+
if (!sessionId) return false;
|
|
6245
|
+
const record = (deps.store ?? defaultInactiveSessionStore()).get(sessionId);
|
|
6246
|
+
if (!record || !isSettledReason(record.reason)) return false;
|
|
6247
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
6248
|
+
if (record.cwd !== cwd) return false;
|
|
6249
|
+
const resolveSync = deps.resolveSync ?? resolveProjectId;
|
|
6250
|
+
return !resolveSync(cwd).projectId;
|
|
6251
|
+
} catch {
|
|
6252
|
+
return false;
|
|
6253
|
+
}
|
|
6254
|
+
}
|
|
6255
|
+
function whyInactive(reason, repository) {
|
|
6256
|
+
const repo = repository ? `\`${repository}\`` : "this folder";
|
|
6257
|
+
switch (reason) {
|
|
6258
|
+
case "no-git-origin":
|
|
6259
|
+
return "this folder has no `.cybedefend/config.json` and no GitHub or GitLab `origin` remote";
|
|
6260
|
+
case "unsupported-remote":
|
|
6261
|
+
return `this folder has no \`.cybedefend/config.json\` and its git \`origin\`${repository ? ` (${repo})` : ""} is not on GitHub or GitLab`;
|
|
6262
|
+
case "no-linked-project":
|
|
6263
|
+
return `this folder has no \`.cybedefend/config.json\` and no CybeDefend project with VibeDefend enabled matches ${repo}`;
|
|
6264
|
+
case "not-signed-in":
|
|
6265
|
+
return `you are not signed in, so the CybeDefend project for ${repo} could not be looked up`;
|
|
6266
|
+
case "lookup-failed":
|
|
6267
|
+
return `the CybeDefend API did not answer, so the project for ${repo} could not be looked up`;
|
|
6268
|
+
}
|
|
6269
|
+
}
|
|
6270
|
+
function composeInactiveNotice(reason, repository, client) {
|
|
6271
|
+
const why = whyInactive(reason, repository);
|
|
6272
|
+
const settled = isSettledReason(reason);
|
|
6273
|
+
const userMessage = settled ? `\u{1F6E1}\uFE0F CybeDefend is off for this session: ${why}. Run \`vibedefend link\` in this folder to turn it on.` : reason === "not-signed-in" ? `\u{1F6E1}\uFE0F CybeDefend is off for now: ${why}. Run \`vibedefend login\` to turn it on.` : `\u{1F6E1}\uFE0F CybeDefend is off for now: ${why}. It will try again on the next prompt or edit.`;
|
|
6274
|
+
const scope = settled ? "- Its hooks stay off until this session ends: no rules fetch, no proposal inbox, no Action Guards, no end-of-session review." : "- Its hooks stay quiet until the project can be found.";
|
|
6275
|
+
const relay = SYSTEM_MESSAGE_CLIENTS.has(client) ? "- The user has already been shown this notice; do not repeat it." : "- Tell the user once, in one short line, that CybeDefend is off for this session and why.";
|
|
6276
|
+
const modelContext = [
|
|
6277
|
+
"## CybeDefend is not active in this session",
|
|
6278
|
+
`CybeDefend found no project for this folder: ${why}.`,
|
|
6279
|
+
scope,
|
|
6280
|
+
"- Do not call CybeDefend MCP tools, run the CybeDefend workflow or ask for a CybeDefend project id unless the user asks about CybeDefend.",
|
|
6281
|
+
relay,
|
|
6282
|
+
""
|
|
6283
|
+
].join("\n");
|
|
6284
|
+
return { userMessage, modelContext };
|
|
6285
|
+
}
|
|
6286
|
+
|
|
6113
6287
|
// src/hooks/runtime/fetch-rules.ts
|
|
6114
6288
|
function emitPreToolUseContext(body, client) {
|
|
6115
6289
|
emitContext(body, client, "PreToolUse");
|
|
@@ -6136,7 +6310,9 @@ async function fetchRulesHook(deps = {}) {
|
|
|
6136
6310
|
if (!event.filePath) return;
|
|
6137
6311
|
const config = loadConfig();
|
|
6138
6312
|
if (!config) return;
|
|
6139
|
-
const
|
|
6313
|
+
const folder = sessionFolderOf(stdin, event.client);
|
|
6314
|
+
if (isSessionInactive(stdin, { store: deps.sessionStore, cwd: folder })) return;
|
|
6315
|
+
const { projectId, apiBase: configApiBase } = await resolveProject(folder);
|
|
6140
6316
|
if (!projectId) return;
|
|
6141
6317
|
const apiBase = process.env.CYBEDEFEND_API_BASE ?? configApiBase ?? config.region.apiBase;
|
|
6142
6318
|
const token = resolveTok(config.region.mcpName, {
|
|
@@ -6146,7 +6322,7 @@ async function fetchRulesHook(deps = {}) {
|
|
|
6146
6322
|
const intent = buildIntent(event);
|
|
6147
6323
|
const files = event.filePaths.length > 0 ? event.filePaths : [event.filePath];
|
|
6148
6324
|
const fileLabel = files.join(", ");
|
|
6149
|
-
const sessionId =
|
|
6325
|
+
const sessionId = sessionIdOf2(stdin);
|
|
6150
6326
|
const usageNotices = [];
|
|
6151
6327
|
const onUsageSignal = (signal) => {
|
|
6152
6328
|
const sentence = signal.kind === "blocked" ? usageNotifier.notifyBlock(sessionId, signal.block) : usageNotifier.notifyWarning(sessionId, signal.warning);
|
|
@@ -6190,7 +6366,7 @@ async function fetchRulesHook(deps = {}) {
|
|
|
6190
6366
|
}
|
|
6191
6367
|
if (blocks.length > 0) emitFn(blocks.join("\n"), event.client);
|
|
6192
6368
|
}
|
|
6193
|
-
function
|
|
6369
|
+
function sessionIdOf2(stdin) {
|
|
6194
6370
|
if (typeof stdin.session_id === "string" && stdin.session_id) return stdin.session_id;
|
|
6195
6371
|
if (typeof stdin.sessionId === "string" && stdin.sessionId) return stdin.sessionId;
|
|
6196
6372
|
return void 0;
|
|
@@ -6275,9 +6451,9 @@ var DIRECT_PROPOSE_DIRECTIVES = {
|
|
|
6275
6451
|
|
|
6276
6452
|
// src/hooks/runtime/self-update-check.ts
|
|
6277
6453
|
import { spawn } from "node:child_process";
|
|
6278
|
-
import { existsSync as
|
|
6279
|
-
import { homedir as
|
|
6280
|
-
import { join as
|
|
6454
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8, rmSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
6455
|
+
import { homedir as homedir8 } from "node:os";
|
|
6456
|
+
import { join as join7 } from "node:path";
|
|
6281
6457
|
|
|
6282
6458
|
// src/hooks/runtime/semver.ts
|
|
6283
6459
|
function parseVersion(input) {
|
|
@@ -6304,8 +6480,8 @@ function isNewer(latest, current) {
|
|
|
6304
6480
|
}
|
|
6305
6481
|
|
|
6306
6482
|
// src/self-update.ts
|
|
6307
|
-
import { fileURLToPath } from "node:url";
|
|
6308
|
-
import { existsSync as
|
|
6483
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
6484
|
+
import { existsSync as existsSync9, realpathSync } from "node:fs";
|
|
6309
6485
|
var GLOBAL_MODES = /* @__PURE__ */ new Set([
|
|
6310
6486
|
"npm-global",
|
|
6311
6487
|
"pnpm-global",
|
|
@@ -6333,14 +6509,14 @@ function detectInstallMode(scriptPath) {
|
|
|
6333
6509
|
}
|
|
6334
6510
|
function resolveScriptPath() {
|
|
6335
6511
|
const fromArgv = process.argv[1];
|
|
6336
|
-
if (fromArgv &&
|
|
6512
|
+
if (fromArgv && existsSync9(fromArgv)) {
|
|
6337
6513
|
try {
|
|
6338
6514
|
return realpathSync(fromArgv);
|
|
6339
6515
|
} catch {
|
|
6340
6516
|
return fromArgv;
|
|
6341
6517
|
}
|
|
6342
6518
|
}
|
|
6343
|
-
return
|
|
6519
|
+
return fileURLToPath2(import.meta.url);
|
|
6344
6520
|
}
|
|
6345
6521
|
|
|
6346
6522
|
// src/hooks/runtime/self-update-check.ts
|
|
@@ -6355,9 +6531,9 @@ function isValidRegistryVersion(value) {
|
|
|
6355
6531
|
}
|
|
6356
6532
|
async function selfUpdateCheck(deps) {
|
|
6357
6533
|
const now = deps.now ?? (() => Date.now());
|
|
6358
|
-
const dir = deps.cybeDir ??
|
|
6359
|
-
const throttlePath =
|
|
6360
|
-
const logPath =
|
|
6534
|
+
const dir = deps.cybeDir ?? join7(process.env.CYBEDEFEND_HOME ?? homedir8(), ".cybedefend");
|
|
6535
|
+
const throttlePath = join7(dir, "update-check.json");
|
|
6536
|
+
const logPath = join7(dir, "last-update.log");
|
|
6361
6537
|
const installMode = deps.installMode ?? (deps.runnerSource ? detectInstallMode(deps.runnerSource) : detectInstallMode(resolveScriptPath()));
|
|
6362
6538
|
const priorFailure = takeUpdateLogNotice(logPath);
|
|
6363
6539
|
const throttle = readThrottle(throttlePath);
|
|
@@ -6390,8 +6566,8 @@ function applyOrNotify(deps, installMode, latest, logPath) {
|
|
|
6390
6566
|
}
|
|
6391
6567
|
function readThrottle(path) {
|
|
6392
6568
|
try {
|
|
6393
|
-
if (!
|
|
6394
|
-
const data = JSON.parse(
|
|
6569
|
+
if (!existsSync10(path)) return null;
|
|
6570
|
+
const data = JSON.parse(readFileSync8(path, "utf8"));
|
|
6395
6571
|
if (typeof data.lastCheckedAt !== "number") return null;
|
|
6396
6572
|
return { lastCheckedAt: data.lastCheckedAt };
|
|
6397
6573
|
} catch {
|
|
@@ -6401,16 +6577,16 @@ function readThrottle(path) {
|
|
|
6401
6577
|
function writeThrottle(path, throttle) {
|
|
6402
6578
|
try {
|
|
6403
6579
|
ensureDirFor(path);
|
|
6404
|
-
|
|
6580
|
+
writeFileSync5(path, JSON.stringify(throttle) + "\n");
|
|
6405
6581
|
} catch {
|
|
6406
6582
|
}
|
|
6407
6583
|
}
|
|
6408
6584
|
function takeUpdateLogNotice(logPath) {
|
|
6409
6585
|
try {
|
|
6410
|
-
if (!
|
|
6586
|
+
if (!existsSync10(logPath)) return null;
|
|
6411
6587
|
let parsed = {};
|
|
6412
6588
|
try {
|
|
6413
|
-
parsed = JSON.parse(
|
|
6589
|
+
parsed = JSON.parse(readFileSync8(logPath, "utf8"));
|
|
6414
6590
|
} catch {
|
|
6415
6591
|
parsed = {};
|
|
6416
6592
|
}
|
|
@@ -6485,18 +6661,18 @@ function pmCommand(mode, spec) {
|
|
|
6485
6661
|
|
|
6486
6662
|
// src/hooks/runtime/hook-refresh-trigger.ts
|
|
6487
6663
|
import { spawn as spawn2 } from "node:child_process";
|
|
6488
|
-
import { existsSync as
|
|
6489
|
-
import { homedir as
|
|
6490
|
-
import { dirname as
|
|
6664
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
6665
|
+
import { homedir as homedir9 } from "node:os";
|
|
6666
|
+
import { dirname as dirname5, join as join8 } from "node:path";
|
|
6491
6667
|
function maybeRefreshStaleWiring(deps) {
|
|
6492
6668
|
try {
|
|
6493
6669
|
const { config, runnerVersion } = deps;
|
|
6494
6670
|
if (!config.runnerSource || config.installedVersion === runnerVersion) {
|
|
6495
6671
|
return false;
|
|
6496
6672
|
}
|
|
6497
|
-
const cliEntry =
|
|
6498
|
-
if (!(deps.exists ??
|
|
6499
|
-
const markerPath = deps.markerPath ??
|
|
6673
|
+
const cliEntry = join8(dirname5(dirname5(config.runnerSource)), "bin", "vibedefend.js");
|
|
6674
|
+
if (!(deps.exists ?? existsSync11)(cliEntry)) return false;
|
|
6675
|
+
const markerPath = deps.markerPath ?? join8(process.env.CYBEDEFEND_HOME ?? homedir9(), ".cybedefend", "hook-refresh.json");
|
|
6500
6676
|
if (readMarkerVersion(markerPath) === runnerVersion) return false;
|
|
6501
6677
|
(deps.spawnRefresh ?? defaultSpawnRefresh)(cliEntry);
|
|
6502
6678
|
writeMarker(markerPath, runnerVersion);
|
|
@@ -6507,8 +6683,8 @@ function maybeRefreshStaleWiring(deps) {
|
|
|
6507
6683
|
}
|
|
6508
6684
|
function readMarkerVersion(path) {
|
|
6509
6685
|
try {
|
|
6510
|
-
if (!
|
|
6511
|
-
const data = JSON.parse(
|
|
6686
|
+
if (!existsSync11(path)) return null;
|
|
6687
|
+
const data = JSON.parse(readFileSync9(path, "utf8"));
|
|
6512
6688
|
return typeof data.version === "string" ? data.version : null;
|
|
6513
6689
|
} catch {
|
|
6514
6690
|
return null;
|
|
@@ -6517,7 +6693,7 @@ function readMarkerVersion(path) {
|
|
|
6517
6693
|
function writeMarker(path, version) {
|
|
6518
6694
|
try {
|
|
6519
6695
|
ensureDirFor(path);
|
|
6520
|
-
|
|
6696
|
+
writeFileSync6(path, JSON.stringify({ version, spawnedAt: Date.now() }) + "\n");
|
|
6521
6697
|
} catch {
|
|
6522
6698
|
}
|
|
6523
6699
|
}
|
|
@@ -6531,18 +6707,18 @@ function defaultSpawnRefresh(cliEntry) {
|
|
|
6531
6707
|
}
|
|
6532
6708
|
|
|
6533
6709
|
// src/version.ts
|
|
6534
|
-
import { readFileSync as
|
|
6535
|
-
import { fileURLToPath as
|
|
6536
|
-
import { dirname as
|
|
6710
|
+
import { readFileSync as readFileSync10 } from "node:fs";
|
|
6711
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6712
|
+
import { dirname as dirname6, join as join9 } from "node:path";
|
|
6537
6713
|
var PKG_NAME = "@cybedefend/vibedefend";
|
|
6538
6714
|
function defaultPkgPath() {
|
|
6539
|
-
return
|
|
6715
|
+
return join9(dirname6(fileURLToPath3(import.meta.url)), "..", "package.json");
|
|
6540
6716
|
}
|
|
6541
6717
|
function readPackageMeta(opts = {}) {
|
|
6542
6718
|
if (typeof opts.bakedVersion === "string" && opts.bakedVersion.length > 0) {
|
|
6543
6719
|
return { name: PKG_NAME, version: opts.bakedVersion };
|
|
6544
6720
|
}
|
|
6545
|
-
const readFile = opts.readFile ?? ((p) =>
|
|
6721
|
+
const readFile = opts.readFile ?? ((p) => readFileSync10(p, "utf8"));
|
|
6546
6722
|
const pkgPath = opts.pkgPath ?? defaultPkgPath();
|
|
6547
6723
|
try {
|
|
6548
6724
|
return JSON.parse(readFile(pkgPath));
|
|
@@ -6551,13 +6727,22 @@ function readPackageMeta(opts = {}) {
|
|
|
6551
6727
|
}
|
|
6552
6728
|
}
|
|
6553
6729
|
var pkg = readPackageMeta({
|
|
6554
|
-
bakedVersion: true ? "1.
|
|
6730
|
+
bakedVersion: true ? "1.5.0" : void 0
|
|
6555
6731
|
});
|
|
6556
6732
|
|
|
6557
6733
|
// src/hooks/runtime/session-start.ts
|
|
6558
6734
|
function emitSessionStartContext(body, client) {
|
|
6559
6735
|
emitContext(body, client, "SessionStart");
|
|
6560
6736
|
}
|
|
6737
|
+
function announceInactive(resolution, sessionId, cwd, store, client, emitNoticeFn) {
|
|
6738
|
+
const reason = resolution.inactiveReason ?? "no-linked-project";
|
|
6739
|
+
if (sessionId) {
|
|
6740
|
+
const prior = store.get(sessionId);
|
|
6741
|
+
if (prior && prior.cwd === cwd && prior.reason === reason) return;
|
|
6742
|
+
store.mark(sessionId, { cwd, reason });
|
|
6743
|
+
}
|
|
6744
|
+
emitNoticeFn(composeInactiveNotice(reason, resolution.repository, client), client);
|
|
6745
|
+
}
|
|
6561
6746
|
async function sessionStartHook(deps = {}) {
|
|
6562
6747
|
const readStdin = deps.readStdin ?? readStdinJson;
|
|
6563
6748
|
const loadConfig = deps.loadConfig ?? loadRuntimeConfig;
|
|
@@ -6566,6 +6751,7 @@ async function sessionStartHook(deps = {}) {
|
|
|
6566
6751
|
const fetchProposals = deps.fetchProposalsFn ?? fetchProposalsCount;
|
|
6567
6752
|
const selfUpdateCheckFn = deps.selfUpdateCheckFn ?? selfUpdateCheck;
|
|
6568
6753
|
const emitFn = deps.emitFn ?? emitSessionStartContext;
|
|
6754
|
+
const emitNoticeFn = deps.emitNoticeFn ?? emitSessionNotice;
|
|
6569
6755
|
const stdin = await readStdin();
|
|
6570
6756
|
const event = sniff(stdin);
|
|
6571
6757
|
const config = loadConfig();
|
|
@@ -6574,8 +6760,16 @@ async function sessionStartHook(deps = {}) {
|
|
|
6574
6760
|
config,
|
|
6575
6761
|
runnerVersion: pkg.version
|
|
6576
6762
|
});
|
|
6577
|
-
const
|
|
6578
|
-
|
|
6763
|
+
const folder = sessionFolderOf(stdin, event.client);
|
|
6764
|
+
const resolution = await resolveProject(folder);
|
|
6765
|
+
const { projectId, apiBase: configApiBase } = resolution;
|
|
6766
|
+
const sessionStore = deps.sessionStore ?? defaultInactiveSessionStore();
|
|
6767
|
+
const sessionId = sessionIdOf(stdin);
|
|
6768
|
+
if (!projectId) {
|
|
6769
|
+
announceInactive(resolution, sessionId, folder, sessionStore, event.client, emitNoticeFn);
|
|
6770
|
+
return;
|
|
6771
|
+
}
|
|
6772
|
+
if (sessionId) sessionStore.clear(sessionId);
|
|
6579
6773
|
const apiBase = process.env.CYBEDEFEND_API_BASE ?? configApiBase ?? config.region.apiBase;
|
|
6580
6774
|
if (process.env.CYBEDEFEND_DRY_RUN === "1") {
|
|
6581
6775
|
emitFn(
|
|
@@ -6667,7 +6861,7 @@ async function sessionStartHook(deps = {}) {
|
|
|
6667
6861
|
}
|
|
6668
6862
|
|
|
6669
6863
|
// src/hooks/runtime/session-review.ts
|
|
6670
|
-
import { existsSync as
|
|
6864
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11 } from "node:fs";
|
|
6671
6865
|
var COUNTED_TOOLS = /* @__PURE__ */ new Set([
|
|
6672
6866
|
"Edit",
|
|
6673
6867
|
"Write",
|
|
@@ -6709,6 +6903,10 @@ async function sessionReviewHook(deps = {}) {
|
|
|
6709
6903
|
}
|
|
6710
6904
|
if (editCount === 0) return;
|
|
6711
6905
|
if (editCount < resolveReviewThreshold(config)) return;
|
|
6906
|
+
const folder = sessionFolderOf(stdin, event.client);
|
|
6907
|
+
if (isSessionInactive(stdin, { store: deps.sessionStore, cwd: folder })) return;
|
|
6908
|
+
const { projectId } = await (deps.resolveProject ?? resolveProjectIdWithApi)(folder);
|
|
6909
|
+
if (!projectId) return;
|
|
6712
6910
|
const userPrompt = extractFirstUserPrompt(transcript);
|
|
6713
6911
|
const proposalMode = resolveProposalMode(config);
|
|
6714
6912
|
let body = composeReviewBody(
|
|
@@ -6719,8 +6917,7 @@ async function sessionReviewHook(deps = {}) {
|
|
|
6719
6917
|
);
|
|
6720
6918
|
const withDiffScan = config.hooks.enableDiffScan !== false;
|
|
6721
6919
|
if (withDiffScan) {
|
|
6722
|
-
|
|
6723
|
-
body += "\n" + composeDiffScanBody(extractChangedFiles(transcript, void 0, cwd));
|
|
6920
|
+
body += "\n" + composeDiffScanBody(extractChangedFiles(transcript, void 0, folder));
|
|
6724
6921
|
}
|
|
6725
6922
|
emitFn(body, event.client, composeStopReason(withDiffScan, proposalMode));
|
|
6726
6923
|
}
|
|
@@ -6751,9 +6948,9 @@ function loadTranscript(stdin, readFile) {
|
|
|
6751
6948
|
return out;
|
|
6752
6949
|
}
|
|
6753
6950
|
function defaultReadTranscript(path) {
|
|
6754
|
-
if (!
|
|
6951
|
+
if (!existsSync12(path)) return null;
|
|
6755
6952
|
try {
|
|
6756
|
-
return
|
|
6953
|
+
return readFileSync11(path, "utf8");
|
|
6757
6954
|
} catch {
|
|
6758
6955
|
return null;
|
|
6759
6956
|
}
|
|
@@ -6986,6 +7183,10 @@ async function preCompactHook(deps = {}) {
|
|
|
6986
7183
|
const config = loadConfig();
|
|
6987
7184
|
if (!config) return;
|
|
6988
7185
|
if (!config.hooks.enableSessionReview) return;
|
|
7186
|
+
const folder = sessionFolderOf(stdin, event.client);
|
|
7187
|
+
if (isSessionInactive(stdin, { store: deps.sessionStore, cwd: folder })) return;
|
|
7188
|
+
const { projectId } = await (deps.resolveProject ?? resolveProjectIdWithApi)(folder);
|
|
7189
|
+
if (!projectId) return;
|
|
6989
7190
|
if (process.env.CYBEDEFEND_DRY_RUN === "1") {
|
|
6990
7191
|
emitFn(
|
|
6991
7192
|
`## \u{1F6E1}\uFE0F CybeDefend PreCompact (dry-run, client=${event.client})
|
|
@@ -7013,19 +7214,19 @@ async function preCompactHook(deps = {}) {
|
|
|
7013
7214
|
}
|
|
7014
7215
|
|
|
7015
7216
|
// src/hooks/runtime/user-prompt-submit.ts
|
|
7016
|
-
import { existsSync as
|
|
7017
|
-
import { homedir as
|
|
7018
|
-
import { join as
|
|
7019
|
-
var
|
|
7217
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
|
|
7218
|
+
import { homedir as homedir10 } from "node:os";
|
|
7219
|
+
import { join as join10 } from "node:path";
|
|
7220
|
+
var SESSIONS_CAP2 = 100;
|
|
7020
7221
|
function defaultSessionsFile() {
|
|
7021
|
-
const dir = process.env.CYBEDEFEND_BASELINE_DIR ??
|
|
7022
|
-
return
|
|
7222
|
+
const dir = process.env.CYBEDEFEND_BASELINE_DIR ?? join10(homedir10(), ".cybedefend");
|
|
7223
|
+
return join10(dir, "user-prompt-seen-sessions.json");
|
|
7023
7224
|
}
|
|
7024
7225
|
function defaultSessionTracker(file = defaultSessionsFile()) {
|
|
7025
7226
|
function load() {
|
|
7026
|
-
if (!
|
|
7227
|
+
if (!existsSync13(file)) return [];
|
|
7027
7228
|
try {
|
|
7028
|
-
const raw =
|
|
7229
|
+
const raw = readFileSync12(file, "utf8");
|
|
7029
7230
|
const data = JSON.parse(raw);
|
|
7030
7231
|
if (!Array.isArray(data.sessions)) return [];
|
|
7031
7232
|
return data.sessions.filter((s) => typeof s === "string");
|
|
@@ -7040,10 +7241,10 @@ function defaultSessionTracker(file = defaultSessionsFile()) {
|
|
|
7040
7241
|
async markSeen(sessionId) {
|
|
7041
7242
|
const existing = load();
|
|
7042
7243
|
if (existing.includes(sessionId)) return;
|
|
7043
|
-
const next = [...existing, sessionId].slice(-
|
|
7244
|
+
const next = [...existing, sessionId].slice(-SESSIONS_CAP2);
|
|
7044
7245
|
try {
|
|
7045
|
-
|
|
7046
|
-
|
|
7246
|
+
mkdirSync6(join10(file, ".."), { recursive: true });
|
|
7247
|
+
writeFileSync7(file, JSON.stringify({ sessions: next }), "utf8");
|
|
7047
7248
|
} catch {
|
|
7048
7249
|
}
|
|
7049
7250
|
}
|
|
@@ -7065,7 +7266,9 @@ async function userPromptSubmitHook(deps = {}) {
|
|
|
7065
7266
|
}
|
|
7066
7267
|
const config = loadConfig();
|
|
7067
7268
|
if (!config) return;
|
|
7068
|
-
const
|
|
7269
|
+
const folder = sessionFolderOf(stdin, event.client);
|
|
7270
|
+
if (isSessionInactive(stdin, { store: deps.sessionStore, cwd: folder })) return;
|
|
7271
|
+
const { projectId, apiBase: configApiBase } = await resolveProject(folder);
|
|
7069
7272
|
if (!projectId) return;
|
|
7070
7273
|
const apiBase = process.env.CYBEDEFEND_API_BASE ?? configApiBase ?? config.region.apiBase;
|
|
7071
7274
|
const token = resolveTok(config.region.mcpName, {
|
|
@@ -8114,10 +8317,10 @@ function nearMiss(req, rule) {
|
|
|
8114
8317
|
}
|
|
8115
8318
|
|
|
8116
8319
|
// src/hooks/runtime/guard-rules-cache.ts
|
|
8117
|
-
import { readFileSync as
|
|
8118
|
-
import { dirname as
|
|
8119
|
-
import { homedir as
|
|
8120
|
-
import { join as
|
|
8320
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, existsSync as existsSync14, mkdirSync as mkdirSync7 } from "node:fs";
|
|
8321
|
+
import { dirname as dirname7 } from "node:path";
|
|
8322
|
+
import { homedir as homedir11 } from "node:os";
|
|
8323
|
+
import { join as join11 } from "node:path";
|
|
8121
8324
|
|
|
8122
8325
|
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
8123
8326
|
var external_exports = {};
|
|
@@ -12229,8 +12432,8 @@ function parseRuleFields(raw) {
|
|
|
12229
12432
|
}
|
|
12230
12433
|
|
|
12231
12434
|
// src/hooks/runtime/guard-rules-cache.ts
|
|
12232
|
-
var DEFAULT_CACHE_FILE =
|
|
12233
|
-
|
|
12435
|
+
var DEFAULT_CACHE_FILE = join11(
|
|
12436
|
+
homedir11(),
|
|
12234
12437
|
".cybedefend",
|
|
12235
12438
|
"guards-cache.json"
|
|
12236
12439
|
);
|
|
@@ -12366,9 +12569,9 @@ function makeGuardRulesCache(opts) {
|
|
|
12366
12569
|
}
|
|
12367
12570
|
}
|
|
12368
12571
|
function readCache(projectId) {
|
|
12369
|
-
if (!
|
|
12572
|
+
if (!existsSync14(cacheFile)) return null;
|
|
12370
12573
|
try {
|
|
12371
|
-
const raw =
|
|
12574
|
+
const raw = readFileSync13(cacheFile, "utf8");
|
|
12372
12575
|
const data = JSON.parse(raw);
|
|
12373
12576
|
if (data.projectId !== projectId) return null;
|
|
12374
12577
|
return data;
|
|
@@ -12379,16 +12582,16 @@ function makeGuardRulesCache(opts) {
|
|
|
12379
12582
|
function writeCache(entry) {
|
|
12380
12583
|
try {
|
|
12381
12584
|
ensureDirFor2(cacheFile);
|
|
12382
|
-
|
|
12585
|
+
writeFileSync8(cacheFile, JSON.stringify(entry), "utf8");
|
|
12383
12586
|
} catch {
|
|
12384
12587
|
}
|
|
12385
12588
|
}
|
|
12386
12589
|
return { refreshIfStale };
|
|
12387
12590
|
}
|
|
12388
12591
|
function ensureDirFor2(filePath) {
|
|
12389
|
-
const dir =
|
|
12390
|
-
if (!
|
|
12391
|
-
|
|
12592
|
+
const dir = dirname7(filePath);
|
|
12593
|
+
if (!existsSync14(dir)) {
|
|
12594
|
+
mkdirSync7(dir, { recursive: true });
|
|
12392
12595
|
}
|
|
12393
12596
|
}
|
|
12394
12597
|
var DEFAULT_TIMEOUT_MS2 = 8e3;
|
|
@@ -12521,11 +12724,11 @@ function detectPromptInjection(text) {
|
|
|
12521
12724
|
}
|
|
12522
12725
|
|
|
12523
12726
|
// src/hooks/runtime/judge-cache.ts
|
|
12524
|
-
import { readFileSync as
|
|
12525
|
-
import { dirname as
|
|
12526
|
-
import { homedir as
|
|
12527
|
-
var DEFAULT_JUDGE_CACHE_FILE =
|
|
12528
|
-
|
|
12727
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, existsSync as existsSync15, mkdirSync as mkdirSync8 } from "node:fs";
|
|
12728
|
+
import { dirname as dirname8, join as join12 } from "node:path";
|
|
12729
|
+
import { homedir as homedir12 } from "node:os";
|
|
12730
|
+
var DEFAULT_JUDGE_CACHE_FILE = join12(
|
|
12731
|
+
homedir12(),
|
|
12529
12732
|
".cybedefend",
|
|
12530
12733
|
"guards-judge-cache.json"
|
|
12531
12734
|
);
|
|
@@ -12535,9 +12738,9 @@ function makeJudgeCache(opts = {}) {
|
|
|
12535
12738
|
const ttlMs = opts.ttlMs ?? DEFAULT_JUDGE_TTL_MS;
|
|
12536
12739
|
const now = opts.now ?? (() => Date.now());
|
|
12537
12740
|
function readAll() {
|
|
12538
|
-
if (!
|
|
12741
|
+
if (!existsSync15(cacheFile)) return {};
|
|
12539
12742
|
try {
|
|
12540
|
-
return JSON.parse(
|
|
12743
|
+
return JSON.parse(readFileSync14(cacheFile, "utf8"));
|
|
12541
12744
|
} catch {
|
|
12542
12745
|
return {};
|
|
12543
12746
|
}
|
|
@@ -12557,36 +12760,36 @@ function makeJudgeCache(opts = {}) {
|
|
|
12557
12760
|
}
|
|
12558
12761
|
all[key] = { res, at: t };
|
|
12559
12762
|
ensureDirFor3(cacheFile);
|
|
12560
|
-
|
|
12763
|
+
writeFileSync9(cacheFile, JSON.stringify(all), "utf8");
|
|
12561
12764
|
} catch {
|
|
12562
12765
|
}
|
|
12563
12766
|
}
|
|
12564
12767
|
return { get, set };
|
|
12565
12768
|
}
|
|
12566
12769
|
function ensureDirFor3(filePath) {
|
|
12567
|
-
const dir =
|
|
12568
|
-
if (!
|
|
12569
|
-
|
|
12770
|
+
const dir = dirname8(filePath);
|
|
12771
|
+
if (!existsSync15(dir)) {
|
|
12772
|
+
mkdirSync8(dir, { recursive: true });
|
|
12570
12773
|
}
|
|
12571
12774
|
}
|
|
12572
12775
|
|
|
12573
12776
|
// src/hooks/runtime/guard-check.ts
|
|
12574
|
-
import { homedir as
|
|
12575
|
-
import { join as
|
|
12777
|
+
import { homedir as homedir14 } from "node:os";
|
|
12778
|
+
import { join as join14 } from "node:path";
|
|
12576
12779
|
|
|
12577
12780
|
// src/hooks/runtime/guard-violations-buffer.ts
|
|
12578
12781
|
import {
|
|
12579
12782
|
appendFileSync,
|
|
12580
|
-
existsSync as
|
|
12581
|
-
readFileSync as
|
|
12582
|
-
writeFileSync as
|
|
12583
|
-
mkdirSync as
|
|
12783
|
+
existsSync as existsSync16,
|
|
12784
|
+
readFileSync as readFileSync15,
|
|
12785
|
+
writeFileSync as writeFileSync10,
|
|
12786
|
+
mkdirSync as mkdirSync9
|
|
12584
12787
|
} from "node:fs";
|
|
12585
|
-
import { dirname as
|
|
12586
|
-
import { homedir as
|
|
12587
|
-
import { join as
|
|
12588
|
-
var DEFAULT_BUFFER_FILE =
|
|
12589
|
-
|
|
12788
|
+
import { dirname as dirname9 } from "node:path";
|
|
12789
|
+
import { homedir as homedir13 } from "node:os";
|
|
12790
|
+
import { join as join13 } from "node:path";
|
|
12791
|
+
var DEFAULT_BUFFER_FILE = join13(
|
|
12792
|
+
homedir13(),
|
|
12590
12793
|
".cybedefend",
|
|
12591
12794
|
"guards-violations-buffer.jsonl"
|
|
12592
12795
|
);
|
|
@@ -12605,10 +12808,10 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
12605
12808
|
}
|
|
12606
12809
|
}
|
|
12607
12810
|
async function flushViolations2(ctx, postFn) {
|
|
12608
|
-
if (!
|
|
12811
|
+
if (!existsSync16(bufferFile)) return;
|
|
12609
12812
|
let content;
|
|
12610
12813
|
try {
|
|
12611
|
-
content =
|
|
12814
|
+
content = readFileSync15(bufferFile, "utf8").trim();
|
|
12612
12815
|
} catch {
|
|
12613
12816
|
return;
|
|
12614
12817
|
}
|
|
@@ -12627,7 +12830,7 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
12627
12830
|
}
|
|
12628
12831
|
if (records.length === 0) {
|
|
12629
12832
|
try {
|
|
12630
|
-
|
|
12833
|
+
writeFileSync10(bufferFile, "", "utf8");
|
|
12631
12834
|
} catch {
|
|
12632
12835
|
}
|
|
12633
12836
|
return;
|
|
@@ -12657,10 +12860,10 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
12657
12860
|
}
|
|
12658
12861
|
try {
|
|
12659
12862
|
if (failed.length === 0) {
|
|
12660
|
-
|
|
12863
|
+
writeFileSync10(bufferFile, "", "utf8");
|
|
12661
12864
|
} else {
|
|
12662
12865
|
const serialised = failed.map((r) => JSON.stringify(r)).join("\n") + "\n";
|
|
12663
|
-
|
|
12866
|
+
writeFileSync10(bufferFile, serialised, "utf8");
|
|
12664
12867
|
}
|
|
12665
12868
|
} catch {
|
|
12666
12869
|
}
|
|
@@ -12668,9 +12871,9 @@ function makeViolationsBuffer(opts = {}) {
|
|
|
12668
12871
|
return { bufferViolation: bufferViolation2, flushViolations: flushViolations2 };
|
|
12669
12872
|
}
|
|
12670
12873
|
function ensureDirFor4(filePath) {
|
|
12671
|
-
const dir =
|
|
12672
|
-
if (!
|
|
12673
|
-
|
|
12874
|
+
const dir = dirname9(filePath);
|
|
12875
|
+
if (!existsSync16(dir)) {
|
|
12876
|
+
mkdirSync9(dir, { recursive: true });
|
|
12674
12877
|
}
|
|
12675
12878
|
}
|
|
12676
12879
|
var _defaultBuffer = makeViolationsBuffer();
|
|
@@ -12696,11 +12899,11 @@ function appendDebugLog(entry) {
|
|
|
12696
12899
|
try {
|
|
12697
12900
|
const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
12698
12901
|
if (!homeDir) return;
|
|
12699
|
-
const { mkdirSync:
|
|
12700
|
-
const { join:
|
|
12701
|
-
const dir =
|
|
12702
|
-
|
|
12703
|
-
appendFileSync2(
|
|
12902
|
+
const { mkdirSync: mkdirSync10, appendFileSync: appendFileSync2 } = __require("node:fs");
|
|
12903
|
+
const { join: join15 } = __require("node:path");
|
|
12904
|
+
const dir = join15(homeDir, ".cybedefend");
|
|
12905
|
+
mkdirSync10(dir, { recursive: true });
|
|
12906
|
+
appendFileSync2(join15(dir, "hook-debug.log"), entry + "\n", "utf8");
|
|
12704
12907
|
} catch {
|
|
12705
12908
|
}
|
|
12706
12909
|
}
|
|
@@ -13071,7 +13274,7 @@ function emitUnverifiedBanner(reason) {
|
|
|
13071
13274
|
}
|
|
13072
13275
|
}
|
|
13073
13276
|
}
|
|
13074
|
-
function
|
|
13277
|
+
function sessionIdOf3(envelope) {
|
|
13075
13278
|
return typeof envelope.session_id === "string" ? envelope.session_id : typeof envelope.sessionId === "string" ? envelope.sessionId : void 0;
|
|
13076
13279
|
}
|
|
13077
13280
|
async function runPreToolUseGuardWith(opts) {
|
|
@@ -13091,7 +13294,7 @@ async function runPreToolUseGuardWith(opts) {
|
|
|
13091
13294
|
}
|
|
13092
13295
|
if (rulesOutcome.kind === "blocked") {
|
|
13093
13296
|
const sentence = opts.usageNotifier?.notifyBlock(
|
|
13094
|
-
|
|
13297
|
+
sessionIdOf3(stdinEnvelope),
|
|
13095
13298
|
rulesOutcome.block
|
|
13096
13299
|
);
|
|
13097
13300
|
if (sentence) emitAgentMessage("warn", sentence);
|
|
@@ -13101,7 +13304,7 @@ async function runPreToolUseGuardWith(opts) {
|
|
|
13101
13304
|
const caller = sniff(stdinEnvelope);
|
|
13102
13305
|
const partial = mapEnvelopeToGuardRequest(stdinEnvelope, caller.client);
|
|
13103
13306
|
if (partial === null) return 0;
|
|
13104
|
-
const sessionId =
|
|
13307
|
+
const sessionId = sessionIdOf3(stdinEnvelope);
|
|
13105
13308
|
const guardRequest = {
|
|
13106
13309
|
...partial,
|
|
13107
13310
|
projectId: projectContext.projectId,
|
|
@@ -13245,12 +13448,12 @@ function emitAgentMessage(verdict, message) {
|
|
|
13245
13448
|
}
|
|
13246
13449
|
function makeProductionJudgeDeps() {
|
|
13247
13450
|
const cache = makeJudgeCache();
|
|
13248
|
-
const warnDir = process.env.CYBEDEFEND_BASELINE_DIR ??
|
|
13451
|
+
const warnDir = process.env.CYBEDEFEND_BASELINE_DIR ?? join14(homedir14(), ".cybedefend");
|
|
13249
13452
|
const warnTracker = defaultSessionTracker(
|
|
13250
|
-
|
|
13453
|
+
join14(warnDir, "guards-judge-warned-sessions.json")
|
|
13251
13454
|
);
|
|
13252
13455
|
const blockedTracker = defaultSessionTracker(
|
|
13253
|
-
|
|
13456
|
+
join14(warnDir, "guards-judge-blocked-sessions.json")
|
|
13254
13457
|
);
|
|
13255
13458
|
return {
|
|
13256
13459
|
usage: {
|
|
@@ -13279,7 +13482,9 @@ async function runPreToolUseGuard() {
|
|
|
13279
13482
|
const envelope = await readStdinJson();
|
|
13280
13483
|
const config = loadRuntimeConfig();
|
|
13281
13484
|
if (!config) return 0;
|
|
13282
|
-
const
|
|
13485
|
+
const folder = sessionFolderOf(envelope, sniff(envelope).client);
|
|
13486
|
+
if (isSessionInactive(envelope, { cwd: folder })) return 0;
|
|
13487
|
+
const { projectId, apiBase: configApiBase } = await resolveProjectIdWithApi(folder);
|
|
13283
13488
|
if (!projectId) return 0;
|
|
13284
13489
|
const apiBaseResolved = process.env.CYBEDEFEND_API_BASE ?? configApiBase ?? config.region.apiBase;
|
|
13285
13490
|
const token = await resolveTokenWithRefresh(
|