@frostbridge/imdl 0.1.7 → 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 +132 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2688,7 +2688,7 @@ function resumeCommand() {
|
|
|
2688
2688
|
import pc6 from "picocolors";
|
|
2689
2689
|
|
|
2690
2690
|
// src/adapters/index.ts
|
|
2691
|
-
import { existsSync as existsSync18, readFileSync as
|
|
2691
|
+
import { existsSync as existsSync18, readFileSync as readFileSync13, writeFileSync as writeFileSync6 } from "fs";
|
|
2692
2692
|
import { join as join17 } from "path";
|
|
2693
2693
|
|
|
2694
2694
|
// src/transport/buffer.ts
|
|
@@ -3197,7 +3197,7 @@ var ClaudeCodeAdapter = class {
|
|
|
3197
3197
|
};
|
|
3198
3198
|
|
|
3199
3199
|
// src/adapters/cursor.ts
|
|
3200
|
-
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";
|
|
3201
3201
|
import { join as join16 } from "path";
|
|
3202
3202
|
import { homedir as homedir13 } from "os";
|
|
3203
3203
|
import { createRequire } from "module";
|
|
@@ -3579,6 +3579,80 @@ var CursorAdapter = class _CursorAdapter {
|
|
|
3579
3579
|
}
|
|
3580
3580
|
return `cursor-${parts[parts.length - 2] || "unknown"}`;
|
|
3581
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
|
+
}
|
|
3582
3656
|
/**
|
|
3583
3657
|
* Returns the workspace storage path for Cursor, or null if not found.
|
|
3584
3658
|
*/
|
|
@@ -3610,6 +3684,13 @@ var CursorAdapter = class _CursorAdapter {
|
|
|
3610
3684
|
return [];
|
|
3611
3685
|
}
|
|
3612
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
|
+
}
|
|
3613
3694
|
};
|
|
3614
3695
|
|
|
3615
3696
|
// src/adapters/index.ts
|
|
@@ -3617,7 +3698,7 @@ var STATE_FILE = join17(getImdlDir(), "adapter-state.json");
|
|
|
3617
3698
|
function loadState() {
|
|
3618
3699
|
try {
|
|
3619
3700
|
if (existsSync18(STATE_FILE)) {
|
|
3620
|
-
return JSON.parse(
|
|
3701
|
+
return JSON.parse(readFileSync13(STATE_FILE, "utf-8"));
|
|
3621
3702
|
}
|
|
3622
3703
|
} catch {
|
|
3623
3704
|
}
|
|
@@ -3698,9 +3779,38 @@ async function collectPrompts() {
|
|
|
3698
3779
|
}
|
|
3699
3780
|
}
|
|
3700
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
|
+
}
|
|
3701
3812
|
const cursorWorkspaces = CursorAdapter.getAllWorkspaces();
|
|
3702
3813
|
if (cursorWorkspaces.length > 0) {
|
|
3703
|
-
const cursorAdapter = new CursorAdapter();
|
|
3704
3814
|
for (const ws of cursorWorkspaces) {
|
|
3705
3815
|
try {
|
|
3706
3816
|
const events = await cursorAdapter.extractEvents({
|
|
@@ -3758,7 +3868,7 @@ async function collectCommand() {
|
|
|
3758
3868
|
|
|
3759
3869
|
// src/commands/daemon.ts
|
|
3760
3870
|
import pc7 from "picocolors";
|
|
3761
|
-
import { existsSync as existsSync19, readFileSync as
|
|
3871
|
+
import { existsSync as existsSync19, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
|
|
3762
3872
|
import { join as join18 } from "path";
|
|
3763
3873
|
var INTERVAL_MS = 3e4;
|
|
3764
3874
|
async function daemonCommand() {
|
|
@@ -3783,7 +3893,7 @@ async function daemonCommand() {
|
|
|
3783
3893
|
async function ingestShellEvents() {
|
|
3784
3894
|
const shellLog = join18(getBufferDir(), "shell-events.ndjson");
|
|
3785
3895
|
if (!existsSync19(shellLog)) return 0;
|
|
3786
|
-
const content =
|
|
3896
|
+
const content = readFileSync14(shellLog, "utf-8").trim();
|
|
3787
3897
|
if (!content) return 0;
|
|
3788
3898
|
const config = loadConfig();
|
|
3789
3899
|
const lines = content.split("\n");
|
|
@@ -3888,7 +3998,7 @@ async function requestCommand(options) {
|
|
|
3888
3998
|
// src/commands/lock.ts
|
|
3889
3999
|
import pc9 from "picocolors";
|
|
3890
4000
|
import { createHash as createHash2 } from "crypto";
|
|
3891
|
-
import { readFileSync as
|
|
4001
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync8, existsSync as existsSync20 } from "fs";
|
|
3892
4002
|
import { join as join19, resolve as resolve3 } from "path";
|
|
3893
4003
|
var LOCKFILE_NAME = "mcp-lock.json";
|
|
3894
4004
|
function computeIntegrity(server, identity) {
|
|
@@ -3986,7 +4096,7 @@ async function verifyCommand(options) {
|
|
|
3986
4096
|
}
|
|
3987
4097
|
let lockfile;
|
|
3988
4098
|
try {
|
|
3989
|
-
lockfile = JSON.parse(
|
|
4099
|
+
lockfile = JSON.parse(readFileSync15(lockPath, "utf-8"));
|
|
3990
4100
|
} catch {
|
|
3991
4101
|
console.log(pc9.red("Failed to parse lockfile."));
|
|
3992
4102
|
process.exit(1);
|
|
@@ -4395,7 +4505,7 @@ async function checkCompliance(developerId) {
|
|
|
4395
4505
|
}
|
|
4396
4506
|
|
|
4397
4507
|
// src/permissions/fixer.ts
|
|
4398
|
-
import { existsSync as existsSync21, readFileSync as
|
|
4508
|
+
import { existsSync as existsSync21, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "fs";
|
|
4399
4509
|
import { join as join20 } from "path";
|
|
4400
4510
|
import { homedir as homedir14 } from "os";
|
|
4401
4511
|
function buildFixesFromChanges(changes) {
|
|
@@ -4413,7 +4523,7 @@ function buildFixForAgent(change, home) {
|
|
|
4413
4523
|
const configPath = join20(home, ".claude", "settings.json");
|
|
4414
4524
|
if (!existsSync21(configPath)) return null;
|
|
4415
4525
|
try {
|
|
4416
|
-
const settings = JSON.parse(
|
|
4526
|
+
const settings = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
4417
4527
|
const tools = settings.allowedTools || [];
|
|
4418
4528
|
if (category === "shell") {
|
|
4419
4529
|
if (!tools.includes("Bash") && !tools.some((t) => t.startsWith("Bash("))) return null;
|
|
@@ -4444,7 +4554,7 @@ function buildFixForAgent(change, home) {
|
|
|
4444
4554
|
const configPath = join20(home, ".cursor", "settings.json");
|
|
4445
4555
|
if (!existsSync21(configPath)) return null;
|
|
4446
4556
|
try {
|
|
4447
|
-
const settings = JSON.parse(
|
|
4557
|
+
const settings = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
4448
4558
|
if ((category === "agentic_mode" || category === "shell") && settings["cursor.composer.yoloMode"] === true) {
|
|
4449
4559
|
return { agentType, category: "agentic_mode", currentGrant: "unrestricted", newGrant: "confirmation", configPath, description: "Disable YOLO mode" };
|
|
4450
4560
|
}
|
|
@@ -4456,7 +4566,7 @@ function buildFixForAgent(change, home) {
|
|
|
4456
4566
|
const configPath = join20(home, ".codex", "config.json");
|
|
4457
4567
|
if (!existsSync21(configPath)) return null;
|
|
4458
4568
|
try {
|
|
4459
|
-
const config = JSON.parse(
|
|
4569
|
+
const config = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
4460
4570
|
if ((category === "agentic_mode" || category === "shell") && config.sandbox_mode === "full_auto") {
|
|
4461
4571
|
return { agentType, category: "agentic_mode", currentGrant: "unrestricted", newGrant: "confirmation", configPath, description: "Switch to supervised mode" };
|
|
4462
4572
|
}
|
|
@@ -4468,7 +4578,7 @@ function buildFixForAgent(change, home) {
|
|
|
4468
4578
|
const configPath = join20(home, "Library", "Application Support", "Code", "User", "settings.json");
|
|
4469
4579
|
if (!existsSync21(configPath)) return null;
|
|
4470
4580
|
try {
|
|
4471
|
-
const settings = JSON.parse(
|
|
4581
|
+
const settings = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
4472
4582
|
if ((category === "agentic_mode" || category === "shell") && (settings["github.copilot.chat.agent.autoApprove"] || settings["chat.agent.autoApprove"])) {
|
|
4473
4583
|
return { agentType, category: "agentic_mode", currentGrant: "unrestricted", newGrant: "confirmation", configPath, description: "Disable autoApprove" };
|
|
4474
4584
|
}
|
|
@@ -4481,7 +4591,7 @@ function buildFixForAgent(change, home) {
|
|
|
4481
4591
|
const configPath = join20(home, ".windsurf", "mcp.json");
|
|
4482
4592
|
if (!existsSync21(configPath)) return null;
|
|
4483
4593
|
try {
|
|
4484
|
-
const config = JSON.parse(
|
|
4594
|
+
const config = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
4485
4595
|
const servers = Object.keys(config.mcpServers || {});
|
|
4486
4596
|
if (servers.length === 0) return null;
|
|
4487
4597
|
return { agentType, category, currentGrant: "unrestricted", newGrant: "denied", configPath, description: `Remove MCP servers (${servers.join(", ")})` };
|
|
@@ -4494,7 +4604,7 @@ function buildFixForAgent(change, home) {
|
|
|
4494
4604
|
}
|
|
4495
4605
|
function applyFix(fix) {
|
|
4496
4606
|
try {
|
|
4497
|
-
const content =
|
|
4607
|
+
const content = readFileSync16(fix.configPath, "utf-8");
|
|
4498
4608
|
const config = JSON.parse(content);
|
|
4499
4609
|
let modified = false;
|
|
4500
4610
|
if (fix.agentType === "claude-code") {
|
|
@@ -4785,7 +4895,7 @@ function grantLevel(grant) {
|
|
|
4785
4895
|
|
|
4786
4896
|
// src/commands/gateway.ts
|
|
4787
4897
|
import pc12 from "picocolors";
|
|
4788
|
-
import { existsSync as existsSync22, readFileSync as
|
|
4898
|
+
import { existsSync as existsSync22, readFileSync as readFileSync17, writeFileSync as writeFileSync10, mkdirSync as mkdirSync3 } from "fs";
|
|
4789
4899
|
import { join as join21 } from "path";
|
|
4790
4900
|
import { homedir as homedir15 } from "os";
|
|
4791
4901
|
import { execSync as execSync2, spawn } from "child_process";
|
|
@@ -4931,7 +5041,7 @@ async function gatewayAlertsCommand(opts) {
|
|
|
4931
5041
|
console.log(pc12.dim("No alerts logged yet."));
|
|
4932
5042
|
return;
|
|
4933
5043
|
}
|
|
4934
|
-
const lines =
|
|
5044
|
+
const lines = readFileSync17(logPath, "utf-8").split("\n").filter(Boolean);
|
|
4935
5045
|
const limit = opts.limit ? parseInt(opts.limit, 10) : 20;
|
|
4936
5046
|
const recent = lines.slice(-limit);
|
|
4937
5047
|
if (opts.json) {
|
|
@@ -5035,7 +5145,7 @@ async function getGatewayStatus() {
|
|
|
5035
5145
|
function getRunningPid() {
|
|
5036
5146
|
if (!existsSync22(GATEWAY_PID_FILE)) return null;
|
|
5037
5147
|
try {
|
|
5038
|
-
const pid = parseInt(
|
|
5148
|
+
const pid = parseInt(readFileSync17(GATEWAY_PID_FILE, "utf-8").trim(), 10);
|
|
5039
5149
|
return isNaN(pid) ? null : pid;
|
|
5040
5150
|
} catch {
|
|
5041
5151
|
return null;
|
|
@@ -5052,7 +5162,7 @@ function isProcessAlive(pid) {
|
|
|
5052
5162
|
function getConfiguredPort() {
|
|
5053
5163
|
if (!existsSync22(GATEWAY_CONFIG)) return DEFAULT_PORT;
|
|
5054
5164
|
try {
|
|
5055
|
-
const content =
|
|
5165
|
+
const content = readFileSync17(GATEWAY_CONFIG, "utf-8");
|
|
5056
5166
|
const match = content.match(/listen_port\s*=\s*(\d+)/);
|
|
5057
5167
|
return match ? parseInt(match[1], 10) : DEFAULT_PORT;
|
|
5058
5168
|
} catch {
|
|
@@ -5124,7 +5234,7 @@ function loadGatewayToml() {
|
|
|
5124
5234
|
if (!existsSync22(GATEWAY_CONFIG)) {
|
|
5125
5235
|
ensureConfig(DEFAULT_PORT);
|
|
5126
5236
|
}
|
|
5127
|
-
return
|
|
5237
|
+
return readFileSync17(GATEWAY_CONFIG, "utf-8");
|
|
5128
5238
|
}
|
|
5129
5239
|
function saveGatewayToml(content) {
|
|
5130
5240
|
writeFileSync10(GATEWAY_CONFIG, content, { mode: 384 });
|
|
@@ -5457,7 +5567,7 @@ function ruleTypeToCategory(type) {
|
|
|
5457
5567
|
}
|
|
5458
5568
|
|
|
5459
5569
|
// src/transport/sync.ts
|
|
5460
|
-
import { readFileSync as
|
|
5570
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync11, existsSync as existsSync23 } from "fs";
|
|
5461
5571
|
import { join as join22 } from "path";
|
|
5462
5572
|
var SYNC_INTERVAL = 6e4;
|
|
5463
5573
|
var SYNC_TIMEOUT = 3e3;
|
|
@@ -5468,7 +5578,7 @@ function getLastSyncTime() {
|
|
|
5468
5578
|
try {
|
|
5469
5579
|
const file = getSyncStateFile();
|
|
5470
5580
|
if (existsSync23(file)) {
|
|
5471
|
-
const data = JSON.parse(
|
|
5581
|
+
const data = JSON.parse(readFileSync18(file, "utf-8"));
|
|
5472
5582
|
return data.lastSync || 0;
|
|
5473
5583
|
}
|
|
5474
5584
|
} catch {
|