@cortexkit/opencode-magic-context 0.9.0 → 0.10.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 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli.js +6 -3
- package/dist/config/schema/magic-context.d.ts +0 -4
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +6 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/derive-budgets.d.ts +57 -0
- package/dist/hooks/magic-context/derive-budgets.d.ts.map +1 -0
- package/dist/hooks/magic-context/event-handler.d.ts +0 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts +1 -3
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +3 -2
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/nudge-injection.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +7 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +293 -142
- 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/tui-action-consumer.d.ts.map +1 -1
- package/dist/shared/models-dev-cache.d.ts +52 -4
- package/dist/shared/models-dev-cache.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/shared/models-dev-cache.test.ts +228 -0
- package/src/shared/models-dev-cache.ts +146 -28
package/dist/index.js
CHANGED
|
@@ -14070,7 +14070,7 @@ var init_agent_overrides = __esm(() => {
|
|
|
14070
14070
|
});
|
|
14071
14071
|
|
|
14072
14072
|
// src/config/schema/magic-context.ts
|
|
14073
|
-
var DEFAULT_NUDGE_INTERVAL_TOKENS = 1e4, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65,
|
|
14073
|
+
var DEFAULT_NUDGE_INTERVAL_TOKENS = 1e4, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65, DEFAULT_HISTORIAN_TIMEOUT_MS = 300000, DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15, DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2", DREAMER_TASKS, DreamingTaskSchema, DEFAULT_DREAMER_TASKS, DreamerConfigSchema, SidekickConfigSchema, BaseEmbeddingConfigSchema, EmbeddingConfigSchema, MagicContextConfigSchema;
|
|
14074
14074
|
var init_magic_context = __esm(() => {
|
|
14075
14075
|
init_zod();
|
|
14076
14076
|
init_agent_overrides();
|
|
@@ -14156,7 +14156,6 @@ var init_magic_context = __esm(() => {
|
|
|
14156
14156
|
drop_tool_structure: exports_external.boolean().default(true),
|
|
14157
14157
|
clear_reasoning_age: exports_external.number().min(10).default(50),
|
|
14158
14158
|
iteration_nudge_threshold: exports_external.number().min(5).default(15),
|
|
14159
|
-
compartment_token_budget: exports_external.number().min(1e4).default(DEFAULT_COMPARTMENT_TOKEN_BUDGET),
|
|
14160
14159
|
history_budget_percentage: exports_external.number().min(0.05).max(0.5).default(DEFAULT_HISTORY_BUDGET_PERCENTAGE),
|
|
14161
14160
|
historian_timeout_ms: exports_external.number().min(60000).default(DEFAULT_HISTORIAN_TIMEOUT_MS),
|
|
14162
14161
|
commit_cluster_trigger: exports_external.object({
|
|
@@ -18374,6 +18373,145 @@ var init_storage = __esm(() => {
|
|
|
18374
18373
|
init_storage_tags();
|
|
18375
18374
|
});
|
|
18376
18375
|
|
|
18376
|
+
// src/shared/models-dev-cache.ts
|
|
18377
|
+
import { createHash } from "crypto";
|
|
18378
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
18379
|
+
import { homedir as homedir5, platform as platform2 } from "os";
|
|
18380
|
+
import { join as join11 } from "path";
|
|
18381
|
+
function hashFast(input) {
|
|
18382
|
+
return createHash("sha1").update(input).digest("hex");
|
|
18383
|
+
}
|
|
18384
|
+
function getModelsJsonPath() {
|
|
18385
|
+
const explicit = process.env.OPENCODE_MODELS_PATH?.trim();
|
|
18386
|
+
if (explicit)
|
|
18387
|
+
return explicit;
|
|
18388
|
+
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
18389
|
+
const os3 = platform2();
|
|
18390
|
+
let cacheBase;
|
|
18391
|
+
if (xdgCache) {
|
|
18392
|
+
cacheBase = xdgCache;
|
|
18393
|
+
} else if (os3 === "win32") {
|
|
18394
|
+
cacheBase = process.env.LOCALAPPDATA ?? join11(homedir5(), "AppData", "Local");
|
|
18395
|
+
} else {
|
|
18396
|
+
cacheBase = join11(homedir5(), ".cache");
|
|
18397
|
+
}
|
|
18398
|
+
const source = process.env.OPENCODE_MODELS_URL?.trim();
|
|
18399
|
+
const filename = source && source !== "https://models.dev" ? `models-${hashFast(source)}.json` : "models.json";
|
|
18400
|
+
return join11(cacheBase, "opencode", filename);
|
|
18401
|
+
}
|
|
18402
|
+
function getOpencodeConfigPath() {
|
|
18403
|
+
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
18404
|
+
const configDir = envDir ? envDir : platform2() === "win32" ? join11(homedir5(), ".config", "opencode") : join11(process.env.XDG_CONFIG_HOME || join11(homedir5(), ".config"), "opencode");
|
|
18405
|
+
const jsonc = join11(configDir, "opencode.jsonc");
|
|
18406
|
+
if (existsSync5(jsonc))
|
|
18407
|
+
return jsonc;
|
|
18408
|
+
const json2 = join11(configDir, "opencode.json");
|
|
18409
|
+
if (existsSync5(json2))
|
|
18410
|
+
return json2;
|
|
18411
|
+
return null;
|
|
18412
|
+
}
|
|
18413
|
+
function loadModelsDevLimitsFromFile() {
|
|
18414
|
+
const limits = new Map;
|
|
18415
|
+
const modelsJsonPath = getModelsJsonPath();
|
|
18416
|
+
let fileFound = false;
|
|
18417
|
+
try {
|
|
18418
|
+
if (existsSync5(modelsJsonPath)) {
|
|
18419
|
+
fileFound = true;
|
|
18420
|
+
const raw = readFileSync4(modelsJsonPath, "utf-8");
|
|
18421
|
+
const data = JSON.parse(raw);
|
|
18422
|
+
for (const [providerId, provider2] of Object.entries(data)) {
|
|
18423
|
+
if (!provider2?.models || typeof provider2.models !== "object")
|
|
18424
|
+
continue;
|
|
18425
|
+
for (const [modelId, model] of Object.entries(provider2.models)) {
|
|
18426
|
+
const context = model?.limit?.context;
|
|
18427
|
+
if (typeof context === "number" && context > 0) {
|
|
18428
|
+
limits.set(`${providerId}/${modelId}`, context);
|
|
18429
|
+
const modes = model?.experimental?.modes;
|
|
18430
|
+
if (modes && typeof modes === "object") {
|
|
18431
|
+
for (const mode of Object.keys(modes)) {
|
|
18432
|
+
limits.set(`${providerId}/${modelId}-${mode}`, context);
|
|
18433
|
+
}
|
|
18434
|
+
}
|
|
18435
|
+
}
|
|
18436
|
+
}
|
|
18437
|
+
}
|
|
18438
|
+
}
|
|
18439
|
+
} catch (error48) {
|
|
18440
|
+
sessionLog("global", `models-dev-cache: failed to read models.json at ${modelsJsonPath}:`, error48 instanceof Error ? error48.message : String(error48));
|
|
18441
|
+
}
|
|
18442
|
+
try {
|
|
18443
|
+
const configPath = getOpencodeConfigPath();
|
|
18444
|
+
if (configPath && existsSync5(configPath)) {
|
|
18445
|
+
let raw = readFileSync4(configPath, "utf-8");
|
|
18446
|
+
raw = raw.replace(/"(?:[^"\\]|\\.)*"|\/\/.*$/gm, (match) => match.startsWith('"') ? match : "");
|
|
18447
|
+
const config2 = JSON.parse(raw);
|
|
18448
|
+
if (config2.provider && typeof config2.provider === "object") {
|
|
18449
|
+
for (const [providerId, provider2] of Object.entries(config2.provider)) {
|
|
18450
|
+
if (!provider2?.models || typeof provider2.models !== "object")
|
|
18451
|
+
continue;
|
|
18452
|
+
for (const [modelId, model] of Object.entries(provider2.models)) {
|
|
18453
|
+
const context = model?.limit?.context;
|
|
18454
|
+
if (typeof context === "number" && context > 0) {
|
|
18455
|
+
limits.set(`${providerId}/${modelId}`, context);
|
|
18456
|
+
}
|
|
18457
|
+
}
|
|
18458
|
+
}
|
|
18459
|
+
}
|
|
18460
|
+
}
|
|
18461
|
+
} catch (error48) {
|
|
18462
|
+
sessionLog("global", "models-dev-cache: failed to read opencode config for custom models:", error48 instanceof Error ? error48.message : String(error48));
|
|
18463
|
+
}
|
|
18464
|
+
sessionLog("global", `models-dev-cache: file-layer loaded ${limits.size} model limits (modelsJsonPath=${modelsJsonPath}, found=${fileFound})`);
|
|
18465
|
+
return limits;
|
|
18466
|
+
}
|
|
18467
|
+
async function refreshModelLimitsFromApi(client) {
|
|
18468
|
+
try {
|
|
18469
|
+
const result = await client.config.providers();
|
|
18470
|
+
const data = result.data;
|
|
18471
|
+
const providers = data?.providers;
|
|
18472
|
+
if (!Array.isArray(providers)) {
|
|
18473
|
+
sessionLog("global", "models-dev-cache: API refresh returned no providers payload");
|
|
18474
|
+
return;
|
|
18475
|
+
}
|
|
18476
|
+
const map2 = new Map;
|
|
18477
|
+
for (const entry of providers) {
|
|
18478
|
+
const p = entry;
|
|
18479
|
+
if (!p?.id || !p.models || typeof p.models !== "object")
|
|
18480
|
+
continue;
|
|
18481
|
+
for (const [modelId, model] of Object.entries(p.models)) {
|
|
18482
|
+
const context = model?.limit?.context;
|
|
18483
|
+
if (typeof context === "number" && context > 0) {
|
|
18484
|
+
map2.set(`${p.id}/${modelId}`, context);
|
|
18485
|
+
}
|
|
18486
|
+
}
|
|
18487
|
+
}
|
|
18488
|
+
apiCache = map2;
|
|
18489
|
+
apiLoadedAt = Date.now();
|
|
18490
|
+
sessionLog("global", `models-dev-cache: API layer loaded ${map2.size} model limits`);
|
|
18491
|
+
} catch (error48) {
|
|
18492
|
+
sessionLog("global", "models-dev-cache: API refresh failed:", error48 instanceof Error ? error48.message : String(error48));
|
|
18493
|
+
}
|
|
18494
|
+
}
|
|
18495
|
+
function getModelsDevContextLimit(providerID, modelID) {
|
|
18496
|
+
const key = `${providerID}/${modelID}`;
|
|
18497
|
+
if (apiCache) {
|
|
18498
|
+
const fromApi = apiCache.get(key);
|
|
18499
|
+
if (typeof fromApi === "number")
|
|
18500
|
+
return fromApi;
|
|
18501
|
+
}
|
|
18502
|
+
const now = Date.now();
|
|
18503
|
+
if (!fileCache || now - fileLastAttempt > RELOAD_INTERVAL_MS) {
|
|
18504
|
+
fileLastAttempt = now;
|
|
18505
|
+
fileCache = loadModelsDevLimitsFromFile();
|
|
18506
|
+
}
|
|
18507
|
+
return fileCache.get(key);
|
|
18508
|
+
}
|
|
18509
|
+
var RELOAD_INTERVAL_MS, apiCache = null, apiLoadedAt = 0, fileCache = null, fileLastAttempt = 0;
|
|
18510
|
+
var init_models_dev_cache = __esm(() => {
|
|
18511
|
+
init_logger();
|
|
18512
|
+
RELOAD_INTERVAL_MS = 5 * 60 * 1000;
|
|
18513
|
+
});
|
|
18514
|
+
|
|
18377
18515
|
// src/features/magic-context/memory/project-identity.ts
|
|
18378
18516
|
import { execSync } from "child_process";
|
|
18379
18517
|
import path3 from "path";
|
|
@@ -18566,6 +18704,67 @@ var init_send_session_notification = __esm(() => {
|
|
|
18566
18704
|
init_logger();
|
|
18567
18705
|
});
|
|
18568
18706
|
|
|
18707
|
+
// src/hooks/magic-context/derive-budgets.ts
|
|
18708
|
+
var exports_derive_budgets = {};
|
|
18709
|
+
__export(exports_derive_budgets, {
|
|
18710
|
+
resolveHistorianContextLimit: () => resolveHistorianContextLimit,
|
|
18711
|
+
deriveTriggerBudget: () => deriveTriggerBudget,
|
|
18712
|
+
deriveHistorianChunkTokens: () => deriveHistorianChunkTokens
|
|
18713
|
+
});
|
|
18714
|
+
function deriveTriggerBudget(mainContextLimit, executeThresholdPercentage) {
|
|
18715
|
+
if (!Number.isFinite(mainContextLimit) || mainContextLimit <= 0) {
|
|
18716
|
+
return TRIGGER_BUDGET_MIN;
|
|
18717
|
+
}
|
|
18718
|
+
const thresholdFraction = Math.max(0, executeThresholdPercentage) / 100;
|
|
18719
|
+
const usable = mainContextLimit * thresholdFraction;
|
|
18720
|
+
const derived = Math.round(usable * TRIGGER_BUDGET_PERCENTAGE);
|
|
18721
|
+
return Math.max(TRIGGER_BUDGET_MIN, Math.min(TRIGGER_BUDGET_MAX, derived));
|
|
18722
|
+
}
|
|
18723
|
+
function deriveHistorianChunkTokens(historianContextLimit) {
|
|
18724
|
+
if (!Number.isFinite(historianContextLimit) || historianContextLimit <= 0) {
|
|
18725
|
+
return HISTORIAN_CHUNK_MIN;
|
|
18726
|
+
}
|
|
18727
|
+
const derived = Math.round(historianContextLimit * HISTORIAN_CHUNK_PERCENTAGE);
|
|
18728
|
+
return Math.max(HISTORIAN_CHUNK_MIN, Math.min(HISTORIAN_CHUNK_MAX, derived));
|
|
18729
|
+
}
|
|
18730
|
+
function resolveHistorianContextLimit(historianModelOverride) {
|
|
18731
|
+
if (typeof historianModelOverride === "string" && historianModelOverride.includes("/")) {
|
|
18732
|
+
const [providerID, ...rest] = historianModelOverride.split("/");
|
|
18733
|
+
const modelID = rest.join("/");
|
|
18734
|
+
if (providerID && modelID) {
|
|
18735
|
+
const limit = getModelsDevContextLimit(providerID, modelID);
|
|
18736
|
+
if (typeof limit === "number" && limit > 0)
|
|
18737
|
+
return limit;
|
|
18738
|
+
}
|
|
18739
|
+
return DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
|
|
18740
|
+
}
|
|
18741
|
+
if (typeof historianModelOverride === "string" && historianModelOverride.trim() !== "") {
|
|
18742
|
+
console.warn(`[magic-context] historian.model "${historianModelOverride}" lacks provider prefix ("provider/model-id"); using fallback chain for chunk-budget derivation.`);
|
|
18743
|
+
}
|
|
18744
|
+
const chain = AGENT_MODEL_REQUIREMENTS[HISTORIAN_AGENT]?.fallbackChain;
|
|
18745
|
+
if (!chain || chain.length === 0)
|
|
18746
|
+
return DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
|
|
18747
|
+
const expanded = expandFallbackChain(chain);
|
|
18748
|
+
let minLimit;
|
|
18749
|
+
for (const key of expanded) {
|
|
18750
|
+
const [providerID, ...rest] = key.split("/");
|
|
18751
|
+
const modelID = rest.join("/");
|
|
18752
|
+
if (!providerID || !modelID)
|
|
18753
|
+
continue;
|
|
18754
|
+
const limit = getModelsDevContextLimit(providerID, modelID);
|
|
18755
|
+
if (typeof limit !== "number" || limit <= 0)
|
|
18756
|
+
continue;
|
|
18757
|
+
if (minLimit === undefined || limit < minLimit)
|
|
18758
|
+
minLimit = limit;
|
|
18759
|
+
}
|
|
18760
|
+
return minLimit ?? DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
|
|
18761
|
+
}
|
|
18762
|
+
var TRIGGER_BUDGET_PERCENTAGE = 0.05, TRIGGER_BUDGET_MIN = 5000, TRIGGER_BUDGET_MAX = 50000, HISTORIAN_CHUNK_PERCENTAGE = 0.25, HISTORIAN_CHUNK_MIN = 8000, HISTORIAN_CHUNK_MAX = 50000, DEFAULT_HISTORIAN_CONTEXT_FALLBACK = 128000;
|
|
18763
|
+
var init_derive_budgets = __esm(() => {
|
|
18764
|
+
init_model_requirements();
|
|
18765
|
+
init_models_dev_cache();
|
|
18766
|
+
});
|
|
18767
|
+
|
|
18569
18768
|
// src/features/magic-context/compaction-marker.ts
|
|
18570
18769
|
import { Database as Database4 } from "bun:sqlite";
|
|
18571
18770
|
import { join as join12 } from "path";
|
|
@@ -19838,10 +20037,6 @@ function prepareCompartmentInjection(db, sessionId, messages, isCacheBusting, pr
|
|
|
19838
20037
|
return cached2;
|
|
19839
20038
|
}
|
|
19840
20039
|
const compartments = getCompartments(db, sessionId);
|
|
19841
|
-
if (compartments.length === 0) {
|
|
19842
|
-
injectionCache.delete(sessionId);
|
|
19843
|
-
return null;
|
|
19844
|
-
}
|
|
19845
20040
|
const facts = getSessionFacts(db, sessionId);
|
|
19846
20041
|
let memoryBlock;
|
|
19847
20042
|
let memoryCount = 0;
|
|
@@ -19860,7 +20055,24 @@ function prepareCompartmentInjection(db, sessionId, messages, isCacheBusting, pr
|
|
|
19860
20055
|
db.prepare("UPDATE session_meta SET memory_block_cache = ?, memory_block_count = ? WHERE session_id = ?").run(memoryBlock ?? "", memoryCount, sessionId);
|
|
19861
20056
|
}
|
|
19862
20057
|
}
|
|
20058
|
+
if (compartments.length === 0 && facts.length === 0 && !memoryBlock) {
|
|
20059
|
+
injectionCache.delete(sessionId);
|
|
20060
|
+
return null;
|
|
20061
|
+
}
|
|
19863
20062
|
const block = buildCompartmentBlock(compartments, facts, memoryBlock);
|
|
20063
|
+
if (compartments.length === 0) {
|
|
20064
|
+
const result2 = {
|
|
20065
|
+
block,
|
|
20066
|
+
compartmentEndMessage: 0,
|
|
20067
|
+
compartmentEndMessageId: "",
|
|
20068
|
+
compartmentCount: 0,
|
|
20069
|
+
skippedVisibleMessages: 0,
|
|
20070
|
+
factCount: facts.length,
|
|
20071
|
+
memoryCount
|
|
20072
|
+
};
|
|
20073
|
+
injectionCache.set(sessionId, result2);
|
|
20074
|
+
return result2;
|
|
20075
|
+
}
|
|
19864
20076
|
const lastCompartment = compartments[compartments.length - 1];
|
|
19865
20077
|
const lastEnd = lastCompartment.endMessage;
|
|
19866
20078
|
const lastEndMessageId = lastCompartment.endMessageId;
|
|
@@ -19917,7 +20129,11 @@ ${prepared.block}
|
|
|
19917
20129
|
${textPart.text}`;
|
|
19918
20130
|
}
|
|
19919
20131
|
const memoryLabel = prepared.memoryCount > 0 ? ` + ${prepared.memoryCount} memories` : "";
|
|
19920
|
-
|
|
20132
|
+
if (prepared.compartmentCount > 0) {
|
|
20133
|
+
sessionLog(sessionId, `injected ${prepared.compartmentCount} compartments + ${prepared.factCount} facts${memoryLabel} into message[0]`);
|
|
20134
|
+
} else {
|
|
20135
|
+
sessionLog(sessionId, `injected ${prepared.factCount} facts${memoryLabel} into message[0] (no compartments yet)`);
|
|
20136
|
+
}
|
|
19921
20137
|
return {
|
|
19922
20138
|
injected: true,
|
|
19923
20139
|
compartmentEndMessage: prepared.compartmentEndMessage,
|
|
@@ -19963,7 +20179,7 @@ async function runCompartmentAgent(deps) {
|
|
|
19963
20179
|
client,
|
|
19964
20180
|
db,
|
|
19965
20181
|
sessionId,
|
|
19966
|
-
|
|
20182
|
+
historianChunkTokens,
|
|
19967
20183
|
directory,
|
|
19968
20184
|
historianTimeoutMs,
|
|
19969
20185
|
getNotificationParams
|
|
@@ -19998,7 +20214,7 @@ No new compartments or facts were written. Rebuild or clear the broken compartme
|
|
|
19998
20214
|
if (protectedTailStart <= offset) {
|
|
19999
20215
|
return;
|
|
20000
20216
|
}
|
|
20001
|
-
const chunk = readSessionChunk(sessionId,
|
|
20217
|
+
const chunk = readSessionChunk(sessionId, historianChunkTokens, offset, protectedTailStart);
|
|
20002
20218
|
if (!chunk.text || chunk.messageCount === 0) {
|
|
20003
20219
|
return;
|
|
20004
20220
|
}
|
|
@@ -20141,7 +20357,7 @@ async function executeContextRecompInternal(deps) {
|
|
|
20141
20357
|
client,
|
|
20142
20358
|
db,
|
|
20143
20359
|
sessionId,
|
|
20144
|
-
|
|
20360
|
+
historianChunkTokens,
|
|
20145
20361
|
directory,
|
|
20146
20362
|
historianTimeoutMs,
|
|
20147
20363
|
getNotificationParams
|
|
@@ -20195,7 +20411,7 @@ No eligible raw history exists before the protected tail, so nothing was rebuilt
|
|
|
20195
20411
|
let candidateFacts = existingStaging?.facts ?? [];
|
|
20196
20412
|
let offset = existingStaging ? existingStaging.lastEndMessage + 1 : 1;
|
|
20197
20413
|
let passCount = existingStaging?.passCount ?? 0;
|
|
20198
|
-
let currentTokenBudget =
|
|
20414
|
+
let currentTokenBudget = historianChunkTokens;
|
|
20199
20415
|
let passAttempt = 1;
|
|
20200
20416
|
const resumed = existingStaging !== null;
|
|
20201
20417
|
if (resumed) {
|
|
@@ -20293,7 +20509,7 @@ Nothing was written.`;
|
|
|
20293
20509
|
];
|
|
20294
20510
|
candidateFacts = validatedPass.facts ?? [];
|
|
20295
20511
|
passCount += 1;
|
|
20296
|
-
currentTokenBudget =
|
|
20512
|
+
currentTokenBudget = historianChunkTokens;
|
|
20297
20513
|
passAttempt = 1;
|
|
20298
20514
|
saveRecompStagingPass(db, sessionId, passCount, candidateCompartments, candidateFacts);
|
|
20299
20515
|
const nextOffset = (validatedPass.compartments?.[validatedPass.compartments.length - 1]?.endMessage ?? chunk.endIndex) + 1;
|
|
@@ -28493,7 +28709,7 @@ Check verifiable memories against actual repository state. Update stale wording,
|
|
|
28493
28709
|
4. **Be conservative.** If you cannot find the referenced code but it might be in a location you haven't checked, do NOT archive. Move on.
|
|
28494
28710
|
|
|
28495
28711
|
### Verification examples
|
|
28496
|
-
- Memory: "
|
|
28712
|
+
- Memory: "history_budget_percentage defaults to 0.15" \u2192 grep schema for \`history_budget_percentage\`, check \`.default(...)\`
|
|
28497
28713
|
- Memory: "Durable state lives in ~/.local/share/opencode/storage/plugin/magic-context/context.db" \u2192 check storage-db.ts for the path construction
|
|
28498
28714
|
- Memory: "ctx_search searches memories, facts, and history" \u2192 grep for ctx_search tool definition and unified search implementation
|
|
28499
28715
|
|
|
@@ -30222,110 +30438,13 @@ function createCompactionHandler() {
|
|
|
30222
30438
|
}
|
|
30223
30439
|
};
|
|
30224
30440
|
}
|
|
30225
|
-
// src/shared/models-dev-cache.ts
|
|
30226
|
-
init_logger();
|
|
30227
|
-
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
30228
|
-
import { homedir as homedir5, platform as platform2 } from "os";
|
|
30229
|
-
import { join as join11 } from "path";
|
|
30230
|
-
var cachedLimits = null;
|
|
30231
|
-
var lastLoadAttempt = 0;
|
|
30232
|
-
var RELOAD_INTERVAL_MS = 5 * 60 * 1000;
|
|
30233
|
-
function getModelsJsonPath() {
|
|
30234
|
-
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
30235
|
-
const os3 = platform2();
|
|
30236
|
-
let cacheBase;
|
|
30237
|
-
if (xdgCache) {
|
|
30238
|
-
cacheBase = xdgCache;
|
|
30239
|
-
} else if (os3 === "win32") {
|
|
30240
|
-
cacheBase = process.env.LOCALAPPDATA ?? join11(homedir5(), "AppData", "Local");
|
|
30241
|
-
} else {
|
|
30242
|
-
cacheBase = join11(homedir5(), ".cache");
|
|
30243
|
-
}
|
|
30244
|
-
return join11(cacheBase, "opencode", "models.json");
|
|
30245
|
-
}
|
|
30246
|
-
function getOpencodeConfigPath() {
|
|
30247
|
-
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
30248
|
-
const configDir = envDir ? envDir : platform2() === "win32" ? join11(homedir5(), ".config", "opencode") : join11(process.env.XDG_CONFIG_HOME || join11(homedir5(), ".config"), "opencode");
|
|
30249
|
-
const jsonc = join11(configDir, "opencode.jsonc");
|
|
30250
|
-
if (existsSync5(jsonc))
|
|
30251
|
-
return jsonc;
|
|
30252
|
-
const json2 = join11(configDir, "opencode.json");
|
|
30253
|
-
if (existsSync5(json2))
|
|
30254
|
-
return json2;
|
|
30255
|
-
return null;
|
|
30256
|
-
}
|
|
30257
|
-
function loadModelsDevLimits() {
|
|
30258
|
-
const limits = new Map;
|
|
30259
|
-
const modelsJsonPath = getModelsJsonPath();
|
|
30260
|
-
try {
|
|
30261
|
-
if (existsSync5(modelsJsonPath)) {
|
|
30262
|
-
const raw = readFileSync4(modelsJsonPath, "utf-8");
|
|
30263
|
-
const data = JSON.parse(raw);
|
|
30264
|
-
for (const [providerId, provider2] of Object.entries(data)) {
|
|
30265
|
-
if (!provider2?.models || typeof provider2.models !== "object")
|
|
30266
|
-
continue;
|
|
30267
|
-
for (const [modelId, model] of Object.entries(provider2.models)) {
|
|
30268
|
-
const context = model?.limit?.context;
|
|
30269
|
-
if (typeof context === "number" && context > 0) {
|
|
30270
|
-
limits.set(`${providerId}/${modelId}`, context);
|
|
30271
|
-
const modes = model?.experimental?.modes;
|
|
30272
|
-
if (modes && typeof modes === "object") {
|
|
30273
|
-
for (const mode of Object.keys(modes)) {
|
|
30274
|
-
limits.set(`${providerId}/${modelId}-${mode}`, context);
|
|
30275
|
-
}
|
|
30276
|
-
}
|
|
30277
|
-
}
|
|
30278
|
-
}
|
|
30279
|
-
}
|
|
30280
|
-
}
|
|
30281
|
-
} catch (error48) {
|
|
30282
|
-
sessionLog("global", "models-dev-cache: failed to read models.json:", error48 instanceof Error ? error48.message : String(error48));
|
|
30283
|
-
}
|
|
30284
|
-
try {
|
|
30285
|
-
const configPath = getOpencodeConfigPath();
|
|
30286
|
-
if (configPath && existsSync5(configPath)) {
|
|
30287
|
-
let raw = readFileSync4(configPath, "utf-8");
|
|
30288
|
-
raw = raw.replace(/"(?:[^"\\]|\\.)*"|\/\/.*$/gm, (match) => match.startsWith('"') ? match : "");
|
|
30289
|
-
const config2 = JSON.parse(raw);
|
|
30290
|
-
if (config2.provider && typeof config2.provider === "object") {
|
|
30291
|
-
for (const [providerId, provider2] of Object.entries(config2.provider)) {
|
|
30292
|
-
if (!provider2?.models || typeof provider2.models !== "object")
|
|
30293
|
-
continue;
|
|
30294
|
-
for (const [modelId, model] of Object.entries(provider2.models)) {
|
|
30295
|
-
const context = model?.limit?.context;
|
|
30296
|
-
if (typeof context === "number" && context > 0) {
|
|
30297
|
-
limits.set(`${providerId}/${modelId}`, context);
|
|
30298
|
-
}
|
|
30299
|
-
}
|
|
30300
|
-
}
|
|
30301
|
-
}
|
|
30302
|
-
}
|
|
30303
|
-
} catch (error48) {
|
|
30304
|
-
sessionLog("global", "models-dev-cache: failed to read opencode config for custom models:", error48 instanceof Error ? error48.message : String(error48));
|
|
30305
|
-
}
|
|
30306
|
-
return limits;
|
|
30307
|
-
}
|
|
30308
|
-
function getModelsDevContextLimit(providerID, modelID) {
|
|
30309
|
-
const now = Date.now();
|
|
30310
|
-
if (!cachedLimits || now - lastLoadAttempt > RELOAD_INTERVAL_MS) {
|
|
30311
|
-
lastLoadAttempt = now;
|
|
30312
|
-
cachedLimits = loadModelsDevLimits();
|
|
30313
|
-
}
|
|
30314
|
-
return cachedLimits.get(`${providerID}/${modelID}`);
|
|
30315
|
-
}
|
|
30316
|
-
|
|
30317
30441
|
// src/hooks/magic-context/event-resolvers.ts
|
|
30442
|
+
init_models_dev_cache();
|
|
30318
30443
|
var DEFAULT_CONTEXT_LIMIT = 128000;
|
|
30319
|
-
function resolveContextLimit(providerID, modelID
|
|
30444
|
+
function resolveContextLimit(providerID, modelID) {
|
|
30320
30445
|
if (!providerID) {
|
|
30321
30446
|
return DEFAULT_CONTEXT_LIMIT;
|
|
30322
30447
|
}
|
|
30323
|
-
if (modelID) {
|
|
30324
|
-
const modelSpecific = config2.modelContextLimitsCache?.get(`${providerID}/${modelID}`);
|
|
30325
|
-
if (typeof modelSpecific === "number" && modelSpecific > 0) {
|
|
30326
|
-
return modelSpecific;
|
|
30327
|
-
}
|
|
30328
|
-
}
|
|
30329
30448
|
if (modelID) {
|
|
30330
30449
|
const modelsDevLimit = getModelsDevContextLimit(providerID, modelID);
|
|
30331
30450
|
if (modelsDevLimit !== undefined) {
|
|
@@ -30608,7 +30727,6 @@ init_storage_tags();
|
|
|
30608
30727
|
init_logger();
|
|
30609
30728
|
|
|
30610
30729
|
// src/hooks/magic-context/compartment-trigger.ts
|
|
30611
|
-
init_magic_context();
|
|
30612
30730
|
init_compartment_storage();
|
|
30613
30731
|
init_storage();
|
|
30614
30732
|
init_logger();
|
|
@@ -30686,7 +30804,7 @@ var TAIL_INFO_DEFAULTS = {
|
|
|
30686
30804
|
tokenEstimate: 0,
|
|
30687
30805
|
commitClusterCount: 0
|
|
30688
30806
|
};
|
|
30689
|
-
function getUnsummarizedTailInfo(db, sessionId,
|
|
30807
|
+
function getUnsummarizedTailInfo(db, sessionId, triggerBudget) {
|
|
30690
30808
|
return withRawSessionMessageCache(() => {
|
|
30691
30809
|
try {
|
|
30692
30810
|
const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
|
|
@@ -30697,7 +30815,7 @@ function getUnsummarizedTailInfo(db, sessionId, compartmentTokenBudget) {
|
|
|
30697
30815
|
if (!hasEligibleHistory) {
|
|
30698
30816
|
return { ...TAIL_INFO_DEFAULTS, nextStartOrdinal };
|
|
30699
30817
|
}
|
|
30700
|
-
const scanBudget = Math.max(MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE,
|
|
30818
|
+
const scanBudget = Math.max(MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE, triggerBudget * TAIL_SIZE_TRIGGER_MULTIPLIER);
|
|
30701
30819
|
const chunk = readSessionChunk(sessionId, scanBudget, nextStartOrdinal, protectedTailStart);
|
|
30702
30820
|
const isMeaningful = chunk.hasMore || chunk.tokenEstimate >= MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE || chunk.messageCount >= MIN_PROACTIVE_TAIL_MESSAGE_COUNT;
|
|
30703
30821
|
return {
|
|
@@ -30713,11 +30831,11 @@ function getUnsummarizedTailInfo(db, sessionId, compartmentTokenBudget) {
|
|
|
30713
30831
|
}
|
|
30714
30832
|
});
|
|
30715
30833
|
}
|
|
30716
|
-
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage,
|
|
30834
|
+
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, autoDropToolAge, protectedTagCount, clearReasoningAge, dropToolStructure = true, commitClusterTrigger) {
|
|
30717
30835
|
if (sessionMeta.compartmentInProgress) {
|
|
30718
30836
|
return { shouldFire: false };
|
|
30719
30837
|
}
|
|
30720
|
-
const tailInfo = getUnsummarizedTailInfo(db, sessionId,
|
|
30838
|
+
const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget);
|
|
30721
30839
|
if (!tailInfo.hasNewRawHistory) {
|
|
30722
30840
|
return { shouldFire: false };
|
|
30723
30841
|
}
|
|
@@ -30733,12 +30851,12 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
30733
30851
|
}
|
|
30734
30852
|
const clusterEnabled = commitClusterTrigger?.enabled ?? true;
|
|
30735
30853
|
const minClusters = commitClusterTrigger?.min_clusters ?? DEFAULT_MIN_COMMIT_CLUSTERS_FOR_TRIGGER;
|
|
30736
|
-
if (clusterEnabled && tailInfo.commitClusterCount >= minClusters && tailInfo.tokenEstimate >=
|
|
30854
|
+
if (clusterEnabled && tailInfo.commitClusterCount >= minClusters && tailInfo.tokenEstimate >= triggerBudget) {
|
|
30737
30855
|
sessionLog(sessionId, `compartment trigger: commit-cluster fire \u2014 ${tailInfo.commitClusterCount} clusters (min=${minClusters}), ~${tailInfo.tokenEstimate} tokens in eligible prefix`);
|
|
30738
30856
|
return { shouldFire: true, reason: "commit_clusters" };
|
|
30739
30857
|
}
|
|
30740
|
-
if (tailInfo.tokenEstimate >=
|
|
30741
|
-
sessionLog(sessionId, `compartment trigger: tail-size fire \u2014 ~${tailInfo.tokenEstimate} tokens exceeds ${
|
|
30858
|
+
if (tailInfo.tokenEstimate >= triggerBudget * TAIL_SIZE_TRIGGER_MULTIPLIER) {
|
|
30859
|
+
sessionLog(sessionId, `compartment trigger: tail-size fire \u2014 ~${tailInfo.tokenEstimate} tokens exceeds ${triggerBudget * TAIL_SIZE_TRIGGER_MULTIPLIER} budget threshold`);
|
|
30742
30860
|
return { shouldFire: true, reason: "tail_size" };
|
|
30743
30861
|
}
|
|
30744
30862
|
const proactiveTriggerPercentage = getProactiveCompartmentTriggerPercentage(executeThresholdPercentage);
|
|
@@ -31082,11 +31200,15 @@ Historian recomp started. Rebuilding compartments and facts from raw session his
|
|
|
31082
31200
|
};
|
|
31083
31201
|
}
|
|
31084
31202
|
|
|
31203
|
+
// src/hooks/magic-context/hook.ts
|
|
31204
|
+
init_derive_budgets();
|
|
31205
|
+
|
|
31085
31206
|
// src/hooks/magic-context/event-handler.ts
|
|
31086
31207
|
init_storage();
|
|
31087
31208
|
init_storage_meta_persisted();
|
|
31088
31209
|
init_logger();
|
|
31089
31210
|
init_compaction_marker_manager();
|
|
31211
|
+
init_derive_budgets();
|
|
31090
31212
|
|
|
31091
31213
|
// src/hooks/magic-context/event-payloads.ts
|
|
31092
31214
|
function getSessionProperties(properties) {
|
|
@@ -31158,7 +31280,6 @@ function getMessageRemovedInfo(properties) {
|
|
|
31158
31280
|
init_note_nudger();
|
|
31159
31281
|
|
|
31160
31282
|
// src/hooks/magic-context/transform-compartment-phase.ts
|
|
31161
|
-
init_magic_context();
|
|
31162
31283
|
init_compartment_storage();
|
|
31163
31284
|
init_storage();
|
|
31164
31285
|
init_logger();
|
|
@@ -31234,7 +31355,7 @@ async function runCompartmentPhase(args) {
|
|
|
31234
31355
|
client: args.client,
|
|
31235
31356
|
db: args.db,
|
|
31236
31357
|
sessionId: args.sessionId,
|
|
31237
|
-
|
|
31358
|
+
historianChunkTokens: args.historianChunkTokens,
|
|
31238
31359
|
historyBudgetTokens: args.historyBudgetTokens,
|
|
31239
31360
|
historianTimeoutMs: args.historianTimeoutMs,
|
|
31240
31361
|
directory: args.compartmentDirectory,
|
|
@@ -31255,7 +31376,7 @@ async function runCompartmentPhase(args) {
|
|
|
31255
31376
|
client: args.client,
|
|
31256
31377
|
db: args.db,
|
|
31257
31378
|
sessionId: args.sessionId,
|
|
31258
|
-
|
|
31379
|
+
historianChunkTokens: args.historianChunkTokens,
|
|
31259
31380
|
historyBudgetTokens: args.historyBudgetTokens,
|
|
31260
31381
|
historianTimeoutMs: args.historianTimeoutMs,
|
|
31261
31382
|
directory: args.compartmentDirectory,
|
|
@@ -31408,9 +31529,7 @@ function createEventHandler2(deps) {
|
|
|
31408
31529
|
}
|
|
31409
31530
|
if (hasUsageTokens) {
|
|
31410
31531
|
const totalInputTokens = (info.tokens?.input ?? 0) + (info.tokens?.cache?.read ?? 0) + (info.tokens?.cache?.write ?? 0);
|
|
31411
|
-
const contextLimit = resolveContextLimit(info.providerID, info.modelID
|
|
31412
|
-
modelContextLimitsCache: deps.config.modelContextLimitsCache
|
|
31413
|
-
});
|
|
31532
|
+
const contextLimit = resolveContextLimit(info.providerID, info.modelID);
|
|
31414
31533
|
const percentage = contextLimit > 0 ? totalInputTokens / contextLimit * 100 : 0;
|
|
31415
31534
|
sessionLog(info.sessionID, `event message.updated: totalInputTokens=${totalInputTokens} contextLimit=${contextLimit} percentage=${percentage.toFixed(1)}%`);
|
|
31416
31535
|
deps.contextUsageMap.set(info.sessionID, {
|
|
@@ -31430,7 +31549,9 @@ function createEventHandler2(deps) {
|
|
|
31430
31549
|
const sessionMeta = getOrCreateSessionMeta(deps.db, info.sessionID);
|
|
31431
31550
|
const previousPercentage = sessionMeta.lastContextPercentage;
|
|
31432
31551
|
if (!sessionMeta.isSubagent) {
|
|
31433
|
-
const
|
|
31552
|
+
const effectiveExecuteThreshold = resolveExecuteThreshold(deps.config.execute_threshold_percentage ?? 65, modelKey, 65);
|
|
31553
|
+
const triggerBudget = deriveTriggerBudget(contextLimit, effectiveExecuteThreshold);
|
|
31554
|
+
const triggerResult = checkCompartmentTrigger(deps.db, info.sessionID, sessionMeta, { percentage, inputTokens: totalInputTokens }, previousPercentage, effectiveExecuteThreshold, triggerBudget, deps.config.auto_drop_tool_age ?? 100, deps.config.protected_tags, deps.config.clear_reasoning_age ?? 50, deps.config.drop_tool_structure ?? true, deps.config.commit_cluster_trigger);
|
|
31434
31555
|
if (triggerResult.shouldFire) {
|
|
31435
31556
|
sessionLog(info.sessionID, `compartment trigger: firing (reason=${triggerResult.reason})`);
|
|
31436
31557
|
updateSessionMeta(deps.db, info.sessionID, {
|
|
@@ -31708,7 +31829,6 @@ function createTextCompleteHandler() {
|
|
|
31708
31829
|
}
|
|
31709
31830
|
|
|
31710
31831
|
// src/hooks/magic-context/transform.ts
|
|
31711
|
-
init_magic_context();
|
|
31712
31832
|
init_compartment_storage();
|
|
31713
31833
|
init_project_identity();
|
|
31714
31834
|
init_storage();
|
|
@@ -32789,6 +32909,14 @@ function isToolProtocolPart(part) {
|
|
|
32789
32909
|
function hasToolProtocolParts(message) {
|
|
32790
32910
|
return message.parts.some(isToolProtocolPart);
|
|
32791
32911
|
}
|
|
32912
|
+
function hasThinkingBearingParts(message) {
|
|
32913
|
+
return message.parts.some((part) => {
|
|
32914
|
+
if (part === null || typeof part !== "object")
|
|
32915
|
+
return false;
|
|
32916
|
+
const p = part;
|
|
32917
|
+
return p.type === "thinking" || p.type === "reasoning" || p.type === "redacted_thinking";
|
|
32918
|
+
});
|
|
32919
|
+
}
|
|
32792
32920
|
function isMessageDropped(message) {
|
|
32793
32921
|
const textParts = message.parts.filter(isTextPart);
|
|
32794
32922
|
if (textParts.length === 0)
|
|
@@ -32823,6 +32951,11 @@ function reinjectNudgeAtAnchor(messages, nudgeText, nudgePlacements, sessionId)
|
|
|
32823
32951
|
nudgePlacements.clear(sessionId);
|
|
32824
32952
|
return false;
|
|
32825
32953
|
}
|
|
32954
|
+
if (hasThinkingBearingParts(message)) {
|
|
32955
|
+
sessionLog(sessionId, `nudge anchor abandoned: message ${message.info.id} now contains thinking/reasoning parts (signed, immutable)`);
|
|
32956
|
+
nudgePlacements.clear(sessionId);
|
|
32957
|
+
return false;
|
|
32958
|
+
}
|
|
32826
32959
|
for (let j = message.parts.length - 1;j >= 0; j--) {
|
|
32827
32960
|
const part = message.parts[j];
|
|
32828
32961
|
if (isTextPart(part)) {
|
|
@@ -32851,6 +32984,8 @@ function appendNudgeToAssistant(messages, nudge, nudgePlacements, sessionId) {
|
|
|
32851
32984
|
continue;
|
|
32852
32985
|
if (isMessageDropped(message))
|
|
32853
32986
|
continue;
|
|
32987
|
+
if (hasThinkingBearingParts(message))
|
|
32988
|
+
continue;
|
|
32854
32989
|
for (let j = message.parts.length - 1;j >= 0; j--) {
|
|
32855
32990
|
const part = message.parts[j];
|
|
32856
32991
|
if (isTextPart(part)) {
|
|
@@ -33134,12 +33269,13 @@ function runPostTransformPhase(args) {
|
|
|
33134
33269
|
const forceMaterialization = args.fullFeatureMode && args.contextUsage.percentage >= args.forceMaterializationPercentage;
|
|
33135
33270
|
const activeCompartmentRun = args.canRunCompartments ? getActiveCompartmentRun(args.sessionId) : undefined;
|
|
33136
33271
|
const compartmentRunning = args.canRunCompartments && !args.awaitedCompartmentRun && activeCompartmentRun !== undefined;
|
|
33137
|
-
const
|
|
33272
|
+
const emergencyBypassCompartmentGate = forceMaterialization;
|
|
33273
|
+
const shouldReadPendingOps = isExplicitFlush || args.schedulerDecision === "execute" || forceMaterialization || compartmentRunning;
|
|
33138
33274
|
const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
|
|
33139
33275
|
const hasPendingUserOps = pendingOps.length > 0;
|
|
33140
|
-
const shouldApplyPendingOps = (args.schedulerDecision === "execute" || isExplicitFlush) && !compartmentRunning;
|
|
33276
|
+
const shouldApplyPendingOps = (args.schedulerDecision === "execute" || isExplicitFlush || forceMaterialization) && (!compartmentRunning || emergencyBypassCompartmentGate);
|
|
33141
33277
|
const isCacheBustingPass = isExplicitFlush || shouldApplyPendingOps;
|
|
33142
|
-
const shouldRunHeuristics = args.fullFeatureMode && !compartmentRunning && (isExplicitFlush || forceMaterialization || args.schedulerDecision === "execute" && !alreadyRanThisTurn);
|
|
33278
|
+
const shouldRunHeuristics = args.fullFeatureMode && (!compartmentRunning || emergencyBypassCompartmentGate) && (isExplicitFlush || forceMaterialization || args.schedulerDecision === "execute" && !alreadyRanThisTurn);
|
|
33143
33279
|
if (shouldRunHeuristics) {
|
|
33144
33280
|
const reason = isExplicitFlush ? "explicit_flush" : forceMaterialization ? `force_materialization (${args.contextUsage.percentage.toFixed(1)}% >= ${args.forceMaterializationPercentage}%)` : `scheduler_execute (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
|
|
33145
33281
|
sessionLog(args.sessionId, `heuristics WILL RUN \u2014 reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=${args.currentTurnId}`);
|
|
@@ -33148,7 +33284,11 @@ function runPostTransformPhase(args) {
|
|
|
33148
33284
|
sessionLog(args.sessionId, `transform: skipping heuristics (already ran for turn ${args.currentTurnId})`);
|
|
33149
33285
|
}
|
|
33150
33286
|
if (compartmentRunning && hasPendingUserOps) {
|
|
33151
|
-
|
|
33287
|
+
if (emergencyBypassCompartmentGate) {
|
|
33288
|
+
sessionLog(args.sessionId, `transform: emergency bypass \u2014 applying ${pendingOps.length} pending ops while compartment agent runs (${args.contextUsage.percentage.toFixed(1)}%)`);
|
|
33289
|
+
} else {
|
|
33290
|
+
sessionLog(args.sessionId, "transform: deferring pending ops \u2014 compartment agent in progress");
|
|
33291
|
+
}
|
|
33152
33292
|
}
|
|
33153
33293
|
try {
|
|
33154
33294
|
if (shouldApplyPendingOps) {
|
|
@@ -33237,7 +33377,11 @@ function runPostTransformPhase(args) {
|
|
|
33237
33377
|
if (args.fullFeatureMode && args.pendingCompartmentInjection) {
|
|
33238
33378
|
const compartmentResult = renderCompartmentInjection(args.sessionId, args.messages, args.pendingCompartmentInjection);
|
|
33239
33379
|
if (compartmentResult.injected) {
|
|
33240
|
-
|
|
33380
|
+
if (compartmentResult.compartmentCount > 0) {
|
|
33381
|
+
sessionLog(args.sessionId, `transform: injected ${compartmentResult.compartmentCount} compartments ` + `(covering raw messages 1-${compartmentResult.compartmentEndMessage}, ` + `skipped ${compartmentResult.skippedVisibleMessages} visible messages)`);
|
|
33382
|
+
} else {
|
|
33383
|
+
sessionLog(args.sessionId, "transform: injected memories/facts block (no compartments yet)");
|
|
33384
|
+
}
|
|
33241
33385
|
}
|
|
33242
33386
|
}
|
|
33243
33387
|
{
|
|
@@ -33503,7 +33647,7 @@ function createTransform(deps) {
|
|
|
33503
33647
|
client: deps.client,
|
|
33504
33648
|
db,
|
|
33505
33649
|
sessionId,
|
|
33506
|
-
|
|
33650
|
+
historianChunkTokens: deps.getHistorianChunkTokens?.() ?? 20000,
|
|
33507
33651
|
historyBudgetTokens,
|
|
33508
33652
|
historianTimeoutMs: deps.historianTimeoutMs,
|
|
33509
33653
|
directory: compartmentDirectory,
|
|
@@ -33624,7 +33768,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so ma
|
|
|
33624
33768
|
db,
|
|
33625
33769
|
sessionId,
|
|
33626
33770
|
resolvedSessionId,
|
|
33627
|
-
|
|
33771
|
+
historianChunkTokens: deps.getHistorianChunkTokens?.() ?? 20000,
|
|
33628
33772
|
historyBudgetTokens,
|
|
33629
33773
|
historianTimeoutMs: deps.historianTimeoutMs,
|
|
33630
33774
|
compartmentDirectory,
|
|
@@ -34331,6 +34475,7 @@ function createMagicContextHook(deps) {
|
|
|
34331
34475
|
const projectPath = resolveProjectIdentity(deps.directory);
|
|
34332
34476
|
registerDreamProjectDirectory(projectPath, deps.directory);
|
|
34333
34477
|
let lastScheduleCheckMs = 0;
|
|
34478
|
+
const getHistorianChunkTokens = () => deriveHistorianChunkTokens(resolveHistorianContextLimit(deps.config.historian?.model));
|
|
34334
34479
|
const nudgePlacements = createNudgePlacementStore(db);
|
|
34335
34480
|
const flushedSessions = new Set;
|
|
34336
34481
|
const lastHeuristicsTurnId = new Map;
|
|
@@ -34368,7 +34513,7 @@ function createMagicContextHook(deps) {
|
|
|
34368
34513
|
enabled: deps.config.memory.enabled,
|
|
34369
34514
|
injectionBudgetTokens: deps.config.memory.injection_budget_tokens
|
|
34370
34515
|
} : undefined,
|
|
34371
|
-
|
|
34516
|
+
getHistorianChunkTokens,
|
|
34372
34517
|
historyBudgetPercentage: deps.config.history_budget_percentage,
|
|
34373
34518
|
executeThresholdPercentage: deps.config.execute_threshold_percentage,
|
|
34374
34519
|
historianTimeoutMs: deps.config.historian_timeout_ms ?? DEFAULT_HISTORIAN_TIMEOUT_MS,
|
|
@@ -34449,7 +34594,7 @@ function createMagicContextHook(deps) {
|
|
|
34449
34594
|
client: deps.client,
|
|
34450
34595
|
db,
|
|
34451
34596
|
sessionId,
|
|
34452
|
-
|
|
34597
|
+
historianChunkTokens: getHistorianChunkTokens(),
|
|
34453
34598
|
historianTimeoutMs: deps.config.historian_timeout_ms ?? DEFAULT_HISTORIAN_TIMEOUT_MS,
|
|
34454
34599
|
directory: deps.directory,
|
|
34455
34600
|
fallbackModelId: (() => {
|
|
@@ -34575,7 +34720,7 @@ function createSessionHooks(args) {
|
|
|
34575
34720
|
clear_reasoning_age: pluginConfig.clear_reasoning_age,
|
|
34576
34721
|
iteration_nudge_threshold: pluginConfig.iteration_nudge_threshold,
|
|
34577
34722
|
execute_threshold_percentage: pluginConfig.execute_threshold_percentage ?? DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE,
|
|
34578
|
-
|
|
34723
|
+
historian: pluginConfig.historian,
|
|
34579
34724
|
history_budget_percentage: pluginConfig.history_budget_percentage,
|
|
34580
34725
|
historian_timeout_ms: pluginConfig.historian_timeout_ms,
|
|
34581
34726
|
memory: pluginConfig.memory,
|
|
@@ -34900,17 +35045,18 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
34900
35045
|
return { ok: false, error: "no session" };
|
|
34901
35046
|
const { executeContextRecomp: executeContextRecomp2 } = await Promise.resolve().then(() => (init_compartment_runner(), exports_compartment_runner));
|
|
34902
35047
|
const { sendIgnoredMessage: sendIgnoredMessage2 } = await Promise.resolve().then(() => (init_send_session_notification(), exports_send_session_notification));
|
|
35048
|
+
const { deriveHistorianChunkTokens: deriveHistorianChunkTokens2, resolveHistorianContextLimit: resolveHistorianContextLimit2 } = await Promise.resolve().then(() => (init_derive_budgets(), exports_derive_budgets));
|
|
34903
35049
|
const db = getDb();
|
|
34904
35050
|
if (!db)
|
|
34905
35051
|
return { ok: false, error: "db unavailable" };
|
|
34906
|
-
const DEFAULT_COMPARTMENT_TOKEN_BUDGET2 = 20000;
|
|
34907
35052
|
const DEFAULT_HISTORIAN_TIMEOUT_MS2 = 600000;
|
|
35053
|
+
const historianChunkTokens = deriveHistorianChunkTokens2(resolveHistorianContextLimit2(config2.historian?.model));
|
|
34908
35054
|
log(`[rpc] recomp requested for session ${sessionId}`);
|
|
34909
35055
|
executeContextRecomp2({
|
|
34910
35056
|
client: args.client,
|
|
34911
35057
|
db,
|
|
34912
35058
|
sessionId,
|
|
34913
|
-
|
|
35059
|
+
historianChunkTokens,
|
|
34914
35060
|
historianTimeoutMs: config2.historian_timeout_ms ?? DEFAULT_HISTORIAN_TIMEOUT_MS2,
|
|
34915
35061
|
directory,
|
|
34916
35062
|
getNotificationParams: () => getNotificationParams(sessionId)
|
|
@@ -36115,6 +36261,7 @@ init_conflict_detector();
|
|
|
36115
36261
|
init_data_path();
|
|
36116
36262
|
init_logger();
|
|
36117
36263
|
init_model_requirements();
|
|
36264
|
+
init_models_dev_cache();
|
|
36118
36265
|
|
|
36119
36266
|
// src/shared/rpc-server.ts
|
|
36120
36267
|
init_logger();
|
|
@@ -36123,11 +36270,11 @@ import { createServer } from "http";
|
|
|
36123
36270
|
import { dirname } from "path";
|
|
36124
36271
|
|
|
36125
36272
|
// src/shared/rpc-utils.ts
|
|
36126
|
-
import { createHash } from "crypto";
|
|
36273
|
+
import { createHash as createHash2 } from "crypto";
|
|
36127
36274
|
import { join as join15 } from "path";
|
|
36128
36275
|
function projectHash(directory) {
|
|
36129
36276
|
const normalized = directory.replace(/\/+$/, "");
|
|
36130
|
-
return
|
|
36277
|
+
return createHash2("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
36131
36278
|
}
|
|
36132
36279
|
function rpcPortFilePath(storageDir, directory) {
|
|
36133
36280
|
return join15(storageDir, "rpc", projectHash(directory), "port");
|
|
@@ -36312,6 +36459,10 @@ var plugin = async (ctx) => {
|
|
|
36312
36459
|
rpcServer.start().catch((err) => {
|
|
36313
36460
|
log(`[magic-context] RPC server failed to start: ${err}`);
|
|
36314
36461
|
});
|
|
36462
|
+
refreshModelLimitsFromApi(ctx.client);
|
|
36463
|
+
setInterval(() => {
|
|
36464
|
+
refreshModelLimitsFromApi(ctx.client);
|
|
36465
|
+
}, 5 * 60 * 1000);
|
|
36315
36466
|
}
|
|
36316
36467
|
if (conflictResult?.hasConflict) {
|
|
36317
36468
|
sendConflictWarning(ctx.client, ctx.directory, conflictResult);
|