@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.
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +1 -1
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/tagger.d.ts +1 -1
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/types.d.ts +1 -0
- package/dist/features/magic-context/types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-prompt.d.ts +1 -1
- package/dist/hooks/magic-context/compartment-prompt.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts +2 -0
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +3 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/index.js +151 -22
- package/package.json +1 -1
|
@@ -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;
|
|
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,
|
|
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;
|
|
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,
|
|
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"}
|
|
@@ -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
|
|
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,
|
|
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;
|
|
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,
|
|
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,
|
|
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;
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
17300
|
-
|
|
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
|
|
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
|
|
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