@frostbridge/imdl 0.1.6 → 0.1.8
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/dist/index.js +262 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -726,6 +726,23 @@ function setPaused(paused) {
|
|
|
726
726
|
}
|
|
727
727
|
}
|
|
728
728
|
}
|
|
729
|
+
var SESSION_FILE = join3(IMDL_DIR, ".last-session");
|
|
730
|
+
function getLastSessionId() {
|
|
731
|
+
try {
|
|
732
|
+
if (existsSync4(SESSION_FILE)) {
|
|
733
|
+
return readFileSync(SESSION_FILE, "utf-8").trim() || "unknown";
|
|
734
|
+
}
|
|
735
|
+
} catch {
|
|
736
|
+
}
|
|
737
|
+
return "unknown";
|
|
738
|
+
}
|
|
739
|
+
function saveLastSessionId(sessionId) {
|
|
740
|
+
try {
|
|
741
|
+
ensureImdlDir();
|
|
742
|
+
writeFileSync(SESSION_FILE, sessionId, { mode: 384 });
|
|
743
|
+
} catch {
|
|
744
|
+
}
|
|
745
|
+
}
|
|
729
746
|
|
|
730
747
|
// src/mcp/reporter.ts
|
|
731
748
|
var THROTTLE_FILE = join4(getImdlDir(), "last-mcp-report");
|
|
@@ -2671,7 +2688,7 @@ function resumeCommand() {
|
|
|
2671
2688
|
import pc6 from "picocolors";
|
|
2672
2689
|
|
|
2673
2690
|
// src/adapters/index.ts
|
|
2674
|
-
import { existsSync as existsSync18, readFileSync as
|
|
2691
|
+
import { existsSync as existsSync18, readFileSync as readFileSync13, writeFileSync as writeFileSync6 } from "fs";
|
|
2675
2692
|
import { join as join17 } from "path";
|
|
2676
2693
|
|
|
2677
2694
|
// src/transport/buffer.ts
|
|
@@ -3180,7 +3197,7 @@ var ClaudeCodeAdapter = class {
|
|
|
3180
3197
|
};
|
|
3181
3198
|
|
|
3182
3199
|
// src/adapters/cursor.ts
|
|
3183
|
-
import { existsSync as existsSync17, readdirSync as readdirSync4, statSync as statSync9 } from "fs";
|
|
3200
|
+
import { existsSync as existsSync17, readdirSync as readdirSync4, readFileSync as readFileSync12, statSync as statSync9 } from "fs";
|
|
3184
3201
|
import { join as join16 } from "path";
|
|
3185
3202
|
import { homedir as homedir13 } from "os";
|
|
3186
3203
|
import { createRequire } from "module";
|
|
@@ -3196,7 +3213,9 @@ var CHAT_DATA_KEYS = [
|
|
|
3196
3213
|
"workbench.panel.aichat.view.aichat.chatdata",
|
|
3197
3214
|
"workbench.panel.aichat.view.aichat.chatdata.v2",
|
|
3198
3215
|
"composer.composerData",
|
|
3199
|
-
"composer.allComposers"
|
|
3216
|
+
"composer.allComposers",
|
|
3217
|
+
"aiService.prompts",
|
|
3218
|
+
"aiService.generations"
|
|
3200
3219
|
];
|
|
3201
3220
|
var CursorAdapter = class _CursorAdapter {
|
|
3202
3221
|
agentType = "cursor";
|
|
@@ -3233,6 +3252,11 @@ var CursorAdapter = class _CursorAdapter {
|
|
|
3233
3252
|
*/
|
|
3234
3253
|
findVscdbFiles(baseDir) {
|
|
3235
3254
|
const files = [];
|
|
3255
|
+
const directDb = join16(baseDir, "state.vscdb");
|
|
3256
|
+
if (existsSync17(directDb)) {
|
|
3257
|
+
files.push(directDb);
|
|
3258
|
+
return files;
|
|
3259
|
+
}
|
|
3236
3260
|
try {
|
|
3237
3261
|
const entries = readdirSync4(baseDir);
|
|
3238
3262
|
for (const entry of entries) {
|
|
@@ -3263,9 +3287,23 @@ var CursorAdapter = class _CursorAdapter {
|
|
|
3263
3287
|
try {
|
|
3264
3288
|
db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
|
3265
3289
|
const rows = this.queryAIChatRows(db);
|
|
3290
|
+
let hasGenerations = false;
|
|
3266
3291
|
for (const row of rows) {
|
|
3267
3292
|
const parsed = this.parseJsonValue(row.value);
|
|
3268
3293
|
if (!parsed) continue;
|
|
3294
|
+
if (row.key === "aiService.generations") {
|
|
3295
|
+
const genEvents = this.extractFromGenerations(parsed, dbPath, since);
|
|
3296
|
+
events.push(...genEvents);
|
|
3297
|
+
if (genEvents.length > 0) hasGenerations = true;
|
|
3298
|
+
continue;
|
|
3299
|
+
}
|
|
3300
|
+
if (row.key === "aiService.prompts") {
|
|
3301
|
+
if (!hasGenerations) {
|
|
3302
|
+
const promptEvents = this.extractFromPrompts(parsed, dbPath, since);
|
|
3303
|
+
events.push(...promptEvents);
|
|
3304
|
+
}
|
|
3305
|
+
continue;
|
|
3306
|
+
}
|
|
3269
3307
|
const conversations = this.extractConversations(parsed);
|
|
3270
3308
|
for (const conv of conversations) {
|
|
3271
3309
|
const convEvents = this.conversationToEvents(conv, dbPath, since);
|
|
@@ -3281,6 +3319,57 @@ var CursorAdapter = class _CursorAdapter {
|
|
|
3281
3319
|
}
|
|
3282
3320
|
return events;
|
|
3283
3321
|
}
|
|
3322
|
+
/**
|
|
3323
|
+
* Extract events from aiService.generations format:
|
|
3324
|
+
* [{unixMs, generationUUID, type, textDescription}, ...]
|
|
3325
|
+
*/
|
|
3326
|
+
extractFromGenerations(data, dbPath, since) {
|
|
3327
|
+
if (!Array.isArray(data)) return [];
|
|
3328
|
+
const events = [];
|
|
3329
|
+
const sessionId = this.sessionIdFromPath(dbPath);
|
|
3330
|
+
for (const gen of data) {
|
|
3331
|
+
if (!gen || typeof gen !== "object") continue;
|
|
3332
|
+
const { unixMs, textDescription, type } = gen;
|
|
3333
|
+
if (!textDescription || typeof textDescription !== "string") continue;
|
|
3334
|
+
if (!unixMs || typeof unixMs !== "number") continue;
|
|
3335
|
+
if (since && unixMs <= since.getTime()) continue;
|
|
3336
|
+
const genType = type;
|
|
3337
|
+
if (genType === "apply") continue;
|
|
3338
|
+
if (this.isNoisePrompt(textDescription)) continue;
|
|
3339
|
+
events.push({
|
|
3340
|
+
sessionId,
|
|
3341
|
+
type: "user_prompt",
|
|
3342
|
+
prompt: textDescription.slice(0, 1e4),
|
|
3343
|
+
timestamp: new Date(unixMs).toISOString(),
|
|
3344
|
+
agentType: "cursor"
|
|
3345
|
+
});
|
|
3346
|
+
}
|
|
3347
|
+
return events;
|
|
3348
|
+
}
|
|
3349
|
+
/**
|
|
3350
|
+
* Extract events from aiService.prompts format:
|
|
3351
|
+
* [{text, commandType}, ...]
|
|
3352
|
+
* No timestamps — only use if generations is empty.
|
|
3353
|
+
*/
|
|
3354
|
+
extractFromPrompts(data, dbPath, _since) {
|
|
3355
|
+
if (!Array.isArray(data) || data.length === 0) return [];
|
|
3356
|
+
const events = [];
|
|
3357
|
+
const sessionId = this.sessionIdFromPath(dbPath);
|
|
3358
|
+
for (const prompt of data) {
|
|
3359
|
+
if (!prompt || typeof prompt !== "object") continue;
|
|
3360
|
+
const { text } = prompt;
|
|
3361
|
+
if (!text || typeof text !== "string") continue;
|
|
3362
|
+
if (this.isNoisePrompt(text)) continue;
|
|
3363
|
+
events.push({
|
|
3364
|
+
sessionId,
|
|
3365
|
+
type: "user_prompt",
|
|
3366
|
+
prompt: text.slice(0, 1e4),
|
|
3367
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3368
|
+
agentType: "cursor"
|
|
3369
|
+
});
|
|
3370
|
+
}
|
|
3371
|
+
return events;
|
|
3372
|
+
}
|
|
3284
3373
|
/**
|
|
3285
3374
|
* Query the ItemTable for rows with AI-related keys.
|
|
3286
3375
|
*/
|
|
@@ -3490,6 +3579,80 @@ var CursorAdapter = class _CursorAdapter {
|
|
|
3490
3579
|
}
|
|
3491
3580
|
return `cursor-${parts[parts.length - 2] || "unknown"}`;
|
|
3492
3581
|
}
|
|
3582
|
+
/**
|
|
3583
|
+
* Scan Cursor's agent-transcripts JSONL files (real-time, like Claude Code).
|
|
3584
|
+
* Path: ~/.cursor/projects/{project}/agent-transcripts/{session}/{session}.jsonl
|
|
3585
|
+
* Uses offsets to only read new lines since last scan.
|
|
3586
|
+
*/
|
|
3587
|
+
extractFromTranscripts(since, offsets) {
|
|
3588
|
+
const projectsDir = join16(homedir13(), ".cursor", "projects");
|
|
3589
|
+
if (!existsSync17(projectsDir)) return { events: [], newOffsets: offsets };
|
|
3590
|
+
const events = [];
|
|
3591
|
+
const newOffsets = { ...offsets };
|
|
3592
|
+
try {
|
|
3593
|
+
const projects = readdirSync4(projectsDir);
|
|
3594
|
+
for (const proj of projects) {
|
|
3595
|
+
const transcriptsDir = join16(projectsDir, proj, "agent-transcripts");
|
|
3596
|
+
if (!existsSync17(transcriptsDir)) continue;
|
|
3597
|
+
let sessionDirs;
|
|
3598
|
+
try {
|
|
3599
|
+
sessionDirs = readdirSync4(transcriptsDir);
|
|
3600
|
+
} catch {
|
|
3601
|
+
continue;
|
|
3602
|
+
}
|
|
3603
|
+
for (const sessionDir of sessionDirs) {
|
|
3604
|
+
const jsonlPath = join16(transcriptsDir, sessionDir, `${sessionDir}.jsonl`);
|
|
3605
|
+
if (!existsSync17(jsonlPath)) continue;
|
|
3606
|
+
if (since) {
|
|
3607
|
+
try {
|
|
3608
|
+
const stat = statSync9(jsonlPath);
|
|
3609
|
+
if (stat.mtimeMs < since.getTime()) continue;
|
|
3610
|
+
} catch {
|
|
3611
|
+
continue;
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
try {
|
|
3615
|
+
const content = readFileSync12(jsonlPath, "utf-8");
|
|
3616
|
+
const lines = content.split("\n").filter((l) => l.trim());
|
|
3617
|
+
const lastOffset = offsets[jsonlPath] || 0;
|
|
3618
|
+
if (lines.length <= lastOffset) continue;
|
|
3619
|
+
const newLines = lines.slice(lastOffset);
|
|
3620
|
+
newOffsets[jsonlPath] = lines.length;
|
|
3621
|
+
const projectPath = "/" + proj.replace(/-/g, "/").replace(/^\//, "");
|
|
3622
|
+
for (const line of newLines) {
|
|
3623
|
+
let entry;
|
|
3624
|
+
try {
|
|
3625
|
+
entry = JSON.parse(line);
|
|
3626
|
+
} catch {
|
|
3627
|
+
continue;
|
|
3628
|
+
}
|
|
3629
|
+
if (entry.role !== "user") continue;
|
|
3630
|
+
const msg = entry.message?.content;
|
|
3631
|
+
if (!Array.isArray(msg)) continue;
|
|
3632
|
+
let text = "";
|
|
3633
|
+
for (const block of msg) {
|
|
3634
|
+
if (block?.type === "text" && block.text) {
|
|
3635
|
+
text += block.text.replace(/<user_query>\n?/g, "").replace(/\n?<\/user_query>/g, "").trim();
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3638
|
+
if (!text || this.isNoisePrompt(text)) continue;
|
|
3639
|
+
events.push({
|
|
3640
|
+
sessionId: `cursor-${sessionDir.slice(0, 8)}`,
|
|
3641
|
+
type: "user_prompt",
|
|
3642
|
+
prompt: text.slice(0, 1e4),
|
|
3643
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3644
|
+
cwd: projectPath,
|
|
3645
|
+
agentType: "cursor"
|
|
3646
|
+
});
|
|
3647
|
+
}
|
|
3648
|
+
} catch {
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
} catch {
|
|
3653
|
+
}
|
|
3654
|
+
return { events, newOffsets };
|
|
3655
|
+
}
|
|
3493
3656
|
/**
|
|
3494
3657
|
* Returns the workspace storage path for Cursor, or null if not found.
|
|
3495
3658
|
*/
|
|
@@ -3521,6 +3684,13 @@ var CursorAdapter = class _CursorAdapter {
|
|
|
3521
3684
|
return [];
|
|
3522
3685
|
}
|
|
3523
3686
|
}
|
|
3687
|
+
/**
|
|
3688
|
+
* Returns the Cursor projects directory for transcript scanning.
|
|
3689
|
+
*/
|
|
3690
|
+
static getProjectsDir() {
|
|
3691
|
+
const dir = join16(homedir13(), ".cursor", "projects");
|
|
3692
|
+
return existsSync17(dir) ? dir : null;
|
|
3693
|
+
}
|
|
3524
3694
|
};
|
|
3525
3695
|
|
|
3526
3696
|
// src/adapters/index.ts
|
|
@@ -3528,7 +3698,7 @@ var STATE_FILE = join17(getImdlDir(), "adapter-state.json");
|
|
|
3528
3698
|
function loadState() {
|
|
3529
3699
|
try {
|
|
3530
3700
|
if (existsSync18(STATE_FILE)) {
|
|
3531
|
-
return JSON.parse(
|
|
3701
|
+
return JSON.parse(readFileSync13(STATE_FILE, "utf-8"));
|
|
3532
3702
|
}
|
|
3533
3703
|
} catch {
|
|
3534
3704
|
}
|
|
@@ -3609,6 +3779,71 @@ async function collectPrompts() {
|
|
|
3609
3779
|
}
|
|
3610
3780
|
}
|
|
3611
3781
|
}
|
|
3782
|
+
const cursorAdapter = new CursorAdapter();
|
|
3783
|
+
if (CursorAdapter.getProjectsDir()) {
|
|
3784
|
+
try {
|
|
3785
|
+
const { events: transcriptEvents, newOffsets } = cursorAdapter.extractFromTranscripts(new Date(state.lastRun), state.offsets);
|
|
3786
|
+
state.offsets = newOffsets;
|
|
3787
|
+
for (const event of transcriptEvents) {
|
|
3788
|
+
let violation;
|
|
3789
|
+
if (event.prompt) {
|
|
3790
|
+
const scan = scanPromptForSecrets(event.prompt);
|
|
3791
|
+
if (scan.hasSecrets) {
|
|
3792
|
+
violation = createPromptViolation(scan.findings);
|
|
3793
|
+
}
|
|
3794
|
+
}
|
|
3795
|
+
const buffered = {
|
|
3796
|
+
sessionId: event.sessionId,
|
|
3797
|
+
type: event.type,
|
|
3798
|
+
toolName: event.toolName,
|
|
3799
|
+
toolInput: event.toolInput ? redactObject(event.toolInput) : void 0,
|
|
3800
|
+
prompt: event.prompt ? redactObject(event.prompt) : void 0,
|
|
3801
|
+
timestamp: event.timestamp,
|
|
3802
|
+
cwd: event.cwd,
|
|
3803
|
+
agentType: "cursor",
|
|
3804
|
+
violation
|
|
3805
|
+
};
|
|
3806
|
+
appendEvent(buffered);
|
|
3807
|
+
collected++;
|
|
3808
|
+
}
|
|
3809
|
+
} catch {
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
const cursorWorkspaces = CursorAdapter.getAllWorkspaces();
|
|
3813
|
+
if (cursorWorkspaces.length > 0) {
|
|
3814
|
+
for (const ws of cursorWorkspaces) {
|
|
3815
|
+
try {
|
|
3816
|
+
const events = await cursorAdapter.extractEvents({
|
|
3817
|
+
kind: "directory",
|
|
3818
|
+
path: ws,
|
|
3819
|
+
since: new Date(state.lastRun)
|
|
3820
|
+
});
|
|
3821
|
+
for (const event of events) {
|
|
3822
|
+
let violation;
|
|
3823
|
+
if (event.prompt) {
|
|
3824
|
+
const scan = scanPromptForSecrets(event.prompt);
|
|
3825
|
+
if (scan.hasSecrets) {
|
|
3826
|
+
violation = createPromptViolation(scan.findings);
|
|
3827
|
+
}
|
|
3828
|
+
}
|
|
3829
|
+
const buffered = {
|
|
3830
|
+
sessionId: event.sessionId,
|
|
3831
|
+
type: event.type,
|
|
3832
|
+
toolName: event.toolName,
|
|
3833
|
+
toolInput: event.toolInput ? redactObject(event.toolInput) : void 0,
|
|
3834
|
+
prompt: event.prompt ? redactObject(event.prompt) : void 0,
|
|
3835
|
+
timestamp: event.timestamp,
|
|
3836
|
+
cwd: event.cwd,
|
|
3837
|
+
agentType: "cursor",
|
|
3838
|
+
violation
|
|
3839
|
+
};
|
|
3840
|
+
appendEvent(buffered);
|
|
3841
|
+
collected++;
|
|
3842
|
+
}
|
|
3843
|
+
} catch {
|
|
3844
|
+
}
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3612
3847
|
if (collected > 0) {
|
|
3613
3848
|
try {
|
|
3614
3849
|
await tryFlush();
|
|
@@ -3633,7 +3868,7 @@ async function collectCommand() {
|
|
|
3633
3868
|
|
|
3634
3869
|
// src/commands/daemon.ts
|
|
3635
3870
|
import pc7 from "picocolors";
|
|
3636
|
-
import { existsSync as existsSync19, readFileSync as
|
|
3871
|
+
import { existsSync as existsSync19, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
|
|
3637
3872
|
import { join as join18 } from "path";
|
|
3638
3873
|
var INTERVAL_MS = 3e4;
|
|
3639
3874
|
async function daemonCommand() {
|
|
@@ -3658,7 +3893,7 @@ async function daemonCommand() {
|
|
|
3658
3893
|
async function ingestShellEvents() {
|
|
3659
3894
|
const shellLog = join18(getBufferDir(), "shell-events.ndjson");
|
|
3660
3895
|
if (!existsSync19(shellLog)) return 0;
|
|
3661
|
-
const content =
|
|
3896
|
+
const content = readFileSync14(shellLog, "utf-8").trim();
|
|
3662
3897
|
if (!content) return 0;
|
|
3663
3898
|
const config = loadConfig();
|
|
3664
3899
|
const lines = content.split("\n");
|
|
@@ -3763,7 +3998,7 @@ async function requestCommand(options) {
|
|
|
3763
3998
|
// src/commands/lock.ts
|
|
3764
3999
|
import pc9 from "picocolors";
|
|
3765
4000
|
import { createHash as createHash2 } from "crypto";
|
|
3766
|
-
import { readFileSync as
|
|
4001
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync8, existsSync as existsSync20 } from "fs";
|
|
3767
4002
|
import { join as join19, resolve as resolve3 } from "path";
|
|
3768
4003
|
var LOCKFILE_NAME = "mcp-lock.json";
|
|
3769
4004
|
function computeIntegrity(server, identity) {
|
|
@@ -3861,7 +4096,7 @@ async function verifyCommand(options) {
|
|
|
3861
4096
|
}
|
|
3862
4097
|
let lockfile;
|
|
3863
4098
|
try {
|
|
3864
|
-
lockfile = JSON.parse(
|
|
4099
|
+
lockfile = JSON.parse(readFileSync15(lockPath, "utf-8"));
|
|
3865
4100
|
} catch {
|
|
3866
4101
|
console.log(pc9.red("Failed to parse lockfile."));
|
|
3867
4102
|
process.exit(1);
|
|
@@ -4270,7 +4505,7 @@ async function checkCompliance(developerId) {
|
|
|
4270
4505
|
}
|
|
4271
4506
|
|
|
4272
4507
|
// src/permissions/fixer.ts
|
|
4273
|
-
import { existsSync as existsSync21, readFileSync as
|
|
4508
|
+
import { existsSync as existsSync21, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "fs";
|
|
4274
4509
|
import { join as join20 } from "path";
|
|
4275
4510
|
import { homedir as homedir14 } from "os";
|
|
4276
4511
|
function buildFixesFromChanges(changes) {
|
|
@@ -4288,7 +4523,7 @@ function buildFixForAgent(change, home) {
|
|
|
4288
4523
|
const configPath = join20(home, ".claude", "settings.json");
|
|
4289
4524
|
if (!existsSync21(configPath)) return null;
|
|
4290
4525
|
try {
|
|
4291
|
-
const settings = JSON.parse(
|
|
4526
|
+
const settings = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
4292
4527
|
const tools = settings.allowedTools || [];
|
|
4293
4528
|
if (category === "shell") {
|
|
4294
4529
|
if (!tools.includes("Bash") && !tools.some((t) => t.startsWith("Bash("))) return null;
|
|
@@ -4319,7 +4554,7 @@ function buildFixForAgent(change, home) {
|
|
|
4319
4554
|
const configPath = join20(home, ".cursor", "settings.json");
|
|
4320
4555
|
if (!existsSync21(configPath)) return null;
|
|
4321
4556
|
try {
|
|
4322
|
-
const settings = JSON.parse(
|
|
4557
|
+
const settings = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
4323
4558
|
if ((category === "agentic_mode" || category === "shell") && settings["cursor.composer.yoloMode"] === true) {
|
|
4324
4559
|
return { agentType, category: "agentic_mode", currentGrant: "unrestricted", newGrant: "confirmation", configPath, description: "Disable YOLO mode" };
|
|
4325
4560
|
}
|
|
@@ -4331,7 +4566,7 @@ function buildFixForAgent(change, home) {
|
|
|
4331
4566
|
const configPath = join20(home, ".codex", "config.json");
|
|
4332
4567
|
if (!existsSync21(configPath)) return null;
|
|
4333
4568
|
try {
|
|
4334
|
-
const config = JSON.parse(
|
|
4569
|
+
const config = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
4335
4570
|
if ((category === "agentic_mode" || category === "shell") && config.sandbox_mode === "full_auto") {
|
|
4336
4571
|
return { agentType, category: "agentic_mode", currentGrant: "unrestricted", newGrant: "confirmation", configPath, description: "Switch to supervised mode" };
|
|
4337
4572
|
}
|
|
@@ -4343,7 +4578,7 @@ function buildFixForAgent(change, home) {
|
|
|
4343
4578
|
const configPath = join20(home, "Library", "Application Support", "Code", "User", "settings.json");
|
|
4344
4579
|
if (!existsSync21(configPath)) return null;
|
|
4345
4580
|
try {
|
|
4346
|
-
const settings = JSON.parse(
|
|
4581
|
+
const settings = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
4347
4582
|
if ((category === "agentic_mode" || category === "shell") && (settings["github.copilot.chat.agent.autoApprove"] || settings["chat.agent.autoApprove"])) {
|
|
4348
4583
|
return { agentType, category: "agentic_mode", currentGrant: "unrestricted", newGrant: "confirmation", configPath, description: "Disable autoApprove" };
|
|
4349
4584
|
}
|
|
@@ -4356,7 +4591,7 @@ function buildFixForAgent(change, home) {
|
|
|
4356
4591
|
const configPath = join20(home, ".windsurf", "mcp.json");
|
|
4357
4592
|
if (!existsSync21(configPath)) return null;
|
|
4358
4593
|
try {
|
|
4359
|
-
const config = JSON.parse(
|
|
4594
|
+
const config = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
4360
4595
|
const servers = Object.keys(config.mcpServers || {});
|
|
4361
4596
|
if (servers.length === 0) return null;
|
|
4362
4597
|
return { agentType, category, currentGrant: "unrestricted", newGrant: "denied", configPath, description: `Remove MCP servers (${servers.join(", ")})` };
|
|
@@ -4369,7 +4604,7 @@ function buildFixForAgent(change, home) {
|
|
|
4369
4604
|
}
|
|
4370
4605
|
function applyFix(fix) {
|
|
4371
4606
|
try {
|
|
4372
|
-
const content =
|
|
4607
|
+
const content = readFileSync16(fix.configPath, "utf-8");
|
|
4373
4608
|
const config = JSON.parse(content);
|
|
4374
4609
|
let modified = false;
|
|
4375
4610
|
if (fix.agentType === "claude-code") {
|
|
@@ -4660,7 +4895,7 @@ function grantLevel(grant) {
|
|
|
4660
4895
|
|
|
4661
4896
|
// src/commands/gateway.ts
|
|
4662
4897
|
import pc12 from "picocolors";
|
|
4663
|
-
import { existsSync as existsSync22, readFileSync as
|
|
4898
|
+
import { existsSync as existsSync22, readFileSync as readFileSync17, writeFileSync as writeFileSync10, mkdirSync as mkdirSync3 } from "fs";
|
|
4664
4899
|
import { join as join21 } from "path";
|
|
4665
4900
|
import { homedir as homedir15 } from "os";
|
|
4666
4901
|
import { execSync as execSync2, spawn } from "child_process";
|
|
@@ -4806,7 +5041,7 @@ async function gatewayAlertsCommand(opts) {
|
|
|
4806
5041
|
console.log(pc12.dim("No alerts logged yet."));
|
|
4807
5042
|
return;
|
|
4808
5043
|
}
|
|
4809
|
-
const lines =
|
|
5044
|
+
const lines = readFileSync17(logPath, "utf-8").split("\n").filter(Boolean);
|
|
4810
5045
|
const limit = opts.limit ? parseInt(opts.limit, 10) : 20;
|
|
4811
5046
|
const recent = lines.slice(-limit);
|
|
4812
5047
|
if (opts.json) {
|
|
@@ -4910,7 +5145,7 @@ async function getGatewayStatus() {
|
|
|
4910
5145
|
function getRunningPid() {
|
|
4911
5146
|
if (!existsSync22(GATEWAY_PID_FILE)) return null;
|
|
4912
5147
|
try {
|
|
4913
|
-
const pid = parseInt(
|
|
5148
|
+
const pid = parseInt(readFileSync17(GATEWAY_PID_FILE, "utf-8").trim(), 10);
|
|
4914
5149
|
return isNaN(pid) ? null : pid;
|
|
4915
5150
|
} catch {
|
|
4916
5151
|
return null;
|
|
@@ -4927,7 +5162,7 @@ function isProcessAlive(pid) {
|
|
|
4927
5162
|
function getConfiguredPort() {
|
|
4928
5163
|
if (!existsSync22(GATEWAY_CONFIG)) return DEFAULT_PORT;
|
|
4929
5164
|
try {
|
|
4930
|
-
const content =
|
|
5165
|
+
const content = readFileSync17(GATEWAY_CONFIG, "utf-8");
|
|
4931
5166
|
const match = content.match(/listen_port\s*=\s*(\d+)/);
|
|
4932
5167
|
return match ? parseInt(match[1], 10) : DEFAULT_PORT;
|
|
4933
5168
|
} catch {
|
|
@@ -4999,7 +5234,7 @@ function loadGatewayToml() {
|
|
|
4999
5234
|
if (!existsSync22(GATEWAY_CONFIG)) {
|
|
5000
5235
|
ensureConfig(DEFAULT_PORT);
|
|
5001
5236
|
}
|
|
5002
|
-
return
|
|
5237
|
+
return readFileSync17(GATEWAY_CONFIG, "utf-8");
|
|
5003
5238
|
}
|
|
5004
5239
|
function saveGatewayToml(content) {
|
|
5005
5240
|
writeFileSync10(GATEWAY_CONFIG, content, { mode: 384 });
|
|
@@ -5332,7 +5567,7 @@ function ruleTypeToCategory(type) {
|
|
|
5332
5567
|
}
|
|
5333
5568
|
|
|
5334
5569
|
// src/transport/sync.ts
|
|
5335
|
-
import { readFileSync as
|
|
5570
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync11, existsSync as existsSync23 } from "fs";
|
|
5336
5571
|
import { join as join22 } from "path";
|
|
5337
5572
|
var SYNC_INTERVAL = 6e4;
|
|
5338
5573
|
var SYNC_TIMEOUT = 3e3;
|
|
@@ -5343,7 +5578,7 @@ function getLastSyncTime() {
|
|
|
5343
5578
|
try {
|
|
5344
5579
|
const file = getSyncStateFile();
|
|
5345
5580
|
if (existsSync23(file)) {
|
|
5346
|
-
const data = JSON.parse(
|
|
5581
|
+
const data = JSON.parse(readFileSync18(file, "utf-8"));
|
|
5347
5582
|
return data.lastSync || 0;
|
|
5348
5583
|
}
|
|
5349
5584
|
} catch {
|
|
@@ -5691,8 +5926,9 @@ async function handleHook(type) {
|
|
|
5691
5926
|
behaviorRiskScore = computeRiskScore(signals);
|
|
5692
5927
|
}
|
|
5693
5928
|
}
|
|
5929
|
+
const sessionId = event.session_id || getLastSessionId();
|
|
5694
5930
|
const buffered = {
|
|
5695
|
-
sessionId
|
|
5931
|
+
sessionId,
|
|
5696
5932
|
type: hookType,
|
|
5697
5933
|
toolName: event.tool_name,
|
|
5698
5934
|
toolInput: redactObject(event.tool_input),
|
|
@@ -5704,6 +5940,9 @@ async function handleHook(type) {
|
|
|
5704
5940
|
behaviorSignals,
|
|
5705
5941
|
behaviorRiskScore
|
|
5706
5942
|
};
|
|
5943
|
+
if (event.session_id) {
|
|
5944
|
+
saveLastSessionId(event.session_id);
|
|
5945
|
+
}
|
|
5707
5946
|
appendEvent(buffered);
|
|
5708
5947
|
try {
|
|
5709
5948
|
await tryFlush();
|