@cortexkit/opencode-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/agents/magic-context-prompt.d.ts +1 -1
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +5 -10
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/features/builtin-commands/commands.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity.d.ts +18 -5
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +13 -2
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +26 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +1 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage-schema-helpers.d.ts +1 -1
- package/dist/features/magic-context/storage-schema-helpers.d.ts.map +1 -1
- package/dist/features/magic-context/storage-v22-backfill-failures.d.ts +3 -1
- package/dist/features/magic-context/storage-v22-backfill-failures.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -1
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
- package/dist/features/magic-context/v22-deferred-backfill.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-hint.d.ts.map +1 -1
- package/dist/hooks/magic-context/caveman-cleanup.d.ts +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +11 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +10 -2
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts +2 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +11 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +2 -3
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts +0 -2
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +0 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +2 -0
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts +16 -1
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/recomp-orchestrator.d.ts +1 -1
- package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +2 -3
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +3 -4
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +3 -3
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +8 -12
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/wrapup-orchestrator.d.ts +13 -0
- package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -0
- package/dist/index.js +1324 -171
- package/dist/plugin/hooks/create-session-hooks.d.ts +0 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/shared/announcement.d.ts +1 -1
- package/dist/shared/announcement.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +1 -2
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/tag-transcript.d.ts +3 -4
- package/dist/shared/tag-transcript.d.ts.map +1 -1
- package/dist/tools/ctx-search/constants.d.ts +1 -1
- package/dist/tools/ctx-search/constants.d.ts.map +1 -1
- package/dist/tools/ctx-search/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/types.d.ts +1 -1
- package/dist/tools/ctx-search/types.d.ts.map +1 -1
- package/dist/tui/data/context-db.d.ts.map +1 -1
- package/package.json +19 -5
- package/src/shared/announcement.ts +5 -4
- package/src/shared/rpc-types.ts +1 -2
- package/src/shared/tag-transcript.ts +3 -4
- package/src/tui/data/context-db.ts +0 -1
- package/src/tui/index.tsx +9 -1
- package/src/tui/slots/sidebar-content.tsx +6 -7
package/dist/index.js
CHANGED
|
@@ -15372,7 +15372,6 @@ var init_magic_context = __esm(() => {
|
|
|
15372
15372
|
enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
|
|
15373
15373
|
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."),
|
|
15374
15374
|
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."),
|
|
15375
|
-
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)"),
|
|
15376
15375
|
historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
|
|
15377
15376
|
dreamer: DreamerConfigSchema.optional().describe("Dreamer agent + scheduling configuration (model, fallback_models, disable, schedule, tasks, etc.)"),
|
|
15378
15377
|
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" })'),
|
|
@@ -15411,9 +15410,9 @@ var init_magic_context = __esm(() => {
|
|
|
15411
15410
|
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."),
|
|
15412
15411
|
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."),
|
|
15413
15412
|
caveman_text_compression: exports_external.object({
|
|
15414
|
-
enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text.
|
|
15413
|
+
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%)."),
|
|
15415
15414
|
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.")
|
|
15416
|
-
}).default({ enabled: false, min_chars: 500 }).describe("Age-tier caveman compression for long user/assistant text parts.
|
|
15415
|
+
}).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)."),
|
|
15417
15416
|
memory: exports_external.object({
|
|
15418
15417
|
enabled: exports_external.boolean().default(true).describe("Enable cross-session memory (default: true)"),
|
|
15419
15418
|
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)"),
|
|
@@ -15783,7 +15782,7 @@ var init_compaction_marker = __esm(async () => {
|
|
|
15783
15782
|
// src/features/magic-context/memory/project-identity.ts
|
|
15784
15783
|
import { execFileSync } from "node:child_process";
|
|
15785
15784
|
import { createHash } from "node:crypto";
|
|
15786
|
-
import { statSync as statSync2 } from "node:fs";
|
|
15785
|
+
import { existsSync as existsSync8, realpathSync, statSync as statSync2 } from "node:fs";
|
|
15787
15786
|
import path3 from "node:path";
|
|
15788
15787
|
function asError(error51) {
|
|
15789
15788
|
return error51 instanceof Error ? error51 : undefined;
|
|
@@ -15860,6 +15859,9 @@ function classifyGitError(error51, rawDirectory) {
|
|
|
15860
15859
|
return new ProjectIdentityError("permission_denied", rawDirectory, "Permission denied while spawning git", asError(error51));
|
|
15861
15860
|
}
|
|
15862
15861
|
const stderr = getErrorStderr(error51).toLowerCase();
|
|
15862
|
+
if (stderr.includes("detected dubious ownership")) {
|
|
15863
|
+
return new ProjectIdentityError("dubious_ownership", rawDirectory, "git refused to read the repository because it detected dubious ownership", asError(error51));
|
|
15864
|
+
}
|
|
15863
15865
|
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")) {
|
|
15864
15866
|
return new ProjectIdentityError("not_git_repo", rawDirectory, "Directory has no git root commit; caller may use directory fallback", asError(error51));
|
|
15865
15867
|
}
|
|
@@ -15872,9 +15874,12 @@ function resolveProjectIdentityStrict(directory) {
|
|
|
15872
15874
|
return cached2;
|
|
15873
15875
|
}
|
|
15874
15876
|
assertDirectoryUsable(canonical, directory);
|
|
15877
|
+
if (!hasGitDir(canonical)) {
|
|
15878
|
+
throw new ProjectIdentityError("not_git_repo", directory, "Directory has no git metadata; caller may use directory fallback");
|
|
15879
|
+
}
|
|
15875
15880
|
let output;
|
|
15876
15881
|
try {
|
|
15877
|
-
output =
|
|
15882
|
+
output = execFileSyncForIdentity("git", ["rev-list", "--max-parents=0", "HEAD"], {
|
|
15878
15883
|
cwd: canonical,
|
|
15879
15884
|
encoding: "utf8",
|
|
15880
15885
|
env: { ...process.env, LC_ALL: "C", LANG: "C" },
|
|
@@ -15892,10 +15897,82 @@ function resolveProjectIdentityStrict(directory) {
|
|
|
15892
15897
|
}
|
|
15893
15898
|
const identity = `git:${rootCommit}`;
|
|
15894
15899
|
identityCache.set(canonical, identity);
|
|
15900
|
+
lastKnownGitIdentityCache.set(canonical, identity);
|
|
15901
|
+
transientFailureCooldown.delete(canonical);
|
|
15902
|
+
dubiousOwnershipFallbackDirectories.delete(canonical);
|
|
15903
|
+
transientGitIdentityReuseLoggedDirectories.delete(canonical);
|
|
15895
15904
|
return identity;
|
|
15896
15905
|
}
|
|
15897
15906
|
function shouldUseDirectoryFallback(error51) {
|
|
15898
|
-
return error51.errorClass
|
|
15907
|
+
return error51.errorClass !== "permission_denied";
|
|
15908
|
+
}
|
|
15909
|
+
function getActiveCooldown(canonical) {
|
|
15910
|
+
const until = transientFailureCooldown.get(canonical);
|
|
15911
|
+
if (until === undefined)
|
|
15912
|
+
return;
|
|
15913
|
+
if (nowMs() < until)
|
|
15914
|
+
return until;
|
|
15915
|
+
transientFailureCooldown.delete(canonical);
|
|
15916
|
+
return;
|
|
15917
|
+
}
|
|
15918
|
+
function lastKnownGitIdentity(canonical) {
|
|
15919
|
+
return lastKnownGitIdentityCache.get(canonical) ?? identityCache.get(canonical);
|
|
15920
|
+
}
|
|
15921
|
+
function nearestLastKnownGitIdentity(canonical) {
|
|
15922
|
+
const visited = new Set;
|
|
15923
|
+
const walk = (start) => {
|
|
15924
|
+
let current = start;
|
|
15925
|
+
while (!visited.has(current)) {
|
|
15926
|
+
visited.add(current);
|
|
15927
|
+
const cached2 = lastKnownGitIdentity(current);
|
|
15928
|
+
if (cached2 !== undefined)
|
|
15929
|
+
return { identity: cached2, source: current };
|
|
15930
|
+
const parent = path3.dirname(current);
|
|
15931
|
+
if (parent === current)
|
|
15932
|
+
break;
|
|
15933
|
+
current = parent;
|
|
15934
|
+
}
|
|
15935
|
+
return;
|
|
15936
|
+
};
|
|
15937
|
+
const exactOrAncestor = walk(canonical);
|
|
15938
|
+
if (exactOrAncestor)
|
|
15939
|
+
return exactOrAncestor;
|
|
15940
|
+
try {
|
|
15941
|
+
const realCanonical = realpathSync.native(canonical);
|
|
15942
|
+
if (realCanonical !== canonical)
|
|
15943
|
+
return walk(realCanonical);
|
|
15944
|
+
} catch {}
|
|
15945
|
+
return;
|
|
15946
|
+
}
|
|
15947
|
+
function reuseLastKnownGitIdentity(canonical) {
|
|
15948
|
+
const cached2 = nearestLastKnownGitIdentity(canonical);
|
|
15949
|
+
if (cached2 === undefined)
|
|
15950
|
+
return;
|
|
15951
|
+
if (!transientGitIdentityReuseLoggedDirectories.has(canonical)) {
|
|
15952
|
+
transientGitIdentityReuseLoggedDirectories.add(canonical);
|
|
15953
|
+
const sourceNote = cached2.source === canonical ? "" : ` from ancestor ${cached2.source}`;
|
|
15954
|
+
log(`[magic-context] git identity resolution is temporarily unavailable for ${canonical}; reusing the last successful project identity${sourceNote} to avoid splitting project-scoped memory`);
|
|
15955
|
+
}
|
|
15956
|
+
return cached2.identity;
|
|
15957
|
+
}
|
|
15958
|
+
function formatDubiousOwnershipWarning(canonical) {
|
|
15959
|
+
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}`;
|
|
15960
|
+
}
|
|
15961
|
+
function recordDubiousOwnershipFallback(canonical) {
|
|
15962
|
+
dubiousOwnershipFallbackDirectories.add(canonical);
|
|
15963
|
+
if (dubiousOwnershipLoggedDirectories.has(canonical))
|
|
15964
|
+
return;
|
|
15965
|
+
dubiousOwnershipLoggedDirectories.add(canonical);
|
|
15966
|
+
log(`[magic-context] ${formatDubiousOwnershipWarning(canonical)}`);
|
|
15967
|
+
}
|
|
15968
|
+
function takeDubiousOwnershipProjectIdentityWarning(directory) {
|
|
15969
|
+
const canonical = path3.resolve(directory);
|
|
15970
|
+
if (!dubiousOwnershipFallbackDirectories.has(canonical))
|
|
15971
|
+
return null;
|
|
15972
|
+
if (dubiousOwnershipWarnedDirectories.has(canonical))
|
|
15973
|
+
return null;
|
|
15974
|
+
dubiousOwnershipWarnedDirectories.add(canonical);
|
|
15975
|
+
return formatDubiousOwnershipWarning(canonical);
|
|
15899
15976
|
}
|
|
15900
15977
|
function resolveProjectIdentity(directory) {
|
|
15901
15978
|
const canonical = path3.resolve(directory);
|
|
@@ -15906,27 +15983,74 @@ function resolveProjectIdentity(directory) {
|
|
|
15906
15983
|
}
|
|
15907
15984
|
directoryFallbackCache.delete(canonical);
|
|
15908
15985
|
}
|
|
15986
|
+
if (getActiveCooldown(canonical) !== undefined) {
|
|
15987
|
+
if (hasGitDir(canonical)) {
|
|
15988
|
+
const cachedGitIdentity = reuseLastKnownGitIdentity(canonical);
|
|
15989
|
+
if (cachedGitIdentity !== undefined) {
|
|
15990
|
+
return cachedGitIdentity;
|
|
15991
|
+
}
|
|
15992
|
+
}
|
|
15993
|
+
return directoryFallback(canonical);
|
|
15994
|
+
}
|
|
15909
15995
|
try {
|
|
15910
15996
|
return resolveProjectIdentityStrict(directory);
|
|
15911
15997
|
} catch (error51) {
|
|
15912
15998
|
if (error51 instanceof ProjectIdentityError && shouldUseDirectoryFallback(error51)) {
|
|
15913
15999
|
const fallback = directoryFallback(canonical);
|
|
15914
|
-
|
|
16000
|
+
const hasGitMetadata = hasGitDir(canonical);
|
|
16001
|
+
if (!hasGitMetadata) {
|
|
15915
16002
|
directoryFallbackCache.set(canonical, fallback);
|
|
16003
|
+
transientFailureCooldown.delete(canonical);
|
|
16004
|
+
} else {
|
|
16005
|
+
transientFailureCooldown.set(canonical, nowMs() + TRANSIENT_FAILURE_COOLDOWN_MS);
|
|
16006
|
+
const cachedGitIdentity = reuseLastKnownGitIdentity(canonical);
|
|
16007
|
+
if (cachedGitIdentity !== undefined) {
|
|
16008
|
+
return cachedGitIdentity;
|
|
16009
|
+
}
|
|
16010
|
+
}
|
|
16011
|
+
if (error51.errorClass === "dubious_ownership") {
|
|
16012
|
+
recordDubiousOwnershipFallback(canonical);
|
|
15916
16013
|
}
|
|
15917
16014
|
return fallback;
|
|
15918
16015
|
}
|
|
15919
16016
|
throw error51;
|
|
15920
16017
|
}
|
|
15921
16018
|
}
|
|
15922
|
-
function
|
|
16019
|
+
function resolveProjectIdentityOrFallback(directory) {
|
|
15923
16020
|
try {
|
|
15924
|
-
|
|
16021
|
+
return resolveProjectIdentity(directory);
|
|
16022
|
+
} catch (error51) {
|
|
16023
|
+
const canonical = path3.resolve(directory);
|
|
16024
|
+
const fallback = directoryFallback(canonical);
|
|
16025
|
+
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
16026
|
+
log(`[magic-context] project identity resolution failed for ${canonical}; using directory fallback ${fallback}: ${message}`);
|
|
16027
|
+
return fallback;
|
|
16028
|
+
}
|
|
16029
|
+
}
|
|
16030
|
+
function hasGitDir(canonical) {
|
|
16031
|
+
if (hasGitDirInAncestorChain(canonical)) {
|
|
15925
16032
|
return true;
|
|
16033
|
+
}
|
|
16034
|
+
try {
|
|
16035
|
+
const realCanonical = realpathSync.native(canonical);
|
|
16036
|
+
return realCanonical !== canonical && hasGitDirInAncestorChain(realCanonical);
|
|
15926
16037
|
} catch {
|
|
15927
16038
|
return false;
|
|
15928
16039
|
}
|
|
15929
16040
|
}
|
|
16041
|
+
function hasGitDirInAncestorChain(startDirectory) {
|
|
16042
|
+
let current = startDirectory;
|
|
16043
|
+
while (true) {
|
|
16044
|
+
if (existsSync8(path3.join(current, ".git"))) {
|
|
16045
|
+
return true;
|
|
16046
|
+
}
|
|
16047
|
+
const parent = path3.dirname(current);
|
|
16048
|
+
if (parent === current) {
|
|
16049
|
+
return false;
|
|
16050
|
+
}
|
|
16051
|
+
current = parent;
|
|
16052
|
+
}
|
|
16053
|
+
}
|
|
15930
16054
|
function normalizeStoredProjectPath(rawOrStored) {
|
|
15931
16055
|
if (rawOrStored.startsWith("git:") || rawOrStored.startsWith("dir:")) {
|
|
15932
16056
|
return rawOrStored;
|
|
@@ -15940,10 +16064,19 @@ function normalizeStoredProjectPath(rawOrStored) {
|
|
|
15940
16064
|
function storedPathBelongsToIdentity(storedProjectPath, projectIdentity) {
|
|
15941
16065
|
return storedProjectPath === projectIdentity || normalizeStoredProjectPath(storedProjectPath) === projectIdentity;
|
|
15942
16066
|
}
|
|
15943
|
-
var GIT_TIMEOUT_MS = 5000, identityCache, directoryFallbackCache, ProjectIdentityError;
|
|
16067
|
+
var GIT_TIMEOUT_MS = 5000, TRANSIENT_FAILURE_COOLDOWN_MS, identityCache, lastKnownGitIdentityCache, directoryFallbackCache, transientFailureCooldown, dubiousOwnershipFallbackDirectories, dubiousOwnershipLoggedDirectories, dubiousOwnershipWarnedDirectories, transientGitIdentityReuseLoggedDirectories, execFileSyncForIdentity, nowMs = () => Date.now(), ProjectIdentityError;
|
|
15944
16068
|
var init_project_identity = __esm(() => {
|
|
16069
|
+
init_logger();
|
|
16070
|
+
TRANSIENT_FAILURE_COOLDOWN_MS = 5 * 60 * 1000;
|
|
15945
16071
|
identityCache = new Map;
|
|
16072
|
+
lastKnownGitIdentityCache = new Map;
|
|
15946
16073
|
directoryFallbackCache = new Map;
|
|
16074
|
+
transientFailureCooldown = new Map;
|
|
16075
|
+
dubiousOwnershipFallbackDirectories = new Set;
|
|
16076
|
+
dubiousOwnershipLoggedDirectories = new Set;
|
|
16077
|
+
dubiousOwnershipWarnedDirectories = new Set;
|
|
16078
|
+
transientGitIdentityReuseLoggedDirectories = new Set;
|
|
16079
|
+
execFileSyncForIdentity = execFileSync;
|
|
15947
16080
|
ProjectIdentityError = class ProjectIdentityError extends Error {
|
|
15948
16081
|
errorClass;
|
|
15949
16082
|
rawDirectory;
|
|
@@ -17144,13 +17277,13 @@ function removeSystemReminders(text) {
|
|
|
17144
17277
|
var SYSTEM_DIRECTIVE_PREFIX = "[SYSTEM DIRECTIVE: MAGIC-CONTEXT";
|
|
17145
17278
|
|
|
17146
17279
|
// src/hooks/magic-context/read-session-db.ts
|
|
17147
|
-
import { existsSync as
|
|
17280
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
17148
17281
|
import { join as join4 } from "node:path";
|
|
17149
17282
|
function getOpenCodeDbPath2() {
|
|
17150
17283
|
return join4(getDataDir(), "opencode", "opencode.db");
|
|
17151
17284
|
}
|
|
17152
17285
|
function openCodeDbExists() {
|
|
17153
|
-
return
|
|
17286
|
+
return existsSync10(getOpenCodeDbPath2());
|
|
17154
17287
|
}
|
|
17155
17288
|
function closeCachedReadOnlyDb() {
|
|
17156
17289
|
if (!cachedReadOnlyDb) {
|
|
@@ -152764,6 +152897,15 @@ var init_migrations = __esm(() => {
|
|
|
152764
152897
|
);
|
|
152765
152898
|
`);
|
|
152766
152899
|
}
|
|
152900
|
+
},
|
|
152901
|
+
{
|
|
152902
|
+
version: 50,
|
|
152903
|
+
description: "add durable ctx-wrapup session marker",
|
|
152904
|
+
up(db) {
|
|
152905
|
+
if (tableExists2(db, "session_meta")) {
|
|
152906
|
+
ensureColumn(db, "session_meta", "wrapup_in_progress_state", "TEXT");
|
|
152907
|
+
}
|
|
152908
|
+
}
|
|
152767
152909
|
}
|
|
152768
152910
|
];
|
|
152769
152911
|
LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -153010,7 +153152,7 @@ var init_tool_definition_tokens = __esm(() => {
|
|
|
153010
153152
|
});
|
|
153011
153153
|
|
|
153012
153154
|
// src/features/magic-context/tool-owner-backfill.ts
|
|
153013
|
-
import { existsSync as
|
|
153155
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
153014
153156
|
import { join as join5 } from "node:path";
|
|
153015
153157
|
function resolveOpencodeDbPath() {
|
|
153016
153158
|
return join5(getDataDir(), "opencode", "opencode.db");
|
|
@@ -153048,7 +153190,7 @@ function runToolOwnerBackfill(db) {
|
|
|
153048
153190
|
return result;
|
|
153049
153191
|
}
|
|
153050
153192
|
const opencodeDbPath = resolveOpencodeDbPath();
|
|
153051
|
-
if (!
|
|
153193
|
+
if (!existsSync11(opencodeDbPath)) {
|
|
153052
153194
|
log(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
|
|
153053
153195
|
markAllUnbackfilledSessionsSkipped(db);
|
|
153054
153196
|
result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
|
|
@@ -153272,7 +153414,7 @@ var init_tool_owner_backfill = __esm(() => {
|
|
|
153272
153414
|
});
|
|
153273
153415
|
|
|
153274
153416
|
// src/features/magic-context/storage-db.ts
|
|
153275
|
-
import { chmodSync, copyFileSync, cpSync, existsSync as
|
|
153417
|
+
import { chmodSync, copyFileSync, cpSync, existsSync as existsSync12, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
|
|
153276
153418
|
import { dirname as dirname4, join as join6 } from "node:path";
|
|
153277
153419
|
function getSchemaFenceRejection() {
|
|
153278
153420
|
return lastSchemaFenceRejection;
|
|
@@ -153292,7 +153434,7 @@ function restrictDatabaseFilePermissions(dbPath) {
|
|
|
153292
153434
|
return;
|
|
153293
153435
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
153294
153436
|
const file2 = `${dbPath}${suffix}`;
|
|
153295
|
-
if (!
|
|
153437
|
+
if (!existsSync12(file2))
|
|
153296
153438
|
continue;
|
|
153297
153439
|
try {
|
|
153298
153440
|
chmodSync(file2, 384);
|
|
@@ -153318,11 +153460,11 @@ function getDatabasePath(db) {
|
|
|
153318
153460
|
return pathByDatabase.get(db) ?? null;
|
|
153319
153461
|
}
|
|
153320
153462
|
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
153321
|
-
if (
|
|
153463
|
+
if (existsSync12(targetDbPath))
|
|
153322
153464
|
return;
|
|
153323
153465
|
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
153324
153466
|
const legacyDbPath = join6(legacyDir, "context.db");
|
|
153325
|
-
if (!
|
|
153467
|
+
if (!existsSync12(legacyDbPath))
|
|
153326
153468
|
return;
|
|
153327
153469
|
log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
|
|
153328
153470
|
ensureSecureStorageDir(targetDbDir);
|
|
@@ -153339,7 +153481,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
153339
153481
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
153340
153482
|
const src = `${legacyDbPath}${suffix}`;
|
|
153341
153483
|
const dst = join6(targetDbDir, `context.db${suffix}`);
|
|
153342
|
-
if (
|
|
153484
|
+
if (existsSync12(src)) {
|
|
153343
153485
|
try {
|
|
153344
153486
|
copyFileSync(src, dst);
|
|
153345
153487
|
} catch (error51) {
|
|
@@ -153349,7 +153491,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
153349
153491
|
}
|
|
153350
153492
|
const legacyModelsDir = join6(legacyDir, "models");
|
|
153351
153493
|
const targetModelsDir = join6(targetDbDir, "models");
|
|
153352
|
-
if (
|
|
153494
|
+
if (existsSync12(legacyModelsDir) && !existsSync12(targetModelsDir)) {
|
|
153353
153495
|
try {
|
|
153354
153496
|
cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
|
|
153355
153497
|
} catch (error51) {
|
|
@@ -153949,6 +154091,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
153949
154091
|
force_emergency_bypass_used INTEGER NOT NULL DEFAULT 0,
|
|
153950
154092
|
emergency_drain_active INTEGER NOT NULL DEFAULT 0,
|
|
153951
154093
|
historian_drain_failure_at INTEGER NOT NULL DEFAULT 0,
|
|
154094
|
+
wrapup_in_progress_state TEXT,
|
|
153952
154095
|
cached_m0_materialized_at INTEGER,
|
|
153953
154096
|
cached_m0_session_facts_version INTEGER,
|
|
153954
154097
|
cached_m0_upgrade_state TEXT,
|
|
@@ -154237,6 +154380,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
154237
154380
|
ensureColumn(db, "session_meta", "force_emergency_bypass_used", "INTEGER NOT NULL DEFAULT 0");
|
|
154238
154381
|
ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
|
|
154239
154382
|
ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
|
|
154383
|
+
ensureColumn(db, "session_meta", "wrapup_in_progress_state", "TEXT");
|
|
154240
154384
|
ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
|
|
154241
154385
|
ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
|
|
154242
154386
|
ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
|
|
@@ -154415,7 +154559,7 @@ function getDatabasePersistenceError(db) {
|
|
|
154415
154559
|
return null;
|
|
154416
154560
|
return persistenceErrorByDatabase.get(db) ?? null;
|
|
154417
154561
|
}
|
|
154418
|
-
var databases, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION =
|
|
154562
|
+
var databases, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 50, PERMISSIONS_ENFORCEABLE, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS = 120000;
|
|
154419
154563
|
var init_storage_db = __esm(async () => {
|
|
154420
154564
|
init_data_path();
|
|
154421
154565
|
init_logger();
|
|
@@ -154755,6 +154899,147 @@ function resetProtectedTailNoEligibleHead(db, sessionId) {
|
|
|
154755
154899
|
db.prepare("UPDATE session_meta SET recovery_no_eligible_head_count = 0 WHERE session_id = ?").run(sessionId);
|
|
154756
154900
|
})();
|
|
154757
154901
|
}
|
|
154902
|
+
function parseWrapupState(value) {
|
|
154903
|
+
if (typeof value !== "string" || value.trim().length === 0)
|
|
154904
|
+
return null;
|
|
154905
|
+
try {
|
|
154906
|
+
const parsed = JSON.parse(value);
|
|
154907
|
+
if (!parsed || typeof parsed !== "object")
|
|
154908
|
+
return null;
|
|
154909
|
+
if (typeof parsed.holderId !== "string" || parsed.holderId.length === 0)
|
|
154910
|
+
return null;
|
|
154911
|
+
const numberFields = [
|
|
154912
|
+
"acquiredAt",
|
|
154913
|
+
"expiresAt",
|
|
154914
|
+
"messagesToKeep",
|
|
154915
|
+
"anchorRawMessageCount",
|
|
154916
|
+
"targetEligibleEndOrdinal",
|
|
154917
|
+
"lastCompartmentEnd",
|
|
154918
|
+
"chunkIndex",
|
|
154919
|
+
"expectedChunks",
|
|
154920
|
+
"updatedAt"
|
|
154921
|
+
];
|
|
154922
|
+
for (const field of numberFields) {
|
|
154923
|
+
if (typeof parsed[field] !== "number" || !Number.isFinite(parsed[field]))
|
|
154924
|
+
return null;
|
|
154925
|
+
}
|
|
154926
|
+
return parsed;
|
|
154927
|
+
} catch {
|
|
154928
|
+
return null;
|
|
154929
|
+
}
|
|
154930
|
+
}
|
|
154931
|
+
function readRawWrapupState(db, sessionId) {
|
|
154932
|
+
const row = db.prepare("SELECT wrapup_in_progress_state FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
154933
|
+
return parseWrapupState(row?.wrapup_in_progress_state);
|
|
154934
|
+
}
|
|
154935
|
+
function getWrapupInProgressState(db, sessionId, now = Date.now()) {
|
|
154936
|
+
const state = readRawWrapupState(db, sessionId);
|
|
154937
|
+
if (!state)
|
|
154938
|
+
return null;
|
|
154939
|
+
if (state.expiresAt > now)
|
|
154940
|
+
return state;
|
|
154941
|
+
try {
|
|
154942
|
+
db.exec("BEGIN IMMEDIATE");
|
|
154943
|
+
} catch {
|
|
154944
|
+
return null;
|
|
154945
|
+
}
|
|
154946
|
+
let finished = false;
|
|
154947
|
+
try {
|
|
154948
|
+
const current = readRawWrapupState(db, sessionId);
|
|
154949
|
+
if (current && current.expiresAt <= now) {
|
|
154950
|
+
db.prepare("UPDATE session_meta SET wrapup_in_progress_state = NULL WHERE session_id = ?").run(sessionId);
|
|
154951
|
+
}
|
|
154952
|
+
db.exec("COMMIT");
|
|
154953
|
+
finished = true;
|
|
154954
|
+
} finally {
|
|
154955
|
+
if (!finished) {
|
|
154956
|
+
try {
|
|
154957
|
+
db.exec("ROLLBACK");
|
|
154958
|
+
} catch {}
|
|
154959
|
+
}
|
|
154960
|
+
}
|
|
154961
|
+
return null;
|
|
154962
|
+
}
|
|
154963
|
+
function isWrapupInProgress(db, sessionId, now = Date.now()) {
|
|
154964
|
+
return getWrapupInProgressState(db, sessionId, now) !== null;
|
|
154965
|
+
}
|
|
154966
|
+
function acquireWrapupInProgress(db, sessionId, state, now = Date.now()) {
|
|
154967
|
+
const acquiredAt = now;
|
|
154968
|
+
const next = {
|
|
154969
|
+
...state,
|
|
154970
|
+
acquiredAt,
|
|
154971
|
+
expiresAt: acquiredAt + WRAPUP_IN_PROGRESS_TTL_MS,
|
|
154972
|
+
updatedAt: acquiredAt
|
|
154973
|
+
};
|
|
154974
|
+
db.exec("BEGIN IMMEDIATE");
|
|
154975
|
+
let finished = false;
|
|
154976
|
+
try {
|
|
154977
|
+
ensureSessionMetaRow(db, sessionId);
|
|
154978
|
+
const current = readRawWrapupState(db, sessionId);
|
|
154979
|
+
if (current && current.expiresAt > now && current.holderId !== state.holderId) {
|
|
154980
|
+
db.exec("COMMIT");
|
|
154981
|
+
finished = true;
|
|
154982
|
+
return { ok: false, state: current };
|
|
154983
|
+
}
|
|
154984
|
+
db.prepare("UPDATE session_meta SET wrapup_in_progress_state = ? WHERE session_id = ?").run(stableStringify(next), sessionId);
|
|
154985
|
+
db.exec("COMMIT");
|
|
154986
|
+
finished = true;
|
|
154987
|
+
return { ok: true, state: next };
|
|
154988
|
+
} finally {
|
|
154989
|
+
if (!finished) {
|
|
154990
|
+
try {
|
|
154991
|
+
db.exec("ROLLBACK");
|
|
154992
|
+
} catch {}
|
|
154993
|
+
}
|
|
154994
|
+
}
|
|
154995
|
+
}
|
|
154996
|
+
function updateWrapupInProgress(db, sessionId, holderId, updates, now = Date.now()) {
|
|
154997
|
+
db.exec("BEGIN IMMEDIATE");
|
|
154998
|
+
let finished = false;
|
|
154999
|
+
try {
|
|
155000
|
+
const current = readRawWrapupState(db, sessionId);
|
|
155001
|
+
if (!current || current.holderId !== holderId || current.expiresAt <= now) {
|
|
155002
|
+
db.exec("ROLLBACK");
|
|
155003
|
+
finished = true;
|
|
155004
|
+
return null;
|
|
155005
|
+
}
|
|
155006
|
+
const next = {
|
|
155007
|
+
...current,
|
|
155008
|
+
...updates,
|
|
155009
|
+
holderId,
|
|
155010
|
+
expiresAt: now + WRAPUP_IN_PROGRESS_TTL_MS,
|
|
155011
|
+
updatedAt: now
|
|
155012
|
+
};
|
|
155013
|
+
db.prepare("UPDATE session_meta SET wrapup_in_progress_state = ? WHERE session_id = ?").run(stableStringify(next), sessionId);
|
|
155014
|
+
db.exec("COMMIT");
|
|
155015
|
+
finished = true;
|
|
155016
|
+
return next;
|
|
155017
|
+
} finally {
|
|
155018
|
+
if (!finished) {
|
|
155019
|
+
try {
|
|
155020
|
+
db.exec("ROLLBACK");
|
|
155021
|
+
} catch {}
|
|
155022
|
+
}
|
|
155023
|
+
}
|
|
155024
|
+
}
|
|
155025
|
+
function releaseWrapupInProgress(db, sessionId, holderId) {
|
|
155026
|
+
db.exec("BEGIN IMMEDIATE");
|
|
155027
|
+
let finished = false;
|
|
155028
|
+
try {
|
|
155029
|
+
const current = readRawWrapupState(db, sessionId);
|
|
155030
|
+
if (current?.holderId === holderId) {
|
|
155031
|
+
db.prepare("UPDATE session_meta SET wrapup_in_progress_state = NULL WHERE session_id = ?").run(sessionId);
|
|
155032
|
+
}
|
|
155033
|
+
db.exec("COMMIT");
|
|
155034
|
+
finished = true;
|
|
155035
|
+
} finally {
|
|
155036
|
+
if (!finished) {
|
|
155037
|
+
try {
|
|
155038
|
+
db.exec("ROLLBACK");
|
|
155039
|
+
} catch {}
|
|
155040
|
+
}
|
|
155041
|
+
}
|
|
155042
|
+
}
|
|
154758
155043
|
function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
|
|
154759
155044
|
if (usagePercentage >= 95)
|
|
154760
155045
|
return Math.min(1e6, Math.max(4 * perRunCap, Math.round(0.5 * usable)));
|
|
@@ -155432,7 +155717,7 @@ function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
|
|
|
155432
155717
|
SET new_work_tokens = ?, total_input_tokens = ?
|
|
155433
155718
|
WHERE session_id = ?`).run(Math.max(0, Math.floor(newWorkTokens)), Math.max(0, Math.floor(totalInputTokens)), sessionId);
|
|
155434
155719
|
}
|
|
155435
|
-
var CAS_RETRY_LIMIT = 5, AUTO_SEARCH_NO_HINT_REASONS, DEFAULT_PROTECTED_TAIL_META, DRAIN_WINDOW_MS, EMERGENCY_DRAIN_ENTER_PERCENTAGE = 95, EMERGENCY_DRAIN_EXIT_MARGIN = 10, EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE = 55, EMERGENCY_DRAIN_FAILURE_BACKOFF_MS = 60000, EMERGENCY_DRAIN_MAX_LATCH_MS;
|
|
155720
|
+
var CAS_RETRY_LIMIT = 5, AUTO_SEARCH_NO_HINT_REASONS, DEFAULT_PROTECTED_TAIL_META, DRAIN_WINDOW_MS, WRAPUP_IN_PROGRESS_TTL_MS, EMERGENCY_DRAIN_ENTER_PERCENTAGE = 95, EMERGENCY_DRAIN_EXIT_MARGIN = 10, EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE = 55, EMERGENCY_DRAIN_FAILURE_BACKOFF_MS = 60000, EMERGENCY_DRAIN_MAX_LATCH_MS;
|
|
155436
155721
|
var init_storage_meta_persisted = __esm(() => {
|
|
155437
155722
|
init_logger();
|
|
155438
155723
|
init_storage_meta_shared();
|
|
@@ -155456,6 +155741,7 @@ var init_storage_meta_persisted = __esm(() => {
|
|
|
155456
155741
|
historianDrainFailureAt: 0
|
|
155457
155742
|
};
|
|
155458
155743
|
DRAIN_WINDOW_MS = 10 * 60 * 1000;
|
|
155744
|
+
WRAPUP_IN_PROGRESS_TTL_MS = 5 * 60 * 1000;
|
|
155459
155745
|
EMERGENCY_DRAIN_MAX_LATCH_MS = 30 * 60 * 1000;
|
|
155460
155746
|
});
|
|
155461
155747
|
|
|
@@ -165860,7 +166146,7 @@ __export(exports_conflict_warning_hook, {
|
|
|
165860
166146
|
sendConflictWarning: () => sendConflictWarning,
|
|
165861
166147
|
cleanupConflictWarnings: () => cleanupConflictWarnings
|
|
165862
166148
|
});
|
|
165863
|
-
import { existsSync as
|
|
166149
|
+
import { existsSync as existsSync16, readFileSync as readFileSync10 } from "node:fs";
|
|
165864
166150
|
import { homedir as homedir7, platform as platform2 } from "node:os";
|
|
165865
166151
|
import { join as join13 } from "node:path";
|
|
165866
166152
|
function getDesktopStatePath() {
|
|
@@ -165881,7 +166167,7 @@ function getDesktopStatePath() {
|
|
|
165881
166167
|
}
|
|
165882
166168
|
function readDesktopState(directory) {
|
|
165883
166169
|
const statePath = getDesktopStatePath();
|
|
165884
|
-
if (!statePath || !
|
|
166170
|
+
if (!statePath || !existsSync16(statePath)) {
|
|
165885
166171
|
log(`[magic-context] conflict-warning: Desktop state file not found at ${statePath}`);
|
|
165886
166172
|
return { sessionId: null, sidecarUrl: null };
|
|
165887
166173
|
}
|
|
@@ -167057,7 +167343,8 @@ function isNativeRuntimeMissingError(error51) {
|
|
|
167057
167343
|
if (code === "ERR_DLOPEN_FAILED" && lower.includes("onnxruntime")) {
|
|
167058
167344
|
return true;
|
|
167059
167345
|
}
|
|
167060
|
-
|
|
167346
|
+
const mentionsNativeRuntime = lower.includes("onnxruntime-node") || lower.includes("onnxruntime_binding");
|
|
167347
|
+
if (!mentionsNativeRuntime)
|
|
167061
167348
|
return false;
|
|
167062
167349
|
return code === "ERR_MODULE_NOT_FOUND" || name2 === "ResolveMessage" || lower.includes("cannot find package") || lower.includes("cannot find module") || lower.includes("err_module_not_found");
|
|
167063
167350
|
}
|
|
@@ -167202,7 +167489,7 @@ class LocalEmbeddingProvider {
|
|
|
167202
167489
|
} catch (error51) {
|
|
167203
167490
|
if (isNativeRuntimeMissingError(error51)) {
|
|
167204
167491
|
nativeRuntimeMissing = true;
|
|
167205
|
-
log("[magic-context] local
|
|
167492
|
+
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.");
|
|
167206
167493
|
} else {
|
|
167207
167494
|
log("[magic-context] embedding model failed to load:", error51);
|
|
167208
167495
|
}
|
|
@@ -169786,7 +170073,7 @@ function getMemoryVerifications(db, memoryIds) {
|
|
|
169786
170073
|
var MEMORY_VERIFICATION_SENTINEL = "";
|
|
169787
170074
|
// src/features/magic-context/memory/verification-paths.ts
|
|
169788
170075
|
import { execFile } from "node:child_process";
|
|
169789
|
-
import { existsSync as
|
|
170076
|
+
import { existsSync as existsSync17, realpathSync as realpathSync3, statSync as statSync5 } from "node:fs";
|
|
169790
170077
|
import path6 from "node:path";
|
|
169791
170078
|
import { promisify } from "node:util";
|
|
169792
170079
|
async function runGit(cwd, args) {
|
|
@@ -169811,7 +170098,7 @@ function isWithin(root, candidate) {
|
|
|
169811
170098
|
}
|
|
169812
170099
|
function safeRealpath(value) {
|
|
169813
170100
|
try {
|
|
169814
|
-
return
|
|
170101
|
+
return realpathSync3.native(value);
|
|
169815
170102
|
} catch {
|
|
169816
170103
|
return null;
|
|
169817
170104
|
}
|
|
@@ -169889,7 +170176,7 @@ function verificationFileExists(baseRoot, filePath) {
|
|
|
169889
170176
|
return false;
|
|
169890
170177
|
const root = path6.resolve(baseRoot);
|
|
169891
170178
|
const candidate = path6.resolve(root, filePath);
|
|
169892
|
-
return isWithin(root, candidate) &&
|
|
170179
|
+
return isWithin(root, candidate) && existsSync17(candidate);
|
|
169893
170180
|
}
|
|
169894
170181
|
async function normalizeVerificationFiles(args) {
|
|
169895
170182
|
const cwd = path6.resolve(args.cwd);
|
|
@@ -169922,7 +170209,7 @@ async function normalizeVerificationFiles(args) {
|
|
|
169922
170209
|
warnings.push(`Skipped verification path "${value}" because it is the repo/project root.`);
|
|
169923
170210
|
continue;
|
|
169924
170211
|
}
|
|
169925
|
-
if (
|
|
170212
|
+
if (existsSync17(candidate)) {
|
|
169926
170213
|
try {
|
|
169927
170214
|
if (statSync5(candidate).isDirectory()) {
|
|
169928
170215
|
warnings.push(`Skipped verification path "${value}" because it is a directory.`);
|
|
@@ -169953,7 +170240,7 @@ async function normalizeVerificationFiles(args) {
|
|
|
169953
170240
|
}
|
|
169954
170241
|
normalized.push(tracked);
|
|
169955
170242
|
} else {
|
|
169956
|
-
if (!
|
|
170243
|
+
if (!existsSync17(candidate)) {
|
|
169957
170244
|
warnings.push(`Skipped verification path "${value}" because it does not exist.`);
|
|
169958
170245
|
continue;
|
|
169959
170246
|
}
|
|
@@ -178941,7 +179228,8 @@ function readCurrentM0SnapshotMarkers(args) {
|
|
|
178941
179228
|
sessionFactsVersion: getSessionFactsVersion(args.db, args.sessionId),
|
|
178942
179229
|
upgradeState: getUpgradeState(args.db, args.sessionId),
|
|
178943
179230
|
systemHash: hard.systemHash,
|
|
178944
|
-
modelKey: hard.modelKey
|
|
179231
|
+
modelKey: hard.modelKey,
|
|
179232
|
+
projectIdentity: args.projectPath ?? null
|
|
178945
179233
|
};
|
|
178946
179234
|
}
|
|
178947
179235
|
function snapshotMarkersFromCachedM0(state) {
|
|
@@ -178974,7 +179262,8 @@ function snapshotMarkersFromCachedM0(state) {
|
|
|
178974
179262
|
sessionFactsVersion: state.cachedM0SessionFactsVersion,
|
|
178975
179263
|
upgradeState: state.cachedM0UpgradeState,
|
|
178976
179264
|
systemHash: state.cachedM0SystemHash ?? "",
|
|
178977
|
-
modelKey: state.cachedM0ModelKey ?? ""
|
|
179265
|
+
modelKey: state.cachedM0ModelKey ?? "",
|
|
179266
|
+
projectIdentity: state.cachedM0ProjectIdentity ?? null
|
|
178978
179267
|
};
|
|
178979
179268
|
}
|
|
178980
179269
|
function mustMaterialize(args) {
|
|
@@ -178993,6 +179282,15 @@ function mustMaterialize(args) {
|
|
|
178993
179282
|
if (hard.cacheExpired && hard.lastResponseTime > 0 && hard.lastResponseTime > (args.state.cachedM0MaterializedAt ?? 0)) {
|
|
178994
179283
|
return { value: true, reason: "ttl_idle" };
|
|
178995
179284
|
}
|
|
179285
|
+
if (current.projectIdentity !== null) {
|
|
179286
|
+
const cachedProjectIdentity = args.state.cachedM0ProjectIdentity ?? null;
|
|
179287
|
+
if (cachedProjectIdentity === null) {
|
|
179288
|
+
args.state.cachedM0ProjectIdentity = current.projectIdentity;
|
|
179289
|
+
args.db.prepare("UPDATE session_meta SET cached_m0_project_identity = ? WHERE session_id = ?").run(current.projectIdentity, args.sessionId);
|
|
179290
|
+
} else if (cachedProjectIdentity !== current.projectIdentity) {
|
|
179291
|
+
return { value: true, reason: "project_change" };
|
|
179292
|
+
}
|
|
179293
|
+
}
|
|
178996
179294
|
if (current.workspaceFingerprint !== null || (args.state.cachedM0WorkspaceFingerprint ?? null) !== null) {
|
|
178997
179295
|
if ((args.state.cachedM0WorkspaceFingerprint ?? null) !== current.workspaceFingerprint) {
|
|
178998
179296
|
return { value: true, reason: "project_memory_epoch" };
|
|
@@ -179233,6 +179531,7 @@ function applyMarkersToState(state, m0Bytes, markers, m1Bytes) {
|
|
|
179233
179531
|
state.cachedM0UpgradeState = markers.upgradeState;
|
|
179234
179532
|
state.cachedM0SystemHash = markers.systemHash;
|
|
179235
179533
|
state.cachedM0ModelKey = markers.modelKey;
|
|
179534
|
+
state.cachedM0ProjectIdentity = markers.projectIdentity;
|
|
179236
179535
|
state.snapshotMarkers = markers;
|
|
179237
179536
|
}
|
|
179238
179537
|
function historySliceTokens(m0Text) {
|
|
@@ -179356,10 +179655,11 @@ function materializeM0(options) {
|
|
|
179356
179655
|
sessionFactsVersion: getSessionFactsVersion(options.db, options.sessionId),
|
|
179357
179656
|
upgradeState: getUpgradeState(options.db, options.sessionId),
|
|
179358
179657
|
systemHash: snapshotMarkers.systemHash,
|
|
179359
|
-
modelKey: snapshotMarkers.modelKey
|
|
179658
|
+
modelKey: snapshotMarkers.modelKey,
|
|
179659
|
+
projectIdentity: projectPath ?? null
|
|
179360
179660
|
};
|
|
179361
179661
|
const memoryEpochStale = current.workspaceFingerprint !== null || snapshotMarkers.workspaceFingerprint !== null ? current.workspaceFingerprint !== snapshotMarkers.workspaceFingerprint : current.projectMemoryEpoch !== snapshotMarkers.projectMemoryEpoch;
|
|
179362
|
-
const stale = memoryEpochStale || current.projectUserProfileVersion !== snapshotMarkers.projectUserProfileVersion || current.maxCompartmentSeq !== snapshotMarkers.maxCompartmentSeq || current.maxMutationId !== snapshotMarkers.maxMutationId || current.maxMemoryMutationId !== snapshotMarkers.maxMemoryMutationId || current.sessionFactsVersion !== snapshotMarkers.sessionFactsVersion || current.upgradeState !== snapshotMarkers.upgradeState;
|
|
179662
|
+
const stale = memoryEpochStale || current.projectUserProfileVersion !== snapshotMarkers.projectUserProfileVersion || current.maxCompartmentSeq !== snapshotMarkers.maxCompartmentSeq || current.maxMutationId !== snapshotMarkers.maxMutationId || current.maxMemoryMutationId !== snapshotMarkers.maxMemoryMutationId || current.sessionFactsVersion !== snapshotMarkers.sessionFactsVersion || current.upgradeState !== snapshotMarkers.upgradeState || (current.projectIdentity ?? null) !== (snapshotMarkers.projectIdentity ?? null);
|
|
179363
179663
|
if (stale) {
|
|
179364
179664
|
options.db.exec("ROLLBACK");
|
|
179365
179665
|
throw new MaterializeContentionError({ reason: "snapshot changed before Phase 3" });
|
|
@@ -179388,7 +179688,8 @@ function materializeM0(options) {
|
|
|
179388
179688
|
sessionFactsVersion: snapshotMarkers.sessionFactsVersion,
|
|
179389
179689
|
upgradeState: snapshotMarkers.upgradeState,
|
|
179390
179690
|
systemHash: snapshotMarkers.systemHash,
|
|
179391
|
-
modelKey: snapshotMarkers.modelKey
|
|
179691
|
+
modelKey: snapshotMarkers.modelKey,
|
|
179692
|
+
projectIdentity: snapshotMarkers.projectIdentity
|
|
179392
179693
|
});
|
|
179393
179694
|
options.db.prepare("UPDATE session_meta SET memory_block_count = ?, memory_block_ids = ? WHERE session_id = ?").run(renderedMemoryIds.length, JSON.stringify(renderedMemoryIds), options.sessionId);
|
|
179394
179695
|
const baselineEndMessageId = lastCompartmentBoundaryId(compartments);
|
|
@@ -179546,6 +179847,7 @@ function readCachedM0M1Row(db, sessionId) {
|
|
|
179546
179847
|
cached_m0_upgrade_state,
|
|
179547
179848
|
cached_m0_system_hash,
|
|
179548
179849
|
cached_m0_model_key,
|
|
179850
|
+
cached_m0_project_identity,
|
|
179549
179851
|
memory_block_ids
|
|
179550
179852
|
FROM session_meta
|
|
179551
179853
|
WHERE session_id = ?`).get(sessionId);
|
|
@@ -179580,11 +179882,12 @@ function markersFromCachedRow(row) {
|
|
|
179580
179882
|
sessionFactsVersion: row.cached_m0_session_facts_version,
|
|
179581
179883
|
upgradeState: row.cached_m0_upgrade_state,
|
|
179582
179884
|
systemHash: row.cached_m0_system_hash ?? "",
|
|
179583
|
-
modelKey: row.cached_m0_model_key ?? ""
|
|
179885
|
+
modelKey: row.cached_m0_model_key ?? "",
|
|
179886
|
+
projectIdentity: row.cached_m0_project_identity ?? null
|
|
179584
179887
|
};
|
|
179585
179888
|
}
|
|
179586
179889
|
function cachedRowMatchesState(row, state) {
|
|
179587
|
-
return bufferEqualsNullable(row.cached_m0_bytes, state.cachedM0Bytes) && row.cached_m0_project_memory_epoch === state.cachedM0ProjectMemoryEpoch && (row.cached_m0_workspace_fingerprint ?? null) === (state.cachedM0WorkspaceFingerprint ?? null) && row.cached_m0_project_user_profile_version === state.cachedM0ProjectUserProfileVersion && row.cached_m0_max_compartment_seq === state.cachedM0MaxCompartmentSeq && row.cached_m0_max_memory_id === state.cachedM0MaxMemoryId && row.cached_m0_max_mutation_id === state.cachedM0MaxMutationId && row.cached_m0_max_memory_mutation_id === state.cachedM0MaxMemoryMutationId && row.cached_m0_materialized_at === state.cachedM0MaterializedAt && row.cached_m0_session_facts_version === state.cachedM0SessionFactsVersion && (row.cached_m0_upgrade_state ?? null) === (state.cachedM0UpgradeState ?? null) && (row.cached_m0_system_hash ?? "") === (state.cachedM0SystemHash ?? "") && (row.cached_m0_model_key ?? "") === (state.cachedM0ModelKey ?? "");
|
|
179890
|
+
return bufferEqualsNullable(row.cached_m0_bytes, state.cachedM0Bytes) && row.cached_m0_project_memory_epoch === state.cachedM0ProjectMemoryEpoch && (row.cached_m0_workspace_fingerprint ?? null) === (state.cachedM0WorkspaceFingerprint ?? null) && row.cached_m0_project_user_profile_version === state.cachedM0ProjectUserProfileVersion && row.cached_m0_max_compartment_seq === state.cachedM0MaxCompartmentSeq && row.cached_m0_max_memory_id === state.cachedM0MaxMemoryId && row.cached_m0_max_mutation_id === state.cachedM0MaxMutationId && row.cached_m0_max_memory_mutation_id === state.cachedM0MaxMemoryMutationId && row.cached_m0_materialized_at === state.cachedM0MaterializedAt && row.cached_m0_session_facts_version === state.cachedM0SessionFactsVersion && (row.cached_m0_upgrade_state ?? null) === (state.cachedM0UpgradeState ?? null) && (row.cached_m0_system_hash ?? "") === (state.cachedM0SystemHash ?? "") && (row.cached_m0_model_key ?? "") === (state.cachedM0ModelKey ?? "") && (row.cached_m0_project_identity ?? null) === (state.cachedM0ProjectIdentity ?? null);
|
|
179588
179891
|
}
|
|
179589
179892
|
function applyCachedRowToState(state, row) {
|
|
179590
179893
|
const markers = markersFromCachedRow(row);
|
|
@@ -179606,6 +179909,7 @@ function applyCachedRowToState(state, row) {
|
|
|
179606
179909
|
state.cachedM0UpgradeState = markers.upgradeState;
|
|
179607
179910
|
state.cachedM0SystemHash = markers.systemHash;
|
|
179608
179911
|
state.cachedM0ModelKey = markers.modelKey;
|
|
179912
|
+
state.cachedM0ProjectIdentity = markers.projectIdentity;
|
|
179609
179913
|
state.snapshotMarkers = markers;
|
|
179610
179914
|
}
|
|
179611
179915
|
function replayCachedM1(state) {
|
|
@@ -180600,6 +180904,43 @@ function semanticSnapBoundary(args) {
|
|
|
180600
180904
|
}
|
|
180601
180905
|
return snapped;
|
|
180602
180906
|
}
|
|
180907
|
+
function snapWrapupBoundaryToUser(args) {
|
|
180908
|
+
const { messages, index, candidate, offset, triggerBudget } = args;
|
|
180909
|
+
if (candidate <= offset)
|
|
180910
|
+
return candidate;
|
|
180911
|
+
const snapTokenLimit = Math.min(Math.max(triggerBudget, 2000), 48000);
|
|
180912
|
+
for (let ordinal = candidate;ordinal >= offset; ordinal -= 1) {
|
|
180913
|
+
const message = messages.find((m) => m.ordinal === ordinal);
|
|
180914
|
+
if (!message)
|
|
180915
|
+
continue;
|
|
180916
|
+
if (message.role !== "user" || !hasMeaningfulUserText(message.parts))
|
|
180917
|
+
continue;
|
|
180918
|
+
const extraTokens = index.rangeTokens(ordinal, candidate);
|
|
180919
|
+
if (extraTokens <= snapTokenLimit)
|
|
180920
|
+
return ordinal;
|
|
180921
|
+
return candidate;
|
|
180922
|
+
}
|
|
180923
|
+
return candidate;
|
|
180924
|
+
}
|
|
180925
|
+
function fenceWrapupBoundaryForToolArcs(args) {
|
|
180926
|
+
let boundary = args.candidate;
|
|
180927
|
+
const maxPasses = args.arcs.length + 1;
|
|
180928
|
+
for (let pass = 0;pass < maxPasses; pass += 1) {
|
|
180929
|
+
let next = boundary;
|
|
180930
|
+
for (const arc of args.arcs) {
|
|
180931
|
+
if (arc.resOrdinal === null) {
|
|
180932
|
+
continue;
|
|
180933
|
+
}
|
|
180934
|
+
if (arc.invOrdinal >= args.lastCompartmentEndOrdinal + 1 && arc.invOrdinal < next && next <= arc.resOrdinal) {
|
|
180935
|
+
next = arc.invOrdinal;
|
|
180936
|
+
}
|
|
180937
|
+
}
|
|
180938
|
+
if (next === boundary)
|
|
180939
|
+
return boundary;
|
|
180940
|
+
boundary = next;
|
|
180941
|
+
}
|
|
180942
|
+
return boundary;
|
|
180943
|
+
}
|
|
180603
180944
|
function applyHeadCap(args) {
|
|
180604
180945
|
const { index, protectedTailStart, offset, arcs, capTokens, recentOpenArcCutoff } = args;
|
|
180605
180946
|
if (offset >= protectedTailStart)
|
|
@@ -180855,6 +181196,124 @@ function resolveBoundaryContext(args) {
|
|
|
180855
181196
|
function resolveOpenCodeProtectedTailBoundary(args) {
|
|
180856
181197
|
return resolveProtectedTailBoundary(resolveBoundaryContext(args));
|
|
180857
181198
|
}
|
|
181199
|
+
function resolveWrapupProtectedTailBoundary(args) {
|
|
181200
|
+
const ctx = resolveBoundaryContext({ ...args, mode: "manual-wrapup" });
|
|
181201
|
+
const createdAt = ctx.createdAt ?? Date.now();
|
|
181202
|
+
const messages = readRawSessionMessages(ctx.sessionId);
|
|
181203
|
+
const absoluteMessageCount = getCachedAbsoluteMessageCount(ctx.sessionId) ?? undefined;
|
|
181204
|
+
const index = buildTrueRawTokenIndex(ctx.sessionId, messages, {
|
|
181205
|
+
providerShapeVersion: ctx.providerShapeVersion,
|
|
181206
|
+
cacheNamespace: ctx.cacheNamespace,
|
|
181207
|
+
absoluteMessageCount,
|
|
181208
|
+
storedTotalForMessage: ctx.storedTokenTotals ? (m) => {
|
|
181209
|
+
const value = ctx.storedTokenTotals?.get(m.id);
|
|
181210
|
+
return value === undefined ? null : value;
|
|
181211
|
+
} : undefined
|
|
181212
|
+
});
|
|
181213
|
+
const rawMessageCount = index.rawMessageCount;
|
|
181214
|
+
const offset = Math.max(1, ctx.lastCompartmentEndOrdinal + 1);
|
|
181215
|
+
const anchorRawMessageCount = Math.max(0, Math.min(rawMessageCount, Math.floor(args.anchorRawMessageCount ?? rawMessageCount)));
|
|
181216
|
+
const usagePercentage = clampPercentage(ctx.usage?.percentage ?? 0);
|
|
181217
|
+
const usageInputTokens = Math.max(0, Math.round(ctx.usage?.inputTokens ?? 0));
|
|
181218
|
+
const rawMessagesAboveLastCompartment = Math.max(0, anchorRawMessageCount - offset + 1);
|
|
181219
|
+
const keep = Math.max(1, Math.floor(args.messagesToKeep));
|
|
181220
|
+
let targetProtectedTailStart = offset;
|
|
181221
|
+
let boundaryReason = "manual-wrapup-empty";
|
|
181222
|
+
if (rawMessageCount === 0 || rawMessagesAboveLastCompartment <= keep) {
|
|
181223
|
+
targetProtectedTailStart = offset;
|
|
181224
|
+
boundaryReason = rawMessageCount === 0 ? "manual-wrapup-empty" : "manual-wrapup-within-keep";
|
|
181225
|
+
} else {
|
|
181226
|
+
targetProtectedTailStart = anchorRawMessageCount - keep + 1;
|
|
181227
|
+
boundaryReason = "manual-wrapup-keep-watermark";
|
|
181228
|
+
const arcs = buildToolArcs(messages);
|
|
181229
|
+
const fenced = fenceWrapupBoundaryForToolArcs({
|
|
181230
|
+
candidate: targetProtectedTailStart,
|
|
181231
|
+
arcs,
|
|
181232
|
+
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal
|
|
181233
|
+
});
|
|
181234
|
+
if (fenced !== targetProtectedTailStart)
|
|
181235
|
+
boundaryReason = "manual-wrapup-tool-arc";
|
|
181236
|
+
targetProtectedTailStart = fenced;
|
|
181237
|
+
const snapped = snapWrapupBoundaryToUser({
|
|
181238
|
+
messages,
|
|
181239
|
+
index,
|
|
181240
|
+
candidate: targetProtectedTailStart,
|
|
181241
|
+
offset,
|
|
181242
|
+
triggerBudget: ctx.triggerBudget
|
|
181243
|
+
});
|
|
181244
|
+
if (snapped !== targetProtectedTailStart)
|
|
181245
|
+
boundaryReason = "manual-wrapup-user-snap";
|
|
181246
|
+
targetProtectedTailStart = snapped;
|
|
181247
|
+
const refenced = fenceWrapupBoundaryForToolArcs({
|
|
181248
|
+
candidate: targetProtectedTailStart,
|
|
181249
|
+
arcs,
|
|
181250
|
+
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal
|
|
181251
|
+
});
|
|
181252
|
+
if (refenced !== targetProtectedTailStart)
|
|
181253
|
+
boundaryReason = "manual-wrapup-tool-arc";
|
|
181254
|
+
targetProtectedTailStart = refenced;
|
|
181255
|
+
}
|
|
181256
|
+
targetProtectedTailStart = clampOrdinal(targetProtectedTailStart, rawMessageCount);
|
|
181257
|
+
const target = deriveProtectedTailTokenTarget({
|
|
181258
|
+
contextLimit: ctx.contextLimit,
|
|
181259
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
181260
|
+
usagePercentage,
|
|
181261
|
+
triggerBudget: ctx.triggerBudget
|
|
181262
|
+
});
|
|
181263
|
+
const perRunCap = selectPerRunCap({
|
|
181264
|
+
usagePercentage,
|
|
181265
|
+
N: target.N,
|
|
181266
|
+
contextLimit: ctx.contextLimit,
|
|
181267
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage
|
|
181268
|
+
});
|
|
181269
|
+
const head = applyHeadCap({
|
|
181270
|
+
index,
|
|
181271
|
+
protectedTailStart: targetProtectedTailStart,
|
|
181272
|
+
offset,
|
|
181273
|
+
arcs: buildToolArcs(messages),
|
|
181274
|
+
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal,
|
|
181275
|
+
capTokens: perRunCap,
|
|
181276
|
+
recentOpenArcCutoff: targetProtectedTailStart
|
|
181277
|
+
});
|
|
181278
|
+
const eligibleEndOrdinal = Math.min(head.eligibleEndOrdinal, targetProtectedTailStart);
|
|
181279
|
+
const rawRangeFingerprint = computeRawRangeFingerprint(messages, offset, eligibleEndOrdinal);
|
|
181280
|
+
const snapshot = {
|
|
181281
|
+
sessionId: ctx.sessionId,
|
|
181282
|
+
mode: "manual-wrapup",
|
|
181283
|
+
offset,
|
|
181284
|
+
offsetMessageId: boundaryMessageId(index, offset),
|
|
181285
|
+
protectedTailStart: targetProtectedTailStart,
|
|
181286
|
+
protectedTailStartMessageId: boundaryMessageId(index, targetProtectedTailStart),
|
|
181287
|
+
eligibleEndOrdinal,
|
|
181288
|
+
eligibleEndMessageId: boundaryMessageId(index, eligibleEndOrdinal - 1),
|
|
181289
|
+
rawMessageCountAtTrigger: rawMessageCount,
|
|
181290
|
+
rawLastMessageIdAtTrigger: boundaryMessageId(index, rawMessageCount),
|
|
181291
|
+
N: keep,
|
|
181292
|
+
usagePercentage,
|
|
181293
|
+
usageInputTokens,
|
|
181294
|
+
usageSource: ctx.usageSource,
|
|
181295
|
+
contextLimit: ctx.contextLimit,
|
|
181296
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
181297
|
+
triggerBudget: ctx.triggerBudget,
|
|
181298
|
+
priorBoundaryOrdinal: ctx.priorBoundaryOrdinal,
|
|
181299
|
+
migrationFloorActive: ctx.migrationFloorActive,
|
|
181300
|
+
emergencyTailScale: ctx.emergencyTailScale,
|
|
181301
|
+
providerShapeVersion: ctx.providerShapeVersion,
|
|
181302
|
+
cacheNamespace: ctx.cacheNamespace,
|
|
181303
|
+
createdAt,
|
|
181304
|
+
rawRangeFingerprint,
|
|
181305
|
+
trueRawEligibleTokens: index.rangeTokens(offset, targetProtectedTailStart),
|
|
181306
|
+
oversizeAtomicUnit: head.oversizeAtomicUnit,
|
|
181307
|
+
boundaryReason
|
|
181308
|
+
};
|
|
181309
|
+
return {
|
|
181310
|
+
snapshot,
|
|
181311
|
+
rawMessagesAboveLastCompartment,
|
|
181312
|
+
anchorRawMessageCount,
|
|
181313
|
+
targetProtectedTailStart,
|
|
181314
|
+
targetEligibleEndOrdinal: targetProtectedTailStart
|
|
181315
|
+
};
|
|
181316
|
+
}
|
|
180858
181317
|
function getRawHistoryEligibility(db, sessionId) {
|
|
180859
181318
|
const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
|
|
180860
181319
|
const offset = Math.max(1, lastCompartmentEnd + 1);
|
|
@@ -183082,7 +183541,7 @@ async function runCompartmentAgent(deps) {
|
|
|
183082
183541
|
currentContextLimit: deps.currentContextLimit ?? boundarySnapshot.contextLimit
|
|
183083
183542
|
}) : { ok: true };
|
|
183084
183543
|
if (!validation.ok && validation.reason === "stale_snapshot") {
|
|
183085
|
-
const refreshed = resolveOpenCodeProtectedTailBoundary({
|
|
183544
|
+
const refreshed = deps.refreshBoundarySnapshot ? deps.refreshBoundarySnapshot(boundarySnapshot, validation) : resolveOpenCodeProtectedTailBoundary({
|
|
183086
183545
|
db,
|
|
183087
183546
|
sessionId,
|
|
183088
183547
|
mode: "incremental-runner",
|
|
@@ -183095,7 +183554,7 @@ async function runCompartmentAgent(deps) {
|
|
|
183095
183554
|
usageSource: boundarySnapshot.usageSource,
|
|
183096
183555
|
emergencyTailScale: boundarySnapshot.emergencyTailScale
|
|
183097
183556
|
});
|
|
183098
|
-
if (hasRunnableCompartmentWindow(refreshed)) {
|
|
183557
|
+
if (refreshed && hasRunnableCompartmentWindow(refreshed)) {
|
|
183099
183558
|
sessionLog(sessionId, `historian: refreshed stale protected-tail snapshot at run time (was: ${validation.detail ?? "stale"}) — eligible head ${refreshed.offset}-${refreshed.eligibleEndOrdinal - 1}`);
|
|
183100
183559
|
boundarySnapshot = refreshed;
|
|
183101
183560
|
validation = { ok: true };
|
|
@@ -183113,7 +183572,8 @@ async function runCompartmentAgent(deps) {
|
|
|
183113
183572
|
if (protectedTailStart <= offset || eligibleEndOrdinal <= offset) {
|
|
183114
183573
|
sessionLog(sessionId, `historian no-op: protectedTailStart=${protectedTailStart} eligibleEnd=${eligibleEndOrdinal} <= offset=${offset} — nothing to compact`);
|
|
183115
183574
|
if (boundarySnapshot.usagePercentage < 80 && !boundarySnapshot.emergencyTailScale) {
|
|
183116
|
-
|
|
183575
|
+
if (!isWrapupInProgress(db, sessionId))
|
|
183576
|
+
clearEmergencyRecovery(db, sessionId);
|
|
183117
183577
|
} else {
|
|
183118
183578
|
const count = recordHighPressureNoEligibleHead(db, boundarySnapshot);
|
|
183119
183579
|
sessionLog(sessionId, `historian high-pressure no-op: recovery remains armed (noEligibleHeadCount=${count})`);
|
|
@@ -183126,7 +183586,7 @@ async function runCompartmentAgent(deps) {
|
|
|
183126
183586
|
}
|
|
183127
183587
|
const perRunCap = selectPerRunCap(boundarySnapshot);
|
|
183128
183588
|
const usable = Math.max(1, Math.round(boundarySnapshot.contextLimit * boundarySnapshot.executeThresholdPercentage / 100));
|
|
183129
|
-
const reserve = reserveProtectedTailDrainTokens({
|
|
183589
|
+
const reserve = deps.forceDrainQuota ? { ok: true, reservation: null } : reserveProtectedTailDrainTokens({
|
|
183130
183590
|
db,
|
|
183131
183591
|
sessionId,
|
|
183132
183592
|
runId: crypto.randomUUID(),
|
|
@@ -183144,12 +183604,14 @@ async function runCompartmentAgent(deps) {
|
|
|
183144
183604
|
}
|
|
183145
183605
|
drainReservation = reserve.reservation;
|
|
183146
183606
|
const chunk = readSessionChunk(sessionId, historianChunkTokens, offset, eligibleEndOrdinal);
|
|
183607
|
+
const forceKeepLastCompartmentForChunk = deps.forceKeepLastCompartment === true && !chunk.hasMore;
|
|
183147
183608
|
telemetry.chunkStartOrdinal = chunk.startIndex;
|
|
183148
183609
|
telemetry.chunkEndOrdinal = chunk.endIndex;
|
|
183149
183610
|
if (!chunk.text || chunk.messageCount === 0) {
|
|
183150
183611
|
sessionLog(sessionId, `historian no-op: chunk empty after filtering (messageCount=${chunk.messageCount}, textLen=${chunk.text?.length ?? 0}) range=${offset}-${eligibleEndOrdinal - 1}`);
|
|
183151
183612
|
if (boundarySnapshot.usagePercentage < 80 && !boundarySnapshot.emergencyTailScale) {
|
|
183152
|
-
|
|
183613
|
+
if (!isWrapupInProgress(db, sessionId))
|
|
183614
|
+
clearEmergencyRecovery(db, sessionId);
|
|
183153
183615
|
} else {
|
|
183154
183616
|
recordHighPressureNoEligibleHead(db, boundarySnapshot);
|
|
183155
183617
|
}
|
|
@@ -183223,7 +183685,7 @@ ${chunkText}`,
|
|
|
183223
183685
|
const BOUNDARY_HEALING_SLACK = 2;
|
|
183224
183686
|
const inEmergency = getOverflowState(db, sessionId).needsEmergencyRecovery;
|
|
183225
183687
|
let persistedCompartments = emittedCompartments;
|
|
183226
|
-
if (!inEmergency && emittedCompartments.length >= 2) {
|
|
183688
|
+
if (!inEmergency && !forceKeepLastCompartmentForChunk && emittedCompartments.length >= 2) {
|
|
183227
183689
|
const lastEmitted = emittedCompartments[emittedCompartments.length - 1];
|
|
183228
183690
|
const lookaheadMargin = chunk.endIndex - lastEmitted.endMessage;
|
|
183229
183691
|
if (lookaheadMargin <= BOUNDARY_HEALING_SLACK) {
|
|
@@ -183247,10 +183709,21 @@ ${chunkText}`,
|
|
|
183247
183709
|
const lastNewEndMessageId = newCompartments[newCompartments.length - 1]?.endMessageId;
|
|
183248
183710
|
const promotionDirectory = sessionDirectory || deps.directory;
|
|
183249
183711
|
const discardedLast = persistedCompartments.length < emittedCompartments.length;
|
|
183712
|
+
const weakLookaheadFinalCompartment = forceKeepLastCompartmentForChunk;
|
|
183713
|
+
const skipUnanchoredPromotion = discardedLast || weakLookaheadFinalCompartment;
|
|
183250
183714
|
const embeddingActive = !!promotionDirectory && deps.memoryEnabled !== false;
|
|
183251
183715
|
const promotionActive = embeddingActive && deps.autoPromote !== false;
|
|
183252
183716
|
const promotionProjectIdentity = promotionDirectory ? resolveProjectIdentity(promotionDirectory) : "";
|
|
183253
|
-
const publishableEvents = (validatedPass.events ?? []).filter((e) =>
|
|
183717
|
+
const publishableEvents = (validatedPass.events ?? []).filter((e) => {
|
|
183718
|
+
if (typeof e.atCompartment !== "number")
|
|
183719
|
+
return !weakLookaheadFinalCompartment;
|
|
183720
|
+
if (e.atCompartment > persistedCompartments.length)
|
|
183721
|
+
return false;
|
|
183722
|
+
if (weakLookaheadFinalCompartment && e.atCompartment >= emittedCompartments.length) {
|
|
183723
|
+
return false;
|
|
183724
|
+
}
|
|
183725
|
+
return true;
|
|
183726
|
+
});
|
|
183254
183727
|
let promotedFactRefs = [];
|
|
183255
183728
|
let persistedIds = [];
|
|
183256
183729
|
const holderId = deps.compartmentLeaseHolderId;
|
|
@@ -183270,7 +183743,7 @@ ${chunkText}`,
|
|
|
183270
183743
|
}
|
|
183271
183744
|
appendCompartments(db, sessionId, persistedCompartments);
|
|
183272
183745
|
persistedIds = getCompartments(db, sessionId).slice(-persistedCompartments.length).map((c) => c.id);
|
|
183273
|
-
if (promotionActive && !
|
|
183746
|
+
if (promotionActive && !skipUnanchoredPromotion) {
|
|
183274
183747
|
promotedFactRefs = promoteSessionFactsDurable(db, sessionId, promotionProjectIdentity, validatedPass.facts ?? []);
|
|
183275
183748
|
}
|
|
183276
183749
|
if (publishableEvents.length > 0) {
|
|
@@ -183285,7 +183758,8 @@ ${chunkText}`,
|
|
|
183285
183758
|
clearHistorianFailureState(db, sessionId);
|
|
183286
183759
|
clearHistorianDrainFailure(db, sessionId);
|
|
183287
183760
|
recordProtectedTailPublicationFloor(db, sessionId, lastCompartmentEnd + 1);
|
|
183288
|
-
|
|
183761
|
+
if (!isWrapupInProgress(db, sessionId))
|
|
183762
|
+
clearEmergencyRecovery(db, sessionId);
|
|
183289
183763
|
drainReservation = null;
|
|
183290
183764
|
if (deferMarkerApplication && lastNewEndMessageId) {
|
|
183291
183765
|
setPendingCompactionMarkerState(db, sessionId, {
|
|
@@ -183357,7 +183831,7 @@ ${chunkText}`,
|
|
|
183357
183831
|
}
|
|
183358
183832
|
})();
|
|
183359
183833
|
}
|
|
183360
|
-
if (deps.experimentalUserMemories === true && !
|
|
183834
|
+
if (deps.experimentalUserMemories === true && !skipUnanchoredPromotion && validatedPass.userObservations && validatedPass.userObservations.length > 0) {
|
|
183361
183835
|
try {
|
|
183362
183836
|
const lastNew = newCompartments[newCompartments.length - 1];
|
|
183363
183837
|
insertUserMemoryCandidates(db, validatedPass.userObservations.map((obs) => ({
|
|
@@ -183371,7 +183845,7 @@ ${chunkText}`,
|
|
|
183371
183845
|
sessionLog(sessionId, "failed to store user memory candidates:", error51);
|
|
183372
183846
|
}
|
|
183373
183847
|
}
|
|
183374
|
-
if (!
|
|
183848
|
+
if (!skipUnanchoredPromotion && promotionProjectIdentity && validatedPass.primerCandidates && validatedPass.primerCandidates.length > 0) {
|
|
183375
183849
|
try {
|
|
183376
183850
|
const firstNew = newCompartments[0];
|
|
183377
183851
|
const lastNew = newCompartments[newCompartments.length - 1];
|
|
@@ -184238,6 +184712,21 @@ function markActiveCompartmentRunPublished(sessionId) {
|
|
|
184238
184712
|
if (activeRun)
|
|
184239
184713
|
activeRun.published = true;
|
|
184240
184714
|
}
|
|
184715
|
+
function registerActiveCompartmentRun(sessionId, promise2, kind = "other") {
|
|
184716
|
+
const activeRun = {
|
|
184717
|
+
promise: Promise.resolve(),
|
|
184718
|
+
published: false,
|
|
184719
|
+
kind
|
|
184720
|
+
};
|
|
184721
|
+
const wrapped = promise2.finally(() => {
|
|
184722
|
+
if (activeRuns.get(sessionId)?.promise === wrapped) {
|
|
184723
|
+
activeRuns.delete(sessionId);
|
|
184724
|
+
}
|
|
184725
|
+
});
|
|
184726
|
+
activeRun.promise = wrapped;
|
|
184727
|
+
activeRuns.set(sessionId, activeRun);
|
|
184728
|
+
return activeRun;
|
|
184729
|
+
}
|
|
184241
184730
|
function withPublishedCallback(deps) {
|
|
184242
184731
|
return {
|
|
184243
184732
|
...deps,
|
|
@@ -184249,8 +184738,12 @@ function withPublishedCallback(deps) {
|
|
|
184249
184738
|
}
|
|
184250
184739
|
function startLeaseRenewal(deps, holderId) {
|
|
184251
184740
|
return setInterval(() => {
|
|
184252
|
-
|
|
184253
|
-
|
|
184741
|
+
try {
|
|
184742
|
+
if (!renewCompartmentLease(deps.db, deps.sessionId, holderId)) {
|
|
184743
|
+
sessionLog(deps.sessionId, "compartment lease renewal failed; publish will be skipped if holder is stale");
|
|
184744
|
+
}
|
|
184745
|
+
} catch (err) {
|
|
184746
|
+
sessionLog(deps.sessionId, `compartment lease renewal threw; publish will be skipped if holder is stale (${err instanceof Error ? err.message : String(err)})`);
|
|
184254
184747
|
}
|
|
184255
184748
|
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
184256
184749
|
}
|
|
@@ -184259,6 +184752,11 @@ function startCompartmentAgent(deps) {
|
|
|
184259
184752
|
if (existing) {
|
|
184260
184753
|
return;
|
|
184261
184754
|
}
|
|
184755
|
+
if (isWrapupInProgress(deps.db, deps.sessionId)) {
|
|
184756
|
+
sessionLog(deps.sessionId, "compartment agent skipped: /ctx-wrapup is active");
|
|
184757
|
+
updateSessionMeta(deps.db, deps.sessionId, { compartmentInProgress: false });
|
|
184758
|
+
return;
|
|
184759
|
+
}
|
|
184262
184760
|
const holderId = crypto.randomUUID();
|
|
184263
184761
|
const lease = acquireCompartmentLease(deps.db, deps.sessionId, holderId);
|
|
184264
184762
|
if (!lease) {
|
|
@@ -184266,6 +184764,12 @@ function startCompartmentAgent(deps) {
|
|
|
184266
184764
|
updateSessionMeta(deps.db, deps.sessionId, { compartmentInProgress: false });
|
|
184267
184765
|
return;
|
|
184268
184766
|
}
|
|
184767
|
+
if (isWrapupInProgress(deps.db, deps.sessionId)) {
|
|
184768
|
+
sessionLog(deps.sessionId, "compartment agent skipped: /ctx-wrapup became active");
|
|
184769
|
+
releaseCompartmentLease(deps.db, deps.sessionId, holderId);
|
|
184770
|
+
updateSessionMeta(deps.db, deps.sessionId, { compartmentInProgress: false });
|
|
184771
|
+
return;
|
|
184772
|
+
}
|
|
184269
184773
|
const renewal = startLeaseRenewal(deps, holderId);
|
|
184270
184774
|
let realRunStarted = false;
|
|
184271
184775
|
const runnerDeps = withPublishedCallback({
|
|
@@ -184287,13 +184791,19 @@ function startCompartmentAgent(deps) {
|
|
|
184287
184791
|
activeRuns.delete(deps.sessionId);
|
|
184288
184792
|
}
|
|
184289
184793
|
});
|
|
184290
|
-
activeRuns.set(deps.sessionId, { promise: promise2, published: false });
|
|
184794
|
+
activeRuns.set(deps.sessionId, { promise: promise2, published: false, kind: "incremental" });
|
|
184291
184795
|
if (!realRunStarted && activeRuns.get(deps.sessionId)?.promise === promise2) {
|
|
184292
184796
|
activeRuns.delete(deps.sessionId);
|
|
184293
184797
|
}
|
|
184294
184798
|
}
|
|
184295
184799
|
async function executeContextRecompWithResult(deps, options = {}) {
|
|
184296
184800
|
const { sessionId } = deps;
|
|
184801
|
+
if (isWrapupInProgress(deps.db, sessionId)) {
|
|
184802
|
+
return {
|
|
184803
|
+
message: "## Magic Recomp — Skipped\n\n/ctx-wrapup is already compacting this session. Wait for it to finish, then try `/ctx-recomp` again.",
|
|
184804
|
+
published: false
|
|
184805
|
+
};
|
|
184806
|
+
}
|
|
184297
184807
|
if (activeRuns.has(sessionId)) {
|
|
184298
184808
|
return {
|
|
184299
184809
|
message: "## Magic Recomp — Skipped\n\nHistorian is already running for this session. Wait for it to finish, then try `/ctx-recomp` again.",
|
|
@@ -184317,7 +184827,7 @@ async function executeContextRecompWithResult(deps, options = {}) {
|
|
|
184317
184827
|
}).catch((err) => {
|
|
184318
184828
|
sessionLog(sessionId, "compartment agent: recomp unhandled rejection:", err);
|
|
184319
184829
|
});
|
|
184320
|
-
activeRuns.set(sessionId, { promise: wrappedPromise, published: false });
|
|
184830
|
+
activeRuns.set(sessionId, { promise: wrappedPromise, published: false, kind: "recomp" });
|
|
184321
184831
|
try {
|
|
184322
184832
|
const message = await promise2;
|
|
184323
184833
|
const published = activeRuns.get(sessionId)?.published === true;
|
|
@@ -184745,6 +185255,13 @@ Recomp crashed: ${String(error51)}`;
|
|
|
184745
185255
|
}
|
|
184746
185256
|
}
|
|
184747
185257
|
async function runManagedUpgrade(ctx, sessionId) {
|
|
185258
|
+
if (isWrapupInProgress(ctx.db, sessionId)) {
|
|
185259
|
+
const message = "/ctx-wrapup is already compacting this session. Wait for it to finish, then try `/ctx-session-upgrade` again.";
|
|
185260
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "skipped", message);
|
|
185261
|
+
return `## Session Upgrade — Skipped
|
|
185262
|
+
|
|
185263
|
+
${message}`;
|
|
185264
|
+
}
|
|
184748
185265
|
setRecompStarting(ctx.liveSessionState, sessionId, "Starting upgrade…", "upgrade");
|
|
184749
185266
|
try {
|
|
184750
185267
|
const compartments = getCompartments(ctx.db, sessionId);
|
|
@@ -184899,13 +185416,14 @@ function shouldShowAnnouncement() {
|
|
|
184899
185416
|
}
|
|
184900
185417
|
return ordering > 0;
|
|
184901
185418
|
}
|
|
184902
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
185419
|
+
var ANNOUNCEMENT_VERSION = "0.31.0", ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU", STATE_FILENAME = "last_announced_version";
|
|
184903
185420
|
var init_announcement = __esm(() => {
|
|
184904
185421
|
init_data_path();
|
|
184905
185422
|
ANNOUNCEMENT_FEATURES = [
|
|
184906
|
-
"
|
|
184907
|
-
"
|
|
184908
|
-
"
|
|
185423
|
+
"New /ctx-wrapup command: compact older history on demand, keeping the newest N messages raw. Run it before switching to a smaller-context model.",
|
|
185424
|
+
"ctx_search now also searches your session notes and smart notes.",
|
|
185425
|
+
"Project identity now survives transient git failures (slow disks, dubious ownership) without splitting your project memory.",
|
|
185426
|
+
"Removed the ctx_reduce_enabled setting; agent-controlled reduction is always on. Caveman text compression is now independent (caveman_text_compression.enabled)."
|
|
184909
185427
|
];
|
|
184910
185428
|
});
|
|
184911
185429
|
|
|
@@ -186333,6 +186851,10 @@ function getMagicContextBuiltinCommands() {
|
|
|
186333
186851
|
template: "ctx-recomp",
|
|
186334
186852
|
description: "Rebuild compartments and facts from raw history (full or <start>-<end> range)"
|
|
186335
186853
|
},
|
|
186854
|
+
"ctx-wrapup": {
|
|
186855
|
+
template: "ctx-wrapup",
|
|
186856
|
+
description: "Compact older live history while keeping the newest messages raw"
|
|
186857
|
+
},
|
|
186336
186858
|
"ctx-session-upgrade": {
|
|
186337
186859
|
template: "ctx-session-upgrade",
|
|
186338
186860
|
description: "Upgrade this session to the latest history format: rebuild compartments and migrate project memories"
|
|
@@ -186692,7 +187214,7 @@ init_project_identity();
|
|
|
186692
187214
|
init_logger();
|
|
186693
187215
|
init_project_identity();
|
|
186694
187216
|
init_session_project_storage();
|
|
186695
|
-
import { existsSync as
|
|
187217
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
186696
187218
|
var LEASE_TTL_MS = 10 * 60 * 1000;
|
|
186697
187219
|
var SESSION_QUERY_CHUNK_SIZE = 250;
|
|
186698
187220
|
var YIELD_EVERY_NEW_DIRECTORIES = 10;
|
|
@@ -186848,7 +187370,7 @@ async function runSessionProjectBackfill(db, sessions, options = {}) {
|
|
|
186848
187370
|
result.skippedEmptyDirectories += 1;
|
|
186849
187371
|
continue;
|
|
186850
187372
|
}
|
|
186851
|
-
const stillExists = existenceCache.get(session.directory) ??
|
|
187373
|
+
const stillExists = existenceCache.get(session.directory) ?? existsSync9(session.directory);
|
|
186852
187374
|
existenceCache.set(session.directory, stillExists);
|
|
186853
187375
|
if (!stillExists) {
|
|
186854
187376
|
result.skippedDeadDirectories += 1;
|
|
@@ -187037,7 +187559,7 @@ await init_storage_db();
|
|
|
187037
187559
|
init_logger();
|
|
187038
187560
|
init_project_identity();
|
|
187039
187561
|
import { createHash as createHash5 } from "node:crypto";
|
|
187040
|
-
import { realpathSync } from "node:fs";
|
|
187562
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
187041
187563
|
import path5 from "node:path";
|
|
187042
187564
|
|
|
187043
187565
|
// src/features/magic-context/memory/relocate-memory.ts
|
|
@@ -187071,7 +187593,10 @@ function countFailures(db) {
|
|
|
187071
187593
|
}
|
|
187072
187594
|
function classifyBackfillError(error51) {
|
|
187073
187595
|
if (error51 instanceof ProjectIdentityError) {
|
|
187074
|
-
return {
|
|
187596
|
+
return {
|
|
187597
|
+
errorClass: error51.errorClass === "dubious_ownership" ? "unknown" : error51.errorClass,
|
|
187598
|
+
errorMessage: error51.message
|
|
187599
|
+
};
|
|
187075
187600
|
}
|
|
187076
187601
|
if (error51 instanceof Error) {
|
|
187077
187602
|
return { errorClass: "unknown", errorMessage: error51.message };
|
|
@@ -187091,7 +187616,7 @@ function resolveBackfillIdentity(rawProjectPath) {
|
|
|
187091
187616
|
function computeLegacyRustDirIdentity(rawProjectPath) {
|
|
187092
187617
|
let canonical;
|
|
187093
187618
|
try {
|
|
187094
|
-
canonical =
|
|
187619
|
+
canonical = realpathSync2(rawProjectPath);
|
|
187095
187620
|
} catch {
|
|
187096
187621
|
canonical = path5.isAbsolute(rawProjectPath) ? rawProjectPath : path5.join(process.cwd(), rawProjectPath);
|
|
187097
187622
|
}
|
|
@@ -187264,20 +187789,20 @@ async function runDeferredV22Backfill(db, options = {}) {
|
|
|
187264
187789
|
|
|
187265
187790
|
// src/hooks/auto-update-checker/index.ts
|
|
187266
187791
|
init_logger();
|
|
187267
|
-
import { existsSync as
|
|
187792
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync9, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
187268
187793
|
import { dirname as dirname7, join as join10 } from "node:path";
|
|
187269
187794
|
|
|
187270
187795
|
// src/hooks/auto-update-checker/cache.ts
|
|
187271
187796
|
init_logger();
|
|
187272
187797
|
var import_comment_json2 = __toESM(require_src2(), 1);
|
|
187273
187798
|
import { spawn } from "node:child_process";
|
|
187274
|
-
import { existsSync as
|
|
187799
|
+
import { existsSync as existsSync14, readFileSync as readFileSync8, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
187275
187800
|
import { basename as basename2, dirname as dirname6, join as join9 } from "node:path";
|
|
187276
187801
|
|
|
187277
187802
|
// src/hooks/auto-update-checker/checker.ts
|
|
187278
187803
|
init_logger();
|
|
187279
187804
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
187280
|
-
import { existsSync as
|
|
187805
|
+
import { existsSync as existsSync13, readFileSync as readFileSync7, renameSync as renameSync2, statSync as statSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
187281
187806
|
import { homedir as homedir5 } from "node:os";
|
|
187282
187807
|
import { dirname as dirname5, isAbsolute as isAbsolute3, join as join8, resolve as resolve2 } from "node:path";
|
|
187283
187808
|
import { fileURLToPath } from "node:url";
|
|
@@ -187387,7 +187912,7 @@ function findPackageJsonUp(startPath) {
|
|
|
187387
187912
|
let dir = stat.isDirectory() ? startPath : dirname5(startPath);
|
|
187388
187913
|
for (let i = 0;i < 10; i++) {
|
|
187389
187914
|
const pkgPath = join8(dir, "package.json");
|
|
187390
|
-
if (
|
|
187915
|
+
if (existsSync13(pkgPath)) {
|
|
187391
187916
|
try {
|
|
187392
187917
|
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync7(pkgPath, "utf-8")));
|
|
187393
187918
|
if (pkg.success && pkg.data.name === PACKAGE_NAME)
|
|
@@ -187405,7 +187930,7 @@ function findPackageJsonUp(startPath) {
|
|
|
187405
187930
|
function getLocalDevPath(directory) {
|
|
187406
187931
|
for (const configPath of getConfigPaths(directory)) {
|
|
187407
187932
|
try {
|
|
187408
|
-
if (!
|
|
187933
|
+
if (!existsSync13(configPath))
|
|
187409
187934
|
continue;
|
|
187410
187935
|
const rawConfig = parseJsonConfig(readFileSync7(configPath, "utf-8"));
|
|
187411
187936
|
const plugins = getPluginEntries(rawConfig);
|
|
@@ -187451,7 +187976,7 @@ function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
|
|
|
187451
187976
|
function findPluginEntry(directory) {
|
|
187452
187977
|
for (const configPath of getConfigPaths(directory)) {
|
|
187453
187978
|
try {
|
|
187454
|
-
if (!
|
|
187979
|
+
if (!existsSync13(configPath))
|
|
187455
187980
|
continue;
|
|
187456
187981
|
const rawConfig = parseJsonConfig(readFileSync7(configPath, "utf-8"));
|
|
187457
187982
|
const plugins = getPluginEntries(rawConfig);
|
|
@@ -187489,7 +188014,7 @@ function getCachedVersion(spec) {
|
|
|
187489
188014
|
].filter(isString);
|
|
187490
188015
|
for (const packageJsonPath of candidates) {
|
|
187491
188016
|
try {
|
|
187492
|
-
if (!
|
|
188017
|
+
if (!existsSync13(packageJsonPath))
|
|
187493
188018
|
continue;
|
|
187494
188019
|
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync7(packageJsonPath, "utf-8")));
|
|
187495
188020
|
if (pkg.success && pkg.data.version) {
|
|
@@ -187544,7 +188069,7 @@ function stripPackageNameFromPath(pathValue, packageName) {
|
|
|
187544
188069
|
}
|
|
187545
188070
|
function removeFromPackageLock(installDir, packageName) {
|
|
187546
188071
|
const lockPath = join9(installDir, "package-lock.json");
|
|
187547
|
-
if (!
|
|
188072
|
+
if (!existsSync14(lockPath))
|
|
187548
188073
|
return false;
|
|
187549
188074
|
try {
|
|
187550
188075
|
const lock = import_comment_json2.parse(readFileSync8(lockPath, "utf-8"));
|
|
@@ -187570,7 +188095,7 @@ function removeFromPackageLock(installDir, packageName) {
|
|
|
187570
188095
|
}
|
|
187571
188096
|
}
|
|
187572
188097
|
function ensureDependencyVersion(packageJsonPath, packageName, version2) {
|
|
187573
|
-
if (!
|
|
188098
|
+
if (!existsSync14(packageJsonPath))
|
|
187574
188099
|
return false;
|
|
187575
188100
|
try {
|
|
187576
188101
|
const raw = import_comment_json2.parse(readFileSync8(packageJsonPath, "utf-8"));
|
|
@@ -187593,7 +188118,7 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
|
|
|
187593
188118
|
}
|
|
187594
188119
|
function removeInstalledPackage(installDir, packageName) {
|
|
187595
188120
|
const packageDir = join9(installDir, "node_modules", packageName);
|
|
187596
|
-
if (!
|
|
188121
|
+
if (!existsSync14(packageDir))
|
|
187597
188122
|
return false;
|
|
187598
188123
|
try {
|
|
187599
188124
|
rmSync2(packageDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
@@ -187615,7 +188140,7 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
|
|
|
187615
188140
|
if (nodeModulesDir && basename2(nodeModulesDir) === "node_modules") {
|
|
187616
188141
|
const installDir = dirname6(nodeModulesDir);
|
|
187617
188142
|
const packageJsonPath = join9(installDir, "package.json");
|
|
187618
|
-
if (!
|
|
188143
|
+
if (!existsSync14(packageJsonPath)) {
|
|
187619
188144
|
try {
|
|
187620
188145
|
writeFileSync4(packageJsonPath, `${JSON.stringify({ private: true, dependencies: {} }, null, 2)}
|
|
187621
188146
|
`);
|
|
@@ -187630,7 +188155,7 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
|
|
|
187630
188155
|
return null;
|
|
187631
188156
|
}
|
|
187632
188157
|
const legacyPackageJsonPath = join9(dirname6(CACHE_DIR), "package.json");
|
|
187633
|
-
if (
|
|
188158
|
+
if (existsSync14(legacyPackageJsonPath)) {
|
|
187634
188159
|
return { installDir: dirname6(CACHE_DIR), packageJsonPath: legacyPackageJsonPath };
|
|
187635
188160
|
}
|
|
187636
188161
|
return null;
|
|
@@ -187755,7 +188280,7 @@ function claimCheckSlot(storageDir, intervalMs) {
|
|
|
187755
188280
|
return true;
|
|
187756
188281
|
try {
|
|
187757
188282
|
const file2 = join10(storageDir, TIMESTAMP_FILENAME);
|
|
187758
|
-
if (
|
|
188283
|
+
if (existsSync15(file2)) {
|
|
187759
188284
|
try {
|
|
187760
188285
|
const raw = JSON.parse(readFileSync9(file2, "utf-8"));
|
|
187761
188286
|
const last = typeof raw.lastCheckedMs === "number" ? raw.lastCheckedMs : 0;
|
|
@@ -188483,7 +189008,7 @@ init_task_config();
|
|
|
188483
189008
|
|
|
188484
189009
|
// src/features/magic-context/dreamer/task-executor.ts
|
|
188485
189010
|
import { createHash as createHash10 } from "node:crypto";
|
|
188486
|
-
import { existsSync as
|
|
189011
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
188487
189012
|
|
|
188488
189013
|
// src/agents/dreamer.ts
|
|
188489
189014
|
var DREAMER_AGENT = "dreamer";
|
|
@@ -189385,6 +189910,9 @@ function requestValidatedAddress(validation, candidate, options) {
|
|
|
189385
189910
|
}
|
|
189386
189911
|
chunks.push(buf);
|
|
189387
189912
|
});
|
|
189913
|
+
response.on("error", (error51) => {
|
|
189914
|
+
reject(toNetworkError(error51, "response failed"));
|
|
189915
|
+
});
|
|
189388
189916
|
response.on("end", () => {
|
|
189389
189917
|
const status = response.statusCode ?? 0;
|
|
189390
189918
|
if (status >= 500) {
|
|
@@ -190093,14 +190621,21 @@ function toSmartNote(note) {
|
|
|
190093
190621
|
};
|
|
190094
190622
|
}
|
|
190095
190623
|
function commitSmartNoteState(db, args) {
|
|
190624
|
+
db.exec("BEGIN IMMEDIATE");
|
|
190096
190625
|
let leaseLost = false;
|
|
190097
|
-
|
|
190626
|
+
try {
|
|
190098
190627
|
if (args.leaseHeld && !args.leaseHeld()) {
|
|
190099
190628
|
leaseLost = true;
|
|
190100
|
-
|
|
190629
|
+
} else {
|
|
190630
|
+
args.write();
|
|
190101
190631
|
}
|
|
190102
|
-
|
|
190103
|
-
}
|
|
190632
|
+
db.exec("COMMIT");
|
|
190633
|
+
} catch (error51) {
|
|
190634
|
+
try {
|
|
190635
|
+
db.exec("ROLLBACK");
|
|
190636
|
+
} catch {}
|
|
190637
|
+
throw error51;
|
|
190638
|
+
}
|
|
190104
190639
|
if (leaseLost) {
|
|
190105
190640
|
throw new Error(`Dream lease lost during smart-note ${args.phase} commit`);
|
|
190106
190641
|
}
|
|
@@ -190570,7 +191105,7 @@ Output exactly JSON: {"met": false}`;
|
|
|
190570
191105
|
|
|
190571
191106
|
// src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
|
|
190572
191107
|
init_logger();
|
|
190573
|
-
import { existsSync as
|
|
191108
|
+
import { existsSync as existsSync18, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
|
|
190574
191109
|
import { join as join15 } from "node:path";
|
|
190575
191110
|
|
|
190576
191111
|
// src/features/magic-context/dreamer/protected-regions.ts
|
|
@@ -190674,7 +191209,7 @@ function snapshotMaintainDocsFiles(docsDir) {
|
|
|
190674
191209
|
for (const name2 of MAINTAIN_DOCS_SNAPSHOT_FILES) {
|
|
190675
191210
|
const path8 = join15(docsDir, name2);
|
|
190676
191211
|
try {
|
|
190677
|
-
if (
|
|
191212
|
+
if (existsSync18(path8)) {
|
|
190678
191213
|
snapshot.set(name2, readFileSync11(path8, "utf8"));
|
|
190679
191214
|
}
|
|
190680
191215
|
} catch {}
|
|
@@ -190706,7 +191241,7 @@ init_memory();
|
|
|
190706
191241
|
init_subagent_token_capture();
|
|
190707
191242
|
|
|
190708
191243
|
// src/features/magic-context/dreamer/map-memories-prompt.ts
|
|
190709
|
-
import { existsSync as
|
|
191244
|
+
import { existsSync as existsSync19, statSync as statSync6 } from "node:fs";
|
|
190710
191245
|
import path8 from "node:path";
|
|
190711
191246
|
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.
|
|
190712
191247
|
|
|
@@ -190744,7 +191279,7 @@ function extractMemoryCandidatePaths(content, repoDir) {
|
|
|
190744
191279
|
if (!abs.startsWith(`${root}/`))
|
|
190745
191280
|
continue;
|
|
190746
191281
|
try {
|
|
190747
|
-
if (
|
|
191282
|
+
if (existsSync19(abs) && statSync6(abs).isFile())
|
|
190748
191283
|
found.add(rel);
|
|
190749
191284
|
} catch {}
|
|
190750
191285
|
if (found.size >= MAX_SEED_PATHS_PER_MEMORY)
|
|
@@ -192573,8 +193108,8 @@ async function runAgenticTask(config2, ctx, helpers) {
|
|
|
192573
193108
|
const lastRunAt = getTaskScheduleState(db, projectIdentity, config2.task)?.lastRunAt ?? null;
|
|
192574
193109
|
const maintainDocsSnapshot = task === "maintain-docs" ? snapshotMaintainDocsFiles(docsDir) : undefined;
|
|
192575
193110
|
const existingDocs = task === "maintain-docs" ? {
|
|
192576
|
-
architecture:
|
|
192577
|
-
structure:
|
|
193111
|
+
architecture: existsSync20(`${docsDir}/ARCHITECTURE.md`),
|
|
193112
|
+
structure: existsSync20(`${docsDir}/STRUCTURE.md`)
|
|
192578
193113
|
} : undefined;
|
|
192579
193114
|
const userMemories = task === "curate" ? getActiveUserMemories(db).map((um) => ({ id: um.id, content: um.content })) : undefined;
|
|
192580
193115
|
let curateMemories;
|
|
@@ -194741,6 +195276,17 @@ ${c.content}
|
|
|
194741
195276
|
init_send_session_notification();
|
|
194742
195277
|
var recompConfirmationBySession = new Map;
|
|
194743
195278
|
var RECOMP_CONFIRMATION_WINDOW_MS = 60000;
|
|
195279
|
+
function isSubagentSession(db, sessionId) {
|
|
195280
|
+
const meta3 = getOrCreateSessionMeta(db, sessionId);
|
|
195281
|
+
if (meta3.isSubagent)
|
|
195282
|
+
return true;
|
|
195283
|
+
try {
|
|
195284
|
+
const row = db.prepare("SELECT is_subagent FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
195285
|
+
return row?.is_subagent === 1 || row?.is_subagent === true;
|
|
195286
|
+
} catch {
|
|
195287
|
+
return false;
|
|
195288
|
+
}
|
|
195289
|
+
}
|
|
194744
195290
|
var RECOMP_USAGE = [
|
|
194745
195291
|
"Usage:",
|
|
194746
195292
|
"- `/ctx-recomp` — full rebuild from message 1 to the protected tail",
|
|
@@ -194779,6 +195325,22 @@ ${RECOMP_USAGE}`
|
|
|
194779
195325
|
}
|
|
194780
195326
|
return { kind: "partial", range: { start, end } };
|
|
194781
195327
|
}
|
|
195328
|
+
function parseWrapupArgs(raw) {
|
|
195329
|
+
const trimmed = raw.trim();
|
|
195330
|
+
if (trimmed === "")
|
|
195331
|
+
return { ok: true, messagesToKeep: 20 };
|
|
195332
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
195333
|
+
return {
|
|
195334
|
+
ok: false,
|
|
195335
|
+
message: "Usage: `/ctx-wrapup [messages_to_keep]` where messages_to_keep is a positive integer."
|
|
195336
|
+
};
|
|
195337
|
+
}
|
|
195338
|
+
const messagesToKeep = Number.parseInt(trimmed, 10);
|
|
195339
|
+
if (!Number.isSafeInteger(messagesToKeep) || messagesToKeep <= 0) {
|
|
195340
|
+
return { ok: false, message: "messages_to_keep must be a positive integer." };
|
|
195341
|
+
}
|
|
195342
|
+
return { ok: true, messagesToKeep };
|
|
195343
|
+
}
|
|
194782
195344
|
var SENTINEL_PREFIX = "__CONTEXT_MANAGEMENT_";
|
|
194783
195345
|
var HTTP_SERVER_RESPONSE_TYPE_ID = "~effect/http/HttpServerResponse";
|
|
194784
195346
|
var HTTP_COOKIES_TYPE_ID = "~effect/http/Cookies";
|
|
@@ -194920,6 +195482,7 @@ function createMagicContextCommandHandler(deps) {
|
|
|
194920
195482
|
const isStatusCommand = (command) => command === "ctx-status";
|
|
194921
195483
|
const isFlushCommand = (command) => command === "ctx-flush";
|
|
194922
195484
|
const isRecompCommand = (command) => command === "ctx-recomp";
|
|
195485
|
+
const isWrapupCommand = (command) => command === "ctx-wrapup";
|
|
194923
195486
|
const isAugCommand = (command) => command === "ctx-aug";
|
|
194924
195487
|
const isDreamCommand = (command) => command === "ctx-dream";
|
|
194925
195488
|
const isSessionUpgradeCommand = (command) => command === "ctx-session-upgrade";
|
|
@@ -194929,11 +195492,12 @@ function createMagicContextCommandHandler(deps) {
|
|
|
194929
195492
|
const isStatus = isStatusCommand(input.command);
|
|
194930
195493
|
const isFlush = isFlushCommand(input.command);
|
|
194931
195494
|
const isRecomp = isRecompCommand(input.command);
|
|
195495
|
+
const isWrapup = isWrapupCommand(input.command);
|
|
194932
195496
|
const isAug = isAugCommand(input.command);
|
|
194933
195497
|
const isDream = isDreamCommand(input.command);
|
|
194934
195498
|
const isSessionUpgrade = isSessionUpgradeCommand(input.command);
|
|
194935
195499
|
const isEmbed = isEmbedCommand(input.command);
|
|
194936
|
-
if (!isStatus && !isFlush && !isRecomp && !isAug && !isDream && !isSessionUpgrade && !isEmbed) {
|
|
195500
|
+
if (!isStatus && !isFlush && !isRecomp && !isWrapup && !isAug && !isDream && !isSessionUpgrade && !isEmbed) {
|
|
194937
195501
|
return;
|
|
194938
195502
|
}
|
|
194939
195503
|
const sessionId = input.sessionID;
|
|
@@ -195003,6 +195567,26 @@ Embedding status is unavailable.`;
|
|
|
195003
195567
|
|
|
195004
195568
|
${statusOutput}` : statusOutput;
|
|
195005
195569
|
}
|
|
195570
|
+
if (isWrapup) {
|
|
195571
|
+
const parsed = parseWrapupArgs(input.arguments);
|
|
195572
|
+
if (isSubagentSession(deps.db, sessionId)) {
|
|
195573
|
+
result = `## Magic Wrapup — Skipped
|
|
195574
|
+
|
|
195575
|
+
/ctx-wrapup is only available in primary sessions.`;
|
|
195576
|
+
} else if (!parsed.ok) {
|
|
195577
|
+
result = `## Magic Wrapup — Invalid Arguments
|
|
195578
|
+
|
|
195579
|
+
${parsed.message}`;
|
|
195580
|
+
} else if (!deps.executeWrapup) {
|
|
195581
|
+
result = `## Magic Wrapup
|
|
195582
|
+
|
|
195583
|
+
/ctx-wrapup is unavailable because the historian handler is not configured.`;
|
|
195584
|
+
} else {
|
|
195585
|
+
result = await deps.executeWrapup(sessionId, {
|
|
195586
|
+
messagesToKeep: parsed.messagesToKeep
|
|
195587
|
+
});
|
|
195588
|
+
}
|
|
195589
|
+
}
|
|
195006
195590
|
if (isRecomp) {
|
|
195007
195591
|
const parsedArgs = parseRecompArgs(input.arguments);
|
|
195008
195592
|
if (parsedArgs.kind === "error") {
|
|
@@ -195309,7 +195893,8 @@ var canonicalReasons = new Set([
|
|
|
195309
195893
|
"first_render",
|
|
195310
195894
|
"pressure_refold",
|
|
195311
195895
|
"upgrade_state",
|
|
195312
|
-
"cached_m1_missing"
|
|
195896
|
+
"cached_m1_missing",
|
|
195897
|
+
"project_change"
|
|
195313
195898
|
]);
|
|
195314
195899
|
var piReasonAliases = {
|
|
195315
195900
|
project_memory_change: "project_memory_epoch",
|
|
@@ -196240,35 +196825,31 @@ function resolveCtxReduceAvailabilityFromMessages(sessionId, messages) {
|
|
|
196240
196825
|
for (const message of messages) {
|
|
196241
196826
|
if (message.info?.role !== "user")
|
|
196242
196827
|
continue;
|
|
196243
|
-
const verdict = verdictFromToolsMap(message.info.tools);
|
|
196244
|
-
|
|
196245
|
-
|
|
196246
|
-
return verdict;
|
|
196247
|
-
}
|
|
196248
|
-
break;
|
|
196828
|
+
const verdict = verdictFromToolsMap(message.info.tools) ?? true;
|
|
196829
|
+
availabilityBySession.set(sessionId, verdict);
|
|
196830
|
+
return verdict;
|
|
196249
196831
|
}
|
|
196250
|
-
availabilityBySession.set(sessionId, true);
|
|
196251
196832
|
return true;
|
|
196252
196833
|
}
|
|
196253
196834
|
function resolveCtxReduceAvailability(sessionId) {
|
|
196254
196835
|
const cached2 = availabilityBySession.get(sessionId);
|
|
196255
196836
|
if (cached2 !== undefined)
|
|
196256
|
-
return cached2;
|
|
196837
|
+
return { callable: cached2, frozen: true };
|
|
196257
196838
|
if (!openCodeDbExists())
|
|
196258
|
-
return true;
|
|
196839
|
+
return { callable: true, frozen: true };
|
|
196259
196840
|
try {
|
|
196260
196841
|
const row = withReadOnlySessionDb((db) => db.prepare(`SELECT json_extract(data, '$.tools') AS tools FROM message
|
|
196261
196842
|
WHERE session_id = ? AND json_extract(data, '$.role') = 'user'
|
|
196262
196843
|
ORDER BY time_created ASC LIMIT 1`).get(sessionId));
|
|
196263
196844
|
if (!row)
|
|
196264
|
-
return true;
|
|
196845
|
+
return { callable: true, frozen: false };
|
|
196265
196846
|
const verdict = row.tools === null ? null : verdictFromToolsMap(JSON.parse(row.tools));
|
|
196266
196847
|
const resolved = verdict ?? true;
|
|
196267
196848
|
availabilityBySession.set(sessionId, resolved);
|
|
196268
|
-
return resolved;
|
|
196849
|
+
return { callable: resolved, frozen: true };
|
|
196269
196850
|
} catch (error51) {
|
|
196270
196851
|
sessionLog(sessionId, "ctx_reduce availability read failed (fail-open):", error51);
|
|
196271
|
-
return true;
|
|
196852
|
+
return { callable: true, frozen: false };
|
|
196272
196853
|
}
|
|
196273
196854
|
}
|
|
196274
196855
|
|
|
@@ -197957,6 +198538,7 @@ function containsProbeVerbatim(text, probes) {
|
|
|
197957
198538
|
init_memory();
|
|
197958
198539
|
init_embedding();
|
|
197959
198540
|
init_storage_memory_fts();
|
|
198541
|
+
init_storage_notes();
|
|
197960
198542
|
init_storage_primers();
|
|
197961
198543
|
init_workspaces();
|
|
197962
198544
|
var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
|
|
@@ -198360,6 +198942,147 @@ function searchMessages(args) {
|
|
|
198360
198942
|
role: entry.row.role
|
|
198361
198943
|
}));
|
|
198362
198944
|
}
|
|
198945
|
+
var NOTE_SEARCHABLE_STATUSES = ["active", "pending", "ready", "dismissed"];
|
|
198946
|
+
function noteSearchText(note) {
|
|
198947
|
+
const reason = note.readyReason?.trim();
|
|
198948
|
+
return reason ? `${note.content}
|
|
198949
|
+
Reason: ${reason}` : note.content;
|
|
198950
|
+
}
|
|
198951
|
+
function tokenizeKeywordNeedle(text) {
|
|
198952
|
+
const matches = text.toLowerCase().match(/[a-z0-9/._:-]+/g) ?? [];
|
|
198953
|
+
const seen = new Set;
|
|
198954
|
+
const tokens = [];
|
|
198955
|
+
for (const match of matches) {
|
|
198956
|
+
if (match.length <= 1 || !/[a-z0-9]/.test(match) || seen.has(match)) {
|
|
198957
|
+
continue;
|
|
198958
|
+
}
|
|
198959
|
+
seen.add(match);
|
|
198960
|
+
tokens.push(match);
|
|
198961
|
+
}
|
|
198962
|
+
return tokens;
|
|
198963
|
+
}
|
|
198964
|
+
function rankNotesForNeedle(notes, needle) {
|
|
198965
|
+
const normalizedNeedle = needle.trim().toLowerCase();
|
|
198966
|
+
if (normalizedNeedle.length === 0) {
|
|
198967
|
+
return [];
|
|
198968
|
+
}
|
|
198969
|
+
const needleTokens = tokenizeKeywordNeedle(normalizedNeedle);
|
|
198970
|
+
const ranked = [];
|
|
198971
|
+
for (const note of notes) {
|
|
198972
|
+
const text = noteSearchText(note);
|
|
198973
|
+
const normalizedText = text.toLowerCase();
|
|
198974
|
+
const noteTokens = new Set(tokenizeKeywordNeedle(normalizedText));
|
|
198975
|
+
const exact = normalizedText.includes(normalizedNeedle);
|
|
198976
|
+
const matchedTokens = needleTokens.filter((token) => noteTokens.has(token)).length;
|
|
198977
|
+
if (!exact && matchedTokens === 0) {
|
|
198978
|
+
continue;
|
|
198979
|
+
}
|
|
198980
|
+
const coverage = needleTokens.length > 0 ? matchedTokens / needleTokens.length : 0;
|
|
198981
|
+
const score = (exact ? 2 : 0) + coverage + (needleTokens.length > 1 && matchedTokens === needleTokens.length ? 0.5 : 0);
|
|
198982
|
+
ranked.push({ note, score, text });
|
|
198983
|
+
}
|
|
198984
|
+
return ranked.sort((left, right) => {
|
|
198985
|
+
if (right.score !== left.score) {
|
|
198986
|
+
return right.score - left.score;
|
|
198987
|
+
}
|
|
198988
|
+
if (right.note.createdAt !== left.note.createdAt) {
|
|
198989
|
+
return right.note.createdAt - left.note.createdAt;
|
|
198990
|
+
}
|
|
198991
|
+
return left.note.id - right.note.id;
|
|
198992
|
+
});
|
|
198993
|
+
}
|
|
198994
|
+
function searchNotes(args) {
|
|
198995
|
+
if (args.limit <= 0) {
|
|
198996
|
+
return [];
|
|
198997
|
+
}
|
|
198998
|
+
const notes = [
|
|
198999
|
+
...getNotes(args.db, {
|
|
199000
|
+
sessionId: args.sessionId,
|
|
199001
|
+
type: "session",
|
|
199002
|
+
status: NOTE_SEARCHABLE_STATUSES
|
|
199003
|
+
}),
|
|
199004
|
+
...getNotes(args.db, {
|
|
199005
|
+
projectPath: args.projectPath,
|
|
199006
|
+
type: "smart",
|
|
199007
|
+
status: NOTE_SEARCHABLE_STATUSES
|
|
199008
|
+
})
|
|
199009
|
+
];
|
|
199010
|
+
if (notes.length === 0) {
|
|
199011
|
+
return [];
|
|
199012
|
+
}
|
|
199013
|
+
const baseList = rankNotesForNeedle(notes, args.query);
|
|
199014
|
+
const probes = args.probes ?? [];
|
|
199015
|
+
if (probes.length === 0) {
|
|
199016
|
+
const ranked2 = baseList.slice(0, args.limit);
|
|
199017
|
+
return ranked2.map((entry, rank) => ({
|
|
199018
|
+
source: "note",
|
|
199019
|
+
content: previewText(entry.text),
|
|
199020
|
+
score: linearDecayScore(rank, ranked2.length),
|
|
199021
|
+
noteId: entry.note.id,
|
|
199022
|
+
status: entry.note.status,
|
|
199023
|
+
createdAt: entry.note.createdAt,
|
|
199024
|
+
anchorOrdinal: entry.note.anchorOrdinal,
|
|
199025
|
+
sourceSessionId: entry.note.sessionId
|
|
199026
|
+
}));
|
|
199027
|
+
}
|
|
199028
|
+
const queryLists = [];
|
|
199029
|
+
if (baseList.length > 0) {
|
|
199030
|
+
queryLists.push({ rows: baseList, weight: 1 });
|
|
199031
|
+
}
|
|
199032
|
+
const probeWeights = new Map;
|
|
199033
|
+
for (const probe of probes) {
|
|
199034
|
+
const rows = rankNotesForNeedle(notes, probe);
|
|
199035
|
+
if (rows.length === 0) {
|
|
199036
|
+
continue;
|
|
199037
|
+
}
|
|
199038
|
+
const weight = probeDiscriminationWeight(rows.length, notes.length);
|
|
199039
|
+
probeWeights.set(probe, weight);
|
|
199040
|
+
queryLists.push({ rows, weight });
|
|
199041
|
+
}
|
|
199042
|
+
const fused = new Map;
|
|
199043
|
+
for (const list of queryLists) {
|
|
199044
|
+
list.rows.forEach((row, rank) => {
|
|
199045
|
+
const rrf = list.weight / (RRF_K + rank);
|
|
199046
|
+
const existing = fused.get(row.note.id);
|
|
199047
|
+
if (existing) {
|
|
199048
|
+
existing.score += rrf;
|
|
199049
|
+
} else {
|
|
199050
|
+
fused.set(row.note.id, { entry: row, score: rrf });
|
|
199051
|
+
}
|
|
199052
|
+
});
|
|
199053
|
+
}
|
|
199054
|
+
for (const match of fused.values()) {
|
|
199055
|
+
let best = 0;
|
|
199056
|
+
for (const probe of probes) {
|
|
199057
|
+
const weight = probeWeights.get(probe) ?? 0;
|
|
199058
|
+
if (weight > best && containsProbeVerbatim(match.entry.text, [probe])) {
|
|
199059
|
+
best = weight;
|
|
199060
|
+
}
|
|
199061
|
+
}
|
|
199062
|
+
if (best > 0) {
|
|
199063
|
+
match.score += best * VERBATIM_RANK_BONUS;
|
|
199064
|
+
}
|
|
199065
|
+
}
|
|
199066
|
+
const ranked = [...fused.values()].sort((left, right) => {
|
|
199067
|
+
if (right.score !== left.score) {
|
|
199068
|
+
return right.score - left.score;
|
|
199069
|
+
}
|
|
199070
|
+
if (right.entry.note.createdAt !== left.entry.note.createdAt) {
|
|
199071
|
+
return right.entry.note.createdAt - left.entry.note.createdAt;
|
|
199072
|
+
}
|
|
199073
|
+
return left.entry.note.id - right.entry.note.id;
|
|
199074
|
+
}).slice(0, args.limit);
|
|
199075
|
+
return ranked.map((entry, rank) => ({
|
|
199076
|
+
source: "note",
|
|
199077
|
+
content: previewText(entry.entry.text),
|
|
199078
|
+
score: linearDecayScore(rank, ranked.length),
|
|
199079
|
+
noteId: entry.entry.note.id,
|
|
199080
|
+
status: entry.entry.note.status,
|
|
199081
|
+
createdAt: entry.entry.note.createdAt,
|
|
199082
|
+
anchorOrdinal: entry.entry.note.anchorOrdinal,
|
|
199083
|
+
sourceSessionId: entry.entry.note.sessionId
|
|
199084
|
+
}));
|
|
199085
|
+
}
|
|
198363
199086
|
function searchCompartmentChunks(args) {
|
|
198364
199087
|
if (!args.queryEmbedding || args.limit <= 0 || !args.modelId || args.modelId === "off")
|
|
198365
199088
|
return [];
|
|
@@ -198445,6 +199168,8 @@ function getSourceBoost(result) {
|
|
|
198445
199168
|
return GIT_COMMIT_SOURCE_BOOST;
|
|
198446
199169
|
case "primer":
|
|
198447
199170
|
return PRIMER_SOURCE_BOOST;
|
|
199171
|
+
case "note":
|
|
199172
|
+
return 1;
|
|
198448
199173
|
}
|
|
198449
199174
|
}
|
|
198450
199175
|
function compareUnifiedResults(left, right) {
|
|
@@ -198468,6 +199193,9 @@ function compareUnifiedResults(left, right) {
|
|
|
198468
199193
|
if (left.source === "primer" && right.source === "primer") {
|
|
198469
199194
|
return right.support - left.support || left.primerId - right.primerId;
|
|
198470
199195
|
}
|
|
199196
|
+
if (left.source === "note" && right.source === "note") {
|
|
199197
|
+
return right.createdAt - left.createdAt || left.noteId - right.noteId;
|
|
199198
|
+
}
|
|
198471
199199
|
return 0;
|
|
198472
199200
|
}
|
|
198473
199201
|
function toGitCommitResult(hit) {
|
|
@@ -198535,11 +199263,11 @@ function searchPrimers(args) {
|
|
|
198535
199263
|
}
|
|
198536
199264
|
function resolveSources(sources) {
|
|
198537
199265
|
if (sources === undefined) {
|
|
198538
|
-
return new Set(["memory", "message", "git_commit", "primer"]);
|
|
199266
|
+
return new Set(["memory", "message", "git_commit", "primer", "note"]);
|
|
198539
199267
|
}
|
|
198540
199268
|
const set2 = new Set;
|
|
198541
199269
|
for (const source of sources) {
|
|
198542
|
-
if (source === "memory" || source === "message" || source === "git_commit" || source === "primer") {
|
|
199270
|
+
if (source === "memory" || source === "message" || source === "git_commit" || source === "primer" || source === "note") {
|
|
198543
199271
|
set2.add(source);
|
|
198544
199272
|
}
|
|
198545
199273
|
}
|
|
@@ -198562,6 +199290,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
198562
199290
|
const runMessages = activeSources.has("message");
|
|
198563
199291
|
const runGitCommits = activeSources.has("git_commit") && gitCommitsEnabled;
|
|
198564
199292
|
const runPrimers = activeSources.has("primer") && memoryFeatureEnabled;
|
|
199293
|
+
const runNotes = activeSources.has("note");
|
|
198565
199294
|
const runCompartmentChunks = runMessages && memoryFeatureEnabled && embeddingEnabled;
|
|
198566
199295
|
const needsEmbedding = (runMemory || runGitCommits || runCompartmentChunks || runPrimers) && embeddingEnabled && isEmbeddingRuntimeEnabled();
|
|
198567
199296
|
const queryEmbeddingPromise = needsEmbedding ? embedQuery(trimmedQuery, options.signal).catch((error51) => {
|
|
@@ -198597,7 +199326,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
198597
199326
|
compartments: compartmentResults,
|
|
198598
199327
|
limit: tierLimit
|
|
198599
199328
|
});
|
|
198600
|
-
const [memoryResults, gitCommitResults, primerResults] = await Promise.all([
|
|
199329
|
+
const [memoryResults, gitCommitResults, primerResults, noteResults] = await Promise.all([
|
|
198601
199330
|
runMemory ? searchMemories({
|
|
198602
199331
|
db,
|
|
198603
199332
|
projectPath,
|
|
@@ -198624,9 +199353,23 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
198624
199353
|
limit: tierLimit,
|
|
198625
199354
|
queryEmbedding,
|
|
198626
199355
|
queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null
|
|
199356
|
+
})) : Promise.resolve([]),
|
|
199357
|
+
runNotes ? Promise.resolve(searchNotes({
|
|
199358
|
+
db,
|
|
199359
|
+
sessionId,
|
|
199360
|
+
projectPath,
|
|
199361
|
+
query: trimmedQuery,
|
|
199362
|
+
limit: tierLimit,
|
|
199363
|
+
probes: messageProbes
|
|
198627
199364
|
})) : Promise.resolve([])
|
|
198628
199365
|
]);
|
|
198629
|
-
const results = [
|
|
199366
|
+
const results = [
|
|
199367
|
+
...memoryResults,
|
|
199368
|
+
...primerResults,
|
|
199369
|
+
...messageLikeResults,
|
|
199370
|
+
...gitCommitResults,
|
|
199371
|
+
...noteResults
|
|
199372
|
+
].sort(compareUnifiedResults).slice(0, limit);
|
|
198630
199373
|
const countRetrievals = options.countRetrievals ?? true;
|
|
198631
199374
|
if (countRetrievals) {
|
|
198632
199375
|
const memoryIds = results.filter((result) => result.source === "memory").map((result) => result.memoryId);
|
|
@@ -198699,6 +199442,10 @@ function renderFragment(result, charCap) {
|
|
|
198699
199442
|
const compressed = cavemanCompress(result.content, "ultra");
|
|
198700
199443
|
return truncate(compressed, charCap);
|
|
198701
199444
|
}
|
|
199445
|
+
case "note": {
|
|
199446
|
+
const compressed = cavemanCompress(result.content, "ultra");
|
|
199447
|
+
return truncate(compressed, charCap);
|
|
199448
|
+
}
|
|
198702
199449
|
}
|
|
198703
199450
|
}
|
|
198704
199451
|
function buildAutoSearchHint(results, options = {}) {
|
|
@@ -199565,6 +200312,13 @@ var degradedCacheCountBySession = new BoundedSessionMap(100);
|
|
|
199565
200312
|
function resetDegradedCacheCount(sessionId) {
|
|
199566
200313
|
degradedCacheCountBySession.delete(sessionId);
|
|
199567
200314
|
}
|
|
200315
|
+
function pendingMarkerCoveredByConsumedBoundary(pending, injection) {
|
|
200316
|
+
if (!injection)
|
|
200317
|
+
return false;
|
|
200318
|
+
if (pending.endMessageId === injection.compartmentEndMessageId)
|
|
200319
|
+
return true;
|
|
200320
|
+
return pending.ordinal <= injection.compartmentEndMessage;
|
|
200321
|
+
}
|
|
199568
200322
|
function clearPendingCompactionMarkerAfterSuccessfulDrain(args) {
|
|
199569
200323
|
if (clearPendingCompactionMarkerStateIf(args.db, args.sessionId, args.pending)) {
|
|
199570
200324
|
return "cleared";
|
|
@@ -199963,24 +200717,29 @@ async function runPostTransformPhase(args) {
|
|
|
199963
200717
|
if (historyWasConsumedThisPass && args.deferredHistoryWasPendingAtPassStart) {
|
|
199964
200718
|
const pending = getPendingCompactionMarkerState(args.db, args.sessionId);
|
|
199965
200719
|
if (pending) {
|
|
199966
|
-
|
|
199967
|
-
|
|
199968
|
-
|
|
199969
|
-
|
|
199970
|
-
|
|
199971
|
-
|
|
199972
|
-
|
|
199973
|
-
|
|
199974
|
-
|
|
199975
|
-
|
|
199976
|
-
|
|
200720
|
+
if (!pendingMarkerCoveredByConsumedBoundary(pending, args.pendingCompartmentInjection)) {
|
|
200721
|
+
suppressV12HistoryDrain = true;
|
|
200722
|
+
sessionLog(args.sessionId, `compaction-marker drain: pending ordinal ${pending.ordinal} is newer than consumed boundary ${args.pendingCompartmentInjection?.compartmentEndMessage ?? "<none>"}; preserving deferred history refresh signal`);
|
|
200723
|
+
} else {
|
|
200724
|
+
const outcome = applyDeferredCompactionMarker(args.db, args.sessionId, pending, args.sessionDirectory);
|
|
200725
|
+
switch (outcome.kind) {
|
|
200726
|
+
case "applied":
|
|
200727
|
+
case "already-current":
|
|
200728
|
+
case "stale-skip":
|
|
200729
|
+
if (clearPendingCompactionMarkerAfterSuccessfulDrain({
|
|
200730
|
+
db: args.db,
|
|
200731
|
+
sessionId: args.sessionId,
|
|
200732
|
+
pending,
|
|
200733
|
+
deferredHistoryRefreshSessions: args.deferredHistoryRefreshSessions
|
|
200734
|
+
}) === "cas-lost-newer-pending") {
|
|
200735
|
+
suppressV12HistoryDrain = true;
|
|
200736
|
+
}
|
|
200737
|
+
break;
|
|
200738
|
+
case "retryable-failure":
|
|
200739
|
+
sessionLog(args.sessionId, "compaction-marker drain: retryable failure; preserving deferred history refresh signal", outcome.error);
|
|
199977
200740
|
suppressV12HistoryDrain = true;
|
|
199978
|
-
|
|
199979
|
-
|
|
199980
|
-
case "retryable-failure":
|
|
199981
|
-
sessionLog(args.sessionId, "compaction-marker drain: retryable failure; preserving deferred history refresh signal", outcome.error);
|
|
199982
|
-
suppressV12HistoryDrain = true;
|
|
199983
|
-
break;
|
|
200741
|
+
break;
|
|
200742
|
+
}
|
|
199984
200743
|
}
|
|
199985
200744
|
}
|
|
199986
200745
|
}
|
|
@@ -200085,6 +200844,16 @@ function getMessageTokensCache(sessionId) {
|
|
|
200085
200844
|
}
|
|
200086
200845
|
return cache;
|
|
200087
200846
|
}
|
|
200847
|
+
function maybeSendProjectIdentityWarning(deps, sessionId, directory, notificationParams) {
|
|
200848
|
+
if (!deps.client)
|
|
200849
|
+
return;
|
|
200850
|
+
const warning = takeDubiousOwnershipProjectIdentityWarning(directory);
|
|
200851
|
+
if (!warning)
|
|
200852
|
+
return;
|
|
200853
|
+
sendIgnoredMessage(deps.client, sessionId, warning, notificationParams).catch((error51) => {
|
|
200854
|
+
sessionLog(sessionId, `project identity warning delivery failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
200855
|
+
});
|
|
200856
|
+
}
|
|
200088
200857
|
function clearMessageTokensCache(sessionId, messageId) {
|
|
200089
200858
|
if (messageId === undefined) {
|
|
200090
200859
|
messageTokensBySession.delete(sessionId);
|
|
@@ -200159,7 +200928,7 @@ function createTransform(deps) {
|
|
|
200159
200928
|
}
|
|
200160
200929
|
const reducedMode = sessionMeta.isSubagent;
|
|
200161
200930
|
const fullFeatureMode = !reducedMode;
|
|
200162
|
-
const
|
|
200931
|
+
const ctxReduceCallable = resolveCtxReduceAvailabilityFromMessages(sessionId, messages);
|
|
200163
200932
|
let sessionDirectory = deps.directory ?? "";
|
|
200164
200933
|
let sessionDirectoryResolvedFromHost = false;
|
|
200165
200934
|
const cachedDirectory = deps.sessionDirectoryBySession?.get(sessionId);
|
|
@@ -200442,8 +201211,15 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
200442
201211
|
}
|
|
200443
201212
|
}
|
|
200444
201213
|
logTransformTiming(sessionId, "emergencyRecoveryBlock", tFirstPass);
|
|
200445
|
-
const
|
|
201214
|
+
const memoryProjectDirectory = compartmentDirectory || process.cwd();
|
|
201215
|
+
const projectIdentity = deps.memoryConfig?.enabled ? resolveProjectIdentity(memoryProjectDirectory) : undefined;
|
|
201216
|
+
if (deps.memoryConfig?.enabled) {
|
|
201217
|
+
maybeSendProjectIdentityWarning(deps, sessionId, memoryProjectDirectory, notificationParams);
|
|
201218
|
+
}
|
|
200446
201219
|
const sessionProjectIdentity = projectIdentity ?? (sessionDirectory ? resolveProjectIdentity(sessionDirectory) : deps.projectPath);
|
|
201220
|
+
if (sessionDirectory) {
|
|
201221
|
+
maybeSendProjectIdentityWarning(deps, sessionId, sessionDirectory, notificationParams);
|
|
201222
|
+
}
|
|
200447
201223
|
if (sessionProjectIdentity && sessionDirectoryResolvedFromHost && recordedSessionProjectIdentity.get(sessionId) !== sessionProjectIdentity) {
|
|
200448
201224
|
recordSessionProjectIdentity(db, sessionId, sessionProjectIdentity);
|
|
200449
201225
|
recordedSessionProjectIdentity.set(sessionId, sessionProjectIdentity);
|
|
@@ -200501,7 +201277,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
200501
201277
|
const tInitFromDb = performance.now();
|
|
200502
201278
|
deps.tagger.initFromDb(sessionId, db, taggerFloor);
|
|
200503
201279
|
logTransformTiming(sessionId, "tag.initFromDb", tInitFromDb);
|
|
200504
|
-
const skipPrefixInjection = !
|
|
201280
|
+
const skipPrefixInjection = !ctxReduceCallable;
|
|
200505
201281
|
const result = tagMessages(sessionId, messages, deps.tagger, db, {
|
|
200506
201282
|
skipPrefixInjection
|
|
200507
201283
|
});
|
|
@@ -200558,7 +201334,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
200558
201334
|
}
|
|
200559
201335
|
logTransformTiming(sessionId, "replayReasoningClearing", tReplay);
|
|
200560
201336
|
}
|
|
200561
|
-
if (!
|
|
201337
|
+
if (!reducedMode && deps.cavemanTextCompression?.enabled) {
|
|
200562
201338
|
const tCavemanReplay = performance.now();
|
|
200563
201339
|
const replayedCaveman = replayCavemanCompression(sessionId, db, targets, targetsSliceTags);
|
|
200564
201340
|
if (replayedCaveman > 0) {
|
|
@@ -200688,7 +201464,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
200688
201464
|
projectPath: sessionProjectIdentity,
|
|
200689
201465
|
sessionDirectory,
|
|
200690
201466
|
autoSearch: deps.autoSearch,
|
|
200691
|
-
cavemanTextCompression:
|
|
201467
|
+
cavemanTextCompression: !reducedMode ? deps.cavemanTextCompression : undefined,
|
|
200692
201468
|
smartDrops: deps.smartDrops === true,
|
|
200693
201469
|
resolvedProviderID,
|
|
200694
201470
|
historyRefreshSessions: deps.historyRefreshSessions,
|
|
@@ -200844,7 +201620,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
200844
201620
|
sessionLog(sessionId, "conversation_tokens UPDATE failed:", error51);
|
|
200845
201621
|
}
|
|
200846
201622
|
}
|
|
200847
|
-
if (
|
|
201623
|
+
if (ctxReduceCallable && deps.channel1StateBySession) {
|
|
200848
201624
|
try {
|
|
200849
201625
|
const resolvedExecuteThresholdPct = resolveExecuteThreshold(deps.executeThresholdPercentage ?? 65, deps.getModelKey?.(sessionId), 65, {
|
|
200850
201626
|
tokensConfig: deps.executeThresholdTokens,
|
|
@@ -201329,6 +202105,343 @@ function createTextCompleteHandler() {
|
|
|
201329
202105
|
};
|
|
201330
202106
|
}
|
|
201331
202107
|
|
|
202108
|
+
// src/hooks/magic-context/wrapup-orchestrator.ts
|
|
202109
|
+
init_compartment_lease();
|
|
202110
|
+
init_compartment_storage();
|
|
202111
|
+
init_logger();
|
|
202112
|
+
init_rpc_notifications();
|
|
202113
|
+
init_send_session_notification();
|
|
202114
|
+
await __promiseAll([
|
|
202115
|
+
init_storage(),
|
|
202116
|
+
init_compartment_runner(),
|
|
202117
|
+
init_compartment_runner_incremental(),
|
|
202118
|
+
init_protected_tail_boundary(),
|
|
202119
|
+
init_recomp_orchestrator()
|
|
202120
|
+
]);
|
|
202121
|
+
import * as crypto3 from "node:crypto";
|
|
202122
|
+
var WAIT_FOR_LEASE_MS = 1000;
|
|
202123
|
+
function sleep2(ms) {
|
|
202124
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
202125
|
+
}
|
|
202126
|
+
function plural(value, word) {
|
|
202127
|
+
return `${value} ${word}${value === 1 ? "" : "s"}`;
|
|
202128
|
+
}
|
|
202129
|
+
function formatAlreadyRunningMessage(state) {
|
|
202130
|
+
if (!state)
|
|
202131
|
+
return "/ctx-wrapup is already running for this session.";
|
|
202132
|
+
const chunk = state.expectedChunks > 0 ? ` chunk ${state.chunkIndex}/${state.expectedChunks}` : "";
|
|
202133
|
+
const through = state.lastCompartmentEnd > 0 ? ` through message ${state.lastCompartmentEnd}` : "";
|
|
202134
|
+
return `/ctx-wrapup is already running for this session${chunk}${through}. Wait for it to finish, then run /ctx-wrapup again if more history remains.`;
|
|
202135
|
+
}
|
|
202136
|
+
function appendFlushHint(ctx, sessionId, message) {
|
|
202137
|
+
if (ctx.hasPendingNaturalBust?.(sessionId))
|
|
202138
|
+
return message;
|
|
202139
|
+
return `${message} If you want it applied on the very next message, run /ctx-flush first.`;
|
|
202140
|
+
}
|
|
202141
|
+
function buildPlan(ctx, sessionId, messagesToKeep, anchorRawMessageCount) {
|
|
202142
|
+
return resolveWrapupProtectedTailBoundary({
|
|
202143
|
+
db: ctx.db,
|
|
202144
|
+
sessionId,
|
|
202145
|
+
mode: "manual-wrapup",
|
|
202146
|
+
contextLimit: ctx.contextLimit,
|
|
202147
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
202148
|
+
usage: null,
|
|
202149
|
+
usageSource: "manual-none",
|
|
202150
|
+
providerShapeVersion: "opencode-v1",
|
|
202151
|
+
cacheNamespace: `opencode:${sessionId}`,
|
|
202152
|
+
messagesToKeep,
|
|
202153
|
+
anchorRawMessageCount
|
|
202154
|
+
});
|
|
202155
|
+
}
|
|
202156
|
+
function emitWrapupProgress(ctx, sessionId, progress) {
|
|
202157
|
+
const current = ctx.liveSessionState.recompProgressBySession.get(sessionId);
|
|
202158
|
+
ctx.liveSessionState.recompProgressBySession.set(sessionId, {
|
|
202159
|
+
sessionId,
|
|
202160
|
+
kind: "wrapup",
|
|
202161
|
+
phase: "recomp",
|
|
202162
|
+
processedMessages: progress.processedMessages ?? current?.processedMessages ?? 0,
|
|
202163
|
+
totalMessages: progress.totalMessages ?? current?.totalMessages ?? 0,
|
|
202164
|
+
passCount: progress.passCount ?? current?.passCount ?? 0,
|
|
202165
|
+
compartmentsCreated: progress.compartmentsCreated ?? current?.compartmentsCreated ?? 0,
|
|
202166
|
+
startedAt: current?.startedAt ?? Date.now(),
|
|
202167
|
+
updatedAt: Date.now(),
|
|
202168
|
+
note: progress.note
|
|
202169
|
+
});
|
|
202170
|
+
}
|
|
202171
|
+
async function waitForExistingIncrementalRun(sessionId) {
|
|
202172
|
+
const active = getActiveCompartmentRun(sessionId);
|
|
202173
|
+
if (!active)
|
|
202174
|
+
return "ok";
|
|
202175
|
+
if (active.kind === "recomp" || active.kind === "wrapup")
|
|
202176
|
+
return "busy";
|
|
202177
|
+
try {
|
|
202178
|
+
await active.promise;
|
|
202179
|
+
} catch {}
|
|
202180
|
+
return "ok";
|
|
202181
|
+
}
|
|
202182
|
+
async function acquireCompartmentLeaseForWrapup(ctx, sessionId, renewWrapupMarker) {
|
|
202183
|
+
const holderId = crypto3.randomUUID();
|
|
202184
|
+
for (;; ) {
|
|
202185
|
+
const active = getActiveCompartmentRun(sessionId);
|
|
202186
|
+
if (active?.kind === "recomp" || active?.kind === "wrapup")
|
|
202187
|
+
return null;
|
|
202188
|
+
if (active) {
|
|
202189
|
+
emitWrapupProgress(ctx, sessionId, { note: "Waiting for the active historian run…" });
|
|
202190
|
+
try {
|
|
202191
|
+
await active.promise;
|
|
202192
|
+
} catch {}
|
|
202193
|
+
continue;
|
|
202194
|
+
}
|
|
202195
|
+
const lease = acquireCompartmentLease(ctx.db, sessionId, holderId);
|
|
202196
|
+
if (lease)
|
|
202197
|
+
return holderId;
|
|
202198
|
+
emitWrapupProgress(ctx, sessionId, { note: "Waiting for the compartment-state lease…" });
|
|
202199
|
+
if (!renewWrapupMarker({}))
|
|
202200
|
+
return null;
|
|
202201
|
+
await sleep2(WAIT_FOR_LEASE_MS);
|
|
202202
|
+
}
|
|
202203
|
+
}
|
|
202204
|
+
async function runOneWrapupIteration(args) {
|
|
202205
|
+
const { ctx, sessionId, plan, messagesToKeep, anchorRawMessageCount } = args;
|
|
202206
|
+
const leaseHolderId = await acquireCompartmentLeaseForWrapup(ctx, sessionId, args.renewWrapupMarker);
|
|
202207
|
+
if (!leaseHolderId)
|
|
202208
|
+
return false;
|
|
202209
|
+
const renewal = setInterval(() => {
|
|
202210
|
+
try {
|
|
202211
|
+
if (!renewCompartmentLease(ctx.db, sessionId, leaseHolderId)) {
|
|
202212
|
+
sessionLog(sessionId, "wrapup: compartment lease renewal failed");
|
|
202213
|
+
}
|
|
202214
|
+
} catch (err) {
|
|
202215
|
+
sessionLog(sessionId, `wrapup: compartment lease renewal threw; continuing (${err instanceof Error ? err.message : String(err)})`);
|
|
202216
|
+
}
|
|
202217
|
+
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
202218
|
+
const runCompartmentAgentForWrapup = ctx.runCompartmentAgentForWrapup ?? runCompartmentAgent;
|
|
202219
|
+
const runnerPromise = runCompartmentAgentForWrapup({
|
|
202220
|
+
client: ctx.client,
|
|
202221
|
+
db: ctx.db,
|
|
202222
|
+
sessionId,
|
|
202223
|
+
historianChunkTokens: ctx.historianChunkTokens,
|
|
202224
|
+
historianTimeoutMs: ctx.historianTimeoutMs,
|
|
202225
|
+
boundarySnapshot: plan.snapshot,
|
|
202226
|
+
currentContextLimit: ctx.contextLimit,
|
|
202227
|
+
directory: ctx.directory,
|
|
202228
|
+
fallbackModels: ctx.fallbackModels,
|
|
202229
|
+
fallbackModelId: ctx.fallbackModelId,
|
|
202230
|
+
language: ctx.language,
|
|
202231
|
+
historianTwoPass: ctx.historianTwoPass,
|
|
202232
|
+
memoryEnabled: ctx.memoryEnabled,
|
|
202233
|
+
autoPromote: ctx.autoPromote,
|
|
202234
|
+
ensureProjectRegistered: ctx.ensureProjectRegistered,
|
|
202235
|
+
getNotificationParams: () => ctx.getNotificationParams(sessionId),
|
|
202236
|
+
preserveInjectionCacheUntilConsumed: true,
|
|
202237
|
+
compartmentLeaseHolderId: leaseHolderId,
|
|
202238
|
+
forceDrainQuota: true,
|
|
202239
|
+
forceKeepLastCompartment: true,
|
|
202240
|
+
refreshBoundarySnapshot: () => buildPlan(ctx, sessionId, messagesToKeep, anchorRawMessageCount).snapshot,
|
|
202241
|
+
onCompartmentStatePublished: (sid) => {
|
|
202242
|
+
markActiveCompartmentRunPublished(sid);
|
|
202243
|
+
ctx.liveSessionState.deferredHistoryRefreshSessions.add(sid);
|
|
202244
|
+
ctx.liveSessionState.deferredMaterializationSessions.add(sid);
|
|
202245
|
+
},
|
|
202246
|
+
onDeferredMarkerPending: (sid) => {
|
|
202247
|
+
ctx.liveSessionState.deferredHistoryRefreshSessions.add(sid);
|
|
202248
|
+
}
|
|
202249
|
+
});
|
|
202250
|
+
registerActiveCompartmentRun(sessionId, runnerPromise, "wrapup");
|
|
202251
|
+
try {
|
|
202252
|
+
await runnerPromise;
|
|
202253
|
+
return true;
|
|
202254
|
+
} finally {
|
|
202255
|
+
clearInterval(renewal);
|
|
202256
|
+
releaseCompartmentLease(ctx.db, sessionId, leaseHolderId);
|
|
202257
|
+
}
|
|
202258
|
+
}
|
|
202259
|
+
async function runManagedWrapup(ctx, sessionId, options) {
|
|
202260
|
+
const messagesToKeep = Math.max(1, Math.floor(options.messagesToKeep));
|
|
202261
|
+
setRecompStarting(ctx.liveSessionState, sessionId, "Estimating wrapup…", "wrapup");
|
|
202262
|
+
const existingWrapup = getWrapupInProgressState(ctx.db, sessionId);
|
|
202263
|
+
if (existingWrapup) {
|
|
202264
|
+
const message2 = formatAlreadyRunningMessage(existingWrapup);
|
|
202265
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "skipped", message2);
|
|
202266
|
+
return `## Magic Wrapup — Skipped
|
|
202267
|
+
|
|
202268
|
+
${message2}`;
|
|
202269
|
+
}
|
|
202270
|
+
const initialPlan = buildPlan(ctx, sessionId, messagesToKeep);
|
|
202271
|
+
if (initialPlan.rawMessagesAboveLastCompartment <= messagesToKeep || !hasRunnableCompartmentWindow(initialPlan.snapshot)) {
|
|
202272
|
+
const message2 = `Nothing to wrap up — only ${initialPlan.rawMessagesAboveLastCompartment} messages above the last compartment.`;
|
|
202273
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "done", message2);
|
|
202274
|
+
return message2;
|
|
202275
|
+
}
|
|
202276
|
+
const expectedChunks = Math.max(1, Math.ceil(initialPlan.snapshot.trueRawEligibleTokens / Math.max(1, ctx.historianChunkTokens)));
|
|
202277
|
+
const wrapupHolderId = crypto3.randomUUID();
|
|
202278
|
+
const acquired = acquireWrapupInProgress(ctx.db, sessionId, {
|
|
202279
|
+
holderId: wrapupHolderId,
|
|
202280
|
+
messagesToKeep,
|
|
202281
|
+
anchorRawMessageCount: initialPlan.anchorRawMessageCount,
|
|
202282
|
+
targetEligibleEndOrdinal: initialPlan.targetEligibleEndOrdinal,
|
|
202283
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(ctx.db, sessionId),
|
|
202284
|
+
chunkIndex: 0,
|
|
202285
|
+
expectedChunks
|
|
202286
|
+
});
|
|
202287
|
+
if (!acquired.ok) {
|
|
202288
|
+
const message2 = formatAlreadyRunningMessage(acquired.state);
|
|
202289
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "skipped", message2);
|
|
202290
|
+
return `## Magic Wrapup — Skipped
|
|
202291
|
+
|
|
202292
|
+
${message2}`;
|
|
202293
|
+
}
|
|
202294
|
+
const startLastEnd = getLastCompartmentEndMessage(ctx.db, sessionId);
|
|
202295
|
+
const startCompartmentCount = getCompartments(ctx.db, sessionId).length;
|
|
202296
|
+
let chunkIndex = 0;
|
|
202297
|
+
let lastEnd = startLastEnd;
|
|
202298
|
+
let stoppedForFailure = false;
|
|
202299
|
+
let stoppedReason = "";
|
|
202300
|
+
let ownershipLost = false;
|
|
202301
|
+
const ownershipLostReason = "another process took over this session's wrapup.";
|
|
202302
|
+
const markOwnershipLost = () => {
|
|
202303
|
+
if (ownershipLost)
|
|
202304
|
+
return;
|
|
202305
|
+
ownershipLost = true;
|
|
202306
|
+
sessionLog(sessionId, "wrapup: durable marker ownership lost; aborting loop");
|
|
202307
|
+
};
|
|
202308
|
+
const renewWrapupMarker = (updates) => {
|
|
202309
|
+
const updated = updateWrapupInProgress(ctx.db, sessionId, wrapupHolderId, updates);
|
|
202310
|
+
if (!updated) {
|
|
202311
|
+
markOwnershipLost();
|
|
202312
|
+
return false;
|
|
202313
|
+
}
|
|
202314
|
+
return true;
|
|
202315
|
+
};
|
|
202316
|
+
const markerRenewal = setInterval(() => {
|
|
202317
|
+
try {
|
|
202318
|
+
renewWrapupMarker({
|
|
202319
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(ctx.db, sessionId),
|
|
202320
|
+
chunkIndex
|
|
202321
|
+
});
|
|
202322
|
+
} catch (err) {
|
|
202323
|
+
sessionLog(sessionId, `wrapup: marker renewal threw; continuing (${err instanceof Error ? err.message : String(err)})`);
|
|
202324
|
+
}
|
|
202325
|
+
}, 60000);
|
|
202326
|
+
markerRenewal.unref?.();
|
|
202327
|
+
try {
|
|
202328
|
+
const activeAtStart = await waitForExistingIncrementalRun(sessionId);
|
|
202329
|
+
if (activeAtStart === "busy") {
|
|
202330
|
+
const message2 = "Another Magic Context rebuild is already running for this session.";
|
|
202331
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "skipped", message2);
|
|
202332
|
+
return `## Magic Wrapup — Skipped
|
|
202333
|
+
|
|
202334
|
+
${message2}`;
|
|
202335
|
+
}
|
|
202336
|
+
try {
|
|
202337
|
+
sendIgnoredMessage(ctx.client, sessionId, `Magic Wrapup started — compacting about ${plural(expectedChunks, "chunk")} of history. This can take a few minutes; the result posts here when done.`, ctx.getNotificationParams(sessionId));
|
|
202338
|
+
} catch {}
|
|
202339
|
+
try {
|
|
202340
|
+
pushNotification("action", { action: "wrapup-progress-kick" }, sessionId);
|
|
202341
|
+
} catch {}
|
|
202342
|
+
if (ownershipLost) {
|
|
202343
|
+
stoppedForFailure = true;
|
|
202344
|
+
stoppedReason = ownershipLostReason;
|
|
202345
|
+
} else {
|
|
202346
|
+
emitWrapupProgress(ctx, sessionId, {
|
|
202347
|
+
processedMessages: Math.max(0, lastEnd),
|
|
202348
|
+
totalMessages: Math.max(0, initialPlan.targetEligibleEndOrdinal - 1),
|
|
202349
|
+
passCount: 0,
|
|
202350
|
+
compartmentsCreated: 0,
|
|
202351
|
+
note: `Eligible ${plural(initialPlan.snapshot.trueRawEligibleTokens, "token")} across about ${plural(expectedChunks, "chunk")}.`
|
|
202352
|
+
});
|
|
202353
|
+
for (;; ) {
|
|
202354
|
+
if (ownershipLost) {
|
|
202355
|
+
stoppedForFailure = true;
|
|
202356
|
+
stoppedReason = ownershipLostReason;
|
|
202357
|
+
break;
|
|
202358
|
+
}
|
|
202359
|
+
if (!renewWrapupMarker({
|
|
202360
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(ctx.db, sessionId),
|
|
202361
|
+
chunkIndex,
|
|
202362
|
+
expectedChunks
|
|
202363
|
+
})) {
|
|
202364
|
+
stoppedForFailure = true;
|
|
202365
|
+
stoppedReason = ownershipLostReason;
|
|
202366
|
+
break;
|
|
202367
|
+
}
|
|
202368
|
+
const plan = buildPlan(ctx, sessionId, messagesToKeep, initialPlan.anchorRawMessageCount);
|
|
202369
|
+
lastEnd = getLastCompartmentEndMessage(ctx.db, sessionId);
|
|
202370
|
+
if (lastEnd + 1 >= plan.targetEligibleEndOrdinal)
|
|
202371
|
+
break;
|
|
202372
|
+
chunkIndex += 1;
|
|
202373
|
+
emitWrapupProgress(ctx, sessionId, {
|
|
202374
|
+
processedMessages: Math.max(0, lastEnd),
|
|
202375
|
+
totalMessages: Math.max(0, plan.targetEligibleEndOrdinal - 1),
|
|
202376
|
+
passCount: chunkIndex - 1,
|
|
202377
|
+
compartmentsCreated: Math.max(0, getCompartments(ctx.db, sessionId).length - startCompartmentCount),
|
|
202378
|
+
note: `Chunk ${chunkIndex}/${expectedChunks}: messages ${plan.snapshot.offset}-${plan.snapshot.eligibleEndOrdinal - 1}…`
|
|
202379
|
+
});
|
|
202380
|
+
if (!renewWrapupMarker({
|
|
202381
|
+
lastCompartmentEnd: lastEnd,
|
|
202382
|
+
chunkIndex,
|
|
202383
|
+
expectedChunks,
|
|
202384
|
+
targetEligibleEndOrdinal: plan.targetEligibleEndOrdinal
|
|
202385
|
+
})) {
|
|
202386
|
+
stoppedForFailure = true;
|
|
202387
|
+
stoppedReason = ownershipLostReason;
|
|
202388
|
+
break;
|
|
202389
|
+
}
|
|
202390
|
+
const beforeEnd = lastEnd;
|
|
202391
|
+
const beforeFailures = getHistorianFailureState(ctx.db, sessionId).failureCount;
|
|
202392
|
+
const ran = await runOneWrapupIteration({
|
|
202393
|
+
ctx,
|
|
202394
|
+
sessionId,
|
|
202395
|
+
plan,
|
|
202396
|
+
messagesToKeep,
|
|
202397
|
+
anchorRawMessageCount: initialPlan.anchorRawMessageCount,
|
|
202398
|
+
renewWrapupMarker
|
|
202399
|
+
});
|
|
202400
|
+
if (!ran) {
|
|
202401
|
+
stoppedForFailure = true;
|
|
202402
|
+
stoppedReason = ownershipLost ? ownershipLostReason : "Another Magic Context rebuild started while wrapup was waiting.";
|
|
202403
|
+
break;
|
|
202404
|
+
}
|
|
202405
|
+
const afterEnd = getLastCompartmentEndMessage(ctx.db, sessionId);
|
|
202406
|
+
const afterFailures = getHistorianFailureState(ctx.db, sessionId).failureCount;
|
|
202407
|
+
if (afterEnd <= beforeEnd) {
|
|
202408
|
+
stoppedForFailure = true;
|
|
202409
|
+
stoppedReason = afterFailures > beforeFailures ? "The historian failed on the current chunk." : "The historian made no forward progress on the current chunk.";
|
|
202410
|
+
break;
|
|
202411
|
+
}
|
|
202412
|
+
lastEnd = afterEnd;
|
|
202413
|
+
emitWrapupProgress(ctx, sessionId, {
|
|
202414
|
+
processedMessages: Math.max(0, lastEnd),
|
|
202415
|
+
totalMessages: Math.max(0, plan.targetEligibleEndOrdinal - 1),
|
|
202416
|
+
passCount: chunkIndex,
|
|
202417
|
+
compartmentsCreated: Math.max(0, getCompartments(ctx.db, sessionId).length - startCompartmentCount),
|
|
202418
|
+
note: `Wrapped through message ${lastEnd}.`
|
|
202419
|
+
});
|
|
202420
|
+
}
|
|
202421
|
+
}
|
|
202422
|
+
} finally {
|
|
202423
|
+
clearInterval(markerRenewal);
|
|
202424
|
+
releaseWrapupInProgress(ctx.db, sessionId, wrapupHolderId);
|
|
202425
|
+
}
|
|
202426
|
+
const finalEnd = getLastCompartmentEndMessage(ctx.db, sessionId);
|
|
202427
|
+
const compartmentsCreated = Math.max(0, getCompartments(ctx.db, sessionId).length - startCompartmentCount);
|
|
202428
|
+
const messagesWrapped = Math.max(0, finalEnd - Math.max(0, startLastEnd));
|
|
202429
|
+
if (stoppedForFailure) {
|
|
202430
|
+
const message2 = `Wrapped up through message ${Math.max(0, finalEnd)} (${plural(messagesWrapped, "message")} into ${plural(compartmentsCreated, "compartment")}). ${stoppedReason} Run /ctx-wrapup again to continue.`;
|
|
202431
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "failed", message2);
|
|
202432
|
+
return `## Magic Wrapup — Partial
|
|
202433
|
+
|
|
202434
|
+
${message2}`;
|
|
202435
|
+
}
|
|
202436
|
+
try {
|
|
202437
|
+
clearEmergencyRecovery(ctx.db, sessionId);
|
|
202438
|
+
} catch {}
|
|
202439
|
+
const base = `Wrapped up ${messagesWrapped} messages into ${compartmentsCreated} compartments. The compacted history is queued and materializes on your next message.`;
|
|
202440
|
+
const message = appendFlushHint(ctx, sessionId, base);
|
|
202441
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "done", message);
|
|
202442
|
+
return message;
|
|
202443
|
+
}
|
|
202444
|
+
|
|
201332
202445
|
// src/hooks/magic-context/hook.ts
|
|
201333
202446
|
await init_compaction_marker_manager();
|
|
201334
202447
|
|
|
@@ -201667,7 +202780,7 @@ Drop silently — do not narrate it. NEVER drop large ranges blindly (e.g., "1-5
|
|
|
201667
202780
|
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.`;
|
|
201668
202781
|
var CAVEMAN_COMPRESSION_WARNING = `
|
|
201669
202782
|
**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.`;
|
|
201670
|
-
function buildMagicContextSection(_agent, protectedTags,
|
|
202783
|
+
function buildMagicContextSection(_agent, protectedTags, ctxReduceCallable = true, dreamerEnabled = false, temporalAwarenessEnabled = false, cavemanTextCompressionEnabled = false, subagentMode = false, language, memoryEnabled = true) {
|
|
201671
202784
|
if (subagentMode) {
|
|
201672
202785
|
return `## Magic Context
|
|
201673
202786
|
|
|
@@ -201678,12 +202791,12 @@ When \`surface_condition\` is provided with \`write\`, the note becomes a projec
|
|
|
201678
202791
|
The dreamer evaluates smart note conditions during nightly runs and surfaces them when conditions are met.
|
|
201679
202792
|
Example: \`ctx_note(action="write", content="Implement X because Y", surface_condition="When PR #42 is merged in this repo")\`` : "";
|
|
201680
202793
|
const temporalGuidance = temporalAwarenessEnabled ? TEMPORAL_AWARENESS_GUIDANCE : "";
|
|
201681
|
-
const cavemanWarning = cavemanTextCompressionEnabled
|
|
202794
|
+
const cavemanWarning = cavemanTextCompressionEnabled ? CAVEMAN_COMPRESSION_WARNING : "";
|
|
201682
202795
|
const languageDirective = buildPrimaryLanguageDirective(language);
|
|
201683
202796
|
const languageGuidance = languageDirective ? `
|
|
201684
202797
|
|
|
201685
202798
|
${languageDirective}` : "";
|
|
201686
|
-
if (!
|
|
202799
|
+
if (!ctxReduceCallable) {
|
|
201687
202800
|
return `## Magic Context
|
|
201688
202801
|
|
|
201689
202802
|
${LONG_TERM_PARTNER_FRAME}
|
|
@@ -201696,7 +202809,7 @@ ${BASE_INTRO_NO_REDUCE(memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${c
|
|
|
201696
202809
|
${LONG_TERM_PARTNER_FRAME}
|
|
201697
202810
|
${PARTNER_FRAME_CLOSER_REDUCE}
|
|
201698
202811
|
|
|
201699
|
-
${BASE_INTRO(protectedTags, memoryEnabled)}${smartNoteGuidance}${temporalGuidance}
|
|
202812
|
+
${BASE_INTRO(protectedTags, memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}
|
|
201700
202813
|
${GENERIC_SECTION}
|
|
201701
202814
|
|
|
201702
202815
|
Prefer many small targeted operations over one large blanket operation, and keep the working set tidy as routine maintenance.${languageGuidance}`;
|
|
@@ -201749,17 +202862,18 @@ function createSystemPromptHashHandler(deps) {
|
|
|
201749
202862
|
} catch (error51) {
|
|
201750
202863
|
sessionLog(sessionId, "system-prompt-hash session meta load failed:", error51);
|
|
201751
202864
|
}
|
|
201752
|
-
const
|
|
201753
|
-
const
|
|
201754
|
-
const
|
|
201755
|
-
const
|
|
201756
|
-
const
|
|
202865
|
+
const isSubagentSession2 = sessionMetaEarly?.isSubagent === true;
|
|
202866
|
+
const availability = resolveCtxReduceAvailability(sessionId);
|
|
202867
|
+
const ctxReduceCallable = availability.callable;
|
|
202868
|
+
const subagentReduceMode = isSubagentSession2 && ctxReduceCallable;
|
|
202869
|
+
const effectiveCtxReduceEnabled = isSubagentSession2 ? false : ctxReduceCallable;
|
|
202870
|
+
const skipGuidanceForDisabledSubagent = isSubagentSession2 && !ctxReduceCallable;
|
|
201757
202871
|
const fullPrompt = output.system.join(`
|
|
201758
202872
|
`);
|
|
201759
202873
|
if (fullPrompt.length > 0 && !fullPrompt.includes(MAGIC_CONTEXT_MARKER) && !skipGuidanceForDisabledSubagent) {
|
|
201760
202874
|
const guidance = buildMagicContextSection(null, deps.protectedTags, effectiveCtxReduceEnabled, deps.dreamerEnabled, deps.experimentalTemporalAwareness, deps.experimentalCavemanTextCompression, subagentReduceMode, deps.language, deps.memoryEnabled !== false);
|
|
201761
202875
|
output.system.push(guidance);
|
|
201762
|
-
sessionLog(sessionId, `injected generic guidance into system prompt (ctxReduce=${effectiveCtxReduceEnabled}, subagent=${
|
|
202876
|
+
sessionLog(sessionId, `injected generic guidance into system prompt (ctxReduce=${effectiveCtxReduceEnabled}, subagent=${isSubagentSession2}, subagentReduceMode=${subagentReduceMode})`);
|
|
201763
202877
|
}
|
|
201764
202878
|
const isCacheBusting = deps.systemPromptRefreshSessions.has(sessionId);
|
|
201765
202879
|
const DATE_PATTERN = /Today's date: .+/;
|
|
@@ -201786,6 +202900,8 @@ function createSystemPromptHashHandler(deps) {
|
|
|
201786
202900
|
`);
|
|
201787
202901
|
if (systemContent.length === 0)
|
|
201788
202902
|
return;
|
|
202903
|
+
if (!availability.frozen)
|
|
202904
|
+
return;
|
|
201789
202905
|
const currentHash = createHash13("md5").update(systemContent).digest("hex");
|
|
201790
202906
|
if (!sessionMetaEarly) {
|
|
201791
202907
|
return;
|
|
@@ -201974,7 +203090,7 @@ function createMagicContextHook(deps) {
|
|
|
201974
203090
|
notifyMagicContextDisabled(deps.client, reason);
|
|
201975
203091
|
return null;
|
|
201976
203092
|
}
|
|
201977
|
-
const projectPath =
|
|
203093
|
+
const projectPath = resolveProjectIdentityOrFallback(deps.directory);
|
|
201978
203094
|
try {
|
|
201979
203095
|
checkCompactionMarkerConsistency(db);
|
|
201980
203096
|
} catch (error51) {
|
|
@@ -201985,20 +203101,21 @@ function createMagicContextHook(deps) {
|
|
|
201985
203101
|
const historianFallbackModels = resolveFallbackChain(deps.config.historian?.fallback_models);
|
|
201986
203102
|
const historyRefreshSessions = deps.liveSessionState?.historyRefreshSessions ?? new Set;
|
|
201987
203103
|
const deferredHistoryRefreshSessions = deps.liveSessionState?.deferredHistoryRefreshSessions ?? new Set;
|
|
203104
|
+
const systemPromptRefreshSessions = deps.liveSessionState?.systemPromptRefreshSessions ?? new Set;
|
|
203105
|
+
const pendingMaterializationSessions = deps.liveSessionState?.pendingMaterializationSessions ?? new Set;
|
|
203106
|
+
const deferredMaterializationSessions = deps.liveSessionState?.deferredMaterializationSessions ?? new Set;
|
|
201988
203107
|
try {
|
|
201989
203108
|
const sessionsWithPending = getSessionsWithPendingMarker(db);
|
|
201990
203109
|
if (sessionsWithPending.length > 0) {
|
|
201991
203110
|
for (const sid of sessionsWithPending) {
|
|
201992
203111
|
deferredHistoryRefreshSessions.add(sid);
|
|
203112
|
+
deferredMaterializationSessions.add(sid);
|
|
201993
203113
|
}
|
|
201994
203114
|
log(`[magic-context] rehydrated ${sessionsWithPending.length} session(s) with pending compaction-marker drain at hook init`);
|
|
201995
203115
|
}
|
|
201996
203116
|
} catch (error51) {
|
|
201997
203117
|
log("[magic-context] hook init: pending-marker rehydration failed:", error51);
|
|
201998
203118
|
}
|
|
201999
|
-
const systemPromptRefreshSessions = deps.liveSessionState?.systemPromptRefreshSessions ?? new Set;
|
|
202000
|
-
const pendingMaterializationSessions = deps.liveSessionState?.pendingMaterializationSessions ?? new Set;
|
|
202001
|
-
const deferredMaterializationSessions = deps.liveSessionState?.deferredMaterializationSessions ?? new Set;
|
|
202002
203119
|
const lastHeuristicsTurnId = new Map;
|
|
202003
203120
|
const commitSeenLastPass = new Map;
|
|
202004
203121
|
const variantBySession = deps.liveSessionState?.variantBySession ?? new Map;
|
|
@@ -202019,7 +203136,15 @@ function createMagicContextHook(deps) {
|
|
|
202019
203136
|
}
|
|
202020
203137
|
return;
|
|
202021
203138
|
};
|
|
202022
|
-
const
|
|
203139
|
+
const maybeSendProjectIdentitySessionWarning = (sessionId, directory) => {
|
|
203140
|
+
const warning = takeDubiousOwnershipProjectIdentityWarning(directory);
|
|
203141
|
+
if (!warning)
|
|
203142
|
+
return;
|
|
203143
|
+
const notificationParams = getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession, deps.config.toast_duration_ms);
|
|
203144
|
+
sendIgnoredMessage(deps.client, sessionId, warning, notificationParams).catch((error51) => {
|
|
203145
|
+
log(`[magic-context] failed to send project identity warning for ${directory}: ${getErrorMessage(error51)}`);
|
|
203146
|
+
});
|
|
203147
|
+
};
|
|
202023
203148
|
const dreamerRunnable = isDreamerRunnable(deps.config);
|
|
202024
203149
|
const dreamerConfig = dreamerRunnable ? deps.config.dreamer : undefined;
|
|
202025
203150
|
const historianRunnable = isHistorianRunnable(deps.config);
|
|
@@ -202056,6 +203181,23 @@ function createMagicContextHook(deps) {
|
|
|
202056
203181
|
ensureProjectRegistered: ensureProjectRegisteredFromOpenCodeDirectory,
|
|
202057
203182
|
getNotificationParams: (sid) => getLiveNotificationParams(sid, liveModelBySession, variantBySession, agentBySession, deps.config.toast_duration_ms)
|
|
202058
203183
|
});
|
|
203184
|
+
const buildManagedWrapupCtx = (sessionId) => ({
|
|
203185
|
+
...buildManagedRecompCtx(sessionId),
|
|
203186
|
+
contextLimit: (() => {
|
|
203187
|
+
const model = resolveLiveModel(sessionId);
|
|
203188
|
+
return model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
|
|
203189
|
+
})(),
|
|
203190
|
+
executeThresholdPercentage: (() => {
|
|
203191
|
+
const model = resolveLiveModel(sessionId);
|
|
203192
|
+
const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
|
|
203193
|
+
return resolveExecuteThresholdDetail(deps.config.execute_threshold_percentage ?? 65, model ? `${model.providerID}/${model.modelID}` : undefined, 65, {
|
|
203194
|
+
tokensConfig: deps.config.execute_threshold_tokens,
|
|
203195
|
+
contextLimit,
|
|
203196
|
+
sessionId
|
|
203197
|
+
}).percentage;
|
|
203198
|
+
})(),
|
|
203199
|
+
hasPendingNaturalBust: (sid) => historyRefreshSessions.has(sid) || systemPromptRefreshSessions.has(sid) || pendingMaterializationSessions.has(sid)
|
|
203200
|
+
});
|
|
202059
203201
|
const executeEmbedHistory = async (sessionId, options) => {
|
|
202060
203202
|
if (deps.config.memory?.enabled === false) {
|
|
202061
203203
|
return "Memory is disabled for this project, so there is no semantic embedding to backfill.";
|
|
@@ -202066,7 +203208,8 @@ function createMagicContextHook(deps) {
|
|
|
202066
203208
|
return "Embedding is already running for this session.";
|
|
202067
203209
|
}
|
|
202068
203210
|
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
202069
|
-
const sessionProjectIdentity =
|
|
203211
|
+
const sessionProjectIdentity = resolveProjectIdentityOrFallback(directory);
|
|
203212
|
+
maybeSendProjectIdentitySessionWarning(sessionId, directory);
|
|
202070
203213
|
embedPauseBySession.delete(sessionId);
|
|
202071
203214
|
const prior = embedRunStateBySession.get(sessionId);
|
|
202072
203215
|
if (prior)
|
|
@@ -202131,13 +203274,15 @@ function createMagicContextHook(deps) {
|
|
|
202131
203274
|
if (ctrl)
|
|
202132
203275
|
ctrl.abort();
|
|
202133
203276
|
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
202134
|
-
const sessionProjectIdentity =
|
|
203277
|
+
const sessionProjectIdentity = resolveProjectIdentityOrFallback(directory);
|
|
203278
|
+
maybeSendProjectIdentitySessionWarning(sessionId, directory);
|
|
202135
203279
|
const cov = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
202136
203280
|
return `Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`;
|
|
202137
203281
|
};
|
|
202138
203282
|
const getEmbedStatusText = (sessionId) => {
|
|
202139
203283
|
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
202140
|
-
const sessionProjectIdentity =
|
|
203284
|
+
const sessionProjectIdentity = resolveProjectIdentityOrFallback(directory);
|
|
203285
|
+
maybeSendProjectIdentitySessionWarning(sessionId, directory);
|
|
202141
203286
|
const coverage = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
202142
203287
|
const progress = recompProgressBySession.get(sessionId);
|
|
202143
203288
|
const drainUi = getEmbedDrainUiStatus(sessionId, progress);
|
|
@@ -202160,7 +203305,8 @@ function createMagicContextHook(deps) {
|
|
|
202160
203305
|
try {
|
|
202161
203306
|
await new Promise((resolve4) => setTimeout(resolve4, 0));
|
|
202162
203307
|
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
202163
|
-
const sessionProjectIdentity =
|
|
203308
|
+
const sessionProjectIdentity = resolveProjectIdentityOrFallback(directory);
|
|
203309
|
+
maybeSendProjectIdentitySessionWarning(sessionId, directory);
|
|
202164
203310
|
const coverage = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
202165
203311
|
if (!coverage.enabled)
|
|
202166
203312
|
return;
|
|
@@ -202194,7 +203340,6 @@ function createMagicContextHook(deps) {
|
|
|
202194
203340
|
db,
|
|
202195
203341
|
channel1StateBySession,
|
|
202196
203342
|
protectedTags: deps.config.protected_tags,
|
|
202197
|
-
ctxReduceEnabled,
|
|
202198
203343
|
smartDrops: deps.config.smart_drops === true,
|
|
202199
203344
|
clearReasoningAge: deps.config.clear_reasoning_age ?? 50,
|
|
202200
203345
|
commitClusterTrigger: deps.config.commit_cluster_trigger,
|
|
@@ -202243,7 +203388,7 @@ function createMagicContextHook(deps) {
|
|
|
202243
203388
|
directory: deps.directory,
|
|
202244
203389
|
ensureProjectRegistered: ensureProjectRegisteredFromOpenCodeDirectory
|
|
202245
203390
|
} : undefined,
|
|
202246
|
-
cavemanTextCompression:
|
|
203391
|
+
cavemanTextCompression: deps.config.caveman_text_compression?.enabled === true ? {
|
|
202247
203392
|
enabled: true,
|
|
202248
203393
|
minChars: deps.config.caveman_text_compression.min_chars ?? 500
|
|
202249
203394
|
} : undefined,
|
|
@@ -202331,6 +203476,7 @@ function createMagicContextHook(deps) {
|
|
|
202331
203476
|
systemPromptRefreshSessions.add(sessionId);
|
|
202332
203477
|
pendingMaterializationSessions.add(sessionId);
|
|
202333
203478
|
},
|
|
203479
|
+
executeWrapup: historianRunnable ? async (sessionId, options) => runManagedWrapup(buildManagedWrapupCtx(sessionId), sessionId, options) : undefined,
|
|
202334
203480
|
executeRecomp: historianRunnable ? async (sessionId, options) => runManagedRecomp(buildManagedRecompCtx(sessionId), sessionId, options) : undefined,
|
|
202335
203481
|
runUpgrade: historianRunnable ? async (sessionId) => runManagedUpgrade(buildManagedRecompCtx(sessionId), sessionId) : undefined,
|
|
202336
203482
|
executeEmbedHistory,
|
|
@@ -202374,7 +203520,6 @@ function createMagicContextHook(deps) {
|
|
|
202374
203520
|
const systemPromptHash = createSystemPromptHashHandler({
|
|
202375
203521
|
db,
|
|
202376
203522
|
protectedTags: deps.config.protected_tags,
|
|
202377
|
-
ctxReduceEnabled,
|
|
202378
203523
|
dreamerEnabled: dreamerRunnable,
|
|
202379
203524
|
memoryEnabled: deps.config.memory?.enabled !== false,
|
|
202380
203525
|
language: deps.config.language,
|
|
@@ -202389,7 +203534,7 @@ function createMagicContextHook(deps) {
|
|
|
202389
203534
|
internalChildSessions,
|
|
202390
203535
|
experimentalUserMemories: userMemoryCollectionEnabled(deps.config.dreamer),
|
|
202391
203536
|
experimentalTemporalAwareness: deps.config.temporal_awareness === true,
|
|
202392
|
-
experimentalCavemanTextCompression:
|
|
203537
|
+
experimentalCavemanTextCompression: deps.config.caveman_text_compression?.enabled === true
|
|
202393
203538
|
});
|
|
202394
203539
|
const systemPromptHashHandler = systemPromptHash.handler;
|
|
202395
203540
|
const eventHook = createEventHook({
|
|
@@ -202408,8 +203553,7 @@ function createMagicContextHook(deps) {
|
|
|
202408
203553
|
lastHeuristicsTurnId,
|
|
202409
203554
|
commitSeenLastPass,
|
|
202410
203555
|
client: deps.client,
|
|
202411
|
-
protectedTags: deps.config.protected_tags
|
|
202412
|
-
ctxReduceEnabled
|
|
203556
|
+
protectedTags: deps.config.protected_tags
|
|
202413
203557
|
});
|
|
202414
203558
|
return {
|
|
202415
203559
|
"experimental.chat.messages.transform": transform2,
|
|
@@ -202424,7 +203568,6 @@ function createMagicContextHook(deps) {
|
|
|
202424
203568
|
systemPromptRefreshSessions,
|
|
202425
203569
|
pendingMaterializationSessions,
|
|
202426
203570
|
lastHeuristicsTurnId,
|
|
202427
|
-
ctxReduceEnabled,
|
|
202428
203571
|
upgradeReminder: historianRunnable ? (sessionId) => maybeSendUpgradeReminder({
|
|
202429
203572
|
client: deps.client,
|
|
202430
203573
|
db,
|
|
@@ -202456,7 +203599,6 @@ function createMagicContextHook(deps) {
|
|
|
202456
203599
|
function buildMagicContextHookConfig(pluginConfig) {
|
|
202457
203600
|
return {
|
|
202458
203601
|
protected_tags: pluginConfig.protected_tags ?? DEFAULT_PROTECTED_TAGS,
|
|
202459
|
-
ctx_reduce_enabled: pluginConfig.ctx_reduce_enabled,
|
|
202460
203602
|
cache_ttl: pluginConfig.cache_ttl,
|
|
202461
203603
|
clear_reasoning_age: pluginConfig.clear_reasoning_age,
|
|
202462
203604
|
toast_duration_ms: pluginConfig.toast_duration_ms,
|
|
@@ -202977,7 +204119,6 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
|
|
|
202977
204119
|
contextLimit: 0,
|
|
202978
204120
|
systemPromptTokens: 0,
|
|
202979
204121
|
compartmentCount: 0,
|
|
202980
|
-
factCount: 0,
|
|
202981
204122
|
memoryCount: 0,
|
|
202982
204123
|
memoryBlockCount: 0,
|
|
202983
204124
|
pendingOpsCount: 0,
|
|
@@ -203016,7 +204157,6 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
|
|
|
203016
204157
|
const memoryBlockCount = meta3 ? Number(meta3.memory_block_count ?? 0) : 0;
|
|
203017
204158
|
const compartmentRow = db.prepare("SELECT COUNT(*) as count FROM compartments WHERE session_id = ?").get(sessionId);
|
|
203018
204159
|
const compartmentCount = compartmentRow?.count ?? 0;
|
|
203019
|
-
const factCount = 0;
|
|
203020
204160
|
let memoryCount = 0;
|
|
203021
204161
|
if (projectIdentity) {
|
|
203022
204162
|
const memRow = db.prepare("SELECT COUNT(*) as count FROM memories WHERE project_path = ? AND status = 'active'").get(projectIdentity);
|
|
@@ -203123,7 +204263,6 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
|
|
|
203123
204263
|
contextLimit,
|
|
203124
204264
|
systemPromptTokens: calibrated.systemTokens,
|
|
203125
204265
|
compartmentCount,
|
|
203126
|
-
factCount,
|
|
203127
204266
|
memoryCount,
|
|
203128
204267
|
memoryBlockCount,
|
|
203129
204268
|
pendingOpsCount,
|
|
@@ -204136,8 +205275,8 @@ function createCtxMemoryTool(deps) {
|
|
|
204136
205275
|
}
|
|
204137
205276
|
});
|
|
204138
205277
|
const idList = targets.map((t) => t.memoryId).join(", ");
|
|
204139
|
-
const
|
|
204140
|
-
return args.reason?.trim() ? `Archived ${
|
|
205278
|
+
const plural2 = targets.length > 1 ? "memories" : "memory";
|
|
205279
|
+
return args.reason?.trim() ? `Archived ${plural2} [ID: ${idList}] (${args.reason.trim()}).` : `Archived ${plural2} [ID: ${idList}].`;
|
|
204141
205280
|
}
|
|
204142
205281
|
return "Error: Unknown action.";
|
|
204143
205282
|
}
|
|
@@ -204542,10 +205681,12 @@ Sources (omit for a broad search across all):
|
|
|
204542
205681
|
- memory: curated cross-session project knowledge — rules, constraints, conventions.
|
|
204543
205682
|
- 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).
|
|
204544
205683
|
- git_commit: this repository's commit history.
|
|
205684
|
+
- note: parked decisions, follow-ups, and dismissed notes with their recorded text.
|
|
204545
205685
|
|
|
204546
205686
|
Picking sources:
|
|
204547
205687
|
- "when did this change / was this working before" → ["git_commit", "message"]
|
|
204548
205688
|
- "did we discuss this earlier" → ["message"]
|
|
205689
|
+
- "did we decide something about this / leave a follow-up" → ["note"]
|
|
204549
205690
|
- "what's our convention / rule for X" → ["memory"]`;
|
|
204550
205691
|
var DEFAULT_CTX_SEARCH_LIMIT = 10;
|
|
204551
205692
|
// src/tools/ctx-search/tools.ts
|
|
@@ -204557,7 +205698,8 @@ var VALID_SOURCES = new Set([
|
|
|
204557
205698
|
"memory",
|
|
204558
205699
|
"message",
|
|
204559
205700
|
"git_commit",
|
|
204560
|
-
"primer"
|
|
205701
|
+
"primer",
|
|
205702
|
+
"note"
|
|
204561
205703
|
]);
|
|
204562
205704
|
function normalizeLimit3(limit) {
|
|
204563
205705
|
if (typeof limit !== "number" || !Number.isFinite(limit)) {
|
|
@@ -204600,7 +205742,8 @@ function formatAge2(committedAtMs) {
|
|
|
204600
205742
|
const years = Math.floor(days / 365);
|
|
204601
205743
|
return years === 1 ? "1y ago" : `${years}y ago`;
|
|
204602
205744
|
}
|
|
204603
|
-
|
|
205745
|
+
var NOTE_EXPAND_HINT = "Use ctx_expand(start=N-10, end=N) around any note @msg anchor above to read the surrounding conversation context.";
|
|
205746
|
+
function formatResult(result, index, currentSessionId) {
|
|
204604
205747
|
if (result.source === "memory") {
|
|
204605
205748
|
const source = result.sourceName ? ` source=${result.sourceName}` : "";
|
|
204606
205749
|
return [
|
|
@@ -204621,6 +205764,14 @@ function formatResult(result, index) {
|
|
|
204621
205764
|
`[${index}] [primer] score=${result.score.toFixed(2)} id=${result.primerId} support=${result.support} match=${result.matchType}`,
|
|
204622
205765
|
result.content
|
|
204623
205766
|
].join(`
|
|
205767
|
+
`);
|
|
205768
|
+
}
|
|
205769
|
+
if (result.source === "note") {
|
|
205770
|
+
const anchor = result.anchorOrdinal !== null && result.sourceSessionId === currentSessionId ? ` @msg ${result.anchorOrdinal}` : "";
|
|
205771
|
+
return [
|
|
205772
|
+
`[${index}] [note] score=${result.score.toFixed(2)} id=#${result.noteId} status=${result.status} ${formatAge2(result.createdAt)}${anchor}`,
|
|
205773
|
+
result.content
|
|
205774
|
+
].join(`
|
|
204624
205775
|
`);
|
|
204625
205776
|
}
|
|
204626
205777
|
if (result.source === "compartment") {
|
|
@@ -204638,14 +205789,17 @@ function formatResult(result, index) {
|
|
|
204638
205789
|
].join(`
|
|
204639
205790
|
`);
|
|
204640
205791
|
}
|
|
204641
|
-
function formatSearchResults(query, results) {
|
|
205792
|
+
function formatSearchResults(query, results, currentSessionId) {
|
|
204642
205793
|
if (results.length === 0) {
|
|
204643
|
-
return `No results found for "${query}" across memories, primers, git commits, or message history.`;
|
|
205794
|
+
return `No results found for "${query}" across notes, memories, primers, git commits, or message history.`;
|
|
204644
205795
|
}
|
|
204645
|
-
const bodyParts = results.map((result, index) => formatResult(result, index + 1));
|
|
205796
|
+
const bodyParts = results.map((result, index) => formatResult(result, index + 1, currentSessionId));
|
|
204646
205797
|
if (results.some((result) => result.source === "message" || result.source === "compartment")) {
|
|
204647
205798
|
bodyParts.push("Use ctx_expand(start, end) with the range from any message result above to read the full conversation context.");
|
|
204648
205799
|
}
|
|
205800
|
+
if (results.some((result) => result.source === "note" && result.anchorOrdinal !== null && result.sourceSessionId === currentSessionId)) {
|
|
205801
|
+
bodyParts.push(NOTE_EXPAND_HINT);
|
|
205802
|
+
}
|
|
204649
205803
|
const body = bodyParts.join(`
|
|
204650
205804
|
|
|
204651
205805
|
`);
|
|
@@ -204659,7 +205813,7 @@ function createCtxSearchTool(deps) {
|
|
|
204659
205813
|
args: {
|
|
204660
205814
|
query: tool5.schema.string().describe("Search query. Matches against memory content, Primers, git commit messages, and raw user/assistant message text."),
|
|
204661
205815
|
limit: tool5.schema.number().optional().describe("Maximum results to return (default: 10)"),
|
|
204662
|
-
sources: tool5.schema.array(tool5.schema.enum(["memory", "message", "git_commit", "primer"])).optional().describe('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.')
|
|
205816
|
+
sources: tool5.schema.array(tool5.schema.enum(["memory", "message", "git_commit", "primer", "note"])).optional().describe('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.')
|
|
204663
205817
|
},
|
|
204664
205818
|
async execute(args, toolContext) {
|
|
204665
205819
|
const query = args.query?.trim();
|
|
@@ -204691,7 +205845,7 @@ function createCtxSearchTool(deps) {
|
|
|
204691
205845
|
visibleMemoryIds,
|
|
204692
205846
|
explicitSearch: true
|
|
204693
205847
|
});
|
|
204694
|
-
return formatSearchResults(query, results);
|
|
205848
|
+
return formatSearchResults(query, results, toolContext.sessionID);
|
|
204695
205849
|
}
|
|
204696
205850
|
});
|
|
204697
205851
|
}
|
|
@@ -204748,14 +205902,13 @@ function createToolRegistry(args) {
|
|
|
204748
205902
|
return {};
|
|
204749
205903
|
}
|
|
204750
205904
|
ensureProjectRegisteredFromOpenCodeDirectory(ctx.directory, db);
|
|
204751
|
-
const resolveProjectPath = (directory) =>
|
|
204752
|
-
const ctxReduceEnabled = pluginConfig.ctx_reduce_enabled !== false;
|
|
205905
|
+
const resolveProjectPath = (directory) => resolveProjectIdentityOrFallback(directory);
|
|
204753
205906
|
const memoryEnabled = pluginConfig.memory?.enabled !== false;
|
|
204754
205907
|
const allTools = {
|
|
204755
|
-
...
|
|
205908
|
+
...createCtxReduceTools({
|
|
204756
205909
|
db,
|
|
204757
205910
|
protectedTags: pluginConfig.protected_tags ?? DEFAULT_PROTECTED_TAGS
|
|
204758
|
-
})
|
|
205911
|
+
}),
|
|
204759
205912
|
...createCtxExpandTools({ db }),
|
|
204760
205913
|
...createCtxNoteTools({
|
|
204761
205914
|
db,
|
|
@@ -205198,7 +206351,7 @@ var server = async (ctx) => {
|
|
|
205198
206351
|
const dreamerRunnable = isDreamerRunnable(pluginConfig);
|
|
205199
206352
|
const timerRegistration = {
|
|
205200
206353
|
directory: ctx.directory,
|
|
205201
|
-
projectIdentity:
|
|
206354
|
+
projectIdentity: resolveProjectIdentityOrFallback(ctx.directory),
|
|
205202
206355
|
client: ctx.client,
|
|
205203
206356
|
dreamerConfig: dreamerRunnable ? pluginConfig.dreamer : undefined,
|
|
205204
206357
|
language: pluginConfig.language,
|