pi-blackhole 0.4.2 → 0.4.3
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 +15 -0
- package/dist/index.js +11660 -0
- package/dist/index.js.map +1 -0
- package/example-config.json +1 -1
- package/index.ts +37 -63
- package/package.json +21 -9
- package/src/commands/cleanup.ts +279 -240
- package/src/commands/memory.ts +236 -184
- package/src/commands/pi-vcc.ts +202 -152
- package/src/commands/vcc-recall.ts +126 -95
- package/src/core/brief.ts +167 -33
- package/src/core/build-sections.ts +8 -2
- package/src/core/config-env.ts +117 -0
- package/src/core/content.ts +31 -7
- package/src/core/drill-down.ts +41 -11
- package/src/core/filter-noise.ts +9 -3
- package/src/core/format-recall.ts +15 -6
- package/src/core/format.ts +14 -4
- package/src/core/lineage.ts +9 -3
- package/src/core/load-messages.ts +24 -5
- package/src/core/normalize.ts +38 -14
- package/src/core/recall-scope.ts +11 -3
- package/src/core/render-entries.ts +22 -6
- package/src/core/sanitize.ts +5 -1
- package/src/core/search-entries.ts +111 -19
- package/src/core/settings.ts +1 -3
- package/src/core/summarize.ts +42 -21
- package/src/core/unified-config.ts +549 -411
- package/src/extract/commits.ts +4 -2
- package/src/extract/files.ts +10 -5
- package/src/extract/goals.ts +7 -2
- package/src/hooks/before-compact.ts +210 -88
- package/src/om/agents/dropper/agent.ts +380 -265
- package/src/om/agents/dropper/coverage.ts +102 -82
- package/src/om/agents/observer/agent.ts +242 -206
- package/src/om/agents/reflector/agent.ts +212 -153
- package/src/om/cleanup.ts +239 -218
- package/src/om/clipboard.ts +59 -51
- package/src/om/compaction-trigger.ts +448 -333
- package/src/om/config.ts +13 -6
- package/src/om/configure-overlay.ts +518 -355
- package/src/om/consolidation.ts +1460 -953
- package/src/om/cooldown.ts +75 -65
- package/src/om/debug-log.ts +86 -68
- package/src/om/ids.ts +1 -1
- package/src/om/ledger/fold.ts +89 -78
- package/src/om/ledger/progress.ts +181 -153
- package/src/om/ledger/projection.ts +248 -185
- package/src/om/ledger/recall.ts +247 -196
- package/src/om/ledger/render-summary.ts +79 -50
- package/src/om/ledger/types.ts +146 -117
- package/src/om/model-budget.ts +23 -13
- package/src/om/pending.ts +243 -179
- package/src/om/provider-stream.ts +52 -7
- package/src/om/retryable-error.ts +12 -16
- package/src/om/reverse-recall.ts +97 -91
- package/src/om/runtime.ts +474 -375
- package/src/om/serialize.ts +190 -166
- package/src/om/status-overlay.ts +246 -195
- package/src/om/tokens.ts +28 -21
- package/src/pi-base/blackhole-settings.ts +437 -0
- package/src/pi-base/config-manager.ts +440 -0
- package/src/pi-base/config.ts +469 -0
- package/src/pi-base/env.ts +43 -0
- package/src/pi-base/paths.ts +47 -0
- package/src/pi-base/settings/body.ts +1648 -0
- package/src/pi-base/settings/fields/action.ts +43 -0
- package/src/pi-base/settings/fields/boolean.ts +47 -0
- package/src/pi-base/settings/fields/custom.ts +72 -0
- package/src/pi-base/settings/fields/enum.ts +310 -0
- package/src/pi-base/settings/fields/index.ts +46 -0
- package/src/pi-base/settings/fields/model.ts +452 -0
- package/src/pi-base/settings/fields/string.ts +527 -0
- package/src/pi-base/settings/fields/text.ts +115 -0
- package/src/pi-base/settings/frame.ts +197 -0
- package/src/pi-base/settings/index.ts +77 -0
- package/src/pi-base/settings/inline-edit.ts +313 -0
- package/src/pi-base/settings/modal.ts +152 -0
- package/src/pi-base/settings/types.ts +500 -0
- package/src/pi-base/settings/validate-field.ts +113 -0
- package/src/pi-base/shell.ts +117 -0
- package/src/pi-base/types.ts +6 -0
- package/src/pi-base/ui.ts +32 -0
- package/src/tools/recall.ts +347 -225
- package/src/types.ts +20 -3
- package/tsup.config.ts +23 -0
- package/vitest.config.ts +15 -15
package/src/om/status-overlay.ts
CHANGED
|
@@ -15,11 +15,11 @@ import { matchesKey } from "@earendil-works/pi-tui";
|
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
|
|
17
17
|
type ThemeShim = {
|
|
18
|
-
|
|
18
|
+
fg: (style: string, text: string) => string;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
const EMPTY_THEME: ThemeShim = {
|
|
22
|
-
|
|
22
|
+
fg: (_s: string, t: string) => t,
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
// ---------------------------------------------------------------------------
|
|
@@ -27,20 +27,20 @@ const EMPTY_THEME: ThemeShim = {
|
|
|
27
27
|
// ---------------------------------------------------------------------------
|
|
28
28
|
|
|
29
29
|
export interface StatusInfo {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
compaction: "auto" | "manual" | "off";
|
|
31
|
+
compactionEngine: "blackhole" | "pi-default";
|
|
32
|
+
tailBehavior: "pi-default" | "minimal";
|
|
33
|
+
memory: boolean;
|
|
34
|
+
compactAfterTokens: number;
|
|
35
|
+
consolidationInFlight: boolean;
|
|
36
|
+
compactInFlight: boolean;
|
|
37
|
+
lastObserverError?: string;
|
|
38
|
+
lastReflectorError?: string;
|
|
39
|
+
lastDropperError?: string;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export interface StatusResult {
|
|
43
|
-
|
|
43
|
+
action: "configure" | "close";
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -58,186 +58,237 @@ export interface StatusResult {
|
|
|
58
58
|
* ```
|
|
59
59
|
*/
|
|
60
60
|
export function createStatusOverlay(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
): {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
61
|
+
info: StatusInfo,
|
|
62
|
+
theme: unknown,
|
|
63
|
+
tui: { requestRender: () => void },
|
|
64
|
+
done: (result: StatusResult | undefined) => void,
|
|
65
|
+
): {
|
|
66
|
+
render(width: number): string[];
|
|
67
|
+
handleInput(data: string): void;
|
|
68
|
+
invalidate(): void;
|
|
69
|
+
dispose(): void;
|
|
70
|
+
} {
|
|
71
|
+
const th: ThemeShim =
|
|
72
|
+
theme && typeof (theme as Record<string, unknown>).fg === "function"
|
|
73
|
+
? (theme as ThemeShim)
|
|
74
|
+
: EMPTY_THEME;
|
|
75
|
+
|
|
76
|
+
const fg = (style: string, text: string) => th.fg(style, text);
|
|
77
|
+
const dim = (s: string) => fg("dim", s);
|
|
78
|
+
const accent = (s: string) => fg("accent", s);
|
|
79
|
+
const success = (s: string) => fg("success", s);
|
|
80
|
+
const warning = (s: string) => fg("warning", s);
|
|
81
|
+
const error = (s: string) => fg("error", s);
|
|
82
|
+
const muted = (s: string) => fg("muted", s);
|
|
83
|
+
|
|
84
|
+
const configItems: { label: string; value: string }[] = [
|
|
85
|
+
{ label: "Compaction", value: info.compaction },
|
|
86
|
+
{ label: "Engine", value: info.compactionEngine },
|
|
87
|
+
{ label: "Tail behavior", value: info.tailBehavior },
|
|
88
|
+
{ label: "Memory", value: info.memory ? "Enabled" : "Disabled" },
|
|
89
|
+
{
|
|
90
|
+
label: "Threshold",
|
|
91
|
+
value: `${info.compactAfterTokens.toLocaleString()} tok`,
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
const pipelineItems: { label: string; value: string }[] = [
|
|
96
|
+
{
|
|
97
|
+
label: "Compaction in flight",
|
|
98
|
+
value: info.compactInFlight ? "yes" : "no",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
label: "Consolidation in flight",
|
|
102
|
+
value: info.consolidationInFlight ? "yes" : "no",
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const errorItems: { label: string; value: string }[] = [];
|
|
107
|
+
if (info.lastObserverError)
|
|
108
|
+
errorItems.push({ label: "Observer", value: info.lastObserverError });
|
|
109
|
+
if (info.lastReflectorError)
|
|
110
|
+
errorItems.push({ label: "Reflector", value: info.lastReflectorError });
|
|
111
|
+
if (info.lastDropperError)
|
|
112
|
+
errorItems.push({ label: "Dropper", value: info.lastDropperError });
|
|
113
|
+
|
|
114
|
+
const actionItems = [
|
|
115
|
+
{ label: "Open configure overlay", value: "configure" as const },
|
|
116
|
+
{ label: "Close", value: "close" as const },
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
// Contiguous selectable item model: no section headers in nav indices
|
|
120
|
+
const selectableConfigCount = configItems.length;
|
|
121
|
+
const selectablePipelineCount = pipelineItems.length;
|
|
122
|
+
const selectableErrorCount = errorItems.length;
|
|
123
|
+
const selectableActionCount = actionItems.length;
|
|
124
|
+
const totalSelectable =
|
|
125
|
+
selectableConfigCount +
|
|
126
|
+
selectablePipelineCount +
|
|
127
|
+
selectableErrorCount +
|
|
128
|
+
selectableActionCount;
|
|
129
|
+
|
|
130
|
+
// Render helpers: map a contiguous nav index to the display positions
|
|
131
|
+
// (section headers are inserted at render time, not in the nav model)
|
|
132
|
+
const navIsAction = (idx: number) =>
|
|
133
|
+
idx >=
|
|
134
|
+
selectableConfigCount + selectablePipelineCount + selectableErrorCount;
|
|
135
|
+
|
|
136
|
+
let selectedIndex = 0;
|
|
137
|
+
let cachedLines: string[] | undefined;
|
|
138
|
+
|
|
139
|
+
function invalidate(): void {
|
|
140
|
+
cachedLines = undefined;
|
|
141
|
+
try {
|
|
142
|
+
tui.requestRender();
|
|
143
|
+
} catch {
|
|
144
|
+
/* no-op */
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function handleInput(data: string): void {
|
|
149
|
+
if (matchesKey(data, "escape")) {
|
|
150
|
+
done({ action: "close" });
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (matchesKey(data, "enter") || matchesKey(data, "space")) {
|
|
155
|
+
if (navIsAction(selectedIndex)) {
|
|
156
|
+
const actionIdx =
|
|
157
|
+
selectedIndex -
|
|
158
|
+
selectableConfigCount -
|
|
159
|
+
selectablePipelineCount -
|
|
160
|
+
selectableErrorCount;
|
|
161
|
+
const action = actionItems[actionIdx]!;
|
|
162
|
+
done({ action: action.value });
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (matchesKey(data, "up")) {
|
|
169
|
+
selectedIndex = Math.max(0, selectedIndex - 1);
|
|
170
|
+
invalidate();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (matchesKey(data, "down")) {
|
|
174
|
+
selectedIndex = Math.min(totalSelectable - 1, selectedIndex + 1);
|
|
175
|
+
invalidate();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function render(width: number): string[] {
|
|
181
|
+
if (cachedLines) return cachedLines;
|
|
182
|
+
|
|
183
|
+
const w = Math.max(2, Math.min(width - 2, 74));
|
|
184
|
+
const innerW = w - 4;
|
|
185
|
+
|
|
186
|
+
const pad = (s: string, len: number) => {
|
|
187
|
+
const vis = visibleWidth(s);
|
|
188
|
+
return s + " ".repeat(Math.max(0, len - vis));
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const line = (content: string) => `│ ${pad(content, innerW)} │`;
|
|
192
|
+
const border = (s: string) => fg("border", s);
|
|
193
|
+
|
|
194
|
+
const lines: string[] = [];
|
|
195
|
+
|
|
196
|
+
// Top border + header
|
|
197
|
+
lines.push(fg("border", `╭${"─".repeat(w - 2)}╮`));
|
|
198
|
+
lines.push(
|
|
199
|
+
fg(
|
|
200
|
+
"border",
|
|
201
|
+
`│ ${accent("Blackhole Status")}${" ".repeat(Math.max(0, innerW + 1 - 16))}│`,
|
|
202
|
+
),
|
|
203
|
+
);
|
|
204
|
+
lines.push(fg("border", `├${"─".repeat(w - 2)}┤`));
|
|
205
|
+
|
|
206
|
+
// Config section
|
|
207
|
+
lines.push(border(line(` ${dim("─── Compaction Config ───")}`)));
|
|
208
|
+
for (let i = 0; i < configItems.length; i++) {
|
|
209
|
+
const item = configItems[i]!;
|
|
210
|
+
const isSelected = selectedIndex === i;
|
|
211
|
+
const prefix = isSelected ? accent(" ›") : " ";
|
|
212
|
+
const label = isSelected ? accent(`${item.label}:`) : `${item.label}:`;
|
|
213
|
+
let value: string;
|
|
214
|
+
switch (item.label) {
|
|
215
|
+
case "Compaction":
|
|
216
|
+
value =
|
|
217
|
+
item.value === "auto"
|
|
218
|
+
? accent(item.value)
|
|
219
|
+
: item.value === "off"
|
|
220
|
+
? muted(item.value)
|
|
221
|
+
: dim(item.value);
|
|
222
|
+
break;
|
|
223
|
+
case "Engine":
|
|
224
|
+
value =
|
|
225
|
+
item.value === "blackhole" ? success(item.value) : dim(item.value);
|
|
226
|
+
break;
|
|
227
|
+
case "Memory":
|
|
228
|
+
value =
|
|
229
|
+
item.value === "Enabled" ? success("Enabled") : muted("Disabled");
|
|
230
|
+
break;
|
|
231
|
+
default:
|
|
232
|
+
value = dim(item.value);
|
|
233
|
+
}
|
|
234
|
+
lines.push(border(line(`${prefix} ${pad(label, 16)} ${value}`)));
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Pipeline section
|
|
238
|
+
if (pipelineItems.length > 0) {
|
|
239
|
+
lines.push(border(line(` ${dim("─── Pipeline ───")}`)));
|
|
240
|
+
for (let i = 0; i < pipelineItems.length; i++) {
|
|
241
|
+
const item = pipelineItems[i]!;
|
|
242
|
+
const isSelected = selectedIndex === selectableConfigCount + i;
|
|
243
|
+
const prefix = isSelected ? accent(" ›") : " ";
|
|
244
|
+
const label = isSelected ? accent(`${item.label}:`) : `${item.label}:`;
|
|
245
|
+
const value = item.value === "yes" ? warning("yes") : dim("no");
|
|
246
|
+
lines.push(border(line(`${prefix} ${pad(label, 16)} ${value}`)));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Errors section
|
|
251
|
+
if (errorItems.length > 0) {
|
|
252
|
+
lines.push(border(line(` ${dim("─── Last Errors ───")}`)));
|
|
253
|
+
for (let i = 0; i < errorItems.length; i++) {
|
|
254
|
+
const item = errorItems[i]!;
|
|
255
|
+
const isSelected =
|
|
256
|
+
selectedIndex === selectableConfigCount + selectablePipelineCount + i;
|
|
257
|
+
const prefix = isSelected ? accent(" ›") : " ";
|
|
258
|
+
const label = isSelected ? accent(`${item.label}:`) : `${item.label}:`;
|
|
259
|
+
const truncated =
|
|
260
|
+
item.value.length > 40 ? item.value.slice(0, 37) + "..." : item.value;
|
|
261
|
+
lines.push(
|
|
262
|
+
border(line(`${prefix} ${pad(label, 16)} ${error(truncated)}`)),
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Separator
|
|
268
|
+
lines.push(border(line(` ${dim("─── Actions ───")}`)));
|
|
269
|
+
|
|
270
|
+
// Action items
|
|
271
|
+
for (let i = 0; i < actionItems.length; i++) {
|
|
272
|
+
const item = actionItems[i]!;
|
|
273
|
+
const isSelected =
|
|
274
|
+
selectedIndex ===
|
|
275
|
+
selectableConfigCount +
|
|
276
|
+
selectablePipelineCount +
|
|
277
|
+
selectableErrorCount +
|
|
278
|
+
i;
|
|
279
|
+
const prefix = isSelected ? accent(" ▶") : " ";
|
|
280
|
+
const text = isSelected ? accent(item.label) : dim(item.label);
|
|
281
|
+
lines.push(border(line(`${prefix} ${text}`)));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Bottom hints
|
|
285
|
+
lines.push(border(line("")));
|
|
286
|
+
lines.push(border(dim(" ↑↓ navigate Enter/Space select Esc close ")));
|
|
287
|
+
lines.push(fg("border", `╰${"─".repeat(w - 2)}╯`));
|
|
288
|
+
|
|
289
|
+
cachedLines = lines;
|
|
290
|
+
return lines;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return { render, handleInput, invalidate, dispose: () => {} };
|
|
243
294
|
}
|
package/src/om/tokens.ts
CHANGED
|
@@ -7,27 +7,34 @@
|
|
|
7
7
|
import { estimateTokens as estimateMessageTokens } from "@earendil-works/pi-coding-agent";
|
|
8
8
|
|
|
9
9
|
export function estimateStringTokens(text: string): number {
|
|
10
|
-
|
|
10
|
+
return Math.ceil(text.length / 4);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function estimateEntryTokens(entry: {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
13
|
+
export function estimateEntryTokens(entry: {
|
|
14
|
+
type: string;
|
|
15
|
+
message?: unknown;
|
|
16
|
+
content?: unknown;
|
|
17
|
+
summary?: unknown;
|
|
18
|
+
}): number {
|
|
19
|
+
if (entry.type === "message" && entry.message) {
|
|
20
|
+
return estimateMessageTokens(
|
|
21
|
+
entry.message as Parameters<typeof estimateMessageTokens>[0],
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
if (entry.type === "custom_message" && entry.content) {
|
|
25
|
+
const content = entry.content;
|
|
26
|
+
if (typeof content === "string") return estimateStringTokens(content);
|
|
27
|
+
if (Array.isArray(content)) {
|
|
28
|
+
let total = 0;
|
|
29
|
+
for (const block of content) {
|
|
30
|
+
if (block.type === "text" && block.text)
|
|
31
|
+
total += estimateStringTokens(block.text);
|
|
32
|
+
}
|
|
33
|
+
return total;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (entry.type === "branch_summary" && typeof entry.summary === "string") {
|
|
37
|
+
return estimateStringTokens(entry.summary);
|
|
38
|
+
}
|
|
39
|
+
return 0;
|
|
32
40
|
}
|
|
33
|
-
|