@adonis-agora/agent-dashboard 0.10.0 → 0.12.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 +25 -0
- package/dist/providers/agent_dashboard_provider.d.ts +2 -1
- package/dist/providers/agent_dashboard_provider.d.ts.map +1 -1
- package/dist/providers/agent_dashboard_provider.js +2 -1
- package/dist/providers/agent_dashboard_provider.js.map +1 -1
- package/dist/spa/assets/index-DUq09Q_k.js +9 -0
- package/dist/spa/index.html +1 -1
- package/dist/src/client/agent-client.d.ts +6 -1
- package/dist/src/client/agent-client.d.ts.map +1 -1
- package/dist/src/client/agent-client.js +10 -0
- package/dist/src/client/agent-client.js.map +1 -1
- package/dist/src/client/types.d.ts +74 -3
- package/dist/src/client/types.d.ts.map +1 -1
- package/package.json +11 -11
- package/dist/spa/assets/index-MrDjRM3K.js +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @adonis-agora/agent-dashboard
|
|
2
2
|
|
|
3
|
+
## 0.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#509](https://github.com/DavideCarvalho/adonis-agora-agent/pull/509) [`6dd2933`](https://github.com/DavideCarvalho/adonis-agora-agent/commit/6dd293330760da5ceddd03d4b3245a405ed2f109) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - One usage ledger for every AI cost, and where a run's time goes.
|
|
8
|
+
|
|
9
|
+
- `AgentService.recordUsage(input, { throwOnError? })` records AI spend from outside agent turns (transcription, TTS, batch embeddings, direct SDK calls) on `agent_token_usage`: `actorRef` (`null` → `PLATFORM_ACTOR_REF`, `'@platform'`), free-form `feature`, `modelId`, `provider`, tokens, `audioSeconds` / `characters` / `requests`, `costUsd` / `costSource`, optional `threadId` / `runId` / `tenantRef` / `metadata`. Never throws unless `throwOnError`; answers `{ recorded }`. Counts against the actor's quota (tokens in the token windows, cost in the USD windows, tokens bumped on the `QuotaStore`); platform cost counts against nobody.
|
|
10
|
+
- The ledger gains `feature`, `provider`, `tenant_ref`, `audio_seconds`, `characters`, `requests`, `metadata`, and a nullable `thread_id` (made nullable in place on Postgres/MySQL, by a table rebuild on SQLite; the foreign key and cascade stay). Agent-turn rows are labelled `agent:<agent name>`. `RecordUsageInput.threadId` is now optional and `UsagePurpose` gains `'external'`.
|
|
11
|
+
- Every ledger row is published as `agora:agent:usage.recorded` (amounts and attribution, never content).
|
|
12
|
+
- Governance: `spendByFeature` / `usageBreakdown` (cost by actor × feature) on `AgentGovernanceQueries`, `GET <path>/governance/spend/feature` and `/governance/usage/breakdown`; `RunUsageRow.feature`.
|
|
13
|
+
- Run timings: `agent_run` gains `queue_ms`, `model_ms`, `tools_ms`, `model_calls`, `tool_calls` and a per-step `timings` JSON. Queue time comes from the durable engine's run `createdAt` (≈0 inline), model time from the `llm.turn` span, tool time from the `tool.execution` measurement (`execution_ms`), wall-clock per step so parallel calls count once. Each figure is journaled with the step that measured it, so a resumed durable run counts every step once. `run.finished` carries `queueMs`, `modelMs`, `toolsMs`, `modelCalls`, `toolCalls`, `stepTimings`; `run.failed` / `run.cancelled` carry `queueMs` (and `run.failed` what it measured). `RunSummaryRow` and `RunDetail.timings` expose them.
|
|
14
|
+
- Dashboard: a "Spend by feature" panel on the Overview (agent turns and recorded usage side by side) and a "Where the time went" panel on the run trace (queue / model / tools / other, and each step).
|
|
15
|
+
|
|
16
|
+
## 0.11.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- [#440](https://github.com/DavideCarvalho/adonis-agora-agent/pull/440) [`c113c76`](https://github.com/DavideCarvalho/adonis-agora-agent/commit/c113c76a890b076caab8bc143c7d2a10d570b7be) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - A run's time to first token, failure code and model are stored, and the governance dashboard and the Telescope tab chart them:
|
|
21
|
+
|
|
22
|
+
- **Stored on the run.** `agent_run` gains nullable `ttft_ms`, `error_code` and `model_id`, added by `createAgentTables`' schema repair (run at boot; with `autoCreateTables: false`, re-run the `create_agent_tables` migration). `RecordRunEndInput` takes `ttftMs`, `errorCode` and `modelId`. A completed run records its time to first token and last model; a failed one records the same stable code its stream `error` frame carries (`quota_exceeded`, `model_no_output`, `run_failed`…), next to the `error` text as before. A run found dead, or failed by OpenCode, is `run_failed`. `RunSummaryRow` carries the three as optional fields.
|
|
23
|
+
- **Tool timing.** A tool call's `execution_ms` is now filled, measured inside its `tool:<id>` checkpoint: how long the tool ran, not how long a replay took to read it back. A replayed call writes none.
|
|
24
|
+
- **Read-model.** `RunReliability` gains optional `latency: { ttft, duration }` (`{ samples, p50Ms, p95Ms }`, nearest-rank, over completed turns a person started; a delegation's child run is left out) and `failuresByCode` (`{ code, count }[]`, most frequent first; a failure from before codes is `unknown`). `PerToolStatRow` gains optional `p50ExecutionMs` / `p95ExecutionMs`. `summarizeLatency` / `summarizeRunMetrics` are exported; `GenuiLatency` is now an alias of the shared `Latency`.
|
|
25
|
+
- **Dashboard.** Reliability shows time to first token and turn duration (p50 / p95) and a failures-by-code donut and table; Tools shows p50 / p95 per tool.
|
|
26
|
+
- **Telescope.** A new "Run latency" section: TTFT and turn-duration distributions (p50 / p95 / p99) from `run.finished`, and failures by code from `run.failed` (`agent.latency`, `agent.failuresByCode`). Active runs now subtract `run.failed` and `run.cancelled` too, and the tool-call counters skip a call re-published on replay.
|
|
27
|
+
|
|
3
28
|
## 0.10.0
|
|
4
29
|
|
|
5
30
|
### Minor Changes
|
|
@@ -37,7 +37,8 @@ export default class AgentDashboardProvider {
|
|
|
37
37
|
/**
|
|
38
38
|
* Resolve the actor through the agent config's resolver, mirroring the governance routes, then run
|
|
39
39
|
* the optional `authorize` gate. Returns `true` to proceed; replies `401` on a missing/failed
|
|
40
|
-
* resolver
|
|
40
|
+
* resolver (or `authorize` returning `{ allowed: false, reason: 'unauthenticated' }`) and `403`
|
|
41
|
+
* when `authorize` otherwise denies (`false`, `{ allowed: false }`, `reason: 'forbidden'`, or throws). The decision itself lives in the
|
|
41
42
|
* router-free {@link evaluateDashboardGate} so it can be unit tested; this only writes the response
|
|
42
43
|
* — the access-denied PAGE (a browser is what hits these routes), via the shared
|
|
43
44
|
* {@link answerDashboardDenial}, which also stands down when `authorize` already redirected.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent_dashboard_provider.d.ts","sourceRoot":"","sources":["../../providers/agent_dashboard_provider.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAsB;IAC7B,SAAS,CAAC,GAAG,EAAE,kBAAkB;IAA7C,YAAsB,GAAG,EAAE,kBAAkB,EAAI;IAEjD,+FAA+F;IAC/F,OAAO,CAAC,SAAS,CAAuC;IAElD,IAAI,kBAyDT;IAED
|
|
1
|
+
{"version":3,"file":"agent_dashboard_provider.d.ts","sourceRoot":"","sources":["../../providers/agent_dashboard_provider.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAsB;IAC7B,SAAS,CAAC,GAAG,EAAE,kBAAkB;IAA7C,YAAsB,GAAG,EAAE,kBAAkB,EAAI;IAEjD,+FAA+F;IAC/F,OAAO,CAAC,SAAS,CAAuC;IAElD,IAAI,kBAyDT;IAED;;;;;;;;OAQG;YACW,IAAI;IAclB;;;OAGG;YACW,SAAS;IAOvB,4FAA4F;YAC9E,SAAS;CAmBxB"}
|
|
@@ -88,7 +88,8 @@ export default class AgentDashboardProvider {
|
|
|
88
88
|
/**
|
|
89
89
|
* Resolve the actor through the agent config's resolver, mirroring the governance routes, then run
|
|
90
90
|
* the optional `authorize` gate. Returns `true` to proceed; replies `401` on a missing/failed
|
|
91
|
-
* resolver
|
|
91
|
+
* resolver (or `authorize` returning `{ allowed: false, reason: 'unauthenticated' }`) and `403`
|
|
92
|
+
* when `authorize` otherwise denies (`false`, `{ allowed: false }`, `reason: 'forbidden'`, or throws). The decision itself lives in the
|
|
92
93
|
* router-free {@link evaluateDashboardGate} so it can be unit tested; this only writes the response
|
|
93
94
|
* — the access-denied PAGE (a browser is what hits these routes), via the shared
|
|
94
95
|
* {@link answerDashboardDenial}, which also stands down when `authorize` already redirected.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent_dashboard_provider.js","sourceRoot":"","sources":["../../providers/agent_dashboard_provider.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"agent_dashboard_provider.js","sourceRoot":"","sources":["../../providers/agent_dashboard_provider.ts"],"names":[],"mappings":"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"}
|