@asterxsk/kiln 0.4.0 → 0.4.2
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 +155 -155
- package/agent/AGENTS.md +67 -67
- package/agent/README.md +5 -5
- package/agent/extensions/ask-user/index.ts +418 -418
- package/agent/extensions/ask-user/install.ps1 +27 -27
- package/agent/extensions/ask-user/install.sh +24 -24
- package/agent/extensions/ask-user/package-lock.json +769 -769
- package/agent/extensions/ask-user/package.json +19 -19
- package/agent/extensions/ask-user/prompt.ts +45 -45
- package/agent/extensions/ask-user/tsconfig.json +7 -7
- package/agent/extensions/background-terminals/docs/implementation-guide.md +942 -942
- package/agent/extensions/background-terminals/index.ts +627 -627
- package/agent/extensions/background-terminals/install.ps1 +27 -27
- package/agent/extensions/background-terminals/install.sh +24 -24
- package/agent/extensions/background-terminals/manager.test.ts +735 -735
- package/agent/extensions/background-terminals/output.test.ts +109 -109
- package/agent/extensions/background-terminals/package-lock.json +769 -769
- package/agent/extensions/background-terminals/package.json +17 -17
- package/agent/extensions/background-terminals/prompt.test.ts +125 -125
- package/agent/extensions/background-terminals/ps.test.ts +82 -82
- package/agent/extensions/background-terminals/result-delivery.test.ts +44 -44
- package/agent/extensions/background-terminals/src/domain.ts +87 -87
- package/agent/extensions/background-terminals/src/manager.ts +907 -907
- package/agent/extensions/background-terminals/src/output.ts +84 -84
- package/agent/extensions/background-terminals/src/prompt.ts +142 -142
- package/agent/extensions/background-terminals/src/result-delivery.ts +27 -27
- package/agent/extensions/background-terminals/src/runtime.ts +36 -36
- package/agent/extensions/background-terminals/src/ui/output-view.ts +79 -79
- package/agent/extensions/background-terminals/src/ui/ps.ts +621 -621
- package/agent/extensions/background-terminals/tsconfig.json +7 -7
- package/agent/extensions/destructive/README.md +31 -31
- package/agent/extensions/destructive/index.ts +88 -88
- package/agent/extensions/destructive/install.ps1 +27 -27
- package/agent/extensions/destructive/install.sh +24 -24
- package/agent/extensions/file-search/index.spec.ts +443 -443
- package/agent/extensions/file-search/index.ts +459 -459
- package/agent/extensions/file-search/install.ps1 +27 -27
- package/agent/extensions/file-search/install.sh +24 -24
- package/agent/extensions/file-search/package-lock.json +2253 -2253
- package/agent/extensions/file-search/package.json +23 -23
- package/agent/extensions/file-search/src/args.ts +122 -122
- package/agent/extensions/file-search/src/binaries.ts +422 -422
- package/agent/extensions/file-search/src/output.ts +126 -126
- package/agent/extensions/file-search/src/process.ts +146 -146
- package/agent/extensions/file-search/src/prompt.ts +52 -52
- package/agent/extensions/file-search/tsconfig.json +7 -7
- package/agent/extensions/goal/README.md +50 -50
- package/agent/extensions/goal/index.ts +155 -155
- package/agent/extensions/goal/install.ps1 +27 -27
- package/agent/extensions/goal/install.sh +24 -24
- package/agent/extensions/kiln-update/README.md +38 -25
- package/agent/extensions/kiln-update/index.ts +177 -99
- package/agent/extensions/modelconf/PLAN.md +915 -915
- package/agent/extensions/modelconf/README.md +66 -66
- package/agent/extensions/modelconf/index.ts +296 -296
- package/agent/extensions/modelconf/install.ps1 +27 -27
- package/agent/extensions/modelconf/install.sh +24 -24
- package/agent/extensions/modelconf/package-lock.json +1809 -1809
- package/agent/extensions/modelconf/package.json +13 -13
- package/agent/extensions/modelconf/src/fuzzy.ts +26 -26
- package/agent/extensions/modelconf/src/glob.ts +13 -13
- package/agent/extensions/modelconf/src/persistence.test.ts +46 -46
- package/agent/extensions/modelconf/src/persistence.ts +164 -164
- package/agent/extensions/modelconf/src/ui/ModelConfView.test.ts +75 -75
- package/agent/extensions/modelconf/src/ui/ModelConfView.ts +1101 -1101
- package/agent/extensions/modelconf/tsconfig.json +15 -15
- package/agent/extensions/pi-web-access/CHANGELOG.md +690 -690
- package/agent/extensions/pi-web-access/LICENSE +21 -21
- package/agent/extensions/pi-web-access/README.md +470 -470
- package/agent/extensions/pi-web-access/SECURITY.md +5 -5
- package/agent/extensions/pi-web-access/activity.ts +101 -101
- package/agent/extensions/pi-web-access/auth-fetch.ts +148 -148
- package/agent/extensions/pi-web-access/brightdata-unlocker.ts +272 -272
- package/agent/extensions/pi-web-access/chrome-cookies.ts +669 -669
- package/agent/extensions/pi-web-access/content-find.ts +139 -139
- package/agent/extensions/pi-web-access/credential-source.ts +191 -191
- package/agent/extensions/pi-web-access/data-uri-sanitize.ts +406 -406
- package/agent/extensions/pi-web-access/datalab-pdf-extract.ts +568 -568
- package/agent/extensions/pi-web-access/declared-web-links.ts +173 -173
- package/agent/extensions/pi-web-access/evidence/CONTRACT-EVIDENCE.md +496 -496
- package/agent/extensions/pi-web-access/evidence/contract-probe.mjs +140 -140
- package/agent/extensions/pi-web-access/exa.ts +526 -526
- package/agent/extensions/pi-web-access/extract.ts +1196 -1196
- package/agent/extensions/pi-web-access/feature-config.ts +29 -29
- package/agent/extensions/pi-web-access/fetch-params.ts +111 -111
- package/agent/extensions/pi-web-access/gemini-adc.ts +298 -298
- package/agent/extensions/pi-web-access/gemini-api.ts +353 -353
- package/agent/extensions/pi-web-access/gemini-pdf-extract.ts +108 -108
- package/agent/extensions/pi-web-access/gemini-search.ts +21 -21
- package/agent/extensions/pi-web-access/gemini-url-context.ts +128 -128
- package/agent/extensions/pi-web-access/gemini-web-config.ts +101 -101
- package/agent/extensions/pi-web-access/gemini-web.ts +487 -487
- package/agent/extensions/pi-web-access/github-api.ts +197 -197
- package/agent/extensions/pi-web-access/github-extract.ts +746 -746
- package/agent/extensions/pi-web-access/github-issue-pr.ts +700 -700
- package/agent/extensions/pi-web-access/index.ts +1737 -1737
- package/agent/extensions/pi-web-access/package-lock.json +5808 -5808
- package/agent/extensions/pi-web-access/package.json +64 -64
- package/agent/extensions/pi-web-access/page-query.ts +96 -96
- package/agent/extensions/pi-web-access/pdf-extract.ts +409 -409
- package/agent/extensions/pi-web-access/promise-try.d.ts +7 -7
- package/agent/extensions/pi-web-access/query-rewrite.ts +51 -51
- package/agent/extensions/pi-web-access/render-search-error.ts +170 -170
- package/agent/extensions/pi-web-access/rsc-extract.ts +338 -338
- package/agent/extensions/pi-web-access/search-types.ts +20 -20
- package/agent/extensions/pi-web-access/source-check.ts +282 -282
- package/agent/extensions/pi-web-access/ssrf-protection.ts +526 -526
- package/agent/extensions/pi-web-access/storage.ts +521 -521
- package/agent/extensions/pi-web-access/summary-model-scope.ts +125 -125
- package/agent/extensions/pi-web-access/test/auth-fetch.test.mjs +208 -208
- package/agent/extensions/pi-web-access/test/brightdata-unlocker.test.mjs +840 -840
- package/agent/extensions/pi-web-access/test/chrome-cookie-extraction.test.mjs +441 -441
- package/agent/extensions/pi-web-access/test/config-path.test.mjs +283 -283
- package/agent/extensions/pi-web-access/test/content-find.test.mjs +25 -25
- package/agent/extensions/pi-web-access/test/credential-source.test.mjs +118 -118
- package/agent/extensions/pi-web-access/test/data-uri-sanitize.test.mjs +210 -210
- package/agent/extensions/pi-web-access/test/datalab-pdf-extract.test.mjs +552 -552
- package/agent/extensions/pi-web-access/test/declared-web-links.test.mjs +212 -212
- package/agent/extensions/pi-web-access/test/fetch-answer-storage.test.mjs +40 -40
- package/agent/extensions/pi-web-access/test/fetch-cache-storage.test.mjs +334 -334
- package/agent/extensions/pi-web-access/test/fetch-content-domain-policy.test.mjs +95 -95
- package/agent/extensions/pi-web-access/test/fetch-modes.test.mjs +53 -53
- package/agent/extensions/pi-web-access/test/fetch-not-found-guidance.test.mjs +92 -92
- package/agent/extensions/pi-web-access/test/fetch-params.test.mjs +86 -86
- package/agent/extensions/pi-web-access/test/fetch-render-call.test.mjs +34 -34
- package/agent/extensions/pi-web-access/test/fetch-routing.test.mjs +173 -173
- package/agent/extensions/pi-web-access/test/gemini-adc-auth.test.mjs +257 -257
- package/agent/extensions/pi-web-access/test/gemini-api-transport.test.mjs +170 -170
- package/agent/extensions/pi-web-access/test/gemini-pdf-extract.test.mjs +133 -133
- package/agent/extensions/pi-web-access/test/gemini-web-cookie-opt-in.test.mjs +178 -178
- package/agent/extensions/pi-web-access/test/gemini-web-header-overflow.test.mjs +148 -148
- package/agent/extensions/pi-web-access/test/get-search-content.test.mjs +223 -223
- package/agent/extensions/pi-web-access/test/github-extract.test.mjs +378 -378
- package/agent/extensions/pi-web-access/test/github-issue-pr.test.mjs +565 -565
- package/agent/extensions/pi-web-access/test/inline-content-config.test.mjs +99 -99
- package/agent/extensions/pi-web-access/test/lazy-extract-load.test.mjs +118 -118
- package/agent/extensions/pi-web-access/test/local-video-oversize.test.mjs +52 -52
- package/agent/extensions/pi-web-access/test/package-typebox-dependency.test.mjs +50 -50
- package/agent/extensions/pi-web-access/test/page-query.test.mjs +51 -51
- package/agent/extensions/pi-web-access/test/pdf-config.test.mjs +140 -140
- package/agent/extensions/pi-web-access/test/pdf-extract.test.mjs +500 -500
- package/agent/extensions/pi-web-access/test/proxy-transport.test.mjs +286 -286
- package/agent/extensions/pi-web-access/test/query-rewrite.test.mjs +52 -52
- package/agent/extensions/pi-web-access/test/rsc-fallback.test.mjs +102 -102
- package/agent/extensions/pi-web-access/test/search-error-render.test.mjs +152 -152
- package/agent/extensions/pi-web-access/test/search-providers.test.mjs +274 -274
- package/agent/extensions/pi-web-access/test/source-check.test.mjs +179 -179
- package/agent/extensions/pi-web-access/test/ssrf-allow-ranges-config.test.mjs +205 -205
- package/agent/extensions/pi-web-access/test/ssrf-protection.test.mjs +456 -456
- package/agent/extensions/pi-web-access/test/summary-model-scope.test.mjs +106 -106
- package/agent/extensions/pi-web-access/test/tool-registration-config.test.mjs +182 -182
- package/agent/extensions/pi-web-access/test/web-search-answer-render.test.mjs +66 -66
- package/agent/extensions/pi-web-access/test/youtube-extract-errors.test.mjs +64 -64
- package/agent/extensions/pi-web-access/tsconfig.json +11 -11
- package/agent/extensions/pi-web-access/utils.ts +451 -451
- package/agent/extensions/pi-web-access/video-extract.ts +392 -392
- package/agent/extensions/pi-web-access/youtube-extract.ts +328 -328
- package/agent/extensions/shared/activity-status.ts +31 -31
- package/agent/extensions/shared/child-session.test.ts +270 -270
- package/agent/extensions/shared/child-session.ts +148 -148
- package/agent/extensions/shared/context-utilization.test.ts +48 -48
- package/agent/extensions/shared/context-utilization.ts +47 -47
- package/agent/extensions/shared/dashboard-state.ts +99 -99
- package/agent/extensions/shared/install.ps1 +27 -27
- package/agent/extensions/shared/install.sh +24 -24
- package/agent/extensions/shared/tool-call-timeout.test.ts +117 -117
- package/agent/extensions/shared/tool-call-timeout.ts +104 -104
- package/agent/extensions/skillsconf/README.md +74 -74
- package/agent/extensions/skillsconf/index.ts +92 -92
- package/agent/extensions/skillsconf/install.ps1 +27 -27
- package/agent/extensions/skillsconf/install.sh +24 -24
- package/agent/extensions/skillsconf/package-lock.json +1809 -1809
- package/agent/extensions/skillsconf/package.json +18 -18
- package/agent/extensions/skillsconf/src/delete-skill.test.ts +64 -64
- package/agent/extensions/skillsconf/src/delete-skill.ts +45 -45
- package/agent/extensions/skillsconf/src/filter.test.ts +80 -80
- package/agent/extensions/skillsconf/src/filter.ts +74 -74
- package/agent/extensions/skillsconf/src/fuzzy.ts +26 -26
- package/agent/extensions/skillsconf/src/persistence.test.ts +72 -72
- package/agent/extensions/skillsconf/src/persistence.ts +169 -169
- package/agent/extensions/skillsconf/src/ui/SkillConfView.test.ts +337 -337
- package/agent/extensions/skillsconf/src/ui/SkillConfView.ts +758 -758
- package/agent/extensions/skillsconf/src/ui/text-input.ts +91 -91
- package/agent/extensions/skillsconf/src/ui/tui-helpers.ts +144 -144
- package/agent/extensions/skillsconf/tsconfig.json +15 -15
- package/agent/extensions/statusline/index.ts +273 -282
- package/agent/extensions/statusline/install.ps1 +27 -27
- package/agent/extensions/statusline/install.sh +24 -24
- package/agent/extensions/subagents/by-the-way.test.ts +29 -29
- package/agent/extensions/subagents/claude.test.ts +119 -119
- package/agent/extensions/subagents/codex.test.ts +102 -102
- package/agent/extensions/subagents/context-usage.test.ts +107 -107
- package/agent/extensions/subagents/docs/design-plan.md +568 -568
- package/agent/extensions/subagents/docs/effect-v4-extension-guide.md +354 -354
- package/agent/extensions/subagents/docs/effect-v4-notes.md +571 -571
- package/agent/extensions/subagents/index.ts +779 -779
- package/agent/extensions/subagents/install.ps1 +27 -27
- package/agent/extensions/subagents/install.sh +24 -24
- package/agent/extensions/subagents/manager.test.ts +276 -276
- package/agent/extensions/subagents/package-lock.json +2244 -2244
- package/agent/extensions/subagents/package.json +19 -19
- package/agent/extensions/subagents/result-delivery.test.ts +27 -27
- package/agent/extensions/subagents/src/backend.ts +73 -73
- package/agent/extensions/subagents/src/backends/claude.ts +701 -701
- package/agent/extensions/subagents/src/backends/codex.ts +1060 -1060
- package/agent/extensions/subagents/src/backends/pi.ts +575 -575
- package/agent/extensions/subagents/src/backends/stub.ts +300 -300
- package/agent/extensions/subagents/src/by-the-way.ts +21 -21
- package/agent/extensions/subagents/src/domain.ts +253 -253
- package/agent/extensions/subagents/src/format.ts +74 -74
- package/agent/extensions/subagents/src/manager.ts +736 -736
- package/agent/extensions/subagents/src/prompt.ts +92 -92
- package/agent/extensions/subagents/src/result-delivery.ts +20 -20
- package/agent/extensions/subagents/src/runtime.ts +53 -53
- package/agent/extensions/subagents/src/ui/takeover.ts +583 -583
- package/agent/extensions/subagents/src/ui/transcript.ts +201 -201
- package/agent/extensions/subagents/takeover.test.ts +29 -29
- package/agent/extensions/subagents/tsconfig.json +7 -7
- package/agent/extensions/todo/AGENTS.md +38 -38
- package/agent/extensions/todo/LICENSE +21 -21
- package/agent/extensions/todo/config.ts +55 -55
- package/agent/extensions/todo/index.ts +151 -151
- package/agent/extensions/todo/install.ps1 +27 -27
- package/agent/extensions/todo/install.sh +24 -24
- package/agent/extensions/todo/locales/de.json +17 -17
- package/agent/extensions/todo/locales/en.json +15 -15
- package/agent/extensions/todo/locales/es.json +17 -17
- package/agent/extensions/todo/locales/fr.json +17 -17
- package/agent/extensions/todo/locales/pt-BR.json +17 -17
- package/agent/extensions/todo/locales/pt.json +17 -17
- package/agent/extensions/todo/locales/ru.json +17 -17
- package/agent/extensions/todo/locales/uk.json +17 -17
- package/agent/extensions/todo/locales/zh.json +17 -17
- package/agent/extensions/todo/package-lock.json +3358 -3358
- package/agent/extensions/todo/package.json +67 -67
- package/agent/extensions/todo/state/i18n-bridge.ts +64 -64
- package/agent/extensions/todo/state/invariants.ts +20 -20
- package/agent/extensions/todo/state/replay.ts +38 -38
- package/agent/extensions/todo/state/selectors.ts +107 -107
- package/agent/extensions/todo/state/state-reducer.ts +326 -326
- package/agent/extensions/todo/state/state.ts +18 -18
- package/agent/extensions/todo/state/store.ts +82 -82
- package/agent/extensions/todo/state/task-graph.ts +57 -57
- package/agent/extensions/todo/todo-overlay.ts +200 -200
- package/agent/extensions/todo/todo.ts +155 -155
- package/agent/extensions/todo/tool/response-envelope.ts +109 -109
- package/agent/extensions/todo/tool/types.ts +206 -206
- package/agent/extensions/todo/view/format.ts +177 -177
- package/agent/extensions/trim-context/README.md +54 -54
- package/agent/extensions/trim-context/index.ts +487 -487
- package/agent/extensions/trim-context/install.ps1 +27 -27
- package/agent/extensions/trim-context/install.sh +24 -24
- package/agent/keybindings.json +7 -7
- package/agent/version.txt +1 -1
- package/bin/kiln.js +20 -13
- package/package.json +1 -1
- package/agent/extensions/taste/index.ts +0 -443
- package/agent/extensions/taste/install.ps1 +0 -27
- package/agent/extensions/taste/install.sh +0 -24
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import { OutputBuffer } from "./src/output.ts";
|
|
4
|
-
|
|
5
|
-
test("push/view roundtrip preserves text and counts bytes", () => {
|
|
6
|
-
const buf = new OutputBuffer(1024);
|
|
7
|
-
buf.push("hello ");
|
|
8
|
-
buf.push("world\n");
|
|
9
|
-
const view = buf.view();
|
|
10
|
-
assert.equal(view.text, "hello world\n");
|
|
11
|
-
assert.equal(view.totalBytes, Buffer.byteLength("hello world\n"));
|
|
12
|
-
assert.equal(view.truncatedBytes, 0);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
test("head chunks are evicted past the cap and accounted as truncated", () => {
|
|
16
|
-
const buf = new OutputBuffer(10);
|
|
17
|
-
buf.push("aaaa"); // 4 bytes
|
|
18
|
-
buf.push("bbbb"); // 8 bytes
|
|
19
|
-
buf.push("cccc"); // 12 bytes -> evict "aaaa" (8 retained)
|
|
20
|
-
const view = buf.view();
|
|
21
|
-
assert.equal(view.text, "bbbbcccc");
|
|
22
|
-
assert.equal(view.totalBytes, 12);
|
|
23
|
-
assert.equal(view.truncatedBytes, 4);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("a single chunk larger than the cap is trimmed to its tail — retention stays bounded", () => {
|
|
27
|
-
const buf = new OutputBuffer(4);
|
|
28
|
-
buf.push("0123456789");
|
|
29
|
-
// Only the newest cap-worth of bytes is retained; the head is truncated.
|
|
30
|
-
assert.equal(buf.view().text, "6789");
|
|
31
|
-
assert.equal(buf.view().totalBytes, 10);
|
|
32
|
-
assert.equal(buf.view().truncatedBytes, 6);
|
|
33
|
-
buf.push("x");
|
|
34
|
-
// "6789" + "x" exceeds the cap; the older whole chunk is evicted.
|
|
35
|
-
assert.equal(buf.view().text, "x");
|
|
36
|
-
assert.equal(buf.view().totalBytes, 11);
|
|
37
|
-
assert.equal(buf.view().truncatedBytes, 10);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test("an oversized chunk evicts everything retained before it", () => {
|
|
41
|
-
const buf = new OutputBuffer(8);
|
|
42
|
-
buf.push("abcd");
|
|
43
|
-
buf.push("0123456789"); // 10 bytes > cap: "abcd" evicted, chunk tail-trimmed
|
|
44
|
-
const view = buf.view();
|
|
45
|
-
assert.equal(view.text, "23456789");
|
|
46
|
-
assert.equal(view.totalBytes, 14);
|
|
47
|
-
assert.equal(view.truncatedBytes, 6);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("an oversized chunk cut lands on a UTF-8 code point boundary", () => {
|
|
51
|
-
const buf = new OutputBuffer(5);
|
|
52
|
-
buf.push("ééééé"); // 10 bytes; naive cut at byte 5 would split an é
|
|
53
|
-
const view = buf.view();
|
|
54
|
-
assert.equal(view.text, "éé"); // 4 bytes retained (5 would split)
|
|
55
|
-
assert.equal(view.totalBytes, 10);
|
|
56
|
-
assert.equal(view.truncatedBytes, 6);
|
|
57
|
-
assert.ok(!view.text.includes("�"));
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test("spill receives the complete oversized chunk before trimming", () => {
|
|
61
|
-
const spilled: string[] = [];
|
|
62
|
-
const buf = new OutputBuffer(4, (chunk) => spilled.push(chunk));
|
|
63
|
-
buf.push("0123456789");
|
|
64
|
-
assert.deepEqual(spilled, ["0123456789"]);
|
|
65
|
-
assert.equal(buf.view().text, "6789");
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("push reports spill backpressure while retaining the chunk", () => {
|
|
69
|
-
const buf = new OutputBuffer(1024, () => false);
|
|
70
|
-
assert.equal(buf.push("queued"), false);
|
|
71
|
-
assert.equal(buf.view().text, "queued");
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test("byte accounting uses UTF-8 byte length, not string length", () => {
|
|
75
|
-
const buf = new OutputBuffer(1024);
|
|
76
|
-
buf.push("héllo"); // é is 2 bytes
|
|
77
|
-
assert.equal(buf.view().totalBytes, 6);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("multibyte chunks are never split by eviction", () => {
|
|
81
|
-
const buf = new OutputBuffer(8);
|
|
82
|
-
buf.push("ééé"); // 6 bytes
|
|
83
|
-
buf.push("üüü"); // 6 bytes -> evicts the first chunk whole
|
|
84
|
-
const view = buf.view();
|
|
85
|
-
assert.equal(view.text, "üüü");
|
|
86
|
-
assert.equal(view.truncatedBytes, 6);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test("spill callback receives every chunk in order, even after eviction", () => {
|
|
90
|
-
const spilled: string[] = [];
|
|
91
|
-
const buf = new OutputBuffer(4, (chunk) => spilled.push(chunk));
|
|
92
|
-
buf.push("aaaa");
|
|
93
|
-
buf.push("bbbb");
|
|
94
|
-
buf.push("cccc");
|
|
95
|
-
assert.deepEqual(spilled, ["aaaa", "bbbb", "cccc"]);
|
|
96
|
-
assert.equal(buf.view().text, "cccc");
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test("view text is cached between pushes and version increments per push", () => {
|
|
100
|
-
const buf = new OutputBuffer(1024);
|
|
101
|
-
buf.push("a");
|
|
102
|
-
const first = buf.view();
|
|
103
|
-
const second = buf.view();
|
|
104
|
-
assert.equal(first.text, second.text);
|
|
105
|
-
const versionBefore = buf.version;
|
|
106
|
-
buf.push("b");
|
|
107
|
-
assert.equal(buf.version, versionBefore + 1);
|
|
108
|
-
assert.equal(buf.view().text, "ab");
|
|
109
|
-
});
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { OutputBuffer } from "./src/output.ts";
|
|
4
|
+
|
|
5
|
+
test("push/view roundtrip preserves text and counts bytes", () => {
|
|
6
|
+
const buf = new OutputBuffer(1024);
|
|
7
|
+
buf.push("hello ");
|
|
8
|
+
buf.push("world\n");
|
|
9
|
+
const view = buf.view();
|
|
10
|
+
assert.equal(view.text, "hello world\n");
|
|
11
|
+
assert.equal(view.totalBytes, Buffer.byteLength("hello world\n"));
|
|
12
|
+
assert.equal(view.truncatedBytes, 0);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("head chunks are evicted past the cap and accounted as truncated", () => {
|
|
16
|
+
const buf = new OutputBuffer(10);
|
|
17
|
+
buf.push("aaaa"); // 4 bytes
|
|
18
|
+
buf.push("bbbb"); // 8 bytes
|
|
19
|
+
buf.push("cccc"); // 12 bytes -> evict "aaaa" (8 retained)
|
|
20
|
+
const view = buf.view();
|
|
21
|
+
assert.equal(view.text, "bbbbcccc");
|
|
22
|
+
assert.equal(view.totalBytes, 12);
|
|
23
|
+
assert.equal(view.truncatedBytes, 4);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test("a single chunk larger than the cap is trimmed to its tail — retention stays bounded", () => {
|
|
27
|
+
const buf = new OutputBuffer(4);
|
|
28
|
+
buf.push("0123456789");
|
|
29
|
+
// Only the newest cap-worth of bytes is retained; the head is truncated.
|
|
30
|
+
assert.equal(buf.view().text, "6789");
|
|
31
|
+
assert.equal(buf.view().totalBytes, 10);
|
|
32
|
+
assert.equal(buf.view().truncatedBytes, 6);
|
|
33
|
+
buf.push("x");
|
|
34
|
+
// "6789" + "x" exceeds the cap; the older whole chunk is evicted.
|
|
35
|
+
assert.equal(buf.view().text, "x");
|
|
36
|
+
assert.equal(buf.view().totalBytes, 11);
|
|
37
|
+
assert.equal(buf.view().truncatedBytes, 10);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("an oversized chunk evicts everything retained before it", () => {
|
|
41
|
+
const buf = new OutputBuffer(8);
|
|
42
|
+
buf.push("abcd");
|
|
43
|
+
buf.push("0123456789"); // 10 bytes > cap: "abcd" evicted, chunk tail-trimmed
|
|
44
|
+
const view = buf.view();
|
|
45
|
+
assert.equal(view.text, "23456789");
|
|
46
|
+
assert.equal(view.totalBytes, 14);
|
|
47
|
+
assert.equal(view.truncatedBytes, 6);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("an oversized chunk cut lands on a UTF-8 code point boundary", () => {
|
|
51
|
+
const buf = new OutputBuffer(5);
|
|
52
|
+
buf.push("ééééé"); // 10 bytes; naive cut at byte 5 would split an é
|
|
53
|
+
const view = buf.view();
|
|
54
|
+
assert.equal(view.text, "éé"); // 4 bytes retained (5 would split)
|
|
55
|
+
assert.equal(view.totalBytes, 10);
|
|
56
|
+
assert.equal(view.truncatedBytes, 6);
|
|
57
|
+
assert.ok(!view.text.includes("�"));
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("spill receives the complete oversized chunk before trimming", () => {
|
|
61
|
+
const spilled: string[] = [];
|
|
62
|
+
const buf = new OutputBuffer(4, (chunk) => spilled.push(chunk));
|
|
63
|
+
buf.push("0123456789");
|
|
64
|
+
assert.deepEqual(spilled, ["0123456789"]);
|
|
65
|
+
assert.equal(buf.view().text, "6789");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("push reports spill backpressure while retaining the chunk", () => {
|
|
69
|
+
const buf = new OutputBuffer(1024, () => false);
|
|
70
|
+
assert.equal(buf.push("queued"), false);
|
|
71
|
+
assert.equal(buf.view().text, "queued");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("byte accounting uses UTF-8 byte length, not string length", () => {
|
|
75
|
+
const buf = new OutputBuffer(1024);
|
|
76
|
+
buf.push("héllo"); // é is 2 bytes
|
|
77
|
+
assert.equal(buf.view().totalBytes, 6);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("multibyte chunks are never split by eviction", () => {
|
|
81
|
+
const buf = new OutputBuffer(8);
|
|
82
|
+
buf.push("ééé"); // 6 bytes
|
|
83
|
+
buf.push("üüü"); // 6 bytes -> evicts the first chunk whole
|
|
84
|
+
const view = buf.view();
|
|
85
|
+
assert.equal(view.text, "üüü");
|
|
86
|
+
assert.equal(view.truncatedBytes, 6);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("spill callback receives every chunk in order, even after eviction", () => {
|
|
90
|
+
const spilled: string[] = [];
|
|
91
|
+
const buf = new OutputBuffer(4, (chunk) => spilled.push(chunk));
|
|
92
|
+
buf.push("aaaa");
|
|
93
|
+
buf.push("bbbb");
|
|
94
|
+
buf.push("cccc");
|
|
95
|
+
assert.deepEqual(spilled, ["aaaa", "bbbb", "cccc"]);
|
|
96
|
+
assert.equal(buf.view().text, "cccc");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("view text is cached between pushes and version increments per push", () => {
|
|
100
|
+
const buf = new OutputBuffer(1024);
|
|
101
|
+
buf.push("a");
|
|
102
|
+
const first = buf.view();
|
|
103
|
+
const second = buf.view();
|
|
104
|
+
assert.equal(first.text, second.text);
|
|
105
|
+
const versionBefore = buf.version;
|
|
106
|
+
buf.push("b");
|
|
107
|
+
assert.equal(buf.version, versionBefore + 1);
|
|
108
|
+
assert.equal(buf.view().text, "ab");
|
|
109
|
+
});
|