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
package/src/shared/rpc.ts CHANGED
@@ -1,145 +1,145 @@
1
- import { Rpc } from "@opencode/plugin/rpc"
2
-
3
- import type { SummaryBlock } from "./blocks.ts"
4
- import type { CacheSample } from "./cache.ts"
5
- import type { CompressionSettings } from "./settings.ts"
6
-
7
- const SettingsGetInputJson = {
8
- type: "object",
9
- properties: { sessionID: { type: "string" } },
10
- additionalProperties: false,
11
- } as const
12
-
13
- const SettingsProperties = {
14
- contextLimit: {
15
- anyOf: [{ type: "string", enum: ["auto"] }, { type: "number" }],
16
- },
17
- triggerPercent: { type: "number" },
18
- nudgeGrowthTokens: { type: "number" },
19
- summaryBlockPercent: { type: "number" },
20
- summaryTotalPercent: { type: "number" },
21
- summaryLanguage: { type: "string", enum: ["auto", "zh", "en"] },
22
- summaryFormat: { type: "string", enum: ["json", "markdown", "babel"] },
23
- autoCompress: { type: "boolean" },
24
- enableCompressTool: { type: "boolean" },
25
- enableDecompressTool: { type: "boolean" },
26
- showTimeline: { type: "boolean" },
27
- showBlockTokens: { type: "boolean" },
28
- decompressInlineMax: { type: "number" },
29
- decompressTempCap: { type: "number" },
30
- decompressShowTokens: { type: "boolean" },
31
- } as const
32
-
33
- const SettingsInputJson = {
34
- type: "object",
35
- properties: SettingsProperties,
36
- required: ["contextLimit", "triggerPercent"],
37
- additionalProperties: false,
38
- } as const
39
-
40
- /** 读取结果比写入多一个 resolvedWindow:auto 时从模型原生窗口解析出来的值。 */
41
- const SettingsOutputJson = {
42
- type: "object",
43
- properties: {
44
- ...SettingsProperties,
45
- resolvedWindow: { type: "number" },
46
- },
47
- required: ["contextLimit", "triggerPercent"],
48
- additionalProperties: false,
49
- } as const
50
-
51
- const OkJson = {
52
- type: "object",
53
- properties: { ok: { type: "boolean" } },
54
- required: ["ok"],
55
- additionalProperties: false,
56
- } as const
57
-
58
- /** 需要明确指定会话的只读查询。 */
59
- const SessionInputJson = {
60
- type: "object",
61
- properties: { sessionID: { type: "string" } },
62
- required: ["sessionID"],
63
- additionalProperties: false,
64
- } as const
65
-
66
- /** 摘要块:服务端返回 active 链,body 是渲染好的 markdown。 */
67
- const BlockJson = {
68
- type: "object",
69
- properties: {
70
- id: { type: "string" },
71
- tier: { type: "number", enum: [1, 2, 3] },
72
- format: { type: "string", enum: ["json", "markdown", "babel"] },
73
- title: { type: "string" },
74
- at: { type: "number" },
75
- tokensBefore: { type: "number" },
76
- tokensAfter: { type: "number" },
77
- sourceBlockIds: { type: "array", items: { type: "string" } },
78
- body: { type: "string" },
79
- },
80
- required: ["id", "tier", "format", "title", "at", "tokensBefore", "tokensAfter", "body"],
81
- additionalProperties: false,
82
- } as const
83
-
84
- const BlocksOutputJson = {
85
- type: "object",
86
- properties: { blocks: { type: "array", items: BlockJson } },
87
- required: ["blocks"],
88
- additionalProperties: false,
89
- } as const
90
-
91
- /** 一条缓存命中样本。 */
92
- const CacheSampleJson = {
93
- type: "object",
94
- properties: {
95
- messageID: { type: "string" },
96
- at: { type: "number" },
97
- input: { type: "number" },
98
- output: { type: "number" },
99
- cached: { type: "number" },
100
- hitRate: { type: "number" },
101
- },
102
- required: ["messageID", "at", "input", "output", "cached", "hitRate"],
103
- additionalProperties: false,
104
- } as const
105
-
106
- const CacheHistoryOutputJson = {
107
- type: "object",
108
- properties: { samples: { type: "array", items: CacheSampleJson } },
109
- required: ["samples"],
110
- additionalProperties: false,
111
- } as const
112
-
113
- /** TUI 与服务端共用的设置 / 面板 RPC。 */
114
- export const ContextRpc: Rpc.PortableDefinition = Rpc.define({
115
- id: "compressed-context",
116
- methods: {
117
- settingsGet: { input: SettingsGetInputJson, output: SettingsOutputJson },
118
- settingsSet: { input: SettingsInputJson, output: OkJson },
119
- blocksGet: { input: SessionInputJson, output: BlocksOutputJson },
120
- cacheHistoryGet: { input: SessionInputJson, output: CacheHistoryOutputJson },
121
- },
122
- events: {},
123
- })
124
-
125
- /** 服务端设置读取结果。 */
126
- export interface ContextSettingsResult extends CompressionSettings {
127
- readonly resolvedWindow?: number
128
- }
129
-
130
- /** TUI 侧对 ContextRpc 的类型化视图。 */
131
- export interface ContextRpcClient {
132
- settingsGet(input: { readonly sessionID?: string }): Promise<ContextSettingsResult>
133
- settingsSet(input: CompressionSettings): Promise<{ readonly ok: boolean }>
134
- blocksGet(input: { readonly sessionID: string }): Promise<{ readonly blocks: readonly SummaryBlock[] }>
135
- cacheHistoryGet(input: {
136
- readonly sessionID: string
137
- }): Promise<{ readonly samples: readonly CacheSample[] }>
138
- }
139
-
140
- /** 输入:带 rpc 方法的 TUI client;输出:类型化 RPC 客户端。 */
141
- export function contextRpc(client: {
142
- rpc(definition: Rpc.PortableDefinition): unknown
143
- }): ContextRpcClient {
144
- return client.rpc(ContextRpc) as ContextRpcClient
145
- }
1
+ import { Rpc } from "@opencode/plugin/rpc"
2
+
3
+ import type { SummaryBlock } from "./blocks.ts"
4
+ import type { CacheSample } from "./cache.ts"
5
+ import type { CompressionSettings } from "./settings.ts"
6
+
7
+ const SettingsGetInputJson = {
8
+ type: "object",
9
+ properties: { sessionID: { type: "string" } },
10
+ additionalProperties: false,
11
+ } as const
12
+
13
+ const SettingsProperties = {
14
+ contextLimit: {
15
+ anyOf: [{ type: "string", enum: ["auto"] }, { type: "number" }],
16
+ },
17
+ triggerPercent: { type: "number" },
18
+ nudgeGrowthTokens: { type: "number" },
19
+ summaryBlockPercent: { type: "number" },
20
+ summaryTotalPercent: { type: "number" },
21
+ summaryLanguage: { type: "string", enum: ["auto", "zh", "en"] },
22
+ summaryFormat: { type: "string", enum: ["json", "markdown", "babel"] },
23
+ autoCompress: { type: "boolean" },
24
+ enableCompressTool: { type: "boolean" },
25
+ enableDecompressTool: { type: "boolean" },
26
+ showTimeline: { type: "boolean" },
27
+ showBlockTokens: { type: "boolean" },
28
+ decompressInlineMax: { type: "number" },
29
+ decompressTempCap: { type: "number" },
30
+ decompressShowTokens: { type: "boolean" },
31
+ } as const
32
+
33
+ const SettingsInputJson = {
34
+ type: "object",
35
+ properties: SettingsProperties,
36
+ required: ["contextLimit", "triggerPercent"],
37
+ additionalProperties: false,
38
+ } as const
39
+
40
+ /** 读取结果比写入多一个 resolvedWindow:auto 时从模型原生窗口解析出来的值。 */
41
+ const SettingsOutputJson = {
42
+ type: "object",
43
+ properties: {
44
+ ...SettingsProperties,
45
+ resolvedWindow: { type: "number" },
46
+ },
47
+ required: ["contextLimit", "triggerPercent"],
48
+ additionalProperties: false,
49
+ } as const
50
+
51
+ const OkJson = {
52
+ type: "object",
53
+ properties: { ok: { type: "boolean" } },
54
+ required: ["ok"],
55
+ additionalProperties: false,
56
+ } as const
57
+
58
+ /** 需要明确指定会话的只读查询。 */
59
+ const SessionInputJson = {
60
+ type: "object",
61
+ properties: { sessionID: { type: "string" } },
62
+ required: ["sessionID"],
63
+ additionalProperties: false,
64
+ } as const
65
+
66
+ /** 摘要块:服务端返回 active 链,body 是渲染好的 markdown。 */
67
+ const BlockJson = {
68
+ type: "object",
69
+ properties: {
70
+ id: { type: "string" },
71
+ tier: { type: "number", enum: [1, 2, 3] },
72
+ format: { type: "string", enum: ["json", "markdown", "babel"] },
73
+ title: { type: "string" },
74
+ at: { type: "number" },
75
+ tokensBefore: { type: "number" },
76
+ tokensAfter: { type: "number" },
77
+ sourceBlockIds: { type: "array", items: { type: "string" } },
78
+ body: { type: "string" },
79
+ },
80
+ required: ["id", "tier", "format", "title", "at", "tokensBefore", "tokensAfter", "body"],
81
+ additionalProperties: false,
82
+ } as const
83
+
84
+ const BlocksOutputJson = {
85
+ type: "object",
86
+ properties: { blocks: { type: "array", items: BlockJson } },
87
+ required: ["blocks"],
88
+ additionalProperties: false,
89
+ } as const
90
+
91
+ /** 一条缓存命中样本。 */
92
+ const CacheSampleJson = {
93
+ type: "object",
94
+ properties: {
95
+ messageID: { type: "string" },
96
+ at: { type: "number" },
97
+ input: { type: "number" },
98
+ output: { type: "number" },
99
+ cached: { type: "number" },
100
+ hitRate: { type: "number" },
101
+ },
102
+ required: ["messageID", "at", "input", "output", "cached", "hitRate"],
103
+ additionalProperties: false,
104
+ } as const
105
+
106
+ const CacheHistoryOutputJson = {
107
+ type: "object",
108
+ properties: { samples: { type: "array", items: CacheSampleJson } },
109
+ required: ["samples"],
110
+ additionalProperties: false,
111
+ } as const
112
+
113
+ /** TUI 与服务端共用的设置 / 面板 RPC。 */
114
+ export const ContextRpc: Rpc.PortableDefinition = Rpc.define({
115
+ id: "compressed-context",
116
+ methods: {
117
+ settingsGet: { input: SettingsGetInputJson, output: SettingsOutputJson },
118
+ settingsSet: { input: SettingsInputJson, output: OkJson },
119
+ blocksGet: { input: SessionInputJson, output: BlocksOutputJson },
120
+ cacheHistoryGet: { input: SessionInputJson, output: CacheHistoryOutputJson },
121
+ },
122
+ events: {},
123
+ })
124
+
125
+ /** 服务端设置读取结果。 */
126
+ export interface ContextSettingsResult extends CompressionSettings {
127
+ readonly resolvedWindow?: number
128
+ }
129
+
130
+ /** TUI 侧对 ContextRpc 的类型化视图。 */
131
+ export interface ContextRpcClient {
132
+ settingsGet(input: { readonly sessionID?: string }): Promise<ContextSettingsResult>
133
+ settingsSet(input: CompressionSettings): Promise<{ readonly ok: boolean }>
134
+ blocksGet(input: { readonly sessionID: string }): Promise<{ readonly blocks: readonly SummaryBlock[] }>
135
+ cacheHistoryGet(input: {
136
+ readonly sessionID: string
137
+ }): Promise<{ readonly samples: readonly CacheSample[] }>
138
+ }
139
+
140
+ /** 输入:带 rpc 方法的 TUI client;输出:类型化 RPC 客户端。 */
141
+ export function contextRpc(client: {
142
+ rpc(definition: Rpc.PortableDefinition): unknown
143
+ }): ContextRpcClient {
144
+ return client.rpc(ContextRpc) as ContextRpcClient
145
+ }
@@ -1,32 +1,32 @@
1
- /**
2
- * 输入:具备 scan 能力的 storage + 前缀 + 每条目的处理函数。
3
- * 输出:无。
4
- * 预期:按 next 游标分页遍历全部匹配条目,逐条串行 await,避免一次性把 key 全读进内存。
5
- */
6
- export interface ScanStorageLike {
7
- readonly scan?: (options: { prefix: string; limit: number; after?: string }) => Promise<{
8
- entries: readonly { key: string; value: unknown }[]
9
- next?: string
10
- }>
11
- }
12
-
13
- /** 输入:storage + 前缀 + 访问函数 + 每页条数;输出:无;预期:storage 无 scan 时直接返回。 */
14
- export async function forEachScannedEntry(
15
- storage: ScanStorageLike,
16
- prefix: string,
17
- visit: (entry: { key: string; value: unknown }) => Promise<void>,
18
- limit = 100,
19
- ): Promise<void> {
20
- if (storage.scan === undefined) return
21
- let after: string | undefined
22
- for (;;) {
23
- const page = await storage.scan({
24
- prefix,
25
- limit,
26
- ...(after === undefined ? {} : { after }),
27
- })
28
- for (const entry of page.entries) await visit(entry)
29
- if (page.next === undefined) return
30
- after = page.next
31
- }
32
- }
1
+ /**
2
+ * 输入:具备 scan 能力的 storage + 前缀 + 每条目的处理函数。
3
+ * 输出:无。
4
+ * 预期:按 next 游标分页遍历全部匹配条目,逐条串行 await,避免一次性把 key 全读进内存。
5
+ */
6
+ export interface ScanStorageLike {
7
+ readonly scan?: (options: { prefix: string; limit: number; after?: string }) => Promise<{
8
+ entries: readonly { key: string; value: unknown }[]
9
+ next?: string
10
+ }>
11
+ }
12
+
13
+ /** 输入:storage + 前缀 + 访问函数 + 每页条数;输出:无;预期:storage 无 scan 时直接返回。 */
14
+ export async function forEachScannedEntry(
15
+ storage: ScanStorageLike,
16
+ prefix: string,
17
+ visit: (entry: { key: string; value: unknown }) => Promise<void>,
18
+ limit = 100,
19
+ ): Promise<void> {
20
+ if (storage.scan === undefined) return
21
+ let after: string | undefined
22
+ for (;;) {
23
+ const page = await storage.scan({
24
+ prefix,
25
+ limit,
26
+ ...(after === undefined ? {} : { after }),
27
+ })
28
+ for (const entry of page.entries) await visit(entry)
29
+ if (page.next === undefined) return
30
+ after = page.next
31
+ }
32
+ }