@cortexkit/opencode-magic-context 0.24.1 → 0.25.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 +4 -2
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts +8 -0
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts +4 -0
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts +6 -0
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts +38 -0
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +1 -0
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-shared.d.ts +2 -1
- package/dist/features/magic-context/storage-meta-shared.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-tags.d.ts +10 -0
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +2 -2
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/types.d.ts +1 -0
- package/dist/features/magic-context/types.d.ts.map +1 -1
- package/dist/hooks/magic-context/apply-operations.d.ts +3 -25
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/caveman-cleanup.d.ts +1 -0
- package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/channel2-delivery.d.ts +2 -0
- package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +7 -5
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +7 -2
- package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
- package/dist/hooks/magic-context/embed-session-state.d.ts +14 -0
- package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -0
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/format-embed-status.d.ts +9 -0
- package/dist/hooks/magic-context/format-embed-status.d.ts.map +1 -0
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +1 -0
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +0 -1
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-content-primitives.d.ts +2 -0
- package/dist/hooks/magic-context/tag-content-primitives.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tool-drop-target.d.ts +1 -1
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/tool-reclaim.d.ts +12 -0
- package/dist/hooks/magic-context/tool-reclaim.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-operations.d.ts +1 -1
- package/dist/hooks/magic-context/transform-operations.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 +2 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1103 -408
- package/dist/plugin/conflict-warning-hook.d.ts.map +1 -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/shared/announcement.d.ts +1 -1
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +20 -0
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +5 -1
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/tools/ctx-expand/constants.d.ts +1 -1
- package/dist/tools/ctx-expand/constants.d.ts.map +1 -1
- package/dist/tools/ctx-expand/render.d.ts +43 -0
- package/dist/tools/ctx-expand/render.d.ts.map +1 -0
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-expand/types.d.ts +6 -2
- package/dist/tools/ctx-expand/types.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/constants.d.ts +1 -1
- package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
- package/dist/tui/data/context-db.d.ts +4 -2
- package/dist/tui/data/context-db.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/shared/announcement.ts +6 -6
- package/src/shared/model-suggestion-retry.test.ts +61 -1
- package/src/shared/model-suggestion-retry.ts +22 -0
- package/src/shared/rpc-types.ts +11 -0
- package/src/shared/sqlite-bind-style.test.ts +82 -0
- package/src/shared/sqlite.ts +30 -1
- package/src/shared/tag-transcript.test.ts +3 -1
- package/src/shared/tag-transcript.ts +19 -17
- package/src/tui/data/context-db.ts +34 -2
- package/src/tui/index.tsx +58 -4
- package/src/tui/slots/sidebar-content.tsx +7 -2
package/dist/index.js
CHANGED
|
@@ -15562,9 +15562,11 @@ async function promptWithTimeout(client, args, timeoutMs, signal) {
|
|
|
15562
15562
|
});
|
|
15563
15563
|
} catch (error51) {
|
|
15564
15564
|
if (signal?.aborted) {
|
|
15565
|
+
await abortChildRun(client, args.path.id);
|
|
15565
15566
|
throw new Error("prompt aborted by external signal");
|
|
15566
15567
|
}
|
|
15567
15568
|
if (controller.signal.aborted) {
|
|
15569
|
+
await abortChildRun(client, args.path.id);
|
|
15568
15570
|
throw new Error(`prompt timed out after ${timeoutMs}ms`);
|
|
15569
15571
|
}
|
|
15570
15572
|
throw error51;
|
|
@@ -15573,6 +15575,13 @@ async function promptWithTimeout(client, args, timeoutMs, signal) {
|
|
|
15573
15575
|
signal?.removeEventListener("abort", onExternalAbort);
|
|
15574
15576
|
}
|
|
15575
15577
|
}
|
|
15578
|
+
async function abortChildRun(client, sessionId) {
|
|
15579
|
+
try {
|
|
15580
|
+
await client.session.abort({ path: { id: sessionId } });
|
|
15581
|
+
} catch (error51) {
|
|
15582
|
+
log(`[model-retry] child session abort failed for ${sessionId}: ${String(error51)}`);
|
|
15583
|
+
}
|
|
15584
|
+
}
|
|
15576
15585
|
function isNonRetryable(error51, externalSignal) {
|
|
15577
15586
|
if (externalSignal?.aborted)
|
|
15578
15587
|
return true;
|
|
@@ -15844,7 +15853,7 @@ function isSessionMetaRow(row) {
|
|
|
15844
15853
|
if (row === null || typeof row !== "object")
|
|
15845
15854
|
return false;
|
|
15846
15855
|
const r = row;
|
|
15847
|
-
return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isStringOrNull(r.cached_m0_workspace_fingerprint) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.cached_m0_system_hash) && isStringOrNull(r.cached_m0_tool_set_hash) && isStringOrNull(r.cached_m0_model_key) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.last_usage_context_limit) && isNumberOrNull(r.prior_boundary_ordinal) && isNumberOrNull(r.protected_tail_policy_version) && isNumberOrNull(r.protected_tail_drain_window_started_at) && isNumberOrNull(r.protected_tail_drain_tokens) && isNumberOrNull(r.recovery_no_eligible_head_count) && isNumberOrNull(r.force_emergency_bypass_window_start) && isNumberOrNull(r.force_emergency_bypass_used) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme);
|
|
15856
|
+
return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isStringOrNull(r.cached_m0_workspace_fingerprint) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.cached_m0_system_hash) && isStringOrNull(r.cached_m0_tool_set_hash) && isStringOrNull(r.cached_m0_model_key) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.last_usage_context_limit) && isNumberOrNull(r.prior_boundary_ordinal) && isNumberOrNull(r.protected_tail_policy_version) && isNumberOrNull(r.protected_tail_drain_window_started_at) && isNumberOrNull(r.protected_tail_drain_tokens) && isNumberOrNull(r.recovery_no_eligible_head_count) && isNumberOrNull(r.force_emergency_bypass_window_start) && isNumberOrNull(r.force_emergency_bypass_used) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme) && isNumberOrNull(r.tool_reclaim_watermark);
|
|
15848
15857
|
}
|
|
15849
15858
|
function getDefaultSessionMeta(sessionId) {
|
|
15850
15859
|
return {
|
|
@@ -15867,6 +15876,7 @@ function getDefaultSessionMeta(sessionId) {
|
|
|
15867
15876
|
conversationTokens: 0,
|
|
15868
15877
|
toolCallTokens: 0,
|
|
15869
15878
|
clearedReasoningThroughTag: 0,
|
|
15879
|
+
toolReclaimWatermark: 0,
|
|
15870
15880
|
lastTodoState: "",
|
|
15871
15881
|
cachedM0Bytes: null,
|
|
15872
15882
|
cachedM1Bytes: null,
|
|
@@ -15930,6 +15940,7 @@ function toSessionMeta(row) {
|
|
|
15930
15940
|
conversationTokens: numOrZero(row.conversation_tokens),
|
|
15931
15941
|
toolCallTokens: numOrZero(row.tool_call_tokens),
|
|
15932
15942
|
clearedReasoningThroughTag: numOrZero(row.cleared_reasoning_through_tag),
|
|
15943
|
+
toolReclaimWatermark: numOrZero(row.tool_reclaim_watermark),
|
|
15933
15944
|
lastTodoState: lastTodoStateRaw,
|
|
15934
15945
|
cachedM0Bytes: toBufferOrNull(row.cached_m0_bytes),
|
|
15935
15946
|
cachedM1Bytes: toBufferOrNull(row.cached_m1_bytes),
|
|
@@ -16039,6 +16050,7 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16039
16050
|
"conversation_tokens",
|
|
16040
16051
|
"tool_call_tokens",
|
|
16041
16052
|
"cleared_reasoning_through_tag",
|
|
16053
|
+
"tool_reclaim_watermark",
|
|
16042
16054
|
"last_todo_state",
|
|
16043
16055
|
"cached_m0_bytes",
|
|
16044
16056
|
"cached_m1_bytes",
|
|
@@ -16087,6 +16099,7 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16087
16099
|
conversationTokens: "conversation_tokens",
|
|
16088
16100
|
toolCallTokens: "tool_call_tokens",
|
|
16089
16101
|
clearedReasoningThroughTag: "cleared_reasoning_through_tag",
|
|
16102
|
+
toolReclaimWatermark: "tool_reclaim_watermark",
|
|
16090
16103
|
lastTodoState: "last_todo_state",
|
|
16091
16104
|
cachedM0Bytes: "cached_m0_bytes",
|
|
16092
16105
|
cachedM1Bytes: "cached_m1_bytes",
|
|
@@ -16363,6 +16376,14 @@ function buildNodeSqliteDatabaseClass(DatabaseSync) {
|
|
|
16363
16376
|
}
|
|
16364
16377
|
super(typeof filename === "string" ? filename : ":memory:", translated);
|
|
16365
16378
|
}
|
|
16379
|
+
prepare(sql) {
|
|
16380
|
+
const stmt = super.prepare(sql);
|
|
16381
|
+
for (const method of ["run", "get", "all"]) {
|
|
16382
|
+
const original = stmt[method].bind(stmt);
|
|
16383
|
+
stmt[method] = (...args) => args.length === 1 && Array.isArray(args[0]) ? original(...args[0]) : original(...args);
|
|
16384
|
+
}
|
|
16385
|
+
return stmt;
|
|
16386
|
+
}
|
|
16366
16387
|
transaction(fn) {
|
|
16367
16388
|
const self = this;
|
|
16368
16389
|
const wrapped = function(...args) {
|
|
@@ -149339,6 +149360,9 @@ function stripCompleteTagPairsGlobally(value) {
|
|
|
149339
149360
|
function stripMalformedTagNotationGlobally(value) {
|
|
149340
149361
|
return value.replace(MALFORMED_TAG_GLOBAL_REGEX, "");
|
|
149341
149362
|
}
|
|
149363
|
+
function stripDanglingTagNotationGlobally(value) {
|
|
149364
|
+
return value.replace(DANGLING_TAG_GLOBAL_REGEX, "");
|
|
149365
|
+
}
|
|
149342
149366
|
function stripTagSectionCharacters(value) {
|
|
149343
149367
|
return value.replace(STRAY_SECTION_CHAR_REGEX, "");
|
|
149344
149368
|
}
|
|
@@ -149346,6 +149370,7 @@ function stripPersistedAssistantText(value) {
|
|
|
149346
149370
|
let text = stripWellFormedLeadingTagPrefix(value);
|
|
149347
149371
|
text = stripCompleteTagPairsGlobally(text);
|
|
149348
149372
|
text = stripMalformedTagNotationGlobally(text);
|
|
149373
|
+
text = stripDanglingTagNotationGlobally(text);
|
|
149349
149374
|
text = stripTagSectionCharacters(text);
|
|
149350
149375
|
return text.trim();
|
|
149351
149376
|
}
|
|
@@ -149358,6 +149383,7 @@ function stripTagPrefix(value) {
|
|
|
149358
149383
|
const prev = stripped;
|
|
149359
149384
|
stripped = stripped.replace(MALFORMED_TAG_PREFIX_REGEX, "");
|
|
149360
149385
|
stripped = stripped.replace(TAG_PREFIX_REGEX, "");
|
|
149386
|
+
stripped = stripped.replace(DANGLING_TAG_PREFIX_REGEX, "");
|
|
149361
149387
|
if (stripped === prev)
|
|
149362
149388
|
break;
|
|
149363
149389
|
}
|
|
@@ -149379,11 +149405,13 @@ function isThinkingPart(part) {
|
|
|
149379
149405
|
const candidate = part;
|
|
149380
149406
|
return candidate.type === "thinking" || candidate.type === "reasoning";
|
|
149381
149407
|
}
|
|
149382
|
-
var encoder, TAG_PREFIX_REGEX, MALFORMED_TAG_PREFIX_REGEX, COMPLETE_TAG_PAIR_GLOBAL_REGEX, MALFORMED_TAG_GLOBAL_REGEX, STRAY_SECTION_CHAR_REGEX;
|
|
149408
|
+
var encoder, TAG_PREFIX_REGEX, MALFORMED_TAG_PREFIX_REGEX, DANGLING_TAG_GLOBAL_REGEX, DANGLING_TAG_PREFIX_REGEX, COMPLETE_TAG_PAIR_GLOBAL_REGEX, MALFORMED_TAG_GLOBAL_REGEX, STRAY_SECTION_CHAR_REGEX;
|
|
149383
149409
|
var init_tag_content_primitives = __esm(() => {
|
|
149384
149410
|
encoder = new TextEncoder;
|
|
149385
149411
|
TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
|
|
149386
149412
|
MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
|
|
149413
|
+
DANGLING_TAG_GLOBAL_REGEX = /\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?/g;
|
|
149414
|
+
DANGLING_TAG_PREFIX_REGEX = /^(?:\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?\s*)+/;
|
|
149387
149415
|
COMPLETE_TAG_PAIR_GLOBAL_REGEX = /\u00a7\d+\u00a7/g;
|
|
149388
149416
|
MALFORMED_TAG_GLOBAL_REGEX = /\u00a7\d+">(?:\u00a7(?:\d+\u00a7)?)?/g;
|
|
149389
149417
|
STRAY_SECTION_CHAR_REGEX = /\u00a7/g;
|
|
@@ -149447,12 +149475,13 @@ function setToolContent(part, content) {
|
|
|
149447
149475
|
part.content = content;
|
|
149448
149476
|
}
|
|
149449
149477
|
}
|
|
149450
|
-
function truncateToolPart(part) {
|
|
149478
|
+
function truncateToolPart(part, tagId) {
|
|
149451
149479
|
if (!isRecord(part))
|
|
149452
149480
|
return;
|
|
149481
|
+
const sentinel = `[dropped §${tagId}§]`;
|
|
149453
149482
|
if (part.type === "tool" && isRecord(part.state)) {
|
|
149454
149483
|
const state = part.state;
|
|
149455
|
-
state.output =
|
|
149484
|
+
state.output = sentinel;
|
|
149456
149485
|
if (isRecord(state.input)) {
|
|
149457
149486
|
const inputSize = estimateInputSize(state.input);
|
|
149458
149487
|
if (inputSize > 500) {
|
|
@@ -149462,7 +149491,7 @@ function truncateToolPart(part) {
|
|
|
149462
149491
|
return;
|
|
149463
149492
|
}
|
|
149464
149493
|
if (part.type === "tool_result") {
|
|
149465
|
-
part.content =
|
|
149494
|
+
part.content = sentinel;
|
|
149466
149495
|
return;
|
|
149467
149496
|
}
|
|
149468
149497
|
if (part.type === "tool-invocation" && isRecord(part.args)) {
|
|
@@ -149579,7 +149608,7 @@ class ToolMutationBatch {
|
|
|
149579
149608
|
this.affectedMessages.clear();
|
|
149580
149609
|
}
|
|
149581
149610
|
}
|
|
149582
|
-
function createToolDropTarget(compositeKey, thinkingParts, index, batch) {
|
|
149611
|
+
function createToolDropTarget(compositeKey, thinkingParts, index, batch, tagId) {
|
|
149583
149612
|
const drop = () => {
|
|
149584
149613
|
const entry = index.get(compositeKey);
|
|
149585
149614
|
if (!entry || entry.occurrences.length === 0)
|
|
@@ -149600,7 +149629,7 @@ function createToolDropTarget(compositeKey, thinkingParts, index, batch) {
|
|
|
149600
149629
|
if (!entry.hasResult)
|
|
149601
149630
|
return "incomplete";
|
|
149602
149631
|
for (const occurrence of entry.occurrences) {
|
|
149603
|
-
truncateToolPart(occurrence.part);
|
|
149632
|
+
truncateToolPart(occurrence.part, tagId);
|
|
149604
149633
|
}
|
|
149605
149634
|
clearThinkingParts(thinkingParts);
|
|
149606
149635
|
return "truncated";
|
|
@@ -151334,6 +151363,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151334
151363
|
ensureColumn(db, "session_meta", "historian_last_failure_at", "INTEGER DEFAULT NULL");
|
|
151335
151364
|
ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
|
|
151336
151365
|
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
151366
|
+
ensureColumn(db, "session_meta", "tool_reclaim_watermark", "INTEGER DEFAULT 0");
|
|
151337
151367
|
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
151338
151368
|
ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
|
|
151339
151369
|
ensureColumn(db, "session_meta", "processed_image_stripped_ids", "TEXT DEFAULT ''");
|
|
@@ -154123,7 +154153,8 @@ var exports_storage_meta_session = {};
|
|
|
154123
154153
|
__export(exports_storage_meta_session, {
|
|
154124
154154
|
updateSessionMeta: () => updateSessionMeta,
|
|
154125
154155
|
getOrCreateSessionMeta: () => getOrCreateSessionMeta,
|
|
154126
|
-
clearSession: () => clearSession
|
|
154156
|
+
clearSession: () => clearSession,
|
|
154157
|
+
advanceToolReclaimWatermark: () => advanceToolReclaimWatermark
|
|
154127
154158
|
});
|
|
154128
154159
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
154129
154160
|
function getSessionMetaSelectColumns(db) {
|
|
@@ -154184,6 +154215,14 @@ function updateSessionMeta(db, sessionId, updates) {
|
|
|
154184
154215
|
db.prepare(`UPDATE session_meta SET ${setClauses.join(", ")} WHERE session_id = ?`).run(...values, sessionId);
|
|
154185
154216
|
})();
|
|
154186
154217
|
}
|
|
154218
|
+
function advanceToolReclaimWatermark(db, sessionId, maxTagNumber) {
|
|
154219
|
+
if (maxTagNumber <= 0)
|
|
154220
|
+
return;
|
|
154221
|
+
db.transaction(() => {
|
|
154222
|
+
ensureSessionMetaRow(db, sessionId);
|
|
154223
|
+
db.prepare("UPDATE session_meta SET tool_reclaim_watermark = MAX(COALESCE(tool_reclaim_watermark, 0), ?) WHERE session_id = ?").run(maxTagNumber, sessionId);
|
|
154224
|
+
})();
|
|
154225
|
+
}
|
|
154187
154226
|
function clearSession(db, sessionId) {
|
|
154188
154227
|
db.transaction(() => {
|
|
154189
154228
|
db.prepare("DELETE FROM pending_ops WHERE session_id = ?").run(sessionId);
|
|
@@ -154222,6 +154261,7 @@ var init_storage_meta_session = __esm(async () => {
|
|
|
154222
154261
|
last_transform_error: "'' AS last_transform_error",
|
|
154223
154262
|
system_prompt_hash: "'' AS system_prompt_hash",
|
|
154224
154263
|
last_todo_state: "'' AS last_todo_state",
|
|
154264
|
+
tool_reclaim_watermark: "0 AS tool_reclaim_watermark",
|
|
154225
154265
|
cached_m0_bytes: "NULL AS cached_m0_bytes",
|
|
154226
154266
|
cached_m1_bytes: "NULL AS cached_m1_bytes",
|
|
154227
154267
|
cached_m0_project_memory_epoch: "NULL AS cached_m0_project_memory_epoch",
|
|
@@ -154629,6 +154669,26 @@ function getActiveTagTokenAggregate(db, sessionId, protectedTags = 0) {
|
|
|
154629
154669
|
nullCount: row?.null_count ?? 0
|
|
154630
154670
|
};
|
|
154631
154671
|
}
|
|
154672
|
+
function getOldestActiveUnprotectedToolTags(db, sessionId, protectedTags = 0, limit = 4) {
|
|
154673
|
+
if (limit <= 0)
|
|
154674
|
+
return [];
|
|
154675
|
+
const boundedLimit = Math.max(1, Math.min(10, Math.floor(limit)));
|
|
154676
|
+
const whereProtected = protectedTags > 0 ? `AND tag_number < (
|
|
154677
|
+
SELECT tag_number FROM tags
|
|
154678
|
+
WHERE session_id = ? AND status = 'active'
|
|
154679
|
+
ORDER BY tag_number DESC LIMIT 1 OFFSET ?
|
|
154680
|
+
)` : "";
|
|
154681
|
+
const params = protectedTags > 0 ? [sessionId, sessionId, protectedTags - 1, boundedLimit] : [sessionId, boundedLimit];
|
|
154682
|
+
const rows = db.prepare(`SELECT tag_number, tool_name
|
|
154683
|
+
FROM tags
|
|
154684
|
+
WHERE session_id = ? AND status = 'active' AND type = 'tool' ${whereProtected}
|
|
154685
|
+
ORDER BY tag_number ASC, id ASC
|
|
154686
|
+
LIMIT ?`).all(...params);
|
|
154687
|
+
return rows.filter((row) => typeof row.tag_number === "number").map((row) => ({
|
|
154688
|
+
tagNumber: row.tag_number,
|
|
154689
|
+
toolName: typeof row.tool_name === "string" ? row.tool_name : null
|
|
154690
|
+
}));
|
|
154691
|
+
}
|
|
154632
154692
|
function getTriggerTagTokenUpperBound(db, sessionId) {
|
|
154633
154693
|
const row = db.prepare(`SELECT
|
|
154634
154694
|
COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
|
|
@@ -163972,6 +164032,58 @@ var init_safe_notification_target = __esm(() => {
|
|
|
163972
164032
|
DEFAULT_TITLE_RE = /^(New session - |Child session - )\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
163973
164033
|
});
|
|
163974
164034
|
|
|
164035
|
+
// src/shared/rpc-notifications.ts
|
|
164036
|
+
var exports_rpc_notifications = {};
|
|
164037
|
+
__export(exports_rpc_notifications, {
|
|
164038
|
+
pushNotification: () => pushNotification,
|
|
164039
|
+
isTuiConnected: () => isTuiConnected,
|
|
164040
|
+
drainNotifications: () => drainNotifications
|
|
164041
|
+
});
|
|
164042
|
+
function pushNotification(type, payload, sessionId) {
|
|
164043
|
+
queue.push({ id: nextNotificationId++, type, payload, sessionId });
|
|
164044
|
+
if (queue.length > 100) {
|
|
164045
|
+
const newestPerSession = new Map;
|
|
164046
|
+
for (const n of queue) {
|
|
164047
|
+
const prev = newestPerSession.get(n.sessionId);
|
|
164048
|
+
if (prev === undefined || n.id > prev) {
|
|
164049
|
+
newestPerSession.set(n.sessionId, n.id);
|
|
164050
|
+
}
|
|
164051
|
+
}
|
|
164052
|
+
const mustKeep = new Set(newestPerSession.values());
|
|
164053
|
+
const byNewest = [...queue].sort((a, b) => b.id - a.id);
|
|
164054
|
+
const kept = [];
|
|
164055
|
+
for (const n of byNewest) {
|
|
164056
|
+
if (kept.length < 50 || mustKeep.has(n.id))
|
|
164057
|
+
kept.push(n);
|
|
164058
|
+
}
|
|
164059
|
+
queue = kept.sort((a, b) => a.id - b.id);
|
|
164060
|
+
}
|
|
164061
|
+
}
|
|
164062
|
+
function drainNotifications(lastReceivedId = 0, sessionId) {
|
|
164063
|
+
const now = Date.now();
|
|
164064
|
+
lastDrainAtAny = now;
|
|
164065
|
+
if (sessionId !== undefined)
|
|
164066
|
+
lastDrainAtBySession.set(sessionId, now);
|
|
164067
|
+
const matchesClient = (notification) => sessionId === undefined || notification.sessionId === undefined || notification.sessionId === sessionId;
|
|
164068
|
+
if (lastReceivedId > 0) {
|
|
164069
|
+
queue = queue.filter((notification) => !(notification.id <= lastReceivedId && matchesClient(notification)));
|
|
164070
|
+
}
|
|
164071
|
+
return queue.filter((notification) => notification.id > lastReceivedId && matchesClient(notification));
|
|
164072
|
+
}
|
|
164073
|
+
function isTuiConnected(sessionId) {
|
|
164074
|
+
const now = Date.now();
|
|
164075
|
+
if (sessionId !== undefined) {
|
|
164076
|
+
const at = lastDrainAtBySession.get(sessionId) ?? 0;
|
|
164077
|
+
return at > 0 && now - at < TUI_CONNECTED_WINDOW_MS;
|
|
164078
|
+
}
|
|
164079
|
+
return lastDrainAtAny > 0 && now - lastDrainAtAny < TUI_CONNECTED_WINDOW_MS;
|
|
164080
|
+
}
|
|
164081
|
+
var queue, nextNotificationId = 1, lastDrainAtBySession, lastDrainAtAny = 0, TUI_CONNECTED_WINDOW_MS = 3000;
|
|
164082
|
+
var init_rpc_notifications = __esm(() => {
|
|
164083
|
+
queue = [];
|
|
164084
|
+
lastDrainAtBySession = new Map;
|
|
164085
|
+
});
|
|
164086
|
+
|
|
163975
164087
|
// src/plugin/conflict-warning-hook.ts
|
|
163976
164088
|
var exports_conflict_warning_hook = {};
|
|
163977
164089
|
__export(exports_conflict_warning_hook, {
|
|
@@ -164306,6 +164418,9 @@ async function sendStartupAnnouncement(client, directory, version2, features, fo
|
|
|
164306
164418
|
if (!sessionId) {
|
|
164307
164419
|
return;
|
|
164308
164420
|
}
|
|
164421
|
+
const { isTuiConnected: isTuiConnected2 } = await Promise.resolve().then(() => (init_rpc_notifications(), exports_rpc_notifications));
|
|
164422
|
+
if (isTuiConnected2(sessionId) || isTuiConnected2())
|
|
164423
|
+
return;
|
|
164309
164424
|
if (await waitForSafeNotificationTarget(client, sessionId) === "skip")
|
|
164310
164425
|
return;
|
|
164311
164426
|
const bullets = features.map((line) => ` • ${line}`).join(`
|
|
@@ -164528,6 +164643,20 @@ function getDistinctStoredModelIds(db, projectPath) {
|
|
|
164528
164643
|
const rows = getDistinctStoredModelIdsStatement(db).all(projectPath);
|
|
164529
164644
|
return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
|
|
164530
164645
|
}
|
|
164646
|
+
function getMemoryEmbedCoverage(db, projectPath, modelId) {
|
|
164647
|
+
const row = db.prepare(`SELECT
|
|
164648
|
+
COUNT(*) AS total,
|
|
164649
|
+
SUM(CASE WHEN EXISTS (
|
|
164650
|
+
SELECT 1 FROM memory_embeddings e
|
|
164651
|
+
WHERE e.memory_id = m.id AND e.model_id = ?
|
|
164652
|
+
) THEN 1 ELSE 0 END) AS embedded
|
|
164653
|
+
FROM memories m
|
|
164654
|
+
WHERE m.project_path = ? AND m.status = 'active'`).get(modelId, projectPath);
|
|
164655
|
+
return {
|
|
164656
|
+
total: typeof row?.total === "number" ? row.total : 0,
|
|
164657
|
+
embedded: typeof row?.embedded === "number" ? row.embedded : 0
|
|
164658
|
+
};
|
|
164659
|
+
}
|
|
164531
164660
|
var saveEmbeddingStatements, loadAllEmbeddingsStatements, deleteEmbeddingStatements, getStoredModelIdStatements, clearAllEmbeddingsStatements, getDistinctStoredModelIdsStatements;
|
|
164532
164661
|
var init_storage_memory_embeddings = __esm(() => {
|
|
164533
164662
|
saveEmbeddingStatements = new WeakMap;
|
|
@@ -165572,6 +165701,28 @@ function countUnembeddedSessionCompartments(db, projectPath, sessionId, modelId)
|
|
|
165572
165701
|
)`).get(projectPath, sessionId, projectPath, modelId);
|
|
165573
165702
|
return typeof row?.n === "number" ? row.n : 0;
|
|
165574
165703
|
}
|
|
165704
|
+
function countSessionCompartmentEmbedCoverage(db, projectPath, sessionId, modelId) {
|
|
165705
|
+
const row = db.prepare(`SELECT
|
|
165706
|
+
COUNT(*) AS total,
|
|
165707
|
+
SUM(CASE WHEN EXISTS (
|
|
165708
|
+
SELECT 1 FROM compartment_chunk_embeddings e
|
|
165709
|
+
WHERE e.compartment_id = c.id
|
|
165710
|
+
AND e.project_path = ?
|
|
165711
|
+
AND e.model_id = ?
|
|
165712
|
+
) THEN 1 ELSE 0 END) AS embedded
|
|
165713
|
+
FROM compartments c
|
|
165714
|
+
JOIN session_projects sp
|
|
165715
|
+
ON sp.session_id = c.session_id
|
|
165716
|
+
AND sp.harness = c.harness
|
|
165717
|
+
AND sp.project_path = ?
|
|
165718
|
+
WHERE c.session_id = ?
|
|
165719
|
+
AND c.start_message IS NOT NULL
|
|
165720
|
+
AND c.end_message IS NOT NULL`).get(projectPath, modelId, projectPath, sessionId);
|
|
165721
|
+
return {
|
|
165722
|
+
total: typeof row?.total === "number" ? row.total : 0,
|
|
165723
|
+
embedded: typeof row?.embedded === "number" ? row.embedded : 0
|
|
165724
|
+
};
|
|
165725
|
+
}
|
|
165575
165726
|
var DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS = 512, CHUNK_WINDOW_SAFETY_RATIO = 0.9, loadFtsRowsStatements, existingHashStatements, existingHashByProjectStatements, deleteByCompartmentStatements, insertEmbeddingStatements, distinctModelStatements, clearProjectStatements, clearProjectModelStatements, searchRowsStatements, searchRowsByModelStatements, backfillCandidateStatements, sessionBackfillCandidateStatements;
|
|
165576
165727
|
var init_compartment_chunk_embedding = __esm(() => {
|
|
165577
165728
|
init_read_session_formatting();
|
|
@@ -165729,6 +165880,18 @@ async function withQuietConsole(fn) {
|
|
|
165729
165880
|
console.error = origError;
|
|
165730
165881
|
}
|
|
165731
165882
|
}
|
|
165883
|
+
function isNativeRuntimeMissingError(error51) {
|
|
165884
|
+
const message = error51 instanceof Error ? error51.message : String(error51 ?? "");
|
|
165885
|
+
const lower = message.toLowerCase();
|
|
165886
|
+
const code = error51?.code;
|
|
165887
|
+
const name2 = error51?.name;
|
|
165888
|
+
if (code === "ERR_DLOPEN_FAILED" && lower.includes("onnxruntime")) {
|
|
165889
|
+
return true;
|
|
165890
|
+
}
|
|
165891
|
+
if (!lower.includes("onnxruntime-node"))
|
|
165892
|
+
return false;
|
|
165893
|
+
return code === "ERR_MODULE_NOT_FOUND" || name2 === "ResolveMessage" || lower.includes("cannot find package") || lower.includes("cannot find module") || lower.includes("err_module_not_found");
|
|
165894
|
+
}
|
|
165732
165895
|
function isTransientLoadError(error51) {
|
|
165733
165896
|
const message = error51 instanceof Error ? error51.message : String(error51 ?? "");
|
|
165734
165897
|
if (!message)
|
|
@@ -165793,6 +165956,9 @@ class LocalEmbeddingProvider {
|
|
|
165793
165956
|
if (this.pipeline) {
|
|
165794
165957
|
return true;
|
|
165795
165958
|
}
|
|
165959
|
+
if (nativeRuntimeMissing) {
|
|
165960
|
+
return false;
|
|
165961
|
+
}
|
|
165796
165962
|
if (this.initPromise) {
|
|
165797
165963
|
await this.initPromise;
|
|
165798
165964
|
return this.pipeline !== null;
|
|
@@ -165859,7 +166025,12 @@ class LocalEmbeddingProvider {
|
|
|
165859
166025
|
await releaseLock();
|
|
165860
166026
|
}
|
|
165861
166027
|
} catch (error51) {
|
|
165862
|
-
|
|
166028
|
+
if (isNativeRuntimeMissingError(error51)) {
|
|
166029
|
+
nativeRuntimeMissing = true;
|
|
166030
|
+
log("[magic-context] local embedding runtime is not installed (onnxruntime-node missing from this install). Local embeddings are disabled. Fix: reinstall the plugin (run `npx @cortexkit/magic-context@latest doctor --force`), or configure an `openai-compatible`/`ollama` embedding endpoint instead. Existing memories are unaffected.");
|
|
166031
|
+
} else {
|
|
166032
|
+
log("[magic-context] embedding model failed to load:", error51);
|
|
166033
|
+
}
|
|
165863
166034
|
this.pipeline = null;
|
|
165864
166035
|
} finally {
|
|
165865
166036
|
this.initPromise = null;
|
|
@@ -165970,7 +166141,7 @@ class LocalEmbeddingProvider {
|
|
|
165970
166141
|
return this.pipeline !== null;
|
|
165971
166142
|
}
|
|
165972
166143
|
}
|
|
165973
|
-
var LOCK_POLL_MS = 150, STALE_LOCK_MS, MAX_LOCK_WAIT_MS;
|
|
166144
|
+
var LOCK_POLL_MS = 150, STALE_LOCK_MS, MAX_LOCK_WAIT_MS, nativeRuntimeMissing = false;
|
|
165974
166145
|
var init_embedding_local = __esm(() => {
|
|
165975
166146
|
init_magic_context();
|
|
165976
166147
|
init_data_path();
|
|
@@ -166384,6 +166555,121 @@ var init_storage_git_commit_embeddings = __esm(() => {
|
|
|
166384
166555
|
distinctModelIdStatements = new WeakMap;
|
|
166385
166556
|
});
|
|
166386
166557
|
|
|
166558
|
+
// src/features/magic-context/git-commits/storage-git-commits.ts
|
|
166559
|
+
function getInsertStatement(db) {
|
|
166560
|
+
let stmt = insertStatements.get(db);
|
|
166561
|
+
if (!stmt) {
|
|
166562
|
+
stmt = db.prepare(`INSERT INTO git_commits (sha, project_path, short_sha, message, author, committed_at, indexed_at)
|
|
166563
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
166564
|
+
ON CONFLICT(sha) DO UPDATE SET
|
|
166565
|
+
project_path = excluded.project_path,
|
|
166566
|
+
short_sha = excluded.short_sha,
|
|
166567
|
+
message = excluded.message,
|
|
166568
|
+
author = excluded.author,
|
|
166569
|
+
committed_at = excluded.committed_at,
|
|
166570
|
+
indexed_at = excluded.indexed_at
|
|
166571
|
+
WHERE git_commits.message != excluded.message`);
|
|
166572
|
+
insertStatements.set(db, stmt);
|
|
166573
|
+
}
|
|
166574
|
+
return stmt;
|
|
166575
|
+
}
|
|
166576
|
+
function getExistingShasStatement(db) {
|
|
166577
|
+
let stmt = existingShasStatements.get(db);
|
|
166578
|
+
if (!stmt) {
|
|
166579
|
+
stmt = db.prepare("SELECT sha FROM git_commits WHERE project_path = ?");
|
|
166580
|
+
existingShasStatements.set(db, stmt);
|
|
166581
|
+
}
|
|
166582
|
+
return stmt;
|
|
166583
|
+
}
|
|
166584
|
+
function getProjectCountStatement(db) {
|
|
166585
|
+
let stmt = projectCountStatements.get(db);
|
|
166586
|
+
if (!stmt) {
|
|
166587
|
+
stmt = db.prepare("SELECT COUNT(*) AS count FROM git_commits WHERE project_path = ?");
|
|
166588
|
+
projectCountStatements.set(db, stmt);
|
|
166589
|
+
}
|
|
166590
|
+
return stmt;
|
|
166591
|
+
}
|
|
166592
|
+
function getLatestCommitTimeStatement(db) {
|
|
166593
|
+
let stmt = latestCommitTimeStatements.get(db);
|
|
166594
|
+
if (!stmt) {
|
|
166595
|
+
stmt = db.prepare("SELECT MAX(committed_at) AS latest FROM git_commits WHERE project_path = ?");
|
|
166596
|
+
latestCommitTimeStatements.set(db, stmt);
|
|
166597
|
+
}
|
|
166598
|
+
return stmt;
|
|
166599
|
+
}
|
|
166600
|
+
function getEvictOverflowStatement(db) {
|
|
166601
|
+
let stmt = evictOverflowStatements.get(db);
|
|
166602
|
+
if (!stmt) {
|
|
166603
|
+
stmt = db.prepare(`DELETE FROM git_commits
|
|
166604
|
+
WHERE rowid IN (
|
|
166605
|
+
SELECT rowid FROM git_commits
|
|
166606
|
+
WHERE project_path = ?
|
|
166607
|
+
ORDER BY committed_at DESC, sha DESC
|
|
166608
|
+
LIMIT -1 OFFSET ?
|
|
166609
|
+
)`);
|
|
166610
|
+
evictOverflowStatements.set(db, stmt);
|
|
166611
|
+
}
|
|
166612
|
+
return stmt;
|
|
166613
|
+
}
|
|
166614
|
+
function upsertCommits(db, projectPath, commits) {
|
|
166615
|
+
if (commits.length === 0)
|
|
166616
|
+
return { inserted: 0, updated: 0 };
|
|
166617
|
+
const existing = new Set;
|
|
166618
|
+
for (const row of getExistingShasStatement(db).all(projectPath)) {
|
|
166619
|
+
existing.add(row.sha);
|
|
166620
|
+
}
|
|
166621
|
+
let inserted = 0;
|
|
166622
|
+
let updated = 0;
|
|
166623
|
+
const now = Date.now();
|
|
166624
|
+
const insertStmt = getInsertStatement(db);
|
|
166625
|
+
db.transaction(() => {
|
|
166626
|
+
for (const commit of commits) {
|
|
166627
|
+
const result = insertStmt.run(commit.sha, projectPath, commit.shortSha, commit.message, commit.author, commit.committedAtMs, now);
|
|
166628
|
+
if (result.changes > 0) {
|
|
166629
|
+
if (existing.has(commit.sha)) {
|
|
166630
|
+
updated++;
|
|
166631
|
+
} else {
|
|
166632
|
+
inserted++;
|
|
166633
|
+
existing.add(commit.sha);
|
|
166634
|
+
}
|
|
166635
|
+
}
|
|
166636
|
+
}
|
|
166637
|
+
})();
|
|
166638
|
+
return { inserted, updated };
|
|
166639
|
+
}
|
|
166640
|
+
function getCommitCount(db, projectPath) {
|
|
166641
|
+
const row = getProjectCountStatement(db).get(projectPath);
|
|
166642
|
+
return row?.count ?? 0;
|
|
166643
|
+
}
|
|
166644
|
+
function getLatestIndexedCommitTimeMs(db, projectPath) {
|
|
166645
|
+
const row = getLatestCommitTimeStatement(db).get(projectPath);
|
|
166646
|
+
return row?.latest ?? null;
|
|
166647
|
+
}
|
|
166648
|
+
function enforceProjectCap(db, projectPath, maxCommits) {
|
|
166649
|
+
if (maxCommits <= 0)
|
|
166650
|
+
return 0;
|
|
166651
|
+
const count = getCommitCount(db, projectPath);
|
|
166652
|
+
if (count <= maxCommits)
|
|
166653
|
+
return 0;
|
|
166654
|
+
getEvictOverflowStatement(db).run(projectPath, maxCommits);
|
|
166655
|
+
const after = getCommitCount(db, projectPath);
|
|
166656
|
+
const evicted = Math.max(0, count - after);
|
|
166657
|
+
if (evicted > 0) {
|
|
166658
|
+
log(`[git-commits] evicted ${evicted} oldest commits for project ${projectPath} (cap=${maxCommits}, was=${count})`);
|
|
166659
|
+
}
|
|
166660
|
+
return evicted;
|
|
166661
|
+
}
|
|
166662
|
+
var insertStatements, existingShasStatements, projectCountStatements, evictStatements, evictOverflowStatements, latestCommitTimeStatements;
|
|
166663
|
+
var init_storage_git_commits = __esm(() => {
|
|
166664
|
+
init_logger();
|
|
166665
|
+
insertStatements = new WeakMap;
|
|
166666
|
+
existingShasStatements = new WeakMap;
|
|
166667
|
+
projectCountStatements = new WeakMap;
|
|
166668
|
+
evictStatements = new WeakMap;
|
|
166669
|
+
evictOverflowStatements = new WeakMap;
|
|
166670
|
+
latestCommitTimeStatements = new WeakMap;
|
|
166671
|
+
});
|
|
166672
|
+
|
|
166387
166673
|
// src/features/magic-context/git-commits/sweep-coordinator.ts
|
|
166388
166674
|
function runImmediate2(db, body) {
|
|
166389
166675
|
db.exec("BEGIN IMMEDIATE");
|
|
@@ -166677,7 +166963,9 @@ function snapshotFor(registration) {
|
|
|
166677
166963
|
enabled,
|
|
166678
166964
|
gitCommitEnabled,
|
|
166679
166965
|
modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
|
|
166680
|
-
chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId
|
|
166966
|
+
chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId,
|
|
166967
|
+
model: registration.observationMode || !providerIsOn ? "off" : ("model" in registration.config) && registration.config.model.trim() ? registration.config.model.trim() : registration.modelId,
|
|
166968
|
+
provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "local"
|
|
166681
166969
|
};
|
|
166682
166970
|
}
|
|
166683
166971
|
function disposeProvider(provider) {
|
|
@@ -166888,8 +167176,9 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
|
|
|
166888
167176
|
}
|
|
166889
167177
|
async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates, signal) {
|
|
166890
167178
|
const noWork = [];
|
|
167179
|
+
const failed = [];
|
|
166891
167180
|
if (candidates.length === 0)
|
|
166892
|
-
return { embedded: 0, noWork };
|
|
167181
|
+
return { embedded: 0, noWork, failed };
|
|
166893
167182
|
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
|
|
166894
167183
|
const prepared = [];
|
|
166895
167184
|
for (const candidate of candidates) {
|
|
@@ -166906,7 +167195,7 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
|
|
|
166906
167195
|
prepared.push({ candidate, windows });
|
|
166907
167196
|
}
|
|
166908
167197
|
if (prepared.length === 0)
|
|
166909
|
-
return { embedded: 0, noWork };
|
|
167198
|
+
return { embedded: 0, noWork, failed };
|
|
166910
167199
|
let embedded = 0;
|
|
166911
167200
|
let i = 0;
|
|
166912
167201
|
while (i < prepared.length) {
|
|
@@ -166923,35 +167212,60 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
|
|
|
166923
167212
|
const texts = [];
|
|
166924
167213
|
for (const item of slice)
|
|
166925
167214
|
texts.push(...item.windows.map((w) => w.text));
|
|
166926
|
-
|
|
166927
|
-
|
|
166928
|
-
if (!result)
|
|
166929
|
-
continue;
|
|
167215
|
+
const persistedIds = new Set;
|
|
167216
|
+
for (let attempt = 0;attempt < EMBED_SLICE_RETRY_ATTEMPTS; attempt++) {
|
|
166930
167217
|
if (signal?.aborted)
|
|
166931
167218
|
break;
|
|
166932
|
-
let
|
|
166933
|
-
|
|
166934
|
-
|
|
166935
|
-
|
|
166936
|
-
|
|
166937
|
-
|
|
167219
|
+
let result = null;
|
|
167220
|
+
const attemptStart = Date.now();
|
|
167221
|
+
try {
|
|
167222
|
+
result = await embedBatchForProject(projectIdentity, texts, signal);
|
|
167223
|
+
} catch (error51) {
|
|
167224
|
+
log("[magic-context] failed to proactively embed compartment chunks:", error51);
|
|
167225
|
+
}
|
|
167226
|
+
if (signal?.aborted)
|
|
167227
|
+
break;
|
|
167228
|
+
if (result) {
|
|
167229
|
+
let offset = 0;
|
|
167230
|
+
for (const item of slice) {
|
|
167231
|
+
const vectors = result.vectors.slice(offset, offset + item.windows.length);
|
|
167232
|
+
offset += item.windows.length;
|
|
167233
|
+
if (persistedIds.has(item.candidate.id))
|
|
167234
|
+
continue;
|
|
167235
|
+
if (vectors.length !== item.windows.length || vectors.some((v) => !v)) {
|
|
167236
|
+
continue;
|
|
167237
|
+
}
|
|
167238
|
+
const rows = item.windows.map((window, index) => ({
|
|
167239
|
+
compartmentId: item.candidate.id,
|
|
167240
|
+
sessionId: item.candidate.sessionId,
|
|
167241
|
+
projectPath: projectIdentity,
|
|
167242
|
+
window,
|
|
167243
|
+
modelId,
|
|
167244
|
+
vector: vectors[index]
|
|
167245
|
+
}));
|
|
167246
|
+
replaceCompartmentChunkEmbeddings(db, rows);
|
|
167247
|
+
persistedIds.add(item.candidate.id);
|
|
166938
167248
|
}
|
|
166939
|
-
const rows = item.windows.map((window, index) => ({
|
|
166940
|
-
compartmentId: item.candidate.id,
|
|
166941
|
-
sessionId: item.candidate.sessionId,
|
|
166942
|
-
projectPath: projectIdentity,
|
|
166943
|
-
window,
|
|
166944
|
-
modelId,
|
|
166945
|
-
vector: vectors[index]
|
|
166946
|
-
}));
|
|
166947
|
-
replaceCompartmentChunkEmbeddings(db, rows);
|
|
166948
|
-
embedded += 1;
|
|
166949
167249
|
}
|
|
166950
|
-
|
|
166951
|
-
|
|
167250
|
+
if (persistedIds.size === slice.length)
|
|
167251
|
+
break;
|
|
167252
|
+
if (persistedIds.size > 0)
|
|
167253
|
+
break;
|
|
167254
|
+
if (Date.now() - attemptStart >= EMBED_SLOW_FAILURE_NO_RETRY_MS)
|
|
167255
|
+
break;
|
|
167256
|
+
if (attempt < EMBED_SLICE_RETRY_ATTEMPTS - 1) {
|
|
167257
|
+
await new Promise((resolve7) => setTimeout(resolve7, EMBED_SLICE_RETRY_BASE_MS * 2 ** attempt));
|
|
167258
|
+
}
|
|
167259
|
+
}
|
|
167260
|
+
embedded += persistedIds.size;
|
|
167261
|
+
if (!signal?.aborted) {
|
|
167262
|
+
for (const item of slice) {
|
|
167263
|
+
if (!persistedIds.has(item.candidate.id))
|
|
167264
|
+
failed.push(item.candidate.id);
|
|
167265
|
+
}
|
|
166952
167266
|
}
|
|
166953
167267
|
}
|
|
166954
|
-
return { embedded, noWork };
|
|
167268
|
+
return { embedded, noWork, failed };
|
|
166955
167269
|
}
|
|
166956
167270
|
async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, options) {
|
|
166957
167271
|
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
@@ -166974,9 +167288,11 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
166974
167288
|
renewal.unref?.();
|
|
166975
167289
|
const batchSize = Math.max(1, options?.batchSize ?? CHUNK_DRAIN_BATCH_SIZE);
|
|
166976
167290
|
const skipIds = [];
|
|
167291
|
+
const failedIds = [];
|
|
166977
167292
|
let embedded = 0;
|
|
166978
167293
|
let aborted2 = false;
|
|
166979
|
-
let
|
|
167294
|
+
let providerDown = false;
|
|
167295
|
+
let consecutiveFailedBatches = 0;
|
|
166980
167296
|
try {
|
|
166981
167297
|
options?.onProgress?.({ embedded, total });
|
|
166982
167298
|
for (;; ) {
|
|
@@ -166984,15 +167300,26 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
166984
167300
|
aborted2 = true;
|
|
166985
167301
|
break;
|
|
166986
167302
|
}
|
|
166987
|
-
const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, skipIds);
|
|
167303
|
+
const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, [...skipIds, ...failedIds]);
|
|
166988
167304
|
if (candidates.length === 0)
|
|
166989
167305
|
break;
|
|
166990
|
-
const {
|
|
167306
|
+
const {
|
|
167307
|
+
embedded: n,
|
|
167308
|
+
noWork,
|
|
167309
|
+
failed
|
|
167310
|
+
} = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, options?.signal);
|
|
166991
167311
|
for (const id of noWork)
|
|
166992
167312
|
skipIds.push(id);
|
|
167313
|
+
for (const id of failed)
|
|
167314
|
+
failedIds.push(id);
|
|
166993
167315
|
if (n === 0 && noWork.length === 0) {
|
|
166994
|
-
|
|
166995
|
-
|
|
167316
|
+
consecutiveFailedBatches += 1;
|
|
167317
|
+
if (consecutiveFailedBatches >= MAX_CONSECUTIVE_FAILED_BATCHES) {
|
|
167318
|
+
providerDown = true;
|
|
167319
|
+
break;
|
|
167320
|
+
}
|
|
167321
|
+
} else {
|
|
167322
|
+
consecutiveFailedBatches = 0;
|
|
166996
167323
|
}
|
|
166997
167324
|
embedded += n;
|
|
166998
167325
|
options?.onProgress?.({ embedded: Math.min(embedded, total), total });
|
|
@@ -167000,23 +167327,58 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
167000
167327
|
}
|
|
167001
167328
|
} finally {
|
|
167002
167329
|
clearInterval(renewal);
|
|
167003
|
-
|
|
167330
|
+
try {
|
|
167331
|
+
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
167332
|
+
} catch (error51) {
|
|
167333
|
+
log("[magic-context] embed drain: lease release failed (will TTL-expire):", error51);
|
|
167334
|
+
}
|
|
167004
167335
|
}
|
|
167005
167336
|
if (aborted2)
|
|
167006
|
-
return { status: "aborted", embedded, total };
|
|
167007
|
-
if (
|
|
167337
|
+
return { status: "aborted", embedded, total, failed: failedIds.length };
|
|
167338
|
+
if (providerDown || failedIds.length > 0) {
|
|
167008
167339
|
const remaining = Math.max(0, countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot.chunkModelId) - skipIds.length);
|
|
167009
|
-
if (remaining > 0)
|
|
167010
|
-
return { status: "stalled", embedded, total, remaining };
|
|
167340
|
+
if (remaining > 0) {
|
|
167341
|
+
return { status: "stalled", embedded, total, remaining, failed: failedIds.length };
|
|
167342
|
+
}
|
|
167011
167343
|
}
|
|
167012
|
-
return { status: "done", embedded, total };
|
|
167344
|
+
return { status: "done", embedded, total, failed: failedIds.length };
|
|
167013
167345
|
}
|
|
167014
|
-
|
|
167346
|
+
function getEmbeddingCoverageStatus(db, projectIdentity, sessionId) {
|
|
167347
|
+
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
167348
|
+
if (!snapshot?.enabled || snapshot.chunkModelId === "off") {
|
|
167349
|
+
return {
|
|
167350
|
+
enabled: false,
|
|
167351
|
+
model: snapshot?.model ?? "off",
|
|
167352
|
+
provider: snapshot?.provider ?? "off",
|
|
167353
|
+
session: { embedded: 0, total: 0 },
|
|
167354
|
+
memories: { embedded: 0, total: 0 },
|
|
167355
|
+
commits: { embedded: 0, total: 0, gitEnabled: false }
|
|
167356
|
+
};
|
|
167357
|
+
}
|
|
167358
|
+
const session = countSessionCompartmentEmbedCoverage(db, projectIdentity, sessionId, snapshot.chunkModelId);
|
|
167359
|
+
const memories = getMemoryEmbedCoverage(db, projectIdentity, snapshot.modelId);
|
|
167360
|
+
const gitEnabled = snapshot.gitCommitEnabled;
|
|
167361
|
+
const commits = gitEnabled ? {
|
|
167362
|
+
embedded: countEmbeddedCommits(db, projectIdentity),
|
|
167363
|
+
total: getCommitCount(db, projectIdentity),
|
|
167364
|
+
gitEnabled: true
|
|
167365
|
+
} : { embedded: 0, total: 0, gitEnabled: false };
|
|
167366
|
+
return {
|
|
167367
|
+
enabled: true,
|
|
167368
|
+
model: snapshot.model,
|
|
167369
|
+
provider: snapshot.provider,
|
|
167370
|
+
session,
|
|
167371
|
+
memories,
|
|
167372
|
+
commits
|
|
167373
|
+
};
|
|
167374
|
+
}
|
|
167375
|
+
var OFF_PROVIDER_IDENTITY = "embedding-provider:off", SWEEP_MAX_WALL_CLOCK_MS, CHUNK_DRAIN_BATCH_SIZE = 8, MAX_WINDOWS_PER_EMBED_CALL = 2, SESSION_EMBED_LEASE_RENEWAL_MS, EMBED_SLICE_RETRY_ATTEMPTS = 3, EMBED_SLICE_RETRY_BASE_MS = 250, EMBED_SLOW_FAILURE_NO_RETRY_MS = 1e4, MAX_CONSECUTIVE_FAILED_BATCHES = 3, projectRegistrations, loadUnembeddedMemoriesStatements, globalRegistrationGeneration = 0, testProviderFactory = null;
|
|
167015
167376
|
var init_project_embedding_registry = __esm(() => {
|
|
167016
167377
|
init_magic_context();
|
|
167017
167378
|
init_logger();
|
|
167018
167379
|
init_compartment_chunk_embedding();
|
|
167019
167380
|
init_storage_git_commit_embeddings();
|
|
167381
|
+
init_storage_git_commits();
|
|
167020
167382
|
init_sweep_coordinator();
|
|
167021
167383
|
init_embedding_cache();
|
|
167022
167384
|
init_embedding_identity();
|
|
@@ -167297,58 +167659,6 @@ var init_models_dev_cache = __esm(() => {
|
|
|
167297
167659
|
init_logger();
|
|
167298
167660
|
});
|
|
167299
167661
|
|
|
167300
|
-
// src/shared/rpc-notifications.ts
|
|
167301
|
-
var exports_rpc_notifications = {};
|
|
167302
|
-
__export(exports_rpc_notifications, {
|
|
167303
|
-
pushNotification: () => pushNotification,
|
|
167304
|
-
isTuiConnected: () => isTuiConnected,
|
|
167305
|
-
drainNotifications: () => drainNotifications
|
|
167306
|
-
});
|
|
167307
|
-
function pushNotification(type, payload, sessionId) {
|
|
167308
|
-
queue2.push({ id: nextNotificationId++, type, payload, sessionId });
|
|
167309
|
-
if (queue2.length > 100) {
|
|
167310
|
-
const newestPerSession = new Map;
|
|
167311
|
-
for (const n of queue2) {
|
|
167312
|
-
const prev = newestPerSession.get(n.sessionId);
|
|
167313
|
-
if (prev === undefined || n.id > prev) {
|
|
167314
|
-
newestPerSession.set(n.sessionId, n.id);
|
|
167315
|
-
}
|
|
167316
|
-
}
|
|
167317
|
-
const mustKeep = new Set(newestPerSession.values());
|
|
167318
|
-
const byNewest = [...queue2].sort((a, b) => b.id - a.id);
|
|
167319
|
-
const kept = [];
|
|
167320
|
-
for (const n of byNewest) {
|
|
167321
|
-
if (kept.length < 50 || mustKeep.has(n.id))
|
|
167322
|
-
kept.push(n);
|
|
167323
|
-
}
|
|
167324
|
-
queue2 = kept.sort((a, b) => a.id - b.id);
|
|
167325
|
-
}
|
|
167326
|
-
}
|
|
167327
|
-
function drainNotifications(lastReceivedId = 0, sessionId) {
|
|
167328
|
-
const now = Date.now();
|
|
167329
|
-
lastDrainAtAny = now;
|
|
167330
|
-
if (sessionId !== undefined)
|
|
167331
|
-
lastDrainAtBySession.set(sessionId, now);
|
|
167332
|
-
const matchesClient = (notification) => sessionId === undefined || notification.sessionId === undefined || notification.sessionId === sessionId;
|
|
167333
|
-
if (lastReceivedId > 0) {
|
|
167334
|
-
queue2 = queue2.filter((notification) => !(notification.id <= lastReceivedId && matchesClient(notification)));
|
|
167335
|
-
}
|
|
167336
|
-
return queue2.filter((notification) => notification.id > lastReceivedId && matchesClient(notification));
|
|
167337
|
-
}
|
|
167338
|
-
function isTuiConnected(sessionId) {
|
|
167339
|
-
const now = Date.now();
|
|
167340
|
-
if (sessionId !== undefined) {
|
|
167341
|
-
const at = lastDrainAtBySession.get(sessionId) ?? 0;
|
|
167342
|
-
return at > 0 && now - at < TUI_CONNECTED_WINDOW_MS;
|
|
167343
|
-
}
|
|
167344
|
-
return lastDrainAtAny > 0 && now - lastDrainAtAny < TUI_CONNECTED_WINDOW_MS;
|
|
167345
|
-
}
|
|
167346
|
-
var queue2, nextNotificationId = 1, lastDrainAtBySession, lastDrainAtAny = 0, TUI_CONNECTED_WINDOW_MS = 3000;
|
|
167347
|
-
var init_rpc_notifications = __esm(() => {
|
|
167348
|
-
queue2 = [];
|
|
167349
|
-
lastDrainAtBySession = new Map;
|
|
167350
|
-
});
|
|
167351
|
-
|
|
167352
167662
|
// src/features/magic-context/compartment-embedding.ts
|
|
167353
167663
|
async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compartments) {
|
|
167354
167664
|
if (compartments.length === 0)
|
|
@@ -170900,7 +171210,7 @@ function buildToolArcs(messages) {
|
|
|
170900
171210
|
}
|
|
170901
171211
|
return arcs.sort((a, b) => a.invOrdinal - b.invOrdinal || (a.resOrdinal ?? Number.MAX_SAFE_INTEGER) - (b.resOrdinal ?? Number.MAX_SAFE_INTEGER));
|
|
170902
171212
|
}
|
|
170903
|
-
function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal) {
|
|
171213
|
+
function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal, recentOpenArcCutoff) {
|
|
170904
171214
|
let boundary = candidate;
|
|
170905
171215
|
for (const arc of arcs) {
|
|
170906
171216
|
if (arc.resOrdinal !== null) {
|
|
@@ -170909,6 +171219,8 @@ function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal) {
|
|
|
170909
171219
|
}
|
|
170910
171220
|
continue;
|
|
170911
171221
|
}
|
|
171222
|
+
if (arc.invOrdinal < recentOpenArcCutoff)
|
|
171223
|
+
continue;
|
|
170912
171224
|
if (arc.invOrdinal >= lastCompartmentEndOrdinal + 1 && arc.invOrdinal < boundary) {
|
|
170913
171225
|
return arc.invOrdinal;
|
|
170914
171226
|
}
|
|
@@ -171148,7 +171460,7 @@ function semanticSnapBoundary(args) {
|
|
|
171148
171460
|
return snapped;
|
|
171149
171461
|
}
|
|
171150
171462
|
function applyHeadCap(args) {
|
|
171151
|
-
const { index, protectedTailStart, offset, arcs, capTokens } = args;
|
|
171463
|
+
const { index, protectedTailStart, offset, arcs, capTokens, recentOpenArcCutoff } = args;
|
|
171152
171464
|
if (offset >= protectedTailStart)
|
|
171153
171465
|
return { eligibleEndOrdinal: offset, oversizeAtomicUnit: false };
|
|
171154
171466
|
let end = index.findHeadEndForCap(offset, protectedTailStart, capTokens);
|
|
@@ -171156,7 +171468,7 @@ function applyHeadCap(args) {
|
|
|
171156
171468
|
for (const arc of arcs) {
|
|
171157
171469
|
const resOrdinal = arc.resOrdinal;
|
|
171158
171470
|
if (resOrdinal === null) {
|
|
171159
|
-
if (arc.invOrdinal >= offset && arc.invOrdinal < end) {
|
|
171471
|
+
if (arc.invOrdinal >= recentOpenArcCutoff && arc.invOrdinal >= offset && arc.invOrdinal < end) {
|
|
171160
171472
|
end = Math.min(end, arc.invOrdinal);
|
|
171161
171473
|
}
|
|
171162
171474
|
continue;
|
|
@@ -171223,7 +171535,14 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171223
171535
|
}
|
|
171224
171536
|
if (ctx.mode === "manual-full-recomp") {
|
|
171225
171537
|
const arcs2 = buildToolArcs(messages);
|
|
171226
|
-
const
|
|
171538
|
+
const recompTarget = deriveProtectedTailTokenTarget({
|
|
171539
|
+
contextLimit: ctx.contextLimit,
|
|
171540
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
171541
|
+
usagePercentage: 0,
|
|
171542
|
+
triggerBudget: ctx.triggerBudget
|
|
171543
|
+
});
|
|
171544
|
+
const recentOpenArcCutoff2 = index.findSuffixStartForTokens(recompTarget.N);
|
|
171545
|
+
const firstOpenArc = arcs2.find((arc) => arc.resOrdinal === null && arc.invOrdinal >= offset && arc.invOrdinal >= recentOpenArcCutoff2);
|
|
171227
171546
|
const protectedTailStart2 = firstOpenArc?.invOrdinal ?? rawMessageCount + 1;
|
|
171228
171547
|
const rawRangeFingerprint2 = computeRawRangeFingerprint(messages, offset, protectedTailStart2);
|
|
171229
171548
|
return {
|
|
@@ -171265,13 +171584,14 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171265
171584
|
const scaledN = ctx.emergencyTailScale ? Math.max(1, Math.floor(target.N * ctx.emergencyTailScale)) : target.N;
|
|
171266
171585
|
const arcs = buildToolArcs(messages);
|
|
171267
171586
|
let boundary = index.findSuffixStartForTokens(scaledN);
|
|
171587
|
+
const recentOpenArcCutoff = boundary;
|
|
171268
171588
|
let boundaryReason = boundary === 1 ? "whole-session-smaller-than-tail" : "size-walk";
|
|
171269
171589
|
const tokenAtBoundary = index.tokenForOrdinal(boundary);
|
|
171270
171590
|
if (boundary <= rawMessageCount && tokenAtBoundary > Math.max(2 * scaledN, 64000) && boundary < rawMessageCount) {
|
|
171271
171591
|
boundary += 1;
|
|
171272
171592
|
boundaryReason = "huge-message-exception";
|
|
171273
171593
|
}
|
|
171274
|
-
boundary = fenceBoundaryForToolArcs(boundary, arcs, ctx.lastCompartmentEndOrdinal);
|
|
171594
|
+
boundary = fenceBoundaryForToolArcs(boundary, arcs, ctx.lastCompartmentEndOrdinal, recentOpenArcCutoff);
|
|
171275
171595
|
const snapped = semanticSnapBoundary({
|
|
171276
171596
|
messages,
|
|
171277
171597
|
index,
|
|
@@ -171281,7 +171601,7 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171281
171601
|
});
|
|
171282
171602
|
if (snapped !== boundary)
|
|
171283
171603
|
boundaryReason = "semantic-snap";
|
|
171284
|
-
boundary = fenceBoundaryForToolArcs(snapped, arcs, ctx.lastCompartmentEndOrdinal);
|
|
171604
|
+
boundary = fenceBoundaryForToolArcs(snapped, arcs, ctx.lastCompartmentEndOrdinal, recentOpenArcCutoff);
|
|
171285
171605
|
let runtimeFloor = offset;
|
|
171286
171606
|
if (ctx.migrationFloorActive)
|
|
171287
171607
|
runtimeFloor = Math.max(runtimeFloor, ctx.priorBoundaryOrdinal);
|
|
@@ -171317,7 +171637,8 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171317
171637
|
offset,
|
|
171318
171638
|
arcs,
|
|
171319
171639
|
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal,
|
|
171320
|
-
capTokens: perRunCap
|
|
171640
|
+
capTokens: perRunCap,
|
|
171641
|
+
recentOpenArcCutoff
|
|
171321
171642
|
});
|
|
171322
171643
|
const rawRangeFingerprint = computeRawRangeFingerprint(messages, offset, head.eligibleEndOrdinal);
|
|
171323
171644
|
return {
|
|
@@ -177274,15 +177595,15 @@ function shouldShowAnnouncement() {
|
|
|
177274
177595
|
}
|
|
177275
177596
|
return state.version !== ANNOUNCEMENT_VERSION;
|
|
177276
177597
|
}
|
|
177277
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
177598
|
+
var ANNOUNCEMENT_VERSION = "0.25.0", ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU", STATE_FILENAME = "last_announced_version";
|
|
177278
177599
|
var init_announcement = __esm(() => {
|
|
177279
177600
|
init_data_path();
|
|
177280
177601
|
ANNOUNCEMENT_FEATURES = [
|
|
177281
|
-
"
|
|
177282
|
-
"
|
|
177283
|
-
"
|
|
177284
|
-
"
|
|
177285
|
-
"
|
|
177602
|
+
"Old tool output is now reclaimed automatically: once a file read / search / command output has gone a full execute cycle unused, it's dropped on the next one — no need to call ctx_reduce for stale results.",
|
|
177603
|
+
"Recover anything that was dropped: ctx_expand({ message: N }) returns a dropped message's full content (every tool call's input + output) from storage. ctx_expand({ start, end, verbose: true }) lists a range message-by-message to find it.",
|
|
177604
|
+
"Searchable history made reliable: /ctx-embed shows embedding coverage and runs a resilient backfill (retries transient failures, no longer bails on the first hiccup); the active session now auto-embeds in the background. ctx_reduce guidance also reframed as deferred + recoverable so models trim spent output earlier.",
|
|
177605
|
+
"Pi: fixed /ctx-dream (was failing with 'Unknown named parameter') and local-embedding load failures on Windows/Desktop (#151, #128).",
|
|
177606
|
+
"Runaway background agents on weak/local models are now capped and force-stopped (#154, #152). Plus several prompt-cache busts removed."
|
|
177286
177607
|
];
|
|
177287
177608
|
});
|
|
177288
177609
|
|
|
@@ -178077,9 +178398,9 @@ function getMagicContextBuiltinCommands() {
|
|
|
178077
178398
|
template: "ctx-dream",
|
|
178078
178399
|
description: "Run the hidden dreamer maintenance pass for this project now"
|
|
178079
178400
|
},
|
|
178080
|
-
"ctx-embed
|
|
178081
|
-
template: "ctx-embed
|
|
178082
|
-
description: "
|
|
178401
|
+
"ctx-embed": {
|
|
178402
|
+
template: "ctx-embed",
|
|
178403
|
+
description: "Embedding status, or start/pause history compartment embedding (start | pause)"
|
|
178083
178404
|
}
|
|
178084
178405
|
};
|
|
178085
178406
|
}
|
|
@@ -179547,7 +179868,7 @@ function enqueueDream(db, projectIdentity, reason, force = false) {
|
|
|
179547
179868
|
return db.transaction(() => {
|
|
179548
179869
|
if (!hasActiveDreamLease(db)) {
|
|
179549
179870
|
const staleThresholdMs = force ? 2 * 60 * 1000 : 120 * 60 * 1000;
|
|
179550
|
-
db.prepare("DELETE FROM dream_queue WHERE project_path = ? AND started_at IS NOT NULL AND started_at < ?").run(
|
|
179871
|
+
db.prepare("DELETE FROM dream_queue WHERE project_path = ? AND started_at IS NOT NULL AND started_at < ?").run(projectIdentity, now - staleThresholdMs);
|
|
179551
179872
|
}
|
|
179552
179873
|
const existing = db.prepare("SELECT id FROM dream_queue WHERE project_path = ?").get(projectIdentity);
|
|
179553
179874
|
if (existing) {
|
|
@@ -181242,120 +181563,7 @@ ${body}` : subject;
|
|
|
181242
181563
|
init_logger();
|
|
181243
181564
|
init_embedding();
|
|
181244
181565
|
init_storage_git_commit_embeddings();
|
|
181245
|
-
|
|
181246
|
-
// src/features/magic-context/git-commits/storage-git-commits.ts
|
|
181247
|
-
init_logger();
|
|
181248
|
-
var insertStatements = new WeakMap;
|
|
181249
|
-
var existingShasStatements = new WeakMap;
|
|
181250
|
-
var projectCountStatements = new WeakMap;
|
|
181251
|
-
var evictStatements = new WeakMap;
|
|
181252
|
-
var evictOverflowStatements = new WeakMap;
|
|
181253
|
-
var latestCommitTimeStatements = new WeakMap;
|
|
181254
|
-
function getInsertStatement(db) {
|
|
181255
|
-
let stmt = insertStatements.get(db);
|
|
181256
|
-
if (!stmt) {
|
|
181257
|
-
stmt = db.prepare(`INSERT INTO git_commits (sha, project_path, short_sha, message, author, committed_at, indexed_at)
|
|
181258
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
181259
|
-
ON CONFLICT(sha) DO UPDATE SET
|
|
181260
|
-
project_path = excluded.project_path,
|
|
181261
|
-
short_sha = excluded.short_sha,
|
|
181262
|
-
message = excluded.message,
|
|
181263
|
-
author = excluded.author,
|
|
181264
|
-
committed_at = excluded.committed_at,
|
|
181265
|
-
indexed_at = excluded.indexed_at
|
|
181266
|
-
WHERE git_commits.message != excluded.message`);
|
|
181267
|
-
insertStatements.set(db, stmt);
|
|
181268
|
-
}
|
|
181269
|
-
return stmt;
|
|
181270
|
-
}
|
|
181271
|
-
function getExistingShasStatement(db) {
|
|
181272
|
-
let stmt = existingShasStatements.get(db);
|
|
181273
|
-
if (!stmt) {
|
|
181274
|
-
stmt = db.prepare("SELECT sha FROM git_commits WHERE project_path = ?");
|
|
181275
|
-
existingShasStatements.set(db, stmt);
|
|
181276
|
-
}
|
|
181277
|
-
return stmt;
|
|
181278
|
-
}
|
|
181279
|
-
function getProjectCountStatement(db) {
|
|
181280
|
-
let stmt = projectCountStatements.get(db);
|
|
181281
|
-
if (!stmt) {
|
|
181282
|
-
stmt = db.prepare("SELECT COUNT(*) AS count FROM git_commits WHERE project_path = ?");
|
|
181283
|
-
projectCountStatements.set(db, stmt);
|
|
181284
|
-
}
|
|
181285
|
-
return stmt;
|
|
181286
|
-
}
|
|
181287
|
-
function getLatestCommitTimeStatement(db) {
|
|
181288
|
-
let stmt = latestCommitTimeStatements.get(db);
|
|
181289
|
-
if (!stmt) {
|
|
181290
|
-
stmt = db.prepare("SELECT MAX(committed_at) AS latest FROM git_commits WHERE project_path = ?");
|
|
181291
|
-
latestCommitTimeStatements.set(db, stmt);
|
|
181292
|
-
}
|
|
181293
|
-
return stmt;
|
|
181294
|
-
}
|
|
181295
|
-
function getEvictOverflowStatement(db) {
|
|
181296
|
-
let stmt = evictOverflowStatements.get(db);
|
|
181297
|
-
if (!stmt) {
|
|
181298
|
-
stmt = db.prepare(`DELETE FROM git_commits
|
|
181299
|
-
WHERE rowid IN (
|
|
181300
|
-
SELECT rowid FROM git_commits
|
|
181301
|
-
WHERE project_path = ?
|
|
181302
|
-
ORDER BY committed_at DESC, sha DESC
|
|
181303
|
-
LIMIT -1 OFFSET ?
|
|
181304
|
-
)`);
|
|
181305
|
-
evictOverflowStatements.set(db, stmt);
|
|
181306
|
-
}
|
|
181307
|
-
return stmt;
|
|
181308
|
-
}
|
|
181309
|
-
function upsertCommits(db, projectPath, commits) {
|
|
181310
|
-
if (commits.length === 0)
|
|
181311
|
-
return { inserted: 0, updated: 0 };
|
|
181312
|
-
const existing = new Set;
|
|
181313
|
-
for (const row of getExistingShasStatement(db).all(projectPath)) {
|
|
181314
|
-
existing.add(row.sha);
|
|
181315
|
-
}
|
|
181316
|
-
let inserted = 0;
|
|
181317
|
-
let updated = 0;
|
|
181318
|
-
const now = Date.now();
|
|
181319
|
-
const insertStmt = getInsertStatement(db);
|
|
181320
|
-
db.transaction(() => {
|
|
181321
|
-
for (const commit of commits) {
|
|
181322
|
-
const result = insertStmt.run(commit.sha, projectPath, commit.shortSha, commit.message, commit.author, commit.committedAtMs, now);
|
|
181323
|
-
if (result.changes > 0) {
|
|
181324
|
-
if (existing.has(commit.sha)) {
|
|
181325
|
-
updated++;
|
|
181326
|
-
} else {
|
|
181327
|
-
inserted++;
|
|
181328
|
-
existing.add(commit.sha);
|
|
181329
|
-
}
|
|
181330
|
-
}
|
|
181331
|
-
}
|
|
181332
|
-
})();
|
|
181333
|
-
return { inserted, updated };
|
|
181334
|
-
}
|
|
181335
|
-
function getCommitCount(db, projectPath) {
|
|
181336
|
-
const row = getProjectCountStatement(db).get(projectPath);
|
|
181337
|
-
return row?.count ?? 0;
|
|
181338
|
-
}
|
|
181339
|
-
function getLatestIndexedCommitTimeMs(db, projectPath) {
|
|
181340
|
-
const row = getLatestCommitTimeStatement(db).get(projectPath);
|
|
181341
|
-
return row?.latest ?? null;
|
|
181342
|
-
}
|
|
181343
|
-
function enforceProjectCap(db, projectPath, maxCommits) {
|
|
181344
|
-
if (maxCommits <= 0)
|
|
181345
|
-
return 0;
|
|
181346
|
-
const count = getCommitCount(db, projectPath);
|
|
181347
|
-
if (count <= maxCommits)
|
|
181348
|
-
return 0;
|
|
181349
|
-
getEvictOverflowStatement(db).run(projectPath, maxCommits);
|
|
181350
|
-
const after = getCommitCount(db, projectPath);
|
|
181351
|
-
const evicted = Math.max(0, count - after);
|
|
181352
|
-
if (evicted > 0) {
|
|
181353
|
-
log(`[git-commits] evicted ${evicted} oldest commits for project ${projectPath} (cap=${maxCommits}, was=${count})`);
|
|
181354
|
-
}
|
|
181355
|
-
return evicted;
|
|
181356
|
-
}
|
|
181357
|
-
|
|
181358
|
-
// src/features/magic-context/git-commits/indexer.ts
|
|
181566
|
+
init_storage_git_commits();
|
|
181359
181567
|
var MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
181360
181568
|
var EMBED_BATCH_SIZE = 16;
|
|
181361
181569
|
var EMBED_MAX_PER_SWEEP = 500;
|
|
@@ -181593,6 +181801,7 @@ function searchGitCommitsSync(db, projectPath, query, options) {
|
|
|
181593
181801
|
|
|
181594
181802
|
// src/features/magic-context/git-commits/index.ts
|
|
181595
181803
|
init_storage_git_commit_embeddings();
|
|
181804
|
+
init_storage_git_commits();
|
|
181596
181805
|
init_sweep_coordinator();
|
|
181597
181806
|
|
|
181598
181807
|
// src/plugin/dream-timer.ts
|
|
@@ -183017,7 +183226,7 @@ function createMagicContextCommandHandler(deps) {
|
|
|
183017
183226
|
const isAugCommand = (command) => command === "ctx-aug";
|
|
183018
183227
|
const isDreamCommand = (command) => command === "ctx-dream";
|
|
183019
183228
|
const isSessionUpgradeCommand = (command) => command === "ctx-session-upgrade";
|
|
183020
|
-
const
|
|
183229
|
+
const isEmbedCommand = (command) => command === "ctx-embed";
|
|
183021
183230
|
return {
|
|
183022
183231
|
"command.execute.before": async (input, _output, _params) => {
|
|
183023
183232
|
const isStatus = isStatusCommand(input.command);
|
|
@@ -183026,8 +183235,8 @@ function createMagicContextCommandHandler(deps) {
|
|
|
183026
183235
|
const isAug = isAugCommand(input.command);
|
|
183027
183236
|
const isDream = isDreamCommand(input.command);
|
|
183028
183237
|
const isSessionUpgrade = isSessionUpgradeCommand(input.command);
|
|
183029
|
-
const
|
|
183030
|
-
if (!isStatus && !isFlush && !isRecomp && !isAug && !isDream && !isSessionUpgrade && !
|
|
183238
|
+
const isEmbed = isEmbedCommand(input.command);
|
|
183239
|
+
if (!isStatus && !isFlush && !isRecomp && !isAug && !isDream && !isSessionUpgrade && !isEmbed) {
|
|
183031
183240
|
return;
|
|
183032
183241
|
}
|
|
183033
183242
|
const sessionId = input.sessionID;
|
|
@@ -183040,15 +183249,50 @@ function createMagicContextCommandHandler(deps) {
|
|
|
183040
183249
|
await executeDreaming(deps, sessionId);
|
|
183041
183250
|
return;
|
|
183042
183251
|
}
|
|
183043
|
-
if (
|
|
183044
|
-
const
|
|
183045
|
-
|
|
183046
|
-
|
|
183252
|
+
if (isEmbed) {
|
|
183253
|
+
const sub = input.arguments.trim().toLowerCase();
|
|
183254
|
+
if (sub === "pause") {
|
|
183255
|
+
const summary = deps.pauseEmbedDrain ? deps.pauseEmbedDrain(sessionId) : "Embedding pause is unavailable.";
|
|
183256
|
+
if (isTuiConnected(sessionId)) {
|
|
183257
|
+
pushNotification("action", { action: "show-result-dialog", title: "Embed", message: summary }, sessionId);
|
|
183258
|
+
} else {
|
|
183259
|
+
await deps.sendNotification(sessionId, summary, {});
|
|
183260
|
+
}
|
|
183261
|
+
throwSentinel(input.command);
|
|
183262
|
+
}
|
|
183263
|
+
if (sub === "start") {
|
|
183264
|
+
const summary = deps.executeEmbedHistory ? await deps.executeEmbedHistory(sessionId) : "Semantic embedding is not configured for this project, so there is nothing to embed.";
|
|
183265
|
+
if (isTuiConnected(sessionId)) {
|
|
183266
|
+
pushNotification("action", { action: "show-result-dialog", title: "Embed", message: summary }, sessionId);
|
|
183267
|
+
} else {
|
|
183268
|
+
await deps.sendNotification(sessionId, summary, {});
|
|
183269
|
+
}
|
|
183270
|
+
throwSentinel(input.command);
|
|
183271
|
+
}
|
|
183272
|
+
if (sub !== "") {
|
|
183273
|
+
await deps.sendNotification(sessionId, "Usage: `/ctx-embed` (status), `/ctx-embed start`, or `/ctx-embed pause`.", {});
|
|
183274
|
+
throwSentinel(input.command);
|
|
183275
|
+
}
|
|
183276
|
+
if (isTuiConnected(sessionId)) {
|
|
183277
|
+
pushNotification("action", { action: "show-embed-dialog" }, sessionId);
|
|
183278
|
+
sessionLog(sessionId, "command ctx-embed: pushed show-embed-dialog to TUI");
|
|
183279
|
+
throwSentinel(input.command);
|
|
183280
|
+
}
|
|
183281
|
+
result = deps.getEmbedStatusText ? `## Embedding Status
|
|
183282
|
+
|
|
183283
|
+
${deps.getEmbedStatusText(sessionId)}` : `## Embedding Status
|
|
183284
|
+
|
|
183285
|
+
Embedding status is unavailable.`;
|
|
183047
183286
|
}
|
|
183048
183287
|
if (isFlush) {
|
|
183049
183288
|
result = executeFlush(deps.db, sessionId);
|
|
183050
183289
|
clearCachedM0M1(deps.db, sessionId);
|
|
183051
183290
|
deps.onFlush?.(sessionId);
|
|
183291
|
+
if (isTuiConnected(sessionId)) {
|
|
183292
|
+
pushNotification("action", { action: "show-flush-dialog", message: result }, sessionId);
|
|
183293
|
+
sessionLog(sessionId, "command ctx-flush: pushed show-flush-dialog to TUI");
|
|
183294
|
+
throwSentinel(input.command);
|
|
183295
|
+
}
|
|
183052
183296
|
}
|
|
183053
183297
|
if (isStatus) {
|
|
183054
183298
|
if (isTuiConnected(sessionId)) {
|
|
@@ -183175,6 +183419,34 @@ ${snap.error}`;
|
|
|
183175
183419
|
// src/hooks/magic-context/hook.ts
|
|
183176
183420
|
init_derive_budgets();
|
|
183177
183421
|
|
|
183422
|
+
// src/hooks/magic-context/embed-session-state.ts
|
|
183423
|
+
var embedPauseBySession = new Set;
|
|
183424
|
+
var embedRunStateBySession = new Map;
|
|
183425
|
+
var autoEmbedAttemptedBySession = new Set;
|
|
183426
|
+
function getEmbedDrainUiStatus(sessionId, progress) {
|
|
183427
|
+
if (embedPauseBySession.has(sessionId)) {
|
|
183428
|
+
return { status: "paused" };
|
|
183429
|
+
}
|
|
183430
|
+
if (progress?.kind === "embed" && progress.phase === "recomp") {
|
|
183431
|
+
return { status: "running" };
|
|
183432
|
+
}
|
|
183433
|
+
if (progress?.kind === "embed" && (progress.phase === "failed" || progress.phase === "skipped") && progress.message) {
|
|
183434
|
+
if (/provider/i.test(progress.message)) {
|
|
183435
|
+
return { status: "stopped", detail: progress.message };
|
|
183436
|
+
}
|
|
183437
|
+
}
|
|
183438
|
+
return { status: "idle" };
|
|
183439
|
+
}
|
|
183440
|
+
function clearEmbedSessionState(sessionId) {
|
|
183441
|
+
embedPauseBySession.delete(sessionId);
|
|
183442
|
+
const ctrl = embedRunStateBySession.get(sessionId);
|
|
183443
|
+
if (ctrl) {
|
|
183444
|
+
ctrl.abort();
|
|
183445
|
+
embedRunStateBySession.delete(sessionId);
|
|
183446
|
+
}
|
|
183447
|
+
autoEmbedAttemptedBySession.delete(sessionId);
|
|
183448
|
+
}
|
|
183449
|
+
|
|
183178
183450
|
// src/features/magic-context/message-index-async.ts
|
|
183179
183451
|
init_logger();
|
|
183180
183452
|
await init_message_index();
|
|
@@ -183535,6 +183807,13 @@ function computePressure(input) {
|
|
|
183535
183807
|
function approxThousands(tokens) {
|
|
183536
183808
|
return `${Math.round(tokens / 1000)}k`;
|
|
183537
183809
|
}
|
|
183810
|
+
function formatOldestReclaimableHint(hint) {
|
|
183811
|
+
if (!hint || hint.length === 0)
|
|
183812
|
+
return "";
|
|
183813
|
+
const rendered = hint.slice(0, 4).map((tag) => `§${tag.tagNumber}§ ${tag.toolName ?? "tool"}`).join(" · ");
|
|
183814
|
+
return rendered.length > 0 ? `
|
|
183815
|
+
oldest reclaimable: ${rendered}.` : "";
|
|
183816
|
+
}
|
|
183538
183817
|
var CHANNEL2_USABLE_FRACTION = 1 / 3;
|
|
183539
183818
|
var CHANNEL2_MIN_RECLAIMABLE = 1e4;
|
|
183540
183819
|
function shouldTriggerChannel2(input) {
|
|
@@ -183544,14 +183823,16 @@ function shouldTriggerChannel2(input) {
|
|
|
183544
183823
|
return true;
|
|
183545
183824
|
return input.reclaimableTokens >= input.usableTokens * CHANNEL2_USABLE_FRACTION;
|
|
183546
183825
|
}
|
|
183547
|
-
function buildChannel2Reminder(undroppedTokens) {
|
|
183826
|
+
function buildChannel2Reminder(undroppedTokens, hint) {
|
|
183548
183827
|
const amount = approxThousands(undroppedTokens);
|
|
183828
|
+
const hintText = formatOldestReclaimableHint(hint);
|
|
183549
183829
|
return `<system-reminder>
|
|
183550
|
-
` + `Routine context housekeeping is near: a large span of this session will be comparted soon, ` + `and ~${amount} tokens of tool output remain unreduced. Drop spent outputs with ctx_reduce ` + `first so the archived span is the part that matters
|
|
183830
|
+
` + `Routine context housekeeping is near: a large span of this session will be comparted soon, ` + `and ~${amount} tokens of tool output remain unreduced. Drop spent outputs with ctx_reduce ` + `first so the archived span is the part that matters.${hintText}
|
|
183551
183831
|
` + `</system-reminder>`;
|
|
183552
183832
|
}
|
|
183553
|
-
function buildChannel1Reminder(level, undroppedTokens) {
|
|
183833
|
+
function buildChannel1Reminder(level, undroppedTokens, hint) {
|
|
183554
183834
|
const amount = approxThousands(undroppedTokens);
|
|
183835
|
+
const hintText = formatOldestReclaimableHint(hint);
|
|
183555
183836
|
let body;
|
|
183556
183837
|
switch (level) {
|
|
183557
183838
|
case "gentle":
|
|
@@ -183567,7 +183848,7 @@ function buildChannel1Reminder(level, undroppedTokens) {
|
|
|
183567
183848
|
return `
|
|
183568
183849
|
|
|
183569
183850
|
<system-reminder>
|
|
183570
|
-
${body}
|
|
183851
|
+
${body}${hintText}
|
|
183571
183852
|
</system-reminder>`;
|
|
183572
183853
|
}
|
|
183573
183854
|
|
|
@@ -183621,10 +183902,10 @@ async function maybeDeliverChannel2(sessionId, deps) {
|
|
|
183621
183902
|
try {
|
|
183622
183903
|
const client3 = getLiveServerClient(serverUrl, deps.directory);
|
|
183623
183904
|
const promptContext = await resolvePromptContext(client3, sessionId);
|
|
183624
|
-
const reminder = buildChannel2Reminder(deps.reclaimableTokens);
|
|
183905
|
+
const reminder = buildChannel2Reminder(deps.reclaimableTokens, deps.oldestReclaimableToolTags);
|
|
183625
183906
|
const body = {
|
|
183626
183907
|
noReply: false,
|
|
183627
|
-
parts: [{ type: "text", text: reminder }]
|
|
183908
|
+
parts: [{ type: "text", text: reminder, synthetic: true }]
|
|
183628
183909
|
};
|
|
183629
183910
|
if (promptContext?.agent)
|
|
183630
183911
|
body.agent = promptContext.agent;
|
|
@@ -184082,7 +184363,8 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config2) {
|
|
|
184082
184363
|
const result = {
|
|
184083
184364
|
compressedToLite: 0,
|
|
184084
184365
|
compressedToFull: 0,
|
|
184085
|
-
compressedToUltra: 0
|
|
184366
|
+
compressedToUltra: 0,
|
|
184367
|
+
mutatedTextTags: 0
|
|
184086
184368
|
};
|
|
184087
184369
|
if (!config2.enabled)
|
|
184088
184370
|
return result;
|
|
@@ -184123,7 +184405,9 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config2) {
|
|
|
184123
184405
|
const target = targets.get(tag.tagNumber);
|
|
184124
184406
|
if (!target)
|
|
184125
184407
|
continue;
|
|
184126
|
-
target.setContent(compressed);
|
|
184408
|
+
const didMutate = target.setContent(compressed);
|
|
184409
|
+
if (didMutate)
|
|
184410
|
+
result.mutatedTextTags += 1;
|
|
184127
184411
|
updateCavemanDepth(db, sessionId, tag.tagNumber, targetDepth);
|
|
184128
184412
|
if (targetDepth === DEPTH_LITE)
|
|
184129
184413
|
result.compressedToLite += 1;
|
|
@@ -184711,28 +184995,6 @@ function stripInlineThinking(messages, messageTagNumbers, clearReasoningAge) {
|
|
|
184711
184995
|
}
|
|
184712
184996
|
return stripped;
|
|
184713
184997
|
}
|
|
184714
|
-
function truncateErroredTools(messages, watermark, messageTagNumbers) {
|
|
184715
|
-
let truncated = 0;
|
|
184716
|
-
for (let i = 0;i < messages.length; i++) {
|
|
184717
|
-
const maxTag = messageTagNumbers.get(messages[i]) ?? 0;
|
|
184718
|
-
if (maxTag > watermark) {
|
|
184719
|
-
continue;
|
|
184720
|
-
}
|
|
184721
|
-
for (const part of messages[i].parts) {
|
|
184722
|
-
if (!isRecord(part) || part.type !== "tool" || !isRecord(part.state)) {
|
|
184723
|
-
continue;
|
|
184724
|
-
}
|
|
184725
|
-
if (part.state.status !== "error") {
|
|
184726
|
-
continue;
|
|
184727
|
-
}
|
|
184728
|
-
if (typeof part.state.error === "string" && part.state.error.length > 100) {
|
|
184729
|
-
part.state.error = `${part.state.error.slice(0, 100)}... [truncated]`;
|
|
184730
|
-
truncated++;
|
|
184731
|
-
}
|
|
184732
|
-
}
|
|
184733
|
-
}
|
|
184734
|
-
return truncated;
|
|
184735
|
-
}
|
|
184736
184998
|
var REASONING_IGNORED_PART_TYPES = new Set([
|
|
184737
184999
|
"step-start",
|
|
184738
185000
|
"step-finish",
|
|
@@ -185150,78 +185412,11 @@ function appendReminderToUserMessage(message, reminder) {
|
|
|
185150
185412
|
|
|
185151
185413
|
// src/hooks/magic-context/apply-operations.ts
|
|
185152
185414
|
await init_storage();
|
|
185153
|
-
|
|
185154
|
-
// src/hooks/magic-context/system-injection-stripper.ts
|
|
185155
|
-
var SYSTEM_INJECTION_MARKERS = [
|
|
185156
|
-
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
185157
|
-
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
185158
|
-
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
185159
|
-
"[Category+Skill Reminder]",
|
|
185160
|
-
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
185161
|
-
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
185162
|
-
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
185163
|
-
"Unstable background agent appears idle",
|
|
185164
|
-
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
185165
|
-
];
|
|
185166
|
-
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
185167
|
-
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
185168
|
-
function stripSystemInjection(text) {
|
|
185169
|
-
let hasInjection = false;
|
|
185170
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
185171
|
-
if (text.includes(marker)) {
|
|
185172
|
-
hasInjection = true;
|
|
185173
|
-
break;
|
|
185174
|
-
}
|
|
185175
|
-
}
|
|
185176
|
-
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
185177
|
-
hasInjection = true;
|
|
185178
|
-
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
185179
|
-
if (!hasInjection)
|
|
185180
|
-
return null;
|
|
185181
|
-
let cleaned = text;
|
|
185182
|
-
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
185183
|
-
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
185184
|
-
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
185185
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
185186
|
-
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
185187
|
-
continue;
|
|
185188
|
-
const idx = cleaned.indexOf(marker);
|
|
185189
|
-
if (idx === -1)
|
|
185190
|
-
continue;
|
|
185191
|
-
const blockEnd = cleaned.indexOf(`
|
|
185192
|
-
|
|
185193
|
-
`, idx + marker.length);
|
|
185194
|
-
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
185195
|
-
}
|
|
185196
|
-
return cleaned.trim();
|
|
185197
|
-
}
|
|
185198
|
-
|
|
185199
|
-
// src/hooks/magic-context/apply-operations.ts
|
|
185200
|
-
init_tag_part_guards();
|
|
185201
|
-
var USER_DROP_PREVIEW_CHARS = 250;
|
|
185202
185415
|
var RECENT_TOOL_SKELETON_WINDOW = 20;
|
|
185203
|
-
function buildReplacementContent(tagId
|
|
185204
|
-
|
|
185205
|
-
|
|
185206
|
-
|
|
185207
|
-
}
|
|
185208
|
-
const currentContent = target.getContent?.() ?? "";
|
|
185209
|
-
const strippedInjection = stripSystemInjection(currentContent);
|
|
185210
|
-
if (strippedInjection !== null && stripTagPrefix(strippedInjection).trim().length === 0) {
|
|
185211
|
-
return `[dropped §${tagId}§]`;
|
|
185212
|
-
}
|
|
185213
|
-
const originalText = stripTagPrefix(currentContent);
|
|
185214
|
-
if (originalText.length <= USER_DROP_PREVIEW_CHARS) {
|
|
185215
|
-
return `[truncated §${tagId}§]
|
|
185216
|
-
${originalText}`;
|
|
185217
|
-
}
|
|
185218
|
-
const hardCut = originalText.slice(0, USER_DROP_PREVIEW_CHARS);
|
|
185219
|
-
const softCutIndex = hardCut.search(/\s\S*$/);
|
|
185220
|
-
const preview = softCutIndex > USER_DROP_PREVIEW_CHARS - 30 ? hardCut.slice(0, softCutIndex) : hardCut;
|
|
185221
|
-
return `[truncated §${tagId}§]
|
|
185222
|
-
${preview}…`;
|
|
185223
|
-
}
|
|
185224
|
-
function applyPendingOperations(sessionId, db, targets, protectedTags = 0, preloadedTags, preloadedPendingOps) {
|
|
185416
|
+
function buildReplacementContent(tagId) {
|
|
185417
|
+
return `[dropped §${tagId}§]`;
|
|
185418
|
+
}
|
|
185419
|
+
function applyPendingOperations(sessionId, db, targets, protectedTags = 0, preloadedTags, preloadedPendingOps, syntheticPendingOps = []) {
|
|
185225
185420
|
let didMutateMessage = false;
|
|
185226
185421
|
db.transaction(() => {
|
|
185227
185422
|
const tags = preloadedTags ?? getTagsBySession(db, sessionId);
|
|
@@ -185229,11 +185424,16 @@ function applyPendingOperations(sessionId, db, targets, protectedTags = 0, prelo
|
|
|
185229
185424
|
const tagTypeById = new Map(tags.map((tag) => [tag.tagNumber, tag.type]));
|
|
185230
185425
|
const protectedTagIds = protectedTags > 0 ? new Set(tags.filter((tag) => tag.status === "active").map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, protectedTags)) : new Set;
|
|
185231
185426
|
const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
|
|
185427
|
+
const opsToApply = [
|
|
185428
|
+
...pendingOps.map((op) => ({ op, synthetic: false })),
|
|
185429
|
+
...syntheticPendingOps.map((op) => ({ op, synthetic: true }))
|
|
185430
|
+
];
|
|
185232
185431
|
const skeletonWindow = new Set(tags.filter((tag) => tag.type === "tool").map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, RECENT_TOOL_SKELETON_WINDOW));
|
|
185233
|
-
for (const pendingOp of
|
|
185432
|
+
for (const { op: pendingOp, synthetic } of opsToApply) {
|
|
185234
185433
|
const tagStatus = tagStatusById.get(pendingOp.tagId);
|
|
185235
185434
|
if (tagStatus === "compacted" || tagStatus === "dropped") {
|
|
185236
|
-
|
|
185435
|
+
if (!synthetic)
|
|
185436
|
+
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
185237
185437
|
continue;
|
|
185238
185438
|
}
|
|
185239
185439
|
if (protectedTagIds.has(pendingOp.tagId)) {
|
|
@@ -185241,33 +185441,46 @@ function applyPendingOperations(sessionId, db, targets, protectedTags = 0, prelo
|
|
|
185241
185441
|
}
|
|
185242
185442
|
const target = targets.get(pendingOp.tagId);
|
|
185243
185443
|
const isToolTag = tagTypeById.get(pendingOp.tagId) === "tool";
|
|
185444
|
+
if (synthetic) {
|
|
185445
|
+
if (!isToolTag || target?.canDrop?.() !== true)
|
|
185446
|
+
continue;
|
|
185447
|
+
}
|
|
185448
|
+
let shouldPersistDrop = false;
|
|
185244
185449
|
if (isToolTag) {
|
|
185245
185450
|
if (skeletonWindow.has(pendingOp.tagId)) {
|
|
185246
185451
|
const truncResult = target?.truncate?.() ?? "absent";
|
|
185247
|
-
if (truncResult === "incomplete") {
|
|
185452
|
+
if (truncResult === "incomplete" || synthetic && truncResult !== "truncated") {
|
|
185248
185453
|
continue;
|
|
185249
185454
|
}
|
|
185250
185455
|
if (truncResult === "truncated") {
|
|
185251
185456
|
didMutateMessage = true;
|
|
185252
185457
|
}
|
|
185253
185458
|
updateTagDropMode(db, sessionId, pendingOp.tagId, "truncated");
|
|
185459
|
+
shouldPersistDrop = true;
|
|
185254
185460
|
} else {
|
|
185255
185461
|
const dropResult = target?.drop?.() ?? "absent";
|
|
185256
|
-
if (dropResult === "incomplete") {
|
|
185462
|
+
if (dropResult === "incomplete" || synthetic && dropResult !== "removed") {
|
|
185257
185463
|
continue;
|
|
185258
185464
|
}
|
|
185259
185465
|
if (dropResult === "removed") {
|
|
185260
185466
|
didMutateMessage = true;
|
|
185261
185467
|
}
|
|
185262
185468
|
updateTagDropMode(db, sessionId, pendingOp.tagId, "full");
|
|
185469
|
+
shouldPersistDrop = true;
|
|
185263
185470
|
}
|
|
185264
185471
|
} else if (target) {
|
|
185265
|
-
const changed = target.setContent(buildReplacementContent(pendingOp.tagId
|
|
185472
|
+
const changed = target.setContent(buildReplacementContent(pendingOp.tagId));
|
|
185266
185473
|
if (changed)
|
|
185267
185474
|
didMutateMessage = true;
|
|
185475
|
+
shouldPersistDrop = true;
|
|
185476
|
+
} else if (!synthetic) {
|
|
185477
|
+
shouldPersistDrop = true;
|
|
185268
185478
|
}
|
|
185479
|
+
if (!shouldPersistDrop)
|
|
185480
|
+
continue;
|
|
185269
185481
|
updateTagStatus(db, sessionId, pendingOp.tagId, "dropped");
|
|
185270
|
-
|
|
185482
|
+
if (!synthetic)
|
|
185483
|
+
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
185271
185484
|
}
|
|
185272
185485
|
})();
|
|
185273
185486
|
return didMutateMessage;
|
|
@@ -185291,7 +185504,7 @@ function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
|
|
|
185291
185504
|
}
|
|
185292
185505
|
}
|
|
185293
185506
|
} else if (target) {
|
|
185294
|
-
const changed = target.setContent(buildReplacementContent(tag.tagNumber
|
|
185507
|
+
const changed = target.setContent(buildReplacementContent(tag.tagNumber));
|
|
185295
185508
|
if (changed)
|
|
185296
185509
|
didMutateMessage = true;
|
|
185297
185510
|
}
|
|
@@ -185808,7 +186021,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
|
185808
186021
|
logTransformTiming(sessionId, "tag.saveSource", performance.now() - accSaveSource);
|
|
185809
186022
|
for (const [compositeKey, tagId] of toolTagByCallId) {
|
|
185810
186023
|
const thinkingParts = toolThinkingByCallId.get(compositeKey) ?? [];
|
|
185811
|
-
targets.set(tagId, createToolDropTarget(compositeKey, thinkingParts, toolCallIndex, batch));
|
|
186024
|
+
targets.set(tagId, createToolDropTarget(compositeKey, thinkingParts, toolCallIndex, batch, tagId));
|
|
185812
186025
|
}
|
|
185813
186026
|
const hasRecentReduceCall = lastReduceMessageIndex >= 0 && messages.length - lastReduceMessageIndex <= RECENT_REDUCE_LOOKBACK;
|
|
185814
186027
|
return {
|
|
@@ -186916,6 +187129,51 @@ function planEmergencyDrop(input) {
|
|
|
186916
187129
|
};
|
|
186917
187130
|
}
|
|
186918
187131
|
|
|
187132
|
+
// src/hooks/magic-context/system-injection-stripper.ts
|
|
187133
|
+
var SYSTEM_INJECTION_MARKERS = [
|
|
187134
|
+
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
187135
|
+
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
187136
|
+
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
187137
|
+
"[Category+Skill Reminder]",
|
|
187138
|
+
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
187139
|
+
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
187140
|
+
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
187141
|
+
"Unstable background agent appears idle",
|
|
187142
|
+
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
187143
|
+
];
|
|
187144
|
+
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
187145
|
+
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
187146
|
+
function stripSystemInjection(text) {
|
|
187147
|
+
let hasInjection = false;
|
|
187148
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
187149
|
+
if (text.includes(marker)) {
|
|
187150
|
+
hasInjection = true;
|
|
187151
|
+
break;
|
|
187152
|
+
}
|
|
187153
|
+
}
|
|
187154
|
+
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
187155
|
+
hasInjection = true;
|
|
187156
|
+
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
187157
|
+
if (!hasInjection)
|
|
187158
|
+
return null;
|
|
187159
|
+
let cleaned = text;
|
|
187160
|
+
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
187161
|
+
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
187162
|
+
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
187163
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
187164
|
+
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
187165
|
+
continue;
|
|
187166
|
+
const idx = cleaned.indexOf(marker);
|
|
187167
|
+
if (idx === -1)
|
|
187168
|
+
continue;
|
|
187169
|
+
const blockEnd = cleaned.indexOf(`
|
|
187170
|
+
|
|
187171
|
+
`, idx + marker.length);
|
|
187172
|
+
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
187173
|
+
}
|
|
187174
|
+
return cleaned.trim();
|
|
187175
|
+
}
|
|
187176
|
+
|
|
186919
187177
|
// src/hooks/magic-context/heuristic-cleanup.ts
|
|
186920
187178
|
init_tag_part_guards();
|
|
186921
187179
|
var DEDUP_SAFE_TOOLS = new Set([
|
|
@@ -187043,7 +187301,9 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
187043
187301
|
continue;
|
|
187044
187302
|
updateTagDropMode(db, sessionId, tag.tagNumber, "full");
|
|
187045
187303
|
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
187046
|
-
|
|
187304
|
+
if (result === "removed" || result === "truncated") {
|
|
187305
|
+
deduplicatedTools++;
|
|
187306
|
+
}
|
|
187047
187307
|
}
|
|
187048
187308
|
}
|
|
187049
187309
|
})();
|
|
@@ -187052,6 +187312,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
187052
187312
|
sessionLog(sessionId, `heuristic cleanup: dropped ${droppedTools} tool tags, deduplicated ${deduplicatedTools} tool calls, dropped ${droppedInjections} system injections`);
|
|
187053
187313
|
}
|
|
187054
187314
|
let compressedTextTags = 0;
|
|
187315
|
+
let mutatedTextTags = 0;
|
|
187055
187316
|
if (config2.caveman?.enabled) {
|
|
187056
187317
|
const cavemanResult = applyCavemanCleanup(sessionId, db, targets, tags, {
|
|
187057
187318
|
enabled: true,
|
|
@@ -187059,8 +187320,15 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
187059
187320
|
protectedTags: config2.protectedTags
|
|
187060
187321
|
});
|
|
187061
187322
|
compressedTextTags = cavemanResult.compressedToLite + cavemanResult.compressedToFull + cavemanResult.compressedToUltra;
|
|
187323
|
+
mutatedTextTags = cavemanResult.mutatedTextTags;
|
|
187062
187324
|
}
|
|
187063
|
-
return {
|
|
187325
|
+
return {
|
|
187326
|
+
droppedTools,
|
|
187327
|
+
deduplicatedTools,
|
|
187328
|
+
droppedInjections,
|
|
187329
|
+
compressedTextTags,
|
|
187330
|
+
mutatedTextTags
|
|
187331
|
+
};
|
|
187064
187332
|
}
|
|
187065
187333
|
function extractToolInfo(part) {
|
|
187066
187334
|
if (part.type === "tool" && typeof part.tool === "string" && DEDUP_SAFE_TOOLS.has(part.tool)) {
|
|
@@ -187234,6 +187502,42 @@ function isTodoItem(value) {
|
|
|
187234
187502
|
return typeof todo.content === "string" && typeof todo.status === "string" && (todo.priority === undefined || typeof todo.priority === "string");
|
|
187235
187503
|
}
|
|
187236
187504
|
|
|
187505
|
+
// src/hooks/magic-context/tool-reclaim.ts
|
|
187506
|
+
await init_storage();
|
|
187507
|
+
function buildSyntheticToolReclaimOps(input) {
|
|
187508
|
+
const watermark = Math.max(0, input.watermark);
|
|
187509
|
+
if (watermark <= 0)
|
|
187510
|
+
return [];
|
|
187511
|
+
const realPendingTagIds = new Set((input.pendingOps ?? []).map((op) => op.tagId));
|
|
187512
|
+
const tags = getActiveTagsBySession(input.db, input.sessionId);
|
|
187513
|
+
const synthetic = [];
|
|
187514
|
+
for (const tag of tags) {
|
|
187515
|
+
if (tag.type !== "tool")
|
|
187516
|
+
continue;
|
|
187517
|
+
if (tag.status !== "active")
|
|
187518
|
+
continue;
|
|
187519
|
+
if (tag.tagNumber > watermark)
|
|
187520
|
+
continue;
|
|
187521
|
+
if (realPendingTagIds.has(tag.tagNumber))
|
|
187522
|
+
continue;
|
|
187523
|
+
if (input.targets.get(tag.tagNumber)?.canDrop?.() !== true)
|
|
187524
|
+
continue;
|
|
187525
|
+
synthetic.push({
|
|
187526
|
+
id: 0,
|
|
187527
|
+
sessionId: input.sessionId,
|
|
187528
|
+
tagId: tag.tagNumber,
|
|
187529
|
+
operation: "drop",
|
|
187530
|
+
queuedAt: 0
|
|
187531
|
+
});
|
|
187532
|
+
}
|
|
187533
|
+
return synthetic;
|
|
187534
|
+
}
|
|
187535
|
+
function advanceToolReclaimWatermarkToCurrentMax(db, sessionId) {
|
|
187536
|
+
const maxTagNumber = getMaxTagNumberBySession(db, sessionId);
|
|
187537
|
+
advanceToolReclaimWatermark(db, sessionId, maxTagNumber);
|
|
187538
|
+
return maxTagNumber;
|
|
187539
|
+
}
|
|
187540
|
+
|
|
187237
187541
|
// src/hooks/magic-context/transform-postprocess-phase.ts
|
|
187238
187542
|
var DEGRADE_CACHE_WARNING_THRESHOLD = 10;
|
|
187239
187543
|
var degradedCacheCountBySession = new BoundedSessionMap(100);
|
|
@@ -187288,12 +187592,14 @@ async function runPostTransformPhase(args) {
|
|
|
187288
187592
|
let deferredMaterializedSuccessfully = false;
|
|
187289
187593
|
let heuristicsRanSuccessfully = false;
|
|
187290
187594
|
let pendingOpsRanSuccessfully = false;
|
|
187595
|
+
let pendingOpsDidMutate = false;
|
|
187596
|
+
let heuristicOrReasoningDidMutate = false;
|
|
187291
187597
|
try {
|
|
187292
187598
|
if (shouldApplyPendingOps) {
|
|
187293
187599
|
const applyReason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : `scheduler_execute (scheduler=${args.schedulerDecision})`;
|
|
187294
187600
|
sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOps.length}, context=${args.contextUsage.percentage.toFixed(1)}%`);
|
|
187295
187601
|
const tApply = performance.now();
|
|
187296
|
-
applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTags, undefined, pendingOps);
|
|
187602
|
+
pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTags, undefined, pendingOps);
|
|
187297
187603
|
logTransformTiming(args.sessionId, "applyPendingOperations", tApply);
|
|
187298
187604
|
}
|
|
187299
187605
|
if (shouldRunHeuristics) {
|
|
@@ -187311,7 +187617,8 @@ async function runPostTransformPhase(args) {
|
|
|
187311
187617
|
} : undefined,
|
|
187312
187618
|
caveman: cavemanConfig
|
|
187313
187619
|
}, heuristicTags);
|
|
187314
|
-
logTransformTiming(args.sessionId, "applyHeuristicCleanup", t5, `droppedTools=${cleanup.droppedTools} deduplicatedTools=${cleanup.deduplicatedTools} droppedInjections=${cleanup.droppedInjections} compressedTextTags=${cleanup.compressedTextTags}`);
|
|
187620
|
+
logTransformTiming(args.sessionId, "applyHeuristicCleanup", t5, `droppedTools=${cleanup.droppedTools} deduplicatedTools=${cleanup.deduplicatedTools} droppedInjections=${cleanup.droppedInjections} compressedTextTags=${cleanup.compressedTextTags} mutatedTextTags=${cleanup.mutatedTextTags}`);
|
|
187621
|
+
const heuristicMutationCount = cleanup.droppedTools + cleanup.deduplicatedTools + cleanup.droppedInjections + cleanup.mutatedTextTags;
|
|
187315
187622
|
const t7 = performance.now();
|
|
187316
187623
|
const clearedReasoning = clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge);
|
|
187317
187624
|
if (canUseEmptySentinels) {
|
|
@@ -187337,6 +187644,7 @@ async function runPostTransformPhase(args) {
|
|
|
187337
187644
|
}
|
|
187338
187645
|
}
|
|
187339
187646
|
logTransformTiming(args.sessionId, "clearOldReasoning", t7);
|
|
187647
|
+
heuristicOrReasoningDidMutate = heuristicMutationCount + clearedReasoning + strippedInline > 0;
|
|
187340
187648
|
if (pendingMaterializationAtPassStart) {
|
|
187341
187649
|
args.pendingMaterializationSessions.delete(args.sessionId);
|
|
187342
187650
|
}
|
|
@@ -187347,7 +187655,31 @@ async function runPostTransformPhase(args) {
|
|
|
187347
187655
|
if (args.schedulerDecision === "execute" && !materializationRequested) {
|
|
187348
187656
|
updateSessionMeta(args.db, args.sessionId, { lastResponseTime: Date.now() });
|
|
187349
187657
|
}
|
|
187658
|
+
const toolReclaimExecutePass = args.schedulerDecision === "execute";
|
|
187659
|
+
const alreadyMutatingThisPass = pendingOpsDidMutate || heuristicOrReasoningDidMutate;
|
|
187660
|
+
let autoReclaimTargetCount = 0;
|
|
187661
|
+
let autoReclaimDidMutate = false;
|
|
187662
|
+
if (toolReclaimExecutePass && alreadyMutatingThisPass && !emergencyDropEligible) {
|
|
187663
|
+
const syntheticPendingOps = buildSyntheticToolReclaimOps({
|
|
187664
|
+
db: args.db,
|
|
187665
|
+
sessionId: args.sessionId,
|
|
187666
|
+
targets: args.targets,
|
|
187667
|
+
watermark: args.sessionMeta.toolReclaimWatermark ?? 0,
|
|
187668
|
+
pendingOps
|
|
187669
|
+
});
|
|
187670
|
+
autoReclaimTargetCount = syntheticPendingOps.length;
|
|
187671
|
+
if (syntheticPendingOps.length > 0) {
|
|
187672
|
+
autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTags, undefined, [], syntheticPendingOps);
|
|
187673
|
+
}
|
|
187674
|
+
}
|
|
187350
187675
|
args.batch?.finalize();
|
|
187676
|
+
if (toolReclaimExecutePass) {
|
|
187677
|
+
const maxTagNumber = advanceToolReclaimWatermarkToCurrentMax(args.db, args.sessionId);
|
|
187678
|
+
args.sessionMeta.toolReclaimWatermark = Math.max(args.sessionMeta.toolReclaimWatermark ?? 0, maxTagNumber);
|
|
187679
|
+
}
|
|
187680
|
+
if (autoReclaimTargetCount > 0) {
|
|
187681
|
+
sessionLog(args.sessionId, `tool reclaim auto-drop: targets=${autoReclaimTargetCount} mutated=${autoReclaimDidMutate}`);
|
|
187682
|
+
}
|
|
187351
187683
|
logTransformTiming(args.sessionId, "batchFinalize:heuristics", performance.now());
|
|
187352
187684
|
if (args.sessionMeta.lastTransformError !== null) {
|
|
187353
187685
|
updateSessionMeta(args.db, args.sessionId, { lastTransformError: null });
|
|
@@ -187359,11 +187691,6 @@ async function runPostTransformPhase(args) {
|
|
|
187359
187691
|
deferredMaterializedSuccessfully = true;
|
|
187360
187692
|
heuristicsRanSuccessfully = true;
|
|
187361
187693
|
}
|
|
187362
|
-
if (args.watermark > 0) {
|
|
187363
|
-
const tWatermarkCleanup = performance.now();
|
|
187364
|
-
truncateErroredTools(args.messages, args.watermark, args.messageTagNumbers);
|
|
187365
|
-
logTransformTiming(args.sessionId, "watermarkCleanup", tWatermarkCleanup);
|
|
187366
|
-
}
|
|
187367
187694
|
if (shouldApplyPendingOps) {
|
|
187368
187695
|
pendingOpsRanSuccessfully = true;
|
|
187369
187696
|
}
|
|
@@ -188390,6 +188717,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
188390
188717
|
const executeThresholdTokens = Math.round((resolvedContextLimit ?? 0) * resolvedExecuteThresholdPct / 100);
|
|
188391
188718
|
const usableTokens = Math.max(0, executeThresholdTokens - contextUsage.inputTokens + liveTailTokens);
|
|
188392
188719
|
resetLastNudgeCycleIfTailShrank(db, sessionId, tailToolTokens);
|
|
188720
|
+
const oldestReclaimableToolTags = getOldestActiveUnprotectedToolTags(db, sessionId, deps.protectedTags);
|
|
188393
188721
|
deps.channel1StateBySession.set(sessionId, {
|
|
188394
188722
|
tailToolTokens,
|
|
188395
188723
|
historyBudgetTokens: historyBudgetTokens ?? 0,
|
|
@@ -188398,9 +188726,10 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
188398
188726
|
lastInputTokens: contextUsage.inputTokens,
|
|
188399
188727
|
turnToolTokens: 0,
|
|
188400
188728
|
usableTokens,
|
|
188401
|
-
reducedSinceRefresh: false
|
|
188729
|
+
reducedSinceRefresh: false,
|
|
188730
|
+
oldestReclaimableToolTags
|
|
188402
188731
|
});
|
|
188403
|
-
const channel2MetricsKnown =
|
|
188732
|
+
const channel2MetricsKnown = resolvedContextLimit !== undefined && resolvedContextLimit > 0 && resolvedExecuteThresholdPct > 0;
|
|
188404
188733
|
if (channel2MetricsKnown) {
|
|
188405
188734
|
const channel2ShouldTrigger = shouldTriggerChannel2({
|
|
188406
188735
|
reclaimableTokens: tailToolTokens,
|
|
@@ -188424,6 +188753,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
188424
188753
|
}
|
|
188425
188754
|
const elapsed = (performance.now() - startTime).toFixed(1);
|
|
188426
188755
|
sessionLog(sessionId, `transform completed in ${elapsed}ms (${messages.length} messages, ${targets.size} targets, watermark: ${watermark})`);
|
|
188756
|
+
deps.maybeAutoEmbedSession?.(sessionId);
|
|
188427
188757
|
};
|
|
188428
188758
|
}
|
|
188429
188759
|
function resolveHistoryBudgetTokens(historyBudgetPercentage, contextUsage, executeThresholdPercentage, modelKey, executeThresholdTokens, resolvedContextLimit) {
|
|
@@ -188469,18 +188799,14 @@ function evictExpiredUsageEntries(contextUsageMap) {
|
|
|
188469
188799
|
}
|
|
188470
188800
|
async function deliverChannel2IfPending(deps, sessionId) {
|
|
188471
188801
|
try {
|
|
188472
|
-
try {
|
|
188473
|
-
const meta3 = getOrCreateSessionMeta(deps.db, sessionId);
|
|
188474
|
-
if (meta3.isSubagent)
|
|
188475
|
-
return;
|
|
188476
|
-
} catch {}
|
|
188477
188802
|
const baseline = deps.channel1StateBySession?.get(sessionId);
|
|
188478
188803
|
await maybeDeliverChannel2(sessionId, {
|
|
188479
188804
|
db: deps.db,
|
|
188480
188805
|
serverUrl: deps.serverUrl,
|
|
188481
188806
|
directory: deps.directory ?? ".",
|
|
188482
188807
|
reclaimableTokens: baseline ? baseline.tailToolTokens + baseline.turnToolTokens : undefined,
|
|
188483
|
-
usableTokens: baseline?.usableTokens
|
|
188808
|
+
usableTokens: baseline?.usableTokens,
|
|
188809
|
+
oldestReclaimableToolTags: baseline?.oldestReclaimableToolTags
|
|
188484
188810
|
});
|
|
188485
188811
|
} catch (error51) {
|
|
188486
188812
|
sessionLog(sessionId, "channel2 delivery wrapper failed (ignored):", error51);
|
|
@@ -188786,6 +189112,46 @@ function createEventHandler2(deps) {
|
|
|
188786
189112
|
};
|
|
188787
189113
|
}
|
|
188788
189114
|
|
|
189115
|
+
// src/hooks/magic-context/format-embed-status.ts
|
|
189116
|
+
function formatEmbedStatusText(coverage, drain) {
|
|
189117
|
+
if (!coverage.enabled) {
|
|
189118
|
+
return "Embedding is off (no provider configured).";
|
|
189119
|
+
}
|
|
189120
|
+
const lines = [];
|
|
189121
|
+
lines.push(`Embedding — model: ${coverage.model} (${coverage.provider})`);
|
|
189122
|
+
lines.push(`This session: ${coverage.session.embedded} / ${coverage.session.total} compartments embedded`);
|
|
189123
|
+
lines.push(`Project memories: ${coverage.memories.embedded} / ${coverage.memories.total} embedded`);
|
|
189124
|
+
if (coverage.commits.gitEnabled) {
|
|
189125
|
+
lines.push(`Git commits: ${coverage.commits.embedded} / ${coverage.commits.total}`);
|
|
189126
|
+
} else {
|
|
189127
|
+
lines.push("Git commits: 0 / 0 (git indexing off)");
|
|
189128
|
+
}
|
|
189129
|
+
let drainLine = "Drain: idle";
|
|
189130
|
+
switch (drain.status) {
|
|
189131
|
+
case "running": {
|
|
189132
|
+
const e = drain.embedded ?? coverage.session.embedded;
|
|
189133
|
+
const t = drain.total ?? coverage.session.total;
|
|
189134
|
+
const failedSuffix = drain.failed && drain.failed > 0 ? ` (${drain.failed} failed)` : "";
|
|
189135
|
+
drainLine = `Drain: running ${e}/${t}${failedSuffix}`;
|
|
189136
|
+
break;
|
|
189137
|
+
}
|
|
189138
|
+
case "paused": {
|
|
189139
|
+
const e = drain.embedded ?? coverage.session.embedded;
|
|
189140
|
+
const t = drain.total ?? coverage.session.total;
|
|
189141
|
+
drainLine = `Drain: paused ${e}/${t}`;
|
|
189142
|
+
break;
|
|
189143
|
+
}
|
|
189144
|
+
case "stopped":
|
|
189145
|
+
drainLine = "Drain: stopped (provider down)";
|
|
189146
|
+
break;
|
|
189147
|
+
default:
|
|
189148
|
+
drainLine = "Drain: idle";
|
|
189149
|
+
}
|
|
189150
|
+
lines.push(drainLine);
|
|
189151
|
+
return lines.join(`
|
|
189152
|
+
`);
|
|
189153
|
+
}
|
|
189154
|
+
|
|
188789
189155
|
// src/hooks/magic-context/hook.ts
|
|
188790
189156
|
await __promiseAll([
|
|
188791
189157
|
init_inject_compartments(),
|
|
@@ -189003,7 +189369,7 @@ function maybeInjectChannel1Nudge(args, sessionId, tool, output) {
|
|
|
189003
189369
|
setLastNudgeLevel(args.db, sessionId, decision.nextLastNudgeLevel);
|
|
189004
189370
|
if (!decision.fire)
|
|
189005
189371
|
return;
|
|
189006
|
-
out.output += buildChannel1Reminder(decision.level, decision.undroppedTokens);
|
|
189372
|
+
out.output += buildChannel1Reminder(decision.level, decision.undroppedTokens, state.oldestReclaimableToolTags);
|
|
189007
189373
|
sessionLog(sessionId, `channel1 nudge fired: level=${decision.level} undropped~${Math.round(decision.undroppedTokens / 1000)}k tool=${tool}`);
|
|
189008
189374
|
}
|
|
189009
189375
|
function createToolExecuteAfterHook(args) {
|
|
@@ -189075,9 +189441,7 @@ Context is managed for you entirely automatically — there's nothing to prune a
|
|
|
189075
189441
|
var CTX_NOTE_GUIDANCE = `Use \`ctx_note\` ONLY for genuinely future concerns — something to revisit much later, not work coming up in the next few turns (that's already in your active context) and not active multi-step work (use todos for that). Magic Context preserves your full context across both compaction and restarts, so an upcoming restart or "let's come back to this later" is never a reason to take a note — nothing is lost either way. Notes you do take survive compression and resurface at natural work boundaries (after commits, historian runs, todo completion).`;
|
|
189076
189442
|
var TOOL_HISTORY_GUIDANCE = `Compressed history intentionally omits tool calls and their outputs — summaries like "I edited file X" are historian records, not patterns to replicate. In the live conversation, older tool calls and their results are cleaned up to save context — you may see your own past messages referencing actions without the corresponding tool call or result visible. This is normal context management. ALWAYS use real tool calls; never simulate, fabricate, or inline tool outputs in your text. If there is no tool result message, the action did not happen. NEVER simulate, hallucinate or claim tool calls, command output, search results, file edits, or diffs in plain text as if they actually occurred.`;
|
|
189077
189443
|
var BASE_INTRO = (protectedTags) => `Messages and tool outputs are tagged with §N§ identifiers (e.g., §1§, §42§).
|
|
189078
|
-
Use \`ctx_reduce\` to
|
|
189079
|
-
- \`drop\`: Remove entirely (best for tool outputs you already acted on).
|
|
189080
|
-
Syntax: "3-5", "1,2,9", or "1-5,8,12-15". Last ${protectedTags} tags are protected.
|
|
189444
|
+
Use \`ctx_reduce\` to mark spent tagged content as discardable and reclaim space. Marking is NOT an immediate delete — it queues the content, which stays fully visible until space is actually needed (as soon as the next turn if you're already under pressure, much later if not), so mark a tool output as soon as you're done with it rather than hoarding the call for the end of the turn. The last ${protectedTags} tags are protected (marking one just queues it until it ages out). Syntax: "3-5", "1,2,9", or "1-5,8,12-15".
|
|
189081
189445
|
Do not announce or narrate \`ctx_reduce\` drops — just call the tool silently. Saying "I'll drop these outputs" wastes tokens the user does not care about.
|
|
189082
189446
|
${CTX_NOTE_GUIDANCE}
|
|
189083
189447
|
Use \`ctx_memory\` for durable project knowledge: write what future sessions must know, update/archive/merge the memories you see in \`<project-memory>\` when they drift. Memories persist across sessions and every new session starts with them.
|
|
@@ -189096,7 +189460,7 @@ Use \`ctx_expand\` to recover the raw conversation behind a \`<compartment>\` su
|
|
|
189096
189460
|
\`ctx_search\` returns ranked results from memories, git commits, and raw message history. Use message ordinals from results with \`ctx_expand\` to retrieve surrounding conversation context.
|
|
189097
189461
|
${TOOL_HISTORY_GUIDANCE}
|
|
189098
189462
|
NEVER drop large ranges blindly (e.g., "1-50"). Review each tag before deciding.
|
|
189099
|
-
|
|
189463
|
+
Keep your user's instructions and intent — never drop a user message for its directive, even an old one. But a large block of pasted content inside a user message (logs, data dumps, long code, attachments) is fair to mark discardable once you've extracted what you need — it stays searchable via \`ctx_search\`.
|
|
189100
189464
|
NEVER drop assistant text messages unless they are exceptionally large. Your conversation messages are lightweight; only large tool outputs are worth dropping.
|
|
189101
189465
|
Before your turn finishes, consider using \`ctx_reduce\` to drop large tool outputs you no longer need.`;
|
|
189102
189466
|
var BASE_INTRO_NO_REDUCE = () => `${CTX_NOTE_GUIDANCE}
|
|
@@ -189517,29 +189881,55 @@ function createMagicContextHook(deps) {
|
|
|
189517
189881
|
ensureProjectRegistered: ensureProjectRegisteredFromOpenCodeDirectory,
|
|
189518
189882
|
getNotificationParams: (sid) => getLiveNotificationParams(sid, liveModelBySession, variantBySession, agentBySession)
|
|
189519
189883
|
});
|
|
189520
|
-
const executeEmbedHistory = async (sessionId) => {
|
|
189884
|
+
const executeEmbedHistory = async (sessionId, options) => {
|
|
189521
189885
|
if (deps.config.memory?.enabled === false) {
|
|
189522
189886
|
return "Memory is disabled for this project, so there is no semantic embedding to backfill.";
|
|
189523
189887
|
}
|
|
189524
189888
|
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
189889
|
+
const active = embedRunStateBySession.get(sessionId);
|
|
189890
|
+
if (active && !active.signal.aborted && !options?.signal) {
|
|
189891
|
+
return "Embedding is already running for this session.";
|
|
189892
|
+
}
|
|
189525
189893
|
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
189526
189894
|
const sessionProjectIdentity = resolveProjectIdentity(directory);
|
|
189527
|
-
|
|
189528
|
-
const
|
|
189529
|
-
|
|
189530
|
-
|
|
189531
|
-
|
|
189532
|
-
|
|
189533
|
-
|
|
189534
|
-
|
|
189535
|
-
|
|
189536
|
-
|
|
189537
|
-
|
|
189538
|
-
|
|
189895
|
+
embedPauseBySession.delete(sessionId);
|
|
189896
|
+
const prior = embedRunStateBySession.get(sessionId);
|
|
189897
|
+
if (prior)
|
|
189898
|
+
prior.abort();
|
|
189899
|
+
const controller = new AbortController;
|
|
189900
|
+
embedRunStateBySession.set(sessionId, controller);
|
|
189901
|
+
const signal = options?.signal ?? controller.signal;
|
|
189902
|
+
if (!options?.silent) {
|
|
189903
|
+
setRecompStarting({ recompProgressBySession }, sessionId, "Embedding history…", "embed");
|
|
189904
|
+
}
|
|
189905
|
+
let runFailed = 0;
|
|
189906
|
+
let outcome;
|
|
189907
|
+
try {
|
|
189908
|
+
outcome = await embedSessionCompartmentChunks(db, sessionProjectIdentity, sessionId, {
|
|
189909
|
+
signal,
|
|
189910
|
+
onProgress: ({ embedded, total }) => {
|
|
189911
|
+
const cur = recompProgressBySession.get(sessionId);
|
|
189912
|
+
if (!cur || cur.phase !== "recomp")
|
|
189913
|
+
return;
|
|
189914
|
+
recompProgressBySession.set(sessionId, {
|
|
189915
|
+
...cur,
|
|
189916
|
+
processedMessages: embedded,
|
|
189917
|
+
totalMessages: total,
|
|
189918
|
+
updatedAt: Date.now()
|
|
189919
|
+
});
|
|
189920
|
+
}
|
|
189921
|
+
});
|
|
189922
|
+
} finally {
|
|
189923
|
+
if (embedRunStateBySession.get(sessionId) === controller) {
|
|
189924
|
+
embedRunStateBySession.delete(sessionId);
|
|
189539
189925
|
}
|
|
189540
|
-
}
|
|
189926
|
+
}
|
|
189927
|
+
if ("failed" in outcome)
|
|
189928
|
+
runFailed = outcome.failed;
|
|
189541
189929
|
const terminal = (phase, message) => {
|
|
189542
|
-
|
|
189930
|
+
if (!options?.silent) {
|
|
189931
|
+
setRecompTerminal({ recompProgressBySession }, sessionId, phase, message);
|
|
189932
|
+
}
|
|
189543
189933
|
return message;
|
|
189544
189934
|
};
|
|
189545
189935
|
switch (outcome.status) {
|
|
@@ -189548,15 +189938,78 @@ function createMagicContextHook(deps) {
|
|
|
189548
189938
|
case "disabled":
|
|
189549
189939
|
return terminal("skipped", "No embedding provider is configured, so there is nothing to embed.");
|
|
189550
189940
|
case "busy":
|
|
189551
|
-
return terminal("skipped",
|
|
189552
|
-
case "aborted":
|
|
189553
|
-
|
|
189941
|
+
return terminal("skipped", "Embedding is already running for this project. Try again shortly.");
|
|
189942
|
+
case "aborted": {
|
|
189943
|
+
const cov = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
189944
|
+
const msg = `Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`;
|
|
189945
|
+
return terminal("skipped", msg);
|
|
189946
|
+
}
|
|
189554
189947
|
case "stalled":
|
|
189555
|
-
return terminal("skipped", `Embedded ${outcome.embedded} compartments; ${outcome.remaining} could not be embedded (the provider returned no result). Run /ctx-embed
|
|
189948
|
+
return terminal("skipped", `Embedded ${outcome.embedded} compartments; ${outcome.remaining} could not be embedded (the provider returned no result). Run /ctx-embed start again to retry them.`);
|
|
189556
189949
|
default:
|
|
189557
|
-
return terminal("done", `Embedded ${outcome.embedded} compartment${outcome.embedded === 1 ? "" : "s"} of history for semantic search.`);
|
|
189950
|
+
return terminal("done", `Embedded ${outcome.embedded} compartment${outcome.embedded === 1 ? "" : "s"} of history for semantic search${runFailed > 0 ? ` (${runFailed} failed)` : ""}.`);
|
|
189558
189951
|
}
|
|
189559
189952
|
};
|
|
189953
|
+
const pauseEmbedDrain = (sessionId) => {
|
|
189954
|
+
embedPauseBySession.add(sessionId);
|
|
189955
|
+
const ctrl = embedRunStateBySession.get(sessionId);
|
|
189956
|
+
if (ctrl)
|
|
189957
|
+
ctrl.abort();
|
|
189958
|
+
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
189959
|
+
const sessionProjectIdentity = resolveProjectIdentity(directory);
|
|
189960
|
+
const cov = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
189961
|
+
return `Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`;
|
|
189962
|
+
};
|
|
189963
|
+
const getEmbedStatusText = (sessionId) => {
|
|
189964
|
+
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
189965
|
+
const sessionProjectIdentity = resolveProjectIdentity(directory);
|
|
189966
|
+
const coverage = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
189967
|
+
const progress = recompProgressBySession.get(sessionId);
|
|
189968
|
+
const drainUi = getEmbedDrainUiStatus(sessionId, progress);
|
|
189969
|
+
return formatEmbedStatusText(coverage, {
|
|
189970
|
+
status: drainUi.status,
|
|
189971
|
+
embedded: progress?.processedMessages,
|
|
189972
|
+
total: progress?.totalMessages
|
|
189973
|
+
});
|
|
189974
|
+
};
|
|
189975
|
+
const maybeAutoEmbedSession = (sessionId) => {
|
|
189976
|
+
if (autoEmbedAttemptedBySession.has(sessionId))
|
|
189977
|
+
return;
|
|
189978
|
+
if (embedPauseBySession.has(sessionId))
|
|
189979
|
+
return;
|
|
189980
|
+
if (deps.config.memory?.enabled === false)
|
|
189981
|
+
return;
|
|
189982
|
+
autoEmbedAttemptedBySession.add(sessionId);
|
|
189983
|
+
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
189984
|
+
(async () => {
|
|
189985
|
+
try {
|
|
189986
|
+
await new Promise((resolve7) => setTimeout(resolve7, 0));
|
|
189987
|
+
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
189988
|
+
const sessionProjectIdentity = resolveProjectIdentity(directory);
|
|
189989
|
+
const coverage = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
189990
|
+
if (!coverage.enabled)
|
|
189991
|
+
return;
|
|
189992
|
+
const remaining = coverage.session.total - coverage.session.embedded;
|
|
189993
|
+
if (remaining <= 0)
|
|
189994
|
+
return;
|
|
189995
|
+
const notifyParams = getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession);
|
|
189996
|
+
if (!isTuiConnected(sessionId)) {
|
|
189997
|
+
const startMsg = `Embedding ${remaining} compartment${remaining === 1 ? "" : "s"} of history in the background…`;
|
|
189998
|
+
await sendIgnoredMessage(deps.client, sessionId, startMsg, {
|
|
189999
|
+
...notifyParams
|
|
190000
|
+
});
|
|
190001
|
+
}
|
|
190002
|
+
const summary = await executeEmbedHistory(sessionId);
|
|
190003
|
+
if (!isTuiConnected(sessionId)) {
|
|
190004
|
+
await sendIgnoredMessage(deps.client, sessionId, summary, {
|
|
190005
|
+
...notifyParams
|
|
190006
|
+
});
|
|
190007
|
+
}
|
|
190008
|
+
} catch (error51) {
|
|
190009
|
+
log("[magic-context] auto-embed drain failed:", error51);
|
|
190010
|
+
}
|
|
190011
|
+
})();
|
|
190012
|
+
};
|
|
189560
190013
|
const sidekickRunnable = isSidekickRunnable(deps.config);
|
|
189561
190014
|
const sidekickConfig = sidekickRunnable ? deps.config.sidekick : undefined;
|
|
189562
190015
|
const transform2 = createTransform({
|
|
@@ -189618,7 +190071,8 @@ function createMagicContextHook(deps) {
|
|
|
189618
190071
|
cavemanTextCompression: ctxReduceEnabled === false && deps.config.caveman_text_compression?.enabled === true ? {
|
|
189619
190072
|
enabled: true,
|
|
189620
190073
|
minChars: deps.config.caveman_text_compression.min_chars ?? 500
|
|
189621
|
-
} : undefined
|
|
190074
|
+
} : undefined,
|
|
190075
|
+
maybeAutoEmbedSession
|
|
189622
190076
|
});
|
|
189623
190077
|
const eventHandler = createEventHandler2({
|
|
189624
190078
|
contextUsageMap,
|
|
@@ -189647,6 +190101,7 @@ function createMagicContextHook(deps) {
|
|
|
189647
190101
|
recompProgressBySession.delete(sessionId);
|
|
189648
190102
|
internalChildSessions.delete(sessionId);
|
|
189649
190103
|
channel1StateBySession.delete(sessionId);
|
|
190104
|
+
clearEmbedSessionState(sessionId);
|
|
189650
190105
|
}
|
|
189651
190106
|
});
|
|
189652
190107
|
const runDreamQueueInBackground = () => {
|
|
@@ -189712,6 +190167,8 @@ function createMagicContextHook(deps) {
|
|
|
189712
190167
|
executeRecomp: historianRunnable ? async (sessionId, options) => runManagedRecomp(buildManagedRecompCtx(sessionId), sessionId, options) : undefined,
|
|
189713
190168
|
runUpgrade: historianRunnable ? async (sessionId) => runManagedUpgrade(buildManagedRecompCtx(sessionId), sessionId) : undefined,
|
|
189714
190169
|
executeEmbedHistory,
|
|
190170
|
+
pauseEmbedDrain,
|
|
190171
|
+
getEmbedStatusText,
|
|
189715
190172
|
sendNotification: async (sessionId, text, params) => {
|
|
189716
190173
|
await sendIgnoredMessage(deps.client, sessionId, text, {
|
|
189717
190174
|
...getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession),
|
|
@@ -189923,6 +190380,7 @@ function truncateError(name2, code, message, maxLen = 240) {
|
|
|
189923
190380
|
|
|
189924
190381
|
// src/plugin/rpc-handlers.ts
|
|
189925
190382
|
init_project_identity();
|
|
190383
|
+
init_project_embedding_registry();
|
|
189926
190384
|
init_tool_definition_tokens();
|
|
189927
190385
|
await init_storage();
|
|
189928
190386
|
|
|
@@ -190643,6 +191101,26 @@ function buildStatusDetail(db, sessionId, directory, modelKey, config2, liveSess
|
|
|
190643
191101
|
}
|
|
190644
191102
|
return detail;
|
|
190645
191103
|
}
|
|
191104
|
+
function buildEmbedDetail(db, sessionId, dir, liveSessionState) {
|
|
191105
|
+
const projectIdentity = resolveProjectIdentity(dir);
|
|
191106
|
+
const coverage = getEmbeddingCoverageStatus(db, projectIdentity, sessionId);
|
|
191107
|
+
const progress = liveSessionState.recompProgressBySession.get(sessionId);
|
|
191108
|
+
const drainUi = getEmbedDrainUiStatus(sessionId, progress);
|
|
191109
|
+
const statusText = formatEmbedStatusText(coverage, {
|
|
191110
|
+
status: drainUi.status,
|
|
191111
|
+
embedded: progress?.processedMessages,
|
|
191112
|
+
total: progress?.totalMessages
|
|
191113
|
+
});
|
|
191114
|
+
return {
|
|
191115
|
+
enabled: coverage.enabled,
|
|
191116
|
+
model: coverage.model,
|
|
191117
|
+
provider: coverage.provider,
|
|
191118
|
+
session: coverage.session,
|
|
191119
|
+
memories: coverage.memories,
|
|
191120
|
+
commits: coverage.commits,
|
|
191121
|
+
statusText
|
|
191122
|
+
};
|
|
191123
|
+
}
|
|
190646
191124
|
function registerRpcHandlers(rpcServer, args) {
|
|
190647
191125
|
const { directory, config: config2, liveSessionState } = args;
|
|
190648
191126
|
const rawConfig = config2;
|
|
@@ -190665,6 +191143,19 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
190665
191143
|
return { error: "unavailable" };
|
|
190666
191144
|
return buildStatusDetail(db, sessionId, dir, modelKey, rawConfig, liveSessionState, injectionBudgetTokens);
|
|
190667
191145
|
});
|
|
191146
|
+
rpcServer.handle("embed-detail", async (params) => {
|
|
191147
|
+
const sessionId = String(params.sessionId ?? "");
|
|
191148
|
+
const dir = String(params.directory ?? directory);
|
|
191149
|
+
const db = getDb();
|
|
191150
|
+
if (!db || !sessionId)
|
|
191151
|
+
return { error: "unavailable" };
|
|
191152
|
+
try {
|
|
191153
|
+
return buildEmbedDetail(db, sessionId, dir, liveSessionState);
|
|
191154
|
+
} catch (err) {
|
|
191155
|
+
log("[rpc] embed-detail error:", err);
|
|
191156
|
+
return { error: "unavailable" };
|
|
191157
|
+
}
|
|
191158
|
+
});
|
|
190668
191159
|
rpcServer.handle("compartment-count", async (params) => {
|
|
190669
191160
|
const sessionId = String(params.sessionId ?? "");
|
|
190670
191161
|
const db = getDb();
|
|
@@ -190787,27 +191278,225 @@ Older parts of this session are summarized into <compartment> blocks inside <ses
|
|
|
190787
191278
|
|
|
190788
191279
|
ctx_expand(start=120, end=245) ← the compartment's own start/end attributes
|
|
190789
191280
|
|
|
190790
|
-
Returns the raw transcript as [N] U:/A: lines, capped at ~15K tokens; an oversized range returns the head and tells you where to continue. Also works with ordinals from ctx_search message results — expand a window around a hit (e.g. start=N-10, end=N+5). Ranges after the last compartment are your live tail — already visible in context, not expandable
|
|
191281
|
+
Returns the raw transcript as [N] U:/A: lines, capped at ~15K tokens; an oversized range returns the head and tells you where to continue. Also works with ordinals from ctx_search message results — expand a window around a hit (e.g. start=N-10, end=N+5). Ranges after the last compartment are your live tail — already visible in context, not expandable.
|
|
191282
|
+
|
|
191283
|
+
Two recovery modes for finer detail:
|
|
191284
|
+
- ctx_expand(start=120, end=245, verbose=true) — lists each message SEPARATELY with its ordinal [N] and a per-part preview (each tool call shown with its output size). Use this to find the exact message or tool call you want, then recover it in full by ordinal.
|
|
191285
|
+
- ctx_expand(message=138) — returns the FULL untruncated content of the message at that ordinal: every text part, and every tool call's complete input + output, read from stored history. This is the cheap way to get back a tool output you dropped with ctx_reduce — the original is still in storage even though the wire shows [dropped §N§]. If the message was deleted from history (session prune/revert), it says so.`;
|
|
190791
191286
|
var CTX_EXPAND_TOKEN_BUDGET = 15000;
|
|
190792
191287
|
|
|
191288
|
+
// src/tools/ctx-expand/render.ts
|
|
191289
|
+
init_read_session_formatting();
|
|
191290
|
+
await init_read_session_chunk();
|
|
191291
|
+
function isRecord3(value) {
|
|
191292
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
191293
|
+
}
|
|
191294
|
+
function roleLabel(role) {
|
|
191295
|
+
if (role === "assistant")
|
|
191296
|
+
return "A (assistant)";
|
|
191297
|
+
if (role === "user")
|
|
191298
|
+
return "U (user)";
|
|
191299
|
+
return role;
|
|
191300
|
+
}
|
|
191301
|
+
function truncate2(value, max) {
|
|
191302
|
+
const t = value.trim();
|
|
191303
|
+
return t.length <= max ? t : `${t.slice(0, max)}…`;
|
|
191304
|
+
}
|
|
191305
|
+
function keyArg(input) {
|
|
191306
|
+
if (!input)
|
|
191307
|
+
return "";
|
|
191308
|
+
for (const k of ["filePath", "path", "pattern", "query", "symbol", "module", "action"]) {
|
|
191309
|
+
const v = input[k];
|
|
191310
|
+
if (typeof v === "string" && v.length > 0)
|
|
191311
|
+
return truncate2(v, 60);
|
|
191312
|
+
}
|
|
191313
|
+
if (typeof input.description === "string")
|
|
191314
|
+
return truncate2(input.description, 60);
|
|
191315
|
+
return "";
|
|
191316
|
+
}
|
|
191317
|
+
function asToolPart(part) {
|
|
191318
|
+
const type = typeof part.type === "string" ? part.type : "";
|
|
191319
|
+
if (type === "tool") {
|
|
191320
|
+
const state = isRecord3(part.state) ? part.state : null;
|
|
191321
|
+
const output = state && typeof state.output === "string" ? state.output : state && state.output != null ? JSON.stringify(state.output) : null;
|
|
191322
|
+
const metadata = state && isRecord3(state.metadata) ? state.metadata : null;
|
|
191323
|
+
const title = state && typeof state.title === "string" && state.title || metadata && typeof metadata.title === "string" && metadata.title || null;
|
|
191324
|
+
return {
|
|
191325
|
+
name: typeof part.tool === "string" ? part.tool : "tool",
|
|
191326
|
+
callId: typeof part.callID === "string" ? part.callID : "",
|
|
191327
|
+
title,
|
|
191328
|
+
input: state && isRecord3(state.input) ? state.input : null,
|
|
191329
|
+
output
|
|
191330
|
+
};
|
|
191331
|
+
}
|
|
191332
|
+
if (type === "tool_use") {
|
|
191333
|
+
return {
|
|
191334
|
+
name: typeof part.name === "string" ? part.name : "tool",
|
|
191335
|
+
callId: typeof part.id === "string" ? part.id : "",
|
|
191336
|
+
title: null,
|
|
191337
|
+
input: isRecord3(part.input) ? part.input : null,
|
|
191338
|
+
output: null
|
|
191339
|
+
};
|
|
191340
|
+
}
|
|
191341
|
+
if (type === "tool_result") {
|
|
191342
|
+
const content = part.content;
|
|
191343
|
+
const output = typeof content === "string" ? content : content != null ? JSON.stringify(content) : null;
|
|
191344
|
+
return {
|
|
191345
|
+
name: "tool_result",
|
|
191346
|
+
callId: typeof part.tool_use_id === "string" ? part.tool_use_id : "",
|
|
191347
|
+
title: null,
|
|
191348
|
+
input: null,
|
|
191349
|
+
output
|
|
191350
|
+
};
|
|
191351
|
+
}
|
|
191352
|
+
return null;
|
|
191353
|
+
}
|
|
191354
|
+
function textOf(part) {
|
|
191355
|
+
if (part.type === "text" && typeof part.text === "string")
|
|
191356
|
+
return part.text;
|
|
191357
|
+
return null;
|
|
191358
|
+
}
|
|
191359
|
+
function reasoningOf(part) {
|
|
191360
|
+
if ((part.type === "reasoning" || part.type === "thinking") && typeof part.text === "string") {
|
|
191361
|
+
return part.text;
|
|
191362
|
+
}
|
|
191363
|
+
return null;
|
|
191364
|
+
}
|
|
191365
|
+
function renderPartPreview(part) {
|
|
191366
|
+
if (!isRecord3(part))
|
|
191367
|
+
return null;
|
|
191368
|
+
const text = textOf(part);
|
|
191369
|
+
if (text !== null) {
|
|
191370
|
+
const t = truncate2(text, 200);
|
|
191371
|
+
return t.length > 0 ? ` • ${t}` : null;
|
|
191372
|
+
}
|
|
191373
|
+
const tool = asToolPart(part);
|
|
191374
|
+
if (tool) {
|
|
191375
|
+
const arg = keyArg(tool.input);
|
|
191376
|
+
const head = arg ? `${tool.name}(${arg})` : tool.name;
|
|
191377
|
+
return tool.output !== null ? ` • tool ${head} → output ~${estimateTokens(tool.output)} tok` : ` • tool ${head}`;
|
|
191378
|
+
}
|
|
191379
|
+
const reasoning = reasoningOf(part);
|
|
191380
|
+
if (reasoning !== null)
|
|
191381
|
+
return ` • [reasoning] ${truncate2(reasoning, 120)}`;
|
|
191382
|
+
const type = typeof part.type === "string" ? part.type : "part";
|
|
191383
|
+
if (type === "file")
|
|
191384
|
+
return " • [file]";
|
|
191385
|
+
if (type === "step-start" || type === "step-finish")
|
|
191386
|
+
return null;
|
|
191387
|
+
return ` • [${type}]`;
|
|
191388
|
+
}
|
|
191389
|
+
function renderPartFull(part) {
|
|
191390
|
+
if (!isRecord3(part))
|
|
191391
|
+
return null;
|
|
191392
|
+
const text = textOf(part);
|
|
191393
|
+
if (text !== null) {
|
|
191394
|
+
return text.trim().length > 0 ? ` [text]
|
|
191395
|
+
${text}` : null;
|
|
191396
|
+
}
|
|
191397
|
+
const tool = asToolPart(part);
|
|
191398
|
+
if (tool) {
|
|
191399
|
+
const lines = [];
|
|
191400
|
+
const idSuffix = tool.callId ? ` #${tool.callId}` : "";
|
|
191401
|
+
lines.push(` [tool: ${tool.name}${idSuffix}]`);
|
|
191402
|
+
if (tool.title && tool.title.trim().length > 0) {
|
|
191403
|
+
lines.push(` description: ${tool.title.trim()}`);
|
|
191404
|
+
}
|
|
191405
|
+
if (tool.input)
|
|
191406
|
+
lines.push(` input: ${JSON.stringify(tool.input)}`);
|
|
191407
|
+
if (tool.output !== null)
|
|
191408
|
+
lines.push(` output:
|
|
191409
|
+
${tool.output}`);
|
|
191410
|
+
return lines.join(`
|
|
191411
|
+
`);
|
|
191412
|
+
}
|
|
191413
|
+
const type = typeof part.type === "string" ? part.type : "part";
|
|
191414
|
+
if (type === "file") {
|
|
191415
|
+
const name2 = typeof part.filename === "string" && part.filename || typeof part.url === "string" && part.url || "";
|
|
191416
|
+
return ` [file]${name2 ? ` ${name2}` : ""}`;
|
|
191417
|
+
}
|
|
191418
|
+
return null;
|
|
191419
|
+
}
|
|
191420
|
+
function renderMessageByOrdinal(sessionId, ordinal) {
|
|
191421
|
+
const msg = readRawSessionMessages(sessionId).find((m) => m.ordinal === ordinal);
|
|
191422
|
+
if (!msg) {
|
|
191423
|
+
return `No message at ordinal ${ordinal} in this session's stored history — it was deleted ` + `(session prune/revert) or the ordinal is wrong, so it can't be recovered. ` + `Re-run the tool if you still need the data.`;
|
|
191424
|
+
}
|
|
191425
|
+
const rendered = msg.parts.map(renderPartFull).filter((l) => l !== null);
|
|
191426
|
+
const lines = [`[${msg.ordinal}] ${roleLabel(msg.role)} — full recovery:`, ""];
|
|
191427
|
+
if (rendered.length === 0) {
|
|
191428
|
+
lines.push(" (no recoverable content — message had only structural/reasoning parts)");
|
|
191429
|
+
} else {
|
|
191430
|
+
lines.push(...rendered);
|
|
191431
|
+
}
|
|
191432
|
+
return lines.join(`
|
|
191433
|
+
`);
|
|
191434
|
+
}
|
|
191435
|
+
function renderVerboseRange(sessionId, start, end, tokenBudget) {
|
|
191436
|
+
const messages = readRawSessionMessages(sessionId).filter((m) => m.ordinal >= start && m.ordinal <= end);
|
|
191437
|
+
const out = [];
|
|
191438
|
+
let usedTokens = 0;
|
|
191439
|
+
let lastOrdinal = start - 1;
|
|
191440
|
+
let truncated = false;
|
|
191441
|
+
for (const msg of messages) {
|
|
191442
|
+
const header = `[${msg.ordinal}] ${roleLabel(msg.role)}`;
|
|
191443
|
+
const partLines = msg.parts.map(renderPartPreview).filter((l) => l !== null);
|
|
191444
|
+
const block = partLines.length > 0 ? `${header}
|
|
191445
|
+
${partLines.join(`
|
|
191446
|
+
`)}` : header;
|
|
191447
|
+
const blockTokens = estimateTokens(block);
|
|
191448
|
+
if (usedTokens + blockTokens > tokenBudget && out.length > 0) {
|
|
191449
|
+
truncated = true;
|
|
191450
|
+
break;
|
|
191451
|
+
}
|
|
191452
|
+
out.push(block);
|
|
191453
|
+
usedTokens += blockTokens;
|
|
191454
|
+
lastOrdinal = msg.ordinal;
|
|
191455
|
+
}
|
|
191456
|
+
return { text: out.join(`
|
|
191457
|
+
|
|
191458
|
+
`), lastOrdinal, truncated };
|
|
191459
|
+
}
|
|
191460
|
+
|
|
190793
191461
|
// src/tools/ctx-expand/tools.ts
|
|
190794
191462
|
function createCtxExpandTool(deps) {
|
|
190795
191463
|
return tool({
|
|
190796
191464
|
description: CTX_EXPAND_DESCRIPTION,
|
|
190797
191465
|
args: {
|
|
190798
|
-
start: tool.schema.number().describe(`First message ordinal to expand — a compartment's start="N" attribute, or an ordinal from a ctx_search message hit`),
|
|
190799
|
-
end: tool.schema.number().describe(`Last message ordinal to expand (inclusive) — a compartment's end="M" attribute`)
|
|
191466
|
+
start: tool.schema.number().optional().describe(`First message ordinal to expand — a compartment's start="N" attribute, or an ordinal from a ctx_search message hit`),
|
|
191467
|
+
end: tool.schema.number().optional().describe(`Last message ordinal to expand (inclusive) — a compartment's end="M" attribute`),
|
|
191468
|
+
verbose: tool.schema.boolean().optional().describe("With start/end: list each message separately with its ordinal [N] and per-part preview (each tool call shown with its output size), so you can pick one to recover in full by ordinal."),
|
|
191469
|
+
message: tool.schema.number().optional().describe("Full untruncated recovery of ONE message by its ordinal (every text part + every tool call's complete input/output). Use an ordinal from a compartment, ctx_search hit, or verbose range. Recovers a tool output you dropped with ctx_reduce.")
|
|
190800
191470
|
},
|
|
190801
191471
|
async execute(args, toolContext) {
|
|
190802
191472
|
const sessionId = toolContext.sessionID;
|
|
191473
|
+
if (typeof args.message === "number" && args.message >= 1) {
|
|
191474
|
+
return renderMessageByOrdinal(sessionId, args.message);
|
|
191475
|
+
}
|
|
190803
191476
|
if (!args.start || !args.end || args.start < 1 || args.end < args.start) {
|
|
190804
|
-
return "Error: start and end
|
|
191477
|
+
return "Error: provide either message=<ordinal>, or start and end (positive integers, start <= end).";
|
|
190805
191478
|
}
|
|
190806
191479
|
const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
190807
191480
|
if (lastCompartmentEnd >= 0 && args.start > lastCompartmentEnd) {
|
|
190808
191481
|
return `Range ${args.start}-${args.end} is entirely within the live tail (after the last compacted message ${lastCompartmentEnd}); those messages are already visible in context.`;
|
|
190809
191482
|
}
|
|
190810
191483
|
const effectiveEnd = lastCompartmentEnd >= 0 ? Math.min(args.end, lastCompartmentEnd) : args.end;
|
|
191484
|
+
if (args.verbose === true) {
|
|
191485
|
+
const v = renderVerboseRange(sessionId, args.start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET);
|
|
191486
|
+
if (!v.text) {
|
|
191487
|
+
return `No messages found in range ${args.start}-${effectiveEnd}. The range may be outside this session's history.`;
|
|
191488
|
+
}
|
|
191489
|
+
const out = [
|
|
191490
|
+
`Messages ${args.start}-${v.lastOrdinal} (verbose). Recover any one in full with ctx_expand(message=<ordinal>):`,
|
|
191491
|
+
"",
|
|
191492
|
+
v.text
|
|
191493
|
+
];
|
|
191494
|
+
if (v.truncated) {
|
|
191495
|
+
out.push("", `Truncated at message ${v.lastOrdinal} (budget: ~${CTX_EXPAND_TOKEN_BUDGET} tokens). Call again with start=${v.lastOrdinal + 1} end=${effectiveEnd} verbose=true for more.`);
|
|
191496
|
+
}
|
|
191497
|
+
return out.join(`
|
|
191498
|
+
`);
|
|
191499
|
+
}
|
|
190811
191500
|
const chunk = readSessionChunk(sessionId, CTX_EXPAND_TOKEN_BUDGET, args.start, effectiveEnd + 1);
|
|
190812
191501
|
if (!chunk.text || chunk.messageCount === 0) {
|
|
190813
191502
|
return `No messages found in range ${args.start}-${args.end}. The range may be outside this session's history.`;
|
|
@@ -191501,15 +192190,16 @@ function createCtxNoteTools(deps) {
|
|
|
191501
192190
|
};
|
|
191502
192191
|
}
|
|
191503
192192
|
// src/tools/ctx-reduce/constants.ts
|
|
191504
|
-
var CTX_REDUCE_DESCRIPTION = `
|
|
191505
|
-
|
|
191506
|
-
|
|
191507
|
-
|
|
191508
|
-
-
|
|
191509
|
-
-
|
|
191510
|
-
|
|
191511
|
-
|
|
191512
|
-
|
|
192193
|
+
var CTX_REDUCE_DESCRIPTION = `Mark spent tagged content as discardable to reclaim context space. This is NOT an immediate delete. Use §N§ identifiers visible in the conversation. The \`drop\` param accepts ranges: "3-5", "1,2,9", "1-5,8".
|
|
192194
|
+
|
|
192195
|
+
How it works:
|
|
192196
|
+
- Marking QUEUES content for release. It stays fully visible to you until context space is actually needed — which may be as soon as the next turn if you are already under pressure, or many turns later if not. So mark spent outputs as soon as you finish with them; don't hoard the call for the end of the turn.
|
|
192197
|
+
- The newest tags are protected: marking one just queues it until it ages out of the recent window, so marking recent output is harmless.
|
|
192198
|
+
- When content is finally released it becomes a short placeholder, and re-running the tool is the only way to get it back. So mark only what you are genuinely DONE with — the test is "have I extracted what I need from this?", not "is it safe / do I have time before it drops?".
|
|
192199
|
+
|
|
192200
|
+
Mark discardable once processed: large outputs you've summarized, repeated or redundant dumps, data written to disk, status/log output that only confirmed an expected state.
|
|
192201
|
+
Keep: user messages, unresolved errors, raw evidence you haven't extracted yet, and outputs whose exact wording may matter later.
|
|
192202
|
+
Never blanket-mark large ranges (e.g. "1-50") — review what each tag holds first.`;
|
|
191513
192203
|
// src/tools/ctx-reduce/tools.ts
|
|
191514
192204
|
import { tool as tool4 } from "@opencode-ai/plugin";
|
|
191515
192205
|
|
|
@@ -192092,6 +192782,9 @@ class MagicContextRpcServer {
|
|
|
192092
192782
|
}
|
|
192093
192783
|
|
|
192094
192784
|
// src/index.ts
|
|
192785
|
+
var HISTORIAN_MAX_STEPS = 40;
|
|
192786
|
+
var SIDEKICK_MAX_STEPS = 40;
|
|
192787
|
+
var DREAMER_MAX_STEPS = 150;
|
|
192095
192788
|
var plugin = async (ctx) => {
|
|
192096
192789
|
const pluginConfig = loadPluginConfig(ctx.directory);
|
|
192097
192790
|
setSqlitePragmaConfig({
|
|
@@ -192308,11 +193001,13 @@ var plugin = async (ctx) => {
|
|
|
192308
193001
|
await hooks.magicContext?.["experimental.text.complete"]?.(input, output);
|
|
192309
193002
|
},
|
|
192310
193003
|
config: async (config2) => {
|
|
192311
|
-
const buildHiddenAgentConfig = (agentId, prompt, allowedTools, overrides) => {
|
|
193004
|
+
const buildHiddenAgentConfig = (agentId, prompt, allowedTools, maxSteps, overrides) => {
|
|
192312
193005
|
const { permission: overridePermission, ...restOverrides } = overrides ?? {};
|
|
192313
193006
|
const basePermission = buildAllowOnlyPermission(allowedTools);
|
|
192314
193007
|
return {
|
|
192315
193008
|
prompt,
|
|
193009
|
+
steps: maxSteps,
|
|
193010
|
+
maxSteps,
|
|
192316
193011
|
...getAgentFallbackModels(agentId) ? { fallback_models: getAgentFallbackModels(agentId) } : {},
|
|
192317
193012
|
...restOverrides,
|
|
192318
193013
|
permission: {
|
|
@@ -192353,10 +193048,10 @@ var plugin = async (ctx) => {
|
|
|
192353
193048
|
})() : undefined;
|
|
192354
193049
|
config2.agent = {
|
|
192355
193050
|
...config2.agent ?? {},
|
|
192356
|
-
[DREAMER_AGENT]: buildHiddenAgentConfig(DREAMER_AGENT, DREAMER_SYSTEM_PROMPT, DREAMER_ALLOWED_TOOLS, dreamerAgentOverrides),
|
|
192357
|
-
[HISTORIAN_AGENT]: buildHiddenAgentConfig(HISTORIAN_AGENT, COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_ALLOWED_TOOLS, historianAgentOverrides),
|
|
192358
|
-
[HISTORIAN_EDITOR_AGENT]: buildHiddenAgentConfig(HISTORIAN_EDITOR_AGENT, HISTORIAN_EDITOR_SYSTEM_PROMPT, HISTORIAN_ALLOWED_TOOLS, historianAgentOverrides),
|
|
192359
|
-
[SIDEKICK_AGENT]: buildHiddenAgentConfig(SIDEKICK_AGENT, SIDEKICK_SYSTEM_PROMPT, SIDEKICK_ALLOWED_TOOLS, sidekickAgentOverrides)
|
|
193051
|
+
[DREAMER_AGENT]: buildHiddenAgentConfig(DREAMER_AGENT, DREAMER_SYSTEM_PROMPT, DREAMER_ALLOWED_TOOLS, DREAMER_MAX_STEPS, dreamerAgentOverrides),
|
|
193052
|
+
[HISTORIAN_AGENT]: buildHiddenAgentConfig(HISTORIAN_AGENT, COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_ALLOWED_TOOLS, HISTORIAN_MAX_STEPS, historianAgentOverrides),
|
|
193053
|
+
[HISTORIAN_EDITOR_AGENT]: buildHiddenAgentConfig(HISTORIAN_EDITOR_AGENT, HISTORIAN_EDITOR_SYSTEM_PROMPT, HISTORIAN_ALLOWED_TOOLS, HISTORIAN_MAX_STEPS, historianAgentOverrides),
|
|
193054
|
+
[SIDEKICK_AGENT]: buildHiddenAgentConfig(SIDEKICK_AGENT, SIDEKICK_SYSTEM_PROMPT, SIDEKICK_ALLOWED_TOOLS, SIDEKICK_MAX_STEPS, sidekickAgentOverrides)
|
|
192360
193055
|
};
|
|
192361
193056
|
}
|
|
192362
193057
|
};
|