@winspan/claude-forge 8.13.1 → 8.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/definition.d.ts +53 -0
- package/dist/agents/definition.d.ts.map +1 -0
- package/dist/agents/definition.js +24 -0
- package/dist/agents/definition.js.map +1 -0
- package/dist/agents/distributor.d.ts +23 -0
- package/dist/agents/distributor.d.ts.map +1 -0
- package/dist/agents/distributor.js +85 -0
- package/dist/agents/distributor.js.map +1 -0
- package/dist/agents/index.d.ts +5 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +5 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/official-agents.d.ts +14 -0
- package/dist/agents/official-agents.d.ts.map +1 -0
- package/dist/agents/official-agents.js +510 -0
- package/dist/agents/official-agents.js.map +1 -0
- package/dist/agents/registry.d.ts +27 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +105 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +17 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/menu.js +183 -0
- package/dist/cli/commands/menu.js.map +1 -1
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/constants.js.map +1 -1
- package/dist/core/storage/schema.sql +60 -0
- package/dist/core/storage/sqlite.d.ts +73 -0
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +159 -0
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/daemon/auto-disable-scheduler.d.ts +53 -0
- package/dist/daemon/auto-disable-scheduler.d.ts.map +1 -0
- package/dist/daemon/auto-disable-scheduler.js +114 -0
- package/dist/daemon/auto-disable-scheduler.js.map +1 -0
- package/dist/daemon/handlers/post-tool-use.d.ts +3 -1
- package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/post-tool-use.js +14 -2
- package/dist/daemon/handlers/post-tool-use.js.map +1 -1
- package/dist/daemon/handlers/stop.d.ts +3 -1
- package/dist/daemon/handlers/stop.d.ts.map +1 -1
- package/dist/daemon/handlers/stop.js +14 -1
- package/dist/daemon/handlers/stop.js.map +1 -1
- package/dist/daemon/handlers/user-prompt.d.ts +18 -7
- package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt.js +97 -23
- package/dist/daemon/handlers/user-prompt.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +53 -18
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/routing-observer.d.ts +39 -0
- package/dist/daemon/routing-observer.d.ts.map +1 -0
- package/dist/daemon/routing-observer.js +156 -0
- package/dist/daemon/routing-observer.js.map +1 -0
- package/dist/engine/agent-router.d.ts +99 -0
- package/dist/engine/agent-router.d.ts.map +1 -0
- package/dist/engine/agent-router.js +206 -0
- package/dist/engine/agent-router.js.map +1 -0
- package/dist/engine/conventions/routing.yaml +84 -0
- package/dist/engine/dsl/parser.d.ts +6 -0
- package/dist/engine/dsl/parser.d.ts.map +1 -1
- package/dist/engine/dsl/parser.js +19 -0
- package/dist/engine/dsl/parser.js.map +1 -1
- package/dist/engine/evidence-store.d.ts.map +1 -1
- package/dist/engine/evidence-store.js +3 -0
- package/dist/engine/evidence-store.js.map +1 -1
- package/dist/engine/experiment-router.d.ts +102 -0
- package/dist/engine/experiment-router.d.ts.map +1 -0
- package/dist/engine/experiment-router.js +289 -0
- package/dist/engine/experiment-router.js.map +1 -0
- package/dist/engine/recommender.d.ts +52 -0
- package/dist/engine/recommender.d.ts.map +1 -0
- package/dist/engine/recommender.js +150 -0
- package/dist/engine/recommender.js.map +1 -0
- package/dist/intelligence/classifier.d.ts +19 -5
- package/dist/intelligence/classifier.d.ts.map +1 -1
- package/dist/intelligence/classifier.js +98 -20
- package/dist/intelligence/classifier.js.map +1 -1
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +5 -2
- package/dist/skills/registry.js.map +1 -1
- package/dist/web/server.d.ts +4 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +551 -0
- package/dist/web/server.js.map +1 -1
- package/dist/web/static/index.html +940 -77
- package/package.json +1 -1
|
@@ -1,27 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* UserPromptHandler — handles UserPromptSubmit hook
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Pipeline:
|
|
5
|
+
* 1. Inject one-shot context (resume, convention, history — first prompt of session)
|
|
6
|
+
* 2. Classify intent (complexity + taskType) via IntentClassifier
|
|
7
|
+
* 3. Route via AgentRouter:
|
|
8
|
+
* - route_to_agent → inject declarative strong-route directive
|
|
9
|
+
* - otherwise → no injection (Claude 走默认流程;Skill 仅通过
|
|
10
|
+
* slash command /<skill-name> 手动触发)
|
|
11
|
+
* 4. Persist routing_events row for Web UI observation
|
|
8
12
|
*/
|
|
9
13
|
import { logger } from '../../core/utils/logger.js';
|
|
14
|
+
export const INJECTION_VERSION = 'v1-declarative-2026-05-08';
|
|
10
15
|
export class UserPromptHandler {
|
|
11
16
|
classifier;
|
|
12
|
-
skills;
|
|
13
17
|
resume;
|
|
14
18
|
historyContext;
|
|
15
19
|
conventionExtractor;
|
|
20
|
+
router;
|
|
21
|
+
agents;
|
|
22
|
+
storage;
|
|
23
|
+
observer;
|
|
16
24
|
resumeInjected = new Set();
|
|
17
25
|
historyInjected = new Set();
|
|
18
26
|
conventionInjected = new Set();
|
|
19
|
-
constructor(classifier,
|
|
27
|
+
constructor(classifier, resume = null, historyContext = null, conventionExtractor = null, router = null, agents = null, storage = null, observer = null) {
|
|
20
28
|
this.classifier = classifier;
|
|
21
|
-
this.skills = skills;
|
|
22
29
|
this.resume = resume;
|
|
23
30
|
this.historyContext = historyContext;
|
|
24
31
|
this.conventionExtractor = conventionExtractor;
|
|
32
|
+
this.router = router;
|
|
33
|
+
this.agents = agents;
|
|
34
|
+
this.storage = storage;
|
|
35
|
+
this.observer = observer;
|
|
25
36
|
}
|
|
26
37
|
async handle(event) {
|
|
27
38
|
const prompt = event.user_prompt || event.tool_input?.user_prompt;
|
|
@@ -29,10 +40,10 @@ export class UserPromptHandler {
|
|
|
29
40
|
return { allow: true };
|
|
30
41
|
}
|
|
31
42
|
try {
|
|
32
|
-
// 0. Inject resume (once per session)
|
|
33
43
|
const sessionKey = `${event.session_id}:${event.project_path}`;
|
|
34
|
-
const contextParts = [];
|
|
35
|
-
const systemParts = [];
|
|
44
|
+
const contextParts = [];
|
|
45
|
+
const systemParts = [];
|
|
46
|
+
// 0a. Resume (once per session)
|
|
36
47
|
if (this.resume && !this.resumeInjected.has(sessionKey)) {
|
|
37
48
|
this.resumeInjected.add(sessionKey);
|
|
38
49
|
const resumeContent = this.resume.load(event.project_path);
|
|
@@ -42,7 +53,7 @@ export class UserPromptHandler {
|
|
|
42
53
|
this.resume.clear(event.project_path);
|
|
43
54
|
}
|
|
44
55
|
}
|
|
45
|
-
// 0b.
|
|
56
|
+
// 0b. Convention (once per session)
|
|
46
57
|
if (this.conventionExtractor && !this.conventionInjected.has(sessionKey)) {
|
|
47
58
|
this.conventionInjected.add(sessionKey);
|
|
48
59
|
const convention = this.conventionExtractor.extract(event.project_path);
|
|
@@ -51,7 +62,7 @@ export class UserPromptHandler {
|
|
|
51
62
|
logger.info('[UserPrompt] Injected project conventions');
|
|
52
63
|
}
|
|
53
64
|
}
|
|
54
|
-
// 0c.
|
|
65
|
+
// 0c. History context (once per session)
|
|
55
66
|
if (this.historyContext && !this.historyInjected.has(sessionKey)) {
|
|
56
67
|
this.historyInjected.add(sessionKey);
|
|
57
68
|
const history = this.historyContext.build(event.project_path);
|
|
@@ -62,21 +73,63 @@ export class UserPromptHandler {
|
|
|
62
73
|
}
|
|
63
74
|
// 1. Classify intent
|
|
64
75
|
const analysis = await this.classifier.classify(prompt, event.project_path);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
const source = analysis.fallbackUsed ? 'regex' : (analysis.classificationMs ? 'ai' : 'ground-truth');
|
|
77
|
+
logger.info(`[UserPrompt] Intent: complexity=${analysis.complexity} taskType=${analysis.taskType} ` +
|
|
78
|
+
`source=${source}${analysis.classificationMs ? ` (${analysis.classificationMs}ms)` : ''}`);
|
|
79
|
+
// 2. Route
|
|
80
|
+
let decision = null;
|
|
81
|
+
let routedAgentName = null;
|
|
82
|
+
let routedType = 'none';
|
|
83
|
+
if (this.router) {
|
|
84
|
+
decision = this.router.decide({ taskType: analysis.taskType, complexity: analysis.complexity }, event.session_id);
|
|
85
|
+
if (decision.action.type === 'route_to_agent') {
|
|
86
|
+
const agentName = decision.action.name;
|
|
87
|
+
const agentDef = this.agents?.get(agentName);
|
|
88
|
+
if (agentDef) {
|
|
89
|
+
routedAgentName = agentName;
|
|
90
|
+
routedType = 'agent';
|
|
91
|
+
systemParts.push(formatAgentDirective(agentName, agentDef.description));
|
|
92
|
+
logger.info(`[UserPrompt] Routed to agent: ${agentName}`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
logger.warn(`[UserPrompt] Router decided agent '${agentName}' but no definition found — falling back to skill`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// 3. (Phase 5) Skill fallback removed: UserPromptSubmit 不再自动推荐 skill。
|
|
100
|
+
// 没有匹到 agent 的 prompt 直接走 Claude 默认流程;slash command /<skill-name>
|
|
101
|
+
// 仍然可以手动触发具体 skill。
|
|
102
|
+
// 4. Persist routing_events row
|
|
103
|
+
if (this.storage) {
|
|
104
|
+
try {
|
|
105
|
+
const eventId = this.storage.writeRoutingEvent({
|
|
106
|
+
session_id: event.session_id,
|
|
107
|
+
project_path: event.project_path,
|
|
108
|
+
ts: Date.parse(event.timestamp) || Date.now(),
|
|
109
|
+
prompt,
|
|
110
|
+
intent_json: JSON.stringify(analysis),
|
|
111
|
+
routed_to_type: routedType,
|
|
112
|
+
routed_to_name: routedAgentName,
|
|
113
|
+
is_forced: routedType === 'agent' ? 1 : 0,
|
|
114
|
+
classification_ms: analysis.classificationMs ?? null,
|
|
115
|
+
fallback_used: analysis.fallbackUsed ? 1 : 0,
|
|
116
|
+
injection_version: INJECTION_VERSION,
|
|
117
|
+
experiment_id: decision?.experimentId ?? null,
|
|
118
|
+
experiment_group: decision?.groupId ?? null,
|
|
119
|
+
});
|
|
120
|
+
if (routedType === 'agent' && this.observer) {
|
|
121
|
+
this.observer.beginPending(event.session_id, eventId, routedAgentName);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
logger.warn(`[UserPrompt] Failed to persist routing_events: ${err}`);
|
|
126
|
+
}
|
|
72
127
|
}
|
|
73
128
|
const result = { allow: true };
|
|
74
|
-
if (contextParts.length > 0)
|
|
129
|
+
if (contextParts.length > 0)
|
|
75
130
|
result.additionalContext = contextParts.join('\n\n');
|
|
76
|
-
|
|
77
|
-
if (systemParts.length > 0) {
|
|
131
|
+
if (systemParts.length > 0)
|
|
78
132
|
result.systemMessage = systemParts.join('\n\n');
|
|
79
|
-
}
|
|
80
133
|
return result;
|
|
81
134
|
}
|
|
82
135
|
catch (err) {
|
|
@@ -85,4 +138,25 @@ export class UserPromptHandler {
|
|
|
85
138
|
}
|
|
86
139
|
}
|
|
87
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Declarative strong-route directive (see plan §3.4).
|
|
143
|
+
* Uses statement form + Task template + escape hatch, avoiding overtly
|
|
144
|
+
* imperative wording that triggers Claude's refusal instinct.
|
|
145
|
+
*/
|
|
146
|
+
function formatAgentDirective(agentName, agentDescription) {
|
|
147
|
+
return [
|
|
148
|
+
'━━━ Claude Forge: Agent Routing ━━━',
|
|
149
|
+
`本次任务的正确执行路径是调用 ${agentName} agent。`,
|
|
150
|
+
'',
|
|
151
|
+
'请使用 Task 工具:',
|
|
152
|
+
` subagent_type: "${agentName}"`,
|
|
153
|
+
' description: "执行用户请求的任务"',
|
|
154
|
+
' prompt: <用户原始 prompt 原样传入>',
|
|
155
|
+
'',
|
|
156
|
+
`该 agent 职责:${agentDescription}`,
|
|
157
|
+
'',
|
|
158
|
+
'若判断该任务不适用此路径,请简述原因后再自行处理(原因将被记录用于路由调优)。',
|
|
159
|
+
'━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
|
|
160
|
+
].join('\n');
|
|
161
|
+
}
|
|
88
162
|
//# sourceMappingURL=user-prompt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-prompt.js","sourceRoot":"","sources":["../../../src/daemon/handlers/user-prompt.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"user-prompt.js","sourceRoot":"","sources":["../../../src/daemon/handlers/user-prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyCH,wBAAsB,WAAW,CAAC,UAAU,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAgP5E"}
|
package/dist/daemon/index.js
CHANGED
|
@@ -25,6 +25,11 @@ import { Distiller } from '../intelligence/distiller.js';
|
|
|
25
25
|
import { HistoryContextBuilder } from '../intelligence/history-context-builder.js';
|
|
26
26
|
import { TaskSegmenter } from '../intelligence/task-segmenter.js';
|
|
27
27
|
import { SkillRegistry } from '../skills/registry.js';
|
|
28
|
+
import { AgentRegistry } from '../agents/registry.js';
|
|
29
|
+
import { AgentRouter } from '../engine/agent-router.js';
|
|
30
|
+
import { ExperimentRouter } from '../engine/experiment-router.js';
|
|
31
|
+
import { RoutingObserver } from './routing-observer.js';
|
|
32
|
+
import { AutoDisableScheduler } from './auto-disable-scheduler.js';
|
|
28
33
|
import { HistoryExporter } from './handlers/history-exporter.js';
|
|
29
34
|
import { ResumeManager } from '../claudemd/resume-manager.js';
|
|
30
35
|
import { ConventionExtractor } from '../claudemd/convention-extractor.js';
|
|
@@ -63,32 +68,58 @@ export async function startDaemon(foreground = false) {
|
|
|
63
68
|
ruleEngine.loadAll();
|
|
64
69
|
const evidenceStore = new EvidenceStore();
|
|
65
70
|
const contextBuilder = new ContextBuilder(evidenceStore);
|
|
66
|
-
|
|
71
|
+
// Classifier always runs; without AI it degrades to ground-truth + keyword fallback.
|
|
72
|
+
const classifier = new IntentClassifier(ai);
|
|
67
73
|
const qualityGate = ai ? new QualityGate(ai) : null;
|
|
68
74
|
const distiller = ai ? new Distiller(ai, storage) : null;
|
|
69
|
-
// Initialize skill registry
|
|
75
|
+
// Initialize skill registry — kept for CLI `claude-forge skills` queries.
|
|
76
|
+
// UserPromptSubmit no longer auto-recommends skills (removed in v8.15.4);
|
|
77
|
+
// skills remain available via slash command `/<skill-name>`.
|
|
70
78
|
const skillApiKey = config.skill_matching?.api_key || apiKey;
|
|
71
|
-
|
|
79
|
+
void new SkillRegistry(skillApiKey);
|
|
72
80
|
if (skillApiKey) {
|
|
73
|
-
logger.info('[Skills]
|
|
81
|
+
logger.info('[Skills] Registry loaded with semantic matching support');
|
|
74
82
|
}
|
|
75
83
|
else {
|
|
76
|
-
logger.info('[Skills]
|
|
84
|
+
logger.info('[Skills] Registry loaded (keyword matching)');
|
|
77
85
|
}
|
|
78
86
|
const exporter = new HistoryExporter(storage);
|
|
79
87
|
const resume = new ResumeManager(storage);
|
|
80
88
|
const historyContext = new HistoryContextBuilder(storage);
|
|
81
89
|
const conventionExtractor = new ConventionExtractor();
|
|
82
90
|
const taskSegmenter = new TaskSegmenter(storage);
|
|
91
|
+
// Agent routing layer
|
|
92
|
+
const agents = new AgentRegistry();
|
|
93
|
+
// Phase 5 Feature 2: let the router consult rule_states for auto-disable.
|
|
94
|
+
const isRuleDisabled = (taskType, agent) => {
|
|
95
|
+
const state = storage.getRuleState(taskType, agent);
|
|
96
|
+
return state !== null && state.disabled === 1;
|
|
97
|
+
};
|
|
98
|
+
const defaultRouter = new AgentRouter({ isRuleDisabled });
|
|
99
|
+
const experimentRouter = new ExperimentRouter({
|
|
100
|
+
storage,
|
|
101
|
+
defaultRouter,
|
|
102
|
+
isRuleDisabled,
|
|
103
|
+
});
|
|
104
|
+
const routingObserver = new RoutingObserver(storage);
|
|
105
|
+
const autoDisableScheduler = new AutoDisableScheduler(storage);
|
|
106
|
+
// Enable hot-reload for routing.yaml (Phase 3) and experiments.yaml (Phase 5)
|
|
107
|
+
defaultRouter.enableHotReload();
|
|
108
|
+
experimentRouter.enableHotReload();
|
|
109
|
+
// Start periodic auto-disable scan (Phase 5 Feature 2)
|
|
110
|
+
autoDisableScheduler.start();
|
|
83
111
|
logger.info('[Engines] Initialized: RuleEngine, ContextBuilder, EvidenceStore, ResumeManager');
|
|
84
|
-
|
|
112
|
+
logger.info('[Engines] Agent routing: AgentRegistry, AgentRouter, ExperimentRouter, RoutingObserver, AutoDisableScheduler');
|
|
113
|
+
if (ai)
|
|
85
114
|
logger.info('[Engines] AI-powered: IntentClassifier, QualityGate, Distiller');
|
|
115
|
+
else
|
|
116
|
+
logger.info('[Engines] IntentClassifier in fallback mode (no API key) — agent routing still active');
|
|
86
117
|
// ── 6. Create handlers ─────────────────────────────────────────────────────
|
|
87
118
|
const handlers = {
|
|
88
|
-
UserPromptSubmit: new UserPromptHandler(classifier
|
|
119
|
+
UserPromptSubmit: new UserPromptHandler(classifier, resume, historyContext, conventionExtractor, experimentRouter, agents, storage, routingObserver),
|
|
89
120
|
PreToolUse: new PreToolUseHandler(ruleEngine, contextBuilder),
|
|
90
|
-
PostToolUse: new PostToolUseHandler(qualityGate ?? null, storage),
|
|
91
|
-
Stop: new StopHandler(distiller ?? null, exporter, resume),
|
|
121
|
+
PostToolUse: new PostToolUseHandler(qualityGate ?? null, storage, routingObserver),
|
|
122
|
+
Stop: new StopHandler(distiller ?? null, exporter, resume, routingObserver),
|
|
92
123
|
};
|
|
93
124
|
// ── 7. Event handler ───────────────────────────────────────────────────────
|
|
94
125
|
const handleEvent = async (event) => {
|
|
@@ -115,15 +146,17 @@ export async function startDaemon(foreground = false) {
|
|
|
115
146
|
error: handled.result.allow ? undefined : handled.result.reason,
|
|
116
147
|
timestamp: Date.parse(event.timestamp) || Date.now(),
|
|
117
148
|
});
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
149
|
+
if (handled.decision.level !== 'allow' || handled.decision.rule_id) {
|
|
150
|
+
storage.writeDecision({
|
|
151
|
+
session_id: event.session_id,
|
|
152
|
+
event_id: toolEventId,
|
|
153
|
+
rule_id: handled.decision.rule_id ?? null,
|
|
154
|
+
level: handled.decision.level,
|
|
155
|
+
reason: handled.decision.reason ?? null,
|
|
156
|
+
suggestion: handled.decision.suggestion ?? null,
|
|
157
|
+
timestamp: Date.parse(event.timestamp) || Date.now(),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
127
160
|
}
|
|
128
161
|
else {
|
|
129
162
|
result = await routeEvent(event, handlers);
|
|
@@ -184,6 +217,8 @@ export async function startDaemon(foreground = false) {
|
|
|
184
217
|
port: config.web.port,
|
|
185
218
|
storage,
|
|
186
219
|
ruleEngine,
|
|
220
|
+
router: defaultRouter,
|
|
221
|
+
agents,
|
|
187
222
|
});
|
|
188
223
|
await webServer.start();
|
|
189
224
|
}
|
package/dist/daemon/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RoutingObserver — tracks in-flight routing decisions and judges whether
|
|
3
|
+
* the main Claude obeyed the injected agent recommendation.
|
|
4
|
+
*
|
|
5
|
+
* Lifecycle per session:
|
|
6
|
+
* 1. UserPromptSubmit handler: after routing decides an agent, call
|
|
7
|
+
* `beginPending(session_id, eventId, routedAgent)`.
|
|
8
|
+
* 2. PostToolUse handler: call `observeTool(session_id, tool_name, tool_input)`
|
|
9
|
+
* to classify the tool (read-only → ignore, decision-type → judge).
|
|
10
|
+
* 3. Stop handler: call `finalizePending(session_id, lastAssistantText?)` to
|
|
11
|
+
* flush any still-pending event as obeyed=NULL and optionally extract
|
|
12
|
+
* refusal_reason from Claude's last message.
|
|
13
|
+
*
|
|
14
|
+
* The 30s safety timer ensures stale pending entries are cleaned up even if
|
|
15
|
+
* no Stop arrives (e.g. daemon restart window).
|
|
16
|
+
*/
|
|
17
|
+
import type { SQLiteStorage } from '../core/storage/sqlite.js';
|
|
18
|
+
export declare class RoutingObserver {
|
|
19
|
+
private storage;
|
|
20
|
+
private pending;
|
|
21
|
+
constructor(storage: SQLiteStorage);
|
|
22
|
+
beginPending(sessionId: string, eventId: number, routedAgent: string | null): void;
|
|
23
|
+
observeTool(sessionId: string, toolName: string, toolInput: Record<string, unknown>): void;
|
|
24
|
+
/**
|
|
25
|
+
* Flush the pending event for a session (obeyed = NULL if still unset,
|
|
26
|
+
* persist downstream chain, optionally extract refusal_reason).
|
|
27
|
+
*/
|
|
28
|
+
finalizePending(sessionId: string, lastAssistantText?: string): void;
|
|
29
|
+
private timeoutPending;
|
|
30
|
+
private dropPending;
|
|
31
|
+
/** Used by tests/introspection. */
|
|
32
|
+
getPending(sessionId: string): {
|
|
33
|
+
eventId: number;
|
|
34
|
+
routedAgent: string | null;
|
|
35
|
+
} | null;
|
|
36
|
+
}
|
|
37
|
+
/** Extract refusal explanation from Claude's last message. */
|
|
38
|
+
export declare function extractRefusalReason(text: string): string | null;
|
|
39
|
+
//# sourceMappingURL=routing-observer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routing-observer.d.ts","sourceRoot":"","sources":["../../src/daemon/routing-observer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAkB/D,qBAAa,eAAe;IAGd,OAAO,CAAC,OAAO;IAF3B,OAAO,CAAC,OAAO,CAAmC;gBAE9B,OAAO,EAAE,aAAa;IAE1C,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAoBlF,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAyC1F;;;OAGG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI;IAwBpE,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,WAAW;IAOnB,mCAAmC;IACnC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI;CAItF;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAahE"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RoutingObserver — tracks in-flight routing decisions and judges whether
|
|
3
|
+
* the main Claude obeyed the injected agent recommendation.
|
|
4
|
+
*
|
|
5
|
+
* Lifecycle per session:
|
|
6
|
+
* 1. UserPromptSubmit handler: after routing decides an agent, call
|
|
7
|
+
* `beginPending(session_id, eventId, routedAgent)`.
|
|
8
|
+
* 2. PostToolUse handler: call `observeTool(session_id, tool_name, tool_input)`
|
|
9
|
+
* to classify the tool (read-only → ignore, decision-type → judge).
|
|
10
|
+
* 3. Stop handler: call `finalizePending(session_id, lastAssistantText?)` to
|
|
11
|
+
* flush any still-pending event as obeyed=NULL and optionally extract
|
|
12
|
+
* refusal_reason from Claude's last message.
|
|
13
|
+
*
|
|
14
|
+
* The 30s safety timer ensures stale pending entries are cleaned up even if
|
|
15
|
+
* no Stop arrives (e.g. daemon restart window).
|
|
16
|
+
*/
|
|
17
|
+
import { logger } from '../core/utils/logger.js';
|
|
18
|
+
const OBEYED_TIMEOUT_MS = 30_000;
|
|
19
|
+
const READ_ONLY_TOOLS = new Set([
|
|
20
|
+
'Read', 'Grep', 'Glob', 'LS', 'NotebookRead', 'WebFetch', 'WebSearch',
|
|
21
|
+
]);
|
|
22
|
+
export class RoutingObserver {
|
|
23
|
+
storage;
|
|
24
|
+
pending = new Map();
|
|
25
|
+
constructor(storage) {
|
|
26
|
+
this.storage = storage;
|
|
27
|
+
}
|
|
28
|
+
beginPending(sessionId, eventId, routedAgent) {
|
|
29
|
+
// Replace any existing pending (new prompt supersedes previous unfinished observation)
|
|
30
|
+
const prev = this.pending.get(sessionId);
|
|
31
|
+
if (prev)
|
|
32
|
+
clearTimeout(prev.timer);
|
|
33
|
+
const timer = setTimeout(() => {
|
|
34
|
+
this.timeoutPending(sessionId);
|
|
35
|
+
}, OBEYED_TIMEOUT_MS);
|
|
36
|
+
timer.unref?.();
|
|
37
|
+
this.pending.set(sessionId, {
|
|
38
|
+
eventId,
|
|
39
|
+
routedAgent,
|
|
40
|
+
t0: Date.now(),
|
|
41
|
+
timer,
|
|
42
|
+
obeyedWritten: false,
|
|
43
|
+
downstreamChain: [],
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
observeTool(sessionId, toolName, toolInput) {
|
|
47
|
+
const entry = this.pending.get(sessionId);
|
|
48
|
+
if (!entry)
|
|
49
|
+
return;
|
|
50
|
+
// Read-only tool — allow Claude's pre-investigation, don't judge yet
|
|
51
|
+
if (READ_ONLY_TOOLS.has(toolName))
|
|
52
|
+
return;
|
|
53
|
+
// Decision-type tool — judge or track downstream
|
|
54
|
+
if (!entry.obeyedWritten) {
|
|
55
|
+
const isTask = toolName === 'Task';
|
|
56
|
+
const subagentType = typeof toolInput.subagent_type === 'string' ? toolInput.subagent_type : null;
|
|
57
|
+
const matched = isTask && subagentType !== null && subagentType === entry.routedAgent;
|
|
58
|
+
const obeyed = matched ? 1 : 0;
|
|
59
|
+
try {
|
|
60
|
+
this.storage.updateRoutingEvent(entry.eventId, {
|
|
61
|
+
obeyed,
|
|
62
|
+
first_tool_name: toolName,
|
|
63
|
+
first_tool_ts: Date.now(),
|
|
64
|
+
});
|
|
65
|
+
entry.obeyedWritten = true;
|
|
66
|
+
if (matched)
|
|
67
|
+
entry.downstreamChain.push(subagentType);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
logger.warn(`[RoutingObserver] updateRoutingEvent failed: ${err}`);
|
|
71
|
+
}
|
|
72
|
+
// If it wasn't a Task call, we have our verdict — stop tracking
|
|
73
|
+
if (!isTask) {
|
|
74
|
+
this.dropPending(sessionId);
|
|
75
|
+
}
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// Already judged — track downstream Task chain
|
|
79
|
+
if (toolName === 'Task' && typeof toolInput.subagent_type === 'string') {
|
|
80
|
+
entry.downstreamChain.push(toolInput.subagent_type);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Flush the pending event for a session (obeyed = NULL if still unset,
|
|
85
|
+
* persist downstream chain, optionally extract refusal_reason).
|
|
86
|
+
*/
|
|
87
|
+
finalizePending(sessionId, lastAssistantText) {
|
|
88
|
+
const entry = this.pending.get(sessionId);
|
|
89
|
+
if (!entry)
|
|
90
|
+
return;
|
|
91
|
+
const patch = {};
|
|
92
|
+
if (!entry.obeyedWritten)
|
|
93
|
+
patch.obeyed = null;
|
|
94
|
+
if (entry.downstreamChain.length > 0) {
|
|
95
|
+
patch.downstream_task_chain = JSON.stringify(entry.downstreamChain);
|
|
96
|
+
}
|
|
97
|
+
if (lastAssistantText && (!entry.obeyedWritten || entry.routedAgent)) {
|
|
98
|
+
const reason = extractRefusalReason(lastAssistantText);
|
|
99
|
+
if (reason)
|
|
100
|
+
patch.refusal_reason = reason;
|
|
101
|
+
}
|
|
102
|
+
if (Object.keys(patch).length > 0) {
|
|
103
|
+
try {
|
|
104
|
+
this.storage.updateRoutingEvent(entry.eventId, patch);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
logger.warn(`[RoutingObserver] finalize failed: ${err}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this.dropPending(sessionId);
|
|
111
|
+
}
|
|
112
|
+
timeoutPending(sessionId) {
|
|
113
|
+
const entry = this.pending.get(sessionId);
|
|
114
|
+
if (!entry)
|
|
115
|
+
return;
|
|
116
|
+
if (!entry.obeyedWritten) {
|
|
117
|
+
try {
|
|
118
|
+
this.storage.updateRoutingEvent(entry.eventId, { obeyed: null });
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
logger.warn(`[RoutingObserver] timeout update failed: ${err}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
this.dropPending(sessionId);
|
|
125
|
+
}
|
|
126
|
+
dropPending(sessionId) {
|
|
127
|
+
const entry = this.pending.get(sessionId);
|
|
128
|
+
if (!entry)
|
|
129
|
+
return;
|
|
130
|
+
clearTimeout(entry.timer);
|
|
131
|
+
this.pending.delete(sessionId);
|
|
132
|
+
}
|
|
133
|
+
/** Used by tests/introspection. */
|
|
134
|
+
getPending(sessionId) {
|
|
135
|
+
const e = this.pending.get(sessionId);
|
|
136
|
+
return e ? { eventId: e.eventId, routedAgent: e.routedAgent } : null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** Extract refusal explanation from Claude's last message. */
|
|
140
|
+
export function extractRefusalReason(text) {
|
|
141
|
+
if (!text)
|
|
142
|
+
return null;
|
|
143
|
+
const patterns = [
|
|
144
|
+
/不适用此路径[^。\n]*[。\n]?/,
|
|
145
|
+
/不需要(?:使用|调用|借助)[^。\n]*agent[^。\n]*/i,
|
|
146
|
+
/I(?:'m| am) not going to use the \w+ agent[^.\n]*/i,
|
|
147
|
+
/Skipping the \w+ agent[^.\n]*/i,
|
|
148
|
+
];
|
|
149
|
+
for (const p of patterns) {
|
|
150
|
+
const m = text.match(p);
|
|
151
|
+
if (m)
|
|
152
|
+
return m[0].trim().slice(0, 300);
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=routing-observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routing-observer.js","sourceRoot":"","sources":["../../src/daemon/routing-observer.ts"],"names":[],"mappings":"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"}
|