@cortexkit/opencode-magic-context 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/config/schema/magic-context.d.ts +17 -0
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/runner.d.ts +9 -1
- package/dist/features/magic-context/dreamer/runner.d.ts.map +1 -1
- package/dist/features/magic-context/key-files/identify-key-files.d.ts +39 -0
- package/dist/features/magic-context/key-files/identify-key-files.d.ts.map +1 -0
- package/dist/features/magic-context/key-files/read-stats.d.ts +20 -0
- package/dist/features/magic-context/key-files/read-stats.d.ts.map +1 -0
- package/dist/features/magic-context/key-files/storage-key-files.d.ts +25 -0
- package/dist/features/magic-context/key-files/storage-key-files.d.ts.map +1 -0
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +5 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +5 -0
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +4 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +509 -43
- package/dist/plugin/dream-timer.d.ts +5 -0
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/tui/data/context-db.ts +6 -6
package/README.md
CHANGED
|
@@ -45,6 +45,8 @@ Your agent should never stop working to manage its own context. Magic Context is
|
|
|
45
45
|
|
|
46
46
|
**User Memories** — historian extracts behavioral observations about you alongside its normal compartment output (communication style, expertise level, review focus, working patterns). Recurring observations are promoted by the dreamer to stable user memories that appear in all sessions via `<user-profile>`. Enable with `experimental.user_memories.enabled: true` (requires dreamer).
|
|
47
47
|
|
|
48
|
+
**Key File Pinning** — dreamer analyzes which files your agent reads most frequently across the session. Core orientation files (architecture, config, types) that get re-read after every context drop are pinned into the system prompt as `<key-files>`, so the agent always has them without needing to re-read from disk. Files are read fresh on each cache-busting pass. Enable with `experimental.pin_key_files.enabled: true` (requires dreamer).
|
|
49
|
+
|
|
48
50
|
---
|
|
49
51
|
|
|
50
52
|
## Get Started
|
|
@@ -195,6 +195,13 @@ export interface MagicContextConfig {
|
|
|
195
195
|
enabled: boolean;
|
|
196
196
|
promotion_threshold: number;
|
|
197
197
|
};
|
|
198
|
+
pin_key_files: {
|
|
199
|
+
enabled: boolean;
|
|
200
|
+
/** Total token budget for all pinned key files (default: 10000) */
|
|
201
|
+
token_budget: number;
|
|
202
|
+
/** Minimum full-read count before a file is considered for pinning (default: 4) */
|
|
203
|
+
min_reads: number;
|
|
204
|
+
};
|
|
198
205
|
};
|
|
199
206
|
embedding: EmbeddingConfig;
|
|
200
207
|
memory: {
|
|
@@ -370,6 +377,11 @@ export declare const MagicContextConfigSchema: z.ZodPipe<z.ZodObject<{
|
|
|
370
377
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
371
378
|
promotion_threshold: z.ZodDefault<z.ZodNumber>;
|
|
372
379
|
}, z.core.$strip>>;
|
|
380
|
+
pin_key_files: z.ZodDefault<z.ZodObject<{
|
|
381
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
382
|
+
token_budget: z.ZodDefault<z.ZodNumber>;
|
|
383
|
+
min_reads: z.ZodDefault<z.ZodNumber>;
|
|
384
|
+
}, z.core.$strip>>;
|
|
373
385
|
}, z.core.$strip>>;
|
|
374
386
|
memory: z.ZodDefault<z.ZodObject<{
|
|
375
387
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -470,6 +482,11 @@ export declare const MagicContextConfigSchema: z.ZodPipe<z.ZodObject<{
|
|
|
470
482
|
enabled: boolean;
|
|
471
483
|
promotion_threshold: number;
|
|
472
484
|
};
|
|
485
|
+
pin_key_files: {
|
|
486
|
+
enabled: boolean;
|
|
487
|
+
token_budget: number;
|
|
488
|
+
min_reads: number;
|
|
489
|
+
};
|
|
473
490
|
};
|
|
474
491
|
memory: {
|
|
475
492
|
enabled: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"magic-context.d.ts","sourceRoot":"","sources":["../../../src/config/schema/magic-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,eAAO,MAAM,6BAA6B,QAAS,CAAC;AACpD,eAAO,MAAM,oCAAoC,KAAK,CAAC;AACvD,eAAO,MAAM,gCAAgC,QAAS,CAAC;AACvD,eAAO,MAAM,4BAA4B,SAAU,CAAC;AACpD,eAAO,MAAM,iCAAiC,OAAO,CAAC;AACtD,eAAO,MAAM,6BAA6B,4BAA4B,CAAC;AAEvE,eAAO,MAAM,aAAa,iFAMhB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;;EAAwB,CAAC;AACxD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,qBAAqB,EAAE,YAAY,EAK/C,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAe/B,CAAC;AACF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAIpB,CAAC;AACd,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC;AA2B/E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;GAmBhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB;;oFAEgF;IAChF,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACpE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,4BAA4B,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACvF,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yBAAyB,EAAE,MAAM,CAAC;IAClC,wBAAwB,EAAE,MAAM,CAAC;IACjC,yBAAyB,EAAE,MAAM,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE;QACpB,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,YAAY,EAAE;QACV,kBAAkB,EAAE,OAAO,CAAC;QAC5B,aAAa,EAAE;YACX,OAAO,EAAE,OAAO,CAAC;YACjB,mBAAmB,EAAE,MAAM,CAAC;SAC/B,CAAC;KACL,CAAC;IACF,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,EAAE;QACJ,OAAO,EAAE,OAAO,CAAC;QACjB,uBAAuB,EAAE,MAAM,CAAC;QAChC,YAAY,EAAE,OAAO,CAAC;QACtB,mCAAmC,EAAE,MAAM,CAAC;KAC/C,CAAC;IACF,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,eAAO,MAAM,wBAAwB
|
|
1
|
+
{"version":3,"file":"magic-context.d.ts","sourceRoot":"","sources":["../../../src/config/schema/magic-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,eAAO,MAAM,6BAA6B,QAAS,CAAC;AACpD,eAAO,MAAM,oCAAoC,KAAK,CAAC;AACvD,eAAO,MAAM,gCAAgC,QAAS,CAAC;AACvD,eAAO,MAAM,4BAA4B,SAAU,CAAC;AACpD,eAAO,MAAM,iCAAiC,OAAO,CAAC;AACtD,eAAO,MAAM,6BAA6B,4BAA4B,CAAC;AAEvE,eAAO,MAAM,aAAa,iFAMhB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;;EAAwB,CAAC;AACxD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,qBAAqB,EAAE,YAAY,EAK/C,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAe/B,CAAC;AACF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAIpB,CAAC;AACd,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC;AA2B/E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;GAmBhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB;;oFAEgF;IAChF,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACpE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,4BAA4B,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACvF,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yBAAyB,EAAE,MAAM,CAAC;IAClC,wBAAwB,EAAE,MAAM,CAAC;IACjC,yBAAyB,EAAE,MAAM,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE;QACpB,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,YAAY,EAAE;QACV,kBAAkB,EAAE,OAAO,CAAC;QAC5B,aAAa,EAAE;YACX,OAAO,EAAE,OAAO,CAAC;YACjB,mBAAmB,EAAE,MAAM,CAAC;SAC/B,CAAC;QACF,aAAa,EAAE;YACX,OAAO,EAAE,OAAO,CAAC;YACjB,mEAAmE;YACnE,YAAY,EAAE,MAAM,CAAC;YACrB,mFAAmF;YACnF,SAAS,EAAE,MAAM,CAAC;SACrB,CAAC;KACL,CAAC;IACF,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,EAAE;QACJ,OAAO,EAAE,OAAO,CAAC;QACjB,uBAAuB,EAAE,MAAM,CAAC;QAChC,YAAY,EAAE,OAAO,CAAC;QACtB,mCAAmC,EAAE,MAAM,CAAC;KAC/C,CAAC;IACF,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyH/B,CAAC"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
2
|
import type { DreamingTask } from "../../../config/schema/magic-context";
|
|
3
3
|
import type { PluginContext } from "../../../plugin/types";
|
|
4
|
+
interface ExperimentalPinKeyFilesConfig {
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
token_budget: number;
|
|
7
|
+
min_reads: number;
|
|
8
|
+
}
|
|
4
9
|
export declare function registerDreamProjectDirectory(projectIdentity: string, directory: string): void;
|
|
5
10
|
export interface DreamRunResult {
|
|
6
11
|
startedAt: number;
|
|
@@ -29,6 +34,7 @@ export declare function runDream(args: {
|
|
|
29
34
|
enabled: boolean;
|
|
30
35
|
promotionThreshold: number;
|
|
31
36
|
};
|
|
37
|
+
experimentalPinKeyFiles?: ExperimentalPinKeyFilesConfig;
|
|
32
38
|
}): Promise<DreamRunResult>;
|
|
33
39
|
export declare function processDreamQueue(args: {
|
|
34
40
|
db: Database;
|
|
@@ -40,5 +46,7 @@ export declare function processDreamQueue(args: {
|
|
|
40
46
|
enabled: boolean;
|
|
41
47
|
promotionThreshold: number;
|
|
42
48
|
};
|
|
49
|
+
experimentalPinKeyFiles?: ExperimentalPinKeyFilesConfig;
|
|
43
50
|
}): Promise<DreamRunResult | null>;
|
|
51
|
+
export {};
|
|
44
52
|
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/dreamer/runner.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/dreamer/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AA0C3D,UAAU,6BAA6B;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,6BAA6B,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAE9F;AAMD,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,OAAO,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAClB,EAAE,CAAC;CACP;AA6RD,wBAAsB,QAAQ,CAAC,IAAI,EAAE;IACjC,EAAE,EAAE,QAAQ,CAAC;IACb,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,6FAA6F;IAC7F,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wBAAwB,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,uBAAuB,CAAC,EAAE,6BAA6B,CAAC;CAC3D,GAAG,OAAO,CAAC,cAAc,CAAC,CA8S1B;AA0LD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC1C,EAAE,EAAE,QAAQ,CAAC;IACb,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,wBAAwB,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,uBAAuB,CAAC,EAAE,6BAA6B,CAAC;CAC3D,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAyDjC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
import { type FileReadStat } from "./read-stats";
|
|
3
|
+
export declare const KEY_FILES_SYSTEM_PROMPT = "You are a file importance evaluator. Given read statistics about files in a coding session, identify which are core orientation files worth pinning in context. Return a JSON array.";
|
|
4
|
+
/**
|
|
5
|
+
* Build the LLM prompt for key file identification.
|
|
6
|
+
* Called from the dreamer runner which handles session creation.
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildKeyFilesPrompt(candidates: FileReadStat[], tokenBudget: number, minReads: number): string;
|
|
9
|
+
/**
|
|
10
|
+
* Parse the LLM's response into a ranked file list.
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseKeyFilesOutput(text: string): Array<{
|
|
13
|
+
filePath: string;
|
|
14
|
+
tokens: number;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* Get candidate files for key-file analysis from OpenCode's DB.
|
|
18
|
+
* Returns files with full reads >= minReads and size under half the budget.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getKeyFileCandidates(openCodeDb: Database, sessionId: string, minReads: number, tokenBudget: number): FileReadStat[];
|
|
21
|
+
/**
|
|
22
|
+
* Apply LLM-ranked results through the knapsack solver and persist.
|
|
23
|
+
*/
|
|
24
|
+
export declare function applyKeyFileResults(db: Database, sessionId: string, llmRanked: Array<{
|
|
25
|
+
filePath: string;
|
|
26
|
+
tokens: number;
|
|
27
|
+
}>, tokenBudget: number, candidatePaths?: Set<string>): {
|
|
28
|
+
filesIdentified: number;
|
|
29
|
+
totalTokens: number;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Pure heuristic fallback when LLM is unavailable.
|
|
33
|
+
* Ranks by: high read count, low edit count, reasonable size.
|
|
34
|
+
*/
|
|
35
|
+
export declare function heuristicKeyFileSelection(db: Database, sessionId: string, candidates: FileReadStat[], tokenBudget: number): {
|
|
36
|
+
filesIdentified: number;
|
|
37
|
+
totalTokens: number;
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=identify-key-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identify-key-files.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/key-files/identify-key-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,KAAK,YAAY,EAAuB,MAAM,cAAc,CAAC;AAGtE,eAAO,MAAM,uBAAuB,yLACsJ,CAAC;AAE3L;;;GAGG;AACH,wBAAgB,mBAAmB,CAC/B,UAAU,EAAE,YAAY,EAAE,EAC1B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACjB,MAAM,CAqCR;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAqB7F;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAChC,UAAU,EAAE,QAAQ,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GACpB,YAAY,EAAE,CAIhB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EACtD,WAAW,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAC7B;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAelD;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACrC,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,YAAY,EAAE,EAC1B,WAAW,EAAE,MAAM,GACpB;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAmBlD"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
export interface FileReadStat {
|
|
3
|
+
filePath: string;
|
|
4
|
+
fullReadCount: number;
|
|
5
|
+
/** Number of distinct compartment ranges the reads span across */
|
|
6
|
+
spreadAcrossCompartments: number;
|
|
7
|
+
/** Number of times the file was edited (write/edit tool) in this session */
|
|
8
|
+
editCount: number;
|
|
9
|
+
/** Byte size of the most recent full read output */
|
|
10
|
+
latestReadBytes: number;
|
|
11
|
+
/** Approximate token count of the most recent full read (~3.5 chars per token) */
|
|
12
|
+
latestReadTokens: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Query file read patterns from OpenCode's DB for a specific session.
|
|
16
|
+
* Returns files that were fully read (no line range) at least `minReads` times,
|
|
17
|
+
* sorted by read frequency descending.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getSessionReadStats(openCodeDb: Database, sessionId: string, minReads: number): FileReadStat[];
|
|
20
|
+
//# sourceMappingURL=read-stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-stats.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/key-files/read-stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,wBAAwB,EAAE,MAAM,CAAC;IACjC,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,eAAe,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAC/B,UAAU,EAAE,QAAQ,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACjB,YAAY,EAAE,CAgFhB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
export interface KeyFileEntry {
|
|
3
|
+
filePath: string;
|
|
4
|
+
/** Approximate token count when last pinned */
|
|
5
|
+
tokens: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Get the pinned key files for a session from session_meta.
|
|
9
|
+
* Returns empty array if not set or parse fails.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getKeyFiles(db: Database, sessionId: string): KeyFileEntry[];
|
|
12
|
+
/**
|
|
13
|
+
* Set the pinned key files for a session.
|
|
14
|
+
*/
|
|
15
|
+
export declare function setKeyFiles(db: Database, sessionId: string, files: KeyFileEntry[]): void;
|
|
16
|
+
/**
|
|
17
|
+
* Greedy-fit files into a token budget.
|
|
18
|
+
* Takes files sorted by priority (dreamer's ranking) and greedily adds
|
|
19
|
+
* them until the budget is exhausted. Returns the selected files.
|
|
20
|
+
*/
|
|
21
|
+
export declare function greedyFitFiles(rankedFiles: Array<{
|
|
22
|
+
filePath: string;
|
|
23
|
+
tokens: number;
|
|
24
|
+
}>, tokenBudget: number): KeyFileEntry[];
|
|
25
|
+
//# sourceMappingURL=storage-key-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-key-files.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/key-files/storage-key-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,EAAE,CAqB3E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,CAYxF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC1B,WAAW,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EACxD,WAAW,EAAE,MAAM,GACpB,YAAY,EAAE,CAehB"}
|
|
@@ -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;AAkBtC,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;AAkBtC,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAkRrD;AAiCD,wBAAgB,YAAY,IAAI,QAAQ,CAsCvC;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"}
|
|
@@ -47,6 +47,11 @@ export declare function createMagicContextCommandHandler(deps: {
|
|
|
47
47
|
enabled: boolean;
|
|
48
48
|
promotionThreshold: number;
|
|
49
49
|
};
|
|
50
|
+
experimentalPinKeyFiles?: {
|
|
51
|
+
enabled: boolean;
|
|
52
|
+
token_budget: number;
|
|
53
|
+
min_reads: number;
|
|
54
|
+
};
|
|
50
55
|
};
|
|
51
56
|
}): {
|
|
52
57
|
"command.execute.before": (input: CommandExecuteInput, _output: CommandExecuteOutput, _params: NotificationParams) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/command-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EACH,KAAK,cAAc,EAGtB,MAAM,sCAAsC,CAAC;AAG9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAOtE,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACjC,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;
|
|
1
|
+
{"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/command-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EACH,KAAK,cAAc,EAGtB,MAAM,sCAAsC,CAAC;AAG9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAOtE,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACjC,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAoKD,wBAAgB,gCAAgC,CAAC,IAAI,EAAE;IACnD,EAAE,EAAE,QAAQ,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,0BAA0B,CAAC,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACtF,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,oBAAoB,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC5D,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,gBAAgB,EAAE,CACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,kBAAkB,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,QAAQ,CAAC,EAAE;QACP,MAAM,EAAE,cAAc,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;KACnC,CAAC;IACF,OAAO,CAAC,EAAE;QACN,MAAM,EAAE,aAAa,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,OAAO,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;QACrE,wBAAwB,CAAC,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,kBAAkB,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5E,uBAAuB,CAAC,EAAE;YACtB,OAAO,EAAE,OAAO,CAAC;YACjB,YAAY,EAAE,MAAM,CAAC;YACrB,SAAS,EAAE,MAAM,CAAC;SACrB,CAAC;KACL,CAAC;CACL;sCASkB,mBAAmB,WACjB,oBAAoB,WACpB,kBAAkB,KAC5B,OAAO,CAAC,IAAI,CAAC;EAoGvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,KAAK,aAAa,EAClB,KAAK,cAAc,EACtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAOvF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AAMxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAWxD,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAiBnF,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,yBAAyB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,iBAAiB,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;IAC9D,MAAM,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;QACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAC;QACnC,4BAA4B,CAAC,EAAE,MAAM,GAAG;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;QACxF,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,uBAAuB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE9C,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,yBAAyB,CAAC,EAAE,MAAM,CAAC;QACnC,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,MAAM,CAAC,EAAE;YACL,OAAO,EAAE,OAAO,CAAC;YACjB,uBAAuB,EAAE,MAAM,CAAC;SACnC,CAAC;QACF,QAAQ,CAAC,EAAE,cAAc,CAAC;QAC1B,OAAO,CAAC,EAAE,aAAa,CAAC;QACxB,sBAAsB,CAAC,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,YAAY,EAAE,MAAM,CAAA;SAAE,CAAC;QACpE,YAAY,CAAC,EAAE;YACX,kBAAkB,CAAC,EAAE,OAAO,CAAC;YAC7B,aAAa,CAAC,EAAE;gBAAE,OAAO,EAAE,OAAO,CAAC;gBAAC,mBAAmB,EAAE,MAAM,CAAA;aAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,KAAK,aAAa,EAClB,KAAK,cAAc,EACtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAOvF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AAMxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAWxD,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAiBnF,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,yBAAyB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,iBAAiB,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;IAC9D,MAAM,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;QACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAC;QACnC,4BAA4B,CAAC,EAAE,MAAM,GAAG;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;QACxF,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,uBAAuB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE9C,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,yBAAyB,CAAC,EAAE,MAAM,CAAC;QACnC,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,MAAM,CAAC,EAAE;YACL,OAAO,EAAE,OAAO,CAAC;YACjB,uBAAuB,EAAE,MAAM,CAAC;SACnC,CAAC;QACF,QAAQ,CAAC,EAAE,cAAc,CAAC;QAC1B,OAAO,CAAC,EAAE,aAAa,CAAC;QACxB,sBAAsB,CAAC,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,YAAY,EAAE,MAAM,CAAA;SAAE,CAAC;QACpE,YAAY,CAAC,EAAE;YACX,kBAAkB,CAAC,EAAE,OAAO,CAAC;YAC7B,aAAa,CAAC,EAAE;gBAAE,OAAO,EAAE,OAAO,CAAC;gBAAC,mBAAmB,EAAE,MAAM,CAAA;aAAE,CAAC;YAClE,aAAa,CAAC,EAAE;gBAAE,OAAO,EAAE,OAAO,CAAC;gBAAC,YAAY,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE,CAAC;SACjF,CAAC;KACL,CAAC;CACL;AAqCD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,gBAAgB;;;;;iBAxCF,CAAC;;;;;;;;;;;;iBA5BxD,CAAA;eACA,CAAF;;mBA4T2B;QAAE,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,UAAU,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE;;;SAa7E"}
|
|
@@ -25,6 +25,10 @@ export declare function createSystemPromptHashHandler(deps: {
|
|
|
25
25
|
lastHeuristicsTurnId: Map<string, string>;
|
|
26
26
|
/** When true, inject stable user memories as <user-profile> into system prompt */
|
|
27
27
|
experimentalUserMemories?: boolean;
|
|
28
|
+
/** When true, inject pinned key files as <key-files> into system prompt */
|
|
29
|
+
experimentalPinKeyFiles?: boolean;
|
|
30
|
+
/** Token budget for key files injection (default 10000) */
|
|
31
|
+
experimentalPinKeyFilesTokenBudget?: number;
|
|
28
32
|
}): (input: {
|
|
29
33
|
sessionID?: string;
|
|
30
34
|
}, output: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt-hash.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/system-prompt-hash.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"system-prompt-hash.d.ts","sourceRoot":"","sources":["../../../src/hooks/magic-context/system-prompt-hash.ts"],"names":[],"mappings":"AAQA,OAAO,EACH,KAAK,eAAe,EAGvB,MAAM,sCAAsC,CAAC;AAwC9C;;;;;;;;;;;;GAYG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE;IAChD,EAAE,EAAE,eAAe,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC;IACxB,6FAA6F;IAC7F,UAAU,EAAE,OAAO,CAAC;IACpB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,kFAAkF;IAClF,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2EAA2E;IAC3E,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,2DAA2D;IAC3D,kCAAkC,CAAC,EAAE,MAAM,CAAC;CAC/C,GAAG,CAAC,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CA2PjF"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAuBlD,QAAA,MAAM,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAuBlD,QAAA,MAAM,MAAM,EAAE,MAkMb,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -22202,10 +22202,16 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
22202
22202
|
user_memories: exports_external.object({
|
|
22203
22203
|
enabled: exports_external.boolean().default(false),
|
|
22204
22204
|
promotion_threshold: exports_external.number().min(2).max(20).default(3)
|
|
22205
|
-
}).default({ enabled: false, promotion_threshold: 3 })
|
|
22205
|
+
}).default({ enabled: false, promotion_threshold: 3 }),
|
|
22206
|
+
pin_key_files: exports_external.object({
|
|
22207
|
+
enabled: exports_external.boolean().default(false),
|
|
22208
|
+
token_budget: exports_external.number().min(2000).max(30000).default(1e4),
|
|
22209
|
+
min_reads: exports_external.number().min(2).max(20).default(4)
|
|
22210
|
+
}).default({ enabled: false, token_budget: 1e4, min_reads: 4 })
|
|
22206
22211
|
}).default({
|
|
22207
22212
|
compaction_markers: false,
|
|
22208
|
-
user_memories: { enabled: false, promotion_threshold: 3 }
|
|
22213
|
+
user_memories: { enabled: false, promotion_threshold: 3 },
|
|
22214
|
+
pin_key_files: { enabled: false, token_budget: 1e4, min_reads: 4 }
|
|
22209
22215
|
}),
|
|
22210
22216
|
memory: exports_external.object({
|
|
22211
22217
|
enabled: exports_external.boolean().default(true),
|
|
@@ -23502,8 +23508,19 @@ function clearStaleEntries(db, maxAgeMs) {
|
|
|
23502
23508
|
return result.changes;
|
|
23503
23509
|
}
|
|
23504
23510
|
// src/features/magic-context/dreamer/runner.ts
|
|
23511
|
+
import { Database } from "bun:sqlite";
|
|
23505
23512
|
import { existsSync as existsSync4 } from "fs";
|
|
23506
|
-
import { join as
|
|
23513
|
+
import { join as join7 } from "path";
|
|
23514
|
+
|
|
23515
|
+
// src/shared/data-path.ts
|
|
23516
|
+
import * as os2 from "os";
|
|
23517
|
+
import * as path2 from "path";
|
|
23518
|
+
function getDataDir() {
|
|
23519
|
+
return process.env.XDG_DATA_HOME ?? path2.join(os2.homedir(), ".local", "share");
|
|
23520
|
+
}
|
|
23521
|
+
function getOpenCodeStorageDir() {
|
|
23522
|
+
return path2.join(getDataDir(), "opencode", "storage");
|
|
23523
|
+
}
|
|
23507
23524
|
|
|
23508
23525
|
// src/shared/error-message.ts
|
|
23509
23526
|
function getErrorMessage(error48) {
|
|
@@ -23513,6 +23530,189 @@ function getErrorMessage(error48) {
|
|
|
23513
23530
|
// src/features/magic-context/dreamer/runner.ts
|
|
23514
23531
|
init_logger();
|
|
23515
23532
|
|
|
23533
|
+
// src/features/magic-context/key-files/identify-key-files.ts
|
|
23534
|
+
init_logger();
|
|
23535
|
+
|
|
23536
|
+
// src/features/magic-context/key-files/read-stats.ts
|
|
23537
|
+
function getSessionReadStats(openCodeDb, sessionId, minReads) {
|
|
23538
|
+
const fullReads = openCodeDb.prepare(`
|
|
23539
|
+
WITH full_reads AS (
|
|
23540
|
+
SELECT
|
|
23541
|
+
json_extract(json_extract(data, '$.state'), '$.input.filePath') as file_path,
|
|
23542
|
+
LENGTH(json_extract(json_extract(data, '$.state'), '$.output')) as output_bytes,
|
|
23543
|
+
p.time_created,
|
|
23544
|
+
ROW_NUMBER() OVER (
|
|
23545
|
+
PARTITION BY json_extract(json_extract(data, '$.state'), '$.input.filePath')
|
|
23546
|
+
ORDER BY p.time_created DESC
|
|
23547
|
+
) as rn
|
|
23548
|
+
FROM part p
|
|
23549
|
+
WHERE p.session_id = ?
|
|
23550
|
+
AND json_extract(data, '$.type') = 'tool'
|
|
23551
|
+
AND json_extract(data, '$.tool') = 'read'
|
|
23552
|
+
AND json_extract(json_extract(data, '$.state'), '$.input.filePath') IS NOT NULL
|
|
23553
|
+
AND json_extract(json_extract(data, '$.state'), '$.input.startLine') IS NULL
|
|
23554
|
+
AND json_extract(json_extract(data, '$.state'), '$.input.start_line') IS NULL
|
|
23555
|
+
AND json_extract(json_extract(data, '$.state'), '$.input.endLine') IS NULL
|
|
23556
|
+
AND json_extract(json_extract(data, '$.state'), '$.input.end_line') IS NULL
|
|
23557
|
+
AND json_extract(json_extract(data, '$.state'), '$.input.offset') IS NULL
|
|
23558
|
+
AND json_extract(json_extract(data, '$.state'), '$.input.limit') IS NULL
|
|
23559
|
+
),
|
|
23560
|
+
file_counts AS (
|
|
23561
|
+
SELECT file_path, COUNT(*) as full_read_count
|
|
23562
|
+
FROM full_reads
|
|
23563
|
+
GROUP BY file_path
|
|
23564
|
+
HAVING full_read_count >= ?
|
|
23565
|
+
)
|
|
23566
|
+
SELECT
|
|
23567
|
+
r.file_path,
|
|
23568
|
+
fc.full_read_count,
|
|
23569
|
+
r.output_bytes as latest_read_bytes
|
|
23570
|
+
FROM full_reads r
|
|
23571
|
+
JOIN file_counts fc ON r.file_path = fc.file_path
|
|
23572
|
+
WHERE r.rn = 1
|
|
23573
|
+
ORDER BY fc.full_read_count DESC
|
|
23574
|
+
`).all(sessionId, minReads);
|
|
23575
|
+
if (fullReads.length === 0)
|
|
23576
|
+
return [];
|
|
23577
|
+
const editCounts = new Map;
|
|
23578
|
+
const editRows = openCodeDb.prepare(`
|
|
23579
|
+
SELECT
|
|
23580
|
+
json_extract(json_extract(data, '$.state'), '$.input.filePath') as file_path,
|
|
23581
|
+
COUNT(*) as edit_count
|
|
23582
|
+
FROM part p
|
|
23583
|
+
WHERE p.session_id = ?
|
|
23584
|
+
AND json_extract(data, '$.type') = 'tool'
|
|
23585
|
+
AND json_extract(data, '$.tool') IN ('edit', 'write', 'mcp_edit', 'mcp_write')
|
|
23586
|
+
AND json_extract(json_extract(data, '$.state'), '$.input.filePath') IS NOT NULL
|
|
23587
|
+
GROUP BY file_path
|
|
23588
|
+
`).all(sessionId);
|
|
23589
|
+
for (const row of editRows) {
|
|
23590
|
+
editCounts.set(row.file_path, row.edit_count);
|
|
23591
|
+
}
|
|
23592
|
+
return fullReads.map((row) => ({
|
|
23593
|
+
filePath: row.file_path,
|
|
23594
|
+
fullReadCount: row.full_read_count,
|
|
23595
|
+
spreadAcrossCompartments: 0,
|
|
23596
|
+
editCount: editCounts.get(row.file_path) ?? 0,
|
|
23597
|
+
latestReadBytes: row.latest_read_bytes ?? 0,
|
|
23598
|
+
latestReadTokens: Math.ceil((row.latest_read_bytes ?? 0) / 3.5)
|
|
23599
|
+
}));
|
|
23600
|
+
}
|
|
23601
|
+
|
|
23602
|
+
// src/features/magic-context/key-files/storage-key-files.ts
|
|
23603
|
+
init_logger();
|
|
23604
|
+
function getKeyFiles(db, sessionId) {
|
|
23605
|
+
try {
|
|
23606
|
+
const row = db.prepare("SELECT key_files FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
23607
|
+
if (!row?.key_files)
|
|
23608
|
+
return [];
|
|
23609
|
+
const parsed = JSON.parse(row.key_files);
|
|
23610
|
+
if (!Array.isArray(parsed))
|
|
23611
|
+
return [];
|
|
23612
|
+
return parsed.filter((e) => typeof e === "object" && e !== null && typeof e.filePath === "string" && typeof e.tokens === "number");
|
|
23613
|
+
} catch {
|
|
23614
|
+
return [];
|
|
23615
|
+
}
|
|
23616
|
+
}
|
|
23617
|
+
function setKeyFiles(db, sessionId, files) {
|
|
23618
|
+
try {
|
|
23619
|
+
db.prepare("INSERT OR IGNORE INTO session_meta (session_id) VALUES (?)").run(sessionId);
|
|
23620
|
+
db.prepare("UPDATE session_meta SET key_files = ? WHERE session_id = ?").run(JSON.stringify(files), sessionId);
|
|
23621
|
+
} catch (error48) {
|
|
23622
|
+
sessionLog(sessionId, "failed to persist key files:", error48);
|
|
23623
|
+
}
|
|
23624
|
+
}
|
|
23625
|
+
function greedyFitFiles(rankedFiles, tokenBudget) {
|
|
23626
|
+
const selected = [];
|
|
23627
|
+
let remainingBudget = tokenBudget;
|
|
23628
|
+
for (const file2 of rankedFiles) {
|
|
23629
|
+
if (file2.tokens <= 0)
|
|
23630
|
+
continue;
|
|
23631
|
+
if (file2.tokens > remainingBudget)
|
|
23632
|
+
continue;
|
|
23633
|
+
selected.push({ filePath: file2.filePath, tokens: file2.tokens });
|
|
23634
|
+
remainingBudget -= file2.tokens;
|
|
23635
|
+
if (remainingBudget <= 0)
|
|
23636
|
+
break;
|
|
23637
|
+
}
|
|
23638
|
+
return selected;
|
|
23639
|
+
}
|
|
23640
|
+
|
|
23641
|
+
// src/features/magic-context/key-files/identify-key-files.ts
|
|
23642
|
+
var KEY_FILES_SYSTEM_PROMPT = "You are a file importance evaluator. Given read statistics about files in a coding session, identify which are core orientation files worth pinning in context. Return a JSON array.";
|
|
23643
|
+
function buildKeyFilesPrompt(candidates, tokenBudget, minReads) {
|
|
23644
|
+
const statsText = candidates.map((s) => `- **${s.filePath}** \u2014 ${s.fullReadCount} full reads, ${s.editCount} edits, ~${s.latestReadTokens} tokens`).join(`
|
|
23645
|
+
`);
|
|
23646
|
+
return `## Identify Key Files for Pinning
|
|
23647
|
+
|
|
23648
|
+
The following files were fully read ${minReads}+ times during a coding session.
|
|
23649
|
+
Identify which ones are **core orientation files** worth keeping permanently in context.
|
|
23650
|
+
|
|
23651
|
+
### Signals of a core orientation file:
|
|
23652
|
+
- Read many times across different phases of work (not clustered in one task)
|
|
23653
|
+
- Read without editing \u2014 consulted for understanding, not modification
|
|
23654
|
+
- Contains architecture, configuration, types, or key abstractions
|
|
23655
|
+
|
|
23656
|
+
### Signals of a NON-core file (exclude):
|
|
23657
|
+
- Read many times but always edited \u2014 actively working on it
|
|
23658
|
+
- Very large (>5000 tokens) \u2014 too expensive to pin
|
|
23659
|
+
- Test files, scripts, or generated files
|
|
23660
|
+
|
|
23661
|
+
### Token budget: ${tokenBudget} tokens total
|
|
23662
|
+
|
|
23663
|
+
### Files:
|
|
23664
|
+
${statsText}
|
|
23665
|
+
|
|
23666
|
+
### Output Format
|
|
23667
|
+
Return a JSON array ranked by importance (most important first):
|
|
23668
|
+
\`\`\`json
|
|
23669
|
+
[
|
|
23670
|
+
{"filePath": "src/path/to/file.ts", "tokens": 2500, "reason": "brief reason"}
|
|
23671
|
+
]
|
|
23672
|
+
\`\`\`
|
|
23673
|
+
|
|
23674
|
+
Only include files you're confident are true orientation files. Return empty array if none qualify.`;
|
|
23675
|
+
}
|
|
23676
|
+
function parseKeyFilesOutput(text) {
|
|
23677
|
+
const jsonMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/) ?? text.match(/\[[\s\S]*\]/);
|
|
23678
|
+
if (!jsonMatch)
|
|
23679
|
+
return [];
|
|
23680
|
+
try {
|
|
23681
|
+
const raw = jsonMatch[1] ?? jsonMatch[0];
|
|
23682
|
+
const parsed = JSON.parse(raw);
|
|
23683
|
+
if (!Array.isArray(parsed))
|
|
23684
|
+
return [];
|
|
23685
|
+
return parsed.filter((item) => typeof item === "object" && item !== null && typeof item.filePath === "string" && typeof item.tokens === "number").map((item) => ({ filePath: item.filePath, tokens: item.tokens }));
|
|
23686
|
+
} catch {
|
|
23687
|
+
return [];
|
|
23688
|
+
}
|
|
23689
|
+
}
|
|
23690
|
+
function getKeyFileCandidates(openCodeDb, sessionId, minReads, tokenBudget) {
|
|
23691
|
+
const stats = getSessionReadStats(openCodeDb, sessionId, minReads);
|
|
23692
|
+
const maxPerFileTokens = Math.min(tokenBudget / 2, 5000);
|
|
23693
|
+
return stats.filter((s) => s.latestReadTokens > 0 && s.latestReadTokens <= maxPerFileTokens);
|
|
23694
|
+
}
|
|
23695
|
+
function applyKeyFileResults(db, sessionId, llmRanked, tokenBudget, candidatePaths) {
|
|
23696
|
+
const filtered = candidatePaths ? llmRanked.filter((f) => candidatePaths.has(f.filePath)) : llmRanked;
|
|
23697
|
+
const selected = greedyFitFiles(filtered, tokenBudget);
|
|
23698
|
+
setKeyFiles(db, sessionId, selected);
|
|
23699
|
+
const totalTokens = selected.reduce((sum, f) => sum + f.tokens, 0);
|
|
23700
|
+
log(`[key-files][${sessionId}] pinned ${selected.length} files (${totalTokens} tokens): ${selected.map((f) => f.filePath).join(", ")}`);
|
|
23701
|
+
return { filesIdentified: selected.length, totalTokens };
|
|
23702
|
+
}
|
|
23703
|
+
function heuristicKeyFileSelection(db, sessionId, candidates, tokenBudget) {
|
|
23704
|
+
const scored = candidates.map((c) => ({
|
|
23705
|
+
filePath: c.filePath,
|
|
23706
|
+
tokens: c.latestReadTokens,
|
|
23707
|
+
score: c.fullReadCount * 2 - c.editCount * 3
|
|
23708
|
+
})).filter((c) => c.score > 0).sort((a, b) => b.score - a.score);
|
|
23709
|
+
const selected = greedyFitFiles(scored, tokenBudget);
|
|
23710
|
+
setKeyFiles(db, sessionId, selected);
|
|
23711
|
+
const totalTokens = selected.reduce((sum, f) => sum + f.tokens, 0);
|
|
23712
|
+
log(`[key-files][${sessionId}] heuristic pinned ${selected.length} files (${totalTokens} tokens)`);
|
|
23713
|
+
return { filesIdentified: selected.length, totalTokens };
|
|
23714
|
+
}
|
|
23715
|
+
|
|
23516
23716
|
// src/features/magic-context/memory/storage-memory-embeddings.ts
|
|
23517
23717
|
var saveEmbeddingStatements = new WeakMap;
|
|
23518
23718
|
var loadAllEmbeddingsStatements = new WeakMap;
|
|
@@ -24408,6 +24608,176 @@ function countNewIds(beforeIds, afterIds) {
|
|
|
24408
24608
|
}
|
|
24409
24609
|
return count;
|
|
24410
24610
|
}
|
|
24611
|
+
function getOpenCodeDbPath() {
|
|
24612
|
+
return join7(getDataDir(), "opencode", "opencode.db");
|
|
24613
|
+
}
|
|
24614
|
+
function openOpenCodeDb() {
|
|
24615
|
+
const dbPath = getOpenCodeDbPath();
|
|
24616
|
+
if (!existsSync4(dbPath)) {
|
|
24617
|
+
log(`[key-files] OpenCode DB not found at ${dbPath} \u2014 skipping`);
|
|
24618
|
+
return null;
|
|
24619
|
+
}
|
|
24620
|
+
try {
|
|
24621
|
+
const db = new Database(dbPath, { readonly: true });
|
|
24622
|
+
db.exec("PRAGMA busy_timeout = 5000");
|
|
24623
|
+
return db;
|
|
24624
|
+
} catch (error48) {
|
|
24625
|
+
log(`[key-files] failed to open OpenCode DB at ${dbPath}: ${getErrorMessage(error48)}`);
|
|
24626
|
+
return null;
|
|
24627
|
+
}
|
|
24628
|
+
}
|
|
24629
|
+
function isSessionIdRow(row) {
|
|
24630
|
+
if (row === null || typeof row !== "object") {
|
|
24631
|
+
return false;
|
|
24632
|
+
}
|
|
24633
|
+
return typeof row.sessionId === "string";
|
|
24634
|
+
}
|
|
24635
|
+
function hasExplicitEmptyKeyFilesOutput(text) {
|
|
24636
|
+
return /```(?:json)?\s*\[\s*\]\s*```/s.test(text) || /^\s*\[\s*\]\s*$/s.test(text);
|
|
24637
|
+
}
|
|
24638
|
+
async function getActiveProjectSessionIds(args) {
|
|
24639
|
+
const listResponse = await args.client.session.list({
|
|
24640
|
+
query: { directory: args.sessionDirectory ?? args.projectIdentity }
|
|
24641
|
+
});
|
|
24642
|
+
const sessions = normalizeSDKResponse(listResponse, [], {
|
|
24643
|
+
preferResponseOnMissingData: true
|
|
24644
|
+
});
|
|
24645
|
+
const projectSessionIds = new Set(sessions.map((session) => typeof session?.id === "string" ? session.id : null).filter((sessionId) => Boolean(sessionId)));
|
|
24646
|
+
if (projectSessionIds.size === 0) {
|
|
24647
|
+
return [];
|
|
24648
|
+
}
|
|
24649
|
+
return args.db.prepare("SELECT session_id AS sessionId FROM session_meta WHERE is_subagent = 0 ORDER BY session_id ASC").all().filter(isSessionIdRow).map((row) => row.sessionId).filter((sessionId) => projectSessionIds.has(sessionId));
|
|
24650
|
+
}
|
|
24651
|
+
async function identifyKeyFilesForSession(args) {
|
|
24652
|
+
let openCodeDb = null;
|
|
24653
|
+
try {
|
|
24654
|
+
openCodeDb = openOpenCodeDb();
|
|
24655
|
+
if (!openCodeDb) {
|
|
24656
|
+
return;
|
|
24657
|
+
}
|
|
24658
|
+
const candidates = getKeyFileCandidates(openCodeDb, args.sessionId, args.config.min_reads, args.config.token_budget);
|
|
24659
|
+
if (candidates.length === 0) {
|
|
24660
|
+
log(`[key-files][${args.sessionId}] no candidates found \u2014 skipping`);
|
|
24661
|
+
return;
|
|
24662
|
+
}
|
|
24663
|
+
const prompt = buildKeyFilesPrompt(candidates, args.config.token_budget, args.config.min_reads);
|
|
24664
|
+
const applyHeuristicFallback = () => {
|
|
24665
|
+
heuristicKeyFileSelection(args.db, args.sessionId, candidates, args.config.token_budget);
|
|
24666
|
+
};
|
|
24667
|
+
let agentSessionId = null;
|
|
24668
|
+
const abortController = new AbortController;
|
|
24669
|
+
const leaseInterval = setInterval(() => {
|
|
24670
|
+
try {
|
|
24671
|
+
if (!renewLease(args.db, args.holderId)) {
|
|
24672
|
+
log(`[key-files][${args.sessionId}] lease renewal failed \u2014 aborting`);
|
|
24673
|
+
abortController.abort();
|
|
24674
|
+
}
|
|
24675
|
+
} catch {
|
|
24676
|
+
abortController.abort();
|
|
24677
|
+
}
|
|
24678
|
+
}, 60000);
|
|
24679
|
+
try {
|
|
24680
|
+
const createResponse = await args.client.session.create({
|
|
24681
|
+
body: {
|
|
24682
|
+
...args.parentSessionId ? { parentID: args.parentSessionId } : {},
|
|
24683
|
+
title: `magic-context-dream-key-files-${args.sessionId.slice(0, 12)}`
|
|
24684
|
+
},
|
|
24685
|
+
query: { directory: args.sessionDirectory }
|
|
24686
|
+
});
|
|
24687
|
+
const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
24688
|
+
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
24689
|
+
if (!agentSessionId) {
|
|
24690
|
+
throw new Error("Could not create key-file identification session.");
|
|
24691
|
+
}
|
|
24692
|
+
log(`[key-files][${args.sessionId}] child session created ${agentSessionId}`);
|
|
24693
|
+
const remainingMs = Math.max(0, args.deadline - Date.now());
|
|
24694
|
+
await promptSyncWithModelSuggestionRetry(args.client, {
|
|
24695
|
+
path: { id: agentSessionId },
|
|
24696
|
+
query: { directory: args.sessionDirectory },
|
|
24697
|
+
body: {
|
|
24698
|
+
agent: DREAMER_AGENT,
|
|
24699
|
+
system: KEY_FILES_SYSTEM_PROMPT,
|
|
24700
|
+
parts: [{ type: "text", text: prompt }]
|
|
24701
|
+
}
|
|
24702
|
+
}, { timeoutMs: Math.min(remainingMs, 5 * 60 * 1000), signal: abortController.signal });
|
|
24703
|
+
const messagesResponse = await args.client.session.messages({
|
|
24704
|
+
path: { id: agentSessionId },
|
|
24705
|
+
query: { directory: args.sessionDirectory }
|
|
24706
|
+
});
|
|
24707
|
+
const messages = normalizeSDKResponse(messagesResponse, [], {
|
|
24708
|
+
preferResponseOnMissingData: true
|
|
24709
|
+
});
|
|
24710
|
+
const responseText = extractLatestAssistantText(messages);
|
|
24711
|
+
if (!responseText) {
|
|
24712
|
+
log(`[key-files][${args.sessionId}] no response from agent \u2014 using heuristic fallback`);
|
|
24713
|
+
applyHeuristicFallback();
|
|
24714
|
+
return;
|
|
24715
|
+
}
|
|
24716
|
+
const parsed = parseKeyFilesOutput(responseText);
|
|
24717
|
+
if (parsed.length > 0 || hasExplicitEmptyKeyFilesOutput(responseText)) {
|
|
24718
|
+
const candidatePaths = new Set(candidates.map((c) => c.filePath));
|
|
24719
|
+
applyKeyFileResults(args.db, args.sessionId, parsed, args.config.token_budget, candidatePaths);
|
|
24720
|
+
return;
|
|
24721
|
+
}
|
|
24722
|
+
log(`[key-files][${args.sessionId}] could not parse agent output \u2014 using heuristic fallback`);
|
|
24723
|
+
applyHeuristicFallback();
|
|
24724
|
+
} catch (error48) {
|
|
24725
|
+
log(`[key-files][${args.sessionId}] identification failed: ${getErrorMessage(error48)} \u2014 using heuristic fallback`);
|
|
24726
|
+
try {
|
|
24727
|
+
applyHeuristicFallback();
|
|
24728
|
+
} catch (fallbackError) {
|
|
24729
|
+
log(`[key-files][${args.sessionId}] heuristic fallback failed: ${getErrorMessage(fallbackError)}`);
|
|
24730
|
+
}
|
|
24731
|
+
} finally {
|
|
24732
|
+
clearInterval(leaseInterval);
|
|
24733
|
+
if (agentSessionId) {
|
|
24734
|
+
await args.client.session.delete({
|
|
24735
|
+
path: { id: agentSessionId },
|
|
24736
|
+
query: { directory: args.sessionDirectory }
|
|
24737
|
+
}).catch((error48) => {
|
|
24738
|
+
log(`[key-files][${args.sessionId}] session cleanup failed: ${getErrorMessage(error48)}`);
|
|
24739
|
+
});
|
|
24740
|
+
}
|
|
24741
|
+
}
|
|
24742
|
+
} finally {
|
|
24743
|
+
if (openCodeDb) {
|
|
24744
|
+
try {
|
|
24745
|
+
openCodeDb.close(false);
|
|
24746
|
+
} catch (error48) {
|
|
24747
|
+
log(`[key-files][${args.sessionId}] failed to close OpenCode DB: ${getErrorMessage(error48)}`);
|
|
24748
|
+
}
|
|
24749
|
+
}
|
|
24750
|
+
}
|
|
24751
|
+
}
|
|
24752
|
+
async function identifyKeyFiles(args) {
|
|
24753
|
+
const sessionIds = await getActiveProjectSessionIds({
|
|
24754
|
+
db: args.db,
|
|
24755
|
+
client: args.client,
|
|
24756
|
+
projectIdentity: args.projectIdentity,
|
|
24757
|
+
sessionDirectory: args.sessionDirectory
|
|
24758
|
+
});
|
|
24759
|
+
if (sessionIds.length === 0) {
|
|
24760
|
+
log(`[key-files] no active sessions found for ${args.projectIdentity}`);
|
|
24761
|
+
return;
|
|
24762
|
+
}
|
|
24763
|
+
log(`[key-files] evaluating ${sessionIds.length} active session(s) for ${args.projectIdentity}`);
|
|
24764
|
+
for (const sessionId of sessionIds) {
|
|
24765
|
+
if (Date.now() > args.deadline) {
|
|
24766
|
+
log("[key-files] deadline reached \u2014 stopping key-file identification");
|
|
24767
|
+
break;
|
|
24768
|
+
}
|
|
24769
|
+
await identifyKeyFilesForSession({
|
|
24770
|
+
db: args.db,
|
|
24771
|
+
client: args.client,
|
|
24772
|
+
parentSessionId: args.parentSessionId,
|
|
24773
|
+
sessionDirectory: args.sessionDirectory,
|
|
24774
|
+
holderId: args.holderId,
|
|
24775
|
+
deadline: args.deadline,
|
|
24776
|
+
sessionId,
|
|
24777
|
+
config: args.config
|
|
24778
|
+
});
|
|
24779
|
+
}
|
|
24780
|
+
}
|
|
24411
24781
|
async function runDream(args) {
|
|
24412
24782
|
const holderId = crypto.randomUUID();
|
|
24413
24783
|
const startedAt = Date.now();
|
|
@@ -24479,8 +24849,8 @@ async function runDream(args) {
|
|
|
24479
24849
|
try {
|
|
24480
24850
|
const docsDir = args.sessionDirectory ?? args.projectIdentity;
|
|
24481
24851
|
const existingDocs = taskName === "maintain-docs" ? {
|
|
24482
|
-
architecture: existsSync4(
|
|
24483
|
-
structure: existsSync4(
|
|
24852
|
+
architecture: existsSync4(join7(docsDir, "ARCHITECTURE.md")),
|
|
24853
|
+
structure: existsSync4(join7(docsDir, "STRUCTURE.md"))
|
|
24484
24854
|
} : undefined;
|
|
24485
24855
|
const taskPrompt = buildDreamTaskPrompt(taskName, {
|
|
24486
24856
|
projectPath: args.projectIdentity,
|
|
@@ -24586,6 +24956,22 @@ async function runDream(args) {
|
|
|
24586
24956
|
log(`[dreamer] smart note evaluation failed: ${getErrorMessage(error48)}`);
|
|
24587
24957
|
}
|
|
24588
24958
|
}
|
|
24959
|
+
if (args.experimentalPinKeyFiles?.enabled && Date.now() <= deadline) {
|
|
24960
|
+
try {
|
|
24961
|
+
await identifyKeyFiles({
|
|
24962
|
+
db: args.db,
|
|
24963
|
+
client: args.client,
|
|
24964
|
+
projectIdentity: args.projectIdentity,
|
|
24965
|
+
parentSessionId,
|
|
24966
|
+
sessionDirectory: args.sessionDirectory ?? args.projectIdentity,
|
|
24967
|
+
holderId,
|
|
24968
|
+
deadline,
|
|
24969
|
+
config: args.experimentalPinKeyFiles
|
|
24970
|
+
});
|
|
24971
|
+
} catch (error48) {
|
|
24972
|
+
log(`[key-files] identification phase failed: ${getErrorMessage(error48)}`);
|
|
24973
|
+
}
|
|
24974
|
+
}
|
|
24589
24975
|
} finally {
|
|
24590
24976
|
releaseLease(args.db, holderId);
|
|
24591
24977
|
log(`[dreamer] lease released: ${holderId}`);
|
|
@@ -24794,7 +25180,8 @@ async function processDreamQueue(args) {
|
|
|
24794
25180
|
taskTimeoutMinutes: args.taskTimeoutMinutes,
|
|
24795
25181
|
maxRuntimeMinutes: args.maxRuntimeMinutes,
|
|
24796
25182
|
sessionDirectory: projectDirectory,
|
|
24797
|
-
experimentalUserMemories: args.experimentalUserMemories
|
|
25183
|
+
experimentalUserMemories: args.experimentalUserMemories,
|
|
25184
|
+
experimentalPinKeyFiles: args.experimentalPinKeyFiles
|
|
24798
25185
|
});
|
|
24799
25186
|
} catch (error48) {
|
|
24800
25187
|
log(`[dreamer] runDream threw for ${entry.projectIdentity}: ${getErrorMessage(error48)}`);
|
|
@@ -25291,7 +25678,7 @@ function getEmbeddingModelId() {
|
|
|
25291
25678
|
|
|
25292
25679
|
// src/features/magic-context/memory/project-identity.ts
|
|
25293
25680
|
import { execSync } from "child_process";
|
|
25294
|
-
import
|
|
25681
|
+
import path3 from "path";
|
|
25295
25682
|
var GIT_TIMEOUT_MS = 5000;
|
|
25296
25683
|
var resolvedCache = new Map;
|
|
25297
25684
|
function getRootCommitHash(directory) {
|
|
@@ -25310,12 +25697,12 @@ function getRootCommitHash(directory) {
|
|
|
25310
25697
|
}
|
|
25311
25698
|
}
|
|
25312
25699
|
function directoryFallback(directory) {
|
|
25313
|
-
const canonical =
|
|
25700
|
+
const canonical = path3.resolve(directory);
|
|
25314
25701
|
const hash2 = Bun.hash(canonical).toString(16).slice(0, 12);
|
|
25315
25702
|
return `dir:${hash2}`;
|
|
25316
25703
|
}
|
|
25317
25704
|
function resolveProjectIdentity(directory) {
|
|
25318
|
-
const resolved =
|
|
25705
|
+
const resolved = path3.resolve(directory);
|
|
25319
25706
|
const cached2 = resolvedCache.get(resolved);
|
|
25320
25707
|
if (cached2 !== undefined) {
|
|
25321
25708
|
return cached2;
|
|
@@ -25402,22 +25789,10 @@ function removeSystemReminders(text) {
|
|
|
25402
25789
|
}
|
|
25403
25790
|
|
|
25404
25791
|
// src/hooks/magic-context/read-session-db.ts
|
|
25405
|
-
import { Database } from "bun:sqlite";
|
|
25792
|
+
import { Database as Database2 } from "bun:sqlite";
|
|
25406
25793
|
import { join as join8 } from "path";
|
|
25407
|
-
|
|
25408
|
-
// src/shared/data-path.ts
|
|
25409
|
-
import * as os2 from "os";
|
|
25410
|
-
import * as path3 from "path";
|
|
25411
|
-
function getDataDir() {
|
|
25412
|
-
return process.env.XDG_DATA_HOME ?? path3.join(os2.homedir(), ".local", "share");
|
|
25413
|
-
}
|
|
25414
|
-
function getOpenCodeStorageDir() {
|
|
25415
|
-
return path3.join(getDataDir(), "opencode", "storage");
|
|
25416
|
-
}
|
|
25417
|
-
|
|
25418
|
-
// src/hooks/magic-context/read-session-db.ts
|
|
25419
25794
|
init_logger();
|
|
25420
|
-
function
|
|
25795
|
+
function getOpenCodeDbPath2() {
|
|
25421
25796
|
return join8(getDataDir(), "opencode", "opencode.db");
|
|
25422
25797
|
}
|
|
25423
25798
|
var cachedReadOnlyDb = null;
|
|
@@ -25434,12 +25809,12 @@ function closeCachedReadOnlyDb() {
|
|
|
25434
25809
|
}
|
|
25435
25810
|
}
|
|
25436
25811
|
function getReadOnlySessionDb() {
|
|
25437
|
-
const dbPath =
|
|
25812
|
+
const dbPath = getOpenCodeDbPath2();
|
|
25438
25813
|
if (cachedReadOnlyDb?.path === dbPath) {
|
|
25439
25814
|
return cachedReadOnlyDb.db;
|
|
25440
25815
|
}
|
|
25441
25816
|
closeCachedReadOnlyDb();
|
|
25442
|
-
const db = new
|
|
25817
|
+
const db = new Database2(dbPath, { readonly: true });
|
|
25443
25818
|
cachedReadOnlyDb = { path: dbPath, db };
|
|
25444
25819
|
return db;
|
|
25445
25820
|
}
|
|
@@ -25992,7 +26367,7 @@ function ensureMessagesIndexed(db, sessionId, readMessages) {
|
|
|
25992
26367
|
})();
|
|
25993
26368
|
}
|
|
25994
26369
|
// src/features/magic-context/storage-db.ts
|
|
25995
|
-
import { Database as
|
|
26370
|
+
import { Database as Database3 } from "bun:sqlite";
|
|
25996
26371
|
import { mkdirSync } from "fs";
|
|
25997
26372
|
import { join as join9 } from "path";
|
|
25998
26373
|
init_logger();
|
|
@@ -26428,6 +26803,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
26428
26803
|
ensureColumn(db, "tags", "reasoning_byte_size", "INTEGER DEFAULT 0");
|
|
26429
26804
|
ensureColumn(db, "session_meta", "system_prompt_tokens", "INTEGER DEFAULT 0");
|
|
26430
26805
|
ensureColumn(db, "session_meta", "compaction_marker_state", "TEXT DEFAULT ''");
|
|
26806
|
+
ensureColumn(db, "session_meta", "key_files", "TEXT DEFAULT ''");
|
|
26431
26807
|
}
|
|
26432
26808
|
function ensureColumn(db, table, column, definition) {
|
|
26433
26809
|
if (!/^[a-z_]+$/.test(table) || !/^[a-z_]+$/.test(column) || !/^[A-Z0-9_'(),\s]+$/i.test(definition)) {
|
|
@@ -26441,7 +26817,7 @@ function ensureColumn(db, table, column, definition) {
|
|
|
26441
26817
|
}
|
|
26442
26818
|
function createFallbackDatabase() {
|
|
26443
26819
|
try {
|
|
26444
|
-
const fallback = new
|
|
26820
|
+
const fallback = new Database3(":memory:");
|
|
26445
26821
|
initializeDatabase(fallback);
|
|
26446
26822
|
runMigrations(fallback);
|
|
26447
26823
|
return fallback;
|
|
@@ -26460,7 +26836,7 @@ function openDatabase() {
|
|
|
26460
26836
|
return existing;
|
|
26461
26837
|
}
|
|
26462
26838
|
mkdirSync(dbDir, { recursive: true });
|
|
26463
|
-
const db = new
|
|
26839
|
+
const db = new Database3(dbPath);
|
|
26464
26840
|
initializeDatabase(db);
|
|
26465
26841
|
runMigrations(db);
|
|
26466
26842
|
databases.set(dbPath, db);
|
|
@@ -27012,7 +27388,8 @@ function startDreamScheduleTimer(args) {
|
|
|
27012
27388
|
dreamerConfig,
|
|
27013
27389
|
embeddingConfig: embeddingConfig2,
|
|
27014
27390
|
memoryEnabled,
|
|
27015
|
-
experimentalUserMemories
|
|
27391
|
+
experimentalUserMemories,
|
|
27392
|
+
experimentalPinKeyFiles
|
|
27016
27393
|
} = args;
|
|
27017
27394
|
const dreamingEnabled = Boolean(dreamerConfig?.enabled && dreamerConfig.schedule?.trim());
|
|
27018
27395
|
const embeddingSweepEnabled = memoryEnabled && embeddingConfig2.provider !== "off";
|
|
@@ -27042,7 +27419,8 @@ function startDreamScheduleTimer(args) {
|
|
|
27042
27419
|
tasks: dreamerConfig.tasks,
|
|
27043
27420
|
taskTimeoutMinutes: dreamerConfig.task_timeout_minutes,
|
|
27044
27421
|
maxRuntimeMinutes: dreamerConfig.max_runtime_minutes,
|
|
27045
|
-
experimentalUserMemories
|
|
27422
|
+
experimentalUserMemories,
|
|
27423
|
+
experimentalPinKeyFiles
|
|
27046
27424
|
}).catch((error48) => {
|
|
27047
27425
|
log("[dreamer] timer-triggered queue processing failed:", error48);
|
|
27048
27426
|
});
|
|
@@ -27841,7 +28219,8 @@ Dreaming is not configured for this project.`, {});
|
|
|
27841
28219
|
tasks: deps.dreamer.config.tasks,
|
|
27842
28220
|
taskTimeoutMinutes: deps.dreamer.config.task_timeout_minutes,
|
|
27843
28221
|
maxRuntimeMinutes: deps.dreamer.config.max_runtime_minutes,
|
|
27844
|
-
experimentalUserMemories: deps.dreamer.experimentalUserMemories
|
|
28222
|
+
experimentalUserMemories: deps.dreamer.experimentalUserMemories,
|
|
28223
|
+
experimentalPinKeyFiles: deps.dreamer.experimentalPinKeyFiles
|
|
27845
28224
|
});
|
|
27846
28225
|
await deps.sendNotification(sessionId, result ? summarizeDreamResult(result) : "Dream queued, but another worker is already processing the queue.", {});
|
|
27847
28226
|
throw new Error(`${SENTINEL_PREFIX}CTX-DREAM_HANDLED__`);
|
|
@@ -27930,7 +28309,7 @@ Historian recomp started. Rebuilding compartments and facts from raw session his
|
|
|
27930
28309
|
init_logger();
|
|
27931
28310
|
|
|
27932
28311
|
// src/features/magic-context/compaction-marker.ts
|
|
27933
|
-
import { Database as
|
|
28312
|
+
import { Database as Database4 } from "bun:sqlite";
|
|
27934
28313
|
import { join as join10 } from "path";
|
|
27935
28314
|
init_logger();
|
|
27936
28315
|
var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
@@ -27952,12 +28331,12 @@ function generateMessageId(timestampMs, counter = 0n) {
|
|
|
27952
28331
|
function generatePartId(timestampMs, counter = 0n) {
|
|
27953
28332
|
return generateId("prt", timestampMs, counter);
|
|
27954
28333
|
}
|
|
27955
|
-
function
|
|
28334
|
+
function getOpenCodeDbPath3() {
|
|
27956
28335
|
return join10(getDataDir(), "opencode", "opencode.db");
|
|
27957
28336
|
}
|
|
27958
28337
|
var cachedWriteDb = null;
|
|
27959
28338
|
function getWritableOpenCodeDb() {
|
|
27960
|
-
const dbPath =
|
|
28339
|
+
const dbPath = getOpenCodeDbPath3();
|
|
27961
28340
|
if (cachedWriteDb?.path === dbPath) {
|
|
27962
28341
|
return cachedWriteDb.db;
|
|
27963
28342
|
}
|
|
@@ -27966,7 +28345,7 @@ function getWritableOpenCodeDb() {
|
|
|
27966
28345
|
cachedWriteDb.db.close(false);
|
|
27967
28346
|
} catch {}
|
|
27968
28347
|
}
|
|
27969
|
-
const db = new
|
|
28348
|
+
const db = new Database4(dbPath);
|
|
27970
28349
|
db.exec("PRAGMA journal_mode=WAL");
|
|
27971
28350
|
db.exec("PRAGMA busy_timeout=5000");
|
|
27972
28351
|
cachedWriteDb = { path: dbPath, db };
|
|
@@ -31965,8 +32344,8 @@ function createToolExecuteAfterHook(args) {
|
|
|
31965
32344
|
}
|
|
31966
32345
|
|
|
31967
32346
|
// src/hooks/magic-context/system-prompt-hash.ts
|
|
31968
|
-
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
31969
|
-
import { join as join12 } from "path";
|
|
32347
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, realpathSync } from "fs";
|
|
32348
|
+
import { join as join12, resolve as resolve2, sep } from "path";
|
|
31970
32349
|
|
|
31971
32350
|
// src/agents/magic-context-prompt.ts
|
|
31972
32351
|
var BASE_INTRO = (protectedTags) => `Messages and tool outputs are tagged with \xA7N\xA7 identifiers (e.g., \xA71\xA7, \xA742\xA7).
|
|
@@ -32168,7 +32547,9 @@ init_logger();
|
|
|
32168
32547
|
var MAGIC_CONTEXT_MARKER = "## Magic Context";
|
|
32169
32548
|
var PROJECT_DOCS_MARKER = "<project-docs>";
|
|
32170
32549
|
var USER_PROFILE_MARKER = "<user-profile>";
|
|
32550
|
+
var KEY_FILES_MARKER = "<key-files>";
|
|
32171
32551
|
var cachedUserProfileBySession = new Map;
|
|
32552
|
+
var cachedKeyFilesBySession = new Map;
|
|
32172
32553
|
var DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
32173
32554
|
function readProjectDocs(directory) {
|
|
32174
32555
|
const sections = [];
|
|
@@ -32250,6 +32631,72 @@ ${items}
|
|
|
32250
32631
|
output.system.push(profileBlock);
|
|
32251
32632
|
}
|
|
32252
32633
|
}
|
|
32634
|
+
if (deps.experimentalPinKeyFiles) {
|
|
32635
|
+
const hasCachedKeyFiles = cachedKeyFilesBySession.has(sessionId);
|
|
32636
|
+
if (!hasCachedKeyFiles || isCacheBusting) {
|
|
32637
|
+
const keyFileEntries = getKeyFiles(deps.db, sessionId);
|
|
32638
|
+
if (keyFileEntries.length > 0) {
|
|
32639
|
+
const sections = [];
|
|
32640
|
+
const projectRoot = resolve2(deps.directory);
|
|
32641
|
+
let remainingBudgetTokens = deps.experimentalPinKeyFilesTokenBudget ?? 1e4;
|
|
32642
|
+
for (const entry of keyFileEntries) {
|
|
32643
|
+
try {
|
|
32644
|
+
const absPath = resolve2(deps.directory, entry.filePath);
|
|
32645
|
+
if (!absPath.startsWith(projectRoot + sep) && absPath !== projectRoot) {
|
|
32646
|
+
log(`[magic-context] key file path escapes project root, skipping: ${entry.filePath}`);
|
|
32647
|
+
continue;
|
|
32648
|
+
}
|
|
32649
|
+
if (!existsSync5(absPath))
|
|
32650
|
+
continue;
|
|
32651
|
+
let realPath;
|
|
32652
|
+
try {
|
|
32653
|
+
realPath = realpathSync(absPath);
|
|
32654
|
+
} catch {
|
|
32655
|
+
continue;
|
|
32656
|
+
}
|
|
32657
|
+
if (!realPath.startsWith(projectRoot + sep) && realPath !== projectRoot) {
|
|
32658
|
+
log(`[magic-context] key file symlink escapes project root, skipping: ${entry.filePath} \u2192 ${realPath}`);
|
|
32659
|
+
continue;
|
|
32660
|
+
}
|
|
32661
|
+
const content = readFileSync4(realPath, "utf-8").trim();
|
|
32662
|
+
if (content.length === 0)
|
|
32663
|
+
continue;
|
|
32664
|
+
const fileTokens = estimateTokens(content);
|
|
32665
|
+
if (fileTokens > remainingBudgetTokens) {
|
|
32666
|
+
log(`[magic-context] key file ${entry.filePath} exceeds remaining budget (${fileTokens} > ${remainingBudgetTokens}), skipping`);
|
|
32667
|
+
continue;
|
|
32668
|
+
}
|
|
32669
|
+
remainingBudgetTokens -= fileTokens;
|
|
32670
|
+
sections.push(`<file path="${escapeXmlAttr(entry.filePath)}">
|
|
32671
|
+
${escapeXmlContent(content)}
|
|
32672
|
+
</file>`);
|
|
32673
|
+
} catch (error48) {
|
|
32674
|
+
log(`[magic-context] failed to read key file ${entry.filePath}:`, error48);
|
|
32675
|
+
}
|
|
32676
|
+
}
|
|
32677
|
+
if (sections.length > 0) {
|
|
32678
|
+
cachedKeyFilesBySession.set(sessionId, `${KEY_FILES_MARKER}
|
|
32679
|
+
${sections.join(`
|
|
32680
|
+
|
|
32681
|
+
`)}
|
|
32682
|
+
</key-files>`);
|
|
32683
|
+
if (!hasCachedKeyFiles) {
|
|
32684
|
+
sessionLog(sessionId, `loaded ${sections.length} key file(s) into system prompt`);
|
|
32685
|
+
} else {
|
|
32686
|
+
sessionLog(sessionId, "refreshed key files (cache-busting pass)");
|
|
32687
|
+
}
|
|
32688
|
+
} else {
|
|
32689
|
+
cachedKeyFilesBySession.set(sessionId, null);
|
|
32690
|
+
}
|
|
32691
|
+
} else {
|
|
32692
|
+
cachedKeyFilesBySession.set(sessionId, null);
|
|
32693
|
+
}
|
|
32694
|
+
}
|
|
32695
|
+
const keyFilesBlock = cachedKeyFilesBySession.get(sessionId);
|
|
32696
|
+
if (keyFilesBlock && !fullPrompt.includes(KEY_FILES_MARKER)) {
|
|
32697
|
+
output.system.push(keyFilesBlock);
|
|
32698
|
+
}
|
|
32699
|
+
}
|
|
32253
32700
|
const DATE_PATTERN = /Today's date: .+/;
|
|
32254
32701
|
for (let i = 0;i < output.system.length; i++) {
|
|
32255
32702
|
const match = output.system[i].match(DATE_PATTERN);
|
|
@@ -32290,7 +32737,7 @@ ${items}
|
|
|
32290
32737
|
} else if (previousHash === "" || previousHash === "0") {
|
|
32291
32738
|
sessionLog(sessionId, `system prompt hash initialized: ${currentHash} (len=${systemContent.length})`);
|
|
32292
32739
|
}
|
|
32293
|
-
const systemPromptTokens =
|
|
32740
|
+
const systemPromptTokens = estimateTokens(systemContent);
|
|
32294
32741
|
if (currentHash !== previousHash) {
|
|
32295
32742
|
updateSessionMeta(deps.db, sessionId, {
|
|
32296
32743
|
systemPromptHash: currentHash,
|
|
@@ -32424,6 +32871,11 @@ function createMagicContextHook(deps) {
|
|
|
32424
32871
|
experimentalUserMemories: deps.config.experimental?.user_memories?.enabled ? {
|
|
32425
32872
|
enabled: true,
|
|
32426
32873
|
promotionThreshold: deps.config.experimental.user_memories?.promotion_threshold
|
|
32874
|
+
} : undefined,
|
|
32875
|
+
experimentalPinKeyFiles: deps.config.experimental?.pin_key_files?.enabled ? {
|
|
32876
|
+
enabled: true,
|
|
32877
|
+
token_budget: deps.config.experimental.pin_key_files?.token_budget,
|
|
32878
|
+
min_reads: deps.config.experimental.pin_key_files?.min_reads
|
|
32427
32879
|
} : undefined
|
|
32428
32880
|
}).catch((error48) => {
|
|
32429
32881
|
log("[dreamer] scheduled queue processing failed:", error48);
|
|
@@ -32470,6 +32922,11 @@ function createMagicContextHook(deps) {
|
|
|
32470
32922
|
experimentalUserMemories: deps.config.experimental?.user_memories?.enabled ? {
|
|
32471
32923
|
enabled: true,
|
|
32472
32924
|
promotionThreshold: deps.config.experimental.user_memories?.promotion_threshold
|
|
32925
|
+
} : undefined,
|
|
32926
|
+
experimentalPinKeyFiles: deps.config.experimental?.pin_key_files?.enabled ? {
|
|
32927
|
+
enabled: true,
|
|
32928
|
+
token_budget: deps.config.experimental.pin_key_files?.token_budget,
|
|
32929
|
+
min_reads: deps.config.experimental.pin_key_files?.min_reads
|
|
32473
32930
|
} : undefined
|
|
32474
32931
|
} : undefined
|
|
32475
32932
|
});
|
|
@@ -32483,7 +32940,9 @@ function createMagicContextHook(deps) {
|
|
|
32483
32940
|
directory: deps.directory,
|
|
32484
32941
|
flushedSessions,
|
|
32485
32942
|
lastHeuristicsTurnId,
|
|
32486
|
-
experimentalUserMemories: deps.config.experimental?.user_memories?.enabled
|
|
32943
|
+
experimentalUserMemories: deps.config.experimental?.user_memories?.enabled,
|
|
32944
|
+
experimentalPinKeyFiles: deps.config.experimental?.pin_key_files?.enabled ?? false,
|
|
32945
|
+
experimentalPinKeyFilesTokenBudget: deps.config.experimental?.pin_key_files?.token_budget
|
|
32487
32946
|
});
|
|
32488
32947
|
const eventHook = createEventHook({
|
|
32489
32948
|
eventHandler,
|
|
@@ -32962,15 +33421,17 @@ Historian reads these notes, deduplicates them, and rewrites the remaining usefu
|
|
|
32962
33421
|
import { tool as tool3 } from "@opencode-ai/plugin";
|
|
32963
33422
|
function formatNoteLine(note) {
|
|
32964
33423
|
const statusSuffix = note.status === "active" ? "" : ` (${note.status})`;
|
|
32965
|
-
const dismissHint = note.status === "dismissed" ? "" : ` _(dismiss with \`ctx_note(action="dismiss", note_id=${note.id})\`)_`;
|
|
32966
33424
|
if (note.type === "session") {
|
|
32967
|
-
return `- **#${note.id}**${statusSuffix}: ${note.content}
|
|
33425
|
+
return `- **#${note.id}**${statusSuffix}: ${note.content}`;
|
|
32968
33426
|
}
|
|
32969
33427
|
const conditionText = note.status === "ready" ? note.readyReason ?? note.surfaceCondition ?? "Condition satisfied" : note.surfaceCondition ?? "No condition recorded";
|
|
32970
33428
|
const conditionLabel = note.status === "ready" ? "Condition met" : "Condition";
|
|
32971
33429
|
return `- **#${note.id}**${statusSuffix}: ${note.content}
|
|
32972
|
-
${conditionLabel}: ${conditionText}
|
|
33430
|
+
${conditionLabel}: ${conditionText}`;
|
|
32973
33431
|
}
|
|
33432
|
+
var DISMISS_FOOTER = `
|
|
33433
|
+
|
|
33434
|
+
To dismiss a stale note: ctx_note(action="dismiss", note_id=N)`;
|
|
32974
33435
|
function buildReadSections(args) {
|
|
32975
33436
|
if (args.filter === undefined) {
|
|
32976
33437
|
const sessionNotes2 = getSessionNotes(args.db, args.sessionId);
|
|
@@ -33109,7 +33570,7 @@ No session notes or smart notes.`;
|
|
|
33109
33570
|
}
|
|
33110
33571
|
return sections.join(`
|
|
33111
33572
|
|
|
33112
|
-
`);
|
|
33573
|
+
`) + DISMISS_FOOTER;
|
|
33113
33574
|
}
|
|
33114
33575
|
});
|
|
33115
33576
|
}
|
|
@@ -33880,6 +34341,11 @@ var plugin = async (ctx) => {
|
|
|
33880
34341
|
experimentalUserMemories: pluginConfig.experimental?.user_memories?.enabled ? {
|
|
33881
34342
|
enabled: true,
|
|
33882
34343
|
promotionThreshold: pluginConfig.experimental.user_memories?.promotion_threshold
|
|
34344
|
+
} : undefined,
|
|
34345
|
+
experimentalPinKeyFiles: pluginConfig.experimental?.pin_key_files?.enabled ? {
|
|
34346
|
+
enabled: true,
|
|
34347
|
+
token_budget: pluginConfig.experimental.pin_key_files?.token_budget,
|
|
34348
|
+
min_reads: pluginConfig.experimental.pin_key_files?.min_reads
|
|
33883
34349
|
} : undefined
|
|
33884
34350
|
});
|
|
33885
34351
|
startTuiActionConsumer({
|
|
@@ -17,5 +17,10 @@ export declare function startDreamScheduleTimer(args: {
|
|
|
17
17
|
enabled: boolean;
|
|
18
18
|
promotionThreshold: number;
|
|
19
19
|
};
|
|
20
|
+
experimentalPinKeyFiles?: {
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
token_budget: number;
|
|
23
|
+
min_reads: number;
|
|
24
|
+
};
|
|
20
25
|
}): (() => void) | undefined;
|
|
21
26
|
//# sourceMappingURL=dream-timer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dream-timer.d.ts","sourceRoot":"","sources":["../../src/plugin/dream-timer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAMrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAK7C;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB,wBAAwB,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"dream-timer.d.ts","sourceRoot":"","sources":["../../src/plugin/dream-timer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAMrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAK7C;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB,wBAAwB,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,uBAAuB,CAAC,EAAE;QACtB,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC;CACL,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAuE3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-session-hooks.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/create-session-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAU7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;CAC1C;;;;;;
|
|
1
|
+
{"version":3,"file":"create-session-hooks.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/create-session-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAU7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;CAC1C;;;;;;qBA4Cq4B,CAAC;;;;;;;;;;;;qBATv3B,CAAN;mBAAiB,CAAC;;;;;0BASwvY,CAAC;;;;;;EADpxY"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-note/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAchE,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,QAAQ,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-note/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAchE,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,QAAQ,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAgND,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAIxF"}
|
package/package.json
CHANGED
|
@@ -272,7 +272,7 @@ export function loadSidebarSnapshot(sessionId: string, directory: string): Sideb
|
|
|
272
272
|
for (const c of compRows) {
|
|
273
273
|
compartmentTokens += Math.ceil(
|
|
274
274
|
`<compartment start="${c.start_message}" end="${c.end_message}" title="${c.title}">\n${c.content}\n</compartment>\n`
|
|
275
|
-
.length /
|
|
275
|
+
.length / 3.5,
|
|
276
276
|
);
|
|
277
277
|
}
|
|
278
278
|
} catch {
|
|
@@ -285,7 +285,7 @@ export function loadSidebarSnapshot(sessionId: string, directory: string): Sideb
|
|
|
285
285
|
)
|
|
286
286
|
.all(sessionId);
|
|
287
287
|
for (const f of factRows) {
|
|
288
|
-
factTokens += Math.ceil(`* ${f.content}\n`.length /
|
|
288
|
+
factTokens += Math.ceil(`* ${f.content}\n`.length / 3.5);
|
|
289
289
|
}
|
|
290
290
|
} catch {
|
|
291
291
|
/* session_facts table may not exist */
|
|
@@ -294,7 +294,7 @@ export function loadSidebarSnapshot(sessionId: string, directory: string): Sideb
|
|
|
294
294
|
if (meta) {
|
|
295
295
|
const cached = (meta as Record<string, unknown>).memory_block_cache;
|
|
296
296
|
if (typeof cached === "string" && cached.length > 0) {
|
|
297
|
-
memoryTokens = Math.ceil(cached.length /
|
|
297
|
+
memoryTokens = Math.ceil(cached.length / 3.5);
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
300
|
|
|
@@ -514,14 +514,14 @@ export function loadStatusDetail(
|
|
|
514
514
|
|
|
515
515
|
let histTokens = 0;
|
|
516
516
|
for (const c of compartments) {
|
|
517
|
-
// ~
|
|
517
|
+
// ~3.5 chars per token estimate (matches plugin's estimateTokens)
|
|
518
518
|
histTokens += Math.ceil(
|
|
519
519
|
`<compartment start="${c.start_message}" end="${c.end_message}" title="${c.title}">\n${c.content}\n</compartment>\n`
|
|
520
|
-
.length /
|
|
520
|
+
.length / 3.5,
|
|
521
521
|
);
|
|
522
522
|
}
|
|
523
523
|
for (const f of facts) {
|
|
524
|
-
histTokens += Math.ceil(`* ${f.content}\n`.length /
|
|
524
|
+
histTokens += Math.ceil(`* ${f.content}\n`.length / 3.5);
|
|
525
525
|
}
|
|
526
526
|
detail.historyBlockTokens = histTokens;
|
|
527
527
|
|