@cortexkit/opencode-magic-context 0.9.1 → 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/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/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 +266 -136
- 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";
|
|
@@ -19980,7 +20179,7 @@ async function runCompartmentAgent(deps) {
|
|
|
19980
20179
|
client,
|
|
19981
20180
|
db,
|
|
19982
20181
|
sessionId,
|
|
19983
|
-
|
|
20182
|
+
historianChunkTokens,
|
|
19984
20183
|
directory,
|
|
19985
20184
|
historianTimeoutMs,
|
|
19986
20185
|
getNotificationParams
|
|
@@ -20015,7 +20214,7 @@ No new compartments or facts were written. Rebuild or clear the broken compartme
|
|
|
20015
20214
|
if (protectedTailStart <= offset) {
|
|
20016
20215
|
return;
|
|
20017
20216
|
}
|
|
20018
|
-
const chunk = readSessionChunk(sessionId,
|
|
20217
|
+
const chunk = readSessionChunk(sessionId, historianChunkTokens, offset, protectedTailStart);
|
|
20019
20218
|
if (!chunk.text || chunk.messageCount === 0) {
|
|
20020
20219
|
return;
|
|
20021
20220
|
}
|
|
@@ -20158,7 +20357,7 @@ async function executeContextRecompInternal(deps) {
|
|
|
20158
20357
|
client,
|
|
20159
20358
|
db,
|
|
20160
20359
|
sessionId,
|
|
20161
|
-
|
|
20360
|
+
historianChunkTokens,
|
|
20162
20361
|
directory,
|
|
20163
20362
|
historianTimeoutMs,
|
|
20164
20363
|
getNotificationParams
|
|
@@ -20212,7 +20411,7 @@ No eligible raw history exists before the protected tail, so nothing was rebuilt
|
|
|
20212
20411
|
let candidateFacts = existingStaging?.facts ?? [];
|
|
20213
20412
|
let offset = existingStaging ? existingStaging.lastEndMessage + 1 : 1;
|
|
20214
20413
|
let passCount = existingStaging?.passCount ?? 0;
|
|
20215
|
-
let currentTokenBudget =
|
|
20414
|
+
let currentTokenBudget = historianChunkTokens;
|
|
20216
20415
|
let passAttempt = 1;
|
|
20217
20416
|
const resumed = existingStaging !== null;
|
|
20218
20417
|
if (resumed) {
|
|
@@ -20310,7 +20509,7 @@ Nothing was written.`;
|
|
|
20310
20509
|
];
|
|
20311
20510
|
candidateFacts = validatedPass.facts ?? [];
|
|
20312
20511
|
passCount += 1;
|
|
20313
|
-
currentTokenBudget =
|
|
20512
|
+
currentTokenBudget = historianChunkTokens;
|
|
20314
20513
|
passAttempt = 1;
|
|
20315
20514
|
saveRecompStagingPass(db, sessionId, passCount, candidateCompartments, candidateFacts);
|
|
20316
20515
|
const nextOffset = (validatedPass.compartments?.[validatedPass.compartments.length - 1]?.endMessage ?? chunk.endIndex) + 1;
|
|
@@ -28510,7 +28709,7 @@ Check verifiable memories against actual repository state. Update stale wording,
|
|
|
28510
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.
|
|
28511
28710
|
|
|
28512
28711
|
### Verification examples
|
|
28513
|
-
- Memory: "
|
|
28712
|
+
- Memory: "history_budget_percentage defaults to 0.15" \u2192 grep schema for \`history_budget_percentage\`, check \`.default(...)\`
|
|
28514
28713
|
- Memory: "Durable state lives in ~/.local/share/opencode/storage/plugin/magic-context/context.db" \u2192 check storage-db.ts for the path construction
|
|
28515
28714
|
- Memory: "ctx_search searches memories, facts, and history" \u2192 grep for ctx_search tool definition and unified search implementation
|
|
28516
28715
|
|
|
@@ -30239,110 +30438,13 @@ function createCompactionHandler() {
|
|
|
30239
30438
|
}
|
|
30240
30439
|
};
|
|
30241
30440
|
}
|
|
30242
|
-
// src/shared/models-dev-cache.ts
|
|
30243
|
-
init_logger();
|
|
30244
|
-
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
30245
|
-
import { homedir as homedir5, platform as platform2 } from "os";
|
|
30246
|
-
import { join as join11 } from "path";
|
|
30247
|
-
var cachedLimits = null;
|
|
30248
|
-
var lastLoadAttempt = 0;
|
|
30249
|
-
var RELOAD_INTERVAL_MS = 5 * 60 * 1000;
|
|
30250
|
-
function getModelsJsonPath() {
|
|
30251
|
-
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
30252
|
-
const os3 = platform2();
|
|
30253
|
-
let cacheBase;
|
|
30254
|
-
if (xdgCache) {
|
|
30255
|
-
cacheBase = xdgCache;
|
|
30256
|
-
} else if (os3 === "win32") {
|
|
30257
|
-
cacheBase = process.env.LOCALAPPDATA ?? join11(homedir5(), "AppData", "Local");
|
|
30258
|
-
} else {
|
|
30259
|
-
cacheBase = join11(homedir5(), ".cache");
|
|
30260
|
-
}
|
|
30261
|
-
return join11(cacheBase, "opencode", "models.json");
|
|
30262
|
-
}
|
|
30263
|
-
function getOpencodeConfigPath() {
|
|
30264
|
-
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
30265
|
-
const configDir = envDir ? envDir : platform2() === "win32" ? join11(homedir5(), ".config", "opencode") : join11(process.env.XDG_CONFIG_HOME || join11(homedir5(), ".config"), "opencode");
|
|
30266
|
-
const jsonc = join11(configDir, "opencode.jsonc");
|
|
30267
|
-
if (existsSync5(jsonc))
|
|
30268
|
-
return jsonc;
|
|
30269
|
-
const json2 = join11(configDir, "opencode.json");
|
|
30270
|
-
if (existsSync5(json2))
|
|
30271
|
-
return json2;
|
|
30272
|
-
return null;
|
|
30273
|
-
}
|
|
30274
|
-
function loadModelsDevLimits() {
|
|
30275
|
-
const limits = new Map;
|
|
30276
|
-
const modelsJsonPath = getModelsJsonPath();
|
|
30277
|
-
try {
|
|
30278
|
-
if (existsSync5(modelsJsonPath)) {
|
|
30279
|
-
const raw = readFileSync4(modelsJsonPath, "utf-8");
|
|
30280
|
-
const data = JSON.parse(raw);
|
|
30281
|
-
for (const [providerId, provider2] of Object.entries(data)) {
|
|
30282
|
-
if (!provider2?.models || typeof provider2.models !== "object")
|
|
30283
|
-
continue;
|
|
30284
|
-
for (const [modelId, model] of Object.entries(provider2.models)) {
|
|
30285
|
-
const context = model?.limit?.context;
|
|
30286
|
-
if (typeof context === "number" && context > 0) {
|
|
30287
|
-
limits.set(`${providerId}/${modelId}`, context);
|
|
30288
|
-
const modes = model?.experimental?.modes;
|
|
30289
|
-
if (modes && typeof modes === "object") {
|
|
30290
|
-
for (const mode of Object.keys(modes)) {
|
|
30291
|
-
limits.set(`${providerId}/${modelId}-${mode}`, context);
|
|
30292
|
-
}
|
|
30293
|
-
}
|
|
30294
|
-
}
|
|
30295
|
-
}
|
|
30296
|
-
}
|
|
30297
|
-
}
|
|
30298
|
-
} catch (error48) {
|
|
30299
|
-
sessionLog("global", "models-dev-cache: failed to read models.json:", error48 instanceof Error ? error48.message : String(error48));
|
|
30300
|
-
}
|
|
30301
|
-
try {
|
|
30302
|
-
const configPath = getOpencodeConfigPath();
|
|
30303
|
-
if (configPath && existsSync5(configPath)) {
|
|
30304
|
-
let raw = readFileSync4(configPath, "utf-8");
|
|
30305
|
-
raw = raw.replace(/"(?:[^"\\]|\\.)*"|\/\/.*$/gm, (match) => match.startsWith('"') ? match : "");
|
|
30306
|
-
const config2 = JSON.parse(raw);
|
|
30307
|
-
if (config2.provider && typeof config2.provider === "object") {
|
|
30308
|
-
for (const [providerId, provider2] of Object.entries(config2.provider)) {
|
|
30309
|
-
if (!provider2?.models || typeof provider2.models !== "object")
|
|
30310
|
-
continue;
|
|
30311
|
-
for (const [modelId, model] of Object.entries(provider2.models)) {
|
|
30312
|
-
const context = model?.limit?.context;
|
|
30313
|
-
if (typeof context === "number" && context > 0) {
|
|
30314
|
-
limits.set(`${providerId}/${modelId}`, context);
|
|
30315
|
-
}
|
|
30316
|
-
}
|
|
30317
|
-
}
|
|
30318
|
-
}
|
|
30319
|
-
}
|
|
30320
|
-
} catch (error48) {
|
|
30321
|
-
sessionLog("global", "models-dev-cache: failed to read opencode config for custom models:", error48 instanceof Error ? error48.message : String(error48));
|
|
30322
|
-
}
|
|
30323
|
-
return limits;
|
|
30324
|
-
}
|
|
30325
|
-
function getModelsDevContextLimit(providerID, modelID) {
|
|
30326
|
-
const now = Date.now();
|
|
30327
|
-
if (!cachedLimits || now - lastLoadAttempt > RELOAD_INTERVAL_MS) {
|
|
30328
|
-
lastLoadAttempt = now;
|
|
30329
|
-
cachedLimits = loadModelsDevLimits();
|
|
30330
|
-
}
|
|
30331
|
-
return cachedLimits.get(`${providerID}/${modelID}`);
|
|
30332
|
-
}
|
|
30333
|
-
|
|
30334
30441
|
// src/hooks/magic-context/event-resolvers.ts
|
|
30442
|
+
init_models_dev_cache();
|
|
30335
30443
|
var DEFAULT_CONTEXT_LIMIT = 128000;
|
|
30336
|
-
function resolveContextLimit(providerID, modelID
|
|
30444
|
+
function resolveContextLimit(providerID, modelID) {
|
|
30337
30445
|
if (!providerID) {
|
|
30338
30446
|
return DEFAULT_CONTEXT_LIMIT;
|
|
30339
30447
|
}
|
|
30340
|
-
if (modelID) {
|
|
30341
|
-
const modelSpecific = config2.modelContextLimitsCache?.get(`${providerID}/${modelID}`);
|
|
30342
|
-
if (typeof modelSpecific === "number" && modelSpecific > 0) {
|
|
30343
|
-
return modelSpecific;
|
|
30344
|
-
}
|
|
30345
|
-
}
|
|
30346
30448
|
if (modelID) {
|
|
30347
30449
|
const modelsDevLimit = getModelsDevContextLimit(providerID, modelID);
|
|
30348
30450
|
if (modelsDevLimit !== undefined) {
|
|
@@ -30625,7 +30727,6 @@ init_storage_tags();
|
|
|
30625
30727
|
init_logger();
|
|
30626
30728
|
|
|
30627
30729
|
// src/hooks/magic-context/compartment-trigger.ts
|
|
30628
|
-
init_magic_context();
|
|
30629
30730
|
init_compartment_storage();
|
|
30630
30731
|
init_storage();
|
|
30631
30732
|
init_logger();
|
|
@@ -30703,7 +30804,7 @@ var TAIL_INFO_DEFAULTS = {
|
|
|
30703
30804
|
tokenEstimate: 0,
|
|
30704
30805
|
commitClusterCount: 0
|
|
30705
30806
|
};
|
|
30706
|
-
function getUnsummarizedTailInfo(db, sessionId,
|
|
30807
|
+
function getUnsummarizedTailInfo(db, sessionId, triggerBudget) {
|
|
30707
30808
|
return withRawSessionMessageCache(() => {
|
|
30708
30809
|
try {
|
|
30709
30810
|
const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
|
|
@@ -30714,7 +30815,7 @@ function getUnsummarizedTailInfo(db, sessionId, compartmentTokenBudget) {
|
|
|
30714
30815
|
if (!hasEligibleHistory) {
|
|
30715
30816
|
return { ...TAIL_INFO_DEFAULTS, nextStartOrdinal };
|
|
30716
30817
|
}
|
|
30717
|
-
const scanBudget = Math.max(MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE,
|
|
30818
|
+
const scanBudget = Math.max(MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE, triggerBudget * TAIL_SIZE_TRIGGER_MULTIPLIER);
|
|
30718
30819
|
const chunk = readSessionChunk(sessionId, scanBudget, nextStartOrdinal, protectedTailStart);
|
|
30719
30820
|
const isMeaningful = chunk.hasMore || chunk.tokenEstimate >= MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE || chunk.messageCount >= MIN_PROACTIVE_TAIL_MESSAGE_COUNT;
|
|
30720
30821
|
return {
|
|
@@ -30730,11 +30831,11 @@ function getUnsummarizedTailInfo(db, sessionId, compartmentTokenBudget) {
|
|
|
30730
30831
|
}
|
|
30731
30832
|
});
|
|
30732
30833
|
}
|
|
30733
|
-
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage,
|
|
30834
|
+
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, autoDropToolAge, protectedTagCount, clearReasoningAge, dropToolStructure = true, commitClusterTrigger) {
|
|
30734
30835
|
if (sessionMeta.compartmentInProgress) {
|
|
30735
30836
|
return { shouldFire: false };
|
|
30736
30837
|
}
|
|
30737
|
-
const tailInfo = getUnsummarizedTailInfo(db, sessionId,
|
|
30838
|
+
const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget);
|
|
30738
30839
|
if (!tailInfo.hasNewRawHistory) {
|
|
30739
30840
|
return { shouldFire: false };
|
|
30740
30841
|
}
|
|
@@ -30750,12 +30851,12 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
30750
30851
|
}
|
|
30751
30852
|
const clusterEnabled = commitClusterTrigger?.enabled ?? true;
|
|
30752
30853
|
const minClusters = commitClusterTrigger?.min_clusters ?? DEFAULT_MIN_COMMIT_CLUSTERS_FOR_TRIGGER;
|
|
30753
|
-
if (clusterEnabled && tailInfo.commitClusterCount >= minClusters && tailInfo.tokenEstimate >=
|
|
30854
|
+
if (clusterEnabled && tailInfo.commitClusterCount >= minClusters && tailInfo.tokenEstimate >= triggerBudget) {
|
|
30754
30855
|
sessionLog(sessionId, `compartment trigger: commit-cluster fire \u2014 ${tailInfo.commitClusterCount} clusters (min=${minClusters}), ~${tailInfo.tokenEstimate} tokens in eligible prefix`);
|
|
30755
30856
|
return { shouldFire: true, reason: "commit_clusters" };
|
|
30756
30857
|
}
|
|
30757
|
-
if (tailInfo.tokenEstimate >=
|
|
30758
|
-
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`);
|
|
30759
30860
|
return { shouldFire: true, reason: "tail_size" };
|
|
30760
30861
|
}
|
|
30761
30862
|
const proactiveTriggerPercentage = getProactiveCompartmentTriggerPercentage(executeThresholdPercentage);
|
|
@@ -31099,11 +31200,15 @@ Historian recomp started. Rebuilding compartments and facts from raw session his
|
|
|
31099
31200
|
};
|
|
31100
31201
|
}
|
|
31101
31202
|
|
|
31203
|
+
// src/hooks/magic-context/hook.ts
|
|
31204
|
+
init_derive_budgets();
|
|
31205
|
+
|
|
31102
31206
|
// src/hooks/magic-context/event-handler.ts
|
|
31103
31207
|
init_storage();
|
|
31104
31208
|
init_storage_meta_persisted();
|
|
31105
31209
|
init_logger();
|
|
31106
31210
|
init_compaction_marker_manager();
|
|
31211
|
+
init_derive_budgets();
|
|
31107
31212
|
|
|
31108
31213
|
// src/hooks/magic-context/event-payloads.ts
|
|
31109
31214
|
function getSessionProperties(properties) {
|
|
@@ -31175,7 +31280,6 @@ function getMessageRemovedInfo(properties) {
|
|
|
31175
31280
|
init_note_nudger();
|
|
31176
31281
|
|
|
31177
31282
|
// src/hooks/magic-context/transform-compartment-phase.ts
|
|
31178
|
-
init_magic_context();
|
|
31179
31283
|
init_compartment_storage();
|
|
31180
31284
|
init_storage();
|
|
31181
31285
|
init_logger();
|
|
@@ -31251,7 +31355,7 @@ async function runCompartmentPhase(args) {
|
|
|
31251
31355
|
client: args.client,
|
|
31252
31356
|
db: args.db,
|
|
31253
31357
|
sessionId: args.sessionId,
|
|
31254
|
-
|
|
31358
|
+
historianChunkTokens: args.historianChunkTokens,
|
|
31255
31359
|
historyBudgetTokens: args.historyBudgetTokens,
|
|
31256
31360
|
historianTimeoutMs: args.historianTimeoutMs,
|
|
31257
31361
|
directory: args.compartmentDirectory,
|
|
@@ -31272,7 +31376,7 @@ async function runCompartmentPhase(args) {
|
|
|
31272
31376
|
client: args.client,
|
|
31273
31377
|
db: args.db,
|
|
31274
31378
|
sessionId: args.sessionId,
|
|
31275
|
-
|
|
31379
|
+
historianChunkTokens: args.historianChunkTokens,
|
|
31276
31380
|
historyBudgetTokens: args.historyBudgetTokens,
|
|
31277
31381
|
historianTimeoutMs: args.historianTimeoutMs,
|
|
31278
31382
|
directory: args.compartmentDirectory,
|
|
@@ -31425,9 +31529,7 @@ function createEventHandler2(deps) {
|
|
|
31425
31529
|
}
|
|
31426
31530
|
if (hasUsageTokens) {
|
|
31427
31531
|
const totalInputTokens = (info.tokens?.input ?? 0) + (info.tokens?.cache?.read ?? 0) + (info.tokens?.cache?.write ?? 0);
|
|
31428
|
-
const contextLimit = resolveContextLimit(info.providerID, info.modelID
|
|
31429
|
-
modelContextLimitsCache: deps.config.modelContextLimitsCache
|
|
31430
|
-
});
|
|
31532
|
+
const contextLimit = resolveContextLimit(info.providerID, info.modelID);
|
|
31431
31533
|
const percentage = contextLimit > 0 ? totalInputTokens / contextLimit * 100 : 0;
|
|
31432
31534
|
sessionLog(info.sessionID, `event message.updated: totalInputTokens=${totalInputTokens} contextLimit=${contextLimit} percentage=${percentage.toFixed(1)}%`);
|
|
31433
31535
|
deps.contextUsageMap.set(info.sessionID, {
|
|
@@ -31447,7 +31549,9 @@ function createEventHandler2(deps) {
|
|
|
31447
31549
|
const sessionMeta = getOrCreateSessionMeta(deps.db, info.sessionID);
|
|
31448
31550
|
const previousPercentage = sessionMeta.lastContextPercentage;
|
|
31449
31551
|
if (!sessionMeta.isSubagent) {
|
|
31450
|
-
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);
|
|
31451
31555
|
if (triggerResult.shouldFire) {
|
|
31452
31556
|
sessionLog(info.sessionID, `compartment trigger: firing (reason=${triggerResult.reason})`);
|
|
31453
31557
|
updateSessionMeta(deps.db, info.sessionID, {
|
|
@@ -31725,7 +31829,6 @@ function createTextCompleteHandler() {
|
|
|
31725
31829
|
}
|
|
31726
31830
|
|
|
31727
31831
|
// src/hooks/magic-context/transform.ts
|
|
31728
|
-
init_magic_context();
|
|
31729
31832
|
init_compartment_storage();
|
|
31730
31833
|
init_project_identity();
|
|
31731
31834
|
init_storage();
|
|
@@ -32806,6 +32909,14 @@ function isToolProtocolPart(part) {
|
|
|
32806
32909
|
function hasToolProtocolParts(message) {
|
|
32807
32910
|
return message.parts.some(isToolProtocolPart);
|
|
32808
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
|
+
}
|
|
32809
32920
|
function isMessageDropped(message) {
|
|
32810
32921
|
const textParts = message.parts.filter(isTextPart);
|
|
32811
32922
|
if (textParts.length === 0)
|
|
@@ -32840,6 +32951,11 @@ function reinjectNudgeAtAnchor(messages, nudgeText, nudgePlacements, sessionId)
|
|
|
32840
32951
|
nudgePlacements.clear(sessionId);
|
|
32841
32952
|
return false;
|
|
32842
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
|
+
}
|
|
32843
32959
|
for (let j = message.parts.length - 1;j >= 0; j--) {
|
|
32844
32960
|
const part = message.parts[j];
|
|
32845
32961
|
if (isTextPart(part)) {
|
|
@@ -32868,6 +32984,8 @@ function appendNudgeToAssistant(messages, nudge, nudgePlacements, sessionId) {
|
|
|
32868
32984
|
continue;
|
|
32869
32985
|
if (isMessageDropped(message))
|
|
32870
32986
|
continue;
|
|
32987
|
+
if (hasThinkingBearingParts(message))
|
|
32988
|
+
continue;
|
|
32871
32989
|
for (let j = message.parts.length - 1;j >= 0; j--) {
|
|
32872
32990
|
const part = message.parts[j];
|
|
32873
32991
|
if (isTextPart(part)) {
|
|
@@ -33151,12 +33269,13 @@ function runPostTransformPhase(args) {
|
|
|
33151
33269
|
const forceMaterialization = args.fullFeatureMode && args.contextUsage.percentage >= args.forceMaterializationPercentage;
|
|
33152
33270
|
const activeCompartmentRun = args.canRunCompartments ? getActiveCompartmentRun(args.sessionId) : undefined;
|
|
33153
33271
|
const compartmentRunning = args.canRunCompartments && !args.awaitedCompartmentRun && activeCompartmentRun !== undefined;
|
|
33154
|
-
const
|
|
33272
|
+
const emergencyBypassCompartmentGate = forceMaterialization;
|
|
33273
|
+
const shouldReadPendingOps = isExplicitFlush || args.schedulerDecision === "execute" || forceMaterialization || compartmentRunning;
|
|
33155
33274
|
const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
|
|
33156
33275
|
const hasPendingUserOps = pendingOps.length > 0;
|
|
33157
|
-
const shouldApplyPendingOps = (args.schedulerDecision === "execute" || isExplicitFlush) && !compartmentRunning;
|
|
33276
|
+
const shouldApplyPendingOps = (args.schedulerDecision === "execute" || isExplicitFlush || forceMaterialization) && (!compartmentRunning || emergencyBypassCompartmentGate);
|
|
33158
33277
|
const isCacheBustingPass = isExplicitFlush || shouldApplyPendingOps;
|
|
33159
|
-
const shouldRunHeuristics = args.fullFeatureMode && !compartmentRunning && (isExplicitFlush || forceMaterialization || args.schedulerDecision === "execute" && !alreadyRanThisTurn);
|
|
33278
|
+
const shouldRunHeuristics = args.fullFeatureMode && (!compartmentRunning || emergencyBypassCompartmentGate) && (isExplicitFlush || forceMaterialization || args.schedulerDecision === "execute" && !alreadyRanThisTurn);
|
|
33160
33279
|
if (shouldRunHeuristics) {
|
|
33161
33280
|
const reason = isExplicitFlush ? "explicit_flush" : forceMaterialization ? `force_materialization (${args.contextUsage.percentage.toFixed(1)}% >= ${args.forceMaterializationPercentage}%)` : `scheduler_execute (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
|
|
33162
33281
|
sessionLog(args.sessionId, `heuristics WILL RUN \u2014 reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=${args.currentTurnId}`);
|
|
@@ -33165,7 +33284,11 @@ function runPostTransformPhase(args) {
|
|
|
33165
33284
|
sessionLog(args.sessionId, `transform: skipping heuristics (already ran for turn ${args.currentTurnId})`);
|
|
33166
33285
|
}
|
|
33167
33286
|
if (compartmentRunning && hasPendingUserOps) {
|
|
33168
|
-
|
|
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
|
+
}
|
|
33169
33292
|
}
|
|
33170
33293
|
try {
|
|
33171
33294
|
if (shouldApplyPendingOps) {
|
|
@@ -33524,7 +33647,7 @@ function createTransform(deps) {
|
|
|
33524
33647
|
client: deps.client,
|
|
33525
33648
|
db,
|
|
33526
33649
|
sessionId,
|
|
33527
|
-
|
|
33650
|
+
historianChunkTokens: deps.getHistorianChunkTokens?.() ?? 20000,
|
|
33528
33651
|
historyBudgetTokens,
|
|
33529
33652
|
historianTimeoutMs: deps.historianTimeoutMs,
|
|
33530
33653
|
directory: compartmentDirectory,
|
|
@@ -33645,7 +33768,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so ma
|
|
|
33645
33768
|
db,
|
|
33646
33769
|
sessionId,
|
|
33647
33770
|
resolvedSessionId,
|
|
33648
|
-
|
|
33771
|
+
historianChunkTokens: deps.getHistorianChunkTokens?.() ?? 20000,
|
|
33649
33772
|
historyBudgetTokens,
|
|
33650
33773
|
historianTimeoutMs: deps.historianTimeoutMs,
|
|
33651
33774
|
compartmentDirectory,
|
|
@@ -34352,6 +34475,7 @@ function createMagicContextHook(deps) {
|
|
|
34352
34475
|
const projectPath = resolveProjectIdentity(deps.directory);
|
|
34353
34476
|
registerDreamProjectDirectory(projectPath, deps.directory);
|
|
34354
34477
|
let lastScheduleCheckMs = 0;
|
|
34478
|
+
const getHistorianChunkTokens = () => deriveHistorianChunkTokens(resolveHistorianContextLimit(deps.config.historian?.model));
|
|
34355
34479
|
const nudgePlacements = createNudgePlacementStore(db);
|
|
34356
34480
|
const flushedSessions = new Set;
|
|
34357
34481
|
const lastHeuristicsTurnId = new Map;
|
|
@@ -34389,7 +34513,7 @@ function createMagicContextHook(deps) {
|
|
|
34389
34513
|
enabled: deps.config.memory.enabled,
|
|
34390
34514
|
injectionBudgetTokens: deps.config.memory.injection_budget_tokens
|
|
34391
34515
|
} : undefined,
|
|
34392
|
-
|
|
34516
|
+
getHistorianChunkTokens,
|
|
34393
34517
|
historyBudgetPercentage: deps.config.history_budget_percentage,
|
|
34394
34518
|
executeThresholdPercentage: deps.config.execute_threshold_percentage,
|
|
34395
34519
|
historianTimeoutMs: deps.config.historian_timeout_ms ?? DEFAULT_HISTORIAN_TIMEOUT_MS,
|
|
@@ -34470,7 +34594,7 @@ function createMagicContextHook(deps) {
|
|
|
34470
34594
|
client: deps.client,
|
|
34471
34595
|
db,
|
|
34472
34596
|
sessionId,
|
|
34473
|
-
|
|
34597
|
+
historianChunkTokens: getHistorianChunkTokens(),
|
|
34474
34598
|
historianTimeoutMs: deps.config.historian_timeout_ms ?? DEFAULT_HISTORIAN_TIMEOUT_MS,
|
|
34475
34599
|
directory: deps.directory,
|
|
34476
34600
|
fallbackModelId: (() => {
|
|
@@ -34596,7 +34720,7 @@ function createSessionHooks(args) {
|
|
|
34596
34720
|
clear_reasoning_age: pluginConfig.clear_reasoning_age,
|
|
34597
34721
|
iteration_nudge_threshold: pluginConfig.iteration_nudge_threshold,
|
|
34598
34722
|
execute_threshold_percentage: pluginConfig.execute_threshold_percentage ?? DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE,
|
|
34599
|
-
|
|
34723
|
+
historian: pluginConfig.historian,
|
|
34600
34724
|
history_budget_percentage: pluginConfig.history_budget_percentage,
|
|
34601
34725
|
historian_timeout_ms: pluginConfig.historian_timeout_ms,
|
|
34602
34726
|
memory: pluginConfig.memory,
|
|
@@ -34921,17 +35045,18 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
34921
35045
|
return { ok: false, error: "no session" };
|
|
34922
35046
|
const { executeContextRecomp: executeContextRecomp2 } = await Promise.resolve().then(() => (init_compartment_runner(), exports_compartment_runner));
|
|
34923
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));
|
|
34924
35049
|
const db = getDb();
|
|
34925
35050
|
if (!db)
|
|
34926
35051
|
return { ok: false, error: "db unavailable" };
|
|
34927
|
-
const DEFAULT_COMPARTMENT_TOKEN_BUDGET2 = 20000;
|
|
34928
35052
|
const DEFAULT_HISTORIAN_TIMEOUT_MS2 = 600000;
|
|
35053
|
+
const historianChunkTokens = deriveHistorianChunkTokens2(resolveHistorianContextLimit2(config2.historian?.model));
|
|
34929
35054
|
log(`[rpc] recomp requested for session ${sessionId}`);
|
|
34930
35055
|
executeContextRecomp2({
|
|
34931
35056
|
client: args.client,
|
|
34932
35057
|
db,
|
|
34933
35058
|
sessionId,
|
|
34934
|
-
|
|
35059
|
+
historianChunkTokens,
|
|
34935
35060
|
historianTimeoutMs: config2.historian_timeout_ms ?? DEFAULT_HISTORIAN_TIMEOUT_MS2,
|
|
34936
35061
|
directory,
|
|
34937
35062
|
getNotificationParams: () => getNotificationParams(sessionId)
|
|
@@ -36136,6 +36261,7 @@ init_conflict_detector();
|
|
|
36136
36261
|
init_data_path();
|
|
36137
36262
|
init_logger();
|
|
36138
36263
|
init_model_requirements();
|
|
36264
|
+
init_models_dev_cache();
|
|
36139
36265
|
|
|
36140
36266
|
// src/shared/rpc-server.ts
|
|
36141
36267
|
init_logger();
|
|
@@ -36144,11 +36270,11 @@ import { createServer } from "http";
|
|
|
36144
36270
|
import { dirname } from "path";
|
|
36145
36271
|
|
|
36146
36272
|
// src/shared/rpc-utils.ts
|
|
36147
|
-
import { createHash } from "crypto";
|
|
36273
|
+
import { createHash as createHash2 } from "crypto";
|
|
36148
36274
|
import { join as join15 } from "path";
|
|
36149
36275
|
function projectHash(directory) {
|
|
36150
36276
|
const normalized = directory.replace(/\/+$/, "");
|
|
36151
|
-
return
|
|
36277
|
+
return createHash2("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
36152
36278
|
}
|
|
36153
36279
|
function rpcPortFilePath(storageDir, directory) {
|
|
36154
36280
|
return join15(storageDir, "rpc", projectHash(directory), "port");
|
|
@@ -36333,6 +36459,10 @@ var plugin = async (ctx) => {
|
|
|
36333
36459
|
rpcServer.start().catch((err) => {
|
|
36334
36460
|
log(`[magic-context] RPC server failed to start: ${err}`);
|
|
36335
36461
|
});
|
|
36462
|
+
refreshModelLimitsFromApi(ctx.client);
|
|
36463
|
+
setInterval(() => {
|
|
36464
|
+
refreshModelLimitsFromApi(ctx.client);
|
|
36465
|
+
}, 5 * 60 * 1000);
|
|
36336
36466
|
}
|
|
36337
36467
|
if (conflictResult?.hasConflict) {
|
|
36338
36468
|
sendConflictWarning(ctx.client, ctx.directory, conflictResult);
|