sophhub 0.4.57 → 0.4.59
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/agents/ai-dept-admin/.config.json +2 -2
- package/package.json +1 -1
- package/skills/agent-install/skill.json +22 -1
- package/skills/agent-install/src/SKILL.md +10 -4
- package/skills/agent-install/src/scripts/resolve_new_instance.py +94 -0
- package/skills/agent-install/src/scripts/update_openclaw.py +12 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.0.
|
|
2
|
+
"version": "1.0.4",
|
|
3
3
|
"agent_id": "ai-dept-admin",
|
|
4
4
|
"description": "部门管理主 Agent:部门知识库、人员档案与绩效、会议(单次/周期/查询)、待办与复盘记录",
|
|
5
5
|
"bot_api_enabled": false,
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"auto_install": true
|
|
34
34
|
}
|
|
35
35
|
],
|
|
36
|
-
"llm": "
|
|
36
|
+
"llm": "DeepSeek-V4-Pro"
|
|
37
37
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-install",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"types": [
|
|
5
5
|
"store"
|
|
6
6
|
],
|
|
7
7
|
"displayName": "Agent安装",
|
|
8
8
|
"description": "安装或升级 Sophclaw Agent(含占位替换、备份、post_install 脚本与自动安装 skill)。",
|
|
9
9
|
"changelog": [
|
|
10
|
+
{
|
|
11
|
+
"changes": [
|
|
12
|
+
"修复 update_openclaw.py 新建实例时覆盖原实例的严重 BUG:改为按目标 openclaw_id 定位条目,新建时追加、不覆盖同源原实例"
|
|
13
|
+
],
|
|
14
|
+
"date": "2026-07-09",
|
|
15
|
+
"version": "0.1.15"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"changes": [
|
|
19
|
+
"安装汇总以 openclaw_id(实例标识)为主,不再展示源 agent_id,避免与实例标识混淆"
|
|
20
|
+
],
|
|
21
|
+
"date": "2026-07-09",
|
|
22
|
+
"version": "0.1.14"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"changes": [
|
|
26
|
+
"新增 resolve_new_instance.py:新建实例时确定生成下一个可用的 openclaw_id 和 workspace,不再依赖 LLM 手动生成"
|
|
27
|
+
],
|
|
28
|
+
"date": "2026-07-09",
|
|
29
|
+
"version": "0.1.13"
|
|
30
|
+
},
|
|
10
31
|
{
|
|
11
32
|
"changes": [
|
|
12
33
|
"新建实例时仅询问 agent_name,openclaw_id 和 workspace 按规则自动生成"
|
|
@@ -61,9 +61,15 @@ uv run {baseDir}/scripts/resolve_install_params.py \
|
|
|
61
61
|
|
|
62
62
|
确认 `openclaw_id`、`workspace`、`agent_name`。有 `placeholder_catalog` 时让用户确认替换文案,用户可覆盖默认值。
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
用户选择「新建实例」时,**仅询问 `agent_name`**(显示名称),`openclaw_id` 和 `workspace` 由脚本确定生成,不向用户索要:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
uv run {baseDir}/scripts/resolve_new_instance.py \
|
|
68
|
+
--agent-id "{agent_id}" \
|
|
69
|
+
--path "/home/node/.openclaw/workspace"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
取返回的 `openclaw_id`(形如 `{agent_id}-{N}`)和 `workspace`(实例 #1 workspace 末尾追加 `-{N}`),后续步骤按此传入 `--openclaw-id` / `--workspace`。
|
|
67
73
|
|
|
68
74
|
**2)按需替换 .md 中的占位符**(有 `placeholders` 时)
|
|
69
75
|
|
|
@@ -158,7 +164,7 @@ uv run {baseDir}/scripts/update_openclaw.py \
|
|
|
158
164
|
|
|
159
165
|
脚本自动处理 `auto_generate_image_description`、`heartbeat`(仅当 `.config.json` 显式配置时写入)、`bot-api` 账号等,输出中包含对应字段便于核对。
|
|
160
166
|
|
|
161
|
-
|
|
167
|
+
完成后汇总(以实例标识 `openclaw_id` 为主,不展示源 `agent_id` 以免与实例标识混淆):openclaw_id、结果(新装/升级/重置/新建实例)、workspace、显示名称、备份目录、skill 列表、bot-api(密钥走安全渠道)。
|
|
162
168
|
|
|
163
169
|
---
|
|
164
170
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""为「新建实例」确定性地生成下一个可用的 openclaw_id 和 workspace。
|
|
3
|
+
|
|
4
|
+
读取 openclaw.json,扫描 agents.list 中所有匹配 ^{agent_id}(-(\d+))?$ 的条目,
|
|
5
|
+
取最大编号 + 1 作为新实例编号,输出 openclaw_id 与 workspace。
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import json
|
|
11
|
+
import re
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
from common import (
|
|
16
|
+
default_openclaw_config_path,
|
|
17
|
+
find_agent_entry,
|
|
18
|
+
load_agent_definition,
|
|
19
|
+
load_openclaw_config,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def next_instance_number(existing_ids: list[str], agent_id: str) -> int:
|
|
24
|
+
"""从已有 id 列表算出下一个实例编号。裸 agent_id 视为 1,agent_id-N 视为 N。"""
|
|
25
|
+
pattern = re.compile(rf"^{re.escape(agent_id)}(?:-(\d+))?$")
|
|
26
|
+
numbers: set[int] = set()
|
|
27
|
+
for eid in existing_ids:
|
|
28
|
+
if not isinstance(eid, str):
|
|
29
|
+
continue
|
|
30
|
+
match = pattern.fullmatch(eid)
|
|
31
|
+
if match is None:
|
|
32
|
+
continue
|
|
33
|
+
suffix = match.group(1)
|
|
34
|
+
numbers.add(int(suffix) if suffix else 1)
|
|
35
|
+
if not numbers:
|
|
36
|
+
return 2
|
|
37
|
+
return max(numbers) + 1
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def base_workspace_for(agent_id: str, agent_def: dict, config: dict) -> str:
|
|
41
|
+
"""实例 #1 的实际 workspace 作为新实例 workspace 的基。取不到则回退到 .config.json 的 workspace。"""
|
|
42
|
+
entry = find_agent_entry(config, agent_id)
|
|
43
|
+
if entry and isinstance(entry.get("workspace"), str) and entry["workspace"].strip():
|
|
44
|
+
return entry["workspace"].rstrip("/")
|
|
45
|
+
configured = agent_def.get("install", {}).get("workspace") or agent_def.get("workspace")
|
|
46
|
+
if isinstance(configured, str) and configured.strip():
|
|
47
|
+
return configured.rstrip("/")
|
|
48
|
+
return f"/home/node/.openclaw/workspace-{agent_id}"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def resolve_new_instance(agent_id: str, source_path: Path, config_path: Path) -> dict[str, object]:
|
|
52
|
+
agent_def = load_agent_definition(agent_id, source_path)
|
|
53
|
+
openclaw = load_openclaw_config(config_path)
|
|
54
|
+
agents_list = openclaw.get("agents", {}).get("list", []) or []
|
|
55
|
+
existing_ids = [a.get("id") for a in agents_list if isinstance(a, dict)]
|
|
56
|
+
|
|
57
|
+
next_n = next_instance_number(existing_ids, agent_id)
|
|
58
|
+
new_openclaw_id = f"{agent_id}-{next_n}"
|
|
59
|
+
base_ws = base_workspace_for(agent_id, agent_def, openclaw)
|
|
60
|
+
new_workspace = f"{base_ws}-{next_n}"
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
"ok": True,
|
|
64
|
+
"agent_id": agent_id,
|
|
65
|
+
"openclaw_id": new_openclaw_id,
|
|
66
|
+
"workspace": new_workspace,
|
|
67
|
+
"instance_number": next_n,
|
|
68
|
+
"message": f"新实例参数:openclaw_id={new_openclaw_id},workspace={new_workspace}",
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def main() -> int:
|
|
73
|
+
parser = argparse.ArgumentParser(description="为新建实例生成下一个可用的 openclaw_id 和 workspace")
|
|
74
|
+
parser.add_argument("--agent-id", required=True, help="Agent ID")
|
|
75
|
+
parser.add_argument("--path", required=True, help="Agent 下载目录(sophhub agent download 的 --path)")
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
"--config",
|
|
78
|
+
default=str(default_openclaw_config_path()),
|
|
79
|
+
help="openclaw.json 路径",
|
|
80
|
+
)
|
|
81
|
+
args = parser.parse_args()
|
|
82
|
+
|
|
83
|
+
result = resolve_new_instance(
|
|
84
|
+
args.agent_id,
|
|
85
|
+
Path(args.path).expanduser().resolve(),
|
|
86
|
+
Path(args.config).expanduser().resolve(),
|
|
87
|
+
)
|
|
88
|
+
json.dump(result, sys.stdout, indent=2, ensure_ascii=False)
|
|
89
|
+
sys.stdout.write("\n")
|
|
90
|
+
return 0
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if __name__ == "__main__":
|
|
94
|
+
raise SystemExit(main())
|
|
@@ -14,6 +14,7 @@ from common import (
|
|
|
14
14
|
deep_merge_dict,
|
|
15
15
|
default_openclaw_config_path,
|
|
16
16
|
dump_json,
|
|
17
|
+
entry_matches_source_agent,
|
|
17
18
|
find_agent_entry,
|
|
18
19
|
find_bot_api_accounts_by_agent_id,
|
|
19
20
|
find_agent_by_workspace,
|
|
@@ -165,15 +166,18 @@ def update_openclaw(
|
|
|
165
166
|
config = load_openclaw_config(config_path)
|
|
166
167
|
main_migration = _ensure_main_agent_in_list(config, config_path)
|
|
167
168
|
desired_workspace = resolved_workspace or agent_def.get("install", {}).get("workspace") or agent_def.get("workspace")
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
target_agent_id = previous.get("id") if previous.get("id") else agent_id
|
|
169
|
+
# 确定目标实例 id:显式传入的 openclaw_id 优先(支持新建/指定实例更新)
|
|
170
|
+
resolved_previous = resolve_existing_agent_entry(config_path, config, agent_id, desired_workspace)
|
|
171
|
+
if resolved_openclaw_id:
|
|
172
|
+
target_agent_id = resolved_openclaw_id
|
|
173
|
+
elif resolved_previous is not None:
|
|
174
|
+
target_agent_id = resolved_previous.get("id") or agent_id
|
|
175
175
|
else:
|
|
176
|
-
target_agent_id =
|
|
176
|
+
target_agent_id = agent_id
|
|
177
|
+
# previous = 目标 id 对应的已有条目(更新场景);校验若已被不同源 agent 占用则报错
|
|
178
|
+
previous = find_agent_entry(config, target_agent_id)
|
|
179
|
+
if previous is not None and not entry_matches_source_agent(config_path, previous, agent_id):
|
|
180
|
+
raise ValueError(f"目标 openclaw id 已存在且不属于当前 Agent: {target_agent_id}")
|
|
177
181
|
|
|
178
182
|
entry = build_agent_entry(
|
|
179
183
|
agent_def,
|