dsh-model-switch 0.4.25 → 0.4.27
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/CHANGELOG.md +25 -0
- package/PRODUCT.md +3 -3
- package/README.md +3 -3
- package/README.zh.md +2 -2
- package/cordis.patch.yml +18 -472
- package/lib/auto-review.js +1 -1
- package/lib/compaction.js +1 -1
- package/lib/index.js +150 -0
- package/lib/session-route-BjNPlliu.js +172 -0
- package/lib/session-title.js +387 -34
- package/lib/subagent-runtime.js +26 -3
- package/lib/types/preset-sync.d.ts +64 -0
- package/lib/types/session-title.d.ts +194 -14
- package/lib/types/subagent-runtime.d.ts +10 -0
- package/package.json +3 -2
|
@@ -8,25 +8,40 @@
|
|
|
8
8
|
* saved group is named through that group's pair while every other session keeps
|
|
9
9
|
* following its own model.
|
|
10
10
|
*
|
|
11
|
-
* The call itself stays inside the official implementation: the
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* without a registered provider.
|
|
11
|
+
* The call itself stays inside the official implementation: the auxiliary-LLM
|
|
12
|
+
* package records exactly the route that was called in `session/title-llm-request`,
|
|
13
|
+
* so the durable record and the actual request can never disagree. Nothing is
|
|
14
|
+
* remounted when settings change — the route is read through on every naming
|
|
15
|
+
* request — so a settings save can neither interrupt an in-flight naming request
|
|
16
|
+
* nor leave the profile without a registered provider.
|
|
18
17
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* Two official auxiliary-LLM lines are supported, selected at runtime from the
|
|
19
|
+
* module surface, because the 0.2.1 release replaced the shared title call:
|
|
20
|
+
* - Up to DSH 0.2.0 (`generateSessionTitleWithLlm`): the module owns the system
|
|
21
|
+
* prompt, input framing, and output validation; the shared policy carries the
|
|
22
|
+
* title-length targets.
|
|
23
|
+
* - DSH 0.2.1+ (`executeSessionTitleLlm`): the provider owns the system prompt,
|
|
24
|
+
* the input, the reasoning-effort selection, and the output interpretation;
|
|
25
|
+
* the shared policy carries execution controls only. This row mirrors the
|
|
26
|
+
* official provider's wording and interpretation so a configured route keeps
|
|
27
|
+
* the official behavior.
|
|
28
|
+
*
|
|
29
|
+
* A naming request that fails is retried once with a widened output budget
|
|
30
|
+
* (max-token failures only) and then falls through the remaining route
|
|
31
|
+
* candidates — the session group's pair, the deployment-wide pair, the row's own
|
|
32
|
+
* pair, then the session's logged route — so one unavailable model or provider
|
|
33
|
+
* cannot leave the session on its deterministic fallback title forever.
|
|
34
|
+
*
|
|
35
|
+
* `cordis.patch.yml` disables the official rows (the seam allows one registered
|
|
36
|
+
* provider per context), and this row mirrors the cadence a disabled row
|
|
21
37
|
* declared, so a profile that restated the row as all-prompts keeps its cadence.
|
|
22
38
|
*
|
|
23
39
|
* @module dsh-model-switch/session-title
|
|
24
40
|
*/
|
|
25
41
|
import type { Context } from '@deepseek-ai/cordis';
|
|
26
42
|
import type { Entry, Loader } from '@deepseek-ai/cordis-plugin-loader';
|
|
27
|
-
import type { SessionTitleAutomaticMode, SessionTitleProviderId, SessionTitleUserMessage } from '@deepseek-ai/dsh-session-title';
|
|
28
|
-
import type
|
|
29
|
-
import { type CapabilityRoute } from './session-route.js';
|
|
43
|
+
import type { SessionTitleAutomaticMode, SessionTitleProviderId, SessionTitleProviderRequest, SessionTitleUserMessage } from '@deepseek-ai/dsh-session-title';
|
|
44
|
+
import { type CapabilityRoute, type RouteBearingSettings } from './session-route.js';
|
|
30
45
|
/** Cordis plugin identity; matches the cordis.patch.yml insert row id. */
|
|
31
46
|
export declare const name = "model-switch-session-title";
|
|
32
47
|
/** The loader names the disabled row, and the seam services the call needs are awaited before the first naming request. */
|
|
@@ -44,6 +59,57 @@ export interface TitleCadence {
|
|
|
44
59
|
}
|
|
45
60
|
/** Both official cadence packages, in the order a profile may declare them. */
|
|
46
61
|
export declare const TITLE_CADENCES: readonly TitleCadence[];
|
|
62
|
+
/** Title-length targets that shape the system instruction. */
|
|
63
|
+
export interface TitleLengthTargets {
|
|
64
|
+
readonly targetWords: number;
|
|
65
|
+
readonly targetCjkCharacters: number;
|
|
66
|
+
}
|
|
67
|
+
/** Route-bearing execution policy shared by both official auxiliary-LLM lines. */
|
|
68
|
+
export interface TitleLlmPolicy {
|
|
69
|
+
readonly maxInputBytes: number;
|
|
70
|
+
readonly maxOutputTokens: number;
|
|
71
|
+
readonly timeoutMs: number;
|
|
72
|
+
readonly provider?: string;
|
|
73
|
+
readonly model?: string;
|
|
74
|
+
}
|
|
75
|
+
/** The model metadata `executeSessionTitleLlm` hands its reasoning selector. */
|
|
76
|
+
export interface TitleModelMetadata {
|
|
77
|
+
readonly reasoning?: {
|
|
78
|
+
readonly efforts?: readonly {
|
|
79
|
+
readonly id: string;
|
|
80
|
+
}[];
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** Provider-owned preparation for one 0.2.1+ auxiliary title request. */
|
|
84
|
+
export interface PreparedTitleCall {
|
|
85
|
+
readonly system: string;
|
|
86
|
+
readonly input: string;
|
|
87
|
+
readonly messageSeqs: readonly SessionTitleUserMessage['seq'][];
|
|
88
|
+
readonly selectReasoningEffort: (model: TitleModelMetadata) => string | undefined;
|
|
89
|
+
}
|
|
90
|
+
/** One content block of the assembled 0.2.1+ auxiliary response. */
|
|
91
|
+
export interface TitleResponseBlock {
|
|
92
|
+
readonly type: string;
|
|
93
|
+
readonly text?: string;
|
|
94
|
+
}
|
|
95
|
+
/** The assembled 0.2.1+ auxiliary response this row interprets. */
|
|
96
|
+
export interface TitleLlmResponse {
|
|
97
|
+
readonly blocks: readonly TitleResponseBlock[];
|
|
98
|
+
readonly finish: {
|
|
99
|
+
readonly kind: string;
|
|
100
|
+
};
|
|
101
|
+
readonly model: {
|
|
102
|
+
readonly provider: string;
|
|
103
|
+
readonly model: string;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/** The auxiliary-LLM module surface; the call entry point differs per DSH line. */
|
|
107
|
+
type TitleLlmModule = typeof import('@deepseek-ai/dsh-session-title-llm');
|
|
108
|
+
/** The untrusted policy split both lines consume. */
|
|
109
|
+
export interface SplitTitlePolicy {
|
|
110
|
+
readonly execution: Record<string, unknown>;
|
|
111
|
+
readonly targets: TitleLengthTargets;
|
|
112
|
+
}
|
|
47
113
|
/**
|
|
48
114
|
* The cadence one official package name declares.
|
|
49
115
|
* @param pkg - the disabled row's package name.
|
|
@@ -61,7 +127,7 @@ export declare function titleCadence(pkg: string | undefined): TitleCadence | un
|
|
|
61
127
|
* @param route - session-resolved naming route, or undefined for the row's own policy.
|
|
62
128
|
* @returns A detached config for one naming request.
|
|
63
129
|
*/
|
|
64
|
-
export declare function composeTitleRoute(config:
|
|
130
|
+
export declare function composeTitleRoute(config: TitleLlmPolicy, route: CapabilityRoute | undefined): TitleLlmPolicy;
|
|
65
131
|
/**
|
|
66
132
|
* Frame the exact human messages one naming revision represents.
|
|
67
133
|
* @param messages - every eligible human message of the revision.
|
|
@@ -84,13 +150,126 @@ export declare function officialTitleEntry(loader: Loader | undefined): Entry |
|
|
|
84
150
|
* result is untrusted: the profile may be hand-edited, so the official policy
|
|
85
151
|
* validator runs over it before any naming request is served.
|
|
86
152
|
*/
|
|
87
|
-
export declare function forwardedConfig(entry: Entry):
|
|
153
|
+
export declare function forwardedConfig(entry: Entry): Record<string, unknown>;
|
|
88
154
|
/**
|
|
89
155
|
* The official package name this row mounts (either cadence).
|
|
90
156
|
* @param entry - the official session-title provider entry.
|
|
91
157
|
* @returns The package name, or undefined when the row declares none.
|
|
92
158
|
*/
|
|
93
159
|
export declare function officialTitlePackage(entry: Entry): string | undefined;
|
|
160
|
+
/**
|
|
161
|
+
* Split one untrusted stored policy into the halves both official lines accept.
|
|
162
|
+
*
|
|
163
|
+
* Execution controls pass through untouched (an invalid value still fails the
|
|
164
|
+
* official validator). Absent execution fields fall back to the shipped
|
|
165
|
+
* official defaults, because a profile that mounts no official row has no
|
|
166
|
+
* policy to forward and this row must still run. Title-length targets are read
|
|
167
|
+
* here for the system instruction: the pre-0.2.1 line wants them in its shared
|
|
168
|
+
* config, while 0.2.1 moved them into each provider.
|
|
169
|
+
* @param forwarded - the disabled official row's stored config.
|
|
170
|
+
* @returns The execution subset and the title-length targets.
|
|
171
|
+
*/
|
|
172
|
+
export declare function splitTitlePolicy(forwarded: Record<string, unknown>): SplitTitlePolicy;
|
|
173
|
+
/**
|
|
174
|
+
* Detect the 0.2.1+ auxiliary-LLM line.
|
|
175
|
+
* @param module - the loaded auxiliary-LLM package.
|
|
176
|
+
* @returns Whether the module exposes the provider-prepared call.
|
|
177
|
+
*/
|
|
178
|
+
export declare function isModernTitleModule(module: TitleLlmModule): boolean;
|
|
179
|
+
/** One validated naming policy: the execution config plus the targets the system instruction needs. */
|
|
180
|
+
export interface ResolvedNamingPolicy {
|
|
181
|
+
readonly config: TitleLlmPolicy;
|
|
182
|
+
readonly targets: TitleLengthTargets;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Validate the stored policy through the official validator of the installed line.
|
|
186
|
+
* @param module - the loaded auxiliary-LLM package.
|
|
187
|
+
* @param forwarded - the disabled official row's stored config.
|
|
188
|
+
* @returns The validated execution config and title-length targets.
|
|
189
|
+
* @throws when the official validator rejects the stored policy.
|
|
190
|
+
*/
|
|
191
|
+
export declare function resolveNamingPolicy(module: TitleLlmModule, forwarded: Record<string, unknown>): ResolvedNamingPolicy;
|
|
192
|
+
/**
|
|
193
|
+
* Candidate routes for one naming request, most specific first and deduplicated.
|
|
194
|
+
*
|
|
195
|
+
* The stored session group's pair wins, then the deployment-wide pair, then the
|
|
196
|
+
* row's own configured pair, then the session's logged route. The list is also
|
|
197
|
+
* the fallback order: a failing candidate falls through to the next one.
|
|
198
|
+
* @param settings - live Model Switch settings; undefined skips the stored pairs.
|
|
199
|
+
* @param provider - the delegating session's provider, when one is observable.
|
|
200
|
+
* @param policy - the validated row policy (its own pair is the third candidate).
|
|
201
|
+
* @param requestRoute - the session's logged main-request route, when one exists.
|
|
202
|
+
* @returns The ordered, deduplicated candidates; empty when only the row policy applies.
|
|
203
|
+
*/
|
|
204
|
+
export declare function titleRouteCandidates(settings: RouteBearingSettings | undefined, provider: string | undefined, policy: TitleLlmPolicy, requestRoute: CapabilityRoute | undefined): readonly CapabilityRoute[];
|
|
205
|
+
/**
|
|
206
|
+
* Whether a failure may be retried on another candidate.
|
|
207
|
+
* A superseded or disposed request keeps no budget, and a deadline that fired is
|
|
208
|
+
* the caller's bound, not the route's fault: both end the attempt loop.
|
|
209
|
+
* @param error - the failure thrown by the auxiliary call.
|
|
210
|
+
* @param request - the service-owned request whose signal bounds the work.
|
|
211
|
+
* @returns Whether another candidate may be tried.
|
|
212
|
+
*/
|
|
213
|
+
export declare function shouldTryNextCandidate(error: unknown, request: SessionTitleProviderRequest): boolean;
|
|
214
|
+
/**
|
|
215
|
+
* Whether the failure is the model filling its output budget before finishing.
|
|
216
|
+
* Official lines report this as `title output reached maxOutputTokens`; a widened
|
|
217
|
+
* budget is the only retry that can succeed for it.
|
|
218
|
+
* @param error - the failure thrown by the auxiliary call.
|
|
219
|
+
* @returns Whether one widened-budget retry is worth trying.
|
|
220
|
+
*/
|
|
221
|
+
export declare function isMaxTokensFailure(error: unknown): boolean;
|
|
222
|
+
/**
|
|
223
|
+
* A widened output budget for the same route.
|
|
224
|
+
* @param maxOutputTokens - the policy's configured budget.
|
|
225
|
+
* @returns Four times the budget, capped at 4096 tokens.
|
|
226
|
+
*/
|
|
227
|
+
export declare function widerTitleBudget(maxOutputTokens: number): number;
|
|
228
|
+
/**
|
|
229
|
+
* Normalize one accepted title exactly like the official service.
|
|
230
|
+
* @param input - untrusted title text.
|
|
231
|
+
* @returns A terminal-safe, whitespace-normalized one-line title, possibly empty.
|
|
232
|
+
*/
|
|
233
|
+
export declare function normalizeTitleText(input: string): string;
|
|
234
|
+
/**
|
|
235
|
+
* Take the title from model output: the first non-empty line, without asterisk
|
|
236
|
+
* emphasis wrapping that whole line. Models that disregard the one-line
|
|
237
|
+
* instruction put the title first and commentary after it.
|
|
238
|
+
* @param text - joined text blocks of the auxiliary response.
|
|
239
|
+
* @returns The candidate title line.
|
|
240
|
+
*/
|
|
241
|
+
export declare function titleFromOutput(text: string): string;
|
|
242
|
+
/**
|
|
243
|
+
* Interpret one assembled 0.2.1+ response as a title.
|
|
244
|
+
* Rejects terminal tool-call and max-token outcomes exactly like the official
|
|
245
|
+
* provider, so the row keeps the official acceptance rules.
|
|
246
|
+
* @param response - the assembled auxiliary response.
|
|
247
|
+
* @returns A non-empty normalized title.
|
|
248
|
+
* @throws when the finish reason, a tool-call block, or empty text makes the response unusable.
|
|
249
|
+
*/
|
|
250
|
+
export declare function titleFromResponse(response: TitleLlmResponse): string;
|
|
251
|
+
/**
|
|
252
|
+
* Select the route's least supported reasoning effort for a title call, as the
|
|
253
|
+
* official 0.2.1 provider does: naming is a short auxiliary task, and a full
|
|
254
|
+
* reasoning budget can consume the whole output allowance.
|
|
255
|
+
* @param model - the prepared model metadata.
|
|
256
|
+
* @returns The first declared effort id, or undefined when the model has none.
|
|
257
|
+
*/
|
|
258
|
+
export declare function selectTitleReasoningEffort(model: TitleModelMetadata): string | undefined;
|
|
259
|
+
/**
|
|
260
|
+
* The official 0.2.1+ system instruction, including the optional current-title anchor.
|
|
261
|
+
* @param targets - title-length targets.
|
|
262
|
+
* @param hasCurrentTitle - whether the request is anchored to an existing provider title.
|
|
263
|
+
* @returns The system prompt text.
|
|
264
|
+
*/
|
|
265
|
+
export declare function titleSystemPrompt(targets: TitleLengthTargets, hasCurrentTitle: boolean): string;
|
|
266
|
+
/**
|
|
267
|
+
* Frame the exact messages as JSON so user text cannot break structural delimiters.
|
|
268
|
+
* @param messages - the selected human messages.
|
|
269
|
+
* @param currentTitle - the accepted provider title to anchor on, when there is one.
|
|
270
|
+
* @returns The framed user input.
|
|
271
|
+
*/
|
|
272
|
+
export declare function frameTitleInput(messages: readonly SessionTitleUserMessage[], currentTitle: string | undefined): string;
|
|
94
273
|
/**
|
|
95
274
|
* Mount the Model Switch session-naming row for this profile.
|
|
96
275
|
*
|
|
@@ -102,3 +281,4 @@ export declare function officialTitlePackage(entry: Entry): string | undefined;
|
|
|
102
281
|
* @param ctx - this row's context.
|
|
103
282
|
*/
|
|
104
283
|
export declare function apply(ctx: Context): Promise<void>;
|
|
284
|
+
export {};
|
|
@@ -48,6 +48,16 @@ export declare function routeSubagentRequest<T extends RoutableSubagentRequest>(
|
|
|
48
48
|
* @throws the fallback startup error when fallback startup fails.
|
|
49
49
|
*/
|
|
50
50
|
export declare function mountWithStartupFallback<T>(candidate: (track: StartupCleanupTracker) => Promise<T>, fallback: (track: StartupCleanupTracker) => Promise<T>): Promise<MountedStartup<T>>;
|
|
51
|
+
/**
|
|
52
|
+
* Operator-facing notice for a Host whose Subagent runtime cannot be routed.
|
|
53
|
+
*
|
|
54
|
+
* DSH 0.2.1 replaced `start()`/`startContinuable()` with the activation API, so
|
|
55
|
+
* this adapter's override point is gone; the row then mounts the untouched
|
|
56
|
+
* official runtime instead of guessing a new seam.
|
|
57
|
+
* @param error - the typed startup incompatibility that rejected the candidate.
|
|
58
|
+
* @returns The notice logged once at startup.
|
|
59
|
+
*/
|
|
60
|
+
export declare function routedRuntimeUnavailableNotice(error: StartupIncompatibilityError): string;
|
|
51
61
|
/** Profile replacement that selects the routed runtime or the untouched official runtime. */
|
|
52
62
|
export declare const profileSubagentRuntime: ((ctx: Context) => Promise<() => Promise<void>>) & {
|
|
53
63
|
inject: string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-model-switch",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.27",
|
|
4
4
|
"description": "Explicit model routing plus composer/Plan picker for DeepSeek Harness",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -106,7 +106,8 @@
|
|
|
106
106
|
"0.1.7-alpha.2": "compatible",
|
|
107
107
|
"0.1.7-rc.1": "compatible",
|
|
108
108
|
"0.1.7-rc.2": "compatible",
|
|
109
|
-
"0.2.0-rc.2": "compatible"
|
|
109
|
+
"0.2.0-rc.2": "compatible",
|
|
110
|
+
"0.2.1-rc.2": "compatible"
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
},
|