@cortexkit/opencode-magic-context 0.30.7 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/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/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 +1310 -167
- 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 +1 -1
- 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";
|
|
@@ -190570,7 +191095,7 @@ Output exactly JSON: {"met": false}`;
|
|
|
190570
191095
|
|
|
190571
191096
|
// src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
|
|
190572
191097
|
init_logger();
|
|
190573
|
-
import { existsSync as
|
|
191098
|
+
import { existsSync as existsSync18, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
|
|
190574
191099
|
import { join as join15 } from "node:path";
|
|
190575
191100
|
|
|
190576
191101
|
// src/features/magic-context/dreamer/protected-regions.ts
|
|
@@ -190674,7 +191199,7 @@ function snapshotMaintainDocsFiles(docsDir) {
|
|
|
190674
191199
|
for (const name2 of MAINTAIN_DOCS_SNAPSHOT_FILES) {
|
|
190675
191200
|
const path8 = join15(docsDir, name2);
|
|
190676
191201
|
try {
|
|
190677
|
-
if (
|
|
191202
|
+
if (existsSync18(path8)) {
|
|
190678
191203
|
snapshot.set(name2, readFileSync11(path8, "utf8"));
|
|
190679
191204
|
}
|
|
190680
191205
|
} catch {}
|
|
@@ -190706,7 +191231,7 @@ init_memory();
|
|
|
190706
191231
|
init_subagent_token_capture();
|
|
190707
191232
|
|
|
190708
191233
|
// src/features/magic-context/dreamer/map-memories-prompt.ts
|
|
190709
|
-
import { existsSync as
|
|
191234
|
+
import { existsSync as existsSync19, statSync as statSync6 } from "node:fs";
|
|
190710
191235
|
import path8 from "node:path";
|
|
190711
191236
|
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
191237
|
|
|
@@ -190744,7 +191269,7 @@ function extractMemoryCandidatePaths(content, repoDir) {
|
|
|
190744
191269
|
if (!abs.startsWith(`${root}/`))
|
|
190745
191270
|
continue;
|
|
190746
191271
|
try {
|
|
190747
|
-
if (
|
|
191272
|
+
if (existsSync19(abs) && statSync6(abs).isFile())
|
|
190748
191273
|
found.add(rel);
|
|
190749
191274
|
} catch {}
|
|
190750
191275
|
if (found.size >= MAX_SEED_PATHS_PER_MEMORY)
|
|
@@ -192573,8 +193098,8 @@ async function runAgenticTask(config2, ctx, helpers) {
|
|
|
192573
193098
|
const lastRunAt = getTaskScheduleState(db, projectIdentity, config2.task)?.lastRunAt ?? null;
|
|
192574
193099
|
const maintainDocsSnapshot = task === "maintain-docs" ? snapshotMaintainDocsFiles(docsDir) : undefined;
|
|
192575
193100
|
const existingDocs = task === "maintain-docs" ? {
|
|
192576
|
-
architecture:
|
|
192577
|
-
structure:
|
|
193101
|
+
architecture: existsSync20(`${docsDir}/ARCHITECTURE.md`),
|
|
193102
|
+
structure: existsSync20(`${docsDir}/STRUCTURE.md`)
|
|
192578
193103
|
} : undefined;
|
|
192579
193104
|
const userMemories = task === "curate" ? getActiveUserMemories(db).map((um) => ({ id: um.id, content: um.content })) : undefined;
|
|
192580
193105
|
let curateMemories;
|
|
@@ -194741,6 +195266,17 @@ ${c.content}
|
|
|
194741
195266
|
init_send_session_notification();
|
|
194742
195267
|
var recompConfirmationBySession = new Map;
|
|
194743
195268
|
var RECOMP_CONFIRMATION_WINDOW_MS = 60000;
|
|
195269
|
+
function isSubagentSession(db, sessionId) {
|
|
195270
|
+
const meta3 = getOrCreateSessionMeta(db, sessionId);
|
|
195271
|
+
if (meta3.isSubagent)
|
|
195272
|
+
return true;
|
|
195273
|
+
try {
|
|
195274
|
+
const row = db.prepare("SELECT is_subagent FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
195275
|
+
return row?.is_subagent === 1 || row?.is_subagent === true;
|
|
195276
|
+
} catch {
|
|
195277
|
+
return false;
|
|
195278
|
+
}
|
|
195279
|
+
}
|
|
194744
195280
|
var RECOMP_USAGE = [
|
|
194745
195281
|
"Usage:",
|
|
194746
195282
|
"- `/ctx-recomp` — full rebuild from message 1 to the protected tail",
|
|
@@ -194779,6 +195315,22 @@ ${RECOMP_USAGE}`
|
|
|
194779
195315
|
}
|
|
194780
195316
|
return { kind: "partial", range: { start, end } };
|
|
194781
195317
|
}
|
|
195318
|
+
function parseWrapupArgs(raw) {
|
|
195319
|
+
const trimmed = raw.trim();
|
|
195320
|
+
if (trimmed === "")
|
|
195321
|
+
return { ok: true, messagesToKeep: 20 };
|
|
195322
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
195323
|
+
return {
|
|
195324
|
+
ok: false,
|
|
195325
|
+
message: "Usage: `/ctx-wrapup [messages_to_keep]` where messages_to_keep is a positive integer."
|
|
195326
|
+
};
|
|
195327
|
+
}
|
|
195328
|
+
const messagesToKeep = Number.parseInt(trimmed, 10);
|
|
195329
|
+
if (!Number.isSafeInteger(messagesToKeep) || messagesToKeep <= 0) {
|
|
195330
|
+
return { ok: false, message: "messages_to_keep must be a positive integer." };
|
|
195331
|
+
}
|
|
195332
|
+
return { ok: true, messagesToKeep };
|
|
195333
|
+
}
|
|
194782
195334
|
var SENTINEL_PREFIX = "__CONTEXT_MANAGEMENT_";
|
|
194783
195335
|
var HTTP_SERVER_RESPONSE_TYPE_ID = "~effect/http/HttpServerResponse";
|
|
194784
195336
|
var HTTP_COOKIES_TYPE_ID = "~effect/http/Cookies";
|
|
@@ -194920,6 +195472,7 @@ function createMagicContextCommandHandler(deps) {
|
|
|
194920
195472
|
const isStatusCommand = (command) => command === "ctx-status";
|
|
194921
195473
|
const isFlushCommand = (command) => command === "ctx-flush";
|
|
194922
195474
|
const isRecompCommand = (command) => command === "ctx-recomp";
|
|
195475
|
+
const isWrapupCommand = (command) => command === "ctx-wrapup";
|
|
194923
195476
|
const isAugCommand = (command) => command === "ctx-aug";
|
|
194924
195477
|
const isDreamCommand = (command) => command === "ctx-dream";
|
|
194925
195478
|
const isSessionUpgradeCommand = (command) => command === "ctx-session-upgrade";
|
|
@@ -194929,11 +195482,12 @@ function createMagicContextCommandHandler(deps) {
|
|
|
194929
195482
|
const isStatus = isStatusCommand(input.command);
|
|
194930
195483
|
const isFlush = isFlushCommand(input.command);
|
|
194931
195484
|
const isRecomp = isRecompCommand(input.command);
|
|
195485
|
+
const isWrapup = isWrapupCommand(input.command);
|
|
194932
195486
|
const isAug = isAugCommand(input.command);
|
|
194933
195487
|
const isDream = isDreamCommand(input.command);
|
|
194934
195488
|
const isSessionUpgrade = isSessionUpgradeCommand(input.command);
|
|
194935
195489
|
const isEmbed = isEmbedCommand(input.command);
|
|
194936
|
-
if (!isStatus && !isFlush && !isRecomp && !isAug && !isDream && !isSessionUpgrade && !isEmbed) {
|
|
195490
|
+
if (!isStatus && !isFlush && !isRecomp && !isWrapup && !isAug && !isDream && !isSessionUpgrade && !isEmbed) {
|
|
194937
195491
|
return;
|
|
194938
195492
|
}
|
|
194939
195493
|
const sessionId = input.sessionID;
|
|
@@ -195003,6 +195557,26 @@ Embedding status is unavailable.`;
|
|
|
195003
195557
|
|
|
195004
195558
|
${statusOutput}` : statusOutput;
|
|
195005
195559
|
}
|
|
195560
|
+
if (isWrapup) {
|
|
195561
|
+
const parsed = parseWrapupArgs(input.arguments);
|
|
195562
|
+
if (isSubagentSession(deps.db, sessionId)) {
|
|
195563
|
+
result = `## Magic Wrapup — Skipped
|
|
195564
|
+
|
|
195565
|
+
/ctx-wrapup is only available in primary sessions.`;
|
|
195566
|
+
} else if (!parsed.ok) {
|
|
195567
|
+
result = `## Magic Wrapup — Invalid Arguments
|
|
195568
|
+
|
|
195569
|
+
${parsed.message}`;
|
|
195570
|
+
} else if (!deps.executeWrapup) {
|
|
195571
|
+
result = `## Magic Wrapup
|
|
195572
|
+
|
|
195573
|
+
/ctx-wrapup is unavailable because the historian handler is not configured.`;
|
|
195574
|
+
} else {
|
|
195575
|
+
result = await deps.executeWrapup(sessionId, {
|
|
195576
|
+
messagesToKeep: parsed.messagesToKeep
|
|
195577
|
+
});
|
|
195578
|
+
}
|
|
195579
|
+
}
|
|
195006
195580
|
if (isRecomp) {
|
|
195007
195581
|
const parsedArgs = parseRecompArgs(input.arguments);
|
|
195008
195582
|
if (parsedArgs.kind === "error") {
|
|
@@ -195309,7 +195883,8 @@ var canonicalReasons = new Set([
|
|
|
195309
195883
|
"first_render",
|
|
195310
195884
|
"pressure_refold",
|
|
195311
195885
|
"upgrade_state",
|
|
195312
|
-
"cached_m1_missing"
|
|
195886
|
+
"cached_m1_missing",
|
|
195887
|
+
"project_change"
|
|
195313
195888
|
]);
|
|
195314
195889
|
var piReasonAliases = {
|
|
195315
195890
|
project_memory_change: "project_memory_epoch",
|
|
@@ -196240,35 +196815,31 @@ function resolveCtxReduceAvailabilityFromMessages(sessionId, messages) {
|
|
|
196240
196815
|
for (const message of messages) {
|
|
196241
196816
|
if (message.info?.role !== "user")
|
|
196242
196817
|
continue;
|
|
196243
|
-
const verdict = verdictFromToolsMap(message.info.tools);
|
|
196244
|
-
|
|
196245
|
-
|
|
196246
|
-
return verdict;
|
|
196247
|
-
}
|
|
196248
|
-
break;
|
|
196818
|
+
const verdict = verdictFromToolsMap(message.info.tools) ?? true;
|
|
196819
|
+
availabilityBySession.set(sessionId, verdict);
|
|
196820
|
+
return verdict;
|
|
196249
196821
|
}
|
|
196250
|
-
availabilityBySession.set(sessionId, true);
|
|
196251
196822
|
return true;
|
|
196252
196823
|
}
|
|
196253
196824
|
function resolveCtxReduceAvailability(sessionId) {
|
|
196254
196825
|
const cached2 = availabilityBySession.get(sessionId);
|
|
196255
196826
|
if (cached2 !== undefined)
|
|
196256
|
-
return cached2;
|
|
196827
|
+
return { callable: cached2, frozen: true };
|
|
196257
196828
|
if (!openCodeDbExists())
|
|
196258
|
-
return true;
|
|
196829
|
+
return { callable: true, frozen: true };
|
|
196259
196830
|
try {
|
|
196260
196831
|
const row = withReadOnlySessionDb((db) => db.prepare(`SELECT json_extract(data, '$.tools') AS tools FROM message
|
|
196261
196832
|
WHERE session_id = ? AND json_extract(data, '$.role') = 'user'
|
|
196262
196833
|
ORDER BY time_created ASC LIMIT 1`).get(sessionId));
|
|
196263
196834
|
if (!row)
|
|
196264
|
-
return true;
|
|
196835
|
+
return { callable: true, frozen: false };
|
|
196265
196836
|
const verdict = row.tools === null ? null : verdictFromToolsMap(JSON.parse(row.tools));
|
|
196266
196837
|
const resolved = verdict ?? true;
|
|
196267
196838
|
availabilityBySession.set(sessionId, resolved);
|
|
196268
|
-
return resolved;
|
|
196839
|
+
return { callable: resolved, frozen: true };
|
|
196269
196840
|
} catch (error51) {
|
|
196270
196841
|
sessionLog(sessionId, "ctx_reduce availability read failed (fail-open):", error51);
|
|
196271
|
-
return true;
|
|
196842
|
+
return { callable: true, frozen: false };
|
|
196272
196843
|
}
|
|
196273
196844
|
}
|
|
196274
196845
|
|
|
@@ -197957,6 +198528,7 @@ function containsProbeVerbatim(text, probes) {
|
|
|
197957
198528
|
init_memory();
|
|
197958
198529
|
init_embedding();
|
|
197959
198530
|
init_storage_memory_fts();
|
|
198531
|
+
init_storage_notes();
|
|
197960
198532
|
init_storage_primers();
|
|
197961
198533
|
init_workspaces();
|
|
197962
198534
|
var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
|
|
@@ -198360,6 +198932,147 @@ function searchMessages(args) {
|
|
|
198360
198932
|
role: entry.row.role
|
|
198361
198933
|
}));
|
|
198362
198934
|
}
|
|
198935
|
+
var NOTE_SEARCHABLE_STATUSES = ["active", "pending", "ready", "dismissed"];
|
|
198936
|
+
function noteSearchText(note) {
|
|
198937
|
+
const reason = note.readyReason?.trim();
|
|
198938
|
+
return reason ? `${note.content}
|
|
198939
|
+
Reason: ${reason}` : note.content;
|
|
198940
|
+
}
|
|
198941
|
+
function tokenizeKeywordNeedle(text) {
|
|
198942
|
+
const matches = text.toLowerCase().match(/[a-z0-9/._:-]+/g) ?? [];
|
|
198943
|
+
const seen = new Set;
|
|
198944
|
+
const tokens = [];
|
|
198945
|
+
for (const match of matches) {
|
|
198946
|
+
if (match.length <= 1 || !/[a-z0-9]/.test(match) || seen.has(match)) {
|
|
198947
|
+
continue;
|
|
198948
|
+
}
|
|
198949
|
+
seen.add(match);
|
|
198950
|
+
tokens.push(match);
|
|
198951
|
+
}
|
|
198952
|
+
return tokens;
|
|
198953
|
+
}
|
|
198954
|
+
function rankNotesForNeedle(notes, needle) {
|
|
198955
|
+
const normalizedNeedle = needle.trim().toLowerCase();
|
|
198956
|
+
if (normalizedNeedle.length === 0) {
|
|
198957
|
+
return [];
|
|
198958
|
+
}
|
|
198959
|
+
const needleTokens = tokenizeKeywordNeedle(normalizedNeedle);
|
|
198960
|
+
const ranked = [];
|
|
198961
|
+
for (const note of notes) {
|
|
198962
|
+
const text = noteSearchText(note);
|
|
198963
|
+
const normalizedText = text.toLowerCase();
|
|
198964
|
+
const noteTokens = new Set(tokenizeKeywordNeedle(normalizedText));
|
|
198965
|
+
const exact = normalizedText.includes(normalizedNeedle);
|
|
198966
|
+
const matchedTokens = needleTokens.filter((token) => noteTokens.has(token)).length;
|
|
198967
|
+
if (!exact && matchedTokens === 0) {
|
|
198968
|
+
continue;
|
|
198969
|
+
}
|
|
198970
|
+
const coverage = needleTokens.length > 0 ? matchedTokens / needleTokens.length : 0;
|
|
198971
|
+
const score = (exact ? 2 : 0) + coverage + (needleTokens.length > 1 && matchedTokens === needleTokens.length ? 0.5 : 0);
|
|
198972
|
+
ranked.push({ note, score, text });
|
|
198973
|
+
}
|
|
198974
|
+
return ranked.sort((left, right) => {
|
|
198975
|
+
if (right.score !== left.score) {
|
|
198976
|
+
return right.score - left.score;
|
|
198977
|
+
}
|
|
198978
|
+
if (right.note.createdAt !== left.note.createdAt) {
|
|
198979
|
+
return right.note.createdAt - left.note.createdAt;
|
|
198980
|
+
}
|
|
198981
|
+
return left.note.id - right.note.id;
|
|
198982
|
+
});
|
|
198983
|
+
}
|
|
198984
|
+
function searchNotes(args) {
|
|
198985
|
+
if (args.limit <= 0) {
|
|
198986
|
+
return [];
|
|
198987
|
+
}
|
|
198988
|
+
const notes = [
|
|
198989
|
+
...getNotes(args.db, {
|
|
198990
|
+
sessionId: args.sessionId,
|
|
198991
|
+
type: "session",
|
|
198992
|
+
status: NOTE_SEARCHABLE_STATUSES
|
|
198993
|
+
}),
|
|
198994
|
+
...getNotes(args.db, {
|
|
198995
|
+
projectPath: args.projectPath,
|
|
198996
|
+
type: "smart",
|
|
198997
|
+
status: NOTE_SEARCHABLE_STATUSES
|
|
198998
|
+
})
|
|
198999
|
+
];
|
|
199000
|
+
if (notes.length === 0) {
|
|
199001
|
+
return [];
|
|
199002
|
+
}
|
|
199003
|
+
const baseList = rankNotesForNeedle(notes, args.query);
|
|
199004
|
+
const probes = args.probes ?? [];
|
|
199005
|
+
if (probes.length === 0) {
|
|
199006
|
+
const ranked2 = baseList.slice(0, args.limit);
|
|
199007
|
+
return ranked2.map((entry, rank) => ({
|
|
199008
|
+
source: "note",
|
|
199009
|
+
content: previewText(entry.text),
|
|
199010
|
+
score: linearDecayScore(rank, ranked2.length),
|
|
199011
|
+
noteId: entry.note.id,
|
|
199012
|
+
status: entry.note.status,
|
|
199013
|
+
createdAt: entry.note.createdAt,
|
|
199014
|
+
anchorOrdinal: entry.note.anchorOrdinal,
|
|
199015
|
+
sourceSessionId: entry.note.sessionId
|
|
199016
|
+
}));
|
|
199017
|
+
}
|
|
199018
|
+
const queryLists = [];
|
|
199019
|
+
if (baseList.length > 0) {
|
|
199020
|
+
queryLists.push({ rows: baseList, weight: 1 });
|
|
199021
|
+
}
|
|
199022
|
+
const probeWeights = new Map;
|
|
199023
|
+
for (const probe of probes) {
|
|
199024
|
+
const rows = rankNotesForNeedle(notes, probe);
|
|
199025
|
+
if (rows.length === 0) {
|
|
199026
|
+
continue;
|
|
199027
|
+
}
|
|
199028
|
+
const weight = probeDiscriminationWeight(rows.length, notes.length);
|
|
199029
|
+
probeWeights.set(probe, weight);
|
|
199030
|
+
queryLists.push({ rows, weight });
|
|
199031
|
+
}
|
|
199032
|
+
const fused = new Map;
|
|
199033
|
+
for (const list of queryLists) {
|
|
199034
|
+
list.rows.forEach((row, rank) => {
|
|
199035
|
+
const rrf = list.weight / (RRF_K + rank);
|
|
199036
|
+
const existing = fused.get(row.note.id);
|
|
199037
|
+
if (existing) {
|
|
199038
|
+
existing.score += rrf;
|
|
199039
|
+
} else {
|
|
199040
|
+
fused.set(row.note.id, { entry: row, score: rrf });
|
|
199041
|
+
}
|
|
199042
|
+
});
|
|
199043
|
+
}
|
|
199044
|
+
for (const match of fused.values()) {
|
|
199045
|
+
let best = 0;
|
|
199046
|
+
for (const probe of probes) {
|
|
199047
|
+
const weight = probeWeights.get(probe) ?? 0;
|
|
199048
|
+
if (weight > best && containsProbeVerbatim(match.entry.text, [probe])) {
|
|
199049
|
+
best = weight;
|
|
199050
|
+
}
|
|
199051
|
+
}
|
|
199052
|
+
if (best > 0) {
|
|
199053
|
+
match.score += best * VERBATIM_RANK_BONUS;
|
|
199054
|
+
}
|
|
199055
|
+
}
|
|
199056
|
+
const ranked = [...fused.values()].sort((left, right) => {
|
|
199057
|
+
if (right.score !== left.score) {
|
|
199058
|
+
return right.score - left.score;
|
|
199059
|
+
}
|
|
199060
|
+
if (right.entry.note.createdAt !== left.entry.note.createdAt) {
|
|
199061
|
+
return right.entry.note.createdAt - left.entry.note.createdAt;
|
|
199062
|
+
}
|
|
199063
|
+
return left.entry.note.id - right.entry.note.id;
|
|
199064
|
+
}).slice(0, args.limit);
|
|
199065
|
+
return ranked.map((entry, rank) => ({
|
|
199066
|
+
source: "note",
|
|
199067
|
+
content: previewText(entry.entry.text),
|
|
199068
|
+
score: linearDecayScore(rank, ranked.length),
|
|
199069
|
+
noteId: entry.entry.note.id,
|
|
199070
|
+
status: entry.entry.note.status,
|
|
199071
|
+
createdAt: entry.entry.note.createdAt,
|
|
199072
|
+
anchorOrdinal: entry.entry.note.anchorOrdinal,
|
|
199073
|
+
sourceSessionId: entry.entry.note.sessionId
|
|
199074
|
+
}));
|
|
199075
|
+
}
|
|
198363
199076
|
function searchCompartmentChunks(args) {
|
|
198364
199077
|
if (!args.queryEmbedding || args.limit <= 0 || !args.modelId || args.modelId === "off")
|
|
198365
199078
|
return [];
|
|
@@ -198445,6 +199158,8 @@ function getSourceBoost(result) {
|
|
|
198445
199158
|
return GIT_COMMIT_SOURCE_BOOST;
|
|
198446
199159
|
case "primer":
|
|
198447
199160
|
return PRIMER_SOURCE_BOOST;
|
|
199161
|
+
case "note":
|
|
199162
|
+
return 1;
|
|
198448
199163
|
}
|
|
198449
199164
|
}
|
|
198450
199165
|
function compareUnifiedResults(left, right) {
|
|
@@ -198468,6 +199183,9 @@ function compareUnifiedResults(left, right) {
|
|
|
198468
199183
|
if (left.source === "primer" && right.source === "primer") {
|
|
198469
199184
|
return right.support - left.support || left.primerId - right.primerId;
|
|
198470
199185
|
}
|
|
199186
|
+
if (left.source === "note" && right.source === "note") {
|
|
199187
|
+
return right.createdAt - left.createdAt || left.noteId - right.noteId;
|
|
199188
|
+
}
|
|
198471
199189
|
return 0;
|
|
198472
199190
|
}
|
|
198473
199191
|
function toGitCommitResult(hit) {
|
|
@@ -198535,11 +199253,11 @@ function searchPrimers(args) {
|
|
|
198535
199253
|
}
|
|
198536
199254
|
function resolveSources(sources) {
|
|
198537
199255
|
if (sources === undefined) {
|
|
198538
|
-
return new Set(["memory", "message", "git_commit", "primer"]);
|
|
199256
|
+
return new Set(["memory", "message", "git_commit", "primer", "note"]);
|
|
198539
199257
|
}
|
|
198540
199258
|
const set2 = new Set;
|
|
198541
199259
|
for (const source of sources) {
|
|
198542
|
-
if (source === "memory" || source === "message" || source === "git_commit" || source === "primer") {
|
|
199260
|
+
if (source === "memory" || source === "message" || source === "git_commit" || source === "primer" || source === "note") {
|
|
198543
199261
|
set2.add(source);
|
|
198544
199262
|
}
|
|
198545
199263
|
}
|
|
@@ -198562,6 +199280,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
198562
199280
|
const runMessages = activeSources.has("message");
|
|
198563
199281
|
const runGitCommits = activeSources.has("git_commit") && gitCommitsEnabled;
|
|
198564
199282
|
const runPrimers = activeSources.has("primer") && memoryFeatureEnabled;
|
|
199283
|
+
const runNotes = activeSources.has("note");
|
|
198565
199284
|
const runCompartmentChunks = runMessages && memoryFeatureEnabled && embeddingEnabled;
|
|
198566
199285
|
const needsEmbedding = (runMemory || runGitCommits || runCompartmentChunks || runPrimers) && embeddingEnabled && isEmbeddingRuntimeEnabled();
|
|
198567
199286
|
const queryEmbeddingPromise = needsEmbedding ? embedQuery(trimmedQuery, options.signal).catch((error51) => {
|
|
@@ -198597,7 +199316,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
198597
199316
|
compartments: compartmentResults,
|
|
198598
199317
|
limit: tierLimit
|
|
198599
199318
|
});
|
|
198600
|
-
const [memoryResults, gitCommitResults, primerResults] = await Promise.all([
|
|
199319
|
+
const [memoryResults, gitCommitResults, primerResults, noteResults] = await Promise.all([
|
|
198601
199320
|
runMemory ? searchMemories({
|
|
198602
199321
|
db,
|
|
198603
199322
|
projectPath,
|
|
@@ -198624,9 +199343,23 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
198624
199343
|
limit: tierLimit,
|
|
198625
199344
|
queryEmbedding,
|
|
198626
199345
|
queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null
|
|
199346
|
+
})) : Promise.resolve([]),
|
|
199347
|
+
runNotes ? Promise.resolve(searchNotes({
|
|
199348
|
+
db,
|
|
199349
|
+
sessionId,
|
|
199350
|
+
projectPath,
|
|
199351
|
+
query: trimmedQuery,
|
|
199352
|
+
limit: tierLimit,
|
|
199353
|
+
probes: messageProbes
|
|
198627
199354
|
})) : Promise.resolve([])
|
|
198628
199355
|
]);
|
|
198629
|
-
const results = [
|
|
199356
|
+
const results = [
|
|
199357
|
+
...memoryResults,
|
|
199358
|
+
...primerResults,
|
|
199359
|
+
...messageLikeResults,
|
|
199360
|
+
...gitCommitResults,
|
|
199361
|
+
...noteResults
|
|
199362
|
+
].sort(compareUnifiedResults).slice(0, limit);
|
|
198630
199363
|
const countRetrievals = options.countRetrievals ?? true;
|
|
198631
199364
|
if (countRetrievals) {
|
|
198632
199365
|
const memoryIds = results.filter((result) => result.source === "memory").map((result) => result.memoryId);
|
|
@@ -198699,6 +199432,10 @@ function renderFragment(result, charCap) {
|
|
|
198699
199432
|
const compressed = cavemanCompress(result.content, "ultra");
|
|
198700
199433
|
return truncate(compressed, charCap);
|
|
198701
199434
|
}
|
|
199435
|
+
case "note": {
|
|
199436
|
+
const compressed = cavemanCompress(result.content, "ultra");
|
|
199437
|
+
return truncate(compressed, charCap);
|
|
199438
|
+
}
|
|
198702
199439
|
}
|
|
198703
199440
|
}
|
|
198704
199441
|
function buildAutoSearchHint(results, options = {}) {
|
|
@@ -199565,6 +200302,13 @@ var degradedCacheCountBySession = new BoundedSessionMap(100);
|
|
|
199565
200302
|
function resetDegradedCacheCount(sessionId) {
|
|
199566
200303
|
degradedCacheCountBySession.delete(sessionId);
|
|
199567
200304
|
}
|
|
200305
|
+
function pendingMarkerCoveredByConsumedBoundary(pending, injection) {
|
|
200306
|
+
if (!injection)
|
|
200307
|
+
return false;
|
|
200308
|
+
if (pending.endMessageId === injection.compartmentEndMessageId)
|
|
200309
|
+
return true;
|
|
200310
|
+
return pending.ordinal <= injection.compartmentEndMessage;
|
|
200311
|
+
}
|
|
199568
200312
|
function clearPendingCompactionMarkerAfterSuccessfulDrain(args) {
|
|
199569
200313
|
if (clearPendingCompactionMarkerStateIf(args.db, args.sessionId, args.pending)) {
|
|
199570
200314
|
return "cleared";
|
|
@@ -199963,24 +200707,29 @@ async function runPostTransformPhase(args) {
|
|
|
199963
200707
|
if (historyWasConsumedThisPass && args.deferredHistoryWasPendingAtPassStart) {
|
|
199964
200708
|
const pending = getPendingCompactionMarkerState(args.db, args.sessionId);
|
|
199965
200709
|
if (pending) {
|
|
199966
|
-
|
|
199967
|
-
|
|
199968
|
-
|
|
199969
|
-
|
|
199970
|
-
|
|
199971
|
-
|
|
199972
|
-
|
|
199973
|
-
|
|
199974
|
-
|
|
199975
|
-
|
|
199976
|
-
|
|
200710
|
+
if (!pendingMarkerCoveredByConsumedBoundary(pending, args.pendingCompartmentInjection)) {
|
|
200711
|
+
suppressV12HistoryDrain = true;
|
|
200712
|
+
sessionLog(args.sessionId, `compaction-marker drain: pending ordinal ${pending.ordinal} is newer than consumed boundary ${args.pendingCompartmentInjection?.compartmentEndMessage ?? "<none>"}; preserving deferred history refresh signal`);
|
|
200713
|
+
} else {
|
|
200714
|
+
const outcome = applyDeferredCompactionMarker(args.db, args.sessionId, pending, args.sessionDirectory);
|
|
200715
|
+
switch (outcome.kind) {
|
|
200716
|
+
case "applied":
|
|
200717
|
+
case "already-current":
|
|
200718
|
+
case "stale-skip":
|
|
200719
|
+
if (clearPendingCompactionMarkerAfterSuccessfulDrain({
|
|
200720
|
+
db: args.db,
|
|
200721
|
+
sessionId: args.sessionId,
|
|
200722
|
+
pending,
|
|
200723
|
+
deferredHistoryRefreshSessions: args.deferredHistoryRefreshSessions
|
|
200724
|
+
}) === "cas-lost-newer-pending") {
|
|
200725
|
+
suppressV12HistoryDrain = true;
|
|
200726
|
+
}
|
|
200727
|
+
break;
|
|
200728
|
+
case "retryable-failure":
|
|
200729
|
+
sessionLog(args.sessionId, "compaction-marker drain: retryable failure; preserving deferred history refresh signal", outcome.error);
|
|
199977
200730
|
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;
|
|
200731
|
+
break;
|
|
200732
|
+
}
|
|
199984
200733
|
}
|
|
199985
200734
|
}
|
|
199986
200735
|
}
|
|
@@ -200085,6 +200834,16 @@ function getMessageTokensCache(sessionId) {
|
|
|
200085
200834
|
}
|
|
200086
200835
|
return cache;
|
|
200087
200836
|
}
|
|
200837
|
+
function maybeSendProjectIdentityWarning(deps, sessionId, directory, notificationParams) {
|
|
200838
|
+
if (!deps.client)
|
|
200839
|
+
return;
|
|
200840
|
+
const warning = takeDubiousOwnershipProjectIdentityWarning(directory);
|
|
200841
|
+
if (!warning)
|
|
200842
|
+
return;
|
|
200843
|
+
sendIgnoredMessage(deps.client, sessionId, warning, notificationParams).catch((error51) => {
|
|
200844
|
+
sessionLog(sessionId, `project identity warning delivery failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
200845
|
+
});
|
|
200846
|
+
}
|
|
200088
200847
|
function clearMessageTokensCache(sessionId, messageId) {
|
|
200089
200848
|
if (messageId === undefined) {
|
|
200090
200849
|
messageTokensBySession.delete(sessionId);
|
|
@@ -200159,7 +200918,7 @@ function createTransform(deps) {
|
|
|
200159
200918
|
}
|
|
200160
200919
|
const reducedMode = sessionMeta.isSubagent;
|
|
200161
200920
|
const fullFeatureMode = !reducedMode;
|
|
200162
|
-
const
|
|
200921
|
+
const ctxReduceCallable = resolveCtxReduceAvailabilityFromMessages(sessionId, messages);
|
|
200163
200922
|
let sessionDirectory = deps.directory ?? "";
|
|
200164
200923
|
let sessionDirectoryResolvedFromHost = false;
|
|
200165
200924
|
const cachedDirectory = deps.sessionDirectoryBySession?.get(sessionId);
|
|
@@ -200442,8 +201201,15 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
200442
201201
|
}
|
|
200443
201202
|
}
|
|
200444
201203
|
logTransformTiming(sessionId, "emergencyRecoveryBlock", tFirstPass);
|
|
200445
|
-
const
|
|
201204
|
+
const memoryProjectDirectory = compartmentDirectory || process.cwd();
|
|
201205
|
+
const projectIdentity = deps.memoryConfig?.enabled ? resolveProjectIdentity(memoryProjectDirectory) : undefined;
|
|
201206
|
+
if (deps.memoryConfig?.enabled) {
|
|
201207
|
+
maybeSendProjectIdentityWarning(deps, sessionId, memoryProjectDirectory, notificationParams);
|
|
201208
|
+
}
|
|
200446
201209
|
const sessionProjectIdentity = projectIdentity ?? (sessionDirectory ? resolveProjectIdentity(sessionDirectory) : deps.projectPath);
|
|
201210
|
+
if (sessionDirectory) {
|
|
201211
|
+
maybeSendProjectIdentityWarning(deps, sessionId, sessionDirectory, notificationParams);
|
|
201212
|
+
}
|
|
200447
201213
|
if (sessionProjectIdentity && sessionDirectoryResolvedFromHost && recordedSessionProjectIdentity.get(sessionId) !== sessionProjectIdentity) {
|
|
200448
201214
|
recordSessionProjectIdentity(db, sessionId, sessionProjectIdentity);
|
|
200449
201215
|
recordedSessionProjectIdentity.set(sessionId, sessionProjectIdentity);
|
|
@@ -200501,7 +201267,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
200501
201267
|
const tInitFromDb = performance.now();
|
|
200502
201268
|
deps.tagger.initFromDb(sessionId, db, taggerFloor);
|
|
200503
201269
|
logTransformTiming(sessionId, "tag.initFromDb", tInitFromDb);
|
|
200504
|
-
const skipPrefixInjection = !
|
|
201270
|
+
const skipPrefixInjection = !ctxReduceCallable;
|
|
200505
201271
|
const result = tagMessages(sessionId, messages, deps.tagger, db, {
|
|
200506
201272
|
skipPrefixInjection
|
|
200507
201273
|
});
|
|
@@ -200558,7 +201324,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
200558
201324
|
}
|
|
200559
201325
|
logTransformTiming(sessionId, "replayReasoningClearing", tReplay);
|
|
200560
201326
|
}
|
|
200561
|
-
if (!
|
|
201327
|
+
if (!reducedMode && deps.cavemanTextCompression?.enabled) {
|
|
200562
201328
|
const tCavemanReplay = performance.now();
|
|
200563
201329
|
const replayedCaveman = replayCavemanCompression(sessionId, db, targets, targetsSliceTags);
|
|
200564
201330
|
if (replayedCaveman > 0) {
|
|
@@ -200688,7 +201454,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
200688
201454
|
projectPath: sessionProjectIdentity,
|
|
200689
201455
|
sessionDirectory,
|
|
200690
201456
|
autoSearch: deps.autoSearch,
|
|
200691
|
-
cavemanTextCompression:
|
|
201457
|
+
cavemanTextCompression: !reducedMode ? deps.cavemanTextCompression : undefined,
|
|
200692
201458
|
smartDrops: deps.smartDrops === true,
|
|
200693
201459
|
resolvedProviderID,
|
|
200694
201460
|
historyRefreshSessions: deps.historyRefreshSessions,
|
|
@@ -200844,7 +201610,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
200844
201610
|
sessionLog(sessionId, "conversation_tokens UPDATE failed:", error51);
|
|
200845
201611
|
}
|
|
200846
201612
|
}
|
|
200847
|
-
if (
|
|
201613
|
+
if (ctxReduceCallable && deps.channel1StateBySession) {
|
|
200848
201614
|
try {
|
|
200849
201615
|
const resolvedExecuteThresholdPct = resolveExecuteThreshold(deps.executeThresholdPercentage ?? 65, deps.getModelKey?.(sessionId), 65, {
|
|
200850
201616
|
tokensConfig: deps.executeThresholdTokens,
|
|
@@ -201329,6 +202095,343 @@ function createTextCompleteHandler() {
|
|
|
201329
202095
|
};
|
|
201330
202096
|
}
|
|
201331
202097
|
|
|
202098
|
+
// src/hooks/magic-context/wrapup-orchestrator.ts
|
|
202099
|
+
init_compartment_lease();
|
|
202100
|
+
init_compartment_storage();
|
|
202101
|
+
init_logger();
|
|
202102
|
+
init_rpc_notifications();
|
|
202103
|
+
init_send_session_notification();
|
|
202104
|
+
await __promiseAll([
|
|
202105
|
+
init_storage(),
|
|
202106
|
+
init_compartment_runner(),
|
|
202107
|
+
init_compartment_runner_incremental(),
|
|
202108
|
+
init_protected_tail_boundary(),
|
|
202109
|
+
init_recomp_orchestrator()
|
|
202110
|
+
]);
|
|
202111
|
+
import * as crypto3 from "node:crypto";
|
|
202112
|
+
var WAIT_FOR_LEASE_MS = 1000;
|
|
202113
|
+
function sleep2(ms) {
|
|
202114
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
202115
|
+
}
|
|
202116
|
+
function plural(value, word) {
|
|
202117
|
+
return `${value} ${word}${value === 1 ? "" : "s"}`;
|
|
202118
|
+
}
|
|
202119
|
+
function formatAlreadyRunningMessage(state) {
|
|
202120
|
+
if (!state)
|
|
202121
|
+
return "/ctx-wrapup is already running for this session.";
|
|
202122
|
+
const chunk = state.expectedChunks > 0 ? ` chunk ${state.chunkIndex}/${state.expectedChunks}` : "";
|
|
202123
|
+
const through = state.lastCompartmentEnd > 0 ? ` through message ${state.lastCompartmentEnd}` : "";
|
|
202124
|
+
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.`;
|
|
202125
|
+
}
|
|
202126
|
+
function appendFlushHint(ctx, sessionId, message) {
|
|
202127
|
+
if (ctx.hasPendingNaturalBust?.(sessionId))
|
|
202128
|
+
return message;
|
|
202129
|
+
return `${message} If you want it applied on the very next message, run /ctx-flush first.`;
|
|
202130
|
+
}
|
|
202131
|
+
function buildPlan(ctx, sessionId, messagesToKeep, anchorRawMessageCount) {
|
|
202132
|
+
return resolveWrapupProtectedTailBoundary({
|
|
202133
|
+
db: ctx.db,
|
|
202134
|
+
sessionId,
|
|
202135
|
+
mode: "manual-wrapup",
|
|
202136
|
+
contextLimit: ctx.contextLimit,
|
|
202137
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
202138
|
+
usage: null,
|
|
202139
|
+
usageSource: "manual-none",
|
|
202140
|
+
providerShapeVersion: "opencode-v1",
|
|
202141
|
+
cacheNamespace: `opencode:${sessionId}`,
|
|
202142
|
+
messagesToKeep,
|
|
202143
|
+
anchorRawMessageCount
|
|
202144
|
+
});
|
|
202145
|
+
}
|
|
202146
|
+
function emitWrapupProgress(ctx, sessionId, progress) {
|
|
202147
|
+
const current = ctx.liveSessionState.recompProgressBySession.get(sessionId);
|
|
202148
|
+
ctx.liveSessionState.recompProgressBySession.set(sessionId, {
|
|
202149
|
+
sessionId,
|
|
202150
|
+
kind: "wrapup",
|
|
202151
|
+
phase: "recomp",
|
|
202152
|
+
processedMessages: progress.processedMessages ?? current?.processedMessages ?? 0,
|
|
202153
|
+
totalMessages: progress.totalMessages ?? current?.totalMessages ?? 0,
|
|
202154
|
+
passCount: progress.passCount ?? current?.passCount ?? 0,
|
|
202155
|
+
compartmentsCreated: progress.compartmentsCreated ?? current?.compartmentsCreated ?? 0,
|
|
202156
|
+
startedAt: current?.startedAt ?? Date.now(),
|
|
202157
|
+
updatedAt: Date.now(),
|
|
202158
|
+
note: progress.note
|
|
202159
|
+
});
|
|
202160
|
+
}
|
|
202161
|
+
async function waitForExistingIncrementalRun(sessionId) {
|
|
202162
|
+
const active = getActiveCompartmentRun(sessionId);
|
|
202163
|
+
if (!active)
|
|
202164
|
+
return "ok";
|
|
202165
|
+
if (active.kind === "recomp" || active.kind === "wrapup")
|
|
202166
|
+
return "busy";
|
|
202167
|
+
try {
|
|
202168
|
+
await active.promise;
|
|
202169
|
+
} catch {}
|
|
202170
|
+
return "ok";
|
|
202171
|
+
}
|
|
202172
|
+
async function acquireCompartmentLeaseForWrapup(ctx, sessionId, renewWrapupMarker) {
|
|
202173
|
+
const holderId = crypto3.randomUUID();
|
|
202174
|
+
for (;; ) {
|
|
202175
|
+
const active = getActiveCompartmentRun(sessionId);
|
|
202176
|
+
if (active?.kind === "recomp" || active?.kind === "wrapup")
|
|
202177
|
+
return null;
|
|
202178
|
+
if (active) {
|
|
202179
|
+
emitWrapupProgress(ctx, sessionId, { note: "Waiting for the active historian run…" });
|
|
202180
|
+
try {
|
|
202181
|
+
await active.promise;
|
|
202182
|
+
} catch {}
|
|
202183
|
+
continue;
|
|
202184
|
+
}
|
|
202185
|
+
const lease = acquireCompartmentLease(ctx.db, sessionId, holderId);
|
|
202186
|
+
if (lease)
|
|
202187
|
+
return holderId;
|
|
202188
|
+
emitWrapupProgress(ctx, sessionId, { note: "Waiting for the compartment-state lease…" });
|
|
202189
|
+
if (!renewWrapupMarker({}))
|
|
202190
|
+
return null;
|
|
202191
|
+
await sleep2(WAIT_FOR_LEASE_MS);
|
|
202192
|
+
}
|
|
202193
|
+
}
|
|
202194
|
+
async function runOneWrapupIteration(args) {
|
|
202195
|
+
const { ctx, sessionId, plan, messagesToKeep, anchorRawMessageCount } = args;
|
|
202196
|
+
const leaseHolderId = await acquireCompartmentLeaseForWrapup(ctx, sessionId, args.renewWrapupMarker);
|
|
202197
|
+
if (!leaseHolderId)
|
|
202198
|
+
return false;
|
|
202199
|
+
const renewal = setInterval(() => {
|
|
202200
|
+
try {
|
|
202201
|
+
if (!renewCompartmentLease(ctx.db, sessionId, leaseHolderId)) {
|
|
202202
|
+
sessionLog(sessionId, "wrapup: compartment lease renewal failed");
|
|
202203
|
+
}
|
|
202204
|
+
} catch (err) {
|
|
202205
|
+
sessionLog(sessionId, `wrapup: compartment lease renewal threw; continuing (${err instanceof Error ? err.message : String(err)})`);
|
|
202206
|
+
}
|
|
202207
|
+
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
202208
|
+
const runCompartmentAgentForWrapup = ctx.runCompartmentAgentForWrapup ?? runCompartmentAgent;
|
|
202209
|
+
const runnerPromise = runCompartmentAgentForWrapup({
|
|
202210
|
+
client: ctx.client,
|
|
202211
|
+
db: ctx.db,
|
|
202212
|
+
sessionId,
|
|
202213
|
+
historianChunkTokens: ctx.historianChunkTokens,
|
|
202214
|
+
historianTimeoutMs: ctx.historianTimeoutMs,
|
|
202215
|
+
boundarySnapshot: plan.snapshot,
|
|
202216
|
+
currentContextLimit: ctx.contextLimit,
|
|
202217
|
+
directory: ctx.directory,
|
|
202218
|
+
fallbackModels: ctx.fallbackModels,
|
|
202219
|
+
fallbackModelId: ctx.fallbackModelId,
|
|
202220
|
+
language: ctx.language,
|
|
202221
|
+
historianTwoPass: ctx.historianTwoPass,
|
|
202222
|
+
memoryEnabled: ctx.memoryEnabled,
|
|
202223
|
+
autoPromote: ctx.autoPromote,
|
|
202224
|
+
ensureProjectRegistered: ctx.ensureProjectRegistered,
|
|
202225
|
+
getNotificationParams: () => ctx.getNotificationParams(sessionId),
|
|
202226
|
+
preserveInjectionCacheUntilConsumed: true,
|
|
202227
|
+
compartmentLeaseHolderId: leaseHolderId,
|
|
202228
|
+
forceDrainQuota: true,
|
|
202229
|
+
forceKeepLastCompartment: true,
|
|
202230
|
+
refreshBoundarySnapshot: () => buildPlan(ctx, sessionId, messagesToKeep, anchorRawMessageCount).snapshot,
|
|
202231
|
+
onCompartmentStatePublished: (sid) => {
|
|
202232
|
+
markActiveCompartmentRunPublished(sid);
|
|
202233
|
+
ctx.liveSessionState.deferredHistoryRefreshSessions.add(sid);
|
|
202234
|
+
ctx.liveSessionState.deferredMaterializationSessions.add(sid);
|
|
202235
|
+
},
|
|
202236
|
+
onDeferredMarkerPending: (sid) => {
|
|
202237
|
+
ctx.liveSessionState.deferredHistoryRefreshSessions.add(sid);
|
|
202238
|
+
}
|
|
202239
|
+
});
|
|
202240
|
+
registerActiveCompartmentRun(sessionId, runnerPromise, "wrapup");
|
|
202241
|
+
try {
|
|
202242
|
+
await runnerPromise;
|
|
202243
|
+
return true;
|
|
202244
|
+
} finally {
|
|
202245
|
+
clearInterval(renewal);
|
|
202246
|
+
releaseCompartmentLease(ctx.db, sessionId, leaseHolderId);
|
|
202247
|
+
}
|
|
202248
|
+
}
|
|
202249
|
+
async function runManagedWrapup(ctx, sessionId, options) {
|
|
202250
|
+
const messagesToKeep = Math.max(1, Math.floor(options.messagesToKeep));
|
|
202251
|
+
setRecompStarting(ctx.liveSessionState, sessionId, "Estimating wrapup…", "wrapup");
|
|
202252
|
+
const existingWrapup = getWrapupInProgressState(ctx.db, sessionId);
|
|
202253
|
+
if (existingWrapup) {
|
|
202254
|
+
const message2 = formatAlreadyRunningMessage(existingWrapup);
|
|
202255
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "skipped", message2);
|
|
202256
|
+
return `## Magic Wrapup — Skipped
|
|
202257
|
+
|
|
202258
|
+
${message2}`;
|
|
202259
|
+
}
|
|
202260
|
+
const initialPlan = buildPlan(ctx, sessionId, messagesToKeep);
|
|
202261
|
+
if (initialPlan.rawMessagesAboveLastCompartment <= messagesToKeep || !hasRunnableCompartmentWindow(initialPlan.snapshot)) {
|
|
202262
|
+
const message2 = `Nothing to wrap up — only ${initialPlan.rawMessagesAboveLastCompartment} messages above the last compartment.`;
|
|
202263
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "done", message2);
|
|
202264
|
+
return message2;
|
|
202265
|
+
}
|
|
202266
|
+
const expectedChunks = Math.max(1, Math.ceil(initialPlan.snapshot.trueRawEligibleTokens / Math.max(1, ctx.historianChunkTokens)));
|
|
202267
|
+
const wrapupHolderId = crypto3.randomUUID();
|
|
202268
|
+
const acquired = acquireWrapupInProgress(ctx.db, sessionId, {
|
|
202269
|
+
holderId: wrapupHolderId,
|
|
202270
|
+
messagesToKeep,
|
|
202271
|
+
anchorRawMessageCount: initialPlan.anchorRawMessageCount,
|
|
202272
|
+
targetEligibleEndOrdinal: initialPlan.targetEligibleEndOrdinal,
|
|
202273
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(ctx.db, sessionId),
|
|
202274
|
+
chunkIndex: 0,
|
|
202275
|
+
expectedChunks
|
|
202276
|
+
});
|
|
202277
|
+
if (!acquired.ok) {
|
|
202278
|
+
const message2 = formatAlreadyRunningMessage(acquired.state);
|
|
202279
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "skipped", message2);
|
|
202280
|
+
return `## Magic Wrapup — Skipped
|
|
202281
|
+
|
|
202282
|
+
${message2}`;
|
|
202283
|
+
}
|
|
202284
|
+
const startLastEnd = getLastCompartmentEndMessage(ctx.db, sessionId);
|
|
202285
|
+
const startCompartmentCount = getCompartments(ctx.db, sessionId).length;
|
|
202286
|
+
let chunkIndex = 0;
|
|
202287
|
+
let lastEnd = startLastEnd;
|
|
202288
|
+
let stoppedForFailure = false;
|
|
202289
|
+
let stoppedReason = "";
|
|
202290
|
+
let ownershipLost = false;
|
|
202291
|
+
const ownershipLostReason = "another process took over this session's wrapup.";
|
|
202292
|
+
const markOwnershipLost = () => {
|
|
202293
|
+
if (ownershipLost)
|
|
202294
|
+
return;
|
|
202295
|
+
ownershipLost = true;
|
|
202296
|
+
sessionLog(sessionId, "wrapup: durable marker ownership lost; aborting loop");
|
|
202297
|
+
};
|
|
202298
|
+
const renewWrapupMarker = (updates) => {
|
|
202299
|
+
const updated = updateWrapupInProgress(ctx.db, sessionId, wrapupHolderId, updates);
|
|
202300
|
+
if (!updated) {
|
|
202301
|
+
markOwnershipLost();
|
|
202302
|
+
return false;
|
|
202303
|
+
}
|
|
202304
|
+
return true;
|
|
202305
|
+
};
|
|
202306
|
+
const markerRenewal = setInterval(() => {
|
|
202307
|
+
try {
|
|
202308
|
+
renewWrapupMarker({
|
|
202309
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(ctx.db, sessionId),
|
|
202310
|
+
chunkIndex
|
|
202311
|
+
});
|
|
202312
|
+
} catch (err) {
|
|
202313
|
+
sessionLog(sessionId, `wrapup: marker renewal threw; continuing (${err instanceof Error ? err.message : String(err)})`);
|
|
202314
|
+
}
|
|
202315
|
+
}, 60000);
|
|
202316
|
+
markerRenewal.unref?.();
|
|
202317
|
+
try {
|
|
202318
|
+
const activeAtStart = await waitForExistingIncrementalRun(sessionId);
|
|
202319
|
+
if (activeAtStart === "busy") {
|
|
202320
|
+
const message2 = "Another Magic Context rebuild is already running for this session.";
|
|
202321
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "skipped", message2);
|
|
202322
|
+
return `## Magic Wrapup — Skipped
|
|
202323
|
+
|
|
202324
|
+
${message2}`;
|
|
202325
|
+
}
|
|
202326
|
+
try {
|
|
202327
|
+
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));
|
|
202328
|
+
} catch {}
|
|
202329
|
+
try {
|
|
202330
|
+
pushNotification("action", { action: "wrapup-progress-kick" }, sessionId);
|
|
202331
|
+
} catch {}
|
|
202332
|
+
if (ownershipLost) {
|
|
202333
|
+
stoppedForFailure = true;
|
|
202334
|
+
stoppedReason = ownershipLostReason;
|
|
202335
|
+
} else {
|
|
202336
|
+
emitWrapupProgress(ctx, sessionId, {
|
|
202337
|
+
processedMessages: Math.max(0, lastEnd),
|
|
202338
|
+
totalMessages: Math.max(0, initialPlan.targetEligibleEndOrdinal - 1),
|
|
202339
|
+
passCount: 0,
|
|
202340
|
+
compartmentsCreated: 0,
|
|
202341
|
+
note: `Eligible ${plural(initialPlan.snapshot.trueRawEligibleTokens, "token")} across about ${plural(expectedChunks, "chunk")}.`
|
|
202342
|
+
});
|
|
202343
|
+
for (;; ) {
|
|
202344
|
+
if (ownershipLost) {
|
|
202345
|
+
stoppedForFailure = true;
|
|
202346
|
+
stoppedReason = ownershipLostReason;
|
|
202347
|
+
break;
|
|
202348
|
+
}
|
|
202349
|
+
if (!renewWrapupMarker({
|
|
202350
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(ctx.db, sessionId),
|
|
202351
|
+
chunkIndex,
|
|
202352
|
+
expectedChunks
|
|
202353
|
+
})) {
|
|
202354
|
+
stoppedForFailure = true;
|
|
202355
|
+
stoppedReason = ownershipLostReason;
|
|
202356
|
+
break;
|
|
202357
|
+
}
|
|
202358
|
+
const plan = buildPlan(ctx, sessionId, messagesToKeep, initialPlan.anchorRawMessageCount);
|
|
202359
|
+
lastEnd = getLastCompartmentEndMessage(ctx.db, sessionId);
|
|
202360
|
+
if (lastEnd + 1 >= plan.targetEligibleEndOrdinal)
|
|
202361
|
+
break;
|
|
202362
|
+
chunkIndex += 1;
|
|
202363
|
+
emitWrapupProgress(ctx, sessionId, {
|
|
202364
|
+
processedMessages: Math.max(0, lastEnd),
|
|
202365
|
+
totalMessages: Math.max(0, plan.targetEligibleEndOrdinal - 1),
|
|
202366
|
+
passCount: chunkIndex - 1,
|
|
202367
|
+
compartmentsCreated: Math.max(0, getCompartments(ctx.db, sessionId).length - startCompartmentCount),
|
|
202368
|
+
note: `Chunk ${chunkIndex}/${expectedChunks}: messages ${plan.snapshot.offset}-${plan.snapshot.eligibleEndOrdinal - 1}…`
|
|
202369
|
+
});
|
|
202370
|
+
if (!renewWrapupMarker({
|
|
202371
|
+
lastCompartmentEnd: lastEnd,
|
|
202372
|
+
chunkIndex,
|
|
202373
|
+
expectedChunks,
|
|
202374
|
+
targetEligibleEndOrdinal: plan.targetEligibleEndOrdinal
|
|
202375
|
+
})) {
|
|
202376
|
+
stoppedForFailure = true;
|
|
202377
|
+
stoppedReason = ownershipLostReason;
|
|
202378
|
+
break;
|
|
202379
|
+
}
|
|
202380
|
+
const beforeEnd = lastEnd;
|
|
202381
|
+
const beforeFailures = getHistorianFailureState(ctx.db, sessionId).failureCount;
|
|
202382
|
+
const ran = await runOneWrapupIteration({
|
|
202383
|
+
ctx,
|
|
202384
|
+
sessionId,
|
|
202385
|
+
plan,
|
|
202386
|
+
messagesToKeep,
|
|
202387
|
+
anchorRawMessageCount: initialPlan.anchorRawMessageCount,
|
|
202388
|
+
renewWrapupMarker
|
|
202389
|
+
});
|
|
202390
|
+
if (!ran) {
|
|
202391
|
+
stoppedForFailure = true;
|
|
202392
|
+
stoppedReason = ownershipLost ? ownershipLostReason : "Another Magic Context rebuild started while wrapup was waiting.";
|
|
202393
|
+
break;
|
|
202394
|
+
}
|
|
202395
|
+
const afterEnd = getLastCompartmentEndMessage(ctx.db, sessionId);
|
|
202396
|
+
const afterFailures = getHistorianFailureState(ctx.db, sessionId).failureCount;
|
|
202397
|
+
if (afterEnd <= beforeEnd) {
|
|
202398
|
+
stoppedForFailure = true;
|
|
202399
|
+
stoppedReason = afterFailures > beforeFailures ? "The historian failed on the current chunk." : "The historian made no forward progress on the current chunk.";
|
|
202400
|
+
break;
|
|
202401
|
+
}
|
|
202402
|
+
lastEnd = afterEnd;
|
|
202403
|
+
emitWrapupProgress(ctx, sessionId, {
|
|
202404
|
+
processedMessages: Math.max(0, lastEnd),
|
|
202405
|
+
totalMessages: Math.max(0, plan.targetEligibleEndOrdinal - 1),
|
|
202406
|
+
passCount: chunkIndex,
|
|
202407
|
+
compartmentsCreated: Math.max(0, getCompartments(ctx.db, sessionId).length - startCompartmentCount),
|
|
202408
|
+
note: `Wrapped through message ${lastEnd}.`
|
|
202409
|
+
});
|
|
202410
|
+
}
|
|
202411
|
+
}
|
|
202412
|
+
} finally {
|
|
202413
|
+
clearInterval(markerRenewal);
|
|
202414
|
+
releaseWrapupInProgress(ctx.db, sessionId, wrapupHolderId);
|
|
202415
|
+
}
|
|
202416
|
+
const finalEnd = getLastCompartmentEndMessage(ctx.db, sessionId);
|
|
202417
|
+
const compartmentsCreated = Math.max(0, getCompartments(ctx.db, sessionId).length - startCompartmentCount);
|
|
202418
|
+
const messagesWrapped = Math.max(0, finalEnd - Math.max(0, startLastEnd));
|
|
202419
|
+
if (stoppedForFailure) {
|
|
202420
|
+
const message2 = `Wrapped up through message ${Math.max(0, finalEnd)} (${plural(messagesWrapped, "message")} into ${plural(compartmentsCreated, "compartment")}). ${stoppedReason} Run /ctx-wrapup again to continue.`;
|
|
202421
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "failed", message2);
|
|
202422
|
+
return `## Magic Wrapup — Partial
|
|
202423
|
+
|
|
202424
|
+
${message2}`;
|
|
202425
|
+
}
|
|
202426
|
+
try {
|
|
202427
|
+
clearEmergencyRecovery(ctx.db, sessionId);
|
|
202428
|
+
} catch {}
|
|
202429
|
+
const base = `Wrapped up ${messagesWrapped} messages into ${compartmentsCreated} compartments. The compacted history is queued and materializes on your next message.`;
|
|
202430
|
+
const message = appendFlushHint(ctx, sessionId, base);
|
|
202431
|
+
setRecompTerminal(ctx.liveSessionState, sessionId, "done", message);
|
|
202432
|
+
return message;
|
|
202433
|
+
}
|
|
202434
|
+
|
|
201332
202435
|
// src/hooks/magic-context/hook.ts
|
|
201333
202436
|
await init_compaction_marker_manager();
|
|
201334
202437
|
|
|
@@ -201667,7 +202770,7 @@ Drop silently — do not narrate it. NEVER drop large ranges blindly (e.g., "1-5
|
|
|
201667
202770
|
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
202771
|
var CAVEMAN_COMPRESSION_WARNING = `
|
|
201669
202772
|
**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,
|
|
202773
|
+
function buildMagicContextSection(_agent, protectedTags, ctxReduceCallable = true, dreamerEnabled = false, temporalAwarenessEnabled = false, cavemanTextCompressionEnabled = false, subagentMode = false, language, memoryEnabled = true) {
|
|
201671
202774
|
if (subagentMode) {
|
|
201672
202775
|
return `## Magic Context
|
|
201673
202776
|
|
|
@@ -201678,12 +202781,12 @@ When \`surface_condition\` is provided with \`write\`, the note becomes a projec
|
|
|
201678
202781
|
The dreamer evaluates smart note conditions during nightly runs and surfaces them when conditions are met.
|
|
201679
202782
|
Example: \`ctx_note(action="write", content="Implement X because Y", surface_condition="When PR #42 is merged in this repo")\`` : "";
|
|
201680
202783
|
const temporalGuidance = temporalAwarenessEnabled ? TEMPORAL_AWARENESS_GUIDANCE : "";
|
|
201681
|
-
const cavemanWarning = cavemanTextCompressionEnabled
|
|
202784
|
+
const cavemanWarning = cavemanTextCompressionEnabled ? CAVEMAN_COMPRESSION_WARNING : "";
|
|
201682
202785
|
const languageDirective = buildPrimaryLanguageDirective(language);
|
|
201683
202786
|
const languageGuidance = languageDirective ? `
|
|
201684
202787
|
|
|
201685
202788
|
${languageDirective}` : "";
|
|
201686
|
-
if (!
|
|
202789
|
+
if (!ctxReduceCallable) {
|
|
201687
202790
|
return `## Magic Context
|
|
201688
202791
|
|
|
201689
202792
|
${LONG_TERM_PARTNER_FRAME}
|
|
@@ -201696,7 +202799,7 @@ ${BASE_INTRO_NO_REDUCE(memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${c
|
|
|
201696
202799
|
${LONG_TERM_PARTNER_FRAME}
|
|
201697
202800
|
${PARTNER_FRAME_CLOSER_REDUCE}
|
|
201698
202801
|
|
|
201699
|
-
${BASE_INTRO(protectedTags, memoryEnabled)}${smartNoteGuidance}${temporalGuidance}
|
|
202802
|
+
${BASE_INTRO(protectedTags, memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}
|
|
201700
202803
|
${GENERIC_SECTION}
|
|
201701
202804
|
|
|
201702
202805
|
Prefer many small targeted operations over one large blanket operation, and keep the working set tidy as routine maintenance.${languageGuidance}`;
|
|
@@ -201749,17 +202852,18 @@ function createSystemPromptHashHandler(deps) {
|
|
|
201749
202852
|
} catch (error51) {
|
|
201750
202853
|
sessionLog(sessionId, "system-prompt-hash session meta load failed:", error51);
|
|
201751
202854
|
}
|
|
201752
|
-
const
|
|
201753
|
-
const
|
|
201754
|
-
const
|
|
201755
|
-
const
|
|
201756
|
-
const
|
|
202855
|
+
const isSubagentSession2 = sessionMetaEarly?.isSubagent === true;
|
|
202856
|
+
const availability = resolveCtxReduceAvailability(sessionId);
|
|
202857
|
+
const ctxReduceCallable = availability.callable;
|
|
202858
|
+
const subagentReduceMode = isSubagentSession2 && ctxReduceCallable;
|
|
202859
|
+
const effectiveCtxReduceEnabled = isSubagentSession2 ? false : ctxReduceCallable;
|
|
202860
|
+
const skipGuidanceForDisabledSubagent = isSubagentSession2 && !ctxReduceCallable;
|
|
201757
202861
|
const fullPrompt = output.system.join(`
|
|
201758
202862
|
`);
|
|
201759
202863
|
if (fullPrompt.length > 0 && !fullPrompt.includes(MAGIC_CONTEXT_MARKER) && !skipGuidanceForDisabledSubagent) {
|
|
201760
202864
|
const guidance = buildMagicContextSection(null, deps.protectedTags, effectiveCtxReduceEnabled, deps.dreamerEnabled, deps.experimentalTemporalAwareness, deps.experimentalCavemanTextCompression, subagentReduceMode, deps.language, deps.memoryEnabled !== false);
|
|
201761
202865
|
output.system.push(guidance);
|
|
201762
|
-
sessionLog(sessionId, `injected generic guidance into system prompt (ctxReduce=${effectiveCtxReduceEnabled}, subagent=${
|
|
202866
|
+
sessionLog(sessionId, `injected generic guidance into system prompt (ctxReduce=${effectiveCtxReduceEnabled}, subagent=${isSubagentSession2}, subagentReduceMode=${subagentReduceMode})`);
|
|
201763
202867
|
}
|
|
201764
202868
|
const isCacheBusting = deps.systemPromptRefreshSessions.has(sessionId);
|
|
201765
202869
|
const DATE_PATTERN = /Today's date: .+/;
|
|
@@ -201786,6 +202890,8 @@ function createSystemPromptHashHandler(deps) {
|
|
|
201786
202890
|
`);
|
|
201787
202891
|
if (systemContent.length === 0)
|
|
201788
202892
|
return;
|
|
202893
|
+
if (!availability.frozen)
|
|
202894
|
+
return;
|
|
201789
202895
|
const currentHash = createHash13("md5").update(systemContent).digest("hex");
|
|
201790
202896
|
if (!sessionMetaEarly) {
|
|
201791
202897
|
return;
|
|
@@ -201974,7 +203080,7 @@ function createMagicContextHook(deps) {
|
|
|
201974
203080
|
notifyMagicContextDisabled(deps.client, reason);
|
|
201975
203081
|
return null;
|
|
201976
203082
|
}
|
|
201977
|
-
const projectPath =
|
|
203083
|
+
const projectPath = resolveProjectIdentityOrFallback(deps.directory);
|
|
201978
203084
|
try {
|
|
201979
203085
|
checkCompactionMarkerConsistency(db);
|
|
201980
203086
|
} catch (error51) {
|
|
@@ -201985,20 +203091,21 @@ function createMagicContextHook(deps) {
|
|
|
201985
203091
|
const historianFallbackModels = resolveFallbackChain(deps.config.historian?.fallback_models);
|
|
201986
203092
|
const historyRefreshSessions = deps.liveSessionState?.historyRefreshSessions ?? new Set;
|
|
201987
203093
|
const deferredHistoryRefreshSessions = deps.liveSessionState?.deferredHistoryRefreshSessions ?? new Set;
|
|
203094
|
+
const systemPromptRefreshSessions = deps.liveSessionState?.systemPromptRefreshSessions ?? new Set;
|
|
203095
|
+
const pendingMaterializationSessions = deps.liveSessionState?.pendingMaterializationSessions ?? new Set;
|
|
203096
|
+
const deferredMaterializationSessions = deps.liveSessionState?.deferredMaterializationSessions ?? new Set;
|
|
201988
203097
|
try {
|
|
201989
203098
|
const sessionsWithPending = getSessionsWithPendingMarker(db);
|
|
201990
203099
|
if (sessionsWithPending.length > 0) {
|
|
201991
203100
|
for (const sid of sessionsWithPending) {
|
|
201992
203101
|
deferredHistoryRefreshSessions.add(sid);
|
|
203102
|
+
deferredMaterializationSessions.add(sid);
|
|
201993
203103
|
}
|
|
201994
203104
|
log(`[magic-context] rehydrated ${sessionsWithPending.length} session(s) with pending compaction-marker drain at hook init`);
|
|
201995
203105
|
}
|
|
201996
203106
|
} catch (error51) {
|
|
201997
203107
|
log("[magic-context] hook init: pending-marker rehydration failed:", error51);
|
|
201998
203108
|
}
|
|
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
203109
|
const lastHeuristicsTurnId = new Map;
|
|
202003
203110
|
const commitSeenLastPass = new Map;
|
|
202004
203111
|
const variantBySession = deps.liveSessionState?.variantBySession ?? new Map;
|
|
@@ -202019,7 +203126,15 @@ function createMagicContextHook(deps) {
|
|
|
202019
203126
|
}
|
|
202020
203127
|
return;
|
|
202021
203128
|
};
|
|
202022
|
-
const
|
|
203129
|
+
const maybeSendProjectIdentitySessionWarning = (sessionId, directory) => {
|
|
203130
|
+
const warning = takeDubiousOwnershipProjectIdentityWarning(directory);
|
|
203131
|
+
if (!warning)
|
|
203132
|
+
return;
|
|
203133
|
+
const notificationParams = getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession, deps.config.toast_duration_ms);
|
|
203134
|
+
sendIgnoredMessage(deps.client, sessionId, warning, notificationParams).catch((error51) => {
|
|
203135
|
+
log(`[magic-context] failed to send project identity warning for ${directory}: ${getErrorMessage(error51)}`);
|
|
203136
|
+
});
|
|
203137
|
+
};
|
|
202023
203138
|
const dreamerRunnable = isDreamerRunnable(deps.config);
|
|
202024
203139
|
const dreamerConfig = dreamerRunnable ? deps.config.dreamer : undefined;
|
|
202025
203140
|
const historianRunnable = isHistorianRunnable(deps.config);
|
|
@@ -202056,6 +203171,23 @@ function createMagicContextHook(deps) {
|
|
|
202056
203171
|
ensureProjectRegistered: ensureProjectRegisteredFromOpenCodeDirectory,
|
|
202057
203172
|
getNotificationParams: (sid) => getLiveNotificationParams(sid, liveModelBySession, variantBySession, agentBySession, deps.config.toast_duration_ms)
|
|
202058
203173
|
});
|
|
203174
|
+
const buildManagedWrapupCtx = (sessionId) => ({
|
|
203175
|
+
...buildManagedRecompCtx(sessionId),
|
|
203176
|
+
contextLimit: (() => {
|
|
203177
|
+
const model = resolveLiveModel(sessionId);
|
|
203178
|
+
return model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
|
|
203179
|
+
})(),
|
|
203180
|
+
executeThresholdPercentage: (() => {
|
|
203181
|
+
const model = resolveLiveModel(sessionId);
|
|
203182
|
+
const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
|
|
203183
|
+
return resolveExecuteThresholdDetail(deps.config.execute_threshold_percentage ?? 65, model ? `${model.providerID}/${model.modelID}` : undefined, 65, {
|
|
203184
|
+
tokensConfig: deps.config.execute_threshold_tokens,
|
|
203185
|
+
contextLimit,
|
|
203186
|
+
sessionId
|
|
203187
|
+
}).percentage;
|
|
203188
|
+
})(),
|
|
203189
|
+
hasPendingNaturalBust: (sid) => historyRefreshSessions.has(sid) || systemPromptRefreshSessions.has(sid) || pendingMaterializationSessions.has(sid)
|
|
203190
|
+
});
|
|
202059
203191
|
const executeEmbedHistory = async (sessionId, options) => {
|
|
202060
203192
|
if (deps.config.memory?.enabled === false) {
|
|
202061
203193
|
return "Memory is disabled for this project, so there is no semantic embedding to backfill.";
|
|
@@ -202066,7 +203198,8 @@ function createMagicContextHook(deps) {
|
|
|
202066
203198
|
return "Embedding is already running for this session.";
|
|
202067
203199
|
}
|
|
202068
203200
|
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
202069
|
-
const sessionProjectIdentity =
|
|
203201
|
+
const sessionProjectIdentity = resolveProjectIdentityOrFallback(directory);
|
|
203202
|
+
maybeSendProjectIdentitySessionWarning(sessionId, directory);
|
|
202070
203203
|
embedPauseBySession.delete(sessionId);
|
|
202071
203204
|
const prior = embedRunStateBySession.get(sessionId);
|
|
202072
203205
|
if (prior)
|
|
@@ -202131,13 +203264,15 @@ function createMagicContextHook(deps) {
|
|
|
202131
203264
|
if (ctrl)
|
|
202132
203265
|
ctrl.abort();
|
|
202133
203266
|
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
202134
|
-
const sessionProjectIdentity =
|
|
203267
|
+
const sessionProjectIdentity = resolveProjectIdentityOrFallback(directory);
|
|
203268
|
+
maybeSendProjectIdentitySessionWarning(sessionId, directory);
|
|
202135
203269
|
const cov = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
202136
203270
|
return `Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`;
|
|
202137
203271
|
};
|
|
202138
203272
|
const getEmbedStatusText = (sessionId) => {
|
|
202139
203273
|
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
202140
|
-
const sessionProjectIdentity =
|
|
203274
|
+
const sessionProjectIdentity = resolveProjectIdentityOrFallback(directory);
|
|
203275
|
+
maybeSendProjectIdentitySessionWarning(sessionId, directory);
|
|
202141
203276
|
const coverage = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
202142
203277
|
const progress = recompProgressBySession.get(sessionId);
|
|
202143
203278
|
const drainUi = getEmbedDrainUiStatus(sessionId, progress);
|
|
@@ -202160,7 +203295,8 @@ function createMagicContextHook(deps) {
|
|
|
202160
203295
|
try {
|
|
202161
203296
|
await new Promise((resolve4) => setTimeout(resolve4, 0));
|
|
202162
203297
|
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
202163
|
-
const sessionProjectIdentity =
|
|
203298
|
+
const sessionProjectIdentity = resolveProjectIdentityOrFallback(directory);
|
|
203299
|
+
maybeSendProjectIdentitySessionWarning(sessionId, directory);
|
|
202164
203300
|
const coverage = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
202165
203301
|
if (!coverage.enabled)
|
|
202166
203302
|
return;
|
|
@@ -202194,7 +203330,6 @@ function createMagicContextHook(deps) {
|
|
|
202194
203330
|
db,
|
|
202195
203331
|
channel1StateBySession,
|
|
202196
203332
|
protectedTags: deps.config.protected_tags,
|
|
202197
|
-
ctxReduceEnabled,
|
|
202198
203333
|
smartDrops: deps.config.smart_drops === true,
|
|
202199
203334
|
clearReasoningAge: deps.config.clear_reasoning_age ?? 50,
|
|
202200
203335
|
commitClusterTrigger: deps.config.commit_cluster_trigger,
|
|
@@ -202243,7 +203378,7 @@ function createMagicContextHook(deps) {
|
|
|
202243
203378
|
directory: deps.directory,
|
|
202244
203379
|
ensureProjectRegistered: ensureProjectRegisteredFromOpenCodeDirectory
|
|
202245
203380
|
} : undefined,
|
|
202246
|
-
cavemanTextCompression:
|
|
203381
|
+
cavemanTextCompression: deps.config.caveman_text_compression?.enabled === true ? {
|
|
202247
203382
|
enabled: true,
|
|
202248
203383
|
minChars: deps.config.caveman_text_compression.min_chars ?? 500
|
|
202249
203384
|
} : undefined,
|
|
@@ -202331,6 +203466,7 @@ function createMagicContextHook(deps) {
|
|
|
202331
203466
|
systemPromptRefreshSessions.add(sessionId);
|
|
202332
203467
|
pendingMaterializationSessions.add(sessionId);
|
|
202333
203468
|
},
|
|
203469
|
+
executeWrapup: historianRunnable ? async (sessionId, options) => runManagedWrapup(buildManagedWrapupCtx(sessionId), sessionId, options) : undefined,
|
|
202334
203470
|
executeRecomp: historianRunnable ? async (sessionId, options) => runManagedRecomp(buildManagedRecompCtx(sessionId), sessionId, options) : undefined,
|
|
202335
203471
|
runUpgrade: historianRunnable ? async (sessionId) => runManagedUpgrade(buildManagedRecompCtx(sessionId), sessionId) : undefined,
|
|
202336
203472
|
executeEmbedHistory,
|
|
@@ -202374,7 +203510,6 @@ function createMagicContextHook(deps) {
|
|
|
202374
203510
|
const systemPromptHash = createSystemPromptHashHandler({
|
|
202375
203511
|
db,
|
|
202376
203512
|
protectedTags: deps.config.protected_tags,
|
|
202377
|
-
ctxReduceEnabled,
|
|
202378
203513
|
dreamerEnabled: dreamerRunnable,
|
|
202379
203514
|
memoryEnabled: deps.config.memory?.enabled !== false,
|
|
202380
203515
|
language: deps.config.language,
|
|
@@ -202389,7 +203524,7 @@ function createMagicContextHook(deps) {
|
|
|
202389
203524
|
internalChildSessions,
|
|
202390
203525
|
experimentalUserMemories: userMemoryCollectionEnabled(deps.config.dreamer),
|
|
202391
203526
|
experimentalTemporalAwareness: deps.config.temporal_awareness === true,
|
|
202392
|
-
experimentalCavemanTextCompression:
|
|
203527
|
+
experimentalCavemanTextCompression: deps.config.caveman_text_compression?.enabled === true
|
|
202393
203528
|
});
|
|
202394
203529
|
const systemPromptHashHandler = systemPromptHash.handler;
|
|
202395
203530
|
const eventHook = createEventHook({
|
|
@@ -202408,8 +203543,7 @@ function createMagicContextHook(deps) {
|
|
|
202408
203543
|
lastHeuristicsTurnId,
|
|
202409
203544
|
commitSeenLastPass,
|
|
202410
203545
|
client: deps.client,
|
|
202411
|
-
protectedTags: deps.config.protected_tags
|
|
202412
|
-
ctxReduceEnabled
|
|
203546
|
+
protectedTags: deps.config.protected_tags
|
|
202413
203547
|
});
|
|
202414
203548
|
return {
|
|
202415
203549
|
"experimental.chat.messages.transform": transform2,
|
|
@@ -202424,7 +203558,6 @@ function createMagicContextHook(deps) {
|
|
|
202424
203558
|
systemPromptRefreshSessions,
|
|
202425
203559
|
pendingMaterializationSessions,
|
|
202426
203560
|
lastHeuristicsTurnId,
|
|
202427
|
-
ctxReduceEnabled,
|
|
202428
203561
|
upgradeReminder: historianRunnable ? (sessionId) => maybeSendUpgradeReminder({
|
|
202429
203562
|
client: deps.client,
|
|
202430
203563
|
db,
|
|
@@ -202456,7 +203589,6 @@ function createMagicContextHook(deps) {
|
|
|
202456
203589
|
function buildMagicContextHookConfig(pluginConfig) {
|
|
202457
203590
|
return {
|
|
202458
203591
|
protected_tags: pluginConfig.protected_tags ?? DEFAULT_PROTECTED_TAGS,
|
|
202459
|
-
ctx_reduce_enabled: pluginConfig.ctx_reduce_enabled,
|
|
202460
203592
|
cache_ttl: pluginConfig.cache_ttl,
|
|
202461
203593
|
clear_reasoning_age: pluginConfig.clear_reasoning_age,
|
|
202462
203594
|
toast_duration_ms: pluginConfig.toast_duration_ms,
|
|
@@ -202977,7 +204109,6 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
|
|
|
202977
204109
|
contextLimit: 0,
|
|
202978
204110
|
systemPromptTokens: 0,
|
|
202979
204111
|
compartmentCount: 0,
|
|
202980
|
-
factCount: 0,
|
|
202981
204112
|
memoryCount: 0,
|
|
202982
204113
|
memoryBlockCount: 0,
|
|
202983
204114
|
pendingOpsCount: 0,
|
|
@@ -203016,7 +204147,6 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
|
|
|
203016
204147
|
const memoryBlockCount = meta3 ? Number(meta3.memory_block_count ?? 0) : 0;
|
|
203017
204148
|
const compartmentRow = db.prepare("SELECT COUNT(*) as count FROM compartments WHERE session_id = ?").get(sessionId);
|
|
203018
204149
|
const compartmentCount = compartmentRow?.count ?? 0;
|
|
203019
|
-
const factCount = 0;
|
|
203020
204150
|
let memoryCount = 0;
|
|
203021
204151
|
if (projectIdentity) {
|
|
203022
204152
|
const memRow = db.prepare("SELECT COUNT(*) as count FROM memories WHERE project_path = ? AND status = 'active'").get(projectIdentity);
|
|
@@ -203123,7 +204253,6 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
|
|
|
203123
204253
|
contextLimit,
|
|
203124
204254
|
systemPromptTokens: calibrated.systemTokens,
|
|
203125
204255
|
compartmentCount,
|
|
203126
|
-
factCount,
|
|
203127
204256
|
memoryCount,
|
|
203128
204257
|
memoryBlockCount,
|
|
203129
204258
|
pendingOpsCount,
|
|
@@ -204136,8 +205265,8 @@ function createCtxMemoryTool(deps) {
|
|
|
204136
205265
|
}
|
|
204137
205266
|
});
|
|
204138
205267
|
const idList = targets.map((t) => t.memoryId).join(", ");
|
|
204139
|
-
const
|
|
204140
|
-
return args.reason?.trim() ? `Archived ${
|
|
205268
|
+
const plural2 = targets.length > 1 ? "memories" : "memory";
|
|
205269
|
+
return args.reason?.trim() ? `Archived ${plural2} [ID: ${idList}] (${args.reason.trim()}).` : `Archived ${plural2} [ID: ${idList}].`;
|
|
204141
205270
|
}
|
|
204142
205271
|
return "Error: Unknown action.";
|
|
204143
205272
|
}
|
|
@@ -204542,10 +205671,12 @@ Sources (omit for a broad search across all):
|
|
|
204542
205671
|
- memory: curated cross-session project knowledge — rules, constraints, conventions.
|
|
204543
205672
|
- 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
205673
|
- git_commit: this repository's commit history.
|
|
205674
|
+
- note: parked decisions, follow-ups, and dismissed notes with their recorded text.
|
|
204545
205675
|
|
|
204546
205676
|
Picking sources:
|
|
204547
205677
|
- "when did this change / was this working before" → ["git_commit", "message"]
|
|
204548
205678
|
- "did we discuss this earlier" → ["message"]
|
|
205679
|
+
- "did we decide something about this / leave a follow-up" → ["note"]
|
|
204549
205680
|
- "what's our convention / rule for X" → ["memory"]`;
|
|
204550
205681
|
var DEFAULT_CTX_SEARCH_LIMIT = 10;
|
|
204551
205682
|
// src/tools/ctx-search/tools.ts
|
|
@@ -204557,7 +205688,8 @@ var VALID_SOURCES = new Set([
|
|
|
204557
205688
|
"memory",
|
|
204558
205689
|
"message",
|
|
204559
205690
|
"git_commit",
|
|
204560
|
-
"primer"
|
|
205691
|
+
"primer",
|
|
205692
|
+
"note"
|
|
204561
205693
|
]);
|
|
204562
205694
|
function normalizeLimit3(limit) {
|
|
204563
205695
|
if (typeof limit !== "number" || !Number.isFinite(limit)) {
|
|
@@ -204600,7 +205732,8 @@ function formatAge2(committedAtMs) {
|
|
|
204600
205732
|
const years = Math.floor(days / 365);
|
|
204601
205733
|
return years === 1 ? "1y ago" : `${years}y ago`;
|
|
204602
205734
|
}
|
|
204603
|
-
|
|
205735
|
+
var NOTE_EXPAND_HINT = "Use ctx_expand(start=N-10, end=N) around any note @msg anchor above to read the surrounding conversation context.";
|
|
205736
|
+
function formatResult(result, index, currentSessionId) {
|
|
204604
205737
|
if (result.source === "memory") {
|
|
204605
205738
|
const source = result.sourceName ? ` source=${result.sourceName}` : "";
|
|
204606
205739
|
return [
|
|
@@ -204621,6 +205754,14 @@ function formatResult(result, index) {
|
|
|
204621
205754
|
`[${index}] [primer] score=${result.score.toFixed(2)} id=${result.primerId} support=${result.support} match=${result.matchType}`,
|
|
204622
205755
|
result.content
|
|
204623
205756
|
].join(`
|
|
205757
|
+
`);
|
|
205758
|
+
}
|
|
205759
|
+
if (result.source === "note") {
|
|
205760
|
+
const anchor = result.anchorOrdinal !== null && result.sourceSessionId === currentSessionId ? ` @msg ${result.anchorOrdinal}` : "";
|
|
205761
|
+
return [
|
|
205762
|
+
`[${index}] [note] score=${result.score.toFixed(2)} id=#${result.noteId} status=${result.status} ${formatAge2(result.createdAt)}${anchor}`,
|
|
205763
|
+
result.content
|
|
205764
|
+
].join(`
|
|
204624
205765
|
`);
|
|
204625
205766
|
}
|
|
204626
205767
|
if (result.source === "compartment") {
|
|
@@ -204638,14 +205779,17 @@ function formatResult(result, index) {
|
|
|
204638
205779
|
].join(`
|
|
204639
205780
|
`);
|
|
204640
205781
|
}
|
|
204641
|
-
function formatSearchResults(query, results) {
|
|
205782
|
+
function formatSearchResults(query, results, currentSessionId) {
|
|
204642
205783
|
if (results.length === 0) {
|
|
204643
|
-
return `No results found for "${query}" across memories, primers, git commits, or message history.`;
|
|
205784
|
+
return `No results found for "${query}" across notes, memories, primers, git commits, or message history.`;
|
|
204644
205785
|
}
|
|
204645
|
-
const bodyParts = results.map((result, index) => formatResult(result, index + 1));
|
|
205786
|
+
const bodyParts = results.map((result, index) => formatResult(result, index + 1, currentSessionId));
|
|
204646
205787
|
if (results.some((result) => result.source === "message" || result.source === "compartment")) {
|
|
204647
205788
|
bodyParts.push("Use ctx_expand(start, end) with the range from any message result above to read the full conversation context.");
|
|
204648
205789
|
}
|
|
205790
|
+
if (results.some((result) => result.source === "note" && result.anchorOrdinal !== null && result.sourceSessionId === currentSessionId)) {
|
|
205791
|
+
bodyParts.push(NOTE_EXPAND_HINT);
|
|
205792
|
+
}
|
|
204649
205793
|
const body = bodyParts.join(`
|
|
204650
205794
|
|
|
204651
205795
|
`);
|
|
@@ -204659,7 +205803,7 @@ function createCtxSearchTool(deps) {
|
|
|
204659
205803
|
args: {
|
|
204660
205804
|
query: tool5.schema.string().describe("Search query. Matches against memory content, Primers, git commit messages, and raw user/assistant message text."),
|
|
204661
205805
|
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.')
|
|
205806
|
+
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
205807
|
},
|
|
204664
205808
|
async execute(args, toolContext) {
|
|
204665
205809
|
const query = args.query?.trim();
|
|
@@ -204691,7 +205835,7 @@ function createCtxSearchTool(deps) {
|
|
|
204691
205835
|
visibleMemoryIds,
|
|
204692
205836
|
explicitSearch: true
|
|
204693
205837
|
});
|
|
204694
|
-
return formatSearchResults(query, results);
|
|
205838
|
+
return formatSearchResults(query, results, toolContext.sessionID);
|
|
204695
205839
|
}
|
|
204696
205840
|
});
|
|
204697
205841
|
}
|
|
@@ -204748,14 +205892,13 @@ function createToolRegistry(args) {
|
|
|
204748
205892
|
return {};
|
|
204749
205893
|
}
|
|
204750
205894
|
ensureProjectRegisteredFromOpenCodeDirectory(ctx.directory, db);
|
|
204751
|
-
const resolveProjectPath = (directory) =>
|
|
204752
|
-
const ctxReduceEnabled = pluginConfig.ctx_reduce_enabled !== false;
|
|
205895
|
+
const resolveProjectPath = (directory) => resolveProjectIdentityOrFallback(directory);
|
|
204753
205896
|
const memoryEnabled = pluginConfig.memory?.enabled !== false;
|
|
204754
205897
|
const allTools = {
|
|
204755
|
-
...
|
|
205898
|
+
...createCtxReduceTools({
|
|
204756
205899
|
db,
|
|
204757
205900
|
protectedTags: pluginConfig.protected_tags ?? DEFAULT_PROTECTED_TAGS
|
|
204758
|
-
})
|
|
205901
|
+
}),
|
|
204759
205902
|
...createCtxExpandTools({ db }),
|
|
204760
205903
|
...createCtxNoteTools({
|
|
204761
205904
|
db,
|
|
@@ -205198,7 +206341,7 @@ var server = async (ctx) => {
|
|
|
205198
206341
|
const dreamerRunnable = isDreamerRunnable(pluginConfig);
|
|
205199
206342
|
const timerRegistration = {
|
|
205200
206343
|
directory: ctx.directory,
|
|
205201
|
-
projectIdentity:
|
|
206344
|
+
projectIdentity: resolveProjectIdentityOrFallback(ctx.directory),
|
|
205202
206345
|
client: ctx.client,
|
|
205203
206346
|
dreamerConfig: dreamerRunnable ? pluginConfig.dreamer : undefined,
|
|
205204
206347
|
language: pluginConfig.language,
|