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,17 @@
|
|
|
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
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
8
|
+
import type { AutotierService } from './service.js';
|
|
9
|
+
import type { AgentStateStore } from './state.js';
|
|
10
|
+
/**
|
|
11
|
+
* Register the `/tier` command on the plugin fiber.
|
|
12
|
+
* @param ctx - the plugin context (must have `commands`).
|
|
13
|
+
* @param service - the live service.
|
|
14
|
+
* @param states - the per-agent state store.
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerTierCommand(ctx: Context, service: AutotierService, states: AgentStateStore): void;
|
|
17
|
+
//# sourceMappingURL=command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/command.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAIlD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AA8BjD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAwBzG"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The explicit-resolve judge for dsh-autotier: it re-checks every default,
|
|
3
|
+
* bound and cross-field requirement field by field, so programmatic
|
|
4
|
+
* construction that bypasses Schemastery normalization still fails loud. The
|
|
5
|
+
* schema itself lives in `schema.ts`.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-autotier/config
|
|
8
|
+
*/
|
|
9
|
+
import { type CostMode, type EffortId, type RoutingMode } from './types.js';
|
|
10
|
+
import type { Config, JudgeConfig, ScenarioToggles, VisionConfig } from './schema.js';
|
|
11
|
+
export { Config } from './schema.js';
|
|
12
|
+
export type { EscalationConfig, FallbackEntry, GuardConfig, IntentConfig, IntentRule, JudgeConfig, ScenarioToggles, TierConfig, VisionConfig, } from './schema.js';
|
|
13
|
+
/** One resolved fallback landing. */
|
|
14
|
+
export interface ResolvedFallbackEntry {
|
|
15
|
+
provider: string;
|
|
16
|
+
model: string;
|
|
17
|
+
}
|
|
18
|
+
/** One resolved tier landing. Runtime-frozen by {@link resolveConfig}. */
|
|
19
|
+
export interface ResolvedTierConfig {
|
|
20
|
+
provider: string;
|
|
21
|
+
model: string;
|
|
22
|
+
effort: EffortId;
|
|
23
|
+
followSession: boolean;
|
|
24
|
+
fallback: ResolvedFallbackEntry[];
|
|
25
|
+
}
|
|
26
|
+
/** One fully-resolved declarative rule. */
|
|
27
|
+
export interface ResolvedRule {
|
|
28
|
+
id: string;
|
|
29
|
+
when: {
|
|
30
|
+
patterns: string[];
|
|
31
|
+
tools: string[];
|
|
32
|
+
cwd: string;
|
|
33
|
+
};
|
|
34
|
+
tier: 'cheap' | 'strong';
|
|
35
|
+
priority: number;
|
|
36
|
+
}
|
|
37
|
+
/** Fully-resolved configuration: every field present, runtime-frozen. */
|
|
38
|
+
export interface ResolvedConfig {
|
|
39
|
+
tiers: {
|
|
40
|
+
strong: ResolvedTierConfig;
|
|
41
|
+
cheap: ResolvedTierConfig;
|
|
42
|
+
vision: Required<VisionConfig>;
|
|
43
|
+
};
|
|
44
|
+
intent: {
|
|
45
|
+
ruleThreshold: number;
|
|
46
|
+
attemptBand: {
|
|
47
|
+
enabled: boolean;
|
|
48
|
+
tauLow: number;
|
|
49
|
+
};
|
|
50
|
+
hysteresis: {
|
|
51
|
+
toStrong: number;
|
|
52
|
+
toCheap: number;
|
|
53
|
+
};
|
|
54
|
+
rules: ResolvedRule[];
|
|
55
|
+
judge: Required<JudgeConfig>;
|
|
56
|
+
scenarios: Required<ScenarioToggles>;
|
|
57
|
+
costMode: CostMode;
|
|
58
|
+
};
|
|
59
|
+
guard: {
|
|
60
|
+
enabled: boolean;
|
|
61
|
+
tiers: ('cheap')[];
|
|
62
|
+
whitelist: string[];
|
|
63
|
+
protectedPaths: string[];
|
|
64
|
+
interopDefend: 'auto' | 'none';
|
|
65
|
+
};
|
|
66
|
+
escalation: {
|
|
67
|
+
threshold: number;
|
|
68
|
+
windowMs: number;
|
|
69
|
+
ttlMs: number;
|
|
70
|
+
fallbackTtlMs: number;
|
|
71
|
+
signature: boolean;
|
|
72
|
+
};
|
|
73
|
+
routingMode: RoutingMode;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Resolve raw config to the frozen runtime policy, re-judging every default,
|
|
77
|
+
* bound and cross-field requirement.
|
|
78
|
+
*
|
|
79
|
+
* @param raw - raw loader config; `undefined` for a bare row.
|
|
80
|
+
* @returns the frozen resolved config.
|
|
81
|
+
* @throws {Error} when a value is out of bounds or a cross-field requirement fails.
|
|
82
|
+
*/
|
|
83
|
+
export declare function resolveConfig(raw: Config | undefined): ResolvedConfig;
|
|
84
|
+
/**
|
|
85
|
+
* Judge a configuration without keeping the resolved value. This is the
|
|
86
|
+
* save-time hook the `autotier` settings namespace registers, so a user write
|
|
87
|
+
* that violates a cross-field requirement is refused at the write instead of
|
|
88
|
+
* silently disabling the plugin.
|
|
89
|
+
*
|
|
90
|
+
* @param value - the configuration to judge.
|
|
91
|
+
* @throws {Error} when the configuration is invalid.
|
|
92
|
+
*/
|
|
93
|
+
export declare function validateConfig(value: Config): void;
|
|
94
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,WAAW,EACjB,MAAM,YAAY,CAAA;AAEnB,OAAO,KAAK,EACV,MAAM,EAIN,WAAW,EACX,eAAe,EAEf,YAAY,EACb,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,YAAY,EACZ,UAAU,EACV,WAAW,EACX,eAAe,EACf,UAAU,EACV,YAAY,GACb,MAAM,aAAa,CAAA;AAEpB,qCAAqC;AACrC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,0EAA0E;AAC1E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,QAAQ,CAAA;IAChB,aAAa,EAAE,OAAO,CAAA;IACtB,QAAQ,EAAE,qBAAqB,EAAE,CAAA;CAClC;AAED,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1D,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,yEAAyE;AACzE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE;QACL,MAAM,EAAE,kBAAkB,CAAA;QAC1B,KAAK,EAAE,kBAAkB,CAAA;QACzB,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAA;KAC/B,CAAA;IACD,MAAM,EAAE;QACN,aAAa,EAAE,MAAM,CAAA;QACrB,WAAW,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAA;QACjD,UAAU,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;QACjD,KAAK,EAAE,YAAY,EAAE,CAAA;QACrB,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAA;QAC5B,SAAS,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAA;QACpC,QAAQ,EAAE,QAAQ,CAAA;KACnB,CAAA;IACD,KAAK,EAAE;QACL,OAAO,EAAE,OAAO,CAAA;QAChB,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,CAAA;QAClB,SAAS,EAAE,MAAM,EAAE,CAAA;QACnB,cAAc,EAAE,MAAM,EAAE,CAAA;QACxB,aAAa,EAAE,MAAM,GAAG,MAAM,CAAA;KAC/B,CAAA;IACD,UAAU,EAAE;QACV,SAAS,EAAE,MAAM,CAAA;QACjB,QAAQ,EAAE,MAAM,CAAA;QAChB,KAAK,EAAE,MAAM,CAAA;QACb,aAAa,EAAE,MAAM,CAAA;QACrB,SAAS,EAAE,OAAO,CAAA;KACnB,CAAA;IACD,WAAW,EAAE,WAAW,CAAA;CACzB;AAuND;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAwBrE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAElD"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-impact command and path rules for the autotier guard.
|
|
3
|
+
*
|
|
4
|
+
* A TypeScript port of the dependency-free rule logic in `lib/pure.js` of
|
|
5
|
+
* `dsh-tier-router` (v0.5.0, MIT — see `THIRD_PARTY_NOTICES.md`): the
|
|
6
|
+
* `ARG_RUNNERS`/`DIRECT_RUNNERS` command-position detection, the 16
|
|
7
|
+
* `HIGH_IMPACT_COMMAND` patterns, and the 5 `HIGH_IMPACT_PATH` patterns. The
|
|
8
|
+
* upstream matching order, case-insensitivity, anchored command position, and
|
|
9
|
+
* 80/120-character truncation are preserved exactly; the port only adds stable
|
|
10
|
+
* rule ids and the `GuardMatch` shape the guard layer consumes.
|
|
11
|
+
*
|
|
12
|
+
* INTENTIONAL DELTA OVER UPSTREAM (the plugin's own Apache-2.0 addition, not
|
|
13
|
+
* upstream code): upstream never looks inside a `sh -c "..."` payload, so
|
|
14
|
+
* `sh -c "rm -rf /"` is a documented false negative. {@link SHELL_WRAPPERS} and
|
|
15
|
+
* {@link SHELL_WRAPPER_MAX_DEPTH} add a second pass that runs only after the
|
|
16
|
+
* upstream rules return no match: it strips a leading command runner, extracts
|
|
17
|
+
* the `-c` payload (single-dash flag clusters such as `-lc`, case-insensitive
|
|
18
|
+
* wrapper names, and the optional backslash escape included), unescapes it, and
|
|
19
|
+
* re-runs the same matcher on it (bounded by depth) under a
|
|
20
|
+
* `shell-wrapper:<inner rule>` id. No upstream verdict changes.
|
|
21
|
+
*
|
|
22
|
+
* Matching is deliberately conservative: it is a review/escalation signal, never
|
|
23
|
+
* a substitute for `dsh-defend`, approvals, or the sandbox policy.
|
|
24
|
+
* @module dsh-autotier/guard-rules
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Shell wrappers whose `-c` payload must be re-scanned (upstream misses these).
|
|
28
|
+
* This table and {@link SHELL_WRAPPER_MAX_DEPTH} are the plugin's own extension,
|
|
29
|
+
* not part of the upstream rule port.
|
|
30
|
+
*/
|
|
31
|
+
export declare const SHELL_WRAPPERS: readonly string[];
|
|
32
|
+
/** Recursion depth bound for nested `sh -c "sh -c ..."` payloads. */
|
|
33
|
+
export declare const SHELL_WRAPPER_MAX_DEPTH = 3;
|
|
34
|
+
/** One named high-impact rule. */
|
|
35
|
+
export interface GuardRule {
|
|
36
|
+
/** Stable kebab-case identifier, also reported in {@link GuardMatch.rule}. */
|
|
37
|
+
readonly id: string;
|
|
38
|
+
/** Human-readable description of the destruction the rule protects against. */
|
|
39
|
+
readonly description: string;
|
|
40
|
+
/** The upstream pattern, unchanged (no `g` flag, so matching is stateless). */
|
|
41
|
+
readonly pattern: RegExp;
|
|
42
|
+
}
|
|
43
|
+
/** A matched rule plus the exact text that matched. */
|
|
44
|
+
export interface GuardMatch {
|
|
45
|
+
/** The {@link GuardRule.id} that matched, or `shell-wrapper:<inner rule>`. */
|
|
46
|
+
readonly rule: string;
|
|
47
|
+
/** The matched rule's description. */
|
|
48
|
+
readonly description: string;
|
|
49
|
+
/**
|
|
50
|
+
* The matched text: for commands the matched substring trimmed and truncated
|
|
51
|
+
* to 80 characters; for paths the whole target path truncated to 120
|
|
52
|
+
* characters (upstream reports the path, not the regex substring).
|
|
53
|
+
*/
|
|
54
|
+
readonly matched: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The 16 upstream `HIGH_IMPACT_COMMAND` patterns, in upstream array order.
|
|
58
|
+
* `matchCommand` returns the first hit, so order is part of the contract:
|
|
59
|
+
* `sudo` precedes `wget-pipe-shell`, and the separate `rm` rule precedes all
|
|
60
|
+
* of these.
|
|
61
|
+
*/
|
|
62
|
+
export declare const HIGH_IMPACT_COMMAND_RULES: readonly GuardRule[];
|
|
63
|
+
/**
|
|
64
|
+
* The 5 upstream `HIGH_IMPACT_PATH` patterns (credentials, keys, secrets), in
|
|
65
|
+
* upstream array order. `.env` matches unless the suffix is an
|
|
66
|
+
* example/sample/template name.
|
|
67
|
+
*/
|
|
68
|
+
export declare const HIGH_IMPACT_PATH_RULES: readonly GuardRule[];
|
|
69
|
+
/**
|
|
70
|
+
* True for `rm` with BOTH recursive and force flags at command position (split
|
|
71
|
+
* flags included). Prose (`echo rm -rf`) and runner-argument false positives
|
|
72
|
+
* (`nohup echo rm -rf`) stay unmatched. Upstream-exact: this never unwraps a
|
|
73
|
+
* shell wrapper.
|
|
74
|
+
*/
|
|
75
|
+
export declare function hasRecursiveForceRm(command: string): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Match one shell command string against the recursive-force `rm` rule first
|
|
78
|
+
* (upstream order) and then the command rules in array order; only when those
|
|
79
|
+
* find nothing, re-scan a `sh -c`-style payload (see the module header delta).
|
|
80
|
+
* @param command - one shell command string.
|
|
81
|
+
* @returns the first match, or null when the command is not high impact.
|
|
82
|
+
*/
|
|
83
|
+
export declare function matchCommand(command: string): GuardMatch | null;
|
|
84
|
+
/**
|
|
85
|
+
* Match one file path (a write/edit target) against the path rules in array
|
|
86
|
+
* order.
|
|
87
|
+
* @param filePath - one target path.
|
|
88
|
+
* @returns the first match, or null when the path is not high impact.
|
|
89
|
+
*/
|
|
90
|
+
export declare function matchPath(filePath: string): GuardMatch | null;
|
|
91
|
+
/**
|
|
92
|
+
* Credential/secret path classification for protected-path review: true when
|
|
93
|
+
* any of the {@link HIGH_IMPACT_PATH_RULES} matches, i.e. exactly the paths
|
|
94
|
+
* {@link matchPath} reports.
|
|
95
|
+
*/
|
|
96
|
+
export declare function isCredentialPath(filePath: string): boolean;
|
|
97
|
+
//# sourceMappingURL=guard-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard-rules.d.ts","sourceRoot":"","sources":["../../src/guard-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAiCH;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAAyC,CAAA;AAErF,qEAAqE;AACrE,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAiCxC,kCAAkC;AAClC,MAAM,WAAW,SAAS;IACxB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,sCAAsC;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,SAAS,EAiBzD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,SAAS,EAMtD,CAAA;AAoGD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAQ7D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The high-risk guard: a deterministic, tier-conditional denial on
|
|
3
|
+
* `tools/pre-execute`. It protects the cheap tier only — the strong model is
|
|
4
|
+
* the reviewer — and it never weakens `dsh-defend`, the approval service or the
|
|
5
|
+
* sandbox policy.
|
|
6
|
+
*
|
|
7
|
+
* Failure discipline: a guard that throws escalates the agent to the strong
|
|
8
|
+
* tier and lets the call through. Denying every call on a guard bug would turn
|
|
9
|
+
* one defect into a dead session; the escalation keeps the safety property
|
|
10
|
+
* (the strong model reviews) without breaking the turn.
|
|
11
|
+
*
|
|
12
|
+
* @module dsh-autotier/guard
|
|
13
|
+
*/
|
|
14
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
15
|
+
import type { ResolvedConfig } from './config.js';
|
|
16
|
+
import { isCredentialPath } from './guard-rules.js';
|
|
17
|
+
import type { AutotierService } from './service.js';
|
|
18
|
+
import type { AgentStateStore } from './state.js';
|
|
19
|
+
import type { TierId } from './types.js';
|
|
20
|
+
/** Redact credential-shaped spans from one snippet. */
|
|
21
|
+
export declare function redactSnippet(text: string): string;
|
|
22
|
+
/** The guard's verdict for one call. */
|
|
23
|
+
export interface GuardVerdict {
|
|
24
|
+
readonly action: 'allow' | 'deny';
|
|
25
|
+
/** Empty for `allow`. */
|
|
26
|
+
readonly reason: string;
|
|
27
|
+
/** The rule id that fired, or `''`. */
|
|
28
|
+
readonly rule: string;
|
|
29
|
+
/** Which axis matched. */
|
|
30
|
+
readonly axis: 'command' | 'path' | 'protected-path' | 'none';
|
|
31
|
+
}
|
|
32
|
+
/** One call as the guard sees it. */
|
|
33
|
+
export interface GuardInput {
|
|
34
|
+
readonly toolName: string;
|
|
35
|
+
readonly args: unknown;
|
|
36
|
+
readonly tier: TierId;
|
|
37
|
+
readonly config: ResolvedConfig;
|
|
38
|
+
/** Resolved sandbox mode, when the policy service is composed. */
|
|
39
|
+
readonly sandboxMode?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Judge one tool call.
|
|
43
|
+
*
|
|
44
|
+
* Order: the guard must be enabled and the executing tier protected, then the
|
|
45
|
+
* whitelist, then the credential/command rules, then the protected-path review
|
|
46
|
+
* rule. A denial names the rule and tells the model to escalate instead of
|
|
47
|
+
* retrying.
|
|
48
|
+
*
|
|
49
|
+
* @param input - the call, the executing tier and the live configuration.
|
|
50
|
+
* @returns the verdict.
|
|
51
|
+
*/
|
|
52
|
+
export declare function evaluateToolCall(input: GuardInput): GuardVerdict;
|
|
53
|
+
/** Options for {@link registerGuardHook}. */
|
|
54
|
+
export interface GuardHookOptions {
|
|
55
|
+
readonly ctx: Context;
|
|
56
|
+
readonly service: AutotierService;
|
|
57
|
+
readonly states: AgentStateStore;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Register the `tools/pre-execute` guard.
|
|
61
|
+
*
|
|
62
|
+
* The listener is registered with `{ prepend: true }` so a denial claims the
|
|
63
|
+
* call before any pass-through listener; every allowed call awaits `next()`.
|
|
64
|
+
*
|
|
65
|
+
* @param options - the plugin context, service and state store.
|
|
66
|
+
*/
|
|
67
|
+
export declare function registerGuardHook({ ctx, service, states }: GuardHookOptions): void;
|
|
68
|
+
/** Re-exported for the status surface. */
|
|
69
|
+
export { isCredentialPath };
|
|
70
|
+
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAIlD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAA2B,MAAM,kBAAkB,CAAA;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AA6BxC,uDAAuD;AACvD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,wCAAwC;AACxC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAA;IACjC,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,gBAAgB,GAAG,MAAM,CAAA;CAC9D;AAED,qCAAqC;AACrC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAkDD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,YAAY,CAqDhE;AAgBD,6CAA6C;AAC7C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;CACjC;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,gBAAgB,GAAG,IAAI,CA0DlF;AAED,0CAA0C;AAC1C,OAAO,EAAE,gBAAgB,EAAE,CAAA"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-autotier: automatic strong/cheap model-tier routing for DeepSeek Harness.
|
|
3
|
+
*
|
|
4
|
+
* One user instruction enters, one tier decision comes out — with no manual
|
|
5
|
+
* model switching. Complex intent is planned on the strong tier and implemented
|
|
6
|
+
* on the cheap tier; simple intent is designed and implemented on the cheap
|
|
7
|
+
* tier directly. High-risk tool calls are denied while the cheap tier executes,
|
|
8
|
+
* and repeated failures escalate to the strong tier with a TTL fallback.
|
|
9
|
+
*
|
|
10
|
+
* The routing seam is the official `agent/request` waterfall: a listener
|
|
11
|
+
* registered at load time on the root scope with `{ prepend: true }` runs
|
|
12
|
+
* outermost, awaits `next()` exactly once, and returns a replacement
|
|
13
|
+
* `LlmCallConfig` (provider/model/effort plus the preserved sampling scalars).
|
|
14
|
+
*
|
|
15
|
+
* @module dsh-autotier
|
|
16
|
+
*/
|
|
17
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
18
|
+
import { type Config as AutotierConfig } from './config.js';
|
|
19
|
+
export { Config, resolveConfig, validateConfig } from './config.js';
|
|
20
|
+
export type { Config as AutotierConfig, ResolvedConfig } from './config.js';
|
|
21
|
+
export type { AutotierStatus, CostMode, EffortId, RouteDecision, RouteSource, RoutingMode, Scenario, TierId, TierRoute, } from './types.js';
|
|
22
|
+
export { EFFORT_IDS, ROUTING_MODES, SCENARIOS, TIER_IDS } from './types.js';
|
|
23
|
+
export { AutotierService } from './service.js';
|
|
24
|
+
export { AutotierRouter } from './routing.js';
|
|
25
|
+
export type { RouteProposal, RouteVeto, TierChange } from './routing.js';
|
|
26
|
+
export { AgentStateStore, registerTierProjection, TIER_PROJECTION_KEY } from './state.js';
|
|
27
|
+
export { classifyIntent, compileRules, computeSignals, evaluateRules, fingerprintOf, PosteriorTable, wilsonLowerBound, } from './intent.js';
|
|
28
|
+
export type { IntentInput, IntentResult, IntentSignals, Posterior, RuleHit } from './intent.js';
|
|
29
|
+
export { attemptBandApplies, createRouteState, decideTier, escalationActive, judgeNeeded, noteFailure, noteFallback, noteJudgeCall, } from './policy.js';
|
|
30
|
+
export type { Decision, RouteState } from './policy.js';
|
|
31
|
+
export { advanceFallback, classifyFallback, effortRank, escalationLadder, fallbackActive, nextEffortStep, resolveRoute, routeEquals, } from './tiers.js';
|
|
32
|
+
export type { EscalationRung, FallbackClass, FallbackRecord } from './tiers.js';
|
|
33
|
+
export { JUDGE_LABELS, parseJudgeLabel, resolveJudgeRoute, runJudge } from './judge.js';
|
|
34
|
+
export type { JudgeOutcome, JudgeRoute } from './judge.js';
|
|
35
|
+
export { evaluateToolCall, redactSnippet, registerGuardHook } from './guard.js';
|
|
36
|
+
export type { GuardInput, GuardVerdict } from './guard.js';
|
|
37
|
+
export { HIGH_IMPACT_COMMAND_RULES, HIGH_IMPACT_PATH_RULES, isCredentialPath, matchCommand, matchPath, } from './guard-rules.js';
|
|
38
|
+
export type { GuardMatch, GuardRule } from './guard-rules.js';
|
|
39
|
+
/** The cordis.yml row id and the plugin name must match. */
|
|
40
|
+
export declare const name = "dsh-autotier";
|
|
41
|
+
/**
|
|
42
|
+
* Hard service dependencies. `sessions` is plural — the service name really is
|
|
43
|
+
* `sessions` (`packages/core/session/src/index.ts` registers `super(ctx,
|
|
44
|
+
* 'sessions')`); declaring a non-existent name would leave this plugin PENDING
|
|
45
|
+
* forever. Every other capability (`agents`, `subagents`, `systemPrompt`,
|
|
46
|
+
* `planMode`, `sessionProjections`, `sandboxPolicy`) is read with `ctx.get()`
|
|
47
|
+
* and degrades when absent.
|
|
48
|
+
*/
|
|
49
|
+
export declare const inject: string[];
|
|
50
|
+
/**
|
|
51
|
+
* Mount the plugin: judge the configuration, register the `autotier` settings
|
|
52
|
+
* namespace, publish the `ctx.autotier` service, and wire the routing listeners,
|
|
53
|
+
* the `/tier` command and the two read-only tools.
|
|
54
|
+
*
|
|
55
|
+
* @param ctx - the plugin context.
|
|
56
|
+
* @param config - the raw row configuration; every field is optional.
|
|
57
|
+
* @throws {Error} when the configuration fails the cross-field judgement.
|
|
58
|
+
*/
|
|
59
|
+
export declare function apply(ctx: Context, config?: AutotierConfig): void;
|
|
60
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,EAAyC,KAAK,MAAM,IAAI,cAAc,EAAE,MAAM,aAAa,CAAA;AAOlG,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACnE,YAAY,EAAE,MAAM,IAAI,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC3E,YAAY,EACV,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,WAAW,EACX,WAAW,EACX,QAAQ,EACR,MAAM,EACN,SAAS,GACV,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACxE,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AACzF,OAAO,EACL,cAAc,EACd,YAAY,EACZ,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC/F,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,GACd,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC/E,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACvF,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC/E,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC1D,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,gBAAgB,EAChB,YAAY,EACZ,SAAS,GACV,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAE7D,4DAA4D;AAC5D,eAAO,MAAM,IAAI,iBAAiB,CAAA;AAElC;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,UAAuD,CAAA;AAE1E;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,cAAmB,GAAG,IAAI,CAqCrE"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The deterministic intent layer: a zero-token classifier (declarative rule
|
|
3
|
+
* table, explicit-intent patterns, bilingual keyword scoring, structural
|
|
4
|
+
* signals) plus the fingerprint posterior table that learns per-shape win rates
|
|
5
|
+
* from terminal outcomes.
|
|
6
|
+
*
|
|
7
|
+
* Everything in this module is pure and synchronous, so the whole classification
|
|
8
|
+
* matrix is unit-testable without a host. The low-confidence judge lives in
|
|
9
|
+
* `judge.ts` and is consulted only when this layer reports low confidence.
|
|
10
|
+
*
|
|
11
|
+
* @module dsh-autotier/intent
|
|
12
|
+
*/
|
|
13
|
+
import type { ResolvedRule, ScenarioToggles } from './config.js';
|
|
14
|
+
import type { Scenario, TierId } from './types.js';
|
|
15
|
+
/** One declarative rule row, already resolved by `resolveConfig`. */
|
|
16
|
+
export interface CompiledRule {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly patterns: readonly RegExp[];
|
|
19
|
+
readonly tools: readonly string[];
|
|
20
|
+
readonly cwd: string;
|
|
21
|
+
readonly tier: 'cheap' | 'strong';
|
|
22
|
+
readonly priority: number;
|
|
23
|
+
}
|
|
24
|
+
/** Compile the resolved rule table, ordered by descending priority. */
|
|
25
|
+
export declare function compileRules(rules: readonly ResolvedRule[]): CompiledRule[];
|
|
26
|
+
/** Input facts the classifier reads. All are derived from the live session. */
|
|
27
|
+
export interface IntentInput {
|
|
28
|
+
/** The newest user message text. */
|
|
29
|
+
readonly text: string;
|
|
30
|
+
/** Tool names already used in this session (advisory depth signal). */
|
|
31
|
+
readonly toolNames: readonly string[];
|
|
32
|
+
/** Whether the newest user message carries an image block. */
|
|
33
|
+
readonly hasImage: boolean;
|
|
34
|
+
/** Number of messages in the session (turn-depth signal). */
|
|
35
|
+
readonly messageCount: number;
|
|
36
|
+
/** Workspace path, matched against rule `when.cwd` prefixes. */
|
|
37
|
+
readonly cwd: string;
|
|
38
|
+
}
|
|
39
|
+
/** Structural signals computed from the input. */
|
|
40
|
+
export interface IntentSignals {
|
|
41
|
+
readonly chars: number;
|
|
42
|
+
readonly estTokens: number;
|
|
43
|
+
/** How many of the token bands `[4000, 12000, 30000]` the input crosses. */
|
|
44
|
+
readonly tokenBands: number;
|
|
45
|
+
readonly fences: number;
|
|
46
|
+
readonly toolCalls: number;
|
|
47
|
+
readonly messageCount: number;
|
|
48
|
+
readonly hardHints: number;
|
|
49
|
+
/** 0..8; `>= 3` escalates to the strong tier regardless of scenario. */
|
|
50
|
+
readonly score: number;
|
|
51
|
+
}
|
|
52
|
+
/** Why a classification short-circuited before keyword scoring. */
|
|
53
|
+
export type ShortCircuit = 'image' | 'long-text' | 'greeting' | 'explicit';
|
|
54
|
+
/** The classifier's verdict. */
|
|
55
|
+
export interface IntentResult {
|
|
56
|
+
readonly scenario: Scenario;
|
|
57
|
+
readonly tier: TierId;
|
|
58
|
+
/** 0..1; the rule layer decides alone at or above `intent.ruleThreshold`. */
|
|
59
|
+
readonly confidence: number;
|
|
60
|
+
/** Keyword score that produced the confidence. */
|
|
61
|
+
readonly keywordScore: number;
|
|
62
|
+
readonly signals: IntentSignals;
|
|
63
|
+
readonly reasons: readonly string[];
|
|
64
|
+
readonly shortCircuit: ShortCircuit | undefined;
|
|
65
|
+
/** Fingerprint of this shape: `scenario|tokenBand|fenceBand`. */
|
|
66
|
+
readonly fingerprint: string;
|
|
67
|
+
}
|
|
68
|
+
/** One declarative-rule hit. */
|
|
69
|
+
export interface RuleHit {
|
|
70
|
+
readonly id: string;
|
|
71
|
+
readonly tier: 'cheap' | 'strong';
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Evaluate the declarative rule table. Rules are already sorted by descending
|
|
75
|
+
* priority; the first match wins. A guard denial always outranks a rule (the
|
|
76
|
+
* guard runs on `tools/pre-execute`, after the routing decision, and denies
|
|
77
|
+
* regardless of tier).
|
|
78
|
+
*
|
|
79
|
+
* @param rules - compiled rules.
|
|
80
|
+
* @param input - the live input facts.
|
|
81
|
+
* @returns the winning hit, or null when no rule matches.
|
|
82
|
+
*/
|
|
83
|
+
export declare function evaluateRules(rules: readonly CompiledRule[], input: IntentInput): RuleHit | null;
|
|
84
|
+
/** Compute the structural signal vector. */
|
|
85
|
+
export declare function computeSignals(input: IntentInput): IntentSignals;
|
|
86
|
+
/** Build the fingerprint key for one classification. */
|
|
87
|
+
export declare function fingerprintOf(scenario: Scenario, signals: IntentSignals): string;
|
|
88
|
+
/** Options for {@link classifyIntent}. */
|
|
89
|
+
export interface ClassifyOptions {
|
|
90
|
+
readonly rules?: readonly CompiledRule[];
|
|
91
|
+
readonly scenarios: Required<ScenarioToggles>;
|
|
92
|
+
/** Score at or above which structural signals force the strong tier. */
|
|
93
|
+
readonly signalThreshold?: number;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Classify one user input. Deterministic and token-free; the caller decides
|
|
97
|
+
* whether the returned confidence warrants a judge call.
|
|
98
|
+
*
|
|
99
|
+
* @param input - the live input facts.
|
|
100
|
+
* @param options - compiled rules and scenario switches.
|
|
101
|
+
* @returns the verdict with its reasons.
|
|
102
|
+
*/
|
|
103
|
+
export declare function classifyIntent(input: IntentInput, options: ClassifyOptions): IntentResult;
|
|
104
|
+
/** One fingerprint's outcome counters. */
|
|
105
|
+
export interface Posterior {
|
|
106
|
+
cheapOK: number;
|
|
107
|
+
cheapN: number;
|
|
108
|
+
strongOK: number;
|
|
109
|
+
strongN: number;
|
|
110
|
+
/** Epoch millis of the last observation. */
|
|
111
|
+
lastSeen: number;
|
|
112
|
+
/** How many observations this key has accumulated (drives the half-life decay). */
|
|
113
|
+
observations: number;
|
|
114
|
+
/** How many exploration probes were spent on this key. */
|
|
115
|
+
probeN: number;
|
|
116
|
+
}
|
|
117
|
+
/** The verdict a posterior yields. */
|
|
118
|
+
export type PosteriorVerdict = 'strong' | 'cheap' | null;
|
|
119
|
+
/** Wilson score interval lower bound for `ok` successes in `n` trials. */
|
|
120
|
+
export declare function wilsonLowerBound(ok: number, n: number, z?: number): number;
|
|
121
|
+
/** Options for {@link PosteriorTable}. */
|
|
122
|
+
export interface PosteriorOptions {
|
|
123
|
+
/** Observations between two half-life decays (default 10). */
|
|
124
|
+
readonly halfLife?: number;
|
|
125
|
+
/** Cold-start threshold: below this total the table abstains (default 8). */
|
|
126
|
+
readonly coldStart?: number;
|
|
127
|
+
/** Exploration probability (default 0.05). */
|
|
128
|
+
readonly epsilon?: number;
|
|
129
|
+
/** LRU capacity (default 2000). */
|
|
130
|
+
readonly capacity?: number;
|
|
131
|
+
/** Deterministic random source for tests. */
|
|
132
|
+
readonly random?: () => number;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Per-fingerprint win-rate posteriors. Labels come from terminal task outcomes
|
|
136
|
+
* only (never from the router's own judge call), and every write decays old
|
|
137
|
+
* counts once per half-life so a shape's reputation can recover.
|
|
138
|
+
*/
|
|
139
|
+
export declare class PosteriorTable {
|
|
140
|
+
private readonly entries;
|
|
141
|
+
private readonly halfLife;
|
|
142
|
+
private readonly coldStart;
|
|
143
|
+
private readonly epsilon;
|
|
144
|
+
private readonly capacity;
|
|
145
|
+
private readonly random;
|
|
146
|
+
/** @param options - tuning knobs; defaults match the design table. */
|
|
147
|
+
constructor(options?: PosteriorOptions);
|
|
148
|
+
/** Number of tracked fingerprints. */
|
|
149
|
+
get size(): number;
|
|
150
|
+
/** Read one posterior without decaying it. */
|
|
151
|
+
get(key: string): Posterior | undefined;
|
|
152
|
+
/** Record one terminal outcome for a fingerprint and tier. */
|
|
153
|
+
record(key: string, tier: TierId, ok: boolean, now: number): void;
|
|
154
|
+
/** Count one exploration probe on a key. */
|
|
155
|
+
probe(key: string): void;
|
|
156
|
+
/**
|
|
157
|
+
* The table's opinion about one fingerprint, without the exploration roll.
|
|
158
|
+
* @param key - the fingerprint.
|
|
159
|
+
* @returns the base verdict and whether an exploration probe is warranted.
|
|
160
|
+
*/
|
|
161
|
+
opinion(key: string): {
|
|
162
|
+
verdict: PosteriorVerdict;
|
|
163
|
+
explore: boolean;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* The table's opinion about one fingerprint. The exploration roll is a
|
|
167
|
+
* decision point, so callers take it once per user input and reuse the
|
|
168
|
+
* result for every step of that input's turn.
|
|
169
|
+
* @param key - the fingerprint.
|
|
170
|
+
* @returns `'strong'`, `'cheap'`, or `null` when the table abstains.
|
|
171
|
+
*/
|
|
172
|
+
verdict(key: string): PosteriorVerdict;
|
|
173
|
+
/** Snapshot every key, newest first, for `/tier status` and diagnostics. */
|
|
174
|
+
snapshot(): {
|
|
175
|
+
key: string;
|
|
176
|
+
posterior: Posterior;
|
|
177
|
+
}[];
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=intent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../src/intent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAElD,qEAAqE;AACrE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,YAAY,EAAE,CAW3E;AAED,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,6DAA6D;IAC7D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,gEAAgE;IAChE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,mEAAmE;AACnE,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAA;AAE1E,gCAAgC;AAChC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,YAAY,EAAE,YAAY,GAAG,SAAS,CAAA;IAC/C,iEAAiE;IACjE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,gCAAgC;AAChC,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;CAClC;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,GAAG,IAAI,CAehG;AA+FD,4CAA4C;AAC5C,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,CA0BhE;AAiBD,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAEhF;AAED,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAA;IAC7C,wEAAwE;IACxE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,GAAG,YAAY,CAmDzF;AAID,0CAA0C;AAC1C,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAA;IAChB,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAA;IACpB,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAA;CACf;AAED,sCAAsC;AACtC,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,GAAG,IAAI,CAAA;AAExD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,SAAO,GAAG,MAAM,CAOxE;AAED,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAA;CAC/B;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC,sEAAsE;gBAC1D,OAAO,GAAE,gBAAqB;IAQ1C,sCAAsC;IACtC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,8CAA8C;IAC9C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIvC,8DAA8D;IAC9D,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAqCjE,4CAA4C;IAC5C,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKxB;;;;OAIG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,gBAAgB,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;IASrE;;;;;;OAMG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB;IAStC,4EAA4E;IAC5E,QAAQ,IAAI;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,SAAS,CAAA;KAAE,EAAE;CAGpD"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The low-confidence judge: a cheap model classifies intent only. It is called
|
|
3
|
+
* when the deterministic layer's confidence falls below `intent.ruleThreshold`,
|
|
4
|
+
* never on cooldown, and never while the previous calls are failing — the
|
|
5
|
+
* classifier's own verdict is always the fallback.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-autotier/judge
|
|
8
|
+
*/
|
|
9
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
10
|
+
import type { ResolvedConfig } from './config.js';
|
|
11
|
+
import type { Scenario, TierId } from './types.js';
|
|
12
|
+
/** The label vocabulary the judge is asked to choose from. */
|
|
13
|
+
export declare const JUDGE_LABELS: readonly {
|
|
14
|
+
readonly label: string;
|
|
15
|
+
readonly scenario: Scenario;
|
|
16
|
+
}[];
|
|
17
|
+
/** The judge's answer. */
|
|
18
|
+
export interface JudgeOutcome {
|
|
19
|
+
/** Whether the call produced a usable label. */
|
|
20
|
+
readonly ok: boolean;
|
|
21
|
+
readonly scenario: Scenario | undefined;
|
|
22
|
+
readonly tier: TierId | undefined;
|
|
23
|
+
/** Short diagnostic; safe for logs (no prompt text). */
|
|
24
|
+
readonly detail: string;
|
|
25
|
+
}
|
|
26
|
+
/** The route the judge call uses. */
|
|
27
|
+
export interface JudgeRoute {
|
|
28
|
+
readonly provider: string;
|
|
29
|
+
readonly model: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the judge route: the configured model, else the first catalog model
|
|
33
|
+
* whose id contains `flash` on the cheap tier's provider.
|
|
34
|
+
* @param ctx - the plugin context (reads `ctx.llm`).
|
|
35
|
+
* @param config - the resolved configuration.
|
|
36
|
+
* @returns the route, or undefined when no candidate exists.
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveJudgeRoute(ctx: Context, config: ResolvedConfig): Promise<JudgeRoute | undefined>;
|
|
39
|
+
/** Extract the first label that appears in the judge's answer. */
|
|
40
|
+
export declare function parseJudgeLabel(answer: string): Scenario | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Run one judge call.
|
|
43
|
+
* @param ctx - the plugin context (reads `ctx.llm`).
|
|
44
|
+
* @param config - the resolved configuration.
|
|
45
|
+
* @param text - the newest user message text.
|
|
46
|
+
* @param signal - the turn's abort signal; the judge adds its own timeout.
|
|
47
|
+
* @returns the outcome; a failure is reported, never thrown.
|
|
48
|
+
*/
|
|
49
|
+
export declare function runJudge(ctx: Context, config: ResolvedConfig, text: string, signal: AbortSignal): Promise<JudgeOutcome>;
|
|
50
|
+
//# sourceMappingURL=judge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"judge.d.ts","sourceRoot":"","sources":["../../src/judge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAElD,8DAA8D;AAC9D,eAAO,MAAM,YAAY,EAAE,SAAS;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,EAS1F,CAAA;AAcD,0BAA0B;AAC1B,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,qCAAqC;AACrC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAc7G;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAQpE;AAED;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,YAAY,CAAC,CAgDvB"}
|