dsh-autotier 0.1.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 +93 -0
- package/CHANGELOG.md +85 -0
- package/LICENSE +201 -0
- package/README.es.md +247 -0
- package/README.hi.md +241 -0
- package/README.md +245 -0
- package/README.pt.md +246 -0
- package/README.zh.md +221 -0
- package/SECURITY.md +55 -0
- package/THIRD_PARTY_NOTICES.md +63 -0
- package/cordis.patch.yml +125 -0
- package/docs/preset-row.md +61 -0
- package/docs/supporting-lanes.md +45 -0
- package/lib/index.js +2848 -0
- package/lib/types/command.d.ts +17 -0
- package/lib/types/command.d.ts.map +1 -0
- package/lib/types/config.d.ts +94 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/guard-rules.d.ts +97 -0
- package/lib/types/guard-rules.d.ts.map +1 -0
- package/lib/types/guard.d.ts +70 -0
- package/lib/types/guard.d.ts.map +1 -0
- package/lib/types/index.d.ts +60 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/intent.d.ts +179 -0
- package/lib/types/intent.d.ts.map +1 -0
- package/lib/types/judge.d.ts +50 -0
- package/lib/types/judge.d.ts.map +1 -0
- package/lib/types/policy.d.ts +109 -0
- package/lib/types/policy.d.ts.map +1 -0
- package/lib/types/routing.d.ts +135 -0
- package/lib/types/routing.d.ts.map +1 -0
- package/lib/types/schema.d.ts +134 -0
- package/lib/types/schema.d.ts.map +1 -0
- package/lib/types/service.d.ts +67 -0
- package/lib/types/service.d.ts.map +1 -0
- package/lib/types/state.d.ts +46 -0
- package/lib/types/state.d.ts.map +1 -0
- package/lib/types/tiers.d.ts +103 -0
- package/lib/types/tiers.d.ts.map +1 -0
- package/lib/types/tools.d.ts +26 -0
- package/lib/types/tools.d.ts.map +1 -0
- package/lib/types/types.d.ts +96 -0
- package/lib/types/types.d.ts.map +1 -0
- package/package.json +179 -0
- package/src/command.ts +73 -0
- package/src/config.ts +358 -0
- package/src/guard-rules.ts +303 -0
- package/src/guard.ts +285 -0
- package/src/index.ts +149 -0
- package/src/intent.ts +484 -0
- package/src/judge.ts +150 -0
- package/src/policy.ts +246 -0
- package/src/routing.ts +575 -0
- package/src/schema.ts +295 -0
- package/src/service.ts +131 -0
- package/src/state.ts +134 -0
- package/src/tiers.ts +212 -0
- package/src/tools.ts +128 -0
- package/src/types.ts +120 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAGxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,+BAA+B;AAC/B,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;CACjC;AAOD,oCAAoC;AACpC,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,YAAY,GAAG,cAAc,CA+ChF;AAED,mCAAmC;AACnC,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,EAAE,YAAY,GAAG,cAAc,CAwCvE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAG5E"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared vocabulary for dsh-autotier: the tier ids, the adapter-owned reasoning
|
|
3
|
+
* effort ids, the routing modes, and the public route/status shapes every
|
|
4
|
+
* module and the `ctx.autotier` service speak.
|
|
5
|
+
* @module dsh-autotier/types
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Service Definition (contract layer): the two cost tiers this plugin routes
|
|
9
|
+
* between. `strong` plans complex intent and reviews high-risk work; `cheap`
|
|
10
|
+
* implements it. The ids are stable wire/settings vocabulary.
|
|
11
|
+
*/
|
|
12
|
+
export declare const TIER_IDS: readonly ["strong", "cheap"];
|
|
13
|
+
/** One of the two cost tiers. */
|
|
14
|
+
export type TierId = (typeof TIER_IDS)[number];
|
|
15
|
+
/**
|
|
16
|
+
* Reasoning-effort ids owned by the provider adapter. The DeepSeek adapter
|
|
17
|
+
* accepts exactly these four (`packages/llm/llm-deepseek/src/index.ts:133`);
|
|
18
|
+
* `medium` does not exist, and an unsupported value fails every request with
|
|
19
|
+
* `UNSUPPORTED_REASONING_EFFORT` instead of degrading.
|
|
20
|
+
*/
|
|
21
|
+
export declare const EFFORT_IDS: readonly ["off", "low", "high", "max"];
|
|
22
|
+
/** One adapter-owned reasoning-effort id. */
|
|
23
|
+
export type EffortId = (typeof EFFORT_IDS)[number];
|
|
24
|
+
/**
|
|
25
|
+
* Routing modes. `auto` is the fully automatic path; the rest are explicit
|
|
26
|
+
* user overrides (`/tier strong|cheap|off`). `delegated` means the session
|
|
27
|
+
* carries an explicit model selection that autotier must not fight.
|
|
28
|
+
*/
|
|
29
|
+
export declare const ROUTING_MODES: readonly ["auto", "strong", "cheap", "delegated", "off"];
|
|
30
|
+
/** One routing mode. */
|
|
31
|
+
export type RoutingMode = (typeof ROUTING_MODES)[number];
|
|
32
|
+
/** Intent classes the rule layer and the judge distinguish. */
|
|
33
|
+
export declare const SCENARIOS: readonly ["coding", "review", "planning", "retrieval", "batch", "daily", "longText", "multimodal"];
|
|
34
|
+
/** One intent class. */
|
|
35
|
+
export type Scenario = (typeof SCENARIOS)[number];
|
|
36
|
+
/** Cost/quality arbitration direction when the signals are ambiguous. */
|
|
37
|
+
export declare const COST_MODES: readonly ["cost-first", "quality-first", "balanced"];
|
|
38
|
+
/** One cost/quality arbitration direction. */
|
|
39
|
+
export type CostMode = (typeof COST_MODES)[number];
|
|
40
|
+
/**
|
|
41
|
+
* One concrete tier landing: the provider/model pair plus the reasoning effort
|
|
42
|
+
* the request should carry. `effort` is omitted only when the tier inherits
|
|
43
|
+
* the session's own effort (followSession).
|
|
44
|
+
*/
|
|
45
|
+
export interface TierRoute {
|
|
46
|
+
readonly provider: string;
|
|
47
|
+
readonly model: string;
|
|
48
|
+
readonly effort?: EffortId;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Why a tier was chosen. `source` is the arbitration layer that won, so an
|
|
52
|
+
* operator can tell a rule hit from a judge call from an escalation.
|
|
53
|
+
*/
|
|
54
|
+
export type RouteSource = 'manual' | 'rule' | 'judge' | 'posterior' | 'plan-mode' | 'guard' | 'escalation' | 'fallback' | 'default';
|
|
55
|
+
/** One routing decision with its provenance. */
|
|
56
|
+
export interface RouteDecision {
|
|
57
|
+
/** The tier the request should use. */
|
|
58
|
+
readonly tier: TierId;
|
|
59
|
+
/** The concrete landing. */
|
|
60
|
+
readonly route: TierRoute;
|
|
61
|
+
/** The arbitration layer that produced this decision. */
|
|
62
|
+
readonly source: RouteSource;
|
|
63
|
+
/** 0..1 confidence of the intent classification (1 for explicit overrides). */
|
|
64
|
+
readonly confidence: number;
|
|
65
|
+
/** Short human-readable reason, safe for logs and `/tier status`. */
|
|
66
|
+
readonly reason: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Service Definition (contract layer): the read-only status snapshot served by
|
|
70
|
+
* `ctx.autotier.status()` and rendered by `/tier status` and the `tier_status`
|
|
71
|
+
* tool. Third-party plugins may depend on this shape.
|
|
72
|
+
*/
|
|
73
|
+
export interface AutotierStatus {
|
|
74
|
+
/** Current routing mode. */
|
|
75
|
+
readonly mode: RoutingMode;
|
|
76
|
+
/** Configured landing per tier (effort omitted when inherited). */
|
|
77
|
+
readonly tiers: {
|
|
78
|
+
readonly strong: TierRoute;
|
|
79
|
+
readonly cheap: TierRoute;
|
|
80
|
+
readonly vision: TierRoute;
|
|
81
|
+
};
|
|
82
|
+
/** Guard switches. */
|
|
83
|
+
readonly guard: {
|
|
84
|
+
readonly enabled: boolean;
|
|
85
|
+
readonly tiers: readonly TierId[];
|
|
86
|
+
};
|
|
87
|
+
/** Escalation switches. */
|
|
88
|
+
readonly escalation: {
|
|
89
|
+
readonly threshold: number;
|
|
90
|
+
readonly windowMs: number;
|
|
91
|
+
readonly ttlMs: number;
|
|
92
|
+
readonly fallbackTtlMs: number;
|
|
93
|
+
readonly signature: boolean;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,eAAO,MAAM,QAAQ,8BAA+B,CAAA;AAEpD,iCAAiC;AACjC,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,UAAU,wCAAyC,CAAA;AAEhE,6CAA6C;AAC7C,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;AAElD;;;;GAIG;AACH,eAAO,MAAM,aAAa,0DAA2D,CAAA;AAErF,wBAAwB;AACxB,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,+DAA+D;AAC/D,eAAO,MAAM,SAAS,oGASZ,CAAA;AAEV,wBAAwB;AACxB,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAA;AAEjD,yEAAyE;AACzE,eAAO,MAAM,UAAU,sDAAuD,CAAA;AAE9E,8CAA8C;AAC9C,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;AAElD;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;CAC3B;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,MAAM,GACN,OAAO,GACP,WAAW,GACX,WAAW,GACX,OAAO,GACP,YAAY,GACZ,UAAU,GACV,SAAS,CAAA;AAEb,gDAAgD;AAChD,MAAM,WAAW,aAAa;IAC5B,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4BAA4B;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;IACzB,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;KAAE,CAAA;IACrG,sBAAsB;IACtB,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAA;IAChF,2BAA2B;IAC3B,QAAQ,CAAC,UAAU,EAAE;QACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;QAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;QACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;QAC9B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;KAC5B,CAAA;CACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-autotier",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Automatic strong/cheap model-tier routing for DeepSeek Harness: intent-gated tier landing on the agent/request waterfall, plan-mode handoff (strong plans, cheap implements), deterministic high-risk guards on tools/pre-execute, failure escalation with TTL fallback, a /tier command, and tier status tools",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/PerryLink/dsh-autotier.git"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/PerryLink/dsh-autotier#readme",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/PerryLink/dsh-autotier/issues"
|
|
12
|
+
},
|
|
13
|
+
"author": "PerryLink",
|
|
14
|
+
"private": false,
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./lib/index.js",
|
|
17
|
+
"types": "./lib/types/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./lib/types/index.d.ts",
|
|
21
|
+
"default": "./lib/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"lib",
|
|
27
|
+
"src",
|
|
28
|
+
"cordis.patch.yml",
|
|
29
|
+
"CHANGELOG.md",
|
|
30
|
+
"THIRD_PARTY_NOTICES.md",
|
|
31
|
+
"SECURITY.md",
|
|
32
|
+
"AGENTS.md",
|
|
33
|
+
"README.md",
|
|
34
|
+
"README.zh.md",
|
|
35
|
+
"README.es.md",
|
|
36
|
+
"README.pt.md",
|
|
37
|
+
"README.hi.md",
|
|
38
|
+
"LICENSE",
|
|
39
|
+
"docs"
|
|
40
|
+
],
|
|
41
|
+
"dsh": {
|
|
42
|
+
"bundle": {
|
|
43
|
+
"patch": "./cordis.patch.yml"
|
|
44
|
+
},
|
|
45
|
+
"compatibility": {
|
|
46
|
+
"dshReleases": {
|
|
47
|
+
"0.1.2-rc.1": "compatible"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"dshWorkshop": {
|
|
52
|
+
"schema": "omdsh-workshop-package/v1",
|
|
53
|
+
"type": "plugin",
|
|
54
|
+
"integration": {
|
|
55
|
+
"protocol": "harness-profile",
|
|
56
|
+
"artifact": "cordis.patch.yml"
|
|
57
|
+
},
|
|
58
|
+
"install": {
|
|
59
|
+
"mode": "transactional",
|
|
60
|
+
"adapter": "profile-bundle",
|
|
61
|
+
"failurePolicy": "generation-rollback",
|
|
62
|
+
"touchesCurrentBeforeActivation": false
|
|
63
|
+
},
|
|
64
|
+
"lifecycle": {
|
|
65
|
+
"activation": "restart-profile",
|
|
66
|
+
"dispose": "supported"
|
|
67
|
+
},
|
|
68
|
+
"permissions": [
|
|
69
|
+
"network:outbound",
|
|
70
|
+
"session:append"
|
|
71
|
+
],
|
|
72
|
+
"compatibility": {
|
|
73
|
+
"dshVersions": [
|
|
74
|
+
"0.1.2-rc.1"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
"capability": {
|
|
78
|
+
"id": "autotier",
|
|
79
|
+
"kind": "command",
|
|
80
|
+
"invocation": "/tier, agent/request, tools/pre-execute",
|
|
81
|
+
"expected": "routes each turn to a strong or cheap model tier, blocks high-risk tool calls while the cheap tier is executing, and escalates to the strong tier after repeated failures"
|
|
82
|
+
},
|
|
83
|
+
"evidence": {
|
|
84
|
+
"install": null,
|
|
85
|
+
"failureIsolation": null,
|
|
86
|
+
"hotReload": null,
|
|
87
|
+
"remove": null
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"keywords": [
|
|
91
|
+
"dsh",
|
|
92
|
+
"dsh-plugin",
|
|
93
|
+
"deepseek-harness",
|
|
94
|
+
"deepseek",
|
|
95
|
+
"cordis",
|
|
96
|
+
"router",
|
|
97
|
+
"model-tier",
|
|
98
|
+
"cost",
|
|
99
|
+
"auto"
|
|
100
|
+
],
|
|
101
|
+
"engines": {
|
|
102
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
103
|
+
},
|
|
104
|
+
"packageManager": "pnpm@11.7.0",
|
|
105
|
+
"peerDependencies": {
|
|
106
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
107
|
+
"@deepseek-ai/dsh-agent": ">=0.1.2-rc.1 <0.2.0",
|
|
108
|
+
"@deepseek-ai/dsh-commands": ">=0.1.2-rc.1 <0.2.0",
|
|
109
|
+
"@deepseek-ai/dsh-llm": ">=0.1.2-rc.1 <0.2.0",
|
|
110
|
+
"@deepseek-ai/dsh-plan-mode": ">=0.1.2-rc.1 <0.2.0",
|
|
111
|
+
"@deepseek-ai/dsh-session": ">=0.1.2-rc.1 <0.2.0",
|
|
112
|
+
"@deepseek-ai/dsh-session-projection": ">=0.1.2-rc.1 <0.2.0",
|
|
113
|
+
"@deepseek-ai/dsh-settings": ">=0.1.2-rc.1 <0.2.0",
|
|
114
|
+
"@deepseek-ai/dsh-tools": ">=0.1.2-rc.1 <0.2.0",
|
|
115
|
+
"@deepseek-ai/schemastery": "^3.18.2"
|
|
116
|
+
},
|
|
117
|
+
"peerDependenciesMeta": {
|
|
118
|
+
"@deepseek-ai/dsh-plan-mode": {
|
|
119
|
+
"optional": true
|
|
120
|
+
},
|
|
121
|
+
"@deepseek-ai/dsh-session-projection": {
|
|
122
|
+
"optional": true
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"dependencies": {
|
|
126
|
+
"tsdown": "^0.22.14",
|
|
127
|
+
"typescript": "^5.9.0"
|
|
128
|
+
},
|
|
129
|
+
"devDependencies": {
|
|
130
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
131
|
+
"@deepseek-ai/cordis-plugin-include": "^1.0.7",
|
|
132
|
+
"@deepseek-ai/cordis-plugin-loader": "^1.0.3",
|
|
133
|
+
"@deepseek-ai/dsh-agent": "0.1.2-rc.1",
|
|
134
|
+
"@deepseek-ai/dsh-agent-default-model": "0.1.2-rc.1",
|
|
135
|
+
"@deepseek-ai/dsh-agent-loop": "0.1.2-rc.1",
|
|
136
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "0.1.2-rc.1",
|
|
137
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.2-rc.1",
|
|
138
|
+
"@deepseek-ai/dsh-commands": "0.1.2-rc.1",
|
|
139
|
+
"@deepseek-ai/dsh-home-paths": "0.1.2-rc.1",
|
|
140
|
+
"@deepseek-ai/dsh-llm": "0.1.2-rc.1",
|
|
141
|
+
"@deepseek-ai/dsh-plan-mode": "0.1.2-rc.1",
|
|
142
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.1.2-rc.1",
|
|
143
|
+
"@deepseek-ai/dsh-session": "0.1.2-rc.1",
|
|
144
|
+
"@deepseek-ai/dsh-session-persistence": "0.1.2-rc.1",
|
|
145
|
+
"@deepseek-ai/dsh-session-projection": "0.1.2-rc.1",
|
|
146
|
+
"@deepseek-ai/dsh-settings": "0.1.2-rc.1",
|
|
147
|
+
"@deepseek-ai/dsh-settings-file": "0.1.2-rc.1",
|
|
148
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
|
|
149
|
+
"@deepseek-ai/dsh-tools": "0.1.2-rc.1",
|
|
150
|
+
"@deepseek-ai/dsh-util-values": "0.1.2-rc.1",
|
|
151
|
+
"@deepseek-ai/schemastery": "^3.18.2",
|
|
152
|
+
"@types/node": "^22.19.0",
|
|
153
|
+
"@types/react": "18.3.31",
|
|
154
|
+
"@vitest/coverage-v8": "3.2.7",
|
|
155
|
+
"oxlint": "0.18.1",
|
|
156
|
+
"react": "18.3.1",
|
|
157
|
+
"react-dom": "18.3.1",
|
|
158
|
+
"vitest": "^3.2.0"
|
|
159
|
+
},
|
|
160
|
+
"scripts": {
|
|
161
|
+
"build": "node scripts/prepare.mjs",
|
|
162
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
163
|
+
"typecheck:ci": "tsc -p tsconfig.ci.json --noEmit",
|
|
164
|
+
"test": "vitest run",
|
|
165
|
+
"test:watch": "vitest",
|
|
166
|
+
"test:coverage": "vitest run --coverage",
|
|
167
|
+
"lint": "oxlint",
|
|
168
|
+
"check:readmes": "node scripts/check-readme-sync.mjs",
|
|
169
|
+
"prepare": "node scripts/prepare.mjs",
|
|
170
|
+
"verify:self-contained": "node scripts/verify-self-contained.mjs",
|
|
171
|
+
"verify:artifacts": "node scripts/verify-artifacts.mjs",
|
|
172
|
+
"prepublishOnly": "pnpm run typecheck && pnpm run typecheck:ci && pnpm test && pnpm run build && pnpm run verify:self-contained && pnpm run verify:artifacts"
|
|
173
|
+
},
|
|
174
|
+
"license": "Apache-2.0",
|
|
175
|
+
"funding": {
|
|
176
|
+
"type": "individual",
|
|
177
|
+
"url": "https://github.com/sponsors/PerryLink"
|
|
178
|
+
}
|
|
179
|
+
}
|
package/src/command.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `/tier` command: a session-scoped escape hatch over the automatic
|
|
3
|
+
* routing. `auto` returns the session to routing, `strong`/`cheap` pin it,
|
|
4
|
+
* `off` disables routing entirely, and `status` prints the live decision state.
|
|
5
|
+
* @module dsh-autotier/command
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
9
|
+
import type {} from '@deepseek-ai/dsh-commands'
|
|
10
|
+
import type { CommandResult } from '@deepseek-ai/dsh-commands'
|
|
11
|
+
import { escalationActive } from './policy.ts'
|
|
12
|
+
import type { AutotierService } from './service.ts'
|
|
13
|
+
import type { AgentStateStore } from './state.ts'
|
|
14
|
+
import { ROUTING_MODES, type RoutingMode } from './types.ts'
|
|
15
|
+
|
|
16
|
+
/** Format the tier table for `/tier status`. */
|
|
17
|
+
function statusText(service: AutotierService, state: ReturnType<AgentStateStore['for']>): string {
|
|
18
|
+
const status = service.status()
|
|
19
|
+
const strong = status.tiers.strong
|
|
20
|
+
const cheap = status.tiers.cheap
|
|
21
|
+
const lines = [
|
|
22
|
+
`dsh-autotier — mode: ${state.override ?? status.mode}`,
|
|
23
|
+
`strong: ${strong.provider}/${strong.model}${strong.effort === undefined ? ' (follows session effort)' : ` @${strong.effort}`}`,
|
|
24
|
+
`cheap: ${cheap.provider}/${cheap.model}${cheap.effort === undefined ? ' (follows session effort)' : ` @${cheap.effort}`}`,
|
|
25
|
+
`vision: ${status.tiers.vision.provider}/${status.tiers.vision.model}`,
|
|
26
|
+
`guard: ${status.guard.enabled ? 'on' : 'off'} (${status.guard.tiers.join(', ')})`,
|
|
27
|
+
]
|
|
28
|
+
const decision = state.decision
|
|
29
|
+
if (decision !== undefined) {
|
|
30
|
+
lines.push(`last intent: ${decision.scenario} (confidence ${decision.confidence.toFixed(2)}, fingerprint ${decision.fingerprint})`)
|
|
31
|
+
if (decision.reasons.length > 0) lines.push(` because: ${decision.reasons.join('; ')}`)
|
|
32
|
+
}
|
|
33
|
+
if (state.appliedTier !== undefined) lines.push(`applied tier: ${state.appliedTier}`)
|
|
34
|
+
if (escalationActive(state, Date.now())) {
|
|
35
|
+
lines.push(`escalation: active for ${String(Math.ceil(((state.escalation?.until ?? 0) - Date.now()) / 1000))}s`)
|
|
36
|
+
}
|
|
37
|
+
if (state.fallback !== undefined) lines.push(`fallback: chain entry ${String(state.fallback.index + 1)}`)
|
|
38
|
+
if (state.planActive) lines.push('plan mode: active (strong tier)')
|
|
39
|
+
if (state.denials > 0) lines.push(`guard denials: ${String(state.denials)} (last rule ${state.lastDenial})`)
|
|
40
|
+
return lines.join('\n')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Register the `/tier` command on the plugin fiber.
|
|
45
|
+
* @param ctx - the plugin context (must have `commands`).
|
|
46
|
+
* @param service - the live service.
|
|
47
|
+
* @param states - the per-agent state store.
|
|
48
|
+
*/
|
|
49
|
+
export function registerTierCommand(ctx: Context, service: AutotierService, states: AgentStateStore): void {
|
|
50
|
+
ctx.commands.register({
|
|
51
|
+
name: 'tier',
|
|
52
|
+
description: 'Show or set this session\'s model tier (auto | strong | cheap | delegated | off | status).',
|
|
53
|
+
input: { hint: 'auto | strong | cheap | delegated | off | status' },
|
|
54
|
+
handler: ({ agent, rawInput }): CommandResult => {
|
|
55
|
+
const argument = rawInput.trim().toLowerCase()
|
|
56
|
+
const state = states.for(agent)
|
|
57
|
+
if (argument === '' || argument === 'status') {
|
|
58
|
+
return { kind: 'success', text: statusText(service, state) }
|
|
59
|
+
}
|
|
60
|
+
const mode = ROUTING_MODES.find(candidate => candidate === argument)
|
|
61
|
+
if (mode === undefined) {
|
|
62
|
+
return { kind: 'error', text: `unknown tier mode ${JSON.stringify(argument)}; use auto | strong | cheap | off | status` }
|
|
63
|
+
}
|
|
64
|
+
state.override = mode === 'auto' ? undefined : (mode as RoutingMode)
|
|
65
|
+
const status = service.status()
|
|
66
|
+
const effective = state.override ?? status.mode
|
|
67
|
+
return {
|
|
68
|
+
kind: 'success',
|
|
69
|
+
text: `dsh-autotier: session mode set to ${effective}\n${statusText(service, state)}`,
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
})
|
|
73
|
+
}
|