open-multi-agent-kit 0.90.0 → 0.90.4
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 +56 -0
- package/README.md +22 -31
- package/dist/cli/args.d.ts +0 -2
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -7
- package/dist/cli/args.js.map +1 -1
- package/dist/config.d.ts +3 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +27 -19
- package/dist/config.js.map +1 -1
- package/dist/core/adaptorch-bridge.d.ts +257 -0
- package/dist/core/adaptorch-bridge.d.ts.map +1 -0
- package/dist/core/adaptorch-bridge.js +473 -0
- package/dist/core/adaptorch-bridge.js.map +1 -0
- package/dist/core/agent-session.d.ts +132 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +327 -5
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bang-skill-invocation.d.ts +26 -0
- package/dist/core/bang-skill-invocation.d.ts.map +1 -0
- package/dist/core/bang-skill-invocation.js +208 -0
- package/dist/core/bang-skill-invocation.js.map +1 -0
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +15 -2
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/compactor.d.ts.map +1 -1
- package/dist/core/compactor.js +0 -3
- package/dist/core/compactor.js.map +1 -1
- package/dist/core/context-budget-governor-v2.d.ts +2 -1
- package/dist/core/context-budget-governor-v2.d.ts.map +1 -1
- package/dist/core/context-budget-governor-v2.js +1 -0
- package/dist/core/context-budget-governor-v2.js.map +1 -1
- package/dist/core/context-budget-headroom-types.d.ts +8 -0
- package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
- package/dist/core/context-budget-headroom-types.js.map +1 -1
- package/dist/core/context-budget-headroom.d.ts +1 -1
- package/dist/core/context-budget-headroom.d.ts.map +1 -1
- package/dist/core/context-budget-headroom.js +17 -4
- package/dist/core/context-budget-headroom.js.map +1 -1
- package/dist/core/context-budget-system-prompt.d.ts +2 -1
- package/dist/core/context-budget-system-prompt.d.ts.map +1 -1
- package/dist/core/context-budget-system-prompt.js +6 -1
- package/dist/core/context-budget-system-prompt.js.map +1 -1
- package/dist/core/context-budget-v2-cache-hash.d.ts +3 -0
- package/dist/core/context-budget-v2-cache-hash.d.ts.map +1 -0
- package/dist/core/context-budget-v2-cache-hash.js +16 -0
- package/dist/core/context-budget-v2-cache-hash.js.map +1 -0
- package/dist/core/context-budget-v2-cache-keys.d.ts +58 -0
- package/dist/core/context-budget-v2-cache-keys.d.ts.map +1 -0
- package/dist/core/context-budget-v2-cache-keys.js +128 -0
- package/dist/core/context-budget-v2-cache-keys.js.map +1 -0
- package/dist/core/context-budget-v2-cache-provider.d.ts +23 -0
- package/dist/core/context-budget-v2-cache-provider.d.ts.map +1 -0
- package/dist/core/context-budget-v2-cache-provider.js +29 -0
- package/dist/core/context-budget-v2-cache-provider.js.map +1 -0
- package/dist/core/context-budget-v2-cache-telemetry.d.ts +36 -0
- package/dist/core/context-budget-v2-cache-telemetry.d.ts.map +1 -0
- package/dist/core/context-budget-v2-cache-telemetry.js +64 -0
- package/dist/core/context-budget-v2-cache-telemetry.js.map +1 -0
- package/dist/core/context-budget-v2-cache-validation.d.ts +36 -0
- package/dist/core/context-budget-v2-cache-validation.d.ts.map +1 -0
- package/dist/core/context-budget-v2-cache-validation.js +98 -0
- package/dist/core/context-budget-v2-cache-validation.js.map +1 -0
- package/dist/core/context-budget-v2-cache.d.ts +36 -0
- package/dist/core/context-budget-v2-cache.d.ts.map +1 -0
- package/dist/core/context-budget-v2-cache.js +50 -0
- package/dist/core/context-budget-v2-cache.js.map +1 -0
- package/dist/core/context-budget-v2-plan-cache-keys.d.ts +16 -0
- package/dist/core/context-budget-v2-plan-cache-keys.d.ts.map +1 -0
- package/dist/core/context-budget-v2-plan-cache-keys.js +49 -0
- package/dist/core/context-budget-v2-plan-cache-keys.js.map +1 -0
- package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
- package/dist/core/context-budget-v2-planner.js +55 -2
- package/dist/core/context-budget-v2-planner.js.map +1 -1
- package/dist/core/context-budget-v2-representation-cache.d.ts +27 -0
- package/dist/core/context-budget-v2-representation-cache.d.ts.map +1 -0
- package/dist/core/context-budget-v2-representation-cache.js +173 -0
- package/dist/core/context-budget-v2-representation-cache.js.map +1 -0
- package/dist/core/context-budget-v2-selection.d.ts +2 -0
- package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
- package/dist/core/context-budget-v2-selection.js +12 -2
- package/dist/core/context-budget-v2-selection.js.map +1 -1
- package/dist/core/context-budget-v2-types.d.ts +107 -1
- package/dist/core/context-budget-v2-types.d.ts.map +1 -1
- package/dist/core/context-budget-v2-types.js.map +1 -1
- package/dist/core/domain-loadouts.d.ts.map +1 -1
- package/dist/core/domain-loadouts.js +1 -1
- package/dist/core/domain-loadouts.js.map +1 -1
- package/dist/core/headroom.d.ts.map +1 -1
- package/dist/core/headroom.js +0 -4
- package/dist/core/headroom.js.map +1 -1
- package/dist/core/hook-inventory.d.ts.map +1 -1
- package/dist/core/hook-inventory.js +6 -0
- package/dist/core/hook-inventory.js.map +1 -1
- package/dist/core/mcp-computer-use-presets.d.ts +64 -0
- package/dist/core/mcp-computer-use-presets.d.ts.map +1 -0
- package/dist/core/mcp-computer-use-presets.js +158 -0
- package/dist/core/mcp-computer-use-presets.js.map +1 -0
- package/dist/core/mcp-public-presets.d.ts +578 -0
- package/dist/core/mcp-public-presets.d.ts.map +1 -0
- package/dist/core/mcp-public-presets.js +647 -0
- package/dist/core/mcp-public-presets.js.map +1 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +1 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/pi-package-intake-candidates.d.ts +14 -1
- package/dist/core/pi-package-intake-candidates.d.ts.map +1 -1
- package/dist/core/pi-package-intake-candidates.js +182 -0
- package/dist/core/pi-package-intake-candidates.js.map +1 -1
- package/dist/core/pi-package-intake.d.ts +8 -1
- package/dist/core/pi-package-intake.d.ts.map +1 -1
- package/dist/core/pi-package-intake.js +14 -4
- package/dist/core/pi-package-intake.js.map +1 -1
- package/dist/core/reasoning-router-bias.d.ts +119 -0
- package/dist/core/reasoning-router-bias.d.ts.map +1 -0
- package/dist/core/reasoning-router-bias.js +287 -0
- package/dist/core/reasoning-router-bias.js.map +1 -0
- package/dist/core/reasoning-router-v2.d.ts +94 -0
- package/dist/core/reasoning-router-v2.d.ts.map +1 -0
- package/dist/core/reasoning-router-v2.js +288 -0
- package/dist/core/reasoning-router-v2.js.map +1 -0
- package/dist/core/reasoning-router-v3.d.ts +15 -0
- package/dist/core/reasoning-router-v3.d.ts.map +1 -0
- package/dist/core/reasoning-router-v3.js +193 -0
- package/dist/core/reasoning-router-v3.js.map +1 -0
- package/dist/core/reasoning-router-v4-weights.d.ts +124 -0
- package/dist/core/reasoning-router-v4-weights.d.ts.map +1 -0
- package/dist/core/reasoning-router-v4-weights.js +112 -0
- package/dist/core/reasoning-router-v4-weights.js.map +1 -0
- package/dist/core/reasoning-router-v4.d.ts +163 -0
- package/dist/core/reasoning-router-v4.d.ts.map +1 -0
- package/dist/core/reasoning-router-v4.js +683 -0
- package/dist/core/reasoning-router-v4.js.map +1 -0
- package/dist/core/reasoning-router-weights.d.ts +155 -0
- package/dist/core/reasoning-router-weights.d.ts.map +1 -0
- package/dist/core/reasoning-router-weights.js +204 -0
- package/dist/core/reasoning-router-weights.js.map +1 -0
- package/dist/core/reasoning-router.d.ts +44 -0
- package/dist/core/reasoning-router.d.ts.map +1 -0
- package/dist/core/reasoning-router.js +138 -0
- package/dist/core/reasoning-router.js.map +1 -0
- package/dist/core/reverse-skill.d.ts +2 -0
- package/dist/core/reverse-skill.d.ts.map +1 -0
- package/dist/core/reverse-skill.js +7 -0
- package/dist/core/reverse-skill.js.map +1 -0
- package/dist/core/router-feedback-collector.d.ts +101 -0
- package/dist/core/router-feedback-collector.d.ts.map +1 -0
- package/dist/core/router-feedback-collector.js +239 -0
- package/dist/core/router-feedback-collector.js.map +1 -0
- package/dist/core/settings-manager.d.ts +31 -3
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +16 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +4 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +2 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +58 -5
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/migrations.d.ts +19 -0
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +39 -15
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-box.d.ts +3 -3
- package/dist/modes/interactive/components/control-panel-box.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel-box.js +10 -10
- package/dist/modes/interactive/components/control-panel-box.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-gradient-motion.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel-gradient-motion.js +2 -1
- package/dist/modes/interactive/components/control-panel-gradient-motion.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-layout.d.ts +15 -1
- package/dist/modes/interactive/components/control-panel-layout.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel-layout.js +212 -68
- package/dist/modes/interactive/components/control-panel-layout.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-runtime-status.d.ts +15 -0
- package/dist/modes/interactive/components/control-panel-runtime-status.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel-runtime-status.js +105 -5
- package/dist/modes/interactive/components/control-panel-runtime-status.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-sparkles.d.ts +27 -0
- package/dist/modes/interactive/components/control-panel-sparkles.d.ts.map +1 -0
- package/dist/modes/interactive/components/control-panel-sparkles.js +42 -0
- package/dist/modes/interactive/components/control-panel-sparkles.js.map +1 -0
- package/dist/modes/interactive/components/control-panel.d.ts +8 -0
- package/dist/modes/interactive/components/control-panel.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel.js +40 -8
- package/dist/modes/interactive/components/control-panel.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +2 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +2 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +6 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +206 -32
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +2 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/docs/loadout-domains/README.md +8 -6
- package/docs/loadout-domains/ai-agent-ops.md +3 -2
- package/docs/loadout-domains/backend-api.md +3 -2
- package/docs/loadout-domains/data-science.md +3 -2
- package/docs/loadout-domains/devops-infra.md +2 -1
- package/docs/loadout-domains/docs-writing.md +7 -2
- package/docs/loadout-domains/frontend-ui.md +42 -11
- package/docs/loadout-domains/korean-document.md +83 -0
- package/docs/loadout-domains/mobile.md +1 -1
- package/docs/loadout-domains/qa-testing.md +4 -2
- package/docs/loadout-domains/security-audit.md +2 -1
- package/docs/loadout-domains/visual-qa.md +94 -0
- package/docs/skills.md +11 -4
- package/docs/usage.md +39 -4
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/preset.ts +2 -2
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +27 -34
- package/package.json +5 -5
- package/dist/agents/jailbreak/index.d.ts +0 -7
- package/dist/agents/jailbreak/index.d.ts.map +0 -1
- package/dist/agents/jailbreak/index.js +0 -7
- package/dist/agents/jailbreak/index.js.map +0 -1
- package/dist/agents/jailbreak/subagent-f.d.ts +0 -44
- package/dist/agents/jailbreak/subagent-f.d.ts.map +0 -1
- package/dist/agents/jailbreak/subagent-f.js +0 -60
- package/dist/agents/jailbreak/subagent-f.js.map +0 -1
- package/dist/cli/jailbreak-args.d.ts +0 -26
- package/dist/cli/jailbreak-args.d.ts.map +0 -1
- package/dist/cli/jailbreak-args.js +0 -86
- package/dist/cli/jailbreak-args.js.map +0 -1
- package/dist/commands/jailbreak.d.ts +0 -49
- package/dist/commands/jailbreak.d.ts.map +0 -1
- package/dist/commands/jailbreak.js +0 -201
- package/dist/commands/jailbreak.js.map +0 -1
- package/dist/encoding/index.d.ts +0 -6
- package/dist/encoding/index.d.ts.map +0 -1
- package/dist/encoding/index.js +0 -6
- package/dist/encoding/index.js.map +0 -1
- package/dist/encoding/l4-encoder.d.ts +0 -96
- package/dist/encoding/l4-encoder.d.ts.map +0 -1
- package/dist/encoding/l4-encoder.js +0 -474
- package/dist/encoding/l4-encoder.js.map +0 -1
- package/dist/fuzzing/index.d.ts +0 -6
- package/dist/fuzzing/index.d.ts.map +0 -1
- package/dist/fuzzing/index.js +0 -6
- package/dist/fuzzing/index.js.map +0 -1
- package/dist/fuzzing/mutation-engine.d.ts +0 -93
- package/dist/fuzzing/mutation-engine.d.ts.map +0 -1
- package/dist/fuzzing/mutation-engine.js +0 -244
- package/dist/fuzzing/mutation-engine.js.map +0 -1
- package/dist/jailbreak-extension.d.ts +0 -48
- package/dist/jailbreak-extension.d.ts.map +0 -1
- package/dist/jailbreak-extension.js +0 -47
- package/dist/jailbreak-extension.js.map +0 -1
- package/dist/modules/index.d.ts +0 -8
- package/dist/modules/index.d.ts.map +0 -1
- package/dist/modules/index.js +0 -7
- package/dist/modules/index.js.map +0 -1
- package/dist/modules/lrl-bypass.d.ts +0 -40
- package/dist/modules/lrl-bypass.d.ts.map +0 -1
- package/dist/modules/lrl-bypass.js +0 -84
- package/dist/modules/lrl-bypass.js.map +0 -1
- package/dist/modules/lrl-deps.d.ts +0 -38
- package/dist/modules/lrl-deps.d.ts.map +0 -1
- package/dist/modules/lrl-deps.js +0 -128
- package/dist/modules/lrl-deps.js.map +0 -1
- package/dist/multiturn/easl-chain.d.ts +0 -113
- package/dist/multiturn/easl-chain.d.ts.map +0 -1
- package/dist/multiturn/easl-chain.js +0 -351
- package/dist/multiturn/easl-chain.js.map +0 -1
- package/dist/multiturn/index.d.ts +0 -6
- package/dist/multiturn/index.d.ts.map +0 -1
- package/dist/multiturn/index.js +0 -6
- package/dist/multiturn/index.js.map +0 -1
- package/dist/routing/fallback-router.d.ts +0 -123
- package/dist/routing/fallback-router.d.ts.map +0 -1
- package/dist/routing/fallback-router.js +0 -355
- package/dist/routing/fallback-router.js.map +0 -1
- package/dist/routing/index.d.ts +0 -6
- package/dist/routing/index.d.ts.map +0 -1
- package/dist/routing/index.js +0 -6
- package/dist/routing/index.js.map +0 -1
- package/dist/types/jailbreak.d.ts +0 -246
- package/dist/types/jailbreak.d.ts.map +0 -1
- package/dist/types/jailbreak.js +0 -8
- package/dist/types/jailbreak.js.map +0 -1
- package/dist/utils/jailbreak/common.d.ts +0 -63
- package/dist/utils/jailbreak/common.d.ts.map +0 -1
- package/dist/utils/jailbreak/common.js +0 -130
- package/dist/utils/jailbreak/common.js.map +0 -1
- package/dist/utils/jailbreak/index.d.ts +0 -7
- package/dist/utils/jailbreak/index.d.ts.map +0 -1
- package/dist/utils/jailbreak/index.js +0 -7
- package/dist/utils/jailbreak/index.js.map +0 -1
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reasoning-router v2 — pure weighted classifier + resolver (Goal 004, Lane I2/I3).
|
|
3
|
+
*
|
|
4
|
+
* Deterministic by construction: same (input, weights) -> same TaskClassV2, and
|
|
5
|
+
* same (taskClass, availableLevels, laneType, bias, hint) -> same ThinkingLevel.
|
|
6
|
+
* No clock, randomness, or I/O. Erasable TypeScript only (ThinkingLevel is
|
|
7
|
+
* imported type-only and erased).
|
|
8
|
+
*
|
|
9
|
+
* ============================================================================
|
|
10
|
+
* v1-COMPAT BEHAVIOR UNDER DEFAULT_WEIGHTS
|
|
11
|
+
* ============================================================================
|
|
12
|
+
* With DEFAULT_WEIGHTS (frozen in reasoning-router-weights.ts), classifyTaskV2
|
|
13
|
+
* reproduces v1 classifyTask on the full v1 corpus (Goal 004 Req 1.4), with one
|
|
14
|
+
* INTENTIONAL fix family: a lone WEAK-debug trigger ("fix") no longer dominates
|
|
15
|
+
* a stronger class signal. Concretely, "fix the typo" classifies as simple-edit,
|
|
16
|
+
* not debug (Goal 004 Req 1.3 — the v1 regression case). This is achieved by the
|
|
17
|
+
* STRONG/WEAK keyword split below: "fix" lives in WEAK-debug only, and
|
|
18
|
+
* DEFAULT_WEIGHTS weights only the STRONG diagonal, so a STRONG simple-edit hit
|
|
19
|
+
* ("typo") outscores the unweighted WEAK "fix".
|
|
20
|
+
*
|
|
21
|
+
* The zero-score cascade (v1 steps 2-6) runs verbatim whenever every scoreClass
|
|
22
|
+
* term is 0, preserving v1's length/lane/default behavior for signal-free turns.
|
|
23
|
+
* sticky/consult/margin thresholds are 0 in DEFAULT_WEIGHTS and treated as
|
|
24
|
+
* INACTIVE (<= 0), so v1-compat never enters the sticky/consult/judge paths.
|
|
25
|
+
* ============================================================================
|
|
26
|
+
*/
|
|
27
|
+
import { scoreClass, TASK_CLASSES_V2, } from "./reasoning-router-weights.js";
|
|
28
|
+
export { DEFAULT_WEIGHTS, scoreClass, TASK_CLASSES_V2 } from "./reasoning-router-weights.js";
|
|
29
|
+
/** Prompts shorter than this (trimmed) classify as trivial via the zero-score cascade. */
|
|
30
|
+
const TRIVIAL_MAX_CHARS = 40;
|
|
31
|
+
/** Prompts at/above this length with no signal are treated as long prose briefs (plan). */
|
|
32
|
+
const COMPLEX_PROSE_MIN_CHARS = 2400;
|
|
33
|
+
/** Ring-buffer cap for multi-turn history (caller-owned). */
|
|
34
|
+
const HISTORY_CAP = 8;
|
|
35
|
+
/**
|
|
36
|
+
* STRONG (class-defining) keyword families, derived from v1 KEYWORD_FAMILIES
|
|
37
|
+
* (reasoning-router.ts). Each pattern is the v1 alternation MINUS the ambiguous
|
|
38
|
+
* WEAK tokens that are split out below. Default i (no `g` flag): stateless.
|
|
39
|
+
*/
|
|
40
|
+
const STRONG_KEYWORDS = [
|
|
41
|
+
{
|
|
42
|
+
taskClass: "debug",
|
|
43
|
+
pattern: /\b(debug(ging)?|bugs?|errors?|exceptions?|crash(es|ing|ed)?|stack\s*trace|traceback|regressions?|broken|fail(s|ing|ed|ure|ures)?|flaky|reproduce)\b/i,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
taskClass: "refactor",
|
|
47
|
+
pattern: /\b(refactor(ing|ed)?|restructur(e|ing)|renam(e|ing)|extract(ing)?|clean\s*up|cleanup|deduplicat(e|ing)|reorganiz(e|ing)|modulariz(e|ing))\b/i,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
taskClass: "review",
|
|
51
|
+
pattern: /\b(review(s|ing|ed)?|audit(s|ing|ed)?|critique|inspect(ing)?)\b/i,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
taskClass: "plan",
|
|
55
|
+
pattern: /\b(plan(s|ning)?|design(s|ing)?|architect(s|ure|ing)?|roadmap|spec(s|ification|ifications)?|strateg(y|ies|ize)|decompos(e|ing|ition)|milestones?)\b/i,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
taskClass: "simple-edit",
|
|
59
|
+
pattern: /\b(typos?|tweak(s|ing|ed)?|one-?liner?|single\s+line|bump(s|ing|ed)?|whitespace|reword(s|ing|ed)?|indentation|punctuation)\b/i,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
taskClass: "code-gen",
|
|
63
|
+
pattern: /\b(implement(s|ing|ation)?|writ(e|ing)|creat(e|es|ing)|build(s|ing)?|generat(e|es|ing)|scaffold(ing)?|prototype)\b/i,
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
/**
|
|
67
|
+
* WEAK (ambiguous) keyword sub-patterns split out of the v1 alternations. Under
|
|
68
|
+
* DEFAULT_WEIGHTS these are INERT (the weight matrix has no WEAK coefficients),
|
|
69
|
+
* so they do not affect v1-compat; they exist for calibrated weight presets.
|
|
70
|
+
* The critical entry is debug "fix": a lone "fix" without a STRONG debug
|
|
71
|
+
* co-trigger no longer wins debug over a stronger sibling-class signal.
|
|
72
|
+
*/
|
|
73
|
+
const WEAK_KEYWORDS = [
|
|
74
|
+
{ taskClass: "debug", pattern: /\bfix(es|ing|ed)?\b/i },
|
|
75
|
+
{ taskClass: "code-gen", pattern: /\badd(s|ing|ed)?\b/i },
|
|
76
|
+
{ taskClass: "refactor", pattern: /\b(simplif(y|ying|ied)|rewrit(e|ing))\b/i },
|
|
77
|
+
{ taskClass: "review", pattern: /\b(assess(ing|ment)?|lgtm|approve)\b/i },
|
|
78
|
+
{ taskClass: "plan", pattern: /\bbreak\s+(this\s+|it\s+)?down\b/i },
|
|
79
|
+
];
|
|
80
|
+
/** Lane fallback when no keyword/code/diff/length signal decides (mirrors v1). */
|
|
81
|
+
const LANE_FALLBACK_CLASS_V2 = {
|
|
82
|
+
planner: "plan",
|
|
83
|
+
security: "review",
|
|
84
|
+
explorer: "review",
|
|
85
|
+
coder: "code-gen",
|
|
86
|
+
reviewer: "review",
|
|
87
|
+
tester: "code-gen",
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Tie-break / iteration order: v1 precedence (highest first). When two classes
|
|
91
|
+
* tie on score, the one appearing earlier here wins, matching v1's first-match
|
|
92
|
+
* semantics. trivial is last (it carries no keyword weight under any preset).
|
|
93
|
+
*/
|
|
94
|
+
const PRECEDENCE_ORDER = [
|
|
95
|
+
"debug",
|
|
96
|
+
"refactor",
|
|
97
|
+
"review",
|
|
98
|
+
"plan",
|
|
99
|
+
"simple-edit",
|
|
100
|
+
"code-gen",
|
|
101
|
+
"trivial",
|
|
102
|
+
];
|
|
103
|
+
function hasCodeFence(text) {
|
|
104
|
+
return text.includes("```");
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Diff detection, identical to v1: explicit hunk headers or `diff --git` count
|
|
108
|
+
* alone; bare +/- line starts only count when BOTH added and removed are present
|
|
109
|
+
* (avoids false positives on markdown bullets).
|
|
110
|
+
*/
|
|
111
|
+
function hasDiffMarkers(text) {
|
|
112
|
+
if (/^@@[^\n]*@@/m.test(text) || /^diff --git /m.test(text))
|
|
113
|
+
return true;
|
|
114
|
+
return /^\+(?!\+)/m.test(text) && /^-(?!-)/m.test(text);
|
|
115
|
+
}
|
|
116
|
+
function clampLenBucket(len) {
|
|
117
|
+
// floor(log2(len+1)) clamped to [0,7]; integer comparison ladder, no float log.
|
|
118
|
+
let bucket = 0;
|
|
119
|
+
let v = len + 1;
|
|
120
|
+
while (v > 1 && bucket < 7) {
|
|
121
|
+
v >>= 1;
|
|
122
|
+
bucket++;
|
|
123
|
+
}
|
|
124
|
+
return bucket;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Deterministic weighted multi-signal classifier (Goal 004 Req 1).
|
|
128
|
+
*
|
|
129
|
+
* Pipeline:
|
|
130
|
+
* 1. Extract RouterFeatures from input (STRONG/WEAK keyword 0/1 counts per
|
|
131
|
+
* family, codeFence, diffHunk, lenBucket, multiTurnPrior, pressureBucket,
|
|
132
|
+
* judgeVote).
|
|
133
|
+
* 2. Score every class via the frozen scoreClass(c, f, weights). top1 = argmax
|
|
134
|
+
* with v1-precedence tie-break; margin = top1 - top2.
|
|
135
|
+
* 3. ZERO-SCORE CASCADE (v1-compat): when maxScore === 0, fall through exactly
|
|
136
|
+
* like v1 steps 2-6 (fence/diff -> code-gen; len<40 -> trivial; len>=2400
|
|
137
|
+
* -> plan; lane fallback; default code-gen).
|
|
138
|
+
* 4. HYSTERESIS: only when weights.stickyThreshold > 0 (INACTIVE for
|
|
139
|
+
* DEFAULT_WEIGHTS). If margin < stickyThreshold and history is non-empty,
|
|
140
|
+
* keep the previous class unless a STRONG keyword matched for top1.
|
|
141
|
+
*
|
|
142
|
+
* Pure: same (input, weights) -> same TaskClassV2.
|
|
143
|
+
*/
|
|
144
|
+
export function classifyTaskV2(input, weights) {
|
|
145
|
+
const prompt = input.prompt.trim();
|
|
146
|
+
const strongKeyword = {};
|
|
147
|
+
const weakKeyword = {};
|
|
148
|
+
for (const { taskClass, pattern } of STRONG_KEYWORDS) {
|
|
149
|
+
strongKeyword[taskClass] = pattern.test(prompt) ? 1 : 0;
|
|
150
|
+
}
|
|
151
|
+
for (const { taskClass, pattern } of WEAK_KEYWORDS) {
|
|
152
|
+
weakKeyword[taskClass] = (weakKeyword[taskClass] ?? 0) + (pattern.test(prompt) ? 1 : 0);
|
|
153
|
+
}
|
|
154
|
+
const codeFence = hasCodeFence(prompt);
|
|
155
|
+
const diffHunk = hasDiffMarkers(prompt);
|
|
156
|
+
const lenBucket = clampLenBucket(prompt.length);
|
|
157
|
+
const history = input.history;
|
|
158
|
+
const multiTurnPrior = history !== undefined && history.length > 0 ? history[0] : null;
|
|
159
|
+
const pressureBucket = input.pressureBucket ?? 0;
|
|
160
|
+
const judgeVote = input.judgeVote ?? null;
|
|
161
|
+
const features = {
|
|
162
|
+
strongKeyword,
|
|
163
|
+
weakKeyword,
|
|
164
|
+
codeFence,
|
|
165
|
+
diffHunk,
|
|
166
|
+
lenBucket,
|
|
167
|
+
multiTurnPrior,
|
|
168
|
+
pressureBucket,
|
|
169
|
+
judgeVote,
|
|
170
|
+
};
|
|
171
|
+
// Score every class; track top1 (v1-precedence tie-break) and the runner-up.
|
|
172
|
+
const scores = new Map();
|
|
173
|
+
for (const c of TASK_CLASSES_V2) {
|
|
174
|
+
scores.set(c, scoreClass(c, features, weights));
|
|
175
|
+
}
|
|
176
|
+
let top1 = PRECEDENCE_ORDER[0];
|
|
177
|
+
for (const c of PRECEDENCE_ORDER) {
|
|
178
|
+
if ((scores.get(c) ?? 0) > (scores.get(top1) ?? 0))
|
|
179
|
+
top1 = c;
|
|
180
|
+
}
|
|
181
|
+
let top2 = null;
|
|
182
|
+
for (const c of PRECEDENCE_ORDER) {
|
|
183
|
+
if (c === top1)
|
|
184
|
+
continue;
|
|
185
|
+
if (top2 === null || (scores.get(c) ?? 0) > (scores.get(top2) ?? 0))
|
|
186
|
+
top2 = c;
|
|
187
|
+
}
|
|
188
|
+
const maxScore = scores.get(top1) ?? 0;
|
|
189
|
+
const margin = top2 !== null ? maxScore - (scores.get(top2) ?? 0) : maxScore;
|
|
190
|
+
// ZERO-SCORE CASCADE: no weighted signal fired -> v1 steps 2-6 verbatim.
|
|
191
|
+
if (maxScore <= 0) {
|
|
192
|
+
if (codeFence || diffHunk)
|
|
193
|
+
return "code-gen";
|
|
194
|
+
if (prompt.length < TRIVIAL_MAX_CHARS)
|
|
195
|
+
return "trivial";
|
|
196
|
+
if (prompt.length >= COMPLEX_PROSE_MIN_CHARS)
|
|
197
|
+
return "plan";
|
|
198
|
+
if (input.laneType)
|
|
199
|
+
return LANE_FALLBACK_CLASS_V2[input.laneType];
|
|
200
|
+
return "code-gen";
|
|
201
|
+
}
|
|
202
|
+
// HYSTERESIS: keep previous class on low-margin multi-turn turns. INACTIVE for
|
|
203
|
+
// DEFAULT_WEIGHTS (stickyThreshold === 0). A STRONG keyword hit on top1 always
|
|
204
|
+
// bypasses stickiness so an intentional topic switch still wins.
|
|
205
|
+
if (weights.stickyThreshold > 0 &&
|
|
206
|
+
margin < weights.stickyThreshold &&
|
|
207
|
+
multiTurnPrior !== null &&
|
|
208
|
+
(features.strongKeyword[top1] ?? 0) <= 0) {
|
|
209
|
+
return multiTurnPrior;
|
|
210
|
+
}
|
|
211
|
+
return top1;
|
|
212
|
+
}
|
|
213
|
+
/** Reasoning ladder used for targets and clamping. Intentionally excludes "off". */
|
|
214
|
+
const REASONING_LADDER_V2 = ["minimal", "low", "medium", "high", "xhigh", "max"];
|
|
215
|
+
/**
|
|
216
|
+
* Static rule table: task class -> recommended ThinkingLevel (before lane
|
|
217
|
+
* adjustment, bias, hint, and clamping). Identical to v1 TASK_CLASS_THINKING_LEVELS.
|
|
218
|
+
*/
|
|
219
|
+
export const TASK_CLASS_THINKING_LEVELS_V2 = {
|
|
220
|
+
trivial: "minimal",
|
|
221
|
+
"simple-edit": "low",
|
|
222
|
+
"code-gen": "medium",
|
|
223
|
+
debug: "high",
|
|
224
|
+
refactor: "high",
|
|
225
|
+
review: "high",
|
|
226
|
+
plan: "xhigh",
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* Lane ladder adjustment (mirrors DEFAULT_WEIGHTS.laneStep and v1 LANE_STEP):
|
|
230
|
+
* planner/security escalate one step, explorer de-escalates one step.
|
|
231
|
+
*/
|
|
232
|
+
const LANE_STEP_V2 = {
|
|
233
|
+
planner: 1,
|
|
234
|
+
security: 1,
|
|
235
|
+
explorer: -1,
|
|
236
|
+
};
|
|
237
|
+
/** Maximum magnitude of the learning/consult bias (ladder steps). */
|
|
238
|
+
const BIAS_MAX = 2;
|
|
239
|
+
/** Confidence floor at which an override hint is fused into the target. */
|
|
240
|
+
const HINT_CONFIDENCE_THRESHOLD = 0.7;
|
|
241
|
+
/**
|
|
242
|
+
* Resolve a ThinkingLevel for a task class (Goal 004 resolver).
|
|
243
|
+
*
|
|
244
|
+
* Pipeline: base rule table -> lane step -> bounded bias [-2,+2] -> optional hint
|
|
245
|
+
* fusion (±2 bounded) -> clamp to availableLevels (v1 algorithm).
|
|
246
|
+
*
|
|
247
|
+
* The clamp guarantees model-capability safety: the return value is always a
|
|
248
|
+
* member of availableLevels and never "off" for reasoning models. With
|
|
249
|
+
* bias=0 and hint=null, output is identical to v1 resolveThinkingLevel.
|
|
250
|
+
*/
|
|
251
|
+
export function resolveThinkingLevelV2(taskClass, availableLevels, laneType, bias, hint) {
|
|
252
|
+
const baseIndex = REASONING_LADDER_V2.indexOf(TASK_CLASS_THINKING_LEVELS_V2[taskClass]);
|
|
253
|
+
const laneStep = laneType ? (LANE_STEP_V2[laneType] ?? 0) : 0;
|
|
254
|
+
const biasClamped = Math.max(-BIAS_MAX, Math.min(BIAS_MAX, bias));
|
|
255
|
+
const ladderTop = REASONING_LADDER_V2.length - 1;
|
|
256
|
+
let targetIndex = Math.max(0, Math.min(baseIndex + laneStep + biasClamped, ladderTop));
|
|
257
|
+
// Hint fusion (Phase A: hint is null). A valid high-confidence hint moves the
|
|
258
|
+
// target toward hint.level by at most ±2 ladder steps (bounded blast radius).
|
|
259
|
+
if (hint !== null && hint.confidence >= HINT_CONFIDENCE_THRESHOLD) {
|
|
260
|
+
const hintIndex = REASONING_LADDER_V2.indexOf(hint.level);
|
|
261
|
+
if (hintIndex >= 0) {
|
|
262
|
+
const delta = hintIndex - targetIndex;
|
|
263
|
+
const step = Math.max(-BIAS_MAX, Math.min(BIAS_MAX, delta));
|
|
264
|
+
targetIndex = Math.max(0, Math.min(targetIndex + step, ladderTop));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Clamp to capability: highest available level <= target, else lowest available.
|
|
268
|
+
const availableOnLadder = REASONING_LADDER_V2.filter((level) => availableLevels.includes(level));
|
|
269
|
+
if (availableOnLadder.length === 0) {
|
|
270
|
+
return availableLevels[0] ?? "off";
|
|
271
|
+
}
|
|
272
|
+
for (let i = targetIndex; i >= 0; i--) {
|
|
273
|
+
const candidate = REASONING_LADDER_V2[i];
|
|
274
|
+
if (availableOnLadder.includes(candidate))
|
|
275
|
+
return candidate;
|
|
276
|
+
}
|
|
277
|
+
return availableOnLadder[0];
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Thin auto-mode wrapper: resolve with bias=0 and hint=null (what the session
|
|
281
|
+
* calls in v2 auto thinking mode). Output equals v1 resolveThinkingLevel for the
|
|
282
|
+
* same (taskClass, availableLevels, laneType).
|
|
283
|
+
*/
|
|
284
|
+
export function resolveThinkingLevelV2ForAuto(taskClass, availableLevels, laneType) {
|
|
285
|
+
return resolveThinkingLevelV2(taskClass, availableLevels, laneType, 0, null);
|
|
286
|
+
}
|
|
287
|
+
export { HISTORY_CAP };
|
|
288
|
+
//# sourceMappingURL=reasoning-router-v2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning-router-v2.js","sourceRoot":"","sources":["../../src/core/reasoning-router-v2.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Reasoning-router v2 — pure weighted classifier + resolver (Goal 004, Lane I2/I3).\n *\n * Deterministic by construction: same (input, weights) -> same TaskClassV2, and\n * same (taskClass, availableLevels, laneType, bias, hint) -> same ThinkingLevel.\n * No clock, randomness, or I/O. Erasable TypeScript only (ThinkingLevel is\n * imported type-only and erased).\n *\n * ============================================================================\n * v1-COMPAT BEHAVIOR UNDER DEFAULT_WEIGHTS\n * ============================================================================\n * With DEFAULT_WEIGHTS (frozen in reasoning-router-weights.ts), classifyTaskV2\n * reproduces v1 classifyTask on the full v1 corpus (Goal 004 Req 1.4), with one\n * INTENTIONAL fix family: a lone WEAK-debug trigger (\"fix\") no longer dominates\n * a stronger class signal. Concretely, \"fix the typo\" classifies as simple-edit,\n * not debug (Goal 004 Req 1.3 — the v1 regression case). This is achieved by the\n * STRONG/WEAK keyword split below: \"fix\" lives in WEAK-debug only, and\n * DEFAULT_WEIGHTS weights only the STRONG diagonal, so a STRONG simple-edit hit\n * (\"typo\") outscores the unweighted WEAK \"fix\".\n *\n * The zero-score cascade (v1 steps 2-6) runs verbatim whenever every scoreClass\n * term is 0, preserving v1's length/lane/default behavior for signal-free turns.\n * sticky/consult/margin thresholds are 0 in DEFAULT_WEIGHTS and treated as\n * INACTIVE (<= 0), so v1-compat never enters the sticky/consult/judge paths.\n * ============================================================================\n */\n\nimport type { ThinkingLevel } from \"omk-agent-core\";\n\nimport {\n\ttype ReasoningLaneTypeV2,\n\ttype RouterFeatures,\n\ttype RouterWeights,\n\tscoreClass,\n\tTASK_CLASSES_V2,\n\ttype TaskClassV2,\n} from \"./reasoning-router-weights.ts\";\n\nexport type {\n\tReasoningLaneTypeV2,\n\tRouterFeatures,\n\tRouterWeights,\n\tTaskClassV2,\n} from \"./reasoning-router-weights.ts\";\nexport { DEFAULT_WEIGHTS, scoreClass, TASK_CLASSES_V2 } from \"./reasoning-router-weights.ts\";\n\n/** Prompts shorter than this (trimmed) classify as trivial via the zero-score cascade. */\nconst TRIVIAL_MAX_CHARS = 40;\n/** Prompts at/above this length with no signal are treated as long prose briefs (plan). */\nconst COMPLEX_PROSE_MIN_CHARS = 2400;\n/** Ring-buffer cap for multi-turn history (caller-owned). */\nconst HISTORY_CAP = 8;\n\n/**\n * STRONG (class-defining) keyword families, derived from v1 KEYWORD_FAMILIES\n * (reasoning-router.ts). Each pattern is the v1 alternation MINUS the ambiguous\n * WEAK tokens that are split out below. Default i (no `g` flag): stateless.\n */\nconst STRONG_KEYWORDS: ReadonlyArray<{ taskClass: TaskClassV2; pattern: RegExp }> = [\n\t{\n\t\ttaskClass: \"debug\",\n\t\tpattern:\n\t\t\t/\\b(debug(ging)?|bugs?|errors?|exceptions?|crash(es|ing|ed)?|stack\\s*trace|traceback|regressions?|broken|fail(s|ing|ed|ure|ures)?|flaky|reproduce)\\b/i,\n\t},\n\t{\n\t\ttaskClass: \"refactor\",\n\t\tpattern:\n\t\t\t/\\b(refactor(ing|ed)?|restructur(e|ing)|renam(e|ing)|extract(ing)?|clean\\s*up|cleanup|deduplicat(e|ing)|reorganiz(e|ing)|modulariz(e|ing))\\b/i,\n\t},\n\t{\n\t\ttaskClass: \"review\",\n\t\tpattern: /\\b(review(s|ing|ed)?|audit(s|ing|ed)?|critique|inspect(ing)?)\\b/i,\n\t},\n\t{\n\t\ttaskClass: \"plan\",\n\t\tpattern:\n\t\t\t/\\b(plan(s|ning)?|design(s|ing)?|architect(s|ure|ing)?|roadmap|spec(s|ification|ifications)?|strateg(y|ies|ize)|decompos(e|ing|ition)|milestones?)\\b/i,\n\t},\n\t{\n\t\ttaskClass: \"simple-edit\",\n\t\tpattern:\n\t\t\t/\\b(typos?|tweak(s|ing|ed)?|one-?liner?|single\\s+line|bump(s|ing|ed)?|whitespace|reword(s|ing|ed)?|indentation|punctuation)\\b/i,\n\t},\n\t{\n\t\ttaskClass: \"code-gen\",\n\t\tpattern:\n\t\t\t/\\b(implement(s|ing|ation)?|writ(e|ing)|creat(e|es|ing)|build(s|ing)?|generat(e|es|ing)|scaffold(ing)?|prototype)\\b/i,\n\t},\n];\n\n/**\n * WEAK (ambiguous) keyword sub-patterns split out of the v1 alternations. Under\n * DEFAULT_WEIGHTS these are INERT (the weight matrix has no WEAK coefficients),\n * so they do not affect v1-compat; they exist for calibrated weight presets.\n * The critical entry is debug \"fix\": a lone \"fix\" without a STRONG debug\n * co-trigger no longer wins debug over a stronger sibling-class signal.\n */\nconst WEAK_KEYWORDS: ReadonlyArray<{ taskClass: TaskClassV2; pattern: RegExp }> = [\n\t{ taskClass: \"debug\", pattern: /\\bfix(es|ing|ed)?\\b/i },\n\t{ taskClass: \"code-gen\", pattern: /\\badd(s|ing|ed)?\\b/i },\n\t{ taskClass: \"refactor\", pattern: /\\b(simplif(y|ying|ied)|rewrit(e|ing))\\b/i },\n\t{ taskClass: \"review\", pattern: /\\b(assess(ing|ment)?|lgtm|approve)\\b/i },\n\t{ taskClass: \"plan\", pattern: /\\bbreak\\s+(this\\s+|it\\s+)?down\\b/i },\n];\n\n/** Lane fallback when no keyword/code/diff/length signal decides (mirrors v1). */\nconst LANE_FALLBACK_CLASS_V2: Record<ReasoningLaneTypeV2, TaskClassV2> = {\n\tplanner: \"plan\",\n\tsecurity: \"review\",\n\texplorer: \"review\",\n\tcoder: \"code-gen\",\n\treviewer: \"review\",\n\ttester: \"code-gen\",\n};\n\n/**\n * Tie-break / iteration order: v1 precedence (highest first). When two classes\n * tie on score, the one appearing earlier here wins, matching v1's first-match\n * semantics. trivial is last (it carries no keyword weight under any preset).\n */\nconst PRECEDENCE_ORDER: readonly TaskClassV2[] = [\n\t\"debug\",\n\t\"refactor\",\n\t\"review\",\n\t\"plan\",\n\t\"simple-edit\",\n\t\"code-gen\",\n\t\"trivial\",\n];\n\nfunction hasCodeFence(text: string): boolean {\n\treturn text.includes(\"```\");\n}\n\n/**\n * Diff detection, identical to v1: explicit hunk headers or `diff --git` count\n * alone; bare +/- line starts only count when BOTH added and removed are present\n * (avoids false positives on markdown bullets).\n */\nfunction hasDiffMarkers(text: string): boolean {\n\tif (/^@@[^\\n]*@@/m.test(text) || /^diff --git /m.test(text)) return true;\n\treturn /^\\+(?!\\+)/m.test(text) && /^-(?!-)/m.test(text);\n}\n\nfunction clampLenBucket(len: number): number {\n\t// floor(log2(len+1)) clamped to [0,7]; integer comparison ladder, no float log.\n\tlet bucket = 0;\n\tlet v = len + 1;\n\twhile (v > 1 && bucket < 7) {\n\t\tv >>= 1;\n\t\tbucket++;\n\t}\n\treturn bucket;\n}\n\n/**\n * Caller-supplied turn input.\n *\n * - prompt: raw turn text (trimmed by the classifier).\n * - laneType: subagent lane, if any (drives lane fallback + resolver step).\n * - history: N=8 ring buffer of prior task classes, NEWEST FIRST (multi-turn).\n * - pressureBucket: context-pressure band 0..3 (see RouterFeatures).\n * - judgeVote: optional tier-2 LLM-judge label (default OFF; injected as data).\n */\nexport interface TaskClassifierInputV2 {\n\tprompt: string;\n\tlaneType?: ReasoningLaneTypeV2;\n\thistory?: readonly TaskClassV2[];\n\tpressureBucket?: number;\n\tjudgeVote?: TaskClassV2 | null;\n}\n\n/**\n * Deterministic weighted multi-signal classifier (Goal 004 Req 1).\n *\n * Pipeline:\n * 1. Extract RouterFeatures from input (STRONG/WEAK keyword 0/1 counts per\n * family, codeFence, diffHunk, lenBucket, multiTurnPrior, pressureBucket,\n * judgeVote).\n * 2. Score every class via the frozen scoreClass(c, f, weights). top1 = argmax\n * with v1-precedence tie-break; margin = top1 - top2.\n * 3. ZERO-SCORE CASCADE (v1-compat): when maxScore === 0, fall through exactly\n * like v1 steps 2-6 (fence/diff -> code-gen; len<40 -> trivial; len>=2400\n * -> plan; lane fallback; default code-gen).\n * 4. HYSTERESIS: only when weights.stickyThreshold > 0 (INACTIVE for\n * DEFAULT_WEIGHTS). If margin < stickyThreshold and history is non-empty,\n * keep the previous class unless a STRONG keyword matched for top1.\n *\n * Pure: same (input, weights) -> same TaskClassV2.\n */\nexport function classifyTaskV2(input: TaskClassifierInputV2, weights: RouterWeights): TaskClassV2 {\n\tconst prompt = input.prompt.trim();\n\n\tconst strongKeyword: Partial<Record<TaskClassV2, number>> = {};\n\tconst weakKeyword: Partial<Record<TaskClassV2, number>> = {};\n\tfor (const { taskClass, pattern } of STRONG_KEYWORDS) {\n\t\tstrongKeyword[taskClass] = pattern.test(prompt) ? 1 : 0;\n\t}\n\tfor (const { taskClass, pattern } of WEAK_KEYWORDS) {\n\t\tweakKeyword[taskClass] = (weakKeyword[taskClass] ?? 0) + (pattern.test(prompt) ? 1 : 0);\n\t}\n\n\tconst codeFence = hasCodeFence(prompt);\n\tconst diffHunk = hasDiffMarkers(prompt);\n\tconst lenBucket = clampLenBucket(prompt.length);\n\tconst history = input.history;\n\tconst multiTurnPrior: TaskClassV2 | null = history !== undefined && history.length > 0 ? history[0] : null;\n\tconst pressureBucket = input.pressureBucket ?? 0;\n\tconst judgeVote = input.judgeVote ?? null;\n\n\tconst features: RouterFeatures = {\n\t\tstrongKeyword,\n\t\tweakKeyword,\n\t\tcodeFence,\n\t\tdiffHunk,\n\t\tlenBucket,\n\t\tmultiTurnPrior,\n\t\tpressureBucket,\n\t\tjudgeVote,\n\t};\n\n\t// Score every class; track top1 (v1-precedence tie-break) and the runner-up.\n\tconst scores = new Map<TaskClassV2, number>();\n\tfor (const c of TASK_CLASSES_V2) {\n\t\tscores.set(c, scoreClass(c, features, weights));\n\t}\n\tlet top1: TaskClassV2 = PRECEDENCE_ORDER[0];\n\tfor (const c of PRECEDENCE_ORDER) {\n\t\tif ((scores.get(c) ?? 0) > (scores.get(top1) ?? 0)) top1 = c;\n\t}\n\tlet top2: TaskClassV2 | null = null;\n\tfor (const c of PRECEDENCE_ORDER) {\n\t\tif (c === top1) continue;\n\t\tif (top2 === null || (scores.get(c) ?? 0) > (scores.get(top2) ?? 0)) top2 = c;\n\t}\n\tconst maxScore = scores.get(top1) ?? 0;\n\tconst margin = top2 !== null ? maxScore - (scores.get(top2) ?? 0) : maxScore;\n\n\t// ZERO-SCORE CASCADE: no weighted signal fired -> v1 steps 2-6 verbatim.\n\tif (maxScore <= 0) {\n\t\tif (codeFence || diffHunk) return \"code-gen\";\n\t\tif (prompt.length < TRIVIAL_MAX_CHARS) return \"trivial\";\n\t\tif (prompt.length >= COMPLEX_PROSE_MIN_CHARS) return \"plan\";\n\t\tif (input.laneType) return LANE_FALLBACK_CLASS_V2[input.laneType];\n\t\treturn \"code-gen\";\n\t}\n\n\t// HYSTERESIS: keep previous class on low-margin multi-turn turns. INACTIVE for\n\t// DEFAULT_WEIGHTS (stickyThreshold === 0). A STRONG keyword hit on top1 always\n\t// bypasses stickiness so an intentional topic switch still wins.\n\tif (\n\t\tweights.stickyThreshold > 0 &&\n\t\tmargin < weights.stickyThreshold &&\n\t\tmultiTurnPrior !== null &&\n\t\t(features.strongKeyword[top1] ?? 0) <= 0\n\t) {\n\t\treturn multiTurnPrior;\n\t}\n\n\treturn top1;\n}\n\n/** Reasoning ladder used for targets and clamping. Intentionally excludes \"off\". */\nconst REASONING_LADDER_V2: readonly ThinkingLevel[] = [\"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n\n/**\n * Static rule table: task class -> recommended ThinkingLevel (before lane\n * adjustment, bias, hint, and clamping). Identical to v1 TASK_CLASS_THINKING_LEVELS.\n */\nexport const TASK_CLASS_THINKING_LEVELS_V2: Readonly<Record<TaskClassV2, ThinkingLevel>> = {\n\ttrivial: \"minimal\",\n\t\"simple-edit\": \"low\",\n\t\"code-gen\": \"medium\",\n\tdebug: \"high\",\n\trefactor: \"high\",\n\treview: \"high\",\n\tplan: \"xhigh\",\n};\n\n/**\n * Lane ladder adjustment (mirrors DEFAULT_WEIGHTS.laneStep and v1 LANE_STEP):\n * planner/security escalate one step, explorer de-escalates one step.\n */\nconst LANE_STEP_V2: Readonly<Partial<Record<ReasoningLaneTypeV2, 1 | -1>>> = {\n\tplanner: 1,\n\tsecurity: 1,\n\texplorer: -1,\n};\n\n/** Maximum magnitude of the learning/consult bias (ladder steps). */\nconst BIAS_MAX = 2;\n/** Confidence floor at which an override hint is fused into the target. */\nconst HINT_CONFIDENCE_THRESHOLD = 0.7;\n\n/**\n * Resolve a ThinkingLevel for a task class (Goal 004 resolver).\n *\n * Pipeline: base rule table -> lane step -> bounded bias [-2,+2] -> optional hint\n * fusion (±2 bounded) -> clamp to availableLevels (v1 algorithm).\n *\n * The clamp guarantees model-capability safety: the return value is always a\n * member of availableLevels and never \"off\" for reasoning models. With\n * bias=0 and hint=null, output is identical to v1 resolveThinkingLevel.\n */\nexport function resolveThinkingLevelV2(\n\ttaskClass: TaskClassV2,\n\tavailableLevels: readonly ThinkingLevel[],\n\tlaneType: ReasoningLaneTypeV2 | undefined,\n\tbias: number,\n\thint: { level: ThinkingLevel; confidence: number } | null,\n): ThinkingLevel {\n\tconst baseIndex = REASONING_LADDER_V2.indexOf(TASK_CLASS_THINKING_LEVELS_V2[taskClass]);\n\tconst laneStep = laneType ? (LANE_STEP_V2[laneType] ?? 0) : 0;\n\tconst biasClamped = Math.max(-BIAS_MAX, Math.min(BIAS_MAX, bias));\n\tconst ladderTop = REASONING_LADDER_V2.length - 1;\n\tlet targetIndex = Math.max(0, Math.min(baseIndex + laneStep + biasClamped, ladderTop));\n\n\t// Hint fusion (Phase A: hint is null). A valid high-confidence hint moves the\n\t// target toward hint.level by at most ±2 ladder steps (bounded blast radius).\n\tif (hint !== null && hint.confidence >= HINT_CONFIDENCE_THRESHOLD) {\n\t\tconst hintIndex = REASONING_LADDER_V2.indexOf(hint.level);\n\t\tif (hintIndex >= 0) {\n\t\t\tconst delta = hintIndex - targetIndex;\n\t\t\tconst step = Math.max(-BIAS_MAX, Math.min(BIAS_MAX, delta));\n\t\t\ttargetIndex = Math.max(0, Math.min(targetIndex + step, ladderTop));\n\t\t}\n\t}\n\n\t// Clamp to capability: highest available level <= target, else lowest available.\n\tconst availableOnLadder = REASONING_LADDER_V2.filter((level) => availableLevels.includes(level));\n\tif (availableOnLadder.length === 0) {\n\t\treturn availableLevels[0] ?? \"off\";\n\t}\n\tfor (let i = targetIndex; i >= 0; i--) {\n\t\tconst candidate = REASONING_LADDER_V2[i];\n\t\tif (availableOnLadder.includes(candidate)) return candidate;\n\t}\n\treturn availableOnLadder[0];\n}\n\n/**\n * Thin auto-mode wrapper: resolve with bias=0 and hint=null (what the session\n * calls in v2 auto thinking mode). Output equals v1 resolveThinkingLevel for the\n * same (taskClass, availableLevels, laneType).\n */\nexport function resolveThinkingLevelV2ForAuto(\n\ttaskClass: TaskClassV2,\n\tavailableLevels: readonly ThinkingLevel[],\n\tlaneType: ReasoningLaneTypeV2 | undefined,\n): ThinkingLevel {\n\treturn resolveThinkingLevelV2(taskClass, availableLevels, laneType, 0, null);\n}\n\nexport { HISTORY_CAP };\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ThinkingLevel } from "omk-agent-core";
|
|
2
|
+
import type { ReasoningLaneTypeV2, TaskClassV2 } from "./reasoning-router-v2.ts";
|
|
3
|
+
export type TaskClassV3 = TaskClassV2;
|
|
4
|
+
export type ReasoningLaneTypeV3 = ReasoningLaneTypeV2;
|
|
5
|
+
export interface TaskClassifierInputV3 {
|
|
6
|
+
prompt: string;
|
|
7
|
+
laneType?: ReasoningLaneTypeV3;
|
|
8
|
+
history?: readonly TaskClassV3[];
|
|
9
|
+
pressureBucket?: number;
|
|
10
|
+
judgeVote?: TaskClassV3 | null;
|
|
11
|
+
}
|
|
12
|
+
export declare function classifyTaskV3(input: TaskClassifierInputV3): TaskClassV3;
|
|
13
|
+
export declare const TASK_CLASS_THINKING_LEVELS_V3: Readonly<Record<TaskClassV3, ThinkingLevel>>;
|
|
14
|
+
export declare function resolveThinkingLevelV3ForAuto(taskClass: TaskClassV3, availableLevels: readonly ThinkingLevel[], laneType: ReasoningLaneTypeV3 | undefined): ThinkingLevel;
|
|
15
|
+
//# sourceMappingURL=reasoning-router-v3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning-router-v3.d.ts","sourceRoot":"","sources":["../../src/core/reasoning-router-v3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGjF,MAAM,MAAM,WAAW,GAAG,WAAW,CAAC;AACtC,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEtD,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,OAAO,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CAC/B;AAyMD,wBAAgB,cAAc,CAAC,KAAK,EAAE,qBAAqB,GAAG,WAAW,CAwBxE;AAED,eAAO,MAAM,6BAA6B,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,CACzD,CAAC;AAE/B,wBAAgB,6BAA6B,CAC5C,SAAS,EAAE,WAAW,EACtB,eAAe,EAAE,SAAS,aAAa,EAAE,EACzC,QAAQ,EAAE,mBAAmB,GAAG,SAAS,GACvC,aAAa,CAEf","sourcesContent":["import type { ThinkingLevel } from \"omk-agent-core\";\nimport type { ReasoningLaneTypeV2, TaskClassV2 } from \"./reasoning-router-v2.ts\";\nimport { resolveThinkingLevelV2ForAuto, TASK_CLASS_THINKING_LEVELS_V2 } from \"./reasoning-router-v2.ts\";\n\nexport type TaskClassV3 = TaskClassV2;\nexport type ReasoningLaneTypeV3 = ReasoningLaneTypeV2;\n\nexport interface TaskClassifierInputV3 {\n\tprompt: string;\n\tlaneType?: ReasoningLaneTypeV3;\n\thistory?: readonly TaskClassV3[];\n\tpressureBucket?: number;\n\tjudgeVote?: TaskClassV3 | null;\n}\n\nconst TRIVIAL_MAX_CHARS = 40;\nconst COMPLEX_PROSE_MIN_CHARS = 2400;\nconst LONG_BRIEF_MIN_CHARS = 512;\n\nconst PRECEDENCE_ORDER_V3: readonly TaskClassV3[] = [\n\t\"debug\",\n\t\"refactor\",\n\t\"review\",\n\t\"plan\",\n\t\"simple-edit\",\n\t\"code-gen\",\n\t\"trivial\",\n];\n\nconst LANE_FALLBACK_CLASS_V3: Readonly<Record<ReasoningLaneTypeV3, TaskClassV3>> = {\n\tplanner: \"plan\",\n\tsecurity: \"review\",\n\texplorer: \"review\",\n\tcoder: \"code-gen\",\n\treviewer: \"review\",\n\ttester: \"code-gen\",\n};\n\ninterface FeaturePattern {\n\treadonly taskClass: TaskClassV3;\n\treadonly pattern: RegExp;\n\treadonly weight: number;\n}\n\ninterface ContextualFeatures {\n\treadonly firstClause: string;\n\treadonly codeFence: boolean;\n\treadonly diffHunk: boolean;\n\treadonly localEdit: boolean;\n\treadonly diagnosticEvidence: boolean;\n\treadonly reviewScope: boolean;\n\treadonly planBrief: boolean;\n\treadonly refactorCue: boolean;\n\treadonly implementationObject: boolean;\n}\n\nconst LOCAL_EDIT_OBJECT_PATTERN =\n\t/\\b(spelling|grammar|capitalization|date\\s+format|author\\s+e-?mail|copyright\\s+year|headline|title|tooltip|placeholder|punctuation|comma|period|semicolon|closing\\s+html\\s+tag|closing\\s+tag|double\\s+space|whitespace|indentation|table\\s+alignment|typos?|one-?liner?|single\\s+line|sentence|stray|trailing)\\b/i;\nconst LOCAL_EDIT_ACTION_OBJECT_PATTERN =\n\t/\\b(update|change|swap|remove|correct|fix|add|adjust|trim)\\s+(?:the\\s+|a\\s+|an\\s+)?(?:missing\\s+|stray\\s+|author\\s+|two\\s+)?(?:e-?mail|comma|period|semicolon|tag|word|words|headline|title|copyright|spelling|grammar)\\b/i;\nconst IMPLEMENTATION_OBJECT_PATTERN =\n\t/\\b(error\\s+handling|input\\s+validation|validation|auth(?:entication)?|retry|endpoint|migration|component|function|utility|helper|module|service|database|schema|column|middleware|rate\\s+limiter|cache|caching|oauth|jwt|webhook)\\b/i;\nconst HARD_DIAGNOSTIC_PATTERN =\n\t/\\b(stack\\s*trace|traceback|panic|segfault|crash(?:es|ing|ed)?|throws?|fails?|failing|flaky|hangs?|timeout|500|EADDRINUSE|silently\\s+fails?)\\b|\\b(?:TypeError|ReferenceError|RangeError|Error):/i;\nconst BUG_OBJECT_PATTERN =\n\t/\\b(null\\s+pointer|null\\s+deref|race(?:\\s+condition)?|heap(?:\\s+overflow)?|use-after-free|memory\\s+leak|deadlock|data\\s+corruption|stale\\s+data|off-by-one|encoding\\s+bug|regression\\s+(?:was\\s+)?introduced|exceptions?|assertion\\s+error|bugs?)\\b/i;\nconst NON_DIAGNOSTIC_DEBUG_CONTEXT_PATTERN = /\\berror\\s+(?:handling|messages?|budgets?)\\b/i;\nconst GENERIC_DIAGNOSTIC_PATTERN = /\\b(errors?|broken|wrong\\s+results|rolls?\\s+back|rollback)\\b/i;\nconst PLAN_BRIEF_PATTERN =\n\t/\\b(context\\s+and\\s+constraints|starting\\s+state|target\\s+state|cross-cutting|deliver:|deliverables?|roadmap|migration\\s+wave|top\\s+(?:ten\\s+)?risks|component\\s+diagram|data\\s+model|architecture|go\\/no-go|phased\\s+(?:delivery|rollout)|bounded\\s+contexts?|strangler\\s+fig|event-driven|quarter-by-quarter|milestone)\\b/i;\nconst REVIEW_SCOPE_PATTERN =\n\t/\\b(pr|pull\\s+request|diff|codebase|strategy|plan|spec|schema|design|api|coverage|security\\s+posture|licensing|risks?|edge\\s+cases|clarity|consistency|dependencies|third-party|ci\\s+pipeline|threat\\s+model|retry\\s+logic|error\\s+handling\\s+strategy|error\\s+messages?)\\b/i;\nconst REFACTOR_CUE_PATTERN =\n\t/\\b(refactor|extract|rename|deduplicate|consolidate|modularize|reorganize|simplify|clean\\s*up|restructure|split\\s+module|move\\s+logic|untangle|merge\\s+duplicate)\\b/i;\n\nconst ADD_KEYWORD_PATTERN = /\\badd\\b/i;\n\nconst KEYWORD_PATTERNS_V3: readonly FeaturePattern[] = [\n\t{\n\t\ttaskClass: \"debug\",\n\t\tpattern: /^(?:debug|investigate\\s+why|reproduce|trace\\b)|\\bfix\\s+this\\s+(?:traceback|panic|error)\\b/i,\n\t\tweight: 4,\n\t},\n\t{ taskClass: \"refactor\", pattern: REFACTOR_CUE_PATTERN, weight: 4 },\n\t{\n\t\ttaskClass: \"review\",\n\t\tpattern: /\\b(review|critique|assess|inspect|approve|lgtm|double-?check|audit(?!\\s+log\\b))\\b/i,\n\t\tweight: 4,\n\t},\n\t{\n\t\ttaskClass: \"plan\",\n\t\tpattern:\n\t\t\t/\\b(plan|design|architect|architecture|roadmap|spec(?:ification)?|strategy|decompose|milestones?|write\\s+a\\s+(?:technical\\s+)?spec|create\\s+a\\s+(?:roadmap|strategy|plan))\\b/i,\n\t\tweight: 4,\n\t},\n\t{ taskClass: \"simple-edit\", pattern: LOCAL_EDIT_OBJECT_PATTERN, weight: 4 },\n\t{ taskClass: \"code-gen\", pattern: /\\b(implement|write|create|build|generate|scaffold|prototype)\\b/i, weight: 4 },\n\t{ taskClass: \"code-gen\", pattern: ADD_KEYWORD_PATTERN, weight: 1 },\n];\n\nfunction hasCodeFence(text: string): boolean {\n\treturn text.includes(\"```\");\n}\n\nfunction hasDiffMarkers(text: string): boolean {\n\tif (/^@@[^\\n]*@@/m.test(text) || /^diff --git /m.test(text)) return true;\n\treturn /^\\+(?!\\+)/m.test(text) && /^-(?!-)/m.test(text);\n}\n\nfunction firstClause(prompt: string): string {\n\tconst firstLine =\n\t\tprompt.replace(/^(?:please|pls|can you|could you|would you|help me|i need you to)\\s+/i, \"\").split(\"\\n\")[0] ?? \"\";\n\treturn firstLine.slice(0, 180);\n}\n\nfunction hasLeadingReviewIntent(text: string): boolean {\n\treturn /^(?:review|audit(?!\\s+log\\b)|critique|inspect|assess|approve|double-?check|lgtm)\\b/i.test(text);\n}\n\nfunction hasLeadingPlanIntent(text: string): boolean {\n\treturn /^(?:plan|design|architect|decompose)\\b|^(?:write|create)\\s+(?:a\\s+)?(?:technical\\s+)?(?:spec|roadmap|strategy|plan)\\b/i.test(\n\t\ttext,\n\t);\n}\n\nfunction hasLeadingRefactorIntent(text: string): boolean {\n\treturn /^(?:refactor|extract|rename|deduplicate|consolidate|modularize|reorganize|simplify|restructure|untangle)\\b|^clean\\s+up\\b|^split\\s+(?:the\\s+)?module\\b|^move\\s+logic\\b/i.test(\n\t\ttext,\n\t);\n}\n\nfunction hasLeadingDebugAction(text: string): boolean {\n\treturn /^(?:debug|investigate\\s+why|reproduce|trace\\b)|^fix\\s+this\\s+(?:traceback|panic|error)\\b/i.test(text);\n}\n\nfunction hasLeadingCodeGenIntent(text: string): boolean {\n\treturn /^(?:implement|write|create|build|generate|scaffold|prototype|add)\\b/i.test(text);\n}\n\nfunction hasLeadingSimpleEditIntent(text: string): boolean {\n\treturn /^(?:correct|update|swap|remove|adjust|fix|add|change|trim|reword|tweak|bump)\\b/i.test(text);\n}\n\nfunction hasDiagnosticEvidence(prompt: string, leading: string): boolean {\n\tif (hasLeadingDebugAction(leading) || HARD_DIAGNOSTIC_PATTERN.test(prompt)) return true;\n\tconst hasContextualDiagnostic =\n\t\tBUG_OBJECT_PATTERN.test(prompt) ||\n\t\t(GENERIC_DIAGNOSTIC_PATTERN.test(prompt) && !NON_DIAGNOSTIC_DEBUG_CONTEXT_PATTERN.test(prompt));\n\tif (!hasContextualDiagnostic) return false;\n\treturn !hasLeadingReviewIntent(leading) && !hasLeadingPlanIntent(leading) && !hasLeadingRefactorIntent(leading);\n}\n\nfunction extractFeatures(prompt: string): ContextualFeatures {\n\tconst leading = firstClause(prompt);\n\tconst implementationObject = IMPLEMENTATION_OBJECT_PATTERN.test(prompt);\n\tconst lowRiskEditAction = /^(?:correct|update|swap|remove|reword|tweak|bump|trim)\\b/i.test(leading);\n\treturn {\n\t\tfirstClause: leading,\n\t\tcodeFence: hasCodeFence(prompt),\n\t\tdiffHunk: hasDiffMarkers(prompt),\n\t\tlocalEdit:\n\t\t\t!implementationObject &&\n\t\t\t(lowRiskEditAction || LOCAL_EDIT_OBJECT_PATTERN.test(prompt) || LOCAL_EDIT_ACTION_OBJECT_PATTERN.test(prompt)),\n\t\tdiagnosticEvidence: hasDiagnosticEvidence(prompt, leading),\n\t\treviewScope: hasLeadingReviewIntent(leading) && REVIEW_SCOPE_PATTERN.test(prompt),\n\t\tplanBrief:\n\t\t\thasLeadingPlanIntent(leading) && (PLAN_BRIEF_PATTERN.test(prompt) || prompt.length >= LONG_BRIEF_MIN_CHARS),\n\t\trefactorCue: REFACTOR_CUE_PATTERN.test(prompt),\n\t\timplementationObject,\n\t};\n}\n\nfunction leadingIntent(features: ContextualFeatures): TaskClassV3 | null {\n\tif (\n\t\tfeatures.diagnosticEvidence &&\n\t\t(hasLeadingDebugAction(features.firstClause) || hasLeadingSimpleEditIntent(features.firstClause))\n\t)\n\t\treturn \"debug\";\n\tif (hasLeadingReviewIntent(features.firstClause)) return \"review\";\n\tif (hasLeadingPlanIntent(features.firstClause)) return \"plan\";\n\tif (hasLeadingRefactorIntent(features.firstClause)) return \"refactor\";\n\tif (features.localEdit && hasLeadingSimpleEditIntent(features.firstClause)) return \"simple-edit\";\n\tif (!features.localEdit && hasLeadingCodeGenIntent(features.firstClause)) return \"code-gen\";\n\treturn null;\n}\n\nfunction emptyScores(): Record<TaskClassV3, number> {\n\treturn {\n\t\ttrivial: 0,\n\t\t\"simple-edit\": 0,\n\t\t\"code-gen\": 0,\n\t\tdebug: 0,\n\t\trefactor: 0,\n\t\treview: 0,\n\t\tplan: 0,\n\t};\n}\n\nfunction applyKeywordScores(scores: Record<TaskClassV3, number>, prompt: string, features: ContextualFeatures): void {\n\tfor (const { taskClass, pattern, weight } of KEYWORD_PATTERNS_V3) {\n\t\tif (taskClass === \"debug\" && !features.diagnosticEvidence) continue;\n\t\tif (pattern === ADD_KEYWORD_PATTERN && features.localEdit) continue;\n\t\tif (pattern.test(prompt)) scores[taskClass] += weight;\n\t}\n}\n\nfunction chooseTop(scores: Record<TaskClassV3, number>): TaskClassV3 {\n\tlet top: TaskClassV3 = \"debug\";\n\tfor (const taskClass of PRECEDENCE_ORDER_V3) {\n\t\tif (scores[taskClass] > scores[top]) top = taskClass;\n\t}\n\treturn top;\n}\n\nexport function classifyTaskV3(input: TaskClassifierInputV3): TaskClassV3 {\n\tconst prompt = input.prompt.trim();\n\tconst features = extractFeatures(prompt);\n\tconst scores = emptyScores();\n\n\tif (features.codeFence || features.diffHunk) scores[\"code-gen\"] += 4;\n\tconst intent = leadingIntent(features);\n\tif (intent !== null) scores[intent] += 8;\n\tif (features.localEdit) scores[\"simple-edit\"] += 7;\n\tif (features.diagnosticEvidence) scores.debug += 7;\n\tif (features.reviewScope) scores.review += 3;\n\tif (features.planBrief) scores.plan += 8;\n\tif (features.refactorCue) scores.refactor += 6;\n\tif (features.implementationObject) scores[\"code-gen\"] += 3;\n\tapplyKeywordScores(scores, prompt, features);\n\n\tconst top = chooseTop(scores);\n\tif (scores[top] <= 0) {\n\t\tif (prompt.length < TRIVIAL_MAX_CHARS) return \"trivial\";\n\t\tif (prompt.length >= COMPLEX_PROSE_MIN_CHARS) return \"plan\";\n\t\tif (input.laneType) return LANE_FALLBACK_CLASS_V3[input.laneType];\n\t\treturn \"code-gen\";\n\t}\n\treturn top;\n}\n\nexport const TASK_CLASS_THINKING_LEVELS_V3: Readonly<Record<TaskClassV3, ThinkingLevel>> =\n\tTASK_CLASS_THINKING_LEVELS_V2;\n\nexport function resolveThinkingLevelV3ForAuto(\n\ttaskClass: TaskClassV3,\n\tavailableLevels: readonly ThinkingLevel[],\n\tlaneType: ReasoningLaneTypeV3 | undefined,\n): ThinkingLevel {\n\treturn resolveThinkingLevelV2ForAuto(taskClass, availableLevels, laneType);\n}\n"]}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { resolveThinkingLevelV2ForAuto, TASK_CLASS_THINKING_LEVELS_V2 } from "./reasoning-router-v2.js";
|
|
2
|
+
const TRIVIAL_MAX_CHARS = 40;
|
|
3
|
+
const COMPLEX_PROSE_MIN_CHARS = 2400;
|
|
4
|
+
const LONG_BRIEF_MIN_CHARS = 512;
|
|
5
|
+
const PRECEDENCE_ORDER_V3 = [
|
|
6
|
+
"debug",
|
|
7
|
+
"refactor",
|
|
8
|
+
"review",
|
|
9
|
+
"plan",
|
|
10
|
+
"simple-edit",
|
|
11
|
+
"code-gen",
|
|
12
|
+
"trivial",
|
|
13
|
+
];
|
|
14
|
+
const LANE_FALLBACK_CLASS_V3 = {
|
|
15
|
+
planner: "plan",
|
|
16
|
+
security: "review",
|
|
17
|
+
explorer: "review",
|
|
18
|
+
coder: "code-gen",
|
|
19
|
+
reviewer: "review",
|
|
20
|
+
tester: "code-gen",
|
|
21
|
+
};
|
|
22
|
+
const LOCAL_EDIT_OBJECT_PATTERN = /\b(spelling|grammar|capitalization|date\s+format|author\s+e-?mail|copyright\s+year|headline|title|tooltip|placeholder|punctuation|comma|period|semicolon|closing\s+html\s+tag|closing\s+tag|double\s+space|whitespace|indentation|table\s+alignment|typos?|one-?liner?|single\s+line|sentence|stray|trailing)\b/i;
|
|
23
|
+
const LOCAL_EDIT_ACTION_OBJECT_PATTERN = /\b(update|change|swap|remove|correct|fix|add|adjust|trim)\s+(?:the\s+|a\s+|an\s+)?(?:missing\s+|stray\s+|author\s+|two\s+)?(?:e-?mail|comma|period|semicolon|tag|word|words|headline|title|copyright|spelling|grammar)\b/i;
|
|
24
|
+
const IMPLEMENTATION_OBJECT_PATTERN = /\b(error\s+handling|input\s+validation|validation|auth(?:entication)?|retry|endpoint|migration|component|function|utility|helper|module|service|database|schema|column|middleware|rate\s+limiter|cache|caching|oauth|jwt|webhook)\b/i;
|
|
25
|
+
const HARD_DIAGNOSTIC_PATTERN = /\b(stack\s*trace|traceback|panic|segfault|crash(?:es|ing|ed)?|throws?|fails?|failing|flaky|hangs?|timeout|500|EADDRINUSE|silently\s+fails?)\b|\b(?:TypeError|ReferenceError|RangeError|Error):/i;
|
|
26
|
+
const BUG_OBJECT_PATTERN = /\b(null\s+pointer|null\s+deref|race(?:\s+condition)?|heap(?:\s+overflow)?|use-after-free|memory\s+leak|deadlock|data\s+corruption|stale\s+data|off-by-one|encoding\s+bug|regression\s+(?:was\s+)?introduced|exceptions?|assertion\s+error|bugs?)\b/i;
|
|
27
|
+
const NON_DIAGNOSTIC_DEBUG_CONTEXT_PATTERN = /\berror\s+(?:handling|messages?|budgets?)\b/i;
|
|
28
|
+
const GENERIC_DIAGNOSTIC_PATTERN = /\b(errors?|broken|wrong\s+results|rolls?\s+back|rollback)\b/i;
|
|
29
|
+
const PLAN_BRIEF_PATTERN = /\b(context\s+and\s+constraints|starting\s+state|target\s+state|cross-cutting|deliver:|deliverables?|roadmap|migration\s+wave|top\s+(?:ten\s+)?risks|component\s+diagram|data\s+model|architecture|go\/no-go|phased\s+(?:delivery|rollout)|bounded\s+contexts?|strangler\s+fig|event-driven|quarter-by-quarter|milestone)\b/i;
|
|
30
|
+
const REVIEW_SCOPE_PATTERN = /\b(pr|pull\s+request|diff|codebase|strategy|plan|spec|schema|design|api|coverage|security\s+posture|licensing|risks?|edge\s+cases|clarity|consistency|dependencies|third-party|ci\s+pipeline|threat\s+model|retry\s+logic|error\s+handling\s+strategy|error\s+messages?)\b/i;
|
|
31
|
+
const REFACTOR_CUE_PATTERN = /\b(refactor|extract|rename|deduplicate|consolidate|modularize|reorganize|simplify|clean\s*up|restructure|split\s+module|move\s+logic|untangle|merge\s+duplicate)\b/i;
|
|
32
|
+
const ADD_KEYWORD_PATTERN = /\badd\b/i;
|
|
33
|
+
const KEYWORD_PATTERNS_V3 = [
|
|
34
|
+
{
|
|
35
|
+
taskClass: "debug",
|
|
36
|
+
pattern: /^(?:debug|investigate\s+why|reproduce|trace\b)|\bfix\s+this\s+(?:traceback|panic|error)\b/i,
|
|
37
|
+
weight: 4,
|
|
38
|
+
},
|
|
39
|
+
{ taskClass: "refactor", pattern: REFACTOR_CUE_PATTERN, weight: 4 },
|
|
40
|
+
{
|
|
41
|
+
taskClass: "review",
|
|
42
|
+
pattern: /\b(review|critique|assess|inspect|approve|lgtm|double-?check|audit(?!\s+log\b))\b/i,
|
|
43
|
+
weight: 4,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
taskClass: "plan",
|
|
47
|
+
pattern: /\b(plan|design|architect|architecture|roadmap|spec(?:ification)?|strategy|decompose|milestones?|write\s+a\s+(?:technical\s+)?spec|create\s+a\s+(?:roadmap|strategy|plan))\b/i,
|
|
48
|
+
weight: 4,
|
|
49
|
+
},
|
|
50
|
+
{ taskClass: "simple-edit", pattern: LOCAL_EDIT_OBJECT_PATTERN, weight: 4 },
|
|
51
|
+
{ taskClass: "code-gen", pattern: /\b(implement|write|create|build|generate|scaffold|prototype)\b/i, weight: 4 },
|
|
52
|
+
{ taskClass: "code-gen", pattern: ADD_KEYWORD_PATTERN, weight: 1 },
|
|
53
|
+
];
|
|
54
|
+
function hasCodeFence(text) {
|
|
55
|
+
return text.includes("```");
|
|
56
|
+
}
|
|
57
|
+
function hasDiffMarkers(text) {
|
|
58
|
+
if (/^@@[^\n]*@@/m.test(text) || /^diff --git /m.test(text))
|
|
59
|
+
return true;
|
|
60
|
+
return /^\+(?!\+)/m.test(text) && /^-(?!-)/m.test(text);
|
|
61
|
+
}
|
|
62
|
+
function firstClause(prompt) {
|
|
63
|
+
const firstLine = prompt.replace(/^(?:please|pls|can you|could you|would you|help me|i need you to)\s+/i, "").split("\n")[0] ?? "";
|
|
64
|
+
return firstLine.slice(0, 180);
|
|
65
|
+
}
|
|
66
|
+
function hasLeadingReviewIntent(text) {
|
|
67
|
+
return /^(?:review|audit(?!\s+log\b)|critique|inspect|assess|approve|double-?check|lgtm)\b/i.test(text);
|
|
68
|
+
}
|
|
69
|
+
function hasLeadingPlanIntent(text) {
|
|
70
|
+
return /^(?:plan|design|architect|decompose)\b|^(?:write|create)\s+(?:a\s+)?(?:technical\s+)?(?:spec|roadmap|strategy|plan)\b/i.test(text);
|
|
71
|
+
}
|
|
72
|
+
function hasLeadingRefactorIntent(text) {
|
|
73
|
+
return /^(?:refactor|extract|rename|deduplicate|consolidate|modularize|reorganize|simplify|restructure|untangle)\b|^clean\s+up\b|^split\s+(?:the\s+)?module\b|^move\s+logic\b/i.test(text);
|
|
74
|
+
}
|
|
75
|
+
function hasLeadingDebugAction(text) {
|
|
76
|
+
return /^(?:debug|investigate\s+why|reproduce|trace\b)|^fix\s+this\s+(?:traceback|panic|error)\b/i.test(text);
|
|
77
|
+
}
|
|
78
|
+
function hasLeadingCodeGenIntent(text) {
|
|
79
|
+
return /^(?:implement|write|create|build|generate|scaffold|prototype|add)\b/i.test(text);
|
|
80
|
+
}
|
|
81
|
+
function hasLeadingSimpleEditIntent(text) {
|
|
82
|
+
return /^(?:correct|update|swap|remove|adjust|fix|add|change|trim|reword|tweak|bump)\b/i.test(text);
|
|
83
|
+
}
|
|
84
|
+
function hasDiagnosticEvidence(prompt, leading) {
|
|
85
|
+
if (hasLeadingDebugAction(leading) || HARD_DIAGNOSTIC_PATTERN.test(prompt))
|
|
86
|
+
return true;
|
|
87
|
+
const hasContextualDiagnostic = BUG_OBJECT_PATTERN.test(prompt) ||
|
|
88
|
+
(GENERIC_DIAGNOSTIC_PATTERN.test(prompt) && !NON_DIAGNOSTIC_DEBUG_CONTEXT_PATTERN.test(prompt));
|
|
89
|
+
if (!hasContextualDiagnostic)
|
|
90
|
+
return false;
|
|
91
|
+
return !hasLeadingReviewIntent(leading) && !hasLeadingPlanIntent(leading) && !hasLeadingRefactorIntent(leading);
|
|
92
|
+
}
|
|
93
|
+
function extractFeatures(prompt) {
|
|
94
|
+
const leading = firstClause(prompt);
|
|
95
|
+
const implementationObject = IMPLEMENTATION_OBJECT_PATTERN.test(prompt);
|
|
96
|
+
const lowRiskEditAction = /^(?:correct|update|swap|remove|reword|tweak|bump|trim)\b/i.test(leading);
|
|
97
|
+
return {
|
|
98
|
+
firstClause: leading,
|
|
99
|
+
codeFence: hasCodeFence(prompt),
|
|
100
|
+
diffHunk: hasDiffMarkers(prompt),
|
|
101
|
+
localEdit: !implementationObject &&
|
|
102
|
+
(lowRiskEditAction || LOCAL_EDIT_OBJECT_PATTERN.test(prompt) || LOCAL_EDIT_ACTION_OBJECT_PATTERN.test(prompt)),
|
|
103
|
+
diagnosticEvidence: hasDiagnosticEvidence(prompt, leading),
|
|
104
|
+
reviewScope: hasLeadingReviewIntent(leading) && REVIEW_SCOPE_PATTERN.test(prompt),
|
|
105
|
+
planBrief: hasLeadingPlanIntent(leading) && (PLAN_BRIEF_PATTERN.test(prompt) || prompt.length >= LONG_BRIEF_MIN_CHARS),
|
|
106
|
+
refactorCue: REFACTOR_CUE_PATTERN.test(prompt),
|
|
107
|
+
implementationObject,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function leadingIntent(features) {
|
|
111
|
+
if (features.diagnosticEvidence &&
|
|
112
|
+
(hasLeadingDebugAction(features.firstClause) || hasLeadingSimpleEditIntent(features.firstClause)))
|
|
113
|
+
return "debug";
|
|
114
|
+
if (hasLeadingReviewIntent(features.firstClause))
|
|
115
|
+
return "review";
|
|
116
|
+
if (hasLeadingPlanIntent(features.firstClause))
|
|
117
|
+
return "plan";
|
|
118
|
+
if (hasLeadingRefactorIntent(features.firstClause))
|
|
119
|
+
return "refactor";
|
|
120
|
+
if (features.localEdit && hasLeadingSimpleEditIntent(features.firstClause))
|
|
121
|
+
return "simple-edit";
|
|
122
|
+
if (!features.localEdit && hasLeadingCodeGenIntent(features.firstClause))
|
|
123
|
+
return "code-gen";
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
function emptyScores() {
|
|
127
|
+
return {
|
|
128
|
+
trivial: 0,
|
|
129
|
+
"simple-edit": 0,
|
|
130
|
+
"code-gen": 0,
|
|
131
|
+
debug: 0,
|
|
132
|
+
refactor: 0,
|
|
133
|
+
review: 0,
|
|
134
|
+
plan: 0,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function applyKeywordScores(scores, prompt, features) {
|
|
138
|
+
for (const { taskClass, pattern, weight } of KEYWORD_PATTERNS_V3) {
|
|
139
|
+
if (taskClass === "debug" && !features.diagnosticEvidence)
|
|
140
|
+
continue;
|
|
141
|
+
if (pattern === ADD_KEYWORD_PATTERN && features.localEdit)
|
|
142
|
+
continue;
|
|
143
|
+
if (pattern.test(prompt))
|
|
144
|
+
scores[taskClass] += weight;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function chooseTop(scores) {
|
|
148
|
+
let top = "debug";
|
|
149
|
+
for (const taskClass of PRECEDENCE_ORDER_V3) {
|
|
150
|
+
if (scores[taskClass] > scores[top])
|
|
151
|
+
top = taskClass;
|
|
152
|
+
}
|
|
153
|
+
return top;
|
|
154
|
+
}
|
|
155
|
+
export function classifyTaskV3(input) {
|
|
156
|
+
const prompt = input.prompt.trim();
|
|
157
|
+
const features = extractFeatures(prompt);
|
|
158
|
+
const scores = emptyScores();
|
|
159
|
+
if (features.codeFence || features.diffHunk)
|
|
160
|
+
scores["code-gen"] += 4;
|
|
161
|
+
const intent = leadingIntent(features);
|
|
162
|
+
if (intent !== null)
|
|
163
|
+
scores[intent] += 8;
|
|
164
|
+
if (features.localEdit)
|
|
165
|
+
scores["simple-edit"] += 7;
|
|
166
|
+
if (features.diagnosticEvidence)
|
|
167
|
+
scores.debug += 7;
|
|
168
|
+
if (features.reviewScope)
|
|
169
|
+
scores.review += 3;
|
|
170
|
+
if (features.planBrief)
|
|
171
|
+
scores.plan += 8;
|
|
172
|
+
if (features.refactorCue)
|
|
173
|
+
scores.refactor += 6;
|
|
174
|
+
if (features.implementationObject)
|
|
175
|
+
scores["code-gen"] += 3;
|
|
176
|
+
applyKeywordScores(scores, prompt, features);
|
|
177
|
+
const top = chooseTop(scores);
|
|
178
|
+
if (scores[top] <= 0) {
|
|
179
|
+
if (prompt.length < TRIVIAL_MAX_CHARS)
|
|
180
|
+
return "trivial";
|
|
181
|
+
if (prompt.length >= COMPLEX_PROSE_MIN_CHARS)
|
|
182
|
+
return "plan";
|
|
183
|
+
if (input.laneType)
|
|
184
|
+
return LANE_FALLBACK_CLASS_V3[input.laneType];
|
|
185
|
+
return "code-gen";
|
|
186
|
+
}
|
|
187
|
+
return top;
|
|
188
|
+
}
|
|
189
|
+
export const TASK_CLASS_THINKING_LEVELS_V3 = TASK_CLASS_THINKING_LEVELS_V2;
|
|
190
|
+
export function resolveThinkingLevelV3ForAuto(taskClass, availableLevels, laneType) {
|
|
191
|
+
return resolveThinkingLevelV2ForAuto(taskClass, availableLevels, laneType);
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=reasoning-router-v3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning-router-v3.js","sourceRoot":"","sources":["../../src/core/reasoning-router-v3.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"omk-agent-core\";\nimport type { ReasoningLaneTypeV2, TaskClassV2 } from \"./reasoning-router-v2.ts\";\nimport { resolveThinkingLevelV2ForAuto, TASK_CLASS_THINKING_LEVELS_V2 } from \"./reasoning-router-v2.ts\";\n\nexport type TaskClassV3 = TaskClassV2;\nexport type ReasoningLaneTypeV3 = ReasoningLaneTypeV2;\n\nexport interface TaskClassifierInputV3 {\n\tprompt: string;\n\tlaneType?: ReasoningLaneTypeV3;\n\thistory?: readonly TaskClassV3[];\n\tpressureBucket?: number;\n\tjudgeVote?: TaskClassV3 | null;\n}\n\nconst TRIVIAL_MAX_CHARS = 40;\nconst COMPLEX_PROSE_MIN_CHARS = 2400;\nconst LONG_BRIEF_MIN_CHARS = 512;\n\nconst PRECEDENCE_ORDER_V3: readonly TaskClassV3[] = [\n\t\"debug\",\n\t\"refactor\",\n\t\"review\",\n\t\"plan\",\n\t\"simple-edit\",\n\t\"code-gen\",\n\t\"trivial\",\n];\n\nconst LANE_FALLBACK_CLASS_V3: Readonly<Record<ReasoningLaneTypeV3, TaskClassV3>> = {\n\tplanner: \"plan\",\n\tsecurity: \"review\",\n\texplorer: \"review\",\n\tcoder: \"code-gen\",\n\treviewer: \"review\",\n\ttester: \"code-gen\",\n};\n\ninterface FeaturePattern {\n\treadonly taskClass: TaskClassV3;\n\treadonly pattern: RegExp;\n\treadonly weight: number;\n}\n\ninterface ContextualFeatures {\n\treadonly firstClause: string;\n\treadonly codeFence: boolean;\n\treadonly diffHunk: boolean;\n\treadonly localEdit: boolean;\n\treadonly diagnosticEvidence: boolean;\n\treadonly reviewScope: boolean;\n\treadonly planBrief: boolean;\n\treadonly refactorCue: boolean;\n\treadonly implementationObject: boolean;\n}\n\nconst LOCAL_EDIT_OBJECT_PATTERN =\n\t/\\b(spelling|grammar|capitalization|date\\s+format|author\\s+e-?mail|copyright\\s+year|headline|title|tooltip|placeholder|punctuation|comma|period|semicolon|closing\\s+html\\s+tag|closing\\s+tag|double\\s+space|whitespace|indentation|table\\s+alignment|typos?|one-?liner?|single\\s+line|sentence|stray|trailing)\\b/i;\nconst LOCAL_EDIT_ACTION_OBJECT_PATTERN =\n\t/\\b(update|change|swap|remove|correct|fix|add|adjust|trim)\\s+(?:the\\s+|a\\s+|an\\s+)?(?:missing\\s+|stray\\s+|author\\s+|two\\s+)?(?:e-?mail|comma|period|semicolon|tag|word|words|headline|title|copyright|spelling|grammar)\\b/i;\nconst IMPLEMENTATION_OBJECT_PATTERN =\n\t/\\b(error\\s+handling|input\\s+validation|validation|auth(?:entication)?|retry|endpoint|migration|component|function|utility|helper|module|service|database|schema|column|middleware|rate\\s+limiter|cache|caching|oauth|jwt|webhook)\\b/i;\nconst HARD_DIAGNOSTIC_PATTERN =\n\t/\\b(stack\\s*trace|traceback|panic|segfault|crash(?:es|ing|ed)?|throws?|fails?|failing|flaky|hangs?|timeout|500|EADDRINUSE|silently\\s+fails?)\\b|\\b(?:TypeError|ReferenceError|RangeError|Error):/i;\nconst BUG_OBJECT_PATTERN =\n\t/\\b(null\\s+pointer|null\\s+deref|race(?:\\s+condition)?|heap(?:\\s+overflow)?|use-after-free|memory\\s+leak|deadlock|data\\s+corruption|stale\\s+data|off-by-one|encoding\\s+bug|regression\\s+(?:was\\s+)?introduced|exceptions?|assertion\\s+error|bugs?)\\b/i;\nconst NON_DIAGNOSTIC_DEBUG_CONTEXT_PATTERN = /\\berror\\s+(?:handling|messages?|budgets?)\\b/i;\nconst GENERIC_DIAGNOSTIC_PATTERN = /\\b(errors?|broken|wrong\\s+results|rolls?\\s+back|rollback)\\b/i;\nconst PLAN_BRIEF_PATTERN =\n\t/\\b(context\\s+and\\s+constraints|starting\\s+state|target\\s+state|cross-cutting|deliver:|deliverables?|roadmap|migration\\s+wave|top\\s+(?:ten\\s+)?risks|component\\s+diagram|data\\s+model|architecture|go\\/no-go|phased\\s+(?:delivery|rollout)|bounded\\s+contexts?|strangler\\s+fig|event-driven|quarter-by-quarter|milestone)\\b/i;\nconst REVIEW_SCOPE_PATTERN =\n\t/\\b(pr|pull\\s+request|diff|codebase|strategy|plan|spec|schema|design|api|coverage|security\\s+posture|licensing|risks?|edge\\s+cases|clarity|consistency|dependencies|third-party|ci\\s+pipeline|threat\\s+model|retry\\s+logic|error\\s+handling\\s+strategy|error\\s+messages?)\\b/i;\nconst REFACTOR_CUE_PATTERN =\n\t/\\b(refactor|extract|rename|deduplicate|consolidate|modularize|reorganize|simplify|clean\\s*up|restructure|split\\s+module|move\\s+logic|untangle|merge\\s+duplicate)\\b/i;\n\nconst ADD_KEYWORD_PATTERN = /\\badd\\b/i;\n\nconst KEYWORD_PATTERNS_V3: readonly FeaturePattern[] = [\n\t{\n\t\ttaskClass: \"debug\",\n\t\tpattern: /^(?:debug|investigate\\s+why|reproduce|trace\\b)|\\bfix\\s+this\\s+(?:traceback|panic|error)\\b/i,\n\t\tweight: 4,\n\t},\n\t{ taskClass: \"refactor\", pattern: REFACTOR_CUE_PATTERN, weight: 4 },\n\t{\n\t\ttaskClass: \"review\",\n\t\tpattern: /\\b(review|critique|assess|inspect|approve|lgtm|double-?check|audit(?!\\s+log\\b))\\b/i,\n\t\tweight: 4,\n\t},\n\t{\n\t\ttaskClass: \"plan\",\n\t\tpattern:\n\t\t\t/\\b(plan|design|architect|architecture|roadmap|spec(?:ification)?|strategy|decompose|milestones?|write\\s+a\\s+(?:technical\\s+)?spec|create\\s+a\\s+(?:roadmap|strategy|plan))\\b/i,\n\t\tweight: 4,\n\t},\n\t{ taskClass: \"simple-edit\", pattern: LOCAL_EDIT_OBJECT_PATTERN, weight: 4 },\n\t{ taskClass: \"code-gen\", pattern: /\\b(implement|write|create|build|generate|scaffold|prototype)\\b/i, weight: 4 },\n\t{ taskClass: \"code-gen\", pattern: ADD_KEYWORD_PATTERN, weight: 1 },\n];\n\nfunction hasCodeFence(text: string): boolean {\n\treturn text.includes(\"```\");\n}\n\nfunction hasDiffMarkers(text: string): boolean {\n\tif (/^@@[^\\n]*@@/m.test(text) || /^diff --git /m.test(text)) return true;\n\treturn /^\\+(?!\\+)/m.test(text) && /^-(?!-)/m.test(text);\n}\n\nfunction firstClause(prompt: string): string {\n\tconst firstLine =\n\t\tprompt.replace(/^(?:please|pls|can you|could you|would you|help me|i need you to)\\s+/i, \"\").split(\"\\n\")[0] ?? \"\";\n\treturn firstLine.slice(0, 180);\n}\n\nfunction hasLeadingReviewIntent(text: string): boolean {\n\treturn /^(?:review|audit(?!\\s+log\\b)|critique|inspect|assess|approve|double-?check|lgtm)\\b/i.test(text);\n}\n\nfunction hasLeadingPlanIntent(text: string): boolean {\n\treturn /^(?:plan|design|architect|decompose)\\b|^(?:write|create)\\s+(?:a\\s+)?(?:technical\\s+)?(?:spec|roadmap|strategy|plan)\\b/i.test(\n\t\ttext,\n\t);\n}\n\nfunction hasLeadingRefactorIntent(text: string): boolean {\n\treturn /^(?:refactor|extract|rename|deduplicate|consolidate|modularize|reorganize|simplify|restructure|untangle)\\b|^clean\\s+up\\b|^split\\s+(?:the\\s+)?module\\b|^move\\s+logic\\b/i.test(\n\t\ttext,\n\t);\n}\n\nfunction hasLeadingDebugAction(text: string): boolean {\n\treturn /^(?:debug|investigate\\s+why|reproduce|trace\\b)|^fix\\s+this\\s+(?:traceback|panic|error)\\b/i.test(text);\n}\n\nfunction hasLeadingCodeGenIntent(text: string): boolean {\n\treturn /^(?:implement|write|create|build|generate|scaffold|prototype|add)\\b/i.test(text);\n}\n\nfunction hasLeadingSimpleEditIntent(text: string): boolean {\n\treturn /^(?:correct|update|swap|remove|adjust|fix|add|change|trim|reword|tweak|bump)\\b/i.test(text);\n}\n\nfunction hasDiagnosticEvidence(prompt: string, leading: string): boolean {\n\tif (hasLeadingDebugAction(leading) || HARD_DIAGNOSTIC_PATTERN.test(prompt)) return true;\n\tconst hasContextualDiagnostic =\n\t\tBUG_OBJECT_PATTERN.test(prompt) ||\n\t\t(GENERIC_DIAGNOSTIC_PATTERN.test(prompt) && !NON_DIAGNOSTIC_DEBUG_CONTEXT_PATTERN.test(prompt));\n\tif (!hasContextualDiagnostic) return false;\n\treturn !hasLeadingReviewIntent(leading) && !hasLeadingPlanIntent(leading) && !hasLeadingRefactorIntent(leading);\n}\n\nfunction extractFeatures(prompt: string): ContextualFeatures {\n\tconst leading = firstClause(prompt);\n\tconst implementationObject = IMPLEMENTATION_OBJECT_PATTERN.test(prompt);\n\tconst lowRiskEditAction = /^(?:correct|update|swap|remove|reword|tweak|bump|trim)\\b/i.test(leading);\n\treturn {\n\t\tfirstClause: leading,\n\t\tcodeFence: hasCodeFence(prompt),\n\t\tdiffHunk: hasDiffMarkers(prompt),\n\t\tlocalEdit:\n\t\t\t!implementationObject &&\n\t\t\t(lowRiskEditAction || LOCAL_EDIT_OBJECT_PATTERN.test(prompt) || LOCAL_EDIT_ACTION_OBJECT_PATTERN.test(prompt)),\n\t\tdiagnosticEvidence: hasDiagnosticEvidence(prompt, leading),\n\t\treviewScope: hasLeadingReviewIntent(leading) && REVIEW_SCOPE_PATTERN.test(prompt),\n\t\tplanBrief:\n\t\t\thasLeadingPlanIntent(leading) && (PLAN_BRIEF_PATTERN.test(prompt) || prompt.length >= LONG_BRIEF_MIN_CHARS),\n\t\trefactorCue: REFACTOR_CUE_PATTERN.test(prompt),\n\t\timplementationObject,\n\t};\n}\n\nfunction leadingIntent(features: ContextualFeatures): TaskClassV3 | null {\n\tif (\n\t\tfeatures.diagnosticEvidence &&\n\t\t(hasLeadingDebugAction(features.firstClause) || hasLeadingSimpleEditIntent(features.firstClause))\n\t)\n\t\treturn \"debug\";\n\tif (hasLeadingReviewIntent(features.firstClause)) return \"review\";\n\tif (hasLeadingPlanIntent(features.firstClause)) return \"plan\";\n\tif (hasLeadingRefactorIntent(features.firstClause)) return \"refactor\";\n\tif (features.localEdit && hasLeadingSimpleEditIntent(features.firstClause)) return \"simple-edit\";\n\tif (!features.localEdit && hasLeadingCodeGenIntent(features.firstClause)) return \"code-gen\";\n\treturn null;\n}\n\nfunction emptyScores(): Record<TaskClassV3, number> {\n\treturn {\n\t\ttrivial: 0,\n\t\t\"simple-edit\": 0,\n\t\t\"code-gen\": 0,\n\t\tdebug: 0,\n\t\trefactor: 0,\n\t\treview: 0,\n\t\tplan: 0,\n\t};\n}\n\nfunction applyKeywordScores(scores: Record<TaskClassV3, number>, prompt: string, features: ContextualFeatures): void {\n\tfor (const { taskClass, pattern, weight } of KEYWORD_PATTERNS_V3) {\n\t\tif (taskClass === \"debug\" && !features.diagnosticEvidence) continue;\n\t\tif (pattern === ADD_KEYWORD_PATTERN && features.localEdit) continue;\n\t\tif (pattern.test(prompt)) scores[taskClass] += weight;\n\t}\n}\n\nfunction chooseTop(scores: Record<TaskClassV3, number>): TaskClassV3 {\n\tlet top: TaskClassV3 = \"debug\";\n\tfor (const taskClass of PRECEDENCE_ORDER_V3) {\n\t\tif (scores[taskClass] > scores[top]) top = taskClass;\n\t}\n\treturn top;\n}\n\nexport function classifyTaskV3(input: TaskClassifierInputV3): TaskClassV3 {\n\tconst prompt = input.prompt.trim();\n\tconst features = extractFeatures(prompt);\n\tconst scores = emptyScores();\n\n\tif (features.codeFence || features.diffHunk) scores[\"code-gen\"] += 4;\n\tconst intent = leadingIntent(features);\n\tif (intent !== null) scores[intent] += 8;\n\tif (features.localEdit) scores[\"simple-edit\"] += 7;\n\tif (features.diagnosticEvidence) scores.debug += 7;\n\tif (features.reviewScope) scores.review += 3;\n\tif (features.planBrief) scores.plan += 8;\n\tif (features.refactorCue) scores.refactor += 6;\n\tif (features.implementationObject) scores[\"code-gen\"] += 3;\n\tapplyKeywordScores(scores, prompt, features);\n\n\tconst top = chooseTop(scores);\n\tif (scores[top] <= 0) {\n\t\tif (prompt.length < TRIVIAL_MAX_CHARS) return \"trivial\";\n\t\tif (prompt.length >= COMPLEX_PROSE_MIN_CHARS) return \"plan\";\n\t\tif (input.laneType) return LANE_FALLBACK_CLASS_V3[input.laneType];\n\t\treturn \"code-gen\";\n\t}\n\treturn top;\n}\n\nexport const TASK_CLASS_THINKING_LEVELS_V3: Readonly<Record<TaskClassV3, ThinkingLevel>> =\n\tTASK_CLASS_THINKING_LEVELS_V2;\n\nexport function resolveThinkingLevelV3ForAuto(\n\ttaskClass: TaskClassV3,\n\tavailableLevels: readonly ThinkingLevel[],\n\tlaneType: ReasoningLaneTypeV3 | undefined,\n): ThinkingLevel {\n\treturn resolveThinkingLevelV2ForAuto(taskClass, availableLevels, laneType);\n}\n"]}
|