compressed-context 0.1.0 → 0.1.1

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 (55) hide show
  1. package/package.json +64 -64
  2. package/src/compression/active-summary-cache.ts +50 -50
  3. package/src/compression/adopt.ts +57 -57
  4. package/src/compression/auto.ts +372 -372
  5. package/src/compression/babel.ts +85 -85
  6. package/src/compression/block.ts +25 -25
  7. package/src/compression/cache-history.ts +75 -75
  8. package/src/compression/compaction.ts +189 -189
  9. package/src/compression/decompress-tool.ts +74 -74
  10. package/src/compression/decompress.ts +292 -292
  11. package/src/compression/deleted-sessions.ts +24 -24
  12. package/src/compression/distill.ts +220 -220
  13. package/src/compression/events.ts +275 -275
  14. package/src/compression/markdown.ts +53 -53
  15. package/src/compression/normalize.ts +114 -114
  16. package/src/compression/render.ts +70 -70
  17. package/src/compression/schema.ts +84 -84
  18. package/src/compression/select.ts +123 -123
  19. package/src/compression/session-message.ts +112 -112
  20. package/src/compression/settings-rpc.ts +111 -111
  21. package/src/compression/settings.ts +175 -175
  22. package/src/compression/state.ts +248 -248
  23. package/src/compression/summarize.ts +595 -595
  24. package/src/compression/summary.ts +73 -73
  25. package/src/compression/tool.ts +142 -142
  26. package/src/compression/transcript-store.ts +258 -258
  27. package/src/compression/transcript.ts +63 -63
  28. package/src/compression/validate.ts +81 -81
  29. package/src/i18n/en.ts +93 -93
  30. package/src/i18n/index.ts +28 -28
  31. package/src/i18n/types.ts +89 -89
  32. package/src/i18n/zh.ts +93 -93
  33. package/src/index.ts +108 -108
  34. package/src/shared/blocks.ts +17 -17
  35. package/src/shared/cache.ts +199 -199
  36. package/src/shared/format.ts +23 -23
  37. package/src/shared/media.ts +184 -184
  38. package/src/shared/parse.ts +25 -25
  39. package/src/shared/parts.ts +72 -72
  40. package/src/shared/rpc.ts +145 -145
  41. package/src/shared/scan.ts +32 -32
  42. package/src/shared/settings.ts +471 -471
  43. package/src/shared/stats.ts +142 -142
  44. package/src/shared/tokens.ts +259 -259
  45. package/src/tui/chart/cache-chart.ts +237 -237
  46. package/src/tui/chart/color.ts +58 -58
  47. package/src/tui/index.tsx +111 -111
  48. package/src/tui/panel/cache.tsx +203 -203
  49. package/src/tui/panel/data.ts +105 -105
  50. package/src/tui/panel/index.tsx +176 -176
  51. package/src/tui/panel/summaries.tsx +192 -192
  52. package/src/tui/settings/dialogs.tsx +215 -215
  53. package/src/tui/settings/options.ts +238 -238
  54. package/src/tui/settings.tsx +418 -418
  55. 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
+ }