nexus-ai-pro 2.4.0 → 2.5.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 (94) hide show
  1. package/API_STABILITY.md +85 -0
  2. package/CHANGELOG.md +147 -1
  3. package/README.md +8 -3
  4. package/SECURITY.md +78 -9
  5. package/dist/context-hub/hub.d.ts +53 -0
  6. package/dist/context-hub/hub.js +108 -3
  7. package/dist/context-hub/index.d.ts +2 -1
  8. package/dist/context-hub/index.js +2 -1
  9. package/dist/context-hub/signing.d.ts +95 -0
  10. package/dist/context-hub/signing.js +88 -0
  11. package/dist/doctor/index.d.ts +4 -2
  12. package/dist/doctor/index.js +29 -0
  13. package/dist/evaluate/threads.d.ts +187 -0
  14. package/dist/evaluate/threads.js +187 -0
  15. package/dist/operations/adapters.d.ts +2 -1
  16. package/dist/operations/runner.js +2 -0
  17. package/dist/operations/stats.js +11 -4
  18. package/dist/postgres/index.d.ts +2 -1
  19. package/dist/postgres/index.js +4 -0
  20. package/dist/postgres/operations.js +11 -4
  21. package/dist/postgres/store.d.ts +7 -0
  22. package/dist/postgres/store.js +21 -0
  23. package/dist/postgres/tenancy.d.ts +43 -0
  24. package/dist/postgres/tenancy.js +71 -0
  25. package/dist/server/deployments.d.ts +127 -12
  26. package/dist/server/deployments.js +402 -37
  27. package/dist/server/metrics.d.ts +2 -0
  28. package/dist/server/metrics.js +7 -0
  29. package/dist/server/runs.d.ts +9 -1
  30. package/dist/server/runs.js +46 -7
  31. package/dist/server/server.js +4 -1
  32. package/dist/server/state.d.ts +12 -2
  33. package/dist/server/state.js +15 -0
  34. package/dist/sqlite/operations.js +15 -4
  35. package/dist/sqlite/store.d.ts +7 -0
  36. package/dist/sqlite/store.js +28 -0
  37. package/dist/store/memory.d.ts +8 -0
  38. package/dist/store/memory.js +12 -1
  39. package/dist/store/redis.d.ts +13 -0
  40. package/dist/store/redis.js +38 -0
  41. package/dist/tracing/instrument.js +1 -0
  42. package/dist/tracing/tracer.d.ts +4 -0
  43. package/dist/tracing/tracer.js +6 -0
  44. package/dist/types/operations.d.ts +7 -0
  45. package/dist/types/server.d.ts +61 -2
  46. package/dist/types/store.d.ts +9 -0
  47. package/dist/version.d.ts +1 -1
  48. package/dist/version.js +1 -1
  49. package/dist-cjs/context-hub/hub.d.ts +53 -0
  50. package/dist-cjs/context-hub/hub.js +110 -4
  51. package/dist-cjs/context-hub/index.d.ts +2 -1
  52. package/dist-cjs/context-hub/index.js +7 -1
  53. package/dist-cjs/context-hub/signing.d.ts +95 -0
  54. package/dist-cjs/context-hub/signing.js +96 -0
  55. package/dist-cjs/doctor/index.d.ts +4 -2
  56. package/dist-cjs/doctor/index.js +29 -0
  57. package/dist-cjs/evaluate/threads.d.ts +187 -0
  58. package/dist-cjs/evaluate/threads.js +198 -0
  59. package/dist-cjs/operations/adapters.d.ts +2 -1
  60. package/dist-cjs/operations/runner.js +2 -0
  61. package/dist-cjs/operations/stats.js +11 -4
  62. package/dist-cjs/postgres/index.d.ts +2 -1
  63. package/dist-cjs/postgres/index.js +8 -1
  64. package/dist-cjs/postgres/operations.js +11 -4
  65. package/dist-cjs/postgres/store.d.ts +7 -0
  66. package/dist-cjs/postgres/store.js +21 -0
  67. package/dist-cjs/postgres/tenancy.d.ts +43 -0
  68. package/dist-cjs/postgres/tenancy.js +110 -0
  69. package/dist-cjs/server/deployments.d.ts +127 -12
  70. package/dist-cjs/server/deployments.js +402 -37
  71. package/dist-cjs/server/metrics.d.ts +2 -0
  72. package/dist-cjs/server/metrics.js +8 -0
  73. package/dist-cjs/server/runs.d.ts +9 -1
  74. package/dist-cjs/server/runs.js +45 -6
  75. package/dist-cjs/server/server.js +4 -1
  76. package/dist-cjs/server/state.d.ts +12 -2
  77. package/dist-cjs/server/state.js +15 -0
  78. package/dist-cjs/sqlite/operations.js +15 -4
  79. package/dist-cjs/sqlite/store.d.ts +7 -0
  80. package/dist-cjs/sqlite/store.js +28 -0
  81. package/dist-cjs/store/memory.d.ts +8 -0
  82. package/dist-cjs/store/memory.js +12 -1
  83. package/dist-cjs/store/redis.d.ts +13 -0
  84. package/dist-cjs/store/redis.js +38 -0
  85. package/dist-cjs/tracing/instrument.js +1 -0
  86. package/dist-cjs/tracing/tracer.d.ts +4 -0
  87. package/dist-cjs/tracing/tracer.js +6 -0
  88. package/dist-cjs/types/operations.d.ts +7 -0
  89. package/dist-cjs/types/server.d.ts +61 -2
  90. package/dist-cjs/types/store.d.ts +9 -0
  91. package/dist-cjs/version.d.ts +1 -1
  92. package/dist-cjs/version.js +1 -1
  93. package/llms.txt +1 -1
  94. package/package.json +27 -1
@@ -1,7 +1,7 @@
1
1
  import { type Regression, type RegressionMetric, type RunSample } from '../insights/regressions.js';
2
2
  import type { EvaluationScore, Evaluator } from '../types/evaluate.js';
3
- import type { DeploymentChange, DeploymentChangeRecord, DeploymentRecord, ReplicaReport, RevisionChoice, RevisionRequest, ServerAssistant, ServerDeployments, ServerStateStore } from '../types/server.js';
4
- export type { DeploymentChange, DeploymentChangeRecord, DeploymentRecord, ReplicaReport, RevisionChoice, RevisionReason, RevisionRequest, RunRevision, } from '../types/server.js';
3
+ import type { BucketStrategy, DeploymentChange, DeploymentChangeRecord, DeploymentRecord, ReplicaReport, RevisionChoice, RevisionRequest, RunRecord, ServerAssistant, ServerDeployments, ServerStateStore } from '../types/server.js';
4
+ export type { BucketStrategy, DeploymentChange, DeploymentChangeRecord, DeploymentRecord, ReplicaReport, RevisionChoice, RevisionReason, RevisionRequest, RunRevision, } from '../types/server.js';
5
5
  /** Options for `Deployments`. */
6
6
  export interface DeploymentsOptions {
7
7
  /**
@@ -22,7 +22,12 @@ export interface DeploymentsOptions {
22
22
  cacheMs?: number;
23
23
  /** History entries kept per deployment. Defaults to 50. */
24
24
  historyLimit?: number;
25
- /** Receives heartbeat failures, which never stop the server. */
25
+ /**
26
+ * How long this replica gathers the runs it finished before writing them to its rollups, in
27
+ * milliseconds. Defaults to 1 second. Reading rollups through this object writes its own first.
28
+ */
29
+ rollupMs?: number;
30
+ /** Receives heartbeat and rollup write failures, which never stop the server. */
26
31
  onError?: (error: unknown) => void;
27
32
  /** Replaces the system clock, for tests. */
28
33
  now?: () => Date;
@@ -37,12 +42,50 @@ export interface RevisionedAssistantOptions {
37
42
  live?: string;
38
43
  /** What the assistant is, reported by the assistants endpoint. */
39
44
  description?: string;
45
+ /**
46
+ * How the deployment places threads, when it is first recorded. Defaults to `fnv1a-v1`. A deployment
47
+ * already recorded keeps its own; `Deployments.bucketing()` changes it.
48
+ */
49
+ bucketStrategy?: BucketStrategy;
50
+ }
51
+ /** One revision's finished runs, as a replica counts them for one deployment version. */
52
+ export interface RevisionRollup {
53
+ /** Runs counted: succeeded, failed, and cancelled. */
54
+ runs: number;
55
+ /** Runs that succeeded or are awaiting input. */
56
+ succeeded: number;
57
+ /** Runs that failed or expired. */
58
+ failed: number;
59
+ /** Runs that were cancelled, which count neither way. */
60
+ cancelled: number;
61
+ /**
62
+ * Durations of succeeded and failed runs, as counts by bucket. A bucket's key is its index; each is
63
+ * 5% wider than the one before, so a percentile read from them is within 2.5% of the true one.
64
+ */
65
+ latency: Record<string, number>;
66
+ /** Total recorded cost of succeeded and failed runs, in US dollars. */
67
+ cost: number;
68
+ /** How many of those runs recorded a cost. */
69
+ costed: number;
70
+ }
71
+ /** What one replica counted under one deployment version, as stored in the state store. */
72
+ export interface DeploymentRollup {
73
+ /** The assistant. */
74
+ assistant: string;
75
+ /** The deployment version the runs were routed under. */
76
+ deployment: number;
77
+ /** The replica that counted them. */
78
+ replica: string;
79
+ /** ISO-8601 time it was last written. */
80
+ updatedAt: string;
81
+ /** The counts, per revision. */
82
+ revisions: Record<string, RevisionRollup>;
40
83
  }
41
84
  /** What one revision's runs did, from `Deployments.stats()`. */
42
85
  export interface RevisionStats {
43
86
  /** The revision. */
44
87
  revision: string;
45
- /** Runs recorded for it, finished or not. */
88
+ /** Runs recorded for it: finished or not from run records, and finished or cancelled from rollups. */
46
89
  runs: number;
47
90
  /** Runs that succeeded or are awaiting input. */
48
91
  succeeded: number;
@@ -100,12 +143,22 @@ export interface RunEvaluationReport {
100
143
  export declare class Deployments implements ServerDeployments {
101
144
  private readonly options;
102
145
  private readonly state;
146
+ /** What fresh workers carry, per assistant, read at most every `cacheMs`. */
147
+ private readonly fleet;
103
148
  /** The change in progress per deployment, which the next one waits for. */
104
149
  private readonly changing;
105
150
  private readonly now;
106
151
  private readonly registrations;
107
152
  private readonly cache;
108
153
  private heartbeat?;
154
+ /** Runs finished here and not yet written, per assistant and deployment version. */
155
+ private readonly pending;
156
+ /** This replica's rollups as last written, so a write needs no read. */
157
+ private readonly written;
158
+ private rollupTimer?;
159
+ private flushing;
160
+ /** Names this replica's rollups before the server attaches it with its own id. */
161
+ private readonly unattached;
109
162
  constructor(options?: DeploymentsOptions);
110
163
  /**
111
164
  * Serves an assistant through its revisions, by id: `{ '2026-09-01': v1, '2026-09-30': v2 }`.
@@ -116,6 +169,12 @@ export declare class Deployments implements ServerDeployments {
116
169
  assistant(id: string, revisions: Record<string, ServerAssistant>, options?: RevisionedAssistantOptions): ServerAssistant;
117
170
  /** Chooses the revision for a run. The server calls it through the assistant; tests may call it directly. */
118
171
  route(assistant: string, request: RevisionRequest): Promise<RevisionChoice | undefined>;
172
+ /**
173
+ * Whether changes are atomic across replicas: true when the state store has `putIfVersion()`.
174
+ * Otherwise, changes on this replica apply in order, but two replicas changing one deployment in
175
+ * the same instant can lose one change.
176
+ */
177
+ get atomicChanges(): boolean;
119
178
  /** Every deployment: those recorded, and the default of every assistant registered here that has none. */
120
179
  list(): Promise<DeploymentRecord[]>;
121
180
  /** One assistant's deployment, as recorded, or its default when this process registered it. */
@@ -131,20 +190,24 @@ export declare class Deployments implements ServerDeployments {
131
190
  * - `promote` makes a revision live, with all the traffic.
132
191
  * - `rollback` sends all traffic back to the live revision when a canary has any; otherwise it
133
192
  * makes the previous live revision live again. `to` names the revision instead.
193
+ * - `bucketing` changes how new threads are placed in the split, keeping the split itself.
134
194
  *
135
195
  * `expectedVersion` applies a change only to the version it was decided on, and throws
136
196
  * `DEPLOYMENT_CONFLICT` otherwise, so two people — or a person and a canary guard — cannot undo each
137
197
  * other without noticing.
138
198
  *
139
199
  * Changes to one deployment through this object apply one at a time, so two made at once on one
140
- * replica both land, in order. The state store has no atomic compare-and-set, so two replicas
141
- * changing one deployment in the same instant can still lose one change: make changes from one
200
+ * replica both land, in order. Across replicas, a state store with `putIfVersion()` makes each
201
+ * change atomic: a replica that loses a race decides again on the winner's record. Without it, two
202
+ * replicas changing one deployment in the same instant can lose one change: make changes from one
142
203
  * place, or pass `expectedVersion` and retry a conflict.
143
204
  */
144
205
  change(assistant: string, change: DeploymentChange & {
145
206
  expectedVersion?: number;
146
207
  }, by?: string): Promise<DeploymentRecord>;
147
208
  private applyChange;
209
+ /** The record a change makes of the stored one, or of the default when none is stored. */
210
+ private decide;
148
211
  /** Sets each revision's share of new runs. */
149
212
  split(assistant: string, traffic: Record<string, number>, options?: {
150
213
  by?: string;
@@ -166,6 +229,14 @@ export declare class Deployments implements ServerDeployments {
166
229
  by?: string;
167
230
  reason?: string;
168
231
  }): Promise<DeploymentRecord>;
232
+ /**
233
+ * Changes how new threads and stateless runs are placed in the split. A thread already on a revision
234
+ * that takes traffic stays there; new threads are placed by the new strategy.
235
+ */
236
+ bucketing(assistant: string, strategy: BucketStrategy, options?: {
237
+ by?: string;
238
+ reason?: string;
239
+ }): Promise<DeploymentRecord>;
169
240
  /** Replicas whose heartbeat is fresh, newest first. */
170
241
  replicas(): Promise<ReplicaReport[]>;
171
242
  /**
@@ -174,19 +245,44 @@ export declare class Deployments implements ServerDeployments {
174
245
  * The server calls it from `start()`.
175
246
  */
176
247
  attach(report: () => ReplicaReport): Promise<void>;
177
- /** Stops heartbeating and removes this replica's report. The server calls it from `stop()`. */
248
+ /**
249
+ * Writes the runs this replica counted, stops heartbeating, and removes this replica's report. The
250
+ * server calls it from `stop()`.
251
+ */
178
252
  detach(): Promise<void>;
179
253
  /** The revisions this process registered, and those fresh replicas report, for an assistant. */
180
254
  revisions(assistant: string): Promise<string[]>;
181
255
  /**
182
- * What each revision's runs did, from the server's run records in the same store: counts, error
183
- * rate, latency percentiles, and mean cost. `since` limits it to runs created from that time, such
184
- * as the start of a canary; `limit` bounds how many recent runs are read, 2,000 by default.
256
+ * What each revision's runs did: counts, error rate, latency percentiles, and mean cost.
257
+ *
258
+ * With `deployment`, a version, they come from the rollups of every run routed under it, on every
259
+ * replica: the whole window a canary guard judges, in one read. Percentiles are then within 2.5%.
260
+ * Runs in flight are counted when they finish. A version no replica counted, such as one served
261
+ * only by replicas older than 2.5, falls back to run records.
262
+ *
263
+ * Otherwise they come from the server's run records in the same store. `since` limits them to runs
264
+ * created from that time, such as the start of a canary; `limit` bounds how many recent runs are
265
+ * read, 2,000 by default.
185
266
  */
186
267
  stats(assistant: string, options?: {
187
268
  since?: string;
188
269
  limit?: number;
270
+ deployment?: number;
189
271
  }): Promise<RevisionStats[]>;
272
+ /**
273
+ * Every revision's rollup under one deployment version, summed over the replicas that counted its
274
+ * runs. This replica's runs not yet written are written first.
275
+ */
276
+ rollups(assistant: string, deployment: number): Promise<Map<string, RevisionRollup>>;
277
+ /**
278
+ * Counts a finished run in this replica's rollup for the deployment version it was routed under.
279
+ * The server calls it as each run finishes. Counts are written every `rollupMs`, each replica to its
280
+ * own record, so counting never contends with another replica.
281
+ */
282
+ recordRun(run: RunRecord): void;
283
+ /** Writes the runs this replica counted and has not written yet. Failures go to `onError` and are retried. */
284
+ flushRollups(): Promise<void>;
285
+ private writeRollups;
190
286
  /**
191
287
  * One revision's finished runs since a time, as samples `compareRuns()` reads: a failed or
192
288
  * expired run is an error, a cancelled one is left out.
@@ -205,6 +301,8 @@ export declare class Deployments implements ServerDeployments {
205
301
  evaluate(assistant: string, options: RunEvaluationOptions): Promise<RunEvaluationReport>;
206
302
  /** The deployment the router uses, reusing a recent read. */
207
303
  private current;
304
+ /** The revisions fresh workers that claim queued runs report carrying, read at most every `cacheMs`. */
305
+ private workerRevisions;
208
306
  /** The deployment of a registered assistant before anything is recorded: its live revision, all traffic. */
209
307
  private initial;
210
308
  private knownRevisions;
@@ -236,6 +334,16 @@ export interface CanaryGuardOptions {
236
334
  * promoted. Without steps, a canary that holds up stays where it is until a person promotes it.
237
335
  */
238
336
  steps?: readonly number[];
337
+ /**
338
+ * What a canary is judged on.
339
+ *
340
+ * - `runs`, the default, reads run samples: the server's run records since the split last changed,
341
+ * the latest 2,000, or those `samples` returns.
342
+ * - `rollups` reads the counts every replica keeps under the deployment's current version: every run
343
+ * since the split last changed, however many, in one read. It judges the error rate, p95 latency,
344
+ * and mean cost, not feedback, so it cannot be combined with `samples` or `feedback`.
345
+ */
346
+ from?: 'runs' | 'rollups';
239
347
  /**
240
348
  * Where a revision's runs come from. Defaults to the server's run records. Give it runs from a
241
349
  * trace store to judge on feedback scores too, with `feedback` naming the keys.
@@ -257,6 +365,9 @@ export interface CanaryGuardOptions {
257
365
  * `minErrorRateIncrease`, `latencyIncrease` with `minLatencyChangeMs`, `costIncrease`, and
258
366
  * `minFeedbackDrop`. A real regression rolls back, and noise or a trivial change does not. Without
259
367
  * it, the error rate uses a z-test at 95%, and latency and cost use their margins alone.
368
+ *
369
+ * From rollups, the error rate is judged by a z-test at this confidence, with
370
+ * `minErrorRateIncrease`, and latency and cost by their margins.
260
371
  */
261
372
  confidence?: number;
262
373
  /** The smallest rise in the error rate, absolute, that counts under `confidence`. Defaults to 0.02. */
@@ -315,5 +426,9 @@ export interface CanaryGuard {
315
426
  * first to act wins, and the rest find the deployment already moved.
316
427
  */
317
428
  export declare function watchCanaries(options: CanaryGuardOptions): CanaryGuard;
318
- /** A stable position in [0, 1) for a key: FNV-1a, so the same thread always lands in the same place. */
319
- export declare function bucket(key: string): number;
429
+ /**
430
+ * A stable position in [0, 1) for a key, so the same thread always lands in the same place. The
431
+ * strategy defaults to `fnv1a-v1`, whose positions never change; `hash-v2` spreads sequential keys
432
+ * evenly too.
433
+ */
434
+ export declare function bucket(key: string, strategy?: BucketStrategy): number;