@aiaiai-pt/martha-cli 0.62.0 → 0.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/index.js +15 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@aiaiai-pt/martha-cli`. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project adheres to semver — `0.x` releases may include breaking changes between minor versions.
|
|
4
4
|
|
|
5
|
+
## [0.63.0] — 2026-10-09
|
|
6
|
+
|
|
7
|
+
### Added — spend ceilings narrowed by API Client (#1635)
|
|
8
|
+
|
|
9
|
+
A ceiling covers the tenant, narrowed to an AI Agent and/or an API Client. It
|
|
10
|
+
applies to a call when every dimension it names matches, so one AI Agent can be
|
|
11
|
+
capped within one API Client.
|
|
12
|
+
|
|
13
|
+
- `martha budget set --client <id>` (combine with `--agent <uuid>` for an agent within a client).
|
|
14
|
+
- `martha budget list` names each ceiling's scope: `tenant`, `agent <name>`,
|
|
15
|
+
`client <name>`, or `agent <name> via client <name>`.
|
|
16
|
+
- `martha spend --group-by client`: spend per API Client.
|
|
17
|
+
|
|
5
18
|
## [0.62.0] — 2026-10-08
|
|
6
19
|
|
|
7
20
|
### Added — `--org` picks the organization for multi-organization tokens (#1611)
|
package/dist/index.js
CHANGED
|
@@ -11244,7 +11244,7 @@ init_config();
|
|
|
11244
11244
|
init_errors();
|
|
11245
11245
|
|
|
11246
11246
|
// src/version.ts
|
|
11247
|
-
var CLI_VERSION = "0.
|
|
11247
|
+
var CLI_VERSION = "0.63.0";
|
|
11248
11248
|
|
|
11249
11249
|
// src/commands/sessions.ts
|
|
11250
11250
|
function relativeTime(iso) {
|
|
@@ -21744,7 +21744,7 @@ ${models.length} models`));
|
|
|
21744
21744
|
|
|
21745
21745
|
// src/commands/spend.ts
|
|
21746
21746
|
init_errors();
|
|
21747
|
-
var GROUPINGS = ["day", "agent", "model", "surface", "billing_owner"];
|
|
21747
|
+
var GROUPINGS = ["day", "agent", "model", "surface", "billing_owner", "client"];
|
|
21748
21748
|
function usd(value) {
|
|
21749
21749
|
return value == null ? "-" : `$${Number(value).toFixed(4)}`;
|
|
21750
21750
|
}
|
|
@@ -21803,6 +21803,13 @@ ${data.tenant_id}: ${t.calls} calls, ${usd(t.cost_usd)}` + (t.unpriced_calls ? `
|
|
|
21803
21803
|
init_errors();
|
|
21804
21804
|
var PERIODS = ["day", "month"];
|
|
21805
21805
|
var ACTIONS = ["warn", "require_approval", "block"];
|
|
21806
|
+
function budgetScope(b) {
|
|
21807
|
+
const agent = b.agent_id ? `agent ${b.agent_name ?? b.agent_id}` : null;
|
|
21808
|
+
const client = b.client_id ? `client ${b.client_name ?? b.client_id}` : null;
|
|
21809
|
+
if (agent && client)
|
|
21810
|
+
return `${agent} via ${client}`;
|
|
21811
|
+
return agent ?? client ?? "tenant";
|
|
21812
|
+
}
|
|
21806
21813
|
function oneOf(value, allowed, flag) {
|
|
21807
21814
|
if (!allowed.includes(value)) {
|
|
21808
21815
|
throw new CLIError(`${flag} must be one of: ${allowed.join(", ")}`, 4 /* Validation */);
|
|
@@ -21832,22 +21839,25 @@ function registerBudgetCommands(program) {
|
|
|
21832
21839
|
return;
|
|
21833
21840
|
}
|
|
21834
21841
|
for (const b of data.budgets) {
|
|
21835
|
-
|
|
21836
|
-
console.log(`${b.id} ${scope.padEnd(42)} ${b.period.padEnd(6)} $${b.limit_usd} ${b.action}`);
|
|
21842
|
+
console.log(`${b.id} ${budgetScope(b).padEnd(42)} ${b.period.padEnd(6)} $${b.limit_usd} ${b.action}`);
|
|
21837
21843
|
}
|
|
21838
21844
|
});
|
|
21839
|
-
budget.command("set").description("Create or replace a ceiling (one per
|
|
21845
|
+
budget.command("set").description("Create or replace a ceiling (one per scope + period)").requiredOption("--period <p>", `One of: ${PERIODS.join(", ")}`).requiredOption("--limit <usd>", "Ceiling in USD (cache reads included)").requiredOption("--action <a>", `One of: ${ACTIONS.join(", ")}`).option("--agent <uuid>", "Narrow to one AI Agent (default: whole tenant)").option("--client <id>", "Narrow to one API Client (with --agent: that agent within it)").option("--note <text>", "Why this ceiling exists").option("--tenant <id>", "Tenant (defaults to your own)").action(async (opts) => {
|
|
21840
21846
|
oneOf(opts.period, PERIODS, "--period");
|
|
21841
21847
|
oneOf(opts.action, ACTIONS, "--action");
|
|
21842
21848
|
if (!/^\d+(\.\d{1,4})?$/.test(opts.limit)) {
|
|
21843
21849
|
throw new CLIError("--limit must be a non-negative USD amount", 4 /* Validation */);
|
|
21844
21850
|
}
|
|
21851
|
+
if (opts.client !== undefined && !/^[1-9]\d*$/.test(opts.client)) {
|
|
21852
|
+
throw new CLIError("--client must be an API Client id (a positive integer)", 4 /* Validation */);
|
|
21853
|
+
}
|
|
21845
21854
|
const ctx = context();
|
|
21846
21855
|
const saved = await ctx.api.put(await path(ctx, opts.tenant), {
|
|
21847
21856
|
period: opts.period,
|
|
21848
21857
|
limit_usd: opts.limit,
|
|
21849
21858
|
action: opts.action,
|
|
21850
21859
|
agent_id: opts.agent ?? null,
|
|
21860
|
+
client_id: opts.client !== undefined ? Number(opts.client) : null,
|
|
21851
21861
|
note: opts.note ?? null
|
|
21852
21862
|
});
|
|
21853
21863
|
if (program.opts().json)
|