c0de-agent 1.1.0 → 1.2.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/core/index.d.ts +1 -0
- package/dist/core/index.js +1 -0
- package/dist/core/workflow.d.ts +25 -0
- package/dist/core/workflow.js +98 -0
- package/dist/server/routes/chat.js +7 -0
- package/package.json +1 -1
package/dist/core/index.d.ts
CHANGED
|
@@ -11,3 +11,4 @@ export { clearSteering, drainSteering, injectSteering } from './steering.js';
|
|
|
11
11
|
export type { CollectedToolCall, ToolCallResult } from './tool-exec.js';
|
|
12
12
|
export { executeToolCall, executeToolCalls, partitionByConflict } from './tool-exec.js';
|
|
13
13
|
export type { AgentConfig, AgentDependencies, AgentError, AgentEvent, AgentState, AgentStatus, CommandContext, CommandResult, LLMSegment, PendingToolCall, ProjectInfo, PromptContext, SlashCommand, TokenBudget, } from './types.js';
|
|
14
|
+
export { containsWorkflow, WORKFLOW_NOTICE } from './workflow.js';
|
package/dist/core/index.js
CHANGED
|
@@ -9,3 +9,4 @@ export { buildSystemPrompt } from './prompt.js';
|
|
|
9
9
|
export { builtinCommands, createSlashRegistry, parseSlashInput } from './slash.js';
|
|
10
10
|
export { clearSteering, drainSteering, injectSteering } from './steering.js';
|
|
11
11
|
export { executeToolCall, executeToolCalls, partitionByConflict } from './tool-exec.js';
|
|
12
|
+
export { containsWorkflow, WORKFLOW_NOTICE } from './workflow.js';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "workflowz" keyword support — Dynamic Workflow(spec: dynamic-workflow-design)。
|
|
3
|
+
*
|
|
4
|
+
* 用户在消息中包含独立单词 `workflowz` 时:
|
|
5
|
+
* 1. 后端检测到关键词(prose 感知,忽略代码块/路径/大小写变体)
|
|
6
|
+
* 2. 向当轮注入一条隐藏 system 通知(steering),引导模型用 `task` 工具批量 fan-out
|
|
7
|
+
* 做确定性的多子 agent 工作流分解
|
|
8
|
+
*
|
|
9
|
+
* 复刻自 oh-my-pi 的 modes/workflow.ts,适配 c0de-agent 的 task 工具 schema:
|
|
10
|
+
* - 批量模式:`{ subagent_type, context, tasks: [{ prompt, description? }] }`
|
|
11
|
+
* - 单任务模式:`{ subagent_type?, prompt, description? }`
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* 判断 `text` 是否在 prose 中包含独立关键词 "workflowz"
|
|
15
|
+
* (小写、空白分隔)——不在代码块、行内代码或路径中。
|
|
16
|
+
*
|
|
17
|
+
* 简化版 prose 检测:移除 ``` 代码块和 `行内代码` 后再匹配。
|
|
18
|
+
*/
|
|
19
|
+
export declare function containsWorkflow(text: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* 工作流通知:注入为 steering system 消息,引导模型用 task 工具做批量 fan-out。
|
|
22
|
+
*
|
|
23
|
+
* 适配 c0de-agent 的 task 工具 schema(subagent_type + context + tasks[])。
|
|
24
|
+
*/
|
|
25
|
+
export declare const WORKFLOW_NOTICE = "<workflow-notice>\nThe user's message contains the **workflowz** keyword: drive this task as a deterministic multi-subagent workflow. Use the `task` tool for batched fan-out \u2014 to be comprehensive (decompose and cover in parallel), to be confident (independent perspectives and adversarial checks before you commit), or to take on scale one context can't hold (audits, migrations, broad sweeps). This overrides any default tendency to do the whole task inline when fanning out would be more thorough.\n\n<when>\nWorth it when the task benefits from decomposition + parallel coverage, or from independent/adversarial cross-checking. For a quick lookup or single edit, just do it directly \u2014 don't spin up agents. Scout inline first (list the files, scope the diff, find the call sites) to discover the work list, then fan out over it. Common shapes:\n- **Understand** \u2014 parallel readers over subsystems \u2192 structured map.\n- **Design** \u2014 independent approaches \u2192 scored synthesis.\n- **Review** \u2014 split dimensions \u2192 find per dimension \u2192 adversarially verify each finding.\n- **Research** \u2014 multi-modal sweep \u2192 deep-read the hits \u2192 synthesize.\n- **Migrate** \u2014 discover sites \u2192 transform each \u2192 verify.\n</when>\n\n<task-contract>\nCall `task` once per independent fan-out batch using the batch form:\n\n task({\n subagent_type: \"coder\",\n context: \"shared background all subagents need\",\n tasks: [\n { prompt: \"specific assignment for agent 1\", description: \"short label\" },\n { prompt: \"specific assignment for agent 2\", description: \"short label\" },\n ]\n })\n\nAvailable subagent types: `general` (full tools, recursive), `coder` (implementation), `researcher` (read-only scout), `reviewer` (code review). Pick the type that matches each task's intent.\n\n`context` carries shared background prepended to every subagent's prompt \u2014 put the shared contract, conventions, and coordination rules here.\n\nEach task in `tasks[]` must be self-contained:\n- `prompt`: exact target (files, symbols, subsystem) + what to do + acceptance criteria\n- `description`: short label for the UI\n\nEach subagent runs in an isolated session and returns its result via the `yield` tool. Subagents skip formatters, linters, and project-wide tests \u2014 the parent runs shared proof once after all results return.\n</task-contract>\n\n<structure>\nDecompose first, then batch the independent leaves:\n\n task({\n subagent_type: \"coder\",\n context: \"# Goal\\nImplement feature X across the codebase\\n# Constraints\\nFollow existing patterns...\\n# Contract\\nReturn findings as structured data...\",\n tasks: [\n { prompt: \"# Target\\nsrc/auth/login.ts\\n# Change\\nAdd rate limiting to login endpoint\\n# Acceptance\\nRate limiter works, tests pass\", description: \"Login rate limiting\" },\n { prompt: \"# Target\\nsrc/auth/signup.ts\\n# Change\\nAdd input validation\\n# Acceptance\\nValidation blocks invalid emails\", description: \"Signup validation\" },\n ]\n })\n\nPrefer one wide batch over serial calls when work items do not share files. If tasks overlap, have agents coordinate before editing.\n</structure>\n\n<patterns>\n- **Adversarial verify** \u2014 dispatch skeptical reviewers with distinct targets, then keep only findings you can verify against source.\n- **Perspective-diverse review** \u2014 use separate correctness, security, performance roles instead of identical reviewers.\n- **Completeness critic** \u2014 after the first batch, dispatch one read-only critic that asks what was missed.\n- **No silent caps** \u2014 if you bound coverage (top-N, sampling), state what was dropped and why.\n- **Parent owns closure** \u2014 subagents return evidence; the parent reads it, resolves contradictions, runs proof, and makes the final decision.\n</patterns>\n\n<execution>\n- Capture multi-phase workflow state in the visible todo system when available.\n- Batch independent subagents in one `task` call.\n- Give every subagent a narrow target, explicit non-goals, and a concrete return packet.\n- After fan-out returns, read the results, patch or decide, and run the shared gate.\n- Keep going until the task is closed \u2014 returned fan-out is a step, not a stopping point.\n</execution>\n</workflow-notice>";
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "workflowz" keyword support — Dynamic Workflow(spec: dynamic-workflow-design)。
|
|
3
|
+
*
|
|
4
|
+
* 用户在消息中包含独立单词 `workflowz` 时:
|
|
5
|
+
* 1. 后端检测到关键词(prose 感知,忽略代码块/路径/大小写变体)
|
|
6
|
+
* 2. 向当轮注入一条隐藏 system 通知(steering),引导模型用 `task` 工具批量 fan-out
|
|
7
|
+
* 做确定性的多子 agent 工作流分解
|
|
8
|
+
*
|
|
9
|
+
* 复刻自 oh-my-pi 的 modes/workflow.ts,适配 c0de-agent 的 task 工具 schema:
|
|
10
|
+
* - 批量模式:`{ subagent_type, context, tasks: [{ prompt, description? }] }`
|
|
11
|
+
* - 单任务模式:`{ subagent_type?, prompt, description? }`
|
|
12
|
+
*/
|
|
13
|
+
// 检测:小写关键词,两侧为空白或字符串边界。非全局,`.test` 无状态。
|
|
14
|
+
const WORKFLOW_WORD = /(?<!\S)workflowz(?!\S)/;
|
|
15
|
+
/**
|
|
16
|
+
* 判断 `text` 是否在 prose 中包含独立关键词 "workflowz"
|
|
17
|
+
* (小写、空白分隔)——不在代码块、行内代码或路径中。
|
|
18
|
+
*
|
|
19
|
+
* 简化版 prose 检测:移除 ``` 代码块和 `行内代码` 后再匹配。
|
|
20
|
+
*/
|
|
21
|
+
export function containsWorkflow(text) {
|
|
22
|
+
// 移除 ``` ... ``` 代码块
|
|
23
|
+
const withoutBlocks = text.replace(/```[\s\S]*?```/g, '');
|
|
24
|
+
// 移除 `行内代码`
|
|
25
|
+
const withoutInline = withoutBlocks.replace(/`[^`]*`/g, '');
|
|
26
|
+
return WORKFLOW_WORD.test(withoutInline);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 工作流通知:注入为 steering system 消息,引导模型用 task 工具做批量 fan-out。
|
|
30
|
+
*
|
|
31
|
+
* 适配 c0de-agent 的 task 工具 schema(subagent_type + context + tasks[])。
|
|
32
|
+
*/
|
|
33
|
+
export const WORKFLOW_NOTICE = `<workflow-notice>
|
|
34
|
+
The user's message contains the **workflowz** keyword: drive this task as a deterministic multi-subagent workflow. Use the \`task\` tool for batched fan-out — to be comprehensive (decompose and cover in parallel), to be confident (independent perspectives and adversarial checks before you commit), or to take on scale one context can't hold (audits, migrations, broad sweeps). This overrides any default tendency to do the whole task inline when fanning out would be more thorough.
|
|
35
|
+
|
|
36
|
+
<when>
|
|
37
|
+
Worth it when the task benefits from decomposition + parallel coverage, or from independent/adversarial cross-checking. For a quick lookup or single edit, just do it directly — don't spin up agents. Scout inline first (list the files, scope the diff, find the call sites) to discover the work list, then fan out over it. Common shapes:
|
|
38
|
+
- **Understand** — parallel readers over subsystems → structured map.
|
|
39
|
+
- **Design** — independent approaches → scored synthesis.
|
|
40
|
+
- **Review** — split dimensions → find per dimension → adversarially verify each finding.
|
|
41
|
+
- **Research** — multi-modal sweep → deep-read the hits → synthesize.
|
|
42
|
+
- **Migrate** — discover sites → transform each → verify.
|
|
43
|
+
</when>
|
|
44
|
+
|
|
45
|
+
<task-contract>
|
|
46
|
+
Call \`task\` once per independent fan-out batch using the batch form:
|
|
47
|
+
|
|
48
|
+
task({
|
|
49
|
+
subagent_type: "coder",
|
|
50
|
+
context: "shared background all subagents need",
|
|
51
|
+
tasks: [
|
|
52
|
+
{ prompt: "specific assignment for agent 1", description: "short label" },
|
|
53
|
+
{ prompt: "specific assignment for agent 2", description: "short label" },
|
|
54
|
+
]
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
Available subagent types: \`general\` (full tools, recursive), \`coder\` (implementation), \`researcher\` (read-only scout), \`reviewer\` (code review). Pick the type that matches each task's intent.
|
|
58
|
+
|
|
59
|
+
\`context\` carries shared background prepended to every subagent's prompt — put the shared contract, conventions, and coordination rules here.
|
|
60
|
+
|
|
61
|
+
Each task in \`tasks[]\` must be self-contained:
|
|
62
|
+
- \`prompt\`: exact target (files, symbols, subsystem) + what to do + acceptance criteria
|
|
63
|
+
- \`description\`: short label for the UI
|
|
64
|
+
|
|
65
|
+
Each subagent runs in an isolated session and returns its result via the \`yield\` tool. Subagents skip formatters, linters, and project-wide tests — the parent runs shared proof once after all results return.
|
|
66
|
+
</task-contract>
|
|
67
|
+
|
|
68
|
+
<structure>
|
|
69
|
+
Decompose first, then batch the independent leaves:
|
|
70
|
+
|
|
71
|
+
task({
|
|
72
|
+
subagent_type: "coder",
|
|
73
|
+
context: "# Goal\\nImplement feature X across the codebase\\n# Constraints\\nFollow existing patterns...\\n# Contract\\nReturn findings as structured data...",
|
|
74
|
+
tasks: [
|
|
75
|
+
{ prompt: "# Target\\nsrc/auth/login.ts\\n# Change\\nAdd rate limiting to login endpoint\\n# Acceptance\\nRate limiter works, tests pass", description: "Login rate limiting" },
|
|
76
|
+
{ prompt: "# Target\\nsrc/auth/signup.ts\\n# Change\\nAdd input validation\\n# Acceptance\\nValidation blocks invalid emails", description: "Signup validation" },
|
|
77
|
+
]
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
Prefer one wide batch over serial calls when work items do not share files. If tasks overlap, have agents coordinate before editing.
|
|
81
|
+
</structure>
|
|
82
|
+
|
|
83
|
+
<patterns>
|
|
84
|
+
- **Adversarial verify** — dispatch skeptical reviewers with distinct targets, then keep only findings you can verify against source.
|
|
85
|
+
- **Perspective-diverse review** — use separate correctness, security, performance roles instead of identical reviewers.
|
|
86
|
+
- **Completeness critic** — after the first batch, dispatch one read-only critic that asks what was missed.
|
|
87
|
+
- **No silent caps** — if you bound coverage (top-N, sampling), state what was dropped and why.
|
|
88
|
+
- **Parent owns closure** — subagents return evidence; the parent reads it, resolves contradictions, runs proof, and makes the final decision.
|
|
89
|
+
</patterns>
|
|
90
|
+
|
|
91
|
+
<execution>
|
|
92
|
+
- Capture multi-phase workflow state in the visible todo system when available.
|
|
93
|
+
- Batch independent subagents in one \`task\` call.
|
|
94
|
+
- Give every subagent a narrow target, explicit non-goals, and a concrete return packet.
|
|
95
|
+
- After fan-out returns, read the results, patch or decide, and run the shared gate.
|
|
96
|
+
- Keep going until the task is closed — returned fan-out is a step, not a stopping point.
|
|
97
|
+
</execution>
|
|
98
|
+
</workflow-notice>`;
|
|
@@ -4,6 +4,8 @@ import { streamSSE } from 'hono/streaming';
|
|
|
4
4
|
import { createAgent, runAgent } from '../../core/agent.js';
|
|
5
5
|
import { compactContext } from '../../core/loop.js';
|
|
6
6
|
import { createSlashRegistry, parseSlashInput } from '../../core/slash.js';
|
|
7
|
+
import { injectSteering } from '../../core/steering.js';
|
|
8
|
+
import { containsWorkflow, WORKFLOW_NOTICE } from '../../core/workflow.js';
|
|
7
9
|
import { getProject } from '../../project/project.js';
|
|
8
10
|
import { getLLMSegments, getSession, updateSessionLastRun } from '../../session/session.js';
|
|
9
11
|
import { upsertFileSnapshot } from '../../session/snapshot.js';
|
|
@@ -253,6 +255,11 @@ function createChatRoute(ctx) {
|
|
|
253
255
|
startedAt: runStartedAt,
|
|
254
256
|
});
|
|
255
257
|
ctx.agentManager.register({ sessionId, state, deps });
|
|
258
|
+
// workflowz 关键词检测:用户消息包含独立关键词时注入工作流通知(steering),
|
|
259
|
+
// 引导模型用 task 工具批量 fan-out 做确定性多子 agent 分解。
|
|
260
|
+
if (containsWorkflow(message)) {
|
|
261
|
+
injectSteering(state, WORKFLOW_NOTICE);
|
|
262
|
+
}
|
|
256
263
|
// 客户端断开时中止 agent
|
|
257
264
|
stream.onAbort(() => {
|
|
258
265
|
ctx.agentManager.abort(sessionId);
|