agent-insights 0.0.13 → 0.0.16
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/cli.js +339 -53
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +324 -54
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type AgentName = "claude-code" | "cursor" | "opencode" | "codex" | "unknown";
|
|
1
|
+
type AgentName = "claude-code" | "cursor" | "opencode" | "codex" | "pi" | "unknown";
|
|
2
2
|
type AgentEventType = "session.start" | "session.end" | "user.prompt.submit" | "tool.start" | "tool.end" | "tool.failure" | "permission.request" | "permission.denied" | "subagent.start" | "subagent.end" | "agent.stop" | "notification" | "context.compact.start" | "context.compact.end" | "error";
|
|
3
3
|
type AgentOutcome = "success" | "error" | "cancelled" | "unknown";
|
|
4
4
|
type AgentEvent = {
|
|
@@ -82,7 +82,7 @@ type AgentInsightsConfig = {
|
|
|
82
82
|
exporter: ExporterConfig;
|
|
83
83
|
transcriptStore: TranscriptStoreConfig;
|
|
84
84
|
sessionAnalysis: SessionAnalysisConfig;
|
|
85
|
-
agents: Record<"claudeCode" | "cursor", AgentConfig>;
|
|
85
|
+
agents: Record<"claudeCode" | "cursor" | "codex" | "pi", AgentConfig>;
|
|
86
86
|
privacy: {
|
|
87
87
|
capturePrompts: false;
|
|
88
88
|
captureMessages: false;
|
|
@@ -94,7 +94,7 @@ declare function defaultConfig(): AgentInsightsConfig;
|
|
|
94
94
|
declare function loadConfig(): Promise<AgentInsightsConfig | undefined>;
|
|
95
95
|
declare function saveConfig(cfg: AgentInsightsConfig): Promise<void>;
|
|
96
96
|
|
|
97
|
-
type AgentId = "claude-code" | "cursor";
|
|
97
|
+
type AgentId = "claude-code" | "cursor" | "codex" | "pi";
|
|
98
98
|
type HookPayload = {
|
|
99
99
|
/** Native event name as emitted by the agent (e.g. `SessionStart`). */
|
|
100
100
|
event: string;
|
package/dist/index.js
CHANGED
|
@@ -257,12 +257,162 @@ function asString(v) {
|
|
|
257
257
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
// src/adapters/
|
|
260
|
+
// src/adapters/codex.ts
|
|
261
261
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
262
262
|
import { homedir as homedir2 } from "os";
|
|
263
263
|
import { dirname as dirname2, join as join2 } from "path";
|
|
264
264
|
var HOOK_COMMAND_NAME2 = "agent-insights";
|
|
265
265
|
var HOOK_MAP2 = {
|
|
266
|
+
SessionStart: "session.start",
|
|
267
|
+
UserPromptSubmit: "user.prompt.submit",
|
|
268
|
+
PreToolUse: "tool.start",
|
|
269
|
+
PostToolUse: "tool.end",
|
|
270
|
+
PermissionRequest: "permission.request",
|
|
271
|
+
Stop: "session.end"
|
|
272
|
+
};
|
|
273
|
+
var CODEX_HOOK_EVENTS = Object.keys(HOOK_MAP2);
|
|
274
|
+
var codexAdapter = {
|
|
275
|
+
id: "codex",
|
|
276
|
+
agent: "codex",
|
|
277
|
+
label: "Codex",
|
|
278
|
+
settingsFile: ".codex/hooks.json",
|
|
279
|
+
map(payload) {
|
|
280
|
+
const type = HOOK_MAP2[payload.event];
|
|
281
|
+
if (!type) return void 0;
|
|
282
|
+
const data = payload.data ?? {};
|
|
283
|
+
const sessionId = asString2(data["session_id"]) ?? asString2(data["sessionId"]);
|
|
284
|
+
const toolName = asString2(data["tool_name"]) ?? asString2(data["toolName"]) ?? asString2(data["tool"]?.["name"]);
|
|
285
|
+
const transcriptPath = asString2(data["transcript_path"]) ?? asString2(data["transcriptPath"]);
|
|
286
|
+
return {
|
|
287
|
+
type,
|
|
288
|
+
...sessionId !== void 0 ? { sessionId } : {},
|
|
289
|
+
...toolName !== void 0 ? { toolName } : {},
|
|
290
|
+
...transcriptPath !== void 0 ? { transcriptPath } : {}
|
|
291
|
+
};
|
|
292
|
+
},
|
|
293
|
+
async install(repoRoot, scope = "global") {
|
|
294
|
+
const path = resolveCodexPath(repoRoot, scope);
|
|
295
|
+
const settings = await readJson2(path);
|
|
296
|
+
const next = { ...settings ?? {} };
|
|
297
|
+
const hooks = {};
|
|
298
|
+
for (const [event, raw] of Object.entries(next.hooks ?? {})) {
|
|
299
|
+
hooks[event] = normalizeEventHooks2(raw);
|
|
300
|
+
}
|
|
301
|
+
for (const event of CODEX_HOOK_EVENTS) {
|
|
302
|
+
const withoutInsights = removeAgentInsightsMatchers2(hooks[event] ?? []);
|
|
303
|
+
hooks[event] = addAgentInsightsHook2(withoutInsights, event);
|
|
304
|
+
}
|
|
305
|
+
next.hooks = hooks;
|
|
306
|
+
await mkdir2(dirname2(path), { recursive: true });
|
|
307
|
+
await writeFile2(path, `${JSON.stringify(next, null, 2)}
|
|
308
|
+
`, "utf8");
|
|
309
|
+
return { written: true, path };
|
|
310
|
+
},
|
|
311
|
+
async uninstall(repoRoot, scope = "global") {
|
|
312
|
+
const path = resolveCodexPath(repoRoot, scope);
|
|
313
|
+
const settings = await readJson2(path);
|
|
314
|
+
if (!settings?.hooks) return { removed: false, path };
|
|
315
|
+
const hooks = {};
|
|
316
|
+
let touched = false;
|
|
317
|
+
for (const [event, raw] of Object.entries(settings.hooks)) {
|
|
318
|
+
const before = normalizeEventHooks2(raw);
|
|
319
|
+
const after = removeAgentInsightsMatchers2(before);
|
|
320
|
+
if (after.length !== before.length || JSON.stringify(after) !== JSON.stringify(before)) {
|
|
321
|
+
touched = true;
|
|
322
|
+
}
|
|
323
|
+
if (after.length > 0) hooks[event] = after;
|
|
324
|
+
}
|
|
325
|
+
settings.hooks = hooks;
|
|
326
|
+
await writeFile2(path, `${JSON.stringify(settings, null, 2)}
|
|
327
|
+
`, "utf8");
|
|
328
|
+
return { removed: touched, path };
|
|
329
|
+
},
|
|
330
|
+
async isInstalled(repoRoot, scope = "global") {
|
|
331
|
+
const settings = await readJson2(
|
|
332
|
+
resolveCodexPath(repoRoot, scope)
|
|
333
|
+
);
|
|
334
|
+
if (!settings?.hooks) return false;
|
|
335
|
+
return Object.values(settings.hooks).some(
|
|
336
|
+
(raw) => normalizeEventHooks2(raw).some(
|
|
337
|
+
(group) => group.hooks.some((h) => isAgentInsightsCommand2(h.command))
|
|
338
|
+
)
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
function resolveCodexPath(repoRoot, scope) {
|
|
343
|
+
return scope === "global" ? join2(homedir2(), ".codex", "hooks.json") : join2(repoRoot, ".codex", "hooks.json");
|
|
344
|
+
}
|
|
345
|
+
function isAgentInsightsCommand2(cmd) {
|
|
346
|
+
if (!cmd) return false;
|
|
347
|
+
return cmd.startsWith(`${HOOK_COMMAND_NAME2} hook`);
|
|
348
|
+
}
|
|
349
|
+
function isHookCommand2(value) {
|
|
350
|
+
if (!value || typeof value !== "object") return false;
|
|
351
|
+
const entry = value;
|
|
352
|
+
return entry.type === "command" && typeof entry.command === "string";
|
|
353
|
+
}
|
|
354
|
+
function normalizeEventHooks2(raw) {
|
|
355
|
+
const groups = [];
|
|
356
|
+
for (const entry of raw) {
|
|
357
|
+
if (!entry || typeof entry !== "object") continue;
|
|
358
|
+
const record = entry;
|
|
359
|
+
if (Array.isArray(record.hooks)) {
|
|
360
|
+
const commands = record.hooks.filter(isHookCommand2);
|
|
361
|
+
if (commands.length === 0) continue;
|
|
362
|
+
groups.push({
|
|
363
|
+
matcher: typeof record.matcher === "string" ? record.matcher : "",
|
|
364
|
+
hooks: commands
|
|
365
|
+
});
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
if (isHookCommand2(record)) {
|
|
369
|
+
groups.push({ matcher: "", hooks: [record] });
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return groups;
|
|
373
|
+
}
|
|
374
|
+
function removeAgentInsightsMatchers2(matchers) {
|
|
375
|
+
const result = [];
|
|
376
|
+
for (const group of matchers) {
|
|
377
|
+
const hooks = group.hooks.filter(
|
|
378
|
+
(h) => !isAgentInsightsCommand2(h.command)
|
|
379
|
+
);
|
|
380
|
+
if (hooks.length > 0) result.push({ ...group, hooks });
|
|
381
|
+
}
|
|
382
|
+
return result;
|
|
383
|
+
}
|
|
384
|
+
function addAgentInsightsHook2(matchers, event) {
|
|
385
|
+
const command = `${HOOK_COMMAND_NAME2} hook ${event}`;
|
|
386
|
+
const entry = { type: "command", command };
|
|
387
|
+
for (const group of matchers) {
|
|
388
|
+
if (group.matcher === "") {
|
|
389
|
+
if (!group.hooks.some((h) => h.command === command)) {
|
|
390
|
+
group.hooks.push(entry);
|
|
391
|
+
}
|
|
392
|
+
return matchers;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return [...matchers, { matcher: "", hooks: [entry] }];
|
|
396
|
+
}
|
|
397
|
+
async function readJson2(path) {
|
|
398
|
+
try {
|
|
399
|
+
const raw = await readFile2(path, "utf8");
|
|
400
|
+
return JSON.parse(raw);
|
|
401
|
+
} catch (err) {
|
|
402
|
+
if (err.code === "ENOENT") return void 0;
|
|
403
|
+
throw err;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
function asString2(v) {
|
|
407
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// src/adapters/cursor.ts
|
|
411
|
+
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
412
|
+
import { homedir as homedir3 } from "os";
|
|
413
|
+
import { dirname as dirname3, join as join3 } from "path";
|
|
414
|
+
var HOOK_COMMAND_NAME3 = "agent-insights";
|
|
415
|
+
var HOOK_MAP3 = {
|
|
266
416
|
sessionStart: "session.start",
|
|
267
417
|
sessionEnd: "session.end",
|
|
268
418
|
beforeSubmitPrompt: "user.prompt.submit",
|
|
@@ -279,19 +429,19 @@ var HOOK_MAP2 = {
|
|
|
279
429
|
afterFileEdit: "tool.end",
|
|
280
430
|
workspaceOpen: "session.start"
|
|
281
431
|
};
|
|
282
|
-
var CURSOR_HOOK_EVENTS = Object.keys(
|
|
432
|
+
var CURSOR_HOOK_EVENTS = Object.keys(HOOK_MAP3);
|
|
283
433
|
var cursorAdapter = {
|
|
284
434
|
id: "cursor",
|
|
285
435
|
agent: "cursor",
|
|
286
436
|
label: "Cursor",
|
|
287
437
|
settingsFile: ".cursor/hooks.json",
|
|
288
438
|
map(payload) {
|
|
289
|
-
const type =
|
|
439
|
+
const type = HOOK_MAP3[payload.event];
|
|
290
440
|
if (!type) return void 0;
|
|
291
441
|
const data = payload.data ?? {};
|
|
292
|
-
const sessionId =
|
|
293
|
-
const toolName =
|
|
294
|
-
const transcriptPath =
|
|
442
|
+
const sessionId = asString3(data["session_id"]) ?? asString3(data["sessionId"]) ?? asString3(data["conversation_id"]);
|
|
443
|
+
const toolName = asString3(data["tool_name"]) ?? asString3(data["toolName"]);
|
|
444
|
+
const transcriptPath = asString3(data["transcript_path"]) ?? asString3(data["transcriptPath"]) ?? asString3(process.env.CURSOR_TRANSCRIPT_PATH);
|
|
295
445
|
return {
|
|
296
446
|
type,
|
|
297
447
|
...sessionId !== void 0 ? { sessionId } : {},
|
|
@@ -301,7 +451,7 @@ var cursorAdapter = {
|
|
|
301
451
|
},
|
|
302
452
|
async install(repoRoot, scope = "global") {
|
|
303
453
|
const path = resolveCursorPath(repoRoot, scope);
|
|
304
|
-
const settings = await
|
|
454
|
+
const settings = await readJson3(path);
|
|
305
455
|
const next = {
|
|
306
456
|
version: 1,
|
|
307
457
|
...settings ?? {}
|
|
@@ -309,26 +459,26 @@ var cursorAdapter = {
|
|
|
309
459
|
const hooks = { ...next.hooks ?? {} };
|
|
310
460
|
for (const event of CURSOR_HOOK_EVENTS) {
|
|
311
461
|
const existing = (hooks[event] ?? []).filter(
|
|
312
|
-
(h) => !
|
|
462
|
+
(h) => !isAgentInsightsCommand3(h.command)
|
|
313
463
|
);
|
|
314
|
-
existing.push({ command: `${
|
|
464
|
+
existing.push({ command: `${HOOK_COMMAND_NAME3} hook ${event}` });
|
|
315
465
|
hooks[event] = existing;
|
|
316
466
|
}
|
|
317
467
|
next.hooks = hooks;
|
|
318
|
-
await
|
|
319
|
-
await
|
|
468
|
+
await mkdir3(dirname3(path), { recursive: true });
|
|
469
|
+
await writeFile3(path, `${JSON.stringify(next, null, 2)}
|
|
320
470
|
`, "utf8");
|
|
321
471
|
return { written: true, path };
|
|
322
472
|
},
|
|
323
473
|
async uninstall(repoRoot, scope = "global") {
|
|
324
474
|
const path = resolveCursorPath(repoRoot, scope);
|
|
325
|
-
const settings = await
|
|
475
|
+
const settings = await readJson3(path);
|
|
326
476
|
if (!settings?.hooks) return { removed: false, path };
|
|
327
477
|
const hooks = { ...settings.hooks };
|
|
328
478
|
let touched = false;
|
|
329
479
|
for (const [event, entries] of Object.entries(hooks)) {
|
|
330
480
|
const filtered = entries.filter(
|
|
331
|
-
(h) => !
|
|
481
|
+
(h) => !isAgentInsightsCommand3(h.command)
|
|
332
482
|
);
|
|
333
483
|
if (filtered.length !== entries.length) touched = true;
|
|
334
484
|
if (filtered.length === 0) {
|
|
@@ -338,44 +488,160 @@ var cursorAdapter = {
|
|
|
338
488
|
}
|
|
339
489
|
}
|
|
340
490
|
settings.hooks = hooks;
|
|
341
|
-
await
|
|
491
|
+
await writeFile3(path, `${JSON.stringify(settings, null, 2)}
|
|
342
492
|
`, "utf8");
|
|
343
493
|
return { removed: touched, path };
|
|
344
494
|
},
|
|
345
495
|
async isInstalled(repoRoot, scope = "global") {
|
|
346
|
-
const settings = await
|
|
496
|
+
const settings = await readJson3(
|
|
347
497
|
resolveCursorPath(repoRoot, scope)
|
|
348
498
|
);
|
|
349
499
|
if (!settings?.hooks) return false;
|
|
350
500
|
return Object.values(settings.hooks).some(
|
|
351
|
-
(entries) => entries.some((h) =>
|
|
501
|
+
(entries) => entries.some((h) => isAgentInsightsCommand3(h.command))
|
|
352
502
|
);
|
|
353
503
|
}
|
|
354
504
|
};
|
|
355
505
|
function resolveCursorPath(repoRoot, scope) {
|
|
356
|
-
return scope === "global" ?
|
|
506
|
+
return scope === "global" ? join3(homedir3(), ".cursor", "hooks.json") : join3(repoRoot, ".cursor", "hooks.json");
|
|
357
507
|
}
|
|
358
|
-
function
|
|
508
|
+
function isAgentInsightsCommand3(cmd) {
|
|
359
509
|
if (!cmd) return false;
|
|
360
|
-
return cmd.startsWith(`${
|
|
510
|
+
return cmd.startsWith(`${HOOK_COMMAND_NAME3} hook`);
|
|
361
511
|
}
|
|
362
|
-
async function
|
|
512
|
+
async function readJson3(path) {
|
|
363
513
|
try {
|
|
364
|
-
const raw = await
|
|
514
|
+
const raw = await readFile3(path, "utf8");
|
|
365
515
|
return JSON.parse(raw);
|
|
366
516
|
} catch (err) {
|
|
367
517
|
if (err.code === "ENOENT") return void 0;
|
|
368
518
|
throw err;
|
|
369
519
|
}
|
|
370
520
|
}
|
|
371
|
-
function
|
|
521
|
+
function asString3(v) {
|
|
522
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// src/adapters/pi.ts
|
|
526
|
+
import { mkdir as mkdir4, readFile as readFile4, unlink, writeFile as writeFile4 } from "fs/promises";
|
|
527
|
+
import { homedir as homedir4 } from "os";
|
|
528
|
+
import { dirname as dirname4, join as join4 } from "path";
|
|
529
|
+
var EXTENSION_FILENAME = "agent-insights.ts";
|
|
530
|
+
var HOOK_MAP4 = {
|
|
531
|
+
session_start: "session.start",
|
|
532
|
+
session_shutdown: "session.end",
|
|
533
|
+
tool_call: "tool.start",
|
|
534
|
+
tool_result: "tool.end"
|
|
535
|
+
};
|
|
536
|
+
var PI_HOOK_EVENTS = Object.keys(HOOK_MAP4);
|
|
537
|
+
var EXTENSION_MARKER = "// installed-by: agent-insights";
|
|
538
|
+
function extensionSource() {
|
|
539
|
+
return `${EXTENSION_MARKER}
|
|
540
|
+
// Generated by \`agent-insights init\`. Edit-with-caution: it's overwritten on every install.
|
|
541
|
+
|
|
542
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
543
|
+
import { spawn } from "node:child_process";
|
|
544
|
+
|
|
545
|
+
const EVENTS = ${JSON.stringify(PI_HOOK_EVENTS)} as const;
|
|
546
|
+
|
|
547
|
+
function emit(event: string, payload: Record<string, unknown>): void {
|
|
548
|
+
try {
|
|
549
|
+
const child = spawn("agent-insights", ["hook", event], {
|
|
550
|
+
stdio: ["pipe", "ignore", "ignore"],
|
|
551
|
+
detached: true,
|
|
552
|
+
});
|
|
553
|
+
child.on("error", () => {});
|
|
554
|
+
child.stdin.end(JSON.stringify(payload));
|
|
555
|
+
child.unref();
|
|
556
|
+
} catch {
|
|
557
|
+
// best-effort
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
export default function (pi: ExtensionAPI) {
|
|
562
|
+
for (const event of EVENTS) {
|
|
563
|
+
pi.on(event as never, async (raw: unknown, ctx: { sessionManager?: { getSessionFile?: () => string | undefined; getSessionId?: () => string | undefined } }) => {
|
|
564
|
+
const transcript_path = ctx.sessionManager?.getSessionFile?.();
|
|
565
|
+
const session_id = ctx.sessionManager?.getSessionId?.();
|
|
566
|
+
const e = (raw ?? {}) as Record<string, unknown>;
|
|
567
|
+
emit(event, {
|
|
568
|
+
...(session_id ? { session_id } : {}),
|
|
569
|
+
...(transcript_path ? { transcript_path } : {}),
|
|
570
|
+
...("toolName" in e && typeof e.toolName === "string"
|
|
571
|
+
? { tool_name: e.toolName }
|
|
572
|
+
: {}),
|
|
573
|
+
...("reason" in e ? { reason: e.reason } : {}),
|
|
574
|
+
});
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
`;
|
|
579
|
+
}
|
|
580
|
+
var piAdapter = {
|
|
581
|
+
id: "pi",
|
|
582
|
+
agent: "pi",
|
|
583
|
+
label: "Pi",
|
|
584
|
+
settingsFile: ".pi/extensions/agent-insights.ts",
|
|
585
|
+
map(payload) {
|
|
586
|
+
const type = HOOK_MAP4[payload.event];
|
|
587
|
+
if (!type) return void 0;
|
|
588
|
+
const data = payload.data ?? {};
|
|
589
|
+
const sessionId = asString4(data["session_id"]) ?? asString4(data["sessionId"]);
|
|
590
|
+
const toolName = asString4(data["tool_name"]) ?? asString4(data["toolName"]);
|
|
591
|
+
const transcriptPath = asString4(data["transcript_path"]) ?? asString4(data["transcriptPath"]);
|
|
592
|
+
return {
|
|
593
|
+
type,
|
|
594
|
+
...sessionId !== void 0 ? { sessionId } : {},
|
|
595
|
+
...toolName !== void 0 ? { toolName } : {},
|
|
596
|
+
...transcriptPath !== void 0 ? { transcriptPath } : {}
|
|
597
|
+
};
|
|
598
|
+
},
|
|
599
|
+
async install(repoRoot, scope = "global") {
|
|
600
|
+
const path = resolvePath(repoRoot, scope);
|
|
601
|
+
await mkdir4(dirname4(path), { recursive: true });
|
|
602
|
+
await writeFile4(path, extensionSource(), "utf8");
|
|
603
|
+
return { written: true, path };
|
|
604
|
+
},
|
|
605
|
+
async uninstall(repoRoot, scope = "global") {
|
|
606
|
+
const path = resolvePath(repoRoot, scope);
|
|
607
|
+
try {
|
|
608
|
+
const raw = await readFile4(path, "utf8");
|
|
609
|
+
if (!raw.includes(EXTENSION_MARKER)) {
|
|
610
|
+
return { removed: false, path };
|
|
611
|
+
}
|
|
612
|
+
await unlink(path);
|
|
613
|
+
return { removed: true, path };
|
|
614
|
+
} catch (err) {
|
|
615
|
+
if (err.code === "ENOENT") {
|
|
616
|
+
return { removed: false, path };
|
|
617
|
+
}
|
|
618
|
+
throw err;
|
|
619
|
+
}
|
|
620
|
+
},
|
|
621
|
+
async isInstalled(repoRoot, scope = "global") {
|
|
622
|
+
const path = resolvePath(repoRoot, scope);
|
|
623
|
+
try {
|
|
624
|
+
const raw = await readFile4(path, "utf8");
|
|
625
|
+
return raw.includes(EXTENSION_MARKER);
|
|
626
|
+
} catch (err) {
|
|
627
|
+
if (err.code === "ENOENT") return false;
|
|
628
|
+
throw err;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
function resolvePath(repoRoot, scope) {
|
|
633
|
+
return scope === "global" ? join4(homedir4(), ".pi", "agent", "extensions", EXTENSION_FILENAME) : join4(repoRoot, ".pi", "extensions", EXTENSION_FILENAME);
|
|
634
|
+
}
|
|
635
|
+
function asString4(v) {
|
|
372
636
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
373
637
|
}
|
|
374
638
|
|
|
375
639
|
// src/adapters/registry.ts
|
|
376
640
|
var adapters = {
|
|
377
641
|
"claude-code": claudeCodeAdapter,
|
|
378
|
-
cursor: cursorAdapter
|
|
642
|
+
cursor: cursorAdapter,
|
|
643
|
+
codex: codexAdapter,
|
|
644
|
+
pi: piAdapter
|
|
379
645
|
};
|
|
380
646
|
var adapterList = Object.values(adapters);
|
|
381
647
|
function getAdapter(id) {
|
|
@@ -383,8 +649,8 @@ function getAdapter(id) {
|
|
|
383
649
|
}
|
|
384
650
|
|
|
385
651
|
// src/config/config.ts
|
|
386
|
-
import { mkdir as
|
|
387
|
-
import { dirname as
|
|
652
|
+
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
653
|
+
import { dirname as dirname5 } from "path";
|
|
388
654
|
|
|
389
655
|
// src/config/analyzer.ts
|
|
390
656
|
var DEFAULT_ANALYZER_URL = "https://agent-insights.labs.vercel.dev";
|
|
@@ -393,25 +659,25 @@ function getAnalyzerUrl() {
|
|
|
393
659
|
}
|
|
394
660
|
|
|
395
661
|
// src/config/paths.ts
|
|
396
|
-
import { homedir as
|
|
397
|
-
import { join as
|
|
662
|
+
import { homedir as homedir5 } from "os";
|
|
663
|
+
import { join as join5 } from "path";
|
|
398
664
|
function configRoot() {
|
|
399
|
-
return process.env.AGENT_INSIGHTS_HOME ??
|
|
665
|
+
return process.env.AGENT_INSIGHTS_HOME ?? join5(homedir5(), ".agent-insights");
|
|
400
666
|
}
|
|
401
667
|
function configFile() {
|
|
402
|
-
return
|
|
668
|
+
return join5(configRoot(), "config.json");
|
|
403
669
|
}
|
|
404
670
|
function authFile() {
|
|
405
|
-
return
|
|
671
|
+
return join5(configRoot(), "auth.json");
|
|
406
672
|
}
|
|
407
673
|
function bypassSecretFile() {
|
|
408
|
-
return
|
|
674
|
+
return join5(configRoot(), "bypass-secret");
|
|
409
675
|
}
|
|
410
676
|
function sessionCacheDir() {
|
|
411
|
-
return
|
|
677
|
+
return join5(configRoot(), "session-cache");
|
|
412
678
|
}
|
|
413
679
|
function logsDir() {
|
|
414
|
-
return
|
|
680
|
+
return join5(configRoot(), "logs");
|
|
415
681
|
}
|
|
416
682
|
|
|
417
683
|
// src/config/config.ts
|
|
@@ -448,7 +714,9 @@ function defaultConfig() {
|
|
|
448
714
|
},
|
|
449
715
|
agents: {
|
|
450
716
|
claudeCode: { enabled: false },
|
|
451
|
-
cursor: { enabled: false }
|
|
717
|
+
cursor: { enabled: false },
|
|
718
|
+
codex: { enabled: false },
|
|
719
|
+
pi: { enabled: false }
|
|
452
720
|
},
|
|
453
721
|
privacy: {
|
|
454
722
|
capturePrompts: false,
|
|
@@ -460,7 +728,7 @@ function defaultConfig() {
|
|
|
460
728
|
}
|
|
461
729
|
async function loadConfig() {
|
|
462
730
|
try {
|
|
463
|
-
const raw = await
|
|
731
|
+
const raw = await readFile5(configFile(), "utf8");
|
|
464
732
|
const parsed = JSON.parse(raw);
|
|
465
733
|
return mergeConfig(defaultConfig(), parsed);
|
|
466
734
|
} catch (err) {
|
|
@@ -470,13 +738,13 @@ async function loadConfig() {
|
|
|
470
738
|
}
|
|
471
739
|
async function saveConfig(cfg) {
|
|
472
740
|
await ensureDirs();
|
|
473
|
-
await
|
|
741
|
+
await writeFile5(configFile(), `${JSON.stringify(cfg, null, 2)}
|
|
474
742
|
`, "utf8");
|
|
475
743
|
}
|
|
476
744
|
async function ensureDirs() {
|
|
477
|
-
await
|
|
478
|
-
await
|
|
479
|
-
await
|
|
745
|
+
await mkdir5(dirname5(configFile()), { recursive: true });
|
|
746
|
+
await mkdir5(sessionCacheDir(), { recursive: true });
|
|
747
|
+
await mkdir5(logsDir(), { recursive: true });
|
|
480
748
|
}
|
|
481
749
|
function mergeConfig(base, patch) {
|
|
482
750
|
return {
|
|
@@ -495,20 +763,22 @@ function mergeConfig(base, patch) {
|
|
|
495
763
|
...base.agents.claudeCode,
|
|
496
764
|
...patch.agents?.claudeCode ?? {}
|
|
497
765
|
},
|
|
498
|
-
cursor: { ...base.agents.cursor, ...patch.agents?.cursor ?? {} }
|
|
766
|
+
cursor: { ...base.agents.cursor, ...patch.agents?.cursor ?? {} },
|
|
767
|
+
codex: { ...base.agents.codex, ...patch.agents?.codex ?? {} },
|
|
768
|
+
pi: { ...base.agents.pi, ...patch.agents?.pi ?? {} }
|
|
499
769
|
},
|
|
500
770
|
privacy: base.privacy
|
|
501
771
|
};
|
|
502
772
|
}
|
|
503
773
|
|
|
504
774
|
// src/transcript/store.ts
|
|
505
|
-
import { readFile as
|
|
775
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
506
776
|
import { put } from "@vercel/blob";
|
|
507
777
|
|
|
508
778
|
// src/auth/store.ts
|
|
509
|
-
import { chmod, readFile as
|
|
510
|
-
import { dirname as
|
|
511
|
-
import { mkdir as
|
|
779
|
+
import { chmod, readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
|
|
780
|
+
import { dirname as dirname6 } from "path";
|
|
781
|
+
import { mkdir as mkdir6 } from "fs/promises";
|
|
512
782
|
|
|
513
783
|
// src/auth/oauth.ts
|
|
514
784
|
import { createHash as createHash2, randomBytes } from "crypto";
|
|
@@ -540,7 +810,7 @@ async function refreshAccessToken(refreshToken) {
|
|
|
540
810
|
var REFRESH_BUFFER_MS = 6e4;
|
|
541
811
|
async function loadAuth() {
|
|
542
812
|
try {
|
|
543
|
-
const raw = await
|
|
813
|
+
const raw = await readFile6(authFile(), "utf8");
|
|
544
814
|
const parsed = JSON.parse(raw);
|
|
545
815
|
if (typeof parsed.accessToken === "string" && parsed.accessToken.length > 0) {
|
|
546
816
|
return parsed;
|
|
@@ -553,8 +823,8 @@ async function loadAuth() {
|
|
|
553
823
|
}
|
|
554
824
|
async function saveAuth(state) {
|
|
555
825
|
const path = authFile();
|
|
556
|
-
await
|
|
557
|
-
await
|
|
826
|
+
await mkdir6(dirname6(path), { recursive: true });
|
|
827
|
+
await writeFile6(path, `${JSON.stringify(state, null, 2)}
|
|
558
828
|
`, {
|
|
559
829
|
encoding: "utf8",
|
|
560
830
|
mode: 384
|
|
@@ -565,9 +835,9 @@ async function saveAuth(state) {
|
|
|
565
835
|
}
|
|
566
836
|
}
|
|
567
837
|
async function clearAuth() {
|
|
568
|
-
const { unlink:
|
|
838
|
+
const { unlink: unlink3 } = await import("fs/promises");
|
|
569
839
|
try {
|
|
570
|
-
await
|
|
840
|
+
await unlink3(authFile());
|
|
571
841
|
} catch (err) {
|
|
572
842
|
if (err.code !== "ENOENT") throw err;
|
|
573
843
|
}
|
|
@@ -598,13 +868,13 @@ async function getValidToken() {
|
|
|
598
868
|
}
|
|
599
869
|
|
|
600
870
|
// src/config/bypass.ts
|
|
601
|
-
import { chmod as chmod2, mkdir as
|
|
602
|
-
import { dirname as
|
|
871
|
+
import { chmod as chmod2, mkdir as mkdir7, readFile as readFile7, unlink as unlink2, writeFile as writeFile7 } from "fs/promises";
|
|
872
|
+
import { dirname as dirname7 } from "path";
|
|
603
873
|
async function loadBypassSecret() {
|
|
604
874
|
const fromEnv = process.env.AGENT_INSIGHTS_BYPASS_SECRET || process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
|
605
875
|
if (fromEnv) return fromEnv;
|
|
606
876
|
try {
|
|
607
|
-
const raw = (await
|
|
877
|
+
const raw = (await readFile7(bypassSecretFile(), "utf8")).trim();
|
|
608
878
|
return raw || void 0;
|
|
609
879
|
} catch (err) {
|
|
610
880
|
if (err.code === "ENOENT") return void 0;
|
|
@@ -636,7 +906,7 @@ var BlobTranscriptStore = class {
|
|
|
636
906
|
token;
|
|
637
907
|
prefix;
|
|
638
908
|
async upload(input) {
|
|
639
|
-
const body = await
|
|
909
|
+
const body = await readFile8(input.transcriptPath);
|
|
640
910
|
const requestedPath = buildPathname(
|
|
641
911
|
this.prefix,
|
|
642
912
|
input.userHash,
|
|
@@ -667,7 +937,7 @@ var AnalyzerTranscriptStore = class {
|
|
|
667
937
|
"transcript store: not logged in \u2014 run `agent-insights login`"
|
|
668
938
|
);
|
|
669
939
|
}
|
|
670
|
-
const body = await
|
|
940
|
+
const body = await readFile8(input.transcriptPath);
|
|
671
941
|
const url = new URL("/api/sessions/upload", this.analyzerUrl).toString();
|
|
672
942
|
const headers = await withBypassHeader({
|
|
673
943
|
authorization: `Bearer ${token}`,
|