@miller-tech/uap 1.72.1 → 1.74.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 (38) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/bin/cli.js +7 -1
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/cli/challenge.d.ts.map +1 -1
  5. package/dist/cli/challenge.js +6 -3
  6. package/dist/cli/challenge.js.map +1 -1
  7. package/dist/cli/coord.d.ts +1 -1
  8. package/dist/cli/coord.d.ts.map +1 -1
  9. package/dist/cli/coord.js +21 -0
  10. package/dist/cli/coord.js.map +1 -1
  11. package/dist/coordination/challenge-runner.d.ts.map +1 -1
  12. package/dist/coordination/challenge-runner.js +42 -31
  13. package/dist/coordination/challenge-runner.js.map +1 -1
  14. package/dist/coordination/database.d.ts.map +1 -1
  15. package/dist/coordination/database.js +12 -0
  16. package/dist/coordination/database.js.map +1 -1
  17. package/dist/coordination/service.d.ts +13 -0
  18. package/dist/coordination/service.d.ts.map +1 -1
  19. package/dist/coordination/service.js +42 -0
  20. package/dist/coordination/service.js.map +1 -1
  21. package/dist/types/config.d.ts +44 -0
  22. package/dist/types/config.d.ts.map +1 -1
  23. package/dist/types/config.js +10 -0
  24. package/dist/types/config.js.map +1 -1
  25. package/dist/utils/concurrency-pool.d.ts +4 -3
  26. package/dist/utils/concurrency-pool.d.ts.map +1 -1
  27. package/dist/utils/concurrency-pool.js +5 -2
  28. package/dist/utils/concurrency-pool.js.map +1 -1
  29. package/dist/utils/model-slot-lease.d.ts +33 -0
  30. package/dist/utils/model-slot-lease.d.ts.map +1 -0
  31. package/dist/utils/model-slot-lease.js +48 -0
  32. package/dist/utils/model-slot-lease.js.map +1 -0
  33. package/dist/utils/model-slots.d.ts +32 -0
  34. package/dist/utils/model-slots.d.ts.map +1 -0
  35. package/dist/utils/model-slots.js +133 -0
  36. package/dist/utils/model-slots.js.map +1 -0
  37. package/package.json +1 -1
  38. package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
@@ -33,8 +33,9 @@
33
33
  export declare function concurrentMap<T, R>(items: T[], fn: (item: T, index: number) => Promise<R>, options?: {
34
34
  /** Maximum concurrent operations. Overrides auto-detection. */
35
35
  maxConcurrent?: number;
36
- /** 'cpu' reserves cores for OS/inference, 'io' allows higher concurrency */
37
- mode?: 'cpu' | 'io';
36
+ /** 'cpu' reserves cores for OS/inference, 'io' allows higher concurrency,
37
+ * 'model' caps to the inference backend's model-slot budget */
38
+ mode?: 'cpu' | 'io' | 'model';
38
39
  }): Promise<R[]>;
39
40
  /**
40
41
  * Map over items with bounded concurrency, settling all promises.
@@ -46,6 +47,6 @@ export declare function concurrentMap<T, R>(items: T[], fn: (item: T, index: num
46
47
  */
47
48
  export declare function concurrentMapSettled<T, R>(items: T[], fn: (item: T, index: number) => Promise<R>, options?: {
48
49
  maxConcurrent?: number;
49
- mode?: 'cpu' | 'io';
50
+ mode?: 'cpu' | 'io' | 'model';
50
51
  }): Promise<PromiseSettledResult<R>[]>;
51
52
  //# sourceMappingURL=concurrency-pool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"concurrency-pool.d.ts","sourceRoot":"","sources":["../../src/utils/concurrency-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,aAAa,CAAC,CAAC,EAAE,CAAC,EACtC,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,OAAO,CAAC,EAAE;IACR,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB,GACA,OAAO,CAAC,CAAC,EAAE,CAAC,CAkBd;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAC7C,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB,GACA,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,CAuBpC"}
1
+ {"version":3,"file":"concurrency-pool.d.ts","sourceRoot":"","sources":["../../src/utils/concurrency-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,aAAa,CAAC,CAAC,EAAE,CAAC,EACtC,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,OAAO,CAAC,EAAE;IACR,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;oEACgE;IAChE,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC;CAC/B,GACA,OAAO,CAAC,CAAC,EAAE,CAAC,CAoBd;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAC7C,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC;CAC/B,GACA,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,CAyBpC"}
@@ -7,6 +7,7 @@
7
7
  * Uses getMaxParallel() for auto-detection with UAP_MAX_PARALLEL env override.
8
8
  */
9
9
  import { getMaxParallel } from './system-resources.js';
10
+ import { getMaxModelConcurrency } from './model-slots.js';
10
11
  /**
11
12
  * Map over items with bounded concurrency.
12
13
  *
@@ -34,7 +35,8 @@ import { getMaxParallel } from './system-resources.js';
34
35
  export async function concurrentMap(items, fn, options) {
35
36
  if (items.length === 0)
36
37
  return [];
37
- const max = options?.maxConcurrent ?? getMaxParallel(options?.mode ?? 'io');
38
+ const max = options?.maxConcurrent ??
39
+ (options?.mode === 'model' ? getMaxModelConcurrency() : getMaxParallel(options?.mode ?? 'io'));
38
40
  const results = new Array(items.length);
39
41
  let nextIndex = 0;
40
42
  const worker = async () => {
@@ -58,7 +60,8 @@ export async function concurrentMap(items, fn, options) {
58
60
  export async function concurrentMapSettled(items, fn, options) {
59
61
  if (items.length === 0)
60
62
  return [];
61
- const max = options?.maxConcurrent ?? getMaxParallel(options?.mode ?? 'io');
63
+ const max = options?.maxConcurrent ??
64
+ (options?.mode === 'model' ? getMaxModelConcurrency() : getMaxParallel(options?.mode ?? 'io'));
62
65
  const results = new Array(items.length);
63
66
  let nextIndex = 0;
64
67
  const worker = async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"concurrency-pool.js","sourceRoot":"","sources":["../../src/utils/concurrency-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAU,EACV,EAA0C,EAC1C,OAKC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,GAAG,GAAG,OAAO,EAAE,aAAa,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC;IAC5E,MAAM,OAAO,GAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,MAAM,MAAM,GAAG,KAAK,IAAmB,EAAE;QACvC,OAAO,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrC,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAEvE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAAU,EACV,EAA0C,EAC1C,OAGC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,GAAG,GAAG,OAAO,EAAE,aAAa,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC;IAC5E,MAAM,OAAO,GAA8B,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACnE,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,MAAM,MAAM,GAAG,KAAK,IAAmB,EAAE;QACvC,OAAO,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBACpC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;YAC9C,CAAC;YAAC,OAAO,MAAM,EAAE,CAAC;gBAChB,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAEvE,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"concurrency-pool.js","sourceRoot":"","sources":["../../src/utils/concurrency-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Cross-process model-slot lease: a semaphore over the inference backend's
3
+ * concurrent slots, shared via the coordination DB so multiple agents AND
4
+ * multiple `uap` processes hitting the same endpoint never exceed the budget.
5
+ *
6
+ * `withModelSlot(holder, fn)` acquires a slot (waiting when the budget is full),
7
+ * runs `fn`, and releases — the right wrapper around any model call / agent spawn.
8
+ */
9
+ import { CoordinationService } from '../coordination/service.js';
10
+ export interface SlotLeaseOptions {
11
+ cwd?: string;
12
+ /** Budget override (else resolved from model-slots). */
13
+ budget?: number;
14
+ /** Lease TTL — a crashed holder is reaped after this. Default 120s. */
15
+ ttlMs?: number;
16
+ /** Max time to wait for a slot before proceeding anyway (fail-open). Default 5m. */
17
+ timeoutMs?: number;
18
+ /** Poll interval while the budget is full. Default 200ms. */
19
+ pollMs?: number;
20
+ /** Reuse an existing service (else one is constructed on the default DB). */
21
+ service?: CoordinationService;
22
+ }
23
+ /**
24
+ * Acquire a model slot, waiting (up to timeoutMs) when the budget is full.
25
+ * Returns a lease id, or null if it timed out (caller may proceed best-effort).
26
+ */
27
+ export declare function acquireModelSlot(holder: string, opts?: SlotLeaseOptions): Promise<{
28
+ leaseId: number | null;
29
+ service: CoordinationService;
30
+ }>;
31
+ /** Run `fn` while holding a model slot (acquire → fn → release). */
32
+ export declare function withModelSlot<T>(holder: string, fn: () => Promise<T>, opts?: SlotLeaseOptions): Promise<T>;
33
+ //# sourceMappingURL=model-slot-lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-slot-lease.d.ts","sourceRoot":"","sources":["../../src/utils/model-slot-lease.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGjE,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AASD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAcnE;AAED,oEAAoE;AACpE,wBAAsB,aAAa,CAAC,CAAC,EACnC,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,CAAC,CAAC,CAOZ"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Cross-process model-slot lease: a semaphore over the inference backend's
3
+ * concurrent slots, shared via the coordination DB so multiple agents AND
4
+ * multiple `uap` processes hitting the same endpoint never exceed the budget.
5
+ *
6
+ * `withModelSlot(holder, fn)` acquires a slot (waiting when the budget is full),
7
+ * runs `fn`, and releases — the right wrapper around any model call / agent spawn.
8
+ */
9
+ import { CoordinationService } from '../coordination/service.js';
10
+ import { getModelSlotBudget } from './model-slots.js';
11
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
12
+ async function resolveBudget(opts) {
13
+ if (opts.budget && opts.budget > 0)
14
+ return opts.budget;
15
+ return (await getModelSlotBudget(opts.cwd)).budget;
16
+ }
17
+ /**
18
+ * Acquire a model slot, waiting (up to timeoutMs) when the budget is full.
19
+ * Returns a lease id, or null if it timed out (caller may proceed best-effort).
20
+ */
21
+ export async function acquireModelSlot(holder, opts = {}) {
22
+ const service = opts.service ?? new CoordinationService();
23
+ const budget = await resolveBudget(opts);
24
+ const ttlMs = opts.ttlMs ?? 120_000;
25
+ const timeoutMs = opts.timeoutMs ?? 300_000;
26
+ const pollMs = opts.pollMs ?? 200;
27
+ const deadline = Date.now() + timeoutMs;
28
+ for (;;) {
29
+ const leaseId = service.acquireModelSlot(holder, budget, ttlMs);
30
+ if (leaseId !== null)
31
+ return { leaseId, service };
32
+ if (Date.now() >= deadline)
33
+ return { leaseId: null, service }; // fail-open
34
+ await sleep(pollMs);
35
+ }
36
+ }
37
+ /** Run `fn` while holding a model slot (acquire → fn → release). */
38
+ export async function withModelSlot(holder, fn, opts = {}) {
39
+ const { leaseId, service } = await acquireModelSlot(holder, opts);
40
+ try {
41
+ return await fn();
42
+ }
43
+ finally {
44
+ if (leaseId !== null)
45
+ service.releaseModelSlot(leaseId);
46
+ }
47
+ }
48
+ //# sourceMappingURL=model-slot-lease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-slot-lease.js","sourceRoot":"","sources":["../../src/utils/model-slot-lease.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAgBtD,MAAM,KAAK,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAEnF,KAAK,UAAU,aAAa,CAAC,IAAsB;IACjD,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,MAAM,CAAC;IACvD,OAAO,CAAC,MAAM,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAc,EACd,OAAyB,EAAE;IAE3B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,mBAAmB,EAAE,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC;IACpC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAExC,SAAS,CAAC;QACR,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAChE,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QAClD,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,YAAY;QAC3E,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,EAAoB,EACpB,OAAyB,EAAE;IAE3B,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClE,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC"}
@@ -0,0 +1,32 @@
1
+ export declare const DEFAULT_SLOTS = 2;
2
+ export type BudgetSource = 'env' | 'config' | 'probe' | 'default';
3
+ /** The inference base URL (without a trailing /v1) for probing `/slots`. */
4
+ export declare function inferenceBase(cwd?: string): string;
5
+ export declare function headroom(cwd?: string): number;
6
+ /** Explicit slot count from env/config (no probing). */
7
+ export declare function configuredSlots(cwd?: string): number | undefined;
8
+ /** Probe a llama.cpp `/slots` endpoint; returns the slot count or null. */
9
+ export declare function probeSlots(base: string, timeoutMs?: number): Promise<number | null>;
10
+ /**
11
+ * Resolve the model-slot budget, probing the endpoint when no override is set.
12
+ * Cached for CACHE_TTL_MS. Call this once at the start of a long-running
13
+ * orchestrator (challenge run, deliver) to warm the cache for sync callers.
14
+ */
15
+ export declare function getModelSlotBudget(cwd?: string, opts?: {
16
+ probe?: boolean;
17
+ force?: boolean;
18
+ }): Promise<{
19
+ budget: number;
20
+ slots: number;
21
+ source: BudgetSource;
22
+ }>;
23
+ /** Warm the cache by probing — call at orchestrator startup. */
24
+ export declare function warmModelSlotBudget(cwd?: string): Promise<number>;
25
+ /**
26
+ * Synchronous budget for hot paths (no probe): env > config > cached probe >
27
+ * default, minus headroom. Use after warmModelSlotBudget() has populated the
28
+ * cache, or when an explicit override is set.
29
+ */
30
+ export declare function getMaxModelConcurrency(cwd?: string): number;
31
+ export declare function resetModelSlotCache(): void;
32
+ //# sourceMappingURL=model-slots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-slots.d.ts","sourceRoot":"","sources":["../../src/utils/model-slots.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,aAAa,IAAI,CAAC;AAY/B,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAoBlE,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED,wBAAgB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEhE;AAED,2EAA2E;AAC3E,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBvF;AAMD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,CAAC,EAAE,MAAM,EACZ,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9C,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC,CA6BlE;AAED,gEAAgE;AAChE,wBAAsB,mBAAmB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEvE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Model-slot budget: how many concurrent model calls the inference backend can
3
+ * actually serve. UAP's other concurrency limits are sized to CPU cores, which
4
+ * silently overruns a slot-limited server (llama.cpp `--parallel N`, or a remote
5
+ * API's concurrency ceiling) and causes timeouts / 429s / proxy doom-loops.
6
+ *
7
+ * Budget resolution (auto-detect + config override):
8
+ * 1. UAP_MODEL_SLOTS env (explicit override, no probe)
9
+ * 2. .uap.json modelConcurrency.slots (config override, no probe)
10
+ * 3. probe the endpoint's llama.cpp `/slots` (auto-detect)
11
+ * 4. DEFAULT_SLOTS (conservative fallback)
12
+ * minus `headroom`, floored at 1. Cached briefly so hot paths stay cheap.
13
+ */
14
+ import { loadUapConfigRaw } from './config-loader.js';
15
+ export const DEFAULT_SLOTS = 2; // matches llama-server-optimize's `--parallel 2`
16
+ const CACHE_TTL_MS = 30_000;
17
+ let _cache = null;
18
+ function cfg(cwd) {
19
+ try {
20
+ const raw = loadUapConfigRaw(cwd ?? process.cwd());
21
+ return raw?.modelConcurrency ?? {};
22
+ }
23
+ catch {
24
+ return {};
25
+ }
26
+ }
27
+ function intEnv(name) {
28
+ const v = process.env[name];
29
+ if (!v)
30
+ return undefined;
31
+ const n = parseInt(v, 10);
32
+ return Number.isFinite(n) && n > 0 ? n : undefined;
33
+ }
34
+ /** The inference base URL (without a trailing /v1) for probing `/slots`. */
35
+ export function inferenceBase(cwd) {
36
+ const raw = process.env.UAP_MODEL_ENDPOINT ||
37
+ process.env.UAP_INFERENCE_ENDPOINT ||
38
+ cfg(cwd).endpoint ||
39
+ 'http://localhost:8080';
40
+ return raw.replace(/\/v1\/?$/, '').replace(/\/+$/, '');
41
+ }
42
+ export function headroom(cwd) {
43
+ return intEnv('UAP_MODEL_SLOT_HEADROOM') ?? cfg(cwd).headroom ?? 0;
44
+ }
45
+ /** Explicit slot count from env/config (no probing). */
46
+ export function configuredSlots(cwd) {
47
+ return intEnv('UAP_MODEL_SLOTS') ?? cfg(cwd).slots;
48
+ }
49
+ /** Probe a llama.cpp `/slots` endpoint; returns the slot count or null. */
50
+ export async function probeSlots(base, timeoutMs = 1500) {
51
+ try {
52
+ const ctrl = new AbortController();
53
+ const t = setTimeout(() => ctrl.abort(), timeoutMs);
54
+ try {
55
+ const res = await fetch(`${base}/slots`, { signal: ctrl.signal });
56
+ if (!res.ok)
57
+ return null;
58
+ const body = (await res.json());
59
+ if (Array.isArray(body) && body.length > 0)
60
+ return body.length;
61
+ return null;
62
+ }
63
+ finally {
64
+ clearTimeout(t);
65
+ }
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
71
+ function applyHeadroom(slots, cwd) {
72
+ return Math.max(1, slots - headroom(cwd));
73
+ }
74
+ /**
75
+ * Resolve the model-slot budget, probing the endpoint when no override is set.
76
+ * Cached for CACHE_TTL_MS. Call this once at the start of a long-running
77
+ * orchestrator (challenge run, deliver) to warm the cache for sync callers.
78
+ */
79
+ export async function getModelSlotBudget(cwd, opts = {}) {
80
+ if (!opts.force && _cache && Date.now() - _cache.at < CACHE_TTL_MS) {
81
+ return { budget: _cache.budget, slots: _cache.slots, source: _cache.source };
82
+ }
83
+ let slots;
84
+ let source;
85
+ const explicit = configuredSlots(cwd);
86
+ if (intEnv('UAP_MODEL_SLOTS') !== undefined) {
87
+ slots = explicit;
88
+ source = 'env';
89
+ }
90
+ else if (explicit !== undefined) {
91
+ slots = explicit;
92
+ source = 'config';
93
+ }
94
+ else if (opts.probe !== false) {
95
+ const probed = await probeSlots(inferenceBase(cwd));
96
+ if (probed !== null) {
97
+ slots = probed;
98
+ source = 'probe';
99
+ }
100
+ else {
101
+ slots = DEFAULT_SLOTS;
102
+ source = 'default';
103
+ }
104
+ }
105
+ else {
106
+ slots = DEFAULT_SLOTS;
107
+ source = 'default';
108
+ }
109
+ const budget = applyHeadroom(slots, cwd);
110
+ _cache = { budget, slots, source, at: Date.now() };
111
+ return { budget, slots, source };
112
+ }
113
+ /** Warm the cache by probing — call at orchestrator startup. */
114
+ export async function warmModelSlotBudget(cwd) {
115
+ return (await getModelSlotBudget(cwd, { probe: true, force: true })).budget;
116
+ }
117
+ /**
118
+ * Synchronous budget for hot paths (no probe): env > config > cached probe >
119
+ * default, minus headroom. Use after warmModelSlotBudget() has populated the
120
+ * cache, or when an explicit override is set.
121
+ */
122
+ export function getMaxModelConcurrency(cwd) {
123
+ const explicit = configuredSlots(cwd);
124
+ if (explicit !== undefined)
125
+ return applyHeadroom(explicit, cwd);
126
+ if (_cache && Date.now() - _cache.at < CACHE_TTL_MS)
127
+ return _cache.budget;
128
+ return applyHeadroom(DEFAULT_SLOTS, cwd);
129
+ }
130
+ export function resetModelSlotCache() {
131
+ _cache = null;
132
+ }
133
+ //# sourceMappingURL=model-slots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-slots.js","sourceRoot":"","sources":["../../src/utils/model-slots.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miller-tech/uap",
3
- "version": "1.72.1",
3
+ "version": "1.74.0",
4
4
  "description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",