@dhf-hermes/grix 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.
Potentially problematic release.
This version of @dhf-hermes/grix might be problematic. Click here for more details.
- package/.gitignore +6 -0
- package/LICENSE +21 -0
- package/README.md +98 -0
- package/bin/grix-hermes.mjs +93 -0
- package/grix-admin/SKILL.md +109 -0
- package/grix-admin/agents/openai.yaml +7 -0
- package/grix-admin/scripts/admin.mjs +12 -0
- package/grix-admin/scripts/bind_from_json.py +118 -0
- package/grix-admin/scripts/bind_local.py +226 -0
- package/grix-egg/SKILL.md +73 -0
- package/grix-egg/agents/openai.yaml +7 -0
- package/grix-egg/references/acceptance-checklist.md +10 -0
- package/grix-egg/scripts/card-link.mjs +12 -0
- package/grix-egg/scripts/validate_install_context.mjs +74 -0
- package/grix-group/SKILL.md +42 -0
- package/grix-group/agents/openai.yaml +7 -0
- package/grix-group/scripts/group.mjs +12 -0
- package/grix-query/SKILL.md +53 -0
- package/grix-query/agents/openai.yaml +7 -0
- package/grix-query/scripts/query.mjs +12 -0
- package/grix-register/SKILL.md +68 -0
- package/grix-register/agents/openai.yaml +7 -0
- package/grix-register/references/handoff-contract.md +21 -0
- package/grix-register/scripts/create_api_agent_and_bind.py +105 -0
- package/grix-register/scripts/grix_auth.py +487 -0
- package/grix-update/SKILL.md +50 -0
- package/grix-update/agents/openai.yaml +7 -0
- package/grix-update/references/cron-setup.md +11 -0
- package/grix-update/scripts/grix_update.py +99 -0
- package/lib/manifest.mjs +68 -0
- package/message-send/SKILL.md +71 -0
- package/message-send/agents/openai.yaml +7 -0
- package/message-send/scripts/card-link.mjs +40 -0
- package/message-send/scripts/send.mjs +12 -0
- package/message-unsend/SKILL.md +39 -0
- package/message-unsend/agents/openai.yaml +7 -0
- package/message-unsend/scripts/unsend.mjs +12 -0
- package/openclaw-memory-setup/SKILL.md +38 -0
- package/openclaw-memory-setup/agents/openai.yaml +7 -0
- package/openclaw-memory-setup/scripts/bench_ollama_embeddings.py +257 -0
- package/openclaw-memory-setup/scripts/set_openclaw_memory_model.py +240 -0
- package/openclaw-memory-setup/scripts/survey_host_readiness.py +379 -0
- package/package.json +51 -0
- package/shared/cli/actions.mjs +339 -0
- package/shared/cli/aibot-client.mjs +274 -0
- package/shared/cli/card-links.mjs +90 -0
- package/shared/cli/config.mjs +141 -0
- package/shared/cli/grix-hermes.mjs +87 -0
- package/shared/cli/targets.mjs +119 -0
- package/shared/references/grix-card-links.md +27 -0
- package/shared/references/hermes-grix-config.md +30 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: grix-egg
|
|
3
|
+
description: 在 Grix 安装私聊里处理 OpenClaw 或 Claude 侧安装工作流时使用。适用于收到 `install_id`、`egg/install`、`main_agent`、`install.route` 等上下文后,按安装路线完成安装、回报进度、发送卡片、拉群验收,并在身份不正确时继续修复。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Grix Egg
|
|
7
|
+
|
|
8
|
+
这是安装总编排技能。
|
|
9
|
+
|
|
10
|
+
开始前,先用 helper 校验安装上下文:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
node scripts/validate_install_context.mjs --from-file ./install-context.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 绝对规则
|
|
17
|
+
|
|
18
|
+
- 远端 Grix 查询走 [grix-query](../grix-query/SKILL.md)
|
|
19
|
+
- 远端群动作走 [grix-group](../grix-group/SKILL.md)
|
|
20
|
+
- 远端 agent / 分类动作走 [grix-admin](../grix-admin/SKILL.md)
|
|
21
|
+
- 消息卡片优先走 [message-send](../message-send/SKILL.md)
|
|
22
|
+
- 本地 OpenClaw 配置只能走官方 CLI
|
|
23
|
+
- 安装进行中不要主动改 `openclaw.json`
|
|
24
|
+
|
|
25
|
+
## 安装状态
|
|
26
|
+
|
|
27
|
+
开始、成功、失败都应发送独立状态卡。
|
|
28
|
+
|
|
29
|
+
格式参考:
|
|
30
|
+
|
|
31
|
+
- [Grix Card Links](../shared/references/grix-card-links.md)
|
|
32
|
+
- [Acceptance Checklist](references/acceptance-checklist.md)
|
|
33
|
+
|
|
34
|
+
需要生成卡片时,优先用:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
node scripts/card-link.mjs egg-status --install-id <INSTALL_ID> --status running --step downloading --summary 已下载
|
|
38
|
+
node scripts/card-link.mjs conversation --session-id <SESSION_ID> --session-type group --title 验收测试群
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 推荐主线
|
|
42
|
+
|
|
43
|
+
### `openclaw_create_new` / `openclaw_existing`
|
|
44
|
+
|
|
45
|
+
1. 识别安装包和目标路线
|
|
46
|
+
2. 如需新建远端 agent,先走 `grix-admin create_agent`
|
|
47
|
+
3. 本地绑定继续走 `grix-admin bind-local`
|
|
48
|
+
4. 下载并落位安装内容
|
|
49
|
+
5. 写入并校验 OpenClaw 配置
|
|
50
|
+
6. 如需自动更新,补 `grix auto update` cron
|
|
51
|
+
7. 创建测试群并拿到准确 `session_id`
|
|
52
|
+
8. 回当前私聊单独发送测试群会话卡片
|
|
53
|
+
9. 在测试群里做身份验收
|
|
54
|
+
10. 回答不正确就继续修,直到身份正确
|
|
55
|
+
|
|
56
|
+
### `claude_existing`
|
|
57
|
+
|
|
58
|
+
1. 定位目标 Claude agent
|
|
59
|
+
2. 安装 `skill.zip`
|
|
60
|
+
3. 如需同步 OpenClaw 配置,继续用官方 CLI
|
|
61
|
+
4. 校验后再决定是否需要拉群验收
|
|
62
|
+
|
|
63
|
+
## 验收规则
|
|
64
|
+
|
|
65
|
+
- 验收群一旦创建成功,就保存准确 `session_id`
|
|
66
|
+
- 后续所有群测消息都发到这个 `session_id`
|
|
67
|
+
- 如果拿到了准确 `session_id`,必须补一张会话卡片
|
|
68
|
+
- 配置已确认正确但人格还是旧结果时,才把 `openclaw gateway restart` 当成定向补救
|
|
69
|
+
|
|
70
|
+
## 收尾
|
|
71
|
+
|
|
72
|
+
- 成功:状态卡 + Agent 资料卡 + 下一步说明
|
|
73
|
+
- 失败:失败状态卡 + 清楚说明停在哪一步
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
|
|
7
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const cardScript = path.resolve(scriptDir, "../../message-send/scripts/card-link.mjs");
|
|
9
|
+
const result = spawnSync(process.execPath, [cardScript, ...process.argv.slice(2)], {
|
|
10
|
+
stdio: "inherit",
|
|
11
|
+
});
|
|
12
|
+
process.exit(result.status ?? 1);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
|
|
5
|
+
function cleanText(value) {
|
|
6
|
+
return String(value ?? "").trim();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function readPayload(argv) {
|
|
10
|
+
const fileIndex = argv.indexOf("--from-file");
|
|
11
|
+
if (fileIndex >= 0 && argv[fileIndex + 1]) {
|
|
12
|
+
return JSON.parse(fs.readFileSync(argv[fileIndex + 1], "utf8"));
|
|
13
|
+
}
|
|
14
|
+
const stdin = fs.readFileSync(0, "utf8").trim();
|
|
15
|
+
if (!stdin) {
|
|
16
|
+
throw new Error("No install context JSON provided.");
|
|
17
|
+
}
|
|
18
|
+
return JSON.parse(stdin);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function requiredForRoute(route) {
|
|
22
|
+
if (route === "openclaw_create_new" || route === "openclaw_existing") {
|
|
23
|
+
return ["install_id", "main_agent"];
|
|
24
|
+
}
|
|
25
|
+
if (route === "claude_existing") {
|
|
26
|
+
return ["install_id"];
|
|
27
|
+
}
|
|
28
|
+
return ["install_id"];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function buildSteps(route) {
|
|
32
|
+
if (route === "openclaw_create_new" || route === "openclaw_existing") {
|
|
33
|
+
return [
|
|
34
|
+
"准备安装上下文",
|
|
35
|
+
"必要时创建远端 API agent",
|
|
36
|
+
"写入并校验 OpenClaw 配置",
|
|
37
|
+
"发送安装状态卡",
|
|
38
|
+
"创建测试群并保存准确 session_id",
|
|
39
|
+
"向当前私聊发送测试群会话卡片",
|
|
40
|
+
"在测试群做身份验收并修到正确"
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
if (route === "claude_existing") {
|
|
44
|
+
return [
|
|
45
|
+
"准备 Claude 安装上下文",
|
|
46
|
+
"安装目标技能或包",
|
|
47
|
+
"必要时同步 OpenClaw 配置",
|
|
48
|
+
"发送状态卡并决定是否群测"
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
return ["识别路由并补齐上下文"];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const payload = readPayload(process.argv.slice(2));
|
|
56
|
+
const install = payload.install && typeof payload.install === "object" ? payload.install : {};
|
|
57
|
+
const route = cleanText(install.route || payload.route || payload.install_route);
|
|
58
|
+
const required = requiredForRoute(route);
|
|
59
|
+
const missing = required.filter((key) => !cleanText(payload[key] ?? install[key]));
|
|
60
|
+
const result = {
|
|
61
|
+
ok: true,
|
|
62
|
+
route,
|
|
63
|
+
missing,
|
|
64
|
+
is_ready: missing.length === 0 && Boolean(route),
|
|
65
|
+
steps: buildSteps(route),
|
|
66
|
+
};
|
|
67
|
+
console.log(JSON.stringify(result, null, 2));
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error(JSON.stringify({
|
|
70
|
+
ok: false,
|
|
71
|
+
error: error instanceof Error ? error.message : String(error)
|
|
72
|
+
}, null, 2));
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: grix-group
|
|
3
|
+
description: 管理 Grix 群聊生命周期和成员关系时使用。适用于建群、查群详情、退群、加人、移人、改角色、全员禁言、成员禁言、解散群等场景。通过 `terminal` 执行 `../shared/cli/grix-hermes.mjs group`。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Grix Group
|
|
7
|
+
|
|
8
|
+
群治理动作统一走共享 CLI,不假设 Hermes 内核里存在 `grix_group` tool。
|
|
9
|
+
|
|
10
|
+
## 执行方式
|
|
11
|
+
|
|
12
|
+
统一用:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
node scripts/group.mjs --action <action> ...
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
常用例子:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
node scripts/group.mjs --action create --name 版本验收群 --member-ids 1001,2001 --member-types 1,2
|
|
22
|
+
node scripts/group.mjs --action detail --session-id <SESSION_ID>
|
|
23
|
+
node scripts/group.mjs --action leave --session-id <SESSION_ID>
|
|
24
|
+
node scripts/group.mjs --action add_members --session-id <SESSION_ID> --member-ids 1002,1003 --member-types 1,1
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 规则
|
|
28
|
+
|
|
29
|
+
- 一次业务动作只做一次 CLI 调用
|
|
30
|
+
- `leave` 静默执行,不要先去群里发告别消息
|
|
31
|
+
- `memberIds` 和 `memberTypes` 数量要对应
|
|
32
|
+
- 不要把本地 agent 名、本地 `main_agent`、OpenClaw 本地 ID 直接当成 Grix 成员 ID
|
|
33
|
+
|
|
34
|
+
## 输出要求
|
|
35
|
+
|
|
36
|
+
- 成功时返回 `session_id`
|
|
37
|
+
- 如果是详情,返回成员数、禁言状态、关键配置
|
|
38
|
+
- 如果是加人/移人/角色更新,说明目标成员和结果
|
|
39
|
+
|
|
40
|
+
## 参考
|
|
41
|
+
|
|
42
|
+
- [Hermes Grix Runtime](../shared/references/hermes-grix-config.md)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
|
|
7
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const sharedCli = path.resolve(scriptDir, "../../shared/cli/grix-hermes.mjs");
|
|
9
|
+
const result = spawnSync(process.execPath, [sharedCli, "group", ...process.argv.slice(2)], {
|
|
10
|
+
stdio: "inherit",
|
|
11
|
+
});
|
|
12
|
+
process.exit(result.status ?? 1);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: grix-query
|
|
3
|
+
description: 查询 Grix 联系人、会话、消息历史时使用。适用于 Hermes 里需要查联系人、找会话、读某个会话历史、按关键词搜消息,但又不能改 Hermes 内核的场景。通过 `terminal` 执行 `../shared/cli/grix-hermes.mjs query`,走 Hermes 已配置的 Grix websocket 凭证。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Grix Query
|
|
7
|
+
|
|
8
|
+
只做只读查询。
|
|
9
|
+
|
|
10
|
+
## 入口
|
|
11
|
+
|
|
12
|
+
先判断用户要的是哪一类:
|
|
13
|
+
|
|
14
|
+
- `contact_search`
|
|
15
|
+
- `session_search`
|
|
16
|
+
- `message_history`
|
|
17
|
+
- `message_search`
|
|
18
|
+
|
|
19
|
+
如果用户要读消息,但没有准确 `session_id`,先做一次 `session_search`。
|
|
20
|
+
|
|
21
|
+
## 执行方式
|
|
22
|
+
|
|
23
|
+
统一用 `terminal` 执行:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
node scripts/query.mjs --action <action> ...
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
常用例子:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
node scripts/query.mjs --action contact_search --keyword alice
|
|
33
|
+
node scripts/query.mjs --action session_search --keyword 测试群
|
|
34
|
+
node scripts/query.mjs --action message_history --session-id <SESSION_ID> --limit 20
|
|
35
|
+
node scripts/query.mjs --action message_search --session-id <SESSION_ID> --keyword 身份 --limit 20
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 分页规则
|
|
39
|
+
|
|
40
|
+
- 第一页先用一个合理 `limit`
|
|
41
|
+
- 继续翻页时复用同一个 `session_id`
|
|
42
|
+
- `message_history` / `message_search` 下一页要带 `before_id`
|
|
43
|
+
|
|
44
|
+
## 输出要求
|
|
45
|
+
|
|
46
|
+
- 成功时明确返回关键 ID
|
|
47
|
+
- 联系人带 `peer_id` / `peer_type`
|
|
48
|
+
- 会话带 `session_id`
|
|
49
|
+
- 消息带 `msg_id` 和必要时间信息
|
|
50
|
+
|
|
51
|
+
## 参考
|
|
52
|
+
|
|
53
|
+
- [Hermes Grix Runtime](../shared/references/hermes-grix-config.md)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
|
|
7
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const sharedCli = path.resolve(scriptDir, "../../shared/cli/grix-hermes.mjs");
|
|
9
|
+
const result = spawnSync(process.execPath, [sharedCli, "query", ...process.argv.slice(2)], {
|
|
10
|
+
stdio: "inherit",
|
|
11
|
+
});
|
|
12
|
+
process.exit(result.status ?? 1);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: grix-register
|
|
3
|
+
description: 用户需要注册 Grix 账号、发送邮箱验证码、登录、创建首个 API agent 并继续完成本地绑定时使用。注册链路走 `scripts/grix_auth.py` 的 HTTP 组件,创建完 API agent 后继续交给 `grix-admin` 的本地绑定流程。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Grix Register
|
|
7
|
+
|
|
8
|
+
这个技能负责 HTTP 注册链路,不依赖 Hermes 内核改造。
|
|
9
|
+
|
|
10
|
+
## 执行方式
|
|
11
|
+
|
|
12
|
+
统一通过 `terminal` 调用:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
python3 scripts/grix_auth.py <subcommand> ...
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 常用子命令
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
python3 scripts/grix_auth.py send-email-code --email <EMAIL> --scene register
|
|
22
|
+
python3 scripts/grix_auth.py register --email <EMAIL> --password <PASSWORD> --email-code <CODE>
|
|
23
|
+
python3 scripts/grix_auth.py login --email <EMAIL> --password <PASSWORD>
|
|
24
|
+
python3 scripts/grix_auth.py create-api-agent --access-token <TOKEN> --agent-name <NAME>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 主线
|
|
28
|
+
|
|
29
|
+
1. 发送邮箱验证码
|
|
30
|
+
2. 完成注册或登录
|
|
31
|
+
3. 创建首个 `provider_type=3` 的 API agent
|
|
32
|
+
4. 从脚本返回里拿:
|
|
33
|
+
- `agent_name`
|
|
34
|
+
- `agent_id`
|
|
35
|
+
- `api_endpoint`
|
|
36
|
+
- `api_key`
|
|
37
|
+
5. 继续执行 [grix-admin](../grix-admin/SKILL.md) 的 `bind-local`
|
|
38
|
+
|
|
39
|
+
如果你想把“创建 API agent + 本地绑定”一次跑完,优先用:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
python3 scripts/create_api_agent_and_bind.py \
|
|
43
|
+
--access-token <TOKEN> \
|
|
44
|
+
--agent-name <NAME> \
|
|
45
|
+
--model <MODEL> \
|
|
46
|
+
--json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
如果已经有一份 `create-api-agent` 的 JSON 结果,也可以:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
python3 scripts/create_api_agent_and_bind.py \
|
|
53
|
+
--agent-json-file ./created-agent.json \
|
|
54
|
+
--model <MODEL> \
|
|
55
|
+
--dry-run \
|
|
56
|
+
--json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 规则
|
|
60
|
+
|
|
61
|
+
- 不要求用户自己开浏览器
|
|
62
|
+
- HTTP 只用于注册、登录、验证码、首个 API agent 创建
|
|
63
|
+
- 本地 OpenClaw 绑定不在这个技能里手工拼,创建完就继续交给 `grix-admin`
|
|
64
|
+
|
|
65
|
+
## 参考
|
|
66
|
+
|
|
67
|
+
- [Hermes Grix Runtime](../shared/references/hermes-grix-config.md)
|
|
68
|
+
- [Handoff To grix-admin](references/handoff-contract.md)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Handoff To grix-admin
|
|
2
|
+
|
|
3
|
+
`grix-register` 在完成注册、登录和首个 API agent 创建后,不再自己手工写本地 OpenClaw 配置。
|
|
4
|
+
|
|
5
|
+
它应继续把下面这组字段交给 `grix-admin`:
|
|
6
|
+
|
|
7
|
+
- `agent_name`
|
|
8
|
+
- `agent_id`
|
|
9
|
+
- `api_endpoint`
|
|
10
|
+
- `api_key`
|
|
11
|
+
|
|
12
|
+
推荐后续命令:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
python3 ../grix-admin/scripts/bind_local.py \
|
|
16
|
+
--agent-name <AGENT_NAME> \
|
|
17
|
+
--agent-id <AGENT_ID> \
|
|
18
|
+
--api-endpoint <WS_URL> \
|
|
19
|
+
--api-key <API_KEY> \
|
|
20
|
+
--model <MODEL>
|
|
21
|
+
```
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Create one API agent through grix_auth.py and optionally bind it locally."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import json
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def load_or_create_payload(args: argparse.Namespace) -> dict[str, Any]:
|
|
15
|
+
if args.agent_json_file:
|
|
16
|
+
return json.loads(Path(args.agent_json_file).read_text(encoding="utf-8"))
|
|
17
|
+
|
|
18
|
+
auth_script = Path(__file__).with_name("grix_auth.py")
|
|
19
|
+
cmd = [
|
|
20
|
+
sys.executable,
|
|
21
|
+
str(auth_script),
|
|
22
|
+
"--base-url",
|
|
23
|
+
args.base_url,
|
|
24
|
+
"create-api-agent",
|
|
25
|
+
"--access-token",
|
|
26
|
+
args.access_token,
|
|
27
|
+
"--agent-name",
|
|
28
|
+
args.agent_name,
|
|
29
|
+
]
|
|
30
|
+
if args.avatar_url:
|
|
31
|
+
cmd.extend(["--avatar-url", args.avatar_url])
|
|
32
|
+
result = subprocess.run(cmd, text=True, capture_output=True)
|
|
33
|
+
if result.returncode != 0:
|
|
34
|
+
raise RuntimeError((result.stderr or result.stdout or "").strip())
|
|
35
|
+
return json.loads(result.stdout)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def main() -> int:
|
|
39
|
+
parser = argparse.ArgumentParser(description="Create one API agent and continue to local bind.")
|
|
40
|
+
parser.add_argument("--access-token", default="")
|
|
41
|
+
parser.add_argument("--agent-name", default="")
|
|
42
|
+
parser.add_argument("--avatar-url", default="")
|
|
43
|
+
parser.add_argument("--base-url", default="https://grix.dhf.pub")
|
|
44
|
+
parser.add_argument("--agent-json-file", default="", help="Use an existing create-api-agent JSON result instead of calling HTTP.")
|
|
45
|
+
parser.add_argument("--model", default="")
|
|
46
|
+
parser.add_argument("--openclaw", default="openclaw")
|
|
47
|
+
parser.add_argument("--openclaw-home", default="")
|
|
48
|
+
parser.add_argument("--skip-current", action="store_true")
|
|
49
|
+
parser.add_argument("--dry-run", action="store_true")
|
|
50
|
+
parser.add_argument("--json", action="store_true")
|
|
51
|
+
args = parser.parse_args()
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
if not args.agent_json_file and (not args.access_token or not args.agent_name):
|
|
55
|
+
raise RuntimeError("Need --agent-json-file or both --access-token and --agent-name.")
|
|
56
|
+
created_payload = load_or_create_payload(args)
|
|
57
|
+
|
|
58
|
+
bind_script = Path(__file__).resolve().parents[2] / "grix-admin" / "scripts" / "bind_from_json.py"
|
|
59
|
+
cmd = [
|
|
60
|
+
sys.executable,
|
|
61
|
+
str(bind_script),
|
|
62
|
+
]
|
|
63
|
+
if args.model:
|
|
64
|
+
cmd.extend(["--model", args.model])
|
|
65
|
+
if args.openclaw:
|
|
66
|
+
cmd.extend(["--openclaw", args.openclaw])
|
|
67
|
+
if args.openclaw_home:
|
|
68
|
+
cmd.extend(["--openclaw-home", args.openclaw_home])
|
|
69
|
+
if args.skip_current:
|
|
70
|
+
cmd.append("--skip-current")
|
|
71
|
+
if args.dry_run:
|
|
72
|
+
cmd.append("--dry-run")
|
|
73
|
+
if args.json:
|
|
74
|
+
cmd.append("--json")
|
|
75
|
+
|
|
76
|
+
bind_result = subprocess.run(
|
|
77
|
+
cmd,
|
|
78
|
+
input=json.dumps(created_payload, ensure_ascii=False),
|
|
79
|
+
text=True,
|
|
80
|
+
capture_output=True,
|
|
81
|
+
)
|
|
82
|
+
if bind_result.returncode != 0:
|
|
83
|
+
raise RuntimeError((bind_result.stderr or bind_result.stdout or "").strip())
|
|
84
|
+
|
|
85
|
+
if args.json:
|
|
86
|
+
payload = {
|
|
87
|
+
"ok": True,
|
|
88
|
+
"created_agent": created_payload,
|
|
89
|
+
"bind_result": json.loads(bind_result.stdout) if bind_result.stdout.strip() else None,
|
|
90
|
+
}
|
|
91
|
+
print(json.dumps(payload, ensure_ascii=False, indent=2))
|
|
92
|
+
else:
|
|
93
|
+
if bind_result.stdout:
|
|
94
|
+
sys.stdout.write(bind_result.stdout)
|
|
95
|
+
return 0
|
|
96
|
+
except Exception as exc: # noqa: BLE001
|
|
97
|
+
if args.json:
|
|
98
|
+
print(json.dumps({"ok": False, "error": str(exc)}, ensure_ascii=False, indent=2), file=sys.stderr)
|
|
99
|
+
else:
|
|
100
|
+
print(str(exc), file=sys.stderr)
|
|
101
|
+
return 1
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
raise SystemExit(main())
|