@frostbridge/imdl 0.1.10 → 0.1.12

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.
Files changed (2) hide show
  1. package/dist/index.js +79 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1228,11 +1228,10 @@ var AGENTS = [
1228
1228
  name: "Claude Code",
1229
1229
  dir: join6(homedir4(), ".claude"),
1230
1230
  mode: "hooks",
1231
- hooksFile: join6(homedir4(), ".claude", "hooks.json"),
1231
+ hooksFile: join6(homedir4(), ".claude", "settings.json"),
1232
1232
  hooks: {
1233
- user_prompt_submit: [{ command: "imdl hook prompt", timeout: 2e3 }],
1234
- pre_tool_use: [{ command: "imdl hook pre-tool", timeout: 2e3 }],
1235
- post_tool_use: [{ command: "imdl hook post-tool", timeout: 1e3 }]
1233
+ PreToolUse: [{ matcher: "*", hooks: [{ type: "command", command: "imdl hook pre-tool", timeout: 5 }] }],
1234
+ PostToolUse: [{ matcher: "*", hooks: [{ type: "command", command: "imdl hook post-tool", timeout: 5 }] }]
1236
1235
  }
1237
1236
  },
1238
1237
  {
@@ -1436,10 +1435,24 @@ function mergeHooks(existing, imdl) {
1436
1435
  if (!result.hooks[event]) {
1437
1436
  result.hooks[event] = imdlHooks;
1438
1437
  } else {
1439
- const existingCommands = result.hooks[event].map((h) => h.command);
1440
- for (const hook of imdlHooks) {
1441
- if (!existingCommands.includes(hook.command)) {
1442
- result.hooks[event].push(hook);
1438
+ for (const newEntry of imdlHooks) {
1439
+ if (newEntry.matcher && newEntry.hooks) {
1440
+ const existingEntry = result.hooks[event].find((e) => e.matcher === newEntry.matcher);
1441
+ if (existingEntry && existingEntry.hooks) {
1442
+ const existingCommands = existingEntry.hooks.map((h) => h.command);
1443
+ for (const hook of newEntry.hooks) {
1444
+ if (!existingCommands.includes(hook.command)) {
1445
+ existingEntry.hooks.push(hook);
1446
+ }
1447
+ }
1448
+ } else {
1449
+ result.hooks[event].push(newEntry);
1450
+ }
1451
+ } else {
1452
+ const existingCommands = result.hooks[event].map((h) => h.command);
1453
+ if (!existingCommands.includes(newEntry.command)) {
1454
+ result.hooks[event].push(newEntry);
1455
+ }
1443
1456
  }
1444
1457
  }
1445
1458
  }
@@ -3899,9 +3912,10 @@ async function daemonCommand() {
3899
3912
  try {
3900
3913
  const count = await collectPrompts();
3901
3914
  const shellCount = await ingestShellEvents();
3902
- const total = count + shellCount;
3915
+ const agentCount = await ingestAgentEvents();
3916
+ const total = count + shellCount + agentCount;
3903
3917
  if (total > 0) {
3904
- console.log(pc7.green(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}] Collected ${total} event${total !== 1 ? "s" : ""} (prompts: ${count}, shell: ${shellCount})`));
3918
+ console.log(pc7.green(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}] Collected ${total} event${total !== 1 ? "s" : ""} (prompts: ${count}, shell: ${shellCount}, os-agent: ${agentCount})`));
3905
3919
  }
3906
3920
  await tryFlush();
3907
3921
  } catch (err) {
@@ -3911,6 +3925,61 @@ async function daemonCommand() {
3911
3925
  await tick();
3912
3926
  setInterval(tick, INTERVAL_MS);
3913
3927
  }
3928
+ async function ingestAgentEvents() {
3929
+ const agentLog = join18(getBufferDir(), "agent-events.ndjson");
3930
+ if (!existsSync19(agentLog)) return 0;
3931
+ const content = readFileSync14(agentLog, "utf-8").trim();
3932
+ if (!content) return 0;
3933
+ const config = loadConfig();
3934
+ const lines = content.split("\n");
3935
+ const events = lines.map((line) => {
3936
+ try {
3937
+ return JSON.parse(line);
3938
+ } catch {
3939
+ return null;
3940
+ }
3941
+ }).filter(Boolean);
3942
+ if (events.length === 0) return 0;
3943
+ const headers = { "Content-Type": "application/json" };
3944
+ if (config.authToken) headers["X-IMDL-Key"] = config.authToken;
3945
+ const sessionId = `os_${config.developerId}_${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
3946
+ const apiEvents = events.map((e) => ({
3947
+ type: e.event_type === "exec" ? "pre_tool_use" : "tool_call",
3948
+ toolName: `os_${e.event_type}`,
3949
+ toolInput: {
3950
+ process: e.process,
3951
+ path: e.path,
3952
+ address: e.address,
3953
+ pid: e.pid,
3954
+ agent: e.agent
3955
+ },
3956
+ timestamp: e.timestamp,
3957
+ violation: e.decision === "block" ? {
3958
+ action: "block",
3959
+ reason: e.reason,
3960
+ policyName: e.policy_name
3961
+ } : void 0,
3962
+ source: "os_agent"
3963
+ }));
3964
+ let sent = 0;
3965
+ for (let i = 0; i < apiEvents.length; i += 50) {
3966
+ const batch = apiEvents.slice(i, i + 50);
3967
+ try {
3968
+ const res = await fetch(`${config.apiUrl}/api/sessions/${sessionId}/events`, {
3969
+ method: "POST",
3970
+ headers,
3971
+ body: JSON.stringify({ events: batch, developerId: config.developerId, source: "os_agent" }),
3972
+ signal: AbortSignal.timeout(1e4)
3973
+ });
3974
+ if (res.ok) sent += batch.length;
3975
+ } catch {
3976
+ }
3977
+ }
3978
+ if (sent === apiEvents.length) {
3979
+ writeFileSync7(agentLog, "", { mode: 384 });
3980
+ }
3981
+ return sent;
3982
+ }
3914
3983
  async function ingestShellEvents() {
3915
3984
  const shellLog = join18(getBufferDir(), "shell-events.ndjson");
3916
3985
  if (!existsSync19(shellLog)) return 0;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "restricted"
5
5
  },
6
- "version": "0.1.10",
6
+ "version": "0.1.12",
7
7
  "description": "IMDL — Intelligent Mediation & Detection Layer. AI agent security CLI.",
8
8
  "files": [
9
9
  "dist"