pokegent 2.0.2 → 2.0.3

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 (2) hide show
  1. package/dist/index.js +502 -463
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3398,10 +3398,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
3398
3398
  * @param {string} [path]
3399
3399
  * @return {(string|null|Command)}
3400
3400
  */
3401
- executableDir(path5) {
3402
- if (path5 === void 0)
3401
+ executableDir(path7) {
3402
+ if (path7 === void 0)
3403
3403
  return this._executableDir;
3404
- this._executableDir = path5;
3404
+ this._executableDir = path7;
3405
3405
  return this;
3406
3406
  }
3407
3407
  /**
@@ -7721,12 +7721,12 @@ var PathBase = class {
7721
7721
  /**
7722
7722
  * Get the Path object referenced by the string path, resolved from this Path
7723
7723
  */
7724
- resolve(path5) {
7725
- if (!path5) {
7724
+ resolve(path7) {
7725
+ if (!path7) {
7726
7726
  return this;
7727
7727
  }
7728
- const rootPath = this.getRootString(path5);
7729
- const dir = path5.substring(rootPath.length);
7728
+ const rootPath = this.getRootString(path7);
7729
+ const dir = path7.substring(rootPath.length);
7730
7730
  const dirParts = dir.split(this.splitSep);
7731
7731
  const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
7732
7732
  return result;
@@ -8478,8 +8478,8 @@ var PathWin32 = class _PathWin32 extends PathBase {
8478
8478
  /**
8479
8479
  * @internal
8480
8480
  */
8481
- getRootString(path5) {
8482
- return win32.parse(path5).root;
8481
+ getRootString(path7) {
8482
+ return win32.parse(path7).root;
8483
8483
  }
8484
8484
  /**
8485
8485
  * @internal
@@ -8525,8 +8525,8 @@ var PathPosix = class _PathPosix extends PathBase {
8525
8525
  /**
8526
8526
  * @internal
8527
8527
  */
8528
- getRootString(path5) {
8529
- return path5.startsWith("/") ? "/" : "";
8528
+ getRootString(path7) {
8529
+ return path7.startsWith("/") ? "/" : "";
8530
8530
  }
8531
8531
  /**
8532
8532
  * @internal
@@ -8575,8 +8575,8 @@ var PathScurryBase = class {
8575
8575
  *
8576
8576
  * @internal
8577
8577
  */
8578
- constructor(cwd = process.cwd(), pathImpl, sep2, { nocase, childrenCacheSize = 16 * 1024, fs: fs7 = defaultFS } = {}) {
8579
- this.#fs = fsFromOption(fs7);
8578
+ constructor(cwd = process.cwd(), pathImpl, sep2, { nocase, childrenCacheSize = 16 * 1024, fs: fs8 = defaultFS } = {}) {
8579
+ this.#fs = fsFromOption(fs8);
8580
8580
  if (cwd instanceof URL || cwd.startsWith("file://")) {
8581
8581
  cwd = fileURLToPath(cwd);
8582
8582
  }
@@ -8615,11 +8615,11 @@ var PathScurryBase = class {
8615
8615
  /**
8616
8616
  * Get the depth of a provided path, string, or the cwd
8617
8617
  */
8618
- depth(path5 = this.cwd) {
8619
- if (typeof path5 === "string") {
8620
- path5 = this.cwd.resolve(path5);
8618
+ depth(path7 = this.cwd) {
8619
+ if (typeof path7 === "string") {
8620
+ path7 = this.cwd.resolve(path7);
8621
8621
  }
8622
- return path5.depth();
8622
+ return path7.depth();
8623
8623
  }
8624
8624
  /**
8625
8625
  * Return the cache of child entries. Exposed so subclasses can create
@@ -9106,9 +9106,9 @@ var PathScurryBase = class {
9106
9106
  process3();
9107
9107
  return results;
9108
9108
  }
9109
- chdir(path5 = this.cwd) {
9109
+ chdir(path7 = this.cwd) {
9110
9110
  const oldCwd = this.cwd;
9111
- this.cwd = typeof path5 === "string" ? this.cwd.resolve(path5) : path5;
9111
+ this.cwd = typeof path7 === "string" ? this.cwd.resolve(path7) : path7;
9112
9112
  this.cwd[setAsCwd](oldCwd);
9113
9113
  }
9114
9114
  };
@@ -9134,8 +9134,8 @@ var PathScurryWin32 = class extends PathScurryBase {
9134
9134
  /**
9135
9135
  * @internal
9136
9136
  */
9137
- newRoot(fs7) {
9138
- return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs7 });
9137
+ newRoot(fs8) {
9138
+ return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs8 });
9139
9139
  }
9140
9140
  /**
9141
9141
  * Return true if the provided path string is an absolute path
@@ -9163,8 +9163,8 @@ var PathScurryPosix = class extends PathScurryBase {
9163
9163
  /**
9164
9164
  * @internal
9165
9165
  */
9166
- newRoot(fs7) {
9167
- return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs7 });
9166
+ newRoot(fs8) {
9167
+ return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs8 });
9168
9168
  }
9169
9169
  /**
9170
9170
  * Return true if the provided path string is an absolute path
@@ -9464,8 +9464,8 @@ var MatchRecord = class {
9464
9464
  }
9465
9465
  // match, absolute, ifdir
9466
9466
  entries() {
9467
- return [...this.store.entries()].map(([path5, n]) => [
9468
- path5,
9467
+ return [...this.store.entries()].map(([path7, n]) => [
9468
+ path7,
9469
9469
  !!(n & 2),
9470
9470
  !!(n & 1)
9471
9471
  ]);
@@ -9670,9 +9670,9 @@ var GlobUtil = class {
9670
9670
  signal;
9671
9671
  maxDepth;
9672
9672
  includeChildMatches;
9673
- constructor(patterns, path5, opts) {
9673
+ constructor(patterns, path7, opts) {
9674
9674
  this.patterns = patterns;
9675
- this.path = path5;
9675
+ this.path = path7;
9676
9676
  this.opts = opts;
9677
9677
  this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
9678
9678
  this.includeChildMatches = opts.includeChildMatches !== false;
@@ -9691,11 +9691,11 @@ var GlobUtil = class {
9691
9691
  });
9692
9692
  }
9693
9693
  }
9694
- #ignored(path5) {
9695
- return this.seen.has(path5) || !!this.#ignore?.ignored?.(path5);
9694
+ #ignored(path7) {
9695
+ return this.seen.has(path7) || !!this.#ignore?.ignored?.(path7);
9696
9696
  }
9697
- #childrenIgnored(path5) {
9698
- return !!this.#ignore?.childrenIgnored?.(path5);
9697
+ #childrenIgnored(path7) {
9698
+ return !!this.#ignore?.childrenIgnored?.(path7);
9699
9699
  }
9700
9700
  // backpressure mechanism
9701
9701
  pause() {
@@ -9910,8 +9910,8 @@ var GlobUtil = class {
9910
9910
  };
9911
9911
  var GlobWalker = class extends GlobUtil {
9912
9912
  matches = /* @__PURE__ */ new Set();
9913
- constructor(patterns, path5, opts) {
9914
- super(patterns, path5, opts);
9913
+ constructor(patterns, path7, opts) {
9914
+ super(patterns, path7, opts);
9915
9915
  }
9916
9916
  matchEmit(e) {
9917
9917
  this.matches.add(e);
@@ -9948,8 +9948,8 @@ var GlobWalker = class extends GlobUtil {
9948
9948
  };
9949
9949
  var GlobStream = class extends GlobUtil {
9950
9950
  results;
9951
- constructor(patterns, path5, opts) {
9952
- super(patterns, path5, opts);
9951
+ constructor(patterns, path7, opts) {
9952
+ super(patterns, path7, opts);
9953
9953
  this.results = new Minipass({
9954
9954
  signal: this.signal,
9955
9955
  objectMode: true
@@ -10245,26 +10245,26 @@ glob.glob = glob;
10245
10245
  // src/constants.ts
10246
10246
  import os from "os";
10247
10247
  var home = os.homedir();
10248
- var APP_TITLE = "\u25D3 Pok\xE9gent";
10248
+ var APP_TITLE = "Agentic";
10249
10249
  var VERSION = "2.0.0";
10250
10250
  var REFRESH_INTERVAL = 2e3;
10251
10251
  var CLI_SIGNATURES = {
10252
- "Mewtwo": { process: ["claude", "claude-code"], config: ["~/.claude", "~/.claude.json", "~/.config/claude"], icon: "\u{1F52E}", pokemonId: 150 },
10253
- "Venusaur": { process: ["codex", "openai-codex"], config: ["~/.codex", "~/.config/codex"], icon: "\u{1F343}", pokemonId: 3 },
10254
- "Blastoise": { process: ["copilot", "github-copilot"], config: ["~/.copilot", "~/.config/github-copilot"], icon: "\u{1F422}", pokemonId: 9 },
10255
- "Pikachu": { process: ["gemini", "gemini-cli"], config: ["~/.gemini", "~/.config/gemini"], icon: "\u26A1", pokemonId: 25 },
10256
- "Eevee": { process: ["cursor"], config: ["~/.cursor", "~/.cursor-server"], icon: "\u{1F98A}", pokemonId: 133 },
10257
- "Charizard": { process: ["amp", "amp-cli"], config: ["~/.amp", "~/.config/amp"], icon: "\u{1F525}", pokemonId: 6 },
10258
- "Charmander": { process: ["cline"], config: ["~/.cline", "~/.vscode/extensions/saoudrizwan.claude-dev-*"], icon: "\u{1F98E}", pokemonId: 4 },
10259
- "Gengar": { process: ["roo", "roo-code"], config: ["~/.roo", "~/.roo-code"], icon: "\u{1F47B}", pokemonId: 94 },
10260
- "Snorlax": { process: ["kilo", "kilo-code"], config: ["~/.kilo", "~/.kilo-code"], icon: "\u{1F43B}", pokemonId: 143 },
10261
- "Zubat": { process: ["kiro"], config: ["~/.kiro", "~/.config/kiro"], icon: "\u{1F987}", pokemonId: 41 },
10262
- "Jigglypuff": { process: ["crush"], config: ["~/.crush"], icon: "\u{1F388}", pokemonId: 39 },
10263
- "Ditto": { process: ["opencode"], config: ["~/.opencode", "~/.config/opencode"], icon: "\u{1F36E}", pokemonId: 132 },
10264
- "Machamp": { process: ["factory", "factory-droid"], config: ["~/.factory-droid"], icon: "\u{1F4AA}", pokemonId: 68 },
10265
- "Rayquaza": { process: ["antigravity", "ag-cli"], config: ["~/.antigravity"], icon: "\u{1F409}", pokemonId: 384 },
10266
- "Lapras": { process: ["kimi", "kimi-cli"], config: ["~/.kimi", "~/.config/kimi"], icon: "\u26F5", pokemonId: 131 },
10267
- "Dragonite": { process: ["qwen", "qwen-code"], config: ["~/.qwen", "~/.config/qwen"], icon: "\u{1F409}", pokemonId: 149 }
10252
+ "claude-code": { process: ["claude", "claude-code"], config: ["~/.claude", "~/.claude.json", "~/.config/claude"], icon: "\u{1F52E}", pokemonId: 150, pokemonSlug: "mewtwo", pokemonName: "Mewtwo" },
10253
+ "codex": { process: ["codex", "openai-codex"], config: ["~/.codex", "~/.config/codex"], icon: "\u{1F343}", pokemonId: 3, pokemonSlug: "venusaur", pokemonName: "Venusaur" },
10254
+ "copilot": { process: ["copilot", "github-copilot"], config: ["~/.copilot", "~/.config/github-copilot"], icon: "\u{1F422}", pokemonId: 9, pokemonSlug: "blastoise", pokemonName: "Blastoise" },
10255
+ "gemini-cli": { process: ["gemini", "gemini-cli"], config: ["~/.gemini", "~/.config/gemini"], icon: "\u26A1", pokemonId: 25, pokemonSlug: "pikachu", pokemonName: "Pikachu" },
10256
+ "cursor": { process: ["cursor"], config: ["~/.cursor", "~/.cursor-server"], icon: "\u{1F98A}", pokemonId: 133, pokemonSlug: "eevee", pokemonName: "Eevee" },
10257
+ "amp": { process: ["amp", "amp-cli"], config: ["~/.amp", "~/.config/amp"], icon: "\u{1F525}", pokemonId: 6, pokemonSlug: "charizard", pokemonName: "Charizard" },
10258
+ "cline": { process: ["cline"], config: ["~/.cline", "~/.vscode/extensions/saoudrizwan.claude-dev-*"], icon: "\u{1F98E}", pokemonId: 4, pokemonSlug: "charmander", pokemonName: "Charmander" },
10259
+ "roo-code": { process: ["roo", "roo-code"], config: ["~/.roo", "~/.roo-code"], icon: "\u{1F47B}", pokemonId: 94, pokemonSlug: "gengar", pokemonName: "Gengar" },
10260
+ "kilo-code": { process: ["kilo", "kilo-code"], config: ["~/.kilo", "~/.kilo-code"], icon: "\u{1F43B}", pokemonId: 143, pokemonSlug: "snorlax", pokemonName: "Snorlax" },
10261
+ "kiro": { process: ["kiro"], config: ["~/.kiro", "~/.config/kiro"], icon: "\u{1F987}", pokemonId: 41, pokemonSlug: "zubat", pokemonName: "Zubat" },
10262
+ "crush": { process: ["crush"], config: ["~/.crush"], icon: "\u{1F388}", pokemonId: 39, pokemonSlug: "jigglypuff", pokemonName: "Jigglypuff" },
10263
+ "opencode": { process: ["opencode"], config: ["~/.opencode", "~/.config/opencode"], icon: "\u{1F36E}", pokemonId: 132, pokemonSlug: "ditto", pokemonName: "Ditto" },
10264
+ "factory": { process: ["factory", "factory-droid"], config: ["~/.factory-droid"], icon: "\u{1F4AA}", pokemonId: 68, pokemonSlug: "machamp", pokemonName: "Machamp" },
10265
+ "antigravity": { process: ["antigravity", "ag-cli"], config: ["~/.antigravity"], icon: "\u{1F409}", pokemonId: 384, pokemonSlug: "rayquaza", pokemonName: "Rayquaza" },
10266
+ "kimi": { process: ["kimi", "kimi-cli"], config: ["~/.kimi", "~/.config/kimi"], icon: "\u26F5", pokemonId: 131, pokemonSlug: "lapras", pokemonName: "Lapras" },
10267
+ "qwen": { process: ["qwen", "qwen-code"], config: ["~/.qwen", "~/.config/qwen"], icon: "\u{1F409}", pokemonId: 149, pokemonSlug: "dragonite", pokemonName: "Dragonite" }
10268
10268
  };
10269
10269
  var MCP_SCAN_PATHS = [
10270
10270
  { path: "~/.claude/mcpServers.json", source: "Claude" },
@@ -10350,7 +10350,7 @@ async function scanClis() {
10350
10350
  }
10351
10351
  }
10352
10352
  }
10353
- results.push({ name, icon: sig.icon, state, pid, cpuPct, memMb, uptimeS, pokemonId: sig.pokemonId });
10353
+ results.push({ name, icon: sig.icon, state, pid, cpuPct, memMb, uptimeS, pokemonId: sig.pokemonId, pokemonSlug: sig.pokemonSlug, pokemonName: sig.pokemonName });
10354
10354
  }
10355
10355
  return results;
10356
10356
  }
@@ -10627,10 +10627,10 @@ async function walkForMtime(dir, callback) {
10627
10627
  }
10628
10628
  async function getEnvIntegrity() {
10629
10629
  let score2 = 1;
10630
- const { execSync: execSync2 } = await import("child_process");
10630
+ const { execSync } = await import("child_process");
10631
10631
  for (const cmd of ENV_CHECKS) {
10632
10632
  try {
10633
- execSync2(`which ${cmd}`, { stdio: "ignore" });
10633
+ execSync(`which ${cmd}`, { stdio: "ignore" });
10634
10634
  } catch {
10635
10635
  score2 -= 0.15;
10636
10636
  }
@@ -10698,20 +10698,20 @@ function getBadges(clis, mcp, models, burn) {
10698
10698
  const running = clis.filter((c) => c.state === "RUNNING").length;
10699
10699
  const providerCount = getProviderCount(models);
10700
10700
  if (mcp.length >= 10)
10701
- badges.push("\u{1F3C6} Pok\xE9dex Master");
10701
+ badges.push("\u{1F3C6} MCP Master");
10702
10702
  if (running >= 3)
10703
- badges.push("\u{1F984} Legendary Trainer");
10703
+ badges.push("\u{1F984} Power Orchestrator");
10704
10704
  if (providerCount >= 3)
10705
- badges.push("\u{1F9EC} Hybrid Evolution");
10705
+ badges.push("\u{1F9EC} Hybrid System");
10706
10706
  if (burn.tokenVelocity >= 1e4)
10707
- badges.push("\u{1F525} Blast Burn");
10707
+ badges.push("\u{1F525} High Throughput");
10708
10708
  if (burn.sessionCount >= 100)
10709
- badges.push("\u{1F48E} Elite Four");
10709
+ badges.push("\u{1F48E} Session Veteran");
10710
10710
  if (agentsPct(clis) > 50 && mcpPct(mcp) > 50 && modelsPct(models) > 50 && burnPct(burn) > 50) {
10711
- badges.push("\u26A1 Thunder Shock");
10711
+ badges.push("\u26A1 Peak Synergy");
10712
10712
  }
10713
10713
  if (models.length >= 5)
10714
- badges.push("\u{1F310} Safari Zone Master");
10714
+ badges.push("\u{1F310} Model Collector");
10715
10715
  return badges;
10716
10716
  }
10717
10717
  function agentsPct(clis) {
@@ -10731,23 +10731,19 @@ function burnPct(burn) {
10731
10731
  }
10732
10732
  function rarityLabel(score2) {
10733
10733
  if (score2 >= 900)
10734
- return "\u{1F31F} MYTHICAL CHAMPION \u2014 Top 1%";
10734
+ return "\u{1F31F} ELITE ARCHITECT \u2014 Top 1%";
10735
10735
  if (score2 >= 750)
10736
- return "\u{1F48E} SHINY LEGENDARY \u2014 Top 5%";
10736
+ return "\u{1F48E} EXPERT SYSTEM \u2014 Top 5%";
10737
10737
  if (score2 >= 600)
10738
- return "\u{1F947} POK\xC9MON MASTER \u2014 Top 15%";
10738
+ return "\u{1F947} ADVANCED SYSTEM \u2014 Top 15%";
10739
10739
  if (score2 >= 400)
10740
- return "\u{1F948} GYM LEADER \u2014 Top 35%";
10740
+ return "\u{1F948} SYSTEM ADMINISTRATOR \u2014 Top 35%";
10741
10741
  if (score2 >= 200)
10742
- return "\u{1F949} ELITE TRAINER \u2014 Top 60%";
10743
- return "\u{1F331} BEGINNER TRAINER \u2014 everyone starts here";
10742
+ return "\u{1F949} SYSTEM OPERATOR \u2014 Top 60%";
10743
+ return "\u{1F331} SYSTEM INITIALIZED \u2014 everyone starts here";
10744
10744
  }
10745
10745
 
10746
10746
  // src/card.ts
10747
- function bar(pct, width = 20, filled = "\u2588", empty = "\u2591") {
10748
- const filledN = Math.floor(pct / 100 * width);
10749
- return filled.repeat(filledN) + empty.repeat(width - filledN);
10750
- }
10751
10747
  function fmtTokens(n) {
10752
10748
  if (n >= 1e6)
10753
10749
  return `${(n / 1e6).toFixed(1)}M`;
@@ -10755,500 +10751,540 @@ function fmtTokens(n) {
10755
10751
  return `${(n / 1e3).toFixed(1)}K`;
10756
10752
  return String(n);
10757
10753
  }
10758
- function renderTerminal(clis, mcp, models, burn, scoreResult) {
10759
- const running = clis.filter((c) => c.state === "RUNNING");
10760
- const idle = clis.filter((c) => c.state === "IDLE" || c.state === "DETECTED");
10761
- const agentLines = [];
10762
- for (const c of [...running, ...idle].slice(0, 6)) {
10763
- if (c.state === "RUNNING") {
10764
- agentLines.push(` ${c.icon} ${c.name.padEnd(18)} \u25CF ${c.cpuPct.toFixed(1).padStart(5)}% CPU`);
10765
- } else {
10766
- agentLines.push(` ${c.icon} ${c.name.padEnd(18)} \u25CB ${c.state.toLowerCase()}`);
10767
- }
10768
- }
10769
- const remaining = clis.length - agentLines.length;
10770
- if (remaining > 0)
10771
- agentLines.push(` \u2026 +${remaining} more`);
10772
- const modelLines = [];
10773
- for (const m of models.slice(0, 5)) {
10774
- const b = bar(m.percentage, 10);
10775
- modelLines.push(` ${m.name.padEnd(18)} ${b} ${m.percentage.toFixed(1).padStart(5)}%`);
10776
- }
10777
- const mcpLines = [];
10778
- const sortedMcp = [...mcp].sort((a, b) => b.toolCount - a.toolCount);
10779
- for (const t of sortedMcp.slice(0, 5)) {
10780
- const tc = t.toolCount ? `[${t.toolCount}]` : "";
10781
- mcpLines.push(` \u25C6 ${t.name.padEnd(16)} ${tc}`);
10782
- }
10783
- const mcpRemaining = mcp.length - 5;
10784
- if (mcpRemaining > 0)
10785
- mcpLines.push(` \u2026 +${mcpRemaining} more`);
10786
- const burnLines = [
10787
- ` PP Tokens ${fmtTokens(burn.totalTokens)}`,
10788
- ` Cost ($) $${burn.estimatedCostUsd.toFixed(2)}/mo`,
10789
- ` PP/min ${fmtTokens(burn.tokenVelocity)}/min`,
10790
- ` Battles ${burn.sessionCount}`,
10791
- ` HP (Intg) ${bar(burn.envIntegrity * 100, 10)} ${Math.round(burn.envIntegrity * 100)}%`
10792
- ];
10793
- const badgeLines = scoreResult.badges.length > 0 ? scoreResult.badges.map((b) => ` ${b}`) : [" (none yet)"];
10794
- const rarity = rarityLabel(scoreResult.total);
10795
- const w = 58;
10796
- const lines = [
10797
- `\u250C${"\u2500".repeat(w)}\u2510`,
10798
- `\u2502 \u25D3 Pok\xE9gent${" ".repeat(w - 20)}${String(scoreResult.total).padStart(4)} pts \u2502`,
10799
- `\u2502${"\u2501".repeat(w)}\u2502`,
10800
- `\u2502${" ".repeat(w)}\u2502`
10801
- ];
10802
- const leftHeader = `\u{1F392} POK\xC9MON TEAM (${running.length} run)`.padEnd(28);
10803
- const rightHeader = `\u{1F4CA} SPECIES MOVEPOOL`.padEnd(24);
10804
- lines.push(`\u2502 ${leftHeader} ${rightHeader}\u2502`);
10805
- const maxRows = Math.max(agentLines.length, modelLines.length, 1);
10806
- for (let i = 0; i < maxRows; i++) {
10807
- const left = (agentLines[i] ?? "").padEnd(28);
10808
- const right = modelLines[i] ?? "";
10809
- lines.push(`\u2502 ${left} ${right.padEnd(24)}\u2502`);
10810
- }
10811
- lines.push(`\u2502${" ".repeat(w)}\u2502`);
10812
- const totalTools = mcp.reduce((sum, t) => sum + t.toolCount, 0);
10813
- const leftHeader2 = `\u{1F392} TMs & HMs (${mcp.length})`.padEnd(26);
10814
- const rightHeader2 = `\u{1F50B} PP BURN (${totalTools} moves)`.padEnd(24);
10815
- lines.push(`\u2502 ${leftHeader2} ${rightHeader2}\u2502`);
10816
- const maxRows2 = Math.max(mcpLines.length, burnLines.length, 1);
10817
- for (let i = 0; i < maxRows2; i++) {
10818
- const left = (mcpLines[i] ?? "").padEnd(26);
10819
- const right = burnLines[i] ?? "";
10820
- lines.push(`\u2502 ${left} ${right.padEnd(24)}\u2502`);
10821
- }
10822
- lines.push(`\u2502${" ".repeat(w)}\u2502`);
10823
- const leftHeader3 = `\u{1F3C6} RARITY`.padEnd(26);
10824
- const rightHeader3 = `\u{1F3C5} BADGES`.padEnd(24);
10825
- lines.push(`\u2502 ${leftHeader3} ${rightHeader3}\u2502`);
10826
- lines.push(`\u2502 ${rarity.padEnd(26)} ${badgeLines[0].padEnd(24)}\u2502`);
10827
- for (const bl of badgeLines.slice(1)) {
10828
- lines.push(`\u2502 ${" ".repeat(26)} ${bl.padEnd(24)}\u2502`);
10829
- }
10830
- lines.push(`\u2502${" ".repeat(w)}\u2502`);
10831
- lines.push(`\u2502${"\u2501".repeat(w)}\u2502`);
10832
- lines.push(`\u2502 pokegent \xB7 npx \xB7 privacy-first (zero network)${" ".repeat(10)}\u2502`);
10833
- lines.push(`\u2514${"\u2500".repeat(w)}\u2518`);
10834
- return lines.join("\n");
10835
- }
10836
-
10837
- // src/markdown.ts
10838
- function renderMarkdown(clis, mcp, models, burn, scoreResult) {
10839
- const running = clis.filter((c) => c.state === "RUNNING");
10840
- const rarity = rarityLabel(scoreResult.total);
10841
- const lines = [
10842
- "```",
10843
- "\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
10844
- `\u2502 \u25D3 Pok\xE9gent ${String(scoreResult.total).padStart(4)} pts \u2502`,
10845
- "\u2502\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2502",
10846
- "\u2502 \u2502"
10847
- ];
10848
- const leftHeader = `\u{1F392} POK\xC9MON TEAM (${running.length} run)`.padEnd(26);
10849
- const rightHeader = `\u{1F4CA} SPECIES MOVEPOOL`.padEnd(23);
10850
- lines.push(`\u2502 ${leftHeader} \u2502 ${rightHeader} \u2502`);
10851
- const agentLines = [];
10852
- for (const c of clis.slice(0, 6)) {
10853
- if (c.state === "RUNNING") {
10854
- agentLines.push(`${c.icon} ${c.name.padEnd(12)} \u25CF run`);
10855
- } else if (c.state === "IDLE" || c.state === "DETECTED") {
10856
- agentLines.push(`${c.icon} ${c.name.padEnd(12)} \u25CB ${c.state.toLowerCase().slice(0, 4)}`);
10857
- } else {
10858
- agentLines.push(`${c.icon} ${c.name.padEnd(12)} \u25CB abs`);
10859
- }
10860
- }
10861
- const modelLines = [];
10862
- for (const m of models.slice(0, 5)) {
10863
- const b = bar(m.percentage, 5);
10864
- modelLines.push(`${m.name.slice(0, 11).padEnd(11)} ${b} ${m.percentage.toFixed(0).padStart(3)}%`);
10865
- }
10866
- const maxRows = Math.max(agentLines.length, modelLines.length);
10867
- for (let i = 0; i < maxRows; i++) {
10868
- const leftPart = (agentLines[i] ?? "").padEnd(26);
10869
- const rightPart = (modelLines[i] ?? "").padEnd(23);
10870
- lines.push(`\u2502 ${leftPart} \u2502 ${rightPart} \u2502`);
10871
- }
10872
- lines.push("\u2502 \u2502");
10873
- const totalTools = mcp.reduce((sum, t) => sum + t.toolCount, 0);
10874
- const leftHeader2 = `\u{1F392} TMs & HMs (${mcp.length})`.padEnd(26);
10875
- const rightHeader2 = `\u{1F50B} PP BURN (${totalTools} moves)`.padEnd(23);
10876
- lines.push(`\u2502 ${leftHeader2} \u2502 ${rightHeader2} \u2502`);
10877
- const mcpLines = [];
10878
- const sortedMcp = [...mcp].sort((a, b) => b.toolCount - a.toolCount);
10879
- for (const t of sortedMcp.slice(0, 5)) {
10880
- const tc = t.toolCount ? `[${t.toolCount}]` : "";
10881
- mcpLines.push(`\u25C6 ${t.name.slice(0, 15).padEnd(15)} ${tc}`);
10882
- }
10883
- const burnLines = [
10884
- `PP Tokens ${fmtTokens(burn.totalTokens)}`,
10885
- `Cost ($) $${burn.estimatedCostUsd.toFixed(2)}/mo`,
10886
- `PP/min ${fmtTokens(burn.tokenVelocity)}/min`,
10887
- `Battles ${burn.sessionCount}`
10888
- ];
10889
- const maxRows2 = Math.max(mcpLines.length, burnLines.length);
10890
- for (let i = 0; i < maxRows2; i++) {
10891
- const leftPart = (mcpLines[i] ?? "").padEnd(26);
10892
- const rightPart = (burnLines[i] ?? "").padEnd(23);
10893
- lines.push(`\u2502 ${leftPart} \u2502 ${rightPart} \u2502`);
10894
- }
10895
- lines.push("\u2502 \u2502");
10896
- if (scoreResult.badges.length > 0) {
10897
- lines.push(`\u2502 \u{1F3C6} ${scoreResult.badges.slice(0, 3).join(", ").padEnd(53)} \u2502`);
10898
- if (scoreResult.badges.length > 3) {
10899
- lines.push(`\u2502 ${scoreResult.badges.slice(3).join(", ").padEnd(53)} \u2502`);
10900
- }
10901
- } else {
10902
- lines.push(`\u2502 \u{1F3C6} (collect badges by training more Pok\xE9mon)${" ".repeat(13)} \u2502`);
10903
- }
10904
- lines.push("\u2502 \u2502");
10905
- lines.push(`\u2502 ${rarity.padEnd(55)} \u2502`);
10906
- lines.push("\u2502\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2502");
10907
- lines.push("\u2502 " + "pokegent \xB7 npx pokegent \xB7 github.com/shafiqimtiaz".padEnd(55) + " \u2502");
10908
- lines.push("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
10909
- lines.push("```");
10910
- return lines.join("\n");
10911
- }
10912
10754
 
10913
10755
  // src/html.ts
10914
10756
  function renderHtml(clis, mcp, models, burn, scoreResult) {
10915
- const running = clis.filter((c) => c.state === "RUNNING");
10916
- const idle = clis.filter((c) => c.state === "IDLE" || c.state === "DETECTED");
10757
+ const clisDetected = clis.filter((c) => c.state !== "ABSENT");
10758
+ const running = clisDetected.filter((c) => c.state === "RUNNING");
10759
+ const idle = clisDetected.filter((c) => c.state === "IDLE" || c.state === "DETECTED");
10917
10760
  const rarity = rarityLabel(scoreResult.total);
10918
- const totalTools = mcp.reduce((sum, t) => sum + t.toolCount, 0);
10919
10761
  const sortedMcp = [...mcp].sort((a, b) => b.toolCount - a.toolCount);
10920
10762
  return `<!DOCTYPE html>
10921
10763
  <html lang="en">
10922
10764
  <head>
10923
10765
  <meta charset="UTF-8">
10924
10766
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
10925
- <title>Pok\xE9gent \u2014 ${scoreResult.total} pts</title>
10926
- <meta property="og:title" content="Pok\xE9gent \u2014 ${scoreResult.total} pts">
10927
- <meta property="og:description" content="${running.length} active Pok\xE9mon, ${mcp.length} TMs/HMs loaded. ${rarity}">
10767
+ <title>Agentic \u2014 ${scoreResult.total} PTS</title>
10768
+ <meta property="og:title" content="Agentic \u2014 ${scoreResult.total} PTS">
10769
+ <meta property="og:description" content="${running.length} active agents, ${mcp.length} MCP servers loaded. ${rarity}">
10928
10770
  <meta property="og:type" content="website">
10929
10771
  <link rel="preconnect" href="https://fonts.googleapis.com">
10930
10772
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10931
- <link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">
10773
+ <link href="https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
10932
10774
  <style>
10775
+ :root {
10776
+ /* Retro \u2014 Color tokens */
10777
+ --black: #000000;
10778
+ --white: #ffffff;
10779
+ --gray-50: #f9fafb;
10780
+ --gray-200: #e2e8f0;
10781
+ --gray-400: #687282;
10782
+ --gray-500: #475565;
10783
+ --gray-900: #111827;
10784
+ --peach: #ffd1ba;
10785
+ --peach-300: #ffb38f;
10786
+ --peach-100: #fff0e8;
10787
+
10788
+ --color-text-primary: var(--gray-500);
10789
+ --color-text-tertiary: var(--gray-900);
10790
+ --color-text-inverse: var(--gray-400);
10791
+ --color-text-on-base: var(--white);
10792
+
10793
+ --color-surface-base: var(--black);
10794
+ --color-surface-muted: var(--white);
10795
+ --color-surface-raised: var(--gray-50);
10796
+ --color-surface-strong: var(--peach);
10797
+
10798
+ --color-border: var(--black);
10799
+ --color-border-subtle: rgba(0,0,0,0.12);
10800
+ --color-focus-ring: var(--gray-900);
10801
+
10802
+ /* Typography */
10803
+ --font-sans: 'Geist', system-ui, -apple-system, sans-serif;
10804
+ --font-mono: 'Geist Mono', ui-monospace, monospace;
10805
+
10806
+ --text-caption: 14px;
10807
+ --text-body-sm: 16px;
10808
+ --text-body-md: 18px;
10809
+ --text-subheading: 20px;
10810
+ --text-heading: 24px;
10811
+
10812
+ --lh-caption: 24px;
10813
+ --lh-body-sm: 24px;
10814
+ --lh-body-md: 24px;
10815
+ --lh-subheading: 24px;
10816
+ --lh-heading: 32px;
10817
+
10818
+ --weight-regular: 400;
10819
+ --weight-medium: 500;
10820
+ --weight-semibold: 600;
10821
+ --weight-bold: 700;
10822
+
10823
+ --tracking-tight: -0.02em;
10824
+ --tracking-normal: 0em;
10825
+ --tracking-wide: 0.04em;
10826
+
10827
+ /* Spacing */
10828
+ --space-1: 4px;
10829
+ --space-2: 8px;
10830
+ --space-3: 12px;
10831
+ --space-4: 16px;
10832
+ --space-5: 20px;
10833
+ --space-6: 24px;
10834
+ --space-7: 32px;
10835
+ --space-8: 40px;
10836
+
10837
+ /* Shape */
10838
+ --radius-xs: 4px;
10839
+ --radius-sm: 6px;
10840
+ --border-width: 2px;
10841
+
10842
+ /* Elevation */
10843
+ --shadow-1: -6px 6px 0 0 #000;
10844
+ }
10845
+
10933
10846
  * { margin: 0; padding: 0; box-sizing: border-box; }
10847
+
10934
10848
  body {
10935
- background-color: #F8F9FA;
10936
- color: #111111;
10937
- font-family: "Press Start 2P", "Courier New", monospace;
10849
+ margin: 0;
10850
+ font: var(--weight-regular) var(--text-body-sm)/var(--lh-body-sm) var(--font-sans);
10851
+ color: var(--color-text-primary);
10852
+ background: var(--color-surface-muted);
10853
+ -webkit-font-smoothing: antialiased;
10854
+ text-rendering: optimizeLegibility;
10938
10855
  min-height: 100vh;
10939
10856
  display: flex;
10940
10857
  align-items: center;
10941
10858
  justify-content: center;
10942
- padding: 2rem;
10943
- }
10944
- .gameboy-frame {
10945
- background: #FFFFFF;
10946
- border: 4px solid #0F1012;
10947
- box-shadow: 4px 4px 0px #0F1012;
10948
- border-radius: 0px;
10949
- padding: 2rem;
10950
- max-width: 800px;
10859
+ padding: var(--space-8) var(--space-4);
10860
+ }
10861
+
10862
+ .retro-card {
10863
+ max-width: 860px;
10951
10864
  width: 100%;
10952
- position: relative;
10865
+ background: var(--white);
10866
+ border: var(--border-width) solid var(--color-border);
10867
+ border-radius: var(--radius-sm);
10868
+ box-shadow: var(--shadow-1);
10869
+ padding: var(--space-6);
10870
+ display: flex;
10871
+ flex-direction: column;
10872
+ gap: var(--space-6);
10953
10873
  }
10954
- .header {
10874
+
10875
+ .card-header {
10955
10876
  display: flex;
10956
10877
  justify-content: space-between;
10957
10878
  align-items: center;
10958
- margin-bottom: 1.5rem;
10959
- padding-bottom: 1rem;
10960
- border-bottom: 4px dashed #0F1012;
10879
+ border-bottom: var(--border-width) solid var(--color-border);
10880
+ padding-bottom: var(--space-4);
10881
+ }
10882
+
10883
+ .brand {
10884
+ display: flex;
10885
+ align-items: center;
10886
+ gap: var(--space-3);
10887
+ }
10888
+
10889
+ .logo-glyph {
10890
+ width: 32px;
10891
+ height: 32px;
10892
+ display: grid;
10893
+ place-items: center;
10894
+ background: var(--color-surface-strong);
10895
+ border: var(--border-width) solid var(--color-border);
10896
+ border-radius: var(--radius-sm);
10897
+ font: var(--weight-bold) 18px/1 var(--font-mono);
10898
+ color: var(--color-text-tertiary);
10899
+ }
10900
+
10901
+ .logo-word {
10902
+ font: var(--weight-bold) var(--text-heading)/1 var(--font-sans);
10903
+ letter-spacing: var(--tracking-tight);
10904
+ color: var(--color-text-tertiary);
10905
+ }
10906
+
10907
+ .score-badge {
10908
+ display: flex;
10909
+ align-items: center;
10910
+ border: var(--border-width) solid var(--color-border);
10911
+ border-radius: var(--radius-xs);
10912
+ overflow: hidden;
10961
10913
  }
10962
- .header h1 {
10963
- font-size: 1.1rem;
10964
- color: #FF0000; /* Pokeball Red */
10914
+
10915
+ .score-label {
10916
+ font: var(--weight-bold) 11px/1 var(--font-mono);
10917
+ color: var(--color-text-on-base);
10918
+ background: var(--color-surface-base);
10919
+ padding: 6px var(--space-3);
10965
10920
  text-transform: uppercase;
10921
+ letter-spacing: var(--tracking-wide);
10922
+ }
10923
+
10924
+ .score-value {
10925
+ font: var(--weight-bold) var(--text-caption)/1 var(--font-mono);
10926
+ color: var(--color-text-tertiary);
10927
+ padding: 6px var(--space-3);
10928
+ background: var(--white);
10929
+ }
10930
+
10931
+ .rarity-banner {
10932
+ background: var(--color-surface-strong);
10933
+ border: var(--border-width) solid var(--color-border);
10934
+ border-radius: var(--radius-sm);
10935
+ padding: var(--space-3) var(--space-4);
10966
10936
  display: flex;
10967
10937
  align-items: center;
10968
- gap: 0.5rem;
10969
- }
10970
- .score {
10971
- font-size: 1.1rem;
10972
- color: #3B4CCA; /* GameFreak Blue */
10973
- font-weight: bold;
10974
- }
10975
- .rarity {
10976
- background: #FFDE00; /* Pikachu Yellow */
10977
- border: 4px solid #0F1012;
10978
- box-shadow: 4px 4px 0px #0F1012;
10979
- padding: 0.75rem;
10980
- text-align: center;
10981
- margin-bottom: 2rem;
10982
- font-size: 0.7rem;
10938
+ justify-content: center;
10939
+ gap: var(--space-2);
10940
+ font: var(--weight-bold) var(--text-body-sm)/1 var(--font-mono);
10941
+ color: var(--color-text-tertiary);
10983
10942
  text-transform: uppercase;
10984
- font-weight: bold;
10943
+ letter-spacing: var(--tracking-wide);
10985
10944
  }
10945
+
10946
+ .rarity-banner svg {
10947
+ width: 18px;
10948
+ height: 18px;
10949
+ }
10950
+
10986
10951
  .grid {
10987
10952
  display: grid;
10988
10953
  grid-template-columns: 1fr 1fr;
10989
- gap: 1.5rem;
10990
- margin-bottom: 1.5rem;
10954
+ gap: var(--space-6);
10991
10955
  }
10956
+
10992
10957
  @media (max-width: 768px) {
10993
10958
  .grid {
10994
10959
  grid-template-columns: 1fr;
10995
10960
  }
10996
10961
  }
10962
+
10997
10963
  .section {
10998
- background: #FFFFFF;
10999
- border: 4px solid #0F1012;
11000
- box-shadow: 4px 4px 0px #0F1012;
11001
- padding: 1.25rem;
10964
+ background: var(--color-surface-raised);
10965
+ border: var(--border-width) solid var(--color-border);
10966
+ border-radius: var(--radius-sm);
10967
+ padding: var(--space-5);
10968
+ display: flex;
10969
+ flex-direction: column;
10970
+ gap: var(--space-4);
11002
10971
  }
10972
+
11003
10973
  .section h2 {
11004
- font-size: 0.65rem;
11005
- color: #111111;
11006
- margin-bottom: 1.25rem;
10974
+ font: var(--weight-semibold) var(--text-caption)/1 var(--font-mono);
10975
+ color: var(--color-text-tertiary);
11007
10976
  text-transform: uppercase;
11008
- border-bottom: 4px solid #0F1012;
11009
- padding-bottom: 0.5rem;
11010
- line-height: 1.4;
10977
+ letter-spacing: var(--tracking-wide);
10978
+ border-bottom: var(--border-width) solid var(--color-border);
10979
+ padding-bottom: var(--space-3);
10980
+ display: flex;
10981
+ align-items: center;
10982
+ gap: var(--space-2);
11011
10983
  }
10984
+
10985
+ .section h2 svg {
10986
+ width: 16px;
10987
+ height: 16px;
10988
+ color: var(--color-text-tertiary);
10989
+ }
10990
+
11012
10991
  .item {
11013
10992
  display: flex;
11014
10993
  align-items: center;
11015
- gap: 0.75rem;
11016
- padding: 0.4rem 0;
11017
- font-family: "Courier New", monospace;
11018
- font-size: 0.95rem;
11019
- font-weight: bold;
11020
- text-transform: uppercase;
11021
- border-bottom: 2px dashed #EEEEEE;
10994
+ gap: var(--space-3);
10995
+ padding: var(--space-2) 0;
10996
+ border-bottom: 1.5px dashed var(--color-border-subtle);
11022
10997
  }
11023
- .sprite-container {
11024
- position: relative;
11025
- width: 40px;
11026
- height: 40px;
11027
- background: #F8F9FA;
11028
- border: 2px solid #0F1012;
10998
+
10999
+ .item:last-of-type {
11000
+ border-bottom: none;
11001
+ }
11002
+
11003
+ .icon-container {
11004
+ width: 44px;
11005
+ height: 44px;
11006
+ background: var(--white);
11007
+ border: var(--border-width) solid var(--color-border);
11008
+ border-radius: var(--radius-xs);
11029
11009
  display: flex;
11030
11010
  align-items: center;
11031
11011
  justify-content: center;
11032
11012
  flex-shrink: 0;
11013
+ font-size: 1.4rem;
11014
+ }
11015
+
11016
+ .item .name {
11017
+ flex: 1;
11018
+ font: var(--weight-semibold) var(--text-caption)/1.4 var(--font-mono);
11019
+ color: var(--color-text-tertiary);
11020
+ }
11021
+
11022
+ .item .state {
11023
+ font: var(--weight-bold) 11px/1 var(--font-mono);
11024
+ padding: 4px var(--space-2);
11025
+ border: var(--border-width) solid var(--color-border);
11026
+ border-radius: var(--radius-xs);
11027
+ text-transform: uppercase;
11028
+ background: var(--white);
11029
+ }
11030
+
11031
+ .item .state.running {
11032
+ background: var(--color-surface-strong);
11033
+ color: var(--color-text-tertiary);
11033
11034
  }
11034
- .pokemon-sprite {
11035
- position: absolute;
11036
- z-index: 2;
11037
- image-rendering: pixelated;
11035
+
11036
+ .item .state.idle {
11037
+ background: var(--peach-100);
11038
+ color: var(--color-text-tertiary);
11038
11039
  }
11039
- .pokemon-sprite.absent {
11040
- filter: grayscale(1) brightness(0.25) opacity(0.3);
11040
+
11041
+ .item .state.detected {
11042
+ background: var(--white);
11043
+ color: var(--color-text-primary);
11044
+ }
11045
+
11046
+ .item .state.absent {
11047
+ background: var(--white);
11048
+ color: var(--color-text-inverse);
11049
+ border-color: var(--color-border-subtle);
11041
11050
  }
11042
- .pokemon-sprite.detected, .pokemon-sprite.idle {
11043
- filter: grayscale(0.8) brightness(0.5) opacity(0.7);
11051
+
11052
+ .more-trigger {
11053
+ cursor: pointer;
11054
+ transition: background 100ms ease;
11044
11055
  }
11045
- .fallback-icon {
11046
- font-size: 1.2rem;
11047
- z-index: 1;
11056
+
11057
+ .more-trigger:hover {
11058
+ background: var(--peach-100);
11048
11059
  }
11049
- .item .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
11050
- .item .state { font-size: 0.7rem; padding: 2px 6px; border: 2px solid #0F1012; background: #E2E8F0; }
11051
- .item .state.running { background: #8B956D; color: #000000; } /* DMG Screen Green Style */
11052
- .item .state.idle { background: #FFDE00; color: #000000; }
11053
- .item .state.detected { background: #E2E8F0; color: #555555; }
11054
- .item .state.absent { background: #FFFFFF; color: #CCCCCC; border-color: #E2E8F0; }
11055
11060
 
11056
- /* HP Style Progress Bar */
11061
+ /* HP Progress Bar */
11057
11062
  .hp-container {
11058
11063
  display: flex;
11059
11064
  align-items: center;
11060
- gap: 0.5rem;
11065
+ gap: var(--space-2);
11061
11066
  width: 100%;
11062
11067
  }
11068
+
11063
11069
  .hp-label {
11064
- font-size: 0.65rem;
11065
- font-family: "Press Start 2P", monospace;
11066
- font-weight: bold;
11067
- flex-shrink: 0;
11070
+ font: var(--weight-bold) 11px/1 var(--font-sans);
11071
+ color: var(--color-text-tertiary);
11072
+ border: 1.5px solid var(--color-border);
11073
+ border-radius: var(--radius-xs);
11074
+ padding: 1px var(--space-1);
11075
+ background: var(--color-surface-strong);
11076
+ text-transform: uppercase;
11068
11077
  }
11078
+
11069
11079
  .bar-container {
11070
11080
  flex: 1;
11071
11081
  height: 12px;
11072
- background: #FFFFFF;
11073
- border: 2px solid #0F1012;
11074
- padding: 1px;
11082
+ background: var(--white);
11083
+ border: var(--border-width) solid var(--color-border);
11084
+ border-radius: var(--radius-xs);
11085
+ overflow: hidden;
11086
+ position: relative;
11075
11087
  }
11088
+
11076
11089
  .bar-fill {
11077
11090
  height: 100%;
11078
- background: #4CAF50;
11079
- transition: width 0.3s linear;
11091
+ background: #34d399;
11092
+ border-right: var(--border-width) solid var(--color-border);
11080
11093
  }
11094
+
11081
11095
  .bar-fill.warning {
11082
- background: #FFC107;
11096
+ background: #fbbf24;
11083
11097
  }
11098
+
11084
11099
  .bar-fill.critical {
11085
- background: #F44336;
11100
+ background: #f87171;
11101
+ }
11102
+
11103
+ .hp-percent {
11104
+ font: var(--weight-bold) 12px/1 var(--font-mono);
11105
+ color: var(--color-text-tertiary);
11106
+ min-width: 32px;
11107
+ text-align: right;
11086
11108
  }
11087
11109
 
11088
11110
  .metric {
11089
11111
  display: flex;
11090
11112
  justify-content: space-between;
11091
- padding: 0.4rem 0;
11092
- font-family: "Courier New", monospace;
11093
- font-size: 0.95rem;
11094
- font-weight: bold;
11113
+ align-items: center;
11114
+ padding: var(--space-2) 0;
11115
+ border-bottom: 1.5px dashed var(--color-border-subtle);
11116
+ font: var(--weight-semibold) var(--text-caption)/1.4 var(--font-mono);
11117
+ }
11118
+
11119
+ .metric .label {
11120
+ color: var(--color-text-primary);
11095
11121
  text-transform: uppercase;
11096
- border-bottom: 2px dashed #EEEEEE;
11097
11122
  }
11098
- .metric .label { color: #555555; }
11099
- .metric .value { color: #111111; }
11123
+
11124
+ .metric .value {
11125
+ color: var(--color-text-tertiary);
11126
+ }
11100
11127
 
11101
11128
  .badges {
11102
11129
  display: flex;
11103
11130
  flex-wrap: wrap;
11104
- gap: 0.75rem;
11105
- margin-top: 1.5rem;
11106
- margin-bottom: 1.5rem;
11131
+ gap: var(--space-2);
11107
11132
  }
11133
+
11108
11134
  .badge {
11109
- background: #FFFFFF;
11110
- border: 3px solid #0F1012;
11111
- padding: 0.5rem 0.75rem;
11112
- font-size: 0.55rem;
11113
- font-weight: bold;
11135
+ font: var(--weight-semibold) 11px/1 var(--font-mono);
11136
+ color: var(--color-text-tertiary);
11137
+ background: var(--color-surface-strong);
11138
+ border: var(--border-width) solid var(--color-border);
11139
+ border-radius: var(--radius-xs);
11140
+ padding: var(--space-2) var(--space-3);
11114
11141
  text-transform: uppercase;
11115
- box-shadow: 2px 2px 0px #0F1012;
11116
- font-family: "Press Start 2P", monospace;
11142
+ letter-spacing: var(--tracking-wide);
11117
11143
  }
11118
11144
 
11119
- /* Dialogue box */
11120
11145
  .dialogue-box {
11121
- background: #0F1012;
11122
- border: 4px solid #FFFFFF;
11123
- outline: 4px solid #0F1012;
11124
- padding: 1.25rem;
11125
- color: #F8F9FA;
11126
- font-family: "Press Start 2P", monospace;
11127
- font-size: 0.6rem;
11128
- line-height: 1.8;
11129
- margin-top: 1rem;
11130
- word-break: break-word;
11146
+ background: var(--color-surface-base);
11147
+ color: var(--color-text-on-base);
11148
+ border: var(--border-width) solid var(--color-border);
11149
+ border-radius: var(--radius-sm);
11150
+ padding: var(--space-4) var(--space-5);
11151
+ font: var(--weight-medium) var(--text-caption)/1.5 var(--font-mono);
11152
+ text-align: center;
11131
11153
  }
11154
+
11132
11155
  .dialogue-box a {
11133
- color: #FFDE00;
11134
- text-decoration: none;
11135
- }
11136
- .dialogue-box a:hover {
11156
+ color: var(--color-surface-strong);
11137
11157
  text-decoration: underline;
11158
+ font-weight: var(--weight-bold);
11138
11159
  }
11139
11160
  </style>
11140
11161
  </head>
11141
11162
  <body>
11142
- <div class="gameboy-frame">
11143
- <div class="header">
11144
- <h1>\u25D3 Pok\xE9gent</h1>
11145
- <div class="score">${scoreResult.total} PTS</div>
11163
+ <div class="retro-card">
11164
+ <div class="card-header">
11165
+ <div class="brand">
11166
+ <span class="logo-glyph">A</span>
11167
+ <span class="logo-word">Agentic</span>
11168
+ </div>
11169
+ <div class="score-badge">
11170
+ <span class="score-label">SCORE</span>
11171
+ <span class="score-value">${scoreResult.total} PTS</span>
11172
+ </div>
11173
+ </div>
11174
+
11175
+ <div class="rarity-banner">
11176
+ <i data-lucide="award"></i>
11177
+ <span>${rarity}</span>
11146
11178
  </div>
11147
- <div class="rarity">${rarity}</div>
11179
+
11148
11180
  <div class="grid">
11181
+ <!-- Section: Agents -->
11149
11182
  <div class="section">
11150
- <h2>\u{1F392} POK\xC9MON TEAM (${running.length} RUN)</h2>
11151
- ${[...running, ...idle].slice(0, 6).map((c) => {
11152
- const spriteUrl = c.pokemonId ? `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/showdown/${c.pokemonId}.gif` : "";
11153
- const imgHtml = spriteUrl ? `<img class="pokemon-sprite ${c.state.toLowerCase()}" src="${spriteUrl}" alt="${c.name}" width="36" height="36" onload="this.nextElementSibling.style.display='none'" onerror="this.style.display='none'" />` : "";
11183
+ <h2><i data-lucide="terminal"></i> AGENTS (${running.length} active)</h2>
11184
+ ${[...running, ...idle].map((c, idx) => {
11185
+ const isHidden = idx >= 6;
11154
11186
  return `
11155
- <div class="item">
11156
- <div class="sprite-container">
11157
- ${imgHtml}
11158
- <span class="icon fallback-icon">${c.icon}</span>
11187
+ <div class="item ${isHidden ? "hidden-agent" : ""}" ${isHidden ? 'style="display: none;"' : ""}>
11188
+ <div class="icon-container">
11189
+ <span class="icon">${c.icon}</span>
11159
11190
  </div>
11160
11191
  <span class="name">${c.name}</span>
11161
11192
  <span class="state ${c.state.toLowerCase()}">${c.state === "RUNNING" ? `${c.cpuPct.toFixed(1)}% CPU` : c.state.toLowerCase()}</span>
11162
11193
  </div>
11163
11194
  `;
11164
11195
  }).join("")}
11165
- ${clis.length > 6 ? `<div class="item" style="color:#555555; padding-left: 0.5rem; font-family:'Courier New', monospace;">\u2026 +${clis.length - 6} MORE</div>` : ""}
11196
+ ${clisDetected.length > 6 ? `
11197
+ <div class="item more-trigger" onclick="document.querySelectorAll('.hidden-agent').forEach(el => el.style.display = 'flex'); this.style.display = 'none';">
11198
+ <span class="name" style="color: var(--color-text-inverse)">\u2026 +${clisDetected.length - 6} MORE</span>
11199
+ <span class="state" style="border-color: var(--color-border-subtle); color: var(--color-text-inverse)">Expand</span>
11200
+ </div>
11201
+ ` : ""}
11166
11202
  </div>
11203
+
11204
+ <!-- Section: Models -->
11167
11205
  <div class="section">
11168
- <h2>\u{1F4CA} SPECIES MOVEPOOL</h2>
11206
+ <h2><i data-lucide="database"></i> AI MODELS</h2>
11169
11207
  ${models.slice(0, 5).map((m) => {
11170
11208
  const barClass = m.percentage > 50 ? "" : m.percentage > 20 ? "warning" : "critical";
11171
11209
  return `
11172
- <div class="item" style="flex-direction:column; align-items:flex-start; gap: 0.25rem;">
11173
- <span class="name" style="font-size:0.85rem">${m.name}</span>
11210
+ <div class="item" style="flex-direction:column; align-items:flex-start; gap: var(--space-2);">
11211
+ <span class="name" style="font-size: var(--text-caption);">${m.name}</span>
11174
11212
  <div class="hp-container">
11175
- <span class="hp-label">HP</span>
11213
+ <span class="hp-label" style="background: var(--color-surface-base); color: var(--white); border-color: var(--color-surface-base);">HP</span>
11176
11214
  <div class="bar-container">
11177
11215
  <div class="bar-fill ${barClass}" style="width:${m.percentage}%"></div>
11178
11216
  </div>
11179
- <span style="font-family:'Courier New', monospace; font-size:0.8rem; min-width:35px; text-align:right">${m.percentage.toFixed(0)}%</span>
11217
+ <span class="hp-percent">${m.percentage.toFixed(0)}%</span>
11180
11218
  </div>
11181
11219
  </div>
11182
11220
  `;
11183
11221
  }).join("")}
11184
11222
  </div>
11223
+
11224
+ <!-- Section: MCP Servers -->
11185
11225
  <div class="section">
11186
- <h2>\u{1F392} TMs & HMs (${mcp.length} ITEMS)</h2>
11187
- ${sortedMcp.slice(0, 5).map((t) => `
11188
- <div class="item">
11189
- <span class="name" style="color:#111111">\u25C6 ${t.name}</span>
11190
- <span style="color:#555555;font-size:0.8rem">[${t.toolCount} MOVES]</span>
11226
+ <h2><i data-lucide="cpu"></i> MCP SERVERS \xB7 Skills (${mcp.length})</h2>
11227
+ ${sortedMcp.map((t, idx) => {
11228
+ const isHidden = idx >= 5;
11229
+ return `
11230
+ <div class="item ${isHidden ? "hidden-mcp" : ""}" ${isHidden ? 'style="display: none;"' : ""}>
11231
+ <span class="name" style="color: var(--color-text-tertiary)">\u25C6 ${t.name}</span>
11232
+ <span class="state" style="border-color: var(--color-border-subtle); color: var(--color-text-primary); font-size: 10px;">[${t.toolCount} SKILLS]</span>
11233
+ </div>
11234
+ `;
11235
+ }).join("")}
11236
+ ${mcp.length > 5 ? `
11237
+ <div class="item more-trigger" onclick="document.querySelectorAll('.hidden-mcp').forEach(el => el.style.display = 'flex'); this.style.display = 'none';">
11238
+ <span class="name" style="color: var(--color-text-inverse)">\u2026 +${mcp.length - 5} MORE</span>
11239
+ <span class="state" style="border-color: var(--color-border-subtle); color: var(--color-text-inverse)">Expand</span>
11191
11240
  </div>
11192
- `).join("")}
11193
- ${mcp.length > 5 ? `<div class="item" style="color:#555555; padding-left: 0.5rem; font-family:'Courier New', monospace;">\u2026 +${mcp.length - 5} MORE</div>` : ""}
11241
+ ` : ""}
11194
11242
  </div>
11243
+
11244
+ <!-- Section: Token Burn -->
11195
11245
  <div class="section">
11196
- <h2>\u{1F50B} PP BURN</h2>
11197
- <div class="metric"><span class="label">PP Tokens</span><span class="value">${fmtTokens(burn.totalTokens)}</span></div>
11246
+ <h2><i data-lucide="zap"></i> SYSTEM METRICS</h2>
11247
+ <div class="metric"><span class="label">Tokens</span><span class="value">${fmtTokens(burn.totalTokens)}</span></div>
11198
11248
  <div class="metric"><span class="label">Cost ($)</span><span class="value">$${burn.estimatedCostUsd.toFixed(2)}/mo</span></div>
11199
- <div class="metric"><span class="label">PP Velocity</span><span class="value">${fmtTokens(burn.tokenVelocity)}/min</span></div>
11200
- <div class="metric"><span class="label">Battles</span><span class="value">${burn.sessionCount}</span></div>
11249
+ <div class="metric"><span class="label">Token Rate</span><span class="value">${fmtTokens(burn.tokenVelocity)}/min</span></div>
11250
+ <div class="metric"><span class="label">Sessions</span><span class="value">${burn.sessionCount}</span></div>
11201
11251
 
11202
- <div class="item" style="flex-direction:column; align-items:flex-start; gap: 0.25rem; border-bottom: none;">
11203
- <span class="label" style="font-size:0.8rem; color:#555555;">HP INTEGRITY</span>
11204
- <div class="hp-container">
11205
- <span class="hp-label">HP</span>
11252
+ <div class="item" style="flex-direction:column; align-items:flex-start; gap: var(--space-2); border-bottom: none; padding-bottom: 0;">
11253
+ <span class="label" style="font: var(--weight-bold) 11px/1 var(--font-mono); color: var(--color-text-inverse); text-transform: uppercase;">System Integrity</span>
11254
+ <div class="hp-container" style="margin-top: var(--space-1);">
11255
+ <span class="hp-label" style="background: var(--color-surface-base); color: var(--white); border-color: var(--color-surface-base);">HP</span>
11206
11256
  <div class="bar-container">
11207
11257
  <div class="bar-fill ${burn.envIntegrity >= 0.8 ? "" : burn.envIntegrity >= 0.5 ? "warning" : "critical"}" style="width:${burn.envIntegrity * 100}%"></div>
11208
11258
  </div>
11209
- <span style="font-family:'Courier New', monospace; font-size:0.8rem; min-width:35px; text-align:right">${Math.round(burn.envIntegrity * 100)}%</span>
11259
+ <span class="hp-percent">${Math.round(burn.envIntegrity * 100)}%</span>
11210
11260
  </div>
11211
11261
  </div>
11212
11262
  </div>
11213
11263
  </div>
11264
+
11265
+ <!-- Badges -->
11214
11266
  <div class="badges">
11215
11267
  ${scoreResult.badges.map((b) => `<span class="badge">${b}</span>`).join("")}
11216
11268
  </div>
11269
+
11270
+ <!-- Dialogue Box / Footer -->
11217
11271
  <div class="dialogue-box">
11218
- GENERATED BY <a href="https://github.com/shafiqimtiaz/pokegent">POK\xC9GENT</a>.<br>
11272
+ GENERATED BY <a href="https://github.com/shafiqimtiaz/pokegent" target="_blank" rel="noopener noreferrer">AGENTIC</a>.<br>
11219
11273
  NPX POKEGENT \xB7 PRIVACY-FIRST LOCAL SCAN.
11220
11274
  </div>
11221
11275
  </div>
11222
- </body>
11223
- </html>`;
11224
- }
11225
11276
 
11226
- // src/clipboard.ts
11227
- import { execSync } from "child_process";
11228
- import os2 from "os";
11229
- function copyToClipboard(text) {
11230
- const platform = os2.platform();
11231
- try {
11232
- if (platform === "darwin") {
11233
- execSync("pbcopy", { input: Buffer.from(text) });
11234
- return true;
11235
- } else if (platform === "linux") {
11236
- for (const cmd of ["xsel --clipboard --input", "xclip -selection clipboard", "wl-copy"]) {
11237
- try {
11238
- execSync(cmd, { input: Buffer.from(text) });
11239
- return true;
11240
- } catch {
11241
- }
11277
+ <!-- Lucide Icons CDN -->
11278
+ <script src="https://unpkg.com/lucide@0.460.0/dist/umd/lucide.min.js"></script>
11279
+ <script>
11280
+ document.addEventListener('DOMContentLoaded', () => {
11281
+ if (window.lucide) {
11282
+ lucide.createIcons({ attrs: { 'stroke-width': 2 } });
11242
11283
  }
11243
- return false;
11244
- } else if (platform === "win32") {
11245
- execSync("clip", { input: Buffer.from(text) });
11246
- return true;
11247
- }
11248
- return false;
11249
- } catch {
11250
- return false;
11251
- }
11284
+ });
11285
+ </script>
11286
+ </body>
11287
+ </html>`;
11252
11288
  }
11253
11289
 
11254
11290
  // src/demo.ts
@@ -11273,7 +11309,7 @@ function mockClis() {
11273
11309
  ];
11274
11310
  return Object.entries(CLI_SIGNATURES).map(([name, sig], i) => {
11275
11311
  const [state, pid, cpuPct, memMb, uptimeS] = states[i % states.length];
11276
- return { name, icon: sig.icon, state, pid, cpuPct, memMb, uptimeS, pokemonId: sig.pokemonId };
11312
+ return { name, icon: sig.icon, state, pid, cpuPct, memMb, uptimeS, pokemonId: sig.pokemonId, pokemonSlug: sig.pokemonSlug, pokemonName: sig.pokemonName };
11277
11313
  });
11278
11314
  }
11279
11315
  function mockMcp() {
@@ -11333,6 +11369,9 @@ function mockBurn2() {
11333
11369
  // src/cli.tsx
11334
11370
  import { useState, useEffect, useCallback, useRef } from "react";
11335
11371
  import { Box, Text, useApp, useInput } from "ink";
11372
+ import fs6 from "fs";
11373
+ import path5 from "path";
11374
+ import os2 from "os";
11336
11375
  import { jsx, jsxs } from "react/jsx-runtime";
11337
11376
  function Dashboard({ demo }) {
11338
11377
  const { exit } = useApp();
@@ -11392,16 +11431,18 @@ function Dashboard({ demo }) {
11392
11431
  if (input === "r")
11393
11432
  runScan();
11394
11433
  if (input === "s" && scoreResult && burn) {
11395
- const md = renderMarkdown(clis, mcp, models, burn, scoreResult);
11396
- const copied = copyToClipboard(md);
11397
- setLastMessage(copied ? "\u2713 Card copied to clipboard!" : "Clipboard unavailable");
11398
- setTimeout(() => setLastMessage(""), 3e3);
11399
- }
11400
- if (input === "h" && scoreResult && burn) {
11401
11434
  const html = renderHtml(clis, mcp, models, burn, scoreResult);
11402
- const copied = copyToClipboard(html);
11403
- setLastMessage(copied ? "\u2713 HTML card copied to clipboard!" : "Clipboard unavailable");
11404
- setTimeout(() => setLastMessage(""), 3e3);
11435
+ const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
11436
+ const baseName = `pokegent-${ts}`;
11437
+ const desktopDir = path5.join(os2.homedir(), "Desktop");
11438
+ const htmlPath = path5.join(desktopDir, `${baseName}.html`);
11439
+ try {
11440
+ fs6.writeFileSync(htmlPath, html);
11441
+ setLastMessage(`\u2713 HTML saved \u2192 ~/Desktop/${baseName}.html`);
11442
+ } catch {
11443
+ setLastMessage("\u2717 Failed to write HTML to Desktop");
11444
+ }
11445
+ setTimeout(() => setLastMessage(""), 4e3);
11405
11446
  }
11406
11447
  });
11407
11448
  if (clis.length === 0) {
@@ -11430,7 +11471,8 @@ function Dashboard({ demo }) {
11430
11471
  ] })
11431
11472
  ] });
11432
11473
  }
11433
- const running = clis.filter((c) => c.state === "RUNNING");
11474
+ const clisDetected = clis.filter((c) => c.state !== "ABSENT");
11475
+ const running = clisDetected.filter((c) => c.state === "RUNNING");
11434
11476
  const totalTools = mcp.reduce((sum, t) => sum + t.toolCount, 0);
11435
11477
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
11436
11478
  /* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", marginBottom: 1, children: [
@@ -11451,11 +11493,11 @@ function Dashboard({ demo }) {
11451
11493
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: "50%", children: [
11452
11494
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
11453
11495
  /* @__PURE__ */ jsxs(Text, { bold: true, color: "blue", children: [
11454
- "\u{1F392} POK\xC9MON TEAM (",
11496
+ "\u{1F392} AGENTS (",
11455
11497
  running.length,
11456
- " running)"
11498
+ " active)"
11457
11499
  ] }),
11458
- clis.slice(0, 8).map((c, i) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { children: [
11500
+ clisDetected.slice(0, 8).map((c, i) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { children: [
11459
11501
  c.icon,
11460
11502
  " ",
11461
11503
  c.name.padEnd(20),
@@ -11466,19 +11508,19 @@ function Dashboard({ demo }) {
11466
11508
  "% CPU"
11467
11509
  ] }) : c.state === "IDLE" ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u25CB idle" }) : c.state === "DETECTED" ? /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u25CB detected" }) : /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u25CB absent" })
11468
11510
  ] }) }, i)),
11469
- clis.length > 8 && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
11511
+ clisDetected.length > 8 && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
11470
11512
  " \u2026 +",
11471
- clis.length - 8,
11513
+ clisDetected.length - 8,
11472
11514
  " more"
11473
11515
  ] })
11474
11516
  ] }),
11475
11517
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
11476
11518
  /* @__PURE__ */ jsxs(Text, { bold: true, color: "yellow", children: [
11477
- "\u{1F392} TMs & HMs (MCP) (",
11519
+ "\u{1F392} MCP SERVERS \xB7 Skills (",
11478
11520
  mcp.length,
11479
- " items, ",
11521
+ " servers, ",
11480
11522
  totalTools,
11481
- " moves)"
11523
+ " skills)"
11482
11524
  ] }),
11483
11525
  [...mcp].sort((a, b) => b.toolCount - a.toolCount).slice(0, 6).map((t, i) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { children: [
11484
11526
  "\u25C6 ",
@@ -11490,14 +11532,14 @@ function Dashboard({ demo }) {
11490
11532
  ] }),
11491
11533
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: "50%", children: [
11492
11534
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
11493
- /* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "\u{1F4CA} SPECIES MOVEPOOL" }),
11535
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "\u{1F4CA} MODELS \xB7 Active List" }),
11494
11536
  models.slice(0, 6).map((m, i) => {
11495
11537
  const filled = Math.floor(m.percentage / 100 * 10);
11496
- const bar2 = "\u2588".repeat(filled) + "\u2591".repeat(10 - filled);
11538
+ const bar = "\u2588".repeat(filled) + "\u2591".repeat(10 - filled);
11497
11539
  return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { children: [
11498
11540
  m.name.padEnd(18),
11499
11541
  " ",
11500
- bar2,
11542
+ bar,
11501
11543
  " ",
11502
11544
  m.percentage.toFixed(1).padStart(5),
11503
11545
  "%"
@@ -11505,9 +11547,9 @@ function Dashboard({ demo }) {
11505
11547
  })
11506
11548
  ] }),
11507
11549
  burn && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
11508
- /* @__PURE__ */ jsx(Text, { bold: true, color: "red", children: "\u{1F50B} PP BURN" }),
11550
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "red", children: "\u{1F50B} SYSTEM METRICS" }),
11509
11551
  /* @__PURE__ */ jsxs(Text, { children: [
11510
- " PP (Tokens) ",
11552
+ " Tokens ",
11511
11553
  burn.totalTokens >= 1e6 ? `${(burn.totalTokens / 1e6).toFixed(1)}M` : `${(burn.totalTokens / 1e3).toFixed(1)}K`
11512
11554
  ] }),
11513
11555
  /* @__PURE__ */ jsxs(Text, { children: [
@@ -11516,16 +11558,16 @@ function Dashboard({ demo }) {
11516
11558
  "/mo"
11517
11559
  ] }),
11518
11560
  /* @__PURE__ */ jsxs(Text, { children: [
11519
- " PP Velocity ",
11561
+ " Token Rate ",
11520
11562
  burn.tokenVelocity >= 1e3 ? `${(burn.tokenVelocity / 1e3).toFixed(1)}K` : burn.tokenVelocity,
11521
11563
  "/min"
11522
11564
  ] }),
11523
11565
  /* @__PURE__ */ jsxs(Text, { children: [
11524
- " Battles ",
11566
+ " Sessions ",
11525
11567
  burn.sessionCount
11526
11568
  ] }),
11527
11569
  /* @__PURE__ */ jsxs(Text, { children: [
11528
- " HP Integrity ",
11570
+ " Integrity ",
11529
11571
  burn.envIntegrity >= 0.8 ? "\u{1F7E2}" : burn.envIntegrity >= 0.5 ? "\u{1F7E1}" : "\u{1F534}",
11530
11572
  " ",
11531
11573
  Math.round(burn.envIntegrity * 100),
@@ -11549,18 +11591,20 @@ function Dashboard({ demo }) {
11549
11591
  "s \u2502 ",
11550
11592
  (/* @__PURE__ */ new Date()).toLocaleTimeString()
11551
11593
  ] }),
11552
- /* @__PURE__ */ jsx(Text, { color: "gray", children: "q quit \u2502 r refresh \u2502 s share \u2502 h html" })
11594
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "q quit \u2502 r refresh \u2502 s share" })
11553
11595
  ] }),
11554
11596
  lastMessage && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: lastMessage }) })
11555
11597
  ] });
11556
11598
  }
11557
11599
 
11558
11600
  // src/index.ts
11559
- import fs6 from "fs/promises";
11601
+ import fs7 from "fs/promises";
11602
+ import path6 from "path";
11603
+ import os3 from "os";
11560
11604
  var program2 = new Command();
11561
11605
  program2.name("pokegent").description("Terminal dashboard that shows your Pok\xE9mon AI coding ecosystem").version(VERSION);
11562
- program2.option("--demo", "Run with mock data").option("--share", "Generate shareable card and copy to clipboard").option("--html", "Generate HTML card file").option("--json", "Export raw data as JSON").action(async (opts) => {
11563
- if (opts.share || opts.html || opts.json) {
11606
+ program2.option("--demo", "Run with mock data").option("--share", "Generate HTML card on ~/Desktop").option("--json", "Export raw data as JSON").action(async (opts) => {
11607
+ if (opts.share || opts.json) {
11564
11608
  await runOneShot(opts);
11565
11609
  } else {
11566
11610
  const { waitUntilExit } = render(React2.createElement(Dashboard, { demo: opts.demo ?? false }));
@@ -11587,17 +11631,12 @@ async function runOneShot(opts) {
11587
11631
  console.log(JSON.stringify({ clis, mcp, models, burn, score: scoreResult }, null, 2));
11588
11632
  return;
11589
11633
  }
11590
- if (opts.html) {
11591
- const html = renderHtml(clis, mcp, models, burn, scoreResult);
11592
- const outPath = "pokegent.html";
11593
- await fs6.writeFile(outPath, html);
11594
- console.log(`\u2713 HTML card written to ${outPath}`);
11595
- return;
11596
- }
11597
- const terminalCard = renderTerminal(clis, mcp, models, burn, scoreResult);
11598
- console.log(terminalCard);
11599
- const mdCard = renderMarkdown(clis, mcp, models, burn, scoreResult);
11600
- const copied = copyToClipboard(mdCard);
11601
- console.log(copied ? "\n\u2713 Markdown card copied to clipboard!" : "\n(clipboard unavailable \u2014 card printed above)");
11634
+ const html = renderHtml(clis, mcp, models, burn, scoreResult);
11635
+ const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
11636
+ const baseName = `pokegent-${ts}`;
11637
+ const desktopDir = path6.join(os3.homedir(), "Desktop");
11638
+ const htmlPath = path6.join(desktopDir, `${baseName}.html`);
11639
+ await fs7.writeFile(htmlPath, html);
11640
+ console.log(`\u2713 HTML saved \u2192 ${htmlPath}`);
11602
11641
  }
11603
11642
  program2.parse();