nexus-ai-pro 2.0.0 → 2.2.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/API_STABILITY.md +65 -0
- package/CHANGELOG.md +267 -1
- package/MIGRATING.md +1 -1
- package/README.md +17 -8
- package/dist/agent/create-agent.d.ts +9 -1
- package/dist/agent/create-agent.js +40 -1
- package/dist/cache/memory-cache.d.ts +8 -0
- package/dist/cache/memory-cache.js +9 -0
- package/dist/cache/semantic-cache.d.ts +6 -3
- package/dist/cache/semantic-cache.js +5 -2
- package/dist/cli/args.js +3 -0
- package/dist/cli/db.d.ts +16 -4
- package/dist/cli/db.js +169 -22
- package/dist/cli/doctor.d.ts +17 -0
- package/dist/cli/doctor.js +53 -0
- package/dist/cli/graph.d.ts +9 -0
- package/dist/cli/graph.js +47 -0
- package/dist/cli.js +21 -2
- package/dist/core/lifecycle.js +11 -6
- package/dist/core/nexus.d.ts +12 -2
- package/dist/core/nexus.js +106 -23
- package/dist/doctor/index.d.ts +90 -0
- package/dist/doctor/index.js +237 -0
- package/dist/evals/judge.d.ts +11 -0
- package/dist/evals/judge.js +33 -0
- package/dist/evaluate/index.d.ts +1 -0
- package/dist/evaluate/index.js +1 -0
- package/dist/evaluate/provenance.d.ts +22 -0
- package/dist/evaluate/provenance.js +10 -0
- package/dist/evaluate/run.js +20 -4
- package/dist/graph/durability.d.ts +27 -0
- package/dist/graph/durability.js +66 -0
- package/dist/graph/errors.d.ts +30 -4
- package/dist/graph/errors.js +18 -2
- package/dist/graph/event-stream.d.ts +75 -0
- package/dist/graph/event-stream.js +289 -0
- package/dist/graph/functional.d.ts +80 -7
- package/dist/graph/functional.js +138 -35
- package/dist/graph/graph.d.ts +56 -8
- package/dist/graph/graph.js +331 -49
- package/dist/graph/index.d.ts +4 -2
- package/dist/graph/index.js +3 -1
- package/dist/graph/lint.d.ts +57 -0
- package/dist/graph/lint.js +141 -0
- package/dist/graph/run-control.d.ts +28 -0
- package/dist/graph/run-control.js +26 -0
- package/dist/images/evals.js +4 -2
- package/dist/operations/adapters.d.ts +52 -4
- package/dist/operations/adapters.js +194 -7
- package/dist/operations/runner.js +14 -15
- package/dist/operations/stats.js +8 -1
- package/dist/operations/store.d.ts +5 -1
- package/dist/operations/store.js +7 -0
- package/dist/ops/circuit-breaker.d.ts +52 -0
- package/dist/ops/circuit-breaker.js +4 -0
- package/dist/ops/circuit-store.d.ts +13 -2
- package/dist/ops/circuit-store.js +68 -0
- package/dist/ops/circuit-sync.d.ts +17 -0
- package/dist/ops/circuit-sync.js +86 -0
- package/dist/ops/health.d.ts +24 -0
- package/dist/ops/health.js +38 -10
- package/dist/ops/index.d.ts +1 -1
- package/dist/ops/index.js +1 -1
- package/dist/ops/rate-limit-adapters.d.ts +23 -0
- package/dist/ops/rate-limit-adapters.js +34 -0
- package/dist/ops/rate-limiter.d.ts +14 -2
- package/dist/ops/rate-limiter.js +31 -0
- package/dist/postgres/circuits.d.ts +21 -4
- package/dist/postgres/circuits.js +65 -4
- package/dist/postgres/client.d.ts +0 -2
- package/dist/postgres/client.js +0 -4
- package/dist/postgres/evaluate.d.ts +16 -4
- package/dist/postgres/evaluate.js +17 -5
- package/dist/postgres/index.d.ts +32 -11
- package/dist/postgres/index.js +65 -31
- package/dist/postgres/migrations.d.ts +60 -0
- package/dist/postgres/migrations.js +121 -0
- package/dist/postgres/operations.d.ts +14 -3
- package/dist/postgres/operations.js +45 -15
- package/dist/postgres/prompts.d.ts +11 -2
- package/dist/postgres/prompts.js +14 -3
- package/dist/postgres/rollups.d.ts +35 -0
- package/dist/postgres/rollups.js +129 -0
- package/dist/postgres/store.d.ts +11 -2
- package/dist/postgres/store.js +14 -3
- package/dist/postgres/traces.d.ts +13 -3
- package/dist/postgres/traces.js +25 -3
- package/dist/postgres/vectors.d.ts +11 -2
- package/dist/postgres/vectors.js +14 -3
- package/dist/router/auto-router.d.ts +34 -7
- package/dist/router/auto-router.js +201 -68
- package/dist/server/assistant.d.ts +44 -0
- package/dist/server/assistant.js +39 -0
- package/dist/server/errors.d.ts +12 -0
- package/dist/server/errors.js +7 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/runs.d.ts +28 -1
- package/dist/server/runs.js +110 -14
- package/dist/sqlite/index.d.ts +16 -3
- package/dist/sqlite/index.js +16 -3
- package/dist/sqlite/migrations.d.ts +26 -0
- package/dist/sqlite/migrations.js +63 -0
- package/dist/sqlite/operations.d.ts +14 -3
- package/dist/sqlite/operations.js +42 -15
- package/dist/sqlite/store.d.ts +9 -2
- package/dist/sqlite/store.js +13 -3
- package/dist/sqlite/vectors.d.ts +11 -2
- package/dist/sqlite/vectors.js +13 -2
- package/dist/store/tenant.d.ts +12 -0
- package/dist/store/tenant.js +29 -0
- package/dist/tenancy/index.d.ts +113 -0
- package/dist/tenancy/index.js +233 -0
- package/dist/testing/record.d.ts +42 -0
- package/dist/testing/record.js +57 -5
- package/dist/tracing/index.d.ts +3 -3
- package/dist/tracing/index.js +2 -2
- package/dist/tracing/instrument.js +30 -0
- package/dist/tracing/otlp.d.ts +91 -0
- package/dist/tracing/otlp.js +124 -0
- package/dist/tracing/rollups.d.ts +100 -0
- package/dist/tracing/rollups.js +139 -0
- package/dist/tracing/stores.d.ts +17 -0
- package/dist/tracing/stores.js +23 -0
- package/dist/tracing/tracer.d.ts +50 -4
- package/dist/tracing/tracer.js +85 -6
- package/dist/types/config.d.ts +33 -2
- package/dist/types/evaluate.d.ts +37 -0
- package/dist/types/graph.d.ts +354 -9
- package/dist/types/graph.js +3 -1
- package/dist/types/messages.d.ts +5 -0
- package/dist/types/operations.d.ts +22 -2
- package/dist/types/response.d.ts +20 -0
- package/dist/types/server.d.ts +18 -0
- package/dist/types/tracing.d.ts +11 -0
- package/dist/utils/schema-migrations.d.ts +97 -0
- package/dist/utils/schema-migrations.js +91 -0
- package/dist/utils/signals.d.ts +17 -0
- package/dist/utils/signals.js +26 -0
- package/dist/utils/tenant.d.ts +14 -0
- package/dist/utils/tenant.js +16 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.js +1 -0
- package/dist-cjs/agent/create-agent.d.ts +9 -1
- package/dist-cjs/agent/create-agent.js +40 -1
- package/dist-cjs/cache/memory-cache.d.ts +8 -0
- package/dist-cjs/cache/memory-cache.js +9 -0
- package/dist-cjs/cache/semantic-cache.d.ts +6 -3
- package/dist-cjs/cache/semantic-cache.js +5 -2
- package/dist-cjs/cli/args.js +3 -0
- package/dist-cjs/cli/db.d.ts +16 -4
- package/dist-cjs/cli/db.js +200 -20
- package/dist-cjs/cli/doctor.d.ts +17 -0
- package/dist-cjs/cli/doctor.js +56 -0
- package/dist-cjs/cli/graph.d.ts +9 -0
- package/dist-cjs/cli/graph.js +50 -0
- package/dist-cjs/core/lifecycle.js +11 -6
- package/dist-cjs/core/nexus.d.ts +12 -2
- package/dist-cjs/core/nexus.js +106 -23
- package/dist-cjs/doctor/index.d.ts +90 -0
- package/dist-cjs/doctor/index.js +276 -0
- package/dist-cjs/evals/judge.d.ts +11 -0
- package/dist-cjs/evals/judge.js +33 -0
- package/dist-cjs/evaluate/index.d.ts +1 -0
- package/dist-cjs/evaluate/index.js +3 -1
- package/dist-cjs/evaluate/provenance.d.ts +22 -0
- package/dist-cjs/evaluate/provenance.js +14 -0
- package/dist-cjs/evaluate/run.js +20 -4
- package/dist-cjs/graph/durability.d.ts +27 -0
- package/dist-cjs/graph/durability.js +70 -0
- package/dist-cjs/graph/errors.d.ts +30 -4
- package/dist-cjs/graph/errors.js +20 -3
- package/dist-cjs/graph/event-stream.d.ts +75 -0
- package/dist-cjs/graph/event-stream.js +295 -0
- package/dist-cjs/graph/functional.d.ts +80 -7
- package/dist-cjs/graph/functional.js +137 -34
- package/dist-cjs/graph/graph.d.ts +56 -8
- package/dist-cjs/graph/graph.js +330 -48
- package/dist-cjs/graph/index.d.ts +4 -2
- package/dist-cjs/graph/index.js +7 -1
- package/dist-cjs/graph/lint.d.ts +57 -0
- package/dist-cjs/graph/lint.js +144 -0
- package/dist-cjs/graph/run-control.d.ts +28 -0
- package/dist-cjs/graph/run-control.js +30 -0
- package/dist-cjs/images/evals.js +4 -2
- package/dist-cjs/operations/adapters.d.ts +52 -4
- package/dist-cjs/operations/adapters.js +193 -6
- package/dist-cjs/operations/runner.js +14 -15
- package/dist-cjs/operations/stats.js +8 -1
- package/dist-cjs/operations/store.d.ts +5 -1
- package/dist-cjs/operations/store.js +7 -0
- package/dist-cjs/ops/circuit-breaker.d.ts +52 -0
- package/dist-cjs/ops/circuit-breaker.js +4 -0
- package/dist-cjs/ops/circuit-store.d.ts +13 -2
- package/dist-cjs/ops/circuit-store.js +68 -0
- package/dist-cjs/ops/circuit-sync.d.ts +17 -0
- package/dist-cjs/ops/circuit-sync.js +87 -0
- package/dist-cjs/ops/health.d.ts +24 -0
- package/dist-cjs/ops/health.js +38 -10
- package/dist-cjs/ops/index.d.ts +1 -1
- package/dist-cjs/ops/rate-limit-adapters.d.ts +23 -0
- package/dist-cjs/ops/rate-limit-adapters.js +35 -1
- package/dist-cjs/ops/rate-limiter.d.ts +14 -2
- package/dist-cjs/ops/rate-limiter.js +32 -0
- package/dist-cjs/postgres/circuits.d.ts +21 -4
- package/dist-cjs/postgres/circuits.js +98 -3
- package/dist-cjs/postgres/client.d.ts +0 -2
- package/dist-cjs/postgres/client.js +0 -5
- package/dist-cjs/postgres/evaluate.d.ts +16 -4
- package/dist-cjs/postgres/evaluate.js +50 -4
- package/dist-cjs/postgres/index.d.ts +32 -11
- package/dist-cjs/postgres/index.js +69 -20
- package/dist-cjs/postgres/migrations.d.ts +60 -0
- package/dist-cjs/postgres/migrations.js +129 -0
- package/dist-cjs/postgres/operations.d.ts +14 -3
- package/dist-cjs/postgres/operations.js +78 -14
- package/dist-cjs/postgres/prompts.d.ts +11 -2
- package/dist-cjs/postgres/prompts.js +47 -2
- package/dist-cjs/postgres/rollups.d.ts +35 -0
- package/dist-cjs/postgres/rollups.js +168 -0
- package/dist-cjs/postgres/store.d.ts +11 -2
- package/dist-cjs/postgres/store.js +47 -2
- package/dist-cjs/postgres/traces.d.ts +13 -3
- package/dist-cjs/postgres/traces.js +58 -2
- package/dist-cjs/postgres/vectors.d.ts +11 -2
- package/dist-cjs/postgres/vectors.js +47 -2
- package/dist-cjs/router/auto-router.d.ts +34 -7
- package/dist-cjs/router/auto-router.js +201 -68
- package/dist-cjs/server/assistant.d.ts +44 -0
- package/dist-cjs/server/assistant.js +39 -0
- package/dist-cjs/server/errors.d.ts +12 -0
- package/dist-cjs/server/errors.js +9 -1
- package/dist-cjs/server/index.d.ts +1 -1
- package/dist-cjs/server/index.js +2 -1
- package/dist-cjs/server/runs.d.ts +28 -1
- package/dist-cjs/server/runs.js +109 -13
- package/dist-cjs/sqlite/index.d.ts +16 -3
- package/dist-cjs/sqlite/index.js +31 -10
- package/dist-cjs/sqlite/migrations.d.ts +26 -0
- package/dist-cjs/sqlite/migrations.js +71 -0
- package/dist-cjs/sqlite/operations.d.ts +14 -3
- package/dist-cjs/sqlite/operations.js +76 -15
- package/dist-cjs/sqlite/store.d.ts +9 -2
- package/dist-cjs/sqlite/store.js +47 -3
- package/dist-cjs/sqlite/vectors.d.ts +11 -2
- package/dist-cjs/sqlite/vectors.js +47 -2
- package/dist-cjs/store/tenant.d.ts +12 -0
- package/dist-cjs/store/tenant.js +33 -0
- package/dist-cjs/tenancy/index.d.ts +113 -0
- package/dist-cjs/tenancy/index.js +250 -0
- package/dist-cjs/testing/record.d.ts +42 -0
- package/dist-cjs/testing/record.js +57 -5
- package/dist-cjs/tracing/index.d.ts +3 -3
- package/dist-cjs/tracing/index.js +4 -1
- package/dist-cjs/tracing/instrument.js +30 -0
- package/dist-cjs/tracing/otlp.d.ts +91 -0
- package/dist-cjs/tracing/otlp.js +129 -0
- package/dist-cjs/tracing/rollups.d.ts +100 -0
- package/dist-cjs/tracing/rollups.js +147 -0
- package/dist-cjs/tracing/stores.d.ts +17 -0
- package/dist-cjs/tracing/stores.js +24 -0
- package/dist-cjs/tracing/tracer.d.ts +50 -4
- package/dist-cjs/tracing/tracer.js +87 -6
- package/dist-cjs/types/config.d.ts +33 -2
- package/dist-cjs/types/evaluate.d.ts +37 -0
- package/dist-cjs/types/graph.d.ts +354 -9
- package/dist-cjs/types/graph.js +3 -1
- package/dist-cjs/types/messages.d.ts +5 -0
- package/dist-cjs/types/operations.d.ts +22 -2
- package/dist-cjs/types/response.d.ts +20 -0
- package/dist-cjs/types/server.d.ts +18 -0
- package/dist-cjs/types/tracing.d.ts +11 -0
- package/dist-cjs/utils/schema-migrations.d.ts +97 -0
- package/dist-cjs/utils/schema-migrations.js +102 -0
- package/dist-cjs/utils/signals.d.ts +17 -0
- package/dist-cjs/utils/signals.js +29 -0
- package/dist-cjs/utils/tenant.d.ts +14 -0
- package/dist-cjs/utils/tenant.js +22 -0
- package/dist-cjs/version.d.ts +5 -0
- package/dist-cjs/version.js +4 -0
- package/llms.txt +4 -3
- package/package.json +110 -2
|
@@ -3,38 +3,140 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AutoRouter = void 0;
|
|
4
4
|
exports.routeDirectModel = routeDirectModel;
|
|
5
5
|
const registry_js_1 = require("../models/registry.js");
|
|
6
|
+
const PLAN_LIMIT = 16;
|
|
7
|
+
const BOOLEAN_CAPABILITIES = ['streaming', 'toolCalling', 'structuredOutputs', 'jsonMode', 'reasoning'];
|
|
6
8
|
class AutoRouter {
|
|
9
|
+
plans = new Map();
|
|
10
|
+
patterns = new Map();
|
|
11
|
+
registryIds = new WeakMap();
|
|
7
12
|
route(ctx) {
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
score: this.score(candidate.model, strategy, ctx.config, ctx.providers.get(candidate.providerName)?.info?.isLocal === true) +
|
|
12
|
-
candidate.weight +
|
|
13
|
-
this.healthScore(candidate.providerName, ctx),
|
|
14
|
-
reason: `auto route by ${strategy} score`,
|
|
15
|
-
}));
|
|
16
|
-
candidates.sort((a, b) => b.score - a.score);
|
|
17
|
-
const winner = candidates[0];
|
|
13
|
+
const plan = this.plan(ctx);
|
|
14
|
+
const ranked = this.rank(plan, ctx);
|
|
15
|
+
const winner = ranked[0];
|
|
18
16
|
if (!winner) {
|
|
19
17
|
throw new Error('No configured providers are available for routing');
|
|
20
18
|
}
|
|
21
19
|
return {
|
|
22
20
|
providerName: winner.providerName,
|
|
23
21
|
model: winner.model,
|
|
24
|
-
reason:
|
|
25
|
-
fallbacks:
|
|
22
|
+
reason: `auto route by ${plan.strategy} score: ${winner.model}`,
|
|
23
|
+
fallbacks: ranked.slice(1).map((candidate) => candidate.attempt),
|
|
26
24
|
};
|
|
27
25
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
26
|
+
get planCount() {
|
|
27
|
+
return this.plans.size;
|
|
28
|
+
}
|
|
29
|
+
plan(ctx) {
|
|
30
|
+
const key = this.planKey(ctx);
|
|
31
|
+
const cached = this.plans.get(key);
|
|
32
|
+
if (cached) {
|
|
33
|
+
this.plans.delete(key);
|
|
34
|
+
this.plans.set(key, cached);
|
|
35
|
+
return cached;
|
|
36
|
+
}
|
|
37
|
+
const plan = this.buildPlan(ctx);
|
|
38
|
+
this.plans.set(key, plan);
|
|
39
|
+
if (this.plans.size > PLAN_LIMIT)
|
|
40
|
+
this.plans.delete(this.plans.keys().next().value);
|
|
41
|
+
return plan;
|
|
42
|
+
}
|
|
43
|
+
planKey(ctx) {
|
|
44
|
+
const routing = ctx.config.routing;
|
|
45
|
+
const models = ctx.config.models;
|
|
46
|
+
const providers = [];
|
|
47
|
+
for (const [name, provider] of ctx.providers)
|
|
48
|
+
providers.push(`${name}${provider.info?.isLocal === true ? '+local' : ''}`);
|
|
49
|
+
return JSON.stringify([
|
|
50
|
+
routing?.strategy ?? 'quality',
|
|
51
|
+
routing?.candidateModels ?? null,
|
|
52
|
+
routing?.modelPreferences ?? null,
|
|
53
|
+
routing?.allowModels ?? null,
|
|
54
|
+
routing?.denyModels ?? null,
|
|
55
|
+
normalizedRequirements(routing?.requiredCapabilities),
|
|
56
|
+
models?.includeDefaults ?? null,
|
|
57
|
+
models?.aliases ?? null,
|
|
58
|
+
models?.registry ? this.registryId(models.registry) : 0,
|
|
59
|
+
providers,
|
|
60
|
+
]);
|
|
34
61
|
}
|
|
35
|
-
|
|
62
|
+
registryId(registry) {
|
|
63
|
+
let id = this.registryIds.get(registry);
|
|
64
|
+
if (id === undefined) {
|
|
65
|
+
id = this.registryIds.get(this.registryIds) ?? 1;
|
|
66
|
+
this.registryIds.set(registry, id);
|
|
67
|
+
this.registryIds.set(this.registryIds, id + 1);
|
|
68
|
+
}
|
|
69
|
+
return id;
|
|
70
|
+
}
|
|
71
|
+
buildPlan(ctx) {
|
|
72
|
+
const strategy = ctx.config.routing?.strategy || 'quality';
|
|
73
|
+
const registry = (0, registry_js_1.getModelRegistry)(ctx.config);
|
|
74
|
+
const requirements = compileRequirements(ctx.config.routing?.requiredCapabilities);
|
|
75
|
+
const candidates = this.getCandidates(ctx, registry, requirements);
|
|
76
|
+
const planned = candidates.map((candidate, index) => ({
|
|
77
|
+
providerName: candidate.providerName,
|
|
78
|
+
model: candidate.model,
|
|
79
|
+
base: this.score(candidate.model, strategy, registry, ctx.providers.get(candidate.providerName)?.info?.isLocal === true) + candidate.weight,
|
|
80
|
+
index,
|
|
81
|
+
attempt: Object.freeze({ providerName: candidate.providerName, model: candidate.model }),
|
|
82
|
+
}));
|
|
83
|
+
const ranked = [...planned].sort(byScore);
|
|
84
|
+
const byProvider = new Map();
|
|
85
|
+
for (const candidate of ranked) {
|
|
86
|
+
const list = byProvider.get(candidate.providerName);
|
|
87
|
+
if (list)
|
|
88
|
+
list.push(candidate);
|
|
89
|
+
else
|
|
90
|
+
byProvider.set(candidate.providerName, [candidate]);
|
|
91
|
+
}
|
|
92
|
+
return { strategy, ranked, byProvider };
|
|
93
|
+
}
|
|
94
|
+
rank(plan, ctx) {
|
|
95
|
+
let excluded;
|
|
96
|
+
if (ctx.openCircuits?.length) {
|
|
97
|
+
const open = new Set(ctx.openCircuits);
|
|
98
|
+
if (plan.ranked.some((candidate) => !open.has(candidate.providerName)))
|
|
99
|
+
excluded = open;
|
|
100
|
+
}
|
|
101
|
+
const offsets = this.healthOffsets(ctx);
|
|
102
|
+
if (!offsets) {
|
|
103
|
+
return excluded ? plan.ranked.filter((candidate) => !excluded.has(candidate.providerName)) : plan.ranked;
|
|
104
|
+
}
|
|
105
|
+
const lists = [];
|
|
106
|
+
let total = 0;
|
|
107
|
+
for (const [providerName, list] of plan.byProvider) {
|
|
108
|
+
if (excluded?.has(providerName))
|
|
109
|
+
continue;
|
|
110
|
+
lists.push({ list, offset: offsets.get(providerName) ?? 0, at: 0 });
|
|
111
|
+
total += list.length;
|
|
112
|
+
}
|
|
113
|
+
const merged = new Array(total);
|
|
114
|
+
for (let position = 0; position < total; position += 1) {
|
|
115
|
+
let best = -1;
|
|
116
|
+
let bestScore = Number.NEGATIVE_INFINITY;
|
|
117
|
+
let bestIndex = Number.POSITIVE_INFINITY;
|
|
118
|
+
for (let which = 0; which < lists.length; which += 1) {
|
|
119
|
+
const head = lists[which];
|
|
120
|
+
const candidate = head.list[head.at];
|
|
121
|
+
if (!candidate)
|
|
122
|
+
continue;
|
|
123
|
+
const score = candidate.base + head.offset;
|
|
124
|
+
if (score > bestScore || (score === bestScore && candidate.index < bestIndex)) {
|
|
125
|
+
best = which;
|
|
126
|
+
bestScore = score;
|
|
127
|
+
bestIndex = candidate.index;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const chosen = lists[best];
|
|
131
|
+
merged[position] = chosen.list[chosen.at];
|
|
132
|
+
chosen.at += 1;
|
|
133
|
+
}
|
|
134
|
+
return merged;
|
|
135
|
+
}
|
|
136
|
+
getCandidates(ctx, registry, requirements) {
|
|
36
137
|
const candidates = [];
|
|
37
138
|
const configuredModels = ctx.config.routing?.candidateModels;
|
|
139
|
+
const passes = (model) => !requirements || this.matchesRequirements(model, registry, requirements);
|
|
38
140
|
if (configuredModels?.length) {
|
|
39
141
|
for (const model of configuredModels) {
|
|
40
142
|
const resolved = (0, registry_js_1.resolveModel)(model, ctx.config);
|
|
@@ -43,23 +145,19 @@ class AutoRouter {
|
|
|
43
145
|
candidates.push({ providerName, model: resolved.model, weight: 0 });
|
|
44
146
|
}
|
|
45
147
|
}
|
|
46
|
-
return candidates.filter((candidate) =>
|
|
148
|
+
return candidates.filter((candidate) => passes(candidate.model));
|
|
47
149
|
}
|
|
48
150
|
const preferences = ctx.config.routing?.modelPreferences?.[ctx.config.routing?.strategy || 'quality'];
|
|
49
151
|
for (const providerName of ctx.providers.keys()) {
|
|
50
|
-
const preferred = this.preferencesForProvider(providerName, preferences, ctx.config);
|
|
152
|
+
const preferred = this.preferencesForProvider(providerName, preferences, ctx.config, registry);
|
|
51
153
|
if (preferred.length) {
|
|
52
154
|
candidates.push(...preferred);
|
|
53
155
|
}
|
|
54
156
|
}
|
|
55
|
-
return candidates.filter((candidate) =>
|
|
56
|
-
return this.isAllowed(candidate.model, ctx.config) && this.matchesRequirements(candidate.model, ctx.config);
|
|
57
|
-
});
|
|
157
|
+
return candidates.filter((candidate) => this.isAllowed(candidate.model, ctx.config) && passes(candidate.model));
|
|
58
158
|
}
|
|
59
|
-
score(model, strategy,
|
|
60
|
-
const
|
|
61
|
-
const normalized = model.startsWith('ollama/') ? model.slice(7) : model;
|
|
62
|
-
const caps = registry[model] || registry[normalized] || this.localFallbackCapabilities(model);
|
|
159
|
+
score(model, strategy, registry, providerIsLocal = false) {
|
|
160
|
+
const caps = this.capabilitiesOf(model, registry);
|
|
63
161
|
if (strategy === 'privacy')
|
|
64
162
|
return providerIsLocal || isLocalModel(model) ? 100 : 30;
|
|
65
163
|
if (strategy === 'speed')
|
|
@@ -68,6 +166,10 @@ class AutoRouter {
|
|
|
68
166
|
return this.costScore(model, caps);
|
|
69
167
|
return this.qualityScore(model, caps);
|
|
70
168
|
}
|
|
169
|
+
capabilitiesOf(model, registry) {
|
|
170
|
+
const normalized = model.startsWith('ollama/') ? model.slice(7) : model;
|
|
171
|
+
return registry[model] || registry[normalized] || this.localFallbackCapabilities(model);
|
|
172
|
+
}
|
|
71
173
|
localFallbackCapabilities(model) {
|
|
72
174
|
return {
|
|
73
175
|
inputModalities: ['text'],
|
|
@@ -113,7 +215,7 @@ class AutoRouter {
|
|
|
113
215
|
return 65;
|
|
114
216
|
return Math.min(85, caps.maxContextTokens / 2000);
|
|
115
217
|
}
|
|
116
|
-
preferencesForProvider(providerName, preferences, config) {
|
|
218
|
+
preferencesForProvider(providerName, preferences, config, registry) {
|
|
117
219
|
if (preferences?.length) {
|
|
118
220
|
return preferences
|
|
119
221
|
.map((preference) => typeof preference === 'string'
|
|
@@ -132,7 +234,7 @@ class AutoRouter {
|
|
|
132
234
|
const registryModels = (0, registry_js_1.listModelsForProvider)(providerName, config);
|
|
133
235
|
if (registryModels.length) {
|
|
134
236
|
return registryModels
|
|
135
|
-
.filter((model) => this.isProviderRunnable(providerName, model,
|
|
237
|
+
.filter((model) => this.isProviderRunnable(providerName, model, registry))
|
|
136
238
|
.map((model) => ({ providerName, model, weight: 0 }));
|
|
137
239
|
}
|
|
138
240
|
if (providerName === 'ollama') {
|
|
@@ -173,52 +275,44 @@ class AutoRouter {
|
|
|
173
275
|
return false;
|
|
174
276
|
return !deny.some((entry) => this.matchesModelPattern(model, entry));
|
|
175
277
|
}
|
|
176
|
-
matchesRequirements(model,
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const registry = (0, registry_js_1.getModelRegistry)(config);
|
|
181
|
-
const normalized = model.startsWith('ollama/') ? model.slice(7) : model;
|
|
182
|
-
const caps = registry[model] || registry[normalized] || this.localFallbackCapabilities(model);
|
|
183
|
-
if (requirements.streaming !== undefined && caps.streaming !== requirements.streaming)
|
|
184
|
-
return false;
|
|
185
|
-
if (requirements.toolCalling !== undefined && caps.toolCalling !== requirements.toolCalling)
|
|
186
|
-
return false;
|
|
187
|
-
if (requirements.structuredOutputs !== undefined && caps.structuredOutputs !== requirements.structuredOutputs)
|
|
278
|
+
matchesRequirements(model, registry, requirements) {
|
|
279
|
+
const caps = this.capabilitiesOf(model, registry);
|
|
280
|
+
const { mustBe, mustNotBe } = capabilityMasks(caps);
|
|
281
|
+
if ((mustBe & requirements.mustBe) !== requirements.mustBe)
|
|
188
282
|
return false;
|
|
189
|
-
if (
|
|
283
|
+
if ((mustNotBe & requirements.mustNotBe) !== requirements.mustNotBe)
|
|
190
284
|
return false;
|
|
191
|
-
|
|
285
|
+
const source = requirements.source;
|
|
286
|
+
if (source.minContextTokens && caps.maxContextTokens < source.minContextTokens)
|
|
192
287
|
return false;
|
|
193
|
-
if (
|
|
288
|
+
if (source.maxInputCostPer1k !== undefined && caps.costPer1kInput > source.maxInputCostPer1k)
|
|
194
289
|
return false;
|
|
195
|
-
if (
|
|
290
|
+
if (source.maxOutputCostPer1k !== undefined && caps.costPer1kOutput > source.maxOutputCostPer1k)
|
|
196
291
|
return false;
|
|
197
|
-
if (
|
|
292
|
+
if (source.statuses?.length && caps.status && !source.statuses.includes(caps.status))
|
|
198
293
|
return false;
|
|
199
|
-
if (
|
|
294
|
+
if (source.inputModalities?.some((modality) => !caps.inputModalities.includes(modality)))
|
|
200
295
|
return false;
|
|
201
|
-
if (
|
|
202
|
-
return false;
|
|
203
|
-
if (requirements.outputModalities?.some((modality) => !caps.outputModalities.includes(modality)))
|
|
296
|
+
if (source.outputModalities?.some((modality) => !caps.outputModalities.includes(modality)))
|
|
204
297
|
return false;
|
|
205
298
|
return true;
|
|
206
299
|
}
|
|
207
300
|
matchesModelPattern(model, pattern) {
|
|
208
301
|
if (pattern === model)
|
|
209
302
|
return true;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
303
|
+
let regex = this.patterns.get(pattern);
|
|
304
|
+
if (regex === undefined) {
|
|
305
|
+
regex = pattern.includes('*')
|
|
306
|
+
? new RegExp(`^${pattern
|
|
307
|
+
.split('*')
|
|
308
|
+
.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
309
|
+
.join('.*')}$`)
|
|
310
|
+
: null;
|
|
311
|
+
this.patterns.set(pattern, regex);
|
|
312
|
+
}
|
|
313
|
+
return regex ? regex.test(model) : false;
|
|
219
314
|
}
|
|
220
|
-
isProviderRunnable(providerName, model,
|
|
221
|
-
const registry = (0, registry_js_1.getModelRegistry)(config);
|
|
315
|
+
isProviderRunnable(providerName, model, registry) {
|
|
222
316
|
const caps = registry[model];
|
|
223
317
|
if (!caps?.endpoints)
|
|
224
318
|
return true;
|
|
@@ -230,16 +324,55 @@ class AutoRouter {
|
|
|
230
324
|
return caps.endpoints.includes('generateContent');
|
|
231
325
|
return true;
|
|
232
326
|
}
|
|
233
|
-
|
|
327
|
+
healthOffsets(ctx) {
|
|
234
328
|
if (!ctx.config.health?.enabled || !ctx.health?.length)
|
|
235
|
-
return
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
329
|
+
return undefined;
|
|
330
|
+
const offsets = new Map();
|
|
331
|
+
for (const snapshot of ctx.health) {
|
|
332
|
+
if (offsets.has(snapshot.providerName))
|
|
333
|
+
continue;
|
|
334
|
+
offsets.set(snapshot.providerName, snapshot.healthy ? snapshot.score / 10 : -100);
|
|
335
|
+
}
|
|
336
|
+
return offsets;
|
|
240
337
|
}
|
|
241
338
|
}
|
|
242
339
|
exports.AutoRouter = AutoRouter;
|
|
340
|
+
function compileRequirements(requirements) {
|
|
341
|
+
if (!requirements)
|
|
342
|
+
return undefined;
|
|
343
|
+
let mustBe = 0;
|
|
344
|
+
let mustNotBe = 0;
|
|
345
|
+
BOOLEAN_CAPABILITIES.forEach((name, bit) => {
|
|
346
|
+
const wanted = requirements[name];
|
|
347
|
+
if (wanted === true)
|
|
348
|
+
mustBe |= 1 << bit;
|
|
349
|
+
else if (wanted === false)
|
|
350
|
+
mustNotBe |= 1 << bit;
|
|
351
|
+
});
|
|
352
|
+
return { mustBe, mustNotBe, source: requirements };
|
|
353
|
+
}
|
|
354
|
+
function capabilityMasks(caps) {
|
|
355
|
+
let mustBe = 0;
|
|
356
|
+
let mustNotBe = 0;
|
|
357
|
+
BOOLEAN_CAPABILITIES.forEach((name, bit) => {
|
|
358
|
+
const value = name === 'reasoning' ? Boolean(caps.reasoning) : caps[name];
|
|
359
|
+
if (value === true)
|
|
360
|
+
mustBe |= 1 << bit;
|
|
361
|
+
else if (value === false)
|
|
362
|
+
mustNotBe |= 1 << bit;
|
|
363
|
+
});
|
|
364
|
+
return { mustBe, mustNotBe };
|
|
365
|
+
}
|
|
366
|
+
function normalizedRequirements(requirements) {
|
|
367
|
+
if (!requirements)
|
|
368
|
+
return null;
|
|
369
|
+
return Object.keys(requirements)
|
|
370
|
+
.sort()
|
|
371
|
+
.map((key) => [key, requirements[key]]);
|
|
372
|
+
}
|
|
373
|
+
function byScore(a, b) {
|
|
374
|
+
return b.base - a.base || a.index - b.index;
|
|
375
|
+
}
|
|
243
376
|
function isLocalModel(model) {
|
|
244
377
|
return (model.startsWith('ollama/') ||
|
|
245
378
|
model.startsWith('lmstudio/') ||
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { GraphStreamProjection } from '../types/graph.js';
|
|
1
2
|
import type { AssistantRunContext, ServerAssistant } from '../types/server.js';
|
|
2
3
|
/**
|
|
3
4
|
* The part of a compiled graph the adapter uses.
|
|
@@ -11,11 +12,15 @@ export interface GraphLike {
|
|
|
11
12
|
threadId?: string;
|
|
12
13
|
signal?: AbortSignal;
|
|
13
14
|
metadata?: Record<string, unknown>;
|
|
15
|
+
tenantId?: string;
|
|
16
|
+
control?: DrainSwitch;
|
|
14
17
|
}): AsyncIterable<unknown>;
|
|
15
18
|
/** Answers an interrupt and continues the thread. */
|
|
16
19
|
resume(threadId: string, value: unknown, options: {
|
|
17
20
|
signal?: AbortSignal;
|
|
18
21
|
metadata?: Record<string, unknown>;
|
|
22
|
+
tenantId?: string;
|
|
23
|
+
control?: DrainSwitch;
|
|
19
24
|
}): AsyncIterable<unknown>;
|
|
20
25
|
/** The thread's checkpoint, at its latest step or at one given. */
|
|
21
26
|
state(threadId: string, step?: number): Promise<{
|
|
@@ -28,18 +33,56 @@ export interface GraphLike {
|
|
|
28
33
|
continue?(threadId: string, options: {
|
|
29
34
|
signal?: AbortSignal;
|
|
30
35
|
metadata?: Record<string, unknown>;
|
|
36
|
+
tenantId?: string;
|
|
37
|
+
control?: DrainSwitch;
|
|
31
38
|
}): AsyncIterable<unknown>;
|
|
32
39
|
/** Writes values into a thread's state, which is how a rollback is applied. */
|
|
33
40
|
updateState?(threadId: string, values: Record<string, unknown>, options?: {
|
|
34
41
|
asNode?: string;
|
|
35
42
|
}): Promise<unknown>;
|
|
43
|
+
/** Runs an input as a stream of typed events. Used when the assistant serves `events`. */
|
|
44
|
+
events?(input: unknown, options: GraphEventOptionsLike): GraphEventsLike;
|
|
45
|
+
/** Like `events()`, answering an interrupt. */
|
|
46
|
+
resumeEvents?(threadId: string, value: unknown, options: GraphEventOptionsLike): GraphEventsLike;
|
|
47
|
+
/** Like `events()`, continuing a thread from its latest checkpoint. */
|
|
48
|
+
continueEvents?(threadId: string, options: GraphEventOptionsLike): GraphEventsLike;
|
|
36
49
|
}
|
|
50
|
+
/** The options of a graph's `events()` the adapter passes. */
|
|
51
|
+
type GraphEventOptionsLike = {
|
|
52
|
+
threadId?: string;
|
|
53
|
+
tenantId?: string;
|
|
54
|
+
signal?: AbortSignal;
|
|
55
|
+
metadata?: Record<string, unknown>;
|
|
56
|
+
control?: DrainSwitch;
|
|
57
|
+
include?: GraphStreamProjection[];
|
|
58
|
+
};
|
|
59
|
+
/** A graph's event stream, as the adapter reads it: the events, then the run's result. */
|
|
60
|
+
type GraphEventsLike = AsyncIterable<unknown> & {
|
|
61
|
+
result: Promise<{
|
|
62
|
+
status: string;
|
|
63
|
+
state: unknown;
|
|
64
|
+
interrupt?: unknown;
|
|
65
|
+
interrupts?: unknown[];
|
|
66
|
+
}>;
|
|
67
|
+
};
|
|
68
|
+
/** Asks a graph to stop after its current superstep. A graph's `RunControl` has this shape. */
|
|
69
|
+
type DrainSwitch = {
|
|
70
|
+
readonly draining: boolean;
|
|
71
|
+
readonly reason?: string;
|
|
72
|
+
};
|
|
37
73
|
/** Options for `graphAssistant()`. */
|
|
38
74
|
export interface GraphAssistantOptions {
|
|
39
75
|
/** What the assistant is, reported by the assistants endpoint. */
|
|
40
76
|
description?: string;
|
|
41
77
|
/** Metadata recorded on every checkpoint the server's runs create. */
|
|
42
78
|
metadata?: Record<string, unknown>;
|
|
79
|
+
/**
|
|
80
|
+
* Records these projections of the graph's event stream on each run, such as `messages` and
|
|
81
|
+
* `tools`, so a client following the run sees model output and tool calls as they happen. The
|
|
82
|
+
* run's last event still carries its state and any question, as without it. Defaults to none: one
|
|
83
|
+
* event per superstep.
|
|
84
|
+
*/
|
|
85
|
+
events?: GraphStreamProjection[];
|
|
43
86
|
}
|
|
44
87
|
/**
|
|
45
88
|
* Serves a compiled graph as an assistant.
|
|
@@ -61,3 +104,4 @@ export declare function graphAssistant(graph: GraphLike, options?: GraphAssistan
|
|
|
61
104
|
export declare function functionAssistant(run: (input: unknown, context: AssistantRunContext) => AsyncIterable<unknown> | Promise<unknown> | unknown, options?: {
|
|
62
105
|
description?: string;
|
|
63
106
|
}): ServerAssistant;
|
|
107
|
+
export {};
|
|
@@ -3,19 +3,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.graphAssistant = graphAssistant;
|
|
4
4
|
exports.functionAssistant = functionAssistant;
|
|
5
5
|
function graphAssistant(graph, options = {}) {
|
|
6
|
+
const projections = options.events?.length ? options.events : undefined;
|
|
7
|
+
const eventOptions = (context, threadId) => ({
|
|
8
|
+
...(threadId ? { threadId } : {}),
|
|
9
|
+
signal: context.signal,
|
|
10
|
+
metadata: { ...options.metadata, runId: context.runId },
|
|
11
|
+
...tenantOf(context),
|
|
12
|
+
...(context.control ? { control: context.control } : {}),
|
|
13
|
+
include: [...(projections ?? []), 'values'],
|
|
14
|
+
});
|
|
6
15
|
return {
|
|
7
16
|
description: options.description,
|
|
8
17
|
stream(input, context) {
|
|
18
|
+
if (projections && graph.events) {
|
|
19
|
+
return withResult(graph.events(input ?? {}, eventOptions(context, context.threadId)));
|
|
20
|
+
}
|
|
9
21
|
return graph.stream(input ?? {}, {
|
|
10
22
|
threadId: context.threadId,
|
|
11
23
|
signal: context.signal,
|
|
12
24
|
metadata: { ...options.metadata, runId: context.runId },
|
|
25
|
+
...tenantOf(context),
|
|
26
|
+
...(context.control ? { control: context.control } : {}),
|
|
13
27
|
});
|
|
14
28
|
},
|
|
15
29
|
resume(threadId, value, context) {
|
|
30
|
+
if (projections && graph.resumeEvents) {
|
|
31
|
+
return withResult(graph.resumeEvents(threadId, value, eventOptions(context)));
|
|
32
|
+
}
|
|
16
33
|
return graph.resume(threadId, value, {
|
|
17
34
|
signal: context.signal,
|
|
18
35
|
metadata: { ...options.metadata, runId: context.runId },
|
|
36
|
+
...tenantOf(context),
|
|
37
|
+
...(context.control ? { control: context.control } : {}),
|
|
19
38
|
});
|
|
20
39
|
},
|
|
21
40
|
async state(threadId) {
|
|
@@ -33,9 +52,13 @@ function graphAssistant(graph, options = {}) {
|
|
|
33
52
|
if (checkpoint.status !== 'running' && checkpoint.status !== 'failed' && checkpoint.status !== 'interrupted') {
|
|
34
53
|
return undefined;
|
|
35
54
|
}
|
|
55
|
+
if (projections && graph.continueEvents)
|
|
56
|
+
return withResult(graph.continueEvents(threadId, eventOptions(context)));
|
|
36
57
|
return graph.continue(threadId, {
|
|
37
58
|
signal: context.signal,
|
|
38
59
|
metadata: { ...options.metadata, runId: context.runId },
|
|
60
|
+
...tenantOf(context),
|
|
61
|
+
...(context.control ? { control: context.control } : {}),
|
|
39
62
|
});
|
|
40
63
|
},
|
|
41
64
|
async restore(threadId, step) {
|
|
@@ -61,3 +84,19 @@ function functionAssistant(run, options = {}) {
|
|
|
61
84
|
},
|
|
62
85
|
};
|
|
63
86
|
}
|
|
87
|
+
function tenantOf(context) {
|
|
88
|
+
const tenantId = context.principal?.tenantId;
|
|
89
|
+
return tenantId ? { tenantId } : {};
|
|
90
|
+
}
|
|
91
|
+
async function* withResult(events) {
|
|
92
|
+
for await (const event of events)
|
|
93
|
+
yield event;
|
|
94
|
+
const result = await events.result;
|
|
95
|
+
yield {
|
|
96
|
+
type: result.status === 'awaiting_input' ? 'interrupt' : 'done',
|
|
97
|
+
status: result.status,
|
|
98
|
+
state: result.state,
|
|
99
|
+
...(result.interrupt === undefined ? {} : { interrupt: result.interrupt }),
|
|
100
|
+
...(result.interrupts === undefined ? {} : { interrupts: result.interrupts }),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
@@ -32,6 +32,18 @@ export declare class ForbiddenError extends ServerError {
|
|
|
32
32
|
/** The scope the route required. */
|
|
33
33
|
scope: string);
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Thrown by an assistant to hand its run to another worker while this replica drains: the server puts
|
|
37
|
+
* the run back on the queue as its next attempt instead of failing it. A function assistant checks
|
|
38
|
+
* `context.control?.draining` between its own steps, saves where it got with `context.saveProgress()`,
|
|
39
|
+
* and throws this; the next worker reads `context.progress`. Thrown when the replica is not draining,
|
|
40
|
+
* it fails the run like any error.
|
|
41
|
+
*/
|
|
42
|
+
export declare class RunHandOffError extends Error {
|
|
43
|
+
/** Always `RUN_HANDED_OFF`. */
|
|
44
|
+
readonly code = "RUN_HANDED_OFF";
|
|
45
|
+
constructor(message?: string);
|
|
46
|
+
}
|
|
35
47
|
/** Raised when a thread is already running something and the busy policy is `reject`. */
|
|
36
48
|
export declare class ThreadBusyError extends ServerError {
|
|
37
49
|
/** The thread. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AssistantCapabilityError = exports.TenantLimitError = exports.ThreadBusyError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = exports.NotFoundError = exports.ServerError = void 0;
|
|
3
|
+
exports.AssistantCapabilityError = exports.TenantLimitError = exports.ThreadBusyError = exports.RunHandOffError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = exports.NotFoundError = exports.ServerError = void 0;
|
|
4
4
|
class ServerError extends Error {
|
|
5
5
|
code;
|
|
6
6
|
status;
|
|
@@ -43,6 +43,14 @@ class ForbiddenError extends ServerError {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
exports.ForbiddenError = ForbiddenError;
|
|
46
|
+
class RunHandOffError extends Error {
|
|
47
|
+
code = 'RUN_HANDED_OFF';
|
|
48
|
+
constructor(message = 'Handed to another worker while this one drains') {
|
|
49
|
+
super(message);
|
|
50
|
+
this.name = 'RunHandOffError';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.RunHandOffError = RunHandOffError;
|
|
46
54
|
class ThreadBusyError extends ServerError {
|
|
47
55
|
threadId;
|
|
48
56
|
runId;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export { functionAssistant, type GraphAssistantOptions, graphAssistant, type GraphLike, } from './assistant.js';
|
|
11
11
|
export { CronScheduler, type CronSchedulerOptions, type DueCronJob, parseCron } from './cron.js';
|
|
12
|
-
export { AssistantCapabilityError, BadRequestError, ForbiddenError, NotFoundError, ServerError, type TenantLimit, TenantLimitError, ThreadBusyError, UnauthorizedError, } from './errors.js';
|
|
12
|
+
export { AssistantCapabilityError, BadRequestError, ForbiddenError, NotFoundError, RunHandOffError, ServerError, type TenantLimit, TenantLimitError, ThreadBusyError, UnauthorizedError, } from './errors.js';
|
|
13
13
|
export { MemoryRunEventLog, type MemoryRunEventLogOptions, type RedisEventLogLikeClient, RedisRunEventLog, type RedisRunEventLogOptions, } from './events.js';
|
|
14
14
|
export { type NodeListenerOptions, type NodeRequestLike, type NodeResponseLike, toNodeListener, } from './node.js';
|
|
15
15
|
export { type DrainResult, RunManager, type RunManagerOptions, type RunQueueOptions, type StartRunOptions, } from './runs.js';
|
package/dist-cjs/server/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MemoryServerStore = exports.fromStore = exports.createAgentServer = exports.RunManager = exports.toNodeListener = exports.RedisRunEventLog = exports.MemoryRunEventLog = exports.UnauthorizedError = exports.ThreadBusyError = exports.TenantLimitError = exports.ServerError = exports.NotFoundError = exports.ForbiddenError = exports.BadRequestError = exports.AssistantCapabilityError = exports.parseCron = exports.CronScheduler = exports.graphAssistant = exports.functionAssistant = void 0;
|
|
3
|
+
exports.MemoryServerStore = exports.fromStore = exports.createAgentServer = exports.RunManager = exports.toNodeListener = exports.RedisRunEventLog = exports.MemoryRunEventLog = exports.UnauthorizedError = exports.ThreadBusyError = exports.TenantLimitError = exports.ServerError = exports.RunHandOffError = exports.NotFoundError = exports.ForbiddenError = exports.BadRequestError = exports.AssistantCapabilityError = exports.parseCron = exports.CronScheduler = exports.graphAssistant = exports.functionAssistant = void 0;
|
|
4
4
|
var assistant_js_1 = require("./assistant.js");
|
|
5
5
|
Object.defineProperty(exports, "functionAssistant", { enumerable: true, get: function () { return assistant_js_1.functionAssistant; } });
|
|
6
6
|
Object.defineProperty(exports, "graphAssistant", { enumerable: true, get: function () { return assistant_js_1.graphAssistant; } });
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "AssistantCapabilityError", { enumerable: true, g
|
|
|
12
12
|
Object.defineProperty(exports, "BadRequestError", { enumerable: true, get: function () { return errors_js_1.BadRequestError; } });
|
|
13
13
|
Object.defineProperty(exports, "ForbiddenError", { enumerable: true, get: function () { return errors_js_1.ForbiddenError; } });
|
|
14
14
|
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return errors_js_1.NotFoundError; } });
|
|
15
|
+
Object.defineProperty(exports, "RunHandOffError", { enumerable: true, get: function () { return errors_js_1.RunHandOffError; } });
|
|
15
16
|
Object.defineProperty(exports, "ServerError", { enumerable: true, get: function () { return errors_js_1.ServerError; } });
|
|
16
17
|
Object.defineProperty(exports, "TenantLimitError", { enumerable: true, get: function () { return errors_js_1.TenantLimitError; } });
|
|
17
18
|
Object.defineProperty(exports, "ThreadBusyError", { enumerable: true, get: function () { return errors_js_1.ThreadBusyError; } });
|
|
@@ -97,6 +97,10 @@ export declare class RunManager {
|
|
|
97
97
|
private readonly local;
|
|
98
98
|
/** Runs holding one of this replica's execution slots. */
|
|
99
99
|
private readonly slots;
|
|
100
|
+
/** The drain switch of each run this replica is executing, so `drain()` can reach graph runs. */
|
|
101
|
+
private readonly controls;
|
|
102
|
+
/** Runs handed back to the queue during a drain, as each graph run stopped at a boundary. */
|
|
103
|
+
private readonly drainedRuns;
|
|
100
104
|
private readonly state;
|
|
101
105
|
private readonly events;
|
|
102
106
|
private readonly now;
|
|
@@ -155,6 +159,8 @@ export declare class RunManager {
|
|
|
155
159
|
* it with a `TenantLimitError`.
|
|
156
160
|
*/
|
|
157
161
|
start(options: StartRunOptions): Promise<RunRecord>;
|
|
162
|
+
/** The rest of `start()`, once the thread, if any, is this run's. */
|
|
163
|
+
private startClaimed;
|
|
158
164
|
/** Cancels a run, including one another replica is executing. */
|
|
159
165
|
cancel(runId: string, principal?: Principal, reason?: string): Promise<RunRecord>;
|
|
160
166
|
/**
|
|
@@ -206,8 +212,29 @@ export declare class RunManager {
|
|
|
206
212
|
private freeSlot;
|
|
207
213
|
private schedule;
|
|
208
214
|
private tick;
|
|
209
|
-
/**
|
|
215
|
+
/**
|
|
216
|
+
* Applies the busy policy, returning the thread once this run holds it. The thread is claimed
|
|
217
|
+
* atomically, so of several replicas starting runs on one thread at once, exactly one proceeds and
|
|
218
|
+
* the rest meet the policy; a thread still busy after the policy has run its course is refused.
|
|
219
|
+
*/
|
|
210
220
|
private settleBusyThread;
|
|
221
|
+
/**
|
|
222
|
+
* Claims a thread for a run. The claim is a record in the operation store under a unique
|
|
223
|
+
* idempotency key, moved from run to run by compare-and-set, so two replicas cannot both take a free
|
|
224
|
+
* thread: creating it races on the key, and taking it over races on the sequence. Resolves
|
|
225
|
+
* undefined once this run holds the thread, or the id of the unfinished run that does.
|
|
226
|
+
*
|
|
227
|
+
* A store without `findByIdempotencyKey` falls back to the thread record's `activeRunId`, which is
|
|
228
|
+
* what every release before 2.2 used, and which two replicas racing can both see empty.
|
|
229
|
+
*/
|
|
230
|
+
private claimThread;
|
|
231
|
+
/**
|
|
232
|
+
* Whether a thread's holder no longer needs it: its run finished, or it was never recorded and its
|
|
233
|
+
* claim is old enough that the replica starting it must have died.
|
|
234
|
+
*/
|
|
235
|
+
private runIsFree;
|
|
236
|
+
/** Frees a thread this run holds. Losing the compare-and-set means another run took it over, which is fine. */
|
|
237
|
+
private releaseClaim;
|
|
211
238
|
/** Waits for a run to finish, for the `enqueue` policy. */
|
|
212
239
|
private waitForRun;
|
|
213
240
|
private releaseThread;
|