@cortexkit/opencode-magic-context 0.31.4 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +2 -0
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +9 -0
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-async.d.ts +2 -1
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- package/dist/features/magic-context/storage-clone.d.ts +34 -0
- package/dist/features/magic-context/storage-clone.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +11 -0
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +2 -1
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/tagger.d.ts +10 -0
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/hooks/magic-context/apply-operations.d.ts +24 -0
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +7 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/decay-render.d.ts +2 -0
- package/dist/hooks/magic-context/decay-render.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +3 -0
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +7 -9
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/m0-token-breakdown.d.ts +5 -4
- package/dist/hooks/magic-context/m0-token-breakdown.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts +2 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +2 -2
- package/dist/hooks/magic-context/read-session-raw.d.ts +8 -0
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/shadow-sender.d.ts +262 -0
- package/dist/hooks/magic-context/shadow-sender.d.ts.map +1 -0
- package/dist/hooks/magic-context/tag-content-primitives.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/temporal-awareness.d.ts +3 -3
- package/dist/hooks/magic-context/transform-operations.d.ts +1 -1
- package/dist/hooks/magic-context/transform-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +5 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +4 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/index.js +1665 -140
- package/dist/plugin/hooks/create-session-hooks.d.ts +48 -175
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/tag-transcript.d.ts +18 -0
- package/dist/shared/tag-transcript.d.ts.map +1 -1
- package/dist/tools/ctx-expand/constants.d.ts +1 -1
- package/dist/tools/ctx-expand/constants.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/shared/rpc-server.ts +8 -0
- package/src/shared/tag-transcript.test.ts +253 -7
- package/src/shared/tag-transcript.ts +422 -114
|
@@ -10,47 +10,59 @@ import type { PluginContext } from "../types";
|
|
|
10
10
|
*/
|
|
11
11
|
export declare function buildMagicContextHookConfig(pluginConfig: MagicContextPluginConfig): {
|
|
12
12
|
protected_tags: number;
|
|
13
|
-
cache_ttl: string | {
|
|
14
|
-
[modelKey: string]: string;
|
|
15
|
-
default: string;
|
|
16
|
-
};
|
|
17
|
-
clear_reasoning_age: number;
|
|
18
|
-
toast_duration_ms: number | undefined;
|
|
19
13
|
execute_threshold_percentage: number | {
|
|
20
14
|
[modelKey: string]: number;
|
|
21
15
|
default: number;
|
|
22
16
|
};
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
disabled_hooks?: string[];
|
|
18
|
+
command?: Record<string, {
|
|
19
|
+
template: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
agent?: string;
|
|
22
|
+
model?: string;
|
|
23
|
+
subtask?: boolean;
|
|
24
|
+
}>;
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
auto_update?: boolean;
|
|
27
|
+
language?: string;
|
|
28
|
+
historian?: import("../../config/schema").HistorianConfig;
|
|
29
|
+
dreamer?: import("../../config/schema").DreamerConfig;
|
|
30
|
+
cache_ttl: string | {
|
|
31
|
+
default: string;
|
|
32
|
+
[modelKey: string]: string;
|
|
33
|
+
};
|
|
34
|
+
toast_duration_ms?: number;
|
|
35
|
+
execute_threshold_tokens?: {
|
|
25
36
|
default?: number;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
disallowed_tools: ("*" | "read" | "aft_outline" | "aft_zoom" | "aft_search")[];
|
|
30
|
-
model?: string | undefined;
|
|
31
|
-
temperature?: number | undefined;
|
|
32
|
-
top_p?: number | undefined;
|
|
33
|
-
prompt?: string | undefined;
|
|
34
|
-
tools?: Record<string, boolean> | undefined;
|
|
35
|
-
disable?: boolean | undefined;
|
|
36
|
-
description?: string | undefined;
|
|
37
|
-
mode?: "subagent" | "primary" | "all" | undefined;
|
|
38
|
-
color?: string | undefined;
|
|
39
|
-
maxSteps?: number | undefined;
|
|
40
|
-
permission?: {
|
|
41
|
-
edit?: "deny" | "allow" | "ask" | undefined;
|
|
42
|
-
bash?: "deny" | "allow" | "ask" | Record<string, "deny" | "allow" | "ask"> | undefined;
|
|
43
|
-
webfetch?: "deny" | "allow" | "ask" | undefined;
|
|
44
|
-
doom_loop?: "deny" | "allow" | "ask" | undefined;
|
|
45
|
-
external_directory?: "deny" | "allow" | "ask" | undefined;
|
|
46
|
-
} | undefined;
|
|
47
|
-
maxTokens?: number | undefined;
|
|
48
|
-
variant?: string | undefined;
|
|
49
|
-
fallback_models?: string | string[] | undefined;
|
|
50
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
51
|
-
} | undefined;
|
|
37
|
+
[modelKey: string]: number | undefined;
|
|
38
|
+
};
|
|
39
|
+
clear_reasoning_age: number;
|
|
52
40
|
history_budget_percentage: number;
|
|
53
41
|
historian_timeout_ms: number;
|
|
42
|
+
commit_cluster_trigger: {
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
min_clusters: number;
|
|
45
|
+
};
|
|
46
|
+
sqlite: {
|
|
47
|
+
cache_size_mb: number;
|
|
48
|
+
mmap_size_mb: number;
|
|
49
|
+
};
|
|
50
|
+
system_prompt_injection: {
|
|
51
|
+
enabled: boolean;
|
|
52
|
+
skip_signatures: string[];
|
|
53
|
+
};
|
|
54
|
+
temporal_awareness: boolean;
|
|
55
|
+
keep_subagents: boolean;
|
|
56
|
+
todowrite: {
|
|
57
|
+
enabled: boolean;
|
|
58
|
+
overlay: boolean;
|
|
59
|
+
};
|
|
60
|
+
smart_drops: boolean;
|
|
61
|
+
caveman_text_compression: {
|
|
62
|
+
enabled: boolean;
|
|
63
|
+
min_chars: number;
|
|
64
|
+
};
|
|
65
|
+
embedding: import("../../config/schema").EmbeddingConfig;
|
|
54
66
|
memory: {
|
|
55
67
|
enabled: boolean;
|
|
56
68
|
injection_budget_tokens: number;
|
|
@@ -67,149 +79,10 @@ export declare function buildMagicContextHookConfig(pluginConfig: MagicContextPl
|
|
|
67
79
|
max_commits: number;
|
|
68
80
|
};
|
|
69
81
|
};
|
|
70
|
-
|
|
71
|
-
timeout_ms: number;
|
|
72
|
-
model?: string | undefined;
|
|
73
|
-
temperature?: number | undefined;
|
|
74
|
-
top_p?: number | undefined;
|
|
75
|
-
prompt?: string | undefined;
|
|
76
|
-
tools?: Record<string, boolean> | undefined;
|
|
77
|
-
disable?: boolean | undefined;
|
|
78
|
-
description?: string | undefined;
|
|
79
|
-
mode?: "subagent" | "primary" | "all" | undefined;
|
|
80
|
-
color?: string | undefined;
|
|
81
|
-
maxSteps?: number | undefined;
|
|
82
|
-
permission?: {
|
|
83
|
-
edit?: "deny" | "allow" | "ask" | undefined;
|
|
84
|
-
bash?: "deny" | "allow" | "ask" | Record<string, "deny" | "allow" | "ask"> | undefined;
|
|
85
|
-
webfetch?: "deny" | "allow" | "ask" | undefined;
|
|
86
|
-
doom_loop?: "deny" | "allow" | "ask" | undefined;
|
|
87
|
-
external_directory?: "deny" | "allow" | "ask" | undefined;
|
|
88
|
-
} | undefined;
|
|
89
|
-
maxTokens?: number | undefined;
|
|
90
|
-
variant?: string | undefined;
|
|
91
|
-
fallback_models?: string | string[] | undefined;
|
|
92
|
-
system_prompt?: string | undefined;
|
|
93
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
94
|
-
} | undefined;
|
|
95
|
-
dreamer: {
|
|
96
|
-
tasks: {
|
|
97
|
-
"map-memories": {
|
|
98
|
-
schedule: string;
|
|
99
|
-
timeout_minutes: number;
|
|
100
|
-
model?: string | undefined;
|
|
101
|
-
fallback_models?: string | string[] | undefined;
|
|
102
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
103
|
-
};
|
|
104
|
-
verify: {
|
|
105
|
-
schedule: string;
|
|
106
|
-
timeout_minutes: number;
|
|
107
|
-
model?: string | undefined;
|
|
108
|
-
fallback_models?: string | string[] | undefined;
|
|
109
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
110
|
-
};
|
|
111
|
-
"verify-broad": {
|
|
112
|
-
schedule: string;
|
|
113
|
-
timeout_minutes: number;
|
|
114
|
-
model?: string | undefined;
|
|
115
|
-
fallback_models?: string | string[] | undefined;
|
|
116
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
117
|
-
};
|
|
118
|
-
curate: {
|
|
119
|
-
schedule: string;
|
|
120
|
-
timeout_minutes: number;
|
|
121
|
-
model?: string | undefined;
|
|
122
|
-
fallback_models?: string | string[] | undefined;
|
|
123
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
124
|
-
};
|
|
125
|
-
"classify-memories": {
|
|
126
|
-
schedule: string;
|
|
127
|
-
timeout_minutes: number;
|
|
128
|
-
model?: string | undefined;
|
|
129
|
-
fallback_models?: string | string[] | undefined;
|
|
130
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
131
|
-
};
|
|
132
|
-
retrospective: {
|
|
133
|
-
schedule: string;
|
|
134
|
-
timeout_minutes: number;
|
|
135
|
-
model?: string | undefined;
|
|
136
|
-
fallback_models?: string | string[] | undefined;
|
|
137
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
138
|
-
};
|
|
139
|
-
"maintain-docs": {
|
|
140
|
-
schedule: string;
|
|
141
|
-
timeout_minutes: number;
|
|
142
|
-
model?: string | undefined;
|
|
143
|
-
fallback_models?: string | string[] | undefined;
|
|
144
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
145
|
-
};
|
|
146
|
-
"evaluate-smart-notes": {
|
|
147
|
-
schedule: string;
|
|
148
|
-
timeout_minutes: number;
|
|
149
|
-
model?: string | undefined;
|
|
150
|
-
fallback_models?: string | string[] | undefined;
|
|
151
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
152
|
-
};
|
|
153
|
-
"review-user-memories": {
|
|
154
|
-
schedule: string;
|
|
155
|
-
timeout_minutes: number;
|
|
156
|
-
model?: string | undefined;
|
|
157
|
-
fallback_models?: string | string[] | undefined;
|
|
158
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
159
|
-
promotion_threshold?: number | undefined;
|
|
160
|
-
};
|
|
161
|
-
"promote-primers": {
|
|
162
|
-
schedule: string;
|
|
163
|
-
timeout_minutes: number;
|
|
164
|
-
model?: string | undefined;
|
|
165
|
-
fallback_models?: string | string[] | undefined;
|
|
166
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
167
|
-
promotion_threshold?: number | undefined;
|
|
168
|
-
};
|
|
169
|
-
"refresh-primers": {
|
|
170
|
-
schedule: string;
|
|
171
|
-
timeout_minutes: number;
|
|
172
|
-
model?: string | undefined;
|
|
173
|
-
fallback_models?: string | string[] | undefined;
|
|
174
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
175
|
-
};
|
|
176
|
-
};
|
|
177
|
-
inject_docs: boolean;
|
|
178
|
-
model?: string | undefined;
|
|
179
|
-
temperature?: number | undefined;
|
|
180
|
-
top_p?: number | undefined;
|
|
181
|
-
prompt?: string | undefined;
|
|
182
|
-
tools?: Record<string, boolean> | undefined;
|
|
183
|
-
disable?: boolean | undefined;
|
|
184
|
-
description?: string | undefined;
|
|
185
|
-
mode?: "subagent" | "primary" | "all" | undefined;
|
|
186
|
-
color?: string | undefined;
|
|
187
|
-
maxSteps?: number | undefined;
|
|
188
|
-
permission?: {
|
|
189
|
-
edit?: "deny" | "allow" | "ask" | undefined;
|
|
190
|
-
bash?: "deny" | "allow" | "ask" | Record<string, "deny" | "allow" | "ask"> | undefined;
|
|
191
|
-
webfetch?: "deny" | "allow" | "ask" | undefined;
|
|
192
|
-
doom_loop?: "deny" | "allow" | "ask" | undefined;
|
|
193
|
-
external_directory?: "deny" | "allow" | "ask" | undefined;
|
|
194
|
-
} | undefined;
|
|
195
|
-
maxTokens?: number | undefined;
|
|
196
|
-
variant?: string | undefined;
|
|
197
|
-
fallback_models?: string | string[] | undefined;
|
|
198
|
-
thinking_level?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
|
|
199
|
-
} | undefined;
|
|
200
|
-
commit_cluster_trigger: {
|
|
201
|
-
enabled: boolean;
|
|
202
|
-
min_clusters: number;
|
|
203
|
-
};
|
|
204
|
-
system_prompt_injection: {
|
|
82
|
+
shadow_transform: {
|
|
205
83
|
enabled: boolean;
|
|
206
|
-
skip_signatures: string[];
|
|
207
|
-
};
|
|
208
|
-
temporal_awareness: boolean;
|
|
209
|
-
caveman_text_compression: {
|
|
210
|
-
enabled: boolean;
|
|
211
|
-
min_chars: number;
|
|
212
84
|
};
|
|
85
|
+
sidekick?: import("../../config/schema").SidekickConfig;
|
|
213
86
|
};
|
|
214
87
|
export declare function createSessionHooks(args: {
|
|
215
88
|
ctx: PluginContext;
|
|
@@ -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;AAO7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,wBAAwB
|
|
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;AAO7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,wBAAwB;;;;;;;;;mBACxE,CAAC;aAA2B,CAAC;aAA2B,CAAC;eACjD,CAAC;;;;;;;;;;;;;eA8Cgja,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAjCnka;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;CACtC;;;;;;qBA2B+wL,CAAC;;;;;;;;;;;;qBAAxxD,CAAC;mBAAyB,CAAC;iBAAuB,CAAC;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAA+trC,CAAC;;;;;;EADp0zC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-server.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-server.ts"],"names":[],"mappings":"AAqBA,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AA0CxF;;;;;;;;;;;GAWG;AACH,qBAAa,qBAAqB;IAC9B,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkC;IAC7D,oEAAoE;IACpE,OAAO,CAAC,OAAO,CAAsC;IAMrD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;gBAE7C,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAKjD,sCAAsC;IACtC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAIjD,6DAA6D;IACvD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"rpc-server.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-server.ts"],"names":[],"mappings":"AAqBA,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AA0CxF;;;;;;;;;;;GAWG;AACH,qBAAa,qBAAqB;IAC9B,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkC;IAC7D,oEAAoE;IACpE,OAAO,CAAC,OAAO,CAAsC;IAMrD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;gBAE7C,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAKjD,sCAAsC;IACtC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAIjD,6DAA6D;IACvD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IA6F9B,6EAA6E;IAC7E,IAAI,IAAI,IAAI;IAuBZ,OAAO,CAAC,uBAAuB;IAgB/B;+CAC2C;YAC7B,WAAW;IAyDzB;8EAC0E;IAC1E,OAAO,CAAC,eAAe;CA+F1B"}
|
|
@@ -66,6 +66,24 @@ export interface TagTranscriptOptions {
|
|
|
66
66
|
* contentId) since all parts of a message share one fingerprint.
|
|
67
67
|
*/
|
|
68
68
|
entryFingerprintByMessageId?: ReadonlyMap<string, string>;
|
|
69
|
+
/**
|
|
70
|
+
* Stable Pi message ids observed on a prior pass. Their immutable parts may
|
|
71
|
+
* reuse tag assignments while this pass still reapplies visible prefixes and
|
|
72
|
+
* rebuilds the complete set of messages affected by each tag.
|
|
73
|
+
*/
|
|
74
|
+
reuseMessageIds?: ReadonlySet<string>;
|
|
75
|
+
/** Exact text/count pairs retained by Pi for safe lazy-token backfill reuse. */
|
|
76
|
+
textTokenCache?: Map<string, {
|
|
77
|
+
text: string;
|
|
78
|
+
tokenCount: number;
|
|
79
|
+
}>;
|
|
80
|
+
/** Exact tool-result text/count pairs retained under composite tag identity. */
|
|
81
|
+
toolTokenCache?: Map<string, {
|
|
82
|
+
text: string;
|
|
83
|
+
tokenCount: number;
|
|
84
|
+
}>;
|
|
85
|
+
/** Optional process-local benchmark callback; production callers omit it. */
|
|
86
|
+
onTiming?: (phase: "identity" | "prefix" | "targets" | "tokenCounting", elapsedMs: number) => void;
|
|
69
87
|
}
|
|
70
88
|
export interface TagTranscriptResult {
|
|
71
89
|
targets: Map<number, TagTarget>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tag-transcript.d.ts","sourceRoot":"","sources":["../../src/shared/tag-transcript.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAQzE,OAAO,EAAwB,KAAK,MAAM,EAAE,MAAM,kCAAkC,CAAC;AASrF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,cAAc,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACjC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;OAOG;IACH,2BAA2B,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"tag-transcript.d.ts","sourceRoot":"","sources":["../../src/shared/tag-transcript.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAQzE,OAAO,EAAwB,KAAK,MAAM,EAAE,MAAM,kCAAkC,CAAC;AASrF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,cAAc,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACjC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;OAOG;IACH,2BAA2B,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D;;;;OAIG;IACH,eAAe,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,gFAAgF;IAChF,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,gFAAgF;IAChF,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,CACP,KAAK,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,eAAe,EAC1D,SAAS,EAAE,MAAM,KAChB,IAAI,CAAC;CACb;AAED,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACnC;AAuED,wBAAgB,aAAa,CACzB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,eAAe,EACnB,OAAO,GAAE,oBAAyB,GACnC,mBAAmB,CA2VrB"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const CTX_EXPAND_DESCRIPTION = "Recover the original conversation from your compacted history.\n\nOlder parts of this session are summarized
|
|
1
|
+
export declare const CTX_EXPAND_DESCRIPTION = "Recover the original conversation from your compacted history.\n\nOlder parts of this session are summarized under `## start-end \u00B7 date \u00B7 title` headings inside <session-history> \u2014 e.g. `## 120-245 \u00B7 \u2026 \u00B7 Fixed tagger collision`. Each heading replaces the raw messages in that ordinal range with a summary. When the summary isn't enough \u2014 you need exact wording, a specific value, an error message, or the reasoning behind a decision \u2014 expand the range:\n\nctx_expand(start=120, end=245) \u2190 the heading's start/end range\n\nReturns the raw transcript as [N] U:/A: lines, capped at ~15K tokens; an oversized range returns the head and tells you where to continue. Also works with ordinals from ctx_search message results \u2014 expand a window around a hit (e.g. start=N-10, end=N+5). Ranges after the last compartment are your live tail \u2014 already visible in context, not expandable.\n\nTwo recovery modes for finer detail:\n- ctx_expand(start=120, end=245, verbose=true) \u2014 lists each message SEPARATELY with its ordinal [N] and a per-part preview (each tool call shown with its output size). Use this to find the exact message or tool call you want, then recover it in full by ordinal.\n- ctx_expand(message=138) \u2014 returns the FULL untruncated content of the message at that ordinal: every text part, and every tool call's complete input + output, read from stored history. This is the cheap way to get back a tool output you dropped with ctx_reduce \u2014 the original is still in storage even though the wire shows [dropped \u00A7N\u00A7]. If the message was deleted from history (session prune/revert), it says so.";
|
|
2
2
|
export declare const CTX_EXPAND_TOKEN_BUDGET = 15000;
|
|
3
3
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-expand/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-expand/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,ipDAU6X,CAAC;AAEja,eAAO,MAAM,uBAAuB,QAAS,CAAC"}
|
package/package.json
CHANGED
package/src/shared/rpc-server.ts
CHANGED
|
@@ -102,6 +102,14 @@ export class MagicContextRpcServer {
|
|
|
102
102
|
|
|
103
103
|
/** Start the server on a random port, write port to disk. */
|
|
104
104
|
async start(): Promise<number> {
|
|
105
|
+
if (typeof Bun === "undefined") {
|
|
106
|
+
// The only RPC consumer is the terminal-TUI sidebar, which exists only
|
|
107
|
+
// under the Bun runtime (OpenCode CLI). On Node/Electron (Desktop) there
|
|
108
|
+
// is no consumer, and Bun.serve would throw — skip cleanly instead of
|
|
109
|
+
// logging a misleading boot error.
|
|
110
|
+
log("rpc server skipped: Bun runtime not available (no TUI consumer)");
|
|
111
|
+
return 0;
|
|
112
|
+
}
|
|
105
113
|
this.startedAt = Date.now();
|
|
106
114
|
const self = this;
|
|
107
115
|
const server = Bun.serve<WsData>({
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/// <reference types="bun-types" />
|
|
2
2
|
|
|
3
3
|
import { describe, expect, it } from "bun:test";
|
|
4
|
+
import { runMigrations } from "../features/magic-context/migrations";
|
|
4
5
|
import type { ContextDatabase } from "../features/magic-context/storage";
|
|
5
|
-
import
|
|
6
|
+
import { initializeDatabase } from "../features/magic-context/storage-db";
|
|
7
|
+
import type { Tagger, ToolTagAccounting } from "../features/magic-context/tagger";
|
|
8
|
+
import { createTagger } from "../features/magic-context/tagger";
|
|
9
|
+
import { Database } from "./sqlite";
|
|
6
10
|
import { tagTranscript } from "./tag-transcript";
|
|
7
11
|
import type { Transcript, TranscriptPart, TranscriptPartKind } from "./transcript";
|
|
8
12
|
|
|
@@ -11,6 +15,7 @@ class FakeTagger implements Tagger {
|
|
|
11
15
|
private toolTags = new Map<string, number>();
|
|
12
16
|
readonly owners: string[] = [];
|
|
13
17
|
readonly byteSizes = new Map<number, number>();
|
|
18
|
+
private readonly toolAccounting = new Map<number, ToolTagAccounting>();
|
|
14
19
|
|
|
15
20
|
assignTag(): number {
|
|
16
21
|
return this.nextTag++;
|
|
@@ -40,6 +45,23 @@ class FakeTagger implements Tagger {
|
|
|
40
45
|
return this.toolTags.get(`${ownerMsgId}\0${callId}`);
|
|
41
46
|
}
|
|
42
47
|
|
|
48
|
+
getToolTagAccounting(
|
|
49
|
+
_sessionId: string,
|
|
50
|
+
callId: string,
|
|
51
|
+
ownerMsgId: string,
|
|
52
|
+
): ToolTagAccounting | undefined {
|
|
53
|
+
const tag = this.getToolTag(_sessionId, callId, ownerMsgId);
|
|
54
|
+
return tag === undefined ? undefined : this.toolAccounting.get(tag);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
setToolTagAccounting(
|
|
58
|
+
_sessionId: string,
|
|
59
|
+
tagNumber: number,
|
|
60
|
+
accounting: ToolTagAccounting,
|
|
61
|
+
): void {
|
|
62
|
+
this.toolAccounting.set(tagNumber, accounting);
|
|
63
|
+
}
|
|
64
|
+
|
|
43
65
|
bindTag(): void {}
|
|
44
66
|
|
|
45
67
|
bindToolTag(_sessionId: string, callId: string, ownerMsgId: string, tagNumber: number): void {
|
|
@@ -123,18 +145,31 @@ class NonTextToolResultPart extends TestPart {
|
|
|
123
145
|
class FakeDb {
|
|
124
146
|
readonly byteSizeUpdates: Array<{ byteSize: number; sessionId: string; tagNumber: number }> =
|
|
125
147
|
[];
|
|
148
|
+
readonly tokenCountUpdates: Array<{
|
|
149
|
+
sessionId: string;
|
|
150
|
+
tagNumber: number;
|
|
151
|
+
tokenCount: number;
|
|
152
|
+
}> = [];
|
|
126
153
|
|
|
127
154
|
prepare(sql: string): { run: (...args: unknown[]) => void } {
|
|
128
155
|
return {
|
|
129
156
|
run: (...args: unknown[]) => {
|
|
130
|
-
|
|
131
|
-
const [byteSize, sessionId, tagNumber] = args;
|
|
157
|
+
const [value, sessionId, tagNumber] = args;
|
|
132
158
|
if (
|
|
133
|
-
typeof
|
|
134
|
-
typeof sessionId
|
|
135
|
-
typeof tagNumber
|
|
159
|
+
typeof value !== "number" ||
|
|
160
|
+
typeof sessionId !== "string" ||
|
|
161
|
+
typeof tagNumber !== "number"
|
|
136
162
|
) {
|
|
137
|
-
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (sql.startsWith("UPDATE tags SET byte_size =")) {
|
|
166
|
+
this.byteSizeUpdates.push({ byteSize: value, sessionId, tagNumber });
|
|
167
|
+
} else if (sql.startsWith("UPDATE tags SET token_count =")) {
|
|
168
|
+
this.tokenCountUpdates.push({
|
|
169
|
+
sessionId,
|
|
170
|
+
tagNumber,
|
|
171
|
+
tokenCount: value,
|
|
172
|
+
});
|
|
138
173
|
}
|
|
139
174
|
},
|
|
140
175
|
};
|
|
@@ -271,6 +306,217 @@ describe("tagTranscript tool aggregation", () => {
|
|
|
271
306
|
expect(result.getText()).toBe(`[dropped §${nearestTag}§]`);
|
|
272
307
|
});
|
|
273
308
|
|
|
309
|
+
it("reuses owner-scoped identities without collapsing duplicate callIds", () => {
|
|
310
|
+
const tagger = new FakeTagger();
|
|
311
|
+
const seedDb = new FakeDb();
|
|
312
|
+
const seedTranscript: Transcript = {
|
|
313
|
+
harness: "pi",
|
|
314
|
+
messages: [
|
|
315
|
+
{
|
|
316
|
+
info: { id: "assistant-old", role: "assistant" },
|
|
317
|
+
parts: [new TestPart("tool_use", "duplicate-call", '{"turn":1}')],
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
info: { id: "user-old", role: "user" },
|
|
321
|
+
parts: [new TestPart("tool_result", "duplicate-call", "old result")],
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
info: { id: "assistant-new", role: "assistant" },
|
|
325
|
+
parts: [new TestPart("tool_use", "duplicate-call", '{"turn":2}')],
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
info: { id: "user-new", role: "user" },
|
|
329
|
+
parts: [new TestPart("tool_result", "duplicate-call", "new result")],
|
|
330
|
+
},
|
|
331
|
+
],
|
|
332
|
+
commit() {},
|
|
333
|
+
};
|
|
334
|
+
tagTranscript(
|
|
335
|
+
"session-duplicate-reuse",
|
|
336
|
+
seedTranscript,
|
|
337
|
+
tagger,
|
|
338
|
+
seedDb as unknown as ContextDatabase,
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
const reusedParts = {
|
|
342
|
+
oldUse: new TestPart("tool_use", "duplicate-call", '{"turn":1}'),
|
|
343
|
+
oldResult: new TestPart("tool_result", "duplicate-call", "old result"),
|
|
344
|
+
newUse: new TestPart("tool_use", "duplicate-call", '{"turn":2}'),
|
|
345
|
+
newResult: new TestPart("tool_result", "duplicate-call", "new result"),
|
|
346
|
+
};
|
|
347
|
+
const reusedTranscript: Transcript = {
|
|
348
|
+
harness: "pi",
|
|
349
|
+
messages: [
|
|
350
|
+
{
|
|
351
|
+
info: { id: "assistant-old", role: "assistant" },
|
|
352
|
+
parts: [reusedParts.oldUse],
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
info: { id: "user-old", role: "user" },
|
|
356
|
+
parts: [reusedParts.oldResult],
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
info: { id: "assistant-new", role: "assistant" },
|
|
360
|
+
parts: [reusedParts.newUse],
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
info: { id: "user-new", role: "user" },
|
|
364
|
+
parts: [reusedParts.newResult],
|
|
365
|
+
},
|
|
366
|
+
],
|
|
367
|
+
commit() {},
|
|
368
|
+
};
|
|
369
|
+
const reuseDb = new FakeDb();
|
|
370
|
+
const reused = tagTranscript(
|
|
371
|
+
"session-duplicate-reuse",
|
|
372
|
+
reusedTranscript,
|
|
373
|
+
tagger,
|
|
374
|
+
reuseDb as unknown as ContextDatabase,
|
|
375
|
+
{
|
|
376
|
+
reuseMessageIds: new Set([
|
|
377
|
+
"assistant-old",
|
|
378
|
+
"user-old",
|
|
379
|
+
"assistant-new",
|
|
380
|
+
"user-new",
|
|
381
|
+
]),
|
|
382
|
+
},
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
const oldTag = tagger.getToolTag(
|
|
386
|
+
"session-duplicate-reuse",
|
|
387
|
+
"duplicate-call",
|
|
388
|
+
"assistant-old",
|
|
389
|
+
);
|
|
390
|
+
const newTag = tagger.getToolTag(
|
|
391
|
+
"session-duplicate-reuse",
|
|
392
|
+
"duplicate-call",
|
|
393
|
+
"assistant-new",
|
|
394
|
+
);
|
|
395
|
+
expect(oldTag).toBeDefined();
|
|
396
|
+
expect(newTag).toBeDefined();
|
|
397
|
+
expect(oldTag).not.toBe(newTag);
|
|
398
|
+
expect(reused.targets.size).toBe(2);
|
|
399
|
+
expect(reusedParts.oldResult.getText()).toBe(`§${oldTag}§ old result`);
|
|
400
|
+
expect(reusedParts.newResult.getText()).toBe(`§${newTag}§ new result`);
|
|
401
|
+
expect(reuseDb.byteSizeUpdates).toEqual([]);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it("backfills a newly appended result after reusing its stable invocation", () => {
|
|
405
|
+
const tagger = new FakeTagger();
|
|
406
|
+
const callId = "late-result";
|
|
407
|
+
tagTranscript(
|
|
408
|
+
"session-late-result",
|
|
409
|
+
{
|
|
410
|
+
harness: "pi",
|
|
411
|
+
messages: [
|
|
412
|
+
{
|
|
413
|
+
info: { id: "assistant-owner", role: "assistant" },
|
|
414
|
+
parts: [new TestPart("tool_use", callId, '{"path":"a"}')],
|
|
415
|
+
},
|
|
416
|
+
],
|
|
417
|
+
commit() {},
|
|
418
|
+
},
|
|
419
|
+
tagger,
|
|
420
|
+
new FakeDb() as unknown as ContextDatabase,
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
const result = new TestPart("tool_result", callId, "late output");
|
|
424
|
+
const db = new FakeDb();
|
|
425
|
+
tagTranscript(
|
|
426
|
+
"session-late-result",
|
|
427
|
+
{
|
|
428
|
+
harness: "pi",
|
|
429
|
+
messages: [
|
|
430
|
+
{
|
|
431
|
+
info: { id: "assistant-owner", role: "assistant" },
|
|
432
|
+
parts: [new TestPart("tool_use", callId, '{"path":"a"}')],
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
info: { id: "user-result", role: "user" },
|
|
436
|
+
parts: [result],
|
|
437
|
+
},
|
|
438
|
+
],
|
|
439
|
+
commit() {},
|
|
440
|
+
},
|
|
441
|
+
tagger,
|
|
442
|
+
db as unknown as ContextDatabase,
|
|
443
|
+
{ reuseMessageIds: new Set(["assistant-owner"]) },
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
const tag = tagger.getToolTag("session-late-result", callId, "assistant-owner");
|
|
447
|
+
expect(result.getText()).toBe(`§${tag}§ late output`);
|
|
448
|
+
expect(db.byteSizeUpdates.some((update) => update.tagNumber === tag)).toBe(true);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it("persists the same grown folded-result accounting with reuse or full derivation", () => {
|
|
452
|
+
interface AccountingRow {
|
|
453
|
+
tagNumber: number;
|
|
454
|
+
byteSize: number;
|
|
455
|
+
tokenCount: number;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const runScenario = (reuse: boolean): { before: AccountingRow; after: AccountingRow } => {
|
|
459
|
+
const db = new Database(":memory:");
|
|
460
|
+
initializeDatabase(db);
|
|
461
|
+
runMigrations(db);
|
|
462
|
+
const sessionId = reuse ? "session-grown-reuse" : "session-grown-derive";
|
|
463
|
+
const tagger = createTagger();
|
|
464
|
+
tagger.initFromDb(sessionId, db);
|
|
465
|
+
const callId = "folded-growth";
|
|
466
|
+
const makeTranscript = (resultText: string): Transcript => ({
|
|
467
|
+
harness: "pi",
|
|
468
|
+
messages: [
|
|
469
|
+
{
|
|
470
|
+
info: { id: "assistant-owner", role: "assistant" },
|
|
471
|
+
parts: [new TestPart("tool_use", callId, '{"path":"a"}')],
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
// Pi folds the tool result into this following user entry, so
|
|
475
|
+
// reuse is decided from the user's stable id.
|
|
476
|
+
info: { id: "user-fold-target", role: "user" },
|
|
477
|
+
parts: [new TestPart("tool_result", callId, resultText)],
|
|
478
|
+
},
|
|
479
|
+
],
|
|
480
|
+
commit() {},
|
|
481
|
+
});
|
|
482
|
+
const readAccounting = (): AccountingRow => {
|
|
483
|
+
const row = db
|
|
484
|
+
.prepare(
|
|
485
|
+
"SELECT tag_number AS tagNumber, byte_size AS byteSize, token_count AS tokenCount FROM tags WHERE session_id = ? AND type = 'tool'",
|
|
486
|
+
)
|
|
487
|
+
.get(sessionId) as AccountingRow | null;
|
|
488
|
+
if (!row) throw new Error("missing tool accounting row");
|
|
489
|
+
return row;
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
tagTranscript(sessionId, makeTranscript("small result"), tagger, db);
|
|
493
|
+
const before = readAccounting();
|
|
494
|
+
const nextPassTagger = createTagger();
|
|
495
|
+
nextPassTagger.initFromDb(sessionId, db);
|
|
496
|
+
tagTranscript(
|
|
497
|
+
sessionId,
|
|
498
|
+
makeTranscript("larger result ".repeat(80)),
|
|
499
|
+
nextPassTagger,
|
|
500
|
+
db,
|
|
501
|
+
{
|
|
502
|
+
reuseMessageIds: reuse
|
|
503
|
+
? new Set(["assistant-owner", "user-fold-target"])
|
|
504
|
+
: undefined,
|
|
505
|
+
},
|
|
506
|
+
);
|
|
507
|
+
const after = readAccounting();
|
|
508
|
+
db.close();
|
|
509
|
+
return { before, after };
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
const reused = runScenario(true);
|
|
513
|
+
const derived = runScenario(false);
|
|
514
|
+
expect(reused.after.tagNumber).toBe(reused.before.tagNumber);
|
|
515
|
+
expect(reused.after.byteSize).toBeGreaterThan(reused.before.byteSize);
|
|
516
|
+
expect(reused.after.tokenCount).toBeGreaterThan(reused.before.tokenCount);
|
|
517
|
+
expect(reused.after).toEqual(derived.after);
|
|
518
|
+
});
|
|
519
|
+
|
|
274
520
|
it("accounts non-text tool_result content when ranking tool output byte size", () => {
|
|
275
521
|
const tagger = new FakeTagger();
|
|
276
522
|
const db = new FakeDb();
|