dsh-autotier 0.1.0 → 0.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/AGENTS.md +26 -3
- package/CHANGELOG.md +59 -0
- package/README.es.md +6 -2
- package/README.hi.md +7 -2
- package/README.md +7 -2
- package/README.pt.md +6 -2
- package/README.zh.md +6 -2
- package/THIRD_PARTY_NOTICES.md +31 -0
- package/docs/roadmap-v0.2.md +114 -0
- package/lib/client.js +5956 -0
- package/lib/client.js.map +1 -0
- package/lib/index.js +274 -58
- package/lib/typert.host.js +26 -0
- package/lib/types/client/TierPill.d.ts +24 -0
- package/lib/types/client/TierPill.d.ts.map +1 -0
- package/lib/types/client/TierSettingsCard.d.ts +31 -0
- package/lib/types/client/TierSettingsCard.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +30 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/locales.d.ts +60 -0
- package/lib/types/client/locales.d.ts.map +1 -0
- package/lib/types/client/present.d.ts +61 -0
- package/lib/types/client/present.d.ts.map +1 -0
- package/lib/types/client/remote.d.ts +313 -0
- package/lib/types/client/remote.d.ts.map +1 -0
- package/lib/types/client/styles.d.ts +12 -0
- package/lib/types/client/styles.d.ts.map +1 -0
- package/lib/types/command.d.ts.map +1 -1
- package/lib/types/index.d.ts +4 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/policy.d.ts +4 -0
- package/lib/types/policy.d.ts.map +1 -1
- package/lib/types/preflight.d.ts +48 -0
- package/lib/types/preflight.d.ts.map +1 -0
- package/lib/types/routing.d.ts +2 -0
- package/lib/types/routing.d.ts.map +1 -1
- package/lib/types/selection.d.ts +50 -0
- package/lib/types/selection.d.ts.map +1 -0
- package/lib/types/tier-remote.d.ts +79 -0
- package/lib/types/tier-remote.d.ts.map +1 -0
- package/lib/types/typert.host.d.ts +300 -0
- package/lib/types/typert.host.d.ts.map +1 -0
- package/lib/types/wire.d.ts +804 -0
- package/lib/types/wire.d.ts.map +1 -0
- package/lib/wire-BpKSOHgo.js +5193 -0
- package/package.json +63 -11
- package/src/client/TierPill.tsx +83 -0
- package/src/client/TierSettingsCard.tsx +175 -0
- package/src/client/index.ts +146 -0
- package/src/client/locales.ts +107 -0
- package/src/client/present.ts +124 -0
- package/src/client/remote.ts +39 -0
- package/src/client/styles.ts +174 -0
- package/src/command.ts +1 -0
- package/src/index.ts +43 -0
- package/src/policy.ts +6 -0
- package/src/preflight.ts +105 -0
- package/src/routing.ts +28 -1
- package/src/selection.ts +124 -0
- package/src/tier-remote.ts +139 -0
- package/src/typert.host.ts +25 -0
- package/src/wire.ts +248 -0
package/lib/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { a as TIER_INVOCATIONS, c as TIER_SESSION_VIEW_SCHEMA, d as TIER_STATUS_SCHEMA, f as COST_MODES, g as TIER_IDS, h as SCENARIOS, i as TIER_CATALOG_SCHEMA, l as TIER_SET_MODE_DESCRIPTOR, m as ROUTING_MODES, n as TIER_AGENT_ID_SCHEMA, o as TIER_MODE_SCHEMA, p as EFFORT_IDS, r as TIER_CATALOG_DESCRIPTOR, s as TIER_NAMESPACE, t as ROUTE_SOURCES, u as TIER_STATUS_DESCRIPTOR } from "./wire-BpKSOHgo.js";
|
|
1
2
|
import z from "@deepseek-ai/schemastery";
|
|
2
3
|
import { BlockAssembler, createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
3
4
|
import { Service } from "@deepseek-ai/cordis";
|
|
5
|
+
import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
4
6
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
5
7
|
//#region src/tiers.ts
|
|
6
8
|
/** The adapter-owned effort ladder, cheapest to strongest. */
|
|
@@ -195,7 +197,9 @@ function createRouteState() {
|
|
|
195
197
|
reviewOwedFor: void 0,
|
|
196
198
|
probe: void 0,
|
|
197
199
|
denials: 0,
|
|
198
|
-
lastDenial: ""
|
|
200
|
+
lastDenial: "",
|
|
201
|
+
lastProviderModel: void 0,
|
|
202
|
+
coexistenceWarned: false
|
|
199
203
|
};
|
|
200
204
|
}
|
|
201
205
|
/** Whether the current failure escalation is still in force. */
|
|
@@ -339,61 +343,6 @@ function noteFallback(state, tier, chainLength, config, now) {
|
|
|
339
343
|
return true;
|
|
340
344
|
}
|
|
341
345
|
//#endregion
|
|
342
|
-
//#region src/types.ts
|
|
343
|
-
/**
|
|
344
|
-
* Shared vocabulary for dsh-autotier: the tier ids, the adapter-owned reasoning
|
|
345
|
-
* effort ids, the routing modes, and the public route/status shapes every
|
|
346
|
-
* module and the `ctx.autotier` service speak.
|
|
347
|
-
* @module dsh-autotier/types
|
|
348
|
-
*/
|
|
349
|
-
/**
|
|
350
|
-
* Service Definition (contract layer): the two cost tiers this plugin routes
|
|
351
|
-
* between. `strong` plans complex intent and reviews high-risk work; `cheap`
|
|
352
|
-
* implements it. The ids are stable wire/settings vocabulary.
|
|
353
|
-
*/
|
|
354
|
-
const TIER_IDS = ["strong", "cheap"];
|
|
355
|
-
/**
|
|
356
|
-
* Reasoning-effort ids owned by the provider adapter. The DeepSeek adapter
|
|
357
|
-
* accepts exactly these four (`packages/llm/llm-deepseek/src/index.ts:133`);
|
|
358
|
-
* `medium` does not exist, and an unsupported value fails every request with
|
|
359
|
-
* `UNSUPPORTED_REASONING_EFFORT` instead of degrading.
|
|
360
|
-
*/
|
|
361
|
-
const EFFORT_IDS = [
|
|
362
|
-
"off",
|
|
363
|
-
"low",
|
|
364
|
-
"high",
|
|
365
|
-
"max"
|
|
366
|
-
];
|
|
367
|
-
/**
|
|
368
|
-
* Routing modes. `auto` is the fully automatic path; the rest are explicit
|
|
369
|
-
* user overrides (`/tier strong|cheap|off`). `delegated` means the session
|
|
370
|
-
* carries an explicit model selection that autotier must not fight.
|
|
371
|
-
*/
|
|
372
|
-
const ROUTING_MODES = [
|
|
373
|
-
"auto",
|
|
374
|
-
"strong",
|
|
375
|
-
"cheap",
|
|
376
|
-
"delegated",
|
|
377
|
-
"off"
|
|
378
|
-
];
|
|
379
|
-
/** Intent classes the rule layer and the judge distinguish. */
|
|
380
|
-
const SCENARIOS = [
|
|
381
|
-
"coding",
|
|
382
|
-
"review",
|
|
383
|
-
"planning",
|
|
384
|
-
"retrieval",
|
|
385
|
-
"batch",
|
|
386
|
-
"daily",
|
|
387
|
-
"longText",
|
|
388
|
-
"multimodal"
|
|
389
|
-
];
|
|
390
|
-
/** Cost/quality arbitration direction when the signals are ambiguous. */
|
|
391
|
-
const COST_MODES = [
|
|
392
|
-
"cost-first",
|
|
393
|
-
"quality-first",
|
|
394
|
-
"balanced"
|
|
395
|
-
];
|
|
396
|
-
//#endregion
|
|
397
346
|
//#region src/command.ts
|
|
398
347
|
/** Format the tier table for `/tier status`. */
|
|
399
348
|
function statusText(service, state) {
|
|
@@ -417,6 +366,7 @@ function statusText(service, state) {
|
|
|
417
366
|
if (state.fallback !== void 0) lines.push(`fallback: chain entry ${String(state.fallback.index + 1)}`);
|
|
418
367
|
if (state.planActive) lines.push("plan mode: active (strong tier)");
|
|
419
368
|
if (state.denials > 0) lines.push(`guard denials: ${String(state.denials)} (last rule ${state.lastDenial})`);
|
|
369
|
+
if (state.coexistenceWarned) lines.push("coexistence: another layer changed the request configuration (see logs)");
|
|
420
370
|
return lines.join("\n");
|
|
421
371
|
}
|
|
422
372
|
/**
|
|
@@ -2078,6 +2028,155 @@ async function runJudge(ctx, config, text, signal) {
|
|
|
2078
2028
|
};
|
|
2079
2029
|
}
|
|
2080
2030
|
//#endregion
|
|
2031
|
+
//#region src/preflight.ts
|
|
2032
|
+
/**
|
|
2033
|
+
* Pre-flight cache and checker for one plugin instance. The cache is per
|
|
2034
|
+
* process and never invalidated: adapter registrations are composition-level
|
|
2035
|
+
* facts, and a reload rebuilds the plugin (and this cache) with them.
|
|
2036
|
+
*/
|
|
2037
|
+
var RoutePreflight = class {
|
|
2038
|
+
ctx;
|
|
2039
|
+
onDegrade;
|
|
2040
|
+
capabilities = /* @__PURE__ */ new Map();
|
|
2041
|
+
degraded = /* @__PURE__ */ new Set();
|
|
2042
|
+
/** @param options - the plugin context and the degrade reporter. */
|
|
2043
|
+
constructor(options) {
|
|
2044
|
+
this.ctx = options.ctx;
|
|
2045
|
+
this.onDegrade = options.onDegrade;
|
|
2046
|
+
}
|
|
2047
|
+
/** One cached capability lookup; a failing adapter is treated as lenient. */
|
|
2048
|
+
capability(provider, model) {
|
|
2049
|
+
const key = `${provider}/${model}`;
|
|
2050
|
+
let pending = this.capabilities.get(key);
|
|
2051
|
+
if (pending === void 0) {
|
|
2052
|
+
pending = this.ctx.llm.listProviders().some((entry) => entry.id === provider) ? this.ctx.llm.resolveModelInfo(provider, model).then((info) => ({
|
|
2053
|
+
registered: true,
|
|
2054
|
+
efforts: info.reasoning === void 0 ? void 0 : new Set(info.reasoning.efforts.map((effort) => String(effort.id)))
|
|
2055
|
+
}), () => ({
|
|
2056
|
+
registered: true,
|
|
2057
|
+
efforts: void 0
|
|
2058
|
+
})) : Promise.resolve({
|
|
2059
|
+
registered: false,
|
|
2060
|
+
efforts: void 0
|
|
2061
|
+
});
|
|
2062
|
+
this.capabilities.set(key, pending);
|
|
2063
|
+
}
|
|
2064
|
+
return pending;
|
|
2065
|
+
}
|
|
2066
|
+
/** Report one degradation at most once per key. */
|
|
2067
|
+
degrade(key, note) {
|
|
2068
|
+
if (this.degraded.has(key)) return;
|
|
2069
|
+
this.degraded.add(key);
|
|
2070
|
+
this.onDegrade(key, note);
|
|
2071
|
+
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Make one tier landing safe to apply.
|
|
2074
|
+
* @param route - the landing the policy produced.
|
|
2075
|
+
* @param tier - the tier configuration, for its fallback chain.
|
|
2076
|
+
* @returns a landing that will not fail the request on provider/effort facts.
|
|
2077
|
+
*/
|
|
2078
|
+
async sanitize(route, tier) {
|
|
2079
|
+
const capability = await this.capability(route.provider, route.model);
|
|
2080
|
+
let safe = route;
|
|
2081
|
+
if (!capability.registered) {
|
|
2082
|
+
const entry = tier.fallback.find((candidate) => this.ctx.llm.listProviders().some((p) => p.id === candidate.provider));
|
|
2083
|
+
if (entry !== void 0) {
|
|
2084
|
+
this.degrade(`provider:${route.provider}`, `provider "${route.provider}" is not registered; using fallback "${entry.provider}/${entry.model}"`);
|
|
2085
|
+
safe = tier.followSession ? {
|
|
2086
|
+
provider: entry.provider,
|
|
2087
|
+
model: entry.model
|
|
2088
|
+
} : {
|
|
2089
|
+
provider: entry.provider,
|
|
2090
|
+
model: entry.model,
|
|
2091
|
+
effort: tier.effort
|
|
2092
|
+
};
|
|
2093
|
+
} else this.degrade(`provider:${route.provider}`, `provider "${route.provider}" is not registered and the tier has no usable fallback`);
|
|
2094
|
+
}
|
|
2095
|
+
const effort = safe.effort;
|
|
2096
|
+
if (effort !== void 0 && capability.efforts !== void 0 && !capability.efforts.has(effort)) {
|
|
2097
|
+
this.degrade(`effort:${route.provider}/${route.model}`, `model "${route.model}" does not accept reasoning effort "${effort}"; the adapter default applies`);
|
|
2098
|
+
safe = {
|
|
2099
|
+
provider: safe.provider,
|
|
2100
|
+
model: safe.model
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
return safe;
|
|
2104
|
+
}
|
|
2105
|
+
};
|
|
2106
|
+
//#endregion
|
|
2107
|
+
//#region src/selection.ts
|
|
2108
|
+
/** Key of one selection, for comparing our own writes with external ones. */
|
|
2109
|
+
function selectionKey(value) {
|
|
2110
|
+
if (value === null || typeof value !== "object") return "";
|
|
2111
|
+
const record = value;
|
|
2112
|
+
return `${typeof record.provider === "string" ? record.provider : ""}/${typeof record.model === "string" ? record.model : ""}@${typeof record.reasoningEffort === "string" ? record.reasoningEffort : ""}`;
|
|
2113
|
+
}
|
|
2114
|
+
/**
|
|
2115
|
+
* Mirrors the applied tier into the default-model document and honours an
|
|
2116
|
+
* external change by delegating every live session.
|
|
2117
|
+
*/
|
|
2118
|
+
var SelectionSync = class {
|
|
2119
|
+
ctx;
|
|
2120
|
+
states;
|
|
2121
|
+
/** The selection this plugin last wrote; used to tell our write from a user's. */
|
|
2122
|
+
selfWrite;
|
|
2123
|
+
/** @param options - the plugin context and the per-agent state store. */
|
|
2124
|
+
constructor(options) {
|
|
2125
|
+
this.ctx = options.ctx;
|
|
2126
|
+
this.states = options.states;
|
|
2127
|
+
this.ctx.on("settings/updated", (ns, next) => {
|
|
2128
|
+
if (String(ns) !== "agent-default-model") return;
|
|
2129
|
+
const key = selectionKey(next);
|
|
2130
|
+
if (this.selfWrite === key) {
|
|
2131
|
+
this.selfWrite = void 0;
|
|
2132
|
+
return;
|
|
2133
|
+
}
|
|
2134
|
+
this.delegateLiveSessions(key);
|
|
2135
|
+
});
|
|
2136
|
+
}
|
|
2137
|
+
/** The optional default-model service. */
|
|
2138
|
+
get defaultModel() {
|
|
2139
|
+
return this.ctx.get("agentDefaultModel");
|
|
2140
|
+
}
|
|
2141
|
+
/**
|
|
2142
|
+
* Mirror one applied landing into the default-model document. Repeated
|
|
2143
|
+
* landings with the same value are skipped, so a long cheap run writes once.
|
|
2144
|
+
* @param route - the landing actually applied.
|
|
2145
|
+
*/
|
|
2146
|
+
noteRoute(route) {
|
|
2147
|
+
const service = this.defaultModel;
|
|
2148
|
+
if (service === void 0) return;
|
|
2149
|
+
const selection = {
|
|
2150
|
+
provider: route.provider,
|
|
2151
|
+
model: route.model,
|
|
2152
|
+
...route.effort === void 0 ? {} : { reasoningEffort: route.effort }
|
|
2153
|
+
};
|
|
2154
|
+
const key = selectionKey(selection);
|
|
2155
|
+
if (this.selfWrite === key) return;
|
|
2156
|
+
this.selfWrite = key;
|
|
2157
|
+
service.saveSelection(selection).catch((error) => {
|
|
2158
|
+
this.selfWrite = void 0;
|
|
2159
|
+
this.ctx.logger.debug("dsh-autotier: could not mirror the tier into the default-model document: %o", error);
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
2162
|
+
/**
|
|
2163
|
+
* An external change to the default model wins: stop routing for every live
|
|
2164
|
+
* session until the user asks for `auto` again.
|
|
2165
|
+
*/
|
|
2166
|
+
delegateLiveSessions(key) {
|
|
2167
|
+
const agents = this.ctx.get("agents");
|
|
2168
|
+
if (agents === void 0) return;
|
|
2169
|
+
let changed = 0;
|
|
2170
|
+
for (const agent of agents.list()) {
|
|
2171
|
+
const state = this.states.for(agent);
|
|
2172
|
+
if (state.override === "off" || state.override === "delegated") continue;
|
|
2173
|
+
state.override = "delegated";
|
|
2174
|
+
changed += 1;
|
|
2175
|
+
}
|
|
2176
|
+
if (changed > 0) this.ctx.logger.info("dsh-autotier: the default model selection changed to %s; %d live session(s) switched to delegated (use /tier auto to resume routing)", key === "" ? "<unknown>" : key, changed);
|
|
2177
|
+
}
|
|
2178
|
+
};
|
|
2179
|
+
//#endregion
|
|
2081
2180
|
//#region src/routing.ts
|
|
2082
2181
|
/** How long third parties have to veto a proposed tier before the turn proceeds. */
|
|
2083
2182
|
const VETO_TIMEOUT_MS = 250;
|
|
@@ -2106,6 +2205,8 @@ var AutotierRouter = class {
|
|
|
2106
2205
|
counters = /* @__PURE__ */ new WeakMap();
|
|
2107
2206
|
/** Router-owned lifetime signal: aborts in-flight judge calls on unload. */
|
|
2108
2207
|
lifetime = new AbortController();
|
|
2208
|
+
preflight;
|
|
2209
|
+
selection;
|
|
2109
2210
|
disposed = false;
|
|
2110
2211
|
/**
|
|
2111
2212
|
* Register every listener on the plugin fiber.
|
|
@@ -2115,6 +2216,14 @@ var AutotierRouter = class {
|
|
|
2115
2216
|
this.ctx = options.ctx;
|
|
2116
2217
|
this.service = options.service;
|
|
2117
2218
|
this.states = options.states;
|
|
2219
|
+
this.preflight = new RoutePreflight({
|
|
2220
|
+
ctx: this.ctx,
|
|
2221
|
+
onDegrade: (_key, note) => this.ctx.logger.warn("dsh-autotier: %s", note)
|
|
2222
|
+
});
|
|
2223
|
+
this.selection = new SelectionSync({
|
|
2224
|
+
ctx: this.ctx,
|
|
2225
|
+
states: this.states
|
|
2226
|
+
});
|
|
2118
2227
|
this.ctx.on("agent/inbox/inserted", (payload) => this.onInboxInserted(payload.agent, payload.message), { prepend: true });
|
|
2119
2228
|
this.ctx.on("agent/request", (payload, next) => this.onRequest(payload.agent, payload.turn, payload.step, next), { prepend: true });
|
|
2120
2229
|
this.ctx.on("agent/error", (payload) => this.onAgentError(payload.agent, payload.error));
|
|
@@ -2377,7 +2486,15 @@ var AutotierRouter = class {
|
|
|
2377
2486
|
const source = veto === void 0 || veto === null ? decision.source : "manual";
|
|
2378
2487
|
const reason = veto === void 0 || veto === null ? decision.reason : `veto: ${veto.reason}`;
|
|
2379
2488
|
const route = this.routeFor(tier, config, intent, state, now, base);
|
|
2380
|
-
const
|
|
2489
|
+
const safeRoute = await this.preflight.sanitize(route, tier === "strong" ? config.tiers.strong : config.tiers.cheap);
|
|
2490
|
+
const applied = resolveRoute(base, safeRoute);
|
|
2491
|
+
const baseKey = `${base.provider}/${base.model}`;
|
|
2492
|
+
if (state.lastProviderModel !== void 0 && state.lastProviderModel !== baseKey && !state.coexistenceWarned) {
|
|
2493
|
+
state.coexistenceWarned = true;
|
|
2494
|
+
this.ctx.logger.warn("dsh-autotier: the request configuration was changed outside this plugin (expected %s, saw %s); another router may be composed. /tier status reports this.", state.lastProviderModel, baseKey);
|
|
2495
|
+
}
|
|
2496
|
+
state.lastProviderModel = `${safeRoute.provider}/${safeRoute.model}`;
|
|
2497
|
+
this.selection.noteRoute(safeRoute);
|
|
2381
2498
|
if (state.appliedTier !== tier) {
|
|
2382
2499
|
const from = state.appliedTier;
|
|
2383
2500
|
state.appliedTier = tier;
|
|
@@ -2672,6 +2789,92 @@ var AgentStateStore = class {
|
|
|
2672
2789
|
}
|
|
2673
2790
|
};
|
|
2674
2791
|
//#endregion
|
|
2792
|
+
//#region src/tier-remote.ts
|
|
2793
|
+
/**
|
|
2794
|
+
* The `tier` Typert Remote service. Constructed by `src/index.ts` on the plugin
|
|
2795
|
+
* fiber; registering it removes it again on unload.
|
|
2796
|
+
*/
|
|
2797
|
+
var TierRemoteService = class extends TypertRemoteService {
|
|
2798
|
+
bindings;
|
|
2799
|
+
/** No service dependencies: a pure surface over the injected bindings. */
|
|
2800
|
+
static inject = [];
|
|
2801
|
+
/**
|
|
2802
|
+
* @param ctx - the owning plugin context.
|
|
2803
|
+
* @param bindings - the read surface, the shared state store and the agent resolver.
|
|
2804
|
+
*/
|
|
2805
|
+
constructor(ctx, bindings) {
|
|
2806
|
+
super(ctx, TIER_NAMESPACE);
|
|
2807
|
+
this.bindings = bindings;
|
|
2808
|
+
}
|
|
2809
|
+
/**
|
|
2810
|
+
* The status snapshot for one session.
|
|
2811
|
+
* @param agentId - the calling session/agent id; omitted reads the composition mode only.
|
|
2812
|
+
* @returns the host status plus the session view (empty when the id is absent or unknown).
|
|
2813
|
+
*/
|
|
2814
|
+
status(agentId) {
|
|
2815
|
+
const base = this.bindings.service.status();
|
|
2816
|
+
return {
|
|
2817
|
+
...base,
|
|
2818
|
+
session: this.viewFor(agentId, base)
|
|
2819
|
+
};
|
|
2820
|
+
}
|
|
2821
|
+
/**
|
|
2822
|
+
* The registered provider/model catalog, straight from the live `ctx.llm`
|
|
2823
|
+
* registry — never hardcoded, so a model the adapter does not advertise
|
|
2824
|
+
* cannot appear.
|
|
2825
|
+
* @returns one entry per registered provider with its models.
|
|
2826
|
+
*/
|
|
2827
|
+
async catalog() {
|
|
2828
|
+
return this.bindings.service.catalog();
|
|
2829
|
+
}
|
|
2830
|
+
/**
|
|
2831
|
+
* Set the session override for one agent and return the refreshed status.
|
|
2832
|
+
* `auto` clears the override; every other mode pins the session. Runtime only.
|
|
2833
|
+
* @param mode - the routing mode to pin, or `auto` to follow the composition mode.
|
|
2834
|
+
* @param agentId - the calling session/agent id (required: the override is per agent).
|
|
2835
|
+
* @returns the refreshed status for that agent.
|
|
2836
|
+
* @throws {TypeError} when the mode is outside the routing vocabulary.
|
|
2837
|
+
* @throws {Error} when no agent id is supplied or the id names no live agent.
|
|
2838
|
+
*/
|
|
2839
|
+
setMode(mode, agentId) {
|
|
2840
|
+
if (!ROUTING_MODES.includes(mode)) throw new TypeError(`tier.setMode: unknown routing mode ${JSON.stringify(mode)}`);
|
|
2841
|
+
if (agentId === void 0 || agentId === "") throw new Error("tier.setMode requires the calling session id (agentId)");
|
|
2842
|
+
const agent = this.bindings.resolveAgent(agentId);
|
|
2843
|
+
if (agent === void 0) throw new Error(`tier.setMode: no live agent for session ${JSON.stringify(agentId)}`);
|
|
2844
|
+
const state = this.bindings.states.for(agent);
|
|
2845
|
+
state.override = mode === "auto" ? void 0 : mode;
|
|
2846
|
+
this.ctx.logger.info("dsh-autotier: session %s routing mode set to %s via the client", agentId, mode);
|
|
2847
|
+
return this.status(agentId);
|
|
2848
|
+
}
|
|
2849
|
+
/** Project the shared per-agent runtime state onto the wire view. */
|
|
2850
|
+
viewFor(agentId, base) {
|
|
2851
|
+
const id = agentId === void 0 || agentId === "" ? null : agentId;
|
|
2852
|
+
const resolved = id === null ? void 0 : this.bindings.resolveAgent(id);
|
|
2853
|
+
if (resolved === void 0) return {
|
|
2854
|
+
agentId: id,
|
|
2855
|
+
override: null,
|
|
2856
|
+
mode: base.mode,
|
|
2857
|
+
appliedTier: null,
|
|
2858
|
+
appliedSource: null,
|
|
2859
|
+
escalation: false,
|
|
2860
|
+
plan: false,
|
|
2861
|
+
denials: 0
|
|
2862
|
+
};
|
|
2863
|
+
const state = this.bindings.states.for(resolved);
|
|
2864
|
+
const override = state.override ?? null;
|
|
2865
|
+
return {
|
|
2866
|
+
agentId: id,
|
|
2867
|
+
override,
|
|
2868
|
+
mode: override ?? base.mode,
|
|
2869
|
+
appliedTier: state.appliedTier ?? null,
|
|
2870
|
+
appliedSource: state.appliedSource ?? null,
|
|
2871
|
+
escalation: escalationActive(state, Date.now()),
|
|
2872
|
+
plan: state.planActive,
|
|
2873
|
+
denials: state.denials
|
|
2874
|
+
};
|
|
2875
|
+
}
|
|
2876
|
+
};
|
|
2877
|
+
//#endregion
|
|
2675
2878
|
//#region src/tools.ts
|
|
2676
2879
|
/** Render one canonical value as a single text block. */
|
|
2677
2880
|
function textBlock(value) {
|
|
@@ -2840,9 +3043,22 @@ function apply(ctx, config = {}) {
|
|
|
2840
3043
|
service,
|
|
2841
3044
|
states
|
|
2842
3045
|
});
|
|
3046
|
+
new TierRemoteService(ctx, {
|
|
3047
|
+
service,
|
|
3048
|
+
states,
|
|
3049
|
+
resolveAgent: (agentId) => {
|
|
3050
|
+
const agents = ctx.get("agents");
|
|
3051
|
+
if (agents === void 0) return void 0;
|
|
3052
|
+
try {
|
|
3053
|
+
return agents.get(agentId);
|
|
3054
|
+
} catch {
|
|
3055
|
+
return;
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
});
|
|
2843
3059
|
if (resolved.guard.interopDefend === "auto") ctx.logger.info("dsh-autotier: guard runs alongside dsh-defend when installed (guard.interopDefend=auto)");
|
|
2844
3060
|
const status = service.status();
|
|
2845
3061
|
ctx.logger.info("dsh-autotier: mode=%s strong=%s/%s cheap=%s/%s guard=%s", status.mode, status.tiers.strong.provider, status.tiers.strong.model, status.tiers.cheap.provider, status.tiers.cheap.model, status.guard.enabled ? "on" : "off");
|
|
2846
3062
|
}
|
|
2847
3063
|
//#endregion
|
|
2848
|
-
export { AgentStateStore, AutotierRouter, AutotierService, Config, EFFORT_IDS, HIGH_IMPACT_COMMAND_RULES, HIGH_IMPACT_PATH_RULES, JUDGE_LABELS, PosteriorTable, ROUTING_MODES, SCENARIOS, TIER_IDS, TIER_PROJECTION_KEY, advanceFallback, apply, attemptBandApplies, classifyFallback, classifyIntent, compileRules, computeSignals, createRouteState, decideTier, effortRank, escalationActive, escalationLadder, evaluateRules, evaluateToolCall, fallbackActive, fingerprintOf, inject, isCredentialPath, judgeNeeded, matchCommand, matchPath, name, nextEffortStep, noteFailure, noteFallback, noteJudgeCall, parseJudgeLabel, redactSnippet, registerGuardHook, registerTierProjection, resolveConfig, resolveJudgeRoute, resolveRoute, routeEquals, runJudge, validateConfig, wilsonLowerBound };
|
|
3064
|
+
export { AgentStateStore, AutotierRouter, AutotierService, Config, EFFORT_IDS, HIGH_IMPACT_COMMAND_RULES, HIGH_IMPACT_PATH_RULES, JUDGE_LABELS, PosteriorTable, ROUTE_SOURCES, ROUTING_MODES, SCENARIOS, TIER_AGENT_ID_SCHEMA, TIER_CATALOG_DESCRIPTOR, TIER_CATALOG_SCHEMA, TIER_IDS, TIER_INVOCATIONS, TIER_MODE_SCHEMA, TIER_NAMESPACE, TIER_PROJECTION_KEY, TIER_SESSION_VIEW_SCHEMA, TIER_SET_MODE_DESCRIPTOR, TIER_STATUS_DESCRIPTOR, TIER_STATUS_SCHEMA, TierRemoteService, advanceFallback, apply, attemptBandApplies, classifyFallback, classifyIntent, compileRules, computeSignals, createRouteState, decideTier, effortRank, escalationActive, escalationLadder, evaluateRules, evaluateToolCall, fallbackActive, fingerprintOf, inject, isCredentialPath, judgeNeeded, matchCommand, matchPath, name, nextEffortStep, noteFailure, noteFallback, noteJudgeCall, parseJudgeLabel, redactSnippet, registerGuardHook, registerTierProjection, resolveConfig, resolveJudgeRoute, resolveRoute, routeEquals, runJudge, validateConfig, wilsonLowerBound };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { a as TIER_INVOCATIONS } from "./wire-BpKSOHgo.js";
|
|
2
|
+
//#region src/typert.host.ts
|
|
3
|
+
/**
|
|
4
|
+
* The hand-written Typert HOST manifest for `dsh-autotier`, exported as
|
|
5
|
+
* `./typert` so the harness's typert-loader registers the `tier`
|
|
6
|
+
* status/catalog/setMode invocations automatically when this plugin mounts.
|
|
7
|
+
* Same shape as a generator output (validated by the loader): package face,
|
|
8
|
+
* empty model and schemas, and the canonical invocation list shared with the
|
|
9
|
+
* client Remote contribution (`src/wire.ts`).
|
|
10
|
+
*
|
|
11
|
+
* @module dsh-autotier/typert
|
|
12
|
+
*/
|
|
13
|
+
/** Host Typert manifest (validated by `@deepseek-ai/dsh-typert-loader`). */
|
|
14
|
+
const TYPERT = Object.freeze({
|
|
15
|
+
package: "dsh-autotier",
|
|
16
|
+
face: "host",
|
|
17
|
+
schemas: Object.freeze([]),
|
|
18
|
+
invocations: TIER_INVOCATIONS,
|
|
19
|
+
model: Object.freeze({
|
|
20
|
+
services: Object.freeze([]),
|
|
21
|
+
events: Object.freeze([]),
|
|
22
|
+
objects: Object.freeze([])
|
|
23
|
+
})
|
|
24
|
+
});
|
|
25
|
+
//#endregion
|
|
26
|
+
export { TYPERT };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The composer tier pill: the session's effective routing mode with an
|
|
3
|
+
* escalation badge. A click cycles the session override through
|
|
4
|
+
* `auto -> strong -> cheap -> off` over `tier/setMode`; the host answers with
|
|
5
|
+
* the refreshed snapshot, so the pill never shows an unconfirmed state.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-autotier/client/TierPill
|
|
8
|
+
*/
|
|
9
|
+
import { type ReactNode } from 'react';
|
|
10
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
11
|
+
import type { RoutingMode } from '../types.js';
|
|
12
|
+
import type { TierStatus } from '../wire.js';
|
|
13
|
+
/** Registration-side injected face: the two Remote calls bound to this session. */
|
|
14
|
+
export interface TierPillInjected {
|
|
15
|
+
/** Read this session's snapshot. */
|
|
16
|
+
status: () => Promise<TierStatus>;
|
|
17
|
+
/** Pin or clear this session's routing mode. */
|
|
18
|
+
setMode: (mode: RoutingMode) => Promise<TierStatus>;
|
|
19
|
+
}
|
|
20
|
+
/** Full component props assembled by the composer tool-row renderer. */
|
|
21
|
+
export type TierPillProps = PropsRuntime<'conversation.input.left'> & PropsLocale<'settings.autotier'> & InjectFace<TierPillInjected>;
|
|
22
|
+
/** The composer pill body. */
|
|
23
|
+
export declare function TierPill({ status, setMode, t }: TierPillProps): ReactNode;
|
|
24
|
+
//# sourceMappingURL=TierPill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TierPill.d.ts","sourceRoot":"","sources":["../../../src/client/TierPill.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC7F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG5C,mFAAmF;AACnF,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,MAAM,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAA;IACjC,gDAAgD;IAChD,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;CACpD;AAED,wEAAwE;AACxE,MAAM,MAAM,aAAa,GACvB,YAAY,CAAC,yBAAyB,CAAC,GACrC,WAAW,CAAC,mBAAmB,CAAC,GAChC,UAAU,CAAC,gBAAgB,CAAC,CAAA;AAEhC,8BAA8B;AAC9B,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,aAAa,GAAG,SAAS,CAoDzE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The autotier Settings card (Plugins section): the session routing-mode
|
|
3
|
+
* selector, the read-only tier landings, the live session state, and the model
|
|
4
|
+
* catalog dropdown fed by `tier/catalog`.
|
|
5
|
+
*
|
|
6
|
+
* The selector writes the *session* override for the session currently open in
|
|
7
|
+
* the shell (resolved by the client entry through the sessions store face), so
|
|
8
|
+
* it stays non-persistent exactly like the pill and `/tier`. When no session is
|
|
9
|
+
* open the host answers with an empty session view and the selector is disabled
|
|
10
|
+
* with an explanation instead of failing silently.
|
|
11
|
+
*
|
|
12
|
+
* @module dsh-autotier/client/TierSettingsCard
|
|
13
|
+
*/
|
|
14
|
+
import { type ReactNode } from 'react';
|
|
15
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
16
|
+
import { type RoutingMode } from '../types.js';
|
|
17
|
+
import type { TierCatalog, TierStatus } from '../wire.js';
|
|
18
|
+
/** Registration-side injected face: the three Remote calls bound to this card. */
|
|
19
|
+
export interface TierSettingsInjected {
|
|
20
|
+
/** Read the current session's snapshot. */
|
|
21
|
+
status: () => Promise<TierStatus>;
|
|
22
|
+
/** Read the live provider/model catalog. */
|
|
23
|
+
catalog: () => Promise<TierCatalog>;
|
|
24
|
+
/** Pin or clear the current session's routing mode. */
|
|
25
|
+
setMode: (mode: RoutingMode) => Promise<TierStatus>;
|
|
26
|
+
}
|
|
27
|
+
/** Full component props assembled by the Plugins-tab renderer. */
|
|
28
|
+
export type TierSettingsCardProps = PropsRuntime<'settings.plugins.tab'> & PropsLocale<'settings.autotier'> & InjectFace<TierSettingsInjected>;
|
|
29
|
+
/** The Settings card body. */
|
|
30
|
+
export declare function TierSettingsCard({ status, catalog, setMode, t }: TierSettingsCardProps): ReactNode;
|
|
31
|
+
//# sourceMappingURL=TierSettingsCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TierSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/TierSettingsCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC7F,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAGzD,kFAAkF;AAClF,MAAM,WAAW,oBAAoB;IACnC,2CAA2C;IAC3C,MAAM,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAA;IACjC,4CAA4C;IAC5C,OAAO,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAA;IACnC,uDAAuD;IACvD,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;CACpD;AAED,kEAAkE;AAClE,MAAM,MAAM,qBAAqB,GAC/B,YAAY,CAAC,sBAAsB,CAAC,GAClC,WAAW,CAAC,mBAAmB,CAAC,GAChC,UAAU,CAAC,oBAAoB,CAAC,CAAA;AAOpC,8BAA8B;AAC9B,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAoIlG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dsh-autotier`, browser half: mounts the `tier` Remote contribution, then
|
|
3
|
+
* registers the composer tier pill into `conversation.input.left` and the
|
|
4
|
+
* autotier card into the Plugins settings section (`settings.plugins.tab`, id
|
|
5
|
+
* `autotier`). All data arrives through the `remote.tier` namespace — the pill
|
|
6
|
+
* binds the session id the slot factory hands it, the Settings card resolves the
|
|
7
|
+
* session currently open in the shell through the sessions store face.
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-autotier/client
|
|
10
|
+
*/
|
|
11
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
12
|
+
export type { TierPillInjected, TierPillProps } from './TierPill.js';
|
|
13
|
+
export type { TierSettingsCardProps, TierSettingsInjected } from './TierSettingsCard.js';
|
|
14
|
+
export type { AutotierLocaleKey } from './locales.js';
|
|
15
|
+
export { catalogEntries, landingText, landings, modalityText, modeKey, nextMode, PILL_CYCLE, pillView, statusDetail, tierKey, } from './present.js';
|
|
16
|
+
export type { TierCatalogEntry, TierPillView, TierTone } from './present.js';
|
|
17
|
+
/** Dictionary namespace owned by this plugin. */
|
|
18
|
+
export declare const NS = "settings.autotier";
|
|
19
|
+
/** Plugin name: matches the package name, the graph row id, and the bundle id. */
|
|
20
|
+
export declare const name = "dsh-autotier";
|
|
21
|
+
/** Services the browser half reads; `remote.tier` appears once this plugin mounts its contribution. */
|
|
22
|
+
export declare const inject: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Browser plugin body: dictionaries, the scoped stylesheet, the Remote
|
|
25
|
+
* contribution mount, the composer pill and the Settings card.
|
|
26
|
+
*
|
|
27
|
+
* @param ctx - client root context.
|
|
28
|
+
*/
|
|
29
|
+
export declare function apply(ctx: ClientContext): Promise<void>;
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAiBnE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACrE,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AACzF,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,EACL,cAAc,EACd,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,OAAO,GACR,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAe5E,iDAAiD;AACjD,eAAO,MAAM,EAAE,sBAAsB,CAAA;AAErC,kFAAkF;AAClF,eAAO,MAAM,IAAI,iBAAiB,CAAA;AAElC,uGAAuG;AACvG,eAAO,MAAM,MAAM,UAAgC,CAAA;AAEnD;;;;;GAKG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAqD7D"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copy dictionaries for the autotier client surfaces (en + zh, the two locales
|
|
3
|
+
* the shared locale registry ships). Every key must exist in both dictionaries:
|
|
4
|
+
* the typed `register` call checks that at compile time, and the presenter test
|
|
5
|
+
* re-checks it at runtime.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-autotier/client/locales
|
|
8
|
+
*/
|
|
9
|
+
/** Simplified Chinese dictionary. */
|
|
10
|
+
export declare const zh: {
|
|
11
|
+
readonly tab: "自动分层";
|
|
12
|
+
readonly loading: "正在读取分层状态…";
|
|
13
|
+
readonly pillLoading: "分层…";
|
|
14
|
+
readonly error: "暂时无法读取分层状态。";
|
|
15
|
+
readonly retry: "重试";
|
|
16
|
+
readonly refresh: "刷新";
|
|
17
|
+
readonly mode: "路由模式";
|
|
18
|
+
readonly modeHint: "仅对当前会话生效;插件重载后恢复 cordis.yml 配置。";
|
|
19
|
+
readonly modeAuto: "自动";
|
|
20
|
+
readonly modeStrong: "强模型";
|
|
21
|
+
readonly modeCheap: "轻量模型";
|
|
22
|
+
readonly modeDelegated: "会话指定";
|
|
23
|
+
readonly modeOff: "关闭";
|
|
24
|
+
readonly pillHint: "点击切换当前会话的路由模式";
|
|
25
|
+
readonly escalated: "已升级";
|
|
26
|
+
readonly landings: "分层落点(只读)";
|
|
27
|
+
readonly tierStrong: "强模型层";
|
|
28
|
+
readonly tierCheap: "轻量层";
|
|
29
|
+
readonly tierVision: "视觉层";
|
|
30
|
+
readonly followsSession: "跟随会话推理强度";
|
|
31
|
+
readonly effort: "推理强度";
|
|
32
|
+
readonly catalog: "模型目录";
|
|
33
|
+
readonly catalogHint: "来自当前已注册的服务商与模型,仅供查看。";
|
|
34
|
+
readonly catalogSelect: "选择模型";
|
|
35
|
+
readonly provider: "服务商";
|
|
36
|
+
readonly model: "模型";
|
|
37
|
+
readonly modalities: "输入模态";
|
|
38
|
+
readonly session: "会话状态";
|
|
39
|
+
readonly sessionOverride: "会话覆盖";
|
|
40
|
+
readonly sessionFollow: "跟随配置";
|
|
41
|
+
readonly appliedTier: "最近落点";
|
|
42
|
+
readonly appliedNone: "暂无";
|
|
43
|
+
readonly escalationActive: "失败升级中";
|
|
44
|
+
readonly planActive: "计划模式";
|
|
45
|
+
readonly denials: "守卫拦截";
|
|
46
|
+
readonly source: "来源";
|
|
47
|
+
readonly noSession: "尚未选择会话:先打开一个会话,才能修改会话模式。";
|
|
48
|
+
readonly unknownAgent: "当前会话尚未注册到路由服务,暂时无法修改模式。";
|
|
49
|
+
};
|
|
50
|
+
/** English dictionary (source of truth for keys). */
|
|
51
|
+
export declare const en: Record<keyof typeof zh, string>;
|
|
52
|
+
/** Every dictionary key. */
|
|
53
|
+
export type AutotierLocaleKey = keyof typeof zh;
|
|
54
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
55
|
+
interface LocaleNamespaceMap {
|
|
56
|
+
/** Autotier settings card and composer pill copy. */
|
|
57
|
+
'settings.autotier': AutotierLocaleKey;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,qCAAqC;AACrC,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCL,CAAA;AAEV,qDAAqD;AACrD,eAAO,MAAM,EAAE,EAAE,MAAM,CAAC,MAAM,OAAO,EAAE,EAAE,MAAM,CAuCrC,CAAA;AAEV,4BAA4B;AAC5B,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,EAAE,CAAA;AAE/C,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,qDAAqD;QACrD,mBAAmB,EAAE,iBAAiB,CAAA;KACvC;CACF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure presentation helpers for the autotier client surfaces: the pill's tone
|
|
3
|
+
* and badge, the mode cycle, locale-key mapping, and the catalog flattening.
|
|
4
|
+
* Every function is a pure function of the wire payload — replay-safe and
|
|
5
|
+
* unit-testable without a browser or a React runtime.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-autotier/client/present
|
|
8
|
+
*/
|
|
9
|
+
import type { RoutingMode, TierId, TierRoute } from '../types.js';
|
|
10
|
+
import type { TierCatalog, TierModelInfo, TierStatus } from '../wire.js';
|
|
11
|
+
import type { AutotierLocaleKey } from './locales.js';
|
|
12
|
+
/** The four visible pill states plus the delegated one. */
|
|
13
|
+
export type TierTone = 'auto' | 'strong' | 'cheap' | 'delegated' | 'off';
|
|
14
|
+
/** The composer pill's derived view. */
|
|
15
|
+
export interface TierPillView {
|
|
16
|
+
/** Effective mode for the session the pill is bound to. */
|
|
17
|
+
readonly mode: RoutingMode;
|
|
18
|
+
/** Visual tone, keyed off the effective mode. */
|
|
19
|
+
readonly tone: TierTone;
|
|
20
|
+
/** Uppercase badge text (`AUTO` | `STRONG` | `CHEAP` | `OFF` | `DELEGATED`). */
|
|
21
|
+
readonly label: string;
|
|
22
|
+
/** Whether the escalation badge is shown. */
|
|
23
|
+
readonly escalation: boolean;
|
|
24
|
+
/** Technical one-line summary used as the button's tooltip. */
|
|
25
|
+
readonly detail: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The pill's click cycle. `delegated` is deliberately absent: it names a state
|
|
29
|
+
* the session carries by itself, not a mode a click should pin. The Settings
|
|
30
|
+
* card still offers every mode.
|
|
31
|
+
*/
|
|
32
|
+
export declare const PILL_CYCLE: readonly RoutingMode[];
|
|
33
|
+
/** One flattened catalog option. */
|
|
34
|
+
export interface TierCatalogEntry {
|
|
35
|
+
/** Stable option value: `provider/modelId`. */
|
|
36
|
+
readonly value: string;
|
|
37
|
+
readonly provider: string;
|
|
38
|
+
readonly model: TierModelInfo;
|
|
39
|
+
}
|
|
40
|
+
/** The next mode in the pill's cycle (an off-cycle mode restarts at `auto`). */
|
|
41
|
+
export declare function nextMode(mode: RoutingMode): RoutingMode;
|
|
42
|
+
/** The locale key naming one routing mode. */
|
|
43
|
+
export declare function modeKey(mode: RoutingMode): AutotierLocaleKey;
|
|
44
|
+
/** The locale key naming one tier. */
|
|
45
|
+
export declare function tierKey(tier: TierId): AutotierLocaleKey;
|
|
46
|
+
/** The pill view for one status snapshot. */
|
|
47
|
+
export declare function pillView(status: TierStatus): TierPillView;
|
|
48
|
+
/** The technical one-line summary of a snapshot (never localized). */
|
|
49
|
+
export declare function statusDetail(status: TierStatus): string;
|
|
50
|
+
/** Render one tier landing: `provider/model`, with ` @effort` when it carries one. */
|
|
51
|
+
export declare function landingText(route: TierRoute): string;
|
|
52
|
+
/** Render one model's input modalities. */
|
|
53
|
+
export declare function modalityText(model: TierModelInfo): string;
|
|
54
|
+
/** Flatten the catalog into select options, preserving provider/model order. */
|
|
55
|
+
export declare function catalogEntries(catalog: TierCatalog): readonly TierCatalogEntry[];
|
|
56
|
+
/** The three configured landings in display order. */
|
|
57
|
+
export declare function landings(status: TierStatus): readonly {
|
|
58
|
+
readonly tier: TierId | 'vision';
|
|
59
|
+
readonly route: TierRoute;
|
|
60
|
+
}[];
|
|
61
|
+
//# sourceMappingURL=present.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"present.d.ts","sourceRoot":"","sources":["../../../src/client/present.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAErD,2DAA2D;AAC3D,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,WAAW,GAAG,KAAK,CAAA;AAExE,wCAAwC;AACxC,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,6CAA6C;IAC7C,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,WAAW,EAAuC,CAAA;AAEpF,oCAAoC;AACpC,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;CAC9B;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAIvD;AAED,8CAA8C;AAC9C,wBAAgB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,iBAAiB,CAQ5D;AAED,sCAAsC;AACtC,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAEvD;AAED,6CAA6C;AAC7C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,CASzD;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAWvD;AAED,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAGpD;AAED,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAEzD;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,gBAAgB,EAAE,CAQhF;AAED,sDAAsD;AACtD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,EAAE,CAMvH"}
|