@wolfx/opencode-magic-context 0.24.1 → 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/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/agents/permissions.d.ts +6 -0
- package/dist/agents/permissions.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +24 -17
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts +25 -0
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-openai.d.ts +8 -4
- package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-provider.d.ts +8 -4
- package/dist/features/magic-context/memory/embedding-provider.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
- package/dist/features/magic-context/memory/relocate-memory.d.ts +58 -0
- package/dist/features/magic-context/memory/relocate-memory.d.ts.map +1 -0
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts +6 -0
- package/dist/features/magic-context/memory/storage-memory-embeddings.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 +41 -3
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +2 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +37 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +1 -0
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-shared.d.ts +4 -1
- package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +2 -2
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +58 -2
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +3 -3
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/tagger.d.ts +1 -1
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts +49 -0
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -0
- 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/v22-deferred-backfill.d.ts.map +1 -1
- package/dist/hooks/magic-context/apply-operations.d.ts +3 -25
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/caveman-cleanup.d.ts +1 -0
- package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/channel2-delivery.d.ts +2 -0
- package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +7 -5
- 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-trigger.d.ts +1 -1
- package/dist/hooks/magic-context/compartment-trigger.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/derive-budgets.d.ts +5 -9
- package/dist/hooks/magic-context/derive-budgets.d.ts.map +1 -1
- package/dist/hooks/magic-context/embed-session-state.d.ts +14 -0
- package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -0
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-payloads.d.ts +1 -0
- package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
- package/dist/hooks/magic-context/format-embed-status.d.ts +9 -0
- package/dist/hooks/magic-context/format-embed-status.d.ts.map +1 -0
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +2 -0
- package/dist/hooks/magic-context/heuristic-cleanup.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/protected-tail-boundary.d.ts +10 -0
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +0 -1
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-content-primitives.d.ts +2 -0
- package/dist/hooks/magic-context/tag-content-primitives.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-id-fallback.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +10 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tool-drop-target.d.ts +1 -1
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/tool-reclaim.d.ts +12 -0
- package/dist/hooks/magic-context/tool-reclaim.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +32 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-operations.d.ts +1 -1
- package/dist/hooks/magic-context/transform-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +6 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +2 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1790 -1025
- package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/shared/announcement.d.ts +1 -1
- package/dist/shared/index.d.ts +0 -1
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
- package/dist/shared/resolve-fallbacks.d.ts +16 -16
- package/dist/shared/resolve-fallbacks.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +20 -0
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +5 -1
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/tools/ctx-expand/constants.d.ts +1 -1
- package/dist/tools/ctx-expand/constants.d.ts.map +1 -1
- package/dist/tools/ctx-expand/render.d.ts +43 -0
- package/dist/tools/ctx-expand/render.d.ts.map +1 -0
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-expand/types.d.ts +6 -2
- package/dist/tools/ctx-expand/types.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/constants.d.ts +1 -1
- package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
- package/dist/tools/ctx-search/tools.d.ts.map +1 -1
- package/dist/tui/data/context-db.d.ts +4 -2
- package/dist/tui/data/context-db.d.ts.map +1 -1
- package/package.json +5 -12
- package/src/shared/announcement.ts +6 -6
- package/src/shared/index.ts +0 -1
- package/src/shared/model-suggestion-retry.test.ts +61 -1
- package/src/shared/model-suggestion-retry.ts +22 -0
- package/src/shared/resolve-fallbacks.test.ts +37 -71
- package/src/shared/resolve-fallbacks.ts +16 -26
- package/src/shared/rpc-types.ts +11 -0
- package/src/shared/sqlite-bind-style.test.ts +82 -0
- package/src/shared/sqlite.ts +30 -1
- package/src/shared/tag-transcript.test.ts +3 -1
- package/src/shared/tag-transcript.ts +19 -17
- package/src/tui/data/context-db.ts +34 -2
- package/src/tui/index.tsx +58 -4
- package/src/tui/slots/sidebar-content.tsx +18 -9
- package/dist/features/magic-context/memory/embedding-local.d.ts +0 -21
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +0 -1
- package/dist/shared/model-requirements.d.ts +0 -26
- package/dist/shared/model-requirements.d.ts.map +0 -1
- package/src/shared/model-requirements.ts +0 -86
package/dist/index.js
CHANGED
|
@@ -47,20 +47,9 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
47
47
|
var __promiseAll = (args) => Promise.all(args);
|
|
48
48
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
49
49
|
|
|
50
|
-
// src/agents/dreamer.ts
|
|
51
|
-
var DREAMER_AGENT = "dreamer";
|
|
52
|
-
|
|
53
50
|
// src/agents/historian.ts
|
|
54
|
-
var exports_historian = {};
|
|
55
|
-
__export(exports_historian, {
|
|
56
|
-
HISTORIAN_EDITOR_AGENT: () => HISTORIAN_EDITOR_AGENT,
|
|
57
|
-
HISTORIAN_AGENT: () => HISTORIAN_AGENT
|
|
58
|
-
});
|
|
59
51
|
var HISTORIAN_AGENT = "historian", HISTORIAN_EDITOR_AGENT = "historian-editor";
|
|
60
52
|
|
|
61
|
-
// src/agents/sidekick.ts
|
|
62
|
-
var SIDEKICK_AGENT = "sidekick";
|
|
63
|
-
|
|
64
53
|
// src/shared/jsonc-parser.ts
|
|
65
54
|
import { existsSync, readFileSync } from "node:fs";
|
|
66
55
|
function stripJsonComments(content) {
|
|
@@ -14836,7 +14825,7 @@ var init_agent_overrides = __esm(() => {
|
|
|
14836
14825
|
});
|
|
14837
14826
|
|
|
14838
14827
|
// src/config/schema/magic-context.ts
|
|
14839
|
-
var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65, 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.", DEFAULT_HISTORIAN_TIMEOUT_MS = 300000, DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15,
|
|
14828
|
+
var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65, 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.", DEFAULT_HISTORIAN_TIMEOUT_MS = 300000, DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15, DREAMER_TASKS, DreamingTaskSchema, DEFAULT_DREAMER_TASKS, PiThinkingLevelSchema, DreamerConfigSchema, SidekickConfigSchema, HistorianConfigSchema, BaseEmbeddingConfigSchema, EmbeddingConfigSchema, MagicContextConfigSchema;
|
|
14840
14829
|
var init_magic_context = __esm(() => {
|
|
14841
14830
|
init_zod();
|
|
14842
14831
|
init_agent_overrides();
|
|
@@ -14879,14 +14868,16 @@ var init_magic_context = __esm(() => {
|
|
|
14879
14868
|
}).optional();
|
|
14880
14869
|
HistorianConfigSchema = AgentOverrideConfigSchema.extend({
|
|
14881
14870
|
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)"),
|
|
14882
|
-
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")
|
|
14871
|
+
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"),
|
|
14872
|
+
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: [])`)
|
|
14883
14873
|
}).optional();
|
|
14884
14874
|
BaseEmbeddingConfigSchema = exports_external.object({
|
|
14885
|
-
provider: exports_external.enum(["
|
|
14886
|
-
model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible
|
|
14875
|
+
provider: exports_external.enum(["openai-compatible", "off"]).default("off").describe("Embedding provider. 'openai-compatible' requires endpoint and model, 'off' disables embeddings (default)."),
|
|
14876
|
+
model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible."),
|
|
14887
14877
|
endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
|
|
14888
14878
|
api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
|
|
14889
|
-
input_type: exports_external.string().optional().describe("
|
|
14879
|
+
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."),
|
|
14880
|
+
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."),
|
|
14890
14881
|
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
14882
|
max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
|
|
14892
14883
|
}).superRefine((data, ctx) => {
|
|
@@ -14906,16 +14897,10 @@ var init_magic_context = __esm(() => {
|
|
|
14906
14897
|
}
|
|
14907
14898
|
});
|
|
14908
14899
|
EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
|
|
14909
|
-
if (data.provider === "local") {
|
|
14910
|
-
return {
|
|
14911
|
-
provider: "local",
|
|
14912
|
-
model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
14913
|
-
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
|
|
14914
|
-
};
|
|
14915
|
-
}
|
|
14916
14900
|
if (data.provider === "openai-compatible") {
|
|
14917
14901
|
const apiKey = data.api_key?.trim();
|
|
14918
14902
|
const inputType = data.input_type?.trim();
|
|
14903
|
+
const queryInputType = data.query_input_type?.trim();
|
|
14919
14904
|
const truncate = data.truncate?.trim();
|
|
14920
14905
|
return {
|
|
14921
14906
|
provider: "openai-compatible",
|
|
@@ -14923,6 +14908,7 @@ var init_magic_context = __esm(() => {
|
|
|
14923
14908
|
endpoint: data.endpoint?.trim() ?? "",
|
|
14924
14909
|
...apiKey ? { api_key: apiKey } : {},
|
|
14925
14910
|
...inputType ? { input_type: inputType } : {},
|
|
14911
|
+
...queryInputType ? { query_input_type: queryInputType } : {},
|
|
14926
14912
|
...truncate ? { truncate } : {},
|
|
14927
14913
|
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
|
|
14928
14914
|
};
|
|
@@ -14962,8 +14948,7 @@ var init_magic_context = __esm(() => {
|
|
|
14962
14948
|
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)")
|
|
14963
14949
|
}).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."),
|
|
14964
14950
|
embedding: EmbeddingConfigSchema.default({
|
|
14965
|
-
provider: "
|
|
14966
|
-
model: DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
14951
|
+
provider: "off"
|
|
14967
14952
|
}).describe("Embedding provider configuration"),
|
|
14968
14953
|
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).'),
|
|
14969
14954
|
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."),
|
|
@@ -15284,58 +15269,6 @@ var init_logger = __esm(() => {
|
|
|
15284
15269
|
}
|
|
15285
15270
|
});
|
|
15286
15271
|
|
|
15287
|
-
// src/shared/model-requirements.ts
|
|
15288
|
-
function expandFallbackChain(chain) {
|
|
15289
|
-
const models = [];
|
|
15290
|
-
for (const entry of chain) {
|
|
15291
|
-
for (const provider of entry.providers) {
|
|
15292
|
-
models.push(`${provider}/${entry.model}`);
|
|
15293
|
-
}
|
|
15294
|
-
}
|
|
15295
|
-
return models;
|
|
15296
|
-
}
|
|
15297
|
-
function getAgentFallbackModels(agent) {
|
|
15298
|
-
const requirement = AGENT_MODEL_REQUIREMENTS[agent];
|
|
15299
|
-
if (!requirement)
|
|
15300
|
-
return;
|
|
15301
|
-
return expandFallbackChain(requirement.fallbackChain);
|
|
15302
|
-
}
|
|
15303
|
-
var HISTORIAN_FALLBACK_CHAIN, DREAMER_FALLBACK_CHAIN, SIDEKICK_FALLBACK_CHAIN, AGENT_MODEL_REQUIREMENTS;
|
|
15304
|
-
var init_model_requirements = __esm(() => {
|
|
15305
|
-
HISTORIAN_FALLBACK_CHAIN = [
|
|
15306
|
-
{ providers: ["github-copilot", "anthropic", "opencode"], model: "claude-sonnet-4-6" },
|
|
15307
|
-
{ providers: ["opencode-go"], model: "minimax-m2.7" },
|
|
15308
|
-
{
|
|
15309
|
-
providers: ["zai-coding-plan", "bailian-coding-plan", "opencode-go", "opencode"],
|
|
15310
|
-
model: "glm-5"
|
|
15311
|
-
},
|
|
15312
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.4" },
|
|
15313
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro" }
|
|
15314
|
-
];
|
|
15315
|
-
DREAMER_FALLBACK_CHAIN = [
|
|
15316
|
-
{ providers: ["github-copilot", "anthropic", "opencode"], model: "claude-sonnet-4-6" },
|
|
15317
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
15318
|
-
{
|
|
15319
|
-
providers: ["zai-coding-plan", "bailian-coding-plan", "opencode-go", "opencode"],
|
|
15320
|
-
model: "glm-5"
|
|
15321
|
-
},
|
|
15322
|
-
{ providers: ["opencode-go"], model: "minimax-m2.7" },
|
|
15323
|
-
{ providers: ["github-copilot", "openai", "opencode"], model: "gpt-5.4-mini" }
|
|
15324
|
-
];
|
|
15325
|
-
SIDEKICK_FALLBACK_CHAIN = [
|
|
15326
|
-
{ providers: ["cerebras"], model: "qwen-3-235b-a22b-instruct-2507" },
|
|
15327
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
15328
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.4-mini" },
|
|
15329
|
-
{ providers: ["opencode"], model: "gpt-5-nano" }
|
|
15330
|
-
];
|
|
15331
|
-
AGENT_MODEL_REQUIREMENTS = {
|
|
15332
|
-
[HISTORIAN_AGENT]: { fallbackChain: HISTORIAN_FALLBACK_CHAIN },
|
|
15333
|
-
[HISTORIAN_EDITOR_AGENT]: { fallbackChain: HISTORIAN_FALLBACK_CHAIN },
|
|
15334
|
-
[DREAMER_AGENT]: { fallbackChain: DREAMER_FALLBACK_CHAIN },
|
|
15335
|
-
[SIDEKICK_AGENT]: { fallbackChain: SIDEKICK_FALLBACK_CHAIN }
|
|
15336
|
-
};
|
|
15337
|
-
});
|
|
15338
|
-
|
|
15339
15272
|
// src/features/magic-context/overflow-detection.ts
|
|
15340
15273
|
function extractErrorMessage(error51) {
|
|
15341
15274
|
if (!error51)
|
|
@@ -15449,15 +15382,9 @@ __export(exports_resolve_fallbacks, {
|
|
|
15449
15382
|
resolveFallbackChain: () => resolveFallbackChain,
|
|
15450
15383
|
parseProviderModel: () => parseProviderModel
|
|
15451
15384
|
});
|
|
15452
|
-
function resolveFallbackChain(
|
|
15385
|
+
function resolveFallbackChain(userFallbacks) {
|
|
15453
15386
|
const userList = normalizeUserFallbacks(userFallbacks);
|
|
15454
|
-
|
|
15455
|
-
return dedupe(userList.filter(isValidModelSpec));
|
|
15456
|
-
}
|
|
15457
|
-
const builtin = getAgentFallbackModels(agentName);
|
|
15458
|
-
if (!builtin || builtin.length === 0)
|
|
15459
|
-
return [];
|
|
15460
|
-
return dedupe(builtin.filter(isValidModelSpec));
|
|
15387
|
+
return dedupe(userList.filter(isValidModelSpec));
|
|
15461
15388
|
}
|
|
15462
15389
|
function normalizeUserFallbacks(userFallbacks) {
|
|
15463
15390
|
if (!userFallbacks)
|
|
@@ -15492,9 +15419,6 @@ function parseProviderModel(spec) {
|
|
|
15492
15419
|
modelID: spec.slice(slash + 1).trim()
|
|
15493
15420
|
};
|
|
15494
15421
|
}
|
|
15495
|
-
var init_resolve_fallbacks = __esm(() => {
|
|
15496
|
-
init_model_requirements();
|
|
15497
|
-
});
|
|
15498
15422
|
|
|
15499
15423
|
// src/shared/model-suggestion-retry.ts
|
|
15500
15424
|
function extractMessage(error51) {
|
|
@@ -15565,9 +15489,11 @@ async function promptWithTimeout(client, args, timeoutMs, signal) {
|
|
|
15565
15489
|
});
|
|
15566
15490
|
} catch (error51) {
|
|
15567
15491
|
if (signal?.aborted) {
|
|
15492
|
+
await abortChildRun(client, args.path.id);
|
|
15568
15493
|
throw new Error("prompt aborted by external signal");
|
|
15569
15494
|
}
|
|
15570
15495
|
if (controller.signal.aborted) {
|
|
15496
|
+
await abortChildRun(client, args.path.id);
|
|
15571
15497
|
throw new Error(`prompt timed out after ${timeoutMs}ms`);
|
|
15572
15498
|
}
|
|
15573
15499
|
throw error51;
|
|
@@ -15576,6 +15502,13 @@ async function promptWithTimeout(client, args, timeoutMs, signal) {
|
|
|
15576
15502
|
signal?.removeEventListener("abort", onExternalAbort);
|
|
15577
15503
|
}
|
|
15578
15504
|
}
|
|
15505
|
+
async function abortChildRun(client, sessionId) {
|
|
15506
|
+
try {
|
|
15507
|
+
await client.session.abort({ path: { id: sessionId } });
|
|
15508
|
+
} catch (error51) {
|
|
15509
|
+
log(`[model-retry] child session abort failed for ${sessionId}: ${String(error51)}`);
|
|
15510
|
+
}
|
|
15511
|
+
}
|
|
15579
15512
|
function isNonRetryable(error51, externalSignal) {
|
|
15580
15513
|
if (externalSignal?.aborted)
|
|
15581
15514
|
return true;
|
|
@@ -15673,7 +15606,6 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
|
|
|
15673
15606
|
var init_model_suggestion_retry = __esm(() => {
|
|
15674
15607
|
init_overflow_detection();
|
|
15675
15608
|
init_logger();
|
|
15676
|
-
init_resolve_fallbacks();
|
|
15677
15609
|
});
|
|
15678
15610
|
|
|
15679
15611
|
// src/shared/normalize-sdk-response.ts
|
|
@@ -15703,9 +15635,7 @@ function normalizeSDKResponse(response, fallback, options) {
|
|
|
15703
15635
|
// src/shared/index.ts
|
|
15704
15636
|
var init_shared = __esm(() => {
|
|
15705
15637
|
init_logger();
|
|
15706
|
-
init_model_requirements();
|
|
15707
15638
|
init_model_suggestion_retry();
|
|
15708
|
-
init_resolve_fallbacks();
|
|
15709
15639
|
});
|
|
15710
15640
|
|
|
15711
15641
|
// src/shared/record-type-guard.ts
|
|
@@ -15847,7 +15777,7 @@ function isSessionMetaRow(row) {
|
|
|
15847
15777
|
if (row === null || typeof row !== "object")
|
|
15848
15778
|
return false;
|
|
15849
15779
|
const r = row;
|
|
15850
|
-
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);
|
|
15780
|
+
return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isStringOrNull(r.cached_m0_workspace_fingerprint) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.cached_m0_system_hash) && isStringOrNull(r.cached_m0_tool_set_hash) && isStringOrNull(r.cached_m0_model_key) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.last_usage_context_limit) && isNumberOrNull(r.prior_boundary_ordinal) && isNumberOrNull(r.protected_tail_policy_version) && isNumberOrNull(r.protected_tail_drain_window_started_at) && isNumberOrNull(r.protected_tail_drain_tokens) && isNumberOrNull(r.recovery_no_eligible_head_count) && isNumberOrNull(r.force_emergency_bypass_window_start) && isNumberOrNull(r.force_emergency_bypass_used) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme) && isNumberOrNull(r.tool_reclaim_watermark);
|
|
15851
15781
|
}
|
|
15852
15782
|
function getDefaultSessionMeta(sessionId) {
|
|
15853
15783
|
return {
|
|
@@ -15870,6 +15800,7 @@ function getDefaultSessionMeta(sessionId) {
|
|
|
15870
15800
|
conversationTokens: 0,
|
|
15871
15801
|
toolCallTokens: 0,
|
|
15872
15802
|
clearedReasoningThroughTag: 0,
|
|
15803
|
+
toolReclaimWatermark: 0,
|
|
15873
15804
|
lastTodoState: "",
|
|
15874
15805
|
cachedM0Bytes: null,
|
|
15875
15806
|
cachedM1Bytes: null,
|
|
@@ -15933,6 +15864,7 @@ function toSessionMeta(row) {
|
|
|
15933
15864
|
conversationTokens: numOrZero(row.conversation_tokens),
|
|
15934
15865
|
toolCallTokens: numOrZero(row.tool_call_tokens),
|
|
15935
15866
|
clearedReasoningThroughTag: numOrZero(row.cleared_reasoning_through_tag),
|
|
15867
|
+
toolReclaimWatermark: numOrZero(row.tool_reclaim_watermark),
|
|
15936
15868
|
lastTodoState: lastTodoStateRaw,
|
|
15937
15869
|
cachedM0Bytes: toBufferOrNull(row.cached_m0_bytes),
|
|
15938
15870
|
cachedM1Bytes: toBufferOrNull(row.cached_m1_bytes),
|
|
@@ -16042,6 +15974,7 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16042
15974
|
"conversation_tokens",
|
|
16043
15975
|
"tool_call_tokens",
|
|
16044
15976
|
"cleared_reasoning_through_tag",
|
|
15977
|
+
"tool_reclaim_watermark",
|
|
16045
15978
|
"last_todo_state",
|
|
16046
15979
|
"cached_m0_bytes",
|
|
16047
15980
|
"cached_m1_bytes",
|
|
@@ -16068,6 +16001,8 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16068
16001
|
"recovery_no_eligible_head_count",
|
|
16069
16002
|
"force_emergency_bypass_window_start",
|
|
16070
16003
|
"force_emergency_bypass_used",
|
|
16004
|
+
"emergency_drain_active",
|
|
16005
|
+
"historian_drain_failure_at",
|
|
16071
16006
|
"upgrade_reminded_at",
|
|
16072
16007
|
"pi_stable_id_scheme"
|
|
16073
16008
|
];
|
|
@@ -16090,6 +16025,7 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16090
16025
|
conversationTokens: "conversation_tokens",
|
|
16091
16026
|
toolCallTokens: "tool_call_tokens",
|
|
16092
16027
|
clearedReasoningThroughTag: "cleared_reasoning_through_tag",
|
|
16028
|
+
toolReclaimWatermark: "tool_reclaim_watermark",
|
|
16093
16029
|
lastTodoState: "last_todo_state",
|
|
16094
16030
|
cachedM0Bytes: "cached_m0_bytes",
|
|
16095
16031
|
cachedM1Bytes: "cached_m1_bytes",
|
|
@@ -16116,6 +16052,8 @@ var init_storage_meta_shared = __esm(() => {
|
|
|
16116
16052
|
recoveryNoEligibleHeadCount: "recovery_no_eligible_head_count",
|
|
16117
16053
|
forceEmergencyBypassWindowStart: "force_emergency_bypass_window_start",
|
|
16118
16054
|
forceEmergencyBypassUsed: "force_emergency_bypass_used",
|
|
16055
|
+
emergencyDrainActive: "emergency_drain_active",
|
|
16056
|
+
historianDrainFailureAt: "historian_drain_failure_at",
|
|
16119
16057
|
upgradeRemindedAt: "upgrade_reminded_at",
|
|
16120
16058
|
piStableIdScheme: "pi_stable_id_scheme"
|
|
16121
16059
|
};
|
|
@@ -16366,6 +16304,14 @@ function buildNodeSqliteDatabaseClass(DatabaseSync) {
|
|
|
16366
16304
|
}
|
|
16367
16305
|
super(typeof filename === "string" ? filename : ":memory:", translated);
|
|
16368
16306
|
}
|
|
16307
|
+
prepare(sql) {
|
|
16308
|
+
const stmt = super.prepare(sql);
|
|
16309
|
+
for (const method of ["run", "get", "all"]) {
|
|
16310
|
+
const original = stmt[method].bind(stmt);
|
|
16311
|
+
stmt[method] = (...args) => args.length === 1 && Array.isArray(args[0]) ? original(...args[0]) : original(...args);
|
|
16312
|
+
}
|
|
16313
|
+
return stmt;
|
|
16314
|
+
}
|
|
16369
16315
|
transaction(fn) {
|
|
16370
16316
|
const self = this;
|
|
16371
16317
|
const wrapped = function(...args) {
|
|
@@ -149342,6 +149288,9 @@ function stripCompleteTagPairsGlobally(value) {
|
|
|
149342
149288
|
function stripMalformedTagNotationGlobally(value) {
|
|
149343
149289
|
return value.replace(MALFORMED_TAG_GLOBAL_REGEX, "");
|
|
149344
149290
|
}
|
|
149291
|
+
function stripDanglingTagNotationGlobally(value) {
|
|
149292
|
+
return value.replace(DANGLING_TAG_GLOBAL_REGEX, "");
|
|
149293
|
+
}
|
|
149345
149294
|
function stripTagSectionCharacters(value) {
|
|
149346
149295
|
return value.replace(STRAY_SECTION_CHAR_REGEX, "");
|
|
149347
149296
|
}
|
|
@@ -149349,6 +149298,7 @@ function stripPersistedAssistantText(value) {
|
|
|
149349
149298
|
let text = stripWellFormedLeadingTagPrefix(value);
|
|
149350
149299
|
text = stripCompleteTagPairsGlobally(text);
|
|
149351
149300
|
text = stripMalformedTagNotationGlobally(text);
|
|
149301
|
+
text = stripDanglingTagNotationGlobally(text);
|
|
149352
149302
|
text = stripTagSectionCharacters(text);
|
|
149353
149303
|
return text.trim();
|
|
149354
149304
|
}
|
|
@@ -149361,6 +149311,7 @@ function stripTagPrefix(value) {
|
|
|
149361
149311
|
const prev = stripped;
|
|
149362
149312
|
stripped = stripped.replace(MALFORMED_TAG_PREFIX_REGEX, "");
|
|
149363
149313
|
stripped = stripped.replace(TAG_PREFIX_REGEX, "");
|
|
149314
|
+
stripped = stripped.replace(DANGLING_TAG_PREFIX_REGEX, "");
|
|
149364
149315
|
if (stripped === prev)
|
|
149365
149316
|
break;
|
|
149366
149317
|
}
|
|
@@ -149382,11 +149333,13 @@ function isThinkingPart(part) {
|
|
|
149382
149333
|
const candidate = part;
|
|
149383
149334
|
return candidate.type === "thinking" || candidate.type === "reasoning";
|
|
149384
149335
|
}
|
|
149385
|
-
var encoder, TAG_PREFIX_REGEX, MALFORMED_TAG_PREFIX_REGEX, COMPLETE_TAG_PAIR_GLOBAL_REGEX, MALFORMED_TAG_GLOBAL_REGEX, STRAY_SECTION_CHAR_REGEX;
|
|
149336
|
+
var encoder, TAG_PREFIX_REGEX, MALFORMED_TAG_PREFIX_REGEX, DANGLING_TAG_GLOBAL_REGEX, DANGLING_TAG_PREFIX_REGEX, COMPLETE_TAG_PAIR_GLOBAL_REGEX, MALFORMED_TAG_GLOBAL_REGEX, STRAY_SECTION_CHAR_REGEX;
|
|
149386
149337
|
var init_tag_content_primitives = __esm(() => {
|
|
149387
149338
|
encoder = new TextEncoder;
|
|
149388
149339
|
TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
|
|
149389
149340
|
MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
|
|
149341
|
+
DANGLING_TAG_GLOBAL_REGEX = /\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?/g;
|
|
149342
|
+
DANGLING_TAG_PREFIX_REGEX = /^(?:\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?\s*)+/;
|
|
149390
149343
|
COMPLETE_TAG_PAIR_GLOBAL_REGEX = /\u00a7\d+\u00a7/g;
|
|
149391
149344
|
MALFORMED_TAG_GLOBAL_REGEX = /\u00a7\d+">(?:\u00a7(?:\d+\u00a7)?)?/g;
|
|
149392
149345
|
STRAY_SECTION_CHAR_REGEX = /\u00a7/g;
|
|
@@ -149450,12 +149403,13 @@ function setToolContent(part, content) {
|
|
|
149450
149403
|
part.content = content;
|
|
149451
149404
|
}
|
|
149452
149405
|
}
|
|
149453
|
-
function truncateToolPart(part) {
|
|
149406
|
+
function truncateToolPart(part, tagId) {
|
|
149454
149407
|
if (!isRecord(part))
|
|
149455
149408
|
return;
|
|
149409
|
+
const sentinel = `[dropped §${tagId}§]`;
|
|
149456
149410
|
if (part.type === "tool" && isRecord(part.state)) {
|
|
149457
149411
|
const state = part.state;
|
|
149458
|
-
state.output =
|
|
149412
|
+
state.output = sentinel;
|
|
149459
149413
|
if (isRecord(state.input)) {
|
|
149460
149414
|
const inputSize = estimateInputSize(state.input);
|
|
149461
149415
|
if (inputSize > 500) {
|
|
@@ -149465,7 +149419,7 @@ function truncateToolPart(part) {
|
|
|
149465
149419
|
return;
|
|
149466
149420
|
}
|
|
149467
149421
|
if (part.type === "tool_result") {
|
|
149468
|
-
part.content =
|
|
149422
|
+
part.content = sentinel;
|
|
149469
149423
|
return;
|
|
149470
149424
|
}
|
|
149471
149425
|
if (part.type === "tool-invocation" && isRecord(part.args)) {
|
|
@@ -149582,7 +149536,7 @@ class ToolMutationBatch {
|
|
|
149582
149536
|
this.affectedMessages.clear();
|
|
149583
149537
|
}
|
|
149584
149538
|
}
|
|
149585
|
-
function createToolDropTarget(compositeKey, thinkingParts, index, batch) {
|
|
149539
|
+
function createToolDropTarget(compositeKey, thinkingParts, index, batch, tagId) {
|
|
149586
149540
|
const drop = () => {
|
|
149587
149541
|
const entry = index.get(compositeKey);
|
|
149588
149542
|
if (!entry || entry.occurrences.length === 0)
|
|
@@ -149603,7 +149557,7 @@ function createToolDropTarget(compositeKey, thinkingParts, index, batch) {
|
|
|
149603
149557
|
if (!entry.hasResult)
|
|
149604
149558
|
return "incomplete";
|
|
149605
149559
|
for (const occurrence of entry.occurrences) {
|
|
149606
|
-
truncateToolPart(occurrence.part);
|
|
149560
|
+
truncateToolPart(occurrence.part, tagId);
|
|
149607
149561
|
}
|
|
149608
149562
|
clearThinkingParts(thinkingParts);
|
|
149609
149563
|
return "truncated";
|
|
@@ -149651,6 +149605,22 @@ var init_tool_drop_target = __esm(() => {
|
|
|
149651
149605
|
});
|
|
149652
149606
|
|
|
149653
149607
|
// src/hooks/magic-context/read-session-chunk.ts
|
|
149608
|
+
function estimateBlockTokens(blockText) {
|
|
149609
|
+
const cached2 = blockTokenMemo.get(blockText);
|
|
149610
|
+
if (cached2 !== undefined) {
|
|
149611
|
+
blockTokenMemo.delete(blockText);
|
|
149612
|
+
blockTokenMemo.set(blockText, cached2);
|
|
149613
|
+
return cached2;
|
|
149614
|
+
}
|
|
149615
|
+
const count = estimateTokens(blockText);
|
|
149616
|
+
if (blockTokenMemo.size >= BLOCK_TOKEN_MEMO_MAX) {
|
|
149617
|
+
const oldest = blockTokenMemo.keys().next().value;
|
|
149618
|
+
if (oldest !== undefined)
|
|
149619
|
+
blockTokenMemo.delete(oldest);
|
|
149620
|
+
}
|
|
149621
|
+
blockTokenMemo.set(blockText, count);
|
|
149622
|
+
return count;
|
|
149623
|
+
}
|
|
149654
149624
|
function cleanUserText(text) {
|
|
149655
149625
|
return removeSystemReminders(text).replace(OMO_INTERNAL_INITIATOR_MARKER, "").trim();
|
|
149656
149626
|
}
|
|
@@ -149818,7 +149788,7 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
149818
149788
|
if (!currentBlock)
|
|
149819
149789
|
return true;
|
|
149820
149790
|
const blockText = formatBlock(currentBlock);
|
|
149821
|
-
const blockTokens =
|
|
149791
|
+
const blockTokens = estimateBlockTokens(blockText);
|
|
149822
149792
|
if (totalTokens + blockTokens > tokenBudget && totalTokens > 0) {
|
|
149823
149793
|
return false;
|
|
149824
149794
|
}
|
|
@@ -149936,13 +149906,14 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
149936
149906
|
toolOnlyRanges
|
|
149937
149907
|
};
|
|
149938
149908
|
}
|
|
149939
|
-
var activeRawMessageCache = null, activeAbsoluteCountCache = null, sessionProviders, PROTECTED_TAIL_USER_TURNS = 5;
|
|
149909
|
+
var BLOCK_TOKEN_MEMO_MAX = 2048, blockTokenMemo, activeRawMessageCache = null, activeAbsoluteCountCache = null, sessionProviders, PROTECTED_TAIL_USER_TURNS = 5;
|
|
149940
149910
|
var init_read_session_chunk = __esm(async () => {
|
|
149941
149911
|
init_read_session_formatting();
|
|
149942
149912
|
init_tag_part_guards();
|
|
149943
149913
|
init_tool_drop_target();
|
|
149944
149914
|
init_read_session_formatting();
|
|
149945
149915
|
await init_read_session_db();
|
|
149916
|
+
blockTokenMemo = new Map;
|
|
149946
149917
|
sessionProviders = new Map;
|
|
149947
149918
|
});
|
|
149948
149919
|
|
|
@@ -150687,6 +150658,9 @@ function resolveDatabasePath(dbPathOverride) {
|
|
|
150687
150658
|
const dbDir = getMagicContextStorageDir();
|
|
150688
150659
|
return { dbDir, dbPath: join6(dbDir, "context.db") };
|
|
150689
150660
|
}
|
|
150661
|
+
function getDatabasePath(db) {
|
|
150662
|
+
return pathByDatabase.get(db) ?? null;
|
|
150663
|
+
}
|
|
150690
150664
|
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
150691
150665
|
if (existsSync7(targetDbPath))
|
|
150692
150666
|
return;
|
|
@@ -151197,6 +151171,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151197
151171
|
recovery_no_eligible_head_count INTEGER NOT NULL DEFAULT 0,
|
|
151198
151172
|
force_emergency_bypass_window_start INTEGER NOT NULL DEFAULT 0,
|
|
151199
151173
|
force_emergency_bypass_used INTEGER NOT NULL DEFAULT 0,
|
|
151174
|
+
emergency_drain_active INTEGER NOT NULL DEFAULT 0,
|
|
151175
|
+
historian_drain_failure_at INTEGER NOT NULL DEFAULT 0,
|
|
151200
151176
|
cached_m0_materialized_at INTEGER,
|
|
151201
151177
|
cached_m0_session_facts_version INTEGER,
|
|
151202
151178
|
cached_m0_upgrade_state TEXT,
|
|
@@ -151260,6 +151236,23 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151260
151236
|
CREATE INDEX IF NOT EXISTS idx_historian_runs_status
|
|
151261
151237
|
ON historian_runs(status, created_at DESC);
|
|
151262
151238
|
|
|
151239
|
+
CREATE TABLE IF NOT EXISTS transform_decisions (
|
|
151240
|
+
session_id TEXT NOT NULL,
|
|
151241
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
151242
|
+
message_id TEXT NOT NULL,
|
|
151243
|
+
ts_ms INTEGER NOT NULL,
|
|
151244
|
+
decision TEXT NOT NULL,
|
|
151245
|
+
materialized INTEGER NOT NULL DEFAULT 0,
|
|
151246
|
+
materialize_reason TEXT,
|
|
151247
|
+
emergency INTEGER NOT NULL DEFAULT 0,
|
|
151248
|
+
dropped_tokens INTEGER NOT NULL DEFAULT 0,
|
|
151249
|
+
dropped_count INTEGER NOT NULL DEFAULT 0,
|
|
151250
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
151251
|
+
PRIMARY KEY (session_id, harness, message_id)
|
|
151252
|
+
);
|
|
151253
|
+
CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
|
|
151254
|
+
ON transform_decisions(session_id, harness);
|
|
151255
|
+
|
|
151263
151256
|
CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
|
|
151264
151257
|
CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
|
|
151265
151258
|
CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
|
|
@@ -151337,6 +151330,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151337
151330
|
ensureColumn(db, "session_meta", "historian_last_failure_at", "INTEGER DEFAULT NULL");
|
|
151338
151331
|
ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
|
|
151339
151332
|
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
151333
|
+
ensureColumn(db, "session_meta", "tool_reclaim_watermark", "INTEGER DEFAULT 0");
|
|
151340
151334
|
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
151341
151335
|
ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
|
|
151342
151336
|
ensureColumn(db, "session_meta", "processed_image_stripped_ids", "TEXT DEFAULT ''");
|
|
@@ -151410,6 +151404,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151410
151404
|
ensureColumn(db, "session_meta", "recovery_no_eligible_head_count", "INTEGER NOT NULL DEFAULT 0");
|
|
151411
151405
|
ensureColumn(db, "session_meta", "force_emergency_bypass_window_start", "INTEGER NOT NULL DEFAULT 0");
|
|
151412
151406
|
ensureColumn(db, "session_meta", "force_emergency_bypass_used", "INTEGER NOT NULL DEFAULT 0");
|
|
151407
|
+
ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
|
|
151408
|
+
ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
|
|
151413
151409
|
ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
|
|
151414
151410
|
ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
|
|
151415
151411
|
ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
|
|
@@ -151488,6 +151484,22 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
151488
151484
|
failed_at INTEGER NOT NULL,
|
|
151489
151485
|
UNIQUE(table_name, row_id)
|
|
151490
151486
|
);
|
|
151487
|
+
CREATE TABLE IF NOT EXISTS transform_decisions (
|
|
151488
|
+
session_id TEXT NOT NULL,
|
|
151489
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
151490
|
+
message_id TEXT NOT NULL,
|
|
151491
|
+
ts_ms INTEGER NOT NULL,
|
|
151492
|
+
decision TEXT NOT NULL,
|
|
151493
|
+
materialized INTEGER NOT NULL DEFAULT 0,
|
|
151494
|
+
materialize_reason TEXT,
|
|
151495
|
+
emergency INTEGER NOT NULL DEFAULT 0,
|
|
151496
|
+
dropped_tokens INTEGER NOT NULL DEFAULT 0,
|
|
151497
|
+
dropped_count INTEGER NOT NULL DEFAULT 0,
|
|
151498
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
151499
|
+
PRIMARY KEY (session_id, harness, message_id)
|
|
151500
|
+
);
|
|
151501
|
+
CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
|
|
151502
|
+
ON transform_decisions(session_id, harness);
|
|
151491
151503
|
`);
|
|
151492
151504
|
ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
151493
151505
|
ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
@@ -151573,7 +151585,9 @@ function healNullIntegerColumns(db) {
|
|
|
151573
151585
|
["protected_tail_drain_tokens", 0],
|
|
151574
151586
|
["recovery_no_eligible_head_count", 0],
|
|
151575
151587
|
["force_emergency_bypass_window_start", 0],
|
|
151576
|
-
["force_emergency_bypass_used", 0]
|
|
151588
|
+
["force_emergency_bypass_used", 0],
|
|
151589
|
+
["emergency_drain_active", 0],
|
|
151590
|
+
["historian_drain_failure_at", 0]
|
|
151577
151591
|
];
|
|
151578
151592
|
for (const [column, fallback] of columns) {
|
|
151579
151593
|
try {
|
|
@@ -151649,6 +151663,7 @@ function openDatabase(dbPathOrOptions) {
|
|
|
151649
151663
|
setDatabase(db);
|
|
151650
151664
|
loadToolDefinitionMeasurements(db);
|
|
151651
151665
|
databases.set(dbPath, db);
|
|
151666
|
+
pathByDatabase.set(db, dbPath);
|
|
151652
151667
|
persistenceByDatabase.set(db, true);
|
|
151653
151668
|
persistenceErrorByDatabase.delete(db);
|
|
151654
151669
|
return db;
|
|
@@ -151668,7 +151683,7 @@ function getDatabasePersistenceError(db) {
|
|
|
151668
151683
|
return null;
|
|
151669
151684
|
return persistenceErrorByDatabase.get(db) ?? null;
|
|
151670
151685
|
}
|
|
151671
|
-
var databases, persistenceByDatabase, persistenceErrorByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION =
|
|
151686
|
+
var databases, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 38, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS = 120000;
|
|
151672
151687
|
var init_storage_db = __esm(async () => {
|
|
151673
151688
|
init_data_path();
|
|
151674
151689
|
init_logger();
|
|
@@ -151682,6 +151697,7 @@ var init_storage_db = __esm(async () => {
|
|
|
151682
151697
|
databases = new Map;
|
|
151683
151698
|
persistenceByDatabase = new WeakMap;
|
|
151684
151699
|
persistenceErrorByDatabase = new WeakMap;
|
|
151700
|
+
pathByDatabase = new WeakMap;
|
|
151685
151701
|
sqlitePragmaConfig = {
|
|
151686
151702
|
cacheSizeMb: 64,
|
|
151687
151703
|
mmapSizeMb: 0
|
|
@@ -153000,6 +153016,41 @@ var init_migrations = __esm(async () => {
|
|
|
153000
153016
|
`);
|
|
153001
153017
|
}
|
|
153002
153018
|
}
|
|
153019
|
+
},
|
|
153020
|
+
{
|
|
153021
|
+
version: 37,
|
|
153022
|
+
description: "emergency drain catch-up latch + historian drain failure backoff",
|
|
153023
|
+
up: (db) => {
|
|
153024
|
+
const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta'").get();
|
|
153025
|
+
if (!hasSessionMeta)
|
|
153026
|
+
return;
|
|
153027
|
+
ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
|
|
153028
|
+
ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
|
|
153029
|
+
}
|
|
153030
|
+
},
|
|
153031
|
+
{
|
|
153032
|
+
version: 38,
|
|
153033
|
+
description: "durable transform decisions for cache-event cause attribution",
|
|
153034
|
+
up: (db) => {
|
|
153035
|
+
db.exec(`
|
|
153036
|
+
CREATE TABLE IF NOT EXISTS transform_decisions (
|
|
153037
|
+
session_id TEXT NOT NULL,
|
|
153038
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
153039
|
+
message_id TEXT NOT NULL,
|
|
153040
|
+
ts_ms INTEGER NOT NULL,
|
|
153041
|
+
decision TEXT NOT NULL,
|
|
153042
|
+
materialized INTEGER NOT NULL DEFAULT 0,
|
|
153043
|
+
materialize_reason TEXT,
|
|
153044
|
+
emergency INTEGER NOT NULL DEFAULT 0,
|
|
153045
|
+
dropped_tokens INTEGER NOT NULL DEFAULT 0,
|
|
153046
|
+
dropped_count INTEGER NOT NULL DEFAULT 0,
|
|
153047
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
153048
|
+
PRIMARY KEY (session_id, harness, message_id)
|
|
153049
|
+
);
|
|
153050
|
+
CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
|
|
153051
|
+
ON transform_decisions(session_id, harness);
|
|
153052
|
+
`);
|
|
153053
|
+
}
|
|
153003
153054
|
}
|
|
153004
153055
|
];
|
|
153005
153056
|
LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -153404,7 +153455,9 @@ function toProtectedTailMeta(row) {
|
|
|
153404
153455
|
protectedTailDrainTokens: numberOr(r.protected_tail_drain_tokens, 0),
|
|
153405
153456
|
recoveryNoEligibleHeadCount: numberOr(r.recovery_no_eligible_head_count, 0),
|
|
153406
153457
|
forceEmergencyBypassWindowStart: numberOr(r.force_emergency_bypass_window_start, 0),
|
|
153407
|
-
forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0)
|
|
153458
|
+
forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0),
|
|
153459
|
+
emergencyDrainActive: numberOr(r.emergency_drain_active, 0),
|
|
153460
|
+
historianDrainFailureAt: numberOr(r.historian_drain_failure_at, 0)
|
|
153408
153461
|
};
|
|
153409
153462
|
}
|
|
153410
153463
|
function loadProtectedTailMeta(db, sessionId) {
|
|
@@ -153412,7 +153465,7 @@ function loadProtectedTailMeta(db, sessionId) {
|
|
|
153412
153465
|
const row = db.prepare(`SELECT prior_boundary_ordinal, protected_tail_policy_version,
|
|
153413
153466
|
protected_tail_drain_window_started_at, protected_tail_drain_tokens,
|
|
153414
153467
|
recovery_no_eligible_head_count, force_emergency_bypass_window_start,
|
|
153415
|
-
force_emergency_bypass_used
|
|
153468
|
+
force_emergency_bypass_used, emergency_drain_active, historian_drain_failure_at
|
|
153416
153469
|
FROM session_meta WHERE session_id = ?`).get(sessionId);
|
|
153417
153470
|
return toProtectedTailMeta(row);
|
|
153418
153471
|
}
|
|
@@ -153461,6 +153514,12 @@ function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
|
|
|
153461
153514
|
return Math.min(750000, Math.max(3 * perRunCap, Math.round(0.35 * usable)));
|
|
153462
153515
|
return Math.min(500000, Math.max(perRunCap, Math.round(0.2 * usable)));
|
|
153463
153516
|
}
|
|
153517
|
+
function emergencyDrainExitThreshold(executeThresholdPercentage) {
|
|
153518
|
+
if (!Number.isFinite(executeThresholdPercentage) || executeThresholdPercentage <= 0) {
|
|
153519
|
+
return EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE;
|
|
153520
|
+
}
|
|
153521
|
+
return Math.max(0, executeThresholdPercentage - EMERGENCY_DRAIN_EXIT_MARGIN);
|
|
153522
|
+
}
|
|
153464
153523
|
function reserveProtectedTailDrainTokens(args) {
|
|
153465
153524
|
const now = args.now ?? Date.now();
|
|
153466
153525
|
const requested = Math.max(0, Math.floor(args.trueRawTokens));
|
|
@@ -153479,18 +153538,30 @@ function reserveProtectedTailDrainTokens(args) {
|
|
|
153479
153538
|
let meta3 = loadProtectedTailMeta(args.db, args.sessionId);
|
|
153480
153539
|
if (now - meta3.protectedTailDrainWindowStartedAt > DRAIN_WINDOW_MS) {
|
|
153481
153540
|
args.db.prepare(`UPDATE session_meta
|
|
153482
|
-
SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0
|
|
153483
|
-
|
|
153484
|
-
WHERE session_id = ?`).run(now, now, args.sessionId);
|
|
153541
|
+
SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0
|
|
153542
|
+
WHERE session_id = ?`).run(now, args.sessionId);
|
|
153485
153543
|
meta3 = loadProtectedTailMeta(args.db, args.sessionId);
|
|
153486
153544
|
}
|
|
153545
|
+
const exitThreshold = emergencyDrainExitThreshold(args.executeThresholdPercentage);
|
|
153546
|
+
let latchActiveSince = meta3.emergencyDrainActive;
|
|
153547
|
+
if (args.usagePercentage >= EMERGENCY_DRAIN_ENTER_PERCENTAGE) {
|
|
153548
|
+
if (latchActiveSince <= 0)
|
|
153549
|
+
latchActiveSince = now;
|
|
153550
|
+
} else if (latchActiveSince > 0) {
|
|
153551
|
+
const expired = now - latchActiveSince > EMERGENCY_DRAIN_MAX_LATCH_MS;
|
|
153552
|
+
if (args.usagePercentage < exitThreshold || expired)
|
|
153553
|
+
latchActiveSince = 0;
|
|
153554
|
+
}
|
|
153555
|
+
if (latchActiveSince !== meta3.emergencyDrainActive) {
|
|
153556
|
+
args.db.prepare("UPDATE session_meta SET emergency_drain_active = ? WHERE session_id = ?").run(latchActiveSince, args.sessionId);
|
|
153557
|
+
}
|
|
153558
|
+
const latchActive = latchActiveSince > 0;
|
|
153487
153559
|
const budget = protectedTailWindowBudget(args.usagePercentage, args.usable, args.perRunCap);
|
|
153488
153560
|
const remaining = Math.max(0, budget - meta3.protectedTailDrainTokens);
|
|
153489
153561
|
let reserved = Math.min(requested, args.perRunCap, remaining);
|
|
153490
153562
|
let bypass = false;
|
|
153491
|
-
const
|
|
153492
|
-
|
|
153493
|
-
if (reserved <= 0 && args.usagePercentage >= 95 && bypassUsed === 0) {
|
|
153563
|
+
const inFailureBackoff = meta3.historianDrainFailureAt > 0 && now - meta3.historianDrainFailureAt < EMERGENCY_DRAIN_FAILURE_BACKOFF_MS;
|
|
153564
|
+
if (reserved <= 0 && latchActive && !inFailureBackoff) {
|
|
153494
153565
|
reserved = Math.min(requested, args.perRunCap);
|
|
153495
153566
|
bypass = true;
|
|
153496
153567
|
}
|
|
@@ -153498,10 +153569,8 @@ function reserveProtectedTailDrainTokens(args) {
|
|
|
153498
153569
|
return;
|
|
153499
153570
|
args.db.prepare(`UPDATE session_meta
|
|
153500
153571
|
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,
|
|
153501
|
-
protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) +
|
|
153502
|
-
|
|
153503
|
-
force_emergency_bypass_used = CASE WHEN ? THEN 1 ELSE force_emergency_bypass_used END
|
|
153504
|
-
WHERE session_id = ?`).run(now, reserved, bypass ? 1 : 0, now, bypass ? 1 : 0, args.sessionId);
|
|
153572
|
+
protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) + ?
|
|
153573
|
+
WHERE session_id = ?`).run(now, reserved, args.sessionId);
|
|
153505
153574
|
result = {
|
|
153506
153575
|
ok: true,
|
|
153507
153576
|
reservedTokens: reserved,
|
|
@@ -153511,6 +153580,25 @@ function reserveProtectedTailDrainTokens(args) {
|
|
|
153511
153580
|
})();
|
|
153512
153581
|
return result;
|
|
153513
153582
|
}
|
|
153583
|
+
function clearEmergencyDrainLatch(db, sessionId) {
|
|
153584
|
+
db.transaction(() => {
|
|
153585
|
+
ensureSessionMetaRow(db, sessionId);
|
|
153586
|
+
db.prepare("UPDATE session_meta SET emergency_drain_active = 0 WHERE session_id = ?").run(sessionId);
|
|
153587
|
+
})();
|
|
153588
|
+
}
|
|
153589
|
+
function recordHistorianDrainFailure(db, sessionId, now) {
|
|
153590
|
+
const ts = now ?? Date.now();
|
|
153591
|
+
db.transaction(() => {
|
|
153592
|
+
ensureSessionMetaRow(db, sessionId);
|
|
153593
|
+
db.prepare("UPDATE session_meta SET historian_drain_failure_at = ? WHERE session_id = ?").run(ts, sessionId);
|
|
153594
|
+
})();
|
|
153595
|
+
}
|
|
153596
|
+
function clearHistorianDrainFailure(db, sessionId) {
|
|
153597
|
+
db.transaction(() => {
|
|
153598
|
+
ensureSessionMetaRow(db, sessionId);
|
|
153599
|
+
db.prepare("UPDATE session_meta SET historian_drain_failure_at = 0 WHERE session_id = ?").run(sessionId);
|
|
153600
|
+
})();
|
|
153601
|
+
}
|
|
153514
153602
|
function rollbackProtectedTailDrainReservation(db, reservation) {
|
|
153515
153603
|
if (!reservation || reservation.tokens <= 0)
|
|
153516
153604
|
return;
|
|
@@ -154078,7 +154166,7 @@ function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
|
|
|
154078
154166
|
SET new_work_tokens = ?, total_input_tokens = ?
|
|
154079
154167
|
WHERE session_id = ?`).run(Math.max(0, Math.floor(newWorkTokens)), Math.max(0, Math.floor(totalInputTokens)), sessionId);
|
|
154080
154168
|
}
|
|
154081
|
-
var CAS_RETRY_LIMIT = 5, AUTO_SEARCH_NO_HINT_REASONS, DEFAULT_PROTECTED_TAIL_META, DRAIN_WINDOW_MS;
|
|
154169
|
+
var CAS_RETRY_LIMIT = 5, AUTO_SEARCH_NO_HINT_REASONS, DEFAULT_PROTECTED_TAIL_META, DRAIN_WINDOW_MS, EMERGENCY_DRAIN_ENTER_PERCENTAGE = 95, EMERGENCY_DRAIN_EXIT_MARGIN = 10, EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE = 55, EMERGENCY_DRAIN_FAILURE_BACKOFF_MS = 60000, EMERGENCY_DRAIN_MAX_LATCH_MS;
|
|
154082
154170
|
var init_storage_meta_persisted = __esm(() => {
|
|
154083
154171
|
init_logger();
|
|
154084
154172
|
init_storage_meta_shared();
|
|
@@ -154097,9 +154185,12 @@ var init_storage_meta_persisted = __esm(() => {
|
|
|
154097
154185
|
protectedTailDrainTokens: 0,
|
|
154098
154186
|
recoveryNoEligibleHeadCount: 0,
|
|
154099
154187
|
forceEmergencyBypassWindowStart: 0,
|
|
154100
|
-
forceEmergencyBypassUsed: 0
|
|
154188
|
+
forceEmergencyBypassUsed: 0,
|
|
154189
|
+
emergencyDrainActive: 0,
|
|
154190
|
+
historianDrainFailureAt: 0
|
|
154101
154191
|
};
|
|
154102
154192
|
DRAIN_WINDOW_MS = 10 * 60 * 1000;
|
|
154193
|
+
EMERGENCY_DRAIN_MAX_LATCH_MS = 30 * 60 * 1000;
|
|
154103
154194
|
});
|
|
154104
154195
|
|
|
154105
154196
|
// src/features/magic-context/resolve-subagent-fallback.ts
|
|
@@ -154126,7 +154217,8 @@ var exports_storage_meta_session = {};
|
|
|
154126
154217
|
__export(exports_storage_meta_session, {
|
|
154127
154218
|
updateSessionMeta: () => updateSessionMeta,
|
|
154128
154219
|
getOrCreateSessionMeta: () => getOrCreateSessionMeta,
|
|
154129
|
-
clearSession: () => clearSession
|
|
154220
|
+
clearSession: () => clearSession,
|
|
154221
|
+
advanceToolReclaimWatermark: () => advanceToolReclaimWatermark
|
|
154130
154222
|
});
|
|
154131
154223
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
154132
154224
|
function getSessionMetaSelectColumns(db) {
|
|
@@ -154187,6 +154279,14 @@ function updateSessionMeta(db, sessionId, updates) {
|
|
|
154187
154279
|
db.prepare(`UPDATE session_meta SET ${setClauses.join(", ")} WHERE session_id = ?`).run(...values, sessionId);
|
|
154188
154280
|
})();
|
|
154189
154281
|
}
|
|
154282
|
+
function advanceToolReclaimWatermark(db, sessionId, maxTagNumber) {
|
|
154283
|
+
if (maxTagNumber <= 0)
|
|
154284
|
+
return;
|
|
154285
|
+
db.transaction(() => {
|
|
154286
|
+
ensureSessionMetaRow(db, sessionId);
|
|
154287
|
+
db.prepare("UPDATE session_meta SET tool_reclaim_watermark = MAX(COALESCE(tool_reclaim_watermark, 0), ?) WHERE session_id = ?").run(maxTagNumber, sessionId);
|
|
154288
|
+
})();
|
|
154289
|
+
}
|
|
154190
154290
|
function clearSession(db, sessionId) {
|
|
154191
154291
|
db.transaction(() => {
|
|
154192
154292
|
db.prepare("DELETE FROM pending_ops WHERE session_id = ?").run(sessionId);
|
|
@@ -154208,6 +154308,7 @@ function clearSession(db, sessionId) {
|
|
|
154208
154308
|
db.prepare("DELETE FROM subagent_invocations WHERE session_id = ?").run(sessionId);
|
|
154209
154309
|
db.prepare("DELETE FROM historian_runs WHERE session_id = ?").run(sessionId);
|
|
154210
154310
|
db.prepare("DELETE FROM plugin_messages WHERE session_id = ?").run(sessionId);
|
|
154311
|
+
db.prepare("DELETE FROM transform_decisions WHERE session_id = ?").run(sessionId);
|
|
154211
154312
|
clearIndexedMessages(db, sessionId);
|
|
154212
154313
|
})();
|
|
154213
154314
|
}
|
|
@@ -154225,6 +154326,7 @@ var init_storage_meta_session = __esm(async () => {
|
|
|
154225
154326
|
last_transform_error: "'' AS last_transform_error",
|
|
154226
154327
|
system_prompt_hash: "'' AS system_prompt_hash",
|
|
154227
154328
|
last_todo_state: "'' AS last_todo_state",
|
|
154329
|
+
tool_reclaim_watermark: "0 AS tool_reclaim_watermark",
|
|
154228
154330
|
cached_m0_bytes: "NULL AS cached_m0_bytes",
|
|
154229
154331
|
cached_m1_bytes: "NULL AS cached_m1_bytes",
|
|
154230
154332
|
cached_m0_project_memory_epoch: "NULL AS cached_m0_project_memory_epoch",
|
|
@@ -154632,12 +154734,37 @@ function getActiveTagTokenAggregate(db, sessionId, protectedTags = 0) {
|
|
|
154632
154734
|
nullCount: row?.null_count ?? 0
|
|
154633
154735
|
};
|
|
154634
154736
|
}
|
|
154635
|
-
function
|
|
154636
|
-
|
|
154737
|
+
function getOldestActiveUnprotectedToolTags(db, sessionId, protectedTags = 0, limit = 4) {
|
|
154738
|
+
if (limit <= 0)
|
|
154739
|
+
return [];
|
|
154740
|
+
const boundedLimit = Math.max(1, Math.min(10, Math.floor(limit)));
|
|
154741
|
+
const whereProtected = protectedTags > 0 ? `AND tag_number < (
|
|
154742
|
+
SELECT tag_number FROM tags
|
|
154743
|
+
WHERE session_id = ? AND status = 'active'
|
|
154744
|
+
ORDER BY tag_number DESC LIMIT 1 OFFSET ?
|
|
154745
|
+
)` : "";
|
|
154746
|
+
const params = protectedTags > 0 ? [sessionId, sessionId, protectedTags - 1, boundedLimit] : [sessionId, boundedLimit];
|
|
154747
|
+
const rows = db.prepare(`SELECT tag_number, tool_name
|
|
154748
|
+
FROM tags
|
|
154749
|
+
WHERE session_id = ? AND status = 'active' AND type = 'tool' ${whereProtected}
|
|
154750
|
+
ORDER BY tag_number ASC, id ASC
|
|
154751
|
+
LIMIT ?`).all(...params);
|
|
154752
|
+
return rows.filter((row) => typeof row.tag_number === "number").map((row) => ({
|
|
154753
|
+
tagNumber: row.tag_number,
|
|
154754
|
+
toolName: typeof row.tool_name === "string" ? row.tool_name : null
|
|
154755
|
+
}));
|
|
154756
|
+
}
|
|
154757
|
+
function getTriggerTagTokenUpperBound(db, sessionId, floor = 0) {
|
|
154758
|
+
const sql = floor > 0 ? `SELECT
|
|
154637
154759
|
COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
|
|
154638
154760
|
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
154639
154761
|
FROM tags
|
|
154640
|
-
WHERE session_id = ? AND status IN ('active', 'dropped')`
|
|
154762
|
+
WHERE session_id = ? AND status IN ('active', 'dropped') AND tag_number >= ?` : `SELECT
|
|
154763
|
+
COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
|
|
154764
|
+
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
154765
|
+
FROM tags
|
|
154766
|
+
WHERE session_id = ? AND status IN ('active', 'dropped')`;
|
|
154767
|
+
const row = floor > 0 ? db.prepare(sql).get(sessionId, floor) : db.prepare(sql).get(sessionId);
|
|
154641
154768
|
return { bound: row?.bound ?? 0, nullCount: row?.null_count ?? 0 };
|
|
154642
154769
|
}
|
|
154643
154770
|
function getActiveTagTokenTotalsByMessage(db, sessionId) {
|
|
@@ -154666,10 +154793,12 @@ function getActiveTagTokenTotalsByMessage(db, sessionId) {
|
|
|
154666
154793
|
}
|
|
154667
154794
|
return out;
|
|
154668
154795
|
}
|
|
154669
|
-
function getAllStatusTagTokenTotalsFlat(db, sessionId) {
|
|
154670
|
-
const rows = db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
154671
|
-
|
|
154672
|
-
|
|
154796
|
+
function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0) {
|
|
154797
|
+
const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
154798
|
+
FROM tags
|
|
154799
|
+
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
|
|
154800
|
+
FROM tags
|
|
154801
|
+
WHERE session_id = ?`).all(sessionId);
|
|
154673
154802
|
const totals = new Map;
|
|
154674
154803
|
const nullMessageIds = new Set;
|
|
154675
154804
|
for (const row of rows) {
|
|
@@ -154828,6 +154957,47 @@ function getTagNumberByMessageId(db, sessionId, messageId) {
|
|
|
154828
154957
|
const row = getTagNumberByMessageIdStatement(db).get(sessionId, messageId);
|
|
154829
154958
|
return isTagNumberRow(row) ? row.tag_number : null;
|
|
154830
154959
|
}
|
|
154960
|
+
function isMinTagNumberRow(row) {
|
|
154961
|
+
return row !== null && typeof row === "object" && "m" in row;
|
|
154962
|
+
}
|
|
154963
|
+
function getMinMessageTagNumberForRawId(db, sessionId, rawId) {
|
|
154964
|
+
if (rawId.includes(":"))
|
|
154965
|
+
return null;
|
|
154966
|
+
let stmt = getMinMessageTagNumberForRawIdStatements.get(db);
|
|
154967
|
+
if (!stmt) {
|
|
154968
|
+
stmt = db.prepare("SELECT MIN(tag_number) AS m FROM tags WHERE session_id = ? AND message_id >= ? AND message_id < ?");
|
|
154969
|
+
getMinMessageTagNumberForRawIdStatements.set(db, stmt);
|
|
154970
|
+
}
|
|
154971
|
+
const row = stmt.get(sessionId, `${rawId}:`, `${rawId};`);
|
|
154972
|
+
return isMinTagNumberRow(row) && typeof row.m === "number" ? row.m : null;
|
|
154973
|
+
}
|
|
154974
|
+
function deriveTagLoadFloor(db, sessionId, rawIds) {
|
|
154975
|
+
let min = Number.POSITIVE_INFINITY;
|
|
154976
|
+
let probes = 0;
|
|
154977
|
+
let hits = 0;
|
|
154978
|
+
let skippedBeforeFirstHit = 0;
|
|
154979
|
+
for (const rawId of rawIds) {
|
|
154980
|
+
if (typeof rawId !== "string" || rawId.length === 0)
|
|
154981
|
+
continue;
|
|
154982
|
+
if (probes >= TAGGER_FLOOR_MAX_PROBES)
|
|
154983
|
+
break;
|
|
154984
|
+
probes++;
|
|
154985
|
+
const m = getMinMessageTagNumberForRawId(db, sessionId, rawId);
|
|
154986
|
+
if (m === null) {
|
|
154987
|
+
if (hits === 0)
|
|
154988
|
+
skippedBeforeFirstHit++;
|
|
154989
|
+
continue;
|
|
154990
|
+
}
|
|
154991
|
+
if (m < min)
|
|
154992
|
+
min = m;
|
|
154993
|
+
if (++hits >= TAGGER_FLOOR_SCAN_MESSAGES)
|
|
154994
|
+
break;
|
|
154995
|
+
}
|
|
154996
|
+
if (!Number.isFinite(min))
|
|
154997
|
+
return 0;
|
|
154998
|
+
const margin = TAGGER_FLOOR_SAFETY_MARGIN + skippedBeforeFirstHit * TAGGER_FLOOR_PER_SKIP_MARGIN;
|
|
154999
|
+
return Math.max(0, min - margin);
|
|
155000
|
+
}
|
|
154831
155001
|
function getTagsBySession(db, sessionId) {
|
|
154832
155002
|
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC`).all(sessionId).filter(isTagRow);
|
|
154833
155003
|
return rows.map(toTagEntry);
|
|
@@ -154966,7 +155136,7 @@ function deleteToolTagsByOwner(db, sessionId, ownerMsgId) {
|
|
|
154966
155136
|
const result = getDeleteToolTagsByOwnerStatement(db).run(sessionId, ownerMsgId);
|
|
154967
155137
|
return result.changes ?? 0;
|
|
154968
155138
|
}
|
|
154969
|
-
var insertTagStatements, updateTagStatusStatements, updateTagDropModeStatements, updateTagMessageIdStatements, getTagNumbersByMessageIdStatements, deleteTagsByMessageIdStatements, getMaxTagNumberBySessionStatements, getTagNumberByMessageIdStatements, updateTagByteSizeStatements, updateTagInputByteSizeStatements, CONTENT_ID_SUFFIX, updateTagTokenCountStatements, updateTagInputTokenCountStatements, getOwnerScopedToolTagNumbersStatements, 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", getActiveTagsBySessionStatements, getMaxDroppedTagNumberStatements, getToolTagNumberByOwnerStatements, getNullOwnerToolTagStatements, adoptNullOwnerToolTagStatements, deleteToolTagsByOwnerStatements;
|
|
155139
|
+
var insertTagStatements, updateTagStatusStatements, updateTagDropModeStatements, updateTagMessageIdStatements, getTagNumbersByMessageIdStatements, deleteTagsByMessageIdStatements, getMaxTagNumberBySessionStatements, getTagNumberByMessageIdStatements, updateTagByteSizeStatements, updateTagInputByteSizeStatements, CONTENT_ID_SUFFIX, updateTagTokenCountStatements, updateTagInputTokenCountStatements, getOwnerScopedToolTagNumbersStatements, getMinMessageTagNumberForRawIdStatements, TAGGER_FLOOR_SCAN_MESSAGES = 8, TAGGER_FLOOR_MAX_PROBES = 64, TAGGER_FLOOR_SAFETY_MARGIN = 256, TAGGER_FLOOR_PER_SKIP_MARGIN = 64, 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", getActiveTagsBySessionStatements, getMaxDroppedTagNumberStatements, getToolTagNumberByOwnerStatements, getNullOwnerToolTagStatements, adoptNullOwnerToolTagStatements, deleteToolTagsByOwnerStatements;
|
|
154970
155140
|
var init_storage_tags = __esm(() => {
|
|
154971
155141
|
insertTagStatements = new WeakMap;
|
|
154972
155142
|
updateTagStatusStatements = new WeakMap;
|
|
@@ -154982,6 +155152,7 @@ var init_storage_tags = __esm(() => {
|
|
|
154982
155152
|
updateTagTokenCountStatements = new WeakMap;
|
|
154983
155153
|
updateTagInputTokenCountStatements = new WeakMap;
|
|
154984
155154
|
getOwnerScopedToolTagNumbersStatements = new WeakMap;
|
|
155155
|
+
getMinMessageTagNumberForRawIdStatements = new WeakMap;
|
|
154985
155156
|
getActiveTagsBySessionStatements = new WeakMap;
|
|
154986
155157
|
getMaxDroppedTagNumberStatements = new WeakMap;
|
|
154987
155158
|
getToolTagNumberByOwnerStatements = new WeakMap;
|
|
@@ -156218,6 +156389,58 @@ var init_safe_notification_target = __esm(() => {
|
|
|
156218
156389
|
DEFAULT_TITLE_RE = /^(New session - |Child session - )\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
156219
156390
|
});
|
|
156220
156391
|
|
|
156392
|
+
// src/shared/rpc-notifications.ts
|
|
156393
|
+
var exports_rpc_notifications = {};
|
|
156394
|
+
__export(exports_rpc_notifications, {
|
|
156395
|
+
pushNotification: () => pushNotification,
|
|
156396
|
+
isTuiConnected: () => isTuiConnected,
|
|
156397
|
+
drainNotifications: () => drainNotifications
|
|
156398
|
+
});
|
|
156399
|
+
function pushNotification(type, payload, sessionId) {
|
|
156400
|
+
queue.push({ id: nextNotificationId++, type, payload, sessionId });
|
|
156401
|
+
if (queue.length > 100) {
|
|
156402
|
+
const newestPerSession = new Map;
|
|
156403
|
+
for (const n of queue) {
|
|
156404
|
+
const prev = newestPerSession.get(n.sessionId);
|
|
156405
|
+
if (prev === undefined || n.id > prev) {
|
|
156406
|
+
newestPerSession.set(n.sessionId, n.id);
|
|
156407
|
+
}
|
|
156408
|
+
}
|
|
156409
|
+
const mustKeep = new Set(newestPerSession.values());
|
|
156410
|
+
const byNewest = [...queue].sort((a, b) => b.id - a.id);
|
|
156411
|
+
const kept = [];
|
|
156412
|
+
for (const n of byNewest) {
|
|
156413
|
+
if (kept.length < 50 || mustKeep.has(n.id))
|
|
156414
|
+
kept.push(n);
|
|
156415
|
+
}
|
|
156416
|
+
queue = kept.sort((a, b) => a.id - b.id);
|
|
156417
|
+
}
|
|
156418
|
+
}
|
|
156419
|
+
function drainNotifications(lastReceivedId = 0, sessionId) {
|
|
156420
|
+
const now = Date.now();
|
|
156421
|
+
lastDrainAtAny = now;
|
|
156422
|
+
if (sessionId !== undefined)
|
|
156423
|
+
lastDrainAtBySession.set(sessionId, now);
|
|
156424
|
+
const matchesClient = (notification) => sessionId === undefined || notification.sessionId === undefined || notification.sessionId === sessionId;
|
|
156425
|
+
if (lastReceivedId > 0) {
|
|
156426
|
+
queue = queue.filter((notification) => !(notification.id <= lastReceivedId && matchesClient(notification)));
|
|
156427
|
+
}
|
|
156428
|
+
return queue.filter((notification) => notification.id > lastReceivedId && matchesClient(notification));
|
|
156429
|
+
}
|
|
156430
|
+
function isTuiConnected(sessionId) {
|
|
156431
|
+
const now = Date.now();
|
|
156432
|
+
if (sessionId !== undefined) {
|
|
156433
|
+
const at = lastDrainAtBySession.get(sessionId) ?? 0;
|
|
156434
|
+
return at > 0 && now - at < TUI_CONNECTED_WINDOW_MS;
|
|
156435
|
+
}
|
|
156436
|
+
return lastDrainAtAny > 0 && now - lastDrainAtAny < TUI_CONNECTED_WINDOW_MS;
|
|
156437
|
+
}
|
|
156438
|
+
var queue, nextNotificationId = 1, lastDrainAtBySession, lastDrainAtAny = 0, TUI_CONNECTED_WINDOW_MS = 3000;
|
|
156439
|
+
var init_rpc_notifications = __esm(() => {
|
|
156440
|
+
queue = [];
|
|
156441
|
+
lastDrainAtBySession = new Map;
|
|
156442
|
+
});
|
|
156443
|
+
|
|
156221
156444
|
// src/plugin/conflict-warning-hook.ts
|
|
156222
156445
|
var exports_conflict_warning_hook = {};
|
|
156223
156446
|
__export(exports_conflict_warning_hook, {
|
|
@@ -156552,6 +156775,9 @@ async function sendStartupAnnouncement(client, directory, version2, features, fo
|
|
|
156552
156775
|
if (!sessionId) {
|
|
156553
156776
|
return;
|
|
156554
156777
|
}
|
|
156778
|
+
const { isTuiConnected: isTuiConnected2 } = await Promise.resolve().then(() => (init_rpc_notifications(), exports_rpc_notifications));
|
|
156779
|
+
if (isTuiConnected2(sessionId) || isTuiConnected2())
|
|
156780
|
+
return;
|
|
156555
156781
|
if (await waitForSafeNotificationTarget(client, sessionId) === "skip")
|
|
156556
156782
|
return;
|
|
156557
156783
|
const bullets = features.map((line) => ` • ${line}`).join(`
|
|
@@ -164531,6 +164757,20 @@ function getDistinctStoredModelIds(db, projectPath) {
|
|
|
164531
164757
|
const rows = getDistinctStoredModelIdsStatement(db).all(projectPath);
|
|
164532
164758
|
return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
|
|
164533
164759
|
}
|
|
164760
|
+
function getMemoryEmbedCoverage(db, projectPath, modelId) {
|
|
164761
|
+
const row = db.prepare(`SELECT
|
|
164762
|
+
COUNT(*) AS total,
|
|
164763
|
+
SUM(CASE WHEN EXISTS (
|
|
164764
|
+
SELECT 1 FROM memory_embeddings e
|
|
164765
|
+
WHERE e.memory_id = m.id AND e.model_id = ?
|
|
164766
|
+
) THEN 1 ELSE 0 END) AS embedded
|
|
164767
|
+
FROM memories m
|
|
164768
|
+
WHERE m.project_path = ? AND m.status = 'active'`).get(modelId, projectPath);
|
|
164769
|
+
return {
|
|
164770
|
+
total: typeof row?.total === "number" ? row.total : 0,
|
|
164771
|
+
embedded: typeof row?.embedded === "number" ? row.embedded : 0
|
|
164772
|
+
};
|
|
164773
|
+
}
|
|
164534
164774
|
var saveEmbeddingStatements, loadAllEmbeddingsStatements, deleteEmbeddingStatements, getStoredModelIdStatements, clearAllEmbeddingsStatements, getDistinctStoredModelIdsStatements;
|
|
164535
164775
|
var init_storage_memory_embeddings = __esm(() => {
|
|
164536
164776
|
saveEmbeddingStatements = new WeakMap;
|
|
@@ -165333,6 +165573,16 @@ function buildCanonicalChunkTextFromFts(db, sessionId, startOrdinal, endOrdinal)
|
|
|
165333
165573
|
return lines.join(`
|
|
165334
165574
|
`);
|
|
165335
165575
|
}
|
|
165576
|
+
function buildCompartmentSummaryFallbackText(db, compartmentId) {
|
|
165577
|
+
const row = db.prepare("SELECT title, p1, content FROM compartments WHERE id = ?").get(compartmentId);
|
|
165578
|
+
if (!row)
|
|
165579
|
+
return "";
|
|
165580
|
+
const title = typeof row.title === "string" ? row.title.trim() : "";
|
|
165581
|
+
const p1 = typeof row.p1 === "string" ? row.p1.trim() : "";
|
|
165582
|
+
const body = p1.length > 0 ? p1 : typeof row.content === "string" ? row.content.trim() : "";
|
|
165583
|
+
return [title, body].filter((s) => s.length > 0).join(`
|
|
165584
|
+
`);
|
|
165585
|
+
}
|
|
165336
165586
|
function canonicalizeInMemoryChunkTextForEmbedding(chunkText, startOrdinal, endOrdinal) {
|
|
165337
165587
|
const lines = [];
|
|
165338
165588
|
for (const rawLine of chunkText.split(/\r?\n/)) {
|
|
@@ -165575,6 +165825,28 @@ function countUnembeddedSessionCompartments(db, projectPath, sessionId, modelId)
|
|
|
165575
165825
|
)`).get(projectPath, sessionId, projectPath, modelId);
|
|
165576
165826
|
return typeof row?.n === "number" ? row.n : 0;
|
|
165577
165827
|
}
|
|
165828
|
+
function countSessionCompartmentEmbedCoverage(db, projectPath, sessionId, modelId) {
|
|
165829
|
+
const row = db.prepare(`SELECT
|
|
165830
|
+
COUNT(*) AS total,
|
|
165831
|
+
SUM(CASE WHEN EXISTS (
|
|
165832
|
+
SELECT 1 FROM compartment_chunk_embeddings e
|
|
165833
|
+
WHERE e.compartment_id = c.id
|
|
165834
|
+
AND e.project_path = ?
|
|
165835
|
+
AND e.model_id = ?
|
|
165836
|
+
) THEN 1 ELSE 0 END) AS embedded
|
|
165837
|
+
FROM compartments c
|
|
165838
|
+
JOIN session_projects sp
|
|
165839
|
+
ON sp.session_id = c.session_id
|
|
165840
|
+
AND sp.harness = c.harness
|
|
165841
|
+
AND sp.project_path = ?
|
|
165842
|
+
WHERE c.session_id = ?
|
|
165843
|
+
AND c.start_message IS NOT NULL
|
|
165844
|
+
AND c.end_message IS NOT NULL`).get(projectPath, modelId, projectPath, sessionId);
|
|
165845
|
+
return {
|
|
165846
|
+
total: typeof row?.total === "number" ? row.total : 0,
|
|
165847
|
+
embedded: typeof row?.embedded === "number" ? row.embedded : 0
|
|
165848
|
+
};
|
|
165849
|
+
}
|
|
165578
165850
|
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;
|
|
165579
165851
|
var init_compartment_chunk_embedding = __esm(() => {
|
|
165580
165852
|
init_read_session_formatting();
|
|
@@ -165623,366 +165895,16 @@ function getEmbeddingProviderIdentity(config2) {
|
|
|
165623
165895
|
endpoint: normalizeEndpoint2(config2.endpoint),
|
|
165624
165896
|
apiKeyPresent: Boolean(config2.api_key?.trim()),
|
|
165625
165897
|
inputType: config2.input_type?.trim() || ""
|
|
165626
|
-
} :
|
|
165627
|
-
|
|
165628
|
-
|
|
165629
|
-
|
|
165630
|
-
apiKeyPresent: false
|
|
165631
|
-
};
|
|
165898
|
+
} : null;
|
|
165899
|
+
if (!identityInput) {
|
|
165900
|
+
return "embedding-provider:off";
|
|
165901
|
+
}
|
|
165632
165902
|
return `embedding-provider:${computeNormalizedHash(JSON.stringify(identityInput))}`;
|
|
165633
165903
|
}
|
|
165634
165904
|
var init_embedding_identity = __esm(() => {
|
|
165635
|
-
init_magic_context();
|
|
165636
165905
|
init_normalize_hash();
|
|
165637
165906
|
});
|
|
165638
165907
|
|
|
165639
|
-
// src/features/magic-context/memory/embedding-local.ts
|
|
165640
|
-
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
165641
|
-
import { open, stat, unlink, writeFile } from "node:fs/promises";
|
|
165642
|
-
import { dirname as dirname4, join as join13 } from "node:path";
|
|
165643
|
-
import { pathToFileURL } from "node:url";
|
|
165644
|
-
async function acquireModelLoadLock(lockPath) {
|
|
165645
|
-
const waitStart = Date.now();
|
|
165646
|
-
while (true) {
|
|
165647
|
-
try {
|
|
165648
|
-
const handle = await open(lockPath, "wx");
|
|
165649
|
-
try {
|
|
165650
|
-
await handle.writeFile(`pid=${process.pid} started=${Date.now()}
|
|
165651
|
-
`);
|
|
165652
|
-
} catch {}
|
|
165653
|
-
await handle.close();
|
|
165654
|
-
return async () => {
|
|
165655
|
-
try {
|
|
165656
|
-
await unlink(lockPath);
|
|
165657
|
-
} catch {}
|
|
165658
|
-
};
|
|
165659
|
-
} catch (error51) {
|
|
165660
|
-
const code = error51.code;
|
|
165661
|
-
if (code !== "EEXIST" && code !== "EPERM") {
|
|
165662
|
-
throw error51;
|
|
165663
|
-
}
|
|
165664
|
-
try {
|
|
165665
|
-
const info = await stat(lockPath);
|
|
165666
|
-
if (Date.now() - info.mtimeMs > STALE_LOCK_MS) {
|
|
165667
|
-
log(`[magic-context] embedding-load lock stale (>${STALE_LOCK_MS}ms), taking over`);
|
|
165668
|
-
try {
|
|
165669
|
-
await unlink(lockPath);
|
|
165670
|
-
} catch {}
|
|
165671
|
-
continue;
|
|
165672
|
-
}
|
|
165673
|
-
} catch {
|
|
165674
|
-
continue;
|
|
165675
|
-
}
|
|
165676
|
-
if (Date.now() - waitStart > MAX_LOCK_WAIT_MS) {
|
|
165677
|
-
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.`);
|
|
165678
|
-
}
|
|
165679
|
-
await new Promise((resolve6) => setTimeout(resolve6, LOCK_POLL_MS));
|
|
165680
|
-
}
|
|
165681
|
-
}
|
|
165682
|
-
}
|
|
165683
|
-
function startLockHeartbeat(lockPath) {
|
|
165684
|
-
const HEARTBEAT_MS = Math.floor(STALE_LOCK_MS / 3);
|
|
165685
|
-
const timer = setInterval(() => {
|
|
165686
|
-
writeFile(lockPath, `pid=${process.pid} alive=${Date.now()}
|
|
165687
|
-
`).catch(() => {});
|
|
165688
|
-
}, HEARTBEAT_MS);
|
|
165689
|
-
timer.unref?.();
|
|
165690
|
-
return () => clearInterval(timer);
|
|
165691
|
-
}
|
|
165692
|
-
async function injectWasmOrtForElectron() {
|
|
165693
|
-
if (typeof process === "undefined" || !process.versions?.electron) {
|
|
165694
|
-
return false;
|
|
165695
|
-
}
|
|
165696
|
-
try {
|
|
165697
|
-
const ortWebSpec = `onnxruntime-${"web"}`;
|
|
165698
|
-
const ortWeb = await import(ortWebSpec);
|
|
165699
|
-
try {
|
|
165700
|
-
const { createRequire: createRequireFn } = await import("node:module");
|
|
165701
|
-
const requireFn = createRequireFn(import.meta.url);
|
|
165702
|
-
const pkgPath = requireFn.resolve("onnxruntime-web/package.json");
|
|
165703
|
-
const distDir = join13(dirname4(pkgPath), "dist");
|
|
165704
|
-
const wasmPathsPrefix = `${pathToFileURL(distDir).href}/`;
|
|
165705
|
-
if (ortWeb.env?.wasm) {
|
|
165706
|
-
ortWeb.env.wasm.wasmPaths = wasmPathsPrefix;
|
|
165707
|
-
}
|
|
165708
|
-
} catch (pathError) {
|
|
165709
|
-
log("[magic-context] could not resolve local onnxruntime-web/dist, falling back to default WASM paths:", pathError instanceof Error ? pathError.message : String(pathError));
|
|
165710
|
-
}
|
|
165711
|
-
globalThis[Symbol.for("onnxruntime")] = ortWeb;
|
|
165712
|
-
log("[magic-context] Electron detected — using onnxruntime-web (WASM) for embeddings (bypasses onnxruntime-node native load)");
|
|
165713
|
-
return true;
|
|
165714
|
-
} catch (error51) {
|
|
165715
|
-
log("[magic-context] failed to inject onnxruntime-web for Electron — letting transformers fall back to native:", error51 instanceof Error ? error51.message : String(error51));
|
|
165716
|
-
return false;
|
|
165717
|
-
}
|
|
165718
|
-
}
|
|
165719
|
-
async function withQuietConsole(fn) {
|
|
165720
|
-
const origWarn = console.warn;
|
|
165721
|
-
const origError = console.error;
|
|
165722
|
-
const redirect = (...args) => {
|
|
165723
|
-
const message = args.map((a) => typeof a === "string" ? a : String(a)).join(" ");
|
|
165724
|
-
log(`[transformers] ${message}`);
|
|
165725
|
-
};
|
|
165726
|
-
console.warn = redirect;
|
|
165727
|
-
console.error = redirect;
|
|
165728
|
-
try {
|
|
165729
|
-
return await fn();
|
|
165730
|
-
} finally {
|
|
165731
|
-
console.warn = origWarn;
|
|
165732
|
-
console.error = origError;
|
|
165733
|
-
}
|
|
165734
|
-
}
|
|
165735
|
-
function isTransientLoadError(error51) {
|
|
165736
|
-
const message = error51 instanceof Error ? error51.message : String(error51 ?? "");
|
|
165737
|
-
if (!message)
|
|
165738
|
-
return false;
|
|
165739
|
-
const lower = message.toLowerCase();
|
|
165740
|
-
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");
|
|
165741
|
-
}
|
|
165742
|
-
function isArrayLikeNumber(value) {
|
|
165743
|
-
if (typeof value !== "object" || value === null || !("length" in value)) {
|
|
165744
|
-
return false;
|
|
165745
|
-
}
|
|
165746
|
-
const arr = value;
|
|
165747
|
-
if (typeof arr.length !== "number") {
|
|
165748
|
-
return false;
|
|
165749
|
-
}
|
|
165750
|
-
return arr.length === 0 || typeof arr[0] === "number";
|
|
165751
|
-
}
|
|
165752
|
-
function toFloat32Array3(values) {
|
|
165753
|
-
return values instanceof Float32Array ? new Float32Array(values) : Float32Array.from(Array.from(values));
|
|
165754
|
-
}
|
|
165755
|
-
function extractBatchEmbeddings(result, expectedCount) {
|
|
165756
|
-
const { data } = result;
|
|
165757
|
-
if (Array.isArray(data) && data.length === expectedCount && data.every((entry) => typeof entry !== "number" && isArrayLikeNumber(entry))) {
|
|
165758
|
-
return data.map((entry) => toFloat32Array3(entry));
|
|
165759
|
-
}
|
|
165760
|
-
if (!isArrayLikeNumber(data)) {
|
|
165761
|
-
log("[magic-context] embedding batch returned unexpected data shape");
|
|
165762
|
-
return Array.from({ length: expectedCount }, () => null);
|
|
165763
|
-
}
|
|
165764
|
-
const flatData = toFloat32Array3(data);
|
|
165765
|
-
const dimension = result.dims?.at(-1) ?? flatData.length / expectedCount;
|
|
165766
|
-
if (!Number.isInteger(dimension) || dimension <= 0 || flatData.length !== expectedCount * dimension) {
|
|
165767
|
-
log("[magic-context] embedding batch returned invalid dimensions");
|
|
165768
|
-
return Array.from({ length: expectedCount }, () => null);
|
|
165769
|
-
}
|
|
165770
|
-
const embeddings = [];
|
|
165771
|
-
for (let index = 0;index < expectedCount; index++) {
|
|
165772
|
-
embeddings.push(flatData.slice(index * dimension, (index + 1) * dimension));
|
|
165773
|
-
}
|
|
165774
|
-
return embeddings;
|
|
165775
|
-
}
|
|
165776
|
-
|
|
165777
|
-
class LocalEmbeddingProvider {
|
|
165778
|
-
modelId;
|
|
165779
|
-
maxInputTokens;
|
|
165780
|
-
model;
|
|
165781
|
-
pipeline = null;
|
|
165782
|
-
initPromise = null;
|
|
165783
|
-
inFlight = 0;
|
|
165784
|
-
disposing = false;
|
|
165785
|
-
disposePromise = null;
|
|
165786
|
-
inFlightWaiters = [];
|
|
165787
|
-
constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512) {
|
|
165788
|
-
this.model = model;
|
|
165789
|
-
this.maxInputTokens = maxInputTokens;
|
|
165790
|
-
this.modelId = getEmbeddingProviderIdentity({ provider: "local", model });
|
|
165791
|
-
}
|
|
165792
|
-
async initialize() {
|
|
165793
|
-
if (this.disposing) {
|
|
165794
|
-
return false;
|
|
165795
|
-
}
|
|
165796
|
-
if (this.pipeline) {
|
|
165797
|
-
return true;
|
|
165798
|
-
}
|
|
165799
|
-
if (this.initPromise) {
|
|
165800
|
-
await this.initPromise;
|
|
165801
|
-
return this.pipeline !== null;
|
|
165802
|
-
}
|
|
165803
|
-
this.initPromise = (async () => {
|
|
165804
|
-
try {
|
|
165805
|
-
if (this.disposing) {
|
|
165806
|
-
return;
|
|
165807
|
-
}
|
|
165808
|
-
await injectWasmOrtForElectron();
|
|
165809
|
-
const transformersSpec = "@huggingface/transformers";
|
|
165810
|
-
const transformersModule = await import(transformersSpec);
|
|
165811
|
-
const env = transformersModule.env;
|
|
165812
|
-
const LogLevel = transformersModule.LogLevel;
|
|
165813
|
-
if (LogLevel && "ERROR" in LogLevel) {
|
|
165814
|
-
env.logLevel = LogLevel.ERROR;
|
|
165815
|
-
}
|
|
165816
|
-
const modelCacheDir = join13(getMagicContextStorageDir(), "models");
|
|
165817
|
-
try {
|
|
165818
|
-
mkdirSync3(modelCacheDir, { recursive: true });
|
|
165819
|
-
env.cacheDir = modelCacheDir;
|
|
165820
|
-
} catch {
|
|
165821
|
-
log("[magic-context] could not create model cache dir, using library default");
|
|
165822
|
-
}
|
|
165823
|
-
const createPipeline = transformersModule.pipeline;
|
|
165824
|
-
const lockPath = join13(modelCacheDir, ".load.lock");
|
|
165825
|
-
const releaseLock = await acquireModelLoadLock(lockPath);
|
|
165826
|
-
const stopHeartbeat = startLockHeartbeat(lockPath);
|
|
165827
|
-
try {
|
|
165828
|
-
const MAX_ATTEMPTS = 3;
|
|
165829
|
-
let lastError;
|
|
165830
|
-
for (let attempt = 1;attempt <= MAX_ATTEMPTS; attempt++) {
|
|
165831
|
-
try {
|
|
165832
|
-
const pipeline = await withQuietConsole(() => createPipeline("feature-extraction", this.model, {
|
|
165833
|
-
dtype: "fp32"
|
|
165834
|
-
}));
|
|
165835
|
-
if (this.disposing) {
|
|
165836
|
-
await pipeline.dispose?.();
|
|
165837
|
-
this.pipeline = null;
|
|
165838
|
-
} else {
|
|
165839
|
-
this.pipeline = pipeline;
|
|
165840
|
-
}
|
|
165841
|
-
lastError = undefined;
|
|
165842
|
-
break;
|
|
165843
|
-
} catch (error51) {
|
|
165844
|
-
lastError = error51;
|
|
165845
|
-
if (!isTransientLoadError(error51) || attempt === MAX_ATTEMPTS) {
|
|
165846
|
-
break;
|
|
165847
|
-
}
|
|
165848
|
-
const delayMs = 300 * attempt + Math.floor(Math.random() * 200);
|
|
165849
|
-
log(`[magic-context] embedding model load attempt ${attempt}/${MAX_ATTEMPTS} failed transiently, retrying in ${delayMs}ms`);
|
|
165850
|
-
await new Promise((resolve6) => setTimeout(resolve6, delayMs));
|
|
165851
|
-
}
|
|
165852
|
-
}
|
|
165853
|
-
if (this.pipeline) {
|
|
165854
|
-
log(`[magic-context] embedding model loaded: ${this.model}`);
|
|
165855
|
-
} else if (this.disposing) {
|
|
165856
|
-
return;
|
|
165857
|
-
} else {
|
|
165858
|
-
throw lastError ?? new Error("unknown embedding load failure");
|
|
165859
|
-
}
|
|
165860
|
-
} finally {
|
|
165861
|
-
stopHeartbeat();
|
|
165862
|
-
await releaseLock();
|
|
165863
|
-
}
|
|
165864
|
-
} catch (error51) {
|
|
165865
|
-
log("[magic-context] embedding model failed to load:", error51);
|
|
165866
|
-
this.pipeline = null;
|
|
165867
|
-
} finally {
|
|
165868
|
-
this.initPromise = null;
|
|
165869
|
-
}
|
|
165870
|
-
})();
|
|
165871
|
-
await this.initPromise;
|
|
165872
|
-
return this.pipeline !== null;
|
|
165873
|
-
}
|
|
165874
|
-
waitForInFlightToDrain() {
|
|
165875
|
-
if (this.inFlight === 0) {
|
|
165876
|
-
return Promise.resolve();
|
|
165877
|
-
}
|
|
165878
|
-
return new Promise((resolve6) => {
|
|
165879
|
-
this.inFlightWaiters.push(resolve6);
|
|
165880
|
-
});
|
|
165881
|
-
}
|
|
165882
|
-
finishInFlight() {
|
|
165883
|
-
this.inFlight = Math.max(0, this.inFlight - 1);
|
|
165884
|
-
if (this.inFlight !== 0)
|
|
165885
|
-
return;
|
|
165886
|
-
const waiters = this.inFlightWaiters.splice(0);
|
|
165887
|
-
for (const waiter of waiters) {
|
|
165888
|
-
waiter();
|
|
165889
|
-
}
|
|
165890
|
-
}
|
|
165891
|
-
async embed(text, signal) {
|
|
165892
|
-
if (signal?.aborted)
|
|
165893
|
-
return null;
|
|
165894
|
-
if (this.disposing)
|
|
165895
|
-
return null;
|
|
165896
|
-
this.inFlight += 1;
|
|
165897
|
-
try {
|
|
165898
|
-
if (!await this.initialize()) {
|
|
165899
|
-
return null;
|
|
165900
|
-
}
|
|
165901
|
-
const pipeline = this.pipeline;
|
|
165902
|
-
if (!pipeline) {
|
|
165903
|
-
return null;
|
|
165904
|
-
}
|
|
165905
|
-
const result = await withQuietConsole(() => pipeline(text, {
|
|
165906
|
-
pooling: "mean",
|
|
165907
|
-
normalize: true
|
|
165908
|
-
}));
|
|
165909
|
-
return extractBatchEmbeddings(result, 1)[0] ?? null;
|
|
165910
|
-
} catch (error51) {
|
|
165911
|
-
log("[magic-context] embedding failed:", error51);
|
|
165912
|
-
return null;
|
|
165913
|
-
} finally {
|
|
165914
|
-
this.finishInFlight();
|
|
165915
|
-
}
|
|
165916
|
-
}
|
|
165917
|
-
async embedBatch(texts, signal) {
|
|
165918
|
-
if (texts.length === 0) {
|
|
165919
|
-
return [];
|
|
165920
|
-
}
|
|
165921
|
-
if (signal?.aborted) {
|
|
165922
|
-
return Array.from({ length: texts.length }, () => null);
|
|
165923
|
-
}
|
|
165924
|
-
if (this.disposing) {
|
|
165925
|
-
return Array.from({ length: texts.length }, () => null);
|
|
165926
|
-
}
|
|
165927
|
-
this.inFlight += 1;
|
|
165928
|
-
try {
|
|
165929
|
-
if (!await this.initialize()) {
|
|
165930
|
-
return Array.from({ length: texts.length }, () => null);
|
|
165931
|
-
}
|
|
165932
|
-
const pipeline = this.pipeline;
|
|
165933
|
-
if (!pipeline) {
|
|
165934
|
-
return Array.from({ length: texts.length }, () => null);
|
|
165935
|
-
}
|
|
165936
|
-
const result = await withQuietConsole(() => pipeline(texts, {
|
|
165937
|
-
pooling: "mean",
|
|
165938
|
-
normalize: true
|
|
165939
|
-
}));
|
|
165940
|
-
return extractBatchEmbeddings(result, texts.length);
|
|
165941
|
-
} catch (error51) {
|
|
165942
|
-
log("[magic-context] embedding batch failed:", error51);
|
|
165943
|
-
return Array.from({ length: texts.length }, () => null);
|
|
165944
|
-
} finally {
|
|
165945
|
-
this.finishInFlight();
|
|
165946
|
-
}
|
|
165947
|
-
}
|
|
165948
|
-
async dispose() {
|
|
165949
|
-
if (this.disposePromise) {
|
|
165950
|
-
return this.disposePromise;
|
|
165951
|
-
}
|
|
165952
|
-
this.disposing = true;
|
|
165953
|
-
this.disposePromise = (async () => {
|
|
165954
|
-
if (this.initPromise) {
|
|
165955
|
-
await this.initPromise;
|
|
165956
|
-
}
|
|
165957
|
-
await this.waitForInFlightToDrain();
|
|
165958
|
-
const pipelineToDispose = this.pipeline;
|
|
165959
|
-
this.pipeline = null;
|
|
165960
|
-
this.initPromise = null;
|
|
165961
|
-
if (!pipelineToDispose) {
|
|
165962
|
-
return;
|
|
165963
|
-
}
|
|
165964
|
-
try {
|
|
165965
|
-
await pipelineToDispose.dispose?.();
|
|
165966
|
-
} catch (error51) {
|
|
165967
|
-
log("[magic-context] embedding model dispose failed:", error51);
|
|
165968
|
-
}
|
|
165969
|
-
})();
|
|
165970
|
-
return this.disposePromise;
|
|
165971
|
-
}
|
|
165972
|
-
isLoaded() {
|
|
165973
|
-
return this.pipeline !== null;
|
|
165974
|
-
}
|
|
165975
|
-
}
|
|
165976
|
-
var LOCK_POLL_MS = 150, STALE_LOCK_MS, MAX_LOCK_WAIT_MS;
|
|
165977
|
-
var init_embedding_local = __esm(() => {
|
|
165978
|
-
init_magic_context();
|
|
165979
|
-
init_data_path();
|
|
165980
|
-
init_logger();
|
|
165981
|
-
init_embedding_identity();
|
|
165982
|
-
STALE_LOCK_MS = 3 * 60000;
|
|
165983
|
-
MAX_LOCK_WAIT_MS = 5 * 60000;
|
|
165984
|
-
});
|
|
165985
|
-
|
|
165986
165908
|
// src/features/magic-context/memory/embedding-ssrf.ts
|
|
165987
165909
|
function isLinkLocalIpv4(host) {
|
|
165988
165910
|
return /^169\.254\.\d{1,3}\.\d{1,3}$/.test(host);
|
|
@@ -166058,6 +165980,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
166058
165980
|
model;
|
|
166059
165981
|
apiKey;
|
|
166060
165982
|
inputType;
|
|
165983
|
+
queryInputType;
|
|
166061
165984
|
truncate;
|
|
166062
165985
|
initialized = false;
|
|
166063
165986
|
failureTimes = [];
|
|
@@ -166070,6 +165993,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
166070
165993
|
this.model = options.model?.trim() ?? "";
|
|
166071
165994
|
this.apiKey = options.apiKey?.trim() ?? "";
|
|
166072
165995
|
this.inputType = options.inputType?.trim() ?? "";
|
|
165996
|
+
this.queryInputType = options.queryInputType?.trim() ?? "";
|
|
166073
165997
|
this.truncate = options.truncate?.trim() ?? "";
|
|
166074
165998
|
this.maxInputTokens = typeof options.maxInputTokens === "number" && Number.isFinite(options.maxInputTokens) ? Math.max(1, Math.floor(options.maxInputTokens)) : 512;
|
|
166075
165999
|
this.modelId = getEmbeddingProviderIdentity({
|
|
@@ -166097,11 +166021,17 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
166097
166021
|
this.initialized = true;
|
|
166098
166022
|
return true;
|
|
166099
166023
|
}
|
|
166100
|
-
|
|
166101
|
-
|
|
166024
|
+
resolveInputTypeForPurpose(purpose = "passage") {
|
|
166025
|
+
if (purpose === "query") {
|
|
166026
|
+
return this.queryInputType || this.inputType;
|
|
166027
|
+
}
|
|
166028
|
+
return this.inputType;
|
|
166029
|
+
}
|
|
166030
|
+
async embed(text, signal, purpose) {
|
|
166031
|
+
const [embedding] = await this.embedBatch([text], signal, purpose);
|
|
166102
166032
|
return embedding ?? null;
|
|
166103
166033
|
}
|
|
166104
|
-
async embedBatch(texts, signal) {
|
|
166034
|
+
async embedBatch(texts, signal, purpose) {
|
|
166105
166035
|
if (texts.length === 0) {
|
|
166106
166036
|
return [];
|
|
166107
166037
|
}
|
|
@@ -166127,6 +166057,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
166127
166057
|
if (signal) {
|
|
166128
166058
|
signal.addEventListener("abort", onOuterAbort, { once: true });
|
|
166129
166059
|
}
|
|
166060
|
+
const inputTypeForRequest = this.resolveInputTypeForPurpose(purpose);
|
|
166130
166061
|
const response = await fetch(`${this.endpoint}/embeddings`, {
|
|
166131
166062
|
method: "POST",
|
|
166132
166063
|
headers: {
|
|
@@ -166136,7 +166067,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
166136
166067
|
body: JSON.stringify({
|
|
166137
166068
|
model: this.model,
|
|
166138
166069
|
input: texts,
|
|
166139
|
-
...
|
|
166070
|
+
...inputTypeForRequest ? { input_type: inputTypeForRequest } : {},
|
|
166140
166071
|
...this.truncate ? { truncate: this.truncate } : {}
|
|
166141
166072
|
}),
|
|
166142
166073
|
redirect: "error",
|
|
@@ -166387,6 +166318,121 @@ var init_storage_git_commit_embeddings = __esm(() => {
|
|
|
166387
166318
|
distinctModelIdStatements = new WeakMap;
|
|
166388
166319
|
});
|
|
166389
166320
|
|
|
166321
|
+
// src/features/magic-context/git-commits/storage-git-commits.ts
|
|
166322
|
+
function getInsertStatement(db) {
|
|
166323
|
+
let stmt = insertStatements.get(db);
|
|
166324
|
+
if (!stmt) {
|
|
166325
|
+
stmt = db.prepare(`INSERT INTO git_commits (sha, project_path, short_sha, message, author, committed_at, indexed_at)
|
|
166326
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
166327
|
+
ON CONFLICT(sha) DO UPDATE SET
|
|
166328
|
+
project_path = excluded.project_path,
|
|
166329
|
+
short_sha = excluded.short_sha,
|
|
166330
|
+
message = excluded.message,
|
|
166331
|
+
author = excluded.author,
|
|
166332
|
+
committed_at = excluded.committed_at,
|
|
166333
|
+
indexed_at = excluded.indexed_at
|
|
166334
|
+
WHERE git_commits.message != excluded.message`);
|
|
166335
|
+
insertStatements.set(db, stmt);
|
|
166336
|
+
}
|
|
166337
|
+
return stmt;
|
|
166338
|
+
}
|
|
166339
|
+
function getExistingShasStatement(db) {
|
|
166340
|
+
let stmt = existingShasStatements.get(db);
|
|
166341
|
+
if (!stmt) {
|
|
166342
|
+
stmt = db.prepare("SELECT sha FROM git_commits WHERE project_path = ?");
|
|
166343
|
+
existingShasStatements.set(db, stmt);
|
|
166344
|
+
}
|
|
166345
|
+
return stmt;
|
|
166346
|
+
}
|
|
166347
|
+
function getProjectCountStatement(db) {
|
|
166348
|
+
let stmt = projectCountStatements.get(db);
|
|
166349
|
+
if (!stmt) {
|
|
166350
|
+
stmt = db.prepare("SELECT COUNT(*) AS count FROM git_commits WHERE project_path = ?");
|
|
166351
|
+
projectCountStatements.set(db, stmt);
|
|
166352
|
+
}
|
|
166353
|
+
return stmt;
|
|
166354
|
+
}
|
|
166355
|
+
function getLatestCommitTimeStatement(db) {
|
|
166356
|
+
let stmt = latestCommitTimeStatements.get(db);
|
|
166357
|
+
if (!stmt) {
|
|
166358
|
+
stmt = db.prepare("SELECT MAX(committed_at) AS latest FROM git_commits WHERE project_path = ?");
|
|
166359
|
+
latestCommitTimeStatements.set(db, stmt);
|
|
166360
|
+
}
|
|
166361
|
+
return stmt;
|
|
166362
|
+
}
|
|
166363
|
+
function getEvictOverflowStatement(db) {
|
|
166364
|
+
let stmt = evictOverflowStatements.get(db);
|
|
166365
|
+
if (!stmt) {
|
|
166366
|
+
stmt = db.prepare(`DELETE FROM git_commits
|
|
166367
|
+
WHERE rowid IN (
|
|
166368
|
+
SELECT rowid FROM git_commits
|
|
166369
|
+
WHERE project_path = ?
|
|
166370
|
+
ORDER BY committed_at DESC, sha DESC
|
|
166371
|
+
LIMIT -1 OFFSET ?
|
|
166372
|
+
)`);
|
|
166373
|
+
evictOverflowStatements.set(db, stmt);
|
|
166374
|
+
}
|
|
166375
|
+
return stmt;
|
|
166376
|
+
}
|
|
166377
|
+
function upsertCommits(db, projectPath, commits) {
|
|
166378
|
+
if (commits.length === 0)
|
|
166379
|
+
return { inserted: 0, updated: 0 };
|
|
166380
|
+
const existing = new Set;
|
|
166381
|
+
for (const row of getExistingShasStatement(db).all(projectPath)) {
|
|
166382
|
+
existing.add(row.sha);
|
|
166383
|
+
}
|
|
166384
|
+
let inserted = 0;
|
|
166385
|
+
let updated = 0;
|
|
166386
|
+
const now = Date.now();
|
|
166387
|
+
const insertStmt = getInsertStatement(db);
|
|
166388
|
+
db.transaction(() => {
|
|
166389
|
+
for (const commit of commits) {
|
|
166390
|
+
const result = insertStmt.run(commit.sha, projectPath, commit.shortSha, commit.message, commit.author, commit.committedAtMs, now);
|
|
166391
|
+
if (result.changes > 0) {
|
|
166392
|
+
if (existing.has(commit.sha)) {
|
|
166393
|
+
updated++;
|
|
166394
|
+
} else {
|
|
166395
|
+
inserted++;
|
|
166396
|
+
existing.add(commit.sha);
|
|
166397
|
+
}
|
|
166398
|
+
}
|
|
166399
|
+
}
|
|
166400
|
+
})();
|
|
166401
|
+
return { inserted, updated };
|
|
166402
|
+
}
|
|
166403
|
+
function getCommitCount(db, projectPath) {
|
|
166404
|
+
const row = getProjectCountStatement(db).get(projectPath);
|
|
166405
|
+
return row?.count ?? 0;
|
|
166406
|
+
}
|
|
166407
|
+
function getLatestIndexedCommitTimeMs(db, projectPath) {
|
|
166408
|
+
const row = getLatestCommitTimeStatement(db).get(projectPath);
|
|
166409
|
+
return row?.latest ?? null;
|
|
166410
|
+
}
|
|
166411
|
+
function enforceProjectCap(db, projectPath, maxCommits) {
|
|
166412
|
+
if (maxCommits <= 0)
|
|
166413
|
+
return 0;
|
|
166414
|
+
const count = getCommitCount(db, projectPath);
|
|
166415
|
+
if (count <= maxCommits)
|
|
166416
|
+
return 0;
|
|
166417
|
+
getEvictOverflowStatement(db).run(projectPath, maxCommits);
|
|
166418
|
+
const after = getCommitCount(db, projectPath);
|
|
166419
|
+
const evicted = Math.max(0, count - after);
|
|
166420
|
+
if (evicted > 0) {
|
|
166421
|
+
log(`[git-commits] evicted ${evicted} oldest commits for project ${projectPath} (cap=${maxCommits}, was=${count})`);
|
|
166422
|
+
}
|
|
166423
|
+
return evicted;
|
|
166424
|
+
}
|
|
166425
|
+
var insertStatements, existingShasStatements, projectCountStatements, evictStatements, evictOverflowStatements, latestCommitTimeStatements;
|
|
166426
|
+
var init_storage_git_commits = __esm(() => {
|
|
166427
|
+
init_logger();
|
|
166428
|
+
insertStatements = new WeakMap;
|
|
166429
|
+
existingShasStatements = new WeakMap;
|
|
166430
|
+
projectCountStatements = new WeakMap;
|
|
166431
|
+
evictStatements = new WeakMap;
|
|
166432
|
+
evictOverflowStatements = new WeakMap;
|
|
166433
|
+
latestCommitTimeStatements = new WeakMap;
|
|
166434
|
+
});
|
|
166435
|
+
|
|
166390
166436
|
// src/features/magic-context/git-commits/sweep-coordinator.ts
|
|
166391
166437
|
function runImmediate2(db, body) {
|
|
166392
166438
|
db.exec("BEGIN IMMEDIATE");
|
|
@@ -166586,18 +166632,13 @@ var init_session_project_storage = __esm(() => {
|
|
|
166586
166632
|
// src/features/magic-context/project-embedding-registry.ts
|
|
166587
166633
|
import { createHash as createHash9, randomUUID } from "node:crypto";
|
|
166588
166634
|
function resolveEmbeddingConfig(config2) {
|
|
166589
|
-
if (!config2 || config2.provider === "
|
|
166590
|
-
return {
|
|
166591
|
-
provider: "local",
|
|
166592
|
-
model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
166593
|
-
...config2?.max_input_tokens ? {
|
|
166594
|
-
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
166595
|
-
} : {}
|
|
166596
|
-
};
|
|
166635
|
+
if (!config2 || config2.provider === "off") {
|
|
166636
|
+
return { provider: "off" };
|
|
166597
166637
|
}
|
|
166598
166638
|
if (config2.provider === "openai-compatible") {
|
|
166599
166639
|
const apiKey = config2.api_key?.trim();
|
|
166600
166640
|
const inputType = config2.input_type?.trim();
|
|
166641
|
+
const queryInputType = config2.query_input_type?.trim();
|
|
166601
166642
|
const truncate = config2.truncate?.trim();
|
|
166602
166643
|
return {
|
|
166603
166644
|
provider: "openai-compatible",
|
|
@@ -166605,6 +166646,7 @@ function resolveEmbeddingConfig(config2) {
|
|
|
166605
166646
|
endpoint: config2.endpoint.trim(),
|
|
166606
166647
|
...apiKey ? { api_key: apiKey } : {},
|
|
166607
166648
|
...inputType ? { input_type: inputType } : {},
|
|
166649
|
+
...queryInputType ? { query_input_type: queryInputType } : {},
|
|
166608
166650
|
...truncate ? { truncate } : {},
|
|
166609
166651
|
...config2.max_input_tokens ? {
|
|
166610
166652
|
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
@@ -166626,11 +166668,12 @@ function createProvider(config2) {
|
|
|
166626
166668
|
model: config2.model,
|
|
166627
166669
|
apiKey: config2.api_key,
|
|
166628
166670
|
inputType: config2.input_type,
|
|
166671
|
+
queryInputType: config2.query_input_type,
|
|
166629
166672
|
truncate: config2.truncate,
|
|
166630
166673
|
maxInputTokens: config2.max_input_tokens
|
|
166631
166674
|
});
|
|
166632
166675
|
}
|
|
166633
|
-
return
|
|
166676
|
+
return null;
|
|
166634
166677
|
}
|
|
166635
166678
|
function stableStringify2(value) {
|
|
166636
166679
|
if (Array.isArray(value)) {
|
|
@@ -166680,7 +166723,9 @@ function snapshotFor(registration) {
|
|
|
166680
166723
|
enabled,
|
|
166681
166724
|
gitCommitEnabled,
|
|
166682
166725
|
modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
|
|
166683
|
-
chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId
|
|
166726
|
+
chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId,
|
|
166727
|
+
model: registration.observationMode || !providerIsOn ? "off" : ("model" in registration.config) && registration.config.model.trim() ? registration.config.model.trim() : registration.modelId,
|
|
166728
|
+
provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "off"
|
|
166684
166729
|
};
|
|
166685
166730
|
}
|
|
166686
166731
|
function disposeProvider(provider) {
|
|
@@ -166806,7 +166851,7 @@ function getOrCreateProjectProvider(registration) {
|
|
|
166806
166851
|
registration.provider = provider;
|
|
166807
166852
|
return provider;
|
|
166808
166853
|
}
|
|
166809
|
-
async function embedTextForProject(projectIdentity, text, signal) {
|
|
166854
|
+
async function embedTextForProject(projectIdentity, text, signal, purpose = "passage") {
|
|
166810
166855
|
const registration = projectRegistrations.get(projectIdentity);
|
|
166811
166856
|
if (!registration)
|
|
166812
166857
|
return null;
|
|
@@ -166815,7 +166860,7 @@ async function embedTextForProject(projectIdentity, text, signal) {
|
|
|
166815
166860
|
const provider = getOrCreateProjectProvider(registration);
|
|
166816
166861
|
if (!provider)
|
|
166817
166862
|
return null;
|
|
166818
|
-
const vector = await provider.embed(text, signal);
|
|
166863
|
+
const vector = await provider.embed(text, signal, purpose);
|
|
166819
166864
|
if (!vector)
|
|
166820
166865
|
return null;
|
|
166821
166866
|
const current = projectRegistrations.get(projectIdentity);
|
|
@@ -166824,7 +166869,7 @@ async function embedTextForProject(projectIdentity, text, signal) {
|
|
|
166824
166869
|
}
|
|
166825
166870
|
return { vector, modelId, generation };
|
|
166826
166871
|
}
|
|
166827
|
-
async function embedBatchForProject(projectIdentity, texts, signal) {
|
|
166872
|
+
async function embedBatchForProject(projectIdentity, texts, signal, purpose = "passage") {
|
|
166828
166873
|
if (texts.length === 0) {
|
|
166829
166874
|
const registration2 = projectRegistrations.get(projectIdentity);
|
|
166830
166875
|
if (!registration2 || registration2.observationMode)
|
|
@@ -166840,7 +166885,7 @@ async function embedBatchForProject(projectIdentity, texts, signal) {
|
|
|
166840
166885
|
const provider = getOrCreateProjectProvider(registration);
|
|
166841
166886
|
if (!provider)
|
|
166842
166887
|
return null;
|
|
166843
|
-
const vectors = await provider.embedBatch(texts, signal);
|
|
166888
|
+
const vectors = await provider.embedBatch(texts, signal, purpose);
|
|
166844
166889
|
const current = projectRegistrations.get(projectIdentity);
|
|
166845
166890
|
if (!current || current.generation !== generation || current.runtimeFingerprint !== runtimeFingerprint) {
|
|
166846
166891
|
return null;
|
|
@@ -166891,12 +166936,13 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
|
|
|
166891
166936
|
}
|
|
166892
166937
|
async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates, signal) {
|
|
166893
166938
|
const noWork = [];
|
|
166939
|
+
const failed = [];
|
|
166894
166940
|
if (candidates.length === 0)
|
|
166895
|
-
return { embedded: 0, noWork };
|
|
166941
|
+
return { embedded: 0, noWork, failed };
|
|
166896
166942
|
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
|
|
166897
166943
|
const prepared = [];
|
|
166898
166944
|
for (const candidate of candidates) {
|
|
166899
|
-
const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage);
|
|
166945
|
+
const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage) || buildCompartmentSummaryFallbackText(db, candidate.id);
|
|
166900
166946
|
if (canonicalText.length === 0) {
|
|
166901
166947
|
noWork.push(candidate.id);
|
|
166902
166948
|
continue;
|
|
@@ -166909,7 +166955,7 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
|
|
|
166909
166955
|
prepared.push({ candidate, windows });
|
|
166910
166956
|
}
|
|
166911
166957
|
if (prepared.length === 0)
|
|
166912
|
-
return { embedded: 0, noWork };
|
|
166958
|
+
return { embedded: 0, noWork, failed };
|
|
166913
166959
|
let embedded = 0;
|
|
166914
166960
|
let i = 0;
|
|
166915
166961
|
while (i < prepared.length) {
|
|
@@ -166926,35 +166972,60 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
|
|
|
166926
166972
|
const texts = [];
|
|
166927
166973
|
for (const item of slice)
|
|
166928
166974
|
texts.push(...item.windows.map((w) => w.text));
|
|
166929
|
-
|
|
166930
|
-
|
|
166931
|
-
if (!result)
|
|
166932
|
-
continue;
|
|
166975
|
+
const persistedIds = new Set;
|
|
166976
|
+
for (let attempt = 0;attempt < EMBED_SLICE_RETRY_ATTEMPTS; attempt++) {
|
|
166933
166977
|
if (signal?.aborted)
|
|
166934
166978
|
break;
|
|
166935
|
-
let
|
|
166936
|
-
|
|
166937
|
-
|
|
166938
|
-
|
|
166939
|
-
|
|
166940
|
-
|
|
166979
|
+
let result = null;
|
|
166980
|
+
const attemptStart = Date.now();
|
|
166981
|
+
try {
|
|
166982
|
+
result = await embedBatchForProject(projectIdentity, texts, signal);
|
|
166983
|
+
} catch (error51) {
|
|
166984
|
+
log("[magic-context] failed to proactively embed compartment chunks:", error51);
|
|
166985
|
+
}
|
|
166986
|
+
if (signal?.aborted)
|
|
166987
|
+
break;
|
|
166988
|
+
if (result) {
|
|
166989
|
+
let offset = 0;
|
|
166990
|
+
for (const item of slice) {
|
|
166991
|
+
const vectors = result.vectors.slice(offset, offset + item.windows.length);
|
|
166992
|
+
offset += item.windows.length;
|
|
166993
|
+
if (persistedIds.has(item.candidate.id))
|
|
166994
|
+
continue;
|
|
166995
|
+
if (vectors.length !== item.windows.length || vectors.some((v) => !v)) {
|
|
166996
|
+
continue;
|
|
166997
|
+
}
|
|
166998
|
+
const rows = item.windows.map((window, index) => ({
|
|
166999
|
+
compartmentId: item.candidate.id,
|
|
167000
|
+
sessionId: item.candidate.sessionId,
|
|
167001
|
+
projectPath: projectIdentity,
|
|
167002
|
+
window,
|
|
167003
|
+
modelId,
|
|
167004
|
+
vector: vectors[index]
|
|
167005
|
+
}));
|
|
167006
|
+
replaceCompartmentChunkEmbeddings(db, rows);
|
|
167007
|
+
persistedIds.add(item.candidate.id);
|
|
166941
167008
|
}
|
|
166942
|
-
const rows = item.windows.map((window, index) => ({
|
|
166943
|
-
compartmentId: item.candidate.id,
|
|
166944
|
-
sessionId: item.candidate.sessionId,
|
|
166945
|
-
projectPath: projectIdentity,
|
|
166946
|
-
window,
|
|
166947
|
-
modelId,
|
|
166948
|
-
vector: vectors[index]
|
|
166949
|
-
}));
|
|
166950
|
-
replaceCompartmentChunkEmbeddings(db, rows);
|
|
166951
|
-
embedded += 1;
|
|
166952
167009
|
}
|
|
166953
|
-
|
|
166954
|
-
|
|
167010
|
+
if (persistedIds.size === slice.length)
|
|
167011
|
+
break;
|
|
167012
|
+
if (persistedIds.size > 0)
|
|
167013
|
+
break;
|
|
167014
|
+
if (Date.now() - attemptStart >= EMBED_SLOW_FAILURE_NO_RETRY_MS)
|
|
167015
|
+
break;
|
|
167016
|
+
if (attempt < EMBED_SLICE_RETRY_ATTEMPTS - 1) {
|
|
167017
|
+
await new Promise((resolve6) => setTimeout(resolve6, EMBED_SLICE_RETRY_BASE_MS * 2 ** attempt));
|
|
167018
|
+
}
|
|
167019
|
+
}
|
|
167020
|
+
embedded += persistedIds.size;
|
|
167021
|
+
if (!signal?.aborted) {
|
|
167022
|
+
for (const item of slice) {
|
|
167023
|
+
if (!persistedIds.has(item.candidate.id))
|
|
167024
|
+
failed.push(item.candidate.id);
|
|
167025
|
+
}
|
|
166955
167026
|
}
|
|
166956
167027
|
}
|
|
166957
|
-
return { embedded, noWork };
|
|
167028
|
+
return { embedded, noWork, failed };
|
|
166958
167029
|
}
|
|
166959
167030
|
async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, options) {
|
|
166960
167031
|
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
@@ -166977,9 +167048,11 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
166977
167048
|
renewal.unref?.();
|
|
166978
167049
|
const batchSize = Math.max(1, options?.batchSize ?? CHUNK_DRAIN_BATCH_SIZE);
|
|
166979
167050
|
const skipIds = [];
|
|
167051
|
+
const failedIds = [];
|
|
166980
167052
|
let embedded = 0;
|
|
166981
167053
|
let aborted2 = false;
|
|
166982
|
-
let
|
|
167054
|
+
let providerDown = false;
|
|
167055
|
+
let consecutiveFailedBatches = 0;
|
|
166983
167056
|
try {
|
|
166984
167057
|
options?.onProgress?.({ embedded, total });
|
|
166985
167058
|
for (;; ) {
|
|
@@ -166987,15 +167060,26 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
166987
167060
|
aborted2 = true;
|
|
166988
167061
|
break;
|
|
166989
167062
|
}
|
|
166990
|
-
const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, skipIds);
|
|
167063
|
+
const candidates = loadUnembeddedSessionChunkCandidates(db, projectIdentity, sessionId, snapshot.chunkModelId, batchSize, [...skipIds, ...failedIds]);
|
|
166991
167064
|
if (candidates.length === 0)
|
|
166992
167065
|
break;
|
|
166993
|
-
const {
|
|
167066
|
+
const {
|
|
167067
|
+
embedded: n,
|
|
167068
|
+
noWork,
|
|
167069
|
+
failed
|
|
167070
|
+
} = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, options?.signal);
|
|
166994
167071
|
for (const id of noWork)
|
|
166995
167072
|
skipIds.push(id);
|
|
167073
|
+
for (const id of failed)
|
|
167074
|
+
failedIds.push(id);
|
|
166996
167075
|
if (n === 0 && noWork.length === 0) {
|
|
166997
|
-
|
|
166998
|
-
|
|
167076
|
+
consecutiveFailedBatches += 1;
|
|
167077
|
+
if (consecutiveFailedBatches >= MAX_CONSECUTIVE_FAILED_BATCHES) {
|
|
167078
|
+
providerDown = true;
|
|
167079
|
+
break;
|
|
167080
|
+
}
|
|
167081
|
+
} else {
|
|
167082
|
+
consecutiveFailedBatches = 0;
|
|
166999
167083
|
}
|
|
167000
167084
|
embedded += n;
|
|
167001
167085
|
options?.onProgress?.({ embedded: Math.min(embedded, total), total });
|
|
@@ -167003,27 +167087,60 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
167003
167087
|
}
|
|
167004
167088
|
} finally {
|
|
167005
167089
|
clearInterval(renewal);
|
|
167006
|
-
|
|
167090
|
+
try {
|
|
167091
|
+
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
167092
|
+
} catch (error51) {
|
|
167093
|
+
log("[magic-context] embed drain: lease release failed (will TTL-expire):", error51);
|
|
167094
|
+
}
|
|
167007
167095
|
}
|
|
167008
167096
|
if (aborted2)
|
|
167009
|
-
return { status: "aborted", embedded, total };
|
|
167010
|
-
if (
|
|
167097
|
+
return { status: "aborted", embedded, total, failed: failedIds.length };
|
|
167098
|
+
if (providerDown || failedIds.length > 0) {
|
|
167011
167099
|
const remaining = Math.max(0, countUnembeddedSessionCompartments(db, projectIdentity, sessionId, snapshot.chunkModelId) - skipIds.length);
|
|
167012
|
-
if (remaining > 0)
|
|
167013
|
-
return { status: "stalled", embedded, total, remaining };
|
|
167100
|
+
if (remaining > 0) {
|
|
167101
|
+
return { status: "stalled", embedded, total, remaining, failed: failedIds.length };
|
|
167102
|
+
}
|
|
167014
167103
|
}
|
|
167015
|
-
return { status: "done", embedded, total };
|
|
167104
|
+
return { status: "done", embedded, total, failed: failedIds.length };
|
|
167016
167105
|
}
|
|
167017
|
-
|
|
167106
|
+
function getEmbeddingCoverageStatus(db, projectIdentity, sessionId) {
|
|
167107
|
+
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
167108
|
+
if (!snapshot?.enabled || snapshot.chunkModelId === "off") {
|
|
167109
|
+
return {
|
|
167110
|
+
enabled: false,
|
|
167111
|
+
model: snapshot?.model ?? "off",
|
|
167112
|
+
provider: snapshot?.provider ?? "off",
|
|
167113
|
+
session: { embedded: 0, total: 0 },
|
|
167114
|
+
memories: { embedded: 0, total: 0 },
|
|
167115
|
+
commits: { embedded: 0, total: 0, gitEnabled: false }
|
|
167116
|
+
};
|
|
167117
|
+
}
|
|
167118
|
+
const session = countSessionCompartmentEmbedCoverage(db, projectIdentity, sessionId, snapshot.chunkModelId);
|
|
167119
|
+
const memories = getMemoryEmbedCoverage(db, projectIdentity, snapshot.modelId);
|
|
167120
|
+
const gitEnabled = snapshot.gitCommitEnabled;
|
|
167121
|
+
const commits = gitEnabled ? {
|
|
167122
|
+
embedded: countEmbeddedCommits(db, projectIdentity),
|
|
167123
|
+
total: getCommitCount(db, projectIdentity),
|
|
167124
|
+
gitEnabled: true
|
|
167125
|
+
} : { embedded: 0, total: 0, gitEnabled: false };
|
|
167126
|
+
return {
|
|
167127
|
+
enabled: true,
|
|
167128
|
+
model: snapshot.model,
|
|
167129
|
+
provider: snapshot.provider,
|
|
167130
|
+
session,
|
|
167131
|
+
memories,
|
|
167132
|
+
commits
|
|
167133
|
+
};
|
|
167134
|
+
}
|
|
167135
|
+
var OFF_PROVIDER_IDENTITY = "embedding-provider:off", SWEEP_MAX_WALL_CLOCK_MS, CHUNK_DRAIN_BATCH_SIZE = 8, MAX_WINDOWS_PER_EMBED_CALL = 2, SESSION_EMBED_LEASE_RENEWAL_MS, EMBED_SLICE_RETRY_ATTEMPTS = 3, EMBED_SLICE_RETRY_BASE_MS = 250, EMBED_SLOW_FAILURE_NO_RETRY_MS = 1e4, MAX_CONSECUTIVE_FAILED_BATCHES = 3, projectRegistrations, loadUnembeddedMemoriesStatements, globalRegistrationGeneration = 0, testProviderFactory = null;
|
|
167018
167136
|
var init_project_embedding_registry = __esm(() => {
|
|
167019
|
-
init_magic_context();
|
|
167020
167137
|
init_logger();
|
|
167021
167138
|
init_compartment_chunk_embedding();
|
|
167022
167139
|
init_storage_git_commit_embeddings();
|
|
167140
|
+
init_storage_git_commits();
|
|
167023
167141
|
init_sweep_coordinator();
|
|
167024
167142
|
init_embedding_cache();
|
|
167025
167143
|
init_embedding_identity();
|
|
167026
|
-
init_embedding_local();
|
|
167027
167144
|
init_embedding_openai();
|
|
167028
167145
|
init_storage_memory_embeddings();
|
|
167029
167146
|
init_session_project_storage();
|
|
@@ -167044,11 +167161,12 @@ function createProvider2(config2) {
|
|
|
167044
167161
|
model: config2.model,
|
|
167045
167162
|
apiKey: config2.api_key,
|
|
167046
167163
|
inputType: config2.input_type,
|
|
167164
|
+
queryInputType: config2.query_input_type,
|
|
167047
167165
|
truncate: config2.truncate,
|
|
167048
167166
|
maxInputTokens: config2.max_input_tokens
|
|
167049
167167
|
});
|
|
167050
167168
|
}
|
|
167051
|
-
return
|
|
167169
|
+
return null;
|
|
167052
167170
|
}
|
|
167053
167171
|
function getOrCreateProvider() {
|
|
167054
167172
|
if (provider) {
|
|
@@ -167072,17 +167190,14 @@ async function embedText(text, signal) {
|
|
|
167072
167190
|
}
|
|
167073
167191
|
var DEFAULT_EMBEDDING_CONFIG, embeddingConfig, provider = null, loadUnembeddedMemoriesStatements2, SWEEP_MAX_WALL_CLOCK_MS2;
|
|
167074
167192
|
var init_embedding = __esm(() => {
|
|
167075
|
-
init_magic_context();
|
|
167076
167193
|
init_logger();
|
|
167077
167194
|
init_compartment_chunk_embedding();
|
|
167078
167195
|
init_embedding_identity();
|
|
167079
|
-
init_embedding_local();
|
|
167080
167196
|
init_embedding_openai();
|
|
167081
167197
|
init_storage_memory_embeddings();
|
|
167082
167198
|
init_project_embedding_registry();
|
|
167083
167199
|
DEFAULT_EMBEDDING_CONFIG = {
|
|
167084
|
-
provider: "
|
|
167085
|
-
model: DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
167200
|
+
provider: "off"
|
|
167086
167201
|
};
|
|
167087
167202
|
embeddingConfig = DEFAULT_EMBEDDING_CONFIG;
|
|
167088
167203
|
loadUnembeddedMemoriesStatements2 = new WeakMap;
|
|
@@ -167163,13 +167278,13 @@ var init_storage_memory_fts = __esm(() => {
|
|
|
167163
167278
|
});
|
|
167164
167279
|
|
|
167165
167280
|
// src/shared/models-dev-cache.ts
|
|
167166
|
-
import { mkdirSync as
|
|
167167
|
-
import { join as
|
|
167281
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync9, renameSync, writeFileSync } from "node:fs";
|
|
167282
|
+
import { join as join13 } from "node:path";
|
|
167168
167283
|
function isSaneLimit(limit) {
|
|
167169
167284
|
return typeof limit === "number" && limit >= MIN_SANE_LIMIT && limit <= MAX_SANE_LIMIT;
|
|
167170
167285
|
}
|
|
167171
167286
|
function persistFilePath() {
|
|
167172
|
-
return
|
|
167287
|
+
return join13(getMagicContextStorageDir(), `model-context-limits-${getHarness()}.json`);
|
|
167173
167288
|
}
|
|
167174
167289
|
function loadPersistedApiCacheOnce() {
|
|
167175
167290
|
if (persistSeedLoaded || apiCache !== null)
|
|
@@ -167199,7 +167314,7 @@ function persistApiCache() {
|
|
|
167199
167314
|
}
|
|
167200
167315
|
try {
|
|
167201
167316
|
const dir = getMagicContextStorageDir();
|
|
167202
|
-
|
|
167317
|
+
mkdirSync3(dir, { recursive: true });
|
|
167203
167318
|
const target = persistFilePath();
|
|
167204
167319
|
const tmp = `${target}.${process.pid}.tmp`;
|
|
167205
167320
|
writeFileSync(tmp, JSON.stringify(obj), { encoding: "utf-8", mode: 384 });
|
|
@@ -167300,58 +167415,6 @@ var init_models_dev_cache = __esm(() => {
|
|
|
167300
167415
|
init_logger();
|
|
167301
167416
|
});
|
|
167302
167417
|
|
|
167303
|
-
// src/shared/rpc-notifications.ts
|
|
167304
|
-
var exports_rpc_notifications = {};
|
|
167305
|
-
__export(exports_rpc_notifications, {
|
|
167306
|
-
pushNotification: () => pushNotification,
|
|
167307
|
-
isTuiConnected: () => isTuiConnected,
|
|
167308
|
-
drainNotifications: () => drainNotifications
|
|
167309
|
-
});
|
|
167310
|
-
function pushNotification(type, payload, sessionId) {
|
|
167311
|
-
queue2.push({ id: nextNotificationId++, type, payload, sessionId });
|
|
167312
|
-
if (queue2.length > 100) {
|
|
167313
|
-
const newestPerSession = new Map;
|
|
167314
|
-
for (const n of queue2) {
|
|
167315
|
-
const prev = newestPerSession.get(n.sessionId);
|
|
167316
|
-
if (prev === undefined || n.id > prev) {
|
|
167317
|
-
newestPerSession.set(n.sessionId, n.id);
|
|
167318
|
-
}
|
|
167319
|
-
}
|
|
167320
|
-
const mustKeep = new Set(newestPerSession.values());
|
|
167321
|
-
const byNewest = [...queue2].sort((a, b) => b.id - a.id);
|
|
167322
|
-
const kept = [];
|
|
167323
|
-
for (const n of byNewest) {
|
|
167324
|
-
if (kept.length < 50 || mustKeep.has(n.id))
|
|
167325
|
-
kept.push(n);
|
|
167326
|
-
}
|
|
167327
|
-
queue2 = kept.sort((a, b) => a.id - b.id);
|
|
167328
|
-
}
|
|
167329
|
-
}
|
|
167330
|
-
function drainNotifications(lastReceivedId = 0, sessionId) {
|
|
167331
|
-
const now = Date.now();
|
|
167332
|
-
lastDrainAtAny = now;
|
|
167333
|
-
if (sessionId !== undefined)
|
|
167334
|
-
lastDrainAtBySession.set(sessionId, now);
|
|
167335
|
-
const matchesClient = (notification) => sessionId === undefined || notification.sessionId === undefined || notification.sessionId === sessionId;
|
|
167336
|
-
if (lastReceivedId > 0) {
|
|
167337
|
-
queue2 = queue2.filter((notification) => !(notification.id <= lastReceivedId && matchesClient(notification)));
|
|
167338
|
-
}
|
|
167339
|
-
return queue2.filter((notification) => notification.id > lastReceivedId && matchesClient(notification));
|
|
167340
|
-
}
|
|
167341
|
-
function isTuiConnected(sessionId) {
|
|
167342
|
-
const now = Date.now();
|
|
167343
|
-
if (sessionId !== undefined) {
|
|
167344
|
-
const at = lastDrainAtBySession.get(sessionId) ?? 0;
|
|
167345
|
-
return at > 0 && now - at < TUI_CONNECTED_WINDOW_MS;
|
|
167346
|
-
}
|
|
167347
|
-
return lastDrainAtAny > 0 && now - lastDrainAtAny < TUI_CONNECTED_WINDOW_MS;
|
|
167348
|
-
}
|
|
167349
|
-
var queue2, nextNotificationId = 1, lastDrainAtBySession, lastDrainAtAny = 0, TUI_CONNECTED_WINDOW_MS = 3000;
|
|
167350
|
-
var init_rpc_notifications = __esm(() => {
|
|
167351
|
-
queue2 = [];
|
|
167352
|
-
lastDrainAtBySession = new Map;
|
|
167353
|
-
});
|
|
167354
|
-
|
|
167355
167418
|
// src/features/magic-context/compartment-embedding.ts
|
|
167356
167419
|
async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compartments) {
|
|
167357
167420
|
if (compartments.length === 0)
|
|
@@ -167360,7 +167423,7 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
|
|
|
167360
167423
|
for (const compartment of compartments) {
|
|
167361
167424
|
try {
|
|
167362
167425
|
const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
|
|
167363
|
-
const canonicalText = fromMemory || buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage);
|
|
167426
|
+
const canonicalText = fromMemory || buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage) || buildCompartmentSummaryFallbackText(db, compartment.id);
|
|
167364
167427
|
if (canonicalText.length === 0)
|
|
167365
167428
|
continue;
|
|
167366
167429
|
const windows = chunkCanonicalText(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
|
|
@@ -167405,7 +167468,7 @@ var init_compartment_embedding = __esm(() => {
|
|
|
167405
167468
|
});
|
|
167406
167469
|
|
|
167407
167470
|
// src/features/magic-context/compaction-marker.ts
|
|
167408
|
-
import { join as
|
|
167471
|
+
import { join as join14 } from "node:path";
|
|
167409
167472
|
function randomBase62(length) {
|
|
167410
167473
|
const chars = [];
|
|
167411
167474
|
for (let i = 0;i < length; i++) {
|
|
@@ -167425,7 +167488,7 @@ function generatePartId(timestampMs, counter = 0n) {
|
|
|
167425
167488
|
return generateId("prt", timestampMs, counter);
|
|
167426
167489
|
}
|
|
167427
167490
|
function getOpenCodeDbPath3() {
|
|
167428
|
-
return
|
|
167491
|
+
return join14(getDataDir(), "opencode", "opencode.db");
|
|
167429
167492
|
}
|
|
167430
167493
|
function isOpenCodeSchemaCompatible(db, dbPath) {
|
|
167431
167494
|
if (cachedSchemaCompatible?.path === dbPath) {
|
|
@@ -167567,7 +167630,7 @@ var init_compaction_marker = __esm(async () => {
|
|
|
167567
167630
|
});
|
|
167568
167631
|
|
|
167569
167632
|
// src/hooks/magic-context/compaction-marker-manager.ts
|
|
167570
|
-
import { join as
|
|
167633
|
+
import { join as join15 } from "node:path";
|
|
167571
167634
|
function validatePendingTarget(db, sessionId, pending) {
|
|
167572
167635
|
const ocMessage = getOpenCodeMessageById(sessionId, pending.endMessageId);
|
|
167573
167636
|
if (!ocMessage) {
|
|
@@ -167676,7 +167739,7 @@ function removeCompactionMarkerForSession(db, sessionId) {
|
|
|
167676
167739
|
}
|
|
167677
167740
|
}
|
|
167678
167741
|
function checkCompactionMarkerConsistency(db) {
|
|
167679
|
-
const opencodeDbPath =
|
|
167742
|
+
const opencodeDbPath = join15(getDataDir(), "opencode", "opencode.db");
|
|
167680
167743
|
let opencodeDb;
|
|
167681
167744
|
try {
|
|
167682
167745
|
opencodeDb = new Database(opencodeDbPath, { readonly: true });
|
|
@@ -168073,8 +168136,8 @@ var init_compartment_runner_validation = __esm(async () => {
|
|
|
168073
168136
|
});
|
|
168074
168137
|
|
|
168075
168138
|
// src/hooks/magic-context/compartment-runner-historian.ts
|
|
168076
|
-
import { mkdirSync as
|
|
168077
|
-
import { join as
|
|
168139
|
+
import { mkdirSync as mkdirSync4, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
168140
|
+
import { join as join16 } from "node:path";
|
|
168078
168141
|
function historianResponseDumpDir(directory) {
|
|
168079
168142
|
return getProjectMagicContextHistorianDir(directory);
|
|
168080
168143
|
}
|
|
@@ -168376,10 +168439,10 @@ function cleanupHistorianDump(sessionId, dumpPath) {
|
|
|
168376
168439
|
function dumpHistorianResponse(sessionId, directory, label, text) {
|
|
168377
168440
|
try {
|
|
168378
168441
|
const dumpDir = historianResponseDumpDir(directory);
|
|
168379
|
-
|
|
168442
|
+
mkdirSync4(dumpDir, { recursive: true });
|
|
168380
168443
|
const safeSessionId = sanitizeDumpName(sessionId);
|
|
168381
168444
|
const safeLabel = sanitizeDumpName(label);
|
|
168382
|
-
const dumpPath =
|
|
168445
|
+
const dumpPath = join16(dumpDir, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
|
|
168383
168446
|
writeFileSync2(dumpPath, text, "utf8");
|
|
168384
168447
|
sessionLog(sessionId, "compartment agent: historian response dumped", {
|
|
168385
168448
|
label,
|
|
@@ -168502,7 +168565,7 @@ function insertCompartmentEvents(db, sessionId, events, compartmentIds) {
|
|
|
168502
168565
|
var init_compartment_events = () => {};
|
|
168503
168566
|
|
|
168504
168567
|
// src/hooks/magic-context/historian-state-file.ts
|
|
168505
|
-
import { mkdirSync as
|
|
168568
|
+
import { mkdirSync as mkdirSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
168506
168569
|
function cleanupHistorianStateFile(path6) {
|
|
168507
168570
|
if (!path6)
|
|
168508
168571
|
return;
|
|
@@ -168840,7 +168903,7 @@ var init_decay_render = __esm(() => {
|
|
|
168840
168903
|
|
|
168841
168904
|
// src/hooks/magic-context/key-files-block.ts
|
|
168842
168905
|
import { readFileSync as readFileSync10, realpathSync as realpathSync4 } from "node:fs";
|
|
168843
|
-
import { join as
|
|
168906
|
+
import { join as join17, sep as sep2 } from "node:path";
|
|
168844
168907
|
function staleKey(update) {
|
|
168845
168908
|
return `${update.projectPath}\x00${update.path}\x00${update.generatedAtWitness}\x00${update.staleReason}`;
|
|
168846
168909
|
}
|
|
@@ -168895,7 +168958,7 @@ function buildKeyFilesBlock(db, projectPath, config2 = { enabled: true, tokenBud
|
|
|
168895
168958
|
let nextStale = null;
|
|
168896
168959
|
let observed = false;
|
|
168897
168960
|
try {
|
|
168898
|
-
const absPath =
|
|
168961
|
+
const absPath = join17(projectPath, row.path);
|
|
168899
168962
|
const real = realpathSync4(absPath);
|
|
168900
168963
|
if (!isUnderResolvedRoot(projectRoot, real)) {
|
|
168901
168964
|
nextStale = "missing";
|
|
@@ -170560,29 +170623,12 @@ function resolveHistorianContextLimit(historianModelOverride) {
|
|
|
170560
170623
|
return DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
|
|
170561
170624
|
}
|
|
170562
170625
|
if (typeof historianModelOverride === "string" && historianModelOverride.trim() !== "") {
|
|
170563
|
-
console.warn(`[magic-context] historian.model "${historianModelOverride}" lacks provider prefix ("provider/model-id"); using
|
|
170626
|
+
console.warn(`[magic-context] historian.model "${historianModelOverride}" lacks provider prefix ("provider/model-id"); using the default context limit for chunk-budget derivation.`);
|
|
170564
170627
|
}
|
|
170565
|
-
|
|
170566
|
-
if (!chain || chain.length === 0)
|
|
170567
|
-
return DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
|
|
170568
|
-
const expanded = expandFallbackChain(chain);
|
|
170569
|
-
let minLimit;
|
|
170570
|
-
for (const key of expanded) {
|
|
170571
|
-
const [providerID, ...rest] = key.split("/");
|
|
170572
|
-
const modelID = rest.join("/");
|
|
170573
|
-
if (!providerID || !modelID)
|
|
170574
|
-
continue;
|
|
170575
|
-
const limit = getSdkContextLimit(providerID, modelID);
|
|
170576
|
-
if (typeof limit !== "number" || limit <= 0)
|
|
170577
|
-
continue;
|
|
170578
|
-
if (minLimit === undefined || limit < minLimit)
|
|
170579
|
-
minLimit = limit;
|
|
170580
|
-
}
|
|
170581
|
-
return minLimit ?? DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
|
|
170628
|
+
return DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
|
|
170582
170629
|
}
|
|
170583
170630
|
var TRIGGER_BUDGET_PERCENTAGE = 0.05, TRIGGER_BUDGET_MIN = 5000, TRIGGER_BUDGET_MAX = 50000, HISTORIAN_CHUNK_PERCENTAGE = 0.25, HISTORIAN_CHUNK_MIN = 8000, HISTORIAN_CHUNK_MAX = 50000, DEFAULT_HISTORIAN_CONTEXT_FALLBACK = 128000;
|
|
170584
170631
|
var init_derive_budgets = __esm(() => {
|
|
170585
|
-
init_model_requirements();
|
|
170586
170632
|
init_models_dev_cache();
|
|
170587
170633
|
});
|
|
170588
170634
|
|
|
@@ -170903,7 +170949,7 @@ function buildToolArcs(messages) {
|
|
|
170903
170949
|
}
|
|
170904
170950
|
return arcs.sort((a, b) => a.invOrdinal - b.invOrdinal || (a.resOrdinal ?? Number.MAX_SAFE_INTEGER) - (b.resOrdinal ?? Number.MAX_SAFE_INTEGER));
|
|
170905
170951
|
}
|
|
170906
|
-
function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal) {
|
|
170952
|
+
function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal, recentOpenArcCutoff) {
|
|
170907
170953
|
let boundary = candidate;
|
|
170908
170954
|
for (const arc of arcs) {
|
|
170909
170955
|
if (arc.resOrdinal !== null) {
|
|
@@ -170912,6 +170958,8 @@ function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal) {
|
|
|
170912
170958
|
}
|
|
170913
170959
|
continue;
|
|
170914
170960
|
}
|
|
170961
|
+
if (arc.invOrdinal < recentOpenArcCutoff)
|
|
170962
|
+
continue;
|
|
170915
170963
|
if (arc.invOrdinal >= lastCompartmentEndOrdinal + 1 && arc.invOrdinal < boundary) {
|
|
170916
170964
|
return arc.invOrdinal;
|
|
170917
170965
|
}
|
|
@@ -171151,7 +171199,7 @@ function semanticSnapBoundary(args) {
|
|
|
171151
171199
|
return snapped;
|
|
171152
171200
|
}
|
|
171153
171201
|
function applyHeadCap(args) {
|
|
171154
|
-
const { index, protectedTailStart, offset, arcs, capTokens } = args;
|
|
171202
|
+
const { index, protectedTailStart, offset, arcs, capTokens, recentOpenArcCutoff } = args;
|
|
171155
171203
|
if (offset >= protectedTailStart)
|
|
171156
171204
|
return { eligibleEndOrdinal: offset, oversizeAtomicUnit: false };
|
|
171157
171205
|
let end = index.findHeadEndForCap(offset, protectedTailStart, capTokens);
|
|
@@ -171159,7 +171207,7 @@ function applyHeadCap(args) {
|
|
|
171159
171207
|
for (const arc of arcs) {
|
|
171160
171208
|
const resOrdinal = arc.resOrdinal;
|
|
171161
171209
|
if (resOrdinal === null) {
|
|
171162
|
-
if (arc.invOrdinal >= offset && arc.invOrdinal < end) {
|
|
171210
|
+
if (arc.invOrdinal >= recentOpenArcCutoff && arc.invOrdinal >= offset && arc.invOrdinal < end) {
|
|
171163
171211
|
end = Math.min(end, arc.invOrdinal);
|
|
171164
171212
|
}
|
|
171165
171213
|
continue;
|
|
@@ -171226,7 +171274,14 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171226
171274
|
}
|
|
171227
171275
|
if (ctx.mode === "manual-full-recomp") {
|
|
171228
171276
|
const arcs2 = buildToolArcs(messages);
|
|
171229
|
-
const
|
|
171277
|
+
const recompTarget = deriveProtectedTailTokenTarget({
|
|
171278
|
+
contextLimit: ctx.contextLimit,
|
|
171279
|
+
executeThresholdPercentage: ctx.executeThresholdPercentage,
|
|
171280
|
+
usagePercentage: 0,
|
|
171281
|
+
triggerBudget: ctx.triggerBudget
|
|
171282
|
+
});
|
|
171283
|
+
const recentOpenArcCutoff2 = index.findSuffixStartForTokens(recompTarget.N);
|
|
171284
|
+
const firstOpenArc = arcs2.find((arc) => arc.resOrdinal === null && arc.invOrdinal >= offset && arc.invOrdinal >= recentOpenArcCutoff2);
|
|
171230
171285
|
const protectedTailStart2 = firstOpenArc?.invOrdinal ?? rawMessageCount + 1;
|
|
171231
171286
|
const rawRangeFingerprint2 = computeRawRangeFingerprint(messages, offset, protectedTailStart2);
|
|
171232
171287
|
return {
|
|
@@ -171268,13 +171323,14 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171268
171323
|
const scaledN = ctx.emergencyTailScale ? Math.max(1, Math.floor(target.N * ctx.emergencyTailScale)) : target.N;
|
|
171269
171324
|
const arcs = buildToolArcs(messages);
|
|
171270
171325
|
let boundary = index.findSuffixStartForTokens(scaledN);
|
|
171326
|
+
const recentOpenArcCutoff = boundary;
|
|
171271
171327
|
let boundaryReason = boundary === 1 ? "whole-session-smaller-than-tail" : "size-walk";
|
|
171272
171328
|
const tokenAtBoundary = index.tokenForOrdinal(boundary);
|
|
171273
171329
|
if (boundary <= rawMessageCount && tokenAtBoundary > Math.max(2 * scaledN, 64000) && boundary < rawMessageCount) {
|
|
171274
171330
|
boundary += 1;
|
|
171275
171331
|
boundaryReason = "huge-message-exception";
|
|
171276
171332
|
}
|
|
171277
|
-
boundary = fenceBoundaryForToolArcs(boundary, arcs, ctx.lastCompartmentEndOrdinal);
|
|
171333
|
+
boundary = fenceBoundaryForToolArcs(boundary, arcs, ctx.lastCompartmentEndOrdinal, recentOpenArcCutoff);
|
|
171278
171334
|
const snapped = semanticSnapBoundary({
|
|
171279
171335
|
messages,
|
|
171280
171336
|
index,
|
|
@@ -171284,7 +171340,7 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171284
171340
|
});
|
|
171285
171341
|
if (snapped !== boundary)
|
|
171286
171342
|
boundaryReason = "semantic-snap";
|
|
171287
|
-
boundary = fenceBoundaryForToolArcs(snapped, arcs, ctx.lastCompartmentEndOrdinal);
|
|
171343
|
+
boundary = fenceBoundaryForToolArcs(snapped, arcs, ctx.lastCompartmentEndOrdinal, recentOpenArcCutoff);
|
|
171288
171344
|
let runtimeFloor = offset;
|
|
171289
171345
|
if (ctx.migrationFloorActive)
|
|
171290
171346
|
runtimeFloor = Math.max(runtimeFloor, ctx.priorBoundaryOrdinal);
|
|
@@ -171320,7 +171376,8 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
171320
171376
|
offset,
|
|
171321
171377
|
arcs,
|
|
171322
171378
|
lastCompartmentEndOrdinal: ctx.lastCompartmentEndOrdinal,
|
|
171323
|
-
capTokens: perRunCap
|
|
171379
|
+
capTokens: perRunCap,
|
|
171380
|
+
recentOpenArcCutoff
|
|
171324
171381
|
});
|
|
171325
171382
|
const rawRangeFingerprint = computeRawRangeFingerprint(messages, offset, head.eligibleEndOrdinal);
|
|
171326
171383
|
return {
|
|
@@ -171371,7 +171428,7 @@ function resolveBoundaryContext(args) {
|
|
|
171371
171428
|
}
|
|
171372
171429
|
let storedTokenTotals;
|
|
171373
171430
|
try {
|
|
171374
|
-
storedTokenTotals = getAllStatusTagTokenTotalsFlat(args.db, args.sessionId).totals;
|
|
171431
|
+
storedTokenTotals = getAllStatusTagTokenTotalsFlat(args.db, args.sessionId, args.taggerFloor ?? 0).totals;
|
|
171375
171432
|
} catch (error51) {
|
|
171376
171433
|
sessionLog(args.sessionId, "protected-tail stored-token map unavailable (live fallback):", error51);
|
|
171377
171434
|
}
|
|
@@ -173575,6 +173632,7 @@ async function runCompartmentAgent(deps) {
|
|
|
173575
173632
|
const count = recordHighPressureNoEligibleHead(db, boundarySnapshot);
|
|
173576
173633
|
sessionLog(sessionId, `historian high-pressure no-op: recovery remains armed (noEligibleHeadCount=${count})`);
|
|
173577
173634
|
}
|
|
173635
|
+
clearEmergencyDrainLatch(db, sessionId);
|
|
173578
173636
|
telemetry.status = "noop";
|
|
173579
173637
|
telemetry.failureReason = "nothing to compact before protected tail";
|
|
173580
173638
|
rollbackDrainReservation();
|
|
@@ -173589,7 +173647,8 @@ async function runCompartmentAgent(deps) {
|
|
|
173589
173647
|
trueRawTokens: boundarySnapshot.trueRawEligibleTokens,
|
|
173590
173648
|
usagePercentage: boundarySnapshot.usagePercentage,
|
|
173591
173649
|
usable,
|
|
173592
|
-
perRunCap
|
|
173650
|
+
perRunCap,
|
|
173651
|
+
executeThresholdPercentage: boundarySnapshot.executeThresholdPercentage
|
|
173593
173652
|
});
|
|
173594
173653
|
if (!reserve.ok) {
|
|
173595
173654
|
sessionLog(sessionId, `historian rate-limit skip: ${reserve.skippedReason ?? "quota exhausted"}`);
|
|
@@ -173608,6 +173667,7 @@ async function runCompartmentAgent(deps) {
|
|
|
173608
173667
|
} else {
|
|
173609
173668
|
recordHighPressureNoEligibleHead(db, boundarySnapshot);
|
|
173610
173669
|
}
|
|
173670
|
+
clearEmergencyDrainLatch(db, sessionId);
|
|
173611
173671
|
telemetry.status = "noop";
|
|
173612
173672
|
telemetry.failureReason = "chunk empty after filtering";
|
|
173613
173673
|
rollbackDrainReservation();
|
|
@@ -173715,6 +173775,7 @@ ${chunkText}`,
|
|
|
173715
173775
|
}
|
|
173716
173776
|
appendCompartments(db, sessionId, persistedCompartments);
|
|
173717
173777
|
clearHistorianFailureState(db, sessionId);
|
|
173778
|
+
clearHistorianDrainFailure(db, sessionId);
|
|
173718
173779
|
recordProtectedTailPublicationFloor(db, sessionId, lastCompartmentEnd + 1);
|
|
173719
173780
|
clearEmergencyRecovery(db, sessionId);
|
|
173720
173781
|
drainReservation = null;
|
|
@@ -173818,8 +173879,11 @@ ${chunkText}`,
|
|
|
173818
173879
|
}
|
|
173819
173880
|
} finally {
|
|
173820
173881
|
if (!completedSuccessfully) {
|
|
173821
|
-
if (!retainDrainReservationForRetryThrottle)
|
|
173882
|
+
if (!retainDrainReservationForRetryThrottle) {
|
|
173822
173883
|
rollbackDrainReservation();
|
|
173884
|
+
} else {
|
|
173885
|
+
recordHistorianDrainFailure(db, sessionId);
|
|
173886
|
+
}
|
|
173823
173887
|
updateSessionMeta(db, sessionId, { compartmentInProgress: false });
|
|
173824
173888
|
}
|
|
173825
173889
|
recordTelemetry();
|
|
@@ -176033,15 +176097,15 @@ var require_windows = __commonJS((exports, module) => {
|
|
|
176033
176097
|
}
|
|
176034
176098
|
return false;
|
|
176035
176099
|
}
|
|
176036
|
-
function checkStat(
|
|
176037
|
-
if (!
|
|
176100
|
+
function checkStat(stat, path6, options) {
|
|
176101
|
+
if (!stat.isSymbolicLink() && !stat.isFile()) {
|
|
176038
176102
|
return false;
|
|
176039
176103
|
}
|
|
176040
176104
|
return checkPathExt(path6, options);
|
|
176041
176105
|
}
|
|
176042
176106
|
function isexe(path6, options, cb) {
|
|
176043
|
-
fs2.stat(path6, function(er,
|
|
176044
|
-
cb(er, er ? false : checkStat(
|
|
176107
|
+
fs2.stat(path6, function(er, stat) {
|
|
176108
|
+
cb(er, er ? false : checkStat(stat, path6, options));
|
|
176045
176109
|
});
|
|
176046
176110
|
}
|
|
176047
176111
|
function sync(path6, options) {
|
|
@@ -176055,20 +176119,20 @@ var require_mode = __commonJS((exports, module) => {
|
|
|
176055
176119
|
isexe.sync = sync;
|
|
176056
176120
|
var fs2 = __require("fs");
|
|
176057
176121
|
function isexe(path6, options, cb) {
|
|
176058
|
-
fs2.stat(path6, function(er,
|
|
176059
|
-
cb(er, er ? false : checkStat(
|
|
176122
|
+
fs2.stat(path6, function(er, stat) {
|
|
176123
|
+
cb(er, er ? false : checkStat(stat, options));
|
|
176060
176124
|
});
|
|
176061
176125
|
}
|
|
176062
176126
|
function sync(path6, options) {
|
|
176063
176127
|
return checkStat(fs2.statSync(path6), options);
|
|
176064
176128
|
}
|
|
176065
|
-
function checkStat(
|
|
176066
|
-
return
|
|
176129
|
+
function checkStat(stat, options) {
|
|
176130
|
+
return stat.isFile() && checkMode(stat, options);
|
|
176067
176131
|
}
|
|
176068
|
-
function checkMode(
|
|
176069
|
-
var mod =
|
|
176070
|
-
var uid =
|
|
176071
|
-
var gid =
|
|
176132
|
+
function checkMode(stat, options) {
|
|
176133
|
+
var mod = stat.mode;
|
|
176134
|
+
var uid = stat.uid;
|
|
176135
|
+
var gid = stat.gid;
|
|
176072
176136
|
var myUid = options.uid !== undefined ? options.uid : process.getuid && process.getuid();
|
|
176073
176137
|
var myGid = options.gid !== undefined ? options.gid : process.getgid && process.getgid();
|
|
176074
176138
|
var u = parseInt("100", 8);
|
|
@@ -176933,7 +176997,6 @@ var init_memory_migration = __esm(async () => {
|
|
|
176933
176997
|
init_shared();
|
|
176934
176998
|
init_assistant_message_extractor();
|
|
176935
176999
|
init_logger();
|
|
176936
|
-
init_resolve_fallbacks();
|
|
176937
177000
|
init_project_identity();
|
|
176938
177001
|
init_storage_memory();
|
|
176939
177002
|
await init_storage();
|
|
@@ -177249,17 +177312,20 @@ function shouldShowAnnouncement() {
|
|
|
177249
177312
|
}
|
|
177250
177313
|
return state.version !== ANNOUNCEMENT_VERSION;
|
|
177251
177314
|
}
|
|
177252
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
177315
|
+
var ANNOUNCEMENT_VERSION = "0.26.0", ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU", STATE_FILENAME = "last_announced_version";
|
|
177253
177316
|
var init_announcement = __esm(() => {
|
|
177254
177317
|
init_data_path();
|
|
177255
177318
|
ANNOUNCEMENT_FEATURES = [
|
|
177256
|
-
"
|
|
177257
|
-
"
|
|
177258
|
-
"
|
|
177259
|
-
"
|
|
177260
|
-
"
|
|
177319
|
+
"Faster on large sessions: per-message transform overhead is at least 2x lower on typical passes and up to ~10x lower when history summarization fires (no more multi-second pause on big sessions).",
|
|
177320
|
+
"No more surprise models: the built-in fallback chain is gone. Hidden agents only use the model (and fallback_models) you configure — no confusing 'model not found' for providers you never set up. `doctor` now records every historian run so real failures are visible.",
|
|
177321
|
+
"Anthropic thinking-block fix: clearing old reasoning no longer risks a stale-signature rejection on Claude / Bedrock / proxied-Claude routes. Plus fewer prompt-cache busts.",
|
|
177322
|
+
"Community fixes: TUI crash on the upgrade progress panel (#168), historian.disallowed_tools for weak models that loop on tool calls (#166), and a Pi-only config key leak (#167).",
|
|
177323
|
+
"New: doctor migrate-session re-homes a session (and optionally its memories) to another project, with a dry-run preview."
|
|
177261
177324
|
];
|
|
177262
177325
|
});
|
|
177326
|
+
|
|
177327
|
+
// src/agents/dreamer.ts
|
|
177328
|
+
var DREAMER_AGENT = "dreamer";
|
|
177263
177329
|
// src/agents/permissions.ts
|
|
177264
177330
|
function buildAllowOnlyPermission(allowedTools) {
|
|
177265
177331
|
const permission = { "*": "deny" };
|
|
@@ -177269,6 +177335,11 @@ function buildAllowOnlyPermission(allowedTools) {
|
|
|
177269
177335
|
return permission;
|
|
177270
177336
|
}
|
|
177271
177337
|
var HISTORIAN_ALLOWED_TOOLS = ["read", "aft_outline", "aft_zoom", "aft_search"];
|
|
177338
|
+
function applyDisallowedTools(defaults, disallowed) {
|
|
177339
|
+
if (disallowed.includes("*"))
|
|
177340
|
+
return [];
|
|
177341
|
+
return defaults.filter((t) => !disallowed.includes(t));
|
|
177342
|
+
}
|
|
177272
177343
|
var DREAMER_ALLOWED_TOOLS = [
|
|
177273
177344
|
"read",
|
|
177274
177345
|
"grep",
|
|
@@ -177284,6 +177355,10 @@ var DREAMER_ALLOWED_TOOLS = [
|
|
|
177284
177355
|
"ctx_note"
|
|
177285
177356
|
];
|
|
177286
177357
|
var SIDEKICK_ALLOWED_TOOLS = ["ctx_search", "aft_outline", "aft_zoom"];
|
|
177358
|
+
|
|
177359
|
+
// src/agents/sidekick.ts
|
|
177360
|
+
var SIDEKICK_AGENT = "sidekick";
|
|
177361
|
+
|
|
177287
177362
|
// src/config/index.ts
|
|
177288
177363
|
init_jsonc_parser();
|
|
177289
177364
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
@@ -177986,9 +178061,9 @@ function getMagicContextBuiltinCommands() {
|
|
|
177986
178061
|
template: "ctx-dream",
|
|
177987
178062
|
description: "Run the hidden dreamer maintenance pass for this project now"
|
|
177988
178063
|
},
|
|
177989
|
-
"ctx-embed
|
|
177990
|
-
template: "ctx-embed
|
|
177991
|
-
description: "
|
|
178064
|
+
"ctx-embed": {
|
|
178065
|
+
template: "ctx-embed",
|
|
178066
|
+
description: "Embedding status, or start/pause history compartment embedding (start | pause)"
|
|
177992
178067
|
}
|
|
177993
178068
|
};
|
|
177994
178069
|
}
|
|
@@ -178237,6 +178312,7 @@ ${modeIntro}
|
|
|
178237
178312
|
4. **Write or update** using the Write tool. Always write to project root, NOT to .planning/.
|
|
178238
178313
|
|
|
178239
178314
|
### Rules
|
|
178315
|
+
- **NEVER touch protected regions**: any content between \`<!-- mc:protected START ... -->\` and \`<!-- mc:protected END -->\` is hand-authored and cache-critical. Reproduce it BYTE-FOR-BYTE in your rewrite — do not edit, reword, reorder, summarize, trim, or drop a single line of it, and keep the marker comments themselves. Only a human edits that region.
|
|
178240
178316
|
- **Be prescriptive**: "Use X pattern" not "X pattern is used"
|
|
178241
178317
|
- **Always include file paths** in backticks
|
|
178242
178318
|
- **Write current state only**: no temporal language, no history
|
|
@@ -178373,7 +178449,6 @@ init_project_identity();
|
|
|
178373
178449
|
init_shared();
|
|
178374
178450
|
init_assistant_message_extractor();
|
|
178375
178451
|
init_logger();
|
|
178376
|
-
init_resolve_fallbacks();
|
|
178377
178452
|
init_subagent_token_capture();
|
|
178378
178453
|
await init_storage();
|
|
178379
178454
|
|
|
@@ -178395,7 +178470,7 @@ function stripThinkingBlocks(text) {
|
|
|
178395
178470
|
|
|
178396
178471
|
// src/features/magic-context/sidekick/agent.ts
|
|
178397
178472
|
async function runSidekick(deps) {
|
|
178398
|
-
const fallbackModels = resolveFallbackChain(
|
|
178473
|
+
const fallbackModels = resolveFallbackChain(deps.config.fallback_models);
|
|
178399
178474
|
let agentSessionId = null;
|
|
178400
178475
|
const startedAt = Date.now();
|
|
178401
178476
|
let invocationRecorded = false;
|
|
@@ -178485,6 +178560,11 @@ init_project_identity();
|
|
|
178485
178560
|
import { createHash as createHash6 } from "node:crypto";
|
|
178486
178561
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
178487
178562
|
import path5 from "node:path";
|
|
178563
|
+
|
|
178564
|
+
// src/features/magic-context/memory/relocate-memory.ts
|
|
178565
|
+
var memoryCopyColumnsCache = new WeakMap;
|
|
178566
|
+
|
|
178567
|
+
// src/features/magic-context/v22-deferred-backfill.ts
|
|
178488
178568
|
var BATCH_SIZE = 25;
|
|
178489
178569
|
var YIELD_EVERY_N_ROWS = 5;
|
|
178490
178570
|
var BACKFILL_META_KEY = "v22_legacy_memory_backfill";
|
|
@@ -178722,6 +178802,7 @@ function createLiveSessionState() {
|
|
|
178722
178802
|
|
|
178723
178803
|
// src/index.ts
|
|
178724
178804
|
init_conflict_warning_hook();
|
|
178805
|
+
|
|
178725
178806
|
// src/features/magic-context/dreamer/storage-dream-state.ts
|
|
178726
178807
|
var getDreamStateStatements = new WeakMap;
|
|
178727
178808
|
var setDreamStateStatements = new WeakMap;
|
|
@@ -178859,7 +178940,7 @@ function enqueueDream(db, projectIdentity, reason, force = false) {
|
|
|
178859
178940
|
return db.transaction(() => {
|
|
178860
178941
|
if (!hasActiveDreamLease(db)) {
|
|
178861
178942
|
const staleThresholdMs = force ? 2 * 60 * 1000 : 120 * 60 * 1000;
|
|
178862
|
-
db.prepare("DELETE FROM dream_queue WHERE project_path = ? AND started_at IS NOT NULL AND started_at < ?").run(
|
|
178943
|
+
db.prepare("DELETE FROM dream_queue WHERE project_path = ? AND started_at IS NOT NULL AND started_at < ?").run(projectIdentity, now - staleThresholdMs);
|
|
178863
178944
|
}
|
|
178864
178945
|
const existing = db.prepare("SELECT id FROM dream_queue WHERE project_path = ?").get(projectIdentity);
|
|
178865
178946
|
if (existing) {
|
|
@@ -178915,21 +178996,21 @@ function clearStaleEntries(db, maxAgeMs, projectIdentity) {
|
|
|
178915
178996
|
return result.changes;
|
|
178916
178997
|
}
|
|
178917
178998
|
// src/features/magic-context/dreamer/runner.ts
|
|
178999
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
179000
|
+
import { join as join12 } from "node:path";
|
|
178918
179001
|
init_shared();
|
|
178919
179002
|
init_assistant_message_extractor();
|
|
178920
179003
|
init_data_path();
|
|
178921
179004
|
init_logger();
|
|
178922
179005
|
await init_sqlite();
|
|
178923
|
-
import { existsSync as existsSync10 } from "node:fs";
|
|
178924
|
-
import { join as join12 } from "node:path";
|
|
178925
179006
|
|
|
178926
179007
|
// src/features/magic-context/key-files/identify-key-files.ts
|
|
179008
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
179009
|
+
import { isAbsolute as isAbsolute3, join as join11, relative as relative2 } from "node:path";
|
|
178927
179010
|
init_read_session_formatting();
|
|
178928
179011
|
init_shared();
|
|
178929
179012
|
init_assistant_message_extractor();
|
|
178930
179013
|
init_logger();
|
|
178931
|
-
import { readFileSync as readFileSync8 } from "node:fs";
|
|
178932
|
-
import { isAbsolute as isAbsolute3, join as join11, relative as relative2 } from "node:path";
|
|
178933
179014
|
init_subagent_token_capture();
|
|
178934
179015
|
init_aft_availability();
|
|
178935
179016
|
init_project_key_files();
|
|
@@ -180554,120 +180635,7 @@ ${body}` : subject;
|
|
|
180554
180635
|
init_logger();
|
|
180555
180636
|
init_embedding();
|
|
180556
180637
|
init_storage_git_commit_embeddings();
|
|
180557
|
-
|
|
180558
|
-
// src/features/magic-context/git-commits/storage-git-commits.ts
|
|
180559
|
-
init_logger();
|
|
180560
|
-
var insertStatements = new WeakMap;
|
|
180561
|
-
var existingShasStatements = new WeakMap;
|
|
180562
|
-
var projectCountStatements = new WeakMap;
|
|
180563
|
-
var evictStatements = new WeakMap;
|
|
180564
|
-
var evictOverflowStatements = new WeakMap;
|
|
180565
|
-
var latestCommitTimeStatements = new WeakMap;
|
|
180566
|
-
function getInsertStatement(db) {
|
|
180567
|
-
let stmt = insertStatements.get(db);
|
|
180568
|
-
if (!stmt) {
|
|
180569
|
-
stmt = db.prepare(`INSERT INTO git_commits (sha, project_path, short_sha, message, author, committed_at, indexed_at)
|
|
180570
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
180571
|
-
ON CONFLICT(sha) DO UPDATE SET
|
|
180572
|
-
project_path = excluded.project_path,
|
|
180573
|
-
short_sha = excluded.short_sha,
|
|
180574
|
-
message = excluded.message,
|
|
180575
|
-
author = excluded.author,
|
|
180576
|
-
committed_at = excluded.committed_at,
|
|
180577
|
-
indexed_at = excluded.indexed_at
|
|
180578
|
-
WHERE git_commits.message != excluded.message`);
|
|
180579
|
-
insertStatements.set(db, stmt);
|
|
180580
|
-
}
|
|
180581
|
-
return stmt;
|
|
180582
|
-
}
|
|
180583
|
-
function getExistingShasStatement(db) {
|
|
180584
|
-
let stmt = existingShasStatements.get(db);
|
|
180585
|
-
if (!stmt) {
|
|
180586
|
-
stmt = db.prepare("SELECT sha FROM git_commits WHERE project_path = ?");
|
|
180587
|
-
existingShasStatements.set(db, stmt);
|
|
180588
|
-
}
|
|
180589
|
-
return stmt;
|
|
180590
|
-
}
|
|
180591
|
-
function getProjectCountStatement(db) {
|
|
180592
|
-
let stmt = projectCountStatements.get(db);
|
|
180593
|
-
if (!stmt) {
|
|
180594
|
-
stmt = db.prepare("SELECT COUNT(*) AS count FROM git_commits WHERE project_path = ?");
|
|
180595
|
-
projectCountStatements.set(db, stmt);
|
|
180596
|
-
}
|
|
180597
|
-
return stmt;
|
|
180598
|
-
}
|
|
180599
|
-
function getLatestCommitTimeStatement(db) {
|
|
180600
|
-
let stmt = latestCommitTimeStatements.get(db);
|
|
180601
|
-
if (!stmt) {
|
|
180602
|
-
stmt = db.prepare("SELECT MAX(committed_at) AS latest FROM git_commits WHERE project_path = ?");
|
|
180603
|
-
latestCommitTimeStatements.set(db, stmt);
|
|
180604
|
-
}
|
|
180605
|
-
return stmt;
|
|
180606
|
-
}
|
|
180607
|
-
function getEvictOverflowStatement(db) {
|
|
180608
|
-
let stmt = evictOverflowStatements.get(db);
|
|
180609
|
-
if (!stmt) {
|
|
180610
|
-
stmt = db.prepare(`DELETE FROM git_commits
|
|
180611
|
-
WHERE rowid IN (
|
|
180612
|
-
SELECT rowid FROM git_commits
|
|
180613
|
-
WHERE project_path = ?
|
|
180614
|
-
ORDER BY committed_at DESC, sha DESC
|
|
180615
|
-
LIMIT -1 OFFSET ?
|
|
180616
|
-
)`);
|
|
180617
|
-
evictOverflowStatements.set(db, stmt);
|
|
180618
|
-
}
|
|
180619
|
-
return stmt;
|
|
180620
|
-
}
|
|
180621
|
-
function upsertCommits(db, projectPath, commits) {
|
|
180622
|
-
if (commits.length === 0)
|
|
180623
|
-
return { inserted: 0, updated: 0 };
|
|
180624
|
-
const existing = new Set;
|
|
180625
|
-
for (const row of getExistingShasStatement(db).all(projectPath)) {
|
|
180626
|
-
existing.add(row.sha);
|
|
180627
|
-
}
|
|
180628
|
-
let inserted = 0;
|
|
180629
|
-
let updated = 0;
|
|
180630
|
-
const now = Date.now();
|
|
180631
|
-
const insertStmt = getInsertStatement(db);
|
|
180632
|
-
db.transaction(() => {
|
|
180633
|
-
for (const commit of commits) {
|
|
180634
|
-
const result = insertStmt.run(commit.sha, projectPath, commit.shortSha, commit.message, commit.author, commit.committedAtMs, now);
|
|
180635
|
-
if (result.changes > 0) {
|
|
180636
|
-
if (existing.has(commit.sha)) {
|
|
180637
|
-
updated++;
|
|
180638
|
-
} else {
|
|
180639
|
-
inserted++;
|
|
180640
|
-
existing.add(commit.sha);
|
|
180641
|
-
}
|
|
180642
|
-
}
|
|
180643
|
-
}
|
|
180644
|
-
})();
|
|
180645
|
-
return { inserted, updated };
|
|
180646
|
-
}
|
|
180647
|
-
function getCommitCount(db, projectPath) {
|
|
180648
|
-
const row = getProjectCountStatement(db).get(projectPath);
|
|
180649
|
-
return row?.count ?? 0;
|
|
180650
|
-
}
|
|
180651
|
-
function getLatestIndexedCommitTimeMs(db, projectPath) {
|
|
180652
|
-
const row = getLatestCommitTimeStatement(db).get(projectPath);
|
|
180653
|
-
return row?.latest ?? null;
|
|
180654
|
-
}
|
|
180655
|
-
function enforceProjectCap(db, projectPath, maxCommits) {
|
|
180656
|
-
if (maxCommits <= 0)
|
|
180657
|
-
return 0;
|
|
180658
|
-
const count = getCommitCount(db, projectPath);
|
|
180659
|
-
if (count <= maxCommits)
|
|
180660
|
-
return 0;
|
|
180661
|
-
getEvictOverflowStatement(db).run(projectPath, maxCommits);
|
|
180662
|
-
const after = getCommitCount(db, projectPath);
|
|
180663
|
-
const evicted = Math.max(0, count - after);
|
|
180664
|
-
if (evicted > 0) {
|
|
180665
|
-
log(`[git-commits] evicted ${evicted} oldest commits for project ${projectPath} (cap=${maxCommits}, was=${count})`);
|
|
180666
|
-
}
|
|
180667
|
-
return evicted;
|
|
180668
|
-
}
|
|
180669
|
-
|
|
180670
|
-
// src/features/magic-context/git-commits/indexer.ts
|
|
180638
|
+
init_storage_git_commits();
|
|
180671
180639
|
var MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
180672
180640
|
var EMBED_BATCH_SIZE = 16;
|
|
180673
180641
|
var EMBED_MAX_PER_SWEEP = 500;
|
|
@@ -180905,12 +180873,12 @@ function searchGitCommitsSync(db, projectPath, query, options) {
|
|
|
180905
180873
|
|
|
180906
180874
|
// src/features/magic-context/git-commits/index.ts
|
|
180907
180875
|
init_storage_git_commit_embeddings();
|
|
180876
|
+
init_storage_git_commits();
|
|
180908
180877
|
init_sweep_coordinator();
|
|
180909
180878
|
|
|
180910
180879
|
// src/plugin/dream-timer.ts
|
|
180911
180880
|
init_embedding();
|
|
180912
180881
|
init_logger();
|
|
180913
|
-
init_resolve_fallbacks();
|
|
180914
180882
|
await init_storage();
|
|
180915
180883
|
var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
|
|
180916
180884
|
var activeTimer = null;
|
|
@@ -181013,7 +180981,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled = getProjectEmbedd
|
|
|
181013
180981
|
experimentalPinKeyFiles: reg.experimentalPinKeyFiles,
|
|
181014
180982
|
projectIdentity: reg.projectIdentity,
|
|
181015
180983
|
sessionDirectoryOverride: reg.directory,
|
|
181016
|
-
fallbackModels: resolveFallbackChain(
|
|
180984
|
+
fallbackModels: resolveFallbackChain(reg.dreamerConfig.fallback_models)
|
|
181017
180985
|
});
|
|
181018
180986
|
} catch (error51) {
|
|
181019
180987
|
log(`[dreamer] timer-triggered queue processing failed for ${reg.projectIdentity}:`, error51);
|
|
@@ -181462,10 +181430,9 @@ function makeToolCompositeKey(ownerMsgId, callId) {
|
|
|
181462
181430
|
}
|
|
181463
181431
|
var GET_COUNTER_SQL = `SELECT counter FROM session_meta WHERE session_id = ?`;
|
|
181464
181432
|
var GET_ASSIGNMENTS_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id FROM tags WHERE session_id = ? ORDER BY tag_number ASC";
|
|
181433
|
+
var GET_ASSIGNMENTS_SCOPED_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id FROM tags WHERE session_id = ? AND tag_number >= ? ORDER BY tag_number ASC";
|
|
181465
181434
|
var PROBE_DATA_VERSION_SQL = "PRAGMA main.data_version";
|
|
181466
|
-
var PROBE_TOTAL_CHANGES_SQL = "SELECT total_changes() AS tc";
|
|
181467
181435
|
var probeDataVersionStatements = new WeakMap;
|
|
181468
|
-
var probeTotalChangesStatements = new WeakMap;
|
|
181469
181436
|
function getProbeDataVersionStatement(db) {
|
|
181470
181437
|
let stmt = probeDataVersionStatements.get(db);
|
|
181471
181438
|
if (!stmt) {
|
|
@@ -181474,14 +181441,6 @@ function getProbeDataVersionStatement(db) {
|
|
|
181474
181441
|
}
|
|
181475
181442
|
return stmt;
|
|
181476
181443
|
}
|
|
181477
|
-
function getProbeTotalChangesStatement(db) {
|
|
181478
|
-
let stmt = probeTotalChangesStatements.get(db);
|
|
181479
|
-
if (!stmt) {
|
|
181480
|
-
stmt = db.prepare(PROBE_TOTAL_CHANGES_SQL);
|
|
181481
|
-
probeTotalChangesStatements.set(db, stmt);
|
|
181482
|
-
}
|
|
181483
|
-
return stmt;
|
|
181484
|
-
}
|
|
181485
181444
|
function isAssignmentRow(row) {
|
|
181486
181445
|
if (row === null || typeof row !== "object") {
|
|
181487
181446
|
return false;
|
|
@@ -181674,20 +181633,18 @@ function createTagger() {
|
|
|
181674
181633
|
}
|
|
181675
181634
|
function probeSignature(db) {
|
|
181676
181635
|
const dvRow = getProbeDataVersionStatement(db).get();
|
|
181677
|
-
const tcRow = getProbeTotalChangesStatement(db).get();
|
|
181678
181636
|
return {
|
|
181679
|
-
dataVersion: dvRow?.data_version ?? 0
|
|
181680
|
-
totalChanges: tcRow?.tc ?? 0
|
|
181637
|
+
dataVersion: dvRow?.data_version ?? 0
|
|
181681
181638
|
};
|
|
181682
181639
|
}
|
|
181683
|
-
function initFromDb(sessionId, db) {
|
|
181640
|
+
function initFromDb(sessionId, db, floor = 0) {
|
|
181684
181641
|
const probe = probeSignature(db);
|
|
181685
181642
|
const cached2 = loadSignatures.get(sessionId);
|
|
181686
|
-
if (cached2 !== undefined && cached2.db === db && cached2.dataVersion === probe.dataVersion && cached2.
|
|
181643
|
+
if (cached2 !== undefined && cached2.db === db && cached2.dataVersion === probe.dataVersion && cached2.floor === floor) {
|
|
181687
181644
|
return;
|
|
181688
181645
|
}
|
|
181689
181646
|
const row = db.prepare(GET_COUNTER_SQL).get(sessionId);
|
|
181690
|
-
const assignmentRows = db.prepare(GET_ASSIGNMENTS_SQL).all(sessionId).filter(isAssignmentRow);
|
|
181647
|
+
const assignmentRows = (floor > 0 ? db.prepare(GET_ASSIGNMENTS_SCOPED_SQL).all(sessionId, floor) : db.prepare(GET_ASSIGNMENTS_SQL).all(sessionId)).filter(isAssignmentRow);
|
|
181691
181648
|
const sessionAssignments = getSessionAssignments(sessionId);
|
|
181692
181649
|
sessionAssignments.clear();
|
|
181693
181650
|
let maxTagNumber = 0;
|
|
@@ -181708,7 +181665,7 @@ function createTagger() {
|
|
|
181708
181665
|
loadSignatures.set(sessionId, {
|
|
181709
181666
|
db,
|
|
181710
181667
|
dataVersion: probe.dataVersion,
|
|
181711
|
-
|
|
181668
|
+
floor
|
|
181712
181669
|
});
|
|
181713
181670
|
}
|
|
181714
181671
|
function cleanup(sessionId) {
|
|
@@ -181731,13 +181688,13 @@ function createTagger() {
|
|
|
181731
181688
|
cleanup
|
|
181732
181689
|
};
|
|
181733
181690
|
}
|
|
181691
|
+
|
|
181734
181692
|
// src/hooks/magic-context/hook.ts
|
|
181735
181693
|
init_magic_context();
|
|
181736
181694
|
init_project_identity();
|
|
181737
181695
|
init_project_embedding_registry();
|
|
181738
181696
|
await init_storage();
|
|
181739
181697
|
init_logger();
|
|
181740
|
-
init_resolve_fallbacks();
|
|
181741
181698
|
init_rpc_notifications();
|
|
181742
181699
|
|
|
181743
181700
|
// src/hooks/magic-context/command-handler.ts
|
|
@@ -181788,6 +181745,7 @@ await __promiseAll([
|
|
|
181788
181745
|
// src/hooks/magic-context/compartment-trigger.ts
|
|
181789
181746
|
init_compartment_storage();
|
|
181790
181747
|
init_logger();
|
|
181748
|
+
init_read_session_true_raw_tokens();
|
|
181791
181749
|
await __promiseAll([
|
|
181792
181750
|
init_storage(),
|
|
181793
181751
|
init_protected_tail_boundary(),
|
|
@@ -181802,6 +181760,38 @@ var TAIL_SIZE_TRIGGER_MULTIPLIER = 3;
|
|
|
181802
181760
|
var FORCE_COMPARTMENT_PERCENTAGE = 80;
|
|
181803
181761
|
var BLOCK_UNTIL_DONE_PERCENTAGE = 95;
|
|
181804
181762
|
var FORCE_MATERIALIZE_PERCENTAGE = 85;
|
|
181763
|
+
var CONTENT_TAG_OWNER_SUFFIX = /:(?:p|file)\d+$/;
|
|
181764
|
+
function tagOwnerMessageId(row) {
|
|
181765
|
+
if (row.type === "tool")
|
|
181766
|
+
return row.tool_owner_message_id ?? row.message_id;
|
|
181767
|
+
return row.message_id.replace(CONTENT_TAG_OWNER_SUFFIX, "");
|
|
181768
|
+
}
|
|
181769
|
+
function getActiveOrDroppedTagOwnerMessageIds(db, sessionId, floor = 0) {
|
|
181770
|
+
const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id
|
|
181771
|
+
FROM tags
|
|
181772
|
+
WHERE session_id = ? AND status IN ('active', 'dropped') AND tag_number >= ?`).all(sessionId, floor) : db.prepare(`SELECT type, message_id, tool_owner_message_id
|
|
181773
|
+
FROM tags
|
|
181774
|
+
WHERE session_id = ? AND status IN ('active', 'dropped')`).all(sessionId);
|
|
181775
|
+
const owners = new Set;
|
|
181776
|
+
for (const row of rows)
|
|
181777
|
+
owners.add(tagOwnerMessageId(row));
|
|
181778
|
+
return owners;
|
|
181779
|
+
}
|
|
181780
|
+
function estimateUntaggedInMemoryTailUpperBound(db, sessionId, inMemoryTail, taggerFloor = 0) {
|
|
181781
|
+
const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
|
|
181782
|
+
const coveredOwnerMessageIds = getActiveOrDroppedTagOwnerMessageIds(db, sessionId, taggerFloor);
|
|
181783
|
+
let total = 0;
|
|
181784
|
+
for (const message of inMemoryTail.messages) {
|
|
181785
|
+
if (message.ordinal <= lastCompartmentEnd)
|
|
181786
|
+
continue;
|
|
181787
|
+
if (coveredOwnerMessageIds.has(message.id))
|
|
181788
|
+
continue;
|
|
181789
|
+
total += estimateTrueRawMessageTokens(message, {
|
|
181790
|
+
providerShapeVersion: "opencode-v1"
|
|
181791
|
+
}).total;
|
|
181792
|
+
}
|
|
181793
|
+
return total;
|
|
181794
|
+
}
|
|
181805
181795
|
function buildTriggerInMemoryTail(db, sessionId, messages) {
|
|
181806
181796
|
if (messages.length === 0)
|
|
181807
181797
|
return;
|
|
@@ -181873,7 +181863,7 @@ function resolveBoundaryContextLimit(usage, fallbackContextLimit) {
|
|
|
181873
181863
|
}
|
|
181874
181864
|
return 128000;
|
|
181875
181865
|
}
|
|
181876
|
-
function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail) {
|
|
181866
|
+
function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail, taggerFloor = 0) {
|
|
181877
181867
|
return withRawSessionMessageCache(() => {
|
|
181878
181868
|
try {
|
|
181879
181869
|
const memoryPrimed = inMemoryTail ? primeInMemoryTailRawMessageCache({
|
|
@@ -181902,7 +181892,8 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
|
|
|
181902
181892
|
contextLimit: resolveBoundaryContextLimit(usage, contextLimit),
|
|
181903
181893
|
executeThresholdPercentage,
|
|
181904
181894
|
usage,
|
|
181905
|
-
usageSource: "live"
|
|
181895
|
+
usageSource: "live",
|
|
181896
|
+
taggerFloor
|
|
181906
181897
|
});
|
|
181907
181898
|
const hasProtectedEligibleHead = boundary.offset < boundary.protectedTailStart;
|
|
181908
181899
|
if (!hasProtectedEligibleHead) {
|
|
@@ -181933,7 +181924,7 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
|
|
|
181933
181924
|
}
|
|
181934
181925
|
});
|
|
181935
181926
|
}
|
|
181936
|
-
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, clearReasoningAge, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail) {
|
|
181927
|
+
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, clearReasoningAge, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride) {
|
|
181937
181928
|
if (sessionMeta.compartmentInProgress) {
|
|
181938
181929
|
sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
|
|
181939
181930
|
return { shouldFire: false };
|
|
@@ -181947,14 +181938,17 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
181947
181938
|
inMemoryTail = undefined;
|
|
181948
181939
|
}
|
|
181949
181940
|
}
|
|
181941
|
+
const taggerFloor = taggerFloorOverride !== undefined && taggerFloorOverride > 0 ? taggerFloorOverride : inMemoryTail ? deriveTagLoadFloor(db, sessionId, inMemoryTail.messages.map((m) => m.id)) : 0;
|
|
181950
181942
|
const proactiveFloorForGate = getProactiveCompartmentTriggerPercentage(executeThresholdPercentage);
|
|
181951
|
-
if (
|
|
181943
|
+
if (usage.percentage < proactiveFloorForGate) {
|
|
181952
181944
|
try {
|
|
181953
|
-
const { bound, nullCount } = getTriggerTagTokenUpperBound(db, sessionId);
|
|
181945
|
+
const { bound: persistedBound, nullCount } = getTriggerTagTokenUpperBound(db, sessionId, taggerFloor);
|
|
181954
181946
|
if (nullCount === 0) {
|
|
181955
|
-
const
|
|
181947
|
+
const untaggedUpperBound = inMemoryTail ? estimateUntaggedInMemoryTailUpperBound(db, sessionId, inMemoryTail, taggerFloor) : 0;
|
|
181948
|
+
const eligibleUpperBound = persistedBound + untaggedUpperBound;
|
|
181956
181949
|
if (eligibleUpperBound < triggerBudget) {
|
|
181957
|
-
|
|
181950
|
+
const memorySuffix = inMemoryTail ? ` (persisted=${persistedBound}, untagged-memory≤${untaggedUpperBound})` : "";
|
|
181951
|
+
sessionLog(sessionId, `compartment trigger: cheap-skip at ${usage.percentage.toFixed(1)}% (below proactive floor ${proactiveFloorForGate}%) — live-tail upper bound ${eligibleUpperBound}${memorySuffix} < triggerBudget ${triggerBudget}; no size trigger possible, skipped full raw read`);
|
|
181958
181952
|
return { shouldFire: false };
|
|
181959
181953
|
}
|
|
181960
181954
|
}
|
|
@@ -181962,7 +181956,7 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
181962
181956
|
sessionLog(sessionId, `compartment trigger: cheap-gate skipped (falling through to full read): ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
181963
181957
|
}
|
|
181964
181958
|
}
|
|
181965
|
-
const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail);
|
|
181959
|
+
const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail, taggerFloor);
|
|
181966
181960
|
if (!tailInfo.hasNewRawHistory) {
|
|
181967
181961
|
try {
|
|
181968
181962
|
const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
|
|
@@ -182328,7 +182322,7 @@ function createMagicContextCommandHandler(deps) {
|
|
|
182328
182322
|
const isAugCommand = (command) => command === "ctx-aug";
|
|
182329
182323
|
const isDreamCommand = (command) => command === "ctx-dream";
|
|
182330
182324
|
const isSessionUpgradeCommand = (command) => command === "ctx-session-upgrade";
|
|
182331
|
-
const
|
|
182325
|
+
const isEmbedCommand = (command) => command === "ctx-embed";
|
|
182332
182326
|
return {
|
|
182333
182327
|
"command.execute.before": async (input, _output, _params) => {
|
|
182334
182328
|
const isStatus = isStatusCommand(input.command);
|
|
@@ -182337,8 +182331,8 @@ function createMagicContextCommandHandler(deps) {
|
|
|
182337
182331
|
const isAug = isAugCommand(input.command);
|
|
182338
182332
|
const isDream = isDreamCommand(input.command);
|
|
182339
182333
|
const isSessionUpgrade = isSessionUpgradeCommand(input.command);
|
|
182340
|
-
const
|
|
182341
|
-
if (!isStatus && !isFlush && !isRecomp && !isAug && !isDream && !isSessionUpgrade && !
|
|
182334
|
+
const isEmbed = isEmbedCommand(input.command);
|
|
182335
|
+
if (!isStatus && !isFlush && !isRecomp && !isAug && !isDream && !isSessionUpgrade && !isEmbed) {
|
|
182342
182336
|
return;
|
|
182343
182337
|
}
|
|
182344
182338
|
const sessionId = input.sessionID;
|
|
@@ -182351,15 +182345,50 @@ function createMagicContextCommandHandler(deps) {
|
|
|
182351
182345
|
await executeDreaming(deps, sessionId);
|
|
182352
182346
|
return;
|
|
182353
182347
|
}
|
|
182354
|
-
if (
|
|
182355
|
-
const
|
|
182356
|
-
|
|
182357
|
-
|
|
182348
|
+
if (isEmbed) {
|
|
182349
|
+
const sub = input.arguments.trim().toLowerCase();
|
|
182350
|
+
if (sub === "pause") {
|
|
182351
|
+
const summary = deps.pauseEmbedDrain ? deps.pauseEmbedDrain(sessionId) : "Embedding pause is unavailable.";
|
|
182352
|
+
if (isTuiConnected(sessionId)) {
|
|
182353
|
+
pushNotification("action", { action: "show-result-dialog", title: "Embed", message: summary }, sessionId);
|
|
182354
|
+
} else {
|
|
182355
|
+
await deps.sendNotification(sessionId, summary, {});
|
|
182356
|
+
}
|
|
182357
|
+
throwSentinel(input.command);
|
|
182358
|
+
}
|
|
182359
|
+
if (sub === "start") {
|
|
182360
|
+
const summary = deps.executeEmbedHistory ? await deps.executeEmbedHistory(sessionId) : "Semantic embedding is not configured for this project, so there is nothing to embed.";
|
|
182361
|
+
if (isTuiConnected(sessionId)) {
|
|
182362
|
+
pushNotification("action", { action: "show-result-dialog", title: "Embed", message: summary }, sessionId);
|
|
182363
|
+
} else {
|
|
182364
|
+
await deps.sendNotification(sessionId, summary, {});
|
|
182365
|
+
}
|
|
182366
|
+
throwSentinel(input.command);
|
|
182367
|
+
}
|
|
182368
|
+
if (sub !== "") {
|
|
182369
|
+
await deps.sendNotification(sessionId, "Usage: `/ctx-embed` (status), `/ctx-embed start`, or `/ctx-embed pause`.", {});
|
|
182370
|
+
throwSentinel(input.command);
|
|
182371
|
+
}
|
|
182372
|
+
if (isTuiConnected(sessionId)) {
|
|
182373
|
+
pushNotification("action", { action: "show-embed-dialog" }, sessionId);
|
|
182374
|
+
sessionLog(sessionId, "command ctx-embed: pushed show-embed-dialog to TUI");
|
|
182375
|
+
throwSentinel(input.command);
|
|
182376
|
+
}
|
|
182377
|
+
result = deps.getEmbedStatusText ? `## Embedding Status
|
|
182378
|
+
|
|
182379
|
+
${deps.getEmbedStatusText(sessionId)}` : `## Embedding Status
|
|
182380
|
+
|
|
182381
|
+
Embedding status is unavailable.`;
|
|
182358
182382
|
}
|
|
182359
182383
|
if (isFlush) {
|
|
182360
182384
|
result = executeFlush(deps.db, sessionId);
|
|
182361
182385
|
clearCachedM0M1(deps.db, sessionId);
|
|
182362
182386
|
deps.onFlush?.(sessionId);
|
|
182387
|
+
if (isTuiConnected(sessionId)) {
|
|
182388
|
+
pushNotification("action", { action: "show-flush-dialog", message: result }, sessionId);
|
|
182389
|
+
sessionLog(sessionId, "command ctx-flush: pushed show-flush-dialog to TUI");
|
|
182390
|
+
throwSentinel(input.command);
|
|
182391
|
+
}
|
|
182363
182392
|
}
|
|
182364
182393
|
if (isStatus) {
|
|
182365
182394
|
if (isTuiConnected(sessionId)) {
|
|
@@ -182486,6 +182515,34 @@ ${snap.error}`;
|
|
|
182486
182515
|
// src/hooks/magic-context/hook.ts
|
|
182487
182516
|
init_derive_budgets();
|
|
182488
182517
|
|
|
182518
|
+
// src/hooks/magic-context/embed-session-state.ts
|
|
182519
|
+
var embedPauseBySession = new Set;
|
|
182520
|
+
var embedRunStateBySession = new Map;
|
|
182521
|
+
var autoEmbedAttemptedBySession = new Set;
|
|
182522
|
+
function getEmbedDrainUiStatus(sessionId, progress) {
|
|
182523
|
+
if (embedPauseBySession.has(sessionId)) {
|
|
182524
|
+
return { status: "paused" };
|
|
182525
|
+
}
|
|
182526
|
+
if (progress?.kind === "embed" && progress.phase === "recomp") {
|
|
182527
|
+
return { status: "running" };
|
|
182528
|
+
}
|
|
182529
|
+
if (progress?.kind === "embed" && (progress.phase === "failed" || progress.phase === "skipped") && progress.message) {
|
|
182530
|
+
if (/provider/i.test(progress.message)) {
|
|
182531
|
+
return { status: "stopped", detail: progress.message };
|
|
182532
|
+
}
|
|
182533
|
+
}
|
|
182534
|
+
return { status: "idle" };
|
|
182535
|
+
}
|
|
182536
|
+
function clearEmbedSessionState(sessionId) {
|
|
182537
|
+
embedPauseBySession.delete(sessionId);
|
|
182538
|
+
const ctrl = embedRunStateBySession.get(sessionId);
|
|
182539
|
+
if (ctrl) {
|
|
182540
|
+
ctrl.abort();
|
|
182541
|
+
embedRunStateBySession.delete(sessionId);
|
|
182542
|
+
}
|
|
182543
|
+
autoEmbedAttemptedBySession.delete(sessionId);
|
|
182544
|
+
}
|
|
182545
|
+
|
|
182489
182546
|
// src/features/magic-context/message-index-async.ts
|
|
182490
182547
|
init_logger();
|
|
182491
182548
|
await init_message_index();
|
|
@@ -182634,9 +182691,142 @@ function clearSessionTracking(sessionId) {
|
|
|
182634
182691
|
// src/hooks/magic-context/event-handler.ts
|
|
182635
182692
|
init_overflow_detection();
|
|
182636
182693
|
init_storage_meta_persisted();
|
|
182694
|
+
await init_storage();
|
|
182695
|
+
|
|
182696
|
+
// src/features/magic-context/transform-decision-log.ts
|
|
182697
|
+
await __promiseAll([
|
|
182698
|
+
init_sqlite(),
|
|
182699
|
+
init_storage_db()
|
|
182700
|
+
]);
|
|
182701
|
+
var canonicalReasons = new Set([
|
|
182702
|
+
"system_hash",
|
|
182703
|
+
"model_change",
|
|
182704
|
+
"project_memory_epoch",
|
|
182705
|
+
"ttl_idle",
|
|
182706
|
+
"explicit_flush",
|
|
182707
|
+
"max_mutation_id",
|
|
182708
|
+
"first_render",
|
|
182709
|
+
"pressure_refold",
|
|
182710
|
+
"upgrade_state",
|
|
182711
|
+
"cached_m1_missing"
|
|
182712
|
+
]);
|
|
182713
|
+
var piReasonAliases = {
|
|
182714
|
+
project_memory_change: "project_memory_epoch",
|
|
182715
|
+
pending_mutations: "max_mutation_id",
|
|
182716
|
+
renderer_upgrade: "upgrade_state",
|
|
182717
|
+
cache_invalid: "cached_m1_missing",
|
|
182718
|
+
drift: "pressure_refold"
|
|
182719
|
+
};
|
|
182720
|
+
var sharedReasonAliases = {
|
|
182721
|
+
model_key: "model_change",
|
|
182722
|
+
pressure: "pressure_refold"
|
|
182723
|
+
};
|
|
182724
|
+
var pendingDecisionBySession = new Map;
|
|
182725
|
+
var pendingPiDecisionBySession = new Map;
|
|
182726
|
+
var lastBoundMessageIdBySession = new Map;
|
|
182727
|
+
var scheduledWriteTokensBySession = new Map;
|
|
182728
|
+
var writerOverrideForTests = null;
|
|
182729
|
+
function normalizeMaterializeReason(harness, reason, rematerialized) {
|
|
182730
|
+
const raw = typeof reason === "string" ? reason.trim() : "";
|
|
182731
|
+
if (raw.length > 0) {
|
|
182732
|
+
const alias = sharedReasonAliases[raw] ?? (harness === "pi" ? piReasonAliases[raw] : undefined) ?? undefined;
|
|
182733
|
+
if (alias)
|
|
182734
|
+
return alias;
|
|
182735
|
+
if (canonicalReasons.has(raw))
|
|
182736
|
+
return raw;
|
|
182737
|
+
return null;
|
|
182738
|
+
}
|
|
182739
|
+
return rematerialized ? "pressure_refold" : null;
|
|
182740
|
+
}
|
|
182741
|
+
function clearOpenCodePendingTransformDecision(sessionId) {
|
|
182742
|
+
pendingDecisionBySession.delete(sessionId);
|
|
182743
|
+
}
|
|
182744
|
+
function clearTransformDecisionSession(sessionId) {
|
|
182745
|
+
pendingDecisionBySession.delete(sessionId);
|
|
182746
|
+
pendingPiDecisionBySession.delete(sessionId);
|
|
182747
|
+
lastBoundMessageIdBySession.delete(sessionId);
|
|
182748
|
+
scheduledWriteTokensBySession.delete(sessionId);
|
|
182749
|
+
}
|
|
182750
|
+
function recordPendingTransformDecision(sessionId, decision) {
|
|
182751
|
+
if (!decision.bustedThisPass) {
|
|
182752
|
+
pendingDecisionBySession.delete(sessionId);
|
|
182753
|
+
return;
|
|
182754
|
+
}
|
|
182755
|
+
pendingDecisionBySession.set(sessionId, decision);
|
|
182756
|
+
}
|
|
182757
|
+
function scheduleOpenCodeTransformDecisionWrite(args) {
|
|
182758
|
+
const pending = pendingDecisionBySession.get(args.sessionId);
|
|
182759
|
+
if (!pending)
|
|
182760
|
+
return false;
|
|
182761
|
+
if (lastBoundMessageIdBySession.get(args.sessionId) === args.messageId) {
|
|
182762
|
+
return false;
|
|
182763
|
+
}
|
|
182764
|
+
const dbPath = getDatabasePath(args.db);
|
|
182765
|
+
if (!dbPath)
|
|
182766
|
+
return false;
|
|
182767
|
+
lastBoundMessageIdBySession.set(args.sessionId, args.messageId);
|
|
182768
|
+
pendingDecisionBySession.delete(args.sessionId);
|
|
182769
|
+
const token = addScheduledWriteToken(args.sessionId);
|
|
182770
|
+
setTimeout(() => {
|
|
182771
|
+
try {
|
|
182772
|
+
if (!hasScheduledWriteToken(args.sessionId, token))
|
|
182773
|
+
return;
|
|
182774
|
+
writeTransformDecisionBestEffort(dbPath, {
|
|
182775
|
+
...pending,
|
|
182776
|
+
sessionId: args.sessionId,
|
|
182777
|
+
harness: "opencode",
|
|
182778
|
+
messageId: args.messageId,
|
|
182779
|
+
inputTokens: args.inputTokens
|
|
182780
|
+
});
|
|
182781
|
+
} finally {
|
|
182782
|
+
deleteScheduledWriteToken(args.sessionId, token);
|
|
182783
|
+
}
|
|
182784
|
+
}, 0);
|
|
182785
|
+
return true;
|
|
182786
|
+
}
|
|
182787
|
+
function addScheduledWriteToken(sessionId) {
|
|
182788
|
+
const token = Symbol(sessionId);
|
|
182789
|
+
let tokens = scheduledWriteTokensBySession.get(sessionId);
|
|
182790
|
+
if (!tokens) {
|
|
182791
|
+
tokens = new Set;
|
|
182792
|
+
scheduledWriteTokensBySession.set(sessionId, tokens);
|
|
182793
|
+
}
|
|
182794
|
+
tokens.add(token);
|
|
182795
|
+
return token;
|
|
182796
|
+
}
|
|
182797
|
+
function hasScheduledWriteToken(sessionId, token) {
|
|
182798
|
+
return scheduledWriteTokensBySession.get(sessionId)?.has(token) === true;
|
|
182799
|
+
}
|
|
182800
|
+
function deleteScheduledWriteToken(sessionId, token) {
|
|
182801
|
+
const tokens = scheduledWriteTokensBySession.get(sessionId);
|
|
182802
|
+
if (!tokens)
|
|
182803
|
+
return;
|
|
182804
|
+
tokens.delete(token);
|
|
182805
|
+
if (tokens.size === 0)
|
|
182806
|
+
scheduledWriteTokensBySession.delete(sessionId);
|
|
182807
|
+
}
|
|
182808
|
+
function writeTransformDecisionBestEffort(dbPath, row) {
|
|
182809
|
+
try {
|
|
182810
|
+
const writer = writerOverrideForTests ?? writeTransformDecisionRow;
|
|
182811
|
+
writer(dbPath, row);
|
|
182812
|
+
} catch {}
|
|
182813
|
+
}
|
|
182814
|
+
function writeTransformDecisionRow(dbPath, row) {
|
|
182815
|
+
const db = new Database(dbPath);
|
|
182816
|
+
try {
|
|
182817
|
+
db.exec("PRAGMA busy_timeout=0");
|
|
182818
|
+
db.prepare(`INSERT OR REPLACE INTO transform_decisions (
|
|
182819
|
+
session_id, harness, message_id, ts_ms, decision, materialized,
|
|
182820
|
+
materialize_reason, emergency, dropped_tokens, dropped_count, input_tokens
|
|
182821
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.sessionId, row.harness, row.messageId, row.tsMs, row.decision, row.materialized ? 1 : 0, row.materializeReason, row.emergency ? 1 : 0, Math.max(0, Math.floor(row.droppedTokens)), Math.max(0, Math.floor(row.droppedCount)), Math.max(0, Math.floor(row.inputTokens)));
|
|
182822
|
+
} finally {
|
|
182823
|
+
closeQuietly(db);
|
|
182824
|
+
}
|
|
182825
|
+
}
|
|
182826
|
+
|
|
182827
|
+
// src/hooks/magic-context/event-handler.ts
|
|
182637
182828
|
init_logger();
|
|
182638
182829
|
init_models_dev_cache();
|
|
182639
|
-
await init_storage();
|
|
182640
182830
|
|
|
182641
182831
|
// src/hooks/magic-context/channel2-delivery.ts
|
|
182642
182832
|
init_storage_meta_persisted();
|
|
@@ -182846,6 +183036,13 @@ function computePressure(input) {
|
|
|
182846
183036
|
function approxThousands(tokens) {
|
|
182847
183037
|
return `${Math.round(tokens / 1000)}k`;
|
|
182848
183038
|
}
|
|
183039
|
+
function formatOldestReclaimableHint(hint) {
|
|
183040
|
+
if (!hint || hint.length === 0)
|
|
183041
|
+
return "";
|
|
183042
|
+
const rendered = hint.slice(0, 4).map((tag) => `§${tag.tagNumber}§ ${tag.toolName ?? "tool"}`).join(" · ");
|
|
183043
|
+
return rendered.length > 0 ? `
|
|
183044
|
+
oldest reclaimable: ${rendered}.` : "";
|
|
183045
|
+
}
|
|
182849
183046
|
var CHANNEL2_USABLE_FRACTION = 1 / 3;
|
|
182850
183047
|
var CHANNEL2_MIN_RECLAIMABLE = 1e4;
|
|
182851
183048
|
function shouldTriggerChannel2(input) {
|
|
@@ -182855,14 +183052,16 @@ function shouldTriggerChannel2(input) {
|
|
|
182855
183052
|
return true;
|
|
182856
183053
|
return input.reclaimableTokens >= input.usableTokens * CHANNEL2_USABLE_FRACTION;
|
|
182857
183054
|
}
|
|
182858
|
-
function buildChannel2Reminder(undroppedTokens) {
|
|
183055
|
+
function buildChannel2Reminder(undroppedTokens, hint) {
|
|
182859
183056
|
const amount = approxThousands(undroppedTokens);
|
|
183057
|
+
const hintText = formatOldestReclaimableHint(hint);
|
|
182860
183058
|
return `<system-reminder>
|
|
182861
|
-
` + `Routine context housekeeping is near: a large span of this session will be comparted soon, ` + `and ~${amount} tokens of tool output remain unreduced. Drop spent outputs with ctx_reduce ` + `first so the archived span is the part that matters
|
|
183059
|
+
` + `Routine context housekeeping is near: a large span of this session will be comparted soon, ` + `and ~${amount} tokens of tool output remain unreduced. Drop spent outputs with ctx_reduce ` + `first so the archived span is the part that matters.${hintText}
|
|
182862
183060
|
` + `</system-reminder>`;
|
|
182863
183061
|
}
|
|
182864
|
-
function buildChannel1Reminder(level, undroppedTokens) {
|
|
183062
|
+
function buildChannel1Reminder(level, undroppedTokens, hint) {
|
|
182865
183063
|
const amount = approxThousands(undroppedTokens);
|
|
183064
|
+
const hintText = formatOldestReclaimableHint(hint);
|
|
182866
183065
|
let body;
|
|
182867
183066
|
switch (level) {
|
|
182868
183067
|
case "gentle":
|
|
@@ -182878,7 +183077,7 @@ function buildChannel1Reminder(level, undroppedTokens) {
|
|
|
182878
183077
|
return `
|
|
182879
183078
|
|
|
182880
183079
|
<system-reminder>
|
|
182881
|
-
${body}
|
|
183080
|
+
${body}${hintText}
|
|
182882
183081
|
</system-reminder>`;
|
|
182883
183082
|
}
|
|
182884
183083
|
|
|
@@ -182932,10 +183131,10 @@ async function maybeDeliverChannel2(sessionId, deps) {
|
|
|
182932
183131
|
try {
|
|
182933
183132
|
const client3 = getLiveServerClient(serverUrl, deps.directory);
|
|
182934
183133
|
const promptContext = await resolvePromptContext(client3, sessionId);
|
|
182935
|
-
const reminder = buildChannel2Reminder(deps.reclaimableTokens);
|
|
183134
|
+
const reminder = buildChannel2Reminder(deps.reclaimableTokens, deps.oldestReclaimableToolTags);
|
|
182936
183135
|
const body = {
|
|
182937
183136
|
noReply: false,
|
|
182938
|
-
parts: [{ type: "text", text: reminder }]
|
|
183137
|
+
parts: [{ type: "text", text: reminder, synthetic: true }]
|
|
182939
183138
|
};
|
|
182940
183139
|
if (promptContext?.agent)
|
|
182941
183140
|
body.agent = promptContext.agent;
|
|
@@ -183031,11 +183230,13 @@ function getMessageUpdatedAssistantInfo(properties) {
|
|
|
183031
183230
|
}
|
|
183032
183231
|
const tokens = isRecord(info.tokens) ? info.tokens : undefined;
|
|
183033
183232
|
const cache = tokens && isRecord(tokens.cache) ? tokens.cache : undefined;
|
|
183233
|
+
const time3 = isRecord(info.time) ? info.time : undefined;
|
|
183034
183234
|
return {
|
|
183035
183235
|
role: "assistant",
|
|
183036
183236
|
finish: typeof info.finish === "string" ? info.finish : undefined,
|
|
183037
183237
|
sessionID: info.sessionID,
|
|
183038
183238
|
messageID: typeof info.id === "string" ? info.id : undefined,
|
|
183239
|
+
completedAt: typeof time3?.completed === "number" ? time3.completed : undefined,
|
|
183039
183240
|
providerID: typeof info.providerID === "string" ? info.providerID : undefined,
|
|
183040
183241
|
modelID: typeof info.modelID === "string" ? info.modelID : undefined,
|
|
183041
183242
|
tokens: {
|
|
@@ -183098,8 +183299,8 @@ init_project_identity();
|
|
|
183098
183299
|
import * as crypto2 from "node:crypto";
|
|
183099
183300
|
init_session_project_storage();
|
|
183100
183301
|
init_storage_meta_persisted();
|
|
183101
|
-
init_logger();
|
|
183102
183302
|
await init_storage();
|
|
183303
|
+
init_logger();
|
|
183103
183304
|
|
|
183104
183305
|
// src/hooks/magic-context/boundary-execution.ts
|
|
183105
183306
|
var FORCE_MATERIALIZE_PERCENTAGE2 = 85;
|
|
@@ -183393,7 +183594,8 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config2) {
|
|
|
183393
183594
|
const result = {
|
|
183394
183595
|
compressedToLite: 0,
|
|
183395
183596
|
compressedToFull: 0,
|
|
183396
|
-
compressedToUltra: 0
|
|
183597
|
+
compressedToUltra: 0,
|
|
183598
|
+
mutatedTextTags: 0
|
|
183397
183599
|
};
|
|
183398
183600
|
if (!config2.enabled)
|
|
183399
183601
|
return result;
|
|
@@ -183434,7 +183636,9 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config2) {
|
|
|
183434
183636
|
const target = targets.get(tag.tagNumber);
|
|
183435
183637
|
if (!target)
|
|
183436
183638
|
continue;
|
|
183437
|
-
target.setContent(compressed);
|
|
183639
|
+
const didMutate = target.setContent(compressed);
|
|
183640
|
+
if (didMutate)
|
|
183641
|
+
result.mutatedTextTags += 1;
|
|
183438
183642
|
updateCavemanDepth(db, sessionId, tag.tagNumber, targetDepth);
|
|
183439
183643
|
if (targetDepth === DEPTH_LITE)
|
|
183440
183644
|
result.compressedToLite += 1;
|
|
@@ -184022,28 +184226,6 @@ function stripInlineThinking(messages, messageTagNumbers, clearReasoningAge) {
|
|
|
184022
184226
|
}
|
|
184023
184227
|
return stripped;
|
|
184024
184228
|
}
|
|
184025
|
-
function truncateErroredTools(messages, watermark, messageTagNumbers) {
|
|
184026
|
-
let truncated = 0;
|
|
184027
|
-
for (let i = 0;i < messages.length; i++) {
|
|
184028
|
-
const maxTag = messageTagNumbers.get(messages[i]) ?? 0;
|
|
184029
|
-
if (maxTag > watermark) {
|
|
184030
|
-
continue;
|
|
184031
|
-
}
|
|
184032
|
-
for (const part of messages[i].parts) {
|
|
184033
|
-
if (!isRecord(part) || part.type !== "tool" || !isRecord(part.state)) {
|
|
184034
|
-
continue;
|
|
184035
|
-
}
|
|
184036
|
-
if (part.state.status !== "error") {
|
|
184037
|
-
continue;
|
|
184038
|
-
}
|
|
184039
|
-
if (typeof part.state.error === "string" && part.state.error.length > 100) {
|
|
184040
|
-
part.state.error = `${part.state.error.slice(0, 100)}... [truncated]`;
|
|
184041
|
-
truncated++;
|
|
184042
|
-
}
|
|
184043
|
-
}
|
|
184044
|
-
}
|
|
184045
|
-
return truncated;
|
|
184046
|
-
}
|
|
184047
184229
|
var REASONING_IGNORED_PART_TYPES = new Set([
|
|
184048
184230
|
"step-start",
|
|
184049
184231
|
"step-finish",
|
|
@@ -184154,6 +184336,7 @@ function stripProcessedImages(messages, frozenIds, options) {
|
|
|
184154
184336
|
init_temporal_awareness();
|
|
184155
184337
|
|
|
184156
184338
|
// src/hooks/magic-context/transform-compartment-phase.ts
|
|
184339
|
+
init_compartment_storage();
|
|
184157
184340
|
init_logger();
|
|
184158
184341
|
await __promiseAll([
|
|
184159
184342
|
init_storage(),
|
|
@@ -184162,9 +184345,29 @@ await __promiseAll([
|
|
|
184162
184345
|
init_send_session_notification();
|
|
184163
184346
|
await __promiseAll([
|
|
184164
184347
|
init_inject_compartments(),
|
|
184165
|
-
init_protected_tail_boundary()
|
|
184348
|
+
init_protected_tail_boundary(),
|
|
184349
|
+
init_read_session_chunk()
|
|
184166
184350
|
]);
|
|
184167
|
-
|
|
184351
|
+
function runCompartmentPhase(args) {
|
|
184352
|
+
const historianRunnable = args.historianRunnable !== false;
|
|
184353
|
+
const willReadRawHistory = historianRunnable && args.canRunCompartments && getActiveCompartmentRun(args.sessionId) === undefined && (args.sessionMeta.compartmentInProgress || !args.skipAwaitForThisPass && args.contextUsage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE);
|
|
184354
|
+
if (!willReadRawHistory) {
|
|
184355
|
+
return runCompartmentPhaseImpl(args);
|
|
184356
|
+
}
|
|
184357
|
+
return withRawSessionMessageCache(() => {
|
|
184358
|
+
try {
|
|
184359
|
+
primeTailRawMessageCache({
|
|
184360
|
+
sessionId: args.resolvedSessionId,
|
|
184361
|
+
lastCompartmentEnd: getLastCompartmentEndMessage(args.db, args.resolvedSessionId),
|
|
184362
|
+
anchorMessageId: getLastCompartmentEndMessageId(args.db, args.resolvedSessionId)
|
|
184363
|
+
});
|
|
184364
|
+
} catch (error51) {
|
|
184365
|
+
sessionLog(args.sessionId, "compartment phase: tail prime failed (non-fatal):", error51);
|
|
184366
|
+
}
|
|
184367
|
+
return runCompartmentPhaseImpl(args);
|
|
184368
|
+
});
|
|
184369
|
+
}
|
|
184370
|
+
async function runCompartmentPhaseImpl(args) {
|
|
184168
184371
|
let pendingCompartmentInjection = args.pendingCompartmentInjection;
|
|
184169
184372
|
let compartmentInProgress = args.sessionMeta.compartmentInProgress;
|
|
184170
184373
|
let published = false;
|
|
@@ -184461,78 +184664,11 @@ function appendReminderToUserMessage(message, reminder) {
|
|
|
184461
184664
|
|
|
184462
184665
|
// src/hooks/magic-context/apply-operations.ts
|
|
184463
184666
|
await init_storage();
|
|
184464
|
-
|
|
184465
|
-
// src/hooks/magic-context/system-injection-stripper.ts
|
|
184466
|
-
var SYSTEM_INJECTION_MARKERS = [
|
|
184467
|
-
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
184468
|
-
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
184469
|
-
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
184470
|
-
"[Category+Skill Reminder]",
|
|
184471
|
-
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
184472
|
-
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
184473
|
-
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
184474
|
-
"Unstable background agent appears idle",
|
|
184475
|
-
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
184476
|
-
];
|
|
184477
|
-
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
184478
|
-
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
184479
|
-
function stripSystemInjection(text) {
|
|
184480
|
-
let hasInjection = false;
|
|
184481
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
184482
|
-
if (text.includes(marker)) {
|
|
184483
|
-
hasInjection = true;
|
|
184484
|
-
break;
|
|
184485
|
-
}
|
|
184486
|
-
}
|
|
184487
|
-
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
184488
|
-
hasInjection = true;
|
|
184489
|
-
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
184490
|
-
if (!hasInjection)
|
|
184491
|
-
return null;
|
|
184492
|
-
let cleaned = text;
|
|
184493
|
-
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
184494
|
-
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
184495
|
-
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
184496
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
184497
|
-
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
184498
|
-
continue;
|
|
184499
|
-
const idx = cleaned.indexOf(marker);
|
|
184500
|
-
if (idx === -1)
|
|
184501
|
-
continue;
|
|
184502
|
-
const blockEnd = cleaned.indexOf(`
|
|
184503
|
-
|
|
184504
|
-
`, idx + marker.length);
|
|
184505
|
-
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
184506
|
-
}
|
|
184507
|
-
return cleaned.trim();
|
|
184508
|
-
}
|
|
184509
|
-
|
|
184510
|
-
// src/hooks/magic-context/apply-operations.ts
|
|
184511
|
-
init_tag_part_guards();
|
|
184512
|
-
var USER_DROP_PREVIEW_CHARS = 250;
|
|
184513
184667
|
var RECENT_TOOL_SKELETON_WINDOW = 20;
|
|
184514
|
-
function buildReplacementContent(tagId
|
|
184515
|
-
|
|
184516
|
-
|
|
184517
|
-
|
|
184518
|
-
}
|
|
184519
|
-
const currentContent = target.getContent?.() ?? "";
|
|
184520
|
-
const strippedInjection = stripSystemInjection(currentContent);
|
|
184521
|
-
if (strippedInjection !== null && stripTagPrefix(strippedInjection).trim().length === 0) {
|
|
184522
|
-
return `[dropped §${tagId}§]`;
|
|
184523
|
-
}
|
|
184524
|
-
const originalText = stripTagPrefix(currentContent);
|
|
184525
|
-
if (originalText.length <= USER_DROP_PREVIEW_CHARS) {
|
|
184526
|
-
return `[truncated §${tagId}§]
|
|
184527
|
-
${originalText}`;
|
|
184528
|
-
}
|
|
184529
|
-
const hardCut = originalText.slice(0, USER_DROP_PREVIEW_CHARS);
|
|
184530
|
-
const softCutIndex = hardCut.search(/\s\S*$/);
|
|
184531
|
-
const preview = softCutIndex > USER_DROP_PREVIEW_CHARS - 30 ? hardCut.slice(0, softCutIndex) : hardCut;
|
|
184532
|
-
return `[truncated §${tagId}§]
|
|
184533
|
-
${preview}…`;
|
|
184534
|
-
}
|
|
184535
|
-
function applyPendingOperations(sessionId, db, targets, protectedTags = 0, preloadedTags, preloadedPendingOps) {
|
|
184668
|
+
function buildReplacementContent(tagId) {
|
|
184669
|
+
return `[dropped §${tagId}§]`;
|
|
184670
|
+
}
|
|
184671
|
+
function applyPendingOperations(sessionId, db, targets, protectedTags = 0, preloadedTags, preloadedPendingOps, syntheticPendingOps = []) {
|
|
184536
184672
|
let didMutateMessage = false;
|
|
184537
184673
|
db.transaction(() => {
|
|
184538
184674
|
const tags = preloadedTags ?? getTagsBySession(db, sessionId);
|
|
@@ -184540,11 +184676,16 @@ function applyPendingOperations(sessionId, db, targets, protectedTags = 0, prelo
|
|
|
184540
184676
|
const tagTypeById = new Map(tags.map((tag) => [tag.tagNumber, tag.type]));
|
|
184541
184677
|
const protectedTagIds = protectedTags > 0 ? new Set(tags.filter((tag) => tag.status === "active").map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, protectedTags)) : new Set;
|
|
184542
184678
|
const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
|
|
184679
|
+
const opsToApply = [
|
|
184680
|
+
...pendingOps.map((op) => ({ op, synthetic: false })),
|
|
184681
|
+
...syntheticPendingOps.map((op) => ({ op, synthetic: true }))
|
|
184682
|
+
];
|
|
184543
184683
|
const skeletonWindow = new Set(tags.filter((tag) => tag.type === "tool").map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, RECENT_TOOL_SKELETON_WINDOW));
|
|
184544
|
-
for (const pendingOp of
|
|
184684
|
+
for (const { op: pendingOp, synthetic } of opsToApply) {
|
|
184545
184685
|
const tagStatus = tagStatusById.get(pendingOp.tagId);
|
|
184546
184686
|
if (tagStatus === "compacted" || tagStatus === "dropped") {
|
|
184547
|
-
|
|
184687
|
+
if (!synthetic)
|
|
184688
|
+
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
184548
184689
|
continue;
|
|
184549
184690
|
}
|
|
184550
184691
|
if (protectedTagIds.has(pendingOp.tagId)) {
|
|
@@ -184552,33 +184693,46 @@ function applyPendingOperations(sessionId, db, targets, protectedTags = 0, prelo
|
|
|
184552
184693
|
}
|
|
184553
184694
|
const target = targets.get(pendingOp.tagId);
|
|
184554
184695
|
const isToolTag = tagTypeById.get(pendingOp.tagId) === "tool";
|
|
184696
|
+
if (synthetic) {
|
|
184697
|
+
if (!isToolTag || target?.canDrop?.() !== true)
|
|
184698
|
+
continue;
|
|
184699
|
+
}
|
|
184700
|
+
let shouldPersistDrop = false;
|
|
184555
184701
|
if (isToolTag) {
|
|
184556
184702
|
if (skeletonWindow.has(pendingOp.tagId)) {
|
|
184557
184703
|
const truncResult = target?.truncate?.() ?? "absent";
|
|
184558
|
-
if (truncResult === "incomplete") {
|
|
184704
|
+
if (truncResult === "incomplete" || synthetic && truncResult !== "truncated") {
|
|
184559
184705
|
continue;
|
|
184560
184706
|
}
|
|
184561
184707
|
if (truncResult === "truncated") {
|
|
184562
184708
|
didMutateMessage = true;
|
|
184563
184709
|
}
|
|
184564
184710
|
updateTagDropMode(db, sessionId, pendingOp.tagId, "truncated");
|
|
184711
|
+
shouldPersistDrop = true;
|
|
184565
184712
|
} else {
|
|
184566
184713
|
const dropResult = target?.drop?.() ?? "absent";
|
|
184567
|
-
if (dropResult === "incomplete") {
|
|
184714
|
+
if (dropResult === "incomplete" || synthetic && dropResult !== "removed") {
|
|
184568
184715
|
continue;
|
|
184569
184716
|
}
|
|
184570
184717
|
if (dropResult === "removed") {
|
|
184571
184718
|
didMutateMessage = true;
|
|
184572
184719
|
}
|
|
184573
184720
|
updateTagDropMode(db, sessionId, pendingOp.tagId, "full");
|
|
184721
|
+
shouldPersistDrop = true;
|
|
184574
184722
|
}
|
|
184575
184723
|
} else if (target) {
|
|
184576
|
-
const changed = target.setContent(buildReplacementContent(pendingOp.tagId
|
|
184724
|
+
const changed = target.setContent(buildReplacementContent(pendingOp.tagId));
|
|
184577
184725
|
if (changed)
|
|
184578
184726
|
didMutateMessage = true;
|
|
184727
|
+
shouldPersistDrop = true;
|
|
184728
|
+
} else if (!synthetic) {
|
|
184729
|
+
shouldPersistDrop = true;
|
|
184579
184730
|
}
|
|
184731
|
+
if (!shouldPersistDrop)
|
|
184732
|
+
continue;
|
|
184580
184733
|
updateTagStatus(db, sessionId, pendingOp.tagId, "dropped");
|
|
184581
|
-
|
|
184734
|
+
if (!synthetic)
|
|
184735
|
+
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
184582
184736
|
}
|
|
184583
184737
|
})();
|
|
184584
184738
|
return didMutateMessage;
|
|
@@ -184602,7 +184756,7 @@ function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
|
|
|
184602
184756
|
}
|
|
184603
184757
|
}
|
|
184604
184758
|
} else if (target) {
|
|
184605
|
-
const changed = target.setContent(buildReplacementContent(tag.tagNumber
|
|
184759
|
+
const changed = target.setContent(buildReplacementContent(tag.tagNumber));
|
|
184606
184760
|
if (changed)
|
|
184607
184761
|
didMutateMessage = true;
|
|
184608
184762
|
}
|
|
@@ -184779,6 +184933,7 @@ function createExistingTagResolver(sessionId, tagger, db) {
|
|
|
184779
184933
|
return;
|
|
184780
184934
|
}
|
|
184781
184935
|
updateTagMessageId(db, sessionId, fallback.tagNumber, currentContentId);
|
|
184936
|
+
tagger.unbindTag(sessionId, fallback.contentId);
|
|
184782
184937
|
tagger.bindTag(sessionId, currentContentId, fallback.tagNumber);
|
|
184783
184938
|
usedTagNumbers.add(fallback.tagNumber);
|
|
184784
184939
|
return fallback.tagNumber;
|
|
@@ -184799,7 +184954,45 @@ function logTransformTiming(sessionId, stage, startMs, extra) {
|
|
|
184799
184954
|
}
|
|
184800
184955
|
|
|
184801
184956
|
// src/hooks/magic-context/tag-messages.ts
|
|
184802
|
-
|
|
184957
|
+
var TOOL_OWNER_CACHE_KEY_SEP = "\x00";
|
|
184958
|
+
function makeToolOwnerCacheKey(sessionId, callId) {
|
|
184959
|
+
return `${sessionId}${TOOL_OWNER_CACHE_KEY_SEP}${callId}`;
|
|
184960
|
+
}
|
|
184961
|
+
function getCachedCandidateToolOwners(db, sessionId, callId, cache, onLookup) {
|
|
184962
|
+
const key = makeToolOwnerCacheKey(sessionId, callId);
|
|
184963
|
+
const cached2 = cache.candidateOwnersByCallId.get(key);
|
|
184964
|
+
if (cached2 !== undefined)
|
|
184965
|
+
return cached2;
|
|
184966
|
+
onLookup?.({ kind: "candidates", callId });
|
|
184967
|
+
const candidates = getCandidateToolOwners(db, sessionId, callId);
|
|
184968
|
+
cache.candidateOwnersByCallId.set(key, candidates);
|
|
184969
|
+
return candidates;
|
|
184970
|
+
}
|
|
184971
|
+
function getCachedMessageTimesFromOpenCodeDb(sessionId, messageIds, cache, onLookup) {
|
|
184972
|
+
const uncached = [...new Set(messageIds)].filter((id) => !cache.messageTimesById.has(id));
|
|
184973
|
+
if (uncached.length > 0) {
|
|
184974
|
+
onLookup?.({ kind: "messageTimes", messageIds: uncached });
|
|
184975
|
+
const resolved = getMessageTimesFromOpenCodeDb(sessionId, uncached);
|
|
184976
|
+
for (const id of uncached) {
|
|
184977
|
+
cache.messageTimesById.set(id, resolved.get(id) ?? null);
|
|
184978
|
+
}
|
|
184979
|
+
}
|
|
184980
|
+
const times = new Map;
|
|
184981
|
+
for (const id of messageIds) {
|
|
184982
|
+
const time3 = cache.messageTimesById.get(id);
|
|
184983
|
+
if (typeof time3 === "number")
|
|
184984
|
+
times.set(id, time3);
|
|
184985
|
+
}
|
|
184986
|
+
return times;
|
|
184987
|
+
}
|
|
184988
|
+
function invalidateCachedCandidateToolOwnersIfNewOwner(cache, sessionId, callId, ownerMsgId) {
|
|
184989
|
+
const key = makeToolOwnerCacheKey(sessionId, callId);
|
|
184990
|
+
const cached2 = cache.candidateOwnersByCallId.get(key);
|
|
184991
|
+
if (cached2 !== undefined && !cached2.includes(ownerMsgId)) {
|
|
184992
|
+
cache.candidateOwnersByCallId.delete(key);
|
|
184993
|
+
}
|
|
184994
|
+
}
|
|
184995
|
+
function deriveToolOwnerMessageId(sessionId, db, message, obs, unpaired, cache, onFallbackLookup) {
|
|
184803
184996
|
const messageId = typeof message.info.id === "string" ? message.info.id : "";
|
|
184804
184997
|
if (obs.kind === "invocation") {
|
|
184805
184998
|
if (messageId) {
|
|
@@ -184819,10 +185012,10 @@ function deriveToolOwnerMessageId(sessionId, db, message, obs, unpaired) {
|
|
|
184819
185012
|
return popped;
|
|
184820
185013
|
}
|
|
184821
185014
|
if (messageId) {
|
|
184822
|
-
const candidates =
|
|
185015
|
+
const candidates = getCachedCandidateToolOwners(db, sessionId, obs.callId, cache, onFallbackLookup);
|
|
184823
185016
|
if (candidates.length > 0) {
|
|
184824
185017
|
const ids = [...candidates, messageId];
|
|
184825
|
-
const times =
|
|
185018
|
+
const times = getCachedMessageTimesFromOpenCodeDb(sessionId, ids, cache, onFallbackLookup);
|
|
184826
185019
|
const persisted = pickNearestPriorOwner(candidates, messageId, times);
|
|
184827
185020
|
if (persisted !== null)
|
|
184828
185021
|
return persisted;
|
|
@@ -184903,6 +185096,7 @@ function extractToolTagMetadata(part) {
|
|
|
184903
185096
|
}
|
|
184904
185097
|
function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
184905
185098
|
const skipPrefixInjection = options.skipPrefixInjection === true;
|
|
185099
|
+
const onToolOwnerFallbackLookup = options.onToolOwnerFallbackLookup;
|
|
184906
185100
|
const targets = new Map;
|
|
184907
185101
|
const reasoningByMessage = new Map;
|
|
184908
185102
|
const messageTagNumbers = new Map;
|
|
@@ -184910,6 +185104,10 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
|
184910
185104
|
const toolThinkingByCallId = new Map;
|
|
184911
185105
|
const toolCallIndex = new Map;
|
|
184912
185106
|
const unpairedInvocations = new Map;
|
|
185107
|
+
const ownerDerivationCache = {
|
|
185108
|
+
candidateOwnersByCallId: new Map,
|
|
185109
|
+
messageTimesById: new Map
|
|
185110
|
+
};
|
|
184913
185111
|
const ownerByPartKey = new Map;
|
|
184914
185112
|
const batch = new ToolMutationBatch(messages);
|
|
184915
185113
|
const assignments = tagger.getAssignments(sessionId);
|
|
@@ -184950,7 +185148,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
|
184950
185148
|
const toolObservation = extractToolCallObservation(part);
|
|
184951
185149
|
if (toolObservation) {
|
|
184952
185150
|
const _tDerive = performance.now();
|
|
184953
|
-
const ownerMsgId = deriveToolOwnerMessageId(sessionId, db, message, toolObservation, unpairedInvocations);
|
|
185151
|
+
const ownerMsgId = deriveToolOwnerMessageId(sessionId, db, message, toolObservation, unpairedInvocations, ownerDerivationCache, onToolOwnerFallbackLookup);
|
|
184954
185152
|
accDerive += performance.now() - _tDerive;
|
|
184955
185153
|
const compositeKey = makeToolCompositeKey(ownerMsgId, toolObservation.callId);
|
|
184956
185154
|
const entry = toolCallIndex.get(compositeKey) ?? {
|
|
@@ -184969,6 +185167,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
|
184969
185167
|
if (orphan !== null) {
|
|
184970
185168
|
const claimed = adoptNullOwnerToolTag(db, orphan.id, ownerMsgId);
|
|
184971
185169
|
if (claimed) {
|
|
185170
|
+
invalidateCachedCandidateToolOwnersIfNewOwner(ownerDerivationCache, sessionId, toolObservation.callId, ownerMsgId);
|
|
184972
185171
|
tagger.bindToolTag(sessionId, toolObservation.callId, ownerMsgId, orphan.tagNumber);
|
|
184973
185172
|
existingTagId = orphan.tagNumber;
|
|
184974
185173
|
} else {
|
|
@@ -184976,6 +185175,13 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
|
184976
185175
|
}
|
|
184977
185176
|
}
|
|
184978
185177
|
}
|
|
185178
|
+
if (existingTagId === undefined) {
|
|
185179
|
+
const persisted = getToolTagNumberByOwner(db, sessionId, toolObservation.callId, ownerMsgId);
|
|
185180
|
+
if (persisted !== null) {
|
|
185181
|
+
tagger.bindToolTag(sessionId, toolObservation.callId, ownerMsgId, persisted);
|
|
185182
|
+
existingTagId = persisted;
|
|
185183
|
+
}
|
|
185184
|
+
}
|
|
184979
185185
|
if (existingTagId !== undefined) {
|
|
184980
185186
|
toolTagByCallId.set(compositeKey, existingTagId);
|
|
184981
185187
|
messageTagNumbers.set(message, Math.max(messageTagNumbers.get(message) ?? 0, existingTagId));
|
|
@@ -185048,6 +185254,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
|
185048
185254
|
inputTokenCount,
|
|
185049
185255
|
reasoningTokenCount: reasoningTokens
|
|
185050
185256
|
}));
|
|
185257
|
+
invalidateCachedCandidateToolOwnersIfNewOwner(ownerDerivationCache, sessionId, toolPart.callID, ownerMsgId);
|
|
185051
185258
|
accAssignToolTag += performance.now() - _tAssignTool;
|
|
185052
185259
|
messageTagNumbers.set(message, Math.max(messageTagNumbers.get(message) ?? 0, tagId));
|
|
185053
185260
|
if (!skipPrefixInjection) {
|
|
@@ -185119,7 +185326,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
|
185119
185326
|
logTransformTiming(sessionId, "tag.saveSource", performance.now() - accSaveSource);
|
|
185120
185327
|
for (const [compositeKey, tagId] of toolTagByCallId) {
|
|
185121
185328
|
const thinkingParts = toolThinkingByCallId.get(compositeKey) ?? [];
|
|
185122
|
-
targets.set(tagId, createToolDropTarget(compositeKey, thinkingParts, toolCallIndex, batch));
|
|
185329
|
+
targets.set(tagId, createToolDropTarget(compositeKey, thinkingParts, toolCallIndex, batch, tagId));
|
|
185123
185330
|
}
|
|
185124
185331
|
const hasRecentReduceCall = lastReduceMessageIndex >= 0 && messages.length - lastReduceMessageIndex <= RECENT_REDUCE_LOOKBACK;
|
|
185125
185332
|
return {
|
|
@@ -186046,7 +186253,7 @@ async function runAutoSearchHint(args) {
|
|
|
186046
186253
|
embeddingEnabled,
|
|
186047
186254
|
gitCommitsEnabled,
|
|
186048
186255
|
embedQuery: async (text, signal) => {
|
|
186049
|
-
const result = await embedTextForProject(options.projectPath, text, signal);
|
|
186256
|
+
const result = await embedTextForProject(options.projectPath, text, signal, "query");
|
|
186050
186257
|
return result?.vector ?? null;
|
|
186051
186258
|
},
|
|
186052
186259
|
isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
|
|
@@ -186227,6 +186434,51 @@ function planEmergencyDrop(input) {
|
|
|
186227
186434
|
};
|
|
186228
186435
|
}
|
|
186229
186436
|
|
|
186437
|
+
// src/hooks/magic-context/system-injection-stripper.ts
|
|
186438
|
+
var SYSTEM_INJECTION_MARKERS = [
|
|
186439
|
+
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
186440
|
+
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
186441
|
+
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
186442
|
+
"[Category+Skill Reminder]",
|
|
186443
|
+
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
186444
|
+
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
186445
|
+
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
186446
|
+
"Unstable background agent appears idle",
|
|
186447
|
+
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
186448
|
+
];
|
|
186449
|
+
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
186450
|
+
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
186451
|
+
function stripSystemInjection(text) {
|
|
186452
|
+
let hasInjection = false;
|
|
186453
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
186454
|
+
if (text.includes(marker)) {
|
|
186455
|
+
hasInjection = true;
|
|
186456
|
+
break;
|
|
186457
|
+
}
|
|
186458
|
+
}
|
|
186459
|
+
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
186460
|
+
hasInjection = true;
|
|
186461
|
+
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
186462
|
+
if (!hasInjection)
|
|
186463
|
+
return null;
|
|
186464
|
+
let cleaned = text;
|
|
186465
|
+
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
186466
|
+
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
186467
|
+
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
186468
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
186469
|
+
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
186470
|
+
continue;
|
|
186471
|
+
const idx = cleaned.indexOf(marker);
|
|
186472
|
+
if (idx === -1)
|
|
186473
|
+
continue;
|
|
186474
|
+
const blockEnd = cleaned.indexOf(`
|
|
186475
|
+
|
|
186476
|
+
`, idx + marker.length);
|
|
186477
|
+
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
186478
|
+
}
|
|
186479
|
+
return cleaned.trim();
|
|
186480
|
+
}
|
|
186481
|
+
|
|
186230
186482
|
// src/hooks/magic-context/heuristic-cleanup.ts
|
|
186231
186483
|
init_tag_part_guards();
|
|
186232
186484
|
var DEDUP_SAFE_TOOLS = new Set([
|
|
@@ -186245,6 +186497,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
186245
186497
|
const maxTag = getMaxTagNumberBySession(db, sessionId);
|
|
186246
186498
|
const protectedCutoff = maxTag - config2.protectedTags;
|
|
186247
186499
|
let droppedTools = 0;
|
|
186500
|
+
let emergencyDroppedTools = 0;
|
|
186248
186501
|
let deduplicatedTools = 0;
|
|
186249
186502
|
let droppedInjections = 0;
|
|
186250
186503
|
if (config2.emergency) {
|
|
@@ -186276,6 +186529,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
186276
186529
|
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
186277
186530
|
updateTagDropMode(db, sessionId, tag.tagNumber, "full");
|
|
186278
186531
|
droppedTools++;
|
|
186532
|
+
emergencyDroppedTools++;
|
|
186279
186533
|
}
|
|
186280
186534
|
}
|
|
186281
186535
|
setEmergencyDropSample(db, sessionId, emergency.currentTotalInputTokens);
|
|
@@ -186354,7 +186608,9 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
186354
186608
|
continue;
|
|
186355
186609
|
updateTagDropMode(db, sessionId, tag.tagNumber, "full");
|
|
186356
186610
|
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
186357
|
-
|
|
186611
|
+
if (result === "removed" || result === "truncated") {
|
|
186612
|
+
deduplicatedTools++;
|
|
186613
|
+
}
|
|
186358
186614
|
}
|
|
186359
186615
|
}
|
|
186360
186616
|
})();
|
|
@@ -186363,6 +186619,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
186363
186619
|
sessionLog(sessionId, `heuristic cleanup: dropped ${droppedTools} tool tags, deduplicated ${deduplicatedTools} tool calls, dropped ${droppedInjections} system injections`);
|
|
186364
186620
|
}
|
|
186365
186621
|
let compressedTextTags = 0;
|
|
186622
|
+
let mutatedTextTags = 0;
|
|
186366
186623
|
if (config2.caveman?.enabled) {
|
|
186367
186624
|
const cavemanResult = applyCavemanCleanup(sessionId, db, targets, tags, {
|
|
186368
186625
|
enabled: true,
|
|
@@ -186370,8 +186627,16 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
186370
186627
|
protectedTags: config2.protectedTags
|
|
186371
186628
|
});
|
|
186372
186629
|
compressedTextTags = cavemanResult.compressedToLite + cavemanResult.compressedToFull + cavemanResult.compressedToUltra;
|
|
186630
|
+
mutatedTextTags = cavemanResult.mutatedTextTags;
|
|
186373
186631
|
}
|
|
186374
|
-
return {
|
|
186632
|
+
return {
|
|
186633
|
+
droppedTools,
|
|
186634
|
+
deduplicatedTools,
|
|
186635
|
+
droppedInjections,
|
|
186636
|
+
emergencyDroppedTools,
|
|
186637
|
+
compressedTextTags,
|
|
186638
|
+
mutatedTextTags
|
|
186639
|
+
};
|
|
186375
186640
|
}
|
|
186376
186641
|
function extractToolInfo(part) {
|
|
186377
186642
|
if (part.type === "tool" && typeof part.tool === "string" && DEDUP_SAFE_TOOLS.has(part.tool)) {
|
|
@@ -186545,6 +186810,42 @@ function isTodoItem(value) {
|
|
|
186545
186810
|
return typeof todo.content === "string" && typeof todo.status === "string" && (todo.priority === undefined || typeof todo.priority === "string");
|
|
186546
186811
|
}
|
|
186547
186812
|
|
|
186813
|
+
// src/hooks/magic-context/tool-reclaim.ts
|
|
186814
|
+
await init_storage();
|
|
186815
|
+
function buildSyntheticToolReclaimOps(input) {
|
|
186816
|
+
const watermark = Math.max(0, input.watermark);
|
|
186817
|
+
if (watermark <= 0)
|
|
186818
|
+
return [];
|
|
186819
|
+
const realPendingTagIds = new Set((input.pendingOps ?? []).map((op) => op.tagId));
|
|
186820
|
+
const tags = getActiveTagsBySession(input.db, input.sessionId);
|
|
186821
|
+
const synthetic = [];
|
|
186822
|
+
for (const tag of tags) {
|
|
186823
|
+
if (tag.type !== "tool")
|
|
186824
|
+
continue;
|
|
186825
|
+
if (tag.status !== "active")
|
|
186826
|
+
continue;
|
|
186827
|
+
if (tag.tagNumber > watermark)
|
|
186828
|
+
continue;
|
|
186829
|
+
if (realPendingTagIds.has(tag.tagNumber))
|
|
186830
|
+
continue;
|
|
186831
|
+
if (input.targets.get(tag.tagNumber)?.canDrop?.() !== true)
|
|
186832
|
+
continue;
|
|
186833
|
+
synthetic.push({
|
|
186834
|
+
id: 0,
|
|
186835
|
+
sessionId: input.sessionId,
|
|
186836
|
+
tagId: tag.tagNumber,
|
|
186837
|
+
operation: "drop",
|
|
186838
|
+
queuedAt: 0
|
|
186839
|
+
});
|
|
186840
|
+
}
|
|
186841
|
+
return synthetic;
|
|
186842
|
+
}
|
|
186843
|
+
function advanceToolReclaimWatermarkToCurrentMax(db, sessionId) {
|
|
186844
|
+
const maxTagNumber = getMaxTagNumberBySession(db, sessionId);
|
|
186845
|
+
advanceToolReclaimWatermark(db, sessionId, maxTagNumber);
|
|
186846
|
+
return maxTagNumber;
|
|
186847
|
+
}
|
|
186848
|
+
|
|
186548
186849
|
// src/hooks/magic-context/transform-postprocess-phase.ts
|
|
186549
186850
|
var DEGRADE_CACHE_WARNING_THRESHOLD = 10;
|
|
186550
186851
|
var degradedCacheCountBySession = new BoundedSessionMap(100);
|
|
@@ -186561,7 +186862,6 @@ async function runPostTransformPhase(args) {
|
|
|
186561
186862
|
const emergencyDropEligible = args.contextUsage.percentage >= args.forceMaterializationPercentage;
|
|
186562
186863
|
const activeCompartmentRun = args.canRunCompartments ? getActiveCompartmentRun(args.sessionId) : undefined;
|
|
186563
186864
|
const compartmentRunning = args.canRunCompartments && !args.awaitedCompartmentRun && activeCompartmentRun !== undefined;
|
|
186564
|
-
const emergencyBypassCompartmentGate = forceMaterialization;
|
|
186565
186865
|
const deferredMaterialize = args.canConsumeDeferredLate && deferredMaterializationWasPending;
|
|
186566
186866
|
const materializationRequested = isExplicitFlush || deferredMaterialize;
|
|
186567
186867
|
const m0M1EnabledForFold = args.fullFeatureMode && args.m0M1 !== undefined && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory);
|
|
@@ -186573,11 +186873,12 @@ async function runPostTransformPhase(args) {
|
|
|
186573
186873
|
projectDirectory: args.m0M1.projectDirectory,
|
|
186574
186874
|
hardSignals: args.m0M1.hardSignals
|
|
186575
186875
|
}).value : false;
|
|
186876
|
+
const bypassCompartmentGate = forceMaterialization || m0HardFoldThisPass;
|
|
186576
186877
|
const shouldReadPendingOps = materializationRequested || args.schedulerDecision === "execute" || forceMaterialization || m0HardFoldThisPass || compartmentRunning;
|
|
186577
186878
|
const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
|
|
186578
186879
|
const hasPendingUserOps = pendingOps.length > 0;
|
|
186579
|
-
const shouldApplyPendingOps = (args.schedulerDecision === "execute" || materializationRequested || forceMaterialization || m0HardFoldThisPass) && (!compartmentRunning ||
|
|
186580
|
-
const shouldRunHeuristics = (!compartmentRunning ||
|
|
186880
|
+
const shouldApplyPendingOps = (args.schedulerDecision === "execute" || materializationRequested || forceMaterialization || m0HardFoldThisPass) && (!compartmentRunning || bypassCompartmentGate);
|
|
186881
|
+
const shouldRunHeuristics = (!compartmentRunning || bypassCompartmentGate) && (materializationRequested || forceMaterialization || m0HardFoldThisPass || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
|
|
186581
186882
|
const isCacheBustingPass = shouldApplyPendingOps || shouldRunHeuristics;
|
|
186582
186883
|
const canUseEmptySentinels = modelAcceptsEmptyContent(args.resolvedProviderID);
|
|
186583
186884
|
if (shouldRunHeuristics) {
|
|
@@ -186589,8 +186890,9 @@ async function runPostTransformPhase(args) {
|
|
|
186589
186890
|
sessionLog(args.sessionId, `transform: skipping heuristics (already ran for turn ${args.currentTurnId})`);
|
|
186590
186891
|
}
|
|
186591
186892
|
if (compartmentRunning && hasPendingUserOps) {
|
|
186592
|
-
if (
|
|
186593
|
-
|
|
186893
|
+
if (bypassCompartmentGate) {
|
|
186894
|
+
const bypassReason = forceMaterialization ? "emergency >=85%" : "m0 hard fold";
|
|
186895
|
+
sessionLog(args.sessionId, `transform: compartment-gate bypass (${bypassReason}) — applying ${pendingOps.length} pending ops while compartment agent runs (${args.contextUsage.percentage.toFixed(1)}%)`);
|
|
186594
186896
|
} else {
|
|
186595
186897
|
sessionLog(args.sessionId, "transform: deferring pending ops — compartment agent in progress");
|
|
186596
186898
|
}
|
|
@@ -186599,12 +186901,24 @@ async function runPostTransformPhase(args) {
|
|
|
186599
186901
|
let deferredMaterializedSuccessfully = false;
|
|
186600
186902
|
let heuristicsRanSuccessfully = false;
|
|
186601
186903
|
let pendingOpsRanSuccessfully = false;
|
|
186904
|
+
let pendingOpsDidMutate = false;
|
|
186905
|
+
let heuristicOrReasoningDidMutate = false;
|
|
186906
|
+
let droppedCount = 0;
|
|
186907
|
+
const droppedTokens = 0;
|
|
186908
|
+
let emergency = false;
|
|
186909
|
+
let m0RematerializedThisPass = false;
|
|
186910
|
+
let m0MaterializeReason = null;
|
|
186911
|
+
let m0M1InjectedThisPass = false;
|
|
186912
|
+
let autoReclaimDidMutateThisPass = false;
|
|
186602
186913
|
try {
|
|
186603
186914
|
if (shouldApplyPendingOps) {
|
|
186604
186915
|
const applyReason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : `scheduler_execute (scheduler=${args.schedulerDecision})`;
|
|
186605
186916
|
sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOps.length}, context=${args.contextUsage.percentage.toFixed(1)}%`);
|
|
186606
186917
|
const tApply = performance.now();
|
|
186607
|
-
applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTags, undefined, pendingOps);
|
|
186918
|
+
pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTags, undefined, pendingOps);
|
|
186919
|
+
if (pendingOpsDidMutate) {
|
|
186920
|
+
droppedCount += pendingOps.length;
|
|
186921
|
+
}
|
|
186608
186922
|
logTransformTiming(args.sessionId, "applyPendingOperations", tApply);
|
|
186609
186923
|
}
|
|
186610
186924
|
if (shouldRunHeuristics) {
|
|
@@ -186622,9 +186936,12 @@ async function runPostTransformPhase(args) {
|
|
|
186622
186936
|
} : undefined,
|
|
186623
186937
|
caveman: cavemanConfig
|
|
186624
186938
|
}, heuristicTags);
|
|
186625
|
-
logTransformTiming(args.sessionId, "applyHeuristicCleanup", t5, `droppedTools=${cleanup.droppedTools} deduplicatedTools=${cleanup.deduplicatedTools} droppedInjections=${cleanup.droppedInjections} compressedTextTags=${cleanup.compressedTextTags}`);
|
|
186939
|
+
logTransformTiming(args.sessionId, "applyHeuristicCleanup", t5, `droppedTools=${cleanup.droppedTools} deduplicatedTools=${cleanup.deduplicatedTools} droppedInjections=${cleanup.droppedInjections} compressedTextTags=${cleanup.compressedTextTags} mutatedTextTags=${cleanup.mutatedTextTags}`);
|
|
186940
|
+
const heuristicMutationCount = cleanup.droppedTools + cleanup.deduplicatedTools + cleanup.droppedInjections + cleanup.mutatedTextTags;
|
|
186941
|
+
droppedCount += cleanup.droppedTools + cleanup.deduplicatedTools + cleanup.droppedInjections + cleanup.mutatedTextTags;
|
|
186942
|
+
emergency ||= cleanup.emergencyDroppedTools > 0;
|
|
186626
186943
|
const t7 = performance.now();
|
|
186627
|
-
const clearedReasoning = clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge);
|
|
186944
|
+
const clearedReasoning = canUseEmptySentinels ? clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge) : 0;
|
|
186628
186945
|
if (canUseEmptySentinels) {
|
|
186629
186946
|
stripClearedReasoning(args.messages);
|
|
186630
186947
|
}
|
|
@@ -186648,6 +186965,8 @@ async function runPostTransformPhase(args) {
|
|
|
186648
186965
|
}
|
|
186649
186966
|
}
|
|
186650
186967
|
logTransformTiming(args.sessionId, "clearOldReasoning", t7);
|
|
186968
|
+
heuristicOrReasoningDidMutate = heuristicMutationCount + clearedReasoning + strippedInline > 0;
|
|
186969
|
+
droppedCount += clearedReasoning + strippedInline;
|
|
186651
186970
|
if (pendingMaterializationAtPassStart) {
|
|
186652
186971
|
args.pendingMaterializationSessions.delete(args.sessionId);
|
|
186653
186972
|
}
|
|
@@ -186658,7 +186977,35 @@ async function runPostTransformPhase(args) {
|
|
|
186658
186977
|
if (args.schedulerDecision === "execute" && !materializationRequested) {
|
|
186659
186978
|
updateSessionMeta(args.db, args.sessionId, { lastResponseTime: Date.now() });
|
|
186660
186979
|
}
|
|
186980
|
+
const toolReclaimExecutePass = args.schedulerDecision === "execute";
|
|
186981
|
+
const alreadyMutatingThisPass = pendingOpsDidMutate || heuristicOrReasoningDidMutate;
|
|
186982
|
+
let autoReclaimTargetCount = 0;
|
|
186983
|
+
let autoReclaimDidMutate = false;
|
|
186984
|
+
if (toolReclaimExecutePass && alreadyMutatingThisPass && !emergencyDropEligible) {
|
|
186985
|
+
const syntheticPendingOps = buildSyntheticToolReclaimOps({
|
|
186986
|
+
db: args.db,
|
|
186987
|
+
sessionId: args.sessionId,
|
|
186988
|
+
targets: args.targets,
|
|
186989
|
+
watermark: args.sessionMeta.toolReclaimWatermark ?? 0,
|
|
186990
|
+
pendingOps
|
|
186991
|
+
});
|
|
186992
|
+
autoReclaimTargetCount = syntheticPendingOps.length;
|
|
186993
|
+
if (syntheticPendingOps.length > 0) {
|
|
186994
|
+
autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTags, undefined, [], syntheticPendingOps);
|
|
186995
|
+
if (autoReclaimDidMutate) {
|
|
186996
|
+
droppedCount += syntheticPendingOps.length;
|
|
186997
|
+
autoReclaimDidMutateThisPass = true;
|
|
186998
|
+
}
|
|
186999
|
+
}
|
|
187000
|
+
}
|
|
186661
187001
|
args.batch?.finalize();
|
|
187002
|
+
if (toolReclaimExecutePass) {
|
|
187003
|
+
const maxTagNumber = advanceToolReclaimWatermarkToCurrentMax(args.db, args.sessionId);
|
|
187004
|
+
args.sessionMeta.toolReclaimWatermark = Math.max(args.sessionMeta.toolReclaimWatermark ?? 0, maxTagNumber);
|
|
187005
|
+
}
|
|
187006
|
+
if (autoReclaimTargetCount > 0) {
|
|
187007
|
+
sessionLog(args.sessionId, `tool reclaim auto-drop: targets=${autoReclaimTargetCount} mutated=${autoReclaimDidMutate}`);
|
|
187008
|
+
}
|
|
186662
187009
|
logTransformTiming(args.sessionId, "batchFinalize:heuristics", performance.now());
|
|
186663
187010
|
if (args.sessionMeta.lastTransformError !== null) {
|
|
186664
187011
|
updateSessionMeta(args.db, args.sessionId, { lastTransformError: null });
|
|
@@ -186670,11 +187017,6 @@ async function runPostTransformPhase(args) {
|
|
|
186670
187017
|
deferredMaterializedSuccessfully = true;
|
|
186671
187018
|
heuristicsRanSuccessfully = true;
|
|
186672
187019
|
}
|
|
186673
|
-
if (args.watermark > 0) {
|
|
186674
|
-
const tWatermarkCleanup = performance.now();
|
|
186675
|
-
truncateErroredTools(args.messages, args.watermark, args.messageTagNumbers);
|
|
186676
|
-
logTransformTiming(args.sessionId, "watermarkCleanup", tWatermarkCleanup);
|
|
186677
|
-
}
|
|
186678
187020
|
if (shouldApplyPendingOps) {
|
|
186679
187021
|
pendingOpsRanSuccessfully = true;
|
|
186680
187022
|
}
|
|
@@ -186733,6 +187075,9 @@ async function runPostTransformPhase(args) {
|
|
|
186733
187075
|
hardSignals: args.m0M1.hardSignals
|
|
186734
187076
|
});
|
|
186735
187077
|
if (result.injected) {
|
|
187078
|
+
m0M1InjectedThisPass = true;
|
|
187079
|
+
m0RematerializedThisPass ||= result.m0RematerializedThisPass;
|
|
187080
|
+
m0MaterializeReason = result.decision.reason ?? m0MaterializeReason;
|
|
186736
187081
|
sessionLog(args.sessionId, `transform: injected m[0]/m[1] (rematerialized=${result.m0RematerializedThisPass}, reason=${result.decision.reason ?? "cache_hit"})`);
|
|
186737
187082
|
}
|
|
186738
187083
|
} catch (error51) {
|
|
@@ -186941,7 +187286,19 @@ async function runPostTransformPhase(args) {
|
|
|
186941
187286
|
sessionLog(args.sessionId, `sticky-injection GC: pruned ${prunedAnchors} note-nudge anchor(s), ${prunedDecisions} auto-search decision(s)`);
|
|
186942
187287
|
}
|
|
186943
187288
|
}
|
|
186944
|
-
|
|
187289
|
+
const materializeReason = m0MaterializeReason ?? (explicitMaterializedSuccessfully ? "explicit_flush" : null);
|
|
187290
|
+
const materialized = m0RematerializedThisPass || explicitMaterializedSuccessfully || deferredMaterializedSuccessfully;
|
|
187291
|
+
const bustedThisPass = args.didMutateFromFlushedStatuses || pendingOpsDidMutate || heuristicOrReasoningDidMutate || autoReclaimDidMutateThisPass || m0RematerializedThisPass || m0M1InjectedThisPass && historyWasConsumedThisPass || historyWasConsumedThisPass;
|
|
187292
|
+
return {
|
|
187293
|
+
explicitMaterializedSuccessfully,
|
|
187294
|
+
deferredMaterializedSuccessfully,
|
|
187295
|
+
materialized,
|
|
187296
|
+
materializeReason,
|
|
187297
|
+
droppedTokens,
|
|
187298
|
+
droppedCount,
|
|
187299
|
+
emergency,
|
|
187300
|
+
bustedThisPass
|
|
187301
|
+
};
|
|
186945
187302
|
}
|
|
186946
187303
|
function checkM0MutationDriftAndSignal(args) {
|
|
186947
187304
|
const currentMaxMutationId = getMaxM0MutationId(args.db, args.sessionId) ?? 0;
|
|
@@ -186976,6 +187333,12 @@ function clearMessageTokensCache(sessionId, messageId) {
|
|
|
186976
187333
|
cache.delete(messageId);
|
|
186977
187334
|
}
|
|
186978
187335
|
var recordedSessionProjectIdentity = new BoundedSessionMap(MESSAGE_TOKENS_CACHE_MAX);
|
|
187336
|
+
function deriveTaggerLoadFloor(messages, sessionId, db) {
|
|
187337
|
+
return deriveTagLoadFloor(db, sessionId, function* () {
|
|
187338
|
+
for (const message of messages)
|
|
187339
|
+
yield message.info?.id;
|
|
187340
|
+
}());
|
|
187341
|
+
}
|
|
186979
187342
|
function findLastAssistantModel2(messages) {
|
|
186980
187343
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
186981
187344
|
const info = messages[i].info;
|
|
@@ -186998,6 +187361,7 @@ function createTransform(deps) {
|
|
|
186998
187361
|
return;
|
|
186999
187362
|
}
|
|
187000
187363
|
const resolvedSessionId = sessionId;
|
|
187364
|
+
clearOpenCodePendingTransformDecision(sessionId);
|
|
187001
187365
|
logTransformTiming(sessionId, "findSessionId", startTime, `messages=${messages.length}`);
|
|
187002
187366
|
const db = deps.db;
|
|
187003
187367
|
if (deps.client !== undefined) {
|
|
@@ -187300,12 +187664,16 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
187300
187664
|
recordSessionProjectIdentity(db, sessionId, sessionProjectIdentity);
|
|
187301
187665
|
recordedSessionProjectIdentity.set(sessionId, sessionProjectIdentity);
|
|
187302
187666
|
}
|
|
187667
|
+
const taggerFloor = deriveTaggerLoadFloor(messages, sessionId, db);
|
|
187668
|
+
if (taggerFloor === 0 && messages.length > 0) {
|
|
187669
|
+
sessionLog(sessionId, `tag floor: 0 (full-scan fallback) — no leading wire message resolved a tag across ${messages.length} msgs`);
|
|
187670
|
+
}
|
|
187303
187671
|
let triggerBoundarySnapshot;
|
|
187304
187672
|
if (fullFeatureMode && historianRunnable && !sessionMeta.compartmentInProgress) {
|
|
187305
187673
|
const tTrigger = performance.now();
|
|
187306
187674
|
try {
|
|
187307
187675
|
const inMemoryTail = buildTriggerInMemoryTail(db, sessionId, extractInMemoryMessageViews(messages));
|
|
187308
|
-
const triggerResult = checkCompartmentTrigger(db, sessionId, sessionMeta, boundaryUsageForProtectedTail, sessionMeta.lastContextPercentage, boundaryExecuteThreshold, deriveTriggerBudget(boundaryContextLimit, boundaryExecuteThreshold), deps.clearReasoningAge, deps.commitClusterTrigger, undefined, boundaryContextLimit, inMemoryTail);
|
|
187676
|
+
const triggerResult = checkCompartmentTrigger(db, sessionId, sessionMeta, boundaryUsageForProtectedTail, sessionMeta.lastContextPercentage, boundaryExecuteThreshold, deriveTriggerBudget(boundaryContextLimit, boundaryExecuteThreshold), deps.clearReasoningAge, deps.commitClusterTrigger, undefined, boundaryContextLimit, inMemoryTail, taggerFloor);
|
|
187309
187677
|
if (triggerResult.shouldFire) {
|
|
187310
187678
|
sessionLog(sessionId, `compartment trigger: firing (reason=${triggerResult.reason})`);
|
|
187311
187679
|
updateSessionMeta(db, sessionId, { compartmentInProgress: true });
|
|
@@ -187347,7 +187715,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
187347
187715
|
try {
|
|
187348
187716
|
const t0 = performance.now();
|
|
187349
187717
|
const tInitFromDb = performance.now();
|
|
187350
|
-
deps.tagger.initFromDb(sessionId, db);
|
|
187718
|
+
deps.tagger.initFromDb(sessionId, db, taggerFloor);
|
|
187351
187719
|
logTransformTiming(sessionId, "tag.initFromDb", tInitFromDb);
|
|
187352
187720
|
const skipPrefixInjection = !ctxReduceEnabledEffective;
|
|
187353
187721
|
const result = tagMessages(sessionId, messages, deps.tagger, db, {
|
|
@@ -187399,7 +187767,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
187399
187767
|
const persistedReasoningWatermark = sessionMeta?.clearedReasoningThroughTag ?? 0;
|
|
187400
187768
|
if (persistedReasoningWatermark > 0) {
|
|
187401
187769
|
const tReplay = performance.now();
|
|
187402
|
-
const replayed = replayClearedReasoning(messages, reasoningByMessage, messageTagNumbers, persistedReasoningWatermark);
|
|
187770
|
+
const replayed = canUseEmptySentinels ? replayClearedReasoning(messages, reasoningByMessage, messageTagNumbers, persistedReasoningWatermark) : 0;
|
|
187403
187771
|
const replayedInline = replayStrippedInlineThinking(messages, messageTagNumbers, persistedReasoningWatermark);
|
|
187404
187772
|
if (replayed > 0 || replayedInline > 0) {
|
|
187405
187773
|
sessionLog(sessionId, `reasoning replay: cleared=${replayed} inlineStripped=${replayedInline} (watermark=${persistedReasoningWatermark})`);
|
|
@@ -187497,7 +187865,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
187497
187865
|
const wasEmergencyBlock = contextUsageEarly.percentage >= FORCE_MATERIALIZE_PERCENTAGE && compartmentPhase.justAwaitedPublication;
|
|
187498
187866
|
const historyRebuiltThisPass = wasEmergencyBlock ? compartmentPhase.rebuiltHistoryThisPass : rebuiltHistoryFromInitialPrepare || compartmentPhase.rebuiltHistoryThisPass;
|
|
187499
187867
|
const tPostProcess = performance.now();
|
|
187500
|
-
await runPostTransformPhase({
|
|
187868
|
+
const postTransformResult = await runPostTransformPhase({
|
|
187501
187869
|
sessionId,
|
|
187502
187870
|
db,
|
|
187503
187871
|
messages,
|
|
@@ -187551,6 +187919,19 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
187551
187919
|
hardSignals: m0HardSignals
|
|
187552
187920
|
}
|
|
187553
187921
|
});
|
|
187922
|
+
if (postTransformResult.bustedThisPass) {
|
|
187923
|
+
recordPendingTransformDecision(sessionId, {
|
|
187924
|
+
tsMs: Date.now(),
|
|
187925
|
+
decision: schedulerDecision,
|
|
187926
|
+
materialized: postTransformResult.materialized,
|
|
187927
|
+
materializeReason: normalizeMaterializeReason("opencode", postTransformResult.materializeReason, postTransformResult.materialized),
|
|
187928
|
+
emergency: postTransformResult.emergency,
|
|
187929
|
+
droppedTokens: postTransformResult.droppedTokens,
|
|
187930
|
+
droppedCount: postTransformResult.droppedCount,
|
|
187931
|
+
inputTokens: contextUsage.inputTokens,
|
|
187932
|
+
bustedThisPass: true
|
|
187933
|
+
});
|
|
187934
|
+
}
|
|
187554
187935
|
logTransformTiming(sessionId, "postTransformPhase", tPostProcess);
|
|
187555
187936
|
const msgTokens = getMessageTokensCache(sessionId);
|
|
187556
187937
|
let storedByMessage;
|
|
@@ -187701,6 +188082,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
187701
188082
|
const executeThresholdTokens = Math.round((resolvedContextLimit ?? 0) * resolvedExecuteThresholdPct / 100);
|
|
187702
188083
|
const usableTokens = Math.max(0, executeThresholdTokens - contextUsage.inputTokens + liveTailTokens);
|
|
187703
188084
|
resetLastNudgeCycleIfTailShrank(db, sessionId, tailToolTokens);
|
|
188085
|
+
const oldestReclaimableToolTags = getOldestActiveUnprotectedToolTags(db, sessionId, deps.protectedTags);
|
|
187704
188086
|
deps.channel1StateBySession.set(sessionId, {
|
|
187705
188087
|
tailToolTokens,
|
|
187706
188088
|
historyBudgetTokens: historyBudgetTokens ?? 0,
|
|
@@ -187709,9 +188091,10 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
187709
188091
|
lastInputTokens: contextUsage.inputTokens,
|
|
187710
188092
|
turnToolTokens: 0,
|
|
187711
188093
|
usableTokens,
|
|
187712
|
-
reducedSinceRefresh: false
|
|
188094
|
+
reducedSinceRefresh: false,
|
|
188095
|
+
oldestReclaimableToolTags
|
|
187713
188096
|
});
|
|
187714
|
-
const channel2MetricsKnown =
|
|
188097
|
+
const channel2MetricsKnown = resolvedContextLimit !== undefined && resolvedContextLimit > 0 && resolvedExecuteThresholdPct > 0;
|
|
187715
188098
|
if (channel2MetricsKnown) {
|
|
187716
188099
|
const channel2ShouldTrigger = shouldTriggerChannel2({
|
|
187717
188100
|
reclaimableTokens: tailToolTokens,
|
|
@@ -187735,6 +188118,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
187735
188118
|
}
|
|
187736
188119
|
const elapsed = (performance.now() - startTime).toFixed(1);
|
|
187737
188120
|
sessionLog(sessionId, `transform completed in ${elapsed}ms (${messages.length} messages, ${targets.size} targets, watermark: ${watermark})`);
|
|
188121
|
+
deps.maybeAutoEmbedSession?.(sessionId);
|
|
187738
188122
|
};
|
|
187739
188123
|
}
|
|
187740
188124
|
function resolveHistoryBudgetTokens(historyBudgetPercentage, contextUsage, executeThresholdPercentage, modelKey, executeThresholdTokens, resolvedContextLimit) {
|
|
@@ -187780,18 +188164,14 @@ function evictExpiredUsageEntries(contextUsageMap) {
|
|
|
187780
188164
|
}
|
|
187781
188165
|
async function deliverChannel2IfPending(deps, sessionId) {
|
|
187782
188166
|
try {
|
|
187783
|
-
try {
|
|
187784
|
-
const meta3 = getOrCreateSessionMeta(deps.db, sessionId);
|
|
187785
|
-
if (meta3.isSubagent)
|
|
187786
|
-
return;
|
|
187787
|
-
} catch {}
|
|
187788
188167
|
const baseline = deps.channel1StateBySession?.get(sessionId);
|
|
187789
188168
|
await maybeDeliverChannel2(sessionId, {
|
|
187790
188169
|
db: deps.db,
|
|
187791
188170
|
serverUrl: deps.serverUrl,
|
|
187792
188171
|
directory: deps.directory ?? ".",
|
|
187793
188172
|
reclaimableTokens: baseline ? baseline.tailToolTokens + baseline.turnToolTokens : undefined,
|
|
187794
|
-
usableTokens: baseline?.usableTokens
|
|
188173
|
+
usableTokens: baseline?.usableTokens,
|
|
188174
|
+
oldestReclaimableToolTags: baseline?.oldestReclaimableToolTags
|
|
187795
188175
|
});
|
|
187796
188176
|
} catch (error51) {
|
|
187797
188177
|
sessionLog(sessionId, "channel2 delivery wrapper failed (ignored):", error51);
|
|
@@ -187933,6 +188313,15 @@ function createEventHandler2(deps) {
|
|
|
187933
188313
|
info.tokens?.cache?.write
|
|
187934
188314
|
];
|
|
187935
188315
|
const hasUsageTokens = usageTokens.some((value) => typeof value === "number" && value > 0);
|
|
188316
|
+
const terminalAssistantUpdate = info.messageID !== undefined && hasUsageTokens && (typeof info.finish === "string" || typeof info.completedAt === "number");
|
|
188317
|
+
if (terminalAssistantUpdate && info.messageID) {
|
|
188318
|
+
scheduleOpenCodeTransformDecisionWrite({
|
|
188319
|
+
db: deps.db,
|
|
188320
|
+
sessionId: info.sessionID,
|
|
188321
|
+
messageId: info.messageID,
|
|
188322
|
+
inputTokens: (info.tokens?.input ?? 0) + (info.tokens?.cache?.read ?? 0) + (info.tokens?.cache?.write ?? 0)
|
|
188323
|
+
});
|
|
188324
|
+
}
|
|
187936
188325
|
sessionLog(info.sessionID, `event message.updated: provider=${info.providerID} model=${info.modelID} hasUsageTokens=${hasUsageTokens} tokens.input=${info.tokens?.input} cache.read=${info.tokens?.cache?.read} cache.write=${info.tokens?.cache?.write}`);
|
|
187937
188326
|
const hasKnownUsage = hasUsageTokens || deps.contextUsageMap.has(info.sessionID);
|
|
187938
188327
|
if (!hasKnownUsage) {
|
|
@@ -188090,6 +188479,7 @@ function createEventHandler2(deps) {
|
|
|
188090
188479
|
deps.onSessionDeleted?.(sessionId);
|
|
188091
188480
|
deps.contextUsageMap.delete(sessionId);
|
|
188092
188481
|
deps.tagger.cleanup(sessionId);
|
|
188482
|
+
clearTransformDecisionSession(sessionId);
|
|
188093
188483
|
clearMessageTokensCache(sessionId);
|
|
188094
188484
|
invalidateTrueRawTokenCache({ sessionId, reason: "session.deleted" });
|
|
188095
188485
|
return;
|
|
@@ -188097,6 +188487,46 @@ function createEventHandler2(deps) {
|
|
|
188097
188487
|
};
|
|
188098
188488
|
}
|
|
188099
188489
|
|
|
188490
|
+
// src/hooks/magic-context/format-embed-status.ts
|
|
188491
|
+
function formatEmbedStatusText(coverage, drain) {
|
|
188492
|
+
if (!coverage.enabled) {
|
|
188493
|
+
return "Embedding is off (no provider configured).";
|
|
188494
|
+
}
|
|
188495
|
+
const lines = [];
|
|
188496
|
+
lines.push(`Embedding — model: ${coverage.model} (${coverage.provider})`);
|
|
188497
|
+
lines.push(`This session: ${coverage.session.embedded} / ${coverage.session.total} compartments embedded`);
|
|
188498
|
+
lines.push(`Project memories: ${coverage.memories.embedded} / ${coverage.memories.total} embedded`);
|
|
188499
|
+
if (coverage.commits.gitEnabled) {
|
|
188500
|
+
lines.push(`Git commits: ${coverage.commits.embedded} / ${coverage.commits.total}`);
|
|
188501
|
+
} else {
|
|
188502
|
+
lines.push("Git commits: 0 / 0 (git indexing off)");
|
|
188503
|
+
}
|
|
188504
|
+
let drainLine = "Drain: idle";
|
|
188505
|
+
switch (drain.status) {
|
|
188506
|
+
case "running": {
|
|
188507
|
+
const e = drain.embedded ?? coverage.session.embedded;
|
|
188508
|
+
const t = drain.total ?? coverage.session.total;
|
|
188509
|
+
const failedSuffix = drain.failed && drain.failed > 0 ? ` (${drain.failed} failed)` : "";
|
|
188510
|
+
drainLine = `Drain: running ${e}/${t}${failedSuffix}`;
|
|
188511
|
+
break;
|
|
188512
|
+
}
|
|
188513
|
+
case "paused": {
|
|
188514
|
+
const e = drain.embedded ?? coverage.session.embedded;
|
|
188515
|
+
const t = drain.total ?? coverage.session.total;
|
|
188516
|
+
drainLine = `Drain: paused ${e}/${t}`;
|
|
188517
|
+
break;
|
|
188518
|
+
}
|
|
188519
|
+
case "stopped":
|
|
188520
|
+
drainLine = "Drain: stopped (provider down)";
|
|
188521
|
+
break;
|
|
188522
|
+
default:
|
|
188523
|
+
drainLine = "Drain: idle";
|
|
188524
|
+
}
|
|
188525
|
+
lines.push(drainLine);
|
|
188526
|
+
return lines.join(`
|
|
188527
|
+
`);
|
|
188528
|
+
}
|
|
188529
|
+
|
|
188100
188530
|
// src/hooks/magic-context/hook.ts
|
|
188101
188531
|
await __promiseAll([
|
|
188102
188532
|
init_inject_compartments(),
|
|
@@ -188338,7 +188768,7 @@ function maybeInjectChannel1Nudge(args, sessionId, tool, output) {
|
|
|
188338
188768
|
setLastNudgeLevel(args.db, sessionId, decision.nextLastNudgeLevel);
|
|
188339
188769
|
if (!decision.fire)
|
|
188340
188770
|
return;
|
|
188341
|
-
out.output += buildChannel1Reminder(decision.level, decision.undroppedTokens);
|
|
188771
|
+
out.output += buildChannel1Reminder(decision.level, decision.undroppedTokens, state.oldestReclaimableToolTags);
|
|
188342
188772
|
sessionLog(sessionId, `channel1 nudge fired: level=${decision.level} undropped~${Math.round(decision.undroppedTokens / 1000)}k tool=${tool}`);
|
|
188343
188773
|
}
|
|
188344
188774
|
function createToolExecuteAfterHook(args) {
|
|
@@ -188410,9 +188840,7 @@ Context is managed for you entirely automatically — there's nothing to prune a
|
|
|
188410
188840
|
var CTX_NOTE_GUIDANCE = `Use \`ctx_note\` ONLY for genuinely future concerns — something to revisit much later, not work coming up in the next few turns (that's already in your active context) and not active multi-step work (use todos for that). Magic Context preserves your full context across both compaction and restarts, so an upcoming restart or "let's come back to this later" is never a reason to take a note — nothing is lost either way. Notes you do take survive compression and resurface at natural work boundaries (after commits, historian runs, todo completion).`;
|
|
188411
188841
|
var TOOL_HISTORY_GUIDANCE = `Compressed history intentionally omits tool calls and their outputs — summaries like "I edited file X" are historian records, not patterns to replicate. In the live conversation, older tool calls and their results are cleaned up to save context — you may see your own past messages referencing actions without the corresponding tool call or result visible. This is normal context management. ALWAYS use real tool calls; never simulate, fabricate, or inline tool outputs in your text. If there is no tool result message, the action did not happen. NEVER simulate, hallucinate or claim tool calls, command output, search results, file edits, or diffs in plain text as if they actually occurred.`;
|
|
188412
188842
|
var BASE_INTRO = (protectedTags) => `Messages and tool outputs are tagged with §N§ identifiers (e.g., §1§, §42§).
|
|
188413
|
-
Use \`ctx_reduce\` to
|
|
188414
|
-
- \`drop\`: Remove entirely (best for tool outputs you already acted on).
|
|
188415
|
-
Syntax: "3-5", "1,2,9", or "1-5,8,12-15". Last ${protectedTags} tags are protected.
|
|
188843
|
+
Use \`ctx_reduce\` to mark spent tagged content as discardable and reclaim space. Marking is NOT an immediate delete — it queues the content, which stays fully visible until space is actually needed (as soon as the next turn if you're already under pressure, much later if not), so mark a tool output as soon as you're done with it rather than hoarding the call for the end of the turn. The last ${protectedTags} tags are protected (marking one just queues it until it ages out). Syntax: "3-5", "1,2,9", or "1-5,8,12-15".
|
|
188416
188844
|
Do not announce or narrate \`ctx_reduce\` drops — just call the tool silently. Saying "I'll drop these outputs" wastes tokens the user does not care about.
|
|
188417
188845
|
${CTX_NOTE_GUIDANCE}
|
|
188418
188846
|
Use \`ctx_memory\` for durable project knowledge: write what future sessions must know, update/archive/merge the memories you see in \`<project-memory>\` when they drift. Memories persist across sessions and every new session starts with them.
|
|
@@ -188431,7 +188859,7 @@ Use \`ctx_expand\` to recover the raw conversation behind a \`<compartment>\` su
|
|
|
188431
188859
|
\`ctx_search\` returns ranked results from memories, git commits, and raw message history. Use message ordinals from results with \`ctx_expand\` to retrieve surrounding conversation context.
|
|
188432
188860
|
${TOOL_HISTORY_GUIDANCE}
|
|
188433
188861
|
NEVER drop large ranges blindly (e.g., "1-50"). Review each tag before deciding.
|
|
188434
|
-
|
|
188862
|
+
Keep your user's instructions and intent — never drop a user message for its directive, even an old one. But a large block of pasted content inside a user message (logs, data dumps, long code, attachments) is fair to mark discardable once you've extracted what you need — it stays searchable via \`ctx_search\`.
|
|
188435
188863
|
NEVER drop assistant text messages unless they are exceptionally large. Your conversation messages are lightweight; only large tool outputs are worth dropping.
|
|
188436
188864
|
Before your turn finishes, consider using \`ctx_reduce\` to drop large tool outputs you no longer need.`;
|
|
188437
188865
|
var BASE_INTRO_NO_REDUCE = () => `${CTX_NOTE_GUIDANCE}
|
|
@@ -188779,7 +189207,7 @@ function createMagicContextHook(deps) {
|
|
|
188779
189207
|
}
|
|
188780
189208
|
let lastScheduleCheckMs = 0;
|
|
188781
189209
|
const getHistorianChunkTokens = () => deriveHistorianChunkTokens(resolveHistorianContextLimit(deps.config.historian?.model));
|
|
188782
|
-
const historianFallbackModels = resolveFallbackChain(
|
|
189210
|
+
const historianFallbackModels = resolveFallbackChain(deps.config.historian?.fallback_models);
|
|
188783
189211
|
const historyRefreshSessions = deps.liveSessionState?.historyRefreshSessions ?? new Set;
|
|
188784
189212
|
const deferredHistoryRefreshSessions = deps.liveSessionState?.deferredHistoryRefreshSessions ?? new Set;
|
|
188785
189213
|
try {
|
|
@@ -188852,29 +189280,55 @@ function createMagicContextHook(deps) {
|
|
|
188852
189280
|
ensureProjectRegistered: ensureProjectRegisteredFromOpenCodeDirectory,
|
|
188853
189281
|
getNotificationParams: (sid) => getLiveNotificationParams(sid, liveModelBySession, variantBySession, agentBySession)
|
|
188854
189282
|
});
|
|
188855
|
-
const executeEmbedHistory = async (sessionId) => {
|
|
189283
|
+
const executeEmbedHistory = async (sessionId, options) => {
|
|
188856
189284
|
if (deps.config.memory?.enabled === false) {
|
|
188857
189285
|
return "Memory is disabled for this project, so there is no semantic embedding to backfill.";
|
|
188858
189286
|
}
|
|
188859
189287
|
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
189288
|
+
const active = embedRunStateBySession.get(sessionId);
|
|
189289
|
+
if (active && !active.signal.aborted && !options?.signal) {
|
|
189290
|
+
return "Embedding is already running for this session.";
|
|
189291
|
+
}
|
|
188860
189292
|
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
188861
189293
|
const sessionProjectIdentity = resolveProjectIdentity(directory);
|
|
188862
|
-
|
|
188863
|
-
const
|
|
188864
|
-
|
|
188865
|
-
|
|
188866
|
-
|
|
188867
|
-
|
|
188868
|
-
|
|
188869
|
-
|
|
188870
|
-
|
|
188871
|
-
|
|
188872
|
-
|
|
188873
|
-
|
|
189294
|
+
embedPauseBySession.delete(sessionId);
|
|
189295
|
+
const prior = embedRunStateBySession.get(sessionId);
|
|
189296
|
+
if (prior)
|
|
189297
|
+
prior.abort();
|
|
189298
|
+
const controller = new AbortController;
|
|
189299
|
+
embedRunStateBySession.set(sessionId, controller);
|
|
189300
|
+
const signal = options?.signal ?? controller.signal;
|
|
189301
|
+
if (!options?.silent) {
|
|
189302
|
+
setRecompStarting({ recompProgressBySession }, sessionId, "Embedding history…", "embed");
|
|
189303
|
+
}
|
|
189304
|
+
let runFailed = 0;
|
|
189305
|
+
let outcome;
|
|
189306
|
+
try {
|
|
189307
|
+
outcome = await embedSessionCompartmentChunks(db, sessionProjectIdentity, sessionId, {
|
|
189308
|
+
signal,
|
|
189309
|
+
onProgress: ({ embedded, total }) => {
|
|
189310
|
+
const cur = recompProgressBySession.get(sessionId);
|
|
189311
|
+
if (!cur || cur.phase !== "recomp")
|
|
189312
|
+
return;
|
|
189313
|
+
recompProgressBySession.set(sessionId, {
|
|
189314
|
+
...cur,
|
|
189315
|
+
processedMessages: embedded,
|
|
189316
|
+
totalMessages: total,
|
|
189317
|
+
updatedAt: Date.now()
|
|
189318
|
+
});
|
|
189319
|
+
}
|
|
189320
|
+
});
|
|
189321
|
+
} finally {
|
|
189322
|
+
if (embedRunStateBySession.get(sessionId) === controller) {
|
|
189323
|
+
embedRunStateBySession.delete(sessionId);
|
|
188874
189324
|
}
|
|
188875
|
-
}
|
|
189325
|
+
}
|
|
189326
|
+
if ("failed" in outcome)
|
|
189327
|
+
runFailed = outcome.failed;
|
|
188876
189328
|
const terminal = (phase, message) => {
|
|
188877
|
-
|
|
189329
|
+
if (!options?.silent) {
|
|
189330
|
+
setRecompTerminal({ recompProgressBySession }, sessionId, phase, message);
|
|
189331
|
+
}
|
|
188878
189332
|
return message;
|
|
188879
189333
|
};
|
|
188880
189334
|
switch (outcome.status) {
|
|
@@ -188883,15 +189337,78 @@ function createMagicContextHook(deps) {
|
|
|
188883
189337
|
case "disabled":
|
|
188884
189338
|
return terminal("skipped", "No embedding provider is configured, so there is nothing to embed.");
|
|
188885
189339
|
case "busy":
|
|
188886
|
-
return terminal("skipped",
|
|
188887
|
-
case "aborted":
|
|
188888
|
-
|
|
189340
|
+
return terminal("skipped", "Embedding is already running for this project. Try again shortly.");
|
|
189341
|
+
case "aborted": {
|
|
189342
|
+
const cov = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
189343
|
+
const msg = `Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`;
|
|
189344
|
+
return terminal("skipped", msg);
|
|
189345
|
+
}
|
|
188889
189346
|
case "stalled":
|
|
188890
|
-
return terminal("skipped", `Embedded ${outcome.embedded} compartments; ${outcome.remaining} could not be embedded (the provider returned no result). Run /ctx-embed
|
|
189347
|
+
return terminal("skipped", `Embedded ${outcome.embedded} compartments; ${outcome.remaining} could not be embedded (the provider returned no result). Run /ctx-embed start again to retry them.`);
|
|
188891
189348
|
default:
|
|
188892
|
-
return terminal("done", `Embedded ${outcome.embedded} compartment${outcome.embedded === 1 ? "" : "s"} of history for semantic search.`);
|
|
189349
|
+
return terminal("done", `Embedded ${outcome.embedded} compartment${outcome.embedded === 1 ? "" : "s"} of history for semantic search${runFailed > 0 ? ` (${runFailed} failed)` : ""}.`);
|
|
188893
189350
|
}
|
|
188894
189351
|
};
|
|
189352
|
+
const pauseEmbedDrain = (sessionId) => {
|
|
189353
|
+
embedPauseBySession.add(sessionId);
|
|
189354
|
+
const ctrl = embedRunStateBySession.get(sessionId);
|
|
189355
|
+
if (ctrl)
|
|
189356
|
+
ctrl.abort();
|
|
189357
|
+
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
189358
|
+
const sessionProjectIdentity = resolveProjectIdentity(directory);
|
|
189359
|
+
const cov = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
189360
|
+
return `Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`;
|
|
189361
|
+
};
|
|
189362
|
+
const getEmbedStatusText = (sessionId) => {
|
|
189363
|
+
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
189364
|
+
const sessionProjectIdentity = resolveProjectIdentity(directory);
|
|
189365
|
+
const coverage = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
189366
|
+
const progress = recompProgressBySession.get(sessionId);
|
|
189367
|
+
const drainUi = getEmbedDrainUiStatus(sessionId, progress);
|
|
189368
|
+
return formatEmbedStatusText(coverage, {
|
|
189369
|
+
status: drainUi.status,
|
|
189370
|
+
embedded: progress?.processedMessages,
|
|
189371
|
+
total: progress?.totalMessages
|
|
189372
|
+
});
|
|
189373
|
+
};
|
|
189374
|
+
const maybeAutoEmbedSession = (sessionId) => {
|
|
189375
|
+
if (autoEmbedAttemptedBySession.has(sessionId))
|
|
189376
|
+
return;
|
|
189377
|
+
if (embedPauseBySession.has(sessionId))
|
|
189378
|
+
return;
|
|
189379
|
+
if (deps.config.memory?.enabled === false)
|
|
189380
|
+
return;
|
|
189381
|
+
autoEmbedAttemptedBySession.add(sessionId);
|
|
189382
|
+
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
189383
|
+
(async () => {
|
|
189384
|
+
try {
|
|
189385
|
+
await new Promise((resolve6) => setTimeout(resolve6, 0));
|
|
189386
|
+
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
189387
|
+
const sessionProjectIdentity = resolveProjectIdentity(directory);
|
|
189388
|
+
const coverage = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
189389
|
+
if (!coverage.enabled)
|
|
189390
|
+
return;
|
|
189391
|
+
const remaining = coverage.session.total - coverage.session.embedded;
|
|
189392
|
+
if (remaining <= 0)
|
|
189393
|
+
return;
|
|
189394
|
+
const notifyParams = getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession);
|
|
189395
|
+
if (!isTuiConnected(sessionId)) {
|
|
189396
|
+
const startMsg = `Embedding ${remaining} compartment${remaining === 1 ? "" : "s"} of history in the background…`;
|
|
189397
|
+
await sendIgnoredMessage(deps.client, sessionId, startMsg, {
|
|
189398
|
+
...notifyParams
|
|
189399
|
+
});
|
|
189400
|
+
}
|
|
189401
|
+
const summary = await executeEmbedHistory(sessionId);
|
|
189402
|
+
if (!isTuiConnected(sessionId)) {
|
|
189403
|
+
await sendIgnoredMessage(deps.client, sessionId, summary, {
|
|
189404
|
+
...notifyParams
|
|
189405
|
+
});
|
|
189406
|
+
}
|
|
189407
|
+
} catch (error51) {
|
|
189408
|
+
log("[magic-context] auto-embed drain failed:", error51);
|
|
189409
|
+
}
|
|
189410
|
+
})();
|
|
189411
|
+
};
|
|
188895
189412
|
const sidekickRunnable = isSidekickRunnable(deps.config);
|
|
188896
189413
|
const sidekickConfig = sidekickRunnable ? deps.config.sidekick : undefined;
|
|
188897
189414
|
const transform2 = createTransform({
|
|
@@ -188953,7 +189470,8 @@ function createMagicContextHook(deps) {
|
|
|
188953
189470
|
cavemanTextCompression: ctxReduceEnabled === false && deps.config.caveman_text_compression?.enabled === true ? {
|
|
188954
189471
|
enabled: true,
|
|
188955
189472
|
minChars: deps.config.caveman_text_compression.min_chars ?? 500
|
|
188956
|
-
} : undefined
|
|
189473
|
+
} : undefined,
|
|
189474
|
+
maybeAutoEmbedSession
|
|
188957
189475
|
});
|
|
188958
189476
|
const eventHandler = createEventHandler2({
|
|
188959
189477
|
contextUsageMap,
|
|
@@ -188982,6 +189500,7 @@ function createMagicContextHook(deps) {
|
|
|
188982
189500
|
recompProgressBySession.delete(sessionId);
|
|
188983
189501
|
internalChildSessions.delete(sessionId);
|
|
188984
189502
|
channel1StateBySession.delete(sessionId);
|
|
189503
|
+
clearEmbedSessionState(sessionId);
|
|
188985
189504
|
}
|
|
188986
189505
|
});
|
|
188987
189506
|
const runDreamQueueInBackground = () => {
|
|
@@ -189016,7 +189535,7 @@ function createMagicContextHook(deps) {
|
|
|
189016
189535
|
token_budget: dreaming.pin_key_files.token_budget,
|
|
189017
189536
|
min_reads: dreaming.pin_key_files.min_reads
|
|
189018
189537
|
} : undefined,
|
|
189019
|
-
fallbackModels: resolveFallbackChain(
|
|
189538
|
+
fallbackModels: resolveFallbackChain(dreaming.fallback_models),
|
|
189020
189539
|
projectIdentity: projectPath
|
|
189021
189540
|
}).catch((error51) => {
|
|
189022
189541
|
log("[dreamer] scheduled queue processing failed:", error51);
|
|
@@ -189047,6 +189566,8 @@ function createMagicContextHook(deps) {
|
|
|
189047
189566
|
executeRecomp: historianRunnable ? async (sessionId, options) => runManagedRecomp(buildManagedRecompCtx(sessionId), sessionId, options) : undefined,
|
|
189048
189567
|
runUpgrade: historianRunnable ? async (sessionId) => runManagedUpgrade(buildManagedRecompCtx(sessionId), sessionId) : undefined,
|
|
189049
189568
|
executeEmbedHistory,
|
|
189569
|
+
pauseEmbedDrain,
|
|
189570
|
+
getEmbedStatusText,
|
|
189050
189571
|
sendNotification: async (sessionId, text, params) => {
|
|
189051
189572
|
await sendIgnoredMessage(deps.client, sessionId, text, {
|
|
189052
189573
|
...getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession),
|
|
@@ -189073,7 +189594,7 @@ function createMagicContextHook(deps) {
|
|
|
189073
189594
|
token_budget: dreamerConfig.pin_key_files.token_budget,
|
|
189074
189595
|
min_reads: dreamerConfig.pin_key_files.min_reads
|
|
189075
189596
|
} : undefined,
|
|
189076
|
-
fallbackModels: resolveFallbackChain(
|
|
189597
|
+
fallbackModels: resolveFallbackChain(dreamerConfig.fallback_models)
|
|
189077
189598
|
} : undefined
|
|
189078
189599
|
});
|
|
189079
189600
|
const systemPromptHash = createSystemPromptHashHandler({
|
|
@@ -189259,6 +189780,7 @@ function truncateError(name2, code, message, maxLen = 240) {
|
|
|
189259
189780
|
|
|
189260
189781
|
// src/plugin/rpc-handlers.ts
|
|
189261
189782
|
init_project_identity();
|
|
189783
|
+
init_project_embedding_registry();
|
|
189262
189784
|
init_tool_definition_tokens();
|
|
189263
189785
|
await init_storage();
|
|
189264
189786
|
|
|
@@ -189979,6 +190501,26 @@ function buildStatusDetail(db, sessionId, directory, modelKey, config2, liveSess
|
|
|
189979
190501
|
}
|
|
189980
190502
|
return detail;
|
|
189981
190503
|
}
|
|
190504
|
+
function buildEmbedDetail(db, sessionId, dir, liveSessionState) {
|
|
190505
|
+
const projectIdentity = resolveProjectIdentity(dir);
|
|
190506
|
+
const coverage = getEmbeddingCoverageStatus(db, projectIdentity, sessionId);
|
|
190507
|
+
const progress = liveSessionState.recompProgressBySession.get(sessionId);
|
|
190508
|
+
const drainUi = getEmbedDrainUiStatus(sessionId, progress);
|
|
190509
|
+
const statusText = formatEmbedStatusText(coverage, {
|
|
190510
|
+
status: drainUi.status,
|
|
190511
|
+
embedded: progress?.processedMessages,
|
|
190512
|
+
total: progress?.totalMessages
|
|
190513
|
+
});
|
|
190514
|
+
return {
|
|
190515
|
+
enabled: coverage.enabled,
|
|
190516
|
+
model: coverage.model,
|
|
190517
|
+
provider: coverage.provider,
|
|
190518
|
+
session: coverage.session,
|
|
190519
|
+
memories: coverage.memories,
|
|
190520
|
+
commits: coverage.commits,
|
|
190521
|
+
statusText
|
|
190522
|
+
};
|
|
190523
|
+
}
|
|
189982
190524
|
function registerRpcHandlers(rpcServer, args) {
|
|
189983
190525
|
const { directory, config: config2, liveSessionState } = args;
|
|
189984
190526
|
const rawConfig = config2;
|
|
@@ -190001,6 +190543,19 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
190001
190543
|
return { error: "unavailable" };
|
|
190002
190544
|
return buildStatusDetail(db, sessionId, dir, modelKey, rawConfig, liveSessionState, injectionBudgetTokens);
|
|
190003
190545
|
});
|
|
190546
|
+
rpcServer.handle("embed-detail", async (params) => {
|
|
190547
|
+
const sessionId = String(params.sessionId ?? "");
|
|
190548
|
+
const dir = String(params.directory ?? directory);
|
|
190549
|
+
const db = getDb();
|
|
190550
|
+
if (!db || !sessionId)
|
|
190551
|
+
return { error: "unavailable" };
|
|
190552
|
+
try {
|
|
190553
|
+
return buildEmbedDetail(db, sessionId, dir, liveSessionState);
|
|
190554
|
+
} catch (err) {
|
|
190555
|
+
log("[rpc] embed-detail error:", err);
|
|
190556
|
+
return { error: "unavailable" };
|
|
190557
|
+
}
|
|
190558
|
+
});
|
|
190004
190559
|
rpcServer.handle("compartment-count", async (params) => {
|
|
190005
190560
|
const sessionId = String(params.sessionId ?? "");
|
|
190006
190561
|
const db = getDb();
|
|
@@ -190015,8 +190570,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
190015
190570
|
});
|
|
190016
190571
|
const buildManagedCtx = async (db) => {
|
|
190017
190572
|
const { deriveHistorianChunkTokens: deriveHistorianChunkTokens2, resolveHistorianContextLimit: resolveHistorianContextLimit2 } = await Promise.resolve().then(() => (init_derive_budgets(), exports_derive_budgets));
|
|
190018
|
-
const { resolveFallbackChain: resolveFallbackChain2 } = await Promise.resolve().then(() =>
|
|
190019
|
-
const { HISTORIAN_AGENT: HISTORIAN_AGENT2 } = await Promise.resolve().then(() => exports_historian);
|
|
190573
|
+
const { resolveFallbackChain: resolveFallbackChain2 } = await Promise.resolve().then(() => exports_resolve_fallbacks);
|
|
190020
190574
|
const DEFAULT_HISTORIAN_TIMEOUT_MS2 = 600000;
|
|
190021
190575
|
return {
|
|
190022
190576
|
client: args.client,
|
|
@@ -190027,7 +190581,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
190027
190581
|
historianTimeoutMs: config2.historian_timeout_ms ?? DEFAULT_HISTORIAN_TIMEOUT_MS2,
|
|
190028
190582
|
memoryEnabled: config2.memory?.enabled ?? true,
|
|
190029
190583
|
autoPromote: config2.memory?.auto_promote ?? true,
|
|
190030
|
-
fallbackModels: resolveFallbackChain2(
|
|
190584
|
+
fallbackModels: resolveFallbackChain2(config2.historian?.fallback_models),
|
|
190031
190585
|
runMigration: config2.memory?.enabled !== false && !!config2.historian?.model,
|
|
190032
190586
|
userMemoriesEnabled: config2.dreamer?.user_memories?.enabled === true,
|
|
190033
190587
|
historianTwoPass: config2.historian?.two_pass === true,
|
|
@@ -190123,27 +190677,225 @@ Older parts of this session are summarized into <compartment> blocks inside <ses
|
|
|
190123
190677
|
|
|
190124
190678
|
ctx_expand(start=120, end=245) ← the compartment's own start/end attributes
|
|
190125
190679
|
|
|
190126
|
-
Returns the raw transcript as [N] U:/A: lines, capped at ~15K tokens; an oversized range returns the head and tells you where to continue. Also works with ordinals from ctx_search message results — expand a window around a hit (e.g. start=N-10, end=N+5). Ranges after the last compartment are your live tail — already visible in context, not expandable
|
|
190680
|
+
Returns the raw transcript as [N] U:/A: lines, capped at ~15K tokens; an oversized range returns the head and tells you where to continue. Also works with ordinals from ctx_search message results — expand a window around a hit (e.g. start=N-10, end=N+5). Ranges after the last compartment are your live tail — already visible in context, not expandable.
|
|
190681
|
+
|
|
190682
|
+
Two recovery modes for finer detail:
|
|
190683
|
+
- ctx_expand(start=120, end=245, verbose=true) — lists each message SEPARATELY with its ordinal [N] and a per-part preview (each tool call shown with its output size). Use this to find the exact message or tool call you want, then recover it in full by ordinal.
|
|
190684
|
+
- ctx_expand(message=138) — returns the FULL untruncated content of the message at that ordinal: every text part, and every tool call's complete input + output, read from stored history. This is the cheap way to get back a tool output you dropped with ctx_reduce — the original is still in storage even though the wire shows [dropped §N§]. If the message was deleted from history (session prune/revert), it says so.`;
|
|
190127
190685
|
var CTX_EXPAND_TOKEN_BUDGET = 15000;
|
|
190128
190686
|
|
|
190687
|
+
// src/tools/ctx-expand/render.ts
|
|
190688
|
+
init_read_session_formatting();
|
|
190689
|
+
await init_read_session_chunk();
|
|
190690
|
+
function isRecord3(value) {
|
|
190691
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
190692
|
+
}
|
|
190693
|
+
function roleLabel(role) {
|
|
190694
|
+
if (role === "assistant")
|
|
190695
|
+
return "A (assistant)";
|
|
190696
|
+
if (role === "user")
|
|
190697
|
+
return "U (user)";
|
|
190698
|
+
return role;
|
|
190699
|
+
}
|
|
190700
|
+
function truncate2(value, max) {
|
|
190701
|
+
const t = value.trim();
|
|
190702
|
+
return t.length <= max ? t : `${t.slice(0, max)}…`;
|
|
190703
|
+
}
|
|
190704
|
+
function keyArg(input) {
|
|
190705
|
+
if (!input)
|
|
190706
|
+
return "";
|
|
190707
|
+
for (const k of ["filePath", "path", "pattern", "query", "symbol", "module", "action"]) {
|
|
190708
|
+
const v = input[k];
|
|
190709
|
+
if (typeof v === "string" && v.length > 0)
|
|
190710
|
+
return truncate2(v, 60);
|
|
190711
|
+
}
|
|
190712
|
+
if (typeof input.description === "string")
|
|
190713
|
+
return truncate2(input.description, 60);
|
|
190714
|
+
return "";
|
|
190715
|
+
}
|
|
190716
|
+
function asToolPart(part) {
|
|
190717
|
+
const type = typeof part.type === "string" ? part.type : "";
|
|
190718
|
+
if (type === "tool") {
|
|
190719
|
+
const state = isRecord3(part.state) ? part.state : null;
|
|
190720
|
+
const output = state && typeof state.output === "string" ? state.output : state && state.output != null ? JSON.stringify(state.output) : null;
|
|
190721
|
+
const metadata = state && isRecord3(state.metadata) ? state.metadata : null;
|
|
190722
|
+
const title = state && typeof state.title === "string" && state.title || metadata && typeof metadata.title === "string" && metadata.title || null;
|
|
190723
|
+
return {
|
|
190724
|
+
name: typeof part.tool === "string" ? part.tool : "tool",
|
|
190725
|
+
callId: typeof part.callID === "string" ? part.callID : "",
|
|
190726
|
+
title,
|
|
190727
|
+
input: state && isRecord3(state.input) ? state.input : null,
|
|
190728
|
+
output
|
|
190729
|
+
};
|
|
190730
|
+
}
|
|
190731
|
+
if (type === "tool_use") {
|
|
190732
|
+
return {
|
|
190733
|
+
name: typeof part.name === "string" ? part.name : "tool",
|
|
190734
|
+
callId: typeof part.id === "string" ? part.id : "",
|
|
190735
|
+
title: null,
|
|
190736
|
+
input: isRecord3(part.input) ? part.input : null,
|
|
190737
|
+
output: null
|
|
190738
|
+
};
|
|
190739
|
+
}
|
|
190740
|
+
if (type === "tool_result") {
|
|
190741
|
+
const content = part.content;
|
|
190742
|
+
const output = typeof content === "string" ? content : content != null ? JSON.stringify(content) : null;
|
|
190743
|
+
return {
|
|
190744
|
+
name: "tool_result",
|
|
190745
|
+
callId: typeof part.tool_use_id === "string" ? part.tool_use_id : "",
|
|
190746
|
+
title: null,
|
|
190747
|
+
input: null,
|
|
190748
|
+
output
|
|
190749
|
+
};
|
|
190750
|
+
}
|
|
190751
|
+
return null;
|
|
190752
|
+
}
|
|
190753
|
+
function textOf(part) {
|
|
190754
|
+
if (part.type === "text" && typeof part.text === "string")
|
|
190755
|
+
return part.text;
|
|
190756
|
+
return null;
|
|
190757
|
+
}
|
|
190758
|
+
function reasoningOf(part) {
|
|
190759
|
+
if ((part.type === "reasoning" || part.type === "thinking") && typeof part.text === "string") {
|
|
190760
|
+
return part.text;
|
|
190761
|
+
}
|
|
190762
|
+
return null;
|
|
190763
|
+
}
|
|
190764
|
+
function renderPartPreview(part) {
|
|
190765
|
+
if (!isRecord3(part))
|
|
190766
|
+
return null;
|
|
190767
|
+
const text = textOf(part);
|
|
190768
|
+
if (text !== null) {
|
|
190769
|
+
const t = truncate2(text, 200);
|
|
190770
|
+
return t.length > 0 ? ` • ${t}` : null;
|
|
190771
|
+
}
|
|
190772
|
+
const tool = asToolPart(part);
|
|
190773
|
+
if (tool) {
|
|
190774
|
+
const arg = keyArg(tool.input);
|
|
190775
|
+
const head = arg ? `${tool.name}(${arg})` : tool.name;
|
|
190776
|
+
return tool.output !== null ? ` • tool ${head} → output ~${estimateTokens(tool.output)} tok` : ` • tool ${head}`;
|
|
190777
|
+
}
|
|
190778
|
+
const reasoning = reasoningOf(part);
|
|
190779
|
+
if (reasoning !== null)
|
|
190780
|
+
return ` • [reasoning] ${truncate2(reasoning, 120)}`;
|
|
190781
|
+
const type = typeof part.type === "string" ? part.type : "part";
|
|
190782
|
+
if (type === "file")
|
|
190783
|
+
return " • [file]";
|
|
190784
|
+
if (type === "step-start" || type === "step-finish")
|
|
190785
|
+
return null;
|
|
190786
|
+
return ` • [${type}]`;
|
|
190787
|
+
}
|
|
190788
|
+
function renderPartFull(part) {
|
|
190789
|
+
if (!isRecord3(part))
|
|
190790
|
+
return null;
|
|
190791
|
+
const text = textOf(part);
|
|
190792
|
+
if (text !== null) {
|
|
190793
|
+
return text.trim().length > 0 ? ` [text]
|
|
190794
|
+
${text}` : null;
|
|
190795
|
+
}
|
|
190796
|
+
const tool = asToolPart(part);
|
|
190797
|
+
if (tool) {
|
|
190798
|
+
const lines = [];
|
|
190799
|
+
const idSuffix = tool.callId ? ` #${tool.callId}` : "";
|
|
190800
|
+
lines.push(` [tool: ${tool.name}${idSuffix}]`);
|
|
190801
|
+
if (tool.title && tool.title.trim().length > 0) {
|
|
190802
|
+
lines.push(` description: ${tool.title.trim()}`);
|
|
190803
|
+
}
|
|
190804
|
+
if (tool.input)
|
|
190805
|
+
lines.push(` input: ${JSON.stringify(tool.input)}`);
|
|
190806
|
+
if (tool.output !== null)
|
|
190807
|
+
lines.push(` output:
|
|
190808
|
+
${tool.output}`);
|
|
190809
|
+
return lines.join(`
|
|
190810
|
+
`);
|
|
190811
|
+
}
|
|
190812
|
+
const type = typeof part.type === "string" ? part.type : "part";
|
|
190813
|
+
if (type === "file") {
|
|
190814
|
+
const name2 = typeof part.filename === "string" && part.filename || typeof part.url === "string" && part.url || "";
|
|
190815
|
+
return ` [file]${name2 ? ` ${name2}` : ""}`;
|
|
190816
|
+
}
|
|
190817
|
+
return null;
|
|
190818
|
+
}
|
|
190819
|
+
function renderMessageByOrdinal(sessionId, ordinal) {
|
|
190820
|
+
const msg = readRawSessionMessages(sessionId).find((m) => m.ordinal === ordinal);
|
|
190821
|
+
if (!msg) {
|
|
190822
|
+
return `No message at ordinal ${ordinal} in this session's stored history — it was deleted ` + `(session prune/revert) or the ordinal is wrong, so it can't be recovered. ` + `Re-run the tool if you still need the data.`;
|
|
190823
|
+
}
|
|
190824
|
+
const rendered = msg.parts.map(renderPartFull).filter((l) => l !== null);
|
|
190825
|
+
const lines = [`[${msg.ordinal}] ${roleLabel(msg.role)} — full recovery:`, ""];
|
|
190826
|
+
if (rendered.length === 0) {
|
|
190827
|
+
lines.push(" (no recoverable content — message had only structural/reasoning parts)");
|
|
190828
|
+
} else {
|
|
190829
|
+
lines.push(...rendered);
|
|
190830
|
+
}
|
|
190831
|
+
return lines.join(`
|
|
190832
|
+
`);
|
|
190833
|
+
}
|
|
190834
|
+
function renderVerboseRange(sessionId, start, end, tokenBudget) {
|
|
190835
|
+
const messages = readRawSessionMessages(sessionId).filter((m) => m.ordinal >= start && m.ordinal <= end);
|
|
190836
|
+
const out = [];
|
|
190837
|
+
let usedTokens = 0;
|
|
190838
|
+
let lastOrdinal = start - 1;
|
|
190839
|
+
let truncated = false;
|
|
190840
|
+
for (const msg of messages) {
|
|
190841
|
+
const header = `[${msg.ordinal}] ${roleLabel(msg.role)}`;
|
|
190842
|
+
const partLines = msg.parts.map(renderPartPreview).filter((l) => l !== null);
|
|
190843
|
+
const block = partLines.length > 0 ? `${header}
|
|
190844
|
+
${partLines.join(`
|
|
190845
|
+
`)}` : header;
|
|
190846
|
+
const blockTokens = estimateTokens(block);
|
|
190847
|
+
if (usedTokens + blockTokens > tokenBudget && out.length > 0) {
|
|
190848
|
+
truncated = true;
|
|
190849
|
+
break;
|
|
190850
|
+
}
|
|
190851
|
+
out.push(block);
|
|
190852
|
+
usedTokens += blockTokens;
|
|
190853
|
+
lastOrdinal = msg.ordinal;
|
|
190854
|
+
}
|
|
190855
|
+
return { text: out.join(`
|
|
190856
|
+
|
|
190857
|
+
`), lastOrdinal, truncated };
|
|
190858
|
+
}
|
|
190859
|
+
|
|
190129
190860
|
// src/tools/ctx-expand/tools.ts
|
|
190130
190861
|
function createCtxExpandTool(deps) {
|
|
190131
190862
|
return tool({
|
|
190132
190863
|
description: CTX_EXPAND_DESCRIPTION,
|
|
190133
190864
|
args: {
|
|
190134
|
-
start: tool.schema.number().describe(`First message ordinal to expand — a compartment's start="N" attribute, or an ordinal from a ctx_search message hit`),
|
|
190135
|
-
end: tool.schema.number().describe(`Last message ordinal to expand (inclusive) — a compartment's end="M" attribute`)
|
|
190865
|
+
start: tool.schema.number().optional().describe(`First message ordinal to expand — a compartment's start="N" attribute, or an ordinal from a ctx_search message hit`),
|
|
190866
|
+
end: tool.schema.number().optional().describe(`Last message ordinal to expand (inclusive) — a compartment's end="M" attribute`),
|
|
190867
|
+
verbose: tool.schema.boolean().optional().describe("With start/end: list each message separately with its ordinal [N] and per-part preview (each tool call shown with its output size), so you can pick one to recover in full by ordinal."),
|
|
190868
|
+
message: tool.schema.number().optional().describe("Full untruncated recovery of ONE message by its ordinal (every text part + every tool call's complete input/output). Use an ordinal from a compartment, ctx_search hit, or verbose range. Recovers a tool output you dropped with ctx_reduce.")
|
|
190136
190869
|
},
|
|
190137
190870
|
async execute(args, toolContext) {
|
|
190138
190871
|
const sessionId = toolContext.sessionID;
|
|
190872
|
+
if (typeof args.message === "number" && args.message >= 1) {
|
|
190873
|
+
return renderMessageByOrdinal(sessionId, args.message);
|
|
190874
|
+
}
|
|
190139
190875
|
if (!args.start || !args.end || args.start < 1 || args.end < args.start) {
|
|
190140
|
-
return "Error: start and end
|
|
190876
|
+
return "Error: provide either message=<ordinal>, or start and end (positive integers, start <= end).";
|
|
190141
190877
|
}
|
|
190142
190878
|
const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
190143
190879
|
if (lastCompartmentEnd >= 0 && args.start > lastCompartmentEnd) {
|
|
190144
190880
|
return `Range ${args.start}-${args.end} is entirely within the live tail (after the last compacted message ${lastCompartmentEnd}); those messages are already visible in context.`;
|
|
190145
190881
|
}
|
|
190146
190882
|
const effectiveEnd = lastCompartmentEnd >= 0 ? Math.min(args.end, lastCompartmentEnd) : args.end;
|
|
190883
|
+
if (args.verbose === true) {
|
|
190884
|
+
const v = renderVerboseRange(sessionId, args.start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET);
|
|
190885
|
+
if (!v.text) {
|
|
190886
|
+
return `No messages found in range ${args.start}-${effectiveEnd}. The range may be outside this session's history.`;
|
|
190887
|
+
}
|
|
190888
|
+
const out = [
|
|
190889
|
+
`Messages ${args.start}-${v.lastOrdinal} (verbose). Recover any one in full with ctx_expand(message=<ordinal>):`,
|
|
190890
|
+
"",
|
|
190891
|
+
v.text
|
|
190892
|
+
];
|
|
190893
|
+
if (v.truncated) {
|
|
190894
|
+
out.push("", `Truncated at message ${v.lastOrdinal} (budget: ~${CTX_EXPAND_TOKEN_BUDGET} tokens). Call again with start=${v.lastOrdinal + 1} end=${effectiveEnd} verbose=true for more.`);
|
|
190895
|
+
}
|
|
190896
|
+
return out.join(`
|
|
190897
|
+
`);
|
|
190898
|
+
}
|
|
190147
190899
|
const chunk = readSessionChunk(sessionId, CTX_EXPAND_TOKEN_BUDGET, args.start, effectiveEnd + 1);
|
|
190148
190900
|
if (!chunk.text || chunk.messageCount === 0) {
|
|
190149
190901
|
return `No messages found in range ${args.start}-${args.end}. The range may be outside this session's history.`;
|
|
@@ -190181,6 +190933,7 @@ Actions:
|
|
|
190181
190933
|
Example: ctx_memory(action="write", category="CONSTRAINTS", content="Pi stores sessions as JSONL under ~/.pi/agent/sessions/, not SQLite")`;
|
|
190182
190934
|
var DEFAULT_SEARCH_LIMIT2 = 10;
|
|
190183
190935
|
// src/tools/ctx-memory/tools.ts
|
|
190936
|
+
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
190184
190937
|
init_memory();
|
|
190185
190938
|
init_embedding();
|
|
190186
190939
|
init_embedding_cache();
|
|
@@ -190188,7 +190941,6 @@ init_normalize_hash();
|
|
|
190188
190941
|
init_workspaces();
|
|
190189
190942
|
init_logger();
|
|
190190
190943
|
await init_storage();
|
|
190191
|
-
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
190192
190944
|
|
|
190193
190945
|
// src/tools/ctx-memory/types.ts
|
|
190194
190946
|
var CTX_MEMORY_ACTIONS = ["write", "archive", "update", "merge"];
|
|
@@ -190837,15 +191589,16 @@ function createCtxNoteTools(deps) {
|
|
|
190837
191589
|
};
|
|
190838
191590
|
}
|
|
190839
191591
|
// src/tools/ctx-reduce/constants.ts
|
|
190840
|
-
var CTX_REDUCE_DESCRIPTION = `
|
|
190841
|
-
|
|
190842
|
-
|
|
190843
|
-
|
|
190844
|
-
-
|
|
190845
|
-
-
|
|
190846
|
-
|
|
190847
|
-
|
|
190848
|
-
|
|
191592
|
+
var CTX_REDUCE_DESCRIPTION = `Mark spent tagged content as discardable to reclaim context space. This is NOT an immediate delete. Use §N§ identifiers visible in the conversation. The \`drop\` param accepts ranges: "3-5", "1,2,9", "1-5,8".
|
|
191593
|
+
|
|
191594
|
+
How it works:
|
|
191595
|
+
- Marking QUEUES content for release. It stays fully visible to you until context space is actually needed — which may be as soon as the next turn if you are already under pressure, or many turns later if not. So mark spent outputs as soon as you finish with them; don't hoard the call for the end of the turn.
|
|
191596
|
+
- The newest tags are protected: marking one just queues it until it ages out of the recent window, so marking recent output is harmless.
|
|
191597
|
+
- When content is finally released it becomes a short placeholder, and re-running the tool is the only way to get it back. So mark only what you are genuinely DONE with — the test is "have I extracted what I need from this?", not "is it safe / do I have time before it drops?".
|
|
191598
|
+
|
|
191599
|
+
Mark discardable once processed: large outputs you've summarized, repeated or redundant dumps, data written to disk, status/log output that only confirmed an expected state.
|
|
191600
|
+
Keep: user messages, unresolved errors, raw evidence you haven't extracted yet, and outputs whose exact wording may matter later.
|
|
191601
|
+
Never blanket-mark large ranges (e.g. "1-50") — review what each tag holds first.`;
|
|
190849
191602
|
// src/tools/ctx-reduce/tools.ts
|
|
190850
191603
|
import { tool as tool4 } from "@opencode-ai/plugin";
|
|
190851
191604
|
|
|
@@ -191112,7 +191865,7 @@ function createCtxSearchTool(deps) {
|
|
|
191112
191865
|
memoryEnabled,
|
|
191113
191866
|
embeddingEnabled,
|
|
191114
191867
|
embedQuery: async (text, signal) => {
|
|
191115
|
-
const result = await embedTextForProject(projectPath, text, signal);
|
|
191868
|
+
const result = await embedTextForProject(projectPath, text, signal, "query");
|
|
191116
191869
|
return result?.vector ?? null;
|
|
191117
191870
|
},
|
|
191118
191871
|
isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
|
|
@@ -191215,14 +191968,13 @@ function createToolRegistry(args) {
|
|
|
191215
191968
|
init_conflict_detector();
|
|
191216
191969
|
init_data_path();
|
|
191217
191970
|
init_logger();
|
|
191218
|
-
init_model_requirements();
|
|
191219
191971
|
init_models_dev_cache();
|
|
191220
191972
|
|
|
191221
191973
|
// src/shared/rpc-server.ts
|
|
191222
191974
|
init_logger();
|
|
191223
191975
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
191224
191976
|
import {
|
|
191225
|
-
mkdirSync as
|
|
191977
|
+
mkdirSync as mkdirSync7,
|
|
191226
191978
|
readdirSync,
|
|
191227
191979
|
readFileSync as readFileSync12,
|
|
191228
191980
|
renameSync as renameSync2,
|
|
@@ -191230,20 +191982,20 @@ import {
|
|
|
191230
191982
|
writeFileSync as writeFileSync5
|
|
191231
191983
|
} from "node:fs";
|
|
191232
191984
|
import { createServer } from "node:http";
|
|
191233
|
-
import { dirname as
|
|
191985
|
+
import { dirname as dirname4 } from "node:path";
|
|
191234
191986
|
|
|
191235
191987
|
// src/shared/rpc-utils.ts
|
|
191236
191988
|
import { createHash as createHash13 } from "node:crypto";
|
|
191237
|
-
import { join as
|
|
191989
|
+
import { join as join19 } from "node:path";
|
|
191238
191990
|
function projectHash(directory) {
|
|
191239
191991
|
const normalized = directory.replace(/\/+$/, "");
|
|
191240
191992
|
return createHash13("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
191241
191993
|
}
|
|
191242
191994
|
function rpcPortDir(storageDir, directory) {
|
|
191243
|
-
return
|
|
191995
|
+
return join19(storageDir, "rpc", projectHash(directory));
|
|
191244
191996
|
}
|
|
191245
191997
|
function rpcPortFilePath(storageDir, directory, pid = process.pid) {
|
|
191246
|
-
return
|
|
191998
|
+
return join19(rpcPortDir(storageDir, directory), `port-${pid}.json`);
|
|
191247
191999
|
}
|
|
191248
192000
|
function isPidAlive(pid) {
|
|
191249
192001
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
@@ -191327,8 +192079,8 @@ class MagicContextRpcServer {
|
|
|
191327
192079
|
this.server = server2;
|
|
191328
192080
|
try {
|
|
191329
192081
|
this.warnIfOtherLiveInstance();
|
|
191330
|
-
const dir =
|
|
191331
|
-
|
|
192082
|
+
const dir = dirname4(this.portFilePath);
|
|
192083
|
+
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
191332
192084
|
const tmpPath = `${this.portFilePath}.tmp`;
|
|
191333
192085
|
writeFileSync5(tmpPath, JSON.stringify({
|
|
191334
192086
|
port: this.port,
|
|
@@ -191428,6 +192180,9 @@ class MagicContextRpcServer {
|
|
|
191428
192180
|
}
|
|
191429
192181
|
|
|
191430
192182
|
// src/index.ts
|
|
192183
|
+
var HISTORIAN_MAX_STEPS = 40;
|
|
192184
|
+
var SIDEKICK_MAX_STEPS = 40;
|
|
192185
|
+
var DREAMER_MAX_STEPS = 150;
|
|
191431
192186
|
var plugin = async (ctx) => {
|
|
191432
192187
|
const pluginConfig = loadPluginConfig(ctx.directory);
|
|
191433
192188
|
setSqlitePragmaConfig({
|
|
@@ -191620,12 +192375,13 @@ var plugin = async (ctx) => {
|
|
|
191620
192375
|
await hooks.magicContext?.["experimental.text.complete"]?.(input, output);
|
|
191621
192376
|
},
|
|
191622
192377
|
config: async (config2) => {
|
|
191623
|
-
const buildHiddenAgentConfig = (
|
|
192378
|
+
const buildHiddenAgentConfig = (prompt, allowedTools, maxSteps, overrides) => {
|
|
191624
192379
|
const { permission: overridePermission, ...restOverrides } = overrides ?? {};
|
|
191625
192380
|
const basePermission = buildAllowOnlyPermission(allowedTools);
|
|
191626
192381
|
return {
|
|
191627
192382
|
prompt,
|
|
191628
|
-
|
|
192383
|
+
steps: maxSteps,
|
|
192384
|
+
maxSteps,
|
|
191629
192385
|
...restOverrides,
|
|
191630
192386
|
permission: {
|
|
191631
192387
|
...basePermission,
|
|
@@ -191647,6 +192403,7 @@ var plugin = async (ctx) => {
|
|
|
191647
192403
|
max_runtime_minutes: _max,
|
|
191648
192404
|
tasks: _tasks,
|
|
191649
192405
|
task_timeout_minutes: _tto,
|
|
192406
|
+
thinking_level: _thinkingLevel,
|
|
191650
192407
|
...agentOverrides
|
|
191651
192408
|
} = pluginConfig.dreamer;
|
|
191652
192409
|
return agentOverrides;
|
|
@@ -191655,20 +192412,28 @@ var plugin = async (ctx) => {
|
|
|
191655
192412
|
const {
|
|
191656
192413
|
timeout_ms: _timeoutMs,
|
|
191657
192414
|
system_prompt: _systemPrompt,
|
|
192415
|
+
thinking_level: _thinkingLevel,
|
|
191658
192416
|
...agentOverrides
|
|
191659
192417
|
} = pluginConfig.sidekick;
|
|
191660
192418
|
return agentOverrides;
|
|
191661
192419
|
})() : undefined;
|
|
191662
192420
|
const historianAgentOverrides = pluginConfig.historian ? (() => {
|
|
191663
|
-
const {
|
|
192421
|
+
const {
|
|
192422
|
+
two_pass: _twoPass,
|
|
192423
|
+
disallowed_tools: _disallowedTools,
|
|
192424
|
+
thinking_level: _thinkingLevel,
|
|
192425
|
+
...agentOverrides
|
|
192426
|
+
} = pluginConfig.historian;
|
|
191664
192427
|
return agentOverrides;
|
|
191665
192428
|
})() : undefined;
|
|
192429
|
+
const historianDisallowed = pluginConfig.historian?.disallowed_tools ?? [];
|
|
192430
|
+
const historianAllowedTools = applyDisallowedTools(HISTORIAN_ALLOWED_TOOLS, historianDisallowed);
|
|
191666
192431
|
config2.agent = {
|
|
191667
192432
|
...config2.agent ?? {},
|
|
191668
|
-
[DREAMER_AGENT]: buildHiddenAgentConfig(
|
|
191669
|
-
[HISTORIAN_AGENT]: buildHiddenAgentConfig(
|
|
191670
|
-
[HISTORIAN_EDITOR_AGENT]: buildHiddenAgentConfig(
|
|
191671
|
-
[SIDEKICK_AGENT]: buildHiddenAgentConfig(
|
|
192433
|
+
[DREAMER_AGENT]: buildHiddenAgentConfig(DREAMER_SYSTEM_PROMPT, DREAMER_ALLOWED_TOOLS, DREAMER_MAX_STEPS, dreamerAgentOverrides),
|
|
192434
|
+
[HISTORIAN_AGENT]: buildHiddenAgentConfig(COMPARTMENT_AGENT_SYSTEM_PROMPT, historianAllowedTools, HISTORIAN_MAX_STEPS, historianAgentOverrides),
|
|
192435
|
+
[HISTORIAN_EDITOR_AGENT]: buildHiddenAgentConfig(HISTORIAN_EDITOR_SYSTEM_PROMPT, historianAllowedTools, HISTORIAN_MAX_STEPS, historianAgentOverrides),
|
|
192436
|
+
[SIDEKICK_AGENT]: buildHiddenAgentConfig(SIDEKICK_SYSTEM_PROMPT, SIDEKICK_ALLOWED_TOOLS, SIDEKICK_MAX_STEPS, sidekickAgentOverrides)
|
|
191672
192437
|
};
|
|
191673
192438
|
}
|
|
191674
192439
|
};
|