@cortexkit/opencode-magic-context 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/config/schema/magic-context.d.ts +10 -3
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/features/builtin-commands/commands.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts +70 -0
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -0
- package/dist/features/magic-context/compartment-embedding.d.ts +22 -26
- package/dist/features/magic-context/compartment-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-backfill.d.ts +3 -2
- package/dist/features/magic-context/memory/embedding-backfill.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-cache.d.ts +3 -2
- package/dist/features/magic-context/memory/embedding-cache.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts +2 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-openai.d.ts +3 -0
- package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-provider.d.ts +2 -0
- package/dist/features/magic-context/memory/embedding-provider.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts +5 -1
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts +1 -7
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory.d.ts +18 -12
- package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts +53 -0
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +14 -1
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/session-project-storage.d.ts +17 -0
- package/dist/features/magic-context/session-project-storage.d.ts.map +1 -0
- package/dist/features/magic-context/storage-db.d.ts +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-memory-mutation-log.d.ts +2 -0
- package/dist/features/magic-context/storage-memory-mutation-log.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +16 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-shared.d.ts +3 -2
- package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +1 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +3 -2
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/tool-definition-tokens.d.ts +0 -21
- package/dist/features/magic-context/tool-definition-tokens.d.ts.map +1 -1
- package/dist/features/magic-context/types.d.ts +1 -0
- package/dist/features/magic-context/types.d.ts.map +1 -1
- package/dist/features/magic-context/workspaces.d.ts +20 -0
- package/dist/features/magic-context/workspaces.d.ts.map +1 -0
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-hint.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +5 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +11 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +18 -0
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -0
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +23 -5
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/issue-135-wire-fixtures.d.ts +8 -0
- package/dist/hooks/magic-context/issue-135-wire-fixtures.d.ts.map +1 -0
- package/dist/hooks/magic-context/openai-compat-adjacency.d.ts +38 -0
- package/dist/hooks/magic-context/openai-compat-adjacency.d.ts.map +1 -0
- package/dist/hooks/magic-context/recomp-orchestrator.d.ts +1 -1
- package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
- package/dist/hooks/magic-context/reference-retrieval.d.ts.map +1 -1
- package/dist/hooks/magic-context/sentinel.d.ts +33 -28
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +34 -17
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-structural-noise.d.ts +5 -7
- package/dist/hooks/magic-context/strip-structural-noise.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +4 -5
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +0 -8
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/index.js +2387 -348
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/shared/announcement.d.ts +1 -1
- package/dist/shared/rpc-types.d.ts +1 -1
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/tools.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/shared/announcement.ts +6 -6
- package/src/shared/rpc-types.ts +1 -1
- package/src/tui/index.tsx +5 -3
- package/src/tui/slots/sidebar-content.tsx +24 -5
package/dist/index.js
CHANGED
|
@@ -14887,7 +14887,8 @@ var init_magic_context = __esm(() => {
|
|
|
14887
14887
|
endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
|
|
14888
14888
|
api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
|
|
14889
14889
|
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."),
|
|
14890
|
-
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.")
|
|
14890
|
+
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."),
|
|
14891
|
+
max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
|
|
14891
14892
|
}).superRefine((data, ctx) => {
|
|
14892
14893
|
if (data.provider === "openai-compatible" && !data.endpoint?.trim()) {
|
|
14893
14894
|
ctx.addIssue({
|
|
@@ -14908,7 +14909,8 @@ var init_magic_context = __esm(() => {
|
|
|
14908
14909
|
if (data.provider === "local") {
|
|
14909
14910
|
return {
|
|
14910
14911
|
provider: "local",
|
|
14911
|
-
model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
14912
|
+
model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
14913
|
+
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
|
|
14912
14914
|
};
|
|
14913
14915
|
}
|
|
14914
14916
|
if (data.provider === "openai-compatible") {
|
|
@@ -14921,7 +14923,8 @@ var init_magic_context = __esm(() => {
|
|
|
14921
14923
|
endpoint: data.endpoint?.trim() ?? "",
|
|
14922
14924
|
...apiKey ? { api_key: apiKey } : {},
|
|
14923
14925
|
...inputType ? { input_type: inputType } : {},
|
|
14924
|
-
...truncate ? { truncate } : {}
|
|
14926
|
+
...truncate ? { truncate } : {},
|
|
14927
|
+
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
|
|
14925
14928
|
};
|
|
14926
14929
|
}
|
|
14927
14930
|
return { provider: "off" };
|
|
@@ -15841,7 +15844,7 @@ function isSessionMetaRow(row) {
|
|
|
15841
15844
|
if (row === null || typeof row !== "object")
|
|
15842
15845
|
return false;
|
|
15843
15846
|
const r = row;
|
|
15844
|
-
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);
|
|
15847
|
+
return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isStringOrNull(r.cached_m0_workspace_fingerprint) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.cached_m0_system_hash) && isStringOrNull(r.cached_m0_tool_set_hash) && isStringOrNull(r.cached_m0_model_key) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.last_usage_context_limit) && isNumberOrNull(r.prior_boundary_ordinal) && isNumberOrNull(r.protected_tail_policy_version) && isNumberOrNull(r.protected_tail_drain_window_started_at) && isNumberOrNull(r.protected_tail_drain_tokens) && isNumberOrNull(r.recovery_no_eligible_head_count) && isNumberOrNull(r.force_emergency_bypass_window_start) && isNumberOrNull(r.force_emergency_bypass_used) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme);
|
|
15845
15848
|
}
|
|
15846
15849
|
function getDefaultSessionMeta(sessionId) {
|
|
15847
15850
|
return {
|
|
@@ -15868,6 +15871,7 @@ function getDefaultSessionMeta(sessionId) {
|
|
|
15868
15871
|
cachedM0Bytes: null,
|
|
15869
15872
|
cachedM1Bytes: null,
|
|
15870
15873
|
cachedM0ProjectMemoryEpoch: null,
|
|
15874
|
+
cachedM0WorkspaceFingerprint: null,
|
|
15871
15875
|
cachedM0ProjectUserProfileVersion: null,
|
|
15872
15876
|
cachedM0MaxCompartmentSeq: null,
|
|
15873
15877
|
cachedM0MaxMemoryId: null,
|
|
@@ -15930,6 +15934,7 @@ function toSessionMeta(row) {
|
|
|
15930
15934
|
cachedM0Bytes: toBufferOrNull(row.cached_m0_bytes),
|
|
15931
15935
|
cachedM1Bytes: toBufferOrNull(row.cached_m1_bytes),
|
|
15932
15936
|
cachedM0ProjectMemoryEpoch: numOrNull(row.cached_m0_project_memory_epoch),
|
|
15937
|
+
cachedM0WorkspaceFingerprint: stringOrNull(row.cached_m0_workspace_fingerprint),
|
|
15933
15938
|
cachedM0ProjectUserProfileVersion: numOrNull(row.cached_m0_project_user_profile_version),
|
|
15934
15939
|
cachedM0MaxCompartmentSeq: numOrNull(row.cached_m0_max_compartment_seq),
|
|
15935
15940
|
cachedM0MaxMemoryId: numOrNull(row.cached_m0_max_memory_id),
|
|
@@ -15960,6 +15965,7 @@ function persistCachedM0(db, sessionId, payload) {
|
|
|
15960
15965
|
db.prepare(`UPDATE session_meta SET
|
|
15961
15966
|
cached_m0_bytes = ?,
|
|
15962
15967
|
cached_m0_project_memory_epoch = ?,
|
|
15968
|
+
cached_m0_workspace_fingerprint = ?,
|
|
15963
15969
|
cached_m0_project_user_profile_version = ?,
|
|
15964
15970
|
cached_m0_max_compartment_seq = ?,
|
|
15965
15971
|
cached_m0_max_memory_id = ?,
|
|
@@ -15971,9 +15977,8 @@ function persistCachedM0(db, sessionId, payload) {
|
|
|
15971
15977
|
cached_m0_session_facts_version = ?,
|
|
15972
15978
|
cached_m0_upgrade_state = ?,
|
|
15973
15979
|
cached_m0_system_hash = ?,
|
|
15974
|
-
cached_m0_tool_set_hash = ?,
|
|
15975
15980
|
cached_m0_model_key = ?
|
|
15976
|
-
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.
|
|
15981
|
+
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);
|
|
15977
15982
|
}
|
|
15978
15983
|
function clearCachedM0M1(db, sessionId) {
|
|
15979
15984
|
ensureSessionMetaRow(db, sessionId);
|
|
@@ -15982,6 +15987,7 @@ function clearCachedM0M1(db, sessionId) {
|
|
|
15982
15987
|
["cached_m0_bytes", null],
|
|
15983
15988
|
["cached_m1_bytes", null],
|
|
15984
15989
|
["cached_m0_project_memory_epoch", null],
|
|
15990
|
+
["cached_m0_workspace_fingerprint", null],
|
|
15985
15991
|
["cached_m0_project_user_profile_version", null],
|
|
15986
15992
|
["cached_m0_max_compartment_seq", null],
|
|
15987
15993
|
["cached_m0_max_memory_id", null],
|
|
@@ -16037,6 +16043,7 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16037
16043
|
"cached_m0_bytes",
|
|
16038
16044
|
"cached_m1_bytes",
|
|
16039
16045
|
"cached_m0_project_memory_epoch",
|
|
16046
|
+
"cached_m0_workspace_fingerprint",
|
|
16040
16047
|
"cached_m0_project_user_profile_version",
|
|
16041
16048
|
"cached_m0_max_compartment_seq",
|
|
16042
16049
|
"cached_m0_max_memory_id",
|
|
@@ -16084,6 +16091,7 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16084
16091
|
cachedM0Bytes: "cached_m0_bytes",
|
|
16085
16092
|
cachedM1Bytes: "cached_m1_bytes",
|
|
16086
16093
|
cachedM0ProjectMemoryEpoch: "cached_m0_project_memory_epoch",
|
|
16094
|
+
cachedM0WorkspaceFingerprint: "cached_m0_workspace_fingerprint",
|
|
16087
16095
|
cachedM0ProjectUserProfileVersion: "cached_m0_project_user_profile_version",
|
|
16088
16096
|
cachedM0MaxCompartmentSeq: "cached_m0_max_compartment_seq",
|
|
16089
16097
|
cachedM0MaxMemoryId: "cached_m0_max_memory_id",
|
|
@@ -16113,6 +16121,7 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16113
16121
|
"cachedM0Bytes",
|
|
16114
16122
|
"cachedM1Bytes",
|
|
16115
16123
|
"cachedM0ProjectMemoryEpoch",
|
|
16124
|
+
"cachedM0WorkspaceFingerprint",
|
|
16116
16125
|
"cachedM0ProjectUserProfileVersion",
|
|
16117
16126
|
"cachedM0MaxCompartmentSeq",
|
|
16118
16127
|
"cachedM0MaxMemoryId",
|
|
@@ -150317,18 +150326,6 @@ function keyFor(providerID, modelID, agentName) {
|
|
|
150317
150326
|
function fingerprintFor(description, parameters) {
|
|
150318
150327
|
return createHash3("sha256").update(description).update("\x00").update(stableStringify(parameters)).digest("hex");
|
|
150319
150328
|
}
|
|
150320
|
-
function getCurrentToolSetHash(providerID, modelID, agentName) {
|
|
150321
|
-
const key = keyFor(providerID, modelID, agentName);
|
|
150322
|
-
const inner = fingerprints.get(key);
|
|
150323
|
-
if (!inner || inner.size === 0)
|
|
150324
|
-
return "";
|
|
150325
|
-
const parts = [];
|
|
150326
|
-
for (const [toolID, fp] of inner)
|
|
150327
|
-
parts.push(`${toolID}\x00${fp}`);
|
|
150328
|
-
parts.sort();
|
|
150329
|
-
return createHash3("sha256").update(parts.join(`
|
|
150330
|
-
`)).digest("hex");
|
|
150331
|
-
}
|
|
150332
150329
|
function setDatabase(db) {
|
|
150333
150330
|
persistenceDb = db;
|
|
150334
150331
|
cachedInsertStmt = null;
|
|
@@ -150836,6 +150833,35 @@ function initializeDatabase(db) {
|
|
|
150836
150833
|
);
|
|
150837
150834
|
CREATE INDEX IF NOT EXISTS idx_compartments_session ON compartments(session_id);
|
|
150838
150835
|
|
|
150836
|
+
CREATE TABLE IF NOT EXISTS compartment_chunk_embeddings (
|
|
150837
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
150838
|
+
compartment_id INTEGER NOT NULL REFERENCES compartments(id) ON DELETE CASCADE,
|
|
150839
|
+
session_id TEXT NOT NULL,
|
|
150840
|
+
project_path TEXT NOT NULL,
|
|
150841
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
150842
|
+
window_index INTEGER NOT NULL DEFAULT 0,
|
|
150843
|
+
start_ordinal INTEGER NOT NULL,
|
|
150844
|
+
end_ordinal INTEGER NOT NULL,
|
|
150845
|
+
chunk_hash TEXT NOT NULL,
|
|
150846
|
+
model_id TEXT NOT NULL,
|
|
150847
|
+
dims INTEGER NOT NULL,
|
|
150848
|
+
vector BLOB NOT NULL,
|
|
150849
|
+
created_at INTEGER NOT NULL,
|
|
150850
|
+
UNIQUE(compartment_id, window_index)
|
|
150851
|
+
);
|
|
150852
|
+
CREATE INDEX IF NOT EXISTS idx_cce_session ON compartment_chunk_embeddings(session_id);
|
|
150853
|
+
CREATE INDEX IF NOT EXISTS idx_cce_project_model ON compartment_chunk_embeddings(project_path, model_id);
|
|
150854
|
+
|
|
150855
|
+
CREATE TABLE IF NOT EXISTS session_projects (
|
|
150856
|
+
session_id TEXT NOT NULL,
|
|
150857
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
150858
|
+
project_path TEXT NOT NULL,
|
|
150859
|
+
updated_at INTEGER NOT NULL,
|
|
150860
|
+
PRIMARY KEY(session_id, harness)
|
|
150861
|
+
);
|
|
150862
|
+
CREATE INDEX IF NOT EXISTS idx_session_projects_project
|
|
150863
|
+
ON session_projects(project_path);
|
|
150864
|
+
|
|
150839
150865
|
CREATE TABLE IF NOT EXISTS compartment_events (
|
|
150840
150866
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
150841
150867
|
session_id TEXT NOT NULL,
|
|
@@ -151021,6 +151047,25 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151021
151047
|
rekeyed_at INTEGER NOT NULL
|
|
151022
151048
|
);
|
|
151023
151049
|
|
|
151050
|
+
CREATE TABLE IF NOT EXISTS workspaces (
|
|
151051
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
151052
|
+
name TEXT NOT NULL UNIQUE,
|
|
151053
|
+
created_at INTEGER NOT NULL,
|
|
151054
|
+
updated_at INTEGER NOT NULL,
|
|
151055
|
+
share_categories TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'
|
|
151056
|
+
);
|
|
151057
|
+
|
|
151058
|
+
CREATE TABLE IF NOT EXISTS workspace_members (
|
|
151059
|
+
workspace_id INTEGER NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
151060
|
+
project_path TEXT NOT NULL,
|
|
151061
|
+
display_name TEXT NOT NULL,
|
|
151062
|
+
display_path TEXT NOT NULL,
|
|
151063
|
+
added_at INTEGER NOT NULL,
|
|
151064
|
+
PRIMARY KEY (workspace_id, project_path)
|
|
151065
|
+
);
|
|
151066
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_unique ON workspace_members(project_path);
|
|
151067
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_name ON workspace_members(workspace_id, display_name);
|
|
151068
|
+
|
|
151024
151069
|
CREATE TABLE IF NOT EXISTS v22_backfill_failures (
|
|
151025
151070
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
151026
151071
|
table_name TEXT NOT NULL,
|
|
@@ -151132,6 +151177,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151132
151177
|
deferred_execute_state TEXT,
|
|
151133
151178
|
cached_m0_bytes BLOB,
|
|
151134
151179
|
cached_m0_project_memory_epoch INTEGER,
|
|
151180
|
+
cached_m0_workspace_fingerprint TEXT,
|
|
151135
151181
|
cached_m0_project_user_profile_version INTEGER,
|
|
151136
151182
|
cached_m0_max_compartment_seq INTEGER,
|
|
151137
151183
|
cached_m0_max_memory_id INTEGER,
|
|
@@ -151290,6 +151336,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151290
151336
|
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
151291
151337
|
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
151292
151338
|
ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
|
|
151339
|
+
ensureColumn(db, "session_meta", "processed_image_stripped_ids", "TEXT DEFAULT ''");
|
|
151293
151340
|
ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
|
|
151294
151341
|
ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
|
|
151295
151342
|
ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
|
|
@@ -151343,6 +151390,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151343
151390
|
ensureColumn(db, "memories", "importance", "INTEGER");
|
|
151344
151391
|
ensureColumn(db, "session_meta", "cached_m0_bytes", "BLOB");
|
|
151345
151392
|
ensureColumn(db, "session_meta", "cached_m0_project_memory_epoch", "INTEGER");
|
|
151393
|
+
ensureColumn(db, "session_meta", "cached_m0_workspace_fingerprint", "TEXT");
|
|
151346
151394
|
ensureColumn(db, "session_meta", "cached_m0_project_user_profile_version", "INTEGER");
|
|
151347
151395
|
ensureColumn(db, "session_meta", "cached_m0_max_compartment_seq", "INTEGER");
|
|
151348
151396
|
ensureColumn(db, "session_meta", "cached_m0_max_memory_id", "INTEGER");
|
|
@@ -151374,6 +151422,15 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151374
151422
|
project_user_profile_version INTEGER NOT NULL DEFAULT 0,
|
|
151375
151423
|
updated_at INTEGER NOT NULL DEFAULT 0
|
|
151376
151424
|
);
|
|
151425
|
+
CREATE TABLE IF NOT EXISTS session_projects (
|
|
151426
|
+
session_id TEXT NOT NULL,
|
|
151427
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
151428
|
+
project_path TEXT NOT NULL,
|
|
151429
|
+
updated_at INTEGER NOT NULL,
|
|
151430
|
+
PRIMARY KEY(session_id, harness)
|
|
151431
|
+
);
|
|
151432
|
+
CREATE INDEX IF NOT EXISTS idx_session_projects_project
|
|
151433
|
+
ON session_projects(project_path);
|
|
151377
151434
|
CREATE TABLE IF NOT EXISTS m0_mutation_log (
|
|
151378
151435
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
151379
151436
|
session_id TEXT NOT NULL,
|
|
@@ -151401,6 +151458,23 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151401
151458
|
new_project_path TEXT NOT NULL,
|
|
151402
151459
|
rekeyed_at INTEGER NOT NULL
|
|
151403
151460
|
);
|
|
151461
|
+
CREATE TABLE IF NOT EXISTS workspaces (
|
|
151462
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
151463
|
+
name TEXT NOT NULL UNIQUE,
|
|
151464
|
+
created_at INTEGER NOT NULL,
|
|
151465
|
+
updated_at INTEGER NOT NULL,
|
|
151466
|
+
share_categories TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'
|
|
151467
|
+
);
|
|
151468
|
+
CREATE TABLE IF NOT EXISTS workspace_members (
|
|
151469
|
+
workspace_id INTEGER NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
151470
|
+
project_path TEXT NOT NULL,
|
|
151471
|
+
display_name TEXT NOT NULL,
|
|
151472
|
+
display_path TEXT NOT NULL,
|
|
151473
|
+
added_at INTEGER NOT NULL,
|
|
151474
|
+
PRIMARY KEY (workspace_id, project_path)
|
|
151475
|
+
);
|
|
151476
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_unique ON workspace_members(project_path);
|
|
151477
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_name ON workspace_members(workspace_id, display_name);
|
|
151404
151478
|
CREATE TABLE IF NOT EXISTS v22_backfill_failures (
|
|
151405
151479
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
151406
151480
|
table_name TEXT NOT NULL,
|
|
@@ -151422,6 +151496,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151422
151496
|
ensureColumn(db, "recomp_compartments", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
151423
151497
|
ensureColumn(db, "recomp_facts", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
151424
151498
|
ensureColumn(db, "message_history_index", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
151499
|
+
ensureColumn(db, "workspaces", "share_categories", `TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'`);
|
|
151425
151500
|
}
|
|
151426
151501
|
function healAllNullColumns(db) {
|
|
151427
151502
|
healNullTextColumns(db);
|
|
@@ -151459,6 +151534,7 @@ function healNullTextColumns(db) {
|
|
|
151459
151534
|
["system_prompt_hash", ""],
|
|
151460
151535
|
["stripped_placeholder_ids", ""],
|
|
151461
151536
|
["stale_reduce_stripped_ids", ""],
|
|
151537
|
+
["processed_image_stripped_ids", ""],
|
|
151462
151538
|
["memory_block_cache", ""],
|
|
151463
151539
|
["memory_block_ids", ""],
|
|
151464
151540
|
["compaction_marker_state", ""],
|
|
@@ -151503,7 +151579,7 @@ function healNullIntegerColumns(db) {
|
|
|
151503
151579
|
}
|
|
151504
151580
|
}
|
|
151505
151581
|
function ensureColumn(db, table, column, definition) {
|
|
151506
|
-
if (!/^[a-z][a-z0-9_]*$/.test(table) || !/^[a-z][a-z0-9_]*$/.test(column) || !/^[A-Z0-9_'(),[\]\s]+$/i.test(definition)) {
|
|
151582
|
+
if (!/^[a-z][a-z0-9_]*$/.test(table) || !/^[a-z][a-z0-9_]*$/.test(column) || !/^[A-Z0-9_"'(),[\]\s]+$/i.test(definition)) {
|
|
151507
151583
|
throw new Error(`Unsafe schema identifier: ${table}.${column} ${definition}`);
|
|
151508
151584
|
}
|
|
151509
151585
|
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
@@ -151589,7 +151665,7 @@ function getDatabasePersistenceError(db) {
|
|
|
151589
151665
|
return null;
|
|
151590
151666
|
return persistenceErrorByDatabase.get(db) ?? null;
|
|
151591
151667
|
}
|
|
151592
|
-
var databases, persistenceByDatabase, persistenceErrorByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION =
|
|
151668
|
+
var databases, persistenceByDatabase, persistenceErrorByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 36, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS = 120000;
|
|
151593
151669
|
var init_storage_db = __esm(async () => {
|
|
151594
151670
|
init_data_path();
|
|
151595
151671
|
init_logger();
|
|
@@ -151609,10 +151685,302 @@ var init_storage_db = __esm(async () => {
|
|
|
151609
151685
|
};
|
|
151610
151686
|
});
|
|
151611
151687
|
|
|
151688
|
+
// src/features/magic-context/memory/constants.ts
|
|
151689
|
+
var V2_MEMORY_CATEGORIES, PROMOTABLE_CATEGORIES, CATEGORY_PRIORITY, MEMORY_CATEGORY_ORDER_UNKNOWN = 99, MEMORY_CATEGORY_ORDER_PRIORITY, MEMORY_CATEGORY_ORDER_SQL, CATEGORY_DEFAULT_TTL;
|
|
151690
|
+
var init_constants = __esm(() => {
|
|
151691
|
+
V2_MEMORY_CATEGORIES = [
|
|
151692
|
+
"PROJECT_RULES",
|
|
151693
|
+
"ARCHITECTURE",
|
|
151694
|
+
"CONSTRAINTS",
|
|
151695
|
+
"CONFIG_VALUES",
|
|
151696
|
+
"NAMING"
|
|
151697
|
+
];
|
|
151698
|
+
PROMOTABLE_CATEGORIES = [
|
|
151699
|
+
"PROJECT_RULES",
|
|
151700
|
+
"ARCHITECTURE",
|
|
151701
|
+
"CONSTRAINTS",
|
|
151702
|
+
"CONFIG_VALUES",
|
|
151703
|
+
"NAMING",
|
|
151704
|
+
"ARCHITECTURE_DECISIONS",
|
|
151705
|
+
"CONFIG_DEFAULTS",
|
|
151706
|
+
"USER_PREFERENCES",
|
|
151707
|
+
"USER_DIRECTIVES",
|
|
151708
|
+
"ENVIRONMENT",
|
|
151709
|
+
"WORKFLOW_RULES",
|
|
151710
|
+
"KNOWN_ISSUES"
|
|
151711
|
+
];
|
|
151712
|
+
CATEGORY_PRIORITY = [
|
|
151713
|
+
"PROJECT_RULES",
|
|
151714
|
+
"ARCHITECTURE",
|
|
151715
|
+
"CONSTRAINTS",
|
|
151716
|
+
"CONFIG_VALUES",
|
|
151717
|
+
"NAMING",
|
|
151718
|
+
"USER_DIRECTIVES",
|
|
151719
|
+
"USER_PREFERENCES",
|
|
151720
|
+
"CONFIG_DEFAULTS",
|
|
151721
|
+
"ARCHITECTURE_DECISIONS",
|
|
151722
|
+
"ENVIRONMENT",
|
|
151723
|
+
"WORKFLOW_RULES",
|
|
151724
|
+
"KNOWN_ISSUES"
|
|
151725
|
+
];
|
|
151726
|
+
MEMORY_CATEGORY_ORDER_PRIORITY = CATEGORY_PRIORITY.reduce((acc, category, index) => {
|
|
151727
|
+
acc[category] = index;
|
|
151728
|
+
return acc;
|
|
151729
|
+
}, {});
|
|
151730
|
+
MEMORY_CATEGORY_ORDER_SQL = `CASE category ${CATEGORY_PRIORITY.map((category, index) => `WHEN '${category}' THEN ${index}`).join(" ")} ELSE ${MEMORY_CATEGORY_ORDER_UNKNOWN} END`;
|
|
151731
|
+
CATEGORY_DEFAULT_TTL = {
|
|
151732
|
+
WORKFLOW_RULES: 90 * 24 * 60 * 60 * 1000,
|
|
151733
|
+
KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
|
|
151734
|
+
};
|
|
151735
|
+
});
|
|
151736
|
+
|
|
151737
|
+
// src/features/magic-context/project-identity.ts
|
|
151738
|
+
var init_project_identity2 = __esm(() => {
|
|
151739
|
+
init_project_identity();
|
|
151740
|
+
});
|
|
151741
|
+
|
|
151742
|
+
// src/features/magic-context/workspaces.ts
|
|
151743
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
151744
|
+
function tableExists(db, tableName) {
|
|
151745
|
+
const row = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name = ? LIMIT 1").get(tableName);
|
|
151746
|
+
return Boolean(row);
|
|
151747
|
+
}
|
|
151748
|
+
function columnExists(db, tableName, columnName) {
|
|
151749
|
+
const rows = db.prepare(`PRAGMA table_info(${tableName})`).all();
|
|
151750
|
+
return rows.some((row) => row.name === columnName);
|
|
151751
|
+
}
|
|
151752
|
+
function uniqueSorted(values) {
|
|
151753
|
+
return [...new Set(values)].sort((left, right) => left.localeCompare(right));
|
|
151754
|
+
}
|
|
151755
|
+
function placeholders(values) {
|
|
151756
|
+
return values.map(() => "?").join(", ");
|
|
151757
|
+
}
|
|
151758
|
+
function normalizeShareCategories(raw) {
|
|
151759
|
+
if (raw === null || raw === undefined)
|
|
151760
|
+
return null;
|
|
151761
|
+
if (typeof raw !== "string")
|
|
151762
|
+
return null;
|
|
151763
|
+
let parsed;
|
|
151764
|
+
try {
|
|
151765
|
+
parsed = JSON.parse(raw);
|
|
151766
|
+
} catch {
|
|
151767
|
+
return null;
|
|
151768
|
+
}
|
|
151769
|
+
if (!Array.isArray(parsed))
|
|
151770
|
+
return null;
|
|
151771
|
+
const categories = [];
|
|
151772
|
+
for (const value of parsed) {
|
|
151773
|
+
if (typeof value !== "string" || !VALID_SHARE_CATEGORIES.has(value)) {
|
|
151774
|
+
return null;
|
|
151775
|
+
}
|
|
151776
|
+
if (!categories.includes(value))
|
|
151777
|
+
categories.push(value);
|
|
151778
|
+
}
|
|
151779
|
+
return categories.sort((left, right) => left.localeCompare(right));
|
|
151780
|
+
}
|
|
151781
|
+
function selectWorkspaceShareCategories(db, identities) {
|
|
151782
|
+
const candidates = uniqueSorted(identities.filter((identity) => identity.length > 0));
|
|
151783
|
+
if (candidates.length === 0 || !tableExists(db, "workspace_members") || !tableExists(db, "workspaces") || !columnExists(db, "workspaces", "share_categories")) {
|
|
151784
|
+
return null;
|
|
151785
|
+
}
|
|
151786
|
+
const row = db.prepare(`SELECT workspace.share_categories AS shareCategories
|
|
151787
|
+
FROM workspace_members AS member
|
|
151788
|
+
JOIN workspaces AS workspace ON workspace.id = member.workspace_id
|
|
151789
|
+
WHERE member.project_path IN (${placeholders(candidates)})
|
|
151790
|
+
ORDER BY workspace.id ASC
|
|
151791
|
+
LIMIT 1`).get(...candidates);
|
|
151792
|
+
return normalizeShareCategories(row?.shareCategories ?? null);
|
|
151793
|
+
}
|
|
151794
|
+
function resolveWorkspaceShareCategories(db, projectIdentity) {
|
|
151795
|
+
return selectWorkspaceShareCategories(db, [projectIdentity]);
|
|
151796
|
+
}
|
|
151797
|
+
function resolveWorkspaceIdentitySet(db, projectIdentity) {
|
|
151798
|
+
if (!tableExists(db, "workspace_members")) {
|
|
151799
|
+
return { identities: [projectIdentity], namesByIdentity: new Map };
|
|
151800
|
+
}
|
|
151801
|
+
const rows = db.prepare(`SELECT member.project_path AS identity, member.display_name AS displayName
|
|
151802
|
+
FROM workspace_members AS anchor
|
|
151803
|
+
JOIN workspace_members AS member ON member.workspace_id = anchor.workspace_id
|
|
151804
|
+
WHERE anchor.project_path = ?
|
|
151805
|
+
ORDER BY member.display_name ASC, member.project_path ASC`).all(projectIdentity);
|
|
151806
|
+
if (rows.length === 0) {
|
|
151807
|
+
return { identities: [projectIdentity], namesByIdentity: new Map };
|
|
151808
|
+
}
|
|
151809
|
+
const namesByIdentity = new Map;
|
|
151810
|
+
const identities = [];
|
|
151811
|
+
for (const row of rows) {
|
|
151812
|
+
if (typeof row.identity !== "string" || row.identity.length === 0)
|
|
151813
|
+
continue;
|
|
151814
|
+
if (identities.includes(row.identity))
|
|
151815
|
+
continue;
|
|
151816
|
+
identities.push(row.identity);
|
|
151817
|
+
if (typeof row.displayName === "string" && row.displayName.length > 0) {
|
|
151818
|
+
namesByIdentity.set(row.identity, row.displayName);
|
|
151819
|
+
}
|
|
151820
|
+
}
|
|
151821
|
+
return identities.length > 0 ? { identities, namesByIdentity } : { identities: [projectIdentity], namesByIdentity: new Map };
|
|
151822
|
+
}
|
|
151823
|
+
function expandWorkspaceIdentitySetWithAliases(db, identities) {
|
|
151824
|
+
const canonical = uniqueSorted(identities.filter((identity) => identity.length > 0));
|
|
151825
|
+
const expanded = new Set(canonical);
|
|
151826
|
+
const canonicalIdentityByStoredPath = new Map;
|
|
151827
|
+
for (const identity of canonical) {
|
|
151828
|
+
canonicalIdentityByStoredPath.set(identity, identity);
|
|
151829
|
+
}
|
|
151830
|
+
if (canonical.length === 0 || !tableExists(db, "v22_identity_rekey_map")) {
|
|
151831
|
+
return { expandedIdentities: [...expanded], canonicalIdentityByStoredPath };
|
|
151832
|
+
}
|
|
151833
|
+
const rows = db.prepare(`SELECT old_project_path AS oldProjectPath, new_project_path AS newProjectPath
|
|
151834
|
+
FROM v22_identity_rekey_map
|
|
151835
|
+
WHERE new_project_path IN (${placeholders(canonical)})
|
|
151836
|
+
ORDER BY old_project_path ASC`).all(...canonical);
|
|
151837
|
+
for (const row of rows) {
|
|
151838
|
+
if (typeof row.oldProjectPath !== "string" || typeof row.newProjectPath !== "string") {
|
|
151839
|
+
continue;
|
|
151840
|
+
}
|
|
151841
|
+
if (!canonicalIdentityByStoredPath.has(row.newProjectPath))
|
|
151842
|
+
continue;
|
|
151843
|
+
expanded.add(row.oldProjectPath);
|
|
151844
|
+
canonicalIdentityByStoredPath.set(row.oldProjectPath, row.newProjectPath);
|
|
151845
|
+
}
|
|
151846
|
+
return { expandedIdentities: [...expanded], canonicalIdentityByStoredPath };
|
|
151847
|
+
}
|
|
151848
|
+
function resolveStoredPathWorkspaceIdentity(storedProjectPath, memberIdentities, canonicalIdentityByStoredPath) {
|
|
151849
|
+
const direct = canonicalIdentityByStoredPath.get(storedProjectPath);
|
|
151850
|
+
if (direct)
|
|
151851
|
+
return direct;
|
|
151852
|
+
const normalized = normalizeStoredProjectPath(storedProjectPath);
|
|
151853
|
+
const normalizedDirect = canonicalIdentityByStoredPath.get(normalized);
|
|
151854
|
+
if (normalizedDirect)
|
|
151855
|
+
return normalizedDirect;
|
|
151856
|
+
if (memberIdentities.includes(normalized))
|
|
151857
|
+
return normalized;
|
|
151858
|
+
for (const identity of memberIdentities) {
|
|
151859
|
+
if (storedPathBelongsToIdentity(storedProjectPath, identity)) {
|
|
151860
|
+
return identity;
|
|
151861
|
+
}
|
|
151862
|
+
}
|
|
151863
|
+
return null;
|
|
151864
|
+
}
|
|
151865
|
+
function storedPathBelongsToWorkspace(storedProjectPath, memberIdentities, expandedIdentities, canonicalIdentityByStoredPath) {
|
|
151866
|
+
if (expandedIdentities.includes(storedProjectPath))
|
|
151867
|
+
return true;
|
|
151868
|
+
return resolveStoredPathWorkspaceIdentity(storedProjectPath, memberIdentities, canonicalIdentityByStoredPath) !== null;
|
|
151869
|
+
}
|
|
151870
|
+
function sourceNameForMemory(storedProjectPath, ownIdentity, memberIdentities, namesByIdentity, canonicalIdentityByStoredPath) {
|
|
151871
|
+
const canonicalIdentity = resolveStoredPathWorkspaceIdentity(storedProjectPath, memberIdentities, canonicalIdentityByStoredPath);
|
|
151872
|
+
if (!canonicalIdentity || canonicalIdentity === ownIdentity)
|
|
151873
|
+
return;
|
|
151874
|
+
return namesByIdentity.get(canonicalIdentity);
|
|
151875
|
+
}
|
|
151876
|
+
function getEpochMap(db, identities) {
|
|
151877
|
+
if (identities.length === 0)
|
|
151878
|
+
return new Map;
|
|
151879
|
+
const rows = db.prepare(`SELECT project_path AS projectPath, project_memory_epoch AS epoch
|
|
151880
|
+
FROM project_state
|
|
151881
|
+
WHERE project_path IN (${placeholders(identities)})`).all(...identities);
|
|
151882
|
+
const epochs = new Map;
|
|
151883
|
+
for (const row of rows) {
|
|
151884
|
+
if (typeof row.projectPath !== "string" || typeof row.epoch !== "number")
|
|
151885
|
+
continue;
|
|
151886
|
+
epochs.set(row.projectPath, row.epoch);
|
|
151887
|
+
}
|
|
151888
|
+
return epochs;
|
|
151889
|
+
}
|
|
151890
|
+
function computeWorkspaceEpochFingerprint(db, identities) {
|
|
151891
|
+
const canonical = uniqueSorted(identities.filter((identity) => identity.length > 0));
|
|
151892
|
+
const epochs = getEpochMap(db, canonical);
|
|
151893
|
+
const shareCategories = selectWorkspaceShareCategories(db, canonical);
|
|
151894
|
+
const hash2 = createHash4("sha256");
|
|
151895
|
+
hash2.update("share_categories", "utf8");
|
|
151896
|
+
hash2.update("\x00");
|
|
151897
|
+
hash2.update(shareCategories === null ? "ALL" : JSON.stringify(shareCategories), "utf8");
|
|
151898
|
+
hash2.update(`
|
|
151899
|
+
`);
|
|
151900
|
+
for (const identity of canonical) {
|
|
151901
|
+
hash2.update(identity, "utf8");
|
|
151902
|
+
hash2.update("\x00");
|
|
151903
|
+
hash2.update(String(epochs.get(identity) ?? 0), "utf8");
|
|
151904
|
+
hash2.update(`
|
|
151905
|
+
`);
|
|
151906
|
+
}
|
|
151907
|
+
return hash2.digest("hex");
|
|
151908
|
+
}
|
|
151909
|
+
function isInTransaction(db) {
|
|
151910
|
+
const candidate = db;
|
|
151911
|
+
return candidate.inTransaction === true || candidate.isTransaction === true;
|
|
151912
|
+
}
|
|
151913
|
+
function workspaceMembersForIdentity(db, identity) {
|
|
151914
|
+
if (!tableExists(db, "workspace_members"))
|
|
151915
|
+
return [identity];
|
|
151916
|
+
const rows = db.prepare(`SELECT member.project_path AS identity
|
|
151917
|
+
FROM workspace_members AS anchor
|
|
151918
|
+
JOIN workspace_members AS member ON member.workspace_id = anchor.workspace_id
|
|
151919
|
+
WHERE anchor.project_path = ?
|
|
151920
|
+
ORDER BY member.project_path ASC`).all(identity);
|
|
151921
|
+
const identities = rows.map((row) => typeof row.identity === "string" ? row.identity : "").filter((value) => value.length > 0);
|
|
151922
|
+
return identities.length > 0 ? uniqueSorted(identities) : [identity];
|
|
151923
|
+
}
|
|
151924
|
+
function bumpEpochRows(db, identities, now) {
|
|
151925
|
+
const stmt = db.prepare(`INSERT INTO project_state
|
|
151926
|
+
(project_path, project_memory_epoch, project_user_profile_version, updated_at)
|
|
151927
|
+
VALUES (?, 1, 0, ?)
|
|
151928
|
+
ON CONFLICT(project_path) DO UPDATE SET
|
|
151929
|
+
project_memory_epoch = project_memory_epoch + 1,
|
|
151930
|
+
updated_at = excluded.updated_at`);
|
|
151931
|
+
for (const identity of uniqueSorted(identities)) {
|
|
151932
|
+
stmt.run(identity, now);
|
|
151933
|
+
}
|
|
151934
|
+
}
|
|
151935
|
+
function bumpEpochsForWorkspaceMembers(db, identity, now = Date.now()) {
|
|
151936
|
+
const run = () => bumpEpochRows(db, workspaceMembersForIdentity(db, identity), now);
|
|
151937
|
+
if (isInTransaction(db)) {
|
|
151938
|
+
run();
|
|
151939
|
+
return;
|
|
151940
|
+
}
|
|
151941
|
+
db.exec("BEGIN IMMEDIATE");
|
|
151942
|
+
try {
|
|
151943
|
+
run();
|
|
151944
|
+
db.exec("COMMIT");
|
|
151945
|
+
} catch (error51) {
|
|
151946
|
+
try {
|
|
151947
|
+
db.exec("ROLLBACK");
|
|
151948
|
+
} catch {}
|
|
151949
|
+
throw error51;
|
|
151950
|
+
}
|
|
151951
|
+
}
|
|
151952
|
+
function bumpEpochsForWorkspaceMemberSet(db, identities, now = Date.now()) {
|
|
151953
|
+
const run = () => bumpEpochRows(db, identities, now);
|
|
151954
|
+
if (isInTransaction(db)) {
|
|
151955
|
+
run();
|
|
151956
|
+
return;
|
|
151957
|
+
}
|
|
151958
|
+
db.exec("BEGIN IMMEDIATE");
|
|
151959
|
+
try {
|
|
151960
|
+
run();
|
|
151961
|
+
db.exec("COMMIT");
|
|
151962
|
+
} catch (error51) {
|
|
151963
|
+
try {
|
|
151964
|
+
db.exec("ROLLBACK");
|
|
151965
|
+
} catch {}
|
|
151966
|
+
throw error51;
|
|
151967
|
+
}
|
|
151968
|
+
}
|
|
151969
|
+
var VALID_SHARE_CATEGORIES;
|
|
151970
|
+
var init_workspaces = __esm(() => {
|
|
151971
|
+
init_constants();
|
|
151972
|
+
init_project_identity2();
|
|
151973
|
+
VALID_SHARE_CATEGORIES = new Set(V2_MEMORY_CATEGORIES);
|
|
151974
|
+
});
|
|
151975
|
+
|
|
151612
151976
|
// src/features/magic-context/migrations.ts
|
|
151613
|
-
function
|
|
151977
|
+
function tableExists2(db, name2) {
|
|
151614
151978
|
return Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(name2));
|
|
151615
151979
|
}
|
|
151980
|
+
function columnExists2(db, table, column) {
|
|
151981
|
+
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
151982
|
+
return rows.some((row) => row.name === column);
|
|
151983
|
+
}
|
|
151616
151984
|
function ensureMigrationsTable(db) {
|
|
151617
151985
|
db.exec(`
|
|
151618
151986
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
@@ -151681,6 +152049,7 @@ function runMigrations(db) {
|
|
|
151681
152049
|
var MIGRATIONS, LATEST_MIGRATION_VERSION;
|
|
151682
152050
|
var init_migrations = __esm(async () => {
|
|
151683
152051
|
init_logger();
|
|
152052
|
+
init_workspaces();
|
|
151684
152053
|
await init_storage_db();
|
|
151685
152054
|
MIGRATIONS = [
|
|
151686
152055
|
{
|
|
@@ -152140,9 +152509,9 @@ var init_migrations = __esm(async () => {
|
|
|
152140
152509
|
version: 22,
|
|
152141
152510
|
description: "v2.0 cache architecture schema foundation",
|
|
152142
152511
|
up: (db) => {
|
|
152143
|
-
const hasSessionMetaTable =
|
|
152144
|
-
const hasCompartmentsTable =
|
|
152145
|
-
const hasMemoriesTable =
|
|
152512
|
+
const hasSessionMetaTable = tableExists2(db, "session_meta");
|
|
152513
|
+
const hasCompartmentsTable = tableExists2(db, "compartments");
|
|
152514
|
+
const hasMemoriesTable = tableExists2(db, "memories");
|
|
152146
152515
|
if (hasSessionMetaTable) {
|
|
152147
152516
|
ensureColumn(db, "session_meta", "cached_m0_bytes", "BLOB");
|
|
152148
152517
|
ensureColumn(db, "session_meta", "cached_m0_project_memory_epoch", "INTEGER");
|
|
@@ -152167,7 +152536,7 @@ var init_migrations = __esm(async () => {
|
|
|
152167
152536
|
ensureColumn(db, "compartments", "p1_embedding_model_id", "TEXT");
|
|
152168
152537
|
ensureColumn(db, "compartments", "legacy", "INTEGER NOT NULL DEFAULT 0");
|
|
152169
152538
|
}
|
|
152170
|
-
const hasRecompCompartmentsTable =
|
|
152539
|
+
const hasRecompCompartmentsTable = tableExists2(db, "recomp_compartments");
|
|
152171
152540
|
if (hasRecompCompartmentsTable) {
|
|
152172
152541
|
ensureColumn(db, "recomp_compartments", "p1", "TEXT");
|
|
152173
152542
|
ensureColumn(db, "recomp_compartments", "p2", "TEXT");
|
|
@@ -152478,13 +152847,163 @@ var init_migrations = __esm(async () => {
|
|
|
152478
152847
|
db.prepare("UPDATE session_meta SET force_emergency_bypass_used = 0 WHERE force_emergency_bypass_used IS NULL").run();
|
|
152479
152848
|
db.prepare("UPDATE session_meta SET last_usage_context_limit = 0 WHERE last_usage_context_limit IS NULL").run();
|
|
152480
152849
|
}
|
|
152850
|
+
},
|
|
152851
|
+
{
|
|
152852
|
+
version: 33,
|
|
152853
|
+
description: "Compartment chunk embeddings for semantic message-history search",
|
|
152854
|
+
up: (db) => {
|
|
152855
|
+
db.exec(`
|
|
152856
|
+
CREATE TABLE IF NOT EXISTS compartment_chunk_embeddings (
|
|
152857
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
152858
|
+
compartment_id INTEGER NOT NULL REFERENCES compartments(id) ON DELETE CASCADE,
|
|
152859
|
+
session_id TEXT NOT NULL,
|
|
152860
|
+
project_path TEXT NOT NULL,
|
|
152861
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
152862
|
+
window_index INTEGER NOT NULL DEFAULT 0,
|
|
152863
|
+
start_ordinal INTEGER NOT NULL,
|
|
152864
|
+
end_ordinal INTEGER NOT NULL,
|
|
152865
|
+
chunk_hash TEXT NOT NULL,
|
|
152866
|
+
model_id TEXT NOT NULL,
|
|
152867
|
+
dims INTEGER NOT NULL,
|
|
152868
|
+
vector BLOB NOT NULL,
|
|
152869
|
+
created_at INTEGER NOT NULL,
|
|
152870
|
+
UNIQUE(compartment_id, window_index)
|
|
152871
|
+
);
|
|
152872
|
+
CREATE INDEX IF NOT EXISTS idx_cce_session
|
|
152873
|
+
ON compartment_chunk_embeddings(session_id);
|
|
152874
|
+
CREATE INDEX IF NOT EXISTS idx_cce_project_model
|
|
152875
|
+
ON compartment_chunk_embeddings(project_path, model_id);
|
|
152876
|
+
`);
|
|
152877
|
+
}
|
|
152878
|
+
},
|
|
152879
|
+
{
|
|
152880
|
+
version: 34,
|
|
152881
|
+
description: "workspace tables and m[0] workspace fingerprint cache reset",
|
|
152882
|
+
up: (db) => {
|
|
152883
|
+
db.exec(`
|
|
152884
|
+
CREATE TABLE IF NOT EXISTS workspaces (
|
|
152885
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
152886
|
+
name TEXT NOT NULL UNIQUE,
|
|
152887
|
+
created_at INTEGER NOT NULL,
|
|
152888
|
+
updated_at INTEGER NOT NULL
|
|
152889
|
+
);
|
|
152890
|
+
CREATE TABLE IF NOT EXISTS workspace_members (
|
|
152891
|
+
workspace_id INTEGER NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
152892
|
+
project_path TEXT NOT NULL,
|
|
152893
|
+
display_name TEXT NOT NULL,
|
|
152894
|
+
display_path TEXT NOT NULL,
|
|
152895
|
+
added_at INTEGER NOT NULL,
|
|
152896
|
+
PRIMARY KEY (workspace_id, project_path)
|
|
152897
|
+
);
|
|
152898
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_unique
|
|
152899
|
+
ON workspace_members(project_path);
|
|
152900
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_member_name
|
|
152901
|
+
ON workspace_members(workspace_id, display_name);
|
|
152902
|
+
`);
|
|
152903
|
+
const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta' LIMIT 1").get();
|
|
152904
|
+
if (!hasSessionMeta)
|
|
152905
|
+
return;
|
|
152906
|
+
ensureColumn(db, "session_meta", "cached_m0_workspace_fingerprint", "TEXT");
|
|
152907
|
+
const columns = new Set(db.prepare("PRAGMA table_info(session_meta)").all().map((column) => column.name));
|
|
152908
|
+
const clears = [
|
|
152909
|
+
["cached_m0_bytes", null],
|
|
152910
|
+
["cached_m1_bytes", null],
|
|
152911
|
+
["cached_m0_project_memory_epoch", null],
|
|
152912
|
+
["cached_m0_workspace_fingerprint", null],
|
|
152913
|
+
["cached_m0_project_user_profile_version", null],
|
|
152914
|
+
["cached_m0_max_compartment_seq", null],
|
|
152915
|
+
["cached_m0_max_memory_id", null],
|
|
152916
|
+
["cached_m0_max_mutation_id", null],
|
|
152917
|
+
["cached_m0_max_memory_mutation_id", null],
|
|
152918
|
+
["cached_m0_project_docs_hash", null],
|
|
152919
|
+
["cached_m0_materialized_at", null],
|
|
152920
|
+
["cached_m0_session_facts_version", null],
|
|
152921
|
+
["cached_m0_upgrade_state", null],
|
|
152922
|
+
["cached_m0_system_hash", null],
|
|
152923
|
+
["cached_m0_tool_set_hash", null],
|
|
152924
|
+
["cached_m0_model_key", null],
|
|
152925
|
+
["cached_m0_last_baseline_end_message_id", null],
|
|
152926
|
+
["memory_block_cache", ""],
|
|
152927
|
+
["memory_block_ids", ""],
|
|
152928
|
+
["memory_block_count", 0]
|
|
152929
|
+
];
|
|
152930
|
+
const setClauses = [];
|
|
152931
|
+
const values = [];
|
|
152932
|
+
for (const [column, value] of clears) {
|
|
152933
|
+
if (!columns.has(column))
|
|
152934
|
+
continue;
|
|
152935
|
+
setClauses.push(`${column} = ?`);
|
|
152936
|
+
values.push(value);
|
|
152937
|
+
}
|
|
152938
|
+
if (setClauses.length > 0) {
|
|
152939
|
+
db.prepare(`UPDATE session_meta SET ${setClauses.join(", ")}`).run(...values);
|
|
152940
|
+
}
|
|
152941
|
+
}
|
|
152942
|
+
},
|
|
152943
|
+
{
|
|
152944
|
+
version: 35,
|
|
152945
|
+
description: "workspace per-category share defaults and epoch refresh",
|
|
152946
|
+
up: (db) => {
|
|
152947
|
+
db.exec(`
|
|
152948
|
+
CREATE TABLE IF NOT EXISTS workspaces (
|
|
152949
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
152950
|
+
name TEXT NOT NULL UNIQUE,
|
|
152951
|
+
created_at INTEGER NOT NULL,
|
|
152952
|
+
updated_at INTEGER NOT NULL,
|
|
152953
|
+
share_categories TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'
|
|
152954
|
+
);
|
|
152955
|
+
`);
|
|
152956
|
+
if (!columnExists2(db, "workspaces", "share_categories")) {
|
|
152957
|
+
db.exec(`ALTER TABLE workspaces ADD COLUMN share_categories TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'`);
|
|
152958
|
+
}
|
|
152959
|
+
db.prepare(`UPDATE workspaces
|
|
152960
|
+
SET share_categories = '["CONSTRAINTS"]'
|
|
152961
|
+
WHERE share_categories IS NULL OR share_categories = ''`).run();
|
|
152962
|
+
if (!tableExists2(db, "workspace_members"))
|
|
152963
|
+
return;
|
|
152964
|
+
const rows = db.prepare(`SELECT DISTINCT project_path AS identity
|
|
152965
|
+
FROM workspace_members
|
|
152966
|
+
WHERE project_path IS NOT NULL AND project_path <> ''
|
|
152967
|
+
ORDER BY project_path ASC`).all();
|
|
152968
|
+
const identities = rows.map((row) => typeof row.identity === "string" ? row.identity : "").filter((identity) => identity.length > 0);
|
|
152969
|
+
if (identities.length > 0) {
|
|
152970
|
+
bumpEpochsForWorkspaceMemberSet(db, identities, Date.now());
|
|
152971
|
+
}
|
|
152972
|
+
}
|
|
152973
|
+
},
|
|
152974
|
+
{
|
|
152975
|
+
version: 36,
|
|
152976
|
+
description: "session project ownership map for compartment chunk backfill scoping",
|
|
152977
|
+
up: (db) => {
|
|
152978
|
+
db.exec(`
|
|
152979
|
+
CREATE TABLE IF NOT EXISTS session_projects (
|
|
152980
|
+
session_id TEXT NOT NULL,
|
|
152981
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
152982
|
+
project_path TEXT NOT NULL,
|
|
152983
|
+
updated_at INTEGER NOT NULL,
|
|
152984
|
+
PRIMARY KEY(session_id, harness)
|
|
152985
|
+
);
|
|
152986
|
+
CREATE INDEX IF NOT EXISTS idx_session_projects_project
|
|
152987
|
+
ON session_projects(project_path);
|
|
152988
|
+
`);
|
|
152989
|
+
const hasChunkTable = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='compartment_chunk_embeddings'").get();
|
|
152990
|
+
if (hasChunkTable) {
|
|
152991
|
+
db.exec(`
|
|
152992
|
+
INSERT OR IGNORE INTO session_projects (session_id, harness, project_path, updated_at)
|
|
152993
|
+
SELECT session_id, harness, MIN(project_path), 0
|
|
152994
|
+
FROM compartment_chunk_embeddings
|
|
152995
|
+
GROUP BY session_id, harness
|
|
152996
|
+
HAVING COUNT(DISTINCT project_path) = 1;
|
|
152997
|
+
`);
|
|
152998
|
+
}
|
|
152999
|
+
}
|
|
152481
153000
|
}
|
|
152482
153001
|
];
|
|
152483
153002
|
LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
152484
153003
|
});
|
|
152485
153004
|
|
|
152486
153005
|
// src/features/magic-context/project-docs-hash.ts
|
|
152487
|
-
import { createHash as
|
|
153006
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
152488
153007
|
import { lstatSync, readFileSync as readFileSync5, statSync as statSync2 } from "node:fs";
|
|
152489
153008
|
import path4 from "node:path";
|
|
152490
153009
|
function canonicalizeDocContent(raw) {
|
|
@@ -152574,7 +153093,7 @@ function hashCanonicalPieces(hashPieces) {
|
|
|
152574
153093
|
if (hashPieces.length === 0) {
|
|
152575
153094
|
return "";
|
|
152576
153095
|
}
|
|
152577
|
-
return
|
|
153096
|
+
return createHash5("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
|
|
152578
153097
|
}
|
|
152579
153098
|
function readProjectDocsCanonical(projectDirectory) {
|
|
152580
153099
|
const canonicalDirectory = path4.resolve(projectDirectory);
|
|
@@ -152612,11 +153131,6 @@ var init_project_docs_hash = __esm(() => {
|
|
|
152612
153131
|
MAX_PROJECT_DOC_BYTES = 256 * 1024;
|
|
152613
153132
|
docsCache = new Map;
|
|
152614
153133
|
});
|
|
152615
|
-
|
|
152616
|
-
// src/features/magic-context/project-identity.ts
|
|
152617
|
-
var init_project_identity2 = __esm(() => {
|
|
152618
|
-
init_project_identity();
|
|
152619
|
-
});
|
|
152620
153134
|
// src/features/magic-context/storage-m0-mutation-log.ts
|
|
152621
153135
|
function assertMutationType(mutationType) {
|
|
152622
153136
|
if (!M0_MUTATION_TYPES.has(mutationType)) {
|
|
@@ -152701,18 +153215,13 @@ function getMemoryMutation(db, id) {
|
|
|
152701
153215
|
WHERE id = ?`).get(id);
|
|
152702
153216
|
return row ? toMemoryMutation(row) : null;
|
|
152703
153217
|
}
|
|
152704
|
-
function
|
|
152705
|
-
|
|
152706
|
-
|
|
152707
|
-
|
|
152708
|
-
|
|
152709
|
-
|
|
152710
|
-
|
|
152711
|
-
FROM memory_mutation_log
|
|
152712
|
-
WHERE project_path = ?
|
|
152713
|
-
AND id > ?
|
|
152714
|
-
AND target_memory_id IN (${placeholders})
|
|
152715
|
-
ORDER BY id ASC`).all(projectPath, afterId ?? 0, ...uniqueIds);
|
|
153218
|
+
function uniqueProjectPaths(projectPaths) {
|
|
153219
|
+
return [...new Set(projectPaths.filter((path5) => path5.length > 0))];
|
|
153220
|
+
}
|
|
153221
|
+
function placeholders2(values) {
|
|
153222
|
+
return values.map(() => "?").join(", ");
|
|
153223
|
+
}
|
|
153224
|
+
function coalesceMutations(rows) {
|
|
152716
153225
|
const chosenByTarget = new Map;
|
|
152717
153226
|
for (const dbRow of rows) {
|
|
152718
153227
|
const candidate = toMemoryMutation(dbRow);
|
|
@@ -152733,10 +153242,54 @@ function getMemoryMutationsForRender(db, projectPath, afterId, renderedMemoryIds
|
|
|
152733
153242
|
}
|
|
152734
153243
|
return [...chosenByTarget.values()].sort((left, right) => left.id - right.id);
|
|
152735
153244
|
}
|
|
153245
|
+
function getMemoryMutationsForRender(db, projectPath, afterId, renderedMemoryIds) {
|
|
153246
|
+
if (renderedMemoryIds.length === 0)
|
|
153247
|
+
return [];
|
|
153248
|
+
const uniqueIds = [...new Set(renderedMemoryIds)].sort((left, right) => left - right);
|
|
153249
|
+
const placeholders3 = uniqueIds.map(() => "?").join(", ");
|
|
153250
|
+
const rows = db.prepare(`SELECT id, project_path, mutation_type, target_memory_id,
|
|
153251
|
+
superseded_by_id, category, new_content, queued_at
|
|
153252
|
+
FROM memory_mutation_log
|
|
153253
|
+
WHERE project_path = ?
|
|
153254
|
+
AND id > ?
|
|
153255
|
+
AND target_memory_id IN (${placeholders3})
|
|
153256
|
+
ORDER BY id ASC`).all(projectPath, afterId ?? 0, ...uniqueIds);
|
|
153257
|
+
return coalesceMutations(rows);
|
|
153258
|
+
}
|
|
153259
|
+
function getMemoryMutationsForRenderByProjects(db, projectPaths, afterId, renderedMemoryIds) {
|
|
153260
|
+
if (renderedMemoryIds.length === 0)
|
|
153261
|
+
return [];
|
|
153262
|
+
const identities = uniqueProjectPaths(projectPaths);
|
|
153263
|
+
if (identities.length === 0)
|
|
153264
|
+
return [];
|
|
153265
|
+
if (identities.length === 1) {
|
|
153266
|
+
return getMemoryMutationsForRender(db, identities[0], afterId, renderedMemoryIds);
|
|
153267
|
+
}
|
|
153268
|
+
const uniqueIds = [...new Set(renderedMemoryIds)].sort((left, right) => left - right);
|
|
153269
|
+
const rows = db.prepare(`SELECT id, project_path, mutation_type, target_memory_id,
|
|
153270
|
+
superseded_by_id, category, new_content, queued_at
|
|
153271
|
+
FROM memory_mutation_log
|
|
153272
|
+
WHERE project_path IN (${placeholders2(identities)})
|
|
153273
|
+
AND id > ?
|
|
153274
|
+
AND target_memory_id IN (${placeholders2(uniqueIds)})
|
|
153275
|
+
ORDER BY id ASC`).all(...identities, afterId ?? 0, ...uniqueIds);
|
|
153276
|
+
return coalesceMutations(rows);
|
|
153277
|
+
}
|
|
152736
153278
|
function getMaxMemoryMutationId(db, projectPath) {
|
|
152737
153279
|
const row = db.prepare("SELECT MAX(id) AS max_id FROM memory_mutation_log WHERE project_path = ?").get(projectPath);
|
|
152738
153280
|
return row?.max_id ?? null;
|
|
152739
153281
|
}
|
|
153282
|
+
function getMaxMemoryMutationIdForProjects(db, projectPaths) {
|
|
153283
|
+
const identities = uniqueProjectPaths(projectPaths);
|
|
153284
|
+
if (identities.length === 0)
|
|
153285
|
+
return null;
|
|
153286
|
+
if (identities.length === 1)
|
|
153287
|
+
return getMaxMemoryMutationId(db, identities[0]);
|
|
153288
|
+
const row = db.prepare(`SELECT MAX(id) AS max_id
|
|
153289
|
+
FROM memory_mutation_log
|
|
153290
|
+
WHERE project_path IN (${placeholders2(identities)})`).get(...identities);
|
|
153291
|
+
return row?.max_id ?? null;
|
|
153292
|
+
}
|
|
152740
153293
|
var MEMORY_MUTATION_TYPES, TERMINAL_MUTATION_TYPES;
|
|
152741
153294
|
var init_storage_memory_mutation_log = __esm(() => {
|
|
152742
153295
|
MEMORY_MUTATION_TYPES = new Set(["archive", "delete", "update", "superseded"]);
|
|
@@ -153429,6 +153982,36 @@ function addStaleReduceStrippedIds(db, sessionId, ids) {
|
|
|
153429
153982
|
sessionLog(sessionId, `stale_reduce_stripped_ids CAS: ${CAS_RETRY_LIMIT} retries exhausted`);
|
|
153430
153983
|
return false;
|
|
153431
153984
|
}
|
|
153985
|
+
function getProcessedImageStrippedIds(db, sessionId) {
|
|
153986
|
+
const row = db.prepare("SELECT processed_image_stripped_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
153987
|
+
return new Set(parseStrippedBlob(row?.processed_image_stripped_ids));
|
|
153988
|
+
}
|
|
153989
|
+
function addProcessedImageStrippedIds(db, sessionId, ids) {
|
|
153990
|
+
const add = [...ids];
|
|
153991
|
+
if (add.length === 0)
|
|
153992
|
+
return true;
|
|
153993
|
+
ensureSessionMetaRow(db, sessionId);
|
|
153994
|
+
for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
|
|
153995
|
+
const row = db.prepare("SELECT processed_image_stripped_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
153996
|
+
const rawStored = row ? row.processed_image_stripped_ids ?? null : null;
|
|
153997
|
+
const current = new Set(parseStrippedBlob(rawStored));
|
|
153998
|
+
let changed = false;
|
|
153999
|
+
for (const id of add) {
|
|
154000
|
+
if (!current.has(id)) {
|
|
154001
|
+
current.add(id);
|
|
154002
|
+
changed = true;
|
|
154003
|
+
}
|
|
154004
|
+
}
|
|
154005
|
+
if (!changed)
|
|
154006
|
+
return true;
|
|
154007
|
+
const nextBlob = JSON.stringify([...current]);
|
|
154008
|
+
const result = db.prepare("UPDATE session_meta SET processed_image_stripped_ids = ? WHERE session_id = ? AND processed_image_stripped_ids IS ?").run(nextBlob, sessionId, rawStored);
|
|
154009
|
+
if (result.changes > 0)
|
|
154010
|
+
return true;
|
|
154011
|
+
}
|
|
154012
|
+
sessionLog(sessionId, `processed_image_stripped_ids CAS: ${CAS_RETRY_LIMIT} retries exhausted`);
|
|
154013
|
+
return false;
|
|
154014
|
+
}
|
|
153432
154015
|
function isPendingCompactionMarker(value) {
|
|
153433
154016
|
return typeof value === "object" && value !== null && typeof value.ordinal === "number" && typeof value.endMessageId === "string" && typeof value.publishedAt === "number";
|
|
153434
154017
|
}
|
|
@@ -153607,6 +154190,8 @@ function clearSession(db, sessionId) {
|
|
|
153607
154190
|
db.prepare("DELETE FROM source_contents WHERE session_id = ?").run(sessionId);
|
|
153608
154191
|
db.prepare("DELETE FROM tags WHERE session_id = ?").run(sessionId);
|
|
153609
154192
|
db.prepare("DELETE FROM session_meta WHERE session_id = ?").run(sessionId);
|
|
154193
|
+
db.prepare("DELETE FROM session_projects WHERE session_id = ?").run(sessionId);
|
|
154194
|
+
db.prepare("DELETE FROM compartment_chunk_embeddings WHERE session_id = ?").run(sessionId);
|
|
153610
154195
|
db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
|
|
153611
154196
|
clearCompressionDepth(db, sessionId);
|
|
153612
154197
|
db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
|
|
@@ -153713,9 +154298,9 @@ function buildStatusClause(status) {
|
|
|
153713
154298
|
if (statuses.length === 0) {
|
|
153714
154299
|
return null;
|
|
153715
154300
|
}
|
|
153716
|
-
const
|
|
154301
|
+
const placeholders3 = statuses.map(() => "?").join(", ");
|
|
153717
154302
|
return {
|
|
153718
|
-
sql: `status IN (${
|
|
154303
|
+
sql: `status IN (${placeholders3})`,
|
|
153719
154304
|
params: statuses
|
|
153720
154305
|
};
|
|
153721
154306
|
}
|
|
@@ -153921,19 +154506,6 @@ function getProjectState(db, projectPath) {
|
|
|
153921
154506
|
WHERE project_path = ?`).get(projectPath);
|
|
153922
154507
|
return row ? toProjectState(row) : null;
|
|
153923
154508
|
}
|
|
153924
|
-
function bumpProjectMemoryEpoch(db, projectPath, now = Date.now()) {
|
|
153925
|
-
db.prepare(`INSERT INTO project_state
|
|
153926
|
-
(project_path, project_memory_epoch, project_user_profile_version, updated_at)
|
|
153927
|
-
VALUES (?, 1, 0, ?)
|
|
153928
|
-
ON CONFLICT(project_path) DO UPDATE SET
|
|
153929
|
-
project_memory_epoch = project_memory_epoch + 1,
|
|
153930
|
-
updated_at = excluded.updated_at`).run(projectPath, now);
|
|
153931
|
-
const state = getProjectState(db, projectPath);
|
|
153932
|
-
if (!state) {
|
|
153933
|
-
throw new Error(`Failed to bump project memory epoch for ${projectPath}`);
|
|
153934
|
-
}
|
|
153935
|
-
return state;
|
|
153936
|
-
}
|
|
153937
154509
|
function bumpProjectUserProfileVersion(db, projectPath = GLOBAL_USER_PROFILE_PROJECT_PATH, now = Date.now()) {
|
|
153938
154510
|
db.prepare(`INSERT INTO project_state
|
|
153939
154511
|
(project_path, project_memory_epoch, project_user_profile_version, updated_at)
|
|
@@ -153969,8 +154541,8 @@ function getSourceContents(db, sessionId, tagIds) {
|
|
|
153969
154541
|
if (tagIds.length === 0) {
|
|
153970
154542
|
return new Map;
|
|
153971
154543
|
}
|
|
153972
|
-
const
|
|
153973
|
-
const rows = db.prepare(`SELECT tag_id, content FROM source_contents WHERE session_id = ? AND tag_id IN (${
|
|
154544
|
+
const placeholders3 = tagIds.map(() => "?").join(", ");
|
|
154545
|
+
const rows = db.prepare(`SELECT tag_id, content FROM source_contents WHERE session_id = ? AND tag_id IN (${placeholders3})`).all(sessionId, ...tagIds).filter(isSourceContentRow);
|
|
153974
154546
|
const sources = new Map;
|
|
153975
154547
|
for (const row of rows) {
|
|
153976
154548
|
sources.set(row.tag_id, row.content);
|
|
@@ -154280,8 +154852,8 @@ function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
|
154280
154852
|
}
|
|
154281
154853
|
return all;
|
|
154282
154854
|
}
|
|
154283
|
-
const
|
|
154284
|
-
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${
|
|
154855
|
+
const placeholders3 = tagNumbers.map(() => "?").join(",");
|
|
154856
|
+
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);
|
|
154285
154857
|
return rows.map(toTagEntry);
|
|
154286
154858
|
}
|
|
154287
154859
|
function getMaxDroppedTagNumber(db, sessionId) {
|
|
@@ -154434,6 +155006,7 @@ var init_storage = __esm(async () => {
|
|
|
154434
155006
|
init_storage_source();
|
|
154435
155007
|
init_storage_tags();
|
|
154436
155008
|
init_storage_v22_backfill_failures();
|
|
155009
|
+
init_workspaces();
|
|
154437
155010
|
await __promiseAll([
|
|
154438
155011
|
init_message_index(),
|
|
154439
155012
|
init_migrations(),
|
|
@@ -163885,7 +164458,7 @@ function isEmbeddingRow(row) {
|
|
|
163885
164458
|
if (row === null || typeof row !== "object")
|
|
163886
164459
|
return false;
|
|
163887
164460
|
const candidate = row;
|
|
163888
|
-
return typeof candidate.memoryId === "number" && isEmbeddingBlob(candidate.embedding);
|
|
164461
|
+
return typeof candidate.memoryId === "number" && isEmbeddingBlob(candidate.embedding) && (candidate.modelId === null || typeof candidate.modelId === "string");
|
|
163889
164462
|
}
|
|
163890
164463
|
function toFloat32Array(blob) {
|
|
163891
164464
|
if (blob instanceof Uint8Array) {
|
|
@@ -163905,7 +164478,7 @@ function getSaveEmbeddingStatement(db) {
|
|
|
163905
164478
|
function getLoadAllEmbeddingsStatement(db) {
|
|
163906
164479
|
let stmt = loadAllEmbeddingsStatements.get(db);
|
|
163907
164480
|
if (!stmt) {
|
|
163908
|
-
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");
|
|
164481
|
+
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");
|
|
163909
164482
|
loadAllEmbeddingsStatements.set(db, stmt);
|
|
163910
164483
|
}
|
|
163911
164484
|
return stmt;
|
|
@@ -163934,7 +164507,10 @@ function loadAllEmbeddings(db, projectPath) {
|
|
|
163934
164507
|
const rows = getLoadAllEmbeddingsStatement(db).all(projectPath).filter(isEmbeddingRow);
|
|
163935
164508
|
const embeddings = new Map;
|
|
163936
164509
|
for (const row of rows) {
|
|
163937
|
-
embeddings.set(row.memoryId,
|
|
164510
|
+
embeddings.set(row.memoryId, {
|
|
164511
|
+
embedding: toFloat32Array(row.embedding),
|
|
164512
|
+
modelId: row.modelId
|
|
164513
|
+
});
|
|
163938
164514
|
}
|
|
163939
164515
|
return embeddings;
|
|
163940
164516
|
}
|
|
@@ -163997,13 +164573,13 @@ var init_embedding_cache = __esm(() => {
|
|
|
163997
164573
|
});
|
|
163998
164574
|
|
|
163999
164575
|
// src/features/magic-context/memory/normalize-hash.ts
|
|
164000
|
-
import { createHash as
|
|
164576
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
164001
164577
|
function normalizeMemoryContent(content) {
|
|
164002
164578
|
return content.toLowerCase().replace(/\s+/g, " ").trim();
|
|
164003
164579
|
}
|
|
164004
164580
|
function computeNormalizedHash(content) {
|
|
164005
164581
|
const normalized = normalizeMemoryContent(content);
|
|
164006
|
-
return
|
|
164582
|
+
return createHash7("md5").update(normalized).digest("hex");
|
|
164007
164583
|
}
|
|
164008
164584
|
var init_normalize_hash = () => {};
|
|
164009
164585
|
|
|
@@ -164117,8 +164693,8 @@ function getMemoriesByProjectStatement(db, statuses) {
|
|
|
164117
164693
|
}
|
|
164118
164694
|
let stmt = statements.get(db);
|
|
164119
164695
|
if (!stmt) {
|
|
164120
|
-
const
|
|
164121
|
-
stmt = db.prepare(`SELECT ${getMemorySelectColumns(db)} FROM memories WHERE project_path = ? AND status IN (${
|
|
164696
|
+
const placeholders3 = statuses.map(() => "?").join(", ");
|
|
164697
|
+
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`);
|
|
164122
164698
|
statements.set(db, stmt);
|
|
164123
164699
|
}
|
|
164124
164700
|
return stmt;
|
|
@@ -164239,6 +164815,97 @@ function getMemoriesByProject(db, projectPath, statuses = ["active", "permanent"
|
|
|
164239
164815
|
const rows = getMemoriesByProjectStatement(db, statuses).all(projectPath, ...statuses, expiryCutoff).filter(isMemoryRow);
|
|
164240
164816
|
return rows.map(toMemory);
|
|
164241
164817
|
}
|
|
164818
|
+
function sqlPlaceholders(values) {
|
|
164819
|
+
return values.map(() => "?").join(", ");
|
|
164820
|
+
}
|
|
164821
|
+
function uniqueValues(values) {
|
|
164822
|
+
return [...new Set(values.filter((value) => value.length > 0))];
|
|
164823
|
+
}
|
|
164824
|
+
function buildWorkspaceMemorySqlFilter(args) {
|
|
164825
|
+
if (args.shareCategories === null || args.shareCategories === undefined) {
|
|
164826
|
+
return { clause: "", params: [], active: false };
|
|
164827
|
+
}
|
|
164828
|
+
const identities = uniqueValues(args.identities);
|
|
164829
|
+
const identitySet = new Set(identities);
|
|
164830
|
+
const ownSet = new Set(uniqueValues(args.ownIdentities ?? []).filter((identity) => identitySet.has(identity)));
|
|
164831
|
+
const foreignIdentities = identities.filter((identity) => !ownSet.has(identity));
|
|
164832
|
+
if (foreignIdentities.length === 0) {
|
|
164833
|
+
return { clause: "", params: [], active: false };
|
|
164834
|
+
}
|
|
164835
|
+
const ownIdentities = identities.filter((identity) => ownSet.has(identity));
|
|
164836
|
+
const shareCategories = uniqueValues([...args.shareCategories]);
|
|
164837
|
+
const qualifier = args.tableName ? `${args.tableName}.` : "";
|
|
164838
|
+
const predicates = [];
|
|
164839
|
+
const params = [];
|
|
164840
|
+
if (ownIdentities.length > 0) {
|
|
164841
|
+
predicates.push(`${qualifier}project_path IN (${sqlPlaceholders(ownIdentities)})`);
|
|
164842
|
+
params.push(...ownIdentities);
|
|
164843
|
+
}
|
|
164844
|
+
if (foreignIdentities.length > 0 && shareCategories.length > 0) {
|
|
164845
|
+
predicates.push(`(${qualifier}project_path IN (${sqlPlaceholders(foreignIdentities)}) AND ${qualifier}category IN (${sqlPlaceholders(shareCategories)}))`);
|
|
164846
|
+
params.push(...foreignIdentities, ...shareCategories);
|
|
164847
|
+
}
|
|
164848
|
+
if (predicates.length === 0) {
|
|
164849
|
+
return { clause: " AND 0 = 1", params: [], active: true };
|
|
164850
|
+
}
|
|
164851
|
+
return { clause: ` AND (${predicates.join(" OR ")})`, params, active: true };
|
|
164852
|
+
}
|
|
164853
|
+
function getMemoriesByProjects(db, projectPaths, statuses = ["active", "permanent"], expiryCutoff = Date.now(), ownIdentities, shareCategories) {
|
|
164854
|
+
const identities = uniqueValues(projectPaths);
|
|
164855
|
+
if (identities.length === 0 || statuses.length === 0)
|
|
164856
|
+
return [];
|
|
164857
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
164858
|
+
identities,
|
|
164859
|
+
ownIdentities,
|
|
164860
|
+
shareCategories
|
|
164861
|
+
});
|
|
164862
|
+
if (identities.length === 1 && !sharingFilter.active) {
|
|
164863
|
+
return getMemoriesByProject(db, identities[0], statuses, expiryCutoff);
|
|
164864
|
+
}
|
|
164865
|
+
const rows = db.prepare(`SELECT ${getMemorySelectColumns(db)}
|
|
164866
|
+
FROM memories
|
|
164867
|
+
WHERE project_path IN (${sqlPlaceholders(identities)})
|
|
164868
|
+
AND status IN (${sqlPlaceholders(statuses)})
|
|
164869
|
+
AND (expires_at IS NULL OR expires_at > ?)${sharingFilter.clause}
|
|
164870
|
+
ORDER BY category ASC, updated_at DESC, id ASC`).all(...identities, ...statuses, expiryCutoff, ...sharingFilter.params).filter(isMemoryRow);
|
|
164871
|
+
return rows.map(toMemory);
|
|
164872
|
+
}
|
|
164873
|
+
function getMaxMemoryIdForProjects(db, projectPaths, ownIdentities, shareCategories) {
|
|
164874
|
+
const identities = uniqueValues(projectPaths);
|
|
164875
|
+
if (identities.length === 0)
|
|
164876
|
+
return 0;
|
|
164877
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
164878
|
+
identities,
|
|
164879
|
+
ownIdentities,
|
|
164880
|
+
shareCategories
|
|
164881
|
+
});
|
|
164882
|
+
if (identities.length === 1 && !sharingFilter.active) {
|
|
164883
|
+
const row2 = db.prepare("SELECT COALESCE(MAX(id), 0) AS max_id FROM memories WHERE project_path = ?").get(identities[0]);
|
|
164884
|
+
return typeof row2?.max_id === "number" ? row2.max_id : 0;
|
|
164885
|
+
}
|
|
164886
|
+
const row = db.prepare(`SELECT COALESCE(MAX(id), 0) AS max_id
|
|
164887
|
+
FROM memories
|
|
164888
|
+
WHERE project_path IN (${sqlPlaceholders(identities)})${sharingFilter.clause}`).get(...identities, ...sharingFilter.params);
|
|
164889
|
+
return typeof row?.max_id === "number" ? row.max_id : 0;
|
|
164890
|
+
}
|
|
164891
|
+
function readNewMemoriesForM1Union(db, projectPaths, afterId, expiryCutoff, ownIdentities, shareCategories) {
|
|
164892
|
+
const identities = uniqueValues(projectPaths);
|
|
164893
|
+
if (identities.length === 0)
|
|
164894
|
+
return [];
|
|
164895
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
164896
|
+
identities,
|
|
164897
|
+
ownIdentities,
|
|
164898
|
+
shareCategories
|
|
164899
|
+
});
|
|
164900
|
+
const rows = db.prepare(`SELECT ${getMemorySelectColumns(db)}
|
|
164901
|
+
FROM memories
|
|
164902
|
+
WHERE project_path IN (${sqlPlaceholders(identities)})
|
|
164903
|
+
AND id > ?
|
|
164904
|
+
AND status IN ('active', 'permanent')
|
|
164905
|
+
AND (expires_at IS NULL OR expires_at > ?)${sharingFilter.clause}
|
|
164906
|
+
ORDER BY ${MEMORY_CATEGORY_ORDER_SQL}, id ASC`).all(...identities, afterId, expiryCutoff, ...sharingFilter.params).filter(isMemoryRow);
|
|
164907
|
+
return rows.map(toMemory);
|
|
164908
|
+
}
|
|
164242
164909
|
function getAllActiveMemoriesForMigration(db, projectPath) {
|
|
164243
164910
|
const rows = getActiveMemoriesNoExpiryStatement(db).all(projectPath).filter(isMemoryRow);
|
|
164244
164911
|
return rows.map(toMemory);
|
|
@@ -164336,6 +165003,7 @@ function getMemoryCountsByStatus(db, projectPath) {
|
|
|
164336
165003
|
}
|
|
164337
165004
|
var COLUMN_MAP, MEMORY_CATEGORY_LOOKUP, MEMORY_STATUS_LOOKUP, MEMORY_SOURCE_TYPE_LOOKUP, VERIFICATION_STATUS_LOOKUP, insertMemoryStatements, getMemoryByHashStatements, getMemoryByIdStatements, activeMemoriesNoExpiryStatements, updateMemorySeenCountStatements, updateMemoryRetrievalCountStatements, updateMemoryStatusStatements, updateArchivedMemoryStatements, updateMemoryVerificationStatements, updateMemoryContentStatements, supersededMemoryStatements, mergeMemoryStatsStatements, deleteMemoryStatements, deleteMemoryEmbeddingStatements, deleteEmbeddingOnContentUpdateStatements, getMemoryCountStatements, getMemoryCountByProjectStatements, getMemoryCountsByStatusStatements, memoriesByProjectStatements, memoryImportanceColumnCache;
|
|
164338
165005
|
var init_storage_memory = __esm(() => {
|
|
165006
|
+
init_constants();
|
|
164339
165007
|
init_embedding_cache();
|
|
164340
165008
|
init_normalize_hash();
|
|
164341
165009
|
COLUMN_MAP = {
|
|
@@ -164441,8 +165109,8 @@ function getUserMemoryCandidates(db) {
|
|
|
164441
165109
|
function deleteUserMemoryCandidates(db, ids) {
|
|
164442
165110
|
if (ids.length === 0)
|
|
164443
165111
|
return;
|
|
164444
|
-
const
|
|
164445
|
-
db.prepare(`DELETE FROM user_memory_candidates WHERE id IN (${
|
|
165112
|
+
const placeholders3 = ids.map(() => "?").join(",");
|
|
165113
|
+
db.prepare(`DELETE FROM user_memory_candidates WHERE id IN (${placeholders3})`).run(...ids);
|
|
164446
165114
|
}
|
|
164447
165115
|
function insertUserMemory(db, content, sourceCandidateIds) {
|
|
164448
165116
|
const now = Date.now();
|
|
@@ -164475,6 +165143,444 @@ function parseUserMemoryRow(row) {
|
|
|
164475
165143
|
};
|
|
164476
165144
|
}
|
|
164477
165145
|
|
|
165146
|
+
// src/features/magic-context/compartment-chunk-embedding.ts
|
|
165147
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
165148
|
+
function getLoadFtsRowsStatement(db) {
|
|
165149
|
+
let stmt = loadFtsRowsStatements.get(db);
|
|
165150
|
+
if (!stmt) {
|
|
165151
|
+
stmt = db.prepare(`SELECT message_ordinal AS messageOrdinal, role, content
|
|
165152
|
+
FROM message_history_fts
|
|
165153
|
+
WHERE session_id = ?
|
|
165154
|
+
AND message_ordinal >= ?
|
|
165155
|
+
AND message_ordinal <= ?
|
|
165156
|
+
AND role IN ('user', 'assistant')
|
|
165157
|
+
ORDER BY message_ordinal ASC`);
|
|
165158
|
+
loadFtsRowsStatements.set(db, stmt);
|
|
165159
|
+
}
|
|
165160
|
+
return stmt;
|
|
165161
|
+
}
|
|
165162
|
+
function getExistingHashStatement(db, scopedToProject) {
|
|
165163
|
+
const map2 = scopedToProject ? existingHashByProjectStatements : existingHashStatements;
|
|
165164
|
+
let stmt = map2.get(db);
|
|
165165
|
+
if (!stmt) {
|
|
165166
|
+
stmt = db.prepare(`SELECT window_index AS windowIndex, chunk_hash AS chunkHash
|
|
165167
|
+
FROM compartment_chunk_embeddings
|
|
165168
|
+
WHERE compartment_id = ?
|
|
165169
|
+
AND model_id = ?
|
|
165170
|
+
${scopedToProject ? "AND project_path = ?" : ""}
|
|
165171
|
+
ORDER BY window_index ASC`);
|
|
165172
|
+
map2.set(db, stmt);
|
|
165173
|
+
}
|
|
165174
|
+
return stmt;
|
|
165175
|
+
}
|
|
165176
|
+
function getDeleteByCompartmentStatement(db) {
|
|
165177
|
+
let stmt = deleteByCompartmentStatements.get(db);
|
|
165178
|
+
if (!stmt) {
|
|
165179
|
+
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE compartment_id = ?");
|
|
165180
|
+
deleteByCompartmentStatements.set(db, stmt);
|
|
165181
|
+
}
|
|
165182
|
+
return stmt;
|
|
165183
|
+
}
|
|
165184
|
+
function getInsertEmbeddingStatement(db) {
|
|
165185
|
+
let stmt = insertEmbeddingStatements.get(db);
|
|
165186
|
+
if (!stmt) {
|
|
165187
|
+
stmt = db.prepare(`INSERT INTO compartment_chunk_embeddings (
|
|
165188
|
+
compartment_id, session_id, project_path, harness, window_index,
|
|
165189
|
+
start_ordinal, end_ordinal, chunk_hash, model_id, dims, vector, created_at
|
|
165190
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
165191
|
+
insertEmbeddingStatements.set(db, stmt);
|
|
165192
|
+
}
|
|
165193
|
+
return stmt;
|
|
165194
|
+
}
|
|
165195
|
+
function getDistinctModelStatement(db) {
|
|
165196
|
+
let stmt = distinctModelStatements.get(db);
|
|
165197
|
+
if (!stmt) {
|
|
165198
|
+
stmt = db.prepare(`SELECT DISTINCT model_id AS modelId
|
|
165199
|
+
FROM compartment_chunk_embeddings
|
|
165200
|
+
WHERE project_path = ?`);
|
|
165201
|
+
distinctModelStatements.set(db, stmt);
|
|
165202
|
+
}
|
|
165203
|
+
return stmt;
|
|
165204
|
+
}
|
|
165205
|
+
function getClearProjectStatement(db) {
|
|
165206
|
+
let stmt = clearProjectStatements.get(db);
|
|
165207
|
+
if (!stmt) {
|
|
165208
|
+
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE project_path = ?");
|
|
165209
|
+
clearProjectStatements.set(db, stmt);
|
|
165210
|
+
}
|
|
165211
|
+
return stmt;
|
|
165212
|
+
}
|
|
165213
|
+
function getClearProjectModelStatement(db) {
|
|
165214
|
+
let stmt = clearProjectModelStatements.get(db);
|
|
165215
|
+
if (!stmt) {
|
|
165216
|
+
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE project_path = ? AND model_id = ?");
|
|
165217
|
+
clearProjectModelStatements.set(db, stmt);
|
|
165218
|
+
}
|
|
165219
|
+
return stmt;
|
|
165220
|
+
}
|
|
165221
|
+
function getSearchRowsStatement(db, withModel) {
|
|
165222
|
+
const map2 = withModel ? searchRowsByModelStatements : searchRowsStatements;
|
|
165223
|
+
let stmt = map2.get(db);
|
|
165224
|
+
if (!stmt) {
|
|
165225
|
+
stmt = db.prepare(`SELECT e.compartment_id AS compartmentId,
|
|
165226
|
+
e.session_id AS sessionId,
|
|
165227
|
+
c.title AS title,
|
|
165228
|
+
c.start_message AS compartmentStart,
|
|
165229
|
+
c.end_message AS compartmentEnd,
|
|
165230
|
+
e.window_index AS windowIndex,
|
|
165231
|
+
e.start_ordinal AS windowStart,
|
|
165232
|
+
e.end_ordinal AS windowEnd,
|
|
165233
|
+
e.chunk_hash AS chunkHash,
|
|
165234
|
+
e.model_id AS modelId,
|
|
165235
|
+
e.dims AS dims,
|
|
165236
|
+
e.vector AS vector
|
|
165237
|
+
FROM compartment_chunk_embeddings e
|
|
165238
|
+
JOIN compartments c ON c.id = e.compartment_id
|
|
165239
|
+
WHERE e.session_id = ?
|
|
165240
|
+
AND e.project_path = ?
|
|
165241
|
+
${withModel ? "AND e.model_id = ?" : ""}
|
|
165242
|
+
ORDER BY e.compartment_id ASC, e.window_index ASC`);
|
|
165243
|
+
map2.set(db, stmt);
|
|
165244
|
+
}
|
|
165245
|
+
return stmt;
|
|
165246
|
+
}
|
|
165247
|
+
function isFinitePositiveInteger(value) {
|
|
165248
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
165249
|
+
}
|
|
165250
|
+
function normalizeCompartmentChunkMaxInputTokens(value) {
|
|
165251
|
+
if (!isFinitePositiveInteger(value)) {
|
|
165252
|
+
return DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS;
|
|
165253
|
+
}
|
|
165254
|
+
return Math.max(1, Math.floor(value));
|
|
165255
|
+
}
|
|
165256
|
+
function normalizeContent(text) {
|
|
165257
|
+
return text.replace(/\s+/g, " ").trim();
|
|
165258
|
+
}
|
|
165259
|
+
function formatOrdinalRange(start, end) {
|
|
165260
|
+
return start === end ? `[${start}]` : `[${start}-${end}]`;
|
|
165261
|
+
}
|
|
165262
|
+
function rolePrefix(role) {
|
|
165263
|
+
if (role === "user")
|
|
165264
|
+
return "U";
|
|
165265
|
+
if (role === "assistant")
|
|
165266
|
+
return "A";
|
|
165267
|
+
return null;
|
|
165268
|
+
}
|
|
165269
|
+
function parseOrdinal(value) {
|
|
165270
|
+
const parsed = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
165271
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
165272
|
+
}
|
|
165273
|
+
function parseCanonicalLineRange(line) {
|
|
165274
|
+
const match = /^\[(\d+)(?:-(\d+))?\]\s+[UA]:/.exec(line.trim());
|
|
165275
|
+
if (!match)
|
|
165276
|
+
return null;
|
|
165277
|
+
const start = Number.parseInt(match[1], 10);
|
|
165278
|
+
const end = match[2] ? Number.parseInt(match[2], 10) : start;
|
|
165279
|
+
if (!Number.isFinite(start) || !Number.isFinite(end))
|
|
165280
|
+
return null;
|
|
165281
|
+
return { start, end };
|
|
165282
|
+
}
|
|
165283
|
+
function hashChunkText(text) {
|
|
165284
|
+
return createHash8("sha256").update(text).digest("hex");
|
|
165285
|
+
}
|
|
165286
|
+
function vectorBlob(vector) {
|
|
165287
|
+
return new Uint8Array(vector.buffer, vector.byteOffset, vector.byteLength);
|
|
165288
|
+
}
|
|
165289
|
+
function toFloat32Array2(blob) {
|
|
165290
|
+
if (blob instanceof Uint8Array) {
|
|
165291
|
+
const buffer2 = blob.buffer.slice(blob.byteOffset, blob.byteOffset + blob.byteLength);
|
|
165292
|
+
return new Float32Array(buffer2);
|
|
165293
|
+
}
|
|
165294
|
+
return new Float32Array(blob.slice(0));
|
|
165295
|
+
}
|
|
165296
|
+
function buildCanonicalChunkTextFromFts(db, sessionId, startOrdinal, endOrdinal) {
|
|
165297
|
+
if (endOrdinal < startOrdinal)
|
|
165298
|
+
return "";
|
|
165299
|
+
const rows = getLoadFtsRowsStatement(db).all(sessionId, startOrdinal, endOrdinal).map((row) => row);
|
|
165300
|
+
const lines = [];
|
|
165301
|
+
let current = null;
|
|
165302
|
+
const flush2 = () => {
|
|
165303
|
+
if (!current || current.parts.length === 0)
|
|
165304
|
+
return;
|
|
165305
|
+
lines.push(`${formatOrdinalRange(current.start, current.end)} ${current.role}: ${current.parts.join(" / ")}`);
|
|
165306
|
+
current = null;
|
|
165307
|
+
};
|
|
165308
|
+
for (const row of rows) {
|
|
165309
|
+
const ordinal = parseOrdinal(row.messageOrdinal);
|
|
165310
|
+
const prefix = rolePrefix(row.role);
|
|
165311
|
+
const content = typeof row.content === "string" ? normalizeContent(row.content) : "";
|
|
165312
|
+
if (ordinal === null || prefix === null || content.length === 0)
|
|
165313
|
+
continue;
|
|
165314
|
+
if (current && current.role === prefix) {
|
|
165315
|
+
current.end = ordinal;
|
|
165316
|
+
current.parts.push(content);
|
|
165317
|
+
continue;
|
|
165318
|
+
}
|
|
165319
|
+
flush2();
|
|
165320
|
+
current = { role: prefix, start: ordinal, end: ordinal, parts: [content] };
|
|
165321
|
+
}
|
|
165322
|
+
flush2();
|
|
165323
|
+
return lines.join(`
|
|
165324
|
+
`);
|
|
165325
|
+
}
|
|
165326
|
+
function canonicalizeInMemoryChunkTextForEmbedding(chunkText, startOrdinal, endOrdinal) {
|
|
165327
|
+
const lines = [];
|
|
165328
|
+
for (const rawLine of chunkText.split(/\r?\n/)) {
|
|
165329
|
+
const line = rawLine.trim();
|
|
165330
|
+
const match = /^(\[(\d+)(?:-(\d+))?\]\s+[UA]:)\s*(.*)$/.exec(line);
|
|
165331
|
+
if (!match)
|
|
165332
|
+
continue;
|
|
165333
|
+
const lineStart = Number.parseInt(match[2], 10);
|
|
165334
|
+
const lineEnd = match[3] ? Number.parseInt(match[3], 10) : lineStart;
|
|
165335
|
+
if (startOrdinal != null && lineEnd < startOrdinal)
|
|
165336
|
+
continue;
|
|
165337
|
+
if (endOrdinal != null && lineStart > endOrdinal)
|
|
165338
|
+
continue;
|
|
165339
|
+
const rawParts = match[4].split(" / ").map((part) => normalizeContent(part)).filter((part) => part.length > 0);
|
|
165340
|
+
const ordinalSpan = lineEnd - lineStart + 1;
|
|
165341
|
+
const roleLabel = match[1].slice(match[1].indexOf("]") + 2);
|
|
165342
|
+
if (ordinalSpan === rawParts.length) {
|
|
165343
|
+
const retained = rawParts.map((part, index) => ({ ordinal: lineStart + index, part })).filter(({ ordinal, part }) => {
|
|
165344
|
+
if (part.startsWith("TC:"))
|
|
165345
|
+
return false;
|
|
165346
|
+
if (startOrdinal != null && ordinal < startOrdinal)
|
|
165347
|
+
return false;
|
|
165348
|
+
if (endOrdinal != null && ordinal > endOrdinal)
|
|
165349
|
+
return false;
|
|
165350
|
+
return true;
|
|
165351
|
+
});
|
|
165352
|
+
if (retained.length === 0)
|
|
165353
|
+
continue;
|
|
165354
|
+
const retainedStart = retained[0].ordinal;
|
|
165355
|
+
const retainedEnd = retained[retained.length - 1].ordinal;
|
|
165356
|
+
lines.push(`${formatOrdinalRange(retainedStart, retainedEnd)} ${roleLabel} ${retained.map(({ part }) => part).join(" / ")}`);
|
|
165357
|
+
continue;
|
|
165358
|
+
}
|
|
165359
|
+
const parts = rawParts.filter((part) => !part.startsWith("TC:"));
|
|
165360
|
+
if (parts.length === 0)
|
|
165361
|
+
continue;
|
|
165362
|
+
lines.push(`${match[1]} ${parts.join(" / ")}`);
|
|
165363
|
+
}
|
|
165364
|
+
return lines.join(`
|
|
165365
|
+
`);
|
|
165366
|
+
}
|
|
165367
|
+
function chunkCanonicalText(canonicalText, startOrdinal, endOrdinal, maxInputTokens) {
|
|
165368
|
+
const lines = canonicalText.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
165369
|
+
if (lines.length === 0 || endOrdinal < startOrdinal)
|
|
165370
|
+
return [];
|
|
165371
|
+
const normalizedMax = normalizeCompartmentChunkMaxInputTokens(maxInputTokens);
|
|
165372
|
+
const fullText = lines.join(`
|
|
165373
|
+
`);
|
|
165374
|
+
if (estimateTokens(fullText) <= normalizedMax) {
|
|
165375
|
+
return [
|
|
165376
|
+
{
|
|
165377
|
+
windowIndex: 0,
|
|
165378
|
+
startOrdinal,
|
|
165379
|
+
endOrdinal,
|
|
165380
|
+
text: fullText,
|
|
165381
|
+
chunkHash: hashChunkText(fullText)
|
|
165382
|
+
}
|
|
165383
|
+
];
|
|
165384
|
+
}
|
|
165385
|
+
const windows = [];
|
|
165386
|
+
let currentLines = [];
|
|
165387
|
+
let currentStart = null;
|
|
165388
|
+
let currentEnd = null;
|
|
165389
|
+
let currentTokens = 0;
|
|
165390
|
+
const flush2 = () => {
|
|
165391
|
+
if (currentLines.length === 0 || currentStart === null || currentEnd === null)
|
|
165392
|
+
return;
|
|
165393
|
+
const text = currentLines.join(`
|
|
165394
|
+
`);
|
|
165395
|
+
windows.push({
|
|
165396
|
+
windowIndex: windows.length + 1,
|
|
165397
|
+
startOrdinal: currentStart,
|
|
165398
|
+
endOrdinal: currentEnd,
|
|
165399
|
+
text,
|
|
165400
|
+
chunkHash: hashChunkText(text)
|
|
165401
|
+
});
|
|
165402
|
+
currentLines = [];
|
|
165403
|
+
currentStart = null;
|
|
165404
|
+
currentEnd = null;
|
|
165405
|
+
currentTokens = 0;
|
|
165406
|
+
};
|
|
165407
|
+
for (const line of lines) {
|
|
165408
|
+
const range = parseCanonicalLineRange(line);
|
|
165409
|
+
const lineStart = range?.start ?? startOrdinal;
|
|
165410
|
+
const lineEnd = range?.end ?? lineStart;
|
|
165411
|
+
const lineTokens = estimateTokens(line);
|
|
165412
|
+
if (currentLines.length > 0 && currentTokens + lineTokens > normalizedMax) {
|
|
165413
|
+
flush2();
|
|
165414
|
+
}
|
|
165415
|
+
if (currentLines.length === 0) {
|
|
165416
|
+
currentStart = lineStart;
|
|
165417
|
+
}
|
|
165418
|
+
currentLines.push(line);
|
|
165419
|
+
currentEnd = lineEnd;
|
|
165420
|
+
currentTokens += lineTokens;
|
|
165421
|
+
}
|
|
165422
|
+
flush2();
|
|
165423
|
+
return windows;
|
|
165424
|
+
}
|
|
165425
|
+
function getExistingChunkHashes(db, compartmentId, modelId, projectPath) {
|
|
165426
|
+
const scoped = typeof projectPath === "string" && projectPath.length > 0;
|
|
165427
|
+
const rows = scoped ? getExistingHashStatement(db, true).all(compartmentId, modelId, projectPath) : getExistingHashStatement(db, false).all(compartmentId, modelId);
|
|
165428
|
+
return new Map(rows.filter((row) => typeof row.windowIndex === "number" && typeof row.chunkHash === "string").map((row) => [row.windowIndex, row.chunkHash]));
|
|
165429
|
+
}
|
|
165430
|
+
function chunkEmbeddingWindowsAreCurrent(db, compartmentId, modelId, windows, projectPath) {
|
|
165431
|
+
const existing = getExistingChunkHashes(db, compartmentId, modelId, projectPath);
|
|
165432
|
+
if (existing.size !== windows.length)
|
|
165433
|
+
return false;
|
|
165434
|
+
return windows.every((window) => existing.get(window.windowIndex) === window.chunkHash);
|
|
165435
|
+
}
|
|
165436
|
+
function replaceCompartmentChunkEmbeddings(db, rows) {
|
|
165437
|
+
if (rows.length === 0)
|
|
165438
|
+
return;
|
|
165439
|
+
const compartmentId = rows[0].compartmentId;
|
|
165440
|
+
const now = Date.now();
|
|
165441
|
+
db.transaction(() => {
|
|
165442
|
+
getDeleteByCompartmentStatement(db).run(compartmentId);
|
|
165443
|
+
const insert = getInsertEmbeddingStatement(db);
|
|
165444
|
+
for (const row of rows) {
|
|
165445
|
+
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);
|
|
165446
|
+
}
|
|
165447
|
+
})();
|
|
165448
|
+
}
|
|
165449
|
+
function getDistinctChunkEmbeddingModelIds(db, projectPath) {
|
|
165450
|
+
const rows = getDistinctModelStatement(db).all(projectPath);
|
|
165451
|
+
return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
|
|
165452
|
+
}
|
|
165453
|
+
function clearChunkEmbeddingsForProject(db, projectPath, modelId) {
|
|
165454
|
+
if (modelId) {
|
|
165455
|
+
return getClearProjectModelStatement(db).run(projectPath, modelId).changes;
|
|
165456
|
+
}
|
|
165457
|
+
return getClearProjectStatement(db).run(projectPath).changes;
|
|
165458
|
+
}
|
|
165459
|
+
function loadCompartmentChunkEmbeddingsForSearch(db, sessionId, projectPath, modelId) {
|
|
165460
|
+
const rows = modelId ? getSearchRowsStatement(db, true).all(sessionId, projectPath, modelId) : getSearchRowsStatement(db, false).all(sessionId, projectPath);
|
|
165461
|
+
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) => ({
|
|
165462
|
+
compartmentId: row.compartmentId,
|
|
165463
|
+
sessionId: row.sessionId,
|
|
165464
|
+
title: row.title,
|
|
165465
|
+
startOrdinal: row.compartmentStart,
|
|
165466
|
+
endOrdinal: row.compartmentEnd,
|
|
165467
|
+
windowIndex: row.windowIndex,
|
|
165468
|
+
windowStartOrdinal: row.windowStart,
|
|
165469
|
+
windowEndOrdinal: row.windowEnd,
|
|
165470
|
+
chunkHash: row.chunkHash,
|
|
165471
|
+
modelId: row.modelId,
|
|
165472
|
+
dims: row.dims,
|
|
165473
|
+
vector: toFloat32Array2(row.vector)
|
|
165474
|
+
}));
|
|
165475
|
+
}
|
|
165476
|
+
function mapBackfillCandidateRows(rows) {
|
|
165477
|
+
return rows.filter((row) => {
|
|
165478
|
+
if (row === null || typeof row !== "object")
|
|
165479
|
+
return false;
|
|
165480
|
+
const candidate = row;
|
|
165481
|
+
return typeof candidate.id === "number" && typeof candidate.sessionId === "string" && typeof candidate.startMessage === "number" && typeof candidate.endMessage === "number" && typeof candidate.title === "string";
|
|
165482
|
+
}).map((row) => ({
|
|
165483
|
+
id: row.id,
|
|
165484
|
+
sessionId: row.sessionId,
|
|
165485
|
+
startMessage: row.startMessage,
|
|
165486
|
+
endMessage: row.endMessage,
|
|
165487
|
+
title: row.title
|
|
165488
|
+
}));
|
|
165489
|
+
}
|
|
165490
|
+
function loadUnembeddedSessionChunkCandidates(db, projectPath, sessionId, modelId, limit, excludeIds) {
|
|
165491
|
+
if (excludeIds && excludeIds.length > 0) {
|
|
165492
|
+
const placeholders3 = excludeIds.map(() => "?").join(", ");
|
|
165493
|
+
const stmt2 = db.prepare(`SELECT c.id AS id,
|
|
165494
|
+
c.session_id AS sessionId,
|
|
165495
|
+
c.start_message AS startMessage,
|
|
165496
|
+
c.end_message AS endMessage,
|
|
165497
|
+
c.title AS title
|
|
165498
|
+
FROM compartments c
|
|
165499
|
+
JOIN session_projects sp
|
|
165500
|
+
ON sp.session_id = c.session_id
|
|
165501
|
+
AND sp.harness = c.harness
|
|
165502
|
+
AND sp.project_path = ?
|
|
165503
|
+
WHERE c.session_id = ?
|
|
165504
|
+
AND c.start_message IS NOT NULL
|
|
165505
|
+
AND c.end_message IS NOT NULL
|
|
165506
|
+
AND c.id NOT IN (${placeholders3})
|
|
165507
|
+
AND NOT EXISTS (
|
|
165508
|
+
SELECT 1
|
|
165509
|
+
FROM compartment_chunk_embeddings current
|
|
165510
|
+
WHERE current.compartment_id = c.id
|
|
165511
|
+
AND current.project_path = ?
|
|
165512
|
+
AND current.model_id = ?
|
|
165513
|
+
)
|
|
165514
|
+
ORDER BY c.start_message ASC, c.id ASC
|
|
165515
|
+
LIMIT ?`);
|
|
165516
|
+
const rows2 = stmt2.all(projectPath, sessionId, ...excludeIds, projectPath, modelId, Math.max(1, limit));
|
|
165517
|
+
return mapBackfillCandidateRows(rows2);
|
|
165518
|
+
}
|
|
165519
|
+
let stmt = sessionBackfillCandidateStatements.get(db);
|
|
165520
|
+
if (!stmt) {
|
|
165521
|
+
stmt = db.prepare(`SELECT c.id AS id,
|
|
165522
|
+
c.session_id AS sessionId,
|
|
165523
|
+
c.start_message AS startMessage,
|
|
165524
|
+
c.end_message AS endMessage,
|
|
165525
|
+
c.title AS title
|
|
165526
|
+
FROM compartments c
|
|
165527
|
+
JOIN session_projects sp
|
|
165528
|
+
ON sp.session_id = c.session_id
|
|
165529
|
+
AND sp.harness = c.harness
|
|
165530
|
+
AND sp.project_path = ?
|
|
165531
|
+
WHERE c.session_id = ?
|
|
165532
|
+
AND c.start_message IS NOT NULL
|
|
165533
|
+
AND c.end_message IS NOT NULL
|
|
165534
|
+
AND NOT EXISTS (
|
|
165535
|
+
SELECT 1
|
|
165536
|
+
FROM compartment_chunk_embeddings current
|
|
165537
|
+
WHERE current.compartment_id = c.id
|
|
165538
|
+
AND current.project_path = ?
|
|
165539
|
+
AND current.model_id = ?
|
|
165540
|
+
)
|
|
165541
|
+
ORDER BY c.start_message ASC, c.id ASC
|
|
165542
|
+
LIMIT ?`);
|
|
165543
|
+
sessionBackfillCandidateStatements.set(db, stmt);
|
|
165544
|
+
}
|
|
165545
|
+
const rows = stmt.all(projectPath, sessionId, projectPath, modelId, Math.max(1, limit));
|
|
165546
|
+
return mapBackfillCandidateRows(rows);
|
|
165547
|
+
}
|
|
165548
|
+
function countUnembeddedSessionCompartments(db, projectPath, sessionId, modelId) {
|
|
165549
|
+
const row = db.prepare(`SELECT COUNT(*) AS n
|
|
165550
|
+
FROM compartments c
|
|
165551
|
+
JOIN session_projects sp
|
|
165552
|
+
ON sp.session_id = c.session_id
|
|
165553
|
+
AND sp.harness = c.harness
|
|
165554
|
+
AND sp.project_path = ?
|
|
165555
|
+
WHERE c.session_id = ?
|
|
165556
|
+
AND c.start_message IS NOT NULL
|
|
165557
|
+
AND c.end_message IS NOT NULL
|
|
165558
|
+
AND NOT EXISTS (
|
|
165559
|
+
SELECT 1
|
|
165560
|
+
FROM compartment_chunk_embeddings current
|
|
165561
|
+
WHERE current.compartment_id = c.id
|
|
165562
|
+
AND current.project_path = ?
|
|
165563
|
+
AND current.model_id = ?
|
|
165564
|
+
)`).get(projectPath, sessionId, projectPath, modelId);
|
|
165565
|
+
return typeof row?.n === "number" ? row.n : 0;
|
|
165566
|
+
}
|
|
165567
|
+
var DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS = 512, loadFtsRowsStatements, existingHashStatements, existingHashByProjectStatements, deleteByCompartmentStatements, insertEmbeddingStatements, distinctModelStatements, clearProjectStatements, clearProjectModelStatements, searchRowsStatements, searchRowsByModelStatements, backfillCandidateStatements, sessionBackfillCandidateStatements;
|
|
165568
|
+
var init_compartment_chunk_embedding = __esm(() => {
|
|
165569
|
+
init_read_session_formatting();
|
|
165570
|
+
loadFtsRowsStatements = new WeakMap;
|
|
165571
|
+
existingHashStatements = new WeakMap;
|
|
165572
|
+
existingHashByProjectStatements = new WeakMap;
|
|
165573
|
+
deleteByCompartmentStatements = new WeakMap;
|
|
165574
|
+
insertEmbeddingStatements = new WeakMap;
|
|
165575
|
+
distinctModelStatements = new WeakMap;
|
|
165576
|
+
clearProjectStatements = new WeakMap;
|
|
165577
|
+
clearProjectModelStatements = new WeakMap;
|
|
165578
|
+
searchRowsStatements = new WeakMap;
|
|
165579
|
+
searchRowsByModelStatements = new WeakMap;
|
|
165580
|
+
backfillCandidateStatements = new WeakMap;
|
|
165581
|
+
sessionBackfillCandidateStatements = new WeakMap;
|
|
165582
|
+
});
|
|
165583
|
+
|
|
164478
165584
|
// src/features/magic-context/memory/cosine-similarity.ts
|
|
164479
165585
|
function cosineSimilarity(a, b) {
|
|
164480
165586
|
if (a.length !== b.length) {
|
|
@@ -164632,19 +165738,19 @@ function isArrayLikeNumber(value) {
|
|
|
164632
165738
|
}
|
|
164633
165739
|
return arr.length === 0 || typeof arr[0] === "number";
|
|
164634
165740
|
}
|
|
164635
|
-
function
|
|
165741
|
+
function toFloat32Array3(values) {
|
|
164636
165742
|
return values instanceof Float32Array ? new Float32Array(values) : Float32Array.from(Array.from(values));
|
|
164637
165743
|
}
|
|
164638
165744
|
function extractBatchEmbeddings(result, expectedCount) {
|
|
164639
165745
|
const { data } = result;
|
|
164640
165746
|
if (Array.isArray(data) && data.length === expectedCount && data.every((entry) => typeof entry !== "number" && isArrayLikeNumber(entry))) {
|
|
164641
|
-
return data.map((entry) =>
|
|
165747
|
+
return data.map((entry) => toFloat32Array3(entry));
|
|
164642
165748
|
}
|
|
164643
165749
|
if (!isArrayLikeNumber(data)) {
|
|
164644
165750
|
log("[magic-context] embedding batch returned unexpected data shape");
|
|
164645
165751
|
return Array.from({ length: expectedCount }, () => null);
|
|
164646
165752
|
}
|
|
164647
|
-
const flatData =
|
|
165753
|
+
const flatData = toFloat32Array3(data);
|
|
164648
165754
|
const dimension = result.dims?.at(-1) ?? flatData.length / expectedCount;
|
|
164649
165755
|
if (!Number.isInteger(dimension) || dimension <= 0 || flatData.length !== expectedCount * dimension) {
|
|
164650
165756
|
log("[magic-context] embedding batch returned invalid dimensions");
|
|
@@ -164659,6 +165765,7 @@ function extractBatchEmbeddings(result, expectedCount) {
|
|
|
164659
165765
|
|
|
164660
165766
|
class LocalEmbeddingProvider {
|
|
164661
165767
|
modelId;
|
|
165768
|
+
maxInputTokens;
|
|
164662
165769
|
model;
|
|
164663
165770
|
pipeline = null;
|
|
164664
165771
|
initPromise = null;
|
|
@@ -164666,8 +165773,9 @@ class LocalEmbeddingProvider {
|
|
|
164666
165773
|
disposing = false;
|
|
164667
165774
|
disposePromise = null;
|
|
164668
165775
|
inFlightWaiters = [];
|
|
164669
|
-
constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL) {
|
|
165776
|
+
constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512) {
|
|
164670
165777
|
this.model = model;
|
|
165778
|
+
this.maxInputTokens = maxInputTokens;
|
|
164671
165779
|
this.modelId = getEmbeddingProviderIdentity({ provider: "local", model });
|
|
164672
165780
|
}
|
|
164673
165781
|
async initialize() {
|
|
@@ -164927,6 +166035,7 @@ function normalizeEndpoint3(endpoint) {
|
|
|
164927
166035
|
|
|
164928
166036
|
class OpenAICompatibleEmbeddingProvider {
|
|
164929
166037
|
modelId;
|
|
166038
|
+
maxInputTokens;
|
|
164930
166039
|
endpoint;
|
|
164931
166040
|
model;
|
|
164932
166041
|
apiKey;
|
|
@@ -164943,11 +166052,13 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
164943
166052
|
this.apiKey = options.apiKey?.trim() ?? "";
|
|
164944
166053
|
this.inputType = options.inputType?.trim() ?? "";
|
|
164945
166054
|
this.truncate = options.truncate?.trim() ?? "";
|
|
166055
|
+
this.maxInputTokens = typeof options.maxInputTokens === "number" && Number.isFinite(options.maxInputTokens) ? Math.max(1, Math.floor(options.maxInputTokens)) : 512;
|
|
164946
166056
|
this.modelId = getEmbeddingProviderIdentity({
|
|
164947
166057
|
provider: "openai-compatible",
|
|
164948
166058
|
endpoint: this.endpoint,
|
|
164949
166059
|
model: this.model,
|
|
164950
|
-
...this.apiKey ? { api_key: this.apiKey } : {}
|
|
166060
|
+
...this.apiKey ? { api_key: this.apiKey } : {},
|
|
166061
|
+
...this.inputType ? { input_type: this.inputType } : {}
|
|
164951
166062
|
});
|
|
164952
166063
|
}
|
|
164953
166064
|
async initialize() {
|
|
@@ -165191,12 +166302,12 @@ function getCountEmbeddedStatement(db) {
|
|
|
165191
166302
|
}
|
|
165192
166303
|
return stmt;
|
|
165193
166304
|
}
|
|
165194
|
-
function
|
|
165195
|
-
let stmt =
|
|
166305
|
+
function getClearProjectStatement2(db) {
|
|
166306
|
+
let stmt = clearProjectStatements2.get(db);
|
|
165196
166307
|
if (!stmt) {
|
|
165197
166308
|
stmt = db.prepare(`DELETE FROM git_commit_embeddings
|
|
165198
166309
|
WHERE sha IN (SELECT sha FROM git_commits WHERE project_path = ?)`);
|
|
165199
|
-
|
|
166310
|
+
clearProjectStatements2.set(db, stmt);
|
|
165200
166311
|
}
|
|
165201
166312
|
return stmt;
|
|
165202
166313
|
}
|
|
@@ -165232,19 +166343,19 @@ function countEmbeddedCommits(db, projectPath) {
|
|
|
165232
166343
|
return row?.count ?? 0;
|
|
165233
166344
|
}
|
|
165234
166345
|
function clearProjectCommitEmbeddings(db, projectPath) {
|
|
165235
|
-
return
|
|
166346
|
+
return getClearProjectStatement2(db).run(projectPath).changes;
|
|
165236
166347
|
}
|
|
165237
166348
|
function getDistinctCommitEmbeddingModelIds(db, projectPath) {
|
|
165238
166349
|
const rows = getDistinctModelIdStatement(db).all(projectPath);
|
|
165239
166350
|
return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
|
|
165240
166351
|
}
|
|
165241
|
-
var saveStatements, loadProjectStatements, loadUnembeddedStatements, countEmbeddedStatements,
|
|
166352
|
+
var saveStatements, loadProjectStatements, loadUnembeddedStatements, countEmbeddedStatements, clearProjectStatements2, distinctModelIdStatements;
|
|
165242
166353
|
var init_storage_git_commit_embeddings = __esm(() => {
|
|
165243
166354
|
saveStatements = new WeakMap;
|
|
165244
166355
|
loadProjectStatements = new WeakMap;
|
|
165245
166356
|
loadUnembeddedStatements = new WeakMap;
|
|
165246
166357
|
countEmbeddedStatements = new WeakMap;
|
|
165247
|
-
|
|
166358
|
+
clearProjectStatements2 = new WeakMap;
|
|
165248
166359
|
distinctModelIdStatements = new WeakMap;
|
|
165249
166360
|
});
|
|
165250
166361
|
|
|
@@ -165370,13 +166481,90 @@ var init_sweep_coordinator = __esm(() => {
|
|
|
165370
166481
|
GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
|
|
165371
166482
|
});
|
|
165372
166483
|
|
|
166484
|
+
// src/features/magic-context/session-project-storage.ts
|
|
166485
|
+
function getUpsertSessionProjectStatement(db) {
|
|
166486
|
+
let stmt = upsertSessionProjectStatements.get(db);
|
|
166487
|
+
if (!stmt) {
|
|
166488
|
+
stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
|
|
166489
|
+
VALUES (?, ?, ?, ?)
|
|
166490
|
+
ON CONFLICT(session_id, harness) DO UPDATE SET
|
|
166491
|
+
project_path = excluded.project_path,
|
|
166492
|
+
updated_at = excluded.updated_at
|
|
166493
|
+
WHERE session_projects.project_path <> excluded.project_path`);
|
|
166494
|
+
upsertSessionProjectStatements.set(db, stmt);
|
|
166495
|
+
}
|
|
166496
|
+
return stmt;
|
|
166497
|
+
}
|
|
166498
|
+
function getRepairSessionChunkProjectStatement(db) {
|
|
166499
|
+
let stmt = repairSessionChunkProjectStatements.get(db);
|
|
166500
|
+
if (!stmt) {
|
|
166501
|
+
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
166502
|
+
SET project_path = ?
|
|
166503
|
+
WHERE session_id = ?
|
|
166504
|
+
AND harness = ?
|
|
166505
|
+
AND project_path <> ?`);
|
|
166506
|
+
repairSessionChunkProjectStatements.set(db, stmt);
|
|
166507
|
+
}
|
|
166508
|
+
return stmt;
|
|
166509
|
+
}
|
|
166510
|
+
function getRepairProjectChunkProjectStatement(db) {
|
|
166511
|
+
let stmt = repairProjectChunkProjectStatements.get(db);
|
|
166512
|
+
if (!stmt) {
|
|
166513
|
+
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
166514
|
+
SET project_path = (
|
|
166515
|
+
SELECT sp.project_path
|
|
166516
|
+
FROM session_projects sp
|
|
166517
|
+
WHERE sp.session_id = compartment_chunk_embeddings.session_id
|
|
166518
|
+
AND sp.harness = compartment_chunk_embeddings.harness
|
|
166519
|
+
LIMIT 1
|
|
166520
|
+
)
|
|
166521
|
+
WHERE EXISTS (
|
|
166522
|
+
SELECT 1
|
|
166523
|
+
FROM session_projects sp
|
|
166524
|
+
WHERE sp.session_id = compartment_chunk_embeddings.session_id
|
|
166525
|
+
AND sp.harness = compartment_chunk_embeddings.harness
|
|
166526
|
+
AND sp.project_path <> compartment_chunk_embeddings.project_path
|
|
166527
|
+
AND (
|
|
166528
|
+
sp.project_path = ?
|
|
166529
|
+
OR compartment_chunk_embeddings.project_path = ?
|
|
166530
|
+
)
|
|
166531
|
+
)`);
|
|
166532
|
+
repairProjectChunkProjectStatements.set(db, stmt);
|
|
166533
|
+
}
|
|
166534
|
+
return stmt;
|
|
166535
|
+
}
|
|
166536
|
+
function recordSessionProjectIdentity(db, sessionId, projectPath) {
|
|
166537
|
+
if (!sessionId || !projectPath)
|
|
166538
|
+
return;
|
|
166539
|
+
const harness = getHarness();
|
|
166540
|
+
const now = Date.now();
|
|
166541
|
+
db.transaction(() => {
|
|
166542
|
+
getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
|
|
166543
|
+
getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
|
|
166544
|
+
})();
|
|
166545
|
+
}
|
|
166546
|
+
function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
|
|
166547
|
+
if (!projectPath)
|
|
166548
|
+
return 0;
|
|
166549
|
+
return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
|
|
166550
|
+
}
|
|
166551
|
+
var upsertSessionProjectStatements, repairSessionChunkProjectStatements, repairProjectChunkProjectStatements;
|
|
166552
|
+
var init_session_project_storage = __esm(() => {
|
|
166553
|
+
upsertSessionProjectStatements = new WeakMap;
|
|
166554
|
+
repairSessionChunkProjectStatements = new WeakMap;
|
|
166555
|
+
repairProjectChunkProjectStatements = new WeakMap;
|
|
166556
|
+
});
|
|
166557
|
+
|
|
165373
166558
|
// src/features/magic-context/project-embedding-registry.ts
|
|
165374
|
-
import { createHash as
|
|
166559
|
+
import { createHash as createHash9, randomUUID } from "node:crypto";
|
|
165375
166560
|
function resolveEmbeddingConfig(config2) {
|
|
165376
166561
|
if (!config2 || config2.provider === "local") {
|
|
165377
166562
|
return {
|
|
165378
166563
|
provider: "local",
|
|
165379
|
-
model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
166564
|
+
model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
166565
|
+
...config2?.max_input_tokens ? {
|
|
166566
|
+
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
166567
|
+
} : {}
|
|
165380
166568
|
};
|
|
165381
166569
|
}
|
|
165382
166570
|
if (config2.provider === "openai-compatible") {
|
|
@@ -165389,7 +166577,10 @@ function resolveEmbeddingConfig(config2) {
|
|
|
165389
166577
|
endpoint: config2.endpoint.trim(),
|
|
165390
166578
|
...apiKey ? { api_key: apiKey } : {},
|
|
165391
166579
|
...inputType ? { input_type: inputType } : {},
|
|
165392
|
-
...truncate ? { truncate } : {}
|
|
166580
|
+
...truncate ? { truncate } : {},
|
|
166581
|
+
...config2.max_input_tokens ? {
|
|
166582
|
+
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
166583
|
+
} : {}
|
|
165393
166584
|
};
|
|
165394
166585
|
}
|
|
165395
166586
|
return { provider: "off" };
|
|
@@ -165407,10 +166598,11 @@ function createProvider(config2) {
|
|
|
165407
166598
|
model: config2.model,
|
|
165408
166599
|
apiKey: config2.api_key,
|
|
165409
166600
|
inputType: config2.input_type,
|
|
165410
|
-
truncate: config2.truncate
|
|
166601
|
+
truncate: config2.truncate,
|
|
166602
|
+
maxInputTokens: config2.max_input_tokens
|
|
165411
166603
|
});
|
|
165412
166604
|
}
|
|
165413
|
-
return new LocalEmbeddingProvider(config2.model);
|
|
166605
|
+
return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
|
|
165414
166606
|
}
|
|
165415
166607
|
function stableStringify2(value) {
|
|
165416
166608
|
if (Array.isArray(value)) {
|
|
@@ -165423,7 +166615,7 @@ function stableStringify2(value) {
|
|
|
165423
166615
|
return JSON.stringify(value);
|
|
165424
166616
|
}
|
|
165425
166617
|
function sha256Prefix(value, length = 16) {
|
|
165426
|
-
return
|
|
166618
|
+
return createHash9("sha256").update(value).digest("hex").slice(0, length);
|
|
165427
166619
|
}
|
|
165428
166620
|
function getRuntimeFingerprint(config2) {
|
|
165429
166621
|
if (config2.provider === "off") {
|
|
@@ -165431,6 +166623,18 @@ function getRuntimeFingerprint(config2) {
|
|
|
165431
166623
|
}
|
|
165432
166624
|
return `${getEmbeddingProviderIdentity(config2)}:${sha256Prefix(stableStringify2(config2))}`;
|
|
165433
166625
|
}
|
|
166626
|
+
function getChunkEmbeddingModelId(config2, providerIdentity) {
|
|
166627
|
+
if (config2.provider === "off") {
|
|
166628
|
+
return OFF_PROVIDER_IDENTITY;
|
|
166629
|
+
}
|
|
166630
|
+
const chunkIdentity = {
|
|
166631
|
+
providerIdentity,
|
|
166632
|
+
chunkerVersion: 1,
|
|
166633
|
+
maxInputTokens: normalizeCompartmentChunkMaxInputTokens("max_input_tokens" in config2 ? config2.max_input_tokens : undefined),
|
|
166634
|
+
truncate: config2.provider === "openai-compatible" ? config2.truncate ?? "" : ""
|
|
166635
|
+
};
|
|
166636
|
+
return `${providerIdentity}:chunk:${sha256Prefix(stableStringify2(chunkIdentity))}`;
|
|
166637
|
+
}
|
|
165434
166638
|
function sameFeatures(a, b) {
|
|
165435
166639
|
return a.memoryEnabled === b.memoryEnabled && a.gitCommitEnabled === b.gitCommitEnabled;
|
|
165436
166640
|
}
|
|
@@ -165447,7 +166651,8 @@ function snapshotFor(registration) {
|
|
|
165447
166651
|
features: { ...registration.features },
|
|
165448
166652
|
enabled,
|
|
165449
166653
|
gitCommitEnabled,
|
|
165450
|
-
modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId
|
|
166654
|
+
modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
|
|
166655
|
+
chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId
|
|
165451
166656
|
};
|
|
165452
166657
|
}
|
|
165453
166658
|
function disposeProvider(provider) {
|
|
@@ -165467,7 +166672,7 @@ function anyStoredModelIdIsStale(storedIds, currentId) {
|
|
|
165467
166672
|
}
|
|
165468
166673
|
return false;
|
|
165469
166674
|
}
|
|
165470
|
-
function maybeWipeStaleEmbeddings(db, projectIdentity, currentProviderIdentity, features) {
|
|
166675
|
+
function maybeWipeStaleEmbeddings(db, projectIdentity, currentProviderIdentity, currentChunkIdentity, features) {
|
|
165471
166676
|
if (currentProviderIdentity === OFF_PROVIDER_IDENTITY) {
|
|
165472
166677
|
return false;
|
|
165473
166678
|
}
|
|
@@ -165488,6 +166693,14 @@ function maybeWipeStaleEmbeddings(db, projectIdentity, currentProviderIdentity,
|
|
|
165488
166693
|
wiped = true;
|
|
165489
166694
|
}
|
|
165490
166695
|
}
|
|
166696
|
+
if (features.memoryEnabled) {
|
|
166697
|
+
repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectIdentity);
|
|
166698
|
+
const chunkIds = getDistinctChunkEmbeddingModelIds(db, projectIdentity);
|
|
166699
|
+
if (anyStoredModelIdIsStale(chunkIds, currentChunkIdentity)) {
|
|
166700
|
+
clearChunkEmbeddingsForProject(db, projectIdentity);
|
|
166701
|
+
wiped = true;
|
|
166702
|
+
}
|
|
166703
|
+
}
|
|
165491
166704
|
})();
|
|
165492
166705
|
return wiped;
|
|
165493
166706
|
}
|
|
@@ -165495,10 +166708,11 @@ function registerProjectEmbeddingAndMaybeWipe(db, projectIdentity, config2, feat
|
|
|
165495
166708
|
const resolvedConfig = resolveEmbeddingConfig(config2);
|
|
165496
166709
|
const providerIdentity = getEmbeddingProviderIdentity(resolvedConfig);
|
|
165497
166710
|
const runtimeFingerprint = getRuntimeFingerprint(resolvedConfig);
|
|
166711
|
+
const chunkModelId = getChunkEmbeddingModelId(resolvedConfig, providerIdentity);
|
|
165498
166712
|
const prior = projectRegistrations.get(projectIdentity);
|
|
165499
166713
|
const canReuseProvider = prior !== undefined && !prior.observationMode && prior.runtimeFingerprint === runtimeFingerprint && prior.providerIdentity === providerIdentity;
|
|
165500
|
-
const wiped = maybeWipeStaleEmbeddings(db, projectIdentity, providerIdentity, features);
|
|
165501
|
-
const generationChanged = prior === undefined || prior.observationMode || prior.runtimeFingerprint !== runtimeFingerprint || !sameFeatures(prior.features, features) || wiped;
|
|
166714
|
+
const wiped = maybeWipeStaleEmbeddings(db, projectIdentity, providerIdentity, chunkModelId, features);
|
|
166715
|
+
const generationChanged = prior === undefined || prior.observationMode || prior.runtimeFingerprint !== runtimeFingerprint || prior.chunkModelId !== chunkModelId || !sameFeatures(prior.features, features) || wiped;
|
|
165502
166716
|
const generation = generationChanged ? ++globalRegistrationGeneration : prior.generation;
|
|
165503
166717
|
const registration = {
|
|
165504
166718
|
projectIdentity,
|
|
@@ -165510,6 +166724,7 @@ function registerProjectEmbeddingAndMaybeWipe(db, projectIdentity, config2, feat
|
|
|
165510
166724
|
generation,
|
|
165511
166725
|
features: { ...features },
|
|
165512
166726
|
modelId: providerIdentity === OFF_PROVIDER_IDENTITY ? "off" : providerIdentity,
|
|
166727
|
+
chunkModelId: providerIdentity === OFF_PROVIDER_IDENTITY ? "off" : chunkModelId,
|
|
165513
166728
|
observationMode: false
|
|
165514
166729
|
};
|
|
165515
166730
|
projectRegistrations.set(projectIdentity, registration);
|
|
@@ -165532,6 +166747,7 @@ function registerProjectInObservationMode(db, projectIdentity, sourceDirectory,
|
|
|
165532
166747
|
generation,
|
|
165533
166748
|
features: { memoryEnabled: false, gitCommitEnabled: false },
|
|
165534
166749
|
modelId: "off",
|
|
166750
|
+
chunkModelId: "off",
|
|
165535
166751
|
observationMode: true
|
|
165536
166752
|
};
|
|
165537
166753
|
projectRegistrations.set(projectIdentity, registration);
|
|
@@ -165542,6 +166758,15 @@ function getProjectEmbeddingSnapshot(projectIdentity) {
|
|
|
165542
166758
|
const registration = projectRegistrations.get(projectIdentity);
|
|
165543
166759
|
return registration ? snapshotFor(registration) : null;
|
|
165544
166760
|
}
|
|
166761
|
+
function getProjectChunkEmbeddingModelId(projectIdentity) {
|
|
166762
|
+
const registration = projectRegistrations.get(projectIdentity);
|
|
166763
|
+
return registration && !registration.observationMode ? registration.chunkModelId : "off";
|
|
166764
|
+
}
|
|
166765
|
+
function getProjectEmbeddingMaxInputTokens(projectIdentity) {
|
|
166766
|
+
const registration = projectRegistrations.get(projectIdentity);
|
|
166767
|
+
const configMax = registration?.config && "max_input_tokens" in registration.config ? registration.config.max_input_tokens : undefined;
|
|
166768
|
+
return normalizeCompartmentChunkMaxInputTokens(registration?.provider?.maxInputTokens ?? configMax);
|
|
166769
|
+
}
|
|
165545
166770
|
function getOrCreateProjectProvider(registration) {
|
|
165546
166771
|
if (registration.providerIdentity === OFF_PROVIDER_IDENTITY || registration.observationMode) {
|
|
165547
166772
|
return null;
|
|
@@ -165636,10 +166861,136 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
|
|
|
165636
166861
|
return 0;
|
|
165637
166862
|
}
|
|
165638
166863
|
}
|
|
165639
|
-
|
|
166864
|
+
async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates, signal) {
|
|
166865
|
+
const noWork = [];
|
|
166866
|
+
if (candidates.length === 0)
|
|
166867
|
+
return { embedded: 0, noWork };
|
|
166868
|
+
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
|
|
166869
|
+
const prepared = [];
|
|
166870
|
+
for (const candidate of candidates) {
|
|
166871
|
+
const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage);
|
|
166872
|
+
if (canonicalText.length === 0) {
|
|
166873
|
+
noWork.push(candidate.id);
|
|
166874
|
+
continue;
|
|
166875
|
+
}
|
|
166876
|
+
const windows = chunkCanonicalText(canonicalText, candidate.startMessage, candidate.endMessage, maxInputTokens);
|
|
166877
|
+
if (windows.length === 0 || chunkEmbeddingWindowsAreCurrent(db, candidate.id, modelId, windows, projectIdentity)) {
|
|
166878
|
+
noWork.push(candidate.id);
|
|
166879
|
+
continue;
|
|
166880
|
+
}
|
|
166881
|
+
prepared.push({ candidate, windows });
|
|
166882
|
+
}
|
|
166883
|
+
if (prepared.length === 0)
|
|
166884
|
+
return { embedded: 0, noWork };
|
|
166885
|
+
let embedded = 0;
|
|
166886
|
+
let i = 0;
|
|
166887
|
+
while (i < prepared.length) {
|
|
166888
|
+
if (signal?.aborted)
|
|
166889
|
+
break;
|
|
166890
|
+
const slice = [];
|
|
166891
|
+
let windowCount = 0;
|
|
166892
|
+
do {
|
|
166893
|
+
const item = prepared[i];
|
|
166894
|
+
slice.push(item);
|
|
166895
|
+
windowCount += item.windows.length;
|
|
166896
|
+
i += 1;
|
|
166897
|
+
} while (i < prepared.length && windowCount + prepared[i].windows.length <= MAX_WINDOWS_PER_EMBED_CALL);
|
|
166898
|
+
const texts = [];
|
|
166899
|
+
for (const item of slice)
|
|
166900
|
+
texts.push(...item.windows.map((w) => w.text));
|
|
166901
|
+
try {
|
|
166902
|
+
const result = await embedBatchForProject(projectIdentity, texts, signal);
|
|
166903
|
+
if (!result)
|
|
166904
|
+
continue;
|
|
166905
|
+
if (signal?.aborted)
|
|
166906
|
+
break;
|
|
166907
|
+
let offset = 0;
|
|
166908
|
+
for (const item of slice) {
|
|
166909
|
+
const vectors = result.vectors.slice(offset, offset + item.windows.length);
|
|
166910
|
+
offset += item.windows.length;
|
|
166911
|
+
if (vectors.length !== item.windows.length || vectors.some((v) => !v)) {
|
|
166912
|
+
continue;
|
|
166913
|
+
}
|
|
166914
|
+
const rows = item.windows.map((window, index) => ({
|
|
166915
|
+
compartmentId: item.candidate.id,
|
|
166916
|
+
sessionId: item.candidate.sessionId,
|
|
166917
|
+
projectPath: projectIdentity,
|
|
166918
|
+
window,
|
|
166919
|
+
modelId,
|
|
166920
|
+
vector: vectors[index]
|
|
166921
|
+
}));
|
|
166922
|
+
replaceCompartmentChunkEmbeddings(db, rows);
|
|
166923
|
+
embedded += 1;
|
|
166924
|
+
}
|
|
166925
|
+
} catch (error51) {
|
|
166926
|
+
log("[magic-context] failed to proactively embed compartment chunks:", error51);
|
|
166927
|
+
}
|
|
166928
|
+
}
|
|
166929
|
+
return { embedded, noWork };
|
|
166930
|
+
}
|
|
166931
|
+
async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, options) {
|
|
166932
|
+
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
166933
|
+
if (!snapshot?.enabled || snapshot.chunkModelId === "off") {
|
|
166934
|
+
return { status: "disabled", embedded: 0, total: 0 };
|
|
166935
|
+
}
|
|
166936
|
+
recordSessionProjectIdentity(db, sessionId, projectIdentity);
|
|
166937
|
+
const total = countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot.chunkModelId);
|
|
166938
|
+
if (total === 0)
|
|
166939
|
+
return { status: "nothing", embedded: 0, total: 0 };
|
|
166940
|
+
const holderId = `session-embed-${randomUUID()}`;
|
|
166941
|
+
const lease2 = acquireGitSweepLease(db, projectIdentity, holderId, { ignoreCooldown: true });
|
|
166942
|
+
if (!lease2.acquired)
|
|
166943
|
+
return { status: "busy", embedded: 0, total };
|
|
166944
|
+
const renewal = setInterval(() => {
|
|
166945
|
+
try {
|
|
166946
|
+
renewGitSweepLease(db, projectIdentity, holderId);
|
|
166947
|
+
} catch {}
|
|
166948
|
+
}, SESSION_EMBED_LEASE_RENEWAL_MS);
|
|
166949
|
+
renewal.unref?.();
|
|
166950
|
+
const batchSize = Math.max(1, options?.batchSize ?? CHUNK_DRAIN_BATCH_SIZE);
|
|
166951
|
+
const skipIds = [];
|
|
166952
|
+
let embedded = 0;
|
|
166953
|
+
let aborted2 = false;
|
|
166954
|
+
let providerStalled = false;
|
|
166955
|
+
try {
|
|
166956
|
+
options?.onProgress?.({ embedded, total });
|
|
166957
|
+
for (;; ) {
|
|
166958
|
+
if (options?.signal?.aborted) {
|
|
166959
|
+
aborted2 = true;
|
|
166960
|
+
break;
|
|
166961
|
+
}
|
|
166962
|
+
const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, skipIds);
|
|
166963
|
+
if (candidates.length === 0)
|
|
166964
|
+
break;
|
|
166965
|
+
const { embedded: n, noWork } = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, options?.signal);
|
|
166966
|
+
for (const id of noWork)
|
|
166967
|
+
skipIds.push(id);
|
|
166968
|
+
if (n === 0 && noWork.length === 0) {
|
|
166969
|
+
providerStalled = true;
|
|
166970
|
+
break;
|
|
166971
|
+
}
|
|
166972
|
+
embedded += n;
|
|
166973
|
+
options?.onProgress?.({ embedded: Math.min(embedded, total), total });
|
|
166974
|
+
await new Promise((resolve7) => setTimeout(resolve7, 0));
|
|
166975
|
+
}
|
|
166976
|
+
} finally {
|
|
166977
|
+
clearInterval(renewal);
|
|
166978
|
+
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
166979
|
+
}
|
|
166980
|
+
if (aborted2)
|
|
166981
|
+
return { status: "aborted", embedded, total };
|
|
166982
|
+
if (providerStalled) {
|
|
166983
|
+
const remaining = Math.max(0, countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot.chunkModelId) - skipIds.length);
|
|
166984
|
+
if (remaining > 0)
|
|
166985
|
+
return { status: "stalled", embedded, total, remaining };
|
|
166986
|
+
}
|
|
166987
|
+
return { status: "done", embedded, total };
|
|
166988
|
+
}
|
|
166989
|
+
var OFF_PROVIDER_IDENTITY = "embedding-provider:off", SWEEP_MAX_WALL_CLOCK_MS, CHUNK_DRAIN_BATCH_SIZE = 8, MAX_WINDOWS_PER_EMBED_CALL = 16, SESSION_EMBED_LEASE_RENEWAL_MS, projectRegistrations, loadUnembeddedMemoriesStatements, globalRegistrationGeneration = 0, testProviderFactory = null;
|
|
165640
166990
|
var init_project_embedding_registry = __esm(() => {
|
|
165641
166991
|
init_magic_context();
|
|
165642
166992
|
init_logger();
|
|
166993
|
+
init_compartment_chunk_embedding();
|
|
165643
166994
|
init_storage_git_commit_embeddings();
|
|
165644
166995
|
init_sweep_coordinator();
|
|
165645
166996
|
init_embedding_cache();
|
|
@@ -165647,7 +166998,9 @@ var init_project_embedding_registry = __esm(() => {
|
|
|
165647
166998
|
init_embedding_local();
|
|
165648
166999
|
init_embedding_openai();
|
|
165649
167000
|
init_storage_memory_embeddings();
|
|
167001
|
+
init_session_project_storage();
|
|
165650
167002
|
SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
|
|
167003
|
+
SESSION_EMBED_LEASE_RENEWAL_MS = 60 * 1000;
|
|
165651
167004
|
projectRegistrations = new Map;
|
|
165652
167005
|
loadUnembeddedMemoriesStatements = new WeakMap;
|
|
165653
167006
|
});
|
|
@@ -165663,10 +167016,11 @@ function createProvider2(config2) {
|
|
|
165663
167016
|
model: config2.model,
|
|
165664
167017
|
apiKey: config2.api_key,
|
|
165665
167018
|
inputType: config2.input_type,
|
|
165666
|
-
truncate: config2.truncate
|
|
167019
|
+
truncate: config2.truncate,
|
|
167020
|
+
maxInputTokens: config2.max_input_tokens
|
|
165667
167021
|
});
|
|
165668
167022
|
}
|
|
165669
|
-
return new LocalEmbeddingProvider(config2.model);
|
|
167023
|
+
return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
|
|
165670
167024
|
}
|
|
165671
167025
|
function getOrCreateProvider() {
|
|
165672
167026
|
if (provider) {
|
|
@@ -165692,6 +167046,7 @@ var DEFAULT_EMBEDDING_CONFIG, embeddingConfig, provider = null, loadUnembeddedMe
|
|
|
165692
167046
|
var init_embedding = __esm(() => {
|
|
165693
167047
|
init_magic_context();
|
|
165694
167048
|
init_logger();
|
|
167049
|
+
init_compartment_chunk_embedding();
|
|
165695
167050
|
init_embedding_identity();
|
|
165696
167051
|
init_embedding_local();
|
|
165697
167052
|
init_embedding_openai();
|
|
@@ -165715,6 +167070,23 @@ function getSearchStatement(db) {
|
|
|
165715
167070
|
}
|
|
165716
167071
|
return stmt;
|
|
165717
167072
|
}
|
|
167073
|
+
function getUnionSearchStatement(db, arity) {
|
|
167074
|
+
let statements = unionSearchStatements.get(arity);
|
|
167075
|
+
if (!statements) {
|
|
167076
|
+
statements = new WeakMap;
|
|
167077
|
+
unionSearchStatements.set(arity, statements);
|
|
167078
|
+
}
|
|
167079
|
+
let stmt = statements.get(db);
|
|
167080
|
+
if (!stmt) {
|
|
167081
|
+
const placeholders3 = Array.from({ length: arity }, () => "?").join(", ");
|
|
167082
|
+
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 ?`);
|
|
167083
|
+
statements.set(db, stmt);
|
|
167084
|
+
}
|
|
167085
|
+
return stmt;
|
|
167086
|
+
}
|
|
167087
|
+
function uniqueProjectPaths2(projectPaths) {
|
|
167088
|
+
return [...new Set(projectPaths.filter((path6) => path6.length > 0))];
|
|
167089
|
+
}
|
|
165718
167090
|
function sanitizeFtsQuery(query) {
|
|
165719
167091
|
const tokens = query.split(/\s+/).filter((token) => token.length > 0);
|
|
165720
167092
|
if (tokens.length === 0)
|
|
@@ -165733,10 +167105,33 @@ function searchMemoriesFTS(db, projectPath, query, limit = DEFAULT_SEARCH_LIMIT)
|
|
|
165733
167105
|
const rows = getSearchStatement(db).all(projectPath, Date.now(), sanitized, limit).filter(isMemoryRow);
|
|
165734
167106
|
return rows.map(toMemory);
|
|
165735
167107
|
}
|
|
165736
|
-
|
|
167108
|
+
function searchMemoriesFTSUnion(db, projectPaths, query, limit = DEFAULT_SEARCH_LIMIT, ownIdentities, shareCategories) {
|
|
167109
|
+
const identities = uniqueProjectPaths2(projectPaths);
|
|
167110
|
+
if (identities.length === 0)
|
|
167111
|
+
return [];
|
|
167112
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
167113
|
+
identities,
|
|
167114
|
+
ownIdentities,
|
|
167115
|
+
shareCategories,
|
|
167116
|
+
tableName: "memories"
|
|
167117
|
+
});
|
|
167118
|
+
if (identities.length === 1 && !sharingFilter.active) {
|
|
167119
|
+
return searchMemoriesFTS(db, identities[0], query, limit);
|
|
167120
|
+
}
|
|
167121
|
+
const trimmedQuery = query.trim();
|
|
167122
|
+
if (trimmedQuery.length === 0 || limit <= 0)
|
|
167123
|
+
return [];
|
|
167124
|
+
const sanitized = sanitizeFtsQuery(trimmedQuery);
|
|
167125
|
+
if (sanitized.length === 0)
|
|
167126
|
+
return [];
|
|
167127
|
+
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);
|
|
167128
|
+
return rows.map(toMemory);
|
|
167129
|
+
}
|
|
167130
|
+
var DEFAULT_SEARCH_LIMIT = 10, searchStatements, unionSearchStatements;
|
|
165737
167131
|
var init_storage_memory_fts = __esm(() => {
|
|
165738
167132
|
init_storage_memory();
|
|
165739
167133
|
searchStatements = new WeakMap;
|
|
167134
|
+
unionSearchStatements = new Map;
|
|
165740
167135
|
});
|
|
165741
167136
|
|
|
165742
167137
|
// src/shared/models-dev-cache.ts
|
|
@@ -165930,26 +167325,54 @@ var init_rpc_notifications = __esm(() => {
|
|
|
165930
167325
|
});
|
|
165931
167326
|
|
|
165932
167327
|
// src/features/magic-context/compartment-embedding.ts
|
|
165933
|
-
async function
|
|
167328
|
+
async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compartments) {
|
|
165934
167329
|
if (compartments.length === 0)
|
|
165935
167330
|
return;
|
|
165936
|
-
const
|
|
165937
|
-
for (const
|
|
165938
|
-
if (!c.p1 || c.p1.length === 0)
|
|
165939
|
-
continue;
|
|
167331
|
+
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectPath);
|
|
167332
|
+
for (const compartment of compartments) {
|
|
165940
167333
|
try {
|
|
165941
|
-
const
|
|
165942
|
-
|
|
165943
|
-
|
|
165944
|
-
|
|
167334
|
+
const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
|
|
167335
|
+
const canonicalText = fromMemory || buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage);
|
|
167336
|
+
if (canonicalText.length === 0)
|
|
167337
|
+
continue;
|
|
167338
|
+
const windows = chunkCanonicalText(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
|
|
167339
|
+
if (windows.length === 0)
|
|
167340
|
+
continue;
|
|
167341
|
+
const currentModelId = getProjectChunkEmbeddingModelId(projectPath);
|
|
167342
|
+
if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
|
|
167343
|
+
continue;
|
|
167344
|
+
}
|
|
167345
|
+
const result = await embedBatchForProject(projectPath, windows.map((window) => window.text));
|
|
167346
|
+
if (!result)
|
|
167347
|
+
continue;
|
|
167348
|
+
if (chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
|
|
167349
|
+
continue;
|
|
167350
|
+
}
|
|
167351
|
+
const rows = [];
|
|
167352
|
+
for (const [index, window] of windows.entries()) {
|
|
167353
|
+
const vector = result.vectors[index];
|
|
167354
|
+
if (!vector)
|
|
167355
|
+
continue;
|
|
167356
|
+
rows.push({
|
|
167357
|
+
compartmentId: compartment.id,
|
|
167358
|
+
sessionId,
|
|
167359
|
+
projectPath,
|
|
167360
|
+
window,
|
|
167361
|
+
modelId: currentModelId,
|
|
167362
|
+
vector
|
|
167363
|
+
});
|
|
167364
|
+
}
|
|
167365
|
+
if (rows.length === windows.length) {
|
|
167366
|
+
replaceCompartmentChunkEmbeddings(db, rows);
|
|
165945
167367
|
}
|
|
165946
167368
|
} catch (error51) {
|
|
165947
|
-
sessionLog(sessionId, `compartment embedding failed for compartment ${
|
|
167369
|
+
sessionLog(sessionId, `compartment chunk embedding failed for compartment ${compartment.id}:`, error51);
|
|
165948
167370
|
}
|
|
165949
167371
|
}
|
|
165950
167372
|
}
|
|
165951
167373
|
var init_compartment_embedding = __esm(() => {
|
|
165952
167374
|
init_logger();
|
|
167375
|
+
init_compartment_chunk_embedding();
|
|
165953
167376
|
init_project_embedding_registry();
|
|
165954
167377
|
});
|
|
165955
167378
|
|
|
@@ -167063,55 +168486,6 @@ var init_historian_state_file = __esm(() => {
|
|
|
167063
168486
|
init_data_path();
|
|
167064
168487
|
});
|
|
167065
168488
|
|
|
167066
|
-
// src/features/magic-context/memory/constants.ts
|
|
167067
|
-
var V2_MEMORY_CATEGORIES, PROMOTABLE_CATEGORIES, CATEGORY_PRIORITY, MEMORY_CATEGORY_ORDER_UNKNOWN = 99, MEMORY_CATEGORY_ORDER_PRIORITY, MEMORY_CATEGORY_ORDER_SQL, CATEGORY_DEFAULT_TTL;
|
|
167068
|
-
var init_constants = __esm(() => {
|
|
167069
|
-
V2_MEMORY_CATEGORIES = [
|
|
167070
|
-
"PROJECT_RULES",
|
|
167071
|
-
"ARCHITECTURE",
|
|
167072
|
-
"CONSTRAINTS",
|
|
167073
|
-
"CONFIG_VALUES",
|
|
167074
|
-
"NAMING"
|
|
167075
|
-
];
|
|
167076
|
-
PROMOTABLE_CATEGORIES = [
|
|
167077
|
-
"PROJECT_RULES",
|
|
167078
|
-
"ARCHITECTURE",
|
|
167079
|
-
"CONSTRAINTS",
|
|
167080
|
-
"CONFIG_VALUES",
|
|
167081
|
-
"NAMING",
|
|
167082
|
-
"ARCHITECTURE_DECISIONS",
|
|
167083
|
-
"CONFIG_DEFAULTS",
|
|
167084
|
-
"USER_PREFERENCES",
|
|
167085
|
-
"USER_DIRECTIVES",
|
|
167086
|
-
"ENVIRONMENT",
|
|
167087
|
-
"WORKFLOW_RULES",
|
|
167088
|
-
"KNOWN_ISSUES"
|
|
167089
|
-
];
|
|
167090
|
-
CATEGORY_PRIORITY = [
|
|
167091
|
-
"PROJECT_RULES",
|
|
167092
|
-
"ARCHITECTURE",
|
|
167093
|
-
"CONSTRAINTS",
|
|
167094
|
-
"CONFIG_VALUES",
|
|
167095
|
-
"NAMING",
|
|
167096
|
-
"USER_DIRECTIVES",
|
|
167097
|
-
"USER_PREFERENCES",
|
|
167098
|
-
"CONFIG_DEFAULTS",
|
|
167099
|
-
"ARCHITECTURE_DECISIONS",
|
|
167100
|
-
"ENVIRONMENT",
|
|
167101
|
-
"WORKFLOW_RULES",
|
|
167102
|
-
"KNOWN_ISSUES"
|
|
167103
|
-
];
|
|
167104
|
-
MEMORY_CATEGORY_ORDER_PRIORITY = CATEGORY_PRIORITY.reduce((acc, category, index) => {
|
|
167105
|
-
acc[category] = index;
|
|
167106
|
-
return acc;
|
|
167107
|
-
}, {});
|
|
167108
|
-
MEMORY_CATEGORY_ORDER_SQL = `CASE category ${CATEGORY_PRIORITY.map((category, index) => `WHEN '${category}' THEN ${index}`).join(" ")} ELSE ${MEMORY_CATEGORY_ORDER_UNKNOWN} END`;
|
|
167109
|
-
CATEGORY_DEFAULT_TTL = {
|
|
167110
|
-
WORKFLOW_RULES: 90 * 24 * 60 * 60 * 1000,
|
|
167111
|
-
KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
|
|
167112
|
-
};
|
|
167113
|
-
});
|
|
167114
|
-
|
|
167115
168489
|
// src/features/magic-context/memory/embedding-backfill.ts
|
|
167116
168490
|
async function ensureMemoryEmbeddings(args) {
|
|
167117
168491
|
const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
@@ -167135,7 +168509,7 @@ async function ensureMemoryEmbeddings(args) {
|
|
|
167135
168509
|
continue;
|
|
167136
168510
|
}
|
|
167137
168511
|
saveEmbedding(args.db, memory.id, embedding, result.modelId);
|
|
167138
|
-
staged.set(memory.id, embedding);
|
|
168512
|
+
staged.set(memory.id, { embedding, modelId: result.modelId });
|
|
167139
168513
|
}
|
|
167140
168514
|
})();
|
|
167141
168515
|
const currentSnapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
@@ -167932,6 +169306,71 @@ function lastCompartmentBoundaryId(compartments) {
|
|
|
167932
169306
|
const last = compartments.at(-1);
|
|
167933
169307
|
return last?.endMessageId && last.endMessageId.length > 0 ? last.endMessageId : null;
|
|
167934
169308
|
}
|
|
169309
|
+
function resolveWorkspaceRenderContext(args) {
|
|
169310
|
+
if (!args.projectPath) {
|
|
169311
|
+
return {
|
|
169312
|
+
identities: [],
|
|
169313
|
+
expandedIdentities: [],
|
|
169314
|
+
ownIdentities: [],
|
|
169315
|
+
shareCategories: null,
|
|
169316
|
+
namesByIdentity: new Map,
|
|
169317
|
+
canonicalIdentityByStoredPath: new Map,
|
|
169318
|
+
isWorkspaced: false
|
|
169319
|
+
};
|
|
169320
|
+
}
|
|
169321
|
+
const identitySet = args.workspaceIdentitySet ?? resolveWorkspaceIdentitySet(args.db, args.projectPath);
|
|
169322
|
+
const isWorkspaced = identitySet.identities.length > 1;
|
|
169323
|
+
const expanded = expandWorkspaceIdentitySetWithAliases(args.db, identitySet.identities);
|
|
169324
|
+
const expandedIdentities = isWorkspaced ? expanded.expandedIdentities : identitySet.identities;
|
|
169325
|
+
const canonicalIdentityByStoredPath = isWorkspaced ? expanded.canonicalIdentityByStoredPath : new Map(identitySet.identities.map((identity) => [identity, identity]));
|
|
169326
|
+
let ownIdentities = expandedIdentities.filter((identity) => canonicalIdentityByStoredPath.get(identity) === args.projectPath);
|
|
169327
|
+
if (ownIdentities.length === 0 && expandedIdentities.includes(args.projectPath)) {
|
|
169328
|
+
ownIdentities = [args.projectPath];
|
|
169329
|
+
}
|
|
169330
|
+
return {
|
|
169331
|
+
identities: identitySet.identities,
|
|
169332
|
+
expandedIdentities,
|
|
169333
|
+
ownIdentities,
|
|
169334
|
+
shareCategories: isWorkspaced ? resolveWorkspaceShareCategories(args.db, args.projectPath) : null,
|
|
169335
|
+
namesByIdentity: identitySet.namesByIdentity,
|
|
169336
|
+
canonicalIdentityByStoredPath,
|
|
169337
|
+
isWorkspaced
|
|
169338
|
+
};
|
|
169339
|
+
}
|
|
169340
|
+
function sourceNamesForMemories(args) {
|
|
169341
|
+
if (!args.projectPath || !args.workspace.isWorkspaced)
|
|
169342
|
+
return;
|
|
169343
|
+
const names = new Map;
|
|
169344
|
+
for (const memory of args.memories) {
|
|
169345
|
+
const source = sourceNameForMemory(memory.projectPath, args.projectPath, args.workspace.identities, args.workspace.namesByIdentity, args.workspace.canonicalIdentityByStoredPath);
|
|
169346
|
+
if (source)
|
|
169347
|
+
names.set(memory.id, source);
|
|
169348
|
+
}
|
|
169349
|
+
return names.size > 0 ? names : undefined;
|
|
169350
|
+
}
|
|
169351
|
+
function memoryCanonicalIdentity(memory, workspace) {
|
|
169352
|
+
return resolveStoredPathWorkspaceIdentity(memory.projectPath, workspace.identities, workspace.canonicalIdentityByStoredPath);
|
|
169353
|
+
}
|
|
169354
|
+
function memorySelectionOrder(left, right) {
|
|
169355
|
+
if (left.status === "permanent" && right.status !== "permanent")
|
|
169356
|
+
return -1;
|
|
169357
|
+
if (right.status === "permanent" && left.status !== "permanent")
|
|
169358
|
+
return 1;
|
|
169359
|
+
const leftImportance = left.importance ?? Number.NEGATIVE_INFINITY;
|
|
169360
|
+
const rightImportance = right.importance ?? Number.NEGATIVE_INFINITY;
|
|
169361
|
+
const importanceDiff = rightImportance - leftImportance;
|
|
169362
|
+
if (importanceDiff !== 0)
|
|
169363
|
+
return importanceDiff;
|
|
169364
|
+
return left.id - right.id;
|
|
169365
|
+
}
|
|
169366
|
+
function memoryRenderOrder(left, right) {
|
|
169367
|
+
const aPriority = MEMORY_CATEGORY_ORDER_PRIORITY[left.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
169368
|
+
const bPriority = MEMORY_CATEGORY_ORDER_PRIORITY[right.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
169369
|
+
const categoryDiff = aPriority - bPriority;
|
|
169370
|
+
if (categoryDiff !== 0)
|
|
169371
|
+
return categoryDiff;
|
|
169372
|
+
return left.id - right.id;
|
|
169373
|
+
}
|
|
167935
169374
|
function cachedStatement(cache, db, sql) {
|
|
167936
169375
|
let stmt = cache.get(db);
|
|
167937
169376
|
if (!stmt) {
|
|
@@ -167974,19 +169413,24 @@ function getGlobalUserProfileVersion(db) {
|
|
|
167974
169413
|
function readCurrentM0SnapshotMarkers(args) {
|
|
167975
169414
|
const projectDirectory = args.projectDirectory ?? args.projectPath ?? "";
|
|
167976
169415
|
const hard = args.hardSignals ?? EMPTY_HARD_SIGNALS;
|
|
169416
|
+
const workspace = resolveWorkspaceRenderContext({
|
|
169417
|
+
db: args.db,
|
|
169418
|
+
projectPath: args.projectPath,
|
|
169419
|
+
workspaceIdentitySet: args.workspaceIdentitySet
|
|
169420
|
+
});
|
|
167977
169421
|
return {
|
|
167978
169422
|
projectMemoryEpoch: getProjectMemoryEpoch(args.db, args.projectPath),
|
|
169423
|
+
workspaceFingerprint: workspace.isWorkspaced ? computeWorkspaceEpochFingerprint(args.db, workspace.identities) : null,
|
|
167979
169424
|
projectUserProfileVersion: getGlobalUserProfileVersion(args.db),
|
|
167980
169425
|
maxCompartmentSeq: getMaxCompartmentSeq(args.db, args.sessionId),
|
|
167981
|
-
maxMemoryId: getMaxMemoryId(args.db, args.projectPath),
|
|
169426
|
+
maxMemoryId: workspace.isWorkspaced ? getMaxMemoryIdForProjects(args.db, workspace.expandedIdentities, workspace.ownIdentities, workspace.shareCategories) : getMaxMemoryId(args.db, args.projectPath),
|
|
167982
169427
|
maxMutationId: getMaxM0MutationId(args.db, args.sessionId) ?? 0,
|
|
167983
|
-
maxMemoryMutationId: args.projectPath ? getMaxMemoryMutationId(args.db, args.projectPath) ?? 0 : 0,
|
|
169428
|
+
maxMemoryMutationId: workspace.isWorkspaced ? getMaxMemoryMutationIdForProjects(args.db, workspace.expandedIdentities) ?? 0 : args.projectPath ? getMaxMemoryMutationId(args.db, args.projectPath) ?? 0 : 0,
|
|
167984
169429
|
projectDocsHash: projectDirectory ? computeProjectDocsHash(projectDirectory) : "",
|
|
167985
169430
|
materializedAt: Date.now(),
|
|
167986
169431
|
sessionFactsVersion: getSessionFactsVersion(args.db, args.sessionId),
|
|
167987
169432
|
upgradeState: getUpgradeState(args.db, args.sessionId),
|
|
167988
169433
|
systemHash: hard.systemHash,
|
|
167989
|
-
toolSetHash: hard.toolSetHash,
|
|
167990
169434
|
modelKey: hard.modelKey
|
|
167991
169435
|
};
|
|
167992
169436
|
}
|
|
@@ -168009,6 +169453,7 @@ function snapshotMarkersFromCachedM0(state) {
|
|
|
168009
169453
|
return null;
|
|
168010
169454
|
return {
|
|
168011
169455
|
projectMemoryEpoch: state.cachedM0ProjectMemoryEpoch,
|
|
169456
|
+
workspaceFingerprint: state.cachedM0WorkspaceFingerprint,
|
|
168012
169457
|
projectUserProfileVersion: state.cachedM0ProjectUserProfileVersion,
|
|
168013
169458
|
maxCompartmentSeq: state.cachedM0MaxCompartmentSeq,
|
|
168014
169459
|
maxMemoryId: state.cachedM0MaxMemoryId,
|
|
@@ -168019,7 +169464,6 @@ function snapshotMarkersFromCachedM0(state) {
|
|
|
168019
169464
|
sessionFactsVersion: state.cachedM0SessionFactsVersion,
|
|
168020
169465
|
upgradeState: state.cachedM0UpgradeState,
|
|
168021
169466
|
systemHash: state.cachedM0SystemHash ?? "",
|
|
168022
|
-
toolSetHash: state.cachedM0ToolSetHash ?? "",
|
|
168023
169467
|
modelKey: state.cachedM0ModelKey ?? ""
|
|
168024
169468
|
};
|
|
168025
169469
|
}
|
|
@@ -168036,41 +169480,30 @@ function mustMaterialize(args) {
|
|
|
168036
169480
|
if (hard.systemHash !== "" && hard.systemHash !== (args.state.cachedM0SystemHash ?? "")) {
|
|
168037
169481
|
return { value: true, reason: "system_hash" };
|
|
168038
169482
|
}
|
|
168039
|
-
if (hard.toolSetHash !== "" && hard.toolSetHash !== (args.state.cachedM0ToolSetHash ?? "")) {
|
|
168040
|
-
return { value: true, reason: "tool_set_hash" };
|
|
168041
|
-
}
|
|
168042
169483
|
if (hard.cacheExpired && hard.lastResponseTime > 0 && hard.lastResponseTime > (args.state.cachedM0MaterializedAt ?? 0)) {
|
|
168043
169484
|
return { value: true, reason: "ttl_idle" };
|
|
168044
169485
|
}
|
|
168045
|
-
if (args.state.
|
|
169486
|
+
if (current.workspaceFingerprint !== null || (args.state.cachedM0WorkspaceFingerprint ?? null) !== null) {
|
|
169487
|
+
if ((args.state.cachedM0WorkspaceFingerprint ?? null) !== current.workspaceFingerprint) {
|
|
169488
|
+
return { value: true, reason: "project_memory_epoch" };
|
|
169489
|
+
}
|
|
169490
|
+
} else if (args.state.cachedM0ProjectMemoryEpoch !== current.projectMemoryEpoch) {
|
|
168046
169491
|
return { value: true, reason: "project_memory_epoch" };
|
|
168047
169492
|
}
|
|
168048
169493
|
if (args.state.cachedM0MaxMutationId !== current.maxMutationId) {
|
|
168049
169494
|
return { value: true, reason: "max_mutation_id" };
|
|
168050
169495
|
}
|
|
168051
|
-
if ((args.state.cachedM0ProjectDocsHash ?? "") !== current.projectDocsHash) {
|
|
168052
|
-
return { value: true, reason: "project_docs_hash" };
|
|
168053
|
-
}
|
|
168054
169496
|
if ((args.state.cachedM0UpgradeState ?? null) !== current.upgradeState) {
|
|
168055
169497
|
return { value: true, reason: "upgrade_state" };
|
|
168056
169498
|
}
|
|
168057
169499
|
return { value: false, reason: null };
|
|
168058
169500
|
}
|
|
168059
|
-
function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens) {
|
|
168060
|
-
const selectionOrder = [...memories].sort(
|
|
168061
|
-
if (a.status === "permanent" && b.status !== "permanent")
|
|
168062
|
-
return -1;
|
|
168063
|
-
if (b.status === "permanent" && a.status !== "permanent")
|
|
168064
|
-
return 1;
|
|
168065
|
-
const importanceDiff = (b.importance ?? 50) - (a.importance ?? 50);
|
|
168066
|
-
if (importanceDiff !== 0)
|
|
168067
|
-
return importanceDiff;
|
|
168068
|
-
return a.id - b.id;
|
|
168069
|
-
});
|
|
169501
|
+
function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens, renderOptions = {}) {
|
|
169502
|
+
const selectionOrder = [...memories].sort(memorySelectionOrder);
|
|
168070
169503
|
const selected = [];
|
|
168071
169504
|
let usedTokens = MEMORY_BLOCK_WRAPPER_TOKENS;
|
|
168072
169505
|
for (const memory of selectionOrder) {
|
|
168073
|
-
const memoryTokens = estimateTokens(renderMemoryLineV2(memory));
|
|
169506
|
+
const memoryTokens = estimateTokens(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
168074
169507
|
if (usedTokens + memoryTokens > budgetTokens)
|
|
168075
169508
|
continue;
|
|
168076
169509
|
selected.push(memory);
|
|
@@ -168079,16 +169512,70 @@ function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens) {
|
|
|
168079
169512
|
if (selected.length < memories.length) {
|
|
168080
169513
|
sessionLog(sessionId, `v2 trimmed memories from ${memories.length} to ${selected.length} to fit injection budget of ${budgetTokens} tokens`);
|
|
168081
169514
|
}
|
|
168082
|
-
const renderOrder = [...selected].sort(
|
|
168083
|
-
const aPriority = MEMORY_CATEGORY_ORDER_PRIORITY[a.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
168084
|
-
const bPriority = MEMORY_CATEGORY_ORDER_PRIORITY[b.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
168085
|
-
const categoryDiff = aPriority - bPriority;
|
|
168086
|
-
if (categoryDiff !== 0)
|
|
168087
|
-
return categoryDiff;
|
|
168088
|
-
return a.id - b.id;
|
|
168089
|
-
});
|
|
169515
|
+
const renderOrder = [...selected].sort(memoryRenderOrder);
|
|
168090
169516
|
return { selected, renderOrder };
|
|
168091
169517
|
}
|
|
169518
|
+
function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, workspace, renderOptions = {}) {
|
|
169519
|
+
if (!workspace.isWorkspaced) {
|
|
169520
|
+
return trimMemoriesToBudgetV2(sessionId, memories, budgetTokens, renderOptions);
|
|
169521
|
+
}
|
|
169522
|
+
const selected = [];
|
|
169523
|
+
const selectedIds = new Set;
|
|
169524
|
+
let usedTokens = MEMORY_BLOCK_WRAPPER_TOKENS;
|
|
169525
|
+
const tokenCost = (memory) => estimateTokens(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
169526
|
+
const trySelect = (memory) => {
|
|
169527
|
+
if (selectedIds.has(memory.id))
|
|
169528
|
+
return false;
|
|
169529
|
+
const tokens = tokenCost(memory);
|
|
169530
|
+
if (usedTokens + tokens > budgetTokens)
|
|
169531
|
+
return false;
|
|
169532
|
+
selected.push(memory);
|
|
169533
|
+
selectedIds.add(memory.id);
|
|
169534
|
+
usedTokens += tokens;
|
|
169535
|
+
return true;
|
|
169536
|
+
};
|
|
169537
|
+
for (const memory of memories.filter((candidate) => candidate.status === "permanent").sort(memorySelectionOrder)) {
|
|
169538
|
+
trySelect(memory);
|
|
169539
|
+
}
|
|
169540
|
+
const remainingAfterPermanent = Math.max(0, budgetTokens - usedTokens);
|
|
169541
|
+
const floorTokens = remainingAfterPermanent / Math.max(1, workspace.identities.length);
|
|
169542
|
+
const byIdentity = new Map;
|
|
169543
|
+
for (const memory of memories) {
|
|
169544
|
+
if (memory.status === "permanent")
|
|
169545
|
+
continue;
|
|
169546
|
+
const identity = memoryCanonicalIdentity(memory, workspace);
|
|
169547
|
+
if (!identity)
|
|
169548
|
+
continue;
|
|
169549
|
+
const list = byIdentity.get(identity) ?? [];
|
|
169550
|
+
list.push(memory);
|
|
169551
|
+
byIdentity.set(identity, list);
|
|
169552
|
+
}
|
|
169553
|
+
for (const identity of workspace.identities) {
|
|
169554
|
+
let memberTokens = 0;
|
|
169555
|
+
const candidates = (byIdentity.get(identity) ?? []).sort(memorySelectionOrder);
|
|
169556
|
+
for (const memory of candidates) {
|
|
169557
|
+
if (selectedIds.has(memory.id))
|
|
169558
|
+
continue;
|
|
169559
|
+
const tokens = tokenCost(memory);
|
|
169560
|
+
if (memberTokens + tokens > floorTokens)
|
|
169561
|
+
continue;
|
|
169562
|
+
if (usedTokens + tokens > budgetTokens)
|
|
169563
|
+
continue;
|
|
169564
|
+
selected.push(memory);
|
|
169565
|
+
selectedIds.add(memory.id);
|
|
169566
|
+
usedTokens += tokens;
|
|
169567
|
+
memberTokens += tokens;
|
|
169568
|
+
}
|
|
169569
|
+
}
|
|
169570
|
+
const remaining = memories.filter((memory) => !selectedIds.has(memory.id)).sort(memorySelectionOrder);
|
|
169571
|
+
for (const memory of remaining) {
|
|
169572
|
+
trySelect(memory);
|
|
169573
|
+
}
|
|
169574
|
+
if (selected.length < memories.length) {
|
|
169575
|
+
sessionLog(sessionId, `v2 trimmed memories from ${memories.length} to ${selected.length} to fit injection budget of ${budgetTokens} tokens`);
|
|
169576
|
+
}
|
|
169577
|
+
return { selected, renderOrder: [...selected].sort(memoryRenderOrder) };
|
|
169578
|
+
}
|
|
168092
169579
|
function safeGetActiveUserMemories(db) {
|
|
168093
169580
|
try {
|
|
168094
169581
|
return getActiveUserMemories(db);
|
|
@@ -168164,15 +169651,16 @@ function readNewMemoriesForM1(db, projectPath, afterId, expiryCutoff) {
|
|
|
168164
169651
|
ORDER BY ${MEMORY_CATEGORY_ORDER_SQL}, id ASC`).all(projectPath, afterId, expiryCutoff).filter(isMemoryRow);
|
|
168165
169652
|
return rows.map((row) => ({ ...row }));
|
|
168166
169653
|
}
|
|
168167
|
-
function renderMemoryLineV2(memory) {
|
|
168168
|
-
|
|
169654
|
+
function renderMemoryLineV2(memory, sourceName) {
|
|
169655
|
+
const sourceAttr = sourceName ? ` source="${escapeXmlAttr(sourceName)}"` : "";
|
|
169656
|
+
return ` <memory id="${memory.id}" category="${escapeXmlAttr(memory.category)}"${sourceAttr} importance="${memory.importance ?? 50}">${escapeXmlContent(memory.content)}</memory>`;
|
|
168169
169657
|
}
|
|
168170
|
-
function renderMemoryBlockV2(memories, wrapper = "project-memory") {
|
|
169658
|
+
function renderMemoryBlockV2(memories, wrapper = "project-memory", renderOptions = {}) {
|
|
168171
169659
|
if (memories.length === 0)
|
|
168172
169660
|
return "";
|
|
168173
169661
|
const lines = [`<${wrapper}>`];
|
|
168174
169662
|
for (const memory of memories) {
|
|
168175
|
-
lines.push(renderMemoryLineV2(memory));
|
|
169663
|
+
lines.push(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
168176
169664
|
}
|
|
168177
169665
|
lines.push(`</${wrapper}>`);
|
|
168178
169666
|
return lines.join(`
|
|
@@ -168211,7 +169699,7 @@ function renderM0(args) {
|
|
|
168211
169699
|
sections.push(sessionHistory.length > 0 ? `<session-history>
|
|
168212
169700
|
${sessionHistory}
|
|
168213
169701
|
</session-history>` : M0_EMPTY_BODY);
|
|
168214
|
-
const memoriesBlock = renderMemoryBlockV2(args.memories);
|
|
169702
|
+
const memoriesBlock = renderMemoryBlockV2(args.memories, "project-memory", args.memoryRenderOptions);
|
|
168215
169703
|
if (memoriesBlock)
|
|
168216
169704
|
sections.push(memoriesBlock);
|
|
168217
169705
|
return sections.join(`
|
|
@@ -168223,6 +169711,7 @@ function applyMarkersToState(state, m0Bytes, markers, m1Bytes) {
|
|
|
168223
169711
|
if (m1Bytes)
|
|
168224
169712
|
state.cachedM1Bytes = m1Bytes;
|
|
168225
169713
|
state.cachedM0ProjectMemoryEpoch = markers.projectMemoryEpoch;
|
|
169714
|
+
state.cachedM0WorkspaceFingerprint = markers.workspaceFingerprint;
|
|
168226
169715
|
state.cachedM0ProjectUserProfileVersion = markers.projectUserProfileVersion;
|
|
168227
169716
|
state.cachedM0MaxCompartmentSeq = markers.maxCompartmentSeq;
|
|
168228
169717
|
state.cachedM0MaxMemoryId = markers.maxMemoryId;
|
|
@@ -168233,7 +169722,6 @@ function applyMarkersToState(state, m0Bytes, markers, m1Bytes) {
|
|
|
168233
169722
|
state.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
|
|
168234
169723
|
state.cachedM0UpgradeState = markers.upgradeState;
|
|
168235
169724
|
state.cachedM0SystemHash = markers.systemHash;
|
|
168236
|
-
state.cachedM0ToolSetHash = markers.toolSetHash;
|
|
168237
169725
|
state.cachedM0ModelKey = markers.modelKey;
|
|
168238
169726
|
state.snapshotMarkers = markers;
|
|
168239
169727
|
}
|
|
@@ -168249,24 +169737,38 @@ function materializeM0(options) {
|
|
|
168249
169737
|
let facts = [];
|
|
168250
169738
|
let memories = [];
|
|
168251
169739
|
let userMemories = [];
|
|
169740
|
+
let workspace = resolveWorkspaceRenderContext({
|
|
169741
|
+
db: options.db,
|
|
169742
|
+
projectPath,
|
|
169743
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
169744
|
+
});
|
|
168252
169745
|
let docs = {
|
|
168253
169746
|
renderedBlock: "",
|
|
168254
169747
|
canonicalHash: ""
|
|
168255
169748
|
};
|
|
168256
169749
|
options.db.exec("BEGIN");
|
|
168257
169750
|
try {
|
|
169751
|
+
workspace = resolveWorkspaceRenderContext({
|
|
169752
|
+
db: options.db,
|
|
169753
|
+
projectPath,
|
|
169754
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
169755
|
+
});
|
|
168258
169756
|
snapshotMarkers = readCurrentM0SnapshotMarkers({
|
|
168259
169757
|
db: options.db,
|
|
168260
169758
|
sessionId: options.sessionId,
|
|
168261
169759
|
projectPath,
|
|
168262
169760
|
projectDirectory,
|
|
168263
|
-
hardSignals: options.hardSignals
|
|
169761
|
+
hardSignals: options.hardSignals,
|
|
169762
|
+
workspaceIdentitySet: {
|
|
169763
|
+
identities: workspace.identities,
|
|
169764
|
+
namesByIdentity: workspace.namesByIdentity
|
|
169765
|
+
}
|
|
168264
169766
|
});
|
|
168265
169767
|
docs = projectDirectory ? readProjectDocsCanonical(projectDirectory) : { renderedBlock: "", canonicalHash: "" };
|
|
168266
169768
|
snapshotMarkers.projectDocsHash = docs.canonicalHash;
|
|
168267
169769
|
compartments = readM0Compartments(options.db, options.sessionId);
|
|
168268
169770
|
facts = [];
|
|
168269
|
-
memories = projectPath ? getMemoriesByProject(options.db, projectPath, ["active", "permanent"]) : [];
|
|
169771
|
+
memories = projectPath ? workspace.isWorkspaced ? getMemoriesByProjects(options.db, workspace.expandedIdentities, ["active", "permanent"], Date.now(), workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(options.db, projectPath, ["active", "permanent"]) : [];
|
|
168270
169772
|
userMemories = safeGetActiveUserMemories(options.db);
|
|
168271
169773
|
options.db.exec("COMMIT");
|
|
168272
169774
|
} catch (error51) {
|
|
@@ -168276,7 +169778,14 @@ function materializeM0(options) {
|
|
|
168276
169778
|
throw error51;
|
|
168277
169779
|
}
|
|
168278
169780
|
const memoryBudget = options.memoryInjectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
|
|
168279
|
-
const
|
|
169781
|
+
const memoryRenderOptions = {
|
|
169782
|
+
sourceNameByMemoryId: sourceNamesForMemories({
|
|
169783
|
+
memories,
|
|
169784
|
+
projectPath,
|
|
169785
|
+
workspace
|
|
169786
|
+
})
|
|
169787
|
+
};
|
|
169788
|
+
const trimmed = workspace.isWorkspaced ? trimWorkspaceMemoriesToBudgetV2(options.sessionId, memories, memoryBudget, workspace, memoryRenderOptions) : trimMemoriesToBudgetV2(options.sessionId, memories, memoryBudget);
|
|
168280
169789
|
let decayPressureMultiplier = 1;
|
|
168281
169790
|
let m0Text = renderM0({
|
|
168282
169791
|
projectDocs: docs.renderedBlock,
|
|
@@ -168284,6 +169793,7 @@ function materializeM0(options) {
|
|
|
168284
169793
|
compartments,
|
|
168285
169794
|
memories: trimmed.renderOrder,
|
|
168286
169795
|
facts,
|
|
169796
|
+
memoryRenderOptions,
|
|
168287
169797
|
historyBudgetTokens: options.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS,
|
|
168288
169798
|
userProfileBudgetTokens: options.userProfileBudgetTokens,
|
|
168289
169799
|
decayPressureMultiplier
|
|
@@ -168298,6 +169808,7 @@ function materializeM0(options) {
|
|
|
168298
169808
|
compartments,
|
|
168299
169809
|
memories: trimmed.renderOrder,
|
|
168300
169810
|
facts,
|
|
169811
|
+
memoryRenderOptions,
|
|
168301
169812
|
historyBudgetTokens: budget,
|
|
168302
169813
|
userProfileBudgetTokens: options.userProfileBudgetTokens,
|
|
168303
169814
|
decayPressureMultiplier
|
|
@@ -168316,32 +169827,46 @@ function materializeM0(options) {
|
|
|
168316
169827
|
let m1Bytes = Buffer4.from(m1Text, "utf8");
|
|
168317
169828
|
options.db.exec("BEGIN IMMEDIATE");
|
|
168318
169829
|
try {
|
|
169830
|
+
const currentWorkspace = resolveWorkspaceRenderContext({
|
|
169831
|
+
db: options.db,
|
|
169832
|
+
projectPath,
|
|
169833
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
169834
|
+
});
|
|
168319
169835
|
const current = {
|
|
168320
169836
|
projectMemoryEpoch: getProjectMemoryEpoch(options.db, projectPath),
|
|
169837
|
+
workspaceFingerprint: currentWorkspace.isWorkspaced ? computeWorkspaceEpochFingerprint(options.db, currentWorkspace.identities) : null,
|
|
168321
169838
|
projectUserProfileVersion: getGlobalUserProfileVersion(options.db),
|
|
168322
169839
|
maxCompartmentSeq: getMaxCompartmentSeq(options.db, options.sessionId),
|
|
168323
|
-
maxMemoryId: getMaxMemoryId(options.db, projectPath),
|
|
169840
|
+
maxMemoryId: currentWorkspace.isWorkspaced ? getMaxMemoryIdForProjects(options.db, currentWorkspace.expandedIdentities, currentWorkspace.ownIdentities, currentWorkspace.shareCategories) : getMaxMemoryId(options.db, projectPath),
|
|
168324
169841
|
maxMutationId: getMaxM0MutationId(options.db, options.sessionId) ?? 0,
|
|
168325
|
-
maxMemoryMutationId: projectPath ? getMaxMemoryMutationId(options.db, projectPath) ?? 0 : 0,
|
|
169842
|
+
maxMemoryMutationId: currentWorkspace.isWorkspaced ? getMaxMemoryMutationIdForProjects(options.db, currentWorkspace.expandedIdentities) ?? 0 : projectPath ? getMaxMemoryMutationId(options.db, projectPath) ?? 0 : 0,
|
|
168326
169843
|
projectDocsHash: phase3ProjectDocsHash,
|
|
168327
169844
|
materializedAt: Date.now(),
|
|
168328
169845
|
sessionFactsVersion: getSessionFactsVersion(options.db, options.sessionId),
|
|
168329
169846
|
upgradeState: getUpgradeState(options.db, options.sessionId),
|
|
168330
169847
|
systemHash: snapshotMarkers.systemHash,
|
|
168331
|
-
toolSetHash: snapshotMarkers.toolSetHash,
|
|
168332
169848
|
modelKey: snapshotMarkers.modelKey
|
|
168333
169849
|
};
|
|
168334
|
-
const
|
|
169850
|
+
const memoryEpochStale = current.workspaceFingerprint !== null || snapshotMarkers.workspaceFingerprint !== null ? current.workspaceFingerprint !== snapshotMarkers.workspaceFingerprint : current.projectMemoryEpoch !== snapshotMarkers.projectMemoryEpoch;
|
|
169851
|
+
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;
|
|
168335
169852
|
if (stale) {
|
|
168336
169853
|
options.db.exec("ROLLBACK");
|
|
168337
169854
|
throw new MaterializeContentionError({ reason: "snapshot changed before Phase 3" });
|
|
168338
169855
|
}
|
|
168339
|
-
const m1Render = renderM1WithMetadata({
|
|
169856
|
+
const m1Render = renderM1WithMetadata({
|
|
169857
|
+
...options,
|
|
169858
|
+
preRenderedKeyFilesBlock,
|
|
169859
|
+
workspaceIdentitySet: {
|
|
169860
|
+
identities: workspace.identities,
|
|
169861
|
+
namesByIdentity: workspace.namesByIdentity
|
|
169862
|
+
}
|
|
169863
|
+
}, snapshotMarkers, renderedMemoryIds);
|
|
168340
169864
|
m1Text = m1Render.text;
|
|
168341
169865
|
m1Bytes = Buffer4.from(m1Text, "utf8");
|
|
168342
169866
|
persistCachedM0(options.db, options.sessionId, {
|
|
168343
169867
|
m0Bytes,
|
|
168344
169868
|
projectMemoryEpoch: snapshotMarkers.projectMemoryEpoch,
|
|
169869
|
+
workspaceFingerprint: snapshotMarkers.workspaceFingerprint,
|
|
168345
169870
|
projectUserProfileVersion: snapshotMarkers.projectUserProfileVersion,
|
|
168346
169871
|
maxCompartmentSeq: snapshotMarkers.maxCompartmentSeq,
|
|
168347
169872
|
maxMemoryId: snapshotMarkers.maxMemoryId,
|
|
@@ -168353,7 +169878,6 @@ function materializeM0(options) {
|
|
|
168353
169878
|
sessionFactsVersion: snapshotMarkers.sessionFactsVersion,
|
|
168354
169879
|
upgradeState: snapshotMarkers.upgradeState,
|
|
168355
169880
|
systemHash: snapshotMarkers.systemHash,
|
|
168356
|
-
toolSetHash: snapshotMarkers.toolSetHash,
|
|
168357
169881
|
modelKey: snapshotMarkers.modelKey
|
|
168358
169882
|
});
|
|
168359
169883
|
options.db.prepare("UPDATE session_meta SET memory_block_count = ?, memory_block_ids = ? WHERE session_id = ?").run(renderedMemoryIds.length, JSON.stringify(renderedMemoryIds), options.sessionId);
|
|
@@ -168405,7 +169929,7 @@ function renderMemoryUpdatesBlock(args) {
|
|
|
168405
169929
|
return { block: "", count: 0 };
|
|
168406
169930
|
}
|
|
168407
169931
|
const renderedIds = new Set(args.renderedMemoryIds);
|
|
168408
|
-
const mutations = getMemoryMutationsForRender(args.db, args.projectPath, args.afterId, args.renderedMemoryIds);
|
|
169932
|
+
const mutations = args.workspace.isWorkspaced ? getMemoryMutationsForRenderByProjects(args.db, args.workspace.expandedIdentities, args.afterId, args.renderedMemoryIds) : getMemoryMutationsForRender(args.db, args.projectPath, args.afterId, args.renderedMemoryIds);
|
|
168409
169933
|
if (mutations.length === 0)
|
|
168410
169934
|
return { block: "", count: 0 };
|
|
168411
169935
|
const lines = ["These memories changed since the snapshot below — trust these:"];
|
|
@@ -168437,12 +169961,18 @@ function renderM1WithMetadata(options, markers, renderedMemoryIds) {
|
|
|
168437
169961
|
throw new RenderM1InvalidMarkersError(options.sessionId);
|
|
168438
169962
|
}
|
|
168439
169963
|
const blocks = [];
|
|
169964
|
+
const workspace = resolveWorkspaceRenderContext({
|
|
169965
|
+
db: options.db,
|
|
169966
|
+
projectPath: options.projectPath,
|
|
169967
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
169968
|
+
});
|
|
168440
169969
|
const keyFiles = renderedKeyFilesBlock(options);
|
|
168441
169970
|
if (keyFiles)
|
|
168442
169971
|
blocks.push(keyFiles);
|
|
168443
169972
|
const memoryUpdates = renderMemoryUpdatesBlock({
|
|
168444
169973
|
db: options.db,
|
|
168445
169974
|
projectPath: options.projectPath,
|
|
169975
|
+
workspace,
|
|
168446
169976
|
afterId: markers.maxMemoryMutationId,
|
|
168447
169977
|
renderedMemoryIds
|
|
168448
169978
|
});
|
|
@@ -168456,9 +169986,16 @@ ${newCompartments.map((compartment) => renderCompartmentAtTier(compartment, 1)).
|
|
|
168456
169986
|
`)}
|
|
168457
169987
|
</new-compartments>`);
|
|
168458
169988
|
}
|
|
168459
|
-
const newMemories = readNewMemoriesForM1(options.db, options.projectPath, markers.maxMemoryId, markers.materializedAt);
|
|
168460
|
-
const
|
|
168461
|
-
|
|
169989
|
+
const newMemories = workspace.isWorkspaced ? readNewMemoriesForM1Union(options.db, workspace.expandedIdentities, markers.maxMemoryId, markers.materializedAt, workspace.ownIdentities, workspace.shareCategories) : readNewMemoriesForM1(options.db, options.projectPath, markers.maxMemoryId, markers.materializedAt);
|
|
169990
|
+
const newMemoryRenderOptions = {
|
|
169991
|
+
sourceNameByMemoryId: sourceNamesForMemories({
|
|
169992
|
+
memories: newMemories,
|
|
169993
|
+
projectPath: options.projectPath,
|
|
169994
|
+
workspace
|
|
169995
|
+
})
|
|
169996
|
+
};
|
|
169997
|
+
const trimmedNewMemories = trimMemoriesToBudgetV2(options.sessionId, newMemories, Math.max(1, Math.floor((options.memoryInjectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS) * 0.25)), newMemoryRenderOptions).renderOrder;
|
|
169998
|
+
const newMemoriesBlock = renderMemoryBlockV2(trimmedNewMemories, "new-memories", newMemoryRenderOptions);
|
|
168462
169999
|
if (newMemoriesBlock)
|
|
168463
170000
|
blocks.push(newMemoriesBlock);
|
|
168464
170001
|
const currentUserProfileVersion = getGlobalUserProfileVersion(options.db);
|
|
@@ -168506,6 +170043,7 @@ function parseMemoryBlockIds(raw) {
|
|
|
168506
170043
|
function readCachedM0M1Row(db, sessionId) {
|
|
168507
170044
|
return db.prepare(`SELECT cached_m0_bytes, cached_m1_bytes,
|
|
168508
170045
|
cached_m0_project_memory_epoch,
|
|
170046
|
+
cached_m0_workspace_fingerprint,
|
|
168509
170047
|
cached_m0_project_user_profile_version,
|
|
168510
170048
|
cached_m0_max_compartment_seq,
|
|
168511
170049
|
cached_m0_max_memory_id,
|
|
@@ -168516,7 +170054,6 @@ function readCachedM0M1Row(db, sessionId) {
|
|
|
168516
170054
|
cached_m0_session_facts_version,
|
|
168517
170055
|
cached_m0_upgrade_state,
|
|
168518
170056
|
cached_m0_system_hash,
|
|
168519
|
-
cached_m0_tool_set_hash,
|
|
168520
170057
|
cached_m0_model_key,
|
|
168521
170058
|
memory_block_ids
|
|
168522
170059
|
FROM session_meta
|
|
@@ -168541,6 +170078,7 @@ function markersFromCachedRow(row) {
|
|
|
168541
170078
|
return null;
|
|
168542
170079
|
return {
|
|
168543
170080
|
projectMemoryEpoch: row.cached_m0_project_memory_epoch,
|
|
170081
|
+
workspaceFingerprint: row.cached_m0_workspace_fingerprint,
|
|
168544
170082
|
projectUserProfileVersion: row.cached_m0_project_user_profile_version,
|
|
168545
170083
|
maxCompartmentSeq: row.cached_m0_max_compartment_seq,
|
|
168546
170084
|
maxMemoryId: row.cached_m0_max_memory_id,
|
|
@@ -168551,12 +170089,11 @@ function markersFromCachedRow(row) {
|
|
|
168551
170089
|
sessionFactsVersion: row.cached_m0_session_facts_version,
|
|
168552
170090
|
upgradeState: row.cached_m0_upgrade_state,
|
|
168553
170091
|
systemHash: row.cached_m0_system_hash ?? "",
|
|
168554
|
-
toolSetHash: row.cached_m0_tool_set_hash ?? "",
|
|
168555
170092
|
modelKey: row.cached_m0_model_key ?? ""
|
|
168556
170093
|
};
|
|
168557
170094
|
}
|
|
168558
170095
|
function cachedRowMatchesState(row, state) {
|
|
168559
|
-
return bufferEqualsNullable(row.cached_m0_bytes, state.cachedM0Bytes) && row.cached_m0_project_memory_epoch === state.cachedM0ProjectMemoryEpoch && row.cached_m0_project_user_profile_version === state.cachedM0ProjectUserProfileVersion && row.cached_m0_max_compartment_seq === state.cachedM0MaxCompartmentSeq && row.cached_m0_max_memory_id === state.cachedM0MaxMemoryId && row.cached_m0_max_mutation_id === state.cachedM0MaxMutationId && row.cached_m0_max_memory_mutation_id === state.cachedM0MaxMemoryMutationId &&
|
|
170096
|
+
return bufferEqualsNullable(row.cached_m0_bytes, state.cachedM0Bytes) && row.cached_m0_project_memory_epoch === state.cachedM0ProjectMemoryEpoch && (row.cached_m0_workspace_fingerprint ?? null) === (state.cachedM0WorkspaceFingerprint ?? null) && row.cached_m0_project_user_profile_version === state.cachedM0ProjectUserProfileVersion && row.cached_m0_max_compartment_seq === state.cachedM0MaxCompartmentSeq && row.cached_m0_max_memory_id === state.cachedM0MaxMemoryId && row.cached_m0_max_mutation_id === state.cachedM0MaxMutationId && row.cached_m0_max_memory_mutation_id === state.cachedM0MaxMemoryMutationId && row.cached_m0_materialized_at === state.cachedM0MaterializedAt && row.cached_m0_session_facts_version === state.cachedM0SessionFactsVersion && (row.cached_m0_upgrade_state ?? null) === (state.cachedM0UpgradeState ?? null) && (row.cached_m0_system_hash ?? "") === (state.cachedM0SystemHash ?? "") && (row.cached_m0_model_key ?? "") === (state.cachedM0ModelKey ?? "");
|
|
168560
170097
|
}
|
|
168561
170098
|
function applyCachedRowToState(state, row) {
|
|
168562
170099
|
const markers = markersFromCachedRow(row);
|
|
@@ -168566,6 +170103,7 @@ function applyCachedRowToState(state, row) {
|
|
|
168566
170103
|
state.cachedM0Bytes = toBuffer(row.cached_m0_bytes);
|
|
168567
170104
|
state.cachedM1Bytes = toBuffer(row.cached_m1_bytes);
|
|
168568
170105
|
state.cachedM0ProjectMemoryEpoch = markers.projectMemoryEpoch;
|
|
170106
|
+
state.cachedM0WorkspaceFingerprint = markers.workspaceFingerprint;
|
|
168569
170107
|
state.cachedM0ProjectUserProfileVersion = markers.projectUserProfileVersion;
|
|
168570
170108
|
state.cachedM0MaxCompartmentSeq = markers.maxCompartmentSeq;
|
|
168571
170109
|
state.cachedM0MaxMemoryId = markers.maxMemoryId;
|
|
@@ -168576,7 +170114,6 @@ function applyCachedRowToState(state, row) {
|
|
|
168576
170114
|
state.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
|
|
168577
170115
|
state.cachedM0UpgradeState = markers.upgradeState;
|
|
168578
170116
|
state.cachedM0SystemHash = markers.systemHash;
|
|
168579
|
-
state.cachedM0ToolSetHash = markers.toolSetHash;
|
|
168580
170117
|
state.cachedM0ModelKey = markers.modelKey;
|
|
168581
170118
|
state.snapshotMarkers = markers;
|
|
168582
170119
|
}
|
|
@@ -168630,20 +170167,36 @@ function prependM0M1Messages(sessionId, messages, m0Text, m1Text) {
|
|
|
168630
170167
|
function renderFreshM0NonPersisted(options) {
|
|
168631
170168
|
const projectPath = options.projectPath;
|
|
168632
170169
|
const projectDirectory = options.projectDirectory;
|
|
170170
|
+
const workspace = resolveWorkspaceRenderContext({
|
|
170171
|
+
db: options.db,
|
|
170172
|
+
projectPath,
|
|
170173
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
170174
|
+
});
|
|
168633
170175
|
const snapshotMarkers = readCurrentM0SnapshotMarkers({
|
|
168634
170176
|
db: options.db,
|
|
168635
170177
|
sessionId: options.sessionId,
|
|
168636
170178
|
projectPath,
|
|
168637
|
-
projectDirectory
|
|
170179
|
+
projectDirectory,
|
|
170180
|
+
workspaceIdentitySet: {
|
|
170181
|
+
identities: workspace.identities,
|
|
170182
|
+
namesByIdentity: workspace.namesByIdentity
|
|
170183
|
+
}
|
|
168638
170184
|
});
|
|
168639
170185
|
const docs = projectDirectory ? readProjectDocsCanonical(projectDirectory) : { renderedBlock: "", canonicalHash: "" };
|
|
168640
170186
|
snapshotMarkers.projectDocsHash = docs.canonicalHash;
|
|
168641
170187
|
snapshotMarkers.materializedAt = options.state.cachedM0MaterializedAt ?? 0;
|
|
168642
170188
|
const compartments = readM0Compartments(options.db, options.sessionId);
|
|
168643
|
-
const memories = projectPath ? getMemoriesByProject(options.db, projectPath, ["active", "permanent"], snapshotMarkers.materializedAt) : [];
|
|
170189
|
+
const memories = projectPath ? workspace.isWorkspaced ? getMemoriesByProjects(options.db, workspace.expandedIdentities, ["active", "permanent"], snapshotMarkers.materializedAt, workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(options.db, projectPath, ["active", "permanent"], snapshotMarkers.materializedAt) : [];
|
|
168644
170190
|
const userMemories = safeGetActiveUserMemories(options.db);
|
|
168645
170191
|
const memoryBudget = options.memoryInjectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
|
|
168646
|
-
const
|
|
170192
|
+
const memoryRenderOptions = {
|
|
170193
|
+
sourceNameByMemoryId: sourceNamesForMemories({
|
|
170194
|
+
memories,
|
|
170195
|
+
projectPath,
|
|
170196
|
+
workspace
|
|
170197
|
+
})
|
|
170198
|
+
};
|
|
170199
|
+
const trimmed = workspace.isWorkspaced ? trimWorkspaceMemoriesToBudgetV2(options.sessionId, memories, memoryBudget, workspace, memoryRenderOptions) : trimMemoriesToBudgetV2(options.sessionId, memories, memoryBudget);
|
|
168647
170200
|
const budget = options.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS;
|
|
168648
170201
|
let decayPressureMultiplier = 1;
|
|
168649
170202
|
let m0Text = renderM0({
|
|
@@ -168652,6 +170205,7 @@ function renderFreshM0NonPersisted(options) {
|
|
|
168652
170205
|
compartments,
|
|
168653
170206
|
memories: trimmed.renderOrder,
|
|
168654
170207
|
facts: [],
|
|
170208
|
+
memoryRenderOptions,
|
|
168655
170209
|
historyBudgetTokens: budget,
|
|
168656
170210
|
userProfileBudgetTokens: options.userProfileBudgetTokens,
|
|
168657
170211
|
decayPressureMultiplier
|
|
@@ -168665,6 +170219,7 @@ function renderFreshM0NonPersisted(options) {
|
|
|
168665
170219
|
compartments,
|
|
168666
170220
|
memories: trimmed.renderOrder,
|
|
168667
170221
|
facts: [],
|
|
170222
|
+
memoryRenderOptions,
|
|
168668
170223
|
historyBudgetTokens: budget,
|
|
168669
170224
|
userProfileBudgetTokens: options.userProfileBudgetTokens,
|
|
168670
170225
|
decayPressureMultiplier
|
|
@@ -168680,6 +170235,12 @@ function renderFreshM0NonPersisted(options) {
|
|
|
168680
170235
|
};
|
|
168681
170236
|
}
|
|
168682
170237
|
function injectM0M1(options) {
|
|
170238
|
+
if (!options.workspaceIdentitySet && options.projectPath) {
|
|
170239
|
+
options = {
|
|
170240
|
+
...options,
|
|
170241
|
+
workspaceIdentitySet: resolveWorkspaceIdentitySet(options.db, options.projectPath)
|
|
170242
|
+
};
|
|
170243
|
+
}
|
|
168683
170244
|
const skipped = {
|
|
168684
170245
|
injected: false,
|
|
168685
170246
|
m0RematerializedThisPass: false,
|
|
@@ -168696,7 +170257,8 @@ function injectM0M1(options) {
|
|
|
168696
170257
|
state: options.state,
|
|
168697
170258
|
projectPath: options.projectPath,
|
|
168698
170259
|
projectDirectory: options.projectDirectory,
|
|
168699
|
-
hardSignals: options.hardSignals
|
|
170260
|
+
hardSignals: options.hardSignals,
|
|
170261
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
168700
170262
|
});
|
|
168701
170263
|
let rematerialized = false;
|
|
168702
170264
|
let contentionExhausted = false;
|
|
@@ -168790,6 +170352,7 @@ var init_inject_compartments = __esm(async () => {
|
|
|
168790
170352
|
init_compartment_storage();
|
|
168791
170353
|
init_constants();
|
|
168792
170354
|
init_storage_memory();
|
|
170355
|
+
init_workspaces();
|
|
168793
170356
|
init_logger();
|
|
168794
170357
|
init_decay_render();
|
|
168795
170358
|
init_key_files_block();
|
|
@@ -168803,7 +170366,6 @@ var init_inject_compartments = __esm(async () => {
|
|
|
168803
170366
|
CONSTRAINT_KEYWORDS = /\b(must|never|always|cannot|should not|must not)\b/i;
|
|
168804
170367
|
EMPTY_HARD_SIGNALS = {
|
|
168805
170368
|
systemHash: "",
|
|
168806
|
-
toolSetHash: "",
|
|
168807
170369
|
modelKey: "",
|
|
168808
170370
|
cacheExpired: false,
|
|
168809
170371
|
lastResponseTime: 0
|
|
@@ -171930,18 +173492,38 @@ async function runCompartmentAgent(deps) {
|
|
|
171930
173492
|
return;
|
|
171931
173493
|
}
|
|
171932
173494
|
const offset = priorCompartments.length > 0 ? priorCompartments[priorCompartments.length - 1].endMessage + 1 : 1;
|
|
171933
|
-
|
|
173495
|
+
let boundarySnapshot = deps.boundarySnapshot ?? null;
|
|
171934
173496
|
if (!boundarySnapshot) {
|
|
171935
173497
|
telemetry.failureReason = "missing protected-tail boundary snapshot";
|
|
171936
173498
|
sessionLog(sessionId, "historian no-op: missing protected-tail boundary snapshot from trigger decision");
|
|
171937
173499
|
rollbackDrainReservation();
|
|
171938
173500
|
return;
|
|
171939
173501
|
}
|
|
171940
|
-
|
|
173502
|
+
let validation = boundarySnapshot.rawRangeFingerprint.length > 0 ? validateBoundarySnapshot({
|
|
171941
173503
|
db,
|
|
171942
173504
|
snapshot: boundarySnapshot,
|
|
171943
173505
|
currentContextLimit: deps.currentContextLimit ?? boundarySnapshot.contextLimit
|
|
171944
173506
|
}) : { ok: true };
|
|
173507
|
+
if (!validation.ok && validation.reason === "stale_snapshot") {
|
|
173508
|
+
const refreshed = resolveOpenCodeProtectedTailBoundary({
|
|
173509
|
+
db,
|
|
173510
|
+
sessionId,
|
|
173511
|
+
mode: "incremental-runner",
|
|
173512
|
+
contextLimit: deps.currentContextLimit ?? boundarySnapshot.contextLimit,
|
|
173513
|
+
executeThresholdPercentage: boundarySnapshot.executeThresholdPercentage,
|
|
173514
|
+
usage: {
|
|
173515
|
+
percentage: boundarySnapshot.usagePercentage,
|
|
173516
|
+
inputTokens: boundarySnapshot.usageInputTokens
|
|
173517
|
+
},
|
|
173518
|
+
usageSource: boundarySnapshot.usageSource,
|
|
173519
|
+
emergencyTailScale: boundarySnapshot.emergencyTailScale
|
|
173520
|
+
});
|
|
173521
|
+
if (hasRunnableCompartmentWindow(refreshed)) {
|
|
173522
|
+
sessionLog(sessionId, `historian: refreshed stale protected-tail snapshot at run time (was: ${validation.detail ?? "stale"}) — eligible head ${refreshed.offset}-${refreshed.eligibleEndOrdinal - 1}`);
|
|
173523
|
+
boundarySnapshot = refreshed;
|
|
173524
|
+
validation = { ok: true };
|
|
173525
|
+
}
|
|
173526
|
+
}
|
|
171945
173527
|
if (!validation.ok) {
|
|
171946
173528
|
sessionLog(sessionId, `historian no-op: stale protected-tail snapshot (${validation.detail ?? validation.reason ?? "unknown"})`);
|
|
171947
173529
|
telemetry.status = "noop";
|
|
@@ -172010,6 +173592,7 @@ async function runCompartmentAgent(deps) {
|
|
|
172010
173592
|
rollbackDrainReservation();
|
|
172011
173593
|
return;
|
|
172012
173594
|
}
|
|
173595
|
+
deps.onHistorianRunStarted?.();
|
|
172013
173596
|
const projectPath = resolveProjectIdentity(directory ?? process.cwd());
|
|
172014
173597
|
const memories = getMemoriesByProject(db, projectPath, ["active", "permanent"]);
|
|
172015
173598
|
const projectMemory = renderMemoryBlock(memories) ?? "";
|
|
@@ -172142,8 +173725,13 @@ ${chunkText}`,
|
|
|
172142
173725
|
}
|
|
172143
173726
|
if (embeddingActive) {
|
|
172144
173727
|
const projectIdentity = resolveProjectIdentity(promotionDirectory);
|
|
172145
|
-
const
|
|
172146
|
-
|
|
173728
|
+
const chunksToEmbed = persistedCompartments.map((c, i) => ({
|
|
173729
|
+
id: persistedIds[i],
|
|
173730
|
+
startMessage: c.startMessage,
|
|
173731
|
+
endMessage: c.endMessage,
|
|
173732
|
+
sourceChunkText: chunk.text
|
|
173733
|
+
})).filter((c) => typeof c.id === "number");
|
|
173734
|
+
embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed);
|
|
172147
173735
|
}
|
|
172148
173736
|
queueDropsForCompartmentalizedMessages(db, sessionId, lastCompartmentEnd);
|
|
172149
173737
|
deps.onCompartmentStatePublished?.(sessionId);
|
|
@@ -172374,8 +173962,12 @@ Found ${existingStaging.compartments.length} staged compartment(s) from ${existi
|
|
|
172374
173962
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
172375
173963
|
await deps.ensureProjectRegistered?.(sessionDirectory, db);
|
|
172376
173964
|
const liveCompartments = getCompartments(db, sessionId);
|
|
172377
|
-
const
|
|
172378
|
-
|
|
173965
|
+
const chunksToEmbed = liveCompartments.map((c) => ({
|
|
173966
|
+
id: c.id,
|
|
173967
|
+
startMessage: c.startMessage,
|
|
173968
|
+
endMessage: c.endMessage
|
|
173969
|
+
}));
|
|
173970
|
+
embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed);
|
|
172379
173971
|
}
|
|
172380
173972
|
const lastCompartmentEnd2 = promoted2.compartments[promoted2.compartments.length - 1]?.endMessage ?? 0;
|
|
172381
173973
|
if (lastCompartmentEnd2 > 0) {
|
|
@@ -172588,8 +174180,12 @@ Another process acquired the compartment-state lease before recomp could publish
|
|
|
172588
174180
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
172589
174181
|
await deps.ensureProjectRegistered?.(sessionDirectory, db);
|
|
172590
174182
|
const liveCompartments = getCompartments(db, sessionId);
|
|
172591
|
-
const
|
|
172592
|
-
|
|
174183
|
+
const chunksToEmbed = liveCompartments.map((c) => ({
|
|
174184
|
+
id: c.id,
|
|
174185
|
+
startMessage: c.startMessage,
|
|
174186
|
+
endMessage: c.endMessage
|
|
174187
|
+
}));
|
|
174188
|
+
embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed);
|
|
172593
174189
|
}
|
|
172594
174190
|
if (lastCompartmentEnd > 0) {
|
|
172595
174191
|
const markerUpdated = updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, deps.directory);
|
|
@@ -172770,8 +174366,12 @@ Could not acquire the compartment-state lease for this session.`;
|
|
|
172770
174366
|
if (deps.memoryEnabled !== false) {
|
|
172771
174367
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
172772
174368
|
const liveCompartments = getCompartments(db, sessionId);
|
|
172773
|
-
const
|
|
172774
|
-
|
|
174369
|
+
const chunksToEmbed = liveCompartments.map((c) => ({
|
|
174370
|
+
id: c.id,
|
|
174371
|
+
startMessage: c.startMessage,
|
|
174372
|
+
endMessage: c.endMessage
|
|
174373
|
+
}));
|
|
174374
|
+
Promise.resolve(deps.ensureProjectRegistered?.(sessionDirectory, db)).then(() => embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed));
|
|
172775
174375
|
}
|
|
172776
174376
|
const lastEnd = merged[merged.length - 1]?.endMessage ?? snapEnd;
|
|
172777
174377
|
if (lastEnd > 0) {
|
|
@@ -175021,7 +176621,14 @@ function startCompartmentAgent(deps) {
|
|
|
175021
176621
|
return;
|
|
175022
176622
|
}
|
|
175023
176623
|
const renewal = startLeaseRenewal(deps, holderId);
|
|
175024
|
-
|
|
176624
|
+
let realRunStarted = false;
|
|
176625
|
+
const runnerDeps = withPublishedCallback({
|
|
176626
|
+
...deps,
|
|
176627
|
+
compartmentLeaseHolderId: holderId,
|
|
176628
|
+
onHistorianRunStarted: () => {
|
|
176629
|
+
realRunStarted = true;
|
|
176630
|
+
}
|
|
176631
|
+
});
|
|
175025
176632
|
const promise2 = runCompartmentAgent(runnerDeps).catch((err) => {
|
|
175026
176633
|
sessionLog(deps.sessionId, "compartment agent: unhandled rejection:", err);
|
|
175027
176634
|
try {
|
|
@@ -175035,6 +176642,9 @@ function startCompartmentAgent(deps) {
|
|
|
175035
176642
|
}
|
|
175036
176643
|
});
|
|
175037
176644
|
activeRuns.set(deps.sessionId, { promise: promise2, published: false });
|
|
176645
|
+
if (!realRunStarted && activeRuns.get(deps.sessionId)?.promise === promise2) {
|
|
176646
|
+
activeRuns.delete(deps.sessionId);
|
|
176647
|
+
}
|
|
175038
176648
|
}
|
|
175039
176649
|
async function executeContextRecompWithResult(deps, options = {}) {
|
|
175040
176650
|
const { sessionId } = deps;
|
|
@@ -175169,7 +176779,7 @@ function applyMemoryMigration(db, projectPath, result) {
|
|
|
175169
176779
|
inserted++;
|
|
175170
176780
|
}
|
|
175171
176781
|
if (removed > 0 || inserted > 0) {
|
|
175172
|
-
|
|
176782
|
+
bumpEpochsForWorkspaceMembers(db, projectPath);
|
|
175173
176783
|
}
|
|
175174
176784
|
})();
|
|
175175
176785
|
return { removed, inserted };
|
|
@@ -175627,15 +177237,15 @@ function shouldShowAnnouncement() {
|
|
|
175627
177237
|
}
|
|
175628
177238
|
return state.version !== ANNOUNCEMENT_VERSION;
|
|
175629
177239
|
}
|
|
175630
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
177240
|
+
var ANNOUNCEMENT_VERSION = "0.24.0", ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU", STATE_FILENAME = "last_announced_version";
|
|
175631
177241
|
var init_announcement = __esm(() => {
|
|
175632
177242
|
init_data_path();
|
|
175633
177243
|
ANNOUNCEMENT_FEATURES = [
|
|
175634
|
-
"
|
|
175635
|
-
"
|
|
175636
|
-
"
|
|
175637
|
-
"
|
|
175638
|
-
"
|
|
177244
|
+
"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).",
|
|
177245
|
+
"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.",
|
|
177246
|
+
"Pi: fixed sessions overflowing the model context while still showing moderate usage — Pi now sheds context before a tool-heavy turn overflows.",
|
|
177247
|
+
"Fewer prompt-cache busts: doc edits, processed screenshots, and a rebuild-then-bust-again case no longer re-bill large prompt prefixes.",
|
|
177248
|
+
"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)."
|
|
175639
177249
|
];
|
|
175640
177250
|
});
|
|
175641
177251
|
|
|
@@ -176429,6 +178039,10 @@ function getMagicContextBuiltinCommands() {
|
|
|
176429
178039
|
"ctx-dream": {
|
|
176430
178040
|
template: "ctx-dream",
|
|
176431
178041
|
description: "Run the hidden dreamer maintenance pass for this project now"
|
|
178042
|
+
},
|
|
178043
|
+
"ctx-embed-history": {
|
|
178044
|
+
template: "ctx-embed-history",
|
|
178045
|
+
description: "Embed all of this session's history compartments for semantic search, in one pass"
|
|
176432
178046
|
}
|
|
176433
178047
|
};
|
|
176434
178048
|
}
|
|
@@ -176922,7 +178536,7 @@ await init_storage_db();
|
|
|
176922
178536
|
// src/features/magic-context/v22-deferred-backfill.ts
|
|
176923
178537
|
init_logger();
|
|
176924
178538
|
init_project_identity();
|
|
176925
|
-
import { createHash as
|
|
178539
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
176926
178540
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
176927
178541
|
import path5 from "node:path";
|
|
176928
178542
|
var BATCH_SIZE = 25;
|
|
@@ -176976,7 +178590,7 @@ function computeLegacyRustDirIdentity(rawProjectPath) {
|
|
|
176976
178590
|
} catch {
|
|
176977
178591
|
canonical = path5.isAbsolute(rawProjectPath) ? rawProjectPath : path5.join(process.cwd(), rawProjectPath);
|
|
176978
178592
|
}
|
|
176979
|
-
return `dir:${
|
|
178593
|
+
return `dir:${createHash6("sha256").update(canonical, "utf8").digest("hex")}`;
|
|
176980
178594
|
}
|
|
176981
178595
|
function upsertRekeyMap(db, oldProjectPath, newProjectPath, rekeyedAt) {
|
|
176982
178596
|
db.prepare(`INSERT INTO v22_identity_rekey_map (old_project_path, new_project_path, rekeyed_at)
|
|
@@ -180114,7 +181728,7 @@ init_project_identity();
|
|
|
180114
181728
|
// src/plugin/embedding-bootstrap-helpers.ts
|
|
180115
181729
|
init_embedding();
|
|
180116
181730
|
init_logger();
|
|
180117
|
-
import { createHash as
|
|
181731
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
180118
181732
|
var EMBEDDING_AFFECTING_KEYS = new Set([
|
|
180119
181733
|
"embedding.api_key",
|
|
180120
181734
|
"embedding.endpoint",
|
|
@@ -180135,7 +181749,7 @@ var EMBEDDING_WARNING_TERMS = [
|
|
|
180135
181749
|
];
|
|
180136
181750
|
var loggedFailureSignatures = new Map;
|
|
180137
181751
|
function sha256Prefix2(value, length = 16) {
|
|
180138
|
-
return
|
|
181752
|
+
return createHash10("sha256").update(value).digest("hex").slice(0, length);
|
|
180139
181753
|
}
|
|
180140
181754
|
function warningLooksEmbeddingRelated(message) {
|
|
180141
181755
|
const lower = message.toLowerCase();
|
|
@@ -180772,7 +182386,7 @@ function createTagger() {
|
|
|
180772
182386
|
// src/hooks/magic-context/hook.ts
|
|
180773
182387
|
init_magic_context();
|
|
180774
182388
|
init_project_identity();
|
|
180775
|
-
|
|
182389
|
+
init_project_embedding_registry();
|
|
180776
182390
|
await init_storage();
|
|
180777
182391
|
init_logger();
|
|
180778
182392
|
init_resolve_fallbacks();
|
|
@@ -181366,6 +182980,7 @@ function createMagicContextCommandHandler(deps) {
|
|
|
181366
182980
|
const isAugCommand = (command) => command === "ctx-aug";
|
|
181367
182981
|
const isDreamCommand = (command) => command === "ctx-dream";
|
|
181368
182982
|
const isSessionUpgradeCommand = (command) => command === "ctx-session-upgrade";
|
|
182983
|
+
const isEmbedHistoryCommand = (command) => command === "ctx-embed-history";
|
|
181369
182984
|
return {
|
|
181370
182985
|
"command.execute.before": async (input, _output, _params) => {
|
|
181371
182986
|
const isStatus = isStatusCommand(input.command);
|
|
@@ -181374,7 +182989,8 @@ function createMagicContextCommandHandler(deps) {
|
|
|
181374
182989
|
const isAug = isAugCommand(input.command);
|
|
181375
182990
|
const isDream = isDreamCommand(input.command);
|
|
181376
182991
|
const isSessionUpgrade = isSessionUpgradeCommand(input.command);
|
|
181377
|
-
|
|
182992
|
+
const isEmbedHistory = isEmbedHistoryCommand(input.command);
|
|
182993
|
+
if (!isStatus && !isFlush && !isRecomp && !isAug && !isDream && !isSessionUpgrade && !isEmbedHistory) {
|
|
181378
182994
|
return;
|
|
181379
182995
|
}
|
|
181380
182996
|
const sessionId = input.sessionID;
|
|
@@ -181387,6 +183003,11 @@ function createMagicContextCommandHandler(deps) {
|
|
|
181387
183003
|
await executeDreaming(deps, sessionId);
|
|
181388
183004
|
return;
|
|
181389
183005
|
}
|
|
183006
|
+
if (isEmbedHistory) {
|
|
183007
|
+
const summary = deps.executeEmbedHistory ? await deps.executeEmbedHistory(sessionId) : "Semantic embedding is not configured for this project, so there is nothing to embed.";
|
|
183008
|
+
await deps.sendNotification(sessionId, summary, {});
|
|
183009
|
+
throwSentinel(input.command);
|
|
183010
|
+
}
|
|
181390
183011
|
if (isFlush) {
|
|
181391
183012
|
result = executeFlush(deps.db, sessionId);
|
|
181392
183013
|
clearCachedM0M1(deps.db, sessionId);
|
|
@@ -182127,6 +183748,7 @@ await init_read_session_chunk();
|
|
|
182127
183748
|
// src/hooks/magic-context/transform.ts
|
|
182128
183749
|
init_project_identity();
|
|
182129
183750
|
import * as crypto2 from "node:crypto";
|
|
183751
|
+
init_session_project_storage();
|
|
182130
183752
|
init_storage_meta_persisted();
|
|
182131
183753
|
init_logger();
|
|
182132
183754
|
await init_storage();
|
|
@@ -182508,6 +184130,63 @@ function replayCavemanCompression(sessionId, db, targets, tags) {
|
|
|
182508
184130
|
|
|
182509
184131
|
// src/hooks/magic-context/transform.ts
|
|
182510
184132
|
await init_compartment_runner();
|
|
184133
|
+
|
|
184134
|
+
// src/hooks/magic-context/ctx-reduce-availability.ts
|
|
184135
|
+
init_logger();
|
|
184136
|
+
await init_read_session_db();
|
|
184137
|
+
var availabilityBySession = new BoundedSessionMap(500);
|
|
184138
|
+
function verdictFromToolsMap(tools) {
|
|
184139
|
+
if (tools === null || typeof tools !== "object" || Array.isArray(tools))
|
|
184140
|
+
return null;
|
|
184141
|
+
const map2 = tools;
|
|
184142
|
+
if (map2.ctx_reduce === true)
|
|
184143
|
+
return true;
|
|
184144
|
+
if (map2.ctx_reduce === false)
|
|
184145
|
+
return false;
|
|
184146
|
+
if (map2["*"] === false)
|
|
184147
|
+
return false;
|
|
184148
|
+
return null;
|
|
184149
|
+
}
|
|
184150
|
+
function resolveCtxReduceAvailabilityFromMessages(sessionId, messages) {
|
|
184151
|
+
const cached2 = availabilityBySession.get(sessionId);
|
|
184152
|
+
if (cached2 !== undefined)
|
|
184153
|
+
return cached2;
|
|
184154
|
+
for (const message of messages) {
|
|
184155
|
+
if (message.info?.role !== "user")
|
|
184156
|
+
continue;
|
|
184157
|
+
const verdict = verdictFromToolsMap(message.info.tools);
|
|
184158
|
+
if (verdict !== null) {
|
|
184159
|
+
availabilityBySession.set(sessionId, verdict);
|
|
184160
|
+
return verdict;
|
|
184161
|
+
}
|
|
184162
|
+
break;
|
|
184163
|
+
}
|
|
184164
|
+
availabilityBySession.set(sessionId, true);
|
|
184165
|
+
return true;
|
|
184166
|
+
}
|
|
184167
|
+
function resolveCtxReduceAvailability(sessionId) {
|
|
184168
|
+
const cached2 = availabilityBySession.get(sessionId);
|
|
184169
|
+
if (cached2 !== undefined)
|
|
184170
|
+
return cached2;
|
|
184171
|
+
if (!openCodeDbExists())
|
|
184172
|
+
return true;
|
|
184173
|
+
try {
|
|
184174
|
+
const row = withReadOnlySessionDb((db) => db.prepare(`SELECT json_extract(data, '$.tools') AS tools FROM message
|
|
184175
|
+
WHERE session_id = ? AND json_extract(data, '$.role') = 'user'
|
|
184176
|
+
ORDER BY time_created ASC LIMIT 1`).get(sessionId));
|
|
184177
|
+
if (!row)
|
|
184178
|
+
return true;
|
|
184179
|
+
const verdict = row.tools === null ? null : verdictFromToolsMap(JSON.parse(row.tools));
|
|
184180
|
+
const resolved = verdict ?? true;
|
|
184181
|
+
availabilityBySession.set(sessionId, resolved);
|
|
184182
|
+
return resolved;
|
|
184183
|
+
} catch (error51) {
|
|
184184
|
+
sessionLog(sessionId, "ctx_reduce availability read failed (fail-open):", error51);
|
|
184185
|
+
return true;
|
|
184186
|
+
}
|
|
184187
|
+
}
|
|
184188
|
+
|
|
184189
|
+
// src/hooks/magic-context/transform.ts
|
|
182511
184190
|
init_derive_budgets();
|
|
182512
184191
|
|
|
182513
184192
|
// src/hooks/magic-context/image-token-estimate.ts
|
|
@@ -182670,6 +184349,7 @@ await __promiseAll([
|
|
|
182670
184349
|
init_read_session_chunk(),
|
|
182671
184350
|
init_read_session_db()
|
|
182672
184351
|
]);
|
|
184352
|
+
|
|
182673
184353
|
// src/hooks/magic-context/sentinel.ts
|
|
182674
184354
|
var WHOLE_MESSAGE_PLACEHOLDER_TEXT = "[dropped]";
|
|
182675
184355
|
function modelAcceptsEmptyContent(providerID) {
|
|
@@ -182727,7 +184407,6 @@ function replaySentinelByMessageIds(messages, ids, providerID) {
|
|
|
182727
184407
|
missingIds.push(id);
|
|
182728
184408
|
return { replayed, missingIds };
|
|
182729
184409
|
}
|
|
182730
|
-
|
|
182731
184410
|
// src/hooks/magic-context/strip-content.ts
|
|
182732
184411
|
var DROPPED_PLACEHOLDER_PATTERN = /^\[dropped §\d+§\]$/;
|
|
182733
184412
|
var TAG_PREFIX_PATTERN = /^§\d+§\s*/;
|
|
@@ -183080,8 +184759,10 @@ function stripReasoningFromMergedAssistants(messages, providerID) {
|
|
|
183080
184759
|
}
|
|
183081
184760
|
return stripped;
|
|
183082
184761
|
}
|
|
183083
|
-
function stripProcessedImages(messages,
|
|
184762
|
+
function stripProcessedImages(messages, frozenIds, options) {
|
|
184763
|
+
const { detect, watermark, messageTagNumbers } = options;
|
|
183084
184764
|
let stripped = 0;
|
|
184765
|
+
const newlyStrippedIds = [];
|
|
183085
184766
|
let hasAssistantResponse = false;
|
|
183086
184767
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
183087
184768
|
const msg = messages[i];
|
|
@@ -183089,13 +184770,17 @@ function stripProcessedImages(messages, watermark, messageTagNumbers) {
|
|
|
183089
184770
|
hasAssistantResponse = true;
|
|
183090
184771
|
continue;
|
|
183091
184772
|
}
|
|
183092
|
-
if (msg.info.role !== "user"
|
|
184773
|
+
if (msg.info.role !== "user") {
|
|
183093
184774
|
continue;
|
|
183094
184775
|
}
|
|
184776
|
+
const id = typeof msg.info.id === "string" ? msg.info.id : undefined;
|
|
184777
|
+
const inFrozen = id !== undefined && frozenIds.has(id);
|
|
183095
184778
|
const maxTag = messageTagNumbers.get(msg) ?? 0;
|
|
183096
|
-
|
|
184779
|
+
const isNewDetection = !inFrozen && detect && hasAssistantResponse && id !== undefined && maxTag <= watermark;
|
|
184780
|
+
if (!inFrozen && !isNewDetection) {
|
|
183097
184781
|
continue;
|
|
183098
184782
|
}
|
|
184783
|
+
let touchedThisMsg = false;
|
|
183099
184784
|
for (let j = 0;j < msg.parts.length; j++) {
|
|
183100
184785
|
const part = msg.parts[j];
|
|
183101
184786
|
if (!isRecord(part) || part.type !== "file") {
|
|
@@ -183107,10 +184792,14 @@ function stripProcessedImages(messages, watermark, messageTagNumbers) {
|
|
|
183107
184792
|
if (typeof part.url === "string" && part.url.startsWith("data:") && part.url.length > 200) {
|
|
183108
184793
|
msg.parts[j] = makeSentinel(part);
|
|
183109
184794
|
stripped++;
|
|
184795
|
+
touchedThisMsg = true;
|
|
183110
184796
|
}
|
|
183111
184797
|
}
|
|
184798
|
+
if (touchedThisMsg && isNewDetection && id !== undefined) {
|
|
184799
|
+
newlyStrippedIds.push(id);
|
|
184800
|
+
}
|
|
183112
184801
|
}
|
|
183113
|
-
return stripped;
|
|
184802
|
+
return { stripped, newlyStrippedIds };
|
|
183114
184803
|
}
|
|
183115
184804
|
|
|
183116
184805
|
// src/hooks/magic-context/transform.ts
|
|
@@ -183426,6 +185115,7 @@ function appendReminderToUserMessage(message, reminder) {
|
|
|
183426
185115
|
init_tag_part_guards();
|
|
183427
185116
|
await init_storage();
|
|
183428
185117
|
var USER_DROP_PREVIEW_CHARS = 250;
|
|
185118
|
+
var RECENT_TOOL_SKELETON_WINDOW = 20;
|
|
183429
185119
|
function buildReplacementContent(tagId, target) {
|
|
183430
185120
|
const role = target.message?.info.role;
|
|
183431
185121
|
if (role !== "user") {
|
|
@@ -183451,6 +185141,7 @@ function applyPendingOperations(sessionId, db, targets, protectedTags = 0, prelo
|
|
|
183451
185141
|
const tagTypeById = new Map(tags.map((tag) => [tag.tagNumber, tag.type]));
|
|
183452
185142
|
const protectedTagIds = protectedTags > 0 ? new Set(tags.filter((tag) => tag.status === "active").map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, protectedTags)) : new Set;
|
|
183453
185143
|
const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
|
|
185144
|
+
const skeletonWindow = new Set(tags.filter((tag) => tag.type === "tool").map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, RECENT_TOOL_SKELETON_WINDOW));
|
|
183454
185145
|
for (const pendingOp of pendingOps) {
|
|
183455
185146
|
const tagStatus = tagStatusById.get(pendingOp.tagId);
|
|
183456
185147
|
if (tagStatus === "compacted" || tagStatus === "dropped") {
|
|
@@ -183463,14 +185154,25 @@ function applyPendingOperations(sessionId, db, targets, protectedTags = 0, prelo
|
|
|
183463
185154
|
const target = targets.get(pendingOp.tagId);
|
|
183464
185155
|
const isToolTag = tagTypeById.get(pendingOp.tagId) === "tool";
|
|
183465
185156
|
if (isToolTag) {
|
|
183466
|
-
|
|
183467
|
-
|
|
183468
|
-
|
|
183469
|
-
|
|
183470
|
-
|
|
183471
|
-
|
|
185157
|
+
if (skeletonWindow.has(pendingOp.tagId)) {
|
|
185158
|
+
const truncResult = target?.truncate?.() ?? "absent";
|
|
185159
|
+
if (truncResult === "incomplete") {
|
|
185160
|
+
continue;
|
|
185161
|
+
}
|
|
185162
|
+
if (truncResult === "truncated") {
|
|
185163
|
+
didMutateMessage = true;
|
|
185164
|
+
}
|
|
185165
|
+
updateTagDropMode(db, sessionId, pendingOp.tagId, "truncated");
|
|
185166
|
+
} else {
|
|
185167
|
+
const dropResult = target?.drop?.() ?? "absent";
|
|
185168
|
+
if (dropResult === "incomplete") {
|
|
185169
|
+
continue;
|
|
185170
|
+
}
|
|
185171
|
+
if (dropResult === "removed") {
|
|
185172
|
+
didMutateMessage = true;
|
|
185173
|
+
}
|
|
185174
|
+
updateTagDropMode(db, sessionId, pendingOp.tagId, "full");
|
|
183472
185175
|
}
|
|
183473
|
-
updateTagDropMode(db, sessionId, pendingOp.tagId, "full");
|
|
183474
185176
|
} else if (target) {
|
|
183475
185177
|
const changed = target.setContent(buildReplacementContent(pendingOp.tagId, target));
|
|
183476
185178
|
if (changed)
|
|
@@ -184040,6 +185742,7 @@ init_embedding();
|
|
|
184040
185742
|
|
|
184041
185743
|
// src/features/magic-context/search.ts
|
|
184042
185744
|
init_logger();
|
|
185745
|
+
init_compartment_chunk_embedding();
|
|
184043
185746
|
|
|
184044
185747
|
// src/features/magic-context/literal-probes.ts
|
|
184045
185748
|
var MAX_PROBES = 5;
|
|
@@ -184101,6 +185804,7 @@ function containsProbeVerbatim(text, probes) {
|
|
|
184101
185804
|
init_memory();
|
|
184102
185805
|
init_embedding();
|
|
184103
185806
|
init_storage_memory_fts();
|
|
185807
|
+
init_workspaces();
|
|
184104
185808
|
var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
|
|
184105
185809
|
var FTS_SEMANTIC_CANDIDATE_LIMIT = 50;
|
|
184106
185810
|
var SEMANTIC_WEIGHT = 0.7;
|
|
@@ -184130,6 +185834,37 @@ function previewText(text) {
|
|
|
184130
185834
|
}
|
|
184131
185835
|
return `${normalized.slice(0, RESULT_PREVIEW_LIMIT - 1).trimEnd()}…`;
|
|
184132
185836
|
}
|
|
185837
|
+
function resolveSearchWorkspaceContext(db, projectPath, identitySet) {
|
|
185838
|
+
const resolved = identitySet ?? resolveWorkspaceIdentitySet(db, projectPath);
|
|
185839
|
+
const isWorkspaced = resolved.identities.length > 1;
|
|
185840
|
+
const expanded = expandWorkspaceIdentitySetWithAliases(db, resolved.identities);
|
|
185841
|
+
const expandedIdentities = isWorkspaced ? expanded.expandedIdentities : resolved.identities;
|
|
185842
|
+
const canonicalIdentityByStoredPath = isWorkspaced ? expanded.canonicalIdentityByStoredPath : new Map(resolved.identities.map((identity) => [identity, identity]));
|
|
185843
|
+
const ownIdentities = expandedIdentities.filter((identity) => canonicalIdentityByStoredPath.get(identity) === projectPath);
|
|
185844
|
+
return {
|
|
185845
|
+
identities: resolved.identities,
|
|
185846
|
+
expandedIdentities,
|
|
185847
|
+
ownIdentities,
|
|
185848
|
+
shareCategories: isWorkspaced ? resolveWorkspaceShareCategories(db, projectPath) : null,
|
|
185849
|
+
namesByIdentity: resolved.namesByIdentity,
|
|
185850
|
+
canonicalIdentityByStoredPath,
|
|
185851
|
+
isWorkspaced
|
|
185852
|
+
};
|
|
185853
|
+
}
|
|
185854
|
+
function memoryWorkspaceIdentity(memory, workspace) {
|
|
185855
|
+
return resolveStoredPathWorkspaceIdentity(memory.projectPath, workspace.identities, workspace.canonicalIdentityByStoredPath);
|
|
185856
|
+
}
|
|
185857
|
+
function sourceNamesForSearchMemories(args) {
|
|
185858
|
+
if (!args.workspace.isWorkspaced)
|
|
185859
|
+
return;
|
|
185860
|
+
const sourceNames = new Map;
|
|
185861
|
+
for (const memory of args.memories) {
|
|
185862
|
+
const source = sourceNameForMemory(memory.projectPath, args.projectPath, args.workspace.identities, args.workspace.namesByIdentity, args.workspace.canonicalIdentityByStoredPath);
|
|
185863
|
+
if (source)
|
|
185864
|
+
sourceNames.set(memory.id, source);
|
|
185865
|
+
}
|
|
185866
|
+
return sourceNames.size > 0 ? sourceNames : undefined;
|
|
185867
|
+
}
|
|
184133
185868
|
function getMessageSearchStatement(db) {
|
|
184134
185869
|
let stmt = messageSearchStatements.get(db);
|
|
184135
185870
|
if (!stmt) {
|
|
@@ -184138,6 +185873,30 @@ function getMessageSearchStatement(db) {
|
|
|
184138
185873
|
}
|
|
184139
185874
|
return stmt;
|
|
184140
185875
|
}
|
|
185876
|
+
var ftsRowCountStatements = new WeakMap;
|
|
185877
|
+
var ftsMatchCountStatements = new WeakMap;
|
|
185878
|
+
function getSessionFtsRowCount(db, sessionId) {
|
|
185879
|
+
let stmt = ftsRowCountStatements.get(db);
|
|
185880
|
+
if (!stmt) {
|
|
185881
|
+
stmt = db.prepare("SELECT COUNT(*) AS n FROM message_history_fts WHERE session_id = ?");
|
|
185882
|
+
ftsRowCountStatements.set(db, stmt);
|
|
185883
|
+
}
|
|
185884
|
+
const row = stmt.get(sessionId);
|
|
185885
|
+
return typeof row?.n === "number" ? row.n : 0;
|
|
185886
|
+
}
|
|
185887
|
+
function countSessionFtsMatches(db, sessionId, ftsQuery) {
|
|
185888
|
+
let stmt = ftsMatchCountStatements.get(db);
|
|
185889
|
+
if (!stmt) {
|
|
185890
|
+
stmt = db.prepare("SELECT COUNT(*) AS n FROM message_history_fts WHERE session_id = ? AND message_history_fts MATCH ?");
|
|
185891
|
+
ftsMatchCountStatements.set(db, stmt);
|
|
185892
|
+
}
|
|
185893
|
+
try {
|
|
185894
|
+
const row = stmt.get(sessionId, ftsQuery);
|
|
185895
|
+
return typeof row?.n === "number" ? row.n : 0;
|
|
185896
|
+
} catch {
|
|
185897
|
+
return 0;
|
|
185898
|
+
}
|
|
185899
|
+
}
|
|
184141
185900
|
function getMessageOrdinal(value) {
|
|
184142
185901
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
184143
185902
|
return value;
|
|
@@ -184153,25 +185912,63 @@ async function getSemanticScores(args) {
|
|
|
184153
185912
|
if (!args.queryEmbedding || args.memories.length === 0) {
|
|
184154
185913
|
return semanticScores;
|
|
184155
185914
|
}
|
|
184156
|
-
|
|
184157
|
-
|
|
184158
|
-
|
|
184159
|
-
|
|
184160
|
-
|
|
184161
|
-
|
|
184162
|
-
|
|
185915
|
+
if (!args.workspace?.isWorkspaced) {
|
|
185916
|
+
const cachedEmbeddings = getProjectEmbeddings(args.db, args.projectPath);
|
|
185917
|
+
const embeddings = await ensureMemoryEmbeddings({
|
|
185918
|
+
db: args.db,
|
|
185919
|
+
projectIdentity: args.projectPath,
|
|
185920
|
+
memories: args.memories,
|
|
185921
|
+
existingEmbeddings: cachedEmbeddings
|
|
185922
|
+
});
|
|
185923
|
+
for (const memory of args.memories) {
|
|
185924
|
+
const memoryEmbedding = embeddings.get(memory.id);
|
|
185925
|
+
if (!memoryEmbedding) {
|
|
185926
|
+
continue;
|
|
185927
|
+
}
|
|
185928
|
+
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding.embedding)));
|
|
185929
|
+
}
|
|
185930
|
+
return semanticScores;
|
|
185931
|
+
}
|
|
185932
|
+
if (!args.queryModelId || args.queryModelId === "off") {
|
|
185933
|
+
return semanticScores;
|
|
185934
|
+
}
|
|
185935
|
+
const workspace = args.workspace;
|
|
185936
|
+
const memoriesByIdentity = new Map;
|
|
184163
185937
|
for (const memory of args.memories) {
|
|
184164
|
-
const
|
|
184165
|
-
if (!
|
|
185938
|
+
const identity = memoryWorkspaceIdentity(memory, workspace);
|
|
185939
|
+
if (!identity)
|
|
185940
|
+
continue;
|
|
185941
|
+
const list = memoriesByIdentity.get(identity) ?? [];
|
|
185942
|
+
list.push(memory);
|
|
185943
|
+
memoriesByIdentity.set(identity, list);
|
|
185944
|
+
}
|
|
185945
|
+
const ownMemories = memoriesByIdentity.get(args.projectPath) ?? [];
|
|
185946
|
+
if (ownMemories.length > 0) {
|
|
185947
|
+
const ownEmbeddings = getProjectEmbeddings(args.db, args.projectPath);
|
|
185948
|
+
await ensureMemoryEmbeddings({
|
|
185949
|
+
db: args.db,
|
|
185950
|
+
projectIdentity: args.projectPath,
|
|
185951
|
+
memories: ownMemories,
|
|
185952
|
+
existingEmbeddings: ownEmbeddings
|
|
185953
|
+
});
|
|
185954
|
+
}
|
|
185955
|
+
for (const identity of workspace.identities) {
|
|
185956
|
+
const memberMemories = memoriesByIdentity.get(identity) ?? [];
|
|
185957
|
+
if (memberMemories.length === 0)
|
|
184166
185958
|
continue;
|
|
185959
|
+
const cachedEmbeddings = getProjectEmbeddings(args.db, identity);
|
|
185960
|
+
for (const memory of memberMemories) {
|
|
185961
|
+
const memoryEmbedding = cachedEmbeddings.get(memory.id);
|
|
185962
|
+
if (!memoryEmbedding || memoryEmbedding.modelId !== args.queryModelId)
|
|
185963
|
+
continue;
|
|
185964
|
+
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding.embedding)));
|
|
184167
185965
|
}
|
|
184168
|
-
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding)));
|
|
184169
185966
|
}
|
|
184170
185967
|
return semanticScores;
|
|
184171
185968
|
}
|
|
184172
185969
|
function getFtsMatches(args) {
|
|
184173
185970
|
try {
|
|
184174
|
-
return searchMemoriesFTS(args.db, args.projectPath, args.query, args.limit);
|
|
185971
|
+
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);
|
|
184175
185972
|
} catch (error51) {
|
|
184176
185973
|
log(`[search] FTS query failed for "${args.query}": ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
184177
185974
|
return [];
|
|
@@ -184185,8 +185982,11 @@ function selectSemanticCandidates(args) {
|
|
|
184185
185982
|
return args.memories;
|
|
184186
185983
|
}
|
|
184187
185984
|
const candidateIds = new Set(args.ftsMatches.map((memory) => memory.id));
|
|
184188
|
-
const
|
|
184189
|
-
|
|
185985
|
+
const embeddingProjects = args.workspace?.isWorkspaced ? args.workspace.identities : [args.projectPath];
|
|
185986
|
+
for (const projectPath of embeddingProjects) {
|
|
185987
|
+
const cachedEmbeddings = peekProjectEmbeddings(projectPath);
|
|
185988
|
+
if (!cachedEmbeddings)
|
|
185989
|
+
continue;
|
|
184190
185990
|
for (const memoryId of cachedEmbeddings.keys()) {
|
|
184191
185991
|
candidateIds.add(memoryId);
|
|
184192
185992
|
}
|
|
@@ -184228,7 +186028,8 @@ function mergeMemoryResults(args) {
|
|
|
184228
186028
|
score,
|
|
184229
186029
|
memoryId: memory.id,
|
|
184230
186030
|
category: memory.category,
|
|
184231
|
-
matchType
|
|
186031
|
+
matchType,
|
|
186032
|
+
sourceName: args.sourceNameByMemoryId?.get(memory.id)
|
|
184232
186033
|
});
|
|
184233
186034
|
}
|
|
184234
186035
|
return results.sort((left, right) => {
|
|
@@ -184242,7 +186043,7 @@ async function searchMemories(args) {
|
|
|
184242
186043
|
if (!args.memoryEnabled) {
|
|
184243
186044
|
return [];
|
|
184244
186045
|
}
|
|
184245
|
-
const memories = getMemoriesByProject(args.db, args.projectPath);
|
|
186046
|
+
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);
|
|
184246
186047
|
if (memories.length === 0) {
|
|
184247
186048
|
return [];
|
|
184248
186049
|
}
|
|
@@ -184250,26 +186051,43 @@ async function searchMemories(args) {
|
|
|
184250
186051
|
db: args.db,
|
|
184251
186052
|
projectPath: args.projectPath,
|
|
184252
186053
|
query: args.query,
|
|
184253
|
-
limit: FTS_SEMANTIC_CANDIDATE_LIMIT
|
|
186054
|
+
limit: FTS_SEMANTIC_CANDIDATE_LIMIT,
|
|
186055
|
+
workspace: args.workspace
|
|
184254
186056
|
});
|
|
184255
186057
|
const ftsScores = getFtsScores(ftsMatches);
|
|
184256
186058
|
const semanticCandidates = selectSemanticCandidates({
|
|
184257
186059
|
memories,
|
|
184258
186060
|
projectPath: args.projectPath,
|
|
184259
|
-
ftsMatches
|
|
186061
|
+
ftsMatches,
|
|
186062
|
+
workspace: args.workspace
|
|
184260
186063
|
});
|
|
184261
186064
|
const semanticScores = await getSemanticScores({
|
|
184262
186065
|
db: args.db,
|
|
184263
186066
|
projectPath: args.projectPath,
|
|
184264
186067
|
memories: semanticCandidates,
|
|
184265
|
-
queryEmbedding: args.queryEmbedding
|
|
186068
|
+
queryEmbedding: args.queryEmbedding,
|
|
186069
|
+
queryModelId: args.queryModelId,
|
|
186070
|
+
workspace: args.workspace
|
|
184266
186071
|
});
|
|
184267
186072
|
return mergeMemoryResults({
|
|
184268
186073
|
memories,
|
|
184269
186074
|
semanticScores,
|
|
184270
186075
|
ftsScores,
|
|
184271
186076
|
limit: args.limit,
|
|
184272
|
-
visibleMemoryIds: args.visibleMemoryIds
|
|
186077
|
+
visibleMemoryIds: args.visibleMemoryIds,
|
|
186078
|
+
sourceNameByMemoryId: sourceNamesForSearchMemories({
|
|
186079
|
+
memories,
|
|
186080
|
+
projectPath: args.projectPath,
|
|
186081
|
+
workspace: args.workspace ?? {
|
|
186082
|
+
identities: [args.projectPath],
|
|
186083
|
+
expandedIdentities: [args.projectPath],
|
|
186084
|
+
namesByIdentity: new Map,
|
|
186085
|
+
canonicalIdentityByStoredPath: new Map([[args.projectPath, args.projectPath]]),
|
|
186086
|
+
ownIdentities: [args.projectPath],
|
|
186087
|
+
shareCategories: null,
|
|
186088
|
+
isWorkspaced: false
|
|
186089
|
+
}
|
|
186090
|
+
})
|
|
184273
186091
|
});
|
|
184274
186092
|
}
|
|
184275
186093
|
function linearDecayScore(rank, total) {
|
|
@@ -184300,7 +186118,13 @@ function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff) {
|
|
|
184300
186118
|
return result;
|
|
184301
186119
|
}
|
|
184302
186120
|
var RRF_K = 60;
|
|
184303
|
-
var
|
|
186121
|
+
var VERBATIM_RANK_BONUS = 1 / RRF_K;
|
|
186122
|
+
var IDF_FALLOFF = 100;
|
|
186123
|
+
function probeDiscriminationWeight(df, corpusSize) {
|
|
186124
|
+
if (corpusSize <= 0 || df <= 0)
|
|
186125
|
+
return 1;
|
|
186126
|
+
return 1 / (1 + IDF_FALLOFF * df / corpusSize);
|
|
186127
|
+
}
|
|
184304
186128
|
function searchMessages(args) {
|
|
184305
186129
|
const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
|
|
184306
186130
|
const fetchLimit = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.limit * 3 : args.limit;
|
|
@@ -184317,20 +186141,31 @@ function searchMessages(args) {
|
|
|
184317
186141
|
role: row.role
|
|
184318
186142
|
}));
|
|
184319
186143
|
}
|
|
186144
|
+
const corpusSize = getSessionFtsRowCount(args.db, args.sessionId);
|
|
184320
186145
|
const queryLists = [];
|
|
184321
186146
|
if (baseQuery.length > 0) {
|
|
184322
|
-
queryLists.push(
|
|
186147
|
+
queryLists.push({
|
|
186148
|
+
rows: runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff),
|
|
186149
|
+
weight: 1
|
|
186150
|
+
});
|
|
184323
186151
|
}
|
|
186152
|
+
const probeWeights = new Map;
|
|
184324
186153
|
for (const probe of probes) {
|
|
184325
186154
|
const probeQuery = sanitizeFtsQuery(probe);
|
|
184326
186155
|
if (probeQuery.length === 0)
|
|
184327
186156
|
continue;
|
|
184328
|
-
|
|
186157
|
+
const df = countSessionFtsMatches(args.db, args.sessionId, probeQuery);
|
|
186158
|
+
const weight = probeDiscriminationWeight(df, corpusSize);
|
|
186159
|
+
probeWeights.set(probe, weight);
|
|
186160
|
+
queryLists.push({
|
|
186161
|
+
rows: runMessageFtsQuery(args.db, args.sessionId, probeQuery, fetchLimit, cutoff),
|
|
186162
|
+
weight
|
|
186163
|
+
});
|
|
184329
186164
|
}
|
|
184330
186165
|
const fused = new Map;
|
|
184331
186166
|
for (const list of queryLists) {
|
|
184332
|
-
list.forEach((row, rank) => {
|
|
184333
|
-
const rrf =
|
|
186167
|
+
list.rows.forEach((row, rank) => {
|
|
186168
|
+
const rrf = list.weight / (RRF_K + rank);
|
|
184334
186169
|
const existing = fused.get(row.messageId);
|
|
184335
186170
|
if (existing) {
|
|
184336
186171
|
existing.score += rrf;
|
|
@@ -184340,26 +186175,107 @@ function searchMessages(args) {
|
|
|
184340
186175
|
});
|
|
184341
186176
|
}
|
|
184342
186177
|
for (const entry of fused.values()) {
|
|
184343
|
-
|
|
184344
|
-
|
|
186178
|
+
let best = 0;
|
|
186179
|
+
for (const probe of probes) {
|
|
186180
|
+
const weight = probeWeights.get(probe) ?? 0;
|
|
186181
|
+
if (weight > best && containsProbeVerbatim(entry.row.content, [probe])) {
|
|
186182
|
+
best = weight;
|
|
186183
|
+
}
|
|
186184
|
+
}
|
|
186185
|
+
if (best > 0) {
|
|
186186
|
+
entry.score += best * VERBATIM_RANK_BONUS;
|
|
184345
186187
|
}
|
|
184346
186188
|
}
|
|
184347
186189
|
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);
|
|
184348
|
-
|
|
184349
|
-
return ranked.map((entry) => ({
|
|
186190
|
+
return ranked.map((entry, rank) => ({
|
|
184350
186191
|
source: "message",
|
|
184351
186192
|
content: previewText(entry.row.content),
|
|
184352
|
-
score:
|
|
186193
|
+
score: linearDecayScore(rank, ranked.length),
|
|
184353
186194
|
messageOrdinal: entry.row.messageOrdinal,
|
|
184354
186195
|
messageId: entry.row.messageId,
|
|
184355
186196
|
role: entry.row.role
|
|
184356
186197
|
}));
|
|
184357
186198
|
}
|
|
186199
|
+
function searchCompartmentChunks(args) {
|
|
186200
|
+
if (!args.queryEmbedding || args.limit <= 0)
|
|
186201
|
+
return [];
|
|
186202
|
+
const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
|
|
186203
|
+
const rows = loadCompartmentChunkEmbeddingsForSearch(args.db, args.sessionId, args.projectPath, args.modelId);
|
|
186204
|
+
if (rows.length === 0)
|
|
186205
|
+
return [];
|
|
186206
|
+
const byCompartment = new Map;
|
|
186207
|
+
for (const row of rows) {
|
|
186208
|
+
if (cutoff !== null && row.endOrdinal > cutoff) {
|
|
186209
|
+
continue;
|
|
186210
|
+
}
|
|
186211
|
+
const score = normalizeCosineScore(cosineSimilarity(args.queryEmbedding, row.vector));
|
|
186212
|
+
if (score <= 0)
|
|
186213
|
+
continue;
|
|
186214
|
+
const existing = byCompartment.get(row.compartmentId);
|
|
186215
|
+
if (!existing || score > existing.score) {
|
|
186216
|
+
byCompartment.set(row.compartmentId, { row, score });
|
|
186217
|
+
}
|
|
186218
|
+
}
|
|
186219
|
+
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 }) => ({
|
|
186220
|
+
source: "compartment",
|
|
186221
|
+
content: previewText(row.title),
|
|
186222
|
+
score: score * SINGLE_SOURCE_PENALTY,
|
|
186223
|
+
compartmentId: row.compartmentId,
|
|
186224
|
+
sessionId: row.sessionId,
|
|
186225
|
+
title: row.title,
|
|
186226
|
+
startOrdinal: row.startOrdinal,
|
|
186227
|
+
endOrdinal: row.endOrdinal,
|
|
186228
|
+
matchType: "semantic"
|
|
186229
|
+
}));
|
|
186230
|
+
}
|
|
186231
|
+
function mergeMessageAndCompartmentResults(args) {
|
|
186232
|
+
if (args.compartments.length === 0)
|
|
186233
|
+
return args.messages;
|
|
186234
|
+
if (args.messages.length === 0)
|
|
186235
|
+
return args.compartments;
|
|
186236
|
+
const fused = new Map;
|
|
186237
|
+
const add = (key, result, score, tieOrdinal) => {
|
|
186238
|
+
const existing = fused.get(key);
|
|
186239
|
+
if (existing) {
|
|
186240
|
+
existing.score += score;
|
|
186241
|
+
return existing;
|
|
186242
|
+
}
|
|
186243
|
+
const entry = { result, score, tieOrdinal, snippetScore: -1 };
|
|
186244
|
+
fused.set(key, entry);
|
|
186245
|
+
return entry;
|
|
186246
|
+
};
|
|
186247
|
+
args.compartments.forEach((compartment, rank) => {
|
|
186248
|
+
add(`compartment:${compartment.compartmentId}`, compartment, 1 / (RRF_K + rank), compartment.startOrdinal);
|
|
186249
|
+
});
|
|
186250
|
+
for (const [rank, message] of args.messages.entries()) {
|
|
186251
|
+
const containing = args.compartments.find((compartment) => message.messageOrdinal >= compartment.startOrdinal && message.messageOrdinal <= compartment.endOrdinal);
|
|
186252
|
+
const contribution = 1 / (RRF_K + rank);
|
|
186253
|
+
if (!containing) {
|
|
186254
|
+
add(`message:${message.messageId}`, message, contribution, message.messageOrdinal);
|
|
186255
|
+
continue;
|
|
186256
|
+
}
|
|
186257
|
+
const entry = add(`compartment:${containing.compartmentId}`, containing, contribution, containing.startOrdinal);
|
|
186258
|
+
if (message.score > entry.snippetScore && entry.result.source === "compartment") {
|
|
186259
|
+
entry.snippetScore = message.score;
|
|
186260
|
+
entry.result = {
|
|
186261
|
+
...entry.result,
|
|
186262
|
+
matchType: "hybrid",
|
|
186263
|
+
snippet: message.content
|
|
186264
|
+
};
|
|
186265
|
+
}
|
|
186266
|
+
}
|
|
186267
|
+
const ranked = [...fused.values()].sort((left, right) => right.score !== left.score ? right.score - left.score : left.tieOrdinal - right.tieOrdinal).slice(0, args.limit);
|
|
186268
|
+
return ranked.map((entry, rank) => ({
|
|
186269
|
+
...entry.result,
|
|
186270
|
+
score: linearDecayScore(rank, ranked.length)
|
|
186271
|
+
}));
|
|
186272
|
+
}
|
|
184358
186273
|
function getSourceBoost(result) {
|
|
184359
186274
|
switch (result.source) {
|
|
184360
186275
|
case "memory":
|
|
184361
186276
|
return MEMORY_SOURCE_BOOST;
|
|
184362
186277
|
case "message":
|
|
186278
|
+
case "compartment":
|
|
184363
186279
|
return MESSAGE_SOURCE_BOOST;
|
|
184364
186280
|
case "git_commit":
|
|
184365
186281
|
return GIT_COMMIT_SOURCE_BOOST;
|
|
@@ -184377,6 +186293,9 @@ function compareUnifiedResults(left, right) {
|
|
|
184377
186293
|
if (left.source === "message" && right.source === "message") {
|
|
184378
186294
|
return left.messageOrdinal - right.messageOrdinal;
|
|
184379
186295
|
}
|
|
186296
|
+
if (left.source === "compartment" && right.source === "compartment") {
|
|
186297
|
+
return left.startOrdinal - right.startOrdinal;
|
|
186298
|
+
}
|
|
184380
186299
|
if (left.source === "git_commit" && right.source === "git_commit") {
|
|
184381
186300
|
return right.committedAtMs - left.committedAtMs;
|
|
184382
186301
|
}
|
|
@@ -184427,10 +186346,12 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
184427
186346
|
const isEmbeddingRuntimeEnabled = options.isEmbeddingRuntimeEnabled ?? isEmbeddingEnabled;
|
|
184428
186347
|
const gitCommitsEnabled = options.gitCommitsEnabled ?? false;
|
|
184429
186348
|
const activeSources = resolveSources(options.sources);
|
|
184430
|
-
const
|
|
186349
|
+
const memoryFeatureEnabled = options.memoryEnabled ?? true;
|
|
186350
|
+
const runMemory = activeSources.has("memory") && memoryFeatureEnabled;
|
|
184431
186351
|
const runMessages = activeSources.has("message");
|
|
184432
186352
|
const runGitCommits = activeSources.has("git_commit") && gitCommitsEnabled;
|
|
184433
|
-
const
|
|
186353
|
+
const runCompartmentChunks = runMessages && memoryFeatureEnabled && embeddingEnabled;
|
|
186354
|
+
const needsEmbedding = (runMemory || runGitCommits || runCompartmentChunks) && embeddingEnabled && isEmbeddingRuntimeEnabled();
|
|
184434
186355
|
const queryEmbeddingPromise = needsEmbedding ? embedQuery(trimmedQuery, options.signal).catch((error51) => {
|
|
184435
186356
|
log(`[search] query embedding failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
184436
186357
|
return null;
|
|
@@ -184446,6 +186367,24 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
184446
186367
|
probes: messageProbes
|
|
184447
186368
|
}) : [];
|
|
184448
186369
|
const queryEmbedding = await queryEmbeddingPromise;
|
|
186370
|
+
const workspace = resolveSearchWorkspaceContext(db, projectPath);
|
|
186371
|
+
const embeddingSnapshot = getProjectEmbeddingSnapshot(projectPath);
|
|
186372
|
+
const embeddingModelId = embeddingSnapshot?.modelId;
|
|
186373
|
+
const chunkModelId = embeddingSnapshot?.chunkModelId;
|
|
186374
|
+
const compartmentResults = runCompartmentChunks ? searchCompartmentChunks({
|
|
186375
|
+
db,
|
|
186376
|
+
sessionId,
|
|
186377
|
+
projectPath,
|
|
186378
|
+
queryEmbedding,
|
|
186379
|
+
limit: tierLimit,
|
|
186380
|
+
maxOrdinal: options.maxMessageOrdinal,
|
|
186381
|
+
modelId: chunkModelId && chunkModelId !== "off" ? chunkModelId : null
|
|
186382
|
+
}) : [];
|
|
186383
|
+
const messageLikeResults = mergeMessageAndCompartmentResults({
|
|
186384
|
+
messages: messageResults,
|
|
186385
|
+
compartments: compartmentResults,
|
|
186386
|
+
limit: tierLimit
|
|
186387
|
+
});
|
|
184449
186388
|
const [memoryResults, gitCommitResults] = await Promise.all([
|
|
184450
186389
|
runMemory ? searchMemories({
|
|
184451
186390
|
db,
|
|
@@ -184454,6 +186393,8 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
184454
186393
|
limit: tierLimit,
|
|
184455
186394
|
memoryEnabled: true,
|
|
184456
186395
|
queryEmbedding,
|
|
186396
|
+
queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null,
|
|
186397
|
+
workspace,
|
|
184457
186398
|
visibleMemoryIds: options.visibleMemoryIds
|
|
184458
186399
|
}) : Promise.resolve([]),
|
|
184459
186400
|
runGitCommits ? Promise.resolve(searchGitCommits({
|
|
@@ -184464,7 +186405,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
184464
186405
|
queryEmbedding
|
|
184465
186406
|
})) : Promise.resolve([])
|
|
184466
186407
|
]);
|
|
184467
|
-
const results = [...memoryResults, ...
|
|
186408
|
+
const results = [...memoryResults, ...messageLikeResults, ...gitCommitResults].sort(compareUnifiedResults).slice(0, limit);
|
|
184468
186409
|
const countRetrievals = options.countRetrievals ?? true;
|
|
184469
186410
|
if (countRetrievals) {
|
|
184470
186411
|
const memoryIds = results.filter((result) => result.source === "memory").map((result) => result.memoryId);
|
|
@@ -184528,6 +186469,11 @@ function renderFragment(result, charCap) {
|
|
|
184528
186469
|
const compressed = cavemanCompress(result.content, "ultra");
|
|
184529
186470
|
return truncate(compressed, charCap);
|
|
184530
186471
|
}
|
|
186472
|
+
case "compartment": {
|
|
186473
|
+
const source = result.snippet ?? result.title;
|
|
186474
|
+
const compressed = cavemanCompress(source, "ultra");
|
|
186475
|
+
return truncate(compressed, charCap);
|
|
186476
|
+
}
|
|
184531
186477
|
}
|
|
184532
186478
|
}
|
|
184533
186479
|
function buildAutoSearchHint(results, options = {}) {
|
|
@@ -185168,7 +187114,7 @@ function isVisibleNoteReadPart(part) {
|
|
|
185168
187114
|
}
|
|
185169
187115
|
|
|
185170
187116
|
// src/hooks/magic-context/todo-view.ts
|
|
185171
|
-
import { createHash as
|
|
187117
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
185172
187118
|
var TERMINAL_STATUSES = new Set(["completed", "cancelled"]);
|
|
185173
187119
|
var TITLE_DONE_STATUSES = new Set(["completed"]);
|
|
185174
187120
|
var SYNTHETIC_CALL_ID_PREFIX = "mc_synthetic_todo_";
|
|
@@ -185213,7 +187159,7 @@ function buildSyntheticTodoPart(stateJson) {
|
|
|
185213
187159
|
};
|
|
185214
187160
|
}
|
|
185215
187161
|
function computeSyntheticCallId(stateJson) {
|
|
185216
|
-
const hash2 =
|
|
187162
|
+
const hash2 = createHash11("sha256").update(stateJson).digest("hex").slice(0, 16);
|
|
185217
187163
|
return `${SYNTHETIC_CALL_ID_PREFIX}${hash2}`;
|
|
185218
187164
|
}
|
|
185219
187165
|
function parseTodoState(stateJson) {
|
|
@@ -185264,15 +187210,25 @@ async function runPostTransformPhase(args) {
|
|
|
185264
187210
|
const emergencyBypassCompartmentGate = forceMaterialization;
|
|
185265
187211
|
const deferredMaterialize = args.canConsumeDeferredLate && deferredMaterializationWasPending;
|
|
185266
187212
|
const materializationRequested = isExplicitFlush || deferredMaterialize;
|
|
185267
|
-
const
|
|
187213
|
+
const m0M1EnabledForFold = args.fullFeatureMode && args.m0M1 !== undefined && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory);
|
|
187214
|
+
const m0HardFoldThisPass = m0M1EnabledForFold && args.m0M1 ? mustMaterialize({
|
|
187215
|
+
db: args.db,
|
|
187216
|
+
sessionId: args.sessionId,
|
|
187217
|
+
state: args.sessionMeta,
|
|
187218
|
+
projectPath: args.m0M1.projectPath,
|
|
187219
|
+
projectDirectory: args.m0M1.projectDirectory,
|
|
187220
|
+
hardSignals: args.m0M1.hardSignals
|
|
187221
|
+
}).value : false;
|
|
187222
|
+
const shouldReadPendingOps = materializationRequested || args.schedulerDecision === "execute" || forceMaterialization || m0HardFoldThisPass || compartmentRunning;
|
|
185268
187223
|
const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
|
|
185269
187224
|
const hasPendingUserOps = pendingOps.length > 0;
|
|
185270
|
-
const shouldApplyPendingOps = (args.schedulerDecision === "execute" || materializationRequested || forceMaterialization) && (!compartmentRunning || emergencyBypassCompartmentGate);
|
|
185271
|
-
const shouldRunHeuristics = (!compartmentRunning || emergencyBypassCompartmentGate) && (materializationRequested || forceMaterialization || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
|
|
187225
|
+
const shouldApplyPendingOps = (args.schedulerDecision === "execute" || materializationRequested || forceMaterialization || m0HardFoldThisPass) && (!compartmentRunning || emergencyBypassCompartmentGate);
|
|
187226
|
+
const shouldRunHeuristics = (!compartmentRunning || emergencyBypassCompartmentGate) && (materializationRequested || forceMaterialization || m0HardFoldThisPass || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
|
|
185272
187227
|
const isCacheBustingPass = shouldApplyPendingOps || shouldRunHeuristics;
|
|
187228
|
+
const canUseEmptySentinels = modelAcceptsEmptyContent(args.resolvedProviderID);
|
|
185273
187229
|
if (shouldRunHeuristics) {
|
|
185274
187230
|
const subagentRerun = !args.fullFeatureMode && alreadyRanThisTurn && args.schedulerDecision === "execute" && !isExplicitFlush && !forceMaterialization;
|
|
185275
|
-
const reason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : forceMaterialization ? `force_materialization (${args.contextUsage.percentage.toFixed(1)}% >= ${args.forceMaterializationPercentage}%)` : subagentRerun ? `scheduler_execute_subagent_rerun (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})` : `scheduler_execute (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
|
|
187231
|
+
const reason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : forceMaterialization ? `force_materialization (${args.contextUsage.percentage.toFixed(1)}% >= ${args.forceMaterializationPercentage}%)` : m0HardFoldThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into known m[0] bust, scheduler=${args.schedulerDecision})` : subagentRerun ? `scheduler_execute_subagent_rerun (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})` : `scheduler_execute (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
|
|
185276
187232
|
sessionLog(args.sessionId, `heuristics WILL RUN — reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=${args.currentTurnId}`);
|
|
185277
187233
|
}
|
|
185278
187234
|
if (alreadyRanThisTurn && args.schedulerDecision === "execute" && !materializationRequested && args.fullFeatureMode) {
|
|
@@ -185315,7 +187271,9 @@ async function runPostTransformPhase(args) {
|
|
|
185315
187271
|
logTransformTiming(args.sessionId, "applyHeuristicCleanup", t5, `droppedTools=${cleanup.droppedTools} deduplicatedTools=${cleanup.deduplicatedTools} droppedInjections=${cleanup.droppedInjections} compressedTextTags=${cleanup.compressedTextTags}`);
|
|
185316
187272
|
const t7 = performance.now();
|
|
185317
187273
|
const clearedReasoning = clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge);
|
|
185318
|
-
|
|
187274
|
+
if (canUseEmptySentinels) {
|
|
187275
|
+
stripClearedReasoning(args.messages);
|
|
187276
|
+
}
|
|
185319
187277
|
const strippedInline = stripInlineThinking(args.messages, args.messageTagNumbers, args.clearReasoningAge);
|
|
185320
187278
|
if (clearedReasoning > 0 || strippedInline > 0) {
|
|
185321
187279
|
let maxTag = 0;
|
|
@@ -185361,7 +187319,6 @@ async function runPostTransformPhase(args) {
|
|
|
185361
187319
|
if (args.watermark > 0) {
|
|
185362
187320
|
const tWatermarkCleanup = performance.now();
|
|
185363
187321
|
truncateErroredTools(args.messages, args.watermark, args.messageTagNumbers);
|
|
185364
|
-
stripProcessedImages(args.messages, args.watermark, args.messageTagNumbers);
|
|
185365
187322
|
logTransformTiming(args.sessionId, "watermarkCleanup", tWatermarkCleanup);
|
|
185366
187323
|
}
|
|
185367
187324
|
if (shouldApplyPendingOps) {
|
|
@@ -185371,21 +187328,40 @@ async function runPostTransformPhase(args) {
|
|
|
185371
187328
|
sessionLog(args.sessionId, "transform failed applying pending operations:", error51);
|
|
185372
187329
|
updateSessionMeta(args.db, args.sessionId, { lastTransformError: getErrorMessage(error51) });
|
|
185373
187330
|
}
|
|
185374
|
-
|
|
185375
|
-
|
|
185376
|
-
|
|
185377
|
-
|
|
185378
|
-
|
|
185379
|
-
|
|
185380
|
-
|
|
185381
|
-
|
|
185382
|
-
|
|
187331
|
+
if (canUseEmptySentinels) {
|
|
187332
|
+
try {
|
|
187333
|
+
const t8 = performance.now();
|
|
187334
|
+
const frozenStaleReduceIds = getStaleReduceStrippedIds(args.db, args.sessionId);
|
|
187335
|
+
const staleReduceResult = dropStaleReduceCalls(args.messages, frozenStaleReduceIds, {
|
|
187336
|
+
detect: isCacheBustingPass,
|
|
187337
|
+
protectedCount: args.protectedTags
|
|
187338
|
+
});
|
|
187339
|
+
if (isCacheBustingPass && staleReduceResult.newlyStrippedIds.length > 0) {
|
|
187340
|
+
addStaleReduceStrippedIds(args.db, args.sessionId, staleReduceResult.newlyStrippedIds);
|
|
187341
|
+
}
|
|
187342
|
+
logTransformTiming(args.sessionId, "dropStaleReduceCalls", t8);
|
|
187343
|
+
} catch (error51) {
|
|
187344
|
+
sessionLog(args.sessionId, "transform failed dropping stale ctx_reduce calls:", error51);
|
|
185383
187345
|
}
|
|
185384
|
-
logTransformTiming(args.sessionId, "dropStaleReduceCalls", t8);
|
|
185385
|
-
} catch (error51) {
|
|
185386
|
-
sessionLog(args.sessionId, "transform failed dropping stale ctx_reduce calls:", error51);
|
|
185387
187346
|
}
|
|
185388
|
-
|
|
187347
|
+
if (canUseEmptySentinels && args.watermark > 0) {
|
|
187348
|
+
try {
|
|
187349
|
+
const tImg = performance.now();
|
|
187350
|
+
const frozenImageIds = getProcessedImageStrippedIds(args.db, args.sessionId);
|
|
187351
|
+
const imageResult = stripProcessedImages(args.messages, frozenImageIds, {
|
|
187352
|
+
detect: isCacheBustingPass,
|
|
187353
|
+
watermark: args.watermark,
|
|
187354
|
+
messageTagNumbers: args.messageTagNumbers
|
|
187355
|
+
});
|
|
187356
|
+
if (isCacheBustingPass && imageResult.newlyStrippedIds.length > 0) {
|
|
187357
|
+
addProcessedImageStrippedIds(args.db, args.sessionId, imageResult.newlyStrippedIds);
|
|
187358
|
+
}
|
|
187359
|
+
logTransformTiming(args.sessionId, "stripProcessedImages", tImg);
|
|
187360
|
+
} catch (error51) {
|
|
187361
|
+
sessionLog(args.sessionId, "transform failed stripping processed images:", error51);
|
|
187362
|
+
}
|
|
187363
|
+
}
|
|
187364
|
+
const m0M1Enabled = m0M1EnabledForFold;
|
|
185389
187365
|
if (m0M1Enabled && args.m0M1) {
|
|
185390
187366
|
const tInjectM0M1 = performance.now();
|
|
185391
187367
|
try {
|
|
@@ -185432,7 +187408,7 @@ async function runPostTransformPhase(args) {
|
|
|
185432
187408
|
const tPlaceholder = performance.now();
|
|
185433
187409
|
const persistedIds = getStrippedPlaceholderIds(args.db, args.sessionId);
|
|
185434
187410
|
if (persistedIds.size > 0) {
|
|
185435
|
-
const { replayed, missingIds } = replaySentinelByMessageIds(args.messages, persistedIds, args.
|
|
187411
|
+
const { replayed, missingIds } = replaySentinelByMessageIds(args.messages, persistedIds, args.resolvedProviderID);
|
|
185436
187412
|
if (replayed > 0) {
|
|
185437
187413
|
sessionLog(args.sessionId, `sentinel replay: neutralized ${replayed} previously-stripped messages`);
|
|
185438
187414
|
}
|
|
@@ -185443,9 +187419,9 @@ async function runPostTransformPhase(args) {
|
|
|
185443
187419
|
}
|
|
185444
187420
|
}
|
|
185445
187421
|
if (isCacheBustingPass) {
|
|
185446
|
-
const droppedResult = stripDroppedPlaceholderMessages(args.messages, args.
|
|
187422
|
+
const droppedResult = stripDroppedPlaceholderMessages(args.messages, args.resolvedProviderID);
|
|
185447
187423
|
const protectedTailStart = Math.max(0, args.messages.length - args.protectedTags * 2);
|
|
185448
|
-
const systemInjectedResult = stripSystemInjectedMessages(args.messages, protectedTailStart, args.
|
|
187424
|
+
const systemInjectedResult = stripSystemInjectedMessages(args.messages, protectedTailStart, args.resolvedProviderID);
|
|
185449
187425
|
const newlyNeutralized = droppedResult.sentineledIds.length + systemInjectedResult.sentineledIds.length;
|
|
185450
187426
|
if (newlyNeutralized > 0) {
|
|
185451
187427
|
const addedIds = [
|
|
@@ -185645,6 +187621,7 @@ function clearMessageTokensCache(sessionId, messageId) {
|
|
|
185645
187621
|
if (cache)
|
|
185646
187622
|
cache.delete(messageId);
|
|
185647
187623
|
}
|
|
187624
|
+
var recordedSessionProjectIdentity = new BoundedSessionMap(MESSAGE_TOKENS_CACHE_MAX);
|
|
185648
187625
|
function findLastAssistantModel2(messages) {
|
|
185649
187626
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
185650
187627
|
const info = messages[i].info;
|
|
@@ -185690,11 +187667,13 @@ function createTransform(deps) {
|
|
|
185690
187667
|
}
|
|
185691
187668
|
const reducedMode = sessionMeta.isSubagent;
|
|
185692
187669
|
const fullFeatureMode = !reducedMode;
|
|
185693
|
-
const ctxReduceEnabledEffective = deps.ctxReduceEnabled !== false;
|
|
187670
|
+
const ctxReduceEnabledEffective = deps.ctxReduceEnabled !== false && resolveCtxReduceAvailabilityFromMessages(sessionId, messages);
|
|
185694
187671
|
let sessionDirectory = deps.directory ?? "";
|
|
187672
|
+
let sessionDirectoryResolvedFromHost = false;
|
|
185695
187673
|
const cachedDirectory = deps.sessionDirectoryBySession?.get(sessionId);
|
|
185696
187674
|
if (cachedDirectory && cachedDirectory.length > 0) {
|
|
185697
187675
|
sessionDirectory = cachedDirectory;
|
|
187676
|
+
sessionDirectoryResolvedFromHost = true;
|
|
185698
187677
|
} else if (deps.client !== undefined) {
|
|
185699
187678
|
try {
|
|
185700
187679
|
const sessionResponse = await deps.client.session.get({ path: { id: sessionId } }).catch(() => null);
|
|
@@ -185702,6 +187681,7 @@ function createTransform(deps) {
|
|
|
185702
187681
|
if (sessionInfo && typeof sessionInfo.directory === "string" && sessionInfo.directory.length > 0) {
|
|
185703
187682
|
sessionDirectory = sessionInfo.directory;
|
|
185704
187683
|
deps.sessionDirectoryBySession?.set(sessionId, sessionDirectory);
|
|
187684
|
+
sessionDirectoryResolvedFromHost = true;
|
|
185705
187685
|
}
|
|
185706
187686
|
} catch {}
|
|
185707
187687
|
}
|
|
@@ -185796,6 +187776,8 @@ function createTransform(deps) {
|
|
|
185796
187776
|
deps.liveModelBySession?.set(sessionId, recovered);
|
|
185797
187777
|
}
|
|
185798
187778
|
}
|
|
187779
|
+
const resolvedProviderID = modelForBudget?.providerID;
|
|
187780
|
+
const canUseEmptySentinels = modelAcceptsEmptyContent(resolvedProviderID);
|
|
185799
187781
|
const resolvedContextLimit = modelForBudget ? resolveTrustedContextLimit(modelForBudget.providerID, modelForBudget.modelID, {
|
|
185800
187782
|
db,
|
|
185801
187783
|
sessionID: sessionId
|
|
@@ -185960,6 +187942,10 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
185960
187942
|
logTransformTiming(sessionId, "emergencyRecoveryBlock", tFirstPass);
|
|
185961
187943
|
const projectIdentity = deps.memoryConfig?.enabled ? resolveProjectIdentity(compartmentDirectory || process.cwd()) : undefined;
|
|
185962
187944
|
const sessionProjectIdentity = projectIdentity ?? (sessionDirectory ? resolveProjectIdentity(sessionDirectory) : deps.projectPath);
|
|
187945
|
+
if (sessionProjectIdentity && sessionDirectoryResolvedFromHost && recordedSessionProjectIdentity.get(sessionId) !== sessionProjectIdentity) {
|
|
187946
|
+
recordSessionProjectIdentity(db, sessionId, sessionProjectIdentity);
|
|
187947
|
+
recordedSessionProjectIdentity.set(sessionId, sessionProjectIdentity);
|
|
187948
|
+
}
|
|
185963
187949
|
let triggerBoundarySnapshot;
|
|
185964
187950
|
if (fullFeatureMode && historianRunnable && !sessionMeta.compartmentInProgress) {
|
|
185965
187951
|
const tTrigger = performance.now();
|
|
@@ -186054,7 +188040,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
186054
188040
|
}
|
|
186055
188041
|
}
|
|
186056
188042
|
const t3 = performance.now();
|
|
186057
|
-
const strippedStructuralNoise = stripStructuralNoise(messages);
|
|
188043
|
+
const strippedStructuralNoise = canUseEmptySentinels ? stripStructuralNoise(messages) : 0;
|
|
186058
188044
|
logTransformTiming(sessionId, "stripStructuralNoise", t3, `strippedParts=${strippedStructuralNoise}`);
|
|
186059
188045
|
const persistedReasoningWatermark = sessionMeta?.clearedReasoningThroughTag ?? 0;
|
|
186060
188046
|
if (persistedReasoningWatermark > 0) {
|
|
@@ -186075,18 +188061,10 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
186075
188061
|
logTransformTiming(sessionId, "replayCavemanCompression", tCavemanReplay);
|
|
186076
188062
|
}
|
|
186077
188063
|
const t4 = performance.now();
|
|
186078
|
-
const strippedClearedReasoning = stripClearedReasoning(messages);
|
|
188064
|
+
const strippedClearedReasoning = canUseEmptySentinels ? stripClearedReasoning(messages) : 0;
|
|
186079
188065
|
logTransformTiming(sessionId, "stripClearedReasoning", t4, `strippedParts=${strippedClearedReasoning}`);
|
|
186080
188066
|
const tMergeStrip = performance.now();
|
|
186081
|
-
|
|
186082
|
-
if (liveProviderID === undefined) {
|
|
186083
|
-
const recovered = findLastAssistantModelFromOpenCodeDb(sessionId);
|
|
186084
|
-
if (recovered) {
|
|
186085
|
-
liveProviderID = recovered.providerID;
|
|
186086
|
-
deps.liveModelBySession?.set(sessionId, recovered);
|
|
186087
|
-
}
|
|
186088
|
-
}
|
|
186089
|
-
const strippedMergedReasoning = stripReasoningFromMergedAssistants(messages, liveProviderID);
|
|
188067
|
+
const strippedMergedReasoning = stripReasoningFromMergedAssistants(messages, resolvedProviderID);
|
|
186090
188068
|
if (strippedMergedReasoning > 0) {
|
|
186091
188069
|
sessionLog(sessionId, `stripped ${strippedMergedReasoning} reasoning parts from merged assistants (anthropic groupIntoBlocks workaround)`);
|
|
186092
188070
|
}
|
|
@@ -186143,7 +188121,6 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
186143
188121
|
logTransformTiming(sessionId, "compartmentPhase", tCompartmentPhase);
|
|
186144
188122
|
const hardModel = deps.liveModelBySession?.get(sessionId);
|
|
186145
188123
|
const hardModelKey = hardModel ? `${hardModel.providerID}/${hardModel.modelID}` : "";
|
|
186146
|
-
const hardToolSetHash = deps.getToolSetHash?.(sessionId) ?? "";
|
|
186147
188124
|
const hardSystemHash = typeof sessionMeta.systemPromptHash === "string" ? sessionMeta.systemPromptHash : "";
|
|
186148
188125
|
let hardTtlMs = 5 * 60 * 1000;
|
|
186149
188126
|
try {
|
|
@@ -186152,7 +188129,6 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
186152
188129
|
const hardCacheExpired = sessionMeta.lastResponseTime > 0 && Date.now() - sessionMeta.lastResponseTime >= hardTtlMs;
|
|
186153
188130
|
const m0HardSignals = {
|
|
186154
188131
|
systemHash: hardSystemHash,
|
|
186155
|
-
toolSetHash: hardToolSetHash,
|
|
186156
188132
|
modelKey: hardModelKey,
|
|
186157
188133
|
cacheExpired: hardCacheExpired,
|
|
186158
188134
|
lastResponseTime: sessionMeta.lastResponseTime
|
|
@@ -186207,7 +188183,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
186207
188183
|
sessionDirectory,
|
|
186208
188184
|
autoSearch: deps.autoSearch,
|
|
186209
188185
|
cavemanTextCompression: deps.ctxReduceEnabled === false && !reducedMode ? deps.cavemanTextCompression : undefined,
|
|
186210
|
-
|
|
188186
|
+
resolvedProviderID,
|
|
186211
188187
|
historyRefreshSessions: deps.historyRefreshSessions,
|
|
186212
188188
|
m0M1: {
|
|
186213
188189
|
projectPath: projectIdentity,
|
|
@@ -187036,7 +189012,7 @@ function createToolExecuteAfterHook(args) {
|
|
|
187036
189012
|
init_send_session_notification();
|
|
187037
189013
|
|
|
187038
189014
|
// src/hooks/magic-context/system-prompt-hash.ts
|
|
187039
|
-
import { createHash as
|
|
189015
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
187040
189016
|
|
|
187041
189017
|
// src/agents/magic-context-prompt.ts
|
|
187042
189018
|
var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
|
|
@@ -187152,9 +189128,9 @@ Prefer many small targeted operations over one large blanket operation, and keep
|
|
|
187152
189128
|
|
|
187153
189129
|
// src/hooks/magic-context/system-prompt-hash.ts
|
|
187154
189130
|
init_logger();
|
|
189131
|
+
await init_storage();
|
|
187155
189132
|
init_key_files_block();
|
|
187156
189133
|
init_read_session_formatting();
|
|
187157
|
-
await init_storage();
|
|
187158
189134
|
var MAGIC_CONTEXT_MARKER = "## Magic Context";
|
|
187159
189135
|
function clearSystemPromptHashSession(sessionId, handleMaps) {
|
|
187160
189136
|
clearKeyFilesCacheForSession(sessionId);
|
|
@@ -187200,9 +189176,10 @@ function createSystemPromptHashHandler(deps) {
|
|
|
187200
189176
|
sessionLog(sessionId, "system-prompt-hash session meta load failed:", error51);
|
|
187201
189177
|
}
|
|
187202
189178
|
const isSubagentSession = sessionMetaEarly?.isSubagent === true;
|
|
187203
|
-
const
|
|
187204
|
-
const
|
|
187205
|
-
const
|
|
189179
|
+
const ctxReduceCallable = resolveCtxReduceAvailability(sessionId);
|
|
189180
|
+
const subagentReduceMode = isSubagentSession && deps.ctxReduceEnabled !== false && ctxReduceCallable;
|
|
189181
|
+
const effectiveCtxReduceEnabled = isSubagentSession ? false : deps.ctxReduceEnabled !== false && ctxReduceCallable;
|
|
189182
|
+
const skipGuidanceForDisabledSubagent = isSubagentSession && (deps.ctxReduceEnabled === false || !ctxReduceCallable);
|
|
187206
189183
|
const fullPrompt = output.system.join(`
|
|
187207
189184
|
`);
|
|
187208
189185
|
if (fullPrompt.length > 0 && !fullPrompt.includes(MAGIC_CONTEXT_MARKER) && !skipGuidanceForDisabledSubagent) {
|
|
@@ -187235,7 +189212,7 @@ function createSystemPromptHashHandler(deps) {
|
|
|
187235
189212
|
`);
|
|
187236
189213
|
if (systemContent.length === 0)
|
|
187237
189214
|
return;
|
|
187238
|
-
const currentHash =
|
|
189215
|
+
const currentHash = createHash12("md5").update(systemContent).digest("hex");
|
|
187239
189216
|
if (!sessionMetaEarly) {
|
|
187240
189217
|
return;
|
|
187241
189218
|
}
|
|
@@ -187496,6 +189473,46 @@ function createMagicContextHook(deps) {
|
|
|
187496
189473
|
ensureProjectRegistered: ensureProjectRegisteredFromOpenCodeDirectory,
|
|
187497
189474
|
getNotificationParams: (sid) => getLiveNotificationParams(sid, liveModelBySession, variantBySession, agentBySession)
|
|
187498
189475
|
});
|
|
189476
|
+
const executeEmbedHistory = async (sessionId) => {
|
|
189477
|
+
if (deps.config.memory?.enabled === false) {
|
|
189478
|
+
return "Memory is disabled for this project, so there is no semantic embedding to backfill.";
|
|
189479
|
+
}
|
|
189480
|
+
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
189481
|
+
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
189482
|
+
const sessionProjectIdentity = resolveProjectIdentity(directory);
|
|
189483
|
+
setRecompStarting({ recompProgressBySession }, sessionId, "Embedding history…", "embed");
|
|
189484
|
+
const outcome = await embedSessionCompartmentChunks(db, sessionProjectIdentity, sessionId, {
|
|
189485
|
+
onProgress: ({ embedded, total }) => {
|
|
189486
|
+
const cur = recompProgressBySession.get(sessionId);
|
|
189487
|
+
if (!cur || cur.phase !== "recomp")
|
|
189488
|
+
return;
|
|
189489
|
+
recompProgressBySession.set(sessionId, {
|
|
189490
|
+
...cur,
|
|
189491
|
+
processedMessages: embedded,
|
|
189492
|
+
totalMessages: total,
|
|
189493
|
+
updatedAt: Date.now()
|
|
189494
|
+
});
|
|
189495
|
+
}
|
|
189496
|
+
});
|
|
189497
|
+
const terminal = (phase, message) => {
|
|
189498
|
+
setRecompTerminal({ recompProgressBySession }, sessionId, phase, message);
|
|
189499
|
+
return message;
|
|
189500
|
+
};
|
|
189501
|
+
switch (outcome.status) {
|
|
189502
|
+
case "nothing":
|
|
189503
|
+
return terminal("done", "All of this session's history is already embedded.");
|
|
189504
|
+
case "disabled":
|
|
189505
|
+
return terminal("skipped", "No embedding provider is configured, so there is nothing to embed.");
|
|
189506
|
+
case "busy":
|
|
189507
|
+
return terminal("skipped", `Embedding is already running for this project — ${outcome.total} compartment${outcome.total === 1 ? "" : "s"} still pending. Try again shortly.`);
|
|
189508
|
+
case "aborted":
|
|
189509
|
+
return terminal("done", `Embedded ${outcome.embedded} of ${outcome.total} compartments before stopping.`);
|
|
189510
|
+
case "stalled":
|
|
189511
|
+
return terminal("skipped", `Embedded ${outcome.embedded} compartments; ${outcome.remaining} could not be embedded (the provider returned no result). Run /ctx-embed-history again to retry them.`);
|
|
189512
|
+
default:
|
|
189513
|
+
return terminal("done", `Embedded ${outcome.embedded} compartment${outcome.embedded === 1 ? "" : "s"} of history for semantic search.`);
|
|
189514
|
+
}
|
|
189515
|
+
};
|
|
187499
189516
|
const sidekickRunnable = isSidekickRunnable(deps.config);
|
|
187500
189517
|
const sidekickConfig = sidekickRunnable ? deps.config.sidekick : undefined;
|
|
187501
189518
|
const transform2 = createTransform({
|
|
@@ -187534,12 +189551,6 @@ function createMagicContextHook(deps) {
|
|
|
187534
189551
|
const model = liveModelBySession.get(sessionId);
|
|
187535
189552
|
return resolveModelKey(model?.providerID, model?.modelID);
|
|
187536
189553
|
},
|
|
187537
|
-
getToolSetHash: (sessionId) => {
|
|
187538
|
-
const model = liveModelBySession.get(sessionId);
|
|
187539
|
-
if (!model)
|
|
187540
|
-
return "";
|
|
187541
|
-
return getCurrentToolSetHash(model.providerID, model.modelID, agentBySession.get(sessionId));
|
|
187542
|
-
},
|
|
187543
189554
|
getFallbackModelId: (sessionId) => {
|
|
187544
189555
|
const model = liveModelBySession.get(sessionId);
|
|
187545
189556
|
return model ? `${model.providerID}/${model.modelID}` : undefined;
|
|
@@ -187656,6 +189667,7 @@ function createMagicContextHook(deps) {
|
|
|
187656
189667
|
},
|
|
187657
189668
|
executeRecomp: historianRunnable ? async (sessionId, options) => runManagedRecomp(buildManagedRecompCtx(sessionId), sessionId, options) : undefined,
|
|
187658
189669
|
runUpgrade: historianRunnable ? async (sessionId) => runManagedUpgrade(buildManagedRecompCtx(sessionId), sessionId) : undefined,
|
|
189670
|
+
executeEmbedHistory,
|
|
187659
189671
|
sendNotification: async (sessionId, text, params) => {
|
|
187660
189672
|
await sendIgnoredMessage(deps.client, sessionId, text, {
|
|
187661
189673
|
...getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession),
|
|
@@ -188793,6 +190805,7 @@ init_memory();
|
|
|
188793
190805
|
init_embedding();
|
|
188794
190806
|
init_embedding_cache();
|
|
188795
190807
|
init_normalize_hash();
|
|
190808
|
+
init_workspaces();
|
|
188796
190809
|
init_logger();
|
|
188797
190810
|
await init_storage();
|
|
188798
190811
|
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
@@ -188952,6 +190965,23 @@ function createCtxMemoryTool(deps) {
|
|
|
188952
190965
|
}
|
|
188953
190966
|
const projectPath = deps.resolveProjectPath(toolContext.directory);
|
|
188954
190967
|
await deps.ensureProjectRegistered?.(toolContext.directory, deps.db);
|
|
190968
|
+
const workspaceIdentitySet = resolveWorkspaceIdentitySet(deps.db, projectPath);
|
|
190969
|
+
const expandedWorkspace = expandWorkspaceIdentitySetWithAliases(deps.db, workspaceIdentitySet.identities);
|
|
190970
|
+
const workspaceVisibleIdentities = workspaceIdentitySet.identities.length > 1 ? expandedWorkspace.expandedIdentities : workspaceIdentitySet.identities;
|
|
190971
|
+
const targetIdentityForStoredPath = (rawProjectPath) => workspaceIdentitySet.identities.length > 1 ? resolveStoredPathWorkspaceIdentity(rawProjectPath, workspaceIdentitySet.identities, expandedWorkspace.canonicalIdentityByStoredPath) ?? projectIdentityForStoredPath(rawProjectPath) : projectIdentityForStoredPath(rawProjectPath);
|
|
190972
|
+
const toolShareCategories = workspaceIdentitySet.identities.length > 1 ? resolveWorkspaceShareCategories(deps.db, projectPath) : null;
|
|
190973
|
+
const memoryVisibleToTool = (memory) => {
|
|
190974
|
+
if (workspaceIdentitySet.identities.length <= 1) {
|
|
190975
|
+
return memoryBelongsToProject(memory, projectPath);
|
|
190976
|
+
}
|
|
190977
|
+
if (!storedPathBelongsToWorkspace(memory.projectPath, workspaceIdentitySet.identities, workspaceVisibleIdentities, expandedWorkspace.canonicalIdentityByStoredPath)) {
|
|
190978
|
+
return false;
|
|
190979
|
+
}
|
|
190980
|
+
const isOwn = targetIdentityForStoredPath(memory.projectPath) === projectPath;
|
|
190981
|
+
if (isOwn)
|
|
190982
|
+
return true;
|
|
190983
|
+
return toolShareCategories === null || toolShareCategories.includes(memory.category);
|
|
190984
|
+
};
|
|
188955
190985
|
const embeddingSnapshot = getProjectEmbeddingSnapshot(projectPath);
|
|
188956
190986
|
if (embeddingSnapshot ? !embeddingSnapshot.features.memoryEnabled : deps.memoryEnabled === false) {
|
|
188957
190987
|
return getDisabledMessage();
|
|
@@ -189008,18 +191038,18 @@ function createCtxMemoryTool(deps) {
|
|
|
189008
191038
|
}
|
|
189009
191039
|
const rawProjectPath = projectPathForMemoryId(deps.db, updateId);
|
|
189010
191040
|
const memory = getMemoryById(deps.db, updateId);
|
|
189011
|
-
if (!memory || !rawProjectPath || !
|
|
191041
|
+
if (!memory || !rawProjectPath || !memoryVisibleToTool(memory)) {
|
|
189012
191042
|
return `Error: Memory with ID ${updateId} was not found.`;
|
|
189013
191043
|
}
|
|
189014
191044
|
if (toolContext.agent !== DREAMER_AGENT && !isPrimaryMutableMemory(memory)) {
|
|
189015
191045
|
return inactiveMemoryError(updateId, "updating");
|
|
189016
191046
|
}
|
|
189017
191047
|
const normalizedHash = computeNormalizedHash(content);
|
|
189018
|
-
const duplicate = getMemoryByHash(deps.db,
|
|
191048
|
+
const duplicate = getMemoryByHash(deps.db, targetIdentityForStoredPath(rawProjectPath), memory.category, normalizedHash);
|
|
189019
191049
|
if (duplicate && duplicate.id !== memory.id) {
|
|
189020
191050
|
return `Error: Memory content already exists as ID ${duplicate.id}; merge or archive duplicates instead.`;
|
|
189021
191051
|
}
|
|
189022
|
-
const projectIdentity =
|
|
191052
|
+
const projectIdentity = targetIdentityForStoredPath(rawProjectPath);
|
|
189023
191053
|
deps.db.transaction(() => {
|
|
189024
191054
|
updateMemoryContentInCurrentTransaction(deps.db, memory, content, normalizedHash);
|
|
189025
191055
|
queueMemoryMutation(deps.db, {
|
|
@@ -189033,7 +191063,7 @@ function createCtxMemoryTool(deps) {
|
|
|
189033
191063
|
queueMemoryEmbedding({
|
|
189034
191064
|
deps,
|
|
189035
191065
|
sessionId: toolContext.sessionID,
|
|
189036
|
-
projectPath,
|
|
191066
|
+
projectPath: projectIdentity,
|
|
189037
191067
|
memoryId: memory.id,
|
|
189038
191068
|
content
|
|
189039
191069
|
});
|
|
@@ -189056,7 +191086,7 @@ function createCtxMemoryTool(deps) {
|
|
|
189056
191086
|
return "Error: One or more source memories were not found.";
|
|
189057
191087
|
}
|
|
189058
191088
|
if (toolContext.agent !== DREAMER_AGENT) {
|
|
189059
|
-
const foreign = sourceMemories.find((memory) => !
|
|
191089
|
+
const foreign = sourceMemories.find((memory) => !memoryVisibleToTool(memory));
|
|
189060
191090
|
if (foreign) {
|
|
189061
191091
|
return `Error: Memory with ID ${foreign.id} was not found.`;
|
|
189062
191092
|
}
|
|
@@ -189140,15 +191170,16 @@ function createCtxMemoryTool(deps) {
|
|
|
189140
191170
|
return `Merged memories [${ids.join(", ")}] into canonical memory [ID: ${canonicalMemory.id}] in ${category}; superseded [${supersededIds.join(", ")}].`;
|
|
189141
191171
|
}
|
|
189142
191172
|
if (args.action === "archive") {
|
|
189143
|
-
const
|
|
189144
|
-
if (!
|
|
191173
|
+
const rawArchiveIds = args.ids;
|
|
191174
|
+
if (!rawArchiveIds || rawArchiveIds.length === 0 || !rawArchiveIds.every(Number.isInteger)) {
|
|
189145
191175
|
return "Error: 'ids' must contain at least one integer memory ID when action is 'archive'.";
|
|
189146
191176
|
}
|
|
191177
|
+
const archiveIds = [...new Set(rawArchiveIds)];
|
|
189147
191178
|
const targets = [];
|
|
189148
191179
|
for (const memoryId of archiveIds) {
|
|
189149
191180
|
const rawProjectPath = projectPathForMemoryId(deps.db, memoryId);
|
|
189150
191181
|
const memory = getMemoryById(deps.db, memoryId);
|
|
189151
|
-
if (!memory || !rawProjectPath || !
|
|
191182
|
+
if (!memory || !rawProjectPath || !memoryVisibleToTool(memory)) {
|
|
189152
191183
|
return `Error: Memory with ID ${memoryId} was not found.`;
|
|
189153
191184
|
}
|
|
189154
191185
|
if (toolContext.agent !== DREAMER_AGENT && !isPrimaryMutableMemory(memory)) {
|
|
@@ -189156,7 +191187,7 @@ function createCtxMemoryTool(deps) {
|
|
|
189156
191187
|
}
|
|
189157
191188
|
targets.push({
|
|
189158
191189
|
memoryId,
|
|
189159
|
-
projectIdentity:
|
|
191190
|
+
projectIdentity: targetIdentityForStoredPath(rawProjectPath)
|
|
189160
191191
|
});
|
|
189161
191192
|
}
|
|
189162
191193
|
deps.db.transaction(() => {
|
|
@@ -189630,8 +191661,9 @@ function formatAge2(committedAtMs) {
|
|
|
189630
191661
|
}
|
|
189631
191662
|
function formatResult(result, index) {
|
|
189632
191663
|
if (result.source === "memory") {
|
|
191664
|
+
const source = result.sourceName ? ` source=${result.sourceName}` : "";
|
|
189633
191665
|
return [
|
|
189634
|
-
`[${index}] [memory] score=${result.score.toFixed(2)} id=${result.memoryId} category=${result.category} match=${result.matchType}`,
|
|
191666
|
+
`[${index}] [memory] score=${result.score.toFixed(2)} id=${result.memoryId} category=${result.category}${source} match=${result.matchType}`,
|
|
189635
191667
|
result.content
|
|
189636
191668
|
].join(`
|
|
189637
191669
|
`);
|
|
@@ -189641,6 +191673,13 @@ function formatResult(result, index) {
|
|
|
189641
191673
|
`[${index}] [git_commit] score=${result.score.toFixed(2)} sha=${result.shortSha} ${formatAge2(result.committedAtMs)} match=${result.matchType}`,
|
|
189642
191674
|
result.content
|
|
189643
191675
|
].join(`
|
|
191676
|
+
`);
|
|
191677
|
+
}
|
|
191678
|
+
if (result.source === "compartment") {
|
|
191679
|
+
return [
|
|
191680
|
+
`[${index}] [message] score=${result.score.toFixed(2)} compartment_id=${result.compartmentId} range=${result.startOrdinal}-${result.endOrdinal} match=${result.matchType} title=${result.title}`,
|
|
191681
|
+
result.snippet ? `Snippet: ${result.snippet}` : result.content
|
|
191682
|
+
].join(`
|
|
189644
191683
|
`);
|
|
189645
191684
|
}
|
|
189646
191685
|
const expandStart = Math.max(1, result.messageOrdinal - 3);
|
|
@@ -189656,7 +191695,7 @@ function formatSearchResults(query, results) {
|
|
|
189656
191695
|
return `No results found for "${query}" across memories, git commits, or message history.`;
|
|
189657
191696
|
}
|
|
189658
191697
|
const bodyParts = results.map((result, index) => formatResult(result, index + 1));
|
|
189659
|
-
if (results.some((result) => result.source === "message")) {
|
|
191698
|
+
if (results.some((result) => result.source === "message" || result.source === "compartment")) {
|
|
189660
191699
|
bodyParts.push("Use ctx_expand(start, end) with the range from any message result above to read the full conversation context.");
|
|
189661
191700
|
}
|
|
189662
191701
|
const body = bodyParts.join(`
|
|
@@ -189814,11 +191853,11 @@ import { createServer } from "node:http";
|
|
|
189814
191853
|
import { dirname as dirname8 } from "node:path";
|
|
189815
191854
|
|
|
189816
191855
|
// src/shared/rpc-utils.ts
|
|
189817
|
-
import { createHash as
|
|
191856
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
189818
191857
|
import { join as join24 } from "node:path";
|
|
189819
191858
|
function projectHash(directory) {
|
|
189820
191859
|
const normalized = directory.replace(/\/+$/, "");
|
|
189821
|
-
return
|
|
191860
|
+
return createHash13("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
189822
191861
|
}
|
|
189823
191862
|
function rpcPortDir(storageDir, directory) {
|
|
189824
191863
|
return join24(storageDir, "rpc", projectHash(directory));
|