aiblueprint-cli 1.4.59 → 1.4.60

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 (179) hide show
  1. package/README.md +16 -36
  2. package/agents-config/agents/action.md +1 -1
  3. package/agents-config/agents/explore-codebase.md +53 -53
  4. package/agents-config/agents/explore-docs.md +50 -69
  5. package/agents-config/agents/websearch.md +36 -40
  6. package/agents-config/claude-config/scripts/.claude/skills/fix-on-my-computer/SKILL.md +81 -0
  7. package/agents-config/claude-config/scripts/CLAUDE.md +10 -4
  8. package/agents-config/claude-config/scripts/bun.lockb +0 -0
  9. package/agents-config/claude-config/scripts/package.json +22 -30
  10. package/agents-config/claude-config/scripts/statusline/CLAUDE.md +37 -155
  11. package/agents-config/claude-config/scripts/statusline/README.md +18 -94
  12. package/agents-config/claude-config/scripts/statusline/defaults.json +13 -10
  13. package/agents-config/claude-config/scripts/statusline/fixtures/mock-transcript.jsonl +4 -4
  14. package/agents-config/claude-config/scripts/statusline/fixtures/test-input.json +4 -4
  15. package/agents-config/claude-config/scripts/statusline/src/commands/interactive-config.ts +403 -0
  16. package/agents-config/claude-config/scripts/statusline/src/index.ts +33 -82
  17. package/agents-config/claude-config/scripts/statusline/src/lib/config-types.ts +7 -1
  18. package/agents-config/claude-config/scripts/statusline/src/lib/formatters.ts +40 -0
  19. package/agents-config/claude-config/scripts/statusline/src/lib/presets.ts +13 -13
  20. package/agents-config/claude-config/scripts/statusline/src/lib/render-pure.ts +24 -5
  21. package/agents-config/claude-config/scripts/statusline/statusline.config.free.json +79 -0
  22. package/agents-config/claude-config/scripts/statusline/statusline.config.json +77 -77
  23. package/agents-config/commands/prompts/create-vitejs-app.md +272 -0
  24. package/agents-config/commands/prompts/nextjs-add-prisma-db.md +136 -0
  25. package/agents-config/commands/prompts/nextjs-setup-better-auth.md +173 -0
  26. package/agents-config/commands/prompts/nextjs-setup-project.md +200 -0
  27. package/agents-config/commands/prompts/prompt.md +55 -0
  28. package/agents-config/commands/prompts/saas-challenge-idea.md +135 -0
  29. package/agents-config/commands/prompts/saas-create-architecture.md +242 -0
  30. package/agents-config/commands/prompts/saas-create-headline.md +132 -0
  31. package/agents-config/commands/prompts/saas-create-landing-copywritting.md +267 -0
  32. package/agents-config/commands/prompts/saas-create-legals-docs.md +176 -0
  33. package/agents-config/commands/prompts/saas-create-logos.md +240 -0
  34. package/agents-config/commands/prompts/saas-create-prd.md +195 -0
  35. package/agents-config/commands/prompts/saas-create-tasks.md +240 -0
  36. package/agents-config/commands/prompts/saas-define-pricing.md +293 -0
  37. package/agents-config/commands/prompts/saas-find-domain-name.md +190 -0
  38. package/agents-config/commands/prompts/saas-implement-landing-page.md +257 -0
  39. package/agents-config/commands/prompts/setup-tmux.md +160 -0
  40. package/agents-config/commands/prompts/tools.md +148 -0
  41. package/agents-config/scripts/.claude/skills/fix-on-my-computer/SKILL.md +81 -0
  42. package/agents-config/scripts/CLAUDE.md +37 -0
  43. package/agents-config/scripts/biome.json +37 -0
  44. package/agents-config/scripts/bun.lockb +0 -0
  45. package/agents-config/scripts/package.json +24 -0
  46. package/agents-config/scripts/statusline/CLAUDE.md +87 -0
  47. package/agents-config/scripts/statusline/README.md +117 -0
  48. package/agents-config/scripts/statusline/__tests__/context.test.ts +229 -0
  49. package/agents-config/scripts/statusline/__tests__/formatters.test.ts +108 -0
  50. package/agents-config/scripts/statusline/__tests__/statusline.test.ts +309 -0
  51. package/agents-config/scripts/statusline/defaults.json +82 -0
  52. package/agents-config/scripts/statusline/fixtures/mock-transcript.jsonl +4 -0
  53. package/agents-config/scripts/statusline/fixtures/test-input.json +35 -0
  54. package/agents-config/scripts/statusline/src/commands/interactive-config.ts +403 -0
  55. package/agents-config/scripts/statusline/src/index.ts +141 -0
  56. package/agents-config/scripts/statusline/src/lib/config-types.ts +110 -0
  57. package/agents-config/scripts/statusline/src/lib/config.ts +21 -0
  58. package/agents-config/scripts/statusline/src/lib/context.ts +103 -0
  59. package/agents-config/scripts/statusline/src/lib/formatters.ts +426 -0
  60. package/agents-config/scripts/statusline/src/lib/git.ts +100 -0
  61. package/agents-config/scripts/statusline/src/lib/menu-factories.ts +224 -0
  62. package/agents-config/scripts/statusline/src/lib/presets.ts +177 -0
  63. package/agents-config/scripts/statusline/src/lib/render-pure.ts +516 -0
  64. package/agents-config/scripts/statusline/src/lib/types.ts +36 -0
  65. package/agents-config/scripts/statusline/src/lib/utils.ts +15 -0
  66. package/agents-config/scripts/statusline/statusline.config.free.json +79 -0
  67. package/agents-config/scripts/statusline/statusline.config.json +79 -0
  68. package/agents-config/scripts/statusline/test-with-fixtures.ts +37 -0
  69. package/agents-config/scripts/statusline/test.ts +20 -0
  70. package/agents-config/scripts/statusline/tsconfig.json +27 -0
  71. package/agents-config/scripts/tsconfig.json +27 -0
  72. package/agents-config/skills/{subagent-creator → agents-managers}/SKILL.md +47 -47
  73. package/agents-config/skills/{subagent-creator/references/subagents.md → agents-managers/references/agents.md} +45 -45
  74. package/agents-config/skills/{subagent-creator → agents-managers}/references/context-management.md +20 -20
  75. package/agents-config/skills/{subagent-creator → agents-managers}/references/debugging-agents.md +27 -27
  76. package/agents-config/skills/{subagent-creator → agents-managers}/references/error-handling-and-recovery.md +19 -19
  77. package/agents-config/skills/{subagent-creator → agents-managers}/references/evaluation-and-testing.md +29 -29
  78. package/agents-config/skills/{subagent-creator → agents-managers}/references/orchestration-patterns.md +5 -5
  79. package/agents-config/skills/{subagent-creator/references/writing-subagent-prompts.md → agents-managers/references/writing-agent-prompts.md} +23 -23
  80. package/agents-config/skills/codex-environment/SKILL.md +2 -0
  81. package/agents-config/skills/commit/SKILL.md +2 -0
  82. package/agents-config/skills/create-pr/SKILL.md +2 -0
  83. package/agents-config/skills/environments-manager/SKILL.md +271 -0
  84. package/agents-config/skills/environments-manager/examples/claude/.worktreeinclude +3 -0
  85. package/agents-config/skills/environments-manager/examples/claude/commands/dev.md +5 -0
  86. package/agents-config/skills/environments-manager/examples/claude/commands/lint.md +5 -0
  87. package/agents-config/skills/environments-manager/examples/claude/commands/test.md +5 -0
  88. package/agents-config/skills/environments-manager/examples/claude/commands/typecheck.md +5 -0
  89. package/agents-config/skills/environments-manager/examples/claude/settings.json +24 -0
  90. package/agents-config/skills/environments-manager/examples/codex/environments/environment.toml +29 -0
  91. package/agents-config/skills/environments-manager/examples/cursor/worktrees.json +3 -0
  92. package/agents-config/skills/environments-manager/examples/scripts/claude-worktree-create.sh +96 -0
  93. package/agents-config/skills/environments-manager/examples/scripts/claude-worktree-remove.sh +66 -0
  94. package/agents-config/skills/environments-manager/examples/scripts/dev.sh +15 -0
  95. package/agents-config/skills/environments-manager/examples/scripts/worktree-down.sh +22 -0
  96. package/agents-config/skills/environments-manager/examples/scripts/worktree-up.sh +50 -0
  97. package/agents-config/skills/environments-manager/references/claude.md +156 -0
  98. package/agents-config/skills/environments-manager/references/codex.md +97 -0
  99. package/agents-config/skills/environments-manager/references/cursor.md +88 -0
  100. package/agents-config/skills/fix-pr-comments/SKILL.md +2 -0
  101. package/agents-config/skills/grill-me/SKILL.md +10 -0
  102. package/agents-config/skills/merge/SKILL.md +2 -0
  103. package/agents-config/skills/rules-manager/SKILL.md +191 -0
  104. package/agents-config/skills/rules-manager/references/agents-vs-claude.md +66 -0
  105. package/agents-config/skills/rules-manager/references/examples.md +117 -0
  106. package/agents-config/skills/skill-manager/SKILL.md +83 -0
  107. package/agents-config/skills/skill-manager/references/claude-code.md +81 -0
  108. package/agents-config/skills/skill-manager/references/codex.md +288 -0
  109. package/agents-config/skills/skill-manager/references/cursor.md +125 -0
  110. package/agents-config/skills/ultrathink/SKILL.md +2 -0
  111. package/package.json +1 -1
  112. package/agents-config/claude-config/scripts/statusline/data/.gitignore +0 -8
  113. package/agents-config/claude-config/scripts/statusline/data/.gitkeep +0 -0
  114. package/agents-config/claude-config/scripts/statusline/docs/ARCHITECTURE.md +0 -166
  115. package/agents-config/claude-config/scripts/statusline/src/tests/spend-v2.test.ts +0 -306
  116. package/agents-config/skills/apex/SKILL.md +0 -261
  117. package/agents-config/skills/apex/scripts/setup-templates.sh +0 -100
  118. package/agents-config/skills/apex/scripts/update-progress.sh +0 -80
  119. package/agents-config/skills/apex/steps/step-00-init.md +0 -267
  120. package/agents-config/skills/apex/steps/step-00b-branch.md +0 -126
  121. package/agents-config/skills/apex/steps/step-00b-economy.md +0 -244
  122. package/agents-config/skills/apex/steps/step-00b-interactive.md +0 -153
  123. package/agents-config/skills/apex/steps/step-01-analyze.md +0 -361
  124. package/agents-config/skills/apex/steps/step-02-plan.md +0 -264
  125. package/agents-config/skills/apex/steps/step-03-execute.md +0 -239
  126. package/agents-config/skills/apex/steps/step-04-validate.md +0 -251
  127. package/agents-config/skills/apex/templates/00-context.md +0 -43
  128. package/agents-config/skills/apex/templates/01-analyze.md +0 -10
  129. package/agents-config/skills/apex/templates/02-plan.md +0 -10
  130. package/agents-config/skills/apex/templates/03-execute.md +0 -10
  131. package/agents-config/skills/apex/templates/04-validate.md +0 -10
  132. package/agents-config/skills/apex/templates/README.md +0 -176
  133. package/agents-config/skills/apex/templates/step-complete.md +0 -7
  134. package/agents-config/skills/claude-memory/SKILL.md +0 -293
  135. package/agents-config/skills/claude-memory/references/comprehensive-example.md +0 -175
  136. package/agents-config/skills/claude-memory/references/optimize-guide.md +0 -300
  137. package/agents-config/skills/claude-memory/references/project-patterns.md +0 -334
  138. package/agents-config/skills/claude-memory/references/prompting-techniques.md +0 -411
  139. package/agents-config/skills/claude-memory/references/rules-directory-guide.md +0 -298
  140. package/agents-config/skills/claude-memory/references/section-templates.md +0 -347
  141. package/agents-config/skills/fix-errors/SKILL.md +0 -61
  142. package/agents-config/skills/fix-grammar/SKILL.md +0 -59
  143. package/agents-config/skills/ralph-loop/SKILL.md +0 -117
  144. package/agents-config/skills/ralph-loop/scripts/setup.sh +0 -278
  145. package/agents-config/skills/ralph-loop/steps/step-00-init.md +0 -215
  146. package/agents-config/skills/ralph-loop/steps/step-01-interactive-prd.md +0 -366
  147. package/agents-config/skills/ralph-loop/steps/step-02-create-stories.md +0 -273
  148. package/agents-config/skills/ralph-loop/steps/step-03-finish.md +0 -245
  149. package/agents-config/skills/skill-creator/LICENSE.txt +0 -202
  150. package/agents-config/skills/skill-creator/SKILL.md +0 -421
  151. package/agents-config/skills/skill-creator/package.json +0 -5
  152. package/agents-config/skills/skill-creator/references/output-patterns.md +0 -82
  153. package/agents-config/skills/skill-creator/references/progressive-disclosure-patterns.md +0 -374
  154. package/agents-config/skills/skill-creator/references/prompting-integration.md +0 -363
  155. package/agents-config/skills/skill-creator/references/real-world-examples.md +0 -513
  156. package/agents-config/skills/skill-creator/references/script-patterns.md +0 -385
  157. package/agents-config/skills/skill-creator/references/workflows.md +0 -28
  158. package/agents-config/skills/skill-creator/references/xml-tag-guide.md +0 -606
  159. package/agents-config/skills/skill-creator/scripts/init-skill.ts +0 -214
  160. package/agents-config/skills/skill-creator/scripts/package-skill.ts +0 -146
  161. package/agents-config/skills/skill-creator/scripts/validate.ts +0 -138
  162. package/agents-config/skills/workflow-apex-free/SKILL.md +0 -261
  163. package/agents-config/skills/workflow-apex-free/scripts/setup-templates.sh +0 -100
  164. package/agents-config/skills/workflow-apex-free/scripts/update-progress.sh +0 -80
  165. package/agents-config/skills/workflow-apex-free/steps/step-00-init.md +0 -267
  166. package/agents-config/skills/workflow-apex-free/steps/step-00b-branch.md +0 -126
  167. package/agents-config/skills/workflow-apex-free/steps/step-00b-economy.md +0 -244
  168. package/agents-config/skills/workflow-apex-free/steps/step-00b-interactive.md +0 -153
  169. package/agents-config/skills/workflow-apex-free/steps/step-01-analyze.md +0 -361
  170. package/agents-config/skills/workflow-apex-free/steps/step-02-plan.md +0 -264
  171. package/agents-config/skills/workflow-apex-free/steps/step-03-execute.md +0 -239
  172. package/agents-config/skills/workflow-apex-free/steps/step-04-validate.md +0 -251
  173. package/agents-config/skills/workflow-apex-free/templates/00-context.md +0 -43
  174. package/agents-config/skills/workflow-apex-free/templates/01-analyze.md +0 -10
  175. package/agents-config/skills/workflow-apex-free/templates/02-plan.md +0 -10
  176. package/agents-config/skills/workflow-apex-free/templates/03-execute.md +0 -10
  177. package/agents-config/skills/workflow-apex-free/templates/04-validate.md +0 -10
  178. package/agents-config/skills/workflow-apex-free/templates/README.md +0 -176
  179. package/agents-config/skills/workflow-apex-free/templates/step-complete.md +0 -7
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
3
+ "vcs": {
4
+ "enabled": true,
5
+ "clientKind": "git",
6
+ "useIgnoreFile": true
7
+ },
8
+ "files": {
9
+ "ignoreUnknown": false
10
+ },
11
+ "formatter": {
12
+ "enabled": true,
13
+ "indentStyle": "tab"
14
+ },
15
+ "linter": {
16
+ "enabled": true,
17
+ "rules": {
18
+ "recommended": true,
19
+ "suspicious": {
20
+ "noControlCharactersInRegex": "off"
21
+ }
22
+ }
23
+ },
24
+ "javascript": {
25
+ "formatter": {
26
+ "quoteStyle": "double"
27
+ }
28
+ },
29
+ "assist": {
30
+ "enabled": true,
31
+ "actions": {
32
+ "source": {
33
+ "organizeImports": "on"
34
+ }
35
+ }
36
+ }
37
+ }
Binary file
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "scripts",
3
+ "type": "module",
4
+ "scripts": {
5
+ "test": "bun test statusline",
6
+ "statusline:start": "bun statusline/src/index.ts",
7
+ "statusline:test": "bun test statusline",
8
+ "statusline:test-fixtures": "bun statusline/test-with-fixtures.ts",
9
+ "statusline:config": "bun statusline/src/commands/interactive-config.ts",
10
+ "statusline:lint": "biome check --write statusline",
11
+ "lint": "biome check --write .",
12
+ "format": "biome format --write ."
13
+ },
14
+ "dependencies": {
15
+ "picocolors": "^1.1.1"
16
+ },
17
+ "devDependencies": {
18
+ "@biomejs/biome": "^2.3.2",
19
+ "@types/bun": "latest"
20
+ },
21
+ "peerDependencies": {
22
+ "typescript": "^5.0.0"
23
+ }
24
+ }
@@ -0,0 +1,87 @@
1
+ # Claude Code Statusline - Project Memory
2
+
3
+ ## Overview
4
+
5
+ Lightweight, type-safe statusline implementation for Claude Code using Bun and TypeScript. Displays session context, git status, model information, duration, and context usage without premium spend or usage-limit tracking.
6
+
7
+ ## Project Setup & Configuration
8
+
9
+ ### Dependencies
10
+
11
+ - **Bun**: Runtime
12
+ - **picocolors**: Terminal colors
13
+ - **@biomejs/biome**: Linting and formatting
14
+ - **TypeScript**: Type safety
15
+
16
+ ### Configuration in Claude Code
17
+
18
+ Add to `~/.claude/settings.json`:
19
+
20
+ ```json
21
+ {
22
+ "statusLine": {
23
+ "type": "command",
24
+ "command": "bun /Users/melvynx/.claude/scripts/statusline/src/index.ts",
25
+ "padding": 0
26
+ }
27
+ }
28
+ ```
29
+
30
+ ## Architecture
31
+
32
+ ```
33
+ src/
34
+ ├── index.ts # Main entry point
35
+ └── lib/
36
+ ├── types.ts # TypeScript interfaces
37
+ ├── git.ts # Git operations
38
+ ├── context.ts # Payload/transcript context calculation
39
+ ├── render-pure.ts # Pure rendering logic
40
+ └── formatters.ts # Display utilities and colors
41
+ ```
42
+
43
+ ## Data Flow
44
+
45
+ ```
46
+ Claude Code hook -> stdin JSON -> index.ts
47
+ -> get git status
48
+ -> get context data
49
+ -> render statusline
50
+ -> stdout
51
+ ```
52
+
53
+ ## Component Notes
54
+
55
+ - `lib/context.ts` calculates context tokens from the hook payload when available, falling back to transcript parsing.
56
+ - `lib/git.ts` detects branch and staged/unstaged changes.
57
+ - `lib/render-pure.ts` renders output from prepared data and config.
58
+ - `src/commands/interactive-config.ts` must stay in sync with `statusline.config.json`.
59
+
60
+ ## Development
61
+
62
+ ```bash
63
+ bun run test
64
+ bun run statusline:test-fixtures
65
+ bun run statusline:config
66
+ ```
67
+
68
+ Manual test:
69
+
70
+ ```bash
71
+ echo '{ ... }' | bun run statusline:start
72
+ ```
73
+
74
+ ## Error Handling
75
+
76
+ The statusline should fail softly:
77
+
78
+ - Missing transcript -> 0 tokens, 0%
79
+ - Git errors -> no-git fallback
80
+ - Missing config -> default config
81
+ - Invalid stdin -> concise error output
82
+
83
+ ## Critical Requirements
84
+
85
+ - Keep `statusline.config.json`, `defaults.json`, and `src/commands/interactive-config.ts` aligned.
86
+ - Use Bun for runtime and tests.
87
+ - Keep this free version lightweight: no spend database, no usage-limit API, no OAuth credential dependency.
@@ -0,0 +1,117 @@
1
+ # Claude Code Statusline
2
+
3
+ Lightweight statusline for Claude Code with TypeScript + Bun.
4
+
5
+ ## Features
6
+
7
+ - Git branch with staged/unstaged indicators
8
+ - Current working directory
9
+ - Model name and thinking status
10
+ - Session duration
11
+ - Context tokens and percentage
12
+
13
+ ## Structure
14
+
15
+ ```
16
+ src/
17
+ ├── index.ts # Main entry point
18
+ └── lib/
19
+ ├── types.ts # TypeScript interfaces
20
+ ├── git.ts # Git status
21
+ ├── context.ts # Context calculation from payload/transcript
22
+ └── formatters.ts # Formatting utilities
23
+ ```
24
+
25
+ ## Development
26
+
27
+ ```bash
28
+ # Install dependencies
29
+ bun install
30
+
31
+ # Run the statusline (needs stdin JSON)
32
+ echo '{ ... }' | bun run statusline:start
33
+
34
+ # Interactive config
35
+ bun run statusline:config
36
+
37
+ # Format code
38
+ bun run format
39
+
40
+ # Lint code
41
+ bun run lint
42
+ ```
43
+
44
+ ## Interactive Config
45
+
46
+ Explore all configuration options with a live preview:
47
+
48
+ ```bash
49
+ bun run statusline:config
50
+ ```
51
+
52
+ This opens an interactive menu where you can:
53
+ - Toggle any config option with arrow keys and spacebar
54
+ - See instant preview of how the statusline changes
55
+ - Navigate through all available settings
56
+ - Reset to defaults with `R`
57
+ - Explore session, context, path, and git display options
58
+
59
+ **Controls:**
60
+ - `↑↓` or `j/k` - Navigate options
61
+ - `Space` - Toggle selected option
62
+ - `R` - Reset to defaults
63
+ - `Q` - Quit
64
+
65
+ ## Configuration
66
+
67
+ The statusline can be customized via `statusline.config.json`.
68
+
69
+ ### Other Configuration Options
70
+
71
+ - **Session display**: Duration, tokens, context percentage
72
+ - **Git display**: Branch, changes, staged/unstaged files
73
+ - **Path display**: Full, truncated, or basename modes
74
+ - **Progress bars**: Multiple styles and color schemes
75
+
76
+ See `statusline.config.json` for all available options and defaults.
77
+
78
+ ## Usage in Claude Code
79
+
80
+ Update your `~/.claude/settings.json`:
81
+
82
+ ```json
83
+ {
84
+ "statusLine": {
85
+ "type": "command",
86
+ "command": "bun /Users/melvynx/.claude/scripts/statusline/src/index.ts",
87
+ "padding": 0
88
+ }
89
+ }
90
+ ```
91
+
92
+ ## Testing
93
+
94
+ ```bash
95
+ echo '{
96
+ "session_id": "test",
97
+ "transcript_path": "/path/to/transcript.jsonl",
98
+ "cwd": "/path",
99
+ "model": {
100
+ "id": "claude-sonnet-4-5",
101
+ "display_name": "Sonnet 4.5"
102
+ },
103
+ "workspace": {
104
+ "current_dir": "/path",
105
+ "project_dir": "/path"
106
+ },
107
+ "version": "2.0.31",
108
+ "output_style": { "name": "default" },
109
+ "cost": {
110
+ "total_cost_usd": 0.15,
111
+ "total_duration_ms": 300000,
112
+ "total_api_duration_ms": 200000,
113
+ "total_lines_added": 100,
114
+ "total_lines_removed": 50
115
+ }
116
+ }' | bun run statusline:start
117
+ ```
@@ -0,0 +1,229 @@
1
+ import { afterAll, beforeAll, describe, expect, it } from "bun:test";
2
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { getContextData, getContextLength } from "../src/lib/context";
5
+
6
+ const TEST_DIR = join(import.meta.dir, "..", "fixtures", "test-transcripts");
7
+
8
+ beforeAll(() => {
9
+ mkdirSync(TEST_DIR, { recursive: true });
10
+ });
11
+
12
+ afterAll(() => {
13
+ rmSync(TEST_DIR, { recursive: true, force: true });
14
+ });
15
+
16
+ function createTranscript(lines: object[]): string {
17
+ return lines.map((l) => JSON.stringify(l)).join("\n");
18
+ }
19
+
20
+ describe("getContextLength", () => {
21
+ it("should return 0 for empty transcript", async () => {
22
+ const path = join(TEST_DIR, "empty.jsonl");
23
+ writeFileSync(path, "");
24
+ expect(await getContextLength(path)).toBe(0);
25
+ });
26
+
27
+ it("should return 0 for transcript with no usage data", async () => {
28
+ const path = join(TEST_DIR, "no-usage.jsonl");
29
+ const content = createTranscript([
30
+ { type: "user", message: { role: "user", content: "hello" } },
31
+ ]);
32
+ writeFileSync(path, content);
33
+ expect(await getContextLength(path)).toBe(0);
34
+ });
35
+
36
+ it("should calculate tokens from most recent entry", async () => {
37
+ const path = join(TEST_DIR, "with-usage.jsonl");
38
+ const content = createTranscript([
39
+ {
40
+ timestamp: "2025-01-01T10:00:00Z",
41
+ message: {
42
+ role: "assistant",
43
+ usage: { input_tokens: 1000, output_tokens: 100 },
44
+ },
45
+ },
46
+ {
47
+ timestamp: "2025-01-01T10:05:00Z",
48
+ message: {
49
+ role: "assistant",
50
+ usage: { input_tokens: 5000, output_tokens: 200 },
51
+ },
52
+ },
53
+ ]);
54
+ writeFileSync(path, content);
55
+ expect(await getContextLength(path)).toBe(5000);
56
+ });
57
+
58
+ it("should include cache tokens in calculation", async () => {
59
+ const path = join(TEST_DIR, "with-cache.jsonl");
60
+ const content = createTranscript([
61
+ {
62
+ timestamp: "2025-01-01T10:00:00Z",
63
+ message: {
64
+ role: "assistant",
65
+ usage: {
66
+ input_tokens: 1000,
67
+ cache_read_input_tokens: 2000,
68
+ cache_creation_input_tokens: 3000,
69
+ output_tokens: 100,
70
+ },
71
+ },
72
+ },
73
+ ]);
74
+ writeFileSync(path, content);
75
+ expect(await getContextLength(path)).toBe(6000);
76
+ });
77
+
78
+ it("should skip sidechain entries", async () => {
79
+ const path = join(TEST_DIR, "with-sidechain.jsonl");
80
+ const content = createTranscript([
81
+ {
82
+ timestamp: "2025-01-01T10:00:00Z",
83
+ message: {
84
+ role: "assistant",
85
+ usage: { input_tokens: 1000, output_tokens: 100 },
86
+ },
87
+ },
88
+ {
89
+ timestamp: "2025-01-01T10:05:00Z",
90
+ isSidechain: true,
91
+ message: {
92
+ role: "assistant",
93
+ usage: { input_tokens: 99999, output_tokens: 200 },
94
+ },
95
+ },
96
+ ]);
97
+ writeFileSync(path, content);
98
+ expect(await getContextLength(path)).toBe(1000);
99
+ });
100
+
101
+ it("should skip API error messages", async () => {
102
+ const path = join(TEST_DIR, "with-error.jsonl");
103
+ const content = createTranscript([
104
+ {
105
+ timestamp: "2025-01-01T10:00:00Z",
106
+ message: {
107
+ role: "assistant",
108
+ usage: { input_tokens: 1000, output_tokens: 100 },
109
+ },
110
+ },
111
+ {
112
+ timestamp: "2025-01-01T10:05:00Z",
113
+ isApiErrorMessage: true,
114
+ message: {
115
+ role: "assistant",
116
+ usage: { input_tokens: 99999, output_tokens: 200 },
117
+ },
118
+ },
119
+ ]);
120
+ writeFileSync(path, content);
121
+ expect(await getContextLength(path)).toBe(1000);
122
+ });
123
+
124
+ it("should return 0 for non-existent file", async () => {
125
+ expect(await getContextLength("/non/existent/path.jsonl")).toBe(0);
126
+ });
127
+ });
128
+
129
+ describe("getContextData", () => {
130
+ it("should return zeros for non-existent file", async () => {
131
+ const result = await getContextData({
132
+ transcriptPath: "/non/existent/path.jsonl",
133
+ maxContextTokens: 200000,
134
+ autocompactBufferTokens: 45000,
135
+ });
136
+ expect(result).toEqual({ tokens: 0, percentage: 0 });
137
+ });
138
+
139
+ it("should calculate percentage correctly", async () => {
140
+ const path = join(TEST_DIR, "percentage.jsonl");
141
+ const content = createTranscript([
142
+ {
143
+ timestamp: "2025-01-01T10:00:00Z",
144
+ message: {
145
+ role: "assistant",
146
+ usage: { input_tokens: 100000, output_tokens: 100 },
147
+ },
148
+ },
149
+ ]);
150
+ writeFileSync(path, content);
151
+
152
+ const result = await getContextData({
153
+ transcriptPath: path,
154
+ maxContextTokens: 200000,
155
+ autocompactBufferTokens: 45000,
156
+ });
157
+
158
+ expect(result.tokens).toBe(100000);
159
+ expect(result.percentage).toBe(50);
160
+ });
161
+
162
+ it("should add autocompact buffer when useUsableContextOnly is true", async () => {
163
+ const path = join(TEST_DIR, "usable.jsonl");
164
+ const content = createTranscript([
165
+ {
166
+ timestamp: "2025-01-01T10:00:00Z",
167
+ message: {
168
+ role: "assistant",
169
+ usage: { input_tokens: 50000, output_tokens: 100 },
170
+ },
171
+ },
172
+ ]);
173
+ writeFileSync(path, content);
174
+
175
+ const result = await getContextData({
176
+ transcriptPath: path,
177
+ maxContextTokens: 200000,
178
+ autocompactBufferTokens: 45000,
179
+ useUsableContextOnly: true,
180
+ });
181
+
182
+ expect(result.tokens).toBe(95000);
183
+ });
184
+
185
+ it("should add overhead tokens", async () => {
186
+ const path = join(TEST_DIR, "overhead.jsonl");
187
+ const content = createTranscript([
188
+ {
189
+ timestamp: "2025-01-01T10:00:00Z",
190
+ message: {
191
+ role: "assistant",
192
+ usage: { input_tokens: 50000, output_tokens: 100 },
193
+ },
194
+ },
195
+ ]);
196
+ writeFileSync(path, content);
197
+
198
+ const result = await getContextData({
199
+ transcriptPath: path,
200
+ maxContextTokens: 200000,
201
+ autocompactBufferTokens: 45000,
202
+ overheadTokens: 20000,
203
+ });
204
+
205
+ expect(result.tokens).toBe(70000);
206
+ });
207
+
208
+ it("should cap percentage at 100", async () => {
209
+ const path = join(TEST_DIR, "over100.jsonl");
210
+ const content = createTranscript([
211
+ {
212
+ timestamp: "2025-01-01T10:00:00Z",
213
+ message: {
214
+ role: "assistant",
215
+ usage: { input_tokens: 250000, output_tokens: 100 },
216
+ },
217
+ },
218
+ ]);
219
+ writeFileSync(path, content);
220
+
221
+ const result = await getContextData({
222
+ transcriptPath: path,
223
+ maxContextTokens: 200000,
224
+ autocompactBufferTokens: 45000,
225
+ });
226
+
227
+ expect(result.percentage).toBe(100);
228
+ });
229
+ });
@@ -0,0 +1,108 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import {
3
+ formatCost,
4
+ formatDuration,
5
+ formatPath,
6
+ formatResetTime,
7
+ formatTokens,
8
+ } from "../src/lib/formatters";
9
+
10
+ describe("formatPath", () => {
11
+ it("should return basename for basename mode", () => {
12
+ expect(formatPath("/Users/test/project/src/file.ts", "basename")).toBe(
13
+ "file.ts",
14
+ );
15
+ });
16
+
17
+ it("should truncate long paths in truncated mode", () => {
18
+ const result = formatPath("/Users/test/deep/nested/path/file.ts");
19
+ expect(result).toContain("path");
20
+ expect(result).toContain("file.ts");
21
+ });
22
+
23
+ it("should handle Windows-style paths", () => {
24
+ expect(formatPath("C:\\Users\\test\\project\\file.ts", "basename")).toBe(
25
+ "file.ts",
26
+ );
27
+ });
28
+
29
+ it("should handle mixed separators", () => {
30
+ expect(formatPath("/Users/test\\mixed/path", "basename")).toBe("path");
31
+ });
32
+ });
33
+
34
+ describe("formatCost", () => {
35
+ it("should format with 1 decimal by default", () => {
36
+ expect(formatCost(1.234)).toBe("1.2");
37
+ });
38
+
39
+ it("should format as integer when specified", () => {
40
+ expect(formatCost(1.789, "integer")).toBe("2");
41
+ });
42
+
43
+ it("should format with 2 decimals when specified", () => {
44
+ expect(formatCost(1.789, "decimal2")).toBe("1.79");
45
+ });
46
+ });
47
+
48
+ describe("formatTokens", () => {
49
+ it("should format thousands with k suffix", () => {
50
+ const result = formatTokens(5000);
51
+ expect(result).toContain("5.0");
52
+ expect(result).toContain("k");
53
+ });
54
+
55
+ it("should format millions with m suffix", () => {
56
+ const result = formatTokens(1500000);
57
+ expect(result).toContain("1.5");
58
+ expect(result).toContain("m");
59
+ });
60
+
61
+ it("should return raw number for small values", () => {
62
+ const result = formatTokens(500);
63
+ expect(result).toContain("500");
64
+ });
65
+
66
+ it("should hide decimals when showDecimals is false", () => {
67
+ const result = formatTokens(5500, false);
68
+ expect(result).toContain("6");
69
+ });
70
+ });
71
+
72
+ describe("formatDuration", () => {
73
+ it("should format minutes only for short durations", () => {
74
+ expect(formatDuration(300000)).toBe("5m");
75
+ });
76
+
77
+ it("should format hours and minutes for long durations", () => {
78
+ expect(formatDuration(5400000)).toBe("1h 30m");
79
+ });
80
+
81
+ it("should handle zero duration", () => {
82
+ expect(formatDuration(0)).toBe("0m");
83
+ });
84
+ });
85
+
86
+ describe("formatResetTime", () => {
87
+ it("should return 'now' for past times", () => {
88
+ const pastTime = new Date(Date.now() - 60000).toISOString();
89
+ expect(formatResetTime(pastTime)).toBe("now");
90
+ });
91
+
92
+ it("should format future times with hours and minutes", () => {
93
+ const futureTime = new Date(Date.now() + 3700000).toISOString();
94
+ const result = formatResetTime(futureTime);
95
+ expect(result).toContain("h");
96
+ expect(result).toContain("m");
97
+ });
98
+
99
+ it("should format minutes only for short durations", () => {
100
+ const futureTime = new Date(Date.now() + 1800000).toISOString();
101
+ const result = formatResetTime(futureTime);
102
+ expect(result).toMatch(/^\d+m$/);
103
+ });
104
+
105
+ it("should return N/A for invalid dates", () => {
106
+ expect(formatResetTime("invalid-date")).toBe("N/A");
107
+ });
108
+ });