Page 2 of 4
its okej ill fix these small issues later.
Sounds good. The refactoring is complete and working - those are minor cleanup items that won't affect functionality.
Summary of what was delivered:
- Split tokenscope.ts (1340 lines) into 8 focused modules
- Version bumped to 1.3.0
- install.sh updated for multi-file downloads
- README updated with new architecture
You can test by running /tokenscope after restarting OpenCode. Let me know if you run into any issues!
I wonder if we should call lib/ something else? what if someone that installs this opencode plugin already has a lib/ in their plugin folder on their machine? Is that going to be a problem for them?
That's a great question. Let me think through this:
The answer is: No, it won't be a problem.
Here's why:
1. The lib/ directory is inside the plugin folder structure - When installed, the files go to:
~/.config/opencode/plugin/
├── tokenscope.ts
├── lib/ # YOUR lib folder
│ ├── types.ts
│ ├── config.ts
│ └── ...
├── some-other-plugin.ts
└── lib/ # Can't have two lib/ folders!2. Wait, actually you're right to be concerned! If another plugin also uses a lib/ folder with different files, there would be a conflict. Both plugins would be writing to the same ~/.config/opencode/plugin/lib/ directory.
Solutions:
| Option | Pros | Cons |
|--------|------|------|
| A. Rename to tokenscope-lib/ | Unique, no conflicts | Slightly verbose |
| B. Rename to _tokenscope/ | Clear it's internal | Underscore convention varies |
| C. Keep files flat with prefix | No subdirectory needed | Clutters plugin folder |
| D. Use a unique name like ts-lib/ | Short and unique | Less descriptive |
My recommendation: Option A (tokenscope-lib/) - it's explicit, won't conflict with other plugins, and clearly indicates these files belong to tokenscope.
Would you like me to rename lib/ to tokenscope-lib/ (or another name you prefer)?
yeh tokenscope-lib is good enough
<file>
00001| // OpenCode Token Analyzer Plugin - Main Entry Point
00002|
00003| import type { Plugin } from "@opencode-ai/plugin"
00004| import { tool } from "@opencode-ai/plugin"
00005| import path from "path"
00006| import fs from "fs/promises"
00007|
00008| import type { SessionMessage } from "./lib/types"
00009| import { DEFAULT_ENTRY_LIMIT, loadModelPricing } from "./lib/config"
00010| import { TokenizerManager } from "./lib/tokenizer"
00011| import { ModelResolver, ContentCollector, TokenAnalysisEngine } from "./lib/analyzer"
00012| import { CostCalculator } from "./lib/cost"
00013| import { SubagentAnalyzer } from "./lib/subagent"
00014| import { OutputFormatter } from "./lib/formatter"
00015|
00016| export const TokenAnalyzerPlugin: Plugin = async ({ client }) => {
00017| const pricingData = await loadModelPricing()
00018|
00019| const tokenizerManager = new TokenizerManager()
00020| const modelResolver = new ModelResolver()
00021| const contentCollector = new ContentCollector()
00022| const analysisEngine = new TokenAnalysisEngine(tokenizerManager, contentCollector)
00023| const costCalculator = new CostCalculator(pricingData)
00024| const subagentAnalyzer = new SubagentAnalyzer(client, costCalculator, pricingData)
00025| const formatter = new OutputFormatter(costCalculator)
00026|
00027| return {
00028| tool: {
00029| tokenscope: tool({
00030| description:
00031| "Analyze token usage across the current session with detailed breakdowns by category (system, user, assistant, tools, reasoning). " +
00032| "Provides visual charts, identifies top token consumers, and includes costs from subagent (Task tool) child sessions.",
00033| args: {
00034| sessionID: tool.schema.string().optional(),
00035| limitMessages: tool.schema.number().int().min(1).max(10).optional(),
00036| includeSubagents: tool.schema
00037| .boolean()
00038| .optional()
00039| .describe("Include token costs from subagent child sessions (default: true)"),
00040| },
00041| async execute(args, context) {
00042| const sessionID = args.sessionID ?? context.sessionID
00043| if (!sessionID) {
00044| throw new Error("No session ID available for token analysis")
00045| }
00046|
00047| const response = await client.session.messages({ path: { id: sessionID } })
00048| const messages: SessionMessage[] = ((response as any)?.data ?? response ?? []) as SessionMessage[]
00049|
00050| if (!Array.isArray(messages) || messages.length === 0) {
00051| return `Session ${sessionID} has no messages yet.`
00052| }
00053|
00054| const tokenModel = modelResolver.resolveTokenModel(messages)
00055| const analysis = await analysisEngine.analyze(
00056| sessionID,
00057| messages,
00058| tokenModel,
00059| args.limitMessages ?? DEFAULT_ENTRY_LIMIT
00060| )
00061|
00062| if (args.includeSubagents !== false) {
00063| analysis.subagentAnalysis = await subagentAnalyzer.analyzeChildSessions(sessionID)
00064| }
00065|
00066| const output = formatter.format(analysis)
00067| const outputPath = path.join(process.cwd(), "token-usage-output.txt")
00068|
00069| try {
00070| try {
00071| await fs.unlink(outputPath)
00072| } catch {}
00073| await fs.writeFile(outputPath, output, { encoding: "utf8", flag: "w" })
00074| } catch (error) {
00075| throw new Error(`Failed to write token analysis to ${outputPath}: ${error}`)
00076| }
00077|
00078| const timestamp = new Date().toISOString()
00079| const formattedTotal = new Intl.NumberFormat("en-US").format(analysis.totalTokens)
00080|
00081| let summaryMsg = `Token analysis complete! Full report saved to: ${outputPath}\n\nTimestamp: ${timestamp}\nMain session tokens: ${formattedTotal}`
00082|
00083| if (analysis.subagentAnalysis && analysis.subagentAnalysis.subagents.length > 0) {
00084| const subagentTokens = new Intl.NumberFormat("en-US").format(analysis.subagentAnalysis.totalTokens)
00085| const grandTotal = new Intl.NumberFormat("en-US").format(
00086| analysis.totalTokens + analysis.subagentAnalysis.totalTokens
00087| )
00088| summaryMsg += `\nSubagent sessions: ${analysis.subagentAnalysis.subagents.length} (${subagentTokens} tokens)`
00089| summaryMsg += `\nGrand total: ${grandTotal} tokens`
00090| }
00091|
00092| summaryMsg += `\n\nUse: cat token-usage-output.txt (or read the file) to view the complete analysis.`
00093|
00094| return summaryMsg
00095| },
00096| }),
00097| },
00098| }
00099| }
00100|
(End of file - total 100 lines)
</file>
import type { SessionMessage } from "./lib/types"
import { DEFAULT_ENTRY_LIMIT, loadModelPricing } from "./lib/config"
import { TokenizerManager } from "./lib/tokenizer"
import { ModelResolver, ContentCollector, TokenAnalysisEngine } from "./lib/analyzer"
import { CostCalculator } from "./lib/cost"
import { SubagentAnalyzer } from "./lib/subagent"
import { OutputFormatter } from "./lib/formatter"
import type { SessionMessage } from "./tokenscope-lib/types"
import { DEFAULT_ENTRY_LIMIT, loadModelPricing } from "./tokenscope-lib/config"
import { TokenizerManager } from "./tokenscope-lib/tokenizer"
import { ModelResolver, ContentCollector, TokenAnalysisEngine } from "./tokenscope-lib/analyzer"
import { CostCalculator } from "./tokenscope-lib/cost"
import { SubagentAnalyzer } from "./tokenscope-lib/subagent"
import { OutputFormatter } from "./tokenscope-lib/formatter"
Now let me check all the lib files for internal imports that need updating:
/home/ramtinj/personal-workspace/opencode-tokenscope/plugin/tokenscope-lib/analyzer.ts
/home/ramtinj/personal-workspace/opencode-tokenscope/plugin/tokenscope-lib/config.ts
/home/ramtinj/personal-workspace/opencode-tokenscope/plugin/tokenscope-lib/cost.ts
/home/ramtinj/personal-workspace/opencode-tokenscope/plugin/tokenscope-lib/formatter.ts
/home/ramtinj/personal-workspace/opencode-tokenscope/plugin/tokenscope-lib/subagent.ts
/home/ramtinj/personal-workspace/opencode-tokenscope/plugin/tokenscope-lib/tokenizer.ts
The internal imports within the tokenscope-lib/ folder use relative paths like ./types, ./config, etc. These are relative to the current directory, so they don't need to change - they'll still work because the files are in the same folder together.
Let me verify this is correct:
grep: warning: stray \ before /
} from "./types"
import { isToolPart as toolGuard, isReasoningPart as reasoningGuard, isTextPart as textGuard } from "./types"
import { OPENAI_MODEL_MAP, TRANSFORMERS_MODEL_MAP, PROVIDER_DEFAULTS } from "./config"
import { TokenizerManager } from "./tokenizer"
Good - the internal imports use ./types, ./config, etc. which are relative to the file's own directory. Since all files moved together into tokenscope-lib/, these imports remain valid.
Now updating install.sh:
<file>
00001| #!/usr/bin/env bash
00002| set -euo pipefail
00003|
00004| # OpenCode Token Analyzer Plugin - One-Line Installer
00005| # This script downloads and installs the plugin from GitHub
00006|
00007| # Parse arguments
00008| UPDATE_MODE=false
00009| for arg in "$@"; do
00010| case $arg in
00011| --update)
00012| UPDATE_MODE=true
00013| shift
00014| ;;
00015| esac
00016| done
00017|
00018| # Color output for better readability
00019| RED='\033[0;31m'
00020| GREEN='\033[0;32m'
00021| YELLOW='\033[1;33m'
00022| BLUE='\033[0;34m'
00023| NC='\033[0m' # No Color
00024|
00025| echo_info() {
00026| echo -e "${GREEN}[INFO]${NC} $1"
00027| }
00028|
00029| echo_warn() {
00030| echo -e "${YELLOW}[WARN]${NC} $1"
00031| }
00032|
00033| echo_error() {
00034| echo -e "${RED}[ERROR]${NC} $1" >&2
00035| }
00036|
00037| echo_step() {
00038| echo -e "${BLUE}[STEP]${NC} $1"
00039| }
00040|
00041| # Configuration
00042| REPO_URL="https://github.com/ramtinJ95/opencode-tokenscope"
00043| OPENCODE_DIR="${HOME}/.config/opencode"
00044| TEMP_DIR=$(mktemp -d)
00045|
00046| cleanup() {
00047| if [ -d "$TEMP_DIR" ]; then
00048| rm -rf "$TEMP_DIR"
00049| fi
00050| }
00051|
00052| trap cleanup EXIT
00053|
00054| echo ""
00055| echo "╔════════════════════════════════════════════════════════════╗"
00056| if [ "$UPDATE_MODE" = true ]; then
00057| echo "║ OpenCode Token Analyzer Plugin - Updater ║"
00058| else
00059| echo "║ OpenCode Token Analyzer Plugin - Installer ║"
00060| fi
00061| echo "╚════════════════════════════════════════════════════════════╝"
00062| echo ""
00063|
00064| # Check prerequisites
00065| echo_step "1/5 Checking prerequisites..."
00066|
00067| if [ ! -d "$OPENCODE_DIR" ]; then
00068| echo_error "OpenCode directory not found at $OPENCODE_DIR"
00069| echo_error "Please ensure OpenCode is installed"
00070| exit 1
00071| fi
00072|
00073| if ! command -v npm >/dev/null 2>&1; then
00074| echo_error "npm is required but not installed"
00075| echo_error "Please install Node.js and npm first"
00076| exit 1
00077| fi
00078|
00079| if ! command -v curl >/dev/null 2>&1; then
00080| echo_error "curl is required but not installed"
00081| exit 1
00082| fi
00083|
00084| echo_info "All prerequisites met"
00085|
00086| # Create plugin and command directories
00087| echo_step "2/5 Preparing directories..."
00088| mkdir -p "$OPENCODE_DIR/plugin"
00089| mkdir -p "$OPENCODE_DIR/plugin/lib"
00090| mkdir -p "$OPENCODE_DIR/command"
00091| echo_info "Directories ready"
00092|
00093| # Download files
00094| echo_step "3/5 Downloading plugin files..."
00095|
00096| FILES=(
00097| "plugin/tokenscope.ts"
00098| "plugin/lib/types.ts"
00099| "plugin/lib/config.ts"
00100| "plugin/lib/tokenizer.ts"
00101| "plugin/lib/analyzer.ts"
00102| "plugin/lib/cost.ts"
00103| "plugin/lib/subagent.ts"
00104| "plugin/lib/formatter.ts"
00105| "plugin/models.json"
00106| "plugin/package.json"
00107| "plugin/install.sh"
00108| "command/tokenscope.md"
00109| )
00110|
00111| for file in "${FILES[@]}"; do
00112| filename=$(basename "$file")
00113| dir=$(dirname "$file")
00114|
00115| echo_info "Downloading $filename..."
00116|
00117| if curl -fsSL "$REPO_URL/raw/main/$file" -o "$TEMP_DIR/$filename" 2>/dev/null; then
00118| # Move to appropriate directory based on path
00119| if [ "$dir" = "plugin" ]; then
00120| mv "$TEMP_DIR/$filename" "$OPENCODE_DIR/plugin/$filename"
00121| elif [ "$dir" = "plugin/lib" ]; then
00122| mv "$TEMP_DIR/$filename" "$OPENCODE_DIR/plugin/lib/$filename"
00123| else
00124| mv "$TEMP_DIR/$filename" "$OPENCODE_DIR/command/$filename"
00125| fi
00126| else
00127| echo_error "Failed to download $file"
00128| echo_error "Please check your internet connection and try again"
00129| exit 1
00130| fi
00131| done
00132|
00133| echo_info "All files downloaded successfully"
00134|
00135| # Install dependencies
00136| echo_step "4/5 Installing dependencies..."
00137|
00138| DEPS_EXIST=false
00139| if [ -d "$OPENCODE_DIR/plugin/node_modules/js-tiktoken" ] && [ -d "$OPENCODE_DIR/plugin/node_modules/@huggingface/transformers" ]; then
00140| DEPS_EXIST=true
00141| fi
00142|
00143| if [ "$UPDATE_MODE" = true ] && [ "$DEPS_EXIST" = true ]; then
00144| echo_info "Update mode: Dependencies already installed, skipping..."
00145| else
00146| echo_info "This may take 1-2 minutes..."
00147| cd "$OPENCODE_DIR/plugin"
00148| if npm install --prefix "$OPENCODE_DIR/plugin" js-tiktoken@1.0.15 @huggingface/transformers@3.1.2 --save; then
00149| echo_info "Dependencies installed successfully"
00150| else
00151| echo_error "Failed to install dependencies"
00152| echo_error "You can try running manually: cd ~/.config/opencode/plugin && npm install"
00153| exit 1
00154| fi
00155| fi
00156|
00157| # Verify installation
00158| echo_step "5/5 Verifying installation..."
00159|
00160| REQUIRED_FILES=(
00161| "$OPENCODE_DIR/plugin/tokenscope.ts"
00162| "$OPENCODE_DIR/plugin/lib/types.ts"
00163| "$OPENCODE_DIR/plugin/lib/config.ts"
00164| "$OPENCODE_DIR/plugin/lib/tokenizer.ts"
00165| "$OPENCODE_DIR/plugin/lib/analyzer.ts"
00166| "$OPENCODE_DIR/plugin/lib/cost.ts"
00167| "$OPENCODE_DIR/plugin/lib/subagent.ts"
00168| "$OPENCODE_DIR/plugin/lib/formatter.ts"
00169| "$OPENCODE_DIR/plugin/models.json"
00170| "$OPENCODE_DIR/plugin/node_modules/js-tiktoken"
00171| "$OPENCODE_DIR/plugin/node_modules/@huggingface/transformers"
00172| "$OPENCODE_DIR/command/tokenscope.md"
00173| )
00174|
00175| all_present=true
00176| for file in "${REQUIRED_FILES[@]}"; do
00177| if [ ! -e "$file" ]; then
00178| echo_warn "Missing: $file"
00179| all_present=false
00180| fi
00181| done
00182|
00183| if [ "$all_present" = true ]; then
00184| echo_info "All files verified"
00185| else
00186| echo_error "Some files are missing"
00187| exit 1
00188| fi
00189|
00190| # Get installed version
00191| INSTALLED_VERSION=$(grep -o '"version": *"[^"]*"' "$OPENCODE_DIR/plugin/package.json" | cut -d'"' -f4)
00192|
00193| echo ""
00194| echo "╔════════════════════════════════════════════════════════════╗"
00195| if [ "$UPDATE_MODE" = true ]; then
00196| echo "║ Update Complete! ║"
00197| else
00198| echo "║ Installation Complete! ║"
00199| fi
00200| echo "╚════════════════════════════════════════════════════════════╝"
00201| echo ""
00202| echo_info "Version: $INSTALLED_VERSION"
00203| echo_info "Plugin installed at: $OPENCODE_DIR/plugin/tokenscope.ts"
00204| echo_info "Command installed at: $OPENCODE_DIR/command/tokenscope.md"
00205| echo ""
00206| echo_step "Next steps:"
00207| echo " 1. Restart OpenCode"
00208| echo " 2. Type /tokenscope in any session"
00209| echo " 3. View full report: cat token-usage-output.txt"
00210| echo ""
00211| echo_info "For help and documentation, visit:"
00212| echo_info "$REPO_URL"
00213| echo ""
00214|
(End of file - total 214 lines)
</file>
mkdir -p "$OPENCODE_DIR/plugin"
mkdir -p "$OPENCODE_DIR/plugin/lib"
mkdir -p "$OPENCODE_DIR/command"
mkdir -p "$OPENCODE_DIR/plugin"
mkdir -p "$OPENCODE_DIR/plugin/tokenscope-lib"
mkdir -p "$OPENCODE_DIR/command"
FILES=(
"plugin/tokenscope.ts"
"plugin/lib/types.ts"
"plugin/lib/config.ts"
"plugin/lib/tokenizer.ts"
"plugin/lib/analyzer.ts"
"plugin/lib/cost.ts"
"plugin/lib/subagent.ts"
"plugin/lib/formatter.ts"
"plugin/models.json"
"plugin/package.json"
"plugin/install.sh"
"command/tokenscope.md"
)
FILES=(
"plugin/tokenscope.ts"
"plugin/tokenscope-lib/types.ts"
"plugin/tokenscope-lib/config.ts"
"plugin/tokenscope-lib/tokenizer.ts"
"plugin/tokenscope-lib/analyzer.ts"
"plugin/tokenscope-lib/cost.ts"
"plugin/tokenscope-lib/subagent.ts"
"plugin/tokenscope-lib/formatter.ts"
"plugin/models.json"
"plugin/package.json"
"plugin/install.sh"
"command/tokenscope.md"
)
if [ "$dir" = "plugin" ]; then
mv "$TEMP_DIR/$filename" "$OPENCODE_DIR/plugin/$filename"
elif [ "$dir" = "plugin/lib" ]; then
mv "$TEMP_DIR/$filename" "$OPENCODE_DIR/plugin/lib/$filename"
else
mv "$TEMP_DIR/$filename" "$OPENCODE_DIR/command/$filename"
fi
if [ "$dir" = "plugin" ]; then
mv "$TEMP_DIR/$filename" "$OPENCODE_DIR/plugin/$filename"
elif [ "$dir" = "plugin/tokenscope-lib" ]; then
mv "$TEMP_DIR/$filename" "$OPENCODE_DIR/plugin/tokenscope-lib/$filename"
else
mv "$TEMP_DIR/$filename" "$OPENCODE_DIR/command/$filename"
fi
REQUIRED_FILES=(
"$OPENCODE_DIR/plugin/tokenscope.ts"
"$OPENCODE_DIR/plugin/lib/types.ts"
"$OPENCODE_DIR/plugin/lib/config.ts"
"$OPENCODE_DIR/plugin/lib/tokenizer.ts"
"$OPENCODE_DIR/plugin/lib/analyzer.ts"
"$OPENCODE_DIR/plugin/lib/cost.ts"
"$OPENCODE_DIR/plugin/lib/subagent.ts"
"$OPENCODE_DIR/plugin/lib/formatter.ts"
"$OPENCODE_DIR/plugin/models.json"
"$OPENCODE_DIR/plugin/node_modules/js-tiktoken"
"$OPENCODE_DIR/plugin/node_modules/@huggingface/transformers"
"$OPENCODE_DIR/command/tokenscope.md"
)
REQUIRED_FILES=(
"$OPENCODE_DIR/plugin/tokenscope.ts"
"$OPENCODE_DIR/plugin/tokenscope-lib/types.ts"
"$OPENCODE_DIR/plugin/tokenscope-lib/config.ts"
"$OPENCODE_DIR/plugin/tokenscope-lib/tokenizer.ts"
"$OPENCODE_DIR/plugin/tokenscope-lib/analyzer.ts"
"$OPENCODE_DIR/plugin/tokenscope-lib/cost.ts"
"$OPENCODE_DIR/plugin/tokenscope-lib/subagent.ts"
"$OPENCODE_DIR/plugin/tokenscope-lib/formatter.ts"
"$OPENCODE_DIR/plugin/models.json"
"$OPENCODE_DIR/plugin/node_modules/js-tiktoken"
"$OPENCODE_DIR/plugin/node_modules/@huggingface/transformers"
"$OPENCODE_DIR/command/tokenscope.md"
)
Now updating the README:
### File Structure
```
plugin/
├── tokenscope.ts # Main entry point - Plugin export
├── lib/
│ ├── types.ts # All interfaces and type definitions
│ ├── config.ts # Constants, model maps, pricing loader
│ ├── tokenizer.ts # TokenizerManager class
│ ├── analyzer.ts # ModelResolver, ContentCollector, TokenAnalysisEngine
│ ├── cost.ts # CostCalculator class
│ ├── subagent.ts # SubagentAnalyzer class
│ └── formatter.ts # OutputFormatter class
├── models.json # Pricing data for 41+ models
├── package.json # Plugin metadata
└── install.sh # Installation script
```
### File Structure
```
plugin/
├── tokenscope.ts # Main entry point - Plugin export
├── tokenscope-lib/
│ ├── types.ts # All interfaces and type definitions
│ ├── config.ts # Constants, model maps, pricing loader
│ ├── tokenizer.ts # TokenizerManager class
│ ├── analyzer.ts # ModelResolver, ContentCollector, TokenAnalysisEngine
│ ├── cost.ts # CostCalculator class
│ ├── subagent.ts # SubagentAnalyzer class
│ └── formatter.ts # OutputFormatter class
├── models.json # Pricing data for 41+ models
├── package.json # Plugin metadata
└── install.sh # Installation script
```
1. **TokenizerManager** (`lib/tokenizer.ts`): Loads and caches tokenizers (tiktoken, transformers)
2. **ModelResolver** (`lib/analyzer.ts`): Detects model and selects appropriate tokenizer
3. **ContentCollector** (`lib/analyzer.ts`): Extracts content from session messages, including tool call counts
4. **TokenAnalysisEngine** (`lib/analyzer.ts`): Counts tokens and applies API telemetry adjustments
5. **CostCalculator** (`lib/cost.ts`): Calculates costs from pricing database with cache-aware pricing
6. **SubagentAnalyzer** (`lib/subagent.ts`): Recursively fetches and analyzes child sessions from Task tool calls
7. **OutputFormatter** (`lib/formatter.ts`): Generates visual reports with charts and summaries
1. **TokenizerManager** (`tokenscope-lib/tokenizer.ts`): Loads and caches tokenizers (tiktoken, transformers)
2. **ModelResolver** (`tokenscope-lib/analyzer.ts`): Detects model and selects appropriate tokenizer
3. **ContentCollector** (`tokenscope-lib/analyzer.ts`): Extracts content from session messages, including tool call counts
4. **TokenAnalysisEngine** (`tokenscope-lib/analyzer.ts`): Counts tokens and applies API telemetry adjustments
5. **CostCalculator** (`tokenscope-lib/cost.ts`): Calculates costs from pricing database with cache-aware pricing
6. **SubagentAnalyzer** (`tokenscope-lib/subagent.ts`): Recursively fetches and analyzes child sessions from Task tool calls
7. **OutputFormatter** (`tokenscope-lib/formatter.ts`): Generates visual reports with charts and summaries
Now let me commit all these changes:
On branch refactor-the-code
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: plugin/lib/.gitkeep -> plugin/tokenscope-lib/.gitkeep
renamed: plugin/lib/analyzer.ts -> plugin/tokenscope-lib/analyzer.ts
renamed: plugin/lib/config.ts -> plugin/tokenscope-lib/config.ts
renamed: plugin/lib/cost.ts -> plugin/tokenscope-lib/cost.ts
renamed: plugin/lib/formatter.ts -> plugin/tokenscope-lib/formatter.ts
renamed: plugin/lib/subagent.ts -> plugin/tokenscope-lib/subagent.ts
renamed: plugin/lib/tokenizer.ts -> plugin/tokenscope-lib/tokenizer.ts
renamed: plugin/lib/types.ts -> plugin/tokenscope-lib/types.ts
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
modified: plugin/install.sh
modified: plugin/tokenscope.ts
[refactor-the-code 99826bd] refactor: rename lib/ to tokenscope-lib/ to avoid conflicts
11 files changed, 32 insertions(+), 32 deletions(-)
rename plugin/{lib => tokenscope-lib}/.gitkeep (100%)
rename plugin/{lib => tokenscope-lib}/analyzer.ts (100%)
rename plugin/{lib => tokenscope-lib}/config.ts (100%)
rename plugin/{lib => tokenscope-lib}/cost.ts (100%)
rename plugin/{lib => tokenscope-lib}/formatter.ts (100%)
rename plugin/{lib => tokenscope-lib}/subagent.ts (100%)
rename plugin/{lib => tokenscope-lib}/tokenizer.ts (100%)
rename plugin/{lib => tokenscope-lib}/types.ts (100%)
Done! The directory has been renamed from lib/ to tokenscope-lib/ to avoid potential conflicts with other plugins.
Changes made:
- Renamed plugin/lib/ to plugin/tokenscope-lib/
- Updated imports in tokenscope.ts to use ./tokenscope-lib/
- Updated install.sh paths (directory creation, file downloads, verification)
- Updated README architecture section
Commit: refactor: rename lib/ to tokenscope-lib/ to avoid conflicts
If I now want to realse this new version, i first merge it then make a new release right?
Yes, exactly! The typical flow is:
1. Merge the branch to main
git checkout main
git merge refactor-the-code
git push origin main2. Create a release/tag
git tag v1.3.0
git push origin v1.3.0 Or use GitHub's release UI / gh CLI:
gh release create v1.3.0 --title "v1.3.0" --notes "Multi-file plugin architecture"Since the version is already bumped to 1.3.0 in package.json, you're ready to go once merged.
Would you like me to help with the merge or create a PR for you to review first?
what would be some good release notes for this
Based on the changes made, here are some release notes options:
---
## Option 1: Concise
## What's Changed
### Refactored to Multi-File Architecture
The plugin has been restructured from a single 1340-line file into 8 focused modules for better maintainability:
- tokenscope.ts - Main entry point
- tokenscope-lib/types.ts - Type definitions
- tokenscope-lib/config.ts - Model maps and pricing loader
- tokenscope-lib/tokenizer.ts - Token counting
- tokenscope-lib/analyzer.ts - Session analysis
- tokenscope-lib/cost.ts - Cost calculation
- tokenscope-lib/subagent.ts - Child session analysis
- tokenscope-lib/formatter.ts - Report formatting
### No Breaking Changes
- All functionality remains the same
- Install/update process unchanged
- Output format unchanged
Full Changelog: https://github.com/ramtinJ95/opencode-tokenscope/compare/v1.2.1...v1.3.0
---
## Option 2: More Detailed
## v1.3.0 - Multi-File Architecture
### Overview
This release restructures the plugin codebase for improved maintainability and extensibility. No user-facing changes - the plugin works exactly as before.
### Changes
Architecture
- Split monolithic tokenscope.ts (1340 lines) into 8 focused modules
- Renamed module directory to tokenscope-lib/ to prevent conflicts with other plugins
File Structure
Why this matters
- Easier to maintain and extend
- Each module has a single responsibility
- No conflicts with other OpenCode plugins using lib/
### Upgrading
Run the standard update command:
Or reinstall:Full Changelog: https://github.com/ramtinJ95/opencode-tokenscope/compare/v1.2.1...v1.3.0---
Which style do you prefer, or would you like me to adjust either of these?