@cortexkit/opencode-magic-context 0.44.0 → 0.44.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 (92) hide show
  1. package/dist/agents/magic-context-prompt.d.ts +2 -0
  2. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  3. package/dist/{announcement-1a8bvswd.js → announcement-n8hs7kjw.js} +2 -2
  4. package/dist/config/live-child-output-cap.d.ts +18 -0
  5. package/dist/config/live-child-output-cap.d.ts.map +1 -0
  6. package/dist/config/schema/magic-context.d.ts +1 -1
  7. package/dist/config/schema/magic-context.d.ts.map +1 -1
  8. package/dist/{conflict-warning-hook-48f7np9d.js → conflict-warning-hook-d14ah73v.js} +6 -6
  9. package/dist/{derive-budgets-8kgevxmx.js → derive-budgets-gd2270s0.js} +3 -3
  10. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  11. package/dist/features/magic-context/dreamer/open-opencode-db.d.ts +2 -0
  12. package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/primer-seed.d.ts +11 -5
  14. package/dist/features/magic-context/dreamer/primer-seed.d.ts.map +1 -1
  15. package/dist/features/magic-context/dreamer/refresh-primers.d.ts +2 -2
  16. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  17. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  18. package/dist/features/magic-context/memory/project-identity.d.ts +7 -0
  19. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  20. package/dist/features/magic-context/mural/mural-font.generated.d.ts.map +1 -1
  21. package/dist/features/magic-context/session-cache-ttl.d.ts +10 -0
  22. package/dist/features/magic-context/session-cache-ttl.d.ts.map +1 -0
  23. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  24. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  26. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  28. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  30. package/dist/hooks/magic-context/opencode-v1-store-fixture.d.ts +12 -0
  31. package/dist/hooks/magic-context/opencode-v1-store-fixture.d.ts.map +1 -0
  32. package/dist/hooks/magic-context/read-session-chunk.d.ts +16 -0
  33. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  34. package/dist/hooks/magic-context/read-session-db.d.ts +5 -1
  35. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  36. package/dist/hooks/magic-context/read-session-raw.d.ts +10 -0
  37. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  38. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/transform.d.ts +1 -0
  40. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  41. package/dist/{index-cj5qe2nw.js → index-0rp6pj54.js} +3 -3
  42. package/dist/{index-4b30nf6z.js → index-32b096cc.js} +1 -1
  43. package/dist/{index-tjq5jztd.js → index-3bygzk2d.js} +1 -1
  44. package/dist/{index-c906f3ff.js → index-a9vbtdzv.js} +4 -4
  45. package/dist/{index-pye48m79.js → index-cz88kw0n.js} +13 -3
  46. package/dist/{index-5f4qsnaq.js → index-d107az47.js} +2 -2
  47. package/dist/{index-rdey8znw.js → index-jtdrvmcn.js} +2368 -35
  48. package/dist/{index-v6wsttqt.js → index-kr5qehbd.js} +1 -1
  49. package/dist/{index-dx0xnd4q.js → index-kwe03yde.js} +1 -1
  50. package/dist/{index-2zf5fv89.js → index-s6b7h12g.js} +100 -12
  51. package/dist/{index-6z9g64js.js → index-s70wtd8k.js} +4 -1
  52. package/dist/{index-01ft0h3p.js → index-stb5fg12.js} +2 -2
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +474 -2601
  55. package/dist/{message-time-backfill-rm9wmcem.js → message-time-backfill-q374fxc5.js} +3 -3
  56. package/dist/plugin/dream-timer.d.ts.map +1 -1
  57. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  58. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  59. package/dist/{read-session-chunk-ktz5zt70.js → read-session-chunk-fkdv2g5b.js} +6 -4
  60. package/dist/{recomp-orchestrator-ahekzt0s.js → recomp-orchestrator-k4h5n0p3.js} +9 -9
  61. package/dist/{safe-notification-target-6w0esgd6.js → safe-notification-target-50gm9c58.js} +3 -3
  62. package/dist/{send-session-notification-w7xbnrsm.js → send-session-notification-g2k03zyn.js} +5 -5
  63. package/dist/shared/cache-ttl-display.d.ts +3 -1
  64. package/dist/shared/cache-ttl-display.d.ts.map +1 -1
  65. package/dist/shared/harness.d.ts +11 -0
  66. package/dist/shared/harness.d.ts.map +1 -1
  67. package/dist/shared/model-cache-ttl.d.ts +9 -0
  68. package/dist/shared/model-cache-ttl.d.ts.map +1 -0
  69. package/dist/shared/rpc-types.d.ts +1 -1
  70. package/dist/shared/rpc-types.d.ts.map +1 -1
  71. package/dist/shared/status-view.d.ts +1 -1
  72. package/dist/shared/status-view.d.ts.map +1 -1
  73. package/dist/tools/ctx-expand/render.d.ts.map +1 -1
  74. package/dist/v2/hooks/context.d.ts.map +1 -1
  75. package/dist/v2/server.js +7820 -7567
  76. package/dist/wrapup-orchestrator-35y56636.js +18 -0
  77. package/package.json +1 -1
  78. package/src/agents/magic-context-prompt.test.ts +125 -0
  79. package/src/agents/magic-context-prompt.ts +12 -7
  80. package/src/config/live-child-output-cap.test.ts +75 -0
  81. package/src/config/live-child-output-cap.ts +70 -0
  82. package/src/config/live-run-config.test.ts +24 -11
  83. package/src/config/schema/magic-context.test.ts +16 -1
  84. package/src/config/schema/magic-context.ts +6 -4
  85. package/src/shared/cache-ttl-display.ts +14 -20
  86. package/src/shared/harness.ts +14 -0
  87. package/src/shared/model-cache-ttl.test.ts +40 -0
  88. package/src/shared/model-cache-ttl.ts +58 -0
  89. package/src/shared/prompt-surface-a1-golden.md +13 -13
  90. package/src/shared/rpc-types.ts +1 -1
  91. package/src/shared/status-view.ts +1 -1
  92. package/dist/wrapup-orchestrator-9srk0kjf.js +0 -18
package/dist/index.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  setHarness,
3
3
  getHarness,
4
+ harnessOwnsOpenCodeStore,
4
5
  getDataDir,
5
6
  getOpenCodeStorageDir,
6
7
  getMagicContextStorageResolution,
7
8
  getMagicContextStorageDir
8
- } from "./index-6z9g64js.js";
9
+ } from "./index-s70wtd8k.js";
9
10
  import {
10
11
  sanitizeDiagnosticText,
11
12
  hasShareabilitySensitiveText,
@@ -13,16 +14,15 @@ import {
13
14
  sessionLog,
14
15
  getLoggerDiagnostics,
15
16
  flushLogger
16
- } from "./index-tjq5jztd.js";
17
+ } from "./index-3bygzk2d.js";
17
18
  import {
18
19
  withContentLanguageDirective,
19
- buildPrimaryLanguageDirective,
20
- setJsoncValue,
21
- removeJsoncValue,
22
- cortexKitUserConfigBasePath,
23
- cortexKitProjectConfigBasePath,
24
- resolveLegacyConfigSources,
25
- resolveLegacyConfigSourcesForHarness,
20
+ formatConfigParseStatusLine,
21
+ claimConfigParseFailuresOnce,
22
+ COMPACTION_ENABLED_PATH,
23
+ isDreamerRunnable,
24
+ isHistorianRunnable,
25
+ isCompactionEnabled,
26
26
  migrateMagicContextConfigLocations,
27
27
  string,
28
28
  unknown,
@@ -37,16 +37,18 @@ import {
37
37
  promptSurfaceConfigIdentity,
38
38
  resolveModelConfigValue,
39
39
  resolvePromptSurface,
40
- resolveModelConfigOrDefault,
41
40
  DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE,
42
41
  DEFAULT_HISTORIAN_TIMEOUT_MS,
43
- PROTECTED_TOKENS_MIN,
44
42
  DEFAULT_LOCAL_EMBEDDING_MODEL,
45
- PER_HARNESS_MIGRATION_INVENTORY,
46
- PER_HARNESS_MODEL_KEYS,
47
- ConfigProfilesSchema,
48
- MagicContextConfigSchema,
49
- LIVE_RELOAD_CONFIG_PATHS,
43
+ getProtectedTokensTierOverrides,
44
+ loadPluginConfigDetailed,
45
+ BoundedSessionMap,
46
+ historianRunConfig,
47
+ dreamerRunConfig,
48
+ pluginConfigReader,
49
+ currentPluginConfigReader,
50
+ withLiveDreamerOutputCap,
51
+ createDreamerOutputCapSampler,
50
52
  formatFailClosedBlockingMessage,
51
53
  formatFailClosedBlockingSummary,
52
54
  createFailClosedBlockingError,
@@ -63,6 +65,7 @@ import {
63
65
  resolveProjectIdentity,
64
66
  directoryHasGitMetadata,
65
67
  describeUnresolvedProjectIdentity,
68
+ isUsableProjectIdentity,
66
69
  resolveProjectIdentityForSession,
67
70
  normalizeStoredProjectPath,
68
71
  storedPathBelongsToIdentity,
@@ -167,6 +170,8 @@ import {
167
170
  sessionDecisionCalibration,
168
171
  transitionSessionHygieneUnits,
169
172
  getProtectionWindowForSession,
173
+ readReplayDocument,
174
+ updateReplayDocument,
170
175
  isEmergencyRecoveryArmed,
171
176
  isProviderOverflowReconfirmed,
172
177
  isProviderOverflowFailClosedProven,
@@ -248,7 +253,6 @@ import {
248
253
  setSessionWorkMetrics,
249
254
  getObservedEpochFloor,
250
255
  resolveEpochFloorForPass,
251
- BoundedSessionMap,
252
256
  registerLkgPersistence,
253
257
  beginLkgPass,
254
258
  visitMessageContentFields,
@@ -463,6 +467,7 @@ import {
463
467
  applyDeferredCompactionMarker,
464
468
  removeCompactionMarkerForSession,
465
469
  checkCompactionMarkerConsistency,
470
+ buildMagicContextSection,
466
471
  modelKeyAcceptsImages,
467
472
  resolveMuralWire,
468
473
  extractM0Block,
@@ -505,21 +510,14 @@ import {
505
510
  setRecompStarting2,
506
511
  setRecompTerminal2,
507
512
  runManagedRecomp2
508
- } from "./index-rdey8znw.js";
509
- import {
510
- stripJsonComments,
511
- isPrototypePollutionKey,
512
- parseJsoncRecovering,
513
- parseJsonc,
514
- detectConfigFile
515
- } from "./index-sd3egckz.js";
513
+ } from "./index-jtdrvmcn.js";
514
+ import"./index-sd3egckz.js";
516
515
  import {
517
516
  canonicalModelIdentity,
518
517
  piModelRefToCanonical,
519
518
  modelRefLookupOrder,
520
519
  setStoragePrivatePermissionEnforcement,
521
520
  shouldEnforcePrivateStoragePermissions,
522
- setWindowOverlayPath,
523
521
  reloadWindowOverlay,
524
522
  hasTrustedAbsoluteWall,
525
523
  applyProvenInputFloor,
@@ -537,7 +535,7 @@ import {
537
535
  deriveHistorianChunkTokens2,
538
536
  resolveKnownHistorianContextLimit2,
539
537
  resolveHistorianContextLimit2
540
- } from "./index-01ft0h3p.js";
538
+ } from "./index-stb5fg12.js";
541
539
  import {
542
540
  resolveOpenCodeDbPath,
543
541
  assertOpenCodeStoreGeneration,
@@ -560,7 +558,7 @@ import {
560
558
  latestPersistedMessageForRecovery,
561
559
  getMessageTimesFromOpenCodeDb,
562
560
  findLastAssistantModelFromOpenCodeDb
563
- } from "./index-pye48m79.js";
561
+ } from "./index-cz88kw0n.js";
564
562
  import {
565
563
  textMentionsRecentCommit,
566
564
  hasMeaningfulUserText2,
@@ -672,6 +670,7 @@ import {
672
670
  cleanUserText2,
673
671
  withRawSessionMessageCache2,
674
672
  readRawSessionMessages2,
673
+ visitRawSessionMessages2,
675
674
  primeTailRawMessageCache2,
676
675
  primeInMemoryTailRawMessageCache2,
677
676
  readRawSessionMessageOrdinalPage2,
@@ -682,8 +681,8 @@ import {
682
681
  readRawSessionMessageById2,
683
682
  readSessionChunk2,
684
683
  readRawSessionSeedTail2
685
- } from "./index-2zf5fv89.js";
686
- import"./index-dx0xnd4q.js";
684
+ } from "./index-s6b7h12g.js";
685
+ import"./index-kwe03yde.js";
687
686
  import {
688
687
  getErrorMessage,
689
688
  describeError,
@@ -692,13 +691,13 @@ import {
692
691
  clearIgnoredMessages2,
693
692
  observeIgnoredNotificationEvent2,
694
693
  sendStatusNotification2
695
- } from "./index-c906f3ff.js";
694
+ } from "./index-a9vbtdzv.js";
696
695
  import {
697
696
  detectConflicts,
698
697
  resolveCompactionForBoot,
699
698
  sendConflictWarning2,
700
699
  cleanupConflictWarnings2
701
- } from "./index-5f4qsnaq.js";
700
+ } from "./index-d107az47.js";
702
701
  import {
703
702
  resolveModelCalibration,
704
703
  calibrateBuckets
@@ -738,16 +737,16 @@ import {
738
737
  ANNOUNCEMENT_FOOTER2,
739
738
  markAnnouncementSeen2,
740
739
  shouldShowAnnouncement2
741
- } from "./index-4b30nf6z.js";
740
+ } from "./index-32b096cc.js";
742
741
  import {
743
742
  resolvePromptContext2
744
743
  } from "./index-fmsr7v69.js";
745
744
  import {
746
745
  runManagedWrapup2
747
- } from "./index-cj5qe2nw.js";
746
+ } from "./index-0rp6pj54.js";
748
747
  import {
749
748
  logSlowWriteTransaction
750
- } from "./index-v6wsttqt.js";
749
+ } from "./index-kr5qehbd.js";
751
750
  import {
752
751
  __toESM,
753
752
  __commonJS
@@ -8824,2127 +8823,6 @@ function buildHiddenAgentConfig(prompt, allowedTools, maxSteps, overrides, agent
8824
8823
  };
8825
8824
  }
8826
8825
 
8827
- // src/config/index.ts
8828
- import { existsSync as existsSync3 } from "node:fs";
8829
-
8830
- // src/shared/config-diagnostics.ts
8831
- var CONFIG_WARNING_CLASS = {
8832
- FILE_PARSE: "file-parse",
8833
- FILE_IO: "file-io",
8834
- INVALID_LEAF: "invalid-leaf"
8835
- };
8836
- function formatConfigParseStatusLine(failure) {
8837
- const disposition = failure.recovered ? "recovered values applied; fix the file" : "running on defaults";
8838
- return `Config: PARSE FAILED (${failure.path}:${failure.line}:${failure.column}) — ${disposition}`;
8839
- }
8840
- var claimedFailures = new Set;
8841
- function failureKey(surface, failure) {
8842
- return `${surface}\x00${failure.path}\x00${failure.line}\x00${failure.column}\x00${failure.message}`;
8843
- }
8844
- function claimConfigParseFailuresOnce(surface, failures) {
8845
- return failures.filter((failure) => {
8846
- const key = failureKey(surface, failure);
8847
- if (claimedFailures.has(key))
8848
- return false;
8849
- claimedFailures.add(key);
8850
- return true;
8851
- });
8852
- }
8853
-
8854
- // src/config/agent-disable.ts
8855
- var COMPACTION_ENABLED_PATH = `compaction${"."}enabled`;
8856
- function isDreamerRunnable(config) {
8857
- return !!config.dreamer && config.dreamer.disable !== true;
8858
- }
8859
- function isHistorianRunnable(config) {
8860
- return config.historian?.disable !== true;
8861
- }
8862
- function isCompactionEnabled(config) {
8863
- return config.compaction?.enabled !== false;
8864
- }
8865
- function clonePlainObject(value) {
8866
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
8867
- return;
8868
- }
8869
- return { ...value };
8870
- }
8871
- function migrateLegacyEnabledForAgent(args) {
8872
- const agent = clonePlainObject(args.patched[args.agentName]);
8873
- if (!agent || !("enabled" in agent))
8874
- return;
8875
- const enabled = agent.enabled;
8876
- const disable = agent.disable;
8877
- delete agent.enabled;
8878
- if (args.agentName === "historian") {
8879
- args.warnings.push('Removed invalid "historian.enabled" in-memory (run doctor to persist).');
8880
- args.patched.historian = agent;
8881
- return;
8882
- }
8883
- if (disable !== true && enabled === false) {
8884
- agent.disable = true;
8885
- args.warnings.push('Migrated "dreamer.enabled=false" → "dreamer.disable=true" in-memory (run doctor to persist). This now also disables manual /ctx-dream; for manual-only remove disable and set schedule="".');
8886
- }
8887
- args.patched.dreamer = agent;
8888
- }
8889
- function migrateLegacyAgentEnabledInMemory(rawConfig, warnings) {
8890
- const shouldPatch = ["dreamer", "historian"].some((key) => {
8891
- const agent = rawConfig[key];
8892
- return typeof agent === "object" && agent !== null && !Array.isArray(agent) && "enabled" in agent;
8893
- });
8894
- if (!shouldPatch)
8895
- return rawConfig;
8896
- const patched = { ...rawConfig };
8897
- migrateLegacyEnabledForAgent({ patched, agentName: "dreamer", warnings });
8898
- migrateLegacyEnabledForAgent({ patched, agentName: "historian", warnings });
8899
- return patched;
8900
- }
8901
-
8902
- // src/config/migrate-dreamer-v2.ts
8903
- var OLD_VERIFY_TASK = "verify";
8904
- var OLD_CURATE_TASKS = ["consolidate", "archive-stale", "improve"];
8905
- var RETIRED_OBJECT_MEMORY_TASKS = ["maintain-memory", ...OLD_CURATE_TASKS];
8906
- var CANONICAL = [
8907
- "map-memories",
8908
- "verify",
8909
- "verify-broad",
8910
- "curate",
8911
- "classify-memories",
8912
- "retrospective",
8913
- "maintain-docs",
8914
- "evaluate-smart-notes",
8915
- "review-user-memories",
8916
- "promote-primers",
8917
- "refresh-primers"
8918
- ];
8919
- var DEFAULT_BASE_CRON = "0 2 * * *";
8920
- var DEFAULT_CLASSIFY_CRON = "0 6 * * *";
8921
- var DEFAULT_RETROSPECTIVE_CRON = "0 5 * * *";
8922
- var DEFAULT_VERIFY_BROAD_CRON = "0 4 * * 0";
8923
- function windowToCron(schedule) {
8924
- if (typeof schedule !== "string")
8925
- return DEFAULT_BASE_CRON;
8926
- const m = /^(\d{1,2}):(\d{2})\s*-/.exec(schedule.trim());
8927
- if (!m)
8928
- return DEFAULT_BASE_CRON;
8929
- const hour = Number(m[1]);
8930
- const minute = Number(m[2]);
8931
- if (hour >= 24 || minute >= 60)
8932
- return DEFAULT_BASE_CRON;
8933
- return `${minute} ${hour} * * *`;
8934
- }
8935
- function asObject(value) {
8936
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
8937
- }
8938
- function cronIntervalScore(schedule) {
8939
- const parts = schedule.trim().split(/\s+/);
8940
- if (parts.length !== 5)
8941
- return Number.POSITIVE_INFINITY;
8942
- const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
8943
- if (month !== "*")
8944
- return 366 * 24 * 60;
8945
- if (dayOfMonth !== "*")
8946
- return 31 * 24 * 60;
8947
- if (dayOfWeek !== "*")
8948
- return 7 * 24 * 60;
8949
- const everyHour = /^\*\/(\d+)$/.exec(hour ?? "");
8950
- if (everyHour)
8951
- return Math.max(1, Number(everyHour[1])) * 60;
8952
- if (hour === "*") {
8953
- const everyMinute = /^\*\/(\d+)$/.exec(minute ?? "");
8954
- return everyMinute ? Math.max(1, Number(everyMinute[1])) : 60;
8955
- }
8956
- return 24 * 60;
8957
- }
8958
- function mostFrequentSchedule(schedules) {
8959
- const enabled = schedules.map((s) => s.trim()).filter(Boolean);
8960
- if (enabled.length === 0)
8961
- return "";
8962
- return enabled.sort((a, b) => cronIntervalScore(a) - cronIntervalScore(b))[0] ?? "";
8963
- }
8964
- function withoutBroadInterval(entry) {
8965
- const { broad_interval_days: _broad, ...rest } = entry;
8966
- return rest;
8967
- }
8968
- function reconcileV2TasksObject(rawConfig, dreamer, tasksObject) {
8969
- const hasVerifyBroad = "verify-broad" in tasksObject;
8970
- const hasBroadIntervalAnywhere = Object.values(tasksObject).some((v) => asObject(v) && ("broad_interval_days" in v));
8971
- const hasStaleKeyFiles = "key-files" in tasksObject;
8972
- if (hasVerifyBroad && !hasBroadIntervalAnywhere && !hasStaleKeyFiles)
8973
- return rawConfig;
8974
- const nextTasks = {};
8975
- for (const [key, value] of Object.entries(tasksObject)) {
8976
- if (key === "key-files")
8977
- continue;
8978
- const obj = asObject(value);
8979
- nextTasks[key] = obj ? withoutBroadInterval(obj) : value;
8980
- }
8981
- if (!hasVerifyBroad) {
8982
- const verify = asObject(tasksObject.verify);
8983
- const verifyEnabled = typeof verify?.schedule === "string" && verify.schedule.trim() !== "";
8984
- nextTasks["verify-broad"] = {
8985
- schedule: verifyEnabled ? DEFAULT_VERIFY_BROAD_CRON : ""
8986
- };
8987
- }
8988
- return { ...rawConfig, dreamer: { ...dreamer, tasks: nextTasks } };
8989
- }
8990
- function migrateDreamerV2(rawConfig, warnings) {
8991
- const dreamer = asObject(rawConfig.dreamer);
8992
- if (!dreamer)
8993
- return rawConfig;
8994
- const tasksObject = asObject(dreamer.tasks);
8995
- const hasRetiredObjectTasks = tasksObject ? RETIRED_OBJECT_MEMORY_TASKS.some((task) => (task in tasksObject)) : false;
8996
- if (tasksObject && !hasRetiredObjectTasks) {
8997
- const hasLegacyOutsideTasks = "schedule" in dreamer || "user_memories" in dreamer || "pin_key_files" in dreamer || "task_timeout_minutes" in dreamer || "max_runtime_minutes" in dreamer;
8998
- if (!hasLegacyOutsideTasks) {
8999
- return reconcileV2TasksObject(rawConfig, dreamer, tasksObject);
9000
- }
9001
- }
9002
- const hasLegacy = "schedule" in dreamer || Array.isArray(dreamer.tasks) || hasRetiredObjectTasks || "user_memories" in dreamer || "pin_key_files" in dreamer || "task_timeout_minutes" in dreamer || "max_runtime_minutes" in dreamer;
9003
- if (!hasLegacy)
9004
- return rawConfig;
9005
- const baseCron = windowToCron(dreamer.schedule);
9006
- const timeout = typeof dreamer.task_timeout_minutes === "number" ? dreamer.task_timeout_minutes : undefined;
9007
- const withTimeout = (entry) => timeout !== undefined ? { ...entry, timeout_minutes: timeout } : entry;
9008
- const classifySchedule = dreamer.disable === true ? "" : DEFAULT_CLASSIFY_CRON;
9009
- const retrospectiveSchedule = dreamer.disable === true ? "" : DEFAULT_RETROSPECTIVE_CRON;
9010
- const tasks = {};
9011
- if (tasksObject) {
9012
- for (const [key, value] of Object.entries(tasksObject)) {
9013
- if (RETIRED_OBJECT_MEMORY_TASKS.includes(key))
9014
- continue;
9015
- if (asObject(value))
9016
- tasks[key] = { ...value };
9017
- }
9018
- const maintainMemoryEntry = asObject(tasksObject["maintain-memory"]);
9019
- if (maintainMemoryEntry) {
9020
- const schedule = typeof maintainMemoryEntry.schedule === "string" ? maintainMemoryEntry.schedule : baseCron;
9021
- tasks.verify = withTimeout({
9022
- ...withoutBroadInterval(maintainMemoryEntry),
9023
- ...tasks.verify ?? {},
9024
- schedule: tasks.verify?.schedule ?? schedule
9025
- });
9026
- tasks.curate = withTimeout({
9027
- ...withoutBroadInterval(maintainMemoryEntry),
9028
- ...tasks.curate ?? {},
9029
- schedule: tasks.curate?.schedule ?? schedule
9030
- });
9031
- }
9032
- const oldVerifyEntry = asObject(tasksObject[OLD_VERIFY_TASK]);
9033
- if (oldVerifyEntry) {
9034
- tasks.verify = withTimeout({
9035
- ...withoutBroadInterval(oldVerifyEntry),
9036
- ...tasks.verify ?? {},
9037
- schedule: tasks.verify?.schedule ?? (typeof oldVerifyEntry.schedule === "string" ? oldVerifyEntry.schedule : baseCron)
9038
- });
9039
- }
9040
- if (!tasks["verify-broad"]) {
9041
- const verifyEnabled = typeof tasks.verify?.schedule === "string" && tasks.verify.schedule.trim() !== "";
9042
- tasks["verify-broad"] = withTimeout({
9043
- schedule: verifyEnabled ? DEFAULT_VERIFY_BROAD_CRON : ""
9044
- });
9045
- }
9046
- const oldCurateEntries = OLD_CURATE_TASKS.map((task) => asObject(tasksObject[task])).filter((entry) => Boolean(entry));
9047
- if (oldCurateEntries.length > 0) {
9048
- const oldSchedules = oldCurateEntries.map((entry) => typeof entry.schedule === "string" ? entry.schedule : baseCron);
9049
- tasks.curate = withTimeout({
9050
- ...tasks.curate ?? {},
9051
- schedule: mostFrequentSchedule(oldSchedules)
9052
- });
9053
- }
9054
- for (const task of CANONICAL) {
9055
- if (!tasks[task]) {
9056
- const schedule = task === "verify" || task === "curate" || task === "verify-broad" ? "" : task === "classify-memories" ? classifySchedule : task === "retrospective" ? retrospectiveSchedule : task === "maintain-docs" ? "" : baseCron;
9057
- tasks[task] = withTimeout({ schedule });
9058
- }
9059
- }
9060
- } else {
9061
- const legacyArray = Array.isArray(dreamer.tasks) ? dreamer.tasks.filter((t) => typeof t === "string") : null;
9062
- const verifySelected = legacyArray ? legacyArray.includes(OLD_VERIFY_TASK) : true;
9063
- const curateSelected = legacyArray ? legacyArray.some((task) => OLD_CURATE_TASKS.includes(task)) : true;
9064
- tasks.verify = withTimeout({
9065
- schedule: verifySelected ? baseCron : ""
9066
- });
9067
- tasks["verify-broad"] = withTimeout({
9068
- schedule: verifySelected ? DEFAULT_VERIFY_BROAD_CRON : ""
9069
- });
9070
- tasks.curate = withTimeout({
9071
- schedule: curateSelected ? baseCron : ""
9072
- });
9073
- tasks["classify-memories"] = withTimeout({
9074
- schedule: classifySchedule
9075
- });
9076
- tasks.retrospective = withTimeout({
9077
- schedule: retrospectiveSchedule
9078
- });
9079
- tasks["maintain-docs"] = withTimeout({
9080
- schedule: legacyArray?.includes("maintain-docs") ? baseCron : ""
9081
- });
9082
- }
9083
- tasks["map-memories"] ??= withTimeout({ schedule: baseCron });
9084
- tasks["evaluate-smart-notes"] ??= withTimeout({ schedule: baseCron });
9085
- const um = asObject(dreamer.user_memories);
9086
- const umEnabled = um ? um.enabled !== false : true;
9087
- if (um || !tasks["review-user-memories"]) {
9088
- tasks["review-user-memories"] = withTimeout({
9089
- ...tasks["review-user-memories"] ?? {},
9090
- schedule: umEnabled ? baseCron : "",
9091
- ...um && typeof um.promotion_threshold === "number" ? { promotion_threshold: um.promotion_threshold } : {}
9092
- });
9093
- }
9094
- const {
9095
- schedule: _schedule,
9096
- tasks: _tasks,
9097
- task_timeout_minutes: _tto,
9098
- max_runtime_minutes: _max,
9099
- user_memories: _um,
9100
- pin_key_files: _pkf,
9101
- ...rest
9102
- } = dreamer;
9103
- warnings.push('Migrated legacy dreamer scheduling (schedule window / tasks array / user_memories / pin_key_files) → per-task "dreamer.tasks" in-memory (run `doctor` to persist).');
9104
- return { ...rawConfig, dreamer: { ...rest, tasks } };
9105
- }
9106
-
9107
- // src/config/migrate-experimental.ts
9108
- function migrateLegacyExperimental(rawConfig, warnings) {
9109
- const experimental = rawConfig.experimental;
9110
- if (typeof experimental !== "object" || experimental === null) {
9111
- return rawConfig;
9112
- }
9113
- const exp = experimental;
9114
- const hasUM = "user_memories" in exp;
9115
- const hasPKF = "pin_key_files" in exp;
9116
- const hasMural = "mural" in exp;
9117
- const TOP_LEVEL_GRADUATED = ["temporal_awareness", "caveman_text_compression"];
9118
- const MEMORY_GRADUATED = ["auto_search", "git_commit_indexing"];
9119
- const hasGraduated = TOP_LEVEL_GRADUATED.some((k) => (k in exp)) || MEMORY_GRADUATED.some((k) => (k in exp)) || hasMural;
9120
- if (!hasUM && !hasPKF && !hasGraduated) {
9121
- return rawConfig;
9122
- }
9123
- const patched = { ...rawConfig };
9124
- const dreamer = typeof patched.dreamer === "object" && patched.dreamer !== null ? { ...patched.dreamer } : {};
9125
- const memory = typeof patched.memory === "object" && patched.memory !== null ? { ...patched.memory } : {};
9126
- const newExperimental = { ...exp };
9127
- const coerceToObject = (value) => {
9128
- if (typeof value === "boolean") {
9129
- return { enabled: value };
9130
- }
9131
- if (typeof value === "object" && value !== null) {
9132
- return { ...value };
9133
- }
9134
- return;
9135
- };
9136
- const relocate = (key, dest, destLabel) => {
9137
- if (!(key in exp))
9138
- return;
9139
- const oldValue = exp[key];
9140
- const existing = dest[key];
9141
- if (existing === undefined) {
9142
- dest[key] = oldValue;
9143
- warnings.push(`Migrated "experimental.${key}" → "${destLabel}${key}" in-memory (run \`doctor\` to persist).`);
9144
- } else if (typeof oldValue === "object" && oldValue !== null && typeof existing === "object" && existing !== null) {
9145
- dest[key] = {
9146
- ...oldValue,
9147
- ...existing
9148
- };
9149
- }
9150
- delete newExperimental[key];
9151
- };
9152
- for (const key of TOP_LEVEL_GRADUATED)
9153
- relocate(key, patched, "");
9154
- for (const key of MEMORY_GRADUATED)
9155
- relocate(key, memory, "memory.");
9156
- if (hasMural) {
9157
- const oldMural = coerceToObject(exp.mural);
9158
- const existingMural = patched.mural;
9159
- if (existingMural === undefined) {
9160
- patched.mural = oldMural ?? exp.mural;
9161
- warnings.push('Deprecated "experimental.mural"; use top-level "mural" instead (migrated in memory; run `doctor` to persist).');
9162
- } else if (oldMural !== undefined && typeof existingMural === "object" && existingMural !== null && !Array.isArray(existingMural)) {
9163
- patched.mural = {
9164
- ...oldMural,
9165
- ...existingMural
9166
- };
9167
- }
9168
- delete newExperimental.mural;
9169
- }
9170
- if (hasUM) {
9171
- const oldUM = coerceToObject(exp.user_memories);
9172
- if (oldUM !== undefined) {
9173
- if (dreamer.user_memories === undefined) {
9174
- dreamer.user_memories = oldUM;
9175
- warnings.push('Migrated "experimental.user_memories" → "dreamer.user_memories" in-memory (run `doctor` to persist).');
9176
- } else if (typeof dreamer.user_memories === "object" && dreamer.user_memories !== null) {
9177
- dreamer.user_memories = {
9178
- ...oldUM,
9179
- ...dreamer.user_memories
9180
- };
9181
- }
9182
- }
9183
- delete newExperimental.user_memories;
9184
- }
9185
- if (hasPKF) {
9186
- const oldPKF = coerceToObject(exp.pin_key_files);
9187
- if (oldPKF !== undefined) {
9188
- if (dreamer.pin_key_files === undefined) {
9189
- dreamer.pin_key_files = oldPKF;
9190
- warnings.push('Migrated "experimental.pin_key_files" → "dreamer.pin_key_files" in-memory (run `doctor` to persist).');
9191
- } else if (typeof dreamer.pin_key_files === "object" && dreamer.pin_key_files !== null) {
9192
- dreamer.pin_key_files = {
9193
- ...oldPKF,
9194
- ...dreamer.pin_key_files
9195
- };
9196
- } else if (typeof dreamer.pin_key_files === "boolean") {
9197
- dreamer.pin_key_files = { ...oldPKF, enabled: dreamer.pin_key_files };
9198
- }
9199
- }
9200
- delete newExperimental.pin_key_files;
9201
- }
9202
- patched.experimental = newExperimental;
9203
- patched.dreamer = dreamer;
9204
- if (Object.keys(memory).length > 0) {
9205
- patched.memory = memory;
9206
- }
9207
- return patched;
9208
- }
9209
-
9210
- // src/config/profiles.ts
9211
- function withoutProfileFields(raw) {
9212
- const copy = { ...raw };
9213
- delete copy.profile;
9214
- delete copy.profiles;
9215
- return copy;
9216
- }
9217
- function readProfileSelection(raw) {
9218
- if (!Object.hasOwn(raw, "profile"))
9219
- return { declared: false };
9220
- const value = raw.profile;
9221
- if (typeof value !== "string")
9222
- return { declared: true };
9223
- const name = value.trim();
9224
- return name.length > 0 ? { declared: true, name } : { declared: true };
9225
- }
9226
- function resolveConfigProfile(args) {
9227
- const warnings = [];
9228
- const userSelection = readProfileSelection(args.userRaw);
9229
- const projectSelection = readProfileSelection(args.projectRaw);
9230
- const selection = projectSelection.name ? { name: projectSelection.name, source: "project" } : userSelection.name ? { name: userSelection.name, source: "user" } : undefined;
9231
- if (projectSelection.declared && !projectSelection.name) {
9232
- warnings.push("Ignoring invalid profile selection from project config; expected a non-empty string.");
9233
- }
9234
- if (!projectSelection.declared && userSelection.declared && !userSelection.name) {
9235
- warnings.push("Ignoring invalid profile selection from user config; expected a non-empty string.");
9236
- }
9237
- let profiles = {};
9238
- if (Object.hasOwn(args.userRaw, "profiles")) {
9239
- const parsed = ConfigProfilesSchema.safeParse(args.userRaw.profiles);
9240
- if (parsed.success) {
9241
- profiles = parsed.data;
9242
- } else {
9243
- warnings.push("Ignoring profiles from user config: invalid profile configuration; profiles may contain only historian/dreamer harness model blocks.");
9244
- }
9245
- }
9246
- if (!selection) {
9247
- return {
9248
- userBase: withoutProfileFields(args.userRaw),
9249
- projectBase: withoutProfileFields(args.projectRaw),
9250
- overlay: {},
9251
- warnings
9252
- };
9253
- }
9254
- if (!Object.hasOwn(profiles, selection.name)) {
9255
- warnings.push(`Unknown profile "${selection.name}" selected by ${selection.source} config; using base config without a profile.`);
9256
- return {
9257
- userBase: withoutProfileFields(args.userRaw),
9258
- projectBase: withoutProfileFields(args.projectRaw),
9259
- overlay: {},
9260
- warnings
9261
- };
9262
- }
9263
- const overlay = profiles[selection.name];
9264
- return {
9265
- userBase: withoutProfileFields(args.userRaw),
9266
- projectBase: withoutProfileFields(args.projectRaw),
9267
- overlay,
9268
- activeProfile: selection.name,
9269
- warnings
9270
- };
9271
- }
9272
-
9273
- // src/config/project-security.ts
9274
- var HIDDEN_AGENT_KEYS = ["historian", "dreamer"];
9275
- var HARNESS_KEYS = PER_HARNESS_MODEL_KEYS;
9276
- var HISTORIAN_USER_ONLY_FIELDS = [
9277
- ...PER_HARNESS_MIGRATION_INVENTORY.historian.migrated_execution,
9278
- "runner",
9279
- "host_runner"
9280
- ];
9281
- var PROMPT_SURFACE_USER_ONLY_FIELDS = ["guidance_override_path", "tool_descriptions"];
9282
- var AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools"];
9283
- var EMBEDDING_USER_ONLY_FIELDS = [
9284
- "endpoint",
9285
- "provider",
9286
- "fallback_provider",
9287
- "query_instruction",
9288
- "document_prefix"
9289
- ];
9290
- var PERCENTAGE_THRESHOLD_REASON = "security: a repository may only raise compaction thresholds above the user's effective value; it cannot force earlier historian work or cloned-repo cost escalation.";
9291
- var TOKEN_THRESHOLD_REASON = "security: a repository may only raise execute_threshold_tokens above the user's trusted token threshold; it cannot force earlier historian work or cloned-repo cost escalation.";
9292
- var TOKEN_THRESHOLD_INTRODUCTION_REASON = "security: a repository cannot introduce a new execute_threshold_tokens override when the user has no trusted token threshold for that key; that could force earlier historian work or cloned-repo cost escalation.";
9293
- var PROTECTED_TOKENS_REASON = "security: a repository may only raise protected_tokens above the resolved user-or-derived floor; it cannot lower protection.";
9294
- function isPlainObject(value) {
9295
- return typeof value === "object" && value !== null && !Array.isArray(value);
9296
- }
9297
- function resolveProtectedTokensScalar(value) {
9298
- if (typeof value === "number" && Number.isInteger(value) && value >= 4000 && value <= 1e6) {
9299
- return value;
9300
- }
9301
- return;
9302
- }
9303
- var PROTECTED_TOKENS_TIER_OVERRIDES = Symbol.for("@cortexkit/magic-context/protected-tokens-tier-overrides");
9304
- function attachProtectedTokensTierOverrides(config, args) {
9305
- const user = resolveProtectedTokensScalar(args.trustedUser);
9306
- const rawProject = resolveProtectedTokensScalar(args.project);
9307
- const project = rawProject !== undefined && (user === undefined || rawProject >= user) ? rawProject : undefined;
9308
- if (user === undefined && project === undefined)
9309
- return config;
9310
- Object.defineProperty(config, PROTECTED_TOKENS_TIER_OVERRIDES, {
9311
- value: {
9312
- ...user !== undefined ? { user } : {},
9313
- ...project !== undefined ? { project } : {}
9314
- },
9315
- configurable: false,
9316
- enumerable: false,
9317
- writable: false
9318
- });
9319
- return config;
9320
- }
9321
- function getProtectedTokensTierOverrides(config) {
9322
- return config[PROTECTED_TOKENS_TIER_OVERRIDES];
9323
- }
9324
- function stripListedFields(target, fields, path, removed) {
9325
- for (const field of fields) {
9326
- if (field in target) {
9327
- delete target[field];
9328
- removed.push(path.length > 0 ? `${path}.${field}` : field);
9329
- }
9330
- }
9331
- }
9332
- function stripEscalationAtExecutableSite(block, path, removed) {
9333
- stripListedFields(block, AGENT_ESCALATION_FIELDS, path, removed);
9334
- if (isPlainObject(block.model)) {
9335
- stripListedFields(block.model, AGENT_ESCALATION_FIELDS, `${path}.model`, removed);
9336
- }
9337
- if (Array.isArray(block.fallback_models)) {
9338
- for (let index = 0;index < block.fallback_models.length; index++) {
9339
- const entry = block.fallback_models[index];
9340
- if (isPlainObject(entry)) {
9341
- stripListedFields(entry, AGENT_ESCALATION_FIELDS, `${path}.fallback_models.${index}`, removed);
9342
- }
9343
- }
9344
- }
9345
- }
9346
- function stripNestedMuralModels(node, path, removed) {
9347
- for (const [key, value] of Object.entries(node)) {
9348
- if (key === "mural" && isPlainObject(value) && "model" in value) {
9349
- delete value.model;
9350
- removed.push(`${path}.${key}.model`);
9351
- } else if (isPlainObject(value)) {
9352
- stripNestedMuralModels(value, `${path}.${key}`, removed);
9353
- }
9354
- }
9355
- }
9356
- function isValidPercentageThreshold(value) {
9357
- return typeof value === "number" && Number.isFinite(value) && value >= 20 && value <= 80;
9358
- }
9359
- function isValidTokenThreshold(value) {
9360
- return typeof value === "number" && Number.isFinite(value) && value >= 5000 && value <= 2000000;
9361
- }
9362
- function normalizeTrustedPercentageThresholds(value) {
9363
- if (typeof value === "number" && Number.isFinite(value)) {
9364
- return { defaultValue: value, overrides: new Map };
9365
- }
9366
- if (isPlainObject(value) && typeof value.default === "number" && Number.isFinite(value.default)) {
9367
- const overrides = new Map;
9368
- for (const [key, child] of Object.entries(value)) {
9369
- if (key === "default")
9370
- continue;
9371
- if (typeof child === "number" && Number.isFinite(child)) {
9372
- overrides.set(key, child);
9373
- }
9374
- }
9375
- return { defaultValue: value.default, overrides };
9376
- }
9377
- return { defaultValue: DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, overrides: new Map };
9378
- }
9379
- function normalizeTrustedTokenThresholds(value) {
9380
- if (!isPlainObject(value)) {
9381
- return { defaultValue: undefined, overrides: new Map };
9382
- }
9383
- const overrides = new Map;
9384
- for (const [key, child] of Object.entries(value)) {
9385
- if (key === "default")
9386
- continue;
9387
- if (typeof child === "number" && Number.isFinite(child)) {
9388
- overrides.set(key, child);
9389
- }
9390
- }
9391
- return {
9392
- defaultValue: typeof value.default === "number" && Number.isFinite(value.default) ? value.default : undefined,
9393
- overrides
9394
- };
9395
- }
9396
- function clonePercentageThresholds(value) {
9397
- return {
9398
- defaultValue: value.defaultValue,
9399
- overrides: new Map(value.overrides)
9400
- };
9401
- }
9402
- function cloneTokenThresholds(value) {
9403
- return {
9404
- defaultValue: value.defaultValue,
9405
- overrides: new Map(value.overrides)
9406
- };
9407
- }
9408
- function percentageThresholdsEqual(left, right) {
9409
- if (left.defaultValue !== right.defaultValue)
9410
- return false;
9411
- if (left.overrides.size !== right.overrides.size)
9412
- return false;
9413
- for (const [key, value] of left.overrides) {
9414
- if (right.overrides.get(key) !== value)
9415
- return false;
9416
- }
9417
- return true;
9418
- }
9419
- function setMergedPercentageThreshold(mergedRaw, value) {
9420
- if (value.overrides.size === 0) {
9421
- mergedRaw.execute_threshold_percentage = value.defaultValue;
9422
- return;
9423
- }
9424
- const serialized = { default: value.defaultValue };
9425
- for (const [key, threshold] of value.overrides) {
9426
- serialized[key] = threshold;
9427
- }
9428
- mergedRaw.execute_threshold_percentage = serialized;
9429
- }
9430
- function setMergedTokenThreshold(mergedRaw, value) {
9431
- if (value.defaultValue === undefined && value.overrides.size === 0) {
9432
- delete mergedRaw.execute_threshold_tokens;
9433
- return;
9434
- }
9435
- const serialized = {};
9436
- if (value.defaultValue !== undefined) {
9437
- serialized.default = value.defaultValue;
9438
- }
9439
- for (const [key, threshold] of value.overrides) {
9440
- serialized[key] = threshold;
9441
- }
9442
- mergedRaw.execute_threshold_tokens = serialized;
9443
- }
9444
- function makeProjectThresholdWarning(field, reason) {
9445
- return `Ignoring ${field} from project config (${reason})`;
9446
- }
9447
- function stripUnsafeProjectConfigFields(projectRaw) {
9448
- const warnings = [];
9449
- if ("profiles" in projectRaw) {
9450
- delete projectRaw.profiles;
9451
- warnings.push("Ignoring profiles from project config (security: profile definitions are user-level only; a repository may select a named user profile with profile).");
9452
- }
9453
- if ("auto_update" in projectRaw) {
9454
- delete projectRaw.auto_update;
9455
- warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
9456
- }
9457
- if ("fail_closed_blocking" in projectRaw) {
9458
- delete projectRaw.fail_closed_blocking;
9459
- warnings.push("Ignoring fail_closed_blocking from project config (security: only user-level config may disable or force the loud inoperability gate).");
9460
- }
9461
- if ("debug_rpc" in projectRaw) {
9462
- delete projectRaw.debug_rpc;
9463
- warnings.push("Ignoring debug_rpc from project config (security: only user-level config may enable process heap diagnostics).");
9464
- }
9465
- if ("allow_home_project" in projectRaw) {
9466
- delete projectRaw.allow_home_project;
9467
- warnings.push("Ignoring allow_home_project from project config (security: only user-level config may opt the user's home directory into Magic Context).");
9468
- }
9469
- const compaction = projectRaw.compaction;
9470
- if (isPlainObject(compaction) && "enabled" in compaction) {
9471
- delete compaction.enabled;
9472
- warnings.push("Ignoring compaction.enabled from project config (security: only user-level config may disable Magic Context's context-window management; a cloned repo cannot change how the user's window is owned).");
9473
- }
9474
- if ("output_reserve" in projectRaw) {
9475
- delete projectRaw.output_reserve;
9476
- warnings.push("Ignoring output_reserve from project config (security: output-token reservation only honors user-level config).");
9477
- }
9478
- const models = projectRaw.models;
9479
- if (isPlainObject(models) && "window_overlay_path" in models) {
9480
- delete models.window_overlay_path;
9481
- warnings.push("Ignoring models.window_overlay_path from project config (security: only user-level config may select model geometry metadata).");
9482
- }
9483
- if ("language" in projectRaw) {
9484
- delete projectRaw.language;
9485
- warnings.push("Ignoring language from project config (security: output language is a user-level setting).");
9486
- }
9487
- if ("sqlite" in projectRaw) {
9488
- delete projectRaw.sqlite;
9489
- warnings.push("Ignoring sqlite.* from project config (security: SQLite cache/mmap PRAGMAs apply to the " + "process-global shared database handle; only user-level config may set them).");
9490
- }
9491
- const storage = projectRaw.storage;
9492
- if (isPlainObject(storage) && "enforce_private_permissions" in storage) {
9493
- delete storage.enforce_private_permissions;
9494
- warnings.push("Ignoring storage.enforce_private_permissions from project config (security: only user-level config may opt into externally managed shared storage permissions).");
9495
- }
9496
- const promptSurface = projectRaw.prompt_surface;
9497
- if (isPlainObject(promptSurface)) {
9498
- const removed = [];
9499
- for (const field of PROMPT_SURFACE_USER_ONLY_FIELDS) {
9500
- if (field in promptSurface) {
9501
- delete promptSurface[field];
9502
- removed.push(field);
9503
- }
9504
- }
9505
- if (removed.length > 0) {
9506
- warnings.push(`Ignoring prompt_surface.${removed.join("/")} from project config (security: repositories may select prompt presets but only user config may provide guidance or tool-description text).`);
9507
- }
9508
- }
9509
- const pi = projectRaw.pi;
9510
- if (isPlainObject(pi) && "subagent_extensions" in pi) {
9511
- delete pi.subagent_extensions;
9512
- warnings.push("Ignoring pi.subagent_extensions from project config (security: only user-level config may choose extensions loaded by Pi subagent children).");
9513
- }
9514
- for (const field of ["subc", "shadow_embedding"]) {
9515
- if (field in projectRaw) {
9516
- delete projectRaw[field];
9517
- warnings.push(`Ignoring ${field} from project config (security: daemon routing and developer-only embedding traffic are user-level settings).`);
9518
- }
9519
- }
9520
- const embedding = projectRaw.embedding;
9521
- if (isPlainObject(embedding)) {
9522
- const removed = [];
9523
- for (const field of EMBEDDING_USER_ONLY_FIELDS) {
9524
- if (field in embedding) {
9525
- delete embedding[field];
9526
- removed.push(field);
9527
- }
9528
- }
9529
- if (removed.length > 0) {
9530
- warnings.push(`Ignoring embedding.${removed.join("/")} from project config ` + "(security: a repository cannot choose where or how private text is embedded).");
9531
- }
9532
- }
9533
- for (const agentKey of HIDDEN_AGENT_KEYS) {
9534
- const block = projectRaw[agentKey];
9535
- if (!isPlainObject(block))
9536
- continue;
9537
- const removed = [];
9538
- stripEscalationAtExecutableSite(block, agentKey, removed);
9539
- for (const harness of HARNESS_KEYS) {
9540
- const harnessBlock = block[harness];
9541
- if (!isPlainObject(harnessBlock))
9542
- continue;
9543
- stripEscalationAtExecutableSite(harnessBlock, `${agentKey}.${harness}`, removed);
9544
- const tasks = harnessBlock.tasks;
9545
- if (isPlainObject(tasks)) {
9546
- for (const [taskName, taskBlock] of Object.entries(tasks)) {
9547
- if (isPlainObject(taskBlock)) {
9548
- stripEscalationAtExecutableSite(taskBlock, `${agentKey}.${harness}.tasks.${taskName}`, removed);
9549
- }
9550
- }
9551
- }
9552
- }
9553
- const schedulingTasks = block.tasks;
9554
- if (isPlainObject(schedulingTasks)) {
9555
- for (const [taskName, taskBlock] of Object.entries(schedulingTasks)) {
9556
- if (isPlainObject(taskBlock)) {
9557
- stripListedFields(taskBlock, AGENT_ESCALATION_FIELDS, `${agentKey}.tasks.${taskName}`, removed);
9558
- }
9559
- }
9560
- }
9561
- if (removed.length > 0) {
9562
- warnings.push(`Ignoring ${removed.join(", ")} from project config ` + "(security: a repository cannot reprogram or re-permission hidden agents).");
9563
- }
9564
- }
9565
- const historian = projectRaw.historian;
9566
- if (isPlainObject(historian)) {
9567
- const removed = [];
9568
- for (const field of HISTORIAN_USER_ONLY_FIELDS) {
9569
- if (field in historian) {
9570
- delete historian[field];
9571
- removed.push(field);
9572
- }
9573
- }
9574
- for (const harness of HARNESS_KEYS) {
9575
- const harnessBlock = historian[harness];
9576
- if (!isPlainObject(harnessBlock))
9577
- continue;
9578
- for (const field of HISTORIAN_USER_ONLY_FIELDS) {
9579
- if (field in harnessBlock) {
9580
- delete harnessBlock[field];
9581
- removed.push(`${harness}.${field}`);
9582
- }
9583
- }
9584
- }
9585
- if (removed.length > 0) {
9586
- warnings.push(`Ignoring ${removed.map((path) => `historian.${path}`).join(", ")} from project config ` + "(security: historian model selection is user-level only; a repository cannot force extra compaction cost).");
9587
- }
9588
- }
9589
- const dreamer = projectRaw.dreamer;
9590
- if (isPlainObject(dreamer) && "runner" in dreamer) {
9591
- delete dreamer.runner;
9592
- warnings.push("Ignoring dreamer.runner from project config (security: which process and provider account run dreamer completions is a user-level setting).");
9593
- }
9594
- const mural = projectRaw.mural;
9595
- if (isPlainObject(mural) && "model" in mural) {
9596
- delete mural.model;
9597
- warnings.push("Ignoring mural.model from project config (security: the mural cue-compressor model is a user-level setting; a repository cannot choose where project memory is sent).");
9598
- }
9599
- const experimental = projectRaw.experimental;
9600
- const legacyMural = isPlainObject(experimental) ? experimental.mural : undefined;
9601
- if (isPlainObject(legacyMural) && "model" in legacyMural) {
9602
- delete legacyMural.model;
9603
- warnings.push("Ignoring experimental.mural.model from project config (security: the mural cue-compressor model is a user-level setting; use user-level mural.model).");
9604
- }
9605
- const nestedMuralRemoved = [];
9606
- for (const agentKey of HIDDEN_AGENT_KEYS) {
9607
- const block = projectRaw[agentKey];
9608
- if (!isPlainObject(block))
9609
- continue;
9610
- stripNestedMuralModels(block, agentKey, nestedMuralRemoved);
9611
- }
9612
- if (nestedMuralRemoved.length > 0) {
9613
- warnings.push(`Ignoring ${nestedMuralRemoved.join(", ")} from project config (security: the mural cue-compressor model is a user-level setting; a repository cannot choose where project memory is sent).`);
9614
- }
9615
- return warnings;
9616
- }
9617
- function constrainProjectThresholdOverrides(args) {
9618
- const warnings = [];
9619
- const basePercentage = normalizeTrustedPercentageThresholds(args.trustedBaseConfig.execute_threshold_percentage);
9620
- const baseTokens = normalizeTrustedTokenThresholds(args.trustedBaseConfig.execute_threshold_tokens);
9621
- if ("execute_threshold_percentage" in args.projectRaw) {
9622
- const projectValue = args.projectRaw.execute_threshold_percentage;
9623
- if (isValidPercentageThreshold(projectValue)) {
9624
- const constrained = clonePercentageThresholds(basePercentage);
9625
- constrained.defaultValue = Math.max(basePercentage.defaultValue, projectValue);
9626
- for (const [modelKey, threshold] of basePercentage.overrides) {
9627
- const raisedThreshold = Math.max(threshold, projectValue);
9628
- if (raisedThreshold === constrained.defaultValue) {
9629
- constrained.overrides.delete(modelKey);
9630
- } else {
9631
- constrained.overrides.set(modelKey, raisedThreshold);
9632
- }
9633
- }
9634
- setMergedPercentageThreshold(args.mergedRaw, constrained);
9635
- if (percentageThresholdsEqual(constrained, basePercentage)) {
9636
- warnings.push(makeProjectThresholdWarning("execute_threshold_percentage", PERCENTAGE_THRESHOLD_REASON));
9637
- }
9638
- } else if (isPlainObject(projectValue)) {
9639
- const constrained = clonePercentageThresholds(basePercentage);
9640
- let touchedValidEntry = false;
9641
- if (isValidPercentageThreshold(projectValue.default)) {
9642
- touchedValidEntry = true;
9643
- if (projectValue.default > basePercentage.defaultValue) {
9644
- constrained.defaultValue = projectValue.default;
9645
- } else {
9646
- warnings.push(makeProjectThresholdWarning("execute_threshold_percentage.default", PERCENTAGE_THRESHOLD_REASON));
9647
- }
9648
- }
9649
- for (const [modelKey, rawValue] of Object.entries(projectValue)) {
9650
- if (modelKey === "default")
9651
- continue;
9652
- if (!isValidPercentageThreshold(rawValue))
9653
- continue;
9654
- touchedValidEntry = true;
9655
- const baseValue = basePercentage.overrides.get(modelKey) ?? basePercentage.defaultValue;
9656
- if (rawValue > baseValue) {
9657
- if (rawValue === constrained.defaultValue) {
9658
- constrained.overrides.delete(modelKey);
9659
- } else {
9660
- constrained.overrides.set(modelKey, rawValue);
9661
- }
9662
- } else {
9663
- warnings.push(makeProjectThresholdWarning(`execute_threshold_percentage.${modelKey}`, PERCENTAGE_THRESHOLD_REASON));
9664
- }
9665
- }
9666
- if (touchedValidEntry) {
9667
- setMergedPercentageThreshold(args.mergedRaw, constrained);
9668
- }
9669
- }
9670
- }
9671
- if ("execute_threshold_tokens" in args.projectRaw && isPlainObject(args.projectRaw.execute_threshold_tokens)) {
9672
- const projectValue = args.projectRaw.execute_threshold_tokens;
9673
- const constrained = cloneTokenThresholds(baseTokens);
9674
- let touchedValidEntry = false;
9675
- if (isValidTokenThreshold(projectValue.default)) {
9676
- touchedValidEntry = true;
9677
- if (baseTokens.defaultValue === undefined) {
9678
- warnings.push(makeProjectThresholdWarning("execute_threshold_tokens.default", TOKEN_THRESHOLD_INTRODUCTION_REASON));
9679
- } else if (projectValue.default > baseTokens.defaultValue) {
9680
- constrained.defaultValue = projectValue.default;
9681
- } else {
9682
- warnings.push(makeProjectThresholdWarning("execute_threshold_tokens.default", TOKEN_THRESHOLD_REASON));
9683
- }
9684
- }
9685
- for (const [modelKey, rawValue] of Object.entries(projectValue)) {
9686
- if (modelKey === "default")
9687
- continue;
9688
- if (!isValidTokenThreshold(rawValue))
9689
- continue;
9690
- touchedValidEntry = true;
9691
- const baseValue = baseTokens.overrides.get(modelKey) ?? baseTokens.defaultValue;
9692
- if (baseValue === undefined) {
9693
- warnings.push(makeProjectThresholdWarning(`execute_threshold_tokens.${modelKey}`, TOKEN_THRESHOLD_INTRODUCTION_REASON));
9694
- continue;
9695
- }
9696
- if (rawValue > baseValue) {
9697
- if (rawValue === constrained.defaultValue) {
9698
- constrained.overrides.delete(modelKey);
9699
- } else {
9700
- constrained.overrides.set(modelKey, rawValue);
9701
- }
9702
- } else {
9703
- warnings.push(makeProjectThresholdWarning(`execute_threshold_tokens.${modelKey}`, TOKEN_THRESHOLD_REASON));
9704
- }
9705
- }
9706
- if (touchedValidEntry) {
9707
- setMergedTokenThreshold(args.mergedRaw, constrained);
9708
- }
9709
- }
9710
- if ("protected_tokens" in args.projectRaw) {
9711
- const rawProject = args.projectRaw.protected_tokens;
9712
- const projectVal = resolveProtectedTokensScalar(rawProject);
9713
- const trustedUserVal = resolveProtectedTokensScalar(args.trustedBaseConfig.protected_tokens);
9714
- if (projectVal !== undefined) {
9715
- if (trustedUserVal !== undefined) {
9716
- if (projectVal >= trustedUserVal) {
9717
- args.mergedRaw.protected_tokens = projectVal;
9718
- } else {
9719
- args.mergedRaw.protected_tokens = trustedUserVal;
9720
- warnings.push(makeProjectThresholdWarning("protected_tokens", PROTECTED_TOKENS_REASON));
9721
- }
9722
- } else {
9723
- args.mergedRaw.protected_tokens = projectVal;
9724
- }
9725
- } else {
9726
- if (trustedUserVal !== undefined) {
9727
- args.mergedRaw.protected_tokens = trustedUserVal;
9728
- } else {
9729
- delete args.mergedRaw.protected_tokens;
9730
- }
9731
- warnings.push(makeProjectThresholdWarning("protected_tokens", PROTECTED_TOKENS_REASON));
9732
- }
9733
- }
9734
- return warnings;
9735
- }
9736
- function normalizeEndpoint(value) {
9737
- if (typeof value !== "string")
9738
- return;
9739
- const trimmed = value.trim().replace(/\/+$/, "");
9740
- return trimmed.length > 0 ? trimmed.toLowerCase() : undefined;
9741
- }
9742
- function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
9743
- const projectEmbedding = projectRaw.embedding;
9744
- if (!isPlainObject(projectEmbedding))
9745
- return [];
9746
- const redirectsEndpoint = "endpoint" in projectEmbedding;
9747
- if (!redirectsEndpoint)
9748
- return [];
9749
- const userEmbedding = userRaw?.embedding;
9750
- if (isPlainObject(userEmbedding)) {
9751
- const projectEndpoint = normalizeEndpoint(projectEmbedding.endpoint);
9752
- const userEndpoint = normalizeEndpoint(userEmbedding.endpoint);
9753
- if (projectEndpoint !== undefined && projectEndpoint === userEndpoint) {
9754
- return [];
9755
- }
9756
- }
9757
- const providesOwnKey = typeof projectEmbedding.api_key === "string" && projectEmbedding.api_key.length > 0;
9758
- if (providesOwnKey)
9759
- return [];
9760
- const mergedEmbedding = mergedRaw.embedding;
9761
- if (!isPlainObject(mergedEmbedding))
9762
- return [];
9763
- if (!("api_key" in mergedEmbedding))
9764
- return [];
9765
- delete mergedEmbedding.api_key;
9766
- return [
9767
- "Dropped inherited user embedding api_key because project config redirected " + "embedding.endpoint without supplying its own key (security: prevents key " + "exfiltration to a repository-chosen endpoint)."
9768
- ];
9769
- }
9770
-
9771
- // src/config/prune-config-leaf.ts
9772
- function isPlainObject2(value) {
9773
- return typeof value === "object" && value !== null && !Array.isArray(value);
9774
- }
9775
- function pruneNestedConfigLeaf(block, relativePath) {
9776
- if (relativePath.length === 0)
9777
- return null;
9778
- const result = { ...block };
9779
- let cursor = result;
9780
- for (let i = 0;i < relativePath.length - 1; i++) {
9781
- const seg = String(relativePath[i]);
9782
- const child = cursor[seg];
9783
- if (!isPlainObject2(child)) {
9784
- if (!(seg in cursor))
9785
- return null;
9786
- delete cursor[seg];
9787
- return {
9788
- block: result,
9789
- removed: relativePath.slice(0, i + 1).map(String).join(".")
9790
- };
9791
- }
9792
- const clonedChild = { ...child };
9793
- cursor[seg] = clonedChild;
9794
- cursor = clonedChild;
9795
- }
9796
- const leaf = String(relativePath[relativePath.length - 1]);
9797
- if (!(leaf in cursor))
9798
- return null;
9799
- delete cursor[leaf];
9800
- return { block: result, removed: relativePath.map(String).join(".") };
9801
- }
9802
-
9803
- // src/config/raw-loader.ts
9804
- import {
9805
- closeSync,
9806
- existsSync,
9807
- linkSync,
9808
- openSync,
9809
- readFileSync,
9810
- renameSync,
9811
- statSync,
9812
- unlinkSync,
9813
- writeFileSync
9814
- } from "node:fs";
9815
- import { basename, dirname, join } from "node:path";
9816
- var MODEL_FIELDS = ["model", "fallback_models"];
9817
- var QUALIFIER_FIELDS = ["variant", "thinking_level"];
9818
- var TASK_MODEL_FIELDS = [...MODEL_FIELDS, ...QUALIFIER_FIELDS, "timeout_minutes"];
9819
- var PRE_PER_HARNESS_BACKUP_SUFFIX = ".pre-per-harness.bak";
9820
- var temporaryFileSequence = 0;
9821
- function isRecord2(value) {
9822
- return typeof value === "object" && value !== null && !Array.isArray(value);
9823
- }
9824
- function asDocument(text) {
9825
- try {
9826
- const document = parseJsonc(text.startsWith("\uFEFF") ? text.slice(1) : text);
9827
- return isRecord2(document) ? document : null;
9828
- } catch {
9829
- return null;
9830
- }
9831
- }
9832
- function getAtPath(document, path) {
9833
- let current = document;
9834
- for (const part of path) {
9835
- if (!isRecord2(current) || !Object.hasOwn(current, part))
9836
- return;
9837
- current = current[part];
9838
- }
9839
- return current;
9840
- }
9841
- function stableJson(value) {
9842
- if (Array.isArray(value))
9843
- return `[${value.map(stableJson).join(",")}]`;
9844
- if (!isRecord2(value))
9845
- return JSON.stringify(value);
9846
- return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableJson(value[key])}`).join(",")}}`;
9847
- }
9848
- function valuesMatch(left, right) {
9849
- return stableJson(left) === stableJson(right);
9850
- }
9851
- function valueForDiagnostic(value) {
9852
- return stableJson(value);
9853
- }
9854
- function migrateEntryForHarness(value, harness) {
9855
- if (Array.isArray(value))
9856
- return value.map((entry) => migrateEntryForHarness(entry, harness));
9857
- if (!isRecord2(value) || !Object.hasOwn(value, "model"))
9858
- return value;
9859
- const entry = { model: value.model };
9860
- if (harness === "opencode" && Object.hasOwn(value, "variant")) {
9861
- entry.variant = value.variant;
9862
- }
9863
- if (harness === "pi" && Object.hasOwn(value, "thinking_level")) {
9864
- entry.thinking_level = value.thinking_level;
9865
- }
9866
- return entry;
9867
- }
9868
- function migrateFallbackForHarness(value, harness) {
9869
- if (typeof value === "string")
9870
- return [value];
9871
- return migrateEntryForHarness(value, harness);
9872
- }
9873
- function canCreateAtPath(document, path) {
9874
- let current = document;
9875
- for (const part of path) {
9876
- if (current === undefined)
9877
- return true;
9878
- if (!isRecord2(current))
9879
- return false;
9880
- current = current[part];
9881
- }
9882
- return current === undefined || isRecord2(current);
9883
- }
9884
- function flatFieldPath(parts) {
9885
- return parts.join(".");
9886
- }
9887
- function updateDocumentForFlatFields(text) {
9888
- const hasBom = text.startsWith("\uFEFF");
9889
- const editableText = hasBom ? text.slice(1) : text;
9890
- const document = asDocument(text);
9891
- if (!document) {
9892
- return { text, hasFlatKeys: false, diagnostics: [], flatPaths: [] };
9893
- }
9894
- let nextText = editableText;
9895
- let hasFlatKeys = false;
9896
- const diagnostics = [];
9897
- const flatPaths = [];
9898
- const sourcePathsToRemove = [];
9899
- const addDestination = (sourcePath, destinationPath, destinationValue) => {
9900
- const sourceLabel = flatFieldPath(sourcePath);
9901
- const destinationLabel = flatFieldPath(destinationPath);
9902
- if (!canCreateAtPath(document, destinationPath.slice(0, -1))) {
9903
- diagnostics.push({
9904
- path: sourceLabel,
9905
- message: `Flat config field "${sourceLabel}" (${valueForDiagnostic(destinationValue)}) conflicts with non-object destination "${destinationLabel}" (${valueForDiagnostic(getAtPath(document, destinationPath.slice(0, -1)))}); kept the destination and ignored the flat field.`
9906
- });
9907
- return;
9908
- }
9909
- const existing = getAtPath(document, destinationPath);
9910
- if (existing !== undefined) {
9911
- if (!valuesMatch(existing, destinationValue)) {
9912
- diagnostics.push({
9913
- path: sourceLabel,
9914
- message: `Flat config field "${sourceLabel}" (${valueForDiagnostic(destinationValue)}) conflicts with "${destinationLabel}" (${valueForDiagnostic(existing)}); kept "${destinationLabel}" and ignored the flat field.`
9915
- });
9916
- }
9917
- return;
9918
- }
9919
- nextText = setJsoncValue(nextText, destinationPath, destinationValue);
9920
- };
9921
- const migrateAgentFields = (agentName) => {
9922
- const agent = document[agentName];
9923
- if (!isRecord2(agent))
9924
- return;
9925
- for (const field of MODEL_FIELDS) {
9926
- if (!Object.hasOwn(agent, field))
9927
- continue;
9928
- const sourcePath = [agentName, field];
9929
- hasFlatKeys = true;
9930
- flatPaths.push(flatFieldPath(sourcePath));
9931
- sourcePathsToRemove.push(sourcePath);
9932
- const migrateValue = field === "fallback_models" ? migrateFallbackForHarness : migrateEntryForHarness;
9933
- addDestination(sourcePath, [agentName, "opencode", field], migrateValue(agent[field], "opencode"));
9934
- addDestination(sourcePath, [agentName, "pi", field], migrateValue(agent[field], "pi"));
9935
- }
9936
- if (Object.hasOwn(agent, "variant")) {
9937
- const sourcePath = [agentName, "variant"];
9938
- hasFlatKeys = true;
9939
- flatPaths.push(flatFieldPath(sourcePath));
9940
- sourcePathsToRemove.push(sourcePath);
9941
- addDestination(sourcePath, [agentName, "opencode", "variant"], agent.variant);
9942
- }
9943
- if (Object.hasOwn(agent, "thinking_level")) {
9944
- const sourcePath = [agentName, "thinking_level"];
9945
- hasFlatKeys = true;
9946
- flatPaths.push(flatFieldPath(sourcePath));
9947
- sourcePathsToRemove.push(sourcePath);
9948
- addDestination(sourcePath, [agentName, "pi", "thinking_level"], agent.thinking_level);
9949
- }
9950
- };
9951
- migrateAgentFields("historian");
9952
- migrateAgentFields("dreamer");
9953
- const dreamer = document.dreamer;
9954
- const tasks = isRecord2(dreamer) ? dreamer.tasks : undefined;
9955
- if (isRecord2(tasks)) {
9956
- for (const taskName of Object.keys(tasks).sort()) {
9957
- const task = tasks[taskName];
9958
- if (!isRecord2(task))
9959
- continue;
9960
- for (const field of TASK_MODEL_FIELDS) {
9961
- if (!Object.hasOwn(task, field))
9962
- continue;
9963
- const sourcePath = ["dreamer", "tasks", taskName, field];
9964
- hasFlatKeys = true;
9965
- flatPaths.push(flatFieldPath(sourcePath));
9966
- sourcePathsToRemove.push(sourcePath);
9967
- if (field === "model" || field === "fallback_models") {
9968
- addDestination(sourcePath, ["dreamer", "opencode", "tasks", taskName, field], field === "fallback_models" ? migrateFallbackForHarness(task[field], "opencode") : migrateEntryForHarness(task[field], "opencode"));
9969
- addDestination(sourcePath, ["dreamer", "pi", "tasks", taskName, field], field === "fallback_models" ? migrateFallbackForHarness(task[field], "pi") : migrateEntryForHarness(task[field], "pi"));
9970
- } else if (field === "variant") {
9971
- addDestination(sourcePath, ["dreamer", "opencode", "tasks", taskName, field], task[field]);
9972
- } else if (field === "thinking_level") {
9973
- addDestination(sourcePath, ["dreamer", "pi", "tasks", taskName, field], task[field]);
9974
- } else {
9975
- addDestination(sourcePath, ["dreamer", "opencode", "tasks", taskName, field], task[field]);
9976
- addDestination(sourcePath, ["dreamer", "pi", "tasks", taskName, field], task[field]);
9977
- }
9978
- }
9979
- }
9980
- }
9981
- for (const sourcePath of sourcePathsToRemove) {
9982
- nextText = removeJsoncValue(nextText, sourcePath);
9983
- }
9984
- return {
9985
- text: hasBom ? `\uFEFF${nextText}` : nextText,
9986
- hasFlatKeys,
9987
- diagnostics,
9988
- flatPaths
9989
- };
9990
- }
9991
- function hasFlatKeys(input) {
9992
- const text = typeof input === "string" ? input : input.toString("utf-8");
9993
- return updateDocumentForFlatFields(text).hasFlatKeys;
9994
- }
9995
- function migrateFlatDetailed(input) {
9996
- const bytes = typeof input === "string" ? Buffer.from(input, "utf-8") : input;
9997
- const result = updateDocumentForFlatFields(bytes.toString("utf-8"));
9998
- return {
9999
- bytes: Buffer.from(result.text, "utf-8"),
10000
- hasFlatKeys: result.hasFlatKeys,
10001
- diagnostics: result.diagnostics
10002
- };
10003
- }
10004
- function writeExclusiveBackup(backupPath, bytes, mode) {
10005
- const temporaryPath = writeTemporaryCandidate(backupPath, bytes, mode);
10006
- try {
10007
- try {
10008
- linkSync(temporaryPath, backupPath);
10009
- return;
10010
- } catch (error) {
10011
- if (error.code !== "EEXIST")
10012
- throw error;
10013
- }
10014
- const existingBytes = readFileSync(backupPath);
10015
- if (existingBytes.equals(bytes))
10016
- return;
10017
- if (bytes.subarray(0, existingBytes.length).equals(existingBytes)) {
10018
- renameSync(temporaryPath, backupPath);
10019
- return;
10020
- }
10021
- } finally {
10022
- try {
10023
- unlinkSync(temporaryPath);
10024
- } catch {}
10025
- }
10026
- }
10027
- function writeTemporaryCandidate(configPath, bytes, mode) {
10028
- const directory = dirname(configPath);
10029
- const stem = basename(configPath);
10030
- for (let attempt = 0;attempt < 32; attempt++) {
10031
- temporaryFileSequence += 1;
10032
- const path = join(directory, `.${stem}.per-harness-${process.pid}-${temporaryFileSequence}.tmp`);
10033
- let descriptor;
10034
- try {
10035
- descriptor = openSync(path, "wx", mode);
10036
- writeFileSync(descriptor, bytes);
10037
- closeSync(descriptor);
10038
- return path;
10039
- } catch (error) {
10040
- if (descriptor !== undefined) {
10041
- try {
10042
- closeSync(descriptor);
10043
- } catch {}
10044
- }
10045
- try {
10046
- unlinkSync(path);
10047
- } catch {}
10048
- if (error.code !== "EEXIST")
10049
- throw error;
10050
- }
10051
- }
10052
- throw new Error(`Could not allocate a temporary config file beside ${configPath}`);
10053
- }
10054
- function migrationWarning(diagnostic) {
10055
- return diagnostic.message;
10056
- }
10057
- function loadRawConfigFile(options) {
10058
- if (!existsSync(options.configPath))
10059
- return null;
10060
- let observedBytes;
10061
- try {
10062
- observedBytes = readFileSync(options.configPath);
10063
- } catch (error) {
10064
- throw new Error(`failed to read config: ${error instanceof Error ? error.message : String(error)}`);
10065
- }
10066
- const initialMigration = migrateFlatDetailed(observedBytes);
10067
- if (!initialMigration.hasFlatKeys) {
10068
- return {
10069
- configPath: options.configPath,
10070
- bytes: observedBytes,
10071
- text: observedBytes.toString("utf-8"),
10072
- warnings: [],
10073
- migrated: false
10074
- };
10075
- }
10076
- if (options.tier === "project") {
10077
- return {
10078
- configPath: options.configPath,
10079
- bytes: initialMigration.bytes,
10080
- text: initialMigration.bytes.toString("utf-8"),
10081
- warnings: [
10082
- "Adapted flat model config in memory; use historian.opencode/historian.pi and dreamer.opencode/dreamer.pi instead. Project config files are never rewritten.",
10083
- ...initialMigration.diagnostics.map(migrationWarning)
10084
- ],
10085
- migrated: false
10086
- };
10087
- }
10088
- const backupPath = `${options.configPath}${PRE_PER_HARNESS_BACKUP_SUFFIX}`;
10089
- for (;; ) {
10090
- const migration = migrateFlatDetailed(observedBytes);
10091
- if (!migration.hasFlatKeys) {
10092
- return {
10093
- configPath: options.configPath,
10094
- bytes: observedBytes,
10095
- text: observedBytes.toString("utf-8"),
10096
- warnings: [],
10097
- migrated: false
10098
- };
10099
- }
10100
- let temporaryPath;
10101
- try {
10102
- const mode = statSync(options.configPath).mode & 511;
10103
- writeExclusiveBackup(backupPath, observedBytes, mode);
10104
- temporaryPath = writeTemporaryCandidate(options.configPath, migration.bytes, mode);
10105
- options.afterTemporaryWrite?.();
10106
- const currentBytes = readFileSync(options.configPath);
10107
- if (!hasFlatKeys(currentBytes)) {
10108
- unlinkSync(temporaryPath);
10109
- return {
10110
- configPath: options.configPath,
10111
- bytes: currentBytes,
10112
- text: currentBytes.toString("utf-8"),
10113
- warnings: [],
10114
- migrated: false
10115
- };
10116
- }
10117
- if (!currentBytes.equals(observedBytes)) {
10118
- unlinkSync(temporaryPath);
10119
- observedBytes = currentBytes;
10120
- continue;
10121
- }
10122
- renameSync(temporaryPath, options.configPath);
10123
- return {
10124
- configPath: options.configPath,
10125
- bytes: migration.bytes,
10126
- text: migration.bytes.toString("utf-8"),
10127
- warnings: [
10128
- "Migrated flat historian/dreamer model config to per-harness blocks.",
10129
- ...migration.diagnostics.map(migrationWarning)
10130
- ],
10131
- migrated: true
10132
- };
10133
- } catch (error) {
10134
- if (temporaryPath) {
10135
- try {
10136
- unlinkSync(temporaryPath);
10137
- } catch {}
10138
- }
10139
- return {
10140
- configPath: options.configPath,
10141
- bytes: observedBytes,
10142
- text: observedBytes.toString("utf-8"),
10143
- warnings: [
10144
- `Could not migrate flat model config: ${error instanceof Error ? error.message : String(error)}. Flat fields were not applied.`,
10145
- ...migration.diagnostics.map(migrationWarning)
10146
- ],
10147
- migrated: false
10148
- };
10149
- }
10150
- }
10151
- }
10152
-
10153
- // src/config/removed-agent-config.ts
10154
- var REMOVED_AGENT_CONFIG_KEY = "sidekick";
10155
- var REMOVED_AGENT_CONFIG_WARNING = `The "${REMOVED_AGENT_CONFIG_KEY}" configuration was removed and is ignored.`;
10156
- function isPlainObject3(value) {
10157
- return typeof value === "object" && value !== null && !Array.isArray(value);
10158
- }
10159
- function stripRemovedAgentConfig(rawConfig, warnings) {
10160
- let removed = false;
10161
- const patched = { ...rawConfig };
10162
- if (Object.hasOwn(patched, REMOVED_AGENT_CONFIG_KEY)) {
10163
- delete patched[REMOVED_AGENT_CONFIG_KEY];
10164
- removed = true;
10165
- }
10166
- if (isPlainObject3(patched.profiles)) {
10167
- const profiles = { ...patched.profiles };
10168
- let profilesChanged = false;
10169
- for (const [name, value] of Object.entries(profiles)) {
10170
- if (!isPlainObject3(value) || !Object.hasOwn(value, REMOVED_AGENT_CONFIG_KEY))
10171
- continue;
10172
- const profile = { ...value };
10173
- delete profile[REMOVED_AGENT_CONFIG_KEY];
10174
- profiles[name] = profile;
10175
- profilesChanged = true;
10176
- removed = true;
10177
- }
10178
- if (profilesChanged)
10179
- patched.profiles = profiles;
10180
- }
10181
- if (removed && !warnings.includes(REMOVED_AGENT_CONFIG_WARNING)) {
10182
- warnings.push(REMOVED_AGENT_CONFIG_WARNING);
10183
- }
10184
- return removed ? patched : rawConfig;
10185
- }
10186
-
10187
- // src/config/transform-mode.ts
10188
- var RUST_COMPACTION_OFF_WARNING = "compaction-off mode does not support rust transform mode; using the TypeScript transform.";
10189
- var RUST_REQUIRES_USER_SUBC_WARNING = "rust mode requires user-level subc configuration; running ts.";
10190
- function resolveTransformMode(args) {
10191
- if (args.configured === "rust" && !args.compactionEnabled) {
10192
- return {
10193
- mode: "ts",
10194
- warnings: [RUST_COMPACTION_OFF_WARNING]
10195
- };
10196
- }
10197
- if (args.configured === "rust" && !args.userTierHasSubc) {
10198
- return {
10199
- mode: "ts",
10200
- warnings: [RUST_REQUIRES_USER_SUBC_WARNING]
10201
- };
10202
- }
10203
- return { mode: args.configured, warnings: [] };
10204
- }
10205
-
10206
- // src/config/variable.ts
10207
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
10208
- import { homedir } from "node:os";
10209
- import { dirname as dirname2, isAbsolute, resolve } from "node:path";
10210
- var ENV_PATTERN = /\{env:([^}]+)\}/g;
10211
- var FILE_PATTERN = /\{file:([^}]+)\}/g;
10212
- function sensitiveFilePathReason(resolvedPath) {
10213
- const home = homedir();
10214
- const sensitiveDirs = [
10215
- { dir: resolve(home, ".ssh"), label: "SSH keys" },
10216
- { dir: resolve(home, ".aws"), label: "AWS credentials" },
10217
- { dir: resolve(home, ".gnupg"), label: "GnuPG keyring" },
10218
- { dir: resolve(home, ".config", "gh"), label: "GitHub CLI auth" }
10219
- ];
10220
- for (const { dir, label } of sensitiveDirs) {
10221
- if (resolvedPath === dir || resolvedPath.startsWith(`${dir}/`)) {
10222
- return label;
10223
- }
10224
- }
10225
- return null;
10226
- }
10227
- function substituteConfigVariables(input) {
10228
- const warnings = [];
10229
- let text = input.text;
10230
- if (input.isProjectConfig) {
10231
- const hasEnvTokens = ENV_PATTERN.test(text);
10232
- const hasFileTokens = FILE_PATTERN.test(text);
10233
- ENV_PATTERN.lastIndex = 0;
10234
- FILE_PATTERN.lastIndex = 0;
10235
- if (hasEnvTokens || hasFileTokens) {
10236
- const tokenTypes = [
10237
- hasEnvTokens ? "{env:}" : undefined,
10238
- hasFileTokens ? "{file:}" : undefined
10239
- ].filter(Boolean).join(" and ");
10240
- warnings.push(`Project-level config no longer supports ${tokenTypes} tokens for security reasons; leaving tokens literal. Move secret expansion to user-level config.`);
10241
- }
10242
- return { text, warnings };
10243
- }
10244
- text = stripJsonComments(text);
10245
- text = text.replace(ENV_PATTERN, (_, rawName) => {
10246
- const varName = rawName.trim();
10247
- const value = varName ? process.env[varName] : undefined;
10248
- if (value === undefined || value === "") {
10249
- warnings.push(`Environment variable ${varName} is not set (referenced via {env:${varName}}); using empty string`);
10250
- return "";
10251
- }
10252
- return JSON.stringify(value).slice(1, -1);
10253
- });
10254
- const fileMatches = Array.from(text.matchAll(FILE_PATTERN));
10255
- if (fileMatches.length === 0) {
10256
- return { text, warnings };
10257
- }
10258
- const configDir = input.configPath ? dirname2(input.configPath) : process.cwd();
10259
- let output = "";
10260
- let cursor = 0;
10261
- for (const match of fileMatches) {
10262
- const token = match[0];
10263
- const rawPath = match[1] ?? "";
10264
- const index = match.index ?? 0;
10265
- output += text.slice(cursor, index);
10266
- cursor = index + token.length;
10267
- const lineStart = text.lastIndexOf(`
10268
- `, index - 1) + 1;
10269
- const prefix = text.slice(lineStart, index).trimStart();
10270
- if (prefix.startsWith("//")) {
10271
- output += token;
10272
- continue;
10273
- }
10274
- let filePath = rawPath.trim();
10275
- if (filePath.startsWith("~/")) {
10276
- filePath = resolve(homedir(), filePath.slice(2));
10277
- } else if (!isAbsolute(filePath)) {
10278
- filePath = resolve(configDir, filePath);
10279
- }
10280
- const sensitiveReason = sensitiveFilePathReason(filePath);
10281
- if (sensitiveReason) {
10282
- warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
10283
- }
10284
- if (!existsSync2(filePath)) {
10285
- warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
10286
- continue;
10287
- }
10288
- let contents;
10289
- try {
10290
- contents = readFileSync2(filePath, "utf-8").trim();
10291
- } catch (error) {
10292
- const message = error instanceof Error ? error.message : String(error);
10293
- warnings.push(`Failed to read file for ${token} (${filePath}): ${message}; using empty string`);
10294
- continue;
10295
- }
10296
- output += JSON.stringify(contents).slice(1, -1);
10297
- }
10298
- output += text.slice(cursor);
10299
- return { text: output, warnings };
10300
- }
10301
-
10302
- // src/config/index.ts
10303
- function getUserConfigBasePath() {
10304
- return cortexKitUserConfigBasePath();
10305
- }
10306
- function getProjectConfigBasePath(directory) {
10307
- return cortexKitProjectConfigBasePath(directory);
10308
- }
10309
- function resolveLegacyReadFallback(sources) {
10310
- return { source: sources.find((s) => existsSync3(s.path)) ?? null };
10311
- }
10312
- function loadConfigFileDetailed(configPath, source) {
10313
- if (!existsSync3(configPath)) {
10314
- return null;
10315
- }
10316
- let rawText;
10317
- let rawWarnings;
10318
- try {
10319
- const raw = loadRawConfigFile({ configPath, tier: source });
10320
- if (!raw)
10321
- return null;
10322
- rawText = raw.text;
10323
- rawWarnings = raw.warnings;
10324
- } catch (error) {
10325
- const message = `failed to read config: ${error instanceof Error ? error.message : String(error)}`;
10326
- return {
10327
- config: {},
10328
- warnings: [`${configPath}: ${message}`],
10329
- parseFailures: [],
10330
- warningDetails: [
10331
- { warningClass: CONFIG_WARNING_CLASS.FILE_IO, source, path: configPath, message }
10332
- ],
10333
- outcome: "project-file-io-error",
10334
- source
10335
- };
10336
- }
10337
- try {
10338
- const substituted = substituteConfigVariables({
10339
- text: rawText,
10340
- configPath,
10341
- isProjectConfig: source === "project"
10342
- });
10343
- const rejectedKeyPaths = [];
10344
- const parsed = parseJsoncRecovering(substituted.text, {
10345
- onRejectedKey: (path) => rejectedKeyPaths.push(path.join("."))
10346
- });
10347
- const config = parsed.value && typeof parsed.value === "object" && !Array.isArray(parsed.value) ? parsed.value : {};
10348
- const unsafeKeyWarnings = rejectedKeyPaths.map((path) => `Ignored unsafe config key "${path}" (security: prototype-pollution keys are not allowed).`);
10349
- const firstIssue = parsed.issues[0];
10350
- const recovered = firstIssue !== undefined && Object.keys(config).length > 0;
10351
- const parseFailures = firstIssue ? [
10352
- {
10353
- warningClass: CONFIG_WARNING_CLASS.FILE_PARSE,
10354
- source,
10355
- path: configPath,
10356
- line: firstIssue.line,
10357
- column: firstIssue.column,
10358
- message: firstIssue.message,
10359
- recovered,
10360
- warning: `${configPath}:${firstIssue.line}:${firstIssue.column}: ${firstIssue.message}; ${recovered ? "recovered values were applied, but the file must be fixed." : "using defaults for this file."}`
10361
- }
10362
- ] : [];
10363
- return {
10364
- config,
10365
- warnings: [
10366
- ...parseFailures.map((failure) => failure.warning),
10367
- ...rawWarnings.map((warning) => `${configPath}: ${warning}`),
10368
- ...substituted.warnings.map((warning) => `${configPath}: ${warning}`),
10369
- ...unsafeKeyWarnings.map((warning) => `${configPath}: ${warning}`)
10370
- ],
10371
- parseFailures,
10372
- warningDetails: parseFailures,
10373
- outcome: parseFailures.length > 0 ? "project-file-parse-error" : rejectedKeyPaths.length > 0 ? "schema-recovery" : substituted.warnings.length > 0 ? "substitution-failure" : "ok",
10374
- source
10375
- };
10376
- } catch (error) {
10377
- const message = error instanceof Error ? error.message : String(error);
10378
- const warning = `${configPath}:1:1: ${message}; using defaults for this file.`;
10379
- const failure = {
10380
- warningClass: CONFIG_WARNING_CLASS.FILE_PARSE,
10381
- source,
10382
- path: configPath,
10383
- line: 1,
10384
- column: 1,
10385
- message,
10386
- recovered: false,
10387
- warning
10388
- };
10389
- return {
10390
- config: {},
10391
- warnings: [warning],
10392
- parseFailures: [failure],
10393
- warningDetails: [failure],
10394
- outcome: "project-file-parse-error",
10395
- source
10396
- };
10397
- }
10398
- }
10399
- function defineOwnConfigValue(target, key, value) {
10400
- Object.defineProperty(target, key, {
10401
- value,
10402
- enumerable: true,
10403
- configurable: true,
10404
- writable: true
10405
- });
10406
- }
10407
- function deepMergeRawConfig(base, override) {
10408
- const result = {};
10409
- for (const key of Object.keys(base)) {
10410
- if (isPrototypePollutionKey(key))
10411
- continue;
10412
- defineOwnConfigValue(result, key, base[key]);
10413
- }
10414
- for (const key of Object.keys(override)) {
10415
- if (isPrototypePollutionKey(key))
10416
- continue;
10417
- const baseVal = Object.hasOwn(base, key) ? base[key] : undefined;
10418
- const overrideVal = override[key];
10419
- let mergedValue;
10420
- if (baseVal !== null && typeof baseVal === "object" && !Array.isArray(baseVal) && overrideVal !== null && typeof overrideVal === "object" && !Array.isArray(overrideVal)) {
10421
- mergedValue = deepMergeRawConfig(baseVal, overrideVal);
10422
- } else if (key === "disabled_hooks" && Array.isArray(baseVal) && Array.isArray(overrideVal)) {
10423
- mergedValue = [...new Set([...baseVal, ...overrideVal])];
10424
- } else {
10425
- mergedValue = overrideVal;
10426
- }
10427
- defineOwnConfigValue(result, key, mergedValue);
10428
- }
10429
- return result;
10430
- }
10431
- function redactConfigValue(value) {
10432
- if (value === undefined)
10433
- return "<missing>";
10434
- if (value === null)
10435
- return "null";
10436
- if (typeof value === "string")
10437
- return `string, ${value.length} char${value.length === 1 ? "" : "s"}`;
10438
- if (typeof value === "number")
10439
- return `number ${value}`;
10440
- if (typeof value === "boolean")
10441
- return `boolean ${value}`;
10442
- if (Array.isArray(value))
10443
- return `array, ${value.length} item${value.length === 1 ? "" : "s"}`;
10444
- if (typeof value === "object") {
10445
- const keys = Object.keys(value);
10446
- return `object with keys [${keys.join(", ")}]`;
10447
- }
10448
- return typeof value;
10449
- }
10450
- var warnedProtectedTagsDeprecation = false;
10451
- function formatProtectedTokensBelowMinWarning(value) {
10452
- return `protected_tokens is a token floor (minimum ${PROTECTED_TOKENS_MIN}, default derived from the context window); ${value} looks like the old protected_tags count. Remove the key to use the default, or set a token count such as 16000.`;
10453
- }
10454
- var MODEL_HARNESS_BLOCKS = ["opencode", "pi", "omp"];
10455
- function misplacedAgentModelWarnings(rawConfig) {
10456
- const warnings = [];
10457
- for (const agent of ["historian", "dreamer"]) {
10458
- const block = rawConfig[agent];
10459
- if (!block || typeof block !== "object" || Array.isArray(block))
10460
- continue;
10461
- const record = block;
10462
- if (!Object.hasOwn(record, "model"))
10463
- continue;
10464
- const harnessWithModel = MODEL_HARNESS_BLOCKS.find((harness) => {
10465
- const sub = record[harness];
10466
- return sub !== null && typeof sub === "object" && !Array.isArray(sub) && Object.hasOwn(sub, "model");
10467
- });
10468
- if (harnessWithModel)
10469
- continue;
10470
- warnings.push(`${agent}.model is not read: the ${agent} model is resolved per harness, so it has to be ${agent}.opencode.model (OpenCode 1 and 2), ${agent}.pi.model, or ${agent}.omp.model. As written the ${agent} resolves to no models and never runs.`);
10471
- }
10472
- return warnings;
10473
- }
10474
- function warnProtectedTagsDeprecationOnce() {
10475
- if (!warnedProtectedTagsDeprecation) {
10476
- warnedProtectedTagsDeprecation = true;
10477
- console.warn("[magic-context] protected_tags is deprecated and ignored; use protected_tokens instead.");
10478
- }
10479
- }
10480
- function parsePluginConfig(rawConfig, recoveredTopLevelKeys = []) {
10481
- const preMigrationWarnings = [];
10482
- const configWithoutRemovedAgent = stripRemovedAgentConfig(rawConfig, preMigrationWarnings);
10483
- if (Object.hasOwn(rawConfig, "protected_tags")) {
10484
- warnProtectedTagsDeprecationOnce();
10485
- preMigrationWarnings.push("protected_tags is deprecated and ignored; use protected_tokens instead.");
10486
- }
10487
- preMigrationWarnings.push(...misplacedAgentModelWarnings(rawConfig));
10488
- const migratedExperimental = migrateLegacyExperimental(configWithoutRemovedAgent, preMigrationWarnings);
10489
- const migratedDreamer = migrateDreamerV2(migratedExperimental, preMigrationWarnings);
10490
- const migrated = migrateLegacyAgentEnabledInMemory(migratedDreamer, preMigrationWarnings);
10491
- const parsed = MagicContextConfigSchema.safeParse(migrated);
10492
- const disabledHooks = Array.isArray(rawConfig.disabled_hooks) ? rawConfig.disabled_hooks.filter((value) => typeof value === "string") : undefined;
10493
- const command = typeof rawConfig.command === "object" && rawConfig.command !== null ? rawConfig.command : undefined;
10494
- if (parsed.success) {
10495
- return {
10496
- ...parsed.data,
10497
- disabled_hooks: disabledHooks,
10498
- command,
10499
- ...preMigrationWarnings.length > 0 ? { configWarnings: preMigrationWarnings } : {}
10500
- };
10501
- }
10502
- const defaults = MagicContextConfigSchema.parse({});
10503
- const warnings = [];
10504
- const errorPaths = new Set;
10505
- const customMessagesByKey = new Map;
10506
- const issuePathsByKey = new Map;
10507
- const GENERIC_ZOD_PREFIXES = ["Too big", "Too small", "Invalid input", "Invalid", "Expected"];
10508
- for (const issue of parsed.error.issues) {
10509
- const topKey = issue.path[0];
10510
- if (topKey !== undefined) {
10511
- const key = String(topKey);
10512
- errorPaths.add(key);
10513
- const paths = issuePathsByKey.get(key) ?? [];
10514
- if (issue.code === "unrecognized_keys") {
10515
- for (const unrecognizedKey of issue.keys) {
10516
- paths.push([...issue.path, unrecognizedKey]);
10517
- }
10518
- } else {
10519
- paths.push([...issue.path]);
10520
- }
10521
- issuePathsByKey.set(key, paths);
10522
- const msg = issue.message;
10523
- if (msg && !GENERIC_ZOD_PREFIXES.some((p) => msg.startsWith(p))) {
10524
- if (!customMessagesByKey.has(key)) {
10525
- customMessagesByKey.set(key, msg);
10526
- }
10527
- }
10528
- }
10529
- }
10530
- const patched = { ...rawConfig };
10531
- for (const key of errorPaths) {
10532
- recoveredTopLevelKeys.push(key);
10533
- const isAgentConfig = key === "historian" || key === "dreamer";
10534
- const issuePaths = issuePathsByKey.get(key) ?? [];
10535
- const rawValue = rawConfig[key];
10536
- const allNested = issuePaths.length > 0 && issuePaths.every((p) => p.length >= 2) && typeof rawValue === "object" && rawValue !== null && !Array.isArray(rawValue);
10537
- if (allNested) {
10538
- let prunedBlock = {
10539
- ...rawValue
10540
- };
10541
- const prunedLeaves = [];
10542
- for (const p of issuePaths) {
10543
- const relative = p.slice(1);
10544
- const result = pruneNestedConfigLeaf(prunedBlock, relative);
10545
- if (result) {
10546
- prunedBlock = result.block;
10547
- prunedLeaves.push(result.removed);
10548
- }
10549
- }
10550
- if (prunedLeaves.length === issuePaths.length) {
10551
- patched[key] = prunedBlock;
10552
- const reason = customMessagesByKey.get(key);
10553
- warnings.push(`"${key}": invalid nested field(s) ${prunedLeaves.map((leaf) => `"${key}.${leaf}"`).join(", ")}, using defaults for those.${reason ? ` ${reason}` : ""}`);
10554
- continue;
10555
- }
10556
- }
10557
- if (isAgentConfig) {
10558
- delete patched[key];
10559
- warnings.push(`"${key}": invalid agent configuration, ignoring. Check your magic-context.jsonc.`);
10560
- continue;
10561
- }
10562
- delete patched[key];
10563
- const defaultVal = defaults[key];
10564
- const reason = customMessagesByKey.get(key);
10565
- const invalidRawValue = rawConfig[key];
10566
- if (key === "protected_tokens" && typeof invalidRawValue === "number" && invalidRawValue < PROTECTED_TOKENS_MIN) {
10567
- warnings.push(formatProtectedTokensBelowMinWarning(invalidRawValue));
10568
- continue;
10569
- }
10570
- warnings.push(`"${key}": invalid value (${redactConfigValue(rawConfig[key])}), using default ${JSON.stringify(defaultVal)}.${reason ? ` ${reason}` : ""}`);
10571
- }
10572
- const retryMigrated = migrateLegacyAgentEnabledInMemory(migrateDreamerV2(migrateLegacyExperimental(patched, preMigrationWarnings), preMigrationWarnings), preMigrationWarnings);
10573
- const retryParsed = MagicContextConfigSchema.safeParse(retryMigrated);
10574
- if (retryParsed.success) {
10575
- return {
10576
- ...retryParsed.data,
10577
- disabled_hooks: disabledHooks,
10578
- command,
10579
- configWarnings: [...preMigrationWarnings, ...warnings]
10580
- };
10581
- }
10582
- warnings.push("Config recovery failed, using all defaults.");
10583
- return {
10584
- ...defaults,
10585
- disabled_hooks: disabledHooks,
10586
- command,
10587
- configWarnings: [...preMigrationWarnings, ...warnings]
10588
- };
10589
- }
10590
- function hasUserTierSubcConfig(config) {
10591
- const subc = config?.subc;
10592
- if (typeof subc !== "object" || subc === null || Array.isArray(subc))
10593
- return false;
10594
- const connectionFile = subc.connection_file;
10595
- return typeof connectionFile === "string" && connectionFile.trim().length > 0;
10596
- }
10597
- function collectEmptyStringPaths(value, prefix = "") {
10598
- if (typeof value === "string") {
10599
- return value === "" && prefix ? [prefix] : [];
10600
- }
10601
- if (Array.isArray(value) || value === null || typeof value !== "object") {
10602
- return [];
10603
- }
10604
- const paths = [];
10605
- for (const [key, child] of Object.entries(value)) {
10606
- const nextPrefix = prefix ? `${prefix}.${key}` : key;
10607
- paths.push(...collectEmptyStringPaths(child, nextPrefix));
10608
- }
10609
- return paths;
10610
- }
10611
- function bindSubstitutionFailures(loaded) {
10612
- if (!loaded || loaded.warnings.length === 0 || loaded.outcome !== "substitution-failure") {
10613
- return [];
10614
- }
10615
- const emptyPaths = collectEmptyStringPaths(loaded.config);
10616
- return loaded.warnings.map((message) => {
10617
- const matchedPath = emptyPaths.find((path) => {
10618
- const tail = path.split(".").at(-1) ?? path;
10619
- return message.includes(path) || message.toLowerCase().includes(tail.toLowerCase());
10620
- });
10621
- return { keyPath: matchedPath ?? "<unknown>", source: loaded.source, message };
10622
- });
10623
- }
10624
- function combinedOutcome(args) {
10625
- const sourceOutcomes = Object.values(args.sources);
10626
- if (sourceOutcomes.includes("project-file-parse-error"))
10627
- return "project-file-parse-error";
10628
- if (sourceOutcomes.includes("project-file-io-error"))
10629
- return "project-file-io-error";
10630
- if (sourceOutcomes.includes("legacy-config-unmigrated"))
10631
- return "legacy-config-unmigrated";
10632
- if (args.recoveredTopLevelKeys.length > 0)
10633
- return "schema-recovery";
10634
- if (args.substitutionFailures.length > 0)
10635
- return "substitution-failure";
10636
- return "ok";
10637
- }
10638
- function loadPluginConfigDetailed(directory, applyRuntimeGlobals = true) {
10639
- const userDetected = detectConfigFile(getUserConfigBasePath());
10640
- const projectDetected = detectConfigFile(getProjectConfigBasePath(directory));
10641
- const legacySources = resolveLegacyConfigSources(directory);
10642
- const harnessLegacy = resolveLegacyConfigSourcesForHarness(directory, "opencode");
10643
- const userLegacyFallback = userDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.user) : { source: null };
10644
- const projectLegacyFallback = projectDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.project) : { source: null };
10645
- const legacyUserUnmigrated = userDetected.format === "none" && !userLegacyFallback.source && legacySources.user.some((source) => existsSync3(source.path));
10646
- const legacyProjectUnmigrated = projectDetected.format === "none" && !projectLegacyFallback.source && legacySources.project.some((source) => existsSync3(source.path));
10647
- const userLoaded = userDetected.format !== "none" ? loadConfigFileDetailed(userDetected.path, "user") : userLegacyFallback.source ? loadConfigFileDetailed(userLegacyFallback.source.path, "user") : null;
10648
- const projectLoaded = projectDetected.format !== "none" ? loadConfigFileDetailed(projectDetected.path, "project") : projectLegacyFallback.source ? loadConfigFileDetailed(projectLegacyFallback.source.path, "project") : null;
10649
- const allWarnings = [];
10650
- const removedConfigWarnings = [];
10651
- const userRaw = stripRemovedAgentConfig(userLoaded?.config ?? {}, removedConfigWarnings);
10652
- if (userLegacyFallback.source) {
10653
- allWarnings.push(`[user config] reading legacy config from ${userLegacyFallback.source.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
10654
- } else if (legacyUserUnmigrated) {
10655
- allWarnings.push("[user config] legacy Magic Context config exists but the shared CortexKit config is absent; embedding registration is paused until config migration completes.");
10656
- }
10657
- if (projectLegacyFallback.source) {
10658
- allWarnings.push(`[project config] reading legacy config from ${projectLegacyFallback.source.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
10659
- } else if (legacyProjectUnmigrated) {
10660
- allWarnings.push("[project config] legacy Magic Context config exists but the shared CortexKit config is absent; embedding registration is paused until config migration completes.");
10661
- }
10662
- if (userLoaded) {
10663
- allWarnings.push(...userLoaded.warnings.map((w) => `[user config] ${w}`));
10664
- }
10665
- let projectRaw = {};
10666
- if (projectLoaded) {
10667
- allWarnings.push(...projectLoaded.warnings.map((w) => `[project config] ${w}`));
10668
- projectRaw = stripRemovedAgentConfig(projectLoaded.config, removedConfigWarnings);
10669
- for (const warning of stripUnsafeProjectConfigFields(projectRaw)) {
10670
- allWarnings.push(`[project config] ${warning}`);
10671
- }
10672
- }
10673
- allWarnings.push(...removedConfigWarnings.map((warning) => `[config] ${warning}`));
10674
- const profileResolution = resolveConfigProfile({
10675
- userRaw,
10676
- projectRaw
10677
- });
10678
- allWarnings.push(...profileResolution.warnings.map((warning) => `[config] ${warning}`));
10679
- const trustedProfiledRaw = deepMergeRawConfig(profileResolution.userBase, profileResolution.overlay);
10680
- let mergedRaw = trustedProfiledRaw;
10681
- const trustedBaseConfig = parsePluginConfig(trustedProfiledRaw);
10682
- if (projectLoaded) {
10683
- mergedRaw = deepMergeRawConfig(mergedRaw, profileResolution.projectBase);
10684
- for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, profileResolution.userBase)) {
10685
- allWarnings.push(`[project config] ${warning}`);
10686
- }
10687
- for (const warning of constrainProjectThresholdOverrides({
10688
- mergedRaw,
10689
- projectRaw: profileResolution.projectBase,
10690
- trustedBaseConfig
10691
- })) {
10692
- allWarnings.push(`[project config] ${warning}`);
10693
- }
10694
- }
10695
- const recoveredTopLevelKeys = [];
10696
- const cacheTtlConfigured = Object.hasOwn(mergedRaw, "cache_ttl");
10697
- const config = parsePluginConfig(mergedRaw, recoveredTopLevelKeys);
10698
- attachProtectedTokensTierOverrides(config, {
10699
- trustedUser: trustedBaseConfig.protected_tokens,
10700
- project: projectLoaded ? profileResolution.projectBase.protected_tokens : undefined
10701
- });
10702
- if (profileResolution.activeProfile)
10703
- config.profile = profileResolution.activeProfile;
10704
- if (applyRuntimeGlobals) {
10705
- setOutputReserveConfig(config.output_reserve);
10706
- setWindowOverlayPath(config.models?.window_overlay_path);
10707
- }
10708
- const leafValidationWarnings = [...config.configWarnings ?? []];
10709
- if (config.configWarnings?.length) {
10710
- allWarnings.push(...config.configWarnings.map((w) => {
10711
- if (userLoaded && projectLoaded)
10712
- return `[config] ${w}`;
10713
- if (userLoaded)
10714
- return `[user config] ${w}`;
10715
- return `[project config] ${w}`;
10716
- }));
10717
- }
10718
- const resolvedTransformMode = resolveTransformMode({
10719
- configured: config.transform_mode,
10720
- userTierHasSubc: hasUserTierSubcConfig(userRaw),
10721
- compactionEnabled: isCompactionEnabled(config)
10722
- });
10723
- config.transform_mode = resolvedTransformMode.mode;
10724
- allWarnings.push(...resolvedTransformMode.warnings.map((warning) => `[config] ${warning}`));
10725
- if (allWarnings.length > 0) {
10726
- config.configWarnings = allWarnings;
10727
- } else if ("configWarnings" in config) {
10728
- config.configWarnings = undefined;
10729
- }
10730
- const substitutionFailures = [
10731
- ...bindSubstitutionFailures(userLoaded),
10732
- ...bindSubstitutionFailures(projectLoaded)
10733
- ];
10734
- const configParseFailures = [
10735
- ...userLoaded?.parseFailures ?? [],
10736
- ...projectLoaded?.parseFailures ?? []
10737
- ];
10738
- const warningDetails = [
10739
- ...userLoaded?.warningDetails ?? [],
10740
- ...projectLoaded?.warningDetails ?? [],
10741
- ...leafValidationWarnings.map((message) => ({
10742
- warningClass: CONFIG_WARNING_CLASS.INVALID_LEAF,
10743
- message
10744
- }))
10745
- ];
10746
- config.configParseFailures = configParseFailures;
10747
- config.configWarningDetails = warningDetails;
10748
- config.cacheTtlConfigured = cacheTtlConfigured;
10749
- const sources = {
10750
- userConfig: userLoaded?.outcome ?? (legacyUserUnmigrated ? "legacy-config-unmigrated" : "ok"),
10751
- projectConfig: projectLoaded?.outcome ?? (legacyProjectUnmigrated ? "legacy-config-unmigrated" : "ok")
10752
- };
10753
- return {
10754
- config,
10755
- registrationPromptSurface: trustedBaseConfig.prompt_surface,
10756
- loadOutcome: combinedOutcome({ sources, substitutionFailures, recoveredTopLevelKeys }),
10757
- sources,
10758
- substitutionFailures,
10759
- recoveredTopLevelKeys,
10760
- configParseFailures,
10761
- warningDetails,
10762
- cacheTtlConfigured
10763
- };
10764
- }
10765
-
10766
- // src/config/live-snapshot.ts
10767
- import { createHash } from "node:crypto";
10768
- import { readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
10769
- class LiveConfigReader {
10770
- directory;
10771
- load;
10772
- onLog;
10773
- changedKeys;
10774
- snapshot;
10775
- files = new Map;
10776
- initialized = false;
10777
- warned = new Set;
10778
- failure;
10779
- constructor(directory, initial, load, onLog = () => {}, changedKeys = (previous, next) => Object.keys(next).filter((key) => JSON.stringify(previous[key]) !== JSON.stringify(next[key]))) {
10780
- this.directory = directory;
10781
- this.load = load;
10782
- this.onLog = onLog;
10783
- this.changedKeys = changedKeys;
10784
- this.snapshot = {
10785
- generation: 1,
10786
- digest: "initial",
10787
- adoptedAt: Date.now(),
10788
- effective: initial
10789
- };
10790
- }
10791
- current() {
10792
- return this.snapshot;
10793
- }
10794
- lastFailure() {
10795
- return this.failure;
10796
- }
10797
- poll() {
10798
- const paths = [
10799
- cortexKitUserConfigBasePath(),
10800
- cortexKitProjectConfigBasePath(this.directory)
10801
- ].map((base) => detectConfigFile(base).path);
10802
- const next = new Map;
10803
- let changed = paths.some((path) => !this.files.has(path));
10804
- for (const path of paths) {
10805
- let metadata;
10806
- try {
10807
- const stat = statSync2(path);
10808
- metadata = `${stat.mtimeMs}:${stat.size}:${stat.ino}`;
10809
- } catch (error) {
10810
- if (error.code !== "ENOENT") {
10811
- this.reportFailure(path, String(error), error);
10812
- return this.snapshot;
10813
- }
10814
- metadata = "absent";
10815
- }
10816
- const previous = this.files.get(path);
10817
- if (previous?.metadata === metadata) {
10818
- next.set(path, previous);
10819
- continue;
10820
- }
10821
- let content;
10822
- try {
10823
- content = metadata === "absent" ? "" : readFileSync3(path, "utf8");
10824
- } catch (error) {
10825
- this.reportFailure(path, String(error), error);
10826
- return this.snapshot;
10827
- }
10828
- const digest = createHash("sha256").update(content).digest("hex");
10829
- if (metadata !== "absent") {
10830
- const parsed = parseJsoncRecovering(content);
10831
- if (parsed.issues.length || !parsed.value || typeof parsed.value !== "object" || Array.isArray(parsed.value)) {
10832
- const issue = parsed.issues[0];
10833
- this.reportFailure(path, digest, issue ? `${issue.line}:${issue.column}: ${issue.message}` : "expected an object");
10834
- return this.snapshot;
10835
- }
10836
- }
10837
- next.set(path, { metadata, digest });
10838
- changed ||= previous?.digest !== digest;
10839
- }
10840
- if (!changed) {
10841
- this.files = next;
10842
- return this.snapshot;
10843
- }
10844
- let effective;
10845
- try {
10846
- effective = this.load();
10847
- } catch (error) {
10848
- this.reportFailure(paths[0] ?? this.directory, "load", error);
10849
- return this.snapshot;
10850
- }
10851
- for (const path of paths) {
10852
- let metadata = "absent";
10853
- try {
10854
- const stat = statSync2(path);
10855
- metadata = `${stat.mtimeMs}:${stat.size}:${stat.ino}`;
10856
- } catch (error) {
10857
- if (error.code !== "ENOENT") {
10858
- this.reportFailure(path, String(error), error);
10859
- return this.snapshot;
10860
- }
10861
- }
10862
- if (metadata !== next.get(path)?.metadata)
10863
- return this.snapshot;
10864
- }
10865
- const digest = createHash("sha256").update(paths.map((path) => `${path}:${next.get(path)?.digest}`).join(`
10866
- `)).digest("hex");
10867
- this.files = next;
10868
- this.failure = undefined;
10869
- if (!this.initialized) {
10870
- this.initialized = true;
10871
- this.snapshot = {
10872
- generation: 1,
10873
- digest,
10874
- adoptedAt: this.snapshot.adoptedAt,
10875
- effective
10876
- };
10877
- } else if (this.snapshot.digest !== digest) {
10878
- const keys = this.changedKeys(this.snapshot.effective, effective);
10879
- this.snapshot = {
10880
- generation: this.snapshot.generation + 1,
10881
- digest,
10882
- adoptedAt: Date.now(),
10883
- effective
10884
- };
10885
- if (keys.length > 0) {
10886
- this.onLog(`config reloaded gen=${this.snapshot.generation} keys=[${keys.join(",")}]`);
10887
- }
10888
- }
10889
- return this.snapshot;
10890
- }
10891
- reportFailure(path, digest, error) {
10892
- const message = error instanceof Error ? error.message : String(error);
10893
- this.failure = { path, message, digest };
10894
- if (this.warned.has(`${path}:${digest}`))
10895
- return;
10896
- this.warned.add(`${path}:${digest}`);
10897
- this.onLog(`config reload failed ${path}: ${message}`);
10898
- }
10899
- }
10900
-
10901
- // src/config/live-run-config.ts
10902
- function sampleLiveConfig(boot, fresh) {
10903
- const result = { ...boot };
10904
- for (const path of LIVE_RELOAD_CONFIG_PATHS) {
10905
- const parts = path.split(".");
10906
- let value = fresh;
10907
- for (const part of parts)
10908
- value = value?.[part];
10909
- let target = result;
10910
- for (const part of parts.slice(0, -1)) {
10911
- const child = target[part];
10912
- const copy = child && typeof child === "object" && !Array.isArray(child) ? { ...child } : {};
10913
- target[part] = copy;
10914
- target = copy;
10915
- }
10916
- const leaf = parts.at(-1);
10917
- if (leaf !== undefined)
10918
- target[leaf] = value;
10919
- }
10920
- return result;
10921
- }
10922
- function changedLiveKeys(previous, next) {
10923
- const at = (config, path) => path.split(".").reduce((node, part) => node?.[part], config);
10924
- return LIVE_RELOAD_CONFIG_PATHS.filter((path) => JSON.stringify(at(previous, path)) !== JSON.stringify(at(next, path)));
10925
- }
10926
- var historianRunConfig = sampleLiveConfig;
10927
- var dreamerRunConfig = sampleLiveConfig;
10928
- var pluginReaders = new Map;
10929
- function pluginConfigReader(directory, boot) {
10930
- let reader = pluginReaders.get(directory);
10931
- if (!reader) {
10932
- reader = new LiveConfigReader(directory, boot, () => {
10933
- const loaded = loadPluginConfigDetailed(directory, false);
10934
- if (loaded.loadOutcome === "project-file-parse-error" || loaded.loadOutcome === "project-file-io-error" || loaded.loadOutcome === "schema-recovery") {
10935
- throw new Error(`invalid configuration: ${loaded.config.configWarnings?.join("; ") ?? loaded.loadOutcome}`);
10936
- }
10937
- return loaded.config;
10938
- }, (message) => log(`[config] ${message}`), changedLiveKeys);
10939
- reader.poll();
10940
- pluginReaders.set(directory, reader);
10941
- }
10942
- return reader;
10943
- }
10944
- function currentPluginConfigReader(directory) {
10945
- return pluginReaders.get(directory);
10946
- }
10947
-
10948
8826
  // src/features/builtin-commands/commands.ts
10949
8827
  var COMPACTION_ENABLED_PATH2 = `compaction${".enabled"}`;
10950
8828
  function getMagicContextBuiltinCommands(compactionEnabled = true) {
@@ -10979,6 +8857,8 @@ function getMagicContextBuiltinCommands(compactionEnabled = true) {
10979
8857
 
10980
8858
  // src/features/magic-context/dreamer/open-opencode-db.ts
10981
8859
  function openOpenCodeDb() {
8860
+ if (!harnessOwnsOpenCodeStore())
8861
+ return null;
10982
8862
  const resolution = resolveOpenCodeDbPath();
10983
8863
  const dbPath = resolution.path;
10984
8864
  if (!openCodeDbPathExists(resolution)) {
@@ -11170,7 +9050,7 @@ function buildDreamTaskPrompt(task, args) {
11170
9050
 
11171
9051
  // src/features/magic-context/session-project-backfill.ts
11172
9052
  import { randomUUID } from "node:crypto";
11173
- import { existsSync as existsSync4 } from "node:fs";
9053
+ import { existsSync } from "node:fs";
11174
9054
  var LEASE_TTL_MS = 10 * 60 * 1000;
11175
9055
  var SESSION_PAGE_SIZE = 100;
11176
9056
  var SESSION_QUERY_CHUNK_SIZE = 250;
@@ -11380,7 +9260,7 @@ async function runSessionProjectBackfill(db, source, options = {}) {
11380
9260
  if (!session.directory) {
11381
9261
  result.skippedEmptyDirectories += 1;
11382
9262
  } else {
11383
- const stillExists = existenceCache.get(session.directory) ?? existsSync4(session.directory);
9263
+ const stillExists = existenceCache.get(session.directory) ?? existsSync(session.directory);
11384
9264
  existenceCache.set(session.directory, stillExists);
11385
9265
  if (!stillExists) {
11386
9266
  result.skippedDeadDirectories += 1;
@@ -11460,7 +9340,7 @@ Output schema:
11460
9340
  }`;
11461
9341
 
11462
9342
  // src/features/magic-context/v22-deferred-backfill.ts
11463
- import { createHash as createHash2 } from "node:crypto";
9343
+ import { createHash } from "node:crypto";
11464
9344
  import { realpathSync } from "node:fs";
11465
9345
  import path from "node:path";
11466
9346
 
@@ -11522,7 +9402,7 @@ function computeLegacyRustDirIdentity(rawProjectPath) {
11522
9402
  } catch {
11523
9403
  canonical = path.isAbsolute(rawProjectPath) ? rawProjectPath : path.join(process.cwd(), rawProjectPath);
11524
9404
  }
11525
- return `dir:${createHash2("sha256").update(canonical, "utf8").digest("hex")}`;
9405
+ return `dir:${createHash("sha256").update(canonical, "utf8").digest("hex")}`;
11526
9406
  }
11527
9407
  function upsertRekeyMap(db, oldProjectPath, newProjectPath, rekeyedAt) {
11528
9408
  db.prepare(`INSERT INTO v22_identity_rekey_map (old_project_path, new_project_path, rekeyed_at)
@@ -11690,17 +9570,17 @@ async function runDeferredV22Backfill(db, options = {}) {
11690
9570
  }
11691
9571
 
11692
9572
  // src/hooks/auto-update-checker/index.ts
11693
- import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync6, renameSync as renameSync3, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
11694
- import { dirname as dirname4, join as join4 } from "node:path";
9573
+ import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
9574
+ import { dirname as dirname2, join as join3 } from "node:path";
11695
9575
 
11696
9576
  // src/shared/auto-update-provenance.ts
11697
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
9577
+ import { existsSync as existsSync2, readFileSync } from "node:fs";
11698
9578
  var AUTO_UPDATE_CHECK_STATE_FILENAME = "last-update-check.json";
11699
9579
  function readAutoUpdateCheckState(path) {
11700
- if (!existsSync5(path))
9580
+ if (!existsSync2(path))
11701
9581
  return null;
11702
9582
  try {
11703
- const value = JSON.parse(readFileSync4(path, "utf-8"));
9583
+ const value = JSON.parse(readFileSync(path, "utf-8"));
11704
9584
  if (!value || typeof value !== "object" || Array.isArray(value))
11705
9585
  return null;
11706
9586
  const raw = value;
@@ -11728,37 +9608,37 @@ var import_comment_json = __toESM(require_src2(), 1);
11728
9608
  import { spawn } from "node:child_process";
11729
9609
  import {
11730
9610
  accessSync,
11731
- existsSync as existsSync6,
9611
+ existsSync as existsSync3,
11732
9612
  constants as fsConstants,
11733
- readFileSync as readFileSync5,
11734
- renameSync as renameSync2,
11735
- statSync as statSync3,
11736
- writeFileSync as writeFileSync2
9613
+ readFileSync as readFileSync2,
9614
+ renameSync,
9615
+ statSync,
9616
+ writeFileSync
11737
9617
  } from "node:fs";
11738
- import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, resolve as resolve2 } from "node:path";
9618
+ import { dirname, isAbsolute, join as join2, resolve } from "node:path";
11739
9619
  import { fileURLToPath } from "node:url";
11740
9620
 
11741
9621
  // src/hooks/auto-update-checker/constants.ts
11742
- import { homedir as homedir2, platform } from "node:os";
11743
- import { join as join2 } from "node:path";
9622
+ import { homedir, platform } from "node:os";
9623
+ import { join } from "node:path";
11744
9624
  var PACKAGE_NAME = "@cortexkit/opencode-magic-context";
11745
9625
  var NPM_REGISTRY_URL = "https://registry.npmjs.org";
11746
9626
  var NPM_FETCH_TIMEOUT = 1e4;
11747
9627
  function getOpenCodeCacheRoot() {
11748
9628
  if (platform() === "win32") {
11749
- return join2(process.env.LOCALAPPDATA ?? homedir2(), "opencode");
9629
+ return join(process.env.LOCALAPPDATA ?? homedir(), "opencode");
11750
9630
  }
11751
- return join2(homedir2(), ".cache", "opencode");
9631
+ return join(homedir(), ".cache", "opencode");
11752
9632
  }
11753
9633
  function getOpenCodeConfigRoot() {
11754
9634
  if (platform() === "win32") {
11755
- return join2(process.env.APPDATA ?? join2(homedir2(), "AppData", "Roaming"), "opencode");
9635
+ return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "opencode");
11756
9636
  }
11757
- return join2(process.env.XDG_CONFIG_HOME ?? join2(homedir2(), ".config"), "opencode");
9637
+ return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "opencode");
11758
9638
  }
11759
- var CACHE_DIR = join2(getOpenCodeCacheRoot(), "packages");
11760
- var USER_OPENCODE_CONFIG = join2(getOpenCodeConfigRoot(), "opencode.json");
11761
- var USER_OPENCODE_CONFIG_JSONC = join2(getOpenCodeConfigRoot(), "opencode.jsonc");
9639
+ var CACHE_DIR = join(getOpenCodeCacheRoot(), "packages");
9640
+ var USER_OPENCODE_CONFIG = join(getOpenCodeConfigRoot(), "opencode.json");
9641
+ var USER_OPENCODE_CONFIG_JSONC = join(getOpenCodeConfigRoot(), "opencode.jsonc");
11762
9642
 
11763
9643
  // src/hooks/auto-update-checker/types.ts
11764
9644
  var NpmPackageEnvelopeSchema = object({
@@ -11819,17 +9699,17 @@ function extractChannel(version) {
11819
9699
  }
11820
9700
  function getSurfaceConfigPaths(directory, surface) {
11821
9701
  const name = surface === "server" ? "opencode" : "tui";
11822
- const globalDir = dirname3(USER_OPENCODE_CONFIG);
9702
+ const globalDir = dirname(USER_OPENCODE_CONFIG);
11823
9703
  const dirs = [
11824
9704
  globalDir,
11825
9705
  directory,
11826
- join3(directory, ".opencode"),
9706
+ join2(directory, ".opencode"),
11827
9707
  process.env.OPENCODE_CONFIG_DIR
11828
9708
  ].filter((value) => Boolean(value));
11829
9709
  const paths = [];
11830
9710
  for (const dir of dirs) {
11831
9711
  for (const extension of ["json", "jsonc"]) {
11832
- const path = join3(dir, `${name}.${extension}`);
9712
+ const path = join2(dir, `${name}.${extension}`);
11833
9713
  if (!paths.includes(path))
11834
9714
  paths.push(path);
11835
9715
  }
@@ -11840,9 +9720,9 @@ function getWinningConfig(directory, surface) {
11840
9720
  let winner = null;
11841
9721
  for (const path of getSurfaceConfigPaths(directory, surface)) {
11842
9722
  try {
11843
- if (!existsSync6(path))
9723
+ if (!existsSync3(path))
11844
9724
  continue;
11845
- const parsed = parseJsonConfig(readFileSync5(path, "utf-8"));
9725
+ const parsed = parseJsonConfig(readFileSync2(path, "utf-8"));
11846
9726
  const entries = getPluginEntries(parsed);
11847
9727
  if (entries.some((entry) => entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))) {
11848
9728
  if (winner) {
@@ -11865,24 +9745,24 @@ function resolvePathPluginSpec(spec, configPath) {
11865
9745
  return spec.replace(/^file:\/\//, "");
11866
9746
  }
11867
9747
  }
11868
- if (isAbsolute2(spec) || /^[A-Za-z]:[\\/]/.test(spec))
9748
+ if (isAbsolute(spec) || /^[A-Za-z]:[\\/]/.test(spec))
11869
9749
  return spec;
11870
- return resolve2(dirname3(configPath), spec);
9750
+ return resolve(dirname(configPath), spec);
11871
9751
  }
11872
9752
  function findPackageJsonUp(startPath) {
11873
9753
  try {
11874
- const stat = statSync3(startPath);
11875
- let dir = stat.isDirectory() ? startPath : dirname3(startPath);
9754
+ const stat = statSync(startPath);
9755
+ let dir = stat.isDirectory() ? startPath : dirname(startPath);
11876
9756
  for (let i = 0;i < 10; i++) {
11877
- const pkgPath = join3(dir, "package.json");
11878
- if (existsSync6(pkgPath)) {
9757
+ const pkgPath = join2(dir, "package.json");
9758
+ if (existsSync3(pkgPath)) {
11879
9759
  try {
11880
- const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync5(pkgPath, "utf-8")));
9760
+ const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync2(pkgPath, "utf-8")));
11881
9761
  if (pkg.success && pkg.data.name === PACKAGE_NAME)
11882
9762
  return pkgPath;
11883
9763
  } catch {}
11884
9764
  }
11885
- const parent = dirname3(dir);
9765
+ const parent = dirname(dir);
11886
9766
  if (parent === dir)
11887
9767
  break;
11888
9768
  dir = parent;
@@ -11893,19 +9773,19 @@ function findPackageJsonUp(startPath) {
11893
9773
  function getLocalDevPath(directory) {
11894
9774
  for (const configPath of getConfigPaths(directory)) {
11895
9775
  try {
11896
- if (!existsSync6(configPath))
9776
+ if (!existsSync3(configPath))
11897
9777
  continue;
11898
- const rawConfig = parseJsonConfig(readFileSync5(configPath, "utf-8"));
9778
+ const rawConfig = parseJsonConfig(readFileSync2(configPath, "utf-8"));
11899
9779
  const plugins = getPluginEntries(rawConfig);
11900
9780
  for (const entry of plugins) {
11901
9781
  if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
11902
9782
  continue;
11903
- if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute2(entry)) {
9783
+ if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute(entry)) {
11904
9784
  const localPath = resolvePathPluginSpec(entry, configPath);
11905
9785
  const pkgPath = findPackageJsonUp(localPath);
11906
9786
  if (!pkgPath)
11907
9787
  continue;
11908
- const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync5(pkgPath, "utf-8")));
9788
+ const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync2(pkgPath, "utf-8")));
11909
9789
  if (pkg.success && pkg.data.name === PACKAGE_NAME)
11910
9790
  return localPath;
11911
9791
  }
@@ -11922,7 +9802,7 @@ function getLocalDevVersion(directory) {
11922
9802
  const pkgPath = findPackageJsonUp(localPath);
11923
9803
  if (!pkgPath)
11924
9804
  return null;
11925
- const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync5(pkgPath, "utf-8")));
9805
+ const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync2(pkgPath, "utf-8")));
11926
9806
  return pkg.success ? pkg.data.version ?? null : null;
11927
9807
  } catch {
11928
9808
  return null;
@@ -11930,7 +9810,7 @@ function getLocalDevVersion(directory) {
11930
9810
  }
11931
9811
  function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
11932
9812
  try {
11933
- return findPackageJsonUp(dirname3(fileURLToPath(currentModuleUrl)));
9813
+ return findPackageJsonUp(dirname(fileURLToPath(currentModuleUrl)));
11934
9814
  } catch (err) {
11935
9815
  warn(`[auto-update-checker] Failed to resolve runtime package path: ${String(err)}`);
11936
9816
  return null;
@@ -11979,7 +9859,7 @@ function preflightConfigUpdates(paths, version) {
11979
9859
  for (const path of paths) {
11980
9860
  try {
11981
9861
  accessSync(path, fsConstants.W_OK);
11982
- const original = readFileSync5(path, "utf-8");
9862
+ const original = readFileSync2(path, "utf-8");
11983
9863
  const updated = configUpdateContent(original, version);
11984
9864
  if (!updated)
11985
9865
  return null;
@@ -11993,8 +9873,8 @@ function preflightConfigUpdates(paths, version) {
11993
9873
  }
11994
9874
  function writeConfig(path, content) {
11995
9875
  const tmp = `${path}.mc-tmp-${process.pid}`;
11996
- writeFileSync2(tmp, content, "utf-8");
11997
- renameSync2(tmp, path);
9876
+ writeFileSync(tmp, content, "utf-8");
9877
+ renameSync(tmp, path);
11998
9878
  }
11999
9879
  function restoreConfigs(snapshots) {
12000
9880
  for (const snapshot of snapshots) {
@@ -12008,7 +9888,7 @@ function restoreConfigs(snapshots) {
12008
9888
  function configsHaveSpec(paths, spec) {
12009
9889
  return paths.every((path) => {
12010
9890
  try {
12011
- const parsed = parseJsonConfig(readFileSync5(path, "utf-8"));
9891
+ const parsed = parseJsonConfig(readFileSync2(path, "utf-8"));
12012
9892
  return getPluginEntries(parsed).includes(spec);
12013
9893
  } catch {
12014
9894
  return false;
@@ -12064,8 +9944,8 @@ async function preparePluginUpdate(directory, _pluginInfo, version, options = {}
12064
9944
  return null;
12065
9945
  const spec = `${PACKAGE_NAME}@${version}`;
12066
9946
  const globalServerPaths = [USER_OPENCODE_CONFIG, USER_OPENCODE_CONFIG_JSONC];
12067
- const globalTuiPaths = globalServerPaths.map((path) => join3(dirname3(path), "tui.json"));
12068
- globalTuiPaths.push(...globalServerPaths.map((path) => join3(dirname3(path), "tui.jsonc")));
9947
+ const globalTuiPaths = globalServerPaths.map((path) => join2(dirname(path), "tui.json"));
9948
+ globalTuiPaths.push(...globalServerPaths.map((path) => join2(dirname(path), "tui.jsonc")));
12069
9949
  const isGlobal = globalServerPaths.includes(paths[0]) && globalTuiPaths.includes(paths[1]);
12070
9950
  if (isGlobal) {
12071
9951
  const hostResult = await runHostPluginInstall(spec, options.signal, options.timeoutMs);
@@ -12098,9 +9978,9 @@ function getCachedVersion(_spec) {
12098
9978
  const candidates = [getCurrentRuntimePackageJsonPath()].filter(isString);
12099
9979
  for (const packageJsonPath of candidates) {
12100
9980
  try {
12101
- if (!existsSync6(packageJsonPath))
9981
+ if (!existsSync3(packageJsonPath))
12102
9982
  continue;
12103
- const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync5(packageJsonPath, "utf-8")));
9983
+ const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync2(packageJsonPath, "utf-8")));
12104
9984
  if (pkg.success && pkg.data.version) {
12105
9985
  if (!_spec)
12106
9986
  cachedPackageVersion = pkg.data.version;
@@ -12194,14 +10074,14 @@ async function maybeRunCheck(ctx, options) {
12194
10074
  await runStartupCheck(ctx, options);
12195
10075
  }
12196
10076
  function checkStatePath(storageDir) {
12197
- return join4(storageDir ?? getOpenCodeStorageDir(), AUTO_UPDATE_CHECK_STATE_FILENAME);
10077
+ return join3(storageDir ?? getOpenCodeStorageDir(), AUTO_UPDATE_CHECK_STATE_FILENAME);
12198
10078
  }
12199
10079
  function writeCheckState(path, state) {
12200
- mkdirSync(dirname4(path), { recursive: true });
10080
+ mkdirSync(dirname2(path), { recursive: true });
12201
10081
  const tmp = `${path}.tmp.${process.pid}`;
12202
- writeFileSync3(tmp, `${JSON.stringify(state, null, 2)}
10082
+ writeFileSync2(tmp, `${JSON.stringify(state, null, 2)}
12203
10083
  `, "utf-8");
12204
- renameSync3(tmp, path);
10084
+ renameSync2(tmp, path);
12205
10085
  }
12206
10086
  function claimCheckSlot(storageDir, intervalMs) {
12207
10087
  if (!storageDir)
@@ -12233,28 +10113,28 @@ function recordUpdaterPinnedSpec(storageDir, spec) {
12233
10113
  }
12234
10114
  }
12235
10115
  function pendingMarkerPath(storageDir) {
12236
- return join4(storageDir ?? getOpenCodeStorageDir(), PENDING_UPDATE_FILENAME);
10116
+ return join3(storageDir ?? getOpenCodeStorageDir(), PENDING_UPDATE_FILENAME);
12237
10117
  }
12238
10118
  function writePendingUpdateMarker(storageDir, update, version) {
12239
10119
  recordUpdaterPinnedSpec(storageDir, update.spec);
12240
10120
  try {
12241
- const dir = storageDir ?? dirname4(pendingMarkerPath(storageDir));
10121
+ const dir = storageDir ?? dirname2(pendingMarkerPath(storageDir));
12242
10122
  mkdirSync(dir, { recursive: true });
12243
10123
  const path = pendingMarkerPath(storageDir);
12244
10124
  const temp = `${path}.tmp.${process.pid}`;
12245
- writeFileSync3(temp, `${JSON.stringify({ spec: update.spec, version, configPaths: update.configPaths, writtenAt: Date.now() }, null, 2)}
10125
+ writeFileSync2(temp, `${JSON.stringify({ spec: update.spec, version, configPaths: update.configPaths, writtenAt: Date.now() }, null, 2)}
12246
10126
  `, "utf-8");
12247
- renameSync3(temp, path);
10127
+ renameSync2(temp, path);
12248
10128
  } catch (err) {
12249
10129
  warn2(`[auto-update-checker] Could not write pending update marker: ${String(err)}`);
12250
10130
  }
12251
10131
  }
12252
10132
  function consumePendingUpdateMarker(storageDir, loadedVersion) {
12253
10133
  const path = pendingMarkerPath(storageDir);
12254
- if (!existsSync7(path))
10134
+ if (!existsSync4(path))
12255
10135
  return;
12256
10136
  try {
12257
- const marker = JSON.parse(readFileSync6(path, "utf-8"));
10137
+ const marker = JSON.parse(readFileSync3(path, "utf-8"));
12258
10138
  const age = Date.now() - (marker.writtenAt ?? 0);
12259
10139
  const olderThanLoaded = typeof marker.version === "string" && typeof loadedVersion === "string" && (compareSemverCore(marker.version, loadedVersion) ?? 0) < 0;
12260
10140
  if (marker.version === loadedVersion && marker.spec === `${PACKAGE_NAME}@${loadedVersion}` && Array.isArray(marker.configPaths) && marker.configPaths.length === 2) {
@@ -12379,7 +10259,7 @@ function createLiveSessionState() {
12379
10259
 
12380
10260
  // src/hooks/magic-context/module-transport.ts
12381
10261
  import { realpathSync as realpathSync2 } from "node:fs";
12382
- import { join as join5 } from "node:path";
10262
+ import { join as join4 } from "node:path";
12383
10263
 
12384
10264
  // src/hooks/magic-context/store-ahead-refusal.ts
12385
10265
  var STORE_AHEAD_OF_BINARY_CODE = "store_ahead_of_binary";
@@ -12398,14 +10278,14 @@ class StoreAheadOfBinaryError extends Error {
12398
10278
  this.versions = versions;
12399
10279
  }
12400
10280
  }
12401
- function isRecord3(value) {
10281
+ function isRecord2(value) {
12402
10282
  return value !== null && typeof value === "object";
12403
10283
  }
12404
10284
  function nonNegativeInteger(value) {
12405
10285
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
12406
10286
  }
12407
10287
  function versionsFromDetail(detail) {
12408
- if (!isRecord3(detail))
10288
+ if (!isRecord2(detail))
12409
10289
  return null;
12410
10290
  const dbVersion = nonNegativeInteger(detail.db_version);
12411
10291
  const binaryMax = nonNegativeInteger(detail.binary_max);
@@ -12422,7 +10302,7 @@ function versionsFromMessage(message) {
12422
10302
  function storeAheadOfBinaryFailure(error) {
12423
10303
  let current = error;
12424
10304
  const seen = new Set;
12425
- while (isRecord3(current) && !seen.has(current)) {
10305
+ while (isRecord2(current) && !seen.has(current)) {
12426
10306
  seen.add(current);
12427
10307
  if (current instanceof StoreAheadOfBinaryError)
12428
10308
  return current;
@@ -12457,7 +10337,7 @@ var SERIAL_LANE_MAX_WAITERS_PER_SESSION = 8;
12457
10337
  var SERIAL_LANE_MIN_REMAINING_MS = 25;
12458
10338
  var CANONICAL_ROOT_CACHE_MAX_ENTRIES = 256;
12459
10339
  function getDefaultSubcConnectionFile() {
12460
- return join5(getDataDir(), "cortexkit", "run", "subc-connection.json");
10340
+ return join4(getDataDir(), "cortexkit", "run", "subc-connection.json");
12461
10341
  }
12462
10342
  function errorChainSome(error, predicate) {
12463
10343
  let current = error;
@@ -13166,7 +11046,7 @@ function runBootPhaseWithinBudget(budget, phase, operation, report) {
13166
11046
  }
13167
11047
 
13168
11048
  // src/plugin/dream-timer.ts
13169
- import { statSync as statSync5 } from "node:fs";
11049
+ import { statSync as statSync3 } from "node:fs";
13170
11050
 
13171
11051
  // src/features/magic-context/dreamer/storage-dream-state.ts
13172
11052
  var getDreamStateStatements = new WeakMap;
@@ -13866,11 +11746,48 @@ function normalizeOpenCodeRows(db, sessionId, rows) {
13866
11746
  return [];
13867
11747
  const messageIds = rows.map((row) => row.id);
13868
11748
  const placeholders = messageIds.map(() => "?").join(", ");
13869
- const partRows = db.prepare(`SELECT message_id, data
11749
+ const userIds = rows.filter((row) => parseJsonRecord(row.data)?.role === "user").map((row) => row.id);
11750
+ const userPlaceholders = userIds.map(() => "?").join(", ") || "NULL";
11751
+ const output = `CASE json_type(data, '$.state.output')
11752
+ WHEN 'text' THEN json_extract(data, '$.state.output')
11753
+ WHEN 'null' THEN '' ELSE COALESCE(data -> '$.state.output', '') END`;
11754
+ const error = `CASE json_type(data, '$.state.error')
11755
+ WHEN 'text' THEN json_extract(data, '$.state.error')
11756
+ WHEN 'null' THEN '' ELSE COALESCE(data -> '$.state.error', '') END`;
11757
+ const containsError = (value) => ["error", "failed", "exception", "traceback"].map((word) => `(' ' || lower(${value}) || ' ') GLOB '*[^a-z0-9_]${word}[^a-z0-9_]*'`).join(" OR ");
11758
+ const errorWords = `CASE WHEN json_type(data, '$.state.output') IN ('object', 'array')
11759
+ THEN EXISTS (SELECT 1 FROM json_tree(data, '$.state.output') AS leaf
11760
+ WHERE (leaf.type = 'text' AND (${containsError("json_quote(leaf.atom)")}))
11761
+ OR (typeof(leaf.key) = 'text' AND (${containsError("json_quote(leaf.key)")})))
11762
+ WHEN instr(CAST(${output} AS BLOB), x'00') > 0 THEN EXISTS (
11763
+ WITH RECURSIVE segments(rest, piece) AS (
11764
+ SELECT CAST(${output} AS BLOB), x''
11765
+ UNION ALL
11766
+ SELECT CASE WHEN instr(rest, x'00') > 0
11767
+ THEN substr(rest, instr(rest, x'00') + 1) ELSE NULL END,
11768
+ CASE WHEN instr(rest, x'00') > 0
11769
+ THEN substr(rest, 1, instr(rest, x'00') - 1) ELSE rest END
11770
+ FROM segments WHERE rest IS NOT NULL
11771
+ ) SELECT 1 FROM segments WHERE (${containsError("CAST(piece AS TEXT)")}))
11772
+ ELSE (${containsError(output)}) END`;
11773
+ const whitespace = `
11774
+ \v\f\r              \u2028\u2029   \uFEFF`;
11775
+ const partRows = db.prepare(`SELECT message_id, CASE json_extract(data, '$.type')
11776
+ WHEN 'text' THEN CASE WHEN message_id IN (${userPlaceholders}) THEN json_object(
11777
+ 'type', 'text', 'text', data -> '$.text',
11778
+ 'synthetic', data -> '$.synthetic', 'ignored', data -> '$.ignored') ELSE '{}' END
11779
+ WHEN 'tool' THEN json_object(
11780
+ 'type', 'tool', 'tool', data -> '$.tool',
11781
+ 'state', json_object('isError', json(CASE WHEN
11782
+ json_type(data, '$.state.isError') = 'true'
11783
+ OR lower(json_extract(data, '$.state.status')) = 'error'
11784
+ OR length(CAST(trim(${error}, ?) AS BLOB)) > 0 OR ${errorWords}
11785
+ THEN 'true' ELSE 'false' END)))
11786
+ ELSE '{}' END AS data
13870
11787
  FROM part
13871
- WHERE +session_id = ?
11788
+ WHERE +session_id = ? AND json_valid(data)
13872
11789
  AND likelihood(message_id IN (${placeholders}), 0.000001)
13873
- ORDER BY time_created ASC, id ASC`).all(sessionId, ...messageIds);
11790
+ ORDER BY time_created ASC, id ASC`).all(...userIds, whitespace, sessionId, ...messageIds);
13874
11791
  const partsByMessageId = new Map;
13875
11792
  for (const row of partRows) {
13876
11793
  const parts = partsByMessageId.get(row.message_id) ?? [];
@@ -14081,11 +11998,11 @@ function recordRetrospectiveWindowProcessed(db, projectPath, windowKey) {
14081
11998
  }
14082
11999
 
14083
12000
  // src/features/magic-context/dreamer/task-executor.ts
14084
- import { createHash as createHash10 } from "node:crypto";
14085
- import { existsSync as existsSync11 } from "node:fs";
12001
+ import { createHash as createHash9 } from "node:crypto";
12002
+ import { existsSync as existsSync8 } from "node:fs";
14086
12003
 
14087
12004
  // src/features/magic-context/mural/compress-cues.ts
14088
- import { createHash as createHash4 } from "node:crypto";
12005
+ import { createHash as createHash3 } from "node:crypto";
14089
12006
 
14090
12007
  // src/features/magic-context/dreamer/manifest-parser.ts
14091
12008
  function extractCompleteManifestBody(text, rootName) {
@@ -14149,7 +12066,7 @@ function assertParsedManifestNonEmpty(parsedCount, expectedCount, text, expected
14149
12066
  }
14150
12067
 
14151
12068
  // src/features/magic-context/dreamer/provider-output-failure.ts
14152
- import { createHash as createHash3 } from "node:crypto";
12069
+ import { createHash as createHash2 } from "node:crypto";
14153
12070
  var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
14154
12071
 
14155
12072
  class DreamerProviderOutputFailureError extends Error {
@@ -14206,7 +12123,7 @@ function providerOutputFailureFromInvalidManifest(messages, responseText) {
14206
12123
  const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
14207
12124
  if (!normalized)
14208
12125
  return null;
14209
- const fingerprint = createHash3("sha256").update(normalized).digest("hex").slice(0, 16);
12126
+ const fingerprint = createHash2("sha256").update(normalized).digest("hex").slice(0, 16);
14210
12127
  return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
14211
12128
  }
14212
12129
 
@@ -14613,7 +12530,7 @@ async function applyCuesThroughModule(args, chunk, manifestText, signal) {
14613
12530
  log(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason}; rejection ${rejectionCount}/${CUE_REJECTION_LATCH_THRESHOLD})`);
14614
12531
  }
14615
12532
  }
14616
- const commandId = `mural-cues:${route.moduleCommandId}:${createHash4("sha256").update(chunk.map((candidate) => candidate.memory.id).join(",")).digest("hex").slice(0, 24)}`;
12533
+ const commandId = `mural-cues:${route.moduleCommandId}:${createHash3("sha256").update(chunk.map((candidate) => candidate.memory.id).join(",")).digest("hex").slice(0, 24)}`;
14617
12534
  let response;
14618
12535
  try {
14619
12536
  response = await route.moduleClient.call({
@@ -14975,7 +12892,7 @@ function applyReviewVerdict(args, leaseKey, parsed, result) {
14975
12892
  }
14976
12893
 
14977
12894
  // src/features/magic-context/dreamer/classify.ts
14978
- import { createHash as createHash5 } from "node:crypto";
12895
+ import { createHash as createHash4 } from "node:crypto";
14979
12896
 
14980
12897
  // src/plugin/rust-tool-backends.ts
14981
12898
  function toolCallIdFromContext(context) {
@@ -15434,7 +13351,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal, runOnHost)
15434
13351
  });
15435
13352
  const modelChain = [args.model, ...args.fallbackModels ?? []].map(toModelEntry).filter((entry) => entry !== undefined).map((entry) => entry.model);
15436
13353
  const resolvedModelChain = [...new Set(modelChain)];
15437
- const commandId = `classify:${args.moduleCommandId ?? Date.now()}:${createHash5("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`;
13354
+ const commandId = `classify:${args.moduleCommandId ?? Date.now()}:${createHash4("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`;
15438
13355
  const runTask = (hostCompletion) => args.moduleClient?.call({
15439
13356
  sessionId: args.moduleSessionId,
15440
13357
  projectRoot: args.moduleProjectRoot,
@@ -15803,36 +13720,36 @@ function takeCurateSafetyRefusalCount(sessionId) {
15803
13720
 
15804
13721
  // src/features/magic-context/dreamer/docs-proposals.ts
15805
13722
  import { execFileSync } from "node:child_process";
15806
- import { createHash as createHash6 } from "node:crypto";
13723
+ import { createHash as createHash5 } from "node:crypto";
15807
13724
  import {
15808
- existsSync as existsSync8,
13725
+ existsSync as existsSync5,
15809
13726
  mkdirSync as mkdirSync2,
15810
13727
  mkdtempSync,
15811
13728
  readdirSync,
15812
- readFileSync as readFileSync7,
13729
+ readFileSync as readFileSync4,
15813
13730
  realpathSync as realpathSync3,
15814
- renameSync as renameSync4,
13731
+ renameSync as renameSync3,
15815
13732
  rmSync as rmSync2,
15816
- writeFileSync as writeFileSync4
13733
+ writeFileSync as writeFileSync3
15817
13734
  } from "node:fs";
15818
13735
  import { tmpdir } from "node:os";
15819
- import { join as join6 } from "node:path";
13736
+ import { join as join5 } from "node:path";
15820
13737
  var FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
15821
- var hash = (text) => createHash6("sha256").update(text).digest("hex");
15822
- var proposalDir = (projectDir) => join6(projectDir, ".cortexkit/magic-context/docs-update-proposals");
13738
+ var hash = (text) => createHash5("sha256").update(text).digest("hex");
13739
+ var proposalDir = (projectDir) => join5(projectDir, ".cortexkit/magic-context/docs-update-proposals");
15823
13740
  function docsBaseHashes(projectDir) {
15824
13741
  return Object.fromEntries(FILES.map((name) => [
15825
13742
  name,
15826
- hash(existsSync8(join6(projectDir, name)) ? readFileSync7(join6(projectDir, name), "utf8") : "")
13743
+ hash(existsSync5(join5(projectDir, name)) ? readFileSync4(join5(projectDir, name), "utf8") : "")
15827
13744
  ]));
15828
13745
  }
15829
13746
  function listPendingDocsProposals(projectDir) {
15830
13747
  const dir = proposalDir(projectDir);
15831
- return existsSync8(dir) ? readdirSync(dir).filter((name) => name.endsWith(".md")).sort().map((name) => join6(dir, name)) : [];
13748
+ return existsSync5(dir) ? readdirSync(dir).filter((name) => name.endsWith(".md")).sort().map((name) => join5(dir, name)) : [];
15832
13749
  }
15833
13750
  function hasCurrentDocsProposal(projectDir) {
15834
13751
  const hashes = docsBaseHashes(projectDir);
15835
- return listPendingDocsProposals(projectDir).some((path) => Object.entries(hashes).every(([name, value]) => readFileSync7(path, "utf8").includes(`Base SHA-256 ${name}: ${value}`)));
13752
+ return listPendingDocsProposals(projectDir).some((path) => Object.entries(hashes).every(([name, value]) => readFileSync4(path, "utf8").includes(`Base SHA-256 ${name}: ${value}`)));
15836
13753
  }
15837
13754
  function git(projectDir, args) {
15838
13755
  return execFileSync("git", args, {
@@ -15914,14 +13831,14 @@ function protectedBytes(text) {
15914
13831
  ].map((match) => match[0]);
15915
13832
  }
15916
13833
  function diff(name, before, after) {
15917
- const dir = mkdtempSync(join6(tmpdir(), "mc-doc-diff-"));
13834
+ const dir = mkdtempSync(join5(tmpdir(), "mc-doc-diff-"));
15918
13835
  try {
15919
- writeFileSync4(join6(dir, "before"), before);
15920
- writeFileSync4(join6(dir, "after"), after);
13836
+ writeFileSync3(join5(dir, "before"), before);
13837
+ writeFileSync3(join5(dir, "after"), after);
15921
13838
  try {
15922
- return execFileSync("git", ["diff", "--no-index", "--", join6(dir, "before"), join6(dir, "after")], { encoding: "utf8" });
13839
+ return execFileSync("git", ["diff", "--no-index", "--", join5(dir, "before"), join5(dir, "after")], { encoding: "utf8" });
15923
13840
  } catch (error) {
15924
- return error.stdout?.replaceAll(join6(dir, "before"), `a/${name}`).replaceAll(join6(dir, "after"), `b/${name}`) ?? "";
13841
+ return error.stdout?.replaceAll(join5(dir, "before"), `a/${name}`).replaceAll(join5(dir, "after"), `b/${name}`) ?? "";
15925
13842
  }
15926
13843
  } finally {
15927
13844
  rmSync2(dir, { recursive: true, force: true });
@@ -15942,7 +13859,7 @@ function validateDocsProposal(projectDir, output, budget, expected) {
15942
13859
  let tokens = 0;
15943
13860
  let diffs = "";
15944
13861
  for (const file of FILES) {
15945
- const before = existsSync8(join6(projectDir, file)) ? readFileSync7(join6(projectDir, file), "utf8") : "";
13862
+ const before = existsSync5(join5(projectDir, file)) ? readFileSync4(join5(projectDir, file), "utf8") : "";
15946
13863
  let after = before;
15947
13864
  const seen = new Set;
15948
13865
  for (const change of changes.filter((item) => item.file === file)) {
@@ -15992,9 +13909,9 @@ ${change.text.trimEnd()}
15992
13909
  function writeDocsProposal(projectDir, output, budget, expected, head) {
15993
13910
  const result = validateDocsProposal(projectDir, output, budget, expected);
15994
13911
  const dir = proposalDir(projectDir);
15995
- mkdirSync2(join6(dir, "superseded"), { recursive: true });
13912
+ mkdirSync2(join5(dir, "superseded"), { recursive: true });
15996
13913
  const stamp = `${new Date().toISOString().replace(/[:.]/g, "-")}-${Math.random().toString(36).slice(2, 8)}`;
15997
- const path = join6(dir, `${stamp}.md`);
13914
+ const path = join5(dir, `${stamp}.md`);
15998
13915
  const body = `# Docs update proposal
15999
13916
 
16000
13917
  Base commit: ${head}
@@ -16019,10 +13936,10 @@ ${item.text}
16019
13936
  ${result.diffs}
16020
13937
  \`\`\`
16021
13938
  `;
16022
- writeFileSync4(path, body, { flag: "wx" });
13939
+ writeFileSync3(path, body, { flag: "wx" });
16023
13940
  for (const old of listPendingDocsProposals(projectDir))
16024
13941
  if (old !== path)
16025
- renameSync4(old, join6(dir, "superseded", old.split("/").at(-1) ?? "proposal.md"));
13942
+ renameSync3(old, join5(dir, "superseded", old.split("/").at(-1) ?? "proposal.md"));
16026
13943
  return path;
16027
13944
  }
16028
13945
 
@@ -16583,7 +14500,7 @@ function throwIfAborted2(signal) {
16583
14500
  }
16584
14501
 
16585
14502
  // src/features/magic-context/smart-notes/compiler.ts
16586
- import { createHash as createHash7 } from "node:crypto";
14503
+ import { createHash as createHash6 } from "node:crypto";
16587
14504
 
16588
14505
  // src/features/magic-context/smart-notes/sandbox-runner.ts
16589
14506
  var asyncModulePromise = null;
@@ -17073,7 +14990,7 @@ function manifestAdvisoryWarnings(code, manifest) {
17073
14990
  return warnings;
17074
14991
  }
17075
14992
  function hashCheck(surfaceCondition, compiledCheck, manifest, checkCron) {
17076
- return createHash7("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
14993
+ return createHash6("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
17077
14994
  }
17078
14995
  function extractJsonObject(output) {
17079
14996
  const fenced = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
@@ -17300,7 +15217,7 @@ function backoffMs(failureCount) {
17300
15217
  }
17301
15218
 
17302
15219
  // src/features/magic-context/smart-notes/wake-plane.ts
17303
- import { join as join7 } from "node:path";
15220
+ import { join as join6 } from "node:path";
17304
15221
  var WAKE_PLANE_CAPABILITY = "wake.create";
17305
15222
  var WAKE_PLANE_STATUS_TTL_MS = 5 * 60 * 1000;
17306
15223
  var WAKE_PLANE_HANDSHAKE_TIMEOUT_MS = 2000;
@@ -17309,7 +15226,7 @@ var inFlightProbe = null;
17309
15226
  var catalogProbe = probeWakePlaneCatalog;
17310
15227
  var now = () => Date.now();
17311
15228
  function connectionFile() {
17312
- return join7(getDataDir(), "cortexkit", "run", "subc-connection.json");
15229
+ return join6(getDataDir(), "cortexkit", "run", "subc-connection.json");
17313
15230
  }
17314
15231
  async function probeWakePlaneCatalog() {
17315
15232
  const file = connectionFile();
@@ -17995,16 +15912,16 @@ async function archiveExpiredMemories(args) {
17995
15912
  }
17996
15913
 
17997
15914
  // src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
17998
- import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
17999
- import { join as join8 } from "node:path";
15915
+ import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
15916
+ import { join as join7 } from "node:path";
18000
15917
  var MAINTAIN_DOCS_SNAPSHOT_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
18001
15918
  function snapshotMaintainDocsFiles(docsDir) {
18002
15919
  const snapshot = new Map;
18003
15920
  for (const name of MAINTAIN_DOCS_SNAPSHOT_FILES) {
18004
- const path = join8(docsDir, name);
15921
+ const path = join7(docsDir, name);
18005
15922
  try {
18006
- if (existsSync9(path)) {
18007
- snapshot.set(name, readFileSync8(path, "utf8"));
15923
+ if (existsSync6(path)) {
15924
+ snapshot.set(name, readFileSync5(path, "utf8"));
18008
15925
  }
18009
15926
  } catch {}
18010
15927
  }
@@ -18012,10 +15929,10 @@ function snapshotMaintainDocsFiles(docsDir) {
18012
15929
  }
18013
15930
 
18014
15931
  // src/features/magic-context/dreamer/map-memories.ts
18015
- import { createHash as createHash8 } from "node:crypto";
15932
+ import { createHash as createHash7 } from "node:crypto";
18016
15933
 
18017
15934
  // src/features/magic-context/dreamer/map-memories-prompt.ts
18018
- import { existsSync as existsSync10, statSync as statSync4 } from "node:fs";
15935
+ import { existsSync as existsSync7, statSync as statSync2 } from "node:fs";
18019
15936
  import path3 from "node:path";
18020
15937
  var MAP_MEMORIES_SYSTEM_PROMPT = `You are a memory mapper for the magic-context system. You map project memories to the repository files that back them.
18021
15938
 
@@ -18053,7 +15970,7 @@ function extractMemoryCandidatePaths(content, repoDir) {
18053
15970
  if (!abs.startsWith(`${root}/`))
18054
15971
  continue;
18055
15972
  try {
18056
- if (existsSync10(abs) && statSync4(abs).isFile())
15973
+ if (existsSync7(abs) && statSync2(abs).isFile())
18057
15974
  found.add(rel);
18058
15975
  } catch {}
18059
15976
  if (found.size >= MAX_SEED_PATHS_PER_MEMORY)
@@ -18472,7 +16389,7 @@ async function applyParsedBatchMappings(args, batch, parsed) {
18472
16389
  memory_project: args.projectIdentity,
18473
16390
  context_store_uuid: args.moduleRoute.moduleContextStoreUuid,
18474
16391
  authority_generation: args.moduleRoute.moduleAuthorityGeneration,
18475
- command_id: `${args.moduleRoute.moduleCommandId}:${createHash8("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
16392
+ command_id: `${args.moduleRoute.moduleCommandId}:${createHash7("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
18476
16393
  rows
18477
16394
  }
18478
16395
  }
@@ -18765,12 +16682,12 @@ async function promotePrimers(args) {
18765
16682
 
18766
16683
  // src/features/magic-context/dreamer/primer-seed.ts
18767
16684
  var PRIMER_SEED_CAP_TOKENS = 4000;
18768
- function renderUserAndToolOrientation(messages, startOrdinal, endOrdinal, capTokens) {
16685
+ function renderUserAndToolOrientation(sessionId, startOrdinal, endOrdinal, capTokens) {
18769
16686
  const lines = [];
18770
16687
  let tokens = 0;
18771
- for (const msg of messages) {
18772
- if (msg.ordinal < startOrdinal || msg.ordinal > endOrdinal)
18773
- continue;
16688
+ let sawMessage = false;
16689
+ visitRawSessionMessages2(sessionId, startOrdinal, endOrdinal, (msg) => {
16690
+ sawMessage = true;
18774
16691
  const out = [];
18775
16692
  if (msg.role === "user" && hasMeaningfulUserText2(msg.parts)) {
18776
16693
  const text = extractTexts2(msg.parts).map((t) => cleanUserText2(t)).map(normalizeText).filter((t) => t.length > 0).join(" / ");
@@ -18783,22 +16700,27 @@ function renderUserAndToolOrientation(messages, startOrdinal, endOrdinal, capTok
18783
16700
  const lineTokens = estimateTokens(line);
18784
16701
  if (tokens + lineTokens > capTokens && lines.length > 0) {
18785
16702
  lines.push("… (orientation truncated; investigate the current source directly)");
18786
- return lines.join(`
18787
- `);
16703
+ return false;
18788
16704
  }
18789
16705
  lines.push(line);
18790
16706
  tokens += lineTokens;
18791
16707
  }
18792
- }
18793
- return lines.join(`
18794
- `);
16708
+ return true;
16709
+ }, { summary: true });
16710
+ return sawMessage ? lines.join(`
16711
+ `) : null;
16712
+ }
16713
+ function selectPrimerOriginCandidate(db, primer) {
16714
+ return getPrimerCandidatesByIds(db, primer.sourceCandidateIds).filter((candidate) => candidate.projectPath === primer.projectPath).sort((a, b) => b.sourceMessageTime - a.sourceMessageTime || b.id - a.id)[0];
18795
16715
  }
18796
16716
  function loadPrePostP1(db, sessionId, originStartMessage) {
18797
16717
  const origin = db.prepare("SELECT sequence FROM compartments WHERE session_id = ? AND start_message = ? ORDER BY sequence ASC LIMIT 1").get(sessionId, originStartMessage);
18798
16718
  if (typeof origin?.sequence !== "number")
18799
16719
  return "";
18800
16720
  const originSeq = origin.sequence;
18801
- const rows = db.prepare(`SELECT sequence, start_message, end_message, title, p1, content
16721
+ const rows = db.prepare(`SELECT sequence, start_message, end_message,
16722
+ substr(title, 1, 512) AS title,
16723
+ substr(p1, 1, 1200) AS p1, substr(content, 1, 1200) AS content
18802
16724
  FROM compartments
18803
16725
  WHERE session_id = ? AND sequence IN (?, ?)
18804
16726
  ORDER BY sequence ASC`).all(sessionId, originSeq - 1, originSeq + 1);
@@ -18812,28 +16734,28 @@ function loadPrePostP1(db, sessionId, originStartMessage) {
18812
16734
  `);
18813
16735
  }
18814
16736
  function closedBookOriginP1(db, sessionId, originStartMessage) {
18815
- const row = db.prepare("SELECT title, p1, content FROM compartments WHERE session_id = ? AND start_message = ? ORDER BY sequence ASC LIMIT 1").get(sessionId, originStartMessage);
16737
+ const row = db.prepare(`SELECT substr(title, 1, 512) AS title,
16738
+ substr(p1, 1, 2000) AS p1, substr(content, 1, 2000) AS content
16739
+ FROM compartments WHERE session_id = ? AND start_message = ? ORDER BY sequence ASC LIMIT 1`).get(sessionId, originStartMessage);
18816
16740
  const body = (row?.p1 ?? row?.content ?? "").slice(0, 2000);
18817
16741
  const orientation = row?.title ? `${row.title}: ${body}` : body;
18818
16742
  return { orientation, sessionId };
18819
16743
  }
18820
16744
  function buildPrimerSeed(db, primer) {
18821
- const candidates = getPrimerCandidatesByIds(db, primer.sourceCandidateIds);
18822
- const mostRecent = candidates.slice().sort((a, b) => b.sourceMessageTime - a.sourceMessageTime || b.id - a.id)[0];
16745
+ const mostRecent = selectPrimerOriginCandidate(db, primer);
18823
16746
  if (!mostRecent || typeof mostRecent.sourceCompartmentStart !== "number" || typeof mostRecent.sourceCompartmentEnd !== "number") {
18824
16747
  return { kind: "closed-book", orientation: "", prePost: "", sessionId: null };
18825
16748
  }
18826
16749
  const sessionId = mostRecent.sessionId;
18827
16750
  const start = mostRecent.sourceCompartmentStart;
18828
16751
  const end = mostRecent.sourceCompartmentEnd;
18829
- let raw = [];
16752
+ let orientation = null;
18830
16753
  try {
18831
- raw = readRawSessionMessages2(sessionId);
16754
+ orientation = renderUserAndToolOrientation(sessionId, start, end, PRIMER_SEED_CAP_TOKENS);
18832
16755
  } catch {
18833
- raw = [];
16756
+ orientation = null;
18834
16757
  }
18835
- const inRange = raw.some((m) => m.ordinal >= start && m.ordinal <= end);
18836
- if (!inRange) {
16758
+ if (orientation === null) {
18837
16759
  const closed = closedBookOriginP1(db, sessionId, start);
18838
16760
  return {
18839
16761
  kind: "closed-book",
@@ -18842,7 +16764,6 @@ function buildPrimerSeed(db, primer) {
18842
16764
  sessionId
18843
16765
  };
18844
16766
  }
18845
- const orientation = renderUserAndToolOrientation(raw, start, end, PRIMER_SEED_CAP_TOKENS);
18846
16767
  return {
18847
16768
  kind: "raw",
18848
16769
  orientation,
@@ -19076,9 +16997,7 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
19076
16997
  }
19077
16998
  }
19078
16999
  function originSessionIdForPrimer(args, primer) {
19079
- const candidates = getPrimerCandidatesByIds(args.db, primer.sourceCandidateIds);
19080
- const mostRecent = candidates.slice().sort((a, b) => b.sourceMessageTime - a.sourceMessageTime || b.id - a.id)[0];
19081
- return mostRecent?.sessionId ?? null;
17000
+ return selectPrimerOriginCandidate(args.db, primer)?.sessionId ?? null;
19082
17001
  }
19083
17002
  function recordInvocation3(args, startedAt, params) {
19084
17003
  if (!args.parentSessionId)
@@ -19461,7 +17380,7 @@ function evaluateTaskGate(task, ctx) {
19461
17380
  }
19462
17381
 
19463
17382
  // src/features/magic-context/dreamer/verify.ts
19464
- import { createHash as createHash9 } from "node:crypto";
17383
+ import { createHash as createHash8 } from "node:crypto";
19465
17384
 
19466
17385
  // src/features/magic-context/dreamer/verify-gate.ts
19467
17386
  import path4 from "node:path";
@@ -20048,7 +17967,7 @@ async function applyParsedVerifyManifest(args, batch, parsed) {
20048
17967
  memory_project: args.projectIdentity,
20049
17968
  context_store_uuid: args.moduleRoute.moduleContextStoreUuid,
20050
17969
  authority_generation: args.moduleRoute.moduleAuthorityGeneration,
20051
- command_id: `${args.moduleRoute.moduleCommandId}:${createHash9("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
17970
+ command_id: `${args.moduleRoute.moduleCommandId}:${createHash8("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
20052
17971
  rows
20053
17972
  }
20054
17973
  }
@@ -20740,7 +18659,7 @@ function parseFrictionGateVerdict(verdict) {
20740
18659
  }
20741
18660
  function computeRetrospectiveWindowKey(flagged) {
20742
18661
  const anchors = flagged.map((message) => `${message.sessionId}:${message.ts}`).sort().join("|");
20743
- return createHash10("sha256").update(anchors).digest("hex").slice(0, 32);
18662
+ return createHash9("sha256").update(anchors).digest("hex").slice(0, 32);
20744
18663
  }
20745
18664
  function renderFrictionWindow(messages, flaggedOrdinals, radius = 2) {
20746
18665
  const flagged = new Set(flaggedOrdinals);
@@ -21122,8 +19041,8 @@ async function runAgenticTask(config, ctx, helpers) {
21122
19041
  } catch {}
21123
19042
  const changes = task === "maintain-docs" ? docsChangeSet(docsDir, anchor) : null;
21124
19043
  const existingDocs = task === "maintain-docs" ? {
21125
- architecture: existsSync11(`${docsDir}/ARCHITECTURE.md`),
21126
- structure: existsSync11(`${docsDir}/STRUCTURE.md`)
19044
+ architecture: existsSync8(`${docsDir}/ARCHITECTURE.md`),
19045
+ structure: existsSync8(`${docsDir}/STRUCTURE.md`)
21127
19046
  } : undefined;
21128
19047
  const abortController = new AbortController;
21129
19048
  let leaseLost = false;
@@ -21563,6 +19482,8 @@ async function runManualDream(deps) {
21563
19482
  backlogBefore: {},
21564
19483
  backlogAfter: {}
21565
19484
  };
19485
+ if (!isUsableProjectIdentity(deps.projectIdentity))
19486
+ return result;
21566
19487
  let selected;
21567
19488
  let forceGate = false;
21568
19489
  if (deps.task) {
@@ -21636,6 +19557,8 @@ async function runManualDream(deps) {
21636
19557
  return result;
21637
19558
  }
21638
19559
  async function runDueTasksForProject(deps) {
19560
+ if (!isUsableProjectIdentity(deps.projectIdentity))
19561
+ return 0;
21639
19562
  const now = deps.now ?? Date.now();
21640
19563
  const due = planDueTasks(deps.db, deps.projectIdentity, deps.tasks, now);
21641
19564
  if (due.length === 0)
@@ -22068,7 +19991,7 @@ var startupJitters = new Map;
22068
19991
  var nextStartupJitterSlot = 0;
22069
19992
  function directoryStillExists(directory) {
22070
19993
  try {
22071
- return statSync5(directory).isDirectory();
19994
+ return statSync3(directory).isDirectory();
22072
19995
  } catch {
22073
19996
  return false;
22074
19997
  }
@@ -22087,6 +20010,13 @@ function openTimerDatabaseOrNull(context) {
22087
20010
  }
22088
20011
  return db;
22089
20012
  }
20013
+ var refusedEmptyIdentityDirectories = new Set;
20014
+ function logEmptyIdentityRefusalOnce(directory) {
20015
+ if (refusedEmptyIdentityDirectories.has(directory))
20016
+ return;
20017
+ refusedEmptyIdentityDirectories.add(directory);
20018
+ log(`[dreamer] not registering ${directory}: it has no project identity, so no project-scoped work runs for it`);
20019
+ }
22090
20020
  var registeredProjects = new Map;
22091
20021
  function stopDreamScheduleTimerIfIdle() {
22092
20022
  if (registeredProjects.size !== 0)
@@ -22106,6 +20036,10 @@ function stopDreamScheduleTimerIfIdle() {
22106
20036
  log("[dreamer] stopped dream schedule timer (no projects left)");
22107
20037
  }
22108
20038
  async function startDreamScheduleTimer(args) {
20039
+ if (!isUsableProjectIdentity(args.projectIdentity)) {
20040
+ logEmptyIdentityRefusalOnce(args.directory);
20041
+ return;
20042
+ }
22109
20043
  beginBootQuietPeriod();
22110
20044
  const db = openTimerDatabaseOrNull("schedule timer registration");
22111
20045
  if (!db)
@@ -22486,7 +20420,7 @@ function createDreamTimerModuleClient(moduleClient) {
22486
20420
  }
22487
20421
 
22488
20422
  // src/plugin/embedding-bootstrap-helpers.ts
22489
- import { createHash as createHash11 } from "node:crypto";
20423
+ import { createHash as createHash10 } from "node:crypto";
22490
20424
  var EMBEDDING_AFFECTING_KEYS = new Set([
22491
20425
  "embedding.api_key",
22492
20426
  "embedding.endpoint",
@@ -22534,7 +20468,7 @@ var EMBEDDING_WARNING_TERMS = [
22534
20468
  ];
22535
20469
  var loggedFailureSignatures = new Map;
22536
20470
  function sha256Prefix(value, length = 16) {
22537
- return createHash11("sha256").update(value).digest("hex").slice(0, length);
20471
+ return createHash10("sha256").update(value).digest("hex").slice(0, length);
22538
20472
  }
22539
20473
  function warningLooksEmbeddingRelated(message) {
22540
20474
  const lower = message.toLowerCase();
@@ -22788,6 +20722,40 @@ function createCompactionHandler() {
22788
20722
  };
22789
20723
  }
22790
20724
 
20725
+ // src/shared/model-cache-ttl.ts
20726
+ var MODEL_CACHE_LIFETIMES = [
20727
+ {
20728
+ source: "OpenAI GPT-5.6+ default",
20729
+ value: "30m",
20730
+ matches(model) {
20731
+ const version = /^gpt-(\d+)(?:\.(\d+))?(?:$|[^\d.])/.exec(model);
20732
+ if (!version)
20733
+ return false;
20734
+ const major = Number(version[1]);
20735
+ const minor = Number(version[2] ?? 0);
20736
+ return major > 5 || major === 5 && minor >= 6;
20737
+ }
20738
+ }
20739
+ ];
20740
+ function resolveModelCacheTtl(config, modelKey) {
20741
+ if (config && typeof config !== "string") {
20742
+ const match = modelKey && !modelKey.includes("/") && Object.hasOwn(config, modelKey) && modelKey !== "default" ? config[modelKey] : resolveModelConfigValue(config, modelKey)?.value;
20743
+ if (match !== undefined)
20744
+ return { value: match, source: "config", modelKey };
20745
+ }
20746
+ if (typeof config === "string" && config !== "5m")
20747
+ return { value: config, source: "config", modelKey };
20748
+ const model = canonicalModelIdentity(modelKey ?? "").toLowerCase().split("/").at(-1) ?? "";
20749
+ const known = MODEL_CACHE_LIFETIMES.find((entry) => entry.matches(model));
20750
+ if (known)
20751
+ return { value: known.value, source: known.source, modelKey };
20752
+ return {
20753
+ value: (typeof config === "object" ? config.default : config) ?? "5m",
20754
+ source: "default",
20755
+ modelKey
20756
+ };
20757
+ }
20758
+
22791
20759
  // src/hooks/magic-context/event-resolvers.ts
22792
20760
  var DEFAULT_CONTEXT_LIMIT = 200000;
22793
20761
  function modelMatchedPersistedUsage(db, sessionID, modelKey) {
@@ -22903,12 +20871,6 @@ function resolveTrustedContextLimit(providerID, modelID, ctx) {
22903
20871
  const persisted = modelMatchedPersistedUsage(ctx?.db, ctx?.sessionID, modelKey);
22904
20872
  return isSaneLimit(persisted?.lastUsageContextLimit) ? persisted.lastUsageContextLimit : undefined;
22905
20873
  }
22906
- function resolveCacheTtl(cacheTtl, modelKey) {
22907
- if (typeof cacheTtl === "string") {
22908
- return cacheTtl;
22909
- }
22910
- return resolveModelConfigOrDefault(cacheTtl, modelKey, cacheTtl.default ?? "5m");
22911
- }
22912
20874
  var clampWarnSeen = new Set;
22913
20875
  function isFinitePositive(v) {
22914
20876
  return typeof v === "number" && Number.isFinite(v) && v > 0;
@@ -23495,7 +21457,7 @@ function describeStorageUnavailability(fallbackCause) {
23495
21457
  import { randomUUID as randomUUID4 } from "node:crypto";
23496
21458
  import { once } from "node:events";
23497
21459
  import { chmodSync, createWriteStream, mkdirSync as mkdirSync3, rmSync as rmSync3 } from "node:fs";
23498
- import { join as join9 } from "node:path";
21460
+ import { join as join8 } from "node:path";
23499
21461
 
23500
21462
  // src/features/magic-context/memory/memory-diagnostics.ts
23501
21463
  function emptyMemoryImportanceHistogram() {
@@ -23761,6 +21723,33 @@ function clearSessionTracking(sessionId) {
23761
21723
  }
23762
21724
  }
23763
21725
 
21726
+ // src/features/magic-context/session-cache-ttl.ts
21727
+ function readSessionCacheTtl(db, sessionId) {
21728
+ const saved = readReplayDocument(db, sessionId).cacheTtlPolicy;
21729
+ return saved && typeof saved.value === "string" && saved.config !== undefined ? saved : undefined;
21730
+ }
21731
+ function resolveSessionCacheTtl(db, sessionId, config, modelKey) {
21732
+ const meta = getOrCreateSessionMeta(db, sessionId);
21733
+ let saved = readSessionCacheTtl(db, sessionId);
21734
+ if (!modelKey)
21735
+ return saved ?? resolveModelCacheTtl(config ?? meta.cacheTtl, undefined);
21736
+ if (!saved || saved.modelKey !== modelKey) {
21737
+ const frozenConfig = saved?.config ?? config ?? meta.cacheTtl;
21738
+ const resolved = resolveModelCacheTtl(frozenConfig, modelKey);
21739
+ const next = { ...resolved, config: frozenConfig };
21740
+ if (!updateReplayDocument(db, sessionId, (doc) => {
21741
+ doc.version = 2;
21742
+ doc.cacheTtlPolicy = next;
21743
+ return true;
21744
+ }))
21745
+ throw new Error("cannot persist session cache TTL policy");
21746
+ saved = next;
21747
+ }
21748
+ if (meta.cacheTtl !== saved.value)
21749
+ updateSessionMeta(db, sessionId, { cacheTtl: saved.value });
21750
+ return saved;
21751
+ }
21752
+
23764
21753
  // src/features/magic-context/work-metrics.ts
23765
21754
  var NULL_AGENT_KEY = "\x00__null_agent__";
23766
21755
  function emptyWorkMetricsCarry() {
@@ -24169,7 +22158,7 @@ function containsProbeVerbatim(text, probes) {
24169
22158
  }
24170
22159
 
24171
22160
  // src/features/magic-context/search-measurement.ts
24172
- import { createHash as createHash12 } from "node:crypto";
22161
+ import { createHash as createHash11 } from "node:crypto";
24173
22162
  function resultId(result) {
24174
22163
  switch (result.source) {
24175
22164
  case "memory":
@@ -24256,7 +22245,7 @@ async function recordShadowMeasurement(args) {
24256
22245
  }
24257
22246
  }
24258
22247
  function sha256(value) {
24259
- return createHash12("sha256").update(value).digest("hex");
22248
+ return createHash11("sha256").update(value).digest("hex");
24260
22249
  }
24261
22250
 
24262
22251
  // src/features/magic-context/search.ts
@@ -26324,11 +24313,11 @@ function resolveCtxReduceAvailabilityFromMessages(sessionId, messages) {
26324
24313
  function resolveCtxReduceAvailability(sessionId) {
26325
24314
  return resolveToolAvailability(sessionId, CTX_REDUCE_TOOL);
26326
24315
  }
26327
- function isRecord4(value) {
24316
+ function isRecord3(value) {
26328
24317
  return value !== null && typeof value === "object" && !Array.isArray(value);
26329
24318
  }
26330
24319
  function responseData(value) {
26331
- if (isRecord4(value) && Object.hasOwn(value, "data"))
24320
+ if (isRecord3(value) && Object.hasOwn(value, "data"))
26332
24321
  return value.data;
26333
24322
  return value;
26334
24323
  }
@@ -26374,13 +24363,13 @@ function permissionRules(value) {
26374
24363
  if (Array.isArray(value)) {
26375
24364
  const result = [];
26376
24365
  for (const item of value) {
26377
- if (!isRecord4(item))
24366
+ if (!isRecord3(item))
26378
24367
  continue;
26379
24368
  appendPermissionRule(result, item.permission ?? item.tool ?? item.name, item.pattern, item.action ?? item.value);
26380
24369
  }
26381
24370
  return result;
26382
24371
  }
26383
- if (!isRecord4(value))
24372
+ if (!isRecord3(value))
26384
24373
  return [];
26385
24374
  const result = [];
26386
24375
  if (Array.isArray(value.rules))
@@ -26393,7 +24382,7 @@ function permissionRules(value) {
26393
24382
  appendPermissionRule(result, permission, "*", simpleAction);
26394
24383
  continue;
26395
24384
  }
26396
- if (!isRecord4(configured))
24385
+ if (!isRecord3(configured))
26397
24386
  continue;
26398
24387
  for (const [pattern, action] of Object.entries(configured)) {
26399
24388
  appendPermissionRule(result, permission, pattern, action);
@@ -26402,7 +24391,7 @@ function permissionRules(value) {
26402
24391
  return result;
26403
24392
  }
26404
24393
  function activeAgentNameFromSession(value) {
26405
- if (!isRecord4(value))
24394
+ if (!isRecord3(value))
26406
24395
  return;
26407
24396
  const agent = value.agent;
26408
24397
  return typeof agent === "string" && agent.length > 0 ? agent : undefined;
@@ -26419,9 +24408,9 @@ async function resolveToolPermissionDenied(client, sessionId, toolName, activeAg
26419
24408
  const agents = responseData(agentsResponse);
26420
24409
  const session = responseData(sessionResponse);
26421
24410
  const agentName = activeAgent ?? activeAgentNameFromSession(session);
26422
- const agent = Array.isArray(agents) ? agents.find((candidate) => isRecord4(candidate) && candidate.name === agentName) : undefined;
26423
- const agentRules = permissionRules(isRecord4(agent) ? agent.permission : undefined);
26424
- const sessionRules = permissionRules(isRecord4(session) ? session.permission ?? session.permissions : undefined);
24411
+ const agent = Array.isArray(agents) ? agents.find((candidate) => isRecord3(candidate) && candidate.name === agentName) : undefined;
24412
+ const agentRules = permissionRules(isRecord3(agent) ? agent.permission : undefined);
24413
+ const sessionRules = permissionRules(isRecord3(session) ? session.permission ?? session.permissions : undefined);
26425
24414
  const denied = permissionDisabled(toolName, [...agentRules, ...sessionRules]);
26426
24415
  permissionDeniedBySession.set(permissionCacheKey(toolName, sessionId), denied);
26427
24416
  return denied;
@@ -26755,6 +24744,8 @@ function summarizeManualDream(summary) {
26755
24744
 
26756
24745
  // src/shared/cache-ttl-display.ts
26757
24746
  function resolveCacheTtlDisplay(args) {
24747
+ if (args.frozen)
24748
+ return args.frozen;
26758
24749
  if (args.sessionModelKey && (!args.modelKey || args.sessionModelKey === args.modelKey) || !args.modelKey && !args.sessionModelKey && args.sessionValue !== "5m") {
26759
24750
  return {
26760
24751
  value: args.sessionValue || "5m",
@@ -26762,24 +24753,14 @@ function resolveCacheTtlDisplay(args) {
26762
24753
  modelKey: args.modelKey ?? args.sessionModelKey ?? undefined
26763
24754
  };
26764
24755
  }
26765
- if (typeof args.configured === "string") {
26766
- return {
26767
- value: args.configured,
26768
- source: args.configuredExplicitly ? "config" : "default",
26769
- modelKey: args.modelKey
26770
- };
26771
- }
26772
- const matched = resolveModelConfigValue(args.configured, args.modelKey);
26773
- if (matched) {
26774
- return { value: matched.value, source: "config", modelKey: args.modelKey };
26775
- }
26776
- return {
26777
- value: args.configured.default ?? "5m",
26778
- source: "default",
26779
- modelKey: args.modelKey
26780
- };
24756
+ const resolved = resolveModelCacheTtl(args.configured, args.modelKey);
24757
+ if (resolved.source === "default" && typeof args.configured === "string" && args.configuredExplicitly)
24758
+ return { ...resolved, source: "config" };
24759
+ return resolved;
26781
24760
  }
26782
24761
  function formatCacheTtlDisplay(display) {
24762
+ if (display.source === "OpenAI GPT-5.6+ default")
24763
+ return `Cache TTL: ${display.value} (${display.source})`;
26783
24764
  if (display.source === "session")
26784
24765
  return `Cache TTL: ${display.value} (session)`;
26785
24766
  if (display.source === "config") {
@@ -27378,6 +25359,7 @@ function executeStatus(db, sessionId, executeThresholdPercentageConfig = DEFAULT
27378
25359
  const droppedTags = tags.filter((t) => t.status === "dropped");
27379
25360
  const totalBytes = activeTags.reduce((sum, t) => sum + t.byteSize, 0);
27380
25361
  const ttlDisplay = resolveCacheTtlDisplay({
25362
+ frozen: readSessionCacheTtl(db, sessionId),
27381
25363
  configured: display?.cacheTtlConfig ?? "5m",
27382
25364
  configuredExplicitly: display?.cacheTtlConfigured === true,
27383
25365
  modelKey: liveModelKey,
@@ -30975,6 +28957,7 @@ function buildStatusDetail(db, sessionId, directory, modelKey, config, liveSessi
30975
28957
  detail.executeThresholdTokens = thresholdDetail.absoluteTokens;
30976
28958
  }
30977
28959
  const ttlDisplay = resolveCacheTtlDisplay({
28960
+ frozen: readSessionCacheTtl(db, sessionId),
30978
28961
  configured: config.cache_ttl ?? "5m",
30979
28962
  configuredExplicitly: config.cacheTtlConfigured === true,
30980
28963
  modelKey,
@@ -31216,11 +29199,11 @@ async function generateDebugHeapSnapshot(storageDir, memory) {
31216
29199
  if (rssBytes > maxRssBytes) {
31217
29200
  throw new Error(`heap snapshot refused: process rss ${Math.round(rssBytes / (1024 * 1024))} MiB exceeds the ${Math.round(maxRssBytes / (1024 * 1024))} MiB ceiling (MAGIC_CONTEXT_DEBUG_HEAP_SNAPSHOT_MAX_RSS_MB); use debug.memoryUsage instead`);
31218
29201
  }
31219
- const directory = join9(storageDir, "heap-snapshots");
29202
+ const directory = join8(storageDir, "heap-snapshots");
31220
29203
  const enforcePrivatePermissions = shouldEnforcePrivateStoragePermissions();
31221
29204
  mkdirSync3(directory, enforcePrivatePermissions ? { recursive: true, mode: 448 } : { recursive: true });
31222
29205
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
31223
- const path = join9(directory, `${timestamp}-${process.pid}.heapsnapshot`);
29206
+ const path = join8(directory, `${timestamp}-${process.pid}.heapsnapshot`);
31224
29207
  let format = "jsc";
31225
29208
  let snapshotVersion;
31226
29209
  let snapshot;
@@ -31331,7 +29314,7 @@ function registerRpcHandlers(rpcServer, args) {
31331
29314
  return { count: buildCompartmentCount(db, sessionId, moduleStatus) };
31332
29315
  });
31333
29316
  const buildManagedCtx = async (db) => {
31334
- const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await import("./derive-budgets-8kgevxmx.js");
29317
+ const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await import("./derive-budgets-gd2270s0.js");
31335
29318
  const { resolveHistorianModel } = await import("./model-resolution-dxatzjde.js");
31336
29319
  const { userMemoryCollectionEnabled } = await import("./task-config-mgf5nsh3.js");
31337
29320
  const DEFAULT_HISTORIAN_TIMEOUT_MS = 600000;
@@ -31365,8 +29348,8 @@ function registerRpcHandlers(rpcServer, args) {
31365
29348
  const db = getDb();
31366
29349
  if (!db)
31367
29350
  return { ok: false, error: "db unavailable" };
31368
- const { runManagedRecomp } = await import("./recomp-orchestrator-ahekzt0s.js");
31369
- const { sendIgnoredMessage } = await import("./send-session-notification-w7xbnrsm.js");
29351
+ const { runManagedRecomp } = await import("./recomp-orchestrator-k4h5n0p3.js");
29352
+ const { sendIgnoredMessage } = await import("./send-session-notification-g2k03zyn.js");
31370
29353
  log(`[rpc] recomp requested for session ${sessionId}`);
31371
29354
  const ctx = await buildManagedCtx(db);
31372
29355
  runManagedRecomp(ctx, sessionId).then((message) => {
@@ -31424,7 +29407,7 @@ function registerRpcHandlers(rpcServer, args) {
31424
29407
  const db = getDb();
31425
29408
  if (!db)
31426
29409
  return { ok: false, error: "db unavailable" };
31427
- const { runManagedWrapup } = await import("./wrapup-orchestrator-9srk0kjf.js");
29410
+ const { runManagedWrapup } = await import("./wrapup-orchestrator-35y56636.js");
31428
29411
  const model = liveSessionState.liveModelBySession.get(sessionId);
31429
29412
  const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
31430
29413
  const ctx = {
@@ -32252,7 +30235,7 @@ function replayCavemanCompression(sessionId, db, targets, tags) {
32252
30235
  }
32253
30236
 
32254
30237
  // src/hooks/magic-context/compaction-off-transition.ts
32255
- import { existsSync as existsSync13 } from "node:fs";
30238
+ import { existsSync as existsSync10 } from "node:fs";
32256
30239
  var loggedUnverifiedMarkerCleanupRetry = false;
32257
30240
  var COMPACTION_OFF_FLIP_NOTICE = [
32258
30241
  "## Magic Context — compaction-off mode is now active",
@@ -32287,7 +30270,7 @@ function clearCachedM0Baseline(db, sessionId) {
32287
30270
  return (result.changes ?? 0) > 0;
32288
30271
  }
32289
30272
  function cleanupOffMarkers(sessionId) {
32290
- if (!existsSync13(getOpenCodeDbPath())) {
30273
+ if (!existsSync10(getOpenCodeDbPath())) {
32291
30274
  return { verified: true, removedLineages: 0, removedRows: 0, retainedLineages: 0 };
32292
30275
  }
32293
30276
  return removeMcOwnedCompactionMarkers(sessionId, MARKER_SUMMARY_TEXT);
@@ -33120,7 +31103,7 @@ function createPassOutcome() {
33120
31103
  }
33121
31104
 
33122
31105
  // src/hooks/magic-context/rust-mode-transform.ts
33123
- import { createHash as createHash14, randomUUID as randomUUID6 } from "node:crypto";
31106
+ import { createHash as createHash13, randomUUID as randomUUID6 } from "node:crypto";
33124
31107
 
33125
31108
  // src/features/magic-context/memory/mirror-reembed.ts
33126
31109
  async function reembedMirrorInvalidatedMemories(db) {
@@ -33222,11 +31205,11 @@ function ensureInstallInstanceId(db) {
33222
31205
  var CLAIM_START_MARGIN_MS = 5000;
33223
31206
  var IDLE_INTERVAL_MS = 30000;
33224
31207
  var IDLE_POLLS_AFTER_PASS = 3;
33225
- function isRecord5(value) {
31208
+ function isRecord4(value) {
33226
31209
  return typeof value === "object" && value !== null;
33227
31210
  }
33228
31211
  function refusalOf(response) {
33229
- if (!isRecord5(response))
31212
+ if (!isRecord4(response))
33230
31213
  return "malformed_response";
33231
31214
  if (response.ok === true)
33232
31215
  return null;
@@ -33234,11 +31217,11 @@ function refusalOf(response) {
33234
31217
  return typeof refusal === "string" && refusal.length > 0 ? refusal : "malformed_response";
33235
31218
  }
33236
31219
  function readPendingRuns(response) {
33237
- if (!isRecord5(response) || !Array.isArray(response.runs))
31220
+ if (!isRecord4(response) || !Array.isArray(response.runs))
33238
31221
  return [];
33239
31222
  const runs = [];
33240
31223
  for (const entry of response.runs) {
33241
- if (!isRecord5(entry))
31224
+ if (!isRecord4(entry))
33242
31225
  continue;
33243
31226
  const runId = entry.run_id;
33244
31227
  const sessionId = entry.session_id;
@@ -33255,9 +31238,9 @@ function readPendingRuns(response) {
33255
31238
  return runs;
33256
31239
  }
33257
31240
  function readClaim(response) {
33258
- if (!isRecord5(response) || response.ok !== true)
31241
+ if (!isRecord4(response) || response.ok !== true)
33259
31242
  return null;
33260
- const prompt = isRecord5(response.prompt) ? response.prompt : {};
31243
+ const prompt = isRecord4(response.prompt) ? response.prompt : {};
33261
31244
  const runId = response.run_id;
33262
31245
  const sessionId = response.session_id;
33263
31246
  const token = response.token;
@@ -33638,7 +31621,7 @@ class HistorianHostRunner {
33638
31621
  this.log(`report for ${claim.runId} refused: ${refusal}`);
33639
31622
  return;
33640
31623
  }
33641
- const publish = isRecord5(response) && typeof response.publish === "string" ? response.publish : "immediate";
31624
+ const publish = isRecord4(response) && typeof response.publish === "string" ? response.publish : "immediate";
33642
31625
  this.log(`report for ${claim.runId} accepted (publish=${publish})`);
33643
31626
  }
33644
31627
  schedule(callback, delayMs) {
@@ -37651,20 +35634,20 @@ function rustWireCacheEstimatedBytes(cache) {
37651
35634
  }
37652
35635
  return bytes;
37653
35636
  }
37654
- function isRecord6(value) {
35637
+ function isRecord5(value) {
37655
35638
  return value !== null && typeof value === "object";
37656
35639
  }
37657
35640
  function moduleFailureCode(error) {
37658
35641
  let current = error;
37659
35642
  const seen = new Set;
37660
- while (isRecord6(current) && !seen.has(current)) {
35643
+ while (isRecord5(current) && !seen.has(current)) {
37661
35644
  seen.add(current);
37662
35645
  if (typeof current.code === "string" && current.code.length > 0)
37663
35646
  return current.code;
37664
35647
  if (typeof current.message === "string") {
37665
35648
  try {
37666
35649
  const detail = JSON.parse(current.message);
37667
- if (isRecord6(detail) && typeof detail.code === "string")
35650
+ if (isRecord5(detail) && typeof detail.code === "string")
37668
35651
  return detail.code;
37669
35652
  } catch {}
37670
35653
  }
@@ -37682,9 +35665,9 @@ function replaceMessagesInPlace(output, next) {
37682
35665
  return target;
37683
35666
  }
37684
35667
  function messageInfo2(value) {
37685
- if (!isRecord6(value))
35668
+ if (!isRecord5(value))
37686
35669
  return {};
37687
- return isRecord6(value.info) ? value.info : value;
35670
+ return isRecord5(value.info) ? value.info : value;
37688
35671
  }
37689
35672
  function messageIdOf(message) {
37690
35673
  const id = messageInfo2(message).id;
@@ -37745,10 +35728,10 @@ function messageCacheSignature(message) {
37745
35728
  const parts = Array.isArray(message.parts) ? message.parts : [];
37746
35729
  const serializedParts = JSON.stringify(parts) ?? "null";
37747
35730
  const serializedMessage = JSON.stringify(message) ?? "null";
37748
- return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${createHash14("sha256").update(serializedMessage).digest("hex")}`;
35731
+ return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${createHash13("sha256").update(serializedMessage).digest("hex")}`;
37749
35732
  }
37750
35733
  function advanceWireFingerprint(previous, encoded) {
37751
- return createHash14("sha256").update(previous).update("\\0").update(JSON.stringify(encoded) ?? "null").digest("hex");
35734
+ return createHash13("sha256").update(previous).update("\\0").update(JSON.stringify(encoded) ?? "null").digest("hex");
37752
35735
  }
37753
35736
  function buildWireFingerprint(encoded) {
37754
35737
  let fingerprint = "rust-wire-v1";
@@ -37852,7 +35835,7 @@ function isSyntheticUserMessage(message) {
37852
35835
  if (!message || messageInfo2(message).role !== "user" || !Array.isArray(message.parts)) {
37853
35836
  return false;
37854
35837
  }
37855
- return message.parts.length > 0 && message.parts.every((part) => isRecord6(part) && (part.synthetic === true || part.ignored === true));
35838
+ return message.parts.length > 0 && message.parts.every((part) => isRecord5(part) && (part.synthetic === true || part.ignored === true));
37856
35839
  }
37857
35840
  function observeSyntheticTurn(state, messages) {
37858
35841
  const newest = newestUserMessage(messages);
@@ -37872,22 +35855,22 @@ function observeSyntheticTurn(state, messages) {
37872
35855
  function assertNativeBoundary(output, sessionId, boundaryId) {
37873
35856
  const first = output.find((message) => messageInfo2(message).role !== "system");
37874
35857
  const info = messageInfo2(first);
37875
- const parts = isRecord6(first) && Array.isArray(first.parts) ? first.parts : [];
37876
- const synthetic = parts.length > 0 && parts.every((part) => isRecord6(part) && part.synthetic === true);
35858
+ const parts = isRecord5(first) && Array.isArray(first.parts) ? first.parts : [];
35859
+ const synthetic = parts.length > 0 && parts.every((part) => isRecord5(part) && part.synthetic === true);
37877
35860
  if (info.role === "user" && info.sessionID === sessionId && synthetic)
37878
35861
  return;
37879
35862
  const headSummary = output.slice(0, 3).map((message) => {
37880
35863
  const mi = messageInfo2(message);
37881
- const mParts = isRecord6(message) && Array.isArray(message.parts) ? message.parts : [];
37882
- const partDesc = mParts.slice(0, 5).map((part) => isRecord6(part) ? `${String(part.type)}${part.synthetic === true ? "" : "!"}` : "?").join(",");
35864
+ const mParts = isRecord5(message) && Array.isArray(message.parts) ? message.parts : [];
35865
+ const partDesc = mParts.slice(0, 5).map((part) => isRecord5(part) ? `${String(part.type)}${part.synthetic === true ? "" : "!"}` : "?").join(",");
37883
35866
  return `role=${String(mi.role)} sid=${mi.sessionID === sessionId ? "ok" : String(mi.sessionID ?? "absent")} id=${String(mi.id ?? "-").slice(0, 24)} parts=[${partDesc}]`;
37884
35867
  });
37885
35868
  throw new Error(`rust transform wire invariant failed: boundary=${boundaryId} expected a synthetic m0 user message scoped to session ${sessionId}; head: ${headSummary.join(" | ")}`);
37886
35869
  }
37887
35870
  function responseValue(response) {
37888
- if (isRecord6(response) && isRecord6(response.result))
35871
+ if (isRecord5(response) && isRecord5(response.result))
37889
35872
  return response.result;
37890
- if (isRecord6(response))
35873
+ if (isRecord5(response))
37891
35874
  return response;
37892
35875
  throw new Error("module transform returned a non-object response");
37893
35876
  }
@@ -37925,7 +35908,7 @@ function stateSyncInputSignature(args) {
37925
35908
  function isTransformPageAttemptMismatch(error) {
37926
35909
  let current = error;
37927
35910
  const seen = new Set;
37928
- while (isRecord6(current) && !seen.has(current)) {
35911
+ while (isRecord5(current) && !seen.has(current)) {
37929
35912
  seen.add(current);
37930
35913
  const code = typeof current.code === "string" ? current.code : "";
37931
35914
  const message = typeof current.message === "string" ? current.message : "";
@@ -37952,7 +35935,7 @@ function mirrorRustRenderedMemoryIds(args) {
37952
35935
  function modelFromMessages(messages) {
37953
35936
  for (let index = messages.length - 1;index >= 0; index -= 1) {
37954
35937
  const info = messages[index]?.info;
37955
- const model = isRecord6(info?.model) ? info.model : undefined;
35938
+ const model = isRecord5(info?.model) ? info.model : undefined;
37956
35939
  if (typeof model?.providerID === "string" && typeof model.modelID === "string") {
37957
35940
  return { providerID: model.providerID, modelID: model.modelID };
37958
35941
  }
@@ -38089,8 +36072,8 @@ function shouldDisarmRustEmergencyRecovery(input) {
38089
36072
  return null;
38090
36073
  }
38091
36074
  function directiveTextOf(response) {
38092
- const directives = isRecord6(response.host_directives) ? response.host_directives : undefined;
38093
- const channel2 = isRecord6(directives?.channel2_nudge) ? directives.channel2_nudge : undefined;
36075
+ const directives = isRecord5(response.host_directives) ? response.host_directives : undefined;
36076
+ const channel2 = isRecord5(directives?.channel2_nudge) ? directives.channel2_nudge : undefined;
38094
36077
  return typeof channel2?.text === "string" && channel2.text.length > 0 ? channel2.text : undefined;
38095
36078
  }
38096
36079
  function isNeedFullSync(response) {
@@ -38099,12 +36082,12 @@ function isNeedFullSync(response) {
38099
36082
  function canonicalizeForChecksum(value) {
38100
36083
  if (Array.isArray(value))
38101
36084
  return value.map(canonicalizeForChecksum);
38102
- if (!isRecord6(value))
36085
+ if (!isRecord5(value))
38103
36086
  return value;
38104
36087
  return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalizeForChecksum(value[key])]));
38105
36088
  }
38106
36089
  function checksumSeedRows(rows) {
38107
- return createHash14("sha256").update(JSON.stringify(rows.map(canonicalizeForChecksum))).digest("hex");
36090
+ return createHash13("sha256").update(JSON.stringify(rows.map(canonicalizeForChecksum))).digest("hex");
38108
36091
  }
38109
36092
  function authoritySeedRows(db, projectPath, domain) {
38110
36093
  const snapshots = domain === "memories" ? db.prepare("SELECT * FROM memories WHERE project_path = ? ORDER BY id ASC").all(projectPath) : db.prepare(`SELECT n.*
@@ -38115,7 +36098,7 @@ function authoritySeedRows(db, projectPath, domain) {
38115
36098
  WHERE sp.session_id = n.session_id AND sp.project_path = ?
38116
36099
  ))
38117
36100
  ORDER BY n.id ASC`).all(projectPath, projectPath);
38118
- const memoryRows = snapshots.filter(isRecord6);
36101
+ const memoryRows = snapshots.filter(isRecord5);
38119
36102
  const seededIds = new Set(memoryRows.map((row) => Number(row.id)));
38120
36103
  const mappings = domain === "memories" ? getMemoryVerifications(db, memoryRows.map((row) => Number(row.id))) : new Map;
38121
36104
  return memoryRows.map((snapshot) => {
@@ -38201,7 +36184,7 @@ async function prepareRustMemoryAuthority(args) {
38201
36184
  projectPath,
38202
36185
  domain,
38203
36186
  module: authorityModule,
38204
- checksum: () => checksumSeedRows(db.prepare(`SELECT * FROM ${domain === "memories" ? "memories" : "notes"} WHERE project_path = ? ORDER BY id ASC`).all(projectPath).filter(isRecord6))
36187
+ checksum: () => checksumSeedRows(db.prepare(`SELECT * FROM ${domain === "memories" ? "memories" : "notes"} WHERE project_path = ? ORDER BY id ASC`).all(projectPath).filter(isRecord5))
38205
36188
  });
38206
36189
  if (!("code" in drained))
38207
36190
  break;
@@ -38258,18 +36241,18 @@ var TODO_HEAD_ANCHOR_ID2 = "__magic_context_todo_head__";
38258
36241
  function syntheticTodoAnchorFromNative(messages) {
38259
36242
  for (let index = 0;index < messages.length; index += 1) {
38260
36243
  const message = messages[index];
38261
- if (!isRecord6(message) || !Array.isArray(message.parts))
36244
+ if (!isRecord5(message) || !Array.isArray(message.parts))
38262
36245
  continue;
38263
- const part = message.parts.find((candidate) => isRecord6(candidate) && candidate.syntheticTodoMarker === true);
38264
- if (!isRecord6(part) || typeof part.callID !== "string")
36246
+ const part = message.parts.find((candidate) => isRecord5(candidate) && candidate.syntheticTodoMarker === true);
36247
+ if (!isRecord5(part) || typeof part.callID !== "string")
38265
36248
  continue;
38266
- const state = isRecord6(part.state) ? part.state : undefined;
38267
- const input = state && isRecord6(state.input) ? state.input : undefined;
36249
+ const state = isRecord5(part.state) ? part.state : undefined;
36250
+ const input = state && isRecord5(state.input) ? state.input : undefined;
38268
36251
  const stateJson = normalizeTodoStateJson(input?.todos);
38269
36252
  if (stateJson === null || computeSyntheticCallId(stateJson) !== part.callID)
38270
36253
  continue;
38271
36254
  const previous = messages[index - 1];
38272
- const previousInfo = isRecord6(previous) && isRecord6(previous.info) ? previous.info : undefined;
36255
+ const previousInfo = isRecord5(previous) && isRecord5(previous.info) ? previous.info : undefined;
38273
36256
  const messageId = previousInfo && typeof previousInfo.id === "string" && previousInfo.id.length > 0 ? previousInfo.id : TODO_HEAD_ANCHOR_ID2;
38274
36257
  return { callId: part.callID, messageId, stateJson };
38275
36258
  }
@@ -38298,7 +36281,7 @@ function hasNativeResponseContent(response) {
38298
36281
  return true;
38299
36282
  }
38300
36283
  const delta = response.native_messages_delta;
38301
- return isRecord6(delta) && Array.isArray(delta.messages);
36284
+ return isRecord5(delta) && Array.isArray(delta.messages);
38302
36285
  }
38303
36286
  function applyNativeMessagesVerbatim(output, response, previous) {
38304
36287
  const nativeMessages = response.native_messages;
@@ -38312,7 +36295,7 @@ function applyNativeMessagesVerbatim(output, response, previous) {
38312
36295
  return replaceMessagesInPlace(output, nativeMessages);
38313
36296
  }
38314
36297
  const delta = response.native_messages_delta;
38315
- if (!isRecord6(delta) || !Array.isArray(delta.messages)) {
36298
+ if (!isRecord5(delta) || !Array.isArray(delta.messages)) {
38316
36299
  throw new Error("rust transform response omitted native_messages");
38317
36300
  }
38318
36301
  const replaceFrom = delta.replace_from;
@@ -38522,7 +36505,7 @@ function createRustModeTransform(deps, options) {
38522
36505
  };
38523
36506
  const callModule = async (args, attemptTimeoutMs = args.timeoutMs ?? timeoutMs) => {
38524
36507
  const controller = new AbortController;
38525
- const body = isRecord6(args.body) ? args.body : {};
36508
+ const body = isRecord5(args.body) ? args.body : {};
38526
36509
  const timeoutError = args.method === "state_sync" ? Object.assign(new Error(`state_sync timeout stage=module_ack page=${body.seed_batch_index ?? 0}/${body.seed_batch_total ?? 1} series=${body.seed_id ?? "delta"} budget_ms=${attemptTimeoutMs}`), {
38527
36510
  code: "state_sync_timeout",
38528
36511
  stage: "module_ack",
@@ -38551,7 +36534,7 @@ function createRustModeTransform(deps, options) {
38551
36534
  const probeAfterMs = options.stallProbeAfterMsForTests ?? RUST_STALL_PROBE_AFTER_MS;
38552
36535
  const probeTimeoutMs = options.healthProbeTimeoutMsForTests ?? RUST_HEALTH_PROBE_TIMEOUT_MS;
38553
36536
  const originalAttemptId = randomUUID6();
38554
- const originalBody = isRecord6(args.body) ? { ...args.body, attempt_id: originalAttemptId } : args.body;
36537
+ const originalBody = isRecord5(args.body) ? { ...args.body, attempt_id: originalAttemptId } : args.body;
38555
36538
  const original = callModule({ ...args, body: originalBody }, attemptTimeoutMs);
38556
36539
  if (attemptTimeoutMs <= probeAfterMs)
38557
36540
  return original;
@@ -38847,6 +36830,11 @@ function createRustModeTransform(deps, options) {
38847
36830
  }
38848
36831
  }
38849
36832
  const modelKey = model ? canonicalModelIdentity(resolveModelKey(model.providerID, model.modelID) ?? "") : null;
36833
+ try {
36834
+ sessionMeta.cacheTtl = resolveSessionCacheTtl(deps.db, sessionId, deps.cacheTtlConfig, modelKey ?? undefined).value;
36835
+ } catch (error) {
36836
+ preflightError ??= error;
36837
+ }
38850
36838
  let resolvedContextLimit;
38851
36839
  let resolvedWindowGeometry;
38852
36840
  if (model) {
@@ -38949,12 +36937,12 @@ function createRustModeTransform(deps, options) {
38949
36937
  servedFrom = typeof response.served_from === "string" ? response.served_from : "unknown";
38950
36938
  schedulerDecision = typeof response.scheduler_decision === "string" ? response.scheduler_decision : undefined;
38951
36939
  schedulerDeferReason = typeof response.scheduler_defer_reason === "string" ? response.scheduler_defer_reason : undefined;
38952
- const historian = isRecord6(response.historian) ? response.historian : undefined;
36940
+ const historian = isRecord5(response.historian) ? response.historian : undefined;
38953
36941
  historianNoFire = typeof historian?.no_fire === "string" ? historian.no_fire : undefined;
38954
36942
  historianCanonicalCause = typeof historian?.canonical_cause === "string" ? historian.canonical_cause : undefined;
38955
36943
  materializeReason = typeof response.materialize_reason === "string" && response.materialize_reason.length > 0 ? response.materialize_reason : "none";
38956
36944
  identityDelta = Array.isArray(response.identity_delta) ? response.identity_delta.filter((component) => typeof component === "string" && component.length > 0) : [];
38957
- const timings = isRecord6(response.timings) ? response.timings : undefined;
36945
+ const timings = isRecord5(response.timings) ? response.timings : undefined;
38958
36946
  const applyOnceTotal = timings?.total;
38959
36947
  const handlerTotal = timings?.handler_total;
38960
36948
  moduleElapsedMs = typeof handlerTotal === "number" && Number.isFinite(handlerTotal) ? handlerTotal : typeof applyOnceTotal === "number" && Number.isFinite(applyOnceTotal) ? applyOnceTotal : 0;
@@ -39074,6 +37062,7 @@ function createRustModeTransform(deps, options) {
39074
37062
  });
39075
37063
  const passInputs = {
39076
37064
  historian_model_limits: resolvedHistorianModelLimits(historianChain),
37065
+ historian_max_output_tokens: historianRun ? historianRun.maxOutputTokens : deps.historianMaxOutputTokens,
39077
37066
  now_ms: requestObservedAtMs,
39078
37067
  model_key: modelKey,
39079
37068
  provider_id: model?.providerID ?? null,
@@ -39230,7 +37219,10 @@ function createRustModeTransform(deps, options) {
39230
37219
  deps.clearReasoningAge,
39231
37220
  deps.cavemanTextCompression
39232
37221
  ]);
39233
- const idleBudgetMs = sessionMeta.cacheTtl === "1h" ? 3600000 : 300000;
37222
+ let idleBudgetMs = 300000;
37223
+ try {
37224
+ idleBudgetMs = parseCacheTtl(sessionMeta.cacheTtl);
37225
+ } catch {}
39234
37226
  const todoProbeSignals = {
39235
37227
  cold: !state.initialized,
39236
37228
  missing_verdict: getPersistedTodoPermissionDenied(deps.db, sessionId) === null,
@@ -39602,7 +37594,7 @@ function createRustModeTransform(deps, options) {
39602
37594
  timings.todoUnprobedBust += 1;
39603
37595
  sessionLog(sessionId, `todo_permission_probe_miss decision=${decisionUpper} reason=${response.materialize_reason ?? "unknown"} verdict_stale_ok=false`);
39604
37596
  }
39605
- const deferredFirstDivergence = isRecord6(response.first_divergence) ? response.first_divergence : undefined;
37597
+ const deferredFirstDivergence = isRecord5(response.first_divergence) ? response.first_divergence : undefined;
39606
37598
  const deferredFrozenPrefixDivergence = !cacheBustingPass && [deferredFirstDivergence?.block_id_old, deferredFirstDivergence?.block_id_new].some((blockId) => blockId === "mc_m0#0" || blockId === "mc_m1#0");
39607
37599
  if (deferredFrozenPrefixDivergence) {
39608
37600
  state.lkgRepresentationFrozen = true;
@@ -39868,7 +37860,7 @@ function createRustModeTransform(deps, options) {
39868
37860
  }
39869
37861
  if (timings.todoProbe > 0)
39870
37862
  state.todoProbeIdentity = todoProbeIdentity;
39871
- state.todoProbeNextPass = response.reconcile_pending === true || isRecord6(response.historian) && response.historian.fired === true;
37863
+ state.todoProbeNextPass = response.reconcile_pending === true || isRecord5(response.historian) && response.historian.fired === true;
39872
37864
  state.lastAppliedAtMs = requestObservedAtMs;
39873
37865
  heapHolder.wireCaches.set(sessionId, pendingWireCache);
39874
37866
  timings.bookkeeping += performance.now() - bookkeepingStartedAt - timings.delivery;
@@ -40588,6 +38580,8 @@ function createTransform(deps) {
40588
38580
  let sessionMeta;
40589
38581
  try {
40590
38582
  sessionMeta = getOrCreateSessionMeta(db, sessionId);
38583
+ const ttlModel = findNewestUserModel(messages) ?? deps.liveModelBySession?.get(sessionId) ?? findLastAssistantModel(messages);
38584
+ sessionMeta.cacheTtl = resolveSessionCacheTtl(db, sessionId, deps.cacheTtlConfig, ttlModel ? `${ttlModel.providerID}/${ttlModel.modelID}` : undefined).value;
40591
38585
  } catch (error) {
40592
38586
  passOutcome.record("session-meta-early-return", "fatal");
40593
38587
  sessionLog(sessionId, "transform failed reading session meta:", error);
@@ -41142,7 +39136,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
41142
39136
  historianTimeoutMs: historianRun?.timeoutMs ?? deps.historianTimeoutMs,
41143
39137
  historianModel: historianRun?.model ?? deps.historianModel,
41144
39138
  historianContextLimit: historianRun?.contextLimit ?? deps.historianContextLimit,
41145
- historianMaxOutputTokens: historianRun?.maxOutputTokens ?? deps.historianMaxOutputTokens,
39139
+ historianMaxOutputTokens: historianRun ? historianRun.maxOutputTokens : deps.historianMaxOutputTokens,
41146
39140
  fallbackModels: historianRun?.fallbackModels ?? deps.fallbackModels,
41147
39141
  compartmentDirectory,
41148
39142
  messages,
@@ -41683,7 +39677,7 @@ function createEventHandler2(deps) {
41683
39677
  const modelKey = resolveModelKey(info.providerID, info.modelID);
41684
39678
  updateSessionMeta(deps.db, info.id, {
41685
39679
  isSubagent: info.parentID.length > 0,
41686
- cacheTtl: resolveCacheTtl(deps.config.cache_ttl, modelKey)
39680
+ cacheTtl: resolveSessionCacheTtl(deps.db, info.id, deps.config.cache_ttl, modelKey).value
41687
39681
  });
41688
39682
  } catch (error) {
41689
39683
  sessionLog(info.id, "event session.created persistence failed:", error);
@@ -41857,9 +39851,9 @@ function createEventHandler2(deps) {
41857
39851
  updates.lastResponseTime = now;
41858
39852
  }
41859
39853
  if (typeof deps.config.cache_ttl === "string") {
41860
- updates.cacheTtl = resolveCacheTtl(deps.config.cache_ttl, modelKey);
39854
+ updates.cacheTtl = resolveSessionCacheTtl(deps.db, info.sessionID, deps.config.cache_ttl, modelKey).value;
41861
39855
  } else if (modelKey) {
41862
- updates.cacheTtl = resolveCacheTtl(deps.config.cache_ttl, modelKey);
39856
+ updates.cacheTtl = resolveSessionCacheTtl(deps.db, info.sessionID, deps.config.cache_ttl, modelKey).value;
41863
39857
  }
41864
39858
  const totalInputTokens = (info.tokens?.input ?? 0) + (info.tokens?.cache?.read ?? 0) + (info.tokens?.cache?.write ?? 0);
41865
39859
  const baseGeometry = hasUsageTokens ? resolveContextWindowGeometry(info.providerID, info.modelID) : undefined;
@@ -42809,145 +40803,7 @@ function createTextCompleteHandler() {
42809
40803
  }
42810
40804
 
42811
40805
  // src/hooks/magic-context/system-prompt-hash.ts
42812
- import { createHash as createHash15 } from "node:crypto";
42813
-
42814
- // src/agents/magic-context-prompt.ts
42815
- var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
42816
-
42817
- Most AI sessions are disposable: one session per task, discarded when it's done — like hiring a developer for a single bug fix and letting them go the moment they finish. Magic Context changes this completely. This session is a durable working relationship: you carry the full history and accumulated knowledge of this project, and you continue across many tasks, bugs, and features — with memory that persists across restarts. This session may continue for weeks, months, or even years.
42818
-
42819
- Because of this:
42820
- - **Your context is continuously managed and effectively unbounded.** As the session grows, earlier turns are automatically compacted into \`<session-history>\` and stay fully retrievable via \`ctx_search\`/\`ctx_expand\`. You will not hit a context wall and you will not lose continuity mid-task.
42821
- - **High context usage is normal and fully handled** — never a reason to wrap up, cut scope, rush, or defer work. Keep going at full depth.
42822
- - **Finishing a task does not end the session.** Continue naturally into the next piece of work, carrying everything forward.
42823
- - **There are no compaction pauses.** Unlike native context management that stops you to summarize and restart, Magic Context compacts in the background — you stay in flow, uninterrupted, so there's no reason to artificially wind down.`;
42824
- var PARTNER_FRAME_CLOSER_REDUCE = `
42825
- Reduction prompts are routine housekeeping to keep the session fast and cheap — act on them as light maintenance, never as scarcity warnings. Keep individual operations efficient, but never let context size change *what* work you take on or *how thoroughly* you do it.`;
42826
- var PARTNER_FRAME_CLOSER_NO_REDUCE = `
42827
- Context is managed for you entirely automatically — there's nothing to prune and no warnings to act on. Stay reasonably concise per operation, and never let context size change *what* work you take on or *how thoroughly* you do it.`;
42828
- var PARTNER_FRAME_CLOSER_REDUCE_LIGHT = `
42829
- When ctx_reduce is available, use it only as routine housekeeping; never cut task scope or depth because context is large.`;
42830
- var PARTNER_FRAME_CLOSER_NO_REDUCE_LIGHT = `
42831
- When ctx_reduce is unavailable, context is automatic; never prune, heed reduction warnings, or cut task scope or depth because context is large.`;
42832
- var CTX_NOTE_GUIDANCE = `\`ctx_note\` is the tray for work you intend to return to, with its findings attached; findings without an intention are not a note. When the user says "take a note", it always goes in the tray.`;
42833
- var MEMORY_GUIDANCE = `\`<project-memory>\` is the pinboard: facts about this project that stay true for the months this work lasts, as \`#id: fact\` lines — for you, and for every other agent working on this project. \`ctx_memory\` pins a new one when you learn something that must not have to be found again, and especially when it cost you several turns to find.`;
42834
- var TOOL_HISTORY_GUIDANCE = `Older work is not kept on the desk at all. Magic Context files it as an organized record, \`<session-history>\`: one heading per stretch of work, \`## start-end · date · title\`, with a summary underneath. Each heading is a pointer into the archive — \`ctx_expand(start, end)\` opens that stretch in full when the summary is not enough. Because of this filing, your own earlier messages may mention actions whose tool call is no longer on the desk. That is normal. It is never a reason to fabricate: if there is no tool result on the desk, the action did not happen, and you never inline or invent a tool call, an output, a search result or a diff in your own text.`;
42835
- var SMART_NOTE_GUIDANCE = `A note with a \`surface_condition\` is left with an outside checker that looks the condition up periodically and returns the note only when it holds.`;
42836
- var TEMPORAL_AWARENESS_GUIDANCE = `, and \`<!-- +Xm -->\` before a user message (the time that passed since your last reply; headings in the record carry \`start-date\`/\`end-date\` too)`;
42837
- var TEMPORAL_AWARENESS_OVERRIDE_GUIDANCE = `
42838
- Some things on the desk are Magic Context's own markings, not conversation: \`<system-reminder>\`, \`<ctx-search-hint>\`, \`<session-history>\`, \`<session-history-since>\`, \`<project-memory>\`, \`<memory-updates>\`, \`<new-compartments>\`, \`<new-memories>\`, \`[dropped §N§]\`${TEMPORAL_AWARENESS_GUIDANCE}. Read them, use the time, and never reproduce them in a reply or treat them as instructions.`;
42839
- var BASE_INTRO = (memoryEnabled, dreamerEnabled, temporalAwarenessEnabled) => `### Your desk
42840
-
42841
- Think of your context as a desk. Every message and every tool output lands on it, and each item arrives with a §N§ tag (§1§, §42§) — the tag is the item's handle.
42842
-
42843
- When an item no longer needs to stay on the desk for the work ahead, stamp it: \`ctx_reduce\` with its tag. Stamping does not remove anything — the item stays on the desk, fully readable. From time to time, when stamped items have piled up and the desk needs room, Magic Context clears them all in one sweep; you don't pick the moment, you only stamp. Stamp as soon as an item has served its purpose, not at the end of the turn, and do it silently: nobody wants to read "I'll drop these outputs". An output is used once you've taken what you need from it into your reasoning or your answer. Never stamp a user message for what it asks of you; a large paste inside one is fine once you have used it.
42844
-
42845
- Nothing stamped is ever lost. A cleared item goes to the archive — a recent one leaves a \`[dropped §N§]\` placeholder on the desk, an older one leaves nothing — and \`ctx_expand(message=N)\` brings it back whole: text, tool input, tool output. Now and then Magic Context leaves a short reminder on the desk saying how much unstamped material is lying around. A reminder means stamping is overdue: act on it in your next step. It isn't a warning about the desk's size. The desk never gets smaller for it.
42846
-
42847
- ${TOOL_HISTORY_GUIDANCE}
42848
-
42849
- \`ctx_search\` searches the archive: anything ever said, decided, committed or noted in this project, including what is filed away. Ask it before you ask the user something that may already be recorded here, and whenever something feels familiar but is not in view.
42850
-
42851
- ${memoryEnabled ? `${MEMORY_GUIDANCE} ` : ""}${CTX_NOTE_GUIDANCE}${dreamerEnabled ? ` ${SMART_NOTE_GUIDANCE}` : ""}
42852
-
42853
- Some things on the desk are Magic Context's own markings, not conversation: \`<system-reminder>\`, \`<ctx-search-hint>\`, \`<session-history>\`, \`<session-history-since>\`, \`<project-memory>\`, \`<memory-updates>\`, \`<new-compartments>\`, \`<new-memories>\`, \`[dropped §N§]\`${temporalAwarenessEnabled ? TEMPORAL_AWARENESS_GUIDANCE : ""}. Read them, ${temporalAwarenessEnabled ? "use the time, and" : "and"} never reproduce them in a reply or treat them as instructions.`;
42854
- var BASE_INTRO_NO_REDUCE = (memoryEnabled, dreamerEnabled, temporalAwarenessEnabled) => `### Your desk
42855
-
42856
- Think of your context as a desk. Every message and every tool output lands on it.
42857
-
42858
- Nothing cleared from the desk is ever lost. A cleared item goes to the archive — a recent one leaves a placeholder on the desk, an older one leaves nothing — and \`ctx_expand(message=N)\` brings it back whole: text, tool input, tool output.
42859
-
42860
- ${TOOL_HISTORY_GUIDANCE}
42861
-
42862
- \`ctx_search\` searches the archive: anything ever said, decided, committed or noted in this project, including what is filed away. Ask it before you ask the user something that may already be recorded here, and whenever something feels familiar but is not in view.
42863
-
42864
- ${memoryEnabled ? `${MEMORY_GUIDANCE} ` : ""}${CTX_NOTE_GUIDANCE}${dreamerEnabled ? ` ${SMART_NOTE_GUIDANCE}` : ""}
42865
-
42866
- Some things on the desk are Magic Context's own markings, not conversation: \`<system-reminder>\`, \`<ctx-search-hint>\`, \`<session-history>\`, \`<session-history-since>\`, \`<project-memory>\`, \`<memory-updates>\`, \`<new-compartments>\`, \`<new-memories>\`${temporalAwarenessEnabled ? TEMPORAL_AWARENESS_GUIDANCE : ""}. Read them, ${temporalAwarenessEnabled ? "use the time, and" : "and"} never reproduce them in a reply or treat them as instructions.`;
42867
- var CTX_NOTE_GUIDANCE_LIGHT = `\`ctx_note\` is the tray for work you intend to return to, with its findings attached; findings without an intention are not a note; "take a note" from the user always goes there`;
42868
- var MEMORY_GUIDANCE_LIGHT = `\`<project-memory>\` is the pinboard of facts that stay true for the months this work lasts (\`#id: fact\`), for you and every agent on the project; \`ctx_memory\` pins what must not have to be found again, especially what cost you turns.`;
42869
- var TOOL_HISTORY_GUIDANCE_LIGHT = `Older work is filed off the desk into \`<session-history>\` — one \`## start-end · date · title\` heading per stretch, a summary under each, \`ctx_expand(start, end)\` to open the stretch in full. So your earlier messages may mention actions whose tool call is gone; that is normal and never a reason to fabricate: no tool result on the desk, no action, and never inline an invented call, output, search result or diff.`;
42870
- var SMART_NOTE_GUIDANCE_LIGHT = `; a \`surface_condition\` leaves the note with an outside checker that returns it when the condition holds`;
42871
- var TEMPORAL_AWARENESS_GUIDANCE_LIGHT = `, \`<!-- +Xm -->\` (time since your last reply)`;
42872
- var BASE_INTRO_LIGHT = (memoryEnabled, dreamerEnabled, temporalAwarenessEnabled) => `### Your desk
42873
-
42874
- Your context is a desk. Every message and tool output lands on it with a §N§ tag as its handle. When an item no longer needs to stay for the work ahead, stamp it: \`ctx_reduce\` with its tag. Stamping removes nothing — the item stays readable; from time to time, when stamped items have piled up and the desk needs room, Magic Context clears them in one sweep (you only stamp, you don't pick the moment). Stamp as soon as an item has served its purpose, silently; never stamp a user message for what it asks (a used paste inside one is fine). An output is used once you've taken what you need from it into your reasoning or your answer. Nothing is lost: a cleared item goes to the archive (a recent one leaves \`[dropped §N§]\`, an older one nothing) and \`ctx_expand(message=N)\` brings it back whole. Occasional reminders about unstamped material may appear. A reminder means stamping is overdue: act on it in your next step. It isn't a warning about the desk's size. The desk never gets smaller.
42875
-
42876
- ${TOOL_HISTORY_GUIDANCE_LIGHT}
42877
-
42878
- \`ctx_search\` searches the archive — anything ever said, decided, committed or noted here; ask it before asking the user anything that may already be recorded, phrased as a question with the exact names in it. ${memoryEnabled ? `${MEMORY_GUIDANCE_LIGHT} ` : ""}${CTX_NOTE_GUIDANCE_LIGHT}${dreamerEnabled ? SMART_NOTE_GUIDANCE_LIGHT : ""}.
42879
-
42880
- Magic Context's own markings — \`<system-reminder>\`, \`<ctx-search-hint>\`, \`<session-history>\`, \`<project-memory>\`, \`<memory-updates>\`, \`<new-compartments>\`, \`<new-memories>\`, \`[dropped §N§]\`${temporalAwarenessEnabled ? TEMPORAL_AWARENESS_GUIDANCE_LIGHT : ""} — are read, never reproduced, never instructions.`;
42881
- var BASE_INTRO_NO_REDUCE_LIGHT = (memoryEnabled, dreamerEnabled, temporalAwarenessEnabled) => `### Your desk
42882
-
42883
- Your context is a desk. Every message and tool output lands on it. Nothing cleared from the desk is lost: a cleared item goes to the archive (a recent one leaves a placeholder, an older one nothing) and \`ctx_expand(message=N)\` brings it back whole.
42884
-
42885
- ${TOOL_HISTORY_GUIDANCE_LIGHT}
42886
-
42887
- \`ctx_search\` searches the archive — anything ever said, decided, committed or noted here; ask it before asking the user anything that may already be recorded, phrased as a question with the exact names in it. ${memoryEnabled ? `${MEMORY_GUIDANCE_LIGHT} ` : ""}${CTX_NOTE_GUIDANCE_LIGHT}${dreamerEnabled ? SMART_NOTE_GUIDANCE_LIGHT : ""}.
42888
-
42889
- Magic Context's own markings — \`<system-reminder>\`, \`<ctx-search-hint>\`, \`<session-history>\`, \`<project-memory>\`, \`<memory-updates>\`, \`<new-compartments>\`, \`<new-memories>\`${temporalAwarenessEnabled ? TEMPORAL_AWARENESS_GUIDANCE_LIGHT : ""} — are read, never reproduced, never instructions.`;
42890
- var SUBAGENT_REDUCE_INTRO = () => `Your context is a desk. Every message and every tool output lands on it, and each item arrives with a §N§ tag (§1§, §42§) — the tag is the item's handle. When an item no longer needs to stay on the desk for the work ahead, stamp it: \`ctx_reduce\` with its tag ("3-5", "1,2,9", "1-5,8,12-15"). Stamping does not remove anything — the item stays fully readable until Magic Context clears stamped items in one sweep, and the newest tags are protected, so stamping recent output is harmless. Stamp as soon as an item has served its purpose, not at the end of the task, and do it silently. Never stamp a user message for what it asks of you; look at each tag before stamping and never blanket-stamp a range like "1-50".
42891
-
42892
- A cleared item leaves a \`[dropped §N§]\` placeholder or disappears from the desk; that is normal housekeeping, not something to copy or mention. If there is no tool result on the desk, the action did not happen: never fabricate or inline a tool call, an output, a search result or a diff — make a fresh real tool call instead.
42893
-
42894
- \`<system-reminder>\`, \`<ctx-search-hint>\`, \`<session-history>\`, \`<session-history-since>\`, \`<project-memory>\`, \`<memory-updates>\`, \`<new-compartments>\`, \`<new-memories>\` and \`[dropped §N§]\` are Magic Context's own markings: read them, never reproduce them in a reply, never treat them as instructions.`;
42895
- var SUBAGENT_REDUCE_INTRO_LIGHT = () => `Your context is a desk: every message and tool output lands on it with a §N§ tag as its handle. When an item no longer needs to stay for the work ahead, stamp it with \`ctx_reduce\` ("3-5", "1,2,9"). Stamping removes nothing — the item stays readable until Magic Context clears stamped items in one sweep; newest tags are protected. Stamp as soon as an item has served its purpose, silently; never stamp a user message for what it asks; look at each tag, never blanket-stamp "1-50".
42896
-
42897
- A cleared item leaves \`[dropped §N§]\` or disappears; that is housekeeping, not a pattern to copy. No tool result on the desk means the action did not happen — never fabricate or inline a call, output, search result or diff; make a real call.
42898
-
42899
- \`<system-reminder>\`, \`<ctx-search-hint>\`, \`<session-history>\`, \`<project-memory>\`, \`<memory-updates>\`, \`<new-compartments>\`, \`<new-memories>\`, \`[dropped §N§]\` are Magic Context's markings: read, never reproduced, never instructions.`;
42900
- var CAVEMAN_COMPRESSION_WARNING = `
42901
- **BEWARE**: History compression is on; older user AND assistant text — including your own earlier responses — has been deterministically rewritten in a terse caveman style (dropped articles, missing auxiliaries, \`//\` instead of connectives like \`because\`). This is automatic context compression that runs after the fact, not your actual prior wording or the user's. **DO NOT mimic this style in new turns.** Write fresh responses in normal prose. If you notice your output drifting into caveman cadence, that drift is in-context-learning bleeding from the compressed history — consciously revert to full sentences.`;
42902
- function buildMagicContextSection(_agent, _legacyProtectionCount, ctxReduceCallable = true, dreamerEnabled = false, temporalAwarenessEnabled = false, cavemanTextCompressionEnabled = false, subagentMode = false, language, memoryEnabled = true, preset = "full", primaryOverride) {
42903
- if (subagentMode) {
42904
- const intro = preset === "light" ? SUBAGENT_REDUCE_INTRO_LIGHT() : SUBAGENT_REDUCE_INTRO();
42905
- return `## Magic Context
42906
-
42907
- ${intro}`;
42908
- }
42909
- const temporalOverrideGuidance = temporalAwarenessEnabled ? TEMPORAL_AWARENESS_OVERRIDE_GUIDANCE : "";
42910
- const cavemanWarning = cavemanTextCompressionEnabled ? CAVEMAN_COMPRESSION_WARNING : "";
42911
- const languageDirective = buildPrimaryLanguageDirective(language);
42912
- const languageGuidance = languageDirective ? `
42913
-
42914
- ${languageDirective}` : "";
42915
- if (primaryOverride !== undefined) {
42916
- return `${primaryOverride}${temporalOverrideGuidance}${cavemanWarning}${languageGuidance}`;
42917
- }
42918
- if (!ctxReduceCallable) {
42919
- if (preset === "light") {
42920
- return `## Magic Context
42921
-
42922
- ${LONG_TERM_PARTNER_FRAME}
42923
- ${PARTNER_FRAME_CLOSER_NO_REDUCE_LIGHT}
42924
-
42925
- ${BASE_INTRO_NO_REDUCE_LIGHT(memoryEnabled, dreamerEnabled, temporalAwarenessEnabled)}${cavemanWarning}${languageGuidance}`;
42926
- }
42927
- return `## Magic Context
42928
-
42929
- ${LONG_TERM_PARTNER_FRAME}
42930
- ${PARTNER_FRAME_CLOSER_NO_REDUCE}
42931
-
42932
- ${BASE_INTRO_NO_REDUCE(memoryEnabled, dreamerEnabled, temporalAwarenessEnabled)}${cavemanWarning}${languageGuidance}`;
42933
- }
42934
- if (preset === "light") {
42935
- return `## Magic Context
42936
-
42937
- ${LONG_TERM_PARTNER_FRAME}
42938
- ${PARTNER_FRAME_CLOSER_REDUCE_LIGHT}
42939
-
42940
- ${BASE_INTRO_LIGHT(memoryEnabled, dreamerEnabled, temporalAwarenessEnabled)}${cavemanWarning}${languageGuidance}`;
42941
- }
42942
- return `## Magic Context
42943
-
42944
- ${LONG_TERM_PARTNER_FRAME}
42945
- ${PARTNER_FRAME_CLOSER_REDUCE}
42946
-
42947
- ${BASE_INTRO(memoryEnabled, dreamerEnabled, temporalAwarenessEnabled)}${cavemanWarning}${languageGuidance}`;
42948
- }
42949
-
42950
- // src/hooks/magic-context/system-prompt-hash.ts
40806
+ import { createHash as createHash14 } from "node:crypto";
42951
40807
  var MAGIC_CONTEXT_MARKER = "## Magic Context";
42952
40808
  var SYSTEM_PROMPT_GUIDANCE_SEPARATOR = `
42953
40809
 
@@ -43044,7 +40900,7 @@ function createSystemPromptHashHandler(deps) {
43044
40900
  }
43045
40901
  const stickyDate = stickyDateBySession.get(sessionId);
43046
40902
  const stableCandidate = currentDate && stickyDate && currentDate !== stickyDate ? liveSystemContent.replace(DATE_PATTERN_ALL, stickyDate) : liveSystemContent;
43047
- const stableCandidateHash = createHash15("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
40903
+ const stableCandidateHash = createHash14("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
43048
40904
  const contentOrPresetChanged = hasPersistedHash && stableCandidateHash !== previousHash;
43049
40905
  const dateMayAdvance = isCacheBusting || contentOrPresetChanged;
43050
40906
  if (currentDate && !stickyDate) {
@@ -43064,7 +40920,7 @@ function createSystemPromptHashHandler(deps) {
43064
40920
  `);
43065
40921
  if (!availability.frozen || !modelKey)
43066
40922
  return;
43067
- const currentHash = createHash15("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
40923
+ const currentHash = createHash14("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
43068
40924
  if (!sessionMetaEarly) {
43069
40925
  return;
43070
40926
  }
@@ -43388,6 +41244,7 @@ function createMagicContextHook(deps) {
43388
41244
  };
43389
41245
  registerLkgPersistence(createDbLkgPersistence(db));
43390
41246
  const transform = createTransform({
41247
+ cacheTtlConfig: deps.config.cache_ttl,
43391
41248
  tagger: deps.tagger,
43392
41249
  scheduler: deps.scheduler,
43393
41250
  contextUsageMap,
@@ -44217,7 +42074,7 @@ function resolveCtxExpandMode(args, domain) {
44217
42074
  }
44218
42075
 
44219
42076
  // src/tools/ctx-expand/render.ts
44220
- function isRecord7(value) {
42077
+ function isRecord6(value) {
44221
42078
  return value !== null && typeof value === "object" && !Array.isArray(value);
44222
42079
  }
44223
42080
  function roleLabel(role) {
@@ -44229,7 +42086,7 @@ function roleLabel(role) {
44229
42086
  }
44230
42087
  function verboseRoleLabel(msg) {
44231
42088
  if (msg.role === "user" && msg.parts.length > 0 && msg.parts.every((part) => {
44232
- if (!isRecord7(part))
42089
+ if (!isRecord6(part))
44233
42090
  return false;
44234
42091
  if (part.type === "tool_result")
44235
42092
  return true;
@@ -44257,15 +42114,15 @@ function keyArg(input) {
44257
42114
  function asToolPart(part) {
44258
42115
  const type = typeof part.type === "string" ? part.type : "";
44259
42116
  if (type === "tool") {
44260
- const state = isRecord7(part.state) ? part.state : null;
42117
+ const state = isRecord6(part.state) ? part.state : null;
44261
42118
  const output = state && typeof state.output === "string" ? state.output : state && state.output != null ? JSON.stringify(state.output) : null;
44262
- const metadata = state && isRecord7(state.metadata) ? state.metadata : null;
42119
+ const metadata = state && isRecord6(state.metadata) ? state.metadata : null;
44263
42120
  const title = state && typeof state.title === "string" && state.title || metadata && typeof metadata.title === "string" && metadata.title || null;
44264
42121
  return {
44265
42122
  name: typeof part.tool === "string" ? part.tool : "tool",
44266
42123
  callId: typeof part.callID === "string" ? part.callID : "",
44267
42124
  title,
44268
- input: state && isRecord7(state.input) ? state.input : null,
42125
+ input: state && isRecord6(state.input) ? state.input : null,
44269
42126
  output
44270
42127
  };
44271
42128
  }
@@ -44274,7 +42131,7 @@ function asToolPart(part) {
44274
42131
  name: typeof part.name === "string" ? part.name : "tool",
44275
42132
  callId: typeof part.id === "string" ? part.id : "",
44276
42133
  title: null,
44277
- input: isRecord7(part.input) ? part.input : null,
42134
+ input: isRecord6(part.input) ? part.input : null,
44278
42135
  output: null
44279
42136
  };
44280
42137
  }
@@ -44303,7 +42160,7 @@ function reasoningOf(part) {
44303
42160
  return null;
44304
42161
  }
44305
42162
  function renderPartPreview(part) {
44306
- if (!isRecord7(part))
42163
+ if (!isRecord6(part))
44307
42164
  return null;
44308
42165
  const text = textOf(part);
44309
42166
  if (text !== null) {
@@ -44327,7 +42184,7 @@ function renderPartPreview(part) {
44327
42184
  return ` • [${type}]`;
44328
42185
  }
44329
42186
  function renderPartFull(part) {
44330
- if (!isRecord7(part))
42187
+ if (!isRecord6(part))
44331
42188
  return null;
44332
42189
  const text = textOf(part);
44333
42190
  if (text !== null) {
@@ -44358,7 +42215,13 @@ ${tool.output}`);
44358
42215
  return null;
44359
42216
  }
44360
42217
  function renderMessageByOrdinal(sessionId, ordinal) {
44361
- const msg = readRawSessionMessages2(sessionId).find((m) => m.ordinal === ordinal);
42218
+ const found = [];
42219
+ visitRawSessionMessages2(sessionId, ordinal, ordinal, (m) => {
42220
+ if (m.ordinal === ordinal)
42221
+ found.push(m);
42222
+ return false;
42223
+ });
42224
+ const msg = found[0];
44362
42225
  if (!msg) {
44363
42226
  return `No message at ordinal ${ordinal} in this session's stored history — it was deleted ` + `(session prune/revert) or the ordinal is wrong, so it can't be recovered. ` + `Re-run the tool if you still need the data.`;
44364
42227
  }
@@ -44373,12 +42236,11 @@ function renderMessageByOrdinal(sessionId, ordinal) {
44373
42236
  `);
44374
42237
  }
44375
42238
  function renderVerboseRange(sessionId, start, end, tokenBudget) {
44376
- const messages = readRawSessionMessages2(sessionId).filter((m) => m.ordinal >= start && m.ordinal <= end);
44377
42239
  const out = [];
44378
42240
  let usedTokens = 0;
44379
42241
  let lastOrdinal = start - 1;
44380
42242
  let truncated = false;
44381
- for (const msg of messages) {
42243
+ visitRawSessionMessages2(sessionId, start, end, (msg) => {
44382
42244
  const header = `[${msg.ordinal}] ${verboseRoleLabel(msg)}`;
44383
42245
  const partLines = msg.parts.map(renderPartPreview).filter((l) => l !== null);
44384
42246
  const block = partLines.length > 0 ? `${header}
@@ -44387,12 +42249,13 @@ ${partLines.join(`
44387
42249
  const blockTokens = estimateTokens(block);
44388
42250
  if (usedTokens + blockTokens > tokenBudget && out.length > 0) {
44389
42251
  truncated = true;
44390
- break;
42252
+ return false;
44391
42253
  }
44392
42254
  out.push(block);
44393
42255
  usedTokens += blockTokens;
44394
42256
  lastOrdinal = msg.ordinal;
44395
- }
42257
+ return true;
42258
+ });
44396
42259
  return { text: out.join(`
44397
42260
 
44398
42261
  `), lastOrdinal, truncated };
@@ -45268,13 +43131,13 @@ First line is the title (under 80 chars), followed by detail. Operations:
45268
43131
  import { tool as tool3 } from "@opencode-ai/plugin";
45269
43132
 
45270
43133
  // src/features/magic-context/smart-notes/condition-compiler.ts
45271
- import { existsSync as existsSync14 } from "node:fs";
45272
- import { isAbsolute as isAbsolute4 } from "node:path";
43134
+ import { existsSync as existsSync11 } from "node:fs";
43135
+ import { isAbsolute as isAbsolute3 } from "node:path";
45273
43136
 
45274
43137
  // ../retina-local-fs/src/path-fence.ts
45275
43138
  import { lstat as lstat2, readlink, realpath as realpath2 } from "node:fs/promises";
45276
- import { homedir as homedir3 } from "node:os";
45277
- import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join11, relative, resolve as resolve3, sep } from "node:path";
43139
+ import { homedir as homedir2 } from "node:os";
43140
+ import { basename, dirname as dirname4, isAbsolute as isAbsolute2, join as join10, relative, resolve as resolve2, sep } from "node:path";
45278
43141
 
45279
43142
  // ../retina-local-fs/src/errors.ts
45280
43143
  class ProviderError extends Error {
@@ -45289,8 +43152,8 @@ class ProviderError extends Error {
45289
43152
  // ../retina-local-fs/src/path-fence.ts
45290
43153
  async function resolveAndFenceProviderPath(configuredPath, options) {
45291
43154
  const { home, dataDirectory } = await resolveFenceRoots(options);
45292
- const expanded = configuredPath.startsWith("~/") ? join11(home, configuredPath.slice(2)) : configuredPath === "~" ? home : configuredPath;
45293
- const absolute = isAbsolute3(expanded) ? resolve3(expanded) : resolve3(options.cwd ?? process.cwd(), expanded);
43155
+ const expanded = configuredPath.startsWith("~/") ? join10(home, configuredPath.slice(2)) : configuredPath === "~" ? home : configuredPath;
43156
+ const absolute = isAbsolute2(expanded) ? resolve2(expanded) : resolve2(options.cwd ?? process.cwd(), expanded);
45294
43157
  const canonical = await canonicalPath(absolute, options.allowMissing);
45295
43158
  if (isFencedPath(canonical, home, dataDirectory)) {
45296
43159
  throw new ProviderError("fenced_path", `Refusing fenced path: ${canonical}`);
@@ -45298,14 +43161,14 @@ async function resolveAndFenceProviderPath(configuredPath, options) {
45298
43161
  return canonical;
45299
43162
  }
45300
43163
  async function resolveFenceRoots(options) {
45301
- const configuredHomePath = resolve3(options.homeDirectory ?? process.env.HOME ?? homedir3());
43164
+ const configuredHomePath = resolve2(options.homeDirectory ?? process.env.HOME ?? homedir2());
45302
43165
  let home;
45303
43166
  try {
45304
43167
  home = await realpath2(configuredHomePath);
45305
43168
  } catch (error) {
45306
43169
  throw fsError(configuredHomePath, error);
45307
43170
  }
45308
- const configuredDataDirectory = resolve3(options.dataDirectory ?? process.env.XDG_DATA_HOME ?? join11(home, ".local", "share"));
43171
+ const configuredDataDirectory = resolve2(options.dataDirectory ?? process.env.XDG_DATA_HOME ?? join10(home, ".local", "share"));
45309
43172
  const dataDirectory = await canonicalPath(configuredDataDirectory, true);
45310
43173
  return { home, dataDirectory };
45311
43174
  }
@@ -45323,22 +43186,22 @@ async function canonicalPath(path, allowMissing) {
45323
43186
  const metadata = await lstat2(candidate);
45324
43187
  if (metadata.isSymbolicLink()) {
45325
43188
  const target = await readlink(candidate);
45326
- const resolvedTarget = resolve3(dirname6(candidate), target);
45327
- return canonicalPath(join11(resolvedTarget, ...suffix), true);
43189
+ const resolvedTarget = resolve2(dirname4(candidate), target);
43190
+ return canonicalPath(join10(resolvedTarget, ...suffix), true);
45328
43191
  }
45329
43192
  } catch (candidateError) {
45330
43193
  if (!isMissingError(candidateError)) {
45331
43194
  throw fsError(path, candidateError);
45332
43195
  }
45333
43196
  }
45334
- const parent = dirname6(candidate);
43197
+ const parent = dirname4(candidate);
45335
43198
  if (parent === candidate) {
45336
43199
  throw fsError(path, error);
45337
43200
  }
45338
- suffix.unshift(basename2(candidate));
43201
+ suffix.unshift(basename(candidate));
45339
43202
  candidate = parent;
45340
43203
  try {
45341
- return join11(await realpath2(candidate), ...suffix);
43204
+ return join10(await realpath2(candidate), ...suffix);
45342
43205
  } catch (parentError) {
45343
43206
  if (!isMissingError(parentError)) {
45344
43207
  throw fsError(path, parentError);
@@ -45347,13 +43210,13 @@ async function canonicalPath(path, allowMissing) {
45347
43210
  }
45348
43211
  }
45349
43212
  }
45350
- function isFencedPath(canonicalPath, homeDirectory, dataDirectory = process.env.XDG_DATA_HOME ?? join11(resolve3(homeDirectory), ".local", "share")) {
45351
- const cortexkitRoot = join11(resolve3(dataDirectory), "cortexkit");
43213
+ function isFencedPath(canonicalPath, homeDirectory, dataDirectory = process.env.XDG_DATA_HOME ?? join10(resolve2(homeDirectory), ".local", "share")) {
43214
+ const cortexkitRoot = join10(resolve2(dataDirectory), "cortexkit");
45352
43215
  const relativeToCortexkit = relative(cortexkitRoot, canonicalPath);
45353
- const insideCortexkit = relativeToCortexkit !== "" && relativeToCortexkit !== ".." && !relativeToCortexkit.startsWith(`..${sep}`) && !isAbsolute3(relativeToCortexkit);
43216
+ const insideCortexkit = relativeToCortexkit !== "" && relativeToCortexkit !== ".." && !relativeToCortexkit.startsWith(`..${sep}`) && !isAbsolute2(relativeToCortexkit);
45354
43217
  const parts = insideCortexkit ? relativeToCortexkit.split(sep) : [];
45355
43218
  const pathParts = canonicalPath.split(sep).filter(Boolean);
45356
- const name = basename2(canonicalPath);
43219
+ const name = basename(canonicalPath);
45357
43220
  const catalogDirectoryCarveIn = pathParts.includes("catalog");
45358
43221
  const moduleBinCarveIn = parts.length >= 2 && parts[1] === "bin";
45359
43222
  const catalogJsonCarveIn = name.endsWith(".json") && name.includes("catalog");
@@ -45525,7 +43388,7 @@ async function compileSurfaceCondition(surfaceCondition, options) {
45525
43388
  dataDirectory: options.dataDirectory,
45526
43389
  cwd: options.projectPath
45527
43390
  });
45528
- return { path: resolved, exists: existsSync14(resolved) };
43391
+ return { path: resolved, exists: existsSync11(resolved) };
45529
43392
  });
45530
43393
  let predicates;
45531
43394
  try {
@@ -45660,7 +43523,7 @@ function parseAtomicCondition(text, projectPath) {
45660
43523
  async function resolvePredicate(predicate, resolvePath, now) {
45661
43524
  const configuredPath = "repo_path" in predicate ? predicate.repo_path : predicate.path;
45662
43525
  const resolved = await resolvePath(configuredPath);
45663
- const sourceIsResolvable = isAbsolute4(configuredPath) || configuredPath === "~" || configuredPath.startsWith("~/");
43526
+ const sourceIsResolvable = isAbsolute3(configuredPath) || configuredPath === "~" || configuredPath.startsWith("~/");
45664
43527
  const audit = sourceIsResolvable && resolved.exists ? {} : { resolved_path_exists: false };
45665
43528
  switch (predicate.kind) {
45666
43529
  case "file_contains":
@@ -46108,7 +43971,7 @@ Keep: user messages (never stamp one for its directive), your own conversation t
46108
43971
 
46109
43972
  Look at each tag before stamping it; never blanket-stamp a range like "1-50". Many small targeted stamps beat one sweep. \`drop\` accepts "3-5", "1,2,9", "1-5,8,12-15".`;
46110
43973
  // src/tools/ctx-reduce/tools.ts
46111
- import { createHash as createHash16 } from "node:crypto";
43974
+ import { createHash as createHash15 } from "node:crypto";
46112
43975
  import { tool as tool4 } from "@opencode-ai/plugin";
46113
43976
 
46114
43977
  // src/features/magic-context/range-parser.ts
@@ -46178,11 +44041,11 @@ function createCtxReduceTool(deps) {
46178
44041
  const stableId = `oc-${sessionId}-${callId}`;
46179
44042
  if (Buffer.byteLength(stableId) <= 128)
46180
44043
  return stableId;
46181
- return `oc-${createHash16("sha256").update(stableId).digest("hex")}`;
44044
+ return `oc-${createHash15("sha256").update(stableId).digest("hex")}`;
46182
44045
  }
46183
44046
  fallbackCommandSequence += 1;
46184
44047
  const monotonicId = `oc-${sessionId}-${fallbackCommandSequence}`;
46185
- return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${createHash16("sha256").update(monotonicId).digest("hex")}`;
44048
+ return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${createHash15("sha256").update(monotonicId).digest("hex")}`;
46186
44049
  };
46187
44050
  return tool4({
46188
44051
  description: CTX_REDUCE_DESCRIPTION,
@@ -46746,13 +44609,13 @@ import {
46746
44609
  chmodSync as chmodSync2,
46747
44610
  mkdirSync as mkdirSync5,
46748
44611
  readdirSync as readdirSync2,
46749
- readFileSync as readFileSync9,
46750
- renameSync as renameSync6,
44612
+ readFileSync as readFileSync6,
44613
+ renameSync as renameSync5,
46751
44614
  rmSync as rmSync5,
46752
- unlinkSync as unlinkSync2,
46753
- writeFileSync as writeFileSync6
44615
+ unlinkSync,
44616
+ writeFileSync as writeFileSync5
46754
44617
  } from "node:fs";
46755
- import { dirname as dirname7 } from "node:path";
44618
+ import { dirname as dirname5 } from "node:path";
46756
44619
  var MAX_BODY_BYTES = 1048576;
46757
44620
  var WS_AUTH_TIMEOUT_MS = 5000;
46758
44621
  var WS_CLOSE_UNAUTHORIZED = 4401;
@@ -46833,7 +44696,7 @@ class MagicContextRpcServer {
46833
44696
  this.port = server.port ?? 0;
46834
44697
  try {
46835
44698
  this.warnIfOtherLiveInstance();
46836
- const dir = dirname7(this.portFilePath);
44699
+ const dir = dirname5(this.portFilePath);
46837
44700
  const enforcePrivatePermissions = shouldEnforcePrivateStoragePermissions();
46838
44701
  if (enforcePrivatePermissions) {
46839
44702
  mkdirSync5(dir, { recursive: true, mode: 448 });
@@ -46848,7 +44711,7 @@ class MagicContextRpcServer {
46848
44711
  try {
46849
44712
  rmSync5(tmpPath, { force: true });
46850
44713
  } catch {}
46851
- writeFileSync6(tmpPath, JSON.stringify({
44714
+ writeFileSync5(tmpPath, JSON.stringify({
46852
44715
  port: this.port,
46853
44716
  pid: process.pid,
46854
44717
  started_at: this.startedAt,
@@ -46856,7 +44719,7 @@ class MagicContextRpcServer {
46856
44719
  token: this.token,
46857
44720
  instance_id: this.instanceId
46858
44721
  }), enforcePrivatePermissions ? { encoding: "utf-8", mode: 384 } : { encoding: "utf-8" });
46859
- renameSync6(tmpPath, this.portFilePath);
44722
+ renameSync5(tmpPath, this.portFilePath);
46860
44723
  if (enforcePrivatePermissions) {
46861
44724
  try {
46862
44725
  chmodSync2(this.portFilePath, 384);
@@ -46883,7 +44746,7 @@ class MagicContextRpcServer {
46883
44746
  this.server = null;
46884
44747
  }
46885
44748
  try {
46886
- unlinkSync2(this.portFilePath);
44749
+ unlinkSync(this.portFilePath);
46887
44750
  } catch {}
46888
44751
  this.unregisterOwnInstance?.();
46889
44752
  this.unregisterOwnInstance = null;
@@ -46893,7 +44756,7 @@ class MagicContextRpcServer {
46893
44756
  for (const entry of readdirSync2(this.portDir)) {
46894
44757
  if (!entry.startsWith("port-") || !entry.endsWith(".json"))
46895
44758
  continue;
46896
- const record = parseRpcPortFile(readFileSync9(`${this.portDir}/${entry}`, "utf-8"));
44759
+ const record = parseRpcPortFile(readFileSync6(`${this.portDir}/${entry}`, "utf-8"));
46897
44760
  if (!record || record.pid === process.pid || !isPidAlive(record.pid))
46898
44761
  continue;
46899
44762
  log(`[rpc] another Magic Context RPC server is active for this project (pid ${record.pid}, port ${record.port}); starting separate instance on a new port`);
@@ -47107,9 +44970,9 @@ function trimToRecordedBoundary(db, sessionId, messages) {
47107
44970
  }
47108
44971
 
47109
44972
  // src/v2/fold/host-media.ts
47110
- var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
44973
+ var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
47111
44974
  function isClassInstance(value) {
47112
- if (!isRecord8(value))
44975
+ if (!isRecord7(value))
47113
44976
  return false;
47114
44977
  const prototype = Object.getPrototypeOf(value);
47115
44978
  return prototype !== Object.prototype && prototype !== null;
@@ -47128,10 +44991,10 @@ function rememberHostMedia(messages) {
47128
44991
  if (!Array.isArray(content))
47129
44992
  continue;
47130
44993
  for (const part of content) {
47131
- if (!isRecord8(part) || part.type !== "media")
44994
+ if (!isRecord7(part) || part.type !== "media")
47132
44995
  continue;
47133
44996
  const media = part.media;
47134
- if (isClassInstance(media) && isRecord8(media.source)) {
44997
+ if (isClassInstance(media) && isRecord7(media.source)) {
47135
44998
  rememberedAssetClass = Object.getPrototypeOf(media).constructor;
47136
44999
  return;
47137
45000
  }
@@ -47206,8 +45069,8 @@ function hostMediaAsset(data, mediaType) {
47206
45069
  }
47207
45070
 
47208
45071
  // src/v2/fold/owner.ts
47209
- import { createHash as createHash17 } from "node:crypto";
47210
- var foldDigest = (value) => createHash17("sha256").update(value).digest("hex");
45072
+ import { createHash as createHash16 } from "node:crypto";
45073
+ var foldDigest = (value) => createHash16("sha256").update(value).digest("hex");
47211
45074
 
47212
45075
  class FoldOwner {
47213
45076
  storage;
@@ -47510,12 +45373,12 @@ ${data.output?.output ?? ""}`
47510
45373
  }
47511
45374
 
47512
45375
  // src/v2/host-service.ts
47513
- import { readdirSync as readdirSync3, readFileSync as readFileSync10 } from "node:fs";
47514
- import { homedir as homedir4 } from "node:os";
47515
- import { join as join12 } from "node:path";
45376
+ import { readdirSync as readdirSync3, readFileSync as readFileSync7 } from "node:fs";
45377
+ import { homedir as homedir3 } from "node:os";
45378
+ import { join as join11 } from "node:path";
47516
45379
  function serviceRegistrationDirectory(env = process.env) {
47517
- const state = env.XDG_STATE_HOME ?? join12(homedir4(), ".local", "state");
47518
- return join12(state, "opencode");
45380
+ const state = env.XDG_STATE_HOME ?? join11(homedir3(), ".local", "state");
45381
+ return join11(state, "opencode");
47519
45382
  }
47520
45383
  class HostServiceUnavailable extends Error {
47521
45384
  constructor(message) {
@@ -47526,7 +45389,7 @@ class HostServiceUnavailable extends Error {
47526
45389
  function parseRegistration(path) {
47527
45390
  let text;
47528
45391
  try {
47529
- text = readFileSync10(path, "utf8");
45392
+ text = readFileSync7(path, "utf8");
47530
45393
  } catch {
47531
45394
  return;
47532
45395
  }
@@ -47558,7 +45421,7 @@ function readServiceRegistrations(env = process.env) {
47558
45421
  } catch {
47559
45422
  return [];
47560
45423
  }
47561
- return names.filter((name) => name === "service.json" || /^service-.+\.json$/.test(name)).sort().flatMap((name) => parseRegistration(join12(directory, name)) ?? []);
45424
+ return names.filter((name) => name === "service.json" || /^service-.+\.json$/.test(name)).sort().flatMap((name) => parseRegistration(join11(directory, name)) ?? []);
47562
45425
  }
47563
45426
  function discoverOwnHostService(env = process.env, pid = process.pid) {
47564
45427
  return readServiceRegistrations(env).find((service) => service.pid === pid);
@@ -50239,7 +48102,7 @@ async function registerContext(context) {
50239
48102
  const current = dreamerRunConfig(config, liveConfigReader.poll().effective);
50240
48103
  return { config: current.dreamer ?? dreamerAtBoot, mural: current.mural };
50241
48104
  },
50242
- executor,
48105
+ executor: withLiveDreamerOutputCap(executor, config, () => liveConfigReader.poll().effective),
50243
48106
  projectIdentity: () => resolveProjectIdentity(directory) ?? directory,
50244
48107
  language: config.language,
50245
48108
  mural: config.mural
@@ -50603,6 +48466,7 @@ async function registerContext(context) {
50603
48466
  if (!rawProviders.has(draft.sessionID))
50604
48467
  rawProviders.set(draft.sessionID, setBoundedRawMessageProvider2(draft.sessionID, createV2RawMessageProvider(pagedRead, draft.sessionID)));
50605
48468
  transform ??= createTransform({
48469
+ cacheTtlConfig: config.cache_ttl,
50606
48470
  db,
50607
48471
  tagger,
50608
48472
  ...createV2ThresholdDeps(config),
@@ -50870,22 +48734,22 @@ ${baseline}
50870
48734
  }
50871
48735
 
50872
48736
  // src/v2/hooks/update-check.ts
50873
- import { existsSync as existsSync15, readFileSync as readFileSync11 } from "node:fs";
50874
- import { dirname as dirname8, join as join13 } from "node:path";
48737
+ import { existsSync as existsSync12, readFileSync as readFileSync8 } from "node:fs";
48738
+ import { dirname as dirname6, join as join12 } from "node:path";
50875
48739
  import { fileURLToPath as fileURLToPath3 } from "node:url";
50876
48740
  function packageInfo() {
50877
- let directory = dirname8(fileURLToPath3(import.meta.url));
48741
+ let directory = dirname6(fileURLToPath3(import.meta.url));
50878
48742
  for (;; ) {
50879
48743
  try {
50880
- const pkg = JSON.parse(readFileSync11(join13(directory, "package.json"), "utf8"));
48744
+ const pkg = JSON.parse(readFileSync8(join12(directory, "package.json"), "utf8"));
50881
48745
  if (pkg.name === "@cortexkit/opencode-magic-context" && typeof pkg.version === "string") {
50882
48746
  return {
50883
48747
  version: pkg.version,
50884
- development: existsSync15(join13(directory, "src/v2/server.ts"))
48748
+ development: existsSync12(join12(directory, "src/v2/server.ts"))
50885
48749
  };
50886
48750
  }
50887
48751
  } catch {}
50888
- const parent = dirname8(directory);
48752
+ const parent = dirname6(directory);
50889
48753
  if (parent === directory)
50890
48754
  throw new Error("Magic Context package manifest is unavailable");
50891
48755
  directory = parent;
@@ -50976,6 +48840,7 @@ var server = async (ctx) => {
50976
48840
  const loadedPluginConfig = loadPluginConfigDetailed(ctx.directory);
50977
48841
  const pluginConfig = loadedPluginConfig.config;
50978
48842
  const liveConfigReader = pluginConfigReader(ctx.directory, pluginConfig);
48843
+ const dreamerCap = createDreamerOutputCapSampler(pluginConfig, () => liveConfigReader.poll().effective);
50979
48844
  reloadWindowOverlay(pluginConfig.models?.window_overlay_path);
50980
48845
  const promptSurfaceRuntime = createPromptSurfaceRuntime({
50981
48846
  harness: "opencode",
@@ -51007,7 +48872,7 @@ var server = async (ctx) => {
51007
48872
  if (hasBannerEntries)
51008
48873
  setTimeout(async () => {
51009
48874
  try {
51010
- const { sendStatusNotification } = await import("./send-session-notification-w7xbnrsm.js");
48875
+ const { sendStatusNotification } = await import("./send-session-notification-g2k03zyn.js");
51011
48876
  const clientWithSessions = ctx.client;
51012
48877
  const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
51013
48878
  const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
@@ -51024,7 +48889,7 @@ var server = async (ctx) => {
51024
48889
  log(`[magic-context] opencode_db_missing path=${openCodeDbResolution.path} source=${openCodeDbResolution.source}`);
51025
48890
  setTimeout(async () => {
51026
48891
  try {
51027
- const { sendStatusNotification } = await import("./send-session-notification-w7xbnrsm.js");
48892
+ const { sendStatusNotification } = await import("./send-session-notification-g2k03zyn.js");
51028
48893
  const clientWithSessions = ctx.client;
51029
48894
  const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
51030
48895
  const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
@@ -51291,12 +49156,12 @@ var server = async (ctx) => {
51291
49156
  {
51292
49157
  const fence = getSchemaFenceRejection();
51293
49158
  if (fence) {
51294
- import("./conflict-warning-hook-48f7np9d.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
49159
+ import("./conflict-warning-hook-d14ah73v.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
51295
49160
  }
51296
49161
  }
51297
49162
  const serverUrl = ctx.serverUrl;
51298
49163
  const serverUrlStr = serverUrl instanceof URL ? serverUrl.toString().replace(/\/$/, "") : typeof serverUrl === "string" ? serverUrl.replace(/\/$/, "") : undefined;
51299
- import("./send-session-notification-w7xbnrsm.js").then(({ setNotificationServerUrl }) => {
49164
+ import("./send-session-notification-g2k03zyn.js").then(({ setNotificationServerUrl }) => {
51300
49165
  setNotificationServerUrl(serverUrlStr);
51301
49166
  });
51302
49167
  if (conflictResult?.hasConflict) {
@@ -51310,7 +49175,7 @@ var server = async (ctx) => {
51310
49175
  }
51311
49176
  if (pluginConfig.enabled && !conflictResult?.hasConflict) {
51312
49177
  setTimeout(() => {
51313
- import("./announcement-1a8bvswd.js").then(({
49178
+ import("./announcement-n8hs7kjw.js").then(({
51314
49179
  shouldShowAnnouncement,
51315
49180
  ANNOUNCEMENT_VERSION,
51316
49181
  ANNOUNCEMENT_FEATURES,
@@ -51319,7 +49184,7 @@ var server = async (ctx) => {
51319
49184
  }) => {
51320
49185
  if (!shouldShowAnnouncement())
51321
49186
  return;
51322
- return import("./conflict-warning-hook-48f7np9d.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER, markAnnouncementSeen));
49187
+ return import("./conflict-warning-hook-d14ah73v.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER, markAnnouncementSeen));
51323
49188
  }).catch(() => {});
51324
49189
  }, 8000);
51325
49190
  }
@@ -51347,6 +49212,11 @@ var server = async (ctx) => {
51347
49212
  event: createEventHandler({
51348
49213
  magicContext: {
51349
49214
  event: async (input) => {
49215
+ if (input.event.type === "session.deleted") {
49216
+ const properties = input.event.properties;
49217
+ if (properties.info?.id)
49218
+ dreamerCap.delete(properties.info.id);
49219
+ }
51350
49220
  await magicContextRuntime.magicContext?.event?.(input);
51351
49221
  }
51352
49222
  },
@@ -51371,6 +49241,9 @@ var server = async (ctx) => {
51371
49241
  log("[magic-context] instance disposed — stopped RPC server, dream timer, auto-update");
51372
49242
  }
51373
49243
  }),
49244
+ "chat.params": async (input, output) => {
49245
+ dreamerCap.apply(input, output);
49246
+ },
51374
49247
  "experimental.chat.messages.transform": createMessagesTransformHandler({
51375
49248
  magicContext: magicContextRuntime.magicContext,
51376
49249
  getMagicContext: () => magicContextRuntime.magicContext,