paean 0.10.18 → 0.10.19

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.10.19] - /usage command (2026-04-15)
4
+
5
+ ### Features
6
+ - Added `paean usage` CLI command and `/usage` TUI slash command: shows subscription tier, total credits, and 5h/7d rolling-window usage with color-coded progress bars.
7
+ - Added `getUsageLimits()` wrapper for zero-api `GET /credits/usage-limits`.
8
+
3
9
  ## [0.8.12] - Deep UX & Stability Optimization (2026-02-11)
4
10
 
5
11
  ### 🛡️ Critical Fixes
@@ -17,6 +17,21 @@ export declare function getCreditsStatus(): Promise<{
17
17
  success: boolean;
18
18
  data: CreditsStatus;
19
19
  }>;
20
+ export interface UsageLimits {
21
+ usage5h: number;
22
+ usage7d: number;
23
+ limits: {
24
+ credits5h: number;
25
+ credits7d: number;
26
+ };
27
+ percentUsed5h: number;
28
+ percentUsed7d: number;
29
+ subscriptionTier: string;
30
+ }
31
+ export declare function getUsageLimits(): Promise<{
32
+ success: boolean;
33
+ data: UsageLimits;
34
+ }>;
20
35
  export interface NetworkDepositInfo {
21
36
  name: string;
22
37
  depositAddress: string;
@@ -1 +1 @@
1
- {"version":3,"file":"credits.d.ts","sourceRoot":"","sources":["../../src/api/credits.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,CAI3F;AAID,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAI3D;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,CAIxD;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IAAE,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,CAAC,CAIhF;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAInF"}
1
+ {"version":3,"file":"credits.d.ts","sourceRoot":"","sources":["../../src/api/credits.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,11 @@ export async function getCreditsStatus() {
8
8
  const { data } = await client.get('/credits/status');
9
9
  return data;
10
10
  }
11
+ export async function getUsageLimits() {
12
+ const client = getApiClient();
13
+ const { data } = await client.get('/credits/usage-limits');
14
+ return data;
15
+ }
11
16
  export async function getDepositInfo() {
12
17
  const client = getApiClient();
13
18
  const { data } = await client.get('/crypto-deposit/info');
@@ -1 +1 @@
1
- {"version":3,"file":"credits.js","sourceRoot":"","sources":["../../src/api/credits.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgB3C,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC;AACd,CAAC;AAuBD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAuBD,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAC7D,OAAO,IAAI,CAAC;AACd,CAAC;AAiBD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACnD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,0BAA0B,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1F,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"credits.js","sourceRoot":"","sources":["../../src/api/credits.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgB3C,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC;AACd,CAAC;AAgBD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC;AAuBD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAuBD,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAC7D,OAAO,IAAI,CAAC;AACd,CAAC;AAiBD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACnD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,0BAA0B,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1F,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/cli.js CHANGED
@@ -33454,10 +33454,23 @@ var contextEmitter, pendingCompactSummary, CONTEXT_TOOL_NAMES, init_context_tool
33454
33454
  });
33455
33455
 
33456
33456
  // src/api/credits.ts
33457
+ var credits_exports = {};
33458
+ __export(credits_exports, {
33459
+ getCreditsStatus: () => getCreditsStatus,
33460
+ getDepositHistory: () => getDepositHistory,
33461
+ getDepositInfo: () => getDepositInfo,
33462
+ getDepositStatus: () => getDepositStatus,
33463
+ getUsageLimits: () => getUsageLimits,
33464
+ pollDeposits: () => pollDeposits
33465
+ });
33457
33466
  async function getCreditsStatus() {
33458
33467
  let client = getApiClient(), { data } = await client.get("/credits/status");
33459
33468
  return data;
33460
33469
  }
33470
+ async function getUsageLimits() {
33471
+ let client = getApiClient(), { data } = await client.get("/credits/usage-limits");
33472
+ return data;
33473
+ }
33461
33474
  async function getDepositInfo() {
33462
33475
  let client = getApiClient(), { data } = await client.get("/crypto-deposit/info");
33463
33476
  return data;
@@ -33479,6 +33492,7 @@ var init_credits = __esm({
33479
33492
  "use strict";
33480
33493
  init_client();
33481
33494
  __name(getCreditsStatus, "getCreditsStatus");
33495
+ __name(getUsageLimits, "getUsageLimits");
33482
33496
  __name(getDepositInfo, "getDepositInfo");
33483
33497
  __name(pollDeposits, "pollDeposits");
33484
33498
  __name(getDepositHistory, "getDepositHistory");
@@ -65873,7 +65887,8 @@ function useCommands(options = {}) {
65873
65887
  "/memory",
65874
65888
  "/shortcuts",
65875
65889
  "/tools",
65876
- "/loop"
65890
+ "/loop",
65891
+ "/usage"
65877
65892
  ], getHelp = (0, import_react30.useCallback)(() => `
65878
65893
  \u2500\u2500\u2500 Commands \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
65879
65894
 
@@ -65888,6 +65903,7 @@ function useCommands(options = {}) {
65888
65903
 
65889
65904
  /status Show session status & config
65890
65905
  /stats Show detailed session statistics
65906
+ /usage Show subscription, credits, and 5h/7d usage
65891
65907
  /mcp Show MCP connection status
65892
65908
  /tools List all available local tools
65893
65909
  /model Show current model info
@@ -67991,6 +68007,34 @@ var init_components = __esm({
67991
68007
  });
67992
68008
 
67993
68009
  // src/ui/App.tsx
68010
+ function renderUsageBar(percent, width = 20) {
68011
+ let p = Math.max(0, Math.min(100, percent)), filled = Math.round(p / 100 * width);
68012
+ return "\u2588".repeat(filled) + "\u2591".repeat(width - filled);
68013
+ }
68014
+ function formatUsageOutput(status, limits) {
68015
+ let bar5h = renderUsageBar(limits.percentUsed5h), bar7d = renderUsageBar(limits.percentUsed7d), out = `
68016
+ \u2500\u2500\u2500 Usage \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
68017
+
68018
+ `;
68019
+ if (out += ` Subscription: ${status.subscriptionTier}
68020
+ `, out += ` Credits: ${status.credits} / ${status.totalCredits}
68021
+ `, status.canRecover)
68022
+ out += ` Recovery: available now
68023
+ `;
68024
+ else if (status.nextRecoveryAt) {
68025
+ let d = new Date(status.nextRecoveryAt);
68026
+ out += ` Next recovery: ${d.toLocaleString()}
68027
+ `;
68028
+ }
68029
+ return out += `
68030
+ \u2500\u2500\u2500 Rolling Windows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
68031
+
68032
+ `, out += ` 5h ${bar5h} ${limits.percentUsed5h}% (${limits.usage5h} / ${limits.limits.credits5h})
68033
+ `, out += ` 7d ${bar7d} ${limits.percentUsed7d}% (${limits.usage7d} / ${limits.limits.credits7d})
68034
+ `, (limits.percentUsed5h >= 90 || limits.percentUsed7d >= 90) && (out += `
68035
+ \u26A0 Approaching usage limits \u2014 requests may be throttled.
68036
+ `), out;
68037
+ }
67994
68038
  var import_react41, import_jsx_runtime8, DOUBLE_CTRL_C_WINDOW, App2, init_App2 = __esm({
67995
68039
  async "src/ui/App.tsx"() {
67996
68040
  "use strict";
@@ -67999,7 +68043,10 @@ var import_react41, import_jsx_runtime8, DOUBLE_CTRL_C_WINDOW, App2, init_App2 =
67999
68043
  await init_components();
68000
68044
  await init_hooks();
68001
68045
  init_ink_theme();
68002
- import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1), DOUBLE_CTRL_C_WINDOW = 1500, App2 = /* @__PURE__ */ __name(({
68046
+ import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1), DOUBLE_CTRL_C_WINDOW = 1500;
68047
+ __name(renderUsageBar, "renderUsageBar");
68048
+ __name(formatUsageOutput, "formatUsageOutput");
68049
+ App2 = /* @__PURE__ */ __name(({
68003
68050
  mcpState,
68004
68051
  onMcpToolCall,
68005
68052
  mcpClient: mcpClient2,
@@ -68149,6 +68196,22 @@ To resume this session: paean --resume=${conversationId}
68149
68196
  return completions.length === 1 ? (setCommandSuggestions([]), completions[0]) : null;
68150
68197
  }, [getCompletions]), handleSubmit = (0, import_react41.useCallback)((input) => {
68151
68198
  if (setCommandOutput(null), setCommandSuggestions([]), input.startsWith("/")) {
68199
+ if (input.trim().toLowerCase() === "/usage") {
68200
+ setCommandOutput(" Fetching usage\u2026"), (async () => {
68201
+ try {
68202
+ let { getCreditsStatus: getCreditsStatus2, getUsageLimits: getUsageLimits2 } = await Promise.resolve().then(() => (init_credits(), credits_exports)), [statusRes, limitsRes] = await Promise.all([
68203
+ getCreditsStatus2(),
68204
+ getUsageLimits2()
68205
+ ]);
68206
+ setCommandOutput(formatUsageOutput(statusRes.data, limitsRes.data));
68207
+ } catch (err) {
68208
+ setCommandOutput(`
68209
+ Failed to fetch usage: ${err?.message || err}
68210
+ `);
68211
+ }
68212
+ })();
68213
+ return;
68214
+ }
68152
68215
  let result = handleCommand(input);
68153
68216
  if (result.handled) {
68154
68217
  if (result.action === "exit") {
@@ -134853,24 +134916,68 @@ function printDeposit(dep) {
134853
134916
  }
134854
134917
  __name(printDeposit, "printDeposit");
134855
134918
 
134919
+ // src/commands/usage.ts
134920
+ init_esm();
134921
+ init_config();
134922
+ init_credits();
134923
+ init_output();
134924
+ function requireAuth6() {
134925
+ isAuthenticated() || (error2("Not logged in. Run `paean login` first."), process.exit(1));
134926
+ }
134927
+ __name(requireAuth6, "requireAuth");
134928
+ function renderBar(percent, width = 24) {
134929
+ let p = Math.max(0, Math.min(100, percent)), filled = Math.round(p / 100 * width), empty = width - filled, bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
134930
+ return p >= 90 ? colors.error(bar) : p >= 70 ? colors.warning(bar) : colors.success(bar);
134931
+ }
134932
+ __name(renderBar, "renderBar");
134933
+ var usageCommand = new Command("usage").description("Show subscription tier, credits, and rolling-window usage (5h / 7d)").option("--json", "Output in JSON format").action(async (options) => {
134934
+ requireAuth6();
134935
+ let spin = spinner("Fetching usage\u2026").start();
134936
+ try {
134937
+ let [statusRes, limitsRes] = await Promise.all([
134938
+ getCreditsStatus(),
134939
+ getUsageLimits()
134940
+ ]);
134941
+ spin.stop();
134942
+ let status = statusRes.data, limits = limitsRes.data;
134943
+ if (options.json) {
134944
+ json({ status, limits });
134945
+ return;
134946
+ }
134947
+ header("Usage"), tableRow("Subscription", colors.bold(status.subscriptionTier)), tableRow("Credits", `${status.credits} / ${status.totalCredits}`), status.canRecover ? tableRow("Recovery", colors.success("available now")) : status.nextRecoveryAt && tableRow("Next recovery", formatDate(status.nextRecoveryAt)), newline(), header("Rolling Window Usage");
134948
+ let bar5h = renderBar(limits.percentUsed5h), bar7d = renderBar(limits.percentUsed7d);
134949
+ tableRow(
134950
+ "5h",
134951
+ `${bar5h} ${limits.percentUsed5h}% (${limits.usage5h} / ${limits.limits.credits5h})`
134952
+ ), tableRow(
134953
+ "7d",
134954
+ `${bar7d} ${limits.percentUsed7d}% (${limits.usage7d} / ${limits.limits.credits7d})`
134955
+ ), newline(), limits.percentUsed5h >= 90 || limits.percentUsed7d >= 90 ? warning2("Approaching usage limits \u2014 requests may be throttled.") : status.credits < 20 && warning2(
134956
+ `Credits are low (${status.credits}). Use \`paean credits deposit-info\` to top up.`
134957
+ );
134958
+ } catch (err) {
134959
+ spin.stop(), errorWithHint(err.message || "Failed to fetch usage");
134960
+ }
134961
+ });
134962
+
134856
134963
  // src/commands/sparklet.ts
134857
134964
  init_esm();
134858
134965
  init_open();
134859
134966
  init_client();
134860
134967
  init_config();
134861
134968
  init_output();
134862
- function requireAuth6() {
134969
+ function requireAuth7() {
134863
134970
  isAuthenticated() || (error2("Not logged in. Run `paean login` first."), process.exit(1));
134864
134971
  }
134865
- __name(requireAuth6, "requireAuth");
134972
+ __name(requireAuth7, "requireAuth");
134866
134973
  var sparkletCommand = new Command("sparklet").description("View and manage sparklets (AI-generated micro-apps)").action(async () => {
134867
- requireAuth6(), await listSparklets();
134974
+ requireAuth7(), await listSparklets();
134868
134975
  });
134869
134976
  sparkletCommand.command("list").description("List your sparklets").option("--json", "Output as JSON").action(async (options) => {
134870
- requireAuth6(), await listSparklets(options.json);
134977
+ requireAuth7(), await listSparklets(options.json);
134871
134978
  });
134872
134979
  sparkletCommand.command("show <id>").description("Show sparklet details").option("--json", "Output as JSON").action(async (id, options) => {
134873
- requireAuth6();
134980
+ requireAuth7();
134874
134981
  try {
134875
134982
  let response = await getApiClient().get(`/sparklet/${id}`), sparklet = response.data.data || response.data;
134876
134983
  if (options.json) {
@@ -134887,7 +134994,7 @@ sparkletCommand.command("show <id>").description("Show sparklet details").option
134887
134994
  }
134888
134995
  });
134889
134996
  sparkletCommand.command("open <id>").description("Open sparklet in browser").action(async (id) => {
134890
- requireAuth6();
134997
+ requireAuth7();
134891
134998
  let url3 = `${getWebUrl()}/sparklet/${id}`;
134892
134999
  dim2(`Opening ${url3}...`);
134893
135000
  try {
@@ -134897,7 +135004,7 @@ sparkletCommand.command("open <id>").description("Open sparklet in browser").act
134897
135004
  }
134898
135005
  });
134899
135006
  sparkletCommand.command("delete <id>").description("Delete a sparklet").action(async (id) => {
134900
- requireAuth6();
135007
+ requireAuth7();
134901
135008
  try {
134902
135009
  await getApiClient().delete(`/sparklet/${id}`), success2("Sparklet deleted.");
134903
135010
  } catch (error4) {
@@ -134906,7 +135013,7 @@ sparkletCommand.command("delete <id>").description("Delete a sparklet").action(a
134906
135013
  }
134907
135014
  });
134908
135015
  sparkletCommand.command("publish <id>").description("Publish or unpublish a sparklet").option("--unpublish", "Unpublish instead of publish").action(async (id, options) => {
134909
- requireAuth6();
135016
+ requireAuth7();
134910
135017
  try {
134911
135018
  await getApiClient().put(`/sparklet/${id}/publish`, {
134912
135019
  isPublished: !options.unpublish
@@ -135596,10 +135703,10 @@ __name(getUserProfile, "getUserProfile");
135596
135703
  // src/commands/workers.ts
135597
135704
  init_config();
135598
135705
  init_output();
135599
- function requireAuth7() {
135706
+ function requireAuth8() {
135600
135707
  isAuthenticated() || (error2("Not logged in. Run `paean login` first."), process.exit(1));
135601
135708
  }
135602
- __name(requireAuth7, "requireAuth");
135709
+ __name(requireAuth8, "requireAuth");
135603
135710
  var DEFAULT_IGNORE_PATTERNS = [
135604
135711
  "node_modules",
135605
135712
  ".git",
@@ -135690,10 +135797,10 @@ function saveManifest(dir, manifest) {
135690
135797
  }
135691
135798
  __name(saveManifest, "saveManifest");
135692
135799
  var workersCommand = new Command("workers").description("Publish and manage Worker packages on 0.works marketplace").action(async () => {
135693
- requireAuth7(), await listMy();
135800
+ requireAuth8(), await listMy();
135694
135801
  });
135695
135802
  workersCommand.command("whoami").description("Show current authenticated user").option("--json", "Output as JSON").action(async (options) => {
135696
- requireAuth7();
135803
+ requireAuth8();
135697
135804
  try {
135698
135805
  let u3 = (await getUserProfile()).user;
135699
135806
  if (options.json) {
@@ -135753,7 +135860,7 @@ workersCommand.command("pack").description("Create a .zip package from the curre
135753
135860
  success2(`Package created: ${outputPath}`), dim2(`Size: ${formatSize(stat4.size)}`), stat4.size > MAX_PACKAGE_SIZE && warning2(`Package exceeds ${formatSize(MAX_PACKAGE_SIZE)} limit`);
135754
135861
  });
135755
135862
  workersCommand.command("publish").description("Package and publish the current directory to 0.works marketplace").option("--draft", "Upload as draft without publishing").option("--zip <path>", "Upload an existing zip file instead of packing").option("--changelog <text>", "Changelog / release notes for this version").action(async (options) => {
135756
- requireAuth7();
135863
+ requireAuth8();
135757
135864
  let dir = process.cwd(), manifest = loadManifest(dir);
135758
135865
  manifest || (error2(`No ${MANIFEST_FILE} found. Run: paean workers init`), process.exit(1)), manifest.name || (error2("name is required in workers.json"), process.exit(1));
135759
135866
  let zipPath = options.zip, tempZip = !1;
@@ -135800,7 +135907,7 @@ View: https://0.works/workers/${worker.slug}`), newline();
135800
135907
  }
135801
135908
  });
135802
135909
  workersCommand.command("publish-id <id>").description("Publish a previously uploaded draft worker by ID").action(async (id) => {
135803
- requireAuth7();
135910
+ requireAuth8();
135804
135911
  try {
135805
135912
  let result = await publishWorkerPackage(id);
135806
135913
  success2(`Published: ${result.worker.displayName}`), dim2("Status: published (pending review)");
@@ -135810,7 +135917,7 @@ workersCommand.command("publish-id <id>").description("Publish a previously uplo
135810
135917
  }
135811
135918
  });
135812
135919
  workersCommand.command("update [bump]").description("Bump version and publish in one step (default: patch)").option("--changelog <text>", "Changelog / release notes").option("--draft", "Upload as draft without publishing").action(async (bump, options) => {
135813
- requireAuth7();
135920
+ requireAuth8();
135814
135921
  let dir = process.cwd(), manifest = loadManifest(dir);
135815
135922
  manifest || (error2(`No ${MANIFEST_FILE} found. Run: paean workers init`), process.exit(1));
135816
135923
  let bumpType = bump || "patch", parts = (manifest.version || "1.0.0").split(".").map(Number);
@@ -135888,7 +135995,7 @@ workersCommand.command("inspect [dir]").description("Inspect directory contents
135888
135995
  tableRow("Hash", `${hash2.substring(0, 16)}...`), totalSize > MAX_PACKAGE_SIZE && issues.push(`Package too large: ${formatSize(totalSize)} > ${formatSize(MAX_PACKAGE_SIZE)}`), files.some((f) => f.toLowerCase().startsWith("readme")) || warnings.push("Consider adding a README.md"), issues.length > 0 && (newline(), error2("Errors:"), issues.forEach((i) => listItem(colors.error(i), 1))), warnings.length > 0 && (newline(), warning2("Warnings:"), warnings.forEach((w2) => listItem(colors.warning(w2), 1))), issues.length === 0 && warnings.length === 0 && (newline(), success2("No issues found.")), newline();
135889
135996
  });
135890
135997
  workersCommand.command("list").alias("ls").description("List my published workers").option("--json", "Output as JSON").action(async (options) => {
135891
- requireAuth7(), await listMy(options.json);
135998
+ requireAuth8(), await listMy(options.json);
135892
135999
  });
135893
136000
  workersCommand.command("search [query]").description("Search the workers marketplace").option("--agent <agent>", "Filter by compatible agent").option("--category <cat>", "Filter by category").option("--json", "Output as JSON").action(async (query, options) => {
135894
136001
  try {
@@ -135924,7 +136031,7 @@ https://0.works/workers/${w2.slug}`), newline();
135924
136031
  }
135925
136032
  });
135926
136033
  workersCommand.command("install <slug>").alias("add").description("Download and install a worker package from the marketplace").option("-v, --version <version>", "Install a specific version").option("-o, --output <dir>", "Output directory (default: .workers/<slug>)").option("--json", "Output download info as JSON").action(async (slug, options) => {
135927
- requireAuth7();
136034
+ requireAuth8();
135928
136035
  let spin = spinner(`Fetching ${slug}...`).start();
135929
136036
  try {
135930
136037
  let w2 = (await getWorkerBySlug(slug)).worker, dlResult = await downloadWorker(slug, options.version);
@@ -135962,7 +136069,7 @@ workersCommand.command("install <slug>").alias("add").description("Download and
135962
136069
  }
135963
136070
  });
135964
136071
  workersCommand.command("purchase <slug>").alias("buy").description("Purchase a paid worker from the marketplace").option("--json", "Output as JSON").action(async (slug, options) => {
135965
- requireAuth7();
136072
+ requireAuth8();
135966
136073
  try {
135967
136074
  let w2 = (await getWorkerBySlug(slug)).worker;
135968
136075
  if (w2.priceType === "free") {
@@ -135983,10 +136090,10 @@ workersCommand.command("purchase <slug>").alias("buy").description("Purchase a p
135983
136090
  });
135984
136091
  var myCommand = workersCommand.command("my").description("Manage your workers (published and purchased)");
135985
136092
  myCommand.command("published").alias("pub").description("List my published workers").option("--json", "Output as JSON").action(async (options) => {
135986
- requireAuth7(), await listMy(options.json);
136093
+ requireAuth8(), await listMy(options.json);
135987
136094
  });
135988
136095
  myCommand.command("purchased").alias("bought").description("List my purchased workers").option("--json", "Output as JSON").action(async (options) => {
135989
- requireAuth7();
136096
+ requireAuth8();
135990
136097
  try {
135991
136098
  let result = await listMyPurchasedWorkers();
135992
136099
  if (options.json) {
@@ -136009,10 +136116,10 @@ myCommand.command("purchased").alias("bought").description("List my purchased wo
136009
136116
  }
136010
136117
  });
136011
136118
  myCommand.action(async () => {
136012
- requireAuth7(), await listMy();
136119
+ requireAuth8(), await listMy();
136013
136120
  });
136014
136121
  workersCommand.command("unpublish <id>").description("Remove a published worker (soft delete)").action(async (id) => {
136015
- requireAuth7();
136122
+ requireAuth8();
136016
136123
  try {
136017
136124
  let result = await deleteWorkerPackage(id);
136018
136125
  success2(`Removed: ${result.worker.displayName}`);
@@ -136127,6 +136234,7 @@ program2.addCommand(devicesCommand);
136127
136234
  program2.addCommand(configCommand);
136128
136235
  program2.addCommand(mcpCommand);
136129
136236
  program2.addCommand(creditsCommand);
136237
+ program2.addCommand(usageCommand);
136130
136238
  program2.addCommand(sparkletCommand);
136131
136239
  program2.addCommand(completionCommand);
136132
136240
  program2.addCommand(wechatCommand);