@mlx-node/server 0.0.9 → 0.0.12

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 (53) hide show
  1. package/dist/chat-session-warm-reuse.d.ts +10 -12
  2. package/dist/chat-session-warm-reuse.d.ts.map +1 -1
  3. package/dist/chat-session-warm-reuse.js +10 -12
  4. package/dist/endpoints/messages.d.ts +2 -2
  5. package/dist/endpoints/messages.d.ts.map +1 -1
  6. package/dist/endpoints/messages.js +492 -349
  7. package/dist/endpoints/responses.d.ts +1 -1
  8. package/dist/endpoints/responses.d.ts.map +1 -1
  9. package/dist/endpoints/responses.js +1149 -1055
  10. package/dist/handler.d.ts.map +1 -1
  11. package/dist/handler.js +1 -1
  12. package/dist/health.d.ts +4 -6
  13. package/dist/health.d.ts.map +1 -1
  14. package/dist/host/discover.d.ts +1 -2
  15. package/dist/host/discover.d.ts.map +1 -1
  16. package/dist/host/discover.js +3 -6
  17. package/dist/host/index.d.ts +6 -1
  18. package/dist/host/index.d.ts.map +1 -1
  19. package/dist/host/index.js +3 -2
  20. package/dist/index.d.ts +2 -4
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +1 -9
  23. package/dist/mappers/anthropic-request.d.ts.map +1 -1
  24. package/dist/mappers/anthropic-request.js +5 -1
  25. package/dist/mappers/request.d.ts +12 -2
  26. package/dist/mappers/request.d.ts.map +1 -1
  27. package/dist/mappers/request.js +26 -2
  28. package/dist/model-work-coordinator.d.ts +50 -0
  29. package/dist/model-work-coordinator.d.ts.map +1 -1
  30. package/dist/model-work-coordinator.js +161 -0
  31. package/dist/registry.d.ts +15 -0
  32. package/dist/registry.d.ts.map +1 -1
  33. package/dist/registry.js +51 -0
  34. package/dist/server.d.ts +21 -3
  35. package/dist/server.d.ts.map +1 -1
  36. package/dist/server.js +30 -6
  37. package/dist/session-registry.d.ts +266 -86
  38. package/dist/session-registry.d.ts.map +1 -1
  39. package/dist/session-registry.js +421 -107
  40. package/dist/streaming.d.ts +37 -2
  41. package/dist/streaming.d.ts.map +1 -1
  42. package/dist/streaming.js +122 -1
  43. package/dist/transport-visibility.d.ts +5 -4
  44. package/dist/transport-visibility.d.ts.map +1 -1
  45. package/dist/transport-visibility.js +5 -4
  46. package/dist/types-anthropic.d.ts +7 -0
  47. package/dist/types-anthropic.d.ts.map +1 -1
  48. package/dist/types.d.ts +9 -0
  49. package/dist/types.d.ts.map +1 -1
  50. package/package.json +4 -4
  51. package/dist/presets.d.ts +0 -82
  52. package/dist/presets.d.ts.map +0 -1
  53. package/dist/presets.js +0 -98
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"AAAA,4GAA4G;AAE5G,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIpD,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAoBnD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uDAAuD;IACvD,KAAK,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,gBAAgB,EAAE,CAAC;IACtC;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,YAAY,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,cAAc,GACvB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAgF9D"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"AAAA,4GAA4G;AAE5G,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIpD,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAoBnD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uDAAuD;IACvD,KAAK,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,gBAAgB,EAAE,CAAC;IACtC;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,YAAY,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,cAAc,GACvB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAiF9D"}
package/dist/handler.js CHANGED
@@ -28,7 +28,7 @@ export function createHandler(registry, options) {
28
28
  const responseRetentionSec = options?.responseRetentionSec;
29
29
  const idleSweeper = options?.idleSweeper ?? null;
30
30
  const resolveModel = options?.resolveModel;
31
- const modelWorkCoordinator = options?.modelWorkCoordinator ?? (resolveModel ? new ModelWorkCoordinator() : undefined);
31
+ const modelWorkCoordinator = options?.modelWorkCoordinator ?? (resolveModel ? new ModelWorkCoordinator(registry.queueDepthLimit) : undefined);
32
32
  const listModels = options?.listModels;
33
33
  const health = options?.health ?? createHealthReporter({ registry, idleSweeper, modelWorkCoordinator: modelWorkCoordinator });
34
34
  return async (req, res) => {
package/dist/health.d.ts CHANGED
@@ -39,12 +39,10 @@ export type ServerHealthStatus = 'ok' | 'loading' | 'degraded' | 'error';
39
39
  * dropped — a supervisor polling after the fact had no way to learn WHY the
40
40
  * server had no resident model.
41
41
  *
42
- * Caveat worth knowing when reading this field: the coordinator brackets
43
- * EVERY resolve attempt, including the no-op fast path taken when the
44
- * requested model is already resident. A successful no-op therefore
45
- * overwrites an earlier failure record. That is why the `'error'` rung is
46
- * additionally gated on "no resident models" — a server that is answering
47
- * requests is not in an error state regardless of what the last bracket did.
42
+ * Resident HTTP requests bypass the load writer and do not overwrite this
43
+ * record with a no-op. The `'error'` rung is nevertheless gated on "no
44
+ * resident models": a server that is answering requests is not in an error
45
+ * state regardless of what the last load bracket did.
48
46
  */
49
47
  export interface ModelLoadRecord {
50
48
  /** Caller-supplied label, normally the model name. `null` when unlabelled. */
@@ -1 +1 @@
1
- {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../src/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAEzE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,yDAAyD;IACzD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,0FAA0F;AAC1F,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,YAAY,EAAE,OAAO,CAAC;IACtB,gDAAgD;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oFAAoF;IACpF,cAAc,EAAE,OAAO,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;CAClC;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE;QACN,2CAA2C;QAC3C,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC;QACjB,oEAAoE;QACpE,YAAY,EAAE,OAAO,CAAC;QACtB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,KAAK,EAAE;QACL,oEAAoE;QACpE,KAAK,EAAE,MAAM,CAAC;QACd,iEAAiE;QACjE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,SAAS,EAAE,OAAO,CAAC;KACpB,CAAC;IACF,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;CAClC;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,kBAAkB,CAShF;AAED,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,mBAAmB,CAEzE;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,aAAa,CAAC;IACxB,kFAAkF;IAClF,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,mFAAmF;IACnF,oBAAoB,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACnD,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,YAAY,CAiDjF"}
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../src/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAEzE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,yDAAyD;IACzD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,0FAA0F;AAC1F,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,YAAY,EAAE,OAAO,CAAC;IACtB,gDAAgD;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oFAAoF;IACpF,cAAc,EAAE,OAAO,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;CAClC;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE;QACN,2CAA2C;QAC3C,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC;QACjB,oEAAoE;QACpE,YAAY,EAAE,OAAO,CAAC;QACtB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,KAAK,EAAE;QACL,oEAAoE;QACpE,KAAK,EAAE,MAAM,CAAC;QACd,iEAAiE;QACjE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,SAAS,EAAE,OAAO,CAAC;KACpB,CAAC;IACF,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;CAClC;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,kBAAkB,CAShF;AAED,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,mBAAmB,CAEzE;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,aAAa,CAAC;IACxB,kFAAkF;IAClF,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,mFAAmF;IACnF,oBAAoB,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACnD,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,YAAY,CAiDjF"}
@@ -1,6 +1,5 @@
1
1
  /** Discover locally-downloaded generative models under a given directory. */
2
- import { type ModelType } from '@mlx-node/lm';
3
- import { type LaunchPreset } from '../presets.js';
2
+ import { type LaunchPreset, type ModelType } from '@mlx-node/lm';
4
3
  /** A locally-downloaded model paired with its sampling preset. */
5
4
  export interface DiscoveredModel {
6
5
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/host/discover.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAM7E,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAElE,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;CACtB;AAKD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAoC5E"}
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/host/discover.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAM7E,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAoC5E"}
@@ -1,10 +1,7 @@
1
1
  /** Discover locally-downloaded generative models under a given directory. */
2
2
  import { readdir } from 'node:fs/promises';
3
3
  import { basename, join } from 'node:path';
4
- import { detectModelType } from '@mlx-node/lm';
5
- import { LAUNCH_PRESETS } from '../presets.js';
6
- // Non-generative detection results that cannot back a chat endpoint.
7
- const NON_GENERATIVE = new Set(['harrier', 'qianfan-ocr', 'internvl_chat']);
4
+ import { detectModelType, NON_GENERATIVE_FAMILY_IDS, launchPresetFor, } from '@mlx-node/lm';
8
5
  /**
9
6
  * Scan `dir` for model subdirectories. Each subdirectory with a recognized
10
7
  * `config.json` is returned with its inferred `ModelType` and `LaunchPreset`.
@@ -35,9 +32,9 @@ export async function discoverModels(dir) {
35
32
  console.warn(`[mlx] skip ${full}: ${err.message}`);
36
33
  continue;
37
34
  }
38
- if (NON_GENERATIVE.has(modelType))
35
+ if (NON_GENERATIVE_FAMILY_IDS.has(modelType))
39
36
  continue;
40
- const preset = LAUNCH_PRESETS[modelType];
37
+ const preset = launchPresetFor(modelType);
41
38
  if (!preset) {
42
39
  if (debug)
43
40
  console.warn(`[mlx] skip ${full}: no LAUNCH_PRESETS entry for ${modelType}`);
@@ -45,7 +45,7 @@ import { type DiscoveredModel } from './discover.js';
45
45
  import { type EnginePolicy } from './env-policy.js';
46
46
  import { type Logger } from './logger.js';
47
47
  /** Families `mlx launch claude` has historically forced onto the paged path. */
48
- export declare const DEFAULT_PAGED_MODEL_TYPES: readonly ['qwen3_5', 'qwen3_5_moe'];
48
+ export declare const DEFAULT_PAGED_MODEL_TYPES: readonly ["qwen3_5", "qwen3_5_moe"];
49
49
  /** Thrown when `modelsDir` holds nothing servable. Carries the dir for the caller's message. */
50
50
  export declare class NoModelsDiscoveredError extends Error {
51
51
  readonly modelsDir: string;
@@ -121,6 +121,11 @@ export interface InferenceHostOptions {
121
121
  storePath?: string;
122
122
  /** Disable response persistence entirely. See `ServerConfig.disableStore`. */
123
123
  disableStore?: boolean;
124
+ /**
125
+ * Per-model waiter cap forwarded to `createServer`. Default 16; pass
126
+ * `'unbounded'` for an explicitly uncapped embedded host.
127
+ */
128
+ maxQueueDepthPerModel?: number | 'unbounded';
124
129
  /**
125
130
  * Remove temp roots left behind by hosts that were killed without running
126
131
  * `close()`. Default `true`; a supervisor that runs several hosts under one
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"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"}
@@ -37,7 +37,7 @@
37
37
  * independently guarded — one failing disposer must not strand the ones
38
38
  * after it.
39
39
  */
40
- import { loadModel as loadModelNative, PagedConfigOverrideManager } from '@mlx-node/lm';
40
+ import { loadModel as loadModelNative, PagedConfigOverrideManager, QWEN35_PAGED_MODEL_TYPES, } from '@mlx-node/lm';
41
41
  import { createServer, resolveAuthToken } from '../server.js';
42
42
  import { discoverModels } from './discover.js';
43
43
  import { applyEnginePolicy } from './env-policy.js';
@@ -47,7 +47,7 @@ import { resolveModelsDir } from './paths.js';
47
47
  import { makeSwapController } from './swap.js';
48
48
  import { hostTempDirPrefix, sweepOrphanHostTempRoots } from './temp-root.js';
49
49
  /** Families `mlx launch claude` has historically forced onto the paged path. */
50
- export const DEFAULT_PAGED_MODEL_TYPES = ['qwen3_5', 'qwen3_5_moe'];
50
+ export const DEFAULT_PAGED_MODEL_TYPES = QWEN35_PAGED_MODEL_TYPES;
51
51
  /** Thrown when `modelsDir` holds nothing servable. Carries the dir for the caller's message. */
52
52
  export class NoModelsDiscoveredError extends Error {
53
53
  modelsDir;
@@ -166,6 +166,7 @@ export async function createInferenceHost(opts = {}) {
166
166
  ...(opts.authToken !== undefined ? { authToken: opts.authToken } : {}),
167
167
  ...(opts.storePath !== undefined ? { storePath: opts.storePath } : {}),
168
168
  ...(opts.disableStore !== undefined ? { disableStore: opts.disableStore } : {}),
169
+ ...(opts.maxQueueDepthPerModel !== undefined ? { maxQueueDepthPerModel: opts.maxQueueDepthPerModel } : {}),
169
170
  };
170
171
  const server = await createServer(serverConfig);
171
172
  // Wrap the loader so managed families get `use_block_paged_cache: true`
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * Exposes loaded models via `POST /v1/responses`, `POST /v1/messages`, and
5
5
  * `GET /v1/models`, in both streaming (SSE) and non-streaming modes.
6
6
  */
7
- export { createServer } from './server.js';
7
+ export { createServer, DEFAULT_MAX_QUEUE_DEPTH_PER_MODEL } from './server.js';
8
8
  export type { CloseOptions, CloseResult, ServerConfig, ServerInstance } from './server.js';
9
9
  /**
10
10
  * Readiness reporting. `deriveHealthStatus` is pure — a supervisor can reuse
@@ -27,10 +27,8 @@ export type { HandlerOptions } from './handler.js';
27
27
  export { ModelRegistry } from './registry.js';
28
28
  export type { ServableModel, ModelEntry, ModelRegistryOptions, RegisterOptions } from './registry.js';
29
29
  export { QueueFullError, SessionRegistry } from './session-registry.js';
30
- export type { SessionLookupResult, SessionRegistryOptions } from './session-registry.js';
30
+ export type { PreDispatchAdmission, SessionLookupResult, SessionRegistryOptions } from './session-registry.js';
31
31
  export { resolveServerTuningForUsage } from './timing.js';
32
- export { QWEN_SAMPLING_DEFAULTS, GEMMA4_SAMPLING_DEFAULTS, LFM2_SAMPLING_DEFAULTS, LAUNCH_PRESETS } from './presets.js';
33
- export type { LaunchPreset } from './presets.js';
34
32
  export type { PublicModelEntry } from './handler.js';
35
33
  export type { ResponsesAPIRequest, ResponseObject, ResponseUsage, ResponseError, InputItem, InputMessage, InputFunctionCall, InputFunctionCallOutput, OutputItem, MessageOutputItem, ReasoningOutputItem, FunctionCallOutputItem, OutputTextPart, SummaryTextPart, ResponsesToolDefinition, ContentPart, InputTextPart, StreamEvent, } from './types.js';
36
34
  export type { AnthropicCountTokensRequest, AnthropicCountTokensResponse, AnthropicMessagesRequest, AnthropicMessagesResponse, AnthropicMessage, AnthropicContentBlock, AnthropicTextContentBlock, AnthropicImageContentBlock, AnthropicToolResultContentBlock, AnthropicToolUseContentBlock, AnthropicThinkingContentBlock, AnthropicToolDefinition, AnthropicToolChoice, AnthropicResponseContent, AnthropicResponseTextBlock, AnthropicResponseThinkingBlock, AnthropicResponseToolUseBlock, AnthropicUsage, AnthropicStreamEvent, AnthropicMessageStartEvent, AnthropicContentBlockStartEvent, AnthropicContentBlockDeltaEvent, AnthropicContentBlockStopEvent, AnthropicMessageDeltaEvent, AnthropicMessageStopEvent, AnthropicDelta, AnthropicTextDelta, AnthropicThinkingDelta, AnthropicInputJsonDelta, SystemBlock, } from './types-anthropic.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE3F;;;GAGG;AACH,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACxF,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEzE;;;GAGG;AACH,OAAO,EAAE,eAAe,IAAI,iBAAiB,EAAE,mBAAmB,IAAI,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACjH,OAAO,EACL,iBAAiB,IAAI,mBAAmB,EACxC,sBAAsB,IAAI,wBAAwB,EAClD,2BAA2B,IAAI,6BAA6B,GAC7D,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEtG,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxE,YAAY,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAS1D,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACxH,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,YAAY,EACV,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,aAAa,EACb,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,EACd,eAAe,EACf,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,qBAAqB,EACrB,yBAAyB,EACzB,0BAA0B,EAC1B,+BAA+B,EAC/B,4BAA4B,EAC5B,6BAA6B,EAC7B,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,8BAA8B,EAC9B,6BAA6B,EAC7B,cAAc,EACd,oBAAoB,EACpB,0BAA0B,EAC1B,+BAA+B,EAC/B,+BAA+B,EAC/B,8BAA8B,EAC9B,0BAA0B,EAC1B,yBAAyB,EACzB,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,iCAAiC,EAAE,MAAM,aAAa,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE3F;;;GAGG;AACH,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACxF,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEzE;;;GAGG;AACH,OAAO,EAAE,eAAe,IAAI,iBAAiB,EAAE,mBAAmB,IAAI,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACjH,OAAO,EACL,iBAAiB,IAAI,mBAAmB,EACxC,sBAAsB,IAAI,wBAAwB,EAClD,2BAA2B,IAAI,6BAA6B,GAC7D,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEtG,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxE,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/G,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAS1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,YAAY,EACV,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,aAAa,EACb,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,EACd,eAAe,EACf,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,qBAAqB,EACrB,yBAAyB,EACzB,0BAA0B,EAC1B,+BAA+B,EAC/B,4BAA4B,EAC5B,6BAA6B,EAC7B,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,8BAA8B,EAC9B,6BAA6B,EAC7B,cAAc,EACd,oBAAoB,EACpB,0BAA0B,EAC1B,+BAA+B,EAC/B,+BAA+B,EAC/B,8BAA8B,EAC9B,0BAA0B,EAC1B,yBAAyB,EACzB,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Exposes loaded models via `POST /v1/responses`, `POST /v1/messages`, and
5
5
  * `GET /v1/models`, in both streaming (SSE) and non-streaming modes.
6
6
  */
7
- export { createServer } from './server.js';
7
+ export { createServer, DEFAULT_MAX_QUEUE_DEPTH_PER_MODEL } from './server.js';
8
8
  /**
9
9
  * Readiness reporting. `deriveHealthStatus` is pure — a supervisor can reuse
10
10
  * it to classify a `ServerHealth` body fetched over HTTP.
@@ -21,12 +21,4 @@ export { createHandler } from './handler.js';
21
21
  export { ModelRegistry } from './registry.js';
22
22
  export { QueueFullError, SessionRegistry } from './session-registry.js';
23
23
  export { resolveServerTuningForUsage } from './timing.js';
24
- // NOTE: `__resetPromptCacheKeyNonceForTests` is intentionally NOT
25
- // re-exported here. It is a test-only helper that nukes the module-
26
- // scoped HMAC nonce (and the once-per-process single-tenant warning
27
- // flag); exposing it on the public surface would let downstream
28
- // consumers invalidate every live tier-2 entry with one call. Tests
29
- // import it from the deep path
30
- // `packages/server/src/session-registry.js` instead.
31
- export { QWEN_SAMPLING_DEFAULTS, GEMMA4_SAMPLING_DEFAULTS, LFM2_SAMPLING_DEFAULTS, LAUNCH_PRESETS } from './presets.js';
32
24
  export { writeSSEEvent, beginSSE, endSSE, activeSSEStreamCount } from './streaming.js';
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-request.d.ts","sourceRoot":"","sources":["../../src/mappers/anthropic-request.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAkB,MAAM,gBAAgB,CAAC;AAE9E,OAAO,KAAK,EAEV,2BAA2B,EAE3B,wBAAwB,EAIzB,MAAM,uBAAuB,CAAC;AAI/B,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAmBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,wBAAwB,CAAC,QAAQ,CAAC,GAAG,MAAM,GAAG,IAAI,CAoBvG;AAiDD,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,wBAAwB,GAAG,2BAA2B,GAC1D,sBAAsB,CA8VxB"}
1
+ {"version":3,"file":"anthropic-request.d.ts","sourceRoot":"","sources":["../../src/mappers/anthropic-request.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAkB,MAAM,gBAAgB,CAAC;AAE9E,OAAO,KAAK,EAEV,2BAA2B,EAE3B,wBAAwB,EAIzB,MAAM,uBAAuB,CAAC;AAI/B,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAmBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,wBAAwB,CAAC,QAAQ,CAAC,GAAG,MAAM,GAAG,IAAI,CAoBvG;AAiDD,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,wBAAwB,GAAG,2BAA2B,GAC1D,sBAAsB,CAkWxB"}
@@ -1,6 +1,6 @@
1
1
  /** Anthropic Messages API request → internal `ChatMessage[]` + `ChatConfig`. */
2
2
  import { anthropicToolUseIdToInternal } from './anthropic-response.js';
3
- import { applyExtraBodyMtpOverrides } from './request.js';
3
+ import { applyExtraBodyMtpOverrides, validateCacheSalt } from './request.js';
4
4
  /**
5
5
  * Anthropic billing/attribution header prefix. Claude Code injects a leading
6
6
  * system block of the shape `"x-anthropic-billing-header: cc_version=...; cch=<token>;"`
@@ -390,6 +390,10 @@ export function mapAnthropicRequest(req) {
390
390
  const config = {
391
391
  reportPerformance: true,
392
392
  };
393
+ if (req.cache_salt != null) {
394
+ validateCacheSalt(req.cache_salt);
395
+ config.cacheSalt = req.cache_salt;
396
+ }
393
397
  if (req.max_tokens != null) {
394
398
  config.maxNewTokens = req.max_tokens;
395
399
  }
@@ -1,6 +1,8 @@
1
1
  /** OpenAI Responses API request → internal `ChatMessage[]` + `ChatConfig`. */
2
2
  import type { ChatConfig, ChatMessage } from '@mlx-node/core';
3
3
  import type { ResponsesAPIRequest } from '../types.js';
4
+ export declare const MAX_CACHE_SALT_BYTES = 256;
5
+ export declare function validateCacheSalt(cacheSalt: unknown): asserts cacheSalt is string;
4
6
  export interface MappedRequest {
5
7
  messages: ChatMessage[];
6
8
  config: ChatConfig;
@@ -13,8 +15,16 @@ export interface MappedRequest {
13
15
  * * `generation_mode: "mtp"` → `enableMtp = true`
14
16
  * * `generation_mode: "ar"` → `enableMtp = false`
15
17
  * * any other / absent value → `enableMtp` untouched, so the
16
- * downstream `ChatSession.mergeConfig` auto-default (true when
17
- * the model ships an MTP head) applies.
18
+ * downstream `ChatSession.mergeConfig` auto-default applies.
19
+ * That default is two-part, not just "has a head": the model
20
+ * must report `hasMtpWeights()` AND opt in through
21
+ * `ChatSession#mtpAutoDefaultAllowed`, which prefers the native
22
+ * `mtpAutoEnabled()` getter when present and otherwise falls
23
+ * back to the `MTP_AUTO_DEFAULT_SUPPRESSED_MODELS` class-name
24
+ * list (both in `packages/lm/src/chat-session.ts`). NemotronH
25
+ * is currently suppressed — its head is a measured throughput
26
+ * loss — so `generation_mode: "mtp"` (or an explicit
27
+ * `enableMtp: true`) is the only way to speculate on it here.
18
28
  *
19
29
  * * `mtp_depth: <positive int ≤ 64>` → `mtpDepth = value`
20
30
  * * non-integer, out-of-range, or absent → `mtpDepth` untouched.
@@ -1 +1 @@
1
- {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/mappers/request.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAE9E,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAkB,MAAM,gBAAgB,CAAC;AAE9E,OAAO,KAAK,EAAe,mBAAmB,EAA2B,MAAM,aAAa,CAAC;AA2G7F,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,SAAS,GACpF,IAAI,CAcN;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,mBAAmB,EAAE,aAAa,CAAC,EAAE,WAAW,EAAE,GAAG,aAAa,CAmIjG;AAwBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAgB5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,WAAW,EAAE,CAyE9G"}
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/mappers/request.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAE9E,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAkB,MAAM,gBAAgB,CAAC;AAE9E,OAAO,KAAK,EAAe,mBAAmB,EAA2B,MAAM,aAAa,CAAC;AAE7F,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAUjF;AA2GD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,SAAS,GACpF,IAAI,CAcN;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,mBAAmB,EAAE,aAAa,CAAC,EAAE,WAAW,EAAE,GAAG,aAAa,CAuIjG;AAwBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAgB5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,WAAW,EAAE,CAyE9G"}
@@ -1,4 +1,16 @@
1
1
  /** OpenAI Responses API request → internal `ChatMessage[]` + `ChatConfig`. */
2
+ export const MAX_CACHE_SALT_BYTES = 256;
3
+ export function validateCacheSalt(cacheSalt) {
4
+ if (typeof cacheSalt !== 'string') {
5
+ throw new Error('cache_salt must be a string');
6
+ }
7
+ if (cacheSalt.length === 0) {
8
+ throw new Error('cache_salt must not be empty');
9
+ }
10
+ if (Buffer.byteLength(cacheSalt, 'utf8') > MAX_CACHE_SALT_BYTES) {
11
+ throw new Error(`cache_salt must be at most ${MAX_CACHE_SALT_BYTES} UTF-8 bytes`);
12
+ }
13
+ }
2
14
  /**
3
15
  * Resolve a message's `content` array into text + optional image bytes.
4
16
  *
@@ -103,8 +115,16 @@ function mapTool(tool) {
103
115
  * * `generation_mode: "mtp"` → `enableMtp = true`
104
116
  * * `generation_mode: "ar"` → `enableMtp = false`
105
117
  * * any other / absent value → `enableMtp` untouched, so the
106
- * downstream `ChatSession.mergeConfig` auto-default (true when
107
- * the model ships an MTP head) applies.
118
+ * downstream `ChatSession.mergeConfig` auto-default applies.
119
+ * That default is two-part, not just "has a head": the model
120
+ * must report `hasMtpWeights()` AND opt in through
121
+ * `ChatSession#mtpAutoDefaultAllowed`, which prefers the native
122
+ * `mtpAutoEnabled()` getter when present and otherwise falls
123
+ * back to the `MTP_AUTO_DEFAULT_SUPPRESSED_MODELS` class-name
124
+ * list (both in `packages/lm/src/chat-session.ts`). NemotronH
125
+ * is currently suppressed — its head is a measured throughput
126
+ * loss — so `generation_mode: "mtp"` (or an explicit
127
+ * `enableMtp: true`) is the only way to speculate on it here.
108
128
  *
109
129
  * * `mtp_depth: <positive int ≤ 64>` → `mtpDepth = value`
110
130
  * * non-integer, out-of-range, or absent → `mtpDepth` untouched.
@@ -231,6 +251,10 @@ export function mapRequest(req, priorMessages) {
231
251
  const config = {
232
252
  reportPerformance: true,
233
253
  };
254
+ if (req.cache_salt != null) {
255
+ validateCacheSalt(req.cache_salt);
256
+ config.cacheSalt = req.cache_salt;
257
+ }
234
258
  if (req.max_output_tokens != null) {
235
259
  config.maxNewTokens = req.max_output_tokens;
236
260
  }
@@ -1,4 +1,5 @@
1
1
  import type { ModelLoadRecord } from './health.js';
2
+ import type { PreDispatchAdmission, SessionRegistry } from './session-registry.js';
2
3
  /**
3
4
  * Result of a `withModelLoad` call that surfaces who actually drove the load
4
5
  * vs. who merely parked behind one that was already in flight. Callers use
@@ -31,6 +32,24 @@ export interface ModelLoadOutcome<T> {
31
32
  waitMs: number;
32
33
  ownMs: number;
33
34
  }
35
+ /** A bounded request admission transferred into the resident FIFO budget. */
36
+ export interface ModelLoadAdmission {
37
+ /**
38
+ * Atomically move this request from the cold-load budget into the
39
+ * resident model's ordinary pre-dispatch budget. Idempotent for the same
40
+ * registry; transferring after a hot-swap releases the old reservation
41
+ * before charging the new binding.
42
+ */
43
+ transferToResident(registry: SessionRegistry): PreDispatchAdmission;
44
+ /** Idempotently release this request's current cold or resident unit. */
45
+ release(): void;
46
+ }
47
+ /** Raised synchronously when unresolved model-load traffic is over capacity. */
48
+ export declare class ModelLoadQueueFullError extends Error {
49
+ readonly admissionFootprint: number;
50
+ readonly limit: number;
51
+ constructor(admissionFootprint: number, limit: number);
52
+ }
34
53
  /**
35
54
  * Process-local gate for native MLX work.
36
55
  *
@@ -46,6 +65,16 @@ export declare class ModelWorkCoordinator {
46
65
  private queuedWriters;
47
66
  private readonly readerWaiters;
48
67
  private readonly writerWaiters;
68
+ private requestLoadAdmissions;
69
+ /** Outstanding permits grouped by the requested model name. */
70
+ private readonly requestLoadAdmissionsByModel;
71
+ /**
72
+ * Resident bindings published synchronously by `ModelRegistry.register`.
73
+ * Publishing transfers every already-admitted cold request before another
74
+ * request can spend the resident budget independently.
75
+ */
76
+ private readonly residentRegistriesByModel;
77
+ private readonly maxRequestLoadQueueDepth;
49
78
  /**
50
79
  * Most recent settled load bracket. Retained here because the coordinator
51
80
  * is the ONE place that brackets every load: a `resolveModel` failure in
@@ -55,6 +84,27 @@ export declare class ModelWorkCoordinator {
55
84
  * an earlier failure" caveat.
56
85
  */
57
86
  private lastLoadRecord;
87
+ constructor(maxRequestLoadQueueDepth?: number);
88
+ /**
89
+ * Bound requests that arrive before a model has a resident
90
+ * `SessionRegistry`. The capacity mirrors the resident FIFO: `limit`
91
+ * waiters plus one owner/runner. Callers retain the permit through every
92
+ * pre-lock await; registration synchronously transfers it into the resident
93
+ * `SessionRegistry` budget before any later arrival can spend that capacity.
94
+ */
95
+ beginRequestLoadAdmission(modelId: string): ModelLoadAdmission;
96
+ /**
97
+ * Publish a requested model name's resident admission lane. Called
98
+ * synchronously from `ModelRegistry.register`, so every outstanding cold
99
+ * permit moves into the registry before a later arrival can be admitted
100
+ * against an apparently empty resident budget.
101
+ */
102
+ bindRequestLoadAdmissions(modelId: string, registry: SessionRegistry): void;
103
+ /** Forget a name only when it still points at the supplied binding. */
104
+ unbindRequestLoadAdmissions(modelId: string, registry: SessionRegistry): void;
105
+ private transferAdmission;
106
+ /** Read-only unresolved/pre-FIFO request footprint for diagnostics/tests. */
107
+ get requestLoadAdmissionCount(): number;
58
108
  /** Read-only: `true` while a load holds the exclusive writer slot. */
59
109
  get writerActive(): boolean;
60
110
  /** Read-only: loads parked in `acquireWrite()` waiting for the slot. */
@@ -1 +1 @@
1
- {"version":3,"file":"model-work-coordinator.d.ts","sourceRoot":"","sources":["../src/model-work-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAqBnD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,MAAM,EAAE,CAAC,CAAC;IACV,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;IACvD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;IACvD;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc,CAAgC;IAEtD,sEAAsE;IACtE,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,wEAAwE;IACxE,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,6EAA6E;IAC7E,IAAI,QAAQ,IAAI,eAAe,GAAG,IAAI,CAErC;IAED;;;OAGG;IACH,OAAO,CAAC,UAAU;IAUlB;;;OAGG;IACG,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAmB3E;IAED;;;;;;;;;;;;OAYG;IACG,yBAAyB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CA2BzG;IAEK,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAO3D;IAED,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,KAAK;CAWd"}
1
+ {"version":3,"file":"model-work-coordinator.d.ts","sourceRoot":"","sources":["../src/model-work-coordinator.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,17 @@ function describeLoadFailure(error) {
20
20
  return 'unknown error';
21
21
  }
22
22
  }
23
+ /** Raised synchronously when unresolved model-load traffic is over capacity. */
24
+ export class ModelLoadQueueFullError extends Error {
25
+ admissionFootprint;
26
+ limit;
27
+ constructor(admissionFootprint, limit) {
28
+ super(`Model load queue full: admission footprint ${admissionFootprint} (waiter limit ${limit})`);
29
+ this.name = 'ModelLoadQueueFullError';
30
+ this.admissionFootprint = admissionFootprint;
31
+ this.limit = limit;
32
+ }
33
+ }
23
34
  /**
24
35
  * Process-local gate for native MLX work.
25
36
  *
@@ -35,6 +46,16 @@ export class ModelWorkCoordinator {
35
46
  queuedWriters = 0;
36
47
  readerWaiters = [];
37
48
  writerWaiters = [];
49
+ requestLoadAdmissions = 0;
50
+ /** Outstanding permits grouped by the requested model name. */
51
+ requestLoadAdmissionsByModel = new Map();
52
+ /**
53
+ * Resident bindings published synchronously by `ModelRegistry.register`.
54
+ * Publishing transfers every already-admitted cold request before another
55
+ * request can spend the resident budget independently.
56
+ */
57
+ residentRegistriesByModel = new Map();
58
+ maxRequestLoadQueueDepth;
38
59
  /**
39
60
  * Most recent settled load bracket. Retained here because the coordinator
40
61
  * is the ONE place that brackets every load: a `resolveModel` failure in
@@ -44,6 +65,146 @@ export class ModelWorkCoordinator {
44
65
  * an earlier failure" caveat.
45
66
  */
46
67
  lastLoadRecord = null;
68
+ constructor(maxRequestLoadQueueDepth) {
69
+ this.maxRequestLoadQueueDepth = maxRequestLoadQueueDepth;
70
+ }
71
+ /**
72
+ * Bound requests that arrive before a model has a resident
73
+ * `SessionRegistry`. The capacity mirrors the resident FIFO: `limit`
74
+ * waiters plus one owner/runner. Callers retain the permit through every
75
+ * pre-lock await; registration synchronously transfers it into the resident
76
+ * `SessionRegistry` budget before any later arrival can spend that capacity.
77
+ */
78
+ beginRequestLoadAdmission(modelId) {
79
+ const limit = this.maxRequestLoadQueueDepth;
80
+ const admissions = this.requestLoadAdmissionsByModel.get(modelId) ?? new Set();
81
+ let coldFootprint = 0;
82
+ for (const admission of admissions) {
83
+ if (!admission.released && admission.coldCounted)
84
+ coldFootprint += 1;
85
+ }
86
+ if (limit !== undefined && coldFootprint >= limit + 1) {
87
+ throw new ModelLoadQueueFullError(coldFootprint, limit);
88
+ }
89
+ if (!this.requestLoadAdmissionsByModel.has(modelId)) {
90
+ this.requestLoadAdmissionsByModel.set(modelId, admissions);
91
+ }
92
+ const state = {
93
+ released: false,
94
+ coldCounted: true,
95
+ };
96
+ admissions.add(state);
97
+ this.requestLoadAdmissions += 1;
98
+ const admission = {
99
+ transferToResident: (registry) => this.transferAdmission(state, registry),
100
+ release: () => {
101
+ if (state.released)
102
+ return;
103
+ state.released = true;
104
+ state.residentAdmission?.release();
105
+ state.residentAdmission = undefined;
106
+ state.residentRegistry = undefined;
107
+ if (state.coldCounted) {
108
+ state.coldCounted = false;
109
+ this.requestLoadAdmissions -= 1;
110
+ if (this.requestLoadAdmissions < 0)
111
+ this.requestLoadAdmissions = 0;
112
+ }
113
+ const active = this.requestLoadAdmissionsByModel.get(modelId);
114
+ active?.delete(state);
115
+ if (active?.size === 0)
116
+ this.requestLoadAdmissionsByModel.delete(modelId);
117
+ },
118
+ };
119
+ const resident = this.residentRegistriesByModel.get(modelId);
120
+ if (resident) {
121
+ try {
122
+ this.transferAdmission(state, resident);
123
+ }
124
+ catch {
125
+ // Preserve the failure on `state`; the handler observes it from its
126
+ // explicit transfer after resolving the binding and returns 429.
127
+ }
128
+ }
129
+ return admission;
130
+ }
131
+ /**
132
+ * Publish a requested model name's resident admission lane. Called
133
+ * synchronously from `ModelRegistry.register`, so every outstanding cold
134
+ * permit moves into the registry before a later arrival can be admitted
135
+ * against an apparently empty resident budget.
136
+ */
137
+ bindRequestLoadAdmissions(modelId, registry) {
138
+ this.residentRegistriesByModel.set(modelId, registry);
139
+ const admissions = this.requestLoadAdmissionsByModel.get(modelId);
140
+ if (!admissions)
141
+ return;
142
+ for (const admission of admissions) {
143
+ if (admission.released)
144
+ continue;
145
+ try {
146
+ this.transferAdmission(admission, registry);
147
+ }
148
+ catch {
149
+ // A cold request that cannot fit after an alias/hot-swap transition is
150
+ // marked fail-closed. Its handler will surface the stored QueueFullError
151
+ // rather than running outside either budget.
152
+ }
153
+ }
154
+ }
155
+ /** Forget a name only when it still points at the supplied binding. */
156
+ unbindRequestLoadAdmissions(modelId, registry) {
157
+ if (this.residentRegistriesByModel.get(modelId) === registry) {
158
+ this.residentRegistriesByModel.delete(modelId);
159
+ }
160
+ }
161
+ transferAdmission(state, registry) {
162
+ if (state.released) {
163
+ throw new Error('Model load admission has already been released');
164
+ }
165
+ if (state.residentRegistry === registry && state.transferError !== undefined) {
166
+ throw state.transferError;
167
+ }
168
+ if (state.residentRegistry === registry && state.residentAdmission) {
169
+ return state.residentAdmission;
170
+ }
171
+ if (state.residentAdmission) {
172
+ state.residentAdmission.release();
173
+ state.residentAdmission = undefined;
174
+ state.residentRegistry = undefined;
175
+ }
176
+ state.transferError = undefined;
177
+ try {
178
+ const residentAdmission = registry.beginPreDispatchAdmission();
179
+ state.residentRegistry = registry;
180
+ state.residentAdmission = residentAdmission;
181
+ if (state.coldCounted) {
182
+ state.coldCounted = false;
183
+ this.requestLoadAdmissions -= 1;
184
+ if (this.requestLoadAdmissions < 0)
185
+ this.requestLoadAdmissions = 0;
186
+ }
187
+ return residentAdmission;
188
+ }
189
+ catch (error) {
190
+ // This permit is now a rejected resident transition, not an invisible
191
+ // cold unit. Remove its cold charge; `transferToResident` rethrows the
192
+ // exact resident error when the owning request resumes.
193
+ if (state.coldCounted) {
194
+ state.coldCounted = false;
195
+ this.requestLoadAdmissions -= 1;
196
+ if (this.requestLoadAdmissions < 0)
197
+ this.requestLoadAdmissions = 0;
198
+ }
199
+ state.transferError = error;
200
+ state.residentRegistry = registry;
201
+ throw error;
202
+ }
203
+ }
204
+ /** Read-only unresolved/pre-FIFO request footprint for diagnostics/tests. */
205
+ get requestLoadAdmissionCount() {
206
+ return this.requestLoadAdmissions;
207
+ }
47
208
  /** Read-only: `true` while a load holds the exclusive writer slot. */
48
209
  get writerActive() {
49
210
  return this.writerHeld;
@@ -39,6 +39,10 @@
39
39
  import type { ChatConfig } from '@mlx-node/core';
40
40
  import type { SessionCapableModel } from '@mlx-node/lm';
41
41
  import { SessionRegistry } from './session-registry.js';
42
+ interface ModelLoadAdmissionCoordinator {
43
+ bindRequestLoadAdmissions(modelId: string, registry: SessionRegistry): void;
44
+ unbindRequestLoadAdmissions(modelId: string, registry: SessionRegistry): void;
45
+ }
42
46
  /** Minimal contract for a model that can be served via chat sessions. */
43
47
  export type ServableModel = SessionCapableModel;
44
48
  /** Model entry stored in the registry. */
@@ -145,7 +149,17 @@ export declare class ModelRegistry {
145
149
  * hard-timeouts have fired.
146
150
  */
147
151
  private readonly retiredInstanceIds;
152
+ private modelLoadAdmissionCoordinator;
148
153
  constructor(opts?: ModelRegistryOptions);
154
+ /** Configured per-model waiter cap, or `undefined` when unbounded. */
155
+ get queueDepthLimit(): number | undefined;
156
+ /**
157
+ * Connect cold-load admission to name registration. The coordinator is
158
+ * attached by the HTTP handler before dispatch; existing names are
159
+ * published immediately and future `register`/`unregister` calls keep the
160
+ * mapping current.
161
+ */
162
+ setModelLoadAdmissionCoordinator(coordinator: ModelLoadAdmissionCoordinator | undefined): void;
149
163
  /**
150
164
  * Register a model under a given name.
151
165
  *
@@ -390,4 +404,5 @@ export declare class ModelRegistry {
390
404
  */
391
405
  hasStreamSupport(model: ServableModel): boolean;
392
406
  }
407
+ export {};
393
408
  //# sourceMappingURL=registry.d.ts.map