@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.
- package/dist/agents/magic-context-prompt.d.ts +2 -0
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/{announcement-1a8bvswd.js → announcement-n8hs7kjw.js} +2 -2
- package/dist/config/live-child-output-cap.d.ts +18 -0
- package/dist/config/live-child-output-cap.d.ts.map +1 -0
- package/dist/config/schema/magic-context.d.ts +1 -1
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-48f7np9d.js → conflict-warning-hook-d14ah73v.js} +6 -6
- package/dist/{derive-budgets-8kgevxmx.js → derive-budgets-gd2270s0.js} +3 -3
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/open-opencode-db.d.ts +2 -0
- package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/primer-seed.d.ts +11 -5
- package/dist/features/magic-context/dreamer/primer-seed.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts +2 -2
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity.d.ts +7 -0
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/mural/mural-font.generated.d.ts.map +1 -1
- package/dist/features/magic-context/session-cache-ttl.d.ts +10 -0
- package/dist/features/magic-context/session-cache-ttl.d.ts.map +1 -0
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/opencode-v1-store-fixture.d.ts +12 -0
- package/dist/hooks/magic-context/opencode-v1-store-fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +16 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +5 -1
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +10 -0
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +1 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-cj5qe2nw.js → index-0rp6pj54.js} +3 -3
- package/dist/{index-4b30nf6z.js → index-32b096cc.js} +1 -1
- package/dist/{index-tjq5jztd.js → index-3bygzk2d.js} +1 -1
- package/dist/{index-c906f3ff.js → index-a9vbtdzv.js} +4 -4
- package/dist/{index-pye48m79.js → index-cz88kw0n.js} +13 -3
- package/dist/{index-5f4qsnaq.js → index-d107az47.js} +2 -2
- package/dist/{index-rdey8znw.js → index-jtdrvmcn.js} +2368 -35
- package/dist/{index-v6wsttqt.js → index-kr5qehbd.js} +1 -1
- package/dist/{index-dx0xnd4q.js → index-kwe03yde.js} +1 -1
- package/dist/{index-2zf5fv89.js → index-s6b7h12g.js} +100 -12
- package/dist/{index-6z9g64js.js → index-s70wtd8k.js} +4 -1
- package/dist/{index-01ft0h3p.js → index-stb5fg12.js} +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +474 -2601
- package/dist/{message-time-backfill-rm9wmcem.js → message-time-backfill-q374fxc5.js} +3 -3
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/{read-session-chunk-ktz5zt70.js → read-session-chunk-fkdv2g5b.js} +6 -4
- package/dist/{recomp-orchestrator-ahekzt0s.js → recomp-orchestrator-k4h5n0p3.js} +9 -9
- package/dist/{safe-notification-target-6w0esgd6.js → safe-notification-target-50gm9c58.js} +3 -3
- package/dist/{send-session-notification-w7xbnrsm.js → send-session-notification-g2k03zyn.js} +5 -5
- package/dist/shared/cache-ttl-display.d.ts +3 -1
- package/dist/shared/cache-ttl-display.d.ts.map +1 -1
- package/dist/shared/harness.d.ts +11 -0
- package/dist/shared/harness.d.ts.map +1 -1
- package/dist/shared/model-cache-ttl.d.ts +9 -0
- package/dist/shared/model-cache-ttl.d.ts.map +1 -0
- package/dist/shared/rpc-types.d.ts +1 -1
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/status-view.d.ts +1 -1
- package/dist/shared/status-view.d.ts.map +1 -1
- package/dist/tools/ctx-expand/render.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/server.js +7820 -7567
- package/dist/wrapup-orchestrator-35y56636.js +18 -0
- package/package.json +1 -1
- package/src/agents/magic-context-prompt.test.ts +125 -0
- package/src/agents/magic-context-prompt.ts +12 -7
- package/src/config/live-child-output-cap.test.ts +75 -0
- package/src/config/live-child-output-cap.ts +70 -0
- package/src/config/live-run-config.test.ts +24 -11
- package/src/config/schema/magic-context.test.ts +16 -1
- package/src/config/schema/magic-context.ts +6 -4
- package/src/shared/cache-ttl-display.ts +14 -20
- package/src/shared/harness.ts +14 -0
- package/src/shared/model-cache-ttl.test.ts +40 -0
- package/src/shared/model-cache-ttl.ts +58 -0
- package/src/shared/prompt-surface-a1-golden.md +13 -13
- package/src/shared/rpc-types.ts +1 -1
- package/src/shared/status-view.ts +1 -1
- 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-
|
|
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-
|
|
17
|
+
} from "./index-3bygzk2d.js";
|
|
17
18
|
import {
|
|
18
19
|
withContentLanguageDirective,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
686
|
-
import"./index-
|
|
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-
|
|
694
|
+
} from "./index-a9vbtdzv.js";
|
|
696
695
|
import {
|
|
697
696
|
detectConflicts,
|
|
698
697
|
resolveCompactionForBoot,
|
|
699
698
|
sendConflictWarning2,
|
|
700
699
|
cleanupConflictWarnings2
|
|
701
|
-
} from "./index-
|
|
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-
|
|
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-
|
|
746
|
+
} from "./index-0rp6pj54.js";
|
|
748
747
|
import {
|
|
749
748
|
logSlowWriteTransaction
|
|
750
|
-
} from "./index-
|
|
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
|
|
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) ??
|
|
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
|
|
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:${
|
|
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
|
|
11694
|
-
import { dirname as
|
|
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
|
|
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 (!
|
|
9580
|
+
if (!existsSync2(path))
|
|
11701
9581
|
return null;
|
|
11702
9582
|
try {
|
|
11703
|
-
const value = JSON.parse(
|
|
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
|
|
9611
|
+
existsSync as existsSync3,
|
|
11732
9612
|
constants as fsConstants,
|
|
11733
|
-
readFileSync as
|
|
11734
|
-
renameSync
|
|
11735
|
-
statSync
|
|
11736
|
-
writeFileSync
|
|
9613
|
+
readFileSync as readFileSync2,
|
|
9614
|
+
renameSync,
|
|
9615
|
+
statSync,
|
|
9616
|
+
writeFileSync
|
|
11737
9617
|
} from "node:fs";
|
|
11738
|
-
import { dirname
|
|
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
|
|
11743
|
-
import { join
|
|
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
|
|
9629
|
+
return join(process.env.LOCALAPPDATA ?? homedir(), "opencode");
|
|
11750
9630
|
}
|
|
11751
|
-
return
|
|
9631
|
+
return join(homedir(), ".cache", "opencode");
|
|
11752
9632
|
}
|
|
11753
9633
|
function getOpenCodeConfigRoot() {
|
|
11754
9634
|
if (platform() === "win32") {
|
|
11755
|
-
return
|
|
9635
|
+
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "opencode");
|
|
11756
9636
|
}
|
|
11757
|
-
return
|
|
9637
|
+
return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "opencode");
|
|
11758
9638
|
}
|
|
11759
|
-
var CACHE_DIR =
|
|
11760
|
-
var USER_OPENCODE_CONFIG =
|
|
11761
|
-
var USER_OPENCODE_CONFIG_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 =
|
|
9702
|
+
const globalDir = dirname(USER_OPENCODE_CONFIG);
|
|
11823
9703
|
const dirs = [
|
|
11824
9704
|
globalDir,
|
|
11825
9705
|
directory,
|
|
11826
|
-
|
|
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 =
|
|
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 (!
|
|
9723
|
+
if (!existsSync3(path))
|
|
11844
9724
|
continue;
|
|
11845
|
-
const parsed = parseJsonConfig(
|
|
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 (
|
|
9748
|
+
if (isAbsolute(spec) || /^[A-Za-z]:[\\/]/.test(spec))
|
|
11869
9749
|
return spec;
|
|
11870
|
-
return
|
|
9750
|
+
return resolve(dirname(configPath), spec);
|
|
11871
9751
|
}
|
|
11872
9752
|
function findPackageJsonUp(startPath) {
|
|
11873
9753
|
try {
|
|
11874
|
-
const stat =
|
|
11875
|
-
let dir = stat.isDirectory() ? 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 =
|
|
11878
|
-
if (
|
|
9757
|
+
const pkgPath = join2(dir, "package.json");
|
|
9758
|
+
if (existsSync3(pkgPath)) {
|
|
11879
9759
|
try {
|
|
11880
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
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 =
|
|
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 (!
|
|
9776
|
+
if (!existsSync3(configPath))
|
|
11897
9777
|
continue;
|
|
11898
|
-
const rawConfig = parseJsonConfig(
|
|
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(".") ||
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
11997
|
-
|
|
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(
|
|
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) =>
|
|
12068
|
-
globalTuiPaths.push(...globalServerPaths.map((path) =>
|
|
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 (!
|
|
9981
|
+
if (!existsSync3(packageJsonPath))
|
|
12102
9982
|
continue;
|
|
12103
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
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
|
|
10077
|
+
return join3(storageDir ?? getOpenCodeStorageDir(), AUTO_UPDATE_CHECK_STATE_FILENAME);
|
|
12198
10078
|
}
|
|
12199
10079
|
function writeCheckState(path, state) {
|
|
12200
|
-
mkdirSync(
|
|
10080
|
+
mkdirSync(dirname2(path), { recursive: true });
|
|
12201
10081
|
const tmp = `${path}.tmp.${process.pid}`;
|
|
12202
|
-
|
|
10082
|
+
writeFileSync2(tmp, `${JSON.stringify(state, null, 2)}
|
|
12203
10083
|
`, "utf-8");
|
|
12204
|
-
|
|
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
|
|
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 ??
|
|
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
|
-
|
|
10125
|
+
writeFileSync2(temp, `${JSON.stringify({ spec: update.spec, version, configPaths: update.configPaths, writtenAt: Date.now() }, null, 2)}
|
|
12246
10126
|
`, "utf-8");
|
|
12247
|
-
|
|
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 (!
|
|
10134
|
+
if (!existsSync4(path))
|
|
12255
10135
|
return;
|
|
12256
10136
|
try {
|
|
12257
|
-
const marker = JSON.parse(
|
|
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
|
|
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
|
|
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 (!
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
14085
|
-
import { existsSync as
|
|
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
|
|
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
|
|
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 =
|
|
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}:${
|
|
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
|
|
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()}:${
|
|
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
|
|
13723
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
15807
13724
|
import {
|
|
15808
|
-
existsSync as
|
|
13725
|
+
existsSync as existsSync5,
|
|
15809
13726
|
mkdirSync as mkdirSync2,
|
|
15810
13727
|
mkdtempSync,
|
|
15811
13728
|
readdirSync,
|
|
15812
|
-
readFileSync as
|
|
13729
|
+
readFileSync as readFileSync4,
|
|
15813
13730
|
realpathSync as realpathSync3,
|
|
15814
|
-
renameSync as
|
|
13731
|
+
renameSync as renameSync3,
|
|
15815
13732
|
rmSync as rmSync2,
|
|
15816
|
-
writeFileSync as
|
|
13733
|
+
writeFileSync as writeFileSync3
|
|
15817
13734
|
} from "node:fs";
|
|
15818
13735
|
import { tmpdir } from "node:os";
|
|
15819
|
-
import { join as
|
|
13736
|
+
import { join as join5 } from "node:path";
|
|
15820
13737
|
var FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
15821
|
-
var hash = (text) =>
|
|
15822
|
-
var proposalDir = (projectDir) =>
|
|
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(
|
|
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
|
|
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]) =>
|
|
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(
|
|
13834
|
+
const dir = mkdtempSync(join5(tmpdir(), "mc-doc-diff-"));
|
|
15918
13835
|
try {
|
|
15919
|
-
|
|
15920
|
-
|
|
13836
|
+
writeFileSync3(join5(dir, "before"), before);
|
|
13837
|
+
writeFileSync3(join5(dir, "after"), after);
|
|
15921
13838
|
try {
|
|
15922
|
-
return execFileSync("git", ["diff", "--no-index", "--",
|
|
13839
|
+
return execFileSync("git", ["diff", "--no-index", "--", join5(dir, "before"), join5(dir, "after")], { encoding: "utf8" });
|
|
15923
13840
|
} catch (error) {
|
|
15924
|
-
return error.stdout?.replaceAll(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
13939
|
+
writeFileSync3(path, body, { flag: "wx" });
|
|
16023
13940
|
for (const old of listPendingDocsProposals(projectDir))
|
|
16024
13941
|
if (old !== path)
|
|
16025
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
17999
|
-
import { join as
|
|
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 =
|
|
15921
|
+
const path = join7(docsDir, name);
|
|
18005
15922
|
try {
|
|
18006
|
-
if (
|
|
18007
|
-
snapshot.set(name,
|
|
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
|
|
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
|
|
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 (
|
|
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}:${
|
|
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(
|
|
16685
|
+
function renderUserAndToolOrientation(sessionId, startOrdinal, endOrdinal, capTokens) {
|
|
18769
16686
|
const lines = [];
|
|
18770
16687
|
let tokens = 0;
|
|
18771
|
-
|
|
18772
|
-
|
|
18773
|
-
|
|
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
|
|
18787
|
-
`);
|
|
16703
|
+
return false;
|
|
18788
16704
|
}
|
|
18789
16705
|
lines.push(line);
|
|
18790
16706
|
tokens += lineTokens;
|
|
18791
16707
|
}
|
|
18792
|
-
|
|
18793
|
-
|
|
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,
|
|
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(
|
|
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
|
|
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
|
|
16752
|
+
let orientation = null;
|
|
18830
16753
|
try {
|
|
18831
|
-
|
|
16754
|
+
orientation = renderUserAndToolOrientation(sessionId, start, end, PRIMER_SEED_CAP_TOKENS);
|
|
18832
16755
|
} catch {
|
|
18833
|
-
|
|
16756
|
+
orientation = null;
|
|
18834
16757
|
}
|
|
18835
|
-
|
|
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
|
-
|
|
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
|
|
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}:${
|
|
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
|
|
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:
|
|
21126
|
-
structure:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
24316
|
+
function isRecord3(value) {
|
|
26328
24317
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
26329
24318
|
}
|
|
26330
24319
|
function responseData(value) {
|
|
26331
|
-
if (
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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) =>
|
|
26423
|
-
const agentRules = permissionRules(
|
|
26424
|
-
const sessionRules = permissionRules(
|
|
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
|
-
|
|
26766
|
-
|
|
26767
|
-
|
|
26768
|
-
|
|
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 =
|
|
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 =
|
|
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-
|
|
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-
|
|
31369
|
-
const { sendIgnoredMessage } = await import("./send-session-notification-
|
|
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-
|
|
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
|
|
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 (!
|
|
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
|
|
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
|
|
31208
|
+
function isRecord4(value) {
|
|
33226
31209
|
return typeof value === "object" && value !== null;
|
|
33227
31210
|
}
|
|
33228
31211
|
function refusalOf(response) {
|
|
33229
|
-
if (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
31241
|
+
if (!isRecord4(response) || response.ok !== true)
|
|
33259
31242
|
return null;
|
|
33260
|
-
const 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 =
|
|
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
|
|
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 (
|
|
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 (
|
|
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 (!
|
|
35668
|
+
if (!isRecord5(value))
|
|
37686
35669
|
return {};
|
|
37687
|
-
return
|
|
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)}:${
|
|
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
|
|
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) =>
|
|
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 =
|
|
37876
|
-
const synthetic = parts.length > 0 && parts.every((part) =>
|
|
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 =
|
|
37882
|
-
const partDesc = mParts.slice(0, 5).map((part) =>
|
|
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 (
|
|
35871
|
+
if (isRecord5(response) && isRecord5(response.result))
|
|
37889
35872
|
return response.result;
|
|
37890
|
-
if (
|
|
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 (
|
|
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 =
|
|
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 =
|
|
38093
|
-
const channel2 =
|
|
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 (!
|
|
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
|
|
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(
|
|
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(
|
|
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 (!
|
|
36244
|
+
if (!isRecord5(message) || !Array.isArray(message.parts))
|
|
38262
36245
|
continue;
|
|
38263
|
-
const part = message.parts.find((candidate) =>
|
|
38264
|
-
if (!
|
|
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 =
|
|
38267
|
-
const input = state &&
|
|
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 =
|
|
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
|
|
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 (!
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 ||
|
|
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
|
|
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:
|
|
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 =
|
|
39854
|
+
updates.cacheTtl = resolveSessionCacheTtl(deps.db, info.sessionID, deps.config.cache_ttl, modelKey).value;
|
|
41861
39855
|
} else if (modelKey) {
|
|
41862
|
-
updates.cacheTtl =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 (!
|
|
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 =
|
|
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 &&
|
|
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 &&
|
|
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:
|
|
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 (!
|
|
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 (!
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
45272
|
-
import { isAbsolute as
|
|
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
|
|
45277
|
-
import { basename
|
|
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("~/") ?
|
|
45293
|
-
const absolute =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
45327
|
-
return canonicalPath(
|
|
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 =
|
|
43197
|
+
const parent = dirname4(candidate);
|
|
45335
43198
|
if (parent === candidate) {
|
|
45336
43199
|
throw fsError(path, error);
|
|
45337
43200
|
}
|
|
45338
|
-
suffix.unshift(
|
|
43201
|
+
suffix.unshift(basename(candidate));
|
|
45339
43202
|
candidate = parent;
|
|
45340
43203
|
try {
|
|
45341
|
-
return
|
|
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 ??
|
|
45351
|
-
const cortexkitRoot =
|
|
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}`) && !
|
|
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 =
|
|
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:
|
|
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 =
|
|
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
|
|
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-${
|
|
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-${
|
|
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
|
|
46750
|
-
renameSync as
|
|
44612
|
+
readFileSync as readFileSync6,
|
|
44613
|
+
renameSync as renameSync5,
|
|
46751
44614
|
rmSync as rmSync5,
|
|
46752
|
-
unlinkSync
|
|
46753
|
-
writeFileSync as
|
|
44615
|
+
unlinkSync,
|
|
44616
|
+
writeFileSync as writeFileSync5
|
|
46754
44617
|
} from "node:fs";
|
|
46755
|
-
import { dirname as
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
44973
|
+
var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47111
44974
|
function isClassInstance(value) {
|
|
47112
|
-
if (!
|
|
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 (!
|
|
44994
|
+
if (!isRecord7(part) || part.type !== "media")
|
|
47132
44995
|
continue;
|
|
47133
44996
|
const media = part.media;
|
|
47134
|
-
if (isClassInstance(media) &&
|
|
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
|
|
47210
|
-
var foldDigest = (value) =>
|
|
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
|
|
47514
|
-
import { homedir as
|
|
47515
|
-
import { join as
|
|
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 ??
|
|
47518
|
-
return
|
|
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 =
|
|
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(
|
|
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
|
|
50874
|
-
import { dirname as
|
|
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 =
|
|
48741
|
+
let directory = dirname6(fileURLToPath3(import.meta.url));
|
|
50878
48742
|
for (;; ) {
|
|
50879
48743
|
try {
|
|
50880
|
-
const pkg = JSON.parse(
|
|
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:
|
|
48748
|
+
development: existsSync12(join12(directory, "src/v2/server.ts"))
|
|
50885
48749
|
};
|
|
50886
48750
|
}
|
|
50887
48751
|
} catch {}
|
|
50888
|
-
const parent =
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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,
|