compressed-context 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +59 -51
  2. package/package.json +64 -64
  3. package/src/compression/active-summary-cache.ts +50 -50
  4. package/src/compression/adopt.ts +57 -57
  5. package/src/compression/auto.ts +386 -372
  6. package/src/compression/babel.ts +85 -85
  7. package/src/compression/block.ts +25 -25
  8. package/src/compression/cache-history.ts +75 -75
  9. package/src/compression/compaction.ts +189 -189
  10. package/src/compression/decompress-tool.ts +74 -74
  11. package/src/compression/decompress.ts +292 -292
  12. package/src/compression/deleted-sessions.ts +24 -24
  13. package/src/compression/distill.ts +220 -220
  14. package/src/compression/events.ts +275 -275
  15. package/src/compression/markdown.ts +53 -53
  16. package/src/compression/normalize.ts +114 -114
  17. package/src/compression/render.ts +70 -70
  18. package/src/compression/schema.ts +131 -84
  19. package/src/compression/select.ts +123 -123
  20. package/src/compression/session-message.ts +112 -112
  21. package/src/compression/settings-rpc.ts +123 -111
  22. package/src/compression/settings.ts +175 -175
  23. package/src/compression/shape.ts +75 -0
  24. package/src/compression/state.ts +248 -248
  25. package/src/compression/summarize.ts +534 -595
  26. package/src/compression/summary.ts +73 -73
  27. package/src/compression/tool.ts +184 -142
  28. package/src/compression/transcript-store.ts +258 -258
  29. package/src/compression/transcript.ts +63 -63
  30. package/src/compression/validate.ts +81 -81
  31. package/src/i18n/en.ts +93 -93
  32. package/src/i18n/index.ts +28 -28
  33. package/src/i18n/types.ts +89 -89
  34. package/src/i18n/zh.ts +93 -93
  35. package/src/index.ts +116 -108
  36. package/src/shared/blocks.ts +17 -17
  37. package/src/shared/cache.ts +199 -199
  38. package/src/shared/format.ts +23 -23
  39. package/src/shared/media.ts +184 -184
  40. package/src/shared/parse.ts +25 -25
  41. package/src/shared/parts.ts +72 -72
  42. package/src/shared/rpc.ts +145 -145
  43. package/src/shared/scan.ts +32 -32
  44. package/src/shared/settings.ts +466 -471
  45. package/src/shared/stats.ts +142 -142
  46. package/src/shared/tokens.ts +259 -259
  47. package/src/tui/chart/cache-chart.ts +237 -237
  48. package/src/tui/chart/color.ts +58 -58
  49. package/src/tui/index.tsx +109 -111
  50. package/src/tui/panel/cache.tsx +203 -203
  51. package/src/tui/panel/data.ts +105 -105
  52. package/src/tui/panel/index.tsx +176 -176
  53. package/src/tui/panel/summaries.tsx +203 -192
  54. package/src/tui/settings/dialogs.tsx +215 -215
  55. package/src/tui/settings/options.ts +238 -238
  56. package/src/tui/settings.tsx +418 -418
  57. package/src/tui/types.ts +4 -4
@@ -1,238 +1,238 @@
1
- import type { DialogSelectOption } from "@opencode/plugin/tui/context"
2
-
3
- import { formatTokens } from "../../shared/format.ts"
4
- import type { Messages } from "../../i18n/index.ts"
5
- import {
6
- effectiveDecompressInlineMax,
7
- effectiveDecompressTempCap,
8
- effectiveSummaryBlockPercent,
9
- effectiveSummaryLanguage,
10
- effectiveSummaryTotalPercent,
11
- isContextLimit,
12
- percentToChars,
13
- type Settings,
14
- } from "../../shared/settings.ts"
15
-
16
- /** 输入:设置;输出:当前语言标签;预期:用于设置菜单右侧的当前值。 */
17
- export function localeLabel(settings: Settings, copy: Messages): string {
18
- if (settings.locale === "auto") return copy.settings.auto
19
- if (settings.locale === "zh") return copy.languages.zh
20
- return copy.languages.en
21
- }
22
-
23
- /** 输入:设置;输出:当前摘要语言标签。 */
24
- export function summaryLanguageLabel(settings: Settings, copy: Messages): string {
25
- const language = effectiveSummaryLanguage(settings)
26
- if (language === "zh") return copy.languages.zh
27
- if (language === "en") return copy.languages.en
28
- return copy.settings.auto
29
- }
30
-
31
- /** 输入:设置 + 已知窗口;输出:上下文上限标签;数字设置是上限,被模型原生窗口压低时显示箭头。 */
32
- export function limitLabel(settings: Settings, copy: Messages, window: number | undefined): string {
33
- const value: unknown = settings.contextLimit
34
- if (!isContextLimit(value) || value === "auto") {
35
- return window === undefined ? copy.settings.limitAuto : `${copy.settings.limitAuto} (${formatTokens(window)})`
36
- }
37
- if (window !== undefined && window < value) {
38
- return copy.settings.limitCapped(formatTokens(value), formatTokens(window))
39
- }
40
- return formatTokens(value)
41
- }
42
-
43
- /** 输入:百分比 + 窗口;输出:`10% ≈ 20k` 这样的标签。 */
44
- export function percentLabel(percent: number, window: number | undefined): string {
45
- const chars = percentToChars(percent, window)
46
- return chars === undefined
47
- ? `${percent.toString()}%`
48
- : `${percent.toString()}% ≈ ${formatTokens(chars)}`
49
- }
50
-
51
- /** 输入:设置;输出:主动压缩提醒间隔标签;0 显示为关闭。 */
52
- export function nudgeLabel(settings: Settings, copy: Messages): string {
53
- return settings.nudgeGrowthTokens === 0 ? copy.settings.off : formatTokens(settings.nudgeGrowthTokens)
54
- }
55
-
56
- /** 输入:设置;输出:当前摘要格式标签。 */
57
- export function summaryFormatLabel(settings: Settings, copy: Messages): string {
58
- if (settings.summaryFormat === "babel") return copy.settings.summaryFormatBabel
59
- return settings.summaryFormat === "markdown"
60
- ? copy.settings.summaryFormatMarkdown
61
- : copy.settings.summaryFormatJson
62
- }
63
-
64
- /** 设置菜单里所有可选 action;options.ts 与 settings.tsx 共用。 */
65
- export const SETTINGS_ACTIONS = [
66
- "limit",
67
- "threshold",
68
- "nudge",
69
- "autoCompress",
70
- "enableCompressTool",
71
- "enableDecompressTool",
72
- "blockPercent",
73
- "totalPercent",
74
- "summaryLanguage",
75
- "summaryFormat",
76
- "showTimeline",
77
- "showBlockTokens",
78
- "show",
79
- "showCacheChart",
80
- "showCacheLog",
81
- "showSummaries",
82
- "decompressInlineMax",
83
- "decompressTempCap",
84
- "decompressShowTokens",
85
- "language",
86
- ] as const
87
-
88
- export type SettingsAction = (typeof SETTINGS_ACTIONS)[number]
89
-
90
- /** 设置菜单里可切换的布尔项。 */
91
- export type ToggleSetting = Extract<
92
- SettingsAction,
93
- | "autoCompress"
94
- | "enableCompressTool"
95
- | "enableDecompressTool"
96
- | "showTimeline"
97
- | "showBlockTokens"
98
- | "showCacheChart"
99
- | "showCacheLog"
100
- | "showSummaries"
101
- | "decompressShowTokens"
102
- >
103
-
104
- /**
105
- * 输入:当前设置 + 文案 + 已解析窗口。
106
- * 输出:按「压缩 / 摘要 / 面板 / 解压 / 界面」分组的设置菜单项。
107
- * 预期:纯函数,方便单测;dialog 会按 category 渲染分组标题。
108
- */
109
- export function buildSettingsOptions(input: {
110
- readonly settings: Settings
111
- readonly copy: Messages
112
- readonly window: number | undefined
113
- }): readonly DialogSelectOption<SettingsAction>[] {
114
- const { settings, copy, window } = input
115
- const onOff = (value: boolean): string => (value ? copy.settings.on : copy.settings.off)
116
- return [
117
- {
118
- title: copy.settings.limit,
119
- value: "limit",
120
- footer: limitLabel(settings, copy, window),
121
- category: copy.settings.categories.compress,
122
- },
123
- {
124
- title: copy.settings.threshold,
125
- value: "threshold",
126
- footer: `${settings.triggerPercent.toString()}%`,
127
- category: copy.settings.categories.compress,
128
- },
129
- {
130
- title: copy.settings.nudgeGrowth,
131
- value: "nudge",
132
- footer: nudgeLabel(settings, copy),
133
- category: copy.settings.categories.compress,
134
- },
135
- {
136
- title: copy.settings.autoCompress,
137
- value: "autoCompress",
138
- footer: onOff(settings.autoCompress),
139
- category: copy.settings.categories.compress,
140
- },
141
- {
142
- title: copy.settings.enableCompressTool,
143
- value: "enableCompressTool",
144
- footer: onOff(settings.enableCompressTool),
145
- category: copy.settings.categories.compress,
146
- },
147
- {
148
- title: copy.settings.enableDecompressTool,
149
- value: "enableDecompressTool",
150
- footer: onOff(settings.enableDecompressTool),
151
- category: copy.settings.categories.compress,
152
- },
153
- {
154
- title: copy.settings.summaryBlockPercent,
155
- value: "blockPercent",
156
- footer: percentLabel(effectiveSummaryBlockPercent(settings), window),
157
- category: copy.settings.categories.summary,
158
- },
159
- {
160
- title: copy.settings.summaryTotalPercent,
161
- value: "totalPercent",
162
- footer: percentLabel(effectiveSummaryTotalPercent(settings), window),
163
- category: copy.settings.categories.summary,
164
- },
165
- {
166
- title: copy.settings.summaryLanguage,
167
- value: "summaryLanguage",
168
- footer: summaryLanguageLabel(settings, copy),
169
- category: copy.settings.categories.summary,
170
- },
171
- {
172
- title: copy.settings.summaryFormat,
173
- value: "summaryFormat",
174
- footer: summaryFormatLabel(settings, copy),
175
- category: copy.settings.categories.summary,
176
- },
177
- {
178
- title: copy.settings.showTimeline,
179
- value: "showTimeline",
180
- footer: onOff(settings.showTimeline),
181
- category: copy.settings.categories.summary,
182
- },
183
- {
184
- title: copy.settings.showBlockTokens,
185
- value: "showBlockTokens",
186
- footer: onOff(settings.showBlockTokens),
187
- category: copy.settings.categories.summary,
188
- },
189
- {
190
- title: copy.settings.show,
191
- value: "show",
192
- footer: onOff(settings.enabled),
193
- category: copy.settings.categories.panel,
194
- },
195
- {
196
- title: copy.settings.showCacheChart,
197
- value: "showCacheChart",
198
- footer: onOff(settings.showCacheChart),
199
- category: copy.settings.categories.panel,
200
- },
201
- {
202
- title: copy.settings.showCacheLog,
203
- value: "showCacheLog",
204
- footer: onOff(settings.showCacheLog),
205
- category: copy.settings.categories.panel,
206
- },
207
- {
208
- title: copy.settings.showSummaries,
209
- value: "showSummaries",
210
- footer: onOff(settings.showSummaries),
211
- category: copy.settings.categories.panel,
212
- },
213
- {
214
- title: copy.settings.decompressInlineMax,
215
- value: "decompressInlineMax",
216
- footer: formatTokens(effectiveDecompressInlineMax(settings)),
217
- category: copy.settings.categories.decompress,
218
- },
219
- {
220
- title: copy.settings.decompressTempCap,
221
- value: "decompressTempCap",
222
- footer: effectiveDecompressTempCap(settings).toString(),
223
- category: copy.settings.categories.decompress,
224
- },
225
- {
226
- title: copy.settings.decompressShowTokens,
227
- value: "decompressShowTokens",
228
- footer: onOff(settings.decompressShowTokens),
229
- category: copy.settings.categories.decompress,
230
- },
231
- {
232
- title: copy.settings.language,
233
- value: "language",
234
- footer: localeLabel(settings, copy),
235
- category: copy.settings.categories.interface,
236
- },
237
- ]
238
- }
1
+ import type { DialogSelectOption } from "@opencode/plugin/tui/context"
2
+
3
+ import { formatTokens } from "../../shared/format.ts"
4
+ import type { Messages } from "../../i18n/index.ts"
5
+ import {
6
+ effectiveDecompressInlineMax,
7
+ effectiveDecompressTempCap,
8
+ effectiveSummaryBlockPercent,
9
+ effectiveSummaryLanguage,
10
+ effectiveSummaryTotalPercent,
11
+ isContextLimit,
12
+ percentToChars,
13
+ type Settings,
14
+ } from "../../shared/settings.ts"
15
+
16
+ /** 输入:设置;输出:当前语言标签;预期:用于设置菜单右侧的当前值。 */
17
+ export function localeLabel(settings: Settings, copy: Messages): string {
18
+ if (settings.locale === "auto") return copy.settings.auto
19
+ if (settings.locale === "zh") return copy.languages.zh
20
+ return copy.languages.en
21
+ }
22
+
23
+ /** 输入:设置;输出:当前摘要语言标签。 */
24
+ export function summaryLanguageLabel(settings: Settings, copy: Messages): string {
25
+ const language = effectiveSummaryLanguage(settings)
26
+ if (language === "zh") return copy.languages.zh
27
+ if (language === "en") return copy.languages.en
28
+ return copy.settings.auto
29
+ }
30
+
31
+ /** 输入:设置 + 已知窗口;输出:上下文上限标签;数字设置是上限,被模型原生窗口压低时显示箭头。 */
32
+ export function limitLabel(settings: Settings, copy: Messages, window: number | undefined): string {
33
+ const value: unknown = settings.contextLimit
34
+ if (!isContextLimit(value) || value === "auto") {
35
+ return window === undefined ? copy.settings.limitAuto : `${copy.settings.limitAuto} (${formatTokens(window)})`
36
+ }
37
+ if (window !== undefined && window < value) {
38
+ return copy.settings.limitCapped(formatTokens(value), formatTokens(window))
39
+ }
40
+ return formatTokens(value)
41
+ }
42
+
43
+ /** 输入:百分比 + 窗口;输出:`10% ≈ 20k` 这样的标签。 */
44
+ export function percentLabel(percent: number, window: number | undefined): string {
45
+ const chars = percentToChars(percent, window)
46
+ return chars === undefined
47
+ ? `${percent.toString()}%`
48
+ : `${percent.toString()}% ≈ ${formatTokens(chars)}`
49
+ }
50
+
51
+ /** 输入:设置;输出:主动压缩提醒间隔标签;0 显示为关闭。 */
52
+ export function nudgeLabel(settings: Settings, copy: Messages): string {
53
+ return settings.nudgeGrowthTokens === 0 ? copy.settings.off : formatTokens(settings.nudgeGrowthTokens)
54
+ }
55
+
56
+ /** 输入:设置;输出:当前摘要格式标签。 */
57
+ export function summaryFormatLabel(settings: Settings, copy: Messages): string {
58
+ if (settings.summaryFormat === "babel") return copy.settings.summaryFormatBabel
59
+ return settings.summaryFormat === "markdown"
60
+ ? copy.settings.summaryFormatMarkdown
61
+ : copy.settings.summaryFormatJson
62
+ }
63
+
64
+ /** 设置菜单里所有可选 action;options.ts 与 settings.tsx 共用。 */
65
+ export const SETTINGS_ACTIONS = [
66
+ "limit",
67
+ "threshold",
68
+ "nudge",
69
+ "autoCompress",
70
+ "enableCompressTool",
71
+ "enableDecompressTool",
72
+ "blockPercent",
73
+ "totalPercent",
74
+ "summaryLanguage",
75
+ "summaryFormat",
76
+ "showTimeline",
77
+ "showBlockTokens",
78
+ "show",
79
+ "showCacheChart",
80
+ "showCacheLog",
81
+ "showSummaries",
82
+ "decompressInlineMax",
83
+ "decompressTempCap",
84
+ "decompressShowTokens",
85
+ "language",
86
+ ] as const
87
+
88
+ export type SettingsAction = (typeof SETTINGS_ACTIONS)[number]
89
+
90
+ /** 设置菜单里可切换的布尔项。 */
91
+ export type ToggleSetting = Extract<
92
+ SettingsAction,
93
+ | "autoCompress"
94
+ | "enableCompressTool"
95
+ | "enableDecompressTool"
96
+ | "showTimeline"
97
+ | "showBlockTokens"
98
+ | "showCacheChart"
99
+ | "showCacheLog"
100
+ | "showSummaries"
101
+ | "decompressShowTokens"
102
+ >
103
+
104
+ /**
105
+ * 输入:当前设置 + 文案 + 已解析窗口。
106
+ * 输出:按「压缩 / 摘要 / 面板 / 解压 / 界面」分组的设置菜单项。
107
+ * 预期:纯函数,方便单测;dialog 会按 category 渲染分组标题。
108
+ */
109
+ export function buildSettingsOptions(input: {
110
+ readonly settings: Settings
111
+ readonly copy: Messages
112
+ readonly window: number | undefined
113
+ }): readonly DialogSelectOption<SettingsAction>[] {
114
+ const { settings, copy, window } = input
115
+ const onOff = (value: boolean): string => (value ? copy.settings.on : copy.settings.off)
116
+ return [
117
+ {
118
+ title: copy.settings.limit,
119
+ value: "limit",
120
+ footer: limitLabel(settings, copy, window),
121
+ category: copy.settings.categories.compress,
122
+ },
123
+ {
124
+ title: copy.settings.threshold,
125
+ value: "threshold",
126
+ footer: `${settings.triggerPercent.toString()}%`,
127
+ category: copy.settings.categories.compress,
128
+ },
129
+ {
130
+ title: copy.settings.nudgeGrowth,
131
+ value: "nudge",
132
+ footer: nudgeLabel(settings, copy),
133
+ category: copy.settings.categories.compress,
134
+ },
135
+ {
136
+ title: copy.settings.autoCompress,
137
+ value: "autoCompress",
138
+ footer: onOff(settings.autoCompress),
139
+ category: copy.settings.categories.compress,
140
+ },
141
+ {
142
+ title: copy.settings.enableCompressTool,
143
+ value: "enableCompressTool",
144
+ footer: onOff(settings.enableCompressTool),
145
+ category: copy.settings.categories.compress,
146
+ },
147
+ {
148
+ title: copy.settings.enableDecompressTool,
149
+ value: "enableDecompressTool",
150
+ footer: onOff(settings.enableDecompressTool),
151
+ category: copy.settings.categories.compress,
152
+ },
153
+ {
154
+ title: copy.settings.summaryBlockPercent,
155
+ value: "blockPercent",
156
+ footer: percentLabel(effectiveSummaryBlockPercent(settings), window),
157
+ category: copy.settings.categories.summary,
158
+ },
159
+ {
160
+ title: copy.settings.summaryTotalPercent,
161
+ value: "totalPercent",
162
+ footer: percentLabel(effectiveSummaryTotalPercent(settings), window),
163
+ category: copy.settings.categories.summary,
164
+ },
165
+ {
166
+ title: copy.settings.summaryLanguage,
167
+ value: "summaryLanguage",
168
+ footer: summaryLanguageLabel(settings, copy),
169
+ category: copy.settings.categories.summary,
170
+ },
171
+ {
172
+ title: copy.settings.summaryFormat,
173
+ value: "summaryFormat",
174
+ footer: summaryFormatLabel(settings, copy),
175
+ category: copy.settings.categories.summary,
176
+ },
177
+ {
178
+ title: copy.settings.showTimeline,
179
+ value: "showTimeline",
180
+ footer: onOff(settings.showTimeline),
181
+ category: copy.settings.categories.summary,
182
+ },
183
+ {
184
+ title: copy.settings.showBlockTokens,
185
+ value: "showBlockTokens",
186
+ footer: onOff(settings.showBlockTokens),
187
+ category: copy.settings.categories.summary,
188
+ },
189
+ {
190
+ title: copy.settings.show,
191
+ value: "show",
192
+ footer: onOff(settings.enabled),
193
+ category: copy.settings.categories.panel,
194
+ },
195
+ {
196
+ title: copy.settings.showCacheChart,
197
+ value: "showCacheChart",
198
+ footer: onOff(settings.showCacheChart),
199
+ category: copy.settings.categories.panel,
200
+ },
201
+ {
202
+ title: copy.settings.showCacheLog,
203
+ value: "showCacheLog",
204
+ footer: onOff(settings.showCacheLog),
205
+ category: copy.settings.categories.panel,
206
+ },
207
+ {
208
+ title: copy.settings.showSummaries,
209
+ value: "showSummaries",
210
+ footer: onOff(settings.showSummaries),
211
+ category: copy.settings.categories.panel,
212
+ },
213
+ {
214
+ title: copy.settings.decompressInlineMax,
215
+ value: "decompressInlineMax",
216
+ footer: formatTokens(effectiveDecompressInlineMax(settings)),
217
+ category: copy.settings.categories.decompress,
218
+ },
219
+ {
220
+ title: copy.settings.decompressTempCap,
221
+ value: "decompressTempCap",
222
+ footer: effectiveDecompressTempCap(settings).toString(),
223
+ category: copy.settings.categories.decompress,
224
+ },
225
+ {
226
+ title: copy.settings.decompressShowTokens,
227
+ value: "decompressShowTokens",
228
+ footer: onOff(settings.decompressShowTokens),
229
+ category: copy.settings.categories.decompress,
230
+ },
231
+ {
232
+ title: copy.settings.language,
233
+ value: "language",
234
+ footer: localeLabel(settings, copy),
235
+ category: copy.settings.categories.interface,
236
+ },
237
+ ]
238
+ }