@cortexkit/pi-magic-context 0.27.3 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +451 -76
- package/dist/subagent-entry.js +153 -8
- package/package.json +1 -1
package/dist/subagent-entry.js
CHANGED
|
@@ -9923,6 +9923,17 @@ function runMigrations(db) {
|
|
|
9923
9923
|
log(`[migrations] schema version now: ${MIGRATIONS[MIGRATIONS.length - 1].version}`);
|
|
9924
9924
|
}
|
|
9925
9925
|
|
|
9926
|
+
// ../plugin/src/shared/commit-detection.ts
|
|
9927
|
+
var HASH_HEX = "[0-9a-f]{7,12}";
|
|
9928
|
+
var COMMIT_HASH_TEST_PATTERN = new RegExp(`\\b${HASH_HEX}\\b`, "i");
|
|
9929
|
+
var COMMIT_VERB_PATTERN = /\b(?:commit(?:ted|ting|s)?|cherry-?pick(?:ed|ing|s)?|merge[ds]?|merging|rebas(?:e|ed|es|ing))\b/i;
|
|
9930
|
+
function textMentionsRecentCommit(text) {
|
|
9931
|
+
return COMMIT_HASH_TEST_PATTERN.test(text) && COMMIT_VERB_PATTERN.test(text);
|
|
9932
|
+
}
|
|
9933
|
+
function createCommitHashExtractPattern() {
|
|
9934
|
+
return new RegExp(`\`?\\b(${HASH_HEX})\\b\`?`, "gi");
|
|
9935
|
+
}
|
|
9936
|
+
|
|
9926
9937
|
// ../plugin/src/shared/internal-initiator-marker.ts
|
|
9927
9938
|
var OMO_INTERNAL_INITIATOR_MARKER = "<!-- OMO_INTERNAL_INITIATOR -->";
|
|
9928
9939
|
|
|
@@ -142374,8 +142385,6 @@ var decoder = {
|
|
|
142374
142385
|
};
|
|
142375
142386
|
|
|
142376
142387
|
// ../plugin/src/hooks/magic-context/read-session-formatting.ts
|
|
142377
|
-
var COMMIT_HASH_PATTERN = /`?\b([0-9a-f]{6,12})\b`?/gi;
|
|
142378
|
-
var COMMIT_HINT_PATTERN = /\b(commit(?:ted)?|cherry-?pick(?:ed)?|hash(?:es)?|sha)\b/i;
|
|
142379
142388
|
var MAX_COMMITS_PER_BLOCK = 5;
|
|
142380
142389
|
function hasMeaningfulUserText(parts) {
|
|
142381
142390
|
for (const part of parts) {
|
|
@@ -142479,7 +142488,7 @@ function formatBlock(block) {
|
|
|
142479
142488
|
function extractCommitHashes(text) {
|
|
142480
142489
|
const hashes = [];
|
|
142481
142490
|
const seen = new Set;
|
|
142482
|
-
for (const match of text.matchAll(
|
|
142491
|
+
for (const match of text.matchAll(createCommitHashExtractPattern())) {
|
|
142483
142492
|
const hash = match[1]?.toLowerCase();
|
|
142484
142493
|
if (!hash || seen.has(hash))
|
|
142485
142494
|
continue;
|
|
@@ -142492,10 +142501,10 @@ function extractCommitHashes(text) {
|
|
|
142492
142501
|
}
|
|
142493
142502
|
function compactTextForSummary(text, role) {
|
|
142494
142503
|
const commitHashes = role === "assistant" ? extractCommitHashes(text) : [];
|
|
142495
|
-
if (commitHashes.length === 0 || !
|
|
142504
|
+
if (commitHashes.length === 0 || !COMMIT_VERB_PATTERN.test(text)) {
|
|
142496
142505
|
return { text, commitHashes };
|
|
142497
142506
|
}
|
|
142498
|
-
const withoutHashes = text.replace(
|
|
142507
|
+
const withoutHashes = text.replace(createCommitHashExtractPattern(), "").replace(/\(\s*\)/g, "").replace(/\s+,/g, ",").replace(/,\s*,+/g, ", ").replace(/\s{2,}/g, " ").replace(/\s+([,.;:])/g, "$1").trim();
|
|
142499
142508
|
return {
|
|
142500
142509
|
text: withoutHashes.length > 0 ? withoutHashes : text,
|
|
142501
142510
|
commitHashes
|
|
@@ -144835,6 +144844,10 @@ function stripUnsafeProjectConfigFields(projectRaw) {
|
|
|
144835
144844
|
delete projectRaw.auto_update;
|
|
144836
144845
|
warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
|
|
144837
144846
|
}
|
|
144847
|
+
if ("language" in projectRaw) {
|
|
144848
|
+
delete projectRaw.language;
|
|
144849
|
+
warnings.push("Ignoring language from project config (security: output language is a user-level setting).");
|
|
144850
|
+
}
|
|
144838
144851
|
if ("sqlite" in projectRaw) {
|
|
144839
144852
|
delete projectRaw.sqlite;
|
|
144840
144853
|
warnings.push("Ignoring sqlite.* from project config (security: SQLite cache/mmap PRAGMAs apply to the " + "process-global shared database handle; only user-level config may set them).");
|
|
@@ -159180,6 +159193,95 @@ function date4(params) {
|
|
|
159180
159193
|
|
|
159181
159194
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
159182
159195
|
config(en_default());
|
|
159196
|
+
// ../plugin/src/agents/language-directive.ts
|
|
159197
|
+
var ENGLISH_LANGUAGE_NAMES = new Intl.DisplayNames(["en"], {
|
|
159198
|
+
type: "language",
|
|
159199
|
+
fallback: "none"
|
|
159200
|
+
});
|
|
159201
|
+
function resolveLanguageName(language) {
|
|
159202
|
+
const code = typeof language === "string" ? language.trim().toLowerCase() : "";
|
|
159203
|
+
if (!/^[a-z]{2}$/.test(code))
|
|
159204
|
+
return "";
|
|
159205
|
+
let english;
|
|
159206
|
+
try {
|
|
159207
|
+
english = ENGLISH_LANGUAGE_NAMES.of(code) ?? undefined;
|
|
159208
|
+
} catch {
|
|
159209
|
+
return "";
|
|
159210
|
+
}
|
|
159211
|
+
if (!english)
|
|
159212
|
+
return "";
|
|
159213
|
+
let endonym;
|
|
159214
|
+
try {
|
|
159215
|
+
endonym = new Intl.DisplayNames([code], { type: "language", fallback: "none" }).of(code) ?? undefined;
|
|
159216
|
+
} catch {
|
|
159217
|
+
endonym = undefined;
|
|
159218
|
+
}
|
|
159219
|
+
return endonym && endonym !== english ? `${english} (${endonym})` : english;
|
|
159220
|
+
}
|
|
159221
|
+
function isValidLanguageCode(language) {
|
|
159222
|
+
return resolveLanguageName(language) !== "";
|
|
159223
|
+
}
|
|
159224
|
+
function buildContentLanguageDirective(language, options = {}) {
|
|
159225
|
+
const target = resolveLanguageName(language);
|
|
159226
|
+
if (!target)
|
|
159227
|
+
return "";
|
|
159228
|
+
const lines = [
|
|
159229
|
+
"## Output language",
|
|
159230
|
+
"",
|
|
159231
|
+
`Write human-readable prose you author in: ${target}.`,
|
|
159232
|
+
"",
|
|
159233
|
+
"Do not translate or rename structural tokens. Copy required output schemas exactly:",
|
|
159234
|
+
"- XML tag names, XML attribute names, JSON keys, tool names, tool-call argument keys, enum values, booleans/null, and required sentinel strings stay in English exactly as shown.",
|
|
159235
|
+
"- Keep code identifiers, file paths, commands, config keys, CLI flags, URLs, commit hashes, model/provider IDs, stack traces, diagnostics, and transcript role markers such as U:, A:, and TC: verbatim.",
|
|
159236
|
+
"- Localize only free-text prose values/content: summaries, memory text, explanations, titles, observations, and answers — unless the prompt says to preserve original wording.",
|
|
159237
|
+
"",
|
|
159238
|
+
"These literal values must remain English when used:",
|
|
159239
|
+
"PROJECT_RULES, ARCHITECTURE, CONSTRAINTS, CONFIG_VALUES, NAMING;",
|
|
159240
|
+
"causal_incident, trajectory_correction;",
|
|
159241
|
+
"feature, design, docs, release, investigation, bug, refactor, infra;",
|
|
159242
|
+
"memory, observation; true, false; No relevant memories found.",
|
|
159243
|
+
"",
|
|
159244
|
+
"Preserve the required output shape. Do not add commentary outside the requested XML/JSON/tool output."
|
|
159245
|
+
];
|
|
159246
|
+
if (options.preserveUserQuotes) {
|
|
159247
|
+
lines.push("", `Preserve U: lines and directly quoted user text in their original source language; write the surrounding summary prose in ${target}.`);
|
|
159248
|
+
}
|
|
159249
|
+
if (options.retrospective) {
|
|
159250
|
+
lines.push("", `Write the lesson text in ${target}; paraphrase source text and never quote the user.`);
|
|
159251
|
+
}
|
|
159252
|
+
return lines.join(`
|
|
159253
|
+
`);
|
|
159254
|
+
}
|
|
159255
|
+
function withContentLanguageDirective(systemPrompt, language, options = {}) {
|
|
159256
|
+
const directive = buildContentLanguageDirective(language, options);
|
|
159257
|
+
return directive ? `${systemPrompt}
|
|
159258
|
+
|
|
159259
|
+
${directive}` : systemPrompt;
|
|
159260
|
+
}
|
|
159261
|
+
function buildMigrationLanguageDirective(language) {
|
|
159262
|
+
const target = resolveLanguageName(language);
|
|
159263
|
+
if (!target)
|
|
159264
|
+
return "";
|
|
159265
|
+
return [
|
|
159266
|
+
"## Output language",
|
|
159267
|
+
"",
|
|
159268
|
+
"Preserve each migrated memory's existing language — do NOT translate a memory just because an output language is set. When merging memories written in different languages, use the language of the clearest / source-majority memory; otherwise keep the source phrasing. Only the category re-mapping changes."
|
|
159269
|
+
].join(`
|
|
159270
|
+
`);
|
|
159271
|
+
}
|
|
159272
|
+
function withMigrationLanguageDirective(systemPrompt, language) {
|
|
159273
|
+
const directive = buildMigrationLanguageDirective(language);
|
|
159274
|
+
return directive ? `${systemPrompt}
|
|
159275
|
+
|
|
159276
|
+
${directive}` : systemPrompt;
|
|
159277
|
+
}
|
|
159278
|
+
function buildPrimaryLanguageDirective(language) {
|
|
159279
|
+
const target = resolveLanguageName(language);
|
|
159280
|
+
if (!target)
|
|
159281
|
+
return "";
|
|
159282
|
+
return `Use ${target} for your natural-language replies to the user unless the user explicitly asks for another language. Keep code, identifiers, file paths, commands, logs, and quoted text verbatim.`;
|
|
159283
|
+
}
|
|
159284
|
+
|
|
159183
159285
|
// ../plugin/src/features/magic-context/defaults.ts
|
|
159184
159286
|
var DEFAULT_PROTECTED_TAGS = 20;
|
|
159185
159287
|
|
|
@@ -159536,6 +159638,7 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
|
|
|
159536
159638
|
var MagicContextConfigSchema = exports_external.object({
|
|
159537
159639
|
enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
|
|
159538
159640
|
auto_update: exports_external.boolean().optional().describe("Enable automatic npm self-update checks for the OpenCode plugin. Security: USER-only in config loader, so hostile project configs cannot suppress updates."),
|
|
159641
|
+
language: exports_external.string().trim().toLowerCase().refine((s) => isValidLanguageCode(s), 'language must be a 2-letter ISO 639-1 code (e.g. "tr", "es", "de")').optional().describe("Output language for Magic Context's generated content and guidance, as a " + '2-letter ISO 639-1 code (e.g. "tr", "es", "de", "ja", "pt"). When set, the ' + "historian, dreamer, sidekick, and the agent-guidance block instruct the model to " + "write its PROSE in this language while keeping all structural tokens (XML tags, " + "the five memory category names, code identifiers, file paths) in English. " + "USER-LEVEL ONLY (ignored in project config for security). Unset = today's " + "behavior (model mirrors the conversation; English scaffolding). Changing it " + "triggers one cache re-materialization; existing compartments/memories keep their " + "original language until naturally rewritten."),
|
|
159539
159642
|
ctx_reduce_enabled: exports_external.boolean().default(true).describe("When false, ctx_reduce tool is hidden, all nudges disabled, and prompt guidance about ctx_reduce stripped. Heuristic cleanup, compartments, memory, and other features still work. (default: true)"),
|
|
159540
159643
|
historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
|
|
159541
159644
|
dreamer: DreamerConfigSchema.optional().describe("Dreamer agent + scheduling configuration (model, fallback_models, disable, schedule, tasks, etc.)"),
|
|
@@ -159573,6 +159676,7 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
159573
159676
|
}).describe("Embedding provider configuration"),
|
|
159574
159677
|
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).'),
|
|
159575
159678
|
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."),
|
|
159679
|
+
smart_drops: exports_external.boolean().default(false).describe("Content-aware reclaim of provably-superseded tool output, layered on the existing execute-pass auto-drop. When on: superseded todowrite (keep newest 1), spent ctx_reduce (keep newest 5), and zero-value meta (bash_status, bash_kill, ctx_note read/dismiss) outputs are dropped; older edits to a file are compressed to a filePath-preserving marker while the newest edit per file stays full. Only acts on passes already busting the cache, so it never originates a cache bust. Honors the protected-tag reserve. Experimental: opt-in, default off until cache stability is proven; when off the wire is byte-identical to the positional-only reclaim. Requires a restart."),
|
|
159576
159680
|
caveman_text_compression: exports_external.object({
|
|
159577
159681
|
enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text. Only active when ctx_reduce_enabled=false. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%)."),
|
|
159578
159682
|
min_chars: exports_external.number().min(100).max(1e4).default(500).describe("Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.")
|
|
@@ -163483,6 +163587,36 @@ function isRecord(value) {
|
|
|
163483
163587
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
163484
163588
|
}
|
|
163485
163589
|
|
|
163590
|
+
// ../plugin/src/hooks/magic-context/edit-marker.ts
|
|
163591
|
+
var TRUNCATION_SENTINEL = "...[truncated]";
|
|
163592
|
+
var EDIT_REGION_HINT_LEN = 40;
|
|
163593
|
+
var PATH_KEYS = new Set(["filePath", "file_path", "path"]);
|
|
163594
|
+
var DIFF_KEYS = new Set(["oldString", "newString", "content", "old_string", "new_string"]);
|
|
163595
|
+
function safeSlice(str, maxLen) {
|
|
163596
|
+
if (str.length <= maxLen)
|
|
163597
|
+
return str;
|
|
163598
|
+
const lastCharCode = str.charCodeAt(maxLen - 1);
|
|
163599
|
+
if (lastCharCode >= 55296 && lastCharCode <= 56319) {
|
|
163600
|
+
return str.slice(0, maxLen - 1);
|
|
163601
|
+
}
|
|
163602
|
+
return str.slice(0, maxLen);
|
|
163603
|
+
}
|
|
163604
|
+
function isEditTool(name2) {
|
|
163605
|
+
return name2 === "edit" || name2 === "write";
|
|
163606
|
+
}
|
|
163607
|
+
function applyEditMarkerToInput(input) {
|
|
163608
|
+
for (const key of Object.keys(input)) {
|
|
163609
|
+
if (PATH_KEYS.has(key))
|
|
163610
|
+
continue;
|
|
163611
|
+
const value = input[key];
|
|
163612
|
+
if (typeof value !== "string" || !DIFF_KEYS.has(key))
|
|
163613
|
+
continue;
|
|
163614
|
+
if (value.endsWith(TRUNCATION_SENTINEL))
|
|
163615
|
+
continue;
|
|
163616
|
+
input[key] = value.length > EDIT_REGION_HINT_LEN ? `${safeSlice(value, EDIT_REGION_HINT_LEN)}${TRUNCATION_SENTINEL}` : value;
|
|
163617
|
+
}
|
|
163618
|
+
}
|
|
163619
|
+
|
|
163486
163620
|
// ../plugin/src/hooks/magic-context/tool-drop-target.ts
|
|
163487
163621
|
var IGNORE_PART_TYPES = new Set([
|
|
163488
163622
|
"thinking",
|
|
@@ -171478,6 +171612,9 @@ function getActiveTagTokenAggregate(db, sessionId, protectedTags = 0) {
|
|
|
171478
171612
|
nullCount: row?.null_count ?? 0
|
|
171479
171613
|
};
|
|
171480
171614
|
}
|
|
171615
|
+
var RECLAIM_HINT_EXCLUDED_TOOLS = ["todowrite"];
|
|
171616
|
+
var RECLAIM_HINT_MIN_TOKENS = 250;
|
|
171617
|
+
var RECLAIM_HINT_EXCLUDED_LIST = RECLAIM_HINT_EXCLUDED_TOOLS.map((name2) => `'${name2.replace(/'/g, "''")}'`).join(", ");
|
|
171481
171618
|
function getOldestActiveUnprotectedToolTags(db, sessionId, protectedTags = 0, limit = 4) {
|
|
171482
171619
|
if (limit <= 0)
|
|
171483
171620
|
return [];
|
|
@@ -171487,10 +171624,18 @@ function getOldestActiveUnprotectedToolTags(db, sessionId, protectedTags = 0, li
|
|
|
171487
171624
|
WHERE session_id = ? AND status = 'active'
|
|
171488
171625
|
ORDER BY tag_number DESC LIMIT 1 OFFSET ?
|
|
171489
171626
|
)` : "";
|
|
171490
|
-
const
|
|
171627
|
+
const excludeStateTools = RECLAIM_HINT_EXCLUDED_LIST ? `AND (tool_name IS NULL OR tool_name NOT IN (${RECLAIM_HINT_EXCLUDED_LIST}))` : "";
|
|
171628
|
+
const valueFloor = `AND (
|
|
171629
|
+
(token_count IS NULL AND input_token_count IS NULL)
|
|
171630
|
+
OR (COALESCE(token_count, 0) + COALESCE(input_token_count, 0)) >= ?
|
|
171631
|
+
)`;
|
|
171632
|
+
const params = protectedTags > 0 ? [sessionId, RECLAIM_HINT_MIN_TOKENS, sessionId, protectedTags - 1, boundedLimit] : [sessionId, RECLAIM_HINT_MIN_TOKENS, boundedLimit];
|
|
171491
171633
|
const rows = db.prepare(`SELECT tag_number, tool_name
|
|
171492
171634
|
FROM tags
|
|
171493
|
-
WHERE session_id = ? AND status = 'active' AND type = 'tool'
|
|
171635
|
+
WHERE session_id = ? AND status = 'active' AND type = 'tool'
|
|
171636
|
+
${excludeStateTools}
|
|
171637
|
+
${valueFloor}
|
|
171638
|
+
${whereProtected}
|
|
171494
171639
|
ORDER BY tag_number ASC, id ASC
|
|
171495
171640
|
LIMIT ?`).all(...params);
|
|
171496
171641
|
return rows.filter((row) => typeof row.tag_number === "number").map((row) => ({
|
|
@@ -171601,7 +171746,7 @@ function toTagEntry(row) {
|
|
|
171601
171746
|
messageId: row.message_id,
|
|
171602
171747
|
type,
|
|
171603
171748
|
status,
|
|
171604
|
-
dropMode: row.drop_mode === "truncated" ? "truncated" : "full",
|
|
171749
|
+
dropMode: row.drop_mode === "truncated" ? "truncated" : row.drop_mode === "edit_marker" ? "edit_marker" : "full",
|
|
171605
171750
|
toolName: row.tool_name ?? null,
|
|
171606
171751
|
inputByteSize: row.input_byte_size ?? 0,
|
|
171607
171752
|
byteSize: row.byte_size,
|
package/package.json
CHANGED