@spendgraph/sdk 0.1.0 → 0.2.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 (62) hide show
  1. package/dist/client.d.ts +37 -0
  2. package/dist/client.js +48 -0
  3. package/dist/core/client/client.d.ts +30 -0
  4. package/dist/core/client/client.js +143 -0
  5. package/dist/core/client/errors.d.ts +25 -0
  6. package/dist/core/client/errors.js +31 -0
  7. package/dist/core/client/index.d.ts +2 -0
  8. package/dist/core/client/index.js +2 -0
  9. package/dist/core/types.d.ts +28 -0
  10. package/dist/core/types.js +1 -0
  11. package/dist/index.d.ts +9 -124
  12. package/dist/index.js +5 -421
  13. package/dist/langchain.js +8 -2
  14. package/dist/resources/alerts.d.ts +18 -0
  15. package/dist/resources/alerts.js +10 -0
  16. package/dist/resources/credentials.d.ts +22 -0
  17. package/dist/resources/credentials.js +22 -0
  18. package/dist/resources/events.d.ts +41 -0
  19. package/dist/resources/events.js +20 -0
  20. package/dist/resources/index.d.ts +21 -0
  21. package/dist/resources/index.js +12 -0
  22. package/dist/resources/ingest.d.ts +42 -0
  23. package/dist/resources/ingest.js +30 -0
  24. package/dist/resources/keys.d.ts +34 -0
  25. package/dist/resources/keys.js +20 -0
  26. package/dist/resources/playground.d.ts +7 -0
  27. package/dist/resources/playground.js +10 -0
  28. package/dist/resources/pricing.d.ts +49 -0
  29. package/dist/resources/pricing.js +42 -0
  30. package/dist/resources/projects.d.ts +54 -0
  31. package/dist/resources/projects.js +51 -0
  32. package/dist/resources/prompts-admin.d.ts +23 -0
  33. package/dist/resources/prompts-admin.js +26 -0
  34. package/dist/resources/prompts.d.ts +124 -0
  35. package/dist/resources/prompts.js +67 -0
  36. package/dist/resources/stats.d.ts +65 -0
  37. package/dist/resources/stats.js +29 -0
  38. package/dist/resources/tools.d.ts +66 -0
  39. package/dist/resources/tools.js +30 -0
  40. package/dist/rollout/index.d.ts +1 -0
  41. package/dist/rollout/index.js +1 -0
  42. package/dist/rollout/rollout.d.ts +75 -0
  43. package/dist/rollout/rollout.js +1 -0
  44. package/dist/schema/index.d.ts +3 -0
  45. package/dist/schema/index.js +2 -0
  46. package/dist/schema/serialize/index.d.ts +1 -0
  47. package/dist/schema/serialize/index.js +1 -0
  48. package/dist/schema/serialize/serialize.d.ts +12 -0
  49. package/dist/schema/serialize/serialize.js +42 -0
  50. package/dist/schema/types/index.d.ts +1 -0
  51. package/dist/schema/types/index.js +1 -0
  52. package/dist/schema/types/types.d.ts +58 -0
  53. package/dist/schema/types/types.js +1 -0
  54. package/dist/schema/validate/index.d.ts +1 -0
  55. package/dist/schema/validate/index.js +1 -0
  56. package/dist/schema/validate/validate.d.ts +28 -0
  57. package/dist/schema/validate/validate.js +108 -0
  58. package/dist/track/index.d.ts +2 -0
  59. package/dist/track/index.js +1 -0
  60. package/dist/track/track.d.ts +209 -0
  61. package/dist/track/track.js +513 -0
  62. package/package.json +3 -2
@@ -0,0 +1,30 @@
1
+ /** The route takes up to this many events per request. */
2
+ export const MAX_EVENTS = 100;
3
+ /** Posts usage straight through, chunked to what the route accepts. */
4
+ export class Ingest {
5
+ client;
6
+ project;
7
+ constructor(client, project) {
8
+ this.client = client;
9
+ this.project = project;
10
+ }
11
+ async send(events) {
12
+ await this.report(events);
13
+ }
14
+ /** The same write, with the server's answer — which ids went unpriced. */
15
+ async report(events) {
16
+ const total = { accepted: 0, rejected: 0, unpricedModels: [] };
17
+ if (events.length === 0)
18
+ return total;
19
+ const unpriced = new Set();
20
+ for (let i = 0; i < events.length; i += MAX_EVENTS) {
21
+ const res = await this.client.post("/api/v1/ingest", { events: events.slice(i, i + MAX_EVENTS) }, { project: this.project });
22
+ total.accepted += res?.accepted ?? 0;
23
+ total.rejected += res?.rejected ?? 0;
24
+ for (const model of res?.unpricedModels ?? [])
25
+ unpriced.add(model);
26
+ }
27
+ total.unpricedModels = [...unpriced];
28
+ return total;
29
+ }
30
+ }
@@ -0,0 +1,34 @@
1
+ import type { Client } from "../core/client/index.js";
2
+ export interface ApiKeyRow {
3
+ id: string;
4
+ name: string;
5
+ projectId: string;
6
+ createdAt: string;
7
+ lastUsedAt: string | null;
8
+ revokedAt: string | null;
9
+ }
10
+ /**
11
+ * API keys. Dashboard session only, deliberately: a key that could mint keys
12
+ * would turn one leaked ingest credential into permanent access.
13
+ */
14
+ export declare class Keys {
15
+ private readonly client;
16
+ constructor(client: Client);
17
+ list(query?: {
18
+ project?: string;
19
+ }): Promise<{
20
+ keys: ApiKeyRow[];
21
+ }>;
22
+ /** The plaintext key is in this response and nowhere else, ever again. */
23
+ create(body: {
24
+ projectId: string;
25
+ name: string;
26
+ }): Promise<{
27
+ key: ApiKeyRow & {
28
+ plaintext: string;
29
+ };
30
+ }>;
31
+ revoke(keyId: string): Promise<{
32
+ revoked: boolean;
33
+ }>;
34
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * API keys. Dashboard session only, deliberately: a key that could mint keys
3
+ * would turn one leaked ingest credential into permanent access.
4
+ */
5
+ export class Keys {
6
+ client;
7
+ constructor(client) {
8
+ this.client = client;
9
+ }
10
+ list(query = {}) {
11
+ return this.client.get("/api/v1/keys", { ...query });
12
+ }
13
+ /** The plaintext key is in this response and nowhere else, ever again. */
14
+ create(body) {
15
+ return this.client.post("/api/v1/keys", body);
16
+ }
17
+ revoke(keyId) {
18
+ return this.client.delete(`/api/v1/keys/${encodeURIComponent(keyId)}`);
19
+ }
20
+ }
@@ -0,0 +1,7 @@
1
+ import type { Client } from "../core/client/index.js";
2
+ /** Ad-hoc runs from the dashboard, streamed. Dashboard session only. */
3
+ export declare class Playground {
4
+ private readonly client;
5
+ constructor(client: Client);
6
+ run(body: Record<string, unknown>): Promise<Record<string, unknown>>;
7
+ }
@@ -0,0 +1,10 @@
1
+ /** Ad-hoc runs from the dashboard, streamed. Dashboard session only. */
2
+ export class Playground {
3
+ client;
4
+ constructor(client) {
5
+ this.client = client;
6
+ }
7
+ run(body) {
8
+ return this.client.post("/api/v1/playground/run", body);
9
+ }
10
+ }
@@ -0,0 +1,49 @@
1
+ import type { Client } from "../core/client/index.js";
2
+ export interface PricingRow {
3
+ model: string;
4
+ provider: string;
5
+ inputPerMtokMicros: number;
6
+ outputPerMtokMicros: number;
7
+ cacheReadPerMtokMicros: number | null;
8
+ cacheWritePerMtokMicros: number | null;
9
+ /** Flat charge per call — Perplexity bills one for the search behind Sonar. */
10
+ perRequestMicros: number | null;
11
+ }
12
+ /** The pricing catalogue. Dashboard session only. */
13
+ export declare class Pricing {
14
+ private readonly client;
15
+ constructor(client: Client);
16
+ list(): Promise<Record<string, unknown>>;
17
+ /** A manual override for one model, which outranks the synced rows. */
18
+ override(model: string, body: Record<string, unknown>): Promise<{
19
+ pricing: PricingRow;
20
+ }>;
21
+ /** Which models the catalogue can price, and which it cannot. */
22
+ coverage(): Promise<Record<string, unknown>>;
23
+ /** What legacy and offer-based pricing would each charge, side by side. */
24
+ readiness(): Promise<Record<string, unknown>>;
25
+ sync(body?: Record<string, unknown>): Promise<Record<string, unknown>>;
26
+ }
27
+ /** The model catalogue and the offers behind it. Dashboard session only. */
28
+ export declare class Models {
29
+ private readonly client;
30
+ constructor(client: Client);
31
+ list(query?: {
32
+ creator?: string;
33
+ limit?: number;
34
+ }): Promise<Record<string, unknown>>;
35
+ offers(query?: {
36
+ model?: string;
37
+ q?: string;
38
+ }): Promise<Record<string, unknown>>;
39
+ /** Prices one workload across models or serving providers. */
40
+ compare(query?: {
41
+ models?: string;
42
+ offers?: string;
43
+ baseline?: string;
44
+ benchmark?: string;
45
+ in?: number;
46
+ out?: number;
47
+ requests?: number;
48
+ }): Promise<Record<string, unknown>>;
49
+ }
@@ -0,0 +1,42 @@
1
+ /** The pricing catalogue. Dashboard session only. */
2
+ export class Pricing {
3
+ client;
4
+ constructor(client) {
5
+ this.client = client;
6
+ }
7
+ list() {
8
+ return this.client.get("/api/v1/pricing");
9
+ }
10
+ /** A manual override for one model, which outranks the synced rows. */
11
+ override(model, body) {
12
+ return this.client.put(`/api/v1/pricing/${encodeURIComponent(model)}`, body);
13
+ }
14
+ /** Which models the catalogue can price, and which it cannot. */
15
+ coverage() {
16
+ return this.client.get("/api/v1/pricing/coverage");
17
+ }
18
+ /** What legacy and offer-based pricing would each charge, side by side. */
19
+ readiness() {
20
+ return this.client.get("/api/v1/pricing/readiness");
21
+ }
22
+ sync(body = {}) {
23
+ return this.client.post("/api/v1/pricing/sync", body);
24
+ }
25
+ }
26
+ /** The model catalogue and the offers behind it. Dashboard session only. */
27
+ export class Models {
28
+ client;
29
+ constructor(client) {
30
+ this.client = client;
31
+ }
32
+ list(query = {}) {
33
+ return this.client.get("/api/v1/models", { ...query });
34
+ }
35
+ offers(query = {}) {
36
+ return this.client.get("/api/v1/offers", { ...query });
37
+ }
38
+ /** Prices one workload across models or serving providers. */
39
+ compare(query = {}) {
40
+ return this.client.get("/api/v1/compare", { ...query });
41
+ }
42
+ }
@@ -0,0 +1,54 @@
1
+ import type { Client } from "../core/client/index.js";
2
+ export interface ProjectRow {
3
+ id: string;
4
+ name: string;
5
+ createdAt: string;
6
+ }
7
+ export interface Budget {
8
+ monthlyLimitMicros: number | null;
9
+ alertThresholdPct: number | null;
10
+ }
11
+ /** Projects, their budgets, members and invites. Dashboard session only. */
12
+ export declare class Projects {
13
+ private readonly client;
14
+ constructor(client: Client);
15
+ list(): Promise<{
16
+ projects: ProjectRow[];
17
+ }>;
18
+ create(body: {
19
+ name: string;
20
+ }): Promise<{
21
+ project: ProjectRow;
22
+ }>;
23
+ budget(projectId: string): Promise<{
24
+ budget: Budget;
25
+ }>;
26
+ setBudget(projectId: string, body: Partial<Budget>): Promise<{
27
+ ok: boolean;
28
+ }>;
29
+ members(projectId: string): Promise<Record<string, unknown>>;
30
+ addMember(projectId: string, body: Record<string, unknown>): Promise<{
31
+ ok: boolean;
32
+ }>;
33
+ removeMember(projectId: string, userId: string): Promise<{
34
+ ok: boolean;
35
+ }>;
36
+ invite(projectId: string, body: Record<string, unknown>): Promise<{
37
+ ok: boolean;
38
+ added?: unknown;
39
+ }>;
40
+ revokeInvite(projectId: string, inviteId: string): Promise<{
41
+ ok: boolean;
42
+ }>;
43
+ }
44
+ /** Accepting an invite is the one project call that identifies a person, not a key. */
45
+ export declare class Invites {
46
+ private readonly client;
47
+ constructor(client: Client);
48
+ preview(token: string): Promise<{
49
+ project: ProjectRow;
50
+ }>;
51
+ accept(token: string): Promise<{
52
+ project: ProjectRow;
53
+ }>;
54
+ }
@@ -0,0 +1,51 @@
1
+ /** Projects, their budgets, members and invites. Dashboard session only. */
2
+ export class Projects {
3
+ client;
4
+ constructor(client) {
5
+ this.client = client;
6
+ }
7
+ list() {
8
+ return this.client.get("/api/v1/projects");
9
+ }
10
+ create(body) {
11
+ return this.client.post("/api/v1/projects", body);
12
+ }
13
+ budget(projectId) {
14
+ return this.client.get(`/api/v1/projects/${encodeURIComponent(projectId)}/budget`);
15
+ }
16
+ setBudget(projectId, body) {
17
+ return this.client.put(`/api/v1/projects/${encodeURIComponent(projectId)}/budget`, body);
18
+ }
19
+ members(projectId) {
20
+ return this.client.get(`/api/v1/projects/${encodeURIComponent(projectId)}/members`);
21
+ }
22
+ addMember(projectId, body) {
23
+ return this.client.post(`/api/v1/projects/${encodeURIComponent(projectId)}/members`, body);
24
+ }
25
+ removeMember(projectId, userId) {
26
+ return this.client.delete(`/api/v1/projects/${encodeURIComponent(projectId)}/members`, {
27
+ userId,
28
+ });
29
+ }
30
+ invite(projectId, body) {
31
+ return this.client.post(`/api/v1/projects/${encodeURIComponent(projectId)}/invites`, body);
32
+ }
33
+ revokeInvite(projectId, inviteId) {
34
+ return this.client.delete(`/api/v1/projects/${encodeURIComponent(projectId)}/invites`, {
35
+ inviteId,
36
+ });
37
+ }
38
+ }
39
+ /** Accepting an invite is the one project call that identifies a person, not a key. */
40
+ export class Invites {
41
+ client;
42
+ constructor(client) {
43
+ this.client = client;
44
+ }
45
+ preview(token) {
46
+ return this.client.get("/api/v1/invites/accept", { token });
47
+ }
48
+ accept(token) {
49
+ return this.client.post("/api/v1/invites/accept", { token });
50
+ }
51
+ }
@@ -0,0 +1,23 @@
1
+ import type { Client } from "../core/client/index.js";
2
+ import type { Scoped } from "./prompts.js";
3
+ /**
4
+ * The prompt operations gated on a dashboard session — publishing a version,
5
+ * archiving a prompt, starting an optimization run, and reading run history.
6
+ */
7
+ export declare class PromptsAdmin {
8
+ private readonly client;
9
+ constructor(client: Client);
10
+ publish(promptId: string, body?: Record<string, unknown>): Promise<Record<string, unknown>>;
11
+ archive(promptId: string, query?: Scoped): Promise<Record<string, unknown>>;
12
+ /** Starts an optimization run. The budget is required, never defaulted. */
13
+ assay(promptId: string, body: Record<string, unknown>): Promise<Record<string, unknown>>;
14
+ runs(query?: {
15
+ project?: string;
16
+ limit?: number;
17
+ }): Promise<{
18
+ runs: unknown[];
19
+ }>;
20
+ run(runId: string): Promise<{
21
+ run: unknown;
22
+ }>;
23
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The prompt operations gated on a dashboard session — publishing a version,
3
+ * archiving a prompt, starting an optimization run, and reading run history.
4
+ */
5
+ export class PromptsAdmin {
6
+ client;
7
+ constructor(client) {
8
+ this.client = client;
9
+ }
10
+ publish(promptId, body = {}) {
11
+ return this.client.post(`/api/v1/prompts/${encodeURIComponent(promptId)}/publish`, body);
12
+ }
13
+ archive(promptId, query = {}) {
14
+ return this.client.post(`/api/v1/prompts/${encodeURIComponent(promptId)}/archive`, {}, { ...query });
15
+ }
16
+ /** Starts an optimization run. The budget is required, never defaulted. */
17
+ assay(promptId, body) {
18
+ return this.client.post(`/api/v1/prompts/${encodeURIComponent(promptId)}/assay`, body);
19
+ }
20
+ runs(query = {}) {
21
+ return this.client.get("/api/v1/prompts/runs", { ...query });
22
+ }
23
+ run(runId) {
24
+ return this.client.get(`/api/v1/prompts/runs/${encodeURIComponent(runId)}`);
25
+ }
26
+ }
@@ -0,0 +1,124 @@
1
+ import type { Client } from "../core/client/index.js";
2
+ export type Role = "system" | "user" | "assistant";
3
+ export interface RenderedMessage {
4
+ role: Role;
5
+ content: string;
6
+ }
7
+ export interface PromptBlock {
8
+ title?: string;
9
+ body?: string;
10
+ }
11
+ export interface SavePromptInput {
12
+ projectId: string;
13
+ name: string;
14
+ blocks?: PromptBlock[];
15
+ variables?: Record<string, string>;
16
+ question?: string;
17
+ models?: string[];
18
+ temperature?: number;
19
+ maxTokens?: number;
20
+ }
21
+ export interface ReportRolloutInput {
22
+ /** Chosen by the caller so a retried report writes one row, not two. */
23
+ rolloutId: string;
24
+ versionId?: string | null;
25
+ model: string;
26
+ fields?: Record<string, string>;
27
+ rendered: RenderedMessage[];
28
+ output?: string;
29
+ status?: "completed" | "failed";
30
+ error?: string;
31
+ inputTokens?: number;
32
+ outputTokens?: number;
33
+ cacheReadTokens?: number;
34
+ cacheWriteTokens?: number;
35
+ citationTokens?: number;
36
+ reasoningTokens?: number;
37
+ latencyMs?: number;
38
+ caseId?: string;
39
+ /** Which repetition this is. pass^k needs it even when k is 1. */
40
+ seed?: number;
41
+ candidateId?: string;
42
+ parentId?: string;
43
+ generation?: number;
44
+ }
45
+ export interface RunPromptInput {
46
+ rolloutId: string;
47
+ [key: string]: unknown;
48
+ }
49
+ export interface DatasetCase {
50
+ caseId: string;
51
+ fieldValues?: Record<string, string>;
52
+ expected?: string | null;
53
+ split?: "feedback" | "held_out";
54
+ }
55
+ export interface Scoped {
56
+ project?: string;
57
+ }
58
+ /**
59
+ * Stored prompts, their versions, datasets and rollouts.
60
+ *
61
+ * This is the half of the API a job uses: every method here takes an API key.
62
+ * Publishing, archiving and optimizing are on the dashboard half — see
63
+ * `PromptsAdmin`.
64
+ */
65
+ export declare class Prompts {
66
+ private readonly client;
67
+ constructor(client: Client);
68
+ list(query?: Scoped & {
69
+ limit?: number;
70
+ cursor?: string;
71
+ archived?: boolean;
72
+ }): Promise<{
73
+ prompts: unknown[];
74
+ nextCursor?: string | null;
75
+ }>;
76
+ create(body: SavePromptInput): Promise<{
77
+ prompt: unknown;
78
+ }>;
79
+ /** One prompt with its current version. `runs` asks for its recent runs too. */
80
+ get<T = Record<string, unknown>>(promptId: string, query?: Scoped & {
81
+ runs?: number;
82
+ }): Promise<T>;
83
+ update(promptId: string, body: SavePromptInput, query?: Scoped): Promise<Record<string, unknown>>;
84
+ versions<T = Record<string, unknown>>(promptId: string, query?: Scoped & {
85
+ limit?: number;
86
+ origin?: string;
87
+ }): Promise<T>;
88
+ /** Promotes a stored version to current. Unchanged text is a no-op, not a fork. */
89
+ promote(promptId: string, versionId: string, query?: Scoped): Promise<{
90
+ promoted: string;
91
+ unchanged?: boolean;
92
+ }>;
93
+ cases<T = Record<string, unknown>>(promptId: string, query?: Scoped): Promise<T>;
94
+ /** Replaces the dataset. Splits are derived, so a case never moves between them. */
95
+ putCases<T = {
96
+ counts: unknown;
97
+ problem: unknown;
98
+ }>(promptId: string, cases: DatasetCase[], query?: Scoped): Promise<T>;
99
+ rollouts(promptId: string, query?: Scoped & {
100
+ limit?: number;
101
+ cursor?: string;
102
+ evaluation?: boolean;
103
+ }): Promise<Record<string, unknown>>;
104
+ /**
105
+ * Records a rollout the caller ran itself. Dedupes on `rolloutId`.
106
+ *
107
+ * `priced` is false where no pricing row covered the model. The stored cost
108
+ * is zero either way — the column is `notNull` — so this flag is the only
109
+ * thing telling a free call apart from an unpriced one.
110
+ */
111
+ report(promptId: string, body: ReportRolloutInput, query?: Scoped): Promise<{
112
+ rollout: unknown;
113
+ deduped?: boolean;
114
+ priced?: boolean;
115
+ }>;
116
+ /** Runs the prompt server-side, where the spec, rendering and pricing already live. */
117
+ run<T = {
118
+ rollout: unknown;
119
+ recorded?: boolean;
120
+ note?: string | null;
121
+ deduped?: boolean;
122
+ priced?: boolean;
123
+ }>(promptId: string, body: RunPromptInput, query?: Scoped): Promise<T>;
124
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Stored prompts, their versions, datasets and rollouts.
3
+ *
4
+ * This is the half of the API a job uses: every method here takes an API key.
5
+ * Publishing, archiving and optimizing are on the dashboard half — see
6
+ * `PromptsAdmin`.
7
+ */
8
+ export class Prompts {
9
+ client;
10
+ constructor(client) {
11
+ this.client = client;
12
+ }
13
+ list(query = {}) {
14
+ return this.client.get("/api/v1/prompts", { ...query });
15
+ }
16
+ create(body) {
17
+ return this.client.post("/api/v1/prompts", body);
18
+ }
19
+ /** One prompt with its current version. `runs` asks for its recent runs too. */
20
+ get(promptId, query = {}) {
21
+ return this.client.get(`/api/v1/prompts/${encodeURIComponent(promptId)}`, { ...query });
22
+ }
23
+ update(promptId, body, query = {}) {
24
+ return this.client.put(`/api/v1/prompts/${encodeURIComponent(promptId)}`, body, { ...query });
25
+ }
26
+ versions(promptId, query = {}) {
27
+ return this.client.get(`/api/v1/prompts/${encodeURIComponent(promptId)}/versions`, {
28
+ ...query,
29
+ });
30
+ }
31
+ /** Promotes a stored version to current. Unchanged text is a no-op, not a fork. */
32
+ promote(promptId, versionId, query = {}) {
33
+ return this.client.post(`/api/v1/prompts/${encodeURIComponent(promptId)}/versions`, { versionId }, { ...query });
34
+ }
35
+ cases(promptId, query = {}) {
36
+ return this.client.get(`/api/v1/prompts/${encodeURIComponent(promptId)}/cases`, {
37
+ ...query,
38
+ });
39
+ }
40
+ /** Replaces the dataset. Splits are derived, so a case never moves between them. */
41
+ putCases(promptId, cases, query = {}) {
42
+ return this.client.put(`/api/v1/prompts/${encodeURIComponent(promptId)}/cases`, { cases }, { ...query });
43
+ }
44
+ rollouts(promptId, query = {}) {
45
+ return this.client.get(`/api/v1/prompts/${encodeURIComponent(promptId)}/rollouts`, {
46
+ ...query,
47
+ });
48
+ }
49
+ /**
50
+ * Records a rollout the caller ran itself. Dedupes on `rolloutId`.
51
+ *
52
+ * `priced` is false where no pricing row covered the model. The stored cost
53
+ * is zero either way — the column is `notNull` — so this flag is the only
54
+ * thing telling a free call apart from an unpriced one.
55
+ */
56
+ report(promptId, body, query = {}) {
57
+ return this.client.post(`/api/v1/prompts/${encodeURIComponent(promptId)}/rollouts`, body, {
58
+ ...query,
59
+ });
60
+ }
61
+ /** Runs the prompt server-side, where the spec, rendering and pricing already live. */
62
+ run(promptId, body, query = {}) {
63
+ return this.client.post(`/api/v1/prompts/${encodeURIComponent(promptId)}/run`, body, {
64
+ ...query,
65
+ });
66
+ }
67
+ }
@@ -0,0 +1,65 @@
1
+ import type { Client } from "../core/client/index.js";
2
+ /** Shared by every stats read. Defaults to the last 30 days, all visible projects. */
3
+ export interface RangeQuery {
4
+ /** ISO timestamp. Defaults to 30 days before `to`. */
5
+ from?: string;
6
+ /** ISO timestamp. Defaults to now. */
7
+ to?: string;
8
+ /** An API key is pinned to its own project and refuses any other. */
9
+ project?: string;
10
+ }
11
+ export interface Totals {
12
+ costMicros: number;
13
+ inputTokens: number;
14
+ outputTokens: number;
15
+ cacheReadTokens: number;
16
+ cacheWriteTokens: number;
17
+ requests: number;
18
+ }
19
+ export interface Summary {
20
+ current: Totals;
21
+ /** The window of the same length immediately before `from`. */
22
+ previous: Totals;
23
+ pricing: unknown;
24
+ }
25
+ export interface TimeseriesPoint {
26
+ day: string;
27
+ costMicros: number;
28
+ inputTokens: number;
29
+ outputTokens: number;
30
+ requests: number;
31
+ }
32
+ export interface Timeseries {
33
+ days: TimeseriesPoint[];
34
+ bucket: string;
35
+ }
36
+ export interface ModelRow {
37
+ model: string;
38
+ costMicros: number;
39
+ inputTokens: number;
40
+ outputTokens: number;
41
+ requests: number;
42
+ }
43
+ /**
44
+ * Spend, read back.
45
+ *
46
+ * Every method here takes an API key, so a job can check what it spent without
47
+ * a dashboard session.
48
+ */
49
+ export declare class Stats {
50
+ private readonly client;
51
+ constructor(client: Client);
52
+ /** Totals for the window, beside the window before it. */
53
+ summary(query?: RangeQuery): Promise<Summary>;
54
+ timeseries(query?: RangeQuery & {
55
+ bucket?: "day" | "hour";
56
+ }): Promise<Timeseries>;
57
+ byModel(query?: RangeQuery): Promise<{
58
+ models: ModelRow[];
59
+ }>;
60
+ byKey(query?: RangeQuery): Promise<Record<string, unknown>>;
61
+ /** Grouped by one metadata tag. `key` picks which tag. */
62
+ byTag(query?: RangeQuery & {
63
+ key?: string;
64
+ }): Promise<Record<string, unknown>>;
65
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Spend, read back.
3
+ *
4
+ * Every method here takes an API key, so a job can check what it spent without
5
+ * a dashboard session.
6
+ */
7
+ export class Stats {
8
+ client;
9
+ constructor(client) {
10
+ this.client = client;
11
+ }
12
+ /** Totals for the window, beside the window before it. */
13
+ summary(query = {}) {
14
+ return this.client.get("/api/v1/stats/summary", { ...query });
15
+ }
16
+ timeseries(query = {}) {
17
+ return this.client.get("/api/v1/stats/timeseries", { ...query });
18
+ }
19
+ byModel(query = {}) {
20
+ return this.client.get("/api/v1/stats/by-model", { ...query });
21
+ }
22
+ byKey(query = {}) {
23
+ return this.client.get("/api/v1/stats/by-key", { ...query });
24
+ }
25
+ /** Grouped by one metadata tag. `key` picks which tag. */
26
+ byTag(query = {}) {
27
+ return this.client.get("/api/v1/stats/by-tag", { ...query });
28
+ }
29
+ }