@cortexkit/opencode-magic-context 0.36.0 → 0.36.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 (108) hide show
  1. package/dist/config/index.d.ts.map +1 -1
  2. package/dist/{conflict-warning-hook-dw9fs934.js → conflict-warning-hook-mt0ttc4x.js} +2 -2
  3. package/dist/features/magic-context/context-authority.d.ts +12 -0
  4. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  5. package/dist/features/magic-context/dreamer/classify.d.ts +2 -0
  6. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  7. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +2 -0
  8. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  9. package/dist/features/magic-context/dreamer/lease.d.ts +10 -3
  10. package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
  11. package/dist/features/magic-context/dreamer/map-memories.d.ts +2 -0
  12. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/module-apply.d.ts +5 -0
  14. package/dist/features/magic-context/dreamer/module-apply.d.ts.map +1 -1
  15. package/dist/features/magic-context/dreamer/promote-primers.d.ts +2 -0
  16. package/dist/features/magic-context/dreamer/promote-primers.d.ts.map +1 -1
  17. package/dist/features/magic-context/dreamer/refresh-primers.d.ts +2 -0
  18. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  19. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +5 -2
  21. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/verify.d.ts +2 -0
  23. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  24. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  25. package/dist/features/magic-context/mural/compress-cues.d.ts +2 -0
  26. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  27. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  28. package/dist/features/magic-context/schema-fence-probe.d.ts +1 -0
  29. package/dist/features/magic-context/schema-fence-probe.d.ts.map +1 -1
  30. package/dist/features/magic-context/smart-notes/condition-compiler.d.ts +1 -0
  31. package/dist/features/magic-context/smart-notes/condition-compiler.d.ts.map +1 -1
  32. package/dist/features/magic-context/storage-clone.d.ts +6 -0
  33. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  34. package/dist/features/magic-context/storage-db.d.ts +1 -1
  35. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  36. package/dist/features/magic-context/storage-identity-merge.d.ts.map +1 -1
  37. package/dist/features/magic-context/storage-tags.d.ts +2 -0
  38. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  39. package/dist/features/magic-context/storage.d.ts +1 -1
  40. package/dist/features/magic-context/storage.d.ts.map +1 -1
  41. package/dist/features/magic-context/user-memory/review-user-memories.d.ts +2 -0
  42. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  43. package/dist/hooks/magic-context/child-session-spawn.d.ts +1 -0
  44. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
  45. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  46. package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -1
  47. package/dist/hooks/magic-context/compartment-render-epoch.d.ts +5 -3
  48. package/dist/hooks/magic-context/compartment-render-epoch.d.ts.map +1 -1
  49. package/dist/hooks/magic-context/embed-session-state.d.ts +1 -1
  50. package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -1
  51. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  52. package/dist/hooks/magic-context/inject-compartments.d.ts +8 -0
  53. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  54. package/dist/hooks/magic-context/lkg-replay.d.ts +5 -2
  55. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  56. package/dist/hooks/magic-context/module-state-sync.d.ts +1 -0
  57. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  58. package/dist/hooks/magic-context/module-transport.d.ts +20 -3
  59. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  60. package/dist/hooks/magic-context/read-session-formatting.d.ts +1 -0
  61. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  62. package/dist/hooks/magic-context/rust-mode-transform.d.ts +3 -0
  63. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  64. package/dist/hooks/magic-context/strip-content.d.ts +6 -1
  65. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  67. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +1 -0
  68. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  69. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  70. package/dist/{index-3nfgbsp4.js → index-1skzp4dc.js} +347 -44
  71. package/dist/{index-z8v31d85.js → index-3zqcdwqr.js} +137 -10
  72. package/dist/{index-0c9dmw9m.js → index-8mtsfhyg.js} +33 -3
  73. package/dist/{index-37rt2bka.js → index-zp6x6s6a.js} +1 -1
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +820 -548
  76. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  77. package/dist/plugin/rust-tool-backends.d.ts +4 -0
  78. package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
  79. package/dist/{recomp-orchestrator-7wbbvf87.js → recomp-orchestrator-a0g9b52q.js} +3 -3
  80. package/dist/shared/conflict-fixer.d.ts.map +1 -1
  81. package/dist/shared/jsonc-edit.d.ts +18 -0
  82. package/dist/shared/jsonc-edit.d.ts.map +1 -0
  83. package/dist/shared/jsonc-parser.d.ts +11 -1
  84. package/dist/shared/jsonc-parser.d.ts.map +1 -1
  85. package/dist/shared/prompt-surface.d.ts +5 -3
  86. package/dist/shared/prompt-surface.d.ts.map +1 -1
  87. package/dist/shared/rpc-utils.d.ts +16 -0
  88. package/dist/shared/rpc-utils.d.ts.map +1 -1
  89. package/dist/shared/tui-preferences.d.ts +9 -0
  90. package/dist/shared/tui-preferences.d.ts.map +1 -1
  91. package/dist/{storage-meta-session-kh5egr11.js → storage-meta-session-df9tstzr.js} +1 -1
  92. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  93. package/package.json +2 -1
  94. package/src/config/index.test.ts +23 -0
  95. package/src/config/index.ts +41 -9
  96. package/src/config/schema/magic-context.test.ts +2 -1
  97. package/src/config/schema/magic-context.ts +3 -3
  98. package/src/shared/conflict-fixer.test.ts +174 -0
  99. package/src/shared/conflict-fixer.ts +66 -70
  100. package/src/shared/jsonc-edit.ts +295 -0
  101. package/src/shared/jsonc-parser.test.ts +33 -0
  102. package/src/shared/jsonc-parser.ts +54 -2
  103. package/src/shared/prompt-surface.test.ts +53 -2
  104. package/src/shared/prompt-surface.ts +20 -9
  105. package/src/shared/rpc-utils.test.ts +36 -0
  106. package/src/shared/rpc-utils.ts +71 -0
  107. package/src/shared/tui-preferences.test.ts +52 -2
  108. package/src/shared/tui-preferences.ts +42 -17
@@ -53,7 +53,11 @@ function removeSystemReminders(text) {
53
53
  }
54
54
 
55
55
  // src/hooks/magic-context/read-session-formatting.ts
56
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
56
57
  import { createRequire } from "node:module";
58
+ import { homedir } from "node:os";
59
+ import { dirname, join, resolve } from "node:path";
60
+ import { pathToFileURL } from "node:url";
57
61
 
58
62
  // src/shared/commit-detection.ts
59
63
  var HASH_HEX = "[0-9a-f]{7,12}";
@@ -146,23 +150,146 @@ function truncateArg(value, maxLen = 60) {
146
150
  return value;
147
151
  return `${value.slice(0, maxLen)}…`;
148
152
  }
149
- var requireFromThisModule = createRequire(import.meta.url);
153
+ var TOKENIZER_PACKAGE_DIRS = [
154
+ ["@cortexkit", "opencode-magic-context"],
155
+ ["@cortexkit", "pi-magic-context"]
156
+ ];
150
157
  var tokenizer;
151
- function getTokenizer() {
158
+ var tokenizerLoadAttempted = false;
159
+ var tokenizerLoadPromise;
160
+ var tokenizerWarningSent = false;
161
+ function tokenizerPackageRoots() {
162
+ const cwd = process.cwd();
163
+ const openCodeCache = join(process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache"), "opencode");
164
+ const roots = [cwd, openCodeCache];
165
+ const candidates = [];
166
+ for (const root of roots) {
167
+ for (const packageDir of TOKENIZER_PACKAGE_DIRS) {
168
+ candidates.push(join(root, "node_modules", ...packageDir, "node_modules", "ai-tokenizer"));
169
+ }
170
+ candidates.push(join(root, "node_modules", "ai-tokenizer"));
171
+ }
172
+ let ancestor = process.argv[1] ? dirname(resolve(process.argv[1])) : cwd;
173
+ while (true) {
174
+ candidates.push(join(ancestor, "node_modules", "ai-tokenizer"));
175
+ const parent = dirname(ancestor);
176
+ if (parent === ancestor)
177
+ break;
178
+ ancestor = parent;
179
+ }
180
+ return [...new Set(candidates)];
181
+ }
182
+ function packageImportTarget(value) {
183
+ if (typeof value === "string")
184
+ return value;
185
+ if (!value || typeof value !== "object")
186
+ return;
187
+ const conditions = value;
188
+ return packageImportTarget(conditions.import) ?? packageImportTarget(conditions.default);
189
+ }
190
+ function findTokenizerImportPaths() {
191
+ for (const packageRoot of tokenizerPackageRoots()) {
192
+ const packageJsonPath = join(packageRoot, "package.json");
193
+ if (!existsSync(packageJsonPath))
194
+ continue;
195
+ try {
196
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
197
+ const tokenizerTarget = packageImportTarget(packageJson.exports?.["."]) ?? (typeof packageJson.module === "string" ? packageJson.module : undefined) ?? (typeof packageJson.main === "string" ? packageJson.main : undefined);
198
+ const encodingTarget = packageImportTarget(packageJson.exports?.["./encoding/claude"]);
199
+ if (!tokenizerTarget || !encodingTarget)
200
+ continue;
201
+ return {
202
+ tokenizerPath: realpathSync(join(packageRoot, tokenizerTarget)),
203
+ encodingPath: realpathSync(join(packageRoot, encodingTarget))
204
+ };
205
+ } catch {}
206
+ }
207
+ return;
208
+ }
209
+ function constructTokenizer(tokenizerModule, claudeEncoding) {
210
+ const typedModule = tokenizerModule;
211
+ const Tokenizer = typedModule.default ?? typedModule.Tokenizer;
212
+ if (!Tokenizer) {
213
+ throw new Error("ai-tokenizer does not expose a Tokenizer constructor");
214
+ }
215
+ return new Tokenizer(claudeEncoding);
216
+ }
217
+ function loadTokenizer() {
218
+ const requireFromThisModule = createRequire(import.meta.url);
219
+ return constructTokenizer(requireFromThisModule("ai-" + "tokenizer"), requireFromThisModule("ai-tokenizer/encoding/" + "claude"));
220
+ }
221
+ async function loadTokenizerFromInstalledPackage() {
222
+ const installedPaths = findTokenizerImportPaths();
223
+ if (!installedPaths) {
224
+ throw new Error("ai-tokenizer was not found under the project, runtime, or OpenCode cache node_modules roots");
225
+ }
226
+ const [tokenizerModule, claudeEncoding] = await Promise.all([
227
+ import(pathToFileURL(installedPaths.tokenizerPath).href),
228
+ import(pathToFileURL(installedPaths.encodingPath).href)
229
+ ]);
230
+ return constructTokenizer(tokenizerModule, claudeEncoding);
231
+ }
232
+ function warnTokenizerFallback(error) {
233
+ if (tokenizerWarningSent)
234
+ return;
235
+ tokenizerWarningSent = true;
236
+ const reason = error instanceof Error ? error.message : String(error);
237
+ console.warn("[magic-context] ai-tokenizer is unavailable; using approximate character-based token counts for this process. Token budgets, persisted per-message counts, and protected-tail/compartment boundaries may be less accurate until restart:", reason);
238
+ }
239
+ async function preloadTokenizer() {
152
240
  if (tokenizer)
241
+ return true;
242
+ if (tokenizerLoadAttempted)
243
+ return false;
244
+ if (tokenizerLoadPromise)
245
+ return tokenizerLoadPromise;
246
+ tokenizerLoadPromise = (async () => {
247
+ try {
248
+ try {
249
+ tokenizer = loadTokenizer();
250
+ } catch {
251
+ tokenizer = await loadTokenizerFromInstalledPackage();
252
+ }
253
+ tokenizerLoadAttempted = true;
254
+ return true;
255
+ } catch (error) {
256
+ tokenizerLoadAttempted = true;
257
+ warnTokenizerFallback(error);
258
+ return false;
259
+ } finally {
260
+ tokenizerLoadPromise = undefined;
261
+ }
262
+ })();
263
+ return tokenizerLoadPromise;
264
+ }
265
+ function getTokenizer() {
266
+ if (tokenizer || tokenizerLoadAttempted)
153
267
  return tokenizer;
154
- const tokenizerModule = requireFromThisModule("ai-" + "tokenizer");
155
- const Tokenizer = tokenizerModule.default ?? tokenizerModule.Tokenizer;
156
- if (!Tokenizer)
157
- throw new Error("ai-tokenizer does not expose a Tokenizer constructor");
158
- const claudeEncoding = requireFromThisModule("ai-tokenizer/encoding/" + "claude");
159
- tokenizer = new Tokenizer(claudeEncoding);
268
+ tokenizerLoadAttempted = true;
269
+ try {
270
+ tokenizer = loadTokenizer();
271
+ } catch (error) {
272
+ warnTokenizerFallback(error);
273
+ }
160
274
  return tokenizer;
161
275
  }
276
+ function estimateTokensHeuristically(text) {
277
+ return Math.ceil(text.length / 3.5);
278
+ }
162
279
  function estimateTokens(text) {
163
280
  if (!text)
164
281
  return 0;
165
- return getTokenizer().encode(text, "all").length;
282
+ const activeTokenizer = getTokenizer();
283
+ if (!activeTokenizer)
284
+ return estimateTokensHeuristically(text);
285
+ try {
286
+ return activeTokenizer.encode(text, "all").length;
287
+ } catch (error) {
288
+ tokenizer = undefined;
289
+ tokenizerLoadAttempted = true;
290
+ warnTokenizerFallback(error);
291
+ return estimateTokensHeuristically(text);
292
+ }
166
293
  }
167
294
  function normalizeText(text) {
168
295
  return text.replace(/\s+/g, " ").trim();
@@ -2889,4 +3016,4 @@ function clearSession(db, sessionId) {
2889
3016
  })();
2890
3017
  }
2891
3018
 
2892
- export { textMentionsRecentCommit, hasMeaningfulUserText, extractTexts, extractToolCallSummaries, estimateTokens, normalizeText, stableStringify, clearCompressionDepth, clearCompressionDepthRange, ensureSessionMetaRow, persistCachedM0, clearCachedM0M1, isRawCompactionSummaryInfo, extractInMemoryMessageViews, buildInMemoryTailRawMessages, isRecord, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, invalidateTrueRawTokenCache, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isThinkingPart, isTextPart, isToolPartWithOutput, isFilePart, buildFileSourceContent, isEditTool, partHasCompletedResult, extractToolCallObservation, ToolMutationBatch, createToolDropTarget, setRawMessageProvider, cleanUserText, withRawSessionMessageCache, readRawSessionMessages, primeTailRawMessageCache, getCachedAbsoluteMessageCount, primeInMemoryTailRawMessageCache, readRawSessionMessageOrdinalPage, getRawSessionStoredMessageCount, readRawSessionMessagePartsById, readRawSessionMessageOrdinalById, readRawSessionMessageById, getRawSessionMessageCount, getRawSessionTagKeysThrough, getLegacyProtectedTailStartOrdinal, readSessionChunk, getMessageIndexSourceIdentity, isMessageIndexSourceCurrent, getLastIndexedOrdinal, getIndexedMessageCorpusSize, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, deleteIndexedMessage, clearIndexedMessages, indexSingleMessage, indexMessagesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, clearSession };
3019
+ export { textMentionsRecentCommit, hasMeaningfulUserText, extractTexts, extractToolCallSummaries, preloadTokenizer, estimateTokens, normalizeText, stableStringify, clearCompressionDepth, clearCompressionDepthRange, ensureSessionMetaRow, persistCachedM0, clearCachedM0M1, isRawCompactionSummaryInfo, extractInMemoryMessageViews, buildInMemoryTailRawMessages, isRecord, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, invalidateTrueRawTokenCache, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isThinkingPart, isTextPart, isToolPartWithOutput, isFilePart, buildFileSourceContent, isEditTool, partHasCompletedResult, extractToolCallObservation, ToolMutationBatch, createToolDropTarget, setRawMessageProvider, cleanUserText, withRawSessionMessageCache, readRawSessionMessages, primeTailRawMessageCache, getCachedAbsoluteMessageCount, primeInMemoryTailRawMessageCache, readRawSessionMessageOrdinalPage, getRawSessionStoredMessageCount, readRawSessionMessagePartsById, readRawSessionMessageOrdinalById, readRawSessionMessageById, getRawSessionMessageCount, getRawSessionTagKeysThrough, getLegacyProtectedTailStartOrdinal, readSessionChunk, getMessageIndexSourceIdentity, isMessageIndexSourceCurrent, getLastIndexedOrdinal, getIndexedMessageCorpusSize, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, deleteIndexedMessage, clearIndexedMessages, indexSingleMessage, indexMessagesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, clearSession };
@@ -90,9 +90,39 @@ function stripTrailingCommas(content) {
90
90
  }
91
91
  return result;
92
92
  }
93
- function parseJsonc(content) {
93
+ var PROTOTYPE_POLLUTION_KEYS = new Set(["__proto__", "constructor", "prototype"]);
94
+ function isPrototypePollutionKey(key) {
95
+ return PROTOTYPE_POLLUTION_KEYS.has(key);
96
+ }
97
+ function sanitizeParsedJson(value, options = {}, path = []) {
98
+ if (Array.isArray(value)) {
99
+ return value.map((entry, index) => sanitizeParsedJson(entry, options, [...path, index]));
100
+ }
101
+ if (value === null || typeof value !== "object")
102
+ return value;
103
+ const source = value;
104
+ const sourcePrototype = Object.getPrototypeOf(source);
105
+ if (sourcePrototype !== null && sourcePrototype !== Object.prototype) {
106
+ options.onRejectedKey?.([...path, "__proto__"]);
107
+ }
108
+ const sanitized = {};
109
+ for (const key of Object.keys(source)) {
110
+ if (isPrototypePollutionKey(key)) {
111
+ options.onRejectedKey?.([...path, key]);
112
+ continue;
113
+ }
114
+ Object.defineProperty(sanitized, key, {
115
+ value: sanitizeParsedJson(source[key], options, [...path, key]),
116
+ enumerable: true,
117
+ configurable: true,
118
+ writable: true
119
+ });
120
+ }
121
+ return sanitized;
122
+ }
123
+ function parseJsonc(content, options = {}) {
94
124
  const normalized = stripTrailingCommas(stripJsonComments(content));
95
- return JSON.parse(normalized);
125
+ return sanitizeParsedJson(JSON.parse(normalized), options);
96
126
  }
97
127
  function readJsoncFile(filePath) {
98
128
  try {
@@ -113,4 +143,4 @@ function detectConfigFile(basePath) {
113
143
  return { format: "none", path: jsoncPath };
114
144
  }
115
145
 
116
- export { stripJsonComments, parseJsonc, readJsoncFile, detectConfigFile };
146
+ export { stripJsonComments, isPrototypePollutionKey, parseJsonc, readJsoncFile, detectConfigFile };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readJsoncFile
3
- } from "./index-0c9dmw9m.js";
3
+ } from "./index-8mtsfhyg.js";
4
4
  import {
5
5
  waitForSafeNotificationTarget
6
6
  } from "./index-tsgs7td8.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAkyBvE,QAAA,MAAM,MAAM,EAAE,YAGb,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAuyBvE,QAAA,MAAM,MAAM,EAAE,YAGb,CAAC;AAEF,eAAe,MAAM,CAAC"}