@cortexkit/pi-magic-context 0.23.1 → 0.24.1
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 +2326 -346
- package/dist/subagent-entry.js +2101 -413
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -141961,6 +141961,7 @@ var SESSION_META_SELECT_COLUMNS = [
|
|
|
141961
141961
|
"cached_m0_bytes",
|
|
141962
141962
|
"cached_m1_bytes",
|
|
141963
141963
|
"cached_m0_project_memory_epoch",
|
|
141964
|
+
"cached_m0_workspace_fingerprint",
|
|
141964
141965
|
"cached_m0_project_user_profile_version",
|
|
141965
141966
|
"cached_m0_max_compartment_seq",
|
|
141966
141967
|
"cached_m0_max_memory_id",
|
|
@@ -142008,6 +142009,7 @@ var META_COLUMNS = {
|
|
|
142008
142009
|
cachedM0Bytes: "cached_m0_bytes",
|
|
142009
142010
|
cachedM1Bytes: "cached_m1_bytes",
|
|
142010
142011
|
cachedM0ProjectMemoryEpoch: "cached_m0_project_memory_epoch",
|
|
142012
|
+
cachedM0WorkspaceFingerprint: "cached_m0_workspace_fingerprint",
|
|
142011
142013
|
cachedM0ProjectUserProfileVersion: "cached_m0_project_user_profile_version",
|
|
142012
142014
|
cachedM0MaxCompartmentSeq: "cached_m0_max_compartment_seq",
|
|
142013
142015
|
cachedM0MaxMemoryId: "cached_m0_max_memory_id",
|
|
@@ -142037,6 +142039,7 @@ var NULL_BIND_META_KEYS = new Set([
|
|
|
142037
142039
|
"cachedM0Bytes",
|
|
142038
142040
|
"cachedM1Bytes",
|
|
142039
142041
|
"cachedM0ProjectMemoryEpoch",
|
|
142042
|
+
"cachedM0WorkspaceFingerprint",
|
|
142040
142043
|
"cachedM0ProjectUserProfileVersion",
|
|
142041
142044
|
"cachedM0MaxCompartmentSeq",
|
|
142042
142045
|
"cachedM0MaxMemoryId",
|
|
@@ -142070,7 +142073,7 @@ function isSessionMetaRow(row) {
|
|
|
142070
142073
|
if (row === null || typeof row !== "object")
|
|
142071
142074
|
return false;
|
|
142072
142075
|
const r = row;
|
|
142073
|
-
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) && 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);
|
|
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);
|
|
142074
142077
|
}
|
|
142075
142078
|
function getDefaultSessionMeta(sessionId) {
|
|
142076
142079
|
return {
|
|
@@ -142097,6 +142100,7 @@ function getDefaultSessionMeta(sessionId) {
|
|
|
142097
142100
|
cachedM0Bytes: null,
|
|
142098
142101
|
cachedM1Bytes: null,
|
|
142099
142102
|
cachedM0ProjectMemoryEpoch: null,
|
|
142103
|
+
cachedM0WorkspaceFingerprint: null,
|
|
142100
142104
|
cachedM0ProjectUserProfileVersion: null,
|
|
142101
142105
|
cachedM0MaxCompartmentSeq: null,
|
|
142102
142106
|
cachedM0MaxMemoryId: null,
|
|
@@ -142159,6 +142163,7 @@ function toSessionMeta(row) {
|
|
|
142159
142163
|
cachedM0Bytes: toBufferOrNull(row.cached_m0_bytes),
|
|
142160
142164
|
cachedM1Bytes: toBufferOrNull(row.cached_m1_bytes),
|
|
142161
142165
|
cachedM0ProjectMemoryEpoch: numOrNull(row.cached_m0_project_memory_epoch),
|
|
142166
|
+
cachedM0WorkspaceFingerprint: stringOrNull(row.cached_m0_workspace_fingerprint),
|
|
142162
142167
|
cachedM0ProjectUserProfileVersion: numOrNull(row.cached_m0_project_user_profile_version),
|
|
142163
142168
|
cachedM0MaxCompartmentSeq: numOrNull(row.cached_m0_max_compartment_seq),
|
|
142164
142169
|
cachedM0MaxMemoryId: numOrNull(row.cached_m0_max_memory_id),
|
|
@@ -142189,6 +142194,7 @@ function persistCachedM0(db, sessionId, payload) {
|
|
|
142189
142194
|
db.prepare(`UPDATE session_meta SET
|
|
142190
142195
|
cached_m0_bytes = ?,
|
|
142191
142196
|
cached_m0_project_memory_epoch = ?,
|
|
142197
|
+
cached_m0_workspace_fingerprint = ?,
|
|
142192
142198
|
cached_m0_project_user_profile_version = ?,
|
|
142193
142199
|
cached_m0_max_compartment_seq = ?,
|
|
142194
142200
|
cached_m0_max_memory_id = ?,
|
|
@@ -142201,7 +142207,7 @@ function persistCachedM0(db, sessionId, payload) {
|
|
|
142201
142207
|
cached_m0_upgrade_state = ?,
|
|
142202
142208
|
cached_m0_system_hash = ?,
|
|
142203
142209
|
cached_m0_model_key = ?
|
|
142204
|
-
WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer2.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, payload.systemHash ?? "", payload.modelKey ?? "", sessionId);
|
|
142210
|
+
WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.workspaceFingerprint ?? null, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer2.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, payload.systemHash ?? "", payload.modelKey ?? "", sessionId);
|
|
142205
142211
|
}
|
|
142206
142212
|
function clearCachedM0M1(db, sessionId) {
|
|
142207
142213
|
ensureSessionMetaRow(db, sessionId);
|
|
@@ -142210,6 +142216,7 @@ function clearCachedM0M1(db, sessionId) {
|
|
|
142210
142216
|
["cached_m0_bytes", null],
|
|
142211
142217
|
["cached_m1_bytes", null],
|
|
142212
142218
|
["cached_m0_project_memory_epoch", null],
|
|
142219
|
+
["cached_m0_workspace_fingerprint", null],
|
|
142213
142220
|
["cached_m0_project_user_profile_version", null],
|
|
142214
142221
|
["cached_m0_max_compartment_seq", null],
|
|
142215
142222
|
["cached_m0_max_memory_id", null],
|
|
@@ -142924,7 +142931,7 @@ var databases = new Map;
|
|
|
142924
142931
|
var persistenceByDatabase = new WeakMap;
|
|
142925
142932
|
var persistenceErrorByDatabase = new WeakMap;
|
|
142926
142933
|
var lastSchemaFenceRejection = null;
|
|
142927
|
-
var LATEST_SUPPORTED_VERSION =
|
|
142934
|
+
var LATEST_SUPPORTED_VERSION = 36;
|
|
142928
142935
|
function resolveDatabasePath(dbPathOverride) {
|
|
142929
142936
|
if (dbPathOverride) {
|
|
142930
142937
|
return { dbDir: dirname2(dbPathOverride), dbPath: dbPathOverride };
|
|
@@ -143090,6 +143097,35 @@ function initializeDatabase(db) {
|
|
|
143090
143097
|
);
|
|
143091
143098
|
CREATE INDEX IF NOT EXISTS idx_compartments_session ON compartments(session_id);
|
|
143092
143099
|
|
|
143100
|
+
CREATE TABLE IF NOT EXISTS compartment_chunk_embeddings (
|
|
143101
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
143102
|
+
compartment_id INTEGER NOT NULL REFERENCES compartments(id) ON DELETE CASCADE,
|
|
143103
|
+
session_id TEXT NOT NULL,
|
|
143104
|
+
project_path TEXT NOT NULL,
|
|
143105
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
143106
|
+
window_index INTEGER NOT NULL DEFAULT 0,
|
|
143107
|
+
start_ordinal INTEGER NOT NULL,
|
|
143108
|
+
end_ordinal INTEGER NOT NULL,
|
|
143109
|
+
chunk_hash TEXT NOT NULL,
|
|
143110
|
+
model_id TEXT NOT NULL,
|
|
143111
|
+
dims INTEGER NOT NULL,
|
|
143112
|
+
vector BLOB NOT NULL,
|
|
143113
|
+
created_at INTEGER NOT NULL,
|
|
143114
|
+
UNIQUE(compartment_id, window_index)
|
|
143115
|
+
);
|
|
143116
|
+
CREATE INDEX IF NOT EXISTS idx_cce_session ON compartment_chunk_embeddings(session_id);
|
|
143117
|
+
CREATE INDEX IF NOT EXISTS idx_cce_project_model ON compartment_chunk_embeddings(project_path, model_id);
|
|
143118
|
+
|
|
143119
|
+
CREATE TABLE IF NOT EXISTS session_projects (
|
|
143120
|
+
session_id TEXT NOT NULL,
|
|
143121
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
143122
|
+
project_path TEXT NOT NULL,
|
|
143123
|
+
updated_at INTEGER NOT NULL,
|
|
143124
|
+
PRIMARY KEY(session_id, harness)
|
|
143125
|
+
);
|
|
143126
|
+
CREATE INDEX IF NOT EXISTS idx_session_projects_project
|
|
143127
|
+
ON session_projects(project_path);
|
|
143128
|
+
|
|
143093
143129
|
CREATE TABLE IF NOT EXISTS compartment_events (
|
|
143094
143130
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
143095
143131
|
session_id TEXT NOT NULL,
|
|
@@ -143275,6 +143311,25 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143275
143311
|
rekeyed_at INTEGER NOT NULL
|
|
143276
143312
|
);
|
|
143277
143313
|
|
|
143314
|
+
CREATE TABLE IF NOT EXISTS workspaces (
|
|
143315
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
143316
|
+
name TEXT NOT NULL UNIQUE,
|
|
143317
|
+
created_at INTEGER NOT NULL,
|
|
143318
|
+
updated_at INTEGER NOT NULL,
|
|
143319
|
+
share_categories TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'
|
|
143320
|
+
);
|
|
143321
|
+
|
|
143322
|
+
CREATE TABLE IF NOT EXISTS workspace_members (
|
|
143323
|
+
workspace_id INTEGER NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
143324
|
+
project_path TEXT NOT NULL,
|
|
143325
|
+
display_name TEXT NOT NULL,
|
|
143326
|
+
display_path TEXT NOT NULL,
|
|
143327
|
+
added_at INTEGER NOT NULL,
|
|
143328
|
+
PRIMARY KEY (workspace_id, project_path)
|
|
143329
|
+
);
|
|
143330
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_unique ON workspace_members(project_path);
|
|
143331
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_name ON workspace_members(workspace_id, display_name);
|
|
143332
|
+
|
|
143278
143333
|
CREATE TABLE IF NOT EXISTS v22_backfill_failures (
|
|
143279
143334
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
143280
143335
|
table_name TEXT NOT NULL,
|
|
@@ -143386,6 +143441,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143386
143441
|
deferred_execute_state TEXT,
|
|
143387
143442
|
cached_m0_bytes BLOB,
|
|
143388
143443
|
cached_m0_project_memory_epoch INTEGER,
|
|
143444
|
+
cached_m0_workspace_fingerprint TEXT,
|
|
143389
143445
|
cached_m0_project_user_profile_version INTEGER,
|
|
143390
143446
|
cached_m0_max_compartment_seq INTEGER,
|
|
143391
143447
|
cached_m0_max_memory_id INTEGER,
|
|
@@ -143544,6 +143600,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143544
143600
|
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
143545
143601
|
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
143546
143602
|
ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
|
|
143603
|
+
ensureColumn(db, "session_meta", "processed_image_stripped_ids", "TEXT DEFAULT ''");
|
|
143547
143604
|
ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
|
|
143548
143605
|
ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
|
|
143549
143606
|
ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
|
|
@@ -143597,6 +143654,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143597
143654
|
ensureColumn(db, "memories", "importance", "INTEGER");
|
|
143598
143655
|
ensureColumn(db, "session_meta", "cached_m0_bytes", "BLOB");
|
|
143599
143656
|
ensureColumn(db, "session_meta", "cached_m0_project_memory_epoch", "INTEGER");
|
|
143657
|
+
ensureColumn(db, "session_meta", "cached_m0_workspace_fingerprint", "TEXT");
|
|
143600
143658
|
ensureColumn(db, "session_meta", "cached_m0_project_user_profile_version", "INTEGER");
|
|
143601
143659
|
ensureColumn(db, "session_meta", "cached_m0_max_compartment_seq", "INTEGER");
|
|
143602
143660
|
ensureColumn(db, "session_meta", "cached_m0_max_memory_id", "INTEGER");
|
|
@@ -143628,6 +143686,15 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143628
143686
|
project_user_profile_version INTEGER NOT NULL DEFAULT 0,
|
|
143629
143687
|
updated_at INTEGER NOT NULL DEFAULT 0
|
|
143630
143688
|
);
|
|
143689
|
+
CREATE TABLE IF NOT EXISTS session_projects (
|
|
143690
|
+
session_id TEXT NOT NULL,
|
|
143691
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
143692
|
+
project_path TEXT NOT NULL,
|
|
143693
|
+
updated_at INTEGER NOT NULL,
|
|
143694
|
+
PRIMARY KEY(session_id, harness)
|
|
143695
|
+
);
|
|
143696
|
+
CREATE INDEX IF NOT EXISTS idx_session_projects_project
|
|
143697
|
+
ON session_projects(project_path);
|
|
143631
143698
|
CREATE TABLE IF NOT EXISTS m0_mutation_log (
|
|
143632
143699
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
143633
143700
|
session_id TEXT NOT NULL,
|
|
@@ -143655,6 +143722,23 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143655
143722
|
new_project_path TEXT NOT NULL,
|
|
143656
143723
|
rekeyed_at INTEGER NOT NULL
|
|
143657
143724
|
);
|
|
143725
|
+
CREATE TABLE IF NOT EXISTS workspaces (
|
|
143726
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
143727
|
+
name TEXT NOT NULL UNIQUE,
|
|
143728
|
+
created_at INTEGER NOT NULL,
|
|
143729
|
+
updated_at INTEGER NOT NULL,
|
|
143730
|
+
share_categories TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'
|
|
143731
|
+
);
|
|
143732
|
+
CREATE TABLE IF NOT EXISTS workspace_members (
|
|
143733
|
+
workspace_id INTEGER NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
143734
|
+
project_path TEXT NOT NULL,
|
|
143735
|
+
display_name TEXT NOT NULL,
|
|
143736
|
+
display_path TEXT NOT NULL,
|
|
143737
|
+
added_at INTEGER NOT NULL,
|
|
143738
|
+
PRIMARY KEY (workspace_id, project_path)
|
|
143739
|
+
);
|
|
143740
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_unique ON workspace_members(project_path);
|
|
143741
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_name ON workspace_members(workspace_id, display_name);
|
|
143658
143742
|
CREATE TABLE IF NOT EXISTS v22_backfill_failures (
|
|
143659
143743
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
143660
143744
|
table_name TEXT NOT NULL,
|
|
@@ -143676,6 +143760,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143676
143760
|
ensureColumn(db, "recomp_compartments", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
143677
143761
|
ensureColumn(db, "recomp_facts", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
143678
143762
|
ensureColumn(db, "message_history_index", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
143763
|
+
ensureColumn(db, "workspaces", "share_categories", `TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'`);
|
|
143679
143764
|
}
|
|
143680
143765
|
function healAllNullColumns(db) {
|
|
143681
143766
|
healNullTextColumns(db);
|
|
@@ -143714,6 +143799,7 @@ function healNullTextColumns(db) {
|
|
|
143714
143799
|
["system_prompt_hash", ""],
|
|
143715
143800
|
["stripped_placeholder_ids", ""],
|
|
143716
143801
|
["stale_reduce_stripped_ids", ""],
|
|
143802
|
+
["processed_image_stripped_ids", ""],
|
|
143717
143803
|
["memory_block_cache", ""],
|
|
143718
143804
|
["memory_block_ids", ""],
|
|
143719
143805
|
["compaction_marker_state", ""],
|
|
@@ -143758,7 +143844,7 @@ function healNullIntegerColumns(db) {
|
|
|
143758
143844
|
}
|
|
143759
143845
|
}
|
|
143760
143846
|
function ensureColumn(db, table, column, definition) {
|
|
143761
|
-
if (!/^[a-z][a-z0-9_]*$/.test(table) || !/^[a-z][a-z0-9_]*$/.test(column) || !/^[A-Z0-9_'(),[\]\s]+$/i.test(definition)) {
|
|
143847
|
+
if (!/^[a-z][a-z0-9_]*$/.test(table) || !/^[a-z][a-z0-9_]*$/.test(column) || !/^[A-Z0-9_"'(),[\]\s]+$/i.test(definition)) {
|
|
143762
143848
|
throw new Error(`Unsafe schema identifier: ${table}.${column} ${definition}`);
|
|
143763
143849
|
}
|
|
143764
143850
|
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
@@ -143835,10 +143921,291 @@ function openDatabase(dbPathOrOptions) {
|
|
|
143835
143921
|
}
|
|
143836
143922
|
}
|
|
143837
143923
|
|
|
143924
|
+
// ../plugin/src/features/magic-context/workspaces.ts
|
|
143925
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
143926
|
+
|
|
143927
|
+
// ../plugin/src/features/magic-context/memory/constants.ts
|
|
143928
|
+
var V2_MEMORY_CATEGORIES = [
|
|
143929
|
+
"PROJECT_RULES",
|
|
143930
|
+
"ARCHITECTURE",
|
|
143931
|
+
"CONSTRAINTS",
|
|
143932
|
+
"CONFIG_VALUES",
|
|
143933
|
+
"NAMING"
|
|
143934
|
+
];
|
|
143935
|
+
var PROMOTABLE_CATEGORIES = [
|
|
143936
|
+
"PROJECT_RULES",
|
|
143937
|
+
"ARCHITECTURE",
|
|
143938
|
+
"CONSTRAINTS",
|
|
143939
|
+
"CONFIG_VALUES",
|
|
143940
|
+
"NAMING",
|
|
143941
|
+
"ARCHITECTURE_DECISIONS",
|
|
143942
|
+
"CONFIG_DEFAULTS",
|
|
143943
|
+
"USER_PREFERENCES",
|
|
143944
|
+
"USER_DIRECTIVES",
|
|
143945
|
+
"ENVIRONMENT",
|
|
143946
|
+
"WORKFLOW_RULES",
|
|
143947
|
+
"KNOWN_ISSUES"
|
|
143948
|
+
];
|
|
143949
|
+
var CATEGORY_PRIORITY = [
|
|
143950
|
+
"PROJECT_RULES",
|
|
143951
|
+
"ARCHITECTURE",
|
|
143952
|
+
"CONSTRAINTS",
|
|
143953
|
+
"CONFIG_VALUES",
|
|
143954
|
+
"NAMING",
|
|
143955
|
+
"USER_DIRECTIVES",
|
|
143956
|
+
"USER_PREFERENCES",
|
|
143957
|
+
"CONFIG_DEFAULTS",
|
|
143958
|
+
"ARCHITECTURE_DECISIONS",
|
|
143959
|
+
"ENVIRONMENT",
|
|
143960
|
+
"WORKFLOW_RULES",
|
|
143961
|
+
"KNOWN_ISSUES"
|
|
143962
|
+
];
|
|
143963
|
+
var MEMORY_CATEGORY_ORDER_UNKNOWN = 99;
|
|
143964
|
+
var MEMORY_CATEGORY_ORDER_PRIORITY = CATEGORY_PRIORITY.reduce((acc, category, index) => {
|
|
143965
|
+
acc[category] = index;
|
|
143966
|
+
return acc;
|
|
143967
|
+
}, {});
|
|
143968
|
+
var MEMORY_CATEGORY_ORDER_SQL = `CASE category ${CATEGORY_PRIORITY.map((category, index) => `WHEN '${category}' THEN ${index}`).join(" ")} ELSE ${MEMORY_CATEGORY_ORDER_UNKNOWN} END`;
|
|
143969
|
+
var CATEGORY_DEFAULT_TTL = {
|
|
143970
|
+
WORKFLOW_RULES: 90 * 24 * 60 * 60 * 1000,
|
|
143971
|
+
KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
|
|
143972
|
+
};
|
|
143973
|
+
// ../plugin/src/features/magic-context/workspaces.ts
|
|
143974
|
+
var VALID_SHARE_CATEGORIES = new Set(V2_MEMORY_CATEGORIES);
|
|
143975
|
+
function tableExists(db, tableName) {
|
|
143976
|
+
const row = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name = ? LIMIT 1").get(tableName);
|
|
143977
|
+
return Boolean(row);
|
|
143978
|
+
}
|
|
143979
|
+
function columnExists(db, tableName, columnName) {
|
|
143980
|
+
const rows = db.prepare(`PRAGMA table_info(${tableName})`).all();
|
|
143981
|
+
return rows.some((row) => row.name === columnName);
|
|
143982
|
+
}
|
|
143983
|
+
function uniqueSorted(values) {
|
|
143984
|
+
return [...new Set(values)].sort((left, right) => left.localeCompare(right));
|
|
143985
|
+
}
|
|
143986
|
+
function placeholders(values) {
|
|
143987
|
+
return values.map(() => "?").join(", ");
|
|
143988
|
+
}
|
|
143989
|
+
function normalizeShareCategories(raw) {
|
|
143990
|
+
if (raw === null || raw === undefined)
|
|
143991
|
+
return null;
|
|
143992
|
+
if (typeof raw !== "string")
|
|
143993
|
+
return null;
|
|
143994
|
+
let parsed;
|
|
143995
|
+
try {
|
|
143996
|
+
parsed = JSON.parse(raw);
|
|
143997
|
+
} catch {
|
|
143998
|
+
return null;
|
|
143999
|
+
}
|
|
144000
|
+
if (!Array.isArray(parsed))
|
|
144001
|
+
return null;
|
|
144002
|
+
const categories = [];
|
|
144003
|
+
for (const value of parsed) {
|
|
144004
|
+
if (typeof value !== "string" || !VALID_SHARE_CATEGORIES.has(value)) {
|
|
144005
|
+
return null;
|
|
144006
|
+
}
|
|
144007
|
+
if (!categories.includes(value))
|
|
144008
|
+
categories.push(value);
|
|
144009
|
+
}
|
|
144010
|
+
return categories.sort((left, right) => left.localeCompare(right));
|
|
144011
|
+
}
|
|
144012
|
+
function selectWorkspaceShareCategories(db, identities) {
|
|
144013
|
+
const candidates = uniqueSorted(identities.filter((identity) => identity.length > 0));
|
|
144014
|
+
if (candidates.length === 0 || !tableExists(db, "workspace_members") || !tableExists(db, "workspaces") || !columnExists(db, "workspaces", "share_categories")) {
|
|
144015
|
+
return null;
|
|
144016
|
+
}
|
|
144017
|
+
const row = db.prepare(`SELECT workspace.share_categories AS shareCategories
|
|
144018
|
+
FROM workspace_members AS member
|
|
144019
|
+
JOIN workspaces AS workspace ON workspace.id = member.workspace_id
|
|
144020
|
+
WHERE member.project_path IN (${placeholders(candidates)})
|
|
144021
|
+
ORDER BY workspace.id ASC
|
|
144022
|
+
LIMIT 1`).get(...candidates);
|
|
144023
|
+
return normalizeShareCategories(row?.shareCategories ?? null);
|
|
144024
|
+
}
|
|
144025
|
+
function resolveWorkspaceShareCategories(db, projectIdentity) {
|
|
144026
|
+
return selectWorkspaceShareCategories(db, [projectIdentity]);
|
|
144027
|
+
}
|
|
144028
|
+
function resolveWorkspaceIdentitySet(db, projectIdentity) {
|
|
144029
|
+
if (!tableExists(db, "workspace_members")) {
|
|
144030
|
+
return { identities: [projectIdentity], namesByIdentity: new Map };
|
|
144031
|
+
}
|
|
144032
|
+
const rows = db.prepare(`SELECT member.project_path AS identity, member.display_name AS displayName
|
|
144033
|
+
FROM workspace_members AS anchor
|
|
144034
|
+
JOIN workspace_members AS member ON member.workspace_id = anchor.workspace_id
|
|
144035
|
+
WHERE anchor.project_path = ?
|
|
144036
|
+
ORDER BY member.display_name ASC, member.project_path ASC`).all(projectIdentity);
|
|
144037
|
+
if (rows.length === 0) {
|
|
144038
|
+
return { identities: [projectIdentity], namesByIdentity: new Map };
|
|
144039
|
+
}
|
|
144040
|
+
const namesByIdentity = new Map;
|
|
144041
|
+
const identities = [];
|
|
144042
|
+
for (const row of rows) {
|
|
144043
|
+
if (typeof row.identity !== "string" || row.identity.length === 0)
|
|
144044
|
+
continue;
|
|
144045
|
+
if (identities.includes(row.identity))
|
|
144046
|
+
continue;
|
|
144047
|
+
identities.push(row.identity);
|
|
144048
|
+
if (typeof row.displayName === "string" && row.displayName.length > 0) {
|
|
144049
|
+
namesByIdentity.set(row.identity, row.displayName);
|
|
144050
|
+
}
|
|
144051
|
+
}
|
|
144052
|
+
return identities.length > 0 ? { identities, namesByIdentity } : { identities: [projectIdentity], namesByIdentity: new Map };
|
|
144053
|
+
}
|
|
144054
|
+
function expandWorkspaceIdentitySetWithAliases(db, identities) {
|
|
144055
|
+
const canonical = uniqueSorted(identities.filter((identity) => identity.length > 0));
|
|
144056
|
+
const expanded = new Set(canonical);
|
|
144057
|
+
const canonicalIdentityByStoredPath = new Map;
|
|
144058
|
+
for (const identity of canonical) {
|
|
144059
|
+
canonicalIdentityByStoredPath.set(identity, identity);
|
|
144060
|
+
}
|
|
144061
|
+
if (canonical.length === 0 || !tableExists(db, "v22_identity_rekey_map")) {
|
|
144062
|
+
return { expandedIdentities: [...expanded], canonicalIdentityByStoredPath };
|
|
144063
|
+
}
|
|
144064
|
+
const rows = db.prepare(`SELECT old_project_path AS oldProjectPath, new_project_path AS newProjectPath
|
|
144065
|
+
FROM v22_identity_rekey_map
|
|
144066
|
+
WHERE new_project_path IN (${placeholders(canonical)})
|
|
144067
|
+
ORDER BY old_project_path ASC`).all(...canonical);
|
|
144068
|
+
for (const row of rows) {
|
|
144069
|
+
if (typeof row.oldProjectPath !== "string" || typeof row.newProjectPath !== "string") {
|
|
144070
|
+
continue;
|
|
144071
|
+
}
|
|
144072
|
+
if (!canonicalIdentityByStoredPath.has(row.newProjectPath))
|
|
144073
|
+
continue;
|
|
144074
|
+
expanded.add(row.oldProjectPath);
|
|
144075
|
+
canonicalIdentityByStoredPath.set(row.oldProjectPath, row.newProjectPath);
|
|
144076
|
+
}
|
|
144077
|
+
return { expandedIdentities: [...expanded], canonicalIdentityByStoredPath };
|
|
144078
|
+
}
|
|
144079
|
+
function resolveStoredPathWorkspaceIdentity(storedProjectPath, memberIdentities, canonicalIdentityByStoredPath) {
|
|
144080
|
+
const direct = canonicalIdentityByStoredPath.get(storedProjectPath);
|
|
144081
|
+
if (direct)
|
|
144082
|
+
return direct;
|
|
144083
|
+
const normalized = normalizeStoredProjectPath(storedProjectPath);
|
|
144084
|
+
const normalizedDirect = canonicalIdentityByStoredPath.get(normalized);
|
|
144085
|
+
if (normalizedDirect)
|
|
144086
|
+
return normalizedDirect;
|
|
144087
|
+
if (memberIdentities.includes(normalized))
|
|
144088
|
+
return normalized;
|
|
144089
|
+
for (const identity of memberIdentities) {
|
|
144090
|
+
if (storedPathBelongsToIdentity(storedProjectPath, identity)) {
|
|
144091
|
+
return identity;
|
|
144092
|
+
}
|
|
144093
|
+
}
|
|
144094
|
+
return null;
|
|
144095
|
+
}
|
|
144096
|
+
function storedPathBelongsToWorkspace(storedProjectPath, memberIdentities, expandedIdentities, canonicalIdentityByStoredPath) {
|
|
144097
|
+
if (expandedIdentities.includes(storedProjectPath))
|
|
144098
|
+
return true;
|
|
144099
|
+
return resolveStoredPathWorkspaceIdentity(storedProjectPath, memberIdentities, canonicalIdentityByStoredPath) !== null;
|
|
144100
|
+
}
|
|
144101
|
+
function sourceNameForMemory(storedProjectPath, ownIdentity, memberIdentities, namesByIdentity, canonicalIdentityByStoredPath) {
|
|
144102
|
+
const canonicalIdentity = resolveStoredPathWorkspaceIdentity(storedProjectPath, memberIdentities, canonicalIdentityByStoredPath);
|
|
144103
|
+
if (!canonicalIdentity || canonicalIdentity === ownIdentity)
|
|
144104
|
+
return;
|
|
144105
|
+
return namesByIdentity.get(canonicalIdentity);
|
|
144106
|
+
}
|
|
144107
|
+
function getEpochMap(db, identities) {
|
|
144108
|
+
if (identities.length === 0)
|
|
144109
|
+
return new Map;
|
|
144110
|
+
const rows = db.prepare(`SELECT project_path AS projectPath, project_memory_epoch AS epoch
|
|
144111
|
+
FROM project_state
|
|
144112
|
+
WHERE project_path IN (${placeholders(identities)})`).all(...identities);
|
|
144113
|
+
const epochs = new Map;
|
|
144114
|
+
for (const row of rows) {
|
|
144115
|
+
if (typeof row.projectPath !== "string" || typeof row.epoch !== "number")
|
|
144116
|
+
continue;
|
|
144117
|
+
epochs.set(row.projectPath, row.epoch);
|
|
144118
|
+
}
|
|
144119
|
+
return epochs;
|
|
144120
|
+
}
|
|
144121
|
+
function computeWorkspaceEpochFingerprint(db, identities) {
|
|
144122
|
+
const canonical = uniqueSorted(identities.filter((identity) => identity.length > 0));
|
|
144123
|
+
const epochs = getEpochMap(db, canonical);
|
|
144124
|
+
const shareCategories = selectWorkspaceShareCategories(db, canonical);
|
|
144125
|
+
const hash = createHash3("sha256");
|
|
144126
|
+
hash.update("share_categories", "utf8");
|
|
144127
|
+
hash.update("\x00");
|
|
144128
|
+
hash.update(shareCategories === null ? "ALL" : JSON.stringify(shareCategories), "utf8");
|
|
144129
|
+
hash.update(`
|
|
144130
|
+
`);
|
|
144131
|
+
for (const identity of canonical) {
|
|
144132
|
+
hash.update(identity, "utf8");
|
|
144133
|
+
hash.update("\x00");
|
|
144134
|
+
hash.update(String(epochs.get(identity) ?? 0), "utf8");
|
|
144135
|
+
hash.update(`
|
|
144136
|
+
`);
|
|
144137
|
+
}
|
|
144138
|
+
return hash.digest("hex");
|
|
144139
|
+
}
|
|
144140
|
+
function isInTransaction(db) {
|
|
144141
|
+
const candidate = db;
|
|
144142
|
+
return candidate.inTransaction === true || candidate.isTransaction === true;
|
|
144143
|
+
}
|
|
144144
|
+
function workspaceMembersForIdentity(db, identity) {
|
|
144145
|
+
if (!tableExists(db, "workspace_members"))
|
|
144146
|
+
return [identity];
|
|
144147
|
+
const rows = db.prepare(`SELECT member.project_path AS identity
|
|
144148
|
+
FROM workspace_members AS anchor
|
|
144149
|
+
JOIN workspace_members AS member ON member.workspace_id = anchor.workspace_id
|
|
144150
|
+
WHERE anchor.project_path = ?
|
|
144151
|
+
ORDER BY member.project_path ASC`).all(identity);
|
|
144152
|
+
const identities = rows.map((row) => typeof row.identity === "string" ? row.identity : "").filter((value) => value.length > 0);
|
|
144153
|
+
return identities.length > 0 ? uniqueSorted(identities) : [identity];
|
|
144154
|
+
}
|
|
144155
|
+
function bumpEpochRows(db, identities, now) {
|
|
144156
|
+
const stmt = db.prepare(`INSERT INTO project_state
|
|
144157
|
+
(project_path, project_memory_epoch, project_user_profile_version, updated_at)
|
|
144158
|
+
VALUES (?, 1, 0, ?)
|
|
144159
|
+
ON CONFLICT(project_path) DO UPDATE SET
|
|
144160
|
+
project_memory_epoch = project_memory_epoch + 1,
|
|
144161
|
+
updated_at = excluded.updated_at`);
|
|
144162
|
+
for (const identity of uniqueSorted(identities)) {
|
|
144163
|
+
stmt.run(identity, now);
|
|
144164
|
+
}
|
|
144165
|
+
}
|
|
144166
|
+
function bumpEpochsForWorkspaceMembers(db, identity, now = Date.now()) {
|
|
144167
|
+
const run = () => bumpEpochRows(db, workspaceMembersForIdentity(db, identity), now);
|
|
144168
|
+
if (isInTransaction(db)) {
|
|
144169
|
+
run();
|
|
144170
|
+
return;
|
|
144171
|
+
}
|
|
144172
|
+
db.exec("BEGIN IMMEDIATE");
|
|
144173
|
+
try {
|
|
144174
|
+
run();
|
|
144175
|
+
db.exec("COMMIT");
|
|
144176
|
+
} catch (error) {
|
|
144177
|
+
try {
|
|
144178
|
+
db.exec("ROLLBACK");
|
|
144179
|
+
} catch {}
|
|
144180
|
+
throw error;
|
|
144181
|
+
}
|
|
144182
|
+
}
|
|
144183
|
+
function bumpEpochsForWorkspaceMemberSet(db, identities, now = Date.now()) {
|
|
144184
|
+
const run = () => bumpEpochRows(db, identities, now);
|
|
144185
|
+
if (isInTransaction(db)) {
|
|
144186
|
+
run();
|
|
144187
|
+
return;
|
|
144188
|
+
}
|
|
144189
|
+
db.exec("BEGIN IMMEDIATE");
|
|
144190
|
+
try {
|
|
144191
|
+
run();
|
|
144192
|
+
db.exec("COMMIT");
|
|
144193
|
+
} catch (error) {
|
|
144194
|
+
try {
|
|
144195
|
+
db.exec("ROLLBACK");
|
|
144196
|
+
} catch {}
|
|
144197
|
+
throw error;
|
|
144198
|
+
}
|
|
144199
|
+
}
|
|
144200
|
+
|
|
143838
144201
|
// ../plugin/src/features/magic-context/migrations.ts
|
|
143839
|
-
function
|
|
144202
|
+
function tableExists2(db, name2) {
|
|
143840
144203
|
return Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(name2));
|
|
143841
144204
|
}
|
|
144205
|
+
function columnExists2(db, table, column) {
|
|
144206
|
+
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
144207
|
+
return rows.some((row) => row.name === column);
|
|
144208
|
+
}
|
|
143842
144209
|
var MIGRATIONS = [
|
|
143843
144210
|
{
|
|
143844
144211
|
version: 1,
|
|
@@ -144297,9 +144664,9 @@ var MIGRATIONS = [
|
|
|
144297
144664
|
version: 22,
|
|
144298
144665
|
description: "v2.0 cache architecture schema foundation",
|
|
144299
144666
|
up: (db) => {
|
|
144300
|
-
const hasSessionMetaTable =
|
|
144301
|
-
const hasCompartmentsTable =
|
|
144302
|
-
const hasMemoriesTable =
|
|
144667
|
+
const hasSessionMetaTable = tableExists2(db, "session_meta");
|
|
144668
|
+
const hasCompartmentsTable = tableExists2(db, "compartments");
|
|
144669
|
+
const hasMemoriesTable = tableExists2(db, "memories");
|
|
144303
144670
|
if (hasSessionMetaTable) {
|
|
144304
144671
|
ensureColumn(db, "session_meta", "cached_m0_bytes", "BLOB");
|
|
144305
144672
|
ensureColumn(db, "session_meta", "cached_m0_project_memory_epoch", "INTEGER");
|
|
@@ -144324,7 +144691,7 @@ var MIGRATIONS = [
|
|
|
144324
144691
|
ensureColumn(db, "compartments", "p1_embedding_model_id", "TEXT");
|
|
144325
144692
|
ensureColumn(db, "compartments", "legacy", "INTEGER NOT NULL DEFAULT 0");
|
|
144326
144693
|
}
|
|
144327
|
-
const hasRecompCompartmentsTable =
|
|
144694
|
+
const hasRecompCompartmentsTable = tableExists2(db, "recomp_compartments");
|
|
144328
144695
|
if (hasRecompCompartmentsTable) {
|
|
144329
144696
|
ensureColumn(db, "recomp_compartments", "p1", "TEXT");
|
|
144330
144697
|
ensureColumn(db, "recomp_compartments", "p2", "TEXT");
|
|
@@ -144635,6 +145002,156 @@ var MIGRATIONS = [
|
|
|
144635
145002
|
db.prepare("UPDATE session_meta SET force_emergency_bypass_used = 0 WHERE force_emergency_bypass_used IS NULL").run();
|
|
144636
145003
|
db.prepare("UPDATE session_meta SET last_usage_context_limit = 0 WHERE last_usage_context_limit IS NULL").run();
|
|
144637
145004
|
}
|
|
145005
|
+
},
|
|
145006
|
+
{
|
|
145007
|
+
version: 33,
|
|
145008
|
+
description: "Compartment chunk embeddings for semantic message-history search",
|
|
145009
|
+
up: (db) => {
|
|
145010
|
+
db.exec(`
|
|
145011
|
+
CREATE TABLE IF NOT EXISTS compartment_chunk_embeddings (
|
|
145012
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
145013
|
+
compartment_id INTEGER NOT NULL REFERENCES compartments(id) ON DELETE CASCADE,
|
|
145014
|
+
session_id TEXT NOT NULL,
|
|
145015
|
+
project_path TEXT NOT NULL,
|
|
145016
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
145017
|
+
window_index INTEGER NOT NULL DEFAULT 0,
|
|
145018
|
+
start_ordinal INTEGER NOT NULL,
|
|
145019
|
+
end_ordinal INTEGER NOT NULL,
|
|
145020
|
+
chunk_hash TEXT NOT NULL,
|
|
145021
|
+
model_id TEXT NOT NULL,
|
|
145022
|
+
dims INTEGER NOT NULL,
|
|
145023
|
+
vector BLOB NOT NULL,
|
|
145024
|
+
created_at INTEGER NOT NULL,
|
|
145025
|
+
UNIQUE(compartment_id, window_index)
|
|
145026
|
+
);
|
|
145027
|
+
CREATE INDEX IF NOT EXISTS idx_cce_session
|
|
145028
|
+
ON compartment_chunk_embeddings(session_id);
|
|
145029
|
+
CREATE INDEX IF NOT EXISTS idx_cce_project_model
|
|
145030
|
+
ON compartment_chunk_embeddings(project_path, model_id);
|
|
145031
|
+
`);
|
|
145032
|
+
}
|
|
145033
|
+
},
|
|
145034
|
+
{
|
|
145035
|
+
version: 34,
|
|
145036
|
+
description: "workspace tables and m[0] workspace fingerprint cache reset",
|
|
145037
|
+
up: (db) => {
|
|
145038
|
+
db.exec(`
|
|
145039
|
+
CREATE TABLE IF NOT EXISTS workspaces (
|
|
145040
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
145041
|
+
name TEXT NOT NULL UNIQUE,
|
|
145042
|
+
created_at INTEGER NOT NULL,
|
|
145043
|
+
updated_at INTEGER NOT NULL
|
|
145044
|
+
);
|
|
145045
|
+
CREATE TABLE IF NOT EXISTS workspace_members (
|
|
145046
|
+
workspace_id INTEGER NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
145047
|
+
project_path TEXT NOT NULL,
|
|
145048
|
+
display_name TEXT NOT NULL,
|
|
145049
|
+
display_path TEXT NOT NULL,
|
|
145050
|
+
added_at INTEGER NOT NULL,
|
|
145051
|
+
PRIMARY KEY (workspace_id, project_path)
|
|
145052
|
+
);
|
|
145053
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_unique
|
|
145054
|
+
ON workspace_members(project_path);
|
|
145055
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_name
|
|
145056
|
+
ON workspace_members(workspace_id, display_name);
|
|
145057
|
+
`);
|
|
145058
|
+
const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta' LIMIT 1").get();
|
|
145059
|
+
if (!hasSessionMeta)
|
|
145060
|
+
return;
|
|
145061
|
+
ensureColumn(db, "session_meta", "cached_m0_workspace_fingerprint", "TEXT");
|
|
145062
|
+
const columns = new Set(db.prepare("PRAGMA table_info(session_meta)").all().map((column) => column.name));
|
|
145063
|
+
const clears = [
|
|
145064
|
+
["cached_m0_bytes", null],
|
|
145065
|
+
["cached_m1_bytes", null],
|
|
145066
|
+
["cached_m0_project_memory_epoch", null],
|
|
145067
|
+
["cached_m0_workspace_fingerprint", null],
|
|
145068
|
+
["cached_m0_project_user_profile_version", null],
|
|
145069
|
+
["cached_m0_max_compartment_seq", null],
|
|
145070
|
+
["cached_m0_max_memory_id", null],
|
|
145071
|
+
["cached_m0_max_mutation_id", null],
|
|
145072
|
+
["cached_m0_max_memory_mutation_id", null],
|
|
145073
|
+
["cached_m0_project_docs_hash", null],
|
|
145074
|
+
["cached_m0_materialized_at", null],
|
|
145075
|
+
["cached_m0_session_facts_version", null],
|
|
145076
|
+
["cached_m0_upgrade_state", null],
|
|
145077
|
+
["cached_m0_system_hash", null],
|
|
145078
|
+
["cached_m0_tool_set_hash", null],
|
|
145079
|
+
["cached_m0_model_key", null],
|
|
145080
|
+
["cached_m0_last_baseline_end_message_id", null],
|
|
145081
|
+
["memory_block_cache", ""],
|
|
145082
|
+
["memory_block_ids", ""],
|
|
145083
|
+
["memory_block_count", 0]
|
|
145084
|
+
];
|
|
145085
|
+
const setClauses = [];
|
|
145086
|
+
const values = [];
|
|
145087
|
+
for (const [column, value] of clears) {
|
|
145088
|
+
if (!columns.has(column))
|
|
145089
|
+
continue;
|
|
145090
|
+
setClauses.push(`${column} = ?`);
|
|
145091
|
+
values.push(value);
|
|
145092
|
+
}
|
|
145093
|
+
if (setClauses.length > 0) {
|
|
145094
|
+
db.prepare(`UPDATE session_meta SET ${setClauses.join(", ")}`).run(...values);
|
|
145095
|
+
}
|
|
145096
|
+
}
|
|
145097
|
+
},
|
|
145098
|
+
{
|
|
145099
|
+
version: 35,
|
|
145100
|
+
description: "workspace per-category share defaults and epoch refresh",
|
|
145101
|
+
up: (db) => {
|
|
145102
|
+
db.exec(`
|
|
145103
|
+
CREATE TABLE IF NOT EXISTS workspaces (
|
|
145104
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
145105
|
+
name TEXT NOT NULL UNIQUE,
|
|
145106
|
+
created_at INTEGER NOT NULL,
|
|
145107
|
+
updated_at INTEGER NOT NULL,
|
|
145108
|
+
share_categories TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'
|
|
145109
|
+
);
|
|
145110
|
+
`);
|
|
145111
|
+
if (!columnExists2(db, "workspaces", "share_categories")) {
|
|
145112
|
+
db.exec(`ALTER TABLE workspaces ADD COLUMN share_categories TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'`);
|
|
145113
|
+
}
|
|
145114
|
+
db.prepare(`UPDATE workspaces
|
|
145115
|
+
SET share_categories = '["CONSTRAINTS"]'
|
|
145116
|
+
WHERE share_categories IS NULL OR share_categories = ''`).run();
|
|
145117
|
+
if (!tableExists2(db, "workspace_members"))
|
|
145118
|
+
return;
|
|
145119
|
+
const rows = db.prepare(`SELECT DISTINCT project_path AS identity
|
|
145120
|
+
FROM workspace_members
|
|
145121
|
+
WHERE project_path IS NOT NULL AND project_path <> ''
|
|
145122
|
+
ORDER BY project_path ASC`).all();
|
|
145123
|
+
const identities = rows.map((row) => typeof row.identity === "string" ? row.identity : "").filter((identity) => identity.length > 0);
|
|
145124
|
+
if (identities.length > 0) {
|
|
145125
|
+
bumpEpochsForWorkspaceMemberSet(db, identities, Date.now());
|
|
145126
|
+
}
|
|
145127
|
+
}
|
|
145128
|
+
},
|
|
145129
|
+
{
|
|
145130
|
+
version: 36,
|
|
145131
|
+
description: "session project ownership map for compartment chunk backfill scoping",
|
|
145132
|
+
up: (db) => {
|
|
145133
|
+
db.exec(`
|
|
145134
|
+
CREATE TABLE IF NOT EXISTS session_projects (
|
|
145135
|
+
session_id TEXT NOT NULL,
|
|
145136
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
145137
|
+
project_path TEXT NOT NULL,
|
|
145138
|
+
updated_at INTEGER NOT NULL,
|
|
145139
|
+
PRIMARY KEY(session_id, harness)
|
|
145140
|
+
);
|
|
145141
|
+
CREATE INDEX IF NOT EXISTS idx_session_projects_project
|
|
145142
|
+
ON session_projects(project_path);
|
|
145143
|
+
`);
|
|
145144
|
+
const hasChunkTable = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='compartment_chunk_embeddings'").get();
|
|
145145
|
+
if (hasChunkTable) {
|
|
145146
|
+
db.exec(`
|
|
145147
|
+
INSERT OR IGNORE INTO session_projects (session_id, harness, project_path, updated_at)
|
|
145148
|
+
SELECT session_id, harness, MIN(project_path), 0
|
|
145149
|
+
FROM compartment_chunk_embeddings
|
|
145150
|
+
GROUP BY session_id, harness
|
|
145151
|
+
HAVING COUNT(DISTINCT project_path) = 1;
|
|
145152
|
+
`);
|
|
145153
|
+
}
|
|
145154
|
+
}
|
|
144638
145155
|
}
|
|
144639
145156
|
];
|
|
144640
145157
|
var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -144704,7 +145221,7 @@ function runMigrations(db) {
|
|
|
144704
145221
|
log(`[migrations] schema version now: ${MIGRATIONS[MIGRATIONS.length - 1].version}`);
|
|
144705
145222
|
}
|
|
144706
145223
|
// ../plugin/src/features/magic-context/project-docs-hash.ts
|
|
144707
|
-
import { createHash as
|
|
145224
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
144708
145225
|
import { lstatSync, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
|
|
144709
145226
|
import path4 from "node:path";
|
|
144710
145227
|
var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
@@ -144802,7 +145319,7 @@ function hashCanonicalPieces(hashPieces) {
|
|
|
144802
145319
|
if (hashPieces.length === 0) {
|
|
144803
145320
|
return "";
|
|
144804
145321
|
}
|
|
144805
|
-
return
|
|
145322
|
+
return createHash4("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
|
|
144806
145323
|
}
|
|
144807
145324
|
function readProjectDocsCanonical(projectDirectory) {
|
|
144808
145325
|
const canonicalDirectory = path4.resolve(projectDirectory);
|
|
@@ -144908,18 +145425,13 @@ function getMemoryMutation(db, id) {
|
|
|
144908
145425
|
WHERE id = ?`).get(id);
|
|
144909
145426
|
return row ? toMemoryMutation(row) : null;
|
|
144910
145427
|
}
|
|
144911
|
-
function
|
|
144912
|
-
|
|
144913
|
-
|
|
144914
|
-
|
|
144915
|
-
|
|
144916
|
-
|
|
144917
|
-
|
|
144918
|
-
FROM memory_mutation_log
|
|
144919
|
-
WHERE project_path = ?
|
|
144920
|
-
AND id > ?
|
|
144921
|
-
AND target_memory_id IN (${placeholders})
|
|
144922
|
-
ORDER BY id ASC`).all(projectPath, afterId ?? 0, ...uniqueIds);
|
|
145428
|
+
function uniqueProjectPaths(projectPaths) {
|
|
145429
|
+
return [...new Set(projectPaths.filter((path5) => path5.length > 0))];
|
|
145430
|
+
}
|
|
145431
|
+
function placeholders2(values) {
|
|
145432
|
+
return values.map(() => "?").join(", ");
|
|
145433
|
+
}
|
|
145434
|
+
function coalesceMutations(rows) {
|
|
144923
145435
|
const chosenByTarget = new Map;
|
|
144924
145436
|
for (const dbRow of rows) {
|
|
144925
145437
|
const candidate = toMemoryMutation(dbRow);
|
|
@@ -144940,10 +145452,54 @@ function getMemoryMutationsForRender(db, projectPath, afterId, renderedMemoryIds
|
|
|
144940
145452
|
}
|
|
144941
145453
|
return [...chosenByTarget.values()].sort((left, right) => left.id - right.id);
|
|
144942
145454
|
}
|
|
145455
|
+
function getMemoryMutationsForRender(db, projectPath, afterId, renderedMemoryIds) {
|
|
145456
|
+
if (renderedMemoryIds.length === 0)
|
|
145457
|
+
return [];
|
|
145458
|
+
const uniqueIds = [...new Set(renderedMemoryIds)].sort((left, right) => left - right);
|
|
145459
|
+
const placeholders3 = uniqueIds.map(() => "?").join(", ");
|
|
145460
|
+
const rows = db.prepare(`SELECT id, project_path, mutation_type, target_memory_id,
|
|
145461
|
+
superseded_by_id, category, new_content, queued_at
|
|
145462
|
+
FROM memory_mutation_log
|
|
145463
|
+
WHERE project_path = ?
|
|
145464
|
+
AND id > ?
|
|
145465
|
+
AND target_memory_id IN (${placeholders3})
|
|
145466
|
+
ORDER BY id ASC`).all(projectPath, afterId ?? 0, ...uniqueIds);
|
|
145467
|
+
return coalesceMutations(rows);
|
|
145468
|
+
}
|
|
145469
|
+
function getMemoryMutationsForRenderByProjects(db, projectPaths, afterId, renderedMemoryIds) {
|
|
145470
|
+
if (renderedMemoryIds.length === 0)
|
|
145471
|
+
return [];
|
|
145472
|
+
const identities = uniqueProjectPaths(projectPaths);
|
|
145473
|
+
if (identities.length === 0)
|
|
145474
|
+
return [];
|
|
145475
|
+
if (identities.length === 1) {
|
|
145476
|
+
return getMemoryMutationsForRender(db, identities[0], afterId, renderedMemoryIds);
|
|
145477
|
+
}
|
|
145478
|
+
const uniqueIds = [...new Set(renderedMemoryIds)].sort((left, right) => left - right);
|
|
145479
|
+
const rows = db.prepare(`SELECT id, project_path, mutation_type, target_memory_id,
|
|
145480
|
+
superseded_by_id, category, new_content, queued_at
|
|
145481
|
+
FROM memory_mutation_log
|
|
145482
|
+
WHERE project_path IN (${placeholders2(identities)})
|
|
145483
|
+
AND id > ?
|
|
145484
|
+
AND target_memory_id IN (${placeholders2(uniqueIds)})
|
|
145485
|
+
ORDER BY id ASC`).all(...identities, afterId ?? 0, ...uniqueIds);
|
|
145486
|
+
return coalesceMutations(rows);
|
|
145487
|
+
}
|
|
144943
145488
|
function getMaxMemoryMutationId(db, projectPath) {
|
|
144944
145489
|
const row = db.prepare("SELECT MAX(id) AS max_id FROM memory_mutation_log WHERE project_path = ?").get(projectPath);
|
|
144945
145490
|
return row?.max_id ?? null;
|
|
144946
145491
|
}
|
|
145492
|
+
function getMaxMemoryMutationIdForProjects(db, projectPaths) {
|
|
145493
|
+
const identities = uniqueProjectPaths(projectPaths);
|
|
145494
|
+
if (identities.length === 0)
|
|
145495
|
+
return null;
|
|
145496
|
+
if (identities.length === 1)
|
|
145497
|
+
return getMaxMemoryMutationId(db, identities[0]);
|
|
145498
|
+
const row = db.prepare(`SELECT MAX(id) AS max_id
|
|
145499
|
+
FROM memory_mutation_log
|
|
145500
|
+
WHERE project_path IN (${placeholders2(identities)})`).get(...identities);
|
|
145501
|
+
return row?.max_id ?? null;
|
|
145502
|
+
}
|
|
144947
145503
|
// ../plugin/src/features/magic-context/storage-meta-persisted.ts
|
|
144948
145504
|
init_logger();
|
|
144949
145505
|
var CAS_RETRY_LIMIT = 5;
|
|
@@ -145789,9 +146345,9 @@ function buildStatusClause(status) {
|
|
|
145789
146345
|
if (statuses.length === 0) {
|
|
145790
146346
|
return null;
|
|
145791
146347
|
}
|
|
145792
|
-
const
|
|
146348
|
+
const placeholders3 = statuses.map(() => "?").join(", ");
|
|
145793
146349
|
return {
|
|
145794
|
-
sql: `status IN (${
|
|
146350
|
+
sql: `status IN (${placeholders3})`,
|
|
145795
146351
|
params: statuses
|
|
145796
146352
|
};
|
|
145797
146353
|
}
|
|
@@ -145987,19 +146543,6 @@ function getProjectState(db, projectPath) {
|
|
|
145987
146543
|
WHERE project_path = ?`).get(projectPath);
|
|
145988
146544
|
return row ? toProjectState(row) : null;
|
|
145989
146545
|
}
|
|
145990
|
-
function bumpProjectMemoryEpoch(db, projectPath, now = Date.now()) {
|
|
145991
|
-
db.prepare(`INSERT INTO project_state
|
|
145992
|
-
(project_path, project_memory_epoch, project_user_profile_version, updated_at)
|
|
145993
|
-
VALUES (?, 1, 0, ?)
|
|
145994
|
-
ON CONFLICT(project_path) DO UPDATE SET
|
|
145995
|
-
project_memory_epoch = project_memory_epoch + 1,
|
|
145996
|
-
updated_at = excluded.updated_at`).run(projectPath, now);
|
|
145997
|
-
const state = getProjectState(db, projectPath);
|
|
145998
|
-
if (!state) {
|
|
145999
|
-
throw new Error(`Failed to bump project memory epoch for ${projectPath}`);
|
|
146000
|
-
}
|
|
146001
|
-
return state;
|
|
146002
|
-
}
|
|
146003
146546
|
function bumpProjectUserProfileVersion(db, projectPath = GLOBAL_USER_PROFILE_PROJECT_PATH, now = Date.now()) {
|
|
146004
146547
|
db.prepare(`INSERT INTO project_state
|
|
146005
146548
|
(project_path, project_memory_epoch, project_user_profile_version, updated_at)
|
|
@@ -146033,8 +146576,8 @@ function getSourceContents(db, sessionId, tagIds) {
|
|
|
146033
146576
|
if (tagIds.length === 0) {
|
|
146034
146577
|
return new Map;
|
|
146035
146578
|
}
|
|
146036
|
-
const
|
|
146037
|
-
const rows = db.prepare(`SELECT tag_id, content FROM source_contents WHERE session_id = ? AND tag_id IN (${
|
|
146579
|
+
const placeholders3 = tagIds.map(() => "?").join(", ");
|
|
146580
|
+
const rows = db.prepare(`SELECT tag_id, content FROM source_contents WHERE session_id = ? AND tag_id IN (${placeholders3})`).all(sessionId, ...tagIds).filter(isSourceContentRow);
|
|
146038
146581
|
const sources = new Map;
|
|
146039
146582
|
for (const row of rows) {
|
|
146040
146583
|
sources.set(row.tag_id, row.content);
|
|
@@ -146125,15 +146668,22 @@ function ownerMessageIdForTagRow(row) {
|
|
|
146125
146668
|
}
|
|
146126
146669
|
return row.message_id.replace(CONTENT_ID_SUFFIX, "");
|
|
146127
146670
|
}
|
|
146128
|
-
function getActiveTagTokenAggregate(db, sessionId) {
|
|
146129
|
-
const
|
|
146671
|
+
function getActiveTagTokenAggregate(db, sessionId, protectedTags = 0) {
|
|
146672
|
+
const toolOutputExpr = protectedTags > 0 ? `COALESCE(SUM(CASE WHEN type = 'tool' AND tag_number < (
|
|
146673
|
+
SELECT tag_number FROM tags
|
|
146674
|
+
WHERE session_id = ? AND status = 'active'
|
|
146675
|
+
ORDER BY tag_number DESC LIMIT 1 OFFSET ?
|
|
146676
|
+
) THEN COALESCE(token_count, 0) ELSE 0 END), 0)` : `COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)`;
|
|
146677
|
+
const sql = `SELECT
|
|
146130
146678
|
COALESCE(SUM(CASE WHEN type != 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)
|
|
146131
146679
|
+ COALESCE(SUM(COALESCE(reasoning_token_count, 0)), 0) AS conversation,
|
|
146132
146680
|
COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) + COALESCE(input_token_count, 0) ELSE 0 END), 0) AS tool_call,
|
|
146133
|
-
|
|
146681
|
+
${toolOutputExpr} AS tool_output,
|
|
146134
146682
|
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
146135
146683
|
FROM tags
|
|
146136
|
-
WHERE session_id = ? AND status = 'active'
|
|
146684
|
+
WHERE session_id = ? AND status = 'active'`;
|
|
146685
|
+
const params = protectedTags > 0 ? [sessionId, protectedTags - 1, sessionId] : [sessionId];
|
|
146686
|
+
const row = db.prepare(sql).get(...params);
|
|
146137
146687
|
return {
|
|
146138
146688
|
conversation: row?.conversation ?? 0,
|
|
146139
146689
|
toolCall: row?.tool_call ?? 0,
|
|
@@ -146324,8 +146874,8 @@ function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
|
146324
146874
|
}
|
|
146325
146875
|
return all;
|
|
146326
146876
|
}
|
|
146327
|
-
const
|
|
146328
|
-
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${
|
|
146877
|
+
const placeholders3 = tagNumbers.map(() => "?").join(",");
|
|
146878
|
+
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${placeholders3}) ORDER BY tag_number ASC, id ASC`).all(sessionId, ...tagNumbers).filter(isTagRow);
|
|
146329
146879
|
return rows.map(toTagEntry);
|
|
146330
146880
|
}
|
|
146331
146881
|
var getToolTagNumberByOwnerStatements = new WeakMap;
|
|
@@ -146395,7 +146945,7 @@ var ERROR_CLASSES = new Set([
|
|
|
146395
146945
|
]);
|
|
146396
146946
|
// ../plugin/src/features/magic-context/v22-deferred-backfill.ts
|
|
146397
146947
|
init_logger();
|
|
146398
|
-
import { createHash as
|
|
146948
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
146399
146949
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
146400
146950
|
import path5 from "node:path";
|
|
146401
146951
|
var BATCH_SIZE = 25;
|
|
@@ -146449,7 +146999,7 @@ function computeLegacyRustDirIdentity(rawProjectPath) {
|
|
|
146449
146999
|
} catch {
|
|
146450
147000
|
canonical = path5.isAbsolute(rawProjectPath) ? rawProjectPath : path5.join(process.cwd(), rawProjectPath);
|
|
146451
147001
|
}
|
|
146452
|
-
return `dir:${
|
|
147002
|
+
return `dir:${createHash5("sha256").update(canonical, "utf8").digest("hex")}`;
|
|
146453
147003
|
}
|
|
146454
147004
|
function upsertRekeyMap(db, oldProjectPath, newProjectPath, rekeyedAt) {
|
|
146455
147005
|
db.prepare(`INSERT INTO v22_identity_rekey_map (old_project_path, new_project_path, rekeyed_at)
|
|
@@ -147007,7 +147557,7 @@ function clearNoteNudgeTriggerOnly(db, sessionId) {
|
|
|
147007
147557
|
}
|
|
147008
147558
|
|
|
147009
147559
|
// ../plugin/src/hooks/magic-context/todo-view.ts
|
|
147010
|
-
import { createHash as
|
|
147560
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
147011
147561
|
var TERMINAL_STATUSES = new Set(["completed", "cancelled"]);
|
|
147012
147562
|
var TITLE_DONE_STATUSES = new Set(["completed"]);
|
|
147013
147563
|
var SYNTHETIC_CALL_ID_PREFIX = "mc_synthetic_todo_";
|
|
@@ -147052,7 +147602,7 @@ function buildSyntheticTodoPart(stateJson) {
|
|
|
147052
147602
|
};
|
|
147053
147603
|
}
|
|
147054
147604
|
function computeSyntheticCallId(stateJson) {
|
|
147055
|
-
const hash =
|
|
147605
|
+
const hash = createHash6("sha256").update(stateJson).digest("hex").slice(0, 16);
|
|
147056
147606
|
return `${SYNTHETIC_CALL_ID_PREFIX}${hash}`;
|
|
147057
147607
|
}
|
|
147058
147608
|
function parseTodoState(stateJson) {
|
|
@@ -147193,13 +147743,13 @@ async function maybeSendUpgradeReminder(deps, sessionId) {
|
|
|
147193
147743
|
init_data_path();
|
|
147194
147744
|
import * as fs2 from "node:fs";
|
|
147195
147745
|
import * as path6 from "node:path";
|
|
147196
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
147746
|
+
var ANNOUNCEMENT_VERSION = "0.24.0";
|
|
147197
147747
|
var ANNOUNCEMENT_FEATURES = [
|
|
147198
|
-
"
|
|
147199
|
-
"
|
|
147200
|
-
"
|
|
147201
|
-
"
|
|
147202
|
-
"
|
|
147748
|
+
"Searchable session history: ctx_search can now find older discussion by meaning, not just keywords. New history is embedded automatically — to backfill an EXISTING session's older history, run /ctx-embed-history once (it works in the background).",
|
|
147749
|
+
"Cross-project workspaces: group related repos and share project memories across them, with per-category control over what's shared. Set them up in the dashboard's Workspaces panel.",
|
|
147750
|
+
"Pi: fixed sessions overflowing the model context while still showing moderate usage — Pi now sheds context before a tool-heavy turn overflows.",
|
|
147751
|
+
"Fewer prompt-cache busts: doc edits, processed screenshots, and a rebuild-then-bust-again case no longer re-bill large prompt prefixes.",
|
|
147752
|
+
"Setup wizard now lists your actual models with type-ahead instead of fixed recommendations, and explains the historian/dreamer roles (issue #144). Plus a GitHub Copilot tool-pairing fix (#135)."
|
|
147203
147753
|
];
|
|
147204
147754
|
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU";
|
|
147205
147755
|
var STATE_FILENAME = "last_announced_version";
|
|
@@ -149082,7 +149632,7 @@ function isEmbeddingRow(row) {
|
|
|
149082
149632
|
if (row === null || typeof row !== "object")
|
|
149083
149633
|
return false;
|
|
149084
149634
|
const candidate = row;
|
|
149085
|
-
return typeof candidate.memoryId === "number" && isEmbeddingBlob(candidate.embedding);
|
|
149635
|
+
return typeof candidate.memoryId === "number" && isEmbeddingBlob(candidate.embedding) && (candidate.modelId === null || typeof candidate.modelId === "string");
|
|
149086
149636
|
}
|
|
149087
149637
|
function toFloat32Array(blob) {
|
|
149088
149638
|
if (blob instanceof Uint8Array) {
|
|
@@ -149102,7 +149652,7 @@ function getSaveEmbeddingStatement(db) {
|
|
|
149102
149652
|
function getLoadAllEmbeddingsStatement(db) {
|
|
149103
149653
|
let stmt = loadAllEmbeddingsStatements.get(db);
|
|
149104
149654
|
if (!stmt) {
|
|
149105
|
-
stmt = db.prepare("SELECT memory_embeddings.memory_id AS memoryId, memory_embeddings.embedding AS embedding FROM memory_embeddings INNER JOIN memories ON memories.id = memory_embeddings.memory_id WHERE memories.project_path = ? ORDER BY memory_embeddings.memory_id ASC");
|
|
149655
|
+
stmt = db.prepare("SELECT memory_embeddings.memory_id AS memoryId, memory_embeddings.embedding AS embedding, memory_embeddings.model_id AS modelId FROM memory_embeddings INNER JOIN memories ON memories.id = memory_embeddings.memory_id WHERE memories.project_path = ? ORDER BY memory_embeddings.memory_id ASC");
|
|
149106
149656
|
loadAllEmbeddingsStatements.set(db, stmt);
|
|
149107
149657
|
}
|
|
149108
149658
|
return stmt;
|
|
@@ -149131,7 +149681,10 @@ function loadAllEmbeddings(db, projectPath) {
|
|
|
149131
149681
|
const rows = getLoadAllEmbeddingsStatement(db).all(projectPath).filter(isEmbeddingRow);
|
|
149132
149682
|
const embeddings = new Map;
|
|
149133
149683
|
for (const row of rows) {
|
|
149134
|
-
embeddings.set(row.memoryId,
|
|
149684
|
+
embeddings.set(row.memoryId, {
|
|
149685
|
+
embedding: toFloat32Array(row.embedding),
|
|
149686
|
+
modelId: row.modelId
|
|
149687
|
+
});
|
|
149135
149688
|
}
|
|
149136
149689
|
return embeddings;
|
|
149137
149690
|
}
|
|
@@ -149182,13 +149735,13 @@ function invalidateMemory(projectPath, memoryId) {
|
|
|
149182
149735
|
}
|
|
149183
149736
|
|
|
149184
149737
|
// ../plugin/src/features/magic-context/memory/normalize-hash.ts
|
|
149185
|
-
import { createHash as
|
|
149738
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
149186
149739
|
function normalizeMemoryContent(content) {
|
|
149187
149740
|
return content.toLowerCase().replace(/\s+/g, " ").trim();
|
|
149188
149741
|
}
|
|
149189
149742
|
function computeNormalizedHash(content) {
|
|
149190
149743
|
const normalized = normalizeMemoryContent(content);
|
|
149191
|
-
return
|
|
149744
|
+
return createHash7("md5").update(normalized).digest("hex");
|
|
149192
149745
|
}
|
|
149193
149746
|
|
|
149194
149747
|
// ../plugin/src/features/magic-context/memory/storage-memory.ts
|
|
@@ -149376,8 +149929,8 @@ function getMemoriesByProjectStatement(db, statuses) {
|
|
|
149376
149929
|
}
|
|
149377
149930
|
let stmt = statements.get(db);
|
|
149378
149931
|
if (!stmt) {
|
|
149379
|
-
const
|
|
149380
|
-
stmt = db.prepare(`SELECT ${getMemorySelectColumns(db)} FROM memories WHERE project_path = ? AND status IN (${
|
|
149932
|
+
const placeholders3 = statuses.map(() => "?").join(", ");
|
|
149933
|
+
stmt = db.prepare(`SELECT ${getMemorySelectColumns(db)} FROM memories WHERE project_path = ? AND status IN (${placeholders3}) AND (expires_at IS NULL OR expires_at > ?) ORDER BY category ASC, updated_at DESC, id ASC`);
|
|
149381
149934
|
statements.set(db, stmt);
|
|
149382
149935
|
}
|
|
149383
149936
|
return stmt;
|
|
@@ -149522,6 +150075,97 @@ function getMemoriesByProject(db, projectPath, statuses = ["active", "permanent"
|
|
|
149522
150075
|
const rows = getMemoriesByProjectStatement(db, statuses).all(projectPath, ...statuses, expiryCutoff).filter(isMemoryRow);
|
|
149523
150076
|
return rows.map(toMemory);
|
|
149524
150077
|
}
|
|
150078
|
+
function sqlPlaceholders(values) {
|
|
150079
|
+
return values.map(() => "?").join(", ");
|
|
150080
|
+
}
|
|
150081
|
+
function uniqueValues(values) {
|
|
150082
|
+
return [...new Set(values.filter((value) => value.length > 0))];
|
|
150083
|
+
}
|
|
150084
|
+
function buildWorkspaceMemorySqlFilter(args) {
|
|
150085
|
+
if (args.shareCategories === null || args.shareCategories === undefined) {
|
|
150086
|
+
return { clause: "", params: [], active: false };
|
|
150087
|
+
}
|
|
150088
|
+
const identities = uniqueValues(args.identities);
|
|
150089
|
+
const identitySet = new Set(identities);
|
|
150090
|
+
const ownSet = new Set(uniqueValues(args.ownIdentities ?? []).filter((identity) => identitySet.has(identity)));
|
|
150091
|
+
const foreignIdentities = identities.filter((identity) => !ownSet.has(identity));
|
|
150092
|
+
if (foreignIdentities.length === 0) {
|
|
150093
|
+
return { clause: "", params: [], active: false };
|
|
150094
|
+
}
|
|
150095
|
+
const ownIdentities = identities.filter((identity) => ownSet.has(identity));
|
|
150096
|
+
const shareCategories = uniqueValues([...args.shareCategories]);
|
|
150097
|
+
const qualifier = args.tableName ? `${args.tableName}.` : "";
|
|
150098
|
+
const predicates = [];
|
|
150099
|
+
const params = [];
|
|
150100
|
+
if (ownIdentities.length > 0) {
|
|
150101
|
+
predicates.push(`${qualifier}project_path IN (${sqlPlaceholders(ownIdentities)})`);
|
|
150102
|
+
params.push(...ownIdentities);
|
|
150103
|
+
}
|
|
150104
|
+
if (foreignIdentities.length > 0 && shareCategories.length > 0) {
|
|
150105
|
+
predicates.push(`(${qualifier}project_path IN (${sqlPlaceholders(foreignIdentities)}) AND ${qualifier}category IN (${sqlPlaceholders(shareCategories)}))`);
|
|
150106
|
+
params.push(...foreignIdentities, ...shareCategories);
|
|
150107
|
+
}
|
|
150108
|
+
if (predicates.length === 0) {
|
|
150109
|
+
return { clause: " AND 0 = 1", params: [], active: true };
|
|
150110
|
+
}
|
|
150111
|
+
return { clause: ` AND (${predicates.join(" OR ")})`, params, active: true };
|
|
150112
|
+
}
|
|
150113
|
+
function getMemoriesByProjects(db, projectPaths, statuses = ["active", "permanent"], expiryCutoff = Date.now(), ownIdentities, shareCategories) {
|
|
150114
|
+
const identities = uniqueValues(projectPaths);
|
|
150115
|
+
if (identities.length === 0 || statuses.length === 0)
|
|
150116
|
+
return [];
|
|
150117
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
150118
|
+
identities,
|
|
150119
|
+
ownIdentities,
|
|
150120
|
+
shareCategories
|
|
150121
|
+
});
|
|
150122
|
+
if (identities.length === 1 && !sharingFilter.active) {
|
|
150123
|
+
return getMemoriesByProject(db, identities[0], statuses, expiryCutoff);
|
|
150124
|
+
}
|
|
150125
|
+
const rows = db.prepare(`SELECT ${getMemorySelectColumns(db)}
|
|
150126
|
+
FROM memories
|
|
150127
|
+
WHERE project_path IN (${sqlPlaceholders(identities)})
|
|
150128
|
+
AND status IN (${sqlPlaceholders(statuses)})
|
|
150129
|
+
AND (expires_at IS NULL OR expires_at > ?)${sharingFilter.clause}
|
|
150130
|
+
ORDER BY category ASC, updated_at DESC, id ASC`).all(...identities, ...statuses, expiryCutoff, ...sharingFilter.params).filter(isMemoryRow);
|
|
150131
|
+
return rows.map(toMemory);
|
|
150132
|
+
}
|
|
150133
|
+
function getMaxMemoryIdForProjects(db, projectPaths, ownIdentities, shareCategories) {
|
|
150134
|
+
const identities = uniqueValues(projectPaths);
|
|
150135
|
+
if (identities.length === 0)
|
|
150136
|
+
return 0;
|
|
150137
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
150138
|
+
identities,
|
|
150139
|
+
ownIdentities,
|
|
150140
|
+
shareCategories
|
|
150141
|
+
});
|
|
150142
|
+
if (identities.length === 1 && !sharingFilter.active) {
|
|
150143
|
+
const row2 = db.prepare("SELECT COALESCE(MAX(id), 0) AS max_id FROM memories WHERE project_path = ?").get(identities[0]);
|
|
150144
|
+
return typeof row2?.max_id === "number" ? row2.max_id : 0;
|
|
150145
|
+
}
|
|
150146
|
+
const row = db.prepare(`SELECT COALESCE(MAX(id), 0) AS max_id
|
|
150147
|
+
FROM memories
|
|
150148
|
+
WHERE project_path IN (${sqlPlaceholders(identities)})${sharingFilter.clause}`).get(...identities, ...sharingFilter.params);
|
|
150149
|
+
return typeof row?.max_id === "number" ? row.max_id : 0;
|
|
150150
|
+
}
|
|
150151
|
+
function readNewMemoriesForM1Union(db, projectPaths, afterId, expiryCutoff, ownIdentities, shareCategories) {
|
|
150152
|
+
const identities = uniqueValues(projectPaths);
|
|
150153
|
+
if (identities.length === 0)
|
|
150154
|
+
return [];
|
|
150155
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
150156
|
+
identities,
|
|
150157
|
+
ownIdentities,
|
|
150158
|
+
shareCategories
|
|
150159
|
+
});
|
|
150160
|
+
const rows = db.prepare(`SELECT ${getMemorySelectColumns(db)}
|
|
150161
|
+
FROM memories
|
|
150162
|
+
WHERE project_path IN (${sqlPlaceholders(identities)})
|
|
150163
|
+
AND id > ?
|
|
150164
|
+
AND status IN ('active', 'permanent')
|
|
150165
|
+
AND (expires_at IS NULL OR expires_at > ?)${sharingFilter.clause}
|
|
150166
|
+
ORDER BY ${MEMORY_CATEGORY_ORDER_SQL}, id ASC`).all(...identities, afterId, expiryCutoff, ...sharingFilter.params).filter(isMemoryRow);
|
|
150167
|
+
return rows.map(toMemory);
|
|
150168
|
+
}
|
|
149525
150169
|
function getAllActiveMemoriesForMigration(db, projectPath) {
|
|
149526
150170
|
const rows = getActiveMemoriesNoExpiryStatement(db).all(projectPath).filter(isMemoryRow);
|
|
149527
150171
|
return rows.map(toMemory);
|
|
@@ -150043,8 +150687,8 @@ function getUserMemoryCandidates(db) {
|
|
|
150043
150687
|
function deleteUserMemoryCandidates(db, ids) {
|
|
150044
150688
|
if (ids.length === 0)
|
|
150045
150689
|
return;
|
|
150046
|
-
const
|
|
150047
|
-
db.prepare(`DELETE FROM user_memory_candidates WHERE id IN (${
|
|
150690
|
+
const placeholders3 = ids.map(() => "?").join(",");
|
|
150691
|
+
db.prepare(`DELETE FROM user_memory_candidates WHERE id IN (${placeholders3})`).run(...ids);
|
|
150048
150692
|
}
|
|
150049
150693
|
function insertUserMemory(db, content, sourceCandidateIds) {
|
|
150050
150694
|
const now = Date.now();
|
|
@@ -165534,7 +166178,8 @@ var BaseEmbeddingConfigSchema = exports_external.object({
|
|
|
165534
166178
|
endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
|
|
165535
166179
|
api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
|
|
165536
166180
|
input_type: exports_external.string().optional().describe("Optional input_type sent in the embedding request body. Required by some openai-compatible providers (e.g. NVIDIA NIM expects 'query' or 'passage'). Omitted from the request when unset."),
|
|
165537
|
-
truncate: exports_external.string().optional().describe("Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts 'NONE' | 'START' | 'END'). Omitted from the request when unset.")
|
|
166181
|
+
truncate: exports_external.string().optional().describe("Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts 'NONE' | 'START' | 'END'). Omitted from the request when unset."),
|
|
166182
|
+
max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
|
|
165538
166183
|
}).superRefine((data, ctx) => {
|
|
165539
166184
|
if (data.provider === "openai-compatible" && !data.endpoint?.trim()) {
|
|
165540
166185
|
ctx.addIssue({
|
|
@@ -165555,7 +166200,8 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
|
|
|
165555
166200
|
if (data.provider === "local") {
|
|
165556
166201
|
return {
|
|
165557
166202
|
provider: "local",
|
|
165558
|
-
model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
166203
|
+
model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
166204
|
+
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
|
|
165559
166205
|
};
|
|
165560
166206
|
}
|
|
165561
166207
|
if (data.provider === "openai-compatible") {
|
|
@@ -165568,7 +166214,8 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
|
|
|
165568
166214
|
endpoint: data.endpoint?.trim() ?? "",
|
|
165569
166215
|
...apiKey ? { api_key: apiKey } : {},
|
|
165570
166216
|
...inputType ? { input_type: inputType } : {},
|
|
165571
|
-
...truncate ? { truncate } : {}
|
|
166217
|
+
...truncate ? { truncate } : {},
|
|
166218
|
+
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
|
|
165572
166219
|
};
|
|
165573
166220
|
}
|
|
165574
166221
|
return { provider: "off" };
|
|
@@ -165650,6 +166297,443 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
165650
166297
|
// ../plugin/src/features/magic-context/memory/embedding.ts
|
|
165651
166298
|
init_logger();
|
|
165652
166299
|
|
|
166300
|
+
// ../plugin/src/features/magic-context/compartment-chunk-embedding.ts
|
|
166301
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
166302
|
+
var DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS = 512;
|
|
166303
|
+
var CHUNK_WINDOW_SAFETY_RATIO = 0.9;
|
|
166304
|
+
var loadFtsRowsStatements = new WeakMap;
|
|
166305
|
+
var existingHashStatements = new WeakMap;
|
|
166306
|
+
var existingHashByProjectStatements = new WeakMap;
|
|
166307
|
+
var deleteByCompartmentStatements = new WeakMap;
|
|
166308
|
+
var insertEmbeddingStatements = new WeakMap;
|
|
166309
|
+
var distinctModelStatements = new WeakMap;
|
|
166310
|
+
var clearProjectStatements = new WeakMap;
|
|
166311
|
+
var clearProjectModelStatements = new WeakMap;
|
|
166312
|
+
var searchRowsStatements = new WeakMap;
|
|
166313
|
+
var searchRowsByModelStatements = new WeakMap;
|
|
166314
|
+
var backfillCandidateStatements = new WeakMap;
|
|
166315
|
+
function getLoadFtsRowsStatement(db) {
|
|
166316
|
+
let stmt = loadFtsRowsStatements.get(db);
|
|
166317
|
+
if (!stmt) {
|
|
166318
|
+
stmt = db.prepare(`SELECT message_ordinal AS messageOrdinal, role, content
|
|
166319
|
+
FROM message_history_fts
|
|
166320
|
+
WHERE session_id = ?
|
|
166321
|
+
AND message_ordinal >= ?
|
|
166322
|
+
AND message_ordinal <= ?
|
|
166323
|
+
AND role IN ('user', 'assistant')
|
|
166324
|
+
ORDER BY message_ordinal ASC`);
|
|
166325
|
+
loadFtsRowsStatements.set(db, stmt);
|
|
166326
|
+
}
|
|
166327
|
+
return stmt;
|
|
166328
|
+
}
|
|
166329
|
+
function getExistingHashStatement(db, scopedToProject) {
|
|
166330
|
+
const map2 = scopedToProject ? existingHashByProjectStatements : existingHashStatements;
|
|
166331
|
+
let stmt = map2.get(db);
|
|
166332
|
+
if (!stmt) {
|
|
166333
|
+
stmt = db.prepare(`SELECT window_index AS windowIndex, chunk_hash AS chunkHash
|
|
166334
|
+
FROM compartment_chunk_embeddings
|
|
166335
|
+
WHERE compartment_id = ?
|
|
166336
|
+
AND model_id = ?
|
|
166337
|
+
${scopedToProject ? "AND project_path = ?" : ""}
|
|
166338
|
+
ORDER BY window_index ASC`);
|
|
166339
|
+
map2.set(db, stmt);
|
|
166340
|
+
}
|
|
166341
|
+
return stmt;
|
|
166342
|
+
}
|
|
166343
|
+
function getDeleteByCompartmentStatement(db) {
|
|
166344
|
+
let stmt = deleteByCompartmentStatements.get(db);
|
|
166345
|
+
if (!stmt) {
|
|
166346
|
+
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE compartment_id = ?");
|
|
166347
|
+
deleteByCompartmentStatements.set(db, stmt);
|
|
166348
|
+
}
|
|
166349
|
+
return stmt;
|
|
166350
|
+
}
|
|
166351
|
+
function getInsertEmbeddingStatement(db) {
|
|
166352
|
+
let stmt = insertEmbeddingStatements.get(db);
|
|
166353
|
+
if (!stmt) {
|
|
166354
|
+
stmt = db.prepare(`INSERT INTO compartment_chunk_embeddings (
|
|
166355
|
+
compartment_id, session_id, project_path, harness, window_index,
|
|
166356
|
+
start_ordinal, end_ordinal, chunk_hash, model_id, dims, vector, created_at
|
|
166357
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
166358
|
+
insertEmbeddingStatements.set(db, stmt);
|
|
166359
|
+
}
|
|
166360
|
+
return stmt;
|
|
166361
|
+
}
|
|
166362
|
+
function getDistinctModelStatement(db) {
|
|
166363
|
+
let stmt = distinctModelStatements.get(db);
|
|
166364
|
+
if (!stmt) {
|
|
166365
|
+
stmt = db.prepare(`SELECT DISTINCT model_id AS modelId
|
|
166366
|
+
FROM compartment_chunk_embeddings
|
|
166367
|
+
WHERE project_path = ?`);
|
|
166368
|
+
distinctModelStatements.set(db, stmt);
|
|
166369
|
+
}
|
|
166370
|
+
return stmt;
|
|
166371
|
+
}
|
|
166372
|
+
function getClearProjectStatement(db) {
|
|
166373
|
+
let stmt = clearProjectStatements.get(db);
|
|
166374
|
+
if (!stmt) {
|
|
166375
|
+
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE project_path = ?");
|
|
166376
|
+
clearProjectStatements.set(db, stmt);
|
|
166377
|
+
}
|
|
166378
|
+
return stmt;
|
|
166379
|
+
}
|
|
166380
|
+
function getClearProjectModelStatement(db) {
|
|
166381
|
+
let stmt = clearProjectModelStatements.get(db);
|
|
166382
|
+
if (!stmt) {
|
|
166383
|
+
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE project_path = ? AND model_id = ?");
|
|
166384
|
+
clearProjectModelStatements.set(db, stmt);
|
|
166385
|
+
}
|
|
166386
|
+
return stmt;
|
|
166387
|
+
}
|
|
166388
|
+
function getSearchRowsStatement(db, withModel) {
|
|
166389
|
+
const map2 = withModel ? searchRowsByModelStatements : searchRowsStatements;
|
|
166390
|
+
let stmt = map2.get(db);
|
|
166391
|
+
if (!stmt) {
|
|
166392
|
+
stmt = db.prepare(`SELECT e.compartment_id AS compartmentId,
|
|
166393
|
+
e.session_id AS sessionId,
|
|
166394
|
+
c.title AS title,
|
|
166395
|
+
c.start_message AS compartmentStart,
|
|
166396
|
+
c.end_message AS compartmentEnd,
|
|
166397
|
+
e.window_index AS windowIndex,
|
|
166398
|
+
e.start_ordinal AS windowStart,
|
|
166399
|
+
e.end_ordinal AS windowEnd,
|
|
166400
|
+
e.chunk_hash AS chunkHash,
|
|
166401
|
+
e.model_id AS modelId,
|
|
166402
|
+
e.dims AS dims,
|
|
166403
|
+
e.vector AS vector
|
|
166404
|
+
FROM compartment_chunk_embeddings e
|
|
166405
|
+
JOIN compartments c ON c.id = e.compartment_id
|
|
166406
|
+
WHERE e.session_id = ?
|
|
166407
|
+
AND e.project_path = ?
|
|
166408
|
+
${withModel ? "AND e.model_id = ?" : ""}
|
|
166409
|
+
ORDER BY e.compartment_id ASC, e.window_index ASC`);
|
|
166410
|
+
map2.set(db, stmt);
|
|
166411
|
+
}
|
|
166412
|
+
return stmt;
|
|
166413
|
+
}
|
|
166414
|
+
function isFinitePositiveInteger(value) {
|
|
166415
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
166416
|
+
}
|
|
166417
|
+
function normalizeCompartmentChunkMaxInputTokens(value) {
|
|
166418
|
+
if (!isFinitePositiveInteger(value)) {
|
|
166419
|
+
return DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS;
|
|
166420
|
+
}
|
|
166421
|
+
return Math.max(1, Math.floor(value));
|
|
166422
|
+
}
|
|
166423
|
+
function normalizeContent(text) {
|
|
166424
|
+
return text.replace(/\s+/g, " ").trim();
|
|
166425
|
+
}
|
|
166426
|
+
function formatOrdinalRange(start, end) {
|
|
166427
|
+
return start === end ? `[${start}]` : `[${start}-${end}]`;
|
|
166428
|
+
}
|
|
166429
|
+
function rolePrefix(role) {
|
|
166430
|
+
if (role === "user")
|
|
166431
|
+
return "U";
|
|
166432
|
+
if (role === "assistant")
|
|
166433
|
+
return "A";
|
|
166434
|
+
return null;
|
|
166435
|
+
}
|
|
166436
|
+
function parseOrdinal(value) {
|
|
166437
|
+
const parsed = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
166438
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
166439
|
+
}
|
|
166440
|
+
function parseCanonicalLineRange(line) {
|
|
166441
|
+
const match = /^\[(\d+)(?:-(\d+))?\]\s+[UA]:/.exec(line.trim());
|
|
166442
|
+
if (!match)
|
|
166443
|
+
return null;
|
|
166444
|
+
const start = Number.parseInt(match[1], 10);
|
|
166445
|
+
const end = match[2] ? Number.parseInt(match[2], 10) : start;
|
|
166446
|
+
if (!Number.isFinite(start) || !Number.isFinite(end))
|
|
166447
|
+
return null;
|
|
166448
|
+
return { start, end };
|
|
166449
|
+
}
|
|
166450
|
+
function hashChunkText(text) {
|
|
166451
|
+
return createHash8("sha256").update(text).digest("hex");
|
|
166452
|
+
}
|
|
166453
|
+
function vectorBlob(vector) {
|
|
166454
|
+
return new Uint8Array(vector.buffer, vector.byteOffset, vector.byteLength);
|
|
166455
|
+
}
|
|
166456
|
+
function toFloat32Array2(blob) {
|
|
166457
|
+
if (blob instanceof Uint8Array) {
|
|
166458
|
+
const buffer2 = blob.buffer.slice(blob.byteOffset, blob.byteOffset + blob.byteLength);
|
|
166459
|
+
return new Float32Array(buffer2);
|
|
166460
|
+
}
|
|
166461
|
+
return new Float32Array(blob.slice(0));
|
|
166462
|
+
}
|
|
166463
|
+
function buildCanonicalChunkTextFromFts(db, sessionId, startOrdinal, endOrdinal) {
|
|
166464
|
+
if (endOrdinal < startOrdinal)
|
|
166465
|
+
return "";
|
|
166466
|
+
const rows = getLoadFtsRowsStatement(db).all(sessionId, startOrdinal, endOrdinal).map((row) => row);
|
|
166467
|
+
const lines = [];
|
|
166468
|
+
let current = null;
|
|
166469
|
+
const flush2 = () => {
|
|
166470
|
+
if (!current || current.parts.length === 0)
|
|
166471
|
+
return;
|
|
166472
|
+
lines.push(`${formatOrdinalRange(current.start, current.end)} ${current.role}: ${current.parts.join(" / ")}`);
|
|
166473
|
+
current = null;
|
|
166474
|
+
};
|
|
166475
|
+
for (const row of rows) {
|
|
166476
|
+
const ordinal = parseOrdinal(row.messageOrdinal);
|
|
166477
|
+
const prefix = rolePrefix(row.role);
|
|
166478
|
+
const content = typeof row.content === "string" ? normalizeContent(row.content) : "";
|
|
166479
|
+
if (ordinal === null || prefix === null || content.length === 0)
|
|
166480
|
+
continue;
|
|
166481
|
+
if (current && current.role === prefix) {
|
|
166482
|
+
current.end = ordinal;
|
|
166483
|
+
current.parts.push(content);
|
|
166484
|
+
continue;
|
|
166485
|
+
}
|
|
166486
|
+
flush2();
|
|
166487
|
+
current = { role: prefix, start: ordinal, end: ordinal, parts: [content] };
|
|
166488
|
+
}
|
|
166489
|
+
flush2();
|
|
166490
|
+
return lines.join(`
|
|
166491
|
+
`);
|
|
166492
|
+
}
|
|
166493
|
+
function canonicalizeInMemoryChunkTextForEmbedding(chunkText, startOrdinal, endOrdinal) {
|
|
166494
|
+
const lines = [];
|
|
166495
|
+
for (const rawLine of chunkText.split(/\r?\n/)) {
|
|
166496
|
+
const line = rawLine.trim();
|
|
166497
|
+
const match = /^(\[(\d+)(?:-(\d+))?\]\s+[UA]:)\s*(.*)$/.exec(line);
|
|
166498
|
+
if (!match)
|
|
166499
|
+
continue;
|
|
166500
|
+
const lineStart = Number.parseInt(match[2], 10);
|
|
166501
|
+
const lineEnd = match[3] ? Number.parseInt(match[3], 10) : lineStart;
|
|
166502
|
+
if (startOrdinal != null && lineEnd < startOrdinal)
|
|
166503
|
+
continue;
|
|
166504
|
+
if (endOrdinal != null && lineStart > endOrdinal)
|
|
166505
|
+
continue;
|
|
166506
|
+
const rawParts = match[4].split(" / ").map((part) => normalizeContent(part)).filter((part) => part.length > 0);
|
|
166507
|
+
const ordinalSpan = lineEnd - lineStart + 1;
|
|
166508
|
+
const roleLabel = match[1].slice(match[1].indexOf("]") + 2);
|
|
166509
|
+
if (ordinalSpan === rawParts.length) {
|
|
166510
|
+
const retained = rawParts.map((part, index) => ({ ordinal: lineStart + index, part })).filter(({ ordinal, part }) => {
|
|
166511
|
+
if (part.startsWith("TC:"))
|
|
166512
|
+
return false;
|
|
166513
|
+
if (startOrdinal != null && ordinal < startOrdinal)
|
|
166514
|
+
return false;
|
|
166515
|
+
if (endOrdinal != null && ordinal > endOrdinal)
|
|
166516
|
+
return false;
|
|
166517
|
+
return true;
|
|
166518
|
+
});
|
|
166519
|
+
if (retained.length === 0)
|
|
166520
|
+
continue;
|
|
166521
|
+
const retainedStart = retained[0].ordinal;
|
|
166522
|
+
const retainedEnd = retained[retained.length - 1].ordinal;
|
|
166523
|
+
lines.push(`${formatOrdinalRange(retainedStart, retainedEnd)} ${roleLabel} ${retained.map(({ part }) => part).join(" / ")}`);
|
|
166524
|
+
continue;
|
|
166525
|
+
}
|
|
166526
|
+
const parts = rawParts.filter((part) => !part.startsWith("TC:"));
|
|
166527
|
+
if (parts.length === 0)
|
|
166528
|
+
continue;
|
|
166529
|
+
lines.push(`${match[1]} ${parts.join(" / ")}`);
|
|
166530
|
+
}
|
|
166531
|
+
return lines.join(`
|
|
166532
|
+
`);
|
|
166533
|
+
}
|
|
166534
|
+
function chunkCanonicalText(canonicalText, startOrdinal, endOrdinal, maxInputTokens) {
|
|
166535
|
+
const lines = canonicalText.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
166536
|
+
if (lines.length === 0 || endOrdinal < startOrdinal)
|
|
166537
|
+
return [];
|
|
166538
|
+
const normalizedMax = normalizeCompartmentChunkMaxInputTokens(maxInputTokens);
|
|
166539
|
+
const effectiveMax = Math.max(1, Math.floor(normalizedMax * CHUNK_WINDOW_SAFETY_RATIO));
|
|
166540
|
+
const fullText = lines.join(`
|
|
166541
|
+
`);
|
|
166542
|
+
if (estimateTokens(fullText) <= effectiveMax) {
|
|
166543
|
+
return [
|
|
166544
|
+
{
|
|
166545
|
+
windowIndex: 0,
|
|
166546
|
+
startOrdinal,
|
|
166547
|
+
endOrdinal,
|
|
166548
|
+
text: fullText,
|
|
166549
|
+
chunkHash: hashChunkText(fullText)
|
|
166550
|
+
}
|
|
166551
|
+
];
|
|
166552
|
+
}
|
|
166553
|
+
const windows = [];
|
|
166554
|
+
let currentLines = [];
|
|
166555
|
+
let currentStart = null;
|
|
166556
|
+
let currentEnd = null;
|
|
166557
|
+
let currentTokens = 0;
|
|
166558
|
+
const flush2 = () => {
|
|
166559
|
+
if (currentLines.length === 0 || currentStart === null || currentEnd === null)
|
|
166560
|
+
return;
|
|
166561
|
+
const text = currentLines.join(`
|
|
166562
|
+
`);
|
|
166563
|
+
windows.push({
|
|
166564
|
+
windowIndex: windows.length + 1,
|
|
166565
|
+
startOrdinal: currentStart,
|
|
166566
|
+
endOrdinal: currentEnd,
|
|
166567
|
+
text,
|
|
166568
|
+
chunkHash: hashChunkText(text)
|
|
166569
|
+
});
|
|
166570
|
+
currentLines = [];
|
|
166571
|
+
currentStart = null;
|
|
166572
|
+
currentEnd = null;
|
|
166573
|
+
currentTokens = 0;
|
|
166574
|
+
};
|
|
166575
|
+
for (const line of lines) {
|
|
166576
|
+
const range = parseCanonicalLineRange(line);
|
|
166577
|
+
const lineStart = range?.start ?? startOrdinal;
|
|
166578
|
+
const lineEnd = range?.end ?? lineStart;
|
|
166579
|
+
const lineTokens = estimateTokens(line);
|
|
166580
|
+
if (currentLines.length > 0 && currentTokens + lineTokens > effectiveMax) {
|
|
166581
|
+
flush2();
|
|
166582
|
+
}
|
|
166583
|
+
if (currentLines.length === 0) {
|
|
166584
|
+
currentStart = lineStart;
|
|
166585
|
+
}
|
|
166586
|
+
currentLines.push(line);
|
|
166587
|
+
currentEnd = lineEnd;
|
|
166588
|
+
currentTokens += lineTokens;
|
|
166589
|
+
}
|
|
166590
|
+
flush2();
|
|
166591
|
+
return windows;
|
|
166592
|
+
}
|
|
166593
|
+
function getExistingChunkHashes(db, compartmentId, modelId, projectPath) {
|
|
166594
|
+
const scoped = typeof projectPath === "string" && projectPath.length > 0;
|
|
166595
|
+
const rows = scoped ? getExistingHashStatement(db, true).all(compartmentId, modelId, projectPath) : getExistingHashStatement(db, false).all(compartmentId, modelId);
|
|
166596
|
+
return new Map(rows.filter((row) => typeof row.windowIndex === "number" && typeof row.chunkHash === "string").map((row) => [row.windowIndex, row.chunkHash]));
|
|
166597
|
+
}
|
|
166598
|
+
function chunkEmbeddingWindowsAreCurrent(db, compartmentId, modelId, windows, projectPath) {
|
|
166599
|
+
const existing = getExistingChunkHashes(db, compartmentId, modelId, projectPath);
|
|
166600
|
+
if (existing.size !== windows.length)
|
|
166601
|
+
return false;
|
|
166602
|
+
return windows.every((window) => existing.get(window.windowIndex) === window.chunkHash);
|
|
166603
|
+
}
|
|
166604
|
+
function replaceCompartmentChunkEmbeddings(db, rows) {
|
|
166605
|
+
if (rows.length === 0)
|
|
166606
|
+
return;
|
|
166607
|
+
const compartmentId = rows[0].compartmentId;
|
|
166608
|
+
const now = Date.now();
|
|
166609
|
+
db.transaction(() => {
|
|
166610
|
+
getDeleteByCompartmentStatement(db).run(compartmentId);
|
|
166611
|
+
const insert = getInsertEmbeddingStatement(db);
|
|
166612
|
+
for (const row of rows) {
|
|
166613
|
+
insert.run(row.compartmentId, row.sessionId, row.projectPath, getHarness(), row.window.windowIndex, row.window.startOrdinal, row.window.endOrdinal, row.window.chunkHash, row.modelId, row.vector.length, vectorBlob(row.vector), row.createdAt ?? now);
|
|
166614
|
+
}
|
|
166615
|
+
})();
|
|
166616
|
+
}
|
|
166617
|
+
function getDistinctChunkEmbeddingModelIds(db, projectPath) {
|
|
166618
|
+
const rows = getDistinctModelStatement(db).all(projectPath);
|
|
166619
|
+
return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
|
|
166620
|
+
}
|
|
166621
|
+
function clearChunkEmbeddingsForProject(db, projectPath, modelId) {
|
|
166622
|
+
if (modelId) {
|
|
166623
|
+
return getClearProjectModelStatement(db).run(projectPath, modelId).changes;
|
|
166624
|
+
}
|
|
166625
|
+
return getClearProjectStatement(db).run(projectPath).changes;
|
|
166626
|
+
}
|
|
166627
|
+
function loadCompartmentChunkEmbeddingsForSearch(db, sessionId, projectPath, modelId) {
|
|
166628
|
+
const rows = modelId ? getSearchRowsStatement(db, true).all(sessionId, projectPath, modelId) : getSearchRowsStatement(db, false).all(sessionId, projectPath);
|
|
166629
|
+
return rows.filter((row) => typeof row.compartmentId === "number" && typeof row.sessionId === "string" && typeof row.title === "string" && typeof row.compartmentStart === "number" && typeof row.compartmentEnd === "number" && typeof row.windowIndex === "number" && typeof row.windowStart === "number" && typeof row.windowEnd === "number" && typeof row.chunkHash === "string" && typeof row.modelId === "string" && typeof row.dims === "number" && (row.vector instanceof Uint8Array || row.vector instanceof ArrayBuffer)).map((row) => ({
|
|
166630
|
+
compartmentId: row.compartmentId,
|
|
166631
|
+
sessionId: row.sessionId,
|
|
166632
|
+
title: row.title,
|
|
166633
|
+
startOrdinal: row.compartmentStart,
|
|
166634
|
+
endOrdinal: row.compartmentEnd,
|
|
166635
|
+
windowIndex: row.windowIndex,
|
|
166636
|
+
windowStartOrdinal: row.windowStart,
|
|
166637
|
+
windowEndOrdinal: row.windowEnd,
|
|
166638
|
+
chunkHash: row.chunkHash,
|
|
166639
|
+
modelId: row.modelId,
|
|
166640
|
+
dims: row.dims,
|
|
166641
|
+
vector: toFloat32Array2(row.vector)
|
|
166642
|
+
}));
|
|
166643
|
+
}
|
|
166644
|
+
function mapBackfillCandidateRows(rows) {
|
|
166645
|
+
return rows.filter((row) => {
|
|
166646
|
+
if (row === null || typeof row !== "object")
|
|
166647
|
+
return false;
|
|
166648
|
+
const candidate = row;
|
|
166649
|
+
return typeof candidate.id === "number" && typeof candidate.sessionId === "string" && typeof candidate.startMessage === "number" && typeof candidate.endMessage === "number" && typeof candidate.title === "string";
|
|
166650
|
+
}).map((row) => ({
|
|
166651
|
+
id: row.id,
|
|
166652
|
+
sessionId: row.sessionId,
|
|
166653
|
+
startMessage: row.startMessage,
|
|
166654
|
+
endMessage: row.endMessage,
|
|
166655
|
+
title: row.title
|
|
166656
|
+
}));
|
|
166657
|
+
}
|
|
166658
|
+
var sessionBackfillCandidateStatements = new WeakMap;
|
|
166659
|
+
function loadUnembeddedSessionChunkCandidates(db, projectPath, sessionId, modelId, limit, excludeIds) {
|
|
166660
|
+
if (excludeIds && excludeIds.length > 0) {
|
|
166661
|
+
const placeholders3 = excludeIds.map(() => "?").join(", ");
|
|
166662
|
+
const stmt2 = db.prepare(`SELECT c.id AS id,
|
|
166663
|
+
c.session_id AS sessionId,
|
|
166664
|
+
c.start_message AS startMessage,
|
|
166665
|
+
c.end_message AS endMessage,
|
|
166666
|
+
c.title AS title
|
|
166667
|
+
FROM compartments c
|
|
166668
|
+
JOIN session_projects sp
|
|
166669
|
+
ON sp.session_id = c.session_id
|
|
166670
|
+
AND sp.harness = c.harness
|
|
166671
|
+
AND sp.project_path = ?
|
|
166672
|
+
WHERE c.session_id = ?
|
|
166673
|
+
AND c.start_message IS NOT NULL
|
|
166674
|
+
AND c.end_message IS NOT NULL
|
|
166675
|
+
AND c.id NOT IN (${placeholders3})
|
|
166676
|
+
AND NOT EXISTS (
|
|
166677
|
+
SELECT 1
|
|
166678
|
+
FROM compartment_chunk_embeddings current
|
|
166679
|
+
WHERE current.compartment_id = c.id
|
|
166680
|
+
AND current.project_path = ?
|
|
166681
|
+
AND current.model_id = ?
|
|
166682
|
+
)
|
|
166683
|
+
ORDER BY c.start_message ASC, c.id ASC
|
|
166684
|
+
LIMIT ?`);
|
|
166685
|
+
const rows2 = stmt2.all(projectPath, sessionId, ...excludeIds, projectPath, modelId, Math.max(1, limit));
|
|
166686
|
+
return mapBackfillCandidateRows(rows2);
|
|
166687
|
+
}
|
|
166688
|
+
let stmt = sessionBackfillCandidateStatements.get(db);
|
|
166689
|
+
if (!stmt) {
|
|
166690
|
+
stmt = db.prepare(`SELECT c.id AS id,
|
|
166691
|
+
c.session_id AS sessionId,
|
|
166692
|
+
c.start_message AS startMessage,
|
|
166693
|
+
c.end_message AS endMessage,
|
|
166694
|
+
c.title AS title
|
|
166695
|
+
FROM compartments c
|
|
166696
|
+
JOIN session_projects sp
|
|
166697
|
+
ON sp.session_id = c.session_id
|
|
166698
|
+
AND sp.harness = c.harness
|
|
166699
|
+
AND sp.project_path = ?
|
|
166700
|
+
WHERE c.session_id = ?
|
|
166701
|
+
AND c.start_message IS NOT NULL
|
|
166702
|
+
AND c.end_message IS NOT NULL
|
|
166703
|
+
AND NOT EXISTS (
|
|
166704
|
+
SELECT 1
|
|
166705
|
+
FROM compartment_chunk_embeddings current
|
|
166706
|
+
WHERE current.compartment_id = c.id
|
|
166707
|
+
AND current.project_path = ?
|
|
166708
|
+
AND current.model_id = ?
|
|
166709
|
+
)
|
|
166710
|
+
ORDER BY c.start_message ASC, c.id ASC
|
|
166711
|
+
LIMIT ?`);
|
|
166712
|
+
sessionBackfillCandidateStatements.set(db, stmt);
|
|
166713
|
+
}
|
|
166714
|
+
const rows = stmt.all(projectPath, sessionId, projectPath, modelId, Math.max(1, limit));
|
|
166715
|
+
return mapBackfillCandidateRows(rows);
|
|
166716
|
+
}
|
|
166717
|
+
function countUnembeddedSessionCompartments(db, projectPath, sessionId, modelId) {
|
|
166718
|
+
const row = db.prepare(`SELECT COUNT(*) AS n
|
|
166719
|
+
FROM compartments c
|
|
166720
|
+
JOIN session_projects sp
|
|
166721
|
+
ON sp.session_id = c.session_id
|
|
166722
|
+
AND sp.harness = c.harness
|
|
166723
|
+
AND sp.project_path = ?
|
|
166724
|
+
WHERE c.session_id = ?
|
|
166725
|
+
AND c.start_message IS NOT NULL
|
|
166726
|
+
AND c.end_message IS NOT NULL
|
|
166727
|
+
AND NOT EXISTS (
|
|
166728
|
+
SELECT 1
|
|
166729
|
+
FROM compartment_chunk_embeddings current
|
|
166730
|
+
WHERE current.compartment_id = c.id
|
|
166731
|
+
AND current.project_path = ?
|
|
166732
|
+
AND current.model_id = ?
|
|
166733
|
+
)`).get(projectPath, sessionId, projectPath, modelId);
|
|
166734
|
+
return typeof row?.n === "number" ? row.n : 0;
|
|
166735
|
+
}
|
|
166736
|
+
|
|
165653
166737
|
// ../plugin/src/features/magic-context/memory/cosine-similarity.ts
|
|
165654
166738
|
function cosineSimilarity(a, b) {
|
|
165655
166739
|
if (a.length !== b.length) {
|
|
@@ -165808,19 +166892,19 @@ function isArrayLikeNumber(value) {
|
|
|
165808
166892
|
}
|
|
165809
166893
|
return arr.length === 0 || typeof arr[0] === "number";
|
|
165810
166894
|
}
|
|
165811
|
-
function
|
|
166895
|
+
function toFloat32Array3(values) {
|
|
165812
166896
|
return values instanceof Float32Array ? new Float32Array(values) : Float32Array.from(Array.from(values));
|
|
165813
166897
|
}
|
|
165814
166898
|
function extractBatchEmbeddings(result, expectedCount) {
|
|
165815
166899
|
const { data } = result;
|
|
165816
166900
|
if (Array.isArray(data) && data.length === expectedCount && data.every((entry) => typeof entry !== "number" && isArrayLikeNumber(entry))) {
|
|
165817
|
-
return data.map((entry) =>
|
|
166901
|
+
return data.map((entry) => toFloat32Array3(entry));
|
|
165818
166902
|
}
|
|
165819
166903
|
if (!isArrayLikeNumber(data)) {
|
|
165820
166904
|
log("[magic-context] embedding batch returned unexpected data shape");
|
|
165821
166905
|
return Array.from({ length: expectedCount }, () => null);
|
|
165822
166906
|
}
|
|
165823
|
-
const flatData =
|
|
166907
|
+
const flatData = toFloat32Array3(data);
|
|
165824
166908
|
const dimension = result.dims?.at(-1) ?? flatData.length / expectedCount;
|
|
165825
166909
|
if (!Number.isInteger(dimension) || dimension <= 0 || flatData.length !== expectedCount * dimension) {
|
|
165826
166910
|
log("[magic-context] embedding batch returned invalid dimensions");
|
|
@@ -165835,6 +166919,7 @@ function extractBatchEmbeddings(result, expectedCount) {
|
|
|
165835
166919
|
|
|
165836
166920
|
class LocalEmbeddingProvider {
|
|
165837
166921
|
modelId;
|
|
166922
|
+
maxInputTokens;
|
|
165838
166923
|
model;
|
|
165839
166924
|
pipeline = null;
|
|
165840
166925
|
initPromise = null;
|
|
@@ -165842,8 +166927,9 @@ class LocalEmbeddingProvider {
|
|
|
165842
166927
|
disposing = false;
|
|
165843
166928
|
disposePromise = null;
|
|
165844
166929
|
inFlightWaiters = [];
|
|
165845
|
-
constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL) {
|
|
166930
|
+
constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512) {
|
|
165846
166931
|
this.model = model;
|
|
166932
|
+
this.maxInputTokens = maxInputTokens;
|
|
165847
166933
|
this.modelId = getEmbeddingProviderIdentity({ provider: "local", model });
|
|
165848
166934
|
}
|
|
165849
166935
|
async initialize() {
|
|
@@ -166091,6 +167177,13 @@ function blockedEmbeddingEndpointReason(endpoint) {
|
|
|
166091
167177
|
function normalizeEndpoint2(endpoint) {
|
|
166092
167178
|
return endpoint?.trim().replace(/\/+$/, "") ?? "";
|
|
166093
167179
|
}
|
|
167180
|
+
function embeddingModelsMatch(served, requested) {
|
|
167181
|
+
const a = served.trim().toLowerCase();
|
|
167182
|
+
const b = requested.trim().toLowerCase();
|
|
167183
|
+
if (a.length === 0 || b.length === 0)
|
|
167184
|
+
return true;
|
|
167185
|
+
return a === b || a.includes(b) || b.includes(a);
|
|
167186
|
+
}
|
|
166094
167187
|
var FAILURE_THRESHOLD = 3;
|
|
166095
167188
|
var FAILURE_WINDOW_MS = 60000;
|
|
166096
167189
|
var OPEN_DURATION_MS = 5 * 60000;
|
|
@@ -166098,6 +167191,7 @@ var FETCH_TIMEOUT_MS = 30000;
|
|
|
166098
167191
|
|
|
166099
167192
|
class OpenAICompatibleEmbeddingProvider {
|
|
166100
167193
|
modelId;
|
|
167194
|
+
maxInputTokens;
|
|
166101
167195
|
endpoint;
|
|
166102
167196
|
model;
|
|
166103
167197
|
apiKey;
|
|
@@ -166107,6 +167201,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
166107
167201
|
failureTimes = [];
|
|
166108
167202
|
circuitOpenUntil = 0;
|
|
166109
167203
|
openLogged = false;
|
|
167204
|
+
modelMismatchLogged = false;
|
|
166110
167205
|
halfOpenProbeInFlight = false;
|
|
166111
167206
|
constructor(options) {
|
|
166112
167207
|
this.endpoint = normalizeEndpoint2(options.endpoint);
|
|
@@ -166114,11 +167209,13 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
166114
167209
|
this.apiKey = options.apiKey?.trim() ?? "";
|
|
166115
167210
|
this.inputType = options.inputType?.trim() ?? "";
|
|
166116
167211
|
this.truncate = options.truncate?.trim() ?? "";
|
|
167212
|
+
this.maxInputTokens = typeof options.maxInputTokens === "number" && Number.isFinite(options.maxInputTokens) ? Math.max(1, Math.floor(options.maxInputTokens)) : 512;
|
|
166117
167213
|
this.modelId = getEmbeddingProviderIdentity({
|
|
166118
167214
|
provider: "openai-compatible",
|
|
166119
167215
|
endpoint: this.endpoint,
|
|
166120
167216
|
model: this.model,
|
|
166121
|
-
...this.apiKey ? { api_key: this.apiKey } : {}
|
|
167217
|
+
...this.apiKey ? { api_key: this.apiKey } : {},
|
|
167218
|
+
...this.inputType ? { input_type: this.inputType } : {}
|
|
166122
167219
|
});
|
|
166123
167220
|
}
|
|
166124
167221
|
async initialize() {
|
|
@@ -166203,6 +167300,15 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
166203
167300
|
this.recordFailure(isProbe);
|
|
166204
167301
|
return Array.from({ length: texts.length }, () => null);
|
|
166205
167302
|
}
|
|
167303
|
+
const servedModel = typeof body.model === "string" ? body.model : "";
|
|
167304
|
+
if (this.model && servedModel && !embeddingModelsMatch(servedModel, this.model)) {
|
|
167305
|
+
if (!this.modelMismatchLogged) {
|
|
167306
|
+
log(`[magic-context] embedding endpoint served a DIFFERENT model than requested — refusing the substituted vectors (they have the wrong dimensions/space). requested="${this.model}" served="${servedModel}". The endpoint likely substituted a loaded model; load/select "${this.model}" on the endpoint, or set embedding.model to the served model.`);
|
|
167307
|
+
this.modelMismatchLogged = true;
|
|
167308
|
+
}
|
|
167309
|
+
this.recordFailure(isProbe);
|
|
167310
|
+
return Array.from({ length: texts.length }, () => null);
|
|
167311
|
+
}
|
|
166206
167312
|
const items = Array.isArray(body.data) ? body.data : [];
|
|
166207
167313
|
const results = Array.from({ length: texts.length }, (_, index) => {
|
|
166208
167314
|
const embedding = items[index]?.embedding;
|
|
@@ -166309,7 +167415,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
166309
167415
|
}
|
|
166310
167416
|
|
|
166311
167417
|
// ../plugin/src/features/magic-context/project-embedding-registry.ts
|
|
166312
|
-
import { createHash as
|
|
167418
|
+
import { createHash as createHash9, randomUUID } from "node:crypto";
|
|
166313
167419
|
init_logger();
|
|
166314
167420
|
|
|
166315
167421
|
// ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
|
|
@@ -166317,7 +167423,7 @@ var saveStatements = new WeakMap;
|
|
|
166317
167423
|
var loadProjectStatements = new WeakMap;
|
|
166318
167424
|
var loadUnembeddedStatements = new WeakMap;
|
|
166319
167425
|
var countEmbeddedStatements = new WeakMap;
|
|
166320
|
-
var
|
|
167426
|
+
var clearProjectStatements2 = new WeakMap;
|
|
166321
167427
|
var distinctModelIdStatements = new WeakMap;
|
|
166322
167428
|
function getSaveStatement(db) {
|
|
166323
167429
|
let stmt = saveStatements.get(db);
|
|
@@ -166365,12 +167471,12 @@ function getCountEmbeddedStatement(db) {
|
|
|
166365
167471
|
}
|
|
166366
167472
|
return stmt;
|
|
166367
167473
|
}
|
|
166368
|
-
function
|
|
166369
|
-
let stmt =
|
|
167474
|
+
function getClearProjectStatement2(db) {
|
|
167475
|
+
let stmt = clearProjectStatements2.get(db);
|
|
166370
167476
|
if (!stmt) {
|
|
166371
167477
|
stmt = db.prepare(`DELETE FROM git_commit_embeddings
|
|
166372
167478
|
WHERE sha IN (SELECT sha FROM git_commits WHERE project_path = ?)`);
|
|
166373
|
-
|
|
167479
|
+
clearProjectStatements2.set(db, stmt);
|
|
166374
167480
|
}
|
|
166375
167481
|
return stmt;
|
|
166376
167482
|
}
|
|
@@ -166406,7 +167512,7 @@ function countEmbeddedCommits(db, projectPath) {
|
|
|
166406
167512
|
return row?.count ?? 0;
|
|
166407
167513
|
}
|
|
166408
167514
|
function clearProjectCommitEmbeddings(db, projectPath) {
|
|
166409
|
-
return
|
|
167515
|
+
return getClearProjectStatement2(db).run(projectPath).changes;
|
|
166410
167516
|
}
|
|
166411
167517
|
function getDistinctCommitEmbeddingModelIds(db, projectPath) {
|
|
166412
167518
|
const rows = getDistinctModelIdStatement(db).all(projectPath);
|
|
@@ -166532,9 +167638,83 @@ function releaseGitSweepLease(db, projectPath, holderId) {
|
|
|
166532
167638
|
});
|
|
166533
167639
|
}
|
|
166534
167640
|
|
|
167641
|
+
// ../plugin/src/features/magic-context/session-project-storage.ts
|
|
167642
|
+
var upsertSessionProjectStatements = new WeakMap;
|
|
167643
|
+
var repairSessionChunkProjectStatements = new WeakMap;
|
|
167644
|
+
var repairProjectChunkProjectStatements = new WeakMap;
|
|
167645
|
+
function getUpsertSessionProjectStatement(db) {
|
|
167646
|
+
let stmt = upsertSessionProjectStatements.get(db);
|
|
167647
|
+
if (!stmt) {
|
|
167648
|
+
stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
|
|
167649
|
+
VALUES (?, ?, ?, ?)
|
|
167650
|
+
ON CONFLICT(session_id, harness) DO UPDATE SET
|
|
167651
|
+
project_path = excluded.project_path,
|
|
167652
|
+
updated_at = excluded.updated_at
|
|
167653
|
+
WHERE session_projects.project_path <> excluded.project_path`);
|
|
167654
|
+
upsertSessionProjectStatements.set(db, stmt);
|
|
167655
|
+
}
|
|
167656
|
+
return stmt;
|
|
167657
|
+
}
|
|
167658
|
+
function getRepairSessionChunkProjectStatement(db) {
|
|
167659
|
+
let stmt = repairSessionChunkProjectStatements.get(db);
|
|
167660
|
+
if (!stmt) {
|
|
167661
|
+
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
167662
|
+
SET project_path = ?
|
|
167663
|
+
WHERE session_id = ?
|
|
167664
|
+
AND harness = ?
|
|
167665
|
+
AND project_path <> ?`);
|
|
167666
|
+
repairSessionChunkProjectStatements.set(db, stmt);
|
|
167667
|
+
}
|
|
167668
|
+
return stmt;
|
|
167669
|
+
}
|
|
167670
|
+
function getRepairProjectChunkProjectStatement(db) {
|
|
167671
|
+
let stmt = repairProjectChunkProjectStatements.get(db);
|
|
167672
|
+
if (!stmt) {
|
|
167673
|
+
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
167674
|
+
SET project_path = (
|
|
167675
|
+
SELECT sp.project_path
|
|
167676
|
+
FROM session_projects sp
|
|
167677
|
+
WHERE sp.session_id = compartment_chunk_embeddings.session_id
|
|
167678
|
+
AND sp.harness = compartment_chunk_embeddings.harness
|
|
167679
|
+
LIMIT 1
|
|
167680
|
+
)
|
|
167681
|
+
WHERE EXISTS (
|
|
167682
|
+
SELECT 1
|
|
167683
|
+
FROM session_projects sp
|
|
167684
|
+
WHERE sp.session_id = compartment_chunk_embeddings.session_id
|
|
167685
|
+
AND sp.harness = compartment_chunk_embeddings.harness
|
|
167686
|
+
AND sp.project_path <> compartment_chunk_embeddings.project_path
|
|
167687
|
+
AND (
|
|
167688
|
+
sp.project_path = ?
|
|
167689
|
+
OR compartment_chunk_embeddings.project_path = ?
|
|
167690
|
+
)
|
|
167691
|
+
)`);
|
|
167692
|
+
repairProjectChunkProjectStatements.set(db, stmt);
|
|
167693
|
+
}
|
|
167694
|
+
return stmt;
|
|
167695
|
+
}
|
|
167696
|
+
function recordSessionProjectIdentity(db, sessionId, projectPath) {
|
|
167697
|
+
if (!sessionId || !projectPath)
|
|
167698
|
+
return;
|
|
167699
|
+
const harness = getHarness();
|
|
167700
|
+
const now = Date.now();
|
|
167701
|
+
db.transaction(() => {
|
|
167702
|
+
getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
|
|
167703
|
+
getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
|
|
167704
|
+
})();
|
|
167705
|
+
}
|
|
167706
|
+
function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
|
|
167707
|
+
if (!projectPath)
|
|
167708
|
+
return 0;
|
|
167709
|
+
return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
|
|
167710
|
+
}
|
|
167711
|
+
|
|
166535
167712
|
// ../plugin/src/features/magic-context/project-embedding-registry.ts
|
|
166536
167713
|
var OFF_PROVIDER_IDENTITY = "embedding-provider:off";
|
|
166537
167714
|
var SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
|
|
167715
|
+
var CHUNK_DRAIN_BATCH_SIZE = 8;
|
|
167716
|
+
var MAX_WINDOWS_PER_EMBED_CALL = 16;
|
|
167717
|
+
var SESSION_EMBED_LEASE_RENEWAL_MS = 60 * 1000;
|
|
166538
167718
|
var projectRegistrations = new Map;
|
|
166539
167719
|
var loadUnembeddedMemoriesStatements = new WeakMap;
|
|
166540
167720
|
var globalRegistrationGeneration = 0;
|
|
@@ -166543,7 +167723,10 @@ function resolveEmbeddingConfig(config2) {
|
|
|
166543
167723
|
if (!config2 || config2.provider === "local") {
|
|
166544
167724
|
return {
|
|
166545
167725
|
provider: "local",
|
|
166546
|
-
model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
167726
|
+
model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
167727
|
+
...config2?.max_input_tokens ? {
|
|
167728
|
+
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
167729
|
+
} : {}
|
|
166547
167730
|
};
|
|
166548
167731
|
}
|
|
166549
167732
|
if (config2.provider === "openai-compatible") {
|
|
@@ -166556,7 +167739,10 @@ function resolveEmbeddingConfig(config2) {
|
|
|
166556
167739
|
endpoint: config2.endpoint.trim(),
|
|
166557
167740
|
...apiKey ? { api_key: apiKey } : {},
|
|
166558
167741
|
...inputType ? { input_type: inputType } : {},
|
|
166559
|
-
...truncate ? { truncate } : {}
|
|
167742
|
+
...truncate ? { truncate } : {},
|
|
167743
|
+
...config2.max_input_tokens ? {
|
|
167744
|
+
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
167745
|
+
} : {}
|
|
166560
167746
|
};
|
|
166561
167747
|
}
|
|
166562
167748
|
return { provider: "off" };
|
|
@@ -166574,10 +167760,11 @@ function createProvider(config2) {
|
|
|
166574
167760
|
model: config2.model,
|
|
166575
167761
|
apiKey: config2.api_key,
|
|
166576
167762
|
inputType: config2.input_type,
|
|
166577
|
-
truncate: config2.truncate
|
|
167763
|
+
truncate: config2.truncate,
|
|
167764
|
+
maxInputTokens: config2.max_input_tokens
|
|
166578
167765
|
});
|
|
166579
167766
|
}
|
|
166580
|
-
return new LocalEmbeddingProvider(config2.model);
|
|
167767
|
+
return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
|
|
166581
167768
|
}
|
|
166582
167769
|
function stableStringify2(value) {
|
|
166583
167770
|
if (Array.isArray(value)) {
|
|
@@ -166590,7 +167777,7 @@ function stableStringify2(value) {
|
|
|
166590
167777
|
return JSON.stringify(value);
|
|
166591
167778
|
}
|
|
166592
167779
|
function sha256Prefix(value, length = 16) {
|
|
166593
|
-
return
|
|
167780
|
+
return createHash9("sha256").update(value).digest("hex").slice(0, length);
|
|
166594
167781
|
}
|
|
166595
167782
|
function getRuntimeFingerprint(config2) {
|
|
166596
167783
|
if (config2.provider === "off") {
|
|
@@ -166598,6 +167785,18 @@ function getRuntimeFingerprint(config2) {
|
|
|
166598
167785
|
}
|
|
166599
167786
|
return `${getEmbeddingProviderIdentity(config2)}:${sha256Prefix(stableStringify2(config2))}`;
|
|
166600
167787
|
}
|
|
167788
|
+
function getChunkEmbeddingModelId(config2, providerIdentity) {
|
|
167789
|
+
if (config2.provider === "off") {
|
|
167790
|
+
return OFF_PROVIDER_IDENTITY;
|
|
167791
|
+
}
|
|
167792
|
+
const chunkIdentity = {
|
|
167793
|
+
providerIdentity,
|
|
167794
|
+
chunkerVersion: 2,
|
|
167795
|
+
maxInputTokens: normalizeCompartmentChunkMaxInputTokens("max_input_tokens" in config2 ? config2.max_input_tokens : undefined),
|
|
167796
|
+
truncate: config2.provider === "openai-compatible" ? config2.truncate ?? "" : ""
|
|
167797
|
+
};
|
|
167798
|
+
return `${providerIdentity}:chunk:${sha256Prefix(stableStringify2(chunkIdentity))}`;
|
|
167799
|
+
}
|
|
166601
167800
|
function sameFeatures(a, b) {
|
|
166602
167801
|
return a.memoryEnabled === b.memoryEnabled && a.gitCommitEnabled === b.gitCommitEnabled;
|
|
166603
167802
|
}
|
|
@@ -166614,7 +167813,8 @@ function snapshotFor(registration) {
|
|
|
166614
167813
|
features: { ...registration.features },
|
|
166615
167814
|
enabled,
|
|
166616
167815
|
gitCommitEnabled,
|
|
166617
|
-
modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId
|
|
167816
|
+
modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
|
|
167817
|
+
chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId
|
|
166618
167818
|
};
|
|
166619
167819
|
}
|
|
166620
167820
|
function disposeProvider(provider) {
|
|
@@ -166634,7 +167834,7 @@ function anyStoredModelIdIsStale(storedIds, currentId) {
|
|
|
166634
167834
|
}
|
|
166635
167835
|
return false;
|
|
166636
167836
|
}
|
|
166637
|
-
function maybeWipeStaleEmbeddings(db, projectIdentity, currentProviderIdentity, features) {
|
|
167837
|
+
function maybeWipeStaleEmbeddings(db, projectIdentity, currentProviderIdentity, currentChunkIdentity, features) {
|
|
166638
167838
|
if (currentProviderIdentity === OFF_PROVIDER_IDENTITY) {
|
|
166639
167839
|
return false;
|
|
166640
167840
|
}
|
|
@@ -166655,6 +167855,14 @@ function maybeWipeStaleEmbeddings(db, projectIdentity, currentProviderIdentity,
|
|
|
166655
167855
|
wiped = true;
|
|
166656
167856
|
}
|
|
166657
167857
|
}
|
|
167858
|
+
if (features.memoryEnabled) {
|
|
167859
|
+
repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectIdentity);
|
|
167860
|
+
const chunkIds = getDistinctChunkEmbeddingModelIds(db, projectIdentity);
|
|
167861
|
+
if (anyStoredModelIdIsStale(chunkIds, currentChunkIdentity)) {
|
|
167862
|
+
clearChunkEmbeddingsForProject(db, projectIdentity);
|
|
167863
|
+
wiped = true;
|
|
167864
|
+
}
|
|
167865
|
+
}
|
|
166658
167866
|
})();
|
|
166659
167867
|
return wiped;
|
|
166660
167868
|
}
|
|
@@ -166662,10 +167870,11 @@ function registerProjectEmbeddingAndMaybeWipe(db, projectIdentity, config2, feat
|
|
|
166662
167870
|
const resolvedConfig = resolveEmbeddingConfig(config2);
|
|
166663
167871
|
const providerIdentity = getEmbeddingProviderIdentity(resolvedConfig);
|
|
166664
167872
|
const runtimeFingerprint = getRuntimeFingerprint(resolvedConfig);
|
|
167873
|
+
const chunkModelId = getChunkEmbeddingModelId(resolvedConfig, providerIdentity);
|
|
166665
167874
|
const prior = projectRegistrations.get(projectIdentity);
|
|
166666
167875
|
const canReuseProvider = prior !== undefined && !prior.observationMode && prior.runtimeFingerprint === runtimeFingerprint && prior.providerIdentity === providerIdentity;
|
|
166667
|
-
const wiped = maybeWipeStaleEmbeddings(db, projectIdentity, providerIdentity, features);
|
|
166668
|
-
const generationChanged = prior === undefined || prior.observationMode || prior.runtimeFingerprint !== runtimeFingerprint || !sameFeatures(prior.features, features) || wiped;
|
|
167876
|
+
const wiped = maybeWipeStaleEmbeddings(db, projectIdentity, providerIdentity, chunkModelId, features);
|
|
167877
|
+
const generationChanged = prior === undefined || prior.observationMode || prior.runtimeFingerprint !== runtimeFingerprint || prior.chunkModelId !== chunkModelId || !sameFeatures(prior.features, features) || wiped;
|
|
166669
167878
|
const generation = generationChanged ? ++globalRegistrationGeneration : prior.generation;
|
|
166670
167879
|
const registration = {
|
|
166671
167880
|
projectIdentity,
|
|
@@ -166677,6 +167886,7 @@ function registerProjectEmbeddingAndMaybeWipe(db, projectIdentity, config2, feat
|
|
|
166677
167886
|
generation,
|
|
166678
167887
|
features: { ...features },
|
|
166679
167888
|
modelId: providerIdentity === OFF_PROVIDER_IDENTITY ? "off" : providerIdentity,
|
|
167889
|
+
chunkModelId: providerIdentity === OFF_PROVIDER_IDENTITY ? "off" : chunkModelId,
|
|
166680
167890
|
observationMode: false
|
|
166681
167891
|
};
|
|
166682
167892
|
projectRegistrations.set(projectIdentity, registration);
|
|
@@ -166699,6 +167909,7 @@ function registerProjectInObservationMode(db, projectIdentity, sourceDirectory,
|
|
|
166699
167909
|
generation,
|
|
166700
167910
|
features: { memoryEnabled: false, gitCommitEnabled: false },
|
|
166701
167911
|
modelId: "off",
|
|
167912
|
+
chunkModelId: "off",
|
|
166702
167913
|
observationMode: true
|
|
166703
167914
|
};
|
|
166704
167915
|
projectRegistrations.set(projectIdentity, registration);
|
|
@@ -166709,6 +167920,15 @@ function getProjectEmbeddingSnapshot(projectIdentity) {
|
|
|
166709
167920
|
const registration = projectRegistrations.get(projectIdentity);
|
|
166710
167921
|
return registration ? snapshotFor(registration) : null;
|
|
166711
167922
|
}
|
|
167923
|
+
function getProjectChunkEmbeddingModelId(projectIdentity) {
|
|
167924
|
+
const registration = projectRegistrations.get(projectIdentity);
|
|
167925
|
+
return registration && !registration.observationMode ? registration.chunkModelId : "off";
|
|
167926
|
+
}
|
|
167927
|
+
function getProjectEmbeddingMaxInputTokens(projectIdentity) {
|
|
167928
|
+
const registration = projectRegistrations.get(projectIdentity);
|
|
167929
|
+
const configMax = registration?.config && "max_input_tokens" in registration.config ? registration.config.max_input_tokens : undefined;
|
|
167930
|
+
return normalizeCompartmentChunkMaxInputTokens(registration?.provider?.maxInputTokens ?? configMax);
|
|
167931
|
+
}
|
|
166712
167932
|
function getOrCreateProjectProvider(registration) {
|
|
166713
167933
|
if (registration.providerIdentity === OFF_PROVIDER_IDENTITY || registration.observationMode) {
|
|
166714
167934
|
return null;
|
|
@@ -166803,6 +168023,131 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
|
|
|
166803
168023
|
return 0;
|
|
166804
168024
|
}
|
|
166805
168025
|
}
|
|
168026
|
+
async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates, signal) {
|
|
168027
|
+
const noWork = [];
|
|
168028
|
+
if (candidates.length === 0)
|
|
168029
|
+
return { embedded: 0, noWork };
|
|
168030
|
+
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
|
|
168031
|
+
const prepared = [];
|
|
168032
|
+
for (const candidate of candidates) {
|
|
168033
|
+
const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage);
|
|
168034
|
+
if (canonicalText.length === 0) {
|
|
168035
|
+
noWork.push(candidate.id);
|
|
168036
|
+
continue;
|
|
168037
|
+
}
|
|
168038
|
+
const windows = chunkCanonicalText(canonicalText, candidate.startMessage, candidate.endMessage, maxInputTokens);
|
|
168039
|
+
if (windows.length === 0 || chunkEmbeddingWindowsAreCurrent(db, candidate.id, modelId, windows, projectIdentity)) {
|
|
168040
|
+
noWork.push(candidate.id);
|
|
168041
|
+
continue;
|
|
168042
|
+
}
|
|
168043
|
+
prepared.push({ candidate, windows });
|
|
168044
|
+
}
|
|
168045
|
+
if (prepared.length === 0)
|
|
168046
|
+
return { embedded: 0, noWork };
|
|
168047
|
+
let embedded = 0;
|
|
168048
|
+
let i = 0;
|
|
168049
|
+
while (i < prepared.length) {
|
|
168050
|
+
if (signal?.aborted)
|
|
168051
|
+
break;
|
|
168052
|
+
const slice = [];
|
|
168053
|
+
let windowCount = 0;
|
|
168054
|
+
do {
|
|
168055
|
+
const item = prepared[i];
|
|
168056
|
+
slice.push(item);
|
|
168057
|
+
windowCount += item.windows.length;
|
|
168058
|
+
i += 1;
|
|
168059
|
+
} while (i < prepared.length && windowCount + prepared[i].windows.length <= MAX_WINDOWS_PER_EMBED_CALL);
|
|
168060
|
+
const texts = [];
|
|
168061
|
+
for (const item of slice)
|
|
168062
|
+
texts.push(...item.windows.map((w) => w.text));
|
|
168063
|
+
try {
|
|
168064
|
+
const result = await embedBatchForProject(projectIdentity, texts, signal);
|
|
168065
|
+
if (!result)
|
|
168066
|
+
continue;
|
|
168067
|
+
if (signal?.aborted)
|
|
168068
|
+
break;
|
|
168069
|
+
let offset = 0;
|
|
168070
|
+
for (const item of slice) {
|
|
168071
|
+
const vectors = result.vectors.slice(offset, offset + item.windows.length);
|
|
168072
|
+
offset += item.windows.length;
|
|
168073
|
+
if (vectors.length !== item.windows.length || vectors.some((v) => !v)) {
|
|
168074
|
+
continue;
|
|
168075
|
+
}
|
|
168076
|
+
const rows = item.windows.map((window, index) => ({
|
|
168077
|
+
compartmentId: item.candidate.id,
|
|
168078
|
+
sessionId: item.candidate.sessionId,
|
|
168079
|
+
projectPath: projectIdentity,
|
|
168080
|
+
window,
|
|
168081
|
+
modelId,
|
|
168082
|
+
vector: vectors[index]
|
|
168083
|
+
}));
|
|
168084
|
+
replaceCompartmentChunkEmbeddings(db, rows);
|
|
168085
|
+
embedded += 1;
|
|
168086
|
+
}
|
|
168087
|
+
} catch (error51) {
|
|
168088
|
+
log("[magic-context] failed to proactively embed compartment chunks:", error51);
|
|
168089
|
+
}
|
|
168090
|
+
}
|
|
168091
|
+
return { embedded, noWork };
|
|
168092
|
+
}
|
|
168093
|
+
async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, options) {
|
|
168094
|
+
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
168095
|
+
if (!snapshot?.enabled || snapshot.chunkModelId === "off") {
|
|
168096
|
+
return { status: "disabled", embedded: 0, total: 0 };
|
|
168097
|
+
}
|
|
168098
|
+
recordSessionProjectIdentity(db, sessionId, projectIdentity);
|
|
168099
|
+
const total = countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot.chunkModelId);
|
|
168100
|
+
if (total === 0)
|
|
168101
|
+
return { status: "nothing", embedded: 0, total: 0 };
|
|
168102
|
+
const holderId = `session-embed-${randomUUID()}`;
|
|
168103
|
+
const lease2 = acquireGitSweepLease(db, projectIdentity, holderId, { ignoreCooldown: true });
|
|
168104
|
+
if (!lease2.acquired)
|
|
168105
|
+
return { status: "busy", embedded: 0, total };
|
|
168106
|
+
const renewal = setInterval(() => {
|
|
168107
|
+
try {
|
|
168108
|
+
renewGitSweepLease(db, projectIdentity, holderId);
|
|
168109
|
+
} catch {}
|
|
168110
|
+
}, SESSION_EMBED_LEASE_RENEWAL_MS);
|
|
168111
|
+
renewal.unref?.();
|
|
168112
|
+
const batchSize = Math.max(1, options?.batchSize ?? CHUNK_DRAIN_BATCH_SIZE);
|
|
168113
|
+
const skipIds = [];
|
|
168114
|
+
let embedded = 0;
|
|
168115
|
+
let aborted2 = false;
|
|
168116
|
+
let providerStalled = false;
|
|
168117
|
+
try {
|
|
168118
|
+
options?.onProgress?.({ embedded, total });
|
|
168119
|
+
for (;; ) {
|
|
168120
|
+
if (options?.signal?.aborted) {
|
|
168121
|
+
aborted2 = true;
|
|
168122
|
+
break;
|
|
168123
|
+
}
|
|
168124
|
+
const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, skipIds);
|
|
168125
|
+
if (candidates.length === 0)
|
|
168126
|
+
break;
|
|
168127
|
+
const { embedded: n, noWork } = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, options?.signal);
|
|
168128
|
+
for (const id of noWork)
|
|
168129
|
+
skipIds.push(id);
|
|
168130
|
+
if (n === 0 && noWork.length === 0) {
|
|
168131
|
+
providerStalled = true;
|
|
168132
|
+
break;
|
|
168133
|
+
}
|
|
168134
|
+
embedded += n;
|
|
168135
|
+
options?.onProgress?.({ embedded: Math.min(embedded, total), total });
|
|
168136
|
+
await new Promise((resolve4) => setTimeout(resolve4, 0));
|
|
168137
|
+
}
|
|
168138
|
+
} finally {
|
|
168139
|
+
clearInterval(renewal);
|
|
168140
|
+
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
168141
|
+
}
|
|
168142
|
+
if (aborted2)
|
|
168143
|
+
return { status: "aborted", embedded, total };
|
|
168144
|
+
if (providerStalled) {
|
|
168145
|
+
const remaining = Math.max(0, countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot.chunkModelId) - skipIds.length);
|
|
168146
|
+
if (remaining > 0)
|
|
168147
|
+
return { status: "stalled", embedded, total, remaining };
|
|
168148
|
+
}
|
|
168149
|
+
return { status: "done", embedded, total };
|
|
168150
|
+
}
|
|
166806
168151
|
|
|
166807
168152
|
// ../plugin/src/features/magic-context/memory/embedding.ts
|
|
166808
168153
|
var DEFAULT_EMBEDDING_CONFIG = {
|
|
@@ -166822,10 +168167,11 @@ function createProvider2(config2) {
|
|
|
166822
168167
|
model: config2.model,
|
|
166823
168168
|
apiKey: config2.api_key,
|
|
166824
168169
|
inputType: config2.input_type,
|
|
166825
|
-
truncate: config2.truncate
|
|
168170
|
+
truncate: config2.truncate,
|
|
168171
|
+
maxInputTokens: config2.max_input_tokens
|
|
166826
168172
|
});
|
|
166827
168173
|
}
|
|
166828
|
-
return new LocalEmbeddingProvider(config2.model);
|
|
168174
|
+
return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
|
|
166829
168175
|
}
|
|
166830
168176
|
function getOrCreateProvider() {
|
|
166831
168177
|
if (provider) {
|
|
@@ -167068,6 +168414,7 @@ init_logger();
|
|
|
167068
168414
|
// ../plugin/src/features/magic-context/memory/storage-memory-fts.ts
|
|
167069
168415
|
var DEFAULT_SEARCH_LIMIT = 10;
|
|
167070
168416
|
var searchStatements = new WeakMap;
|
|
168417
|
+
var unionSearchStatements = new Map;
|
|
167071
168418
|
function getSearchStatement(db) {
|
|
167072
168419
|
let stmt = searchStatements.get(db);
|
|
167073
168420
|
if (!stmt) {
|
|
@@ -167076,6 +168423,23 @@ function getSearchStatement(db) {
|
|
|
167076
168423
|
}
|
|
167077
168424
|
return stmt;
|
|
167078
168425
|
}
|
|
168426
|
+
function getUnionSearchStatement(db, arity) {
|
|
168427
|
+
let statements = unionSearchStatements.get(arity);
|
|
168428
|
+
if (!statements) {
|
|
168429
|
+
statements = new WeakMap;
|
|
168430
|
+
unionSearchStatements.set(arity, statements);
|
|
168431
|
+
}
|
|
168432
|
+
let stmt = statements.get(db);
|
|
168433
|
+
if (!stmt) {
|
|
168434
|
+
const placeholders3 = Array.from({ length: arity }, () => "?").join(", ");
|
|
168435
|
+
stmt = db.prepare(`SELECT ${getMemorySelectColumns(db)} FROM memories_fts INNER JOIN memories ON memories.id = memories_fts.rowid WHERE memories.project_path IN (${placeholders3}) AND memories.status IN ('active', 'permanent') AND (memories.expires_at IS NULL OR memories.expires_at > ?) AND memories_fts MATCH ? ORDER BY bm25(memories_fts), memories.updated_at DESC, memories.id ASC LIMIT ?`);
|
|
168436
|
+
statements.set(db, stmt);
|
|
168437
|
+
}
|
|
168438
|
+
return stmt;
|
|
168439
|
+
}
|
|
168440
|
+
function uniqueProjectPaths2(projectPaths) {
|
|
168441
|
+
return [...new Set(projectPaths.filter((path7) => path7.length > 0))];
|
|
168442
|
+
}
|
|
167079
168443
|
function sanitizeFtsQuery(query) {
|
|
167080
168444
|
const tokens = query.split(/\s+/).filter((token) => token.length > 0);
|
|
167081
168445
|
if (tokens.length === 0)
|
|
@@ -167094,6 +168458,28 @@ function searchMemoriesFTS(db, projectPath, query, limit = DEFAULT_SEARCH_LIMIT)
|
|
|
167094
168458
|
const rows = getSearchStatement(db).all(projectPath, Date.now(), sanitized, limit).filter(isMemoryRow);
|
|
167095
168459
|
return rows.map(toMemory);
|
|
167096
168460
|
}
|
|
168461
|
+
function searchMemoriesFTSUnion(db, projectPaths, query, limit = DEFAULT_SEARCH_LIMIT, ownIdentities, shareCategories) {
|
|
168462
|
+
const identities = uniqueProjectPaths2(projectPaths);
|
|
168463
|
+
if (identities.length === 0)
|
|
168464
|
+
return [];
|
|
168465
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
168466
|
+
identities,
|
|
168467
|
+
ownIdentities,
|
|
168468
|
+
shareCategories,
|
|
168469
|
+
tableName: "memories"
|
|
168470
|
+
});
|
|
168471
|
+
if (identities.length === 1 && !sharingFilter.active) {
|
|
168472
|
+
return searchMemoriesFTS(db, identities[0], query, limit);
|
|
168473
|
+
}
|
|
168474
|
+
const trimmedQuery = query.trim();
|
|
168475
|
+
if (trimmedQuery.length === 0 || limit <= 0)
|
|
168476
|
+
return [];
|
|
168477
|
+
const sanitized = sanitizeFtsQuery(trimmedQuery);
|
|
168478
|
+
if (sanitized.length === 0)
|
|
168479
|
+
return [];
|
|
168480
|
+
const rows = sharingFilter.active ? db.prepare(`SELECT ${getMemorySelectColumns(db)} FROM memories_fts INNER JOIN memories ON memories.id = memories_fts.rowid WHERE memories.project_path IN (${identities.map(() => "?").join(", ")}) AND memories.status IN ('active', 'permanent') AND (memories.expires_at IS NULL OR memories.expires_at > ?) AND memories_fts MATCH ?${sharingFilter.clause} ORDER BY bm25(memories_fts), memories.updated_at DESC, memories.id ASC LIMIT ?`).all(...identities, Date.now(), sanitized, ...sharingFilter.params, limit).filter(isMemoryRow) : getUnionSearchStatement(db, identities.length).all(...identities, Date.now(), sanitized, limit).filter(isMemoryRow);
|
|
168481
|
+
return rows.map(toMemory);
|
|
168482
|
+
}
|
|
167097
168483
|
|
|
167098
168484
|
// ../plugin/src/features/magic-context/git-commits/search-git-commits.ts
|
|
167099
168485
|
var ftsStatements = new WeakMap;
|
|
@@ -167386,7 +168772,7 @@ async function sweepGitCommits(args) {
|
|
|
167386
168772
|
}
|
|
167387
168773
|
|
|
167388
168774
|
// ../plugin/src/plugin/embedding-bootstrap-helpers.ts
|
|
167389
|
-
import { createHash as
|
|
168775
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
167390
168776
|
init_logger();
|
|
167391
168777
|
var EMBEDDING_AFFECTING_KEYS = new Set([
|
|
167392
168778
|
"embedding.api_key",
|
|
@@ -167408,7 +168794,7 @@ var EMBEDDING_WARNING_TERMS = [
|
|
|
167408
168794
|
];
|
|
167409
168795
|
var loggedFailureSignatures = new Map;
|
|
167410
168796
|
function sha256Prefix2(value, length = 16) {
|
|
167411
|
-
return
|
|
168797
|
+
return createHash10("sha256").update(value).digest("hex").slice(0, length);
|
|
167412
168798
|
}
|
|
167413
168799
|
function warningLooksEmbeddingRelated(message) {
|
|
167414
168800
|
const lower = message.toLowerCase();
|
|
@@ -168450,6 +169836,88 @@ function registerCtxDreamCommand(pi, deps) {
|
|
|
168450
169836
|
});
|
|
168451
169837
|
}
|
|
168452
169838
|
|
|
169839
|
+
// src/commands/ctx-embed-history.ts
|
|
169840
|
+
function registerCtxEmbedHistoryCommand(pi, deps) {
|
|
169841
|
+
pi.registerCommand("ctx-embed-history", {
|
|
169842
|
+
description: "Embed all of this session's history compartments for semantic search, in one pass",
|
|
169843
|
+
handler: async (_args, ctx) => {
|
|
169844
|
+
const sessionId = resolveSessionId(ctx);
|
|
169845
|
+
if (!sessionId) {
|
|
169846
|
+
sendCtxStatusMessage(pi, {
|
|
169847
|
+
title: "/ctx-embed-history",
|
|
169848
|
+
text: `## /ctx-embed-history
|
|
169849
|
+
|
|
169850
|
+
No active Pi session is available.`,
|
|
169851
|
+
level: "error"
|
|
169852
|
+
});
|
|
169853
|
+
return;
|
|
169854
|
+
}
|
|
169855
|
+
if (deps.memoryEnabled === false) {
|
|
169856
|
+
sendCtxStatusMessage(pi, {
|
|
169857
|
+
title: "/ctx-embed-history",
|
|
169858
|
+
text: `## /ctx-embed-history
|
|
169859
|
+
|
|
169860
|
+
Memory is disabled for this project, so there is no semantic embedding to backfill.`,
|
|
169861
|
+
level: "info"
|
|
169862
|
+
});
|
|
169863
|
+
return;
|
|
169864
|
+
}
|
|
169865
|
+
const project = deps.resolveProject?.(ctx) ?? {
|
|
169866
|
+
projectDir: deps.projectDir,
|
|
169867
|
+
projectIdentity: deps.projectIdentity
|
|
169868
|
+
};
|
|
169869
|
+
await ensureProjectRegisteredFromPiDirectory(project.projectDir, deps.db);
|
|
169870
|
+
const outcome = await embedSessionCompartmentChunks(deps.db, project.projectIdentity, sessionId);
|
|
169871
|
+
const { text, level } = (() => {
|
|
169872
|
+
switch (outcome.status) {
|
|
169873
|
+
case "nothing":
|
|
169874
|
+
return {
|
|
169875
|
+
text: `## /ctx-embed-history
|
|
169876
|
+
|
|
169877
|
+
All of this session's history is already embedded.`,
|
|
169878
|
+
level: "info"
|
|
169879
|
+
};
|
|
169880
|
+
case "disabled":
|
|
169881
|
+
return {
|
|
169882
|
+
text: `## /ctx-embed-history
|
|
169883
|
+
|
|
169884
|
+
No embedding provider is configured, so there is nothing to embed.`,
|
|
169885
|
+
level: "info"
|
|
169886
|
+
};
|
|
169887
|
+
case "busy":
|
|
169888
|
+
return {
|
|
169889
|
+
text: `## /ctx-embed-history
|
|
169890
|
+
|
|
169891
|
+
Embedding is already running for this project — ${outcome.total} compartment${outcome.total === 1 ? "" : "s"} still pending. Try again shortly.`,
|
|
169892
|
+
level: "info"
|
|
169893
|
+
};
|
|
169894
|
+
case "stalled":
|
|
169895
|
+
return {
|
|
169896
|
+
text: `## /ctx-embed-history
|
|
169897
|
+
|
|
169898
|
+
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.`,
|
|
169899
|
+
level: "info"
|
|
169900
|
+
};
|
|
169901
|
+
default:
|
|
169902
|
+
return {
|
|
169903
|
+
text: `## /ctx-embed-history
|
|
169904
|
+
|
|
169905
|
+
Embedded ${outcome.embedded} compartment${outcome.embedded === 1 ? "" : "s"} of history for semantic search.`,
|
|
169906
|
+
level: "success"
|
|
169907
|
+
};
|
|
169908
|
+
}
|
|
169909
|
+
})();
|
|
169910
|
+
sendCtxStatusMessage(pi, { title: "/ctx-embed-history", text, level }, {
|
|
169911
|
+
sessionId,
|
|
169912
|
+
projectIdentity: project.projectIdentity,
|
|
169913
|
+
status: outcome.status,
|
|
169914
|
+
embedded: outcome.embedded,
|
|
169915
|
+
total: outcome.total
|
|
169916
|
+
});
|
|
169917
|
+
}
|
|
169918
|
+
});
|
|
169919
|
+
}
|
|
169920
|
+
|
|
168453
169921
|
// ../plugin/src/hooks/magic-context/execute-flush.ts
|
|
168454
169922
|
init_logger();
|
|
168455
169923
|
function executeFlush(db, sessionId) {
|
|
@@ -168863,6 +170331,51 @@ function computePiWorkMetrics(sessionEntries) {
|
|
|
168863
170331
|
return { newWorkTokens, totalInputTokens };
|
|
168864
170332
|
}
|
|
168865
170333
|
|
|
170334
|
+
// ../plugin/src/hooks/magic-context/system-injection-stripper.ts
|
|
170335
|
+
var SYSTEM_INJECTION_MARKERS = [
|
|
170336
|
+
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
170337
|
+
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
170338
|
+
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
170339
|
+
"[Category+Skill Reminder]",
|
|
170340
|
+
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
170341
|
+
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
170342
|
+
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
170343
|
+
"Unstable background agent appears idle",
|
|
170344
|
+
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
170345
|
+
];
|
|
170346
|
+
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
170347
|
+
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
170348
|
+
function stripSystemInjection(text) {
|
|
170349
|
+
let hasInjection = false;
|
|
170350
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
170351
|
+
if (text.includes(marker)) {
|
|
170352
|
+
hasInjection = true;
|
|
170353
|
+
break;
|
|
170354
|
+
}
|
|
170355
|
+
}
|
|
170356
|
+
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
170357
|
+
hasInjection = true;
|
|
170358
|
+
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
170359
|
+
if (!hasInjection)
|
|
170360
|
+
return null;
|
|
170361
|
+
let cleaned = text;
|
|
170362
|
+
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
170363
|
+
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
170364
|
+
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
170365
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
170366
|
+
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
170367
|
+
continue;
|
|
170368
|
+
const idx = cleaned.indexOf(marker);
|
|
170369
|
+
if (idx === -1)
|
|
170370
|
+
continue;
|
|
170371
|
+
const blockEnd = cleaned.indexOf(`
|
|
170372
|
+
|
|
170373
|
+
`, idx + marker.length);
|
|
170374
|
+
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
170375
|
+
}
|
|
170376
|
+
return cleaned.trim();
|
|
170377
|
+
}
|
|
170378
|
+
|
|
168866
170379
|
// ../plugin/src/hooks/magic-context/apply-operations.ts
|
|
168867
170380
|
var USER_DROP_PREVIEW_CHARS = 250;
|
|
168868
170381
|
var RECENT_TOOL_SKELETON_WINDOW = 20;
|
|
@@ -168872,6 +170385,10 @@ function buildReplacementContent(tagId, target) {
|
|
|
168872
170385
|
return `[dropped §${tagId}§]`;
|
|
168873
170386
|
}
|
|
168874
170387
|
const currentContent = target.getContent?.() ?? "";
|
|
170388
|
+
const strippedInjection = stripSystemInjection(currentContent);
|
|
170389
|
+
if (strippedInjection !== null && stripTagPrefix(strippedInjection).trim().length === 0) {
|
|
170390
|
+
return `[dropped §${tagId}§]`;
|
|
170391
|
+
}
|
|
168875
170392
|
const originalText = stripTagPrefix(currentContent);
|
|
168876
170393
|
if (originalText.length <= USER_DROP_PREVIEW_CHARS) {
|
|
168877
170394
|
return `[truncated §${tagId}§]
|
|
@@ -170480,8 +171997,8 @@ var CHANNEL1_SENTINEL = "<system-reminder>";
|
|
|
170480
171997
|
var TOKENS_PER_BYTE = 0.25;
|
|
170481
171998
|
var CHANNEL1_FLOOR_TOKENS = 1e4;
|
|
170482
171999
|
var CHANNEL1_REFIRE_FLOOR_TOKENS = 1e4;
|
|
170483
|
-
function channel1RefireTokens(
|
|
170484
|
-
const scaled = Math.round(0.05 * Math.max(0,
|
|
172000
|
+
function channel1RefireTokens(workingWindowTokens) {
|
|
172001
|
+
const scaled = Math.round(0.05 * Math.max(0, workingWindowTokens));
|
|
170485
172002
|
return Math.max(CHANNEL1_REFIRE_FLOOR_TOKENS, scaled);
|
|
170486
172003
|
}
|
|
170487
172004
|
var S_GENTLE = 0.2;
|
|
@@ -170497,7 +172014,7 @@ function toolOutputTokens(output) {
|
|
|
170497
172014
|
return Math.round(byteSize(output) * TOKENS_PER_BYTE);
|
|
170498
172015
|
}
|
|
170499
172016
|
function decideChannel1(input) {
|
|
170500
|
-
const { undroppedTokens, pressure,
|
|
172017
|
+
const { undroppedTokens, pressure, workingWindowTokens, hasRecentReduce } = input;
|
|
170501
172018
|
const resetCycle = hasRecentReduce || undroppedTokens < input.lastNudgeUndropped;
|
|
170502
172019
|
const lastNudge = resetCycle ? 0 : input.lastNudgeUndropped;
|
|
170503
172020
|
const lastLevel = resetCycle ? "" : input.lastNudgeLevel;
|
|
@@ -170512,7 +172029,7 @@ function decideChannel1(input) {
|
|
|
170512
172029
|
return quiet();
|
|
170513
172030
|
if (undroppedTokens < CHANNEL1_FLOOR_TOKENS)
|
|
170514
172031
|
return quiet();
|
|
170515
|
-
const budget =
|
|
172032
|
+
const budget = workingWindowTokens > 0 ? workingWindowTokens : undroppedTokens || 1;
|
|
170516
172033
|
const severity = undroppedTokens / budget * pressure;
|
|
170517
172034
|
if (severity < S_GENTLE)
|
|
170518
172035
|
return quiet();
|
|
@@ -170524,7 +172041,7 @@ function decideChannel1(input) {
|
|
|
170524
172041
|
else
|
|
170525
172042
|
level = "gentle";
|
|
170526
172043
|
if (lastLevel === "") {
|
|
170527
|
-
if (undroppedTokens < lastNudge + channel1RefireTokens(
|
|
172044
|
+
if (undroppedTokens < lastNudge + channel1RefireTokens(workingWindowTokens)) {
|
|
170528
172045
|
return quiet();
|
|
170529
172046
|
}
|
|
170530
172047
|
} else if (LEVEL_RANK[level] <= LEVEL_RANK[lastLevel]) {
|
|
@@ -170569,13 +172086,13 @@ function buildChannel1Reminder(level, undroppedTokens) {
|
|
|
170569
172086
|
let body;
|
|
170570
172087
|
switch (level) {
|
|
170571
172088
|
case "gentle":
|
|
170572
|
-
body = `You have ~${amount} tokens of tool output you have not reduced. ` + `
|
|
172089
|
+
body = `You have ~${amount} tokens of tool output you have not reduced. ` + `When you are done with earlier outputs, dropping them with ctx_reduce keeps context lean.`;
|
|
170573
172090
|
break;
|
|
170574
172091
|
case "firm":
|
|
170575
|
-
body = `~${amount} tokens of unreduced tool output
|
|
172092
|
+
body = `~${amount} tokens of unreduced tool output has built up. ` + `At your next natural stopping point, consider dropping what you have already processed with ctx_reduce.`;
|
|
170576
172093
|
break;
|
|
170577
172094
|
case "urgent":
|
|
170578
|
-
body = `~${amount} tokens of unreduced tool output remain
|
|
172095
|
+
body = `~${amount} tokens of unreduced tool output remain, and a large span of this session will be comparted before long. ` + `Consider dropping spent outputs with ctx_reduce so the archived span is the part that matters.`;
|
|
170579
172096
|
break;
|
|
170580
172097
|
}
|
|
170581
172098
|
return `
|
|
@@ -170585,53 +172102,6 @@ ${body}
|
|
|
170585
172102
|
</system-reminder>`;
|
|
170586
172103
|
}
|
|
170587
172104
|
|
|
170588
|
-
// ../plugin/src/features/magic-context/memory/constants.ts
|
|
170589
|
-
var V2_MEMORY_CATEGORIES = [
|
|
170590
|
-
"PROJECT_RULES",
|
|
170591
|
-
"ARCHITECTURE",
|
|
170592
|
-
"CONSTRAINTS",
|
|
170593
|
-
"CONFIG_VALUES",
|
|
170594
|
-
"NAMING"
|
|
170595
|
-
];
|
|
170596
|
-
var PROMOTABLE_CATEGORIES = [
|
|
170597
|
-
"PROJECT_RULES",
|
|
170598
|
-
"ARCHITECTURE",
|
|
170599
|
-
"CONSTRAINTS",
|
|
170600
|
-
"CONFIG_VALUES",
|
|
170601
|
-
"NAMING",
|
|
170602
|
-
"ARCHITECTURE_DECISIONS",
|
|
170603
|
-
"CONFIG_DEFAULTS",
|
|
170604
|
-
"USER_PREFERENCES",
|
|
170605
|
-
"USER_DIRECTIVES",
|
|
170606
|
-
"ENVIRONMENT",
|
|
170607
|
-
"WORKFLOW_RULES",
|
|
170608
|
-
"KNOWN_ISSUES"
|
|
170609
|
-
];
|
|
170610
|
-
var CATEGORY_PRIORITY = [
|
|
170611
|
-
"PROJECT_RULES",
|
|
170612
|
-
"ARCHITECTURE",
|
|
170613
|
-
"CONSTRAINTS",
|
|
170614
|
-
"CONFIG_VALUES",
|
|
170615
|
-
"NAMING",
|
|
170616
|
-
"USER_DIRECTIVES",
|
|
170617
|
-
"USER_PREFERENCES",
|
|
170618
|
-
"CONFIG_DEFAULTS",
|
|
170619
|
-
"ARCHITECTURE_DECISIONS",
|
|
170620
|
-
"ENVIRONMENT",
|
|
170621
|
-
"WORKFLOW_RULES",
|
|
170622
|
-
"KNOWN_ISSUES"
|
|
170623
|
-
];
|
|
170624
|
-
var MEMORY_CATEGORY_ORDER_UNKNOWN = 99;
|
|
170625
|
-
var MEMORY_CATEGORY_ORDER_PRIORITY = CATEGORY_PRIORITY.reduce((acc, category, index) => {
|
|
170626
|
-
acc[category] = index;
|
|
170627
|
-
return acc;
|
|
170628
|
-
}, {});
|
|
170629
|
-
var MEMORY_CATEGORY_ORDER_SQL = `CASE category ${CATEGORY_PRIORITY.map((category, index) => `WHEN '${category}' THEN ${index}`).join(" ")} ELSE ${MEMORY_CATEGORY_ORDER_UNKNOWN} END`;
|
|
170630
|
-
var CATEGORY_DEFAULT_TTL = {
|
|
170631
|
-
WORKFLOW_RULES: 90 * 24 * 60 * 60 * 1000,
|
|
170632
|
-
KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
|
|
170633
|
-
};
|
|
170634
|
-
|
|
170635
172105
|
// ../plugin/src/shared/bounded-session-map.ts
|
|
170636
172106
|
class BoundedSessionMap {
|
|
170637
172107
|
maxEntries;
|
|
@@ -171042,26 +172512,40 @@ ${sections.join(`
|
|
|
171042
172512
|
var DEFAULT_MEMORY_BUDGET_TOKENS = 8000;
|
|
171043
172513
|
var MEMORY_BLOCK_WRAPPER_TOKENS = 6;
|
|
171044
172514
|
var DEFAULT_USER_PROFILE_BUDGET_TOKENS = 4000;
|
|
172515
|
+
function memoryCanonicalIdentity(memory, workspace) {
|
|
172516
|
+
return resolveStoredPathWorkspaceIdentity(memory.projectPath, workspace.identities, workspace.canonicalIdentityByStoredPath);
|
|
172517
|
+
}
|
|
172518
|
+
function memorySelectionOrder(left, right) {
|
|
172519
|
+
if (left.status === "permanent" && right.status !== "permanent")
|
|
172520
|
+
return -1;
|
|
172521
|
+
if (right.status === "permanent" && left.status !== "permanent")
|
|
172522
|
+
return 1;
|
|
172523
|
+
const leftImportance = left.importance ?? Number.NEGATIVE_INFINITY;
|
|
172524
|
+
const rightImportance = right.importance ?? Number.NEGATIVE_INFINITY;
|
|
172525
|
+
const importanceDiff = rightImportance - leftImportance;
|
|
172526
|
+
if (importanceDiff !== 0)
|
|
172527
|
+
return importanceDiff;
|
|
172528
|
+
return left.id - right.id;
|
|
172529
|
+
}
|
|
172530
|
+
function memoryRenderOrder(left, right) {
|
|
172531
|
+
const aPriority = MEMORY_CATEGORY_ORDER_PRIORITY[left.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
172532
|
+
const bPriority = MEMORY_CATEGORY_ORDER_PRIORITY[right.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
172533
|
+
const categoryDiff = aPriority - bPriority;
|
|
172534
|
+
if (categoryDiff !== 0)
|
|
172535
|
+
return categoryDiff;
|
|
172536
|
+
return left.id - right.id;
|
|
172537
|
+
}
|
|
171045
172538
|
var maxCompartmentSeqStatements = new WeakMap;
|
|
171046
172539
|
var maxMemoryIdStatements = new WeakMap;
|
|
171047
172540
|
var legacyCompartmentCountStatements = new WeakMap;
|
|
171048
172541
|
var m0CompartmentStatements = new WeakMap;
|
|
171049
172542
|
var newCompartmentStatements = new WeakMap;
|
|
171050
|
-
function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens) {
|
|
171051
|
-
const selectionOrder = [...memories].sort(
|
|
171052
|
-
if (a.status === "permanent" && b.status !== "permanent")
|
|
171053
|
-
return -1;
|
|
171054
|
-
if (b.status === "permanent" && a.status !== "permanent")
|
|
171055
|
-
return 1;
|
|
171056
|
-
const importanceDiff = (b.importance ?? 50) - (a.importance ?? 50);
|
|
171057
|
-
if (importanceDiff !== 0)
|
|
171058
|
-
return importanceDiff;
|
|
171059
|
-
return a.id - b.id;
|
|
171060
|
-
});
|
|
172543
|
+
function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens, renderOptions = {}) {
|
|
172544
|
+
const selectionOrder = [...memories].sort(memorySelectionOrder);
|
|
171061
172545
|
const selected = [];
|
|
171062
172546
|
let usedTokens = MEMORY_BLOCK_WRAPPER_TOKENS;
|
|
171063
172547
|
for (const memory of selectionOrder) {
|
|
171064
|
-
const memoryTokens = estimateTokens(renderMemoryLineV2(memory));
|
|
172548
|
+
const memoryTokens = estimateTokens(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
171065
172549
|
if (usedTokens + memoryTokens > budgetTokens)
|
|
171066
172550
|
continue;
|
|
171067
172551
|
selected.push(memory);
|
|
@@ -171070,16 +172554,70 @@ function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens) {
|
|
|
171070
172554
|
if (selected.length < memories.length) {
|
|
171071
172555
|
sessionLog(sessionId, `v2 trimmed memories from ${memories.length} to ${selected.length} to fit injection budget of ${budgetTokens} tokens`);
|
|
171072
172556
|
}
|
|
171073
|
-
const renderOrder = [...selected].sort(
|
|
171074
|
-
const aPriority = MEMORY_CATEGORY_ORDER_PRIORITY[a.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
171075
|
-
const bPriority = MEMORY_CATEGORY_ORDER_PRIORITY[b.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
171076
|
-
const categoryDiff = aPriority - bPriority;
|
|
171077
|
-
if (categoryDiff !== 0)
|
|
171078
|
-
return categoryDiff;
|
|
171079
|
-
return a.id - b.id;
|
|
171080
|
-
});
|
|
172557
|
+
const renderOrder = [...selected].sort(memoryRenderOrder);
|
|
171081
172558
|
return { selected, renderOrder };
|
|
171082
172559
|
}
|
|
172560
|
+
function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, workspace, renderOptions = {}) {
|
|
172561
|
+
if (!workspace.isWorkspaced) {
|
|
172562
|
+
return trimMemoriesToBudgetV2(sessionId, memories, budgetTokens, renderOptions);
|
|
172563
|
+
}
|
|
172564
|
+
const selected = [];
|
|
172565
|
+
const selectedIds = new Set;
|
|
172566
|
+
let usedTokens = MEMORY_BLOCK_WRAPPER_TOKENS;
|
|
172567
|
+
const tokenCost = (memory) => estimateTokens(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
172568
|
+
const trySelect = (memory) => {
|
|
172569
|
+
if (selectedIds.has(memory.id))
|
|
172570
|
+
return false;
|
|
172571
|
+
const tokens = tokenCost(memory);
|
|
172572
|
+
if (usedTokens + tokens > budgetTokens)
|
|
172573
|
+
return false;
|
|
172574
|
+
selected.push(memory);
|
|
172575
|
+
selectedIds.add(memory.id);
|
|
172576
|
+
usedTokens += tokens;
|
|
172577
|
+
return true;
|
|
172578
|
+
};
|
|
172579
|
+
for (const memory of memories.filter((candidate) => candidate.status === "permanent").sort(memorySelectionOrder)) {
|
|
172580
|
+
trySelect(memory);
|
|
172581
|
+
}
|
|
172582
|
+
const remainingAfterPermanent = Math.max(0, budgetTokens - usedTokens);
|
|
172583
|
+
const floorTokens = remainingAfterPermanent / Math.max(1, workspace.identities.length);
|
|
172584
|
+
const byIdentity = new Map;
|
|
172585
|
+
for (const memory of memories) {
|
|
172586
|
+
if (memory.status === "permanent")
|
|
172587
|
+
continue;
|
|
172588
|
+
const identity = memoryCanonicalIdentity(memory, workspace);
|
|
172589
|
+
if (!identity)
|
|
172590
|
+
continue;
|
|
172591
|
+
const list = byIdentity.get(identity) ?? [];
|
|
172592
|
+
list.push(memory);
|
|
172593
|
+
byIdentity.set(identity, list);
|
|
172594
|
+
}
|
|
172595
|
+
for (const identity of workspace.identities) {
|
|
172596
|
+
let memberTokens = 0;
|
|
172597
|
+
const candidates = (byIdentity.get(identity) ?? []).sort(memorySelectionOrder);
|
|
172598
|
+
for (const memory of candidates) {
|
|
172599
|
+
if (selectedIds.has(memory.id))
|
|
172600
|
+
continue;
|
|
172601
|
+
const tokens = tokenCost(memory);
|
|
172602
|
+
if (memberTokens + tokens > floorTokens)
|
|
172603
|
+
continue;
|
|
172604
|
+
if (usedTokens + tokens > budgetTokens)
|
|
172605
|
+
continue;
|
|
172606
|
+
selected.push(memory);
|
|
172607
|
+
selectedIds.add(memory.id);
|
|
172608
|
+
usedTokens += tokens;
|
|
172609
|
+
memberTokens += tokens;
|
|
172610
|
+
}
|
|
172611
|
+
}
|
|
172612
|
+
const remaining = memories.filter((memory) => !selectedIds.has(memory.id)).sort(memorySelectionOrder);
|
|
172613
|
+
for (const memory of remaining) {
|
|
172614
|
+
trySelect(memory);
|
|
172615
|
+
}
|
|
172616
|
+
if (selected.length < memories.length) {
|
|
172617
|
+
sessionLog(sessionId, `v2 trimmed memories from ${memories.length} to ${selected.length} to fit injection budget of ${budgetTokens} tokens`);
|
|
172618
|
+
}
|
|
172619
|
+
return { selected, renderOrder: [...selected].sort(memoryRenderOrder) };
|
|
172620
|
+
}
|
|
171083
172621
|
function trimUserMemoriesToBudget(memories, budgetTokens) {
|
|
171084
172622
|
const selected = [];
|
|
171085
172623
|
let usedTokens = 0;
|
|
@@ -171092,15 +172630,16 @@ function trimUserMemoriesToBudget(memories, budgetTokens) {
|
|
|
171092
172630
|
}
|
|
171093
172631
|
return selected;
|
|
171094
172632
|
}
|
|
171095
|
-
function renderMemoryLineV2(memory) {
|
|
171096
|
-
|
|
172633
|
+
function renderMemoryLineV2(memory, sourceName) {
|
|
172634
|
+
const sourceAttr = sourceName ? ` source="${escapeXmlAttr(sourceName)}"` : "";
|
|
172635
|
+
return ` <memory id="${memory.id}" category="${escapeXmlAttr(memory.category)}"${sourceAttr} importance="${memory.importance ?? 50}">${escapeXmlContent(memory.content)}</memory>`;
|
|
171097
172636
|
}
|
|
171098
|
-
function renderMemoryBlockV2(memories, wrapper = "project-memory") {
|
|
172637
|
+
function renderMemoryBlockV2(memories, wrapper = "project-memory", renderOptions = {}) {
|
|
171099
172638
|
if (memories.length === 0)
|
|
171100
172639
|
return "";
|
|
171101
172640
|
const lines = [`<${wrapper}>`];
|
|
171102
172641
|
for (const memory of memories) {
|
|
171103
|
-
lines.push(renderMemoryLineV2(memory));
|
|
172642
|
+
lines.push(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
171104
172643
|
}
|
|
171105
172644
|
lines.push(`</${wrapper}>`);
|
|
171106
172645
|
return lines.join(`
|
|
@@ -171694,7 +173233,7 @@ async function ensureMemoryEmbeddings(args) {
|
|
|
171694
173233
|
continue;
|
|
171695
173234
|
}
|
|
171696
173235
|
saveEmbedding(args.db, memory.id, embedding, result.modelId);
|
|
171697
|
-
staged.set(memory.id, embedding);
|
|
173236
|
+
staged.set(memory.id, { embedding, modelId: result.modelId });
|
|
171698
173237
|
}
|
|
171699
173238
|
})();
|
|
171700
173239
|
const currentSnapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
@@ -171785,6 +173324,37 @@ function previewText(text) {
|
|
|
171785
173324
|
}
|
|
171786
173325
|
return `${normalized.slice(0, RESULT_PREVIEW_LIMIT - 1).trimEnd()}…`;
|
|
171787
173326
|
}
|
|
173327
|
+
function resolveSearchWorkspaceContext(db, projectPath, identitySet) {
|
|
173328
|
+
const resolved = identitySet ?? resolveWorkspaceIdentitySet(db, projectPath);
|
|
173329
|
+
const isWorkspaced = resolved.identities.length > 1;
|
|
173330
|
+
const expanded = expandWorkspaceIdentitySetWithAliases(db, resolved.identities);
|
|
173331
|
+
const expandedIdentities = isWorkspaced ? expanded.expandedIdentities : resolved.identities;
|
|
173332
|
+
const canonicalIdentityByStoredPath = isWorkspaced ? expanded.canonicalIdentityByStoredPath : new Map(resolved.identities.map((identity) => [identity, identity]));
|
|
173333
|
+
const ownIdentities = expandedIdentities.filter((identity) => canonicalIdentityByStoredPath.get(identity) === projectPath);
|
|
173334
|
+
return {
|
|
173335
|
+
identities: resolved.identities,
|
|
173336
|
+
expandedIdentities,
|
|
173337
|
+
ownIdentities,
|
|
173338
|
+
shareCategories: isWorkspaced ? resolveWorkspaceShareCategories(db, projectPath) : null,
|
|
173339
|
+
namesByIdentity: resolved.namesByIdentity,
|
|
173340
|
+
canonicalIdentityByStoredPath,
|
|
173341
|
+
isWorkspaced
|
|
173342
|
+
};
|
|
173343
|
+
}
|
|
173344
|
+
function memoryWorkspaceIdentity(memory, workspace) {
|
|
173345
|
+
return resolveStoredPathWorkspaceIdentity(memory.projectPath, workspace.identities, workspace.canonicalIdentityByStoredPath);
|
|
173346
|
+
}
|
|
173347
|
+
function sourceNamesForSearchMemories(args) {
|
|
173348
|
+
if (!args.workspace.isWorkspaced)
|
|
173349
|
+
return;
|
|
173350
|
+
const sourceNames = new Map;
|
|
173351
|
+
for (const memory of args.memories) {
|
|
173352
|
+
const source = sourceNameForMemory(memory.projectPath, args.projectPath, args.workspace.identities, args.workspace.namesByIdentity, args.workspace.canonicalIdentityByStoredPath);
|
|
173353
|
+
if (source)
|
|
173354
|
+
sourceNames.set(memory.id, source);
|
|
173355
|
+
}
|
|
173356
|
+
return sourceNames.size > 0 ? sourceNames : undefined;
|
|
173357
|
+
}
|
|
171788
173358
|
function getMessageSearchStatement(db) {
|
|
171789
173359
|
let stmt = messageSearchStatements.get(db);
|
|
171790
173360
|
if (!stmt) {
|
|
@@ -171793,6 +173363,30 @@ function getMessageSearchStatement(db) {
|
|
|
171793
173363
|
}
|
|
171794
173364
|
return stmt;
|
|
171795
173365
|
}
|
|
173366
|
+
var ftsRowCountStatements = new WeakMap;
|
|
173367
|
+
var ftsMatchCountStatements = new WeakMap;
|
|
173368
|
+
function getSessionFtsRowCount(db, sessionId) {
|
|
173369
|
+
let stmt = ftsRowCountStatements.get(db);
|
|
173370
|
+
if (!stmt) {
|
|
173371
|
+
stmt = db.prepare("SELECT COUNT(*) AS n FROM message_history_fts WHERE session_id = ?");
|
|
173372
|
+
ftsRowCountStatements.set(db, stmt);
|
|
173373
|
+
}
|
|
173374
|
+
const row = stmt.get(sessionId);
|
|
173375
|
+
return typeof row?.n === "number" ? row.n : 0;
|
|
173376
|
+
}
|
|
173377
|
+
function countSessionFtsMatches(db, sessionId, ftsQuery) {
|
|
173378
|
+
let stmt = ftsMatchCountStatements.get(db);
|
|
173379
|
+
if (!stmt) {
|
|
173380
|
+
stmt = db.prepare("SELECT COUNT(*) AS n FROM message_history_fts WHERE session_id = ? AND message_history_fts MATCH ?");
|
|
173381
|
+
ftsMatchCountStatements.set(db, stmt);
|
|
173382
|
+
}
|
|
173383
|
+
try {
|
|
173384
|
+
const row = stmt.get(sessionId, ftsQuery);
|
|
173385
|
+
return typeof row?.n === "number" ? row.n : 0;
|
|
173386
|
+
} catch {
|
|
173387
|
+
return 0;
|
|
173388
|
+
}
|
|
173389
|
+
}
|
|
171796
173390
|
function getMessageOrdinal(value) {
|
|
171797
173391
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
171798
173392
|
return value;
|
|
@@ -171808,25 +173402,63 @@ async function getSemanticScores(args) {
|
|
|
171808
173402
|
if (!args.queryEmbedding || args.memories.length === 0) {
|
|
171809
173403
|
return semanticScores;
|
|
171810
173404
|
}
|
|
171811
|
-
|
|
171812
|
-
|
|
171813
|
-
|
|
171814
|
-
|
|
171815
|
-
|
|
171816
|
-
|
|
171817
|
-
|
|
173405
|
+
if (!args.workspace?.isWorkspaced) {
|
|
173406
|
+
const cachedEmbeddings = getProjectEmbeddings(args.db, args.projectPath);
|
|
173407
|
+
const embeddings = await ensureMemoryEmbeddings({
|
|
173408
|
+
db: args.db,
|
|
173409
|
+
projectIdentity: args.projectPath,
|
|
173410
|
+
memories: args.memories,
|
|
173411
|
+
existingEmbeddings: cachedEmbeddings
|
|
173412
|
+
});
|
|
173413
|
+
for (const memory of args.memories) {
|
|
173414
|
+
const memoryEmbedding = embeddings.get(memory.id);
|
|
173415
|
+
if (!memoryEmbedding) {
|
|
173416
|
+
continue;
|
|
173417
|
+
}
|
|
173418
|
+
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding.embedding)));
|
|
173419
|
+
}
|
|
173420
|
+
return semanticScores;
|
|
173421
|
+
}
|
|
173422
|
+
if (!args.queryModelId || args.queryModelId === "off") {
|
|
173423
|
+
return semanticScores;
|
|
173424
|
+
}
|
|
173425
|
+
const workspace = args.workspace;
|
|
173426
|
+
const memoriesByIdentity = new Map;
|
|
171818
173427
|
for (const memory of args.memories) {
|
|
171819
|
-
const
|
|
171820
|
-
if (!
|
|
173428
|
+
const identity = memoryWorkspaceIdentity(memory, workspace);
|
|
173429
|
+
if (!identity)
|
|
173430
|
+
continue;
|
|
173431
|
+
const list = memoriesByIdentity.get(identity) ?? [];
|
|
173432
|
+
list.push(memory);
|
|
173433
|
+
memoriesByIdentity.set(identity, list);
|
|
173434
|
+
}
|
|
173435
|
+
const ownMemories = memoriesByIdentity.get(args.projectPath) ?? [];
|
|
173436
|
+
if (ownMemories.length > 0) {
|
|
173437
|
+
const ownEmbeddings = getProjectEmbeddings(args.db, args.projectPath);
|
|
173438
|
+
await ensureMemoryEmbeddings({
|
|
173439
|
+
db: args.db,
|
|
173440
|
+
projectIdentity: args.projectPath,
|
|
173441
|
+
memories: ownMemories,
|
|
173442
|
+
existingEmbeddings: ownEmbeddings
|
|
173443
|
+
});
|
|
173444
|
+
}
|
|
173445
|
+
for (const identity of workspace.identities) {
|
|
173446
|
+
const memberMemories = memoriesByIdentity.get(identity) ?? [];
|
|
173447
|
+
if (memberMemories.length === 0)
|
|
171821
173448
|
continue;
|
|
173449
|
+
const cachedEmbeddings = getProjectEmbeddings(args.db, identity);
|
|
173450
|
+
for (const memory of memberMemories) {
|
|
173451
|
+
const memoryEmbedding = cachedEmbeddings.get(memory.id);
|
|
173452
|
+
if (!memoryEmbedding || memoryEmbedding.modelId !== args.queryModelId)
|
|
173453
|
+
continue;
|
|
173454
|
+
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding.embedding)));
|
|
171822
173455
|
}
|
|
171823
|
-
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding)));
|
|
171824
173456
|
}
|
|
171825
173457
|
return semanticScores;
|
|
171826
173458
|
}
|
|
171827
173459
|
function getFtsMatches(args) {
|
|
171828
173460
|
try {
|
|
171829
|
-
return searchMemoriesFTS(args.db, args.projectPath, args.query, args.limit);
|
|
173461
|
+
return args.workspace?.isWorkspaced ? searchMemoriesFTSUnion(args.db, args.workspace.expandedIdentities, args.query, args.limit, args.workspace.ownIdentities, args.workspace.shareCategories) : searchMemoriesFTS(args.db, args.projectPath, args.query, args.limit);
|
|
171830
173462
|
} catch (error51) {
|
|
171831
173463
|
log(`[search] FTS query failed for "${args.query}": ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
171832
173464
|
return [];
|
|
@@ -171840,8 +173472,11 @@ function selectSemanticCandidates(args) {
|
|
|
171840
173472
|
return args.memories;
|
|
171841
173473
|
}
|
|
171842
173474
|
const candidateIds = new Set(args.ftsMatches.map((memory) => memory.id));
|
|
171843
|
-
const
|
|
171844
|
-
|
|
173475
|
+
const embeddingProjects = args.workspace?.isWorkspaced ? args.workspace.identities : [args.projectPath];
|
|
173476
|
+
for (const projectPath of embeddingProjects) {
|
|
173477
|
+
const cachedEmbeddings = peekProjectEmbeddings(projectPath);
|
|
173478
|
+
if (!cachedEmbeddings)
|
|
173479
|
+
continue;
|
|
171845
173480
|
for (const memoryId of cachedEmbeddings.keys()) {
|
|
171846
173481
|
candidateIds.add(memoryId);
|
|
171847
173482
|
}
|
|
@@ -171883,7 +173518,8 @@ function mergeMemoryResults(args) {
|
|
|
171883
173518
|
score,
|
|
171884
173519
|
memoryId: memory.id,
|
|
171885
173520
|
category: memory.category,
|
|
171886
|
-
matchType
|
|
173521
|
+
matchType,
|
|
173522
|
+
sourceName: args.sourceNameByMemoryId?.get(memory.id)
|
|
171887
173523
|
});
|
|
171888
173524
|
}
|
|
171889
173525
|
return results.sort((left, right) => {
|
|
@@ -171897,7 +173533,7 @@ async function searchMemories(args) {
|
|
|
171897
173533
|
if (!args.memoryEnabled) {
|
|
171898
173534
|
return [];
|
|
171899
173535
|
}
|
|
171900
|
-
const memories = getMemoriesByProject(args.db, args.projectPath);
|
|
173536
|
+
const memories = args.workspace?.isWorkspaced ? getMemoriesByProjects(args.db, args.workspace.expandedIdentities, ["active", "permanent"], Date.now(), args.workspace.ownIdentities, args.workspace.shareCategories) : getMemoriesByProject(args.db, args.projectPath);
|
|
171901
173537
|
if (memories.length === 0) {
|
|
171902
173538
|
return [];
|
|
171903
173539
|
}
|
|
@@ -171905,26 +173541,43 @@ async function searchMemories(args) {
|
|
|
171905
173541
|
db: args.db,
|
|
171906
173542
|
projectPath: args.projectPath,
|
|
171907
173543
|
query: args.query,
|
|
171908
|
-
limit: FTS_SEMANTIC_CANDIDATE_LIMIT
|
|
173544
|
+
limit: FTS_SEMANTIC_CANDIDATE_LIMIT,
|
|
173545
|
+
workspace: args.workspace
|
|
171909
173546
|
});
|
|
171910
173547
|
const ftsScores = getFtsScores(ftsMatches);
|
|
171911
173548
|
const semanticCandidates = selectSemanticCandidates({
|
|
171912
173549
|
memories,
|
|
171913
173550
|
projectPath: args.projectPath,
|
|
171914
|
-
ftsMatches
|
|
173551
|
+
ftsMatches,
|
|
173552
|
+
workspace: args.workspace
|
|
171915
173553
|
});
|
|
171916
173554
|
const semanticScores = await getSemanticScores({
|
|
171917
173555
|
db: args.db,
|
|
171918
173556
|
projectPath: args.projectPath,
|
|
171919
173557
|
memories: semanticCandidates,
|
|
171920
|
-
queryEmbedding: args.queryEmbedding
|
|
173558
|
+
queryEmbedding: args.queryEmbedding,
|
|
173559
|
+
queryModelId: args.queryModelId,
|
|
173560
|
+
workspace: args.workspace
|
|
171921
173561
|
});
|
|
171922
173562
|
return mergeMemoryResults({
|
|
171923
173563
|
memories,
|
|
171924
173564
|
semanticScores,
|
|
171925
173565
|
ftsScores,
|
|
171926
173566
|
limit: args.limit,
|
|
171927
|
-
visibleMemoryIds: args.visibleMemoryIds
|
|
173567
|
+
visibleMemoryIds: args.visibleMemoryIds,
|
|
173568
|
+
sourceNameByMemoryId: sourceNamesForSearchMemories({
|
|
173569
|
+
memories,
|
|
173570
|
+
projectPath: args.projectPath,
|
|
173571
|
+
workspace: args.workspace ?? {
|
|
173572
|
+
identities: [args.projectPath],
|
|
173573
|
+
expandedIdentities: [args.projectPath],
|
|
173574
|
+
namesByIdentity: new Map,
|
|
173575
|
+
canonicalIdentityByStoredPath: new Map([[args.projectPath, args.projectPath]]),
|
|
173576
|
+
ownIdentities: [args.projectPath],
|
|
173577
|
+
shareCategories: null,
|
|
173578
|
+
isWorkspaced: false
|
|
173579
|
+
}
|
|
173580
|
+
})
|
|
171928
173581
|
});
|
|
171929
173582
|
}
|
|
171930
173583
|
function linearDecayScore(rank, total) {
|
|
@@ -171955,7 +173608,13 @@ function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff) {
|
|
|
171955
173608
|
return result;
|
|
171956
173609
|
}
|
|
171957
173610
|
var RRF_K = 60;
|
|
171958
|
-
var
|
|
173611
|
+
var VERBATIM_RANK_BONUS = 1 / RRF_K;
|
|
173612
|
+
var IDF_FALLOFF = 100;
|
|
173613
|
+
function probeDiscriminationWeight(df, corpusSize) {
|
|
173614
|
+
if (corpusSize <= 0 || df <= 0)
|
|
173615
|
+
return 1;
|
|
173616
|
+
return 1 / (1 + IDF_FALLOFF * df / corpusSize);
|
|
173617
|
+
}
|
|
171959
173618
|
function searchMessages(args) {
|
|
171960
173619
|
const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
|
|
171961
173620
|
const fetchLimit = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.limit * 3 : args.limit;
|
|
@@ -171972,20 +173631,31 @@ function searchMessages(args) {
|
|
|
171972
173631
|
role: row.role
|
|
171973
173632
|
}));
|
|
171974
173633
|
}
|
|
173634
|
+
const corpusSize = getSessionFtsRowCount(args.db, args.sessionId);
|
|
171975
173635
|
const queryLists = [];
|
|
171976
173636
|
if (baseQuery.length > 0) {
|
|
171977
|
-
queryLists.push(
|
|
173637
|
+
queryLists.push({
|
|
173638
|
+
rows: runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff),
|
|
173639
|
+
weight: 1
|
|
173640
|
+
});
|
|
171978
173641
|
}
|
|
173642
|
+
const probeWeights = new Map;
|
|
171979
173643
|
for (const probe of probes) {
|
|
171980
173644
|
const probeQuery = sanitizeFtsQuery(probe);
|
|
171981
173645
|
if (probeQuery.length === 0)
|
|
171982
173646
|
continue;
|
|
171983
|
-
|
|
173647
|
+
const df = countSessionFtsMatches(args.db, args.sessionId, probeQuery);
|
|
173648
|
+
const weight = probeDiscriminationWeight(df, corpusSize);
|
|
173649
|
+
probeWeights.set(probe, weight);
|
|
173650
|
+
queryLists.push({
|
|
173651
|
+
rows: runMessageFtsQuery(args.db, args.sessionId, probeQuery, fetchLimit, cutoff),
|
|
173652
|
+
weight
|
|
173653
|
+
});
|
|
171984
173654
|
}
|
|
171985
173655
|
const fused = new Map;
|
|
171986
173656
|
for (const list of queryLists) {
|
|
171987
|
-
list.forEach((row, rank) => {
|
|
171988
|
-
const rrf =
|
|
173657
|
+
list.rows.forEach((row, rank) => {
|
|
173658
|
+
const rrf = list.weight / (RRF_K + rank);
|
|
171989
173659
|
const existing = fused.get(row.messageId);
|
|
171990
173660
|
if (existing) {
|
|
171991
173661
|
existing.score += rrf;
|
|
@@ -171995,26 +173665,107 @@ function searchMessages(args) {
|
|
|
171995
173665
|
});
|
|
171996
173666
|
}
|
|
171997
173667
|
for (const entry of fused.values()) {
|
|
171998
|
-
|
|
171999
|
-
|
|
173668
|
+
let best = 0;
|
|
173669
|
+
for (const probe of probes) {
|
|
173670
|
+
const weight = probeWeights.get(probe) ?? 0;
|
|
173671
|
+
if (weight > best && containsProbeVerbatim(entry.row.content, [probe])) {
|
|
173672
|
+
best = weight;
|
|
173673
|
+
}
|
|
173674
|
+
}
|
|
173675
|
+
if (best > 0) {
|
|
173676
|
+
entry.score += best * VERBATIM_RANK_BONUS;
|
|
172000
173677
|
}
|
|
172001
173678
|
}
|
|
172002
173679
|
const ranked = [...fused.values()].sort((a, b) => b.score !== a.score ? b.score - a.score : a.row.messageOrdinal - b.row.messageOrdinal).slice(0, args.limit);
|
|
172003
|
-
|
|
172004
|
-
return ranked.map((entry) => ({
|
|
173680
|
+
return ranked.map((entry, rank) => ({
|
|
172005
173681
|
source: "message",
|
|
172006
173682
|
content: previewText(entry.row.content),
|
|
172007
|
-
score:
|
|
173683
|
+
score: linearDecayScore(rank, ranked.length),
|
|
172008
173684
|
messageOrdinal: entry.row.messageOrdinal,
|
|
172009
173685
|
messageId: entry.row.messageId,
|
|
172010
173686
|
role: entry.row.role
|
|
172011
173687
|
}));
|
|
172012
173688
|
}
|
|
173689
|
+
function searchCompartmentChunks(args) {
|
|
173690
|
+
if (!args.queryEmbedding || args.limit <= 0)
|
|
173691
|
+
return [];
|
|
173692
|
+
const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
|
|
173693
|
+
const rows = loadCompartmentChunkEmbeddingsForSearch(args.db, args.sessionId, args.projectPath, args.modelId);
|
|
173694
|
+
if (rows.length === 0)
|
|
173695
|
+
return [];
|
|
173696
|
+
const byCompartment = new Map;
|
|
173697
|
+
for (const row of rows) {
|
|
173698
|
+
if (cutoff !== null && row.endOrdinal > cutoff) {
|
|
173699
|
+
continue;
|
|
173700
|
+
}
|
|
173701
|
+
const score = normalizeCosineScore(cosineSimilarity(args.queryEmbedding, row.vector));
|
|
173702
|
+
if (score <= 0)
|
|
173703
|
+
continue;
|
|
173704
|
+
const existing = byCompartment.get(row.compartmentId);
|
|
173705
|
+
if (!existing || score > existing.score) {
|
|
173706
|
+
byCompartment.set(row.compartmentId, { row, score });
|
|
173707
|
+
}
|
|
173708
|
+
}
|
|
173709
|
+
return [...byCompartment.values()].sort((left, right) => right.score !== left.score ? right.score - left.score : left.row.startOrdinal - right.row.startOrdinal).slice(0, args.limit).map(({ row, score }) => ({
|
|
173710
|
+
source: "compartment",
|
|
173711
|
+
content: previewText(row.title),
|
|
173712
|
+
score: score * SINGLE_SOURCE_PENALTY,
|
|
173713
|
+
compartmentId: row.compartmentId,
|
|
173714
|
+
sessionId: row.sessionId,
|
|
173715
|
+
title: row.title,
|
|
173716
|
+
startOrdinal: row.startOrdinal,
|
|
173717
|
+
endOrdinal: row.endOrdinal,
|
|
173718
|
+
matchType: "semantic"
|
|
173719
|
+
}));
|
|
173720
|
+
}
|
|
173721
|
+
function mergeMessageAndCompartmentResults(args) {
|
|
173722
|
+
if (args.compartments.length === 0)
|
|
173723
|
+
return args.messages;
|
|
173724
|
+
if (args.messages.length === 0)
|
|
173725
|
+
return args.compartments;
|
|
173726
|
+
const fused = new Map;
|
|
173727
|
+
const add = (key, result, score, tieOrdinal) => {
|
|
173728
|
+
const existing = fused.get(key);
|
|
173729
|
+
if (existing) {
|
|
173730
|
+
existing.score += score;
|
|
173731
|
+
return existing;
|
|
173732
|
+
}
|
|
173733
|
+
const entry = { result, score, tieOrdinal, snippetScore: -1 };
|
|
173734
|
+
fused.set(key, entry);
|
|
173735
|
+
return entry;
|
|
173736
|
+
};
|
|
173737
|
+
args.compartments.forEach((compartment, rank) => {
|
|
173738
|
+
add(`compartment:${compartment.compartmentId}`, compartment, 1 / (RRF_K + rank), compartment.startOrdinal);
|
|
173739
|
+
});
|
|
173740
|
+
for (const [rank, message] of args.messages.entries()) {
|
|
173741
|
+
const containing = args.compartments.find((compartment) => message.messageOrdinal >= compartment.startOrdinal && message.messageOrdinal <= compartment.endOrdinal);
|
|
173742
|
+
const contribution = 1 / (RRF_K + rank);
|
|
173743
|
+
if (!containing) {
|
|
173744
|
+
add(`message:${message.messageId}`, message, contribution, message.messageOrdinal);
|
|
173745
|
+
continue;
|
|
173746
|
+
}
|
|
173747
|
+
const entry = add(`compartment:${containing.compartmentId}`, containing, contribution, containing.startOrdinal);
|
|
173748
|
+
if (message.score > entry.snippetScore && entry.result.source === "compartment") {
|
|
173749
|
+
entry.snippetScore = message.score;
|
|
173750
|
+
entry.result = {
|
|
173751
|
+
...entry.result,
|
|
173752
|
+
matchType: "hybrid",
|
|
173753
|
+
snippet: message.content
|
|
173754
|
+
};
|
|
173755
|
+
}
|
|
173756
|
+
}
|
|
173757
|
+
const ranked = [...fused.values()].sort((left, right) => right.score !== left.score ? right.score - left.score : left.tieOrdinal - right.tieOrdinal).slice(0, args.limit);
|
|
173758
|
+
return ranked.map((entry, rank) => ({
|
|
173759
|
+
...entry.result,
|
|
173760
|
+
score: linearDecayScore(rank, ranked.length)
|
|
173761
|
+
}));
|
|
173762
|
+
}
|
|
172013
173763
|
function getSourceBoost(result) {
|
|
172014
173764
|
switch (result.source) {
|
|
172015
173765
|
case "memory":
|
|
172016
173766
|
return MEMORY_SOURCE_BOOST;
|
|
172017
173767
|
case "message":
|
|
173768
|
+
case "compartment":
|
|
172018
173769
|
return MESSAGE_SOURCE_BOOST;
|
|
172019
173770
|
case "git_commit":
|
|
172020
173771
|
return GIT_COMMIT_SOURCE_BOOST;
|
|
@@ -172032,6 +173783,9 @@ function compareUnifiedResults(left, right) {
|
|
|
172032
173783
|
if (left.source === "message" && right.source === "message") {
|
|
172033
173784
|
return left.messageOrdinal - right.messageOrdinal;
|
|
172034
173785
|
}
|
|
173786
|
+
if (left.source === "compartment" && right.source === "compartment") {
|
|
173787
|
+
return left.startOrdinal - right.startOrdinal;
|
|
173788
|
+
}
|
|
172035
173789
|
if (left.source === "git_commit" && right.source === "git_commit") {
|
|
172036
173790
|
return right.committedAtMs - left.committedAtMs;
|
|
172037
173791
|
}
|
|
@@ -172082,10 +173836,12 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
172082
173836
|
const isEmbeddingRuntimeEnabled = options.isEmbeddingRuntimeEnabled ?? isEmbeddingEnabled;
|
|
172083
173837
|
const gitCommitsEnabled = options.gitCommitsEnabled ?? false;
|
|
172084
173838
|
const activeSources = resolveSources(options.sources);
|
|
172085
|
-
const
|
|
173839
|
+
const memoryFeatureEnabled = options.memoryEnabled ?? true;
|
|
173840
|
+
const runMemory = activeSources.has("memory") && memoryFeatureEnabled;
|
|
172086
173841
|
const runMessages = activeSources.has("message");
|
|
172087
173842
|
const runGitCommits = activeSources.has("git_commit") && gitCommitsEnabled;
|
|
172088
|
-
const
|
|
173843
|
+
const runCompartmentChunks = runMessages && memoryFeatureEnabled && embeddingEnabled;
|
|
173844
|
+
const needsEmbedding = (runMemory || runGitCommits || runCompartmentChunks) && embeddingEnabled && isEmbeddingRuntimeEnabled();
|
|
172089
173845
|
const queryEmbeddingPromise = needsEmbedding ? embedQuery(trimmedQuery, options.signal).catch((error51) => {
|
|
172090
173846
|
log(`[search] query embedding failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
172091
173847
|
return null;
|
|
@@ -172101,6 +173857,24 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
172101
173857
|
probes: messageProbes
|
|
172102
173858
|
}) : [];
|
|
172103
173859
|
const queryEmbedding = await queryEmbeddingPromise;
|
|
173860
|
+
const workspace = resolveSearchWorkspaceContext(db, projectPath);
|
|
173861
|
+
const embeddingSnapshot = getProjectEmbeddingSnapshot(projectPath);
|
|
173862
|
+
const embeddingModelId = embeddingSnapshot?.modelId;
|
|
173863
|
+
const chunkModelId = embeddingSnapshot?.chunkModelId;
|
|
173864
|
+
const compartmentResults = runCompartmentChunks ? searchCompartmentChunks({
|
|
173865
|
+
db,
|
|
173866
|
+
sessionId,
|
|
173867
|
+
projectPath,
|
|
173868
|
+
queryEmbedding,
|
|
173869
|
+
limit: tierLimit,
|
|
173870
|
+
maxOrdinal: options.maxMessageOrdinal,
|
|
173871
|
+
modelId: chunkModelId && chunkModelId !== "off" ? chunkModelId : null
|
|
173872
|
+
}) : [];
|
|
173873
|
+
const messageLikeResults = mergeMessageAndCompartmentResults({
|
|
173874
|
+
messages: messageResults,
|
|
173875
|
+
compartments: compartmentResults,
|
|
173876
|
+
limit: tierLimit
|
|
173877
|
+
});
|
|
172104
173878
|
const [memoryResults, gitCommitResults] = await Promise.all([
|
|
172105
173879
|
runMemory ? searchMemories({
|
|
172106
173880
|
db,
|
|
@@ -172109,6 +173883,8 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
172109
173883
|
limit: tierLimit,
|
|
172110
173884
|
memoryEnabled: true,
|
|
172111
173885
|
queryEmbedding,
|
|
173886
|
+
queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null,
|
|
173887
|
+
workspace,
|
|
172112
173888
|
visibleMemoryIds: options.visibleMemoryIds
|
|
172113
173889
|
}) : Promise.resolve([]),
|
|
172114
173890
|
runGitCommits ? Promise.resolve(searchGitCommits({
|
|
@@ -172119,7 +173895,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
172119
173895
|
queryEmbedding
|
|
172120
173896
|
})) : Promise.resolve([])
|
|
172121
173897
|
]);
|
|
172122
|
-
const results = [...memoryResults, ...
|
|
173898
|
+
const results = [...memoryResults, ...messageLikeResults, ...gitCommitResults].sort(compareUnifiedResults).slice(0, limit);
|
|
172123
173899
|
const countRetrievals = options.countRetrievals ?? true;
|
|
172124
173900
|
if (countRetrievals) {
|
|
172125
173901
|
const memoryIds = results.filter((result) => result.source === "memory").map((result) => result.memoryId);
|
|
@@ -172179,6 +173955,11 @@ function renderFragment(result, charCap) {
|
|
|
172179
173955
|
const compressed = cavemanCompress(result.content, "ultra");
|
|
172180
173956
|
return truncate(compressed, charCap);
|
|
172181
173957
|
}
|
|
173958
|
+
case "compartment": {
|
|
173959
|
+
const source = result.snippet ?? result.title;
|
|
173960
|
+
const compressed = cavemanCompress(source, "ultra");
|
|
173961
|
+
return truncate(compressed, charCap);
|
|
173962
|
+
}
|
|
172182
173963
|
}
|
|
172183
173964
|
}
|
|
172184
173965
|
function buildAutoSearchHint(results, options = {}) {
|
|
@@ -172630,10 +174411,11 @@ function maybeChannel1ReminderForToolResult(args) {
|
|
|
172630
174411
|
contextLimit: state.contextLimit,
|
|
172631
174412
|
executeThresholdPercentage: state.executeThresholdPercentage
|
|
172632
174413
|
});
|
|
174414
|
+
const workingWindowTokens = Math.round(state.contextLimit * state.executeThresholdPercentage / 100);
|
|
172633
174415
|
const decision = decideChannel1({
|
|
172634
174416
|
undroppedTokens,
|
|
172635
174417
|
pressure,
|
|
172636
|
-
|
|
174418
|
+
workingWindowTokens,
|
|
172637
174419
|
lastNudgeUndropped: getLastNudgeUndropped(db, sessionId),
|
|
172638
174420
|
lastNudgeLevel: getLastNudgeLevel(db, sessionId),
|
|
172639
174421
|
hasRecentReduce: false
|
|
@@ -172868,51 +174650,6 @@ function planEmergencyDrop(input) {
|
|
|
172868
174650
|
};
|
|
172869
174651
|
}
|
|
172870
174652
|
|
|
172871
|
-
// ../plugin/src/hooks/magic-context/system-injection-stripper.ts
|
|
172872
|
-
var SYSTEM_INJECTION_MARKERS = [
|
|
172873
|
-
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
172874
|
-
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
172875
|
-
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
172876
|
-
"[Category+Skill Reminder]",
|
|
172877
|
-
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
172878
|
-
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
172879
|
-
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
172880
|
-
"Unstable background agent appears idle",
|
|
172881
|
-
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
172882
|
-
];
|
|
172883
|
-
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
172884
|
-
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
172885
|
-
function stripSystemInjection(text) {
|
|
172886
|
-
let hasInjection = false;
|
|
172887
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
172888
|
-
if (text.includes(marker)) {
|
|
172889
|
-
hasInjection = true;
|
|
172890
|
-
break;
|
|
172891
|
-
}
|
|
172892
|
-
}
|
|
172893
|
-
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
172894
|
-
hasInjection = true;
|
|
172895
|
-
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
172896
|
-
if (!hasInjection)
|
|
172897
|
-
return null;
|
|
172898
|
-
let cleaned = text;
|
|
172899
|
-
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
172900
|
-
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
172901
|
-
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
172902
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
172903
|
-
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
172904
|
-
continue;
|
|
172905
|
-
const idx = cleaned.indexOf(marker);
|
|
172906
|
-
if (idx === -1)
|
|
172907
|
-
continue;
|
|
172908
|
-
const blockEnd = cleaned.indexOf(`
|
|
172909
|
-
|
|
172910
|
-
`, idx + marker.length);
|
|
172911
|
-
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
172912
|
-
}
|
|
172913
|
-
return cleaned.trim();
|
|
172914
|
-
}
|
|
172915
|
-
|
|
172916
174653
|
// src/heuristic-cleanup-pi.ts
|
|
172917
174654
|
init_logger();
|
|
172918
174655
|
var DEDUP_SAFE_TOOLS = new Set([
|
|
@@ -173602,6 +175339,49 @@ function safeGetActiveUserMemoriesPi(db) {
|
|
|
173602
175339
|
function memoryProjectPath(state) {
|
|
173603
175340
|
return state.memoryEnabled === false ? undefined : state.projectIdentity;
|
|
173604
175341
|
}
|
|
175342
|
+
function resolveWorkspaceRenderContextPi(state, db) {
|
|
175343
|
+
const memPath = memoryProjectPath(state);
|
|
175344
|
+
if (!memPath) {
|
|
175345
|
+
return {
|
|
175346
|
+
identities: [],
|
|
175347
|
+
expandedIdentities: [],
|
|
175348
|
+
ownIdentities: [],
|
|
175349
|
+
shareCategories: null,
|
|
175350
|
+
namesByIdentity: new Map,
|
|
175351
|
+
canonicalIdentityByStoredPath: new Map,
|
|
175352
|
+
isWorkspaced: false
|
|
175353
|
+
};
|
|
175354
|
+
}
|
|
175355
|
+
const identitySet = resolveWorkspaceIdentitySet(db, memPath);
|
|
175356
|
+
const isWorkspaced = identitySet.identities.length > 1;
|
|
175357
|
+
const expanded = expandWorkspaceIdentitySetWithAliases(db, identitySet.identities);
|
|
175358
|
+
const expandedIdentities = isWorkspaced ? expanded.expandedIdentities : identitySet.identities;
|
|
175359
|
+
const canonicalIdentityByStoredPath = isWorkspaced ? expanded.canonicalIdentityByStoredPath : new Map(identitySet.identities.map((identity) => [identity, identity]));
|
|
175360
|
+
let ownIdentities = expandedIdentities.filter((identity) => canonicalIdentityByStoredPath.get(identity) === memPath);
|
|
175361
|
+
if (ownIdentities.length === 0 && expandedIdentities.includes(memPath)) {
|
|
175362
|
+
ownIdentities = [memPath];
|
|
175363
|
+
}
|
|
175364
|
+
return {
|
|
175365
|
+
identities: identitySet.identities,
|
|
175366
|
+
expandedIdentities,
|
|
175367
|
+
ownIdentities,
|
|
175368
|
+
shareCategories: isWorkspaced ? resolveWorkspaceShareCategories(db, memPath) : null,
|
|
175369
|
+
namesByIdentity: identitySet.namesByIdentity,
|
|
175370
|
+
canonicalIdentityByStoredPath,
|
|
175371
|
+
isWorkspaced
|
|
175372
|
+
};
|
|
175373
|
+
}
|
|
175374
|
+
function sourceNamesForPiMemories(args) {
|
|
175375
|
+
if (!args.projectPath || !args.workspace.isWorkspaced)
|
|
175376
|
+
return;
|
|
175377
|
+
const names = new Map;
|
|
175378
|
+
for (const memory of args.memories) {
|
|
175379
|
+
const source = sourceNameForMemory(memory.projectPath, args.projectPath, args.workspace.identities, args.workspace.namesByIdentity, args.workspace.canonicalIdentityByStoredPath);
|
|
175380
|
+
if (source)
|
|
175381
|
+
names.set(memory.id, source);
|
|
175382
|
+
}
|
|
175383
|
+
return names.size > 0 ? names : undefined;
|
|
175384
|
+
}
|
|
173605
175385
|
var EMPTY_PI_HARD_SIGNALS = {
|
|
173606
175386
|
systemHash: "",
|
|
173607
175387
|
modelKey: "",
|
|
@@ -173649,6 +175429,7 @@ function getCachedMarkers(db, state, compartmentsForNormalization) {
|
|
|
173649
175429
|
maxMutationId: meta3.cachedM0MaxMutationId,
|
|
173650
175430
|
maxMemoryMutationId: meta3.cachedM0MaxMemoryMutationId,
|
|
173651
175431
|
projectMemoryEpoch: meta3.cachedM0ProjectMemoryEpoch,
|
|
175432
|
+
workspaceFingerprint: meta3.cachedM0WorkspaceFingerprint,
|
|
173652
175433
|
projectUserProfileVersion: meta3.cachedM0ProjectUserProfileVersion,
|
|
173653
175434
|
projectDocsHash: meta3.cachedM0ProjectDocsHash,
|
|
173654
175435
|
sessionFactsVersion: meta3.cachedM0SessionFactsVersion,
|
|
@@ -173668,15 +175449,17 @@ function readCurrentMarkers(db, state, projectDocsHash) {
|
|
|
173668
175449
|
}
|
|
173669
175450
|
function readCurrentMarkersFromCompartments(db, state, compartments, projectDocsHash) {
|
|
173670
175451
|
const memPath = memoryProjectPath(state);
|
|
173671
|
-
const
|
|
175452
|
+
const workspace = resolveWorkspaceRenderContextPi(state, db);
|
|
175453
|
+
const maxMemoryId = memPath ? workspace.isWorkspaced ? getMaxMemoryIdForProjects(db, workspace.expandedIdentities, workspace.ownIdentities, workspace.shareCategories) : getMaxMemoryIdForProjects(db, [memPath]) : 0;
|
|
173672
175454
|
const projectState = memPath ? getProjectState(db, memPath) : undefined;
|
|
173673
175455
|
const globalState = getProjectState(db, GLOBAL_USER_PROFILE_PROJECT_PATH);
|
|
173674
175456
|
return {
|
|
173675
175457
|
maxCompartmentSeq: compartments.length > 0 ? compartments.reduce((max, compartment) => compartment.sequence > max ? compartment.sequence : max, EMPTY_MAX_COMPARTMENT_SEQ) : EMPTY_MAX_COMPARTMENT_SEQ,
|
|
173676
|
-
maxMemoryId
|
|
175458
|
+
maxMemoryId,
|
|
173677
175459
|
maxMutationId: getMaxM0MutationId(db, state.sessionId) ?? 0,
|
|
173678
|
-
maxMemoryMutationId: memPath ? getMaxMemoryMutationId(db, memPath) ?? 0 : 0,
|
|
175460
|
+
maxMemoryMutationId: memPath ? workspace.isWorkspaced ? getMaxMemoryMutationIdForProjects(db, workspace.expandedIdentities) ?? 0 : getMaxMemoryMutationId(db, memPath) ?? 0 : 0,
|
|
173679
175461
|
projectMemoryEpoch: projectState?.projectMemoryEpoch ?? 0,
|
|
175462
|
+
workspaceFingerprint: workspace.isWorkspaced ? computeWorkspaceEpochFingerprint(db, workspace.identities) : null,
|
|
173680
175463
|
projectUserProfileVersion: globalState?.projectUserProfileVersion ?? 0,
|
|
173681
175464
|
projectDocsHash: projectDocsHash ?? readProjectDocsCanonical(state.projectDirectory).canonicalHash,
|
|
173682
175465
|
sessionFactsVersion: getSessionFactsVersion(db, state.sessionId),
|
|
@@ -173714,10 +175497,11 @@ function mustMaterializePi(state, db, currentCompartmentsOverride) {
|
|
|
173714
175497
|
if (meta3.cachedM0UpgradeState !== current.upgradeState) {
|
|
173715
175498
|
return { value: true, reason: "renderer_upgrade" };
|
|
173716
175499
|
}
|
|
173717
|
-
if (current.
|
|
173718
|
-
|
|
173719
|
-
|
|
173720
|
-
|
|
175500
|
+
if (current.workspaceFingerprint !== null || (meta3.cachedM0WorkspaceFingerprint ?? null) !== null) {
|
|
175501
|
+
if (current.workspaceFingerprint !== (meta3.cachedM0WorkspaceFingerprint ?? null)) {
|
|
175502
|
+
return { value: true, reason: "project_memory_change" };
|
|
175503
|
+
}
|
|
175504
|
+
} else if (current.projectMemoryEpoch !== (meta3.cachedM0ProjectMemoryEpoch ?? 0)) {
|
|
173721
175505
|
return { value: true, reason: "project_memory_change" };
|
|
173722
175506
|
}
|
|
173723
175507
|
if (current.maxMutationId !== (meta3.cachedM0MaxMutationId ?? 0)) {
|
|
@@ -173734,11 +175518,19 @@ ${memories.map((memory) => `- ${escapeXmlContent(memory.content)}`).join(`
|
|
|
173734
175518
|
`)}
|
|
173735
175519
|
</${wrapper}>`;
|
|
173736
175520
|
}
|
|
173737
|
-
function renderM0Pi(state, db, projectDocs = readProjectDocsCanonical(state.projectDirectory).renderedBlock, decayPressureMultiplier = 1, memoriesOverride, compartmentsOverride, userProfileOverride) {
|
|
175521
|
+
function renderM0Pi(state, db, projectDocs = readProjectDocsCanonical(state.projectDirectory).renderedBlock, decayPressureMultiplier = 1, memoriesOverride, compartmentsOverride, userProfileOverride, workspaceOverride) {
|
|
173738
175522
|
const memPath = memoryProjectPath(state);
|
|
173739
|
-
const
|
|
173740
|
-
const
|
|
173741
|
-
const
|
|
175523
|
+
const workspace = workspaceOverride ?? resolveWorkspaceRenderContextPi(state, db);
|
|
175524
|
+
const allMemories = memoriesOverride ?? (memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], Date.now(), workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(db, memPath, ["active", "permanent"]) : []);
|
|
175525
|
+
const memoryRenderOptions = {
|
|
175526
|
+
sourceNameByMemoryId: sourceNamesForPiMemories({
|
|
175527
|
+
memories: allMemories,
|
|
175528
|
+
projectPath: memPath,
|
|
175529
|
+
workspace
|
|
175530
|
+
})
|
|
175531
|
+
};
|
|
175532
|
+
const memories = allMemories.length > 0 ? workspace.isWorkspaced ? trimWorkspaceMemoriesToBudgetV2(state.sessionId, allMemories, state.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS, workspace, memoryRenderOptions).renderOrder : trimMemoriesToBudgetV2(state.sessionId, allMemories, state.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS).renderOrder : allMemories;
|
|
175533
|
+
const memoryBlock = memories.length > 0 ? renderMemoryBlockV2(memories, "project-memory", memoryRenderOptions) : undefined;
|
|
173742
175534
|
const baseHistoryBudget = state.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS;
|
|
173743
175535
|
const decayed = renderDecayedCompartments({
|
|
173744
175536
|
compartments: compartmentsOverride ?? getCompartments(db, state.sessionId),
|
|
@@ -173760,10 +175552,19 @@ ${decayed}
|
|
|
173760
175552
|
|
|
173761
175553
|
`).trim();
|
|
173762
175554
|
}
|
|
173763
|
-
function renderedMemoryIdsForPi(state, memories) {
|
|
175555
|
+
function renderedMemoryIdsForPi(state, memories, workspace, db) {
|
|
173764
175556
|
if (memories.length === 0)
|
|
173765
175557
|
return [];
|
|
173766
|
-
|
|
175558
|
+
const resolvedWorkspace = workspace ?? (db ? resolveWorkspaceRenderContextPi(state, db) : undefined);
|
|
175559
|
+
const renderOptions = resolvedWorkspace ? {
|
|
175560
|
+
sourceNameByMemoryId: sourceNamesForPiMemories({
|
|
175561
|
+
memories,
|
|
175562
|
+
projectPath: memoryProjectPath(state),
|
|
175563
|
+
workspace: resolvedWorkspace
|
|
175564
|
+
})
|
|
175565
|
+
} : {};
|
|
175566
|
+
const trimmed = resolvedWorkspace?.isWorkspaced ? trimWorkspaceMemoriesToBudgetV2(state.sessionId, [...memories], state.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS, resolvedWorkspace, renderOptions) : trimMemoriesToBudgetV2(state.sessionId, [...memories], state.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS);
|
|
175567
|
+
return trimmed.renderOrder.map((memory) => memory.id);
|
|
173767
175568
|
}
|
|
173768
175569
|
function isTransientSqliteLockError(error51) {
|
|
173769
175570
|
if (!error51 || typeof error51 !== "object")
|
|
@@ -173788,17 +175589,19 @@ class PiMaterializeContentionError extends Error {
|
|
|
173788
175589
|
function readFrozenM0InputsPi(state, db, docs = readProjectDocsCanonical(state.projectDirectory), memoryCutoff) {
|
|
173789
175590
|
const memPath = memoryProjectPath(state);
|
|
173790
175591
|
const read = db.transaction(() => {
|
|
175592
|
+
const workspace = resolveWorkspaceRenderContextPi(state, db);
|
|
173791
175593
|
const compartments = getCompartments(db, state.sessionId);
|
|
173792
|
-
const memories = memPath ? getMemoriesByProject(db, memPath, ["active", "permanent"], memoryCutoff) : [];
|
|
175594
|
+
const memories = memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], memoryCutoff, workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(db, memPath, ["active", "permanent"], memoryCutoff) : [];
|
|
173793
175595
|
const userProfile = safeGetActiveUserMemoriesPi(db);
|
|
173794
175596
|
const projectState = memPath ? getProjectState(db, memPath) : undefined;
|
|
173795
175597
|
const globalState = getProjectState(db, GLOBAL_USER_PROFILE_PROJECT_PATH);
|
|
173796
175598
|
const markers = {
|
|
173797
175599
|
maxCompartmentSeq: compartments.reduce((max, compartment) => compartment.sequence > max ? compartment.sequence : max, EMPTY_MAX_COMPARTMENT_SEQ),
|
|
173798
|
-
maxMemoryId:
|
|
175600
|
+
maxMemoryId: memPath ? workspace.isWorkspaced ? getMaxMemoryIdForProjects(db, workspace.expandedIdentities, workspace.ownIdentities, workspace.shareCategories) : getMaxMemoryIdForProjects(db, [memPath]) : 0,
|
|
173799
175601
|
maxMutationId: getMaxM0MutationId(db, state.sessionId) ?? 0,
|
|
173800
|
-
maxMemoryMutationId: memPath ? getMaxMemoryMutationId(db, memPath) ?? 0 : 0,
|
|
175602
|
+
maxMemoryMutationId: memPath ? workspace.isWorkspaced ? getMaxMemoryMutationIdForProjects(db, workspace.expandedIdentities) ?? 0 : getMaxMemoryMutationId(db, memPath) ?? 0 : 0,
|
|
173801
175603
|
projectMemoryEpoch: projectState?.projectMemoryEpoch ?? 0,
|
|
175604
|
+
workspaceFingerprint: workspace.isWorkspaced ? computeWorkspaceEpochFingerprint(db, workspace.identities) : null,
|
|
173802
175605
|
projectUserProfileVersion: globalState?.projectUserProfileVersion ?? 0,
|
|
173803
175606
|
projectDocsHash: docs.canonicalHash,
|
|
173804
175607
|
sessionFactsVersion: getSessionFactsVersion(db, state.sessionId),
|
|
@@ -173808,7 +175611,7 @@ function readFrozenM0InputsPi(state, db, docs = readProjectDocsCanonical(state.p
|
|
|
173808
175611
|
systemHash: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
|
|
173809
175612
|
modelKey: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey
|
|
173810
175613
|
};
|
|
173811
|
-
return { docs, markers, compartments, memories, userProfile };
|
|
175614
|
+
return { docs, markers, compartments, memories, userProfile, workspace };
|
|
173812
175615
|
});
|
|
173813
175616
|
return read();
|
|
173814
175617
|
}
|
|
@@ -173819,17 +175622,17 @@ function renderFreshM0PiNonPersisted(state, db) {
|
|
|
173819
175622
|
frozen.markers.materializedAt = cachedMaterializedAt;
|
|
173820
175623
|
const historyBudget = state.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS;
|
|
173821
175624
|
let dpm = 1;
|
|
173822
|
-
let m0 = renderM0Pi(state, db, docs.renderedBlock, dpm, frozen.memories, frozen.compartments, frozen.userProfile);
|
|
175625
|
+
let m0 = renderM0Pi(state, db, docs.renderedBlock, dpm, frozen.memories, frozen.compartments, frozen.userProfile, frozen.workspace);
|
|
173823
175626
|
let attempts = 0;
|
|
173824
175627
|
while (historyBudget > 0 && historySliceTokensPi(m0) > historyBudget * 1.05 && attempts < 3) {
|
|
173825
175628
|
dpm *= 1.15;
|
|
173826
|
-
m0 = renderM0Pi(state, db, docs.renderedBlock, dpm, frozen.memories, frozen.compartments, frozen.userProfile);
|
|
175629
|
+
m0 = renderM0Pi(state, db, docs.renderedBlock, dpm, frozen.memories, frozen.compartments, frozen.userProfile, frozen.workspace);
|
|
173827
175630
|
attempts += 1;
|
|
173828
175631
|
}
|
|
173829
175632
|
return {
|
|
173830
175633
|
m0,
|
|
173831
175634
|
snapshotMarkers: frozen.markers,
|
|
173832
|
-
renderedMemoryIds: renderedMemoryIdsForPi(state, frozen.memories)
|
|
175635
|
+
renderedMemoryIds: renderedMemoryIdsForPi(state, frozen.memories, frozen.workspace, db)
|
|
173833
175636
|
};
|
|
173834
175637
|
}
|
|
173835
175638
|
function materializeM0Pi(state, db) {
|
|
@@ -173839,14 +175642,14 @@ function materializeM0Pi(state, db) {
|
|
|
173839
175642
|
const snapshotMemories = frozen.memories;
|
|
173840
175643
|
const snapshotCompartments = frozen.compartments;
|
|
173841
175644
|
const snapshotUserProfile = frozen.userProfile;
|
|
173842
|
-
const renderedMemoryIds = renderedMemoryIdsForPi(state, snapshotMemories);
|
|
175645
|
+
const renderedMemoryIds = renderedMemoryIdsForPi(state, snapshotMemories, frozen.workspace, db);
|
|
173843
175646
|
let decayPressureMultiplier = 1;
|
|
173844
|
-
let m0 = renderM0Pi(state, db, docs.renderedBlock, decayPressureMultiplier, snapshotMemories, snapshotCompartments, snapshotUserProfile);
|
|
175647
|
+
let m0 = renderM0Pi(state, db, docs.renderedBlock, decayPressureMultiplier, snapshotMemories, snapshotCompartments, snapshotUserProfile, frozen.workspace);
|
|
173845
175648
|
const historyBudget = state.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS;
|
|
173846
175649
|
let attempts = 0;
|
|
173847
175650
|
while (historyBudget > 0 && historySliceTokensPi(m0) > historyBudget * 1.05 && attempts < 3) {
|
|
173848
175651
|
decayPressureMultiplier *= 1.15;
|
|
173849
|
-
m0 = renderM0Pi(state, db, docs.renderedBlock, decayPressureMultiplier, snapshotMemories, snapshotCompartments, snapshotUserProfile);
|
|
175652
|
+
m0 = renderM0Pi(state, db, docs.renderedBlock, decayPressureMultiplier, snapshotMemories, snapshotCompartments, snapshotUserProfile, frozen.workspace);
|
|
173850
175653
|
attempts += 1;
|
|
173851
175654
|
}
|
|
173852
175655
|
const m0Bytes = Buffer.from(m0, "utf8");
|
|
@@ -173862,7 +175665,8 @@ function materializeM0Pi(state, db) {
|
|
|
173862
175665
|
}
|
|
173863
175666
|
try {
|
|
173864
175667
|
const current = readCurrentMarkers(db, state, phase3ProjectDocsHash);
|
|
173865
|
-
const
|
|
175668
|
+
const memoryEpochStale = current.workspaceFingerprint !== null || snapshotMarkers.workspaceFingerprint !== null ? current.workspaceFingerprint !== snapshotMarkers.workspaceFingerprint : current.projectMemoryEpoch !== snapshotMarkers.projectMemoryEpoch;
|
|
175669
|
+
const stale = memoryEpochStale || current.projectUserProfileVersion !== snapshotMarkers.projectUserProfileVersion || current.maxCompartmentSeq !== snapshotMarkers.maxCompartmentSeq || current.maxMutationId !== snapshotMarkers.maxMutationId || current.maxMemoryMutationId !== snapshotMarkers.maxMemoryMutationId || current.sessionFactsVersion !== snapshotMarkers.sessionFactsVersion || current.upgradeState !== snapshotMarkers.upgradeState;
|
|
173866
175670
|
if (stale) {
|
|
173867
175671
|
db.exec("ROLLBACK");
|
|
173868
175672
|
throw new PiMaterializeContentionError("snapshot changed before persist");
|
|
@@ -173873,6 +175677,7 @@ function materializeM0Pi(state, db) {
|
|
|
173873
175677
|
persistCachedM0(db, state.sessionId, {
|
|
173874
175678
|
m0Bytes,
|
|
173875
175679
|
projectMemoryEpoch: snapshotMarkers.projectMemoryEpoch,
|
|
175680
|
+
workspaceFingerprint: snapshotMarkers.workspaceFingerprint,
|
|
173876
175681
|
projectUserProfileVersion: snapshotMarkers.projectUserProfileVersion,
|
|
173877
175682
|
maxCompartmentSeq: snapshotMarkers.maxCompartmentSeq,
|
|
173878
175683
|
maxMemoryId: snapshotMarkers.maxMemoryId,
|
|
@@ -173937,7 +175742,7 @@ function renderMemoryUpdatesBlockPi(args) {
|
|
|
173937
175742
|
if (args.renderedMemoryIds.length === 0)
|
|
173938
175743
|
return { block: "", count: 0 };
|
|
173939
175744
|
const renderedIds = new Set(args.renderedMemoryIds);
|
|
173940
|
-
const mutations = getMemoryMutationsForRender(args.db, args.projectPath, args.afterId, args.renderedMemoryIds);
|
|
175745
|
+
const mutations = args.workspace.isWorkspaced ? getMemoryMutationsForRenderByProjects(args.db, args.workspace.expandedIdentities, args.afterId, args.renderedMemoryIds) : getMemoryMutationsForRender(args.db, args.projectPath, args.afterId, args.renderedMemoryIds);
|
|
173941
175746
|
if (mutations.length === 0)
|
|
173942
175747
|
return { block: "", count: 0 };
|
|
173943
175748
|
const lines = [
|
|
@@ -173968,6 +175773,7 @@ ${lines.join(`
|
|
|
173968
175773
|
}
|
|
173969
175774
|
function renderM1PiWithMetadata(state, db, markers, renderedMemoryIds, preRenderedKeyFilesBlock, compartmentsOverride) {
|
|
173970
175775
|
const sections = [];
|
|
175776
|
+
const workspace = resolveWorkspaceRenderContextPi(state, db);
|
|
173971
175777
|
const keyFiles = renderedKeyFilesBlockPi(state, db, preRenderedKeyFilesBlock);
|
|
173972
175778
|
if (keyFiles)
|
|
173973
175779
|
sections.push(keyFiles);
|
|
@@ -173975,6 +175781,7 @@ function renderM1PiWithMetadata(state, db, markers, renderedMemoryIds, preRender
|
|
|
173975
175781
|
const memoryUpdates = memPath ? renderMemoryUpdatesBlockPi({
|
|
173976
175782
|
db,
|
|
173977
175783
|
projectPath: memPath,
|
|
175784
|
+
workspace,
|
|
173978
175785
|
afterId: markers.maxMemoryMutationId,
|
|
173979
175786
|
renderedMemoryIds
|
|
173980
175787
|
}) : { block: undefined, count: 0 };
|
|
@@ -173989,11 +175796,18 @@ function renderM1PiWithMetadata(state, db, markers, renderedMemoryIds, preRender
|
|
|
173989
175796
|
${body}
|
|
173990
175797
|
</new-compartments>`);
|
|
173991
175798
|
}
|
|
173992
|
-
const newMemories = memPath ? getMemoriesByProject(db, memPath, ["active", "permanent"], markers.materializedAt).filter((memory) => memory.id > markers.maxMemoryId) : [];
|
|
175799
|
+
const newMemories = memPath ? workspace.isWorkspaced ? readNewMemoriesForM1Union(db, workspace.expandedIdentities, markers.maxMemoryId, markers.materializedAt, workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(db, memPath, ["active", "permanent"], markers.materializedAt).filter((memory) => memory.id > markers.maxMemoryId) : [];
|
|
173993
175800
|
if (newMemories.length > 0) {
|
|
173994
175801
|
const memoryBudget = state.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
|
|
173995
|
-
const
|
|
173996
|
-
|
|
175802
|
+
const memoryRenderOptions = {
|
|
175803
|
+
sourceNameByMemoryId: sourceNamesForPiMemories({
|
|
175804
|
+
memories: newMemories,
|
|
175805
|
+
projectPath: memPath,
|
|
175806
|
+
workspace
|
|
175807
|
+
})
|
|
175808
|
+
};
|
|
175809
|
+
const trimmedNewMemories = trimMemoriesToBudgetV2(state.sessionId, newMemories, Math.max(1, Math.floor(memoryBudget * 0.25)), memoryRenderOptions).renderOrder;
|
|
175810
|
+
const newMemoriesBlock = renderMemoryBlockV2(trimmedNewMemories, "new-memories", memoryRenderOptions);
|
|
173997
175811
|
if (newMemoriesBlock)
|
|
173998
175812
|
sections.push(newMemoriesBlock);
|
|
173999
175813
|
}
|
|
@@ -174042,6 +175856,7 @@ function parseMemoryBlockIds(raw) {
|
|
|
174042
175856
|
function readCachedPiM0M1Row(db, sessionId) {
|
|
174043
175857
|
return db.prepare(`SELECT cached_m0_bytes, cached_m1_bytes,
|
|
174044
175858
|
cached_m0_project_memory_epoch,
|
|
175859
|
+
cached_m0_workspace_fingerprint,
|
|
174045
175860
|
cached_m0_project_user_profile_version,
|
|
174046
175861
|
cached_m0_max_compartment_seq,
|
|
174047
175862
|
cached_m0_max_memory_id,
|
|
@@ -174085,6 +175900,7 @@ function markersFromCachedPiRow(row, compartmentsForNormalization) {
|
|
|
174085
175900
|
maxMutationId: row.cached_m0_max_mutation_id,
|
|
174086
175901
|
maxMemoryMutationId: row.cached_m0_max_memory_mutation_id,
|
|
174087
175902
|
projectMemoryEpoch: row.cached_m0_project_memory_epoch,
|
|
175903
|
+
workspaceFingerprint: row.cached_m0_workspace_fingerprint,
|
|
174088
175904
|
projectUserProfileVersion: row.cached_m0_project_user_profile_version,
|
|
174089
175905
|
projectDocsHash: row.cached_m0_project_docs_hash ?? "",
|
|
174090
175906
|
materializedAt: row.cached_m0_materialized_at,
|
|
@@ -174099,7 +175915,7 @@ function cachedPiRowMatchesSnapshot(args) {
|
|
|
174099
175915
|
const rowMarkers = markersFromCachedPiRow(args.row, args.compartmentsForNormalization);
|
|
174100
175916
|
if (!rowMarkers)
|
|
174101
175917
|
return false;
|
|
174102
|
-
return bufferEqualsNullable(args.row.cached_m0_bytes, args.m0Bytes) && rowMarkers.projectMemoryEpoch === args.markers.projectMemoryEpoch && rowMarkers.projectUserProfileVersion === args.markers.projectUserProfileVersion && rowMarkers.maxCompartmentSeq === args.markers.maxCompartmentSeq && rowMarkers.maxMemoryId === args.markers.maxMemoryId && rowMarkers.maxMutationId === args.markers.maxMutationId && rowMarkers.maxMemoryMutationId === args.markers.maxMemoryMutationId &&
|
|
175918
|
+
return bufferEqualsNullable(args.row.cached_m0_bytes, args.m0Bytes) && rowMarkers.projectMemoryEpoch === args.markers.projectMemoryEpoch && rowMarkers.projectUserProfileVersion === args.markers.projectUserProfileVersion && rowMarkers.maxCompartmentSeq === args.markers.maxCompartmentSeq && rowMarkers.maxMemoryId === args.markers.maxMemoryId && rowMarkers.maxMutationId === args.markers.maxMutationId && rowMarkers.maxMemoryMutationId === args.markers.maxMemoryMutationId && rowMarkers.materializedAt === args.markers.materializedAt && rowMarkers.sessionFactsVersion === args.markers.sessionFactsVersion && (rowMarkers.upgradeState ?? null) === (args.markers.upgradeState ?? null) && (rowMarkers.systemHash ?? "") === (args.markers.systemHash ?? "") && (rowMarkers.modelKey ?? "") === (args.markers.modelKey ?? "") && (rowMarkers.workspaceFingerprint ?? null) === (args.markers.workspaceFingerprint ?? null);
|
|
174103
175919
|
}
|
|
174104
175920
|
function decodeCachedM1(row, sessionId) {
|
|
174105
175921
|
if (!row.cached_m1_bytes) {
|
|
@@ -174310,14 +176126,14 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
174310
176126
|
const skippedVisibleMessages = boundaryId ? trimPiMessagesToBoundary(piMessages, entryIds, boundaryId) : 0;
|
|
174311
176127
|
prependM0M1Messages(piMessages, m0, m1);
|
|
174312
176128
|
sessionLog(state.sessionId, `injected m[0]/m[1] into Pi messages (${m0.length} + ${m1.length} bytes, materialized=${materialized}${decision.reason ? ` reason=${decision.reason}` : ""})`);
|
|
176129
|
+
const memPath = memoryProjectPath(state);
|
|
176130
|
+
const workspace = resolveWorkspaceRenderContextPi(state, db);
|
|
176131
|
+
const memoryCount = memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], Date.now(), workspace.ownIdentities, workspace.shareCategories).length : getMemoriesByProject(db, memPath, ["active", "permanent"]).length : 0;
|
|
174313
176132
|
return {
|
|
174314
176133
|
injected: true,
|
|
174315
176134
|
compartmentCount: getCompartments(db, state.sessionId).length,
|
|
174316
176135
|
factCount: 0,
|
|
174317
|
-
memoryCount
|
|
174318
|
-
"active",
|
|
174319
|
-
"permanent"
|
|
174320
|
-
]).length : 0,
|
|
176136
|
+
memoryCount,
|
|
174321
176137
|
skippedVisibleMessages,
|
|
174322
176138
|
m0Materialized: materialized,
|
|
174323
176139
|
m0Reason: decision.reason,
|
|
@@ -174378,21 +176194,48 @@ import * as crypto2 from "node:crypto";
|
|
|
174378
176194
|
|
|
174379
176195
|
// ../plugin/src/features/magic-context/compartment-embedding.ts
|
|
174380
176196
|
init_logger();
|
|
174381
|
-
async function
|
|
176197
|
+
async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compartments) {
|
|
174382
176198
|
if (compartments.length === 0)
|
|
174383
176199
|
return;
|
|
174384
|
-
const
|
|
174385
|
-
for (const
|
|
174386
|
-
if (!c.p1 || c.p1.length === 0)
|
|
174387
|
-
continue;
|
|
176200
|
+
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectPath);
|
|
176201
|
+
for (const compartment of compartments) {
|
|
174388
176202
|
try {
|
|
174389
|
-
const
|
|
174390
|
-
|
|
174391
|
-
|
|
174392
|
-
|
|
176203
|
+
const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
|
|
176204
|
+
const canonicalText = fromMemory || buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage);
|
|
176205
|
+
if (canonicalText.length === 0)
|
|
176206
|
+
continue;
|
|
176207
|
+
const windows = chunkCanonicalText(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
|
|
176208
|
+
if (windows.length === 0)
|
|
176209
|
+
continue;
|
|
176210
|
+
const currentModelId = getProjectChunkEmbeddingModelId(projectPath);
|
|
176211
|
+
if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
|
|
176212
|
+
continue;
|
|
176213
|
+
}
|
|
176214
|
+
const result = await embedBatchForProject(projectPath, windows.map((window) => window.text));
|
|
176215
|
+
if (!result)
|
|
176216
|
+
continue;
|
|
176217
|
+
if (chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
|
|
176218
|
+
continue;
|
|
176219
|
+
}
|
|
176220
|
+
const rows = [];
|
|
176221
|
+
for (const [index, window] of windows.entries()) {
|
|
176222
|
+
const vector = result.vectors[index];
|
|
176223
|
+
if (!vector)
|
|
176224
|
+
continue;
|
|
176225
|
+
rows.push({
|
|
176226
|
+
compartmentId: compartment.id,
|
|
176227
|
+
sessionId,
|
|
176228
|
+
projectPath,
|
|
176229
|
+
window,
|
|
176230
|
+
modelId: currentModelId,
|
|
176231
|
+
vector
|
|
176232
|
+
});
|
|
176233
|
+
}
|
|
176234
|
+
if (rows.length === windows.length) {
|
|
176235
|
+
replaceCompartmentChunkEmbeddings(db, rows);
|
|
174393
176236
|
}
|
|
174394
176237
|
} catch (error51) {
|
|
174395
|
-
sessionLog(sessionId, `compartment embedding failed for compartment ${
|
|
176238
|
+
sessionLog(sessionId, `compartment chunk embedding failed for compartment ${compartment.id}:`, error51);
|
|
174396
176239
|
}
|
|
174397
176240
|
}
|
|
174398
176241
|
}
|
|
@@ -177461,6 +179304,7 @@ async function runPiHistorian(deps) {
|
|
|
177461
179304
|
fallbackModels,
|
|
177462
179305
|
historianChunkTokens,
|
|
177463
179306
|
boundarySnapshot: providedBoundarySnapshot,
|
|
179307
|
+
refreshBoundarySnapshot,
|
|
177464
179308
|
currentContextLimit,
|
|
177465
179309
|
historianTimeoutMs = DEFAULT_HISTORIAN_TIMEOUT_MS2,
|
|
177466
179310
|
twoPass,
|
|
@@ -177514,16 +179358,29 @@ async function runPiHistorian(deps) {
|
|
|
177514
179358
|
return;
|
|
177515
179359
|
}
|
|
177516
179360
|
const offset = priorCompartments.length > 0 ? priorCompartments[priorCompartments.length - 1].endMessage + 1 : 1;
|
|
177517
|
-
|
|
179361
|
+
let boundarySnapshot = providedBoundarySnapshot ?? null;
|
|
177518
179362
|
if (!boundarySnapshot) {
|
|
177519
179363
|
sessionLog(sessionId, "historian no-op: missing protected-tail boundary snapshot from Pi trigger decision");
|
|
177520
179364
|
return;
|
|
177521
179365
|
}
|
|
177522
|
-
|
|
179366
|
+
let validation = boundarySnapshot.rawRangeFingerprint.length > 0 ? validateBoundarySnapshot({
|
|
177523
179367
|
db,
|
|
177524
179368
|
snapshot: boundarySnapshot,
|
|
177525
179369
|
currentContextLimit: currentContextLimit ?? boundarySnapshot.contextLimit
|
|
177526
179370
|
}) : { ok: true };
|
|
179371
|
+
if (!validation.ok && validation.reason === "stale_snapshot" && refreshBoundarySnapshot) {
|
|
179372
|
+
try {
|
|
179373
|
+
const refreshed = refreshBoundarySnapshot();
|
|
179374
|
+
if (hasRunnableCompartmentWindow(refreshed)) {
|
|
179375
|
+
sessionLog(sessionId, `historian: refreshed stale protected-tail snapshot at run time (was: ${validation.detail ?? "stale"}) — eligible head ${refreshed.offset}-${refreshed.eligibleEndOrdinal - 1}`);
|
|
179376
|
+
boundarySnapshot = refreshed;
|
|
179377
|
+
validation = { ok: true };
|
|
179378
|
+
}
|
|
179379
|
+
} catch (error51) {
|
|
179380
|
+
const desc = describeError(error51);
|
|
179381
|
+
sessionLog(sessionId, `historian: failed to refresh stale protected-tail snapshot at run time (${validation.detail ?? "stale"}): ${desc.brief}`);
|
|
179382
|
+
}
|
|
179383
|
+
}
|
|
177527
179384
|
if (!validation.ok) {
|
|
177528
179385
|
sessionLog(sessionId, `historian no-op: stale protected-tail snapshot (${validation.detail ?? validation.reason ?? "unknown"})`);
|
|
177529
179386
|
return;
|
|
@@ -177852,8 +179709,13 @@ ${chunkText}`,
|
|
|
177852
179709
|
}
|
|
177853
179710
|
}
|
|
177854
179711
|
if (embeddingActive) {
|
|
177855
|
-
const
|
|
177856
|
-
|
|
179712
|
+
const chunksToEmbed = newCompartments.map((c, i) => ({
|
|
179713
|
+
id: persistedIds[i],
|
|
179714
|
+
startMessage: c.startMessage,
|
|
179715
|
+
endMessage: c.endMessage,
|
|
179716
|
+
sourceChunkText: chunk.text
|
|
179717
|
+
})).filter((c) => typeof c.id === "number");
|
|
179718
|
+
embedAndStoreCompartmentChunks(db, sessionId, projectPath, chunksToEmbed);
|
|
177857
179719
|
}
|
|
177858
179720
|
onPublished?.();
|
|
177859
179721
|
completedSuccessfully = true;
|
|
@@ -178401,7 +180263,7 @@ function stripPiDroppedPlaceholderMessages(args) {
|
|
|
178401
180263
|
}
|
|
178402
180264
|
|
|
178403
180265
|
// src/system-prompt.ts
|
|
178404
|
-
import { createHash as
|
|
180266
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
178405
180267
|
|
|
178406
180268
|
// ../plugin/src/agents/magic-context-prompt.ts
|
|
178407
180269
|
var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
|
|
@@ -178552,7 +180414,7 @@ function processSystemPromptForCache(args) {
|
|
|
178552
180414
|
sessionLog(sessionId, `system prompt date frozen: real=${liveDate}, using=${stickyDate} (cache-stable pass)`);
|
|
178553
180415
|
}
|
|
178554
180416
|
}
|
|
178555
|
-
const currentHash =
|
|
180417
|
+
const currentHash = createHash11("md5").update(frozenPrompt).digest("hex");
|
|
178556
180418
|
const hashChanged = !isFirstHash && currentHash !== previousHash;
|
|
178557
180419
|
if (hashChanged) {
|
|
178558
180420
|
sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${frozenPrompt.length})`);
|
|
@@ -179179,6 +181041,19 @@ function extractStableId(msg, index, entryIds) {
|
|
|
179179
181041
|
// src/context-handler.ts
|
|
179180
181042
|
var FORCE_MATERIALIZATION_PERCENTAGE = 85;
|
|
179181
181043
|
var EMERGENCY_BLOCK_PERCENTAGE = 95;
|
|
181044
|
+
var FORWARD_PRESSURE_LIMIT_FACTOR = 0.85;
|
|
181045
|
+
function applyForwardPressureFloor(trailingPercentage, trailingInputTokens, piUsageTokens, correctedLimit) {
|
|
181046
|
+
const forwardTokens = typeof piUsageTokens === "number" && piUsageTokens > 0 ? piUsageTokens : 0;
|
|
181047
|
+
if (forwardTokens === 0 || !isSaneLimit(correctedLimit)) {
|
|
181048
|
+
return { percentage: trailingPercentage, inputTokens: trailingInputTokens };
|
|
181049
|
+
}
|
|
181050
|
+
const forwardPressureLimit = correctedLimit * FORWARD_PRESSURE_LIMIT_FACTOR;
|
|
181051
|
+
const forwardPercentage = forwardTokens / forwardPressureLimit * 100;
|
|
181052
|
+
return forwardPercentage > trailingPercentage ? {
|
|
181053
|
+
percentage: forwardPercentage,
|
|
181054
|
+
inputTokens: Math.max(trailingInputTokens, forwardTokens)
|
|
181055
|
+
} : { percentage: trailingPercentage, inputTokens: trailingInputTokens };
|
|
181056
|
+
}
|
|
179182
181057
|
var DEFAULT_CLEAR_REASONING_AGE = 50;
|
|
179183
181058
|
var PI_STABLE_ID_SCHEME = 1;
|
|
179184
181059
|
var lastEmergencyNotificationAtMs = new Map;
|
|
@@ -179263,7 +181138,7 @@ function trackSessionForProject(projectIdentity, sessionId) {
|
|
|
179263
181138
|
function isContextHandlerSessionActive(sessionId) {
|
|
179264
181139
|
return activeContextHandlerSessions.has(sessionId);
|
|
179265
181140
|
}
|
|
179266
|
-
function updateSessionProjectTracking(sessionId, projectIdentity) {
|
|
181141
|
+
function updateSessionProjectTracking(sessionId, projectIdentity, db) {
|
|
179267
181142
|
const prev = lastSeenProjectIdentityBySession.get(sessionId);
|
|
179268
181143
|
if (prev && prev !== projectIdentity) {
|
|
179269
181144
|
const prevSessions = sessionsByProject.get(prev);
|
|
@@ -179272,6 +181147,11 @@ function updateSessionProjectTracking(sessionId, projectIdentity) {
|
|
|
179272
181147
|
sessionsByProject.delete(prev);
|
|
179273
181148
|
clearPiSystemPromptSession(sessionId);
|
|
179274
181149
|
}
|
|
181150
|
+
if (db && prev !== projectIdentity) {
|
|
181151
|
+
try {
|
|
181152
|
+
recordSessionProjectIdentity(db, sessionId, projectIdentity);
|
|
181153
|
+
} catch {}
|
|
181154
|
+
}
|
|
179275
181155
|
trackSessionForProject(projectIdentity, sessionId);
|
|
179276
181156
|
lastSeenProjectIdentityBySession.set(sessionId, projectIdentity);
|
|
179277
181157
|
}
|
|
@@ -179552,7 +181432,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
179552
181432
|
const schedulerConfig = options.scheduler ?? DEFAULT_SCHEDULER_CONFIG;
|
|
179553
181433
|
const scheduler2 = schedulerFor(options);
|
|
179554
181434
|
const projectIdentity = resolveProjectIdentity(projectDirectory);
|
|
179555
|
-
updateSessionProjectTracking(sessionId, projectIdentity);
|
|
181435
|
+
updateSessionProjectTracking(sessionId, projectIdentity, options.db);
|
|
179556
181436
|
logTransformTiming(sessionId, "findSessionId", tFindSession, `messages=${event.messages.length}`);
|
|
179557
181437
|
const branchEntries = readPiBranchEntriesForContext(ctx, sessionId);
|
|
179558
181438
|
const rawMessageProvider = {
|
|
@@ -179661,9 +181541,10 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
179661
181541
|
if (!usedPersistedUsage && isSaneLimit(usageContextLimit) && usageInputTokens > 0) {
|
|
179662
181542
|
usagePercentage = usageInputTokens / usageContextLimit * 100;
|
|
179663
181543
|
}
|
|
181544
|
+
({ percentage: usagePercentage, inputTokens: usageInputTokens } = applyForwardPressureFloor(usagePercentage, usageInputTokens, piUsage?.tokens, usageContextLimit));
|
|
179664
181545
|
if (needsEmergencyBump) {
|
|
179665
181546
|
sessionLog(sessionId, `transform: overflow recovery flag set — bumping percentage to 95% (detectedLimit=${usageContextLimit ?? "unknown"})`);
|
|
179666
|
-
usagePercentage = 95;
|
|
181547
|
+
usagePercentage = Math.max(usagePercentage, 95);
|
|
179667
181548
|
}
|
|
179668
181549
|
let schedulerDecision;
|
|
179669
181550
|
const tScheduler = performance.now();
|
|
@@ -179888,7 +181769,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
179888
181769
|
let tailToolTokens;
|
|
179889
181770
|
let liveTailTokens;
|
|
179890
181771
|
try {
|
|
179891
|
-
const agg = getActiveTagTokenAggregate(options.db, sessionId);
|
|
181772
|
+
const agg = getActiveTagTokenAggregate(options.db, sessionId, options.protectedTags ?? 20);
|
|
179892
181773
|
tailToolTokens = agg.toolOutput;
|
|
179893
181774
|
liveTailTokens = agg.conversation + agg.toolCall;
|
|
179894
181775
|
} catch {
|
|
@@ -180047,6 +181928,7 @@ function spawnPiHistorianRun(args) {
|
|
|
180047
181928
|
provider: provider2,
|
|
180048
181929
|
unregister,
|
|
180049
181930
|
boundarySnapshot,
|
|
181931
|
+
refreshBoundarySnapshot,
|
|
180050
181932
|
currentContextLimit
|
|
180051
181933
|
} = args;
|
|
180052
181934
|
const holderId = crypto3.randomUUID();
|
|
@@ -180070,6 +181952,7 @@ function spawnPiHistorianRun(args) {
|
|
|
180070
181952
|
fallbackModels: historian.fallbackModels,
|
|
180071
181953
|
historianChunkTokens: historian.historianChunkTokens,
|
|
180072
181954
|
boundarySnapshot,
|
|
181955
|
+
refreshBoundarySnapshot,
|
|
180073
181956
|
currentContextLimit,
|
|
180074
181957
|
historianTimeoutMs: historian.timeoutMs,
|
|
180075
181958
|
twoPass: historian.twoPass,
|
|
@@ -180136,6 +182019,7 @@ function maybeFireHistorian(args) {
|
|
|
180136
182019
|
let usageContextLimit;
|
|
180137
182020
|
try {
|
|
180138
182021
|
const piUsage = ctx.getContextUsage?.();
|
|
182022
|
+
let usageSource;
|
|
180139
182023
|
usageContextLimit = isSaneLimit(piUsage?.contextWindow) ? piUsage.contextWindow : undefined;
|
|
180140
182024
|
if (usageContextLimit === undefined && isSaneLimit(ctx.model?.contextWindow)) {
|
|
180141
182025
|
usageContextLimit = ctx.model.contextWindow;
|
|
@@ -180152,7 +182036,7 @@ function maybeFireHistorian(args) {
|
|
|
180152
182036
|
percentage: sessionMetaForUsage.lastContextPercentage,
|
|
180153
182037
|
inputTokens: sessionMetaForUsage.lastInputTokens
|
|
180154
182038
|
};
|
|
180155
|
-
|
|
182039
|
+
usageSource = "session_meta";
|
|
180156
182040
|
} else {
|
|
180157
182041
|
if (!piUsage || piUsage.tokens === null || piUsage.percent === null || piUsage.contextWindow === 0) {
|
|
180158
182042
|
sessionLog(sessionId, `historian trigger eval: no usage info yet (tokens=${piUsage?.tokens ?? "<no piUsage>"}, percent=${piUsage?.percent ?? "<no piUsage>"}, contextWindow=${piUsage?.contextWindow ?? "<no piUsage>"})`);
|
|
@@ -180163,8 +182047,10 @@ function maybeFireHistorian(args) {
|
|
|
180163
182047
|
percentage: fallbackPercentage,
|
|
180164
182048
|
inputTokens: piUsage.tokens
|
|
180165
182049
|
};
|
|
180166
|
-
|
|
182050
|
+
usageSource = "piUsage fallback";
|
|
180167
182051
|
}
|
|
182052
|
+
usage = applyForwardPressureFloor(usage.percentage, usage.inputTokens, piUsage?.tokens, usageContextLimit);
|
|
182053
|
+
sessionLog(sessionId, `historian trigger eval: usage=${usage.percentage.toFixed(1)}% (${usage.inputTokens} tokens) [${usageSource}], checking trigger...`);
|
|
180168
182054
|
} catch (err) {
|
|
180169
182055
|
sessionLog(sessionId, `historian trigger eval: getContextUsage threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
180170
182056
|
return;
|
|
@@ -180195,10 +182081,14 @@ function maybeFireHistorian(args) {
|
|
|
180195
182081
|
cacheNamespace: `pi:${sessionId}`,
|
|
180196
182082
|
emergencyTailScale
|
|
180197
182083
|
}));
|
|
180198
|
-
|
|
180199
|
-
|
|
180200
|
-
|
|
180201
|
-
|
|
182084
|
+
const resolveRunnablePiBoundarySnapshot = () => {
|
|
182085
|
+
let snapshot = ensureRunnablePiBoundaryForTests(resolvePiBoundarySnapshot());
|
|
182086
|
+
if (!hasRunnableCompartmentWindow(snapshot) && usage.percentage >= 80) {
|
|
182087
|
+
snapshot = ensureRunnablePiBoundaryForTests(resolvePiBoundarySnapshot(usage.percentage >= 95 ? 0.25 : 0.5));
|
|
182088
|
+
}
|
|
182089
|
+
return snapshot;
|
|
182090
|
+
};
|
|
182091
|
+
const boundarySnapshot = resolveRunnablePiBoundarySnapshot();
|
|
180202
182092
|
let triggered = false;
|
|
180203
182093
|
try {
|
|
180204
182094
|
if (isFirstContextPassForSession) {
|
|
@@ -180223,6 +182113,7 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
180223
182113
|
provider: provider2,
|
|
180224
182114
|
unregister,
|
|
180225
182115
|
boundarySnapshot,
|
|
182116
|
+
refreshBoundarySnapshot: resolveRunnablePiBoundarySnapshot,
|
|
180226
182117
|
currentContextLimit: boundaryContextLimit
|
|
180227
182118
|
});
|
|
180228
182119
|
return;
|
|
@@ -180231,6 +182122,15 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
180231
182122
|
const trigger = checkCompartmentTrigger(db, sessionId, sessionMeta, usage, 0, triggerInputs.executeThresholdPercentage, triggerInputs.triggerBudget, triggerInputs.clearReasoningAge, triggerInputs.commitClusterTrigger, args.activeTags, boundaryContextLimit);
|
|
180232
182123
|
if (!trigger.shouldFire) {
|
|
180233
182124
|
sessionLog(sessionId, `historian trigger eval: shouldFire=false (no trigger condition met)`);
|
|
182125
|
+
try {
|
|
182126
|
+
const overflowState = getOverflowState(db, sessionId);
|
|
182127
|
+
if (overflowState.needsEmergencyRecovery && usage.percentage < FORCE_MATERIALIZATION_PERCENTAGE && !inFlightHistorian.has(sessionId) && !hasRunnableCompartmentWindow(boundarySnapshot)) {
|
|
182128
|
+
clearEmergencyRecovery(db, sessionId);
|
|
182129
|
+
sessionLog(sessionId, `historian: disarming stale emergency recovery — real pressure ${usage.percentage.toFixed(1)}% with no runnable compartment window (would otherwise bump to 95% every pass)`);
|
|
182130
|
+
}
|
|
182131
|
+
} catch (err) {
|
|
182132
|
+
sessionLog(sessionId, `historian: emergency-recovery disarm check failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
182133
|
+
}
|
|
180234
182134
|
return;
|
|
180235
182135
|
}
|
|
180236
182136
|
triggered = true;
|
|
@@ -180246,6 +182146,7 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
180246
182146
|
resolvedBoundarySnapshot: boundarySnapshot,
|
|
180247
182147
|
triggerBoundarySnapshot: trigger.boundarySnapshot
|
|
180248
182148
|
}),
|
|
182149
|
+
refreshBoundarySnapshot: resolveRunnablePiBoundarySnapshot,
|
|
180249
182150
|
currentContextLimit: boundaryContextLimit
|
|
180250
182151
|
});
|
|
180251
182152
|
} catch (err) {
|
|
@@ -180286,7 +182187,31 @@ async function runPipeline(args) {
|
|
|
180286
182187
|
const alreadyRanHeuristicsThisTurn = currentTurnId !== null && lastHeuristicsTurnIdBySession.get(args.sessionId) === currentTurnId;
|
|
180287
182188
|
const canConsumeDeferredLate = args.schedulerDecision === "execute" || args.forceMaterialization === true || args.contextUsage.percentage >= FORCE_MATERIALIZATION_PERCENTAGE;
|
|
180288
182189
|
const deferredMaterializeEligible = canConsumeDeferredLate && deferredMaterializationSessions.has(args.sessionId);
|
|
180289
|
-
const
|
|
182190
|
+
const piHardSignals = args.injection ? (() => {
|
|
182191
|
+
const hardMeta = getOrCreateSessionMeta(args.db, args.sessionId);
|
|
182192
|
+
let piTtlMs = 5 * 60 * 1000;
|
|
182193
|
+
try {
|
|
182194
|
+
piTtlMs = parseCacheTtl(hardMeta.cacheTtl);
|
|
182195
|
+
} catch {}
|
|
182196
|
+
return {
|
|
182197
|
+
systemHash: typeof hardMeta.systemPromptHash === "string" ? hardMeta.systemPromptHash : "",
|
|
182198
|
+
modelKey: liveModelBySession.get(args.sessionId) ?? "",
|
|
182199
|
+
cacheExpired: hardMeta.lastResponseTime > 0 && Date.now() - hardMeta.lastResponseTime >= piTtlMs,
|
|
182200
|
+
lastResponseTime: hardMeta.lastResponseTime
|
|
182201
|
+
};
|
|
182202
|
+
})() : undefined;
|
|
182203
|
+
const m0HardFoldThisPass = args.injection && piHardSignals ? mustMaterializePi({
|
|
182204
|
+
sessionId: args.sessionId,
|
|
182205
|
+
projectIdentity: args.projectIdentity,
|
|
182206
|
+
projectDirectory: args.projectDirectory,
|
|
182207
|
+
memoryEnabled: args.injection.memoryEnabled,
|
|
182208
|
+
injectionBudgetTokens: args.injection.injectionBudgetTokens,
|
|
182209
|
+
historyBudgetTokens: args.injection.historyBudgetTokens,
|
|
182210
|
+
keyFilesEnabled: args.injection.keyFilesEnabled,
|
|
182211
|
+
keyFilesTokenBudget: args.injection.keyFilesTokenBudget,
|
|
182212
|
+
hardSignals: piHardSignals
|
|
182213
|
+
}, args.db, getCompartments(args.db, args.sessionId)).value : false;
|
|
182214
|
+
const shouldRunHeuristics = args.heuristics !== undefined && (args.forceMaterialization === true || hasPendingMaterialization(args.sessionId) || deferredMaterializeEligible || m0HardFoldThisPass || args.schedulerDecision === "execute" && !alreadyRanHeuristicsThisTurn);
|
|
180290
182215
|
const entryFingerprintByMessageId = buildEntryFingerprintMap(args.messages, stableIdResolver);
|
|
180291
182216
|
adoptPiFallbackTags(args.db, args.sessionId, args.tagger, entryFingerprintByMessageId);
|
|
180292
182217
|
const tTag = performance.now();
|
|
@@ -180313,12 +182238,12 @@ async function runPipeline(args) {
|
|
|
180313
182238
|
const deferredMaterializationWasPending = deferredMaterializationSessions.has(args.sessionId);
|
|
180314
182239
|
const deferredHistoryRefreshWasPending = deferredHistoryWasPendingAtPassStart;
|
|
180315
182240
|
const pendingOps = getPendingOps(args.db, args.sessionId);
|
|
180316
|
-
const baseShouldApplyPendingOps = args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal;
|
|
182241
|
+
const baseShouldApplyPendingOps = args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || m0HardFoldThisPass;
|
|
180317
182242
|
const deferredMaterialize = canConsumeDeferredLate && deferredMaterializationWasPending;
|
|
180318
182243
|
const deferredHistoryRefresh = canConsumeDeferredLate && deferredHistoryRefreshWasPending;
|
|
180319
182244
|
const shouldApplyPendingOps = baseShouldApplyPendingOps || deferredMaterialize;
|
|
180320
182245
|
if (shouldApplyPendingOps) {
|
|
180321
|
-
const applyReason = hasPendingMaterializeSignal ? "explicit_flush" : deferredMaterialize ? "deferred_publication" : args.forceMaterialization ? "force_materialization" : `scheduler_execute (scheduler=${args.schedulerDecision})`;
|
|
182246
|
+
const applyReason = hasPendingMaterializeSignal ? "explicit_flush" : deferredMaterialize ? "deferred_publication" : args.forceMaterialization ? "force_materialization" : m0HardFoldThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into known m[0] bust, scheduler=${args.schedulerDecision})` : `scheduler_execute (scheduler=${args.schedulerDecision})`;
|
|
180322
182247
|
sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOps.length}, context=${args.contextUsage.percentage.toFixed(1)}%`);
|
|
180323
182248
|
try {
|
|
180324
182249
|
const tApplyPending = performance.now();
|
|
@@ -180389,7 +182314,7 @@ async function runPipeline(args) {
|
|
|
180389
182314
|
const activeTags = getActiveTagsBySession(args.db, args.sessionId);
|
|
180390
182315
|
logTransformTiming(args.sessionId, "getActiveTagsBySession", tActiveTags, `count=${activeTags.length}`);
|
|
180391
182316
|
if (shouldRunHeuristics) {
|
|
180392
|
-
const reason = args.forceMaterialization ? "force_materialization" : `scheduler_execute (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
|
|
182317
|
+
const reason = args.forceMaterialization ? "force_materialization" : m0HardFoldThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into known m[0] bust, scheduler=${args.schedulerDecision})` : `scheduler_execute (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
|
|
180393
182318
|
sessionLog(args.sessionId, `heuristics WILL RUN — reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=n/a`);
|
|
180394
182319
|
} else {
|
|
180395
182320
|
const reason = args.heuristics === undefined ? "disabled" : "scheduler_defer";
|
|
@@ -180477,17 +182402,6 @@ async function runPipeline(args) {
|
|
|
180477
182402
|
if (args.injection) {
|
|
180478
182403
|
try {
|
|
180479
182404
|
const tInjection = performance.now();
|
|
180480
|
-
const hardMeta = getOrCreateSessionMeta(args.db, args.sessionId);
|
|
180481
|
-
let piTtlMs = 5 * 60 * 1000;
|
|
180482
|
-
try {
|
|
180483
|
-
piTtlMs = parseCacheTtl(hardMeta.cacheTtl);
|
|
180484
|
-
} catch {}
|
|
180485
|
-
const piHardSignals = {
|
|
180486
|
-
systemHash: typeof hardMeta.systemPromptHash === "string" ? hardMeta.systemPromptHash : "",
|
|
180487
|
-
modelKey: liveModelBySession.get(args.sessionId) ?? "",
|
|
180488
|
-
cacheExpired: hardMeta.lastResponseTime > 0 && Date.now() - hardMeta.lastResponseTime >= piTtlMs,
|
|
180489
|
-
lastResponseTime: hardMeta.lastResponseTime
|
|
180490
|
-
};
|
|
180491
182405
|
injectionResult = injectM0M1Pi({
|
|
180492
182406
|
sessionId: args.sessionId,
|
|
180493
182407
|
projectIdentity: args.projectIdentity,
|
|
@@ -181577,8 +183491,12 @@ Found ${existingStaging.compartments.length} staged compartment(s) from ${existi
|
|
|
181577
183491
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
181578
183492
|
await deps.ensureProjectRegistered?.(sessionDirectory, db);
|
|
181579
183493
|
const liveCompartments = getCompartments(db, sessionId);
|
|
181580
|
-
const
|
|
181581
|
-
|
|
183494
|
+
const chunksToEmbed = liveCompartments.map((c) => ({
|
|
183495
|
+
id: c.id,
|
|
183496
|
+
startMessage: c.startMessage,
|
|
183497
|
+
endMessage: c.endMessage
|
|
183498
|
+
}));
|
|
183499
|
+
embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed);
|
|
181582
183500
|
}
|
|
181583
183501
|
const lastCompartmentEnd2 = promoted2.compartments[promoted2.compartments.length - 1]?.endMessage ?? 0;
|
|
181584
183502
|
if (lastCompartmentEnd2 > 0) {
|
|
@@ -181791,8 +183709,12 @@ Another process acquired the compartment-state lease before recomp could publish
|
|
|
181791
183709
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
181792
183710
|
await deps.ensureProjectRegistered?.(sessionDirectory, db);
|
|
181793
183711
|
const liveCompartments = getCompartments(db, sessionId);
|
|
181794
|
-
const
|
|
181795
|
-
|
|
183712
|
+
const chunksToEmbed = liveCompartments.map((c) => ({
|
|
183713
|
+
id: c.id,
|
|
183714
|
+
startMessage: c.startMessage,
|
|
183715
|
+
endMessage: c.endMessage
|
|
183716
|
+
}));
|
|
183717
|
+
embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed);
|
|
181796
183718
|
}
|
|
181797
183719
|
if (lastCompartmentEnd > 0) {
|
|
181798
183720
|
const markerUpdated = updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, deps.directory);
|
|
@@ -181949,8 +183871,12 @@ Could not acquire the compartment-state lease for this session.`;
|
|
|
181949
183871
|
if (deps.memoryEnabled !== false) {
|
|
181950
183872
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
181951
183873
|
const liveCompartments = getCompartments(db, sessionId);
|
|
181952
|
-
const
|
|
181953
|
-
|
|
183874
|
+
const chunksToEmbed = liveCompartments.map((c) => ({
|
|
183875
|
+
id: c.id,
|
|
183876
|
+
startMessage: c.startMessage,
|
|
183877
|
+
endMessage: c.endMessage
|
|
183878
|
+
}));
|
|
183879
|
+
Promise.resolve(deps.ensureProjectRegistered?.(sessionDirectory, db)).then(() => embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed));
|
|
181954
183880
|
}
|
|
181955
183881
|
const lastEnd = merged[merged.length - 1]?.endMessage ?? snapEnd;
|
|
181956
183882
|
if (lastEnd > 0) {
|
|
@@ -182585,6 +184511,11 @@ Historian recomp started. Rebuilding compartments and facts from raw Pi session
|
|
|
182585
184511
|
fallbackModelId: ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined
|
|
182586
184512
|
}, parsed.kind === "partial" ? { range: parsed.range } : {});
|
|
182587
184513
|
if (result.published) {
|
|
184514
|
+
try {
|
|
184515
|
+
clearEmergencyRecovery(deps.db, sessionId);
|
|
184516
|
+
} catch (recoveryError) {
|
|
184517
|
+
sessionLog(sessionId, `/ctx-recomp: clearEmergencyRecovery failed (continuing): ${describeError(recoveryError).brief}`);
|
|
184518
|
+
}
|
|
182588
184519
|
try {
|
|
182589
184520
|
stagePiRecompMarker({ db: deps.db, sessionId, ctx });
|
|
182590
184521
|
} catch (markerError) {
|
|
@@ -182762,7 +184693,7 @@ function applyMemoryMigration(db, projectPath, result) {
|
|
|
182762
184693
|
inserted++;
|
|
182763
184694
|
}
|
|
182764
184695
|
if (removed > 0 || inserted > 0) {
|
|
182765
|
-
|
|
184696
|
+
bumpEpochsForWorkspaceMembers(db, projectPath);
|
|
182766
184697
|
}
|
|
182767
184698
|
})();
|
|
182768
184699
|
return { removed, inserted };
|
|
@@ -183238,7 +185169,7 @@ function formatThresholdPercent(value) {
|
|
|
183238
185169
|
// package.json
|
|
183239
185170
|
var package_default = {
|
|
183240
185171
|
name: "@cortexkit/pi-magic-context",
|
|
183241
|
-
version: "0.
|
|
185172
|
+
version: "0.24.1",
|
|
183242
185173
|
type: "module",
|
|
183243
185174
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
183244
185175
|
main: "dist/index.js",
|
|
@@ -188102,6 +190033,23 @@ function createCtxMemoryTool(deps) {
|
|
|
188102
190033
|
}
|
|
188103
190034
|
const projectIdentity = resolveProjectIdentity(ctx.cwd);
|
|
188104
190035
|
await deps.ensureProjectRegistered?.(ctx.cwd, deps.db);
|
|
190036
|
+
const workspaceIdentitySet = resolveWorkspaceIdentitySet(deps.db, projectIdentity);
|
|
190037
|
+
const expandedWorkspace = expandWorkspaceIdentitySetWithAliases(deps.db, workspaceIdentitySet.identities);
|
|
190038
|
+
const workspaceVisibleIdentities = workspaceIdentitySet.identities.length > 1 ? expandedWorkspace.expandedIdentities : workspaceIdentitySet.identities;
|
|
190039
|
+
const targetIdentityForStoredPath = (rawProjectPath) => workspaceIdentitySet.identities.length > 1 ? resolveStoredPathWorkspaceIdentity(rawProjectPath, workspaceIdentitySet.identities, expandedWorkspace.canonicalIdentityByStoredPath) ?? normalizeStoredProjectPath(rawProjectPath) : normalizeStoredProjectPath(rawProjectPath);
|
|
190040
|
+
const toolShareCategories = workspaceIdentitySet.identities.length > 1 ? resolveWorkspaceShareCategories(deps.db, projectIdentity) : null;
|
|
190041
|
+
const memoryVisibleToTool = (memory2) => {
|
|
190042
|
+
if (workspaceIdentitySet.identities.length <= 1) {
|
|
190043
|
+
return storedPathBelongsToIdentity(memory2.projectPath, projectIdentity);
|
|
190044
|
+
}
|
|
190045
|
+
if (!storedPathBelongsToWorkspace(memory2.projectPath, workspaceIdentitySet.identities, workspaceVisibleIdentities, expandedWorkspace.canonicalIdentityByStoredPath)) {
|
|
190046
|
+
return false;
|
|
190047
|
+
}
|
|
190048
|
+
const isOwn = targetIdentityForStoredPath(memory2.projectPath) === projectIdentity;
|
|
190049
|
+
if (isOwn)
|
|
190050
|
+
return true;
|
|
190051
|
+
return toolShareCategories === null || toolShareCategories.includes(memory2.category);
|
|
190052
|
+
};
|
|
188105
190053
|
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
188106
190054
|
if (snapshot ? !snapshot.features.memoryEnabled : deps.memoryEnabled === false) {
|
|
188107
190055
|
return err2("Cross-session memory is disabled for this project.");
|
|
@@ -188148,28 +190096,34 @@ function createCtxMemoryTool(deps) {
|
|
|
188148
190096
|
return err2("Error: 'content' is required when action is 'update'.");
|
|
188149
190097
|
}
|
|
188150
190098
|
const memory2 = getMemoryById(deps.db, updateId);
|
|
188151
|
-
if (!memory2 || !
|
|
190099
|
+
if (!memory2 || !memoryVisibleToTool(memory2)) {
|
|
188152
190100
|
return err2(`Error: Memory with ID ${updateId} was not found.`);
|
|
188153
190101
|
}
|
|
188154
190102
|
if (!dreamerAllowed && !isPrimaryMutableMemory(memory2)) {
|
|
188155
190103
|
return err2(inactiveMemoryError(updateId, "updating"));
|
|
188156
190104
|
}
|
|
188157
190105
|
const normalizedHash = computeNormalizedHash(content);
|
|
188158
|
-
const
|
|
190106
|
+
const targetIdentity = targetIdentityForStoredPath(memory2.projectPath);
|
|
190107
|
+
const duplicate = getMemoryByHash(deps.db, targetIdentity, memory2.category, normalizedHash);
|
|
188159
190108
|
if (duplicate && duplicate.id !== memory2.id) {
|
|
188160
190109
|
return err2(`Error: Memory content already exists as ID ${duplicate.id}; merge or archive duplicates instead.`);
|
|
188161
190110
|
}
|
|
188162
190111
|
deps.db.transaction(() => {
|
|
188163
190112
|
updateMemoryContent(deps.db, memory2.id, content, normalizedHash);
|
|
188164
190113
|
queueMemoryMutation(deps.db, {
|
|
188165
|
-
projectPath:
|
|
190114
|
+
projectPath: targetIdentity,
|
|
188166
190115
|
mutationType: "update",
|
|
188167
190116
|
targetMemoryId: memory2.id,
|
|
188168
190117
|
category: memory2.category,
|
|
188169
190118
|
newContent: content
|
|
188170
190119
|
});
|
|
188171
190120
|
})();
|
|
188172
|
-
queueEmbedding({
|
|
190121
|
+
queueEmbedding({
|
|
190122
|
+
deps,
|
|
190123
|
+
projectIdentity: targetIdentity,
|
|
190124
|
+
memoryId: memory2.id,
|
|
190125
|
+
content
|
|
190126
|
+
});
|
|
188173
190127
|
return ok2(`Updated memory [ID: ${memory2.id}] in ${memory2.category}.`);
|
|
188174
190128
|
}
|
|
188175
190129
|
if (params.action === "merge") {
|
|
@@ -188189,7 +190143,7 @@ function createCtxMemoryTool(deps) {
|
|
|
188189
190143
|
return err2("Error: One or more source memories were not found.");
|
|
188190
190144
|
}
|
|
188191
190145
|
if (!dreamerAllowed) {
|
|
188192
|
-
const foreign = sourceMemories.find((memory2) => !
|
|
190146
|
+
const foreign = sourceMemories.find((memory2) => !memoryVisibleToTool(memory2));
|
|
188193
190147
|
if (foreign) {
|
|
188194
190148
|
return err2(`Error: Memory with ID ${foreign.id} was not found.`);
|
|
188195
190149
|
}
|
|
@@ -188278,26 +190232,36 @@ function createCtxMemoryTool(deps) {
|
|
|
188278
190232
|
return ok2(`Merged memories [${ids.join(", ")}] into canonical memory [ID: ${canonicalMemory.id}] in ${category}; superseded [${supersededIds.join(", ")}].`);
|
|
188279
190233
|
}
|
|
188280
190234
|
if (params.action === "archive") {
|
|
188281
|
-
const
|
|
188282
|
-
if (!
|
|
190235
|
+
const rawArchiveIds = params.ids;
|
|
190236
|
+
if (!rawArchiveIds || rawArchiveIds.length === 0 || !rawArchiveIds.every(Number.isInteger)) {
|
|
188283
190237
|
return err2("Error: 'ids' must contain at least one integer memory ID when action is 'archive'.");
|
|
188284
190238
|
}
|
|
190239
|
+
const archiveIds = [...new Set(rawArchiveIds)];
|
|
188285
190240
|
for (const memoryId of archiveIds) {
|
|
188286
190241
|
const memory2 = getMemoryById(deps.db, memoryId);
|
|
188287
|
-
if (!memory2 || !
|
|
190242
|
+
if (!memory2 || !memoryVisibleToTool(memory2)) {
|
|
188288
190243
|
return err2(`Error: Memory with ID ${memoryId} was not found.`);
|
|
188289
190244
|
}
|
|
188290
190245
|
if (!dreamerAllowed && !isPrimaryMutableMemory(memory2)) {
|
|
188291
190246
|
return err2(inactiveMemoryError(memoryId, "archiving"));
|
|
188292
190247
|
}
|
|
188293
190248
|
}
|
|
190249
|
+
const targets = archiveIds.map((memoryId) => {
|
|
190250
|
+
const memory2 = getMemoryById(deps.db, memoryId);
|
|
190251
|
+
if (!memory2)
|
|
190252
|
+
throw new Error(`validated memory ${memoryId} disappeared`);
|
|
190253
|
+
return {
|
|
190254
|
+
memoryId,
|
|
190255
|
+
projectIdentity: targetIdentityForStoredPath(memory2.projectPath)
|
|
190256
|
+
};
|
|
190257
|
+
});
|
|
188294
190258
|
deps.db.transaction(() => {
|
|
188295
|
-
for (const
|
|
188296
|
-
archiveMemory(deps.db, memoryId, params.reason);
|
|
190259
|
+
for (const target2 of targets) {
|
|
190260
|
+
archiveMemory(deps.db, target2.memoryId, params.reason);
|
|
188297
190261
|
queueMemoryMutation(deps.db, {
|
|
188298
|
-
projectPath: projectIdentity,
|
|
190262
|
+
projectPath: target2.projectIdentity,
|
|
188299
190263
|
mutationType: "archive",
|
|
188300
|
-
targetMemoryId: memoryId
|
|
190264
|
+
targetMemoryId: target2.memoryId
|
|
188301
190265
|
});
|
|
188302
190266
|
}
|
|
188303
190267
|
})();
|
|
@@ -188805,8 +190769,9 @@ function formatAge2(committedAtMs) {
|
|
|
188805
190769
|
}
|
|
188806
190770
|
function formatResult(result, index) {
|
|
188807
190771
|
if (result.source === "memory") {
|
|
190772
|
+
const source = result.sourceName ? ` source=${result.sourceName}` : "";
|
|
188808
190773
|
return [
|
|
188809
|
-
`[${index}] [memory] score=${result.score.toFixed(2)} id=${result.memoryId} category=${result.category} match=${result.matchType}`,
|
|
190774
|
+
`[${index}] [memory] score=${result.score.toFixed(2)} id=${result.memoryId} category=${result.category}${source} match=${result.matchType}`,
|
|
188810
190775
|
result.content
|
|
188811
190776
|
].join(`
|
|
188812
190777
|
`);
|
|
@@ -188816,6 +190781,13 @@ function formatResult(result, index) {
|
|
|
188816
190781
|
`[${index}] [git_commit] score=${result.score.toFixed(2)} sha=${result.shortSha} ${formatAge2(result.committedAtMs)} match=${result.matchType}`,
|
|
188817
190782
|
result.content
|
|
188818
190783
|
].join(`
|
|
190784
|
+
`);
|
|
190785
|
+
}
|
|
190786
|
+
if (result.source === "compartment") {
|
|
190787
|
+
return [
|
|
190788
|
+
`[${index}] [message] score=${result.score.toFixed(2)} compartment_id=${result.compartmentId} range=${result.startOrdinal}-${result.endOrdinal} match=${result.matchType} title=${result.title}`,
|
|
190789
|
+
result.snippet ? `Snippet: ${result.snippet}` : result.content
|
|
190790
|
+
].join(`
|
|
188819
190791
|
`);
|
|
188820
190792
|
}
|
|
188821
190793
|
const expandStart = Math.max(1, result.messageOrdinal - 3);
|
|
@@ -188831,7 +190803,7 @@ function formatSearchResults(query, results) {
|
|
|
188831
190803
|
return `No results found for "${query}" across memories, git commits, or message history.`;
|
|
188832
190804
|
}
|
|
188833
190805
|
const bodyParts = results.map((result, index) => formatResult(result, index + 1));
|
|
188834
|
-
if (results.some((result) => result.source === "message")) {
|
|
190806
|
+
if (results.some((result) => result.source === "message" || result.source === "compartment")) {
|
|
188835
190807
|
bodyParts.push("Use ctx_expand(start, end) with the range from any message result above to read the full conversation context.");
|
|
188836
190808
|
}
|
|
188837
190809
|
const body = bodyParts.join(`
|
|
@@ -189327,6 +191299,14 @@ async function src_default2(pi) {
|
|
|
189327
191299
|
onProjectSeen: (identity) => seenDreamerProjectIdentities.add(identity)
|
|
189328
191300
|
});
|
|
189329
191301
|
info("registered /ctx-dream");
|
|
191302
|
+
registerCtxEmbedHistoryCommand(pi, {
|
|
191303
|
+
db,
|
|
191304
|
+
projectDir,
|
|
191305
|
+
projectIdentity,
|
|
191306
|
+
memoryEnabled: config2.memory.enabled,
|
|
191307
|
+
resolveProject: resolveCurrentProject
|
|
191308
|
+
});
|
|
191309
|
+
info("registered /ctx-embed-history");
|
|
189330
191310
|
const dreamerConfig = resolveDreamerFromConfig(config2);
|
|
189331
191311
|
if (dreamerConfig) {
|
|
189332
191312
|
registerPiDreamerProject({
|