@cortexkit/opencode-magic-context 0.23.1 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +80 -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 +17 -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 -1
- package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +1 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +10 -1
- package/dist/features/magic-context/storage-tags.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/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 +23 -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-nudge.d.ts +7 -2
- package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +23 -3
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- 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/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.map +1 -1
- package/dist/index.js +2411 -365
- 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/shared/tui-preferences.d.ts +32 -0
- package/dist/shared/tui-preferences.d.ts.map +1 -0
- 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/shared/tui-preferences.test.ts +210 -0
- package/src/shared/tui-preferences.ts +303 -0
- package/src/tui/index.tsx +5 -3
- package/src/tui/slots/sidebar-content.tsx +123 -15
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 = ?,
|
|
@@ -15972,7 +15978,7 @@ function persistCachedM0(db, sessionId, payload) {
|
|
|
15972
15978
|
cached_m0_upgrade_state = ?,
|
|
15973
15979
|
cached_m0_system_hash = ?,
|
|
15974
15980
|
cached_m0_model_key = ?
|
|
15975
|
-
WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer2.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, payload.systemHash ?? "", payload.modelKey ?? "", sessionId);
|
|
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);
|
|
15976
15982
|
}
|
|
15977
15983
|
function clearCachedM0M1(db, sessionId) {
|
|
15978
15984
|
ensureSessionMetaRow(db, sessionId);
|
|
@@ -15981,6 +15987,7 @@ function clearCachedM0M1(db, sessionId) {
|
|
|
15981
15987
|
["cached_m0_bytes", null],
|
|
15982
15988
|
["cached_m1_bytes", null],
|
|
15983
15989
|
["cached_m0_project_memory_epoch", null],
|
|
15990
|
+
["cached_m0_workspace_fingerprint", null],
|
|
15984
15991
|
["cached_m0_project_user_profile_version", null],
|
|
15985
15992
|
["cached_m0_max_compartment_seq", null],
|
|
15986
15993
|
["cached_m0_max_memory_id", null],
|
|
@@ -16036,6 +16043,7 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16036
16043
|
"cached_m0_bytes",
|
|
16037
16044
|
"cached_m1_bytes",
|
|
16038
16045
|
"cached_m0_project_memory_epoch",
|
|
16046
|
+
"cached_m0_workspace_fingerprint",
|
|
16039
16047
|
"cached_m0_project_user_profile_version",
|
|
16040
16048
|
"cached_m0_max_compartment_seq",
|
|
16041
16049
|
"cached_m0_max_memory_id",
|
|
@@ -16083,6 +16091,7 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16083
16091
|
cachedM0Bytes: "cached_m0_bytes",
|
|
16084
16092
|
cachedM1Bytes: "cached_m1_bytes",
|
|
16085
16093
|
cachedM0ProjectMemoryEpoch: "cached_m0_project_memory_epoch",
|
|
16094
|
+
cachedM0WorkspaceFingerprint: "cached_m0_workspace_fingerprint",
|
|
16086
16095
|
cachedM0ProjectUserProfileVersion: "cached_m0_project_user_profile_version",
|
|
16087
16096
|
cachedM0MaxCompartmentSeq: "cached_m0_max_compartment_seq",
|
|
16088
16097
|
cachedM0MaxMemoryId: "cached_m0_max_memory_id",
|
|
@@ -16112,6 +16121,7 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16112
16121
|
"cachedM0Bytes",
|
|
16113
16122
|
"cachedM1Bytes",
|
|
16114
16123
|
"cachedM0ProjectMemoryEpoch",
|
|
16124
|
+
"cachedM0WorkspaceFingerprint",
|
|
16115
16125
|
"cachedM0ProjectUserProfileVersion",
|
|
16116
16126
|
"cachedM0MaxCompartmentSeq",
|
|
16117
16127
|
"cachedM0MaxMemoryId",
|
|
@@ -150823,6 +150833,35 @@ function initializeDatabase(db) {
|
|
|
150823
150833
|
);
|
|
150824
150834
|
CREATE INDEX IF NOT EXISTS idx_compartments_session ON compartments(session_id);
|
|
150825
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
|
+
|
|
150826
150865
|
CREATE TABLE IF NOT EXISTS compartment_events (
|
|
150827
150866
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
150828
150867
|
session_id TEXT NOT NULL,
|
|
@@ -151008,6 +151047,25 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151008
151047
|
rekeyed_at INTEGER NOT NULL
|
|
151009
151048
|
);
|
|
151010
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
|
+
|
|
151011
151069
|
CREATE TABLE IF NOT EXISTS v22_backfill_failures (
|
|
151012
151070
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
151013
151071
|
table_name TEXT NOT NULL,
|
|
@@ -151119,6 +151177,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151119
151177
|
deferred_execute_state TEXT,
|
|
151120
151178
|
cached_m0_bytes BLOB,
|
|
151121
151179
|
cached_m0_project_memory_epoch INTEGER,
|
|
151180
|
+
cached_m0_workspace_fingerprint TEXT,
|
|
151122
151181
|
cached_m0_project_user_profile_version INTEGER,
|
|
151123
151182
|
cached_m0_max_compartment_seq INTEGER,
|
|
151124
151183
|
cached_m0_max_memory_id INTEGER,
|
|
@@ -151277,6 +151336,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151277
151336
|
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
151278
151337
|
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
151279
151338
|
ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
|
|
151339
|
+
ensureColumn(db, "session_meta", "processed_image_stripped_ids", "TEXT DEFAULT ''");
|
|
151280
151340
|
ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
|
|
151281
151341
|
ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
|
|
151282
151342
|
ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
|
|
@@ -151330,6 +151390,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151330
151390
|
ensureColumn(db, "memories", "importance", "INTEGER");
|
|
151331
151391
|
ensureColumn(db, "session_meta", "cached_m0_bytes", "BLOB");
|
|
151332
151392
|
ensureColumn(db, "session_meta", "cached_m0_project_memory_epoch", "INTEGER");
|
|
151393
|
+
ensureColumn(db, "session_meta", "cached_m0_workspace_fingerprint", "TEXT");
|
|
151333
151394
|
ensureColumn(db, "session_meta", "cached_m0_project_user_profile_version", "INTEGER");
|
|
151334
151395
|
ensureColumn(db, "session_meta", "cached_m0_max_compartment_seq", "INTEGER");
|
|
151335
151396
|
ensureColumn(db, "session_meta", "cached_m0_max_memory_id", "INTEGER");
|
|
@@ -151361,6 +151422,15 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151361
151422
|
project_user_profile_version INTEGER NOT NULL DEFAULT 0,
|
|
151362
151423
|
updated_at INTEGER NOT NULL DEFAULT 0
|
|
151363
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);
|
|
151364
151434
|
CREATE TABLE IF NOT EXISTS m0_mutation_log (
|
|
151365
151435
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
151366
151436
|
session_id TEXT NOT NULL,
|
|
@@ -151388,6 +151458,23 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151388
151458
|
new_project_path TEXT NOT NULL,
|
|
151389
151459
|
rekeyed_at INTEGER NOT NULL
|
|
151390
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);
|
|
151391
151478
|
CREATE TABLE IF NOT EXISTS v22_backfill_failures (
|
|
151392
151479
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
151393
151480
|
table_name TEXT NOT NULL,
|
|
@@ -151409,6 +151496,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151409
151496
|
ensureColumn(db, "recomp_compartments", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
151410
151497
|
ensureColumn(db, "recomp_facts", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
151411
151498
|
ensureColumn(db, "message_history_index", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
151499
|
+
ensureColumn(db, "workspaces", "share_categories", `TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'`);
|
|
151412
151500
|
}
|
|
151413
151501
|
function healAllNullColumns(db) {
|
|
151414
151502
|
healNullTextColumns(db);
|
|
@@ -151446,6 +151534,7 @@ function healNullTextColumns(db) {
|
|
|
151446
151534
|
["system_prompt_hash", ""],
|
|
151447
151535
|
["stripped_placeholder_ids", ""],
|
|
151448
151536
|
["stale_reduce_stripped_ids", ""],
|
|
151537
|
+
["processed_image_stripped_ids", ""],
|
|
151449
151538
|
["memory_block_cache", ""],
|
|
151450
151539
|
["memory_block_ids", ""],
|
|
151451
151540
|
["compaction_marker_state", ""],
|
|
@@ -151490,7 +151579,7 @@ function healNullIntegerColumns(db) {
|
|
|
151490
151579
|
}
|
|
151491
151580
|
}
|
|
151492
151581
|
function ensureColumn(db, table, column, definition) {
|
|
151493
|
-
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)) {
|
|
151494
151583
|
throw new Error(`Unsafe schema identifier: ${table}.${column} ${definition}`);
|
|
151495
151584
|
}
|
|
151496
151585
|
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
@@ -151576,7 +151665,7 @@ function getDatabasePersistenceError(db) {
|
|
|
151576
151665
|
return null;
|
|
151577
151666
|
return persistenceErrorByDatabase.get(db) ?? null;
|
|
151578
151667
|
}
|
|
151579
|
-
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;
|
|
151580
151669
|
var init_storage_db = __esm(async () => {
|
|
151581
151670
|
init_data_path();
|
|
151582
151671
|
init_logger();
|
|
@@ -151596,10 +151685,302 @@ var init_storage_db = __esm(async () => {
|
|
|
151596
151685
|
};
|
|
151597
151686
|
});
|
|
151598
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
|
+
|
|
151599
151976
|
// src/features/magic-context/migrations.ts
|
|
151600
|
-
function
|
|
151977
|
+
function tableExists2(db, name2) {
|
|
151601
151978
|
return Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(name2));
|
|
151602
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
|
+
}
|
|
151603
151984
|
function ensureMigrationsTable(db) {
|
|
151604
151985
|
db.exec(`
|
|
151605
151986
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
@@ -151668,6 +152049,7 @@ function runMigrations(db) {
|
|
|
151668
152049
|
var MIGRATIONS, LATEST_MIGRATION_VERSION;
|
|
151669
152050
|
var init_migrations = __esm(async () => {
|
|
151670
152051
|
init_logger();
|
|
152052
|
+
init_workspaces();
|
|
151671
152053
|
await init_storage_db();
|
|
151672
152054
|
MIGRATIONS = [
|
|
151673
152055
|
{
|
|
@@ -152127,9 +152509,9 @@ var init_migrations = __esm(async () => {
|
|
|
152127
152509
|
version: 22,
|
|
152128
152510
|
description: "v2.0 cache architecture schema foundation",
|
|
152129
152511
|
up: (db) => {
|
|
152130
|
-
const hasSessionMetaTable =
|
|
152131
|
-
const hasCompartmentsTable =
|
|
152132
|
-
const hasMemoriesTable =
|
|
152512
|
+
const hasSessionMetaTable = tableExists2(db, "session_meta");
|
|
152513
|
+
const hasCompartmentsTable = tableExists2(db, "compartments");
|
|
152514
|
+
const hasMemoriesTable = tableExists2(db, "memories");
|
|
152133
152515
|
if (hasSessionMetaTable) {
|
|
152134
152516
|
ensureColumn(db, "session_meta", "cached_m0_bytes", "BLOB");
|
|
152135
152517
|
ensureColumn(db, "session_meta", "cached_m0_project_memory_epoch", "INTEGER");
|
|
@@ -152154,7 +152536,7 @@ var init_migrations = __esm(async () => {
|
|
|
152154
152536
|
ensureColumn(db, "compartments", "p1_embedding_model_id", "TEXT");
|
|
152155
152537
|
ensureColumn(db, "compartments", "legacy", "INTEGER NOT NULL DEFAULT 0");
|
|
152156
152538
|
}
|
|
152157
|
-
const hasRecompCompartmentsTable =
|
|
152539
|
+
const hasRecompCompartmentsTable = tableExists2(db, "recomp_compartments");
|
|
152158
152540
|
if (hasRecompCompartmentsTable) {
|
|
152159
152541
|
ensureColumn(db, "recomp_compartments", "p1", "TEXT");
|
|
152160
152542
|
ensureColumn(db, "recomp_compartments", "p2", "TEXT");
|
|
@@ -152465,13 +152847,163 @@ var init_migrations = __esm(async () => {
|
|
|
152465
152847
|
db.prepare("UPDATE session_meta SET force_emergency_bypass_used = 0 WHERE force_emergency_bypass_used IS NULL").run();
|
|
152466
152848
|
db.prepare("UPDATE session_meta SET last_usage_context_limit = 0 WHERE last_usage_context_limit IS NULL").run();
|
|
152467
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
|
+
}
|
|
152468
153000
|
}
|
|
152469
153001
|
];
|
|
152470
153002
|
LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
152471
153003
|
});
|
|
152472
153004
|
|
|
152473
153005
|
// src/features/magic-context/project-docs-hash.ts
|
|
152474
|
-
import { createHash as
|
|
153006
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
152475
153007
|
import { lstatSync, readFileSync as readFileSync5, statSync as statSync2 } from "node:fs";
|
|
152476
153008
|
import path4 from "node:path";
|
|
152477
153009
|
function canonicalizeDocContent(raw) {
|
|
@@ -152561,7 +153093,7 @@ function hashCanonicalPieces(hashPieces) {
|
|
|
152561
153093
|
if (hashPieces.length === 0) {
|
|
152562
153094
|
return "";
|
|
152563
153095
|
}
|
|
152564
|
-
return
|
|
153096
|
+
return createHash5("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
|
|
152565
153097
|
}
|
|
152566
153098
|
function readProjectDocsCanonical(projectDirectory) {
|
|
152567
153099
|
const canonicalDirectory = path4.resolve(projectDirectory);
|
|
@@ -152599,11 +153131,6 @@ var init_project_docs_hash = __esm(() => {
|
|
|
152599
153131
|
MAX_PROJECT_DOC_BYTES = 256 * 1024;
|
|
152600
153132
|
docsCache = new Map;
|
|
152601
153133
|
});
|
|
152602
|
-
|
|
152603
|
-
// src/features/magic-context/project-identity.ts
|
|
152604
|
-
var init_project_identity2 = __esm(() => {
|
|
152605
|
-
init_project_identity();
|
|
152606
|
-
});
|
|
152607
153134
|
// src/features/magic-context/storage-m0-mutation-log.ts
|
|
152608
153135
|
function assertMutationType(mutationType) {
|
|
152609
153136
|
if (!M0_MUTATION_TYPES.has(mutationType)) {
|
|
@@ -152688,18 +153215,13 @@ function getMemoryMutation(db, id) {
|
|
|
152688
153215
|
WHERE id = ?`).get(id);
|
|
152689
153216
|
return row ? toMemoryMutation(row) : null;
|
|
152690
153217
|
}
|
|
152691
|
-
function
|
|
152692
|
-
|
|
152693
|
-
|
|
152694
|
-
|
|
152695
|
-
|
|
152696
|
-
|
|
152697
|
-
|
|
152698
|
-
FROM memory_mutation_log
|
|
152699
|
-
WHERE project_path = ?
|
|
152700
|
-
AND id > ?
|
|
152701
|
-
AND target_memory_id IN (${placeholders})
|
|
152702
|
-
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) {
|
|
152703
153225
|
const chosenByTarget = new Map;
|
|
152704
153226
|
for (const dbRow of rows) {
|
|
152705
153227
|
const candidate = toMemoryMutation(dbRow);
|
|
@@ -152720,10 +153242,54 @@ function getMemoryMutationsForRender(db, projectPath, afterId, renderedMemoryIds
|
|
|
152720
153242
|
}
|
|
152721
153243
|
return [...chosenByTarget.values()].sort((left, right) => left.id - right.id);
|
|
152722
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
|
+
}
|
|
152723
153278
|
function getMaxMemoryMutationId(db, projectPath) {
|
|
152724
153279
|
const row = db.prepare("SELECT MAX(id) AS max_id FROM memory_mutation_log WHERE project_path = ?").get(projectPath);
|
|
152725
153280
|
return row?.max_id ?? null;
|
|
152726
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
|
+
}
|
|
152727
153293
|
var MEMORY_MUTATION_TYPES, TERMINAL_MUTATION_TYPES;
|
|
152728
153294
|
var init_storage_memory_mutation_log = __esm(() => {
|
|
152729
153295
|
MEMORY_MUTATION_TYPES = new Set(["archive", "delete", "update", "superseded"]);
|
|
@@ -153416,6 +153982,36 @@ function addStaleReduceStrippedIds(db, sessionId, ids) {
|
|
|
153416
153982
|
sessionLog(sessionId, `stale_reduce_stripped_ids CAS: ${CAS_RETRY_LIMIT} retries exhausted`);
|
|
153417
153983
|
return false;
|
|
153418
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
|
+
}
|
|
153419
154015
|
function isPendingCompactionMarker(value) {
|
|
153420
154016
|
return typeof value === "object" && value !== null && typeof value.ordinal === "number" && typeof value.endMessageId === "string" && typeof value.publishedAt === "number";
|
|
153421
154017
|
}
|
|
@@ -153594,6 +154190,8 @@ function clearSession(db, sessionId) {
|
|
|
153594
154190
|
db.prepare("DELETE FROM source_contents WHERE session_id = ?").run(sessionId);
|
|
153595
154191
|
db.prepare("DELETE FROM tags WHERE session_id = ?").run(sessionId);
|
|
153596
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);
|
|
153597
154195
|
db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
|
|
153598
154196
|
clearCompressionDepth(db, sessionId);
|
|
153599
154197
|
db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
|
|
@@ -153700,9 +154298,9 @@ function buildStatusClause(status) {
|
|
|
153700
154298
|
if (statuses.length === 0) {
|
|
153701
154299
|
return null;
|
|
153702
154300
|
}
|
|
153703
|
-
const
|
|
154301
|
+
const placeholders3 = statuses.map(() => "?").join(", ");
|
|
153704
154302
|
return {
|
|
153705
|
-
sql: `status IN (${
|
|
154303
|
+
sql: `status IN (${placeholders3})`,
|
|
153706
154304
|
params: statuses
|
|
153707
154305
|
};
|
|
153708
154306
|
}
|
|
@@ -153908,19 +154506,6 @@ function getProjectState(db, projectPath) {
|
|
|
153908
154506
|
WHERE project_path = ?`).get(projectPath);
|
|
153909
154507
|
return row ? toProjectState(row) : null;
|
|
153910
154508
|
}
|
|
153911
|
-
function bumpProjectMemoryEpoch(db, projectPath, now = Date.now()) {
|
|
153912
|
-
db.prepare(`INSERT INTO project_state
|
|
153913
|
-
(project_path, project_memory_epoch, project_user_profile_version, updated_at)
|
|
153914
|
-
VALUES (?, 1, 0, ?)
|
|
153915
|
-
ON CONFLICT(project_path) DO UPDATE SET
|
|
153916
|
-
project_memory_epoch = project_memory_epoch + 1,
|
|
153917
|
-
updated_at = excluded.updated_at`).run(projectPath, now);
|
|
153918
|
-
const state = getProjectState(db, projectPath);
|
|
153919
|
-
if (!state) {
|
|
153920
|
-
throw new Error(`Failed to bump project memory epoch for ${projectPath}`);
|
|
153921
|
-
}
|
|
153922
|
-
return state;
|
|
153923
|
-
}
|
|
153924
154509
|
function bumpProjectUserProfileVersion(db, projectPath = GLOBAL_USER_PROFILE_PROJECT_PATH, now = Date.now()) {
|
|
153925
154510
|
db.prepare(`INSERT INTO project_state
|
|
153926
154511
|
(project_path, project_memory_epoch, project_user_profile_version, updated_at)
|
|
@@ -153956,8 +154541,8 @@ function getSourceContents(db, sessionId, tagIds) {
|
|
|
153956
154541
|
if (tagIds.length === 0) {
|
|
153957
154542
|
return new Map;
|
|
153958
154543
|
}
|
|
153959
|
-
const
|
|
153960
|
-
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);
|
|
153961
154546
|
const sources = new Map;
|
|
153962
154547
|
for (const row of rows) {
|
|
153963
154548
|
sources.set(row.tag_id, row.content);
|
|
@@ -154021,15 +154606,22 @@ function ownerMessageIdForTagRow(row) {
|
|
|
154021
154606
|
}
|
|
154022
154607
|
return row.message_id.replace(CONTENT_ID_SUFFIX, "");
|
|
154023
154608
|
}
|
|
154024
|
-
function getActiveTagTokenAggregate(db, sessionId) {
|
|
154025
|
-
const
|
|
154609
|
+
function getActiveTagTokenAggregate(db, sessionId, protectedTags = 0) {
|
|
154610
|
+
const toolOutputExpr = protectedTags > 0 ? `COALESCE(SUM(CASE WHEN type = 'tool' AND tag_number < (
|
|
154611
|
+
SELECT tag_number FROM tags
|
|
154612
|
+
WHERE session_id = ? AND status = 'active'
|
|
154613
|
+
ORDER BY tag_number DESC LIMIT 1 OFFSET ?
|
|
154614
|
+
) THEN COALESCE(token_count, 0) ELSE 0 END), 0)` : `COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)`;
|
|
154615
|
+
const sql = `SELECT
|
|
154026
154616
|
COALESCE(SUM(CASE WHEN type != 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)
|
|
154027
154617
|
+ COALESCE(SUM(COALESCE(reasoning_token_count, 0)), 0) AS conversation,
|
|
154028
154618
|
COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) + COALESCE(input_token_count, 0) ELSE 0 END), 0) AS tool_call,
|
|
154029
|
-
|
|
154619
|
+
${toolOutputExpr} AS tool_output,
|
|
154030
154620
|
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
154031
154621
|
FROM tags
|
|
154032
|
-
WHERE session_id = ? AND status = 'active'
|
|
154622
|
+
WHERE session_id = ? AND status = 'active'`;
|
|
154623
|
+
const params = protectedTags > 0 ? [sessionId, protectedTags - 1, sessionId] : [sessionId];
|
|
154624
|
+
const row = db.prepare(sql).get(...params);
|
|
154033
154625
|
return {
|
|
154034
154626
|
conversation: row?.conversation ?? 0,
|
|
154035
154627
|
toolCall: row?.tool_call ?? 0,
|
|
@@ -154267,8 +154859,8 @@ function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
|
154267
154859
|
}
|
|
154268
154860
|
return all;
|
|
154269
154861
|
}
|
|
154270
|
-
const
|
|
154271
|
-
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${
|
|
154862
|
+
const placeholders3 = tagNumbers.map(() => "?").join(",");
|
|
154863
|
+
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);
|
|
154272
154864
|
return rows.map(toTagEntry);
|
|
154273
154865
|
}
|
|
154274
154866
|
function getMaxDroppedTagNumber(db, sessionId) {
|
|
@@ -154421,6 +155013,7 @@ var init_storage = __esm(async () => {
|
|
|
154421
155013
|
init_storage_source();
|
|
154422
155014
|
init_storage_tags();
|
|
154423
155015
|
init_storage_v22_backfill_failures();
|
|
155016
|
+
init_workspaces();
|
|
154424
155017
|
await __promiseAll([
|
|
154425
155018
|
init_message_index(),
|
|
154426
155019
|
init_migrations(),
|
|
@@ -163872,7 +164465,7 @@ function isEmbeddingRow(row) {
|
|
|
163872
164465
|
if (row === null || typeof row !== "object")
|
|
163873
164466
|
return false;
|
|
163874
164467
|
const candidate = row;
|
|
163875
|
-
return typeof candidate.memoryId === "number" && isEmbeddingBlob(candidate.embedding);
|
|
164468
|
+
return typeof candidate.memoryId === "number" && isEmbeddingBlob(candidate.embedding) && (candidate.modelId === null || typeof candidate.modelId === "string");
|
|
163876
164469
|
}
|
|
163877
164470
|
function toFloat32Array(blob) {
|
|
163878
164471
|
if (blob instanceof Uint8Array) {
|
|
@@ -163892,7 +164485,7 @@ function getSaveEmbeddingStatement(db) {
|
|
|
163892
164485
|
function getLoadAllEmbeddingsStatement(db) {
|
|
163893
164486
|
let stmt = loadAllEmbeddingsStatements.get(db);
|
|
163894
164487
|
if (!stmt) {
|
|
163895
|
-
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");
|
|
164488
|
+
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");
|
|
163896
164489
|
loadAllEmbeddingsStatements.set(db, stmt);
|
|
163897
164490
|
}
|
|
163898
164491
|
return stmt;
|
|
@@ -163921,7 +164514,10 @@ function loadAllEmbeddings(db, projectPath) {
|
|
|
163921
164514
|
const rows = getLoadAllEmbeddingsStatement(db).all(projectPath).filter(isEmbeddingRow);
|
|
163922
164515
|
const embeddings = new Map;
|
|
163923
164516
|
for (const row of rows) {
|
|
163924
|
-
embeddings.set(row.memoryId,
|
|
164517
|
+
embeddings.set(row.memoryId, {
|
|
164518
|
+
embedding: toFloat32Array(row.embedding),
|
|
164519
|
+
modelId: row.modelId
|
|
164520
|
+
});
|
|
163925
164521
|
}
|
|
163926
164522
|
return embeddings;
|
|
163927
164523
|
}
|
|
@@ -163984,13 +164580,13 @@ var init_embedding_cache = __esm(() => {
|
|
|
163984
164580
|
});
|
|
163985
164581
|
|
|
163986
164582
|
// src/features/magic-context/memory/normalize-hash.ts
|
|
163987
|
-
import { createHash as
|
|
164583
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
163988
164584
|
function normalizeMemoryContent(content) {
|
|
163989
164585
|
return content.toLowerCase().replace(/\s+/g, " ").trim();
|
|
163990
164586
|
}
|
|
163991
164587
|
function computeNormalizedHash(content) {
|
|
163992
164588
|
const normalized = normalizeMemoryContent(content);
|
|
163993
|
-
return
|
|
164589
|
+
return createHash7("md5").update(normalized).digest("hex");
|
|
163994
164590
|
}
|
|
163995
164591
|
var init_normalize_hash = () => {};
|
|
163996
164592
|
|
|
@@ -164104,8 +164700,8 @@ function getMemoriesByProjectStatement(db, statuses) {
|
|
|
164104
164700
|
}
|
|
164105
164701
|
let stmt = statements.get(db);
|
|
164106
164702
|
if (!stmt) {
|
|
164107
|
-
const
|
|
164108
|
-
stmt = db.prepare(`SELECT ${getMemorySelectColumns(db)} FROM memories WHERE project_path = ? AND status IN (${
|
|
164703
|
+
const placeholders3 = statuses.map(() => "?").join(", ");
|
|
164704
|
+
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`);
|
|
164109
164705
|
statements.set(db, stmt);
|
|
164110
164706
|
}
|
|
164111
164707
|
return stmt;
|
|
@@ -164226,6 +164822,97 @@ function getMemoriesByProject(db, projectPath, statuses = ["active", "permanent"
|
|
|
164226
164822
|
const rows = getMemoriesByProjectStatement(db, statuses).all(projectPath, ...statuses, expiryCutoff).filter(isMemoryRow);
|
|
164227
164823
|
return rows.map(toMemory);
|
|
164228
164824
|
}
|
|
164825
|
+
function sqlPlaceholders(values) {
|
|
164826
|
+
return values.map(() => "?").join(", ");
|
|
164827
|
+
}
|
|
164828
|
+
function uniqueValues(values) {
|
|
164829
|
+
return [...new Set(values.filter((value) => value.length > 0))];
|
|
164830
|
+
}
|
|
164831
|
+
function buildWorkspaceMemorySqlFilter(args) {
|
|
164832
|
+
if (args.shareCategories === null || args.shareCategories === undefined) {
|
|
164833
|
+
return { clause: "", params: [], active: false };
|
|
164834
|
+
}
|
|
164835
|
+
const identities = uniqueValues(args.identities);
|
|
164836
|
+
const identitySet = new Set(identities);
|
|
164837
|
+
const ownSet = new Set(uniqueValues(args.ownIdentities ?? []).filter((identity) => identitySet.has(identity)));
|
|
164838
|
+
const foreignIdentities = identities.filter((identity) => !ownSet.has(identity));
|
|
164839
|
+
if (foreignIdentities.length === 0) {
|
|
164840
|
+
return { clause: "", params: [], active: false };
|
|
164841
|
+
}
|
|
164842
|
+
const ownIdentities = identities.filter((identity) => ownSet.has(identity));
|
|
164843
|
+
const shareCategories = uniqueValues([...args.shareCategories]);
|
|
164844
|
+
const qualifier = args.tableName ? `${args.tableName}.` : "";
|
|
164845
|
+
const predicates = [];
|
|
164846
|
+
const params = [];
|
|
164847
|
+
if (ownIdentities.length > 0) {
|
|
164848
|
+
predicates.push(`${qualifier}project_path IN (${sqlPlaceholders(ownIdentities)})`);
|
|
164849
|
+
params.push(...ownIdentities);
|
|
164850
|
+
}
|
|
164851
|
+
if (foreignIdentities.length > 0 && shareCategories.length > 0) {
|
|
164852
|
+
predicates.push(`(${qualifier}project_path IN (${sqlPlaceholders(foreignIdentities)}) AND ${qualifier}category IN (${sqlPlaceholders(shareCategories)}))`);
|
|
164853
|
+
params.push(...foreignIdentities, ...shareCategories);
|
|
164854
|
+
}
|
|
164855
|
+
if (predicates.length === 0) {
|
|
164856
|
+
return { clause: " AND 0 = 1", params: [], active: true };
|
|
164857
|
+
}
|
|
164858
|
+
return { clause: ` AND (${predicates.join(" OR ")})`, params, active: true };
|
|
164859
|
+
}
|
|
164860
|
+
function getMemoriesByProjects(db, projectPaths, statuses = ["active", "permanent"], expiryCutoff = Date.now(), ownIdentities, shareCategories) {
|
|
164861
|
+
const identities = uniqueValues(projectPaths);
|
|
164862
|
+
if (identities.length === 0 || statuses.length === 0)
|
|
164863
|
+
return [];
|
|
164864
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
164865
|
+
identities,
|
|
164866
|
+
ownIdentities,
|
|
164867
|
+
shareCategories
|
|
164868
|
+
});
|
|
164869
|
+
if (identities.length === 1 && !sharingFilter.active) {
|
|
164870
|
+
return getMemoriesByProject(db, identities[0], statuses, expiryCutoff);
|
|
164871
|
+
}
|
|
164872
|
+
const rows = db.prepare(`SELECT ${getMemorySelectColumns(db)}
|
|
164873
|
+
FROM memories
|
|
164874
|
+
WHERE project_path IN (${sqlPlaceholders(identities)})
|
|
164875
|
+
AND status IN (${sqlPlaceholders(statuses)})
|
|
164876
|
+
AND (expires_at IS NULL OR expires_at > ?)${sharingFilter.clause}
|
|
164877
|
+
ORDER BY category ASC, updated_at DESC, id ASC`).all(...identities, ...statuses, expiryCutoff, ...sharingFilter.params).filter(isMemoryRow);
|
|
164878
|
+
return rows.map(toMemory);
|
|
164879
|
+
}
|
|
164880
|
+
function getMaxMemoryIdForProjects(db, projectPaths, ownIdentities, shareCategories) {
|
|
164881
|
+
const identities = uniqueValues(projectPaths);
|
|
164882
|
+
if (identities.length === 0)
|
|
164883
|
+
return 0;
|
|
164884
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
164885
|
+
identities,
|
|
164886
|
+
ownIdentities,
|
|
164887
|
+
shareCategories
|
|
164888
|
+
});
|
|
164889
|
+
if (identities.length === 1 && !sharingFilter.active) {
|
|
164890
|
+
const row2 = db.prepare("SELECT COALESCE(MAX(id), 0) AS max_id FROM memories WHERE project_path = ?").get(identities[0]);
|
|
164891
|
+
return typeof row2?.max_id === "number" ? row2.max_id : 0;
|
|
164892
|
+
}
|
|
164893
|
+
const row = db.prepare(`SELECT COALESCE(MAX(id), 0) AS max_id
|
|
164894
|
+
FROM memories
|
|
164895
|
+
WHERE project_path IN (${sqlPlaceholders(identities)})${sharingFilter.clause}`).get(...identities, ...sharingFilter.params);
|
|
164896
|
+
return typeof row?.max_id === "number" ? row.max_id : 0;
|
|
164897
|
+
}
|
|
164898
|
+
function readNewMemoriesForM1Union(db, projectPaths, afterId, expiryCutoff, ownIdentities, shareCategories) {
|
|
164899
|
+
const identities = uniqueValues(projectPaths);
|
|
164900
|
+
if (identities.length === 0)
|
|
164901
|
+
return [];
|
|
164902
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
164903
|
+
identities,
|
|
164904
|
+
ownIdentities,
|
|
164905
|
+
shareCategories
|
|
164906
|
+
});
|
|
164907
|
+
const rows = db.prepare(`SELECT ${getMemorySelectColumns(db)}
|
|
164908
|
+
FROM memories
|
|
164909
|
+
WHERE project_path IN (${sqlPlaceholders(identities)})
|
|
164910
|
+
AND id > ?
|
|
164911
|
+
AND status IN ('active', 'permanent')
|
|
164912
|
+
AND (expires_at IS NULL OR expires_at > ?)${sharingFilter.clause}
|
|
164913
|
+
ORDER BY ${MEMORY_CATEGORY_ORDER_SQL}, id ASC`).all(...identities, afterId, expiryCutoff, ...sharingFilter.params).filter(isMemoryRow);
|
|
164914
|
+
return rows.map(toMemory);
|
|
164915
|
+
}
|
|
164229
164916
|
function getAllActiveMemoriesForMigration(db, projectPath) {
|
|
164230
164917
|
const rows = getActiveMemoriesNoExpiryStatement(db).all(projectPath).filter(isMemoryRow);
|
|
164231
164918
|
return rows.map(toMemory);
|
|
@@ -164323,6 +165010,7 @@ function getMemoryCountsByStatus(db, projectPath) {
|
|
|
164323
165010
|
}
|
|
164324
165011
|
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;
|
|
164325
165012
|
var init_storage_memory = __esm(() => {
|
|
165013
|
+
init_constants();
|
|
164326
165014
|
init_embedding_cache();
|
|
164327
165015
|
init_normalize_hash();
|
|
164328
165016
|
COLUMN_MAP = {
|
|
@@ -164428,8 +165116,8 @@ function getUserMemoryCandidates(db) {
|
|
|
164428
165116
|
function deleteUserMemoryCandidates(db, ids) {
|
|
164429
165117
|
if (ids.length === 0)
|
|
164430
165118
|
return;
|
|
164431
|
-
const
|
|
164432
|
-
db.prepare(`DELETE FROM user_memory_candidates WHERE id IN (${
|
|
165119
|
+
const placeholders3 = ids.map(() => "?").join(",");
|
|
165120
|
+
db.prepare(`DELETE FROM user_memory_candidates WHERE id IN (${placeholders3})`).run(...ids);
|
|
164433
165121
|
}
|
|
164434
165122
|
function insertUserMemory(db, content, sourceCandidateIds) {
|
|
164435
165123
|
const now = Date.now();
|
|
@@ -164462,6 +165150,445 @@ function parseUserMemoryRow(row) {
|
|
|
164462
165150
|
};
|
|
164463
165151
|
}
|
|
164464
165152
|
|
|
165153
|
+
// src/features/magic-context/compartment-chunk-embedding.ts
|
|
165154
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
165155
|
+
function getLoadFtsRowsStatement(db) {
|
|
165156
|
+
let stmt = loadFtsRowsStatements.get(db);
|
|
165157
|
+
if (!stmt) {
|
|
165158
|
+
stmt = db.prepare(`SELECT message_ordinal AS messageOrdinal, role, content
|
|
165159
|
+
FROM message_history_fts
|
|
165160
|
+
WHERE session_id = ?
|
|
165161
|
+
AND message_ordinal >= ?
|
|
165162
|
+
AND message_ordinal <= ?
|
|
165163
|
+
AND role IN ('user', 'assistant')
|
|
165164
|
+
ORDER BY message_ordinal ASC`);
|
|
165165
|
+
loadFtsRowsStatements.set(db, stmt);
|
|
165166
|
+
}
|
|
165167
|
+
return stmt;
|
|
165168
|
+
}
|
|
165169
|
+
function getExistingHashStatement(db, scopedToProject) {
|
|
165170
|
+
const map2 = scopedToProject ? existingHashByProjectStatements : existingHashStatements;
|
|
165171
|
+
let stmt = map2.get(db);
|
|
165172
|
+
if (!stmt) {
|
|
165173
|
+
stmt = db.prepare(`SELECT window_index AS windowIndex, chunk_hash AS chunkHash
|
|
165174
|
+
FROM compartment_chunk_embeddings
|
|
165175
|
+
WHERE compartment_id = ?
|
|
165176
|
+
AND model_id = ?
|
|
165177
|
+
${scopedToProject ? "AND project_path = ?" : ""}
|
|
165178
|
+
ORDER BY window_index ASC`);
|
|
165179
|
+
map2.set(db, stmt);
|
|
165180
|
+
}
|
|
165181
|
+
return stmt;
|
|
165182
|
+
}
|
|
165183
|
+
function getDeleteByCompartmentStatement(db) {
|
|
165184
|
+
let stmt = deleteByCompartmentStatements.get(db);
|
|
165185
|
+
if (!stmt) {
|
|
165186
|
+
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE compartment_id = ?");
|
|
165187
|
+
deleteByCompartmentStatements.set(db, stmt);
|
|
165188
|
+
}
|
|
165189
|
+
return stmt;
|
|
165190
|
+
}
|
|
165191
|
+
function getInsertEmbeddingStatement(db) {
|
|
165192
|
+
let stmt = insertEmbeddingStatements.get(db);
|
|
165193
|
+
if (!stmt) {
|
|
165194
|
+
stmt = db.prepare(`INSERT INTO compartment_chunk_embeddings (
|
|
165195
|
+
compartment_id, session_id, project_path, harness, window_index,
|
|
165196
|
+
start_ordinal, end_ordinal, chunk_hash, model_id, dims, vector, created_at
|
|
165197
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
165198
|
+
insertEmbeddingStatements.set(db, stmt);
|
|
165199
|
+
}
|
|
165200
|
+
return stmt;
|
|
165201
|
+
}
|
|
165202
|
+
function getDistinctModelStatement(db) {
|
|
165203
|
+
let stmt = distinctModelStatements.get(db);
|
|
165204
|
+
if (!stmt) {
|
|
165205
|
+
stmt = db.prepare(`SELECT DISTINCT model_id AS modelId
|
|
165206
|
+
FROM compartment_chunk_embeddings
|
|
165207
|
+
WHERE project_path = ?`);
|
|
165208
|
+
distinctModelStatements.set(db, stmt);
|
|
165209
|
+
}
|
|
165210
|
+
return stmt;
|
|
165211
|
+
}
|
|
165212
|
+
function getClearProjectStatement(db) {
|
|
165213
|
+
let stmt = clearProjectStatements.get(db);
|
|
165214
|
+
if (!stmt) {
|
|
165215
|
+
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE project_path = ?");
|
|
165216
|
+
clearProjectStatements.set(db, stmt);
|
|
165217
|
+
}
|
|
165218
|
+
return stmt;
|
|
165219
|
+
}
|
|
165220
|
+
function getClearProjectModelStatement(db) {
|
|
165221
|
+
let stmt = clearProjectModelStatements.get(db);
|
|
165222
|
+
if (!stmt) {
|
|
165223
|
+
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE project_path = ? AND model_id = ?");
|
|
165224
|
+
clearProjectModelStatements.set(db, stmt);
|
|
165225
|
+
}
|
|
165226
|
+
return stmt;
|
|
165227
|
+
}
|
|
165228
|
+
function getSearchRowsStatement(db, withModel) {
|
|
165229
|
+
const map2 = withModel ? searchRowsByModelStatements : searchRowsStatements;
|
|
165230
|
+
let stmt = map2.get(db);
|
|
165231
|
+
if (!stmt) {
|
|
165232
|
+
stmt = db.prepare(`SELECT e.compartment_id AS compartmentId,
|
|
165233
|
+
e.session_id AS sessionId,
|
|
165234
|
+
c.title AS title,
|
|
165235
|
+
c.start_message AS compartmentStart,
|
|
165236
|
+
c.end_message AS compartmentEnd,
|
|
165237
|
+
e.window_index AS windowIndex,
|
|
165238
|
+
e.start_ordinal AS windowStart,
|
|
165239
|
+
e.end_ordinal AS windowEnd,
|
|
165240
|
+
e.chunk_hash AS chunkHash,
|
|
165241
|
+
e.model_id AS modelId,
|
|
165242
|
+
e.dims AS dims,
|
|
165243
|
+
e.vector AS vector
|
|
165244
|
+
FROM compartment_chunk_embeddings e
|
|
165245
|
+
JOIN compartments c ON c.id = e.compartment_id
|
|
165246
|
+
WHERE e.session_id = ?
|
|
165247
|
+
AND e.project_path = ?
|
|
165248
|
+
${withModel ? "AND e.model_id = ?" : ""}
|
|
165249
|
+
ORDER BY e.compartment_id ASC, e.window_index ASC`);
|
|
165250
|
+
map2.set(db, stmt);
|
|
165251
|
+
}
|
|
165252
|
+
return stmt;
|
|
165253
|
+
}
|
|
165254
|
+
function isFinitePositiveInteger(value) {
|
|
165255
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
165256
|
+
}
|
|
165257
|
+
function normalizeCompartmentChunkMaxInputTokens(value) {
|
|
165258
|
+
if (!isFinitePositiveInteger(value)) {
|
|
165259
|
+
return DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS;
|
|
165260
|
+
}
|
|
165261
|
+
return Math.max(1, Math.floor(value));
|
|
165262
|
+
}
|
|
165263
|
+
function normalizeContent(text) {
|
|
165264
|
+
return text.replace(/\s+/g, " ").trim();
|
|
165265
|
+
}
|
|
165266
|
+
function formatOrdinalRange(start, end) {
|
|
165267
|
+
return start === end ? `[${start}]` : `[${start}-${end}]`;
|
|
165268
|
+
}
|
|
165269
|
+
function rolePrefix(role) {
|
|
165270
|
+
if (role === "user")
|
|
165271
|
+
return "U";
|
|
165272
|
+
if (role === "assistant")
|
|
165273
|
+
return "A";
|
|
165274
|
+
return null;
|
|
165275
|
+
}
|
|
165276
|
+
function parseOrdinal(value) {
|
|
165277
|
+
const parsed = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
165278
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
165279
|
+
}
|
|
165280
|
+
function parseCanonicalLineRange(line) {
|
|
165281
|
+
const match = /^\[(\d+)(?:-(\d+))?\]\s+[UA]:/.exec(line.trim());
|
|
165282
|
+
if (!match)
|
|
165283
|
+
return null;
|
|
165284
|
+
const start = Number.parseInt(match[1], 10);
|
|
165285
|
+
const end = match[2] ? Number.parseInt(match[2], 10) : start;
|
|
165286
|
+
if (!Number.isFinite(start) || !Number.isFinite(end))
|
|
165287
|
+
return null;
|
|
165288
|
+
return { start, end };
|
|
165289
|
+
}
|
|
165290
|
+
function hashChunkText(text) {
|
|
165291
|
+
return createHash8("sha256").update(text).digest("hex");
|
|
165292
|
+
}
|
|
165293
|
+
function vectorBlob(vector) {
|
|
165294
|
+
return new Uint8Array(vector.buffer, vector.byteOffset, vector.byteLength);
|
|
165295
|
+
}
|
|
165296
|
+
function toFloat32Array2(blob) {
|
|
165297
|
+
if (blob instanceof Uint8Array) {
|
|
165298
|
+
const buffer2 = blob.buffer.slice(blob.byteOffset, blob.byteOffset + blob.byteLength);
|
|
165299
|
+
return new Float32Array(buffer2);
|
|
165300
|
+
}
|
|
165301
|
+
return new Float32Array(blob.slice(0));
|
|
165302
|
+
}
|
|
165303
|
+
function buildCanonicalChunkTextFromFts(db, sessionId, startOrdinal, endOrdinal) {
|
|
165304
|
+
if (endOrdinal < startOrdinal)
|
|
165305
|
+
return "";
|
|
165306
|
+
const rows = getLoadFtsRowsStatement(db).all(sessionId, startOrdinal, endOrdinal).map((row) => row);
|
|
165307
|
+
const lines = [];
|
|
165308
|
+
let current = null;
|
|
165309
|
+
const flush2 = () => {
|
|
165310
|
+
if (!current || current.parts.length === 0)
|
|
165311
|
+
return;
|
|
165312
|
+
lines.push(`${formatOrdinalRange(current.start, current.end)} ${current.role}: ${current.parts.join(" / ")}`);
|
|
165313
|
+
current = null;
|
|
165314
|
+
};
|
|
165315
|
+
for (const row of rows) {
|
|
165316
|
+
const ordinal = parseOrdinal(row.messageOrdinal);
|
|
165317
|
+
const prefix = rolePrefix(row.role);
|
|
165318
|
+
const content = typeof row.content === "string" ? normalizeContent(row.content) : "";
|
|
165319
|
+
if (ordinal === null || prefix === null || content.length === 0)
|
|
165320
|
+
continue;
|
|
165321
|
+
if (current && current.role === prefix) {
|
|
165322
|
+
current.end = ordinal;
|
|
165323
|
+
current.parts.push(content);
|
|
165324
|
+
continue;
|
|
165325
|
+
}
|
|
165326
|
+
flush2();
|
|
165327
|
+
current = { role: prefix, start: ordinal, end: ordinal, parts: [content] };
|
|
165328
|
+
}
|
|
165329
|
+
flush2();
|
|
165330
|
+
return lines.join(`
|
|
165331
|
+
`);
|
|
165332
|
+
}
|
|
165333
|
+
function canonicalizeInMemoryChunkTextForEmbedding(chunkText, startOrdinal, endOrdinal) {
|
|
165334
|
+
const lines = [];
|
|
165335
|
+
for (const rawLine of chunkText.split(/\r?\n/)) {
|
|
165336
|
+
const line = rawLine.trim();
|
|
165337
|
+
const match = /^(\[(\d+)(?:-(\d+))?\]\s+[UA]:)\s*(.*)$/.exec(line);
|
|
165338
|
+
if (!match)
|
|
165339
|
+
continue;
|
|
165340
|
+
const lineStart = Number.parseInt(match[2], 10);
|
|
165341
|
+
const lineEnd = match[3] ? Number.parseInt(match[3], 10) : lineStart;
|
|
165342
|
+
if (startOrdinal != null && lineEnd < startOrdinal)
|
|
165343
|
+
continue;
|
|
165344
|
+
if (endOrdinal != null && lineStart > endOrdinal)
|
|
165345
|
+
continue;
|
|
165346
|
+
const rawParts = match[4].split(" / ").map((part) => normalizeContent(part)).filter((part) => part.length > 0);
|
|
165347
|
+
const ordinalSpan = lineEnd - lineStart + 1;
|
|
165348
|
+
const roleLabel = match[1].slice(match[1].indexOf("]") + 2);
|
|
165349
|
+
if (ordinalSpan === rawParts.length) {
|
|
165350
|
+
const retained = rawParts.map((part, index) => ({ ordinal: lineStart + index, part })).filter(({ ordinal, part }) => {
|
|
165351
|
+
if (part.startsWith("TC:"))
|
|
165352
|
+
return false;
|
|
165353
|
+
if (startOrdinal != null && ordinal < startOrdinal)
|
|
165354
|
+
return false;
|
|
165355
|
+
if (endOrdinal != null && ordinal > endOrdinal)
|
|
165356
|
+
return false;
|
|
165357
|
+
return true;
|
|
165358
|
+
});
|
|
165359
|
+
if (retained.length === 0)
|
|
165360
|
+
continue;
|
|
165361
|
+
const retainedStart = retained[0].ordinal;
|
|
165362
|
+
const retainedEnd = retained[retained.length - 1].ordinal;
|
|
165363
|
+
lines.push(`${formatOrdinalRange(retainedStart, retainedEnd)} ${roleLabel} ${retained.map(({ part }) => part).join(" / ")}`);
|
|
165364
|
+
continue;
|
|
165365
|
+
}
|
|
165366
|
+
const parts = rawParts.filter((part) => !part.startsWith("TC:"));
|
|
165367
|
+
if (parts.length === 0)
|
|
165368
|
+
continue;
|
|
165369
|
+
lines.push(`${match[1]} ${parts.join(" / ")}`);
|
|
165370
|
+
}
|
|
165371
|
+
return lines.join(`
|
|
165372
|
+
`);
|
|
165373
|
+
}
|
|
165374
|
+
function chunkCanonicalText(canonicalText, startOrdinal, endOrdinal, maxInputTokens) {
|
|
165375
|
+
const lines = canonicalText.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
165376
|
+
if (lines.length === 0 || endOrdinal < startOrdinal)
|
|
165377
|
+
return [];
|
|
165378
|
+
const normalizedMax = normalizeCompartmentChunkMaxInputTokens(maxInputTokens);
|
|
165379
|
+
const effectiveMax = Math.max(1, Math.floor(normalizedMax * CHUNK_WINDOW_SAFETY_RATIO));
|
|
165380
|
+
const fullText = lines.join(`
|
|
165381
|
+
`);
|
|
165382
|
+
if (estimateTokens(fullText) <= effectiveMax) {
|
|
165383
|
+
return [
|
|
165384
|
+
{
|
|
165385
|
+
windowIndex: 0,
|
|
165386
|
+
startOrdinal,
|
|
165387
|
+
endOrdinal,
|
|
165388
|
+
text: fullText,
|
|
165389
|
+
chunkHash: hashChunkText(fullText)
|
|
165390
|
+
}
|
|
165391
|
+
];
|
|
165392
|
+
}
|
|
165393
|
+
const windows = [];
|
|
165394
|
+
let currentLines = [];
|
|
165395
|
+
let currentStart = null;
|
|
165396
|
+
let currentEnd = null;
|
|
165397
|
+
let currentTokens = 0;
|
|
165398
|
+
const flush2 = () => {
|
|
165399
|
+
if (currentLines.length === 0 || currentStart === null || currentEnd === null)
|
|
165400
|
+
return;
|
|
165401
|
+
const text = currentLines.join(`
|
|
165402
|
+
`);
|
|
165403
|
+
windows.push({
|
|
165404
|
+
windowIndex: windows.length + 1,
|
|
165405
|
+
startOrdinal: currentStart,
|
|
165406
|
+
endOrdinal: currentEnd,
|
|
165407
|
+
text,
|
|
165408
|
+
chunkHash: hashChunkText(text)
|
|
165409
|
+
});
|
|
165410
|
+
currentLines = [];
|
|
165411
|
+
currentStart = null;
|
|
165412
|
+
currentEnd = null;
|
|
165413
|
+
currentTokens = 0;
|
|
165414
|
+
};
|
|
165415
|
+
for (const line of lines) {
|
|
165416
|
+
const range = parseCanonicalLineRange(line);
|
|
165417
|
+
const lineStart = range?.start ?? startOrdinal;
|
|
165418
|
+
const lineEnd = range?.end ?? lineStart;
|
|
165419
|
+
const lineTokens = estimateTokens(line);
|
|
165420
|
+
if (currentLines.length > 0 && currentTokens + lineTokens > effectiveMax) {
|
|
165421
|
+
flush2();
|
|
165422
|
+
}
|
|
165423
|
+
if (currentLines.length === 0) {
|
|
165424
|
+
currentStart = lineStart;
|
|
165425
|
+
}
|
|
165426
|
+
currentLines.push(line);
|
|
165427
|
+
currentEnd = lineEnd;
|
|
165428
|
+
currentTokens += lineTokens;
|
|
165429
|
+
}
|
|
165430
|
+
flush2();
|
|
165431
|
+
return windows;
|
|
165432
|
+
}
|
|
165433
|
+
function getExistingChunkHashes(db, compartmentId, modelId, projectPath) {
|
|
165434
|
+
const scoped = typeof projectPath === "string" && projectPath.length > 0;
|
|
165435
|
+
const rows = scoped ? getExistingHashStatement(db, true).all(compartmentId, modelId, projectPath) : getExistingHashStatement(db, false).all(compartmentId, modelId);
|
|
165436
|
+
return new Map(rows.filter((row) => typeof row.windowIndex === "number" && typeof row.chunkHash === "string").map((row) => [row.windowIndex, row.chunkHash]));
|
|
165437
|
+
}
|
|
165438
|
+
function chunkEmbeddingWindowsAreCurrent(db, compartmentId, modelId, windows, projectPath) {
|
|
165439
|
+
const existing = getExistingChunkHashes(db, compartmentId, modelId, projectPath);
|
|
165440
|
+
if (existing.size !== windows.length)
|
|
165441
|
+
return false;
|
|
165442
|
+
return windows.every((window) => existing.get(window.windowIndex) === window.chunkHash);
|
|
165443
|
+
}
|
|
165444
|
+
function replaceCompartmentChunkEmbeddings(db, rows) {
|
|
165445
|
+
if (rows.length === 0)
|
|
165446
|
+
return;
|
|
165447
|
+
const compartmentId = rows[0].compartmentId;
|
|
165448
|
+
const now = Date.now();
|
|
165449
|
+
db.transaction(() => {
|
|
165450
|
+
getDeleteByCompartmentStatement(db).run(compartmentId);
|
|
165451
|
+
const insert = getInsertEmbeddingStatement(db);
|
|
165452
|
+
for (const row of rows) {
|
|
165453
|
+
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);
|
|
165454
|
+
}
|
|
165455
|
+
})();
|
|
165456
|
+
}
|
|
165457
|
+
function getDistinctChunkEmbeddingModelIds(db, projectPath) {
|
|
165458
|
+
const rows = getDistinctModelStatement(db).all(projectPath);
|
|
165459
|
+
return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
|
|
165460
|
+
}
|
|
165461
|
+
function clearChunkEmbeddingsForProject(db, projectPath, modelId) {
|
|
165462
|
+
if (modelId) {
|
|
165463
|
+
return getClearProjectModelStatement(db).run(projectPath, modelId).changes;
|
|
165464
|
+
}
|
|
165465
|
+
return getClearProjectStatement(db).run(projectPath).changes;
|
|
165466
|
+
}
|
|
165467
|
+
function loadCompartmentChunkEmbeddingsForSearch(db, sessionId, projectPath, modelId) {
|
|
165468
|
+
const rows = modelId ? getSearchRowsStatement(db, true).all(sessionId, projectPath, modelId) : getSearchRowsStatement(db, false).all(sessionId, projectPath);
|
|
165469
|
+
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) => ({
|
|
165470
|
+
compartmentId: row.compartmentId,
|
|
165471
|
+
sessionId: row.sessionId,
|
|
165472
|
+
title: row.title,
|
|
165473
|
+
startOrdinal: row.compartmentStart,
|
|
165474
|
+
endOrdinal: row.compartmentEnd,
|
|
165475
|
+
windowIndex: row.windowIndex,
|
|
165476
|
+
windowStartOrdinal: row.windowStart,
|
|
165477
|
+
windowEndOrdinal: row.windowEnd,
|
|
165478
|
+
chunkHash: row.chunkHash,
|
|
165479
|
+
modelId: row.modelId,
|
|
165480
|
+
dims: row.dims,
|
|
165481
|
+
vector: toFloat32Array2(row.vector)
|
|
165482
|
+
}));
|
|
165483
|
+
}
|
|
165484
|
+
function mapBackfillCandidateRows(rows) {
|
|
165485
|
+
return rows.filter((row) => {
|
|
165486
|
+
if (row === null || typeof row !== "object")
|
|
165487
|
+
return false;
|
|
165488
|
+
const candidate = row;
|
|
165489
|
+
return typeof candidate.id === "number" && typeof candidate.sessionId === "string" && typeof candidate.startMessage === "number" && typeof candidate.endMessage === "number" && typeof candidate.title === "string";
|
|
165490
|
+
}).map((row) => ({
|
|
165491
|
+
id: row.id,
|
|
165492
|
+
sessionId: row.sessionId,
|
|
165493
|
+
startMessage: row.startMessage,
|
|
165494
|
+
endMessage: row.endMessage,
|
|
165495
|
+
title: row.title
|
|
165496
|
+
}));
|
|
165497
|
+
}
|
|
165498
|
+
function loadUnembeddedSessionChunkCandidates(db, projectPath, sessionId, modelId, limit, excludeIds) {
|
|
165499
|
+
if (excludeIds && excludeIds.length > 0) {
|
|
165500
|
+
const placeholders3 = excludeIds.map(() => "?").join(", ");
|
|
165501
|
+
const stmt2 = db.prepare(`SELECT c.id AS id,
|
|
165502
|
+
c.session_id AS sessionId,
|
|
165503
|
+
c.start_message AS startMessage,
|
|
165504
|
+
c.end_message AS endMessage,
|
|
165505
|
+
c.title AS title
|
|
165506
|
+
FROM compartments c
|
|
165507
|
+
JOIN session_projects sp
|
|
165508
|
+
ON sp.session_id = c.session_id
|
|
165509
|
+
AND sp.harness = c.harness
|
|
165510
|
+
AND sp.project_path = ?
|
|
165511
|
+
WHERE c.session_id = ?
|
|
165512
|
+
AND c.start_message IS NOT NULL
|
|
165513
|
+
AND c.end_message IS NOT NULL
|
|
165514
|
+
AND c.id NOT IN (${placeholders3})
|
|
165515
|
+
AND NOT EXISTS (
|
|
165516
|
+
SELECT 1
|
|
165517
|
+
FROM compartment_chunk_embeddings current
|
|
165518
|
+
WHERE current.compartment_id = c.id
|
|
165519
|
+
AND current.project_path = ?
|
|
165520
|
+
AND current.model_id = ?
|
|
165521
|
+
)
|
|
165522
|
+
ORDER BY c.start_message ASC, c.id ASC
|
|
165523
|
+
LIMIT ?`);
|
|
165524
|
+
const rows2 = stmt2.all(projectPath, sessionId, ...excludeIds, projectPath, modelId, Math.max(1, limit));
|
|
165525
|
+
return mapBackfillCandidateRows(rows2);
|
|
165526
|
+
}
|
|
165527
|
+
let stmt = sessionBackfillCandidateStatements.get(db);
|
|
165528
|
+
if (!stmt) {
|
|
165529
|
+
stmt = db.prepare(`SELECT c.id AS id,
|
|
165530
|
+
c.session_id AS sessionId,
|
|
165531
|
+
c.start_message AS startMessage,
|
|
165532
|
+
c.end_message AS endMessage,
|
|
165533
|
+
c.title AS title
|
|
165534
|
+
FROM compartments c
|
|
165535
|
+
JOIN session_projects sp
|
|
165536
|
+
ON sp.session_id = c.session_id
|
|
165537
|
+
AND sp.harness = c.harness
|
|
165538
|
+
AND sp.project_path = ?
|
|
165539
|
+
WHERE c.session_id = ?
|
|
165540
|
+
AND c.start_message IS NOT NULL
|
|
165541
|
+
AND c.end_message IS NOT NULL
|
|
165542
|
+
AND NOT EXISTS (
|
|
165543
|
+
SELECT 1
|
|
165544
|
+
FROM compartment_chunk_embeddings current
|
|
165545
|
+
WHERE current.compartment_id = c.id
|
|
165546
|
+
AND current.project_path = ?
|
|
165547
|
+
AND current.model_id = ?
|
|
165548
|
+
)
|
|
165549
|
+
ORDER BY c.start_message ASC, c.id ASC
|
|
165550
|
+
LIMIT ?`);
|
|
165551
|
+
sessionBackfillCandidateStatements.set(db, stmt);
|
|
165552
|
+
}
|
|
165553
|
+
const rows = stmt.all(projectPath, sessionId, projectPath, modelId, Math.max(1, limit));
|
|
165554
|
+
return mapBackfillCandidateRows(rows);
|
|
165555
|
+
}
|
|
165556
|
+
function countUnembeddedSessionCompartments(db, projectPath, sessionId, modelId) {
|
|
165557
|
+
const row = db.prepare(`SELECT COUNT(*) AS n
|
|
165558
|
+
FROM compartments c
|
|
165559
|
+
JOIN session_projects sp
|
|
165560
|
+
ON sp.session_id = c.session_id
|
|
165561
|
+
AND sp.harness = c.harness
|
|
165562
|
+
AND sp.project_path = ?
|
|
165563
|
+
WHERE c.session_id = ?
|
|
165564
|
+
AND c.start_message IS NOT NULL
|
|
165565
|
+
AND c.end_message IS NOT NULL
|
|
165566
|
+
AND NOT EXISTS (
|
|
165567
|
+
SELECT 1
|
|
165568
|
+
FROM compartment_chunk_embeddings current
|
|
165569
|
+
WHERE current.compartment_id = c.id
|
|
165570
|
+
AND current.project_path = ?
|
|
165571
|
+
AND current.model_id = ?
|
|
165572
|
+
)`).get(projectPath, sessionId, projectPath, modelId);
|
|
165573
|
+
return typeof row?.n === "number" ? row.n : 0;
|
|
165574
|
+
}
|
|
165575
|
+
var DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS = 512, CHUNK_WINDOW_SAFETY_RATIO = 0.9, loadFtsRowsStatements, existingHashStatements, existingHashByProjectStatements, deleteByCompartmentStatements, insertEmbeddingStatements, distinctModelStatements, clearProjectStatements, clearProjectModelStatements, searchRowsStatements, searchRowsByModelStatements, backfillCandidateStatements, sessionBackfillCandidateStatements;
|
|
165576
|
+
var init_compartment_chunk_embedding = __esm(() => {
|
|
165577
|
+
init_read_session_formatting();
|
|
165578
|
+
loadFtsRowsStatements = new WeakMap;
|
|
165579
|
+
existingHashStatements = new WeakMap;
|
|
165580
|
+
existingHashByProjectStatements = new WeakMap;
|
|
165581
|
+
deleteByCompartmentStatements = new WeakMap;
|
|
165582
|
+
insertEmbeddingStatements = new WeakMap;
|
|
165583
|
+
distinctModelStatements = new WeakMap;
|
|
165584
|
+
clearProjectStatements = new WeakMap;
|
|
165585
|
+
clearProjectModelStatements = new WeakMap;
|
|
165586
|
+
searchRowsStatements = new WeakMap;
|
|
165587
|
+
searchRowsByModelStatements = new WeakMap;
|
|
165588
|
+
backfillCandidateStatements = new WeakMap;
|
|
165589
|
+
sessionBackfillCandidateStatements = new WeakMap;
|
|
165590
|
+
});
|
|
165591
|
+
|
|
164465
165592
|
// src/features/magic-context/memory/cosine-similarity.ts
|
|
164466
165593
|
function cosineSimilarity(a, b) {
|
|
164467
165594
|
if (a.length !== b.length) {
|
|
@@ -164619,19 +165746,19 @@ function isArrayLikeNumber(value) {
|
|
|
164619
165746
|
}
|
|
164620
165747
|
return arr.length === 0 || typeof arr[0] === "number";
|
|
164621
165748
|
}
|
|
164622
|
-
function
|
|
165749
|
+
function toFloat32Array3(values) {
|
|
164623
165750
|
return values instanceof Float32Array ? new Float32Array(values) : Float32Array.from(Array.from(values));
|
|
164624
165751
|
}
|
|
164625
165752
|
function extractBatchEmbeddings(result, expectedCount) {
|
|
164626
165753
|
const { data } = result;
|
|
164627
165754
|
if (Array.isArray(data) && data.length === expectedCount && data.every((entry) => typeof entry !== "number" && isArrayLikeNumber(entry))) {
|
|
164628
|
-
return data.map((entry) =>
|
|
165755
|
+
return data.map((entry) => toFloat32Array3(entry));
|
|
164629
165756
|
}
|
|
164630
165757
|
if (!isArrayLikeNumber(data)) {
|
|
164631
165758
|
log("[magic-context] embedding batch returned unexpected data shape");
|
|
164632
165759
|
return Array.from({ length: expectedCount }, () => null);
|
|
164633
165760
|
}
|
|
164634
|
-
const flatData =
|
|
165761
|
+
const flatData = toFloat32Array3(data);
|
|
164635
165762
|
const dimension = result.dims?.at(-1) ?? flatData.length / expectedCount;
|
|
164636
165763
|
if (!Number.isInteger(dimension) || dimension <= 0 || flatData.length !== expectedCount * dimension) {
|
|
164637
165764
|
log("[magic-context] embedding batch returned invalid dimensions");
|
|
@@ -164646,6 +165773,7 @@ function extractBatchEmbeddings(result, expectedCount) {
|
|
|
164646
165773
|
|
|
164647
165774
|
class LocalEmbeddingProvider {
|
|
164648
165775
|
modelId;
|
|
165776
|
+
maxInputTokens;
|
|
164649
165777
|
model;
|
|
164650
165778
|
pipeline = null;
|
|
164651
165779
|
initPromise = null;
|
|
@@ -164653,8 +165781,9 @@ class LocalEmbeddingProvider {
|
|
|
164653
165781
|
disposing = false;
|
|
164654
165782
|
disposePromise = null;
|
|
164655
165783
|
inFlightWaiters = [];
|
|
164656
|
-
constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL) {
|
|
165784
|
+
constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512) {
|
|
164657
165785
|
this.model = model;
|
|
165786
|
+
this.maxInputTokens = maxInputTokens;
|
|
164658
165787
|
this.modelId = getEmbeddingProviderIdentity({ provider: "local", model });
|
|
164659
165788
|
}
|
|
164660
165789
|
async initialize() {
|
|
@@ -164911,9 +166040,17 @@ var init_embedding_ssrf = __esm(() => {
|
|
|
164911
166040
|
function normalizeEndpoint3(endpoint) {
|
|
164912
166041
|
return endpoint?.trim().replace(/\/+$/, "") ?? "";
|
|
164913
166042
|
}
|
|
166043
|
+
function embeddingModelsMatch(served, requested) {
|
|
166044
|
+
const a = served.trim().toLowerCase();
|
|
166045
|
+
const b = requested.trim().toLowerCase();
|
|
166046
|
+
if (a.length === 0 || b.length === 0)
|
|
166047
|
+
return true;
|
|
166048
|
+
return a === b || a.includes(b) || b.includes(a);
|
|
166049
|
+
}
|
|
164914
166050
|
|
|
164915
166051
|
class OpenAICompatibleEmbeddingProvider {
|
|
164916
166052
|
modelId;
|
|
166053
|
+
maxInputTokens;
|
|
164917
166054
|
endpoint;
|
|
164918
166055
|
model;
|
|
164919
166056
|
apiKey;
|
|
@@ -164923,6 +166060,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
164923
166060
|
failureTimes = [];
|
|
164924
166061
|
circuitOpenUntil = 0;
|
|
164925
166062
|
openLogged = false;
|
|
166063
|
+
modelMismatchLogged = false;
|
|
164926
166064
|
halfOpenProbeInFlight = false;
|
|
164927
166065
|
constructor(options) {
|
|
164928
166066
|
this.endpoint = normalizeEndpoint3(options.endpoint);
|
|
@@ -164930,11 +166068,13 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
164930
166068
|
this.apiKey = options.apiKey?.trim() ?? "";
|
|
164931
166069
|
this.inputType = options.inputType?.trim() ?? "";
|
|
164932
166070
|
this.truncate = options.truncate?.trim() ?? "";
|
|
166071
|
+
this.maxInputTokens = typeof options.maxInputTokens === "number" && Number.isFinite(options.maxInputTokens) ? Math.max(1, Math.floor(options.maxInputTokens)) : 512;
|
|
164933
166072
|
this.modelId = getEmbeddingProviderIdentity({
|
|
164934
166073
|
provider: "openai-compatible",
|
|
164935
166074
|
endpoint: this.endpoint,
|
|
164936
166075
|
model: this.model,
|
|
164937
|
-
...this.apiKey ? { api_key: this.apiKey } : {}
|
|
166076
|
+
...this.apiKey ? { api_key: this.apiKey } : {},
|
|
166077
|
+
...this.inputType ? { input_type: this.inputType } : {}
|
|
164938
166078
|
});
|
|
164939
166079
|
}
|
|
164940
166080
|
async initialize() {
|
|
@@ -165019,6 +166159,15 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
165019
166159
|
this.recordFailure(isProbe);
|
|
165020
166160
|
return Array.from({ length: texts.length }, () => null);
|
|
165021
166161
|
}
|
|
166162
|
+
const servedModel = typeof body.model === "string" ? body.model : "";
|
|
166163
|
+
if (this.model && servedModel && !embeddingModelsMatch(servedModel, this.model)) {
|
|
166164
|
+
if (!this.modelMismatchLogged) {
|
|
166165
|
+
log(`[magic-context] embedding endpoint served a DIFFERENT model than requested — refusing the substituted vectors (they have the wrong dimensions/space). requested="${this.model}" served="${servedModel}". The endpoint likely substituted a loaded model; load/select "${this.model}" on the endpoint, or set embedding.model to the served model.`);
|
|
166166
|
+
this.modelMismatchLogged = true;
|
|
166167
|
+
}
|
|
166168
|
+
this.recordFailure(isProbe);
|
|
166169
|
+
return Array.from({ length: texts.length }, () => null);
|
|
166170
|
+
}
|
|
165022
166171
|
const items = Array.isArray(body.data) ? body.data : [];
|
|
165023
166172
|
const results = Array.from({ length: texts.length }, (_, index) => {
|
|
165024
166173
|
const embedding = items[index]?.embedding;
|
|
@@ -165178,12 +166327,12 @@ function getCountEmbeddedStatement(db) {
|
|
|
165178
166327
|
}
|
|
165179
166328
|
return stmt;
|
|
165180
166329
|
}
|
|
165181
|
-
function
|
|
165182
|
-
let stmt =
|
|
166330
|
+
function getClearProjectStatement2(db) {
|
|
166331
|
+
let stmt = clearProjectStatements2.get(db);
|
|
165183
166332
|
if (!stmt) {
|
|
165184
166333
|
stmt = db.prepare(`DELETE FROM git_commit_embeddings
|
|
165185
166334
|
WHERE sha IN (SELECT sha FROM git_commits WHERE project_path = ?)`);
|
|
165186
|
-
|
|
166335
|
+
clearProjectStatements2.set(db, stmt);
|
|
165187
166336
|
}
|
|
165188
166337
|
return stmt;
|
|
165189
166338
|
}
|
|
@@ -165219,19 +166368,19 @@ function countEmbeddedCommits(db, projectPath) {
|
|
|
165219
166368
|
return row?.count ?? 0;
|
|
165220
166369
|
}
|
|
165221
166370
|
function clearProjectCommitEmbeddings(db, projectPath) {
|
|
165222
|
-
return
|
|
166371
|
+
return getClearProjectStatement2(db).run(projectPath).changes;
|
|
165223
166372
|
}
|
|
165224
166373
|
function getDistinctCommitEmbeddingModelIds(db, projectPath) {
|
|
165225
166374
|
const rows = getDistinctModelIdStatement(db).all(projectPath);
|
|
165226
166375
|
return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
|
|
165227
166376
|
}
|
|
165228
|
-
var saveStatements, loadProjectStatements, loadUnembeddedStatements, countEmbeddedStatements,
|
|
166377
|
+
var saveStatements, loadProjectStatements, loadUnembeddedStatements, countEmbeddedStatements, clearProjectStatements2, distinctModelIdStatements;
|
|
165229
166378
|
var init_storage_git_commit_embeddings = __esm(() => {
|
|
165230
166379
|
saveStatements = new WeakMap;
|
|
165231
166380
|
loadProjectStatements = new WeakMap;
|
|
165232
166381
|
loadUnembeddedStatements = new WeakMap;
|
|
165233
166382
|
countEmbeddedStatements = new WeakMap;
|
|
165234
|
-
|
|
166383
|
+
clearProjectStatements2 = new WeakMap;
|
|
165235
166384
|
distinctModelIdStatements = new WeakMap;
|
|
165236
166385
|
});
|
|
165237
166386
|
|
|
@@ -165357,13 +166506,90 @@ var init_sweep_coordinator = __esm(() => {
|
|
|
165357
166506
|
GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
|
|
165358
166507
|
});
|
|
165359
166508
|
|
|
166509
|
+
// src/features/magic-context/session-project-storage.ts
|
|
166510
|
+
function getUpsertSessionProjectStatement(db) {
|
|
166511
|
+
let stmt = upsertSessionProjectStatements.get(db);
|
|
166512
|
+
if (!stmt) {
|
|
166513
|
+
stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
|
|
166514
|
+
VALUES (?, ?, ?, ?)
|
|
166515
|
+
ON CONFLICT(session_id, harness) DO UPDATE SET
|
|
166516
|
+
project_path = excluded.project_path,
|
|
166517
|
+
updated_at = excluded.updated_at
|
|
166518
|
+
WHERE session_projects.project_path <> excluded.project_path`);
|
|
166519
|
+
upsertSessionProjectStatements.set(db, stmt);
|
|
166520
|
+
}
|
|
166521
|
+
return stmt;
|
|
166522
|
+
}
|
|
166523
|
+
function getRepairSessionChunkProjectStatement(db) {
|
|
166524
|
+
let stmt = repairSessionChunkProjectStatements.get(db);
|
|
166525
|
+
if (!stmt) {
|
|
166526
|
+
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
166527
|
+
SET project_path = ?
|
|
166528
|
+
WHERE session_id = ?
|
|
166529
|
+
AND harness = ?
|
|
166530
|
+
AND project_path <> ?`);
|
|
166531
|
+
repairSessionChunkProjectStatements.set(db, stmt);
|
|
166532
|
+
}
|
|
166533
|
+
return stmt;
|
|
166534
|
+
}
|
|
166535
|
+
function getRepairProjectChunkProjectStatement(db) {
|
|
166536
|
+
let stmt = repairProjectChunkProjectStatements.get(db);
|
|
166537
|
+
if (!stmt) {
|
|
166538
|
+
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
166539
|
+
SET project_path = (
|
|
166540
|
+
SELECT sp.project_path
|
|
166541
|
+
FROM session_projects sp
|
|
166542
|
+
WHERE sp.session_id = compartment_chunk_embeddings.session_id
|
|
166543
|
+
AND sp.harness = compartment_chunk_embeddings.harness
|
|
166544
|
+
LIMIT 1
|
|
166545
|
+
)
|
|
166546
|
+
WHERE EXISTS (
|
|
166547
|
+
SELECT 1
|
|
166548
|
+
FROM session_projects sp
|
|
166549
|
+
WHERE sp.session_id = compartment_chunk_embeddings.session_id
|
|
166550
|
+
AND sp.harness = compartment_chunk_embeddings.harness
|
|
166551
|
+
AND sp.project_path <> compartment_chunk_embeddings.project_path
|
|
166552
|
+
AND (
|
|
166553
|
+
sp.project_path = ?
|
|
166554
|
+
OR compartment_chunk_embeddings.project_path = ?
|
|
166555
|
+
)
|
|
166556
|
+
)`);
|
|
166557
|
+
repairProjectChunkProjectStatements.set(db, stmt);
|
|
166558
|
+
}
|
|
166559
|
+
return stmt;
|
|
166560
|
+
}
|
|
166561
|
+
function recordSessionProjectIdentity(db, sessionId, projectPath) {
|
|
166562
|
+
if (!sessionId || !projectPath)
|
|
166563
|
+
return;
|
|
166564
|
+
const harness = getHarness();
|
|
166565
|
+
const now = Date.now();
|
|
166566
|
+
db.transaction(() => {
|
|
166567
|
+
getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
|
|
166568
|
+
getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
|
|
166569
|
+
})();
|
|
166570
|
+
}
|
|
166571
|
+
function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
|
|
166572
|
+
if (!projectPath)
|
|
166573
|
+
return 0;
|
|
166574
|
+
return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
|
|
166575
|
+
}
|
|
166576
|
+
var upsertSessionProjectStatements, repairSessionChunkProjectStatements, repairProjectChunkProjectStatements;
|
|
166577
|
+
var init_session_project_storage = __esm(() => {
|
|
166578
|
+
upsertSessionProjectStatements = new WeakMap;
|
|
166579
|
+
repairSessionChunkProjectStatements = new WeakMap;
|
|
166580
|
+
repairProjectChunkProjectStatements = new WeakMap;
|
|
166581
|
+
});
|
|
166582
|
+
|
|
165360
166583
|
// src/features/magic-context/project-embedding-registry.ts
|
|
165361
|
-
import { createHash as
|
|
166584
|
+
import { createHash as createHash9, randomUUID } from "node:crypto";
|
|
165362
166585
|
function resolveEmbeddingConfig(config2) {
|
|
165363
166586
|
if (!config2 || config2.provider === "local") {
|
|
165364
166587
|
return {
|
|
165365
166588
|
provider: "local",
|
|
165366
|
-
model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
166589
|
+
model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
166590
|
+
...config2?.max_input_tokens ? {
|
|
166591
|
+
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
166592
|
+
} : {}
|
|
165367
166593
|
};
|
|
165368
166594
|
}
|
|
165369
166595
|
if (config2.provider === "openai-compatible") {
|
|
@@ -165376,7 +166602,10 @@ function resolveEmbeddingConfig(config2) {
|
|
|
165376
166602
|
endpoint: config2.endpoint.trim(),
|
|
165377
166603
|
...apiKey ? { api_key: apiKey } : {},
|
|
165378
166604
|
...inputType ? { input_type: inputType } : {},
|
|
165379
|
-
...truncate ? { truncate } : {}
|
|
166605
|
+
...truncate ? { truncate } : {},
|
|
166606
|
+
...config2.max_input_tokens ? {
|
|
166607
|
+
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
166608
|
+
} : {}
|
|
165380
166609
|
};
|
|
165381
166610
|
}
|
|
165382
166611
|
return { provider: "off" };
|
|
@@ -165394,10 +166623,11 @@ function createProvider(config2) {
|
|
|
165394
166623
|
model: config2.model,
|
|
165395
166624
|
apiKey: config2.api_key,
|
|
165396
166625
|
inputType: config2.input_type,
|
|
165397
|
-
truncate: config2.truncate
|
|
166626
|
+
truncate: config2.truncate,
|
|
166627
|
+
maxInputTokens: config2.max_input_tokens
|
|
165398
166628
|
});
|
|
165399
166629
|
}
|
|
165400
|
-
return new LocalEmbeddingProvider(config2.model);
|
|
166630
|
+
return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
|
|
165401
166631
|
}
|
|
165402
166632
|
function stableStringify2(value) {
|
|
165403
166633
|
if (Array.isArray(value)) {
|
|
@@ -165410,7 +166640,7 @@ function stableStringify2(value) {
|
|
|
165410
166640
|
return JSON.stringify(value);
|
|
165411
166641
|
}
|
|
165412
166642
|
function sha256Prefix(value, length = 16) {
|
|
165413
|
-
return
|
|
166643
|
+
return createHash9("sha256").update(value).digest("hex").slice(0, length);
|
|
165414
166644
|
}
|
|
165415
166645
|
function getRuntimeFingerprint(config2) {
|
|
165416
166646
|
if (config2.provider === "off") {
|
|
@@ -165418,6 +166648,18 @@ function getRuntimeFingerprint(config2) {
|
|
|
165418
166648
|
}
|
|
165419
166649
|
return `${getEmbeddingProviderIdentity(config2)}:${sha256Prefix(stableStringify2(config2))}`;
|
|
165420
166650
|
}
|
|
166651
|
+
function getChunkEmbeddingModelId(config2, providerIdentity) {
|
|
166652
|
+
if (config2.provider === "off") {
|
|
166653
|
+
return OFF_PROVIDER_IDENTITY;
|
|
166654
|
+
}
|
|
166655
|
+
const chunkIdentity = {
|
|
166656
|
+
providerIdentity,
|
|
166657
|
+
chunkerVersion: 2,
|
|
166658
|
+
maxInputTokens: normalizeCompartmentChunkMaxInputTokens("max_input_tokens" in config2 ? config2.max_input_tokens : undefined),
|
|
166659
|
+
truncate: config2.provider === "openai-compatible" ? config2.truncate ?? "" : ""
|
|
166660
|
+
};
|
|
166661
|
+
return `${providerIdentity}:chunk:${sha256Prefix(stableStringify2(chunkIdentity))}`;
|
|
166662
|
+
}
|
|
165421
166663
|
function sameFeatures(a, b) {
|
|
165422
166664
|
return a.memoryEnabled === b.memoryEnabled && a.gitCommitEnabled === b.gitCommitEnabled;
|
|
165423
166665
|
}
|
|
@@ -165434,7 +166676,8 @@ function snapshotFor(registration) {
|
|
|
165434
166676
|
features: { ...registration.features },
|
|
165435
166677
|
enabled,
|
|
165436
166678
|
gitCommitEnabled,
|
|
165437
|
-
modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId
|
|
166679
|
+
modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
|
|
166680
|
+
chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId
|
|
165438
166681
|
};
|
|
165439
166682
|
}
|
|
165440
166683
|
function disposeProvider(provider) {
|
|
@@ -165454,7 +166697,7 @@ function anyStoredModelIdIsStale(storedIds, currentId) {
|
|
|
165454
166697
|
}
|
|
165455
166698
|
return false;
|
|
165456
166699
|
}
|
|
165457
|
-
function maybeWipeStaleEmbeddings(db, projectIdentity, currentProviderIdentity, features) {
|
|
166700
|
+
function maybeWipeStaleEmbeddings(db, projectIdentity, currentProviderIdentity, currentChunkIdentity, features) {
|
|
165458
166701
|
if (currentProviderIdentity === OFF_PROVIDER_IDENTITY) {
|
|
165459
166702
|
return false;
|
|
165460
166703
|
}
|
|
@@ -165475,6 +166718,14 @@ function maybeWipeStaleEmbeddings(db, projectIdentity, currentProviderIdentity,
|
|
|
165475
166718
|
wiped = true;
|
|
165476
166719
|
}
|
|
165477
166720
|
}
|
|
166721
|
+
if (features.memoryEnabled) {
|
|
166722
|
+
repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectIdentity);
|
|
166723
|
+
const chunkIds = getDistinctChunkEmbeddingModelIds(db, projectIdentity);
|
|
166724
|
+
if (anyStoredModelIdIsStale(chunkIds, currentChunkIdentity)) {
|
|
166725
|
+
clearChunkEmbeddingsForProject(db, projectIdentity);
|
|
166726
|
+
wiped = true;
|
|
166727
|
+
}
|
|
166728
|
+
}
|
|
165478
166729
|
})();
|
|
165479
166730
|
return wiped;
|
|
165480
166731
|
}
|
|
@@ -165482,10 +166733,11 @@ function registerProjectEmbeddingAndMaybeWipe(db, projectIdentity, config2, feat
|
|
|
165482
166733
|
const resolvedConfig = resolveEmbeddingConfig(config2);
|
|
165483
166734
|
const providerIdentity = getEmbeddingProviderIdentity(resolvedConfig);
|
|
165484
166735
|
const runtimeFingerprint = getRuntimeFingerprint(resolvedConfig);
|
|
166736
|
+
const chunkModelId = getChunkEmbeddingModelId(resolvedConfig, providerIdentity);
|
|
165485
166737
|
const prior = projectRegistrations.get(projectIdentity);
|
|
165486
166738
|
const canReuseProvider = prior !== undefined && !prior.observationMode && prior.runtimeFingerprint === runtimeFingerprint && prior.providerIdentity === providerIdentity;
|
|
165487
|
-
const wiped = maybeWipeStaleEmbeddings(db, projectIdentity, providerIdentity, features);
|
|
165488
|
-
const generationChanged = prior === undefined || prior.observationMode || prior.runtimeFingerprint !== runtimeFingerprint || !sameFeatures(prior.features, features) || wiped;
|
|
166739
|
+
const wiped = maybeWipeStaleEmbeddings(db, projectIdentity, providerIdentity, chunkModelId, features);
|
|
166740
|
+
const generationChanged = prior === undefined || prior.observationMode || prior.runtimeFingerprint !== runtimeFingerprint || prior.chunkModelId !== chunkModelId || !sameFeatures(prior.features, features) || wiped;
|
|
165489
166741
|
const generation = generationChanged ? ++globalRegistrationGeneration : prior.generation;
|
|
165490
166742
|
const registration = {
|
|
165491
166743
|
projectIdentity,
|
|
@@ -165497,6 +166749,7 @@ function registerProjectEmbeddingAndMaybeWipe(db, projectIdentity, config2, feat
|
|
|
165497
166749
|
generation,
|
|
165498
166750
|
features: { ...features },
|
|
165499
166751
|
modelId: providerIdentity === OFF_PROVIDER_IDENTITY ? "off" : providerIdentity,
|
|
166752
|
+
chunkModelId: providerIdentity === OFF_PROVIDER_IDENTITY ? "off" : chunkModelId,
|
|
165500
166753
|
observationMode: false
|
|
165501
166754
|
};
|
|
165502
166755
|
projectRegistrations.set(projectIdentity, registration);
|
|
@@ -165519,6 +166772,7 @@ function registerProjectInObservationMode(db, projectIdentity, sourceDirectory,
|
|
|
165519
166772
|
generation,
|
|
165520
166773
|
features: { memoryEnabled: false, gitCommitEnabled: false },
|
|
165521
166774
|
modelId: "off",
|
|
166775
|
+
chunkModelId: "off",
|
|
165522
166776
|
observationMode: true
|
|
165523
166777
|
};
|
|
165524
166778
|
projectRegistrations.set(projectIdentity, registration);
|
|
@@ -165529,6 +166783,15 @@ function getProjectEmbeddingSnapshot(projectIdentity) {
|
|
|
165529
166783
|
const registration = projectRegistrations.get(projectIdentity);
|
|
165530
166784
|
return registration ? snapshotFor(registration) : null;
|
|
165531
166785
|
}
|
|
166786
|
+
function getProjectChunkEmbeddingModelId(projectIdentity) {
|
|
166787
|
+
const registration = projectRegistrations.get(projectIdentity);
|
|
166788
|
+
return registration && !registration.observationMode ? registration.chunkModelId : "off";
|
|
166789
|
+
}
|
|
166790
|
+
function getProjectEmbeddingMaxInputTokens(projectIdentity) {
|
|
166791
|
+
const registration = projectRegistrations.get(projectIdentity);
|
|
166792
|
+
const configMax = registration?.config && "max_input_tokens" in registration.config ? registration.config.max_input_tokens : undefined;
|
|
166793
|
+
return normalizeCompartmentChunkMaxInputTokens(registration?.provider?.maxInputTokens ?? configMax);
|
|
166794
|
+
}
|
|
165532
166795
|
function getOrCreateProjectProvider(registration) {
|
|
165533
166796
|
if (registration.providerIdentity === OFF_PROVIDER_IDENTITY || registration.observationMode) {
|
|
165534
166797
|
return null;
|
|
@@ -165623,10 +166886,136 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
|
|
|
165623
166886
|
return 0;
|
|
165624
166887
|
}
|
|
165625
166888
|
}
|
|
165626
|
-
|
|
166889
|
+
async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates, signal) {
|
|
166890
|
+
const noWork = [];
|
|
166891
|
+
if (candidates.length === 0)
|
|
166892
|
+
return { embedded: 0, noWork };
|
|
166893
|
+
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
|
|
166894
|
+
const prepared = [];
|
|
166895
|
+
for (const candidate of candidates) {
|
|
166896
|
+
const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage);
|
|
166897
|
+
if (canonicalText.length === 0) {
|
|
166898
|
+
noWork.push(candidate.id);
|
|
166899
|
+
continue;
|
|
166900
|
+
}
|
|
166901
|
+
const windows = chunkCanonicalText(canonicalText, candidate.startMessage, candidate.endMessage, maxInputTokens);
|
|
166902
|
+
if (windows.length === 0 || chunkEmbeddingWindowsAreCurrent(db, candidate.id, modelId, windows, projectIdentity)) {
|
|
166903
|
+
noWork.push(candidate.id);
|
|
166904
|
+
continue;
|
|
166905
|
+
}
|
|
166906
|
+
prepared.push({ candidate, windows });
|
|
166907
|
+
}
|
|
166908
|
+
if (prepared.length === 0)
|
|
166909
|
+
return { embedded: 0, noWork };
|
|
166910
|
+
let embedded = 0;
|
|
166911
|
+
let i = 0;
|
|
166912
|
+
while (i < prepared.length) {
|
|
166913
|
+
if (signal?.aborted)
|
|
166914
|
+
break;
|
|
166915
|
+
const slice = [];
|
|
166916
|
+
let windowCount = 0;
|
|
166917
|
+
do {
|
|
166918
|
+
const item = prepared[i];
|
|
166919
|
+
slice.push(item);
|
|
166920
|
+
windowCount += item.windows.length;
|
|
166921
|
+
i += 1;
|
|
166922
|
+
} while (i < prepared.length && windowCount + prepared[i].windows.length <= MAX_WINDOWS_PER_EMBED_CALL);
|
|
166923
|
+
const texts = [];
|
|
166924
|
+
for (const item of slice)
|
|
166925
|
+
texts.push(...item.windows.map((w) => w.text));
|
|
166926
|
+
try {
|
|
166927
|
+
const result = await embedBatchForProject(projectIdentity, texts, signal);
|
|
166928
|
+
if (!result)
|
|
166929
|
+
continue;
|
|
166930
|
+
if (signal?.aborted)
|
|
166931
|
+
break;
|
|
166932
|
+
let offset = 0;
|
|
166933
|
+
for (const item of slice) {
|
|
166934
|
+
const vectors = result.vectors.slice(offset, offset + item.windows.length);
|
|
166935
|
+
offset += item.windows.length;
|
|
166936
|
+
if (vectors.length !== item.windows.length || vectors.some((v) => !v)) {
|
|
166937
|
+
continue;
|
|
166938
|
+
}
|
|
166939
|
+
const rows = item.windows.map((window, index) => ({
|
|
166940
|
+
compartmentId: item.candidate.id,
|
|
166941
|
+
sessionId: item.candidate.sessionId,
|
|
166942
|
+
projectPath: projectIdentity,
|
|
166943
|
+
window,
|
|
166944
|
+
modelId,
|
|
166945
|
+
vector: vectors[index]
|
|
166946
|
+
}));
|
|
166947
|
+
replaceCompartmentChunkEmbeddings(db, rows);
|
|
166948
|
+
embedded += 1;
|
|
166949
|
+
}
|
|
166950
|
+
} catch (error51) {
|
|
166951
|
+
log("[magic-context] failed to proactively embed compartment chunks:", error51);
|
|
166952
|
+
}
|
|
166953
|
+
}
|
|
166954
|
+
return { embedded, noWork };
|
|
166955
|
+
}
|
|
166956
|
+
async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, options) {
|
|
166957
|
+
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
166958
|
+
if (!snapshot?.enabled || snapshot.chunkModelId === "off") {
|
|
166959
|
+
return { status: "disabled", embedded: 0, total: 0 };
|
|
166960
|
+
}
|
|
166961
|
+
recordSessionProjectIdentity(db, sessionId, projectIdentity);
|
|
166962
|
+
const total = countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot.chunkModelId);
|
|
166963
|
+
if (total === 0)
|
|
166964
|
+
return { status: "nothing", embedded: 0, total: 0 };
|
|
166965
|
+
const holderId = `session-embed-${randomUUID()}`;
|
|
166966
|
+
const lease2 = acquireGitSweepLease(db, projectIdentity, holderId, { ignoreCooldown: true });
|
|
166967
|
+
if (!lease2.acquired)
|
|
166968
|
+
return { status: "busy", embedded: 0, total };
|
|
166969
|
+
const renewal = setInterval(() => {
|
|
166970
|
+
try {
|
|
166971
|
+
renewGitSweepLease(db, projectIdentity, holderId);
|
|
166972
|
+
} catch {}
|
|
166973
|
+
}, SESSION_EMBED_LEASE_RENEWAL_MS);
|
|
166974
|
+
renewal.unref?.();
|
|
166975
|
+
const batchSize = Math.max(1, options?.batchSize ?? CHUNK_DRAIN_BATCH_SIZE);
|
|
166976
|
+
const skipIds = [];
|
|
166977
|
+
let embedded = 0;
|
|
166978
|
+
let aborted2 = false;
|
|
166979
|
+
let providerStalled = false;
|
|
166980
|
+
try {
|
|
166981
|
+
options?.onProgress?.({ embedded, total });
|
|
166982
|
+
for (;; ) {
|
|
166983
|
+
if (options?.signal?.aborted) {
|
|
166984
|
+
aborted2 = true;
|
|
166985
|
+
break;
|
|
166986
|
+
}
|
|
166987
|
+
const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, skipIds);
|
|
166988
|
+
if (candidates.length === 0)
|
|
166989
|
+
break;
|
|
166990
|
+
const { embedded: n, noWork } = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, options?.signal);
|
|
166991
|
+
for (const id of noWork)
|
|
166992
|
+
skipIds.push(id);
|
|
166993
|
+
if (n === 0 && noWork.length === 0) {
|
|
166994
|
+
providerStalled = true;
|
|
166995
|
+
break;
|
|
166996
|
+
}
|
|
166997
|
+
embedded += n;
|
|
166998
|
+
options?.onProgress?.({ embedded: Math.min(embedded, total), total });
|
|
166999
|
+
await new Promise((resolve7) => setTimeout(resolve7, 0));
|
|
167000
|
+
}
|
|
167001
|
+
} finally {
|
|
167002
|
+
clearInterval(renewal);
|
|
167003
|
+
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
167004
|
+
}
|
|
167005
|
+
if (aborted2)
|
|
167006
|
+
return { status: "aborted", embedded, total };
|
|
167007
|
+
if (providerStalled) {
|
|
167008
|
+
const remaining = Math.max(0, countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot.chunkModelId) - skipIds.length);
|
|
167009
|
+
if (remaining > 0)
|
|
167010
|
+
return { status: "stalled", embedded, total, remaining };
|
|
167011
|
+
}
|
|
167012
|
+
return { status: "done", embedded, total };
|
|
167013
|
+
}
|
|
167014
|
+
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;
|
|
165627
167015
|
var init_project_embedding_registry = __esm(() => {
|
|
165628
167016
|
init_magic_context();
|
|
165629
167017
|
init_logger();
|
|
167018
|
+
init_compartment_chunk_embedding();
|
|
165630
167019
|
init_storage_git_commit_embeddings();
|
|
165631
167020
|
init_sweep_coordinator();
|
|
165632
167021
|
init_embedding_cache();
|
|
@@ -165634,7 +167023,9 @@ var init_project_embedding_registry = __esm(() => {
|
|
|
165634
167023
|
init_embedding_local();
|
|
165635
167024
|
init_embedding_openai();
|
|
165636
167025
|
init_storage_memory_embeddings();
|
|
167026
|
+
init_session_project_storage();
|
|
165637
167027
|
SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
|
|
167028
|
+
SESSION_EMBED_LEASE_RENEWAL_MS = 60 * 1000;
|
|
165638
167029
|
projectRegistrations = new Map;
|
|
165639
167030
|
loadUnembeddedMemoriesStatements = new WeakMap;
|
|
165640
167031
|
});
|
|
@@ -165650,10 +167041,11 @@ function createProvider2(config2) {
|
|
|
165650
167041
|
model: config2.model,
|
|
165651
167042
|
apiKey: config2.api_key,
|
|
165652
167043
|
inputType: config2.input_type,
|
|
165653
|
-
truncate: config2.truncate
|
|
167044
|
+
truncate: config2.truncate,
|
|
167045
|
+
maxInputTokens: config2.max_input_tokens
|
|
165654
167046
|
});
|
|
165655
167047
|
}
|
|
165656
|
-
return new LocalEmbeddingProvider(config2.model);
|
|
167048
|
+
return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
|
|
165657
167049
|
}
|
|
165658
167050
|
function getOrCreateProvider() {
|
|
165659
167051
|
if (provider) {
|
|
@@ -165679,6 +167071,7 @@ var DEFAULT_EMBEDDING_CONFIG, embeddingConfig, provider = null, loadUnembeddedMe
|
|
|
165679
167071
|
var init_embedding = __esm(() => {
|
|
165680
167072
|
init_magic_context();
|
|
165681
167073
|
init_logger();
|
|
167074
|
+
init_compartment_chunk_embedding();
|
|
165682
167075
|
init_embedding_identity();
|
|
165683
167076
|
init_embedding_local();
|
|
165684
167077
|
init_embedding_openai();
|
|
@@ -165702,6 +167095,23 @@ function getSearchStatement(db) {
|
|
|
165702
167095
|
}
|
|
165703
167096
|
return stmt;
|
|
165704
167097
|
}
|
|
167098
|
+
function getUnionSearchStatement(db, arity) {
|
|
167099
|
+
let statements = unionSearchStatements.get(arity);
|
|
167100
|
+
if (!statements) {
|
|
167101
|
+
statements = new WeakMap;
|
|
167102
|
+
unionSearchStatements.set(arity, statements);
|
|
167103
|
+
}
|
|
167104
|
+
let stmt = statements.get(db);
|
|
167105
|
+
if (!stmt) {
|
|
167106
|
+
const placeholders3 = Array.from({ length: arity }, () => "?").join(", ");
|
|
167107
|
+
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 ?`);
|
|
167108
|
+
statements.set(db, stmt);
|
|
167109
|
+
}
|
|
167110
|
+
return stmt;
|
|
167111
|
+
}
|
|
167112
|
+
function uniqueProjectPaths2(projectPaths) {
|
|
167113
|
+
return [...new Set(projectPaths.filter((path6) => path6.length > 0))];
|
|
167114
|
+
}
|
|
165705
167115
|
function sanitizeFtsQuery(query) {
|
|
165706
167116
|
const tokens = query.split(/\s+/).filter((token) => token.length > 0);
|
|
165707
167117
|
if (tokens.length === 0)
|
|
@@ -165720,10 +167130,33 @@ function searchMemoriesFTS(db, projectPath, query, limit = DEFAULT_SEARCH_LIMIT)
|
|
|
165720
167130
|
const rows = getSearchStatement(db).all(projectPath, Date.now(), sanitized, limit).filter(isMemoryRow);
|
|
165721
167131
|
return rows.map(toMemory);
|
|
165722
167132
|
}
|
|
165723
|
-
|
|
167133
|
+
function searchMemoriesFTSUnion(db, projectPaths, query, limit = DEFAULT_SEARCH_LIMIT, ownIdentities, shareCategories) {
|
|
167134
|
+
const identities = uniqueProjectPaths2(projectPaths);
|
|
167135
|
+
if (identities.length === 0)
|
|
167136
|
+
return [];
|
|
167137
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter({
|
|
167138
|
+
identities,
|
|
167139
|
+
ownIdentities,
|
|
167140
|
+
shareCategories,
|
|
167141
|
+
tableName: "memories"
|
|
167142
|
+
});
|
|
167143
|
+
if (identities.length === 1 && !sharingFilter.active) {
|
|
167144
|
+
return searchMemoriesFTS(db, identities[0], query, limit);
|
|
167145
|
+
}
|
|
167146
|
+
const trimmedQuery = query.trim();
|
|
167147
|
+
if (trimmedQuery.length === 0 || limit <= 0)
|
|
167148
|
+
return [];
|
|
167149
|
+
const sanitized = sanitizeFtsQuery(trimmedQuery);
|
|
167150
|
+
if (sanitized.length === 0)
|
|
167151
|
+
return [];
|
|
167152
|
+
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);
|
|
167153
|
+
return rows.map(toMemory);
|
|
167154
|
+
}
|
|
167155
|
+
var DEFAULT_SEARCH_LIMIT = 10, searchStatements, unionSearchStatements;
|
|
165724
167156
|
var init_storage_memory_fts = __esm(() => {
|
|
165725
167157
|
init_storage_memory();
|
|
165726
167158
|
searchStatements = new WeakMap;
|
|
167159
|
+
unionSearchStatements = new Map;
|
|
165727
167160
|
});
|
|
165728
167161
|
|
|
165729
167162
|
// src/shared/models-dev-cache.ts
|
|
@@ -165917,26 +167350,54 @@ var init_rpc_notifications = __esm(() => {
|
|
|
165917
167350
|
});
|
|
165918
167351
|
|
|
165919
167352
|
// src/features/magic-context/compartment-embedding.ts
|
|
165920
|
-
async function
|
|
167353
|
+
async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compartments) {
|
|
165921
167354
|
if (compartments.length === 0)
|
|
165922
167355
|
return;
|
|
165923
|
-
const
|
|
165924
|
-
for (const
|
|
165925
|
-
if (!c.p1 || c.p1.length === 0)
|
|
165926
|
-
continue;
|
|
167356
|
+
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectPath);
|
|
167357
|
+
for (const compartment of compartments) {
|
|
165927
167358
|
try {
|
|
165928
|
-
const
|
|
165929
|
-
|
|
165930
|
-
|
|
165931
|
-
|
|
167359
|
+
const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
|
|
167360
|
+
const canonicalText = fromMemory || buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage);
|
|
167361
|
+
if (canonicalText.length === 0)
|
|
167362
|
+
continue;
|
|
167363
|
+
const windows = chunkCanonicalText(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
|
|
167364
|
+
if (windows.length === 0)
|
|
167365
|
+
continue;
|
|
167366
|
+
const currentModelId = getProjectChunkEmbeddingModelId(projectPath);
|
|
167367
|
+
if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
|
|
167368
|
+
continue;
|
|
167369
|
+
}
|
|
167370
|
+
const result = await embedBatchForProject(projectPath, windows.map((window) => window.text));
|
|
167371
|
+
if (!result)
|
|
167372
|
+
continue;
|
|
167373
|
+
if (chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
|
|
167374
|
+
continue;
|
|
167375
|
+
}
|
|
167376
|
+
const rows = [];
|
|
167377
|
+
for (const [index, window] of windows.entries()) {
|
|
167378
|
+
const vector = result.vectors[index];
|
|
167379
|
+
if (!vector)
|
|
167380
|
+
continue;
|
|
167381
|
+
rows.push({
|
|
167382
|
+
compartmentId: compartment.id,
|
|
167383
|
+
sessionId,
|
|
167384
|
+
projectPath,
|
|
167385
|
+
window,
|
|
167386
|
+
modelId: currentModelId,
|
|
167387
|
+
vector
|
|
167388
|
+
});
|
|
167389
|
+
}
|
|
167390
|
+
if (rows.length === windows.length) {
|
|
167391
|
+
replaceCompartmentChunkEmbeddings(db, rows);
|
|
165932
167392
|
}
|
|
165933
167393
|
} catch (error51) {
|
|
165934
|
-
sessionLog(sessionId, `compartment embedding failed for compartment ${
|
|
167394
|
+
sessionLog(sessionId, `compartment chunk embedding failed for compartment ${compartment.id}:`, error51);
|
|
165935
167395
|
}
|
|
165936
167396
|
}
|
|
165937
167397
|
}
|
|
165938
167398
|
var init_compartment_embedding = __esm(() => {
|
|
165939
167399
|
init_logger();
|
|
167400
|
+
init_compartment_chunk_embedding();
|
|
165940
167401
|
init_project_embedding_registry();
|
|
165941
167402
|
});
|
|
165942
167403
|
|
|
@@ -167050,55 +168511,6 @@ var init_historian_state_file = __esm(() => {
|
|
|
167050
168511
|
init_data_path();
|
|
167051
168512
|
});
|
|
167052
168513
|
|
|
167053
|
-
// src/features/magic-context/memory/constants.ts
|
|
167054
|
-
var V2_MEMORY_CATEGORIES, PROMOTABLE_CATEGORIES, CATEGORY_PRIORITY, MEMORY_CATEGORY_ORDER_UNKNOWN = 99, MEMORY_CATEGORY_ORDER_PRIORITY, MEMORY_CATEGORY_ORDER_SQL, CATEGORY_DEFAULT_TTL;
|
|
167055
|
-
var init_constants = __esm(() => {
|
|
167056
|
-
V2_MEMORY_CATEGORIES = [
|
|
167057
|
-
"PROJECT_RULES",
|
|
167058
|
-
"ARCHITECTURE",
|
|
167059
|
-
"CONSTRAINTS",
|
|
167060
|
-
"CONFIG_VALUES",
|
|
167061
|
-
"NAMING"
|
|
167062
|
-
];
|
|
167063
|
-
PROMOTABLE_CATEGORIES = [
|
|
167064
|
-
"PROJECT_RULES",
|
|
167065
|
-
"ARCHITECTURE",
|
|
167066
|
-
"CONSTRAINTS",
|
|
167067
|
-
"CONFIG_VALUES",
|
|
167068
|
-
"NAMING",
|
|
167069
|
-
"ARCHITECTURE_DECISIONS",
|
|
167070
|
-
"CONFIG_DEFAULTS",
|
|
167071
|
-
"USER_PREFERENCES",
|
|
167072
|
-
"USER_DIRECTIVES",
|
|
167073
|
-
"ENVIRONMENT",
|
|
167074
|
-
"WORKFLOW_RULES",
|
|
167075
|
-
"KNOWN_ISSUES"
|
|
167076
|
-
];
|
|
167077
|
-
CATEGORY_PRIORITY = [
|
|
167078
|
-
"PROJECT_RULES",
|
|
167079
|
-
"ARCHITECTURE",
|
|
167080
|
-
"CONSTRAINTS",
|
|
167081
|
-
"CONFIG_VALUES",
|
|
167082
|
-
"NAMING",
|
|
167083
|
-
"USER_DIRECTIVES",
|
|
167084
|
-
"USER_PREFERENCES",
|
|
167085
|
-
"CONFIG_DEFAULTS",
|
|
167086
|
-
"ARCHITECTURE_DECISIONS",
|
|
167087
|
-
"ENVIRONMENT",
|
|
167088
|
-
"WORKFLOW_RULES",
|
|
167089
|
-
"KNOWN_ISSUES"
|
|
167090
|
-
];
|
|
167091
|
-
MEMORY_CATEGORY_ORDER_PRIORITY = CATEGORY_PRIORITY.reduce((acc, category, index) => {
|
|
167092
|
-
acc[category] = index;
|
|
167093
|
-
return acc;
|
|
167094
|
-
}, {});
|
|
167095
|
-
MEMORY_CATEGORY_ORDER_SQL = `CASE category ${CATEGORY_PRIORITY.map((category, index) => `WHEN '${category}' THEN ${index}`).join(" ")} ELSE ${MEMORY_CATEGORY_ORDER_UNKNOWN} END`;
|
|
167096
|
-
CATEGORY_DEFAULT_TTL = {
|
|
167097
|
-
WORKFLOW_RULES: 90 * 24 * 60 * 60 * 1000,
|
|
167098
|
-
KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
|
|
167099
|
-
};
|
|
167100
|
-
});
|
|
167101
|
-
|
|
167102
168514
|
// src/features/magic-context/memory/embedding-backfill.ts
|
|
167103
168515
|
async function ensureMemoryEmbeddings(args) {
|
|
167104
168516
|
const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
@@ -167122,7 +168534,7 @@ async function ensureMemoryEmbeddings(args) {
|
|
|
167122
168534
|
continue;
|
|
167123
168535
|
}
|
|
167124
168536
|
saveEmbedding(args.db, memory.id, embedding, result.modelId);
|
|
167125
|
-
staged.set(memory.id, embedding);
|
|
168537
|
+
staged.set(memory.id, { embedding, modelId: result.modelId });
|
|
167126
168538
|
}
|
|
167127
168539
|
})();
|
|
167128
168540
|
const currentSnapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
@@ -167881,7 +169293,7 @@ ${prepared.block}
|
|
|
167881
169293
|
if (!firstMessage || !textPart || isDroppedPlaceholder(textPart.text)) {
|
|
167882
169294
|
messages.unshift({
|
|
167883
169295
|
info: { role: "user", sessionID: sessionId },
|
|
167884
|
-
parts: [{ type: "text", text: historyBlock }]
|
|
169296
|
+
parts: [{ type: "text", text: historyBlock, synthetic: true }]
|
|
167885
169297
|
});
|
|
167886
169298
|
} else {
|
|
167887
169299
|
textPart.text = `${historyBlock}
|
|
@@ -167919,6 +169331,71 @@ function lastCompartmentBoundaryId(compartments) {
|
|
|
167919
169331
|
const last = compartments.at(-1);
|
|
167920
169332
|
return last?.endMessageId && last.endMessageId.length > 0 ? last.endMessageId : null;
|
|
167921
169333
|
}
|
|
169334
|
+
function resolveWorkspaceRenderContext(args) {
|
|
169335
|
+
if (!args.projectPath) {
|
|
169336
|
+
return {
|
|
169337
|
+
identities: [],
|
|
169338
|
+
expandedIdentities: [],
|
|
169339
|
+
ownIdentities: [],
|
|
169340
|
+
shareCategories: null,
|
|
169341
|
+
namesByIdentity: new Map,
|
|
169342
|
+
canonicalIdentityByStoredPath: new Map,
|
|
169343
|
+
isWorkspaced: false
|
|
169344
|
+
};
|
|
169345
|
+
}
|
|
169346
|
+
const identitySet = args.workspaceIdentitySet ?? resolveWorkspaceIdentitySet(args.db, args.projectPath);
|
|
169347
|
+
const isWorkspaced = identitySet.identities.length > 1;
|
|
169348
|
+
const expanded = expandWorkspaceIdentitySetWithAliases(args.db, identitySet.identities);
|
|
169349
|
+
const expandedIdentities = isWorkspaced ? expanded.expandedIdentities : identitySet.identities;
|
|
169350
|
+
const canonicalIdentityByStoredPath = isWorkspaced ? expanded.canonicalIdentityByStoredPath : new Map(identitySet.identities.map((identity) => [identity, identity]));
|
|
169351
|
+
let ownIdentities = expandedIdentities.filter((identity) => canonicalIdentityByStoredPath.get(identity) === args.projectPath);
|
|
169352
|
+
if (ownIdentities.length === 0 && expandedIdentities.includes(args.projectPath)) {
|
|
169353
|
+
ownIdentities = [args.projectPath];
|
|
169354
|
+
}
|
|
169355
|
+
return {
|
|
169356
|
+
identities: identitySet.identities,
|
|
169357
|
+
expandedIdentities,
|
|
169358
|
+
ownIdentities,
|
|
169359
|
+
shareCategories: isWorkspaced ? resolveWorkspaceShareCategories(args.db, args.projectPath) : null,
|
|
169360
|
+
namesByIdentity: identitySet.namesByIdentity,
|
|
169361
|
+
canonicalIdentityByStoredPath,
|
|
169362
|
+
isWorkspaced
|
|
169363
|
+
};
|
|
169364
|
+
}
|
|
169365
|
+
function sourceNamesForMemories(args) {
|
|
169366
|
+
if (!args.projectPath || !args.workspace.isWorkspaced)
|
|
169367
|
+
return;
|
|
169368
|
+
const names = new Map;
|
|
169369
|
+
for (const memory of args.memories) {
|
|
169370
|
+
const source = sourceNameForMemory(memory.projectPath, args.projectPath, args.workspace.identities, args.workspace.namesByIdentity, args.workspace.canonicalIdentityByStoredPath);
|
|
169371
|
+
if (source)
|
|
169372
|
+
names.set(memory.id, source);
|
|
169373
|
+
}
|
|
169374
|
+
return names.size > 0 ? names : undefined;
|
|
169375
|
+
}
|
|
169376
|
+
function memoryCanonicalIdentity(memory, workspace) {
|
|
169377
|
+
return resolveStoredPathWorkspaceIdentity(memory.projectPath, workspace.identities, workspace.canonicalIdentityByStoredPath);
|
|
169378
|
+
}
|
|
169379
|
+
function memorySelectionOrder(left, right) {
|
|
169380
|
+
if (left.status === "permanent" && right.status !== "permanent")
|
|
169381
|
+
return -1;
|
|
169382
|
+
if (right.status === "permanent" && left.status !== "permanent")
|
|
169383
|
+
return 1;
|
|
169384
|
+
const leftImportance = left.importance ?? Number.NEGATIVE_INFINITY;
|
|
169385
|
+
const rightImportance = right.importance ?? Number.NEGATIVE_INFINITY;
|
|
169386
|
+
const importanceDiff = rightImportance - leftImportance;
|
|
169387
|
+
if (importanceDiff !== 0)
|
|
169388
|
+
return importanceDiff;
|
|
169389
|
+
return left.id - right.id;
|
|
169390
|
+
}
|
|
169391
|
+
function memoryRenderOrder(left, right) {
|
|
169392
|
+
const aPriority = MEMORY_CATEGORY_ORDER_PRIORITY[left.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
169393
|
+
const bPriority = MEMORY_CATEGORY_ORDER_PRIORITY[right.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
169394
|
+
const categoryDiff = aPriority - bPriority;
|
|
169395
|
+
if (categoryDiff !== 0)
|
|
169396
|
+
return categoryDiff;
|
|
169397
|
+
return left.id - right.id;
|
|
169398
|
+
}
|
|
167922
169399
|
function cachedStatement(cache, db, sql) {
|
|
167923
169400
|
let stmt = cache.get(db);
|
|
167924
169401
|
if (!stmt) {
|
|
@@ -167961,13 +169438,19 @@ function getGlobalUserProfileVersion(db) {
|
|
|
167961
169438
|
function readCurrentM0SnapshotMarkers(args) {
|
|
167962
169439
|
const projectDirectory = args.projectDirectory ?? args.projectPath ?? "";
|
|
167963
169440
|
const hard = args.hardSignals ?? EMPTY_HARD_SIGNALS;
|
|
169441
|
+
const workspace = resolveWorkspaceRenderContext({
|
|
169442
|
+
db: args.db,
|
|
169443
|
+
projectPath: args.projectPath,
|
|
169444
|
+
workspaceIdentitySet: args.workspaceIdentitySet
|
|
169445
|
+
});
|
|
167964
169446
|
return {
|
|
167965
169447
|
projectMemoryEpoch: getProjectMemoryEpoch(args.db, args.projectPath),
|
|
169448
|
+
workspaceFingerprint: workspace.isWorkspaced ? computeWorkspaceEpochFingerprint(args.db, workspace.identities) : null,
|
|
167966
169449
|
projectUserProfileVersion: getGlobalUserProfileVersion(args.db),
|
|
167967
169450
|
maxCompartmentSeq: getMaxCompartmentSeq(args.db, args.sessionId),
|
|
167968
|
-
maxMemoryId: getMaxMemoryId(args.db, args.projectPath),
|
|
169451
|
+
maxMemoryId: workspace.isWorkspaced ? getMaxMemoryIdForProjects(args.db, workspace.expandedIdentities, workspace.ownIdentities, workspace.shareCategories) : getMaxMemoryId(args.db, args.projectPath),
|
|
167969
169452
|
maxMutationId: getMaxM0MutationId(args.db, args.sessionId) ?? 0,
|
|
167970
|
-
maxMemoryMutationId: args.projectPath ? getMaxMemoryMutationId(args.db, args.projectPath) ?? 0 : 0,
|
|
169453
|
+
maxMemoryMutationId: workspace.isWorkspaced ? getMaxMemoryMutationIdForProjects(args.db, workspace.expandedIdentities) ?? 0 : args.projectPath ? getMaxMemoryMutationId(args.db, args.projectPath) ?? 0 : 0,
|
|
167971
169454
|
projectDocsHash: projectDirectory ? computeProjectDocsHash(projectDirectory) : "",
|
|
167972
169455
|
materializedAt: Date.now(),
|
|
167973
169456
|
sessionFactsVersion: getSessionFactsVersion(args.db, args.sessionId),
|
|
@@ -167995,6 +169478,7 @@ function snapshotMarkersFromCachedM0(state) {
|
|
|
167995
169478
|
return null;
|
|
167996
169479
|
return {
|
|
167997
169480
|
projectMemoryEpoch: state.cachedM0ProjectMemoryEpoch,
|
|
169481
|
+
workspaceFingerprint: state.cachedM0WorkspaceFingerprint,
|
|
167998
169482
|
projectUserProfileVersion: state.cachedM0ProjectUserProfileVersion,
|
|
167999
169483
|
maxCompartmentSeq: state.cachedM0MaxCompartmentSeq,
|
|
168000
169484
|
maxMemoryId: state.cachedM0MaxMemoryId,
|
|
@@ -168024,35 +169508,27 @@ function mustMaterialize(args) {
|
|
|
168024
169508
|
if (hard.cacheExpired && hard.lastResponseTime > 0 && hard.lastResponseTime > (args.state.cachedM0MaterializedAt ?? 0)) {
|
|
168025
169509
|
return { value: true, reason: "ttl_idle" };
|
|
168026
169510
|
}
|
|
168027
|
-
if (args.state.
|
|
169511
|
+
if (current.workspaceFingerprint !== null || (args.state.cachedM0WorkspaceFingerprint ?? null) !== null) {
|
|
169512
|
+
if ((args.state.cachedM0WorkspaceFingerprint ?? null) !== current.workspaceFingerprint) {
|
|
169513
|
+
return { value: true, reason: "project_memory_epoch" };
|
|
169514
|
+
}
|
|
169515
|
+
} else if (args.state.cachedM0ProjectMemoryEpoch !== current.projectMemoryEpoch) {
|
|
168028
169516
|
return { value: true, reason: "project_memory_epoch" };
|
|
168029
169517
|
}
|
|
168030
169518
|
if (args.state.cachedM0MaxMutationId !== current.maxMutationId) {
|
|
168031
169519
|
return { value: true, reason: "max_mutation_id" };
|
|
168032
169520
|
}
|
|
168033
|
-
if ((args.state.cachedM0ProjectDocsHash ?? "") !== current.projectDocsHash) {
|
|
168034
|
-
return { value: true, reason: "project_docs_hash" };
|
|
168035
|
-
}
|
|
168036
169521
|
if ((args.state.cachedM0UpgradeState ?? null) !== current.upgradeState) {
|
|
168037
169522
|
return { value: true, reason: "upgrade_state" };
|
|
168038
169523
|
}
|
|
168039
169524
|
return { value: false, reason: null };
|
|
168040
169525
|
}
|
|
168041
|
-
function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens) {
|
|
168042
|
-
const selectionOrder = [...memories].sort(
|
|
168043
|
-
if (a.status === "permanent" && b.status !== "permanent")
|
|
168044
|
-
return -1;
|
|
168045
|
-
if (b.status === "permanent" && a.status !== "permanent")
|
|
168046
|
-
return 1;
|
|
168047
|
-
const importanceDiff = (b.importance ?? 50) - (a.importance ?? 50);
|
|
168048
|
-
if (importanceDiff !== 0)
|
|
168049
|
-
return importanceDiff;
|
|
168050
|
-
return a.id - b.id;
|
|
168051
|
-
});
|
|
169526
|
+
function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens, renderOptions = {}) {
|
|
169527
|
+
const selectionOrder = [...memories].sort(memorySelectionOrder);
|
|
168052
169528
|
const selected = [];
|
|
168053
169529
|
let usedTokens = MEMORY_BLOCK_WRAPPER_TOKENS;
|
|
168054
169530
|
for (const memory of selectionOrder) {
|
|
168055
|
-
const memoryTokens = estimateTokens(renderMemoryLineV2(memory));
|
|
169531
|
+
const memoryTokens = estimateTokens(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
168056
169532
|
if (usedTokens + memoryTokens > budgetTokens)
|
|
168057
169533
|
continue;
|
|
168058
169534
|
selected.push(memory);
|
|
@@ -168061,16 +169537,70 @@ function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens) {
|
|
|
168061
169537
|
if (selected.length < memories.length) {
|
|
168062
169538
|
sessionLog(sessionId, `v2 trimmed memories from ${memories.length} to ${selected.length} to fit injection budget of ${budgetTokens} tokens`);
|
|
168063
169539
|
}
|
|
168064
|
-
const renderOrder = [...selected].sort(
|
|
168065
|
-
const aPriority = MEMORY_CATEGORY_ORDER_PRIORITY[a.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
168066
|
-
const bPriority = MEMORY_CATEGORY_ORDER_PRIORITY[b.category] ?? MEMORY_CATEGORY_ORDER_UNKNOWN;
|
|
168067
|
-
const categoryDiff = aPriority - bPriority;
|
|
168068
|
-
if (categoryDiff !== 0)
|
|
168069
|
-
return categoryDiff;
|
|
168070
|
-
return a.id - b.id;
|
|
168071
|
-
});
|
|
169540
|
+
const renderOrder = [...selected].sort(memoryRenderOrder);
|
|
168072
169541
|
return { selected, renderOrder };
|
|
168073
169542
|
}
|
|
169543
|
+
function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, workspace, renderOptions = {}) {
|
|
169544
|
+
if (!workspace.isWorkspaced) {
|
|
169545
|
+
return trimMemoriesToBudgetV2(sessionId, memories, budgetTokens, renderOptions);
|
|
169546
|
+
}
|
|
169547
|
+
const selected = [];
|
|
169548
|
+
const selectedIds = new Set;
|
|
169549
|
+
let usedTokens = MEMORY_BLOCK_WRAPPER_TOKENS;
|
|
169550
|
+
const tokenCost = (memory) => estimateTokens(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
169551
|
+
const trySelect = (memory) => {
|
|
169552
|
+
if (selectedIds.has(memory.id))
|
|
169553
|
+
return false;
|
|
169554
|
+
const tokens = tokenCost(memory);
|
|
169555
|
+
if (usedTokens + tokens > budgetTokens)
|
|
169556
|
+
return false;
|
|
169557
|
+
selected.push(memory);
|
|
169558
|
+
selectedIds.add(memory.id);
|
|
169559
|
+
usedTokens += tokens;
|
|
169560
|
+
return true;
|
|
169561
|
+
};
|
|
169562
|
+
for (const memory of memories.filter((candidate) => candidate.status === "permanent").sort(memorySelectionOrder)) {
|
|
169563
|
+
trySelect(memory);
|
|
169564
|
+
}
|
|
169565
|
+
const remainingAfterPermanent = Math.max(0, budgetTokens - usedTokens);
|
|
169566
|
+
const floorTokens = remainingAfterPermanent / Math.max(1, workspace.identities.length);
|
|
169567
|
+
const byIdentity = new Map;
|
|
169568
|
+
for (const memory of memories) {
|
|
169569
|
+
if (memory.status === "permanent")
|
|
169570
|
+
continue;
|
|
169571
|
+
const identity = memoryCanonicalIdentity(memory, workspace);
|
|
169572
|
+
if (!identity)
|
|
169573
|
+
continue;
|
|
169574
|
+
const list = byIdentity.get(identity) ?? [];
|
|
169575
|
+
list.push(memory);
|
|
169576
|
+
byIdentity.set(identity, list);
|
|
169577
|
+
}
|
|
169578
|
+
for (const identity of workspace.identities) {
|
|
169579
|
+
let memberTokens = 0;
|
|
169580
|
+
const candidates = (byIdentity.get(identity) ?? []).sort(memorySelectionOrder);
|
|
169581
|
+
for (const memory of candidates) {
|
|
169582
|
+
if (selectedIds.has(memory.id))
|
|
169583
|
+
continue;
|
|
169584
|
+
const tokens = tokenCost(memory);
|
|
169585
|
+
if (memberTokens + tokens > floorTokens)
|
|
169586
|
+
continue;
|
|
169587
|
+
if (usedTokens + tokens > budgetTokens)
|
|
169588
|
+
continue;
|
|
169589
|
+
selected.push(memory);
|
|
169590
|
+
selectedIds.add(memory.id);
|
|
169591
|
+
usedTokens += tokens;
|
|
169592
|
+
memberTokens += tokens;
|
|
169593
|
+
}
|
|
169594
|
+
}
|
|
169595
|
+
const remaining = memories.filter((memory) => !selectedIds.has(memory.id)).sort(memorySelectionOrder);
|
|
169596
|
+
for (const memory of remaining) {
|
|
169597
|
+
trySelect(memory);
|
|
169598
|
+
}
|
|
169599
|
+
if (selected.length < memories.length) {
|
|
169600
|
+
sessionLog(sessionId, `v2 trimmed memories from ${memories.length} to ${selected.length} to fit injection budget of ${budgetTokens} tokens`);
|
|
169601
|
+
}
|
|
169602
|
+
return { selected, renderOrder: [...selected].sort(memoryRenderOrder) };
|
|
169603
|
+
}
|
|
168074
169604
|
function safeGetActiveUserMemories(db) {
|
|
168075
169605
|
try {
|
|
168076
169606
|
return getActiveUserMemories(db);
|
|
@@ -168146,15 +169676,16 @@ function readNewMemoriesForM1(db, projectPath, afterId, expiryCutoff) {
|
|
|
168146
169676
|
ORDER BY ${MEMORY_CATEGORY_ORDER_SQL}, id ASC`).all(projectPath, afterId, expiryCutoff).filter(isMemoryRow);
|
|
168147
169677
|
return rows.map((row) => ({ ...row }));
|
|
168148
169678
|
}
|
|
168149
|
-
function renderMemoryLineV2(memory) {
|
|
168150
|
-
|
|
169679
|
+
function renderMemoryLineV2(memory, sourceName) {
|
|
169680
|
+
const sourceAttr = sourceName ? ` source="${escapeXmlAttr(sourceName)}"` : "";
|
|
169681
|
+
return ` <memory id="${memory.id}" category="${escapeXmlAttr(memory.category)}"${sourceAttr} importance="${memory.importance ?? 50}">${escapeXmlContent(memory.content)}</memory>`;
|
|
168151
169682
|
}
|
|
168152
|
-
function renderMemoryBlockV2(memories, wrapper = "project-memory") {
|
|
169683
|
+
function renderMemoryBlockV2(memories, wrapper = "project-memory", renderOptions = {}) {
|
|
168153
169684
|
if (memories.length === 0)
|
|
168154
169685
|
return "";
|
|
168155
169686
|
const lines = [`<${wrapper}>`];
|
|
168156
169687
|
for (const memory of memories) {
|
|
168157
|
-
lines.push(renderMemoryLineV2(memory));
|
|
169688
|
+
lines.push(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
168158
169689
|
}
|
|
168159
169690
|
lines.push(`</${wrapper}>`);
|
|
168160
169691
|
return lines.join(`
|
|
@@ -168193,7 +169724,7 @@ function renderM0(args) {
|
|
|
168193
169724
|
sections.push(sessionHistory.length > 0 ? `<session-history>
|
|
168194
169725
|
${sessionHistory}
|
|
168195
169726
|
</session-history>` : M0_EMPTY_BODY);
|
|
168196
|
-
const memoriesBlock = renderMemoryBlockV2(args.memories);
|
|
169727
|
+
const memoriesBlock = renderMemoryBlockV2(args.memories, "project-memory", args.memoryRenderOptions);
|
|
168197
169728
|
if (memoriesBlock)
|
|
168198
169729
|
sections.push(memoriesBlock);
|
|
168199
169730
|
return sections.join(`
|
|
@@ -168205,6 +169736,7 @@ function applyMarkersToState(state, m0Bytes, markers, m1Bytes) {
|
|
|
168205
169736
|
if (m1Bytes)
|
|
168206
169737
|
state.cachedM1Bytes = m1Bytes;
|
|
168207
169738
|
state.cachedM0ProjectMemoryEpoch = markers.projectMemoryEpoch;
|
|
169739
|
+
state.cachedM0WorkspaceFingerprint = markers.workspaceFingerprint;
|
|
168208
169740
|
state.cachedM0ProjectUserProfileVersion = markers.projectUserProfileVersion;
|
|
168209
169741
|
state.cachedM0MaxCompartmentSeq = markers.maxCompartmentSeq;
|
|
168210
169742
|
state.cachedM0MaxMemoryId = markers.maxMemoryId;
|
|
@@ -168230,24 +169762,38 @@ function materializeM0(options) {
|
|
|
168230
169762
|
let facts = [];
|
|
168231
169763
|
let memories = [];
|
|
168232
169764
|
let userMemories = [];
|
|
169765
|
+
let workspace = resolveWorkspaceRenderContext({
|
|
169766
|
+
db: options.db,
|
|
169767
|
+
projectPath,
|
|
169768
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
169769
|
+
});
|
|
168233
169770
|
let docs = {
|
|
168234
169771
|
renderedBlock: "",
|
|
168235
169772
|
canonicalHash: ""
|
|
168236
169773
|
};
|
|
168237
169774
|
options.db.exec("BEGIN");
|
|
168238
169775
|
try {
|
|
169776
|
+
workspace = resolveWorkspaceRenderContext({
|
|
169777
|
+
db: options.db,
|
|
169778
|
+
projectPath,
|
|
169779
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
169780
|
+
});
|
|
168239
169781
|
snapshotMarkers = readCurrentM0SnapshotMarkers({
|
|
168240
169782
|
db: options.db,
|
|
168241
169783
|
sessionId: options.sessionId,
|
|
168242
169784
|
projectPath,
|
|
168243
169785
|
projectDirectory,
|
|
168244
|
-
hardSignals: options.hardSignals
|
|
169786
|
+
hardSignals: options.hardSignals,
|
|
169787
|
+
workspaceIdentitySet: {
|
|
169788
|
+
identities: workspace.identities,
|
|
169789
|
+
namesByIdentity: workspace.namesByIdentity
|
|
169790
|
+
}
|
|
168245
169791
|
});
|
|
168246
169792
|
docs = projectDirectory ? readProjectDocsCanonical(projectDirectory) : { renderedBlock: "", canonicalHash: "" };
|
|
168247
169793
|
snapshotMarkers.projectDocsHash = docs.canonicalHash;
|
|
168248
169794
|
compartments = readM0Compartments(options.db, options.sessionId);
|
|
168249
169795
|
facts = [];
|
|
168250
|
-
memories = projectPath ? getMemoriesByProject(options.db, projectPath, ["active", "permanent"]) : [];
|
|
169796
|
+
memories = projectPath ? workspace.isWorkspaced ? getMemoriesByProjects(options.db, workspace.expandedIdentities, ["active", "permanent"], Date.now(), workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(options.db, projectPath, ["active", "permanent"]) : [];
|
|
168251
169797
|
userMemories = safeGetActiveUserMemories(options.db);
|
|
168252
169798
|
options.db.exec("COMMIT");
|
|
168253
169799
|
} catch (error51) {
|
|
@@ -168257,7 +169803,14 @@ function materializeM0(options) {
|
|
|
168257
169803
|
throw error51;
|
|
168258
169804
|
}
|
|
168259
169805
|
const memoryBudget = options.memoryInjectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
|
|
168260
|
-
const
|
|
169806
|
+
const memoryRenderOptions = {
|
|
169807
|
+
sourceNameByMemoryId: sourceNamesForMemories({
|
|
169808
|
+
memories,
|
|
169809
|
+
projectPath,
|
|
169810
|
+
workspace
|
|
169811
|
+
})
|
|
169812
|
+
};
|
|
169813
|
+
const trimmed = workspace.isWorkspaced ? trimWorkspaceMemoriesToBudgetV2(options.sessionId, memories, memoryBudget, workspace, memoryRenderOptions) : trimMemoriesToBudgetV2(options.sessionId, memories, memoryBudget);
|
|
168261
169814
|
let decayPressureMultiplier = 1;
|
|
168262
169815
|
let m0Text = renderM0({
|
|
168263
169816
|
projectDocs: docs.renderedBlock,
|
|
@@ -168265,6 +169818,7 @@ function materializeM0(options) {
|
|
|
168265
169818
|
compartments,
|
|
168266
169819
|
memories: trimmed.renderOrder,
|
|
168267
169820
|
facts,
|
|
169821
|
+
memoryRenderOptions,
|
|
168268
169822
|
historyBudgetTokens: options.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS,
|
|
168269
169823
|
userProfileBudgetTokens: options.userProfileBudgetTokens,
|
|
168270
169824
|
decayPressureMultiplier
|
|
@@ -168279,6 +169833,7 @@ function materializeM0(options) {
|
|
|
168279
169833
|
compartments,
|
|
168280
169834
|
memories: trimmed.renderOrder,
|
|
168281
169835
|
facts,
|
|
169836
|
+
memoryRenderOptions,
|
|
168282
169837
|
historyBudgetTokens: budget,
|
|
168283
169838
|
userProfileBudgetTokens: options.userProfileBudgetTokens,
|
|
168284
169839
|
decayPressureMultiplier
|
|
@@ -168297,13 +169852,19 @@ function materializeM0(options) {
|
|
|
168297
169852
|
let m1Bytes = Buffer4.from(m1Text, "utf8");
|
|
168298
169853
|
options.db.exec("BEGIN IMMEDIATE");
|
|
168299
169854
|
try {
|
|
169855
|
+
const currentWorkspace = resolveWorkspaceRenderContext({
|
|
169856
|
+
db: options.db,
|
|
169857
|
+
projectPath,
|
|
169858
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
169859
|
+
});
|
|
168300
169860
|
const current = {
|
|
168301
169861
|
projectMemoryEpoch: getProjectMemoryEpoch(options.db, projectPath),
|
|
169862
|
+
workspaceFingerprint: currentWorkspace.isWorkspaced ? computeWorkspaceEpochFingerprint(options.db, currentWorkspace.identities) : null,
|
|
168302
169863
|
projectUserProfileVersion: getGlobalUserProfileVersion(options.db),
|
|
168303
169864
|
maxCompartmentSeq: getMaxCompartmentSeq(options.db, options.sessionId),
|
|
168304
|
-
maxMemoryId: getMaxMemoryId(options.db, projectPath),
|
|
169865
|
+
maxMemoryId: currentWorkspace.isWorkspaced ? getMaxMemoryIdForProjects(options.db, currentWorkspace.expandedIdentities, currentWorkspace.ownIdentities, currentWorkspace.shareCategories) : getMaxMemoryId(options.db, projectPath),
|
|
168305
169866
|
maxMutationId: getMaxM0MutationId(options.db, options.sessionId) ?? 0,
|
|
168306
|
-
maxMemoryMutationId: projectPath ? getMaxMemoryMutationId(options.db, projectPath) ?? 0 : 0,
|
|
169867
|
+
maxMemoryMutationId: currentWorkspace.isWorkspaced ? getMaxMemoryMutationIdForProjects(options.db, currentWorkspace.expandedIdentities) ?? 0 : projectPath ? getMaxMemoryMutationId(options.db, projectPath) ?? 0 : 0,
|
|
168307
169868
|
projectDocsHash: phase3ProjectDocsHash,
|
|
168308
169869
|
materializedAt: Date.now(),
|
|
168309
169870
|
sessionFactsVersion: getSessionFactsVersion(options.db, options.sessionId),
|
|
@@ -168311,17 +169872,26 @@ function materializeM0(options) {
|
|
|
168311
169872
|
systemHash: snapshotMarkers.systemHash,
|
|
168312
169873
|
modelKey: snapshotMarkers.modelKey
|
|
168313
169874
|
};
|
|
168314
|
-
const
|
|
169875
|
+
const memoryEpochStale = current.workspaceFingerprint !== null || snapshotMarkers.workspaceFingerprint !== null ? current.workspaceFingerprint !== snapshotMarkers.workspaceFingerprint : current.projectMemoryEpoch !== snapshotMarkers.projectMemoryEpoch;
|
|
169876
|
+
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;
|
|
168315
169877
|
if (stale) {
|
|
168316
169878
|
options.db.exec("ROLLBACK");
|
|
168317
169879
|
throw new MaterializeContentionError({ reason: "snapshot changed before Phase 3" });
|
|
168318
169880
|
}
|
|
168319
|
-
const m1Render = renderM1WithMetadata({
|
|
169881
|
+
const m1Render = renderM1WithMetadata({
|
|
169882
|
+
...options,
|
|
169883
|
+
preRenderedKeyFilesBlock,
|
|
169884
|
+
workspaceIdentitySet: {
|
|
169885
|
+
identities: workspace.identities,
|
|
169886
|
+
namesByIdentity: workspace.namesByIdentity
|
|
169887
|
+
}
|
|
169888
|
+
}, snapshotMarkers, renderedMemoryIds);
|
|
168320
169889
|
m1Text = m1Render.text;
|
|
168321
169890
|
m1Bytes = Buffer4.from(m1Text, "utf8");
|
|
168322
169891
|
persistCachedM0(options.db, options.sessionId, {
|
|
168323
169892
|
m0Bytes,
|
|
168324
169893
|
projectMemoryEpoch: snapshotMarkers.projectMemoryEpoch,
|
|
169894
|
+
workspaceFingerprint: snapshotMarkers.workspaceFingerprint,
|
|
168325
169895
|
projectUserProfileVersion: snapshotMarkers.projectUserProfileVersion,
|
|
168326
169896
|
maxCompartmentSeq: snapshotMarkers.maxCompartmentSeq,
|
|
168327
169897
|
maxMemoryId: snapshotMarkers.maxMemoryId,
|
|
@@ -168384,7 +169954,7 @@ function renderMemoryUpdatesBlock(args) {
|
|
|
168384
169954
|
return { block: "", count: 0 };
|
|
168385
169955
|
}
|
|
168386
169956
|
const renderedIds = new Set(args.renderedMemoryIds);
|
|
168387
|
-
const mutations = getMemoryMutationsForRender(args.db, args.projectPath, args.afterId, args.renderedMemoryIds);
|
|
169957
|
+
const mutations = args.workspace.isWorkspaced ? getMemoryMutationsForRenderByProjects(args.db, args.workspace.expandedIdentities, args.afterId, args.renderedMemoryIds) : getMemoryMutationsForRender(args.db, args.projectPath, args.afterId, args.renderedMemoryIds);
|
|
168388
169958
|
if (mutations.length === 0)
|
|
168389
169959
|
return { block: "", count: 0 };
|
|
168390
169960
|
const lines = ["These memories changed since the snapshot below — trust these:"];
|
|
@@ -168416,12 +169986,18 @@ function renderM1WithMetadata(options, markers, renderedMemoryIds) {
|
|
|
168416
169986
|
throw new RenderM1InvalidMarkersError(options.sessionId);
|
|
168417
169987
|
}
|
|
168418
169988
|
const blocks = [];
|
|
169989
|
+
const workspace = resolveWorkspaceRenderContext({
|
|
169990
|
+
db: options.db,
|
|
169991
|
+
projectPath: options.projectPath,
|
|
169992
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
169993
|
+
});
|
|
168419
169994
|
const keyFiles = renderedKeyFilesBlock(options);
|
|
168420
169995
|
if (keyFiles)
|
|
168421
169996
|
blocks.push(keyFiles);
|
|
168422
169997
|
const memoryUpdates = renderMemoryUpdatesBlock({
|
|
168423
169998
|
db: options.db,
|
|
168424
169999
|
projectPath: options.projectPath,
|
|
170000
|
+
workspace,
|
|
168425
170001
|
afterId: markers.maxMemoryMutationId,
|
|
168426
170002
|
renderedMemoryIds
|
|
168427
170003
|
});
|
|
@@ -168435,9 +170011,16 @@ ${newCompartments.map((compartment) => renderCompartmentAtTier(compartment, 1)).
|
|
|
168435
170011
|
`)}
|
|
168436
170012
|
</new-compartments>`);
|
|
168437
170013
|
}
|
|
168438
|
-
const newMemories = readNewMemoriesForM1(options.db, options.projectPath, markers.maxMemoryId, markers.materializedAt);
|
|
168439
|
-
const
|
|
168440
|
-
|
|
170014
|
+
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);
|
|
170015
|
+
const newMemoryRenderOptions = {
|
|
170016
|
+
sourceNameByMemoryId: sourceNamesForMemories({
|
|
170017
|
+
memories: newMemories,
|
|
170018
|
+
projectPath: options.projectPath,
|
|
170019
|
+
workspace
|
|
170020
|
+
})
|
|
170021
|
+
};
|
|
170022
|
+
const trimmedNewMemories = trimMemoriesToBudgetV2(options.sessionId, newMemories, Math.max(1, Math.floor((options.memoryInjectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS) * 0.25)), newMemoryRenderOptions).renderOrder;
|
|
170023
|
+
const newMemoriesBlock = renderMemoryBlockV2(trimmedNewMemories, "new-memories", newMemoryRenderOptions);
|
|
168441
170024
|
if (newMemoriesBlock)
|
|
168442
170025
|
blocks.push(newMemoriesBlock);
|
|
168443
170026
|
const currentUserProfileVersion = getGlobalUserProfileVersion(options.db);
|
|
@@ -168485,6 +170068,7 @@ function parseMemoryBlockIds(raw) {
|
|
|
168485
170068
|
function readCachedM0M1Row(db, sessionId) {
|
|
168486
170069
|
return db.prepare(`SELECT cached_m0_bytes, cached_m1_bytes,
|
|
168487
170070
|
cached_m0_project_memory_epoch,
|
|
170071
|
+
cached_m0_workspace_fingerprint,
|
|
168488
170072
|
cached_m0_project_user_profile_version,
|
|
168489
170073
|
cached_m0_max_compartment_seq,
|
|
168490
170074
|
cached_m0_max_memory_id,
|
|
@@ -168519,6 +170103,7 @@ function markersFromCachedRow(row) {
|
|
|
168519
170103
|
return null;
|
|
168520
170104
|
return {
|
|
168521
170105
|
projectMemoryEpoch: row.cached_m0_project_memory_epoch,
|
|
170106
|
+
workspaceFingerprint: row.cached_m0_workspace_fingerprint,
|
|
168522
170107
|
projectUserProfileVersion: row.cached_m0_project_user_profile_version,
|
|
168523
170108
|
maxCompartmentSeq: row.cached_m0_max_compartment_seq,
|
|
168524
170109
|
maxMemoryId: row.cached_m0_max_memory_id,
|
|
@@ -168533,7 +170118,7 @@ function markersFromCachedRow(row) {
|
|
|
168533
170118
|
};
|
|
168534
170119
|
}
|
|
168535
170120
|
function cachedRowMatchesState(row, state) {
|
|
168536
|
-
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 &&
|
|
170121
|
+
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 ?? "");
|
|
168537
170122
|
}
|
|
168538
170123
|
function applyCachedRowToState(state, row) {
|
|
168539
170124
|
const markers = markersFromCachedRow(row);
|
|
@@ -168543,6 +170128,7 @@ function applyCachedRowToState(state, row) {
|
|
|
168543
170128
|
state.cachedM0Bytes = toBuffer(row.cached_m0_bytes);
|
|
168544
170129
|
state.cachedM1Bytes = toBuffer(row.cached_m1_bytes);
|
|
168545
170130
|
state.cachedM0ProjectMemoryEpoch = markers.projectMemoryEpoch;
|
|
170131
|
+
state.cachedM0WorkspaceFingerprint = markers.workspaceFingerprint;
|
|
168546
170132
|
state.cachedM0ProjectUserProfileVersion = markers.projectUserProfileVersion;
|
|
168547
170133
|
state.cachedM0MaxCompartmentSeq = markers.maxCompartmentSeq;
|
|
168548
170134
|
state.cachedM0MaxMemoryId = markers.maxMemoryId;
|
|
@@ -168597,29 +170183,51 @@ function softRefreshCachedM1(options) {
|
|
|
168597
170183
|
function prependM0M1Messages(sessionId, messages, m0Text, m1Text) {
|
|
168598
170184
|
messages.unshift({
|
|
168599
170185
|
info: { role: "user", sessionID: sessionId },
|
|
168600
|
-
parts: [
|
|
170186
|
+
parts: [
|
|
170187
|
+
{
|
|
170188
|
+
type: "text",
|
|
170189
|
+
text: m0Text.length > 0 ? m0Text : M0_EMPTY_BODY,
|
|
170190
|
+
synthetic: true
|
|
170191
|
+
}
|
|
170192
|
+
]
|
|
168601
170193
|
}, {
|
|
168602
170194
|
info: { role: "user", sessionID: sessionId },
|
|
168603
|
-
parts: [{ type: "text", text: m1Text }]
|
|
170195
|
+
parts: [{ type: "text", text: m1Text, synthetic: true }]
|
|
168604
170196
|
});
|
|
168605
170197
|
}
|
|
168606
170198
|
function renderFreshM0NonPersisted(options) {
|
|
168607
170199
|
const projectPath = options.projectPath;
|
|
168608
170200
|
const projectDirectory = options.projectDirectory;
|
|
170201
|
+
const workspace = resolveWorkspaceRenderContext({
|
|
170202
|
+
db: options.db,
|
|
170203
|
+
projectPath,
|
|
170204
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
170205
|
+
});
|
|
168609
170206
|
const snapshotMarkers = readCurrentM0SnapshotMarkers({
|
|
168610
170207
|
db: options.db,
|
|
168611
170208
|
sessionId: options.sessionId,
|
|
168612
170209
|
projectPath,
|
|
168613
|
-
projectDirectory
|
|
170210
|
+
projectDirectory,
|
|
170211
|
+
workspaceIdentitySet: {
|
|
170212
|
+
identities: workspace.identities,
|
|
170213
|
+
namesByIdentity: workspace.namesByIdentity
|
|
170214
|
+
}
|
|
168614
170215
|
});
|
|
168615
170216
|
const docs = projectDirectory ? readProjectDocsCanonical(projectDirectory) : { renderedBlock: "", canonicalHash: "" };
|
|
168616
170217
|
snapshotMarkers.projectDocsHash = docs.canonicalHash;
|
|
168617
170218
|
snapshotMarkers.materializedAt = options.state.cachedM0MaterializedAt ?? 0;
|
|
168618
170219
|
const compartments = readM0Compartments(options.db, options.sessionId);
|
|
168619
|
-
const memories = projectPath ? getMemoriesByProject(options.db, projectPath, ["active", "permanent"], snapshotMarkers.materializedAt) : [];
|
|
170220
|
+
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) : [];
|
|
168620
170221
|
const userMemories = safeGetActiveUserMemories(options.db);
|
|
168621
170222
|
const memoryBudget = options.memoryInjectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
|
|
168622
|
-
const
|
|
170223
|
+
const memoryRenderOptions = {
|
|
170224
|
+
sourceNameByMemoryId: sourceNamesForMemories({
|
|
170225
|
+
memories,
|
|
170226
|
+
projectPath,
|
|
170227
|
+
workspace
|
|
170228
|
+
})
|
|
170229
|
+
};
|
|
170230
|
+
const trimmed = workspace.isWorkspaced ? trimWorkspaceMemoriesToBudgetV2(options.sessionId, memories, memoryBudget, workspace, memoryRenderOptions) : trimMemoriesToBudgetV2(options.sessionId, memories, memoryBudget);
|
|
168623
170231
|
const budget = options.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS;
|
|
168624
170232
|
let decayPressureMultiplier = 1;
|
|
168625
170233
|
let m0Text = renderM0({
|
|
@@ -168628,6 +170236,7 @@ function renderFreshM0NonPersisted(options) {
|
|
|
168628
170236
|
compartments,
|
|
168629
170237
|
memories: trimmed.renderOrder,
|
|
168630
170238
|
facts: [],
|
|
170239
|
+
memoryRenderOptions,
|
|
168631
170240
|
historyBudgetTokens: budget,
|
|
168632
170241
|
userProfileBudgetTokens: options.userProfileBudgetTokens,
|
|
168633
170242
|
decayPressureMultiplier
|
|
@@ -168641,6 +170250,7 @@ function renderFreshM0NonPersisted(options) {
|
|
|
168641
170250
|
compartments,
|
|
168642
170251
|
memories: trimmed.renderOrder,
|
|
168643
170252
|
facts: [],
|
|
170253
|
+
memoryRenderOptions,
|
|
168644
170254
|
historyBudgetTokens: budget,
|
|
168645
170255
|
userProfileBudgetTokens: options.userProfileBudgetTokens,
|
|
168646
170256
|
decayPressureMultiplier
|
|
@@ -168656,6 +170266,12 @@ function renderFreshM0NonPersisted(options) {
|
|
|
168656
170266
|
};
|
|
168657
170267
|
}
|
|
168658
170268
|
function injectM0M1(options) {
|
|
170269
|
+
if (!options.workspaceIdentitySet && options.projectPath) {
|
|
170270
|
+
options = {
|
|
170271
|
+
...options,
|
|
170272
|
+
workspaceIdentitySet: resolveWorkspaceIdentitySet(options.db, options.projectPath)
|
|
170273
|
+
};
|
|
170274
|
+
}
|
|
168659
170275
|
const skipped = {
|
|
168660
170276
|
injected: false,
|
|
168661
170277
|
m0RematerializedThisPass: false,
|
|
@@ -168672,7 +170288,8 @@ function injectM0M1(options) {
|
|
|
168672
170288
|
state: options.state,
|
|
168673
170289
|
projectPath: options.projectPath,
|
|
168674
170290
|
projectDirectory: options.projectDirectory,
|
|
168675
|
-
hardSignals: options.hardSignals
|
|
170291
|
+
hardSignals: options.hardSignals,
|
|
170292
|
+
workspaceIdentitySet: options.workspaceIdentitySet
|
|
168676
170293
|
});
|
|
168677
170294
|
let rematerialized = false;
|
|
168678
170295
|
let contentionExhausted = false;
|
|
@@ -168766,6 +170383,7 @@ var init_inject_compartments = __esm(async () => {
|
|
|
168766
170383
|
init_compartment_storage();
|
|
168767
170384
|
init_constants();
|
|
168768
170385
|
init_storage_memory();
|
|
170386
|
+
init_workspaces();
|
|
168769
170387
|
init_logger();
|
|
168770
170388
|
init_decay_render();
|
|
168771
170389
|
init_key_files_block();
|
|
@@ -171905,18 +173523,38 @@ async function runCompartmentAgent(deps) {
|
|
|
171905
173523
|
return;
|
|
171906
173524
|
}
|
|
171907
173525
|
const offset = priorCompartments.length > 0 ? priorCompartments[priorCompartments.length - 1].endMessage + 1 : 1;
|
|
171908
|
-
|
|
173526
|
+
let boundarySnapshot = deps.boundarySnapshot ?? null;
|
|
171909
173527
|
if (!boundarySnapshot) {
|
|
171910
173528
|
telemetry.failureReason = "missing protected-tail boundary snapshot";
|
|
171911
173529
|
sessionLog(sessionId, "historian no-op: missing protected-tail boundary snapshot from trigger decision");
|
|
171912
173530
|
rollbackDrainReservation();
|
|
171913
173531
|
return;
|
|
171914
173532
|
}
|
|
171915
|
-
|
|
173533
|
+
let validation = boundarySnapshot.rawRangeFingerprint.length > 0 ? validateBoundarySnapshot({
|
|
171916
173534
|
db,
|
|
171917
173535
|
snapshot: boundarySnapshot,
|
|
171918
173536
|
currentContextLimit: deps.currentContextLimit ?? boundarySnapshot.contextLimit
|
|
171919
173537
|
}) : { ok: true };
|
|
173538
|
+
if (!validation.ok && validation.reason === "stale_snapshot") {
|
|
173539
|
+
const refreshed = resolveOpenCodeProtectedTailBoundary({
|
|
173540
|
+
db,
|
|
173541
|
+
sessionId,
|
|
173542
|
+
mode: "incremental-runner",
|
|
173543
|
+
contextLimit: deps.currentContextLimit ?? boundarySnapshot.contextLimit,
|
|
173544
|
+
executeThresholdPercentage: boundarySnapshot.executeThresholdPercentage,
|
|
173545
|
+
usage: {
|
|
173546
|
+
percentage: boundarySnapshot.usagePercentage,
|
|
173547
|
+
inputTokens: boundarySnapshot.usageInputTokens
|
|
173548
|
+
},
|
|
173549
|
+
usageSource: boundarySnapshot.usageSource,
|
|
173550
|
+
emergencyTailScale: boundarySnapshot.emergencyTailScale
|
|
173551
|
+
});
|
|
173552
|
+
if (hasRunnableCompartmentWindow(refreshed)) {
|
|
173553
|
+
sessionLog(sessionId, `historian: refreshed stale protected-tail snapshot at run time (was: ${validation.detail ?? "stale"}) — eligible head ${refreshed.offset}-${refreshed.eligibleEndOrdinal - 1}`);
|
|
173554
|
+
boundarySnapshot = refreshed;
|
|
173555
|
+
validation = { ok: true };
|
|
173556
|
+
}
|
|
173557
|
+
}
|
|
171920
173558
|
if (!validation.ok) {
|
|
171921
173559
|
sessionLog(sessionId, `historian no-op: stale protected-tail snapshot (${validation.detail ?? validation.reason ?? "unknown"})`);
|
|
171922
173560
|
telemetry.status = "noop";
|
|
@@ -171985,6 +173623,7 @@ async function runCompartmentAgent(deps) {
|
|
|
171985
173623
|
rollbackDrainReservation();
|
|
171986
173624
|
return;
|
|
171987
173625
|
}
|
|
173626
|
+
deps.onHistorianRunStarted?.();
|
|
171988
173627
|
const projectPath = resolveProjectIdentity(directory ?? process.cwd());
|
|
171989
173628
|
const memories = getMemoriesByProject(db, projectPath, ["active", "permanent"]);
|
|
171990
173629
|
const projectMemory = renderMemoryBlock(memories) ?? "";
|
|
@@ -172117,8 +173756,13 @@ ${chunkText}`,
|
|
|
172117
173756
|
}
|
|
172118
173757
|
if (embeddingActive) {
|
|
172119
173758
|
const projectIdentity = resolveProjectIdentity(promotionDirectory);
|
|
172120
|
-
const
|
|
172121
|
-
|
|
173759
|
+
const chunksToEmbed = persistedCompartments.map((c, i) => ({
|
|
173760
|
+
id: persistedIds[i],
|
|
173761
|
+
startMessage: c.startMessage,
|
|
173762
|
+
endMessage: c.endMessage,
|
|
173763
|
+
sourceChunkText: chunk.text
|
|
173764
|
+
})).filter((c) => typeof c.id === "number");
|
|
173765
|
+
embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed);
|
|
172122
173766
|
}
|
|
172123
173767
|
queueDropsForCompartmentalizedMessages(db, sessionId, lastCompartmentEnd);
|
|
172124
173768
|
deps.onCompartmentStatePublished?.(sessionId);
|
|
@@ -172349,8 +173993,12 @@ Found ${existingStaging.compartments.length} staged compartment(s) from ${existi
|
|
|
172349
173993
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
172350
173994
|
await deps.ensureProjectRegistered?.(sessionDirectory, db);
|
|
172351
173995
|
const liveCompartments = getCompartments(db, sessionId);
|
|
172352
|
-
const
|
|
172353
|
-
|
|
173996
|
+
const chunksToEmbed = liveCompartments.map((c) => ({
|
|
173997
|
+
id: c.id,
|
|
173998
|
+
startMessage: c.startMessage,
|
|
173999
|
+
endMessage: c.endMessage
|
|
174000
|
+
}));
|
|
174001
|
+
embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed);
|
|
172354
174002
|
}
|
|
172355
174003
|
const lastCompartmentEnd2 = promoted2.compartments[promoted2.compartments.length - 1]?.endMessage ?? 0;
|
|
172356
174004
|
if (lastCompartmentEnd2 > 0) {
|
|
@@ -172563,8 +174211,12 @@ Another process acquired the compartment-state lease before recomp could publish
|
|
|
172563
174211
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
172564
174212
|
await deps.ensureProjectRegistered?.(sessionDirectory, db);
|
|
172565
174213
|
const liveCompartments = getCompartments(db, sessionId);
|
|
172566
|
-
const
|
|
172567
|
-
|
|
174214
|
+
const chunksToEmbed = liveCompartments.map((c) => ({
|
|
174215
|
+
id: c.id,
|
|
174216
|
+
startMessage: c.startMessage,
|
|
174217
|
+
endMessage: c.endMessage
|
|
174218
|
+
}));
|
|
174219
|
+
embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed);
|
|
172568
174220
|
}
|
|
172569
174221
|
if (lastCompartmentEnd > 0) {
|
|
172570
174222
|
const markerUpdated = updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, deps.directory);
|
|
@@ -172745,8 +174397,12 @@ Could not acquire the compartment-state lease for this session.`;
|
|
|
172745
174397
|
if (deps.memoryEnabled !== false) {
|
|
172746
174398
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
172747
174399
|
const liveCompartments = getCompartments(db, sessionId);
|
|
172748
|
-
const
|
|
172749
|
-
|
|
174400
|
+
const chunksToEmbed = liveCompartments.map((c) => ({
|
|
174401
|
+
id: c.id,
|
|
174402
|
+
startMessage: c.startMessage,
|
|
174403
|
+
endMessage: c.endMessage
|
|
174404
|
+
}));
|
|
174405
|
+
Promise.resolve(deps.ensureProjectRegistered?.(sessionDirectory, db)).then(() => embedAndStoreCompartmentChunks(db, sessionId, projectIdentity, chunksToEmbed));
|
|
172750
174406
|
}
|
|
172751
174407
|
const lastEnd = merged[merged.length - 1]?.endMessage ?? snapEnd;
|
|
172752
174408
|
if (lastEnd > 0) {
|
|
@@ -174996,7 +176652,14 @@ function startCompartmentAgent(deps) {
|
|
|
174996
176652
|
return;
|
|
174997
176653
|
}
|
|
174998
176654
|
const renewal = startLeaseRenewal(deps, holderId);
|
|
174999
|
-
|
|
176655
|
+
let realRunStarted = false;
|
|
176656
|
+
const runnerDeps = withPublishedCallback({
|
|
176657
|
+
...deps,
|
|
176658
|
+
compartmentLeaseHolderId: holderId,
|
|
176659
|
+
onHistorianRunStarted: () => {
|
|
176660
|
+
realRunStarted = true;
|
|
176661
|
+
}
|
|
176662
|
+
});
|
|
175000
176663
|
const promise2 = runCompartmentAgent(runnerDeps).catch((err) => {
|
|
175001
176664
|
sessionLog(deps.sessionId, "compartment agent: unhandled rejection:", err);
|
|
175002
176665
|
try {
|
|
@@ -175010,6 +176673,9 @@ function startCompartmentAgent(deps) {
|
|
|
175010
176673
|
}
|
|
175011
176674
|
});
|
|
175012
176675
|
activeRuns.set(deps.sessionId, { promise: promise2, published: false });
|
|
176676
|
+
if (!realRunStarted && activeRuns.get(deps.sessionId)?.promise === promise2) {
|
|
176677
|
+
activeRuns.delete(deps.sessionId);
|
|
176678
|
+
}
|
|
175013
176679
|
}
|
|
175014
176680
|
async function executeContextRecompWithResult(deps, options = {}) {
|
|
175015
176681
|
const { sessionId } = deps;
|
|
@@ -175144,7 +176810,7 @@ function applyMemoryMigration(db, projectPath, result) {
|
|
|
175144
176810
|
inserted++;
|
|
175145
176811
|
}
|
|
175146
176812
|
if (removed > 0 || inserted > 0) {
|
|
175147
|
-
|
|
176813
|
+
bumpEpochsForWorkspaceMembers(db, projectPath);
|
|
175148
176814
|
}
|
|
175149
176815
|
})();
|
|
175150
176816
|
return { removed, inserted };
|
|
@@ -175444,6 +177110,11 @@ async function runManagedRecomp(ctx, sessionId, options) {
|
|
|
175444
177110
|
try {
|
|
175445
177111
|
const message = await executeContextRecomp(buildRecompDeps(ctx, sessionId), options);
|
|
175446
177112
|
const terminalPhase = isRecompSkip(message) ? "skipped" : isRecompFailure(message) ? "failed" : "done";
|
|
177113
|
+
if (terminalPhase === "done") {
|
|
177114
|
+
try {
|
|
177115
|
+
clearEmergencyRecovery(ctx.db, sessionId);
|
|
177116
|
+
} catch {}
|
|
177117
|
+
}
|
|
175447
177118
|
setRecompTerminal(ctx.liveSessionState, sessionId, terminalPhase, extractRecompReason(message));
|
|
175448
177119
|
return message;
|
|
175449
177120
|
} catch (error51) {
|
|
@@ -175542,6 +177213,7 @@ var RECOMP_DONE_GRACE_MS = 30000;
|
|
|
175542
177213
|
var init_recomp_orchestrator = __esm(async () => {
|
|
175543
177214
|
init_compartment_storage();
|
|
175544
177215
|
init_project_identity2();
|
|
177216
|
+
init_storage_meta_persisted();
|
|
175545
177217
|
await __promiseAll([
|
|
175546
177218
|
init_memory_migration(),
|
|
175547
177219
|
init_compartment_runner()
|
|
@@ -175602,15 +177274,15 @@ function shouldShowAnnouncement() {
|
|
|
175602
177274
|
}
|
|
175603
177275
|
return state.version !== ANNOUNCEMENT_VERSION;
|
|
175604
177276
|
}
|
|
175605
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
177277
|
+
var ANNOUNCEMENT_VERSION = "0.24.0", ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU", STATE_FILENAME = "last_announced_version";
|
|
175606
177278
|
var init_announcement = __esm(() => {
|
|
175607
177279
|
init_data_path();
|
|
175608
177280
|
ANNOUNCEMENT_FEATURES = [
|
|
175609
|
-
"
|
|
175610
|
-
"
|
|
175611
|
-
"
|
|
175612
|
-
"
|
|
175613
|
-
"
|
|
177281
|
+
"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).",
|
|
177282
|
+
"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.",
|
|
177283
|
+
"Pi: fixed sessions overflowing the model context while still showing moderate usage — Pi now sheds context before a tool-heavy turn overflows.",
|
|
177284
|
+
"Fewer prompt-cache busts: doc edits, processed screenshots, and a rebuild-then-bust-again case no longer re-bill large prompt prefixes.",
|
|
177285
|
+
"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)."
|
|
175614
177286
|
];
|
|
175615
177287
|
});
|
|
175616
177288
|
|
|
@@ -176404,6 +178076,10 @@ function getMagicContextBuiltinCommands() {
|
|
|
176404
178076
|
"ctx-dream": {
|
|
176405
178077
|
template: "ctx-dream",
|
|
176406
178078
|
description: "Run the hidden dreamer maintenance pass for this project now"
|
|
178079
|
+
},
|
|
178080
|
+
"ctx-embed-history": {
|
|
178081
|
+
template: "ctx-embed-history",
|
|
178082
|
+
description: "Embed all of this session's history compartments for semantic search, in one pass"
|
|
176407
178083
|
}
|
|
176408
178084
|
};
|
|
176409
178085
|
}
|
|
@@ -176897,7 +178573,7 @@ await init_storage_db();
|
|
|
176897
178573
|
// src/features/magic-context/v22-deferred-backfill.ts
|
|
176898
178574
|
init_logger();
|
|
176899
178575
|
init_project_identity();
|
|
176900
|
-
import { createHash as
|
|
178576
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
176901
178577
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
176902
178578
|
import path5 from "node:path";
|
|
176903
178579
|
var BATCH_SIZE = 25;
|
|
@@ -176951,7 +178627,7 @@ function computeLegacyRustDirIdentity(rawProjectPath) {
|
|
|
176951
178627
|
} catch {
|
|
176952
178628
|
canonical = path5.isAbsolute(rawProjectPath) ? rawProjectPath : path5.join(process.cwd(), rawProjectPath);
|
|
176953
178629
|
}
|
|
176954
|
-
return `dir:${
|
|
178630
|
+
return `dir:${createHash6("sha256").update(canonical, "utf8").digest("hex")}`;
|
|
176955
178631
|
}
|
|
176956
178632
|
function upsertRekeyMap(db, oldProjectPath, newProjectPath, rekeyedAt) {
|
|
176957
178633
|
db.prepare(`INSERT INTO v22_identity_rekey_map (old_project_path, new_project_path, rekeyed_at)
|
|
@@ -180089,7 +181765,7 @@ init_project_identity();
|
|
|
180089
181765
|
// src/plugin/embedding-bootstrap-helpers.ts
|
|
180090
181766
|
init_embedding();
|
|
180091
181767
|
init_logger();
|
|
180092
|
-
import { createHash as
|
|
181768
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
180093
181769
|
var EMBEDDING_AFFECTING_KEYS = new Set([
|
|
180094
181770
|
"embedding.api_key",
|
|
180095
181771
|
"embedding.endpoint",
|
|
@@ -180110,7 +181786,7 @@ var EMBEDDING_WARNING_TERMS = [
|
|
|
180110
181786
|
];
|
|
180111
181787
|
var loggedFailureSignatures = new Map;
|
|
180112
181788
|
function sha256Prefix2(value, length = 16) {
|
|
180113
|
-
return
|
|
181789
|
+
return createHash10("sha256").update(value).digest("hex").slice(0, length);
|
|
180114
181790
|
}
|
|
180115
181791
|
function warningLooksEmbeddingRelated(message) {
|
|
180116
181792
|
const lower = message.toLowerCase();
|
|
@@ -180747,6 +182423,7 @@ function createTagger() {
|
|
|
180747
182423
|
// src/hooks/magic-context/hook.ts
|
|
180748
182424
|
init_magic_context();
|
|
180749
182425
|
init_project_identity();
|
|
182426
|
+
init_project_embedding_registry();
|
|
180750
182427
|
await init_storage();
|
|
180751
182428
|
init_logger();
|
|
180752
182429
|
init_resolve_fallbacks();
|
|
@@ -181340,6 +183017,7 @@ function createMagicContextCommandHandler(deps) {
|
|
|
181340
183017
|
const isAugCommand = (command) => command === "ctx-aug";
|
|
181341
183018
|
const isDreamCommand = (command) => command === "ctx-dream";
|
|
181342
183019
|
const isSessionUpgradeCommand = (command) => command === "ctx-session-upgrade";
|
|
183020
|
+
const isEmbedHistoryCommand = (command) => command === "ctx-embed-history";
|
|
181343
183021
|
return {
|
|
181344
183022
|
"command.execute.before": async (input, _output, _params) => {
|
|
181345
183023
|
const isStatus = isStatusCommand(input.command);
|
|
@@ -181348,7 +183026,8 @@ function createMagicContextCommandHandler(deps) {
|
|
|
181348
183026
|
const isAug = isAugCommand(input.command);
|
|
181349
183027
|
const isDream = isDreamCommand(input.command);
|
|
181350
183028
|
const isSessionUpgrade = isSessionUpgradeCommand(input.command);
|
|
181351
|
-
|
|
183029
|
+
const isEmbedHistory = isEmbedHistoryCommand(input.command);
|
|
183030
|
+
if (!isStatus && !isFlush && !isRecomp && !isAug && !isDream && !isSessionUpgrade && !isEmbedHistory) {
|
|
181352
183031
|
return;
|
|
181353
183032
|
}
|
|
181354
183033
|
const sessionId = input.sessionID;
|
|
@@ -181361,6 +183040,11 @@ function createMagicContextCommandHandler(deps) {
|
|
|
181361
183040
|
await executeDreaming(deps, sessionId);
|
|
181362
183041
|
return;
|
|
181363
183042
|
}
|
|
183043
|
+
if (isEmbedHistory) {
|
|
183044
|
+
const summary = deps.executeEmbedHistory ? await deps.executeEmbedHistory(sessionId) : "Semantic embedding is not configured for this project, so there is nothing to embed.";
|
|
183045
|
+
await deps.sendNotification(sessionId, summary, {});
|
|
183046
|
+
throwSentinel(input.command);
|
|
183047
|
+
}
|
|
181364
183048
|
if (isFlush) {
|
|
181365
183049
|
result = executeFlush(deps.db, sessionId);
|
|
181366
183050
|
clearCachedM0M1(deps.db, sessionId);
|
|
@@ -181728,8 +183412,8 @@ var CHANNEL1_SENTINEL = "<system-reminder>";
|
|
|
181728
183412
|
var TOKENS_PER_BYTE = 0.25;
|
|
181729
183413
|
var CHANNEL1_FLOOR_TOKENS = 1e4;
|
|
181730
183414
|
var CHANNEL1_REFIRE_FLOOR_TOKENS = 1e4;
|
|
181731
|
-
function channel1RefireTokens(
|
|
181732
|
-
const scaled = Math.round(0.05 * Math.max(0,
|
|
183415
|
+
function channel1RefireTokens(workingWindowTokens) {
|
|
183416
|
+
const scaled = Math.round(0.05 * Math.max(0, workingWindowTokens));
|
|
181733
183417
|
return Math.max(CHANNEL1_REFIRE_FLOOR_TOKENS, scaled);
|
|
181734
183418
|
}
|
|
181735
183419
|
var S_GENTLE = 0.2;
|
|
@@ -181799,7 +183483,7 @@ function computeTailTokenEstimate(messages) {
|
|
|
181799
183483
|
};
|
|
181800
183484
|
}
|
|
181801
183485
|
function decideChannel1(input) {
|
|
181802
|
-
const { undroppedTokens, pressure,
|
|
183486
|
+
const { undroppedTokens, pressure, workingWindowTokens, hasRecentReduce } = input;
|
|
181803
183487
|
const resetCycle = hasRecentReduce || undroppedTokens < input.lastNudgeUndropped;
|
|
181804
183488
|
const lastNudge = resetCycle ? 0 : input.lastNudgeUndropped;
|
|
181805
183489
|
const lastLevel = resetCycle ? "" : input.lastNudgeLevel;
|
|
@@ -181814,7 +183498,7 @@ function decideChannel1(input) {
|
|
|
181814
183498
|
return quiet();
|
|
181815
183499
|
if (undroppedTokens < CHANNEL1_FLOOR_TOKENS)
|
|
181816
183500
|
return quiet();
|
|
181817
|
-
const budget =
|
|
183501
|
+
const budget = workingWindowTokens > 0 ? workingWindowTokens : undroppedTokens || 1;
|
|
181818
183502
|
const severity = undroppedTokens / budget * pressure;
|
|
181819
183503
|
if (severity < S_GENTLE)
|
|
181820
183504
|
return quiet();
|
|
@@ -181826,7 +183510,7 @@ function decideChannel1(input) {
|
|
|
181826
183510
|
else
|
|
181827
183511
|
level = "gentle";
|
|
181828
183512
|
if (lastLevel === "") {
|
|
181829
|
-
if (undroppedTokens < lastNudge + channel1RefireTokens(
|
|
183513
|
+
if (undroppedTokens < lastNudge + channel1RefireTokens(workingWindowTokens)) {
|
|
181830
183514
|
return quiet();
|
|
181831
183515
|
}
|
|
181832
183516
|
} else if (LEVEL_RANK[level] <= LEVEL_RANK[lastLevel]) {
|
|
@@ -181871,13 +183555,13 @@ function buildChannel1Reminder(level, undroppedTokens) {
|
|
|
181871
183555
|
let body;
|
|
181872
183556
|
switch (level) {
|
|
181873
183557
|
case "gentle":
|
|
181874
|
-
body = `You have ~${amount} tokens of tool output you have not reduced. ` + `
|
|
183558
|
+
body = `You have ~${amount} tokens of tool output you have not reduced. ` + `When you are done with earlier outputs, dropping them with ctx_reduce keeps context lean.`;
|
|
181875
183559
|
break;
|
|
181876
183560
|
case "firm":
|
|
181877
|
-
body = `~${amount} tokens of unreduced tool output
|
|
183561
|
+
body = `~${amount} tokens of unreduced tool output has built up. ` + `At your next natural stopping point, consider dropping what you have already processed with ctx_reduce.`;
|
|
181878
183562
|
break;
|
|
181879
183563
|
case "urgent":
|
|
181880
|
-
body = `~${amount} tokens of unreduced tool output remain
|
|
183564
|
+
body = `~${amount} tokens of unreduced tool output remain, and a large span of this session will be comparted before long. ` + `Consider dropping spent outputs with ctx_reduce so the archived span is the part that matters.`;
|
|
181881
183565
|
break;
|
|
181882
183566
|
}
|
|
181883
183567
|
return `
|
|
@@ -182101,6 +183785,7 @@ await init_read_session_chunk();
|
|
|
182101
183785
|
// src/hooks/magic-context/transform.ts
|
|
182102
183786
|
init_project_identity();
|
|
182103
183787
|
import * as crypto2 from "node:crypto";
|
|
183788
|
+
init_session_project_storage();
|
|
182104
183789
|
init_storage_meta_persisted();
|
|
182105
183790
|
init_logger();
|
|
182106
183791
|
await init_storage();
|
|
@@ -182701,6 +184386,7 @@ await __promiseAll([
|
|
|
182701
184386
|
init_read_session_chunk(),
|
|
182702
184387
|
init_read_session_db()
|
|
182703
184388
|
]);
|
|
184389
|
+
|
|
182704
184390
|
// src/hooks/magic-context/sentinel.ts
|
|
182705
184391
|
var WHOLE_MESSAGE_PLACEHOLDER_TEXT = "[dropped]";
|
|
182706
184392
|
function modelAcceptsEmptyContent(providerID) {
|
|
@@ -182758,7 +184444,6 @@ function replaySentinelByMessageIds(messages, ids, providerID) {
|
|
|
182758
184444
|
missingIds.push(id);
|
|
182759
184445
|
return { replayed, missingIds };
|
|
182760
184446
|
}
|
|
182761
|
-
|
|
182762
184447
|
// src/hooks/magic-context/strip-content.ts
|
|
182763
184448
|
var DROPPED_PLACEHOLDER_PATTERN = /^\[dropped §\d+§\]$/;
|
|
182764
184449
|
var TAG_PREFIX_PATTERN = /^§\d+§\s*/;
|
|
@@ -183111,8 +184796,10 @@ function stripReasoningFromMergedAssistants(messages, providerID) {
|
|
|
183111
184796
|
}
|
|
183112
184797
|
return stripped;
|
|
183113
184798
|
}
|
|
183114
|
-
function stripProcessedImages(messages,
|
|
184799
|
+
function stripProcessedImages(messages, frozenIds, options) {
|
|
184800
|
+
const { detect, watermark, messageTagNumbers } = options;
|
|
183115
184801
|
let stripped = 0;
|
|
184802
|
+
const newlyStrippedIds = [];
|
|
183116
184803
|
let hasAssistantResponse = false;
|
|
183117
184804
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
183118
184805
|
const msg = messages[i];
|
|
@@ -183120,13 +184807,17 @@ function stripProcessedImages(messages, watermark, messageTagNumbers) {
|
|
|
183120
184807
|
hasAssistantResponse = true;
|
|
183121
184808
|
continue;
|
|
183122
184809
|
}
|
|
183123
|
-
if (msg.info.role !== "user"
|
|
184810
|
+
if (msg.info.role !== "user") {
|
|
183124
184811
|
continue;
|
|
183125
184812
|
}
|
|
184813
|
+
const id = typeof msg.info.id === "string" ? msg.info.id : undefined;
|
|
184814
|
+
const inFrozen = id !== undefined && frozenIds.has(id);
|
|
183126
184815
|
const maxTag = messageTagNumbers.get(msg) ?? 0;
|
|
183127
|
-
|
|
184816
|
+
const isNewDetection = !inFrozen && detect && hasAssistantResponse && id !== undefined && maxTag <= watermark;
|
|
184817
|
+
if (!inFrozen && !isNewDetection) {
|
|
183128
184818
|
continue;
|
|
183129
184819
|
}
|
|
184820
|
+
let touchedThisMsg = false;
|
|
183130
184821
|
for (let j = 0;j < msg.parts.length; j++) {
|
|
183131
184822
|
const part = msg.parts[j];
|
|
183132
184823
|
if (!isRecord(part) || part.type !== "file") {
|
|
@@ -183138,10 +184829,14 @@ function stripProcessedImages(messages, watermark, messageTagNumbers) {
|
|
|
183138
184829
|
if (typeof part.url === "string" && part.url.startsWith("data:") && part.url.length > 200) {
|
|
183139
184830
|
msg.parts[j] = makeSentinel(part);
|
|
183140
184831
|
stripped++;
|
|
184832
|
+
touchedThisMsg = true;
|
|
183141
184833
|
}
|
|
183142
184834
|
}
|
|
184835
|
+
if (touchedThisMsg && isNewDetection && id !== undefined) {
|
|
184836
|
+
newlyStrippedIds.push(id);
|
|
184837
|
+
}
|
|
183143
184838
|
}
|
|
183144
|
-
return stripped;
|
|
184839
|
+
return { stripped, newlyStrippedIds };
|
|
183145
184840
|
}
|
|
183146
184841
|
|
|
183147
184842
|
// src/hooks/magic-context/transform.ts
|
|
@@ -183454,8 +185149,55 @@ function appendReminderToUserMessage(message, reminder) {
|
|
|
183454
185149
|
}
|
|
183455
185150
|
|
|
183456
185151
|
// src/hooks/magic-context/apply-operations.ts
|
|
183457
|
-
init_tag_part_guards();
|
|
183458
185152
|
await init_storage();
|
|
185153
|
+
|
|
185154
|
+
// src/hooks/magic-context/system-injection-stripper.ts
|
|
185155
|
+
var SYSTEM_INJECTION_MARKERS = [
|
|
185156
|
+
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
185157
|
+
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
185158
|
+
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
185159
|
+
"[Category+Skill Reminder]",
|
|
185160
|
+
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
185161
|
+
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
185162
|
+
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
185163
|
+
"Unstable background agent appears idle",
|
|
185164
|
+
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
185165
|
+
];
|
|
185166
|
+
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
185167
|
+
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
185168
|
+
function stripSystemInjection(text) {
|
|
185169
|
+
let hasInjection = false;
|
|
185170
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
185171
|
+
if (text.includes(marker)) {
|
|
185172
|
+
hasInjection = true;
|
|
185173
|
+
break;
|
|
185174
|
+
}
|
|
185175
|
+
}
|
|
185176
|
+
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
185177
|
+
hasInjection = true;
|
|
185178
|
+
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
185179
|
+
if (!hasInjection)
|
|
185180
|
+
return null;
|
|
185181
|
+
let cleaned = text;
|
|
185182
|
+
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
185183
|
+
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
185184
|
+
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
185185
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
185186
|
+
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
185187
|
+
continue;
|
|
185188
|
+
const idx = cleaned.indexOf(marker);
|
|
185189
|
+
if (idx === -1)
|
|
185190
|
+
continue;
|
|
185191
|
+
const blockEnd = cleaned.indexOf(`
|
|
185192
|
+
|
|
185193
|
+
`, idx + marker.length);
|
|
185194
|
+
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
185195
|
+
}
|
|
185196
|
+
return cleaned.trim();
|
|
185197
|
+
}
|
|
185198
|
+
|
|
185199
|
+
// src/hooks/magic-context/apply-operations.ts
|
|
185200
|
+
init_tag_part_guards();
|
|
183459
185201
|
var USER_DROP_PREVIEW_CHARS = 250;
|
|
183460
185202
|
var RECENT_TOOL_SKELETON_WINDOW = 20;
|
|
183461
185203
|
function buildReplacementContent(tagId, target) {
|
|
@@ -183464,6 +185206,10 @@ function buildReplacementContent(tagId, target) {
|
|
|
183464
185206
|
return `[dropped §${tagId}§]`;
|
|
183465
185207
|
}
|
|
183466
185208
|
const currentContent = target.getContent?.() ?? "";
|
|
185209
|
+
const strippedInjection = stripSystemInjection(currentContent);
|
|
185210
|
+
if (strippedInjection !== null && stripTagPrefix(strippedInjection).trim().length === 0) {
|
|
185211
|
+
return `[dropped §${tagId}§]`;
|
|
185212
|
+
}
|
|
183467
185213
|
const originalText = stripTagPrefix(currentContent);
|
|
183468
185214
|
if (originalText.length <= USER_DROP_PREVIEW_CHARS) {
|
|
183469
185215
|
return `[truncated §${tagId}§]
|
|
@@ -184084,6 +185830,7 @@ init_embedding();
|
|
|
184084
185830
|
|
|
184085
185831
|
// src/features/magic-context/search.ts
|
|
184086
185832
|
init_logger();
|
|
185833
|
+
init_compartment_chunk_embedding();
|
|
184087
185834
|
|
|
184088
185835
|
// src/features/magic-context/literal-probes.ts
|
|
184089
185836
|
var MAX_PROBES = 5;
|
|
@@ -184145,6 +185892,7 @@ function containsProbeVerbatim(text, probes) {
|
|
|
184145
185892
|
init_memory();
|
|
184146
185893
|
init_embedding();
|
|
184147
185894
|
init_storage_memory_fts();
|
|
185895
|
+
init_workspaces();
|
|
184148
185896
|
var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
|
|
184149
185897
|
var FTS_SEMANTIC_CANDIDATE_LIMIT = 50;
|
|
184150
185898
|
var SEMANTIC_WEIGHT = 0.7;
|
|
@@ -184174,6 +185922,37 @@ function previewText(text) {
|
|
|
184174
185922
|
}
|
|
184175
185923
|
return `${normalized.slice(0, RESULT_PREVIEW_LIMIT - 1).trimEnd()}…`;
|
|
184176
185924
|
}
|
|
185925
|
+
function resolveSearchWorkspaceContext(db, projectPath, identitySet) {
|
|
185926
|
+
const resolved = identitySet ?? resolveWorkspaceIdentitySet(db, projectPath);
|
|
185927
|
+
const isWorkspaced = resolved.identities.length > 1;
|
|
185928
|
+
const expanded = expandWorkspaceIdentitySetWithAliases(db, resolved.identities);
|
|
185929
|
+
const expandedIdentities = isWorkspaced ? expanded.expandedIdentities : resolved.identities;
|
|
185930
|
+
const canonicalIdentityByStoredPath = isWorkspaced ? expanded.canonicalIdentityByStoredPath : new Map(resolved.identities.map((identity) => [identity, identity]));
|
|
185931
|
+
const ownIdentities = expandedIdentities.filter((identity) => canonicalIdentityByStoredPath.get(identity) === projectPath);
|
|
185932
|
+
return {
|
|
185933
|
+
identities: resolved.identities,
|
|
185934
|
+
expandedIdentities,
|
|
185935
|
+
ownIdentities,
|
|
185936
|
+
shareCategories: isWorkspaced ? resolveWorkspaceShareCategories(db, projectPath) : null,
|
|
185937
|
+
namesByIdentity: resolved.namesByIdentity,
|
|
185938
|
+
canonicalIdentityByStoredPath,
|
|
185939
|
+
isWorkspaced
|
|
185940
|
+
};
|
|
185941
|
+
}
|
|
185942
|
+
function memoryWorkspaceIdentity(memory, workspace) {
|
|
185943
|
+
return resolveStoredPathWorkspaceIdentity(memory.projectPath, workspace.identities, workspace.canonicalIdentityByStoredPath);
|
|
185944
|
+
}
|
|
185945
|
+
function sourceNamesForSearchMemories(args) {
|
|
185946
|
+
if (!args.workspace.isWorkspaced)
|
|
185947
|
+
return;
|
|
185948
|
+
const sourceNames = new Map;
|
|
185949
|
+
for (const memory of args.memories) {
|
|
185950
|
+
const source = sourceNameForMemory(memory.projectPath, args.projectPath, args.workspace.identities, args.workspace.namesByIdentity, args.workspace.canonicalIdentityByStoredPath);
|
|
185951
|
+
if (source)
|
|
185952
|
+
sourceNames.set(memory.id, source);
|
|
185953
|
+
}
|
|
185954
|
+
return sourceNames.size > 0 ? sourceNames : undefined;
|
|
185955
|
+
}
|
|
184177
185956
|
function getMessageSearchStatement(db) {
|
|
184178
185957
|
let stmt = messageSearchStatements.get(db);
|
|
184179
185958
|
if (!stmt) {
|
|
@@ -184182,6 +185961,30 @@ function getMessageSearchStatement(db) {
|
|
|
184182
185961
|
}
|
|
184183
185962
|
return stmt;
|
|
184184
185963
|
}
|
|
185964
|
+
var ftsRowCountStatements = new WeakMap;
|
|
185965
|
+
var ftsMatchCountStatements = new WeakMap;
|
|
185966
|
+
function getSessionFtsRowCount(db, sessionId) {
|
|
185967
|
+
let stmt = ftsRowCountStatements.get(db);
|
|
185968
|
+
if (!stmt) {
|
|
185969
|
+
stmt = db.prepare("SELECT COUNT(*) AS n FROM message_history_fts WHERE session_id = ?");
|
|
185970
|
+
ftsRowCountStatements.set(db, stmt);
|
|
185971
|
+
}
|
|
185972
|
+
const row = stmt.get(sessionId);
|
|
185973
|
+
return typeof row?.n === "number" ? row.n : 0;
|
|
185974
|
+
}
|
|
185975
|
+
function countSessionFtsMatches(db, sessionId, ftsQuery) {
|
|
185976
|
+
let stmt = ftsMatchCountStatements.get(db);
|
|
185977
|
+
if (!stmt) {
|
|
185978
|
+
stmt = db.prepare("SELECT COUNT(*) AS n FROM message_history_fts WHERE session_id = ? AND message_history_fts MATCH ?");
|
|
185979
|
+
ftsMatchCountStatements.set(db, stmt);
|
|
185980
|
+
}
|
|
185981
|
+
try {
|
|
185982
|
+
const row = stmt.get(sessionId, ftsQuery);
|
|
185983
|
+
return typeof row?.n === "number" ? row.n : 0;
|
|
185984
|
+
} catch {
|
|
185985
|
+
return 0;
|
|
185986
|
+
}
|
|
185987
|
+
}
|
|
184185
185988
|
function getMessageOrdinal(value) {
|
|
184186
185989
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
184187
185990
|
return value;
|
|
@@ -184197,25 +186000,63 @@ async function getSemanticScores(args) {
|
|
|
184197
186000
|
if (!args.queryEmbedding || args.memories.length === 0) {
|
|
184198
186001
|
return semanticScores;
|
|
184199
186002
|
}
|
|
184200
|
-
|
|
184201
|
-
|
|
184202
|
-
|
|
184203
|
-
|
|
184204
|
-
|
|
184205
|
-
|
|
184206
|
-
|
|
186003
|
+
if (!args.workspace?.isWorkspaced) {
|
|
186004
|
+
const cachedEmbeddings = getProjectEmbeddings(args.db, args.projectPath);
|
|
186005
|
+
const embeddings = await ensureMemoryEmbeddings({
|
|
186006
|
+
db: args.db,
|
|
186007
|
+
projectIdentity: args.projectPath,
|
|
186008
|
+
memories: args.memories,
|
|
186009
|
+
existingEmbeddings: cachedEmbeddings
|
|
186010
|
+
});
|
|
186011
|
+
for (const memory of args.memories) {
|
|
186012
|
+
const memoryEmbedding = embeddings.get(memory.id);
|
|
186013
|
+
if (!memoryEmbedding) {
|
|
186014
|
+
continue;
|
|
186015
|
+
}
|
|
186016
|
+
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding.embedding)));
|
|
186017
|
+
}
|
|
186018
|
+
return semanticScores;
|
|
186019
|
+
}
|
|
186020
|
+
if (!args.queryModelId || args.queryModelId === "off") {
|
|
186021
|
+
return semanticScores;
|
|
186022
|
+
}
|
|
186023
|
+
const workspace = args.workspace;
|
|
186024
|
+
const memoriesByIdentity = new Map;
|
|
184207
186025
|
for (const memory of args.memories) {
|
|
184208
|
-
const
|
|
184209
|
-
if (!
|
|
186026
|
+
const identity = memoryWorkspaceIdentity(memory, workspace);
|
|
186027
|
+
if (!identity)
|
|
186028
|
+
continue;
|
|
186029
|
+
const list = memoriesByIdentity.get(identity) ?? [];
|
|
186030
|
+
list.push(memory);
|
|
186031
|
+
memoriesByIdentity.set(identity, list);
|
|
186032
|
+
}
|
|
186033
|
+
const ownMemories = memoriesByIdentity.get(args.projectPath) ?? [];
|
|
186034
|
+
if (ownMemories.length > 0) {
|
|
186035
|
+
const ownEmbeddings = getProjectEmbeddings(args.db, args.projectPath);
|
|
186036
|
+
await ensureMemoryEmbeddings({
|
|
186037
|
+
db: args.db,
|
|
186038
|
+
projectIdentity: args.projectPath,
|
|
186039
|
+
memories: ownMemories,
|
|
186040
|
+
existingEmbeddings: ownEmbeddings
|
|
186041
|
+
});
|
|
186042
|
+
}
|
|
186043
|
+
for (const identity of workspace.identities) {
|
|
186044
|
+
const memberMemories = memoriesByIdentity.get(identity) ?? [];
|
|
186045
|
+
if (memberMemories.length === 0)
|
|
184210
186046
|
continue;
|
|
186047
|
+
const cachedEmbeddings = getProjectEmbeddings(args.db, identity);
|
|
186048
|
+
for (const memory of memberMemories) {
|
|
186049
|
+
const memoryEmbedding = cachedEmbeddings.get(memory.id);
|
|
186050
|
+
if (!memoryEmbedding || memoryEmbedding.modelId !== args.queryModelId)
|
|
186051
|
+
continue;
|
|
186052
|
+
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding.embedding)));
|
|
184211
186053
|
}
|
|
184212
|
-
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding)));
|
|
184213
186054
|
}
|
|
184214
186055
|
return semanticScores;
|
|
184215
186056
|
}
|
|
184216
186057
|
function getFtsMatches(args) {
|
|
184217
186058
|
try {
|
|
184218
|
-
return searchMemoriesFTS(args.db, args.projectPath, args.query, args.limit);
|
|
186059
|
+
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);
|
|
184219
186060
|
} catch (error51) {
|
|
184220
186061
|
log(`[search] FTS query failed for "${args.query}": ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
184221
186062
|
return [];
|
|
@@ -184229,8 +186070,11 @@ function selectSemanticCandidates(args) {
|
|
|
184229
186070
|
return args.memories;
|
|
184230
186071
|
}
|
|
184231
186072
|
const candidateIds = new Set(args.ftsMatches.map((memory) => memory.id));
|
|
184232
|
-
const
|
|
184233
|
-
|
|
186073
|
+
const embeddingProjects = args.workspace?.isWorkspaced ? args.workspace.identities : [args.projectPath];
|
|
186074
|
+
for (const projectPath of embeddingProjects) {
|
|
186075
|
+
const cachedEmbeddings = peekProjectEmbeddings(projectPath);
|
|
186076
|
+
if (!cachedEmbeddings)
|
|
186077
|
+
continue;
|
|
184234
186078
|
for (const memoryId of cachedEmbeddings.keys()) {
|
|
184235
186079
|
candidateIds.add(memoryId);
|
|
184236
186080
|
}
|
|
@@ -184272,7 +186116,8 @@ function mergeMemoryResults(args) {
|
|
|
184272
186116
|
score,
|
|
184273
186117
|
memoryId: memory.id,
|
|
184274
186118
|
category: memory.category,
|
|
184275
|
-
matchType
|
|
186119
|
+
matchType,
|
|
186120
|
+
sourceName: args.sourceNameByMemoryId?.get(memory.id)
|
|
184276
186121
|
});
|
|
184277
186122
|
}
|
|
184278
186123
|
return results.sort((left, right) => {
|
|
@@ -184286,7 +186131,7 @@ async function searchMemories(args) {
|
|
|
184286
186131
|
if (!args.memoryEnabled) {
|
|
184287
186132
|
return [];
|
|
184288
186133
|
}
|
|
184289
|
-
const memories = getMemoriesByProject(args.db, args.projectPath);
|
|
186134
|
+
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);
|
|
184290
186135
|
if (memories.length === 0) {
|
|
184291
186136
|
return [];
|
|
184292
186137
|
}
|
|
@@ -184294,26 +186139,43 @@ async function searchMemories(args) {
|
|
|
184294
186139
|
db: args.db,
|
|
184295
186140
|
projectPath: args.projectPath,
|
|
184296
186141
|
query: args.query,
|
|
184297
|
-
limit: FTS_SEMANTIC_CANDIDATE_LIMIT
|
|
186142
|
+
limit: FTS_SEMANTIC_CANDIDATE_LIMIT,
|
|
186143
|
+
workspace: args.workspace
|
|
184298
186144
|
});
|
|
184299
186145
|
const ftsScores = getFtsScores(ftsMatches);
|
|
184300
186146
|
const semanticCandidates = selectSemanticCandidates({
|
|
184301
186147
|
memories,
|
|
184302
186148
|
projectPath: args.projectPath,
|
|
184303
|
-
ftsMatches
|
|
186149
|
+
ftsMatches,
|
|
186150
|
+
workspace: args.workspace
|
|
184304
186151
|
});
|
|
184305
186152
|
const semanticScores = await getSemanticScores({
|
|
184306
186153
|
db: args.db,
|
|
184307
186154
|
projectPath: args.projectPath,
|
|
184308
186155
|
memories: semanticCandidates,
|
|
184309
|
-
queryEmbedding: args.queryEmbedding
|
|
186156
|
+
queryEmbedding: args.queryEmbedding,
|
|
186157
|
+
queryModelId: args.queryModelId,
|
|
186158
|
+
workspace: args.workspace
|
|
184310
186159
|
});
|
|
184311
186160
|
return mergeMemoryResults({
|
|
184312
186161
|
memories,
|
|
184313
186162
|
semanticScores,
|
|
184314
186163
|
ftsScores,
|
|
184315
186164
|
limit: args.limit,
|
|
184316
|
-
visibleMemoryIds: args.visibleMemoryIds
|
|
186165
|
+
visibleMemoryIds: args.visibleMemoryIds,
|
|
186166
|
+
sourceNameByMemoryId: sourceNamesForSearchMemories({
|
|
186167
|
+
memories,
|
|
186168
|
+
projectPath: args.projectPath,
|
|
186169
|
+
workspace: args.workspace ?? {
|
|
186170
|
+
identities: [args.projectPath],
|
|
186171
|
+
expandedIdentities: [args.projectPath],
|
|
186172
|
+
namesByIdentity: new Map,
|
|
186173
|
+
canonicalIdentityByStoredPath: new Map([[args.projectPath, args.projectPath]]),
|
|
186174
|
+
ownIdentities: [args.projectPath],
|
|
186175
|
+
shareCategories: null,
|
|
186176
|
+
isWorkspaced: false
|
|
186177
|
+
}
|
|
186178
|
+
})
|
|
184317
186179
|
});
|
|
184318
186180
|
}
|
|
184319
186181
|
function linearDecayScore(rank, total) {
|
|
@@ -184344,7 +186206,13 @@ function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff) {
|
|
|
184344
186206
|
return result;
|
|
184345
186207
|
}
|
|
184346
186208
|
var RRF_K = 60;
|
|
184347
|
-
var
|
|
186209
|
+
var VERBATIM_RANK_BONUS = 1 / RRF_K;
|
|
186210
|
+
var IDF_FALLOFF = 100;
|
|
186211
|
+
function probeDiscriminationWeight(df, corpusSize) {
|
|
186212
|
+
if (corpusSize <= 0 || df <= 0)
|
|
186213
|
+
return 1;
|
|
186214
|
+
return 1 / (1 + IDF_FALLOFF * df / corpusSize);
|
|
186215
|
+
}
|
|
184348
186216
|
function searchMessages(args) {
|
|
184349
186217
|
const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
|
|
184350
186218
|
const fetchLimit = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.limit * 3 : args.limit;
|
|
@@ -184361,20 +186229,31 @@ function searchMessages(args) {
|
|
|
184361
186229
|
role: row.role
|
|
184362
186230
|
}));
|
|
184363
186231
|
}
|
|
186232
|
+
const corpusSize = getSessionFtsRowCount(args.db, args.sessionId);
|
|
184364
186233
|
const queryLists = [];
|
|
184365
186234
|
if (baseQuery.length > 0) {
|
|
184366
|
-
queryLists.push(
|
|
186235
|
+
queryLists.push({
|
|
186236
|
+
rows: runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff),
|
|
186237
|
+
weight: 1
|
|
186238
|
+
});
|
|
184367
186239
|
}
|
|
186240
|
+
const probeWeights = new Map;
|
|
184368
186241
|
for (const probe of probes) {
|
|
184369
186242
|
const probeQuery = sanitizeFtsQuery(probe);
|
|
184370
186243
|
if (probeQuery.length === 0)
|
|
184371
186244
|
continue;
|
|
184372
|
-
|
|
186245
|
+
const df = countSessionFtsMatches(args.db, args.sessionId, probeQuery);
|
|
186246
|
+
const weight = probeDiscriminationWeight(df, corpusSize);
|
|
186247
|
+
probeWeights.set(probe, weight);
|
|
186248
|
+
queryLists.push({
|
|
186249
|
+
rows: runMessageFtsQuery(args.db, args.sessionId, probeQuery, fetchLimit, cutoff),
|
|
186250
|
+
weight
|
|
186251
|
+
});
|
|
184373
186252
|
}
|
|
184374
186253
|
const fused = new Map;
|
|
184375
186254
|
for (const list of queryLists) {
|
|
184376
|
-
list.forEach((row, rank) => {
|
|
184377
|
-
const rrf =
|
|
186255
|
+
list.rows.forEach((row, rank) => {
|
|
186256
|
+
const rrf = list.weight / (RRF_K + rank);
|
|
184378
186257
|
const existing = fused.get(row.messageId);
|
|
184379
186258
|
if (existing) {
|
|
184380
186259
|
existing.score += rrf;
|
|
@@ -184384,26 +186263,107 @@ function searchMessages(args) {
|
|
|
184384
186263
|
});
|
|
184385
186264
|
}
|
|
184386
186265
|
for (const entry of fused.values()) {
|
|
184387
|
-
|
|
184388
|
-
|
|
186266
|
+
let best = 0;
|
|
186267
|
+
for (const probe of probes) {
|
|
186268
|
+
const weight = probeWeights.get(probe) ?? 0;
|
|
186269
|
+
if (weight > best && containsProbeVerbatim(entry.row.content, [probe])) {
|
|
186270
|
+
best = weight;
|
|
186271
|
+
}
|
|
186272
|
+
}
|
|
186273
|
+
if (best > 0) {
|
|
186274
|
+
entry.score += best * VERBATIM_RANK_BONUS;
|
|
184389
186275
|
}
|
|
184390
186276
|
}
|
|
184391
186277
|
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);
|
|
184392
|
-
|
|
184393
|
-
return ranked.map((entry) => ({
|
|
186278
|
+
return ranked.map((entry, rank) => ({
|
|
184394
186279
|
source: "message",
|
|
184395
186280
|
content: previewText(entry.row.content),
|
|
184396
|
-
score:
|
|
186281
|
+
score: linearDecayScore(rank, ranked.length),
|
|
184397
186282
|
messageOrdinal: entry.row.messageOrdinal,
|
|
184398
186283
|
messageId: entry.row.messageId,
|
|
184399
186284
|
role: entry.row.role
|
|
184400
186285
|
}));
|
|
184401
186286
|
}
|
|
186287
|
+
function searchCompartmentChunks(args) {
|
|
186288
|
+
if (!args.queryEmbedding || args.limit <= 0)
|
|
186289
|
+
return [];
|
|
186290
|
+
const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
|
|
186291
|
+
const rows = loadCompartmentChunkEmbeddingsForSearch(args.db, args.sessionId, args.projectPath, args.modelId);
|
|
186292
|
+
if (rows.length === 0)
|
|
186293
|
+
return [];
|
|
186294
|
+
const byCompartment = new Map;
|
|
186295
|
+
for (const row of rows) {
|
|
186296
|
+
if (cutoff !== null && row.endOrdinal > cutoff) {
|
|
186297
|
+
continue;
|
|
186298
|
+
}
|
|
186299
|
+
const score = normalizeCosineScore(cosineSimilarity(args.queryEmbedding, row.vector));
|
|
186300
|
+
if (score <= 0)
|
|
186301
|
+
continue;
|
|
186302
|
+
const existing = byCompartment.get(row.compartmentId);
|
|
186303
|
+
if (!existing || score > existing.score) {
|
|
186304
|
+
byCompartment.set(row.compartmentId, { row, score });
|
|
186305
|
+
}
|
|
186306
|
+
}
|
|
186307
|
+
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 }) => ({
|
|
186308
|
+
source: "compartment",
|
|
186309
|
+
content: previewText(row.title),
|
|
186310
|
+
score: score * SINGLE_SOURCE_PENALTY,
|
|
186311
|
+
compartmentId: row.compartmentId,
|
|
186312
|
+
sessionId: row.sessionId,
|
|
186313
|
+
title: row.title,
|
|
186314
|
+
startOrdinal: row.startOrdinal,
|
|
186315
|
+
endOrdinal: row.endOrdinal,
|
|
186316
|
+
matchType: "semantic"
|
|
186317
|
+
}));
|
|
186318
|
+
}
|
|
186319
|
+
function mergeMessageAndCompartmentResults(args) {
|
|
186320
|
+
if (args.compartments.length === 0)
|
|
186321
|
+
return args.messages;
|
|
186322
|
+
if (args.messages.length === 0)
|
|
186323
|
+
return args.compartments;
|
|
186324
|
+
const fused = new Map;
|
|
186325
|
+
const add = (key, result, score, tieOrdinal) => {
|
|
186326
|
+
const existing = fused.get(key);
|
|
186327
|
+
if (existing) {
|
|
186328
|
+
existing.score += score;
|
|
186329
|
+
return existing;
|
|
186330
|
+
}
|
|
186331
|
+
const entry = { result, score, tieOrdinal, snippetScore: -1 };
|
|
186332
|
+
fused.set(key, entry);
|
|
186333
|
+
return entry;
|
|
186334
|
+
};
|
|
186335
|
+
args.compartments.forEach((compartment, rank) => {
|
|
186336
|
+
add(`compartment:${compartment.compartmentId}`, compartment, 1 / (RRF_K + rank), compartment.startOrdinal);
|
|
186337
|
+
});
|
|
186338
|
+
for (const [rank, message] of args.messages.entries()) {
|
|
186339
|
+
const containing = args.compartments.find((compartment) => message.messageOrdinal >= compartment.startOrdinal && message.messageOrdinal <= compartment.endOrdinal);
|
|
186340
|
+
const contribution = 1 / (RRF_K + rank);
|
|
186341
|
+
if (!containing) {
|
|
186342
|
+
add(`message:${message.messageId}`, message, contribution, message.messageOrdinal);
|
|
186343
|
+
continue;
|
|
186344
|
+
}
|
|
186345
|
+
const entry = add(`compartment:${containing.compartmentId}`, containing, contribution, containing.startOrdinal);
|
|
186346
|
+
if (message.score > entry.snippetScore && entry.result.source === "compartment") {
|
|
186347
|
+
entry.snippetScore = message.score;
|
|
186348
|
+
entry.result = {
|
|
186349
|
+
...entry.result,
|
|
186350
|
+
matchType: "hybrid",
|
|
186351
|
+
snippet: message.content
|
|
186352
|
+
};
|
|
186353
|
+
}
|
|
186354
|
+
}
|
|
186355
|
+
const ranked = [...fused.values()].sort((left, right) => right.score !== left.score ? right.score - left.score : left.tieOrdinal - right.tieOrdinal).slice(0, args.limit);
|
|
186356
|
+
return ranked.map((entry, rank) => ({
|
|
186357
|
+
...entry.result,
|
|
186358
|
+
score: linearDecayScore(rank, ranked.length)
|
|
186359
|
+
}));
|
|
186360
|
+
}
|
|
184402
186361
|
function getSourceBoost(result) {
|
|
184403
186362
|
switch (result.source) {
|
|
184404
186363
|
case "memory":
|
|
184405
186364
|
return MEMORY_SOURCE_BOOST;
|
|
184406
186365
|
case "message":
|
|
186366
|
+
case "compartment":
|
|
184407
186367
|
return MESSAGE_SOURCE_BOOST;
|
|
184408
186368
|
case "git_commit":
|
|
184409
186369
|
return GIT_COMMIT_SOURCE_BOOST;
|
|
@@ -184421,6 +186381,9 @@ function compareUnifiedResults(left, right) {
|
|
|
184421
186381
|
if (left.source === "message" && right.source === "message") {
|
|
184422
186382
|
return left.messageOrdinal - right.messageOrdinal;
|
|
184423
186383
|
}
|
|
186384
|
+
if (left.source === "compartment" && right.source === "compartment") {
|
|
186385
|
+
return left.startOrdinal - right.startOrdinal;
|
|
186386
|
+
}
|
|
184424
186387
|
if (left.source === "git_commit" && right.source === "git_commit") {
|
|
184425
186388
|
return right.committedAtMs - left.committedAtMs;
|
|
184426
186389
|
}
|
|
@@ -184471,10 +186434,12 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
184471
186434
|
const isEmbeddingRuntimeEnabled = options.isEmbeddingRuntimeEnabled ?? isEmbeddingEnabled;
|
|
184472
186435
|
const gitCommitsEnabled = options.gitCommitsEnabled ?? false;
|
|
184473
186436
|
const activeSources = resolveSources(options.sources);
|
|
184474
|
-
const
|
|
186437
|
+
const memoryFeatureEnabled = options.memoryEnabled ?? true;
|
|
186438
|
+
const runMemory = activeSources.has("memory") && memoryFeatureEnabled;
|
|
184475
186439
|
const runMessages = activeSources.has("message");
|
|
184476
186440
|
const runGitCommits = activeSources.has("git_commit") && gitCommitsEnabled;
|
|
184477
|
-
const
|
|
186441
|
+
const runCompartmentChunks = runMessages && memoryFeatureEnabled && embeddingEnabled;
|
|
186442
|
+
const needsEmbedding = (runMemory || runGitCommits || runCompartmentChunks) && embeddingEnabled && isEmbeddingRuntimeEnabled();
|
|
184478
186443
|
const queryEmbeddingPromise = needsEmbedding ? embedQuery(trimmedQuery, options.signal).catch((error51) => {
|
|
184479
186444
|
log(`[search] query embedding failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
184480
186445
|
return null;
|
|
@@ -184490,6 +186455,24 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
184490
186455
|
probes: messageProbes
|
|
184491
186456
|
}) : [];
|
|
184492
186457
|
const queryEmbedding = await queryEmbeddingPromise;
|
|
186458
|
+
const workspace = resolveSearchWorkspaceContext(db, projectPath);
|
|
186459
|
+
const embeddingSnapshot = getProjectEmbeddingSnapshot(projectPath);
|
|
186460
|
+
const embeddingModelId = embeddingSnapshot?.modelId;
|
|
186461
|
+
const chunkModelId = embeddingSnapshot?.chunkModelId;
|
|
186462
|
+
const compartmentResults = runCompartmentChunks ? searchCompartmentChunks({
|
|
186463
|
+
db,
|
|
186464
|
+
sessionId,
|
|
186465
|
+
projectPath,
|
|
186466
|
+
queryEmbedding,
|
|
186467
|
+
limit: tierLimit,
|
|
186468
|
+
maxOrdinal: options.maxMessageOrdinal,
|
|
186469
|
+
modelId: chunkModelId && chunkModelId !== "off" ? chunkModelId : null
|
|
186470
|
+
}) : [];
|
|
186471
|
+
const messageLikeResults = mergeMessageAndCompartmentResults({
|
|
186472
|
+
messages: messageResults,
|
|
186473
|
+
compartments: compartmentResults,
|
|
186474
|
+
limit: tierLimit
|
|
186475
|
+
});
|
|
184493
186476
|
const [memoryResults, gitCommitResults] = await Promise.all([
|
|
184494
186477
|
runMemory ? searchMemories({
|
|
184495
186478
|
db,
|
|
@@ -184498,6 +186481,8 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
184498
186481
|
limit: tierLimit,
|
|
184499
186482
|
memoryEnabled: true,
|
|
184500
186483
|
queryEmbedding,
|
|
186484
|
+
queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null,
|
|
186485
|
+
workspace,
|
|
184501
186486
|
visibleMemoryIds: options.visibleMemoryIds
|
|
184502
186487
|
}) : Promise.resolve([]),
|
|
184503
186488
|
runGitCommits ? Promise.resolve(searchGitCommits({
|
|
@@ -184508,7 +186493,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
184508
186493
|
queryEmbedding
|
|
184509
186494
|
})) : Promise.resolve([])
|
|
184510
186495
|
]);
|
|
184511
|
-
const results = [...memoryResults, ...
|
|
186496
|
+
const results = [...memoryResults, ...messageLikeResults, ...gitCommitResults].sort(compareUnifiedResults).slice(0, limit);
|
|
184512
186497
|
const countRetrievals = options.countRetrievals ?? true;
|
|
184513
186498
|
if (countRetrievals) {
|
|
184514
186499
|
const memoryIds = results.filter((result) => result.source === "memory").map((result) => result.memoryId);
|
|
@@ -184572,6 +186557,11 @@ function renderFragment(result, charCap) {
|
|
|
184572
186557
|
const compressed = cavemanCompress(result.content, "ultra");
|
|
184573
186558
|
return truncate(compressed, charCap);
|
|
184574
186559
|
}
|
|
186560
|
+
case "compartment": {
|
|
186561
|
+
const source = result.snippet ?? result.title;
|
|
186562
|
+
const compressed = cavemanCompress(source, "ultra");
|
|
186563
|
+
return truncate(compressed, charCap);
|
|
186564
|
+
}
|
|
184575
186565
|
}
|
|
184576
186566
|
}
|
|
184577
186567
|
function buildAutoSearchHint(results, options = {}) {
|
|
@@ -184926,51 +186916,6 @@ function planEmergencyDrop(input) {
|
|
|
184926
186916
|
};
|
|
184927
186917
|
}
|
|
184928
186918
|
|
|
184929
|
-
// src/hooks/magic-context/system-injection-stripper.ts
|
|
184930
|
-
var SYSTEM_INJECTION_MARKERS = [
|
|
184931
|
-
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
184932
|
-
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
184933
|
-
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
184934
|
-
"[Category+Skill Reminder]",
|
|
184935
|
-
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
184936
|
-
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
184937
|
-
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
184938
|
-
"Unstable background agent appears idle",
|
|
184939
|
-
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
184940
|
-
];
|
|
184941
|
-
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
184942
|
-
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
184943
|
-
function stripSystemInjection(text) {
|
|
184944
|
-
let hasInjection = false;
|
|
184945
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
184946
|
-
if (text.includes(marker)) {
|
|
184947
|
-
hasInjection = true;
|
|
184948
|
-
break;
|
|
184949
|
-
}
|
|
184950
|
-
}
|
|
184951
|
-
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
184952
|
-
hasInjection = true;
|
|
184953
|
-
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
184954
|
-
if (!hasInjection)
|
|
184955
|
-
return null;
|
|
184956
|
-
let cleaned = text;
|
|
184957
|
-
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
184958
|
-
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
184959
|
-
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
184960
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
184961
|
-
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
184962
|
-
continue;
|
|
184963
|
-
const idx = cleaned.indexOf(marker);
|
|
184964
|
-
if (idx === -1)
|
|
184965
|
-
continue;
|
|
184966
|
-
const blockEnd = cleaned.indexOf(`
|
|
184967
|
-
|
|
184968
|
-
`, idx + marker.length);
|
|
184969
|
-
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
184970
|
-
}
|
|
184971
|
-
return cleaned.trim();
|
|
184972
|
-
}
|
|
184973
|
-
|
|
184974
186919
|
// src/hooks/magic-context/heuristic-cleanup.ts
|
|
184975
186920
|
init_tag_part_guards();
|
|
184976
186921
|
var DEDUP_SAFE_TOOLS = new Set([
|
|
@@ -185212,7 +187157,7 @@ function isVisibleNoteReadPart(part) {
|
|
|
185212
187157
|
}
|
|
185213
187158
|
|
|
185214
187159
|
// src/hooks/magic-context/todo-view.ts
|
|
185215
|
-
import { createHash as
|
|
187160
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
185216
187161
|
var TERMINAL_STATUSES = new Set(["completed", "cancelled"]);
|
|
185217
187162
|
var TITLE_DONE_STATUSES = new Set(["completed"]);
|
|
185218
187163
|
var SYNTHETIC_CALL_ID_PREFIX = "mc_synthetic_todo_";
|
|
@@ -185257,7 +187202,7 @@ function buildSyntheticTodoPart(stateJson) {
|
|
|
185257
187202
|
};
|
|
185258
187203
|
}
|
|
185259
187204
|
function computeSyntheticCallId(stateJson) {
|
|
185260
|
-
const hash2 =
|
|
187205
|
+
const hash2 = createHash11("sha256").update(stateJson).digest("hex").slice(0, 16);
|
|
185261
187206
|
return `${SYNTHETIC_CALL_ID_PREFIX}${hash2}`;
|
|
185262
187207
|
}
|
|
185263
187208
|
function parseTodoState(stateJson) {
|
|
@@ -185308,15 +187253,25 @@ async function runPostTransformPhase(args) {
|
|
|
185308
187253
|
const emergencyBypassCompartmentGate = forceMaterialization;
|
|
185309
187254
|
const deferredMaterialize = args.canConsumeDeferredLate && deferredMaterializationWasPending;
|
|
185310
187255
|
const materializationRequested = isExplicitFlush || deferredMaterialize;
|
|
185311
|
-
const
|
|
187256
|
+
const m0M1EnabledForFold = args.fullFeatureMode && args.m0M1 !== undefined && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory);
|
|
187257
|
+
const m0HardFoldThisPass = m0M1EnabledForFold && args.m0M1 ? mustMaterialize({
|
|
187258
|
+
db: args.db,
|
|
187259
|
+
sessionId: args.sessionId,
|
|
187260
|
+
state: args.sessionMeta,
|
|
187261
|
+
projectPath: args.m0M1.projectPath,
|
|
187262
|
+
projectDirectory: args.m0M1.projectDirectory,
|
|
187263
|
+
hardSignals: args.m0M1.hardSignals
|
|
187264
|
+
}).value : false;
|
|
187265
|
+
const shouldReadPendingOps = materializationRequested || args.schedulerDecision === "execute" || forceMaterialization || m0HardFoldThisPass || compartmentRunning;
|
|
185312
187266
|
const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
|
|
185313
187267
|
const hasPendingUserOps = pendingOps.length > 0;
|
|
185314
|
-
const shouldApplyPendingOps = (args.schedulerDecision === "execute" || materializationRequested || forceMaterialization) && (!compartmentRunning || emergencyBypassCompartmentGate);
|
|
185315
|
-
const shouldRunHeuristics = (!compartmentRunning || emergencyBypassCompartmentGate) && (materializationRequested || forceMaterialization || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
|
|
187268
|
+
const shouldApplyPendingOps = (args.schedulerDecision === "execute" || materializationRequested || forceMaterialization || m0HardFoldThisPass) && (!compartmentRunning || emergencyBypassCompartmentGate);
|
|
187269
|
+
const shouldRunHeuristics = (!compartmentRunning || emergencyBypassCompartmentGate) && (materializationRequested || forceMaterialization || m0HardFoldThisPass || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
|
|
185316
187270
|
const isCacheBustingPass = shouldApplyPendingOps || shouldRunHeuristics;
|
|
187271
|
+
const canUseEmptySentinels = modelAcceptsEmptyContent(args.resolvedProviderID);
|
|
185317
187272
|
if (shouldRunHeuristics) {
|
|
185318
187273
|
const subagentRerun = !args.fullFeatureMode && alreadyRanThisTurn && args.schedulerDecision === "execute" && !isExplicitFlush && !forceMaterialization;
|
|
185319
|
-
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})`;
|
|
187274
|
+
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})`;
|
|
185320
187275
|
sessionLog(args.sessionId, `heuristics WILL RUN — reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=${args.currentTurnId}`);
|
|
185321
187276
|
}
|
|
185322
187277
|
if (alreadyRanThisTurn && args.schedulerDecision === "execute" && !materializationRequested && args.fullFeatureMode) {
|
|
@@ -185359,7 +187314,9 @@ async function runPostTransformPhase(args) {
|
|
|
185359
187314
|
logTransformTiming(args.sessionId, "applyHeuristicCleanup", t5, `droppedTools=${cleanup.droppedTools} deduplicatedTools=${cleanup.deduplicatedTools} droppedInjections=${cleanup.droppedInjections} compressedTextTags=${cleanup.compressedTextTags}`);
|
|
185360
187315
|
const t7 = performance.now();
|
|
185361
187316
|
const clearedReasoning = clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge);
|
|
185362
|
-
|
|
187317
|
+
if (canUseEmptySentinels) {
|
|
187318
|
+
stripClearedReasoning(args.messages);
|
|
187319
|
+
}
|
|
185363
187320
|
const strippedInline = stripInlineThinking(args.messages, args.messageTagNumbers, args.clearReasoningAge);
|
|
185364
187321
|
if (clearedReasoning > 0 || strippedInline > 0) {
|
|
185365
187322
|
let maxTag = 0;
|
|
@@ -185405,7 +187362,6 @@ async function runPostTransformPhase(args) {
|
|
|
185405
187362
|
if (args.watermark > 0) {
|
|
185406
187363
|
const tWatermarkCleanup = performance.now();
|
|
185407
187364
|
truncateErroredTools(args.messages, args.watermark, args.messageTagNumbers);
|
|
185408
|
-
stripProcessedImages(args.messages, args.watermark, args.messageTagNumbers);
|
|
185409
187365
|
logTransformTiming(args.sessionId, "watermarkCleanup", tWatermarkCleanup);
|
|
185410
187366
|
}
|
|
185411
187367
|
if (shouldApplyPendingOps) {
|
|
@@ -185415,21 +187371,40 @@ async function runPostTransformPhase(args) {
|
|
|
185415
187371
|
sessionLog(args.sessionId, "transform failed applying pending operations:", error51);
|
|
185416
187372
|
updateSessionMeta(args.db, args.sessionId, { lastTransformError: getErrorMessage(error51) });
|
|
185417
187373
|
}
|
|
185418
|
-
|
|
185419
|
-
|
|
185420
|
-
|
|
185421
|
-
|
|
185422
|
-
|
|
185423
|
-
|
|
185424
|
-
|
|
185425
|
-
|
|
185426
|
-
|
|
187374
|
+
if (canUseEmptySentinels) {
|
|
187375
|
+
try {
|
|
187376
|
+
const t8 = performance.now();
|
|
187377
|
+
const frozenStaleReduceIds = getStaleReduceStrippedIds(args.db, args.sessionId);
|
|
187378
|
+
const staleReduceResult = dropStaleReduceCalls(args.messages, frozenStaleReduceIds, {
|
|
187379
|
+
detect: isCacheBustingPass,
|
|
187380
|
+
protectedCount: args.protectedTags
|
|
187381
|
+
});
|
|
187382
|
+
if (isCacheBustingPass && staleReduceResult.newlyStrippedIds.length > 0) {
|
|
187383
|
+
addStaleReduceStrippedIds(args.db, args.sessionId, staleReduceResult.newlyStrippedIds);
|
|
187384
|
+
}
|
|
187385
|
+
logTransformTiming(args.sessionId, "dropStaleReduceCalls", t8);
|
|
187386
|
+
} catch (error51) {
|
|
187387
|
+
sessionLog(args.sessionId, "transform failed dropping stale ctx_reduce calls:", error51);
|
|
185427
187388
|
}
|
|
185428
|
-
logTransformTiming(args.sessionId, "dropStaleReduceCalls", t8);
|
|
185429
|
-
} catch (error51) {
|
|
185430
|
-
sessionLog(args.sessionId, "transform failed dropping stale ctx_reduce calls:", error51);
|
|
185431
187389
|
}
|
|
185432
|
-
|
|
187390
|
+
if (canUseEmptySentinels && args.watermark > 0) {
|
|
187391
|
+
try {
|
|
187392
|
+
const tImg = performance.now();
|
|
187393
|
+
const frozenImageIds = getProcessedImageStrippedIds(args.db, args.sessionId);
|
|
187394
|
+
const imageResult = stripProcessedImages(args.messages, frozenImageIds, {
|
|
187395
|
+
detect: isCacheBustingPass,
|
|
187396
|
+
watermark: args.watermark,
|
|
187397
|
+
messageTagNumbers: args.messageTagNumbers
|
|
187398
|
+
});
|
|
187399
|
+
if (isCacheBustingPass && imageResult.newlyStrippedIds.length > 0) {
|
|
187400
|
+
addProcessedImageStrippedIds(args.db, args.sessionId, imageResult.newlyStrippedIds);
|
|
187401
|
+
}
|
|
187402
|
+
logTransformTiming(args.sessionId, "stripProcessedImages", tImg);
|
|
187403
|
+
} catch (error51) {
|
|
187404
|
+
sessionLog(args.sessionId, "transform failed stripping processed images:", error51);
|
|
187405
|
+
}
|
|
187406
|
+
}
|
|
187407
|
+
const m0M1Enabled = m0M1EnabledForFold;
|
|
185433
187408
|
if (m0M1Enabled && args.m0M1) {
|
|
185434
187409
|
const tInjectM0M1 = performance.now();
|
|
185435
187410
|
try {
|
|
@@ -185476,7 +187451,7 @@ async function runPostTransformPhase(args) {
|
|
|
185476
187451
|
const tPlaceholder = performance.now();
|
|
185477
187452
|
const persistedIds = getStrippedPlaceholderIds(args.db, args.sessionId);
|
|
185478
187453
|
if (persistedIds.size > 0) {
|
|
185479
|
-
const { replayed, missingIds } = replaySentinelByMessageIds(args.messages, persistedIds, args.
|
|
187454
|
+
const { replayed, missingIds } = replaySentinelByMessageIds(args.messages, persistedIds, args.resolvedProviderID);
|
|
185480
187455
|
if (replayed > 0) {
|
|
185481
187456
|
sessionLog(args.sessionId, `sentinel replay: neutralized ${replayed} previously-stripped messages`);
|
|
185482
187457
|
}
|
|
@@ -185487,9 +187462,9 @@ async function runPostTransformPhase(args) {
|
|
|
185487
187462
|
}
|
|
185488
187463
|
}
|
|
185489
187464
|
if (isCacheBustingPass) {
|
|
185490
|
-
const droppedResult = stripDroppedPlaceholderMessages(args.messages, args.
|
|
187465
|
+
const droppedResult = stripDroppedPlaceholderMessages(args.messages, args.resolvedProviderID);
|
|
185491
187466
|
const protectedTailStart = Math.max(0, args.messages.length - args.protectedTags * 2);
|
|
185492
|
-
const systemInjectedResult = stripSystemInjectedMessages(args.messages, protectedTailStart, args.
|
|
187467
|
+
const systemInjectedResult = stripSystemInjectedMessages(args.messages, protectedTailStart, args.resolvedProviderID);
|
|
185493
187468
|
const newlyNeutralized = droppedResult.sentineledIds.length + systemInjectedResult.sentineledIds.length;
|
|
185494
187469
|
if (newlyNeutralized > 0) {
|
|
185495
187470
|
const addedIds = [
|
|
@@ -185689,6 +187664,7 @@ function clearMessageTokensCache(sessionId, messageId) {
|
|
|
185689
187664
|
if (cache)
|
|
185690
187665
|
cache.delete(messageId);
|
|
185691
187666
|
}
|
|
187667
|
+
var recordedSessionProjectIdentity = new BoundedSessionMap(MESSAGE_TOKENS_CACHE_MAX);
|
|
185692
187668
|
function findLastAssistantModel2(messages) {
|
|
185693
187669
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
185694
187670
|
const info = messages[i].info;
|
|
@@ -185736,9 +187712,11 @@ function createTransform(deps) {
|
|
|
185736
187712
|
const fullFeatureMode = !reducedMode;
|
|
185737
187713
|
const ctxReduceEnabledEffective = deps.ctxReduceEnabled !== false && resolveCtxReduceAvailabilityFromMessages(sessionId, messages);
|
|
185738
187714
|
let sessionDirectory = deps.directory ?? "";
|
|
187715
|
+
let sessionDirectoryResolvedFromHost = false;
|
|
185739
187716
|
const cachedDirectory = deps.sessionDirectoryBySession?.get(sessionId);
|
|
185740
187717
|
if (cachedDirectory && cachedDirectory.length > 0) {
|
|
185741
187718
|
sessionDirectory = cachedDirectory;
|
|
187719
|
+
sessionDirectoryResolvedFromHost = true;
|
|
185742
187720
|
} else if (deps.client !== undefined) {
|
|
185743
187721
|
try {
|
|
185744
187722
|
const sessionResponse = await deps.client.session.get({ path: { id: sessionId } }).catch(() => null);
|
|
@@ -185746,6 +187724,7 @@ function createTransform(deps) {
|
|
|
185746
187724
|
if (sessionInfo && typeof sessionInfo.directory === "string" && sessionInfo.directory.length > 0) {
|
|
185747
187725
|
sessionDirectory = sessionInfo.directory;
|
|
185748
187726
|
deps.sessionDirectoryBySession?.set(sessionId, sessionDirectory);
|
|
187727
|
+
sessionDirectoryResolvedFromHost = true;
|
|
185749
187728
|
}
|
|
185750
187729
|
} catch {}
|
|
185751
187730
|
}
|
|
@@ -185840,6 +187819,8 @@ function createTransform(deps) {
|
|
|
185840
187819
|
deps.liveModelBySession?.set(sessionId, recovered);
|
|
185841
187820
|
}
|
|
185842
187821
|
}
|
|
187822
|
+
const resolvedProviderID = modelForBudget?.providerID;
|
|
187823
|
+
const canUseEmptySentinels = modelAcceptsEmptyContent(resolvedProviderID);
|
|
185843
187824
|
const resolvedContextLimit = modelForBudget ? resolveTrustedContextLimit(modelForBudget.providerID, modelForBudget.modelID, {
|
|
185844
187825
|
db,
|
|
185845
187826
|
sessionID: sessionId
|
|
@@ -186004,6 +187985,10 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
186004
187985
|
logTransformTiming(sessionId, "emergencyRecoveryBlock", tFirstPass);
|
|
186005
187986
|
const projectIdentity = deps.memoryConfig?.enabled ? resolveProjectIdentity(compartmentDirectory || process.cwd()) : undefined;
|
|
186006
187987
|
const sessionProjectIdentity = projectIdentity ?? (sessionDirectory ? resolveProjectIdentity(sessionDirectory) : deps.projectPath);
|
|
187988
|
+
if (sessionProjectIdentity && sessionDirectoryResolvedFromHost && recordedSessionProjectIdentity.get(sessionId) !== sessionProjectIdentity) {
|
|
187989
|
+
recordSessionProjectIdentity(db, sessionId, sessionProjectIdentity);
|
|
187990
|
+
recordedSessionProjectIdentity.set(sessionId, sessionProjectIdentity);
|
|
187991
|
+
}
|
|
186007
187992
|
let triggerBoundarySnapshot;
|
|
186008
187993
|
if (fullFeatureMode && historianRunnable && !sessionMeta.compartmentInProgress) {
|
|
186009
187994
|
const tTrigger = performance.now();
|
|
@@ -186098,7 +188083,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
186098
188083
|
}
|
|
186099
188084
|
}
|
|
186100
188085
|
const t3 = performance.now();
|
|
186101
|
-
const strippedStructuralNoise = stripStructuralNoise(messages);
|
|
188086
|
+
const strippedStructuralNoise = canUseEmptySentinels ? stripStructuralNoise(messages) : 0;
|
|
186102
188087
|
logTransformTiming(sessionId, "stripStructuralNoise", t3, `strippedParts=${strippedStructuralNoise}`);
|
|
186103
188088
|
const persistedReasoningWatermark = sessionMeta?.clearedReasoningThroughTag ?? 0;
|
|
186104
188089
|
if (persistedReasoningWatermark > 0) {
|
|
@@ -186119,18 +188104,10 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
186119
188104
|
logTransformTiming(sessionId, "replayCavemanCompression", tCavemanReplay);
|
|
186120
188105
|
}
|
|
186121
188106
|
const t4 = performance.now();
|
|
186122
|
-
const strippedClearedReasoning = stripClearedReasoning(messages);
|
|
188107
|
+
const strippedClearedReasoning = canUseEmptySentinels ? stripClearedReasoning(messages) : 0;
|
|
186123
188108
|
logTransformTiming(sessionId, "stripClearedReasoning", t4, `strippedParts=${strippedClearedReasoning}`);
|
|
186124
188109
|
const tMergeStrip = performance.now();
|
|
186125
|
-
|
|
186126
|
-
if (liveProviderID === undefined) {
|
|
186127
|
-
const recovered = findLastAssistantModelFromOpenCodeDb(sessionId);
|
|
186128
|
-
if (recovered) {
|
|
186129
|
-
liveProviderID = recovered.providerID;
|
|
186130
|
-
deps.liveModelBySession?.set(sessionId, recovered);
|
|
186131
|
-
}
|
|
186132
|
-
}
|
|
186133
|
-
const strippedMergedReasoning = stripReasoningFromMergedAssistants(messages, liveProviderID);
|
|
188110
|
+
const strippedMergedReasoning = stripReasoningFromMergedAssistants(messages, resolvedProviderID);
|
|
186134
188111
|
if (strippedMergedReasoning > 0) {
|
|
186135
188112
|
sessionLog(sessionId, `stripped ${strippedMergedReasoning} reasoning parts from merged assistants (anthropic groupIntoBlocks workaround)`);
|
|
186136
188113
|
}
|
|
@@ -186249,7 +188226,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
186249
188226
|
sessionDirectory,
|
|
186250
188227
|
autoSearch: deps.autoSearch,
|
|
186251
188228
|
cavemanTextCompression: deps.ctxReduceEnabled === false && !reducedMode ? deps.cavemanTextCompression : undefined,
|
|
186252
|
-
|
|
188229
|
+
resolvedProviderID,
|
|
186253
188230
|
historyRefreshSessions: deps.historyRefreshSessions,
|
|
186254
188231
|
m0M1: {
|
|
186255
188232
|
projectPath: projectIdentity,
|
|
@@ -186402,7 +188379,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
186402
188379
|
let tailToolTokens;
|
|
186403
188380
|
let liveTailTokens;
|
|
186404
188381
|
try {
|
|
186405
|
-
const agg = getActiveTagTokenAggregate(db, sessionId);
|
|
188382
|
+
const agg = getActiveTagTokenAggregate(db, sessionId, deps.protectedTags);
|
|
186406
188383
|
tailToolTokens = agg.toolOutput;
|
|
186407
188384
|
liveTailTokens = agg.conversation + agg.toolCall;
|
|
186408
188385
|
} catch {
|
|
@@ -187013,10 +188990,11 @@ function maybeInjectChannel1Nudge(args, sessionId, tool, output) {
|
|
|
187013
188990
|
contextLimit: state.contextLimit,
|
|
187014
188991
|
executeThresholdPercentage: state.executeThresholdPercentage
|
|
187015
188992
|
});
|
|
188993
|
+
const workingWindowTokens = Math.round(state.contextLimit * state.executeThresholdPercentage / 100);
|
|
187016
188994
|
const decision = decideChannel1({
|
|
187017
188995
|
undroppedTokens,
|
|
187018
188996
|
pressure,
|
|
187019
|
-
|
|
188997
|
+
workingWindowTokens,
|
|
187020
188998
|
lastNudgeUndropped: getLastNudgeUndropped(args.db, sessionId),
|
|
187021
188999
|
lastNudgeLevel: getLastNudgeLevel(args.db, sessionId),
|
|
187022
189000
|
hasRecentReduce: false
|
|
@@ -187078,7 +189056,7 @@ function createToolExecuteAfterHook(args) {
|
|
|
187078
189056
|
init_send_session_notification();
|
|
187079
189057
|
|
|
187080
189058
|
// src/hooks/magic-context/system-prompt-hash.ts
|
|
187081
|
-
import { createHash as
|
|
189059
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
187082
189060
|
|
|
187083
189061
|
// src/agents/magic-context-prompt.ts
|
|
187084
189062
|
var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
|
|
@@ -187278,7 +189256,7 @@ function createSystemPromptHashHandler(deps) {
|
|
|
187278
189256
|
`);
|
|
187279
189257
|
if (systemContent.length === 0)
|
|
187280
189258
|
return;
|
|
187281
|
-
const currentHash =
|
|
189259
|
+
const currentHash = createHash12("md5").update(systemContent).digest("hex");
|
|
187282
189260
|
if (!sessionMetaEarly) {
|
|
187283
189261
|
return;
|
|
187284
189262
|
}
|
|
@@ -187539,6 +189517,46 @@ function createMagicContextHook(deps) {
|
|
|
187539
189517
|
ensureProjectRegistered: ensureProjectRegisteredFromOpenCodeDirectory,
|
|
187540
189518
|
getNotificationParams: (sid) => getLiveNotificationParams(sid, liveModelBySession, variantBySession, agentBySession)
|
|
187541
189519
|
});
|
|
189520
|
+
const executeEmbedHistory = async (sessionId) => {
|
|
189521
|
+
if (deps.config.memory?.enabled === false) {
|
|
189522
|
+
return "Memory is disabled for this project, so there is no semantic embedding to backfill.";
|
|
189523
|
+
}
|
|
189524
|
+
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
189525
|
+
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
189526
|
+
const sessionProjectIdentity = resolveProjectIdentity(directory);
|
|
189527
|
+
setRecompStarting({ recompProgressBySession }, sessionId, "Embedding history…", "embed");
|
|
189528
|
+
const outcome = await embedSessionCompartmentChunks(db, sessionProjectIdentity, sessionId, {
|
|
189529
|
+
onProgress: ({ embedded, total }) => {
|
|
189530
|
+
const cur = recompProgressBySession.get(sessionId);
|
|
189531
|
+
if (!cur || cur.phase !== "recomp")
|
|
189532
|
+
return;
|
|
189533
|
+
recompProgressBySession.set(sessionId, {
|
|
189534
|
+
...cur,
|
|
189535
|
+
processedMessages: embedded,
|
|
189536
|
+
totalMessages: total,
|
|
189537
|
+
updatedAt: Date.now()
|
|
189538
|
+
});
|
|
189539
|
+
}
|
|
189540
|
+
});
|
|
189541
|
+
const terminal = (phase, message) => {
|
|
189542
|
+
setRecompTerminal({ recompProgressBySession }, sessionId, phase, message);
|
|
189543
|
+
return message;
|
|
189544
|
+
};
|
|
189545
|
+
switch (outcome.status) {
|
|
189546
|
+
case "nothing":
|
|
189547
|
+
return terminal("done", "All of this session's history is already embedded.");
|
|
189548
|
+
case "disabled":
|
|
189549
|
+
return terminal("skipped", "No embedding provider is configured, so there is nothing to embed.");
|
|
189550
|
+
case "busy":
|
|
189551
|
+
return terminal("skipped", `Embedding is already running for this project — ${outcome.total} compartment${outcome.total === 1 ? "" : "s"} still pending. Try again shortly.`);
|
|
189552
|
+
case "aborted":
|
|
189553
|
+
return terminal("done", `Embedded ${outcome.embedded} of ${outcome.total} compartments before stopping.`);
|
|
189554
|
+
case "stalled":
|
|
189555
|
+
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.`);
|
|
189556
|
+
default:
|
|
189557
|
+
return terminal("done", `Embedded ${outcome.embedded} compartment${outcome.embedded === 1 ? "" : "s"} of history for semantic search.`);
|
|
189558
|
+
}
|
|
189559
|
+
};
|
|
187542
189560
|
const sidekickRunnable = isSidekickRunnable(deps.config);
|
|
187543
189561
|
const sidekickConfig = sidekickRunnable ? deps.config.sidekick : undefined;
|
|
187544
189562
|
const transform2 = createTransform({
|
|
@@ -187693,6 +189711,7 @@ function createMagicContextHook(deps) {
|
|
|
187693
189711
|
},
|
|
187694
189712
|
executeRecomp: historianRunnable ? async (sessionId, options) => runManagedRecomp(buildManagedRecompCtx(sessionId), sessionId, options) : undefined,
|
|
187695
189713
|
runUpgrade: historianRunnable ? async (sessionId) => runManagedUpgrade(buildManagedRecompCtx(sessionId), sessionId) : undefined,
|
|
189714
|
+
executeEmbedHistory,
|
|
187696
189715
|
sendNotification: async (sessionId, text, params) => {
|
|
187697
189716
|
await sendIgnoredMessage(deps.client, sessionId, text, {
|
|
187698
189717
|
...getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession),
|
|
@@ -188830,6 +190849,7 @@ init_memory();
|
|
|
188830
190849
|
init_embedding();
|
|
188831
190850
|
init_embedding_cache();
|
|
188832
190851
|
init_normalize_hash();
|
|
190852
|
+
init_workspaces();
|
|
188833
190853
|
init_logger();
|
|
188834
190854
|
await init_storage();
|
|
188835
190855
|
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
@@ -188989,6 +191009,23 @@ function createCtxMemoryTool(deps) {
|
|
|
188989
191009
|
}
|
|
188990
191010
|
const projectPath = deps.resolveProjectPath(toolContext.directory);
|
|
188991
191011
|
await deps.ensureProjectRegistered?.(toolContext.directory, deps.db);
|
|
191012
|
+
const workspaceIdentitySet = resolveWorkspaceIdentitySet(deps.db, projectPath);
|
|
191013
|
+
const expandedWorkspace = expandWorkspaceIdentitySetWithAliases(deps.db, workspaceIdentitySet.identities);
|
|
191014
|
+
const workspaceVisibleIdentities = workspaceIdentitySet.identities.length > 1 ? expandedWorkspace.expandedIdentities : workspaceIdentitySet.identities;
|
|
191015
|
+
const targetIdentityForStoredPath = (rawProjectPath) => workspaceIdentitySet.identities.length > 1 ? resolveStoredPathWorkspaceIdentity(rawProjectPath, workspaceIdentitySet.identities, expandedWorkspace.canonicalIdentityByStoredPath) ?? projectIdentityForStoredPath(rawProjectPath) : projectIdentityForStoredPath(rawProjectPath);
|
|
191016
|
+
const toolShareCategories = workspaceIdentitySet.identities.length > 1 ? resolveWorkspaceShareCategories(deps.db, projectPath) : null;
|
|
191017
|
+
const memoryVisibleToTool = (memory) => {
|
|
191018
|
+
if (workspaceIdentitySet.identities.length <= 1) {
|
|
191019
|
+
return memoryBelongsToProject(memory, projectPath);
|
|
191020
|
+
}
|
|
191021
|
+
if (!storedPathBelongsToWorkspace(memory.projectPath, workspaceIdentitySet.identities, workspaceVisibleIdentities, expandedWorkspace.canonicalIdentityByStoredPath)) {
|
|
191022
|
+
return false;
|
|
191023
|
+
}
|
|
191024
|
+
const isOwn = targetIdentityForStoredPath(memory.projectPath) === projectPath;
|
|
191025
|
+
if (isOwn)
|
|
191026
|
+
return true;
|
|
191027
|
+
return toolShareCategories === null || toolShareCategories.includes(memory.category);
|
|
191028
|
+
};
|
|
188992
191029
|
const embeddingSnapshot = getProjectEmbeddingSnapshot(projectPath);
|
|
188993
191030
|
if (embeddingSnapshot ? !embeddingSnapshot.features.memoryEnabled : deps.memoryEnabled === false) {
|
|
188994
191031
|
return getDisabledMessage();
|
|
@@ -189045,18 +191082,18 @@ function createCtxMemoryTool(deps) {
|
|
|
189045
191082
|
}
|
|
189046
191083
|
const rawProjectPath = projectPathForMemoryId(deps.db, updateId);
|
|
189047
191084
|
const memory = getMemoryById(deps.db, updateId);
|
|
189048
|
-
if (!memory || !rawProjectPath || !
|
|
191085
|
+
if (!memory || !rawProjectPath || !memoryVisibleToTool(memory)) {
|
|
189049
191086
|
return `Error: Memory with ID ${updateId} was not found.`;
|
|
189050
191087
|
}
|
|
189051
191088
|
if (toolContext.agent !== DREAMER_AGENT && !isPrimaryMutableMemory(memory)) {
|
|
189052
191089
|
return inactiveMemoryError(updateId, "updating");
|
|
189053
191090
|
}
|
|
189054
191091
|
const normalizedHash = computeNormalizedHash(content);
|
|
189055
|
-
const duplicate = getMemoryByHash(deps.db,
|
|
191092
|
+
const duplicate = getMemoryByHash(deps.db, targetIdentityForStoredPath(rawProjectPath), memory.category, normalizedHash);
|
|
189056
191093
|
if (duplicate && duplicate.id !== memory.id) {
|
|
189057
191094
|
return `Error: Memory content already exists as ID ${duplicate.id}; merge or archive duplicates instead.`;
|
|
189058
191095
|
}
|
|
189059
|
-
const projectIdentity =
|
|
191096
|
+
const projectIdentity = targetIdentityForStoredPath(rawProjectPath);
|
|
189060
191097
|
deps.db.transaction(() => {
|
|
189061
191098
|
updateMemoryContentInCurrentTransaction(deps.db, memory, content, normalizedHash);
|
|
189062
191099
|
queueMemoryMutation(deps.db, {
|
|
@@ -189070,7 +191107,7 @@ function createCtxMemoryTool(deps) {
|
|
|
189070
191107
|
queueMemoryEmbedding({
|
|
189071
191108
|
deps,
|
|
189072
191109
|
sessionId: toolContext.sessionID,
|
|
189073
|
-
projectPath,
|
|
191110
|
+
projectPath: projectIdentity,
|
|
189074
191111
|
memoryId: memory.id,
|
|
189075
191112
|
content
|
|
189076
191113
|
});
|
|
@@ -189093,7 +191130,7 @@ function createCtxMemoryTool(deps) {
|
|
|
189093
191130
|
return "Error: One or more source memories were not found.";
|
|
189094
191131
|
}
|
|
189095
191132
|
if (toolContext.agent !== DREAMER_AGENT) {
|
|
189096
|
-
const foreign = sourceMemories.find((memory) => !
|
|
191133
|
+
const foreign = sourceMemories.find((memory) => !memoryVisibleToTool(memory));
|
|
189097
191134
|
if (foreign) {
|
|
189098
191135
|
return `Error: Memory with ID ${foreign.id} was not found.`;
|
|
189099
191136
|
}
|
|
@@ -189177,15 +191214,16 @@ function createCtxMemoryTool(deps) {
|
|
|
189177
191214
|
return `Merged memories [${ids.join(", ")}] into canonical memory [ID: ${canonicalMemory.id}] in ${category}; superseded [${supersededIds.join(", ")}].`;
|
|
189178
191215
|
}
|
|
189179
191216
|
if (args.action === "archive") {
|
|
189180
|
-
const
|
|
189181
|
-
if (!
|
|
191217
|
+
const rawArchiveIds = args.ids;
|
|
191218
|
+
if (!rawArchiveIds || rawArchiveIds.length === 0 || !rawArchiveIds.every(Number.isInteger)) {
|
|
189182
191219
|
return "Error: 'ids' must contain at least one integer memory ID when action is 'archive'.";
|
|
189183
191220
|
}
|
|
191221
|
+
const archiveIds = [...new Set(rawArchiveIds)];
|
|
189184
191222
|
const targets = [];
|
|
189185
191223
|
for (const memoryId of archiveIds) {
|
|
189186
191224
|
const rawProjectPath = projectPathForMemoryId(deps.db, memoryId);
|
|
189187
191225
|
const memory = getMemoryById(deps.db, memoryId);
|
|
189188
|
-
if (!memory || !rawProjectPath || !
|
|
191226
|
+
if (!memory || !rawProjectPath || !memoryVisibleToTool(memory)) {
|
|
189189
191227
|
return `Error: Memory with ID ${memoryId} was not found.`;
|
|
189190
191228
|
}
|
|
189191
191229
|
if (toolContext.agent !== DREAMER_AGENT && !isPrimaryMutableMemory(memory)) {
|
|
@@ -189193,7 +191231,7 @@ function createCtxMemoryTool(deps) {
|
|
|
189193
191231
|
}
|
|
189194
191232
|
targets.push({
|
|
189195
191233
|
memoryId,
|
|
189196
|
-
projectIdentity:
|
|
191234
|
+
projectIdentity: targetIdentityForStoredPath(rawProjectPath)
|
|
189197
191235
|
});
|
|
189198
191236
|
}
|
|
189199
191237
|
deps.db.transaction(() => {
|
|
@@ -189667,8 +191705,9 @@ function formatAge2(committedAtMs) {
|
|
|
189667
191705
|
}
|
|
189668
191706
|
function formatResult(result, index) {
|
|
189669
191707
|
if (result.source === "memory") {
|
|
191708
|
+
const source = result.sourceName ? ` source=${result.sourceName}` : "";
|
|
189670
191709
|
return [
|
|
189671
|
-
`[${index}] [memory] score=${result.score.toFixed(2)} id=${result.memoryId} category=${result.category} match=${result.matchType}`,
|
|
191710
|
+
`[${index}] [memory] score=${result.score.toFixed(2)} id=${result.memoryId} category=${result.category}${source} match=${result.matchType}`,
|
|
189672
191711
|
result.content
|
|
189673
191712
|
].join(`
|
|
189674
191713
|
`);
|
|
@@ -189678,6 +191717,13 @@ function formatResult(result, index) {
|
|
|
189678
191717
|
`[${index}] [git_commit] score=${result.score.toFixed(2)} sha=${result.shortSha} ${formatAge2(result.committedAtMs)} match=${result.matchType}`,
|
|
189679
191718
|
result.content
|
|
189680
191719
|
].join(`
|
|
191720
|
+
`);
|
|
191721
|
+
}
|
|
191722
|
+
if (result.source === "compartment") {
|
|
191723
|
+
return [
|
|
191724
|
+
`[${index}] [message] score=${result.score.toFixed(2)} compartment_id=${result.compartmentId} range=${result.startOrdinal}-${result.endOrdinal} match=${result.matchType} title=${result.title}`,
|
|
191725
|
+
result.snippet ? `Snippet: ${result.snippet}` : result.content
|
|
191726
|
+
].join(`
|
|
189681
191727
|
`);
|
|
189682
191728
|
}
|
|
189683
191729
|
const expandStart = Math.max(1, result.messageOrdinal - 3);
|
|
@@ -189693,7 +191739,7 @@ function formatSearchResults(query, results) {
|
|
|
189693
191739
|
return `No results found for "${query}" across memories, git commits, or message history.`;
|
|
189694
191740
|
}
|
|
189695
191741
|
const bodyParts = results.map((result, index) => formatResult(result, index + 1));
|
|
189696
|
-
if (results.some((result) => result.source === "message")) {
|
|
191742
|
+
if (results.some((result) => result.source === "message" || result.source === "compartment")) {
|
|
189697
191743
|
bodyParts.push("Use ctx_expand(start, end) with the range from any message result above to read the full conversation context.");
|
|
189698
191744
|
}
|
|
189699
191745
|
const body = bodyParts.join(`
|
|
@@ -189851,11 +191897,11 @@ import { createServer } from "node:http";
|
|
|
189851
191897
|
import { dirname as dirname8 } from "node:path";
|
|
189852
191898
|
|
|
189853
191899
|
// src/shared/rpc-utils.ts
|
|
189854
|
-
import { createHash as
|
|
191900
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
189855
191901
|
import { join as join24 } from "node:path";
|
|
189856
191902
|
function projectHash(directory) {
|
|
189857
191903
|
const normalized = directory.replace(/\/+$/, "");
|
|
189858
|
-
return
|
|
191904
|
+
return createHash13("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
189859
191905
|
}
|
|
189860
191906
|
function rpcPortDir(storageDir, directory) {
|
|
189861
191907
|
return join24(storageDir, "rpc", projectHash(directory));
|