@cortexkit/pi-magic-context 0.30.7 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.js +1246 -144
- 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() {
|
|
@@ -149637,7 +149763,7 @@ function parseReportedLimit(message) {
|
|
|
149637
149763
|
|
|
149638
149764
|
// ../plugin/src/features/magic-context/session-project-backfill.ts
|
|
149639
149765
|
init_logger();
|
|
149640
|
-
import { existsSync as
|
|
149766
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
149641
149767
|
|
|
149642
149768
|
// ../plugin/src/features/magic-context/session-project-storage.ts
|
|
149643
149769
|
var upsertSessionProjectStatements = new WeakMap;
|
|
@@ -149866,7 +149992,7 @@ async function runSessionProjectBackfill(db, sessions, options = {}) {
|
|
|
149866
149992
|
result.skippedEmptyDirectories += 1;
|
|
149867
149993
|
continue;
|
|
149868
149994
|
}
|
|
149869
|
-
const stillExists = existenceCache.get(session.directory) ??
|
|
149995
|
+
const stillExists = existenceCache.get(session.directory) ?? existsSync5(session.directory);
|
|
149870
149996
|
existenceCache.set(session.directory, stillExists);
|
|
149871
149997
|
if (!stillExists) {
|
|
149872
149998
|
result.skippedDeadDirectories += 1;
|
|
@@ -152116,6 +152242,15 @@ var MIGRATIONS = [
|
|
|
152116
152242
|
);
|
|
152117
152243
|
`);
|
|
152118
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
|
+
}
|
|
152119
152254
|
}
|
|
152120
152255
|
];
|
|
152121
152256
|
var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -152304,7 +152439,7 @@ function readProjectDocsCanonical(projectDirectory) {
|
|
|
152304
152439
|
return { renderedBlock, canonicalHash };
|
|
152305
152440
|
}
|
|
152306
152441
|
// ../plugin/src/features/magic-context/storage-db.ts
|
|
152307
|
-
import { chmodSync, copyFileSync, cpSync, existsSync as
|
|
152442
|
+
import { chmodSync, copyFileSync, cpSync, existsSync as existsSync7, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
|
|
152308
152443
|
init_data_path();
|
|
152309
152444
|
import { dirname as dirname3, join as join5 } from "node:path";
|
|
152310
152445
|
|
|
@@ -152443,7 +152578,7 @@ function loadToolDefinitionMeasurements(db) {
|
|
|
152443
152578
|
// ../plugin/src/features/magic-context/tool-owner-backfill.ts
|
|
152444
152579
|
init_data_path();
|
|
152445
152580
|
init_logger();
|
|
152446
|
-
import { existsSync as
|
|
152581
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
152447
152582
|
import { join as join4 } from "node:path";
|
|
152448
152583
|
var LEASE_DURATION_MS = 5 * 60 * 1000;
|
|
152449
152584
|
var LEASE_RENEWAL_MS = 60 * 1000;
|
|
@@ -152483,7 +152618,7 @@ function runToolOwnerBackfill(db) {
|
|
|
152483
152618
|
return result;
|
|
152484
152619
|
}
|
|
152485
152620
|
const opencodeDbPath = resolveOpencodeDbPath();
|
|
152486
|
-
if (!
|
|
152621
|
+
if (!existsSync6(opencodeDbPath)) {
|
|
152487
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.`);
|
|
152488
152623
|
markAllUnbackfilledSessionsSkipped(db);
|
|
152489
152624
|
result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
|
|
@@ -152705,7 +152840,7 @@ var persistenceByDatabase = new WeakMap;
|
|
|
152705
152840
|
var persistenceErrorByDatabase = new WeakMap;
|
|
152706
152841
|
var pathByDatabase = new WeakMap;
|
|
152707
152842
|
var lastSchemaFenceRejection = null;
|
|
152708
|
-
var LATEST_SUPPORTED_VERSION =
|
|
152843
|
+
var LATEST_SUPPORTED_VERSION = 50;
|
|
152709
152844
|
var PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
|
|
152710
152845
|
function ensureSecureStorageDir(dir) {
|
|
152711
152846
|
mkdirSync4(dir, { recursive: true, mode: 448 });
|
|
@@ -152722,7 +152857,7 @@ function restrictDatabaseFilePermissions(dbPath) {
|
|
|
152722
152857
|
return;
|
|
152723
152858
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
152724
152859
|
const file = `${dbPath}${suffix}`;
|
|
152725
|
-
if (!
|
|
152860
|
+
if (!existsSync7(file))
|
|
152726
152861
|
continue;
|
|
152727
152862
|
try {
|
|
152728
152863
|
chmodSync(file, 384);
|
|
@@ -152748,11 +152883,11 @@ function getDatabasePath(db) {
|
|
|
152748
152883
|
return pathByDatabase.get(db) ?? null;
|
|
152749
152884
|
}
|
|
152750
152885
|
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
152751
|
-
if (
|
|
152886
|
+
if (existsSync7(targetDbPath))
|
|
152752
152887
|
return;
|
|
152753
152888
|
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
152754
152889
|
const legacyDbPath = join5(legacyDir, "context.db");
|
|
152755
|
-
if (!
|
|
152890
|
+
if (!existsSync7(legacyDbPath))
|
|
152756
152891
|
return;
|
|
152757
152892
|
log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
|
|
152758
152893
|
ensureSecureStorageDir(targetDbDir);
|
|
@@ -152769,7 +152904,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
152769
152904
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
152770
152905
|
const src = `${legacyDbPath}${suffix}`;
|
|
152771
152906
|
const dst = join5(targetDbDir, `context.db${suffix}`);
|
|
152772
|
-
if (
|
|
152907
|
+
if (existsSync7(src)) {
|
|
152773
152908
|
try {
|
|
152774
152909
|
copyFileSync(src, dst);
|
|
152775
152910
|
} catch (error) {
|
|
@@ -152779,7 +152914,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
152779
152914
|
}
|
|
152780
152915
|
const legacyModelsDir = join5(legacyDir, "models");
|
|
152781
152916
|
const targetModelsDir = join5(targetDbDir, "models");
|
|
152782
|
-
if (
|
|
152917
|
+
if (existsSync7(legacyModelsDir) && !existsSync7(targetModelsDir)) {
|
|
152783
152918
|
try {
|
|
152784
152919
|
cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
|
|
152785
152920
|
} catch (error) {
|
|
@@ -153383,6 +153518,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
153383
153518
|
force_emergency_bypass_used INTEGER NOT NULL DEFAULT 0,
|
|
153384
153519
|
emergency_drain_active INTEGER NOT NULL DEFAULT 0,
|
|
153385
153520
|
historian_drain_failure_at INTEGER NOT NULL DEFAULT 0,
|
|
153521
|
+
wrapup_in_progress_state TEXT,
|
|
153386
153522
|
cached_m0_materialized_at INTEGER,
|
|
153387
153523
|
cached_m0_session_facts_version INTEGER,
|
|
153388
153524
|
cached_m0_upgrade_state TEXT,
|
|
@@ -153671,6 +153807,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
153671
153807
|
ensureColumn(db, "session_meta", "force_emergency_bypass_used", "INTEGER NOT NULL DEFAULT 0");
|
|
153672
153808
|
ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
|
|
153673
153809
|
ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
|
|
153810
|
+
ensureColumn(db, "session_meta", "wrapup_in_progress_state", "TEXT");
|
|
153674
153811
|
ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
|
|
153675
153812
|
ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
|
|
153676
153813
|
ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
|
|
@@ -154143,6 +154280,148 @@ function recordProtectedTailNoEligibleHead(db, sessionId) {
|
|
|
154143
154280
|
return loadProtectedTailMeta(db, sessionId).recoveryNoEligibleHeadCount;
|
|
154144
154281
|
}
|
|
154145
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
|
+
}
|
|
154146
154425
|
function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
|
|
154147
154426
|
if (usagePercentage >= 95)
|
|
154148
154427
|
return Math.min(1e6, Math.max(4 * perRunCap, Math.round(0.5 * usable)));
|
|
@@ -155999,7 +156278,7 @@ var ERROR_CLASSES = new Set([
|
|
|
155999
156278
|
// ../plugin/src/features/magic-context/v22-deferred-backfill.ts
|
|
156000
156279
|
init_logger();
|
|
156001
156280
|
import { createHash as createHash4 } from "node:crypto";
|
|
156002
|
-
import { realpathSync } from "node:fs";
|
|
156281
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
156003
156282
|
import path5 from "node:path";
|
|
156004
156283
|
|
|
156005
156284
|
// ../plugin/src/features/magic-context/memory/relocate-memory.ts
|
|
@@ -156033,7 +156312,10 @@ function countFailures(db) {
|
|
|
156033
156312
|
}
|
|
156034
156313
|
function classifyBackfillError(error) {
|
|
156035
156314
|
if (error instanceof ProjectIdentityError) {
|
|
156036
|
-
return {
|
|
156315
|
+
return {
|
|
156316
|
+
errorClass: error.errorClass === "dubious_ownership" ? "unknown" : error.errorClass,
|
|
156317
|
+
errorMessage: error.message
|
|
156318
|
+
};
|
|
156037
156319
|
}
|
|
156038
156320
|
if (error instanceof Error) {
|
|
156039
156321
|
return { errorClass: "unknown", errorMessage: error.message };
|
|
@@ -156053,7 +156335,7 @@ function resolveBackfillIdentity(rawProjectPath) {
|
|
|
156053
156335
|
function computeLegacyRustDirIdentity(rawProjectPath) {
|
|
156054
156336
|
let canonical;
|
|
156055
156337
|
try {
|
|
156056
|
-
canonical =
|
|
156338
|
+
canonical = realpathSync2(rawProjectPath);
|
|
156057
156339
|
} catch {
|
|
156058
156340
|
canonical = path5.isAbsolute(rawProjectPath) ? rawProjectPath : path5.join(process.cwd(), rawProjectPath);
|
|
156059
156341
|
}
|
|
@@ -156744,11 +157026,12 @@ function compareSemverCore(a, b) {
|
|
|
156744
157026
|
|
|
156745
157027
|
// ../plugin/src/shared/announcement.ts
|
|
156746
157028
|
init_data_path();
|
|
156747
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
157029
|
+
var ANNOUNCEMENT_VERSION = "0.31.0";
|
|
156748
157030
|
var ANNOUNCEMENT_FEATURES = [
|
|
156749
|
-
"
|
|
156750
|
-
"
|
|
156751
|
-
"
|
|
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)."
|
|
156752
157035
|
];
|
|
156753
157036
|
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU";
|
|
156754
157037
|
var STATE_FILENAME = "last_announced_version";
|
|
@@ -156924,7 +157207,7 @@ init_logger();
|
|
|
156924
157207
|
|
|
156925
157208
|
// src/subagent-runner.ts
|
|
156926
157209
|
import * as childProcess from "node:child_process";
|
|
156927
|
-
import { existsSync as
|
|
157210
|
+
import { existsSync as existsSync9, mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
156928
157211
|
import { createRequire as createRequire2 } from "node:module";
|
|
156929
157212
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
156930
157213
|
import { basename as basename2, dirname as dirname4, join as join8, resolve as resolvePath } from "node:path";
|
|
@@ -157055,7 +157338,7 @@ function resolveBundledPiCli() {
|
|
|
157055
157338
|
const require_ = createRequire2(import.meta.url);
|
|
157056
157339
|
const pkgJson = require_.resolve("@earendil-works/pi-coding-agent/package.json");
|
|
157057
157340
|
const cliPath = join8(dirname4(pkgJson), "dist/cli.js");
|
|
157058
|
-
if (
|
|
157341
|
+
if (existsSync9(cliPath))
|
|
157059
157342
|
return cliPath;
|
|
157060
157343
|
return null;
|
|
157061
157344
|
} catch {
|
|
@@ -157066,7 +157349,7 @@ function resolvePiInvocation() {
|
|
|
157066
157349
|
const execPath = process.execPath;
|
|
157067
157350
|
const currentScript = process.argv[1];
|
|
157068
157351
|
const isBunVirtualScript = currentScript?.startsWith("/$bunfs/root/") ?? false;
|
|
157069
|
-
if (currentScript && !isBunVirtualScript &&
|
|
157352
|
+
if (currentScript && !isBunVirtualScript && existsSync9(currentScript)) {
|
|
157070
157353
|
return { command: execPath, prefixArgs: [currentScript] };
|
|
157071
157354
|
}
|
|
157072
157355
|
const execName = basename2(execPath).toLowerCase();
|
|
@@ -157084,7 +157367,7 @@ function resolveSubagentEntryPath() {
|
|
|
157084
157367
|
try {
|
|
157085
157368
|
const here = dirname4(fileURLToPath(import.meta.url));
|
|
157086
157369
|
const candidate = resolvePath(here, "subagent-entry.js");
|
|
157087
|
-
if (
|
|
157370
|
+
if (existsSync9(candidate))
|
|
157088
157371
|
return candidate;
|
|
157089
157372
|
return;
|
|
157090
157373
|
} catch {
|
|
@@ -157753,13 +158036,13 @@ ${sidekickText}
|
|
|
157753
158036
|
init_logger();
|
|
157754
158037
|
|
|
157755
158038
|
// ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
|
|
157756
|
-
import { existsSync as
|
|
158039
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
157757
158040
|
init_logger();
|
|
157758
158041
|
|
|
157759
158042
|
// ../plugin/src/features/magic-context/compaction-marker.ts
|
|
157760
158043
|
init_data_path();
|
|
157761
158044
|
init_logger();
|
|
157762
|
-
import { existsSync as
|
|
158045
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
157763
158046
|
import { join as join9 } from "node:path";
|
|
157764
158047
|
var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
157765
158048
|
function randomBase62(length) {
|
|
@@ -157826,7 +158109,7 @@ function getWritableOpenCodeDb() {
|
|
|
157826
158109
|
closeQuietly(cachedWriteDb.db);
|
|
157827
158110
|
} catch {}
|
|
157828
158111
|
}
|
|
157829
|
-
if (!
|
|
158112
|
+
if (!existsSync10(dbPath)) {
|
|
157830
158113
|
throw new Error(`OpenCode database not found at ${dbPath} (is OpenCode installed?)`);
|
|
157831
158114
|
}
|
|
157832
158115
|
const db = new Database(dbPath);
|
|
@@ -157947,7 +158230,7 @@ function removeCompactionMarker(state) {
|
|
|
157947
158230
|
// ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
|
|
157948
158231
|
function openOpenCodeDb() {
|
|
157949
158232
|
const dbPath = getOpenCodeDbPath2();
|
|
157950
|
-
if (!
|
|
158233
|
+
if (!existsSync11(dbPath)) {
|
|
157951
158234
|
log(`[dreamer] OpenCode DB not found at ${dbPath} — skipping OpenCode history scan`);
|
|
157952
158235
|
return null;
|
|
157953
158236
|
}
|
|
@@ -157963,7 +158246,7 @@ function openOpenCodeDb() {
|
|
|
157963
158246
|
|
|
157964
158247
|
// ../plugin/src/features/magic-context/dreamer/task-executor.ts
|
|
157965
158248
|
import { createHash as createHash10 } from "node:crypto";
|
|
157966
|
-
import { existsSync as
|
|
158249
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
157967
158250
|
|
|
157968
158251
|
// ../plugin/src/agents/dreamer.ts
|
|
157969
158252
|
var DREAMER_AGENT = "dreamer";
|
|
@@ -172915,7 +173198,6 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
172915
173198
|
enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
|
|
172916
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."),
|
|
172917
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."),
|
|
172918
|
-
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)"),
|
|
172919
173201
|
historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
|
|
172920
173202
|
dreamer: DreamerConfigSchema.optional().describe("Dreamer agent + scheduling configuration (model, fallback_models, disable, schedule, tasks, etc.)"),
|
|
172921
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" })'),
|
|
@@ -172954,9 +173236,9 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
172954
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."),
|
|
172955
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."),
|
|
172956
173238
|
caveman_text_compression: exports_external.object({
|
|
172957
|
-
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%)."),
|
|
172958
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.")
|
|
172959
|
-
}).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)."),
|
|
172960
173242
|
memory: exports_external.object({
|
|
172961
173243
|
enabled: exports_external.boolean().default(true).describe("Enable cross-session memory (default: true)"),
|
|
172962
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)"),
|
|
@@ -173763,7 +174045,8 @@ function isNativeRuntimeMissingError(error51) {
|
|
|
173763
174045
|
if (code === "ERR_DLOPEN_FAILED" && lower.includes("onnxruntime")) {
|
|
173764
174046
|
return true;
|
|
173765
174047
|
}
|
|
173766
|
-
|
|
174048
|
+
const mentionsNativeRuntime = lower.includes("onnxruntime-node") || lower.includes("onnxruntime_binding");
|
|
174049
|
+
if (!mentionsNativeRuntime)
|
|
173767
174050
|
return false;
|
|
173768
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");
|
|
173769
174052
|
}
|
|
@@ -173908,7 +174191,7 @@ class LocalEmbeddingProvider {
|
|
|
173908
174191
|
} catch (error51) {
|
|
173909
174192
|
if (isNativeRuntimeMissingError(error51)) {
|
|
173910
174193
|
nativeRuntimeMissing = true;
|
|
173911
|
-
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.");
|
|
173912
174195
|
} else {
|
|
173913
174196
|
log("[magic-context] embedding model failed to load:", error51);
|
|
173914
174197
|
}
|
|
@@ -176485,7 +176768,7 @@ function getMemoryVerifications(db, memoryIds) {
|
|
|
176485
176768
|
}
|
|
176486
176769
|
// ../plugin/src/features/magic-context/memory/verification-paths.ts
|
|
176487
176770
|
import { execFile } from "node:child_process";
|
|
176488
|
-
import { existsSync as
|
|
176771
|
+
import { existsSync as existsSync12, realpathSync as realpathSync3, statSync as statSync4 } from "node:fs";
|
|
176489
176772
|
import path7 from "node:path";
|
|
176490
176773
|
import { promisify } from "node:util";
|
|
176491
176774
|
var execFileAsync = promisify(execFile);
|
|
@@ -176512,7 +176795,7 @@ function isWithin(root, candidate) {
|
|
|
176512
176795
|
}
|
|
176513
176796
|
function safeRealpath(value) {
|
|
176514
176797
|
try {
|
|
176515
|
-
return
|
|
176798
|
+
return realpathSync3.native(value);
|
|
176516
176799
|
} catch {
|
|
176517
176800
|
return null;
|
|
176518
176801
|
}
|
|
@@ -176590,7 +176873,7 @@ function verificationFileExists(baseRoot, filePath) {
|
|
|
176590
176873
|
return false;
|
|
176591
176874
|
const root = path7.resolve(baseRoot);
|
|
176592
176875
|
const candidate = path7.resolve(root, filePath);
|
|
176593
|
-
return isWithin(root, candidate) &&
|
|
176876
|
+
return isWithin(root, candidate) && existsSync12(candidate);
|
|
176594
176877
|
}
|
|
176595
176878
|
async function normalizeVerificationFiles(args) {
|
|
176596
176879
|
const cwd = path7.resolve(args.cwd);
|
|
@@ -176623,7 +176906,7 @@ async function normalizeVerificationFiles(args) {
|
|
|
176623
176906
|
warnings.push(`Skipped verification path "${value}" because it is the repo/project root.`);
|
|
176624
176907
|
continue;
|
|
176625
176908
|
}
|
|
176626
|
-
if (
|
|
176909
|
+
if (existsSync12(candidate)) {
|
|
176627
176910
|
try {
|
|
176628
176911
|
if (statSync4(candidate).isDirectory()) {
|
|
176629
176912
|
warnings.push(`Skipped verification path "${value}" because it is a directory.`);
|
|
@@ -176654,7 +176937,7 @@ async function normalizeVerificationFiles(args) {
|
|
|
176654
176937
|
}
|
|
176655
176938
|
normalized.push(tracked);
|
|
176656
176939
|
} else {
|
|
176657
|
-
if (!
|
|
176940
|
+
if (!existsSync12(candidate)) {
|
|
176658
176941
|
warnings.push(`Skipped verification path "${value}" because it does not exist.`);
|
|
176659
176942
|
continue;
|
|
176660
176943
|
}
|
|
@@ -178093,6 +178376,9 @@ function requestValidatedAddress(validation, candidate, options) {
|
|
|
178093
178376
|
}
|
|
178094
178377
|
chunks.push(buf);
|
|
178095
178378
|
});
|
|
178379
|
+
response.on("error", (error51) => {
|
|
178380
|
+
reject(toNetworkError(error51, "response failed"));
|
|
178381
|
+
});
|
|
178096
178382
|
response.on("end", () => {
|
|
178097
178383
|
const status = response.statusCode ?? 0;
|
|
178098
178384
|
if (status >= 500) {
|
|
@@ -178822,14 +179108,21 @@ function toSmartNote(note) {
|
|
|
178822
179108
|
};
|
|
178823
179109
|
}
|
|
178824
179110
|
function commitSmartNoteState(db, args) {
|
|
179111
|
+
db.exec("BEGIN IMMEDIATE");
|
|
178825
179112
|
let leaseLost = false;
|
|
178826
|
-
|
|
179113
|
+
try {
|
|
178827
179114
|
if (args.leaseHeld && !args.leaseHeld()) {
|
|
178828
179115
|
leaseLost = true;
|
|
178829
|
-
|
|
179116
|
+
} else {
|
|
179117
|
+
args.write();
|
|
178830
179118
|
}
|
|
178831
|
-
|
|
178832
|
-
}
|
|
179119
|
+
db.exec("COMMIT");
|
|
179120
|
+
} catch (error51) {
|
|
179121
|
+
try {
|
|
179122
|
+
db.exec("ROLLBACK");
|
|
179123
|
+
} catch {}
|
|
179124
|
+
throw error51;
|
|
179125
|
+
}
|
|
178833
179126
|
if (leaseLost) {
|
|
178834
179127
|
throw new Error(`Dream lease lost during smart-note ${args.phase} commit`);
|
|
178835
179128
|
}
|
|
@@ -179297,7 +179590,7 @@ Output exactly JSON: {"met": false}`;
|
|
|
179297
179590
|
|
|
179298
179591
|
// ../plugin/src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
|
|
179299
179592
|
init_logger();
|
|
179300
|
-
import { existsSync as
|
|
179593
|
+
import { existsSync as existsSync13, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
|
|
179301
179594
|
import { join as join11 } from "node:path";
|
|
179302
179595
|
|
|
179303
179596
|
// ../plugin/src/features/magic-context/dreamer/protected-regions.ts
|
|
@@ -179401,7 +179694,7 @@ function snapshotMaintainDocsFiles(docsDir) {
|
|
|
179401
179694
|
for (const name2 of MAINTAIN_DOCS_SNAPSHOT_FILES) {
|
|
179402
179695
|
const path9 = join11(docsDir, name2);
|
|
179403
179696
|
try {
|
|
179404
|
-
if (
|
|
179697
|
+
if (existsSync13(path9)) {
|
|
179405
179698
|
snapshot.set(name2, readFileSync6(path9, "utf8"));
|
|
179406
179699
|
}
|
|
179407
179700
|
} catch {}
|
|
@@ -179429,7 +179722,7 @@ function enforceMaintainDocsProtectedRegions(args) {
|
|
|
179429
179722
|
init_logger();
|
|
179430
179723
|
|
|
179431
179724
|
// ../plugin/src/features/magic-context/dreamer/map-memories-prompt.ts
|
|
179432
|
-
import { existsSync as
|
|
179725
|
+
import { existsSync as existsSync14, statSync as statSync5 } from "node:fs";
|
|
179433
179726
|
import path9 from "node:path";
|
|
179434
179727
|
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.
|
|
179435
179728
|
|
|
@@ -179467,7 +179760,7 @@ function extractMemoryCandidatePaths(content, repoDir) {
|
|
|
179467
179760
|
if (!abs.startsWith(`${root}/`))
|
|
179468
179761
|
continue;
|
|
179469
179762
|
try {
|
|
179470
|
-
if (
|
|
179763
|
+
if (existsSync14(abs) && statSync5(abs).isFile())
|
|
179471
179764
|
found.add(rel);
|
|
179472
179765
|
} catch {}
|
|
179473
179766
|
if (found.size >= MAX_SEED_PATHS_PER_MEMORY)
|
|
@@ -181608,8 +181901,8 @@ async function runAgenticTask(config2, ctx, helpers) {
|
|
|
181608
181901
|
const lastRunAt = getTaskScheduleState(db, projectIdentity, config2.task)?.lastRunAt ?? null;
|
|
181609
181902
|
const maintainDocsSnapshot = task === "maintain-docs" ? snapshotMaintainDocsFiles(docsDir) : undefined;
|
|
181610
181903
|
const existingDocs = task === "maintain-docs" ? {
|
|
181611
|
-
architecture:
|
|
181612
|
-
structure:
|
|
181904
|
+
architecture: existsSync15(`${docsDir}/ARCHITECTURE.md`),
|
|
181905
|
+
structure: existsSync15(`${docsDir}/STRUCTURE.md`)
|
|
181613
181906
|
} : undefined;
|
|
181614
181907
|
const userMemories = task === "curate" ? getActiveUserMemories(db).map((um) => ({ id: um.id, content: um.content })) : undefined;
|
|
181615
181908
|
let curateMemories;
|
|
@@ -182824,7 +183117,7 @@ function pruneNestedConfigLeaf(block, relativePath) {
|
|
|
182824
183117
|
}
|
|
182825
183118
|
|
|
182826
183119
|
// src/config/index.ts
|
|
182827
|
-
import { existsSync as
|
|
183120
|
+
import { existsSync as existsSync17, readFileSync as readFileSync8 } from "node:fs";
|
|
182828
183121
|
|
|
182829
183122
|
// ../plugin/src/config/migrate-dreamer-v2.ts
|
|
182830
183123
|
var OLD_VERIFY_TASK = "verify";
|
|
@@ -183206,7 +183499,7 @@ function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
|
|
|
183206
183499
|
}
|
|
183207
183500
|
|
|
183208
183501
|
// ../plugin/src/config/variable.ts
|
|
183209
|
-
import { existsSync as
|
|
183502
|
+
import { existsSync as existsSync16, readFileSync as readFileSync7 } from "node:fs";
|
|
183210
183503
|
import { homedir as homedir4 } from "node:os";
|
|
183211
183504
|
import { dirname as dirname6, isAbsolute as isAbsolute2, resolve } from "node:path";
|
|
183212
183505
|
|
|
@@ -183341,7 +183634,7 @@ function substituteConfigVariables(input) {
|
|
|
183341
183634
|
if (sensitiveReason) {
|
|
183342
183635
|
warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
|
|
183343
183636
|
}
|
|
183344
|
-
if (!
|
|
183637
|
+
if (!existsSync16(filePath)) {
|
|
183345
183638
|
warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
|
|
183346
183639
|
continue;
|
|
183347
183640
|
}
|
|
@@ -183370,10 +183663,10 @@ function getUserConfigPaths() {
|
|
|
183370
183663
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
183371
183664
|
}
|
|
183372
183665
|
function resolveFirstExisting(paths) {
|
|
183373
|
-
return paths.find((path11) =>
|
|
183666
|
+
return paths.find((path11) => existsSync17(path11));
|
|
183374
183667
|
}
|
|
183375
183668
|
function resolvePiLegacyFallback(sources) {
|
|
183376
|
-
return sources.find((source) =>
|
|
183669
|
+
return sources.find((source) => existsSync17(source.path)) ?? null;
|
|
183377
183670
|
}
|
|
183378
183671
|
function loadConfigFile(path11, scope) {
|
|
183379
183672
|
try {
|
|
@@ -183510,7 +183803,7 @@ function loadPiConfig(opts = {}) {
|
|
|
183510
183803
|
if (loaded)
|
|
183511
183804
|
loadedFiles.push(loaded);
|
|
183512
183805
|
}
|
|
183513
|
-
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) =>
|
|
183806
|
+
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync17(source.path));
|
|
183514
183807
|
const userPath = resolveFirstExisting(getUserConfigPaths());
|
|
183515
183808
|
const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
|
|
183516
183809
|
const userReadPath = userPath ?? userLegacyFallback?.path;
|
|
@@ -183519,7 +183812,7 @@ function loadPiConfig(opts = {}) {
|
|
|
183519
183812
|
if (loaded)
|
|
183520
183813
|
loadedFiles.push(loaded);
|
|
183521
183814
|
}
|
|
183522
|
-
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) =>
|
|
183815
|
+
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync17(source.path));
|
|
183523
183816
|
if (userLegacyFallback) {
|
|
183524
183817
|
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.`);
|
|
183525
183818
|
} else if (legacyUserUnmigrated) {
|
|
@@ -183620,7 +183913,7 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
183620
183913
|
if (loaded)
|
|
183621
183914
|
loadedFiles.push(loaded);
|
|
183622
183915
|
}
|
|
183623
|
-
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) =>
|
|
183916
|
+
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync17(source.path));
|
|
183624
183917
|
const userPath = resolveFirstExisting(getUserConfigPaths());
|
|
183625
183918
|
const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
|
|
183626
183919
|
const userReadPath = userPath ?? userLegacyFallback?.path;
|
|
@@ -183629,7 +183922,7 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
183629
183922
|
if (loaded)
|
|
183630
183923
|
loadedFiles.push(loaded);
|
|
183631
183924
|
}
|
|
183632
|
-
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) =>
|
|
183925
|
+
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync17(source.path));
|
|
183633
183926
|
if (userLegacyFallback) {
|
|
183634
183927
|
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.`);
|
|
183635
183928
|
} else if (legacyUserUnmigrated) {
|
|
@@ -185100,7 +185393,8 @@ var canonicalReasons = new Set([
|
|
|
185100
185393
|
"first_render",
|
|
185101
185394
|
"pressure_refold",
|
|
185102
185395
|
"upgrade_state",
|
|
185103
|
-
"cached_m1_missing"
|
|
185396
|
+
"cached_m1_missing",
|
|
185397
|
+
"project_change"
|
|
185104
185398
|
]);
|
|
185105
185399
|
var piReasonAliases = {
|
|
185106
185400
|
project_memory_change: "project_memory_epoch",
|
|
@@ -186379,6 +186673,43 @@ function semanticSnapBoundary(args) {
|
|
|
186379
186673
|
}
|
|
186380
186674
|
return snapped;
|
|
186381
186675
|
}
|
|
186676
|
+
function snapWrapupBoundaryToUser(args) {
|
|
186677
|
+
const { messages, index, candidate, offset, triggerBudget } = args;
|
|
186678
|
+
if (candidate <= offset)
|
|
186679
|
+
return candidate;
|
|
186680
|
+
const snapTokenLimit = Math.min(Math.max(triggerBudget, 2000), 48000);
|
|
186681
|
+
for (let ordinal = candidate;ordinal >= offset; ordinal -= 1) {
|
|
186682
|
+
const message = messages.find((m) => m.ordinal === ordinal);
|
|
186683
|
+
if (!message)
|
|
186684
|
+
continue;
|
|
186685
|
+
if (message.role !== "user" || !hasMeaningfulUserText(message.parts))
|
|
186686
|
+
continue;
|
|
186687
|
+
const extraTokens = index.rangeTokens(ordinal, candidate);
|
|
186688
|
+
if (extraTokens <= snapTokenLimit)
|
|
186689
|
+
return ordinal;
|
|
186690
|
+
return candidate;
|
|
186691
|
+
}
|
|
186692
|
+
return candidate;
|
|
186693
|
+
}
|
|
186694
|
+
function fenceWrapupBoundaryForToolArcs(args) {
|
|
186695
|
+
let boundary = args.candidate;
|
|
186696
|
+
const maxPasses = args.arcs.length + 1;
|
|
186697
|
+
for (let pass = 0;pass < maxPasses; pass += 1) {
|
|
186698
|
+
let next = boundary;
|
|
186699
|
+
for (const arc of args.arcs) {
|
|
186700
|
+
if (arc.resOrdinal === null) {
|
|
186701
|
+
continue;
|
|
186702
|
+
}
|
|
186703
|
+
if (arc.invOrdinal >= args.lastCompartmentEndOrdinal + 1 && arc.invOrdinal < next && next <= arc.resOrdinal) {
|
|
186704
|
+
next = arc.invOrdinal;
|
|
186705
|
+
}
|
|
186706
|
+
}
|
|
186707
|
+
if (next === boundary)
|
|
186708
|
+
return boundary;
|
|
186709
|
+
boundary = next;
|
|
186710
|
+
}
|
|
186711
|
+
return boundary;
|
|
186712
|
+
}
|
|
186382
186713
|
function applyHeadCap(args) {
|
|
186383
186714
|
const { index, protectedTailStart, offset, arcs, capTokens, recentOpenArcCutoff } = args;
|
|
186384
186715
|
if (offset >= protectedTailStart)
|
|
@@ -186634,6 +186965,124 @@ function resolveBoundaryContext(args) {
|
|
|
186634
186965
|
function resolveOpenCodeProtectedTailBoundary(args) {
|
|
186635
186966
|
return resolveProtectedTailBoundary(resolveBoundaryContext(args));
|
|
186636
186967
|
}
|
|
186968
|
+
function resolveWrapupProtectedTailBoundary(args) {
|
|
186969
|
+
const ctx = resolveBoundaryContext({ ...args, mode: "manual-wrapup" });
|
|
186970
|
+
const createdAt = ctx.createdAt ?? Date.now();
|
|
186971
|
+
const messages = readRawSessionMessages(ctx.sessionId);
|
|
186972
|
+
const absoluteMessageCount = getCachedAbsoluteMessageCount(ctx.sessionId) ?? undefined;
|
|
186973
|
+
const index = buildTrueRawTokenIndex(ctx.sessionId, messages, {
|
|
186974
|
+
providerShapeVersion: ctx.providerShapeVersion,
|
|
186975
|
+
cacheNamespace: ctx.cacheNamespace,
|
|
186976
|
+
absoluteMessageCount,
|
|
186977
|
+
storedTotalForMessage: ctx.storedTokenTotals ? (m) => {
|
|
186978
|
+
const value = ctx.storedTokenTotals?.get(m.id);
|
|
186979
|
+
return value === undefined ? null : value;
|
|
186980
|
+
} : undefined
|
|
186981
|
+
});
|
|
186982
|
+
const rawMessageCount = index.rawMessageCount;
|
|
186983
|
+
const offset = Math.max(1, ctx.lastCompartmentEndOrdinal + 1);
|
|
186984
|
+
const anchorRawMessageCount = Math.max(0, Math.min(rawMessageCount, Math.floor(args.anchorRawMessageCount ?? rawMessageCount)));
|
|
186985
|
+
const usagePercentage = clampPercentage(ctx.usage?.percentage ?? 0);
|
|
186986
|
+
const usageInputTokens = Math.max(0, Math.round(ctx.usage?.inputTokens ?? 0));
|
|
186987
|
+
const rawMessagesAboveLastCompartment = Math.max(0, anchorRawMessageCount - offset + 1);
|
|
186988
|
+
const keep = Math.max(1, Math.floor(args.messagesToKeep));
|
|
186989
|
+
let targetProtectedTailStart = offset;
|
|
186990
|
+
let boundaryReason = "manual-wrapup-empty";
|
|
186991
|
+
if (rawMessageCount === 0 || rawMessagesAboveLastCompartment <= keep) {
|
|
186992
|
+
targetProtectedTailStart = offset;
|
|
186993
|
+
boundaryReason = rawMessageCount === 0 ? "manual-wrapup-empty" : "manual-wrapup-within-keep";
|
|
186994
|
+
} else {
|
|
186995
|
+
targetProtectedTailStart = anchorRawMessageCount - keep + 1;
|
|
186996
|
+
boundaryReason = "manual-wrapup-keep-watermark";
|
|
186997
|
+
const arcs = buildToolArcs(messages);
|
|
186998
|
+
const fenced = fenceWrapupBoundaryForToolArcs({
|
|
186999
|
+
candidate: targetProtectedTailStart,
|
|
187000
|
+
arcs,
|
|
187001
|
+
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal
|
|
187002
|
+
});
|
|
187003
|
+
if (fenced !== targetProtectedTailStart)
|
|
187004
|
+
boundaryReason = "manual-wrapup-tool-arc";
|
|
187005
|
+
targetProtectedTailStart = fenced;
|
|
187006
|
+
const snapped = snapWrapupBoundaryToUser({
|
|
187007
|
+
messages,
|
|
187008
|
+
index,
|
|
187009
|
+
candidate: targetProtectedTailStart,
|
|
187010
|
+
offset,
|
|
187011
|
+
triggerBudget: ctx.triggerBudget
|
|
187012
|
+
});
|
|
187013
|
+
if (snapped !== targetProtectedTailStart)
|
|
187014
|
+
boundaryReason = "manual-wrapup-user-snap";
|
|
187015
|
+
targetProtectedTailStart = snapped;
|
|
187016
|
+
const refenced = fenceWrapupBoundaryForToolArcs({
|
|
187017
|
+
candidate: targetProtectedTailStart,
|
|
187018
|
+
arcs,
|
|
187019
|
+
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal
|
|
187020
|
+
});
|
|
187021
|
+
if (refenced !== targetProtectedTailStart)
|
|
187022
|
+
boundaryReason = "manual-wrapup-tool-arc";
|
|
187023
|
+
targetProtectedTailStart = refenced;
|
|
187024
|
+
}
|
|
187025
|
+
targetProtectedTailStart = clampOrdinal(targetProtectedTailStart, rawMessageCount);
|
|
187026
|
+
const target = deriveProtectedTailTokenTarget({
|
|
187027
|
+
contextLimit: ctx.contextLimit,
|
|
187028
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
187029
|
+
usagePercentage,
|
|
187030
|
+
triggerBudget: ctx.triggerBudget
|
|
187031
|
+
});
|
|
187032
|
+
const perRunCap = selectPerRunCap({
|
|
187033
|
+
usagePercentage,
|
|
187034
|
+
N: target.N,
|
|
187035
|
+
contextLimit: ctx.contextLimit,
|
|
187036
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage
|
|
187037
|
+
});
|
|
187038
|
+
const head = applyHeadCap({
|
|
187039
|
+
index,
|
|
187040
|
+
protectedTailStart: targetProtectedTailStart,
|
|
187041
|
+
offset,
|
|
187042
|
+
arcs: buildToolArcs(messages),
|
|
187043
|
+
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal,
|
|
187044
|
+
capTokens: perRunCap,
|
|
187045
|
+
recentOpenArcCutoff: targetProtectedTailStart
|
|
187046
|
+
});
|
|
187047
|
+
const eligibleEndOrdinal = Math.min(head.eligibleEndOrdinal, targetProtectedTailStart);
|
|
187048
|
+
const rawRangeFingerprint = computeRawRangeFingerprint(messages, offset, eligibleEndOrdinal);
|
|
187049
|
+
const snapshot = {
|
|
187050
|
+
sessionId: ctx.sessionId,
|
|
187051
|
+
mode: "manual-wrapup",
|
|
187052
|
+
offset,
|
|
187053
|
+
offsetMessageId: boundaryMessageId(index, offset),
|
|
187054
|
+
protectedTailStart: targetProtectedTailStart,
|
|
187055
|
+
protectedTailStartMessageId: boundaryMessageId(index, targetProtectedTailStart),
|
|
187056
|
+
eligibleEndOrdinal,
|
|
187057
|
+
eligibleEndMessageId: boundaryMessageId(index, eligibleEndOrdinal - 1),
|
|
187058
|
+
rawMessageCountAtTrigger: rawMessageCount,
|
|
187059
|
+
rawLastMessageIdAtTrigger: boundaryMessageId(index, rawMessageCount),
|
|
187060
|
+
N: keep,
|
|
187061
|
+
usagePercentage,
|
|
187062
|
+
usageInputTokens,
|
|
187063
|
+
usageSource: ctx.usageSource,
|
|
187064
|
+
contextLimit: ctx.contextLimit,
|
|
187065
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
187066
|
+
triggerBudget: ctx.triggerBudget,
|
|
187067
|
+
priorBoundaryOrdinal: ctx.priorBoundaryOrdinal,
|
|
187068
|
+
migrationFloorActive: ctx.migrationFloorActive,
|
|
187069
|
+
emergencyTailScale: ctx.emergencyTailScale,
|
|
187070
|
+
providerShapeVersion: ctx.providerShapeVersion,
|
|
187071
|
+
cacheNamespace: ctx.cacheNamespace,
|
|
187072
|
+
createdAt,
|
|
187073
|
+
rawRangeFingerprint,
|
|
187074
|
+
trueRawEligibleTokens: index.rangeTokens(offset, targetProtectedTailStart),
|
|
187075
|
+
oversizeAtomicUnit: head.oversizeAtomicUnit,
|
|
187076
|
+
boundaryReason
|
|
187077
|
+
};
|
|
187078
|
+
return {
|
|
187079
|
+
snapshot,
|
|
187080
|
+
rawMessagesAboveLastCompartment,
|
|
187081
|
+
anchorRawMessageCount,
|
|
187082
|
+
targetProtectedTailStart,
|
|
187083
|
+
targetEligibleEndOrdinal: targetProtectedTailStart
|
|
187084
|
+
};
|
|
187085
|
+
}
|
|
186637
187086
|
function getRawHistoryEligibility(db, sessionId) {
|
|
186638
187087
|
const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
|
|
186639
187088
|
const offset = Math.max(1, lastCompartmentEnd + 1);
|
|
@@ -188679,6 +189128,147 @@ function searchMessages(args) {
|
|
|
188679
189128
|
role: entry.row.role
|
|
188680
189129
|
}));
|
|
188681
189130
|
}
|
|
189131
|
+
var NOTE_SEARCHABLE_STATUSES = ["active", "pending", "ready", "dismissed"];
|
|
189132
|
+
function noteSearchText(note) {
|
|
189133
|
+
const reason = note.readyReason?.trim();
|
|
189134
|
+
return reason ? `${note.content}
|
|
189135
|
+
Reason: ${reason}` : note.content;
|
|
189136
|
+
}
|
|
189137
|
+
function tokenizeKeywordNeedle(text) {
|
|
189138
|
+
const matches = text.toLowerCase().match(/[a-z0-9/._:-]+/g) ?? [];
|
|
189139
|
+
const seen = new Set;
|
|
189140
|
+
const tokens = [];
|
|
189141
|
+
for (const match of matches) {
|
|
189142
|
+
if (match.length <= 1 || !/[a-z0-9]/.test(match) || seen.has(match)) {
|
|
189143
|
+
continue;
|
|
189144
|
+
}
|
|
189145
|
+
seen.add(match);
|
|
189146
|
+
tokens.push(match);
|
|
189147
|
+
}
|
|
189148
|
+
return tokens;
|
|
189149
|
+
}
|
|
189150
|
+
function rankNotesForNeedle(notes, needle) {
|
|
189151
|
+
const normalizedNeedle = needle.trim().toLowerCase();
|
|
189152
|
+
if (normalizedNeedle.length === 0) {
|
|
189153
|
+
return [];
|
|
189154
|
+
}
|
|
189155
|
+
const needleTokens = tokenizeKeywordNeedle(normalizedNeedle);
|
|
189156
|
+
const ranked = [];
|
|
189157
|
+
for (const note of notes) {
|
|
189158
|
+
const text = noteSearchText(note);
|
|
189159
|
+
const normalizedText = text.toLowerCase();
|
|
189160
|
+
const noteTokens = new Set(tokenizeKeywordNeedle(normalizedText));
|
|
189161
|
+
const exact = normalizedText.includes(normalizedNeedle);
|
|
189162
|
+
const matchedTokens = needleTokens.filter((token) => noteTokens.has(token)).length;
|
|
189163
|
+
if (!exact && matchedTokens === 0) {
|
|
189164
|
+
continue;
|
|
189165
|
+
}
|
|
189166
|
+
const coverage = needleTokens.length > 0 ? matchedTokens / needleTokens.length : 0;
|
|
189167
|
+
const score = (exact ? 2 : 0) + coverage + (needleTokens.length > 1 && matchedTokens === needleTokens.length ? 0.5 : 0);
|
|
189168
|
+
ranked.push({ note, score, text });
|
|
189169
|
+
}
|
|
189170
|
+
return ranked.sort((left, right) => {
|
|
189171
|
+
if (right.score !== left.score) {
|
|
189172
|
+
return right.score - left.score;
|
|
189173
|
+
}
|
|
189174
|
+
if (right.note.createdAt !== left.note.createdAt) {
|
|
189175
|
+
return right.note.createdAt - left.note.createdAt;
|
|
189176
|
+
}
|
|
189177
|
+
return left.note.id - right.note.id;
|
|
189178
|
+
});
|
|
189179
|
+
}
|
|
189180
|
+
function searchNotes(args) {
|
|
189181
|
+
if (args.limit <= 0) {
|
|
189182
|
+
return [];
|
|
189183
|
+
}
|
|
189184
|
+
const notes = [
|
|
189185
|
+
...getNotes(args.db, {
|
|
189186
|
+
sessionId: args.sessionId,
|
|
189187
|
+
type: "session",
|
|
189188
|
+
status: NOTE_SEARCHABLE_STATUSES
|
|
189189
|
+
}),
|
|
189190
|
+
...getNotes(args.db, {
|
|
189191
|
+
projectPath: args.projectPath,
|
|
189192
|
+
type: "smart",
|
|
189193
|
+
status: NOTE_SEARCHABLE_STATUSES
|
|
189194
|
+
})
|
|
189195
|
+
];
|
|
189196
|
+
if (notes.length === 0) {
|
|
189197
|
+
return [];
|
|
189198
|
+
}
|
|
189199
|
+
const baseList = rankNotesForNeedle(notes, args.query);
|
|
189200
|
+
const probes = args.probes ?? [];
|
|
189201
|
+
if (probes.length === 0) {
|
|
189202
|
+
const ranked2 = baseList.slice(0, args.limit);
|
|
189203
|
+
return ranked2.map((entry, rank) => ({
|
|
189204
|
+
source: "note",
|
|
189205
|
+
content: previewText(entry.text),
|
|
189206
|
+
score: linearDecayScore(rank, ranked2.length),
|
|
189207
|
+
noteId: entry.note.id,
|
|
189208
|
+
status: entry.note.status,
|
|
189209
|
+
createdAt: entry.note.createdAt,
|
|
189210
|
+
anchorOrdinal: entry.note.anchorOrdinal,
|
|
189211
|
+
sourceSessionId: entry.note.sessionId
|
|
189212
|
+
}));
|
|
189213
|
+
}
|
|
189214
|
+
const queryLists = [];
|
|
189215
|
+
if (baseList.length > 0) {
|
|
189216
|
+
queryLists.push({ rows: baseList, weight: 1 });
|
|
189217
|
+
}
|
|
189218
|
+
const probeWeights = new Map;
|
|
189219
|
+
for (const probe of probes) {
|
|
189220
|
+
const rows = rankNotesForNeedle(notes, probe);
|
|
189221
|
+
if (rows.length === 0) {
|
|
189222
|
+
continue;
|
|
189223
|
+
}
|
|
189224
|
+
const weight = probeDiscriminationWeight(rows.length, notes.length);
|
|
189225
|
+
probeWeights.set(probe, weight);
|
|
189226
|
+
queryLists.push({ rows, weight });
|
|
189227
|
+
}
|
|
189228
|
+
const fused = new Map;
|
|
189229
|
+
for (const list of queryLists) {
|
|
189230
|
+
list.rows.forEach((row, rank) => {
|
|
189231
|
+
const rrf = list.weight / (RRF_K + rank);
|
|
189232
|
+
const existing = fused.get(row.note.id);
|
|
189233
|
+
if (existing) {
|
|
189234
|
+
existing.score += rrf;
|
|
189235
|
+
} else {
|
|
189236
|
+
fused.set(row.note.id, { entry: row, score: rrf });
|
|
189237
|
+
}
|
|
189238
|
+
});
|
|
189239
|
+
}
|
|
189240
|
+
for (const match of fused.values()) {
|
|
189241
|
+
let best = 0;
|
|
189242
|
+
for (const probe of probes) {
|
|
189243
|
+
const weight = probeWeights.get(probe) ?? 0;
|
|
189244
|
+
if (weight > best && containsProbeVerbatim(match.entry.text, [probe])) {
|
|
189245
|
+
best = weight;
|
|
189246
|
+
}
|
|
189247
|
+
}
|
|
189248
|
+
if (best > 0) {
|
|
189249
|
+
match.score += best * VERBATIM_RANK_BONUS;
|
|
189250
|
+
}
|
|
189251
|
+
}
|
|
189252
|
+
const ranked = [...fused.values()].sort((left, right) => {
|
|
189253
|
+
if (right.score !== left.score) {
|
|
189254
|
+
return right.score - left.score;
|
|
189255
|
+
}
|
|
189256
|
+
if (right.entry.note.createdAt !== left.entry.note.createdAt) {
|
|
189257
|
+
return right.entry.note.createdAt - left.entry.note.createdAt;
|
|
189258
|
+
}
|
|
189259
|
+
return left.entry.note.id - right.entry.note.id;
|
|
189260
|
+
}).slice(0, args.limit);
|
|
189261
|
+
return ranked.map((entry, rank) => ({
|
|
189262
|
+
source: "note",
|
|
189263
|
+
content: previewText(entry.entry.text),
|
|
189264
|
+
score: linearDecayScore(rank, ranked.length),
|
|
189265
|
+
noteId: entry.entry.note.id,
|
|
189266
|
+
status: entry.entry.note.status,
|
|
189267
|
+
createdAt: entry.entry.note.createdAt,
|
|
189268
|
+
anchorOrdinal: entry.entry.note.anchorOrdinal,
|
|
189269
|
+
sourceSessionId: entry.entry.note.sessionId
|
|
189270
|
+
}));
|
|
189271
|
+
}
|
|
188682
189272
|
function searchCompartmentChunks(args) {
|
|
188683
189273
|
if (!args.queryEmbedding || args.limit <= 0 || !args.modelId || args.modelId === "off")
|
|
188684
189274
|
return [];
|
|
@@ -188764,6 +189354,8 @@ function getSourceBoost(result) {
|
|
|
188764
189354
|
return GIT_COMMIT_SOURCE_BOOST;
|
|
188765
189355
|
case "primer":
|
|
188766
189356
|
return PRIMER_SOURCE_BOOST;
|
|
189357
|
+
case "note":
|
|
189358
|
+
return 1;
|
|
188767
189359
|
}
|
|
188768
189360
|
}
|
|
188769
189361
|
function compareUnifiedResults(left, right) {
|
|
@@ -188787,6 +189379,9 @@ function compareUnifiedResults(left, right) {
|
|
|
188787
189379
|
if (left.source === "primer" && right.source === "primer") {
|
|
188788
189380
|
return right.support - left.support || left.primerId - right.primerId;
|
|
188789
189381
|
}
|
|
189382
|
+
if (left.source === "note" && right.source === "note") {
|
|
189383
|
+
return right.createdAt - left.createdAt || left.noteId - right.noteId;
|
|
189384
|
+
}
|
|
188790
189385
|
return 0;
|
|
188791
189386
|
}
|
|
188792
189387
|
function toGitCommitResult(hit) {
|
|
@@ -188854,11 +189449,11 @@ function searchPrimers(args) {
|
|
|
188854
189449
|
}
|
|
188855
189450
|
function resolveSources(sources) {
|
|
188856
189451
|
if (sources === undefined) {
|
|
188857
|
-
return new Set(["memory", "message", "git_commit", "primer"]);
|
|
189452
|
+
return new Set(["memory", "message", "git_commit", "primer", "note"]);
|
|
188858
189453
|
}
|
|
188859
189454
|
const set2 = new Set;
|
|
188860
189455
|
for (const source of sources) {
|
|
188861
|
-
if (source === "memory" || source === "message" || source === "git_commit" || source === "primer") {
|
|
189456
|
+
if (source === "memory" || source === "message" || source === "git_commit" || source === "primer" || source === "note") {
|
|
188862
189457
|
set2.add(source);
|
|
188863
189458
|
}
|
|
188864
189459
|
}
|
|
@@ -188881,6 +189476,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
188881
189476
|
const runMessages = activeSources.has("message");
|
|
188882
189477
|
const runGitCommits = activeSources.has("git_commit") && gitCommitsEnabled;
|
|
188883
189478
|
const runPrimers = activeSources.has("primer") && memoryFeatureEnabled;
|
|
189479
|
+
const runNotes = activeSources.has("note");
|
|
188884
189480
|
const runCompartmentChunks = runMessages && memoryFeatureEnabled && embeddingEnabled;
|
|
188885
189481
|
const needsEmbedding = (runMemory || runGitCommits || runCompartmentChunks || runPrimers) && embeddingEnabled && isEmbeddingRuntimeEnabled();
|
|
188886
189482
|
const queryEmbeddingPromise = needsEmbedding ? embedQuery(trimmedQuery, options.signal).catch((error51) => {
|
|
@@ -188916,7 +189512,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
188916
189512
|
compartments: compartmentResults,
|
|
188917
189513
|
limit: tierLimit
|
|
188918
189514
|
});
|
|
188919
|
-
const [memoryResults, gitCommitResults, primerResults] = await Promise.all([
|
|
189515
|
+
const [memoryResults, gitCommitResults, primerResults, noteResults] = await Promise.all([
|
|
188920
189516
|
runMemory ? searchMemories({
|
|
188921
189517
|
db,
|
|
188922
189518
|
projectPath,
|
|
@@ -188943,9 +189539,23 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
188943
189539
|
limit: tierLimit,
|
|
188944
189540
|
queryEmbedding,
|
|
188945
189541
|
queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null
|
|
189542
|
+
})) : Promise.resolve([]),
|
|
189543
|
+
runNotes ? Promise.resolve(searchNotes({
|
|
189544
|
+
db,
|
|
189545
|
+
sessionId,
|
|
189546
|
+
projectPath,
|
|
189547
|
+
query: trimmedQuery,
|
|
189548
|
+
limit: tierLimit,
|
|
189549
|
+
probes: messageProbes
|
|
188946
189550
|
})) : Promise.resolve([])
|
|
188947
189551
|
]);
|
|
188948
|
-
const results = [
|
|
189552
|
+
const results = [
|
|
189553
|
+
...memoryResults,
|
|
189554
|
+
...primerResults,
|
|
189555
|
+
...messageLikeResults,
|
|
189556
|
+
...gitCommitResults,
|
|
189557
|
+
...noteResults
|
|
189558
|
+
].sort(compareUnifiedResults).slice(0, limit);
|
|
188949
189559
|
const countRetrievals = options.countRetrievals ?? true;
|
|
188950
189560
|
if (countRetrievals) {
|
|
188951
189561
|
const memoryIds = results.filter((result) => result.source === "memory").map((result) => result.memoryId);
|
|
@@ -189014,6 +189624,10 @@ function renderFragment(result, charCap) {
|
|
|
189014
189624
|
const compressed = cavemanCompress(result.content, "ultra");
|
|
189015
189625
|
return truncate(compressed, charCap);
|
|
189016
189626
|
}
|
|
189627
|
+
case "note": {
|
|
189628
|
+
const compressed = cavemanCompress(result.content, "ultra");
|
|
189629
|
+
return truncate(compressed, charCap);
|
|
189630
|
+
}
|
|
189017
189631
|
}
|
|
189018
189632
|
}
|
|
189019
189633
|
function buildAutoSearchHint(results, options = {}) {
|
|
@@ -189235,13 +189849,11 @@ async function runAutoSearchHintForPi(args) {
|
|
|
189235
189849
|
};
|
|
189236
189850
|
results = await unifiedSearchWithTimeout(db, sessionId, options.projectPath, rawPrompt, searchOptions, AUTO_SEARCH_TIMEOUT_MS);
|
|
189237
189851
|
} catch (error51) {
|
|
189238
|
-
log(`[auto-search] unified search failed for session ${sessionId}: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
189239
|
-
writeNoHintAndReconcile("error");
|
|
189852
|
+
log(`[auto-search] unified search failed for session ${sessionId} (will retry next pass): ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
189240
189853
|
return messages;
|
|
189241
189854
|
}
|
|
189242
189855
|
if (results === null) {
|
|
189243
|
-
sessionLog(sessionId, `auto-search: timed out after ${AUTO_SEARCH_TIMEOUT_MS}ms, skipping hint for this turn`);
|
|
189244
|
-
writeNoHintAndReconcile("timeout");
|
|
189856
|
+
sessionLog(sessionId, `auto-search: timed out after ${AUTO_SEARCH_TIMEOUT_MS}ms, skipping hint for this turn (will retry)`);
|
|
189245
189857
|
return messages;
|
|
189246
189858
|
}
|
|
189247
189859
|
if (results.length === 0) {
|
|
@@ -190816,6 +191428,15 @@ function findCompartmentBoundaryForSnapshot(markers) {
|
|
|
190816
191428
|
return null;
|
|
190817
191429
|
return markers.lastBaselineEndMessageId;
|
|
190818
191430
|
}
|
|
191431
|
+
function resolveRenderedCompartmentBoundary(compartments, boundaryId) {
|
|
191432
|
+
if (!boundaryId)
|
|
191433
|
+
return { endMessageId: null, ordinal: null };
|
|
191434
|
+
const boundary = compartments.find((compartment) => compartment.endMessageId === boundaryId);
|
|
191435
|
+
return {
|
|
191436
|
+
endMessageId: boundaryId,
|
|
191437
|
+
ordinal: typeof boundary?.endMessage === "number" ? boundary.endMessage : null
|
|
191438
|
+
};
|
|
191439
|
+
}
|
|
190819
191440
|
function prependM0M1Messages(piMessages, m0, m1) {
|
|
190820
191441
|
const firstTimestamp = piMessages[0]?.timestamp;
|
|
190821
191442
|
const baseTimestamp = typeof firstTimestamp === "number" ? firstTimestamp : Date.now();
|
|
@@ -190945,6 +191566,7 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
190945
191566
|
}
|
|
190946
191567
|
}
|
|
190947
191568
|
const boundaryId = findCompartmentBoundaryForSnapshot(markers);
|
|
191569
|
+
const renderedBoundary = resolveRenderedCompartmentBoundary(currentCompartments, boundaryId);
|
|
190948
191570
|
const skippedVisibleMessages = boundaryId ? trimPiMessagesToBoundary(piMessages, entryIds, boundaryId) : 0;
|
|
190949
191571
|
prependM0M1Messages(piMessages, m0, m1);
|
|
190950
191572
|
sessionLog(state.sessionId, `injected m[0]/m[1] into Pi messages (${m0.length} + ${m1.length} bytes, materialized=${materialized}${decision.reason ? ` reason=${decision.reason}` : ""})`);
|
|
@@ -190961,6 +191583,8 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
190961
191583
|
m0Reason: decision.reason,
|
|
190962
191584
|
m0Bytes: m0.length,
|
|
190963
191585
|
m1Bytes: m1.length,
|
|
191586
|
+
contentionExhausted,
|
|
191587
|
+
renderedBoundary,
|
|
190964
191588
|
syntheticLeadingCount: 2
|
|
190965
191589
|
};
|
|
190966
191590
|
}
|
|
@@ -194232,7 +194856,9 @@ async function runPiHistorian(deps) {
|
|
|
194232
194856
|
compartmentLeaseHolderId,
|
|
194233
194857
|
readBranchEntries,
|
|
194234
194858
|
notifyIssue,
|
|
194235
|
-
ensureProjectRegistered = ensureProjectRegisteredFromPiDirectory
|
|
194859
|
+
ensureProjectRegistered = ensureProjectRegisteredFromPiDirectory,
|
|
194860
|
+
forceDrainQuota,
|
|
194861
|
+
forceKeepLastCompartment
|
|
194236
194862
|
} = deps;
|
|
194237
194863
|
const notify = async (message) => {
|
|
194238
194864
|
if (shouldSuppressHistorianAlert(sessionId)) {
|
|
@@ -194307,7 +194933,8 @@ async function runPiHistorian(deps) {
|
|
|
194307
194933
|
if (protectedTailStart <= offset || eligibleEndOrdinal <= offset) {
|
|
194308
194934
|
sessionLog(sessionId, `historian no-op: protectedTailStart=${protectedTailStart} eligibleEnd=${eligibleEndOrdinal} <= offset=${offset} — nothing to compact`);
|
|
194309
194935
|
if (boundarySnapshot.usagePercentage < 80) {
|
|
194310
|
-
|
|
194936
|
+
if (!isWrapupInProgress(db, sessionId))
|
|
194937
|
+
clearEmergencyRecovery(db, sessionId);
|
|
194311
194938
|
} else {
|
|
194312
194939
|
recordHighPressureNoEligibleHead(db, boundarySnapshot);
|
|
194313
194940
|
}
|
|
@@ -194316,7 +194943,7 @@ async function runPiHistorian(deps) {
|
|
|
194316
194943
|
}
|
|
194317
194944
|
const perRunCap = selectPerRunCap(boundarySnapshot);
|
|
194318
194945
|
const usable = Math.max(1, Math.round(boundarySnapshot.contextLimit * boundarySnapshot.executeThresholdPercentage / 100));
|
|
194319
|
-
const reserve = reserveProtectedTailDrainTokens({
|
|
194946
|
+
const reserve = forceDrainQuota ? { ok: true, reservation: null } : reserveProtectedTailDrainTokens({
|
|
194320
194947
|
db,
|
|
194321
194948
|
sessionId,
|
|
194322
194949
|
runId: crypto2.randomUUID(),
|
|
@@ -194334,10 +194961,12 @@ async function runPiHistorian(deps) {
|
|
|
194334
194961
|
}
|
|
194335
194962
|
drainReservation = reserve.reservation;
|
|
194336
194963
|
const chunk = readSessionChunk(sessionId, historianChunkTokens, offset, eligibleEndOrdinal);
|
|
194964
|
+
const forceKeepLastCompartmentForChunk = forceKeepLastCompartment === true && !chunk.hasMore;
|
|
194337
194965
|
if (!chunk.text || chunk.messageCount === 0) {
|
|
194338
194966
|
sessionLog(sessionId, `historian no-op: chunk empty after filtering (messageCount=${chunk.messageCount}, textLen=${chunk.text?.length ?? 0}) range=${offset}-${protectedTailStart - 1}`);
|
|
194339
194967
|
if (boundarySnapshot.usagePercentage < 80) {
|
|
194340
|
-
|
|
194968
|
+
if (!isWrapupInProgress(db, sessionId))
|
|
194969
|
+
clearEmergencyRecovery(db, sessionId);
|
|
194341
194970
|
} else {
|
|
194342
194971
|
recordHighPressureNoEligibleHead(db, boundarySnapshot);
|
|
194343
194972
|
}
|
|
@@ -194527,7 +195156,7 @@ ${chunkText}`,
|
|
|
194527
195156
|
const inEmergency = getOverflowState(db, sessionId).needsEmergencyRecovery;
|
|
194528
195157
|
const emittedCompartments = validatedPass.compartments;
|
|
194529
195158
|
let newCompartments = emittedCompartments;
|
|
194530
|
-
if (!inEmergency && emittedCompartments.length >= 2) {
|
|
195159
|
+
if (!inEmergency && !forceKeepLastCompartmentForChunk && emittedCompartments.length >= 2) {
|
|
194531
195160
|
const lastEmitted = emittedCompartments[emittedCompartments.length - 1];
|
|
194532
195161
|
const lookaheadMargin = chunk.endIndex - lastEmitted.endMessage;
|
|
194533
195162
|
if (lookaheadMargin <= BOUNDARY_HEALING_SLACK) {
|
|
@@ -194560,9 +195189,19 @@ ${chunkText}`,
|
|
|
194560
195189
|
}
|
|
194561
195190
|
}
|
|
194562
195191
|
const discardedLast = newCompartments.length < emittedCompartments.length;
|
|
195192
|
+
const weakLookaheadFinalCompartment = forceKeepLastCompartmentForChunk;
|
|
195193
|
+
const skipUnanchoredPromotion = discardedLast || weakLookaheadFinalCompartment;
|
|
194563
195194
|
const embeddingActive = memoryEnabled !== false;
|
|
194564
195195
|
const promotionActive = embeddingActive && autoPromote !== false;
|
|
194565
|
-
const publishableEvents = (validatedPass.events ?? []).filter((e) =>
|
|
195196
|
+
const publishableEvents = (validatedPass.events ?? []).filter((e) => {
|
|
195197
|
+
if (typeof e.atCompartment !== "number")
|
|
195198
|
+
return !weakLookaheadFinalCompartment;
|
|
195199
|
+
if (e.atCompartment > newCompartments.length)
|
|
195200
|
+
return false;
|
|
195201
|
+
if (weakLookaheadFinalCompartment && e.atCompartment >= emittedCompartments.length)
|
|
195202
|
+
return false;
|
|
195203
|
+
return true;
|
|
195204
|
+
});
|
|
194566
195205
|
let promotedFactRefs = [];
|
|
194567
195206
|
let persistedIds = [];
|
|
194568
195207
|
if (!compartmentLeaseHolderId) {
|
|
@@ -194581,7 +195220,7 @@ ${chunkText}`,
|
|
|
194581
195220
|
}
|
|
194582
195221
|
appendCompartments(db, sessionId, newCompartments);
|
|
194583
195222
|
persistedIds = getCompartments(db, sessionId).slice(-newCompartments.length).map((c) => c.id);
|
|
194584
|
-
if (promotionActive && !
|
|
195223
|
+
if (promotionActive && !skipUnanchoredPromotion) {
|
|
194585
195224
|
promotedFactRefs = promoteSessionFactsDurable(db, sessionId, projectPath, validatedPass.facts ?? []);
|
|
194586
195225
|
}
|
|
194587
195226
|
if (publishableEvents.length > 0) {
|
|
@@ -194596,7 +195235,8 @@ ${chunkText}`,
|
|
|
194596
195235
|
clearHistorianFailureState(db, sessionId);
|
|
194597
195236
|
clearHistorianDrainFailure(db, sessionId);
|
|
194598
195237
|
recordProtectedTailPublicationFloor(db, sessionId, lastNewEnd + 1);
|
|
194599
|
-
|
|
195238
|
+
if (!isWrapupInProgress(db, sessionId))
|
|
195239
|
+
clearEmergencyRecovery(db, sessionId);
|
|
194600
195240
|
if (firstKeptEntryId && lastNewEndMessageId) {
|
|
194601
195241
|
setPendingPiCompactionMarkerState(db, sessionId, {
|
|
194602
195242
|
firstKeptEntryId,
|
|
@@ -194620,7 +195260,7 @@ ${chunkText}`,
|
|
|
194620
195260
|
completedSuccessfully = true;
|
|
194621
195261
|
sessionLog(sessionId, `historian: published ${newCompartments.length} compartment(s), ${validatedPass.facts?.length ?? 0} fact(s) covering messages ${chunk.startIndex}-${lastNewEnd}`);
|
|
194622
195262
|
onNoteTrigger(db, sessionId, "historian_complete");
|
|
194623
|
-
if (userMemoriesEnabled === true && !
|
|
195263
|
+
if (userMemoriesEnabled === true && !skipUnanchoredPromotion && validatedPass.userObservations?.length) {
|
|
194624
195264
|
try {
|
|
194625
195265
|
insertUserMemoryCandidates(db, validatedPass.userObservations.map((obs) => ({
|
|
194626
195266
|
content: obs,
|
|
@@ -194633,7 +195273,7 @@ ${chunkText}`,
|
|
|
194633
195273
|
sessionLog(sessionId, "failed to store user memory candidates:", error51);
|
|
194634
195274
|
}
|
|
194635
195275
|
}
|
|
194636
|
-
if (!
|
|
195276
|
+
if (!skipUnanchoredPromotion && validatedPass.primerCandidates?.length && projectPath) {
|
|
194637
195277
|
try {
|
|
194638
195278
|
const firstNew = newCompartments[0];
|
|
194639
195279
|
const lastNew = newCompartments[newCompartments.length - 1];
|
|
@@ -195330,7 +195970,7 @@ Drop silently — do not narrate it. NEVER drop large ranges blindly (e.g., "1-5
|
|
|
195330
195970
|
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.`;
|
|
195331
195971
|
var CAVEMAN_COMPRESSION_WARNING = `
|
|
195332
195972
|
**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.`;
|
|
195333
|
-
function buildMagicContextSection(_agent, protectedTags,
|
|
195973
|
+
function buildMagicContextSection(_agent, protectedTags, ctxReduceCallable = true, dreamerEnabled = false, temporalAwarenessEnabled = false, cavemanTextCompressionEnabled = false, subagentMode = false, language, memoryEnabled = true) {
|
|
195334
195974
|
if (subagentMode) {
|
|
195335
195975
|
return `## Magic Context
|
|
195336
195976
|
|
|
@@ -195341,12 +195981,12 @@ When \`surface_condition\` is provided with \`write\`, the note becomes a projec
|
|
|
195341
195981
|
The dreamer evaluates smart note conditions during nightly runs and surfaces them when conditions are met.
|
|
195342
195982
|
Example: \`ctx_note(action="write", content="Implement X because Y", surface_condition="When PR #42 is merged in this repo")\`` : "";
|
|
195343
195983
|
const temporalGuidance = temporalAwarenessEnabled ? TEMPORAL_AWARENESS_GUIDANCE : "";
|
|
195344
|
-
const cavemanWarning = cavemanTextCompressionEnabled
|
|
195984
|
+
const cavemanWarning = cavemanTextCompressionEnabled ? CAVEMAN_COMPRESSION_WARNING : "";
|
|
195345
195985
|
const languageDirective = buildPrimaryLanguageDirective(language);
|
|
195346
195986
|
const languageGuidance = languageDirective ? `
|
|
195347
195987
|
|
|
195348
195988
|
${languageDirective}` : "";
|
|
195349
|
-
if (!
|
|
195989
|
+
if (!ctxReduceCallable) {
|
|
195350
195990
|
return `## Magic Context
|
|
195351
195991
|
|
|
195352
195992
|
${LONG_TERM_PARTNER_FRAME}
|
|
@@ -195359,7 +195999,7 @@ ${BASE_INTRO_NO_REDUCE(memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${c
|
|
|
195359
195999
|
${LONG_TERM_PARTNER_FRAME}
|
|
195360
196000
|
${PARTNER_FRAME_CLOSER_REDUCE}
|
|
195361
196001
|
|
|
195362
|
-
${BASE_INTRO(protectedTags, memoryEnabled)}${smartNoteGuidance}${temporalGuidance}
|
|
196002
|
+
${BASE_INTRO(protectedTags, memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}
|
|
195363
196003
|
${GENERIC_SECTION}
|
|
195364
196004
|
|
|
195365
196005
|
Prefer many small targeted operations over one large blanket operation, and keep the working set tidy as routine maintenance.${languageGuidance}`;
|
|
@@ -195374,7 +196014,7 @@ function buildMagicContextBlock(opts) {
|
|
|
195374
196014
|
const includeGuidance = (opts.includeGuidance ?? true) && !existing.includes(MAGIC_CONTEXT_MARKER);
|
|
195375
196015
|
if (!includeGuidance)
|
|
195376
196016
|
return null;
|
|
195377
|
-
return buildMagicContextSection(null, opts.protectedTags ?? 20, opts.
|
|
196017
|
+
return buildMagicContextSection(null, opts.protectedTags ?? 20, opts.ctxReduceCallable ?? true, opts.dreamerEnabled ?? false, opts.temporalAwarenessEnabled ?? false, opts.cavemanTextCompressionEnabled ?? false, false, opts.language, opts.memoryEnabled !== false);
|
|
195378
196018
|
}
|
|
195379
196019
|
var DATE_PATTERN = /Today's date: .+/;
|
|
195380
196020
|
function processSystemPromptForCache(args) {
|
|
@@ -196067,6 +196707,7 @@ function applyForwardPressureFloor(trailingPercentage, trailingInputTokens, piUs
|
|
|
196067
196707
|
inputTokens: Math.max(trailingInputTokens, forwardTokens)
|
|
196068
196708
|
} : { percentage: trailingPercentage, inputTokens: trailingInputTokens };
|
|
196069
196709
|
}
|
|
196710
|
+
var injectM0M1PiForRun = injectM0M1Pi;
|
|
196070
196711
|
var DEFAULT_CLEAR_REASONING_AGE = 50;
|
|
196071
196712
|
var PI_STABLE_ID_SCHEME = 1;
|
|
196072
196713
|
var lastEmergencyNotificationAtMs = new Map;
|
|
@@ -196766,7 +197407,6 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
196766
197407
|
projectIdentity,
|
|
196767
197408
|
projectDirectory,
|
|
196768
197409
|
messages: event.messages,
|
|
196769
|
-
ctxReduceEnabled: options.ctxReduceEnabled,
|
|
196770
197410
|
smartDrops: options.smartDrops === true,
|
|
196771
197411
|
protectedTags: options.protectedTags ?? 20,
|
|
196772
197412
|
heuristics: options.heuristics,
|
|
@@ -196799,7 +197439,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
196799
197439
|
},
|
|
196800
197440
|
temporalAwareness: options.injection?.temporalAwareness === true,
|
|
196801
197441
|
appendCompaction: resolvePiAppendCompaction(ctx),
|
|
196802
|
-
readBranchEntries: resolvePiReadBranchEntries(ctx)
|
|
197442
|
+
readBranchEntries: resolvePiReadBranchEntries(ctx),
|
|
197443
|
+
isSubagent: sessionMeta.isSubagent
|
|
196803
197444
|
});
|
|
196804
197445
|
const piDecisionSnapshotNewestAssistant = branchEntries === null ? undefined : findNewestPiAssistantEntryId(branchEntries);
|
|
196805
197446
|
if (result.bustedThisPass && piDecisionSnapshotNewestAssistant !== undefined) {
|
|
@@ -196881,7 +197522,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
196881
197522
|
}
|
|
196882
197523
|
try {
|
|
196883
197524
|
const sessionMetaForCh1 = getOrCreateSessionMeta(options.db, sessionId);
|
|
196884
|
-
if (
|
|
197525
|
+
if (!sessionMetaForCh1.isSubagent) {
|
|
196885
197526
|
const resolvedExecuteThresholdPct = resolveExecuteThreshold(schedulerConfig.executeThresholdPercentage ?? 65, liveModelBySession.get(sessionId), 65, {
|
|
196886
197527
|
tokensConfig: schedulerConfig.executeThresholdTokens,
|
|
196887
197528
|
contextLimit: usageContextLimit ?? 0
|
|
@@ -197009,8 +197650,12 @@ function resolveHistoryBudgetTokensForPi(args) {
|
|
|
197009
197650
|
}
|
|
197010
197651
|
function startPiCompartmentLeaseRenewal(db, sessionId, holderId) {
|
|
197011
197652
|
return setInterval(() => {
|
|
197012
|
-
|
|
197013
|
-
|
|
197653
|
+
try {
|
|
197654
|
+
if (!renewCompartmentLease(db, sessionId, holderId)) {
|
|
197655
|
+
sessionLog(sessionId, "compartment lease renewal failed; publish will be skipped if holder is stale");
|
|
197656
|
+
}
|
|
197657
|
+
} catch (err) {
|
|
197658
|
+
sessionLog(sessionId, `compartment lease renewal threw; publish will be skipped if holder is stale (${err instanceof Error ? err.message : String(err)})`);
|
|
197014
197659
|
}
|
|
197015
197660
|
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
197016
197661
|
}
|
|
@@ -197070,6 +197715,11 @@ function spawnPiHistorianRun(args) {
|
|
|
197070
197715
|
sessionLog(sessionId, "historian skipped: compartment lease held by another process");
|
|
197071
197716
|
return;
|
|
197072
197717
|
}
|
|
197718
|
+
if (isWrapupInProgress(db, sessionId)) {
|
|
197719
|
+
sessionLog(sessionId, "historian skipped: /ctx-wrapup became active");
|
|
197720
|
+
releaseCompartmentLease(db, sessionId, holderId);
|
|
197721
|
+
return;
|
|
197722
|
+
}
|
|
197073
197723
|
const renewal = startPiCompartmentLeaseRenewal(db, sessionId, holderId);
|
|
197074
197724
|
try {
|
|
197075
197725
|
await runPiHistorian({
|
|
@@ -197148,6 +197798,10 @@ function maybeFireHistorian(args) {
|
|
|
197148
197798
|
sessionLog(sessionId, "historian trigger eval: in-flight, skipping");
|
|
197149
197799
|
return;
|
|
197150
197800
|
}
|
|
197801
|
+
if (isWrapupInProgress(db, sessionId)) {
|
|
197802
|
+
sessionLog(sessionId, "historian trigger eval: /ctx-wrapup active, skipping");
|
|
197803
|
+
return;
|
|
197804
|
+
}
|
|
197151
197805
|
let usage;
|
|
197152
197806
|
let usageContextLimit;
|
|
197153
197807
|
try {
|
|
@@ -197290,6 +197944,14 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
197290
197944
|
unregister();
|
|
197291
197945
|
}
|
|
197292
197946
|
}
|
|
197947
|
+
function pendingPiMarkerCoveredByRenderedBoundary(pending, injection) {
|
|
197948
|
+
if (!injection || injection.contentionExhausted)
|
|
197949
|
+
return false;
|
|
197950
|
+
const boundary = injection.renderedBoundary;
|
|
197951
|
+
if (pending.endMessageId === boundary.endMessageId)
|
|
197952
|
+
return true;
|
|
197953
|
+
return boundary.ordinal !== null && pending.ordinal <= boundary.ordinal;
|
|
197954
|
+
}
|
|
197293
197955
|
async function runPipeline(args) {
|
|
197294
197956
|
let executedWorkThisPass = false;
|
|
197295
197957
|
let historyWasConsumedThisPass = false;
|
|
@@ -197303,6 +197965,7 @@ async function runPipeline(args) {
|
|
|
197303
197965
|
let emergency = false;
|
|
197304
197966
|
let autoReclaimDidMutateThisPass = false;
|
|
197305
197967
|
let suppressDeferredHistoryDrain = false;
|
|
197968
|
+
let deferredMaterializationConsumedThisPass = false;
|
|
197306
197969
|
let casLost = false;
|
|
197307
197970
|
const deferredHistoryWasPendingAtPassStart = deferredHistoryRefreshSessions.has(args.sessionId);
|
|
197308
197971
|
if (args.temporalAwareness) {
|
|
@@ -197325,6 +197988,8 @@ async function runPipeline(args) {
|
|
|
197325
197988
|
return findLatestUserMessageIdPi(args.messages, ids)?.messageId ?? null;
|
|
197326
197989
|
})();
|
|
197327
197990
|
const alreadyRanHeuristicsThisTurn = currentTurnId !== null && lastHeuristicsTurnIdBySession.get(args.sessionId) === currentTurnId;
|
|
197991
|
+
const sessionMetaForAvailability = getOrCreateSessionMeta(args.db, args.sessionId);
|
|
197992
|
+
const ctxReduceCallable = !sessionMetaForAvailability.isSubagent;
|
|
197328
197993
|
const canConsumeDeferredLate = args.schedulerDecision === "execute" || args.forceMaterialization === true || args.contextUsage.percentage >= FORCE_MATERIALIZATION_PERCENTAGE;
|
|
197329
197994
|
const deferredMaterializeEligible = canConsumeDeferredLate && deferredMaterializationSessions.has(args.sessionId);
|
|
197330
197995
|
const piHardSignals = args.injection ? (() => {
|
|
@@ -197365,7 +198030,7 @@ async function runPipeline(args) {
|
|
|
197365
198030
|
}
|
|
197366
198031
|
const tTag = performance.now();
|
|
197367
198032
|
const { targets } = tagTranscript(args.sessionId, transcript, args.tagger, args.db, {
|
|
197368
|
-
skipPrefixInjection: !
|
|
198033
|
+
skipPrefixInjection: !ctxReduceCallable,
|
|
197369
198034
|
entryFingerprintByMessageId
|
|
197370
198035
|
});
|
|
197371
198036
|
logTransformTiming(args.sessionId, "tagMessages", tTag);
|
|
@@ -197451,14 +198116,16 @@ async function runPipeline(args) {
|
|
|
197451
198116
|
sessionLog(args.sessionId, `reasoning replay failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
197452
198117
|
}
|
|
197453
198118
|
}
|
|
197454
|
-
|
|
197455
|
-
|
|
197456
|
-
|
|
197457
|
-
|
|
197458
|
-
|
|
198119
|
+
if (args.heuristics?.caveman?.enabled && !args.isSubagent) {
|
|
198120
|
+
try {
|
|
198121
|
+
const tags = getTagsByNumbers(args.db, args.sessionId, targetTagNumbers);
|
|
198122
|
+
const replayed = replayCavemanCompression(args.sessionId, args.db, targets, tags);
|
|
198123
|
+
if (replayed > 0) {
|
|
198124
|
+
sessionLog(args.sessionId, `caveman replay: ${replayed} tags re-compressed from source`);
|
|
198125
|
+
}
|
|
198126
|
+
} catch (err) {
|
|
198127
|
+
sessionLog(args.sessionId, `caveman replay failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
197459
198128
|
}
|
|
197460
|
-
} catch (err) {
|
|
197461
|
-
sessionLog(args.sessionId, `caveman replay failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
197462
198129
|
}
|
|
197463
198130
|
let heuristicsExecuted = false;
|
|
197464
198131
|
let heuristicsResult = null;
|
|
@@ -197481,7 +198148,7 @@ async function runPipeline(args) {
|
|
|
197481
198148
|
currentTotalInputTokens: args.contextUsage.inputTokens,
|
|
197482
198149
|
ceilingTokens: args.emergencyCeilingTokens
|
|
197483
198150
|
} : undefined,
|
|
197484
|
-
caveman: args.heuristics.caveman
|
|
198151
|
+
caveman: args.isSubagent ? undefined : args.heuristics.caveman
|
|
197485
198152
|
}, activeTags, stableIdResolver);
|
|
197486
198153
|
const heuristicMutationCount = heuristicsResult.droppedTools + heuristicsResult.deduplicatedTools + heuristicsResult.droppedInjections + heuristicsResult.droppedStaleReduceCalls + heuristicsResult.mutatedTextTags;
|
|
197487
198154
|
droppedCount += heuristicsResult.droppedTools + heuristicsResult.deduplicatedTools + heuristicsResult.droppedInjections + heuristicsResult.droppedStaleReduceCalls + heuristicsResult.mutatedTextTags;
|
|
@@ -197504,7 +198171,7 @@ async function runPipeline(args) {
|
|
|
197504
198171
|
if (deferredMaterialize && pendingOpsAppliedThisPass) {
|
|
197505
198172
|
const fullPassSucceeded = shouldRunHeuristics ? heuristicsExecuted : true;
|
|
197506
198173
|
if (fullPassSucceeded) {
|
|
197507
|
-
consumeDeferredMaterialization(args.sessionId);
|
|
198174
|
+
deferredMaterializationConsumedThisPass = consumeDeferredMaterialization(args.sessionId);
|
|
197508
198175
|
}
|
|
197509
198176
|
}
|
|
197510
198177
|
if (args.reasoningClearing && shouldRunHeuristics) {
|
|
@@ -197621,7 +198288,7 @@ async function runPipeline(args) {
|
|
|
197621
198288
|
if (args.injection) {
|
|
197622
198289
|
try {
|
|
197623
198290
|
const tInjection = performance.now();
|
|
197624
|
-
injectionResult =
|
|
198291
|
+
injectionResult = injectM0M1PiForRun({
|
|
197625
198292
|
sessionId: args.sessionId,
|
|
197626
198293
|
projectIdentity: args.projectIdentity,
|
|
197627
198294
|
projectDirectory: args.projectDirectory,
|
|
@@ -197653,11 +198320,23 @@ async function runPipeline(args) {
|
|
|
197653
198320
|
forceDiscovery: args.stableIdSchemeCutover === true
|
|
197654
198321
|
});
|
|
197655
198322
|
const deferredHistoryDrainEligible = historyWasConsumedThisPass && materializationSatisfiedThisPass && (deferredHistoryWasPendingAtPassStart || hasPendingMaterializeSignal) && !suppressDeferredHistoryDrain && !casLost;
|
|
198323
|
+
let preserveDeferredMaterializationForMarkerDrain = false;
|
|
197656
198324
|
if (deferredHistoryDrainEligible) {
|
|
197657
198325
|
try {
|
|
197658
198326
|
const pending = getPendingPiCompactionMarkerState(args.db, args.sessionId);
|
|
197659
198327
|
if (!pending) {
|
|
197660
|
-
|
|
198328
|
+
if (injectionResult?.contentionExhausted === true) {
|
|
198329
|
+
suppressDeferredHistoryDrain = true;
|
|
198330
|
+
preserveDeferredMaterializationForMarkerDrain = true;
|
|
198331
|
+
sessionLog(args.sessionId, "Pi deferred-history drain skipped: m[0]/m[1] used a contention fallback; preserving deferred signals");
|
|
198332
|
+
} else {
|
|
198333
|
+
consumeDeferredHistoryRefresh(args.sessionId);
|
|
198334
|
+
}
|
|
198335
|
+
} else if (!pendingPiMarkerCoveredByRenderedBoundary(pending, injectionResult)) {
|
|
198336
|
+
suppressDeferredHistoryDrain = true;
|
|
198337
|
+
preserveDeferredMaterializationForMarkerDrain = true;
|
|
198338
|
+
const boundary = injectionResult?.renderedBoundary;
|
|
198339
|
+
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`);
|
|
197661
198340
|
} else if (!args.appendCompaction || !args.readBranchEntries) {
|
|
197662
198341
|
suppressDeferredHistoryDrain = true;
|
|
197663
198342
|
sessionLog(args.sessionId, "Pi compaction-marker drain skipped: sessionManager appendCompaction/getBranch unavailable; preserving deferred-history signal");
|
|
@@ -197680,6 +198359,9 @@ async function runPipeline(args) {
|
|
|
197680
198359
|
sessionLog(args.sessionId, `Pi compaction-marker drain failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
197681
198360
|
}
|
|
197682
198361
|
}
|
|
198362
|
+
if (preserveDeferredMaterializationForMarkerDrain && deferredMaterializationConsumedThisPass) {
|
|
198363
|
+
signalPiDeferredMaterialization(args.sessionId);
|
|
198364
|
+
}
|
|
197683
198365
|
if (executedWorkThisPass) {
|
|
197684
198366
|
try {
|
|
197685
198367
|
const currentFlag = peekDeferredExecutePending(args.db, args.sessionId);
|
|
@@ -199235,13 +199917,23 @@ function withPublishedCallback(deps) {
|
|
|
199235
199917
|
}
|
|
199236
199918
|
function startLeaseRenewal(deps, holderId) {
|
|
199237
199919
|
return setInterval(() => {
|
|
199238
|
-
|
|
199239
|
-
|
|
199920
|
+
try {
|
|
199921
|
+
if (!renewCompartmentLease(deps.db, deps.sessionId, holderId)) {
|
|
199922
|
+
sessionLog(deps.sessionId, "compartment lease renewal failed; publish will be skipped if holder is stale");
|
|
199923
|
+
}
|
|
199924
|
+
} catch (err) {
|
|
199925
|
+
sessionLog(deps.sessionId, `compartment lease renewal threw; publish will be skipped if holder is stale (${err instanceof Error ? err.message : String(err)})`);
|
|
199240
199926
|
}
|
|
199241
199927
|
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
199242
199928
|
}
|
|
199243
199929
|
async function executeContextRecompWithResult(deps, options = {}) {
|
|
199244
199930
|
const { sessionId } = deps;
|
|
199931
|
+
if (isWrapupInProgress(deps.db, sessionId)) {
|
|
199932
|
+
return {
|
|
199933
|
+
message: "## Magic Recomp — Skipped\n\n/ctx-wrapup is already compacting this session. Wait for it to finish, then try `/ctx-recomp` again.",
|
|
199934
|
+
published: false
|
|
199935
|
+
};
|
|
199936
|
+
}
|
|
199245
199937
|
if (activeRuns.has(sessionId)) {
|
|
199246
199938
|
return {
|
|
199247
199939
|
message: "## Magic Recomp — Skipped\n\nHistorian is already running for this session. Wait for it to finish, then try `/ctx-recomp` again.",
|
|
@@ -199265,7 +199957,7 @@ async function executeContextRecompWithResult(deps, options = {}) {
|
|
|
199265
199957
|
}).catch((err) => {
|
|
199266
199958
|
sessionLog(sessionId, "compartment agent: recomp unhandled rejection:", err);
|
|
199267
199959
|
});
|
|
199268
|
-
activeRuns.set(sessionId, { promise: wrappedPromise, published: false });
|
|
199960
|
+
activeRuns.set(sessionId, { promise: wrappedPromise, published: false, kind: "recomp" });
|
|
199269
199961
|
try {
|
|
199270
199962
|
const message = await promise2;
|
|
199271
199963
|
const published = activeRuns.get(sessionId)?.published === true;
|
|
@@ -199597,6 +200289,14 @@ ${parsed.message}`,
|
|
|
199597
200289
|
});
|
|
199598
200290
|
return;
|
|
199599
200291
|
}
|
|
200292
|
+
if (isWrapupInProgress(deps.db, sessionId)) {
|
|
200293
|
+
sendCtxStatusMessage(pi, {
|
|
200294
|
+
title: "/ctx-recomp",
|
|
200295
|
+
text: "## Magic Recomp\n\n/ctx-wrapup is already compacting this session. Wait for it to finish, then try `/ctx-recomp` again.",
|
|
200296
|
+
level: "warning"
|
|
200297
|
+
});
|
|
200298
|
+
return;
|
|
200299
|
+
}
|
|
199600
200300
|
if (isPiRecompInFlight(sessionId)) {
|
|
199601
200301
|
sendCtxStatusMessage(pi, {
|
|
199602
200302
|
title: "/ctx-recomp",
|
|
@@ -199988,6 +200688,16 @@ No active Pi session is available.`,
|
|
|
199988
200688
|
});
|
|
199989
200689
|
return;
|
|
199990
200690
|
}
|
|
200691
|
+
if (isWrapupInProgress(deps.db, sessionId)) {
|
|
200692
|
+
sendCtxStatusMessage(pi, {
|
|
200693
|
+
title: "/ctx-session-upgrade",
|
|
200694
|
+
text: `## Session Upgrade
|
|
200695
|
+
|
|
200696
|
+
/ctx-wrapup is already compacting this session. Wait for it to finish, then try again.`,
|
|
200697
|
+
level: "warning"
|
|
200698
|
+
});
|
|
200699
|
+
return;
|
|
200700
|
+
}
|
|
199991
200701
|
if (isPiRecompInFlight(sessionId)) {
|
|
199992
200702
|
sendCtxStatusMessage(pi, {
|
|
199993
200703
|
title: "/ctx-session-upgrade",
|
|
@@ -200319,7 +201029,7 @@ function formatThresholdPercent(value) {
|
|
|
200319
201029
|
// package.json
|
|
200320
201030
|
var package_default = {
|
|
200321
201031
|
name: "@cortexkit/pi-magic-context",
|
|
200322
|
-
version: "0.
|
|
201032
|
+
version: "0.31.1",
|
|
200323
201033
|
type: "module",
|
|
200324
201034
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
200325
201035
|
main: "dist/index.js",
|
|
@@ -200585,7 +201295,6 @@ ${safeStringify(tool.parameters)}`);
|
|
|
200585
201295
|
inputTokens,
|
|
200586
201296
|
systemPromptTokens,
|
|
200587
201297
|
compartmentCount: compartments.length,
|
|
200588
|
-
factCount: 0,
|
|
200589
201298
|
memoryCount: safeRead(() => getMemoryCount(deps.db, deps.projectIdentity), 0),
|
|
200590
201299
|
memoryBlockCount,
|
|
200591
201300
|
sessionNoteCount: safeRead(() => getNotes(deps.db, {
|
|
@@ -200861,6 +201570,365 @@ function readHistorianState(db, sessionId, meta3) {
|
|
|
200861
201570
|
};
|
|
200862
201571
|
}
|
|
200863
201572
|
|
|
201573
|
+
// src/commands/ctx-wrapup.ts
|
|
201574
|
+
import * as crypto4 from "node:crypto";
|
|
201575
|
+
var DEFAULT_MESSAGES_TO_KEEP = 20;
|
|
201576
|
+
var LEASE_WAIT_MS = 1000;
|
|
201577
|
+
function parseWrapupArgs(raw) {
|
|
201578
|
+
const trimmed = raw.trim();
|
|
201579
|
+
if (trimmed === "")
|
|
201580
|
+
return { ok: true, messagesToKeep: DEFAULT_MESSAGES_TO_KEEP };
|
|
201581
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
201582
|
+
return {
|
|
201583
|
+
ok: false,
|
|
201584
|
+
message: "Usage: `/ctx-wrapup [messages_to_keep]` where messages_to_keep is a positive integer."
|
|
201585
|
+
};
|
|
201586
|
+
}
|
|
201587
|
+
const messagesToKeep = Number.parseInt(trimmed, 10);
|
|
201588
|
+
if (!Number.isSafeInteger(messagesToKeep) || messagesToKeep <= 0) {
|
|
201589
|
+
return {
|
|
201590
|
+
ok: false,
|
|
201591
|
+
message: "messages_to_keep must be a positive integer."
|
|
201592
|
+
};
|
|
201593
|
+
}
|
|
201594
|
+
return { ok: true, messagesToKeep };
|
|
201595
|
+
}
|
|
201596
|
+
function registerCtxWrapupCommand(pi, deps) {
|
|
201597
|
+
pi.registerCommand("ctx-wrapup", {
|
|
201598
|
+
description: "Compact older Magic Context history while keeping the newest messages raw",
|
|
201599
|
+
handler: async (args, ctx) => {
|
|
201600
|
+
const sessionId = resolveSessionId(ctx);
|
|
201601
|
+
if (!sessionId) {
|
|
201602
|
+
sendCtxStatusMessage(pi, {
|
|
201603
|
+
title: "/ctx-wrapup",
|
|
201604
|
+
text: `## Magic Wrapup
|
|
201605
|
+
|
|
201606
|
+
No active Pi session is available.`,
|
|
201607
|
+
level: "error"
|
|
201608
|
+
});
|
|
201609
|
+
return;
|
|
201610
|
+
}
|
|
201611
|
+
const sessionMeta = getOrCreateSessionMeta(deps.db, sessionId);
|
|
201612
|
+
if (sessionMeta.isSubagent) {
|
|
201613
|
+
sendCtxStatusMessage(pi, {
|
|
201614
|
+
title: "/ctx-wrapup",
|
|
201615
|
+
text: `## Magic Wrapup — Skipped
|
|
201616
|
+
|
|
201617
|
+
/ctx-wrapup is only available in primary sessions.`,
|
|
201618
|
+
level: "warning"
|
|
201619
|
+
});
|
|
201620
|
+
return;
|
|
201621
|
+
}
|
|
201622
|
+
if (!deps.historianModel) {
|
|
201623
|
+
sendCtxStatusMessage(pi, {
|
|
201624
|
+
title: "/ctx-wrapup",
|
|
201625
|
+
text: "## Magic Wrapup\n\n/ctx-wrapup is unavailable because `historian.model` is not configured.",
|
|
201626
|
+
level: "error"
|
|
201627
|
+
});
|
|
201628
|
+
return;
|
|
201629
|
+
}
|
|
201630
|
+
const parsed = parseWrapupArgs(args);
|
|
201631
|
+
if (!parsed.ok) {
|
|
201632
|
+
sendCtxStatusMessage(pi, {
|
|
201633
|
+
title: "/ctx-wrapup",
|
|
201634
|
+
text: `## Magic Wrapup — Invalid Arguments
|
|
201635
|
+
|
|
201636
|
+
${parsed.message}`,
|
|
201637
|
+
level: "error"
|
|
201638
|
+
});
|
|
201639
|
+
return;
|
|
201640
|
+
}
|
|
201641
|
+
const result = await runPiWrapup(pi, deps, ctx, sessionId, parsed.messagesToKeep);
|
|
201642
|
+
sendCtxStatusMessage(pi, {
|
|
201643
|
+
title: "/ctx-wrapup",
|
|
201644
|
+
text: result,
|
|
201645
|
+
level: result.includes("Failed") || result.includes("Partial") ? "error" : "success"
|
|
201646
|
+
});
|
|
201647
|
+
}
|
|
201648
|
+
});
|
|
201649
|
+
}
|
|
201650
|
+
async function runPiWrapup(pi, deps, ctx, sessionId, messagesToKeep) {
|
|
201651
|
+
if (getOrCreateSessionMeta(deps.db, sessionId).isSubagent) {
|
|
201652
|
+
return `## Magic Wrapup — Skipped
|
|
201653
|
+
|
|
201654
|
+
/ctx-wrapup is only available in primary sessions.`;
|
|
201655
|
+
}
|
|
201656
|
+
if (isPiRecompInFlight(sessionId)) {
|
|
201657
|
+
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.";
|
|
201658
|
+
}
|
|
201659
|
+
const provider2 = { readMessages: () => readPiSessionMessages(ctx) };
|
|
201660
|
+
const unregister = setRawMessageProvider(sessionId, provider2);
|
|
201661
|
+
let holderId = "";
|
|
201662
|
+
try {
|
|
201663
|
+
const contextLimit = resolvePiContextLimit(ctx);
|
|
201664
|
+
const modelKey = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
|
|
201665
|
+
const executeThresholdPercentage = resolveExecuteThreshold(deps.executeThresholdPercentage ?? 65, modelKey, 65, {
|
|
201666
|
+
tokensConfig: deps.executeThresholdTokens,
|
|
201667
|
+
contextLimit,
|
|
201668
|
+
sessionId
|
|
201669
|
+
});
|
|
201670
|
+
const initialPlan = resolveWrapupProtectedTailBoundary({
|
|
201671
|
+
db: deps.db,
|
|
201672
|
+
sessionId,
|
|
201673
|
+
mode: "manual-wrapup",
|
|
201674
|
+
contextLimit,
|
|
201675
|
+
executeThresholdPercentage,
|
|
201676
|
+
usage: { percentage: 0, inputTokens: 0 },
|
|
201677
|
+
usageSource: "manual-none",
|
|
201678
|
+
providerShapeVersion: "pi-folded-v1",
|
|
201679
|
+
cacheNamespace: `pi:${sessionId}`,
|
|
201680
|
+
messagesToKeep
|
|
201681
|
+
});
|
|
201682
|
+
if (initialPlan.rawMessagesAboveLastCompartment <= messagesToKeep) {
|
|
201683
|
+
return `## Magic Wrapup
|
|
201684
|
+
|
|
201685
|
+
Nothing to wrap up — only ${initialPlan.rawMessagesAboveLastCompartment} messages above the last compartment.`;
|
|
201686
|
+
}
|
|
201687
|
+
if (!hasRunnableCompartmentWindow(initialPlan.snapshot)) {
|
|
201688
|
+
return `## Magic Wrapup — Partial
|
|
201689
|
+
|
|
201690
|
+
No runnable wrapup boundary is available yet; wrapped up 0 messages into 0 compartments. Run /ctx-wrapup again to continue.`;
|
|
201691
|
+
}
|
|
201692
|
+
holderId = crypto4.randomUUID();
|
|
201693
|
+
const acquired = acquireWrapupInProgress(deps.db, sessionId, {
|
|
201694
|
+
holderId,
|
|
201695
|
+
messagesToKeep,
|
|
201696
|
+
anchorRawMessageCount: initialPlan.anchorRawMessageCount,
|
|
201697
|
+
targetEligibleEndOrdinal: initialPlan.targetEligibleEndOrdinal,
|
|
201698
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(deps.db, sessionId),
|
|
201699
|
+
chunkIndex: 0,
|
|
201700
|
+
expectedChunks: estimateChunks(initialPlan.snapshot.trueRawEligibleTokens, deps.historianChunkTokens)
|
|
201701
|
+
});
|
|
201702
|
+
if (!acquired.ok) {
|
|
201703
|
+
return formatExistingWrapup(acquired.state ?? getWrapupInProgressState(deps.db, sessionId));
|
|
201704
|
+
}
|
|
201705
|
+
let ownershipLost = false;
|
|
201706
|
+
const ownershipLostReason = "another process took over this session's wrapup";
|
|
201707
|
+
const markOwnershipLost = () => {
|
|
201708
|
+
if (ownershipLost)
|
|
201709
|
+
return;
|
|
201710
|
+
ownershipLost = true;
|
|
201711
|
+
};
|
|
201712
|
+
const renewWrapupMarker = (updates) => {
|
|
201713
|
+
const updated = updateWrapupInProgress(deps.db, sessionId, holderId, updates);
|
|
201714
|
+
if (!updated) {
|
|
201715
|
+
markOwnershipLost();
|
|
201716
|
+
return false;
|
|
201717
|
+
}
|
|
201718
|
+
return true;
|
|
201719
|
+
};
|
|
201720
|
+
const renewal = setInterval(() => {
|
|
201721
|
+
try {
|
|
201722
|
+
renewWrapupMarker({
|
|
201723
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(deps.db, sessionId)
|
|
201724
|
+
});
|
|
201725
|
+
} catch (err) {
|
|
201726
|
+
console.warn(`[magic-context][pi] /ctx-wrapup marker renewal failed for ${sessionId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
201727
|
+
}
|
|
201728
|
+
}, 60000);
|
|
201729
|
+
try {
|
|
201730
|
+
sendCtxStatusMessage(pi, {
|
|
201731
|
+
title: "/ctx-wrapup",
|
|
201732
|
+
text: `## Magic Wrapup
|
|
201733
|
+
|
|
201734
|
+
Eligible history is about ${initialPlan.snapshot.trueRawEligibleTokens.toLocaleString()} tokens across approximately ${estimateChunks(initialPlan.snapshot.trueRawEligibleTokens, deps.historianChunkTokens)} historian chunk(s).`,
|
|
201735
|
+
level: "info"
|
|
201736
|
+
});
|
|
201737
|
+
const startEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
201738
|
+
const startCompartmentCount = getCompartments(deps.db, sessionId).length;
|
|
201739
|
+
let chunkIndex = 0;
|
|
201740
|
+
let lastEnd = startEnd;
|
|
201741
|
+
let targetEligibleEndOrdinal = initialPlan.targetEligibleEndOrdinal;
|
|
201742
|
+
let failure = null;
|
|
201743
|
+
for (;; ) {
|
|
201744
|
+
if (ownershipLost) {
|
|
201745
|
+
failure = `${ownershipLostReason}; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.`;
|
|
201746
|
+
break;
|
|
201747
|
+
}
|
|
201748
|
+
if (!renewWrapupMarker({
|
|
201749
|
+
chunkIndex,
|
|
201750
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(deps.db, sessionId)
|
|
201751
|
+
})) {
|
|
201752
|
+
failure = `${ownershipLostReason}; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.`;
|
|
201753
|
+
break;
|
|
201754
|
+
}
|
|
201755
|
+
const plan = resolveWrapupProtectedTailBoundary({
|
|
201756
|
+
db: deps.db,
|
|
201757
|
+
sessionId,
|
|
201758
|
+
mode: "manual-wrapup",
|
|
201759
|
+
contextLimit,
|
|
201760
|
+
executeThresholdPercentage,
|
|
201761
|
+
usage: { percentage: 0, inputTokens: 0 },
|
|
201762
|
+
usageSource: "manual-none",
|
|
201763
|
+
providerShapeVersion: "pi-folded-v1",
|
|
201764
|
+
cacheNamespace: `pi:${sessionId}`,
|
|
201765
|
+
messagesToKeep,
|
|
201766
|
+
anchorRawMessageCount: initialPlan.anchorRawMessageCount
|
|
201767
|
+
});
|
|
201768
|
+
targetEligibleEndOrdinal = plan.targetEligibleEndOrdinal;
|
|
201769
|
+
lastEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
201770
|
+
if (lastEnd + 1 >= targetEligibleEndOrdinal)
|
|
201771
|
+
break;
|
|
201772
|
+
if (!hasRunnableCompartmentWindow(plan.snapshot)) {
|
|
201773
|
+
failure = `No runnable wrapup boundary is available yet; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.`;
|
|
201774
|
+
break;
|
|
201775
|
+
}
|
|
201776
|
+
chunkIndex += 1;
|
|
201777
|
+
if (!renewWrapupMarker({
|
|
201778
|
+
chunkIndex,
|
|
201779
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(deps.db, sessionId),
|
|
201780
|
+
targetEligibleEndOrdinal: plan.targetEligibleEndOrdinal,
|
|
201781
|
+
expectedChunks: Math.max(chunkIndex, estimateChunks(plan.snapshot.trueRawEligibleTokens, deps.historianChunkTokens))
|
|
201782
|
+
})) {
|
|
201783
|
+
failure = `${ownershipLostReason}; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.`;
|
|
201784
|
+
break;
|
|
201785
|
+
}
|
|
201786
|
+
sendCtxStatusMessage(pi, {
|
|
201787
|
+
title: "/ctx-wrapup",
|
|
201788
|
+
text: `## Magic Wrapup
|
|
201789
|
+
|
|
201790
|
+
Chunk ${chunkIndex}: wrapping messages ${plan.snapshot.offset}-${plan.snapshot.eligibleEndOrdinal - 1} (~${plan.snapshot.trueRawEligibleTokens.toLocaleString()} eligible tokens remain).`,
|
|
201791
|
+
level: "info"
|
|
201792
|
+
});
|
|
201793
|
+
const leaseHolder = await acquireCompartmentLeaseEventually(deps.db, sessionId, renewWrapupMarker);
|
|
201794
|
+
if (!leaseHolder) {
|
|
201795
|
+
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.";
|
|
201796
|
+
break;
|
|
201797
|
+
}
|
|
201798
|
+
const leaseRenewal = setInterval(() => {
|
|
201799
|
+
try {
|
|
201800
|
+
renewCompartmentLease(deps.db, sessionId, leaseHolder);
|
|
201801
|
+
} catch (err) {
|
|
201802
|
+
console.warn(`[magic-context][pi] /ctx-wrapup compartment lease renewal failed for ${sessionId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
201803
|
+
}
|
|
201804
|
+
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
201805
|
+
try {
|
|
201806
|
+
const runHistorian = deps.runPiHistorianForWrapup ?? runPiHistorian;
|
|
201807
|
+
await runHistorian({
|
|
201808
|
+
db: deps.db,
|
|
201809
|
+
sessionId,
|
|
201810
|
+
directory: ctx.cwd,
|
|
201811
|
+
provider: provider2,
|
|
201812
|
+
runner: deps.runner,
|
|
201813
|
+
historianModel: deps.historianModel,
|
|
201814
|
+
fallbackModels: deps.historianFallbacks,
|
|
201815
|
+
historianChunkTokens: deps.historianChunkTokens,
|
|
201816
|
+
boundarySnapshot: plan.snapshot,
|
|
201817
|
+
refreshBoundarySnapshot: () => resolveWrapupProtectedTailBoundary({
|
|
201818
|
+
db: deps.db,
|
|
201819
|
+
sessionId,
|
|
201820
|
+
mode: "manual-wrapup",
|
|
201821
|
+
contextLimit,
|
|
201822
|
+
executeThresholdPercentage,
|
|
201823
|
+
usage: { percentage: 0, inputTokens: 0 },
|
|
201824
|
+
usageSource: "manual-none",
|
|
201825
|
+
providerShapeVersion: "pi-folded-v1",
|
|
201826
|
+
cacheNamespace: `pi:${sessionId}`,
|
|
201827
|
+
messagesToKeep,
|
|
201828
|
+
anchorRawMessageCount: initialPlan.anchorRawMessageCount
|
|
201829
|
+
}).snapshot,
|
|
201830
|
+
currentContextLimit: contextLimit,
|
|
201831
|
+
historianTimeoutMs: deps.historianTimeoutMs,
|
|
201832
|
+
thinkingLevel: deps.historianThinkingLevel,
|
|
201833
|
+
memoryEnabled: deps.memoryEnabled,
|
|
201834
|
+
autoPromote: deps.autoPromote,
|
|
201835
|
+
userMemoriesEnabled: deps.userMemoriesEnabled,
|
|
201836
|
+
language: deps.language,
|
|
201837
|
+
compartmentLeaseHolderId: leaseHolder,
|
|
201838
|
+
readBranchEntries: () => readBranchEntries(ctx),
|
|
201839
|
+
notifyIssue: (text) => sendCtxStatusMessage(pi, {
|
|
201840
|
+
title: "/ctx-wrapup",
|
|
201841
|
+
text,
|
|
201842
|
+
level: "warning"
|
|
201843
|
+
}),
|
|
201844
|
+
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
201845
|
+
forceDrainQuota: true,
|
|
201846
|
+
forceKeepLastCompartment: true,
|
|
201847
|
+
onPublished: () => {
|
|
201848
|
+
updateStatusLine(ctx, { db: deps.db, projectIdentity: ctx.cwd });
|
|
201849
|
+
signalPiDeferredHistoryRefresh(sessionId);
|
|
201850
|
+
signalPiDeferredMaterialization(sessionId);
|
|
201851
|
+
}
|
|
201852
|
+
});
|
|
201853
|
+
} finally {
|
|
201854
|
+
clearInterval(leaseRenewal);
|
|
201855
|
+
releaseCompartmentLease(deps.db, sessionId, leaseHolder);
|
|
201856
|
+
}
|
|
201857
|
+
const afterEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
201858
|
+
if (afterEnd <= lastEnd) {
|
|
201859
|
+
failure = `No forward progress after chunk ${chunkIndex}; wrapped up through message ${lastEnd}. Run /ctx-wrapup again to continue.`;
|
|
201860
|
+
break;
|
|
201861
|
+
}
|
|
201862
|
+
lastEnd = afterEnd;
|
|
201863
|
+
}
|
|
201864
|
+
const finalEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
201865
|
+
if (!failure && finalEnd + 1 < targetEligibleEndOrdinal) {
|
|
201866
|
+
failure = `Wrapped up through message ${finalEnd}, but no runnable wrapup boundary remained before target message ${targetEligibleEndOrdinal}. Run /ctx-wrapup again to continue.`;
|
|
201867
|
+
}
|
|
201868
|
+
const finalCompartmentCount = getCompartments(deps.db, sessionId).length;
|
|
201869
|
+
const messagesWrapped = Math.max(0, finalEnd - startEnd);
|
|
201870
|
+
const compartmentsCreated = Math.max(0, finalCompartmentCount - startCompartmentCount);
|
|
201871
|
+
if (failure) {
|
|
201872
|
+
return `## Magic Wrapup — Partial
|
|
201873
|
+
|
|
201874
|
+
Wrapped up ${messagesWrapped} messages into ${compartmentsCreated} compartments; ${failure}`;
|
|
201875
|
+
}
|
|
201876
|
+
try {
|
|
201877
|
+
clearEmergencyRecovery(deps.db, sessionId);
|
|
201878
|
+
} catch {}
|
|
201879
|
+
return `## Magic Wrapup
|
|
201880
|
+
|
|
201881
|
+
Wrapped up ${messagesWrapped} messages into ${compartmentsCreated} compartments. The compacted history is queued and materializes on your next message.`;
|
|
201882
|
+
} finally {
|
|
201883
|
+
clearInterval(renewal);
|
|
201884
|
+
releaseWrapupInProgress(deps.db, sessionId, holderId);
|
|
201885
|
+
}
|
|
201886
|
+
} finally {
|
|
201887
|
+
unregister();
|
|
201888
|
+
}
|
|
201889
|
+
}
|
|
201890
|
+
function resolvePiContextLimit(ctx) {
|
|
201891
|
+
const usage = ctx.getContextUsage?.();
|
|
201892
|
+
if (typeof usage?.contextWindow === "number" && usage.contextWindow > 0) {
|
|
201893
|
+
return usage.contextWindow;
|
|
201894
|
+
}
|
|
201895
|
+
if (typeof ctx.model?.contextWindow === "number" && ctx.model.contextWindow > 0) {
|
|
201896
|
+
return ctx.model.contextWindow;
|
|
201897
|
+
}
|
|
201898
|
+
return 128000;
|
|
201899
|
+
}
|
|
201900
|
+
async function acquireCompartmentLeaseEventually(db, sessionId, renewWrapupMarker) {
|
|
201901
|
+
for (;; ) {
|
|
201902
|
+
const holderId = crypto4.randomUUID();
|
|
201903
|
+
const lease = acquireCompartmentLease(db, sessionId, holderId);
|
|
201904
|
+
if (lease)
|
|
201905
|
+
return holderId;
|
|
201906
|
+
if (!renewWrapupMarker({}))
|
|
201907
|
+
return null;
|
|
201908
|
+
await new Promise((resolve3) => setTimeout(resolve3, LEASE_WAIT_MS));
|
|
201909
|
+
}
|
|
201910
|
+
}
|
|
201911
|
+
function estimateChunks(tokens, chunkTokens) {
|
|
201912
|
+
return Math.max(1, Math.ceil(Math.max(0, tokens) / Math.max(1, chunkTokens)));
|
|
201913
|
+
}
|
|
201914
|
+
function formatExistingWrapup(state) {
|
|
201915
|
+
if (!state) {
|
|
201916
|
+
return `## Magic Wrapup — Skipped
|
|
201917
|
+
|
|
201918
|
+
Another /ctx-wrapup is already compacting this session. Wait for it to finish, then try again.`;
|
|
201919
|
+
}
|
|
201920
|
+
return `## Magic Wrapup — Skipped
|
|
201921
|
+
|
|
201922
|
+
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.`;
|
|
201923
|
+
}
|
|
201924
|
+
function readBranchEntries(ctx) {
|
|
201925
|
+
const getBranch = ctx.sessionManager.getBranch;
|
|
201926
|
+
if (typeof getBranch !== "function")
|
|
201927
|
+
return [];
|
|
201928
|
+
const branch = getBranch.call(ctx.sessionManager);
|
|
201929
|
+
return Array.isArray(branch?.entries) ? branch.entries : [];
|
|
201930
|
+
}
|
|
201931
|
+
|
|
200864
201932
|
// src/pi-pressure.ts
|
|
200865
201933
|
function extractAssistantUsage(message) {
|
|
200866
201934
|
if (!message || typeof message !== "object")
|
|
@@ -206252,14 +207320,17 @@ Sources (omit for a broad search across all):
|
|
|
206252
207320
|
- memory: curated cross-session project knowledge — rules, constraints, conventions.
|
|
206253
207321
|
- 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).
|
|
206254
207322
|
- git_commit: this repository's commit history.
|
|
207323
|
+
- note: parked decisions, follow-ups, and dismissed notes with their recorded text.
|
|
206255
207324
|
|
|
206256
207325
|
Picking sources:
|
|
206257
207326
|
- "when did this change / was this working before" → ["git_commit", "message"]
|
|
206258
207327
|
- "did we discuss this earlier" → ["message"]
|
|
207328
|
+
- "did we decide something about this / leave a follow-up" → ["note"]
|
|
206259
207329
|
- "what's our convention / rule for X" → ["memory"]`;
|
|
206260
207330
|
|
|
206261
207331
|
// src/tools/ctx-search.ts
|
|
206262
207332
|
var DEFAULT_LIMIT = 10;
|
|
207333
|
+
var NOTE_EXPAND_HINT = "Use ctx_expand(start=N-10, end=N) around any note @msg anchor above to read the surrounding conversation context.";
|
|
206263
207334
|
var ParamsSchema5 = exports_typebox.Object({
|
|
206264
207335
|
query: exports_typebox.String({
|
|
206265
207336
|
description: "Search query. Matches against memory content, Primers, git commit messages, and raw user/assistant message text."
|
|
@@ -206271,9 +207342,10 @@ var ParamsSchema5 = exports_typebox.Object({
|
|
|
206271
207342
|
exports_typebox.Literal("memory"),
|
|
206272
207343
|
exports_typebox.Literal("message"),
|
|
206273
207344
|
exports_typebox.Literal("git_commit"),
|
|
206274
|
-
exports_typebox.Literal("primer")
|
|
207345
|
+
exports_typebox.Literal("primer"),
|
|
207346
|
+
exports_typebox.Literal("note")
|
|
206275
207347
|
]), {
|
|
206276
|
-
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.'
|
|
207348
|
+
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.'
|
|
206277
207349
|
}))
|
|
206278
207350
|
});
|
|
206279
207351
|
function normalizeLimit3(limit) {
|
|
@@ -206300,7 +207372,7 @@ function formatAge2(committedAtMs) {
|
|
|
206300
207372
|
const years = Math.floor(days / 365);
|
|
206301
207373
|
return years === 1 ? "1y ago" : `${years}y ago`;
|
|
206302
207374
|
}
|
|
206303
|
-
function formatResult(result, index) {
|
|
207375
|
+
function formatResult(result, index, currentSessionId) {
|
|
206304
207376
|
if (result.source === "memory") {
|
|
206305
207377
|
const source = result.sourceName ? ` source=${result.sourceName}` : "";
|
|
206306
207378
|
return [
|
|
@@ -206321,6 +207393,14 @@ function formatResult(result, index) {
|
|
|
206321
207393
|
`[${index}] [primer] score=${result.score.toFixed(2)} id=${result.primerId} support=${result.support} match=${result.matchType}`,
|
|
206322
207394
|
result.content
|
|
206323
207395
|
].join(`
|
|
207396
|
+
`);
|
|
207397
|
+
}
|
|
207398
|
+
if (result.source === "note") {
|
|
207399
|
+
const anchor = result.anchorOrdinal !== null && result.sourceSessionId === currentSessionId ? ` @msg ${result.anchorOrdinal}` : "";
|
|
207400
|
+
return [
|
|
207401
|
+
`[${index}] [note] score=${result.score.toFixed(2)} id=#${result.noteId} status=${result.status} ${formatAge2(result.createdAt)}${anchor}`,
|
|
207402
|
+
result.content
|
|
207403
|
+
].join(`
|
|
206324
207404
|
`);
|
|
206325
207405
|
}
|
|
206326
207406
|
if (result.source === "compartment") {
|
|
@@ -206338,14 +207418,17 @@ function formatResult(result, index) {
|
|
|
206338
207418
|
].join(`
|
|
206339
207419
|
`);
|
|
206340
207420
|
}
|
|
206341
|
-
function formatSearchResults(query, results) {
|
|
207421
|
+
function formatSearchResults(query, results, currentSessionId) {
|
|
206342
207422
|
if (results.length === 0) {
|
|
206343
|
-
return `No results found for "${query}" across memories, primers, git commits, or message history.`;
|
|
207423
|
+
return `No results found for "${query}" across notes, memories, primers, git commits, or message history.`;
|
|
206344
207424
|
}
|
|
206345
|
-
const bodyParts = results.map((result, index) => formatResult(result, index + 1));
|
|
207425
|
+
const bodyParts = results.map((result, index) => formatResult(result, index + 1, currentSessionId));
|
|
206346
207426
|
if (results.some((result) => result.source === "message" || result.source === "compartment")) {
|
|
206347
207427
|
bodyParts.push("Use ctx_expand(start, end) with the range from any message result above to read the full conversation context.");
|
|
206348
207428
|
}
|
|
207429
|
+
if (results.some((result) => result.source === "note" && result.anchorOrdinal !== null && result.sourceSessionId === currentSessionId)) {
|
|
207430
|
+
bodyParts.push(NOTE_EXPAND_HINT);
|
|
207431
|
+
}
|
|
206349
207432
|
const body = bodyParts.join(`
|
|
206350
207433
|
|
|
206351
207434
|
`);
|
|
@@ -206394,7 +207477,12 @@ function createCtxSearchTool(deps) {
|
|
|
206394
207477
|
explicitSearch: true
|
|
206395
207478
|
});
|
|
206396
207479
|
return {
|
|
206397
|
-
content: [
|
|
207480
|
+
content: [
|
|
207481
|
+
{
|
|
207482
|
+
type: "text",
|
|
207483
|
+
text: formatSearchResults(query, results, sessionId)
|
|
207484
|
+
}
|
|
207485
|
+
],
|
|
206398
207486
|
details: undefined
|
|
206399
207487
|
};
|
|
206400
207488
|
}
|
|
@@ -206491,7 +207579,7 @@ function registerMagicContextTools(pi, opts) {
|
|
|
206491
207579
|
pi.registerTool(createCtxExpandTool({ db: opts.db }));
|
|
206492
207580
|
}
|
|
206493
207581
|
pi.registerTool(createTodowriteTool());
|
|
206494
|
-
if (opts.
|
|
207582
|
+
if (!opts.sessionScopedToolsDisabled) {
|
|
206495
207583
|
pi.registerTool(createCtxReduceTool({
|
|
206496
207584
|
db: opts.db,
|
|
206497
207585
|
protectedTags: opts.protectedTags ?? 20
|
|
@@ -206503,7 +207591,7 @@ function registerMagicContextTools(pi, opts) {
|
|
|
206503
207591
|
var PREFIX = "[magic-context][pi]";
|
|
206504
207592
|
function resolveCurrentProject(ctx) {
|
|
206505
207593
|
const projectDir = ctx.cwd;
|
|
206506
|
-
const projectIdentity =
|
|
207594
|
+
const projectIdentity = resolveProjectIdentityOrFallback(projectDir);
|
|
206507
207595
|
return { projectDir, projectIdentity };
|
|
206508
207596
|
}
|
|
206509
207597
|
function persistPiMessageEndModelMeta(args) {
|
|
@@ -206705,13 +207793,13 @@ async function src_default2(pi) {
|
|
|
206705
207793
|
})();
|
|
206706
207794
|
}, 0);
|
|
206707
207795
|
const projectDir = process.cwd();
|
|
206708
|
-
const projectIdentity =
|
|
207796
|
+
const projectIdentity = resolveProjectIdentityOrFallback(projectDir);
|
|
206709
207797
|
const seenDreamerProjectIdentities = new Set([projectIdentity]);
|
|
206710
207798
|
try {
|
|
206711
207799
|
const pendingPiMarkerSessions = getSessionsWithPendingPiMarker(db);
|
|
206712
207800
|
for (const sid of pendingPiMarkerSessions) {
|
|
206713
207801
|
signalPiDeferredHistoryRefresh(sid);
|
|
206714
|
-
|
|
207802
|
+
signalPiDeferredMaterialization(sid);
|
|
206715
207803
|
}
|
|
206716
207804
|
if (pendingPiMarkerSessions.length > 0) {
|
|
206717
207805
|
log(`${PREFIX} rehydrated ${pendingPiMarkerSessions.length} Pi deferred compaction marker session(s)`);
|
|
@@ -206749,11 +207837,10 @@ async function src_default2(pi) {
|
|
|
206749
207837
|
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
206750
207838
|
allowDreamerActions: false,
|
|
206751
207839
|
memoryToolEnabled: true,
|
|
206752
|
-
ctxReduceEnabled: config2.ctx_reduce_enabled === true,
|
|
206753
207840
|
protectedTags: config2.protected_tags ?? 20,
|
|
206754
207841
|
dreamerEnabled: isDreamerRunnable(config2)
|
|
206755
207842
|
});
|
|
206756
|
-
info(
|
|
207843
|
+
info("registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand, ctx_reduce");
|
|
206757
207844
|
const historianConfig = resolveHistorianFromConfig(config2);
|
|
206758
207845
|
if (historianConfig) {
|
|
206759
207846
|
historianConfig.onStatusChange = (ctx) => {
|
|
@@ -206767,11 +207854,10 @@ async function src_default2(pi) {
|
|
|
206767
207854
|
const contextOptionsByDir = new Map;
|
|
206768
207855
|
const buildContextOptions = (cfg, hist, auto) => ({
|
|
206769
207856
|
db: database,
|
|
206770
|
-
ctxReduceEnabled: cfg.ctx_reduce_enabled,
|
|
206771
207857
|
smartDrops: cfg.smart_drops === true,
|
|
206772
207858
|
protectedTags: cfg.protected_tags ?? 20,
|
|
206773
207859
|
heuristics: {
|
|
206774
|
-
caveman: cfg.
|
|
207860
|
+
caveman: cfg.caveman_text_compression ? {
|
|
206775
207861
|
enabled: cfg.caveman_text_compression.enabled,
|
|
206776
207862
|
minChars: cfg.caveman_text_compression.min_chars
|
|
206777
207863
|
} : undefined,
|
|
@@ -206866,6 +207952,22 @@ async function src_default2(pi) {
|
|
|
206866
207952
|
autoPromote: config2.memory.auto_promote
|
|
206867
207953
|
});
|
|
206868
207954
|
info("registered /ctx-recomp");
|
|
207955
|
+
registerCtxWrapupCommand(pi, {
|
|
207956
|
+
db,
|
|
207957
|
+
runner: new PiSubagentRunner,
|
|
207958
|
+
historianModel: historianConfig?.model,
|
|
207959
|
+
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(historianConfig?.model)),
|
|
207960
|
+
historianFallbacks: historianConfig?.fallbackModels,
|
|
207961
|
+
historianTimeoutMs: config2.historian_timeout_ms,
|
|
207962
|
+
historianThinkingLevel: historianConfig?.thinkingLevel,
|
|
207963
|
+
language: config2.language,
|
|
207964
|
+
memoryEnabled: config2.memory.enabled,
|
|
207965
|
+
autoPromote: config2.memory.auto_promote,
|
|
207966
|
+
userMemoriesEnabled: userMemoryCollectionEnabled(config2.dreamer),
|
|
207967
|
+
executeThresholdPercentage: config2.execute_threshold_percentage,
|
|
207968
|
+
executeThresholdTokens: config2.execute_threshold_tokens
|
|
207969
|
+
});
|
|
207970
|
+
info("registered /ctx-wrapup");
|
|
206869
207971
|
registerCtxSessionUpgradeCommand(pi, {
|
|
206870
207972
|
db,
|
|
206871
207973
|
runner: new PiSubagentRunner,
|
|
@@ -207015,10 +208117,10 @@ async function src_default2(pi) {
|
|
|
207015
208117
|
memoryEnabled: effectiveConfig.memory.enabled,
|
|
207016
208118
|
includeGuidance: true,
|
|
207017
208119
|
protectedTags: effectiveConfig.protected_tags,
|
|
207018
|
-
|
|
208120
|
+
ctxReduceCallable: true,
|
|
207019
208121
|
dreamerEnabled: effectiveDreamerRunnable,
|
|
207020
208122
|
temporalAwarenessEnabled: effectiveConfig.temporal_awareness ?? false,
|
|
207021
|
-
cavemanTextCompressionEnabled: effectiveConfig.
|
|
208123
|
+
cavemanTextCompressionEnabled: effectiveConfig.caveman_text_compression?.enabled === true,
|
|
207022
208124
|
language: effectiveConfig.language,
|
|
207023
208125
|
userMemoriesEnabled: userMemoryCollectionEnabled(effectiveConfig.dreamer),
|
|
207024
208126
|
isCacheBusting,
|