@cortexkit/opencode-magic-context 0.3.1 → 0.3.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"magic-context-prompt.d.ts","sourceRoot":"","sources":["../../src/agents/magic-context-prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,KAAK,SAAS,GACR,UAAU,GACV,OAAO,GACP,YAAY,GACZ,iBAAiB,GACjB,QAAQ,GACR,QAAQ,GACR,eAAe,CAAC;AAoLtB;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAOlF;AAED,wBAAgB,wBAAwB,CACpC,KAAK,EAAE,SAAS,GAAG,IAAI,EACvB,aAAa,EAAE,MAAM,EACrB,gBAAgB,UAAO,EACvB,cAAc,UAAQ,GACvB,MAAM,CAUR"}
1
+ {"version":3,"file":"magic-context-prompt.d.ts","sourceRoot":"","sources":["../../src/agents/magic-context-prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,KAAK,SAAS,GACR,UAAU,GACV,OAAO,GACP,YAAY,GACZ,iBAAiB,GACjB,QAAQ,GACR,QAAQ,GACR,eAAe,CAAC;AA4LtB;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAOlF;AAED,wBAAgB,wBAAwB,CACpC,KAAK,EAAE,SAAS,GAAG,IAAI,EACvB,aAAa,EAAE,MAAM,EACrB,gBAAgB,UAAO,EACvB,cAAc,UAAQ,GACvB,MAAM,CAUR"}
@@ -1 +1 @@
1
- {"version":3,"file":"storage-db.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/storage-db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAiBtC,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAuPrD;AA6BD,wBAAgB,YAAY,IAAI,QAAQ,CAqCvC;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAEzD;AAED,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAEvE;AAED,wBAAgB,aAAa,IAAI,IAAI,CAUpC;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC"}
1
+ {"version":3,"file":"storage-db.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/storage-db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAiBtC,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAwPrD;AA6BD,wBAAgB,YAAY,IAAI,QAAQ,CAqCvC;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAEzD;AAED,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAEvE;AAED,wBAAgB,aAAa,IAAI,IAAI,CAUpC;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import type { Database } from "bun:sqlite";
2
2
  import type { TagEntry } from "./types";
3
- export declare function insertTag(db: Database, sessionId: string, messageId: string, type: TagEntry["type"], byteSize: number, tagNumber: number): number;
3
+ export declare function insertTag(db: Database, sessionId: string, messageId: string, type: TagEntry["type"], byteSize: number, tagNumber: number, reasoningByteSize?: number): number;
4
4
  export declare function updateTagStatus(db: Database, sessionId: string, tagId: number, status: TagEntry["status"]): void;
5
5
  export declare function updateTagMessageId(db: Database, sessionId: string, tagId: number, messageId: string): void;
6
6
  export declare function deleteTagsByMessageId(db: Database, sessionId: string, messageId: string): number[];
@@ -1 +1 @@
1
- {"version":3,"file":"storage-tags.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/storage-tags.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAuIxC,wBAAgB,SAAS,CACrB,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAClB,MAAM,CAIR;AAED,wBAAgB,eAAe,CAC3B,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAC3B,IAAI,CAEN;AAED,wBAAgB,kBAAkB,CAC9B,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAClB,IAAI,CAEN;AAED,wBAAgB,qBAAqB,CACjC,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,MAAM,EAAE,CAoBV;AAED,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGhF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE,CAS5E;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAY1F;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CAapF"}
1
+ {"version":3,"file":"storage-tags.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/storage-tags.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AA0IxC,wBAAgB,SAAS,CACrB,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,iBAAiB,GAAE,MAAU,GAC9B,MAAM,CAWR;AAED,wBAAgB,eAAe,CAC3B,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAC3B,IAAI,CAEN;AAED,wBAAgB,kBAAkB,CAC9B,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAClB,IAAI,CAEN;AAED,wBAAgB,qBAAqB,CACjC,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,MAAM,EAAE,CAoBV;AAED,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGhF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE,CAS5E;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAY1F;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CAapF"}
@@ -1,7 +1,7 @@
1
1
  import type { Database } from "bun:sqlite";
2
2
  import type { TagEntry } from "./types";
3
3
  export interface Tagger {
4
- assignTag(sessionId: string, messageId: string, type: TagEntry["type"], byteSize: number, db: Database): number;
4
+ assignTag(sessionId: string, messageId: string, type: TagEntry["type"], byteSize: number, db: Database, reasoningByteSize?: number): number;
5
5
  getTag(sessionId: string, messageId: string): number | undefined;
6
6
  bindTag(sessionId: string, messageId: string, tagNumber: number): void;
7
7
  getAssignments(sessionId: string): ReadonlyMap<string, number>;
@@ -1 +1 @@
1
- {"version":3,"file":"tagger.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/tagger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,MAAM,WAAW,MAAM;IACnB,SAAS,CACL,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EACtB,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,QAAQ,GACb,MAAM,CAAC;IACV,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACjE,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACvE,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/D,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,IAAI,CAAC;IACpD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,IAAI,CAAC;IAClD,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAuCD,wBAAgB,YAAY,IAAI,MAAM,CA2GrC"}
1
+ {"version":3,"file":"tagger.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/tagger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,MAAM,WAAW,MAAM;IACnB,SAAS,CACL,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EACtB,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,QAAQ,EACZ,iBAAiB,CAAC,EAAE,MAAM,GAC3B,MAAM,CAAC;IACV,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACjE,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACvE,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/D,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,IAAI,CAAC;IACpD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,IAAI,CAAC;IAClD,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAuCD,wBAAgB,YAAY,IAAI,MAAM,CA4GrC"}
@@ -4,6 +4,7 @@ export interface TagEntry {
4
4
  type: "message" | "tool" | "file";
5
5
  status: "active" | "dropped" | "compacted";
6
6
  byteSize: number;
7
+ reasoningByteSize: number;
7
8
  sessionId: string;
8
9
  }
9
10
  export interface PendingOp {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IAClC,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC;IAC7D,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,4BAA4B,EAAE,MAAM,CAAC;IACrC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,0BAA0B,EAAE,MAAM,CAAC;CACtC;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpD,MAAM,WAAW,YAAY;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACvB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IAClC,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC;IAC7D,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,4BAA4B,EAAE,MAAM,CAAC;IACrC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,0BAA0B,EAAE,MAAM,CAAC;CACtC;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpD,MAAM,WAAW,YAAY;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACvB"}
@@ -1,4 +1,4 @@
1
- export declare const COMPARTMENT_AGENT_SYSTEM_PROMPT = "You condense long AI coding sessions into two outputs:\n\n1. compartments: completed logical work units\n2. facts: persistent cross-cutting information for future work\n\nCompartment rules:\n- A compartment is one contiguous completed work unit: investigation, fix, refactor, docs update, feature, or decision.\n- Start a new compartment only when the work clearly pivots to a different objective.\n- Do not create compartments for magic-context commands or tool-only noise.\n- If the input ends mid-topic, leave it out and report its first message index in <unprocessed_from>.\n- All compartment start/end ordinals and <unprocessed_from> must use the absolute raw message numbers shown in the input. Never renumber relative to this chunk.\n- Only emit NEW compartments for the new messages. Do not re-emit existing compartments from the existing state.\n- Write comprehensive, detailed compartments. Include file paths, function names, commit hashes, config keys, and values when they matter.\n- Do not list every changed file. Do not narrate tool calls. Do not preserve dead-end exploration beyond a brief clause when needed.\n\nUser message preservation:\n- Include high-signal user messages verbatim inside compartments, prefixed with U:.\n- A high-signal user message states a goal, constraint, design decision, direction, preference, or rationale.\n- Drop trivial messages: yes, continue, I agree, thanks, looks good, go ahead, and similar low-signal steering.\n- Drop large pasted text unless it contains durable rules or requirements; summarize its gist instead.\n- Place U: lines at the point in the summary where the user's direction changed the work.\n- Limit to 3-5 U: lines per compartment \u2014 keep only the most important ones.\n\nCompartment example:\n<compartment start=\"50\" end=\"120\" title=\"Built the LSP stack\">\nU: We need inline diagnostics on every edit, not just on-demand\nImplemented in-process LSP client with per-server reader threads and crossbeam-channel delivery. Added inline edit diagnostics to write, edit, and apply_patch. commits: a3f891, b22c4e\nU: Ship this as 0.2.0\nUpdated docs and publish automation, released v0.2.0.\n</compartment>\n\nFact rules:\n- Facts are editable state, not append-only notes. Rewrite, normalize, deduplicate, or drop existing facts whenever needed.\n- Before emitting any fact, check all existing facts in the same category for semantic duplicates. If two facts describe the same decision, constraint, or default with different wording, merge them into one canonical statement. Never emit two facts that could be answered by the same question.\n- When project memories are provided as read-only reference, drop any session fact that is already covered by a project memory. Project memories are the canonical cross-session source; session facts must not duplicate them.\n- Facts must be durable and actionable after the conversation ends.\n- A fact is either a stable invariant/default or a reusable operating rule. If it mainly explains what happened, it belongs in a compartment, not a fact.\n- Facts belong only in these categories when relevant: WORKFLOW_RULES, ARCHITECTURE_DECISIONS, CONSTRAINTS, CONFIG_DEFAULTS, KNOWN_ISSUES, ENVIRONMENT, NAMING, USER_PREFERENCES, USER_DIRECTIVES.\n- Keep only high-signal facts. Omit greetings, acknowledgements, temporary status, one-off sequencing, branch-local tactics, and task-local cleanup notes.\n- When a user message carries durable goals, constraints, preferences, or decision rationale, add a USER_DIRECTIVES fact when future agents should follow it after the session is compacted.\n- Do not turn task-local details into facts.\n- Do not keep stale facts. Rewrite or drop them even if the new input only implies they are obsolete.\n- Keep existing ARCHITECTURE_DECISIONS and CONSTRAINTS facts when they are still valid and uncontradicted; rewrite them into canonical form instead of dropping them.\n- Facts must be present tense and operational. Do not use chronology or provenance wording such as: initially, currently, remained, previously, later, then, was implemented, we changed, used to.\n- One fact bullet must contain exactly one rule/default/constraint/preference. If a candidate fact mixes history with guidance, keep the guidance and drop the history.\n- Durability test: a future agent should still act correctly on the fact next session, after merge/restart, without rereading the conversation.\n- Category guide:\n - WORKFLOW_RULES: standing repeatable process only. Prefer Do/When form: When <condition>, <action>. Do not store one-off branch strategy or task-specific sequencing unless it is standing policy.\n - ARCHITECTURE_DECISIONS: stable design choice. Use: <component> uses <choice> because <reason>.\n - CONSTRAINTS: hard must/must-not rule or invariant. Use: <thing> must/must not <action> because <reason>.\n - CONFIG_DEFAULTS: stable default only. Use: <key>=<value>.\n - KNOWN_ISSUES: unresolved recurring problem only. Do not store solved-issue stories.\n - ENVIRONMENT: stable setup fact that affects future work.\n - NAMING: canonical term choice. Use: Use <term>; avoid <term>.\n - USER_PREFERENCES: durable user preference. Prefer Do/When form.\n - USER_DIRECTIVES: durable user-stated goal, constraint, preference, or rationale. Keep the user's wording when it carries meaning, but narrow it to 1-3 sentences and remove filler.\n- Fact dedup examples:\n - These are DUPLICATES (merge into one): \"Plugin config uses layered JSONC files\" and \"AFT plugin config uses layered JSONC files at ~/.config/opencode/aft.jsonc and <project>/.opencode/aft.jsonc, with project values deep-merging over user values.\" \u2192 keep the longer, more specific version only.\n - These are NOT duplicates (keep both): \"AFT uses 1-based line numbers\" and \"AFT converts to LSP 0-based UTF-16 at the protocol boundary\" \u2192 different aspects of the same system.\n- Fact rewrite examples:\n - Bad ARCHITECTURE_DECISIONS: The new tool-heavy `ctx_reduce` reminder was initially implemented as a hidden instruction appended to the latest user message in `transform`.\n - Good ARCHITECTURE_DECISIONS: `ctx_reduce` turn reminders are injected into the latest user message in `transform`.\n - Bad WORKFLOW_RULES: Current local workflow remained feat -> integrate -> build for code changes.\n - Good WORKFLOW_RULES (only if this is standing policy): For magic-context changes, commit on `feat/magic-context`, cherry-pick to `integrate/athena-magic-context`, run `bun run build` on integrate, then return to `feat/magic-context`.\n\nInput notes:\n- [N] or [N-M] is a stable raw OpenCode message range.\n- U: means user.\n- A: means assistant.\n- commits: ... on an assistant block lists commit hashes mentioned in that work unit; keep the relevant ones in the compartment summary when they matter.\n- Tool-only noise is already stripped before you see the input.\n\nOutput valid XML only in this shape:\n<output>\n<compartments>\n<compartment start=\"FIRST\" end=\"LAST\" title=\"short title\">\nU: Verbatim high-signal user message\nSummary text describing what was done and why.\nU: Another high-signal user message if applicable\nMore summary text.\n</compartment>\n</compartments>\n<facts>\n<WORKFLOW_RULES>\n* Fact text\n</WORKFLOW_RULES>\n</facts>\n<meta>\n<messages_processed>FIRST-LAST</messages_processed>\n<unprocessed_from>INDEX</unprocessed_from>\n</meta>\n</output>\n\nOmit empty fact categories. Compartments must be ordered, contiguous for the ranges they cover, and non-overlapping.";
1
+ export declare const COMPARTMENT_AGENT_SYSTEM_PROMPT = "You condense long AI coding sessions into two outputs:\n\n1. compartments: completed logical work units\n2. facts: persistent cross-cutting information for future work\n\nCompartment rules:\n- A compartment is one contiguous completed work unit: investigation, fix, refactor, docs update, feature, or decision.\n- Start a new compartment only when the work clearly pivots to a different objective.\n- Do not create compartments for magic-context commands or tool-only noise.\n- If the input ends mid-topic, leave it out and report its first message index in <unprocessed_from>.\n- All compartment start/end ordinals and <unprocessed_from> must use the absolute raw message numbers shown in the input. Never renumber relative to this chunk.\n- Only emit NEW compartments for the new messages. Do not re-emit existing compartments from the existing state.\n- Write comprehensive, detailed compartments. Include file paths, function names, commit hashes, config keys, and values when they matter.\n- Do not list every changed file. Do not narrate tool calls. Do not preserve dead-end exploration beyond a brief clause when needed.\n\nUser message preservation:\n- Include high-signal user messages verbatim inside compartments, prefixed with U:.\n- A high-signal user message states a goal, constraint, design decision, direction, preference, or rationale.\n- Drop trivial messages: yes, continue, I agree, thanks, looks good, go ahead, and similar low-signal steering.\n- Drop large pasted text unless it contains durable rules or requirements; summarize its gist instead.\n- Place U: lines at the point in the summary where the user's direction changed the work.\n- Limit to 3-5 U: lines per compartment \u2014 keep only the most important ones.\n\nCompartment example:\n<compartment start=\"50\" end=\"120\" title=\"Built the LSP stack\">\nU: We need inline diagnostics on every edit, not just on-demand\nImplemented in-process LSP client with per-server reader threads and crossbeam-channel delivery. Added inline edit diagnostics to write, edit, and apply_patch. commits: a3f891, b22c4e\nU: Ship this as 0.2.0\nUpdated docs and publish automation, released v0.2.0.\n</compartment>\n\nFact rules:\n- Facts are editable state, not append-only notes. Rewrite, normalize, deduplicate, or drop existing facts whenever needed.\n- Before emitting any fact, check all existing facts in the same category for semantic duplicates. If two facts describe the same decision, constraint, or default with different wording, merge them into one canonical statement. Never emit two facts that could be answered by the same question.\n- When project memories are provided as read-only reference, drop any session fact that is already covered by a project memory. Project memories are the canonical cross-session source; session facts must not duplicate them.\n- Facts must be durable and actionable after the conversation ends.\n- A fact is either a stable invariant/default or a reusable operating rule. If it mainly explains what happened, it belongs in a compartment, not a fact.\n- Facts belong only in these categories when relevant: WORKFLOW_RULES, ARCHITECTURE_DECISIONS, CONSTRAINTS, CONFIG_DEFAULTS, KNOWN_ISSUES, ENVIRONMENT, NAMING, USER_PREFERENCES, USER_DIRECTIVES.\n- Keep only high-signal facts. Omit greetings, acknowledgements, temporary status, one-off sequencing, branch-local tactics, and task-local cleanup notes.\n- When a user message carries durable goals, constraints, preferences, or decision rationale, add a USER_DIRECTIVES fact when future agents should follow it after the session is compacted.\n- Do not turn task-local details into facts.\n- Do not keep stale facts. Rewrite or drop them even if the new input only implies they are obsolete.\n- Keep existing ARCHITECTURE_DECISIONS and CONSTRAINTS facts when they are still valid and uncontradicted; rewrite them into canonical form instead of dropping them.\n- Facts must be present tense and operational. Do not use chronology or provenance wording such as: initially, currently, remained, previously, later, then, was implemented, we changed, used to.\n- One fact bullet must contain exactly one rule/default/constraint/preference. If a candidate fact mixes history with guidance, keep the guidance and drop the history.\n- Durability test: a future agent should still act correctly on the fact next session, after merge/restart, without rereading the conversation.\n- Category guide:\n - WORKFLOW_RULES: standing repeatable process only. Prefer Do/When form: When <condition>, <action>. Do not store one-off branch strategy or task-specific sequencing unless it is standing policy.\n - ARCHITECTURE_DECISIONS: stable design choice. Use: <component> uses <choice> because <reason>.\n - CONSTRAINTS: hard must/must-not rule or invariant. Use: <thing> must/must not <action> because <reason>.\n - CONFIG_DEFAULTS: stable default only. Use: <key>=<value>.\n - KNOWN_ISSUES: unresolved recurring problem only. Do not store solved-issue stories.\n - ENVIRONMENT: stable setup fact that affects future work.\n - NAMING: canonical term choice. Use: Use <term>; avoid <term>.\n - USER_PREFERENCES: durable user preference. Prefer Do/When form.\n - USER_DIRECTIVES: durable user-stated goal, constraint, preference, or rationale. Keep the user's wording when it carries meaning, but narrow it to 1-3 sentences and remove filler.\n- Fact dedup examples:\n - These are DUPLICATES (merge into one): \"Plugin config uses layered JSONC files\" and \"AFT plugin config uses layered JSONC files at ~/.config/opencode/aft.jsonc and <project>/.opencode/aft.jsonc, with project values deep-merging over user values.\" \u2192 keep the longer, more specific version only.\n - These are NOT duplicates (keep both): \"AFT uses 1-based line numbers\" and \"AFT converts to LSP 0-based UTF-16 at the protocol boundary\" \u2192 different aspects of the same system.\n- Fact rewrite examples:\n - Bad ARCHITECTURE_DECISIONS: The new tool-heavy `ctx_reduce` reminder was initially implemented as a hidden instruction appended to the latest user message in `transform`.\n - Good ARCHITECTURE_DECISIONS: `ctx_reduce` turn reminders are injected into the latest user message in `transform`.\n - Bad WORKFLOW_RULES: Current local workflow remained feat -> integrate -> build for code changes.\n - Good WORKFLOW_RULES (only if this is standing policy): For magic-context changes, commit on `feat/magic-context`, cherry-pick to `integrate/athena-magic-context`, run `bun run build` on integrate, then return to `feat/magic-context`.\n\nInput notes:\n- [N] or [N-M] is a stable raw OpenCode message range.\n- U: means user.\n- A: means assistant.\n- TC: means tool call \u2014 a compact summary of what the agent did (e.g., \"TC: Fix lint errors\", \"TC: read(src/index.ts)\", \"TC: grep(ctx_memory)\"). TC lines appear when there is no text describing the action. Use them to understand what happened between text blocks, but do not copy them verbatim into compartments \u2014 incorporate their meaning into the narrative.\n- commits: ... on an assistant block lists commit hashes mentioned in that work unit; keep the relevant ones in the compartment summary when they matter.\n\nOutput valid XML only in this shape:\n<output>\n<compartments>\n<compartment start=\"FIRST\" end=\"LAST\" title=\"short title\">\nU: Verbatim high-signal user message\nSummary text describing what was done and why.\nU: Another high-signal user message if applicable\nMore summary text.\n</compartment>\n</compartments>\n<facts>\n<WORKFLOW_RULES>\n* Fact text\n</WORKFLOW_RULES>\n</facts>\n<meta>\n<messages_processed>FIRST-LAST</messages_processed>\n<unprocessed_from>INDEX</unprocessed_from>\n</meta>\n</output>\n\nOmit empty fact categories. Compartments must be ordered, contiguous for the ranges they cover, and non-overlapping.";
2
2
  export declare const COMPRESSOR_AGENT_SYSTEM_PROMPT = "You compress older compartments from a long AI coding session to fit within a token budget.\n\nYou receive a set of compartments that are over budget. Your job is to merge and shorten them so the total output is approximately the target token count.\n\nRules:\n- You have full authority over which compartments to merge and which to keep separate.\n- Merged compartments must cover the same start-to-end range as the originals they replace.\n- Drop verbatim U: (user message) lines from merged compartments. Instead, summarize the user's key intent in the prose: \"User directed X. Implemented Y.\"\n- Keep summaries outcome-focused. Mention file paths, function names, commit hashes, and config keys only when they matter conceptually.\n- You may merge 2-5 adjacent compartments into one broader compartment when they share a theme or phase of work.\n- You may keep a compartment separate but shorten its summary.\n- Do not add new information. Do not invent details not present in the input.\n- Compartments must remain ordered and non-overlapping.\n- Preserve the start and end ordinals exactly from the original compartments.\n\nOutput valid XML only in this shape:\n<output>\n<compartments>\n<compartment start=\"FIRST\" end=\"LAST\" title=\"short title\">Compressed summary text.</compartment>\n</compartments>\n</output>";
3
3
  export declare function buildCompressorPrompt(compartments: Array<{
4
4
  startMessage: number;
@@ -1 +1 @@
1
- {"version":3,"file":"compartment-prompt.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/compartment-prompt.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,+BAA+B,o4OA6FyE,CAAC;AAEtH,eAAO,MAAM,8BAA8B,ozCAoBjC,CAAC;AAEX,wBAAgB,qBAAqB,CACjC,YAAY,EAAE,KAAK,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC,EACF,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,GACrB,MAAM,CAgBR;AAED,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAiB9F"}
1
+ {"version":3,"file":"compartment-prompt.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/compartment-prompt.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,+BAA+B,4rPA6FyE,CAAC;AAEtH,eAAO,MAAM,8BAA8B,ozCAoBjC,CAAC;AAEX,wBAAgB,qBAAqB,CACjC,YAAY,EAAE,KAAK,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC,EACF,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,GACrB,MAAM,CAgBR;AAED,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAiB9F"}
@@ -10,5 +10,5 @@ export interface CompartmentTriggerResult {
10
10
  reason?: "projected_headroom" | "force_80" | "commit_clusters" | "tail_size";
11
11
  }
12
12
  export declare function getProactiveCompartmentTriggerPercentage(executeThresholdPercentage: number): number;
13
- export declare function checkCompartmentTrigger(db: Database, sessionId: string, sessionMeta: SessionMeta, usage: ContextUsage, _previousPercentage: number, executeThresholdPercentage: number, compartmentTokenBudget?: number): CompartmentTriggerResult;
13
+ export declare function checkCompartmentTrigger(db: Database, sessionId: string, sessionMeta: SessionMeta, usage: ContextUsage, _previousPercentage: number, executeThresholdPercentage: number, compartmentTokenBudget?: number, autoDropToolAge?: number, protectedTagCount?: number, clearReasoningAge?: number): CompartmentTriggerResult;
14
14
  //# sourceMappingURL=compartment-trigger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compartment-trigger.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/compartment-trigger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAUpF,QAAA,MAAM,sBAAsB,OAAO,CAAC;AAKpC,QAAA,MAAM,4BAA4B,KAAK,CAAC;AACxC,QAAA,MAAM,2BAA2B,KAAK,CAAC;AACvC,QAAA,MAAM,4BAA4B,KAAK,CAAC;AAExC,OAAO,EACH,2BAA2B,EAC3B,4BAA4B,EAC5B,4BAA4B,EAC5B,sBAAsB,GACzB,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACrC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,oBAAoB,GAAG,UAAU,GAAG,iBAAiB,GAAG,WAAW,CAAC;CAChF;AAED,wBAAgB,wCAAwC,CACpD,0BAA0B,EAAE,MAAM,GACnC,MAAM,CAER;AAwFD,wBAAgB,uBAAuB,CACnC,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,YAAY,EACnB,mBAAmB,EAAE,MAAM,EAC3B,0BAA0B,EAAE,MAAM,EAClC,sBAAsB,GAAE,MAAyC,GAClE,wBAAwB,CAsF1B"}
1
+ {"version":3,"file":"compartment-trigger.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/compartment-trigger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAUpF,QAAA,MAAM,sBAAsB,OAAO,CAAC;AAKpC,QAAA,MAAM,4BAA4B,KAAK,CAAC;AACxC,QAAA,MAAM,2BAA2B,KAAK,CAAC;AACvC,QAAA,MAAM,4BAA4B,KAAK,CAAC;AAExC,OAAO,EACH,2BAA2B,EAC3B,4BAA4B,EAC5B,4BAA4B,EAC5B,sBAAsB,GACzB,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACrC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,oBAAoB,GAAG,UAAU,GAAG,iBAAiB,GAAG,WAAW,CAAC;CAChF;AAED,wBAAgB,wCAAwC,CACpD,0BAA0B,EAAE,MAAM,GACnC,MAAM,CAER;AAsID,wBAAgB,uBAAuB,CACnC,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,YAAY,EACnB,mBAAmB,EAAE,MAAM,EAC3B,0BAA0B,EAAE,MAAM,EAClC,sBAAsB,GAAE,MAAyC,EACjE,eAAe,CAAC,EAAE,MAAM,EACxB,iBAAiB,CAAC,EAAE,MAAM,EAC1B,iBAAiB,CAAC,EAAE,MAAM,GAC3B,wBAAwB,CA8F1B"}
@@ -14,6 +14,8 @@ export interface EventHandlerDeps {
14
14
  onSessionCacheInvalidated?: (sessionId: string) => void;
15
15
  config: {
16
16
  protected_tags: number;
17
+ auto_drop_tool_age?: number;
18
+ clear_reasoning_age?: number;
17
19
  execute_threshold_percentage?: number | {
18
20
  default: number;
19
21
  [modelKey: string]: number;
@@ -1 +1 @@
1
- {"version":3,"file":"event-handler.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/event-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAkBvF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAiBvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAIvD,KAAK,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtD,UAAU,iBAAiB;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACrB;AAOD,MAAM,WAAW,gBAAgB;IAC7B,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAChD,iBAAiB,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;IAC9D,eAAe,EAAE,mBAAmB,CAAC;IACrC,yBAAyB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,MAAM,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;QACvB,4BAA4B,CAAC,EAAE,MAAM,GAAG;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;QACxF,SAAS,EAAE,cAAc,CAAC;QAC1B,uBAAuB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACjD,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,UAAU,CAAC,cAAc,sCAAsC,EAAE,YAAY,CAAC,CAAC;CACtF;AAqGD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,IACvC,OAAO;IAAE,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,KAAG,OAAO,CAAC,IAAI,CAAC,CA0OzF"}
1
+ {"version":3,"file":"event-handler.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/event-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAkBvF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAiBvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAIvD,KAAK,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtD,UAAU,iBAAiB;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACrB;AAOD,MAAM,WAAW,gBAAgB;IAC7B,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAChD,iBAAiB,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;IAC9D,eAAe,EAAE,mBAAmB,CAAC;IACrC,yBAAyB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,MAAM,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;QACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,4BAA4B,CAAC,EAAE,MAAM,GAAG;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;QACxF,SAAS,EAAE,cAAc,CAAC;QAC1B,uBAAuB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACjD,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,UAAU,CAAC,cAAc,sCAAsC,EAAE,YAAY,CAAC,CAAC;CACtF;AAqGD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,IACvC,OAAO;IAAE,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,KAAG,OAAO,CAAC,IAAI,CAAC,CA8OzF"}
@@ -1 +1 @@
1
- {"version":3,"file":"read-session-chunk.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/read-session-chunk.ts"],"names":[],"mappings":"AAGA,OAAO,EAUH,KAAK,gBAAgB,EACxB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,UAAU,EAAgC,MAAM,oBAAoB,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAIhF,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,MAAM,WAAW,YAAY;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,4GAA4G;IAC5G,kBAAkB,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAa5D;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,EAAE,CAatE;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBjG;AAID,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAStE;AAED,wBAAgB,gBAAgB,CAC5B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,MAAM,GAAE,MAAU,EAClB,kBAAkB,CAAC,EAAE,MAAM,GAC5B,YAAY,CAsHd;AAED,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAK9F"}
1
+ {"version":3,"file":"read-session-chunk.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/read-session-chunk.ts"],"names":[],"mappings":"AAGA,OAAO,EAWH,KAAK,gBAAgB,EACxB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,UAAU,EAAgC,MAAM,oBAAoB,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAIhF,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,MAAM,WAAW,YAAY;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,4GAA4G;IAC5G,kBAAkB,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAa5D;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,EAAE,CAatE;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBjG;AAID,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAStE;AAED,wBAAgB,gBAAgB,CAC5B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,MAAM,GAAE,MAAU,EAClB,kBAAkB,CAAC,EAAE,MAAM,GAC5B,YAAY,CAmJd;AAED,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAK9F"}
@@ -12,6 +12,9 @@ export interface ChunkBlock {
12
12
  }
13
13
  export declare function hasMeaningfulUserText(parts: unknown[]): boolean;
14
14
  export declare function extractTexts(parts: unknown[]): string[];
15
+ /** Extract compact tool-call summaries from message parts.
16
+ * Returns lines like "TC: Fix lint errors" or "TC: read(src/index.ts)". */
17
+ export declare function extractToolCallSummaries(parts: unknown[]): string[];
15
18
  export declare function estimateTokens(text: string): number;
16
19
  export declare function normalizeText(text: string): string;
17
20
  export declare function compactRole(role: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"read-session-formatting.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/read-session-formatting.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B;AAMD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAiB/D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAUvD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAQrD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAW1D;AAED,wBAAgB,qBAAqB,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACb;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAmB1C;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAS9E"}
1
+ {"version":3,"file":"read-session-formatting.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/read-session-formatting.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B;AAMD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAiB/D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAUvD;AAED;4EAC4E;AAC5E,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CA2BnE;AAwBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAQrD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAW1D;AAED,wBAAgB,qBAAqB,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACb;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAmB1C;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAS9E"}
@@ -1 +1 @@
1
- {"version":3,"file":"tag-messages.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/tag-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAE5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAWlE,OAAO,EAGH,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,iBAAiB,EACpB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7E,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC;AAElE,MAAM,MAAM,SAAS,GAAG;IACpB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,cAAc,CAAC;IAC5B,OAAO,CAAC,EAAE,WAAW,CAAC;CACzB,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAChC,kBAAkB,EAAE,GAAG,CAAC,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACzD,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC5C,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,iBAAiB,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,yEAAyE;IACzE,eAAe,EAAE,OAAO,CAAC;CAC5B;AAuBD,wBAAgB,WAAW,CACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,WAAW,EAAE,EACvB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,eAAe,GACpB,iBAAiB,CA+OnB"}
1
+ {"version":3,"file":"tag-messages.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/tag-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAE5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAWlE,OAAO,EAGH,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,iBAAiB,EACpB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7E,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC;AAElE,MAAM,MAAM,SAAS,GAAG;IACpB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,cAAc,CAAC;IAC5B,OAAO,CAAC,EAAE,WAAW,CAAC;CACzB,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAChC,kBAAkB,EAAE,GAAG,CAAC,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACzD,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC5C,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,iBAAiB,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,yEAAyE;IACzE,eAAe,EAAE,OAAO,CAAC;CAC5B;AAoCD,wBAAgB,WAAW,CACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,WAAW,EAAE,EACvB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,eAAe,GACpB,iBAAiB,CAoPnB"}
package/dist/index.js CHANGED
@@ -14879,8 +14879,8 @@ Input notes:
14879
14879
  - [N] or [N-M] is a stable raw OpenCode message range.
14880
14880
  - U: means user.
14881
14881
  - A: means assistant.
14882
+ - TC: means tool call \u2014 a compact summary of what the agent did (e.g., "TC: Fix lint errors", "TC: read(src/index.ts)", "TC: grep(ctx_memory)"). TC lines appear when there is no text describing the action. Use them to understand what happened between text blocks, but do not copy them verbatim into compartments \u2014 incorporate their meaning into the narrative.
14882
14883
  - commits: ... on an assistant block lists commit hashes mentioned in that work unit; keep the relevant ones in the compartment summary when they matter.
14883
- - Tool-only noise is already stripped before you see the input.
14884
14884
 
14885
14885
  Output valid XML only in this shape:
14886
14886
  <output>
@@ -15666,6 +15666,54 @@ function extractTexts(parts) {
15666
15666
  }
15667
15667
  return texts;
15668
15668
  }
15669
+ function extractToolCallSummaries(parts) {
15670
+ const summaries = [];
15671
+ for (const part of parts) {
15672
+ if (part === null || typeof part !== "object")
15673
+ continue;
15674
+ const p = part;
15675
+ if (p.type !== "tool" || typeof p.tool !== "string")
15676
+ continue;
15677
+ const state = p.state;
15678
+ if (!state || typeof state !== "object")
15679
+ continue;
15680
+ const input = state.input;
15681
+ const metadata = state.metadata;
15682
+ const description = input && typeof input.description === "string" && input.description || metadata && typeof metadata.description === "string" && metadata.description;
15683
+ if (description) {
15684
+ summaries.push(`TC: ${description}`);
15685
+ continue;
15686
+ }
15687
+ const toolName = p.tool;
15688
+ const keyArg = extractKeyArg(toolName, input);
15689
+ summaries.push(keyArg ? `TC: ${toolName}(${keyArg})` : `TC: ${toolName}`);
15690
+ }
15691
+ return summaries;
15692
+ }
15693
+ function extractKeyArg(_toolName, input) {
15694
+ if (!input)
15695
+ return null;
15696
+ if (typeof input.filePath === "string")
15697
+ return truncateArg(input.filePath);
15698
+ if (typeof input.path === "string")
15699
+ return truncateArg(input.path);
15700
+ if (typeof input.pattern === "string")
15701
+ return truncateArg(input.pattern);
15702
+ if (typeof input.query === "string")
15703
+ return truncateArg(input.query);
15704
+ if (typeof input.symbol === "string")
15705
+ return input.symbol;
15706
+ if (typeof input.module === "string")
15707
+ return input.module;
15708
+ if (typeof input.action === "string")
15709
+ return input.action;
15710
+ return null;
15711
+ }
15712
+ function truncateArg(value, maxLen = 60) {
15713
+ if (value.length <= maxLen)
15714
+ return value;
15715
+ return `${value.slice(0, maxLen)}\u2026`;
15716
+ }
15669
15717
  function estimateTokens(text) {
15670
15718
  return Math.ceil(text.length / 3.5);
15671
15719
  }
@@ -15922,11 +15970,37 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
15922
15970
  continue;
15923
15971
  const meta3 = { ordinal: msg.ordinal, messageId: msg.id };
15924
15972
  if (msg.role === "user" && !hasMeaningfulUserText(msg.parts)) {
15925
- pendingNoiseMeta.push(meta3);
15973
+ const tcSummaries = extractToolCallSummaries(msg.parts);
15974
+ if (tcSummaries.length === 0) {
15975
+ pendingNoiseMeta.push(meta3);
15976
+ continue;
15977
+ }
15978
+ const tcText = tcSummaries.join(" / ");
15979
+ if (currentBlock && currentBlock.role === "A") {
15980
+ currentBlock.endOrdinal = msg.ordinal;
15981
+ currentBlock.parts.push(tcText);
15982
+ currentBlock.meta.push(...pendingNoiseMeta, meta3);
15983
+ pendingNoiseMeta = [];
15984
+ } else {
15985
+ if (!flushCurrentBlock())
15986
+ break;
15987
+ currentBlock = {
15988
+ role: "A",
15989
+ startOrdinal: pendingNoiseMeta[0]?.ordinal ?? msg.ordinal,
15990
+ endOrdinal: msg.ordinal,
15991
+ parts: [tcText],
15992
+ meta: [...pendingNoiseMeta, meta3],
15993
+ commitHashes: []
15994
+ };
15995
+ pendingNoiseMeta = [];
15996
+ }
15926
15997
  continue;
15927
15998
  }
15928
15999
  const role = compactRole(msg.role);
15929
- const compacted = compactTextForSummary(extractTexts(msg.parts).map((t) => msg.role === "user" ? cleanUserText(t) : t).map(normalizeText).filter((value) => value.length > 0).join(" / "), msg.role);
16000
+ const textParts = extractTexts(msg.parts).map((t) => msg.role === "user" ? cleanUserText(t) : t).map(normalizeText).filter((value) => value.length > 0);
16001
+ const toolSummaries = textParts.length === 0 ? extractToolCallSummaries(msg.parts) : [];
16002
+ const allParts = [...textParts, ...toolSummaries];
16003
+ const compacted = compactTextForSummary(allParts.join(" / "), msg.role);
15930
16004
  const text = compacted.text;
15931
16005
  if (!text) {
15932
16006
  pendingNoiseMeta.push(meta3);
@@ -16353,6 +16427,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
16353
16427
  ensureColumn(db, "session_meta", "memory_block_cache", "TEXT DEFAULT ''");
16354
16428
  ensureColumn(db, "session_meta", "memory_block_count", "INTEGER DEFAULT 0");
16355
16429
  ensureColumn(db, "dream_queue", "retry_count", "INTEGER DEFAULT 0");
16430
+ ensureColumn(db, "tags", "reasoning_byte_size", "INTEGER DEFAULT 0");
16356
16431
  }
16357
16432
  function ensureColumn(db, table, column, definition) {
16358
16433
  if (!/^[a-z_]+$/.test(table) || !/^[a-z_]+$/.test(column) || !/^[A-Z0-9_'(),\s]+$/i.test(definition)) {
@@ -16811,7 +16886,7 @@ var getMaxTagNumberBySessionStatements = new WeakMap;
16811
16886
  function getInsertTagStatement(db) {
16812
16887
  let stmt = insertTagStatements.get(db);
16813
16888
  if (!stmt) {
16814
- stmt = db.prepare("INSERT INTO tags (session_id, message_id, type, byte_size, tag_number) VALUES (?, ?, ?, ?, ?)");
16889
+ stmt = db.prepare("INSERT INTO tags (session_id, message_id, type, byte_size, reasoning_byte_size, tag_number) VALUES (?, ?, ?, ?, ?, ?)");
16815
16890
  insertTagStatements.set(db, stmt);
16816
16891
  }
16817
16892
  return stmt;
@@ -16871,6 +16946,7 @@ function toTagEntry(row) {
16871
16946
  type,
16872
16947
  status,
16873
16948
  byteSize: row.byte_size,
16949
+ reasoningByteSize: row.reasoning_byte_size ?? 0,
16874
16950
  sessionId: row.session_id
16875
16951
  };
16876
16952
  }
@@ -16889,8 +16965,8 @@ function isMaxTagNumberRow(row) {
16889
16965
  function escapeLikePattern(value) {
16890
16966
  return value.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_");
16891
16967
  }
16892
- function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber) {
16893
- getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, tagNumber);
16968
+ function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoningByteSize = 0) {
16969
+ getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, reasoningByteSize, tagNumber);
16894
16970
  return tagNumber;
16895
16971
  }
16896
16972
  function updateTagStatus(db, sessionId, tagId, status) {
@@ -16915,14 +16991,14 @@ function getMaxTagNumberBySession(db, sessionId) {
16915
16991
  return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
16916
16992
  }
16917
16993
  function getTagsBySession(db, sessionId) {
16918
- const rows = db.prepare("SELECT id, message_id, type, status, byte_size, session_id, tag_number FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC").all(sessionId).filter(isTagRow);
16994
+ const rows = db.prepare("SELECT id, message_id, type, status, byte_size, reasoning_byte_size, session_id, tag_number FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC").all(sessionId).filter(isTagRow);
16919
16995
  return rows.map(toTagEntry);
16920
16996
  }
16921
16997
  function getTopNBySize(db, sessionId, n) {
16922
16998
  if (n <= 0) {
16923
16999
  return [];
16924
17000
  }
16925
- const rows = db.prepare("SELECT id, message_id, type, status, byte_size, session_id, tag_number FROM tags WHERE session_id = ? AND status = 'active' ORDER BY byte_size DESC, tag_number ASC LIMIT ?").all(sessionId, n).filter(isTagRow);
17001
+ const rows = db.prepare("SELECT id, message_id, type, status, byte_size, reasoning_byte_size, session_id, tag_number FROM tags WHERE session_id = ? AND status = 'active' ORDER BY byte_size DESC, tag_number ASC LIMIT ?").all(sessionId, n).filter(isTagRow);
16926
17002
  return rows.map(toTagEntry);
16927
17003
  }
16928
17004
  // src/plugin/dream-timer.ts
@@ -17142,7 +17218,7 @@ function createTagger() {
17142
17218
  }
17143
17219
  return map2;
17144
17220
  }
17145
- function assignTag(sessionId, messageId, type, byteSize2, db) {
17221
+ function assignTag(sessionId, messageId, type, byteSize2, db, reasoningByteSize = 0) {
17146
17222
  const sessionAssignments = getSessionAssignments(sessionId);
17147
17223
  const existing = sessionAssignments.get(messageId);
17148
17224
  if (existing !== undefined) {
@@ -17151,7 +17227,7 @@ function createTagger() {
17151
17227
  const current = counters.get(sessionId) ?? 0;
17152
17228
  const next = current + 1;
17153
17229
  db.transaction(() => {
17154
- insertTag(db, sessionId, messageId, type, byteSize2, next);
17230
+ insertTag(db, sessionId, messageId, type, byteSize2, next, reasoningByteSize);
17155
17231
  getUpsertCounterStatement(db).run(sessionId, next);
17156
17232
  })();
17157
17233
  counters.set(sessionId, next);
@@ -17287,17 +17363,50 @@ var FORCE_MATERIALIZE_PERCENTAGE = 85;
17287
17363
  function getProactiveCompartmentTriggerPercentage(executeThresholdPercentage) {
17288
17364
  return Math.max(0, executeThresholdPercentage - PROACTIVE_TRIGGER_OFFSET_PERCENTAGE);
17289
17365
  }
17290
- function estimateProjectedPostDropPercentage(db, sessionId, usage) {
17291
- const pendingDrops = getPendingOps(db, sessionId).filter((op) => op.operation === "drop");
17292
- if (pendingDrops.length === 0)
17293
- return null;
17366
+ function estimateProjectedPostDropPercentage(db, sessionId, usage, autoDropToolAge, protectedTags, clearReasoningAge, clearedReasoningThroughTag) {
17294
17367
  const activeTags = getTagsBySession(db, sessionId).filter((tag) => tag.status === "active");
17295
- const totalActiveBytes = activeTags.reduce((sum, tag) => sum + tag.byteSize, 0);
17368
+ const totalActiveBytes = activeTags.reduce((sum, tag) => sum + tag.byteSize + tag.reasoningByteSize, 0);
17296
17369
  if (totalActiveBytes === 0)
17297
17370
  return null;
17371
+ let droppableBytes = 0;
17372
+ const pendingDrops = getPendingOps(db, sessionId).filter((op) => op.operation === "drop");
17298
17373
  const pendingDropTagIds = new Set(pendingDrops.map((op) => op.tagId));
17299
- const pendingDropBytes = activeTags.filter((tag) => pendingDropTagIds.has(tag.tagNumber)).reduce((sum, tag) => sum + tag.byteSize, 0);
17300
- const dropRatio = pendingDropBytes / totalActiveBytes;
17374
+ if (pendingDrops.length > 0) {
17375
+ droppableBytes += activeTags.filter((tag) => pendingDropTagIds.has(tag.tagNumber)).reduce((sum, tag) => sum + tag.byteSize + tag.reasoningByteSize, 0);
17376
+ }
17377
+ const maxTag = activeTags.reduce((max, t) => Math.max(max, t.tagNumber), 0);
17378
+ if (autoDropToolAge !== undefined && protectedTags !== undefined) {
17379
+ const toolAgeCutoff = maxTag - autoDropToolAge;
17380
+ const protectedCutoff = maxTag - protectedTags;
17381
+ for (const tag of activeTags) {
17382
+ if (pendingDropTagIds.has(tag.tagNumber))
17383
+ continue;
17384
+ if (tag.tagNumber > protectedCutoff)
17385
+ continue;
17386
+ if (tag.type === "tool" && tag.tagNumber <= toolAgeCutoff) {
17387
+ droppableBytes += tag.byteSize + tag.reasoningByteSize;
17388
+ }
17389
+ }
17390
+ }
17391
+ if (clearReasoningAge !== undefined && clearedReasoningThroughTag !== undefined) {
17392
+ const reasoningAgeCutoff = maxTag - clearReasoningAge;
17393
+ for (const tag of activeTags) {
17394
+ if (tag.type !== "message")
17395
+ continue;
17396
+ if (pendingDropTagIds.has(tag.tagNumber))
17397
+ continue;
17398
+ if (tag.tagNumber <= clearedReasoningThroughTag)
17399
+ continue;
17400
+ if (tag.tagNumber > reasoningAgeCutoff)
17401
+ continue;
17402
+ if (tag.reasoningByteSize > 0) {
17403
+ droppableBytes += tag.reasoningByteSize;
17404
+ }
17405
+ }
17406
+ }
17407
+ if (droppableBytes === 0)
17408
+ return null;
17409
+ const dropRatio = Math.min(droppableBytes / totalActiveBytes, 1);
17301
17410
  return usage.percentage * (1 - dropRatio);
17302
17411
  }
17303
17412
  var TAIL_INFO_DEFAULTS = {
@@ -17334,7 +17443,7 @@ function getUnsummarizedTailInfo(db, sessionId, compartmentTokenBudget) {
17334
17443
  }
17335
17444
  });
17336
17445
  }
17337
- function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, compartmentTokenBudget = DEFAULT_COMPARTMENT_TOKEN_BUDGET) {
17446
+ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, compartmentTokenBudget = DEFAULT_COMPARTMENT_TOKEN_BUDGET, autoDropToolAge, protectedTagCount, clearReasoningAge) {
17338
17447
  if (sessionMeta.compartmentInProgress) {
17339
17448
  return { shouldFire: false };
17340
17449
  }
@@ -17342,7 +17451,7 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
17342
17451
  if (!tailInfo.hasNewRawHistory) {
17343
17452
  return { shouldFire: false };
17344
17453
  }
17345
- const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage);
17454
+ const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, autoDropToolAge, protectedTagCount, clearReasoningAge, sessionMeta.clearedReasoningThroughTag);
17346
17455
  const relativePostDropTarget = executeThresholdPercentage * POST_DROP_TARGET_RATIO;
17347
17456
  if (usage.percentage >= FORCE_COMPARTMENT_PERCENTAGE) {
17348
17457
  if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
@@ -17989,7 +18098,7 @@ function createEventHandler2(deps) {
17989
18098
  const sessionMeta = getOrCreateSessionMeta(deps.db, info.sessionID);
17990
18099
  const previousPercentage = sessionMeta.lastContextPercentage;
17991
18100
  if (!sessionMeta.isSubagent) {
17992
- const triggerResult = checkCompartmentTrigger(deps.db, info.sessionID, sessionMeta, { percentage, inputTokens: totalInputTokens }, previousPercentage, resolveExecuteThreshold(deps.config.execute_threshold_percentage ?? 65, modelKey, 65));
18101
+ const triggerResult = checkCompartmentTrigger(deps.db, info.sessionID, sessionMeta, { percentage, inputTokens: totalInputTokens }, previousPercentage, resolveExecuteThreshold(deps.config.execute_threshold_percentage ?? 65, modelKey, 65), undefined, deps.config.auto_drop_tool_age ?? 100, deps.config.protected_tags, deps.config.clear_reasoning_age ?? 50);
17993
18102
  if (triggerResult.shouldFire) {
17994
18103
  sessionLog(info.sessionID, `compartment trigger: firing (reason=${triggerResult.reason})`);
17995
18104
  updateSessionMeta(deps.db, info.sessionID, {
@@ -21119,6 +21228,16 @@ function collectRelevantSourceTagIds(messages, assignments) {
21119
21228
  }
21120
21229
  return Array.from(relevantTagIds);
21121
21230
  }
21231
+ function getReasoningByteSize(parts) {
21232
+ let reasoningBytes = 0;
21233
+ for (const part of parts) {
21234
+ const content = part.thinking ?? part.text ?? "";
21235
+ if (content && content !== "[cleared]") {
21236
+ reasoningBytes += byteSize(content);
21237
+ }
21238
+ }
21239
+ return reasoningBytes;
21240
+ }
21122
21241
  function tagMessages(sessionId, messages, tagger, db) {
21123
21242
  const targets = new Map;
21124
21243
  const reasoningByMessage = new Map;
@@ -21179,7 +21298,8 @@ function tagMessages(sessionId, messages, tagger, db) {
21179
21298
  const thinkingParts = messageThinkingParts;
21180
21299
  const contentId = `${messageId}:p${partIndex}`;
21181
21300
  const existingTagId = resolver.resolve(messageId, "message", contentId, textOrdinal);
21182
- const tagId = tagger.assignTag(sessionId, contentId, "message", byteSize(textPart.text), db);
21301
+ const reasoningBytes = textOrdinal === 0 ? getReasoningByteSize(thinkingParts) : 0;
21302
+ const tagId = tagger.assignTag(sessionId, contentId, "message", byteSize(textPart.text), db, reasoningBytes);
21183
21303
  if (existingTagId === undefined) {
21184
21304
  const sourceContent = stripTagPrefix(textPart.text);
21185
21305
  if (sourceContent.trim().length > 0) {
@@ -21215,7 +21335,8 @@ function tagMessages(sessionId, messages, tagger, db) {
21215
21335
  if (isToolPartWithOutput(part)) {
21216
21336
  const toolPart = part;
21217
21337
  const thinkingParts = precedingThinkingParts;
21218
- const tagId = tagger.assignTag(sessionId, toolPart.callID, "tool", byteSize(toolPart.state.output), db);
21338
+ const reasoningBytes = getReasoningByteSize(thinkingParts);
21339
+ const tagId = tagger.assignTag(sessionId, toolPart.callID, "tool", byteSize(toolPart.state.output), db, reasoningBytes);
21219
21340
  messageTagNumbers.set(message, Math.max(messageTagNumbers.get(message) ?? 0, tagId));
21220
21341
  toolPart.state.output = prependTag(tagId, toolPart.state.output);
21221
21342
  toolTagByCallId.set(toolPart.callID, tagId);
@@ -22190,6 +22311,10 @@ Use \`ctx_reduce\` to manage context size. It supports one operation:
22190
22311
  Syntax: "3-5", "1,2,9", or "1-5,8,12-15". Last ${protectedTags} tags are protected.
22191
22312
  Use \`ctx_note\` for deferred intentions \u2014 things to tackle later, not right now. NOT for task tracking (use todos). Notes survive context compression and you'll be reminded at natural work boundaries (after commits, historian runs, todo completion).
22192
22313
  Use \`ctx_memory\` to manage cross-session project memories. Write new memories or delete stale ones. Memories persist across sessions and are automatically injected into new sessions.
22314
+ **Save to memory proactively**: If you spent multiple turns finding something (a file path, a DB location, a config pattern, a workaround), save it with \`ctx_memory\` so future sessions don't repeat the search. Examples:
22315
+ - Found a project's source code path after searching \u2192 \`ctx_memory(action="write", category="ENVIRONMENT", content="OpenCode source is at ~/Work/OSS/opencode")\`
22316
+ - Discovered a non-obvious build/test command \u2192 \`ctx_memory(action="write", category="WORKFLOW_RULES", content="Always use scripts/release.sh for releases")\`
22317
+ - Learned a constraint the hard way \u2192 \`ctx_memory(action="write", category="CONSTRAINTS", content="Dashboard Tauri build needs RGBA PNGs, not grayscale")\`
22193
22318
  Use \`ctx_search\` to search across project memories, session facts, and conversation history from one query.
22194
22319
  Use \`ctx_expand\` to decompress a compartment range to see the original conversation transcript. Use \`start\`/\`end\` from \`<compartment start=N end=M>\` attributes. Returns the compacted U:/A: transcript for that message range, capped at ~15K tokens.
22195
22320
  **Search before asking the user**: If you can't remember or don't know something that might have been discussed before or stored in project memory, use \`ctx_search\` before asking the user. Examples:
@@ -22206,6 +22331,10 @@ Before your turn finishes, consider using \`ctx_reduce\` to drop large tool outp
22206
22331
  var BASE_INTRO_NO_REDUCE = `Messages and tool outputs are tagged with \xA7N\xA7 identifiers (e.g., \xA71\xA7, \xA742\xA7).
22207
22332
  Use \`ctx_note\` for deferred intentions \u2014 things to tackle later, not right now. NOT for task tracking (use todos). Notes survive context compression and you'll be reminded at natural work boundaries (after commits, historian runs, todo completion).
22208
22333
  Use \`ctx_memory\` to manage cross-session project memories. Write new memories or delete stale ones. Memories persist across sessions and are automatically injected into new sessions.
22334
+ **Save to memory proactively**: If you spent multiple turns finding something (a file path, a DB location, a config pattern, a workaround), save it with \`ctx_memory\` so future sessions don't repeat the search. Examples:
22335
+ - Found a project's source code path after searching \u2192 \`ctx_memory(action="write", category="ENVIRONMENT", content="OpenCode source is at ~/Work/OSS/opencode")\`
22336
+ - Discovered a non-obvious build/test command \u2192 \`ctx_memory(action="write", category="WORKFLOW_RULES", content="Always use scripts/release.sh for releases")\`
22337
+ - Learned a constraint the hard way \u2192 \`ctx_memory(action="write", category="CONSTRAINTS", content="Dashboard Tauri build needs RGBA PNGs, not grayscale")\`
22209
22338
  Use \`ctx_search\` to search across project memories, session facts, and conversation history from one query.
22210
22339
  Use \`ctx_expand\` to decompress a compartment range to see the original conversation transcript. Use \`start\`/\`end\` from \`<compartment start=N end=M>\` attributes. Returns the compacted U:/A: transcript for that message range, capped at ~15K tokens.
22211
22340
  **Search before asking the user**: If you can't remember or don't know something that might have been discussed before or stored in project memory, use \`ctx_search\` before asking the user. Examples:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",