@betrue/openclaw-claude-code-plugin 1.0.9 → 1.0.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.
- package/README.md +32 -14
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,12 +21,21 @@ openclaw gateway restart
|
|
|
21
21
|
|
|
22
22
|
### 2. Configure notifications (minimal)
|
|
23
23
|
|
|
24
|
-
Add to `~/.openclaw/openclaw.json
|
|
24
|
+
Add to `~/.openclaw/openclaw.json`:
|
|
25
25
|
|
|
26
|
-
```
|
|
26
|
+
```jsonc
|
|
27
27
|
{
|
|
28
|
-
"
|
|
29
|
-
|
|
28
|
+
"plugins": {
|
|
29
|
+
"entries": {
|
|
30
|
+
"openclaw-claude-code-plugin": {
|
|
31
|
+
"enabled": true,
|
|
32
|
+
"config": {
|
|
33
|
+
"fallbackChannel": "telegram|my-bot|123456789",
|
|
34
|
+
"maxSessions": 5
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
30
39
|
}
|
|
31
40
|
```
|
|
32
41
|
|
|
@@ -124,7 +133,7 @@ Foreground sessions stream full output in real time. Background sessions only se
|
|
|
124
133
|
|
|
125
134
|
## Configuration
|
|
126
135
|
|
|
127
|
-
Set values in `~/.openclaw/openclaw.json` under `plugins.
|
|
136
|
+
Set values in `~/.openclaw/openclaw.json` under `plugins.entries["openclaw-claude-code-plugin"].config`.
|
|
128
137
|
|
|
129
138
|
### Essential parameters
|
|
130
139
|
|
|
@@ -140,16 +149,25 @@ Set values in `~/.openclaw/openclaw.json` under `plugins.config["openclaw-claude
|
|
|
140
149
|
|
|
141
150
|
### Example
|
|
142
151
|
|
|
143
|
-
```
|
|
152
|
+
```jsonc
|
|
144
153
|
{
|
|
145
|
-
"
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
154
|
+
"plugins": {
|
|
155
|
+
"entries": {
|
|
156
|
+
"openclaw-claude-code-plugin": {
|
|
157
|
+
"enabled": true,
|
|
158
|
+
"config": {
|
|
159
|
+
"maxSessions": 3,
|
|
160
|
+
"defaultBudgetUsd": 10,
|
|
161
|
+
"defaultModel": "sonnet",
|
|
162
|
+
"permissionMode": "bypassPermissions",
|
|
163
|
+
"fallbackChannel": "telegram|main-bot|123456789",
|
|
164
|
+
"agentChannels": {
|
|
165
|
+
"/home/user/agent-seo": "telegram|seo-bot|123456789",
|
|
166
|
+
"/home/user/agent-main": "telegram|main-bot|123456789"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
153
171
|
}
|
|
154
172
|
}
|
|
155
173
|
```
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ var ci=Object.create;var Jt=Object.defineProperty;var mi=Object.getOwnPropertyDe
|
|
|
4
4
|
`)}]};let R=e.agentId||Ns(p);if(R&&!e.agentId&&console.warn(`[claude-launch] Using resolveAgentId fallback for agentId="${R}" \u2014 this may be an account alias, not the real agent ID`),R){let Ue=(0,Sn.join)((0,Es.homedir)(),".openclaw","openclaw.json"),ct=!1,pr;try{if((0,at.existsSync)(Ue)){let On=(0,at.readFileSync)(Ue,"utf-8"),fr=JSON.parse(On)?.agents?.list;if(Array.isArray(fr)){let wn=fr.find(ui=>ui.id===R);wn&&wn.heartbeat!=null&&(ct=!0,pr=wn.heartbeat.every)}}}catch(On){console.log(`[claude-launch] Failed to read openclaw config at ${Ue}: ${On.message}`)}if(!ct)return console.log(`[claude-launch] Heartbeat not configured for agent "${R}" \u2014 blocking launch`),{isError:!0,content:[{type:"text",text:["ERROR: Launch blocked \u2014 no heartbeat configured for this agent.","",'Claude Code sessions require heartbeat to be enabled for automatic "waiting for input" notifications.',"","You must configure the heartbeat FIRST. Here's what to do:","",`1. Edit ~/.openclaw/openclaw.json and add heartbeat config for agent "${R}":`,"",` jq '.agents.list |= map(if .id == "${R}" then . + {"heartbeat": {"every": "60m", "target": "last"}} else . end)' ~/.openclaw/openclaw.json > /tmp/openclaw-updated.json && mv /tmp/openclaw-updated.json ~/.openclaw/openclaw.json`,"","2. Verify the config was applied:","",` cat ~/.openclaw/openclaw.json | jq '.agents.list[] | select(.id == "${R}") | .heartbeat'`,"","3. Launch a Claude Code session to restart the Gateway and wake you back:",""," claude_launch(",' prompt="STEP 1: Restart Gateway to activate heartbeat: openclaw gateway restart'," STEP 2: Wait 5 seconds",` STEP 3: Wake the agent: openclaw agent --agent ${R} --message 'Heartbeat configured, continuing task'`,' STEP 4: Continue the original task: [USER_TASK]",',' name="setup-heartbeat"'," )"].join(`
|
|
5
5
|
`)}]};if(pr==="5s")return console.log(`[claude-launch] Heartbeat interval too short (5s) for agent "${R}" \u2014 blocking launch`),{isError:!0,content:[{type:"text",text:["ERROR: Launch blocked \u2014 heartbeat interval too short (5s).","","A heartbeat interval of 5s wastes tokens unnecessarily. Targeted agent messages wake you instantly, so the heartbeat interval only affects regular polling.","","Fix the heartbeat interval to 60m:","",` jq '.agents.list |= map(if .id == "${R}" then .heartbeat.every = "60m" else . end)' ~/.openclaw/openclaw.json > /tmp/openclaw-updated.json && mv /tmp/openclaw-updated.json ~/.openclaw/openclaw.json`,"","Then ask the user to restart the gateway. Do NOT restart the gateway yourself \u2014 only the user can do this safely. After the user confirms the restart, retry your launch."].join(`
|
|
6
6
|
`)}]}}let re=(0,Sn.join)(p,"HEARTBEAT.md"),De=!1;try{if((0,at.existsSync)(re)){let Ue=(0,at.readFileSync)(re,"utf-8");/^(\s|#.*)*$/.test(Ue)||(De=!0)}}catch(Ue){console.log(`[claude-launch] Failed to read HEARTBEAT.md at ${re}: ${Ue.message}`)}if(!De)return console.log(`[claude-launch] HEARTBEAT.md missing or empty at ${re} \u2014 blocking launch`),{isError:!0,content:[{type:"text",text:["ERROR: Launch blocked \u2014 no HEARTBEAT.md file found or file is effectively empty.","","Claude Code sessions require a HEARTBEAT.md with real content as a safety-net fallback.","The plugin wakes you instantly via targeted agent messages when sessions need attention,","but the heartbeat acts as a 60m backup in case a wake message is lost.","","You must create HEARTBEAT.md FIRST. Here's what to do:","",`1. Create ${p}/HEARTBEAT.md with this content:`,"",`cat > ${p}/HEARTBEAT.md << 'EOF'`,"# Heartbeat Agent","","## Check Claude Code sessions (safety-net fallback)","Note: The plugin sends targeted wake messages instantly when sessions need attention.","This heartbeat is a 60m backup in case a wake message was lost.","","Si des sessions Claude Code sont en attente (waiting for input) :","1. `claude_sessions` pour lister les sessions actives","2. Si session waiting \u2192 `claude_output(session)` pour voir la question","3. Traiter ou notifier l'utilisateur","","Sinon \u2192 HEARTBEAT_OK","EOF","","2. Verify the heartbeat frequency is set to 60m:","","cat ~/.openclaw/openclaw.json | jq '.agents.list[] | .heartbeat.every'","",'If NOT "60m", update it:',"",`jq '.agents.list |= map(.heartbeat.every = "60m")' ~/.openclaw/openclaw.json > /tmp/openclaw-updated.json && mv /tmp/openclaw-updated.json ~/.openclaw/openclaw.json`,"","3. Launch Claude Code to restart Gateway:",""," claude_launch(",' prompt="STEP 1: Restart Gateway: openclaw gateway restart'," STEP 2: Wait 5s"," STEP 3: Wake agent: openclaw agent --message 'HEARTBEAT.md configured'",' STEP 4: Continue task: [USER_TASK]",',' name="setup-heartbeat-md"'," )"].join(`
|
|
7
|
-
`)}]};if(!Y(r))return console.log(`[claude-launch] No agentChannels mapping for workdir "${r}" \u2014 blocking launch`),{isError:!0,content:[{type:"text",text:[`ERROR: Launch blocked \u2014 no agentChannels mapping found for workspace "${r}".`,"","Claude Code sessions require the workspace directory to be mapped in the agentChannels config","so notifications can be routed to the correct agent and chat.","","You must add the workspace to agentChannels FIRST. Here's what to do:","",
|
|
7
|
+
`)}]};if(!Y(r))return console.log(`[claude-launch] No agentChannels mapping for workdir "${r}" \u2014 blocking launch`),{isError:!0,content:[{type:"text",text:[`ERROR: Launch blocked \u2014 no agentChannels mapping found for workspace "${r}".`,"","Claude Code sessions require the workspace directory to be mapped in the agentChannels config","so notifications can be routed to the correct agent and chat.","","You must add the workspace to agentChannels FIRST. Here's what to do:","",'1. Edit ~/.openclaw/openclaw.json and add the workspace mapping under plugins.entries["openclaw-claude-code-plugin"].config.agentChannels:',"",` jq '.plugins.entries["openclaw-claude-code-plugin"].config.agentChannels["${r}"] = "channel|accountId|chatId"' ~/.openclaw/openclaw.json > /tmp/openclaw-updated.json && mv /tmp/openclaw-updated.json ~/.openclaw/openclaw.json`,"",' Replace "channel|accountId|chatId" with the actual values, e.g.: "telegram|my-agent|123456789"',"","2. Verify the config was applied:","",` cat ~/.openclaw/openclaw.json | jq '.plugins.entries["openclaw-claude-code-plugin"].config.agentChannels'`,"","3. Restart the Gateway to pick up the new config, then retry the launch:",""," openclaw gateway restart"].join(`
|
|
8
8
|
`)}]}}let g=d.spawn({prompt:n.prompt,name:n.name,workdir:r,model:n.model||F.defaultModel,maxBudgetUsd:o,systemPrompt:n.system_prompt,allowedTools:n.allowed_tools,resumeSessionId:s,forkSession:n.fork_session,multiTurn:!n.multi_turn_disabled,permissionMode:n.permission_mode,originChannel:m,originAgentId:e.agentId||void 0}),U=n.prompt.length>80?n.prompt.slice(0,80)+"...":n.prompt,E=["Session launched successfully.",` Name: ${g.name}`,` ID: ${g.id}`,` Dir: ${r}`,` Model: ${g.model??"default"}`,` Prompt: "${U}"`];return n.resume_session_id&&E.push(` Resume: ${n.resume_session_id}${n.fork_session?" (forked)":""}`),n.multi_turn_disabled?E.push(" Mode: single-turn (fire-and-forget)"):E.push(" Mode: multi-turn (use claude_respond to send follow-up messages)"),E.push(""),E.push("Use claude_sessions to check status, claude_output to see output."),{content:[{type:"text",text:E.join(`
|
|
9
9
|
`)}]}}catch(s){return{content:[{type:"text",text:`Error launching session: ${s.message}`}]}}}}}function _s(e){return{name:"claude_sessions",description:"List all Claude Code sessions with their status and progress.",parameters:f.Object({status:f.Optional(f.Union([f.Literal("all"),f.Literal("running"),f.Literal("completed"),f.Literal("failed")],{description:'Filter by status (default "all")'}))}),async execute(t,n){if(!d)return{content:[{type:"text",text:"Error: SessionManager not initialized. The claude-code service must be running."}]};let r=n.status||"all",o=d.list(r),s=o;if(e?.workspaceDir){let m=Y(e.workspaceDir);m?(console.log(`[claude_sessions] Filtering sessions by agentChannel=${m}`),s=o.filter(p=>{let g=p.originChannel===m;return console.log(`[claude_sessions] session=${p.id} originChannel=${p.originChannel} match=${g}`),g})):console.log(`[claude_sessions] No agentChannel found for workspaceDir=${e.workspaceDir}, returning all sessions`)}return s.length===0?{content:[{type:"text",text:"No sessions found."}]}:{content:[{type:"text",text:s.map(Rt).join(`
|
|
10
10
|
|