@cortexkit/pi-magic-context 0.30.6 → 0.31.0
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/README.md +1 -0
- package/dist/index.js +1521 -213
- package/dist/subagent-entry.js +511 -51
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -62,26 +62,26 @@ var currentHarness = "opencode", harnessLocked = false;
|
|
|
62
62
|
// ../plugin/src/shared/data-path.ts
|
|
63
63
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
64
64
|
import * as os from "node:os";
|
|
65
|
-
import * as
|
|
65
|
+
import * as path from "node:path";
|
|
66
66
|
function getDataDir() {
|
|
67
|
-
return process.env.XDG_DATA_HOME ??
|
|
67
|
+
return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
|
|
68
68
|
}
|
|
69
69
|
function getMagicContextTempDir(harness = getHarness()) {
|
|
70
|
-
return
|
|
70
|
+
return path.join(os.tmpdir(), harness, "magic-context");
|
|
71
71
|
}
|
|
72
72
|
function getMagicContextLogPath(harness = getHarness()) {
|
|
73
73
|
const envPath = process.env.MAGIC_CONTEXT_LOG_PATH?.trim();
|
|
74
74
|
if (envPath)
|
|
75
75
|
return envPath;
|
|
76
|
-
return
|
|
76
|
+
return path.join(getMagicContextTempDir(harness), "magic-context.log");
|
|
77
77
|
}
|
|
78
78
|
function getProjectMagicContextDir(directory) {
|
|
79
|
-
return
|
|
79
|
+
return path.join(directory, ".cortexkit", "magic-context");
|
|
80
80
|
}
|
|
81
81
|
function ensureCortexKitArtifactGitignore(directory) {
|
|
82
82
|
try {
|
|
83
|
-
const cortexKitDir =
|
|
84
|
-
const gitignorePath =
|
|
83
|
+
const cortexKitDir = path.join(directory, ".cortexkit");
|
|
84
|
+
const gitignorePath = path.join(cortexKitDir, ".gitignore");
|
|
85
85
|
let existing = "";
|
|
86
86
|
if (existsSync2(gitignorePath)) {
|
|
87
87
|
existing = readFileSync2(gitignorePath, "utf8");
|
|
@@ -101,25 +101,25 @@ ${GITIGNORE_GUARD_CLOSE}
|
|
|
101
101
|
} catch {}
|
|
102
102
|
}
|
|
103
103
|
function getProjectMagicContextHistorianDir(directory) {
|
|
104
|
-
return
|
|
104
|
+
return path.join(getProjectMagicContextDir(directory), "historian");
|
|
105
105
|
}
|
|
106
106
|
function getOpenCodeStorageDir() {
|
|
107
|
-
return
|
|
107
|
+
return path.join(getDataDir(), "opencode", "storage");
|
|
108
108
|
}
|
|
109
109
|
function getMagicContextStorageDir() {
|
|
110
|
-
return
|
|
110
|
+
return path.join(getDataDir(), "cortexkit", "magic-context");
|
|
111
111
|
}
|
|
112
112
|
function getLegacyOpenCodeMagicContextStorageDir() {
|
|
113
|
-
return
|
|
113
|
+
return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
|
|
114
114
|
}
|
|
115
115
|
var GITIGNORE_GUARD_OPEN = "# >>> cortexkit:magic-context", GITIGNORE_GUARD_CLOSE = "# <<< cortexkit:magic-context";
|
|
116
116
|
var init_data_path = () => {};
|
|
117
117
|
|
|
118
118
|
// ../plugin/src/shared/logger.ts
|
|
119
119
|
import * as fs from "node:fs";
|
|
120
|
-
import * as
|
|
120
|
+
import * as path2 from "node:path";
|
|
121
121
|
function ensureDir(filePath) {
|
|
122
|
-
const dir =
|
|
122
|
+
const dir = path2.dirname(filePath);
|
|
123
123
|
if (dir === lastEnsuredDir)
|
|
124
124
|
return;
|
|
125
125
|
try {
|
|
@@ -15707,13 +15707,23 @@ function summarizeDreamSchedule(dreamer) {
|
|
|
15707
15707
|
}
|
|
15708
15708
|
|
|
15709
15709
|
// ../plugin/src/features/magic-context/memory/project-identity.ts
|
|
15710
|
+
init_logger();
|
|
15710
15711
|
import { execFileSync } from "node:child_process";
|
|
15711
15712
|
import { createHash } from "node:crypto";
|
|
15712
|
-
import { statSync as statSync2 } from "node:fs";
|
|
15713
|
-
import
|
|
15713
|
+
import { existsSync as existsSync3, realpathSync, statSync as statSync2 } from "node:fs";
|
|
15714
|
+
import path3 from "node:path";
|
|
15714
15715
|
var GIT_TIMEOUT_MS = 5000;
|
|
15716
|
+
var TRANSIENT_FAILURE_COOLDOWN_MS = 5 * 60 * 1000;
|
|
15715
15717
|
var identityCache = new Map;
|
|
15718
|
+
var lastKnownGitIdentityCache = new Map;
|
|
15716
15719
|
var directoryFallbackCache = new Map;
|
|
15720
|
+
var transientFailureCooldown = new Map;
|
|
15721
|
+
var dubiousOwnershipFallbackDirectories = new Set;
|
|
15722
|
+
var dubiousOwnershipLoggedDirectories = new Set;
|
|
15723
|
+
var dubiousOwnershipWarnedDirectories = new Set;
|
|
15724
|
+
var transientGitIdentityReuseLoggedDirectories = new Set;
|
|
15725
|
+
var execFileSyncForIdentity = execFileSync;
|
|
15726
|
+
var nowMs = () => Date.now();
|
|
15717
15727
|
|
|
15718
15728
|
class ProjectIdentityError extends Error {
|
|
15719
15729
|
errorClass;
|
|
@@ -15765,7 +15775,7 @@ function getErrorStderr(error) {
|
|
|
15765
15775
|
return "";
|
|
15766
15776
|
}
|
|
15767
15777
|
function directoryFallback(directory) {
|
|
15768
|
-
const canonical =
|
|
15778
|
+
const canonical = path3.resolve(directory);
|
|
15769
15779
|
const hash = createHash("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
|
|
15770
15780
|
return `dir:${hash}`;
|
|
15771
15781
|
}
|
|
@@ -15803,21 +15813,27 @@ function classifyGitError(error, rawDirectory) {
|
|
|
15803
15813
|
return new ProjectIdentityError("permission_denied", rawDirectory, "Permission denied while spawning git", asError(error));
|
|
15804
15814
|
}
|
|
15805
15815
|
const stderr = getErrorStderr(error).toLowerCase();
|
|
15816
|
+
if (stderr.includes("detected dubious ownership")) {
|
|
15817
|
+
return new ProjectIdentityError("dubious_ownership", rawDirectory, "git refused to read the repository because it detected dubious ownership", asError(error));
|
|
15818
|
+
}
|
|
15806
15819
|
if (stderr.includes("not a git repository") || stderr.includes("does not have any commits yet") || stderr.includes("ambiguous argument 'head'") || stderr.includes("unknown revision or path")) {
|
|
15807
15820
|
return new ProjectIdentityError("not_git_repo", rawDirectory, "Directory has no git root commit; caller may use directory fallback", asError(error));
|
|
15808
15821
|
}
|
|
15809
15822
|
return new ProjectIdentityError("unknown", rawDirectory, "git rev-list failed while resolving project identity", asError(error));
|
|
15810
15823
|
}
|
|
15811
15824
|
function resolveProjectIdentityStrict(directory) {
|
|
15812
|
-
const canonical =
|
|
15825
|
+
const canonical = path3.resolve(directory);
|
|
15813
15826
|
const cached = identityCache.get(canonical);
|
|
15814
15827
|
if (cached !== undefined) {
|
|
15815
15828
|
return cached;
|
|
15816
15829
|
}
|
|
15817
15830
|
assertDirectoryUsable(canonical, directory);
|
|
15831
|
+
if (!hasGitDir(canonical)) {
|
|
15832
|
+
throw new ProjectIdentityError("not_git_repo", directory, "Directory has no git metadata; caller may use directory fallback");
|
|
15833
|
+
}
|
|
15818
15834
|
let output;
|
|
15819
15835
|
try {
|
|
15820
|
-
output =
|
|
15836
|
+
output = execFileSyncForIdentity("git", ["rev-list", "--max-parents=0", "HEAD"], {
|
|
15821
15837
|
cwd: canonical,
|
|
15822
15838
|
encoding: "utf8",
|
|
15823
15839
|
env: { ...process.env, LC_ALL: "C", LANG: "C" },
|
|
@@ -15835,13 +15851,76 @@ function resolveProjectIdentityStrict(directory) {
|
|
|
15835
15851
|
}
|
|
15836
15852
|
const identity = `git:${rootCommit}`;
|
|
15837
15853
|
identityCache.set(canonical, identity);
|
|
15854
|
+
lastKnownGitIdentityCache.set(canonical, identity);
|
|
15855
|
+
transientFailureCooldown.delete(canonical);
|
|
15856
|
+
dubiousOwnershipFallbackDirectories.delete(canonical);
|
|
15857
|
+
transientGitIdentityReuseLoggedDirectories.delete(canonical);
|
|
15838
15858
|
return identity;
|
|
15839
15859
|
}
|
|
15840
15860
|
function shouldUseDirectoryFallback(error) {
|
|
15841
|
-
return error.errorClass
|
|
15861
|
+
return error.errorClass !== "permission_denied";
|
|
15862
|
+
}
|
|
15863
|
+
function getActiveCooldown(canonical) {
|
|
15864
|
+
const until = transientFailureCooldown.get(canonical);
|
|
15865
|
+
if (until === undefined)
|
|
15866
|
+
return;
|
|
15867
|
+
if (nowMs() < until)
|
|
15868
|
+
return until;
|
|
15869
|
+
transientFailureCooldown.delete(canonical);
|
|
15870
|
+
return;
|
|
15871
|
+
}
|
|
15872
|
+
function lastKnownGitIdentity(canonical) {
|
|
15873
|
+
return lastKnownGitIdentityCache.get(canonical) ?? identityCache.get(canonical);
|
|
15874
|
+
}
|
|
15875
|
+
function nearestLastKnownGitIdentity(canonical) {
|
|
15876
|
+
const visited = new Set;
|
|
15877
|
+
const walk = (start) => {
|
|
15878
|
+
let current = start;
|
|
15879
|
+
while (!visited.has(current)) {
|
|
15880
|
+
visited.add(current);
|
|
15881
|
+
const cached = lastKnownGitIdentity(current);
|
|
15882
|
+
if (cached !== undefined)
|
|
15883
|
+
return { identity: cached, source: current };
|
|
15884
|
+
const parent = path3.dirname(current);
|
|
15885
|
+
if (parent === current)
|
|
15886
|
+
break;
|
|
15887
|
+
current = parent;
|
|
15888
|
+
}
|
|
15889
|
+
return;
|
|
15890
|
+
};
|
|
15891
|
+
const exactOrAncestor = walk(canonical);
|
|
15892
|
+
if (exactOrAncestor)
|
|
15893
|
+
return exactOrAncestor;
|
|
15894
|
+
try {
|
|
15895
|
+
const realCanonical = realpathSync.native(canonical);
|
|
15896
|
+
if (realCanonical !== canonical)
|
|
15897
|
+
return walk(realCanonical);
|
|
15898
|
+
} catch {}
|
|
15899
|
+
return;
|
|
15900
|
+
}
|
|
15901
|
+
function reuseLastKnownGitIdentity(canonical) {
|
|
15902
|
+
const cached = nearestLastKnownGitIdentity(canonical);
|
|
15903
|
+
if (cached === undefined)
|
|
15904
|
+
return;
|
|
15905
|
+
if (!transientGitIdentityReuseLoggedDirectories.has(canonical)) {
|
|
15906
|
+
transientGitIdentityReuseLoggedDirectories.add(canonical);
|
|
15907
|
+
const sourceNote = cached.source === canonical ? "" : ` from ancestor ${cached.source}`;
|
|
15908
|
+
log(`[magic-context] git identity resolution is temporarily unavailable for ${canonical}; reusing the last successful project identity${sourceNote} to avoid splitting project-scoped memory`);
|
|
15909
|
+
}
|
|
15910
|
+
return cached.identity;
|
|
15911
|
+
}
|
|
15912
|
+
function formatDubiousOwnershipWarning(canonical) {
|
|
15913
|
+
return `Magic Context: git refused to read ${canonical} (dubious ownership — the repo is owned by a different user). Using a directory-based project identity for now, which keeps memory separate from this repo's normal identity. Fix: git config --global --add safe.directory ${canonical}`;
|
|
15914
|
+
}
|
|
15915
|
+
function recordDubiousOwnershipFallback(canonical) {
|
|
15916
|
+
dubiousOwnershipFallbackDirectories.add(canonical);
|
|
15917
|
+
if (dubiousOwnershipLoggedDirectories.has(canonical))
|
|
15918
|
+
return;
|
|
15919
|
+
dubiousOwnershipLoggedDirectories.add(canonical);
|
|
15920
|
+
log(`[magic-context] ${formatDubiousOwnershipWarning(canonical)}`);
|
|
15842
15921
|
}
|
|
15843
15922
|
function resolveProjectIdentity(directory) {
|
|
15844
|
-
const canonical =
|
|
15923
|
+
const canonical = path3.resolve(directory);
|
|
15845
15924
|
const cachedFallback = directoryFallbackCache.get(canonical);
|
|
15846
15925
|
if (cachedFallback !== undefined) {
|
|
15847
15926
|
if (!hasGitDir(canonical)) {
|
|
@@ -15849,27 +15928,74 @@ function resolveProjectIdentity(directory) {
|
|
|
15849
15928
|
}
|
|
15850
15929
|
directoryFallbackCache.delete(canonical);
|
|
15851
15930
|
}
|
|
15931
|
+
if (getActiveCooldown(canonical) !== undefined) {
|
|
15932
|
+
if (hasGitDir(canonical)) {
|
|
15933
|
+
const cachedGitIdentity = reuseLastKnownGitIdentity(canonical);
|
|
15934
|
+
if (cachedGitIdentity !== undefined) {
|
|
15935
|
+
return cachedGitIdentity;
|
|
15936
|
+
}
|
|
15937
|
+
}
|
|
15938
|
+
return directoryFallback(canonical);
|
|
15939
|
+
}
|
|
15852
15940
|
try {
|
|
15853
15941
|
return resolveProjectIdentityStrict(directory);
|
|
15854
15942
|
} catch (error) {
|
|
15855
15943
|
if (error instanceof ProjectIdentityError && shouldUseDirectoryFallback(error)) {
|
|
15856
15944
|
const fallback = directoryFallback(canonical);
|
|
15857
|
-
|
|
15945
|
+
const hasGitMetadata = hasGitDir(canonical);
|
|
15946
|
+
if (!hasGitMetadata) {
|
|
15858
15947
|
directoryFallbackCache.set(canonical, fallback);
|
|
15948
|
+
transientFailureCooldown.delete(canonical);
|
|
15949
|
+
} else {
|
|
15950
|
+
transientFailureCooldown.set(canonical, nowMs() + TRANSIENT_FAILURE_COOLDOWN_MS);
|
|
15951
|
+
const cachedGitIdentity = reuseLastKnownGitIdentity(canonical);
|
|
15952
|
+
if (cachedGitIdentity !== undefined) {
|
|
15953
|
+
return cachedGitIdentity;
|
|
15954
|
+
}
|
|
15955
|
+
}
|
|
15956
|
+
if (error.errorClass === "dubious_ownership") {
|
|
15957
|
+
recordDubiousOwnershipFallback(canonical);
|
|
15859
15958
|
}
|
|
15860
15959
|
return fallback;
|
|
15861
15960
|
}
|
|
15862
15961
|
throw error;
|
|
15863
15962
|
}
|
|
15864
15963
|
}
|
|
15865
|
-
function
|
|
15964
|
+
function resolveProjectIdentityOrFallback(directory) {
|
|
15866
15965
|
try {
|
|
15867
|
-
|
|
15966
|
+
return resolveProjectIdentity(directory);
|
|
15967
|
+
} catch (error) {
|
|
15968
|
+
const canonical = path3.resolve(directory);
|
|
15969
|
+
const fallback = directoryFallback(canonical);
|
|
15970
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15971
|
+
log(`[magic-context] project identity resolution failed for ${canonical}; using directory fallback ${fallback}: ${message}`);
|
|
15972
|
+
return fallback;
|
|
15973
|
+
}
|
|
15974
|
+
}
|
|
15975
|
+
function hasGitDir(canonical) {
|
|
15976
|
+
if (hasGitDirInAncestorChain(canonical)) {
|
|
15868
15977
|
return true;
|
|
15978
|
+
}
|
|
15979
|
+
try {
|
|
15980
|
+
const realCanonical = realpathSync.native(canonical);
|
|
15981
|
+
return realCanonical !== canonical && hasGitDirInAncestorChain(realCanonical);
|
|
15869
15982
|
} catch {
|
|
15870
15983
|
return false;
|
|
15871
15984
|
}
|
|
15872
15985
|
}
|
|
15986
|
+
function hasGitDirInAncestorChain(startDirectory) {
|
|
15987
|
+
let current = startDirectory;
|
|
15988
|
+
while (true) {
|
|
15989
|
+
if (existsSync3(path3.join(current, ".git"))) {
|
|
15990
|
+
return true;
|
|
15991
|
+
}
|
|
15992
|
+
const parent = path3.dirname(current);
|
|
15993
|
+
if (parent === current) {
|
|
15994
|
+
return false;
|
|
15995
|
+
}
|
|
15996
|
+
current = parent;
|
|
15997
|
+
}
|
|
15998
|
+
}
|
|
15873
15999
|
function normalizeStoredProjectPath(rawOrStored) {
|
|
15874
16000
|
if (rawOrStored.startsWith("git:") || rawOrStored.startsWith("dir:")) {
|
|
15875
16001
|
return rawOrStored;
|
|
@@ -15902,7 +16028,7 @@ function removeSystemReminders(text) {
|
|
|
15902
16028
|
// ../plugin/src/hooks/magic-context/read-session-db.ts
|
|
15903
16029
|
init_data_path();
|
|
15904
16030
|
init_logger();
|
|
15905
|
-
import { existsSync as
|
|
16031
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
15906
16032
|
import { join as join3 } from "node:path";
|
|
15907
16033
|
|
|
15908
16034
|
// ../plugin/src/shared/sqlite.ts
|
|
@@ -15971,7 +16097,7 @@ function getOpenCodeDbPath() {
|
|
|
15971
16097
|
return join3(getDataDir(), "opencode", "opencode.db");
|
|
15972
16098
|
}
|
|
15973
16099
|
function openCodeDbExists() {
|
|
15974
|
-
return
|
|
16100
|
+
return existsSync4(getOpenCodeDbPath());
|
|
15975
16101
|
}
|
|
15976
16102
|
var cachedReadOnlyDb = null;
|
|
15977
16103
|
function closeCachedReadOnlyDb() {
|
|
@@ -149634,6 +149760,263 @@ function parseReportedLimit(message) {
|
|
|
149634
149760
|
}
|
|
149635
149761
|
return;
|
|
149636
149762
|
}
|
|
149763
|
+
|
|
149764
|
+
// ../plugin/src/features/magic-context/session-project-backfill.ts
|
|
149765
|
+
init_logger();
|
|
149766
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
149767
|
+
|
|
149768
|
+
// ../plugin/src/features/magic-context/session-project-storage.ts
|
|
149769
|
+
var upsertSessionProjectStatements = new WeakMap;
|
|
149770
|
+
var repairSessionChunkProjectStatements = new WeakMap;
|
|
149771
|
+
var repairProjectChunkProjectStatements = new WeakMap;
|
|
149772
|
+
function getUpsertSessionProjectStatement(db) {
|
|
149773
|
+
let stmt = upsertSessionProjectStatements.get(db);
|
|
149774
|
+
if (!stmt) {
|
|
149775
|
+
stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
|
|
149776
|
+
VALUES (?, ?, ?, ?)
|
|
149777
|
+
ON CONFLICT(session_id, harness) DO UPDATE SET
|
|
149778
|
+
project_path = excluded.project_path,
|
|
149779
|
+
updated_at = excluded.updated_at
|
|
149780
|
+
WHERE session_projects.project_path <> excluded.project_path`);
|
|
149781
|
+
upsertSessionProjectStatements.set(db, stmt);
|
|
149782
|
+
}
|
|
149783
|
+
return stmt;
|
|
149784
|
+
}
|
|
149785
|
+
function getRepairSessionChunkProjectStatement(db) {
|
|
149786
|
+
let stmt = repairSessionChunkProjectStatements.get(db);
|
|
149787
|
+
if (!stmt) {
|
|
149788
|
+
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
149789
|
+
SET project_path = ?
|
|
149790
|
+
WHERE session_id = ?
|
|
149791
|
+
AND harness = ?
|
|
149792
|
+
AND project_path <> ?`);
|
|
149793
|
+
repairSessionChunkProjectStatements.set(db, stmt);
|
|
149794
|
+
}
|
|
149795
|
+
return stmt;
|
|
149796
|
+
}
|
|
149797
|
+
function getRepairProjectChunkProjectStatement(db) {
|
|
149798
|
+
let stmt = repairProjectChunkProjectStatements.get(db);
|
|
149799
|
+
if (!stmt) {
|
|
149800
|
+
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
149801
|
+
SET project_path = (
|
|
149802
|
+
SELECT sp.project_path
|
|
149803
|
+
FROM session_projects sp
|
|
149804
|
+
WHERE sp.session_id = compartment_chunk_embeddings.session_id
|
|
149805
|
+
AND sp.harness = compartment_chunk_embeddings.harness
|
|
149806
|
+
LIMIT 1
|
|
149807
|
+
)
|
|
149808
|
+
WHERE EXISTS (
|
|
149809
|
+
SELECT 1
|
|
149810
|
+
FROM session_projects sp
|
|
149811
|
+
WHERE sp.session_id = compartment_chunk_embeddings.session_id
|
|
149812
|
+
AND sp.harness = compartment_chunk_embeddings.harness
|
|
149813
|
+
AND sp.project_path <> compartment_chunk_embeddings.project_path
|
|
149814
|
+
AND (
|
|
149815
|
+
sp.project_path = ?
|
|
149816
|
+
OR compartment_chunk_embeddings.project_path = ?
|
|
149817
|
+
)
|
|
149818
|
+
)`);
|
|
149819
|
+
repairProjectChunkProjectStatements.set(db, stmt);
|
|
149820
|
+
}
|
|
149821
|
+
return stmt;
|
|
149822
|
+
}
|
|
149823
|
+
function recordSessionProjectIdentity(db, sessionId, projectPath) {
|
|
149824
|
+
if (!sessionId || !projectPath)
|
|
149825
|
+
return;
|
|
149826
|
+
const harness = getHarness();
|
|
149827
|
+
const now = Date.now();
|
|
149828
|
+
db.transaction(() => {
|
|
149829
|
+
getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
|
|
149830
|
+
getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
|
|
149831
|
+
})();
|
|
149832
|
+
}
|
|
149833
|
+
function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
|
|
149834
|
+
if (!projectPath)
|
|
149835
|
+
return 0;
|
|
149836
|
+
return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
|
|
149837
|
+
}
|
|
149838
|
+
|
|
149839
|
+
// ../plugin/src/features/magic-context/session-project-backfill.ts
|
|
149840
|
+
var LEASE_TTL_MS = 10 * 60 * 1000;
|
|
149841
|
+
var SESSION_QUERY_CHUNK_SIZE = 250;
|
|
149842
|
+
var YIELD_EVERY_NEW_DIRECTORIES = 10;
|
|
149843
|
+
function ensureBackfillStateTable(db) {
|
|
149844
|
+
db.exec(`
|
|
149845
|
+
CREATE TABLE IF NOT EXISTS session_project_backfill_state (
|
|
149846
|
+
harness TEXT PRIMARY KEY,
|
|
149847
|
+
status TEXT NOT NULL CHECK (status IN ('running', 'completed')),
|
|
149848
|
+
started_at INTEGER,
|
|
149849
|
+
lease_expires_at INTEGER,
|
|
149850
|
+
completed_at INTEGER
|
|
149851
|
+
);
|
|
149852
|
+
`);
|
|
149853
|
+
}
|
|
149854
|
+
function withImmediateTransaction(db, fn) {
|
|
149855
|
+
db.exec("BEGIN IMMEDIATE");
|
|
149856
|
+
try {
|
|
149857
|
+
const result = fn();
|
|
149858
|
+
db.exec("COMMIT");
|
|
149859
|
+
return result;
|
|
149860
|
+
} catch (error) {
|
|
149861
|
+
try {
|
|
149862
|
+
db.exec("ROLLBACK");
|
|
149863
|
+
} catch {}
|
|
149864
|
+
throw error;
|
|
149865
|
+
}
|
|
149866
|
+
}
|
|
149867
|
+
function defaultYieldFn() {
|
|
149868
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
149869
|
+
}
|
|
149870
|
+
function acquireBackfillLease(db, harness, now) {
|
|
149871
|
+
ensureBackfillStateTable(db);
|
|
149872
|
+
return withImmediateTransaction(db, () => {
|
|
149873
|
+
const current = db.prepare(`SELECT harness, status, started_at, lease_expires_at, completed_at
|
|
149874
|
+
FROM session_project_backfill_state
|
|
149875
|
+
WHERE harness = ?`).get(harness);
|
|
149876
|
+
if (current?.status === "completed") {
|
|
149877
|
+
return "already_completed";
|
|
149878
|
+
}
|
|
149879
|
+
if (current?.status === "running" && current.lease_expires_at !== null && current.lease_expires_at > now) {
|
|
149880
|
+
return "blocked_by_lease";
|
|
149881
|
+
}
|
|
149882
|
+
db.prepare(`INSERT INTO session_project_backfill_state(
|
|
149883
|
+
harness,
|
|
149884
|
+
status,
|
|
149885
|
+
started_at,
|
|
149886
|
+
lease_expires_at,
|
|
149887
|
+
completed_at
|
|
149888
|
+
)
|
|
149889
|
+
VALUES (?, 'running', ?, ?, NULL)
|
|
149890
|
+
ON CONFLICT(harness) DO UPDATE SET
|
|
149891
|
+
status = 'running',
|
|
149892
|
+
started_at = excluded.started_at,
|
|
149893
|
+
lease_expires_at = excluded.lease_expires_at,
|
|
149894
|
+
completed_at = NULL`).run(harness, now, now + LEASE_TTL_MS);
|
|
149895
|
+
return "completed";
|
|
149896
|
+
});
|
|
149897
|
+
}
|
|
149898
|
+
function renewBackfillLease(db, harness, now) {
|
|
149899
|
+
ensureBackfillStateTable(db);
|
|
149900
|
+
db.prepare(`UPDATE session_project_backfill_state
|
|
149901
|
+
SET lease_expires_at = ?
|
|
149902
|
+
WHERE harness = ? AND status = 'running'`).run(now + LEASE_TTL_MS, harness);
|
|
149903
|
+
}
|
|
149904
|
+
function markBackfillCompleted(db, harness, now) {
|
|
149905
|
+
ensureBackfillStateTable(db);
|
|
149906
|
+
db.prepare(`INSERT INTO session_project_backfill_state(
|
|
149907
|
+
harness,
|
|
149908
|
+
status,
|
|
149909
|
+
started_at,
|
|
149910
|
+
lease_expires_at,
|
|
149911
|
+
completed_at
|
|
149912
|
+
)
|
|
149913
|
+
VALUES (?, 'completed', ?, NULL, ?)
|
|
149914
|
+
ON CONFLICT(harness) DO UPDATE SET
|
|
149915
|
+
status = 'completed',
|
|
149916
|
+
lease_expires_at = NULL,
|
|
149917
|
+
completed_at = excluded.completed_at`).run(harness, now, now);
|
|
149918
|
+
}
|
|
149919
|
+
function dedupeSessions(sessions) {
|
|
149920
|
+
const sessionsById = new Map;
|
|
149921
|
+
for (const session of sessions) {
|
|
149922
|
+
if (!session.sessionId)
|
|
149923
|
+
continue;
|
|
149924
|
+
const existing = sessionsById.get(session.sessionId);
|
|
149925
|
+
if (!existing) {
|
|
149926
|
+
sessionsById.set(session.sessionId, {
|
|
149927
|
+
sessionId: session.sessionId,
|
|
149928
|
+
directory: session.directory
|
|
149929
|
+
});
|
|
149930
|
+
continue;
|
|
149931
|
+
}
|
|
149932
|
+
if (!existing.directory && session.directory) {
|
|
149933
|
+
sessionsById.set(session.sessionId, {
|
|
149934
|
+
sessionId: session.sessionId,
|
|
149935
|
+
directory: session.directory
|
|
149936
|
+
});
|
|
149937
|
+
}
|
|
149938
|
+
}
|
|
149939
|
+
return [...sessionsById.values()];
|
|
149940
|
+
}
|
|
149941
|
+
function getMappedSessionIds(db, harness, sessions) {
|
|
149942
|
+
const mapped = new Set;
|
|
149943
|
+
for (let index = 0;index < sessions.length; index += SESSION_QUERY_CHUNK_SIZE) {
|
|
149944
|
+
const chunk = sessions.slice(index, index + SESSION_QUERY_CHUNK_SIZE);
|
|
149945
|
+
if (chunk.length === 0)
|
|
149946
|
+
continue;
|
|
149947
|
+
const placeholders = chunk.map(() => "?").join(", ");
|
|
149948
|
+
const rows = db.prepare(`SELECT session_id
|
|
149949
|
+
FROM session_projects
|
|
149950
|
+
WHERE harness = ?
|
|
149951
|
+
AND session_id IN (${placeholders})`).all(harness, ...chunk.map((session) => session.sessionId));
|
|
149952
|
+
for (const row of rows) {
|
|
149953
|
+
mapped.add(row.session_id);
|
|
149954
|
+
}
|
|
149955
|
+
}
|
|
149956
|
+
return mapped;
|
|
149957
|
+
}
|
|
149958
|
+
async function runSessionProjectBackfill(db, sessions, options = {}) {
|
|
149959
|
+
const startedAt = performance.now();
|
|
149960
|
+
const harness = getHarness();
|
|
149961
|
+
const now = options.now ?? Date.now;
|
|
149962
|
+
const resolveIdentity = options.resolveIdentity ?? resolveProjectIdentity;
|
|
149963
|
+
const yieldFn = options.yieldFn ?? defaultYieldFn;
|
|
149964
|
+
const dedupedSessions = dedupeSessions(sessions);
|
|
149965
|
+
const result = {
|
|
149966
|
+
status: "completed",
|
|
149967
|
+
totalSessions: dedupedSessions.length,
|
|
149968
|
+
alreadyMappedSessions: 0,
|
|
149969
|
+
unmappedSessions: 0,
|
|
149970
|
+
backfilledSessions: 0,
|
|
149971
|
+
skippedDeadDirectories: 0,
|
|
149972
|
+
skippedEmptyDirectories: 0,
|
|
149973
|
+
durationMs: 0
|
|
149974
|
+
};
|
|
149975
|
+
const leaseStatus = acquireBackfillLease(db, harness, now());
|
|
149976
|
+
if (leaseStatus !== "completed") {
|
|
149977
|
+
result.status = leaseStatus;
|
|
149978
|
+
result.durationMs = performance.now() - startedAt;
|
|
149979
|
+
return result;
|
|
149980
|
+
}
|
|
149981
|
+
const mappedSessionIds = getMappedSessionIds(db, harness, dedupedSessions);
|
|
149982
|
+
result.alreadyMappedSessions = mappedSessionIds.size;
|
|
149983
|
+
const existenceCache = new Map;
|
|
149984
|
+
const identityCache2 = new Map;
|
|
149985
|
+
let newDirectoryResolutions = 0;
|
|
149986
|
+
for (const session of dedupedSessions) {
|
|
149987
|
+
if (mappedSessionIds.has(session.sessionId)) {
|
|
149988
|
+
continue;
|
|
149989
|
+
}
|
|
149990
|
+
result.unmappedSessions += 1;
|
|
149991
|
+
if (!session.directory) {
|
|
149992
|
+
result.skippedEmptyDirectories += 1;
|
|
149993
|
+
continue;
|
|
149994
|
+
}
|
|
149995
|
+
const stillExists = existenceCache.get(session.directory) ?? existsSync5(session.directory);
|
|
149996
|
+
existenceCache.set(session.directory, stillExists);
|
|
149997
|
+
if (!stillExists) {
|
|
149998
|
+
result.skippedDeadDirectories += 1;
|
|
149999
|
+
continue;
|
|
150000
|
+
}
|
|
150001
|
+
let identity = identityCache2.get(session.directory);
|
|
150002
|
+
if (!identity) {
|
|
150003
|
+
identity = resolveIdentity(session.directory);
|
|
150004
|
+
identityCache2.set(session.directory, identity);
|
|
150005
|
+
newDirectoryResolutions += 1;
|
|
150006
|
+
if (newDirectoryResolutions % YIELD_EVERY_NEW_DIRECTORIES === 0) {
|
|
150007
|
+
renewBackfillLease(db, harness, now());
|
|
150008
|
+
await yieldFn();
|
|
150009
|
+
renewBackfillLease(db, harness, now());
|
|
150010
|
+
}
|
|
150011
|
+
}
|
|
150012
|
+
recordSessionProjectIdentity(db, session.sessionId, identity);
|
|
150013
|
+
result.backfilledSessions += 1;
|
|
150014
|
+
}
|
|
150015
|
+
markBackfillCompleted(db, harness, now());
|
|
150016
|
+
result.durationMs = performance.now() - startedAt;
|
|
150017
|
+
log(`[session-projects] backfilled ${result.backfilledSessions} of ${result.unmappedSessions} unmapped sessions (skipped ${result.skippedDeadDirectories} dead dirs) in ${Math.round(result.durationMs)}ms`);
|
|
150018
|
+
return result;
|
|
150019
|
+
}
|
|
149637
150020
|
// ../plugin/src/features/magic-context/compartment-lease.ts
|
|
149638
150021
|
var COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
149639
150022
|
var COMPARTMENT_LEASE_RENEWAL_MS = 60 * 1000;
|
|
@@ -151859,6 +152242,15 @@ var MIGRATIONS = [
|
|
|
151859
152242
|
);
|
|
151860
152243
|
`);
|
|
151861
152244
|
}
|
|
152245
|
+
},
|
|
152246
|
+
{
|
|
152247
|
+
version: 50,
|
|
152248
|
+
description: "add durable ctx-wrapup session marker",
|
|
152249
|
+
up(db) {
|
|
152250
|
+
if (tableExists2(db, "session_meta")) {
|
|
152251
|
+
ensureColumn(db, "session_meta", "wrapup_in_progress_state", "TEXT");
|
|
152252
|
+
}
|
|
152253
|
+
}
|
|
151862
152254
|
}
|
|
151863
152255
|
];
|
|
151864
152256
|
var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -152047,7 +152439,7 @@ function readProjectDocsCanonical(projectDirectory) {
|
|
|
152047
152439
|
return { renderedBlock, canonicalHash };
|
|
152048
152440
|
}
|
|
152049
152441
|
// ../plugin/src/features/magic-context/storage-db.ts
|
|
152050
|
-
import { chmodSync, copyFileSync, cpSync, existsSync as
|
|
152442
|
+
import { chmodSync, copyFileSync, cpSync, existsSync as existsSync7, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
|
|
152051
152443
|
init_data_path();
|
|
152052
152444
|
import { dirname as dirname3, join as join5 } from "node:path";
|
|
152053
152445
|
|
|
@@ -152186,14 +152578,14 @@ function loadToolDefinitionMeasurements(db) {
|
|
|
152186
152578
|
// ../plugin/src/features/magic-context/tool-owner-backfill.ts
|
|
152187
152579
|
init_data_path();
|
|
152188
152580
|
init_logger();
|
|
152189
|
-
import { existsSync as
|
|
152581
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
152190
152582
|
import { join as join4 } from "node:path";
|
|
152191
152583
|
var LEASE_DURATION_MS = 5 * 60 * 1000;
|
|
152192
152584
|
var LEASE_RENEWAL_MS = 60 * 1000;
|
|
152193
152585
|
function resolveOpencodeDbPath() {
|
|
152194
152586
|
return join4(getDataDir(), "opencode", "opencode.db");
|
|
152195
152587
|
}
|
|
152196
|
-
function
|
|
152588
|
+
function ensureBackfillStateTable2(db) {
|
|
152197
152589
|
db.exec(`
|
|
152198
152590
|
CREATE TABLE IF NOT EXISTS tool_owner_backfill_state (
|
|
152199
152591
|
session_id TEXT PRIMARY KEY,
|
|
@@ -152209,7 +152601,7 @@ function ensureBackfillStateTable(db) {
|
|
|
152209
152601
|
}
|
|
152210
152602
|
function runToolOwnerBackfill(db) {
|
|
152211
152603
|
const startedAt = performance.now();
|
|
152212
|
-
|
|
152604
|
+
ensureBackfillStateTable2(db);
|
|
152213
152605
|
const result = {
|
|
152214
152606
|
sessionsProcessed: 0,
|
|
152215
152607
|
sessionsSkippedNoOcDb: 0,
|
|
@@ -152226,7 +152618,7 @@ function runToolOwnerBackfill(db) {
|
|
|
152226
152618
|
return result;
|
|
152227
152619
|
}
|
|
152228
152620
|
const opencodeDbPath = resolveOpencodeDbPath();
|
|
152229
|
-
if (!
|
|
152621
|
+
if (!existsSync6(opencodeDbPath)) {
|
|
152230
152622
|
log(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
|
|
152231
152623
|
markAllUnbackfilledSessionsSkipped(db);
|
|
152232
152624
|
result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
|
|
@@ -152249,7 +152641,7 @@ function runToolOwnerBackfill(db) {
|
|
|
152249
152641
|
return result;
|
|
152250
152642
|
}
|
|
152251
152643
|
function isToolOwnerBackfillNeeded(db) {
|
|
152252
|
-
|
|
152644
|
+
ensureBackfillStateTable2(db);
|
|
152253
152645
|
const row = db.prepare(`SELECT 1 AS hit
|
|
152254
152646
|
FROM tags
|
|
152255
152647
|
WHERE type = 'tool' AND tool_owner_message_id IS NULL
|
|
@@ -152448,7 +152840,7 @@ var persistenceByDatabase = new WeakMap;
|
|
|
152448
152840
|
var persistenceErrorByDatabase = new WeakMap;
|
|
152449
152841
|
var pathByDatabase = new WeakMap;
|
|
152450
152842
|
var lastSchemaFenceRejection = null;
|
|
152451
|
-
var LATEST_SUPPORTED_VERSION =
|
|
152843
|
+
var LATEST_SUPPORTED_VERSION = 50;
|
|
152452
152844
|
var PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
|
|
152453
152845
|
function ensureSecureStorageDir(dir) {
|
|
152454
152846
|
mkdirSync4(dir, { recursive: true, mode: 448 });
|
|
@@ -152465,7 +152857,7 @@ function restrictDatabaseFilePermissions(dbPath) {
|
|
|
152465
152857
|
return;
|
|
152466
152858
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
152467
152859
|
const file = `${dbPath}${suffix}`;
|
|
152468
|
-
if (!
|
|
152860
|
+
if (!existsSync7(file))
|
|
152469
152861
|
continue;
|
|
152470
152862
|
try {
|
|
152471
152863
|
chmodSync(file, 384);
|
|
@@ -152491,11 +152883,11 @@ function getDatabasePath(db) {
|
|
|
152491
152883
|
return pathByDatabase.get(db) ?? null;
|
|
152492
152884
|
}
|
|
152493
152885
|
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
152494
|
-
if (
|
|
152886
|
+
if (existsSync7(targetDbPath))
|
|
152495
152887
|
return;
|
|
152496
152888
|
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
152497
152889
|
const legacyDbPath = join5(legacyDir, "context.db");
|
|
152498
|
-
if (!
|
|
152890
|
+
if (!existsSync7(legacyDbPath))
|
|
152499
152891
|
return;
|
|
152500
152892
|
log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
|
|
152501
152893
|
ensureSecureStorageDir(targetDbDir);
|
|
@@ -152512,7 +152904,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
152512
152904
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
152513
152905
|
const src = `${legacyDbPath}${suffix}`;
|
|
152514
152906
|
const dst = join5(targetDbDir, `context.db${suffix}`);
|
|
152515
|
-
if (
|
|
152907
|
+
if (existsSync7(src)) {
|
|
152516
152908
|
try {
|
|
152517
152909
|
copyFileSync(src, dst);
|
|
152518
152910
|
} catch (error) {
|
|
@@ -152522,7 +152914,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
152522
152914
|
}
|
|
152523
152915
|
const legacyModelsDir = join5(legacyDir, "models");
|
|
152524
152916
|
const targetModelsDir = join5(targetDbDir, "models");
|
|
152525
|
-
if (
|
|
152917
|
+
if (existsSync7(legacyModelsDir) && !existsSync7(targetModelsDir)) {
|
|
152526
152918
|
try {
|
|
152527
152919
|
cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
|
|
152528
152920
|
} catch (error) {
|
|
@@ -153126,6 +153518,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
153126
153518
|
force_emergency_bypass_used INTEGER NOT NULL DEFAULT 0,
|
|
153127
153519
|
emergency_drain_active INTEGER NOT NULL DEFAULT 0,
|
|
153128
153520
|
historian_drain_failure_at INTEGER NOT NULL DEFAULT 0,
|
|
153521
|
+
wrapup_in_progress_state TEXT,
|
|
153129
153522
|
cached_m0_materialized_at INTEGER,
|
|
153130
153523
|
cached_m0_session_facts_version INTEGER,
|
|
153131
153524
|
cached_m0_upgrade_state TEXT,
|
|
@@ -153414,6 +153807,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
153414
153807
|
ensureColumn(db, "session_meta", "force_emergency_bypass_used", "INTEGER NOT NULL DEFAULT 0");
|
|
153415
153808
|
ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
|
|
153416
153809
|
ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
|
|
153810
|
+
ensureColumn(db, "session_meta", "wrapup_in_progress_state", "TEXT");
|
|
153417
153811
|
ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
|
|
153418
153812
|
ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
|
|
153419
153813
|
ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
|
|
@@ -153886,6 +154280,148 @@ function recordProtectedTailNoEligibleHead(db, sessionId) {
|
|
|
153886
154280
|
return loadProtectedTailMeta(db, sessionId).recoveryNoEligibleHeadCount;
|
|
153887
154281
|
}
|
|
153888
154282
|
var DRAIN_WINDOW_MS = 10 * 60 * 1000;
|
|
154283
|
+
var WRAPUP_IN_PROGRESS_TTL_MS = 5 * 60 * 1000;
|
|
154284
|
+
function parseWrapupState(value) {
|
|
154285
|
+
if (typeof value !== "string" || value.trim().length === 0)
|
|
154286
|
+
return null;
|
|
154287
|
+
try {
|
|
154288
|
+
const parsed = JSON.parse(value);
|
|
154289
|
+
if (!parsed || typeof parsed !== "object")
|
|
154290
|
+
return null;
|
|
154291
|
+
if (typeof parsed.holderId !== "string" || parsed.holderId.length === 0)
|
|
154292
|
+
return null;
|
|
154293
|
+
const numberFields = [
|
|
154294
|
+
"acquiredAt",
|
|
154295
|
+
"expiresAt",
|
|
154296
|
+
"messagesToKeep",
|
|
154297
|
+
"anchorRawMessageCount",
|
|
154298
|
+
"targetEligibleEndOrdinal",
|
|
154299
|
+
"lastCompartmentEnd",
|
|
154300
|
+
"chunkIndex",
|
|
154301
|
+
"expectedChunks",
|
|
154302
|
+
"updatedAt"
|
|
154303
|
+
];
|
|
154304
|
+
for (const field of numberFields) {
|
|
154305
|
+
if (typeof parsed[field] !== "number" || !Number.isFinite(parsed[field]))
|
|
154306
|
+
return null;
|
|
154307
|
+
}
|
|
154308
|
+
return parsed;
|
|
154309
|
+
} catch {
|
|
154310
|
+
return null;
|
|
154311
|
+
}
|
|
154312
|
+
}
|
|
154313
|
+
function readRawWrapupState(db, sessionId) {
|
|
154314
|
+
const row = db.prepare("SELECT wrapup_in_progress_state FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
154315
|
+
return parseWrapupState(row?.wrapup_in_progress_state);
|
|
154316
|
+
}
|
|
154317
|
+
function getWrapupInProgressState(db, sessionId, now = Date.now()) {
|
|
154318
|
+
const state = readRawWrapupState(db, sessionId);
|
|
154319
|
+
if (!state)
|
|
154320
|
+
return null;
|
|
154321
|
+
if (state.expiresAt > now)
|
|
154322
|
+
return state;
|
|
154323
|
+
try {
|
|
154324
|
+
db.exec("BEGIN IMMEDIATE");
|
|
154325
|
+
} catch {
|
|
154326
|
+
return null;
|
|
154327
|
+
}
|
|
154328
|
+
let finished = false;
|
|
154329
|
+
try {
|
|
154330
|
+
const current = readRawWrapupState(db, sessionId);
|
|
154331
|
+
if (current && current.expiresAt <= now) {
|
|
154332
|
+
db.prepare("UPDATE session_meta SET wrapup_in_progress_state = NULL WHERE session_id = ?").run(sessionId);
|
|
154333
|
+
}
|
|
154334
|
+
db.exec("COMMIT");
|
|
154335
|
+
finished = true;
|
|
154336
|
+
} finally {
|
|
154337
|
+
if (!finished) {
|
|
154338
|
+
try {
|
|
154339
|
+
db.exec("ROLLBACK");
|
|
154340
|
+
} catch {}
|
|
154341
|
+
}
|
|
154342
|
+
}
|
|
154343
|
+
return null;
|
|
154344
|
+
}
|
|
154345
|
+
function isWrapupInProgress(db, sessionId, now = Date.now()) {
|
|
154346
|
+
return getWrapupInProgressState(db, sessionId, now) !== null;
|
|
154347
|
+
}
|
|
154348
|
+
function acquireWrapupInProgress(db, sessionId, state, now = Date.now()) {
|
|
154349
|
+
const acquiredAt = now;
|
|
154350
|
+
const next = {
|
|
154351
|
+
...state,
|
|
154352
|
+
acquiredAt,
|
|
154353
|
+
expiresAt: acquiredAt + WRAPUP_IN_PROGRESS_TTL_MS,
|
|
154354
|
+
updatedAt: acquiredAt
|
|
154355
|
+
};
|
|
154356
|
+
db.exec("BEGIN IMMEDIATE");
|
|
154357
|
+
let finished = false;
|
|
154358
|
+
try {
|
|
154359
|
+
ensureSessionMetaRow(db, sessionId);
|
|
154360
|
+
const current = readRawWrapupState(db, sessionId);
|
|
154361
|
+
if (current && current.expiresAt > now && current.holderId !== state.holderId) {
|
|
154362
|
+
db.exec("COMMIT");
|
|
154363
|
+
finished = true;
|
|
154364
|
+
return { ok: false, state: current };
|
|
154365
|
+
}
|
|
154366
|
+
db.prepare("UPDATE session_meta SET wrapup_in_progress_state = ? WHERE session_id = ?").run(stableStringify(next), sessionId);
|
|
154367
|
+
db.exec("COMMIT");
|
|
154368
|
+
finished = true;
|
|
154369
|
+
return { ok: true, state: next };
|
|
154370
|
+
} finally {
|
|
154371
|
+
if (!finished) {
|
|
154372
|
+
try {
|
|
154373
|
+
db.exec("ROLLBACK");
|
|
154374
|
+
} catch {}
|
|
154375
|
+
}
|
|
154376
|
+
}
|
|
154377
|
+
}
|
|
154378
|
+
function updateWrapupInProgress(db, sessionId, holderId, updates, now = Date.now()) {
|
|
154379
|
+
db.exec("BEGIN IMMEDIATE");
|
|
154380
|
+
let finished = false;
|
|
154381
|
+
try {
|
|
154382
|
+
const current = readRawWrapupState(db, sessionId);
|
|
154383
|
+
if (!current || current.holderId !== holderId || current.expiresAt <= now) {
|
|
154384
|
+
db.exec("ROLLBACK");
|
|
154385
|
+
finished = true;
|
|
154386
|
+
return null;
|
|
154387
|
+
}
|
|
154388
|
+
const next = {
|
|
154389
|
+
...current,
|
|
154390
|
+
...updates,
|
|
154391
|
+
holderId,
|
|
154392
|
+
expiresAt: now + WRAPUP_IN_PROGRESS_TTL_MS,
|
|
154393
|
+
updatedAt: now
|
|
154394
|
+
};
|
|
154395
|
+
db.prepare("UPDATE session_meta SET wrapup_in_progress_state = ? WHERE session_id = ?").run(stableStringify(next), sessionId);
|
|
154396
|
+
db.exec("COMMIT");
|
|
154397
|
+
finished = true;
|
|
154398
|
+
return next;
|
|
154399
|
+
} finally {
|
|
154400
|
+
if (!finished) {
|
|
154401
|
+
try {
|
|
154402
|
+
db.exec("ROLLBACK");
|
|
154403
|
+
} catch {}
|
|
154404
|
+
}
|
|
154405
|
+
}
|
|
154406
|
+
}
|
|
154407
|
+
function releaseWrapupInProgress(db, sessionId, holderId) {
|
|
154408
|
+
db.exec("BEGIN IMMEDIATE");
|
|
154409
|
+
let finished = false;
|
|
154410
|
+
try {
|
|
154411
|
+
const current = readRawWrapupState(db, sessionId);
|
|
154412
|
+
if (current?.holderId === holderId) {
|
|
154413
|
+
db.prepare("UPDATE session_meta SET wrapup_in_progress_state = NULL WHERE session_id = ?").run(sessionId);
|
|
154414
|
+
}
|
|
154415
|
+
db.exec("COMMIT");
|
|
154416
|
+
finished = true;
|
|
154417
|
+
} finally {
|
|
154418
|
+
if (!finished) {
|
|
154419
|
+
try {
|
|
154420
|
+
db.exec("ROLLBACK");
|
|
154421
|
+
} catch {}
|
|
154422
|
+
}
|
|
154423
|
+
}
|
|
154424
|
+
}
|
|
153889
154425
|
function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
|
|
153890
154426
|
if (usagePercentage >= 95)
|
|
153891
154427
|
return Math.min(1e6, Math.max(4 * perRunCap, Math.round(0.5 * usable)));
|
|
@@ -155742,7 +156278,7 @@ var ERROR_CLASSES = new Set([
|
|
|
155742
156278
|
// ../plugin/src/features/magic-context/v22-deferred-backfill.ts
|
|
155743
156279
|
init_logger();
|
|
155744
156280
|
import { createHash as createHash4 } from "node:crypto";
|
|
155745
|
-
import { realpathSync } from "node:fs";
|
|
156281
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
155746
156282
|
import path5 from "node:path";
|
|
155747
156283
|
|
|
155748
156284
|
// ../plugin/src/features/magic-context/memory/relocate-memory.ts
|
|
@@ -155776,7 +156312,10 @@ function countFailures(db) {
|
|
|
155776
156312
|
}
|
|
155777
156313
|
function classifyBackfillError(error) {
|
|
155778
156314
|
if (error instanceof ProjectIdentityError) {
|
|
155779
|
-
return {
|
|
156315
|
+
return {
|
|
156316
|
+
errorClass: error.errorClass === "dubious_ownership" ? "unknown" : error.errorClass,
|
|
156317
|
+
errorMessage: error.message
|
|
156318
|
+
};
|
|
155780
156319
|
}
|
|
155781
156320
|
if (error instanceof Error) {
|
|
155782
156321
|
return { errorClass: "unknown", errorMessage: error.message };
|
|
@@ -155796,7 +156335,7 @@ function resolveBackfillIdentity(rawProjectPath) {
|
|
|
155796
156335
|
function computeLegacyRustDirIdentity(rawProjectPath) {
|
|
155797
156336
|
let canonical;
|
|
155798
156337
|
try {
|
|
155799
|
-
canonical =
|
|
156338
|
+
canonical = realpathSync2(rawProjectPath);
|
|
155800
156339
|
} catch {
|
|
155801
156340
|
canonical = path5.isAbsolute(rawProjectPath) ? rawProjectPath : path5.join(process.cwd(), rawProjectPath);
|
|
155802
156341
|
}
|
|
@@ -156487,11 +157026,12 @@ function compareSemverCore(a, b) {
|
|
|
156487
157026
|
|
|
156488
157027
|
// ../plugin/src/shared/announcement.ts
|
|
156489
157028
|
init_data_path();
|
|
156490
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
157029
|
+
var ANNOUNCEMENT_VERSION = "0.31.0";
|
|
156491
157030
|
var ANNOUNCEMENT_FEATURES = [
|
|
156492
|
-
"
|
|
156493
|
-
"
|
|
156494
|
-
"
|
|
157031
|
+
"New /ctx-wrapup command: compact older history on demand, keeping the newest N messages raw. Run it before switching to a smaller-context model.",
|
|
157032
|
+
"ctx_search now also searches your session notes and smart notes.",
|
|
157033
|
+
"Project identity now survives transient git failures (slow disks, dubious ownership) without splitting your project memory.",
|
|
157034
|
+
"Removed the ctx_reduce_enabled setting; agent-controlled reduction is always on. Caveman text compression is now independent (caveman_text_compression.enabled)."
|
|
156495
157035
|
];
|
|
156496
157036
|
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU";
|
|
156497
157037
|
var STATE_FILENAME = "last_announced_version";
|
|
@@ -156667,7 +157207,7 @@ init_logger();
|
|
|
156667
157207
|
|
|
156668
157208
|
// src/subagent-runner.ts
|
|
156669
157209
|
import * as childProcess from "node:child_process";
|
|
156670
|
-
import { existsSync as
|
|
157210
|
+
import { existsSync as existsSync9, mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
156671
157211
|
import { createRequire as createRequire2 } from "node:module";
|
|
156672
157212
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
156673
157213
|
import { basename as basename2, dirname as dirname4, join as join8, resolve as resolvePath } from "node:path";
|
|
@@ -156798,7 +157338,7 @@ function resolveBundledPiCli() {
|
|
|
156798
157338
|
const require_ = createRequire2(import.meta.url);
|
|
156799
157339
|
const pkgJson = require_.resolve("@earendil-works/pi-coding-agent/package.json");
|
|
156800
157340
|
const cliPath = join8(dirname4(pkgJson), "dist/cli.js");
|
|
156801
|
-
if (
|
|
157341
|
+
if (existsSync9(cliPath))
|
|
156802
157342
|
return cliPath;
|
|
156803
157343
|
return null;
|
|
156804
157344
|
} catch {
|
|
@@ -156809,7 +157349,7 @@ function resolvePiInvocation() {
|
|
|
156809
157349
|
const execPath = process.execPath;
|
|
156810
157350
|
const currentScript = process.argv[1];
|
|
156811
157351
|
const isBunVirtualScript = currentScript?.startsWith("/$bunfs/root/") ?? false;
|
|
156812
|
-
if (currentScript && !isBunVirtualScript &&
|
|
157352
|
+
if (currentScript && !isBunVirtualScript && existsSync9(currentScript)) {
|
|
156813
157353
|
return { command: execPath, prefixArgs: [currentScript] };
|
|
156814
157354
|
}
|
|
156815
157355
|
const execName = basename2(execPath).toLowerCase();
|
|
@@ -156827,7 +157367,7 @@ function resolveSubagentEntryPath() {
|
|
|
156827
157367
|
try {
|
|
156828
157368
|
const here = dirname4(fileURLToPath(import.meta.url));
|
|
156829
157369
|
const candidate = resolvePath(here, "subagent-entry.js");
|
|
156830
|
-
if (
|
|
157370
|
+
if (existsSync9(candidate))
|
|
156831
157371
|
return candidate;
|
|
156832
157372
|
return;
|
|
156833
157373
|
} catch {
|
|
@@ -157496,12 +158036,13 @@ ${sidekickText}
|
|
|
157496
158036
|
init_logger();
|
|
157497
158037
|
|
|
157498
158038
|
// ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
|
|
157499
|
-
import { existsSync as
|
|
158039
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
157500
158040
|
init_logger();
|
|
157501
158041
|
|
|
157502
158042
|
// ../plugin/src/features/magic-context/compaction-marker.ts
|
|
157503
158043
|
init_data_path();
|
|
157504
158044
|
init_logger();
|
|
158045
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
157505
158046
|
import { join as join9 } from "node:path";
|
|
157506
158047
|
var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
157507
158048
|
function randomBase62(length) {
|
|
@@ -157568,6 +158109,9 @@ function getWritableOpenCodeDb() {
|
|
|
157568
158109
|
closeQuietly(cachedWriteDb.db);
|
|
157569
158110
|
} catch {}
|
|
157570
158111
|
}
|
|
158112
|
+
if (!existsSync10(dbPath)) {
|
|
158113
|
+
throw new Error(`OpenCode database not found at ${dbPath} (is OpenCode installed?)`);
|
|
158114
|
+
}
|
|
157571
158115
|
const db = new Database(dbPath);
|
|
157572
158116
|
db.exec("PRAGMA busy_timeout=5000");
|
|
157573
158117
|
db.exec("PRAGMA journal_mode=WAL");
|
|
@@ -157686,8 +158230,8 @@ function removeCompactionMarker(state) {
|
|
|
157686
158230
|
// ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
|
|
157687
158231
|
function openOpenCodeDb() {
|
|
157688
158232
|
const dbPath = getOpenCodeDbPath2();
|
|
157689
|
-
if (!
|
|
157690
|
-
log(`[
|
|
158233
|
+
if (!existsSync11(dbPath)) {
|
|
158234
|
+
log(`[dreamer] OpenCode DB not found at ${dbPath} — skipping OpenCode history scan`);
|
|
157691
158235
|
return null;
|
|
157692
158236
|
}
|
|
157693
158237
|
try {
|
|
@@ -157695,14 +158239,14 @@ function openOpenCodeDb() {
|
|
|
157695
158239
|
db.exec("PRAGMA busy_timeout = 5000");
|
|
157696
158240
|
return db;
|
|
157697
158241
|
} catch (error) {
|
|
157698
|
-
log(`[
|
|
158242
|
+
log(`[dreamer] failed to open OpenCode DB at ${dbPath}: ${getErrorMessage(error)}`);
|
|
157699
158243
|
return null;
|
|
157700
158244
|
}
|
|
157701
158245
|
}
|
|
157702
158246
|
|
|
157703
158247
|
// ../plugin/src/features/magic-context/dreamer/task-executor.ts
|
|
157704
158248
|
import { createHash as createHash10 } from "node:crypto";
|
|
157705
|
-
import { existsSync as
|
|
158249
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
157706
158250
|
|
|
157707
158251
|
// ../plugin/src/agents/dreamer.ts
|
|
157708
158252
|
var DREAMER_AGENT = "dreamer";
|
|
@@ -172654,7 +173198,6 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
172654
173198
|
enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
|
|
172655
173199
|
auto_update: exports_external.boolean().optional().describe("Enable automatic npm self-update checks for the OpenCode plugin. Security: USER-only in config loader, so hostile project configs cannot suppress updates."),
|
|
172656
173200
|
language: exports_external.string().trim().toLowerCase().refine((s) => isValidLanguageCode(s), 'language must be a 2-letter ISO 639-1 code (e.g. "tr", "es", "de")').optional().describe("Output language for Magic Context's generated content and guidance, as a " + '2-letter ISO 639-1 code (e.g. "tr", "es", "de", "ja", "pt"). When set, the ' + "historian, dreamer, sidekick, and the agent-guidance block instruct the model to " + "write its PROSE in this language while keeping all structural tokens (XML tags, " + "the five memory category names, code identifiers, file paths) in English. " + "USER-LEVEL ONLY (ignored in project config for security). Unset = today's " + "behavior (model mirrors the conversation; English scaffolding). Changing it " + "triggers one cache re-materialization; existing compartments/memories keep their " + "original language until naturally rewritten."),
|
|
172657
|
-
ctx_reduce_enabled: exports_external.boolean().default(true).describe("When false, ctx_reduce tool is hidden, all nudges disabled, and prompt guidance about ctx_reduce stripped. Heuristic cleanup, compartments, memory, and other features still work. (default: true)"),
|
|
172658
173201
|
historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
|
|
172659
173202
|
dreamer: DreamerConfigSchema.optional().describe("Dreamer agent + scheduling configuration (model, fallback_models, disable, schedule, tasks, etc.)"),
|
|
172660
173203
|
cache_ttl: exports_external.union([exports_external.string(), exports_external.object({ default: exports_external.string() }).catchall(exports_external.string())]).default("5m").describe('Cache TTL: string (e.g. "5m") or per-model object ({ default: "5m", "model-id": "10m" })'),
|
|
@@ -172693,9 +173236,9 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
172693
173236
|
keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
|
|
172694
173237
|
smart_drops: exports_external.boolean().default(false).describe("Content-aware reclaim of provably-superseded tool output, layered on the existing execute-pass auto-drop. When on: superseded todowrite (keep newest 1), spent ctx_reduce (keep newest 5), and zero-value meta (bash_status, bash_kill, ctx_note read/dismiss) outputs are dropped; older edits to a file are compressed to a filePath-preserving marker while the newest edit per file stays full. Only acts on passes already busting the cache, so it never originates a cache bust. Honors the protected-tag reserve. Experimental: opt-in, default off until cache stability is proven; when off the wire is byte-identical to the positional-only reclaim. Requires a restart."),
|
|
172695
173238
|
caveman_text_compression: exports_external.object({
|
|
172696
|
-
enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text.
|
|
173239
|
+
enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text. Active for primary sessions when enabled; never for subagents. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%)."),
|
|
172697
173240
|
min_chars: exports_external.number().min(100).max(1e4).default(500).describe("Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.")
|
|
172698
|
-
}).default({ enabled: false, min_chars: 500 }).describe("Age-tier caveman compression for long user/assistant text parts.
|
|
173241
|
+
}).default({ enabled: false, min_chars: 500 }).describe("Age-tier caveman compression for long user/assistant text parts. Active for primary sessions when enabled; never for subagents. Oldest 20% of eligible tags (outside protected tail) go to ultra, next 20% to full, next 20% to lite, newest 40% untouched. Graduated from experimental.caveman_text_compression; opt-in, default off (lossy)."),
|
|
172699
173242
|
memory: exports_external.object({
|
|
172700
173243
|
enabled: exports_external.boolean().default(true).describe("Enable cross-session memory (default: true)"),
|
|
172701
173244
|
injection_budget_tokens: exports_external.number().min(500).max(20000).default(4000).describe("Token budget for memory injection on session start (min: 500, max: 20000, default: 4000)"),
|
|
@@ -173502,7 +174045,8 @@ function isNativeRuntimeMissingError(error51) {
|
|
|
173502
174045
|
if (code === "ERR_DLOPEN_FAILED" && lower.includes("onnxruntime")) {
|
|
173503
174046
|
return true;
|
|
173504
174047
|
}
|
|
173505
|
-
|
|
174048
|
+
const mentionsNativeRuntime = lower.includes("onnxruntime-node") || lower.includes("onnxruntime_binding");
|
|
174049
|
+
if (!mentionsNativeRuntime)
|
|
173506
174050
|
return false;
|
|
173507
174051
|
return code === "ERR_MODULE_NOT_FOUND" || name2 === "ResolveMessage" || lower.includes("cannot find package") || lower.includes("cannot find module") || lower.includes("err_module_not_found");
|
|
173508
174052
|
}
|
|
@@ -173647,7 +174191,7 @@ class LocalEmbeddingProvider {
|
|
|
173647
174191
|
} catch (error51) {
|
|
173648
174192
|
if (isNativeRuntimeMissingError(error51)) {
|
|
173649
174193
|
nativeRuntimeMissing = true;
|
|
173650
|
-
log("[magic-context] local
|
|
174194
|
+
log("[magic-context] local embeddings are disabled because the onnxruntime-node native binding is missing or failed to load. Run `npx @cortexkit/magic-context@latest doctor` for repair guidance (use `doctor --force` to reinstall cached plugin packages), or configure an `openai-compatible` embedding HTTP endpoint. Existing memories are unaffected.");
|
|
173651
174195
|
} else {
|
|
173652
174196
|
log("[magic-context] embedding model failed to load:", error51);
|
|
173653
174197
|
}
|
|
@@ -174572,77 +175116,6 @@ function invalidateMemory(projectPath, memoryId) {
|
|
|
174572
175116
|
}
|
|
174573
175117
|
}
|
|
174574
175118
|
|
|
174575
|
-
// ../plugin/src/features/magic-context/session-project-storage.ts
|
|
174576
|
-
var upsertSessionProjectStatements = new WeakMap;
|
|
174577
|
-
var repairSessionChunkProjectStatements = new WeakMap;
|
|
174578
|
-
var repairProjectChunkProjectStatements = new WeakMap;
|
|
174579
|
-
function getUpsertSessionProjectStatement(db) {
|
|
174580
|
-
let stmt = upsertSessionProjectStatements.get(db);
|
|
174581
|
-
if (!stmt) {
|
|
174582
|
-
stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
|
|
174583
|
-
VALUES (?, ?, ?, ?)
|
|
174584
|
-
ON CONFLICT(session_id, harness) DO UPDATE SET
|
|
174585
|
-
project_path = excluded.project_path,
|
|
174586
|
-
updated_at = excluded.updated_at
|
|
174587
|
-
WHERE session_projects.project_path <> excluded.project_path`);
|
|
174588
|
-
upsertSessionProjectStatements.set(db, stmt);
|
|
174589
|
-
}
|
|
174590
|
-
return stmt;
|
|
174591
|
-
}
|
|
174592
|
-
function getRepairSessionChunkProjectStatement(db) {
|
|
174593
|
-
let stmt = repairSessionChunkProjectStatements.get(db);
|
|
174594
|
-
if (!stmt) {
|
|
174595
|
-
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
174596
|
-
SET project_path = ?
|
|
174597
|
-
WHERE session_id = ?
|
|
174598
|
-
AND harness = ?
|
|
174599
|
-
AND project_path <> ?`);
|
|
174600
|
-
repairSessionChunkProjectStatements.set(db, stmt);
|
|
174601
|
-
}
|
|
174602
|
-
return stmt;
|
|
174603
|
-
}
|
|
174604
|
-
function getRepairProjectChunkProjectStatement(db) {
|
|
174605
|
-
let stmt = repairProjectChunkProjectStatements.get(db);
|
|
174606
|
-
if (!stmt) {
|
|
174607
|
-
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
174608
|
-
SET project_path = (
|
|
174609
|
-
SELECT sp.project_path
|
|
174610
|
-
FROM session_projects sp
|
|
174611
|
-
WHERE sp.session_id = compartment_chunk_embeddings.session_id
|
|
174612
|
-
AND sp.harness = compartment_chunk_embeddings.harness
|
|
174613
|
-
LIMIT 1
|
|
174614
|
-
)
|
|
174615
|
-
WHERE EXISTS (
|
|
174616
|
-
SELECT 1
|
|
174617
|
-
FROM session_projects sp
|
|
174618
|
-
WHERE sp.session_id = compartment_chunk_embeddings.session_id
|
|
174619
|
-
AND sp.harness = compartment_chunk_embeddings.harness
|
|
174620
|
-
AND sp.project_path <> compartment_chunk_embeddings.project_path
|
|
174621
|
-
AND (
|
|
174622
|
-
sp.project_path = ?
|
|
174623
|
-
OR compartment_chunk_embeddings.project_path = ?
|
|
174624
|
-
)
|
|
174625
|
-
)`);
|
|
174626
|
-
repairProjectChunkProjectStatements.set(db, stmt);
|
|
174627
|
-
}
|
|
174628
|
-
return stmt;
|
|
174629
|
-
}
|
|
174630
|
-
function recordSessionProjectIdentity(db, sessionId, projectPath) {
|
|
174631
|
-
if (!sessionId || !projectPath)
|
|
174632
|
-
return;
|
|
174633
|
-
const harness = getHarness();
|
|
174634
|
-
const now = Date.now();
|
|
174635
|
-
db.transaction(() => {
|
|
174636
|
-
getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
|
|
174637
|
-
getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
|
|
174638
|
-
})();
|
|
174639
|
-
}
|
|
174640
|
-
function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
|
|
174641
|
-
if (!projectPath)
|
|
174642
|
-
return 0;
|
|
174643
|
-
return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
|
|
174644
|
-
}
|
|
174645
|
-
|
|
174646
175119
|
// ../plugin/src/features/magic-context/project-embedding-registry.ts
|
|
174647
175120
|
var OFF_PROVIDER_IDENTITY = "embedding-provider:off";
|
|
174648
175121
|
var SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
|
|
@@ -176295,7 +176768,7 @@ function getMemoryVerifications(db, memoryIds) {
|
|
|
176295
176768
|
}
|
|
176296
176769
|
// ../plugin/src/features/magic-context/memory/verification-paths.ts
|
|
176297
176770
|
import { execFile } from "node:child_process";
|
|
176298
|
-
import { existsSync as
|
|
176771
|
+
import { existsSync as existsSync12, realpathSync as realpathSync3, statSync as statSync4 } from "node:fs";
|
|
176299
176772
|
import path7 from "node:path";
|
|
176300
176773
|
import { promisify } from "node:util";
|
|
176301
176774
|
var execFileAsync = promisify(execFile);
|
|
@@ -176322,7 +176795,7 @@ function isWithin(root, candidate) {
|
|
|
176322
176795
|
}
|
|
176323
176796
|
function safeRealpath(value) {
|
|
176324
176797
|
try {
|
|
176325
|
-
return
|
|
176798
|
+
return realpathSync3.native(value);
|
|
176326
176799
|
} catch {
|
|
176327
176800
|
return null;
|
|
176328
176801
|
}
|
|
@@ -176400,7 +176873,7 @@ function verificationFileExists(baseRoot, filePath) {
|
|
|
176400
176873
|
return false;
|
|
176401
176874
|
const root = path7.resolve(baseRoot);
|
|
176402
176875
|
const candidate = path7.resolve(root, filePath);
|
|
176403
|
-
return isWithin(root, candidate) &&
|
|
176876
|
+
return isWithin(root, candidate) && existsSync12(candidate);
|
|
176404
176877
|
}
|
|
176405
176878
|
async function normalizeVerificationFiles(args) {
|
|
176406
176879
|
const cwd = path7.resolve(args.cwd);
|
|
@@ -176433,7 +176906,7 @@ async function normalizeVerificationFiles(args) {
|
|
|
176433
176906
|
warnings.push(`Skipped verification path "${value}" because it is the repo/project root.`);
|
|
176434
176907
|
continue;
|
|
176435
176908
|
}
|
|
176436
|
-
if (
|
|
176909
|
+
if (existsSync12(candidate)) {
|
|
176437
176910
|
try {
|
|
176438
176911
|
if (statSync4(candidate).isDirectory()) {
|
|
176439
176912
|
warnings.push(`Skipped verification path "${value}" because it is a directory.`);
|
|
@@ -176464,7 +176937,7 @@ async function normalizeVerificationFiles(args) {
|
|
|
176464
176937
|
}
|
|
176465
176938
|
normalized.push(tracked);
|
|
176466
176939
|
} else {
|
|
176467
|
-
if (!
|
|
176940
|
+
if (!existsSync12(candidate)) {
|
|
176468
176941
|
warnings.push(`Skipped verification path "${value}" because it does not exist.`);
|
|
176469
176942
|
continue;
|
|
176470
176943
|
}
|
|
@@ -179107,7 +179580,7 @@ Output exactly JSON: {"met": false}`;
|
|
|
179107
179580
|
|
|
179108
179581
|
// ../plugin/src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
|
|
179109
179582
|
init_logger();
|
|
179110
|
-
import { existsSync as
|
|
179583
|
+
import { existsSync as existsSync13, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
|
|
179111
179584
|
import { join as join11 } from "node:path";
|
|
179112
179585
|
|
|
179113
179586
|
// ../plugin/src/features/magic-context/dreamer/protected-regions.ts
|
|
@@ -179211,7 +179684,7 @@ function snapshotMaintainDocsFiles(docsDir) {
|
|
|
179211
179684
|
for (const name2 of MAINTAIN_DOCS_SNAPSHOT_FILES) {
|
|
179212
179685
|
const path9 = join11(docsDir, name2);
|
|
179213
179686
|
try {
|
|
179214
|
-
if (
|
|
179687
|
+
if (existsSync13(path9)) {
|
|
179215
179688
|
snapshot.set(name2, readFileSync6(path9, "utf8"));
|
|
179216
179689
|
}
|
|
179217
179690
|
} catch {}
|
|
@@ -179239,7 +179712,7 @@ function enforceMaintainDocsProtectedRegions(args) {
|
|
|
179239
179712
|
init_logger();
|
|
179240
179713
|
|
|
179241
179714
|
// ../plugin/src/features/magic-context/dreamer/map-memories-prompt.ts
|
|
179242
|
-
import { existsSync as
|
|
179715
|
+
import { existsSync as existsSync14, statSync as statSync5 } from "node:fs";
|
|
179243
179716
|
import path9 from "node:path";
|
|
179244
179717
|
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.
|
|
179245
179718
|
|
|
@@ -179277,7 +179750,7 @@ function extractMemoryCandidatePaths(content, repoDir) {
|
|
|
179277
179750
|
if (!abs.startsWith(`${root}/`))
|
|
179278
179751
|
continue;
|
|
179279
179752
|
try {
|
|
179280
|
-
if (
|
|
179753
|
+
if (existsSync14(abs) && statSync5(abs).isFile())
|
|
179281
179754
|
found.add(rel);
|
|
179282
179755
|
} catch {}
|
|
179283
179756
|
if (found.size >= MAX_SEED_PATHS_PER_MEMORY)
|
|
@@ -181418,8 +181891,8 @@ async function runAgenticTask(config2, ctx, helpers) {
|
|
|
181418
181891
|
const lastRunAt = getTaskScheduleState(db, projectIdentity, config2.task)?.lastRunAt ?? null;
|
|
181419
181892
|
const maintainDocsSnapshot = task === "maintain-docs" ? snapshotMaintainDocsFiles(docsDir) : undefined;
|
|
181420
181893
|
const existingDocs = task === "maintain-docs" ? {
|
|
181421
|
-
architecture:
|
|
181422
|
-
structure:
|
|
181894
|
+
architecture: existsSync15(`${docsDir}/ARCHITECTURE.md`),
|
|
181895
|
+
structure: existsSync15(`${docsDir}/STRUCTURE.md`)
|
|
181423
181896
|
} : undefined;
|
|
181424
181897
|
const userMemories = task === "curate" ? getActiveUserMemories(db).map((um) => ({ id: um.id, content: um.content })) : undefined;
|
|
181425
181898
|
let curateMemories;
|
|
@@ -182634,7 +183107,7 @@ function pruneNestedConfigLeaf(block, relativePath) {
|
|
|
182634
183107
|
}
|
|
182635
183108
|
|
|
182636
183109
|
// src/config/index.ts
|
|
182637
|
-
import { existsSync as
|
|
183110
|
+
import { existsSync as existsSync17, readFileSync as readFileSync8 } from "node:fs";
|
|
182638
183111
|
|
|
182639
183112
|
// ../plugin/src/config/migrate-dreamer-v2.ts
|
|
182640
183113
|
var OLD_VERIFY_TASK = "verify";
|
|
@@ -183016,7 +183489,7 @@ function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
|
|
|
183016
183489
|
}
|
|
183017
183490
|
|
|
183018
183491
|
// ../plugin/src/config/variable.ts
|
|
183019
|
-
import { existsSync as
|
|
183492
|
+
import { existsSync as existsSync16, readFileSync as readFileSync7 } from "node:fs";
|
|
183020
183493
|
import { homedir as homedir4 } from "node:os";
|
|
183021
183494
|
import { dirname as dirname6, isAbsolute as isAbsolute2, resolve } from "node:path";
|
|
183022
183495
|
|
|
@@ -183151,7 +183624,7 @@ function substituteConfigVariables(input) {
|
|
|
183151
183624
|
if (sensitiveReason) {
|
|
183152
183625
|
warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
|
|
183153
183626
|
}
|
|
183154
|
-
if (!
|
|
183627
|
+
if (!existsSync16(filePath)) {
|
|
183155
183628
|
warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
|
|
183156
183629
|
continue;
|
|
183157
183630
|
}
|
|
@@ -183180,10 +183653,10 @@ function getUserConfigPaths() {
|
|
|
183180
183653
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
183181
183654
|
}
|
|
183182
183655
|
function resolveFirstExisting(paths) {
|
|
183183
|
-
return paths.find((path11) =>
|
|
183656
|
+
return paths.find((path11) => existsSync17(path11));
|
|
183184
183657
|
}
|
|
183185
183658
|
function resolvePiLegacyFallback(sources) {
|
|
183186
|
-
return sources.find((source) =>
|
|
183659
|
+
return sources.find((source) => existsSync17(source.path)) ?? null;
|
|
183187
183660
|
}
|
|
183188
183661
|
function loadConfigFile(path11, scope) {
|
|
183189
183662
|
try {
|
|
@@ -183320,7 +183793,7 @@ function loadPiConfig(opts = {}) {
|
|
|
183320
183793
|
if (loaded)
|
|
183321
183794
|
loadedFiles.push(loaded);
|
|
183322
183795
|
}
|
|
183323
|
-
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) =>
|
|
183796
|
+
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync17(source.path));
|
|
183324
183797
|
const userPath = resolveFirstExisting(getUserConfigPaths());
|
|
183325
183798
|
const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
|
|
183326
183799
|
const userReadPath = userPath ?? userLegacyFallback?.path;
|
|
@@ -183329,7 +183802,7 @@ function loadPiConfig(opts = {}) {
|
|
|
183329
183802
|
if (loaded)
|
|
183330
183803
|
loadedFiles.push(loaded);
|
|
183331
183804
|
}
|
|
183332
|
-
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) =>
|
|
183805
|
+
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync17(source.path));
|
|
183333
183806
|
if (userLegacyFallback) {
|
|
183334
183807
|
warnings.push(`[user config] reading legacy config from ${userLegacyFallback.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
|
|
183335
183808
|
} else if (legacyUserUnmigrated) {
|
|
@@ -183430,7 +183903,7 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
183430
183903
|
if (loaded)
|
|
183431
183904
|
loadedFiles.push(loaded);
|
|
183432
183905
|
}
|
|
183433
|
-
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) =>
|
|
183906
|
+
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync17(source.path));
|
|
183434
183907
|
const userPath = resolveFirstExisting(getUserConfigPaths());
|
|
183435
183908
|
const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
|
|
183436
183909
|
const userReadPath = userPath ?? userLegacyFallback?.path;
|
|
@@ -183439,7 +183912,7 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
183439
183912
|
if (loaded)
|
|
183440
183913
|
loadedFiles.push(loaded);
|
|
183441
183914
|
}
|
|
183442
|
-
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) =>
|
|
183915
|
+
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync17(source.path));
|
|
183443
183916
|
if (userLegacyFallback) {
|
|
183444
183917
|
warnings.push(`[user config] reading legacy config from ${userLegacyFallback.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
|
|
183445
183918
|
} else if (legacyUserUnmigrated) {
|
|
@@ -184910,7 +185383,8 @@ var canonicalReasons = new Set([
|
|
|
184910
185383
|
"first_render",
|
|
184911
185384
|
"pressure_refold",
|
|
184912
185385
|
"upgrade_state",
|
|
184913
|
-
"cached_m1_missing"
|
|
185386
|
+
"cached_m1_missing",
|
|
185387
|
+
"project_change"
|
|
184914
185388
|
]);
|
|
184915
185389
|
var piReasonAliases = {
|
|
184916
185390
|
project_memory_change: "project_memory_epoch",
|
|
@@ -186189,6 +186663,43 @@ function semanticSnapBoundary(args) {
|
|
|
186189
186663
|
}
|
|
186190
186664
|
return snapped;
|
|
186191
186665
|
}
|
|
186666
|
+
function snapWrapupBoundaryToUser(args) {
|
|
186667
|
+
const { messages, index, candidate, offset, triggerBudget } = args;
|
|
186668
|
+
if (candidate <= offset)
|
|
186669
|
+
return candidate;
|
|
186670
|
+
const snapTokenLimit = Math.min(Math.max(triggerBudget, 2000), 48000);
|
|
186671
|
+
for (let ordinal = candidate;ordinal >= offset; ordinal -= 1) {
|
|
186672
|
+
const message = messages.find((m) => m.ordinal === ordinal);
|
|
186673
|
+
if (!message)
|
|
186674
|
+
continue;
|
|
186675
|
+
if (message.role !== "user" || !hasMeaningfulUserText(message.parts))
|
|
186676
|
+
continue;
|
|
186677
|
+
const extraTokens = index.rangeTokens(ordinal, candidate);
|
|
186678
|
+
if (extraTokens <= snapTokenLimit)
|
|
186679
|
+
return ordinal;
|
|
186680
|
+
return candidate;
|
|
186681
|
+
}
|
|
186682
|
+
return candidate;
|
|
186683
|
+
}
|
|
186684
|
+
function fenceWrapupBoundaryForToolArcs(args) {
|
|
186685
|
+
let boundary = args.candidate;
|
|
186686
|
+
const maxPasses = args.arcs.length + 1;
|
|
186687
|
+
for (let pass = 0;pass < maxPasses; pass += 1) {
|
|
186688
|
+
let next = boundary;
|
|
186689
|
+
for (const arc of args.arcs) {
|
|
186690
|
+
if (arc.resOrdinal === null) {
|
|
186691
|
+
continue;
|
|
186692
|
+
}
|
|
186693
|
+
if (arc.invOrdinal >= args.lastCompartmentEndOrdinal + 1 && arc.invOrdinal < next && next <= arc.resOrdinal) {
|
|
186694
|
+
next = arc.invOrdinal;
|
|
186695
|
+
}
|
|
186696
|
+
}
|
|
186697
|
+
if (next === boundary)
|
|
186698
|
+
return boundary;
|
|
186699
|
+
boundary = next;
|
|
186700
|
+
}
|
|
186701
|
+
return boundary;
|
|
186702
|
+
}
|
|
186192
186703
|
function applyHeadCap(args) {
|
|
186193
186704
|
const { index, protectedTailStart, offset, arcs, capTokens, recentOpenArcCutoff } = args;
|
|
186194
186705
|
if (offset >= protectedTailStart)
|
|
@@ -186444,6 +186955,124 @@ function resolveBoundaryContext(args) {
|
|
|
186444
186955
|
function resolveOpenCodeProtectedTailBoundary(args) {
|
|
186445
186956
|
return resolveProtectedTailBoundary(resolveBoundaryContext(args));
|
|
186446
186957
|
}
|
|
186958
|
+
function resolveWrapupProtectedTailBoundary(args) {
|
|
186959
|
+
const ctx = resolveBoundaryContext({ ...args, mode: "manual-wrapup" });
|
|
186960
|
+
const createdAt = ctx.createdAt ?? Date.now();
|
|
186961
|
+
const messages = readRawSessionMessages(ctx.sessionId);
|
|
186962
|
+
const absoluteMessageCount = getCachedAbsoluteMessageCount(ctx.sessionId) ?? undefined;
|
|
186963
|
+
const index = buildTrueRawTokenIndex(ctx.sessionId, messages, {
|
|
186964
|
+
providerShapeVersion: ctx.providerShapeVersion,
|
|
186965
|
+
cacheNamespace: ctx.cacheNamespace,
|
|
186966
|
+
absoluteMessageCount,
|
|
186967
|
+
storedTotalForMessage: ctx.storedTokenTotals ? (m) => {
|
|
186968
|
+
const value = ctx.storedTokenTotals?.get(m.id);
|
|
186969
|
+
return value === undefined ? null : value;
|
|
186970
|
+
} : undefined
|
|
186971
|
+
});
|
|
186972
|
+
const rawMessageCount = index.rawMessageCount;
|
|
186973
|
+
const offset = Math.max(1, ctx.lastCompartmentEndOrdinal + 1);
|
|
186974
|
+
const anchorRawMessageCount = Math.max(0, Math.min(rawMessageCount, Math.floor(args.anchorRawMessageCount ?? rawMessageCount)));
|
|
186975
|
+
const usagePercentage = clampPercentage(ctx.usage?.percentage ?? 0);
|
|
186976
|
+
const usageInputTokens = Math.max(0, Math.round(ctx.usage?.inputTokens ?? 0));
|
|
186977
|
+
const rawMessagesAboveLastCompartment = Math.max(0, anchorRawMessageCount - offset + 1);
|
|
186978
|
+
const keep = Math.max(1, Math.floor(args.messagesToKeep));
|
|
186979
|
+
let targetProtectedTailStart = offset;
|
|
186980
|
+
let boundaryReason = "manual-wrapup-empty";
|
|
186981
|
+
if (rawMessageCount === 0 || rawMessagesAboveLastCompartment <= keep) {
|
|
186982
|
+
targetProtectedTailStart = offset;
|
|
186983
|
+
boundaryReason = rawMessageCount === 0 ? "manual-wrapup-empty" : "manual-wrapup-within-keep";
|
|
186984
|
+
} else {
|
|
186985
|
+
targetProtectedTailStart = anchorRawMessageCount - keep + 1;
|
|
186986
|
+
boundaryReason = "manual-wrapup-keep-watermark";
|
|
186987
|
+
const arcs = buildToolArcs(messages);
|
|
186988
|
+
const fenced = fenceWrapupBoundaryForToolArcs({
|
|
186989
|
+
candidate: targetProtectedTailStart,
|
|
186990
|
+
arcs,
|
|
186991
|
+
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal
|
|
186992
|
+
});
|
|
186993
|
+
if (fenced !== targetProtectedTailStart)
|
|
186994
|
+
boundaryReason = "manual-wrapup-tool-arc";
|
|
186995
|
+
targetProtectedTailStart = fenced;
|
|
186996
|
+
const snapped = snapWrapupBoundaryToUser({
|
|
186997
|
+
messages,
|
|
186998
|
+
index,
|
|
186999
|
+
candidate: targetProtectedTailStart,
|
|
187000
|
+
offset,
|
|
187001
|
+
triggerBudget: ctx.triggerBudget
|
|
187002
|
+
});
|
|
187003
|
+
if (snapped !== targetProtectedTailStart)
|
|
187004
|
+
boundaryReason = "manual-wrapup-user-snap";
|
|
187005
|
+
targetProtectedTailStart = snapped;
|
|
187006
|
+
const refenced = fenceWrapupBoundaryForToolArcs({
|
|
187007
|
+
candidate: targetProtectedTailStart,
|
|
187008
|
+
arcs,
|
|
187009
|
+
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal
|
|
187010
|
+
});
|
|
187011
|
+
if (refenced !== targetProtectedTailStart)
|
|
187012
|
+
boundaryReason = "manual-wrapup-tool-arc";
|
|
187013
|
+
targetProtectedTailStart = refenced;
|
|
187014
|
+
}
|
|
187015
|
+
targetProtectedTailStart = clampOrdinal(targetProtectedTailStart, rawMessageCount);
|
|
187016
|
+
const target = deriveProtectedTailTokenTarget({
|
|
187017
|
+
contextLimit: ctx.contextLimit,
|
|
187018
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
187019
|
+
usagePercentage,
|
|
187020
|
+
triggerBudget: ctx.triggerBudget
|
|
187021
|
+
});
|
|
187022
|
+
const perRunCap = selectPerRunCap({
|
|
187023
|
+
usagePercentage,
|
|
187024
|
+
N: target.N,
|
|
187025
|
+
contextLimit: ctx.contextLimit,
|
|
187026
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage
|
|
187027
|
+
});
|
|
187028
|
+
const head = applyHeadCap({
|
|
187029
|
+
index,
|
|
187030
|
+
protectedTailStart: targetProtectedTailStart,
|
|
187031
|
+
offset,
|
|
187032
|
+
arcs: buildToolArcs(messages),
|
|
187033
|
+
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal,
|
|
187034
|
+
capTokens: perRunCap,
|
|
187035
|
+
recentOpenArcCutoff: targetProtectedTailStart
|
|
187036
|
+
});
|
|
187037
|
+
const eligibleEndOrdinal = Math.min(head.eligibleEndOrdinal, targetProtectedTailStart);
|
|
187038
|
+
const rawRangeFingerprint = computeRawRangeFingerprint(messages, offset, eligibleEndOrdinal);
|
|
187039
|
+
const snapshot = {
|
|
187040
|
+
sessionId: ctx.sessionId,
|
|
187041
|
+
mode: "manual-wrapup",
|
|
187042
|
+
offset,
|
|
187043
|
+
offsetMessageId: boundaryMessageId(index, offset),
|
|
187044
|
+
protectedTailStart: targetProtectedTailStart,
|
|
187045
|
+
protectedTailStartMessageId: boundaryMessageId(index, targetProtectedTailStart),
|
|
187046
|
+
eligibleEndOrdinal,
|
|
187047
|
+
eligibleEndMessageId: boundaryMessageId(index, eligibleEndOrdinal - 1),
|
|
187048
|
+
rawMessageCountAtTrigger: rawMessageCount,
|
|
187049
|
+
rawLastMessageIdAtTrigger: boundaryMessageId(index, rawMessageCount),
|
|
187050
|
+
N: keep,
|
|
187051
|
+
usagePercentage,
|
|
187052
|
+
usageInputTokens,
|
|
187053
|
+
usageSource: ctx.usageSource,
|
|
187054
|
+
contextLimit: ctx.contextLimit,
|
|
187055
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
187056
|
+
triggerBudget: ctx.triggerBudget,
|
|
187057
|
+
priorBoundaryOrdinal: ctx.priorBoundaryOrdinal,
|
|
187058
|
+
migrationFloorActive: ctx.migrationFloorActive,
|
|
187059
|
+
emergencyTailScale: ctx.emergencyTailScale,
|
|
187060
|
+
providerShapeVersion: ctx.providerShapeVersion,
|
|
187061
|
+
cacheNamespace: ctx.cacheNamespace,
|
|
187062
|
+
createdAt,
|
|
187063
|
+
rawRangeFingerprint,
|
|
187064
|
+
trueRawEligibleTokens: index.rangeTokens(offset, targetProtectedTailStart),
|
|
187065
|
+
oversizeAtomicUnit: head.oversizeAtomicUnit,
|
|
187066
|
+
boundaryReason
|
|
187067
|
+
};
|
|
187068
|
+
return {
|
|
187069
|
+
snapshot,
|
|
187070
|
+
rawMessagesAboveLastCompartment,
|
|
187071
|
+
anchorRawMessageCount,
|
|
187072
|
+
targetProtectedTailStart,
|
|
187073
|
+
targetEligibleEndOrdinal: targetProtectedTailStart
|
|
187074
|
+
};
|
|
187075
|
+
}
|
|
186447
187076
|
function getRawHistoryEligibility(db, sessionId) {
|
|
186448
187077
|
const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
|
|
186449
187078
|
const offset = Math.max(1, lastCompartmentEnd + 1);
|
|
@@ -188489,6 +189118,147 @@ function searchMessages(args) {
|
|
|
188489
189118
|
role: entry.row.role
|
|
188490
189119
|
}));
|
|
188491
189120
|
}
|
|
189121
|
+
var NOTE_SEARCHABLE_STATUSES = ["active", "pending", "ready", "dismissed"];
|
|
189122
|
+
function noteSearchText(note) {
|
|
189123
|
+
const reason = note.readyReason?.trim();
|
|
189124
|
+
return reason ? `${note.content}
|
|
189125
|
+
Reason: ${reason}` : note.content;
|
|
189126
|
+
}
|
|
189127
|
+
function tokenizeKeywordNeedle(text) {
|
|
189128
|
+
const matches = text.toLowerCase().match(/[a-z0-9/._:-]+/g) ?? [];
|
|
189129
|
+
const seen = new Set;
|
|
189130
|
+
const tokens = [];
|
|
189131
|
+
for (const match of matches) {
|
|
189132
|
+
if (match.length <= 1 || !/[a-z0-9]/.test(match) || seen.has(match)) {
|
|
189133
|
+
continue;
|
|
189134
|
+
}
|
|
189135
|
+
seen.add(match);
|
|
189136
|
+
tokens.push(match);
|
|
189137
|
+
}
|
|
189138
|
+
return tokens;
|
|
189139
|
+
}
|
|
189140
|
+
function rankNotesForNeedle(notes, needle) {
|
|
189141
|
+
const normalizedNeedle = needle.trim().toLowerCase();
|
|
189142
|
+
if (normalizedNeedle.length === 0) {
|
|
189143
|
+
return [];
|
|
189144
|
+
}
|
|
189145
|
+
const needleTokens = tokenizeKeywordNeedle(normalizedNeedle);
|
|
189146
|
+
const ranked = [];
|
|
189147
|
+
for (const note of notes) {
|
|
189148
|
+
const text = noteSearchText(note);
|
|
189149
|
+
const normalizedText = text.toLowerCase();
|
|
189150
|
+
const noteTokens = new Set(tokenizeKeywordNeedle(normalizedText));
|
|
189151
|
+
const exact = normalizedText.includes(normalizedNeedle);
|
|
189152
|
+
const matchedTokens = needleTokens.filter((token) => noteTokens.has(token)).length;
|
|
189153
|
+
if (!exact && matchedTokens === 0) {
|
|
189154
|
+
continue;
|
|
189155
|
+
}
|
|
189156
|
+
const coverage = needleTokens.length > 0 ? matchedTokens / needleTokens.length : 0;
|
|
189157
|
+
const score = (exact ? 2 : 0) + coverage + (needleTokens.length > 1 && matchedTokens === needleTokens.length ? 0.5 : 0);
|
|
189158
|
+
ranked.push({ note, score, text });
|
|
189159
|
+
}
|
|
189160
|
+
return ranked.sort((left, right) => {
|
|
189161
|
+
if (right.score !== left.score) {
|
|
189162
|
+
return right.score - left.score;
|
|
189163
|
+
}
|
|
189164
|
+
if (right.note.createdAt !== left.note.createdAt) {
|
|
189165
|
+
return right.note.createdAt - left.note.createdAt;
|
|
189166
|
+
}
|
|
189167
|
+
return left.note.id - right.note.id;
|
|
189168
|
+
});
|
|
189169
|
+
}
|
|
189170
|
+
function searchNotes(args) {
|
|
189171
|
+
if (args.limit <= 0) {
|
|
189172
|
+
return [];
|
|
189173
|
+
}
|
|
189174
|
+
const notes = [
|
|
189175
|
+
...getNotes(args.db, {
|
|
189176
|
+
sessionId: args.sessionId,
|
|
189177
|
+
type: "session",
|
|
189178
|
+
status: NOTE_SEARCHABLE_STATUSES
|
|
189179
|
+
}),
|
|
189180
|
+
...getNotes(args.db, {
|
|
189181
|
+
projectPath: args.projectPath,
|
|
189182
|
+
type: "smart",
|
|
189183
|
+
status: NOTE_SEARCHABLE_STATUSES
|
|
189184
|
+
})
|
|
189185
|
+
];
|
|
189186
|
+
if (notes.length === 0) {
|
|
189187
|
+
return [];
|
|
189188
|
+
}
|
|
189189
|
+
const baseList = rankNotesForNeedle(notes, args.query);
|
|
189190
|
+
const probes = args.probes ?? [];
|
|
189191
|
+
if (probes.length === 0) {
|
|
189192
|
+
const ranked2 = baseList.slice(0, args.limit);
|
|
189193
|
+
return ranked2.map((entry, rank) => ({
|
|
189194
|
+
source: "note",
|
|
189195
|
+
content: previewText(entry.text),
|
|
189196
|
+
score: linearDecayScore(rank, ranked2.length),
|
|
189197
|
+
noteId: entry.note.id,
|
|
189198
|
+
status: entry.note.status,
|
|
189199
|
+
createdAt: entry.note.createdAt,
|
|
189200
|
+
anchorOrdinal: entry.note.anchorOrdinal,
|
|
189201
|
+
sourceSessionId: entry.note.sessionId
|
|
189202
|
+
}));
|
|
189203
|
+
}
|
|
189204
|
+
const queryLists = [];
|
|
189205
|
+
if (baseList.length > 0) {
|
|
189206
|
+
queryLists.push({ rows: baseList, weight: 1 });
|
|
189207
|
+
}
|
|
189208
|
+
const probeWeights = new Map;
|
|
189209
|
+
for (const probe of probes) {
|
|
189210
|
+
const rows = rankNotesForNeedle(notes, probe);
|
|
189211
|
+
if (rows.length === 0) {
|
|
189212
|
+
continue;
|
|
189213
|
+
}
|
|
189214
|
+
const weight = probeDiscriminationWeight(rows.length, notes.length);
|
|
189215
|
+
probeWeights.set(probe, weight);
|
|
189216
|
+
queryLists.push({ rows, weight });
|
|
189217
|
+
}
|
|
189218
|
+
const fused = new Map;
|
|
189219
|
+
for (const list of queryLists) {
|
|
189220
|
+
list.rows.forEach((row, rank) => {
|
|
189221
|
+
const rrf = list.weight / (RRF_K + rank);
|
|
189222
|
+
const existing = fused.get(row.note.id);
|
|
189223
|
+
if (existing) {
|
|
189224
|
+
existing.score += rrf;
|
|
189225
|
+
} else {
|
|
189226
|
+
fused.set(row.note.id, { entry: row, score: rrf });
|
|
189227
|
+
}
|
|
189228
|
+
});
|
|
189229
|
+
}
|
|
189230
|
+
for (const match of fused.values()) {
|
|
189231
|
+
let best = 0;
|
|
189232
|
+
for (const probe of probes) {
|
|
189233
|
+
const weight = probeWeights.get(probe) ?? 0;
|
|
189234
|
+
if (weight > best && containsProbeVerbatim(match.entry.text, [probe])) {
|
|
189235
|
+
best = weight;
|
|
189236
|
+
}
|
|
189237
|
+
}
|
|
189238
|
+
if (best > 0) {
|
|
189239
|
+
match.score += best * VERBATIM_RANK_BONUS;
|
|
189240
|
+
}
|
|
189241
|
+
}
|
|
189242
|
+
const ranked = [...fused.values()].sort((left, right) => {
|
|
189243
|
+
if (right.score !== left.score) {
|
|
189244
|
+
return right.score - left.score;
|
|
189245
|
+
}
|
|
189246
|
+
if (right.entry.note.createdAt !== left.entry.note.createdAt) {
|
|
189247
|
+
return right.entry.note.createdAt - left.entry.note.createdAt;
|
|
189248
|
+
}
|
|
189249
|
+
return left.entry.note.id - right.entry.note.id;
|
|
189250
|
+
}).slice(0, args.limit);
|
|
189251
|
+
return ranked.map((entry, rank) => ({
|
|
189252
|
+
source: "note",
|
|
189253
|
+
content: previewText(entry.entry.text),
|
|
189254
|
+
score: linearDecayScore(rank, ranked.length),
|
|
189255
|
+
noteId: entry.entry.note.id,
|
|
189256
|
+
status: entry.entry.note.status,
|
|
189257
|
+
createdAt: entry.entry.note.createdAt,
|
|
189258
|
+
anchorOrdinal: entry.entry.note.anchorOrdinal,
|
|
189259
|
+
sourceSessionId: entry.entry.note.sessionId
|
|
189260
|
+
}));
|
|
189261
|
+
}
|
|
188492
189262
|
function searchCompartmentChunks(args) {
|
|
188493
189263
|
if (!args.queryEmbedding || args.limit <= 0 || !args.modelId || args.modelId === "off")
|
|
188494
189264
|
return [];
|
|
@@ -188574,6 +189344,8 @@ function getSourceBoost(result) {
|
|
|
188574
189344
|
return GIT_COMMIT_SOURCE_BOOST;
|
|
188575
189345
|
case "primer":
|
|
188576
189346
|
return PRIMER_SOURCE_BOOST;
|
|
189347
|
+
case "note":
|
|
189348
|
+
return 1;
|
|
188577
189349
|
}
|
|
188578
189350
|
}
|
|
188579
189351
|
function compareUnifiedResults(left, right) {
|
|
@@ -188597,6 +189369,9 @@ function compareUnifiedResults(left, right) {
|
|
|
188597
189369
|
if (left.source === "primer" && right.source === "primer") {
|
|
188598
189370
|
return right.support - left.support || left.primerId - right.primerId;
|
|
188599
189371
|
}
|
|
189372
|
+
if (left.source === "note" && right.source === "note") {
|
|
189373
|
+
return right.createdAt - left.createdAt || left.noteId - right.noteId;
|
|
189374
|
+
}
|
|
188600
189375
|
return 0;
|
|
188601
189376
|
}
|
|
188602
189377
|
function toGitCommitResult(hit) {
|
|
@@ -188664,11 +189439,11 @@ function searchPrimers(args) {
|
|
|
188664
189439
|
}
|
|
188665
189440
|
function resolveSources(sources) {
|
|
188666
189441
|
if (sources === undefined) {
|
|
188667
|
-
return new Set(["memory", "message", "git_commit", "primer"]);
|
|
189442
|
+
return new Set(["memory", "message", "git_commit", "primer", "note"]);
|
|
188668
189443
|
}
|
|
188669
189444
|
const set2 = new Set;
|
|
188670
189445
|
for (const source of sources) {
|
|
188671
|
-
if (source === "memory" || source === "message" || source === "git_commit" || source === "primer") {
|
|
189446
|
+
if (source === "memory" || source === "message" || source === "git_commit" || source === "primer" || source === "note") {
|
|
188672
189447
|
set2.add(source);
|
|
188673
189448
|
}
|
|
188674
189449
|
}
|
|
@@ -188691,6 +189466,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
188691
189466
|
const runMessages = activeSources.has("message");
|
|
188692
189467
|
const runGitCommits = activeSources.has("git_commit") && gitCommitsEnabled;
|
|
188693
189468
|
const runPrimers = activeSources.has("primer") && memoryFeatureEnabled;
|
|
189469
|
+
const runNotes = activeSources.has("note");
|
|
188694
189470
|
const runCompartmentChunks = runMessages && memoryFeatureEnabled && embeddingEnabled;
|
|
188695
189471
|
const needsEmbedding = (runMemory || runGitCommits || runCompartmentChunks || runPrimers) && embeddingEnabled && isEmbeddingRuntimeEnabled();
|
|
188696
189472
|
const queryEmbeddingPromise = needsEmbedding ? embedQuery(trimmedQuery, options.signal).catch((error51) => {
|
|
@@ -188726,7 +189502,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
188726
189502
|
compartments: compartmentResults,
|
|
188727
189503
|
limit: tierLimit
|
|
188728
189504
|
});
|
|
188729
|
-
const [memoryResults, gitCommitResults, primerResults] = await Promise.all([
|
|
189505
|
+
const [memoryResults, gitCommitResults, primerResults, noteResults] = await Promise.all([
|
|
188730
189506
|
runMemory ? searchMemories({
|
|
188731
189507
|
db,
|
|
188732
189508
|
projectPath,
|
|
@@ -188753,9 +189529,23 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
188753
189529
|
limit: tierLimit,
|
|
188754
189530
|
queryEmbedding,
|
|
188755
189531
|
queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null
|
|
189532
|
+
})) : Promise.resolve([]),
|
|
189533
|
+
runNotes ? Promise.resolve(searchNotes({
|
|
189534
|
+
db,
|
|
189535
|
+
sessionId,
|
|
189536
|
+
projectPath,
|
|
189537
|
+
query: trimmedQuery,
|
|
189538
|
+
limit: tierLimit,
|
|
189539
|
+
probes: messageProbes
|
|
188756
189540
|
})) : Promise.resolve([])
|
|
188757
189541
|
]);
|
|
188758
|
-
const results = [
|
|
189542
|
+
const results = [
|
|
189543
|
+
...memoryResults,
|
|
189544
|
+
...primerResults,
|
|
189545
|
+
...messageLikeResults,
|
|
189546
|
+
...gitCommitResults,
|
|
189547
|
+
...noteResults
|
|
189548
|
+
].sort(compareUnifiedResults).slice(0, limit);
|
|
188759
189549
|
const countRetrievals = options.countRetrievals ?? true;
|
|
188760
189550
|
if (countRetrievals) {
|
|
188761
189551
|
const memoryIds = results.filter((result) => result.source === "memory").map((result) => result.memoryId);
|
|
@@ -188824,6 +189614,10 @@ function renderFragment(result, charCap) {
|
|
|
188824
189614
|
const compressed = cavemanCompress(result.content, "ultra");
|
|
188825
189615
|
return truncate(compressed, charCap);
|
|
188826
189616
|
}
|
|
189617
|
+
case "note": {
|
|
189618
|
+
const compressed = cavemanCompress(result.content, "ultra");
|
|
189619
|
+
return truncate(compressed, charCap);
|
|
189620
|
+
}
|
|
188827
189621
|
}
|
|
188828
189622
|
}
|
|
188829
189623
|
function buildAutoSearchHint(results, options = {}) {
|
|
@@ -189045,13 +189839,11 @@ async function runAutoSearchHintForPi(args) {
|
|
|
189045
189839
|
};
|
|
189046
189840
|
results = await unifiedSearchWithTimeout(db, sessionId, options.projectPath, rawPrompt, searchOptions, AUTO_SEARCH_TIMEOUT_MS);
|
|
189047
189841
|
} catch (error51) {
|
|
189048
|
-
log(`[auto-search] unified search failed for session ${sessionId}: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
189049
|
-
writeNoHintAndReconcile("error");
|
|
189842
|
+
log(`[auto-search] unified search failed for session ${sessionId} (will retry next pass): ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
189050
189843
|
return messages;
|
|
189051
189844
|
}
|
|
189052
189845
|
if (results === null) {
|
|
189053
|
-
sessionLog(sessionId, `auto-search: timed out after ${AUTO_SEARCH_TIMEOUT_MS}ms, skipping hint for this turn`);
|
|
189054
|
-
writeNoHintAndReconcile("timeout");
|
|
189846
|
+
sessionLog(sessionId, `auto-search: timed out after ${AUTO_SEARCH_TIMEOUT_MS}ms, skipping hint for this turn (will retry)`);
|
|
189055
189847
|
return messages;
|
|
189056
189848
|
}
|
|
189057
189849
|
if (results.length === 0) {
|
|
@@ -190626,6 +191418,15 @@ function findCompartmentBoundaryForSnapshot(markers) {
|
|
|
190626
191418
|
return null;
|
|
190627
191419
|
return markers.lastBaselineEndMessageId;
|
|
190628
191420
|
}
|
|
191421
|
+
function resolveRenderedCompartmentBoundary(compartments, boundaryId) {
|
|
191422
|
+
if (!boundaryId)
|
|
191423
|
+
return { endMessageId: null, ordinal: null };
|
|
191424
|
+
const boundary = compartments.find((compartment) => compartment.endMessageId === boundaryId);
|
|
191425
|
+
return {
|
|
191426
|
+
endMessageId: boundaryId,
|
|
191427
|
+
ordinal: typeof boundary?.endMessage === "number" ? boundary.endMessage : null
|
|
191428
|
+
};
|
|
191429
|
+
}
|
|
190629
191430
|
function prependM0M1Messages(piMessages, m0, m1) {
|
|
190630
191431
|
const firstTimestamp = piMessages[0]?.timestamp;
|
|
190631
191432
|
const baseTimestamp = typeof firstTimestamp === "number" ? firstTimestamp : Date.now();
|
|
@@ -190755,6 +191556,7 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
190755
191556
|
}
|
|
190756
191557
|
}
|
|
190757
191558
|
const boundaryId = findCompartmentBoundaryForSnapshot(markers);
|
|
191559
|
+
const renderedBoundary = resolveRenderedCompartmentBoundary(currentCompartments, boundaryId);
|
|
190758
191560
|
const skippedVisibleMessages = boundaryId ? trimPiMessagesToBoundary(piMessages, entryIds, boundaryId) : 0;
|
|
190759
191561
|
prependM0M1Messages(piMessages, m0, m1);
|
|
190760
191562
|
sessionLog(state.sessionId, `injected m[0]/m[1] into Pi messages (${m0.length} + ${m1.length} bytes, materialized=${materialized}${decision.reason ? ` reason=${decision.reason}` : ""})`);
|
|
@@ -190771,6 +191573,8 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
190771
191573
|
m0Reason: decision.reason,
|
|
190772
191574
|
m0Bytes: m0.length,
|
|
190773
191575
|
m1Bytes: m1.length,
|
|
191576
|
+
contentionExhausted,
|
|
191577
|
+
renderedBoundary,
|
|
190774
191578
|
syntheticLeadingCount: 2
|
|
190775
191579
|
};
|
|
190776
191580
|
}
|
|
@@ -194042,7 +194846,9 @@ async function runPiHistorian(deps) {
|
|
|
194042
194846
|
compartmentLeaseHolderId,
|
|
194043
194847
|
readBranchEntries,
|
|
194044
194848
|
notifyIssue,
|
|
194045
|
-
ensureProjectRegistered = ensureProjectRegisteredFromPiDirectory
|
|
194849
|
+
ensureProjectRegistered = ensureProjectRegisteredFromPiDirectory,
|
|
194850
|
+
forceDrainQuota,
|
|
194851
|
+
forceKeepLastCompartment
|
|
194046
194852
|
} = deps;
|
|
194047
194853
|
const notify = async (message) => {
|
|
194048
194854
|
if (shouldSuppressHistorianAlert(sessionId)) {
|
|
@@ -194117,7 +194923,8 @@ async function runPiHistorian(deps) {
|
|
|
194117
194923
|
if (protectedTailStart <= offset || eligibleEndOrdinal <= offset) {
|
|
194118
194924
|
sessionLog(sessionId, `historian no-op: protectedTailStart=${protectedTailStart} eligibleEnd=${eligibleEndOrdinal} <= offset=${offset} — nothing to compact`);
|
|
194119
194925
|
if (boundarySnapshot.usagePercentage < 80) {
|
|
194120
|
-
|
|
194926
|
+
if (!isWrapupInProgress(db, sessionId))
|
|
194927
|
+
clearEmergencyRecovery(db, sessionId);
|
|
194121
194928
|
} else {
|
|
194122
194929
|
recordHighPressureNoEligibleHead(db, boundarySnapshot);
|
|
194123
194930
|
}
|
|
@@ -194126,7 +194933,7 @@ async function runPiHistorian(deps) {
|
|
|
194126
194933
|
}
|
|
194127
194934
|
const perRunCap = selectPerRunCap(boundarySnapshot);
|
|
194128
194935
|
const usable = Math.max(1, Math.round(boundarySnapshot.contextLimit * boundarySnapshot.executeThresholdPercentage / 100));
|
|
194129
|
-
const reserve = reserveProtectedTailDrainTokens({
|
|
194936
|
+
const reserve = forceDrainQuota ? { ok: true, reservation: null } : reserveProtectedTailDrainTokens({
|
|
194130
194937
|
db,
|
|
194131
194938
|
sessionId,
|
|
194132
194939
|
runId: crypto2.randomUUID(),
|
|
@@ -194144,10 +194951,12 @@ async function runPiHistorian(deps) {
|
|
|
194144
194951
|
}
|
|
194145
194952
|
drainReservation = reserve.reservation;
|
|
194146
194953
|
const chunk = readSessionChunk(sessionId, historianChunkTokens, offset, eligibleEndOrdinal);
|
|
194954
|
+
const forceKeepLastCompartmentForChunk = forceKeepLastCompartment === true && !chunk.hasMore;
|
|
194147
194955
|
if (!chunk.text || chunk.messageCount === 0) {
|
|
194148
194956
|
sessionLog(sessionId, `historian no-op: chunk empty after filtering (messageCount=${chunk.messageCount}, textLen=${chunk.text?.length ?? 0}) range=${offset}-${protectedTailStart - 1}`);
|
|
194149
194957
|
if (boundarySnapshot.usagePercentage < 80) {
|
|
194150
|
-
|
|
194958
|
+
if (!isWrapupInProgress(db, sessionId))
|
|
194959
|
+
clearEmergencyRecovery(db, sessionId);
|
|
194151
194960
|
} else {
|
|
194152
194961
|
recordHighPressureNoEligibleHead(db, boundarySnapshot);
|
|
194153
194962
|
}
|
|
@@ -194337,7 +195146,7 @@ ${chunkText}`,
|
|
|
194337
195146
|
const inEmergency = getOverflowState(db, sessionId).needsEmergencyRecovery;
|
|
194338
195147
|
const emittedCompartments = validatedPass.compartments;
|
|
194339
195148
|
let newCompartments = emittedCompartments;
|
|
194340
|
-
if (!inEmergency && emittedCompartments.length >= 2) {
|
|
195149
|
+
if (!inEmergency && !forceKeepLastCompartmentForChunk && emittedCompartments.length >= 2) {
|
|
194341
195150
|
const lastEmitted = emittedCompartments[emittedCompartments.length - 1];
|
|
194342
195151
|
const lookaheadMargin = chunk.endIndex - lastEmitted.endMessage;
|
|
194343
195152
|
if (lookaheadMargin <= BOUNDARY_HEALING_SLACK) {
|
|
@@ -194370,9 +195179,19 @@ ${chunkText}`,
|
|
|
194370
195179
|
}
|
|
194371
195180
|
}
|
|
194372
195181
|
const discardedLast = newCompartments.length < emittedCompartments.length;
|
|
195182
|
+
const weakLookaheadFinalCompartment = forceKeepLastCompartmentForChunk;
|
|
195183
|
+
const skipUnanchoredPromotion = discardedLast || weakLookaheadFinalCompartment;
|
|
194373
195184
|
const embeddingActive = memoryEnabled !== false;
|
|
194374
195185
|
const promotionActive = embeddingActive && autoPromote !== false;
|
|
194375
|
-
const publishableEvents = (validatedPass.events ?? []).filter((e) =>
|
|
195186
|
+
const publishableEvents = (validatedPass.events ?? []).filter((e) => {
|
|
195187
|
+
if (typeof e.atCompartment !== "number")
|
|
195188
|
+
return !weakLookaheadFinalCompartment;
|
|
195189
|
+
if (e.atCompartment > newCompartments.length)
|
|
195190
|
+
return false;
|
|
195191
|
+
if (weakLookaheadFinalCompartment && e.atCompartment >= emittedCompartments.length)
|
|
195192
|
+
return false;
|
|
195193
|
+
return true;
|
|
195194
|
+
});
|
|
194376
195195
|
let promotedFactRefs = [];
|
|
194377
195196
|
let persistedIds = [];
|
|
194378
195197
|
if (!compartmentLeaseHolderId) {
|
|
@@ -194391,7 +195210,7 @@ ${chunkText}`,
|
|
|
194391
195210
|
}
|
|
194392
195211
|
appendCompartments(db, sessionId, newCompartments);
|
|
194393
195212
|
persistedIds = getCompartments(db, sessionId).slice(-newCompartments.length).map((c) => c.id);
|
|
194394
|
-
if (promotionActive && !
|
|
195213
|
+
if (promotionActive && !skipUnanchoredPromotion) {
|
|
194395
195214
|
promotedFactRefs = promoteSessionFactsDurable(db, sessionId, projectPath, validatedPass.facts ?? []);
|
|
194396
195215
|
}
|
|
194397
195216
|
if (publishableEvents.length > 0) {
|
|
@@ -194406,7 +195225,8 @@ ${chunkText}`,
|
|
|
194406
195225
|
clearHistorianFailureState(db, sessionId);
|
|
194407
195226
|
clearHistorianDrainFailure(db, sessionId);
|
|
194408
195227
|
recordProtectedTailPublicationFloor(db, sessionId, lastNewEnd + 1);
|
|
194409
|
-
|
|
195228
|
+
if (!isWrapupInProgress(db, sessionId))
|
|
195229
|
+
clearEmergencyRecovery(db, sessionId);
|
|
194410
195230
|
if (firstKeptEntryId && lastNewEndMessageId) {
|
|
194411
195231
|
setPendingPiCompactionMarkerState(db, sessionId, {
|
|
194412
195232
|
firstKeptEntryId,
|
|
@@ -194430,7 +195250,7 @@ ${chunkText}`,
|
|
|
194430
195250
|
completedSuccessfully = true;
|
|
194431
195251
|
sessionLog(sessionId, `historian: published ${newCompartments.length} compartment(s), ${validatedPass.facts?.length ?? 0} fact(s) covering messages ${chunk.startIndex}-${lastNewEnd}`);
|
|
194432
195252
|
onNoteTrigger(db, sessionId, "historian_complete");
|
|
194433
|
-
if (userMemoriesEnabled === true && !
|
|
195253
|
+
if (userMemoriesEnabled === true && !skipUnanchoredPromotion && validatedPass.userObservations?.length) {
|
|
194434
195254
|
try {
|
|
194435
195255
|
insertUserMemoryCandidates(db, validatedPass.userObservations.map((obs) => ({
|
|
194436
195256
|
content: obs,
|
|
@@ -194443,7 +195263,7 @@ ${chunkText}`,
|
|
|
194443
195263
|
sessionLog(sessionId, "failed to store user memory candidates:", error51);
|
|
194444
195264
|
}
|
|
194445
195265
|
}
|
|
194446
|
-
if (!
|
|
195266
|
+
if (!skipUnanchoredPromotion && validatedPass.primerCandidates?.length && projectPath) {
|
|
194447
195267
|
try {
|
|
194448
195268
|
const firstNew = newCompartments[0];
|
|
194449
195269
|
const lastNew = newCompartments[newCompartments.length - 1];
|
|
@@ -195140,7 +195960,7 @@ Drop silently — do not narrate it. NEVER drop large ranges blindly (e.g., "1-5
|
|
|
195140
195960
|
Older tool calls may show \`[dropped §N§]\` sentinels; that is normal context management, not a pattern to copy. ALWAYS make fresh real tool calls when you need data again; never fabricate or inline tool output.`;
|
|
195141
195961
|
var CAVEMAN_COMPRESSION_WARNING = `
|
|
195142
195962
|
**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.`;
|
|
195143
|
-
function buildMagicContextSection(_agent, protectedTags,
|
|
195963
|
+
function buildMagicContextSection(_agent, protectedTags, ctxReduceCallable = true, dreamerEnabled = false, temporalAwarenessEnabled = false, cavemanTextCompressionEnabled = false, subagentMode = false, language, memoryEnabled = true) {
|
|
195144
195964
|
if (subagentMode) {
|
|
195145
195965
|
return `## Magic Context
|
|
195146
195966
|
|
|
@@ -195151,12 +195971,12 @@ When \`surface_condition\` is provided with \`write\`, the note becomes a projec
|
|
|
195151
195971
|
The dreamer evaluates smart note conditions during nightly runs and surfaces them when conditions are met.
|
|
195152
195972
|
Example: \`ctx_note(action="write", content="Implement X because Y", surface_condition="When PR #42 is merged in this repo")\`` : "";
|
|
195153
195973
|
const temporalGuidance = temporalAwarenessEnabled ? TEMPORAL_AWARENESS_GUIDANCE : "";
|
|
195154
|
-
const cavemanWarning = cavemanTextCompressionEnabled
|
|
195974
|
+
const cavemanWarning = cavemanTextCompressionEnabled ? CAVEMAN_COMPRESSION_WARNING : "";
|
|
195155
195975
|
const languageDirective = buildPrimaryLanguageDirective(language);
|
|
195156
195976
|
const languageGuidance = languageDirective ? `
|
|
195157
195977
|
|
|
195158
195978
|
${languageDirective}` : "";
|
|
195159
|
-
if (!
|
|
195979
|
+
if (!ctxReduceCallable) {
|
|
195160
195980
|
return `## Magic Context
|
|
195161
195981
|
|
|
195162
195982
|
${LONG_TERM_PARTNER_FRAME}
|
|
@@ -195169,7 +195989,7 @@ ${BASE_INTRO_NO_REDUCE(memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${c
|
|
|
195169
195989
|
${LONG_TERM_PARTNER_FRAME}
|
|
195170
195990
|
${PARTNER_FRAME_CLOSER_REDUCE}
|
|
195171
195991
|
|
|
195172
|
-
${BASE_INTRO(protectedTags, memoryEnabled)}${smartNoteGuidance}${temporalGuidance}
|
|
195992
|
+
${BASE_INTRO(protectedTags, memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}
|
|
195173
195993
|
${GENERIC_SECTION}
|
|
195174
195994
|
|
|
195175
195995
|
Prefer many small targeted operations over one large blanket operation, and keep the working set tidy as routine maintenance.${languageGuidance}`;
|
|
@@ -195184,7 +196004,7 @@ function buildMagicContextBlock(opts) {
|
|
|
195184
196004
|
const includeGuidance = (opts.includeGuidance ?? true) && !existing.includes(MAGIC_CONTEXT_MARKER);
|
|
195185
196005
|
if (!includeGuidance)
|
|
195186
196006
|
return null;
|
|
195187
|
-
return buildMagicContextSection(null, opts.protectedTags ?? 20, opts.
|
|
196007
|
+
return buildMagicContextSection(null, opts.protectedTags ?? 20, opts.ctxReduceCallable ?? true, opts.dreamerEnabled ?? false, opts.temporalAwarenessEnabled ?? false, opts.cavemanTextCompressionEnabled ?? false, false, opts.language, opts.memoryEnabled !== false);
|
|
195188
196008
|
}
|
|
195189
196009
|
var DATE_PATTERN = /Today's date: .+/;
|
|
195190
196010
|
function processSystemPromptForCache(args) {
|
|
@@ -195877,6 +196697,7 @@ function applyForwardPressureFloor(trailingPercentage, trailingInputTokens, piUs
|
|
|
195877
196697
|
inputTokens: Math.max(trailingInputTokens, forwardTokens)
|
|
195878
196698
|
} : { percentage: trailingPercentage, inputTokens: trailingInputTokens };
|
|
195879
196699
|
}
|
|
196700
|
+
var injectM0M1PiForRun = injectM0M1Pi;
|
|
195880
196701
|
var DEFAULT_CLEAR_REASONING_AGE = 50;
|
|
195881
196702
|
var PI_STABLE_ID_SCHEME = 1;
|
|
195882
196703
|
var lastEmergencyNotificationAtMs = new Map;
|
|
@@ -196576,7 +197397,6 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
196576
197397
|
projectIdentity,
|
|
196577
197398
|
projectDirectory,
|
|
196578
197399
|
messages: event.messages,
|
|
196579
|
-
ctxReduceEnabled: options.ctxReduceEnabled,
|
|
196580
197400
|
smartDrops: options.smartDrops === true,
|
|
196581
197401
|
protectedTags: options.protectedTags ?? 20,
|
|
196582
197402
|
heuristics: options.heuristics,
|
|
@@ -196609,7 +197429,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
196609
197429
|
},
|
|
196610
197430
|
temporalAwareness: options.injection?.temporalAwareness === true,
|
|
196611
197431
|
appendCompaction: resolvePiAppendCompaction(ctx),
|
|
196612
|
-
readBranchEntries: resolvePiReadBranchEntries(ctx)
|
|
197432
|
+
readBranchEntries: resolvePiReadBranchEntries(ctx),
|
|
197433
|
+
isSubagent: sessionMeta.isSubagent
|
|
196613
197434
|
});
|
|
196614
197435
|
const piDecisionSnapshotNewestAssistant = branchEntries === null ? undefined : findNewestPiAssistantEntryId(branchEntries);
|
|
196615
197436
|
if (result.bustedThisPass && piDecisionSnapshotNewestAssistant !== undefined) {
|
|
@@ -196691,7 +197512,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
196691
197512
|
}
|
|
196692
197513
|
try {
|
|
196693
197514
|
const sessionMetaForCh1 = getOrCreateSessionMeta(options.db, sessionId);
|
|
196694
|
-
if (
|
|
197515
|
+
if (!sessionMetaForCh1.isSubagent) {
|
|
196695
197516
|
const resolvedExecuteThresholdPct = resolveExecuteThreshold(schedulerConfig.executeThresholdPercentage ?? 65, liveModelBySession.get(sessionId), 65, {
|
|
196696
197517
|
tokensConfig: schedulerConfig.executeThresholdTokens,
|
|
196697
197518
|
contextLimit: usageContextLimit ?? 0
|
|
@@ -196819,8 +197640,12 @@ function resolveHistoryBudgetTokensForPi(args) {
|
|
|
196819
197640
|
}
|
|
196820
197641
|
function startPiCompartmentLeaseRenewal(db, sessionId, holderId) {
|
|
196821
197642
|
return setInterval(() => {
|
|
196822
|
-
|
|
196823
|
-
|
|
197643
|
+
try {
|
|
197644
|
+
if (!renewCompartmentLease(db, sessionId, holderId)) {
|
|
197645
|
+
sessionLog(sessionId, "compartment lease renewal failed; publish will be skipped if holder is stale");
|
|
197646
|
+
}
|
|
197647
|
+
} catch (err) {
|
|
197648
|
+
sessionLog(sessionId, `compartment lease renewal threw; publish will be skipped if holder is stale (${err instanceof Error ? err.message : String(err)})`);
|
|
196824
197649
|
}
|
|
196825
197650
|
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
196826
197651
|
}
|
|
@@ -196880,6 +197705,11 @@ function spawnPiHistorianRun(args) {
|
|
|
196880
197705
|
sessionLog(sessionId, "historian skipped: compartment lease held by another process");
|
|
196881
197706
|
return;
|
|
196882
197707
|
}
|
|
197708
|
+
if (isWrapupInProgress(db, sessionId)) {
|
|
197709
|
+
sessionLog(sessionId, "historian skipped: /ctx-wrapup became active");
|
|
197710
|
+
releaseCompartmentLease(db, sessionId, holderId);
|
|
197711
|
+
return;
|
|
197712
|
+
}
|
|
196883
197713
|
const renewal = startPiCompartmentLeaseRenewal(db, sessionId, holderId);
|
|
196884
197714
|
try {
|
|
196885
197715
|
await runPiHistorian({
|
|
@@ -196958,6 +197788,10 @@ function maybeFireHistorian(args) {
|
|
|
196958
197788
|
sessionLog(sessionId, "historian trigger eval: in-flight, skipping");
|
|
196959
197789
|
return;
|
|
196960
197790
|
}
|
|
197791
|
+
if (isWrapupInProgress(db, sessionId)) {
|
|
197792
|
+
sessionLog(sessionId, "historian trigger eval: /ctx-wrapup active, skipping");
|
|
197793
|
+
return;
|
|
197794
|
+
}
|
|
196961
197795
|
let usage;
|
|
196962
197796
|
let usageContextLimit;
|
|
196963
197797
|
try {
|
|
@@ -197100,6 +197934,14 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
197100
197934
|
unregister();
|
|
197101
197935
|
}
|
|
197102
197936
|
}
|
|
197937
|
+
function pendingPiMarkerCoveredByRenderedBoundary(pending, injection) {
|
|
197938
|
+
if (!injection || injection.contentionExhausted)
|
|
197939
|
+
return false;
|
|
197940
|
+
const boundary = injection.renderedBoundary;
|
|
197941
|
+
if (pending.endMessageId === boundary.endMessageId)
|
|
197942
|
+
return true;
|
|
197943
|
+
return boundary.ordinal !== null && pending.ordinal <= boundary.ordinal;
|
|
197944
|
+
}
|
|
197103
197945
|
async function runPipeline(args) {
|
|
197104
197946
|
let executedWorkThisPass = false;
|
|
197105
197947
|
let historyWasConsumedThisPass = false;
|
|
@@ -197113,6 +197955,7 @@ async function runPipeline(args) {
|
|
|
197113
197955
|
let emergency = false;
|
|
197114
197956
|
let autoReclaimDidMutateThisPass = false;
|
|
197115
197957
|
let suppressDeferredHistoryDrain = false;
|
|
197958
|
+
let deferredMaterializationConsumedThisPass = false;
|
|
197116
197959
|
let casLost = false;
|
|
197117
197960
|
const deferredHistoryWasPendingAtPassStart = deferredHistoryRefreshSessions.has(args.sessionId);
|
|
197118
197961
|
if (args.temporalAwareness) {
|
|
@@ -197135,6 +197978,8 @@ async function runPipeline(args) {
|
|
|
197135
197978
|
return findLatestUserMessageIdPi(args.messages, ids)?.messageId ?? null;
|
|
197136
197979
|
})();
|
|
197137
197980
|
const alreadyRanHeuristicsThisTurn = currentTurnId !== null && lastHeuristicsTurnIdBySession.get(args.sessionId) === currentTurnId;
|
|
197981
|
+
const sessionMetaForAvailability = getOrCreateSessionMeta(args.db, args.sessionId);
|
|
197982
|
+
const ctxReduceCallable = !sessionMetaForAvailability.isSubagent;
|
|
197138
197983
|
const canConsumeDeferredLate = args.schedulerDecision === "execute" || args.forceMaterialization === true || args.contextUsage.percentage >= FORCE_MATERIALIZATION_PERCENTAGE;
|
|
197139
197984
|
const deferredMaterializeEligible = canConsumeDeferredLate && deferredMaterializationSessions.has(args.sessionId);
|
|
197140
197985
|
const piHardSignals = args.injection ? (() => {
|
|
@@ -197175,7 +198020,7 @@ async function runPipeline(args) {
|
|
|
197175
198020
|
}
|
|
197176
198021
|
const tTag = performance.now();
|
|
197177
198022
|
const { targets } = tagTranscript(args.sessionId, transcript, args.tagger, args.db, {
|
|
197178
|
-
skipPrefixInjection: !
|
|
198023
|
+
skipPrefixInjection: !ctxReduceCallable,
|
|
197179
198024
|
entryFingerprintByMessageId
|
|
197180
198025
|
});
|
|
197181
198026
|
logTransformTiming(args.sessionId, "tagMessages", tTag);
|
|
@@ -197261,14 +198106,16 @@ async function runPipeline(args) {
|
|
|
197261
198106
|
sessionLog(args.sessionId, `reasoning replay failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
197262
198107
|
}
|
|
197263
198108
|
}
|
|
197264
|
-
|
|
197265
|
-
|
|
197266
|
-
|
|
197267
|
-
|
|
197268
|
-
|
|
198109
|
+
if (args.heuristics?.caveman?.enabled && !args.isSubagent) {
|
|
198110
|
+
try {
|
|
198111
|
+
const tags = getTagsByNumbers(args.db, args.sessionId, targetTagNumbers);
|
|
198112
|
+
const replayed = replayCavemanCompression(args.sessionId, args.db, targets, tags);
|
|
198113
|
+
if (replayed > 0) {
|
|
198114
|
+
sessionLog(args.sessionId, `caveman replay: ${replayed} tags re-compressed from source`);
|
|
198115
|
+
}
|
|
198116
|
+
} catch (err) {
|
|
198117
|
+
sessionLog(args.sessionId, `caveman replay failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
197269
198118
|
}
|
|
197270
|
-
} catch (err) {
|
|
197271
|
-
sessionLog(args.sessionId, `caveman replay failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
197272
198119
|
}
|
|
197273
198120
|
let heuristicsExecuted = false;
|
|
197274
198121
|
let heuristicsResult = null;
|
|
@@ -197291,7 +198138,7 @@ async function runPipeline(args) {
|
|
|
197291
198138
|
currentTotalInputTokens: args.contextUsage.inputTokens,
|
|
197292
198139
|
ceilingTokens: args.emergencyCeilingTokens
|
|
197293
198140
|
} : undefined,
|
|
197294
|
-
caveman: args.heuristics.caveman
|
|
198141
|
+
caveman: args.isSubagent ? undefined : args.heuristics.caveman
|
|
197295
198142
|
}, activeTags, stableIdResolver);
|
|
197296
198143
|
const heuristicMutationCount = heuristicsResult.droppedTools + heuristicsResult.deduplicatedTools + heuristicsResult.droppedInjections + heuristicsResult.droppedStaleReduceCalls + heuristicsResult.mutatedTextTags;
|
|
197297
198144
|
droppedCount += heuristicsResult.droppedTools + heuristicsResult.deduplicatedTools + heuristicsResult.droppedInjections + heuristicsResult.droppedStaleReduceCalls + heuristicsResult.mutatedTextTags;
|
|
@@ -197314,7 +198161,7 @@ async function runPipeline(args) {
|
|
|
197314
198161
|
if (deferredMaterialize && pendingOpsAppliedThisPass) {
|
|
197315
198162
|
const fullPassSucceeded = shouldRunHeuristics ? heuristicsExecuted : true;
|
|
197316
198163
|
if (fullPassSucceeded) {
|
|
197317
|
-
consumeDeferredMaterialization(args.sessionId);
|
|
198164
|
+
deferredMaterializationConsumedThisPass = consumeDeferredMaterialization(args.sessionId);
|
|
197318
198165
|
}
|
|
197319
198166
|
}
|
|
197320
198167
|
if (args.reasoningClearing && shouldRunHeuristics) {
|
|
@@ -197431,7 +198278,7 @@ async function runPipeline(args) {
|
|
|
197431
198278
|
if (args.injection) {
|
|
197432
198279
|
try {
|
|
197433
198280
|
const tInjection = performance.now();
|
|
197434
|
-
injectionResult =
|
|
198281
|
+
injectionResult = injectM0M1PiForRun({
|
|
197435
198282
|
sessionId: args.sessionId,
|
|
197436
198283
|
projectIdentity: args.projectIdentity,
|
|
197437
198284
|
projectDirectory: args.projectDirectory,
|
|
@@ -197463,11 +198310,23 @@ async function runPipeline(args) {
|
|
|
197463
198310
|
forceDiscovery: args.stableIdSchemeCutover === true
|
|
197464
198311
|
});
|
|
197465
198312
|
const deferredHistoryDrainEligible = historyWasConsumedThisPass && materializationSatisfiedThisPass && (deferredHistoryWasPendingAtPassStart || hasPendingMaterializeSignal) && !suppressDeferredHistoryDrain && !casLost;
|
|
198313
|
+
let preserveDeferredMaterializationForMarkerDrain = false;
|
|
197466
198314
|
if (deferredHistoryDrainEligible) {
|
|
197467
198315
|
try {
|
|
197468
198316
|
const pending = getPendingPiCompactionMarkerState(args.db, args.sessionId);
|
|
197469
198317
|
if (!pending) {
|
|
197470
|
-
|
|
198318
|
+
if (injectionResult?.contentionExhausted === true) {
|
|
198319
|
+
suppressDeferredHistoryDrain = true;
|
|
198320
|
+
preserveDeferredMaterializationForMarkerDrain = true;
|
|
198321
|
+
sessionLog(args.sessionId, "Pi deferred-history drain skipped: m[0]/m[1] used a contention fallback; preserving deferred signals");
|
|
198322
|
+
} else {
|
|
198323
|
+
consumeDeferredHistoryRefresh(args.sessionId);
|
|
198324
|
+
}
|
|
198325
|
+
} else if (!pendingPiMarkerCoveredByRenderedBoundary(pending, injectionResult)) {
|
|
198326
|
+
suppressDeferredHistoryDrain = true;
|
|
198327
|
+
preserveDeferredMaterializationForMarkerDrain = true;
|
|
198328
|
+
const boundary = injectionResult?.renderedBoundary;
|
|
198329
|
+
sessionLog(args.sessionId, `Pi compaction-marker drain skipped: pending ordinal ${pending.ordinal} is newer than rendered boundary ${boundary?.ordinal ?? "<none>"} endMessageId=${boundary?.endMessageId ?? "<none>"}; preserving deferred signals`);
|
|
197471
198330
|
} else if (!args.appendCompaction || !args.readBranchEntries) {
|
|
197472
198331
|
suppressDeferredHistoryDrain = true;
|
|
197473
198332
|
sessionLog(args.sessionId, "Pi compaction-marker drain skipped: sessionManager appendCompaction/getBranch unavailable; preserving deferred-history signal");
|
|
@@ -197490,6 +198349,9 @@ async function runPipeline(args) {
|
|
|
197490
198349
|
sessionLog(args.sessionId, `Pi compaction-marker drain failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
197491
198350
|
}
|
|
197492
198351
|
}
|
|
198352
|
+
if (preserveDeferredMaterializationForMarkerDrain && deferredMaterializationConsumedThisPass) {
|
|
198353
|
+
signalPiDeferredMaterialization(args.sessionId);
|
|
198354
|
+
}
|
|
197493
198355
|
if (executedWorkThisPass) {
|
|
197494
198356
|
try {
|
|
197495
198357
|
const currentFlag = peekDeferredExecutePending(args.db, args.sessionId);
|
|
@@ -197795,6 +198657,9 @@ function existingMarkerAlreadyCoversTarget(sessionId, existing, targetOrdinal, t
|
|
|
197795
198657
|
return true;
|
|
197796
198658
|
}
|
|
197797
198659
|
function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, directory) {
|
|
198660
|
+
if (getHarness() !== "opencode") {
|
|
198661
|
+
return true;
|
|
198662
|
+
}
|
|
197798
198663
|
const targetEndMessageId = getCompartmentEndMessageIdForOrdinal(db, sessionId, lastCompartmentEnd);
|
|
197799
198664
|
if (!targetEndMessageId) {
|
|
197800
198665
|
sessionLog(sessionId, `compaction-marker: no compartment endMessageId for ordinal ${lastCompartmentEnd}; preserving existing marker`);
|
|
@@ -199042,13 +199907,23 @@ function withPublishedCallback(deps) {
|
|
|
199042
199907
|
}
|
|
199043
199908
|
function startLeaseRenewal(deps, holderId) {
|
|
199044
199909
|
return setInterval(() => {
|
|
199045
|
-
|
|
199046
|
-
|
|
199910
|
+
try {
|
|
199911
|
+
if (!renewCompartmentLease(deps.db, deps.sessionId, holderId)) {
|
|
199912
|
+
sessionLog(deps.sessionId, "compartment lease renewal failed; publish will be skipped if holder is stale");
|
|
199913
|
+
}
|
|
199914
|
+
} catch (err) {
|
|
199915
|
+
sessionLog(deps.sessionId, `compartment lease renewal threw; publish will be skipped if holder is stale (${err instanceof Error ? err.message : String(err)})`);
|
|
199047
199916
|
}
|
|
199048
199917
|
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
199049
199918
|
}
|
|
199050
199919
|
async function executeContextRecompWithResult(deps, options = {}) {
|
|
199051
199920
|
const { sessionId } = deps;
|
|
199921
|
+
if (isWrapupInProgress(deps.db, sessionId)) {
|
|
199922
|
+
return {
|
|
199923
|
+
message: "## Magic Recomp — Skipped\n\n/ctx-wrapup is already compacting this session. Wait for it to finish, then try `/ctx-recomp` again.",
|
|
199924
|
+
published: false
|
|
199925
|
+
};
|
|
199926
|
+
}
|
|
199052
199927
|
if (activeRuns.has(sessionId)) {
|
|
199053
199928
|
return {
|
|
199054
199929
|
message: "## Magic Recomp — Skipped\n\nHistorian is already running for this session. Wait for it to finish, then try `/ctx-recomp` again.",
|
|
@@ -199072,7 +199947,7 @@ async function executeContextRecompWithResult(deps, options = {}) {
|
|
|
199072
199947
|
}).catch((err) => {
|
|
199073
199948
|
sessionLog(sessionId, "compartment agent: recomp unhandled rejection:", err);
|
|
199074
199949
|
});
|
|
199075
|
-
activeRuns.set(sessionId, { promise: wrappedPromise, published: false });
|
|
199950
|
+
activeRuns.set(sessionId, { promise: wrappedPromise, published: false, kind: "recomp" });
|
|
199076
199951
|
try {
|
|
199077
199952
|
const message = await promise2;
|
|
199078
199953
|
const published = activeRuns.get(sessionId)?.published === true;
|
|
@@ -199404,6 +200279,14 @@ ${parsed.message}`,
|
|
|
199404
200279
|
});
|
|
199405
200280
|
return;
|
|
199406
200281
|
}
|
|
200282
|
+
if (isWrapupInProgress(deps.db, sessionId)) {
|
|
200283
|
+
sendCtxStatusMessage(pi, {
|
|
200284
|
+
title: "/ctx-recomp",
|
|
200285
|
+
text: "## Magic Recomp\n\n/ctx-wrapup is already compacting this session. Wait for it to finish, then try `/ctx-recomp` again.",
|
|
200286
|
+
level: "warning"
|
|
200287
|
+
});
|
|
200288
|
+
return;
|
|
200289
|
+
}
|
|
199407
200290
|
if (isPiRecompInFlight(sessionId)) {
|
|
199408
200291
|
sendCtxStatusMessage(pi, {
|
|
199409
200292
|
title: "/ctx-recomp",
|
|
@@ -199795,6 +200678,16 @@ No active Pi session is available.`,
|
|
|
199795
200678
|
});
|
|
199796
200679
|
return;
|
|
199797
200680
|
}
|
|
200681
|
+
if (isWrapupInProgress(deps.db, sessionId)) {
|
|
200682
|
+
sendCtxStatusMessage(pi, {
|
|
200683
|
+
title: "/ctx-session-upgrade",
|
|
200684
|
+
text: `## Session Upgrade
|
|
200685
|
+
|
|
200686
|
+
/ctx-wrapup is already compacting this session. Wait for it to finish, then try again.`,
|
|
200687
|
+
level: "warning"
|
|
200688
|
+
});
|
|
200689
|
+
return;
|
|
200690
|
+
}
|
|
199798
200691
|
if (isPiRecompInFlight(sessionId)) {
|
|
199799
200692
|
sendCtxStatusMessage(pi, {
|
|
199800
200693
|
title: "/ctx-session-upgrade",
|
|
@@ -200126,7 +201019,7 @@ function formatThresholdPercent(value) {
|
|
|
200126
201019
|
// package.json
|
|
200127
201020
|
var package_default = {
|
|
200128
201021
|
name: "@cortexkit/pi-magic-context",
|
|
200129
|
-
version: "0.
|
|
201022
|
+
version: "0.31.0",
|
|
200130
201023
|
type: "module",
|
|
200131
201024
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
200132
201025
|
main: "dist/index.js",
|
|
@@ -200392,7 +201285,6 @@ ${safeStringify(tool.parameters)}`);
|
|
|
200392
201285
|
inputTokens,
|
|
200393
201286
|
systemPromptTokens,
|
|
200394
201287
|
compartmentCount: compartments.length,
|
|
200395
|
-
factCount: 0,
|
|
200396
201288
|
memoryCount: safeRead(() => getMemoryCount(deps.db, deps.projectIdentity), 0),
|
|
200397
201289
|
memoryBlockCount,
|
|
200398
201290
|
sessionNoteCount: safeRead(() => getNotes(deps.db, {
|
|
@@ -200668,6 +201560,365 @@ function readHistorianState(db, sessionId, meta3) {
|
|
|
200668
201560
|
};
|
|
200669
201561
|
}
|
|
200670
201562
|
|
|
201563
|
+
// src/commands/ctx-wrapup.ts
|
|
201564
|
+
import * as crypto4 from "node:crypto";
|
|
201565
|
+
var DEFAULT_MESSAGES_TO_KEEP = 20;
|
|
201566
|
+
var LEASE_WAIT_MS = 1000;
|
|
201567
|
+
function parseWrapupArgs(raw) {
|
|
201568
|
+
const trimmed = raw.trim();
|
|
201569
|
+
if (trimmed === "")
|
|
201570
|
+
return { ok: true, messagesToKeep: DEFAULT_MESSAGES_TO_KEEP };
|
|
201571
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
201572
|
+
return {
|
|
201573
|
+
ok: false,
|
|
201574
|
+
message: "Usage: `/ctx-wrapup [messages_to_keep]` where messages_to_keep is a positive integer."
|
|
201575
|
+
};
|
|
201576
|
+
}
|
|
201577
|
+
const messagesToKeep = Number.parseInt(trimmed, 10);
|
|
201578
|
+
if (!Number.isSafeInteger(messagesToKeep) || messagesToKeep <= 0) {
|
|
201579
|
+
return {
|
|
201580
|
+
ok: false,
|
|
201581
|
+
message: "messages_to_keep must be a positive integer."
|
|
201582
|
+
};
|
|
201583
|
+
}
|
|
201584
|
+
return { ok: true, messagesToKeep };
|
|
201585
|
+
}
|
|
201586
|
+
function registerCtxWrapupCommand(pi, deps) {
|
|
201587
|
+
pi.registerCommand("ctx-wrapup", {
|
|
201588
|
+
description: "Compact older Magic Context history while keeping the newest messages raw",
|
|
201589
|
+
handler: async (args, ctx) => {
|
|
201590
|
+
const sessionId = resolveSessionId(ctx);
|
|
201591
|
+
if (!sessionId) {
|
|
201592
|
+
sendCtxStatusMessage(pi, {
|
|
201593
|
+
title: "/ctx-wrapup",
|
|
201594
|
+
text: `## Magic Wrapup
|
|
201595
|
+
|
|
201596
|
+
No active Pi session is available.`,
|
|
201597
|
+
level: "error"
|
|
201598
|
+
});
|
|
201599
|
+
return;
|
|
201600
|
+
}
|
|
201601
|
+
const sessionMeta = getOrCreateSessionMeta(deps.db, sessionId);
|
|
201602
|
+
if (sessionMeta.isSubagent) {
|
|
201603
|
+
sendCtxStatusMessage(pi, {
|
|
201604
|
+
title: "/ctx-wrapup",
|
|
201605
|
+
text: `## Magic Wrapup — Skipped
|
|
201606
|
+
|
|
201607
|
+
/ctx-wrapup is only available in primary sessions.`,
|
|
201608
|
+
level: "warning"
|
|
201609
|
+
});
|
|
201610
|
+
return;
|
|
201611
|
+
}
|
|
201612
|
+
if (!deps.historianModel) {
|
|
201613
|
+
sendCtxStatusMessage(pi, {
|
|
201614
|
+
title: "/ctx-wrapup",
|
|
201615
|
+
text: "## Magic Wrapup\n\n/ctx-wrapup is unavailable because `historian.model` is not configured.",
|
|
201616
|
+
level: "error"
|
|
201617
|
+
});
|
|
201618
|
+
return;
|
|
201619
|
+
}
|
|
201620
|
+
const parsed = parseWrapupArgs(args);
|
|
201621
|
+
if (!parsed.ok) {
|
|
201622
|
+
sendCtxStatusMessage(pi, {
|
|
201623
|
+
title: "/ctx-wrapup",
|
|
201624
|
+
text: `## Magic Wrapup — Invalid Arguments
|
|
201625
|
+
|
|
201626
|
+
${parsed.message}`,
|
|
201627
|
+
level: "error"
|
|
201628
|
+
});
|
|
201629
|
+
return;
|
|
201630
|
+
}
|
|
201631
|
+
const result = await runPiWrapup(pi, deps, ctx, sessionId, parsed.messagesToKeep);
|
|
201632
|
+
sendCtxStatusMessage(pi, {
|
|
201633
|
+
title: "/ctx-wrapup",
|
|
201634
|
+
text: result,
|
|
201635
|
+
level: result.includes("Failed") || result.includes("Partial") ? "error" : "success"
|
|
201636
|
+
});
|
|
201637
|
+
}
|
|
201638
|
+
});
|
|
201639
|
+
}
|
|
201640
|
+
async function runPiWrapup(pi, deps, ctx, sessionId, messagesToKeep) {
|
|
201641
|
+
if (getOrCreateSessionMeta(deps.db, sessionId).isSubagent) {
|
|
201642
|
+
return `## Magic Wrapup — Skipped
|
|
201643
|
+
|
|
201644
|
+
/ctx-wrapup is only available in primary sessions.`;
|
|
201645
|
+
}
|
|
201646
|
+
if (isPiRecompInFlight(sessionId)) {
|
|
201647
|
+
return "## Magic Wrapup — Skipped\n\nA recomp or upgrade is already running for this session. Wait for it to finish, then try `/ctx-wrapup` again.";
|
|
201648
|
+
}
|
|
201649
|
+
const provider2 = { readMessages: () => readPiSessionMessages(ctx) };
|
|
201650
|
+
const unregister = setRawMessageProvider(sessionId, provider2);
|
|
201651
|
+
let holderId = "";
|
|
201652
|
+
try {
|
|
201653
|
+
const contextLimit = resolvePiContextLimit(ctx);
|
|
201654
|
+
const modelKey = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
|
|
201655
|
+
const executeThresholdPercentage = resolveExecuteThreshold(deps.executeThresholdPercentage ?? 65, modelKey, 65, {
|
|
201656
|
+
tokensConfig: deps.executeThresholdTokens,
|
|
201657
|
+
contextLimit,
|
|
201658
|
+
sessionId
|
|
201659
|
+
});
|
|
201660
|
+
const initialPlan = resolveWrapupProtectedTailBoundary({
|
|
201661
|
+
db: deps.db,
|
|
201662
|
+
sessionId,
|
|
201663
|
+
mode: "manual-wrapup",
|
|
201664
|
+
contextLimit,
|
|
201665
|
+
executeThresholdPercentage,
|
|
201666
|
+
usage: { percentage: 0, inputTokens: 0 },
|
|
201667
|
+
usageSource: "manual-none",
|
|
201668
|
+
providerShapeVersion: "pi-folded-v1",
|
|
201669
|
+
cacheNamespace: `pi:${sessionId}`,
|
|
201670
|
+
messagesToKeep
|
|
201671
|
+
});
|
|
201672
|
+
if (initialPlan.rawMessagesAboveLastCompartment <= messagesToKeep) {
|
|
201673
|
+
return `## Magic Wrapup
|
|
201674
|
+
|
|
201675
|
+
Nothing to wrap up — only ${initialPlan.rawMessagesAboveLastCompartment} messages above the last compartment.`;
|
|
201676
|
+
}
|
|
201677
|
+
if (!hasRunnableCompartmentWindow(initialPlan.snapshot)) {
|
|
201678
|
+
return `## Magic Wrapup — Partial
|
|
201679
|
+
|
|
201680
|
+
No runnable wrapup boundary is available yet; wrapped up 0 messages into 0 compartments. Run /ctx-wrapup again to continue.`;
|
|
201681
|
+
}
|
|
201682
|
+
holderId = crypto4.randomUUID();
|
|
201683
|
+
const acquired = acquireWrapupInProgress(deps.db, sessionId, {
|
|
201684
|
+
holderId,
|
|
201685
|
+
messagesToKeep,
|
|
201686
|
+
anchorRawMessageCount: initialPlan.anchorRawMessageCount,
|
|
201687
|
+
targetEligibleEndOrdinal: initialPlan.targetEligibleEndOrdinal,
|
|
201688
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(deps.db, sessionId),
|
|
201689
|
+
chunkIndex: 0,
|
|
201690
|
+
expectedChunks: estimateChunks(initialPlan.snapshot.trueRawEligibleTokens, deps.historianChunkTokens)
|
|
201691
|
+
});
|
|
201692
|
+
if (!acquired.ok) {
|
|
201693
|
+
return formatExistingWrapup(acquired.state ?? getWrapupInProgressState(deps.db, sessionId));
|
|
201694
|
+
}
|
|
201695
|
+
let ownershipLost = false;
|
|
201696
|
+
const ownershipLostReason = "another process took over this session's wrapup";
|
|
201697
|
+
const markOwnershipLost = () => {
|
|
201698
|
+
if (ownershipLost)
|
|
201699
|
+
return;
|
|
201700
|
+
ownershipLost = true;
|
|
201701
|
+
};
|
|
201702
|
+
const renewWrapupMarker = (updates) => {
|
|
201703
|
+
const updated = updateWrapupInProgress(deps.db, sessionId, holderId, updates);
|
|
201704
|
+
if (!updated) {
|
|
201705
|
+
markOwnershipLost();
|
|
201706
|
+
return false;
|
|
201707
|
+
}
|
|
201708
|
+
return true;
|
|
201709
|
+
};
|
|
201710
|
+
const renewal = setInterval(() => {
|
|
201711
|
+
try {
|
|
201712
|
+
renewWrapupMarker({
|
|
201713
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(deps.db, sessionId)
|
|
201714
|
+
});
|
|
201715
|
+
} catch (err) {
|
|
201716
|
+
console.warn(`[magic-context][pi] /ctx-wrapup marker renewal failed for ${sessionId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
201717
|
+
}
|
|
201718
|
+
}, 60000);
|
|
201719
|
+
try {
|
|
201720
|
+
sendCtxStatusMessage(pi, {
|
|
201721
|
+
title: "/ctx-wrapup",
|
|
201722
|
+
text: `## Magic Wrapup
|
|
201723
|
+
|
|
201724
|
+
Eligible history is about ${initialPlan.snapshot.trueRawEligibleTokens.toLocaleString()} tokens across approximately ${estimateChunks(initialPlan.snapshot.trueRawEligibleTokens, deps.historianChunkTokens)} historian chunk(s).`,
|
|
201725
|
+
level: "info"
|
|
201726
|
+
});
|
|
201727
|
+
const startEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
201728
|
+
const startCompartmentCount = getCompartments(deps.db, sessionId).length;
|
|
201729
|
+
let chunkIndex = 0;
|
|
201730
|
+
let lastEnd = startEnd;
|
|
201731
|
+
let targetEligibleEndOrdinal = initialPlan.targetEligibleEndOrdinal;
|
|
201732
|
+
let failure = null;
|
|
201733
|
+
for (;; ) {
|
|
201734
|
+
if (ownershipLost) {
|
|
201735
|
+
failure = `${ownershipLostReason}; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.`;
|
|
201736
|
+
break;
|
|
201737
|
+
}
|
|
201738
|
+
if (!renewWrapupMarker({
|
|
201739
|
+
chunkIndex,
|
|
201740
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(deps.db, sessionId)
|
|
201741
|
+
})) {
|
|
201742
|
+
failure = `${ownershipLostReason}; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.`;
|
|
201743
|
+
break;
|
|
201744
|
+
}
|
|
201745
|
+
const plan = resolveWrapupProtectedTailBoundary({
|
|
201746
|
+
db: deps.db,
|
|
201747
|
+
sessionId,
|
|
201748
|
+
mode: "manual-wrapup",
|
|
201749
|
+
contextLimit,
|
|
201750
|
+
executeThresholdPercentage,
|
|
201751
|
+
usage: { percentage: 0, inputTokens: 0 },
|
|
201752
|
+
usageSource: "manual-none",
|
|
201753
|
+
providerShapeVersion: "pi-folded-v1",
|
|
201754
|
+
cacheNamespace: `pi:${sessionId}`,
|
|
201755
|
+
messagesToKeep,
|
|
201756
|
+
anchorRawMessageCount: initialPlan.anchorRawMessageCount
|
|
201757
|
+
});
|
|
201758
|
+
targetEligibleEndOrdinal = plan.targetEligibleEndOrdinal;
|
|
201759
|
+
lastEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
201760
|
+
if (lastEnd + 1 >= targetEligibleEndOrdinal)
|
|
201761
|
+
break;
|
|
201762
|
+
if (!hasRunnableCompartmentWindow(plan.snapshot)) {
|
|
201763
|
+
failure = `No runnable wrapup boundary is available yet; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.`;
|
|
201764
|
+
break;
|
|
201765
|
+
}
|
|
201766
|
+
chunkIndex += 1;
|
|
201767
|
+
if (!renewWrapupMarker({
|
|
201768
|
+
chunkIndex,
|
|
201769
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(deps.db, sessionId),
|
|
201770
|
+
targetEligibleEndOrdinal: plan.targetEligibleEndOrdinal,
|
|
201771
|
+
expectedChunks: Math.max(chunkIndex, estimateChunks(plan.snapshot.trueRawEligibleTokens, deps.historianChunkTokens))
|
|
201772
|
+
})) {
|
|
201773
|
+
failure = `${ownershipLostReason}; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.`;
|
|
201774
|
+
break;
|
|
201775
|
+
}
|
|
201776
|
+
sendCtxStatusMessage(pi, {
|
|
201777
|
+
title: "/ctx-wrapup",
|
|
201778
|
+
text: `## Magic Wrapup
|
|
201779
|
+
|
|
201780
|
+
Chunk ${chunkIndex}: wrapping messages ${plan.snapshot.offset}-${plan.snapshot.eligibleEndOrdinal - 1} (~${plan.snapshot.trueRawEligibleTokens.toLocaleString()} eligible tokens remain).`,
|
|
201781
|
+
level: "info"
|
|
201782
|
+
});
|
|
201783
|
+
const leaseHolder = await acquireCompartmentLeaseEventually(deps.db, sessionId, renewWrapupMarker);
|
|
201784
|
+
if (!leaseHolder) {
|
|
201785
|
+
failure = ownershipLost ? `${ownershipLostReason}; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.` : "Another Magic Context rebuild started while wrapup was waiting. Run /ctx-wrapup again to continue.";
|
|
201786
|
+
break;
|
|
201787
|
+
}
|
|
201788
|
+
const leaseRenewal = setInterval(() => {
|
|
201789
|
+
try {
|
|
201790
|
+
renewCompartmentLease(deps.db, sessionId, leaseHolder);
|
|
201791
|
+
} catch (err) {
|
|
201792
|
+
console.warn(`[magic-context][pi] /ctx-wrapup compartment lease renewal failed for ${sessionId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
201793
|
+
}
|
|
201794
|
+
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
201795
|
+
try {
|
|
201796
|
+
const runHistorian = deps.runPiHistorianForWrapup ?? runPiHistorian;
|
|
201797
|
+
await runHistorian({
|
|
201798
|
+
db: deps.db,
|
|
201799
|
+
sessionId,
|
|
201800
|
+
directory: ctx.cwd,
|
|
201801
|
+
provider: provider2,
|
|
201802
|
+
runner: deps.runner,
|
|
201803
|
+
historianModel: deps.historianModel,
|
|
201804
|
+
fallbackModels: deps.historianFallbacks,
|
|
201805
|
+
historianChunkTokens: deps.historianChunkTokens,
|
|
201806
|
+
boundarySnapshot: plan.snapshot,
|
|
201807
|
+
refreshBoundarySnapshot: () => resolveWrapupProtectedTailBoundary({
|
|
201808
|
+
db: deps.db,
|
|
201809
|
+
sessionId,
|
|
201810
|
+
mode: "manual-wrapup",
|
|
201811
|
+
contextLimit,
|
|
201812
|
+
executeThresholdPercentage,
|
|
201813
|
+
usage: { percentage: 0, inputTokens: 0 },
|
|
201814
|
+
usageSource: "manual-none",
|
|
201815
|
+
providerShapeVersion: "pi-folded-v1",
|
|
201816
|
+
cacheNamespace: `pi:${sessionId}`,
|
|
201817
|
+
messagesToKeep,
|
|
201818
|
+
anchorRawMessageCount: initialPlan.anchorRawMessageCount
|
|
201819
|
+
}).snapshot,
|
|
201820
|
+
currentContextLimit: contextLimit,
|
|
201821
|
+
historianTimeoutMs: deps.historianTimeoutMs,
|
|
201822
|
+
thinkingLevel: deps.historianThinkingLevel,
|
|
201823
|
+
memoryEnabled: deps.memoryEnabled,
|
|
201824
|
+
autoPromote: deps.autoPromote,
|
|
201825
|
+
userMemoriesEnabled: deps.userMemoriesEnabled,
|
|
201826
|
+
language: deps.language,
|
|
201827
|
+
compartmentLeaseHolderId: leaseHolder,
|
|
201828
|
+
readBranchEntries: () => readBranchEntries(ctx),
|
|
201829
|
+
notifyIssue: (text) => sendCtxStatusMessage(pi, {
|
|
201830
|
+
title: "/ctx-wrapup",
|
|
201831
|
+
text,
|
|
201832
|
+
level: "warning"
|
|
201833
|
+
}),
|
|
201834
|
+
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
201835
|
+
forceDrainQuota: true,
|
|
201836
|
+
forceKeepLastCompartment: true,
|
|
201837
|
+
onPublished: () => {
|
|
201838
|
+
updateStatusLine(ctx, { db: deps.db, projectIdentity: ctx.cwd });
|
|
201839
|
+
signalPiDeferredHistoryRefresh(sessionId);
|
|
201840
|
+
signalPiDeferredMaterialization(sessionId);
|
|
201841
|
+
}
|
|
201842
|
+
});
|
|
201843
|
+
} finally {
|
|
201844
|
+
clearInterval(leaseRenewal);
|
|
201845
|
+
releaseCompartmentLease(deps.db, sessionId, leaseHolder);
|
|
201846
|
+
}
|
|
201847
|
+
const afterEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
201848
|
+
if (afterEnd <= lastEnd) {
|
|
201849
|
+
failure = `No forward progress after chunk ${chunkIndex}; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.`;
|
|
201850
|
+
break;
|
|
201851
|
+
}
|
|
201852
|
+
lastEnd = afterEnd;
|
|
201853
|
+
}
|
|
201854
|
+
const finalEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
201855
|
+
if (!failure && finalEnd + 1 < targetEligibleEndOrdinal) {
|
|
201856
|
+
failure = `Wrapped up through message ${finalEnd}, but no runnable wrapup boundary remained before target message ${targetEligibleEndOrdinal}. Run /ctx-wrapup again to continue.`;
|
|
201857
|
+
}
|
|
201858
|
+
const finalCompartmentCount = getCompartments(deps.db, sessionId).length;
|
|
201859
|
+
const messagesWrapped = Math.max(0, finalEnd - startEnd);
|
|
201860
|
+
const compartmentsCreated = Math.max(0, finalCompartmentCount - startCompartmentCount);
|
|
201861
|
+
if (failure) {
|
|
201862
|
+
return `## Magic Wrapup — Partial
|
|
201863
|
+
|
|
201864
|
+
Wrapped up ${messagesWrapped} messages into ${compartmentsCreated} compartments; ${failure}`;
|
|
201865
|
+
}
|
|
201866
|
+
try {
|
|
201867
|
+
clearEmergencyRecovery(deps.db, sessionId);
|
|
201868
|
+
} catch {}
|
|
201869
|
+
return `## Magic Wrapup
|
|
201870
|
+
|
|
201871
|
+
Wrapped up ${messagesWrapped} messages into ${compartmentsCreated} compartments. The compacted history is queued and materializes on your next message.`;
|
|
201872
|
+
} finally {
|
|
201873
|
+
clearInterval(renewal);
|
|
201874
|
+
releaseWrapupInProgress(deps.db, sessionId, holderId);
|
|
201875
|
+
}
|
|
201876
|
+
} finally {
|
|
201877
|
+
unregister();
|
|
201878
|
+
}
|
|
201879
|
+
}
|
|
201880
|
+
function resolvePiContextLimit(ctx) {
|
|
201881
|
+
const usage = ctx.getContextUsage?.();
|
|
201882
|
+
if (typeof usage?.contextWindow === "number" && usage.contextWindow > 0) {
|
|
201883
|
+
return usage.contextWindow;
|
|
201884
|
+
}
|
|
201885
|
+
if (typeof ctx.model?.contextWindow === "number" && ctx.model.contextWindow > 0) {
|
|
201886
|
+
return ctx.model.contextWindow;
|
|
201887
|
+
}
|
|
201888
|
+
return 128000;
|
|
201889
|
+
}
|
|
201890
|
+
async function acquireCompartmentLeaseEventually(db, sessionId, renewWrapupMarker) {
|
|
201891
|
+
for (;; ) {
|
|
201892
|
+
const holderId = crypto4.randomUUID();
|
|
201893
|
+
const lease = acquireCompartmentLease(db, sessionId, holderId);
|
|
201894
|
+
if (lease)
|
|
201895
|
+
return holderId;
|
|
201896
|
+
if (!renewWrapupMarker({}))
|
|
201897
|
+
return null;
|
|
201898
|
+
await new Promise((resolve3) => setTimeout(resolve3, LEASE_WAIT_MS));
|
|
201899
|
+
}
|
|
201900
|
+
}
|
|
201901
|
+
function estimateChunks(tokens, chunkTokens) {
|
|
201902
|
+
return Math.max(1, Math.ceil(Math.max(0, tokens) / Math.max(1, chunkTokens)));
|
|
201903
|
+
}
|
|
201904
|
+
function formatExistingWrapup(state) {
|
|
201905
|
+
if (!state) {
|
|
201906
|
+
return `## Magic Wrapup — Skipped
|
|
201907
|
+
|
|
201908
|
+
Another /ctx-wrapup is already compacting this session. Wait for it to finish, then try again.`;
|
|
201909
|
+
}
|
|
201910
|
+
return `## Magic Wrapup — Skipped
|
|
201911
|
+
|
|
201912
|
+
Another /ctx-wrapup is already compacting this session (chunk ${state.chunkIndex}/${Math.max(state.chunkIndex, state.expectedChunks)}, wrapped through message ${state.lastCompartmentEnd}). Wait for it to finish, then try again.`;
|
|
201913
|
+
}
|
|
201914
|
+
function readBranchEntries(ctx) {
|
|
201915
|
+
const getBranch = ctx.sessionManager.getBranch;
|
|
201916
|
+
if (typeof getBranch !== "function")
|
|
201917
|
+
return [];
|
|
201918
|
+
const branch = getBranch.call(ctx.sessionManager);
|
|
201919
|
+
return Array.isArray(branch?.entries) ? branch.entries : [];
|
|
201920
|
+
}
|
|
201921
|
+
|
|
200671
201922
|
// src/pi-pressure.ts
|
|
200672
201923
|
function extractAssistantUsage(message) {
|
|
200673
201924
|
if (!message || typeof message !== "object")
|
|
@@ -206059,14 +207310,17 @@ Sources (omit for a broad search across all):
|
|
|
206059
207310
|
- memory: curated cross-session project knowledge — rules, constraints, conventions.
|
|
206060
207311
|
- message: the raw conversation behind your compacted history. Hits include message ordinals — expand the surrounding exchange with ctx_expand(start=N-10, end=N+5).
|
|
206061
207312
|
- git_commit: this repository's commit history.
|
|
207313
|
+
- note: parked decisions, follow-ups, and dismissed notes with their recorded text.
|
|
206062
207314
|
|
|
206063
207315
|
Picking sources:
|
|
206064
207316
|
- "when did this change / was this working before" → ["git_commit", "message"]
|
|
206065
207317
|
- "did we discuss this earlier" → ["message"]
|
|
207318
|
+
- "did we decide something about this / leave a follow-up" → ["note"]
|
|
206066
207319
|
- "what's our convention / rule for X" → ["memory"]`;
|
|
206067
207320
|
|
|
206068
207321
|
// src/tools/ctx-search.ts
|
|
206069
207322
|
var DEFAULT_LIMIT = 10;
|
|
207323
|
+
var NOTE_EXPAND_HINT = "Use ctx_expand(start=N-10, end=N) around any note @msg anchor above to read the surrounding conversation context.";
|
|
206070
207324
|
var ParamsSchema5 = exports_typebox.Object({
|
|
206071
207325
|
query: exports_typebox.String({
|
|
206072
207326
|
description: "Search query. Matches against memory content, Primers, git commit messages, and raw user/assistant message text."
|
|
@@ -206078,9 +207332,10 @@ var ParamsSchema5 = exports_typebox.Object({
|
|
|
206078
207332
|
exports_typebox.Literal("memory"),
|
|
206079
207333
|
exports_typebox.Literal("message"),
|
|
206080
207334
|
exports_typebox.Literal("git_commit"),
|
|
206081
|
-
exports_typebox.Literal("primer")
|
|
207335
|
+
exports_typebox.Literal("primer"),
|
|
207336
|
+
exports_typebox.Literal("note")
|
|
206082
207337
|
]), {
|
|
206083
|
-
description: 'Optional. Restrict to specific sources. Examples: ["primer"] for standing project explanations, ["git_commit"] for "when did we change X", ["memory"] for naming conventions, ["message"] for "did we discuss this earlier", ["git_commit","message"] for regression hunts. Omit for a broad search across all enabled sources.'
|
|
207338
|
+
description: 'Optional. Restrict to specific sources. Examples: ["primer"] for standing project explanations, ["git_commit"] for "when did we change X", ["memory"] for naming conventions, ["message"] for "did we discuss this earlier", ["note"] for parked decisions or follow-ups, ["git_commit","message"] for regression hunts. Omit for a broad search across all enabled sources.'
|
|
206084
207339
|
}))
|
|
206085
207340
|
});
|
|
206086
207341
|
function normalizeLimit3(limit) {
|
|
@@ -206107,7 +207362,7 @@ function formatAge2(committedAtMs) {
|
|
|
206107
207362
|
const years = Math.floor(days / 365);
|
|
206108
207363
|
return years === 1 ? "1y ago" : `${years}y ago`;
|
|
206109
207364
|
}
|
|
206110
|
-
function formatResult(result, index) {
|
|
207365
|
+
function formatResult(result, index, currentSessionId) {
|
|
206111
207366
|
if (result.source === "memory") {
|
|
206112
207367
|
const source = result.sourceName ? ` source=${result.sourceName}` : "";
|
|
206113
207368
|
return [
|
|
@@ -206128,6 +207383,14 @@ function formatResult(result, index) {
|
|
|
206128
207383
|
`[${index}] [primer] score=${result.score.toFixed(2)} id=${result.primerId} support=${result.support} match=${result.matchType}`,
|
|
206129
207384
|
result.content
|
|
206130
207385
|
].join(`
|
|
207386
|
+
`);
|
|
207387
|
+
}
|
|
207388
|
+
if (result.source === "note") {
|
|
207389
|
+
const anchor = result.anchorOrdinal !== null && result.sourceSessionId === currentSessionId ? ` @msg ${result.anchorOrdinal}` : "";
|
|
207390
|
+
return [
|
|
207391
|
+
`[${index}] [note] score=${result.score.toFixed(2)} id=#${result.noteId} status=${result.status} ${formatAge2(result.createdAt)}${anchor}`,
|
|
207392
|
+
result.content
|
|
207393
|
+
].join(`
|
|
206131
207394
|
`);
|
|
206132
207395
|
}
|
|
206133
207396
|
if (result.source === "compartment") {
|
|
@@ -206145,14 +207408,17 @@ function formatResult(result, index) {
|
|
|
206145
207408
|
].join(`
|
|
206146
207409
|
`);
|
|
206147
207410
|
}
|
|
206148
|
-
function formatSearchResults(query, results) {
|
|
207411
|
+
function formatSearchResults(query, results, currentSessionId) {
|
|
206149
207412
|
if (results.length === 0) {
|
|
206150
|
-
return `No results found for "${query}" across memories, primers, git commits, or message history.`;
|
|
207413
|
+
return `No results found for "${query}" across notes, memories, primers, git commits, or message history.`;
|
|
206151
207414
|
}
|
|
206152
|
-
const bodyParts = results.map((result, index) => formatResult(result, index + 1));
|
|
207415
|
+
const bodyParts = results.map((result, index) => formatResult(result, index + 1, currentSessionId));
|
|
206153
207416
|
if (results.some((result) => result.source === "message" || result.source === "compartment")) {
|
|
206154
207417
|
bodyParts.push("Use ctx_expand(start, end) with the range from any message result above to read the full conversation context.");
|
|
206155
207418
|
}
|
|
207419
|
+
if (results.some((result) => result.source === "note" && result.anchorOrdinal !== null && result.sourceSessionId === currentSessionId)) {
|
|
207420
|
+
bodyParts.push(NOTE_EXPAND_HINT);
|
|
207421
|
+
}
|
|
206156
207422
|
const body = bodyParts.join(`
|
|
206157
207423
|
|
|
206158
207424
|
`);
|
|
@@ -206201,7 +207467,12 @@ function createCtxSearchTool(deps) {
|
|
|
206201
207467
|
explicitSearch: true
|
|
206202
207468
|
});
|
|
206203
207469
|
return {
|
|
206204
|
-
content: [
|
|
207470
|
+
content: [
|
|
207471
|
+
{
|
|
207472
|
+
type: "text",
|
|
207473
|
+
text: formatSearchResults(query, results, sessionId)
|
|
207474
|
+
}
|
|
207475
|
+
],
|
|
206205
207476
|
details: undefined
|
|
206206
207477
|
};
|
|
206207
207478
|
}
|
|
@@ -206298,7 +207569,7 @@ function registerMagicContextTools(pi, opts) {
|
|
|
206298
207569
|
pi.registerTool(createCtxExpandTool({ db: opts.db }));
|
|
206299
207570
|
}
|
|
206300
207571
|
pi.registerTool(createTodowriteTool());
|
|
206301
|
-
if (opts.
|
|
207572
|
+
if (!opts.sessionScopedToolsDisabled) {
|
|
206302
207573
|
pi.registerTool(createCtxReduceTool({
|
|
206303
207574
|
db: opts.db,
|
|
206304
207575
|
protectedTags: opts.protectedTags ?? 20
|
|
@@ -206310,7 +207581,7 @@ function registerMagicContextTools(pi, opts) {
|
|
|
206310
207581
|
var PREFIX = "[magic-context][pi]";
|
|
206311
207582
|
function resolveCurrentProject(ctx) {
|
|
206312
207583
|
const projectDir = ctx.cwd;
|
|
206313
|
-
const projectIdentity =
|
|
207584
|
+
const projectIdentity = resolveProjectIdentityOrFallback(projectDir);
|
|
206314
207585
|
return { projectDir, projectIdentity };
|
|
206315
207586
|
}
|
|
206316
207587
|
function persistPiMessageEndModelMeta(args) {
|
|
@@ -206497,14 +207768,28 @@ async function src_default2(pi) {
|
|
|
206497
207768
|
runDeferredV22Backfill(db).catch((err5) => {
|
|
206498
207769
|
warn(`[v22-backfill] background runner failed: ${err5}`);
|
|
206499
207770
|
});
|
|
207771
|
+
setTimeout(() => {
|
|
207772
|
+
(async () => {
|
|
207773
|
+
try {
|
|
207774
|
+
const api2 = await loadDefaultPiSessionApi();
|
|
207775
|
+
const sessions = await api2.listSessions();
|
|
207776
|
+
await runSessionProjectBackfill(database, sessions.map((session) => ({
|
|
207777
|
+
sessionId: typeof session?.id === "string" ? session.id : "",
|
|
207778
|
+
directory: typeof session?.cwd === "string" ? session.cwd : ""
|
|
207779
|
+
})));
|
|
207780
|
+
} catch (err5) {
|
|
207781
|
+
warn(`[session-projects] background runner failed: ${err5}`);
|
|
207782
|
+
}
|
|
207783
|
+
})();
|
|
207784
|
+
}, 0);
|
|
206500
207785
|
const projectDir = process.cwd();
|
|
206501
|
-
const projectIdentity =
|
|
207786
|
+
const projectIdentity = resolveProjectIdentityOrFallback(projectDir);
|
|
206502
207787
|
const seenDreamerProjectIdentities = new Set([projectIdentity]);
|
|
206503
207788
|
try {
|
|
206504
207789
|
const pendingPiMarkerSessions = getSessionsWithPendingPiMarker(db);
|
|
206505
207790
|
for (const sid of pendingPiMarkerSessions) {
|
|
206506
207791
|
signalPiDeferredHistoryRefresh(sid);
|
|
206507
|
-
|
|
207792
|
+
signalPiDeferredMaterialization(sid);
|
|
206508
207793
|
}
|
|
206509
207794
|
if (pendingPiMarkerSessions.length > 0) {
|
|
206510
207795
|
log(`${PREFIX} rehydrated ${pendingPiMarkerSessions.length} Pi deferred compaction marker session(s)`);
|
|
@@ -206542,11 +207827,10 @@ async function src_default2(pi) {
|
|
|
206542
207827
|
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
206543
207828
|
allowDreamerActions: false,
|
|
206544
207829
|
memoryToolEnabled: true,
|
|
206545
|
-
ctxReduceEnabled: config2.ctx_reduce_enabled === true,
|
|
206546
207830
|
protectedTags: config2.protected_tags ?? 20,
|
|
206547
207831
|
dreamerEnabled: isDreamerRunnable(config2)
|
|
206548
207832
|
});
|
|
206549
|
-
info(
|
|
207833
|
+
info("registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand, ctx_reduce");
|
|
206550
207834
|
const historianConfig = resolveHistorianFromConfig(config2);
|
|
206551
207835
|
if (historianConfig) {
|
|
206552
207836
|
historianConfig.onStatusChange = (ctx) => {
|
|
@@ -206560,11 +207844,10 @@ async function src_default2(pi) {
|
|
|
206560
207844
|
const contextOptionsByDir = new Map;
|
|
206561
207845
|
const buildContextOptions = (cfg, hist, auto) => ({
|
|
206562
207846
|
db: database,
|
|
206563
|
-
ctxReduceEnabled: cfg.ctx_reduce_enabled,
|
|
206564
207847
|
smartDrops: cfg.smart_drops === true,
|
|
206565
207848
|
protectedTags: cfg.protected_tags ?? 20,
|
|
206566
207849
|
heuristics: {
|
|
206567
|
-
caveman: cfg.
|
|
207850
|
+
caveman: cfg.caveman_text_compression ? {
|
|
206568
207851
|
enabled: cfg.caveman_text_compression.enabled,
|
|
206569
207852
|
minChars: cfg.caveman_text_compression.min_chars
|
|
206570
207853
|
} : undefined,
|
|
@@ -206621,7 +207904,7 @@ async function src_default2(pi) {
|
|
|
206621
207904
|
const bootContextOptions = buildContextOptions(config2, historianConfig, autoSearchConfig);
|
|
206622
207905
|
contextOptionsByDir.set(projectDir, bootContextOptions);
|
|
206623
207906
|
registerPiContextHandler(pi, bootContextOptions);
|
|
206624
|
-
info(historianConfig ? `registered historian trigger (model=${historianConfig.model}, executeThreshold=${historianConfig.executeThresholdPercentage
|
|
207907
|
+
info(historianConfig ? `registered historian trigger (model=${historianConfig.model}, executeThreshold=${formatExecuteThresholdForLog(historianConfig.executeThresholdPercentage)})` : "registered historian trigger: DISABLED (set historian.model in magic-context.jsonc)");
|
|
206625
207908
|
info(autoSearchConfig.enabled ? `registered auto-search hint (threshold=${autoSearchConfig.scoreThreshold}, minChars=${autoSearchConfig.minPromptChars})` : "registered auto-search hint: DISABLED (memory.auto_search.enabled=false)");
|
|
206626
207909
|
const sidekickConfig = resolveSidekickFromConfig(config2);
|
|
206627
207910
|
registerCtxAugCommand(pi, sidekickConfig);
|
|
@@ -206659,6 +207942,22 @@ async function src_default2(pi) {
|
|
|
206659
207942
|
autoPromote: config2.memory.auto_promote
|
|
206660
207943
|
});
|
|
206661
207944
|
info("registered /ctx-recomp");
|
|
207945
|
+
registerCtxWrapupCommand(pi, {
|
|
207946
|
+
db,
|
|
207947
|
+
runner: new PiSubagentRunner,
|
|
207948
|
+
historianModel: historianConfig?.model,
|
|
207949
|
+
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(historianConfig?.model)),
|
|
207950
|
+
historianFallbacks: historianConfig?.fallbackModels,
|
|
207951
|
+
historianTimeoutMs: config2.historian_timeout_ms,
|
|
207952
|
+
historianThinkingLevel: historianConfig?.thinkingLevel,
|
|
207953
|
+
language: config2.language,
|
|
207954
|
+
memoryEnabled: config2.memory.enabled,
|
|
207955
|
+
autoPromote: config2.memory.auto_promote,
|
|
207956
|
+
userMemoriesEnabled: userMemoryCollectionEnabled(config2.dreamer),
|
|
207957
|
+
executeThresholdPercentage: config2.execute_threshold_percentage,
|
|
207958
|
+
executeThresholdTokens: config2.execute_threshold_tokens
|
|
207959
|
+
});
|
|
207960
|
+
info("registered /ctx-wrapup");
|
|
206662
207961
|
registerCtxSessionUpgradeCommand(pi, {
|
|
206663
207962
|
db,
|
|
206664
207963
|
runner: new PiSubagentRunner,
|
|
@@ -206808,10 +208107,10 @@ async function src_default2(pi) {
|
|
|
206808
208107
|
memoryEnabled: effectiveConfig.memory.enabled,
|
|
206809
208108
|
includeGuidance: true,
|
|
206810
208109
|
protectedTags: effectiveConfig.protected_tags,
|
|
206811
|
-
|
|
208110
|
+
ctxReduceCallable: true,
|
|
206812
208111
|
dreamerEnabled: effectiveDreamerRunnable,
|
|
206813
208112
|
temporalAwarenessEnabled: effectiveConfig.temporal_awareness ?? false,
|
|
206814
|
-
cavemanTextCompressionEnabled: effectiveConfig.
|
|
208113
|
+
cavemanTextCompressionEnabled: effectiveConfig.caveman_text_compression?.enabled === true,
|
|
206815
208114
|
language: effectiveConfig.language,
|
|
206816
208115
|
userMemoriesEnabled: userMemoryCollectionEnabled(effectiveConfig.dreamer),
|
|
206817
208116
|
isCacheBusting,
|
|
@@ -207078,6 +208377,15 @@ ${block}` : event.systemPrompt;
|
|
|
207078
208377
|
} catch {}
|
|
207079
208378
|
});
|
|
207080
208379
|
}
|
|
208380
|
+
function formatExecuteThresholdForLog(value) {
|
|
208381
|
+
if (value === undefined)
|
|
208382
|
+
return "65%";
|
|
208383
|
+
if (typeof value === "number")
|
|
208384
|
+
return `${value}%`;
|
|
208385
|
+
const overrides = Object.entries(value).filter(([key]) => key !== "default").map(([key, pct]) => `${key}=${pct}%`);
|
|
208386
|
+
const base = `${value.default}%`;
|
|
208387
|
+
return overrides.length > 0 ? `${base} (${overrides.join(", ")})` : base;
|
|
208388
|
+
}
|
|
207081
208389
|
export {
|
|
207082
208390
|
resolveSidekickFromConfig,
|
|
207083
208391
|
resolveHistorianFromConfig,
|