@clocknext/sdk 0.7.0 → 0.8.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/dist/index.d.cts CHANGED
@@ -185,12 +185,38 @@ interface SerializedUsageLog {
185
185
  balance: UsageBalance | null;
186
186
  createdAt: string;
187
187
  }
188
- /** Result of a single signal send (sync mode, or `{ wait: true }`). */
188
+ /**
189
+ * Result of a single signal send (sync mode, or `{ wait: true }`).
190
+ *
191
+ * `queued: true` has TWO causes, and they are not the same thing:
192
+ * 1. **Client-side buffering** (async mode, no `wait`) — the signal is in this
193
+ * process's buffer and has not been sent. No `messageId`.
194
+ * 2. **Server-side durable hand-off** — the request WAS sent and the server
195
+ * answered `202 Accepted`, having enqueued it for a worker to price. Carries
196
+ * a `messageId`. `usageLog` is null: the log does not exist yet.
197
+ *
198
+ * In case 2 the signal is accepted but **not yet billed**, and it has only been
199
+ * shallowly validated. A bad `agentKey`, a customer with no matching plan, or an
200
+ * exhausted allowance is detected by the worker LATER and never surfaces here —
201
+ * the signal is simply dropped. A `202` therefore means "accepted", never
202
+ * "recorded". To confirm a signal actually landed, read it back with
203
+ * `signals.list({ customerId })`.
204
+ *
205
+ * When the server has no queue configured it prices inline instead and returns
206
+ * `queued: false` with a populated `usageLog`, validating synchronously.
207
+ */
189
208
  interface TrackResult {
190
- /** True when the signal was buffered (async mode) and not yet sent. */
209
+ /** True when the signal has not been priced yet — either buffered locally
210
+ * (async mode) or accepted for asynchronous processing by the server. */
191
211
  queued: boolean;
192
- /** The computed usage log — present only once the signal has been sent. */
212
+ /** The computed usage log. Non-null ONLY when the server priced the signal
213
+ * inline (`queued: false`); null on a `202` hand-off and absent while the
214
+ * signal sits in the client-side buffer. */
193
215
  usageLog?: SerializedUsageLog | null;
216
+ /** The server's durable-queue message id, present only on a `202` hand-off
217
+ * (server-side queueing). Absent for client-side buffering and for inline
218
+ * pricing. */
219
+ messageId?: string;
194
220
  }
195
221
  interface UsageList {
196
222
  customer: {
@@ -279,7 +305,9 @@ interface OutcomeBalance {
279
305
  granted: number;
280
306
  remaining: number;
281
307
  /** Each step's `agentKey` is what `signals.outcome()` and the outcome adjust
282
- * API use to address this outcome (outcomes have no key of their own). */
308
+ * API use to address this outcome at runtime. The outcome also has its own
309
+ * separate key ({@link Outcome.agentKey}), but neither of those APIs accepts
310
+ * it — it identifies the outcome in the catalogue, not in a signal. */
283
311
  steps: {
284
312
  id: string;
285
313
  name: string;
@@ -734,10 +762,12 @@ interface CreditAdjustInput {
734
762
  notes?: string;
735
763
  }
736
764
  /** Grant/claw an outcome balance. `delta` is a non-zero whole number; floored at
737
- * 0. The outcome is addressed by a STEP's `agentKey` (outcomes have no key of
738
- * their own). */
765
+ * 0. The outcome is addressed here by a STEP's `agentKey`, which resolves to its
766
+ * parent outcome — NOT by the outcome's own `agentKey` ({@link Outcome.agentKey}),
767
+ * which this endpoint does not accept. */
739
768
  interface OutcomeAdjustInput {
740
- /** An outcome step's stable agent key — identifies the parent outcome. */
769
+ /** An outcome STEP's stable agent key — identifies the parent outcome. Passing
770
+ * the outcome's own `agentKey` here fails with `422`. */
741
771
  agentKey: string;
742
772
  delta: number;
743
773
  notes?: string;
@@ -846,6 +876,17 @@ interface OutcomeStepInput {
846
876
  interface Outcome {
847
877
  id: string;
848
878
  name: string;
879
+ /**
880
+ * The OUTCOME's own stable agent key — its durable identity, mirroring
881
+ * {@link Credit.agentKey}. Lowercased `[a-z0-9._-]`, max 80 chars, unique per
882
+ * organisation. A rename never changes it.
883
+ *
884
+ * Distinct from each step's `agentKey` in `steps`, and in a SEPARATE
885
+ * namespace: usage is always reported against a STEP's key
886
+ * (`signals.outcome({ agentKey })`), never this one. This key identifies the
887
+ * outcome itself when creating or updating it.
888
+ */
889
+ agentKey: string;
849
890
  description: string | null;
850
891
  isActive: boolean;
851
892
  marginPercent: number;
@@ -874,6 +915,15 @@ interface OutcomeDetail extends Outcome {
874
915
  }
875
916
  interface CreateOutcomeInput {
876
917
  name: string;
918
+ /**
919
+ * The OUTCOME's own stable agent key — REQUIRED. Lowercased `[a-z0-9._-]`,
920
+ * max 80 chars, unique per organisation (the server lowercases and trims it).
921
+ *
922
+ * Separate namespace from `steps[].agentKey`: this names the outcome, a step
923
+ * key names a step and is what `signals.outcome()` reports against. Omitting
924
+ * it is rejected with a `ValidationError` (400).
925
+ */
926
+ agentKey: string;
877
927
  basePrice: number;
878
928
  marginPercent: number;
879
929
  pricePerOutcome: number;
@@ -1280,8 +1330,14 @@ declare class Invoices {
1280
1330
 
1281
1331
  /**
1282
1332
  * The `outcomes` resource — manage the org's outcome *types* (the catalog). An
1283
- * outcome is a multi-step workflow; each step has a stable `agentKey` you pass
1284
- * to `signals.outcome()`. `/api/v1/outcomes`.
1333
+ * outcome is a multi-step workflow. `/api/v1/outcomes`.
1334
+ *
1335
+ * Two distinct kinds of agent key, in separate namespaces, each unique per
1336
+ * organisation — do not conflate them:
1337
+ * - the OUTCOME's own `agentKey`, REQUIRED on `create()` and `update()`, which
1338
+ * names the outcome itself in the catalogue;
1339
+ * - each STEP's `agentKey`, which is what you pass to `signals.outcome()` to
1340
+ * report usage and to the outcome-adjust API.
1285
1341
  */
1286
1342
  declare class Outcomes {
1287
1343
  private readonly transport;
@@ -1431,15 +1487,31 @@ declare function signalToWire(signal: Signal): Record<string, unknown>;
1431
1487
  /**
1432
1488
  * The `signals` resource: record usage signals and read them back.
1433
1489
  *
1434
- * In async mode (default), `track()` buffers the signal and returns immediately
1435
- * with `{ queued: true }`. Pass `{ wait: true }` (or construct the client in
1436
- * `sync` mode) to await the send and receive the computed `usageLog`.
1490
+ * In async mode (default), `track()` buffers the signal locally and returns
1491
+ * immediately with `{ queued: true }`. Pass `{ wait: true }` (or construct the
1492
+ * client in `sync` mode) to await the request.
1493
+ *
1494
+ * Awaiting the request does NOT guarantee a priced result. Where the server has
1495
+ * a durable queue configured it answers `202` and prices the signal in a worker,
1496
+ * so `track()` resolves `{ queued: true, messageId, usageLog: null }` — accepted,
1497
+ * not yet billed, and validated only later (a bad `agentKey` is dropped there,
1498
+ * silently). Only when the server prices inline do you get
1499
+ * `{ queued: false, usageLog }`. Branch on `queued`; never assume `usageLog`.
1500
+ * `verify()` is the way to validate and price a signal synchronously, and
1501
+ * `list()` is how you confirm one actually landed.
1437
1502
  */
1438
1503
  declare class Signals {
1439
1504
  private readonly transport;
1440
1505
  private readonly flusher;
1441
1506
  private readonly cfg;
1442
1507
  constructor(transport: Transport, flusher: Flusher, cfg: ResolvedConfig);
1508
+ /**
1509
+ * Record one usage signal. `POST /api/v1/usage`.
1510
+ *
1511
+ * Returns as soon as the signal is buffered (async mode) or the request has
1512
+ * been answered (`{ wait: true }` / sync mode). See {@link TrackResult}: a
1513
+ * resolved promise means "accepted", which is not the same as "billed".
1514
+ */
1443
1515
  track(signal: Signal, opts?: {
1444
1516
  wait?: boolean;
1445
1517
  }): Promise<TrackResult>;
package/dist/index.d.ts CHANGED
@@ -185,12 +185,38 @@ interface SerializedUsageLog {
185
185
  balance: UsageBalance | null;
186
186
  createdAt: string;
187
187
  }
188
- /** Result of a single signal send (sync mode, or `{ wait: true }`). */
188
+ /**
189
+ * Result of a single signal send (sync mode, or `{ wait: true }`).
190
+ *
191
+ * `queued: true` has TWO causes, and they are not the same thing:
192
+ * 1. **Client-side buffering** (async mode, no `wait`) — the signal is in this
193
+ * process's buffer and has not been sent. No `messageId`.
194
+ * 2. **Server-side durable hand-off** — the request WAS sent and the server
195
+ * answered `202 Accepted`, having enqueued it for a worker to price. Carries
196
+ * a `messageId`. `usageLog` is null: the log does not exist yet.
197
+ *
198
+ * In case 2 the signal is accepted but **not yet billed**, and it has only been
199
+ * shallowly validated. A bad `agentKey`, a customer with no matching plan, or an
200
+ * exhausted allowance is detected by the worker LATER and never surfaces here —
201
+ * the signal is simply dropped. A `202` therefore means "accepted", never
202
+ * "recorded". To confirm a signal actually landed, read it back with
203
+ * `signals.list({ customerId })`.
204
+ *
205
+ * When the server has no queue configured it prices inline instead and returns
206
+ * `queued: false` with a populated `usageLog`, validating synchronously.
207
+ */
189
208
  interface TrackResult {
190
- /** True when the signal was buffered (async mode) and not yet sent. */
209
+ /** True when the signal has not been priced yet — either buffered locally
210
+ * (async mode) or accepted for asynchronous processing by the server. */
191
211
  queued: boolean;
192
- /** The computed usage log — present only once the signal has been sent. */
212
+ /** The computed usage log. Non-null ONLY when the server priced the signal
213
+ * inline (`queued: false`); null on a `202` hand-off and absent while the
214
+ * signal sits in the client-side buffer. */
193
215
  usageLog?: SerializedUsageLog | null;
216
+ /** The server's durable-queue message id, present only on a `202` hand-off
217
+ * (server-side queueing). Absent for client-side buffering and for inline
218
+ * pricing. */
219
+ messageId?: string;
194
220
  }
195
221
  interface UsageList {
196
222
  customer: {
@@ -279,7 +305,9 @@ interface OutcomeBalance {
279
305
  granted: number;
280
306
  remaining: number;
281
307
  /** Each step's `agentKey` is what `signals.outcome()` and the outcome adjust
282
- * API use to address this outcome (outcomes have no key of their own). */
308
+ * API use to address this outcome at runtime. The outcome also has its own
309
+ * separate key ({@link Outcome.agentKey}), but neither of those APIs accepts
310
+ * it — it identifies the outcome in the catalogue, not in a signal. */
283
311
  steps: {
284
312
  id: string;
285
313
  name: string;
@@ -734,10 +762,12 @@ interface CreditAdjustInput {
734
762
  notes?: string;
735
763
  }
736
764
  /** Grant/claw an outcome balance. `delta` is a non-zero whole number; floored at
737
- * 0. The outcome is addressed by a STEP's `agentKey` (outcomes have no key of
738
- * their own). */
765
+ * 0. The outcome is addressed here by a STEP's `agentKey`, which resolves to its
766
+ * parent outcome — NOT by the outcome's own `agentKey` ({@link Outcome.agentKey}),
767
+ * which this endpoint does not accept. */
739
768
  interface OutcomeAdjustInput {
740
- /** An outcome step's stable agent key — identifies the parent outcome. */
769
+ /** An outcome STEP's stable agent key — identifies the parent outcome. Passing
770
+ * the outcome's own `agentKey` here fails with `422`. */
741
771
  agentKey: string;
742
772
  delta: number;
743
773
  notes?: string;
@@ -846,6 +876,17 @@ interface OutcomeStepInput {
846
876
  interface Outcome {
847
877
  id: string;
848
878
  name: string;
879
+ /**
880
+ * The OUTCOME's own stable agent key — its durable identity, mirroring
881
+ * {@link Credit.agentKey}. Lowercased `[a-z0-9._-]`, max 80 chars, unique per
882
+ * organisation. A rename never changes it.
883
+ *
884
+ * Distinct from each step's `agentKey` in `steps`, and in a SEPARATE
885
+ * namespace: usage is always reported against a STEP's key
886
+ * (`signals.outcome({ agentKey })`), never this one. This key identifies the
887
+ * outcome itself when creating or updating it.
888
+ */
889
+ agentKey: string;
849
890
  description: string | null;
850
891
  isActive: boolean;
851
892
  marginPercent: number;
@@ -874,6 +915,15 @@ interface OutcomeDetail extends Outcome {
874
915
  }
875
916
  interface CreateOutcomeInput {
876
917
  name: string;
918
+ /**
919
+ * The OUTCOME's own stable agent key — REQUIRED. Lowercased `[a-z0-9._-]`,
920
+ * max 80 chars, unique per organisation (the server lowercases and trims it).
921
+ *
922
+ * Separate namespace from `steps[].agentKey`: this names the outcome, a step
923
+ * key names a step and is what `signals.outcome()` reports against. Omitting
924
+ * it is rejected with a `ValidationError` (400).
925
+ */
926
+ agentKey: string;
877
927
  basePrice: number;
878
928
  marginPercent: number;
879
929
  pricePerOutcome: number;
@@ -1280,8 +1330,14 @@ declare class Invoices {
1280
1330
 
1281
1331
  /**
1282
1332
  * The `outcomes` resource — manage the org's outcome *types* (the catalog). An
1283
- * outcome is a multi-step workflow; each step has a stable `agentKey` you pass
1284
- * to `signals.outcome()`. `/api/v1/outcomes`.
1333
+ * outcome is a multi-step workflow. `/api/v1/outcomes`.
1334
+ *
1335
+ * Two distinct kinds of agent key, in separate namespaces, each unique per
1336
+ * organisation — do not conflate them:
1337
+ * - the OUTCOME's own `agentKey`, REQUIRED on `create()` and `update()`, which
1338
+ * names the outcome itself in the catalogue;
1339
+ * - each STEP's `agentKey`, which is what you pass to `signals.outcome()` to
1340
+ * report usage and to the outcome-adjust API.
1285
1341
  */
1286
1342
  declare class Outcomes {
1287
1343
  private readonly transport;
@@ -1431,15 +1487,31 @@ declare function signalToWire(signal: Signal): Record<string, unknown>;
1431
1487
  /**
1432
1488
  * The `signals` resource: record usage signals and read them back.
1433
1489
  *
1434
- * In async mode (default), `track()` buffers the signal and returns immediately
1435
- * with `{ queued: true }`. Pass `{ wait: true }` (or construct the client in
1436
- * `sync` mode) to await the send and receive the computed `usageLog`.
1490
+ * In async mode (default), `track()` buffers the signal locally and returns
1491
+ * immediately with `{ queued: true }`. Pass `{ wait: true }` (or construct the
1492
+ * client in `sync` mode) to await the request.
1493
+ *
1494
+ * Awaiting the request does NOT guarantee a priced result. Where the server has
1495
+ * a durable queue configured it answers `202` and prices the signal in a worker,
1496
+ * so `track()` resolves `{ queued: true, messageId, usageLog: null }` — accepted,
1497
+ * not yet billed, and validated only later (a bad `agentKey` is dropped there,
1498
+ * silently). Only when the server prices inline do you get
1499
+ * `{ queued: false, usageLog }`. Branch on `queued`; never assume `usageLog`.
1500
+ * `verify()` is the way to validate and price a signal synchronously, and
1501
+ * `list()` is how you confirm one actually landed.
1437
1502
  */
1438
1503
  declare class Signals {
1439
1504
  private readonly transport;
1440
1505
  private readonly flusher;
1441
1506
  private readonly cfg;
1442
1507
  constructor(transport: Transport, flusher: Flusher, cfg: ResolvedConfig);
1508
+ /**
1509
+ * Record one usage signal. `POST /api/v1/usage`.
1510
+ *
1511
+ * Returns as soon as the signal is buffered (async mode) or the request has
1512
+ * been answered (`{ wait: true }` / sync mode). See {@link TrackResult}: a
1513
+ * resolved promise means "accepted", which is not the same as "billed".
1514
+ */
1443
1515
  track(signal: Signal, opts?: {
1444
1516
  wait?: boolean;
1445
1517
  }): Promise<TrackResult>;
package/dist/index.js CHANGED
@@ -227,7 +227,7 @@ function sleep(ms) {
227
227
  }
228
228
 
229
229
  // src/http.ts
230
- var SDK_VERSION = "0.7.0" ;
230
+ var SDK_VERSION = "0.8.0" ;
231
231
  var Transport = class {
232
232
  constructor(cfg) {
233
233
  this.cfg = cfg;
@@ -887,6 +887,13 @@ var Signals = class {
887
887
  transport;
888
888
  flusher;
889
889
  cfg;
890
+ /**
891
+ * Record one usage signal. `POST /api/v1/usage`.
892
+ *
893
+ * Returns as soon as the signal is buffered (async mode) or the request has
894
+ * been answered (`{ wait: true }` / sync mode). See {@link TrackResult}: a
895
+ * resolved promise means "accepted", which is not the same as "billed".
896
+ */
890
897
  async track(signal, opts = {}) {
891
898
  const body = signalToWire(signal);
892
899
  if (body.idempotencyKey == null) body.idempotencyKey = newKey();
@@ -903,8 +910,9 @@ var Signals = class {
903
910
  retry: true
904
911
  });
905
912
  return {
906
- queued: false,
907
- usageLog: res.usageLog ?? null
913
+ queued: res.queued === true,
914
+ usageLog: res.usageLog ?? null,
915
+ ...res.messageId != null ? { messageId: res.messageId } : {}
908
916
  };
909
917
  }
910
918
  /**