context-mode 1.0.162 → 1.0.164

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 (149) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.openclaw-plugin/openclaw.plugin.json +1 -1
  5. package/.openclaw-plugin/package.json +1 -1
  6. package/README.md +149 -30
  7. package/bin/statusline.mjs +24 -4
  8. package/build/adapters/antigravity/index.d.ts +1 -1
  9. package/build/adapters/antigravity-cli/index.d.ts +51 -0
  10. package/build/adapters/antigravity-cli/index.js +342 -0
  11. package/build/adapters/claude-code/hooks.d.ts +1 -0
  12. package/build/adapters/claude-code/hooks.js +3 -0
  13. package/build/adapters/claude-code/index.js +24 -5
  14. package/build/adapters/client-map.js +5 -0
  15. package/build/adapters/codex/hooks.d.ts +5 -1
  16. package/build/adapters/codex/hooks.js +5 -1
  17. package/build/adapters/codex/index.d.ts +9 -1
  18. package/build/adapters/codex/index.js +87 -5
  19. package/build/adapters/copilot-cli/hooks.d.ts +33 -0
  20. package/build/adapters/copilot-cli/hooks.js +64 -0
  21. package/build/adapters/copilot-cli/index.d.ts +48 -0
  22. package/build/adapters/copilot-cli/index.js +341 -0
  23. package/build/adapters/detect.d.ts +1 -1
  24. package/build/adapters/detect.js +71 -3
  25. package/build/adapters/openclaw/mcp-tools.js +1 -1
  26. package/build/adapters/opencode/index.js +31 -17
  27. package/build/adapters/opencode/zod3tov4.js +27 -6
  28. package/build/adapters/pi/extension.d.ts +2 -12
  29. package/build/adapters/pi/extension.js +128 -109
  30. package/build/adapters/types.d.ts +5 -4
  31. package/build/adapters/types.js +4 -3
  32. package/build/cache-heal.d.ts +48 -0
  33. package/build/cache-heal.js +150 -0
  34. package/build/cli.js +37 -97
  35. package/build/executor.d.ts +25 -0
  36. package/build/executor.js +143 -22
  37. package/build/lifecycle.d.ts +48 -0
  38. package/build/lifecycle.js +111 -0
  39. package/build/opencode-plugin.js +5 -2
  40. package/build/routing-block.d.ts +8 -0
  41. package/build/routing-block.js +86 -0
  42. package/build/runtime.d.ts +0 -36
  43. package/build/runtime.js +107 -27
  44. package/build/search/flood-guard.d.ts +57 -0
  45. package/build/search/flood-guard.js +80 -0
  46. package/build/security.d.ts +73 -3
  47. package/build/security.js +293 -33
  48. package/build/server.d.ts +14 -0
  49. package/build/server.js +441 -354
  50. package/build/session/analytics.d.ts +1 -1
  51. package/build/session/analytics.js +5 -1
  52. package/build/session/db.js +23 -3
  53. package/build/session/extract.js +78 -0
  54. package/build/store.d.ts +1 -1
  55. package/build/store.js +139 -25
  56. package/build/tool-naming.d.ts +4 -0
  57. package/build/tool-naming.js +24 -0
  58. package/build/util/jsonc.d.ts +14 -0
  59. package/build/util/jsonc.js +104 -0
  60. package/cli.bundle.mjs +253 -250
  61. package/configs/antigravity/GEMINI.md +2 -2
  62. package/configs/antigravity-cli/hooks/hooks.json +37 -0
  63. package/configs/antigravity-cli/hooks.json +37 -0
  64. package/configs/antigravity-cli/mcp_config.json +10 -0
  65. package/configs/antigravity-cli/plugin.json +14 -0
  66. package/configs/antigravity-cli/rules/context-mode.md +77 -0
  67. package/configs/antigravity-cli/skills/context-mode/SKILL.md +77 -0
  68. package/configs/claude-code/CLAUDE.md +2 -2
  69. package/configs/codex/AGENTS.md +2 -2
  70. package/configs/copilot-cli/.github/plugin/plugin.json +23 -0
  71. package/configs/copilot-cli/.mcp.json +12 -0
  72. package/configs/copilot-cli/README.md +47 -0
  73. package/configs/copilot-cli/hooks.json +41 -0
  74. package/configs/copilot-cli/skills/context-mode/SKILL.md +38 -0
  75. package/configs/gemini-cli/GEMINI.md +2 -2
  76. package/configs/jetbrains-copilot/copilot-instructions.md +2 -2
  77. package/configs/kilo/AGENTS.md +2 -2
  78. package/configs/kiro/KIRO.md +2 -2
  79. package/configs/omp/SYSTEM.md +2 -2
  80. package/configs/openclaw/AGENTS.md +2 -2
  81. package/configs/opencode/AGENTS.md +2 -2
  82. package/configs/qwen-code/QWEN.md +2 -2
  83. package/configs/vscode-copilot/copilot-instructions.md +2 -2
  84. package/configs/zed/AGENTS.md +2 -2
  85. package/hooks/antigravity-cli/payload.mjs +98 -0
  86. package/hooks/antigravity-cli/posttooluse.mjs +138 -0
  87. package/hooks/antigravity-cli/pretooluse.mjs +78 -0
  88. package/hooks/antigravity-cli/stop.mjs +58 -0
  89. package/hooks/codex/pretooluse.mjs +14 -4
  90. package/hooks/codex/stop.mjs +12 -4
  91. package/hooks/copilot-cli/posttooluse.mjs +79 -0
  92. package/hooks/copilot-cli/precompact.mjs +66 -0
  93. package/hooks/copilot-cli/pretooluse.mjs +41 -0
  94. package/hooks/copilot-cli/sessionstart.mjs +121 -0
  95. package/hooks/copilot-cli/stop.mjs +59 -0
  96. package/hooks/copilot-cli/userpromptsubmit.mjs +77 -0
  97. package/hooks/core/codex-caps.mjs +112 -0
  98. package/hooks/core/formatters.mjs +158 -7
  99. package/hooks/core/mcp-ready.mjs +37 -8
  100. package/hooks/core/routing.mjs +94 -8
  101. package/hooks/core/tool-naming.mjs +3 -0
  102. package/hooks/hooks.json +12 -1
  103. package/hooks/pretooluse.mjs +6 -2
  104. package/hooks/routing-block.mjs +3 -4
  105. package/hooks/security.bundle.mjs +2 -1
  106. package/hooks/session-db.bundle.mjs +5 -5
  107. package/hooks/session-directive.mjs +88 -20
  108. package/hooks/session-extract.bundle.mjs +2 -2
  109. package/hooks/session-helpers.mjs +21 -0
  110. package/hooks/sessionstart.mjs +37 -5
  111. package/hooks/stop.mjs +49 -0
  112. package/openclaw.plugin.json +1 -1
  113. package/package.json +2 -10
  114. package/server.bundle.mjs +206 -200
  115. package/skills/ctx-insight/SKILL.md +12 -17
  116. package/build/util/db-lock.d.ts +0 -65
  117. package/build/util/db-lock.js +0 -166
  118. package/insight/index.html +0 -13
  119. package/insight/package.json +0 -55
  120. package/insight/server.mjs +0 -1265
  121. package/insight/src/components/analytics.tsx +0 -112
  122. package/insight/src/components/ui/badge.tsx +0 -52
  123. package/insight/src/components/ui/button.tsx +0 -58
  124. package/insight/src/components/ui/card.tsx +0 -103
  125. package/insight/src/components/ui/chart.tsx +0 -371
  126. package/insight/src/components/ui/collapsible.tsx +0 -19
  127. package/insight/src/components/ui/input.tsx +0 -20
  128. package/insight/src/components/ui/progress.tsx +0 -83
  129. package/insight/src/components/ui/scroll-area.tsx +0 -55
  130. package/insight/src/components/ui/separator.tsx +0 -23
  131. package/insight/src/components/ui/table.tsx +0 -114
  132. package/insight/src/components/ui/tabs.tsx +0 -82
  133. package/insight/src/components/ui/tooltip.tsx +0 -64
  134. package/insight/src/lib/api.ts +0 -144
  135. package/insight/src/lib/utils.ts +0 -6
  136. package/insight/src/main.tsx +0 -22
  137. package/insight/src/routeTree.gen.ts +0 -189
  138. package/insight/src/router.tsx +0 -19
  139. package/insight/src/routes/__root.tsx +0 -55
  140. package/insight/src/routes/enterprise.tsx +0 -316
  141. package/insight/src/routes/index.tsx +0 -1482
  142. package/insight/src/routes/knowledge.tsx +0 -221
  143. package/insight/src/routes/knowledge_.$dbHash.$sourceId.tsx +0 -137
  144. package/insight/src/routes/search.tsx +0 -97
  145. package/insight/src/routes/sessions.tsx +0 -179
  146. package/insight/src/routes/sessions_.$dbHash.$sessionId.tsx +0 -181
  147. package/insight/src/styles.css +0 -104
  148. package/insight/tsconfig.json +0 -29
  149. package/insight/vite.config.ts +0 -19
@@ -7,10 +7,54 @@
7
7
 
8
8
  import { writeFileSync } from "node:fs";
9
9
 
10
+ // ── Leg-boundary helpers (#780) ──
11
+ // The current Claude Code session_id persists across `--continue` legs, so the
12
+ // events array can carry rows written in a PRIOR leg. The last `session_start`
13
+ // lifecycle event (emitted by the prior leg's SessionStart, before this leg's
14
+ // directive is built — sessionstart.mjs:206/258, 277/293) is the boundary that
15
+ // opened the current leg. Rows with created_at < boundary are prior-leg.
16
+ function computeLegBoundary(events) {
17
+ let boundary = null;
18
+ for (const ev of events) {
19
+ if (ev.category === "session_start" && ev.created_at) boundary = ev.created_at;
20
+ }
21
+ return boundary;
22
+ }
23
+
24
+ // True when an event was written in a leg strictly before the current one.
25
+ // No boundary (first leg) → nothing is prior-leg, so everything stays current.
26
+ function isPriorLeg(ev, boundary) {
27
+ return boundary != null && ev.created_at != null && ev.created_at < boundary;
28
+ }
29
+
30
+ // ── Data References sizing (#840) ──
31
+ // Inlining every captured tool-output verbatim defeats context-mode's own
32
+ // raw-bytes-stay-out principle. Inline only a small recent window; reference
33
+ // large blobs with a one-line pointer. The full payloads stay queryable in
34
+ // FTS5 via ctx_search(source: "session-events").
35
+ const DATA_REF_INLINE_MAX = 8; // most-recent captures rendered inline
36
+ const DATA_REF_ENTRY_MAX = 150; // per-entry char cap before it is referenced
37
+
38
+ function renderDataReferences(entries, push, searchHint) {
39
+ const recent = entries.slice(-DATA_REF_INLINE_MAX);
40
+ for (const ev of recent) {
41
+ const raw = ev.data ?? "";
42
+ const text = raw.length > DATA_REF_ENTRY_MAX
43
+ ? `${raw.substring(0, DATA_REF_ENTRY_MAX - 3)}… (${raw.length} bytes — query ${searchHint})`
44
+ : raw;
45
+ push(`- ${text}`);
46
+ }
47
+ const older = entries.length - recent.length;
48
+ if (older > 0) {
49
+ push(`- … ${older} older captures kept in the sandbox — query ${searchHint}.`);
50
+ }
51
+ }
52
+
10
53
  // ── Group events by category and extract metadata ──
11
54
  export function groupEvents(events) {
12
55
  const grouped = {};
13
56
  let lastPrompt = "";
57
+ const legBoundary = computeLegBoundary(events);
14
58
  for (const ev of events) {
15
59
  if (ev.category === "prompt") {
16
60
  lastPrompt = ev.data;
@@ -25,13 +69,13 @@ export function groupEvents(events) {
25
69
  const base = path?.split(/[/\\]/).pop()?.trim();
26
70
  if (base && !base.includes("*")) fileNames.add(base);
27
71
  }
28
- return { grouped, lastPrompt, fileNames };
72
+ return { grouped, lastPrompt, fileNames, legBoundary };
29
73
  }
30
74
 
31
75
  // ── Write session events as markdown for FTS5 auto-indexing ──
32
76
  // Structured with H2 headings per category — optimal for FTS5 chunking.
33
77
  export function writeSessionEventsFile(events, eventsPath) {
34
- const { grouped, lastPrompt, fileNames } = groupEvents(events);
78
+ const { grouped, lastPrompt, fileNames, legBoundary } = groupEvents(events);
35
79
 
36
80
  const lines = [];
37
81
  lines.push("# Session Resume");
@@ -149,10 +193,23 @@ export function writeSessionEventsFile(events, eventsPath) {
149
193
  }
150
194
 
151
195
  if (grouped.subagent?.length > 0) {
152
- lines.push("## Subagent Tasks");
153
- lines.push("");
154
- for (const ev of grouped.subagent) lines.push(`- ${ev.data}`);
155
- lines.push("");
196
+ // #780 — only current-leg subagent events are "current". Prior-leg ones
197
+ // are reframed as history so stale [completed]/[launched] labels are not
198
+ // re-injected as if the agent ran in this conversation.
199
+ const currentSub = grouped.subagent.filter(ev => !isPriorLeg(ev, legBoundary));
200
+ const priorSub = grouped.subagent.filter(ev => isPriorLeg(ev, legBoundary));
201
+ if (currentSub.length > 0) {
202
+ lines.push("## Subagent Tasks");
203
+ lines.push("");
204
+ for (const ev of currentSub) lines.push(`- ${ev.data}`);
205
+ lines.push("");
206
+ }
207
+ if (priorSub.length > 0) {
208
+ lines.push("## Subagent Tasks (earlier session — not current)");
209
+ lines.push("");
210
+ for (const ev of priorSub) lines.push(`- ${ev.data}`);
211
+ lines.push("");
212
+ }
156
213
  }
157
214
 
158
215
  if (grouped.skill?.length > 0) {
@@ -180,7 +237,11 @@ export function writeSessionEventsFile(events, eventsPath) {
180
237
  if (grouped.data?.length > 0) {
181
238
  lines.push("## Data References");
182
239
  lines.push("");
183
- for (const ev of grouped.data) lines.push(`- ${ev.data}`);
240
+ renderDataReferences(
241
+ grouped.data,
242
+ (l) => lines.push(l),
243
+ 'ctx_search(source: "session-events")',
244
+ );
184
245
  lines.push("");
185
246
  }
186
247
 
@@ -212,8 +273,10 @@ export function writeSessionEventsFile(events, eventsPath) {
212
273
 
213
274
  // ── Build session guide — actionable narrative for LLM to continue from ──
214
275
  export function buildSessionDirective(source, eventMeta, toolNamer) {
215
- const { grouped, lastPrompt, fileNames } = eventMeta;
276
+ const { grouped, lastPrompt, fileNames, legBoundary } = eventMeta;
216
277
  const isCompact = source === "compact";
278
+ const searchTool = toolNamer ? toolNamer("ctx_search") : "ctx_search";
279
+ const dataSearchHint = `${searchTool}(source: "session-events")`;
217
280
 
218
281
  let block = `\n<session_knowledge source="${isCompact ? "compact" : "continue"}">`;
219
282
  block += `\n<session_guide>`;
@@ -333,14 +396,23 @@ export function buildSessionDirective(source, eventMeta, toolNamer) {
333
396
  block += `\n`;
334
397
  }
335
398
 
336
- // 9. Subagent tasks
399
+ // 9. Subagent tasks — #780: prior-leg events are NOT current work. Render
400
+ // only current-leg subagents under "Subagent Tasks"; reframe prior-leg
401
+ // ones so stale [completed]/[launched] labels don't read as this leg's.
337
402
  if (grouped.subagent?.length > 0) {
338
- block += `\n## Subagent Tasks`;
339
- for (const ev of grouped.subagent) {
340
- const text = ev.data.length > 120 ? ev.data.substring(0, 117) + "..." : ev.data;
341
- block += `\n- ${text}`;
403
+ const fmt = (ev) => ev.data.length > 120 ? ev.data.substring(0, 117) + "..." : ev.data;
404
+ const currentSub = grouped.subagent.filter(ev => !isPriorLeg(ev, legBoundary));
405
+ const priorSub = grouped.subagent.filter(ev => isPriorLeg(ev, legBoundary));
406
+ if (currentSub.length > 0) {
407
+ block += `\n## Subagent Tasks`;
408
+ for (const ev of currentSub) block += `\n- ${fmt(ev)}`;
409
+ block += `\n`;
410
+ }
411
+ if (priorSub.length > 0) {
412
+ block += `\n## Subagent Tasks (earlier session — not current)`;
413
+ for (const ev of priorSub) block += `\n- ${fmt(ev)}`;
414
+ block += `\n`;
342
415
  }
343
- block += `\n`;
344
416
  }
345
417
 
346
418
  // 10. Skills invoked
@@ -363,13 +435,10 @@ export function buildSessionDirective(source, eventMeta, toolNamer) {
363
435
  block += `\n`;
364
436
  }
365
437
 
366
- // 12. Data references
438
+ // 12. Data references — #840: reference (don't inline) large tool-outputs.
367
439
  if (grouped.data?.length > 0) {
368
440
  block += `\n## Data References`;
369
- for (const ev of grouped.data) {
370
- const text = ev.data.length > 150 ? ev.data.substring(0, 147) + "..." : ev.data;
371
- block += `\n- ${text}`;
372
- }
441
+ renderDataReferences(grouped.data, (l) => { block += `\n${l}`; }, dataSearchHint);
373
442
  block += `\n`;
374
443
  }
375
444
 
@@ -417,7 +486,6 @@ export function buildSessionDirective(source, eventMeta, toolNamer) {
417
486
  // Search on demand — detailed data lives in FTS5
418
487
  block += `\n<session_search>`;
419
488
  block += `\nDetailed session data is indexed in context-mode FTS5 (source: "session-events").`;
420
- const searchTool = toolNamer ? toolNamer("ctx_search") : "ctx_search";
421
489
  block += `\nUse ${searchTool}(queries: [...], source: "session-events") when you need specifics.`;
422
490
  block += `\nDo NOT call ctx_index() — data is already indexed.`;
423
491
  block += `\n</session_search>`;
@@ -1,2 +1,2 @@
1
- function i(t){return t==null?"":String(t)}function v(t){return t==null?"":typeof t=="string"?t:JSON.stringify(t)}function _(t){let e=String(t.tool_response??""),n=String(t.tool_input?.command??"");if(e.startsWith("context-mode:")||n.startsWith('echo "context-mode:')||n.startsWith("echo 'context-mode:"))return!1;let r=t.tool_output?.isError===!0||t.tool_output?.is_error===!0;return t.tool_name==="Bash"&&/exit code [1-9]|error:|Error:|FAIL|failed/i.test(e)||r}function R(t){if(!t)return[];let e=[];for(let r of t.split(/\r?\n/)){if(r.startsWith("*** Add File: ")){e.push({path:r.slice(14).trim(),type:"file_write"});continue}if(r.startsWith("*** Update File: ")){e.push({path:r.slice(17).trim(),type:"file_edit"});continue}if(r.startsWith("*** Delete File: ")){e.push({path:r.slice(17).trim(),type:"file_edit"});continue}r.startsWith("*** Move to: ")&&e.push({path:r.slice(13).trim(),type:"file_edit"})}let n=new Set;return e.filter(r=>{if(!r.path)return!1;let o=`${r.type}:${r.path}`;return n.has(o)?!1:(n.add(o),!0)})}function S(t){return/(?:^|[/\\])\.claude[/\\]plans[/\\]/.test(t)}function $(t){let{tool_name:e,tool_input:n,tool_response:r}=t,o=[];if(e==="Read"){let s=String(n.file_path??"");return(/(?:CLAUDE|AGENTS(?:\.override)?|GEMINI|QWEN|KIRO)\.md$/i.test(s)||/\/copilot-instructions\.md$/i.test(s)||/\/context-mode\.mdc$/i.test(s)||/\.claude[\\/]/i.test(s)||/[\\/]memor(?:y|ies)[\\/][^\\/]+\.md$/i.test(s))&&(o.push({type:"rule",category:"rule",data:i(s),priority:1}),r&&r.length>0&&o.push({type:"rule_content",category:"rule",data:i(r),priority:1})),o.push({type:"file_read",category:"file",data:i(s),priority:1}),o}if(e==="Edit"){let s=String(n.file_path??"");return o.push({type:"file_edit",category:"file",data:i(s),priority:1}),o}if(e==="NotebookEdit"){let s=String(n.notebook_path??"");return o.push({type:"file_edit",category:"file",data:i(s),priority:1}),o}if(e==="Write"){let s=String(n.file_path??"");return o.push({type:"file_write",category:"file",data:i(s),priority:1}),o}if(e==="apply_patch"){if(_(t))return[];let s=R(String(n.command??n.patch??""));for(let a of s)o.push({type:a.type,category:"file",data:i(a.path),priority:1});return o}if(e==="Glob"){let s=String(n.pattern??"");return o.push({type:"file_glob",category:"file",data:i(s),priority:3}),o}if(e==="Grep"){let s=String(n.pattern??""),a=String(n.path??"");return o.push({type:"file_search",category:"file",data:i(`${s} in ${a}`),priority:3}),o}return o}function I(t){if(t.tool_name!=="Bash")return[];let n=String(t.tool_input.command??"").match(/\bcd\s+("([^"]+)"|'([^']+)'|(\S+))/);if(!n)return[];let r=n[2]??n[3]??n[4]??"";return[{type:"cwd",category:"cwd",data:i(r),priority:2}]}function C(t){let{tool_response:e}=t,n=String(e??"");return _(t)?[{type:"error_tool",category:"error",data:i(n),priority:2}]:[]}var E=[{pattern:/\bgit\s+checkout\b/,operation:"branch"},{pattern:/\bgit\s+commit\b/,operation:"commit"},{pattern:/\bgit\s+merge\s+\S+/,operation:"merge"},{pattern:/\bgit\s+rebase\b/,operation:"rebase"},{pattern:/\bgit\s+stash\b/,operation:"stash"},{pattern:/\bgit\s+push\b/,operation:"push"},{pattern:/\bgit\s+pull\b/,operation:"pull"},{pattern:/\bgit\s+log\b/,operation:"log"},{pattern:/\bgit\s+diff\b/,operation:"diff"},{pattern:/\bgit\s+status\b/,operation:"status"},{pattern:/\bgit\s+branch\b/,operation:"branch"},{pattern:/\bgit\s+reset\b/,operation:"reset"},{pattern:/\bgit\s+add\b/,operation:"add"},{pattern:/\bgit\s+cherry-pick\b/,operation:"cherry-pick"},{pattern:/\bgit\s+tag\b/,operation:"tag"},{pattern:/\bgit\s+fetch\b/,operation:"fetch"},{pattern:/\bgit\s+clone\b/,operation:"clone"},{pattern:/\bgit\s+worktree\b/,operation:"worktree"}];function H(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??""),n=P(e),r;if(n&&n.operation&&(r=E.find(s=>s.operation===n.operation)),r||(r=E.find(s=>s.pattern.test(e))),!r)return[];let o=[];if(n?.scopedDir&&o.push({type:"cwd",category:"cwd",data:i(n.scopedDir),priority:2}),r.operation==="commit"){let s=N(e);if(s)return o.push({type:"git_commit",category:"git",data:i(s),priority:2}),o}return o.push({type:"git",category:"git",data:i(r.operation),priority:2}),o}function O(t){return typeof t!="string"||t.length===0?t:t==="~"?w():t.startsWith("~/")?w()+t.slice(1):t}function w(){try{return process.env.HOME||process.env.USERPROFILE||(process.env.HOMEDRIVE&&process.env.HOMEPATH?process.env.HOMEDRIVE+process.env.HOMEPATH:"")||"~"}catch{return"~"}}function P(t){let e=x(t),n=0;for(;n<e.length&&M(e[n]);)n++;for(;n<e.length&&e[n]!=="git"&&!e[n].endsWith("/git")&&L(e[n]);)n++;if(n>=e.length||e[n]!=="git"&&!e[n].endsWith("/git"))return null;n++;let r=null,o=null;for(;n<e.length;){let s=e[n];if(s==="-C"||s==="--directory"){r=e[n+1]??null,n+=2;continue}if(s.startsWith("--directory=")){r=s.slice(12),n++;continue}if(s.length>0&&s[0]==="-"){n++;continue}o=s;break}return r&&(r=O(r)),{scopedDir:r,operation:o}}function M(t){if(t.length===0)return!1;let e=!1;for(let n=0;n<t.length;n++){let r=t.charCodeAt(n);if(n===0){if(!(r>=65&&r<=90||r===95))return!1}else if(r===61){e=!0;break}else if(!(r>=65&&r<=90||r>=48&&r<=57||r===95))return!1}return e}function L(t){switch(t){case"sudo":case"doas":case"env":case"exec":case"time":return!0;default:return!1}}function x(t){let e=[],n=t.length,r=0;for(;r<n;){for(;r<n&&(t[r]===" "||t[r]===" ");)r++;if(r>=n)break;let o="";for(;r<n&&t[r]!==" "&&t[r]!==" ";){let s=t[r];if(s==='"'||s==="'"){let a=s;for(r++;r<n&&t[r]!==a;)t[r]==="\\"&&r+1<n?(o+=t[r+1],r+=2):(o+=t[r],r++);r<n&&r++}else s==="\\"&&r+1<n?(o+=t[r+1],r+=2):(o+=s,r++)}e.push(o)}return e}function N(t){let e=x(t),n="--message=";for(let r=0;r<e.length;r++){let o=e[r];if(o.length>n.length&&o.startsWith(n)){let s=o.slice(n.length);return s.length>0?s:null}if(o==="--message"){let s=e[r+1];return s&&s.length>0?s:null}if(o.length>=2&&o[0]==="-"&&o[1]!=="-"&&o[o.length-1]==="m"&&j(o,1)){let s=e[r+1];return s&&s.length>0?s:null}}return null}function j(t,e){if(e>=t.length)return!1;for(let n=e;n<t.length;n++){let r=t.charCodeAt(n);if(r<97||r>122)return!1}return!0}function W(t){return new Set(["TodoWrite","TaskCreate","TaskUpdate"]).has(t.tool_name)?[{type:t.tool_name==="TaskUpdate"?"task_update":t.tool_name==="TaskCreate"?"task_create":"task",category:"task",data:i(JSON.stringify(t.tool_input)),priority:1}]:[]}function D(t){let e=2166136261;for(let n=0;n<t.length;n++)e^=t.charCodeAt(n),e=Math.imul(e,16777619);return(e>>>0).toString(16).padStart(8,"0")}function B(t){let e=t.tool_input.plan;if(typeof e=="string"&&e.length>0)return e;let n=t.tool_response;if(typeof n=="string"&&n.length>0)try{let r=JSON.parse(n);if(r&&typeof r=="object"&&typeof r.plan=="string")return r.plan}catch{}return null}function F(t){if(t.tool_name==="EnterPlanMode")return[{type:"plan_enter",category:"plan",data:"entered plan mode",priority:2}];if(t.tool_name==="ExitPlanMode"){let e=[],n=t.tool_input.allowedPrompts,r=Array.isArray(n)&&n.length>0?`exited plan mode (allowed: ${v(n.map(a=>typeof a=="object"&&a!==null&&"prompt"in a?String(a.prompt):String(a)).join(", "))})`:"exited plan mode",o=B(t);typeof o=="string"&&o.length>0&&(r+=` plan_bytes:${o.length} plan_hash:${D(o)}`),e.push({type:"plan_exit",category:"plan",data:i(r),priority:2});let s=String(t.tool_response??"").toLowerCase();return s.includes("approved")||s.includes("approve")?e.push({type:"plan_approved",category:"plan",data:"plan approved by user",priority:1}):(s.includes("rejected")||s.includes("decline")||s.includes("denied"))&&e.push({type:"plan_rejected",category:"plan",data:i(`plan rejected: ${t.tool_response??""}`),priority:2}),e}if(t.tool_name==="Write"||t.tool_name==="Edit"){let e=String(t.tool_input.file_path??"");if(S(e))return[{type:"plan_file_write",category:"plan",data:i(`plan file: ${e.split(/[/\\]/).pop()??e}`),priority:2}]}return t.tool_name==="apply_patch"?_(t)?[]:R(String(t.tool_input.command??t.tool_input.patch??"")).filter(n=>S(n.path)).map(n=>({type:"plan_file_write",category:"plan",data:i(`plan file: ${n.path.split(/[/\\]/).pop()??n.path}`),priority:2})):[]}var U=[/\bsource\s+\S*activate\b/,/\bexport\s+\w+=/,/\bnvm\s+use\b/,/\bpyenv\s+(shell|local|global)\b/,/\bconda\s+activate\b/,/\brbenv\s+(shell|local|global)\b/,/\bnpm\s+install\b/,/\bnpm\s+ci\b/,/\bpip\s+install\b/,/\bbun\s+install\b/,/\byarn\s+(add|install)\b/,/\bpnpm\s+(add|install)\b/,/\bcargo\s+(install|add)\b/,/\bgo\s+(install|get)\b/,/\brustup\b/,/\basdf\b/,/\bvolta\b/,/\bdeno\s+install\b/];function G(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??"");if(!U.some(o=>o.test(e)))return[];let r=e.replace(/\bexport\s+(\w+)=\S*/g,"export $1=***");return[{type:"env",category:"env",data:i(r),priority:2}]}function K(t){if(t.tool_name!=="Skill")return[];let e=String(t.tool_input.skill??"");return[{type:"skill",category:"skill",data:i(e),priority:2}]}function J(t){if(!t.tool_response?.includes("Error")&&!t.tool_output?.isError)return[];let e=String(t.tool_response||""),n=[/not supported/i,/cannot/i,/does not support/i,/FAIL/i,/refused/i,/permission denied/i,/incompatible/i];for(let r of n){let o=e.match(r);if(o){let s=e.toLowerCase().indexOf(o[0].toLowerCase()),a=e.slice(Math.max(0,s-50),Math.min(e.length,s+200)).trim();return[{type:"constraint_discovered",category:"constraint",data:i(a),priority:2}]}}return[]}function q(t){if(t.tool_name!=="Agent")return[];let e=i(String(t.tool_input.prompt??t.tool_input.description??"")),n=t.tool_response?i(String(t.tool_response)):"",r=n.length>0;return[{type:r?"subagent_completed":"subagent_launched",category:"subagent",data:i(r?`[completed] ${e} \u2192 ${n}`:`[launched] ${e}`),priority:r?2:3}]}function z(t){let{tool_name:e,tool_input:n,tool_response:r}=t;if(!e.startsWith("mcp__"))return[];let o=e.split("__"),s=o[o.length-1]||e,a=Object.values(n).find(l=>typeof l=="string"),p=a?`: ${i(String(a))}`:"",c=r&&r.length>0?`
2
- response: ${i(r)}`:"";return[{type:"mcp",category:"mcp",data:i(`${s}${p}${c}`),priority:3}]}var V=2048;function Q(t,e){if(Buffer.byteLength(t,"utf8")<=e)return{value:t,truncated:!1};let n=Buffer.from(t,"utf8"),r=e;for(;r>0&&(n[r]&192)===128;)r--;return{value:n.subarray(0,r).toString("utf8"),truncated:!0}}var X=/(authorization|auth_token|access_token|refresh_token|bearer|token|secret|password|passwd|pwd|api[-_]?key|apikey|cookie|set-cookie|signature|private[-_]?key|client[-_]?secret|x[-_]?api[-_]?key)/i,Y="[REDACTED]";function b(t,e=new WeakSet){if(t==null||typeof t!="object")return t;if(e.has(t))return"[CIRCULAR]";e.add(t);let n;if(Array.isArray(t))n=t.map(r=>b(r,e));else{let r={};for(let[o,s]of Object.entries(t))X.test(o)?r[o]=Y:r[o]=b(s,e);n=r}return e.delete(t),n}function Z(t){let{tool_name:e,tool_input:n}=t;if(!e.startsWith("mcp__"))return[];let r=b(n??{}),o;try{o=JSON.stringify(r)}catch{o="{}"}let{value:s,truncated:a}=Q(o,V),p=a?`{"tool_name":${JSON.stringify(e)},"params_raw":${JSON.stringify(s)},"truncated":true}`:`{"tool_name":${JSON.stringify(e)},"params":${s}}`;return[{type:"mcp_tool_call",category:"mcp_tool_call",data:i(p),priority:4}]}function tt(t){if(t.tool_name!=="AskUserQuestion")return[];let e=t.tool_input.questions,n=Array.isArray(e)&&e.length>0?String(e[0].question??""):"",r=String(t.tool_response??""),o="";try{let c=JSON.parse(r)?.answers;if(c&&typeof c=="object"){let l=g=>typeof g=="string"?g:Array.isArray(g)?g.filter(h=>typeof h=="string").join(" | "):"",u=n?l(c[n]):"";u?o=u:o=Object.values(c).map(l).filter(h=>h.length>0).join(" | ")}}catch{}let s=i(o),a=n?`Q: ${i(n)} \u2192 A: ${s}`:`answer: ${s}`;return[{type:"decision_question",category:"decision",data:i(a),priority:2}]}function et(t){if(t.tool_name!=="Agent")return[];if(!t.tool_response||t.tool_response.length===0)return[];let e=t.tool_response.length>500?t.tool_response.slice(0,500):t.tool_response;return[{type:"agent_finding",category:"agent-finding",data:i(e),priority:2}]}function nt(t){let e=[v(t.tool_input),i(t.tool_response)].join(" ");if(e.length===0)return[];let n=new Set,r=e.match(/https?:\/\/[^\s)]+/g);if(r)for(let c of r)c=c.replace(/["'})\],;.]+$/,""),/localhost|127\.0\.0\.1/i.test(c)||n.add(c);let o=e.match(/(?<!\w)#(\d+)/g);if(o)for(let c of o)n.add(c);if(n.size===0)return[];let s,a=i(t.tool_response).match(/Fetched and indexed[^\(]*\(([\d.]+)\s*KB\)/i);if(a){let c=Number(a[1]);Number.isFinite(c)&&c>0&&(s=Math.round(c*1024))}let p={type:"external_ref",category:"external-ref",data:i(Array.from(n).join(", ")),priority:3};return s!==void 0&&(p.bytes_avoided=s),[p]}function rt(t){if(t.tool_name==="EnterWorktree"){let e=String(t.tool_input.name??"unnamed");return[{type:"worktree",category:"env",data:i(`entered worktree: ${e}`),priority:2}]}if(t.tool_name==="ExitWorktree"){let e=!!t.tool_input.discard_changes;return[{type:"worktree_exit",category:"env",data:i(`exited worktree (discard_changes:${e})`),priority:2}]}return[]}function ot(t){if(typeof t!="string"||t.length===0)return null;let e=t.indexOf("://");if(e<0)return null;let n=e+3;if(n>=t.length)return null;let r=t.length;for(let s=n;s<t.length;s++){let a=t.charCodeAt(s);if(a===47||a===63||a===35){r=s;break}}let o=t.slice(n,r);return o.length>0?o:null}function st(t){if(t.tool_name!=="WebFetch")return[];let e=t.tool_response;if(typeof e!="string"||e.length===0)return[];let n;try{n=JSON.parse(e)}catch{return[]}if(!n||typeof n!="object")return[];let r=n,o=[];if(typeof r.code=="number"&&o.push(`code:${r.code}`),typeof r.bytes=="number"&&o.push(`bytes:${r.bytes}`),typeof r.durationMs=="number"&&o.push(`durMs:${r.durationMs}`),typeof r.url=="string"){let s=ot(r.url);s&&o.push(`host:${s}`)}return o.length===0?[]:[{type:"webfetch_metadata",category:"data",data:i(o.join(" ")),priority:3}]}function it(t){if(t.tool_name!=="Bash")return[];let e=t.tool_response;if(typeof e!="string"||e.length===0)return[];let n;try{n=JSON.parse(e)}catch{return[]}if(!n||typeof n!="object")return[];let r=n;if(!(typeof r.interrupted=="boolean"||typeof r.stderr=="string"||typeof r.returnCodeInterpretation=="string"))return[];let s=[];return typeof r.interrupted=="boolean"&&s.push(`interrupted:${r.interrupted}`),typeof r.returnCodeInterpretation=="string"&&s.push(`rcInterp:${r.returnCodeInterpretation.slice(0,80)}`),typeof r.stderr=="string"&&s.push(`stderrBytes:${r.stderr.length}`),[{type:"bash_outcome",category:"data",data:i(s.join(" ")),priority:3}]}function at(t){if(t.tool_name!=="Read")return[];let e=t.tool_response;if(typeof e!="string"||e.length===0)return[];let n;try{n=JSON.parse(e)}catch{return[]}if(!n||typeof n!="object")return[];let r=n,o=r.type;if(o!=="text"&&o!=="image")return[];let s=[`type:${o}`];if(o==="text")typeof r.numLines=="number"&&s.push(`lines:${r.numLines}`),typeof r.totalLines=="number"&&s.push(`totalLines:${r.totalLines}`),typeof r.startLine=="number"&&s.push(`start:${r.startLine}`);else{typeof r.originalSize=="number"&&s.push(`origSize:${r.originalSize}`);let a=r.dimensions;if(a&&typeof a=="object"){let p=a;typeof p.width=="number"&&typeof p.height=="number"&&s.push(`dims:${p.width}x${p.height}`)}}return[{type:"file_read_metadata",category:"data",data:i(s.join(" ")),priority:3}]}var y={"claude-opus-4-8":{input:5,output:25,cache_write:6.25,cache_read:.5},"claude-opus-4-7":{input:5,output:25,cache_write:6.25,cache_read:.5},"claude-sonnet-4-6":{input:3,output:15,cache_write:3.75,cache_read:.3},"claude-haiku-4-5":{input:1,output:5,cache_write:1.25,cache_read:.1},default:{input:3,output:15,cache_write:3.75,cache_read:.3}};function ct(t,e){let n=[t.tool_input?.model,t.model,e.model],r=Object.keys(y).filter(o=>o!=="default");for(let o of n)if(!(typeof o!="string"||o.length===0)){if(o in y)return o;for(let s of r)if(o.startsWith(s))return s}return"default"}function pt(t,e,n,r,o){let s=y[t]??y.default;return(e*s.input+n*s.output+r*s.cache_write+o*s.cache_read)/1e6}function lt(t){if(t.tool_name!=="Task")return[];let e=t.tool_response;if(typeof e!="string"||e.length===0)return[];let n;try{n=JSON.parse(e)}catch{return[]}if(!n||typeof n!="object")return[];let r=n,o=r.usage&&typeof r.usage=="object"?r.usage:{};if(!(typeof r.totalTokens=="number"||typeof r.totalDurationMs=="number"||typeof o.input_tokens=="number"||typeof o.output_tokens=="number"||typeof o.service_tier=="string"))return[];let a=[];typeof r.totalTokens=="number"&&a.push(`totalTokens:${r.totalTokens}`),typeof r.totalDurationMs=="number"&&a.push(`totalDurMs:${r.totalDurationMs}`),typeof o.input_tokens=="number"&&a.push(`tokens_in:${o.input_tokens}`),typeof o.output_tokens=="number"&&a.push(`tokens_out:${o.output_tokens}`),typeof o.cache_creation_input_tokens=="number"&&a.push(`cache_create:${o.cache_creation_input_tokens}`),typeof o.cache_read_input_tokens=="number"&&a.push(`cache_read:${o.cache_read_input_tokens}`),typeof o.service_tier=="string"&&a.push(`tier:${o.service_tier.slice(0,32)}`);let p=typeof o.input_tokens=="number"?o.input_tokens:0,c=typeof o.output_tokens=="number"?o.output_tokens:0,l=typeof o.cache_creation_input_tokens=="number"?o.cache_creation_input_tokens:0,u=typeof o.cache_read_input_tokens=="number"?o.cache_read_input_tokens:0;if(p>0||c>0||l>0||u>0){let h=ct(t,r),A=pt(h,p,c,l,u);a.push(`cost_usd:${A.toFixed(6).replace(/0+$/,"").replace(/\.$/,".0")}`)}return[{type:"agent_usage",category:"cost",data:i(a.join(" ")),priority:2}]}var T=/[,;,;、،]/u,ut=15,ft=500;function dt(t){if(m.test(t)||!k.test(t)||!T.test(t))return!1;let e=[...t].length;return e>=ut&&e<=ft}function gt(t){let e=t.trim();return dt(e)?[{type:"decision",category:"decision",data:i(t),priority:2}]:[]}var ht=8,_t=120,yt=new RegExp("\\p{L}+\\s+\\p{L}+","u"),mt=new RegExp("\\p{L}{6,}","u");function bt(t){let e=t.split(/[.!\n。!]/u)[0].trim();if(m.test(e)||T.test(e)||!k.test(e))return!1;let n=[...e].length;return n<ht||n>_t?!1:yt.test(e)||mt.test(e)}function kt(t){let e=t.trim();return bt(e)?[{type:"role",category:"role",data:i(t),priority:3}]:[]}var m=/[??؟¿]/u,k=new RegExp("\\p{L}","u"),St=60;function Et(t){if(m.test(t)||!k.test(t))return!1;let e=[...t].length;return e>0&&e<St}function wt(t){let e=t.trim();if(!e)return[];let n;return m.test(e)?n="investigate":Et(e)&&(n="implement"),n?[{type:"intent",category:"intent",data:i(n),priority:4}]:[]}var vt=/^(?:\/goal\s+|(?:goal|objective)\s*:\s*)(.+)$/is;function Rt(t){let e=t.trim();if(!e)return[];let n=e.match(vt);if(!n)return[];let r=n[1].trim();return r?[{type:"goal",category:"goal",data:i(r),priority:4}]:[]}var xt=/(?:\bError\s*:|\bException\s*:|\bTraceback\b|\bat\s+\S+\s*\([^)]*:\d+:\d+\))/u,Tt=/[✓✔✅☑🎉]/u,At=/^\s*(?:fixed|resolved)\s*:/iu;function $t(t){let e=[];return Tt.test(t)||At.test(t)?(e.push({type:"blocker_resolved",category:"blocked-on",data:i(t),priority:2}),e):(xt.test(t)&&e.push({type:"blocker",category:"blocked-on",data:i(t),priority:2}),e)}function It(t){return t.length<=1024?[]:[{type:"data",category:"data",data:i(t),priority:4}]}var f=null;function Ct(t){let{tool_name:e,tool_response:n}=t,r=String(n??"");if(_(t))return f={tool:e,error:r.slice(0,200),callsSince:0},[];if(!f)return[];if(f.callsSince++,f.callsSince>10)return f=null,[];if(!!_(t))return[];let s=e===f.tool,a=f.tool==="Read"&&(e==="Edit"||e==="Write"||e==="apply_patch");if(s||a){let p={type:"error_resolved",category:"error-resolution",data:i(`Error in ${f.tool}: ${f.error} \u2192 Fixed`),priority:2};return f=null,[p]}return[]}function Wt(){f=null}var d=[];function Ht(t){return`${t.length}:${t.slice(0,20)}`}function Ot(t){let{tool_name:e,tool_input:n}=t,r=Ht(JSON.stringify(n).slice(0,200));if(d.push({tool:e,inputHash:r}),d.length>50&&d.splice(0,d.length-50),d.length<3)return[];let o=0;for(let s=d.length-1;s>=0&&(d[s].tool===e&&d[s].inputHash===r);s--)o++;return o>=3?(d.splice(d.length-o),[{type:"retry_detected",category:"iteration-loop",data:i(`${e} called ${o} times with similar input`),priority:2}]):[]}function Dt(){d.length=0}var Pt={run_shell_command:"Bash",read_file:"Read",read_many_files:"Read",grep_search:"Grep",search_file_content:"Grep",web_fetch:"WebFetch",write_file:"Write",edit:"Edit",glob:"Glob",todo_write:"TodoWrite",ask_user_question:"AskUserQuestion",list_directory:"LS",save_memory:"Memory",skill:"Skill",exit_plan_mode:"ExitPlanMode",agent:"Agent",bash:"Bash",view:"Read",grep:"Grep",fetch:"WebFetch",shell:"Bash",shell_command:"Bash",exec_command:"Bash","container.exec":"Bash",local_shell:"Bash",grep_files:"Grep"};function Mt(t){let e=Pt[t.tool_name];return!e||e===t.tool_name?t:{...t,tool_name:e}}function Bt(t){try{let e=Mt(t),n=[];return n.push(...$(e)),n.push(...I(e)),n.push(...C(e)),n.push(...H(e)),n.push(...G(e)),n.push(...W(e)),n.push(...F(e)),n.push(...K(e)),n.push(...q(e)),n.push(...z(e)),n.push(...Z(e)),n.push(...tt(e)),n.push(...J(e)),n.push(...rt(e)),n.push(...st(e)),n.push(...it(e)),n.push(...at(e)),n.push(...lt(e)),n.push(...et(e)),n.push(...nt(e)),n.push(...Ct(e)),n.push(...Ot(e)),n}catch{return[]}}function Ft(t){try{let e=[];return e.push(...jt(t)),e.push(...gt(t)),e.push(...kt(t)),e.push(...wt(t)),e.push(...Rt(t)),e.push(...$t(t)),e.push(...It(t)),e}catch{return[]}}function Ut(t){if(!t||typeof t!="object")return[];let e=t,n=[],r=e.mcp_servers,o=null;return r&&typeof r=="object"&&!Array.isArray(r)&&(o=Object.keys(r),n.push(`mcp_count:${o.length}`),o.length>0&&n.push(`mcp_servers:${o.slice(0,8).join(",")}`)),typeof e.model=="string"&&n.push(`model:${e.model.slice(0,64)}`),typeof e.permission_mode=="string"&&n.push(`permission_mode:${e.permission_mode.slice(0,32)}`),n.length===0?[]:[{type:"session_settings_snapshot",category:"env",data:i(n.join(" ")),priority:2}]}var Lt=["Latin","Cyrillic","Arabic","Han","Hangul","Hiragana","Katakana","Devanagari","Hebrew","Thai","Greek"],Nt={prompt_length:0,prompt_word_count:0,prompt_uppercase_ratio:0,prompt_file_ref_count:0,prompt_path_ref_count:0,prompt_script_primary:null,prompt_script_count:0,prompt_question_glyph_count:0,prompt_code_block_count:0,prompt_url_count:0,prompt_word_tokens:[]};function Gt(t){if(typeof t!="string"||t.length===0)return{...Nt,prompt_word_tokens:[]};let e=t.match(new RegExp("\\p{L}+","gu"))??[],n=(t.match(new RegExp("\\p{Lu}","gu"))??[]).length,r=e.join("").length,o=(t.match(/```/g)??[]).length,s={};for(let l of Lt){let u=new RegExp(`\\p{Script=${l}}`,"gu"),g=(t.match(u)??[]).length;g>0&&(s[l]=g)}let a=Object.entries(s).sort((l,u)=>u[1]-l[1])[0]?.[0]??null,p=new Set,c=[];for(let l of e){if(l.length<3)continue;let u=l.toLowerCase();p.has(u)||(p.add(u),c.push(u))}return{prompt_length:t.length,prompt_word_count:e.length,prompt_uppercase_ratio:r===0?0:n/r,prompt_file_ref_count:(t.match(/(\w+\/)+\w+\.\w+/g)??[]).length,prompt_path_ref_count:(t.match(/\.{0,2}\/[\w\/.-]+/g)??[]).length,prompt_script_primary:a,prompt_script_count:Object.keys(s).length,prompt_question_glyph_count:(t.match(/[??؟]/gu)??[]).length,prompt_code_block_count:Math.floor(o/2),prompt_url_count:(t.match(/https?:\/\/[^\s]+/gu)??[]).length,prompt_word_tokens:c}}function jt(t){if(typeof t!="string"||t.length===0)return[];let e=0;for(;e<t.length;){let o=t.charCodeAt(e);if(o!==32&&o!==9)break;e++}if(e+5>t.length)return[];if(t.slice(e,e+5)!=="/plan")return[];if(e+5<t.length){let o=t.charCodeAt(e+5);if(!(o===32||o===9||o===10||o===13))return[]}let n=t.slice(e+5).trim(),r=n.length>0?`plan via /plan slash: ${n.slice(0,120)}`:"plan via /plan slash";return[{type:"plan_enter",category:"plan",data:i(r),priority:2}]}export{Bt as extractEvents,Ut as extractSessionSettings,Ft as extractUserEvents,Gt as extractUserPromptFeatures,Wt as resetErrorResolutionState,Dt as resetIterationLoopState};
1
+ function i(t){return t==null?"":String(t)}function v(t){return t==null?"":typeof t=="string"?t:JSON.stringify(t)}function _(t){let e=String(t.tool_response??""),n=String(t.tool_input?.command??"");if(e.startsWith("context-mode:")||n.startsWith('echo "context-mode:')||n.startsWith("echo 'context-mode:"))return!1;let r=t.tool_output?.isError===!0||t.tool_output?.is_error===!0;return t.tool_name==="Bash"&&/exit code [1-9]|error:|Error:|FAIL|failed/i.test(e)||r}function R(t){if(!t)return[];let e=[];for(let r of t.split(/\r?\n/)){if(r.startsWith("*** Add File: ")){e.push({path:r.slice(14).trim(),type:"file_write"});continue}if(r.startsWith("*** Update File: ")){e.push({path:r.slice(17).trim(),type:"file_edit"});continue}if(r.startsWith("*** Delete File: ")){e.push({path:r.slice(17).trim(),type:"file_edit"});continue}r.startsWith("*** Move to: ")&&e.push({path:r.slice(13).trim(),type:"file_edit"})}let n=new Set;return e.filter(r=>{if(!r.path)return!1;let o=`${r.type}:${r.path}`;return n.has(o)?!1:(n.add(o),!0)})}function S(t){return/(?:^|[/\\])\.claude[/\\]plans[/\\]/.test(t)}function I(t){let{tool_name:e,tool_input:n,tool_response:r}=t,o=[];if(e==="Read"){let s=String(n.file_path??"");return(/(?:CLAUDE|AGENTS(?:\.override)?|GEMINI|QWEN|KIRO)\.md$/i.test(s)||/\/copilot-instructions\.md$/i.test(s)||/\/context-mode\.mdc$/i.test(s)||/\.claude[\\/]/i.test(s)||/[\\/]memor(?:y|ies)[\\/][^\\/]+\.md$/i.test(s))&&(o.push({type:"rule",category:"rule",data:i(s),priority:1}),r&&r.length>0&&o.push({type:"rule_content",category:"rule",data:i(r),priority:1})),o.push({type:"file_read",category:"file",data:i(s),priority:1}),o}if(e==="Edit"){let s=String(n.file_path??"");return o.push({type:"file_edit",category:"file",data:i(s),priority:1}),o}if(e==="NotebookEdit"){let s=String(n.notebook_path??"");return o.push({type:"file_edit",category:"file",data:i(s),priority:1}),o}if(e==="Write"){let s=String(n.file_path??"");return o.push({type:"file_write",category:"file",data:i(s),priority:1}),o}if(e==="apply_patch"){if(_(t))return[];let s=R(String(n.command??n.patch??""));for(let a of s)o.push({type:a.type,category:"file",data:i(a.path),priority:1});return o}if(e==="Glob"){let s=String(n.pattern??"");return o.push({type:"file_glob",category:"file",data:i(s),priority:3}),o}if(e==="Grep"){let s=String(n.pattern??""),a=String(n.path??"");return o.push({type:"file_search",category:"file",data:i(`${s} in ${a}`),priority:3}),o}return o}function $(t){if(t.tool_name!=="Bash")return[];let n=String(t.tool_input.command??"").match(/\bcd\s+("([^"]+)"|'([^']+)'|(\S+))/);if(!n)return[];let r=n[2]??n[3]??n[4]??"";return[{type:"cwd",category:"cwd",data:i(r),priority:2}]}function O(t){let{tool_response:e}=t,n=String(e??"");return _(t)?[{type:"error_tool",category:"error",data:i(n),priority:2}]:[]}var E=[{pattern:/\bgit\s+checkout\b/,operation:"branch"},{pattern:/\bgit\s+commit\b/,operation:"commit"},{pattern:/\bgit\s+merge\s+\S+/,operation:"merge"},{pattern:/\bgit\s+rebase\b/,operation:"rebase"},{pattern:/\bgit\s+stash\b/,operation:"stash"},{pattern:/\bgit\s+push\b/,operation:"push"},{pattern:/\bgit\s+pull\b/,operation:"pull"},{pattern:/\bgit\s+log\b/,operation:"log"},{pattern:/\bgit\s+diff\b/,operation:"diff"},{pattern:/\bgit\s+status\b/,operation:"status"},{pattern:/\bgit\s+branch\b/,operation:"branch"},{pattern:/\bgit\s+reset\b/,operation:"reset"},{pattern:/\bgit\s+add\b/,operation:"add"},{pattern:/\bgit\s+cherry-pick\b/,operation:"cherry-pick"},{pattern:/\bgit\s+tag\b/,operation:"tag"},{pattern:/\bgit\s+fetch\b/,operation:"fetch"},{pattern:/\bgit\s+clone\b/,operation:"clone"},{pattern:/\bgit\s+worktree\b/,operation:"worktree"}];function C(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??""),n=P(e),r;if(n&&n.operation&&(r=E.find(s=>s.operation===n.operation)),r||(r=E.find(s=>s.pattern.test(e))),!r)return[];let o=[];if(n?.scopedDir&&o.push({type:"cwd",category:"cwd",data:i(n.scopedDir),priority:2}),r.operation==="commit"){let s=N(e);if(s)return o.push({type:"git_commit",category:"git",data:i(s),priority:2}),o}return o.push({type:"git",category:"git",data:i(r.operation),priority:2}),o}function L(t){return typeof t!="string"||t.length===0?t:t==="~"?w():t.startsWith("~/")?w()+t.slice(1):t}function w(){try{return process.env.HOME||process.env.USERPROFILE||(process.env.HOMEDRIVE&&process.env.HOMEPATH?process.env.HOMEDRIVE+process.env.HOMEPATH:"")||"~"}catch{return"~"}}function P(t){let e=x(t),n=0;for(;n<e.length&&H(e[n]);)n++;for(;n<e.length&&e[n]!=="git"&&!e[n].endsWith("/git")&&M(e[n]);)n++;if(n>=e.length||e[n]!=="git"&&!e[n].endsWith("/git"))return null;n++;let r=null,o=null;for(;n<e.length;){let s=e[n];if(s==="-C"||s==="--directory"){r=e[n+1]??null,n+=2;continue}if(s.startsWith("--directory=")){r=s.slice(12),n++;continue}if(s.length>0&&s[0]==="-"){n++;continue}o=s;break}return r&&(r=L(r)),{scopedDir:r,operation:o}}function H(t){if(t.length===0)return!1;let e=!1;for(let n=0;n<t.length;n++){let r=t.charCodeAt(n);if(n===0){if(!(r>=65&&r<=90||r===95))return!1}else if(r===61){e=!0;break}else if(!(r>=65&&r<=90||r>=48&&r<=57||r===95))return!1}return e}function M(t){switch(t){case"sudo":case"doas":case"env":case"exec":case"time":return!0;default:return!1}}function x(t){let e=[],n=t.length,r=0;for(;r<n;){for(;r<n&&(t[r]===" "||t[r]===" ");)r++;if(r>=n)break;let o="";for(;r<n&&t[r]!==" "&&t[r]!==" ";){let s=t[r];if(s==='"'||s==="'"){let a=s;for(r++;r<n&&t[r]!==a;)t[r]==="\\"&&r+1<n?(o+=t[r+1],r+=2):(o+=t[r],r++);r<n&&r++}else s==="\\"&&r+1<n?(o+=t[r+1],r+=2):(o+=s,r++)}e.push(o)}return e}function N(t){let e=x(t),n="--message=";for(let r=0;r<e.length;r++){let o=e[r];if(o.length>n.length&&o.startsWith(n)){let s=o.slice(n.length);return s.length>0?s:null}if(o==="--message"){let s=e[r+1];return s&&s.length>0?s:null}if(o.length>=2&&o[0]==="-"&&o[1]!=="-"&&o[o.length-1]==="m"&&j(o,1)){let s=e[r+1];return s&&s.length>0?s:null}}return null}function j(t,e){if(e>=t.length)return!1;for(let n=e;n<t.length;n++){let r=t.charCodeAt(n);if(r<97||r>122)return!1}return!0}function W(t){return new Set(["TodoWrite","TaskCreate","TaskUpdate"]).has(t.tool_name)?[{type:t.tool_name==="TaskUpdate"?"task_update":t.tool_name==="TaskCreate"?"task_create":"task",category:"task",data:i(JSON.stringify(t.tool_input)),priority:1}]:[]}function D(t){let e=2166136261;for(let n=0;n<t.length;n++)e^=t.charCodeAt(n),e=Math.imul(e,16777619);return(e>>>0).toString(16).padStart(8,"0")}function F(t){let e=t.tool_input.plan;if(typeof e=="string"&&e.length>0)return e;let n=t.tool_response;if(typeof n=="string"&&n.length>0)try{let r=JSON.parse(n);if(r&&typeof r=="object"&&typeof r.plan=="string")return r.plan}catch{}return null}function B(t){if(t.tool_name==="EnterPlanMode")return[{type:"plan_enter",category:"plan",data:"entered plan mode",priority:2}];if(t.tool_name==="ExitPlanMode"){let e=[],n=t.tool_input.allowedPrompts,r=Array.isArray(n)&&n.length>0?`exited plan mode (allowed: ${v(n.map(a=>typeof a=="object"&&a!==null&&"prompt"in a?String(a.prompt):String(a)).join(", "))})`:"exited plan mode",o=F(t);typeof o=="string"&&o.length>0&&(r+=` plan_bytes:${o.length} plan_hash:${D(o)}`),e.push({type:"plan_exit",category:"plan",data:i(r),priority:2});let s=String(t.tool_response??"").toLowerCase();return s.includes("approved")||s.includes("approve")?e.push({type:"plan_approved",category:"plan",data:"plan approved by user",priority:1}):(s.includes("rejected")||s.includes("decline")||s.includes("denied"))&&e.push({type:"plan_rejected",category:"plan",data:i(`plan rejected: ${t.tool_response??""}`),priority:2}),e}if(t.tool_name==="Write"||t.tool_name==="Edit"){let e=String(t.tool_input.file_path??"");if(S(e))return[{type:"plan_file_write",category:"plan",data:i(`plan file: ${e.split(/[/\\]/).pop()??e}`),priority:2}]}return t.tool_name==="apply_patch"?_(t)?[]:R(String(t.tool_input.command??t.tool_input.patch??"")).filter(n=>S(n.path)).map(n=>({type:"plan_file_write",category:"plan",data:i(`plan file: ${n.path.split(/[/\\]/).pop()??n.path}`),priority:2})):[]}var U=[/\bsource\s+\S*activate\b/,/\bexport\s+\w+=/,/\bnvm\s+use\b/,/\bpyenv\s+(shell|local|global)\b/,/\bconda\s+activate\b/,/\brbenv\s+(shell|local|global)\b/,/\bnpm\s+install\b/,/\bnpm\s+ci\b/,/\bpip\s+install\b/,/\bbun\s+install\b/,/\byarn\s+(add|install)\b/,/\bpnpm\s+(add|install)\b/,/\bcargo\s+(install|add)\b/,/\bgo\s+(install|get)\b/,/\brustup\b/,/\basdf\b/,/\bvolta\b/,/\bdeno\s+install\b/];function K(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??"");if(!U.some(o=>o.test(e)))return[];let r=e.replace(/\bexport\s+(\w+)=\S*/g,"export $1=***");return[{type:"env",category:"env",data:i(r),priority:2}]}function G(t){if(t.tool_name!=="Skill")return[];let e=String(t.tool_input.skill??"");return[{type:"skill",category:"skill",data:i(e),priority:2}]}function J(t){if(!t.tool_response?.includes("Error")&&!t.tool_output?.isError)return[];let e=String(t.tool_response||""),n=[/not supported/i,/cannot/i,/does not support/i,/FAIL/i,/refused/i,/permission denied/i,/incompatible/i];for(let r of n){let o=e.match(r);if(o){let s=e.toLowerCase().indexOf(o[0].toLowerCase()),a=e.slice(Math.max(0,s-50),Math.min(e.length,s+200)).trim();return[{type:"constraint_discovered",category:"constraint",data:i(a),priority:2}]}}return[]}function q(t){if(t.tool_name!=="Agent")return[];let e=i(String(t.tool_input.prompt??t.tool_input.description??"")),n=t.tool_response?i(String(t.tool_response)):"",r=n.length>0;return[{type:r?"subagent_completed":"subagent_launched",category:"subagent",data:i(r?`[completed] ${e} \u2192 ${n}`:`[launched] ${e}`),priority:r?2:3}]}function z(t){let{tool_name:e,tool_input:n,tool_response:r}=t;if(!e.startsWith("mcp__"))return[];let o=e.split("__"),s=o[o.length-1]||e,a=Object.values(n).find(p=>typeof p=="string"),l=a?`: ${i(String(a))}`:"",c=r&&r.length>0?`
2
+ response: ${i(r)}`:"";return[{type:"mcp",category:"mcp",data:i(`${s}${l}${c}`),priority:3}]}var V=2048;function X(t,e){if(Buffer.byteLength(t,"utf8")<=e)return{value:t,truncated:!1};let n=Buffer.from(t,"utf8"),r=e;for(;r>0&&(n[r]&192)===128;)r--;return{value:n.subarray(0,r).toString("utf8"),truncated:!0}}var Q=/(authorization|auth_token|access_token|refresh_token|bearer|token|secret|password|passwd|pwd|api[-_]?key|apikey|cookie|set-cookie|signature|private[-_]?key|client[-_]?secret|x[-_]?api[-_]?key)/i,Y="[REDACTED]";function b(t,e=new WeakSet){if(t==null||typeof t!="object")return t;if(e.has(t))return"[CIRCULAR]";e.add(t);let n;if(Array.isArray(t))n=t.map(r=>b(r,e));else{let r={};for(let[o,s]of Object.entries(t))Q.test(o)?r[o]=Y:r[o]=b(s,e);n=r}return e.delete(t),n}function Z(t){let{tool_name:e,tool_input:n}=t;if(!e.startsWith("mcp__"))return[];let r=b(n??{}),o;try{o=JSON.stringify(r)}catch{o="{}"}let{value:s,truncated:a}=X(o,V),l=a?`{"tool_name":${JSON.stringify(e)},"params_raw":${JSON.stringify(s)},"truncated":true}`:`{"tool_name":${JSON.stringify(e)},"params":${s}}`;return[{type:"mcp_tool_call",category:"mcp_tool_call",data:i(l),priority:4}]}function tt(t){if(t.tool_name!=="AskUserQuestion")return[];let e=t.tool_input.questions,n=Array.isArray(e)&&e.length>0?String(e[0].question??""):"",r=String(t.tool_response??""),o="";try{let c=JSON.parse(r)?.answers;if(c&&typeof c=="object"){let p=h=>typeof h=="string"?h:Array.isArray(h)?h.filter(g=>typeof g=="string").join(" | "):"",u=n?p(c[n]):"";u?o=u:o=Object.values(c).map(p).filter(g=>g.length>0).join(" | ")}}catch{}let s=i(o),a=n?`Q: ${i(n)} \u2192 A: ${s}`:`answer: ${s}`;return[{type:"decision_question",category:"decision",data:i(a),priority:2}]}function et(t){if(t.tool_name!=="Agent")return[];if(!t.tool_response||t.tool_response.length===0)return[];let e=t.tool_response.length>500?t.tool_response.slice(0,500):t.tool_response;return[{type:"agent_finding",category:"agent-finding",data:i(e),priority:2}]}function nt(t){let e=[v(t.tool_input),i(t.tool_response)].join(" ");if(e.length===0)return[];let n=new Set,r=e.match(/https?:\/\/[^\s)]+/g);if(r)for(let c of r)c=c.replace(/["'})\],;.]+$/,""),/localhost|127\.0\.0\.1/i.test(c)||n.add(c);let o=e.match(/(?<!\w)#(\d+)/g);if(o)for(let c of o)n.add(c);if(n.size===0)return[];let s,a=i(t.tool_response).match(/Fetched and indexed[^\(]*\(([\d.]+)\s*KB\)/i);if(a){let c=Number(a[1]);Number.isFinite(c)&&c>0&&(s=Math.round(c*1024))}let l={type:"external_ref",category:"external-ref",data:i(Array.from(n).join(", ")),priority:3};return s!==void 0&&(l.bytes_avoided=s),[l]}function rt(t){if(t.tool_name==="EnterWorktree"){let e=String(t.tool_input.name??"unnamed");return[{type:"worktree",category:"env",data:i(`entered worktree: ${e}`),priority:2}]}if(t.tool_name==="ExitWorktree"){let e=!!t.tool_input.discard_changes;return[{type:"worktree_exit",category:"env",data:i(`exited worktree (discard_changes:${e})`),priority:2}]}return[]}function ot(t){if(typeof t!="string"||t.length===0)return null;let e=t.indexOf("://");if(e<0)return null;let n=e+3;if(n>=t.length)return null;let r=t.length;for(let s=n;s<t.length;s++){let a=t.charCodeAt(s);if(a===47||a===63||a===35){r=s;break}}let o=t.slice(n,r);return o.length>0?o:null}function st(t){if(t.tool_name!=="WebFetch")return[];let e=t.tool_response;if(typeof e!="string"||e.length===0)return[];let n;try{n=JSON.parse(e)}catch{return[]}if(!n||typeof n!="object")return[];let r=n,o=[];if(typeof r.code=="number"&&o.push(`code:${r.code}`),typeof r.bytes=="number"&&o.push(`bytes:${r.bytes}`),typeof r.durationMs=="number"&&o.push(`durMs:${r.durationMs}`),typeof r.url=="string"){let s=ot(r.url);s&&o.push(`host:${s}`)}return o.length===0?[]:[{type:"webfetch_metadata",category:"data",data:i(o.join(" ")),priority:3}]}function it(t){if(t.tool_name!=="Bash")return[];let e=t.tool_response;if(typeof e!="string"||e.length===0)return[];let n;try{n=JSON.parse(e)}catch{return[]}if(!n||typeof n!="object")return[];let r=n;if(!(typeof r.interrupted=="boolean"||typeof r.stderr=="string"||typeof r.returnCodeInterpretation=="string"))return[];let s=[];return typeof r.interrupted=="boolean"&&s.push(`interrupted:${r.interrupted}`),typeof r.returnCodeInterpretation=="string"&&s.push(`rcInterp:${r.returnCodeInterpretation.slice(0,80)}`),typeof r.stderr=="string"&&s.push(`stderrBytes:${r.stderr.length}`),[{type:"bash_outcome",category:"data",data:i(s.join(" ")),priority:3}]}function at(t){if(t.tool_name!=="Read")return[];let e=t.tool_response;if(typeof e!="string"||e.length===0)return[];let n;try{n=JSON.parse(e)}catch{return[]}if(!n||typeof n!="object")return[];let r=n,o=r.type;if(o!=="text"&&o!=="image")return[];let s=[`type:${o}`];if(o==="text")typeof r.numLines=="number"&&s.push(`lines:${r.numLines}`),typeof r.totalLines=="number"&&s.push(`totalLines:${r.totalLines}`),typeof r.startLine=="number"&&s.push(`start:${r.startLine}`);else{typeof r.originalSize=="number"&&s.push(`origSize:${r.originalSize}`);let a=r.dimensions;if(a&&typeof a=="object"){let l=a;typeof l.width=="number"&&typeof l.height=="number"&&s.push(`dims:${l.width}x${l.height}`)}}return[{type:"file_read_metadata",category:"data",data:i(s.join(" ")),priority:3}]}var y={"claude-opus-4-8":{input:5,output:25,cache_write:6.25,cache_read:.5},"claude-opus-4-7":{input:5,output:25,cache_write:6.25,cache_read:.5},"claude-sonnet-4-6":{input:3,output:15,cache_write:3.75,cache_read:.3},"claude-haiku-4-5":{input:1,output:5,cache_write:1.25,cache_read:.1},default:{input:3,output:15,cache_write:3.75,cache_read:.3}};function ct(t,e){let n=[t.tool_input?.model,t.model,e.model],r=Object.keys(y).filter(o=>o!=="default");for(let o of n)if(!(typeof o!="string"||o.length===0)){if(o in y)return o;for(let s of r)if(o.startsWith(s))return s}return"default"}function lt(t,e,n,r,o){let s=y[t]??y.default;return(e*s.input+n*s.output+r*s.cache_write+o*s.cache_read)/1e6}function pt(t){if(t.tool_name!=="Task")return[];let e=t.tool_response;if(typeof e!="string"||e.length===0)return[];let n;try{n=JSON.parse(e)}catch{return[]}if(!n||typeof n!="object")return[];let r=n,o=r.usage&&typeof r.usage=="object"?r.usage:{};if(!(typeof r.totalTokens=="number"||typeof r.totalDurationMs=="number"||typeof o.input_tokens=="number"||typeof o.output_tokens=="number"||typeof o.service_tier=="string"))return[];let a=[];typeof r.totalTokens=="number"&&a.push(`totalTokens:${r.totalTokens}`),typeof r.totalDurationMs=="number"&&a.push(`totalDurMs:${r.totalDurationMs}`),typeof o.input_tokens=="number"&&a.push(`tokens_in:${o.input_tokens}`),typeof o.output_tokens=="number"&&a.push(`tokens_out:${o.output_tokens}`),typeof o.cache_creation_input_tokens=="number"&&a.push(`cache_create:${o.cache_creation_input_tokens}`),typeof o.cache_read_input_tokens=="number"&&a.push(`cache_read:${o.cache_read_input_tokens}`),typeof o.service_tier=="string"&&a.push(`tier:${o.service_tier.slice(0,32)}`);let l=typeof o.input_tokens=="number"?o.input_tokens:0,c=typeof o.output_tokens=="number"?o.output_tokens:0,p=typeof o.cache_creation_input_tokens=="number"?o.cache_creation_input_tokens:0,u=typeof o.cache_read_input_tokens=="number"?o.cache_read_input_tokens:0;if(l>0||c>0||p>0||u>0){let g=ct(t,r),A=lt(g,l,c,p,u);a.push(`cost_usd:${A.toFixed(6).replace(/0+$/,"").replace(/\.$/,".0")}`)}return[{type:"agent_usage",category:"cost",data:i(a.join(" ")),priority:2}]}var T=/[,;,;、،]/u,ut=15,ft=500;function dt(t){if(m.test(t)||!k.test(t)||!T.test(t))return!1;let e=[...t].length;return e>=ut&&e<=ft}function ht(t){let e=t.trim();return dt(e)?[{type:"decision",category:"decision",data:i(t),priority:2}]:[]}var gt=8,_t=120,yt=new RegExp("\\p{L}+\\s+\\p{L}+","u"),mt=new RegExp("\\p{L}{6,}","u"),bt=new Set(["ok","okay","sure","yeah","yep","yup","alright","fine","well","so","hmm","right","please"]),kt=["you are","you're","your role","you will be","you act","you will act","act as","act like","behave as","behave like","imagine you","pretend you","assume the role","take the role","play the role","respond as","tu es","tu est","vous etes","vous \xEAtes","sen ","siz ","eres ","t\xFA eres","usted es","\u0442\u044B ","\u0432\u044B ","\u3042\u306A\u305F\u306F","\u541B\u306F","\u304A\u524D\u306F","\u3042\u306A\u305F\u304C","\u4F60\u662F","\u60A8\u662F","\u0924\u0941\u092E ","\u0906\u092A ","\u0924\u0942 ","\u0623\u0646\u062A ","\u0627\u0646\u062A ","\u0623\u0646\u062A\u064E "],St=["always ","never ","respond ","reply ","answer ","speak ","write ","prefer ","format ","output ","communicate ","use only "];function Et(t){let e=t.toLowerCase().trim();if(!e)return!1;let n=e.split(" ").filter(o=>o.length>0);for(;n.length>0&&bt.has(n[0]);)n.shift();let r=n.join(" ");if(!r)return!1;for(let o of kt)if(r.startsWith(o))return!0;for(let o of St)if(r.startsWith(o))return!0;return!1}function wt(t){let e=t.split(/[.!\n。!]/u)[0].trim();if(m.test(e)||T.test(e)||!k.test(e))return!1;let n=[...e].length;return n<gt||n>_t||!Et(e)?!1:yt.test(e)||mt.test(e)}function vt(t){let e=t.trim();return wt(e)?[{type:"role",category:"role",data:i(t),priority:3}]:[]}var m=/[??؟¿]/u,k=new RegExp("\\p{L}","u"),Rt=60;function xt(t){if(m.test(t)||!k.test(t))return!1;let e=[...t].length;return e>0&&e<Rt}function Tt(t){let e=t.trim();if(!e)return[];let n;return m.test(e)?n="investigate":xt(e)&&(n="implement"),n?[{type:"intent",category:"intent",data:i(n),priority:4}]:[]}var At=/^(?:\/goal\s+|(?:goal|objective)\s*:\s*)(.+)$/is;function It(t){let e=t.trim();if(!e)return[];let n=e.match(At);if(!n)return[];let r=n[1].trim();return r?[{type:"goal",category:"goal",data:i(r),priority:4}]:[]}var $t=/(?:\bError\s*:|\bException\s*:|\bTraceback\b|\bat\s+\S+\s*\([^)]*:\d+:\d+\))/u,Ot=/[✓✔✅☑🎉]/u,Ct=/^\s*(?:fixed|resolved)\s*:/iu;function Lt(t){let e=[];return Ot.test(t)||Ct.test(t)?(e.push({type:"blocker_resolved",category:"blocked-on",data:i(t),priority:2}),e):($t.test(t)&&e.push({type:"blocker",category:"blocked-on",data:i(t),priority:2}),e)}function Pt(t){return t.length<=1024?[]:[{type:"data",category:"data",data:i(t),priority:4}]}var f=null;function Ht(t){let{tool_name:e,tool_response:n}=t,r=String(n??"");if(_(t))return f={tool:e,error:r.slice(0,200),callsSince:0},[];if(!f)return[];if(f.callsSince++,f.callsSince>10)return f=null,[];if(!!_(t))return[];let s=e===f.tool,a=f.tool==="Read"&&(e==="Edit"||e==="Write"||e==="apply_patch");if(s||a){let l={type:"error_resolved",category:"error-resolution",data:i(`Error in ${f.tool}: ${f.error} \u2192 Fixed`),priority:2};return f=null,[l]}return[]}function Ut(){f=null}var d=[];function Mt(t){return`${t.length}:${t.slice(0,20)}`}function Nt(t){let{tool_name:e,tool_input:n}=t,r=Mt(JSON.stringify(n).slice(0,200));if(d.push({tool:e,inputHash:r}),d.length>50&&d.splice(0,d.length-50),d.length<3)return[];let o=0;for(let s=d.length-1;s>=0&&(d[s].tool===e&&d[s].inputHash===r);s--)o++;return o>=3?(d.splice(d.length-o),[{type:"retry_detected",category:"iteration-loop",data:i(`${e} called ${o} times with similar input`),priority:2}]):[]}function Kt(){d.length=0}var jt={run_shell_command:"Bash",read_file:"Read",read_many_files:"Read",grep_search:"Grep",search_file_content:"Grep",web_fetch:"WebFetch",write_file:"Write",edit:"Edit",glob:"Glob",todo_write:"TodoWrite",ask_user_question:"AskUserQuestion",list_directory:"LS",save_memory:"Memory",skill:"Skill",exit_plan_mode:"ExitPlanMode",agent:"Agent",bash:"Bash",view:"Read",grep:"Grep",fetch:"WebFetch",shell:"Bash",shell_command:"Bash",exec_command:"Bash","container.exec":"Bash",local_shell:"Bash",grep_files:"Grep",run_command:"Bash",view_file:"Read",read_url_content:"WebFetch",list_dir:"LS",search_web:"WebSearch"};function Wt(t){let e=jt[t.tool_name];return!e||e===t.tool_name?t:{...t,tool_name:e}}function Gt(t){try{let e=Wt(t),n=[];return n.push(...I(e)),n.push(...$(e)),n.push(...O(e)),n.push(...C(e)),n.push(...K(e)),n.push(...W(e)),n.push(...B(e)),n.push(...G(e)),n.push(...q(e)),n.push(...z(e)),n.push(...Z(e)),n.push(...tt(e)),n.push(...J(e)),n.push(...rt(e)),n.push(...st(e)),n.push(...it(e)),n.push(...at(e)),n.push(...pt(e)),n.push(...et(e)),n.push(...nt(e)),n.push(...Ht(e)),n.push(...Nt(e)),n}catch{return[]}}function Jt(t){try{let e=[];return e.push(...Bt(t)),e.push(...ht(t)),e.push(...vt(t)),e.push(...Tt(t)),e.push(...It(t)),e.push(...Lt(t)),e.push(...Pt(t)),e}catch{return[]}}function qt(t){if(!t||typeof t!="object")return[];let e=t,n=[],r=e.mcp_servers,o=null;return r&&typeof r=="object"&&!Array.isArray(r)&&(o=Object.keys(r),n.push(`mcp_count:${o.length}`),o.length>0&&n.push(`mcp_servers:${o.slice(0,8).join(",")}`)),typeof e.model=="string"&&n.push(`model:${e.model.slice(0,64)}`),typeof e.permission_mode=="string"&&n.push(`permission_mode:${e.permission_mode.slice(0,32)}`),n.length===0?[]:[{type:"session_settings_snapshot",category:"env",data:i(n.join(" ")),priority:2}]}var Dt=["Latin","Cyrillic","Arabic","Han","Hangul","Hiragana","Katakana","Devanagari","Hebrew","Thai","Greek"],Ft={prompt_length:0,prompt_word_count:0,prompt_uppercase_ratio:0,prompt_file_ref_count:0,prompt_path_ref_count:0,prompt_script_primary:null,prompt_script_count:0,prompt_question_glyph_count:0,prompt_code_block_count:0,prompt_url_count:0,prompt_word_tokens:[]};function zt(t){if(typeof t!="string"||t.length===0)return{...Ft,prompt_word_tokens:[]};let e=t.match(new RegExp("\\p{L}+","gu"))??[],n=(t.match(new RegExp("\\p{Lu}","gu"))??[]).length,r=e.join("").length,o=(t.match(/```/g)??[]).length,s={};for(let p of Dt){let u=new RegExp(`\\p{Script=${p}}`,"gu"),h=(t.match(u)??[]).length;h>0&&(s[p]=h)}let a=Object.entries(s).sort((p,u)=>u[1]-p[1])[0]?.[0]??null,l=new Set,c=[];for(let p of e){if(p.length<3)continue;let u=p.toLowerCase();l.has(u)||(l.add(u),c.push(u))}return{prompt_length:t.length,prompt_word_count:e.length,prompt_uppercase_ratio:r===0?0:n/r,prompt_file_ref_count:(t.match(/(\w+\/)+\w+\.\w+/g)??[]).length,prompt_path_ref_count:(t.match(/\.{0,2}\/[\w\/.-]+/g)??[]).length,prompt_script_primary:a,prompt_script_count:Object.keys(s).length,prompt_question_glyph_count:(t.match(/[??؟]/gu)??[]).length,prompt_code_block_count:Math.floor(o/2),prompt_url_count:(t.match(/https?:\/\/[^\s]+/gu)??[]).length,prompt_word_tokens:c}}function Bt(t){if(typeof t!="string"||t.length===0)return[];let e=0;for(;e<t.length;){let o=t.charCodeAt(e);if(o!==32&&o!==9)break;e++}if(e+5>t.length)return[];if(t.slice(e,e+5)!=="/plan")return[];if(e+5<t.length){let o=t.charCodeAt(e+5);if(!(o===32||o===9||o===10||o===13))return[]}let n=t.slice(e+5).trim(),r=n.length>0?`plan via /plan slash: ${n.slice(0,120)}`:"plan via /plan slash";return[{type:"plan_enter",category:"plan",data:i(r),priority:2}]}export{Gt as extractEvents,qt as extractSessionSettings,Jt as extractUserEvents,zt as extractUserPromptFeatures,Ut as resetErrorResolutionState,Kt as resetIterationLoopState};
@@ -143,6 +143,19 @@ export const GEMINI_OPTS = {
143
143
  sessionIdEnv: undefined,
144
144
  };
145
145
 
146
+ /**
147
+ * Antigravity CLI (`agy`) platform options. Shares the Gemini-family session
148
+ * root (~/.gemini/context-mode/sessions). agy supplies the conversation id and
149
+ * workspace path inside the hook payload (mapped to session_id/cwd before these
150
+ * opts are consulted), so no env-var fallbacks are needed.
151
+ */
152
+ export const ANTIGRAVITY_CLI_OPTS = {
153
+ configDir: ".gemini",
154
+ configDirEnv: undefined,
155
+ projectDirEnv: undefined,
156
+ sessionIdEnv: undefined,
157
+ };
158
+
146
159
  /** VS Code Copilot platform options. */
147
160
  export const VSCODE_OPTS = {
148
161
  configDir: ".vscode",
@@ -151,6 +164,14 @@ export const VSCODE_OPTS = {
151
164
  sessionIdEnv: undefined,
152
165
  };
153
166
 
167
+ /** GitHub Copilot CLI platform options. */
168
+ export const COPILOT_OPTS = {
169
+ configDir: ".copilot",
170
+ configDirEnv: "COPILOT_HOME",
171
+ projectDirEnv: undefined,
172
+ sessionIdEnv: undefined,
173
+ };
174
+
154
175
  /** Cursor platform options. */
155
176
  export const CURSOR_OPTS = {
156
177
  configDir: ".cursor",
@@ -42,7 +42,7 @@ await runHook(async () => {
42
42
  const { createSessionLoaders, attributeAndInsertEvents } = await import("./session-loaders.mjs");
43
43
  const { join, dirname } = await import("node:path");
44
44
  const { fileURLToPath } = await import("node:url");
45
- const { readFileSync, unlinkSync, readdirSync, rmSync, lstatSync } = await import("node:fs");
45
+ const { readFileSync, unlinkSync, readdirSync, rmSync, lstatSync, realpathSync, symlinkSync } = await import("node:fs");
46
46
 
47
47
  const detectedPlatform = detectPlatformFromEnv();
48
48
  const toolNamer = createToolNamer(detectedPlatform);
@@ -398,12 +398,44 @@ await runHook(async () => {
398
398
  const now = Date.now();
399
399
  for (const d of readdirSync(cacheParent)) {
400
400
  if (d === myDir) continue;
401
+ const oldDir = join(cacheParent, d);
401
402
  try {
402
- const st = lstatSync(join(cacheParent, d));
403
- if (now - st.mtimeMs > ONE_HOUR) {
404
- rmSync(join(cacheParent, d), { recursive: true, force: true });
403
+ const st = lstatSync(oldDir);
404
+ let danglingBreadcrumb = false;
405
+ if (st.isSymbolicLink()) {
406
+ try {
407
+ realpathSync(oldDir);
408
+ } catch {
409
+ danglingBreadcrumb = true;
410
+ }
405
411
  }
406
- } catch { /* skip */ }
412
+ if (danglingBreadcrumb || now - st.mtimeMs > ONE_HOUR) {
413
+ rmSync(oldDir, { recursive: true, force: true });
414
+ // Leave a breadcrumb symlink (junction on Windows) in the
415
+ // removed version's place so sessions that loaded hooks
416
+ // from it before an auto-update keep resolving their
417
+ // scripts instead of erroring on every hook call until
418
+ // restart (#814, #807). Also fires when the entry was
419
+ // itself a stale breadcrumb, re-pointing it at the live
420
+ // root (a chain of updates would otherwise leave links
421
+ // targeting intermediate versions that no longer exist).
422
+ // The fresh mtime makes #644's lstat age gate protect it
423
+ // for the next hour, and the next sweep refreshes it
424
+ // again. Same pattern as healCacheMidSession (server.ts)
425
+ // and postinstall.mjs.
426
+ try {
427
+ symlinkSync(pluginRoot, oldDir, process.platform === "win32" ? "junction" : undefined);
428
+ } catch { /* best effort — plain delete is the pre-#814 behaviour */ }
429
+ }
430
+ } catch {
431
+ // On Windows, a dangling junction can fail before we can read
432
+ // its own mtime. Treat that as a stale breadcrumb and try to
433
+ // repoint it at the live root; failures remain best-effort.
434
+ try {
435
+ rmSync(oldDir, { recursive: true, force: true });
436
+ symlinkSync(pluginRoot, oldDir, process.platform === "win32" ? "junction" : undefined);
437
+ } catch { /* skip */ }
438
+ }
407
439
  }
408
440
  }
409
441
  }
package/hooks/stop.mjs ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ import "./suppress-stderr.mjs";
3
+ import "./ensure-deps.mjs";
4
+ /**
5
+ * Claude Code Stop hook — record turn-end state for continuity.
6
+ *
7
+ * Stop fires when Claude is about to finish the current assistant turn. This is
8
+ * not a true session shutdown event, so record a turn_end marker and never ask
9
+ * Claude to continue.
10
+ */
11
+
12
+ import { readStdin, parseStdin, getSessionId, getSessionDBPath, getInputProjectDir } from "./session-helpers.mjs";
13
+ import { createSessionLoaders } from "./session-loaders.mjs";
14
+ import { dirname } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+
17
+ const HOOK_DIR = dirname(fileURLToPath(import.meta.url));
18
+ const { loadSessionDB } = createSessionLoaders(HOOK_DIR);
19
+
20
+ try {
21
+ const raw = await readStdin();
22
+ const input = parseStdin(raw);
23
+ const projectDir = getInputProjectDir(input);
24
+
25
+ const { SessionDB } = await loadSessionDB();
26
+ const dbPath = getSessionDBPath(undefined, projectDir);
27
+ const db = new SessionDB({ dbPath });
28
+ const sessionId = getSessionId(input);
29
+
30
+ db.ensureSession(sessionId, projectDir);
31
+ const payload = {
32
+ stop_hook_active: input.stop_hook_active ?? false,
33
+ last_assistant_message: typeof input.last_assistant_message === "string"
34
+ ? input.last_assistant_message.slice(0, 2000)
35
+ : null,
36
+ };
37
+ db.insertEvent(sessionId, {
38
+ type: "turn_end",
39
+ category: "session",
40
+ data: JSON.stringify(payload),
41
+ priority: 1,
42
+ }, "Stop");
43
+
44
+ db.close();
45
+ } catch {
46
+ // Claude Code hooks must not block the session.
47
+ }
48
+
49
+ process.stdout.write("{}\n");
@@ -3,7 +3,7 @@
3
3
  "name": "Context Mode",
4
4
  "kind": "tool",
5
5
  "description": "OpenClaw plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
6
- "version": "1.0.162",
6
+ "version": "1.0.164",
7
7
  "sandbox": {
8
8
  "mode": "permissive",
9
9
  "filesystem_access": "full",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.162",
3
+ "version": "1.0.164",
4
4
  "type": "module",
5
5
  "description": "MCP plugin that saves 98% of your context window. Works with Claude Code, Gemini CLI, VS Code Copilot, OpenCode, and Codex CLI. Sandboxed code execution, FTS5 knowledge base, and intent-driven search.",
6
6
  "author": "Mert Koseoğlu",
@@ -62,14 +62,6 @@
62
62
  "build",
63
63
  "hooks",
64
64
  "configs",
65
- "insight/server.mjs",
66
- "insight/package.json",
67
- "insight/tsconfig.json",
68
- "insight/vite.config.ts",
69
- "insight/tailwind.config.ts",
70
- "insight/postcss.config.js",
71
- "insight/index.html",
72
- "insight/src",
73
65
  "server.bundle.mjs",
74
66
  "cli.bundle.mjs",
75
67
  "bin",
@@ -92,7 +84,7 @@
92
84
  "assert-asymmetric-drift": "node scripts/assert-asymmetric-drift.mjs",
93
85
  "bundle": "esbuild src/server.ts --bundle --platform=node --target=node18 --format=esm --outfile=server.bundle.mjs --external:better-sqlite3 --external:turndown --external:turndown-plugin-gfm --external:@mixmark-io/domino --minify && esbuild src/cli.ts --bundle --platform=node --target=node18 --format=esm --outfile=cli.bundle.mjs --external:better-sqlite3 --minify && esbuild src/session/extract.ts --bundle --platform=node --target=node18 --format=esm --outfile=hooks/session-extract.bundle.mjs --minify && esbuild src/session/snapshot.ts --bundle --platform=node --target=node18 --format=esm --outfile=hooks/session-snapshot.bundle.mjs --minify && esbuild src/session/db.ts --bundle --platform=node --target=node18 --format=esm --outfile=hooks/session-db.bundle.mjs --external:better-sqlite3 --minify && esbuild src/security.ts --bundle --platform=node --target=node18 --format=esm --outfile=hooks/security.bundle.mjs --minify",
94
86
  "version-sync": "node scripts/version-sync.mjs",
95
- "version": "node scripts/version-sync.mjs && git add package.json .claude-plugin/plugin.json .claude-plugin/marketplace.json .cursor-plugin/plugin.json .codex-plugin/plugin.json .openclaw-plugin/openclaw.plugin.json .openclaw-plugin/package.json openclaw.plugin.json .pi/extensions/context-mode/package.json",
87
+ "version": "node scripts/version-sync.mjs && git add package.json .claude-plugin/plugin.json .claude-plugin/marketplace.json .cursor-plugin/plugin.json .codex-plugin/plugin.json .openclaw-plugin/openclaw.plugin.json .openclaw-plugin/package.json openclaw.plugin.json .pi/extensions/context-mode/package.json configs/antigravity-cli/plugin.json configs/copilot-cli/.github/plugin/plugin.json",
96
88
  "prepublishOnly": "npm run build",
97
89
  "dev": "npx tsx src/server.ts",
98
90
  "setup": "npx tsx src/cli.ts setup",