odai-dsh-agent 0.2.3 → 0.2.6
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/README.md +3 -3
- package/build/bin/odai-dsh-agent.d.mts +3 -0
- package/build/bin/odai-dsh-agent.d.mts.map +1 -0
- package/build/bin/odai-dsh-agent.mjs +114 -0
- package/build/bin/odai-dsh-agent.mjs.map +1 -0
- package/build/src/dsh-version.d.mts +16 -0
- package/build/src/dsh-version.d.mts.map +1 -0
- package/build/src/dsh-version.mjs +20 -0
- package/build/src/dsh-version.mjs.map +1 -0
- package/build/src/installer.d.mts +46 -0
- package/build/src/installer.d.mts.map +1 -0
- package/build/src/installer.mjs +397 -0
- package/build/src/installer.mjs.map +1 -0
- package/package.json +13 -12
- package/preset/odai/runtime/compaction-config.d.mts +66 -0
- package/preset/odai/runtime/compaction-config.d.mts.map +1 -0
- package/preset/odai/runtime/compaction-config.mjs +320 -342
- package/preset/odai/runtime/compaction-config.mjs.map +1 -0
- package/preset/odai/runtime/compaction-runtime.d.mts +68 -0
- package/preset/odai/runtime/compaction-runtime.d.mts.map +1 -0
- package/preset/odai/runtime/compaction-runtime.mjs +157 -0
- package/preset/odai/runtime/compaction-runtime.mjs.map +1 -0
- package/preset/odai/runtime/context-activation.d.mts +31 -0
- package/preset/odai/runtime/context-activation.d.mts.map +1 -0
- package/preset/odai/runtime/context-activation.mjs +55 -49
- package/preset/odai/runtime/context-activation.mjs.map +1 -0
- package/preset/odai/runtime/context-capability.d.mts +16 -0
- package/preset/odai/runtime/context-capability.d.mts.map +1 -0
- package/preset/odai/runtime/context-capability.mjs +79 -74
- package/preset/odai/runtime/context-capability.mjs.map +1 -0
- package/preset/odai/runtime/governance.d.mts +30 -0
- package/preset/odai/runtime/governance.d.mts.map +1 -0
- package/preset/odai/runtime/governance.mjs +126 -113
- package/preset/odai/runtime/governance.mjs.map +1 -0
- package/preset/odai/runtime/human-care.d.mts +13 -0
- package/preset/odai/runtime/human-care.d.mts.map +1 -0
- package/preset/odai/runtime/human-care.mjs +45 -42
- package/preset/odai/runtime/human-care.mjs.map +1 -0
- package/preset/odai/runtime/human-safety-continuity-store.d.mts +43 -0
- package/preset/odai/runtime/human-safety-continuity-store.d.mts.map +1 -0
- package/preset/odai/runtime/human-safety-continuity-store.mjs +193 -215
- package/preset/odai/runtime/human-safety-continuity-store.mjs.map +1 -0
- package/preset/odai/runtime/human-safety-continuity.d.mts +27 -0
- package/preset/odai/runtime/human-safety-continuity.d.mts.map +1 -0
- package/preset/odai/runtime/human-safety-continuity.mjs +205 -216
- package/preset/odai/runtime/human-safety-continuity.mjs.map +1 -0
- package/preset/odai/runtime/human-safety.d.mts +14 -0
- package/preset/odai/runtime/human-safety.d.mts.map +1 -0
- package/preset/odai/runtime/human-safety.mjs +50 -47
- package/preset/odai/runtime/human-safety.mjs.map +1 -0
- package/preset/odai/runtime/index.d.mts +8 -0
- package/preset/odai/runtime/index.d.mts.map +1 -0
- package/preset/odai/runtime/index.mjs +161 -2441
- package/preset/odai/runtime/index.mjs.map +1 -0
- package/preset/odai/runtime/lifecycle-runtime.d.mts +83 -0
- package/preset/odai/runtime/lifecycle-runtime.d.mts.map +1 -0
- package/preset/odai/runtime/lifecycle-runtime.mjs +1081 -0
- package/preset/odai/runtime/lifecycle-runtime.mjs.map +1 -0
- package/preset/odai/runtime/model-route.d.mts +22 -0
- package/preset/odai/runtime/model-route.d.mts.map +1 -0
- package/preset/odai/runtime/model-route.mjs +68 -60
- package/preset/odai/runtime/model-route.mjs.map +1 -0
- package/preset/odai/runtime/output-config.d.mts +54 -0
- package/preset/odai/runtime/output-config.d.mts.map +1 -0
- package/preset/odai/runtime/output-config.mjs +289 -315
- package/preset/odai/runtime/output-config.mjs.map +1 -0
- package/preset/odai/runtime/output-policy-state.d.mts +3 -0
- package/preset/odai/runtime/output-policy-state.d.mts.map +1 -0
- package/preset/odai/runtime/output-policy-state.mjs +41 -29
- package/preset/odai/runtime/output-policy-state.mjs.map +1 -0
- package/preset/odai/runtime/prompt-runtime.d.mts +55 -0
- package/preset/odai/runtime/prompt-runtime.d.mts.map +1 -0
- package/preset/odai/runtime/prompt-runtime.mjs +303 -0
- package/preset/odai/runtime/prompt-runtime.mjs.map +1 -0
- package/preset/odai/runtime/research-packet.d.mts +30 -0
- package/preset/odai/runtime/research-packet.d.mts.map +1 -0
- package/preset/odai/runtime/research-packet.mjs +116 -117
- package/preset/odai/runtime/research-packet.mjs.map +1 -0
- package/preset/odai/runtime/responsibility-gap.d.mts +26 -0
- package/preset/odai/runtime/responsibility-gap.d.mts.map +1 -0
- package/preset/odai/runtime/responsibility-gap.mjs +91 -85
- package/preset/odai/runtime/responsibility-gap.mjs.map +1 -0
- package/preset/odai/runtime/responsibility-scope.d.mts +69 -0
- package/preset/odai/runtime/responsibility-scope.d.mts.map +1 -0
- package/preset/odai/runtime/responsibility-scope.mjs +199 -171
- package/preset/odai/runtime/responsibility-scope.mjs.map +1 -0
- package/preset/odai/runtime/role-overlays.d.mts +5 -0
- package/preset/odai/runtime/role-overlays.d.mts.map +1 -0
- package/preset/odai/runtime/role-overlays.mjs +14 -13
- package/preset/odai/runtime/role-overlays.mjs.map +1 -0
- package/preset/odai/runtime/route-card.d.mts +42 -0
- package/preset/odai/runtime/route-card.d.mts.map +1 -0
- package/preset/odai/runtime/route-card.mjs +158 -146
- package/preset/odai/runtime/route-card.mjs.map +1 -0
- package/preset/odai/runtime/router.d.mts +79 -0
- package/preset/odai/runtime/router.d.mts.map +1 -0
- package/preset/odai/runtime/router.mjs +491 -559
- package/preset/odai/runtime/router.mjs.map +1 -0
- package/preset/odai/runtime/routing-config.d.mts +76 -0
- package/preset/odai/runtime/routing-config.d.mts.map +1 -0
- package/preset/odai/runtime/routing-config.mjs +373 -438
- package/preset/odai/runtime/routing-config.mjs.map +1 -0
- package/preset/odai/runtime/routing-context.d.mts +47 -0
- package/preset/odai/runtime/routing-context.d.mts.map +1 -0
- package/preset/odai/runtime/routing-context.mjs +238 -273
- package/preset/odai/runtime/routing-context.mjs.map +1 -0
- package/preset/odai/runtime/runtime-config.d.mts +24 -0
- package/preset/odai/runtime/runtime-config.d.mts.map +1 -0
- package/preset/odai/runtime/runtime-config.mjs +181 -0
- package/preset/odai/runtime/runtime-config.mjs.map +1 -0
- package/preset/odai/runtime/runtime-support.d.mts +91 -0
- package/preset/odai/runtime/runtime-support.d.mts.map +1 -0
- package/preset/odai/runtime/runtime-support.mjs +371 -0
- package/preset/odai/runtime/runtime-support.mjs.map +1 -0
- package/preset/odai/runtime/runtime-types.d.mts +235 -0
- package/preset/odai/runtime/runtime-types.d.mts.map +1 -0
- package/preset/odai/runtime/runtime-types.mjs +4 -0
- package/preset/odai/runtime/runtime-types.mjs.map +1 -0
- package/preset/odai/runtime/semantic-memory-store.d.mts +110 -0
- package/preset/odai/runtime/semantic-memory-store.d.mts.map +1 -0
- package/preset/odai/runtime/semantic-memory-store.mjs +271 -385
- package/preset/odai/runtime/semantic-memory-store.mjs.map +1 -0
- package/preset/odai/runtime/semantic-memory.d.mts +88 -0
- package/preset/odai/runtime/semantic-memory.d.mts.map +1 -0
- package/preset/odai/runtime/semantic-memory.mjs +790 -750
- package/preset/odai/runtime/semantic-memory.mjs.map +1 -0
- package/preset/odai/runtime/session-compat.d.mts +31 -0
- package/preset/odai/runtime/session-compat.d.mts.map +1 -0
- package/preset/odai/runtime/session-compat.mjs +301 -328
- package/preset/odai/runtime/session-compat.mjs.map +1 -0
- package/preset/odai/runtime/session-evidence.d.mts +25 -0
- package/preset/odai/runtime/session-evidence.d.mts.map +1 -0
- package/preset/odai/runtime/session-evidence.mjs +309 -287
- package/preset/odai/runtime/session-evidence.mjs.map +1 -0
- package/preset/odai/runtime/skill-bundle.d.mts +53 -0
- package/preset/odai/runtime/skill-bundle.d.mts.map +1 -0
- package/preset/odai/runtime/skill-bundle.mjs +286 -276
- package/preset/odai/runtime/skill-bundle.mjs.map +1 -0
- package/preset/odai/runtime/skill-evolution.d.mts +112 -0
- package/preset/odai/runtime/skill-evolution.d.mts.map +1 -0
- package/preset/odai/runtime/skill-evolution.mjs +1287 -1261
- package/preset/odai/runtime/skill-evolution.mjs.map +1 -0
- package/preset/odai/runtime/skill-selection-state.d.mts +5 -0
- package/preset/odai/runtime/skill-selection-state.d.mts.map +1 -0
- package/preset/odai/runtime/skill-selection-state.mjs +59 -43
- package/preset/odai/runtime/skill-selection-state.mjs.map +1 -0
- package/preset/odai/runtime/skill-selector.d.mts +28 -0
- package/preset/odai/runtime/skill-selector.d.mts.map +1 -0
- package/preset/odai/runtime/skill-selector.mjs +100 -109
- package/preset/odai/runtime/skill-selector.mjs.map +1 -0
- package/preset/odai/runtime/skill-source-config.d.mts +32 -0
- package/preset/odai/runtime/skill-source-config.d.mts.map +1 -0
- package/preset/odai/runtime/skill-source-config.mjs +200 -210
- package/preset/odai/runtime/skill-source-config.mjs.map +1 -0
- package/preset/odai/runtime/store-lock.d.mts +2 -0
- package/preset/odai/runtime/store-lock.d.mts.map +1 -0
- package/preset/odai/runtime/store-lock.mjs +92 -87
- package/preset/odai/runtime/store-lock.mjs.map +1 -0
- package/preset/odai/runtime/tool-runtime.d.mts +43 -0
- package/preset/odai/runtime/tool-runtime.d.mts.map +1 -0
- package/preset/odai/runtime/tool-runtime.mjs +221 -0
- package/preset/odai/runtime/tool-runtime.mjs.map +1 -0
- package/bin/odai-dsh-agent.mjs +0 -108
- package/scripts/verify-agent-load.mjs +0 -257
- package/src/dsh-version.mjs +0 -24
- package/src/installer.mjs +0 -398
|
@@ -1,683 +1,615 @@
|
|
|
1
|
+
import { isUnknownRecord } from "./runtime-types.mjs";
|
|
2
|
+
function isContinuationRole(value) {
|
|
3
|
+
return value === "planner" || value === "executor" || value === "frontend";
|
|
4
|
+
}
|
|
1
5
|
export const HIGH_IMPACT_PLANNER_REASON = "PLANNER_UNVERIFIED_HIGH_IMPACT_CHANGE";
|
|
2
6
|
export const RESEARCHER_EVIDENCE_REASON = "RESEARCHER_MULTI_SOURCE_DECISION_EVIDENCE";
|
|
3
7
|
export const FRONTEND_SPECIALIST_REASON = "FRONTEND_SUBSTANTIAL_INTERFACE_WORK";
|
|
4
8
|
export const EXECUTOR_ROUTE_CARD_REASON = "EXECUTOR_FROZEN_ROUTE_NET_BENEFIT";
|
|
5
9
|
export const OUTPUT_LIMIT_CONTINUATION_REASON = "RESPONSIBILITY_OUTPUT_LIMIT_CONTINUATION";
|
|
6
|
-
|
|
7
10
|
const RESPONSIBILITY_LABELS = Object.freeze({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
researcher: "多源事实调查",
|
|
12
|
+
planner: "规划",
|
|
13
|
+
executor: "执行",
|
|
14
|
+
reviewer: "验收",
|
|
15
|
+
frontend: "前端设计与制作",
|
|
13
16
|
});
|
|
14
|
-
|
|
15
17
|
const PLANNER_PATTERNS = [
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
];
|
|
25
|
-
|
|
18
|
+
/独立(?:判断|规划|分析|决定|决策)/iu,
|
|
19
|
+
/比较(?:一下)?(?:方案|路线|架构)/iu,
|
|
20
|
+
/架构选型/iu,
|
|
21
|
+
/先(?:判断|规划)(?:路线|方案)/iu,
|
|
22
|
+
/second opinion (?:on|for) (?:the )?(?:plan|approach|architecture)/iu,
|
|
23
|
+
/compare (?:the )?(?:approaches|options|architectures)/iu,
|
|
24
|
+
/architecture decision/iu,
|
|
25
|
+
/(?:independently decide|independent decision)/iu,
|
|
26
|
+
];
|
|
26
27
|
const PLANNER_META_PATTERNS = [
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
/(?:你|是否|有没有|有没).{0,12}(?:规划|计划)(?:了|过|吗|没有)/iu,
|
|
29
|
+
/(?:did you|have you).{0,24}\bplan(?:ned|ning)?\b/iu,
|
|
29
30
|
];
|
|
30
|
-
|
|
31
31
|
const REVIEWER_PATTERNS = [
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
];
|
|
39
|
-
|
|
32
|
+
/独立(?:审查|复核|评审)/iu,
|
|
33
|
+
/(?:代码|安全|变更)(?:审查|复核|评审)/iu,
|
|
34
|
+
/code review/iu,
|
|
35
|
+
/security review/iu,
|
|
36
|
+
/independent review/iu,
|
|
37
|
+
/challenge (?:the )?(?:plan|implementation|result)/iu,
|
|
38
|
+
];
|
|
40
39
|
const RISK_PATTERNS = [
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
/(?:高风险|安全|权限|删除|迁移|发布|生产环境)/iu,
|
|
41
|
+
/(?:支付|付款|结算|扣款|退款|订单)[^。!?\n]{0,60}(?:提供方|服务|接口|请求|结果|状态|超时|重试|金额|交易|配置|回调|不稳定)/iu,
|
|
42
|
+
/(?:high[- ]risk|security|permission|delete|migration|production)/iu,
|
|
43
|
+
/(?:checkout|payment|billing|charge|refund)[^.!?\n]{0,80}(?:provider|service|request|result|status|timeout|retry|transaction|configuration|unstable|fail|超时|重试|不稳定)/iu,
|
|
45
44
|
];
|
|
46
|
-
|
|
47
45
|
const UNVERIFIED_CAUSAL_PATTERNS = [
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
/(?:我看|看起来|看来|估计|大概|八成|明显|肯定)(?:就)?是/iu,
|
|
47
|
+
/(?:问题|原因|根因)(?:应该|可能|大概|估计)(?:就)?在/iu,
|
|
48
|
+
/\b(?:it\s+)?(?:looks?|seems)\s+like\b/iu,
|
|
49
|
+
/\b(?:i think|probably|apparently|clearly|obviously)\b[^.!?\n]{0,80}\b(?:is|are|because|caused by|comes from)\b/iu,
|
|
52
50
|
];
|
|
53
|
-
|
|
54
51
|
const CONCRETE_CHANGE_PATTERNS = [
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
/把[^。!?\n]{1,120}(?:降到|提到|提高到|改成|设为|设置为|切到|换成|开启|关闭|删除|清空|迁移到|发布到|上线)/iu,
|
|
53
|
+
/(?:降低|提高|增加|减少|修改|设置|开启|关闭|删除|清空|迁移|发布|上线)[^。!?\n]{0,80}(?:\d|配置|超时|重试|权限|数据|服务)/iu,
|
|
54
|
+
/\b(?:set|change|reduce|lower|increase|raise|disable|enable|delete|drop|clear|migrate|deploy|release)\b[^.!?\n]{0,100}\b(?:to|from|timeout|retries|permission|data|service|production)\b/iu,
|
|
58
55
|
];
|
|
59
|
-
|
|
60
56
|
const SPECIFIC_PARAMETER_PATTERNS = [
|
|
61
|
-
|
|
57
|
+
/\d+(?:\.\d+)?\s*(?:毫秒|秒|分钟|小时|次|%|%|ms|sec(?:ond)?s?|min(?:ute)?s?|hours?|retries?|mb|gb)/iu,
|
|
62
58
|
];
|
|
63
|
-
|
|
64
59
|
const URGENCY_PATTERNS = [
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
/(?:先止血|立即|马上|赶紧|紧急|热修)/iu,
|
|
61
|
+
/\b(?:hotfix|immediately|right away|stop the bleeding)\b/iu,
|
|
67
62
|
];
|
|
68
|
-
|
|
69
63
|
const IRREVERSIBLE_ACTION_PATTERNS = [
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
/(?:删除|清空|迁移|发布|上线|关闭)/iu,
|
|
65
|
+
/\b(?:delete|drop|clear|migrate|deploy|release|disable)\b/iu,
|
|
72
66
|
];
|
|
73
|
-
|
|
74
67
|
const CONTINUATION_PATTERNS = [
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
/(?:继续|接着|进一步|深入|再(?:判断|分析|评估|检查|处理)|按(?:照)?(?:刚才|上面|上述|前面|这个|该)|那就|就按|能做不|能不能做|可以做不|可以做吗)/iu,
|
|
69
|
+
/\b(?:continue|proceed|go ahead|follow up|dig deeper|based on (?:that|the previous|the above)|can you (?:do|handle|implement) (?:it|that))\b/iu,
|
|
77
70
|
];
|
|
78
|
-
|
|
79
71
|
const PURE_RESPONSIBILITY_CONTINUATION_PATTERNS = [
|
|
80
|
-
|
|
81
|
-
|
|
72
|
+
/^\s*(?:请)?(?:继续|接着|接下去|续上|恢复)(?:(?:执行|完成|处理|做|推进|设计|分析|规划))?(?:(?:刚才|之前|上次|这个|该|原来)的?)?(?:任务|工作|实现|方案|设计|分析|规划)?(?:下去|完成|吧)?[。!!]?\s*$/iu,
|
|
73
|
+
/^\s*(?:please\s+)?(?:continue|go on|resume|carry on|keep going)(?:\s+(?:the\s+)?(?:previous|interrupted|same)?\s*(?:task|work|implementation|plan|design|analysis))?[.!]?\s*$/iu,
|
|
82
74
|
];
|
|
83
75
|
const OUTPUT_LIMIT_DIAGNOSTIC_PATTERNS = [
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
76
|
+
/(?:截断|断掉|中断|输出[^。!?\n]{0,12}(?:上限|预算)|(?:上限|预算)[^。!?\n]{0,12}输出|max\s*[_-]?\s*tokens?)/iu,
|
|
77
|
+
/(?:token|令牌)[^。!?\n]{0,16}(?:limit|budget|上限|预算|截断)/iu,
|
|
78
|
+
/(?:为什么|为何|怎么)[^。!?\n]{0,20}(?:停|断|中断|没继续|不继续)/iu,
|
|
87
79
|
];
|
|
88
|
-
|
|
89
80
|
const LOW_RISK_TRANSFORM_PATTERNS = [
|
|
90
|
-
|
|
91
|
-
|
|
81
|
+
/(?:重述|总结|概括|压缩|翻译|改写|润色|格式化|解释(?:一下)?)/iu,
|
|
82
|
+
/\b(?:restate|summari[sz]e|translate|shorten|rewrite|format|explain)\b/iu,
|
|
92
83
|
];
|
|
93
|
-
|
|
94
84
|
const EXPLICIT_EXECUTION_CONTINUATION_PATTERNS = [
|
|
95
|
-
|
|
96
|
-
|
|
85
|
+
/(?:继续|接着|就按|按(?:照)?(?:(?:这个|该|上述|上面|前面|刚才)的?)?(?:方案|计划|卡片))/iu,
|
|
86
|
+
/\b(?:continue|proceed|go ahead|follow the plan)\b/iu,
|
|
97
87
|
];
|
|
98
88
|
const IMPLEMENTATION_AUTHORIZATION_PATTERNS = [
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
89
|
+
/(?:做(?:完|好|掉|这个|这项|这次|一个)|实现|修复|完成|落地|开发|添加|新增|替换|删除|执行|全都做好)/iu,
|
|
90
|
+
/(?:请|麻烦|直接|开始|继续)(?:帮我)?(?:处理|修改|更新)|帮我(?:处理|修改|更新)|需要(?:处理|修改|更新)|可以(?:帮我)?(?:处理|修改|更新)|^(?:处理|修改|更新)(?:一下|这个|该|文件|代码|配置|依赖|问题|功能|实现|文档|测试)/iu,
|
|
91
|
+
/\b(?:do it|implement|fix|complete|build|add|replace|remove|execute|ship)\b/iu,
|
|
92
|
+
/^(?:please\s+)?(?:(?:change|modify)\b|update\b(?!\s+(?:me|us|them|everyone|the team)\b))|\b(?:please|can you|could you|would you|go ahead and|start to|continue to)\s+(?:(?:change|modify)\b|update\b(?!\s+(?:me|us|them|everyone|the team)\b))|\bi (?:need|want) you to\s+(?:(?:change|modify)\b|update\b(?!\s+(?:me|us|them|everyone|the team)\b))/iu,
|
|
103
93
|
];
|
|
104
94
|
const PLAN_ONLY_PATTERNS = [
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
95
|
+
/(?:只|仅).{0,16}(?:规划|计划|分析|评估|建议|方案|审查|复核|评审|检查)/iu,
|
|
96
|
+
/(?:先|帮我)(?:规划|计划|分析|评估)(?:一下)?[^。!?\n]{0,40}(?:$|[。!?])/iu,
|
|
97
|
+
/^\s*(?:请)?(?:规划|计划|分析|评估|建议|审查|复核|评审|检查)/iu,
|
|
98
|
+
/^\s*(?:请)?(?:列一下|列出|整理(?:一份)?|给我(?:一份)?)[^。!?\n]{0,64}(?:地方|清单|列表|说明|建议|方案|示例|影响|步骤)(?:$|[。!?])/iu,
|
|
99
|
+
/\b(?:review|audit|inspect)\s+only\b/iu,
|
|
100
|
+
/\b(?:just|only)\s+(?:plan|analy[sz]e|assess|evaluate|review|audit|inspect|recommend|explain|describe|outline|list)\b/iu,
|
|
101
|
+
/^\s*(?:please\s+)?(?:plan|analy[sz]e|assess|evaluate|review|audit|inspect|recommend|explain|describe|outline|list)\b/iu,
|
|
112
102
|
];
|
|
113
103
|
const PLAN_THEN_IMPLEMENT_PATTERNS = [
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
104
|
+
/(?:规划|计划|分析|评估|建议|审查|复核|评审|检查)[^。!?\n]{0,48}(?:然后|再|之后|接着|并(?:且)?)[^。!?\n]{0,24}(?:实现|修复|完成|落地|开发|添加|新增|修改|更新(?![^。!?\n]{0,8}(?:我|我们|团队|进展|结果|情况|发现|消息|状态))|替换|删除|执行)/iu,
|
|
105
|
+
/(?:列一下|列出|整理(?:一份)?|给我(?:一份)?)[^。!?\n]{0,64}(?:然后|再|之后|接着|并(?:且)?)[^。!?\n]{0,24}(?:实现|修复|完成|落地|开发|添加|新增|修改|更新|替换|删除|执行)/iu,
|
|
106
|
+
/\b(?:plan|analy[sz]e|assess|evaluate|review|audit|inspect|recommend|explain|describe|outline|list)\b[^.!?\n]{0,64}\b(?:then|and(?: then)?|after that)\b[^.!?\n]{0,24}\b(?:implement|fix|complete|build|add|change|update(?!\s+(?:me|us|them|everyone|the team)\b)|modify|replace|remove|execute|ship)\b/iu,
|
|
117
107
|
];
|
|
118
108
|
const STATUS_UPDATE_PATTERNS = [
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
109
|
+
/(?:更新|同步)[^。!?\n]{0,24}(?:进展|结果|情况|发现|消息|状态)/iu,
|
|
110
|
+
/\bupdate\b[^.!?\n]{1,48}\b(?:on|about|regarding)\b/iu,
|
|
111
|
+
/\bupdate\b[^.!?\n]{1,48}\bwith\s+(?:the\s+)?(?:findings|progress|results|status|details|news|outcome)\b/iu,
|
|
122
112
|
];
|
|
123
113
|
const UNAMBIGUOUS_DELIVERY_PATTERNS = [
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
114
|
+
/(?:^|[,;。]|然后|再|之后|接着|并(?:且)?|请|帮我)(?:做(?:完|好|掉)|实现|修复|完成|落地|开发|添加|新增|修改|替换|删除|执行)/iu,
|
|
115
|
+
/更新(?:代码|项目|依赖|包|清单|文档|测试|配置|文件|运行时|服务|应用|界面|数据库|架构)/iu,
|
|
116
|
+
/\b(?:do it|implement|execute|ship)\b/iu,
|
|
117
|
+
/(?:^|\b(?:then|and|to|please)\s+)\b(?:fix|complete|build|add|change|modify|replace|remove)\b/iu,
|
|
118
|
+
/\bupdate\s+(?:the\s+)?(?:code|project|dependencies?|packages?|manifest|docs?|documentation|tests?|config(?:uration)?|files?|runtime|services?|app(?:lication)?|ui|interface|schema|database|architecture)\b/iu,
|
|
129
119
|
];
|
|
130
120
|
const NON_IMPLEMENTATION_QUERY_PATTERNS = [
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
121
|
+
/(?:有什么|有何|哪些|是什么|为何|为什么|怎么样|怎么看|发生了什么|有变化吗|影响(?:是|有)?什么)[^。!?\n]*[??]?$/iu,
|
|
122
|
+
/^\s*(?:what|why|how)\b[^.!?\n]*[?]\s*$/iu,
|
|
123
|
+
/\b(?:what changed|what changes|what impact|which changes|difference between)\b[^.!?\n]*[?]?$/iu,
|
|
134
124
|
];
|
|
135
125
|
const NO_IMPLEMENTATION_PATTERNS = [
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
126
|
+
/(?:不要|别|请勿|禁止|无需|不用|不需要|不能)[^。!?\n]{0,28}(?:改|修改|编辑|写入|实现|执行|落地|动文件|动代码)/iu,
|
|
127
|
+
/\b(?:do not|don't|never|without)\b[^.!?\n]{0,48}\b(?:implement|modify|edit|change|write|execute|apply|make changes?)\b/iu,
|
|
128
|
+
/\b(?:plan|analyze|assess|evaluate|recommend)(?: only)?\b[^.!?]{0,30}\b(?:do not|don't|without) (?:implementing|changes?)\b/iu,
|
|
139
129
|
];
|
|
140
130
|
const GLOBAL_NO_EDIT_PATTERNS = [
|
|
141
|
-
|
|
142
|
-
|
|
131
|
+
/(?:不要|别|请勿|禁止)[^,;。!?\n]{0,12}(?:改|修改|编辑|写入)[^,;。!?\n]{0,12}(?:任何|全部|所有|整个)[^,;。!?\n]{0,12}(?:文件|代码|内容|实现|东西)/iu,
|
|
132
|
+
/\b(?:do not|don't|never)\b[^,;.!?\n]{0,12}\b(?:modify|edit|change|write)\b[^,;.!?\n]{0,16}\b(?:anything|any (?:files?|code|changes?)|all (?:files?|code|changes?)|the (?:whole|entire) codebase)\b/iu,
|
|
143
133
|
];
|
|
144
134
|
const SCOPED_NO_EDIT_WITH_EXECUTION_PATTERNS = [
|
|
145
|
-
|
|
146
|
-
|
|
135
|
+
/(?:不要|别|请勿)[^,;。!?\n]{0,12}(?:改|修改|编辑|写入)(?![^,;。!?\n]{0,12}(?:任何|全部|所有|整个))[^,;。!?\n]{1,28}[,;。](?![^,;。!?\n]{0,20}(?:不要|别|请勿|禁止|无需|不用|不需要|不能))[ \t]*[^,;。!?\n]{0,20}(?:实现|修复|修改|更新|执行|落地)/iu,
|
|
136
|
+
/\b(?:do not|don't|never)\b[^,;.!?\n]{0,12}\b(?:modify|edit|change|write)\b(?![^,;.!?\n]{0,16}\b(?:anything|any (?:files?|code|changes?)|all (?:files?|code|changes?)|the (?:whole|entire) codebase)\b)[^,;.!?\n]{1,36}[,;.](?![^,;.!?\n]{0,24}\b(?:do not|don't|never|no need to|without|skip)\b)\s*[^,;.!?\n]{0,24}\b(?:implement|fix|change|update|execute|apply)\b/iu,
|
|
147
137
|
];
|
|
148
138
|
const EXECUTION_ACTION_PATTERNS = [
|
|
149
|
-
|
|
150
|
-
|
|
139
|
+
/(?:开始|执行|实施|落实|动手)/iu,
|
|
140
|
+
/\b(?:start|execute|implement|apply)\b/iu,
|
|
151
141
|
];
|
|
152
142
|
const ROUTE_CARD_REFERENCE_PATTERNS = [
|
|
153
|
-
|
|
154
|
-
|
|
143
|
+
/(?:(?:这个|该|上述|上面|前面|刚才)的?(?:方案|计划|卡片|实现|改动|工作))/iu,
|
|
144
|
+
/\b(?:(?:this|that|the|above|previous)\s+(?:plan|proposal|route card|implementation|change)|(?:it|that))\b/iu,
|
|
155
145
|
];
|
|
156
146
|
const NEW_TASK_PATTERNS = [
|
|
157
|
-
|
|
158
|
-
|
|
147
|
+
/(?:另一个|另一项|另一件|另外(?:一个|一项|一件)|新(?:的)?(?:问题|任务|需求|工作))/iu,
|
|
148
|
+
/\b(?:another|(?:a )?new|different|separate)\s+(?:task|issue|problem|request|change|project)\b/iu,
|
|
159
149
|
];
|
|
160
|
-
|
|
161
150
|
const FRONTEND_SCOPE_PATTERNS = [
|
|
162
|
-
|
|
163
|
-
|
|
151
|
+
/(?:前端|界面|页面|网页|网站|着陆页|应用界面|仪表盘|控制台|组件|交互界面|移动端|桌面端|游戏界面|3D场景)/iu,
|
|
152
|
+
/\b(?:front[- ]?end|ui|ux|interface|web(?:site| app)?|landing page|page|dashboard|component|mobile|desktop|game ui|3d scene)\b/iu,
|
|
164
153
|
];
|
|
165
154
|
const FRONTEND_DELIVERY_PATTERNS = [
|
|
166
|
-
|
|
167
|
-
|
|
155
|
+
/(?:设计|制作|实现|开发|构建|创建|搭建|改版|重做|重构|优化|美化|修复)/iu,
|
|
156
|
+
/\b(?:design|build|implement|develop|create|craft|redesign|revamp|rework|optimi[sz]e|fix)\b/iu,
|
|
168
157
|
];
|
|
169
158
|
const FRONTEND_STRONG_WORK_PATTERNS = [
|
|
170
|
-
|
|
171
|
-
|
|
159
|
+
/(?:从零|新建|新做|整页|整站|整体改版|完整界面|设计并实现|重新设计|重做|改版|搭建)/iu,
|
|
160
|
+
/\b(?:build|create|design and implement|redesign|revamp|rebuild)\b[^.!?\n]{0,60}\b(?:ui|interface|page|website|web app|dashboard|component|game)\b/iu,
|
|
172
161
|
];
|
|
173
162
|
const FRONTEND_SURFACE_PATTERNS = [
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
163
|
+
/登录(?:页|页面)/iu,
|
|
164
|
+
/(?:登录后)?首页/iu,
|
|
165
|
+
/(?:个人空间|个人中心|用户中心|个人主页)/iu,
|
|
166
|
+
/(?:注册|设置|搜索|列表|详情|结算|支付)(?:页|页面)/iu,
|
|
167
|
+
/\b(?:login page|home page|profile|personal space|settings page|search page|list page|detail page|checkout page)\b/iu,
|
|
179
168
|
];
|
|
180
169
|
const FRONTEND_NON_UI_PATTERNS = [
|
|
181
|
-
|
|
182
|
-
|
|
170
|
+
/(?:API|接口)(?:调用|请求|响应|超时|缓存|鉴权|数据|字段|契约)/iu,
|
|
171
|
+
/\b(?:api|endpoint|backend|server-side)\b/iu,
|
|
183
172
|
];
|
|
184
173
|
const FRONTEND_UI_PRODUCTION_PATTERNS = [
|
|
185
|
-
|
|
186
|
-
|
|
174
|
+
/(?:UI|UX|用户界面|界面介绍|布局|样式|排版|配色|交互|视觉|响应式|移动端|桌面端|截图|浏览器验收)/iu,
|
|
175
|
+
/\b(?:ui|ux|interface|layout|styling|typography|interaction|visual|responsive|mobile|desktop|screenshot|browser acceptance)\b/iu,
|
|
187
176
|
];
|
|
188
177
|
const FRONTEND_EXPLICIT_SPECIALIST_PATTERNS = [
|
|
189
|
-
|
|
190
|
-
|
|
178
|
+
/(?:交给|使用|用)[^。!?\n]{0,30}(?:前端|UI|UX)(?:专长|专家|模型)/iu,
|
|
179
|
+
/\b(?:use|with|via)\b[^.!?\n]{0,30}\b(?:front[- ]?end|ui|ux) (?:specialist|expert|model)\b/iu,
|
|
191
180
|
];
|
|
192
181
|
const FRONTEND_AXIS_PATTERNS = Object.freeze({
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
182
|
+
responsive: [/(?:响应式|移动端|桌面端|多端|窄屏|宽屏|视口)/iu, /\b(?:responsive|mobile|desktop|viewport|breakpoint)\b/iu],
|
|
183
|
+
interaction: [/(?:交互|动效|动画|拖拽|手势|状态流转|多状态)/iu, /\b(?:interaction|animation|motion|drag|gesture|state flow|multiple states)\b/iu],
|
|
184
|
+
visual: [/(?:视觉|品牌|排版|配色|设计系统|素材|图片|图标|3D|游戏界面)/iu, /\b(?:visual|brand|typography|palette|design system|asset|image|icon|3d|game ui)\b/iu],
|
|
185
|
+
comprehension: [/(?:一眼(?:就)?(?:看懂|明白|理解)|做什么|首屏认知|价值表达|信息架构|界面介绍)/iu, /\b(?:understand at a glance|first-screen comprehension|value proposition|information architecture|what (?:it|the product) does)\b/iu],
|
|
186
|
+
acceptance: [/(?:截图|浏览器验收|视觉验收|无障碍|Playwright|真机)/iu, /\b(?:screenshot|browser acceptance|visual acceptance|accessibility|playwright|device testing)\b/iu],
|
|
198
187
|
});
|
|
199
|
-
|
|
200
188
|
function matchesAny(text, patterns) {
|
|
201
|
-
|
|
189
|
+
return patterns.some((pattern) => pattern.test(text));
|
|
202
190
|
}
|
|
203
|
-
|
|
204
191
|
function stripQuotedMaterial(text) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
192
|
+
return text
|
|
193
|
+
.replace(/```[\s\S]*?```/gu, " ")
|
|
194
|
+
.replace(/^\s*>.*$/gmu, " ")
|
|
195
|
+
.replace(/`[^`\n]*`/gu, " ")
|
|
196
|
+
.replace(/“[^”\n]*”|‘[^’\n]*’|「[^」\n]*」|『[^』\n]*』|《[^》\n]*》|"[^"\n]*"/gu, " ");
|
|
210
197
|
}
|
|
211
|
-
|
|
212
198
|
export function classifyResponsibilityInterruptionText(text) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
199
|
+
const explicit = stripQuotedMaterial(String(text ?? "")).trim();
|
|
200
|
+
if (!explicit)
|
|
201
|
+
return "clear";
|
|
202
|
+
if (matchesAny(explicit, PURE_RESPONSIBILITY_CONTINUATION_PATTERNS))
|
|
203
|
+
return "continue";
|
|
204
|
+
if (matchesAny(explicit, OUTPUT_LIMIT_DIAGNOSTIC_PATTERNS))
|
|
205
|
+
return "preserve";
|
|
206
|
+
return "clear";
|
|
218
207
|
}
|
|
219
|
-
|
|
220
208
|
function isExecutionContinuation(text) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
209
|
+
if (matchesAny(text, NEW_TASK_PATTERNS))
|
|
210
|
+
return false;
|
|
211
|
+
if (matchesAny(text, EXPLICIT_EXECUTION_CONTINUATION_PATTERNS))
|
|
212
|
+
return true;
|
|
213
|
+
return matchesAny(text, EXECUTION_ACTION_PATTERNS)
|
|
214
|
+
&& matchesAny(text, ROUTE_CARD_REFERENCE_PATTERNS);
|
|
225
215
|
}
|
|
226
|
-
|
|
227
216
|
export function classifyImplementationAuthorization(text) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
217
|
+
const explicit = stripQuotedMaterial(String(text ?? "")).trim();
|
|
218
|
+
if (!explicit)
|
|
219
|
+
return Object.freeze({ status: "unknown" });
|
|
220
|
+
if (matchesAny(explicit, GLOBAL_NO_EDIT_PATTERNS))
|
|
221
|
+
return Object.freeze({ status: "plan-only" });
|
|
222
|
+
if (matchesAny(explicit, SCOPED_NO_EDIT_WITH_EXECUTION_PATTERNS))
|
|
223
|
+
return Object.freeze({ status: "authorized" });
|
|
224
|
+
if (matchesAny(explicit, NO_IMPLEMENTATION_PATTERNS))
|
|
225
|
+
return Object.freeze({ status: "plan-only" });
|
|
226
|
+
if (matchesAny(explicit, STATUS_UPDATE_PATTERNS)
|
|
227
|
+
&& !matchesAny(explicit, UNAMBIGUOUS_DELIVERY_PATTERNS)
|
|
228
|
+
&& !matchesAny(explicit, CONCRETE_CHANGE_PATTERNS)) {
|
|
229
|
+
return Object.freeze({ status: matchesAny(explicit, PLAN_ONLY_PATTERNS) ? "plan-only" : "unknown" });
|
|
230
|
+
}
|
|
231
|
+
if (isExecutionContinuation(explicit) || matchesAny(explicit, PLAN_THEN_IMPLEMENT_PATTERNS)) {
|
|
232
|
+
return Object.freeze({ status: "authorized" });
|
|
233
|
+
}
|
|
234
|
+
if (matchesAny(explicit, PLAN_ONLY_PATTERNS))
|
|
235
|
+
return Object.freeze({ status: "plan-only" });
|
|
236
|
+
if (matchesAny(explicit, NON_IMPLEMENTATION_QUERY_PATTERNS))
|
|
237
|
+
return Object.freeze({ status: "unknown" });
|
|
238
|
+
if (matchesAny(explicit, IMPLEMENTATION_AUTHORIZATION_PATTERNS)
|
|
239
|
+
|| matchesAny(explicit, CONCRETE_CHANGE_PATTERNS)) {
|
|
240
|
+
return Object.freeze({ status: "authorized" });
|
|
241
|
+
}
|
|
242
|
+
return Object.freeze({ status: "unknown" });
|
|
248
243
|
}
|
|
249
|
-
|
|
250
244
|
function hasContextualPlannerGap(text) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
245
|
+
return matchesAny(text, RISK_PATTERNS)
|
|
246
|
+
&& matchesAny(text, UNVERIFIED_CAUSAL_PATTERNS)
|
|
247
|
+
&& matchesAny(text, CONCRETE_CHANGE_PATTERNS)
|
|
248
|
+
&& (matchesAny(text, SPECIFIC_PARAMETER_PATTERNS)
|
|
249
|
+
|| matchesAny(text, URGENCY_PATTERNS)
|
|
250
|
+
|| matchesAny(text, IRREVERSIBLE_ACTION_PATTERNS));
|
|
257
251
|
}
|
|
258
|
-
|
|
259
252
|
function isLowRiskTransform(text) {
|
|
260
|
-
|
|
253
|
+
return matchesAny(stripQuotedMaterial(text), LOW_RISK_TRANSFORM_PATTERNS);
|
|
261
254
|
}
|
|
262
|
-
|
|
263
255
|
function frontendSpecializationSignals(text) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
256
|
+
const explicit = matchesAny(text, FRONTEND_EXPLICIT_SPECIALIST_PATTERNS);
|
|
257
|
+
const surfaceCount = FRONTEND_SURFACE_PATTERNS.filter((pattern) => pattern.test(text)).length;
|
|
258
|
+
const explicitScope = matchesAny(text, FRONTEND_SCOPE_PATTERNS);
|
|
259
|
+
const scope = surfaceCount > 0 || explicitScope;
|
|
260
|
+
const delivery = matchesAny(text, FRONTEND_DELIVERY_PATTERNS);
|
|
261
|
+
const strongWork = matchesAny(text, FRONTEND_STRONG_WORK_PATTERNS);
|
|
262
|
+
const axes = Object.entries(FRONTEND_AXIS_PATTERNS)
|
|
263
|
+
.filter(([, patterns]) => matchesAny(text, patterns))
|
|
264
|
+
.map(([axis]) => axis);
|
|
265
|
+
const nonUiRequest = matchesAny(text, FRONTEND_NON_UI_PATTERNS)
|
|
266
|
+
&& !matchesAny(text, FRONTEND_UI_PRODUCTION_PATTERNS);
|
|
267
|
+
const specialistDepth = explicit
|
|
268
|
+
|| strongWork
|
|
269
|
+
|| axes.length >= 2
|
|
270
|
+
|| (surfaceCount >= 2 && (explicitScope || axes.length >= 1));
|
|
271
|
+
return Object.freeze({
|
|
272
|
+
explicit,
|
|
273
|
+
scope,
|
|
274
|
+
delivery,
|
|
275
|
+
strongWork,
|
|
276
|
+
nonUiRequest,
|
|
277
|
+
specialistDepth,
|
|
278
|
+
surfaceCount,
|
|
279
|
+
axes: Object.freeze(axes),
|
|
280
|
+
substantial: scope && delivery && specialistDepth && !nonUiRequest,
|
|
281
|
+
});
|
|
290
282
|
}
|
|
291
|
-
|
|
292
283
|
function frontendRouteSignals(frontend) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
284
|
+
return [
|
|
285
|
+
...(frontend.scope ? ["frontend-interface-scope"] : []),
|
|
286
|
+
...(frontend.delivery ? ["frontend-delivery-request"] : []),
|
|
287
|
+
...(frontend.explicit ? ["explicit-frontend-specialist"] : []),
|
|
288
|
+
...(frontend.strongWork ? ["substantial-frontend-work"] : []),
|
|
289
|
+
...(frontend.surfaceCount >= 2 ? ["frontend-multi-surface"] : []),
|
|
290
|
+
...frontend.axes.map((axis) => `frontend-${axis}`),
|
|
291
|
+
];
|
|
301
292
|
}
|
|
302
|
-
|
|
303
293
|
function genuineUserText(message) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
294
|
+
const source = message?.source;
|
|
295
|
+
if (message?.role !== "user" || !isUnknownRecord(source) || source.kind !== "user" || !Array.isArray(message.content))
|
|
296
|
+
return "";
|
|
297
|
+
return message.content
|
|
298
|
+
.filter((block) => block?.type === "text" && typeof block.text === "string")
|
|
299
|
+
.map((block) => block.text)
|
|
300
|
+
.join("\n")
|
|
301
|
+
.trim();
|
|
310
302
|
}
|
|
311
|
-
|
|
312
303
|
function genuineUserTexts(messages, sessionEvents = []) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
304
|
+
const candidates = [
|
|
305
|
+
...(Array.isArray(messages) ? [...messages].reverse() : []),
|
|
306
|
+
...(Array.isArray(sessionEvents)
|
|
307
|
+
? [...sessionEvents].reverse()
|
|
308
|
+
.filter((event) => event?.type === "user/message")
|
|
309
|
+
.map((event) => event.data)
|
|
310
|
+
: []),
|
|
311
|
+
];
|
|
312
|
+
const seen = new Set();
|
|
313
|
+
const texts = [];
|
|
314
|
+
for (const message of candidates) {
|
|
315
|
+
const text = genuineUserText(message);
|
|
316
|
+
if (!text || seen.has(text))
|
|
317
|
+
continue;
|
|
318
|
+
seen.add(text);
|
|
319
|
+
texts.push(text);
|
|
320
|
+
}
|
|
321
|
+
return texts;
|
|
330
322
|
}
|
|
331
|
-
|
|
332
323
|
function route(role, reasonCode, reason, signals, action = role === "controller" ? "direct" : "delegate", targetRole) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
324
|
+
return Object.freeze({
|
|
325
|
+
role,
|
|
326
|
+
mode: action,
|
|
327
|
+
action,
|
|
328
|
+
...(targetRole === undefined ? {} : { targetRole }),
|
|
329
|
+
reasonCode,
|
|
330
|
+
reason,
|
|
331
|
+
signals: Object.freeze([...new Set(signals)]),
|
|
332
|
+
});
|
|
342
333
|
}
|
|
343
|
-
|
|
344
334
|
export function decideResearchPrefetch(input = {}) {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
"researcher",
|
|
353
|
-
RESEARCHER_EVIDENCE_REASON,
|
|
354
|
-
proposal.gap,
|
|
355
|
-
["evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`],
|
|
356
|
-
);
|
|
335
|
+
const text = typeof input.text === "string" ? input.text.trim() : "";
|
|
336
|
+
const explicitIntentText = stripQuotedMaterial(text);
|
|
337
|
+
const proposal = input.proposal?.responsibility === "researcher" ? input.proposal : undefined;
|
|
338
|
+
if (!proposal || !explicitIntentText || isLowRiskTransform(explicitIntentText)) {
|
|
339
|
+
return route("controller", "RESEARCHER_PREFETCH_NOT_NEEDED", "No evidence-grounded multi-source compression gap was proposed.", ["no-research-prefetch"]);
|
|
340
|
+
}
|
|
341
|
+
return route("researcher", RESEARCHER_EVIDENCE_REASON, proposal.gap, ["evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`]);
|
|
357
342
|
}
|
|
358
|
-
|
|
359
343
|
/**
|
|
360
344
|
* Choose the smallest useful odai role. Risk alone never creates another role.
|
|
361
345
|
* Executor routing requires a frozen route card and observable net benefit;
|
|
362
346
|
* those facts cannot be inferred from task prose.
|
|
363
347
|
*/
|
|
364
348
|
export function decideRoute(input = {}) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
signals.push("
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
const frontendSignals = frontend.scope || frontend.explicit ? frontendRouteSignals(frontend) : [];
|
|
492
|
-
if (frontend.substantial && !isLowRiskTransform(explicitIntentText)) {
|
|
493
|
-
signals.push(...frontendSignals);
|
|
494
|
-
return route(
|
|
495
|
-
"controller",
|
|
496
|
-
FRONTEND_SPECIALIST_REASON,
|
|
497
|
-
"Substantial user-facing interface work can benefit from a configured frontend specialist without a child handoff.",
|
|
498
|
-
signals,
|
|
499
|
-
"upgrade",
|
|
500
|
-
"frontend",
|
|
501
|
-
);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
signals.push(...frontendSignals, "no-independent-gap");
|
|
505
|
-
const direct = route(
|
|
506
|
-
"controller",
|
|
507
|
-
"DIRECT_DEFAULT_NO_INDEPENDENT_GAP",
|
|
508
|
-
"No evidence-grounded independent decision, execution, or acceptance gap was found.",
|
|
509
|
-
signals,
|
|
510
|
-
);
|
|
511
|
-
if (frontendSignals.length > 0) {
|
|
512
|
-
const lowRiskTransform = isLowRiskTransform(explicitIntentText);
|
|
513
|
-
considerations.push(Object.freeze({
|
|
514
|
-
role: "frontend",
|
|
515
|
-
match: "partial",
|
|
516
|
-
action: "skip",
|
|
517
|
-
reasonCode: frontend.nonUiRequest
|
|
518
|
-
? "FRONTEND_API_REQUEST"
|
|
519
|
-
: lowRiskTransform
|
|
520
|
-
? "FRONTEND_LOW_RISK_TRANSFORM"
|
|
521
|
-
: "FRONTEND_BELOW_SPECIALIST_THRESHOLD",
|
|
522
|
-
signals: Object.freeze(frontendSignals),
|
|
523
|
-
unmet: Object.freeze(frontend.nonUiRequest
|
|
524
|
-
? ["ui-production-request"]
|
|
525
|
-
: [
|
|
526
|
-
...(frontend.scope ? [] : ["interface-scope"]),
|
|
527
|
-
...(frontend.delivery ? [] : ["delivery-request"]),
|
|
528
|
-
...(frontend.specialistDepth ? [] : ["specialist-or-substantial-scope"]),
|
|
529
|
-
]),
|
|
530
|
-
}));
|
|
531
|
-
}
|
|
532
|
-
return considerations.length === 0
|
|
533
|
-
? direct
|
|
534
|
-
: Object.freeze({ ...direct, considerations: Object.freeze(considerations) });
|
|
349
|
+
const text = typeof input.text === "string" ? input.text.trim() : "";
|
|
350
|
+
const explicitIntentText = stripQuotedMaterial(text);
|
|
351
|
+
const proposal = input.proposal;
|
|
352
|
+
const signals = [];
|
|
353
|
+
const considerations = [];
|
|
354
|
+
const riskPresent = matchesAny(text, RISK_PATTERNS);
|
|
355
|
+
const unverifiedCausalClaim = matchesAny(text, UNVERIFIED_CAUSAL_PATTERNS);
|
|
356
|
+
const concreteChangeRequest = matchesAny(text, CONCRETE_CHANGE_PATTERNS);
|
|
357
|
+
const specificOperationalParameter = matchesAny(text, SPECIFIC_PARAMETER_PATTERNS);
|
|
358
|
+
const urgencyPressure = matchesAny(text, URGENCY_PATTERNS);
|
|
359
|
+
const irreversibleAction = matchesAny(text, IRREVERSIBLE_ACTION_PATTERNS);
|
|
360
|
+
const frontend = frontendSpecializationSignals(explicitIntentText);
|
|
361
|
+
if (riskPresent)
|
|
362
|
+
signals.push("risk-present");
|
|
363
|
+
if (unverifiedCausalClaim)
|
|
364
|
+
signals.push("unverified-causal-claim");
|
|
365
|
+
if (concreteChangeRequest)
|
|
366
|
+
signals.push("concrete-change-request");
|
|
367
|
+
if (specificOperationalParameter)
|
|
368
|
+
signals.push("specific-operational-parameter");
|
|
369
|
+
if (urgencyPressure)
|
|
370
|
+
signals.push("urgency-pressure");
|
|
371
|
+
if (irreversibleAction)
|
|
372
|
+
signals.push("irreversible-action");
|
|
373
|
+
const interruption = input.interruption;
|
|
374
|
+
if (isContinuationRole(interruption?.responsibility)
|
|
375
|
+
&& classifyResponsibilityInterruptionText(interruption?.continuationText) === "continue") {
|
|
376
|
+
return route("controller", OUTPUT_LIMIT_CONTINUATION_REASON, `The verified ${interruption.responsibility} responsibility was interrupted by the provider output limit and the user explicitly continued it.`, ["verified-output-limit-interruption", "explicit-continuation"], "upgrade", interruption.responsibility);
|
|
377
|
+
}
|
|
378
|
+
const executionAuthorizedByState = proposal?.responsibility === "executor"
|
|
379
|
+
&& input.routeCard?.authorization?.status === "authorized";
|
|
380
|
+
if (input.routeCard?.frozen === true
|
|
381
|
+
&& input.routeCard?.observableBenefit === true
|
|
382
|
+
&& (isExecutionContinuation(explicitIntentText) || executionAuthorizedByState)) {
|
|
383
|
+
signals.push("route-card-frozen", "observable-net-benefit", ...(executionAuthorizedByState ? ["evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`] : ["explicit-execution-continuation"]));
|
|
384
|
+
return route("controller", EXECUTOR_ROUTE_CARD_REASON, executionAuthorizedByState
|
|
385
|
+
? proposal.gap
|
|
386
|
+
: "A frozen route card exists, executor separation has an observable net benefit, and the user explicitly continued implementation.", signals, "upgrade", "executor");
|
|
387
|
+
}
|
|
388
|
+
if (proposal?.responsibility === "user") {
|
|
389
|
+
signals.push("user-decision-gap", `state:${proposal.stateDigest}`);
|
|
390
|
+
return route("controller", "USER_DECISION_REQUIRED", proposal.gap, signals);
|
|
391
|
+
}
|
|
392
|
+
if (proposal?.responsibility === "reviewer") {
|
|
393
|
+
signals.push("evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`);
|
|
394
|
+
return route("reviewer", "REVIEWER_EVIDENCE_STATE_GAP", proposal.gap, signals);
|
|
395
|
+
}
|
|
396
|
+
if (proposal?.responsibility === "planner") {
|
|
397
|
+
signals.push("evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`);
|
|
398
|
+
return route("controller", "PLANNER_EVIDENCE_STATE_GAP", proposal.gap, signals, "upgrade", "planner");
|
|
399
|
+
}
|
|
400
|
+
if (proposal?.responsibility === "frontend") {
|
|
401
|
+
signals.push("evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`);
|
|
402
|
+
return route("controller", "FRONTEND_EVIDENCE_STATE_GAP", proposal.gap, signals, "upgrade", "frontend");
|
|
403
|
+
}
|
|
404
|
+
if (matchesAny(explicitIntentText, REVIEWER_PATTERNS)) {
|
|
405
|
+
signals.push("review-language-present");
|
|
406
|
+
considerations.push(Object.freeze({
|
|
407
|
+
role: "reviewer",
|
|
408
|
+
match: "lexical",
|
|
409
|
+
action: "skip",
|
|
410
|
+
reasonCode: "REVIEWER_GAP_NOT_PROVEN",
|
|
411
|
+
signals: Object.freeze(["review-language-present"]),
|
|
412
|
+
unmet: Object.freeze(["current-evidence-package", "acceptance-impact"]),
|
|
413
|
+
}));
|
|
414
|
+
}
|
|
415
|
+
if (matchesAny(explicitIntentText, PLANNER_PATTERNS)) {
|
|
416
|
+
signals.push("planning-language-present");
|
|
417
|
+
considerations.push(Object.freeze({
|
|
418
|
+
role: "planner",
|
|
419
|
+
match: "lexical",
|
|
420
|
+
action: "skip",
|
|
421
|
+
reasonCode: "PLANNER_GAP_NOT_PROVEN",
|
|
422
|
+
signals: Object.freeze(["planning-language-present"]),
|
|
423
|
+
unmet: Object.freeze(["evidence-grounded-decision-branch", "observable-capability-benefit"]),
|
|
424
|
+
}));
|
|
425
|
+
}
|
|
426
|
+
else if (matchesAny(explicitIntentText, PLANNER_META_PATTERNS)) {
|
|
427
|
+
signals.push("planner-meta-question");
|
|
428
|
+
considerations.push(Object.freeze({
|
|
429
|
+
role: "planner",
|
|
430
|
+
match: "meta-question",
|
|
431
|
+
action: "skip",
|
|
432
|
+
reasonCode: "PLANNER_META_QUERY_NO_INDEPENDENT_GAP",
|
|
433
|
+
signals: Object.freeze(["planner-meta-question"]),
|
|
434
|
+
unmet: Object.freeze(["prior-task-state-with-unresolved-decision-branch"]),
|
|
435
|
+
}));
|
|
436
|
+
}
|
|
437
|
+
const contextualPlannerGap = riskPresent
|
|
438
|
+
&& unverifiedCausalClaim
|
|
439
|
+
&& concreteChangeRequest
|
|
440
|
+
&& (specificOperationalParameter || urgencyPressure || irreversibleAction);
|
|
441
|
+
if (contextualPlannerGap) {
|
|
442
|
+
return route("controller", HIGH_IMPACT_PLANNER_REASON, "An unverified causal claim is being used to justify a concrete high-impact change, so the controller needs a stronger decision route.", signals, "upgrade", "planner");
|
|
443
|
+
}
|
|
444
|
+
const frontendSignals = frontend.scope || frontend.explicit ? frontendRouteSignals(frontend) : [];
|
|
445
|
+
if (frontend.substantial && !isLowRiskTransform(explicitIntentText)) {
|
|
446
|
+
signals.push(...frontendSignals);
|
|
447
|
+
return route("controller", FRONTEND_SPECIALIST_REASON, "Substantial user-facing interface work can benefit from a configured frontend specialist without a child handoff.", signals, "upgrade", "frontend");
|
|
448
|
+
}
|
|
449
|
+
signals.push(...frontendSignals, "no-independent-gap");
|
|
450
|
+
const direct = route("controller", "DIRECT_DEFAULT_NO_INDEPENDENT_GAP", "No evidence-grounded independent decision, execution, or acceptance gap was found.", signals);
|
|
451
|
+
if (frontendSignals.length > 0) {
|
|
452
|
+
const lowRiskTransform = isLowRiskTransform(explicitIntentText);
|
|
453
|
+
considerations.push(Object.freeze({
|
|
454
|
+
role: "frontend",
|
|
455
|
+
match: "partial",
|
|
456
|
+
action: "skip",
|
|
457
|
+
reasonCode: frontend.nonUiRequest
|
|
458
|
+
? "FRONTEND_API_REQUEST"
|
|
459
|
+
: lowRiskTransform
|
|
460
|
+
? "FRONTEND_LOW_RISK_TRANSFORM"
|
|
461
|
+
: "FRONTEND_BELOW_SPECIALIST_THRESHOLD",
|
|
462
|
+
signals: Object.freeze(frontendSignals),
|
|
463
|
+
unmet: Object.freeze(frontend.nonUiRequest
|
|
464
|
+
? ["ui-production-request"]
|
|
465
|
+
: [
|
|
466
|
+
...(frontend.scope ? [] : ["interface-scope"]),
|
|
467
|
+
...(frontend.delivery ? [] : ["delivery-request"]),
|
|
468
|
+
...(frontend.specialistDepth ? [] : ["specialist-or-substantial-scope"]),
|
|
469
|
+
]),
|
|
470
|
+
}));
|
|
471
|
+
}
|
|
472
|
+
return considerations.length === 0
|
|
473
|
+
? direct
|
|
474
|
+
: Object.freeze({ ...direct, considerations: Object.freeze(considerations) });
|
|
535
475
|
}
|
|
536
|
-
|
|
537
476
|
export function extractLatestUserText(messages) {
|
|
538
|
-
|
|
477
|
+
return genuineUserTexts(messages)[0] ?? "";
|
|
539
478
|
}
|
|
540
|
-
|
|
541
479
|
export function extractRoutingText(messages, sessionEvents) {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
480
|
+
const texts = genuineUserTexts(messages, sessionEvents);
|
|
481
|
+
const latest = texts[0] ?? "";
|
|
482
|
+
if (!latest
|
|
483
|
+
|| hasContextualPlannerGap(latest)
|
|
484
|
+
|| !matchesAny(stripQuotedMaterial(latest), CONTINUATION_PATTERNS)
|
|
485
|
+
|| isLowRiskTransform(latest)) {
|
|
486
|
+
return latest;
|
|
487
|
+
}
|
|
488
|
+
let referencedHighImpact;
|
|
489
|
+
let referencedFrontend;
|
|
490
|
+
for (const text of texts.slice(1)) {
|
|
491
|
+
if (hasContextualPlannerGap(text)) {
|
|
492
|
+
referencedHighImpact = text;
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
495
|
+
const frontend = frontendSpecializationSignals(stripQuotedMaterial(text));
|
|
496
|
+
if (frontend.scope && frontend.delivery) {
|
|
497
|
+
referencedFrontend = text;
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
500
|
+
if (!isLowRiskTransform(text))
|
|
501
|
+
break;
|
|
502
|
+
}
|
|
503
|
+
if (referencedHighImpact) {
|
|
504
|
+
return `${latest}\n\nReferenced earlier high-impact user context:\n${referencedHighImpact}`;
|
|
557
505
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
referencedFrontend = text;
|
|
561
|
-
break;
|
|
506
|
+
if (referencedFrontend) {
|
|
507
|
+
return `${latest}\n\nReferenced earlier frontend user context:\n${referencedFrontend}`;
|
|
562
508
|
}
|
|
563
|
-
|
|
564
|
-
}
|
|
565
|
-
if (referencedHighImpact) {
|
|
566
|
-
return `${latest}\n\nReferenced earlier high-impact user context:\n${referencedHighImpact}`;
|
|
567
|
-
}
|
|
568
|
-
if (referencedFrontend) {
|
|
569
|
-
return `${latest}\n\nReferenced earlier frontend user context:\n${referencedFrontend}`;
|
|
570
|
-
}
|
|
571
|
-
return latest;
|
|
509
|
+
return latest;
|
|
572
510
|
}
|
|
573
|
-
|
|
574
511
|
export function requiresFailClosedProtection(decision) {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
512
|
+
if (decision?.reasonCode === HIGH_IMPACT_PLANNER_REASON)
|
|
513
|
+
return true;
|
|
514
|
+
if (!decision)
|
|
515
|
+
return false;
|
|
516
|
+
const decisionRole = decision.targetRole ?? decision.role;
|
|
517
|
+
if (decisionRole !== "planner" && decisionRole !== "executor" && decisionRole !== "reviewer")
|
|
518
|
+
return false;
|
|
519
|
+
const signals = new Set(decision.signals);
|
|
520
|
+
if (!signals.has("risk-present"))
|
|
521
|
+
return false;
|
|
522
|
+
return signals.has("irreversible-action")
|
|
523
|
+
|| (signals.has("concrete-change-request")
|
|
524
|
+
&& (signals.has("specific-operational-parameter") || signals.has("urgency-pressure")));
|
|
585
525
|
}
|
|
586
|
-
|
|
587
526
|
function observeProtocol(decision) {
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
527
|
+
const shared = [
|
|
528
|
+
"Observe-mode controller protocol:",
|
|
529
|
+
"- No independent role was run. Do not claim independent planning or review.",
|
|
530
|
+
"- Perform the missing responsibility locally: separate facts from assumptions, inspect decisive project evidence, and state what remains unverified.",
|
|
531
|
+
"- Ground the path in capabilities and evidence that actually exist. Treat unavailable environments, tools, owners, thresholds, and protections as missing conditions, not facts.",
|
|
532
|
+
"- End with concrete evidence-gathering steps and explicit decision criteria that let the user safely continue; objection alone is not a complete delivery.",
|
|
533
|
+
];
|
|
534
|
+
if (!requiresFailClosedProtection(decision))
|
|
535
|
+
return shared;
|
|
536
|
+
return [
|
|
537
|
+
...shared,
|
|
538
|
+
"- High-impact fail-closed boundary: do not implement, persist, or publish the requested change in this turn. Use read-only evidence only.",
|
|
539
|
+
"- Explain the protection-chain gap and keep the current state unchanged until the decision basis and end-to-end safety dependency are verified.",
|
|
540
|
+
];
|
|
602
541
|
}
|
|
603
|
-
|
|
604
542
|
export function renderRouteNotice(decision, runtimeMode, actualRoute) {
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
].join("\n");
|
|
543
|
+
const routeRole = decision.targetRole ?? decision.role;
|
|
544
|
+
const isUpgrade = decision.action === "upgrade"
|
|
545
|
+
&& (runtimeMode === "auto" || ["executor", "frontend"].includes(routeRole));
|
|
546
|
+
const action = isUpgrade
|
|
547
|
+
? "The current controller turn requested an in-place upgrade; no child was started."
|
|
548
|
+
: runtimeMode === "observe"
|
|
549
|
+
? `The ${routeRole} gap was selected in observe mode; do not start a child automatically.`
|
|
550
|
+
: `The ${routeRole} route was selected and executed as an independent child.`;
|
|
551
|
+
const routeIdentity = actualRoute
|
|
552
|
+
? [`${isUpgrade ? "requested controller route" : "verified child route"}: ${actualRoute.provider}/${actualRoute.model} (reasoning: ${actualRoute.reasoningEffort ?? "unspecified"}, maxTokens: ${actualRoute.maxTokens ?? (isUpgrade ? "inherited from Controller policy" : "provider default")})`]
|
|
553
|
+
: [];
|
|
554
|
+
return [
|
|
555
|
+
"odai automatic routing decision",
|
|
556
|
+
`role: ${decision.role}`,
|
|
557
|
+
`action: ${isUpgrade ? "upgrade" : decision.action}`,
|
|
558
|
+
...(decision.targetRole ? [`target responsibility: ${decision.targetRole}`] : []),
|
|
559
|
+
`reason: ${decision.reasonCode}`,
|
|
560
|
+
`runtime: ${runtimeMode}`,
|
|
561
|
+
action,
|
|
562
|
+
...routeIdentity,
|
|
563
|
+
...(runtimeMode === "observe" ? ["", ...observeProtocol(decision)] : []),
|
|
564
|
+
].join("\n");
|
|
628
565
|
}
|
|
629
|
-
|
|
630
566
|
export function renderMissingRouteConfigNotice(decision, runtimeMode, configFailure) {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
])
|
|
651
|
-
].join("\n");
|
|
567
|
+
const routeRole = decision.targetRole ?? decision.role;
|
|
568
|
+
const naturalRole = RESPONSIBILITY_LABELS[routeRole] ?? routeRole;
|
|
569
|
+
const invalidConfig = typeof configFailure === "string" && configFailure !== "";
|
|
570
|
+
return [
|
|
571
|
+
`odai routing capability is ${invalidConfig ? "invalid" : "not configured"}`,
|
|
572
|
+
`required responsibility: ${routeRole}`,
|
|
573
|
+
`runtime: ${runtimeMode}`,
|
|
574
|
+
`${invalidConfig ? "untrusted" : "missing"} responsibility mapping: ${routeRole}`,
|
|
575
|
+
...(invalidConfig ? [`configuration error: ${configFailure}`] : []),
|
|
576
|
+
`No ${routeRole} model was called. Do not claim that this responsibility ran or that the controller was upgraded.`,
|
|
577
|
+
`Tell the user that the required ${routeRole} model is ${invalidConfig ? "unavailable because its saved configuration is invalid" : "not configured"}. Ask them to name the provider, model, and optional reasoning effort in natural language.`,
|
|
578
|
+
`Example: “把${naturalRole}模型设为 <provider>/<model>,推理档设为 <effort>。”`,
|
|
579
|
+
`When the user specifies that mapping, call the odai_routing_config tool to ${invalidConfig ? "repair and " : ""}persist it. Do not ask the user to edit YAML or JSON, run a command, or add routing terminology to future task prompts.`,
|
|
580
|
+
...(requiresFailClosedProtection(decision) ? [
|
|
581
|
+
"High-impact fail-closed protection is active for this turn.",
|
|
582
|
+
"Do not implement, persist, or publish the requested change. Use read-only evidence only until the missing responsibility is configured or the decision gap is otherwise resolved.",
|
|
583
|
+
] : [
|
|
584
|
+
"Continue only with parts that do not depend on the missing independent responsibility.",
|
|
585
|
+
]),
|
|
586
|
+
].join("\n");
|
|
652
587
|
}
|
|
653
|
-
|
|
654
588
|
export function renderRouteFailureNotice(decision, failure) {
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
].join("\n");
|
|
589
|
+
const routeRole = decision.targetRole ?? decision.role;
|
|
590
|
+
if (!requiresFailClosedProtection(decision)) {
|
|
591
|
+
return `odai ${routeRole} route failed (${failure}); continue directly as controller and do not claim delegated evidence.`;
|
|
592
|
+
}
|
|
593
|
+
return [
|
|
594
|
+
`odai ${routeRole} route failed (${failure}); no independent evidence was obtained.`,
|
|
595
|
+
"High-impact fail-closed protection is active for this turn.",
|
|
596
|
+
"Do not implement, persist, or publish the requested change. Use read-only evidence only.",
|
|
597
|
+
"Ground the path in capabilities and evidence that actually exist. Treat unavailable environments, tools, owners, thresholds, and protections as missing conditions, not facts.",
|
|
598
|
+
"Explain the unresolved decision-evidence and protection-chain gaps, then provide concrete evidence-gathering steps and explicit decision criteria. Objection alone is not a complete delivery.",
|
|
599
|
+
].join("\n");
|
|
667
600
|
}
|
|
668
|
-
|
|
669
601
|
export function renderDelegationPrompt(decision, taskText, roleContract) {
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
].join("\n");
|
|
602
|
+
if (typeof roleContract !== "string" || roleContract.trim() === "") {
|
|
603
|
+
throw new TypeError(`canonical ${decision.role} role contract must be a non-empty string`);
|
|
604
|
+
}
|
|
605
|
+
return [
|
|
606
|
+
`You are the odai ${decision.role}.`,
|
|
607
|
+
roleContract.trim(),
|
|
608
|
+
"Runtime boundary: do not edit files, run shell commands, ask the user, or delegate further. The controller owns all final decisions and delivery.",
|
|
609
|
+
"Context boundary: this is a bounded task and evidence packet, not an inherited controller transcript. Use only the supplied contract, task, evidence, and source pointers; do not request or reconstruct the controller's full history.",
|
|
610
|
+
"",
|
|
611
|
+
"Task:",
|
|
612
|
+
taskText,
|
|
613
|
+
].join("\n");
|
|
683
614
|
}
|
|
615
|
+
//# sourceMappingURL=router.mjs.map
|