@hasna/economy 0.3.28 → 0.4.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 +95 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +6 -13
- package/SECURITY.md +1 -1
- package/dist/cli/commands/extras.d.ts.map +1 -1
- package/dist/cli/index.js +1135 -853
- package/dist/db/cloud.d.ts +16 -8
- package/dist/db/cloud.d.ts.map +1 -1
- package/dist/db/database.d.ts +19 -0
- package/dist/db/database.d.ts.map +1 -1
- package/dist/index.js +198 -19
- package/dist/ingest/claude.d.ts.map +1 -1
- package/dist/ingest/loops.d.ts +9 -0
- package/dist/ingest/loops.d.ts.map +1 -1
- package/dist/lib/accounts-store.d.ts +83 -0
- package/dist/lib/accounts-store.d.ts.map +1 -0
- package/dist/lib/accounts.d.ts +2 -1
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/api-display-url.d.ts +19 -0
- package/dist/lib/api-display-url.d.ts.map +1 -0
- package/dist/lib/autosync-gate.d.ts +15 -0
- package/dist/lib/autosync-gate.d.ts.map +1 -0
- package/dist/lib/cloud-ingest.d.ts +15 -1
- package/dist/lib/cloud-ingest.d.ts.map +1 -1
- package/dist/lib/cloud-storage.d.ts +166 -10
- package/dist/lib/cloud-storage.d.ts.map +1 -1
- package/dist/lib/gatherer.d.ts.map +1 -1
- package/dist/lib/serve-auth.d.ts.map +1 -1
- package/dist/lib/store/index.d.ts +6 -3
- package/dist/lib/store/index.d.ts.map +1 -1
- package/dist/lib/test-hermetic-accounts.d.ts +3 -2
- package/dist/lib/test-hermetic-accounts.d.ts.map +1 -1
- package/dist/lib/test-hermetic-fleet-env.d.ts +4 -0
- package/dist/lib/test-hermetic-fleet-env.d.ts.map +1 -0
- package/dist/mcp/agent-registry.d.ts +85 -0
- package/dist/mcp/agent-registry.d.ts.map +1 -0
- package/dist/mcp/harness.d.ts +26 -0
- package/dist/mcp/harness.d.ts.map +1 -0
- package/dist/mcp/index.js +1340 -302
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/otel/index.js +430 -16
- package/dist/server/index.js +548 -155
- package/dist/server/serve.d.ts +0 -2
- package/dist/server/serve.d.ts.map +1 -1
- package/docs/cli.md +2 -3
- package/docs/configuration.md +23 -10
- package/docs/ingestion.md +1 -1
- package/docs/mcp.md +4 -2
- package/docs/otel.md +8 -2
- package/docs/rest-api.md +2 -2
- package/package.json +5 -11
- package/postinstall.js +52 -1
- package/dashboard/README.md +0 -26
- package/dist/cli/brains.d.ts +0 -3
- package/dist/cli/brains.d.ts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,100 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 00118b3: Resolve credentials through the `@hasna/contracts` 1.0.2 client chain (hasna/apps#1720).
|
|
8
|
+
|
|
9
|
+
The CLI, the MCP server and the `./sdk` store surface no longer carry a
|
|
10
|
+
credential chain of their own. All three route through the one resolver in
|
|
11
|
+
`@hasna/contracts` (bumped from 0.13.4 to the exact 1.0.2), which reads, per
|
|
12
|
+
call: an explicit `--api-key`/`--profile`, then `HASNA_ECONOMY_API_KEY_OVERRIDE`
|
|
13
|
+
/ `HASNA_PROFILE` / `HASNA_ECONOMY_API_KEY_REF`, then the macOS Keychain item
|
|
14
|
+
`hasna.credentials.economy.api-key`, then `~/.hasna/economy/config/credentials`
|
|
15
|
+
(0600, `HASNA_ECONOMY_API_KEY=…`), then `HASNA_ECONOMY_API_KEY`. The authority
|
|
16
|
+
follows the same ladder — `HASNA_ECONOMY_API_URL`, the Keychain `api-url` item,
|
|
17
|
+
the credentials file — and now DEFAULTS to the fleet gateway
|
|
18
|
+
`https://api.hasna.com/economy` once a credential resolves, so a key alone is a
|
|
19
|
+
complete configuration. A long-lived MCP server re-resolves the credential on
|
|
20
|
+
every request, so a rotation heals without a restart.
|
|
21
|
+
|
|
22
|
+
What this removes:
|
|
23
|
+
|
|
24
|
+
- The app's own legacy env chain: the unprefixed serve token `ECONOMY_API_TOKEN`
|
|
25
|
+
(canonical `HASNA_ECONOMY_API_TOKEN` remains) and `ECONOMY_MACHINE_ID`
|
|
26
|
+
(canonical `HASNA_ECONOMY_MACHINE_ID`).
|
|
27
|
+
- Retired `*_MODE` / `*_STORAGE_MODE` switches stay a hard error, and the
|
|
28
|
+
DEPRECATED notice is gone: `HASNA_ECONOMY_API_KEY` is a legitimate resolver
|
|
29
|
+
tier, it just sits below the Keychain and the credentials file.
|
|
30
|
+
- Nothing reads `~/.hasna/fleet-env`, `~/.hasna/cloud`, `~/.config/hasna` or
|
|
31
|
+
`$XDG_CONFIG_HOME` — the resolver never consults those locations.
|
|
32
|
+
|
|
33
|
+
What this keeps and adds:
|
|
34
|
+
|
|
35
|
+
- Fail loud (owner directive 2026-09-04): hosted with no credential = non-zero
|
|
36
|
+
exit, no SQLite file, no `economy-local-fallback` event, and an error naming
|
|
37
|
+
every tier consulted. Local mode is served only by the explicit opt-in
|
|
38
|
+
`HASNA_ECONOMY_LOCAL=1` (alias `ECONOMY_LOCAL=1` for one release), which
|
|
39
|
+
yields to every hosted signal and now prints one `economy: local mode …` line
|
|
40
|
+
on stderr.
|
|
41
|
+
- `economy transport` (new CLI command): reports the resolved transport and the
|
|
42
|
+
credential SOURCE — `/v1` authority, `api_url_source`, `api_key_source`,
|
|
43
|
+
`api_key_tier` — never the key value; `--json` for the full report. It is the
|
|
44
|
+
one surface that reports a refusal instead of throwing.
|
|
45
|
+
- The `./sdk` store surface (`getStore`) is unchanged in shape, and it is the
|
|
46
|
+
ONLY SDK: the Store takes no `baseUrl`, so the package can never attach an
|
|
47
|
+
ambient fleet key to a caller-supplied one (hasna/apps#1794) — the authority
|
|
48
|
+
and the credential both come from the resolver, per call.
|
|
49
|
+
- `@hasna/contracts` stays a runtime dependency (economy builds with
|
|
50
|
+
`--packages external`), so the published declarations importing its types
|
|
51
|
+
resolve for consumers. The `/v1/machines` and `/v1/fleet` surfaces are
|
|
52
|
+
unchanged and keep working against the resolved authority.
|
|
53
|
+
|
|
54
|
+
### Patch Changes
|
|
55
|
+
|
|
56
|
+
- 361d51b: Fail-closed / resolver validation fixes for the hosted-by-default client
|
|
57
|
+
(hasna/apps#1720, validation round 1).
|
|
58
|
+
|
|
59
|
+
- **MCP: no SQLite under the app home in hosted mode.** `economy-mcp` opened
|
|
60
|
+
the agent-lifecycle registry (`agent-registry.db` plus its WAL/SHM sidecars)
|
|
61
|
+
at startup — in hosted mode too, before any tool was called. The registry
|
|
62
|
+
store is now resolved on first tool use, and a hosted client keeps it in
|
|
63
|
+
memory for the life of the process; only the explicit `HASNA_ECONOMY_LOCAL=1`
|
|
64
|
+
opt-in persists `agent-registry.db` beside the local store
|
|
65
|
+
(`HASNA_AGENT_REGISTRY_DB_PATH` still names a file explicitly in either lane).
|
|
66
|
+
- **MCP: the fail-closed diagnostic is the first stderr line**
|
|
67
|
+
(`MCP server error: Economy fails closed …`, naming the Keychain item, the
|
|
68
|
+
credentials file and `HASNA_ECONOMY_API_KEY`) instead of Bun's code frame.
|
|
69
|
+
- **`economy transport` exits 1 when no credential resolves.** The report is
|
|
70
|
+
still printed (`--json` included), so the diagnostic stays readable while a
|
|
71
|
+
script can no longer take a refusal for a hosted transport.
|
|
72
|
+
- **`economy-otel` follows the storage seam.** With a resolved credential the
|
|
73
|
+
sidecar forwards the request/session rows of every accepted payload to the
|
|
74
|
+
shared API's `/v1/ingest` (the response gains `forwarded`; nothing is written
|
|
75
|
+
under `~/.hasna/economy`); under `HASNA_ECONOMY_LOCAL=1` it writes the
|
|
76
|
+
on-box store and announces local mode on stderr; with neither it fails
|
|
77
|
+
closed before binding. `economy-otel` stays undeclared in
|
|
78
|
+
`hasna.contract.json` because `-otel` is outside the contract kit's bin
|
|
79
|
+
allowlist.
|
|
80
|
+
- **Hosted `economy sync` keeps its mtime cache as a JSON file under the cache
|
|
81
|
+
root** (`HASNA_CACHE_HOME`, else `~/Library/Caches/Hasna/economy` on macOS /
|
|
82
|
+
`~/.cache/hasna/economy` elsewhere; `HASNA_ECONOMY_INGEST_CACHE` overrides)
|
|
83
|
+
instead of `~/.hasna/economy/ingest-cache.db`. An older cache file is simply
|
|
84
|
+
not read — one re-read, absorbed by the server's idempotent upserts — and can
|
|
85
|
+
be deleted.
|
|
86
|
+
- **Manifest:** the CLI and MCP surfaces declare `authMode: api-key`
|
|
87
|
+
(credential via the `@hasna/contracts` chain) and the SDK surface
|
|
88
|
+
`exportSubpath: ./sdk`.
|
|
89
|
+
- **No `-sdk` split package.** The unpublished in-tree `@hasna/economy-sdk`
|
|
90
|
+
(`sdk/`) is removed: the SDK is the `./sdk` export of this one package — the
|
|
91
|
+
Store abstraction, which takes no `baseUrl` and therefore never attaches an
|
|
92
|
+
ambient fleet key to a caller-supplied one (hasna/apps#1794).
|
|
93
|
+
- Test hygiene: `src/mcp/http.test.ts` restores the local opt-in it pins, so
|
|
94
|
+
the #1788 ambient-gate test passes in the full suite; new spawned-bin tests
|
|
95
|
+
cover the MCP hosted / fail-closed arms, the three `economy-otel` lanes and
|
|
96
|
+
the `economy transport` exit codes.
|
|
97
|
+
|
|
3
98
|
## 0.3.28
|
|
4
99
|
|
|
5
100
|
### Patch Changes
|
package/CONTRIBUTING.md
CHANGED
|
@@ -13,7 +13,7 @@ bun run typecheck
|
|
|
13
13
|
bun run build
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
The SDK is the `./sdk` export subpath of this package (`src/index.ts`, the Store abstraction); there is no separate `sdk/` package to build or publish.
|
|
17
17
|
|
|
18
18
|
## Release And Package Hygiene
|
|
19
19
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @hasna/economy
|
|
2
2
|
|
|
3
|
-
AI coding cost tracker for Claude Code, Takumi, Codex, Gemini, OpenCode, Cursor, Pi, and Hermes. It ships as a CLI, MCP server, REST API,
|
|
3
|
+
AI coding cost tracker for Claude Code, Takumi, Codex, Gemini, OpenCode, Cursor, Pi, and Hermes. It ships as a CLI, MCP server, REST API, and native macOS menu bar app.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@hasna/economy)
|
|
6
6
|
[](LICENSE)
|
|
@@ -14,7 +14,7 @@ AI coding cost tracker for Claude Code, Takumi, Codex, Gemini, OpenCode, Cursor,
|
|
|
14
14
|
- Seeds editable model pricing with input, output, cache-read, 5-minute cache-write, 1-hour cache-write, and context-cache storage rates.
|
|
15
15
|
- Handles tiered pricing such as Gemini long-prompt rates and OpenAI long-context rates.
|
|
16
16
|
- Reconciles estimates against Anthropic, OpenAI, and Gemini billing sources.
|
|
17
|
-
- Exposes cost data through CLI commands, an MCP server, REST endpoints
|
|
17
|
+
- Exposes cost data through CLI commands, an MCP server, and REST endpoints.
|
|
18
18
|
- Syncs project metadata from the `@hasna/projects` registry during full local sync.
|
|
19
19
|
- Sends budget alert webhooks and retries failed deliveries on later syncs.
|
|
20
20
|
|
|
@@ -33,12 +33,6 @@ economy pricing list
|
|
|
33
33
|
economy serve --port 3456
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
Open the dashboard with:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
economy dashboard --port 3456
|
|
40
|
-
```
|
|
41
|
-
|
|
42
36
|
## Documentation
|
|
43
37
|
|
|
44
38
|
- [CLI reference](docs/cli.md)
|
|
@@ -237,7 +231,7 @@ Start the server:
|
|
|
237
231
|
economy-serve --port 3456
|
|
238
232
|
```
|
|
239
233
|
|
|
240
|
-
The canonical API uses `/v1`; `/api` remains a legacy alias for
|
|
234
|
+
The canonical API uses `/v1`; `/api` remains a legacy alias for older clients. For example:
|
|
241
235
|
|
|
242
236
|
- `GET /health`, `/ready`, `/version`, and `/openapi.json`
|
|
243
237
|
- `GET /v1/summary?period=today`
|
|
@@ -248,8 +242,6 @@ The canonical API uses `/v1`; `/api` remains a legacy alias for the dashboard an
|
|
|
248
242
|
|
|
249
243
|
See the [REST API reference](docs/rest-api.md) for every route, response envelopes, authentication, and legacy aliases. The server publishes the current generated contract at `/openapi.json`.
|
|
250
244
|
|
|
251
|
-
The server also serves the built dashboard when `dashboard/dist` is present. The dashboard includes account-scoped session filtering, subscription plan create/update/delete controls in Savings, and savings/usage/account tables for subscription-aware cost analysis.
|
|
252
|
-
|
|
253
245
|
## Native macOS Menubar
|
|
254
246
|
|
|
255
247
|
The `menubar/` app is a native SwiftUI `MenuBarExtra` app, not Electron. It targets Swift 5.9+ and macOS 14+, and talks to the REST API exposed by `economy-serve`. It shows today/week/month spend, token and request counts, top agents, top accounts, top projects, active subscription plans, subscription savings, multi-agent usage snapshots, recent sessions, and fleet status. The default server URL is `http://127.0.0.1:3456`.
|
|
@@ -276,7 +268,9 @@ Data is stored under a single data root resolved through the `@hasna/paths` reso
|
|
|
276
268
|
|
|
277
269
|
The main SQLite database lives at `<data-root>/economy.db` (`~/.hasna/economy/economy.db` by default). Older `~/.economy/` data is copied on first open when the new directory does not exist. Override the database path with `HASNA_ECONOMY_DB_PATH` or `ECONOMY_DB`.
|
|
278
270
|
|
|
279
|
-
For shared deployments, CLI and
|
|
271
|
+
For shared deployments, CLI, MCP and `./sdk` can use a remote `/v1` API instead of local SQLite. Their credential is resolved by `@hasna/contracts` 1.0.2, fresh per request, from: an explicit `--api-key`/`--profile` argument, the env pointers `HASNA_ECONOMY_API_KEY_OVERRIDE` / `HASNA_PROFILE` / `HASNA_ECONOMY_API_KEY_REF`, the macOS Keychain item `hasna.credentials.economy.api-key`, the 0600 file `~/.hasna/economy/config/credentials` (`HASNA_ECONOMY_API_KEY=…`), then `HASNA_ECONOMY_API_KEY` in the environment. The authority follows the same ladder (`HASNA_ECONOMY_API_URL`, the Keychain `api-url` item, the credentials file) and defaults to the fleet gateway `https://api.hasna.com/economy`. Unprefixed `ECONOMY_API_URL`/`ECONOMY_API_KEY` aliases are legacy, accepted for one release.
|
|
272
|
+
|
|
273
|
+
**A run without a credential fails closed**: non-zero exit, no SQLite file, no local-fallback event. The on-box store is served only with the explicit opt-in `HASNA_ECONOMY_LOCAL=1` (alias `ECONOMY_LOCAL=1`), which prints `economy: local mode …` on stderr. See [configuration](docs/configuration.md) for the full client resolution, server auth, Postgres mode, and all environment variables.
|
|
280
274
|
|
|
281
275
|
## Development
|
|
282
276
|
|
|
@@ -285,7 +279,6 @@ bun test
|
|
|
285
279
|
bun run typecheck
|
|
286
280
|
bun run build
|
|
287
281
|
bun scripts/sync-openapi.ts
|
|
288
|
-
cd dashboard && bun run lint
|
|
289
282
|
cd menubar && swift build -c release
|
|
290
283
|
```
|
|
291
284
|
|
package/SECURITY.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Supported Versions
|
|
4
4
|
|
|
5
|
-
Security fixes are handled for the latest published
|
|
5
|
+
Security fixes are handled for the latest published version of `@hasna/economy` (the CLI, MCP, server and `./sdk` surfaces ship in that one package).
|
|
6
6
|
|
|
7
7
|
## Reporting A Vulnerability
|
|
8
8
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extras.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/extras.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"extras.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/extras.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAmDnC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+V/D;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyC5D"}
|