@adonis-agora/agent-dashboard 0.1.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/LICENSE +21 -0
  3. package/README.md +57 -0
  4. package/dist/providers/agent_dashboard_provider.d.ts +33 -0
  5. package/dist/providers/agent_dashboard_provider.d.ts.map +1 -0
  6. package/dist/providers/agent_dashboard_provider.js +101 -0
  7. package/dist/providers/agent_dashboard_provider.js.map +1 -0
  8. package/dist/spa/assets/index-BYLm0nq8.css +1 -0
  9. package/dist/spa/assets/index-DR5D-Xzw.js +9 -0
  10. package/dist/spa/index.html +13 -0
  11. package/dist/src/client/agent-client.d.ts +55 -0
  12. package/dist/src/client/agent-client.d.ts.map +1 -0
  13. package/dist/src/client/agent-client.js +141 -0
  14. package/dist/src/client/agent-client.js.map +1 -0
  15. package/dist/src/client/api-base.d.ts +23 -0
  16. package/dist/src/client/api-base.d.ts.map +1 -0
  17. package/dist/src/client/api-base.js +32 -0
  18. package/dist/src/client/api-base.js.map +1 -0
  19. package/dist/src/client/default-range.d.ts +10 -0
  20. package/dist/src/client/default-range.d.ts.map +1 -0
  21. package/dist/src/client/default-range.js +26 -0
  22. package/dist/src/client/default-range.js.map +1 -0
  23. package/dist/src/client/format.d.ts +22 -0
  24. package/dist/src/client/format.d.ts.map +1 -0
  25. package/dist/src/client/format.js +76 -0
  26. package/dist/src/client/format.js.map +1 -0
  27. package/dist/src/client/index.d.ts +9 -0
  28. package/dist/src/client/index.d.ts.map +1 -0
  29. package/dist/src/client/index.js +8 -0
  30. package/dist/src/client/index.js.map +1 -0
  31. package/dist/src/client/spend-summary.d.ts +43 -0
  32. package/dist/src/client/spend-summary.d.ts.map +1 -0
  33. package/dist/src/client/spend-summary.js +59 -0
  34. package/dist/src/client/spend-summary.js.map +1 -0
  35. package/dist/src/client/trend-path.d.ts +27 -0
  36. package/dist/src/client/trend-path.d.ts.map +1 -0
  37. package/dist/src/client/trend-path.js +25 -0
  38. package/dist/src/client/trend-path.js.map +1 -0
  39. package/dist/src/client/types.d.ts +202 -0
  40. package/dist/src/client/types.d.ts.map +1 -0
  41. package/dist/src/client/types.js +8 -0
  42. package/dist/src/client/types.js.map +1 -0
  43. package/dist/src/server/define_config.d.ts +18 -0
  44. package/dist/src/server/define_config.d.ts.map +1 -0
  45. package/dist/src/server/define_config.js +6 -0
  46. package/dist/src/server/define_config.js.map +1 -0
  47. package/dist/src/server/paths.d.ts +27 -0
  48. package/dist/src/server/paths.d.ts.map +1 -0
  49. package/dist/src/server/paths.js +78 -0
  50. package/dist/src/server/paths.js.map +1 -0
  51. package/package.json +84 -0
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>agent · governance console</title>
7
+ <script type="module" crossorigin src="./assets/index-DR5D-Xzw.js"></script>
8
+ <link rel="stylesheet" crossorigin href="./assets/index-BYLm0nq8.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
@@ -0,0 +1,55 @@
1
+ import type { ActorSpendRow, GovernanceRange, ListRunsFilter, ListRunsResult, ModelSpendRow, PendingApprovalRow, PendingApprovalsFilter, PerToolStatRow, QuotaToday, RunDetail, RunReliability, ThreadActivityRow, ToolCallActivityRow, ToolStatsRange, UsageTrendPoint } from './types.js';
2
+ /** Thrown on a non-2xx governance response, carrying the HTTP status for the UI to branch on. */
3
+ export declare class AgentApiError extends Error {
4
+ readonly status: number;
5
+ constructor(message: string, status: number);
6
+ }
7
+ type FetchLike = typeof fetch;
8
+ export interface AgentClientOptions {
9
+ /** Agent API base (e.g. `/agent`). Defaults to the injected/derived base for the current page. */
10
+ baseUrl?: string;
11
+ /** Injectable `fetch` (tests pass a stub). Defaults to the global. */
12
+ fetch?: FetchLike;
13
+ /** Cap for the `recent*` feeds; the server clamps to 200. Defaults to 50. */
14
+ limit?: number;
15
+ }
16
+ /**
17
+ * A framework-free browser client for the `@adonis-agora/agent` provider's READ surface: the five
18
+ * `/agent/governance/*` rollups plus the per-actor `quota/today`. Same-origin, `credentials:
19
+ * 'same-origin'` so the host's actor/auth cookie gates every call exactly as it gates the routes
20
+ * server-side. No third-party HTTP dependency.
21
+ */
22
+ export declare class AgentClient {
23
+ private readonly base;
24
+ private readonly doFetch;
25
+ private readonly limit;
26
+ constructor(options?: AgentClientOptions);
27
+ private get;
28
+ private post;
29
+ spendByModel(range: GovernanceRange): Promise<ModelSpendRow[]>;
30
+ spendByActor(range: GovernanceRange): Promise<ActorSpendRow[]>;
31
+ usageTrend(range: GovernanceRange): Promise<UsageTrendPoint[]>;
32
+ recentToolCalls(limit?: number): Promise<ToolCallActivityRow[]>;
33
+ recentThreads(limit?: number): Promise<ThreadActivityRow[]>;
34
+ quotaToday(): Promise<QuotaToday>;
35
+ /** `GET /agent/governance/runs` — filterable, cursor-paginated run list, newest-first. */
36
+ listRuns(filter?: ListRunsFilter): Promise<ListRunsResult>;
37
+ /** `GET /agent/governance/runs/:id` — one run's full trace, or `null` if unknown. */
38
+ runDetail(runId: string): Promise<RunDetail | null>;
39
+ /** `GET /agent/governance/approvals/pending` — cross-thread HITL inbox, oldest first. */
40
+ pendingApprovals(filter?: PendingApprovalsFilter): Promise<PendingApprovalRow[]>;
41
+ /** `GET /agent/governance/tools/stats` — per-tool call/failure/rejection/latency rollup. */
42
+ perToolStats(range?: ToolStatsRange): Promise<PerToolStatRow[]>;
43
+ /** `GET /agent/governance/reliability` — success/failure/cancel rates + mean settled duration. */
44
+ runReliability(range?: ToolStatsRange): Promise<RunReliability>;
45
+ /** `POST /agent/tool-call/approve` — release a `pending_approval` tool call. */
46
+ approveToolCall(runId: string, toolCallId: string): Promise<{
47
+ ok: boolean;
48
+ }>;
49
+ /** `POST /agent/tool-call/reject` — deny a `pending_approval` tool call, with an optional reason. */
50
+ rejectToolCall(runId: string, toolCallId: string, reason?: string): Promise<{
51
+ ok: boolean;
52
+ }>;
53
+ }
54
+ export {};
55
+ //# sourceMappingURL=agent-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-client.d.ts","sourceRoot":"","sources":["../../../src/client/agent-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,cAAc,EACd,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,sBAAsB,EACtB,cAAc,EACd,UAAU,EACV,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,iGAAiG;AACjG,qBAAa,aAAc,SAAQ,KAAK;IAGpC,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADvB,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM;CAK1B;AAED,KAAK,SAAS,GAAG,OAAO,KAAK,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,kGAAkG;IAClG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,OAAO,GAAE,kBAAuB;YAM9B,GAAG;YAcH,IAAI;IAalB,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAO9D,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAO9D,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAO9D,eAAe,CAAC,KAAK,SAAa,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAMnE,aAAa,CAAC,KAAK,SAAa,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAI/D,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC;IAMjC,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,GAAE,cAAmB,GAAG,OAAO,CAAC,cAAc,CAAC;IAW9D,qFAAqF;IACrF,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAInD,yFAAyF;IACzF,gBAAgB,CAAC,MAAM,GAAE,sBAA2B,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAMpF,4FAA4F;IAC5F,YAAY,CAAC,KAAK,GAAE,cAAmB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAOnE,kGAAkG;IAClG,cAAc,CAAC,KAAK,GAAE,cAAmB,GAAG,OAAO,CAAC,cAAc,CAAC;IASnE,gFAAgF;IAChF,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC;IAI5E,qGAAqG;IACrG,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC;CAO7F"}
@@ -0,0 +1,141 @@
1
+ import { resolveApiBase } from './api-base.js';
2
+ /** Thrown on a non-2xx governance response, carrying the HTTP status for the UI to branch on. */
3
+ export class AgentApiError extends Error {
4
+ status;
5
+ constructor(message, status) {
6
+ super(message);
7
+ this.status = status;
8
+ this.name = 'AgentApiError';
9
+ }
10
+ }
11
+ /**
12
+ * A framework-free browser client for the `@adonis-agora/agent` provider's READ surface: the five
13
+ * `/agent/governance/*` rollups plus the per-actor `quota/today`. Same-origin, `credentials:
14
+ * 'same-origin'` so the host's actor/auth cookie gates every call exactly as it gates the routes
15
+ * server-side. No third-party HTTP dependency.
16
+ */
17
+ export class AgentClient {
18
+ base;
19
+ doFetch;
20
+ limit;
21
+ constructor(options = {}) {
22
+ this.base = (options.baseUrl ?? resolveApiBase()).replace(/\/+$/, '');
23
+ this.doFetch = options.fetch ?? globalThis.fetch.bind(globalThis);
24
+ this.limit = options.limit ?? 50;
25
+ }
26
+ async get(path, query = {}) {
27
+ const search = new URLSearchParams(query).toString();
28
+ const url = `${this.base}${path}${search ? `?${search}` : ''}`;
29
+ const response = await this.doFetch(url, {
30
+ method: 'GET',
31
+ headers: { accept: 'application/json' },
32
+ credentials: 'same-origin',
33
+ });
34
+ if (!response.ok) {
35
+ throw new AgentApiError(`GET ${path} failed (${response.status})`, response.status);
36
+ }
37
+ return (await response.json());
38
+ }
39
+ async post(path, body) {
40
+ const response = await this.doFetch(`${this.base}${path}`, {
41
+ method: 'POST',
42
+ headers: { accept: 'application/json', 'content-type': 'application/json' },
43
+ credentials: 'same-origin',
44
+ body: JSON.stringify(body),
45
+ });
46
+ if (!response.ok) {
47
+ throw new AgentApiError(`POST ${path} failed (${response.status})`, response.status);
48
+ }
49
+ return (await response.json());
50
+ }
51
+ spendByModel(range) {
52
+ return this.get('/governance/spend/model', {
53
+ from: range.fromDay,
54
+ to: range.toDay,
55
+ });
56
+ }
57
+ spendByActor(range) {
58
+ return this.get('/governance/spend/actor', {
59
+ from: range.fromDay,
60
+ to: range.toDay,
61
+ });
62
+ }
63
+ usageTrend(range) {
64
+ return this.get('/governance/usage/trend', {
65
+ from: range.fromDay,
66
+ to: range.toDay,
67
+ });
68
+ }
69
+ recentToolCalls(limit = this.limit) {
70
+ return this.get('/governance/tool-calls/recent', {
71
+ limit: String(limit),
72
+ });
73
+ }
74
+ recentThreads(limit = this.limit) {
75
+ return this.get('/governance/threads/recent', { limit: String(limit) });
76
+ }
77
+ quotaToday() {
78
+ return this.get('/quota/today');
79
+ }
80
+ // ── Run lifecycle governance (the run-tracking read-model). ─────────────────
81
+ /** `GET /agent/governance/runs` — filterable, cursor-paginated run list, newest-first. */
82
+ listRuns(filter = {}) {
83
+ const query = { limit: String(filter.limit ?? this.limit) };
84
+ if (filter.actor)
85
+ query.actor = filter.actor;
86
+ if (filter.agent)
87
+ query.agent = filter.agent;
88
+ if (filter.status)
89
+ query.status = filter.status;
90
+ if (filter.from)
91
+ query.from = filter.from;
92
+ if (filter.to)
93
+ query.to = filter.to;
94
+ if (filter.cursor)
95
+ query.cursor = filter.cursor;
96
+ return this.get('/governance/runs', query);
97
+ }
98
+ /** `GET /agent/governance/runs/:id` — one run's full trace, or `null` if unknown. */
99
+ runDetail(runId) {
100
+ return this.get(`/governance/runs/${encodeURIComponent(runId)}`);
101
+ }
102
+ /** `GET /agent/governance/approvals/pending` — cross-thread HITL inbox, oldest first. */
103
+ pendingApprovals(filter = {}) {
104
+ const query = { limit: String(filter.limit ?? this.limit) };
105
+ if (filter.actor)
106
+ query.actor = filter.actor;
107
+ return this.get('/governance/approvals/pending', query);
108
+ }
109
+ /** `GET /agent/governance/tools/stats` — per-tool call/failure/rejection/latency rollup. */
110
+ perToolStats(range = {}) {
111
+ const query = {};
112
+ if (range.from)
113
+ query.from = range.from;
114
+ if (range.to)
115
+ query.to = range.to;
116
+ return this.get('/governance/tools/stats', query);
117
+ }
118
+ /** `GET /agent/governance/reliability` — success/failure/cancel rates + mean settled duration. */
119
+ runReliability(range = {}) {
120
+ const query = {};
121
+ if (range.from)
122
+ query.from = range.from;
123
+ if (range.to)
124
+ query.to = range.to;
125
+ return this.get('/governance/reliability', query);
126
+ }
127
+ // ── HITL decisions — the EXISTING mutating routes the approvals inbox wires to. ──
128
+ /** `POST /agent/tool-call/approve` — release a `pending_approval` tool call. */
129
+ approveToolCall(runId, toolCallId) {
130
+ return this.post('/tool-call/approve', { runId, toolCallId });
131
+ }
132
+ /** `POST /agent/tool-call/reject` — deny a `pending_approval` tool call, with an optional reason. */
133
+ rejectToolCall(runId, toolCallId, reason) {
134
+ return this.post('/tool-call/reject', {
135
+ runId,
136
+ toolCallId,
137
+ ...(reason ? { reason } : {}),
138
+ });
139
+ }
140
+ }
141
+ //# sourceMappingURL=agent-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-client.js","sourceRoot":"","sources":["../../../src/client/agent-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Resolve the base URL of the agent routes the SPA calls. The provider injects the exact base it
3
+ * mounted the agent under as `window.__AGENT_DASHBOARD_BASE__` when it serves `index.html`; when that
4
+ * is absent (e.g. the standalone `vite dev` preview) we derive it from the page's own location by
5
+ * stripping the trailing `/dashboard` mount segment. Either way the SPA never hard-codes `/agent`.
6
+ */
7
+ declare global {
8
+ interface Window {
9
+ __AGENT_DASHBOARD_BASE__?: string;
10
+ }
11
+ }
12
+ /**
13
+ * Derive the agent API base from the dashboard's own `pathname`. The dashboard is mounted at
14
+ * `<agentBase>/dashboard`, so we drop that last segment: `/agent/dashboard` → `/agent`,
15
+ * `/api/agent/dashboard/` → `/api/agent`. A pathname that does not end in `/dashboard` is returned
16
+ * cleaned (trailing slash removed) as a best-effort base.
17
+ */
18
+ export declare function deriveApiBase(pathname: string): string;
19
+ /** The resolved agent API base for this page (injected value wins, else location-derived). */
20
+ export declare function resolveApiBase(win?: Pick<Window, 'location'> & {
21
+ __AGENT_DASHBOARD_BASE__?: string;
22
+ }): string;
23
+ //# sourceMappingURL=api-base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-base.d.ts","sourceRoot":"","sources":["../../../src/client/api-base.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,wBAAwB,CAAC,EAAE,MAAM,CAAC;KACnC;CACF;AAOD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOtD;AAED,8FAA8F;AAC9F,wBAAgB,cAAc,CAC5B,GAAG,GAAE,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG;IAAE,wBAAwB,CAAC,EAAE,MAAM,CAAA;CAAW,GAC7E,MAAM,CAIR"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Resolve the base URL of the agent routes the SPA calls. The provider injects the exact base it
3
+ * mounted the agent under as `window.__AGENT_DASHBOARD_BASE__` when it serves `index.html`; when that
4
+ * is absent (e.g. the standalone `vite dev` preview) we derive it from the page's own location by
5
+ * stripping the trailing `/dashboard` mount segment. Either way the SPA never hard-codes `/agent`.
6
+ */
7
+ /** Strip a trailing `/` (but never reduce `/` itself to `''`). */
8
+ function stripTrailingSlash(path) {
9
+ return path.length > 1 ? path.replace(/\/+$/, '') : path;
10
+ }
11
+ /**
12
+ * Derive the agent API base from the dashboard's own `pathname`. The dashboard is mounted at
13
+ * `<agentBase>/dashboard`, so we drop that last segment: `/agent/dashboard` → `/agent`,
14
+ * `/api/agent/dashboard/` → `/api/agent`. A pathname that does not end in `/dashboard` is returned
15
+ * cleaned (trailing slash removed) as a best-effort base.
16
+ */
17
+ export function deriveApiBase(pathname) {
18
+ const clean = stripTrailingSlash(pathname);
19
+ if (clean.endsWith('/dashboard')) {
20
+ const base = clean.slice(0, -'/dashboard'.length);
21
+ return base === '' ? '/' : base;
22
+ }
23
+ return clean === '' ? '/' : clean;
24
+ }
25
+ /** The resolved agent API base for this page (injected value wins, else location-derived). */
26
+ export function resolveApiBase(win = window) {
27
+ const injected = win.__AGENT_DASHBOARD_BASE__;
28
+ if (typeof injected === 'string' && injected !== '')
29
+ return stripTrailingSlash(injected);
30
+ return deriveApiBase(win.location.pathname);
31
+ }
32
+ //# sourceMappingURL=api-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-base.js","sourceRoot":"","sources":["../../../src/client/api-base.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,kEAAkE;AAClE,SAAS,kBAAkB,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,KAAK,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAClD,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AACpC,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,cAAc,CAC5B,MAAwE,MAAM;IAE9E,MAAM,QAAQ,GAAG,GAAG,CAAC,wBAAwB,CAAC;IAC9C,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,EAAE;QAAE,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACzF,OAAO,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { GovernanceRange } from './types.js';
2
+ /** `YYYY-MM-DD` for the UTC day `offsetDays` before `now` (negative → past). */
3
+ export declare function utcDay(now: Date, offsetDays?: number): string;
4
+ /** True for a well-formed `YYYY-MM-DD` calendar day. */
5
+ export declare function isIsoDay(value: string): boolean;
6
+ /** The default range: the trailing `days` UTC days ending today (inclusive), default 7. */
7
+ export declare function defaultRange(now?: Date, days?: number): GovernanceRange;
8
+ /** Coerce a possibly-invalid range into a valid one, falling back to {@link defaultRange}. */
9
+ export declare function normalizeRange(range: Partial<GovernanceRange>, now?: Date): GovernanceRange;
10
+ //# sourceMappingURL=default-range.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-range.d.ts","sourceRoot":"","sources":["../../../src/client/default-range.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,gFAAgF;AAChF,wBAAgB,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,SAAI,GAAG,MAAM,CAGxD;AAED,wDAAwD;AACxD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAI/C;AAED,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,GAAG,GAAE,IAAiB,EAAE,IAAI,SAAI,GAAG,eAAe,CAG9E;AAED,8FAA8F;AAC9F,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,EAC/B,GAAG,GAAE,IAAiB,GACrB,eAAe,CAMjB"}
@@ -0,0 +1,26 @@
1
+ /** `YYYY-MM-DD` for the UTC day `offsetDays` before `now` (negative → past). */
2
+ export function utcDay(now, offsetDays = 0) {
3
+ const d = new Date(now.getTime() + offsetDays * 86_400_000);
4
+ return d.toISOString().slice(0, 10);
5
+ }
6
+ /** True for a well-formed `YYYY-MM-DD` calendar day. */
7
+ export function isIsoDay(value) {
8
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value))
9
+ return false;
10
+ const time = Date.parse(`${value}T00:00:00.000Z`);
11
+ return !Number.isNaN(time) && value === new Date(time).toISOString().slice(0, 10);
12
+ }
13
+ /** The default range: the trailing `days` UTC days ending today (inclusive), default 7. */
14
+ export function defaultRange(now = new Date(), days = 7) {
15
+ const span = Math.max(1, Math.floor(days));
16
+ return { fromDay: utcDay(now, -(span - 1)), toDay: utcDay(now, 0) };
17
+ }
18
+ /** Coerce a possibly-invalid range into a valid one, falling back to {@link defaultRange}. */
19
+ export function normalizeRange(range, now = new Date()) {
20
+ const fallback = defaultRange(now);
21
+ const fromDay = range.fromDay && isIsoDay(range.fromDay) ? range.fromDay : fallback.fromDay;
22
+ const toDay = range.toDay && isIsoDay(range.toDay) ? range.toDay : fallback.toDay;
23
+ // Guard an inverted range (from after to) by swapping.
24
+ return fromDay <= toDay ? { fromDay, toDay } : { fromDay: toDay, toDay: fromDay };
25
+ }
26
+ //# sourceMappingURL=default-range.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-range.js","sourceRoot":"","sources":["../../../src/client/default-range.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,MAAM,UAAU,MAAM,CAAC,GAAS,EAAE,UAAU,GAAG,CAAC;IAC9C,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,UAAU,GAAG,UAAU,CAAC,CAAC;IAC5D,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,gBAAgB,CAAC,CAAC;IAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACpF,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,YAAY,CAAC,MAAY,IAAI,IAAI,EAAE,EAAE,IAAI,GAAG,CAAC;IAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;AACtE,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,cAAc,CAC5B,KAA+B,EAC/B,MAAY,IAAI,IAAI,EAAE;IAEtB,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;IAC5F,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;IAClF,uDAAuD;IACvD,OAAO,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACpF,CAAC"}
@@ -0,0 +1,22 @@
1
+ /** Compact number / currency / model-label formatting for the console. All pure; unit-tested. */
2
+ /** Format a USD amount. Small amounts keep precision; large ones read as `$1.20k` / `$3.40M`. */
3
+ export declare function formatUsd(amount: number): string;
4
+ /** Format a token/count with compact suffixes (`1.2k`, `3.4M`, `1.1B`). */
5
+ export declare function formatCount(value: number): string;
6
+ /** Format a 0..1 ratio as an integer percent (`0.1234` -> `12%`). */
7
+ export declare function formatPercent(ratio: number): string;
8
+ /**
9
+ * Format a millisecond duration compactly (`820ms`, `3.4s`, `2.1m`, `1.3h`). `null`/`undefined`/
10
+ * non-finite → `—` (used for still-running runs and tools that never recorded a latency).
11
+ */
12
+ export declare function formatDuration(ms: number | null | undefined): string;
13
+ /**
14
+ * Shorten a raw model id for display. Bedrock inference-profile ARNs
15
+ * (`arn:aws:bedrock:…:inference-profile/<region>.<provider>.<model>`) overflow cards, so we keep the
16
+ * distinguishing `<model>` and drop the ARN prefix plus the region/provider qualifiers. Non-ARN ids
17
+ * (e.g. `gpt-4o`) pass through unchanged; the full id is surfaced via a `title` tooltip at call sites.
18
+ */
19
+ export declare function formatModelLabel(modelId: string): string;
20
+ /** Format an ISO timestamp as a short, locale-stable `MMM D, HH:MM` label; `''`/invalid → `—`. */
21
+ export declare function formatTimestamp(iso: string): string;
22
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/client/format.ts"],"names":[],"mappings":"AAAA,iGAAiG;AAEjG,iGAAiG;AACjG,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAQpE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED,kGAAkG;AAClG,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CASnD"}
@@ -0,0 +1,76 @@
1
+ /** Compact number / currency / model-label formatting for the console. All pure; unit-tested. */
2
+ /** Format a USD amount. Small amounts keep precision; large ones read as `$1.20k` / `$3.40M`. */
3
+ export function formatUsd(amount) {
4
+ if (!Number.isFinite(amount))
5
+ return '$0.00';
6
+ const abs = Math.abs(amount);
7
+ if (abs >= 1_000_000)
8
+ return `$${(amount / 1_000_000).toFixed(2)}M`;
9
+ if (abs >= 1_000)
10
+ return `$${(amount / 1_000).toFixed(2)}k`;
11
+ if (abs > 0 && abs < 0.01)
12
+ return '<$0.01';
13
+ return `$${amount.toFixed(2)}`;
14
+ }
15
+ /** Format a token/count with compact suffixes (`1.2k`, `3.4M`, `1.1B`). */
16
+ export function formatCount(value) {
17
+ if (!Number.isFinite(value))
18
+ return '0';
19
+ const abs = Math.abs(value);
20
+ if (abs >= 1_000_000_000)
21
+ return `${(value / 1_000_000_000).toFixed(1)}B`;
22
+ if (abs >= 1_000_000)
23
+ return `${(value / 1_000_000).toFixed(1)}M`;
24
+ if (abs >= 1_000)
25
+ return `${(value / 1_000).toFixed(1)}k`;
26
+ return `${Math.round(value)}`;
27
+ }
28
+ /** Format a 0..1 ratio as an integer percent (`0.1234` -> `12%`). */
29
+ export function formatPercent(ratio) {
30
+ if (!Number.isFinite(ratio))
31
+ return '0%';
32
+ return `${Math.round(ratio * 100)}%`;
33
+ }
34
+ /**
35
+ * Format a millisecond duration compactly (`820ms`, `3.4s`, `2.1m`, `1.3h`). `null`/`undefined`/
36
+ * non-finite → `—` (used for still-running runs and tools that never recorded a latency).
37
+ */
38
+ export function formatDuration(ms) {
39
+ if (ms === null || ms === undefined || !Number.isFinite(ms))
40
+ return '—';
41
+ if (ms < 1000)
42
+ return `${Math.round(ms)}ms`;
43
+ const seconds = ms / 1000;
44
+ if (seconds < 60)
45
+ return `${seconds.toFixed(1)}s`;
46
+ const minutes = seconds / 60;
47
+ if (minutes < 60)
48
+ return `${minutes.toFixed(1)}m`;
49
+ return `${(minutes / 60).toFixed(1)}h`;
50
+ }
51
+ /**
52
+ * Shorten a raw model id for display. Bedrock inference-profile ARNs
53
+ * (`arn:aws:bedrock:…:inference-profile/<region>.<provider>.<model>`) overflow cards, so we keep the
54
+ * distinguishing `<model>` and drop the ARN prefix plus the region/provider qualifiers. Non-ARN ids
55
+ * (e.g. `gpt-4o`) pass through unchanged; the full id is surfaced via a `title` tooltip at call sites.
56
+ */
57
+ export function formatModelLabel(modelId) {
58
+ if (!modelId.includes('/'))
59
+ return modelId;
60
+ const profile = modelId.slice(modelId.lastIndexOf('/') + 1);
61
+ return profile.replace(/^[a-z]{2}[a-z-]*\.[a-z0-9]+\./, '');
62
+ }
63
+ /** Format an ISO timestamp as a short, locale-stable `MMM D, HH:MM` label; `''`/invalid → `—`. */
64
+ export function formatTimestamp(iso) {
65
+ if (iso === '')
66
+ return '—';
67
+ const date = new Date(iso);
68
+ if (Number.isNaN(date.getTime()))
69
+ return '—';
70
+ const month = date.toLocaleString('en-US', { month: 'short', timeZone: 'UTC' });
71
+ const day = date.getUTCDate();
72
+ const hh = String(date.getUTCHours()).padStart(2, '0');
73
+ const mm = String(date.getUTCMinutes()).padStart(2, '0');
74
+ return `${month} ${day}, ${hh}:${mm}`;
75
+ }
76
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/client/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export * from './types.js';
2
+ export * from './format.js';
3
+ export * from './default-range.js';
4
+ export * from './spend-summary.js';
5
+ export * from './trend-path.js';
6
+ export * from './api-base.js';
7
+ export { AgentClient, AgentApiError } from './agent-client.js';
8
+ export type { AgentClientOptions } from './agent-client.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export * from './types.js';
2
+ export * from './format.js';
3
+ export * from './default-range.js';
4
+ export * from './spend-summary.js';
5
+ export * from './trend-path.js';
6
+ export * from './api-base.js';
7
+ export { AgentClient, AgentApiError } from './agent-client.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,43 @@
1
+ import type { ActorSpendRow, ModelSpendRow } from './types.js';
2
+ /** Headline totals for a range, summed across every model row. */
3
+ export interface SpendTotals {
4
+ costUsd: number;
5
+ inputTokens: number;
6
+ outputTokens: number;
7
+ totalTokens: number;
8
+ requests: number;
9
+ }
10
+ /** A model row enriched with its share (0..1) of total cost — for share bars / donut segments. */
11
+ export interface ModelSpendShare extends ModelSpendRow {
12
+ totalTokens: number;
13
+ /** Fraction of total cost (0..1); falls back to token share when nothing is priced. */
14
+ costShare: number;
15
+ }
16
+ /** One donut arc segment: a normalized 0..1 slice with its cumulative offset (also 0..1). */
17
+ export interface DonutSegment {
18
+ key: string;
19
+ value: number;
20
+ fraction: number;
21
+ offset: number;
22
+ }
23
+ /** Sum the by-model rows into the headline totals. */
24
+ export declare function summarizeSpend(rows: ModelSpendRow[]): SpendTotals;
25
+ /**
26
+ * Enrich each model row with its cost share, sorted by cost descending. When nothing has a cost
27
+ * (every model unpriced) the share falls back to token share so bars/donut still convey the usage
28
+ * mix instead of collapsing to zero.
29
+ */
30
+ export declare function withShares(rows: ModelSpendRow[]): ModelSpendShare[];
31
+ /**
32
+ * Build donut segments from the shared rows: each `fraction` is the row's `costShare` and `offset`
33
+ * is the running cumulative fraction (so an SVG can lay arcs end-to-end). Zero-share rows are dropped
34
+ * so the donut has no invisible slices.
35
+ */
36
+ export declare function donutSegments(rows: ModelSpendShare[]): DonutSegment[];
37
+ /** Total spend + tokens across the by-actor rows (headline for the actor panel). */
38
+ export declare function summarizeActors(rows: ActorSpendRow[]): {
39
+ costUsd: number;
40
+ totalTokens: number;
41
+ requests: number;
42
+ };
43
+ //# sourceMappingURL=spend-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spend-summary.d.ts","sourceRoot":"","sources":["../../../src/client/spend-summary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,kGAAkG;AAClG,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,uFAAuF;IACvF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,6FAA6F;AAC7F,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,WAAW,CAgBjE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,eAAe,EAAE,CAWnE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,YAAY,EAAE,CASrE;AAED,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CASA"}
@@ -0,0 +1,59 @@
1
+ /** Sum the by-model rows into the headline totals. */
2
+ export function summarizeSpend(rows) {
3
+ const totals = {
4
+ costUsd: 0,
5
+ inputTokens: 0,
6
+ outputTokens: 0,
7
+ totalTokens: 0,
8
+ requests: 0,
9
+ };
10
+ for (const row of rows) {
11
+ totals.costUsd += row.costUsd;
12
+ totals.inputTokens += row.inputTokens;
13
+ totals.outputTokens += row.outputTokens;
14
+ totals.requests += row.requests;
15
+ }
16
+ totals.totalTokens = totals.inputTokens + totals.outputTokens;
17
+ return totals;
18
+ }
19
+ /**
20
+ * Enrich each model row with its cost share, sorted by cost descending. When nothing has a cost
21
+ * (every model unpriced) the share falls back to token share so bars/donut still convey the usage
22
+ * mix instead of collapsing to zero.
23
+ */
24
+ export function withShares(rows) {
25
+ const totalCost = rows.reduce((sum, row) => sum + row.costUsd, 0);
26
+ const totalTokens = rows.reduce((sum, row) => sum + row.inputTokens + row.outputTokens, 0);
27
+ return rows
28
+ .map((row) => {
29
+ const rowTokens = row.inputTokens + row.outputTokens;
30
+ const costShare = totalCost > 0 ? row.costUsd / totalCost : totalTokens > 0 ? rowTokens / totalTokens : 0;
31
+ return { ...row, totalTokens: rowTokens, costShare };
32
+ })
33
+ .sort((a, b) => b.costUsd - a.costUsd || b.totalTokens - a.totalTokens);
34
+ }
35
+ /**
36
+ * Build donut segments from the shared rows: each `fraction` is the row's `costShare` and `offset`
37
+ * is the running cumulative fraction (so an SVG can lay arcs end-to-end). Zero-share rows are dropped
38
+ * so the donut has no invisible slices.
39
+ */
40
+ export function donutSegments(rows) {
41
+ const segments = [];
42
+ let offset = 0;
43
+ for (const row of rows) {
44
+ if (row.costShare <= 0)
45
+ continue;
46
+ segments.push({ key: row.modelId, value: row.costUsd, fraction: row.costShare, offset });
47
+ offset += row.costShare;
48
+ }
49
+ return segments;
50
+ }
51
+ /** Total spend + tokens across the by-actor rows (headline for the actor panel). */
52
+ export function summarizeActors(rows) {
53
+ return rows.reduce((acc, row) => ({
54
+ costUsd: acc.costUsd + row.costUsd,
55
+ totalTokens: acc.totalTokens + row.totalTokens,
56
+ requests: acc.requests + row.requests,
57
+ }), { costUsd: 0, totalTokens: 0, requests: 0 });
58
+ }
59
+ //# sourceMappingURL=spend-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spend-summary.js","sourceRoot":"","sources":["../../../src/client/spend-summary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { UsageTrendPoint } from './types.js';
2
+ /** Which series a trend chart plots. */
3
+ export type TrendMetric = 'costUsd' | 'totalTokens';
4
+ /** A plotted point in SVG user space. */
5
+ export interface TrendVertex {
6
+ day: string;
7
+ value: number;
8
+ x: number;
9
+ y: number;
10
+ }
11
+ /** Everything an SVG needs to draw a normalized area/line trend inside `width`x`height`. */
12
+ export interface TrendGeometry {
13
+ /** `M..L..` polyline through every vertex (empty when there is nothing to plot). */
14
+ line: string;
15
+ /** Closed area path (line + baseline) for a filled gradient; empty when nothing to plot. */
16
+ area: string;
17
+ vertices: TrendVertex[];
18
+ /** Series max used to normalize the y-axis (floored to 1 so a flat/empty series still draws). */
19
+ max: number;
20
+ }
21
+ /**
22
+ * Project a daily trend series into SVG geometry. The x-axis spreads points evenly across `width`;
23
+ * the y-axis is normalized against the series max (inverted, since SVG y grows downward). A single
24
+ * point renders centered; an empty series yields empty paths and `max: 1`. Pure — no DOM.
25
+ */
26
+ export declare function buildTrendGeometry(points: UsageTrendPoint[], metric: TrendMetric, width: number, height: number): TrendGeometry;
27
+ //# sourceMappingURL=trend-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trend-path.d.ts","sourceRoot":"","sources":["../../../src/client/trend-path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wCAAwC;AACxC,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,aAAa,CAAC;AAEpD,yCAAyC;AACzC,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,4FAA4F;AAC5F,MAAM,WAAW,aAAa;IAC5B,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;IACb,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,iGAAiG;IACjG,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,eAAe,EAAE,EACzB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,aAAa,CAsBf"}