@frostbridge/imdl 0.1.6 → 0.1.7
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 +131 -2
- 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");
|
|
@@ -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
|
*/
|
|
@@ -3609,6 +3698,42 @@ async function collectPrompts() {
|
|
|
3609
3698
|
}
|
|
3610
3699
|
}
|
|
3611
3700
|
}
|
|
3701
|
+
const cursorWorkspaces = CursorAdapter.getAllWorkspaces();
|
|
3702
|
+
if (cursorWorkspaces.length > 0) {
|
|
3703
|
+
const cursorAdapter = new CursorAdapter();
|
|
3704
|
+
for (const ws of cursorWorkspaces) {
|
|
3705
|
+
try {
|
|
3706
|
+
const events = await cursorAdapter.extractEvents({
|
|
3707
|
+
kind: "directory",
|
|
3708
|
+
path: ws,
|
|
3709
|
+
since: new Date(state.lastRun)
|
|
3710
|
+
});
|
|
3711
|
+
for (const event of events) {
|
|
3712
|
+
let violation;
|
|
3713
|
+
if (event.prompt) {
|
|
3714
|
+
const scan = scanPromptForSecrets(event.prompt);
|
|
3715
|
+
if (scan.hasSecrets) {
|
|
3716
|
+
violation = createPromptViolation(scan.findings);
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
const buffered = {
|
|
3720
|
+
sessionId: event.sessionId,
|
|
3721
|
+
type: event.type,
|
|
3722
|
+
toolName: event.toolName,
|
|
3723
|
+
toolInput: event.toolInput ? redactObject(event.toolInput) : void 0,
|
|
3724
|
+
prompt: event.prompt ? redactObject(event.prompt) : void 0,
|
|
3725
|
+
timestamp: event.timestamp,
|
|
3726
|
+
cwd: event.cwd,
|
|
3727
|
+
agentType: "cursor",
|
|
3728
|
+
violation
|
|
3729
|
+
};
|
|
3730
|
+
appendEvent(buffered);
|
|
3731
|
+
collected++;
|
|
3732
|
+
}
|
|
3733
|
+
} catch {
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3612
3737
|
if (collected > 0) {
|
|
3613
3738
|
try {
|
|
3614
3739
|
await tryFlush();
|
|
@@ -5691,8 +5816,9 @@ async function handleHook(type) {
|
|
|
5691
5816
|
behaviorRiskScore = computeRiskScore(signals);
|
|
5692
5817
|
}
|
|
5693
5818
|
}
|
|
5819
|
+
const sessionId = event.session_id || getLastSessionId();
|
|
5694
5820
|
const buffered = {
|
|
5695
|
-
sessionId
|
|
5821
|
+
sessionId,
|
|
5696
5822
|
type: hookType,
|
|
5697
5823
|
toolName: event.tool_name,
|
|
5698
5824
|
toolInput: redactObject(event.tool_input),
|
|
@@ -5704,6 +5830,9 @@ async function handleHook(type) {
|
|
|
5704
5830
|
behaviorSignals,
|
|
5705
5831
|
behaviorRiskScore
|
|
5706
5832
|
};
|
|
5833
|
+
if (event.session_id) {
|
|
5834
|
+
saveLastSessionId(event.session_id);
|
|
5835
|
+
}
|
|
5707
5836
|
appendEvent(buffered);
|
|
5708
5837
|
try {
|
|
5709
5838
|
await tryFlush();
|