dsh-model-switch 0.4.20 → 0.4.22
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 +220 -203
- package/IMPLEMENTATION_PLAN.md +40 -40
- package/LICENSE +21 -21
- package/PRODUCT.md +33 -33
- package/README.md +218 -208
- package/README.zh.md +216 -206
- package/cordis.patch.yml +515 -30
- package/lib/client.js +845 -258
- package/lib/compaction.js +205 -0
- package/lib/index.js +100 -242
- package/lib/types/capabilities-rpc.d.ts +2 -3
- package/lib/types/client/ModelSwitchSettings.d.ts +5 -2
- package/lib/types/client/derived-settings-scope.d.ts +4 -4
- package/lib/types/client/locales.d.ts +12 -3
- package/lib/types/client/picker/PlanReviewCard.d.ts +0 -3
- package/lib/types/client/picker/locales.d.ts +0 -8
- package/lib/types/client/remote-settings-scope.d.ts +45 -45
- package/lib/types/client-contract.d.ts +13 -4
- package/lib/types/compaction.d.ts +56 -0
- package/lib/types/host-runtime.d.ts +6 -28
- package/lib/types/host-settings.d.ts +17 -30
- package/lib/types/picker/plan-goal.d.ts +29 -3
- package/lib/types/provider-group.d.ts +78 -0
- package/package.json +360 -356
- package/lib/types/picker/plan-compact.d.ts +0 -48
- package/lib/types/plan-compact.d.ts +0 -82
|
@@ -38,9 +38,18 @@ export declare const zh: {
|
|
|
38
38
|
readonly autoReviewFollow: "跟随会话模型";
|
|
39
39
|
readonly autoReviewHelp: "为官方 auto-review(Auto 权限预设的逐调用审查)指定审查模型;需启用官方 auto-review 能力包。关闭时审查跟随当前会话模型。";
|
|
40
40
|
readonly autoReviewRouteHelp: "审查请求固定使用这里的 Provider/模型,与会话模型无关;保存后对下一次审查立即生效。";
|
|
41
|
-
readonly
|
|
42
|
-
readonly
|
|
43
|
-
readonly
|
|
41
|
+
readonly compaction: "压缩模型";
|
|
42
|
+
readonly compactionFollow: "跟随会话模型";
|
|
43
|
+
readonly compactionHelp: "为官方压缩(/compact 与官方自动压缩)指定摘要模型;关闭(两个字段都留空)时使用官方默认,即当前会话的目标模型。";
|
|
44
|
+
readonly compactionRouteHelp: "摘要请求固定使用这里的 Provider/模型,与会话目标模型无关;保存后对下一次压缩立即生效。保存时若恰有压缩进行中,可能被打断并在下次重试。";
|
|
45
|
+
readonly providerGroups: "供应商配置组";
|
|
46
|
+
readonly providerGroupsCard: "按供应商预设路由";
|
|
47
|
+
readonly providerGroupsSummary: "切换主模型供应商时自动应用对应组";
|
|
48
|
+
readonly providerGroupsHelp: "为压缩、子代理、审查按供应商分别保存路由。";
|
|
49
|
+
readonly providerGroupsBodyHelp: "每个供应商保存一组压缩、子代理、审查路由;主模型切换到该供应商时,这三条路由自动写入上方对应卡片。切换到未配置的供应商时现有路由保持不变;应用会覆盖三张卡片的当前值(含手动修改)。";
|
|
50
|
+
readonly providerGroupPick: "选择供应商以编辑其配置组。";
|
|
51
|
+
readonly providerGroupDelete: "删除该组";
|
|
52
|
+
readonly providerGroupApplyFailed: "主模型已保存,但供应商组应用失败:";
|
|
44
53
|
readonly 'reason.central-subagent-routing': "Alpha.4 没有全局子代理启动路由接口。";
|
|
45
54
|
readonly 'reason.packaged-preset-roots': "Alpha.4 不支持插件提供额外 preset root。";
|
|
46
55
|
readonly 'reason.tool-owner-suppression': "Alpha.4 没有工具所有者或来源抑制接口。";
|
|
@@ -3,7 +3,6 @@ import type { ConfigFormSnapshot } from '@deepseek-ai/dsh-client-ui-settings/cli
|
|
|
3
3
|
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
4
4
|
import type { MainSettingsView } from '../../client-contract.ts';
|
|
5
5
|
import { type GoalRemote } from '../../picker/plan-goal.ts';
|
|
6
|
-
import type { PlanCompactOutcome } from '../../picker/plan-compact.ts';
|
|
7
6
|
import type { PlanPreviewBinding } from './plan-preview.ts';
|
|
8
7
|
import { type PickerDirectoryFace } from './PickerDirectory.ts';
|
|
9
8
|
import type { PickerInteractionOperations } from './popup-dismissal.ts';
|
|
@@ -29,8 +28,6 @@ export interface PlanReviewFace extends PickerDirectoryFace {
|
|
|
29
28
|
goalRemote: () => GoalRemote | undefined;
|
|
30
29
|
/** Full-plan sidebar navigation (ui-plan's registered opener). */
|
|
31
30
|
planPreview: PlanPreviewBinding;
|
|
32
|
-
/** Host-backed pre-execution compaction; absent seams degrade to no compaction. */
|
|
33
|
-
planCompact?: (sessionId: string, provider: string, model: string) => Promise<PlanCompactOutcome>;
|
|
34
31
|
/** Live catalog-group-id → card-key map from ProviderDirectory. */
|
|
35
32
|
catalogRoutes?: () => Readonly<Record<string, string>>;
|
|
36
33
|
}
|
|
@@ -51,10 +51,6 @@ export declare const zh: {
|
|
|
51
51
|
'plan.goalUnsupported': string;
|
|
52
52
|
'plan.responseRejected': string;
|
|
53
53
|
'plan.cancelRejected': string;
|
|
54
|
-
'plan.compacting': string;
|
|
55
|
-
'plan.compacted': string;
|
|
56
|
-
'plan.compactEmpty': string;
|
|
57
|
-
'plan.compactFailed': string;
|
|
58
54
|
'markdown.copy': string;
|
|
59
55
|
'markdown.copied': string;
|
|
60
56
|
'markdown.footnotes': string;
|
|
@@ -112,10 +108,6 @@ export declare const en: {
|
|
|
112
108
|
'plan.goalUnsupported': string;
|
|
113
109
|
'plan.responseRejected': string;
|
|
114
110
|
'plan.cancelRejected': string;
|
|
115
|
-
'plan.compacting': string;
|
|
116
|
-
'plan.compacted': string;
|
|
117
|
-
'plan.compactEmpty': string;
|
|
118
|
-
'plan.compactFailed': string;
|
|
119
111
|
'markdown.copy': string;
|
|
120
112
|
'markdown.copied': string;
|
|
121
113
|
'markdown.footnotes': string;
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
import type { SettingsPathOpView } from '@deepseek-ai/dsh-api-remotes/client';
|
|
2
|
-
import type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
3
|
-
interface RemoteError {
|
|
4
|
-
code: string;
|
|
5
|
-
message: string;
|
|
6
|
-
}
|
|
7
|
-
interface RemoteResult<T> {
|
|
8
|
-
ok: boolean;
|
|
9
|
-
value?: T;
|
|
10
|
-
error?: RemoteError;
|
|
11
|
-
}
|
|
12
|
-
interface NamespaceView {
|
|
13
|
-
ns: string;
|
|
14
|
-
value: unknown;
|
|
15
|
-
base?: unknown;
|
|
16
|
-
user?: unknown;
|
|
17
|
-
revision: number;
|
|
18
|
-
}
|
|
19
|
-
interface DescribeValue {
|
|
20
|
-
writable: boolean;
|
|
21
|
-
namespaces: readonly NamespaceView[];
|
|
22
|
-
}
|
|
23
|
-
export interface RemoteSettingsFace {
|
|
24
|
-
describe(): Promise<RemoteResult<DescribeValue>>;
|
|
25
|
-
mutate(ns: string, ops: readonly unknown[], expectedRevision: number | undefined): Promise<RemoteResult<NamespaceView>>;
|
|
26
|
-
}
|
|
27
|
-
/** Host-backed settings scope used by this plugin on authenticated remote browsers. */
|
|
28
|
-
export declare class RemoteSettingsScope<T> implements SettingsScope<T> {
|
|
29
|
-
private readonly api;
|
|
30
|
-
private readonly namespace;
|
|
31
|
-
private readonly decode;
|
|
32
|
-
private snapshot;
|
|
33
|
-
private readonly listeners;
|
|
34
|
-
constructor(api: RemoteSettingsFace, namespace: string, decode: (value: unknown) => T | undefined);
|
|
35
|
-
getSnapshot: () => SettingsScopeSnapshot<T>;
|
|
36
|
-
subscribe: (listener: () => void) => (() => void);
|
|
37
|
-
reload(): Promise<void>;
|
|
38
|
-
set(field: string, value: unknown): Promise<void>;
|
|
39
|
-
unset(field: string): Promise<void>;
|
|
40
|
-
mutate(ops: readonly SettingsPathOpView[], expectedRevision?: number): Promise<void>;
|
|
41
|
-
private write;
|
|
42
|
-
private accept;
|
|
43
|
-
private publish;
|
|
44
|
-
}
|
|
45
|
-
export {};
|
|
1
|
+
import type { SettingsPathOpView } from '@deepseek-ai/dsh-api-remotes/client';
|
|
2
|
+
import type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
3
|
+
interface RemoteError {
|
|
4
|
+
code: string;
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
interface RemoteResult<T> {
|
|
8
|
+
ok: boolean;
|
|
9
|
+
value?: T;
|
|
10
|
+
error?: RemoteError;
|
|
11
|
+
}
|
|
12
|
+
interface NamespaceView {
|
|
13
|
+
ns: string;
|
|
14
|
+
value: unknown;
|
|
15
|
+
base?: unknown;
|
|
16
|
+
user?: unknown;
|
|
17
|
+
revision: number;
|
|
18
|
+
}
|
|
19
|
+
interface DescribeValue {
|
|
20
|
+
writable: boolean;
|
|
21
|
+
namespaces: readonly NamespaceView[];
|
|
22
|
+
}
|
|
23
|
+
export interface RemoteSettingsFace {
|
|
24
|
+
describe(): Promise<RemoteResult<DescribeValue>>;
|
|
25
|
+
mutate(ns: string, ops: readonly unknown[], expectedRevision: number | undefined): Promise<RemoteResult<NamespaceView>>;
|
|
26
|
+
}
|
|
27
|
+
/** Host-backed settings scope used by this plugin on authenticated remote browsers. */
|
|
28
|
+
export declare class RemoteSettingsScope<T> implements SettingsScope<T> {
|
|
29
|
+
private readonly api;
|
|
30
|
+
private readonly namespace;
|
|
31
|
+
private readonly decode;
|
|
32
|
+
private snapshot;
|
|
33
|
+
private readonly listeners;
|
|
34
|
+
constructor(api: RemoteSettingsFace, namespace: string, decode: (value: unknown) => T | undefined);
|
|
35
|
+
getSnapshot: () => SettingsScopeSnapshot<T>;
|
|
36
|
+
subscribe: (listener: () => void) => (() => void);
|
|
37
|
+
reload(): Promise<void>;
|
|
38
|
+
set(field: string, value: unknown): Promise<void>;
|
|
39
|
+
unset(field: string): Promise<void>;
|
|
40
|
+
mutate(ops: readonly SettingsPathOpView[], expectedRevision?: number): Promise<void>;
|
|
41
|
+
private write;
|
|
42
|
+
private accept;
|
|
43
|
+
private publish;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ProviderGroupsStorage } from './provider-group.js';
|
|
1
2
|
export declare const MODEL_SWITCH_CONFIG_ID = "model-switch";
|
|
2
3
|
export declare const MAIN_DEFAULT_CONFIG_ID = "agent-default-model";
|
|
3
4
|
export declare const PROVIDERS_CONFIG_ID = "llm-providers-ui";
|
|
@@ -21,8 +22,10 @@ export interface ModelSwitchSettingsView {
|
|
|
21
22
|
compactOnSwitch?: boolean;
|
|
22
23
|
autoReviewProvider?: string;
|
|
23
24
|
autoReviewModel?: string;
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
compactProvider?: string;
|
|
26
|
+
compactModel?: string;
|
|
27
|
+
/** Raw saved per-provider groups; edited whole through the provider-groups card. */
|
|
28
|
+
providerGroups?: ProviderGroupsStorage;
|
|
26
29
|
}
|
|
27
30
|
export interface SubagentSettingsView {
|
|
28
31
|
mode: 'follow-main' | 'fixed';
|
|
@@ -55,9 +58,15 @@ export declare const AUTO_REVIEW_SETTINGS_FIELDS: Readonly<{
|
|
|
55
58
|
readonly provider: "autoReviewProvider";
|
|
56
59
|
readonly model: "autoReviewModel";
|
|
57
60
|
}>;
|
|
61
|
+
/** Compaction summarization route for `/compact` and automatic compaction; both unset means the official default (the conversation target). */
|
|
62
|
+
export declare const COMPACTION_SETTINGS_FIELDS: Readonly<{
|
|
63
|
+
readonly provider: "compactProvider";
|
|
64
|
+
readonly model: "compactModel";
|
|
65
|
+
}>;
|
|
58
66
|
export declare function deriveSubagentSettings(settings: ModelSwitchSettingsView): SubagentSettingsView;
|
|
59
67
|
export declare function deriveSearchSettings(settings: ModelSwitchSettingsView): CapabilityRouteView;
|
|
60
68
|
export declare function deriveImageSettings(settings: ModelSwitchSettingsView): CapabilityRouteView;
|
|
61
69
|
export declare function deriveAutoReviewSettings(settings: ModelSwitchSettingsView): CapabilityRouteView;
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
export declare function deriveCompactionSettings(settings: ModelSwitchSettingsView): CapabilityRouteView;
|
|
71
|
+
/** Whether both fields of a model route form a complete pair; an incomplete pair stays off. */
|
|
72
|
+
export declare function routePairConfigured(route: CapabilityRouteView | undefined): boolean;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { Entry, Loader } from '@deepseek-ai/cordis-plugin-loader';
|
|
3
|
+
import type { BasicCompactionConfig } from '@deepseek-ai/dsh-compaction-basic';
|
|
4
|
+
/** Cordis plugin identity; matches the cordis.patch.yml insert row id. */
|
|
5
|
+
export declare const name = "model-switch-compaction";
|
|
6
|
+
/** The loader is awaited at row activation; settings and the official row are still read structurally so stock compaction survives a disabled Model Switch row. */
|
|
7
|
+
export declare const inject: string[];
|
|
8
|
+
/** Both identifiers trimmed and non-empty; undefined means "official default". */
|
|
9
|
+
export interface CompactionRoute {
|
|
10
|
+
readonly provider: string;
|
|
11
|
+
readonly model: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the configurable summarization route from live settings.
|
|
15
|
+
* @param settings - Model Switch settings carrying the optional compaction pair.
|
|
16
|
+
* @returns Both identifiers trimmed and non-empty, or undefined (official default).
|
|
17
|
+
*/
|
|
18
|
+
export declare function compactionRouteOf(settings: {
|
|
19
|
+
readonly compactProvider?: string;
|
|
20
|
+
readonly compactModel?: string;
|
|
21
|
+
} | undefined): CompactionRoute | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Merge the resolved route over the official row's own config.
|
|
24
|
+
* @param forwarded - config the official compaction-basic row was configured with.
|
|
25
|
+
* @param route - resolved summarization route; undefined keeps official behavior.
|
|
26
|
+
* @returns A detached config safe to hand to a fresh engine construction.
|
|
27
|
+
*/
|
|
28
|
+
export declare function composeCompactionConfig(forwarded: BasicCompactionConfig, route: CompactionRoute | undefined): BasicCompactionConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Locate the official compaction row in the loader tree.
|
|
31
|
+
* Disabled entries stay in the tree, so a name-matched disable still matches.
|
|
32
|
+
* @param loader - the host loader, when one is reachable.
|
|
33
|
+
* @returns The official entry, or undefined when this profile has no such row.
|
|
34
|
+
*/
|
|
35
|
+
export declare function officialCompactionEntry(loader: Loader | undefined): Entry | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Copy the official row's stored config, ignoring non-object payloads.
|
|
38
|
+
* @param entry - the official compaction entry.
|
|
39
|
+
* @returns A plain object spread; missing or invalid configs become `{}`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function forwardedConfig(entry: Entry): BasicCompactionConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Mount the Model Switch compaction engine for this profile.
|
|
44
|
+
*
|
|
45
|
+
* Installs a sibling row that replaces the official compaction-basic engine
|
|
46
|
+
* with the same package under the configurable summarization route. Host
|
|
47
|
+
* settings and the loader are read structurally so a disabled `model-switch`
|
|
48
|
+
* row leaves official compaction untouched. Reconciles run on
|
|
49
|
+
* `model-switch/settings-update` (emitted by the host on volatile commits and
|
|
50
|
+
* ordinary saves); the listener is global so instances of this row inside
|
|
51
|
+
* agent-preset realms still hear the host row's emission. The initial
|
|
52
|
+
* reconcile is awaited so `/compact` resolves the service as soon as this row
|
|
53
|
+
* completes.
|
|
54
|
+
* @param ctx - this row's context.
|
|
55
|
+
*/
|
|
56
|
+
export declare function apply(ctx: Context): Promise<void>;
|
|
@@ -1,43 +1,21 @@
|
|
|
1
1
|
import { Context, Service } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { ModelSelection } from '@deepseek-ai/dsh-agent';
|
|
3
3
|
import type { AgentDefaultModelConfig } from '@deepseek-ai/dsh-agent-default-model';
|
|
4
|
-
import { type Config as ModelSwitchSettingsConfig, type ModelSwitchSettings } from './host-settings.js';
|
|
4
|
+
import { Config, type Config as ModelSwitchSettingsConfig, type ModelSwitchSettings } from './host-settings.js';
|
|
5
5
|
import { ModelSwitchAdapterRegistry } from './adapter-registry.js';
|
|
6
6
|
declare module '@deepseek-ai/cordis' {
|
|
7
7
|
interface Context {
|
|
8
8
|
modelSwitch: ModelSwitchRuntime;
|
|
9
9
|
}
|
|
10
|
+
interface Events {
|
|
11
|
+
/** Model Switch settings changed; reread via `modelSwitch.currentSettings()`. */
|
|
12
|
+
'model-switch/settings-update'(): void;
|
|
13
|
+
}
|
|
10
14
|
}
|
|
11
15
|
/** Host owner for Model Switch settings and the released Main-default adapter. */
|
|
12
16
|
export declare class ModelSwitchRuntime extends Service {
|
|
13
17
|
static inject: string[];
|
|
14
|
-
static Config: import("@deepseek-ai/schemastery").default<
|
|
15
|
-
subagentMode: import("@deepseek-ai/schemastery").default<"follow-main" | "fixed", "follow-main" | "fixed", "volatile-defined">;
|
|
16
|
-
subagentProvider: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
17
|
-
subagentModel: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
18
|
-
subagentReasoningEffort: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
19
|
-
searchProvider: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
20
|
-
searchModel: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
21
|
-
imageProvider: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
22
|
-
imageModel: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
23
|
-
compactOnSwitch: import("@deepseek-ai/schemastery").default<boolean, boolean, "volatile-defined">;
|
|
24
|
-
autoReviewProvider: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
25
|
-
autoReviewModel: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
26
|
-
planCompactThreshold: import("@deepseek-ai/schemastery").default<number, number, "volatile-defined">;
|
|
27
|
-
}>>, Schemastery.ObjectT<NoInfer<{
|
|
28
|
-
subagentMode: import("@deepseek-ai/schemastery").default<"follow-main" | "fixed", "follow-main" | "fixed", "volatile-defined">;
|
|
29
|
-
subagentProvider: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
30
|
-
subagentModel: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
31
|
-
subagentReasoningEffort: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
32
|
-
searchProvider: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
33
|
-
searchModel: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
34
|
-
imageProvider: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
35
|
-
imageModel: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
36
|
-
compactOnSwitch: import("@deepseek-ai/schemastery").default<boolean, boolean, "volatile-defined">;
|
|
37
|
-
autoReviewProvider: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
38
|
-
autoReviewModel: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
39
|
-
planCompactThreshold: import("@deepseek-ai/schemastery").default<number, number, "volatile-defined">;
|
|
40
|
-
}>>, "plain">;
|
|
18
|
+
static Config: import("@deepseek-ai/schemastery").default<any, Config, "plain">;
|
|
41
19
|
get capabilities(): {
|
|
42
20
|
searchProviderAdapters: {
|
|
43
21
|
available: boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Volatile } from '@deepseek-ai/cordis';
|
|
2
2
|
import z from '@deepseek-ai/schemastery';
|
|
3
|
+
import { type ProviderGroupEntry, type ProviderGroups } from './provider-group.js';
|
|
3
4
|
export type SubagentMode = 'follow-main' | 'fixed';
|
|
4
5
|
/** Resolved live values consumed by Model Switch. */
|
|
5
6
|
export interface ModelSwitchSettings {
|
|
@@ -16,8 +17,12 @@ export interface ModelSwitchSettings {
|
|
|
16
17
|
autoReviewProvider?: string;
|
|
17
18
|
/** Reviewer model for the Auto preset; set together with `autoReviewProvider`. */
|
|
18
19
|
autoReviewModel?: string;
|
|
19
|
-
/**
|
|
20
|
-
|
|
20
|
+
/** Summarization provider for `/compact` and automatic compaction; both fields unset = official default (the conversation target). */
|
|
21
|
+
compactProvider?: string;
|
|
22
|
+
/** Summarization model for `/compact` and automatic compaction; set together with `compactProvider`. */
|
|
23
|
+
compactModel?: string;
|
|
24
|
+
/** Per-provider compaction/subagent/review presets, keyed by provider id; absent when no group is saved. */
|
|
25
|
+
providerGroups?: ProviderGroups;
|
|
21
26
|
}
|
|
22
27
|
/** Loader-owned references; every field is directly editable in the profile form. */
|
|
23
28
|
export interface Config {
|
|
@@ -32,33 +37,15 @@ export interface Config {
|
|
|
32
37
|
compactOnSwitch: Volatile<boolean>;
|
|
33
38
|
autoReviewProvider: Volatile<string | undefined>;
|
|
34
39
|
autoReviewModel: Volatile<string | undefined>;
|
|
35
|
-
|
|
40
|
+
compactProvider: Volatile<string | undefined>;
|
|
41
|
+
compactModel: Volatile<string | undefined>;
|
|
42
|
+
/** Saved per-provider capability groups as one entry per provider; entry route fields are '' when the capability stays at its default. */
|
|
43
|
+
providerGroups: Volatile<readonly ProviderGroupEntry[]>;
|
|
36
44
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
searchModel: z<string, string, "volatile">;
|
|
44
|
-
imageProvider: z<string, string, "volatile">;
|
|
45
|
-
imageModel: z<string, string, "volatile">;
|
|
46
|
-
compactOnSwitch: z<boolean, boolean, "volatile-defined">;
|
|
47
|
-
autoReviewProvider: z<string, string, "volatile">;
|
|
48
|
-
autoReviewModel: z<string, string, "volatile">;
|
|
49
|
-
planCompactThreshold: z<number, number, "volatile-defined">;
|
|
50
|
-
}>>, Schemastery.ObjectT<NoInfer<{
|
|
51
|
-
subagentMode: z<"follow-main" | "fixed", "follow-main" | "fixed", "volatile-defined">;
|
|
52
|
-
subagentProvider: z<string, string, "volatile">;
|
|
53
|
-
subagentModel: z<string, string, "volatile">;
|
|
54
|
-
subagentReasoningEffort: z<string, string, "volatile">;
|
|
55
|
-
searchProvider: z<string, string, "volatile">;
|
|
56
|
-
searchModel: z<string, string, "volatile">;
|
|
57
|
-
imageProvider: z<string, string, "volatile">;
|
|
58
|
-
imageModel: z<string, string, "volatile">;
|
|
59
|
-
compactOnSwitch: z<boolean, boolean, "volatile-defined">;
|
|
60
|
-
autoReviewProvider: z<string, string, "volatile">;
|
|
61
|
-
autoReviewModel: z<string, string, "volatile">;
|
|
62
|
-
planCompactThreshold: z<number, number, "volatile-defined">;
|
|
63
|
-
}>>, "plain">;
|
|
45
|
+
/**
|
|
46
|
+
* Annotated rather than inferred: the nested entry schema's inferred type
|
|
47
|
+
* expands to cosmokit internals (`Dict`) that cannot be named in the emitted
|
|
48
|
+
* declaration, and the annotation pins the output shape to this interface.
|
|
49
|
+
*/
|
|
50
|
+
export declare const Config: z<any, Config, 'plain'>;
|
|
64
51
|
export declare function readConfig(config: Config): ModelSwitchSettings;
|
|
@@ -61,8 +61,33 @@ export type GoalHandoff = {
|
|
|
61
61
|
readonly code?: string;
|
|
62
62
|
readonly message: string;
|
|
63
63
|
};
|
|
64
|
+
/** Identity of the plan document under review, for its durable address. */
|
|
65
|
+
export interface PlanDocumentRef {
|
|
66
|
+
/** Logged tool invocation that owns the plan; absent while only the review is pending. */
|
|
67
|
+
readonly callId?: string;
|
|
68
|
+
/** Browser-unique pending request identity (the review card's key). */
|
|
69
|
+
readonly requestKey: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Address the plan document exactly as the official opener does.
|
|
73
|
+
*
|
|
74
|
+
* A logged plan (`callId` present) resolves from `dsh-resource://plan/...`
|
|
75
|
+
* for as long as the session log holds the call; before that the pending
|
|
76
|
+
* review's own `dsh-resource://plan-review/...` address is the one that
|
|
77
|
+
* opens its preview.
|
|
78
|
+
*
|
|
79
|
+
* @param sessionId - the session that owns the review.
|
|
80
|
+
* @param ref - logged call identity plus the pending request key.
|
|
81
|
+
* @returns The plan resource address.
|
|
82
|
+
*/
|
|
83
|
+
export declare function planDocumentAddress(sessionId: string, ref: PlanDocumentRef): string;
|
|
64
84
|
/**
|
|
65
|
-
* Make
|
|
85
|
+
* Make this plan the session's armed goal, replacing any unfinished goal.
|
|
86
|
+
*
|
|
87
|
+
* The objective is a short instruction carrying the plan document's address,
|
|
88
|
+
* not the plan's raw markdown: goal objectives are injected into every round,
|
|
89
|
+
* and a full plan would be truncated by length limits mid-sentence. The round
|
|
90
|
+
* driver reads the plan from the address instead.
|
|
66
91
|
*
|
|
67
92
|
* Ordering mirrors the card's own commit-then-answer rule: a refusal here keeps
|
|
68
93
|
* the Plan pending instead of approving work that no goal tracks. The replace
|
|
@@ -71,7 +96,8 @@ export type GoalHandoff = {
|
|
|
71
96
|
*
|
|
72
97
|
* @param remote - the released goal remote, absent when no goal package is mounted.
|
|
73
98
|
* @param sessionId - the session that owns both the review and the goal.
|
|
74
|
-
* @param plan - the plan markdown under review.
|
|
99
|
+
* @param plan - the plan markdown under review (validated non-empty).
|
|
100
|
+
* @param ref - the plan document identity used for its address.
|
|
75
101
|
* @returns Whether the goal now tracks this plan, or why it does not.
|
|
76
102
|
*/
|
|
77
|
-
export declare function setPlanAsGoal(remote: GoalRemote | undefined, sessionId: string, plan: string): Promise<GoalHandoff>;
|
|
103
|
+
export declare function setPlanAsGoal(remote: GoalRemote | undefined, sessionId: string, plan: string, ref: PlanDocumentRef): Promise<GoalHandoff>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider configuration groups: per-provider presets for the compaction,
|
|
3
|
+
* subagent, and auto-review routes.
|
|
4
|
+
*
|
|
5
|
+
* A group stores the exact flat settings fields it will write, so applying a
|
|
6
|
+
* group is a plain settings-layer write: every capability consumer keeps
|
|
7
|
+
* reading the live values unchanged. All functions here are pure and never
|
|
8
|
+
* throw on malformed storage.
|
|
9
|
+
*/
|
|
10
|
+
import type { SubagentMode } from './host-settings.js';
|
|
11
|
+
/** Flat settings fields a provider group can pin — exactly what an application writes. */
|
|
12
|
+
export type ProviderGroupRouteField = 'compactProvider' | 'compactModel' | 'autoReviewProvider' | 'autoReviewModel' | 'subagentProvider' | 'subagentModel' | 'subagentReasoningEffort';
|
|
13
|
+
/** Stored entry: the owning provider plus every route field; '' means the capability stays at its default. */
|
|
14
|
+
export interface ProviderGroupEntry {
|
|
15
|
+
provider: string;
|
|
16
|
+
compactProvider: string;
|
|
17
|
+
compactModel: string;
|
|
18
|
+
autoReviewProvider: string;
|
|
19
|
+
autoReviewModel: string;
|
|
20
|
+
subagentProvider: string;
|
|
21
|
+
subagentModel: string;
|
|
22
|
+
subagentReasoningEffort: string;
|
|
23
|
+
}
|
|
24
|
+
/** Normalized view of one provider's group; absent fields follow their default state. */
|
|
25
|
+
export type ProviderGroupConfig = Partial<Record<ProviderGroupRouteField, string>>;
|
|
26
|
+
/** Normalized provider → group map. */
|
|
27
|
+
export type ProviderGroups = Readonly<Record<string, ProviderGroupConfig>>;
|
|
28
|
+
/** Storage shape of the volatile `providerGroups` config field: one entry per provider. */
|
|
29
|
+
export type ProviderGroupsStorage = readonly ProviderGroupEntry[];
|
|
30
|
+
/**
|
|
31
|
+
* Strip a raw stored value to well-formed groups; never throws. Both storage
|
|
32
|
+
* shapes are accepted: the stored entry array (keys live in each entry's
|
|
33
|
+
* `provider` field) and a hand-written provider → routes map (keys are the
|
|
34
|
+
* providers). All-empty entries stay: they pin a provider to every default.
|
|
35
|
+
*/
|
|
36
|
+
export declare function normalizeProviderGroups(raw: unknown): ProviderGroups;
|
|
37
|
+
/**
|
|
38
|
+
* The saved group for a provider.
|
|
39
|
+
* @returns the normalized group, or undefined when the provider has no group —
|
|
40
|
+
* which is what leaves the live routes untouched during a switch.
|
|
41
|
+
*/
|
|
42
|
+
export declare function groupOf(groups: ProviderGroups | undefined, provider: string): ProviderGroupConfig | undefined;
|
|
43
|
+
/** One application write; `value` undefined means "unset this field". */
|
|
44
|
+
export type ProviderGroupWrite = {
|
|
45
|
+
readonly field: 'subagentMode';
|
|
46
|
+
readonly mode: SubagentMode;
|
|
47
|
+
} | {
|
|
48
|
+
readonly field: ProviderGroupRouteField;
|
|
49
|
+
readonly value: string | undefined;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Ordered writes applying one group with full-replacement semantics: pinned
|
|
53
|
+
* capabilities land as pairs, everything else reverts to its default state
|
|
54
|
+
* (compaction/review follow the session model; Subagent follows official
|
|
55
|
+
* inherit). The mode write comes last so a fixed route never publishes with
|
|
56
|
+
* the previous provider's fields still half-written.
|
|
57
|
+
*/
|
|
58
|
+
export declare function providerGroupWrites(group: ProviderGroupConfig): ProviderGroupWrite[];
|
|
59
|
+
/** Storage entry for one provider's group; absent or blank route fields become ''. */
|
|
60
|
+
export declare function entryOf(provider: string, group: ProviderGroupConfig): ProviderGroupEntry;
|
|
61
|
+
/**
|
|
62
|
+
* The stored entry list with one provider's group replaced (an entry) or
|
|
63
|
+
* removed (undefined). Every entry is re-normalized and de-duplicated so a
|
|
64
|
+
* save can never write junk back; the input is never mutated. A blank
|
|
65
|
+
* provider only normalizes.
|
|
66
|
+
*/
|
|
67
|
+
export declare function withProviderGroup(storage: unknown, provider: string, group: ProviderGroupConfig | undefined): ProviderGroupsStorage;
|
|
68
|
+
/** Minimal writable settings surface an application needs; satisfied by the owned ConfigForm. */
|
|
69
|
+
export interface ProviderGroupSink {
|
|
70
|
+
set(field: 'subagentMode' | ProviderGroupRouteField, value: string): Promise<unknown>;
|
|
71
|
+
unset(field: ProviderGroupRouteField): Promise<unknown>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Apply a saved group's routes to the live flat settings.
|
|
75
|
+
* @returns true when a group existed and every write settled; false when the
|
|
76
|
+
* provider has no group (nothing was written). A rejected write propagates.
|
|
77
|
+
*/
|
|
78
|
+
export declare function applyProviderGroupTo(sink: ProviderGroupSink, groups: ProviderGroups | undefined, provider: string): Promise<boolean>;
|