@selesai/code 0.9.15 → 0.10.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.
- package/CHANGELOG.md +22 -0
- package/README.md +6 -9
- package/dist/defaults/models.json +2 -2
- package/dist/defaults/settings.json +3 -7
- package/dist/extensions/package.json +2 -4
- package/dist/extensions/pi-zentui/.editorconfig +12 -0
- package/dist/extensions/pi-zentui/.github/CODEOWNERS +1 -0
- package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/bug_report.yml +110 -0
- package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/config_question.yml +56 -0
- package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/feature_request.yml +63 -0
- package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/rendering_issue.yml +106 -0
- package/dist/extensions/pi-zentui/.github/ISSUE_TEMPLATE/runtime_detection.yml +103 -0
- package/dist/extensions/pi-zentui/.github/dependabot.yml +47 -0
- package/dist/extensions/pi-zentui/.github/pull_request_template.md +34 -0
- package/dist/extensions/pi-zentui/.github/release.yml +18 -0
- package/dist/extensions/pi-zentui/.github/workflows/ci.yml +79 -0
- package/dist/extensions/pi-zentui/.github/workflows/publish.yml +63 -0
- package/dist/extensions/pi-zentui/AGENTS.md +107 -0
- package/dist/extensions/pi-zentui/CONTRIBUTING.md +68 -0
- package/dist/extensions/pi-zentui/LICENSE +21 -0
- package/dist/extensions/pi-zentui/README.md +188 -0
- package/dist/extensions/pi-zentui/SECURITY.md +18 -0
- package/dist/extensions/pi-zentui/assets/main-cover.png +0 -0
- package/dist/extensions/pi-zentui/assets/screenshots/editor-accent-rail.png +0 -0
- package/dist/extensions/pi-zentui/assets/screenshots/editor-minimalist.png +0 -0
- package/dist/extensions/pi-zentui/assets/screenshots/editor-opencode-copy-friendly.png +0 -0
- package/dist/extensions/pi-zentui/assets/screenshots/editor-opencode.png +0 -0
- package/dist/extensions/pi-zentui/assets/screenshots/user-message-compact.png +0 -0
- package/dist/extensions/pi-zentui/assets/screenshots/user-message-framed-copy-friendly.png +0 -0
- package/dist/extensions/pi-zentui/assets/screenshots/user-message-framed.png +0 -0
- package/dist/extensions/pi-zentui/assets/screenshots/user-message-labeled.png +0 -0
- package/dist/extensions/pi-zentui/assets/zentui.png +0 -0
- package/dist/extensions/pi-zentui/biome.json +31 -0
- package/dist/extensions/pi-zentui/docs/configuration.md +509 -0
- package/dist/extensions/pi-zentui/docs/footer-format.md +162 -0
- package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-editor.ts +99 -0
- package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-layout-patch.ts +457 -0
- package/dist/extensions/pi-zentui/extensions/zentui/completion-menu.ts +157 -0
- package/dist/extensions/pi-zentui/extensions/zentui/config.ts +2100 -0
- package/dist/extensions/pi-zentui/extensions/zentui/editor-metadata-format.ts +321 -0
- package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +73 -0
- package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +89 -0
- package/dist/extensions/pi-zentui/extensions/zentui/footer-format.ts +364 -0
- package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +122 -0
- package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +812 -0
- package/dist/extensions/pi-zentui/extensions/zentui/format.ts +568 -0
- package/dist/extensions/pi-zentui/extensions/zentui/git.ts +384 -0
- package/dist/extensions/pi-zentui/extensions/zentui/icons.ts +252 -0
- package/dist/extensions/pi-zentui/extensions/zentui/index.ts +1406 -0
- package/dist/extensions/pi-zentui/extensions/zentui/interaction-summary.ts +1049 -0
- package/dist/extensions/pi-zentui/extensions/zentui/live-context.ts +75 -0
- package/dist/extensions/pi-zentui/extensions/zentui/minimalist-editor.ts +463 -0
- package/dist/extensions/pi-zentui/extensions/zentui/package-version.ts +651 -0
- package/dist/extensions/pi-zentui/extensions/zentui/project-refresh.ts +120 -0
- package/dist/extensions/pi-zentui/extensions/zentui/project-state.ts +59 -0
- package/dist/extensions/pi-zentui/extensions/zentui/prototype-patch-registry.ts +166 -0
- package/dist/extensions/pi-zentui/extensions/zentui/repository-root.ts +98 -0
- package/dist/extensions/pi-zentui/extensions/zentui/runtime.ts +841 -0
- package/dist/extensions/pi-zentui/extensions/zentui/selector-border.ts +93 -0
- package/dist/extensions/pi-zentui/extensions/zentui/session-lifecycle.ts +60 -0
- package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +1796 -0
- package/dist/extensions/pi-zentui/extensions/zentui/settings-previews.ts +128 -0
- package/dist/extensions/pi-zentui/extensions/zentui/state.ts +94 -0
- package/dist/extensions/pi-zentui/extensions/zentui/style.ts +424 -0
- package/dist/extensions/pi-zentui/extensions/zentui/telemetry.ts +82 -0
- package/dist/extensions/pi-zentui/extensions/zentui/ui.ts +1290 -0
- package/dist/extensions/pi-zentui/extensions/zentui/user-message-osc.ts +248 -0
- package/dist/extensions/pi-zentui/extensions/zentui/user-message-styles.ts +215 -0
- package/dist/extensions/pi-zentui/extensions/zentui/user-message.ts +206 -0
- package/dist/extensions/pi-zentui/extensions/zentui/working-line-messages.ts +24 -0
- package/dist/extensions/pi-zentui/extensions/zentui/working-line-spinners.ts +54 -0
- package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +1433 -0
- package/dist/extensions/pi-zentui/package-lock.json +5311 -0
- package/dist/extensions/pi-zentui/package.json +60 -0
- package/dist/extensions/pi-zentui/test/accent-rail-editor.test.ts +232 -0
- package/dist/extensions/pi-zentui/test/accent-rail-layout-patch.test.ts +669 -0
- package/dist/extensions/pi-zentui/test/completion-menu.test.ts +265 -0
- package/dist/extensions/pi-zentui/test/config.test.ts +3119 -0
- package/dist/extensions/pi-zentui/test/editor-metadata-format.test.ts +405 -0
- package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +260 -0
- package/dist/extensions/pi-zentui/test/editor-viewport-indicators.test.ts +1286 -0
- package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +7196 -0
- package/dist/extensions/pi-zentui/test/extension-status.test.ts +182 -0
- package/dist/extensions/pi-zentui/test/fixtures/starship-nerd-font-symbols.toml +172 -0
- package/dist/extensions/pi-zentui/test/footer-format.test.ts +431 -0
- package/dist/extensions/pi-zentui/test/footer-layout.test.ts +113 -0
- package/dist/extensions/pi-zentui/test/footer-repository-path.test.ts +123 -0
- package/dist/extensions/pi-zentui/test/format.test.ts +865 -0
- package/dist/extensions/pi-zentui/test/git.test.ts +212 -0
- package/dist/extensions/pi-zentui/test/icons.test.ts +69 -0
- package/dist/extensions/pi-zentui/test/interaction-summary.test.ts +1402 -0
- package/dist/extensions/pi-zentui/test/live-context-integration.test.ts +378 -0
- package/dist/extensions/pi-zentui/test/live-context.test.ts +139 -0
- package/dist/extensions/pi-zentui/test/minimalist-editor.test.ts +811 -0
- package/dist/extensions/pi-zentui/test/package-version.test.ts +321 -0
- package/dist/extensions/pi-zentui/test/project-refresh.test.ts +250 -0
- package/dist/extensions/pi-zentui/test/project-state.test.ts +159 -0
- package/dist/extensions/pi-zentui/test/repository-root.test.ts +108 -0
- package/dist/extensions/pi-zentui/test/responsive-dependencies.test.ts +825 -0
- package/dist/extensions/pi-zentui/test/runtime.test.ts +183 -0
- package/dist/extensions/pi-zentui/test/session-lifecycle.test.ts +40 -0
- package/dist/extensions/pi-zentui/test/settings-command.test.ts +1381 -0
- package/dist/extensions/pi-zentui/test/settings-previews.test.ts +347 -0
- package/dist/extensions/pi-zentui/test/state.test.ts +84 -0
- package/dist/extensions/pi-zentui/test/telemetry-lifecycle-integration.test.ts +276 -0
- package/dist/extensions/pi-zentui/test/telemetry.test.ts +105 -0
- package/dist/extensions/pi-zentui/test/turn-summary-lifecycle.integration.test.ts +327 -0
- package/dist/extensions/pi-zentui/test/user-message-osc.test.ts +164 -0
- package/dist/extensions/pi-zentui/test/user-message-styles.test.ts +292 -0
- package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +730 -0
- package/dist/extensions/pi-zentui/test/working-line-messages.test.ts +34 -0
- package/dist/extensions/pi-zentui/test/working-line.test.ts +1990 -0
- package/dist/extensions/pi-zentui/tsconfig.json +16 -0
- package/dist/extensions/tps.test.ts +38 -0
- package/dist/extensions/{pi-powerline-footer/tps.ts → tps.ts} +4 -0
- package/dist/skills/design-references/SKILL.md +31 -0
- package/dist/skills/design-references/references/clickhouse/DESIGN.md +544 -0
- package/dist/themes/adventure.json +84 -0
- package/dist/themes/adwaita-dark.json +84 -0
- package/dist/themes/arcoiris.json +84 -0
- package/dist/themes/arthur.json +84 -0
- package/dist/themes/atom.json +84 -0
- package/dist/themes/aura.json +84 -0
- package/dist/themes/black-metal-bathory.json +84 -0
- package/dist/themes/black-metal-burzum.json +84 -0
- package/dist/themes/black-metal-khold.json +84 -0
- package/dist/themes/box.json +84 -0
- package/dist/themes/brogrammer.json +84 -0
- package/dist/themes/carbonfox.json +84 -0
- package/dist/themes/catppuccin-mocha.json +84 -0
- package/dist/themes/citruszest.json +84 -0
- package/dist/themes/cursor-dark.json +84 -0
- package/dist/themes/cutie-pro.json +84 -0
- package/dist/themes/dark-modern.json +84 -0
- package/dist/themes/dark-pastel.json +84 -0
- package/dist/themes/dimmed-monokai.json +84 -0
- package/dist/themes/doom-peacock.json +84 -0
- package/dist/themes/dracula-plus.json +84 -0
- package/dist/themes/dracula.json +80 -0
- package/dist/themes/earthsong.json +84 -0
- package/dist/themes/everforest-dark-hard.json +84 -0
- package/dist/themes/everforest-dark.json +80 -0
- package/dist/themes/fahrenheit.json +84 -0
- package/dist/themes/flatland.json +84 -0
- package/dist/themes/flexoki-dark.json +84 -0
- package/dist/themes/front-end-delight.json +84 -0
- package/dist/themes/fun-forrest.json +84 -0
- package/dist/themes/galizur.json +84 -0
- package/dist/themes/github-dark-colorblind.json +84 -0
- package/dist/themes/github-dark-high-contrast.json +84 -0
- package/dist/themes/glacier.json +84 -0
- package/dist/themes/gruber-darker.json +84 -0
- package/dist/themes/gruvbox-dark-hard.json +84 -0
- package/dist/themes/gruvbox-dark.json +84 -0
- package/dist/themes/gruvbox-material.json +84 -0
- package/dist/themes/guezwhoz.json +84 -0
- package/dist/themes/hacktober.json +84 -0
- package/dist/themes/hardcore.json +84 -0
- package/dist/themes/havn-skumring.json +84 -0
- package/dist/themes/ic-orange-ppl.json +84 -0
- package/dist/themes/iterm2-smoooooth.json +84 -0
- package/dist/themes/iterm2-tango-dark.json +84 -0
- package/dist/themes/japanesque.json +84 -0
- package/dist/themes/jellybeans.json +84 -0
- package/dist/themes/kanagawa-wave.json +84 -0
- package/dist/themes/kurokula.json +84 -0
- package/dist/themes/later-this-evening.json +84 -0
- package/dist/themes/lovelace.json +84 -0
- package/dist/themes/material-darker.json +84 -0
- package/dist/themes/matte-black.json +84 -0
- package/dist/themes/mellow.json +84 -0
- package/dist/themes/miasma.json +84 -0
- package/dist/themes/nord.json +80 -0
- package/dist/themes/nvim-dark.json +84 -0
- package/dist/themes/one-dark.json +80 -0
- package/dist/themes/popping-and-locking.json +84 -0
- package/dist/themes/rose-pine.json +80 -0
- package/dist/themes/sea-shells.json +84 -0
- package/dist/themes/sleepy-hollow.json +84 -0
- package/dist/themes/smyck.json +84 -0
- package/dist/themes/solarized-dark.json +80 -0
- package/dist/themes/tokyo-night.json +80 -0
- package/dist/themes/tomorrow-night-bright.json +84 -0
- package/dist/themes/tomorrow-night-burns.json +84 -0
- package/dist/themes/tomorrow-night.json +84 -0
- package/dist/themes/twilight.json +84 -0
- package/dist/themes/vague.json +84 -0
- package/dist/themes/vesper.json +84 -0
- package/dist/themes/xcode-dark-hc.json +84 -0
- package/docs/custom-provider.md +0 -1
- package/package.json +3 -3
- package/dist/extensions/auto-model/auto-model.test.ts +0 -18
- package/dist/extensions/auto-model/classifier.ts +0 -23
- package/dist/extensions/auto-model/config.ts +0 -51
- package/dist/extensions/auto-model/index.ts +0 -22
- package/dist/extensions/auto-model/lifecycle.test.ts +0 -24
- package/dist/extensions/pi-powerline-footer/.github/workflows/test.yml +0 -27
- package/dist/extensions/pi-powerline-footer/CHANGELOG.md +0 -687
- package/dist/extensions/pi-powerline-footer/CONTRIBUTING.md +0 -16
- package/dist/extensions/pi-powerline-footer/README.md +0 -513
- package/dist/extensions/pi-powerline-footer/banner.png +0 -0
- package/dist/extensions/pi-powerline-footer/bash-mode/completion.ts +0 -586
- package/dist/extensions/pi-powerline-footer/bash-mode/editor.ts +0 -583
- package/dist/extensions/pi-powerline-footer/bash-mode/history.ts +0 -204
- package/dist/extensions/pi-powerline-footer/bash-mode/shell-session.ts +0 -286
- package/dist/extensions/pi-powerline-footer/bash-mode/transcript.ts +0 -108
- package/dist/extensions/pi-powerline-footer/bash-mode/types.ts +0 -60
- package/dist/extensions/pi-powerline-footer/cd-command.ts +0 -190
- package/dist/extensions/pi-powerline-footer/colors.ts +0 -70
- package/dist/extensions/pi-powerline-footer/context-usage.ts +0 -156
- package/dist/extensions/pi-powerline-footer/currency-rates.ts +0 -142
- package/dist/extensions/pi-powerline-footer/editor-composition.ts +0 -32
- package/dist/extensions/pi-powerline-footer/editor-performance.ts +0 -99
- package/dist/extensions/pi-powerline-footer/git-status.ts +0 -329
- package/dist/extensions/pi-powerline-footer/guide.ts +0 -220
- package/dist/extensions/pi-powerline-footer/icons.ts +0 -190
- package/dist/extensions/pi-powerline-footer/index.ts +0 -3428
- package/dist/extensions/pi-powerline-footer/lifecycle.ts +0 -10
- package/dist/extensions/pi-powerline-footer/package.json +0 -49
- package/dist/extensions/pi-powerline-footer/paths.ts +0 -22
- package/dist/extensions/pi-powerline-footer/powerline-config.ts +0 -446
- package/dist/extensions/pi-powerline-footer/presets.ts +0 -102
- package/dist/extensions/pi-powerline-footer/queue/store.ts +0 -313
- package/dist/extensions/pi-powerline-footer/queue/types.ts +0 -53
- package/dist/extensions/pi-powerline-footer/render-scheduler.ts +0 -29
- package/dist/extensions/pi-powerline-footer/segments.ts +0 -570
- package/dist/extensions/pi-powerline-footer/separators.ts +0 -57
- package/dist/extensions/pi-powerline-footer/session-usage.ts +0 -44
- package/dist/extensions/pi-powerline-footer/shortcuts.ts +0 -61
- package/dist/extensions/pi-powerline-footer/tests/bash-mode.test.ts +0 -1905
- package/dist/extensions/pi-powerline-footer/tests/cd-command.test.ts +0 -144
- package/dist/extensions/pi-powerline-footer/tests/context-usage.test.ts +0 -156
- package/dist/extensions/pi-powerline-footer/tests/custom-items.test.ts +0 -344
- package/dist/extensions/pi-powerline-footer/tests/editor-composition.test.ts +0 -48
- package/dist/extensions/pi-powerline-footer/tests/editor-performance.test.ts +0 -43
- package/dist/extensions/pi-powerline-footer/tests/editor-responsiveness.test.ts +0 -136
- package/dist/extensions/pi-powerline-footer/tests/fixed-editor-border.test.ts +0 -39
- package/dist/extensions/pi-powerline-footer/tests/git-optional-locks.test.ts +0 -64
- package/dist/extensions/pi-powerline-footer/tests/git-status.test.ts +0 -92
- package/dist/extensions/pi-powerline-footer/tests/guide.test.ts +0 -129
- package/dist/extensions/pi-powerline-footer/tests/jump-shortcuts.test.ts +0 -116
- package/dist/extensions/pi-powerline-footer/tests/mode-aware-trigger.test.ts +0 -79
- package/dist/extensions/pi-powerline-footer/tests/paths.test.ts +0 -63
- package/dist/extensions/pi-powerline-footer/tests/queue-store.test.ts +0 -65
- package/dist/extensions/pi-powerline-footer/tests/quit-cursor.test.ts +0 -14
- package/dist/extensions/pi-powerline-footer/tests/remaining-regressions.test.ts +0 -173
- package/dist/extensions/pi-powerline-footer/tests/session-usage.test.ts +0 -47
- package/dist/extensions/pi-powerline-footer/tests/stash-shortcut.test.ts +0 -37
- package/dist/extensions/pi-powerline-footer/tests/thinking-segment.test.ts +0 -76
- package/dist/extensions/pi-powerline-footer/tests/token-stats.test.ts +0 -249
- package/dist/extensions/pi-powerline-footer/tests/tps.test.ts +0 -39
- package/dist/extensions/pi-powerline-footer/tests/usage-display.test.ts +0 -237
- package/dist/extensions/pi-powerline-footer/tests/welcome.test.ts +0 -199
- package/dist/extensions/pi-powerline-footer/tests/working-vibes.test.ts +0 -317
- package/dist/extensions/pi-powerline-footer/theme.example.json +0 -24
- package/dist/extensions/pi-powerline-footer/theme.json +0 -12
- package/dist/extensions/pi-powerline-footer/theme.ts +0 -241
- package/dist/extensions/pi-powerline-footer/token-stats.ts +0 -304
- package/dist/extensions/pi-powerline-footer/tsconfig.json +0 -13
- package/dist/extensions/pi-powerline-footer/types.ts +0 -235
- package/dist/extensions/pi-powerline-footer/welcome-dismiss.ts +0 -34
- package/dist/extensions/pi-powerline-footer/welcome.ts +0 -709
- package/dist/extensions/pi-powerline-footer/working-vibes.ts +0 -721
- package/dist/extensions/preview-tools-disabled.test.ts +0 -37
- package/dist/extensions/preview-tools-disabled.ts +0 -11
- package/dist/themes/powerline-footer/theme.json +0 -33
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { computeSessionTokenStats, SessionBranchCache, SessionTokenStatsCache } from "../token-stats.ts";
|
|
5
|
-
|
|
6
|
-
function makeUsage(input: number, output: number, cacheRead = 0, cacheWrite = 0, costPerToken = 0.001) {
|
|
7
|
-
return {
|
|
8
|
-
input,
|
|
9
|
-
output,
|
|
10
|
-
cacheRead,
|
|
11
|
-
cacheWrite,
|
|
12
|
-
cost: { total: (input + output + cacheRead + cacheWrite) * costPerToken },
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function assistantEvent(usage: ReturnType<typeof makeUsage>, stopReason: string = "stop") {
|
|
17
|
-
return {
|
|
18
|
-
type: "message",
|
|
19
|
-
message: {
|
|
20
|
-
role: "assistant",
|
|
21
|
-
content: [{ type: "text", text: "hi" }],
|
|
22
|
-
usage,
|
|
23
|
-
stopReason,
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function userEvent() {
|
|
29
|
-
return {
|
|
30
|
-
type: "message",
|
|
31
|
-
message: { role: "user", content: [{ type: "text", text: "hello" }] },
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function subagentToolResultEvent(costs: number[]) {
|
|
36
|
-
return {
|
|
37
|
-
type: "message",
|
|
38
|
-
message: {
|
|
39
|
-
role: "toolResult",
|
|
40
|
-
toolName: "subagent",
|
|
41
|
-
details: { results: costs.map((cost) => ({ usage: { cost } })) },
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function subagentSlashResultEvent(costs: number[]) {
|
|
47
|
-
return {
|
|
48
|
-
type: "custom_message",
|
|
49
|
-
customType: "subagent-slash-result",
|
|
50
|
-
details: { result: { details: { results: costs.map((cost) => ({ usage: { cost } })) } } },
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
test("session branch cache reuses a leaf path and refreshes when the leaf changes", () => {
|
|
55
|
-
const cache = new SessionBranchCache();
|
|
56
|
-
let leafId = "leaf-1";
|
|
57
|
-
let branch: unknown[] = [{ id: leafId, value: 1 }];
|
|
58
|
-
let branchReads = 0;
|
|
59
|
-
const provider = {
|
|
60
|
-
getLeafId: () => leafId,
|
|
61
|
-
getBranch: () => {
|
|
62
|
-
branchReads += 1;
|
|
63
|
-
return branch;
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
assert.deepEqual(cache.get(null), []);
|
|
68
|
-
|
|
69
|
-
const first = cache.get(provider);
|
|
70
|
-
(branch[0] as { value: number }).value = 2;
|
|
71
|
-
assert.equal(cache.get(provider), first);
|
|
72
|
-
assert.equal((cache.get(provider)[0] as { value: number }).value, 2);
|
|
73
|
-
assert.equal(branchReads, 1);
|
|
74
|
-
|
|
75
|
-
leafId = "leaf-2";
|
|
76
|
-
branch = [...branch, { id: leafId }];
|
|
77
|
-
assert.equal(cache.get(provider), branch);
|
|
78
|
-
assert.equal(branchReads, 2);
|
|
79
|
-
|
|
80
|
-
cache.reset();
|
|
81
|
-
cache.get(provider);
|
|
82
|
-
assert.equal(branchReads, 3);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test("computeSessionTokenStats aggregates usage and tracks thinking level", () => {
|
|
86
|
-
const events = [
|
|
87
|
-
userEvent(),
|
|
88
|
-
{ type: "thinking_level_change", thinkingLevel: "high" },
|
|
89
|
-
assistantEvent(makeUsage(10, 5)),
|
|
90
|
-
assistantEvent(makeUsage(20, 7, 3, 2), "error"), // skipped: error
|
|
91
|
-
assistantEvent(makeUsage(30, 9, 4, 1), "aborted"), // skipped: aborted
|
|
92
|
-
assistantEvent(makeUsage(40, 11, 6, 2)),
|
|
93
|
-
];
|
|
94
|
-
|
|
95
|
-
const stats = computeSessionTokenStats(events);
|
|
96
|
-
|
|
97
|
-
assert.equal(stats.input, 50);
|
|
98
|
-
assert.equal(stats.output, 16);
|
|
99
|
-
assert.equal(stats.cacheRead, 6);
|
|
100
|
-
assert.equal(stats.cacheWrite, 2);
|
|
101
|
-
assert.ok(Math.abs(stats.cost - 0.074) < 1e-12);
|
|
102
|
-
assert.equal(stats.lastAssistant, (events[5] as any).message);
|
|
103
|
-
assert.equal(stats.thinkingLevelFromSession, "high");
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test("computeSessionTokenStats sums subagent child run cost from tool results and slash results", () => {
|
|
107
|
-
const events = [
|
|
108
|
-
userEvent(),
|
|
109
|
-
assistantEvent(makeUsage(10, 5)),
|
|
110
|
-
subagentToolResultEvent([0.12, 0.34]),
|
|
111
|
-
subagentSlashResultEvent([0.5]),
|
|
112
|
-
];
|
|
113
|
-
|
|
114
|
-
const stats = computeSessionTokenStats(events);
|
|
115
|
-
assert.ok(Math.abs(stats.subagentCost - 0.96) < 1e-12);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test("computeSessionTokenStats ignores assistant messages without tokens for lastAssistant", () => {
|
|
119
|
-
const events = [
|
|
120
|
-
assistantEvent(makeUsage(10, 5)),
|
|
121
|
-
assistantEvent(makeUsage(0, 0)),
|
|
122
|
-
];
|
|
123
|
-
|
|
124
|
-
const stats = computeSessionTokenStats(events);
|
|
125
|
-
assert.equal(stats.lastAssistant, (events[0] as any).message);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test("cache reuses stats object while session is unchanged", () => {
|
|
129
|
-
const cache = new SessionTokenStatsCache();
|
|
130
|
-
const events = [userEvent(), assistantEvent(makeUsage(10, 5))];
|
|
131
|
-
|
|
132
|
-
const first = cache.get(events);
|
|
133
|
-
const second = cache.get(events);
|
|
134
|
-
|
|
135
|
-
assert.equal(second, first);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test("cache recomputes when events are appended", () => {
|
|
139
|
-
const cache = new SessionTokenStatsCache();
|
|
140
|
-
const events = [assistantEvent(makeUsage(10, 5))];
|
|
141
|
-
|
|
142
|
-
const first = cache.get(events);
|
|
143
|
-
events.push(assistantEvent(makeUsage(20, 7)));
|
|
144
|
-
const second = cache.get(events);
|
|
145
|
-
|
|
146
|
-
assert.notEqual(second, first);
|
|
147
|
-
assert.equal(second.input, 30);
|
|
148
|
-
assert.equal(second.output, 12);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test("cache recomputes when the last event is updated in place (streaming)", () => {
|
|
152
|
-
const cache = new SessionTokenStatsCache();
|
|
153
|
-
const tail = assistantEvent(makeUsage(10, 5), "streaming");
|
|
154
|
-
const events = [userEvent(), tail];
|
|
155
|
-
|
|
156
|
-
const first = cache.get(events);
|
|
157
|
-
assert.equal(first.output, 5);
|
|
158
|
-
|
|
159
|
-
// Streaming updates the trailing assistant message in place: same event
|
|
160
|
-
// count, same object references, fresh usage numbers.
|
|
161
|
-
tail.message.usage = makeUsage(10, 42);
|
|
162
|
-
tail.message.stopReason = "stop";
|
|
163
|
-
|
|
164
|
-
const second = cache.get(events);
|
|
165
|
-
assert.notEqual(second, first);
|
|
166
|
-
assert.equal(second.output, 42);
|
|
167
|
-
assert.equal(second.lastAssistant, tail.message);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
test("cache recomputes when the last subagent result cost is updated in place", () => {
|
|
171
|
-
const cache = new SessionTokenStatsCache();
|
|
172
|
-
const tail = subagentToolResultEvent([0.1]);
|
|
173
|
-
const events = [assistantEvent(makeUsage(10, 5)), tail];
|
|
174
|
-
|
|
175
|
-
const first = cache.get(events);
|
|
176
|
-
assert.equal(first.subagentCost, 0.1);
|
|
177
|
-
|
|
178
|
-
tail.message.details.results = [{ usage: { cost: 0.3 } }];
|
|
179
|
-
|
|
180
|
-
const second = cache.get(events);
|
|
181
|
-
assert.notEqual(second, first);
|
|
182
|
-
assert.equal(second.subagentCost, 0.3);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
test("cache recomputes when the last event turns into an error in place", () => {
|
|
186
|
-
const cache = new SessionTokenStatsCache();
|
|
187
|
-
const tail = assistantEvent(makeUsage(10, 5));
|
|
188
|
-
const events = [assistantEvent(makeUsage(1, 1)), tail];
|
|
189
|
-
|
|
190
|
-
const first = cache.get(events);
|
|
191
|
-
assert.equal(first.input, 11);
|
|
192
|
-
|
|
193
|
-
tail.message.stopReason = "error";
|
|
194
|
-
|
|
195
|
-
const second = cache.get(events);
|
|
196
|
-
assert.notEqual(second, first);
|
|
197
|
-
assert.equal(second.input, 1);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
test("cache recomputes when the last event is replaced with a same-sized list", () => {
|
|
201
|
-
const cache = new SessionTokenStatsCache();
|
|
202
|
-
const events = [userEvent(), assistantEvent(makeUsage(10, 5))];
|
|
203
|
-
|
|
204
|
-
const first = cache.get(events);
|
|
205
|
-
events[1] = assistantEvent(makeUsage(10, 5));
|
|
206
|
-
const second = cache.get(events);
|
|
207
|
-
|
|
208
|
-
assert.notEqual(second, first);
|
|
209
|
-
assert.deepEqual(
|
|
210
|
-
{ input: second.input, output: second.output },
|
|
211
|
-
{ input: first.input, output: first.output },
|
|
212
|
-
);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
test("cache does not rescan for in-place changes to non-trailing events", () => {
|
|
216
|
-
const cache = new SessionTokenStatsCache();
|
|
217
|
-
const head = assistantEvent(makeUsage(10, 5));
|
|
218
|
-
const events = [head, assistantEvent(makeUsage(20, 7))];
|
|
219
|
-
|
|
220
|
-
const first = cache.get(events);
|
|
221
|
-
|
|
222
|
-
// Historical events are treated as immutable; only the trailing event is
|
|
223
|
-
// re-validated. This documents the cache's correctness boundary.
|
|
224
|
-
head.message.usage = makeUsage(999, 999);
|
|
225
|
-
const second = cache.get(events);
|
|
226
|
-
|
|
227
|
-
assert.equal(second, first);
|
|
228
|
-
assert.equal(second.input, 30);
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
test("reset forces recomputation", () => {
|
|
232
|
-
const cache = new SessionTokenStatsCache();
|
|
233
|
-
const events = [assistantEvent(makeUsage(10, 5))];
|
|
234
|
-
|
|
235
|
-
const first = cache.get(events);
|
|
236
|
-
cache.reset();
|
|
237
|
-
const second = cache.get(events);
|
|
238
|
-
|
|
239
|
-
assert.notEqual(second, first);
|
|
240
|
-
assert.equal(second.input, first.input);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
test("index.ts wires the token stats cache into buildSegmentContext", () => {
|
|
244
|
-
const source = readFileSync(new URL("../index.ts", import.meta.url), "utf-8");
|
|
245
|
-
assert.match(source, /import \{ SessionBranchCache, SessionTokenStatsCache \} from "\.\/token-stats\.ts";/);
|
|
246
|
-
assert.match(source, /sessionBranchCache\.get\(ctx\.sessionManager\)/);
|
|
247
|
-
assert.match(source, /tokenStatsCache\.get\(sessionEvents\)/);
|
|
248
|
-
assert.match(source, /tokenStatsCache\.reset\(\)/);
|
|
249
|
-
});
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { calculateReliableTps, type TpsTiming } from "../tps.ts";
|
|
4
|
-
|
|
5
|
-
function timing(overrides: Partial<TpsTiming> = {}): TpsTiming {
|
|
6
|
-
return {
|
|
7
|
-
messageStartMs: 0,
|
|
8
|
-
lastUpdateMs: 350,
|
|
9
|
-
firstTokenMs: 100,
|
|
10
|
-
updateCount: 5,
|
|
11
|
-
firstStreamUpdateMs: 150,
|
|
12
|
-
lastStreamUpdateMs: 350,
|
|
13
|
-
stallMs: 0,
|
|
14
|
-
generationMs: 400,
|
|
15
|
-
...overrides,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
test("calculateReliableTps uses active stream time for sufficiently sampled output", () => {
|
|
20
|
-
assert.deepEqual(calculateReliableTps(100, timing()), {
|
|
21
|
-
tps: 500,
|
|
22
|
-
effectiveMs: 200,
|
|
23
|
-
isPrimary: true,
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
test("calculateReliableTps falls back around stalls and rejects implausible samples", () => {
|
|
28
|
-
assert.deepEqual(calculateReliableTps(100, timing({ updateCount: 2, firstStreamUpdateMs: 150, lastStreamUpdateMs: 250, generationMs: 500 })), {
|
|
29
|
-
tps: 200,
|
|
30
|
-
effectiveMs: 500,
|
|
31
|
-
isPrimary: false,
|
|
32
|
-
});
|
|
33
|
-
assert.deepEqual(calculateReliableTps(100, timing({ stallMs: 100 })), {
|
|
34
|
-
tps: 333.3,
|
|
35
|
-
effectiveMs: 300,
|
|
36
|
-
isPrimary: false,
|
|
37
|
-
});
|
|
38
|
-
assert.equal(calculateReliableTps(10_001, timing()), null);
|
|
39
|
-
});
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { renderSegment } from "../segments.ts";
|
|
4
|
-
import { mergeSegmentOptions, parsePowerlineConfig } from "../powerline-config.ts";
|
|
5
|
-
import type { SegmentContext, StatusLineSegmentOptions } from "../types.ts";
|
|
6
|
-
|
|
7
|
-
const PRESET_NAMES = ["default", "compact"];
|
|
8
|
-
|
|
9
|
-
const originalNerdFonts = process.env.POWERLINE_NERD_FONTS;
|
|
10
|
-
process.env.POWERLINE_NERD_FONTS = "0";
|
|
11
|
-
|
|
12
|
-
test.after(() => {
|
|
13
|
-
if (originalNerdFonts === undefined) {
|
|
14
|
-
delete process.env.POWERLINE_NERD_FONTS;
|
|
15
|
-
} else {
|
|
16
|
-
process.env.POWERLINE_NERD_FONTS = originalNerdFonts;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
function stripAnsi(text: string): string {
|
|
21
|
-
return text.replace(/\x1b\[[0-9;]*m/g, "");
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function plainTheme(): any {
|
|
25
|
-
return {
|
|
26
|
-
fg: (_color: string, text: string) => text,
|
|
27
|
-
bg: (_color: string, text: string) => text,
|
|
28
|
-
bold: (text: string) => text,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function createSegmentContext(options: StatusLineSegmentOptions = {}, overrides: Partial<SegmentContext> = {}): SegmentContext {
|
|
33
|
-
return {
|
|
34
|
-
model: undefined,
|
|
35
|
-
thinkingLevel: "off",
|
|
36
|
-
sessionId: undefined,
|
|
37
|
-
usageStats: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, subagentCost: 0 },
|
|
38
|
-
contextTokens: 0,
|
|
39
|
-
contextPercent: 0,
|
|
40
|
-
contextWindow: 0,
|
|
41
|
-
contextApproximate: false,
|
|
42
|
-
autoCompactEnabled: true,
|
|
43
|
-
customCompactionEnabled: false,
|
|
44
|
-
usingSubscription: false,
|
|
45
|
-
queueSummary: { queueCount: 0, blockedCount: 0, compacting: false, leadingText: null, leadingIntent: null, leadingStatus: null },
|
|
46
|
-
sessionStartTime: Date.now(),
|
|
47
|
-
shellModeActive: false,
|
|
48
|
-
shellRunning: false,
|
|
49
|
-
shellName: null,
|
|
50
|
-
shellCwd: null,
|
|
51
|
-
git: { branch: null, staged: 0, unstaged: 0, untracked: 0 },
|
|
52
|
-
extensionStatuses: new Map(),
|
|
53
|
-
hiddenExtensionStatusKeys: new Set(),
|
|
54
|
-
customItemsById: new Map(),
|
|
55
|
-
options,
|
|
56
|
-
theme: plainTheme(),
|
|
57
|
-
colors: {},
|
|
58
|
-
...overrides,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// ── context_pct format ──────────────────────────────────────────────────────
|
|
63
|
-
|
|
64
|
-
test("context_pct defaults to the full tokens/window rendering", () => {
|
|
65
|
-
const ctx = createSegmentContext({}, {
|
|
66
|
-
contextTokens: 12300,
|
|
67
|
-
contextWindow: 200000,
|
|
68
|
-
contextPercent: 6.15,
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const rendered = renderSegment("context_pct", ctx);
|
|
72
|
-
assert.equal(stripAnsi(rendered.content), "12k/200k (6.2%)");
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test("context_pct percent format renders a bare rounded percentage", () => {
|
|
76
|
-
const ctx = createSegmentContext({ context: { format: "percent" } }, {
|
|
77
|
-
contextTokens: 12300,
|
|
78
|
-
contextWindow: 200000,
|
|
79
|
-
contextPercent: 6.15,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const rendered = renderSegment("context_pct", ctx);
|
|
83
|
-
assert.equal(stripAnsi(rendered.content), "6%");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test("context_pct renders unknown usage after compaction", () => {
|
|
87
|
-
const full = createSegmentContext({}, {
|
|
88
|
-
contextTokens: null,
|
|
89
|
-
contextWindow: 200000,
|
|
90
|
-
contextPercent: null,
|
|
91
|
-
});
|
|
92
|
-
const percent = createSegmentContext({ context: { format: "percent" } }, {
|
|
93
|
-
contextTokens: null,
|
|
94
|
-
contextWindow: 200000,
|
|
95
|
-
contextPercent: null,
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
assert.equal(stripAnsi(renderSegment("context_pct", full).content), "?/200k");
|
|
99
|
-
assert.equal(stripAnsi(renderSegment("context_pct", percent).content), "?");
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test("context_pct marks context estimates as approximate", () => {
|
|
103
|
-
const full = createSegmentContext({}, {
|
|
104
|
-
contextTokens: 18000,
|
|
105
|
-
contextWindow: 272000,
|
|
106
|
-
contextPercent: 6.6176,
|
|
107
|
-
contextApproximate: true,
|
|
108
|
-
});
|
|
109
|
-
const percent = createSegmentContext({ context: { format: "percent" } }, {
|
|
110
|
-
contextTokens: 18000,
|
|
111
|
-
contextWindow: 272000,
|
|
112
|
-
contextPercent: 6.6176,
|
|
113
|
-
contextApproximate: true,
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
assert.equal(stripAnsi(renderSegment("context_pct", full).content), "~18k/272k (6.6%)");
|
|
117
|
-
assert.equal(stripAnsi(renderSegment("context_pct", percent).content), "~7%");
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
test("context_pct percent format keeps threshold colors and drops icons", () => {
|
|
121
|
-
for (const [percent, expected] of [[69, "69%"], [85, "85%"], [95, "95%"]] as const) {
|
|
122
|
-
const ctx = createSegmentContext({ context: { format: "percent" } }, {
|
|
123
|
-
contextTokens: percent,
|
|
124
|
-
contextWindow: 100,
|
|
125
|
-
contextPercent: percent,
|
|
126
|
-
});
|
|
127
|
-
const rendered = renderSegment("context_pct", ctx);
|
|
128
|
-
assert.equal(stripAnsi(rendered.content), expected);
|
|
129
|
-
assert.ok(!rendered.content.includes("◫"), "no context icon in percent mode");
|
|
130
|
-
assert.ok(!rendered.content.includes("AC"), "no auto-compact icon in percent mode");
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// ── cache_read format ───────────────────────────────────────────────────────
|
|
135
|
-
|
|
136
|
-
test("cache_read defaults to raw token count", () => {
|
|
137
|
-
const ctx = createSegmentContext({}, {
|
|
138
|
-
usageStats: { input: 1000, output: 0, cacheRead: 12300, cacheWrite: 0, cost: 0, subagentCost: 0 },
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
const rendered = renderSegment("cache_read", ctx);
|
|
142
|
-
assert.equal(stripAnsi(rendered.content), "cache in: 12k");
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
test("cache_read percent format renders the cache hit rate", () => {
|
|
146
|
-
const ctx = createSegmentContext({ cache_read: { format: "percent" } }, {
|
|
147
|
-
usageStats: { input: 2000, output: 0, cacheRead: 8000, cacheWrite: 0, cost: 0, subagentCost: 0 },
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
const rendered = renderSegment("cache_read", ctx);
|
|
151
|
-
assert.equal(stripAnsi(rendered.content), "cache 80%");
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
test("cache_read both format renders raw token count and cache hit rate", () => {
|
|
155
|
-
const ctx = createSegmentContext({ cache_read: { format: "both" } }, {
|
|
156
|
-
usageStats: { input: 2000, output: 0, cacheRead: 8000, cacheWrite: 0, cost: 0, subagentCost: 0 },
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
const rendered = renderSegment("cache_read", ctx);
|
|
160
|
-
assert.equal(stripAnsi(rendered.content), "cache in: 8.0k (80%)");
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
test("cache_read percent and both formats handle zero input without NaN", () => {
|
|
164
|
-
const percentCtx = createSegmentContext({ cache_read: { format: "percent" } }, {
|
|
165
|
-
usageStats: { input: 0, output: 0, cacheRead: 5, cacheWrite: 0, cost: 0, subagentCost: 0 },
|
|
166
|
-
});
|
|
167
|
-
assert.equal(stripAnsi(renderSegment("cache_read", percentCtx).content), "cache 100%");
|
|
168
|
-
|
|
169
|
-
const bothCtx = createSegmentContext({ cache_read: { format: "both" } }, {
|
|
170
|
-
usageStats: { input: 0, output: 0, cacheRead: 5, cacheWrite: 0, cost: 0, subagentCost: 0 },
|
|
171
|
-
});
|
|
172
|
-
assert.equal(stripAnsi(renderSegment("cache_read", bothCtx).content), "cache in: 5 (100%)");
|
|
173
|
-
|
|
174
|
-
const hidden = createSegmentContext({ cache_read: { format: "both" } });
|
|
175
|
-
assert.deepEqual(renderSegment("cache_read", hidden), { content: "", visible: false });
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// ── queue segment ──────────────────────────────────────────────────────────
|
|
179
|
-
|
|
180
|
-
test("queue segment hides when empty", () => {
|
|
181
|
-
const ctx = createSegmentContext();
|
|
182
|
-
assert.deepEqual(renderSegment("queue", ctx), { content: "", visible: false });
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
test("queue segment summarizes queued and blocked items", () => {
|
|
186
|
-
const ctx = createSegmentContext({}, {
|
|
187
|
-
queueSummary: { queueCount: 2, blockedCount: 1, compacting: false, leadingText: "fix README", leadingIntent: "post-compact", leadingStatus: "blocked" },
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
assert.equal(stripAnsi(renderSegment("queue", ctx).content), "q 2 · blocked 1");
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
test("queue segment highlights compaction-held prompts", () => {
|
|
194
|
-
const ctx = createSegmentContext({}, {
|
|
195
|
-
queueSummary: { queueCount: 1, blockedCount: 0, compacting: true, leadingText: "run after compact", leadingIntent: "post-compact", leadingStatus: "queued" },
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
assert.equal(stripAnsi(renderSegment("queue", ctx).content), "compact q 1");
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
// ── config parsing / merging ────────────────────────────────────────────────
|
|
202
|
-
|
|
203
|
-
test("parsePowerlineConfig accepts context and cache_read formats", () => {
|
|
204
|
-
const config = parsePowerlineConfig({
|
|
205
|
-
context: { format: "percent" },
|
|
206
|
-
cache_read: { format: "both" },
|
|
207
|
-
}, PRESET_NAMES);
|
|
208
|
-
|
|
209
|
-
assert.equal(config.segmentOptions.context?.format, "percent");
|
|
210
|
-
assert.equal(config.segmentOptions.cache_read?.format, "both");
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
test("parsePowerlineConfig ignores invalid format values", () => {
|
|
214
|
-
const config = parsePowerlineConfig({
|
|
215
|
-
context: { format: "bogus" },
|
|
216
|
-
cache_read: { format: 42 },
|
|
217
|
-
}, PRESET_NAMES);
|
|
218
|
-
|
|
219
|
-
assert.equal(config.segmentOptions.context?.format, undefined);
|
|
220
|
-
assert.equal(config.segmentOptions.cache_read?.format, undefined);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
test("parsePowerlineConfig defaults to upstream rendering when options are absent", () => {
|
|
224
|
-
const config = parsePowerlineConfig({}, PRESET_NAMES);
|
|
225
|
-
assert.equal(config.segmentOptions.context, undefined);
|
|
226
|
-
assert.equal(config.segmentOptions.cache_read, undefined);
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
test("mergeSegmentOptions merges context and cache_read per key", () => {
|
|
230
|
-
const merged = mergeSegmentOptions(
|
|
231
|
-
{ context: { format: "percent" }, cache_read: { format: "percent" } },
|
|
232
|
-
{ context: { format: "full" }, cache_read: { format: "both" } },
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
assert.equal(merged.context?.format, "full");
|
|
236
|
-
assert.equal(merged.cache_read?.format, "both");
|
|
237
|
-
});
|