@wolfx/pi-magic-context 0.25.0 → 0.26.0-patch.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +14872 -14858
- package/dist/subagent-entry.js +292 -451
- package/package.json +2 -4
package/dist/subagent-entry.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
1
|
var __create = Object.create;
|
|
3
2
|
var __getProtoOf = Object.getPrototypeOf;
|
|
4
3
|
var __defProp = Object.defineProperty;
|
|
@@ -44,7 +43,6 @@ var __export = (target, all) => {
|
|
|
44
43
|
});
|
|
45
44
|
};
|
|
46
45
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
47
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
48
46
|
|
|
49
47
|
// ../plugin/src/shared/harness.ts
|
|
50
48
|
function setHarness(value) {
|
|
@@ -9582,6 +9580,41 @@ var MIGRATIONS = [
|
|
|
9582
9580
|
`);
|
|
9583
9581
|
}
|
|
9584
9582
|
}
|
|
9583
|
+
},
|
|
9584
|
+
{
|
|
9585
|
+
version: 37,
|
|
9586
|
+
description: "emergency drain catch-up latch + historian drain failure backoff",
|
|
9587
|
+
up: (db) => {
|
|
9588
|
+
const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta'").get();
|
|
9589
|
+
if (!hasSessionMeta)
|
|
9590
|
+
return;
|
|
9591
|
+
ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
|
|
9592
|
+
ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
|
|
9593
|
+
}
|
|
9594
|
+
},
|
|
9595
|
+
{
|
|
9596
|
+
version: 38,
|
|
9597
|
+
description: "durable transform decisions for cache-event cause attribution",
|
|
9598
|
+
up: (db) => {
|
|
9599
|
+
db.exec(`
|
|
9600
|
+
CREATE TABLE IF NOT EXISTS transform_decisions (
|
|
9601
|
+
session_id TEXT NOT NULL,
|
|
9602
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
9603
|
+
message_id TEXT NOT NULL,
|
|
9604
|
+
ts_ms INTEGER NOT NULL,
|
|
9605
|
+
decision TEXT NOT NULL,
|
|
9606
|
+
materialized INTEGER NOT NULL DEFAULT 0,
|
|
9607
|
+
materialize_reason TEXT,
|
|
9608
|
+
emergency INTEGER NOT NULL DEFAULT 0,
|
|
9609
|
+
dropped_tokens INTEGER NOT NULL DEFAULT 0,
|
|
9610
|
+
dropped_count INTEGER NOT NULL DEFAULT 0,
|
|
9611
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
9612
|
+
PRIMARY KEY (session_id, harness, message_id)
|
|
9613
|
+
);
|
|
9614
|
+
CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
|
|
9615
|
+
ON transform_decisions(session_id, harness);
|
|
9616
|
+
`);
|
|
9617
|
+
}
|
|
9585
9618
|
}
|
|
9586
9619
|
];
|
|
9587
9620
|
var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -142558,8 +142591,9 @@ function backfillToolOwnersInChunks(db, result) {
|
|
|
142558
142591
|
var databases = new Map;
|
|
142559
142592
|
var persistenceByDatabase = new WeakMap;
|
|
142560
142593
|
var persistenceErrorByDatabase = new WeakMap;
|
|
142594
|
+
var pathByDatabase = new WeakMap;
|
|
142561
142595
|
var lastSchemaFenceRejection = null;
|
|
142562
|
-
var LATEST_SUPPORTED_VERSION =
|
|
142596
|
+
var LATEST_SUPPORTED_VERSION = 38;
|
|
142563
142597
|
function resolveDatabasePath(dbPathOverride) {
|
|
142564
142598
|
if (dbPathOverride) {
|
|
142565
142599
|
return { dbDir: dirname2(dbPathOverride), dbPath: dbPathOverride };
|
|
@@ -142572,6 +142606,9 @@ function resolveDatabasePath(dbPathOverride) {
|
|
|
142572
142606
|
const dbDir = getMagicContextStorageDir();
|
|
142573
142607
|
return { dbDir, dbPath: join4(dbDir, "context.db") };
|
|
142574
142608
|
}
|
|
142609
|
+
function getDatabasePath(db) {
|
|
142610
|
+
return pathByDatabase.get(db) ?? null;
|
|
142611
|
+
}
|
|
142575
142612
|
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
142576
142613
|
if (existsSync3(targetDbPath))
|
|
142577
142614
|
return;
|
|
@@ -143086,6 +143123,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143086
143123
|
recovery_no_eligible_head_count INTEGER NOT NULL DEFAULT 0,
|
|
143087
143124
|
force_emergency_bypass_window_start INTEGER NOT NULL DEFAULT 0,
|
|
143088
143125
|
force_emergency_bypass_used INTEGER NOT NULL DEFAULT 0,
|
|
143126
|
+
emergency_drain_active INTEGER NOT NULL DEFAULT 0,
|
|
143127
|
+
historian_drain_failure_at INTEGER NOT NULL DEFAULT 0,
|
|
143089
143128
|
cached_m0_materialized_at INTEGER,
|
|
143090
143129
|
cached_m0_session_facts_version INTEGER,
|
|
143091
143130
|
cached_m0_upgrade_state TEXT,
|
|
@@ -143149,6 +143188,23 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143149
143188
|
CREATE INDEX IF NOT EXISTS idx_historian_runs_status
|
|
143150
143189
|
ON historian_runs(status, created_at DESC);
|
|
143151
143190
|
|
|
143191
|
+
CREATE TABLE IF NOT EXISTS transform_decisions (
|
|
143192
|
+
session_id TEXT NOT NULL,
|
|
143193
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
143194
|
+
message_id TEXT NOT NULL,
|
|
143195
|
+
ts_ms INTEGER NOT NULL,
|
|
143196
|
+
decision TEXT NOT NULL,
|
|
143197
|
+
materialized INTEGER NOT NULL DEFAULT 0,
|
|
143198
|
+
materialize_reason TEXT,
|
|
143199
|
+
emergency INTEGER NOT NULL DEFAULT 0,
|
|
143200
|
+
dropped_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143201
|
+
dropped_count INTEGER NOT NULL DEFAULT 0,
|
|
143202
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143203
|
+
PRIMARY KEY (session_id, harness, message_id)
|
|
143204
|
+
);
|
|
143205
|
+
CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
|
|
143206
|
+
ON transform_decisions(session_id, harness);
|
|
143207
|
+
|
|
143152
143208
|
CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
|
|
143153
143209
|
CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
|
|
143154
143210
|
CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
|
|
@@ -143300,6 +143356,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143300
143356
|
ensureColumn(db, "session_meta", "recovery_no_eligible_head_count", "INTEGER NOT NULL DEFAULT 0");
|
|
143301
143357
|
ensureColumn(db, "session_meta", "force_emergency_bypass_window_start", "INTEGER NOT NULL DEFAULT 0");
|
|
143302
143358
|
ensureColumn(db, "session_meta", "force_emergency_bypass_used", "INTEGER NOT NULL DEFAULT 0");
|
|
143359
|
+
ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
|
|
143360
|
+
ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
|
|
143303
143361
|
ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
|
|
143304
143362
|
ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
|
|
143305
143363
|
ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
|
|
@@ -143378,6 +143436,22 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143378
143436
|
failed_at INTEGER NOT NULL,
|
|
143379
143437
|
UNIQUE(table_name, row_id)
|
|
143380
143438
|
);
|
|
143439
|
+
CREATE TABLE IF NOT EXISTS transform_decisions (
|
|
143440
|
+
session_id TEXT NOT NULL,
|
|
143441
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
143442
|
+
message_id TEXT NOT NULL,
|
|
143443
|
+
ts_ms INTEGER NOT NULL,
|
|
143444
|
+
decision TEXT NOT NULL,
|
|
143445
|
+
materialized INTEGER NOT NULL DEFAULT 0,
|
|
143446
|
+
materialize_reason TEXT,
|
|
143447
|
+
emergency INTEGER NOT NULL DEFAULT 0,
|
|
143448
|
+
dropped_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143449
|
+
dropped_count INTEGER NOT NULL DEFAULT 0,
|
|
143450
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143451
|
+
PRIMARY KEY (session_id, harness, message_id)
|
|
143452
|
+
);
|
|
143453
|
+
CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
|
|
143454
|
+
ON transform_decisions(session_id, harness);
|
|
143381
143455
|
`);
|
|
143382
143456
|
ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
143383
143457
|
ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
@@ -143464,7 +143538,9 @@ function healNullIntegerColumns(db) {
|
|
|
143464
143538
|
["protected_tail_drain_tokens", 0],
|
|
143465
143539
|
["recovery_no_eligible_head_count", 0],
|
|
143466
143540
|
["force_emergency_bypass_window_start", 0],
|
|
143467
|
-
["force_emergency_bypass_used", 0]
|
|
143541
|
+
["force_emergency_bypass_used", 0],
|
|
143542
|
+
["emergency_drain_active", 0],
|
|
143543
|
+
["historian_drain_failure_at", 0]
|
|
143468
143544
|
];
|
|
143469
143545
|
for (const [column, fallback] of columns) {
|
|
143470
143546
|
try {
|
|
@@ -143540,6 +143616,7 @@ function openDatabase(dbPathOrOptions) {
|
|
|
143540
143616
|
setDatabase(db);
|
|
143541
143617
|
loadToolDefinitionMeasurements(db);
|
|
143542
143618
|
databases.set(dbPath, db);
|
|
143619
|
+
pathByDatabase.set(db, dbPath);
|
|
143543
143620
|
persistenceByDatabase.set(db, true);
|
|
143544
143621
|
persistenceErrorByDatabase.delete(db);
|
|
143545
143622
|
return db;
|
|
@@ -158101,7 +158178,6 @@ var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65;
|
|
|
158101
158178
|
var EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 80% for cache safety: a single large agent step can overflow the context window before Magic Context can compact between turns, forcing OpenCode's native compaction (hard to recover from). 80% also leaves headroom below the 85%/95% emergency bands. Use a value between 20 and 80.";
|
|
158102
158179
|
var DEFAULT_HISTORIAN_TIMEOUT_MS = 300000;
|
|
158103
158180
|
var DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15;
|
|
158104
|
-
var DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2";
|
|
158105
158181
|
var DREAMER_TASKS = [
|
|
158106
158182
|
"consolidate",
|
|
158107
158183
|
"verify",
|
|
@@ -158141,14 +158217,16 @@ var SidekickConfigSchema = AgentOverrideConfigSchema.extend({
|
|
|
158141
158217
|
}).optional();
|
|
158142
158218
|
var HistorianConfigSchema = AgentOverrideConfigSchema.extend({
|
|
158143
158219
|
two_pass: exports_external.boolean().default(false).describe("Run a second editor pass over historian output to clean low-signal U: lines and cross-compartment duplicates. Adds ~1 extra API call and ~1.3x cost per historian run. Useful for models without extended thinking support. (default: false)"),
|
|
158144
|
-
thinking_level: PiThinkingLevelSchema.describe("Pi only: explicit thinking level passed as --thinking <level> to Pi historian subagent invocations. Required when using reasoning models (e.g. github-copilot/gpt-5.4) because Pi's default thinking-level resolution can pick a value the provider rejects. OpenCode users set variant instead. Valid: off | minimal | low | medium | high | xhigh")
|
|
158220
|
+
thinking_level: PiThinkingLevelSchema.describe("Pi only: explicit thinking level passed as --thinking <level> to Pi historian subagent invocations. Required when using reasoning models (e.g. github-copilot/gpt-5.4) because Pi's default thinking-level resolution can pick a value the provider rejects. OpenCode users set variant instead. Valid: off | minimal | low | medium | high | xhigh"),
|
|
158221
|
+
disallowed_tools: exports_external.array(exports_external.enum(["*", "read", "aft_outline", "aft_zoom", "aft_search"])).default([]).describe(`OpenCode only. Tools to REMOVE from the historian's default allow-list [read, aft_outline, aft_zoom, aft_search]. Applies to both historian and historian-editor agents. Use ["*"] to strip all tool definitions from the model request — this prevents weak instruction-following models (e.g. mistral-small-latest) from entering tool-calling loops. Individual tool names remove just that tool. Note: a user-supplied historian.permission override can re-allow a tool that disallowed_tools removed — disallowed_tools sets the baseline, permission overrides take precedence. (default: [])`)
|
|
158145
158222
|
}).optional();
|
|
158146
158223
|
var BaseEmbeddingConfigSchema = exports_external.object({
|
|
158147
|
-
provider: exports_external.enum(["
|
|
158148
|
-
model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible
|
|
158224
|
+
provider: exports_external.enum(["openai-compatible", "off"]).default("off").describe("Embedding provider. 'openai-compatible' requires endpoint and model, 'off' disables embeddings (default)."),
|
|
158225
|
+
model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible."),
|
|
158149
158226
|
endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
|
|
158150
158227
|
api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
|
|
158151
|
-
input_type: exports_external.string().optional().describe("
|
|
158228
|
+
input_type: exports_external.string().optional().describe("Default input_type for stored/indexed (passage) embeddings in the request body. Required by some openai-compatible providers (e.g. NVIDIA NIM). Omitted from the request when unset."),
|
|
158229
|
+
query_input_type: exports_external.string().optional().describe("Optional input_type for query (search) embeddings on asymmetric models (e.g. NVIDIA NIM 'query'). When unset, query embeddings use embedding.input_type. Passage/stored content always uses embedding.input_type."),
|
|
158152
158230
|
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."),
|
|
158153
158231
|
max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
|
|
158154
158232
|
}).superRefine((data, ctx) => {
|
|
@@ -158168,16 +158246,10 @@ var BaseEmbeddingConfigSchema = exports_external.object({
|
|
|
158168
158246
|
}
|
|
158169
158247
|
});
|
|
158170
158248
|
var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
|
|
158171
|
-
if (data.provider === "local") {
|
|
158172
|
-
return {
|
|
158173
|
-
provider: "local",
|
|
158174
|
-
model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
158175
|
-
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
|
|
158176
|
-
};
|
|
158177
|
-
}
|
|
158178
158249
|
if (data.provider === "openai-compatible") {
|
|
158179
158250
|
const apiKey = data.api_key?.trim();
|
|
158180
158251
|
const inputType = data.input_type?.trim();
|
|
158252
|
+
const queryInputType = data.query_input_type?.trim();
|
|
158181
158253
|
const truncate = data.truncate?.trim();
|
|
158182
158254
|
return {
|
|
158183
158255
|
provider: "openai-compatible",
|
|
@@ -158185,6 +158257,7 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
|
|
|
158185
158257
|
endpoint: data.endpoint?.trim() ?? "",
|
|
158186
158258
|
...apiKey ? { api_key: apiKey } : {},
|
|
158187
158259
|
...inputType ? { input_type: inputType } : {},
|
|
158260
|
+
...queryInputType ? { query_input_type: queryInputType } : {},
|
|
158188
158261
|
...truncate ? { truncate } : {},
|
|
158189
158262
|
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
|
|
158190
158263
|
};
|
|
@@ -158224,8 +158297,7 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
158224
158297
|
mmap_size_mb: exports_external.number().min(0).max(8192).default(0).describe("Memory-mapped I/O size in MiB (PRAGMA mmap_size). 0 disables mmap (SQLite default). Raising it can cut read overhead on large DBs at the cost of address space. (min 0, max 8192, default 0)")
|
|
158225
158298
|
}).default({ cache_size_mb: 64, mmap_size_mb: 0 }).describe("SQLite connection tuning for Magic Context's own context.db. These are per-connection PRAGMAs applied at open; they do not change the schema or what is stored."),
|
|
158226
158299
|
embedding: EmbeddingConfigSchema.default({
|
|
158227
|
-
provider: "
|
|
158228
|
-
model: DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
158300
|
+
provider: "off"
|
|
158229
158301
|
}).describe("Embedding provider configuration"),
|
|
158230
158302
|
temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add start/end date attributes on compartments. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
|
|
158231
158303
|
keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
|
|
@@ -158908,6 +158980,16 @@ function buildCanonicalChunkTextFromFts(db, sessionId, startOrdinal, endOrdinal)
|
|
|
158908
158980
|
return lines.join(`
|
|
158909
158981
|
`);
|
|
158910
158982
|
}
|
|
158983
|
+
function buildCompartmentSummaryFallbackText(db, compartmentId) {
|
|
158984
|
+
const row = db.prepare("SELECT title, p1, content FROM compartments WHERE id = ?").get(compartmentId);
|
|
158985
|
+
if (!row)
|
|
158986
|
+
return "";
|
|
158987
|
+
const title = typeof row.title === "string" ? row.title.trim() : "";
|
|
158988
|
+
const p1 = typeof row.p1 === "string" ? row.p1.trim() : "";
|
|
158989
|
+
const body = p1.length > 0 ? p1 : typeof row.content === "string" ? row.content.trim() : "";
|
|
158990
|
+
return [title, body].filter((s) => s.length > 0).join(`
|
|
158991
|
+
`);
|
|
158992
|
+
}
|
|
158911
158993
|
function canonicalizeInMemoryChunkTextForEmbedding(chunkText, startOrdinal, endOrdinal) {
|
|
158912
158994
|
const lines = [];
|
|
158913
158995
|
for (const rawLine of chunkText.split(/\r?\n/)) {
|
|
@@ -159215,377 +159297,11 @@ function getEmbeddingProviderIdentity(config2) {
|
|
|
159215
159297
|
endpoint: normalizeEndpoint2(config2.endpoint),
|
|
159216
159298
|
apiKeyPresent: Boolean(config2.api_key?.trim()),
|
|
159217
159299
|
inputType: config2.input_type?.trim() || ""
|
|
159218
|
-
} :
|
|
159219
|
-
|
|
159220
|
-
|
|
159221
|
-
endpoint: "",
|
|
159222
|
-
apiKeyPresent: false
|
|
159223
|
-
};
|
|
159224
|
-
return `embedding-provider:${computeNormalizedHash(JSON.stringify(identityInput))}`;
|
|
159225
|
-
}
|
|
159226
|
-
|
|
159227
|
-
// ../plugin/src/features/magic-context/memory/embedding-local.ts
|
|
159228
|
-
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
159229
|
-
import { open, stat, unlink, writeFile } from "node:fs/promises";
|
|
159230
|
-
import { dirname as dirname4, join as join6 } from "node:path";
|
|
159231
|
-
import { pathToFileURL } from "node:url";
|
|
159232
|
-
init_data_path();
|
|
159233
|
-
init_logger();
|
|
159234
|
-
var LOCK_POLL_MS = 150;
|
|
159235
|
-
var STALE_LOCK_MS = 3 * 60000;
|
|
159236
|
-
var MAX_LOCK_WAIT_MS = 5 * 60000;
|
|
159237
|
-
async function acquireModelLoadLock(lockPath) {
|
|
159238
|
-
const waitStart = Date.now();
|
|
159239
|
-
while (true) {
|
|
159240
|
-
try {
|
|
159241
|
-
const handle = await open(lockPath, "wx");
|
|
159242
|
-
try {
|
|
159243
|
-
await handle.writeFile(`pid=${process.pid} started=${Date.now()}
|
|
159244
|
-
`);
|
|
159245
|
-
} catch {}
|
|
159246
|
-
await handle.close();
|
|
159247
|
-
return async () => {
|
|
159248
|
-
try {
|
|
159249
|
-
await unlink(lockPath);
|
|
159250
|
-
} catch {}
|
|
159251
|
-
};
|
|
159252
|
-
} catch (error51) {
|
|
159253
|
-
const code = error51.code;
|
|
159254
|
-
if (code !== "EEXIST" && code !== "EPERM") {
|
|
159255
|
-
throw error51;
|
|
159256
|
-
}
|
|
159257
|
-
try {
|
|
159258
|
-
const info = await stat(lockPath);
|
|
159259
|
-
if (Date.now() - info.mtimeMs > STALE_LOCK_MS) {
|
|
159260
|
-
log(`[magic-context] embedding-load lock stale (>${STALE_LOCK_MS}ms), taking over`);
|
|
159261
|
-
try {
|
|
159262
|
-
await unlink(lockPath);
|
|
159263
|
-
} catch {}
|
|
159264
|
-
continue;
|
|
159265
|
-
}
|
|
159266
|
-
} catch {
|
|
159267
|
-
continue;
|
|
159268
|
-
}
|
|
159269
|
-
if (Date.now() - waitStart > MAX_LOCK_WAIT_MS) {
|
|
159270
|
-
throw new Error(`[magic-context] embedding-load lock wait exceeded ${MAX_LOCK_WAIT_MS}ms; another process is still loading the model. Skipping this init attempt to avoid an unsynchronized native load.`);
|
|
159271
|
-
}
|
|
159272
|
-
await new Promise((resolve3) => setTimeout(resolve3, LOCK_POLL_MS));
|
|
159273
|
-
}
|
|
159274
|
-
}
|
|
159275
|
-
}
|
|
159276
|
-
function startLockHeartbeat(lockPath) {
|
|
159277
|
-
const HEARTBEAT_MS = Math.floor(STALE_LOCK_MS / 3);
|
|
159278
|
-
const timer = setInterval(() => {
|
|
159279
|
-
writeFile(lockPath, `pid=${process.pid} alive=${Date.now()}
|
|
159280
|
-
`).catch(() => {});
|
|
159281
|
-
}, HEARTBEAT_MS);
|
|
159282
|
-
timer.unref?.();
|
|
159283
|
-
return () => clearInterval(timer);
|
|
159284
|
-
}
|
|
159285
|
-
async function injectWasmOrtForElectron() {
|
|
159286
|
-
if (typeof process === "undefined" || !process.versions?.electron) {
|
|
159287
|
-
return false;
|
|
159288
|
-
}
|
|
159289
|
-
try {
|
|
159290
|
-
const ortWebSpec = `onnxruntime-${"web"}`;
|
|
159291
|
-
const ortWeb = await import(ortWebSpec);
|
|
159292
|
-
try {
|
|
159293
|
-
const { createRequire: createRequireFn } = await import("node:module");
|
|
159294
|
-
const requireFn = createRequireFn(import.meta.url);
|
|
159295
|
-
const pkgPath = requireFn.resolve("onnxruntime-web/package.json");
|
|
159296
|
-
const distDir = join6(dirname4(pkgPath), "dist");
|
|
159297
|
-
const wasmPathsPrefix = `${pathToFileURL(distDir).href}/`;
|
|
159298
|
-
if (ortWeb.env?.wasm) {
|
|
159299
|
-
ortWeb.env.wasm.wasmPaths = wasmPathsPrefix;
|
|
159300
|
-
}
|
|
159301
|
-
} catch (pathError) {
|
|
159302
|
-
log("[magic-context] could not resolve local onnxruntime-web/dist, falling back to default WASM paths:", pathError instanceof Error ? pathError.message : String(pathError));
|
|
159303
|
-
}
|
|
159304
|
-
globalThis[Symbol.for("onnxruntime")] = ortWeb;
|
|
159305
|
-
log("[magic-context] Electron detected — using onnxruntime-web (WASM) for embeddings (bypasses onnxruntime-node native load)");
|
|
159306
|
-
return true;
|
|
159307
|
-
} catch (error51) {
|
|
159308
|
-
log("[magic-context] failed to inject onnxruntime-web for Electron — letting transformers fall back to native:", error51 instanceof Error ? error51.message : String(error51));
|
|
159309
|
-
return false;
|
|
159310
|
-
}
|
|
159311
|
-
}
|
|
159312
|
-
async function withQuietConsole(fn) {
|
|
159313
|
-
const origWarn = console.warn;
|
|
159314
|
-
const origError = console.error;
|
|
159315
|
-
const redirect = (...args) => {
|
|
159316
|
-
const message = args.map((a) => typeof a === "string" ? a : String(a)).join(" ");
|
|
159317
|
-
log(`[transformers] ${message}`);
|
|
159318
|
-
};
|
|
159319
|
-
console.warn = redirect;
|
|
159320
|
-
console.error = redirect;
|
|
159321
|
-
try {
|
|
159322
|
-
return await fn();
|
|
159323
|
-
} finally {
|
|
159324
|
-
console.warn = origWarn;
|
|
159325
|
-
console.error = origError;
|
|
159326
|
-
}
|
|
159327
|
-
}
|
|
159328
|
-
var nativeRuntimeMissing = false;
|
|
159329
|
-
function isNativeRuntimeMissingError(error51) {
|
|
159330
|
-
const message = error51 instanceof Error ? error51.message : String(error51 ?? "");
|
|
159331
|
-
const lower = message.toLowerCase();
|
|
159332
|
-
const code = error51?.code;
|
|
159333
|
-
const name2 = error51?.name;
|
|
159334
|
-
if (code === "ERR_DLOPEN_FAILED" && lower.includes("onnxruntime")) {
|
|
159335
|
-
return true;
|
|
159336
|
-
}
|
|
159337
|
-
if (!lower.includes("onnxruntime-node"))
|
|
159338
|
-
return false;
|
|
159339
|
-
return code === "ERR_MODULE_NOT_FOUND" || name2 === "ResolveMessage" || lower.includes("cannot find package") || lower.includes("cannot find module") || lower.includes("err_module_not_found");
|
|
159340
|
-
}
|
|
159341
|
-
function isTransientLoadError(error51) {
|
|
159342
|
-
const message = error51 instanceof Error ? error51.message : String(error51 ?? "");
|
|
159343
|
-
if (!message)
|
|
159344
|
-
return false;
|
|
159345
|
-
const lower = message.toLowerCase();
|
|
159346
|
-
return lower.includes("protobuf parsing failed") || lower.includes("unable to get model file path or buffer") || lower.includes("ebusy") || lower.includes("resource busy") || lower.includes("resource temporarily unavailable");
|
|
159347
|
-
}
|
|
159348
|
-
function isArrayLikeNumber(value) {
|
|
159349
|
-
if (typeof value !== "object" || value === null || !("length" in value)) {
|
|
159350
|
-
return false;
|
|
159351
|
-
}
|
|
159352
|
-
const arr = value;
|
|
159353
|
-
if (typeof arr.length !== "number") {
|
|
159354
|
-
return false;
|
|
159355
|
-
}
|
|
159356
|
-
return arr.length === 0 || typeof arr[0] === "number";
|
|
159357
|
-
}
|
|
159358
|
-
function toFloat32Array2(values) {
|
|
159359
|
-
return values instanceof Float32Array ? new Float32Array(values) : Float32Array.from(Array.from(values));
|
|
159360
|
-
}
|
|
159361
|
-
function extractBatchEmbeddings(result, expectedCount) {
|
|
159362
|
-
const { data } = result;
|
|
159363
|
-
if (Array.isArray(data) && data.length === expectedCount && data.every((entry) => typeof entry !== "number" && isArrayLikeNumber(entry))) {
|
|
159364
|
-
return data.map((entry) => toFloat32Array2(entry));
|
|
159365
|
-
}
|
|
159366
|
-
if (!isArrayLikeNumber(data)) {
|
|
159367
|
-
log("[magic-context] embedding batch returned unexpected data shape");
|
|
159368
|
-
return Array.from({ length: expectedCount }, () => null);
|
|
159369
|
-
}
|
|
159370
|
-
const flatData = toFloat32Array2(data);
|
|
159371
|
-
const dimension = result.dims?.at(-1) ?? flatData.length / expectedCount;
|
|
159372
|
-
if (!Number.isInteger(dimension) || dimension <= 0 || flatData.length !== expectedCount * dimension) {
|
|
159373
|
-
log("[magic-context] embedding batch returned invalid dimensions");
|
|
159374
|
-
return Array.from({ length: expectedCount }, () => null);
|
|
159375
|
-
}
|
|
159376
|
-
const embeddings = [];
|
|
159377
|
-
for (let index = 0;index < expectedCount; index++) {
|
|
159378
|
-
embeddings.push(flatData.slice(index * dimension, (index + 1) * dimension));
|
|
159379
|
-
}
|
|
159380
|
-
return embeddings;
|
|
159381
|
-
}
|
|
159382
|
-
|
|
159383
|
-
class LocalEmbeddingProvider {
|
|
159384
|
-
modelId;
|
|
159385
|
-
maxInputTokens;
|
|
159386
|
-
model;
|
|
159387
|
-
pipeline = null;
|
|
159388
|
-
initPromise = null;
|
|
159389
|
-
inFlight = 0;
|
|
159390
|
-
disposing = false;
|
|
159391
|
-
disposePromise = null;
|
|
159392
|
-
inFlightWaiters = [];
|
|
159393
|
-
constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512) {
|
|
159394
|
-
this.model = model;
|
|
159395
|
-
this.maxInputTokens = maxInputTokens;
|
|
159396
|
-
this.modelId = getEmbeddingProviderIdentity({ provider: "local", model });
|
|
159397
|
-
}
|
|
159398
|
-
async initialize() {
|
|
159399
|
-
if (this.disposing) {
|
|
159400
|
-
return false;
|
|
159401
|
-
}
|
|
159402
|
-
if (this.pipeline) {
|
|
159403
|
-
return true;
|
|
159404
|
-
}
|
|
159405
|
-
if (nativeRuntimeMissing) {
|
|
159406
|
-
return false;
|
|
159407
|
-
}
|
|
159408
|
-
if (this.initPromise) {
|
|
159409
|
-
await this.initPromise;
|
|
159410
|
-
return this.pipeline !== null;
|
|
159411
|
-
}
|
|
159412
|
-
this.initPromise = (async () => {
|
|
159413
|
-
try {
|
|
159414
|
-
if (this.disposing) {
|
|
159415
|
-
return;
|
|
159416
|
-
}
|
|
159417
|
-
await injectWasmOrtForElectron();
|
|
159418
|
-
const transformersSpec = "@huggingface/transformers";
|
|
159419
|
-
const transformersModule = await import(transformersSpec);
|
|
159420
|
-
const env = transformersModule.env;
|
|
159421
|
-
const LogLevel = transformersModule.LogLevel;
|
|
159422
|
-
if (LogLevel && "ERROR" in LogLevel) {
|
|
159423
|
-
env.logLevel = LogLevel.ERROR;
|
|
159424
|
-
}
|
|
159425
|
-
const modelCacheDir = join6(getMagicContextStorageDir(), "models");
|
|
159426
|
-
try {
|
|
159427
|
-
mkdirSync3(modelCacheDir, { recursive: true });
|
|
159428
|
-
env.cacheDir = modelCacheDir;
|
|
159429
|
-
} catch {
|
|
159430
|
-
log("[magic-context] could not create model cache dir, using library default");
|
|
159431
|
-
}
|
|
159432
|
-
const createPipeline = transformersModule.pipeline;
|
|
159433
|
-
const lockPath = join6(modelCacheDir, ".load.lock");
|
|
159434
|
-
const releaseLock = await acquireModelLoadLock(lockPath);
|
|
159435
|
-
const stopHeartbeat = startLockHeartbeat(lockPath);
|
|
159436
|
-
try {
|
|
159437
|
-
const MAX_ATTEMPTS = 3;
|
|
159438
|
-
let lastError;
|
|
159439
|
-
for (let attempt = 1;attempt <= MAX_ATTEMPTS; attempt++) {
|
|
159440
|
-
try {
|
|
159441
|
-
const pipeline = await withQuietConsole(() => createPipeline("feature-extraction", this.model, {
|
|
159442
|
-
dtype: "fp32"
|
|
159443
|
-
}));
|
|
159444
|
-
if (this.disposing) {
|
|
159445
|
-
await pipeline.dispose?.();
|
|
159446
|
-
this.pipeline = null;
|
|
159447
|
-
} else {
|
|
159448
|
-
this.pipeline = pipeline;
|
|
159449
|
-
}
|
|
159450
|
-
lastError = undefined;
|
|
159451
|
-
break;
|
|
159452
|
-
} catch (error51) {
|
|
159453
|
-
lastError = error51;
|
|
159454
|
-
if (!isTransientLoadError(error51) || attempt === MAX_ATTEMPTS) {
|
|
159455
|
-
break;
|
|
159456
|
-
}
|
|
159457
|
-
const delayMs = 300 * attempt + Math.floor(Math.random() * 200);
|
|
159458
|
-
log(`[magic-context] embedding model load attempt ${attempt}/${MAX_ATTEMPTS} failed transiently, retrying in ${delayMs}ms`);
|
|
159459
|
-
await new Promise((resolve3) => setTimeout(resolve3, delayMs));
|
|
159460
|
-
}
|
|
159461
|
-
}
|
|
159462
|
-
if (this.pipeline) {
|
|
159463
|
-
log(`[magic-context] embedding model loaded: ${this.model}`);
|
|
159464
|
-
} else if (this.disposing) {
|
|
159465
|
-
return;
|
|
159466
|
-
} else {
|
|
159467
|
-
throw lastError ?? new Error("unknown embedding load failure");
|
|
159468
|
-
}
|
|
159469
|
-
} finally {
|
|
159470
|
-
stopHeartbeat();
|
|
159471
|
-
await releaseLock();
|
|
159472
|
-
}
|
|
159473
|
-
} catch (error51) {
|
|
159474
|
-
if (isNativeRuntimeMissingError(error51)) {
|
|
159475
|
-
nativeRuntimeMissing = true;
|
|
159476
|
-
log("[magic-context] local embedding runtime is not installed (onnxruntime-node missing from this install). Local embeddings are disabled. Fix: reinstall the plugin (run `npx @wolfx/magic-context@latest doctor --force`), or configure an `openai-compatible`/`ollama` embedding endpoint instead. Existing memories are unaffected.");
|
|
159477
|
-
} else {
|
|
159478
|
-
log("[magic-context] embedding model failed to load:", error51);
|
|
159479
|
-
}
|
|
159480
|
-
this.pipeline = null;
|
|
159481
|
-
} finally {
|
|
159482
|
-
this.initPromise = null;
|
|
159483
|
-
}
|
|
159484
|
-
})();
|
|
159485
|
-
await this.initPromise;
|
|
159486
|
-
return this.pipeline !== null;
|
|
159487
|
-
}
|
|
159488
|
-
waitForInFlightToDrain() {
|
|
159489
|
-
if (this.inFlight === 0) {
|
|
159490
|
-
return Promise.resolve();
|
|
159491
|
-
}
|
|
159492
|
-
return new Promise((resolve3) => {
|
|
159493
|
-
this.inFlightWaiters.push(resolve3);
|
|
159494
|
-
});
|
|
159495
|
-
}
|
|
159496
|
-
finishInFlight() {
|
|
159497
|
-
this.inFlight = Math.max(0, this.inFlight - 1);
|
|
159498
|
-
if (this.inFlight !== 0)
|
|
159499
|
-
return;
|
|
159500
|
-
const waiters = this.inFlightWaiters.splice(0);
|
|
159501
|
-
for (const waiter of waiters) {
|
|
159502
|
-
waiter();
|
|
159503
|
-
}
|
|
159504
|
-
}
|
|
159505
|
-
async embed(text, signal) {
|
|
159506
|
-
if (signal?.aborted)
|
|
159507
|
-
return null;
|
|
159508
|
-
if (this.disposing)
|
|
159509
|
-
return null;
|
|
159510
|
-
this.inFlight += 1;
|
|
159511
|
-
try {
|
|
159512
|
-
if (!await this.initialize()) {
|
|
159513
|
-
return null;
|
|
159514
|
-
}
|
|
159515
|
-
const pipeline = this.pipeline;
|
|
159516
|
-
if (!pipeline) {
|
|
159517
|
-
return null;
|
|
159518
|
-
}
|
|
159519
|
-
const result = await withQuietConsole(() => pipeline(text, {
|
|
159520
|
-
pooling: "mean",
|
|
159521
|
-
normalize: true
|
|
159522
|
-
}));
|
|
159523
|
-
return extractBatchEmbeddings(result, 1)[0] ?? null;
|
|
159524
|
-
} catch (error51) {
|
|
159525
|
-
log("[magic-context] embedding failed:", error51);
|
|
159526
|
-
return null;
|
|
159527
|
-
} finally {
|
|
159528
|
-
this.finishInFlight();
|
|
159529
|
-
}
|
|
159530
|
-
}
|
|
159531
|
-
async embedBatch(texts, signal) {
|
|
159532
|
-
if (texts.length === 0) {
|
|
159533
|
-
return [];
|
|
159534
|
-
}
|
|
159535
|
-
if (signal?.aborted) {
|
|
159536
|
-
return Array.from({ length: texts.length }, () => null);
|
|
159537
|
-
}
|
|
159538
|
-
if (this.disposing) {
|
|
159539
|
-
return Array.from({ length: texts.length }, () => null);
|
|
159540
|
-
}
|
|
159541
|
-
this.inFlight += 1;
|
|
159542
|
-
try {
|
|
159543
|
-
if (!await this.initialize()) {
|
|
159544
|
-
return Array.from({ length: texts.length }, () => null);
|
|
159545
|
-
}
|
|
159546
|
-
const pipeline = this.pipeline;
|
|
159547
|
-
if (!pipeline) {
|
|
159548
|
-
return Array.from({ length: texts.length }, () => null);
|
|
159549
|
-
}
|
|
159550
|
-
const result = await withQuietConsole(() => pipeline(texts, {
|
|
159551
|
-
pooling: "mean",
|
|
159552
|
-
normalize: true
|
|
159553
|
-
}));
|
|
159554
|
-
return extractBatchEmbeddings(result, texts.length);
|
|
159555
|
-
} catch (error51) {
|
|
159556
|
-
log("[magic-context] embedding batch failed:", error51);
|
|
159557
|
-
return Array.from({ length: texts.length }, () => null);
|
|
159558
|
-
} finally {
|
|
159559
|
-
this.finishInFlight();
|
|
159560
|
-
}
|
|
159561
|
-
}
|
|
159562
|
-
async dispose() {
|
|
159563
|
-
if (this.disposePromise) {
|
|
159564
|
-
return this.disposePromise;
|
|
159565
|
-
}
|
|
159566
|
-
this.disposing = true;
|
|
159567
|
-
this.disposePromise = (async () => {
|
|
159568
|
-
if (this.initPromise) {
|
|
159569
|
-
await this.initPromise;
|
|
159570
|
-
}
|
|
159571
|
-
await this.waitForInFlightToDrain();
|
|
159572
|
-
const pipelineToDispose = this.pipeline;
|
|
159573
|
-
this.pipeline = null;
|
|
159574
|
-
this.initPromise = null;
|
|
159575
|
-
if (!pipelineToDispose) {
|
|
159576
|
-
return;
|
|
159577
|
-
}
|
|
159578
|
-
try {
|
|
159579
|
-
await pipelineToDispose.dispose?.();
|
|
159580
|
-
} catch (error51) {
|
|
159581
|
-
log("[magic-context] embedding model dispose failed:", error51);
|
|
159582
|
-
}
|
|
159583
|
-
})();
|
|
159584
|
-
return this.disposePromise;
|
|
159585
|
-
}
|
|
159586
|
-
isLoaded() {
|
|
159587
|
-
return this.pipeline !== null;
|
|
159300
|
+
} : null;
|
|
159301
|
+
if (!identityInput) {
|
|
159302
|
+
return "embedding-provider:off";
|
|
159588
159303
|
}
|
|
159304
|
+
return `embedding-provider:${computeNormalizedHash(JSON.stringify(identityInput))}`;
|
|
159589
159305
|
}
|
|
159590
159306
|
|
|
159591
159307
|
// ../plugin/src/features/magic-context/memory/embedding-openai.ts
|
|
@@ -159667,6 +159383,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
159667
159383
|
model;
|
|
159668
159384
|
apiKey;
|
|
159669
159385
|
inputType;
|
|
159386
|
+
queryInputType;
|
|
159670
159387
|
truncate;
|
|
159671
159388
|
initialized = false;
|
|
159672
159389
|
failureTimes = [];
|
|
@@ -159679,6 +159396,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
159679
159396
|
this.model = options.model?.trim() ?? "";
|
|
159680
159397
|
this.apiKey = options.apiKey?.trim() ?? "";
|
|
159681
159398
|
this.inputType = options.inputType?.trim() ?? "";
|
|
159399
|
+
this.queryInputType = options.queryInputType?.trim() ?? "";
|
|
159682
159400
|
this.truncate = options.truncate?.trim() ?? "";
|
|
159683
159401
|
this.maxInputTokens = typeof options.maxInputTokens === "number" && Number.isFinite(options.maxInputTokens) ? Math.max(1, Math.floor(options.maxInputTokens)) : 512;
|
|
159684
159402
|
this.modelId = getEmbeddingProviderIdentity({
|
|
@@ -159706,11 +159424,17 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
159706
159424
|
this.initialized = true;
|
|
159707
159425
|
return true;
|
|
159708
159426
|
}
|
|
159709
|
-
|
|
159710
|
-
|
|
159427
|
+
resolveInputTypeForPurpose(purpose = "passage") {
|
|
159428
|
+
if (purpose === "query") {
|
|
159429
|
+
return this.queryInputType || this.inputType;
|
|
159430
|
+
}
|
|
159431
|
+
return this.inputType;
|
|
159432
|
+
}
|
|
159433
|
+
async embed(text, signal, purpose) {
|
|
159434
|
+
const [embedding] = await this.embedBatch([text], signal, purpose);
|
|
159711
159435
|
return embedding ?? null;
|
|
159712
159436
|
}
|
|
159713
|
-
async embedBatch(texts, signal) {
|
|
159437
|
+
async embedBatch(texts, signal, purpose) {
|
|
159714
159438
|
if (texts.length === 0) {
|
|
159715
159439
|
return [];
|
|
159716
159440
|
}
|
|
@@ -159736,6 +159460,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
159736
159460
|
if (signal) {
|
|
159737
159461
|
signal.addEventListener("abort", onOuterAbort, { once: true });
|
|
159738
159462
|
}
|
|
159463
|
+
const inputTypeForRequest = this.resolveInputTypeForPurpose(purpose);
|
|
159739
159464
|
const response = await fetch(`${this.endpoint}/embeddings`, {
|
|
159740
159465
|
method: "POST",
|
|
159741
159466
|
headers: {
|
|
@@ -159745,7 +159470,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
159745
159470
|
body: JSON.stringify({
|
|
159746
159471
|
model: this.model,
|
|
159747
159472
|
input: texts,
|
|
159748
|
-
...
|
|
159473
|
+
...inputTypeForRequest ? { input_type: inputTypeForRequest } : {},
|
|
159749
159474
|
...this.truncate ? { truncate: this.truncate } : {}
|
|
159750
159475
|
}),
|
|
159751
159476
|
redirect: "error",
|
|
@@ -159901,7 +159626,7 @@ function isEmbeddingRow(row) {
|
|
|
159901
159626
|
const candidate = row;
|
|
159902
159627
|
return typeof candidate.memoryId === "number" && isEmbeddingBlob(candidate.embedding) && (candidate.modelId === null || typeof candidate.modelId === "string");
|
|
159903
159628
|
}
|
|
159904
|
-
function
|
|
159629
|
+
function toFloat32Array2(blob) {
|
|
159905
159630
|
if (blob instanceof Uint8Array) {
|
|
159906
159631
|
const buffer2 = blob.buffer.slice(blob.byteOffset, blob.byteOffset + blob.byteLength);
|
|
159907
159632
|
return new Float32Array(buffer2);
|
|
@@ -159949,7 +159674,7 @@ function loadAllEmbeddings(db, projectPath) {
|
|
|
159949
159674
|
const embeddings = new Map;
|
|
159950
159675
|
for (const row of rows) {
|
|
159951
159676
|
embeddings.set(row.memoryId, {
|
|
159952
|
-
embedding:
|
|
159677
|
+
embedding: toFloat32Array2(row.embedding),
|
|
159953
159678
|
modelId: row.modelId
|
|
159954
159679
|
});
|
|
159955
159680
|
}
|
|
@@ -159978,8 +159703,8 @@ function getMemoryEmbedCoverage(db, projectPath, modelId) {
|
|
|
159978
159703
|
}
|
|
159979
159704
|
|
|
159980
159705
|
// ../plugin/src/features/magic-context/project-embedding-registry.ts
|
|
159981
|
-
import { createHash as createHash6, randomUUID } from "node:crypto";
|
|
159982
159706
|
init_logger();
|
|
159707
|
+
import { createHash as createHash6, randomUUID } from "node:crypto";
|
|
159983
159708
|
|
|
159984
159709
|
// ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
|
|
159985
159710
|
var saveStatements = new WeakMap;
|
|
@@ -160437,18 +160162,13 @@ var loadUnembeddedMemoriesStatements = new WeakMap;
|
|
|
160437
160162
|
var globalRegistrationGeneration = 0;
|
|
160438
160163
|
var testProviderFactory = null;
|
|
160439
160164
|
function resolveEmbeddingConfig(config2) {
|
|
160440
|
-
if (!config2 || config2.provider === "
|
|
160441
|
-
return {
|
|
160442
|
-
provider: "local",
|
|
160443
|
-
model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
160444
|
-
...config2?.max_input_tokens ? {
|
|
160445
|
-
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
160446
|
-
} : {}
|
|
160447
|
-
};
|
|
160165
|
+
if (!config2 || config2.provider === "off") {
|
|
160166
|
+
return { provider: "off" };
|
|
160448
160167
|
}
|
|
160449
160168
|
if (config2.provider === "openai-compatible") {
|
|
160450
160169
|
const apiKey = config2.api_key?.trim();
|
|
160451
160170
|
const inputType = config2.input_type?.trim();
|
|
160171
|
+
const queryInputType = config2.query_input_type?.trim();
|
|
160452
160172
|
const truncate = config2.truncate?.trim();
|
|
160453
160173
|
return {
|
|
160454
160174
|
provider: "openai-compatible",
|
|
@@ -160456,6 +160176,7 @@ function resolveEmbeddingConfig(config2) {
|
|
|
160456
160176
|
endpoint: config2.endpoint.trim(),
|
|
160457
160177
|
...apiKey ? { api_key: apiKey } : {},
|
|
160458
160178
|
...inputType ? { input_type: inputType } : {},
|
|
160179
|
+
...queryInputType ? { query_input_type: queryInputType } : {},
|
|
160459
160180
|
...truncate ? { truncate } : {},
|
|
160460
160181
|
...config2.max_input_tokens ? {
|
|
160461
160182
|
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
@@ -160477,11 +160198,12 @@ function createProvider(config2) {
|
|
|
160477
160198
|
model: config2.model,
|
|
160478
160199
|
apiKey: config2.api_key,
|
|
160479
160200
|
inputType: config2.input_type,
|
|
160201
|
+
queryInputType: config2.query_input_type,
|
|
160480
160202
|
truncate: config2.truncate,
|
|
160481
160203
|
maxInputTokens: config2.max_input_tokens
|
|
160482
160204
|
});
|
|
160483
160205
|
}
|
|
160484
|
-
return
|
|
160206
|
+
return null;
|
|
160485
160207
|
}
|
|
160486
160208
|
function stableStringify2(value) {
|
|
160487
160209
|
if (Array.isArray(value)) {
|
|
@@ -160533,7 +160255,7 @@ function snapshotFor(registration) {
|
|
|
160533
160255
|
modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
|
|
160534
160256
|
chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId,
|
|
160535
160257
|
model: registration.observationMode || !providerIsOn ? "off" : ("model" in registration.config) && registration.config.model.trim() ? registration.config.model.trim() : registration.modelId,
|
|
160536
|
-
provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "
|
|
160258
|
+
provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "off"
|
|
160537
160259
|
};
|
|
160538
160260
|
}
|
|
160539
160261
|
function disposeProvider(provider) {
|
|
@@ -160659,7 +160381,7 @@ function getOrCreateProjectProvider(registration) {
|
|
|
160659
160381
|
registration.provider = provider;
|
|
160660
160382
|
return provider;
|
|
160661
160383
|
}
|
|
160662
|
-
async function embedTextForProject(projectIdentity, text, signal) {
|
|
160384
|
+
async function embedTextForProject(projectIdentity, text, signal, purpose = "passage") {
|
|
160663
160385
|
const registration = projectRegistrations.get(projectIdentity);
|
|
160664
160386
|
if (!registration)
|
|
160665
160387
|
return null;
|
|
@@ -160668,7 +160390,7 @@ async function embedTextForProject(projectIdentity, text, signal) {
|
|
|
160668
160390
|
const provider = getOrCreateProjectProvider(registration);
|
|
160669
160391
|
if (!provider)
|
|
160670
160392
|
return null;
|
|
160671
|
-
const vector = await provider.embed(text, signal);
|
|
160393
|
+
const vector = await provider.embed(text, signal, purpose);
|
|
160672
160394
|
if (!vector)
|
|
160673
160395
|
return null;
|
|
160674
160396
|
const current = projectRegistrations.get(projectIdentity);
|
|
@@ -160677,7 +160399,7 @@ async function embedTextForProject(projectIdentity, text, signal) {
|
|
|
160677
160399
|
}
|
|
160678
160400
|
return { vector, modelId, generation };
|
|
160679
160401
|
}
|
|
160680
|
-
async function embedBatchForProject(projectIdentity, texts, signal) {
|
|
160402
|
+
async function embedBatchForProject(projectIdentity, texts, signal, purpose = "passage") {
|
|
160681
160403
|
if (texts.length === 0) {
|
|
160682
160404
|
const registration2 = projectRegistrations.get(projectIdentity);
|
|
160683
160405
|
if (!registration2 || registration2.observationMode)
|
|
@@ -160693,7 +160415,7 @@ async function embedBatchForProject(projectIdentity, texts, signal) {
|
|
|
160693
160415
|
const provider = getOrCreateProjectProvider(registration);
|
|
160694
160416
|
if (!provider)
|
|
160695
160417
|
return null;
|
|
160696
|
-
const vectors = await provider.embedBatch(texts, signal);
|
|
160418
|
+
const vectors = await provider.embedBatch(texts, signal, purpose);
|
|
160697
160419
|
const current = projectRegistrations.get(projectIdentity);
|
|
160698
160420
|
if (!current || current.generation !== generation || current.runtimeFingerprint !== runtimeFingerprint) {
|
|
160699
160421
|
return null;
|
|
@@ -160750,7 +160472,7 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
|
|
|
160750
160472
|
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
|
|
160751
160473
|
const prepared = [];
|
|
160752
160474
|
for (const candidate of candidates) {
|
|
160753
|
-
const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage);
|
|
160475
|
+
const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage) || buildCompartmentSummaryFallbackText(db, candidate.id);
|
|
160754
160476
|
if (canonicalText.length === 0) {
|
|
160755
160477
|
noWork.push(candidate.id);
|
|
160756
160478
|
continue;
|
|
@@ -160943,8 +160665,7 @@ function getEmbeddingCoverageStatus(db, projectIdentity, sessionId) {
|
|
|
160943
160665
|
|
|
160944
160666
|
// ../plugin/src/features/magic-context/memory/embedding.ts
|
|
160945
160667
|
var DEFAULT_EMBEDDING_CONFIG = {
|
|
160946
|
-
provider: "
|
|
160947
|
-
model: DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
160668
|
+
provider: "off"
|
|
160948
160669
|
};
|
|
160949
160670
|
var embeddingConfig = DEFAULT_EMBEDDING_CONFIG;
|
|
160950
160671
|
var provider = null;
|
|
@@ -160959,11 +160680,12 @@ function createProvider2(config2) {
|
|
|
160959
160680
|
model: config2.model,
|
|
160960
160681
|
apiKey: config2.api_key,
|
|
160961
160682
|
inputType: config2.input_type,
|
|
160683
|
+
queryInputType: config2.query_input_type,
|
|
160962
160684
|
truncate: config2.truncate,
|
|
160963
160685
|
maxInputTokens: config2.max_input_tokens
|
|
160964
160686
|
});
|
|
160965
160687
|
}
|
|
160966
|
-
return
|
|
160688
|
+
return null;
|
|
160967
160689
|
}
|
|
160968
160690
|
function getOrCreateProvider() {
|
|
160969
160691
|
if (provider) {
|
|
@@ -161194,6 +160916,8 @@ var SESSION_META_SELECT_COLUMNS = [
|
|
|
161194
160916
|
"recovery_no_eligible_head_count",
|
|
161195
160917
|
"force_emergency_bypass_window_start",
|
|
161196
160918
|
"force_emergency_bypass_used",
|
|
160919
|
+
"emergency_drain_active",
|
|
160920
|
+
"historian_drain_failure_at",
|
|
161197
160921
|
"upgrade_reminded_at",
|
|
161198
160922
|
"pi_stable_id_scheme"
|
|
161199
160923
|
];
|
|
@@ -161243,6 +160967,8 @@ var META_COLUMNS = {
|
|
|
161243
160967
|
recoveryNoEligibleHeadCount: "recovery_no_eligible_head_count",
|
|
161244
160968
|
forceEmergencyBypassWindowStart: "force_emergency_bypass_window_start",
|
|
161245
160969
|
forceEmergencyBypassUsed: "force_emergency_bypass_used",
|
|
160970
|
+
emergencyDrainActive: "emergency_drain_active",
|
|
160971
|
+
historianDrainFailureAt: "historian_drain_failure_at",
|
|
161246
160972
|
upgradeRemindedAt: "upgrade_reminded_at",
|
|
161247
160973
|
piStableIdScheme: "pi_stable_id_scheme"
|
|
161248
160974
|
};
|
|
@@ -161630,9 +161356,9 @@ function escapeXmlContent(s) {
|
|
|
161630
161356
|
init_data_path();
|
|
161631
161357
|
init_logger();
|
|
161632
161358
|
import { existsSync as existsSync6 } from "node:fs";
|
|
161633
|
-
import { join as
|
|
161359
|
+
import { join as join6 } from "node:path";
|
|
161634
161360
|
function getOpenCodeDbPath() {
|
|
161635
|
-
return
|
|
161361
|
+
return join6(getDataDir(), "opencode", "opencode.db");
|
|
161636
161362
|
}
|
|
161637
161363
|
function openCodeDbExists() {
|
|
161638
161364
|
return existsSync6(getOpenCodeDbPath());
|
|
@@ -161944,6 +161670,24 @@ class ToolMutationBatch {
|
|
|
161944
161670
|
}
|
|
161945
161671
|
|
|
161946
161672
|
// ../plugin/src/hooks/magic-context/read-session-chunk.ts
|
|
161673
|
+
var BLOCK_TOKEN_MEMO_MAX = 2048;
|
|
161674
|
+
var blockTokenMemo = new Map;
|
|
161675
|
+
function estimateBlockTokens(blockText) {
|
|
161676
|
+
const cached2 = blockTokenMemo.get(blockText);
|
|
161677
|
+
if (cached2 !== undefined) {
|
|
161678
|
+
blockTokenMemo.delete(blockText);
|
|
161679
|
+
blockTokenMemo.set(blockText, cached2);
|
|
161680
|
+
return cached2;
|
|
161681
|
+
}
|
|
161682
|
+
const count = estimateTokens(blockText);
|
|
161683
|
+
if (blockTokenMemo.size >= BLOCK_TOKEN_MEMO_MAX) {
|
|
161684
|
+
const oldest = blockTokenMemo.keys().next().value;
|
|
161685
|
+
if (oldest !== undefined)
|
|
161686
|
+
blockTokenMemo.delete(oldest);
|
|
161687
|
+
}
|
|
161688
|
+
blockTokenMemo.set(blockText, count);
|
|
161689
|
+
return count;
|
|
161690
|
+
}
|
|
161947
161691
|
var activeRawMessageCache = null;
|
|
161948
161692
|
var activeAbsoluteCountCache = null;
|
|
161949
161693
|
var sessionProviders = new Map;
|
|
@@ -162126,7 +161870,7 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
162126
161870
|
if (!currentBlock)
|
|
162127
161871
|
return true;
|
|
162128
161872
|
const blockText = formatBlock(currentBlock);
|
|
162129
|
-
const blockTokens =
|
|
161873
|
+
const blockTokens = estimateBlockTokens(blockText);
|
|
162130
161874
|
if (totalTokens + blockTokens > tokenBudget && totalTokens > 0) {
|
|
162131
161875
|
return false;
|
|
162132
161876
|
}
|
|
@@ -167733,12 +167477,12 @@ function canonicalizeDocContent(raw) {
|
|
|
167733
167477
|
}
|
|
167734
167478
|
function fingerprintFile(filePath) {
|
|
167735
167479
|
try {
|
|
167736
|
-
const
|
|
167737
|
-
const isReadableDoc =
|
|
167480
|
+
const stat = lstatSync(filePath);
|
|
167481
|
+
const isReadableDoc = stat.isFile() && stat.size <= MAX_PROJECT_DOC_BYTES;
|
|
167738
167482
|
return {
|
|
167739
167483
|
exists: isReadableDoc,
|
|
167740
|
-
mtimeMs:
|
|
167741
|
-
size:
|
|
167484
|
+
mtimeMs: stat.mtimeMs,
|
|
167485
|
+
size: stat.size
|
|
167742
167486
|
};
|
|
167743
167487
|
} catch {
|
|
167744
167488
|
return { exists: false, mtimeMs: 0, size: 0 };
|
|
@@ -168076,7 +167820,9 @@ var DEFAULT_PROTECTED_TAIL_META = {
|
|
|
168076
167820
|
protectedTailDrainTokens: 0,
|
|
168077
167821
|
recoveryNoEligibleHeadCount: 0,
|
|
168078
167822
|
forceEmergencyBypassWindowStart: 0,
|
|
168079
|
-
forceEmergencyBypassUsed: 0
|
|
167823
|
+
forceEmergencyBypassUsed: 0,
|
|
167824
|
+
emergencyDrainActive: 0,
|
|
167825
|
+
historianDrainFailureAt: 0
|
|
168080
167826
|
};
|
|
168081
167827
|
function toProtectedTailMeta(row) {
|
|
168082
167828
|
if (row === null || typeof row !== "object")
|
|
@@ -168090,7 +167836,9 @@ function toProtectedTailMeta(row) {
|
|
|
168090
167836
|
protectedTailDrainTokens: numberOr(r.protected_tail_drain_tokens, 0),
|
|
168091
167837
|
recoveryNoEligibleHeadCount: numberOr(r.recovery_no_eligible_head_count, 0),
|
|
168092
167838
|
forceEmergencyBypassWindowStart: numberOr(r.force_emergency_bypass_window_start, 0),
|
|
168093
|
-
forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0)
|
|
167839
|
+
forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0),
|
|
167840
|
+
emergencyDrainActive: numberOr(r.emergency_drain_active, 0),
|
|
167841
|
+
historianDrainFailureAt: numberOr(r.historian_drain_failure_at, 0)
|
|
168094
167842
|
};
|
|
168095
167843
|
}
|
|
168096
167844
|
function loadProtectedTailMeta(db, sessionId) {
|
|
@@ -168098,7 +167846,7 @@ function loadProtectedTailMeta(db, sessionId) {
|
|
|
168098
167846
|
const row = db.prepare(`SELECT prior_boundary_ordinal, protected_tail_policy_version,
|
|
168099
167847
|
protected_tail_drain_window_started_at, protected_tail_drain_tokens,
|
|
168100
167848
|
recovery_no_eligible_head_count, force_emergency_bypass_window_start,
|
|
168101
|
-
force_emergency_bypass_used
|
|
167849
|
+
force_emergency_bypass_used, emergency_drain_active, historian_drain_failure_at
|
|
168102
167850
|
FROM session_meta WHERE session_id = ?`).get(sessionId);
|
|
168103
167851
|
return toProtectedTailMeta(row);
|
|
168104
167852
|
}
|
|
@@ -168142,6 +167890,17 @@ function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
|
|
|
168142
167890
|
return Math.min(750000, Math.max(3 * perRunCap, Math.round(0.35 * usable)));
|
|
168143
167891
|
return Math.min(500000, Math.max(perRunCap, Math.round(0.2 * usable)));
|
|
168144
167892
|
}
|
|
167893
|
+
var EMERGENCY_DRAIN_ENTER_PERCENTAGE = 95;
|
|
167894
|
+
var EMERGENCY_DRAIN_EXIT_MARGIN = 10;
|
|
167895
|
+
var EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE = 55;
|
|
167896
|
+
var EMERGENCY_DRAIN_FAILURE_BACKOFF_MS = 60000;
|
|
167897
|
+
var EMERGENCY_DRAIN_MAX_LATCH_MS = 30 * 60 * 1000;
|
|
167898
|
+
function emergencyDrainExitThreshold(executeThresholdPercentage) {
|
|
167899
|
+
if (!Number.isFinite(executeThresholdPercentage) || executeThresholdPercentage <= 0) {
|
|
167900
|
+
return EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE;
|
|
167901
|
+
}
|
|
167902
|
+
return Math.max(0, executeThresholdPercentage - EMERGENCY_DRAIN_EXIT_MARGIN);
|
|
167903
|
+
}
|
|
168145
167904
|
function reserveProtectedTailDrainTokens(args) {
|
|
168146
167905
|
const now = args.now ?? Date.now();
|
|
168147
167906
|
const requested = Math.max(0, Math.floor(args.trueRawTokens));
|
|
@@ -168160,18 +167919,30 @@ function reserveProtectedTailDrainTokens(args) {
|
|
|
168160
167919
|
let meta3 = loadProtectedTailMeta(args.db, args.sessionId);
|
|
168161
167920
|
if (now - meta3.protectedTailDrainWindowStartedAt > DRAIN_WINDOW_MS) {
|
|
168162
167921
|
args.db.prepare(`UPDATE session_meta
|
|
168163
|
-
SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0
|
|
168164
|
-
|
|
168165
|
-
WHERE session_id = ?`).run(now, now, args.sessionId);
|
|
167922
|
+
SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0
|
|
167923
|
+
WHERE session_id = ?`).run(now, args.sessionId);
|
|
168166
167924
|
meta3 = loadProtectedTailMeta(args.db, args.sessionId);
|
|
168167
167925
|
}
|
|
167926
|
+
const exitThreshold = emergencyDrainExitThreshold(args.executeThresholdPercentage);
|
|
167927
|
+
let latchActiveSince = meta3.emergencyDrainActive;
|
|
167928
|
+
if (args.usagePercentage >= EMERGENCY_DRAIN_ENTER_PERCENTAGE) {
|
|
167929
|
+
if (latchActiveSince <= 0)
|
|
167930
|
+
latchActiveSince = now;
|
|
167931
|
+
} else if (latchActiveSince > 0) {
|
|
167932
|
+
const expired = now - latchActiveSince > EMERGENCY_DRAIN_MAX_LATCH_MS;
|
|
167933
|
+
if (args.usagePercentage < exitThreshold || expired)
|
|
167934
|
+
latchActiveSince = 0;
|
|
167935
|
+
}
|
|
167936
|
+
if (latchActiveSince !== meta3.emergencyDrainActive) {
|
|
167937
|
+
args.db.prepare("UPDATE session_meta SET emergency_drain_active = ? WHERE session_id = ?").run(latchActiveSince, args.sessionId);
|
|
167938
|
+
}
|
|
167939
|
+
const latchActive = latchActiveSince > 0;
|
|
168168
167940
|
const budget = protectedTailWindowBudget(args.usagePercentage, args.usable, args.perRunCap);
|
|
168169
167941
|
const remaining = Math.max(0, budget - meta3.protectedTailDrainTokens);
|
|
168170
167942
|
let reserved = Math.min(requested, args.perRunCap, remaining);
|
|
168171
167943
|
let bypass = false;
|
|
168172
|
-
const
|
|
168173
|
-
|
|
168174
|
-
if (reserved <= 0 && args.usagePercentage >= 95 && bypassUsed === 0) {
|
|
167944
|
+
const inFailureBackoff = meta3.historianDrainFailureAt > 0 && now - meta3.historianDrainFailureAt < EMERGENCY_DRAIN_FAILURE_BACKOFF_MS;
|
|
167945
|
+
if (reserved <= 0 && latchActive && !inFailureBackoff) {
|
|
168175
167946
|
reserved = Math.min(requested, args.perRunCap);
|
|
168176
167947
|
bypass = true;
|
|
168177
167948
|
}
|
|
@@ -168179,10 +167950,8 @@ function reserveProtectedTailDrainTokens(args) {
|
|
|
168179
167950
|
return;
|
|
168180
167951
|
args.db.prepare(`UPDATE session_meta
|
|
168181
167952
|
SET protected_tail_drain_window_started_at = CASE WHEN protected_tail_drain_window_started_at = 0 THEN ? ELSE protected_tail_drain_window_started_at END,
|
|
168182
|
-
protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) +
|
|
168183
|
-
|
|
168184
|
-
force_emergency_bypass_used = CASE WHEN ? THEN 1 ELSE force_emergency_bypass_used END
|
|
168185
|
-
WHERE session_id = ?`).run(now, reserved, bypass ? 1 : 0, now, bypass ? 1 : 0, args.sessionId);
|
|
167953
|
+
protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) + ?
|
|
167954
|
+
WHERE session_id = ?`).run(now, reserved, args.sessionId);
|
|
168186
167955
|
result = {
|
|
168187
167956
|
ok: true,
|
|
168188
167957
|
reservedTokens: reserved,
|
|
@@ -168192,6 +167961,25 @@ function reserveProtectedTailDrainTokens(args) {
|
|
|
168192
167961
|
})();
|
|
168193
167962
|
return result;
|
|
168194
167963
|
}
|
|
167964
|
+
function clearEmergencyDrainLatch(db, sessionId) {
|
|
167965
|
+
db.transaction(() => {
|
|
167966
|
+
ensureSessionMetaRow(db, sessionId);
|
|
167967
|
+
db.prepare("UPDATE session_meta SET emergency_drain_active = 0 WHERE session_id = ?").run(sessionId);
|
|
167968
|
+
})();
|
|
167969
|
+
}
|
|
167970
|
+
function recordHistorianDrainFailure(db, sessionId, now) {
|
|
167971
|
+
const ts = now ?? Date.now();
|
|
167972
|
+
db.transaction(() => {
|
|
167973
|
+
ensureSessionMetaRow(db, sessionId);
|
|
167974
|
+
db.prepare("UPDATE session_meta SET historian_drain_failure_at = ? WHERE session_id = ?").run(ts, sessionId);
|
|
167975
|
+
})();
|
|
167976
|
+
}
|
|
167977
|
+
function clearHistorianDrainFailure(db, sessionId) {
|
|
167978
|
+
db.transaction(() => {
|
|
167979
|
+
ensureSessionMetaRow(db, sessionId);
|
|
167980
|
+
db.prepare("UPDATE session_meta SET historian_drain_failure_at = 0 WHERE session_id = ?").run(sessionId);
|
|
167981
|
+
})();
|
|
167982
|
+
}
|
|
168195
167983
|
function rollbackProtectedTailDrainReservation(db, reservation) {
|
|
168196
167984
|
if (!reservation || reservation.tokens <= 0)
|
|
168197
167985
|
return;
|
|
@@ -169213,12 +169001,17 @@ function getOldestActiveUnprotectedToolTags(db, sessionId, protectedTags = 0, li
|
|
|
169213
169001
|
toolName: typeof row.tool_name === "string" ? row.tool_name : null
|
|
169214
169002
|
}));
|
|
169215
169003
|
}
|
|
169216
|
-
function getTriggerTagTokenUpperBound(db, sessionId) {
|
|
169217
|
-
const
|
|
169004
|
+
function getTriggerTagTokenUpperBound(db, sessionId, floor = 0) {
|
|
169005
|
+
const sql = floor > 0 ? `SELECT
|
|
169218
169006
|
COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
|
|
169219
169007
|
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
169220
169008
|
FROM tags
|
|
169221
|
-
WHERE session_id = ? AND status IN ('active', 'dropped')`
|
|
169009
|
+
WHERE session_id = ? AND status IN ('active', 'dropped') AND tag_number >= ?` : `SELECT
|
|
169010
|
+
COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
|
|
169011
|
+
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
169012
|
+
FROM tags
|
|
169013
|
+
WHERE session_id = ? AND status IN ('active', 'dropped')`;
|
|
169014
|
+
const row = floor > 0 ? db.prepare(sql).get(sessionId, floor) : db.prepare(sql).get(sessionId);
|
|
169222
169015
|
return { bound: row?.bound ?? 0, nullCount: row?.null_count ?? 0 };
|
|
169223
169016
|
}
|
|
169224
169017
|
function updateTagInputByteSize(db, sessionId, tagNumber, newInputByteSize) {
|
|
@@ -169245,10 +169038,12 @@ function getUpdateTagInputTokenCountStatement(db) {
|
|
|
169245
169038
|
function updateTagTokenCount(db, sessionId, tagNumber, newTokenCount) {
|
|
169246
169039
|
getUpdateTagTokenCountStatement(db).run(newTokenCount, sessionId, tagNumber);
|
|
169247
169040
|
}
|
|
169248
|
-
function getAllStatusTagTokenTotalsFlat(db, sessionId) {
|
|
169249
|
-
const rows = db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
169250
|
-
|
|
169251
|
-
|
|
169041
|
+
function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0) {
|
|
169042
|
+
const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
169043
|
+
FROM tags
|
|
169044
|
+
WHERE session_id = ? AND tag_number >= ?`).all(sessionId, floor) : db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
169045
|
+
FROM tags
|
|
169046
|
+
WHERE session_id = ?`).all(sessionId);
|
|
169252
169047
|
const totals = new Map;
|
|
169253
169048
|
const nullMessageIds = new Set;
|
|
169254
169049
|
for (const row of rows) {
|
|
@@ -169367,6 +169162,52 @@ function getTagNumberByMessageId(db, sessionId, messageId) {
|
|
|
169367
169162
|
const row = getTagNumberByMessageIdStatement(db).get(sessionId, messageId);
|
|
169368
169163
|
return isTagNumberRow(row) ? row.tag_number : null;
|
|
169369
169164
|
}
|
|
169165
|
+
var getMinMessageTagNumberForRawIdStatements = new WeakMap;
|
|
169166
|
+
function isMinTagNumberRow(row) {
|
|
169167
|
+
return row !== null && typeof row === "object" && "m" in row;
|
|
169168
|
+
}
|
|
169169
|
+
function getMinMessageTagNumberForRawId(db, sessionId, rawId) {
|
|
169170
|
+
if (rawId.includes(":"))
|
|
169171
|
+
return null;
|
|
169172
|
+
let stmt = getMinMessageTagNumberForRawIdStatements.get(db);
|
|
169173
|
+
if (!stmt) {
|
|
169174
|
+
stmt = db.prepare("SELECT MIN(tag_number) AS m FROM tags WHERE session_id = ? AND message_id >= ? AND message_id < ?");
|
|
169175
|
+
getMinMessageTagNumberForRawIdStatements.set(db, stmt);
|
|
169176
|
+
}
|
|
169177
|
+
const row = stmt.get(sessionId, `${rawId}:`, `${rawId};`);
|
|
169178
|
+
return isMinTagNumberRow(row) && typeof row.m === "number" ? row.m : null;
|
|
169179
|
+
}
|
|
169180
|
+
var TAGGER_FLOOR_SCAN_MESSAGES = 8;
|
|
169181
|
+
var TAGGER_FLOOR_MAX_PROBES = 64;
|
|
169182
|
+
var TAGGER_FLOOR_SAFETY_MARGIN = 256;
|
|
169183
|
+
var TAGGER_FLOOR_PER_SKIP_MARGIN = 64;
|
|
169184
|
+
function deriveTagLoadFloor(db, sessionId, rawIds) {
|
|
169185
|
+
let min = Number.POSITIVE_INFINITY;
|
|
169186
|
+
let probes = 0;
|
|
169187
|
+
let hits = 0;
|
|
169188
|
+
let skippedBeforeFirstHit = 0;
|
|
169189
|
+
for (const rawId of rawIds) {
|
|
169190
|
+
if (typeof rawId !== "string" || rawId.length === 0)
|
|
169191
|
+
continue;
|
|
169192
|
+
if (probes >= TAGGER_FLOOR_MAX_PROBES)
|
|
169193
|
+
break;
|
|
169194
|
+
probes++;
|
|
169195
|
+
const m = getMinMessageTagNumberForRawId(db, sessionId, rawId);
|
|
169196
|
+
if (m === null) {
|
|
169197
|
+
if (hits === 0)
|
|
169198
|
+
skippedBeforeFirstHit++;
|
|
169199
|
+
continue;
|
|
169200
|
+
}
|
|
169201
|
+
if (m < min)
|
|
169202
|
+
min = m;
|
|
169203
|
+
if (++hits >= TAGGER_FLOOR_SCAN_MESSAGES)
|
|
169204
|
+
break;
|
|
169205
|
+
}
|
|
169206
|
+
if (!Number.isFinite(min))
|
|
169207
|
+
return 0;
|
|
169208
|
+
const margin = TAGGER_FLOOR_SAFETY_MARGIN + skippedBeforeFirstHit * TAGGER_FLOOR_PER_SKIP_MARGIN;
|
|
169209
|
+
return Math.max(0, min - margin);
|
|
169210
|
+
}
|
|
169370
169211
|
var TAG_SELECT_COLUMNS = "id, message_id, type, status, drop_mode, tool_name, input_byte_size, byte_size, reasoning_byte_size, session_id, tag_number, caveman_depth, tool_owner_message_id";
|
|
169371
169212
|
function getTagsBySession(db, sessionId) {
|
|
169372
169213
|
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC`).all(sessionId).filter(isTagRow);
|
|
@@ -171540,13 +171381,13 @@ function extractM0Block(m0Text, tag) {
|
|
|
171540
171381
|
|
|
171541
171382
|
// ../plugin/src/hooks/magic-context/key-files-block.ts
|
|
171542
171383
|
import { readFileSync as readFileSync6, realpathSync as realpathSync2 } from "node:fs";
|
|
171543
|
-
import { join as
|
|
171384
|
+
import { join as join8, sep as sep2 } from "node:path";
|
|
171544
171385
|
|
|
171545
171386
|
// ../plugin/src/features/magic-context/key-files/aft-availability.ts
|
|
171546
171387
|
var import_comment_json2 = __toESM(require_src2(), 1);
|
|
171547
171388
|
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
|
|
171548
171389
|
import { homedir as homedir4 } from "node:os";
|
|
171549
|
-
import { isAbsolute as isAbsolute2, join as
|
|
171390
|
+
import { isAbsolute as isAbsolute2, join as join7, resolve as resolve3 } from "node:path";
|
|
171550
171391
|
import { fileURLToPath } from "node:url";
|
|
171551
171392
|
var overrideAvailability = null;
|
|
171552
171393
|
function parseConfig(path5) {
|
|
@@ -171567,14 +171408,14 @@ function resolveLocalEntryPackageName(value, configDir) {
|
|
|
171567
171408
|
return null;
|
|
171568
171409
|
}
|
|
171569
171410
|
} else if (value.startsWith("~/")) {
|
|
171570
|
-
dir =
|
|
171411
|
+
dir = join7(homedir4(), value.slice(2));
|
|
171571
171412
|
} else if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) {
|
|
171572
171413
|
dir = isAbsolute2(value) ? value : resolve3(configDir, value);
|
|
171573
171414
|
} else {
|
|
171574
171415
|
return null;
|
|
171575
171416
|
}
|
|
171576
171417
|
try {
|
|
171577
|
-
const pkg = JSON.parse(readFileSync5(
|
|
171418
|
+
const pkg = JSON.parse(readFileSync5(join7(dir, "package.json"), "utf-8"));
|
|
171578
171419
|
return typeof pkg.name === "string" ? pkg.name : null;
|
|
171579
171420
|
} catch {
|
|
171580
171421
|
return null;
|
|
@@ -171605,16 +171446,16 @@ function hasAftAtKeys(value, keys2, configDir) {
|
|
|
171605
171446
|
function getAftAvailability() {
|
|
171606
171447
|
const home = process.env.HOME || homedir4();
|
|
171607
171448
|
const opencodePaths = [
|
|
171608
|
-
|
|
171609
|
-
|
|
171449
|
+
join7(home, ".config", "opencode", "opencode.jsonc"),
|
|
171450
|
+
join7(home, ".config", "opencode", "opencode.json")
|
|
171610
171451
|
];
|
|
171611
|
-
const piPaths = [
|
|
171452
|
+
const piPaths = [join7(home, ".pi", "agent", "settings.json")];
|
|
171612
171453
|
const checkedPaths = [...opencodePaths, ...piPaths];
|
|
171613
171454
|
let opencode = false;
|
|
171614
171455
|
for (const path5 of opencodePaths) {
|
|
171615
171456
|
try {
|
|
171616
171457
|
const config2 = parseConfig(path5);
|
|
171617
|
-
const configDir =
|
|
171458
|
+
const configDir = join7(path5, "..");
|
|
171618
171459
|
if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"], configDir)) {
|
|
171619
171460
|
opencode = true;
|
|
171620
171461
|
break;
|
|
@@ -171625,7 +171466,7 @@ function getAftAvailability() {
|
|
|
171625
171466
|
for (const path5 of piPaths) {
|
|
171626
171467
|
try {
|
|
171627
171468
|
const config2 = parseConfig(path5);
|
|
171628
|
-
const configDir =
|
|
171469
|
+
const configDir = join7(path5, "..");
|
|
171629
171470
|
if (hasAftAtKeys(config2, ["packages", "extensions"], configDir)) {
|
|
171630
171471
|
pi = true;
|
|
171631
171472
|
break;
|
|
@@ -171704,7 +171545,7 @@ function buildKeyFilesBlock(db, projectPath, config2 = { enabled: true, tokenBud
|
|
|
171704
171545
|
let nextStale = null;
|
|
171705
171546
|
let observed = false;
|
|
171706
171547
|
try {
|
|
171707
|
-
const absPath =
|
|
171548
|
+
const absPath = join8(projectPath, row.path);
|
|
171708
171549
|
const real = realpathSync2(absPath);
|
|
171709
171550
|
if (!isUnderResolvedRoot(projectRoot, real)) {
|
|
171710
171551
|
nextStale = "missing";
|
|
@@ -172105,7 +171946,7 @@ function createCtxSearchTool(deps) {
|
|
|
172105
171946
|
memoryEnabled,
|
|
172106
171947
|
embeddingEnabled,
|
|
172107
171948
|
embedQuery: async (text, signal) => {
|
|
172108
|
-
const result = await embedTextForProject(projectIdentity, text, signal);
|
|
171949
|
+
const result = await embedTextForProject(projectIdentity, text, signal, "query");
|
|
172109
171950
|
return result?.vector ?? null;
|
|
172110
171951
|
},
|
|
172111
171952
|
isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
|