grix-connector 3.10.1 → 3.11.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.
@@ -0,0 +1,293 @@
1
+ # API Contract
2
+
3
+ ## Purpose
4
+
5
+ `grix-admin` is responsible for local binding and runtime convergence, and when the current agent has the corresponding scope, supports completing the following through `grix_admin` via WS:
6
+
7
+ 1. Create new remote API agents
8
+ 2. Query agent categories under the current account
9
+ 3. Create categories
10
+ 4. Modify categories
11
+ 5. Assign or clear categories for specified agents
12
+
13
+ ## Base Rules
14
+
15
+ 1. Do not ask users to provide website account/password for this flow.
16
+ 2. All remote creation and category actions must go through `grix_admin` via the current account's authenticated WS channel.
17
+ 3. If `agent_name` / `agent_id` / `api_endpoint` / `api_key` are incomplete, and the current account cannot create remotely, stop first and require backend admin to complete them.
18
+ 4. The current agent must first have the corresponding scope enabled on the frontend permissions page; without scope, WS will fail directly.
19
+ 5. For `bind-local` / `create-and-bind` / `connector-bind-local` / `create-and-connector-bind`, "config written successfully" does not equal completion; if this invocation already has real routing verification conditions, real verification passing must also be counted as part of the success criteria; otherwise explicitly hand the subsequent verification responsibility back to the upper-level flow.
20
+
21
+ ## Direct `grix_admin` Contract
22
+
23
+ ### 1. Create Remote Agent
24
+
25
+ ```json
26
+ {
27
+ "action": "create_agent",
28
+ "agentName": "ops helper",
29
+ "introduction": "Handles deployment and on-call collaboration",
30
+ "isMain": false,
31
+ "categoryName": "Project Assistant",
32
+ "parentCategoryId": "0",
33
+ "categorySortOrder": 10
34
+ }
35
+ ```
36
+
37
+ Key fields to read from the return:
38
+
39
+ 1. `createdAgent.id`
40
+ 2. `createdAgent.agent_name`
41
+ 3. `createdAgent.api_endpoint`
42
+ 4. `createdAgent.api_key`
43
+
44
+ Required scope:
45
+
46
+ 1. `agent.api.create`
47
+ 2. If `categoryName` is included, may additionally need `agent.category.list`, `agent.category.create`, `agent.category.assign`
48
+ 3. If `categoryId` is included, additionally needs `agent.category.assign`
49
+
50
+ ### 2. List Categories
51
+
52
+ ```json
53
+ {
54
+ "action": "list_categories"
55
+ }
56
+ ```
57
+
58
+ Required scope:
59
+
60
+ 1. `agent.category.list`
61
+
62
+ ### 3. Create Category
63
+
64
+ ```json
65
+ {
66
+ "action": "create_category",
67
+ "name": "Project Assistant",
68
+ "parentId": "0",
69
+ "sortOrder": 10
70
+ }
71
+ ```
72
+
73
+ Required scope:
74
+
75
+ 1. `agent.category.create`
76
+
77
+ ### 4. Update Category
78
+
79
+ ```json
80
+ {
81
+ "action": "update_category",
82
+ "categoryId": "20001",
83
+ "name": "On-call Assistant",
84
+ "parentId": "0",
85
+ "sortOrder": 20
86
+ }
87
+ ```
88
+
89
+ Required scope:
90
+
91
+ 1. `agent.category.update`
92
+
93
+ ### 5. Assign or Clear Category
94
+
95
+ ```json
96
+ {
97
+ "action": "assign_category",
98
+ "agentId": "10001",
99
+ "categoryId": "20001"
100
+ }
101
+ ```
102
+
103
+ Clear category:
104
+
105
+ ```json
106
+ {
107
+ "action": "assign_category",
108
+ "agentId": "10001",
109
+ "categoryId": "0"
110
+ }
111
+ ```
112
+
113
+ Required scope:
114
+
115
+ 1. `agent.category.assign`
116
+
117
+ ## Local Bind Steps
118
+
119
+ After remote agent parameters are complete, continue with local binding. The target environment determines which path to follow.
120
+
121
+ ### Path A: OpenClaw
122
+
123
+ Use official OpenClaw CLI commands:
124
+
125
+ 1. Prepare local directories:
126
+ - `workspace=~/.openclaw/workspace-<agent_name>`
127
+ - `agentDir=~/.openclaw/agents/<agent_name>/agent`
128
+ - Add minimal `IDENTITY.md`, `SOUL.md`, `AGENTS.md` when required persona files are missing
129
+ 2. Resolve `model` in this order:
130
+ - The existing `model` from that local agent's entry
131
+ - `agents.defaults.model.primary`
132
+ - If still unavailable, clearly report error and stop
133
+ 3. Read current config and merge:
134
+ - `channels.grix.accounts`
135
+ - `agents.list`
136
+ - `tools.profile`
137
+ - `tools.alsoAllow`
138
+ - `tools.sessions.visibility`
139
+ 4. Write back using official CLI:
140
+ - `channels.grix.accounts.<agent_name>`
141
+ - `agents.list`
142
+ - `openclaw agents bind --agent <agent_name> --bind grix:<agent_name>`
143
+ - `tools.profile`
144
+ - `tools.alsoAllow`
145
+ - `tools.sessions.visibility`
146
+ - If needed, restore `channels.grix.enabled=true`
147
+ 5. After writing, perform static validation first:
148
+ - `openclaw config validate`
149
+ - `openclaw config get --json channels.grix.accounts.<agent_name>`
150
+ - `openclaw config get --json agents.list`
151
+ - `openclaw agents bindings --agent <agent_name> --json`
152
+ 6. If this invocation already has real verification conditions, must immediately perform a real routing verification; reuse the current install/acceptance context, do not invent additional probes. Reply falling to the main agent, default assistant, old persona, or old config are all considered failures.
153
+ 7. Only when step 5 static validation passes and this invocation itself handles step 6 real verification but verification fails, is one `openclaw gateway restart` allowed; after restart, must redo the same round of real routing verification.
154
+ 8. If this invocation cannot perform real verification, can only state "config has been written, runtime not yet tested, needs subsequent flow to continue verification"; do not write it as "already fully taken effect".
155
+
156
+ ### Path B: grix-connector
157
+
158
+ Directly manage `~/.grix/config/agents.json` and hot-reload the daemon:
159
+
160
+ 1. Target file: `~/.grix/config/agents.json`. Initialize as `{ "agents": [] }` if missing.
161
+ 2. Read the existing `agents` array. Match by `name === agent_name`:
162
+ - If found, update the existing entry in place.
163
+ - If not found, append a new entry.
164
+ 3. Write the entry with these fields:
165
+ - `name`: `agent_name`
166
+ - `ws_url`: `api_endpoint`
167
+ - `agent_id`: `agent_id`
168
+ - `api_key`: `api_key`
169
+ - `client_type`: `client_type` (default `pi`)
170
+ 4. Preserve valid JSON, set file permissions to `0o600`, and create a timestamped backup (also `0o600`) before writing.
171
+ 5. Trigger reload through the synchronous Admin API:
172
+ - Default endpoint: `POST http://127.0.0.1:19580/api/reload`
173
+ - The endpoint waits for `manager.reload()` to complete and returns `{ ok: true, result }` or an error. Use this instead of the CLI `grix-connector reload` to avoid races and to surface reload failures.
174
+ - If the admin port was customized via `GRIX_ADMIN_PORT` or `--admin-port`, read the actual port from `~/.grix/data/admin-port`.
175
+ 6. Verify via Admin API `GET http://127.0.0.1:<admin-port>/api/agents`:
176
+ - Find entry where `name === agent_name`.
177
+ - Confirm the entry exists and reports `alive === true`.
178
+ - **Caveat**: `alive=true` only means the daemon started the instance. It does **not** prove the Agent successfully authenticated with the Grix platform.
179
+ 7. Perform secondary platform-connection verification:
180
+ - Inspect daemon logs for WebSocket connection success / authentication failure messages for this Agent.
181
+ - Or ask the owner to send a test message to the Agent and confirm it responds.
182
+ 8. If verification fails, report the observed status and stop; do not claim success.
183
+ 9. If this invocation cannot perform real verification, can only state "config has been written, reload completed, runtime not yet tested"; do not write it as "already fully taken effect".
184
+
185
+ ## `bind-local` Input Contract
186
+
187
+ ```json
188
+ {
189
+ "task": "bind-local\nagent_name=grix-main\nagent_id=2029786829095440384\napi_endpoint=wss://grix.dhf.pub/v1/agent-api/ws?agent_id=2029786829095440384\napi_key=ak_xxx\ndo_not_create_remote_agent=true"
190
+ }
191
+ ```
192
+
193
+ This mode prioritizes local binding; if this invocation has real verification conditions, must also complete real routing verification before it counts as full convergence; otherwise only complete static binding and explicitly hand subsequent verification responsibility to the upper-level flow.
194
+
195
+ ## `connector-bind-local` Input Contract
196
+
197
+ ```json
198
+ {
199
+ "task": "connector-bind-local\nagent_name=programmer-pi\nagent_id=2079349263263338496\napi_endpoint=wss://grix.dhf.pub/v1/agent-api/ws?agent_id=2079349263263338496\napi_key=ak_xxx\nclient_type=pi"
200
+ }
201
+ ```
202
+
203
+ Field mapping to `~/.grix/config/agents.json`:
204
+
205
+ | Input field | JSON field | Notes |
206
+ | -------------- | ------------ | ------------------------------------------ |
207
+ | `agent_name` | `name` | Also used as the matching key |
208
+ | `api_endpoint` | `ws_url` | The WebSocket URL for the agent API |
209
+ | `agent_id` | `agent_id` | Platform agent ID |
210
+ | `api_key` | `api_key` | Agent API key |
211
+ | `client_type` | `client_type`| Optional, default `pi` |
212
+
213
+ Convergence rules:
214
+
215
+ 1. Backup `~/.grix/config/agents.json` before writing; set backup permissions to `0o600`.
216
+ 2. Preserve valid JSON and set file permissions to `0o600`.
217
+ 3. Trigger reload via synchronous Admin API `POST http://127.0.0.1:19580/api/reload` (or the port stored in `~/.grix/data/admin-port` if customized).
218
+ 4. Verify via `GET http://127.0.0.1:<admin-port>/api/agents` that the entry exists and has `alive=true`.
219
+ 5. Perform secondary platform-connection verification by checking daemon logs or sending a test message; do not treat `alive=true` as proof of successful platform authentication.
220
+
221
+ ## `create-and-bind` Input Contract
222
+
223
+ When the main agent already has an available account and `agent.api.create` scope, can enter the creation flow through `grix_admin.task`:
224
+
225
+ ```json
226
+ {
227
+ "task": "create-and-bind\nagentName=ops helper\nintroduction=Handles deployment and on-call collaboration\nisMain=false\ncategoryName=Project Assistant\nparentCategoryId=0\ncategorySortOrder=10"
228
+ }
229
+ ```
230
+
231
+ This mode requires steps in order:
232
+
233
+ 1. First make one direct call with `action=create_agent`, passing optional `categoryId` / `categoryName` / `parentCategoryId` / `categorySortOrder` together
234
+ 2. If the return already includes the category assignment result, continue directly
235
+ 3. If the caller used a legacy path, or the return does not include the category assignment result, supplement with:
236
+ - `categoryId` -> `action=assign_category`
237
+ - `categoryName` -> `action=list_categories`
238
+ - Not found -> `action=create_category`
239
+ - After obtaining category ID -> `action=assign_category`
240
+ 4. Finally follow the same local binding and runtime convergence flow as `bind-local`
241
+
242
+ Notes:
243
+
244
+ 1. `categoryId` and `categoryName` cannot be provided simultaneously
245
+ 2. When matching `categoryName`, must also consider `parentCategoryId`
246
+ 3. If the remote return indicates missing `agent.api.create` or any `agent.category.*` scope, clearly state which specific scope is missing
247
+
248
+ ## `create-and-connector-bind` Input Contract
249
+
250
+ When the main agent already has an available account and `agent.api.create` scope, and the target runtime is grix-connector:
251
+
252
+ ```json
253
+ {
254
+ "task": "create-and-connector-bind\nagentName=程序员 pi\nintroduction=A coding assistant\nisMain=false\nclientType=pi\ncategoryName=Developers\nparentCategoryId=0\ncategorySortOrder=10"
255
+ }
256
+ ```
257
+
258
+ This mode requires steps in order:
259
+
260
+ 1. Make one direct call with `action=create_agent`, passing optional `categoryId` / `categoryName` / `parentCategoryId` / `categorySortOrder` together.
261
+ 2. If the return already includes the category assignment result, continue directly; otherwise supplement with the same category resolution logic as `create-and-bind`.
262
+ 3. Read `createdAgent.id`, `createdAgent.agent_name`, `createdAgent.api_endpoint`, `createdAgent.api_key` from the result.
263
+ 4. Follow the `connector-bind-local` local binding and runtime convergence flow, using `clientType` (default `pi`) for the `client_type` field.
264
+ 5. Trigger reload via the synchronous Admin API `POST /api/reload`, verify the Agent entry exists and `alive=true` via `GET /api/agents`, and perform secondary platform-connection verification (log inspection or test message).
265
+
266
+ Notes:
267
+
268
+ 1. `categoryId` and `categoryName` cannot be provided simultaneously.
269
+ 2. `clientType` defaults to `pi` when omitted.
270
+ 3. If the remote return indicates missing `agent.api.create` or any `agent.category.*` scope, clearly state which specific scope is missing.
271
+
272
+ ## `category-manage` Input Contract
273
+
274
+ When only doing subsequent category management, enter through `grix_admin.task`:
275
+
276
+ ```json
277
+ {
278
+ "task": "category-manage\noperation=assign\nagentId=10001\ncategoryId=0"
279
+ }
280
+ ```
281
+
282
+ Mapping:
283
+
284
+ 1. `operation=list` -> `action=list_categories`
285
+ 2. `operation=create` -> `action=create_category`
286
+ 3. `operation=update` -> `action=update_category`
287
+ 4. `operation=assign` -> `action=assign_category`
288
+
289
+ Notes:
290
+
291
+ 1. For `operation=assign`, `categoryId=0` means clear the category
292
+ 2. No step can be executed cross-account
293
+ 3. Do not hand-write HTTP or fall back to legacy scripts
@@ -1 +1 @@
1
- import{readFileSync as p,readdirSync as c,existsSync as a,mkdirSync as k,cpSync as y,writeFileSync as h,rmSync as g}from"node:fs";import{join as t,dirname as S}from"node:path";import{homedir as m}from"node:os";import{fileURLToPath as D}from"node:url";import{parseSkillFrontmatter as v,scanSkills as x,dedupeSkills as F}from"../adapter/claude/skill-scanner.js";import{resolveRuntimePaths as w}from"../core/config/index.js";import{log as u}from"../core/log/index.js";const l=S(D(import.meta.url)),f=".grix-managed";function d(){const e=[];let i;try{i=c(l,{withFileTypes:!0,encoding:"utf8"})}catch{return e}for(const r of i){if(!r.isDirectory())continue;const n=t(l,r.name,"SKILL.md");try{const s=p(n,"utf-8"),o=v(s);o?.name&&e.push({name:o.name,description:o.description,trigger:o.trigger,source:"connector",managed:!0})}catch{}}return e}function T(e){let i=[];try{i=x(e)}catch{i=[]}return F([...i,...d()])}function j(e){const i=[];let r;try{r=c(l,{withFileTypes:!0,encoding:"utf8"})}catch{return i}for(const n of r){if(!n.isDirectory())continue;const s=t(l,n.name);if(a(t(s,"SKILL.md")))try{k(e,{recursive:!0});const o=t(e,n.name);y(s,o,{recursive:!0}),h(t(o,f),"","utf8"),i.push(n.name)}catch{}}return i}function C(){return(process.env.KIMI_CODE_HOME||"").trim()||t(m(),".kimi-code")}function L(){const e=m(),i=process.env.XDG_CONFIG_HOME||t(e,".config");return[t(w().dataDir,"claude-plugin","skills"),t(e,".codex","skills"),t(e,".gemini","skills"),t(e,".qwen","skills"),t(e,".pi","agent","skills"),t(e,".codewhale","skills"),t(i,"opencode","skills"),t(e,".cursor","skills"),t(e,".openhuman","skills"),t(e,".kiro","skills"),t(e,".reasonix","skills"),t(C(),"skills")]}function O(){const e=[];for(const i of L()){let r;try{r=c(i,{withFileTypes:!0,encoding:"utf8"})}catch{continue}for(const n of r){if(!n.isDirectory())continue;const s=t(i,n.name);if(a(t(s,f)))try{g(s,{recursive:!0,force:!0}),e.push(s)}catch{}}}return e.length>0&&u.info("default-skills",`Cleaned ${e.length} projected skill dir(s)`),e}function b(){const e=d();if(e.length===0){u.warn("default-skills","No connector system skills found \u2014 dist/default-skills/ may be missing SKILL.md files");return}u.info("default-skills",`Connector system skills available: [${e.map(i=>i.name).join(", ")}]`)}export{T as buildReportedSkills,O as cleanupProjectedSkills,b as logDefaultSkillsCheck,C as resolveKimiCodeHome,d as scanDefaultSkills,j as syncDefaultSkillsToDir};
1
+ import{readFileSync as p,readdirSync as c,existsSync as a,mkdirSync as k,cpSync as y,writeFileSync as h,rmSync as g}from"node:fs";import{join as t,dirname as S}from"node:path";import{homedir as m}from"node:os";import{fileURLToPath as D}from"node:url";import{parseSkillFrontmatter as v,scanSkills as x,dedupeSkills as F,MANAGED_MARKER as f}from"../adapter/claude/skill-scanner.js";import{resolveRuntimePaths as w}from"../core/config/index.js";import{log as u}from"../core/log/index.js";const l=S(D(import.meta.url));function d(){const e=[];let i;try{i=c(l,{withFileTypes:!0,encoding:"utf8"})}catch{return e}for(const r of i){if(!r.isDirectory())continue;const n=t(l,r.name,"SKILL.md");try{const s=p(n,"utf-8"),o=v(s);o?.name&&e.push({name:o.name,description:o.description,trigger:o.trigger,source:"connector",managed:!0})}catch{}}return e}function T(e){let i=[];try{i=x(e)}catch{i=[]}return F([...i,...d()])}function j(e){const i=[];let r;try{r=c(l,{withFileTypes:!0,encoding:"utf8"})}catch{return i}for(const n of r){if(!n.isDirectory())continue;const s=t(l,n.name);if(a(t(s,"SKILL.md")))try{k(e,{recursive:!0});const o=t(e,n.name);y(s,o,{recursive:!0}),h(t(o,f),"","utf8"),i.push(n.name)}catch{}}return i}function C(){return(process.env.KIMI_CODE_HOME||"").trim()||t(m(),".kimi-code")}function L(){const e=m(),i=process.env.XDG_CONFIG_HOME||t(e,".config");return[t(w().dataDir,"claude-plugin","skills"),t(e,".codex","skills"),t(e,".gemini","skills"),t(e,".qwen","skills"),t(e,".pi","agent","skills"),t(e,".codewhale","skills"),t(i,"opencode","skills"),t(e,".cursor","skills"),t(e,".openhuman","skills"),t(e,".kiro","skills"),t(e,".reasonix","skills"),t(C(),"skills")]}function O(){const e=[];for(const i of L()){let r;try{r=c(i,{withFileTypes:!0,encoding:"utf8"})}catch{continue}for(const n of r){if(!n.isDirectory())continue;const s=t(i,n.name);if(a(t(s,f)))try{g(s,{recursive:!0,force:!0}),e.push(s)}catch{}}}return e.length>0&&u.info("default-skills",`Cleaned ${e.length} projected skill dir(s)`),e}function b(){const e=d();if(e.length===0){u.warn("default-skills","No connector system skills found \u2014 dist/default-skills/ may be missing SKILL.md files");return}u.info("default-skills",`Connector system skills available: [${e.map(i=>i.name).join(", ")}]`)}export{T as buildReportedSkills,O as cleanupProjectedSkills,b as logDefaultSkillsCheck,C as resolveKimiCodeHome,d as scanDefaultSkills,j as syncDefaultSkillsToDir};
@@ -1 +1 @@
1
- function a(e){const t=new Set([`http://127.0.0.1:${e.serverPort}`,`http://localhost:${e.serverPort}`,...e.allowedOrigins]),o=new Set([`127.0.0.1:${e.serverPort}`,`localhost:${e.serverPort}`,...e.allowedHosts]);return{validateRequest(s){const r=i(s,t);if(!r.ok)return r;const n=l(s,o);return n.ok?{ok:!0}:n}}}function i(e,t){const o=e.headers.origin;return o?t.has(o)?{ok:!0}:{ok:!1,statusCode:403,message:`Origin not allowed: ${o}`}:{ok:!0}}function l(e,t){const o=e.headers.host;return o?t.has(o)?{ok:!0}:{ok:!1,statusCode:403,message:`Host not allowed: ${o}`}:{ok:!1,statusCode:403,message:"Missing Host header"}}export{a as createSecurityPolicy};
1
+ function a(t){const o=new Set([`http://127.0.0.1:${t.serverPort}`,`http://localhost:${t.serverPort}`,...t.allowedOrigins]),e=new Set([`127.0.0.1:${t.serverPort}`,`localhost:${t.serverPort}`,...t.allowedHosts]);return{validateRequest(s){const r=i(s,o);if(!r.ok)return r;const n=l(s,e);return n.ok?{ok:!0}:n}}}function i(t,o){const e=t.headers.origin;return e?o.has(e)?{ok:!0}:{ok:!1,statusCode:403,message:`Origin not allowed: ${e}`}:{ok:!0}}function l(t,o){const e=t.headers.host;return e?o.has(e)?{ok:!0}:{ok:!1,statusCode:403,message:`Host not allowed: ${e}`}:{ok:!1,statusCode:403,message:"Missing Host header"}}export{a as createSecurityPolicy};
@@ -1,19 +1,19 @@
1
1
  ---
2
2
  name: grix-admin
3
- description: Responsible for OpenClaw local configuration, binding, and runtime convergence; can create new remote API agents through the current agent's WS channel, and supports querying, creating, modifying agent categories and assigning categories to agents, reusable across agent creation and management flows.
3
+ description: Responsible for OpenClaw and grix-connector local configuration, binding, and runtime convergence; can create new remote API agents through the current agent's WS channel, and supports querying, creating, modifying agent categories and assigning categories to agents, reusable across agent creation and management flows.
4
4
  ---
5
5
 
6
6
  # Grix Agent Admin
7
7
 
8
8
  `grix-admin` is responsible for three things:
9
9
 
10
- 1. Landing existing remote agent parameters into local OpenClaw, and handling runtime convergence after binding.
10
+ 1. Landing existing remote agent parameters into local OpenClaw or grix-connector, and handling runtime convergence after binding.
11
11
  2. When the current main agent is already online and has the corresponding scope, creating new remote API agents through `grix_admin`'s direct actions, then continuing with local landing.
12
12
  3. During agent creation or subsequent agent management, reusing `grix_admin`'s direct actions to query categories, create categories, modify categories, and assign categories to agents.
13
13
 
14
14
  ## Entry Method
15
15
 
16
- 1. In most cases, enter this skill from `grix_admin`'s `task` entry; the first line of `task` must clearly state `bind-local`, `create-and-bind`, or `category-manage`.
16
+ 1. In most cases, enter this skill from `grix_admin`'s `task` entry; the first line of `task` must clearly state `bind-local`, `create-and-bind`, `category-manage`, `connector-bind-local`, or `create-and-connector-bind`.
17
17
  2. Only when executing "remote API agent creation / category query / category creation / category modification / category assignment" remote steps within this skill should you directly call `grix_admin` once, without passing `task` again.
18
18
  3. In new flows, always explicitly pass `action` when directly calling `grix_admin`:
19
19
  - `create_agent`
@@ -22,6 +22,7 @@ description: Responsible for OpenClaw local configuration, binding, and runtime
22
22
  - `update_category`
23
23
  - `assign_category`
24
24
  4. The legacy direct call format for `create_agent` (passing only `agentName` and other fields without `action`) is still compatible, but should not be used in new flows.
25
+ 5. Use `bind-local` / `create-and-bind` for **OpenClaw** local configuration; use `connector-bind-local` / `create-and-connector-bind` for **grix-connector** local configuration. Do not mix the two targets in a single invocation.
25
26
 
26
27
  ## Direct Action List
27
28
 
@@ -111,11 +112,11 @@ Fields written in `grix_admin.task`:
111
112
  1. First line must be `create-and-bind`
112
113
  2. `agentName` (required)
113
114
  3. `introduction` (optional)
114
- 5. `isMain` (optional, default `false`)
115
- 6. `categoryId` (optional): assign the new agent directly to an existing category
116
- 7. `categoryName` (optional): create if not exists, then assign
117
- 8. `parentCategoryId` (optional): only used in the `categoryName` approach, default `0`
118
- 9. `categorySortOrder` (optional): only used when creating a category
115
+ 4. `isMain` (optional, default `false`)
116
+ 5. `categoryId` (optional): assign the new agent directly to an existing category
117
+ 6. `categoryName` (optional): create if not exists, then assign
118
+ 7. `parentCategoryId` (optional): only used in the `categoryName` approach, default `0`
119
+ 8. `categorySortOrder` (optional): only used when creating a category
119
120
 
120
121
  Execution rules:
121
122
 
@@ -143,11 +144,11 @@ Fields written in `grix_admin.task`:
143
144
 
144
145
  1. First line must be `category-manage`
145
146
  2. `operation` (required): only `list`, `create`, `update`, `assign` are allowed
146
- 4. `name` (`create` / `update` required)
147
- 5. `parentId` (`create` / `update` required)
148
- 6. `sortOrder` (`create` / `update` optional)
149
- 7. `categoryId` (`update` / `assign` required; for `assign`, `0` means clear)
150
- 8. `agentId` (`assign` required)
147
+ 3. `name` (`create` / `update` required)
148
+ 4. `parentId` (`create` / `update` required)
149
+ 5. `sortOrder` (`create` / `update` optional)
150
+ 6. `categoryId` (`update` / `assign` required; for `assign`, `0` means clear)
151
+ 7. `agentId` (`assign` required)
151
152
 
152
153
  Execution rules:
153
154
 
@@ -164,11 +165,88 @@ Execution rules:
164
165
  - `categoryId=0` explicitly means clear the agent's current category
165
166
  7. If the current management task also includes "creating a new agent", prefer using `create-and-bind`; do not split remote creation into other custom flows.
166
167
 
168
+ ## Mode D: connector-bind-local (grix-connector Local Binding)
169
+
170
+ Input fields (written in `grix_admin.task`, all required):
171
+
172
+ 1. First line must be `connector-bind-local`
173
+ 2. `agent_name`
174
+ 3. `agent_id`
175
+ 4. `api_endpoint`
176
+ 5. `api_key`
177
+ 6. `client_type` (optional, default `pi`)
178
+
179
+ Execution rules:
180
+
181
+ 1. Do not perform remote creation; execute local grix-connector binding directly. Do not invoke any OpenClaw CLI commands in this mode.
182
+ 2. Target file: `~/.grix/config/agents.json`. If the file or directory does not exist, initialize it as `{ "agents": [] }`.
183
+ 3. Read the existing `agents` array. If an entry with the same `name` as `agent_name` already exists, update it in place; otherwise append a new entry.
184
+ 4. Write the following fields into the entry:
185
+ - `name`: `agent_name`
186
+ - `ws_url`: `api_endpoint`
187
+ - `agent_id`: `agent_id`
188
+ - `api_key`: `api_key`
189
+ - `client_type`: `client_type` (default `pi`)
190
+ 5. Preserve valid JSON and set file permissions to `0o600`. Before writing, create a timestamped backup at `~/.grix/config/agents.json.bak.<YYYYMMDDHHMMSS>` and also set the backup file permissions to `0o600`.
191
+ 6. If `grix-connector` daemon is running (`grix-connector status` returns `daemon_state=running`), trigger reload via the daemon Admin API:
192
+ - Default endpoint: `POST http://127.0.0.1:19580/api/reload`
193
+ - The actual admin port may be overridden by `GRIX_ADMIN_PORT` or `--admin-port`; if the default fails, read `~/.grix/data/admin-port` for the current port.
194
+ - This endpoint is synchronous: it waits for `manager.reload()` to finish and returns `{ ok: true, result }` or an error. Unlike the CLI `grix-connector reload`, it does not suffer from "signal sent but config not yet applied" race conditions, and it surfaces JSON parse errors or `RELOAD_UNSAFE` failures to the caller.
195
+ - If the reload request returns an error, report the error and stop; do not proceed to verification.
196
+ 7. After reload succeeds, verify that the daemon has loaded the new entry via `GET /api/agents`:
197
+ - Find an entry where `name === agent_name`.
198
+ - Confirm the entry exists and reports `alive === true`.
199
+ - **Important**: `alive=true` only means the daemon has started the Agent instance; it does **not** prove the Agent has successfully connected to the Grix platform or that the API key is valid. Authentication failures do not flip `alive` to `false`.
200
+ - Therefore, perform a secondary convergence check: inspect the latest daemon log in `~/.grix/log/` (files are named `grix-connector-<YYYY-MM-DD>.log`; list the directory and open the most recent one) for WebSocket connection success / authentication failure messages for this Agent, or ask the owner to send a test message to the Agent.
201
+ - If the secondary check fails, state "config loaded and instance started, but platform connection not yet verified"; do not claim full convergence.
202
+ 8. If this invocation cannot perform real verification, clearly state "config has been written, reload completed, runtime not yet tested, needs subsequent flow to continue verification"; do not claim it has fully taken effect.
203
+ 9. Success definition:
204
+ - Can perform real verification: "config written + reload succeeded + Agent entry exists with `alive=true` + platform connection verified (log or test message)" counts as `connector-bind-local` complete.
205
+ - Cannot perform real verification: only "config written + reload succeeded" can be claimed.
206
+
207
+ ## Mode E: create-and-connector-bind (Create Remote Agent Then Bind to grix-connector)
208
+
209
+ Fields written in `grix_admin.task`:
210
+
211
+ 1. First line must be `create-and-connector-bind`
212
+ 2. `agentName` (required)
213
+ 3. `introduction` (optional)
214
+ 4. `isMain` (optional, default `false`)
215
+ 5. `clientType` (optional, default `pi`)
216
+ 6. `categoryId` (optional): assign the new agent directly to an existing category
217
+ 7. `categoryName` (optional): create if not exists, then assign
218
+ 8. `parentCategoryId` (optional): only used in the `categoryName` approach, default `0`
219
+ 9. `categorySortOrder` (optional): only used when creating a category
220
+
221
+ Execution rules:
222
+
223
+ 1. Confirm the current session is bound to a valid Grix account; cross-account execution is prohibited.
224
+ 2. If both `categoryId` and `categoryName` are provided, report an error and stop immediately to avoid ambiguity.
225
+ 3. Call `grix_admin` only once with `action=create_agent`, delegating remote creation and optional category handling to it; pass:
226
+ - `action=create_agent`
227
+ - `agentName`
228
+ - Optional `introduction`
229
+ - Optional `isMain`
230
+ - Optional `categoryId`
231
+ - Optional `categoryName`
232
+ - Optional `parentCategoryId`
233
+ - Optional `categorySortOrder`
234
+ 4. After remote creation succeeds, read `createdAgent.id`, `createdAgent.agent_name`, `createdAgent.api_endpoint`, `createdAgent.api_key` from the return result.
235
+ 5. If the request included category information, check whether the return already includes the category assignment result; if not, proceed with supplementary steps according to `categoryId` / `categoryName` rules and explain the reason.
236
+ 6. In the `categoryName` flow, if multiple categories with the exact same name appear under the same parent, stop and ask the owner to clean up categories or use an explicit `categoryId` instead.
237
+ 7. After remote creation and optional category steps succeed, immediately transition to the `connector-bind-local` local binding steps using the returned parameters and `clientType`.
238
+ 8. Trigger reload via the synchronous Admin API `POST /api/reload` (see Mode D for port resolution and failure handling); then verify the new Agent entry exists and `alive=true` via `GET /api/agents`, and perform the secondary platform-connection verification (log inspection or test message).
239
+ 9. `isMain=true` should only be used when actually creating a new main API agent; generally subsequent new agents should not enable this by default.
240
+ 10. Throughout the `create-and-connector-bind` flow, do not treat "config written successfully" as completion; only when this invocation handles real verification and verification passes is it complete.
241
+
167
242
  ## Remote Creation Fallback Conditions
168
243
 
169
- If the current task has neither an existing `agent_name`, `agent_id`, `api_endpoint`, `api_key`, nor an available online main channel or `agent.api.create` permission, stop this skill first and clearly prompt the user to create the remote agent through the backend admin path. After obtaining these parameters, proceed with `bind-local`.
244
+ If the current task has neither an existing `agent_name`, `agent_id`, `api_endpoint`, `api_key`, nor an available online main channel or `agent.api.create` permission, stop this skill first and clearly prompt the user to create the remote agent through the backend admin path. After obtaining these parameters:
245
+
246
+ - For OpenClaw target, proceed with `bind-local`.
247
+ - For grix-connector target, proceed with `connector-bind-local`.
170
248
 
171
- ## Guardrails (Applicable to All Three Modes)
249
+ ## Guardrails (Applicable to All Modes)
172
250
 
173
251
  1. Never ask user for website account/password.
174
252
  2. `bind-local` mode must not call back to `grix-register` to avoid circular routing.
@@ -176,26 +254,34 @@ If the current task has neither an existing `agent_name`, `agent_id`, `api_endpo
176
254
  4. The complete `api_key` is only passed back once; do not repeatedly echo it in plaintext.
177
255
  5. Before local `openclaw config set` / `validate` succeeds, do not claim config is complete; when this invocation can perform real verification, do not claim `bind-local` / `create-and-bind` is complete until real routing verification passes.
178
256
  6. During an install private chat, do not manually modify `openclaw.json` and then execute `openclaw gateway restart`.
179
- 7. Do not reference or call `grix_agent_bind.py`; this skill only uses official OpenClaw config commands.
257
+ 7. Do not reference or call `grix_agent_bind.py`; for OpenClaw modes this skill only uses official OpenClaw CLI commands.
258
+ 8. For `connector-bind-local` / `create-and-connector-bind`, directly reading and writing `~/.grix/config/agents.json` is the intended mechanism; this is grix-connector's own configuration domain, not a third-party product.
259
+ 9. When writing `~/.grix/config/agents.json`, always create a timestamped backup first, preserve valid JSON, and set both the config file and the backup file permissions to `0o600`.
260
+ 10. After writing grix-connector config, trigger reload through the synchronous Admin API `POST /api/reload` (not the CLI `grix-connector reload`) so that reload errors are visible to the caller. Verify the Agent entry exists and reports `alive=true`, and perform a secondary platform-connection check before claiming full convergence.
180
261
 
181
262
  ## Error Handling Rules
182
263
 
183
- 1. `bind-local` missing fields: clearly state which field is missing and stop.
184
- 2. `create-and-bind` missing `agentName`: clearly state which field is missing and stop.
185
- 3. `create-and-bind` with both `categoryId` and `categoryName`: clearly state the conflict and stop.
264
+ 1. `bind-local` / `connector-bind-local` missing fields: clearly state which field is missing and stop.
265
+ 2. `create-and-bind` / `create-and-connector-bind` missing `agentName`: clearly state which field is missing and stop.
266
+ 3. `create-and-bind` / `create-and-connector-bind` with both `categoryId` and `categoryName`: clearly state the conflict and stop.
186
267
  4. `category-manage` missing `operation` or operation-specific fields: clearly state which field is missing and stop.
187
268
  5. Remote returns `code=4003` or message explicitly mentions `agent.api.create`: tell the owner to grant `agent.api.create` on the Agent permissions page.
188
269
  6. Remote returns `code=4003` or message explicitly mentions `agent.category.list` / `agent.category.create` / `agent.category.update` / `agent.category.assign`: tell the owner to grant the corresponding scope on the Agent permissions page.
189
270
  7. Missing remote agent parameters and current account cannot create: clearly require backend admin creation first.
190
- 8. Local config failure: return the failed command and result, then stop; emphasize which `get` / `set` / `validate` step failed.
191
- 9. This invocation handles real routing verification, and after one `openclaw gateway restart` retest still fails: clearly state "static config has been written, but runtime has not yet switched successfully"; converge as failed or partially complete, do not write it as success.
271
+ 8. Local config failure (OpenClaw): return the failed command and result, then stop; emphasize which `get` / `set` / `validate` step failed.
272
+ 9. Local config failure (grix-connector): report the exact JSON parse error, write error, or `~/.grix/config/agents.json` state, then stop.
273
+ 10. Synchronous Admin API reload failed (e.g., returns non-2xx, `RELOAD_UNSAFE`, JSON parse error in agents.json): report the error body and daemon status; do not proceed to verification or claim the Agent is online.
274
+ 11. Admin API verification failed (Agent entry missing or not `alive=true`): report the observed entry or missing entry, then stop.
275
+ 12. Secondary platform-connection verification failed (log shows authentication/connection errors, or test message not delivered): state "config loaded and instance started, but platform connection not verified"; converge as partially complete, do not claim full convergence.
276
+ 13. This invocation handles real routing verification, and after one `openclaw gateway restart` retest still fails: clearly state "static config has been written, but runtime has not yet switched successfully"; converge as failed or partially complete, do not write it as success.
192
277
 
193
278
  ## Response Style
194
279
 
195
- 1. Clearly state whether the current execution is `bind-local`, `create-and-bind`, or `category-manage`.
196
- 2. Report in phases: remote creation / category handling (if any) / local config writing / validation results.
280
+ 1. Clearly state whether the current execution is `bind-local`, `create-and-bind`, `category-manage`, `connector-bind-local`, or `create-and-connector-bind`.
281
+ 2. Report in phases: remote creation / category handling (if any) / local config writing / reload / validation results.
197
282
  3. Clearly state whether local config has taken effect; if only static config succeeded but this invocation cannot perform real verification, can only write "config has been written, runtime not yet tested, needs subsequent flow to continue verification"; if only the category step succeeded, also state that clearly.
198
- 4. If remote creation succeeded but category or local binding subsequently failed, clearly state it is "partially complete"; do not generically write it as success.
283
+ 4. For grix-connector flows, explicitly report whether the synchronous Admin API reload succeeded, whether the Admin API shows the Agent entry exists with `alive=true`, and the result of any secondary platform-connection verification.
284
+ 5. If remote creation succeeded but category or local binding subsequently failed, clearly state it is "partially complete"; do not generically write it as success.
199
285
 
200
286
  ## References
201
287
 
@@ -16,7 +16,7 @@
16
16
  2. All remote creation and category actions must go through `grix_admin` via the current account's authenticated WS channel.
17
17
  3. If `agent_name` / `agent_id` / `api_endpoint` / `api_key` are incomplete, and the current account cannot create remotely, stop first and require backend admin to complete them.
18
18
  4. The current agent must first have the corresponding scope enabled on the frontend permissions page; without scope, WS will fail directly.
19
- 5. For `bind-local` / `create-and-bind`, "config written successfully" does not equal completion; if this invocation already has real routing verification conditions, real verification passing must also be counted as part of the success criteria; otherwise explicitly hand the subsequent verification responsibility back to the upper-level flow.
19
+ 5. For `bind-local` / `create-and-bind` / `connector-bind-local` / `create-and-connector-bind`, "config written successfully" does not equal completion; if this invocation already has real routing verification conditions, real verification passing must also be counted as part of the success criteria; otherwise explicitly hand the subsequent verification responsibility back to the upper-level flow.
20
20
 
21
21
  ## Direct `grix_admin` Contract
22
22
 
@@ -116,7 +116,11 @@ Required scope:
116
116
 
117
117
  ## Local Bind Steps
118
118
 
119
- After remote agent parameters are complete, continue with local binding through the official OpenClaw CLI:
119
+ After remote agent parameters are complete, continue with local binding. The target environment determines which path to follow.
120
+
121
+ ### Path A: OpenClaw
122
+
123
+ Use official OpenClaw CLI commands:
120
124
 
121
125
  1. Prepare local directories:
122
126
  - `workspace=~/.openclaw/workspace-<agent_name>`
@@ -149,6 +153,35 @@ After remote agent parameters are complete, continue with local binding through
149
153
  7. Only when step 5 static validation passes and this invocation itself handles step 6 real verification but verification fails, is one `openclaw gateway restart` allowed; after restart, must redo the same round of real routing verification.
150
154
  8. If this invocation cannot perform real verification, can only state "config has been written, runtime not yet tested, needs subsequent flow to continue verification"; do not write it as "already fully taken effect".
151
155
 
156
+ ### Path B: grix-connector
157
+
158
+ Directly manage `~/.grix/config/agents.json` and hot-reload the daemon:
159
+
160
+ 1. Target file: `~/.grix/config/agents.json`. Initialize as `{ "agents": [] }` if missing.
161
+ 2. Read the existing `agents` array. Match by `name === agent_name`:
162
+ - If found, update the existing entry in place.
163
+ - If not found, append a new entry.
164
+ 3. Write the entry with these fields:
165
+ - `name`: `agent_name`
166
+ - `ws_url`: `api_endpoint`
167
+ - `agent_id`: `agent_id`
168
+ - `api_key`: `api_key`
169
+ - `client_type`: `client_type` (default `pi`)
170
+ 4. Preserve valid JSON, set file permissions to `0o600`, and create a timestamped backup (also `0o600`) before writing.
171
+ 5. Trigger reload through the synchronous Admin API:
172
+ - Default endpoint: `POST http://127.0.0.1:19580/api/reload`
173
+ - The endpoint waits for `manager.reload()` to complete and returns `{ ok: true, result }` or an error. Use this instead of the CLI `grix-connector reload` to avoid races and to surface reload failures.
174
+ - If the admin port was customized via `GRIX_ADMIN_PORT` or `--admin-port`, read the actual port from `~/.grix/data/admin-port`.
175
+ 6. Verify via Admin API `GET http://127.0.0.1:<admin-port>/api/agents`:
176
+ - Find entry where `name === agent_name`.
177
+ - Confirm the entry exists and reports `alive === true`.
178
+ - **Caveat**: `alive=true` only means the daemon started the instance. It does **not** prove the Agent successfully authenticated with the Grix platform.
179
+ 7. Perform secondary platform-connection verification:
180
+ - Inspect daemon logs for WebSocket connection success / authentication failure messages for this Agent.
181
+ - Or ask the owner to send a test message to the Agent and confirm it responds.
182
+ 8. If verification fails, report the observed status and stop; do not claim success.
183
+ 9. If this invocation cannot perform real verification, can only state "config has been written, reload completed, runtime not yet tested"; do not write it as "already fully taken effect".
184
+
152
185
  ## `bind-local` Input Contract
153
186
 
154
187
  ```json
@@ -159,6 +192,32 @@ After remote agent parameters are complete, continue with local binding through
159
192
 
160
193
  This mode prioritizes local binding; if this invocation has real verification conditions, must also complete real routing verification before it counts as full convergence; otherwise only complete static binding and explicitly hand subsequent verification responsibility to the upper-level flow.
161
194
 
195
+ ## `connector-bind-local` Input Contract
196
+
197
+ ```json
198
+ {
199
+ "task": "connector-bind-local\nagent_name=programmer-pi\nagent_id=2079349263263338496\napi_endpoint=wss://grix.dhf.pub/v1/agent-api/ws?agent_id=2079349263263338496\napi_key=ak_xxx\nclient_type=pi"
200
+ }
201
+ ```
202
+
203
+ Field mapping to `~/.grix/config/agents.json`:
204
+
205
+ | Input field | JSON field | Notes |
206
+ | -------------- | ------------ | ------------------------------------------ |
207
+ | `agent_name` | `name` | Also used as the matching key |
208
+ | `api_endpoint` | `ws_url` | The WebSocket URL for the agent API |
209
+ | `agent_id` | `agent_id` | Platform agent ID |
210
+ | `api_key` | `api_key` | Agent API key |
211
+ | `client_type` | `client_type`| Optional, default `pi` |
212
+
213
+ Convergence rules:
214
+
215
+ 1. Backup `~/.grix/config/agents.json` before writing; set backup permissions to `0o600`.
216
+ 2. Preserve valid JSON and set file permissions to `0o600`.
217
+ 3. Trigger reload via synchronous Admin API `POST http://127.0.0.1:19580/api/reload` (or the port stored in `~/.grix/data/admin-port` if customized).
218
+ 4. Verify via `GET http://127.0.0.1:<admin-port>/api/agents` that the entry exists and has `alive=true`.
219
+ 5. Perform secondary platform-connection verification by checking daemon logs or sending a test message; do not treat `alive=true` as proof of successful platform authentication.
220
+
162
221
  ## `create-and-bind` Input Contract
163
222
 
164
223
  When the main agent already has an available account and `agent.api.create` scope, can enter the creation flow through `grix_admin.task`:
@@ -186,6 +245,30 @@ Notes:
186
245
  2. When matching `categoryName`, must also consider `parentCategoryId`
187
246
  3. If the remote return indicates missing `agent.api.create` or any `agent.category.*` scope, clearly state which specific scope is missing
188
247
 
248
+ ## `create-and-connector-bind` Input Contract
249
+
250
+ When the main agent already has an available account and `agent.api.create` scope, and the target runtime is grix-connector:
251
+
252
+ ```json
253
+ {
254
+ "task": "create-and-connector-bind\nagentName=程序员 pi\nintroduction=A coding assistant\nisMain=false\nclientType=pi\ncategoryName=Developers\nparentCategoryId=0\ncategorySortOrder=10"
255
+ }
256
+ ```
257
+
258
+ This mode requires steps in order:
259
+
260
+ 1. Make one direct call with `action=create_agent`, passing optional `categoryId` / `categoryName` / `parentCategoryId` / `categorySortOrder` together.
261
+ 2. If the return already includes the category assignment result, continue directly; otherwise supplement with the same category resolution logic as `create-and-bind`.
262
+ 3. Read `createdAgent.id`, `createdAgent.agent_name`, `createdAgent.api_endpoint`, `createdAgent.api_key` from the result.
263
+ 4. Follow the `connector-bind-local` local binding and runtime convergence flow, using `clientType` (default `pi`) for the `client_type` field.
264
+ 5. Trigger reload via the synchronous Admin API `POST /api/reload`, verify the Agent entry exists and `alive=true` via `GET /api/agents`, and perform secondary platform-connection verification (log inspection or test message).
265
+
266
+ Notes:
267
+
268
+ 1. `categoryId` and `categoryName` cannot be provided simultaneously.
269
+ 2. `clientType` defaults to `pi` when omitted.
270
+ 3. If the remote return indicates missing `agent.api.create` or any `agent.category.*` scope, clearly state which specific scope is missing.
271
+
189
272
  ## `category-manage` Input Contract
190
273
 
191
274
  When only doing subsequent category management, enter through `grix_admin.task`:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grix-connector",
3
- "version": "3.10.1",
3
+ "version": "3.11.0",
4
4
  "description": "Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",