@moneysiren/cli 0.1.0-alpha.0 → 0.1.0-alpha.10
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 +15 -4
- package/dist/apps/cli/src/cli.d.ts +4 -1
- package/dist/apps/cli/src/cli.js +20 -3
- package/dist/apps/cli/src/commands/install.js +134 -6
- package/dist/apps/cli/src/commands/modes.js +18 -10
- package/dist/apps/cli/src/commands/runtime.d.ts +5 -0
- package/dist/apps/cli/src/commands/runtime.js +366 -0
- package/dist/apps/cli/src/desktop-runtime.d.ts +54 -0
- package/dist/apps/cli/src/desktop-runtime.js +720 -0
- package/dist/apps/cli/src/home.js +27 -0
- package/dist/apps/cli/src/index.js +0 -0
- package/dist/apps/cli/src/postinstall.js +1 -1
- package/dist/apps/cli/src/release-installer.d.ts +57 -0
- package/dist/apps/cli/src/release-installer.js +432 -0
- package/dist/apps/cli/src/runtime-adapter.js +1 -1
- package/dist/apps/cli/src/slash.js +27 -0
- package/dist/apps/cli/src/version.d.ts +2 -0
- package/dist/apps/cli/src/version.js +2 -0
- package/dist/packages/config/src/load.js +3 -0
- package/dist/packages/config/src/schema.d.ts +3 -0
- package/dist/packages/config/src/schema.js +3 -0
- package/dist/packages/local-api/src/server.js +1 -1
- package/dist/packages/view-model/src/hud-model.d.ts +74 -0
- package/dist/packages/view-model/src/hud-model.js +295 -0
- package/dist/packages/view-model/src/index.d.ts +5 -2
- package/dist/packages/view-model/src/index.js +4 -1
- package/dist/packages/view-model/src/notification-preferences-model.d.ts +30 -2
- package/dist/packages/view-model/src/notification-preferences-model.js +183 -1
- package/dist/packages/view-model/src/notification-preferences.d.ts +1 -1
- package/dist/packages/view-model/src/notification-preferences.js +1 -1
- package/dist/packages/view-model/src/sync-state.d.ts +47 -0
- package/dist/packages/view-model/src/sync-state.js +140 -0
- package/dist/packages/view-model/src/usage-progress.d.ts +22 -0
- package/dist/packages/view-model/src/usage-progress.js +57 -0
- package/dist/packages/view-model/src/view-model.d.ts +22 -0
- package/dist/packages/view-model/src/view-model.js +142 -0
- package/package.json +3 -2
|
@@ -4,8 +4,10 @@ const OPENAI_PROVIDER_KEY = "openai";
|
|
|
4
4
|
const AWS_PROVIDER_KEY = "aws";
|
|
5
5
|
const SUPABASE_PROVIDER_KEY = "supabase";
|
|
6
6
|
const CLOUDFLARE_PROVIDER_KEY = "cloudflare";
|
|
7
|
+
const CODEX_APP_PROVIDER_KEY = "codex-app";
|
|
7
8
|
const CODEX_CLI_PROVIDER_KEY = "codex-cli";
|
|
8
9
|
const CLAUDE_CLI_PROVIDER_KEY = "claude-cli";
|
|
10
|
+
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
9
11
|
const SENSITIVE_TEXT_PATTERN = /(https:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9/_-]+|\b(?:sk|sbp|xox[baprs])[-_][A-Za-z0-9_-]+\b|\bacct[_-][A-Za-z0-9_-]+\b|\b(?:proj|project)[_-][A-Za-z0-9_-]+\b|\b(?:in|invoice)[_-][A-Za-z0-9_-]+\b|[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,})/gi;
|
|
10
12
|
const EMPTY_STORE = {
|
|
11
13
|
providers: [],
|
|
@@ -115,10 +117,23 @@ export function buildTodayLiveView(store, options) {
|
|
|
115
117
|
...provider,
|
|
116
118
|
providerKey: safeText(provider.providerKey),
|
|
117
119
|
displayName: safeText(provider.displayName),
|
|
120
|
+
...(provider.expiresAt === undefined ? {} : { expiresAt: provider.expiresAt }),
|
|
121
|
+
...(provider.lastAttemptAt === undefined ? {} : { lastAttemptAt: provider.lastAttemptAt }),
|
|
122
|
+
...(provider.lastSuccessAt === undefined ? {} : { lastSuccessAt: provider.lastSuccessAt }),
|
|
123
|
+
...(provider.freshUntil === undefined ? {} : { freshUntil: provider.freshUntil }),
|
|
124
|
+
...(provider.staleUntil === undefined ? {} : { staleUntil: provider.staleUntil }),
|
|
125
|
+
...(provider.lastRefreshFailed === undefined ? {} : { lastRefreshFailed: provider.lastRefreshFailed }),
|
|
126
|
+
...(provider.revision === undefined ? {} : { revision: provider.revision }),
|
|
127
|
+
...(provider.message === undefined ? {} : { message: safeText(provider.message) }),
|
|
118
128
|
metrics: (provider.metrics ?? []).map((metric) => ({
|
|
119
129
|
key: safeText(metric.key),
|
|
120
130
|
value: metric.value,
|
|
121
131
|
unit: safeText(metric.unit),
|
|
132
|
+
...(metric.resetAt === undefined ? {} : { resetAt: safeText(metric.resetAt) }),
|
|
133
|
+
...(metric.resetAtLatest === undefined ? {} : { resetAtLatest: safeText(metric.resetAtLatest) }),
|
|
134
|
+
...(metric.itemKey === undefined ? {} : { itemKey: safeText(metric.itemKey) }),
|
|
135
|
+
...(metric.accuracy === undefined ? {} : { accuracy: metric.accuracy }),
|
|
136
|
+
...(metric.source === undefined ? {} : { source: safeText(metric.source) }),
|
|
122
137
|
})),
|
|
123
138
|
}));
|
|
124
139
|
const includedProviders = providers.filter((provider) => provider.included && provider.todayLiveAmountMinor !== null);
|
|
@@ -387,6 +402,8 @@ function buildDigestItems(overview, todayLive, alerts) {
|
|
|
387
402
|
usedTokensMetricKey: "weekly_tokens",
|
|
388
403
|
clickPath: "/ko/services/codex-cli",
|
|
389
404
|
}),
|
|
405
|
+
codexResetCreditCountItem(todayLive),
|
|
406
|
+
codexResetCreditExpiryItem(todayLive),
|
|
390
407
|
{
|
|
391
408
|
widgetKey: "supabase_usage_health",
|
|
392
409
|
kind: "health",
|
|
@@ -425,6 +442,13 @@ function cliRemainingPercentItem(options) {
|
|
|
425
442
|
severity: remainingPercentSeverity(percent),
|
|
426
443
|
label: options.label,
|
|
427
444
|
value: percent === null ? "Not available" : formatPercent(percent),
|
|
445
|
+
...(percent === null ? {} : {
|
|
446
|
+
numericValue: percent,
|
|
447
|
+
unit: "percent",
|
|
448
|
+
remainingPercent: percent,
|
|
449
|
+
usedPercent: clampPercent(100 - percent),
|
|
450
|
+
}),
|
|
451
|
+
providerKey: options.providerKey,
|
|
428
452
|
...(firstProvider === undefined
|
|
429
453
|
? {}
|
|
430
454
|
: {
|
|
@@ -434,6 +458,68 @@ function cliRemainingPercentItem(options) {
|
|
|
434
458
|
clickPath: options.clickPath,
|
|
435
459
|
};
|
|
436
460
|
}
|
|
461
|
+
function codexResetCreditCountItem(todayLive) {
|
|
462
|
+
const providers = [
|
|
463
|
+
...todayProviders(todayLive, CODEX_APP_PROVIDER_KEY),
|
|
464
|
+
...todayProviders(todayLive, CODEX_CLI_PROVIDER_KEY),
|
|
465
|
+
];
|
|
466
|
+
const firstProvider = providers[0];
|
|
467
|
+
const metricEntry = firstMetricEntry(providers, "usage_reset_credits");
|
|
468
|
+
const count = metricEntry?.metric.value ?? null;
|
|
469
|
+
const clickProviderKey = metricEntry?.provider.providerKey ?? CODEX_CLI_PROVIDER_KEY;
|
|
470
|
+
return {
|
|
471
|
+
widgetKey: "codex_reset_credit_count",
|
|
472
|
+
kind: "usage",
|
|
473
|
+
severity: "info",
|
|
474
|
+
label: "Codex reset credits",
|
|
475
|
+
value: count === null ? "Not available" : formatCount(count),
|
|
476
|
+
...(count === null ? {} : {
|
|
477
|
+
numericValue: count,
|
|
478
|
+
unit: "count",
|
|
479
|
+
}),
|
|
480
|
+
...(metricEntry === undefined ? {} : { providerKey: metricEntry.provider.providerKey }),
|
|
481
|
+
...(firstProvider === undefined
|
|
482
|
+
? {}
|
|
483
|
+
: {
|
|
484
|
+
freshness: firstProvider.freshness,
|
|
485
|
+
confidence: firstProvider.confidence,
|
|
486
|
+
}),
|
|
487
|
+
clickPath: `/ko/services/${clickProviderKey}`,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
function codexResetCreditExpiryItem(todayLive) {
|
|
491
|
+
const providers = [
|
|
492
|
+
...todayProviders(todayLive, CODEX_APP_PROVIDER_KEY),
|
|
493
|
+
...todayProviders(todayLive, CODEX_CLI_PROVIDER_KEY),
|
|
494
|
+
];
|
|
495
|
+
const firstProvider = providers[0];
|
|
496
|
+
const exactExpiry = earliestMetricResetAt(providers, "usage_reset_credit");
|
|
497
|
+
const estimatedExpiry = earliestMetricResetAt(providers, "usage_reset_credit_estimate");
|
|
498
|
+
const earliestExpiry = exactExpiry ?? estimatedExpiry;
|
|
499
|
+
const metric = earliestResetCreditMetric(providers, exactExpiry === null ? "usage_reset_credit_estimate" : "usage_reset_credit", earliestExpiry);
|
|
500
|
+
const metricProviderKey = metric === undefined ? undefined : providerForMetric(providers, metric);
|
|
501
|
+
const daysUntil = earliestExpiry === null
|
|
502
|
+
? null
|
|
503
|
+
: Math.ceil((Date.parse(earliestExpiry) - Date.parse(todayLive.generatedAt)) / MS_PER_DAY);
|
|
504
|
+
return {
|
|
505
|
+
widgetKey: "codex_reset_credit_expiry",
|
|
506
|
+
kind: "usage",
|
|
507
|
+
severity: resetCreditExpirySeverity(daysUntil),
|
|
508
|
+
label: "Codex reset credit expiry",
|
|
509
|
+
value: resetCreditExpiryValue(daysUntil),
|
|
510
|
+
...(earliestExpiry === null ? {} : { resetAt: earliestExpiry }),
|
|
511
|
+
...(metric?.resetAtLatest === undefined ? {} : { resetAtLatest: metric.resetAtLatest }),
|
|
512
|
+
...(metric?.accuracy === undefined ? {} : { accuracy: metric.accuracy }),
|
|
513
|
+
...(metricProviderKey === undefined ? {} : { providerKey: metricProviderKey }),
|
|
514
|
+
...(firstProvider === undefined
|
|
515
|
+
? {}
|
|
516
|
+
: {
|
|
517
|
+
freshness: firstProvider.freshness,
|
|
518
|
+
confidence: firstProvider.confidence,
|
|
519
|
+
}),
|
|
520
|
+
clickPath: "/ko/services/codex-cli",
|
|
521
|
+
};
|
|
522
|
+
}
|
|
437
523
|
async function resolveStore(options) {
|
|
438
524
|
if (options.store !== undefined) {
|
|
439
525
|
return options.store;
|
|
@@ -529,6 +615,33 @@ function metricFirst(providers, metricKey) {
|
|
|
529
615
|
}
|
|
530
616
|
return null;
|
|
531
617
|
}
|
|
618
|
+
function firstMetricEntry(providers, metricKey) {
|
|
619
|
+
for (const provider of providers) {
|
|
620
|
+
const metric = provider.metrics.find((item) => item.key === metricKey);
|
|
621
|
+
if (metric !== undefined) {
|
|
622
|
+
return { provider, metric };
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return undefined;
|
|
626
|
+
}
|
|
627
|
+
function earliestMetricResetAt(providers, metricKey) {
|
|
628
|
+
const values = providers.flatMap((provider) => provider.metrics
|
|
629
|
+
.filter((metric) => metric.key === metricKey && metric.resetAt !== undefined)
|
|
630
|
+
.map((metric) => metric.resetAt)
|
|
631
|
+
.filter((value) => Number.isFinite(Date.parse(value))));
|
|
632
|
+
return values.sort((first, second) => Date.parse(first) - Date.parse(second))[0] ?? null;
|
|
633
|
+
}
|
|
634
|
+
function earliestResetCreditMetric(providers, metricKey, resetAt) {
|
|
635
|
+
if (resetAt === null) {
|
|
636
|
+
return undefined;
|
|
637
|
+
}
|
|
638
|
+
return providers
|
|
639
|
+
.flatMap((provider) => provider.metrics)
|
|
640
|
+
.find((metric) => metric.key === metricKey && metric.resetAt === resetAt);
|
|
641
|
+
}
|
|
642
|
+
function providerForMetric(providers, target) {
|
|
643
|
+
return providers.find((provider) => provider.metrics.some((metric) => metric === target))?.providerKey;
|
|
644
|
+
}
|
|
532
645
|
function remainingPercentFromMetrics(providers, remainingTokensMetricKey, usedTokensMetricKey, usedPercentMetricKey) {
|
|
533
646
|
const remainingTokens = metricSum(providers, remainingTokensMetricKey);
|
|
534
647
|
const usedTokens = metricSum(providers, usedTokensMetricKey);
|
|
@@ -541,6 +654,30 @@ function remainingPercentFromMetrics(providers, remainingTokensMetricKey, usedTo
|
|
|
541
654
|
const usedPercent = metricFirst(providers, usedPercentMetricKey);
|
|
542
655
|
return usedPercent === null ? null : clampPercent(100 - usedPercent);
|
|
543
656
|
}
|
|
657
|
+
function resetCreditExpirySeverity(daysUntil) {
|
|
658
|
+
if (daysUntil === null) {
|
|
659
|
+
return "info";
|
|
660
|
+
}
|
|
661
|
+
if (daysUntil <= 1) {
|
|
662
|
+
return "critical";
|
|
663
|
+
}
|
|
664
|
+
if (daysUntil <= 7) {
|
|
665
|
+
return "warning";
|
|
666
|
+
}
|
|
667
|
+
return "info";
|
|
668
|
+
}
|
|
669
|
+
function resetCreditExpiryValue(daysUntil) {
|
|
670
|
+
if (daysUntil === null) {
|
|
671
|
+
return "Not available";
|
|
672
|
+
}
|
|
673
|
+
if (daysUntil <= 0) {
|
|
674
|
+
return "May expire now";
|
|
675
|
+
}
|
|
676
|
+
if (daysUntil === 1) {
|
|
677
|
+
return "May expire within 1 day";
|
|
678
|
+
}
|
|
679
|
+
return `May expire within ${daysUntil} days`;
|
|
680
|
+
}
|
|
544
681
|
function providerRiskSeverity(provider) {
|
|
545
682
|
if (provider?.riskLevel === "critical") {
|
|
546
683
|
return "critical";
|
|
@@ -662,6 +799,11 @@ function formatTokens(tokens) {
|
|
|
662
799
|
maximumFractionDigits: 0,
|
|
663
800
|
}).format(tokens);
|
|
664
801
|
}
|
|
802
|
+
function formatCount(value) {
|
|
803
|
+
return new Intl.NumberFormat("en-US", {
|
|
804
|
+
maximumFractionDigits: 0,
|
|
805
|
+
}).format(value);
|
|
806
|
+
}
|
|
665
807
|
function formatPercent(percent) {
|
|
666
808
|
const rounded = Number.isInteger(percent) ? percent.toFixed(0) : percent.toFixed(1);
|
|
667
809
|
return `${rounded}%`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moneysiren/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.10",
|
|
4
4
|
"description": "Local-first cloud/SaaS usage, status, and expected billing CLI for MoneySiren.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"node": ">=20.11.0"
|
|
11
11
|
},
|
|
12
12
|
"bin": {
|
|
13
|
-
"moneysiren": "dist/apps/cli/src/index.js"
|
|
13
|
+
"moneysiren": "dist/apps/cli/src/index.js",
|
|
14
|
+
"msiren": "dist/apps/cli/src/index.js"
|
|
14
15
|
},
|
|
15
16
|
"main": "dist/apps/cli/src/cli.js",
|
|
16
17
|
"types": "dist/apps/cli/src/cli.d.ts",
|