@cortexkit/opencode-magic-context 0.27.3 → 0.28.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.
Files changed (55) hide show
  1. package/dist/agents/language-directive.d.ts +27 -0
  2. package/dist/agents/language-directive.d.ts.map +1 -0
  3. package/dist/agents/magic-context-prompt.d.ts +1 -1
  4. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  5. package/dist/config/project-security.d.ts +1 -0
  6. package/dist/config/project-security.d.ts.map +1 -1
  7. package/dist/config/schema/magic-context.d.ts +4 -0
  8. package/dist/config/schema/magic-context.d.ts.map +1 -1
  9. package/dist/features/magic-context/dreamer/refresh-primers.d.ts +1 -0
  10. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  11. package/dist/features/magic-context/dreamer/task-config.d.ts +1 -1
  12. package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -0
  14. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  15. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +1 -0
  16. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  17. package/dist/features/magic-context/dreamer/verify.d.ts +1 -0
  18. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  19. package/dist/features/magic-context/memory/memory-migration.d.ts +1 -0
  20. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  21. package/dist/features/magic-context/sidekick/agent.d.ts +1 -0
  22. package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
  23. package/dist/features/magic-context/storage-tags.d.ts +0 -5
  24. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  25. package/dist/features/magic-context/user-memory/review-user-memories.d.ts +1 -0
  26. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/command-handler.d.ts +1 -0
  28. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/compartment-runner-historian.d.ts +1 -0
  30. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  32. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  34. package/dist/hooks/magic-context/compartment-runner-types.d.ts +1 -0
  35. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  36. package/dist/hooks/magic-context/compartment-runner-validation.d.ts +1 -1
  37. package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
  38. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +13 -3
  39. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
  40. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  41. package/dist/hooks/magic-context/hook.d.ts +1 -0
  42. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  43. package/dist/hooks/magic-context/recomp-orchestrator.d.ts +1 -0
  44. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  45. package/dist/hooks/magic-context/system-prompt-hash.d.ts +2 -0
  46. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +192 -43
  49. package/dist/plugin/dream-timer.d.ts +1 -0
  50. package/dist/plugin/dream-timer.d.ts.map +1 -1
  51. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  52. package/dist/shared/announcement.d.ts +1 -1
  53. package/dist/shared/announcement.d.ts.map +1 -1
  54. package/package.json +1 -1
  55. package/src/shared/announcement.ts +3 -6
package/dist/index.js CHANGED
@@ -169,6 +169,98 @@ var init_logger = __esm(() => {
169
169
  }
170
170
  });
171
171
 
172
+ // src/agents/language-directive.ts
173
+ function resolveLanguageName(language) {
174
+ const code = typeof language === "string" ? language.trim().toLowerCase() : "";
175
+ if (!/^[a-z]{2}$/.test(code))
176
+ return "";
177
+ let english;
178
+ try {
179
+ english = ENGLISH_LANGUAGE_NAMES.of(code) ?? undefined;
180
+ } catch {
181
+ return "";
182
+ }
183
+ if (!english)
184
+ return "";
185
+ let endonym;
186
+ try {
187
+ endonym = new Intl.DisplayNames([code], { type: "language", fallback: "none" }).of(code) ?? undefined;
188
+ } catch {
189
+ endonym = undefined;
190
+ }
191
+ return endonym && endonym !== english ? `${english} (${endonym})` : english;
192
+ }
193
+ function isValidLanguageCode(language) {
194
+ return resolveLanguageName(language) !== "";
195
+ }
196
+ function buildContentLanguageDirective(language, options = {}) {
197
+ const target = resolveLanguageName(language);
198
+ if (!target)
199
+ return "";
200
+ const lines = [
201
+ "## Output language",
202
+ "",
203
+ `Write human-readable prose you author in: ${target}.`,
204
+ "",
205
+ "Do not translate or rename structural tokens. Copy required output schemas exactly:",
206
+ "- 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.",
207
+ "- 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.",
208
+ "- Localize only free-text prose values/content: summaries, memory text, explanations, titles, observations, and answers — unless the prompt says to preserve original wording.",
209
+ "",
210
+ "These literal values must remain English when used:",
211
+ "PROJECT_RULES, ARCHITECTURE, CONSTRAINTS, CONFIG_VALUES, NAMING;",
212
+ "causal_incident, trajectory_correction;",
213
+ "feature, design, docs, release, investigation, bug, refactor, infra;",
214
+ "memory, observation; true, false; No relevant memories found.",
215
+ "",
216
+ "Preserve the required output shape. Do not add commentary outside the requested XML/JSON/tool output."
217
+ ];
218
+ if (options.preserveUserQuotes) {
219
+ lines.push("", `Preserve U: lines and directly quoted user text in their original source language; write the surrounding summary prose in ${target}.`);
220
+ }
221
+ if (options.retrospective) {
222
+ lines.push("", `Write the lesson text in ${target}; paraphrase source text and never quote the user.`);
223
+ }
224
+ return lines.join(`
225
+ `);
226
+ }
227
+ function withContentLanguageDirective(systemPrompt, language, options = {}) {
228
+ const directive = buildContentLanguageDirective(language, options);
229
+ return directive ? `${systemPrompt}
230
+
231
+ ${directive}` : systemPrompt;
232
+ }
233
+ function buildMigrationLanguageDirective(language) {
234
+ const target = resolveLanguageName(language);
235
+ if (!target)
236
+ return "";
237
+ return [
238
+ "## Output language",
239
+ "",
240
+ "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."
241
+ ].join(`
242
+ `);
243
+ }
244
+ function withMigrationLanguageDirective(systemPrompt, language) {
245
+ const directive = buildMigrationLanguageDirective(language);
246
+ return directive ? `${systemPrompt}
247
+
248
+ ${directive}` : systemPrompt;
249
+ }
250
+ function buildPrimaryLanguageDirective(language) {
251
+ const target = resolveLanguageName(language);
252
+ if (!target)
253
+ return "";
254
+ 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.`;
255
+ }
256
+ var ENGLISH_LANGUAGE_NAMES;
257
+ var init_language_directive = __esm(() => {
258
+ ENGLISH_LANGUAGE_NAMES = new Intl.DisplayNames(["en"], {
259
+ type: "language",
260
+ fallback: "none"
261
+ });
262
+ });
263
+
172
264
  // src/shared/jsonc-parser.ts
173
265
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
174
266
  function stripJsonComments(content) {
@@ -15155,6 +15247,7 @@ function defaultTaskConfig(task) {
15155
15247
  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, DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2", DreamingTaskSchema, PiThinkingLevelSchema, CronScheduleSchema, DreamTaskBaseConfigSchema, PromotionThresholdSchema, PrimerPromotionThresholdSchema, DreamTaskConfigSchema, ReviewUserMemoriesTaskConfigSchema, PromotePrimersTaskConfigSchema, DEFAULT_TASK_SCHEDULES, DreamTasksSchema, DreamerConfigSchema, SidekickConfigSchema, HistorianConfigSchema, BaseEmbeddingConfigSchema, EmbeddingConfigSchema, MagicContextConfigSchema;
15156
15248
  var init_magic_context = __esm(() => {
15157
15249
  init_zod();
15250
+ init_language_directive();
15158
15251
  init_cron();
15159
15252
  init_task_registry();
15160
15253
  init_agent_overrides();
@@ -15276,6 +15369,7 @@ var init_magic_context = __esm(() => {
15276
15369
  MagicContextConfigSchema = exports_external.object({
15277
15370
  enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
15278
15371
  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."),
15372
+ 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."),
15279
15373
  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)"),
15280
15374
  historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
15281
15375
  dreamer: DreamerConfigSchema.optional().describe("Dreamer agent + scheduling configuration (model, fallback_models, disable, schedule, tasks, etc.)"),
@@ -155736,10 +155830,18 @@ function getOldestActiveUnprotectedToolTags(db, sessionId, protectedTags = 0, li
155736
155830
  WHERE session_id = ? AND status = 'active'
155737
155831
  ORDER BY tag_number DESC LIMIT 1 OFFSET ?
155738
155832
  )` : "";
155739
- const params = protectedTags > 0 ? [sessionId, sessionId, protectedTags - 1, boundedLimit] : [sessionId, boundedLimit];
155833
+ const excludeStateTools = RECLAIM_HINT_EXCLUDED_LIST ? `AND (tool_name IS NULL OR tool_name NOT IN (${RECLAIM_HINT_EXCLUDED_LIST}))` : "";
155834
+ const valueFloor = `AND (
155835
+ (token_count IS NULL AND input_token_count IS NULL)
155836
+ OR (COALESCE(token_count, 0) + COALESCE(input_token_count, 0)) >= ?
155837
+ )`;
155838
+ const params = protectedTags > 0 ? [sessionId, RECLAIM_HINT_MIN_TOKENS, sessionId, protectedTags - 1, boundedLimit] : [sessionId, RECLAIM_HINT_MIN_TOKENS, boundedLimit];
155740
155839
  const rows = db.prepare(`SELECT tag_number, tool_name
155741
155840
  FROM tags
155742
- WHERE session_id = ? AND status = 'active' AND type = 'tool' ${whereProtected}
155841
+ WHERE session_id = ? AND status = 'active' AND type = 'tool'
155842
+ ${excludeStateTools}
155843
+ ${valueFloor}
155844
+ ${whereProtected}
155743
155845
  ORDER BY tag_number ASC, id ASC
155744
155846
  LIMIT ?`).all(...params);
155745
155847
  return rows.filter((row) => typeof row.tag_number === "number").map((row) => ({
@@ -156129,7 +156231,7 @@ function deleteToolTagsByOwner(db, sessionId, ownerMsgId) {
156129
156231
  const result = getDeleteToolTagsByOwnerStatement(db).run(sessionId, ownerMsgId);
156130
156232
  return result.changes ?? 0;
156131
156233
  }
156132
- 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;
156234
+ var insertTagStatements, updateTagStatusStatements, updateTagDropModeStatements, updateTagMessageIdStatements, getTagNumbersByMessageIdStatements, deleteTagsByMessageIdStatements, getMaxTagNumberBySessionStatements, getTagNumberByMessageIdStatements, updateTagByteSizeStatements, updateTagInputByteSizeStatements, CONTENT_ID_SUFFIX, RECLAIM_HINT_EXCLUDED_TOOLS, RECLAIM_HINT_MIN_TOKENS = 250, RECLAIM_HINT_EXCLUDED_LIST, 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;
156133
156235
  var init_storage_tags = __esm(() => {
156134
156236
  insertTagStatements = new WeakMap;
156135
156237
  updateTagStatusStatements = new WeakMap;
@@ -156142,6 +156244,8 @@ var init_storage_tags = __esm(() => {
156142
156244
  updateTagByteSizeStatements = new WeakMap;
156143
156245
  updateTagInputByteSizeStatements = new WeakMap;
156144
156246
  CONTENT_ID_SUFFIX = /:(?:p|file)\d+$/;
156247
+ RECLAIM_HINT_EXCLUDED_TOOLS = ["todowrite"];
156248
+ RECLAIM_HINT_EXCLUDED_LIST = RECLAIM_HINT_EXCLUDED_TOOLS.map((name2) => `'${name2.replace(/'/g, "''")}'`).join(", ");
156145
156249
  updateTagTokenCountStatements = new WeakMap;
156146
156250
  updateTagInputTokenCountStatements = new WeakMap;
156147
156251
  getOwnerScopedToolTagNumbersStatements = new WeakMap;
@@ -165855,7 +165959,7 @@ __export(exports_task_config, {
165855
165959
  dreamTaskScheduled: () => dreamTaskScheduled,
165856
165960
  buildDreamTaskRuntimeConfigs: () => buildDreamTaskRuntimeConfigs
165857
165961
  });
165858
- function buildDreamTaskRuntimeConfigs(dreamer) {
165962
+ function buildDreamTaskRuntimeConfigs(dreamer, language) {
165859
165963
  const tasks = dreamer.tasks ?? {};
165860
165964
  return CANONICAL_DREAM_TASKS.map((task) => {
165861
165965
  const t = tasks[task] ?? {
@@ -165871,6 +165975,7 @@ function buildDreamTaskRuntimeConfigs(dreamer) {
165871
165975
  model,
165872
165976
  fallbackModels,
165873
165977
  thinkingLevel,
165978
+ language,
165874
165979
  timeoutMinutes: t.timeout_minutes ?? 20,
165875
165980
  promotionThreshold: t.promotion_threshold
165876
165981
  };
@@ -177223,8 +177328,8 @@ function buildHistorianFailureNotice(failureCount, lastError) {
177223
177328
  ].join(`
177224
177329
  `);
177225
177330
  }
177226
- function buildHistorianRepairPrompt(originalPrompt, previousOutput, validationError) {
177227
- return [
177331
+ function buildHistorianRepairPrompt(originalPrompt, previousOutput, validationError, language) {
177332
+ const prompt = [
177228
177333
  originalPrompt,
177229
177334
  "",
177230
177335
  "Your previous XML response was invalid and cannot be persisted.",
@@ -177237,6 +177342,7 @@ function buildHistorianRepairPrompt(originalPrompt, previousOutput, validationEr
177237
177342
  previousOutput
177238
177343
  ].join(`
177239
177344
  `);
177345
+ return withContentLanguageDirective(prompt, language, { preserveUserQuotes: true });
177240
177346
  }
177241
177347
  function validateStoredCompartments(compartments) {
177242
177348
  if (compartments.length === 0) {
@@ -177313,6 +177419,7 @@ function getReducedRecompTokenBudget(currentBudget) {
177313
177419
  }
177314
177420
  var MIN_RECOMP_CHUNK_TOKEN_BUDGET = 20, HISTORIAN_PERSISTENT_FAILURE_THRESHOLD = 3;
177315
177421
  var init_compartment_runner_validation = __esm(async () => {
177422
+ init_language_directive();
177316
177423
  init_compartment_parser();
177317
177424
  await init_compartment_runner_mapping();
177318
177425
  });
@@ -177350,7 +177457,7 @@ async function runValidatedHistorianPass(args) {
177350
177457
  return finalResult;
177351
177458
  }
177352
177459
  await args.callbacks?.onRepairRetry?.(firstValidation.error ?? "invalid compartment output");
177353
- const repairPrompt = buildHistorianRepairPrompt(args.prompt, firstRun.result, firstValidation.error ?? "invalid compartment output");
177460
+ const repairPrompt = buildHistorianRepairPrompt(args.prompt, firstRun.result, firstValidation.error ?? "invalid compartment output", args.language);
177354
177461
  const repairRun = await runHistorianPrompt({
177355
177462
  ...args,
177356
177463
  prompt: repairPrompt,
@@ -182735,7 +182842,8 @@ ${chunkText}`,
182735
182842
  timeoutMs: historianTimeoutMs,
182736
182843
  fallbackModelId: deps.fallbackModelId,
182737
182844
  fallbackModels: deps.fallbackModels,
182738
- twoPass: deps.historianTwoPass
182845
+ twoPass: deps.historianTwoPass,
182846
+ language: deps.language
182739
182847
  });
182740
182848
  if (!validatedPass.ok) {
182741
182849
  sessionLog(sessionId, `historian failure: source=validation reason="${validatedPass.error}" chunkRange=${chunk.startIndex}-${chunk.endIndex} fallbackModel=${deps.fallbackModelId ?? "<none>"} twoPass=${deps.historianTwoPass ? "true" : "false"}`);
@@ -183211,6 +183319,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
183211
183319
  twoPass: deps.historianTwoPass,
183212
183320
  subagentKind: "recomp",
183213
183321
  agentId: HISTORIAN_RECOMP_AGENT,
183322
+ language: deps.language,
183214
183323
  callbacks: {
183215
183324
  onRepairRetry: async (error51) => {
183216
183325
  emitProgress(`Repair retry (pass ${passCount + 1})…`);
@@ -183653,6 +183762,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
183653
183762
  twoPass: deps.historianTwoPass,
183654
183763
  subagentKind: "recomp",
183655
183764
  agentId: HISTORIAN_RECOMP_AGENT,
183765
+ language: deps.language,
183656
183766
  callbacks: {
183657
183767
  onRepairRetry: async (error51) => {
183658
183768
  await sendIgnoredMessage(client, sessionId, `## Magic Recomp — Partial
@@ -186013,7 +186123,7 @@ async function runMemoryMigration(deps) {
186013
186123
  query: { directory },
186014
186124
  body: {
186015
186125
  agent: HISTORIAN_AGENT,
186016
- system: MIGRATION_SYSTEM_PROMPT,
186126
+ system: withMigrationLanguageDirective(MIGRATION_SYSTEM_PROMPT, deps.language),
186017
186127
  ...modelOverride ? { model: modelOverride } : {},
186018
186128
  parts: [{ type: "text", text: prompt, synthetic: true }]
186019
186129
  }
@@ -186092,6 +186202,7 @@ async function runMemoryMigration(deps) {
186092
186202
  }
186093
186203
  var V2_CATEGORIES, MIGRATED_BLOCK_RE, USER_OBS_BLOCK_RE, CATEGORY_BLOCK_RE = (cat) => new RegExp(`<${cat}>([\\s\\S]*?)</${cat}>`), MIGRATION_SYSTEM_PROMPT;
186094
186204
  var init_memory_migration = __esm(async () => {
186205
+ init_language_directive();
186095
186206
  init_shared();
186096
186207
  init_assistant_message_extractor();
186097
186208
  init_logger();
@@ -186208,6 +186319,7 @@ function buildRecompDeps(ctx, sessionId) {
186208
186319
  memoryEnabled: ctx.memoryEnabled,
186209
186320
  autoPromote: ctx.autoPromote,
186210
186321
  fallbackModels: ctx.fallbackModels,
186322
+ language: ctx.language,
186211
186323
  fallbackModelId: ctx.fallbackModelId ?? resolveLiveModelKey(ctx.liveSessionState, sessionId),
186212
186324
  historianTwoPass: ctx.historianTwoPass,
186213
186325
  ensureProjectRegistered: ctx.ensureProjectRegistered,
@@ -186339,7 +186451,8 @@ async function runUpgradeMemoryMigration(ctx, sessionId, migrationDirectory) {
186339
186451
  primaryModelId: ctx.fallbackModelId ?? resolveLiveModelKey(ctx.liveSessionState, sessionId),
186340
186452
  fallbackModels: ctx.fallbackModels,
186341
186453
  timeoutMs: ctx.historianTimeoutMs,
186342
- userMemoriesEnabled: ctx.userMemoriesEnabled
186454
+ userMemoriesEnabled: ctx.userMemoriesEnabled,
186455
+ language: ctx.language
186343
186456
  });
186344
186457
  return outcome.summary;
186345
186458
  } catch (error51) {
@@ -186415,15 +186528,12 @@ function shouldShowAnnouncement() {
186415
186528
  }
186416
186529
  return ordering > 0;
186417
186530
  }
186418
- var ANNOUNCEMENT_VERSION = "0.27.0", ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU", STATE_FILENAME = "last_announced_version";
186531
+ var ANNOUNCEMENT_VERSION = "0.28.0", ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU", STATE_FILENAME = "last_announced_version";
186419
186532
  var init_announcement = __esm(() => {
186420
186533
  init_data_path();
186421
186534
  ANNOUNCEMENT_FEATURES = [
186422
- "Dreamer V2: each maintenance task now runs on its own schedule (cron), with its own model. Configure them in setup, the dashboard, or magic-context.jsonc.",
186423
- "New 'classify' task scores each memory's importance so the most relevant stay in context as your work shifts; new 'retrospective' learns from moments you had to correct or re-explain. Both cache-safe, on by default, off anytime.",
186424
- "New Primers: durable answers to the questions that keep coming up about your project, kept current by the dreamer investigating the actual code.",
186425
- "Embedding storage no longer wipes your vectors when you change model or endpoint. Different models now coexist, so switching providers keeps your existing vectors.",
186426
- "Config moved to a shared CortexKit location (~/.config/cortexkit/ and <project>/.cortexkit/). This happens automatically on first run; your old file is preserved."
186535
+ `New 'language' option: set a top-level 2-letter language code (e.g. "tr" or "es") and Magic Context writes its summaries, memories, and guidance in that language, while keeping all structure (tags, categories, code, paths) in English. User-level only, off by default.`,
186536
+ "The ctx_reduce reminder now reflects how much tool output is actually reclaimable, instead of escalating to 'urgent' just because you're near compaction. It also no longer suggests dropping the agent's task list or tiny status outputs."
186427
186537
  ];
186428
186538
  });
186429
186539
 
@@ -186717,6 +186827,9 @@ function buildHiddenAgentConfig(prompt, allowedTools, maxSteps, overrides, agent
186717
186827
  };
186718
186828
  }
186719
186829
 
186830
+ // src/index.ts
186831
+ init_language_directive();
186832
+
186720
186833
  // src/config/index.ts
186721
186834
  init_jsonc_parser();
186722
186835
  import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
@@ -187461,6 +187574,10 @@ function stripUnsafeProjectConfigFields(projectRaw) {
187461
187574
  delete projectRaw.auto_update;
187462
187575
  warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
187463
187576
  }
187577
+ if ("language" in projectRaw) {
187578
+ delete projectRaw.language;
187579
+ warnings.push("Ignoring language from project config (security: output language is a user-level setting).");
187580
+ }
187464
187581
  if ("sqlite" in projectRaw) {
187465
187582
  delete projectRaw.sqlite;
187466
187583
  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).");
@@ -188293,6 +188410,9 @@ function buildDreamTaskPrompt(task, args) {
188293
188410
  // src/index.ts
188294
188411
  init_project_identity();
188295
188412
 
188413
+ // src/features/magic-context/sidekick/agent.ts
188414
+ init_language_directive();
188415
+
188296
188416
  // src/agents/sidekick.ts
188297
188417
  var SIDEKICK_AGENT = "sidekick";
188298
188418
 
@@ -188360,12 +188480,13 @@ async function runSidekick(deps) {
188360
188480
  throw error51;
188361
188481
  }
188362
188482
  const childSessionId = agentSessionId;
188483
+ const systemPrompt = withContentLanguageDirective(deps.config.system_prompt?.trim() || deps.config.prompt?.trim() || SIDEKICK_SYSTEM_PROMPT, deps.language);
188363
188484
  const sidekickRun = await promptSyncWithValidatedOutputRetry(deps.client, {
188364
188485
  path: { id: childSessionId },
188365
188486
  query: { directory: deps.sessionDirectory ?? deps.projectPath },
188366
188487
  body: {
188367
188488
  agent: SIDEKICK_AGENT,
188368
- system: deps.config.system_prompt?.trim() || deps.config.prompt?.trim() || SIDEKICK_SYSTEM_PROMPT,
188489
+ system: systemPrompt,
188369
188490
  parts: [{ type: "text", text: deps.userMessage, synthetic: true }]
188370
188491
  }
188371
188492
  }, {
@@ -189928,6 +190049,7 @@ var DREAMER_DOCS_AGENT = "dreamer-docs";
189928
190049
  var DREAMER_REVIEWER_AGENT = "dreamer-reviewer";
189929
190050
 
189930
190051
  // src/features/magic-context/dreamer/task-executor.ts
190052
+ init_language_directive();
189931
190053
  init_shared();
189932
190054
  init_assistant_message_extractor();
189933
190055
  init_logger();
@@ -189936,6 +190058,7 @@ init_memory();
189936
190058
  init_subagent_token_capture();
189937
190059
 
189938
190060
  // src/features/magic-context/user-memory/review-user-memories.ts
190061
+ init_language_directive();
189939
190062
  init_shared();
189940
190063
  init_assistant_message_extractor();
189941
190064
  init_logger();
@@ -190050,7 +190173,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
190050
190173
  query: { directory: args.sessionDirectory },
190051
190174
  body: {
190052
190175
  agent: DREAMER_REVIEWER_AGENT,
190053
- system: REVIEW_USER_MEMORIES_SYSTEM_PROMPT,
190176
+ system: withContentLanguageDirective(REVIEW_USER_MEMORIES_SYSTEM_PROMPT, args.language),
190054
190177
  ...modelBodyField(args.model),
190055
190178
  parts: [{ type: "text", text: prompt, synthetic: true }]
190056
190179
  }
@@ -192634,6 +192757,7 @@ async function promotePrimers(args) {
192634
192757
  }
192635
192758
 
192636
192759
  // src/features/magic-context/dreamer/refresh-primers.ts
192760
+ init_language_directive();
192637
192761
  init_read_session_formatting();
192638
192762
  init_shared();
192639
192763
  init_assistant_message_extractor();
@@ -192872,7 +192996,7 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
192872
192996
  query: { directory: args.sessionDirectory },
192873
192997
  body: {
192874
192998
  agent: DREAMER_PRIMER_INVESTIGATOR_AGENT,
192875
- system: PRIMER_INVESTIGATOR_SYSTEM_PROMPT,
192999
+ system: withContentLanguageDirective(PRIMER_INVESTIGATOR_SYSTEM_PROMPT, args.language),
192876
193000
  ...modelBodyField(args.model),
192877
193001
  parts: [{ type: "text", text: prompt, synthetic: true }]
192878
193002
  }
@@ -193108,6 +193232,7 @@ function insertDreamRun(db, run) {
193108
193232
  init_task_registry();
193109
193233
 
193110
193234
  // src/features/magic-context/dreamer/verify.ts
193235
+ init_language_directive();
193111
193236
  init_shared();
193112
193237
  init_assistant_message_extractor();
193113
193238
  init_logger();
@@ -193335,7 +193460,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
193335
193460
  query: { directory: args.sessionDirectory },
193336
193461
  body: {
193337
193462
  agent: DREAMER_MEMORY_MAPPER_AGENT,
193338
- system: VERIFY_SYSTEM_PROMPT,
193463
+ system: withContentLanguageDirective(VERIFY_SYSTEM_PROMPT, args.language),
193339
193464
  ...modelBodyField(args.model),
193340
193465
  parts: [{ type: "text", text: prompt, synthetic: true }]
193341
193466
  }
@@ -193615,7 +193740,8 @@ function createDreamTaskExecutor(deps) {
193615
193740
  deadline,
193616
193741
  promotionThreshold: config2.promotionThreshold ?? 3,
193617
193742
  model: config2.model,
193618
- fallbackModels: config2.fallbackModels
193743
+ fallbackModels: config2.fallbackModels,
193744
+ language: config2.language ?? deps.language
193619
193745
  });
193620
193746
  recordRun("completed", null);
193621
193747
  log(`[dreamer] review-user-memories: promoted=${result.promoted} merged=${result.merged} dismissed=${result.dismissed}`);
@@ -193651,7 +193777,8 @@ function createDreamTaskExecutor(deps) {
193651
193777
  deadline,
193652
193778
  forceBroad: config2.task === "verify-broad",
193653
193779
  model: config2.model,
193654
- fallbackModels: config2.fallbackModels
193780
+ fallbackModels: config2.fallbackModels,
193781
+ language: config2.language ?? deps.language
193655
193782
  });
193656
193783
  recordRun("completed", null, {
193657
193784
  memoryChanges: computeMemoryDelta(memoryBefore)
@@ -193703,6 +193830,7 @@ function createDreamTaskExecutor(deps) {
193703
193830
  deadline,
193704
193831
  model: config2.model,
193705
193832
  fallbackModels: config2.fallbackModels,
193833
+ language: config2.language ?? deps.language,
193706
193834
  rawProviderFactory: deps.primerRawProviderFactory
193707
193835
  });
193708
193836
  recordRun("completed", null);
@@ -193820,6 +193948,7 @@ function retrospectiveEventsForSessions(db, sessionIds) {
193820
193948
  try {
193821
193949
  for (const event of getCompartmentEvents(db, sessionId)) {
193822
193950
  if (event.kind !== "causal_incident" && event.kind !== "trajectory_correction") {
193951
+ log(`[dreamer] dropping event: unknown kind="${event.kind}"`);
193823
193952
  continue;
193824
193953
  }
193825
193954
  events.push({
@@ -193944,7 +194073,9 @@ async function runRetrospectiveTask(config2, ctx, helpers) {
193944
194073
  const frictionWindow = renderFrictionWindow(messages, flagged.map((message) => message.ordinal));
193945
194074
  const eventSessionIds = new Set(messages.map((message) => message.sessionId));
193946
194075
  const events = retrospectiveEventsForSessions(db, eventSessionIds);
193947
- const deepenRun = await runChildTurn(RETROSPECTIVE_SYSTEM_PROMPT, buildRetrospectivePrompt({ projectPath: projectIdentity, frictionWindow, events }));
194076
+ const deepenRun = await runChildTurn(withContentLanguageDirective(RETROSPECTIVE_SYSTEM_PROMPT, config2.language ?? deps.language, {
194077
+ retrospective: true
194078
+ }), buildRetrospectivePrompt({ projectPath: projectIdentity, frictionWindow, events }));
193948
194079
  if (leaseLost)
193949
194080
  throw new Error("Dream lease lost during retrospective");
193950
194081
  const sourceSessionId = flagged[0]?.sessionId ?? userMessages[0]?.sessionId ?? "retrospective";
@@ -194030,7 +194161,7 @@ async function runAgenticTask(config2, ctx, helpers) {
194030
194161
  query: { directory: docsDir },
194031
194162
  body: {
194032
194163
  agent: task === "maintain-docs" ? DREAMER_DOCS_AGENT : DREAMER_AGENT,
194033
- system: task === "maintain-docs" ? MAINTAIN_DOCS_SYSTEM_PROMPT : CURATE_SYSTEM_PROMPT,
194164
+ system: task === "maintain-docs" ? MAINTAIN_DOCS_SYSTEM_PROMPT : withContentLanguageDirective(CURATE_SYSTEM_PROMPT, config2.language ?? deps.language),
194034
194165
  ...modelBodyField(config2.model),
194035
194166
  parts: [{ type: "text", text: taskPrompt, synthetic: true }]
194036
194167
  }
@@ -194852,7 +194983,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
194852
194983
  }
194853
194984
  try {
194854
194985
  await runCompiledSmartNoteSweep(reg, db);
194855
- const runtimeConfigs = buildDreamTaskRuntimeConfigs(dreamerConfig);
194986
+ const runtimeConfigs = buildDreamTaskRuntimeConfigs(dreamerConfig, reg.language);
194856
194987
  const executor = createDreamTaskExecutor({
194857
194988
  client: reg.client,
194858
194989
  sessionDirectory: reg.directory,
@@ -194860,7 +194991,8 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
194860
194991
  retrospectiveRawProvider: reg.retrospectiveRawProvider ?? ((db2) => new OpenCodeRetrospectiveRawProvider({ contextDb: db2, openOpenCodeDb })),
194861
194992
  primerRawProviderFactory: reg.primerRawProviderFactory,
194862
194993
  userMemoryCollectionEnabled: userMemoryCollectionEnabled(dreamerConfig),
194863
- ensureProjectRegistered: reg.ensureRegistered
194994
+ ensureProjectRegistered: reg.ensureRegistered,
194995
+ language: reg.language
194864
194996
  });
194865
194997
  const ran = await runDueTasksForProject({
194866
194998
  db,
@@ -196224,7 +196356,8 @@ Provide a prompt to augment with project memory context.`, {});
196224
196356
  projectPath: deps.sidekick.projectPath,
196225
196357
  sessionDirectory: deps.sidekick.sessionDirectory,
196226
196358
  userMessage: prompt,
196227
- config: deps.sidekick.config
196359
+ config: deps.sidekick.config,
196360
+ language: deps.sidekick.language
196228
196361
  });
196229
196362
  let augmentedPrompt;
196230
196363
  if (sidekickResult) {
@@ -196831,6 +196964,7 @@ function channel1RefireTokens(workingWindowTokens) {
196831
196964
  var S_GENTLE = 0.2;
196832
196965
  var S_FIRM = 0.4;
196833
196966
  var S_URGENT = 0.65;
196967
+ var CHANNEL1_PRESSURE_FLOOR = 0.8;
196834
196968
  var LEVEL_RANK = { gentle: 1, firm: 2, urgent: 3 };
196835
196969
  var DROP_SENTINELS = ["[dropped", "[truncated"];
196836
196970
  function isDroppedToolOutput(output) {
@@ -196895,7 +197029,8 @@ function computeTailTokenEstimate(messages) {
196895
197029
  };
196896
197030
  }
196897
197031
  function decideChannel1(input) {
196898
- const { undroppedTokens, pressure, workingWindowTokens, hasRecentReduce } = input;
197032
+ const { undroppedTokens, workingWindowTokens, hasRecentReduce } = input;
197033
+ const pressure = Math.min(1, Math.max(0, input.pressure));
196899
197034
  const resetCycle = hasRecentReduce || undroppedTokens < input.lastNudgeUndropped;
196900
197035
  const lastNudge = resetCycle ? 0 : input.lastNudgeUndropped;
196901
197036
  const lastLevel = resetCycle ? "" : input.lastNudgeLevel;
@@ -196910,8 +197045,10 @@ function decideChannel1(input) {
196910
197045
  return quiet();
196911
197046
  if (undroppedTokens < CHANNEL1_FLOOR_TOKENS)
196912
197047
  return quiet();
196913
- const budget = workingWindowTokens > 0 ? workingWindowTokens : undroppedTokens || 1;
196914
- const severity = undroppedTokens / budget * pressure;
197048
+ if (pressure < CHANNEL1_PRESSURE_FLOOR)
197049
+ return quiet();
197050
+ const denom = Math.max(input.estimatedInputTokens, 1);
197051
+ const severity = Math.min(1, undroppedTokens / denom);
196915
197052
  if (severity < S_GENTLE)
196916
197053
  return quiet();
196917
197054
  let level;
@@ -202764,6 +202901,7 @@ function maybeInjectChannel1Nudge(args, sessionId, tool, output) {
202764
202901
  const decision = decideChannel1({
202765
202902
  undroppedTokens,
202766
202903
  pressure,
202904
+ estimatedInputTokens: state.lastInputTokens + state.turnToolTokens,
202767
202905
  workingWindowTokens,
202768
202906
  lastNudgeUndropped: getLastNudgeUndropped(args.db, sessionId),
202769
202907
  lastNudgeLevel: getLastNudgeLevel(args.db, sessionId),
@@ -202829,6 +202967,7 @@ init_send_session_notification();
202829
202967
  import { createHash as createHash13 } from "node:crypto";
202830
202968
 
202831
202969
  // src/agents/magic-context-prompt.ts
202970
+ init_language_directive();
202832
202971
  var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
202833
202972
 
202834
202973
  Most AI sessions are disposable: one session per task, discarded when it's done — like hiring a developer for a single bug fix and letting them go the moment they finish. Magic Context changes this completely. This session is a durable working relationship: you carry the full history and accumulated knowledge of this project, and you continue across many tasks, bugs, and features — with memory that persists across restarts. This session may continue for weeks, months, or even years.
@@ -202907,7 +203046,7 @@ Drop silently — do not narrate it. NEVER drop large ranges blindly (e.g., "1-5
202907
203046
  Older tool calls may show \`[dropped §N§]\` sentinels; that is normal context management, not a pattern to copy. ALWAYS make fresh real tool calls when you need data again; never fabricate or inline tool output.`;
202908
203047
  var CAVEMAN_COMPRESSION_WARNING = `
202909
203048
  **BEWARE**: History compression is on; older user AND assistant text — including your own earlier responses — has been deterministically rewritten in a terse caveman style (dropped articles, missing auxiliaries, \`//\` instead of connectives like \`because\`). This is automatic context compression that runs after the fact, not your actual prior wording or the user's. **DO NOT mimic this style in new turns.** Write fresh responses in normal prose. If you notice your output drifting into caveman cadence, that drift is in-context-learning bleeding from the compressed history — consciously revert to full sentences.`;
202910
- function buildMagicContextSection(_agent, protectedTags, ctxReduceEnabled = true, dreamerEnabled = false, temporalAwarenessEnabled = false, cavemanTextCompressionEnabled = false, subagentMode = false) {
203049
+ function buildMagicContextSection(_agent, protectedTags, ctxReduceEnabled = true, dreamerEnabled = false, temporalAwarenessEnabled = false, cavemanTextCompressionEnabled = false, subagentMode = false, language) {
202911
203050
  if (subagentMode) {
202912
203051
  return `## Magic Context
202913
203052
 
@@ -202919,13 +203058,17 @@ The dreamer evaluates smart note conditions during nightly runs and surfaces the
202919
203058
  Example: \`ctx_note(action="write", content="Implement X because Y", surface_condition="When PR #42 is merged in this repo")\`` : "";
202920
203059
  const temporalGuidance = temporalAwarenessEnabled ? TEMPORAL_AWARENESS_GUIDANCE : "";
202921
203060
  const cavemanWarning = cavemanTextCompressionEnabled && !ctxReduceEnabled ? CAVEMAN_COMPRESSION_WARNING : "";
203061
+ const languageDirective = buildPrimaryLanguageDirective(language);
203062
+ const languageGuidance = languageDirective ? `
203063
+
203064
+ ${languageDirective}` : "";
202922
203065
  if (!ctxReduceEnabled) {
202923
203066
  return `## Magic Context
202924
203067
 
202925
203068
  ${LONG_TERM_PARTNER_FRAME}
202926
203069
  ${PARTNER_FRAME_CLOSER_NO_REDUCE}
202927
203070
 
202928
- ${BASE_INTRO_NO_REDUCE()}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}`;
203071
+ ${BASE_INTRO_NO_REDUCE()}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}${languageGuidance}`;
202929
203072
  }
202930
203073
  return `## Magic Context
202931
203074
 
@@ -202935,7 +203078,7 @@ ${PARTNER_FRAME_CLOSER_REDUCE}
202935
203078
  ${BASE_INTRO(protectedTags)}${smartNoteGuidance}${temporalGuidance}
202936
203079
  ${GENERIC_SECTION}
202937
203080
 
202938
- Prefer many small targeted operations over one large blanket operation, and keep the working set tidy as routine maintenance.`;
203081
+ Prefer many small targeted operations over one large blanket operation, and keep the working set tidy as routine maintenance.${languageGuidance}`;
202939
203082
  }
202940
203083
 
202941
203084
  // src/hooks/magic-context/system-prompt-hash.ts
@@ -202993,7 +203136,7 @@ function createSystemPromptHashHandler(deps) {
202993
203136
  const fullPrompt = output.system.join(`
202994
203137
  `);
202995
203138
  if (fullPrompt.length > 0 && !fullPrompt.includes(MAGIC_CONTEXT_MARKER) && !skipGuidanceForDisabledSubagent) {
202996
- const guidance = buildMagicContextSection(null, deps.protectedTags, effectiveCtxReduceEnabled, deps.dreamerEnabled, deps.experimentalTemporalAwareness, deps.experimentalCavemanTextCompression, subagentReduceMode);
203139
+ const guidance = buildMagicContextSection(null, deps.protectedTags, effectiveCtxReduceEnabled, deps.dreamerEnabled, deps.experimentalTemporalAwareness, deps.experimentalCavemanTextCompression, subagentReduceMode, deps.language);
202997
203140
  output.system.push(guidance);
202998
203141
  sessionLog(sessionId, `injected generic guidance into system prompt (ctxReduce=${effectiveCtxReduceEnabled}, subagent=${isSubagentSession}, subagentReduceMode=${subagentReduceMode})`);
202999
203142
  }
@@ -203281,6 +203424,7 @@ function createMagicContextHook(deps) {
203281
203424
  memoryEnabled: deps.config.memory?.enabled ?? true,
203282
203425
  autoPromote: deps.config.memory?.auto_promote ?? true,
203283
203426
  fallbackModels: historianFallbackModels,
203427
+ language: deps.config.language,
203284
203428
  fallbackModelId: (() => {
203285
203429
  const model = resolveLiveModel(sessionId);
203286
203430
  return model ? `${model.providerID}/${model.modelID}` : undefined;
@@ -203319,7 +203463,7 @@ function createMagicContextHook(deps) {
203319
203463
  signal,
203320
203464
  onProgress: ({ embedded, total }) => {
203321
203465
  const cur = recompProgressBySession.get(sessionId);
203322
- if (!cur || cur.phase !== "recomp")
203466
+ if (cur?.phase !== "recomp")
203323
203467
  return;
203324
203468
  recompProgressBySession.set(sessionId, {
203325
203469
  ...cur,
@@ -203522,7 +203666,7 @@ function createMagicContextHook(deps) {
203522
203666
  return;
203523
203667
  }
203524
203668
  lastScheduleCheckMs = now;
203525
- const runtimeConfigs = buildDreamTaskRuntimeConfigs(dreaming);
203669
+ const runtimeConfigs = buildDreamTaskRuntimeConfigs(dreaming, deps.config.language);
203526
203670
  const executor = createDreamTaskExecutor({
203527
203671
  client: deps.client,
203528
203672
  sessionDirectory: deps.directory,
@@ -203531,7 +203675,8 @@ function createMagicContextHook(deps) {
203531
203675
  contextDb: providerDb,
203532
203676
  openOpenCodeDb
203533
203677
  }),
203534
- userMemoryCollectionEnabled: userMemoryCollectionEnabled(dreaming)
203678
+ userMemoryCollectionEnabled: userMemoryCollectionEnabled(dreaming),
203679
+ language: deps.config.language
203535
203680
  });
203536
203681
  runDueTasksForProject({
203537
203682
  db,
@@ -203580,7 +203725,8 @@ function createMagicContextHook(deps) {
203580
203725
  config: sidekickConfig,
203581
203726
  projectPath,
203582
203727
  sessionDirectory: deps.directory,
203583
- client: deps.client
203728
+ client: deps.client,
203729
+ language: deps.config.language
203584
203730
  } : undefined,
203585
203731
  dreamer: dreamerConfig ? {
203586
203732
  config: dreamerConfig,
@@ -203588,7 +203734,7 @@ function createMagicContextHook(deps) {
203588
203734
  runManual: (task) => runManualDream({
203589
203735
  db,
203590
203736
  projectIdentity: projectPath,
203591
- tasks: buildDreamTaskRuntimeConfigs(dreamerConfig),
203737
+ tasks: buildDreamTaskRuntimeConfigs(dreamerConfig, deps.config.language),
203592
203738
  executor: createDreamTaskExecutor({
203593
203739
  client: deps.client,
203594
203740
  sessionDirectory: deps.directory,
@@ -203597,7 +203743,8 @@ function createMagicContextHook(deps) {
203597
203743
  contextDb: providerDb,
203598
203744
  openOpenCodeDb
203599
203745
  }),
203600
- userMemoryCollectionEnabled: userMemoryCollectionEnabled(dreamerConfig)
203746
+ userMemoryCollectionEnabled: userMemoryCollectionEnabled(dreamerConfig),
203747
+ language: deps.config.language
203601
203748
  }),
203602
203749
  task
203603
203750
  })
@@ -203608,6 +203755,7 @@ function createMagicContextHook(deps) {
203608
203755
  protectedTags: deps.config.protected_tags,
203609
203756
  ctxReduceEnabled,
203610
203757
  dreamerEnabled: dreamerRunnable,
203758
+ language: deps.config.language,
203611
203759
  injectDocs: deps.config.dreamer?.inject_docs !== false,
203612
203760
  directory: deps.directory,
203613
203761
  historyRefreshSessions,
@@ -206339,6 +206487,7 @@ var server2 = async (ctx) => {
206339
206487
  projectIdentity: resolveProjectIdentity(ctx.directory),
206340
206488
  client: ctx.client,
206341
206489
  dreamerConfig: dreamerRunnable ? pluginConfig.dreamer : undefined,
206490
+ language: pluginConfig.language,
206342
206491
  embeddingConfig: pluginConfig.embedding,
206343
206492
  memoryEnabled: pluginConfig.memory?.enabled === true,
206344
206493
  gitCommitIndexing: pluginConfig.memory.git_commit_indexing?.enabled ? {
@@ -206510,9 +206659,9 @@ var server2 = async (ctx) => {
206510
206659
  const registrations = buildHiddenAgentRegistrations({
206511
206660
  dreamerPrompt: DREAMER_SYSTEM_PROMPT,
206512
206661
  smartNoteCompilerPrompt: SMART_NOTE_COMPILER_SYSTEM_PROMPT,
206513
- historianPrompt: COMPARTMENT_AGENT_SYSTEM_PROMPT,
206514
- historianRecompPrompt: COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT,
206515
- historianEditorPrompt: HISTORIAN_EDITOR_SYSTEM_PROMPT,
206662
+ historianPrompt: withContentLanguageDirective(COMPARTMENT_AGENT_SYSTEM_PROMPT, pluginConfig.language, { preserveUserQuotes: true }),
206663
+ historianRecompPrompt: withContentLanguageDirective(COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, pluginConfig.language, { preserveUserQuotes: true }),
206664
+ historianEditorPrompt: withContentLanguageDirective(HISTORIAN_EDITOR_SYSTEM_PROMPT, pluginConfig.language, { preserveUserQuotes: true }),
206516
206665
  sidekickPrompt: SIDEKICK_SYSTEM_PROMPT,
206517
206666
  dreamerOverrides: dreamerAgentOverrides,
206518
206667
  historianOverrides: historianAgentOverrides,
@@ -14,6 +14,7 @@ interface ProjectRegistration {
14
14
  projectIdentity: string;
15
15
  client: PluginContext["client"];
16
16
  dreamerConfig?: DreamerConfig;
17
+ language?: string;
17
18
  gitCommitIndexing?: {
18
19
  enabled: boolean;
19
20
  since_days: number;