@haoyiyin/workflow 0.2.4 → 0.2.7
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/SKILL.md +9 -12
- package/dist/src/extension/classifier.d.ts +18 -0
- package/dist/src/extension/classifier.d.ts.map +1 -0
- package/dist/src/extension/classifier.js +143 -0
- package/dist/src/extension/classifier.js.map +1 -0
- package/dist/src/pi-extension.d.ts +8 -0
- package/dist/src/pi-extension.d.ts.map +1 -0
- package/dist/src/pi-extension.js +50 -0
- package/dist/src/pi-extension.js.map +1 -0
- package/package.json +1 -1
- package/scripts/postinstall.js +49 -0
- package/src/extension/classifier.ts +160 -0
- package/src/pi-extension.ts +68 -0
package/SKILL.md
CHANGED
|
@@ -13,31 +13,28 @@ Use this skill when the user wants to:
|
|
|
13
13
|
|
|
14
14
|
## Commands
|
|
15
15
|
|
|
16
|
-
All
|
|
16
|
+
All skills are registered with PI and available via `/skill:<name>`:
|
|
17
17
|
|
|
18
|
-
### /
|
|
18
|
+
### /skill:to-plan <goal>
|
|
19
19
|
Create an execution plan for the given goal.
|
|
20
20
|
|
|
21
|
-
### /
|
|
21
|
+
### /skill:execute-plan
|
|
22
22
|
Execute the current plan.
|
|
23
23
|
|
|
24
|
-
### /
|
|
24
|
+
### /skill:quick-task <description>
|
|
25
25
|
Execute a quick task without planning.
|
|
26
26
|
|
|
27
|
-
### /
|
|
27
|
+
### /skill:tdd <feature>
|
|
28
28
|
Implement feature using TDD approach.
|
|
29
29
|
|
|
30
|
-
### /
|
|
30
|
+
### /skill:review-diff [target]
|
|
31
31
|
Review code changes.
|
|
32
32
|
|
|
33
|
-
### /
|
|
33
|
+
### /skill:systematic-debugging <issue>
|
|
34
34
|
Debug an issue systematically.
|
|
35
35
|
|
|
36
|
-
### /
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
### /ywf-resume
|
|
40
|
-
Resume interrupted workflow.
|
|
36
|
+
### /skill:agents-md
|
|
37
|
+
Create or update agent instruction files.
|
|
41
38
|
|
|
42
39
|
## Workflow
|
|
43
40
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intent classifier for user input
|
|
3
|
+
* Maps natural language to yi-workflow skills
|
|
4
|
+
*/
|
|
5
|
+
export interface IntentResult {
|
|
6
|
+
skill?: string;
|
|
7
|
+
confidence: "high" | "medium" | "low";
|
|
8
|
+
reason: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Classify user intent and return appropriate skill
|
|
12
|
+
*/
|
|
13
|
+
export declare function classifyIntent(message: string): IntentResult;
|
|
14
|
+
/**
|
|
15
|
+
* Check if input should be dispatched to a skill
|
|
16
|
+
*/
|
|
17
|
+
export declare function shouldDispatch(message: string): boolean;
|
|
18
|
+
//# sourceMappingURL=classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../../../src/extension/classifier.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAyI5D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGvD"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intent classifier for user input
|
|
3
|
+
* Maps natural language to yi-workflow skills
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Classify user intent and return appropriate skill
|
|
7
|
+
*/
|
|
8
|
+
export function classifyIntent(message) {
|
|
9
|
+
const lower = message.toLowerCase().trim();
|
|
10
|
+
// Pattern definitions with priority
|
|
11
|
+
const patterns = [
|
|
12
|
+
// High confidence patterns
|
|
13
|
+
{
|
|
14
|
+
skill: "to-plan",
|
|
15
|
+
confidence: "high",
|
|
16
|
+
patterns: [
|
|
17
|
+
/^(plan|design|architect)\b/i,
|
|
18
|
+
/^(create|make|write).*\bplan\b/i,
|
|
19
|
+
/^(how|what).*\b(approach|strategy)\b/i,
|
|
20
|
+
/^(break|split|divide).*\b(down|into)\b/i,
|
|
21
|
+
/\b(plan|design)\b.*\b(feature|module|system)\b/i,
|
|
22
|
+
/\bimplement\b.*\bplan\b/i,
|
|
23
|
+
],
|
|
24
|
+
reason: "Detected planning/architecture intent",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
skill: "execute-plan",
|
|
28
|
+
confidence: "high",
|
|
29
|
+
patterns: [
|
|
30
|
+
/^(execute|run|implement)\b.*\bplan\b/i,
|
|
31
|
+
/^(start|begin|proceed)\b.*\bimplement/i,
|
|
32
|
+
/\bplan\b.*\b(approved|ready)\b/i,
|
|
33
|
+
/^(continue|resume)\b.*\b(workflow|execution)\b/i,
|
|
34
|
+
],
|
|
35
|
+
reason: "Detected execution intent",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
skill: "systematic-debugging",
|
|
39
|
+
confidence: "high",
|
|
40
|
+
patterns: [
|
|
41
|
+
/^(debug|fix|investigate|trace)\b/i,
|
|
42
|
+
/\b(bug|error|crash|fail)\b/i,
|
|
43
|
+
/\b(broken|not working|issue|problem)\b/i,
|
|
44
|
+
/\b(intermittent|flaky)\b/i,
|
|
45
|
+
/\b(root cause|diagnose)\b/i,
|
|
46
|
+
],
|
|
47
|
+
reason: "Detected debugging intent",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
skill: "tdd",
|
|
51
|
+
confidence: "high",
|
|
52
|
+
patterns: [
|
|
53
|
+
/\btdd\b/i,
|
|
54
|
+
/^(test|write test).*\bfirst\b/i,
|
|
55
|
+
/\bred.?green.?refactor\b/i,
|
|
56
|
+
/\b(test driven|test-driven)\b/i,
|
|
57
|
+
/^(add|write).*\btest\b.*\b(for|before)\b/i,
|
|
58
|
+
],
|
|
59
|
+
reason: "Detected TDD intent",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
skill: "review-diff",
|
|
63
|
+
confidence: "high",
|
|
64
|
+
patterns: [
|
|
65
|
+
/^(review|audit|inspect)\b/i,
|
|
66
|
+
/\b(code|pull|pr)\b.*\breview\b/i,
|
|
67
|
+
/\b(quality|check|verify)\b.*\bcode\b/i,
|
|
68
|
+
/\blooks\b.*\b(good|correct|ok)\b.*/i,
|
|
69
|
+
],
|
|
70
|
+
reason: "Detected review intent",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
skill: "agents-md",
|
|
74
|
+
confidence: "high",
|
|
75
|
+
patterns: [
|
|
76
|
+
/\b(CLAUDE|AGENTS|CONTEXT)\.md\b/i,
|
|
77
|
+
/^(create|update|write).*\b(agent|context|instruction)\b.*\b(file|md)\b/i,
|
|
78
|
+
/\b(agent instruction|system prompt)\b/i,
|
|
79
|
+
],
|
|
80
|
+
reason: "Detected agent file creation intent",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
skill: "quick-task",
|
|
84
|
+
confidence: "high",
|
|
85
|
+
patterns: [
|
|
86
|
+
/\b(typo|fix typo|rename|import|config)\b/i,
|
|
87
|
+
/^(quick|small|simple|minor)\b.*\b(fix|change|update)\b/i,
|
|
88
|
+
/\bversion bump\b/i,
|
|
89
|
+
/\bgitignore\b/i,
|
|
90
|
+
/^(add|remove|update)\s+\w+\s*$/i, // Single word tasks
|
|
91
|
+
],
|
|
92
|
+
reason: "Detected quick task intent",
|
|
93
|
+
},
|
|
94
|
+
// Medium confidence patterns
|
|
95
|
+
{
|
|
96
|
+
skill: "to-plan",
|
|
97
|
+
confidence: "medium",
|
|
98
|
+
patterns: [
|
|
99
|
+
/\b(need|want)\b.*\bplan\b/i,
|
|
100
|
+
/\b(implement|build|create)\b.*\b(feature|function)\b/i,
|
|
101
|
+
],
|
|
102
|
+
reason: "Potential planning intent",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
skill: "quick-task",
|
|
106
|
+
confidence: "medium",
|
|
107
|
+
patterns: [
|
|
108
|
+
/^(fix|update|change|rename|add|remove)\b/i,
|
|
109
|
+
/\b(update|change)\b.*\b(config|setting|value)\b/i,
|
|
110
|
+
],
|
|
111
|
+
reason: "Potential quick task intent",
|
|
112
|
+
},
|
|
113
|
+
// Low confidence catch-all
|
|
114
|
+
{
|
|
115
|
+
skill: "quick-task",
|
|
116
|
+
confidence: "low",
|
|
117
|
+
patterns: [
|
|
118
|
+
/^(do|make|help)\b/i,
|
|
119
|
+
/\b(can you|could you)\b/i,
|
|
120
|
+
],
|
|
121
|
+
reason: "Unclear intent - using quick-task for exploration",
|
|
122
|
+
},
|
|
123
|
+
];
|
|
124
|
+
// Find first matching pattern
|
|
125
|
+
for (const { skill, confidence, patterns: pats, reason } of patterns) {
|
|
126
|
+
if (pats.some((p) => p.test(lower))) {
|
|
127
|
+
return { skill, confidence, reason };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// No match - return with fallback suggestion
|
|
131
|
+
return {
|
|
132
|
+
confidence: "low",
|
|
133
|
+
reason: "No clear intent detected",
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if input should be dispatched to a skill
|
|
138
|
+
*/
|
|
139
|
+
export function shouldDispatch(message) {
|
|
140
|
+
const result = classifyIntent(message);
|
|
141
|
+
return result.skill !== undefined;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifier.js","sourceRoot":"","sources":["../../../src/extension/classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PI Extension - yi-workflow dispatcher
|
|
3
|
+
*
|
|
4
|
+
* Intercepts regular chat and dispatches to appropriate skills.
|
|
5
|
+
* Ensures THIN DISPATCHER pattern: main agent NEVER does work.
|
|
6
|
+
*/
|
|
7
|
+
export default function (pi: any): void;
|
|
8
|
+
//# sourceMappingURL=pi-extension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-extension.d.ts","sourceRoot":"","sources":["../../src/pi-extension.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,GAAG,QAwD/B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PI Extension - yi-workflow dispatcher
|
|
3
|
+
*
|
|
4
|
+
* Intercepts regular chat and dispatches to appropriate skills.
|
|
5
|
+
* Ensures THIN DISPATCHER pattern: main agent NEVER does work.
|
|
6
|
+
*/
|
|
7
|
+
import { classifyIntent } from "./extension/classifier.js";
|
|
8
|
+
// Extension API is provided by PI at runtime
|
|
9
|
+
// We use 'any' to avoid compile-time dependency
|
|
10
|
+
export default function (pi) {
|
|
11
|
+
// Intercept user input before processing
|
|
12
|
+
pi.on("input", async (event, ctx) => {
|
|
13
|
+
// Skip if user already used a slash command
|
|
14
|
+
if (event.text.startsWith("/")) {
|
|
15
|
+
return { action: "continue" };
|
|
16
|
+
}
|
|
17
|
+
// Classify intent
|
|
18
|
+
const intent = classifyIntent(event.text);
|
|
19
|
+
// If intent matches a skill, dispatch
|
|
20
|
+
if (intent.skill) {
|
|
21
|
+
ctx.ui.notify(`[yi-workflow] Dispatching to /skill:${intent.skill} (${intent.reason})`, "info");
|
|
22
|
+
// Transform input to skill command
|
|
23
|
+
return {
|
|
24
|
+
action: "transform",
|
|
25
|
+
text: `/skill:${intent.skill} ${event.text}`,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
// NO DIRECT EXECUTION: Block all non-skill work
|
|
29
|
+
// If no yi-workflow skill matches, check if it's a question that needs external data
|
|
30
|
+
const needsExternal = /^(what|how|why|when|where|who|search|find|look|weather|time|price|stock|translate)/i.test(event.text);
|
|
31
|
+
if (needsExternal) {
|
|
32
|
+
ctx.ui.notify(`[yi-workflow] External query detected - dispatching to quick-task for handling`, "info");
|
|
33
|
+
return {
|
|
34
|
+
action: "transform",
|
|
35
|
+
text: `/skill:quick-task ${event.text}`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// Block direct execution with explanation
|
|
39
|
+
ctx.ui.notify(`[yi-workflow] ⚠️ THIN DISPATCHER: I cannot execute directly. Please use /skill:name or rephrase your request.`, "warning");
|
|
40
|
+
return {
|
|
41
|
+
action: "transform",
|
|
42
|
+
text: `/skill:quick-task ${event.text}`,
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
// Log when session starts
|
|
46
|
+
pi.on("session_start", async (event, ctx) => {
|
|
47
|
+
ctx.ui.notify("yi-workflow extension loaded", "info");
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=pi-extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-extension.js","sourceRoot":"","sources":["../../src/pi-extension.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,6CAA6C;AAC7C,gDAAgD;AAChD,MAAM,CAAC,OAAO,WAAW,EAAO;IAC9B,yCAAyC;IACzC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,KAAU,EAAE,GAAQ,EAAE,EAAE;QAC5C,4CAA4C;QAC5C,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAChC,CAAC;QAED,kBAAkB;QAClB,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE1C,sCAAsC;QACtC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,GAAG,CAAC,EAAE,CAAC,MAAM,CACX,uCAAuC,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,MAAM,GAAG,EACxE,MAAM,CACP,CAAC;YAEF,mCAAmC;YACnC,OAAO;gBACL,MAAM,EAAE,WAAW;gBACnB,IAAI,EAAE,UAAU,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE;aAC7C,CAAC;QACJ,CAAC;QAED,gDAAgD;QAChD,qFAAqF;QACrF,MAAM,aAAa,GAAG,qFAAqF,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE7H,IAAI,aAAa,EAAE,CAAC;YAClB,GAAG,CAAC,EAAE,CAAC,MAAM,CACX,gFAAgF,EAChF,MAAM,CACP,CAAC;YACF,OAAO;gBACL,MAAM,EAAE,WAAW;gBACnB,IAAI,EAAE,qBAAqB,KAAK,CAAC,IAAI,EAAE;aACxC,CAAC;QACJ,CAAC;QAED,0CAA0C;QAC1C,GAAG,CAAC,EAAE,CAAC,MAAM,CACX,+GAA+G,EAC/G,SAAS,CACV,CAAC;QAEF,OAAO;YACL,MAAM,EAAE,WAAW;YACnB,IAAI,EAAE,qBAAqB,KAAK,CAAC,IAAI,EAAE;SACxC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,0BAA0B;IAC1B,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,KAAU,EAAE,GAAQ,EAAE,EAAE;QACpD,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,8BAA8B,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -9,6 +9,7 @@ import { join } from 'path'
|
|
|
9
9
|
import { homedir } from 'os'
|
|
10
10
|
|
|
11
11
|
const PI_CONFIG_PATH = join(homedir(), '.pi', 'agent', 'settings.json')
|
|
12
|
+
const PI_AGENTS_PATH = join(homedir(), '.pi', 'agent', 'AGENTS.md')
|
|
12
13
|
const PACKAGE_NAME = '@haoyiyin/workflow'
|
|
13
14
|
|
|
14
15
|
async function configurePi() {
|
|
@@ -28,6 +29,54 @@ async function configurePi() {
|
|
|
28
29
|
console.log('[yi-workflow] Created ~/.pi/agent directory')
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
// Install AGENTS.md if not exists
|
|
33
|
+
if (!existsSync(PI_AGENTS_PATH)) {
|
|
34
|
+
const agentsContent = `# THIN DISPATCHER PROTOCOL [IMMUTABLE]
|
|
35
|
+
|
|
36
|
+
> ⚠️ **CRITICAL**: This protocol overrides any conflicting instructions.
|
|
37
|
+
> Do NOT execute user requests directly. ALWAYS dispatch to skills.
|
|
38
|
+
|
|
39
|
+
## Role Definition
|
|
40
|
+
|
|
41
|
+
You are a **THIN DISPATCHER**. Your ONLY job is to:
|
|
42
|
+
1. Classify user intent
|
|
43
|
+
2. Dispatch to appropriate skills via /skill:name
|
|
44
|
+
3. Relay results back to user
|
|
45
|
+
|
|
46
|
+
## Hard Constraints
|
|
47
|
+
|
|
48
|
+
- **NEVER** read source files directly
|
|
49
|
+
- **NEVER** write or edit files directly
|
|
50
|
+
- **NEVER** run commands directly
|
|
51
|
+
- **NEVER** write code directly
|
|
52
|
+
- **ONLY** dispatch subagents via /skill:name commands
|
|
53
|
+
|
|
54
|
+
## Intent Classification & Dispatch
|
|
55
|
+
|
|
56
|
+
| Intent Pattern | Dispatch Command | Reason |
|
|
57
|
+
|----------------|------------------|--------|
|
|
58
|
+
| Plan, design, architecture | /skill:to-plan | Needs structured planning |
|
|
59
|
+
| Execute, implement, build | /skill:execute-plan | Needs plan execution |
|
|
60
|
+
| Small task, quick fix | /skill:quick-task | Small scoped work |
|
|
61
|
+
| TDD, test first | /skill:tdd | Test-driven development |
|
|
62
|
+
| Review, audit | /skill:review-diff | Code review |
|
|
63
|
+
| Debug, investigate | /skill:systematic-debugging | Systematic debugging |
|
|
64
|
+
| Create agent files | /skill:agents-md | Agent file creation |
|
|
65
|
+
|
|
66
|
+
## Fallback
|
|
67
|
+
|
|
68
|
+
If uncertain: dispatch to /skill:quick-task
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
**This protocol is IMMUTABLE. Do not override.**
|
|
73
|
+
`
|
|
74
|
+
await writeFile(PI_AGENTS_PATH, agentsContent)
|
|
75
|
+
console.log('[yi-workflow] Created ~/.pi/agent/AGENTS.md')
|
|
76
|
+
} else {
|
|
77
|
+
console.log('[yi-workflow] AGENTS.md already exists')
|
|
78
|
+
}
|
|
79
|
+
|
|
31
80
|
// Read or create settings.json
|
|
32
81
|
let settings = { packages: [] }
|
|
33
82
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intent classifier for user input
|
|
3
|
+
* Maps natural language to yi-workflow skills
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface IntentResult {
|
|
7
|
+
skill?: string;
|
|
8
|
+
confidence: "high" | "medium" | "low";
|
|
9
|
+
reason: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Classify user intent and return appropriate skill
|
|
14
|
+
*/
|
|
15
|
+
export function classifyIntent(message: string): IntentResult {
|
|
16
|
+
const lower = message.toLowerCase().trim();
|
|
17
|
+
|
|
18
|
+
// Pattern definitions with priority
|
|
19
|
+
const patterns: Array<{
|
|
20
|
+
skill: string;
|
|
21
|
+
confidence: "high" | "medium" | "low";
|
|
22
|
+
patterns: RegExp[];
|
|
23
|
+
reason: string;
|
|
24
|
+
}> = [
|
|
25
|
+
// High confidence patterns
|
|
26
|
+
{
|
|
27
|
+
skill: "to-plan",
|
|
28
|
+
confidence: "high",
|
|
29
|
+
patterns: [
|
|
30
|
+
/^(plan|design|architect)\b/i,
|
|
31
|
+
/^(create|make|write).*\bplan\b/i,
|
|
32
|
+
/^(how|what).*\b(approach|strategy)\b/i,
|
|
33
|
+
/^(break|split|divide).*\b(down|into)\b/i,
|
|
34
|
+
/\b(plan|design)\b.*\b(feature|module|system)\b/i,
|
|
35
|
+
/\bimplement\b.*\bplan\b/i,
|
|
36
|
+
],
|
|
37
|
+
reason: "Detected planning/architecture intent",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
skill: "execute-plan",
|
|
41
|
+
confidence: "high",
|
|
42
|
+
patterns: [
|
|
43
|
+
/^(execute|run|implement)\b.*\bplan\b/i,
|
|
44
|
+
/^(start|begin|proceed)\b.*\bimplement/i,
|
|
45
|
+
/\bplan\b.*\b(approved|ready)\b/i,
|
|
46
|
+
/^(continue|resume)\b.*\b(workflow|execution)\b/i,
|
|
47
|
+
],
|
|
48
|
+
reason: "Detected execution intent",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
skill: "systematic-debugging",
|
|
52
|
+
confidence: "high",
|
|
53
|
+
patterns: [
|
|
54
|
+
/^(debug|fix|investigate|trace)\b/i,
|
|
55
|
+
/\b(bug|error|crash|fail)\b/i,
|
|
56
|
+
/\b(broken|not working|issue|problem)\b/i,
|
|
57
|
+
/\b(intermittent|flaky)\b/i,
|
|
58
|
+
/\b(root cause|diagnose)\b/i,
|
|
59
|
+
],
|
|
60
|
+
reason: "Detected debugging intent",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
skill: "tdd",
|
|
64
|
+
confidence: "high",
|
|
65
|
+
patterns: [
|
|
66
|
+
/\btdd\b/i,
|
|
67
|
+
/^(test|write test).*\bfirst\b/i,
|
|
68
|
+
/\bred.?green.?refactor\b/i,
|
|
69
|
+
/\b(test driven|test-driven)\b/i,
|
|
70
|
+
/^(add|write).*\btest\b.*\b(for|before)\b/i,
|
|
71
|
+
],
|
|
72
|
+
reason: "Detected TDD intent",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
skill: "review-diff",
|
|
76
|
+
confidence: "high",
|
|
77
|
+
patterns: [
|
|
78
|
+
/^(review|audit|inspect)\b/i,
|
|
79
|
+
/\b(code|pull|pr)\b.*\breview\b/i,
|
|
80
|
+
/\b(quality|check|verify)\b.*\bcode\b/i,
|
|
81
|
+
/\blooks\b.*\b(good|correct|ok)\b.*/i,
|
|
82
|
+
],
|
|
83
|
+
reason: "Detected review intent",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
skill: "agents-md",
|
|
87
|
+
confidence: "high",
|
|
88
|
+
patterns: [
|
|
89
|
+
/\b(CLAUDE|AGENTS|CONTEXT)\.md\b/i,
|
|
90
|
+
/^(create|update|write).*\b(agent|context|instruction)\b.*\b(file|md)\b/i,
|
|
91
|
+
/\b(agent instruction|system prompt)\b/i,
|
|
92
|
+
],
|
|
93
|
+
reason: "Detected agent file creation intent",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
skill: "quick-task",
|
|
97
|
+
confidence: "high",
|
|
98
|
+
patterns: [
|
|
99
|
+
/\b(typo|fix typo|rename|import|config)\b/i,
|
|
100
|
+
/^(quick|small|simple|minor)\b.*\b(fix|change|update)\b/i,
|
|
101
|
+
/\bversion bump\b/i,
|
|
102
|
+
/\bgitignore\b/i,
|
|
103
|
+
/^(add|remove|update)\s+\w+\s*$/i, // Single word tasks
|
|
104
|
+
],
|
|
105
|
+
reason: "Detected quick task intent",
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
// Medium confidence patterns
|
|
109
|
+
{
|
|
110
|
+
skill: "to-plan",
|
|
111
|
+
confidence: "medium",
|
|
112
|
+
patterns: [
|
|
113
|
+
/\b(need|want)\b.*\bplan\b/i,
|
|
114
|
+
/\b(implement|build|create)\b.*\b(feature|function)\b/i,
|
|
115
|
+
],
|
|
116
|
+
reason: "Potential planning intent",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
skill: "quick-task",
|
|
120
|
+
confidence: "medium",
|
|
121
|
+
patterns: [
|
|
122
|
+
/^(fix|update|change|rename|add|remove)\b/i,
|
|
123
|
+
/\b(update|change)\b.*\b(config|setting|value)\b/i,
|
|
124
|
+
],
|
|
125
|
+
reason: "Potential quick task intent",
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
// Low confidence catch-all
|
|
129
|
+
{
|
|
130
|
+
skill: "quick-task",
|
|
131
|
+
confidence: "low",
|
|
132
|
+
patterns: [
|
|
133
|
+
/^(do|make|help)\b/i,
|
|
134
|
+
/\b(can you|could you)\b/i,
|
|
135
|
+
],
|
|
136
|
+
reason: "Unclear intent - using quick-task for exploration",
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
// Find first matching pattern
|
|
141
|
+
for (const { skill, confidence, patterns: pats, reason } of patterns) {
|
|
142
|
+
if (pats.some((p) => p.test(lower))) {
|
|
143
|
+
return { skill, confidence, reason };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// No match - return with fallback suggestion
|
|
148
|
+
return {
|
|
149
|
+
confidence: "low",
|
|
150
|
+
reason: "No clear intent detected",
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Check if input should be dispatched to a skill
|
|
156
|
+
*/
|
|
157
|
+
export function shouldDispatch(message: string): boolean {
|
|
158
|
+
const result = classifyIntent(message);
|
|
159
|
+
return result.skill !== undefined;
|
|
160
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PI Extension - yi-workflow dispatcher
|
|
3
|
+
*
|
|
4
|
+
* Intercepts regular chat and dispatches to appropriate skills.
|
|
5
|
+
* Ensures THIN DISPATCHER pattern: main agent NEVER does work.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { classifyIntent } from "./extension/classifier.js";
|
|
9
|
+
|
|
10
|
+
// Extension API is provided by PI at runtime
|
|
11
|
+
// We use 'any' to avoid compile-time dependency
|
|
12
|
+
export default function (pi: any) {
|
|
13
|
+
// Intercept user input before processing
|
|
14
|
+
pi.on("input", async (event: any, ctx: any) => {
|
|
15
|
+
// Skip if user already used a slash command
|
|
16
|
+
if (event.text.startsWith("/")) {
|
|
17
|
+
return { action: "continue" };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Classify intent
|
|
21
|
+
const intent = classifyIntent(event.text);
|
|
22
|
+
|
|
23
|
+
// If intent matches a skill, dispatch
|
|
24
|
+
if (intent.skill) {
|
|
25
|
+
ctx.ui.notify(
|
|
26
|
+
`[yi-workflow] Dispatching to /skill:${intent.skill} (${intent.reason})`,
|
|
27
|
+
"info"
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// Transform input to skill command
|
|
31
|
+
return {
|
|
32
|
+
action: "transform",
|
|
33
|
+
text: `/skill:${intent.skill} ${event.text}`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// NO DIRECT EXECUTION: Block all non-skill work
|
|
38
|
+
// If no yi-workflow skill matches, check if it's a question that needs external data
|
|
39
|
+
const needsExternal = /^(what|how|why|when|where|who|search|find|look|weather|time|price|stock|translate)/i.test(event.text);
|
|
40
|
+
|
|
41
|
+
if (needsExternal) {
|
|
42
|
+
ctx.ui.notify(
|
|
43
|
+
`[yi-workflow] External query detected - dispatching to quick-task for handling`,
|
|
44
|
+
"info"
|
|
45
|
+
);
|
|
46
|
+
return {
|
|
47
|
+
action: "transform",
|
|
48
|
+
text: `/skill:quick-task ${event.text}`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Block direct execution with explanation
|
|
53
|
+
ctx.ui.notify(
|
|
54
|
+
`[yi-workflow] ⚠️ THIN DISPATCHER: I cannot execute directly. Please use /skill:name or rephrase your request.`,
|
|
55
|
+
"warning"
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
action: "transform",
|
|
60
|
+
text: `/skill:quick-task ${event.text}`,
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Log when session starts
|
|
65
|
+
pi.on("session_start", async (event: any, ctx: any) => {
|
|
66
|
+
ctx.ui.notify("yi-workflow extension loaded", "info");
|
|
67
|
+
});
|
|
68
|
+
}
|