@wolfx/pi-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/dist/index.js +1008 -352
- package/dist/subagent-entry.js +559 -175
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -8275,6 +8275,14 @@ function buildNodeSqliteDatabaseClass(DatabaseSync) {
|
|
|
8275
8275
|
}
|
|
8276
8276
|
super(typeof filename === "string" ? filename : ":memory:", translated);
|
|
8277
8277
|
}
|
|
8278
|
+
prepare(sql) {
|
|
8279
|
+
const stmt = super.prepare(sql);
|
|
8280
|
+
for (const method of ["run", "get", "all"]) {
|
|
8281
|
+
const original = stmt[method].bind(stmt);
|
|
8282
|
+
stmt[method] = (...args) => args.length === 1 && Array.isArray(args[0]) ? original(...args[0]) : original(...args);
|
|
8283
|
+
}
|
|
8284
|
+
return stmt;
|
|
8285
|
+
}
|
|
8278
8286
|
transaction(fn) {
|
|
8279
8287
|
const self = this;
|
|
8280
8288
|
const wrapped = function(...args) {
|
|
@@ -141059,6 +141067,8 @@ function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
|
141059
141067
|
var encoder = new TextEncoder;
|
|
141060
141068
|
var TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
|
|
141061
141069
|
var MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
|
|
141070
|
+
var DANGLING_TAG_GLOBAL_REGEX = /\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?/g;
|
|
141071
|
+
var DANGLING_TAG_PREFIX_REGEX = /^(?:\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?\s*)+/;
|
|
141062
141072
|
var COMPLETE_TAG_PAIR_GLOBAL_REGEX = /\u00a7\d+\u00a7/g;
|
|
141063
141073
|
var MALFORMED_TAG_GLOBAL_REGEX = /\u00a7\d+">(?:\u00a7(?:\d+\u00a7)?)?/g;
|
|
141064
141074
|
var STRAY_SECTION_CHAR_REGEX = /\u00a7/g;
|
|
@@ -141071,6 +141081,9 @@ function stripCompleteTagPairsGlobally(value) {
|
|
|
141071
141081
|
function stripMalformedTagNotationGlobally(value) {
|
|
141072
141082
|
return value.replace(MALFORMED_TAG_GLOBAL_REGEX, "");
|
|
141073
141083
|
}
|
|
141084
|
+
function stripDanglingTagNotationGlobally(value) {
|
|
141085
|
+
return value.replace(DANGLING_TAG_GLOBAL_REGEX, "");
|
|
141086
|
+
}
|
|
141074
141087
|
function stripTagSectionCharacters(value) {
|
|
141075
141088
|
return value.replace(STRAY_SECTION_CHAR_REGEX, "");
|
|
141076
141089
|
}
|
|
@@ -141078,6 +141091,7 @@ function stripPersistedAssistantText(value) {
|
|
|
141078
141091
|
let text = stripWellFormedLeadingTagPrefix(value);
|
|
141079
141092
|
text = stripCompleteTagPairsGlobally(text);
|
|
141080
141093
|
text = stripMalformedTagNotationGlobally(text);
|
|
141094
|
+
text = stripDanglingTagNotationGlobally(text);
|
|
141081
141095
|
text = stripTagSectionCharacters(text);
|
|
141082
141096
|
return text.trim();
|
|
141083
141097
|
}
|
|
@@ -141090,6 +141104,7 @@ function stripTagPrefix(value) {
|
|
|
141090
141104
|
const prev = stripped;
|
|
141091
141105
|
stripped = stripped.replace(MALFORMED_TAG_PREFIX_REGEX, "");
|
|
141092
141106
|
stripped = stripped.replace(TAG_PREFIX_REGEX, "");
|
|
141107
|
+
stripped = stripped.replace(DANGLING_TAG_PREFIX_REGEX, "");
|
|
141093
141108
|
if (stripped === prev)
|
|
141094
141109
|
break;
|
|
141095
141110
|
}
|
|
@@ -141957,6 +141972,7 @@ var SESSION_META_SELECT_COLUMNS = [
|
|
|
141957
141972
|
"conversation_tokens",
|
|
141958
141973
|
"tool_call_tokens",
|
|
141959
141974
|
"cleared_reasoning_through_tag",
|
|
141975
|
+
"tool_reclaim_watermark",
|
|
141960
141976
|
"last_todo_state",
|
|
141961
141977
|
"cached_m0_bytes",
|
|
141962
141978
|
"cached_m1_bytes",
|
|
@@ -142005,6 +142021,7 @@ var META_COLUMNS = {
|
|
|
142005
142021
|
conversationTokens: "conversation_tokens",
|
|
142006
142022
|
toolCallTokens: "tool_call_tokens",
|
|
142007
142023
|
clearedReasoningThroughTag: "cleared_reasoning_through_tag",
|
|
142024
|
+
toolReclaimWatermark: "tool_reclaim_watermark",
|
|
142008
142025
|
lastTodoState: "last_todo_state",
|
|
142009
142026
|
cachedM0Bytes: "cached_m0_bytes",
|
|
142010
142027
|
cachedM1Bytes: "cached_m1_bytes",
|
|
@@ -142073,7 +142090,7 @@ function isSessionMetaRow(row) {
|
|
|
142073
142090
|
if (row === null || typeof row !== "object")
|
|
142074
142091
|
return false;
|
|
142075
142092
|
const r = row;
|
|
142076
|
-
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);
|
|
142093
|
+
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);
|
|
142077
142094
|
}
|
|
142078
142095
|
function getDefaultSessionMeta(sessionId) {
|
|
142079
142096
|
return {
|
|
@@ -142096,6 +142113,7 @@ function getDefaultSessionMeta(sessionId) {
|
|
|
142096
142113
|
conversationTokens: 0,
|
|
142097
142114
|
toolCallTokens: 0,
|
|
142098
142115
|
clearedReasoningThroughTag: 0,
|
|
142116
|
+
toolReclaimWatermark: 0,
|
|
142099
142117
|
lastTodoState: "",
|
|
142100
142118
|
cachedM0Bytes: null,
|
|
142101
142119
|
cachedM1Bytes: null,
|
|
@@ -142159,6 +142177,7 @@ function toSessionMeta(row) {
|
|
|
142159
142177
|
conversationTokens: numOrZero(row.conversation_tokens),
|
|
142160
142178
|
toolCallTokens: numOrZero(row.tool_call_tokens),
|
|
142161
142179
|
clearedReasoningThroughTag: numOrZero(row.cleared_reasoning_through_tag),
|
|
142180
|
+
toolReclaimWatermark: numOrZero(row.tool_reclaim_watermark),
|
|
142162
142181
|
lastTodoState: lastTodoStateRaw,
|
|
142163
142182
|
cachedM0Bytes: toBufferOrNull(row.cached_m0_bytes),
|
|
142164
142183
|
cachedM1Bytes: toBufferOrNull(row.cached_m1_bytes),
|
|
@@ -143598,6 +143617,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143598
143617
|
ensureColumn(db, "session_meta", "historian_last_failure_at", "INTEGER DEFAULT NULL");
|
|
143599
143618
|
ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
|
|
143600
143619
|
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
143620
|
+
ensureColumn(db, "session_meta", "tool_reclaim_watermark", "INTEGER DEFAULT 0");
|
|
143601
143621
|
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
143602
143622
|
ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
|
|
143603
143623
|
ensureColumn(db, "session_meta", "processed_image_stripped_ids", "TEXT DEFAULT ''");
|
|
@@ -146217,6 +146237,7 @@ var SESSION_META_FALLBACK_SELECTS = {
|
|
|
146217
146237
|
last_transform_error: "'' AS last_transform_error",
|
|
146218
146238
|
system_prompt_hash: "'' AS system_prompt_hash",
|
|
146219
146239
|
last_todo_state: "'' AS last_todo_state",
|
|
146240
|
+
tool_reclaim_watermark: "0 AS tool_reclaim_watermark",
|
|
146220
146241
|
cached_m0_bytes: "NULL AS cached_m0_bytes",
|
|
146221
146242
|
cached_m1_bytes: "NULL AS cached_m1_bytes",
|
|
146222
146243
|
cached_m0_project_memory_epoch: "NULL AS cached_m0_project_memory_epoch",
|
|
@@ -146294,6 +146315,14 @@ function updateSessionMeta(db, sessionId, updates) {
|
|
|
146294
146315
|
db.prepare(`UPDATE session_meta SET ${setClauses.join(", ")} WHERE session_id = ?`).run(...values, sessionId);
|
|
146295
146316
|
})();
|
|
146296
146317
|
}
|
|
146318
|
+
function advanceToolReclaimWatermark(db, sessionId, maxTagNumber) {
|
|
146319
|
+
if (maxTagNumber <= 0)
|
|
146320
|
+
return;
|
|
146321
|
+
db.transaction(() => {
|
|
146322
|
+
ensureSessionMetaRow(db, sessionId);
|
|
146323
|
+
db.prepare("UPDATE session_meta SET tool_reclaim_watermark = MAX(COALESCE(tool_reclaim_watermark, 0), ?) WHERE session_id = ?").run(maxTagNumber, sessionId);
|
|
146324
|
+
})();
|
|
146325
|
+
}
|
|
146297
146326
|
// ../plugin/src/features/magic-context/storage-notes.ts
|
|
146298
146327
|
var NOTE_TYPES = new Set(["session", "smart"]);
|
|
146299
146328
|
var NOTE_STATUSES = new Set(["active", "pending", "ready", "dismissed"]);
|
|
@@ -146691,6 +146720,26 @@ function getActiveTagTokenAggregate(db, sessionId, protectedTags = 0) {
|
|
|
146691
146720
|
nullCount: row?.null_count ?? 0
|
|
146692
146721
|
};
|
|
146693
146722
|
}
|
|
146723
|
+
function getOldestActiveUnprotectedToolTags(db, sessionId, protectedTags = 0, limit = 4) {
|
|
146724
|
+
if (limit <= 0)
|
|
146725
|
+
return [];
|
|
146726
|
+
const boundedLimit = Math.max(1, Math.min(10, Math.floor(limit)));
|
|
146727
|
+
const whereProtected = protectedTags > 0 ? `AND tag_number < (
|
|
146728
|
+
SELECT tag_number FROM tags
|
|
146729
|
+
WHERE session_id = ? AND status = 'active'
|
|
146730
|
+
ORDER BY tag_number DESC LIMIT 1 OFFSET ?
|
|
146731
|
+
)` : "";
|
|
146732
|
+
const params = protectedTags > 0 ? [sessionId, sessionId, protectedTags - 1, boundedLimit] : [sessionId, boundedLimit];
|
|
146733
|
+
const rows = db.prepare(`SELECT tag_number, tool_name
|
|
146734
|
+
FROM tags
|
|
146735
|
+
WHERE session_id = ? AND status = 'active' AND type = 'tool' ${whereProtected}
|
|
146736
|
+
ORDER BY tag_number ASC, id ASC
|
|
146737
|
+
LIMIT ?`).all(...params);
|
|
146738
|
+
return rows.filter((row) => typeof row.tag_number === "number").map((row) => ({
|
|
146739
|
+
tagNumber: row.tag_number,
|
|
146740
|
+
toolName: typeof row.tool_name === "string" ? row.tool_name : null
|
|
146741
|
+
}));
|
|
146742
|
+
}
|
|
146694
146743
|
function getTriggerTagTokenUpperBound(db, sessionId) {
|
|
146695
146744
|
const row = db.prepare(`SELECT
|
|
146696
146745
|
COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
|
|
@@ -147743,13 +147792,13 @@ async function maybeSendUpgradeReminder(deps, sessionId) {
|
|
|
147743
147792
|
init_data_path();
|
|
147744
147793
|
import * as fs2 from "node:fs";
|
|
147745
147794
|
import * as path6 from "node:path";
|
|
147746
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
147795
|
+
var ANNOUNCEMENT_VERSION = "0.25.0";
|
|
147747
147796
|
var ANNOUNCEMENT_FEATURES = [
|
|
147748
|
-
"
|
|
147749
|
-
"
|
|
147750
|
-
"
|
|
147751
|
-
"
|
|
147752
|
-
"
|
|
147797
|
+
"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.",
|
|
147798
|
+
"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.",
|
|
147799
|
+
"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.",
|
|
147800
|
+
"Pi: fixed /ctx-dream (was failing with 'Unknown named parameter') and local-embedding load failures on Windows/Desktop (#151, #128).",
|
|
147801
|
+
"Runaway background agents on weak/local models are now capped and force-stopped (#154, #152). Plus several prompt-cache busts removed."
|
|
147753
147802
|
];
|
|
147754
147803
|
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU";
|
|
147755
147804
|
var STATE_FILENAME = "last_announced_version";
|
|
@@ -148693,7 +148742,7 @@ function enqueueDream(db, projectIdentity, reason, force = false) {
|
|
|
148693
148742
|
return db.transaction(() => {
|
|
148694
148743
|
if (!hasActiveDreamLease(db)) {
|
|
148695
148744
|
const staleThresholdMs = force ? 2 * 60 * 1000 : 120 * 60 * 1000;
|
|
148696
|
-
db.prepare("DELETE FROM dream_queue WHERE project_path = ? AND started_at IS NOT NULL AND started_at < ?").run(
|
|
148745
|
+
db.prepare("DELETE FROM dream_queue WHERE project_path = ? AND started_at IS NOT NULL AND started_at < ?").run(projectIdentity, now - staleThresholdMs);
|
|
148697
148746
|
}
|
|
148698
148747
|
const existing = db.prepare("SELECT id FROM dream_queue WHERE project_path = ?").get(projectIdentity);
|
|
148699
148748
|
if (existing) {
|
|
@@ -148828,9 +148877,11 @@ async function promptWithTimeout(client, args, timeoutMs, signal) {
|
|
|
148828
148877
|
});
|
|
148829
148878
|
} catch (error) {
|
|
148830
148879
|
if (signal?.aborted) {
|
|
148880
|
+
await abortChildRun(client, args.path.id);
|
|
148831
148881
|
throw new Error("prompt aborted by external signal");
|
|
148832
148882
|
}
|
|
148833
148883
|
if (controller.signal.aborted) {
|
|
148884
|
+
await abortChildRun(client, args.path.id);
|
|
148834
148885
|
throw new Error(`prompt timed out after ${timeoutMs}ms`);
|
|
148835
148886
|
}
|
|
148836
148887
|
throw error;
|
|
@@ -148839,6 +148890,13 @@ async function promptWithTimeout(client, args, timeoutMs, signal) {
|
|
|
148839
148890
|
signal?.removeEventListener("abort", onExternalAbort);
|
|
148840
148891
|
}
|
|
148841
148892
|
}
|
|
148893
|
+
async function abortChildRun(client, sessionId) {
|
|
148894
|
+
try {
|
|
148895
|
+
await client.session.abort({ path: { id: sessionId } });
|
|
148896
|
+
} catch (error) {
|
|
148897
|
+
log(`[model-retry] child session abort failed for ${sessionId}: ${String(error)}`);
|
|
148898
|
+
}
|
|
148899
|
+
}
|
|
148842
148900
|
function isNonRetryable(error, externalSignal) {
|
|
148843
148901
|
if (externalSignal?.aborted)
|
|
148844
148902
|
return true;
|
|
@@ -149695,6 +149753,20 @@ function getDistinctStoredModelIds(db, projectPath) {
|
|
|
149695
149753
|
const rows = getDistinctStoredModelIdsStatement(db).all(projectPath);
|
|
149696
149754
|
return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
|
|
149697
149755
|
}
|
|
149756
|
+
function getMemoryEmbedCoverage(db, projectPath, modelId) {
|
|
149757
|
+
const row = db.prepare(`SELECT
|
|
149758
|
+
COUNT(*) AS total,
|
|
149759
|
+
SUM(CASE WHEN EXISTS (
|
|
149760
|
+
SELECT 1 FROM memory_embeddings e
|
|
149761
|
+
WHERE e.memory_id = m.id AND e.model_id = ?
|
|
149762
|
+
) THEN 1 ELSE 0 END) AS embedded
|
|
149763
|
+
FROM memories m
|
|
149764
|
+
WHERE m.project_path = ? AND m.status = 'active'`).get(modelId, projectPath);
|
|
149765
|
+
return {
|
|
149766
|
+
total: typeof row?.total === "number" ? row.total : 0,
|
|
149767
|
+
embedded: typeof row?.embedded === "number" ? row.embedded : 0
|
|
149768
|
+
};
|
|
149769
|
+
}
|
|
149698
149770
|
|
|
149699
149771
|
// ../plugin/src/features/magic-context/memory/embedding-cache.ts
|
|
149700
149772
|
var DEFAULT_EMBEDDING_CACHE_TTL_MS = 60000;
|
|
@@ -166736,6 +166808,28 @@ function countUnembeddedSessionCompartments(db, projectPath, sessionId, modelId)
|
|
|
166736
166808
|
)`).get(projectPath, sessionId, projectPath, modelId);
|
|
166737
166809
|
return typeof row?.n === "number" ? row.n : 0;
|
|
166738
166810
|
}
|
|
166811
|
+
function countSessionCompartmentEmbedCoverage(db, projectPath, sessionId, modelId) {
|
|
166812
|
+
const row = db.prepare(`SELECT
|
|
166813
|
+
COUNT(*) AS total,
|
|
166814
|
+
SUM(CASE WHEN EXISTS (
|
|
166815
|
+
SELECT 1 FROM compartment_chunk_embeddings e
|
|
166816
|
+
WHERE e.compartment_id = c.id
|
|
166817
|
+
AND e.project_path = ?
|
|
166818
|
+
AND e.model_id = ?
|
|
166819
|
+
) THEN 1 ELSE 0 END) AS embedded
|
|
166820
|
+
FROM compartments c
|
|
166821
|
+
JOIN session_projects sp
|
|
166822
|
+
ON sp.session_id = c.session_id
|
|
166823
|
+
AND sp.harness = c.harness
|
|
166824
|
+
AND sp.project_path = ?
|
|
166825
|
+
WHERE c.session_id = ?
|
|
166826
|
+
AND c.start_message IS NOT NULL
|
|
166827
|
+
AND c.end_message IS NOT NULL`).get(projectPath, modelId, projectPath, sessionId);
|
|
166828
|
+
return {
|
|
166829
|
+
total: typeof row?.total === "number" ? row.total : 0,
|
|
166830
|
+
embedded: typeof row?.embedded === "number" ? row.embedded : 0
|
|
166831
|
+
};
|
|
166832
|
+
}
|
|
166739
166833
|
|
|
166740
166834
|
// ../plugin/src/features/magic-context/memory/cosine-similarity.ts
|
|
166741
166835
|
function cosineSimilarity(a, b) {
|
|
@@ -166878,6 +166972,19 @@ async function withQuietConsole(fn) {
|
|
|
166878
166972
|
console.error = origError;
|
|
166879
166973
|
}
|
|
166880
166974
|
}
|
|
166975
|
+
var nativeRuntimeMissing = false;
|
|
166976
|
+
function isNativeRuntimeMissingError(error51) {
|
|
166977
|
+
const message = error51 instanceof Error ? error51.message : String(error51 ?? "");
|
|
166978
|
+
const lower = message.toLowerCase();
|
|
166979
|
+
const code = error51?.code;
|
|
166980
|
+
const name2 = error51?.name;
|
|
166981
|
+
if (code === "ERR_DLOPEN_FAILED" && lower.includes("onnxruntime")) {
|
|
166982
|
+
return true;
|
|
166983
|
+
}
|
|
166984
|
+
if (!lower.includes("onnxruntime-node"))
|
|
166985
|
+
return false;
|
|
166986
|
+
return code === "ERR_MODULE_NOT_FOUND" || name2 === "ResolveMessage" || lower.includes("cannot find package") || lower.includes("cannot find module") || lower.includes("err_module_not_found");
|
|
166987
|
+
}
|
|
166881
166988
|
function isTransientLoadError(error51) {
|
|
166882
166989
|
const message = error51 instanceof Error ? error51.message : String(error51 ?? "");
|
|
166883
166990
|
if (!message)
|
|
@@ -166942,6 +167049,9 @@ class LocalEmbeddingProvider {
|
|
|
166942
167049
|
if (this.pipeline) {
|
|
166943
167050
|
return true;
|
|
166944
167051
|
}
|
|
167052
|
+
if (nativeRuntimeMissing) {
|
|
167053
|
+
return false;
|
|
167054
|
+
}
|
|
166945
167055
|
if (this.initPromise) {
|
|
166946
167056
|
await this.initPromise;
|
|
166947
167057
|
return this.pipeline !== null;
|
|
@@ -167008,7 +167118,12 @@ class LocalEmbeddingProvider {
|
|
|
167008
167118
|
await releaseLock();
|
|
167009
167119
|
}
|
|
167010
167120
|
} catch (error51) {
|
|
167011
|
-
|
|
167121
|
+
if (isNativeRuntimeMissingError(error51)) {
|
|
167122
|
+
nativeRuntimeMissing = true;
|
|
167123
|
+
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 @wolfx/magic-context@latest doctor --force`), or configure an `openai-compatible`/`ollama` embedding endpoint instead. Existing memories are unaffected.");
|
|
167124
|
+
} else {
|
|
167125
|
+
log("[magic-context] embedding model failed to load:", error51);
|
|
167126
|
+
}
|
|
167012
167127
|
this.pipeline = null;
|
|
167013
167128
|
} finally {
|
|
167014
167129
|
this.initPromise = null;
|
|
@@ -167522,6 +167637,118 @@ function getDistinctCommitEmbeddingModelIds(db, projectPath) {
|
|
|
167522
167637
|
return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
|
|
167523
167638
|
}
|
|
167524
167639
|
|
|
167640
|
+
// ../plugin/src/features/magic-context/git-commits/storage-git-commits.ts
|
|
167641
|
+
init_logger();
|
|
167642
|
+
var insertStatements = new WeakMap;
|
|
167643
|
+
var existingShasStatements = new WeakMap;
|
|
167644
|
+
var projectCountStatements = new WeakMap;
|
|
167645
|
+
var evictStatements = new WeakMap;
|
|
167646
|
+
var evictOverflowStatements = new WeakMap;
|
|
167647
|
+
var latestCommitTimeStatements = new WeakMap;
|
|
167648
|
+
function getInsertStatement(db) {
|
|
167649
|
+
let stmt = insertStatements.get(db);
|
|
167650
|
+
if (!stmt) {
|
|
167651
|
+
stmt = db.prepare(`INSERT INTO git_commits (sha, project_path, short_sha, message, author, committed_at, indexed_at)
|
|
167652
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
167653
|
+
ON CONFLICT(sha) DO UPDATE SET
|
|
167654
|
+
project_path = excluded.project_path,
|
|
167655
|
+
short_sha = excluded.short_sha,
|
|
167656
|
+
message = excluded.message,
|
|
167657
|
+
author = excluded.author,
|
|
167658
|
+
committed_at = excluded.committed_at,
|
|
167659
|
+
indexed_at = excluded.indexed_at
|
|
167660
|
+
WHERE git_commits.message != excluded.message`);
|
|
167661
|
+
insertStatements.set(db, stmt);
|
|
167662
|
+
}
|
|
167663
|
+
return stmt;
|
|
167664
|
+
}
|
|
167665
|
+
function getExistingShasStatement(db) {
|
|
167666
|
+
let stmt = existingShasStatements.get(db);
|
|
167667
|
+
if (!stmt) {
|
|
167668
|
+
stmt = db.prepare("SELECT sha FROM git_commits WHERE project_path = ?");
|
|
167669
|
+
existingShasStatements.set(db, stmt);
|
|
167670
|
+
}
|
|
167671
|
+
return stmt;
|
|
167672
|
+
}
|
|
167673
|
+
function getProjectCountStatement(db) {
|
|
167674
|
+
let stmt = projectCountStatements.get(db);
|
|
167675
|
+
if (!stmt) {
|
|
167676
|
+
stmt = db.prepare("SELECT COUNT(*) AS count FROM git_commits WHERE project_path = ?");
|
|
167677
|
+
projectCountStatements.set(db, stmt);
|
|
167678
|
+
}
|
|
167679
|
+
return stmt;
|
|
167680
|
+
}
|
|
167681
|
+
function getLatestCommitTimeStatement(db) {
|
|
167682
|
+
let stmt = latestCommitTimeStatements.get(db);
|
|
167683
|
+
if (!stmt) {
|
|
167684
|
+
stmt = db.prepare("SELECT MAX(committed_at) AS latest FROM git_commits WHERE project_path = ?");
|
|
167685
|
+
latestCommitTimeStatements.set(db, stmt);
|
|
167686
|
+
}
|
|
167687
|
+
return stmt;
|
|
167688
|
+
}
|
|
167689
|
+
function getEvictOverflowStatement(db) {
|
|
167690
|
+
let stmt = evictOverflowStatements.get(db);
|
|
167691
|
+
if (!stmt) {
|
|
167692
|
+
stmt = db.prepare(`DELETE FROM git_commits
|
|
167693
|
+
WHERE rowid IN (
|
|
167694
|
+
SELECT rowid FROM git_commits
|
|
167695
|
+
WHERE project_path = ?
|
|
167696
|
+
ORDER BY committed_at DESC, sha DESC
|
|
167697
|
+
LIMIT -1 OFFSET ?
|
|
167698
|
+
)`);
|
|
167699
|
+
evictOverflowStatements.set(db, stmt);
|
|
167700
|
+
}
|
|
167701
|
+
return stmt;
|
|
167702
|
+
}
|
|
167703
|
+
function upsertCommits(db, projectPath, commits) {
|
|
167704
|
+
if (commits.length === 0)
|
|
167705
|
+
return { inserted: 0, updated: 0 };
|
|
167706
|
+
const existing = new Set;
|
|
167707
|
+
for (const row of getExistingShasStatement(db).all(projectPath)) {
|
|
167708
|
+
existing.add(row.sha);
|
|
167709
|
+
}
|
|
167710
|
+
let inserted = 0;
|
|
167711
|
+
let updated = 0;
|
|
167712
|
+
const now = Date.now();
|
|
167713
|
+
const insertStmt = getInsertStatement(db);
|
|
167714
|
+
db.transaction(() => {
|
|
167715
|
+
for (const commit of commits) {
|
|
167716
|
+
const result = insertStmt.run(commit.sha, projectPath, commit.shortSha, commit.message, commit.author, commit.committedAtMs, now);
|
|
167717
|
+
if (result.changes > 0) {
|
|
167718
|
+
if (existing.has(commit.sha)) {
|
|
167719
|
+
updated++;
|
|
167720
|
+
} else {
|
|
167721
|
+
inserted++;
|
|
167722
|
+
existing.add(commit.sha);
|
|
167723
|
+
}
|
|
167724
|
+
}
|
|
167725
|
+
}
|
|
167726
|
+
})();
|
|
167727
|
+
return { inserted, updated };
|
|
167728
|
+
}
|
|
167729
|
+
function getCommitCount(db, projectPath) {
|
|
167730
|
+
const row = getProjectCountStatement(db).get(projectPath);
|
|
167731
|
+
return row?.count ?? 0;
|
|
167732
|
+
}
|
|
167733
|
+
function getLatestIndexedCommitTimeMs(db, projectPath) {
|
|
167734
|
+
const row = getLatestCommitTimeStatement(db).get(projectPath);
|
|
167735
|
+
return row?.latest ?? null;
|
|
167736
|
+
}
|
|
167737
|
+
function enforceProjectCap(db, projectPath, maxCommits) {
|
|
167738
|
+
if (maxCommits <= 0)
|
|
167739
|
+
return 0;
|
|
167740
|
+
const count = getCommitCount(db, projectPath);
|
|
167741
|
+
if (count <= maxCommits)
|
|
167742
|
+
return 0;
|
|
167743
|
+
getEvictOverflowStatement(db).run(projectPath, maxCommits);
|
|
167744
|
+
const after = getCommitCount(db, projectPath);
|
|
167745
|
+
const evicted = Math.max(0, count - after);
|
|
167746
|
+
if (evicted > 0) {
|
|
167747
|
+
log(`[git-commits] evicted ${evicted} oldest commits for project ${projectPath} (cap=${maxCommits}, was=${count})`);
|
|
167748
|
+
}
|
|
167749
|
+
return evicted;
|
|
167750
|
+
}
|
|
167751
|
+
|
|
167525
167752
|
// ../plugin/src/features/magic-context/git-commits/sweep-coordinator.ts
|
|
167526
167753
|
var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
|
|
167527
167754
|
var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
@@ -167716,8 +167943,12 @@ function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
|
|
|
167716
167943
|
var OFF_PROVIDER_IDENTITY = "embedding-provider:off";
|
|
167717
167944
|
var SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
|
|
167718
167945
|
var CHUNK_DRAIN_BATCH_SIZE = 8;
|
|
167719
|
-
var MAX_WINDOWS_PER_EMBED_CALL =
|
|
167946
|
+
var MAX_WINDOWS_PER_EMBED_CALL = 2;
|
|
167720
167947
|
var SESSION_EMBED_LEASE_RENEWAL_MS = 60 * 1000;
|
|
167948
|
+
var EMBED_SLICE_RETRY_ATTEMPTS = 3;
|
|
167949
|
+
var EMBED_SLICE_RETRY_BASE_MS = 250;
|
|
167950
|
+
var EMBED_SLOW_FAILURE_NO_RETRY_MS = 1e4;
|
|
167951
|
+
var MAX_CONSECUTIVE_FAILED_BATCHES = 3;
|
|
167721
167952
|
var projectRegistrations = new Map;
|
|
167722
167953
|
var loadUnembeddedMemoriesStatements = new WeakMap;
|
|
167723
167954
|
var globalRegistrationGeneration = 0;
|
|
@@ -167817,7 +168048,9 @@ function snapshotFor(registration) {
|
|
|
167817
168048
|
enabled,
|
|
167818
168049
|
gitCommitEnabled,
|
|
167819
168050
|
modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
|
|
167820
|
-
chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId
|
|
168051
|
+
chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId,
|
|
168052
|
+
model: registration.observationMode || !providerIsOn ? "off" : ("model" in registration.config) && registration.config.model.trim() ? registration.config.model.trim() : registration.modelId,
|
|
168053
|
+
provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "local"
|
|
167821
168054
|
};
|
|
167822
168055
|
}
|
|
167823
168056
|
function disposeProvider(provider) {
|
|
@@ -168028,8 +168261,9 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
|
|
|
168028
168261
|
}
|
|
168029
168262
|
async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates, signal) {
|
|
168030
168263
|
const noWork = [];
|
|
168264
|
+
const failed = [];
|
|
168031
168265
|
if (candidates.length === 0)
|
|
168032
|
-
return { embedded: 0, noWork };
|
|
168266
|
+
return { embedded: 0, noWork, failed };
|
|
168033
168267
|
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
|
|
168034
168268
|
const prepared = [];
|
|
168035
168269
|
for (const candidate of candidates) {
|
|
@@ -168046,7 +168280,7 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
|
|
|
168046
168280
|
prepared.push({ candidate, windows });
|
|
168047
168281
|
}
|
|
168048
168282
|
if (prepared.length === 0)
|
|
168049
|
-
return { embedded: 0, noWork };
|
|
168283
|
+
return { embedded: 0, noWork, failed };
|
|
168050
168284
|
let embedded = 0;
|
|
168051
168285
|
let i = 0;
|
|
168052
168286
|
while (i < prepared.length) {
|
|
@@ -168063,35 +168297,60 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
|
|
|
168063
168297
|
const texts = [];
|
|
168064
168298
|
for (const item of slice)
|
|
168065
168299
|
texts.push(...item.windows.map((w) => w.text));
|
|
168066
|
-
|
|
168067
|
-
|
|
168068
|
-
if (!result)
|
|
168069
|
-
continue;
|
|
168300
|
+
const persistedIds = new Set;
|
|
168301
|
+
for (let attempt = 0;attempt < EMBED_SLICE_RETRY_ATTEMPTS; attempt++) {
|
|
168070
168302
|
if (signal?.aborted)
|
|
168071
168303
|
break;
|
|
168072
|
-
let
|
|
168073
|
-
|
|
168074
|
-
|
|
168075
|
-
|
|
168076
|
-
|
|
168077
|
-
|
|
168304
|
+
let result = null;
|
|
168305
|
+
const attemptStart = Date.now();
|
|
168306
|
+
try {
|
|
168307
|
+
result = await embedBatchForProject(projectIdentity, texts, signal);
|
|
168308
|
+
} catch (error51) {
|
|
168309
|
+
log("[magic-context] failed to proactively embed compartment chunks:", error51);
|
|
168310
|
+
}
|
|
168311
|
+
if (signal?.aborted)
|
|
168312
|
+
break;
|
|
168313
|
+
if (result) {
|
|
168314
|
+
let offset = 0;
|
|
168315
|
+
for (const item of slice) {
|
|
168316
|
+
const vectors = result.vectors.slice(offset, offset + item.windows.length);
|
|
168317
|
+
offset += item.windows.length;
|
|
168318
|
+
if (persistedIds.has(item.candidate.id))
|
|
168319
|
+
continue;
|
|
168320
|
+
if (vectors.length !== item.windows.length || vectors.some((v) => !v)) {
|
|
168321
|
+
continue;
|
|
168322
|
+
}
|
|
168323
|
+
const rows = item.windows.map((window, index) => ({
|
|
168324
|
+
compartmentId: item.candidate.id,
|
|
168325
|
+
sessionId: item.candidate.sessionId,
|
|
168326
|
+
projectPath: projectIdentity,
|
|
168327
|
+
window,
|
|
168328
|
+
modelId,
|
|
168329
|
+
vector: vectors[index]
|
|
168330
|
+
}));
|
|
168331
|
+
replaceCompartmentChunkEmbeddings(db, rows);
|
|
168332
|
+
persistedIds.add(item.candidate.id);
|
|
168078
168333
|
}
|
|
168079
|
-
const rows = item.windows.map((window, index) => ({
|
|
168080
|
-
compartmentId: item.candidate.id,
|
|
168081
|
-
sessionId: item.candidate.sessionId,
|
|
168082
|
-
projectPath: projectIdentity,
|
|
168083
|
-
window,
|
|
168084
|
-
modelId,
|
|
168085
|
-
vector: vectors[index]
|
|
168086
|
-
}));
|
|
168087
|
-
replaceCompartmentChunkEmbeddings(db, rows);
|
|
168088
|
-
embedded += 1;
|
|
168089
168334
|
}
|
|
168090
|
-
|
|
168091
|
-
|
|
168335
|
+
if (persistedIds.size === slice.length)
|
|
168336
|
+
break;
|
|
168337
|
+
if (persistedIds.size > 0)
|
|
168338
|
+
break;
|
|
168339
|
+
if (Date.now() - attemptStart >= EMBED_SLOW_FAILURE_NO_RETRY_MS)
|
|
168340
|
+
break;
|
|
168341
|
+
if (attempt < EMBED_SLICE_RETRY_ATTEMPTS - 1) {
|
|
168342
|
+
await new Promise((resolve4) => setTimeout(resolve4, EMBED_SLICE_RETRY_BASE_MS * 2 ** attempt));
|
|
168343
|
+
}
|
|
168344
|
+
}
|
|
168345
|
+
embedded += persistedIds.size;
|
|
168346
|
+
if (!signal?.aborted) {
|
|
168347
|
+
for (const item of slice) {
|
|
168348
|
+
if (!persistedIds.has(item.candidate.id))
|
|
168349
|
+
failed.push(item.candidate.id);
|
|
168350
|
+
}
|
|
168092
168351
|
}
|
|
168093
168352
|
}
|
|
168094
|
-
return { embedded, noWork };
|
|
168353
|
+
return { embedded, noWork, failed };
|
|
168095
168354
|
}
|
|
168096
168355
|
async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, options) {
|
|
168097
168356
|
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
@@ -168114,9 +168373,11 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
168114
168373
|
renewal.unref?.();
|
|
168115
168374
|
const batchSize = Math.max(1, options?.batchSize ?? CHUNK_DRAIN_BATCH_SIZE);
|
|
168116
168375
|
const skipIds = [];
|
|
168376
|
+
const failedIds = [];
|
|
168117
168377
|
let embedded = 0;
|
|
168118
168378
|
let aborted2 = false;
|
|
168119
|
-
let
|
|
168379
|
+
let providerDown = false;
|
|
168380
|
+
let consecutiveFailedBatches = 0;
|
|
168120
168381
|
try {
|
|
168121
168382
|
options?.onProgress?.({ embedded, total });
|
|
168122
168383
|
for (;; ) {
|
|
@@ -168124,15 +168385,26 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
168124
168385
|
aborted2 = true;
|
|
168125
168386
|
break;
|
|
168126
168387
|
}
|
|
168127
|
-
const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, skipIds);
|
|
168388
|
+
const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, [...skipIds, ...failedIds]);
|
|
168128
168389
|
if (candidates.length === 0)
|
|
168129
168390
|
break;
|
|
168130
|
-
const {
|
|
168391
|
+
const {
|
|
168392
|
+
embedded: n,
|
|
168393
|
+
noWork,
|
|
168394
|
+
failed
|
|
168395
|
+
} = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, options?.signal);
|
|
168131
168396
|
for (const id of noWork)
|
|
168132
168397
|
skipIds.push(id);
|
|
168398
|
+
for (const id of failed)
|
|
168399
|
+
failedIds.push(id);
|
|
168133
168400
|
if (n === 0 && noWork.length === 0) {
|
|
168134
|
-
|
|
168135
|
-
|
|
168401
|
+
consecutiveFailedBatches += 1;
|
|
168402
|
+
if (consecutiveFailedBatches >= MAX_CONSECUTIVE_FAILED_BATCHES) {
|
|
168403
|
+
providerDown = true;
|
|
168404
|
+
break;
|
|
168405
|
+
}
|
|
168406
|
+
} else {
|
|
168407
|
+
consecutiveFailedBatches = 0;
|
|
168136
168408
|
}
|
|
168137
168409
|
embedded += n;
|
|
168138
168410
|
options?.onProgress?.({ embedded: Math.min(embedded, total), total });
|
|
@@ -168140,16 +168412,50 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
168140
168412
|
}
|
|
168141
168413
|
} finally {
|
|
168142
168414
|
clearInterval(renewal);
|
|
168143
|
-
|
|
168415
|
+
try {
|
|
168416
|
+
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
168417
|
+
} catch (error51) {
|
|
168418
|
+
log("[magic-context] embed drain: lease release failed (will TTL-expire):", error51);
|
|
168419
|
+
}
|
|
168144
168420
|
}
|
|
168145
168421
|
if (aborted2)
|
|
168146
|
-
return { status: "aborted", embedded, total };
|
|
168147
|
-
if (
|
|
168422
|
+
return { status: "aborted", embedded, total, failed: failedIds.length };
|
|
168423
|
+
if (providerDown || failedIds.length > 0) {
|
|
168148
168424
|
const remaining = Math.max(0, countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot.chunkModelId) - skipIds.length);
|
|
168149
|
-
if (remaining > 0)
|
|
168150
|
-
return { status: "stalled", embedded, total, remaining };
|
|
168425
|
+
if (remaining > 0) {
|
|
168426
|
+
return { status: "stalled", embedded, total, remaining, failed: failedIds.length };
|
|
168427
|
+
}
|
|
168151
168428
|
}
|
|
168152
|
-
return { status: "done", embedded, total };
|
|
168429
|
+
return { status: "done", embedded, total, failed: failedIds.length };
|
|
168430
|
+
}
|
|
168431
|
+
function getEmbeddingCoverageStatus(db, projectIdentity, sessionId) {
|
|
168432
|
+
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
168433
|
+
if (!snapshot?.enabled || snapshot.chunkModelId === "off") {
|
|
168434
|
+
return {
|
|
168435
|
+
enabled: false,
|
|
168436
|
+
model: snapshot?.model ?? "off",
|
|
168437
|
+
provider: snapshot?.provider ?? "off",
|
|
168438
|
+
session: { embedded: 0, total: 0 },
|
|
168439
|
+
memories: { embedded: 0, total: 0 },
|
|
168440
|
+
commits: { embedded: 0, total: 0, gitEnabled: false }
|
|
168441
|
+
};
|
|
168442
|
+
}
|
|
168443
|
+
const session = countSessionCompartmentEmbedCoverage(db, projectIdentity, sessionId, snapshot.chunkModelId);
|
|
168444
|
+
const memories = getMemoryEmbedCoverage(db, projectIdentity, snapshot.modelId);
|
|
168445
|
+
const gitEnabled = snapshot.gitCommitEnabled;
|
|
168446
|
+
const commits = gitEnabled ? {
|
|
168447
|
+
embedded: countEmbeddedCommits(db, projectIdentity),
|
|
168448
|
+
total: getCommitCount(db, projectIdentity),
|
|
168449
|
+
gitEnabled: true
|
|
168450
|
+
} : { embedded: 0, total: 0, gitEnabled: false };
|
|
168451
|
+
return {
|
|
168452
|
+
enabled: true,
|
|
168453
|
+
model: snapshot.model,
|
|
168454
|
+
provider: snapshot.provider,
|
|
168455
|
+
session,
|
|
168456
|
+
memories,
|
|
168457
|
+
commits
|
|
168458
|
+
};
|
|
168153
168459
|
}
|
|
168154
168460
|
|
|
168155
168461
|
// ../plugin/src/features/magic-context/memory/embedding.ts
|
|
@@ -168198,118 +168504,6 @@ async function embedText(text, signal) {
|
|
|
168198
168504
|
}
|
|
168199
168505
|
var SWEEP_MAX_WALL_CLOCK_MS2 = 10 * 60 * 1000;
|
|
168200
168506
|
|
|
168201
|
-
// ../plugin/src/features/magic-context/git-commits/storage-git-commits.ts
|
|
168202
|
-
init_logger();
|
|
168203
|
-
var insertStatements = new WeakMap;
|
|
168204
|
-
var existingShasStatements = new WeakMap;
|
|
168205
|
-
var projectCountStatements = new WeakMap;
|
|
168206
|
-
var evictStatements = new WeakMap;
|
|
168207
|
-
var evictOverflowStatements = new WeakMap;
|
|
168208
|
-
var latestCommitTimeStatements = new WeakMap;
|
|
168209
|
-
function getInsertStatement(db) {
|
|
168210
|
-
let stmt = insertStatements.get(db);
|
|
168211
|
-
if (!stmt) {
|
|
168212
|
-
stmt = db.prepare(`INSERT INTO git_commits (sha, project_path, short_sha, message, author, committed_at, indexed_at)
|
|
168213
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
168214
|
-
ON CONFLICT(sha) DO UPDATE SET
|
|
168215
|
-
project_path = excluded.project_path,
|
|
168216
|
-
short_sha = excluded.short_sha,
|
|
168217
|
-
message = excluded.message,
|
|
168218
|
-
author = excluded.author,
|
|
168219
|
-
committed_at = excluded.committed_at,
|
|
168220
|
-
indexed_at = excluded.indexed_at
|
|
168221
|
-
WHERE git_commits.message != excluded.message`);
|
|
168222
|
-
insertStatements.set(db, stmt);
|
|
168223
|
-
}
|
|
168224
|
-
return stmt;
|
|
168225
|
-
}
|
|
168226
|
-
function getExistingShasStatement(db) {
|
|
168227
|
-
let stmt = existingShasStatements.get(db);
|
|
168228
|
-
if (!stmt) {
|
|
168229
|
-
stmt = db.prepare("SELECT sha FROM git_commits WHERE project_path = ?");
|
|
168230
|
-
existingShasStatements.set(db, stmt);
|
|
168231
|
-
}
|
|
168232
|
-
return stmt;
|
|
168233
|
-
}
|
|
168234
|
-
function getProjectCountStatement(db) {
|
|
168235
|
-
let stmt = projectCountStatements.get(db);
|
|
168236
|
-
if (!stmt) {
|
|
168237
|
-
stmt = db.prepare("SELECT COUNT(*) AS count FROM git_commits WHERE project_path = ?");
|
|
168238
|
-
projectCountStatements.set(db, stmt);
|
|
168239
|
-
}
|
|
168240
|
-
return stmt;
|
|
168241
|
-
}
|
|
168242
|
-
function getLatestCommitTimeStatement(db) {
|
|
168243
|
-
let stmt = latestCommitTimeStatements.get(db);
|
|
168244
|
-
if (!stmt) {
|
|
168245
|
-
stmt = db.prepare("SELECT MAX(committed_at) AS latest FROM git_commits WHERE project_path = ?");
|
|
168246
|
-
latestCommitTimeStatements.set(db, stmt);
|
|
168247
|
-
}
|
|
168248
|
-
return stmt;
|
|
168249
|
-
}
|
|
168250
|
-
function getEvictOverflowStatement(db) {
|
|
168251
|
-
let stmt = evictOverflowStatements.get(db);
|
|
168252
|
-
if (!stmt) {
|
|
168253
|
-
stmt = db.prepare(`DELETE FROM git_commits
|
|
168254
|
-
WHERE rowid IN (
|
|
168255
|
-
SELECT rowid FROM git_commits
|
|
168256
|
-
WHERE project_path = ?
|
|
168257
|
-
ORDER BY committed_at DESC, sha DESC
|
|
168258
|
-
LIMIT -1 OFFSET ?
|
|
168259
|
-
)`);
|
|
168260
|
-
evictOverflowStatements.set(db, stmt);
|
|
168261
|
-
}
|
|
168262
|
-
return stmt;
|
|
168263
|
-
}
|
|
168264
|
-
function upsertCommits(db, projectPath, commits) {
|
|
168265
|
-
if (commits.length === 0)
|
|
168266
|
-
return { inserted: 0, updated: 0 };
|
|
168267
|
-
const existing = new Set;
|
|
168268
|
-
for (const row of getExistingShasStatement(db).all(projectPath)) {
|
|
168269
|
-
existing.add(row.sha);
|
|
168270
|
-
}
|
|
168271
|
-
let inserted = 0;
|
|
168272
|
-
let updated = 0;
|
|
168273
|
-
const now = Date.now();
|
|
168274
|
-
const insertStmt = getInsertStatement(db);
|
|
168275
|
-
db.transaction(() => {
|
|
168276
|
-
for (const commit of commits) {
|
|
168277
|
-
const result = insertStmt.run(commit.sha, projectPath, commit.shortSha, commit.message, commit.author, commit.committedAtMs, now);
|
|
168278
|
-
if (result.changes > 0) {
|
|
168279
|
-
if (existing.has(commit.sha)) {
|
|
168280
|
-
updated++;
|
|
168281
|
-
} else {
|
|
168282
|
-
inserted++;
|
|
168283
|
-
existing.add(commit.sha);
|
|
168284
|
-
}
|
|
168285
|
-
}
|
|
168286
|
-
}
|
|
168287
|
-
})();
|
|
168288
|
-
return { inserted, updated };
|
|
168289
|
-
}
|
|
168290
|
-
function getCommitCount(db, projectPath) {
|
|
168291
|
-
const row = getProjectCountStatement(db).get(projectPath);
|
|
168292
|
-
return row?.count ?? 0;
|
|
168293
|
-
}
|
|
168294
|
-
function getLatestIndexedCommitTimeMs(db, projectPath) {
|
|
168295
|
-
const row = getLatestCommitTimeStatement(db).get(projectPath);
|
|
168296
|
-
return row?.latest ?? null;
|
|
168297
|
-
}
|
|
168298
|
-
function enforceProjectCap(db, projectPath, maxCommits) {
|
|
168299
|
-
if (maxCommits <= 0)
|
|
168300
|
-
return 0;
|
|
168301
|
-
const count = getCommitCount(db, projectPath);
|
|
168302
|
-
if (count <= maxCommits)
|
|
168303
|
-
return 0;
|
|
168304
|
-
getEvictOverflowStatement(db).run(projectPath, maxCommits);
|
|
168305
|
-
const after = getCommitCount(db, projectPath);
|
|
168306
|
-
const evicted = Math.max(0, count - after);
|
|
168307
|
-
if (evicted > 0) {
|
|
168308
|
-
log(`[git-commits] evicted ${evicted} oldest commits for project ${projectPath} (cap=${maxCommits}, was=${count})`);
|
|
168309
|
-
}
|
|
168310
|
-
return evicted;
|
|
168311
|
-
}
|
|
168312
|
-
|
|
168313
168507
|
// ../plugin/src/features/magic-context/git-commits/indexer.ts
|
|
168314
168508
|
var MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
168315
168509
|
var EMBED_BATCH_SIZE = 16;
|
|
@@ -169843,87 +170037,229 @@ function registerCtxDreamCommand(pi, deps) {
|
|
|
169843
170037
|
});
|
|
169844
170038
|
}
|
|
169845
170039
|
|
|
169846
|
-
// src/
|
|
169847
|
-
|
|
169848
|
-
|
|
169849
|
-
|
|
169850
|
-
|
|
170040
|
+
// ../plugin/src/hooks/magic-context/embed-session-state.ts
|
|
170041
|
+
var embedPauseBySession = new Set;
|
|
170042
|
+
var embedRunStateBySession = new Map;
|
|
170043
|
+
var autoEmbedAttemptedBySession = new Set;
|
|
170044
|
+
|
|
170045
|
+
// ../plugin/src/hooks/magic-context/format-embed-status.ts
|
|
170046
|
+
function formatEmbedStatusText(coverage, drain) {
|
|
170047
|
+
if (!coverage.enabled) {
|
|
170048
|
+
return "Embedding is off (no provider configured).";
|
|
170049
|
+
}
|
|
170050
|
+
const lines = [];
|
|
170051
|
+
lines.push(`Embedding — model: ${coverage.model} (${coverage.provider})`);
|
|
170052
|
+
lines.push(`This session: ${coverage.session.embedded} / ${coverage.session.total} compartments embedded`);
|
|
170053
|
+
lines.push(`Project memories: ${coverage.memories.embedded} / ${coverage.memories.total} embedded`);
|
|
170054
|
+
if (coverage.commits.gitEnabled) {
|
|
170055
|
+
lines.push(`Git commits: ${coverage.commits.embedded} / ${coverage.commits.total}`);
|
|
170056
|
+
} else {
|
|
170057
|
+
lines.push("Git commits: 0 / 0 (git indexing off)");
|
|
170058
|
+
}
|
|
170059
|
+
let drainLine = "Drain: idle";
|
|
170060
|
+
switch (drain.status) {
|
|
170061
|
+
case "running": {
|
|
170062
|
+
const e = drain.embedded ?? coverage.session.embedded;
|
|
170063
|
+
const t = drain.total ?? coverage.session.total;
|
|
170064
|
+
const failedSuffix = drain.failed && drain.failed > 0 ? ` (${drain.failed} failed)` : "";
|
|
170065
|
+
drainLine = `Drain: running ${e}/${t}${failedSuffix}`;
|
|
170066
|
+
break;
|
|
170067
|
+
}
|
|
170068
|
+
case "paused": {
|
|
170069
|
+
const e = drain.embedded ?? coverage.session.embedded;
|
|
170070
|
+
const t = drain.total ?? coverage.session.total;
|
|
170071
|
+
drainLine = `Drain: paused ${e}/${t}`;
|
|
170072
|
+
break;
|
|
170073
|
+
}
|
|
170074
|
+
case "stopped":
|
|
170075
|
+
drainLine = "Drain: stopped (provider down)";
|
|
170076
|
+
break;
|
|
170077
|
+
default:
|
|
170078
|
+
drainLine = "Drain: idle";
|
|
170079
|
+
}
|
|
170080
|
+
lines.push(drainLine);
|
|
170081
|
+
return lines.join(`
|
|
170082
|
+
`);
|
|
170083
|
+
}
|
|
170084
|
+
|
|
170085
|
+
// src/commands/ctx-embed.ts
|
|
170086
|
+
function clearPiEmbedSessionState(sessionId) {
|
|
170087
|
+
embedPauseBySession.delete(sessionId);
|
|
170088
|
+
const ctrl = embedRunStateBySession.get(sessionId);
|
|
170089
|
+
if (ctrl) {
|
|
170090
|
+
ctrl.abort();
|
|
170091
|
+
embedRunStateBySession.delete(sessionId);
|
|
170092
|
+
}
|
|
170093
|
+
autoEmbedAttemptedBySession.delete(sessionId);
|
|
170094
|
+
}
|
|
170095
|
+
async function runEmbedDrain(db, projectIdentity, sessionId) {
|
|
170096
|
+
const activeCtrl = embedRunStateBySession.get(sessionId);
|
|
170097
|
+
if (activeCtrl && !activeCtrl.signal.aborted) {
|
|
170098
|
+
return {
|
|
170099
|
+
text: `## /ctx-embed
|
|
170100
|
+
|
|
170101
|
+
Embedding is already running for this session.`,
|
|
170102
|
+
level: "info"
|
|
170103
|
+
};
|
|
170104
|
+
}
|
|
170105
|
+
embedPauseBySession.delete(sessionId);
|
|
170106
|
+
const prior = embedRunStateBySession.get(sessionId);
|
|
170107
|
+
if (prior)
|
|
170108
|
+
prior.abort();
|
|
170109
|
+
const controller = new AbortController;
|
|
170110
|
+
embedRunStateBySession.set(sessionId, controller);
|
|
170111
|
+
let outcome;
|
|
170112
|
+
try {
|
|
170113
|
+
outcome = await embedSessionCompartmentChunks(db, projectIdentity, sessionId, {
|
|
170114
|
+
signal: controller.signal
|
|
170115
|
+
});
|
|
170116
|
+
} finally {
|
|
170117
|
+
if (embedRunStateBySession.get(sessionId) === controller) {
|
|
170118
|
+
embedRunStateBySession.delete(sessionId);
|
|
170119
|
+
}
|
|
170120
|
+
}
|
|
170121
|
+
switch (outcome.status) {
|
|
170122
|
+
case "nothing":
|
|
170123
|
+
return {
|
|
170124
|
+
text: `## /ctx-embed
|
|
170125
|
+
|
|
170126
|
+
All of this session's history is already embedded.`,
|
|
170127
|
+
level: "info"
|
|
170128
|
+
};
|
|
170129
|
+
case "disabled":
|
|
170130
|
+
return {
|
|
170131
|
+
text: `## /ctx-embed
|
|
170132
|
+
|
|
170133
|
+
No embedding provider is configured, so there is nothing to embed.`,
|
|
170134
|
+
level: "info"
|
|
170135
|
+
};
|
|
170136
|
+
case "busy":
|
|
170137
|
+
return {
|
|
170138
|
+
text: `## /ctx-embed
|
|
170139
|
+
|
|
170140
|
+
Embedding is already running for this project. Try again shortly.`,
|
|
170141
|
+
level: "info"
|
|
170142
|
+
};
|
|
170143
|
+
case "aborted": {
|
|
170144
|
+
const cov = getEmbeddingCoverageStatus(db, projectIdentity, sessionId);
|
|
170145
|
+
return {
|
|
170146
|
+
text: `## /ctx-embed
|
|
170147
|
+
|
|
170148
|
+
Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`,
|
|
170149
|
+
level: "info"
|
|
170150
|
+
};
|
|
170151
|
+
}
|
|
170152
|
+
case "stalled":
|
|
170153
|
+
return {
|
|
170154
|
+
text: `## /ctx-embed
|
|
170155
|
+
|
|
170156
|
+
Embedded ${outcome.embedded} compartment${outcome.embedded === 1 ? "" : "s"}; ${outcome.remaining} could not be embedded (the provider returned no result). Run /ctx-embed start again to retry them.`,
|
|
170157
|
+
level: "info"
|
|
170158
|
+
};
|
|
170159
|
+
default:
|
|
170160
|
+
return {
|
|
170161
|
+
text: `## /ctx-embed
|
|
170162
|
+
|
|
170163
|
+
Embedded ${outcome.embedded} compartment${outcome.embedded === 1 ? "" : "s"} of history for semantic search.`,
|
|
170164
|
+
level: "success"
|
|
170165
|
+
};
|
|
170166
|
+
}
|
|
170167
|
+
}
|
|
170168
|
+
function registerCtxEmbedCommand(pi, deps) {
|
|
170169
|
+
pi.registerCommand("ctx-embed", {
|
|
170170
|
+
description: "Embedding status, or start/pause history compartment embedding (start | pause)",
|
|
170171
|
+
handler: async (args, ctx) => {
|
|
169851
170172
|
const sessionId = resolveSessionId(ctx);
|
|
169852
170173
|
if (!sessionId) {
|
|
169853
170174
|
sendCtxStatusMessage(pi, {
|
|
169854
|
-
title: "/ctx-embed
|
|
169855
|
-
text: `## /ctx-embed
|
|
170175
|
+
title: "/ctx-embed",
|
|
170176
|
+
text: `## /ctx-embed
|
|
169856
170177
|
|
|
169857
170178
|
No active Pi session is available.`,
|
|
169858
170179
|
level: "error"
|
|
169859
170180
|
});
|
|
169860
170181
|
return;
|
|
169861
170182
|
}
|
|
170183
|
+
const project = deps.resolveProject?.(ctx) ?? {
|
|
170184
|
+
projectDir: deps.projectDir,
|
|
170185
|
+
projectIdentity: deps.projectIdentity
|
|
170186
|
+
};
|
|
170187
|
+
const sub = args.trim().toLowerCase();
|
|
170188
|
+
if (sub === "pause") {
|
|
170189
|
+
embedPauseBySession.add(sessionId);
|
|
170190
|
+
const ctrl = embedRunStateBySession.get(sessionId);
|
|
170191
|
+
if (ctrl)
|
|
170192
|
+
ctrl.abort();
|
|
170193
|
+
const cov = getEmbeddingCoverageStatus(deps.db, project.projectIdentity, sessionId);
|
|
170194
|
+
sendCtxStatusMessage(pi, {
|
|
170195
|
+
title: "/ctx-embed",
|
|
170196
|
+
text: `## /ctx-embed
|
|
170197
|
+
|
|
170198
|
+
Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`,
|
|
170199
|
+
level: "info"
|
|
170200
|
+
});
|
|
170201
|
+
return;
|
|
170202
|
+
}
|
|
169862
170203
|
if (deps.memoryEnabled === false) {
|
|
169863
170204
|
sendCtxStatusMessage(pi, {
|
|
169864
|
-
title: "/ctx-embed
|
|
169865
|
-
text: `## /ctx-embed
|
|
170205
|
+
title: "/ctx-embed",
|
|
170206
|
+
text: `## /ctx-embed
|
|
169866
170207
|
|
|
169867
170208
|
Memory is disabled for this project, so there is no semantic embedding to backfill.`,
|
|
169868
170209
|
level: "info"
|
|
169869
170210
|
});
|
|
169870
170211
|
return;
|
|
169871
170212
|
}
|
|
169872
|
-
const project = deps.resolveProject?.(ctx) ?? {
|
|
169873
|
-
projectDir: deps.projectDir,
|
|
169874
|
-
projectIdentity: deps.projectIdentity
|
|
169875
|
-
};
|
|
169876
170213
|
await ensureProjectRegisteredFromPiDirectory(project.projectDir, deps.db);
|
|
169877
|
-
|
|
169878
|
-
|
|
169879
|
-
|
|
169880
|
-
|
|
169881
|
-
|
|
169882
|
-
|
|
169883
|
-
|
|
169884
|
-
|
|
169885
|
-
|
|
169886
|
-
|
|
169887
|
-
|
|
169888
|
-
|
|
169889
|
-
|
|
169890
|
-
|
|
169891
|
-
|
|
169892
|
-
|
|
169893
|
-
|
|
169894
|
-
|
|
169895
|
-
return {
|
|
169896
|
-
text: `## /ctx-embed-history
|
|
169897
|
-
|
|
169898
|
-
Embedding is already running for this project — ${outcome.total} compartment${outcome.total === 1 ? "" : "s"} still pending. Try again shortly.`,
|
|
169899
|
-
level: "info"
|
|
169900
|
-
};
|
|
169901
|
-
case "stalled":
|
|
169902
|
-
return {
|
|
169903
|
-
text: `## /ctx-embed-history
|
|
169904
|
-
|
|
169905
|
-
Embedded ${outcome.embedded} compartment${outcome.embedded === 1 ? "" : "s"}; ${outcome.remaining} could not be embedded (the provider returned no result). Run /ctx-embed-history again to retry them.`,
|
|
169906
|
-
level: "info"
|
|
169907
|
-
};
|
|
169908
|
-
default:
|
|
169909
|
-
return {
|
|
169910
|
-
text: `## /ctx-embed-history
|
|
170214
|
+
if (sub === "start") {
|
|
170215
|
+
const { text, level } = await runEmbedDrain(deps.db, project.projectIdentity, sessionId);
|
|
170216
|
+
sendCtxStatusMessage(pi, { title: "/ctx-embed", text, level });
|
|
170217
|
+
return;
|
|
170218
|
+
}
|
|
170219
|
+
if (sub !== "") {
|
|
170220
|
+
sendCtxStatusMessage(pi, {
|
|
170221
|
+
title: "/ctx-embed",
|
|
170222
|
+
text: "## /ctx-embed\n\nUsage: `/ctx-embed` (status), `/ctx-embed start`, or `/ctx-embed pause`.",
|
|
170223
|
+
level: "info"
|
|
170224
|
+
});
|
|
170225
|
+
return;
|
|
170226
|
+
}
|
|
170227
|
+
const coverage = getEmbeddingCoverageStatus(deps.db, project.projectIdentity, sessionId);
|
|
170228
|
+
const statusText = formatEmbedStatusText(coverage, { status: "idle" });
|
|
170229
|
+
sendCtxStatusMessage(pi, {
|
|
170230
|
+
title: "/ctx-embed",
|
|
170231
|
+
text: `## Embedding Status
|
|
169911
170232
|
|
|
169912
|
-
|
|
169913
|
-
|
|
169914
|
-
};
|
|
169915
|
-
}
|
|
169916
|
-
})();
|
|
169917
|
-
sendCtxStatusMessage(pi, { title: "/ctx-embed-history", text, level }, {
|
|
169918
|
-
sessionId,
|
|
169919
|
-
projectIdentity: project.projectIdentity,
|
|
169920
|
-
status: outcome.status,
|
|
169921
|
-
embedded: outcome.embedded,
|
|
169922
|
-
total: outcome.total
|
|
170233
|
+
${statusText}`,
|
|
170234
|
+
level: "info"
|
|
169923
170235
|
});
|
|
169924
170236
|
}
|
|
169925
170237
|
});
|
|
169926
170238
|
}
|
|
170239
|
+
function maybeAutoEmbedPiSession(deps, sessionId, projectDir, projectIdentity, notify) {
|
|
170240
|
+
if (autoEmbedAttemptedBySession.has(sessionId))
|
|
170241
|
+
return;
|
|
170242
|
+
if (embedPauseBySession.has(sessionId))
|
|
170243
|
+
return;
|
|
170244
|
+
if (deps.memoryEnabled === false)
|
|
170245
|
+
return;
|
|
170246
|
+
autoEmbedAttemptedBySession.add(sessionId);
|
|
170247
|
+
(async () => {
|
|
170248
|
+
try {
|
|
170249
|
+
await new Promise((resolve5) => setTimeout(resolve5, 0));
|
|
170250
|
+
await ensureProjectRegisteredFromPiDirectory(projectDir, deps.db);
|
|
170251
|
+
const coverage = getEmbeddingCoverageStatus(deps.db, projectIdentity, sessionId);
|
|
170252
|
+
if (!coverage.enabled)
|
|
170253
|
+
return;
|
|
170254
|
+
const remaining = coverage.session.total - coverage.session.embedded;
|
|
170255
|
+
if (remaining <= 0)
|
|
170256
|
+
return;
|
|
170257
|
+
notify(`Embedding ${remaining} compartment${remaining === 1 ? "" : "s"} of history in the background…`);
|
|
170258
|
+
const { text } = await runEmbedDrain(deps.db, projectIdentity, sessionId);
|
|
170259
|
+
notify(text.replace(/^## \/ctx-embed\n\n/, ""));
|
|
170260
|
+
} catch {}
|
|
170261
|
+
})();
|
|
170262
|
+
}
|
|
169927
170263
|
|
|
169928
170264
|
// ../plugin/src/hooks/magic-context/execute-flush.ts
|
|
169929
170265
|
init_logger();
|
|
@@ -170338,76 +170674,12 @@ function computePiWorkMetrics(sessionEntries) {
|
|
|
170338
170674
|
return { newWorkTokens, totalInputTokens };
|
|
170339
170675
|
}
|
|
170340
170676
|
|
|
170341
|
-
// ../plugin/src/hooks/magic-context/system-injection-stripper.ts
|
|
170342
|
-
var SYSTEM_INJECTION_MARKERS = [
|
|
170343
|
-
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
170344
|
-
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
170345
|
-
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
170346
|
-
"[Category+Skill Reminder]",
|
|
170347
|
-
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
170348
|
-
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
170349
|
-
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
170350
|
-
"Unstable background agent appears idle",
|
|
170351
|
-
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
170352
|
-
];
|
|
170353
|
-
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
170354
|
-
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
170355
|
-
function stripSystemInjection(text) {
|
|
170356
|
-
let hasInjection = false;
|
|
170357
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
170358
|
-
if (text.includes(marker)) {
|
|
170359
|
-
hasInjection = true;
|
|
170360
|
-
break;
|
|
170361
|
-
}
|
|
170362
|
-
}
|
|
170363
|
-
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
170364
|
-
hasInjection = true;
|
|
170365
|
-
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
170366
|
-
if (!hasInjection)
|
|
170367
|
-
return null;
|
|
170368
|
-
let cleaned = text;
|
|
170369
|
-
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
170370
|
-
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
170371
|
-
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
170372
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
170373
|
-
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
170374
|
-
continue;
|
|
170375
|
-
const idx = cleaned.indexOf(marker);
|
|
170376
|
-
if (idx === -1)
|
|
170377
|
-
continue;
|
|
170378
|
-
const blockEnd = cleaned.indexOf(`
|
|
170379
|
-
|
|
170380
|
-
`, idx + marker.length);
|
|
170381
|
-
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
170382
|
-
}
|
|
170383
|
-
return cleaned.trim();
|
|
170384
|
-
}
|
|
170385
|
-
|
|
170386
170677
|
// ../plugin/src/hooks/magic-context/apply-operations.ts
|
|
170387
|
-
var USER_DROP_PREVIEW_CHARS = 250;
|
|
170388
170678
|
var RECENT_TOOL_SKELETON_WINDOW = 20;
|
|
170389
|
-
function buildReplacementContent(tagId
|
|
170390
|
-
|
|
170391
|
-
|
|
170392
|
-
|
|
170393
|
-
}
|
|
170394
|
-
const currentContent = target.getContent?.() ?? "";
|
|
170395
|
-
const strippedInjection = stripSystemInjection(currentContent);
|
|
170396
|
-
if (strippedInjection !== null && stripTagPrefix(strippedInjection).trim().length === 0) {
|
|
170397
|
-
return `[dropped §${tagId}§]`;
|
|
170398
|
-
}
|
|
170399
|
-
const originalText = stripTagPrefix(currentContent);
|
|
170400
|
-
if (originalText.length <= USER_DROP_PREVIEW_CHARS) {
|
|
170401
|
-
return `[truncated §${tagId}§]
|
|
170402
|
-
${originalText}`;
|
|
170403
|
-
}
|
|
170404
|
-
const hardCut = originalText.slice(0, USER_DROP_PREVIEW_CHARS);
|
|
170405
|
-
const softCutIndex = hardCut.search(/\s\S*$/);
|
|
170406
|
-
const preview = softCutIndex > USER_DROP_PREVIEW_CHARS - 30 ? hardCut.slice(0, softCutIndex) : hardCut;
|
|
170407
|
-
return `[truncated §${tagId}§]
|
|
170408
|
-
${preview}…`;
|
|
170409
|
-
}
|
|
170410
|
-
function applyPendingOperations(sessionId, db, targets, protectedTags = 0, preloadedTags, preloadedPendingOps) {
|
|
170679
|
+
function buildReplacementContent(tagId) {
|
|
170680
|
+
return `[dropped §${tagId}§]`;
|
|
170681
|
+
}
|
|
170682
|
+
function applyPendingOperations(sessionId, db, targets, protectedTags = 0, preloadedTags, preloadedPendingOps, syntheticPendingOps = []) {
|
|
170411
170683
|
let didMutateMessage = false;
|
|
170412
170684
|
db.transaction(() => {
|
|
170413
170685
|
const tags = preloadedTags ?? getTagsBySession(db, sessionId);
|
|
@@ -170415,11 +170687,16 @@ function applyPendingOperations(sessionId, db, targets, protectedTags = 0, prelo
|
|
|
170415
170687
|
const tagTypeById = new Map(tags.map((tag) => [tag.tagNumber, tag.type]));
|
|
170416
170688
|
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;
|
|
170417
170689
|
const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
|
|
170690
|
+
const opsToApply = [
|
|
170691
|
+
...pendingOps.map((op) => ({ op, synthetic: false })),
|
|
170692
|
+
...syntheticPendingOps.map((op) => ({ op, synthetic: true }))
|
|
170693
|
+
];
|
|
170418
170694
|
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));
|
|
170419
|
-
for (const pendingOp of
|
|
170695
|
+
for (const { op: pendingOp, synthetic } of opsToApply) {
|
|
170420
170696
|
const tagStatus = tagStatusById.get(pendingOp.tagId);
|
|
170421
170697
|
if (tagStatus === "compacted" || tagStatus === "dropped") {
|
|
170422
|
-
|
|
170698
|
+
if (!synthetic)
|
|
170699
|
+
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
170423
170700
|
continue;
|
|
170424
170701
|
}
|
|
170425
170702
|
if (protectedTagIds.has(pendingOp.tagId)) {
|
|
@@ -170427,33 +170704,46 @@ function applyPendingOperations(sessionId, db, targets, protectedTags = 0, prelo
|
|
|
170427
170704
|
}
|
|
170428
170705
|
const target = targets.get(pendingOp.tagId);
|
|
170429
170706
|
const isToolTag = tagTypeById.get(pendingOp.tagId) === "tool";
|
|
170707
|
+
if (synthetic) {
|
|
170708
|
+
if (!isToolTag || target?.canDrop?.() !== true)
|
|
170709
|
+
continue;
|
|
170710
|
+
}
|
|
170711
|
+
let shouldPersistDrop = false;
|
|
170430
170712
|
if (isToolTag) {
|
|
170431
170713
|
if (skeletonWindow.has(pendingOp.tagId)) {
|
|
170432
170714
|
const truncResult = target?.truncate?.() ?? "absent";
|
|
170433
|
-
if (truncResult === "incomplete") {
|
|
170715
|
+
if (truncResult === "incomplete" || synthetic && truncResult !== "truncated") {
|
|
170434
170716
|
continue;
|
|
170435
170717
|
}
|
|
170436
170718
|
if (truncResult === "truncated") {
|
|
170437
170719
|
didMutateMessage = true;
|
|
170438
170720
|
}
|
|
170439
170721
|
updateTagDropMode(db, sessionId, pendingOp.tagId, "truncated");
|
|
170722
|
+
shouldPersistDrop = true;
|
|
170440
170723
|
} else {
|
|
170441
170724
|
const dropResult = target?.drop?.() ?? "absent";
|
|
170442
|
-
if (dropResult === "incomplete") {
|
|
170725
|
+
if (dropResult === "incomplete" || synthetic && dropResult !== "removed") {
|
|
170443
170726
|
continue;
|
|
170444
170727
|
}
|
|
170445
170728
|
if (dropResult === "removed") {
|
|
170446
170729
|
didMutateMessage = true;
|
|
170447
170730
|
}
|
|
170448
170731
|
updateTagDropMode(db, sessionId, pendingOp.tagId, "full");
|
|
170732
|
+
shouldPersistDrop = true;
|
|
170449
170733
|
}
|
|
170450
170734
|
} else if (target) {
|
|
170451
|
-
const changed = target.setContent(buildReplacementContent(pendingOp.tagId
|
|
170735
|
+
const changed = target.setContent(buildReplacementContent(pendingOp.tagId));
|
|
170452
170736
|
if (changed)
|
|
170453
170737
|
didMutateMessage = true;
|
|
170738
|
+
shouldPersistDrop = true;
|
|
170739
|
+
} else if (!synthetic) {
|
|
170740
|
+
shouldPersistDrop = true;
|
|
170454
170741
|
}
|
|
170742
|
+
if (!shouldPersistDrop)
|
|
170743
|
+
continue;
|
|
170455
170744
|
updateTagStatus(db, sessionId, pendingOp.tagId, "dropped");
|
|
170456
|
-
|
|
170745
|
+
if (!synthetic)
|
|
170746
|
+
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
170457
170747
|
}
|
|
170458
170748
|
})();
|
|
170459
170749
|
return didMutateMessage;
|
|
@@ -170477,7 +170767,7 @@ function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
|
|
|
170477
170767
|
}
|
|
170478
170768
|
}
|
|
170479
170769
|
} else if (target) {
|
|
170480
|
-
const changed = target.setContent(buildReplacementContent(tag.tagNumber
|
|
170770
|
+
const changed = target.setContent(buildReplacementContent(tag.tagNumber));
|
|
170481
170771
|
if (changed)
|
|
170482
170772
|
didMutateMessage = true;
|
|
170483
170773
|
}
|
|
@@ -170765,7 +171055,8 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config2) {
|
|
|
170765
171055
|
const result = {
|
|
170766
171056
|
compressedToLite: 0,
|
|
170767
171057
|
compressedToFull: 0,
|
|
170768
|
-
compressedToUltra: 0
|
|
171058
|
+
compressedToUltra: 0,
|
|
171059
|
+
mutatedTextTags: 0
|
|
170769
171060
|
};
|
|
170770
171061
|
if (!config2.enabled)
|
|
170771
171062
|
return result;
|
|
@@ -170806,7 +171097,9 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config2) {
|
|
|
170806
171097
|
const target = targets.get(tag.tagNumber);
|
|
170807
171098
|
if (!target)
|
|
170808
171099
|
continue;
|
|
170809
|
-
target.setContent(compressed);
|
|
171100
|
+
const didMutate = target.setContent(compressed);
|
|
171101
|
+
if (didMutate)
|
|
171102
|
+
result.mutatedTextTags += 1;
|
|
170810
171103
|
updateCavemanDepth(db, sessionId, tag.tagNumber, targetDepth);
|
|
170811
171104
|
if (targetDepth === DEPTH_LITE)
|
|
170812
171105
|
result.compressedToLite += 1;
|
|
@@ -171184,7 +171477,7 @@ function buildToolArcs(messages) {
|
|
|
171184
171477
|
}
|
|
171185
171478
|
return arcs.sort((a, b) => a.invOrdinal - b.invOrdinal || (a.resOrdinal ?? Number.MAX_SAFE_INTEGER) - (b.resOrdinal ?? Number.MAX_SAFE_INTEGER));
|
|
171186
171479
|
}
|
|
171187
|
-
function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal) {
|
|
171480
|
+
function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal, recentOpenArcCutoff) {
|
|
171188
171481
|
let boundary = candidate;
|
|
171189
171482
|
for (const arc of arcs) {
|
|
171190
171483
|
if (arc.resOrdinal !== null) {
|
|
@@ -171193,6 +171486,8 @@ function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal) {
|
|
|
171193
171486
|
}
|
|
171194
171487
|
continue;
|
|
171195
171488
|
}
|
|
171489
|
+
if (arc.invOrdinal < recentOpenArcCutoff)
|
|
171490
|
+
continue;
|
|
171196
171491
|
if (arc.invOrdinal >= lastCompartmentEndOrdinal + 1 && arc.invOrdinal < boundary) {
|
|
171197
171492
|
return arc.invOrdinal;
|
|
171198
171493
|
}
|
|
@@ -171430,7 +171725,7 @@ function semanticSnapBoundary(args) {
|
|
|
171430
171725
|
return snapped;
|
|
171431
171726
|
}
|
|
171432
171727
|
function applyHeadCap(args) {
|
|
171433
|
-
const { index, protectedTailStart, offset, arcs, capTokens } = args;
|
|
171728
|
+
const { index, protectedTailStart, offset, arcs, capTokens, recentOpenArcCutoff } = args;
|
|
171434
171729
|
if (offset >= protectedTailStart)
|
|
171435
171730
|
return { eligibleEndOrdinal: offset, oversizeAtomicUnit: false };
|
|
171436
171731
|
let end = index.findHeadEndForCap(offset, protectedTailStart, capTokens);
|
|
@@ -171438,7 +171733,7 @@ function applyHeadCap(args) {
|
|
|
171438
171733
|
for (const arc of arcs) {
|
|
171439
171734
|
const resOrdinal = arc.resOrdinal;
|
|
171440
171735
|
if (resOrdinal === null) {
|
|
171441
|
-
if (arc.invOrdinal >= offset && arc.invOrdinal < end) {
|
|
171736
|
+
if (arc.invOrdinal >= recentOpenArcCutoff && arc.invOrdinal >= offset && arc.invOrdinal < end) {
|
|
171442
171737
|
end = Math.min(end, arc.invOrdinal);
|
|
171443
171738
|
}
|
|
171444
171739
|
continue;
|
|
@@ -171505,7 +171800,14 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171505
171800
|
}
|
|
171506
171801
|
if (ctx.mode === "manual-full-recomp") {
|
|
171507
171802
|
const arcs2 = buildToolArcs(messages);
|
|
171508
|
-
const
|
|
171803
|
+
const recompTarget = deriveProtectedTailTokenTarget({
|
|
171804
|
+
contextLimit: ctx.contextLimit,
|
|
171805
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
171806
|
+
usagePercentage: 0,
|
|
171807
|
+
triggerBudget: ctx.triggerBudget
|
|
171808
|
+
});
|
|
171809
|
+
const recentOpenArcCutoff2 = index.findSuffixStartForTokens(recompTarget.N);
|
|
171810
|
+
const firstOpenArc = arcs2.find((arc) => arc.resOrdinal === null && arc.invOrdinal >= offset && arc.invOrdinal >= recentOpenArcCutoff2);
|
|
171509
171811
|
const protectedTailStart2 = firstOpenArc?.invOrdinal ?? rawMessageCount + 1;
|
|
171510
171812
|
const rawRangeFingerprint2 = computeRawRangeFingerprint(messages, offset, protectedTailStart2);
|
|
171511
171813
|
return {
|
|
@@ -171547,13 +171849,14 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171547
171849
|
const scaledN = ctx.emergencyTailScale ? Math.max(1, Math.floor(target.N * ctx.emergencyTailScale)) : target.N;
|
|
171548
171850
|
const arcs = buildToolArcs(messages);
|
|
171549
171851
|
let boundary = index.findSuffixStartForTokens(scaledN);
|
|
171852
|
+
const recentOpenArcCutoff = boundary;
|
|
171550
171853
|
let boundaryReason = boundary === 1 ? "whole-session-smaller-than-tail" : "size-walk";
|
|
171551
171854
|
const tokenAtBoundary = index.tokenForOrdinal(boundary);
|
|
171552
171855
|
if (boundary <= rawMessageCount && tokenAtBoundary > Math.max(2 * scaledN, 64000) && boundary < rawMessageCount) {
|
|
171553
171856
|
boundary += 1;
|
|
171554
171857
|
boundaryReason = "huge-message-exception";
|
|
171555
171858
|
}
|
|
171556
|
-
boundary = fenceBoundaryForToolArcs(boundary, arcs, ctx.lastCompartmentEndOrdinal);
|
|
171859
|
+
boundary = fenceBoundaryForToolArcs(boundary, arcs, ctx.lastCompartmentEndOrdinal, recentOpenArcCutoff);
|
|
171557
171860
|
const snapped = semanticSnapBoundary({
|
|
171558
171861
|
messages,
|
|
171559
171862
|
index,
|
|
@@ -171563,7 +171866,7 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171563
171866
|
});
|
|
171564
171867
|
if (snapped !== boundary)
|
|
171565
171868
|
boundaryReason = "semantic-snap";
|
|
171566
|
-
boundary = fenceBoundaryForToolArcs(snapped, arcs, ctx.lastCompartmentEndOrdinal);
|
|
171869
|
+
boundary = fenceBoundaryForToolArcs(snapped, arcs, ctx.lastCompartmentEndOrdinal, recentOpenArcCutoff);
|
|
171567
171870
|
let runtimeFloor = offset;
|
|
171568
171871
|
if (ctx.migrationFloorActive)
|
|
171569
171872
|
runtimeFloor = Math.max(runtimeFloor, ctx.priorBoundaryOrdinal);
|
|
@@ -171599,7 +171902,8 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171599
171902
|
offset,
|
|
171600
171903
|
arcs,
|
|
171601
171904
|
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal,
|
|
171602
|
-
capTokens: perRunCap
|
|
171905
|
+
capTokens: perRunCap,
|
|
171906
|
+
recentOpenArcCutoff
|
|
171603
171907
|
});
|
|
171604
171908
|
const rawRangeFingerprint = computeRawRangeFingerprint(messages, offset, head.eligibleEndOrdinal);
|
|
171605
171909
|
return {
|
|
@@ -172073,6 +172377,13 @@ function computePressure(input) {
|
|
|
172073
172377
|
function approxThousands(tokens) {
|
|
172074
172378
|
return `${Math.round(tokens / 1000)}k`;
|
|
172075
172379
|
}
|
|
172380
|
+
function formatOldestReclaimableHint(hint) {
|
|
172381
|
+
if (!hint || hint.length === 0)
|
|
172382
|
+
return "";
|
|
172383
|
+
const rendered = hint.slice(0, 4).map((tag) => `§${tag.tagNumber}§ ${tag.toolName ?? "tool"}`).join(" · ");
|
|
172384
|
+
return rendered.length > 0 ? `
|
|
172385
|
+
oldest reclaimable: ${rendered}.` : "";
|
|
172386
|
+
}
|
|
172076
172387
|
var CHANNEL2_USABLE_FRACTION = 1 / 3;
|
|
172077
172388
|
var CHANNEL2_MIN_RECLAIMABLE = 1e4;
|
|
172078
172389
|
function shouldTriggerChannel2(input) {
|
|
@@ -172082,14 +172393,16 @@ function shouldTriggerChannel2(input) {
|
|
|
172082
172393
|
return true;
|
|
172083
172394
|
return input.reclaimableTokens >= input.usableTokens * CHANNEL2_USABLE_FRACTION;
|
|
172084
172395
|
}
|
|
172085
|
-
function buildChannel2Reminder(undroppedTokens) {
|
|
172396
|
+
function buildChannel2Reminder(undroppedTokens, hint) {
|
|
172086
172397
|
const amount = approxThousands(undroppedTokens);
|
|
172398
|
+
const hintText = formatOldestReclaimableHint(hint);
|
|
172087
172399
|
return `<system-reminder>
|
|
172088
|
-
` + `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
|
|
172400
|
+
` + `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}
|
|
172089
172401
|
` + `</system-reminder>`;
|
|
172090
172402
|
}
|
|
172091
|
-
function buildChannel1Reminder(level, undroppedTokens) {
|
|
172403
|
+
function buildChannel1Reminder(level, undroppedTokens, hint) {
|
|
172092
172404
|
const amount = approxThousands(undroppedTokens);
|
|
172405
|
+
const hintText = formatOldestReclaimableHint(hint);
|
|
172093
172406
|
let body;
|
|
172094
172407
|
switch (level) {
|
|
172095
172408
|
case "gentle":
|
|
@@ -172105,7 +172418,7 @@ function buildChannel1Reminder(level, undroppedTokens) {
|
|
|
172105
172418
|
return `
|
|
172106
172419
|
|
|
172107
172420
|
<system-reminder>
|
|
172108
|
-
${body}
|
|
172421
|
+
${body}${hintText}
|
|
172109
172422
|
</system-reminder>`;
|
|
172110
172423
|
}
|
|
172111
172424
|
|
|
@@ -172653,6 +172966,41 @@ function renderMemoryBlockV2(memories, wrapper = "project-memory", renderOptions
|
|
|
172653
172966
|
`);
|
|
172654
172967
|
}
|
|
172655
172968
|
|
|
172969
|
+
// ../plugin/src/hooks/magic-context/tool-reclaim.ts
|
|
172970
|
+
function buildSyntheticToolReclaimOps(input) {
|
|
172971
|
+
const watermark = Math.max(0, input.watermark);
|
|
172972
|
+
if (watermark <= 0)
|
|
172973
|
+
return [];
|
|
172974
|
+
const realPendingTagIds = new Set((input.pendingOps ?? []).map((op) => op.tagId));
|
|
172975
|
+
const tags = getActiveTagsBySession(input.db, input.sessionId);
|
|
172976
|
+
const synthetic = [];
|
|
172977
|
+
for (const tag of tags) {
|
|
172978
|
+
if (tag.type !== "tool")
|
|
172979
|
+
continue;
|
|
172980
|
+
if (tag.status !== "active")
|
|
172981
|
+
continue;
|
|
172982
|
+
if (tag.tagNumber > watermark)
|
|
172983
|
+
continue;
|
|
172984
|
+
if (realPendingTagIds.has(tag.tagNumber))
|
|
172985
|
+
continue;
|
|
172986
|
+
if (input.targets.get(tag.tagNumber)?.canDrop?.() !== true)
|
|
172987
|
+
continue;
|
|
172988
|
+
synthetic.push({
|
|
172989
|
+
id: 0,
|
|
172990
|
+
sessionId: input.sessionId,
|
|
172991
|
+
tagId: tag.tagNumber,
|
|
172992
|
+
operation: "drop",
|
|
172993
|
+
queuedAt: 0
|
|
172994
|
+
});
|
|
172995
|
+
}
|
|
172996
|
+
return synthetic;
|
|
172997
|
+
}
|
|
172998
|
+
function advanceToolReclaimWatermarkToCurrentMax(db, sessionId) {
|
|
172999
|
+
const maxTagNumber = getMaxTagNumberBySession(db, sessionId);
|
|
173000
|
+
advanceToolReclaimWatermark(db, sessionId, maxTagNumber);
|
|
173001
|
+
return maxTagNumber;
|
|
173002
|
+
}
|
|
173003
|
+
|
|
172656
173004
|
// src/context-handler.ts
|
|
172657
173005
|
init_logger();
|
|
172658
173006
|
|
|
@@ -173063,7 +173411,7 @@ function tagToolPart(args) {
|
|
|
173063
173411
|
const tagged = prependTag(tagId, text);
|
|
173064
173412
|
args.part.setText(tagged);
|
|
173065
173413
|
}
|
|
173066
|
-
args.targets.set(tagId, buildToolTarget(args.part, args.message));
|
|
173414
|
+
args.targets.set(tagId, buildToolTarget(args.part, args.message, tagId));
|
|
173067
173415
|
}
|
|
173068
173416
|
function setToolContentOrText(part, content) {
|
|
173069
173417
|
try {
|
|
@@ -173103,7 +173451,7 @@ function buildAggregateTarget(tagId, occurrences) {
|
|
|
173103
173451
|
return any2 ? "removed" : "absent";
|
|
173104
173452
|
},
|
|
173105
173453
|
truncate() {
|
|
173106
|
-
const sentinel =
|
|
173454
|
+
const sentinel = `[dropped §${tagId}§]`;
|
|
173107
173455
|
let any2 = false;
|
|
173108
173456
|
for (const occ of occurrences) {
|
|
173109
173457
|
if (setToolContentOrText(occ.part, sentinel)) {
|
|
@@ -173135,7 +173483,7 @@ function buildTextTarget(part, message) {
|
|
|
173135
173483
|
}
|
|
173136
173484
|
};
|
|
173137
173485
|
}
|
|
173138
|
-
function buildToolTarget(part, message) {
|
|
173486
|
+
function buildToolTarget(part, message, tagId) {
|
|
173139
173487
|
return {
|
|
173140
173488
|
setContent(content) {
|
|
173141
173489
|
return setToolContentOrText(part, content);
|
|
@@ -173144,11 +173492,11 @@ function buildToolTarget(part, message) {
|
|
|
173144
173492
|
return part.getText() ?? null;
|
|
173145
173493
|
},
|
|
173146
173494
|
drop() {
|
|
173147
|
-
const replaced = part.replaceWithSentinel(`[dropped §${
|
|
173495
|
+
const replaced = part.replaceWithSentinel(`[dropped §${tagId}§]`);
|
|
173148
173496
|
return replaced ? "removed" : "absent";
|
|
173149
173497
|
},
|
|
173150
173498
|
truncate() {
|
|
173151
|
-
const ok = setToolContentOrText(part,
|
|
173499
|
+
const ok = setToolContentOrText(part, `[dropped §${tagId}§]`);
|
|
173152
173500
|
return ok ? "truncated" : "absent";
|
|
173153
173501
|
},
|
|
173154
173502
|
message: {
|
|
@@ -174433,9 +174781,10 @@ function maybeChannel1ReminderForToolResult(args) {
|
|
|
174433
174781
|
return null;
|
|
174434
174782
|
return {
|
|
174435
174783
|
type: "text",
|
|
174436
|
-
text: buildChannel1Reminder(decision.level, decision.undroppedTokens)
|
|
174784
|
+
text: buildChannel1Reminder(decision.level, decision.undroppedTokens, state.oldestReclaimableToolTags)
|
|
174437
174785
|
};
|
|
174438
174786
|
}
|
|
174787
|
+
var CHANNEL2_NUDGE_CUSTOM_TYPE = "magic-context:ceiling-nudge";
|
|
174439
174788
|
function maybeDeliverChannel2Pi(pi, db, sessionId, deliverAs = "followUp") {
|
|
174440
174789
|
let state;
|
|
174441
174790
|
try {
|
|
@@ -174463,9 +174812,12 @@ function maybeDeliverChannel2Pi(pi, db, sessionId, deliverAs = "followUp") {
|
|
|
174463
174812
|
if (!casChannel2NudgeState(db, sessionId, "pending", "claimed"))
|
|
174464
174813
|
return false;
|
|
174465
174814
|
try {
|
|
174466
|
-
pi.
|
|
174467
|
-
|
|
174468
|
-
|
|
174815
|
+
pi.sendMessage({
|
|
174816
|
+
customType: CHANNEL2_NUDGE_CUSTOM_TYPE,
|
|
174817
|
+
content: buildChannel2Reminder(undropped, baseline.oldestReclaimableToolTags),
|
|
174818
|
+
display: false,
|
|
174819
|
+
details: { kind: "channel-2-ceiling-nudge" }
|
|
174820
|
+
}, { deliverAs });
|
|
174469
174821
|
} catch (error51) {
|
|
174470
174822
|
try {
|
|
174471
174823
|
casChannel2NudgeState(db, sessionId, "claimed", "pending");
|
|
@@ -174657,6 +175009,51 @@ function planEmergencyDrop(input) {
|
|
|
174657
175009
|
};
|
|
174658
175010
|
}
|
|
174659
175011
|
|
|
175012
|
+
// ../plugin/src/hooks/magic-context/system-injection-stripper.ts
|
|
175013
|
+
var SYSTEM_INJECTION_MARKERS = [
|
|
175014
|
+
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
175015
|
+
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
175016
|
+
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
175017
|
+
"[Category+Skill Reminder]",
|
|
175018
|
+
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
175019
|
+
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
175020
|
+
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
175021
|
+
"Unstable background agent appears idle",
|
|
175022
|
+
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
175023
|
+
];
|
|
175024
|
+
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
175025
|
+
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
175026
|
+
function stripSystemInjection(text) {
|
|
175027
|
+
let hasInjection = false;
|
|
175028
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
175029
|
+
if (text.includes(marker)) {
|
|
175030
|
+
hasInjection = true;
|
|
175031
|
+
break;
|
|
175032
|
+
}
|
|
175033
|
+
}
|
|
175034
|
+
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
175035
|
+
hasInjection = true;
|
|
175036
|
+
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
175037
|
+
if (!hasInjection)
|
|
175038
|
+
return null;
|
|
175039
|
+
let cleaned = text;
|
|
175040
|
+
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
175041
|
+
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
175042
|
+
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
175043
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
175044
|
+
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
175045
|
+
continue;
|
|
175046
|
+
const idx = cleaned.indexOf(marker);
|
|
175047
|
+
if (idx === -1)
|
|
175048
|
+
continue;
|
|
175049
|
+
const blockEnd = cleaned.indexOf(`
|
|
175050
|
+
|
|
175051
|
+
`, idx + marker.length);
|
|
175052
|
+
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
175053
|
+
}
|
|
175054
|
+
return cleaned.trim();
|
|
175055
|
+
}
|
|
175056
|
+
|
|
174660
175057
|
// src/heuristic-cleanup-pi.ts
|
|
174661
175058
|
init_logger();
|
|
174662
175059
|
var DEDUP_SAFE_TOOLS = new Set([
|
|
@@ -174815,10 +175212,14 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config2, pr
|
|
|
174815
175212
|
if (!matched)
|
|
174816
175213
|
continue;
|
|
174817
175214
|
const target = targets.get(tag.tagNumber);
|
|
174818
|
-
target?.drop?.();
|
|
175215
|
+
const result = target?.drop?.() ?? "absent";
|
|
175216
|
+
if (result === "incomplete")
|
|
175217
|
+
continue;
|
|
174819
175218
|
updateTagDropMode(db, sessionId, tag.tagNumber, "full");
|
|
174820
175219
|
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
174821
|
-
|
|
175220
|
+
if (result === "removed" || result === "truncated") {
|
|
175221
|
+
droppedStaleReduceCalls++;
|
|
175222
|
+
}
|
|
174822
175223
|
}
|
|
174823
175224
|
})();
|
|
174824
175225
|
}
|
|
@@ -174890,7 +175291,9 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config2, pr
|
|
|
174890
175291
|
continue;
|
|
174891
175292
|
updateTagDropMode(db, sessionId, tag.tagNumber, "full");
|
|
174892
175293
|
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
174893
|
-
|
|
175294
|
+
if (result === "removed" || result === "truncated") {
|
|
175295
|
+
deduplicatedTools++;
|
|
175296
|
+
}
|
|
174894
175297
|
}
|
|
174895
175298
|
}
|
|
174896
175299
|
})();
|
|
@@ -174899,6 +175302,7 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config2, pr
|
|
|
174899
175302
|
sessionLog(sessionId, `heuristic cleanup: dropped ${droppedTools} tool tags, stale ctx_reduce=${droppedStaleReduceCalls}, deduplicated ${deduplicatedTools} tool calls, dropped ${droppedInjections} system injections`);
|
|
174900
175303
|
}
|
|
174901
175304
|
let compressedTextTags = 0;
|
|
175305
|
+
let mutatedTextTags = 0;
|
|
174902
175306
|
if (config2.caveman?.enabled) {
|
|
174903
175307
|
const cavemanResult = applyCavemanCleanup(sessionId, db, targets, tags, {
|
|
174904
175308
|
enabled: true,
|
|
@@ -174906,13 +175310,15 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config2, pr
|
|
|
174906
175310
|
protectedTags: config2.protectedTags
|
|
174907
175311
|
});
|
|
174908
175312
|
compressedTextTags = cavemanResult.compressedToLite + cavemanResult.compressedToFull + cavemanResult.compressedToUltra;
|
|
175313
|
+
mutatedTextTags = cavemanResult.mutatedTextTags;
|
|
174909
175314
|
}
|
|
174910
175315
|
return {
|
|
174911
175316
|
droppedTools,
|
|
174912
175317
|
deduplicatedTools,
|
|
174913
175318
|
droppedInjections,
|
|
174914
175319
|
droppedStaleReduceCalls,
|
|
174915
|
-
compressedTextTags
|
|
175320
|
+
compressedTextTags,
|
|
175321
|
+
mutatedTextTags
|
|
174916
175322
|
};
|
|
174917
175323
|
}
|
|
174918
175324
|
function buildMessageIdToMaxTagFromTargets(targets) {
|
|
@@ -180289,9 +180695,7 @@ Context is managed for you entirely automatically — there's nothing to prune a
|
|
|
180289
180695
|
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).`;
|
|
180290
180696
|
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.`;
|
|
180291
180697
|
var BASE_INTRO = (protectedTags) => `Messages and tool outputs are tagged with §N§ identifiers (e.g., §1§, §42§).
|
|
180292
|
-
Use \`ctx_reduce\` to
|
|
180293
|
-
- \`drop\`: Remove entirely (best for tool outputs you already acted on).
|
|
180294
|
-
Syntax: "3-5", "1,2,9", or "1-5,8,12-15". Last ${protectedTags} tags are protected.
|
|
180698
|
+
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".
|
|
180295
180699
|
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.
|
|
180296
180700
|
${CTX_NOTE_GUIDANCE}
|
|
180297
180701
|
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.
|
|
@@ -180310,7 +180714,7 @@ Use \`ctx_expand\` to recover the raw conversation behind a \`<compartment>\` su
|
|
|
180310
180714
|
\`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.
|
|
180311
180715
|
${TOOL_HISTORY_GUIDANCE}
|
|
180312
180716
|
NEVER drop large ranges blindly (e.g., "1-50"). Review each tag before deciding.
|
|
180313
|
-
|
|
180717
|
+
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\`.
|
|
180314
180718
|
NEVER drop assistant text messages unless they are exceptionally large. Your conversation messages are lightweight; only large tool outputs are worth dropping.
|
|
180315
180719
|
Before your turn finishes, consider using \`ctx_reduce\` to drop large tool outputs you no longer need.`;
|
|
180316
180720
|
var BASE_INTRO_NO_REDUCE = () => `${CTX_NOTE_GUIDANCE}
|
|
@@ -181787,6 +182191,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
181787
182191
|
const executeThresholdTokensPi = Math.round((usageContextLimit ?? 0) * resolvedExecuteThresholdPct / 100);
|
|
181788
182192
|
const usableTokensPi = Math.max(0, executeThresholdTokensPi - usageInputTokens + liveTailTokens);
|
|
181789
182193
|
resetLastNudgeCycleIfTailShrank(options.db, sessionId, tailToolTokens);
|
|
182194
|
+
const oldestReclaimableToolTags = getOldestActiveUnprotectedToolTags(options.db, sessionId, options.protectedTags ?? 20);
|
|
181790
182195
|
setPiChannel1Baseline(sessionId, {
|
|
181791
182196
|
tailToolTokens,
|
|
181792
182197
|
historyBudgetTokens: historyBudgetTokens ?? 0,
|
|
@@ -181795,7 +182200,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
181795
182200
|
lastInputTokens: usageInputTokens,
|
|
181796
182201
|
turnToolTokens: 0,
|
|
181797
182202
|
usableTokens: usableTokensPi,
|
|
181798
|
-
reducedSinceRefresh: false
|
|
182203
|
+
reducedSinceRefresh: false,
|
|
182204
|
+
oldestReclaimableToolTags
|
|
181799
182205
|
});
|
|
181800
182206
|
if (usageContextLimit && usageContextLimit > 0 && resolvedExecuteThresholdPct > 0) {
|
|
181801
182207
|
const channel2ShouldTrigger = shouldTriggerChannel2({
|
|
@@ -181823,6 +182229,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
181823
182229
|
logTransformTiming(sessionId, "postTransformPhase", tPostTransform);
|
|
181824
182230
|
sessionLog(sessionId, `transform completed in ${(performance.now() - transformStartTime).toFixed(1)}ms (${outputMessages.length} messages, ${result.targetCount} targets, watermark: ${result.reasoningWatermark})`);
|
|
181825
182231
|
clearLastTransformErrorIfSet(options.db, sessionId);
|
|
182232
|
+
options.maybeAutoEmbedSession?.(sessionId, projectDirectory, projectIdentity);
|
|
181826
182233
|
return { messages: outputMessages };
|
|
181827
182234
|
} catch (err) {
|
|
181828
182235
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -182169,6 +182576,8 @@ async function runPipeline(args) {
|
|
|
182169
182576
|
let historyWasConsumedThisPass = false;
|
|
182170
182577
|
let materializationSatisfiedThisPass = false;
|
|
182171
182578
|
let pendingOpsAppliedThisPass = false;
|
|
182579
|
+
let pendingOpsDidMutate = false;
|
|
182580
|
+
let heuristicOrReasoningDidMutate = false;
|
|
182172
182581
|
let suppressDeferredHistoryDrain = false;
|
|
182173
182582
|
let casLost = false;
|
|
182174
182583
|
const deferredHistoryWasPendingAtPassStart = deferredHistoryRefreshSessions.has(args.sessionId);
|
|
@@ -182254,7 +182663,7 @@ async function runPipeline(args) {
|
|
|
182254
182663
|
sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOps.length}, context=${args.contextUsage.percentage.toFixed(1)}%`);
|
|
182255
182664
|
try {
|
|
182256
182665
|
const tApplyPending = performance.now();
|
|
182257
|
-
applyPendingOperations(args.sessionId, args.db, targets, args.protectedTags, undefined, pendingOps);
|
|
182666
|
+
pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, targets, args.protectedTags, undefined, pendingOps);
|
|
182258
182667
|
logTransformTiming(args.sessionId, "applyPendingOperations", tApplyPending);
|
|
182259
182668
|
executedWorkThisPass = true;
|
|
182260
182669
|
materializationSatisfiedThisPass = true;
|
|
@@ -182338,6 +182747,9 @@ async function runPipeline(args) {
|
|
|
182338
182747
|
} : undefined,
|
|
182339
182748
|
caveman: args.heuristics.caveman
|
|
182340
182749
|
}, activeTags, stableIdResolver);
|
|
182750
|
+
const heuristicMutationCount = heuristicsResult.droppedTools + heuristicsResult.deduplicatedTools + heuristicsResult.droppedInjections + heuristicsResult.droppedStaleReduceCalls + heuristicsResult.mutatedTextTags;
|
|
182751
|
+
if (heuristicMutationCount > 0)
|
|
182752
|
+
heuristicOrReasoningDidMutate = true;
|
|
182341
182753
|
heuristicsExecuted = true;
|
|
182342
182754
|
executedWorkThisPass = true;
|
|
182343
182755
|
if (hasPendingMaterializeSignal) {
|
|
@@ -182346,7 +182758,7 @@ async function runPipeline(args) {
|
|
|
182346
182758
|
if (currentTurnId !== null) {
|
|
182347
182759
|
lastHeuristicsTurnIdBySession.set(args.sessionId, currentTurnId);
|
|
182348
182760
|
}
|
|
182349
|
-
logTransformTiming(args.sessionId, "applyHeuristicCleanup", tHeuristic, `droppedTools=${heuristicsResult.droppedTools} deduplicatedTools=${heuristicsResult.deduplicatedTools} droppedInjections=${heuristicsResult.droppedInjections} compressedTextTags=${heuristicsResult.compressedTextTags}`);
|
|
182761
|
+
logTransformTiming(args.sessionId, "applyHeuristicCleanup", tHeuristic, `droppedTools=${heuristicsResult.droppedTools} deduplicatedTools=${heuristicsResult.deduplicatedTools} droppedInjections=${heuristicsResult.droppedInjections} staleReduce=${heuristicsResult.droppedStaleReduceCalls} compressedTextTags=${heuristicsResult.compressedTextTags} mutatedTextTags=${heuristicsResult.mutatedTextTags}`);
|
|
182350
182762
|
} catch (err) {
|
|
182351
182763
|
sessionLog(args.sessionId, `heuristic cleanup failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
182352
182764
|
}
|
|
@@ -182383,6 +182795,9 @@ async function runPipeline(args) {
|
|
|
182383
182795
|
}
|
|
182384
182796
|
logTransformTiming(args.sessionId, "clearOldReasoning", tClearReasoning);
|
|
182385
182797
|
logTransformTiming(args.sessionId, "watermarkCleanup", tClearReasoning);
|
|
182798
|
+
if (clearOutcome.cleared > 0 || stripOutcome.stripped > 0) {
|
|
182799
|
+
heuristicOrReasoningDidMutate = true;
|
|
182800
|
+
}
|
|
182386
182801
|
if (combinedWatermark > prevWatermark || clearOutcome.cleared > 0 || stripOutcome.stripped > 0) {
|
|
182387
182802
|
executedWorkThisPass = true;
|
|
182388
182803
|
}
|
|
@@ -182390,7 +182805,32 @@ async function runPipeline(args) {
|
|
|
182390
182805
|
sessionLog(args.sessionId, `reasoning clearing failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
182391
182806
|
}
|
|
182392
182807
|
}
|
|
182808
|
+
const toolReclaimExecutePass = args.schedulerDecision === "execute";
|
|
182809
|
+
const alreadyMutatingThisPass = pendingOpsDidMutate || heuristicOrReasoningDidMutate;
|
|
182810
|
+
const emergencyDropEligible = args.forceMaterialization === true || args.contextUsage.percentage >= FORCE_MATERIALIZATION_PERCENTAGE;
|
|
182811
|
+
let autoReclaimTargetCount = 0;
|
|
182812
|
+
let autoReclaimDidMutate = false;
|
|
182813
|
+
if (toolReclaimExecutePass && alreadyMutatingThisPass && !emergencyDropEligible) {
|
|
182814
|
+
const reclaimMeta = getOrCreateSessionMeta(args.db, args.sessionId);
|
|
182815
|
+
const syntheticPendingOps = buildSyntheticToolReclaimOps({
|
|
182816
|
+
db: args.db,
|
|
182817
|
+
sessionId: args.sessionId,
|
|
182818
|
+
targets,
|
|
182819
|
+
watermark: reclaimMeta.toolReclaimWatermark ?? 0,
|
|
182820
|
+
pendingOps
|
|
182821
|
+
});
|
|
182822
|
+
autoReclaimTargetCount = syntheticPendingOps.length;
|
|
182823
|
+
if (syntheticPendingOps.length > 0) {
|
|
182824
|
+
autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, targets, args.protectedTags, undefined, [], syntheticPendingOps);
|
|
182825
|
+
}
|
|
182826
|
+
}
|
|
182393
182827
|
transcript.commit();
|
|
182828
|
+
if (toolReclaimExecutePass) {
|
|
182829
|
+
advanceToolReclaimWatermarkToCurrentMax(args.db, args.sessionId);
|
|
182830
|
+
}
|
|
182831
|
+
if (autoReclaimTargetCount > 0) {
|
|
182832
|
+
sessionLog(args.sessionId, `tool reclaim auto-drop: targets=${autoReclaimTargetCount} mutated=${autoReclaimDidMutate}`);
|
|
182833
|
+
}
|
|
182394
182834
|
const postCommitStableIdByRef = new Map;
|
|
182395
182835
|
const postCommitEntryIdByRef = new Map;
|
|
182396
182836
|
for (let i = 0;i < args.messages.length; i++) {
|
|
@@ -182674,6 +183114,7 @@ function clearContextHandlerSession(sessionId) {
|
|
|
182674
183114
|
rawMessageProviderUnregistersBySession.delete(sessionId);
|
|
182675
183115
|
}
|
|
182676
183116
|
clearSessionTracking(sessionId);
|
|
183117
|
+
clearPiEmbedSessionState(sessionId);
|
|
182677
183118
|
}
|
|
182678
183119
|
|
|
182679
183120
|
// src/commands/ctx-flush.ts
|
|
@@ -185176,7 +185617,7 @@ function formatThresholdPercent(value) {
|
|
|
185176
185617
|
// package.json
|
|
185177
185618
|
var package_default = {
|
|
185178
185619
|
name: "@wolfx/pi-magic-context",
|
|
185179
|
-
version: "0.
|
|
185620
|
+
version: "0.25.0",
|
|
185180
185621
|
type: "module",
|
|
185181
185622
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
185182
185623
|
main: "dist/index.js",
|
|
@@ -185230,8 +185671,8 @@ var package_default = {
|
|
|
185230
185671
|
typescript: "^5.8.0"
|
|
185231
185672
|
},
|
|
185232
185673
|
peerDependencies: {
|
|
185233
|
-
"@earendil-works/pi-coding-agent": "
|
|
185234
|
-
"@earendil-works/pi-tui": "
|
|
185674
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
185675
|
+
"@earendil-works/pi-tui": "*"
|
|
185235
185676
|
},
|
|
185236
185677
|
exports: {
|
|
185237
185678
|
".": {
|
|
@@ -185816,9 +186257,184 @@ Older parts of this session are summarized into <compartment> blocks inside <ses
|
|
|
185816
186257
|
|
|
185817
186258
|
ctx_expand(start=120, end=245) ← the compartment's own start/end attributes
|
|
185818
186259
|
|
|
185819
|
-
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
|
|
186260
|
+
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.
|
|
186261
|
+
|
|
186262
|
+
Two recovery modes for finer detail:
|
|
186263
|
+
- 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.
|
|
186264
|
+
- 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.`;
|
|
185820
186265
|
var CTX_EXPAND_TOKEN_BUDGET = 15000;
|
|
185821
186266
|
|
|
186267
|
+
// ../plugin/src/tools/ctx-expand/render.ts
|
|
186268
|
+
function isRecord3(value) {
|
|
186269
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
186270
|
+
}
|
|
186271
|
+
function roleLabel(role) {
|
|
186272
|
+
if (role === "assistant")
|
|
186273
|
+
return "A (assistant)";
|
|
186274
|
+
if (role === "user")
|
|
186275
|
+
return "U (user)";
|
|
186276
|
+
return role;
|
|
186277
|
+
}
|
|
186278
|
+
function truncate2(value, max) {
|
|
186279
|
+
const t = value.trim();
|
|
186280
|
+
return t.length <= max ? t : `${t.slice(0, max)}…`;
|
|
186281
|
+
}
|
|
186282
|
+
function keyArg(input) {
|
|
186283
|
+
if (!input)
|
|
186284
|
+
return "";
|
|
186285
|
+
for (const k of ["filePath", "path", "pattern", "query", "symbol", "module", "action"]) {
|
|
186286
|
+
const v = input[k];
|
|
186287
|
+
if (typeof v === "string" && v.length > 0)
|
|
186288
|
+
return truncate2(v, 60);
|
|
186289
|
+
}
|
|
186290
|
+
if (typeof input.description === "string")
|
|
186291
|
+
return truncate2(input.description, 60);
|
|
186292
|
+
return "";
|
|
186293
|
+
}
|
|
186294
|
+
function asToolPart(part) {
|
|
186295
|
+
const type = typeof part.type === "string" ? part.type : "";
|
|
186296
|
+
if (type === "tool") {
|
|
186297
|
+
const state = isRecord3(part.state) ? part.state : null;
|
|
186298
|
+
const output = state && typeof state.output === "string" ? state.output : state && state.output != null ? JSON.stringify(state.output) : null;
|
|
186299
|
+
const metadata = state && isRecord3(state.metadata) ? state.metadata : null;
|
|
186300
|
+
const title = state && typeof state.title === "string" && state.title || metadata && typeof metadata.title === "string" && metadata.title || null;
|
|
186301
|
+
return {
|
|
186302
|
+
name: typeof part.tool === "string" ? part.tool : "tool",
|
|
186303
|
+
callId: typeof part.callID === "string" ? part.callID : "",
|
|
186304
|
+
title,
|
|
186305
|
+
input: state && isRecord3(state.input) ? state.input : null,
|
|
186306
|
+
output
|
|
186307
|
+
};
|
|
186308
|
+
}
|
|
186309
|
+
if (type === "tool_use") {
|
|
186310
|
+
return {
|
|
186311
|
+
name: typeof part.name === "string" ? part.name : "tool",
|
|
186312
|
+
callId: typeof part.id === "string" ? part.id : "",
|
|
186313
|
+
title: null,
|
|
186314
|
+
input: isRecord3(part.input) ? part.input : null,
|
|
186315
|
+
output: null
|
|
186316
|
+
};
|
|
186317
|
+
}
|
|
186318
|
+
if (type === "tool_result") {
|
|
186319
|
+
const content = part.content;
|
|
186320
|
+
const output = typeof content === "string" ? content : content != null ? JSON.stringify(content) : null;
|
|
186321
|
+
return {
|
|
186322
|
+
name: "tool_result",
|
|
186323
|
+
callId: typeof part.tool_use_id === "string" ? part.tool_use_id : "",
|
|
186324
|
+
title: null,
|
|
186325
|
+
input: null,
|
|
186326
|
+
output
|
|
186327
|
+
};
|
|
186328
|
+
}
|
|
186329
|
+
return null;
|
|
186330
|
+
}
|
|
186331
|
+
function textOf(part) {
|
|
186332
|
+
if (part.type === "text" && typeof part.text === "string")
|
|
186333
|
+
return part.text;
|
|
186334
|
+
return null;
|
|
186335
|
+
}
|
|
186336
|
+
function reasoningOf(part) {
|
|
186337
|
+
if ((part.type === "reasoning" || part.type === "thinking") && typeof part.text === "string") {
|
|
186338
|
+
return part.text;
|
|
186339
|
+
}
|
|
186340
|
+
return null;
|
|
186341
|
+
}
|
|
186342
|
+
function renderPartPreview(part) {
|
|
186343
|
+
if (!isRecord3(part))
|
|
186344
|
+
return null;
|
|
186345
|
+
const text = textOf(part);
|
|
186346
|
+
if (text !== null) {
|
|
186347
|
+
const t = truncate2(text, 200);
|
|
186348
|
+
return t.length > 0 ? ` • ${t}` : null;
|
|
186349
|
+
}
|
|
186350
|
+
const tool = asToolPart(part);
|
|
186351
|
+
if (tool) {
|
|
186352
|
+
const arg = keyArg(tool.input);
|
|
186353
|
+
const head = arg ? `${tool.name}(${arg})` : tool.name;
|
|
186354
|
+
return tool.output !== null ? ` • tool ${head} → output ~${estimateTokens(tool.output)} tok` : ` • tool ${head}`;
|
|
186355
|
+
}
|
|
186356
|
+
const reasoning = reasoningOf(part);
|
|
186357
|
+
if (reasoning !== null)
|
|
186358
|
+
return ` • [reasoning] ${truncate2(reasoning, 120)}`;
|
|
186359
|
+
const type = typeof part.type === "string" ? part.type : "part";
|
|
186360
|
+
if (type === "file")
|
|
186361
|
+
return " • [file]";
|
|
186362
|
+
if (type === "step-start" || type === "step-finish")
|
|
186363
|
+
return null;
|
|
186364
|
+
return ` • [${type}]`;
|
|
186365
|
+
}
|
|
186366
|
+
function renderPartFull(part) {
|
|
186367
|
+
if (!isRecord3(part))
|
|
186368
|
+
return null;
|
|
186369
|
+
const text = textOf(part);
|
|
186370
|
+
if (text !== null) {
|
|
186371
|
+
return text.trim().length > 0 ? ` [text]
|
|
186372
|
+
${text}` : null;
|
|
186373
|
+
}
|
|
186374
|
+
const tool = asToolPart(part);
|
|
186375
|
+
if (tool) {
|
|
186376
|
+
const lines = [];
|
|
186377
|
+
const idSuffix = tool.callId ? ` #${tool.callId}` : "";
|
|
186378
|
+
lines.push(` [tool: ${tool.name}${idSuffix}]`);
|
|
186379
|
+
if (tool.title && tool.title.trim().length > 0) {
|
|
186380
|
+
lines.push(` description: ${tool.title.trim()}`);
|
|
186381
|
+
}
|
|
186382
|
+
if (tool.input)
|
|
186383
|
+
lines.push(` input: ${JSON.stringify(tool.input)}`);
|
|
186384
|
+
if (tool.output !== null)
|
|
186385
|
+
lines.push(` output:
|
|
186386
|
+
${tool.output}`);
|
|
186387
|
+
return lines.join(`
|
|
186388
|
+
`);
|
|
186389
|
+
}
|
|
186390
|
+
const type = typeof part.type === "string" ? part.type : "part";
|
|
186391
|
+
if (type === "file") {
|
|
186392
|
+
const name2 = typeof part.filename === "string" && part.filename || typeof part.url === "string" && part.url || "";
|
|
186393
|
+
return ` [file]${name2 ? ` ${name2}` : ""}`;
|
|
186394
|
+
}
|
|
186395
|
+
return null;
|
|
186396
|
+
}
|
|
186397
|
+
function renderMessageByOrdinal(sessionId, ordinal) {
|
|
186398
|
+
const msg = readRawSessionMessages(sessionId).find((m) => m.ordinal === ordinal);
|
|
186399
|
+
if (!msg) {
|
|
186400
|
+
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.`;
|
|
186401
|
+
}
|
|
186402
|
+
const rendered = msg.parts.map(renderPartFull).filter((l) => l !== null);
|
|
186403
|
+
const lines = [`[${msg.ordinal}] ${roleLabel(msg.role)} — full recovery:`, ""];
|
|
186404
|
+
if (rendered.length === 0) {
|
|
186405
|
+
lines.push(" (no recoverable content — message had only structural/reasoning parts)");
|
|
186406
|
+
} else {
|
|
186407
|
+
lines.push(...rendered);
|
|
186408
|
+
}
|
|
186409
|
+
return lines.join(`
|
|
186410
|
+
`);
|
|
186411
|
+
}
|
|
186412
|
+
function renderVerboseRange(sessionId, start, end, tokenBudget) {
|
|
186413
|
+
const messages = readRawSessionMessages(sessionId).filter((m) => m.ordinal >= start && m.ordinal <= end);
|
|
186414
|
+
const out = [];
|
|
186415
|
+
let usedTokens = 0;
|
|
186416
|
+
let lastOrdinal = start - 1;
|
|
186417
|
+
let truncated = false;
|
|
186418
|
+
for (const msg of messages) {
|
|
186419
|
+
const header = `[${msg.ordinal}] ${roleLabel(msg.role)}`;
|
|
186420
|
+
const partLines = msg.parts.map(renderPartPreview).filter((l) => l !== null);
|
|
186421
|
+
const block = partLines.length > 0 ? `${header}
|
|
186422
|
+
${partLines.join(`
|
|
186423
|
+
`)}` : header;
|
|
186424
|
+
const blockTokens = estimateTokens(block);
|
|
186425
|
+
if (usedTokens + blockTokens > tokenBudget && out.length > 0) {
|
|
186426
|
+
truncated = true;
|
|
186427
|
+
break;
|
|
186428
|
+
}
|
|
186429
|
+
out.push(block);
|
|
186430
|
+
usedTokens += blockTokens;
|
|
186431
|
+
lastOrdinal = msg.ordinal;
|
|
186432
|
+
}
|
|
186433
|
+
return { text: out.join(`
|
|
186434
|
+
|
|
186435
|
+
`), lastOrdinal, truncated };
|
|
186436
|
+
}
|
|
186437
|
+
|
|
185822
186438
|
// ../../node_modules/.bun/typebox@1.1.38/node_modules/typebox/build/system/memory/memory.mjs
|
|
185823
186439
|
var exports_memory = {};
|
|
185824
186440
|
__export(exports_memory, {
|
|
@@ -189884,12 +190500,18 @@ __export(exports_typebox, {
|
|
|
189884
190500
|
});
|
|
189885
190501
|
// src/tools/ctx-expand.ts
|
|
189886
190502
|
var ParamsSchema = exports_typebox.Object({
|
|
189887
|
-
start: exports_typebox.Number({
|
|
190503
|
+
start: exports_typebox.Optional(exports_typebox.Number({
|
|
189888
190504
|
description: "Start message ordinal (from compartment start attribute)"
|
|
189889
|
-
}),
|
|
189890
|
-
end: exports_typebox.Number({
|
|
190505
|
+
})),
|
|
190506
|
+
end: exports_typebox.Optional(exports_typebox.Number({
|
|
189891
190507
|
description: "End message ordinal (from compartment end attribute)"
|
|
189892
|
-
})
|
|
190508
|
+
})),
|
|
190509
|
+
verbose: exports_typebox.Optional(exports_typebox.Boolean({
|
|
190510
|
+
description: "With start/end: list each message separately with its ordinal [N] and per-part preview, so you can recover one in full by ordinal."
|
|
190511
|
+
})),
|
|
190512
|
+
message: exports_typebox.Optional(exports_typebox.Number({
|
|
190513
|
+
description: "Full untruncated recovery of ONE message by its ordinal (text + every tool call's full input/output). Recovers a tool output you dropped with ctx_reduce."
|
|
190514
|
+
}))
|
|
189893
190515
|
});
|
|
189894
190516
|
function ok(text) {
|
|
189895
190517
|
return { content: [{ type: "text", text }], details: undefined };
|
|
@@ -189908,22 +190530,41 @@ function createCtxExpandTool(deps) {
|
|
|
189908
190530
|
description: CTX_EXPAND_DESCRIPTION,
|
|
189909
190531
|
parameters: ParamsSchema,
|
|
189910
190532
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
189911
|
-
if (typeof params.start !== "number" || typeof params.end !== "number" || params.start < 1 || params.end < params.start) {
|
|
189912
|
-
return err("Error: start and end must be positive integers with start <= end.");
|
|
189913
|
-
}
|
|
189914
190533
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
189915
190534
|
if (!sessionId) {
|
|
189916
190535
|
return err("Error: no active Pi session.");
|
|
189917
190536
|
}
|
|
189918
|
-
const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
189919
|
-
if (lastCompartmentEnd >= 0 && params.start > lastCompartmentEnd) {
|
|
189920
|
-
return ok(`Range ${params.start}-${params.end} is entirely within the live tail (after the last compacted message ${lastCompartmentEnd}); those messages are already visible in context.`);
|
|
189921
|
-
}
|
|
189922
|
-
const effectiveEnd = lastCompartmentEnd >= 0 ? Math.min(params.end, lastCompartmentEnd) : params.end;
|
|
189923
190537
|
const unregister = setRawMessageProvider(sessionId, {
|
|
189924
190538
|
readMessages: () => readPiSessionMessages(ctx)
|
|
189925
190539
|
});
|
|
189926
190540
|
try {
|
|
190541
|
+
if (typeof params.message === "number" && params.message >= 1) {
|
|
190542
|
+
return ok(renderMessageByOrdinal(sessionId, params.message));
|
|
190543
|
+
}
|
|
190544
|
+
if (typeof params.start !== "number" || typeof params.end !== "number" || params.start < 1 || params.end < params.start) {
|
|
190545
|
+
return err("Error: provide either message=<ordinal>, or start and end (positive integers, start <= end).");
|
|
190546
|
+
}
|
|
190547
|
+
const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
190548
|
+
if (lastCompartmentEnd >= 0 && params.start > lastCompartmentEnd) {
|
|
190549
|
+
return ok(`Range ${params.start}-${params.end} is entirely within the live tail (after the last compacted message ${lastCompartmentEnd}); those messages are already visible in context.`);
|
|
190550
|
+
}
|
|
190551
|
+
const effectiveEnd = lastCompartmentEnd >= 0 ? Math.min(params.end, lastCompartmentEnd) : params.end;
|
|
190552
|
+
if (params.verbose === true) {
|
|
190553
|
+
const v = renderVerboseRange(sessionId, params.start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET);
|
|
190554
|
+
if (!v.text) {
|
|
190555
|
+
return ok(`No messages found in range ${params.start}-${effectiveEnd}. The range may be outside this session's history.`);
|
|
190556
|
+
}
|
|
190557
|
+
const out = [
|
|
190558
|
+
`Messages ${params.start}-${v.lastOrdinal} (verbose). Recover any one in full with ctx_expand(message=<ordinal>):`,
|
|
190559
|
+
"",
|
|
190560
|
+
v.text
|
|
190561
|
+
];
|
|
190562
|
+
if (v.truncated) {
|
|
190563
|
+
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.`);
|
|
190564
|
+
}
|
|
190565
|
+
return ok(out.join(`
|
|
190566
|
+
`));
|
|
190567
|
+
}
|
|
189927
190568
|
const chunk = readSessionChunk(sessionId, CTX_EXPAND_TOKEN_BUDGET, params.start, effectiveEnd + 1);
|
|
189928
190569
|
if (!chunk.text || chunk.messageCount === 0) {
|
|
189929
190570
|
return ok(`No messages found in range ${params.start}-${params.end}. The range may be outside this session's history.`);
|
|
@@ -190642,15 +191283,16 @@ function parseInteger(str) {
|
|
|
190642
191283
|
}
|
|
190643
191284
|
|
|
190644
191285
|
// ../plugin/src/tools/ctx-reduce/constants.ts
|
|
190645
|
-
var CTX_REDUCE_DESCRIPTION = `
|
|
190646
|
-
|
|
191286
|
+
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".
|
|
191287
|
+
|
|
191288
|
+
How it works:
|
|
191289
|
+
- 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.
|
|
191290
|
+
- The newest tags are protected: marking one just queues it until it ages out of the recent window, so marking recent output is harmless.
|
|
191291
|
+
- 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?".
|
|
190647
191292
|
|
|
190648
|
-
|
|
190649
|
-
|
|
190650
|
-
-
|
|
190651
|
-
- Protected tags are accepted but deferred until they leave the last protected range.
|
|
190652
|
-
- Keep recent context — only reduce OLD content that is no longer relevant to current work.
|
|
190653
|
-
- Dropped content is gone forever.`;
|
|
191293
|
+
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.
|
|
191294
|
+
Keep: user messages, unresolved errors, raw evidence you haven't extracted yet, and outputs whose exact wording may matter later.
|
|
191295
|
+
Never blanket-mark large ranges (e.g. "1-50") — review what each tag holds first.`;
|
|
190654
191296
|
|
|
190655
191297
|
// src/tools/ctx-reduce.ts
|
|
190656
191298
|
var ParamsSchema4 = exports_typebox.Object({
|
|
@@ -191251,7 +191893,21 @@ async function src_default2(pi) {
|
|
|
191251
191893
|
},
|
|
191252
191894
|
historian: hist,
|
|
191253
191895
|
autoSearch: auto,
|
|
191254
|
-
resolveForProject: resolveContextOptionsForProject
|
|
191896
|
+
resolveForProject: resolveContextOptionsForProject,
|
|
191897
|
+
maybeAutoEmbedSession: (sessionId, dir, identity) => {
|
|
191898
|
+
maybeAutoEmbedPiSession({
|
|
191899
|
+
db: database,
|
|
191900
|
+
projectDir: dir,
|
|
191901
|
+
projectIdentity: identity,
|
|
191902
|
+
memoryEnabled: cfg.memory.enabled
|
|
191903
|
+
}, sessionId, dir, identity, (text) => {
|
|
191904
|
+
pi.sendMessage({
|
|
191905
|
+
customType: "ctx-status",
|
|
191906
|
+
content: text,
|
|
191907
|
+
display: true
|
|
191908
|
+
}, { triggerTurn: false });
|
|
191909
|
+
});
|
|
191910
|
+
}
|
|
191255
191911
|
});
|
|
191256
191912
|
function resolveContextOptionsForProject(dir) {
|
|
191257
191913
|
const cached2 = contextOptionsByDir.get(dir);
|
|
@@ -191333,14 +191989,14 @@ async function src_default2(pi) {
|
|
|
191333
191989
|
onProjectSeen: (identity) => seenDreamerProjectIdentities.add(identity)
|
|
191334
191990
|
});
|
|
191335
191991
|
info("registered /ctx-dream");
|
|
191336
|
-
|
|
191992
|
+
registerCtxEmbedCommand(pi, {
|
|
191337
191993
|
db,
|
|
191338
191994
|
projectDir,
|
|
191339
191995
|
projectIdentity,
|
|
191340
191996
|
memoryEnabled: config2.memory.enabled,
|
|
191341
191997
|
resolveProject: resolveCurrentProject
|
|
191342
191998
|
});
|
|
191343
|
-
info("registered /ctx-embed
|
|
191999
|
+
info("registered /ctx-embed");
|
|
191344
192000
|
const dreamerConfig = resolveDreamerFromConfig(config2);
|
|
191345
192001
|
if (dreamerConfig) {
|
|
191346
192002
|
registerPiDreamerProject({
|