@clocknext/sdk 0.14.0 → 0.16.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.
@@ -1,5 +1,6 @@
1
1
  import type { Transport } from "../http.js";
2
2
  import type { Flusher } from "../flusher.js";
3
+ import { customerRefToWire } from "../customer-ref.js";
3
4
  import { newKey } from "../idempotency.js";
4
5
  import type {
5
6
  CompositeCompletionInput,
@@ -15,8 +16,6 @@ import type {
15
16
  TrackResult,
16
17
  UnitInput,
17
18
  UnitTrackResult,
18
- UnitUsageList,
19
- UsageList,
20
19
  UsageLogListParams,
21
20
  UsageLogPage,
22
21
  WalletInput,
@@ -68,14 +67,16 @@ const USAGE_LOG_PATH = "/api/v1/signal/usage-log";
68
67
  export function signalToWire(signal: Signal): Record<string, unknown> {
69
68
  const t = signal.tokens;
70
69
  const body: Record<string, unknown> = {
71
- customerId: signal.customerId,
70
+ ...customerRefToWire(signal),
72
71
  // `usage` is required on all three model-priced kinds. input/output are
73
- // always sent; `cacheTokens` only when provided (the server defaults 0).
72
+ // always sent; `cacheTokens` / `cacheWriteTokens` only when provided (the
73
+ // server defaults each to 0).
74
74
  usage: {
75
75
  model: signal.model,
76
76
  inputTokens: t.input,
77
77
  outputTokens: t.output,
78
78
  ...(t.cache != null ? { cacheTokens: t.cache } : {}),
79
+ ...(t.cacheWrite != null ? { cacheWriteTokens: t.cacheWrite } : {}),
79
80
  },
80
81
  };
81
82
  if (signal.member) body.member = signal.member;
@@ -282,9 +283,8 @@ export class Signals {
282
283
  path: OUTCOME_COMPLETE_PATH,
283
284
  idempotencyKey,
284
285
  body: {
285
- customerId: input.customerId,
286
+ ...customerRefToWire(input),
286
287
  runId: input.runId,
287
- complete: true,
288
288
  ...(input.member ? { member: input.member } : {}),
289
289
  idempotencyKey,
290
290
  },
@@ -300,27 +300,6 @@ export class Signals {
300
300
  };
301
301
  }
302
302
 
303
- /**
304
- * Recent usage logs + totals for a customer. `GET /api/v1/usage`.
305
- *
306
- * Still the legacy path, deliberately. The `/api/v1/signal/*` family is
307
- * POST-only — it replaced how usage is INGESTED, not how it is read — so
308
- * `GET /api/v1/usage` has no successor and is not deprecated. It is also the
309
- * only way to prove a signal landed, which matters more now that ingestion
310
- * answers `202` for everything.
311
- */
312
- async list(params: {
313
- customerId: string;
314
- limit?: number;
315
- }): Promise<UsageList> {
316
- const res = await this.transport.request<UsageList>({
317
- method: "GET",
318
- path: "/api/v1/usage",
319
- query: { customerId: params.customerId, limit: params.limit },
320
- });
321
- return { customer: res.customer, totals: res.totals, logs: res.logs };
322
- }
323
-
324
303
  /**
325
304
  * Record one unit-metered event (a fixed-price meter with no tokens),
326
305
  * addressed to a catalog unit by its `agentKey`. Sent immediately — unit
@@ -342,7 +321,7 @@ export class Signals {
342
321
  path: UNIT_PATH,
343
322
  idempotencyKey,
344
323
  body: {
345
- customerId: input.customerId,
324
+ ...customerRefToWire(input),
346
325
  agentKey: input.agentKey,
347
326
  ...(input.quantity != null ? { quantity: input.quantity } : {}),
348
327
  ...(input.member ? { member: input.member } : {}),
@@ -410,7 +389,7 @@ export class Signals {
410
389
  path: COMPOSITE_COMPLETE_PATH,
411
390
  idempotencyKey,
412
391
  body: {
413
- customerId: input.customerId,
392
+ ...customerRefToWire(input),
414
393
  composite: { [input.composite.ref]: input.composite.value },
415
394
  // Auto-assigned like the others. A retry here could not double-BILL
416
395
  // even without it — closing a closed occurrence is a server-side
@@ -432,23 +411,6 @@ export class Signals {
432
411
  };
433
412
  }
434
413
 
435
- /**
436
- * A customer's unit balances + recent unit events. `GET /api/v1/units`.
437
- *
438
- * Legacy path for the same reason as {@link list}: the signal family is
439
- * POST-only, so the read side has no successor and is not deprecated.
440
- */
441
- unitUsage(params: {
442
- customerId: string;
443
- limit?: number;
444
- }): Promise<UnitUsageList> {
445
- return this.transport.request<UnitUsageList>({
446
- method: "GET",
447
- path: "/api/v1/units",
448
- query: { customerId: params.customerId, limit: params.limit },
449
- });
450
- }
451
-
452
414
  /**
453
415
  * One customer's usage history, merged from every meter kind — credit,
454
416
  * outcome, unit, wallet, and completed composite occurrences — into one
@@ -1,76 +1,76 @@
1
1
  import { activeQuery, filterByActive } from "../filters.js";
2
2
  import type { Transport } from "../http.js";
3
- import type {
4
- CreateUnitInput,
5
- Unit,
6
- UnitDetail,
7
- UpdateUnitInput,
8
- } from "../types.js";
3
+ import type { CreateUnitInput, Unit, UpdateUnitInput } from "../types.js";
9
4
 
10
5
  /**
11
- * The `units` resource — manage the org's unit *types* (the catalog): named,
12
- * quantity-priced meters (FLAT / SLAB / VOLUME). Record consumption against a
13
- * unit with `signals.unit()`. `/api/v1/units-catalog`.
6
+ * The `units` resource — fixed-price, non-LLM events (uploads, seats, API
7
+ * calls), priced FLAT, SLAB or VOLUME. `/api/v1/units`.
8
+ *
9
+ * There is no `delete()` — the API never deletes catalogue items. Retire a
10
+ * unit with `archive()`; `unarchive()` brings it back unchanged.
14
11
  */
15
12
  export class Units {
16
13
  constructor(private readonly transport: Transport) {}
17
14
 
18
- /** List unit types. Pass `{ active: true }` to only return active ones.
19
- * `{ active: false }` returns only archived ones; omitting it returns
20
- * both. See `activeQuery` — the API itself only supports `true`. */
15
+ /** List them. `{ active: true }` returns only active ones, `{ active: false }`
16
+ * only archived ones; omit it for both. */
21
17
  async list(params: { active?: boolean } = {}): Promise<Unit[]> {
22
18
  const res = await this.transport.request<{ units: Unit[] }>({
23
19
  method: "GET",
24
- path: "/api/v1/units-catalog",
20
+ path: "/api/v1/units",
25
21
  query: { active: activeQuery(params.active) },
26
22
  });
27
23
  return filterByActive(res.units, params.active);
28
24
  }
29
25
 
30
- /** Create a unit type. `POST /api/v1/units-catalog`. */
31
- async create(input: CreateUnitInput): Promise<Unit> {
26
+ /** One unit's configuration. */
27
+ async get(id: string): Promise<Unit> {
32
28
  const res = await this.transport.request<{ unit: Unit }>({
33
- method: "POST",
34
- path: "/api/v1/units-catalog",
35
- body: input,
29
+ method: "GET",
30
+ path: `/api/v1/units/${encodeURIComponent(id)}`,
36
31
  });
37
32
  return res.unit;
38
33
  }
39
34
 
40
- /** Fetch one unit type with stats. `GET /api/v1/units-catalog/:id`. */
41
- async get(id: string): Promise<UnitDetail> {
42
- const res = await this.transport.request<{ unit: UnitDetail }>({
43
- method: "GET",
44
- path: `/api/v1/units-catalog/${encodeURIComponent(id)}`,
35
+ /** Create one. It starts active. Not retried on failure — a retry could
36
+ * create a second row. */
37
+ async create(input: CreateUnitInput): Promise<Unit> {
38
+ const res = await this.transport.request<{ created: true; unit: Unit }>({
39
+ method: "POST",
40
+ path: "/api/v1/units",
41
+ body: input,
45
42
  });
46
43
  return res.unit;
47
44
  }
48
45
 
49
- /** Update a unit type's definition. `PATCH /api/v1/units-catalog/:id`. */
46
+ /** PARTIAL update: only the fields you send change. `tiers`, when sent, is
47
+ * the complete new tier list. */
50
48
  async update(id: string, input: UpdateUnitInput): Promise<Unit> {
51
- const res = await this.transport.request<{ unit: Unit }>({
49
+ const res = await this.transport.request<{ updated: true; unit: Unit }>({
52
50
  method: "PATCH",
53
- path: `/api/v1/units-catalog/${encodeURIComponent(id)}`,
51
+ path: `/api/v1/units/${encodeURIComponent(id)}`,
54
52
  body: input,
55
53
  });
56
54
  return res.unit;
57
55
  }
58
56
 
59
- /** Activate or deactivate a unit type. */
60
- async setActive(id: string, isActive: boolean): Promise<Unit> {
61
- const res = await this.transport.request<{ unit: Unit }>({
62
- method: "PATCH",
63
- path: `/api/v1/units-catalog/${encodeURIComponent(id)}`,
64
- body: { isActive },
57
+ /** Retire it (`isActive` → false). Nothing is deleted. Safe to retry. */
58
+ async archive(id: string): Promise<Unit> {
59
+ const res = await this.transport.request<{ archived: true; unit: Unit }>({
60
+ method: "POST",
61
+ path: `/api/v1/units/${encodeURIComponent(id)}/archive`,
62
+ retry: true,
65
63
  });
66
64
  return res.unit;
67
65
  }
68
66
 
69
- /** Delete a unit type. */
70
- async delete(id: string): Promise<void> {
71
- await this.transport.request({
72
- method: "DELETE",
73
- path: `/api/v1/units-catalog/${encodeURIComponent(id)}`,
67
+ /** Bring an archived one back (`isActive` → true). Safe to retry. */
68
+ async unarchive(id: string): Promise<Unit> {
69
+ const res = await this.transport.request<{ unarchived: true; unit: Unit }>({
70
+ method: "POST",
71
+ path: `/api/v1/units/${encodeURIComponent(id)}/unarchive`,
72
+ retry: true,
74
73
  });
74
+ return res.unit;
75
75
  }
76
76
  }