squads-cli 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +161 -4
- package/dist/{chunk-HKWCBCEK.js → chunk-4CMAEQQY.js} +6 -2
- package/dist/chunk-4CMAEQQY.js.map +1 -0
- package/dist/{chunk-NA3IECJA.js → chunk-N7KDWU4W.js} +155 -58
- package/dist/chunk-N7KDWU4W.js.map +1 -0
- package/dist/{chunk-7PRYDHZW.js → chunk-NHGLXN2F.js} +8 -6
- package/dist/chunk-NHGLXN2F.js.map +1 -0
- package/dist/{chunk-QPH5OR7J.js → chunk-O7UV3FWI.js} +139 -21
- package/dist/chunk-O7UV3FWI.js.map +1 -0
- package/dist/{chunk-BV6S5AWZ.js → chunk-ZTQ7ISUR.js} +28 -109
- package/dist/chunk-ZTQ7ISUR.js.map +1 -0
- package/dist/cli.js +5493 -7665
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +110 -2
- package/dist/index.js +302 -26
- package/dist/index.js.map +1 -1
- package/dist/{memory-ZXDXF6KF.js → memory-VNF2VFRB.js} +2 -2
- package/dist/{sessions-F6LRY7EN.js → sessions-6PB7ALCE.js} +3 -3
- package/dist/{squad-parser-MSYE4PXL.js → squad-parser-4BI3G4RS.js} +4 -2
- package/dist/templates/seed/BUSINESS_BRIEF.md.template +27 -0
- package/dist/templates/seed/CLAUDE.md.template +69 -0
- package/dist/templates/seed/config/provider.yaml +4 -0
- package/dist/templates/seed/hooks/settings.json.template +31 -0
- package/dist/templates/seed/memory/company/manager/state.md +16 -0
- package/dist/templates/seed/memory/engineering/issue-solver/state.md +12 -0
- package/dist/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
- package/dist/templates/seed/memory/marketing/content-drafter/state.md +12 -0
- package/dist/templates/seed/memory/operations/ops-lead/state.md +12 -0
- package/dist/templates/seed/memory/research/researcher/state.md +10 -0
- package/dist/templates/seed/skills/gh/SKILL.md +57 -0
- package/dist/templates/seed/skills/squads-cli/SKILL.md +88 -0
- package/dist/templates/seed/squads/company/SQUAD.md +49 -0
- package/dist/templates/seed/squads/company/company-critic.md +21 -0
- package/dist/templates/seed/squads/company/company-eval.md +21 -0
- package/dist/templates/seed/squads/company/event-dispatcher.md +21 -0
- package/dist/templates/seed/squads/company/goal-tracker.md +21 -0
- package/dist/templates/seed/squads/company/manager.md +66 -0
- package/dist/templates/seed/squads/engineering/SQUAD.md +48 -0
- package/dist/templates/seed/squads/engineering/code-reviewer.md +57 -0
- package/dist/templates/seed/squads/engineering/issue-solver.md +58 -0
- package/dist/templates/seed/squads/engineering/test-writer.md +50 -0
- package/dist/templates/seed/squads/intelligence/SQUAD.md +37 -0
- package/dist/templates/seed/squads/intelligence/intel-critic.md +36 -0
- package/dist/templates/seed/squads/intelligence/intel-eval.md +31 -0
- package/dist/templates/seed/squads/intelligence/intel-lead.md +71 -0
- package/dist/templates/seed/squads/marketing/SQUAD.md +47 -0
- package/dist/templates/seed/squads/marketing/content-drafter.md +71 -0
- package/dist/templates/seed/squads/marketing/growth-analyst.md +49 -0
- package/dist/templates/seed/squads/marketing/social-poster.md +44 -0
- package/dist/templates/seed/squads/operations/SQUAD.md +45 -0
- package/dist/templates/seed/squads/operations/finance-tracker.md +47 -0
- package/dist/templates/seed/squads/operations/goal-tracker.md +48 -0
- package/dist/templates/seed/squads/operations/ops-lead.md +58 -0
- package/dist/templates/seed/squads/research/SQUAD.md +38 -0
- package/dist/templates/seed/squads/research/analyst.md +27 -0
- package/dist/templates/seed/squads/research/research-critic.md +20 -0
- package/dist/templates/seed/squads/research/research-eval.md +20 -0
- package/dist/templates/seed/squads/research/researcher.md +28 -0
- package/dist/{terminal-JZSAQSN7.js → terminal-YKA4O5CX.js} +4 -2
- package/dist/{update-MAY6EXFQ.js → update-ALJKFFM7.js} +3 -2
- package/package.json +9 -22
- package/templates/seed/BUSINESS_BRIEF.md.template +27 -0
- package/templates/seed/CLAUDE.md.template +69 -0
- package/templates/seed/config/provider.yaml +4 -0
- package/templates/seed/hooks/settings.json.template +31 -0
- package/templates/seed/memory/company/manager/state.md +16 -0
- package/templates/seed/memory/engineering/issue-solver/state.md +12 -0
- package/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
- package/templates/seed/memory/marketing/content-drafter/state.md +12 -0
- package/templates/seed/memory/operations/ops-lead/state.md +12 -0
- package/templates/seed/memory/research/researcher/state.md +10 -0
- package/templates/seed/skills/gh/SKILL.md +57 -0
- package/templates/seed/skills/squads-cli/SKILL.md +88 -0
- package/templates/seed/squads/company/SQUAD.md +49 -0
- package/templates/seed/squads/company/company-critic.md +21 -0
- package/templates/seed/squads/company/company-eval.md +21 -0
- package/templates/seed/squads/company/event-dispatcher.md +21 -0
- package/templates/seed/squads/company/goal-tracker.md +21 -0
- package/templates/seed/squads/company/manager.md +66 -0
- package/templates/seed/squads/engineering/SQUAD.md +48 -0
- package/templates/seed/squads/engineering/code-reviewer.md +57 -0
- package/templates/seed/squads/engineering/issue-solver.md +58 -0
- package/templates/seed/squads/engineering/test-writer.md +50 -0
- package/templates/seed/squads/intelligence/SQUAD.md +37 -0
- package/templates/seed/squads/intelligence/intel-critic.md +36 -0
- package/templates/seed/squads/intelligence/intel-eval.md +31 -0
- package/templates/seed/squads/intelligence/intel-lead.md +71 -0
- package/templates/seed/squads/marketing/SQUAD.md +47 -0
- package/templates/seed/squads/marketing/content-drafter.md +71 -0
- package/templates/seed/squads/marketing/growth-analyst.md +49 -0
- package/templates/seed/squads/marketing/social-poster.md +44 -0
- package/templates/seed/squads/operations/SQUAD.md +45 -0
- package/templates/seed/squads/operations/finance-tracker.md +47 -0
- package/templates/seed/squads/operations/goal-tracker.md +48 -0
- package/templates/seed/squads/operations/ops-lead.md +58 -0
- package/templates/seed/squads/research/SQUAD.md +38 -0
- package/templates/seed/squads/research/analyst.md +27 -0
- package/templates/seed/squads/research/research-critic.md +20 -0
- package/templates/seed/squads/research/research-eval.md +20 -0
- package/templates/seed/squads/research/researcher.md +28 -0
- package/dist/chunk-7PRYDHZW.js.map +0 -1
- package/dist/chunk-BV6S5AWZ.js.map +0 -1
- package/dist/chunk-HKWCBCEK.js.map +0 -1
- package/dist/chunk-NA3IECJA.js.map +0 -1
- package/dist/chunk-QPH5OR7J.js.map +0 -1
- package/docker/.env.example +0 -17
- package/docker/README.md +0 -92
- package/docker/docker-compose.engram.yml +0 -304
- package/docker/docker-compose.yml +0 -250
- package/docker/init-db.sql +0 -478
- package/docker/init-engram-db.sql +0 -148
- package/docker/init-langfuse-db.sh +0 -10
- package/docker/otel-collector.yaml +0 -34
- package/docker/squads-bridge/Dockerfile +0 -14
- package/docker/squads-bridge/Dockerfile.proxy +0 -14
- package/docker/squads-bridge/anthropic_proxy.py +0 -313
- package/docker/squads-bridge/requirements.txt +0 -7
- package/docker/squads-bridge/squads_bridge.py +0 -2299
- package/docker/telemetry-ping/Dockerfile +0 -10
- package/docker/telemetry-ping/deploy.sh +0 -69
- package/docker/telemetry-ping/main.py +0 -136
- package/docker/telemetry-ping/requirements.txt +0 -3
- /package/dist/{memory-ZXDXF6KF.js.map → memory-VNF2VFRB.js.map} +0 -0
- /package/dist/{sessions-F6LRY7EN.js.map → sessions-6PB7ALCE.js.map} +0 -0
- /package/dist/{squad-parser-MSYE4PXL.js.map → squad-parser-4BI3G4RS.js.map} +0 -0
- /package/dist/{terminal-JZSAQSN7.js.map → terminal-YKA4O5CX.js.map} +0 -0
- /package/dist/{update-MAY6EXFQ.js.map → update-ALJKFFM7.js.map} +0 -0
package/README.md
CHANGED
|
@@ -4,14 +4,17 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/squads-cli)
|
|
5
5
|
[](https://github.com/agents-squads/squads-cli)
|
|
6
6
|
[](LICENSE)
|
|
7
|
+
[](https://agents-squads.com/docs)
|
|
7
8
|
|
|
8
|
-
**
|
|
9
|
+
**Build your AI workforce.** Finance, marketing, engineering, operations — AI agents organized into domain-aligned squads that actually run your business.
|
|
10
|
+
|
|
11
|
+
📖 **[Documentation](https://agents-squads.com/docs)** · 🚀 **[Getting Started](https://agents-squads.com/onboarding)** · 💡 **[Architecture Guide](https://agents-squads.com/engineering/squads-architecture)**
|
|
9
12
|
|
|
10
13
|
```bash
|
|
11
14
|
npm install -g squads-cli && squads init
|
|
12
15
|
```
|
|
13
16
|
|
|
14
|
-
> **Why squads?**
|
|
17
|
+
> **Why squads?** A full business team costs $1M+/year. An AI workforce costs API calls. Squads organizes AI agents by business domain — giving them persistent memory, goals, and coordinated execution. Your agents, your data, no lock-in. Works with Claude, GPT-4, Gemini, and more.
|
|
15
18
|
|
|
16
19
|

|
|
17
20
|
|
|
@@ -36,6 +39,16 @@ $ squads status
|
|
|
36
39
|
└────────────────────────────────────────────────────────┘
|
|
37
40
|
```
|
|
38
41
|
|
|
42
|
+
## Traditional Hiring vs AI Workforce
|
|
43
|
+
|
|
44
|
+
| | Traditional Team | AI Workforce (squads-cli) |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| **Cost** | $1M+/year for a small team | API calls ($50-500/month) |
|
|
47
|
+
| **Availability** | 8 hours/day, 5 days/week | 24/7, including weekends |
|
|
48
|
+
| **Scale** | Hire, train, onboard (months) | Add a markdown file (minutes) |
|
|
49
|
+
| **Ownership** | Vendor contracts, platforms | Your agents, your data, your system |
|
|
50
|
+
| **Memory** | Tribal knowledge, Notion docs | Persistent state across sessions |
|
|
51
|
+
|
|
39
52
|
## Why squads-cli?
|
|
40
53
|
|
|
41
54
|
| Other Frameworks | squads-cli |
|
|
@@ -240,6 +253,92 @@ $ squads update
|
|
|
240
253
|
● Updated to 0.2.0
|
|
241
254
|
```
|
|
242
255
|
|
|
256
|
+
### Agent History
|
|
257
|
+
|
|
258
|
+
Track and review agent execution history with costs and performance metrics:
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
$ squads history
|
|
262
|
+
|
|
263
|
+
squads history
|
|
264
|
+
|
|
265
|
+
Last 7 days of agent executions
|
|
266
|
+
|
|
267
|
+
┌────────────────────────────────────────────────────────────┐
|
|
268
|
+
│ TIMESTAMP SQUAD AGENT COST STATUS │
|
|
269
|
+
├────────────────────────────────────────────────────────────┤
|
|
270
|
+
│ 2026-01-06 10:30 engineering ci-lead $0.45 ✓ │
|
|
271
|
+
│ 2026-01-06 09:15 website seo-critic $0.23 ✓ │
|
|
272
|
+
│ 2026-01-05 16:20 customer lead $0.89 ✓ │
|
|
273
|
+
└────────────────────────────────────────────────────────────┘
|
|
274
|
+
|
|
275
|
+
Total cost: $1.57 │ 3 executions
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Filter by squad and get detailed metrics:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
squads history -s engineering -v # Verbose with token details
|
|
282
|
+
squads history -d 30 -j # Last 30 days, JSON output
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Context Feed
|
|
286
|
+
|
|
287
|
+
Get curated context for agents based on goals, memory, and recent activity:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
# Human-readable summary
|
|
291
|
+
squads context -s engineering
|
|
292
|
+
|
|
293
|
+
# JSON for agent consumption
|
|
294
|
+
squads context -s engineering --json
|
|
295
|
+
|
|
296
|
+
# Search memory for specific topic
|
|
297
|
+
squads context -t "authentication" -s website
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Perfect for injecting relevant context into agent prompts or hooks.
|
|
301
|
+
|
|
302
|
+
### Live Monitoring
|
|
303
|
+
|
|
304
|
+
**Watch Mode** — Refresh any command in real-time:
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
squads watch status # Refresh every 2 seconds
|
|
308
|
+
squads watch "dash --ceo" -n 5 # Custom interval
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
**Live Dashboard** — Interactive TUI like htop:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
squads live # Full dashboard
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Process Table** — Real-time process monitoring:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
squads top # Live process table
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Infrastructure Health
|
|
324
|
+
|
|
325
|
+
Quick health check across all services without verbose Docker output:
|
|
326
|
+
|
|
327
|
+
```
|
|
328
|
+
$ squads health
|
|
329
|
+
|
|
330
|
+
squads health
|
|
331
|
+
|
|
332
|
+
✓ postgres healthy
|
|
333
|
+
✓ redis healthy
|
|
334
|
+
✓ bridge healthy
|
|
335
|
+
✓ langfuse healthy
|
|
336
|
+
|
|
337
|
+
● 4/4 core services healthy
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Use `-v` to see logs for failing services.
|
|
341
|
+
|
|
243
342
|
## Core Concepts
|
|
244
343
|
|
|
245
344
|
### Squads = Domain-Aligned Teams
|
|
@@ -933,6 +1032,49 @@ squads tonight status Check progress
|
|
|
933
1032
|
squads tonight stop Kill all agents
|
|
934
1033
|
squads tonight report View morning report
|
|
935
1034
|
|
|
1035
|
+
squads cron sync Sync agent schedules to launchd (macOS)
|
|
1036
|
+
squads cron list [squad] List scheduled agents
|
|
1037
|
+
squads cron status Show launchd status and next runs
|
|
1038
|
+
squads cron enable <agent> Enable an agent's schedule
|
|
1039
|
+
squads cron disable <agent> Disable an agent's schedule
|
|
1040
|
+
squads cron logs [agent] Show execution logs
|
|
1041
|
+
|
|
1042
|
+
squads approval send <type> Send approval request to Slack
|
|
1043
|
+
squads approval list List pending approvals
|
|
1044
|
+
squads approval check <id> Check approval status
|
|
1045
|
+
squads approval cancel <id> Cancel pending approval
|
|
1046
|
+
|
|
1047
|
+
squads orchestrate <squad> Run squad with lead agent orchestration
|
|
1048
|
+
-f, --foreground Run in foreground (no tmux)
|
|
1049
|
+
|
|
1050
|
+
squads skill list List uploaded skills
|
|
1051
|
+
squads skill upload <path> Upload skill directory to Anthropic API
|
|
1052
|
+
squads skill delete <id> Delete a skill
|
|
1053
|
+
squads skill show <id> Show skill details
|
|
1054
|
+
squads skill convert <agent> Convert agent.md to SKILL.md format
|
|
1055
|
+
|
|
1056
|
+
squads permissions show <squad> Show permission context for a squad
|
|
1057
|
+
squads permissions check <squad> Validate permissions before execution
|
|
1058
|
+
-a, --agent <agent> Specify agent for context
|
|
1059
|
+
|
|
1060
|
+
squads slack sync Sync squad channels with Slack
|
|
1061
|
+
squads slack channels List Slack channels
|
|
1062
|
+
squads slack test Test Slack connection
|
|
1063
|
+
|
|
1064
|
+
squads providers Show available LLM CLI providers
|
|
1065
|
+
--json JSON output
|
|
1066
|
+
|
|
1067
|
+
squads autonomy Show autonomy score and confidence metrics
|
|
1068
|
+
-s, --squad <squad> Filter by squad
|
|
1069
|
+
-p, --period <period> Period: today, week, month
|
|
1070
|
+
--json JSON output
|
|
1071
|
+
|
|
1072
|
+
squads kpi show <squad> Show KPI status for a squad
|
|
1073
|
+
squads kpi record <squad> <kpi> <value> Record KPI value
|
|
1074
|
+
squads kpi trend <squad> <kpi> Show KPI trend over time
|
|
1075
|
+
squads kpi insights <squad> Generate AI insights from KPIs
|
|
1076
|
+
--json JSON output
|
|
1077
|
+
|
|
936
1078
|
squads update Interactive update
|
|
937
1079
|
-y, --yes Auto-confirm
|
|
938
1080
|
-c, --check Check only
|
|
@@ -944,6 +1086,8 @@ squads whoami Show user
|
|
|
944
1086
|
|
|
945
1087
|
## Claude Code Integration
|
|
946
1088
|
|
|
1089
|
+
For comprehensive documentation on hooks and skills, see the **[Hooks and Skills Guide](https://agents-squads.com/engineering/hooks-and-skills)**.
|
|
1090
|
+
|
|
947
1091
|
### Option 1: Session Hooks (Recommended)
|
|
948
1092
|
|
|
949
1093
|
Add to `.claude/settings.json`:
|
|
@@ -1116,10 +1260,23 @@ npm run lint # ESLint
|
|
|
1116
1260
|
npm run typecheck # TypeScript check
|
|
1117
1261
|
```
|
|
1118
1262
|
|
|
1119
|
-
##
|
|
1263
|
+
## Documentation & Resources
|
|
1120
1264
|
|
|
1265
|
+
**Official Documentation:**
|
|
1266
|
+
- 📖 [Documentation](https://agents-squads.com/docs) — Complete CLI reference and tutorials
|
|
1267
|
+
- 🚀 [Getting Started](https://agents-squads.com/onboarding) — Quick setup guide
|
|
1268
|
+
- 🏗️ [Architecture Guide](https://agents-squads.com/engineering/squads-architecture) — How squads work under the hood
|
|
1269
|
+
- ⚡ [Hooks and Skills](https://agents-squads.com/engineering/hooks-and-skills) — Claude Code integration patterns
|
|
1270
|
+
- 💰 [Cost Management](https://agents-squads.com/engineering/cost-management) — Budget tracking and optimization
|
|
1271
|
+
|
|
1272
|
+
**Related Repositories:**
|
|
1121
1273
|
- [agents-squads](https://github.com/agents-squads/agents-squads) — Full framework with infrastructure
|
|
1122
1274
|
- [engram](https://github.com/agents-squads/engram) — Persistent memory for AI agents
|
|
1275
|
+
- [squads-infra](https://github.com/agents-squads/squads-infra) — Docker infrastructure stack
|
|
1276
|
+
|
|
1277
|
+
**Research & Intelligence:**
|
|
1278
|
+
- [AI Agent Research](https://agents-squads.com/research) — Latest AI agent analysis
|
|
1279
|
+
- [Enterprise AI Report](https://agents-squads.com/intelligence/enterprise-ai-agents-2025) — Market intelligence
|
|
1123
1280
|
|
|
1124
1281
|
## License
|
|
1125
1282
|
|
|
@@ -1127,4 +1284,4 @@ npm run typecheck # TypeScript check
|
|
|
1127
1284
|
|
|
1128
1285
|
---
|
|
1129
1286
|
|
|
1130
|
-
Built by [Agents Squads](https://agents-squads.com) — AI
|
|
1287
|
+
Built by [Agents Squads](https://agents-squads.com) — your AI workforce.
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
RESET,
|
|
4
|
+
colors
|
|
5
|
+
} from "./chunk-N7KDWU4W.js";
|
|
2
6
|
import {
|
|
3
7
|
__require
|
|
4
8
|
} from "./chunk-7OCVIDC7.js";
|
|
@@ -196,7 +200,7 @@ async function autoUpdateOnStartup(silent = false) {
|
|
|
196
200
|
child.on("close", (code) => {
|
|
197
201
|
if (code === 0) {
|
|
198
202
|
console.log(`
|
|
199
|
-
\
|
|
203
|
+
${colors.green}\u2713${RESET} Update successful! v${info.latestVersion} will be used on your next run.
|
|
200
204
|
`);
|
|
201
205
|
writeAutoUpdateCache({ lastAttempt: now, lastSuccess: now });
|
|
202
206
|
try {
|
|
@@ -222,4 +226,4 @@ export {
|
|
|
222
226
|
refreshVersionCache,
|
|
223
227
|
autoUpdateOnStartup
|
|
224
228
|
};
|
|
225
|
-
//# sourceMappingURL=chunk-
|
|
229
|
+
//# sourceMappingURL=chunk-4CMAEQQY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/update.ts"],"sourcesContent":["/**\n * Update checker for squads-cli\n * Checks npm registry for newer versions and caches result\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { homedir } from 'os';\nimport { execSync } from 'child_process';\nimport { fileURLToPath } from 'url';\nimport { colors as termColors, RESET as termReset } from './terminal.js';\n\n// Get current version from package.json\nfunction getPackageVersion(): string {\n try {\n // Try to find package.json relative to this module\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n\n // Look up from dist/lib to find package.json\n const possiblePaths = [\n join(__dirname, '..', '..', 'package.json'), // From dist/lib/\n join(__dirname, '..', 'package.json'), // From dist/\n join(__dirname, 'package.json'), // Same dir\n ];\n\n for (const pkgPath of possiblePaths) {\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.version || '0.0.0';\n }\n }\n } catch {\n // Ignore errors\n }\n return '0.0.0';\n}\n\nconst CURRENT_VERSION = getPackageVersion();\n\n// Cache settings\nconst CACHE_DIR = join(homedir(), '.squads');\nconst CACHE_FILE = join(CACHE_DIR, 'update-check.json');\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours\n\ninterface UpdateCache {\n latestVersion: string;\n checkedAt: number;\n}\n\nexport interface UpdateInfo {\n currentVersion: string;\n latestVersion: string;\n updateAvailable: boolean;\n}\n\n/**\n * Compare semantic versions\n * Returns true if v2 > v1\n */\nfunction isNewerVersion(v1: string, v2: string): boolean {\n const parts1 = v1.replace(/^v/, '').split('.').map(Number);\n const parts2 = v2.replace(/^v/, '').split('.').map(Number);\n\n for (let i = 0; i < 3; i++) {\n const p1 = parts1[i] || 0;\n const p2 = parts2[i] || 0;\n if (p2 > p1) return true;\n if (p2 < p1) return false;\n }\n return false;\n}\n\n/**\n * Read cached update info\n */\nfunction readCache(): UpdateCache | null {\n try {\n if (!existsSync(CACHE_FILE)) return null;\n const data = JSON.parse(readFileSync(CACHE_FILE, 'utf-8'));\n return data as UpdateCache;\n } catch {\n return null;\n }\n}\n\n/**\n * Write update info to cache\n */\nfunction writeCache(latestVersion: string): void {\n try {\n if (!existsSync(CACHE_DIR)) {\n mkdirSync(CACHE_DIR, { recursive: true });\n }\n const cache: UpdateCache = {\n latestVersion,\n checkedAt: Date.now(),\n };\n writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2));\n } catch {\n // Ignore cache write errors\n }\n}\n\n/**\n * Fetch latest version from npm registry\n */\nfunction fetchLatestVersion(): string | null {\n try {\n const result = execSync('npm view squads-cli version 2>/dev/null', {\n encoding: 'utf-8',\n timeout: 5000,\n }).trim();\n return result || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check for updates (uses cache to avoid frequent npm calls)\n * Non-blocking: returns cached data immediately, triggers background refresh if stale\n */\nexport function checkForUpdate(): UpdateInfo {\n const result: UpdateInfo = {\n currentVersion: CURRENT_VERSION,\n latestVersion: CURRENT_VERSION,\n updateAvailable: false,\n };\n\n // Check cache first\n const cache = readCache();\n const now = Date.now();\n\n if (cache) {\n // Always use cached value immediately for fast response\n result.latestVersion = cache.latestVersion;\n result.updateAvailable = isNewerVersion(CURRENT_VERSION, cache.latestVersion);\n\n // If cache is stale, trigger background refresh (non-blocking)\n if ((now - cache.checkedAt) >= CACHE_TTL_MS) {\n // Fire and forget - don't await\n triggerBackgroundRefresh();\n }\n return result;\n }\n\n // No cache at all - trigger background refresh and return defaults\n triggerBackgroundRefresh();\n return result;\n}\n\n/**\n * Trigger a background version check that doesn't block the CLI\n * Uses spawn to run npm in a detached process\n */\nfunction triggerBackgroundRefresh(): void {\n try {\n // Use spawn with detached: true to run in background\n // This won't block the main process\n const { spawn } = require('child_process') as typeof import('child_process');\n const child = spawn('npm', ['view', 'squads-cli', 'version'], {\n detached: true,\n stdio: ['ignore', 'pipe', 'ignore'],\n shell: true,\n });\n\n // Collect output\n let output = '';\n child.stdout?.on('data', (data: Buffer) => {\n output += data.toString();\n });\n\n child.on('close', () => {\n const version = output.trim();\n if (version && /^\\d+\\.\\d+\\.\\d+/.test(version)) {\n writeCache(version);\n }\n });\n\n // Unref to allow main process to exit\n child.unref();\n } catch {\n // Ignore errors - background refresh is best effort\n }\n}\n\n/**\n * Get current version\n */\nexport function getCurrentVersion(): string {\n return CURRENT_VERSION;\n}\n\n/**\n * Perform the actual update via npm\n * Returns true if successful\n */\nexport function performUpdate(): { success: boolean; error?: string } {\n try {\n execSync('npm update -g squads-cli', {\n encoding: 'utf-8',\n stdio: 'inherit',\n timeout: 120000, // 2 minutes\n });\n // Clear cache so next check fetches fresh\n try {\n unlinkSync(CACHE_FILE);\n } catch {\n // Ignore\n }\n return { success: true };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : 'Unknown error',\n };\n }\n}\n\n/**\n * Force refresh the version cache (bypass TTL)\n */\nexport function refreshVersionCache(): UpdateInfo {\n const latestVersion = fetchLatestVersion();\n if (latestVersion) {\n writeCache(latestVersion);\n return {\n currentVersion: CURRENT_VERSION,\n latestVersion,\n updateAvailable: isNewerVersion(CURRENT_VERSION, latestVersion),\n };\n }\n return checkForUpdate();\n}\n\n// Auto-update settings\nconst AUTO_UPDATE_CACHE_FILE = join(CACHE_DIR, 'auto-update.json');\nconst AUTO_UPDATE_COOLDOWN_MS = 60 * 60 * 1000; // 1 hour cooldown between auto-update attempts\n\ninterface AutoUpdateCache {\n lastAttempt: number;\n lastSuccess?: number;\n}\n\nfunction readAutoUpdateCache(): AutoUpdateCache | null {\n try {\n if (!existsSync(AUTO_UPDATE_CACHE_FILE)) return null;\n return JSON.parse(readFileSync(AUTO_UPDATE_CACHE_FILE, 'utf-8'));\n } catch {\n return null;\n }\n}\n\nfunction writeAutoUpdateCache(cache: AutoUpdateCache): void {\n try {\n if (!existsSync(CACHE_DIR)) {\n mkdirSync(CACHE_DIR, { recursive: true });\n }\n writeFileSync(AUTO_UPDATE_CACHE_FILE, JSON.stringify(cache, null, 2));\n } catch {\n // Ignore errors\n }\n}\n\n/**\n * Seamless auto-update on CLI startup (like Gemini CLI)\n * Checks for updates and auto-installs without prompting.\n * Shows a message on success: \"Update successful! The new version will be used on your next run.\"\n *\n * @param silent - If true, don't show any output (for background checks)\n * @returns Promise that resolves when check/update is complete\n */\nexport async function autoUpdateOnStartup(silent = false): Promise<void> {\n // Skip in CI or if auto-update disabled\n if (process.env.CI || process.env.SQUADS_NO_AUTO_UPDATE) return;\n\n // Check cooldown - don't spam npm\n const autoCache = readAutoUpdateCache();\n const now = Date.now();\n if (autoCache && (now - autoCache.lastAttempt) < AUTO_UPDATE_COOLDOWN_MS) {\n return; // Too soon since last attempt\n }\n\n // Check if update is available\n const info = checkForUpdate();\n if (!info.updateAvailable) return;\n\n // Write attempt timestamp before trying\n writeAutoUpdateCache({ lastAttempt: now, lastSuccess: autoCache?.lastSuccess });\n\n // Perform update silently in background using spawn\n try {\n const { spawn } = await import('child_process');\n\n // Run npm update in background\n const child = spawn('npm', ['update', '-g', 'squads-cli'], {\n detached: true,\n stdio: silent ? 'ignore' : ['ignore', 'pipe', 'pipe'],\n shell: true,\n });\n\n if (!silent && child.stdout) {\n // Wait for completion and check result\n await new Promise<void>((resolve) => {\n child.on('close', (code) => {\n if (code === 0) {\n // Success - show Gemini-style message\n console.log(`\\n ${termColors.green}✓${termReset} Update successful! v${info.latestVersion} will be used on your next run.\\n`);\n writeAutoUpdateCache({ lastAttempt: now, lastSuccess: now });\n // Clear version cache so next startup detects new version\n try { unlinkSync(CACHE_FILE); } catch { /* ignore */ }\n }\n resolve();\n });\n\n // Timeout after 30 seconds\n setTimeout(() => resolve(), 30000);\n });\n } else {\n // Silent mode - just fire and forget\n child.unref();\n }\n } catch {\n // Ignore errors - auto-update is best effort\n }\n}\n"],"mappings":";;;;;;;;;;AAKA,SAAS,YAAY,cAAc,eAAe,WAAW,kBAAkB;AAC/E,SAAS,MAAM,eAAe;AAC9B,SAAS,eAAe;AACxB,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAI9B,SAAS,oBAA4B;AACnC,MAAI;AAEF,UAAMA,cAAa,cAAc,YAAY,GAAG;AAChD,UAAMC,aAAY,QAAQD,WAAU;AAGpC,UAAM,gBAAgB;AAAA,MACpB,KAAKC,YAAW,MAAM,MAAM,cAAc;AAAA;AAAA,MAC1C,KAAKA,YAAW,MAAM,cAAc;AAAA;AAAA,MACpC,KAAKA,YAAW,cAAc;AAAA;AAAA,IAChC;AAEA,eAAW,WAAW,eAAe;AACnC,UAAI,WAAW,OAAO,GAAG;AACvB,cAAM,MAAM,KAAK,MAAM,aAAa,SAAS,OAAO,CAAC;AACrD,eAAO,IAAI,WAAW;AAAA,MACxB;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEA,IAAM,kBAAkB,kBAAkB;AAG1C,IAAM,YAAY,KAAK,QAAQ,GAAG,SAAS;AAC3C,IAAM,aAAa,KAAK,WAAW,mBAAmB;AACtD,IAAM,eAAe,KAAK,KAAK,KAAK;AAiBpC,SAAS,eAAe,IAAY,IAAqB;AACvD,QAAM,SAAS,GAAG,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AACzD,QAAM,SAAS,GAAG,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AAEzD,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,KAAK,OAAO,CAAC,KAAK;AACxB,UAAM,KAAK,OAAO,CAAC,KAAK;AACxB,QAAI,KAAK,GAAI,QAAO;AACpB,QAAI,KAAK,GAAI,QAAO;AAAA,EACtB;AACA,SAAO;AACT;AAKA,SAAS,YAAgC;AACvC,MAAI;AACF,QAAI,CAAC,WAAW,UAAU,EAAG,QAAO;AACpC,UAAM,OAAO,KAAK,MAAM,aAAa,YAAY,OAAO,CAAC;AACzD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,WAAW,eAA6B;AAC/C,MAAI;AACF,QAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,gBAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1C;AACA,UAAM,QAAqB;AAAA,MACzB;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB;AACA,kBAAc,YAAY,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,EAC1D,QAAQ;AAAA,EAER;AACF;AAKA,SAAS,qBAAoC;AAC3C,MAAI;AACF,UAAM,SAAS,SAAS,2CAA2C;AAAA,MACjE,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC,EAAE,KAAK;AACR,WAAO,UAAU;AAAA,EACnB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,iBAA6B;AAC3C,QAAM,SAAqB;AAAA,IACzB,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,iBAAiB;AAAA,EACnB;AAGA,QAAM,QAAQ,UAAU;AACxB,QAAM,MAAM,KAAK,IAAI;AAErB,MAAI,OAAO;AAET,WAAO,gBAAgB,MAAM;AAC7B,WAAO,kBAAkB,eAAe,iBAAiB,MAAM,aAAa;AAG5E,QAAK,MAAM,MAAM,aAAc,cAAc;AAE3C,+BAAyB;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAGA,2BAAyB;AACzB,SAAO;AACT;AAMA,SAAS,2BAAiC;AACxC,MAAI;AAGF,UAAM,EAAE,MAAM,IAAI,UAAQ,eAAe;AACzC,UAAM,QAAQ,MAAM,OAAO,CAAC,QAAQ,cAAc,SAAS,GAAG;AAAA,MAC5D,UAAU;AAAA,MACV,OAAO,CAAC,UAAU,QAAQ,QAAQ;AAAA,MAClC,OAAO;AAAA,IACT,CAAC;AAGD,QAAI,SAAS;AACb,UAAM,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AACzC,gBAAU,KAAK,SAAS;AAAA,IAC1B,CAAC;AAED,UAAM,GAAG,SAAS,MAAM;AACtB,YAAM,UAAU,OAAO,KAAK;AAC5B,UAAI,WAAW,iBAAiB,KAAK,OAAO,GAAG;AAC7C,mBAAW,OAAO;AAAA,MACpB;AAAA,IACF,CAAC;AAGD,UAAM,MAAM;AAAA,EACd,QAAQ;AAAA,EAER;AACF;AAKO,SAAS,oBAA4B;AAC1C,SAAO;AACT;AAMO,SAAS,gBAAsD;AACpE,MAAI;AACF,aAAS,4BAA4B;AAAA,MACnC,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA;AAAA,IACX,CAAC;AAED,QAAI;AACF,iBAAW,UAAU;AAAA,IACvB,QAAQ;AAAA,IAER;AACA,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,eAAe,QAAQ,IAAI,UAAU;AAAA,IAC9C;AAAA,EACF;AACF;AAKO,SAAS,sBAAkC;AAChD,QAAM,gBAAgB,mBAAmB;AACzC,MAAI,eAAe;AACjB,eAAW,aAAa;AACxB,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB;AAAA,MACA,iBAAiB,eAAe,iBAAiB,aAAa;AAAA,IAChE;AAAA,EACF;AACA,SAAO,eAAe;AACxB;AAGA,IAAM,yBAAyB,KAAK,WAAW,kBAAkB;AACjE,IAAM,0BAA0B,KAAK,KAAK;AAO1C,SAAS,sBAA8C;AACrD,MAAI;AACF,QAAI,CAAC,WAAW,sBAAsB,EAAG,QAAO;AAChD,WAAO,KAAK,MAAM,aAAa,wBAAwB,OAAO,CAAC;AAAA,EACjE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,qBAAqB,OAA8B;AAC1D,MAAI;AACF,QAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,gBAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1C;AACA,kBAAc,wBAAwB,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,EACtE,QAAQ;AAAA,EAER;AACF;AAUA,eAAsB,oBAAoB,SAAS,OAAsB;AAEvE,MAAI,QAAQ,IAAI,MAAM,QAAQ,IAAI,sBAAuB;AAGzD,QAAM,YAAY,oBAAoB;AACtC,QAAM,MAAM,KAAK,IAAI;AACrB,MAAI,aAAc,MAAM,UAAU,cAAe,yBAAyB;AACxE;AAAA,EACF;AAGA,QAAM,OAAO,eAAe;AAC5B,MAAI,CAAC,KAAK,gBAAiB;AAG3B,uBAAqB,EAAE,aAAa,KAAK,aAAa,WAAW,YAAY,CAAC;AAG9E,MAAI;AACF,UAAM,EAAE,MAAM,IAAI,MAAM,OAAO,eAAe;AAG9C,UAAM,QAAQ,MAAM,OAAO,CAAC,UAAU,MAAM,YAAY,GAAG;AAAA,MACzD,UAAU;AAAA,MACV,OAAO,SAAS,WAAW,CAAC,UAAU,QAAQ,MAAM;AAAA,MACpD,OAAO;AAAA,IACT,CAAC;AAED,QAAI,CAAC,UAAU,MAAM,QAAQ;AAE3B,YAAM,IAAI,QAAc,CAAC,YAAY;AACnC,cAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,cAAI,SAAS,GAAG;AAEd,oBAAQ,IAAI;AAAA,IAAO,OAAW,KAAK,SAAI,KAAS,wBAAwB,KAAK,aAAa;AAAA,CAAmC;AAC7H,iCAAqB,EAAE,aAAa,KAAK,aAAa,IAAI,CAAC;AAE3D,gBAAI;AAAE,yBAAW,UAAU;AAAA,YAAG,QAAQ;AAAA,YAAe;AAAA,UACvD;AACA,kBAAQ;AAAA,QACV,CAAC;AAGD,mBAAW,MAAM,QAAQ,GAAG,GAAK;AAAA,MACnC,CAAC;AAAA,IACH,OAAO;AAEL,YAAM,MAAM;AAAA,IACd;AAAA,EACF,QAAQ;AAAA,EAER;AACF;","names":["__filename","__dirname"]}
|
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/lib/terminal.ts
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
function isColorEnabled() {
|
|
5
|
+
if (process.env.NO_COLOR !== void 0) return false;
|
|
6
|
+
if (process.env.FORCE_COLOR !== void 0) return true;
|
|
7
|
+
if (isAiCli()) return true;
|
|
8
|
+
return process.stdout.isTTY ?? false;
|
|
9
|
+
}
|
|
10
|
+
function isAiCli() {
|
|
11
|
+
if (process.env.CLAUDECODE !== void 0) return true;
|
|
12
|
+
if (process.env.GEMINI_API_KEY !== void 0) return true;
|
|
13
|
+
if (process.env.CURSOR_CHANNEL !== void 0) return true;
|
|
14
|
+
if (process.env.CODY_AUTH !== void 0) return true;
|
|
15
|
+
if (process.env.CODEIUM_API_KEY !== void 0) return true;
|
|
16
|
+
if (process.env.GITHUB_COPILOT_CLI !== void 0) return true;
|
|
17
|
+
if (process.env.AIDER_MODEL !== void 0) return true;
|
|
18
|
+
if (process.env.CONTINUE_GLOBAL_DIR !== void 0) return true;
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
var COLOR_ENABLED = isColorEnabled();
|
|
22
|
+
var ESC = COLOR_ENABLED ? "\x1B[" : "";
|
|
23
|
+
var RESET = COLOR_ENABLED ? "\x1B[0m" : "";
|
|
6
24
|
function supportsTrueColor() {
|
|
25
|
+
if (!COLOR_ENABLED) return false;
|
|
7
26
|
const colorterm = process.env.COLORTERM;
|
|
8
27
|
if (colorterm === "truecolor" || colorterm === "24bit") return true;
|
|
9
28
|
const term = process.env.TERM || "";
|
|
@@ -14,29 +33,73 @@ function supportsTrueColor() {
|
|
|
14
33
|
return false;
|
|
15
34
|
}
|
|
16
35
|
var USE_TRUE_COLOR = supportsTrueColor();
|
|
17
|
-
var rgb = (r, g, b) =>
|
|
18
|
-
var bgRgb = (r, g, b) =>
|
|
19
|
-
|
|
20
|
-
|
|
36
|
+
var rgb = (r, g, b) => COLOR_ENABLED ? `\x1B[38;2;${r};${g};${b}m` : "";
|
|
37
|
+
var bgRgb = (r, g, b) => COLOR_ENABLED ? `\x1B[48;2;${r};${g};${b}m` : "";
|
|
38
|
+
function isLightBackground() {
|
|
39
|
+
const theme = process.env.SQUADS_THEME?.toLowerCase();
|
|
40
|
+
if (theme === "light") return true;
|
|
41
|
+
if (theme === "dark") return false;
|
|
42
|
+
const colorfgbg = process.env.COLORFGBG;
|
|
43
|
+
if (colorfgbg) {
|
|
44
|
+
const parts = colorfgbg.split(";");
|
|
45
|
+
const bg = parseInt(parts[parts.length - 1], 10);
|
|
46
|
+
if (!isNaN(bg) && (bg === 15 || bg === 7)) return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
var USE_LIGHT_MODE = isLightBackground();
|
|
51
|
+
var noColors = {
|
|
52
|
+
purple: "",
|
|
53
|
+
pink: "",
|
|
54
|
+
cyan: "",
|
|
55
|
+
green: "",
|
|
56
|
+
yellow: "",
|
|
57
|
+
red: "",
|
|
58
|
+
gray: "",
|
|
59
|
+
dim: "",
|
|
60
|
+
white: ""
|
|
61
|
+
};
|
|
62
|
+
var ansiDark = {
|
|
63
|
+
purple: "\x1B[35m",
|
|
21
64
|
// magenta
|
|
22
|
-
pink:
|
|
65
|
+
pink: "\x1B[95m",
|
|
23
66
|
// bright magenta
|
|
24
|
-
cyan:
|
|
67
|
+
cyan: "\x1B[36m",
|
|
25
68
|
// cyan
|
|
26
|
-
green:
|
|
69
|
+
green: "\x1B[32m",
|
|
27
70
|
// green
|
|
28
|
-
yellow:
|
|
71
|
+
yellow: "\x1B[33m",
|
|
29
72
|
// yellow
|
|
30
|
-
red:
|
|
73
|
+
red: "\x1B[31m",
|
|
31
74
|
// red
|
|
32
|
-
gray:
|
|
75
|
+
gray: "\x1B[90m",
|
|
33
76
|
// bright black (gray)
|
|
34
|
-
dim:
|
|
77
|
+
dim: "\x1B[90m",
|
|
35
78
|
// bright black (gray)
|
|
36
|
-
white:
|
|
79
|
+
white: "\x1B[97m"
|
|
37
80
|
// bright white
|
|
38
81
|
};
|
|
39
|
-
var
|
|
82
|
+
var ansiLight = {
|
|
83
|
+
purple: "\x1B[35m",
|
|
84
|
+
// magenta (same, works on light)
|
|
85
|
+
pink: "\x1B[35m",
|
|
86
|
+
// magenta (bright is too light)
|
|
87
|
+
cyan: "\x1B[36m",
|
|
88
|
+
// cyan
|
|
89
|
+
green: "\x1B[32m",
|
|
90
|
+
// green
|
|
91
|
+
yellow: "\x1B[33m",
|
|
92
|
+
// yellow
|
|
93
|
+
red: "\x1B[31m",
|
|
94
|
+
// red
|
|
95
|
+
gray: "\x1B[90m",
|
|
96
|
+
// bright black (gray)
|
|
97
|
+
dim: "\x1B[90m",
|
|
98
|
+
// bright black (gray)
|
|
99
|
+
white: "\x1B[30m"
|
|
100
|
+
// black for light backgrounds
|
|
101
|
+
};
|
|
102
|
+
var darkPalette = {
|
|
40
103
|
purple: rgb(168, 85, 247),
|
|
41
104
|
// #a855f7
|
|
42
105
|
pink: rgb(236, 72, 153),
|
|
@@ -54,24 +117,59 @@ var colors = USE_TRUE_COLOR ? {
|
|
|
54
117
|
dim: rgb(75, 85, 99),
|
|
55
118
|
// #4b5563
|
|
56
119
|
white: rgb(255, 255, 255)
|
|
57
|
-
} : ansi;
|
|
58
|
-
var bold = `${ESC}1m`;
|
|
59
|
-
var dim = `${ESC}2m`;
|
|
60
|
-
var cursor = {
|
|
61
|
-
hide: `${ESC}?25l`,
|
|
62
|
-
show: `${ESC}?25h`,
|
|
63
|
-
up: (n = 1) => `${ESC}${n}A`,
|
|
64
|
-
down: (n = 1) => `${ESC}${n}B`,
|
|
65
|
-
left: (n = 1) => `${ESC}${n}D`,
|
|
66
|
-
right: (n = 1) => `${ESC}${n}C`,
|
|
67
|
-
to: (x, y) => `${ESC}${y};${x}H`,
|
|
68
|
-
save: `${ESC}s`,
|
|
69
|
-
restore: `${ESC}u`
|
|
70
120
|
};
|
|
71
|
-
var
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
121
|
+
var lightPalette = {
|
|
122
|
+
purple: rgb(124, 58, 237),
|
|
123
|
+
// #7c3aed (purple-600)
|
|
124
|
+
pink: rgb(219, 39, 119),
|
|
125
|
+
// #db2777 (pink-600)
|
|
126
|
+
cyan: rgb(8, 145, 178),
|
|
127
|
+
// #0891b2 (cyan-600)
|
|
128
|
+
green: rgb(22, 163, 74),
|
|
129
|
+
// #16a34a (green-600)
|
|
130
|
+
yellow: rgb(202, 138, 4),
|
|
131
|
+
// #ca8a04 (yellow-600)
|
|
132
|
+
red: rgb(220, 38, 38),
|
|
133
|
+
// #dc2626 (red-600)
|
|
134
|
+
gray: rgb(75, 85, 99),
|
|
135
|
+
// #4b5563 (gray-600)
|
|
136
|
+
dim: rgb(107, 114, 128),
|
|
137
|
+
// #6b7280 (gray-500)
|
|
138
|
+
white: rgb(0, 0, 0)
|
|
139
|
+
// black for light backgrounds
|
|
140
|
+
};
|
|
141
|
+
var colors = !COLOR_ENABLED ? noColors : USE_TRUE_COLOR ? USE_LIGHT_MODE ? lightPalette : darkPalette : USE_LIGHT_MODE ? ansiLight : ansiDark;
|
|
142
|
+
var bold = COLOR_ENABLED ? "\x1B[1m" : "";
|
|
143
|
+
var dim = COLOR_ENABLED ? "\x1B[2m" : "";
|
|
144
|
+
var cursor = COLOR_ENABLED ? {
|
|
145
|
+
hide: "\x1B[?25l",
|
|
146
|
+
show: "\x1B[?25h",
|
|
147
|
+
up: (n = 1) => `\x1B[${n}A`,
|
|
148
|
+
down: (n = 1) => `\x1B[${n}B`,
|
|
149
|
+
left: (n = 1) => `\x1B[${n}D`,
|
|
150
|
+
right: (n = 1) => `\x1B[${n}C`,
|
|
151
|
+
to: (x, y) => `\x1B[${y};${x}H`,
|
|
152
|
+
save: "\x1B[s",
|
|
153
|
+
restore: "\x1B[u"
|
|
154
|
+
} : {
|
|
155
|
+
hide: "",
|
|
156
|
+
show: "",
|
|
157
|
+
up: (_n = 1) => "",
|
|
158
|
+
down: (_n = 1) => "",
|
|
159
|
+
left: (_n = 1) => "",
|
|
160
|
+
right: (_n = 1) => "",
|
|
161
|
+
to: (_x, _y) => "",
|
|
162
|
+
save: "",
|
|
163
|
+
restore: ""
|
|
164
|
+
};
|
|
165
|
+
var clear = COLOR_ENABLED ? {
|
|
166
|
+
line: "\x1B[2K",
|
|
167
|
+
toEnd: "\x1B[0K",
|
|
168
|
+
screen: "\x1B[2J\x1B[0;0H"
|
|
169
|
+
} : {
|
|
170
|
+
line: "",
|
|
171
|
+
toEnd: "",
|
|
172
|
+
screen: ""
|
|
75
173
|
};
|
|
76
174
|
function supportsUnicode() {
|
|
77
175
|
if (process.platform === "win32") {
|
|
@@ -85,6 +183,7 @@ function supportsUnicode() {
|
|
|
85
183
|
}
|
|
86
184
|
var USE_UNICODE = supportsUnicode();
|
|
87
185
|
function gradient(text) {
|
|
186
|
+
if (!COLOR_ENABLED) return text;
|
|
88
187
|
const stops = [
|
|
89
188
|
[168, 85, 247],
|
|
90
189
|
// purple
|
|
@@ -182,7 +281,11 @@ var icons = USE_UNICODE ? {
|
|
|
182
281
|
active: `${colors.green}\u25CF${RESET}`,
|
|
183
282
|
running: `${colors.yellow}\u25C6${RESET}`,
|
|
184
283
|
progress: `${colors.cyan}\u25C6${RESET}`,
|
|
185
|
-
empty: `${colors.dim}\u25C7${RESET}
|
|
284
|
+
empty: `${colors.dim}\u25C7${RESET}`,
|
|
285
|
+
// Privacy indicators
|
|
286
|
+
internal: `${colors.purple}\u{1F512}${RESET}`,
|
|
287
|
+
publicOk: `${colors.green}\u{1F310}${RESET}`,
|
|
288
|
+
caution: `${colors.yellow}\u26A0\uFE0F${RESET}`
|
|
186
289
|
} : {
|
|
187
290
|
success: `${colors.green}*${RESET}`,
|
|
188
291
|
warning: `${colors.yellow}!${RESET}`,
|
|
@@ -191,35 +294,28 @@ var icons = USE_UNICODE ? {
|
|
|
191
294
|
active: `${colors.green}*${RESET}`,
|
|
192
295
|
running: `${colors.yellow}>${RESET}`,
|
|
193
296
|
progress: `${colors.cyan}>${RESET}`,
|
|
194
|
-
empty: `${colors.dim}.${RESET}
|
|
297
|
+
empty: `${colors.dim}.${RESET}`,
|
|
298
|
+
// Privacy indicators (ASCII)
|
|
299
|
+
internal: `${colors.purple}[INTERNAL]${RESET}`,
|
|
300
|
+
publicOk: `${colors.green}[PUBLIC]${RESET}`,
|
|
301
|
+
caution: `${colors.yellow}[CAUTION]${RESET}`
|
|
195
302
|
};
|
|
303
|
+
function privacyHeader(level = "internal") {
|
|
304
|
+
const headers = {
|
|
305
|
+
internal: ` ${icons.internal} ${colors.purple}INTERNAL ONLY${RESET} ${colors.dim}\u2014 not for external sharing${RESET}`,
|
|
306
|
+
public: ` ${icons.publicOk} ${colors.green}PUBLIC OK${RESET} ${colors.dim}\u2014 safe to share externally${RESET}`,
|
|
307
|
+
caution: ` ${icons.caution} ${colors.yellow}CAUTION${RESET} ${colors.dim}\u2014 review before sharing${RESET}`
|
|
308
|
+
};
|
|
309
|
+
return headers[level] + "\n " + colors.dim + "\u2500".repeat(50) + RESET;
|
|
310
|
+
}
|
|
196
311
|
function stripAnsi(str) {
|
|
197
312
|
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
198
313
|
}
|
|
199
|
-
function isAiCli() {
|
|
200
|
-
if (process.env.CLAUDECODE !== void 0) return true;
|
|
201
|
-
if (process.env.GEMINI_API_KEY !== void 0) return true;
|
|
202
|
-
if (process.env.CURSOR_CHANNEL !== void 0) return true;
|
|
203
|
-
if (process.env.CODY_AUTH !== void 0) return true;
|
|
204
|
-
if (process.env.CODEIUM_API_KEY !== void 0) return true;
|
|
205
|
-
if (process.env.GITHUB_COPILOT_CLI !== void 0) return true;
|
|
206
|
-
if (process.env.AIDER_MODEL !== void 0) return true;
|
|
207
|
-
if (process.env.CONTINUE_GLOBAL_DIR !== void 0) return true;
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
function isColorEnabled() {
|
|
211
|
-
if (process.env.NO_COLOR !== void 0) return false;
|
|
212
|
-
if (process.env.FORCE_COLOR !== void 0) return true;
|
|
213
|
-
if (isAiCli()) return true;
|
|
214
|
-
return process.stdout.isTTY ?? false;
|
|
215
|
-
}
|
|
216
314
|
function write(str) {
|
|
217
|
-
|
|
218
|
-
process.stdout.write(output);
|
|
315
|
+
process.stdout.write(str);
|
|
219
316
|
}
|
|
220
317
|
function writeLine(str = "") {
|
|
221
|
-
|
|
222
|
-
process.stdout.write(output + "\n");
|
|
318
|
+
process.stdout.write(str + "\n");
|
|
223
319
|
}
|
|
224
320
|
var SPARKLINE_BLOCKS = USE_UNICODE ? ["\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"] : ["_", ".", "-", "=", "+", "#", "#", "#"];
|
|
225
321
|
function sparkline(values, _width) {
|
|
@@ -261,6 +357,8 @@ function barChart(value, max, width = 20, label) {
|
|
|
261
357
|
}
|
|
262
358
|
|
|
263
359
|
export {
|
|
360
|
+
isColorEnabled,
|
|
361
|
+
isAiCli,
|
|
264
362
|
ESC,
|
|
265
363
|
RESET,
|
|
266
364
|
rgb,
|
|
@@ -277,12 +375,11 @@ export {
|
|
|
277
375
|
truncate,
|
|
278
376
|
spinnerFrames,
|
|
279
377
|
icons,
|
|
378
|
+
privacyHeader,
|
|
280
379
|
stripAnsi,
|
|
281
|
-
isAiCli,
|
|
282
|
-
isColorEnabled,
|
|
283
380
|
write,
|
|
284
381
|
writeLine,
|
|
285
382
|
sparkline,
|
|
286
383
|
barChart
|
|
287
384
|
};
|
|
288
|
-
//# sourceMappingURL=chunk-
|
|
385
|
+
//# sourceMappingURL=chunk-N7KDWU4W.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/terminal.ts"],"sourcesContent":["// Terminal utilities - Bun-style approach\n// Raw ANSI for performance, no heavy deps\n\n// Check if we should use colors (TTY detection)\n// Evaluated once at module load — must be before any ANSI constant definitions\nexport function isColorEnabled(): boolean {\n // NO_COLOR environment variable (standard: https://no-color.org/)\n if (process.env.NO_COLOR !== undefined) return false;\n // Force color via environment variable\n if (process.env.FORCE_COLOR !== undefined) return true;\n // AI coding assistants - enable colors (they support ANSI)\n if (isAiCli()) return true;\n // Check if output is a TTY\n return process.stdout.isTTY ?? false;\n}\n\n// Check if running under an AI coding assistant\nexport function isAiCli(): boolean {\n // Claude Code\n if (process.env.CLAUDECODE !== undefined) return true;\n // Gemini CLI\n if (process.env.GEMINI_API_KEY !== undefined) return true;\n // Cursor\n if (process.env.CURSOR_CHANNEL !== undefined) return true;\n // Sourcegraph Cody\n if (process.env.CODY_AUTH !== undefined) return true;\n // Windsurf (Codeium)\n if (process.env.CODEIUM_API_KEY !== undefined) return true;\n // Copilot CLI\n if (process.env.GITHUB_COPILOT_CLI !== undefined) return true;\n // Aider\n if (process.env.AIDER_MODEL !== undefined) return true;\n // Continue.dev\n if (process.env.CONTINUE_GLOBAL_DIR !== undefined) return true;\n return false;\n}\n\n// Master color toggle — when false, all ANSI codes become empty strings\nconst COLOR_ENABLED = isColorEnabled();\n\n// ANSI escape codes (empty when piped/NO_COLOR)\nexport const ESC = COLOR_ENABLED ? '\\x1b[' : '';\nexport const RESET = COLOR_ENABLED ? '\\x1b[0m' : '';\n\n// Detect true color support\nfunction supportsTrueColor(): boolean {\n if (!COLOR_ENABLED) return false;\n const colorterm = process.env.COLORTERM;\n if (colorterm === 'truecolor' || colorterm === '24bit') return true;\n const term = process.env.TERM || '';\n if (term.includes('256color') || term.includes('truecolor')) return true;\n // iTerm2, VS Code, modern terminals\n if (process.env.TERM_PROGRAM === 'iTerm.app') return true;\n if (process.env.TERM_PROGRAM === 'vscode') return true;\n if (process.env.WT_SESSION) return true; // Windows Terminal\n return false;\n}\n\nconst USE_TRUE_COLOR = supportsTrueColor();\n\n// Colors - use 24-bit RGB if supported, fallback to basic ANSI\n// Returns empty string when colors are disabled (piped output, NO_COLOR)\nexport const rgb = (r: number, g: number, b: number) => COLOR_ENABLED ? `\\x1b[38;2;${r};${g};${b}m` : '';\nexport const bgRgb = (r: number, g: number, b: number) => COLOR_ENABLED ? `\\x1b[48;2;${r};${g};${b}m` : '';\n\n// Detect light terminal background\n// Uses COLORFGBG env var (format: \"fg;bg\" where bg > 7 = light)\n// or SQUADS_THEME env var for explicit override\nfunction isLightBackground(): boolean {\n const theme = process.env.SQUADS_THEME?.toLowerCase();\n if (theme === 'light') return true;\n if (theme === 'dark') return false;\n\n // COLORFGBG is set by some terminals (xterm, rxvt, etc.)\n // Format: \"foreground;background\" where numbers are ANSI color indices\n // Light backgrounds typically use indices > 7 (white = 15, light gray = 7)\n const colorfgbg = process.env.COLORFGBG;\n if (colorfgbg) {\n const parts = colorfgbg.split(';');\n const bg = parseInt(parts[parts.length - 1], 10);\n if (!isNaN(bg) && (bg === 15 || bg === 7)) return true;\n }\n\n return false;\n}\n\nconst USE_LIGHT_MODE = isLightBackground();\n\n// Empty palette for when colors are disabled\nconst noColors = {\n purple: '', pink: '', cyan: '', green: '', yellow: '',\n red: '', gray: '', dim: '', white: '',\n};\n\n// Basic ANSI color codes (work everywhere)\nconst ansiDark = {\n purple: '\\x1b[35m', // magenta\n pink: '\\x1b[95m', // bright magenta\n cyan: '\\x1b[36m', // cyan\n green: '\\x1b[32m', // green\n yellow: '\\x1b[33m', // yellow\n red: '\\x1b[31m', // red\n gray: '\\x1b[90m', // bright black (gray)\n dim: '\\x1b[90m', // bright black (gray)\n white: '\\x1b[97m', // bright white\n};\n\nconst ansiLight = {\n purple: '\\x1b[35m', // magenta (same, works on light)\n pink: '\\x1b[35m', // magenta (bright is too light)\n cyan: '\\x1b[36m', // cyan\n green: '\\x1b[32m', // green\n yellow: '\\x1b[33m', // yellow\n red: '\\x1b[31m', // red\n gray: '\\x1b[90m', // bright black (gray)\n dim: '\\x1b[90m', // bright black (gray)\n white: '\\x1b[30m', // black for light backgrounds\n};\n\n// Dark mode palette (original - for dark backgrounds)\nconst darkPalette = {\n purple: rgb(168, 85, 247), // #a855f7\n pink: rgb(236, 72, 153), // #ec4899\n cyan: rgb(6, 182, 212), // #06b6d4\n green: rgb(16, 185, 129), // #10b981\n yellow: rgb(234, 179, 8), // #eab308\n red: rgb(239, 68, 68), // #ef4444\n gray: rgb(107, 114, 128), // #6b7280\n dim: rgb(75, 85, 99), // #4b5563\n white: rgb(255, 255, 255),\n};\n\n// Light mode palette (darker colors for contrast on light backgrounds)\nconst lightPalette = {\n purple: rgb(124, 58, 237), // #7c3aed (purple-600)\n pink: rgb(219, 39, 119), // #db2777 (pink-600)\n cyan: rgb(8, 145, 178), // #0891b2 (cyan-600)\n green: rgb(22, 163, 74), // #16a34a (green-600)\n yellow: rgb(202, 138, 4), // #ca8a04 (yellow-600)\n red: rgb(220, 38, 38), // #dc2626 (red-600)\n gray: rgb(75, 85, 99), // #4b5563 (gray-600)\n dim: rgb(107, 114, 128), // #6b7280 (gray-500)\n white: rgb(0, 0, 0), // black for light backgrounds\n};\n\n// Named colors (our brand palette) - with theme and fallback support\n// Returns empty strings when colors are disabled (piped output, NO_COLOR)\nexport const colors = !COLOR_ENABLED\n ? noColors\n : USE_TRUE_COLOR\n ? (USE_LIGHT_MODE ? lightPalette : darkPalette)\n : (USE_LIGHT_MODE ? ansiLight : ansiDark);\n\n// Styles (empty when colors disabled)\nexport const bold = COLOR_ENABLED ? '\\x1b[1m' : '';\nexport const dim = COLOR_ENABLED ? '\\x1b[2m' : '';\n\n// Cursor control (no-op when piped)\nexport const cursor = COLOR_ENABLED ? {\n hide: '\\x1b[?25l',\n show: '\\x1b[?25h',\n up: (n = 1) => `\\x1b[${n}A`,\n down: (n = 1) => `\\x1b[${n}B`,\n left: (n = 1) => `\\x1b[${n}D`,\n right: (n = 1) => `\\x1b[${n}C`,\n to: (x: number, y: number) => `\\x1b[${y};${x}H`,\n save: '\\x1b[s',\n restore: '\\x1b[u',\n} : {\n hide: '',\n show: '',\n up: (_n = 1) => '',\n down: (_n = 1) => '',\n left: (_n = 1) => '',\n right: (_n = 1) => '',\n to: (_x: number, _y: number) => '',\n save: '',\n restore: '',\n};\n\n// Clear (no-op when piped)\nexport const clear = COLOR_ENABLED ? {\n line: '\\x1b[2K',\n toEnd: '\\x1b[0K',\n screen: '\\x1b[2J\\x1b[0;0H',\n} : {\n line: '',\n toEnd: '',\n screen: '',\n};\n\n// Check if terminal supports Unicode\nfunction supportsUnicode(): boolean {\n // Windows CMD typically doesn't support Unicode well\n if (process.platform === 'win32') {\n // Windows Terminal supports Unicode\n if (process.env.WT_SESSION) return true;\n // ConEmu supports Unicode\n if (process.env.ConEmuTask) return true;\n // Fallback: check for UTF-8 codepage\n if (process.env.LANG?.includes('UTF') || process.env.LC_ALL?.includes('UTF')) return true;\n return false;\n }\n // Most modern terminals on macOS/Linux support Unicode\n // But AI CLIs might not render them well in their output\n // Force ASCII for known problematic environments\n if (process.env.SQUADS_ASCII !== undefined) return false;\n return true;\n}\n\nconst USE_UNICODE = supportsUnicode();\n\n// Gradient text (purple → pink → cyan)\nexport function gradient(text: string): string {\n if (!COLOR_ENABLED) return text;\n\n const stops = [\n [168, 85, 247], // purple\n [192, 132, 252], // purple-light\n [232, 121, 249], // pink\n [244, 114, 182], // pink-light\n [251, 113, 133], // rose\n ];\n\n let result = '';\n for (let i = 0; i < text.length; i++) {\n const t = i / Math.max(text.length - 1, 1);\n const stopIndex = t * (stops.length - 1);\n const lower = Math.floor(stopIndex);\n const upper = Math.min(lower + 1, stops.length - 1);\n const blend = stopIndex - lower;\n\n const r = Math.round(stops[lower][0] + (stops[upper][0] - stops[lower][0]) * blend);\n const g = Math.round(stops[lower][1] + (stops[upper][1] - stops[lower][1]) * blend);\n const b = Math.round(stops[lower][2] + (stops[upper][2] - stops[lower][2]) * blend);\n\n result += rgb(r, g, b) + text[i];\n }\n return result + RESET;\n}\n\n// Progress bar characters\nconst BAR_FILLED = USE_UNICODE ? '━' : '=';\nconst BAR_EMPTY = USE_UNICODE ? '━' : '-';\n\n// Progress bar with gradient fill\nexport function progressBar(percent: number, width = 20): string {\n // Clamp values to prevent negative repeat counts\n const clampedPercent = Math.max(0, Math.min(100, percent || 0));\n const filled = Math.round((clampedPercent / 100) * width);\n const empty = Math.max(0, width - filled);\n\n let bar = '';\n for (let i = 0; i < filled; i++) {\n const t = i / Math.max(filled - 1, 1);\n const r = Math.round(16 + (168 - 16) * t);\n const g = Math.round(185 + (85 - 185) * t);\n const b = Math.round(129 + (247 - 129) * t);\n bar += rgb(r, g, b) + BAR_FILLED;\n }\n\n bar += colors.dim + BAR_EMPTY.repeat(empty) + RESET;\n return bar;\n}\n\n// Box drawing - with ASCII fallback\nexport const box = USE_UNICODE ? {\n topLeft: '┌',\n topRight: '┐',\n bottomLeft: '└',\n bottomRight: '┘',\n horizontal: '─',\n vertical: '│',\n teeRight: '├',\n teeLeft: '┤',\n} : {\n topLeft: '+',\n topRight: '+',\n bottomLeft: '+',\n bottomRight: '+',\n horizontal: '-',\n vertical: '|',\n teeRight: '+',\n teeLeft: '+',\n};\n\n// Format helpers\nexport function padEnd(str: string, len: number): string {\n // Strip ANSI codes for length calculation\n const visible = str.replace(/\\x1b\\[[0-9;]*m/g, '');\n const pad = Math.max(0, len - visible.length);\n return str + ' '.repeat(pad);\n}\n\nexport function truncate(str: string, len: number): string {\n const visible = str.replace(/\\x1b\\[[0-9;]*m/g, '');\n if (visible.length <= len) return str;\n\n // Simple truncation (won't handle mid-ANSI truncation perfectly)\n let result = '';\n let count = 0;\n let i = 0;\n\n while (i < str.length && count < len - 1) {\n if (str[i] === '\\x1b') {\n const end = str.indexOf('m', i);\n if (end !== -1) {\n result += str.slice(i, end + 1);\n i = end + 1;\n continue;\n }\n }\n result += str[i];\n count++;\n i++;\n }\n\n return result + colors.dim + '…' + RESET;\n}\n\n// Spinner frames - with ASCII fallback\nexport const spinnerFrames = USE_UNICODE\n ? ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']\n : ['-', '\\\\', '|', '/'];\n\n// Status icons - with ASCII fallback\nexport const icons = USE_UNICODE ? {\n success: `${colors.green}●${RESET}`,\n warning: `${colors.yellow}○${RESET}`,\n error: `${colors.red}●${RESET}`,\n pending: `${colors.dim}○${RESET}`,\n active: `${colors.green}●${RESET}`,\n running: `${colors.yellow}◆${RESET}`,\n progress: `${colors.cyan}◆${RESET}`,\n empty: `${colors.dim}◇${RESET}`,\n // Privacy indicators\n internal: `${colors.purple}🔒${RESET}`,\n publicOk: `${colors.green}🌐${RESET}`,\n caution: `${colors.yellow}⚠️${RESET}`,\n} : {\n success: `${colors.green}*${RESET}`,\n warning: `${colors.yellow}!${RESET}`,\n error: `${colors.red}x${RESET}`,\n pending: `${colors.dim}o${RESET}`,\n active: `${colors.green}*${RESET}`,\n running: `${colors.yellow}>${RESET}`,\n progress: `${colors.cyan}>${RESET}`,\n empty: `${colors.dim}.${RESET}`,\n // Privacy indicators (ASCII)\n internal: `${colors.purple}[INTERNAL]${RESET}`,\n publicOk: `${colors.green}[PUBLIC]${RESET}`,\n caution: `${colors.yellow}[CAUTION]${RESET}`,\n};\n\n// Privacy level type\nexport type PrivacyLevel = 'internal' | 'public' | 'caution';\n\n// Privacy header - shows trust indicator at top of output\nexport function privacyHeader(level: PrivacyLevel = 'internal'): string {\n const headers = {\n internal: ` ${icons.internal} ${colors.purple}INTERNAL ONLY${RESET} ${colors.dim}— not for external sharing${RESET}`,\n public: ` ${icons.publicOk} ${colors.green}PUBLIC OK${RESET} ${colors.dim}— safe to share externally${RESET}`,\n caution: ` ${icons.caution} ${colors.yellow}CAUTION${RESET} ${colors.dim}— review before sharing${RESET}`,\n };\n return headers[level] + '\\n ' + colors.dim + '─'.repeat(50) + RESET;\n}\n\n// Strip ANSI escape codes from a string\nexport function stripAnsi(str: string): string {\n return str.replace(/\\x1b\\[[0-9;]*m/g, '');\n}\n\n// Write without newline\nexport function write(str: string): void {\n process.stdout.write(str);\n}\n\n// Write line\nexport function writeLine(str = ''): void {\n process.stdout.write(str + '\\n');\n}\n\n// Sparkline characters - Unicode blocks vs ASCII\nconst SPARKLINE_BLOCKS = USE_UNICODE\n ? ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█']\n : ['_', '.', '-', '=', '+', '#', '#', '#'];\n\n// Sparkline chart using block characters\nexport function sparkline(values: number[], _width?: number): string {\n if (values.length === 0) return '';\n\n const max = Math.max(...values, 1);\n\n let result = '';\n for (const val of values) {\n const normalized = val / max;\n const blockIndex = Math.min(Math.floor(normalized * SPARKLINE_BLOCKS.length), SPARKLINE_BLOCKS.length - 1);\n\n // Color gradient from dim to cyan to green based on value\n if (normalized === 0) {\n result += colors.dim + SPARKLINE_BLOCKS[0];\n } else if (normalized < 0.5) {\n result += colors.cyan + SPARKLINE_BLOCKS[blockIndex];\n } else {\n result += colors.green + SPARKLINE_BLOCKS[blockIndex];\n }\n }\n\n return result + RESET;\n}\n\n// Bar chart (horizontal)\nexport function barChart(value: number, max: number, width: number = 20, label?: string): string {\n // Guard against invalid inputs to prevent crashes\n const safeValue = Math.max(0, value || 0);\n const safeMax = Math.max(1, max || 1); // Prevent division by zero\n const ratio = Math.min(1, safeValue / safeMax); // Clamp ratio to 0-1\n const filled = Math.round(ratio * width);\n const empty = width - filled;\n\n let bar = '';\n for (let i = 0; i < filled; i++) {\n const t = i / Math.max(filled - 1, 1);\n // Green to cyan gradient\n const r = Math.round(16 + (6 - 16) * t);\n const g = Math.round(185 + (182 - 185) * t);\n const b = Math.round(129 + (212 - 129) * t);\n bar += rgb(r, g, b) + BAR_FILLED;\n }\n\n bar += colors.dim + BAR_EMPTY.repeat(empty) + RESET;\n\n if (label) {\n return `${bar} ${label}`;\n }\n return bar;\n}\n"],"mappings":"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","names":[]}
|