@laurentenhoor/devclaw 0.1.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/LICENSE +21 -0
- package/README.md +406 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/audit.d.ts +2 -0
- package/dist/lib/audit.d.ts.map +1 -0
- package/dist/lib/audit.js +42 -0
- package/dist/lib/audit.js.map +1 -0
- package/dist/lib/binding-manager.d.ts +35 -0
- package/dist/lib/binding-manager.d.ts.map +1 -0
- package/dist/lib/binding-manager.js +88 -0
- package/dist/lib/binding-manager.js.map +1 -0
- package/dist/lib/cli.d.ts +12 -0
- package/dist/lib/cli.d.ts.map +1 -0
- package/dist/lib/cli.js +69 -0
- package/dist/lib/cli.js.map +1 -0
- package/dist/lib/dispatch.d.ts +58 -0
- package/dist/lib/dispatch.d.ts.map +1 -0
- package/dist/lib/dispatch.js +163 -0
- package/dist/lib/dispatch.js.map +1 -0
- package/dist/lib/model-selector.d.ts +21 -0
- package/dist/lib/model-selector.d.ts.map +1 -0
- package/dist/lib/model-selector.js +74 -0
- package/dist/lib/model-selector.js.map +1 -0
- package/dist/lib/notify.d.ts +54 -0
- package/dist/lib/notify.d.ts.map +1 -0
- package/dist/lib/notify.js +143 -0
- package/dist/lib/notify.js.map +1 -0
- package/dist/lib/onboarding.d.ts +5 -0
- package/dist/lib/onboarding.d.ts.map +1 -0
- package/dist/lib/onboarding.js +124 -0
- package/dist/lib/onboarding.js.map +1 -0
- package/dist/lib/projects.d.ts +64 -0
- package/dist/lib/projects.d.ts.map +1 -0
- package/dist/lib/projects.js +127 -0
- package/dist/lib/projects.js.map +1 -0
- package/dist/lib/providers/github.d.ts +23 -0
- package/dist/lib/providers/github.d.ts.map +1 -0
- package/dist/lib/providers/github.js +130 -0
- package/dist/lib/providers/github.js.map +1 -0
- package/dist/lib/providers/gitlab.d.ts +23 -0
- package/dist/lib/providers/gitlab.d.ts.map +1 -0
- package/dist/lib/providers/gitlab.js +133 -0
- package/dist/lib/providers/gitlab.js.map +1 -0
- package/dist/lib/providers/index.d.ts +12 -0
- package/dist/lib/providers/index.d.ts.map +1 -0
- package/dist/lib/providers/index.js +25 -0
- package/dist/lib/providers/index.js.map +1 -0
- package/dist/lib/providers/provider.d.ts +35 -0
- package/dist/lib/providers/provider.d.ts.map +1 -0
- package/dist/lib/providers/provider.js +13 -0
- package/dist/lib/providers/provider.js.map +1 -0
- package/dist/lib/services/health.d.ts +38 -0
- package/dist/lib/services/health.d.ts.map +1 -0
- package/dist/lib/services/health.js +100 -0
- package/dist/lib/services/health.js.map +1 -0
- package/dist/lib/services/heartbeat.d.ts +38 -0
- package/dist/lib/services/heartbeat.d.ts.map +1 -0
- package/dist/lib/services/heartbeat.js +199 -0
- package/dist/lib/services/heartbeat.js.map +1 -0
- package/dist/lib/services/pipeline.d.ts +36 -0
- package/dist/lib/services/pipeline.d.ts.map +1 -0
- package/dist/lib/services/pipeline.js +90 -0
- package/dist/lib/services/pipeline.js.map +1 -0
- package/dist/lib/services/queue.d.ts +14 -0
- package/dist/lib/services/queue.d.ts.map +1 -0
- package/dist/lib/services/queue.js +31 -0
- package/dist/lib/services/queue.js.map +1 -0
- package/dist/lib/services/tick.d.ts +62 -0
- package/dist/lib/services/tick.d.ts.map +1 -0
- package/dist/lib/services/tick.js +160 -0
- package/dist/lib/services/tick.js.map +1 -0
- package/dist/lib/setup/agent.d.ts +14 -0
- package/dist/lib/setup/agent.d.ts.map +1 -0
- package/dist/lib/setup/agent.js +72 -0
- package/dist/lib/setup/agent.js.map +1 -0
- package/dist/lib/setup/config.d.ts +22 -0
- package/dist/lib/setup/config.d.ts.map +1 -0
- package/dist/lib/setup/config.js +67 -0
- package/dist/lib/setup/config.js.map +1 -0
- package/dist/lib/setup/index.d.ts +53 -0
- package/dist/lib/setup/index.d.ts.map +1 -0
- package/dist/lib/setup/index.js +68 -0
- package/dist/lib/setup/index.js.map +1 -0
- package/dist/lib/setup/workspace.d.ts +6 -0
- package/dist/lib/setup/workspace.d.ts.map +1 -0
- package/dist/lib/setup/workspace.js +69 -0
- package/dist/lib/setup/workspace.js.map +1 -0
- package/dist/lib/templates.d.ts +9 -0
- package/dist/lib/templates.d.ts.map +1 -0
- package/dist/lib/templates.js +163 -0
- package/dist/lib/templates.js.map +1 -0
- package/dist/lib/tiers.d.ts +55 -0
- package/dist/lib/tiers.d.ts.map +1 -0
- package/dist/lib/tiers.js +74 -0
- package/dist/lib/tiers.js.map +1 -0
- package/dist/lib/tool-helpers.d.ts +44 -0
- package/dist/lib/tool-helpers.d.ts.map +1 -0
- package/dist/lib/tool-helpers.js +65 -0
- package/dist/lib/tool-helpers.js.map +1 -0
- package/dist/lib/tools/health.d.ts +28 -0
- package/dist/lib/tools/health.d.ts.map +1 -0
- package/dist/lib/tools/health.js +61 -0
- package/dist/lib/tools/health.js.map +1 -0
- package/dist/lib/tools/onboard.d.ts +24 -0
- package/dist/lib/tools/onboard.d.ts.map +1 -0
- package/dist/lib/tools/onboard.js +27 -0
- package/dist/lib/tools/onboard.js.map +1 -0
- package/dist/lib/tools/project-register.d.ts +51 -0
- package/dist/lib/tools/project-register.d.ts.map +1 -0
- package/dist/lib/tools/project-register.js +172 -0
- package/dist/lib/tools/project-register.js.map +1 -0
- package/dist/lib/tools/queue-status.test.d.ts +2 -0
- package/dist/lib/tools/queue-status.test.d.ts.map +1 -0
- package/dist/lib/tools/queue-status.test.js +48 -0
- package/dist/lib/tools/queue-status.test.js.map +1 -0
- package/dist/lib/tools/setup.d.ts +76 -0
- package/dist/lib/tools/setup.d.ts.map +1 -0
- package/dist/lib/tools/setup.js +102 -0
- package/dist/lib/tools/setup.js.map +1 -0
- package/dist/lib/tools/status.d.ts +24 -0
- package/dist/lib/tools/status.d.ts.map +1 -0
- package/dist/lib/tools/status.js +53 -0
- package/dist/lib/tools/status.js.map +1 -0
- package/dist/lib/tools/task-comment.d.ts +40 -0
- package/dist/lib/tools/task-comment.d.ts.map +1 -0
- package/dist/lib/tools/task-comment.js +84 -0
- package/dist/lib/tools/task-comment.js.map +1 -0
- package/dist/lib/tools/task-create.d.ts +54 -0
- package/dist/lib/tools/task-create.d.ts.map +1 -0
- package/dist/lib/tools/task-create.js +77 -0
- package/dist/lib/tools/task-create.js.map +1 -0
- package/dist/lib/tools/task-update.d.ts +40 -0
- package/dist/lib/tools/task-update.d.ts.map +1 -0
- package/dist/lib/tools/task-update.js +79 -0
- package/dist/lib/tools/task-update.js.map +1 -0
- package/dist/lib/tools/task-update.test.d.ts +7 -0
- package/dist/lib/tools/task-update.test.d.ts.map +1 -0
- package/dist/lib/tools/task-update.test.js +55 -0
- package/dist/lib/tools/task-update.test.js.map +1 -0
- package/dist/lib/tools/work-finish.d.ts +43 -0
- package/dist/lib/tools/work-finish.d.ts.map +1 -0
- package/dist/lib/tools/work-finish.js +77 -0
- package/dist/lib/tools/work-finish.js.map +1 -0
- package/dist/lib/tools/work-start.d.ts +39 -0
- package/dist/lib/tools/work-start.d.ts.map +1 -0
- package/dist/lib/tools/work-start.js +129 -0
- package/dist/lib/tools/work-start.js.map +1 -0
- package/dist/lib/types.d.ts +17 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +8 -0
- package/dist/lib/types.js.map +1 -0
- package/docs/ARCHITECTURE.md +662 -0
- package/docs/CONFIGURATION.md +336 -0
- package/docs/MANAGEMENT.md +120 -0
- package/docs/ONBOARDING.md +251 -0
- package/docs/QA_WORKFLOW.md +120 -0
- package/docs/ROADMAP.md +96 -0
- package/docs/TESTING.md +339 -0
- package/docs/TOOLS.md +361 -0
- package/package.json +55 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
2
|
+
/**
|
|
3
|
+
* Create a new agent via `openclaw agents add`.
|
|
4
|
+
* Cleans up .git and BOOTSTRAP.md from the workspace, updates display name.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createAgent(api: OpenClawPluginApi, name: string, channelBinding?: "telegram" | "whatsapp" | null): Promise<{
|
|
7
|
+
agentId: string;
|
|
8
|
+
workspacePath: string;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Resolve workspace path from an agent ID via OpenClaw config API.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveWorkspacePath(api: OpenClawPluginApi, agentId: string): string;
|
|
14
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../lib/setup/agent.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAI7D;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,iBAAiB,EACtB,IAAI,EAAE,MAAM,EACZ,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,GAC9C,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAQpF"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* setup/agent.ts — Agent creation and workspace resolution.
|
|
3
|
+
*/
|
|
4
|
+
import { execFile } from "node:child_process";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import fs from "node:fs/promises";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
/**
|
|
10
|
+
* Create a new agent via `openclaw agents add`.
|
|
11
|
+
* Cleans up .git and BOOTSTRAP.md from the workspace, updates display name.
|
|
12
|
+
*/
|
|
13
|
+
export async function createAgent(api, name, channelBinding) {
|
|
14
|
+
const agentId = name
|
|
15
|
+
.toLowerCase()
|
|
16
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
17
|
+
.replace(/^-|-$/g, "");
|
|
18
|
+
const args = ["agents", "add", agentId, "--non-interactive"];
|
|
19
|
+
if (channelBinding)
|
|
20
|
+
args.push("--bind", channelBinding);
|
|
21
|
+
try {
|
|
22
|
+
await execFileAsync("openclaw", args, { timeout: 30_000 });
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
throw new Error(`Failed to create agent "${name}": ${err.message}`);
|
|
26
|
+
}
|
|
27
|
+
const workspacePath = resolveWorkspacePath(api, agentId);
|
|
28
|
+
await cleanupWorkspace(workspacePath);
|
|
29
|
+
await updateAgentDisplayName(api, agentId, name);
|
|
30
|
+
return { agentId, workspacePath };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolve workspace path from an agent ID via OpenClaw config API.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveWorkspacePath(api, agentId) {
|
|
36
|
+
const config = api.runtime.config.loadConfig();
|
|
37
|
+
const agent = config.agents?.list?.find((a) => a.id === agentId);
|
|
38
|
+
if (!agent?.workspace) {
|
|
39
|
+
throw new Error(`Agent "${agentId}" not found in openclaw.json or has no workspace configured.`);
|
|
40
|
+
}
|
|
41
|
+
return agent.workspace;
|
|
42
|
+
}
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Private helpers
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
async function cleanupWorkspace(workspacePath) {
|
|
47
|
+
// openclaw agents add creates a .git dir and BOOTSTRAP.md — remove them
|
|
48
|
+
try {
|
|
49
|
+
await fs.rm(path.join(workspacePath, ".git"), { recursive: true });
|
|
50
|
+
}
|
|
51
|
+
catch { /* may not exist */ }
|
|
52
|
+
try {
|
|
53
|
+
await fs.unlink(path.join(workspacePath, "BOOTSTRAP.md"));
|
|
54
|
+
}
|
|
55
|
+
catch { /* may not exist */ }
|
|
56
|
+
}
|
|
57
|
+
async function updateAgentDisplayName(api, agentId, name) {
|
|
58
|
+
if (name === agentId)
|
|
59
|
+
return;
|
|
60
|
+
try {
|
|
61
|
+
const config = api.runtime.config.loadConfig();
|
|
62
|
+
const agent = config.agents?.list?.find((a) => a.id === agentId);
|
|
63
|
+
if (agent) {
|
|
64
|
+
agent.name = name;
|
|
65
|
+
await api.runtime.config.writeConfigFile(config);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
console.warn(`Warning: Could not update display name: ${err.message}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../lib/setup/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* setup/config.ts — Plugin config writer (openclaw.json).
|
|
3
|
+
*
|
|
4
|
+
* Handles: model level config, tool restrictions, subagent cleanup.
|
|
5
|
+
*/
|
|
6
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
7
|
+
type ModelConfig = {
|
|
8
|
+
dev: Record<string, string>;
|
|
9
|
+
qa: Record<string, string>;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Write DevClaw model level config to openclaw.json plugins section.
|
|
13
|
+
*
|
|
14
|
+
* Also configures:
|
|
15
|
+
* - Tool restrictions (deny sessions_spawn, sessions_send) for DevClaw agents
|
|
16
|
+
* - Subagent cleanup interval (30 days) to keep development sessions alive
|
|
17
|
+
*
|
|
18
|
+
* Read-modify-write to preserve existing config.
|
|
19
|
+
*/
|
|
20
|
+
export declare function writePluginConfig(api: OpenClawPluginApi, models: ModelConfig, agentId?: string, projectExecution?: "parallel" | "sequential"): Promise<void>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../lib/setup/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAG7D,KAAK,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC;AAE/E;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE,MAAM,EAChB,gBAAgB,CAAC,EAAE,UAAU,GAAG,YAAY,GAC3C,OAAO,CAAC,IAAI,CAAC,CAkBf"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { HEARTBEAT_DEFAULTS } from "../services/heartbeat.js";
|
|
2
|
+
/**
|
|
3
|
+
* Write DevClaw model level config to openclaw.json plugins section.
|
|
4
|
+
*
|
|
5
|
+
* Also configures:
|
|
6
|
+
* - Tool restrictions (deny sessions_spawn, sessions_send) for DevClaw agents
|
|
7
|
+
* - Subagent cleanup interval (30 days) to keep development sessions alive
|
|
8
|
+
*
|
|
9
|
+
* Read-modify-write to preserve existing config.
|
|
10
|
+
*/
|
|
11
|
+
export async function writePluginConfig(api, models, agentId, projectExecution) {
|
|
12
|
+
const config = api.runtime.config.loadConfig();
|
|
13
|
+
ensurePluginStructure(config);
|
|
14
|
+
config.plugins.entries.devclaw.config.models = models;
|
|
15
|
+
if (projectExecution) {
|
|
16
|
+
config.plugins.entries.devclaw.config.projectExecution = projectExecution;
|
|
17
|
+
}
|
|
18
|
+
ensureHeartbeatDefaults(config);
|
|
19
|
+
configureSubagentCleanup(config);
|
|
20
|
+
if (agentId) {
|
|
21
|
+
addToolRestrictions(config, agentId);
|
|
22
|
+
}
|
|
23
|
+
await api.runtime.config.writeConfigFile(config);
|
|
24
|
+
}
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Private helpers
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
function ensurePluginStructure(config) {
|
|
29
|
+
if (!config.plugins)
|
|
30
|
+
config.plugins = {};
|
|
31
|
+
const plugins = config.plugins;
|
|
32
|
+
if (!plugins.entries)
|
|
33
|
+
plugins.entries = {};
|
|
34
|
+
const entries = plugins.entries;
|
|
35
|
+
if (!entries.devclaw)
|
|
36
|
+
entries.devclaw = {};
|
|
37
|
+
const devclaw = entries.devclaw;
|
|
38
|
+
if (!devclaw.config)
|
|
39
|
+
devclaw.config = {};
|
|
40
|
+
}
|
|
41
|
+
function configureSubagentCleanup(config) {
|
|
42
|
+
if (!config.agents)
|
|
43
|
+
config.agents = {};
|
|
44
|
+
const agents = config.agents;
|
|
45
|
+
if (!agents.defaults)
|
|
46
|
+
agents.defaults = {};
|
|
47
|
+
const defaults = agents.defaults;
|
|
48
|
+
if (!defaults.subagents)
|
|
49
|
+
defaults.subagents = {};
|
|
50
|
+
defaults.subagents.archiveAfterMinutes = 43200;
|
|
51
|
+
}
|
|
52
|
+
function addToolRestrictions(config, agentId) {
|
|
53
|
+
const agent = config.agents?.list?.find((a) => a.id === agentId);
|
|
54
|
+
if (agent) {
|
|
55
|
+
if (!agent.tools)
|
|
56
|
+
agent.tools = {};
|
|
57
|
+
agent.tools.deny = ["sessions_spawn", "sessions_send"];
|
|
58
|
+
delete agent.tools.allow;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function ensureHeartbeatDefaults(config) {
|
|
62
|
+
const devclaw = config.plugins.entries.devclaw.config;
|
|
63
|
+
if (!devclaw.work_heartbeat) {
|
|
64
|
+
devclaw.work_heartbeat = { ...HEARTBEAT_DEFAULTS };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../lib/setup/config.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAI9D;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAsB,EACtB,MAAmB,EACnB,OAAgB,EAChB,gBAA4C;IAE5C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAA6B,CAAC;IAE1E,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAc,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;IAE/D,IAAI,gBAAgB,EAAE,CAAC;QACpB,MAAc,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;IACrF,CAAC;IAED,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAEjC,IAAI,OAAO,EAAE,CAAC;QACZ,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,MAAa,CAAC,CAAC;AAC1D,CAAC;AAED,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E,SAAS,qBAAqB,CAAC,MAA+B;IAC5D,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAkC,CAAC;IAC1D,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAkC,CAAC;IAC3D,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAkC,CAAC;IAC3D,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,wBAAwB,CAAC,MAA+B;IAC/D,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAiC,CAAC;IACxD,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAmC,CAAC;IAC5D,IAAI,CAAC,QAAQ,CAAC,SAAS;QAAE,QAAQ,CAAC,SAAS,GAAG,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAqC,CAAC,mBAAmB,GAAG,KAAK,CAAC;AAC9E,CAAC;AAED,SAAS,mBAAmB,CAAC,MAA+B,EAAE,OAAe;IAC3E,MAAM,KAAK,GAAI,MAAc,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IAC1F,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC,KAAK,CAAC,KAAK;YAAE,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;QACnC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;QACvD,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAAC,MAA+B;IAC9D,MAAM,OAAO,GAAI,MAAc,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;IAC/D,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC5B,OAAO,CAAC,cAAc,GAAG,EAAE,GAAG,kBAAkB,EAAE,CAAC;IACrD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* setup/index.ts — DevClaw setup orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Coordinates: agent creation → model config → workspace scaffolding.
|
|
5
|
+
* Used by both the `setup` tool and the `openclaw devclaw setup` CLI command.
|
|
6
|
+
*/
|
|
7
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
8
|
+
export type ModelConfig = {
|
|
9
|
+
dev: Record<string, string>;
|
|
10
|
+
qa: Record<string, string>;
|
|
11
|
+
};
|
|
12
|
+
export type SetupOpts = {
|
|
13
|
+
/** OpenClaw plugin API for config access. */
|
|
14
|
+
api: OpenClawPluginApi;
|
|
15
|
+
/** Create a new agent with this name. Mutually exclusive with agentId. */
|
|
16
|
+
newAgentName?: string;
|
|
17
|
+
/** Channel binding for new agent. Only used when newAgentName is set. */
|
|
18
|
+
channelBinding?: "telegram" | "whatsapp" | null;
|
|
19
|
+
/** Migrate channel binding from this agent ID. Only used when newAgentName and channelBinding are set. */
|
|
20
|
+
migrateFrom?: string;
|
|
21
|
+
/** Use an existing agent by ID. Mutually exclusive with newAgentName. */
|
|
22
|
+
agentId?: string;
|
|
23
|
+
/** Override workspace path (auto-detected from agent if not given). */
|
|
24
|
+
workspacePath?: string;
|
|
25
|
+
/** Model overrides per role.level. Missing levels use defaults. */
|
|
26
|
+
models?: {
|
|
27
|
+
dev?: Partial<Record<string, string>>;
|
|
28
|
+
qa?: Partial<Record<string, string>>;
|
|
29
|
+
};
|
|
30
|
+
/** Plugin-level project execution mode: parallel or sequential. Default: parallel. */
|
|
31
|
+
projectExecution?: "parallel" | "sequential";
|
|
32
|
+
};
|
|
33
|
+
export type SetupResult = {
|
|
34
|
+
agentId: string;
|
|
35
|
+
agentCreated: boolean;
|
|
36
|
+
workspacePath: string;
|
|
37
|
+
models: ModelConfig;
|
|
38
|
+
filesWritten: string[];
|
|
39
|
+
warnings: string[];
|
|
40
|
+
bindingMigrated?: {
|
|
41
|
+
from: string;
|
|
42
|
+
channel: "telegram" | "whatsapp";
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Run the full DevClaw setup.
|
|
47
|
+
*
|
|
48
|
+
* 1. Create agent (optional) or resolve existing workspace
|
|
49
|
+
* 2. Merge model config and write to openclaw.json
|
|
50
|
+
* 3. Write workspace files (AGENTS.md, HEARTBEAT.md, roles, memory)
|
|
51
|
+
*/
|
|
52
|
+
export declare function runSetup(opts: SetupOpts): Promise<SetupResult>;
|
|
53
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/setup/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAO7D,MAAM,MAAM,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC;AAEtF,MAAM,MAAM,SAAS,GAAG;IACtB,6CAA6C;IAC7C,GAAG,EAAE,iBAAiB,CAAC;IACvB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAAC;IAChD,0GAA0G;IAC1G,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,MAAM,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAAC,EAAE,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,CAAC;IACzF,sFAAsF;IACtF,gBAAgB,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,CAAC,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,UAAU,GAAG,UAAU,CAAC;KAClC,CAAC;CACH,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAYpE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { DEFAULT_MODELS } from "../tiers.js";
|
|
2
|
+
import { migrateChannelBinding } from "../binding-manager.js";
|
|
3
|
+
import { createAgent, resolveWorkspacePath } from "./agent.js";
|
|
4
|
+
import { writePluginConfig } from "./config.js";
|
|
5
|
+
import { scaffoldWorkspace } from "./workspace.js";
|
|
6
|
+
/**
|
|
7
|
+
* Run the full DevClaw setup.
|
|
8
|
+
*
|
|
9
|
+
* 1. Create agent (optional) or resolve existing workspace
|
|
10
|
+
* 2. Merge model config and write to openclaw.json
|
|
11
|
+
* 3. Write workspace files (AGENTS.md, HEARTBEAT.md, roles, memory)
|
|
12
|
+
*/
|
|
13
|
+
export async function runSetup(opts) {
|
|
14
|
+
const warnings = [];
|
|
15
|
+
const { agentId, workspacePath, agentCreated, bindingMigrated } = await resolveOrCreateAgent(opts, warnings);
|
|
16
|
+
const models = buildModelConfig(opts.models);
|
|
17
|
+
await writePluginConfig(opts.api, models, agentId, opts.projectExecution);
|
|
18
|
+
const filesWritten = await scaffoldWorkspace(workspacePath);
|
|
19
|
+
return { agentId, agentCreated, workspacePath, models, filesWritten, warnings, bindingMigrated };
|
|
20
|
+
}
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Private helpers
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
async function resolveOrCreateAgent(opts, warnings) {
|
|
25
|
+
if (opts.newAgentName) {
|
|
26
|
+
const { agentId, workspacePath } = await createAgent(opts.api, opts.newAgentName, opts.channelBinding);
|
|
27
|
+
const bindingMigrated = await tryMigrateBinding(opts, agentId, warnings);
|
|
28
|
+
return { agentId, workspacePath, agentCreated: true, bindingMigrated };
|
|
29
|
+
}
|
|
30
|
+
if (opts.agentId) {
|
|
31
|
+
const workspacePath = opts.workspacePath ?? resolveWorkspacePath(opts.api, opts.agentId);
|
|
32
|
+
return { agentId: opts.agentId, workspacePath, agentCreated: false };
|
|
33
|
+
}
|
|
34
|
+
if (opts.workspacePath) {
|
|
35
|
+
return { agentId: "unknown", workspacePath: opts.workspacePath, agentCreated: false };
|
|
36
|
+
}
|
|
37
|
+
throw new Error("Setup requires either newAgentName, agentId, or workspacePath");
|
|
38
|
+
}
|
|
39
|
+
async function tryMigrateBinding(opts, agentId, warnings) {
|
|
40
|
+
if (!opts.migrateFrom || !opts.channelBinding)
|
|
41
|
+
return undefined;
|
|
42
|
+
try {
|
|
43
|
+
await migrateChannelBinding(opts.api, opts.channelBinding, opts.migrateFrom, agentId);
|
|
44
|
+
return { from: opts.migrateFrom, channel: opts.channelBinding };
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
warnings.push(`Failed to migrate binding from "${opts.migrateFrom}": ${err.message}`);
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function buildModelConfig(overrides) {
|
|
52
|
+
const dev = { ...DEFAULT_MODELS.dev };
|
|
53
|
+
const qa = { ...DEFAULT_MODELS.qa };
|
|
54
|
+
if (overrides?.dev) {
|
|
55
|
+
for (const [level, model] of Object.entries(overrides.dev)) {
|
|
56
|
+
if (model)
|
|
57
|
+
dev[level] = model;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (overrides?.qa) {
|
|
61
|
+
for (const [level, model] of Object.entries(overrides.qa)) {
|
|
62
|
+
if (model)
|
|
63
|
+
qa[level] = model;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { dev, qa };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/setup/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write all workspace files for a DevClaw agent.
|
|
3
|
+
* Returns the list of files that were written (skips files that already exist).
|
|
4
|
+
*/
|
|
5
|
+
export declare function scaffoldWorkspace(workspacePath: string): Promise<string[]>;
|
|
6
|
+
//# sourceMappingURL=workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../../lib/setup/workspace.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAuChF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* setup/workspace.ts — Workspace file scaffolding.
|
|
3
|
+
*
|
|
4
|
+
* Writes AGENTS.md, HEARTBEAT.md, default role instructions, and projects.json.
|
|
5
|
+
*/
|
|
6
|
+
import fs from "node:fs/promises";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { AGENTS_MD_TEMPLATE, HEARTBEAT_MD_TEMPLATE, DEFAULT_DEV_INSTRUCTIONS, DEFAULT_QA_INSTRUCTIONS, } from "../templates.js";
|
|
9
|
+
/**
|
|
10
|
+
* Write all workspace files for a DevClaw agent.
|
|
11
|
+
* Returns the list of files that were written (skips files that already exist).
|
|
12
|
+
*/
|
|
13
|
+
export async function scaffoldWorkspace(workspacePath) {
|
|
14
|
+
const filesWritten = [];
|
|
15
|
+
// AGENTS.md (backup existing)
|
|
16
|
+
await backupAndWrite(path.join(workspacePath, "AGENTS.md"), AGENTS_MD_TEMPLATE);
|
|
17
|
+
filesWritten.push("AGENTS.md");
|
|
18
|
+
// HEARTBEAT.md
|
|
19
|
+
await backupAndWrite(path.join(workspacePath, "HEARTBEAT.md"), HEARTBEAT_MD_TEMPLATE);
|
|
20
|
+
filesWritten.push("HEARTBEAT.md");
|
|
21
|
+
// projects/projects.json
|
|
22
|
+
const projectsDir = path.join(workspacePath, "projects");
|
|
23
|
+
await fs.mkdir(projectsDir, { recursive: true });
|
|
24
|
+
const projectsJsonPath = path.join(projectsDir, "projects.json");
|
|
25
|
+
if (!await fileExists(projectsJsonPath)) {
|
|
26
|
+
await fs.writeFile(projectsJsonPath, JSON.stringify({ projects: {} }, null, 2) + "\n", "utf-8");
|
|
27
|
+
filesWritten.push("projects/projects.json");
|
|
28
|
+
}
|
|
29
|
+
// projects/roles/default/ (fallback role instructions)
|
|
30
|
+
const defaultRolesDir = path.join(projectsDir, "roles", "default");
|
|
31
|
+
await fs.mkdir(defaultRolesDir, { recursive: true });
|
|
32
|
+
const devRolePath = path.join(defaultRolesDir, "dev.md");
|
|
33
|
+
if (!await fileExists(devRolePath)) {
|
|
34
|
+
await fs.writeFile(devRolePath, DEFAULT_DEV_INSTRUCTIONS, "utf-8");
|
|
35
|
+
filesWritten.push("projects/roles/default/dev.md");
|
|
36
|
+
}
|
|
37
|
+
const qaRolePath = path.join(defaultRolesDir, "qa.md");
|
|
38
|
+
if (!await fileExists(qaRolePath)) {
|
|
39
|
+
await fs.writeFile(qaRolePath, DEFAULT_QA_INSTRUCTIONS, "utf-8");
|
|
40
|
+
filesWritten.push("projects/roles/default/qa.md");
|
|
41
|
+
}
|
|
42
|
+
// log/ directory (audit.log created on first write)
|
|
43
|
+
const logDir = path.join(workspacePath, "log");
|
|
44
|
+
await fs.mkdir(logDir, { recursive: true });
|
|
45
|
+
return filesWritten;
|
|
46
|
+
}
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Private helpers
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
async function backupAndWrite(filePath, content) {
|
|
51
|
+
try {
|
|
52
|
+
await fs.access(filePath);
|
|
53
|
+
await fs.copyFile(filePath, filePath + ".bak");
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
await fs.writeFile(filePath, content, "utf-8");
|
|
59
|
+
}
|
|
60
|
+
async function fileExists(filePath) {
|
|
61
|
+
try {
|
|
62
|
+
await fs.access(filePath);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../lib/setup/workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared templates for workspace files.
|
|
3
|
+
* Used by setup and project_register.
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_DEV_INSTRUCTIONS = "# DEV Worker Instructions\n\n## Context You Receive\n\nWhen you start work, you're given:\n\n- **Issue:** number, title, body, URL, labels, state\n- **Comments:** full discussion thread on the issue\n- **Assignees:** who's assigned\n- **Timestamps:** created, updated dates\n- **Project:** repo path, base branch, project name\n\nRead the comments carefully \u2014 they often contain clarifications, decisions, or scope changes that aren't in the original issue body.\n\n## Your Job\n\n- Work in a git worktree (never switch branches in the main repo)\n- Run tests before completing\n- Create an MR/PR to the base branch and merge it\n- **IMPORTANT:** Do NOT use closing keywords in PR/MR descriptions (no \"Closes #X\", \"Fixes #X\", \"Resolves #X\"). Use \"As described in issue #X\" or \"Addresses issue #X\" instead. DevClaw manages issue state \u2014 auto-closing bypasses QA.\n- Clean up the worktree after merging\n- When done, call work_finish with role \"dev\", result \"done\", and a brief summary\n- If you discover unrelated bugs, call task_create to file them\n- Do NOT call work_start, status, health, or project_register\n";
|
|
6
|
+
export declare const DEFAULT_QA_INSTRUCTIONS = "# QA Worker Instructions\n\n- Pull latest from the base branch\n- Run tests and linting\n- Verify the changes address the issue requirements\n- Check for regressions in related functionality\n- **Always** call task_comment with your review findings \u2014 even if everything looks good, leave a brief summary of what you checked\n- When done, call work_finish with role \"qa\" and one of:\n - result \"pass\" if everything looks good\n - result \"fail\" with specific issues if problems found\n - result \"refine\" if you need human input to decide\n- If you discover unrelated bugs, call task_create to file them\n- Do NOT call work_start, status, health, or project_register\n";
|
|
7
|
+
export declare const AGENTS_MD_TEMPLATE = "# AGENTS.md - Development Orchestration (DevClaw)\n\n## If You Are a Sub-Agent (DEV/QA Worker)\n\nSkip the orchestrator section. Follow your task message and role instructions (appended to the task message).\n\n### Conventions\n\n- Conventional commits: `feat:`, `fix:`, `chore:`, `refactor:`, `test:`, `docs:`\n- Include issue number: `feat: add user authentication (#12)`\n- Branch naming: `feature/<id>-<slug>` or `fix/<id>-<slug>`\n- **DEV always works in a git worktree** (never switch branches in the main repo)\n- **DEV must merge to base branch** before announcing completion\n- **Do NOT use closing keywords in PR/MR descriptions** (no \"Closes #X\", \"Fixes #X\", \"Resolves #X\"). Use \"As described in issue #X\" or \"Addresses issue #X\". DevClaw manages issue state \u2014 auto-closing bypasses QA.\n- **QA tests on the deployed version** and inspects code on the base branch\n- **QA always calls task_comment** with review findings before completing\n- Always run tests before completing\n\n### Completing Your Task\n\nWhen you are done, **call `work_finish` yourself** \u2014 do not just announce in text.\n\n- **DEV done:** `work_finish({ role: \"dev\", result: \"done\", projectGroupId: \"<from task message>\", summary: \"<brief summary>\" })`\n- **QA pass:** `work_finish({ role: \"qa\", result: \"pass\", projectGroupId: \"<from task message>\", summary: \"<brief summary>\" })`\n- **QA fail:** `work_finish({ role: \"qa\", result: \"fail\", projectGroupId: \"<from task message>\", summary: \"<specific issues>\" })`\n- **QA refine:** `work_finish({ role: \"qa\", result: \"refine\", projectGroupId: \"<from task message>\", summary: \"<what needs human input>\" })`\n\nThe `projectGroupId` is included in your task message.\n\n### Filing Follow-Up Issues\n\nIf you discover unrelated bugs or needed improvements during your work, call `task_create` to file them:\n\n`task_create({ projectGroupId: \"<from task message>\", title: \"Bug: ...\", description: \"...\" })`\n\n### Tools You Should NOT Use\n\nThese are orchestrator-only tools. Do not call them:\n- `work_start`, `status`, `health`, `project_register`\n\n---\n\n## Orchestrator\n\nYou are a **development orchestrator**. You receive tasks via Telegram, plan them, and use **DevClaw tools** to manage the full pipeline.\n\n### DevClaw Tools\n\nAll orchestration goes through these tools. You do NOT manually manage sessions, labels, or projects.json.\n\n| Tool | What it does |\n|---|---|\n| `project_register` | One-time project setup: creates labels, scaffolds role files, adds to projects.json |\n| `task_create` | Create issues from chat (bugs, features, tasks) |\n| `task_update` | Update issue title, description, or labels |\n| `status` | Task queue and worker state per project (lightweight dashboard) |\n| `health` | Scan worker health: zombies, stale workers, orphaned state. Pass fix=true to auto-fix |\n| `work_start` | End-to-end: label transition, level assignment, session create/reuse, dispatch with role instructions |\n| `work_finish` | End-to-end: label transition, state update, issue close/reopen. Ticks scheduler after completion. |\n\n### Pipeline Flow\n\n```\nPlanning \u2192 To Do \u2192 Doing \u2192 To Test \u2192 Testing \u2192 Done\n \u2193\n To Improve \u2192 Doing (fix cycle)\n \u2193\n Refining (human decision)\n```\n\nIssue labels are the single source of truth for task state.\n\n### Developer Assignment\n\nEvaluate each task and pass the appropriate developer level to `work_start`:\n\n- **junior** \u2014 trivial: typos, single-file fix, quick change\n- **medior** \u2014 standard: features, bug fixes, multi-file changes\n- **senior** \u2014 complex: architecture, system-wide refactoring, 5+ services\n- **reviewer** \u2014 QA: code inspection, validation, test runs\n\n### Picking Up Work\n\n1. Use `status` to see what's available\n2. Priority: `To Improve` (fix failures) > `To Test` (QA) > `To Do` (new work)\n3. Evaluate complexity, choose developer level\n4. Call `work_start` with `issueId`, `role`, `projectGroupId`, `level`\n5. Post the `announcement` from the tool response to Telegram\n\n### When Work Completes\n\nWorkers call `work_finish` themselves \u2014 the label transition, state update, and audit log happen atomically. After completion, `work_finish` ticks the scheduler to fill free slots:\n\n- DEV \"done\" \u2192 issue moves to \"To Test\" \u2192 scheduler dispatches QA\n- QA \"fail\" \u2192 issue moves to \"To Improve\" \u2192 scheduler dispatches DEV\n- QA \"pass\" \u2192 Done, no further dispatch\n- QA \"refine\" / blocked \u2192 needs human input\n\nThe response includes `tickPickups` showing any tasks that were auto-dispatched. Post announcements from the tool response to Telegram.\n\n### Prompt Instructions\n\nWorkers receive role-specific instructions appended to their task message. These are loaded from `projects/roles/<project-name>/<role>.md` in the workspace, falling back to `projects/roles/default/<role>.md` if no project-specific file exists. `project_register` scaffolds these files automatically \u2014 edit them to customize worker behavior per project.\n\n### Heartbeats\n\n**Do nothing.** The heartbeat service runs automatically as an internal interval-based process \u2014 zero LLM tokens. It handles health checks (zombie detection, stale workers) and queue dispatch (filling free worker slots by priority) every 60 seconds by default. Configure via `plugins.entries.devclaw.config.work_heartbeat` in openclaw.json.\n\n### Safety\n\n- Don't push to main directly\n- Don't force-push\n- Don't close issues without QA pass\n- Ask before architectural decisions affecting multiple projects\n";
|
|
8
|
+
export declare const HEARTBEAT_MD_TEMPLATE = "# HEARTBEAT.md\n\nDo nothing. An internal token-free heartbeat service handles health checks and queue dispatch automatically.\n";
|
|
9
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../lib/templates.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,wBAAwB,snCAwBpC,CAAC;AAEF,eAAO,MAAM,uBAAuB,8qBAanC,CAAC;AAEF,eAAO,MAAM,kBAAkB,ypLAkH9B,CAAC;AAEF,eAAO,MAAM,qBAAqB,qIAGjC,CAAC"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared templates for workspace files.
|
|
3
|
+
* Used by setup and project_register.
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_DEV_INSTRUCTIONS = `# DEV Worker Instructions
|
|
6
|
+
|
|
7
|
+
## Context You Receive
|
|
8
|
+
|
|
9
|
+
When you start work, you're given:
|
|
10
|
+
|
|
11
|
+
- **Issue:** number, title, body, URL, labels, state
|
|
12
|
+
- **Comments:** full discussion thread on the issue
|
|
13
|
+
- **Assignees:** who's assigned
|
|
14
|
+
- **Timestamps:** created, updated dates
|
|
15
|
+
- **Project:** repo path, base branch, project name
|
|
16
|
+
|
|
17
|
+
Read the comments carefully — they often contain clarifications, decisions, or scope changes that aren't in the original issue body.
|
|
18
|
+
|
|
19
|
+
## Your Job
|
|
20
|
+
|
|
21
|
+
- Work in a git worktree (never switch branches in the main repo)
|
|
22
|
+
- Run tests before completing
|
|
23
|
+
- Create an MR/PR to the base branch and merge it
|
|
24
|
+
- **IMPORTANT:** Do NOT use closing keywords in PR/MR descriptions (no "Closes #X", "Fixes #X", "Resolves #X"). Use "As described in issue #X" or "Addresses issue #X" instead. DevClaw manages issue state — auto-closing bypasses QA.
|
|
25
|
+
- Clean up the worktree after merging
|
|
26
|
+
- When done, call work_finish with role "dev", result "done", and a brief summary
|
|
27
|
+
- If you discover unrelated bugs, call task_create to file them
|
|
28
|
+
- Do NOT call work_start, status, health, or project_register
|
|
29
|
+
`;
|
|
30
|
+
export const DEFAULT_QA_INSTRUCTIONS = `# QA Worker Instructions
|
|
31
|
+
|
|
32
|
+
- Pull latest from the base branch
|
|
33
|
+
- Run tests and linting
|
|
34
|
+
- Verify the changes address the issue requirements
|
|
35
|
+
- Check for regressions in related functionality
|
|
36
|
+
- **Always** call task_comment with your review findings — even if everything looks good, leave a brief summary of what you checked
|
|
37
|
+
- When done, call work_finish with role "qa" and one of:
|
|
38
|
+
- result "pass" if everything looks good
|
|
39
|
+
- result "fail" with specific issues if problems found
|
|
40
|
+
- result "refine" if you need human input to decide
|
|
41
|
+
- If you discover unrelated bugs, call task_create to file them
|
|
42
|
+
- Do NOT call work_start, status, health, or project_register
|
|
43
|
+
`;
|
|
44
|
+
export const AGENTS_MD_TEMPLATE = `# AGENTS.md - Development Orchestration (DevClaw)
|
|
45
|
+
|
|
46
|
+
## If You Are a Sub-Agent (DEV/QA Worker)
|
|
47
|
+
|
|
48
|
+
Skip the orchestrator section. Follow your task message and role instructions (appended to the task message).
|
|
49
|
+
|
|
50
|
+
### Conventions
|
|
51
|
+
|
|
52
|
+
- Conventional commits: \`feat:\`, \`fix:\`, \`chore:\`, \`refactor:\`, \`test:\`, \`docs:\`
|
|
53
|
+
- Include issue number: \`feat: add user authentication (#12)\`
|
|
54
|
+
- Branch naming: \`feature/<id>-<slug>\` or \`fix/<id>-<slug>\`
|
|
55
|
+
- **DEV always works in a git worktree** (never switch branches in the main repo)
|
|
56
|
+
- **DEV must merge to base branch** before announcing completion
|
|
57
|
+
- **Do NOT use closing keywords in PR/MR descriptions** (no "Closes #X", "Fixes #X", "Resolves #X"). Use "As described in issue #X" or "Addresses issue #X". DevClaw manages issue state — auto-closing bypasses QA.
|
|
58
|
+
- **QA tests on the deployed version** and inspects code on the base branch
|
|
59
|
+
- **QA always calls task_comment** with review findings before completing
|
|
60
|
+
- Always run tests before completing
|
|
61
|
+
|
|
62
|
+
### Completing Your Task
|
|
63
|
+
|
|
64
|
+
When you are done, **call \`work_finish\` yourself** — do not just announce in text.
|
|
65
|
+
|
|
66
|
+
- **DEV done:** \`work_finish({ role: "dev", result: "done", projectGroupId: "<from task message>", summary: "<brief summary>" })\`
|
|
67
|
+
- **QA pass:** \`work_finish({ role: "qa", result: "pass", projectGroupId: "<from task message>", summary: "<brief summary>" })\`
|
|
68
|
+
- **QA fail:** \`work_finish({ role: "qa", result: "fail", projectGroupId: "<from task message>", summary: "<specific issues>" })\`
|
|
69
|
+
- **QA refine:** \`work_finish({ role: "qa", result: "refine", projectGroupId: "<from task message>", summary: "<what needs human input>" })\`
|
|
70
|
+
|
|
71
|
+
The \`projectGroupId\` is included in your task message.
|
|
72
|
+
|
|
73
|
+
### Filing Follow-Up Issues
|
|
74
|
+
|
|
75
|
+
If you discover unrelated bugs or needed improvements during your work, call \`task_create\` to file them:
|
|
76
|
+
|
|
77
|
+
\`task_create({ projectGroupId: "<from task message>", title: "Bug: ...", description: "..." })\`
|
|
78
|
+
|
|
79
|
+
### Tools You Should NOT Use
|
|
80
|
+
|
|
81
|
+
These are orchestrator-only tools. Do not call them:
|
|
82
|
+
- \`work_start\`, \`status\`, \`health\`, \`project_register\`
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Orchestrator
|
|
87
|
+
|
|
88
|
+
You are a **development orchestrator**. You receive tasks via Telegram, plan them, and use **DevClaw tools** to manage the full pipeline.
|
|
89
|
+
|
|
90
|
+
### DevClaw Tools
|
|
91
|
+
|
|
92
|
+
All orchestration goes through these tools. You do NOT manually manage sessions, labels, or projects.json.
|
|
93
|
+
|
|
94
|
+
| Tool | What it does |
|
|
95
|
+
|---|---|
|
|
96
|
+
| \`project_register\` | One-time project setup: creates labels, scaffolds role files, adds to projects.json |
|
|
97
|
+
| \`task_create\` | Create issues from chat (bugs, features, tasks) |
|
|
98
|
+
| \`task_update\` | Update issue title, description, or labels |
|
|
99
|
+
| \`status\` | Task queue and worker state per project (lightweight dashboard) |
|
|
100
|
+
| \`health\` | Scan worker health: zombies, stale workers, orphaned state. Pass fix=true to auto-fix |
|
|
101
|
+
| \`work_start\` | End-to-end: label transition, level assignment, session create/reuse, dispatch with role instructions |
|
|
102
|
+
| \`work_finish\` | End-to-end: label transition, state update, issue close/reopen. Ticks scheduler after completion. |
|
|
103
|
+
|
|
104
|
+
### Pipeline Flow
|
|
105
|
+
|
|
106
|
+
\`\`\`
|
|
107
|
+
Planning → To Do → Doing → To Test → Testing → Done
|
|
108
|
+
↓
|
|
109
|
+
To Improve → Doing (fix cycle)
|
|
110
|
+
↓
|
|
111
|
+
Refining (human decision)
|
|
112
|
+
\`\`\`
|
|
113
|
+
|
|
114
|
+
Issue labels are the single source of truth for task state.
|
|
115
|
+
|
|
116
|
+
### Developer Assignment
|
|
117
|
+
|
|
118
|
+
Evaluate each task and pass the appropriate developer level to \`work_start\`:
|
|
119
|
+
|
|
120
|
+
- **junior** — trivial: typos, single-file fix, quick change
|
|
121
|
+
- **medior** — standard: features, bug fixes, multi-file changes
|
|
122
|
+
- **senior** — complex: architecture, system-wide refactoring, 5+ services
|
|
123
|
+
- **reviewer** — QA: code inspection, validation, test runs
|
|
124
|
+
|
|
125
|
+
### Picking Up Work
|
|
126
|
+
|
|
127
|
+
1. Use \`status\` to see what's available
|
|
128
|
+
2. Priority: \`To Improve\` (fix failures) > \`To Test\` (QA) > \`To Do\` (new work)
|
|
129
|
+
3. Evaluate complexity, choose developer level
|
|
130
|
+
4. Call \`work_start\` with \`issueId\`, \`role\`, \`projectGroupId\`, \`level\`
|
|
131
|
+
5. Post the \`announcement\` from the tool response to Telegram
|
|
132
|
+
|
|
133
|
+
### When Work Completes
|
|
134
|
+
|
|
135
|
+
Workers call \`work_finish\` themselves — the label transition, state update, and audit log happen atomically. After completion, \`work_finish\` ticks the scheduler to fill free slots:
|
|
136
|
+
|
|
137
|
+
- DEV "done" → issue moves to "To Test" → scheduler dispatches QA
|
|
138
|
+
- QA "fail" → issue moves to "To Improve" → scheduler dispatches DEV
|
|
139
|
+
- QA "pass" → Done, no further dispatch
|
|
140
|
+
- QA "refine" / blocked → needs human input
|
|
141
|
+
|
|
142
|
+
The response includes \`tickPickups\` showing any tasks that were auto-dispatched. Post announcements from the tool response to Telegram.
|
|
143
|
+
|
|
144
|
+
### Prompt Instructions
|
|
145
|
+
|
|
146
|
+
Workers receive role-specific instructions appended to their task message. These are loaded from \`projects/roles/<project-name>/<role>.md\` in the workspace, falling back to \`projects/roles/default/<role>.md\` if no project-specific file exists. \`project_register\` scaffolds these files automatically — edit them to customize worker behavior per project.
|
|
147
|
+
|
|
148
|
+
### Heartbeats
|
|
149
|
+
|
|
150
|
+
**Do nothing.** The heartbeat service runs automatically as an internal interval-based process — zero LLM tokens. It handles health checks (zombie detection, stale workers) and queue dispatch (filling free worker slots by priority) every 60 seconds by default. Configure via \`plugins.entries.devclaw.config.work_heartbeat\` in openclaw.json.
|
|
151
|
+
|
|
152
|
+
### Safety
|
|
153
|
+
|
|
154
|
+
- Don't push to main directly
|
|
155
|
+
- Don't force-push
|
|
156
|
+
- Don't close issues without QA pass
|
|
157
|
+
- Ask before architectural decisions affecting multiple projects
|
|
158
|
+
`;
|
|
159
|
+
export const HEARTBEAT_MD_TEMPLATE = `# HEARTBEAT.md
|
|
160
|
+
|
|
161
|
+
Do nothing. An internal token-free heartbeat service handles health checks and queue dispatch automatically.
|
|
162
|
+
`;
|
|
163
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../lib/templates.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBvC,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;CAatC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkHjC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;CAGpC,CAAC"}
|