@haoyiyin/workflow 0.2.7 → 0.2.10

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.
@@ -1 +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"}
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,QAqG/B"}
@@ -8,6 +8,8 @@ import { classifyIntent } from "./extension/classifier.js";
8
8
  // Extension API is provided by PI at runtime
9
9
  // We use 'any' to avoid compile-time dependency
10
10
  export default function (pi) {
11
+ // Store transformed input for before_agent_start to detect
12
+ let transformedInput = null;
11
13
  // Intercept user input before processing
12
14
  pi.on("input", async (event, ctx) => {
13
15
  // Skip if user already used a slash command
@@ -16,35 +18,78 @@ export default function (pi) {
16
18
  }
17
19
  // Classify intent
18
20
  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
- };
21
+ const targetSkill = intent.skill || "quick-task";
22
+ // Determine reason for dispatch
23
+ let reason = intent.reason;
24
+ if (!intent.skill) {
25
+ const needsExternal = /^(what|how|why|when|where|who|search|find|look|weather|time|price|stock|translate)/i.test(event.text);
26
+ if (needsExternal) {
27
+ reason = "External query - needs subagent";
28
+ }
29
+ else {
30
+ reason = "Default dispatch - no direct execution allowed";
31
+ }
27
32
  }
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");
33
+ ctx.ui.notify(`[yi-workflow] Dispatching to /skill:${targetSkill} (${reason})`, "info");
34
+ // Transform to explicit skill command with instruction not to analyze
35
+ const transformedText = `=== SKILL COMMAND ===\n/skill:${targetSkill}\n\nINPUT:\n${event.text}\n\n=== DO NOT ANALYZE ===\nYou MUST call the skill above immediately. NO thinking. NO planning. NO analysis. Just call the skill.`;
36
+ // Store for before_agent_start hook
37
+ transformedInput = transformedText;
38
+ // Transform input - this will be passed to main agent
40
39
  return {
41
40
  action: "transform",
42
- text: `/skill:quick-task ${event.text}`,
41
+ text: transformedText,
43
42
  };
44
43
  });
45
44
  // Log when session starts
46
45
  pi.on("session_start", async (event, ctx) => {
47
46
  ctx.ui.notify("yi-workflow extension loaded", "info");
48
47
  });
48
+ // CRITICAL: Inject THIN DISPATCHER rules into system prompt
49
+ // This ensures main agent NEVER executes work directly
50
+ pi.on("before_agent_start", async (event, ctx) => {
51
+ const systemPrompt = event.systemPrompt || "";
52
+ // Get the user input (either from event or from transformed global)
53
+ const userInput = transformedInput || event.userInput || "";
54
+ // Detect if this input was transformed to a skill command
55
+ const isSkillCommand = userInput.startsWith("/skill:");
56
+ // Prepend THIN DISPATCHER constraints
57
+ const thinDispatcherRules = `
58
+ ╔══════════════════════════════════════════════════════════════════╗
59
+ ║ THIN DISPATCHER PROTOCOL [ABSOLUTE] ║
60
+ ╚══════════════════════════════════════════════════════════════════╝
61
+
62
+ YOU ARE A THIN DISPATCHER. YOUR ONLY JOB IS TO DISPATCH TO SKILLS.
63
+
64
+ ⚠️ ABSOLUTE RULE #1: If user input starts with "/skill:", you MUST call that skill.
65
+ ⚠️ ABSOLUTE RULE #2: You NEVER execute work yourself - only dispatch.
66
+ ⚠️ ABSOLUTE RULE #3: Tools (Read, Edit, Bash, etc.) are FORBIDDEN unless in subagent.
67
+
68
+ FORBIDDEN ACTIONS (VIOLATION = PROTOCOL BREACH):
69
+ - Reading files (use /skill:review-diff)
70
+ - Writing/editing files (use /skill:execute-plan)
71
+ - Running commands (use /skill:quick-task)
72
+ - Writing code directly (use /skill:tdd or /skill:execute-plan)
73
+ - Using any tool directly (use /skill:quick-task to dispatch subagent)
74
+
75
+ CURRENT INPUT: "${userInput}"
76
+ IS_SKILL_COMMAND: ${isSkillCommand ? "YES - MUST CALL SKILL" : "NO"}
77
+
78
+ ${isSkillCommand ? `
79
+ ╔══════════════════════════════════════════════════════════════════╗
80
+ ║ ⚠️ MANDATORY: CALL THE SKILL BELOW ⚠️ ║
81
+ ╚══════════════════════════════════════════════════════════════════╝
82
+ The input starts with "/skill:". You MUST call that skill.
83
+ DO NOT process this input as a regular conversation.
84
+ DO NOT use tools directly.
85
+ CALL THE SKILL: "${userInput.split(" ")[0]}"
86
+ ` : ""}
87
+ `;
88
+ // Prepend to system prompt
89
+ event.systemPrompt = thinDispatcherRules + "\n\n" + systemPrompt;
90
+ // Reset transformed input for next turn
91
+ transformedInput = null;
92
+ return { action: "continue" };
93
+ });
49
94
  }
50
95
  //# sourceMappingURL=pi-extension.js.map
@@ -1 +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"}
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,2DAA2D;IAC3D,IAAI,gBAAgB,GAAkB,IAAI,CAAC;IAE3C,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;QAC1C,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,IAAI,YAAY,CAAC;QAEjD,gCAAgC;QAChC,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,aAAa,GAAG,qFAAqF,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7H,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,GAAG,iCAAiC,CAAC;YAC7C,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,gDAAgD,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,GAAG,CAAC,EAAE,CAAC,MAAM,CACX,uCAAuC,WAAW,KAAK,MAAM,GAAG,EAChE,MAAM,CACP,CAAC;QAEF,sEAAsE;QACtE,MAAM,eAAe,GAAG,iCAAiC,WAAW,eAAe,KAAK,CAAC,IAAI,oIAAoI,CAAC;QAElO,oCAAoC;QACpC,gBAAgB,GAAG,eAAe,CAAC;QAEnC,sDAAsD;QACtD,OAAO;YACL,MAAM,EAAE,WAAW;YACnB,IAAI,EAAE,eAAe;SACtB,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;IAEH,4DAA4D;IAC5D,uDAAuD;IACvD,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,KAAK,EAAE,KAAU,EAAE,GAAQ,EAAE,EAAE;QACzD,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC;QAE9C,oEAAoE;QACpE,MAAM,SAAS,GAAG,gBAAgB,IAAI,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;QAE5D,0DAA0D;QAC1D,MAAM,cAAc,GAAG,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAEvD,sCAAsC;QACtC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;kBAkBd,SAAS;oBACP,cAAc,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,IAAI;;EAEjE,cAAc,CAAC,CAAC,CAAC;;;;;;;mBAOA,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACzC,CAAC,CAAC,CAAC,EAAE;CACL,CAAC;QAEE,2BAA2B;QAC3B,KAAK,CAAC,YAAY,GAAG,mBAAmB,GAAG,MAAM,GAAG,YAAY,CAAC;QAEjE,wCAAwC;QACxC,gBAAgB,GAAG,IAAI,CAAC;QAExB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haoyiyin/workflow",
3
- "version": "0.2.7",
3
+ "version": "0.2.10",
4
4
  "type": "module",
5
5
  "description": "Production workflow skills for planning, executing, reviewing, and finishing coding-agent work",
6
6
  "main": "./dist/index.js",
@@ -10,6 +10,9 @@ import { classifyIntent } from "./extension/classifier.js";
10
10
  // Extension API is provided by PI at runtime
11
11
  // We use 'any' to avoid compile-time dependency
12
12
  export default function (pi: any) {
13
+ // Store transformed input for before_agent_start to detect
14
+ let transformedInput: string | null = null;
15
+
13
16
  // Intercept user input before processing
14
17
  pi.on("input", async (event: any, ctx: any) => {
15
18
  // Skip if user already used a slash command
@@ -19,45 +22,34 @@ export default function (pi: any) {
19
22
 
20
23
  // Classify intent
21
24
  const intent = classifyIntent(event.text);
25
+ const targetSkill = intent.skill || "quick-task";
22
26
 
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
- };
27
+ // Determine reason for dispatch
28
+ let reason = intent.reason;
29
+ if (!intent.skill) {
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
+ reason = "External query - needs subagent";
33
+ } else {
34
+ reason = "Default dispatch - no direct execution allowed";
35
+ }
50
36
  }
51
37
 
52
- // Block direct execution with explanation
53
38
  ctx.ui.notify(
54
- `[yi-workflow] ⚠️ THIN DISPATCHER: I cannot execute directly. Please use /skill:name or rephrase your request.`,
55
- "warning"
39
+ `[yi-workflow] Dispatching to /skill:${targetSkill} (${reason})`,
40
+ "info"
56
41
  );
57
42
 
43
+ // Transform to explicit skill command with instruction not to analyze
44
+ const transformedText = `=== SKILL COMMAND ===\n/skill:${targetSkill}\n\nINPUT:\n${event.text}\n\n=== DO NOT ANALYZE ===\nYou MUST call the skill above immediately. NO thinking. NO planning. NO analysis. Just call the skill.`;
45
+
46
+ // Store for before_agent_start hook
47
+ transformedInput = transformedText;
48
+
49
+ // Transform input - this will be passed to main agent
58
50
  return {
59
51
  action: "transform",
60
- text: `/skill:quick-task ${event.text}`,
52
+ text: transformedText,
61
53
  };
62
54
  });
63
55
 
@@ -65,4 +57,57 @@ export default function (pi: any) {
65
57
  pi.on("session_start", async (event: any, ctx: any) => {
66
58
  ctx.ui.notify("yi-workflow extension loaded", "info");
67
59
  });
60
+
61
+ // CRITICAL: Inject THIN DISPATCHER rules into system prompt
62
+ // This ensures main agent NEVER executes work directly
63
+ pi.on("before_agent_start", async (event: any, ctx: any) => {
64
+ const systemPrompt = event.systemPrompt || "";
65
+
66
+ // Get the user input (either from event or from transformed global)
67
+ const userInput = transformedInput || event.userInput || "";
68
+
69
+ // Detect if this input was transformed to a skill command
70
+ const isSkillCommand = userInput.startsWith("/skill:");
71
+
72
+ // Prepend THIN DISPATCHER constraints
73
+ const thinDispatcherRules = `
74
+ ╔══════════════════════════════════════════════════════════════════╗
75
+ ║ THIN DISPATCHER PROTOCOL [ABSOLUTE] ║
76
+ ╚══════════════════════════════════════════════════════════════════╝
77
+
78
+ YOU ARE A THIN DISPATCHER. YOUR ONLY JOB IS TO DISPATCH TO SKILLS.
79
+
80
+ ⚠️ ABSOLUTE RULE #1: If user input starts with "/skill:", you MUST call that skill.
81
+ ⚠️ ABSOLUTE RULE #2: You NEVER execute work yourself - only dispatch.
82
+ ⚠️ ABSOLUTE RULE #3: Tools (Read, Edit, Bash, etc.) are FORBIDDEN unless in subagent.
83
+
84
+ FORBIDDEN ACTIONS (VIOLATION = PROTOCOL BREACH):
85
+ - Reading files (use /skill:review-diff)
86
+ - Writing/editing files (use /skill:execute-plan)
87
+ - Running commands (use /skill:quick-task)
88
+ - Writing code directly (use /skill:tdd or /skill:execute-plan)
89
+ - Using any tool directly (use /skill:quick-task to dispatch subagent)
90
+
91
+ CURRENT INPUT: "${userInput}"
92
+ IS_SKILL_COMMAND: ${isSkillCommand ? "YES - MUST CALL SKILL" : "NO"}
93
+
94
+ ${isSkillCommand ? `
95
+ ╔══════════════════════════════════════════════════════════════════╗
96
+ ║ ⚠️ MANDATORY: CALL THE SKILL BELOW ⚠️ ║
97
+ ╚══════════════════════════════════════════════════════════════════╝
98
+ The input starts with "/skill:". You MUST call that skill.
99
+ DO NOT process this input as a regular conversation.
100
+ DO NOT use tools directly.
101
+ CALL THE SKILL: "${userInput.split(" ")[0]}"
102
+ ` : ""}
103
+ `;
104
+
105
+ // Prepend to system prompt
106
+ event.systemPrompt = thinDispatcherRules + "\n\n" + systemPrompt;
107
+
108
+ // Reset transformed input for next turn
109
+ transformedInput = null;
110
+
111
+ return { action: "continue" };
112
+ });
68
113
  }