@gitset-dev/cli 1.2.0 → 2.0.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.
Files changed (41) hide show
  1. package/{LICENSE.md → LICENSE} +1 -1
  2. package/README.md +80 -159
  3. package/index.js +230 -0
  4. package/lib/ai/capabilities.js +81 -0
  5. package/lib/ai/errors.js +115 -0
  6. package/lib/ai/index.js +98 -0
  7. package/lib/ai/providers/anthropic.js +62 -0
  8. package/lib/ai/providers/gemini.js +77 -0
  9. package/lib/ai/providers/mock.js +41 -0
  10. package/lib/ai/providers/openai-compatible.js +72 -0
  11. package/lib/ai/retry.js +31 -0
  12. package/lib/cli-commit.js +143 -0
  13. package/lib/cli-config.js +207 -0
  14. package/lib/cli-issue.js +144 -0
  15. package/lib/cli-pr.js +168 -0
  16. package/lib/cli-readme.js +153 -0
  17. package/lib/commit-local.js +67 -0
  18. package/lib/config.js +134 -0
  19. package/lib/generate-local.js +59 -0
  20. package/lib/labels-ai.js +41 -0
  21. package/lib/prompts/defaults.js +191 -0
  22. package/lib/prompts/index.js +79 -0
  23. package/lib/setup-wizard.js +115 -0
  24. package/npm-shrinkwrap.json +566 -0
  25. package/package.json +35 -35
  26. package/src/commands/dependabot-resolver.js +314 -0
  27. package/src/commands/gitignore.js +110 -0
  28. package/src/commands/init.js +38 -0
  29. package/src/commands/labelspack.js +94 -0
  30. package/src/commands/license.js +208 -0
  31. package/src/commands/release.js +180 -0
  32. package/src/commands/repo.js +176 -0
  33. package/src/commands/status.js +56 -0
  34. package/src/commands/template.js +92 -0
  35. package/src/commands/tree.js +77 -0
  36. package/src/utils/dependabot-analyzer.js +101 -0
  37. package/src/utils/labels.js +102 -0
  38. package/src/utils/theme.js +70 -0
  39. package/src/utils/ui.js +173 -0
  40. package/.github/workflows/npm_publish.yml +0 -38
  41. package/src/index.js +0 -505
@@ -357,7 +357,7 @@ Exhibit A - Source Code Form License Notice
357
357
 
358
358
  This Source Code Form is subject to the terms of the Mozilla Public
359
359
  License, v. 2.0. If a copy of the MPL was not distributed with this
360
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
360
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
361
361
 
362
362
  If it is not possible or desirable to put the notice in a particular
363
363
  file, then You may include the notice in a location (such as a LICENSE
package/README.md CHANGED
@@ -1,191 +1,112 @@
1
1
  <div align="center">
2
- <img src="https://github.com/imprvhub/gitset/blob/main/public/favicon-192.png" alt="GitSet CLI" />
3
- <br>
4
- <a href="https://badge.fury.io/js/@gitset-dev%2Fcli">
5
- <img src="https://img.shields.io/npm/v/@gitset-dev/cli?color=%237BFEF5" alt="npm version" />
6
- </a>
7
- <a href="https://opensource.org/licenses/MPL-2.0">
8
- <img src="https://img.shields.io/badge/License-MPL_2.0-%237BFEF5" alt="License: MPL 2.0" />
9
- </a>
10
- <br>
11
- <br>
12
- <h3>
13
- GitSet CLI - AI-Driven Commit Message Generation
14
- </h3>
15
- </div>
16
-
17
- ## Overview
2
+ <a href="https://gitset.dev" target="_blank">
3
+ <img src="https://raw.githubusercontent.com/gitset-dev/gitset/main/public/cli/favicon-192.png" alt="Gitset CLI" width="88" />
4
+ </a>
18
5
 
19
- GitSet CLI is an integral component of the GitSet.dev ecosystem, designed to enhance Git workflow automation through AI-driven commit message generation. By leveraging Google's Gemini Pro AI technology, it provides intelligent analysis of staged changes to generate contextually appropriate commit messages, supporting both semantic and personalized formatting styles.
6
+ <h1>Gitset CLI</h1>
20
7
 
21
- ## Key Capabilities
8
+ <p><strong><code>Draft. Refine. Ship.</code></strong></p>
22
9
 
23
- The GitSet CLI enhances repository management through:
24
-
25
- - **AI-Powered Analysis**: Utilizes advanced AI processing to analyze staged changes and generate contextually appropriate commit messages
26
- - **Semantic Versioning Support**: Implements conventional commit standards for maintaining structured version control
27
- - **Style Adaptation**: Analyzes existing commit patterns to match personal or team commit message conventions
28
- - **Efficient Processing**: Provides rapid analysis and suggestion generation while maintaining minimal resource utilization
29
- - **Cross-Platform Architecture**: Ensures consistent operation across various operating systems and environments
30
- - **License Management**: Flexible licensing system with both free and pro tiers for different usage needs
31
- - **Usage Tracking**: Built-in monitoring of API usage and license status
10
+ <p>
11
+ <img src="https://img.shields.io/badge/license-MPL--2.0-blue?style=flat-square" alt="MPL-2.0" />
12
+ <img src="https://img.shields.io/badge/model-BYOAI-white?style=flat-square" alt="BYOAI" />
13
+ <img src="https://img.shields.io/badge/node-%E2%89%A518-green?style=flat-square" alt="node >= 18" />
14
+ </p>
15
+ </div>
32
16
 
33
- ## System Requirements
17
+ ---
34
18
 
35
- - Node.js Runtime Environment (Version 18.0.0 or higher)
36
- - Git (Installed and configured)
37
- - Active internet connection for AI processing
19
+ Gitset is an open-source toolkit for everything around your code on GitHub:
20
+ commit messages, issues, pull requests, release notes, READMEs, labels, and
21
+ repository upkeep. Every tool drafts from your repository's real context; you
22
+ refine the draft until it ships. This package is the **CLI** — the same
23
+ tools, in your terminal.
38
24
 
39
- ## Installation Process
25
+ **The CLI runs entirely on your machine.** There is no account, no login, and
26
+ no telemetry. Your provider keys live in `~/.gitset` with owner-only
27
+ permissions, and your code goes from your machine to your AI provider —
28
+ nowhere else. It never contacts a Gitset server.
40
29
 
41
- Install the GitSet CLI globally via npm:
30
+ ## Install
42
31
 
43
- ```bash
32
+ ```sh
44
33
  npm install -g @gitset-dev/cli
45
34
  ```
46
35
 
47
- ## Implementation Guide
48
-
49
- ### Basic Usage
36
+ Requires Node.js 18+. Commands that publish to GitHub (`--create`,
37
+ `--apply`) use the [GitHub CLI](https://cli.github.com) (`gh`) with your
38
+ existing login.
50
39
 
51
- 1. Stage your modifications:
52
- ```bash
53
- git add .
54
- ```
40
+ ## Quick start
55
41
 
56
- 2. Generate commit message suggestions:
57
- ```bash
58
- # Semantic versioning format (default)
59
- gitset suggest
42
+ ```sh
43
+ # interactive setup — pick a provider, paste your key, pick a model
44
+ gitset config
60
45
 
61
- # Custom formatting style
62
- gitset suggest --mode custom
46
+ # stage changes, draft a commit message, refine it, commit
47
+ git add -A
48
+ gitset commit
63
49
  ```
64
50
 
65
- 3. Implement the generated message:
66
- ```bash
67
- git commit -m "generated_message"
68
- ```
69
-
70
- ### License Management
71
-
72
- Activate your GitSet license:
73
- ```bash
74
- # Activate with license key
75
- gitset activate <license-key>
51
+ `gitset config` walks you through it (provider list, masked key entry, a
52
+ curated model per provider with "recommended" pre-selected). Prefer flags or
53
+ scripting? `gitset config set anthropic --key sk-... --default` still works
54
+ exactly as before. Providers: `anthropic` · `openai` · `gemini` ·
55
+ `openrouter` · `custom` (any OpenAI-compatible endpoint). Override per run
56
+ with `--provider` and `--model`.
76
57
 
77
- # Check license status and usage
78
- gitset status
58
+ Terminal on a light background? `gitset config theme light` switches the
59
+ accent color to one tuned for readability there (defaults to a dark-terminal
60
+ palette).
79
61
 
80
- # Remove current license
81
- gitset deactivate
82
- ```
62
+ ## Commands
83
63
 
84
- ### Operational Modes
64
+ Drafting (uses your provider key):
85
65
 
86
- #### Semantic Mode (Default Implementation)
87
- Implements conventional commit standards to generate structured, semantic commit messages. This mode is optimized for maintaining consistent and professional Git history in enterprise environments.
66
+ | Command | Drafts |
67
+ |---|---|
68
+ | `gitset commit` | A commit message from your staged changes, with interactive refine |
69
+ | `gitset pr` | A pull-request description from the branch diff (`--create` opens it via `gh`) |
70
+ | `gitset issue -m "..."` | A structured GitHub issue from one sentence + repo context |
71
+ | `gitset readme` | A README from your tracked files (`--template` uses yours as the base) |
72
+ | `gitset release` | Release notes from a commit range (default: since the last tag) |
73
+ | `gitset gitignore` | A `.gitignore` for the detected stack |
74
+ | `gitset repo about` | A repository description + topics, applied via `gh` |
88
75
 
89
- Example output:
90
- ```bash
91
- $ gitset suggest
92
- ✨ Generated Suggestion:
93
- ------------------------
94
- feat: Implement JWT authentication system
76
+ Local tools (no AI):
95
77
 
96
- - Add token generation and validation mechanisms
97
- - Integrate login and registration endpoints
98
- - Configure route protection middleware
99
- ```
78
+ | Command | Does |
79
+ |---|---|
80
+ | `gitset labelspack` | Applies your reusable label set (`~/.gitset/labels.md`) to the repo |
81
+ | `gitset repo backup` | Writes a scheduled mirror-backup GitHub Actions workflow |
82
+ | `gitset repo license` | Generates a LICENSE file, fully offline |
83
+ | `gitset template` / `gitset init` | Manage / scaffold your local templates |
84
+ | `gitset dependabot` | Resolve open Dependabot alerts |
85
+ | `gitset tree` · `gitset status` | Repository structure · git + provider status |
100
86
 
101
- #### Custom Mode
102
- Analyzes existing commit patterns to generate messages that align with established conventions:
103
-
104
- - Evaluates recent commit history (default: 20 commits) for pattern recognition
105
- - Adapts to existing formatting conventions and structural patterns
106
- - Maintains sequential naming conventions if detected
107
- - Preserves emoji usage patterns and placement
108
- - Replicates capitalization and punctuation styles
109
- - Balances descriptive content with stylistic consistency
110
-
111
- Example of style adaptation:
112
- ```bash
113
- # Given existing commit pattern:
114
- FEATURE_123: Enhanced login interface 🚀
115
- FEATURE_124: Updated navigation system ✨
116
- FEATURE_125: Resolved routing conflicts 🔧
117
-
118
- # Generated suggestion maintains consistency:
119
- FEATURE_126: Implemented user preferences 🎯
120
- ```
87
+ Common flags: `--provider` `--model` `--yes` `--print` `--json`. Run
88
+ `gitset help <command>` for everything else.
121
89
 
122
- ## Configuration Reference
90
+ ## Templates
123
91
 
124
- ### Command Structure
92
+ Define your commit style, issue structure, PR format, README skeleton, or
93
+ release-notes layout once in `~/.gitset/templates` and every draft follows
94
+ it — the same define-once-reuse-everywhere model as the
95
+ [web app](https://gitset.dev). `gitset template edit <commit|pr|issue|readme|release>`
96
+ opens (or creates) one in `$EDITOR` — no need to hunt for the file path.
125
97
 
126
- Available commands:
127
- - `gitset suggest` - Initiates commit message generation based on staged changes
128
- - `gitset activate` - Activates GitSet with a license key
129
- - `gitset status` - Checks current license status and usage
130
- - `gitset deactivate` - Removes current license configuration
131
- - `gitset help` - Displays detailed usage information
98
+ ## Configuration
132
99
 
133
- ### Available Parameters
100
+ Keys and defaults: `~/.gitset/config.json` (created with `0600`
101
+ permissions). Templates: `~/.gitset/templates`. Label pack:
102
+ `~/.gitset/labels.md`. Delete `~/.gitset` and every trace is gone.
134
103
 
135
- For suggest command:
136
- - `--mode <mode>` - Specifies generation mode ('semantic' or 'custom')
137
- - `--commit-count <count>` - Defines number of commits to analyze (default: 20)
138
- - `--version` - Displays CLI version information
139
- - `--help` - Provides command usage information
104
+ ## Contributing
140
105
 
141
- ## Plans and Pricing
106
+ Issues and pull requests are welcome:
107
+ [gitset-dev/gitset-cli-v2](https://github.com/gitset-dev/gitset-cli-v2).
142
108
 
143
- - **Basic (Free)**
144
- - 10 requests per month
145
- - Basic commit message generation
146
- - Semantic and custom modes support
147
-
148
- - **Pro**
149
- - Unlimited requests
150
- - Advanced features and priority support
151
- - Visit https://gitset.dev/pricing for details
152
-
153
- ## Development Contribution
154
-
155
- We welcome contributions to enhance the GitSet CLI. Please follow these steps:
156
-
157
- 1. Fork the repository
158
- 2. Create a feature branch:
159
- ```bash
160
- git checkout -b feature/enhancement-description
161
- ```
162
- 3. Implement modifications:
163
- ```bash
164
- git commit -m 'feat: Add enhancement description'
165
- ```
166
- 4. Push changes:
167
- ```bash
168
- git push origin feature/enhancement-description
169
- ```
170
- 5. Submit a Pull Request
171
-
172
- ## License Information
173
-
174
- This project operates under the Mozilla Public License 2.0 - refer to [LICENSE.md](LICENSE.md) for detailed terms.
175
-
176
- ## Support Channels
177
-
178
- - Technical Support: support@gitset.dev
179
- - Contact Form: https://gitset.dev/contact
180
- - Issue Tracking: https://github.com/gitset-dev/gitset-cli/issues
181
- - Account Management: https://gitset.dev/account
182
-
183
- ## Acknowledgments
184
-
185
- - Contributors who have helped improve this tool
186
- - Commander.js for CLI framework support
187
- - Google's Gemini Pro for AI capabilities
188
-
189
- ---
109
+ ## License
190
110
 
191
- Part of the [GitSet.dev](https://gitset.dev) ecosystem - Smart AI Documentation & Version Control for GitHub Repositories.
111
+ [MPL-2.0](LICENSE) © Iván Luna. The Gitset name and logo are not covered by
112
+ the code license.
package/index.js ADDED
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Gitset CLI — everything around your code, drafted in your terminal (BYOAI).
6
+ *
7
+ * Slim dispatcher. Every AI command runs LOCALLY with the user's own
8
+ * provider key (managed by `gitset config`, stored in ~/.gitset, never
9
+ * transmitted). There is NO login and NO Gitset backend — the entire old
10
+ * gitset_key / remote-API system has been removed.
11
+ */
12
+
13
+ const theme = require('./src/utils/theme');
14
+
15
+ function showHelp() {
16
+ console.log(`${theme.bold('gitset')} — everything around your code, drafted in your terminal (BYOAI)
17
+
18
+ ${theme.bold('First time?')} Run ${theme.accent('gitset config')} — an interactive wizard sets up your AI provider in under a minute.
19
+
20
+ ${theme.bold('AI commands')} (use your own provider key):
21
+ commit Generate a commit message from staged changes
22
+ pr Generate a pull-request description from the branch diff
23
+ issue Draft a GitHub issue from a description
24
+ readme Generate a README from repo context
25
+ release Generate release notes from the commit range
26
+ gitignore Generate a .gitignore for the detected stack
27
+ repo about AI repo description + topics, applied via gh
28
+
29
+ ${theme.bold('Local tools')} (no AI):
30
+ repo license Generate a LICENSE file (offline)
31
+ repo backup Write a secure mirror-backup GitHub Actions workflow
32
+ tree Print the repository structure
33
+ labelspack Apply a label pack to the current repo
34
+ dependabot Resolve Dependabot alerts
35
+ status Show git + provider status
36
+ template Manage local templates (~/.gitset/templates), edit <tool> to customize
37
+ init Scaffold local templates
38
+
39
+ ${theme.bold('Setup')}:
40
+ config interactive setup wizard
41
+ config set <provider> --key <key> [--model m] [--default]
42
+ config list | remove <provider> | theme <dark|light> | path
43
+
44
+ ${theme.bold('Common flags')}: --provider <p> --model <m> --yes --json --print
45
+ Providers: anthropic · openai · gemini · openrouter · custom
46
+ Run ${theme.accent('gitset help <command>')} or ${theme.accent('gitset <command> --help')} for command details.
47
+
48
+ Gitset is open source & BYOAI: no accounts, no quotas, keys stay on your machine.
49
+ ${theme.bold('Draft. Refine. Ship.')} — https://gitset.dev`);
50
+ }
51
+
52
+ const USAGE = {
53
+ commit: `Usage: gitset commit [flags]
54
+ Generate a commit message from staged changes, with interactive refine.
55
+ --provider <p> override the default provider for this run
56
+ --model <m> override the model
57
+ --style <s> commit style (default: conventional)
58
+ --all, -a git add -A before generating
59
+ --yes accept the first result (non-interactive)
60
+ --print print the message only; do not commit
61
+ --json machine-readable output
62
+ Exit codes: 0 ok · 1 usage/git · 2 provider error`,
63
+ pr: `Usage: gitset pr [flags]
64
+ Generate a pull-request description from the branch diff.
65
+ --base <branch> base branch (default: detected)
66
+ --title <t> PR title (default: generated)
67
+ --create open the PR via gh after accepting
68
+ --provider <p> · --model <m> · --yes · --print · --json
69
+ Exit codes: 0 ok · 1 usage · 2 provider error`,
70
+ issue: `Usage: gitset issue --message <description> [flags]
71
+ Draft a GitHub issue from a description (+ local repo context).
72
+ --message, -m what the issue is about (required)
73
+ --title <t> issue title (default: generated)
74
+ --create create the issue via gh after accepting
75
+ --provider <p> · --model <m> · --yes · --print · --json
76
+ Exit codes: 0 ok · 1 usage · 2 provider error`,
77
+ readme: `Usage: gitset readme [flags]
78
+ Generate a README from local repo context (git-tracked files).
79
+ --output <file> write path (default: README.md)
80
+ --template <f> use a template file as the structural base
81
+ --force overwrite an existing file
82
+ --provider <p> · --model <m> · --yes · --print · --json
83
+ Exit codes: 0 ok · 1 usage/io · 2 provider error`,
84
+ release: `Usage: gitset release [flags]
85
+ Generate release notes from a commit range.
86
+ --from <ref> start ref (default: last tag)
87
+ --to <ref> end ref (default: HEAD)
88
+ --version <v> release version/tag name
89
+ --provider <p> · --model <m>`,
90
+ gitignore: `Usage: gitset gitignore [flags]
91
+ Generate a .gitignore for the locally detected stack.
92
+ --select type the stacks yourself instead of auto-detect
93
+ --append append to the existing .gitignore
94
+ --force overwrite the existing .gitignore
95
+ --provider <p> · --model <m> · --print`,
96
+ repo: `Usage: gitset repo <about|license|backup> [flags]
97
+ about AI description + topics from local context, applied via gh
98
+ (--apply · --yes · --provider <p> · --model <m>)
99
+ license generate a LICENSE file (offline; see gitset license --list)
100
+ backup write a secure mirror-backup GitHub Actions workflow`,
101
+ license: `Usage: gitset license [--id <spdx>] [--owner <name>] [--list] [--force]
102
+ Fully offline LICENSE generator (MIT, ISC, BSD, Apache-2.0, Unlicense).`,
103
+ tree: `Usage: gitset tree [flags]
104
+ Print the repository structure.
105
+ --depth <n> limit depth
106
+ --all include dotfiles
107
+ --exclude <pat> exclude pattern (repeatable)
108
+ --no-gitignore don't honor .gitignore`,
109
+ labelspack: `Usage: gitset labelspack [flags]
110
+ Manage & apply a label pack (local pack + gh).
111
+ (none) list the pack
112
+ --apply create/update the labels in the current repo via gh
113
+ --init write the default pack to ~/.gitset/labels.md
114
+ --add --name <x> --color <hex> --description "..." add a label
115
+ --sync pull the repo's labels into the local pack`,
116
+ dependabot: `Usage: gitset dependabot [--resolve] [--dry-run] [--save-dev]
117
+ Resolve Dependabot alerts for the current repo (local + gh).`,
118
+ status: `Usage: gitset status
119
+ Show git + configured-provider status.`,
120
+ template: `Usage: gitset template <list|show|edit|path>
121
+ Manage local templates in ~/.gitset/templates.
122
+ list show templates you have
123
+ show <name> print a template's contents
124
+ edit <name> open (or create) a template in $EDITOR
125
+ path print the templates directory`,
126
+ init: `Usage: gitset init
127
+ Scaffold the local template directory.`,
128
+ config: `Usage: gitset config [set|list|remove|theme|path]
129
+ (no args) interactive setup wizard
130
+ set interactive wizard, or: set <provider> --key <key> [--model m] [--base-url u] [--default]
131
+ list show configured providers (keys never printed)
132
+ remove <provider>
133
+ theme <dark|light> colors tuned for your terminal background
134
+ path print the config file location
135
+ Providers: anthropic · openai · gemini · openrouter · custom`,
136
+ };
137
+
138
+ function showCommandHelp(cmd) {
139
+ if (USAGE[cmd]) { console.log(USAGE[cmd]); return 0; }
140
+ console.error(`${theme.error('✗')} Unknown command: ${cmd}`);
141
+ showHelp();
142
+ return 1;
143
+ }
144
+
145
+ function deprecatedAuth(name) {
146
+ console.log(`${theme.warn('ℹ')} \`gitset ${name}\` was removed — Gitset v2 is BYOAI, there is no login.
147
+ Configure a provider instead: ${theme.accent('gitset config')}`);
148
+ return 0;
149
+ }
150
+
151
+ async function main() {
152
+ const args = process.argv.slice(2);
153
+ const command = args[0];
154
+ const rest = args.slice(1);
155
+ let code = 0;
156
+
157
+ if (command === 'help' && rest[0]) {
158
+ process.exitCode = showCommandHelp(rest[0]);
159
+ return;
160
+ }
161
+ if (command && command !== 'help' && (rest.includes('--help') || rest.includes('-h'))) {
162
+ process.exitCode = showCommandHelp(command);
163
+ return;
164
+ }
165
+
166
+ switch (command) {
167
+ case 'commit':
168
+ code = await require('./lib/cli-commit').runCommitCommand(rest); break;
169
+ case 'pr':
170
+ code = await require('./lib/cli-pr').runPrCommand(rest); break;
171
+ case 'issue':
172
+ code = await require('./lib/cli-issue').runIssueCommand(rest); break;
173
+ case 'readme':
174
+ code = await require('./lib/cli-readme').runReadmeCommand(rest); break;
175
+ case 'gitignore':
176
+ code = await require('./src/commands/gitignore').runGitignoreCommand(rest); break;
177
+ case 'release':
178
+ code = await require('./src/commands/release')({
179
+ from: optVal(args, '--from'), to: optVal(args, '--to'), version: optVal(args, '--version'),
180
+ provider: optVal(args, '--provider'), model: optVal(args, '--model'),
181
+ }) || 0; break;
182
+
183
+ case 'config':
184
+ code = await require('./lib/cli-config').runConfigCommand(rest); break;
185
+
186
+ case 'repo':
187
+ code = await require('./src/commands/repo').runRepoCommand(rest); break;
188
+
189
+ case 'tree':
190
+ code = require('./src/commands/tree').runTreeCommand(rest); break;
191
+ case 'status':
192
+ code = require('./src/commands/status').runStatusCommand(); break;
193
+ case 'init':
194
+ code = require('./src/commands/init').runInitCommand(); break;
195
+ case 'template':
196
+ code = require('./src/commands/template').runTemplateCommand(rest); break;
197
+ case 'license':
198
+ code = await require('./src/commands/license').runLicenseCommand(rest); break;
199
+ case 'labelspack':
200
+ code = await require('./src/commands/labelspack').runLabelspackCommand(rest); break;
201
+ case 'dependabot':
202
+ code = (await require('./src/commands/dependabot-resolver')(null, rest)) || 0; break;
203
+
204
+ case 'auth': case 'verify': case 'logout':
205
+ code = deprecatedAuth(command); break;
206
+
207
+ case 'help': case '--help': case '-h': case undefined:
208
+ showHelp(); break;
209
+
210
+ case 'version': case '--version': case '-v':
211
+ console.log(require('./package.json').version); break;
212
+
213
+ default:
214
+ console.error(`${theme.error('✗')} Unknown command: ${command}`);
215
+ showHelp();
216
+ code = 1;
217
+ }
218
+
219
+ process.exitCode = code || 0;
220
+ }
221
+
222
+ function optVal(args, name) {
223
+ const i = args.indexOf(name);
224
+ return i !== -1 && args[i + 1] && !args[i + 1].startsWith('--') ? args[i + 1] : undefined;
225
+ }
226
+
227
+ main().catch((err) => {
228
+ console.error(`${theme.error('✗')} Fatal: ${err && err.message ? err.message : err}`);
229
+ process.exit(1);
230
+ });
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+
3
+ const PROVIDERS = Object.freeze({
4
+ anthropic: {
5
+ label: 'Anthropic (Claude)',
6
+ defaultModel: 'claude-sonnet-4-6',
7
+ models: ['claude-sonnet-4-6', 'claude-haiku-4-5'],
8
+ streaming: true,
9
+ jsonMode: false,
10
+ contextFloor: 200_000,
11
+ keyHint: 'sk-ant-...',
12
+ },
13
+ openai: {
14
+ label: 'OpenAI',
15
+ defaultModel: 'gpt-4o',
16
+ models: ['gpt-4o', 'gpt-4o-mini', 'gpt-4.1'],
17
+ streaming: true,
18
+ jsonMode: true,
19
+ contextFloor: 128_000,
20
+ keyHint: 'sk-...',
21
+ },
22
+ gemini: {
23
+ label: 'Google Gemini',
24
+ defaultModel: 'gemini-2.5-flash',
25
+ models: ['gemini-2.5-flash', 'gemini-2.5-pro'],
26
+ streaming: true,
27
+ jsonMode: true,
28
+ contextFloor: 1_000_000,
29
+ keyHint: 'AIza...',
30
+ },
31
+ openrouter: {
32
+ label: 'OpenRouter',
33
+ defaultModel: 'anthropic/claude-sonnet-4-6',
34
+ models: ['anthropic/claude-sonnet-4-6', 'openai/gpt-4o'],
35
+ streaming: true,
36
+ jsonMode: true,
37
+ contextFloor: 32_000,
38
+ keyHint: 'sk-or-...',
39
+ baseURL: 'https://openrouter.ai/api/v1',
40
+ },
41
+ deepseek: {
42
+ label: 'DeepSeek',
43
+ defaultModel: 'deepseek-chat',
44
+ models: ['deepseek-chat', 'deepseek-reasoner'],
45
+ streaming: true,
46
+ jsonMode: true,
47
+ contextFloor: 64_000,
48
+ keyHint: 'sk-...',
49
+ baseURL: 'https://api.deepseek.com',
50
+ },
51
+ mock: {
52
+ label: 'Mock (offline/testing)',
53
+ defaultModel: 'mock-1',
54
+ streaming: true,
55
+ jsonMode: true,
56
+ contextFloor: 1_000_000,
57
+ keyHint: 'any',
58
+ },
59
+ });
60
+
61
+ const SUPPORTED = Object.keys(PROVIDERS);
62
+
63
+ const FORBIDDEN_MODELS = Object.freeze([
64
+ 'claude-opus-4-8',
65
+ 'claude-fable-5',
66
+ 'claude-mythos-5',
67
+ 'claude-mythos-preview',
68
+ ]);
69
+
70
+ function isForbiddenModel(model) {
71
+ if (!model) return false;
72
+ const bare = String(model).trim().toLowerCase().split('/').pop();
73
+ return FORBIDDEN_MODELS.includes(bare);
74
+ }
75
+
76
+ function estimateTokens(text) {
77
+ if (!text) return 0;
78
+ return Math.ceil(String(text).length / 4);
79
+ }
80
+
81
+ module.exports = { PROVIDERS, SUPPORTED, FORBIDDEN_MODELS, isForbiddenModel, estimateTokens };