pi-smart-compact 9.7.1 → 10.0.1

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 (206) hide show
  1. package/ARCHITECTURE.md +973 -372
  2. package/CHANGELOG.md +721 -0
  3. package/LICENSE +8 -0
  4. package/README.md +128 -640
  5. package/SECURITY.md +34 -12
  6. package/SUPPORT.md +26 -9
  7. package/assets/DejaVu-LICENSE.txt +187 -0
  8. package/assets/DejaVuSansMono.ttf +0 -0
  9. package/assets/README.md +26 -0
  10. package/assets/skills/context-management/SKILL.md +34 -0
  11. package/dist/app/anchor-cache.d.ts +36 -0
  12. package/dist/app/anchor-cache.d.ts.map +1 -0
  13. package/dist/app/artifact-storage.d.ts +47 -0
  14. package/dist/app/artifact-storage.d.ts.map +1 -0
  15. package/dist/app/background-preparation.d.ts +39 -0
  16. package/dist/app/background-preparation.d.ts.map +1 -0
  17. package/dist/app/compaction-commit-store.d.ts +5 -1
  18. package/dist/app/compaction-commit-store.d.ts.map +1 -1
  19. package/dist/app/context-evidence.d.ts +57 -0
  20. package/dist/app/context-evidence.d.ts.map +1 -0
  21. package/dist/app/context-guide.d.ts +3 -0
  22. package/dist/app/context-guide.d.ts.map +1 -0
  23. package/dist/app/context-operations.d.ts +106 -0
  24. package/dist/app/context-operations.d.ts.map +1 -0
  25. package/dist/app/effective-state.d.ts +23 -0
  26. package/dist/app/effective-state.d.ts.map +1 -0
  27. package/dist/app/global-settings-runtime.d.ts +3 -3
  28. package/dist/app/global-settings-runtime.d.ts.map +1 -1
  29. package/dist/app/hindsight-memory.d.ts +100 -0
  30. package/dist/app/hindsight-memory.d.ts.map +1 -0
  31. package/dist/app/host-cache-ledger.d.ts +68 -0
  32. package/dist/app/host-cache-ledger.d.ts.map +1 -0
  33. package/dist/app/lazy-tools.d.ts +36 -0
  34. package/dist/app/lazy-tools.d.ts.map +1 -0
  35. package/dist/app/memory-backend.d.ts +58 -0
  36. package/dist/app/memory-backend.d.ts.map +1 -0
  37. package/dist/app/mnemopi-memory.d.ts +13 -0
  38. package/dist/app/mnemopi-memory.d.ts.map +1 -0
  39. package/dist/app/mnemopi-protocol.d.ts +78 -0
  40. package/dist/app/mnemopi-protocol.d.ts.map +1 -0
  41. package/dist/app/mnemopi-worker.d.ts +2 -0
  42. package/dist/app/mnemopi-worker.d.ts.map +1 -0
  43. package/dist/app/model-feasibility.d.ts +20 -0
  44. package/dist/app/model-feasibility.d.ts.map +1 -0
  45. package/dist/app/native-compaction.d.ts +88 -0
  46. package/dist/app/native-compaction.d.ts.map +1 -0
  47. package/dist/app/native-continuity-bridge.d.ts.map +1 -1
  48. package/dist/app/navigation-data.d.ts +28 -0
  49. package/dist/app/navigation-data.d.ts.map +1 -0
  50. package/dist/app/navigation-types.d.ts +60 -0
  51. package/dist/app/navigation-types.d.ts.map +1 -0
  52. package/dist/app/pending-slot.d.ts +11 -1
  53. package/dist/app/pending-slot.d.ts.map +1 -1
  54. package/dist/app/preflight.d.ts.map +1 -1
  55. package/dist/app/register-context-tools.d.ts +16 -3
  56. package/dist/app/register-context-tools.d.ts.map +1 -1
  57. package/dist/app/register-navigation.d.ts +20 -0
  58. package/dist/app/register-navigation.d.ts.map +1 -0
  59. package/dist/app/register-smart-compact-command.d.ts +17 -2
  60. package/dist/app/register-smart-compact-command.d.ts.map +1 -1
  61. package/dist/app/register-smart-compact-tool.d.ts.map +1 -1
  62. package/dist/app/register-smart-context-tool.d.ts +55 -0
  63. package/dist/app/register-smart-context-tool.d.ts.map +1 -0
  64. package/dist/app/run-context.d.ts +1 -0
  65. package/dist/app/run-context.d.ts.map +1 -1
  66. package/dist/app/run-smart-compact.d.ts +3 -3
  67. package/dist/app/run-smart-compact.d.ts.map +1 -1
  68. package/dist/app/session-handoff.d.ts +64 -0
  69. package/dist/app/session-handoff.d.ts.map +1 -0
  70. package/dist/app/session-lineage.d.ts +17 -0
  71. package/dist/app/session-lineage.d.ts.map +1 -0
  72. package/dist/app/session-run-lock.d.ts +0 -2
  73. package/dist/app/session-run-lock.d.ts.map +1 -1
  74. package/dist/app/settled-auto-trigger.d.ts +2 -0
  75. package/dist/app/settled-auto-trigger.d.ts.map +1 -1
  76. package/dist/app/smart-compact-input.d.ts +1 -1
  77. package/dist/app/smart-compact-input.d.ts.map +1 -1
  78. package/dist/app/smart-compact-policy.d.ts +1 -1
  79. package/dist/app/smart-compact-policy.d.ts.map +1 -1
  80. package/dist/app/steps/extract.d.ts +45 -1
  81. package/dist/app/steps/extract.d.ts.map +1 -1
  82. package/dist/app/steps/metrics.d.ts +1 -0
  83. package/dist/app/steps/metrics.d.ts.map +1 -1
  84. package/dist/app/steps/persist.d.ts.map +1 -1
  85. package/dist/app/steps/prepare.d.ts.map +1 -1
  86. package/dist/app/steps/recover.d.ts +9 -0
  87. package/dist/app/steps/recover.d.ts.map +1 -1
  88. package/dist/app/steps/synthesize.d.ts.map +1 -1
  89. package/dist/app/steps/tier.d.ts.map +1 -1
  90. package/dist/app/steps/verify.d.ts.map +1 -1
  91. package/dist/app/steps/visual.d.ts +4 -0
  92. package/dist/app/steps/visual.d.ts.map +1 -0
  93. package/dist/app/steps/window.d.ts.map +1 -1
  94. package/dist/app/tool-artifacts.d.ts +27 -0
  95. package/dist/app/tool-artifacts.d.ts.map +1 -0
  96. package/dist/app/visual-archive.d.ts +29 -0
  97. package/dist/app/visual-archive.d.ts.map +1 -0
  98. package/dist/constants.d.ts +96 -1
  99. package/dist/constants.d.ts.map +1 -1
  100. package/dist/domain/compaction-usage.d.ts +16 -0
  101. package/dist/domain/compaction-usage.d.ts.map +1 -0
  102. package/dist/domain/model-capacity.d.ts +12 -0
  103. package/dist/domain/model-capacity.d.ts.map +1 -0
  104. package/dist/domain/provider-evaluation.d.ts +7 -0
  105. package/dist/domain/provider-evaluation.d.ts.map +1 -1
  106. package/dist/domain/telemetry.d.ts +43 -2
  107. package/dist/domain/telemetry.d.ts.map +1 -1
  108. package/dist/domain/tool-semantics.d.ts +23 -0
  109. package/dist/domain/tool-semantics.d.ts.map +1 -1
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +15757 -6942
  112. package/dist/infra/ai-messages.d.ts +1 -1
  113. package/dist/infra/ai-messages.d.ts.map +1 -1
  114. package/dist/infra/context-graph.d.ts +38 -7
  115. package/dist/infra/context-graph.d.ts.map +1 -1
  116. package/dist/infra/fs.d.ts.map +1 -1
  117. package/dist/infra/hindsight-client.d.ts +73 -0
  118. package/dist/infra/hindsight-client.d.ts.map +1 -0
  119. package/dist/infra/hindsight-receipts.d.ts +68 -0
  120. package/dist/infra/hindsight-receipts.d.ts.map +1 -0
  121. package/dist/infra/llm-client.d.ts +26 -23
  122. package/dist/infra/llm-client.d.ts.map +1 -1
  123. package/dist/infra/memory-ref.d.ts +27 -0
  124. package/dist/infra/memory-ref.d.ts.map +1 -0
  125. package/dist/infra/native-protocol.d.ts +54 -0
  126. package/dist/infra/native-protocol.d.ts.map +1 -0
  127. package/dist/infra/optional-components.d.ts +15 -0
  128. package/dist/infra/optional-components.d.ts.map +1 -0
  129. package/dist/infra/paths.d.ts +2 -0
  130. package/dist/infra/paths.d.ts.map +1 -1
  131. package/dist/infra/services.d.ts +15 -5
  132. package/dist/infra/services.d.ts.map +1 -1
  133. package/dist/infra/visual-renderer.d.ts +16 -0
  134. package/dist/infra/visual-renderer.d.ts.map +1 -0
  135. package/dist/mnemopi-worker.js +213 -0
  136. package/dist/phases/explore.d.ts +12 -9
  137. package/dist/phases/explore.d.ts.map +1 -1
  138. package/dist/phases/synthesize.d.ts +18 -3
  139. package/dist/phases/synthesize.d.ts.map +1 -1
  140. package/dist/phases/verify.d.ts +5 -1
  141. package/dist/phases/verify.d.ts.map +1 -1
  142. package/dist/rtk.d.ts +7 -0
  143. package/dist/rtk.d.ts.map +1 -0
  144. package/dist/rtk.js +767 -0
  145. package/dist/types.d.ts +128 -4
  146. package/dist/types.d.ts.map +1 -1
  147. package/dist/ui/dashboard-format.d.ts +2 -1
  148. package/dist/ui/dashboard-format.d.ts.map +1 -1
  149. package/dist/ui/dashboard-insights.d.ts +9 -1
  150. package/dist/ui/dashboard-insights.d.ts.map +1 -1
  151. package/dist/ui/error-format.d.ts +7 -2
  152. package/dist/ui/error-format.d.ts.map +1 -1
  153. package/dist/ui/handoff-overlay.d.ts +26 -0
  154. package/dist/ui/handoff-overlay.d.ts.map +1 -0
  155. package/dist/ui/home-overlay.d.ts +54 -0
  156. package/dist/ui/home-overlay.d.ts.map +1 -0
  157. package/dist/ui/metrics-dashboard-overlay.d.ts.map +1 -1
  158. package/dist/ui/metrics-report.d.ts.map +1 -1
  159. package/dist/ui/navigation-overlay.d.ts +92 -0
  160. package/dist/ui/navigation-overlay.d.ts.map +1 -0
  161. package/dist/ui/overlays.d.ts +12 -2
  162. package/dist/ui/overlays.d.ts.map +1 -1
  163. package/dist/ui/profiles.d.ts +51 -0
  164. package/dist/ui/profiles.d.ts.map +1 -0
  165. package/dist/ui/settings-complex.d.ts +49 -3
  166. package/dist/ui/settings-complex.d.ts.map +1 -1
  167. package/dist/ui/settings-list.d.ts +28 -0
  168. package/dist/ui/settings-list.d.ts.map +1 -0
  169. package/dist/ui/settings-overlay.d.ts +13 -6
  170. package/dist/ui/settings-overlay.d.ts.map +1 -1
  171. package/dist/ui/storage-report.d.ts +4 -0
  172. package/dist/ui/storage-report.d.ts.map +1 -0
  173. package/dist/utils/backups.d.ts.map +1 -1
  174. package/dist/utils/cache.d.ts +6 -2
  175. package/dist/utils/cache.d.ts.map +1 -1
  176. package/dist/utils/config.d.ts +12 -0
  177. package/dist/utils/config.d.ts.map +1 -1
  178. package/dist/utils/helpers.d.ts.map +1 -1
  179. package/dist/utils/id-fingerprint.d.ts +3 -1
  180. package/dist/utils/id-fingerprint.d.ts.map +1 -1
  181. package/dist/utils/issues.d.ts +61 -0
  182. package/dist/utils/issues.d.ts.map +1 -0
  183. package/dist/utils/pruning.d.ts.map +1 -1
  184. package/dist/utils/session-log.d.ts +0 -2
  185. package/dist/utils/session-log.d.ts.map +1 -1
  186. package/dist/utils/state.d.ts +3 -1
  187. package/dist/utils/state.d.ts.map +1 -1
  188. package/dist/utils/tokens.d.ts +10 -2
  189. package/dist/utils/tokens.d.ts.map +1 -1
  190. package/docs/MIGRATING_TO_V8.md +7 -1
  191. package/docs/README.md +69 -0
  192. package/docs/RELEASE.md +173 -56
  193. package/docs/assets/banner.png +0 -0
  194. package/docs/assets/banner.svg +1158 -70
  195. package/docs/assets/pi-smart-compact.png +0 -0
  196. package/docs/assets/pi-smart-compact.svg +24 -0
  197. package/docs/configuration.md +637 -0
  198. package/docs/evaluation.md +408 -0
  199. package/docs/guide.md +860 -0
  200. package/docs/hindsight-memory.md +314 -0
  201. package/docs/identity.md +124 -0
  202. package/package.json +44 -11
  203. package/dist/provider-eval.js +0 -2122
  204. package/dist/provider-scenario-eval.js +0 -2900
  205. package/dist/telemetry-report.js +0 -1973
  206. package/docs/provider-evaluation-2026-08-06.md +0 -63
package/dist/rtk.js ADDED
@@ -0,0 +1,767 @@
1
+ // @bun
2
+ // src/domain/scrub.ts
3
+ var SECRET_PATTERNS = [
4
+ {
5
+ kind: "private-key",
6
+ regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g
7
+ },
8
+ { kind: "aws-access-key", regex: /\bAKIA[0-9A-Z]{16}\b/g },
9
+ { kind: "google-api-key", regex: /\bAIza[0-9A-Za-z_-]{30,}\b/g },
10
+ { kind: "stripe-key", regex: /\b[rs]k_(?:live|test)_[0-9A-Za-z]{16,}\b/g },
11
+ { kind: "gitlab-token", regex: /\bglpat-[0-9A-Za-z_-]{20,}\b/g },
12
+ { kind: "npm-token", regex: /\bnpm_[0-9A-Za-z]{30,}\b/g },
13
+ { kind: "github-token", regex: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/g },
14
+ { kind: "api-key", regex: /\bsk-(?:ant-)?[A-Za-z0-9_-]{20,}\b/g },
15
+ { kind: "slack-token", regex: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g },
16
+ {
17
+ kind: "jwt",
18
+ regex: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g
19
+ },
20
+ {
21
+ kind: "bearer-token",
22
+ regex: /\bBearer\s+[A-Za-z0-9._~+/-]{12,}=*/gi,
23
+ replacement: () => "Bearer [REDACTED:bearer-token]"
24
+ },
25
+ {
26
+ kind: "connection-password",
27
+ regex: /\b([a-z][a-z0-9+.-]*:\/\/[^:\s/@]+:)[^@\s/]+(@)/gi,
28
+ replacement: (prefix, suffix) => prefix + "[REDACTED:password]" + suffix
29
+ },
30
+ {
31
+ kind: "credential",
32
+ regex: /\b((?:[A-Za-z0-9]+[_-])*(?:api[_-]?key|access[_-]?token|auth[_-]?token|token|password|passwd|secret(?:[_-]?(?:access)?[_-]?key)?|client[_-]?secret)(?:[_-][A-Za-z0-9]+)*)\s*([:=])\s*["']?([^\s"']{16,})["']?/gi,
33
+ replacement: (name, separator, value, match) => /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+$/.test(value) ? match : name + separator + "[REDACTED:credential]"
34
+ }
35
+ ];
36
+ function passesLuhn(candidate) {
37
+ const digits = candidate.replace(/\D/g, "");
38
+ if (digits.length < 13 || digits.length > 19)
39
+ return false;
40
+ if (/^(\d)\1+$/.test(digits))
41
+ return false;
42
+ let sum = 0, double = false;
43
+ for (let i = digits.length - 1;i >= 0; i--) {
44
+ let d = digits.charCodeAt(i) - 48;
45
+ if (double) {
46
+ d *= 2;
47
+ if (d > 9)
48
+ d -= 9;
49
+ }
50
+ sum += d;
51
+ double = !double;
52
+ }
53
+ return sum % 10 === 0;
54
+ }
55
+ var PII_PATTERNS = [
56
+ { kind: "email", regex: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi },
57
+ {
58
+ kind: "payment-card",
59
+ regex: /\b(?:\d[ -]*?){13,19}\b/g,
60
+ replacement: (candidate) => passesLuhn(candidate) ? "[REDACTED:payment-card]" : candidate
61
+ },
62
+ { kind: "phone", regex: /(?<![\w.])(?:\+?\d[\d ()-]{8,}\d)(?![\w.])/g }
63
+ ];
64
+ function redact(text, patterns) {
65
+ const counts = new Map;
66
+ let value = text;
67
+ for (const pattern of patterns) {
68
+ value = value.replace(pattern.regex, (...args) => {
69
+ const match = String(args[0]);
70
+ let replacement = "[REDACTED:" + pattern.kind + "]";
71
+ if (pattern.replacement) {
72
+ const groups = args.slice(1, -2).map(String);
73
+ replacement = pattern.replacement(...groups, match);
74
+ }
75
+ if (replacement === match)
76
+ return match;
77
+ counts.set(pattern.kind, (counts.get(pattern.kind) ?? 0) + 1);
78
+ return replacement;
79
+ });
80
+ }
81
+ return {
82
+ value,
83
+ findings: [...counts].map(([kind, count]) => ({ kind, count }))
84
+ };
85
+ }
86
+ function mergeFindings(target, findings) {
87
+ for (const finding of findings)
88
+ target.set(finding.kind, (target.get(finding.kind) ?? 0) + finding.count);
89
+ }
90
+ var SECRET_KEY_NAMES = {
91
+ api_key: true,
92
+ apikey: true,
93
+ access_token: true,
94
+ auth_token: true,
95
+ authorization: true,
96
+ password: true,
97
+ passwd: true,
98
+ secret: true,
99
+ secret_key: true,
100
+ secret_access_key: true,
101
+ client_secret: true,
102
+ private_key: true,
103
+ database_url: true,
104
+ connection_string: true,
105
+ token: true,
106
+ refresh_token: true,
107
+ session_token: true,
108
+ credential: true,
109
+ credentials: true,
110
+ cookie: true,
111
+ set_cookie: true,
112
+ otp: true,
113
+ one_time_password: true,
114
+ passcode: true
115
+ };
116
+ function normalizeObjectKey(key) {
117
+ return key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
118
+ }
119
+ function isSecretBearingKey(key) {
120
+ const normalized = normalizeObjectKey(key);
121
+ if (SECRET_KEY_NAMES[normalized])
122
+ return true;
123
+ return /(?:^|_)(?:api_key|access_token|auth_token|password|passwd|secret_access_key|client_secret|private_key|refresh_token|session_token|one_time_password|passcode)(?:_|$)/.test(normalized);
124
+ }
125
+
126
+ class SecretScrubber {
127
+ secretsEnabled;
128
+ piiEnabled;
129
+ total = 0;
130
+ constructor(secretsEnabled = true, piiEnabled = false) {
131
+ this.secretsEnabled = secretsEnabled;
132
+ this.piiEnabled = piiEnabled;
133
+ }
134
+ scrubText(text) {
135
+ let value = text;
136
+ const findings = new Map;
137
+ if (this.secretsEnabled) {
138
+ const result = redact(value, SECRET_PATTERNS);
139
+ value = result.value;
140
+ mergeFindings(findings, result.findings);
141
+ }
142
+ if (this.piiEnabled) {
143
+ const result = redact(value, PII_PATTERNS);
144
+ value = result.value;
145
+ mergeFindings(findings, result.findings);
146
+ }
147
+ const merged = [...findings].map(([kind, count]) => ({ kind, count }));
148
+ this.total += merged.reduce((sum, finding) => sum + finding.count, 0);
149
+ return { value, findings: merged };
150
+ }
151
+ scrubValue(input) {
152
+ const findings = new Map;
153
+ const seen = new WeakMap;
154
+ const recordCredential = () => {
155
+ findings.set("credential", (findings.get("credential") ?? 0) + 1);
156
+ this.total++;
157
+ };
158
+ const visit = (value) => {
159
+ if (typeof value === "string") {
160
+ const result = this.scrubText(value);
161
+ mergeFindings(findings, result.findings);
162
+ return result.value;
163
+ }
164
+ if (value == null || typeof value !== "object")
165
+ return value;
166
+ const cached = seen.get(value);
167
+ if (cached !== undefined)
168
+ return cached;
169
+ if (Array.isArray(value)) {
170
+ const output = [];
171
+ seen.set(value, output);
172
+ for (const item of value)
173
+ output.push(visit(item));
174
+ return output;
175
+ }
176
+ const output = {};
177
+ seen.set(value, output);
178
+ for (const [key, item] of Object.entries(value)) {
179
+ const carriesSecret = typeof item === "string" && item.length >= 8;
180
+ if (this.secretsEnabled && isSecretBearingKey(key) && carriesSecret) {
181
+ output[key] = "[REDACTED:credential]";
182
+ recordCredential();
183
+ } else {
184
+ output[key] = visit(item);
185
+ }
186
+ }
187
+ return output;
188
+ };
189
+ const value = visit(input);
190
+ return {
191
+ value,
192
+ findings: [...findings].map(([kind, count]) => ({ kind, count }))
193
+ };
194
+ }
195
+ count() {
196
+ return this.total;
197
+ }
198
+ }
199
+
200
+ // src/constants.ts
201
+ var VERSION = "10.0.1";
202
+ var OPTIONAL_COMPONENTS = {
203
+ mnemopi: { name: "@oh-my-pi/pi-mnemopi", version: "18.3.1", enables: "Mnemopi memory store" },
204
+ bun: { name: "bun", version: "1.4.2", enables: "Mnemopi worker runtime when no Bun 1.3.14+ is on PATH" },
205
+ resvg: { name: "@resvg/resvg-js", version: "2.6.2", enables: "image snapshots" }
206
+ };
207
+ var CHARS_PER_TOKEN = 3.8;
208
+ var MIN_COMPACTION_SAVING_RATIO = 0.1;
209
+ var ESTIMATOR_ROUNDING_TOLERANCE_TOKENS = 1;
210
+ var POST_SUMMARY_RESERVE_RATIO = 0.25;
211
+ var MAX_STATE_OPEN_LOOPS = 25;
212
+ var AUTO_TRIGGER_TIMEOUT_CAP_MS = 60000;
213
+ var AUTO_TRIGGER_MAX_LLM_CALLS = 4;
214
+ var SETTLED_TRIGGER_COOLDOWN_MS = 10 * 60000;
215
+ var REBUILD_MIN_TOKENS = 16384;
216
+ var AUTO_TRIM_BREAK_EVEN_REQUESTS = 24;
217
+ var CACHE_WARMING_MIN_SAVINGS_USD = 0.05;
218
+ var BUDGET_LIMITS = {
219
+ CALLS: { min: 1, max: 100 },
220
+ INPUT_TOKENS: { min: 1e4, max: 1e6 },
221
+ LATENCY_MS: { min: 5000, max: 600000 }
222
+ };
223
+ var COMPACT_SYSTEM_PREFIX = "You are an expert conversation summarizer for a coding agent. " + "Produce structured markdown summaries. " + "Follow output format exactly. " + "Use EXACT names \u2014 never paraphrase code identifiers. " + "Trust deterministic extraction data over intuition.";
224
+ var PROFILES = {
225
+ light: {
226
+ summaryBudgetTokens: 1e4,
227
+ keepRecentTokens: 30000,
228
+ minChunkTokens: 800,
229
+ maxChunkTokens: 12000,
230
+ singlePassMaxTokens: 40000,
231
+ batchMaxTokens: 30000
232
+ },
233
+ balanced: {
234
+ summaryBudgetTokens: 6000,
235
+ keepRecentTokens: 20000,
236
+ minChunkTokens: 500,
237
+ maxChunkTokens: 8000,
238
+ singlePassMaxTokens: 30000,
239
+ batchMaxTokens: 24000
240
+ },
241
+ aggressive: {
242
+ summaryBudgetTokens: 3000,
243
+ keepRecentTokens: 1e4,
244
+ minChunkTokens: 300,
245
+ maxChunkTokens: 6000,
246
+ singlePassMaxTokens: 20000,
247
+ batchMaxTokens: 18000
248
+ }
249
+ };
250
+ var PROFILE_NUMERIC_BOUNDS = {
251
+ summaryBudgetTokens: [256, 1e5],
252
+ keepRecentTokens: [1000, 500000],
253
+ minChunkTokens: [100, 1e5],
254
+ maxChunkTokens: [500, 200000],
255
+ singlePassMaxTokens: [1000, 500000],
256
+ batchMaxTokens: [1000, 500000]
257
+ };
258
+ var LARGE_CONTEXT_WINDOW_TOKENS = 400000;
259
+ var CONFIG_NUMERIC_LIMITS = {
260
+ minContextPercent: { min: 0, max: 100, integer: false },
261
+ prepareContextPercent: { min: 0, max: 100, integer: false },
262
+ autoTriggerTimeoutMs: { min: 1000, max: 300000, integer: true },
263
+ maxLlmCalls: { min: 0, max: 100, integer: true },
264
+ maxLlmInputTokens: { min: 0, max: 1e6, integer: true },
265
+ maxContextTokens: { min: 16384, max: 2000000, integer: true, zeroOrRange: true },
266
+ codexMaxCallMs: {
267
+ min: 5000,
268
+ max: 3600000,
269
+ integer: true,
270
+ zeroOrRange: true
271
+ },
272
+ maxLatencyMs: {
273
+ min: 5000,
274
+ max: 7200000,
275
+ integer: true,
276
+ zeroOrRange: true
277
+ },
278
+ pendingTtlMs: { min: 1000, max: 3600000, integer: true },
279
+ hindsightTimeoutMs: { min: 1000, max: 60000, integer: true },
280
+ hindsightRecallMaxTokens: { min: 128, max: 4096, integer: true }
281
+ };
282
+ var DEFAULT_CONFIG = {
283
+ mode: "auto",
284
+ profile: "balanced",
285
+ profiles: PROFILES,
286
+ summaryModel: null,
287
+ segmentationModel: null,
288
+ verificationModel: null,
289
+ summaryThinkingLevel: "minimal",
290
+ segmentationThinkingLevel: "minimal",
291
+ agentToolAccess: "inherit",
292
+ toolLoading: "lazy",
293
+ autoTrigger: true,
294
+ showStatus: true,
295
+ autoTriggerStrategy: "native-hook",
296
+ autoTriggerTimeoutMs: 120000,
297
+ backupEnabled: true,
298
+ backupDir: "",
299
+ minContextPercent: 60,
300
+ prepareContextPercent: null,
301
+ maxContextTokens: 0,
302
+ requireApproval: true,
303
+ scrubSecrets: true,
304
+ scrubPii: false,
305
+ maxLlmCalls: 8,
306
+ maxLlmInputTokens: 0,
307
+ codexMaxCallMs: 0,
308
+ maxLatencyMs: 0,
309
+ pendingTtlMs: 300000,
310
+ focusWeighting: true,
311
+ zeroCallEnabled: true,
312
+ contextGraphEnabled: true,
313
+ compactionEngines: ["eesv"],
314
+ memoryBackend: "local",
315
+ hindsightBaseUrl: null,
316
+ hindsightBankId: null,
317
+ hindsightApiKeyEnv: null,
318
+ hindsightTimeoutMs: 12000,
319
+ hindsightRecallMaxTokens: 2048,
320
+ mnemopiDataDir: null,
321
+ visualArchiveEnabled: false,
322
+ artifactOffloadEnabled: false,
323
+ contextHygieneEnabled: false,
324
+ contextNavigationEnabled: true,
325
+ contextRecallEnabled: true,
326
+ contextPivotEnabled: true,
327
+ contextAnchorCacheEnabled: true,
328
+ contextAnchorStatusEnabled: true,
329
+ contextGuidanceEnabled: true,
330
+ telemetryChannel: "stable",
331
+ adaptiveDamageFeedback: false,
332
+ onlineDamageMonitor: true,
333
+ pinPaths: []
334
+ };
335
+ var NO_OP_RE = /applied:\s*0|no changes applied|nothing to (?:do|change)|0 edits? applied/i;
336
+ var SHIFT_RE = /\u015Fimdi|simdi|peki|bi de|bide|ge\u00E7elim|gecelim|bakal\u0131m|bakalim|yapal\u0131m|yapalim|ba\u015Fka|baska|sonra|tamam \u015Fimdi|tamam simdi|now let|also|next|let's|moving on|switch to/iu;
337
+ var CHOICE_RE = /use\s+\S+\s+(?:instead|not|rather)|don't\s+use|avoid\s+|switch\s+to\s+|go\s+with\s+|prefer\s+/i;
338
+ var SINGLE_PASS_PREFIX = `Summarize this coding agent conversation. Produce ONE structured summary.
339
+ ` + `
340
+ Rules for Accuracy:
341
+ ` + `1. Session Type: read-only tool calls = REVIEW, not implementation
342
+ ` + `2. Status: Check for user complaints before marking "Done"
343
+ ` + `3. Exact Names: Quote specific variable/function/parameter names, don't paraphrase
344
+ ` + `4. Files: Use the VERIFIED file lists above (deterministically extracted, zero hallucination risk)
345
+ ` + `
346
+ Output EXACTLY this format:
347
+
348
+ ` + `## Goal
349
+ [What the user is trying to accomplish]
350
+ ` + `## Constraints & Preferences
351
+ - [CRITICAL: user requirements, preferences, constraints]
352
+ ` + `## Progress
353
+ ### Done
354
+ - [x] [Completed tasks with file references]
355
+ ### In Progress
356
+ - [ ] [Current work state]
357
+ ### Blocked
358
+ - [Issues]
359
+ ` + `## Key Decisions
360
+ - **[Decision]**: [Rationale]
361
+ ` + `## Files Modified
362
+ - [Verified list from deterministic extraction]
363
+ ` + `## Files Deleted
364
+ - [Verified deleted paths from deterministic extraction]
365
+ ` + `## Files Read
366
+ - [Verified list from deterministic extraction]
367
+ ` + `## Next Steps
368
+ 1. [What should happen next]
369
+ ` + `## Critical Context
370
+ - [Specific data, patterns, info needed to continue]
371
+ - [Error patterns or gotchas]
372
+ ` + `## Topics Covered
373
+ [Chronological bullet list with priority in brackets]
374
+ `;
375
+ var SINGLE_PASS_SUFFIX = `
376
+ {PREV_CONTEXT}
377
+
378
+ {EXTRACTION_CONTEXT}
379
+
380
+ {EXPLORATION_CONTEXT}
381
+
382
+ <conversation>
383
+ {CONVERSATION}
384
+ </conversation>`;
385
+ var BATCH_PROMPT_PREFIX = `Summarize these conversation segments.
386
+
387
+ Rules for Accuracy:
388
+ ` + `1. Use EXACT file paths from extraction data
389
+ ` + `2. Status: only mark "done" if there's clear evidence (successful test run, user confirmation)
390
+ ` + `3. Quote specific values, don't paraphrase code
391
+
392
+ ` + `For EACH segment produce EXACTLY:
393
+ ` + `### CHUNK {NUMBER}: {TOPIC_NAME}
394
+ ` + `**Priority**: [critical|high|normal|low]
395
+ ` + `**Summary**: [2-4 sentences: what happened, errors, code changes with paths]
396
+ ` + `**Decisions**: [comma-separated, or "None"]
397
+ ` + `**Modified**: [comma-separated paths, or "None"]
398
+ ` + `**Deleted**: [comma-separated paths, or "None"]
399
+ ` + `**Read**: [comma-separated paths, or "None"]
400
+ `;
401
+ var BATCH_PROMPT_SUFFIX = `
402
+ {EXTRACTION_CONTEXT}
403
+
404
+ <segments>
405
+ {TEXT}
406
+ </segments>`;
407
+ var ASSEMBLY_PROMPT_PREFIX = `Merge these topic summaries into ONE coherent summary.
408
+
409
+ ` + `## IMMUTABLE CONTEXT (do not modify or contradict these facts)
410
+ ` + `These are deterministically verified from the original conversation. They take priority over ANY summary content below.
411
+
412
+ ` + `Rules:
413
+ ` + `1. Preserve ALL critical/high info. Condense normal, minimize low.
414
+ ` + `2. Chronological order.
415
+ ` + `3. The pre-processed data below is GROUND TRUTH \u2014 trust it over individual summaries.
416
+ ` + `4. Files Modified list is deterministically verified \u2014 if a summary says a file was modified but it's NOT in the list above, omit it.
417
+ ` + `5. Key Decisions below are verified \u2014 preserve them exactly, do not paraphrase the decision text.
418
+ ` + `6. Do NOT fabricate file paths, function names, or error messages not present in the verified data.
419
+
420
+ ` + `Format:
421
+ ` + `## Goal
422
+ [Overall objective]
423
+ ` + `## Constraints & Preferences
424
+ - [CRITICAL requirements, preferences, constraints]
425
+ ` + `## Progress
426
+ ### Done
427
+ - [x] [Completed tasks with file refs]
428
+ ### In Progress
429
+ - [ ] [Current work state]
430
+ ### Blocked
431
+ - [Issues]
432
+ ` + `## Key Decisions
433
+ - **[Decision]**: [Rationale]
434
+ ` + `## Files Modified
435
+ - [Verified deterministic list]
436
+ ` + `## Files Deleted
437
+ - [Verified deterministic deleted paths]
438
+ ` + `## Files Read
439
+ - [Verified deterministic list]
440
+ ` + `## Next Steps
441
+ 1. [What should happen next]
442
+ ` + `## Critical Context
443
+ - [Data, patterns, info needed]
444
+ ` + `## Topics Covered
445
+ [Chronological bullets with priority]
446
+ `;
447
+ var ASSEMBLY_PROMPT_SUFFIX = `
448
+ IMMUTABLE CONTEXT (verified deterministic data):
449
+ - Key Decisions: {DECISIONS}
450
+ - Files Modified (VERIFIED): {MODIFIED}
451
+ - Files Read (VERIFIED): {READ}
452
+ - Files Deleted (VERIFIED): {DELETED}
453
+
454
+ {EXPLORATION_CONTEXT}
455
+ {PREV_CONTEXT}
456
+
457
+ <summaries>{SUMMARIES}</summaries>`;
458
+ var SESSION_TYPE_INSTRUCTIONS = {
459
+ debugging: "Focus on: error chains, root cause analysis, attempted fixes, resolution status. Prioritize error messages and stack traces. Mark files as Done only if all errors resolved.",
460
+ implementation: "Focus on: files created/modified, architectural decisions, feature completeness, test coverage. Prioritize code changes with exact paths.",
461
+ review: "Focus on: files read, issues found, recommendations, approval status. Prioritize findings over changes. Read-only tool calls = REVIEW, not implementation.",
462
+ discussion: "Focus on: decisions made, trade-offs discussed, consensus reached. Prioritize rationale over implementation details."
463
+ };
464
+ var SECTION_GOAL = "## Goal";
465
+ var SECTION_CONSTRAINTS = "## Constraints & Preferences";
466
+ var SECTION_PROGRESS = "## Progress";
467
+ var SECTION_DECISIONS = "## Key Decisions";
468
+ var SECTION_FILES_MODIFIED = "## Files Modified";
469
+ var SECTION_FILES_READ = "## Files Read";
470
+ var SECTION_FILES_DELETED = "## Files Deleted";
471
+ var SECTION_NEXT_STEPS = "## Next Steps";
472
+ var SECTION_CRITICAL_CONTEXT = "## Critical Context";
473
+ var SECTION_TOPICS = "## Topics Covered";
474
+ var SECTION_OPEN_LOOPS = "## Open Loops";
475
+ var SECTION_CHANGES = "## Changes Since Last Compaction";
476
+ var LOG_PREFIX = "[smart-compact]";
477
+ var MIN_TOKEN_THRESHOLD = 5000;
478
+ var MAX_EXPLORATION_ROUNDS = 3;
479
+ var BACKUP_MAX_FILES = 20;
480
+ var BACKUP_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1000;
481
+ var FIVE_MINUTES_MS = 5 * 60 * 1000;
482
+ var ONE_HOUR_MS = 60 * 60 * 1000;
483
+ var SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
484
+ var STATE_SNAPSHOT_MAX_FILES = 64;
485
+ var EXTRACTION_LIMITS = {
486
+ MODIFIED_FILES: 120,
487
+ READ_FILES: 160,
488
+ DELETED_FILES: 120,
489
+ ERRORS: 80,
490
+ DECISIONS: 80,
491
+ CONSTRAINTS: 80,
492
+ TOPICS: 80,
493
+ TIMELINE: 120,
494
+ MEDIA_ATTACHMENTS: 40,
495
+ REFERENCED_FILES: 200
496
+ };
497
+ var THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000;
498
+ var EXTRACTION_CACHE_PREFIX = "compact-extraction-";
499
+ var ID_PREFIX = {
500
+ PROJECT: "proj-",
501
+ COMPACT_SESSION: "sc-",
502
+ MULTI_TOOL_USE_SYNTHETIC: "mtu_",
503
+ OPEN_LOOP: "loop-",
504
+ DECISION: "decision-",
505
+ ERROR: "error-"
506
+ };
507
+ var TUNING = {
508
+ EMA_PREV: 0.7,
509
+ EMA_SAMPLE: 0.3,
510
+ CALIBRATION_CLAMP_MIN: 0.3,
511
+ CALIBRATION_CLAMP_MAX: 3,
512
+ CONFIDENCE_HIGH: 0.85,
513
+ CONFIDENCE_MEDIUM: 0.8,
514
+ CONFIDENCE_LOW: 0.6
515
+ };
516
+ var TRUNC = {
517
+ MESSAGE: 300,
518
+ ERROR_DETAIL: 500,
519
+ DECISION_SUMMARY: 200,
520
+ USER_RESPONSE: 300,
521
+ CONSTRAINT_TEXT: 300,
522
+ OPEN_LOOP_SUMMARY: 120,
523
+ TIMELINE_EVENT: 150,
524
+ TIMELINE_ERROR: 100,
525
+ SNIPPET: 80,
526
+ PREVIEW: 150,
527
+ PREVIEW_MID: 200,
528
+ DETAIL: 300,
529
+ PREVIEW_LONG: 400,
530
+ PREVIEW_XL: 500,
531
+ PREVIOUS_SUMMARY: 12000,
532
+ CONTINUITY_CAPSULE: 4000,
533
+ CHUNK_FALLBACK: 180,
534
+ DECISION_DETAIL: 60,
535
+ TOPIC_LABEL: 100,
536
+ PROJ_ID_HASH: 12,
537
+ CONV_HASH: 8,
538
+ RESULT_GAPS: 5,
539
+ SESSION_ID_DISPLAY: 20,
540
+ ERROR_SNIPPET: 30,
541
+ TIMELINE_DISPLAY: 10,
542
+ EXPLORE_RESULTS: 15,
543
+ BACKUP_PREVIEW_LINES: 5,
544
+ FINGERPRINT_SEG: 2
545
+ };
546
+ var MAX_TOOL_OUTPUT_CHARS = 800;
547
+ var MAX_EXPLORER_OUTPUT_CHARS = 12000;
548
+ var LIKELY_ERROR_RE = /(?:command not found|no such file|permission denied|syntax error|cannot find|module not found|compilation error|build failed|test failed|^FAIL\b|ERROR:)/i;
549
+ var TRIM_RISK_LINE_RE = /\b(?:error|fail(?:ed|ure)|warn(?:ing)?|exception|traceback|panic|exit code|exited with|command not found|permission denied|ENOENT|EACCES)\b/i;
550
+ var TRIM_MARKER_MAX_LINES = 6;
551
+ var TRIM_MARKER_MAX_CHARS = 400;
552
+ var ERROR_RETRY_WINDOW = 6;
553
+ var ERROR_RESOLVE_WINDOW = 10;
554
+ var HANDOFF_MAX_CHARS = 16000;
555
+ var HANDOFF_RECALL_MAX_CHARS = 6000;
556
+ var HANDOFF_RECALL_LIMIT = 5;
557
+ var LINEAGE_MAX_DEPTH = 3;
558
+ var LINEAGE_MAX_FILE_BYTES = 64 * 1024 * 1024;
559
+ var METRICS_BUFFER_MAX = 200;
560
+ var RUNTIME_LOG_MAX_BYTES = 5 * 1024 * 1024;
561
+ var CONFIG_KEY = "smartCompact";
562
+ var CONFIG_KEY_ALT = "semanticCompact";
563
+ var EXPLORER_SYSTEM_PROMPT = `You are a conversation analyst. You have deterministic extraction data and can query the raw conversation using tools.
564
+
565
+ ` + `Your job:
566
+ ` + `1. Verify/enrich the extracted boundaries (merge, split, or add as needed)
567
+ ` + `2. Identify cross-topic relationships
568
+ ` + `3. Find implicit constraints (user tone, frustration, urgency)
569
+ ` + `4. Assess completion status accurately
570
+ ` + `5. Extract the narrative arc
571
+
572
+ ` + `Use tools BEFORE forming conclusions. Finish within 3 tool rounds.
573
+
574
+ ` + `After exploration, output ONLY a JSON object (no markdown):
575
+ ` + '{"boundaries":[{"afterIndex":N,"topic":"...","priority":"critical|high|normal|low","confidence":0.0-1.0}],"mainGoal":"...","sessionType":"implementation|review|debugging|discussion","enrichedConstraints":[...],"crossReferences":[...],"statusAssessment":{"done":[...],"inProgress":[...],"blocked":[...]},"criticalContext":[...],"keyDecisions":[...]}';
576
+
577
+ // src/utils/logger.ts
578
+ var DEBUG = process.env.DEBUG?.includes("smart-compact") ?? false;
579
+ function ts() {
580
+ return new Date().toISOString();
581
+ }
582
+ function error(msg, err) {
583
+ const detail = err instanceof Error ? err.message + `
584
+ ` + err.stack : err ?? "";
585
+ console.error(ts() + " " + LOG_PREFIX + " " + msg + (detail ? ": " + detail : ""));
586
+ }
587
+ function info(msg, ...args) {
588
+ console.error(ts() + " " + LOG_PREFIX + " [info] " + msg, ...args);
589
+ }
590
+ function debug(msg, ...args) {
591
+ if (DEBUG)
592
+ console.error(ts() + " " + LOG_PREFIX + " [debug] " + msg, ...args);
593
+ }
594
+ function debugError(msg, err) {
595
+ if (DEBUG)
596
+ error(msg, err);
597
+ }
598
+
599
+ // src/utils/issues.ts
600
+ var MAX_HISTORY = 20;
601
+ var MAX_QUEUE = 20;
602
+ var MAX_MESSAGE_CHARS = 400;
603
+ var PREFIX = "Smart Compact: ";
604
+ var history = new Map;
605
+ var shownThisSession = new Set;
606
+ var queue = [];
607
+ var currentSessionId;
608
+ var scrubber = new SecretScrubber(true, false);
609
+ function formatIssueMessage(message) {
610
+ const oneLine = scrubber.scrubText(message).value.replace(/\s*\n\s*at .*$/gs, "").replace(/\s+/g, " ").trim();
611
+ const prefixed = oneLine.startsWith(PREFIX) ? oneLine : PREFIX + oneLine;
612
+ return prefixed.length > MAX_MESSAGE_CHARS ? prefixed.slice(0, MAX_MESSAGE_CHARS - 1) + "\u2026" : prefixed;
613
+ }
614
+ function errorDetail(error) {
615
+ const text = error instanceof Error ? error.message : typeof error === "string" ? error : "";
616
+ return scrubber.scrubText(text.split(`
617
+ `)[0] ?? "").value.trim().slice(0, 200);
618
+ }
619
+ function sessionOf(sink) {
620
+ try {
621
+ return sink?.sessionManager?.getSessionId?.() || undefined;
622
+ } catch {
623
+ return;
624
+ }
625
+ }
626
+ function syncSession(sink) {
627
+ const sessionId = sessionOf(sink);
628
+ if (sessionId && sessionId !== currentSessionId) {
629
+ currentSessionId = sessionId;
630
+ shownThisSession.clear();
631
+ }
632
+ }
633
+ function deliver(record, sink) {
634
+ if (shownThisSession.has(record.key))
635
+ return;
636
+ shownThisSession.add(record.key);
637
+ if (sink.hasUI !== false && sink.ui) {
638
+ try {
639
+ sink.ui.notify(record.message, record.severity);
640
+ return;
641
+ } catch {}
642
+ }
643
+ process.stderr.write(record.message + `
644
+ `);
645
+ }
646
+ function remember(input) {
647
+ const now = Date.now();
648
+ const message = formatIssueMessage(input.message);
649
+ const existing = history.get(input.key);
650
+ const record = existing ? { ...existing, message, severity: input.severity ?? existing.severity, lastAt: now, count: existing.count + 1 } : { key: input.key, severity: input.severity ?? "warning", message, firstAt: now, lastAt: now, count: 1 };
651
+ history.delete(input.key);
652
+ history.set(input.key, record);
653
+ while (history.size > MAX_HISTORY)
654
+ history.delete(history.keys().next().value);
655
+ return record;
656
+ }
657
+ function recordIssue(input) {
658
+ if (input.error !== undefined)
659
+ debugError(input.key, input.error);
660
+ remember(input);
661
+ }
662
+ function reportIssue(input, sink) {
663
+ if (input.error !== undefined)
664
+ debugError(input.key, input.error);
665
+ const record = remember(input);
666
+ if (sink && !sink.silentBackground) {
667
+ syncSession(sink);
668
+ flushIssues(sink);
669
+ deliver(record, sink);
670
+ return;
671
+ }
672
+ if (queue.some((item) => item.key === record.key))
673
+ return;
674
+ if (queue.length >= MAX_QUEUE)
675
+ queue.shift();
676
+ queue.push(record);
677
+ }
678
+ function flushIssues(sink) {
679
+ if (!queue.length || sink.silentBackground)
680
+ return;
681
+ syncSession(sink);
682
+ const pending = queue.splice(0, queue.length);
683
+ for (const record of pending)
684
+ deliver(history.get(record.key) ?? record, sink);
685
+ }
686
+ function notifyUser(sink, message, type = "info") {
687
+ if (sink?.silentBackground)
688
+ return;
689
+ if (sink && sink.hasUI !== false && sink.ui) {
690
+ try {
691
+ sink.ui.notify(message, type);
692
+ return;
693
+ } catch {}
694
+ }
695
+ if (type === "info")
696
+ return;
697
+ process.stderr.write(formatIssueMessage(message) + `
698
+ `);
699
+ }
700
+ function recentIssues() {
701
+ return [...history.values()].reverse();
702
+ }
703
+ function formatRecentIssues(now = Date.now()) {
704
+ const issues = recentIssues();
705
+ if (!issues.length)
706
+ return "Recent issues: none";
707
+ const lines = ["Recent issues (" + issues.length + "):"];
708
+ for (const issue of issues) {
709
+ const age = Math.max(0, Math.round((now - issue.lastAt) / 1000));
710
+ const when = age < 60 ? age + "s ago" : age < 3600 ? Math.round(age / 60) + "m ago" : Math.round(age / 3600) + "h ago";
711
+ lines.push(" " + (issue.severity === "error" ? "\u2717 " : "\u26A0 ") + when + (issue.count > 1 ? " \xD7" + issue.count : "") + " \u2014 " + issue.message.slice(PREFIX.length));
712
+ }
713
+ return lines.join(`
714
+ `);
715
+ }
716
+
717
+ // src/rtk.ts
718
+ function rtkCompanion(pi) {
719
+ let generation = 0;
720
+ let available;
721
+ const reset = () => {
722
+ generation++;
723
+ available = undefined;
724
+ };
725
+ pi.on("session_start", reset);
726
+ pi.on("session_before_switch", reset);
727
+ pi.on("session_before_fork", reset);
728
+ pi.on("session_tree", reset);
729
+ pi.on("session_shutdown", reset);
730
+ pi.on("tool_call", async (event, ctx) => {
731
+ if (event.toolName !== "bash" || process.env.RTK_DISABLED === "1" || ctx.signal?.aborted)
732
+ return;
733
+ const command = event.input.command;
734
+ if (typeof command !== "string" || !command.trim() || command.length > 32768 || /^\s*rtk(?:\s|$)/.test(command))
735
+ return;
736
+ if (/[|;&<>\n\r\u0000`$()]/.test(command))
737
+ return;
738
+ if (!/^\s*(?:git\s+status|cargo\s+test|bun\s+test)\s*$/.test(command))
739
+ return;
740
+ const started = generation;
741
+ try {
742
+ available ??= pi.exec("rtk", ["--version"], { timeout: 2000, signal: ctx.signal }).then((result) => {
743
+ const version = /^rtk\s+(\d+)\.(\d+)\.(\d+)(?:\s|$)/.exec(result.stdout.trim());
744
+ return !result.killed && result.code === 0 && Boolean(version && (+version[1] > 0 || +version[2] >= 50));
745
+ }).catch(() => false);
746
+ if (!await available) {
747
+ if (started === generation && !ctx.signal?.aborted) {
748
+ reportIssue({
749
+ key: "rtk.inactive",
750
+ message: "RTK rewriting is inactive: requires rtk >=0.50 in PATH. Commands run unchanged. Install or update rtk, or stop loading the RTK companion."
751
+ }, ctx);
752
+ }
753
+ return;
754
+ }
755
+ if (started !== generation || ctx.signal?.aborted)
756
+ return;
757
+ const result = await pi.exec("rtk", ["rewrite", command], { timeout: 2000, signal: ctx.signal });
758
+ const rewritten = result.stdout.trim();
759
+ if (started !== generation || ctx.signal?.aborted || process.env.RTK_DISABLED === "1" || event.input.command !== command || result.killed || ![0, 3].includes(result.code) || !/^rtk\s/.test(rewritten) || rewritten.length > 32768 || /[|;&<>\n\r\u0000`$()]/.test(rewritten))
760
+ return;
761
+ event.input.command = rewritten;
762
+ } catch {}
763
+ });
764
+ }
765
+ export {
766
+ rtkCompanion as default
767
+ };