@shundoo-ai/dsh-cosmic 1.0.0 → 1.0.2-alpha.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/cordis.patch.yml +4 -0
- package/package.json +1 -3
- package/run.py +3 -3
- package/skills/cosmic-build/references/entity-download.md +4 -4
- package/skills/cosmic-build/skills/cosmic-vibe-coding/SKILL.md +7 -6
- package/skills/cosmic-build/skills/cosmic-vibe-coding/scripts/dev.py +4 -4
- package/skills/cosmic-dev-best-practices/references/cosmic-jdwp-debug-config.md +1 -1
- package/skills/cosmic-dev-best-practices/references/cosmic-meta-api.md +1 -1
- package/skills/erp-analysis/SKILL.md +11 -10
- package/skills/erp-analysis/references/email-delivery.md +6 -6
- package/skills/erp-analysis/references/html-report-guide.md +2 -2
- package/skills/erp-analysis/references/index.md +7 -7
- package/skills/erp-analysis/references/session-review-workflow.md +1 -1
- package/skills/erp-analysis/references/subprocess-execution.md +5 -5
- package/skills/erp-analysis/scripts/init-python.ps1 +13 -6
- package/skills/erp-analysis/scripts/init-python.sh +11 -5
- package/skills/erp-analysis/templates/AGENTS.template.md +18 -8
- package/agent.cordis.yml +0 -269
- package/preset.yml +0 -2
package/cordis.patch.yml
CHANGED
package/package.json
CHANGED
package/run.py
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
用法(子进程执行模式,但去掉 heredoc/临时文件层):
|
|
11
11
|
macOS/Linux:
|
|
12
|
-
ANALYSIS_ID=<id> {
|
|
12
|
+
ANALYSIS_ID=<id> {VENV}/bin/python {PRESET}/run.py runs/query.py
|
|
13
13
|
Windows PowerShell:
|
|
14
|
-
$env:ANALYSIS_ID="<id>"; {
|
|
14
|
+
$env:ANALYSIS_ID="<id>"; {VENV}/Scripts/python.exe {PRESET}/run.py runs/query.py
|
|
15
15
|
|
|
16
16
|
目标脚本内直接读环境变量:
|
|
17
17
|
PRESET = os.environ["PRESET_DIR"]
|
|
@@ -52,7 +52,7 @@ def main():
|
|
|
52
52
|
env["OUT_DIR"] = out_dir
|
|
53
53
|
env["ANALYSIS_ID"] = analysis_id
|
|
54
54
|
|
|
55
|
-
# 子进程复用当前解释器(=
|
|
55
|
+
# 子进程复用当前解释器(= venv 里的 python,跨平台恒正确)
|
|
56
56
|
return subprocess.call([sys.executable] + sys.argv[1:], env=env)
|
|
57
57
|
|
|
58
58
|
|
|
@@ -24,7 +24,7 @@ preset(标准,随分发,不动)
|
|
|
24
24
|
agent 查数据时遇到企业扩展的情况(字段缺失 / 对象找不到),按需下载该实体到工作区:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
{
|
|
27
|
+
{VENV}/bin/python {PRESET}/skills/cosmic-dev/scripts/entity-download.py --entity <实体标识>
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
输出到工作区 `.dsh/cosmic/erpdb/scheme/<实体标识>/<实体标识>.entity.md`。
|
|
@@ -34,7 +34,7 @@ agent 查数据时遇到企业扩展的情况(字段缺失 / 对象找不到
|
|
|
34
34
|
> 切换 ERP 环境、或首次绑定某企业且确认有大范围扩展时,全量刷新:
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
{
|
|
37
|
+
{VENV}/bin/python {PRESET}/skills/cosmic-dev/scripts/entity-download.py --force
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
- 读 preset `entity-map.md` 全部实体标识,输出到工作区 `.dsh/cosmic/erpdb/scheme/`;
|
|
@@ -48,13 +48,13 @@ agent 查数据时遇到企业扩展的情况(字段缺失 / 对象找不到
|
|
|
48
48
|
3. **对象找不到**:entity-map(preset→工作区)grep 不到实体标识 → 二开/新增对象。**不要反复试关键词**,直接 queryForms 搜:
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
{
|
|
51
|
+
{VENV}/bin/python {PRESET}/skills/cosmic-dev/skills/cosmic-meta-api/scripts/cosmic_api.py queryForms --keyword <关键词>
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
从结果取目标表单的 `formNumber`(表单编码 = 实体标识)。**若命中多个同名/相似业务对象(如多个「报关单」分属不同应用/业务云),不要自己猜测,列出候选(表单名称 + 实体标识 + 归属)询问用户选哪个**;用户选定后下载:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
|
-
{
|
|
57
|
+
{VENV}/bin/python {PRESET}/skills/cosmic-dev/scripts/entity-download.py --entity <formNumber>
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
下载成功后工作区 entity-map 自动追加该对象(中文名从 entity.md 的 `**DisplayName:**` 读,归属应用/业务云由脚本内部经 `queryForms --keyword <formNumber>` 反查 `appName`/`cloudName` 自动填充,无需手动传参)。
|
|
@@ -26,18 +26,19 @@ description: >
|
|
|
26
26
|
## 触发后的第一步:读环境配置
|
|
27
27
|
|
|
28
28
|
> 路径约定(与 erp-analysis 一致):
|
|
29
|
-
> - preset 根 `{PRESET}
|
|
29
|
+
> - preset 根 `{PRESET}` = `$DSH_PROFILE_DIR/node_modules/@shundoo-ai/dsh-cosmic`(preset 包目录,含 `run.py`、`.config/`、`skills/`;`$DSH_PROFILE_DIR` 由 dsh 注入每次 shell)。权威定义见 `run.py` 里 `PRESET = os.path.dirname(os.path.abspath(__file__))`——等价于本 SKILL.md 目录的上两级。
|
|
30
30
|
> - 本 skill 目录 `{SKILL_DIR}` = `{PRESET}/skills/cosmic-build/skills/cosmic-vibe-coding`
|
|
31
|
-
> - Python
|
|
31
|
+
> - Python 运行时 `{VENV}` = `$DSH_HOME/cache/cosmic/venv`(机器级,与 preset 版本解耦):
|
|
32
|
+
> `{VENV}/bin/python`(macOS/Linux)/ `{VENV}/Scripts/python.exe`(Windows)
|
|
32
33
|
|
|
33
34
|
无论走哪个职责,agent 先执行:
|
|
34
35
|
|
|
35
36
|
```bash
|
|
36
|
-
{
|
|
37
|
+
{VENV}/bin/python {SKILL_DIR}/scripts/dev.py read
|
|
37
38
|
```
|
|
38
39
|
|
|
39
40
|
- 输出的 JSON 里 `erp_url` / `account_id` / `java_home` 等**关键字段非空** → 配置就绪,直接走职责②③。
|
|
40
|
-
- 输出 `{}`(未初始化)→ 引导用户跑 `{
|
|
41
|
+
- 输出 `{}`(未初始化)→ 引导用户跑 `{VENV}/bin/python {SKILL_DIR}/scripts/dev.py init` 初始化(读 `.kd/config.json` 覆盖 dev.json),即职责①。
|
|
41
42
|
|
|
42
43
|
---
|
|
43
44
|
|
|
@@ -63,8 +64,8 @@ description: >
|
|
|
63
64
|
2. **用 `scripts/dev.py` 生成环境配置**(从 `.kd/config.json` 读,不手工输入):
|
|
64
65
|
|
|
65
66
|
```bash
|
|
66
|
-
{
|
|
67
|
-
{
|
|
67
|
+
{VENV}/bin/python {SKILL_DIR}/scripts/dev.py init # 读 .kd/config.json 的 url → 覆盖 dev.json
|
|
68
|
+
{VENV}/bin/python {SKILL_DIR}/scripts/dev.py read # 日常只读 dev.json
|
|
68
69
|
```
|
|
69
70
|
|
|
70
71
|
`dev.py init` 读 `<cwd>/.dsh/cosmic/.kd/config.json`(default env,复用 kd_env_loader,与 erp-analysis 同源),取 `url` 自动解析端口;**accountId 配置有值直接用,为空则调 `getAllDatacenters.do` 自动填**(优先 `default:true` 的数据中心,否则取第一个;失败保持空),**tenantId 配置有值用配置、为空默认 `ierp`**、`java_home` 从 IDEA 项目 SDK 自动发现,并**覆盖** `<cwd>/.dsh/cosmic/config/dev.json`。**若 url 为空,脚本中断并提醒「设置 erp 登录信息」。**
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
无参打印帮助。
|
|
14
14
|
|
|
15
15
|
用法:
|
|
16
|
-
{
|
|
17
|
-
{
|
|
18
|
-
{
|
|
19
|
-
{
|
|
16
|
+
{VENV}/bin/python dev.py init # 初始化:读 .kd/config.json → 覆盖 dev.json
|
|
17
|
+
{VENV}/bin/python dev.py read # 只读 dev.json
|
|
18
|
+
{VENV}/bin/python dev.py --read # 只读 dev.json(兼容旧用法)
|
|
19
|
+
{VENV}/bin/python dev.py --config <path> init|read # 指定配置文件路径
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
22
|
import argparse
|
|
@@ -122,7 +122,7 @@ JH=<cosmic安装目录>/jdk_mac_x86
|
|
|
122
122
|
**重新热部署 `sd-yun-wrzs`**(重启后执行):
|
|
123
123
|
|
|
124
124
|
```bash
|
|
125
|
-
SKILL_DIR=$
|
|
125
|
+
SKILL_DIR=$DSH_PROFILE_DIR/node_modules/@shundoo-ai/dsh-cosmic/skills/cosmic-build/skills/cosmic-vibe-coding
|
|
126
126
|
JH=<cosmic安装目录>/jdk_mac_x86
|
|
127
127
|
PID=$(lsof -tiTCP:8080 -sTCP:LISTEN | head -1)
|
|
128
128
|
"$JH/bin/java" -cp "$JH/lib/tools.jar:$SKILL_DIR/assets/kd-reloadjar-agent.jar" kd.reloadjar.Attacher \
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
13
|
{PYTHON} {cosmic_api} <命令> [参数]
|
|
14
|
-
# {PYTHON} = {
|
|
14
|
+
# {PYTHON} = {VENV}/bin/python(macOS/Linux);{VENV}/Scripts/python.exe(Windows)
|
|
15
15
|
# {cosmic_api} = {PRESET}/skills/cosmic-build/skills/cosmic-meta-api/scripts/cosmic_api.py
|
|
16
16
|
```
|
|
17
17
|
|
|
@@ -43,7 +43,7 @@ erp-analysis/
|
|
|
43
43
|
│ ├── report_builder_markdown.py ← Markdown 报告(Jinja2)
|
|
44
44
|
│ ├── report_analysis_id.py ← 分析 ID 生成
|
|
45
45
|
│ ├── send_email.py ← 邮件发送(smtplib + MIME)
|
|
46
|
-
│ ├── init-python.sh / init-python.ps1 ← Python 运行时初始化(uv
|
|
46
|
+
│ ├── init-python.sh / init-python.ps1 ← Python 运行时初始化(uv;建到 $DSH_HOME/cache/cosmic/venv)
|
|
47
47
|
│ └── requirements.txt ← 依赖清单(含 requests:传输层 gzip 协商必需,缺失时大查询慢 7 倍+)
|
|
48
48
|
└── templates/
|
|
49
49
|
├── report_template.j2 ← HTML 模板
|
|
@@ -54,7 +54,8 @@ erp-analysis/
|
|
|
54
54
|
|
|
55
55
|
路径分三层,别混:
|
|
56
56
|
|
|
57
|
-
- **preset 根 `{PRESET}
|
|
57
|
+
- **preset 根 `{PRESET}`** = `$DSH_PROFILE_DIR/node_modules/@shundoo-ai/dsh-cosmic`(preset 包目录,含 `run.py`、`.config/`、`skills/`;`$DSH_PROFILE_DIR` 由 dsh 注入每次 shell)。**权威定义**:read `{PRESET}/run.py` 里的 `PRESET = os.path.dirname(os.path.abspath(__file__))`——等价于本 SKILL.md 目录(`{PRESET}/skills/erp-analysis/`)的上两级。
|
|
58
|
+
- **Python 运行时 `{VENV}`**:`$DSH_HOME/cache/cosmic/venv` —— **机器级**、与 preset 版本解耦(升级 preset 不重建);**不在 preset 根、不在工作目录**。`$DSH_HOME` 由 dsh 注入每次 shell,缺省 `~/.dsh`。
|
|
58
59
|
- **skill 目录**:`{PRESET}/skills/erp-analysis/`(本 SKILL.md 所在,含 `references/`、`scripts/`)。
|
|
59
60
|
- **工作目录 cwd**:独立的产物目录(产物落 `runs/`、`runtime/`、`config/`)。
|
|
60
61
|
|
|
@@ -70,13 +71,13 @@ erp-analysis/
|
|
|
70
71
|
|
|
71
72
|
```bash
|
|
72
73
|
# macOS/Linux
|
|
73
|
-
ANALYSIS_ID=<id> {
|
|
74
|
+
ANALYSIS_ID=<id> {VENV}/bin/python {PRESET}/run.py runs/<session>/<analysis_id>/xxx.py
|
|
74
75
|
|
|
75
76
|
# Windows PowerShell
|
|
76
|
-
$env:ANALYSIS_ID="<id>"; {
|
|
77
|
+
$env:ANALYSIS_ID="<id>"; {VENV}/Scripts/python.exe {PRESET}/run.py runs/<session>/<analysis_id>/xxx.py
|
|
77
78
|
```
|
|
78
79
|
|
|
79
|
-
`ANALYSIS_ID` 由 agent 分析开始时生成一次(`{
|
|
80
|
+
`ANALYSIS_ID` 由 agent 分析开始时生成一次(`{VENV}/bin/python -c "import sys; sys.path.insert(0, '{PRESET}/skills/erp-analysis/scripts'); from report_analysis_id import gen_analysis_id; print(gen_analysis_id())"`),一次分析的所有脚本共用一个值。
|
|
80
81
|
|
|
81
82
|
## 标准脚本头(agent 写脚本必用,照抄)
|
|
82
83
|
|
|
@@ -98,9 +99,9 @@ from _core.commands import do_auth
|
|
|
98
99
|
|
|
99
100
|
第一动作:`read` `{PRESET}/skills/erp-analysis/references/index.md`,严格按其流程执行。
|
|
100
101
|
|
|
101
|
-
> **entity-map.md**:先调 `{
|
|
102
|
+
> **entity-map.md**:先调 `{VENV}/bin/python {PRESET}/skills/cosmic-build/scripts/entity-download.py --map-paths` 拿两个绝对路径(preset 标准实体 + 工作区企业新增对象),再依次 `grep`:先 grep preset(命中率高)、无果再 grep 工作区。**禁止 `read` 全文加载**(580KB 炸 token)。工作区 entity-map 已由 `erp-config.py` 自动初始化(空表头),grep 无匹配 = 无企业新增对象。
|
|
102
103
|
>
|
|
103
|
-
> **scheme 元数据**:先调 `{
|
|
104
|
+
> **scheme 元数据**:先调 `{VENV}/bin/python {PRESET}/skills/cosmic-build/scripts/entity-download.py --path {entity}` 拿实体 entity.md 的绝对路径(内部已处理「工作区企业扩展优先、preset 标准兜底」),再 `read` 该路径。字段引用用 **Name 列**(字段标识)。⚠️ **模板 skill 已写死字段名时,跳过 entity.md 全文 read**(直接信 skill 写脚本,详见 index.md Step 4)。
|
|
104
105
|
>
|
|
105
106
|
> **API 调用**:统一走 `_core.config` 的 `_api_call()`(见标准脚本头)。已注册 endpoint:`dataQuery`、`dataQueryWithPagination`。调用代码见 `references/api-reference.md` §五,执行策略见 `references/api-execution.md`。
|
|
106
107
|
|
|
@@ -145,7 +146,7 @@ DSH 会话界面只有 `write`/`edit` 工具**本轮**触碰过的文件才会
|
|
|
145
146
|
|
|
146
147
|
## 运行时与凭证
|
|
147
148
|
|
|
148
|
-
- Python:`{
|
|
149
|
+
- Python:`{VENV}/`(preset 根,uv 创建,多工作区共享)。首次使用跑 init-python:macOS/Linux 用 `bash {PRESET}/skills/erp-analysis/scripts/init-python.sh`,Windows 用 `pwsh {PRESET}/skills/erp-analysis/scripts/init-python.ps1`。
|
|
149
150
|
- token 缓存 / openapi 元数据缓存:由 `_core.config` 自动解析到 `RUNTIME_DIR`(有 app 会话时为 `<cwd>/app/<appCode>/_runtime/cosmic-metadata/`,无则为 `<cwd>/app/_runtime/cosmic-metadata/`),无需手动指定;token 缓存默认 25min,到期自动重新登录。
|
|
150
151
|
- 凭证(per-workspace):`_core` 优先读工作区 `.dsh/cosmic/.kd/config.json`(真实凭证,不进 git),缺失时从 preset 模板 `cosmic-build/skills/config.json` 自动拷贝。
|
|
151
152
|
|
|
@@ -155,9 +156,9 @@ DSH 会话界面只有 `write`/`edit` 工具**本轮**触碰过的文件才会
|
|
|
155
156
|
|
|
156
157
|
**主流程(选项目 → 自动填连接信息 → 只补账号密码):**
|
|
157
158
|
|
|
158
|
-
1. 列项目:`{
|
|
159
|
+
1. 列项目:`{VENV}/bin/python {PRESET}/skills/erp-analysis/scripts/erp-config.py list`,把输出的 markdown 表格转述给用户选(含项目标识 + 名称 + 生产/测试/自定义)。
|
|
159
160
|
2. 用户选项目 → `erp-config.py apply --id <项目标识>`:从 preset `cosmic-build/skills/tenant.json` 取该项目的 url/tenantId/accountId/client_id/client_secret/x-acgw-identity 写入,**并清空 user/password**(切换项目 = 换身份,旧账号无意义)。
|
|
160
|
-
3. 读当前配置确认:`{
|
|
161
|
+
3. 读当前配置确认:`{VENV}/bin/python {PRESET}/skills/erp-analysis/scripts/erp-config.py read`(首次会自动从 preset 空模板生成;password/appSecret 已脱敏),把 read 结果列给用户(已设置显示当前值、未设置标「未设置」)——此时连接字段应为所选项目的值,user/password 为「未设置」。
|
|
161
162
|
4. 用户只补账号密码 → `erp-config.py write --user <账号> --password <密码>`。
|
|
162
163
|
5. 验证登录(`do_auth`),成功后并列执行两个动作:
|
|
163
164
|
- `{PRESET}/skills/erp-analysis/scripts/pull_project_templates.py` — 拉取项目模板(按 baseUrl 反查项目,见 `references/template-distribution.md`)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## 前置条件
|
|
6
6
|
|
|
7
|
-
- Python 运行时已初始化(`{
|
|
7
|
+
- Python 运行时已初始化(`{VENV}/`,跑 init-python 创建)
|
|
8
8
|
- SMTP 配置优先读工作区 `.dsh/cosmic/config/email-smtp.toml`(由 `pull_project_templates.py` 从 tenant 仓库拉取项目企业邮箱),缺失回退 preset `.config/email-smtp.toml` 兜底
|
|
9
9
|
|
|
10
10
|
## 邮件发送铁律(一律 background,四步不可跳)
|
|
@@ -20,17 +20,17 @@
|
|
|
20
20
|
|
|
21
21
|
**Step 1 · Phase 2 结束后立即启动 background 进程**
|
|
22
22
|
|
|
23
|
-
> ⚠️ **脚本路径硬性规定**:邮件脚本路径**唯一为** `{PRESET}/skills/erp-analysis/scripts/send_email.py`。用 `bash` 工具,设 `run_in_background: true`。send_email.py 不依赖 `ANALYSIS_ID`,直接跑
|
|
23
|
+
> ⚠️ **脚本路径硬性规定**:邮件脚本路径**唯一为** `{PRESET}/skills/erp-analysis/scripts/send_email.py`。用 `bash` 工具,设 `run_in_background: true`。send_email.py 不依赖 `ANALYSIS_ID`,直接跑 `{VENV}` 里的解释器即可,无需走 `run.py`。
|
|
24
24
|
|
|
25
25
|
```text
|
|
26
26
|
bash 工具调用:
|
|
27
|
-
command: '{
|
|
27
|
+
command: '{VENV}/bin/python {PRESET}/skills/erp-analysis/scripts/send_email.py --to "x@y.com" --subject "..." --body "..." --attachment "/path/report.html"'
|
|
28
28
|
run_in_background: true
|
|
29
29
|
description: "后台发送分析报告邮件"
|
|
30
30
|
# 立即拿到 job id,继续下一步(Phase 3 / Phase 4 / 输出 chat 等)
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
> 📌 **background 常见错误**:若报 `ModuleNotFoundError`(缺标准库外依赖,本脚本无此类依赖),或 `command not found`,检查
|
|
33
|
+
> 📌 **background 常见错误**:若报 `ModuleNotFoundError`(缺标准库外依赖,本脚本无此类依赖),或 `command not found`,检查 `{VENV}` 是否初始化、路径引号是否闭合。
|
|
34
34
|
|
|
35
35
|
**Step 2 · 继续跑其他任务**(Phase 3 PNG、Phase 4 chat、输出 chat 报告等)
|
|
36
36
|
|
|
@@ -86,7 +86,7 @@ display_name = "发件人显示名"
|
|
|
86
86
|
|
|
87
87
|
### 单收件人单附件(最常用)
|
|
88
88
|
```text
|
|
89
|
-
{
|
|
89
|
+
{VENV}/bin/python {PRESET}/skills/erp-analysis/scripts/send_email.py \
|
|
90
90
|
--to "user@example.com" \
|
|
91
91
|
--subject "分析报告标题" \
|
|
92
92
|
--body "您好,附件为交互式 HTML 报告,下载后用浏览器打开查看完整图表。" \
|
|
@@ -114,7 +114,7 @@ display_name = "发件人显示名"
|
|
|
114
114
|
|---|---|---|
|
|
115
115
|
| 0 | ✅ 成功 | 邮件已发送 |
|
|
116
116
|
| 2 | 参数错误(最常见:位置参数代替命名参数) | 必须用命名参数 `--to` `--subject` `--body` `--attachment` |
|
|
117
|
-
| 126/127 | 命令未找到 | 检查
|
|
117
|
+
| 126/127 | 命令未找到 | 检查 `{VENV}` 是否初始化、路径引号闭合 |
|
|
118
118
|
| 其他 | 认证/网络/TLS/附件超限 | 检查网络、SMTP 配置、附件大小(建议 ≤ 10MB) |
|
|
119
119
|
|
|
120
120
|
> - `--to` 多人用逗号分隔:`--to "a@b.com,c@d.com"`
|
|
@@ -120,7 +120,7 @@ for title in titles:
|
|
|
120
120
|
|
|
121
121
|
```bash
|
|
122
122
|
# write 脚本 → runs/<session_key>/<analysis_id>/chart.py
|
|
123
|
-
ANALYSIS_ID=<id> {
|
|
123
|
+
ANALYSIS_ID=<id> {VENV}/bin/python {PRESET}/run.py runs/<session_key>/<analysis_id>/chart.py
|
|
124
124
|
```
|
|
125
125
|
|
|
126
126
|
```python
|
|
@@ -173,7 +173,7 @@ print("bundle OK")
|
|
|
173
173
|
|
|
174
174
|
```bash
|
|
175
175
|
# write 脚本 → runs/<session_key>/<analysis_id>/report.py
|
|
176
|
-
ANALYSIS_ID=<id> {
|
|
176
|
+
ANALYSIS_ID=<id> {VENV}/bin/python {PRESET}/run.py runs/<session_key>/<analysis_id>/report.py
|
|
177
177
|
```
|
|
178
178
|
|
|
179
179
|
```python
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
1. **标准脚本头**:见 SKILL.md(读 run.py 注入的 `PRESET_DIR`/`OUT_DIR` + sys.path),agent 写脚本时照抄。
|
|
8
8
|
|
|
9
|
-
2. **analysis_id**:agent 在分析开始时生成**一次**(`{
|
|
9
|
+
2. **analysis_id**:agent 在分析开始时生成**一次**(`{VENV}/bin/python -c "import sys; sys.path.insert(0, '{PRESET}/skills/erp-analysis/scripts'); from report_analysis_id import gen_analysis_id; print(gen_analysis_id())"`),硬编码进该分析的所有脚本。**禁止每个脚本各自调 `gen_analysis_id()`**(会产生不同 ID,产物散落)。
|
|
10
10
|
|
|
11
11
|
3. **产物目录约定**:所有脚本、数据缓存、图表、报告都落 `runs/<session_key>/<analysis_id>/`(session_key = `DSH_SESSION_ID`,analysis_id = 上面生成)。
|
|
12
12
|
|
|
13
|
-
4. **Python 执行**:统一走 `{PRESET}/run.py`(`ANALYSIS_ID=<id> {
|
|
13
|
+
4. **Python 执行**:统一走 `{PRESET}/run.py`(`ANALYSIS_ID=<id> {VENV}/bin/python {PRESET}/run.py <脚本>`)。首次使用先跑 init-python(macOS/Linux 用 `init-python.sh`,Windows 用 `init-python.ps1`)初始化运行时。
|
|
14
14
|
|
|
15
15
|
## 流程步骤
|
|
16
16
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
先调 `entity-download.py --map-paths` 拿两个 entity-map 绝对路径,再依次 `grep`(先 preset 标准实体、无果再 workspace 企业新增对象):
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
{
|
|
30
|
+
{VENV}/bin/python {PRESET}/skills/cosmic-build/scripts/entity-download.py --map-paths
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
```
|
|
@@ -44,13 +44,13 @@ grep pattern="过磅" path="<workspace 路径>"
|
|
|
44
44
|
**grep 两处都无果 = 二开/新增对象**。**不要反复试关键词**,直接 queryForms 搜:
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
{
|
|
47
|
+
{VENV}/bin/python {PRESET}/skills/cosmic-build/skills/cosmic-meta-api/scripts/cosmic_api.py queryForms --keyword <关键词>
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
从结果取目标表单的 `formNumber`(表单编码,即实体标识)。**若命中多个同名/相似业务对象(如多个「报关单」分属不同应用/业务云),不要自己猜测,列出候选(表单名称 + 实体标识 + 归属)询问用户选哪个**;用户选定后下载:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
{
|
|
53
|
+
{VENV}/bin/python {PRESET}/skills/cosmic-build/scripts/entity-download.py --entity <formNumber>
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
(下载成功后工作区 entity-map 自动追加该对象,归属应用/业务云由脚本内部经 queryForms 反查自动填充)
|
|
@@ -66,7 +66,7 @@ grep pattern="过磅" path="<workspace 路径>"
|
|
|
66
66
|
先调 `entity-download.py --path` 拿实体 entity.md 的绝对路径(内部已处理「工作区企业扩展优先、preset 标准兜底」)。**字段定位默认 `read` 全文**:
|
|
67
67
|
|
|
68
68
|
```bash
|
|
69
|
-
{
|
|
69
|
+
{VENV}/bin/python {PRESET}/skills/cosmic-build/scripts/entity-download.py --path {entity}
|
|
70
70
|
# 输出绝对路径 → 按下方字段定位方式读取
|
|
71
71
|
```
|
|
72
72
|
|
|
@@ -161,7 +161,7 @@ df = pd.DataFrame(result['data']['rows'])
|
|
|
161
161
|
|
|
162
162
|
plotly 制图,详见 `references/chart-guide.md`。图表用 `fig.to_html()` 生成交互式 HTML(**不用 kaleido / write_image / PNG**)。
|
|
163
163
|
|
|
164
|
-
**执行方式**:`write` 脚本到 `runs/<session_key>/<analysis_id>/xxx.py`(如 `query.py`),再 `ANALYSIS_ID=<id> {
|
|
164
|
+
**执行方式**:`write` 脚本到 `runs/<session_key>/<analysis_id>/xxx.py`(如 `query.py`),再 `ANALYSIS_ID=<id> {VENV}/bin/python {PRESET}/run.py runs/<session_key>/<analysis_id>/xxx.py`。取数与制图可在同一脚本内完成,跨脚本共享数据用 `runs/<session_key>/<analysis_id>/` 下的 JSON / pickle 文件。
|
|
165
165
|
|
|
166
166
|
### Step 9:出报告
|
|
167
167
|
|
|
@@ -127,7 +127,7 @@ print(f"总超时次数: {len(timeouts)}")
|
|
|
127
127
|
|
|
128
128
|
对耗时 >10s 但非超时的 assistant 消息,检查:
|
|
129
129
|
- 是否为取数脚本 → 统计 `_api_call` 次数(取数 + 聚合 + 制图)
|
|
130
|
-
- 是否为报告脚本 → `write` 脚本再 `ANALYSIS_ID=<id> {
|
|
130
|
+
- 是否为报告脚本 → `write` 脚本再 `ANALYSIS_ID=<id> {VENV}/bin/python {PRESET}/run.py` 执行
|
|
131
131
|
- 是否为 `edit` 修复 → 查出 bug 根因(从 old_string 和 new_string 对比)
|
|
132
132
|
- 是否为邮件发送 → 确认成功(`job_output` 输出含 `✅ 邮件已发送至` 且 exit=0)
|
|
133
133
|
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
## 一. 基础设施
|
|
10
10
|
|
|
11
|
-
- **执行方式**:`write` 脚本,再 `ANALYSIS_ID=<id> {
|
|
11
|
+
- **执行方式**:`write` 脚本,再 `ANALYSIS_ID=<id> {VENV}/bin/python {PRESET}/run.py <脚本>` 执行。
|
|
12
12
|
- **统一入口 run.py**:算好路径(`PRESET_DIR`/`OUT_DIR`/`ANALYSIS_ID`)注入环境变量,再以子进程跑目标脚本。
|
|
13
13
|
- **会话/分析隔离**:`DSH_SESSION_ID` 由 DSH 注入;产物按 `runs/<session_key>/<analysis_id>/` 隔离(多会话、多分析互不干扰)。
|
|
14
14
|
- **数据通道**:苍穹 API `_api_call()` 统一调用(数据取策略详见 `api-execution.md`)。
|
|
15
|
-
-
|
|
15
|
+
- **运行时**:`{VENV}`(= `$DSH_HOME/cache/cosmic/venv`,**机器级**、与 preset 版本解耦、多工作区共享),首次使用跑 init-python(macOS/Linux 用 `init-python.sh`,Windows 用 `init-python.ps1`)。**依赖不用每次分析前验证**——脚本 import 失败报 `ModuleNotFoundError` 时再跑 init-python 补装即可;日常分析禁止预先跑 `import pandas/plotly/jinja2` 这类 ad-hoc 检查。⚠️ `requests` 是传输层必需依赖(gzip 协商,见 `api-execution.md`),init-python 的验证导入已包含它,缺失时 init 会失败提示。init-python 装依赖会写 `~/.cache/uv`,DSH sandbox 下报 `Operation not permitted` 属正常——需提权(`sandbox_permissions`)或在终端手动跑 init-python。
|
|
16
16
|
|
|
17
17
|
## 二. 执行命令
|
|
18
18
|
|
|
@@ -30,11 +30,11 @@ Agent 先 `write` 脚本,再用 run.py 执行(run.py 注入 `PRESET_DIR`/`OU
|
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
32
|
# 1. 生成 analysis_id(一次分析一次)
|
|
33
|
-
AID=$({
|
|
33
|
+
AID=$({VENV}/bin/python -c "import sys; sys.path.insert(0, '{PRESET}/skills/erp-analysis/scripts'); from report_analysis_id import gen_analysis_id; print(gen_analysis_id())")
|
|
34
34
|
# 2. write 脚本到 OUT_DIR:runs/$DSH_SESSION_ID/$AID/query.py
|
|
35
35
|
# (脚本与产物同目录,随分析隔离,避免并发分析脚本名互相覆盖)
|
|
36
36
|
# 3. run.py 执行(cwd = 工作目录,workdir 保持默认)
|
|
37
|
-
ANALYSIS_ID=$AID {
|
|
37
|
+
ANALYSIS_ID=$AID {VENV}/bin/python {PRESET}/run.py runs/$DSH_SESSION_ID/$AID/query.py
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
脚本内容:
|
|
@@ -82,7 +82,7 @@ DSH 的 `write` 无 8K 限制,直接一次写完整 `.py` 文件再 `bash` 执
|
|
|
82
82
|
|
|
83
83
|
### R1. 执行入口铁律
|
|
84
84
|
|
|
85
|
-
- 脚本一律 `write` 成文件,再 `ANALYSIS_ID=<id> {
|
|
85
|
+
- 脚本一律 `write` 成文件,再 `ANALYSIS_ID=<id> {VENV}/bin/python {PRESET}/run.py <脚本>`。
|
|
86
86
|
- 长任务(大查询 / 多图)用 `run_in_background: true`,通过 `job_output` 收集结果。
|
|
87
87
|
|
|
88
88
|
### R2. 数据缓存
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
# 苍穹数据分析 preset —— Python 运行时初始化(幂等,Windows PowerShell 版)
|
|
2
2
|
# 用法:pwsh {PRESET}/skills/erp-analysis/scripts/init-python.ps1
|
|
3
|
-
#
|
|
3
|
+
# 行为:把 .venv 建在 **机器级** 目录 `$env:DSH_HOME\cache\cosmic\venv`(与 preset 版本解耦,
|
|
4
|
+
# 升级 preset 不重建;多工作区共享);已存在则跳过创建,但仍按 requirements.txt 同步依赖。
|
|
4
5
|
$ErrorActionPreference = "Stop"
|
|
5
6
|
|
|
6
7
|
# 国内镜像(可用环境变量覆盖):Python 包走清华源、Python 解释器走 npmmirror
|
|
@@ -15,8 +16,11 @@ if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Path # .../skills/erp-analysis/scripts
|
|
18
|
-
$ROOT = (Resolve-Path (Join-Path $SCRIPT_DIR "../../..")).Path # preset
|
|
19
|
-
|
|
19
|
+
$ROOT = (Resolve-Path (Join-Path $SCRIPT_DIR "../../..")).Path # preset 根目录(run.py 所在)
|
|
20
|
+
# Python 运行时是「机器级」的:放 $DSH_HOME 下,与 preset 包解耦。
|
|
21
|
+
# $env:DSH_HOME 由 dsh 注入每次 shell;缺省 $HOME\.dsh(与 dsh 的 resolveDshHome 同规则)。
|
|
22
|
+
$DshHome = if ($env:DSH_HOME) { $env:DSH_HOME } else { Join-Path $HOME ".dsh" }
|
|
23
|
+
$VENV = if ($env:COSMIC_VENV) { $env:COSMIC_VENV } else { Join-Path $DshHome "cache\cosmic\venv" }
|
|
20
24
|
$REQ = Join-Path $SCRIPT_DIR "requirements.txt"
|
|
21
25
|
$PY_VER = "3.14"
|
|
22
26
|
|
|
@@ -25,8 +29,11 @@ Write-Host "==> venv: $VENV"
|
|
|
25
29
|
|
|
26
30
|
# 1) 创建 venv(幂等;uv 会自动下载缺失的 3.14)
|
|
27
31
|
if (Test-Path $VENV) {
|
|
28
|
-
Write-Host "==>
|
|
32
|
+
Write-Host "==> venv 已存在,跳过创建(继续同步依赖)"
|
|
29
33
|
} else {
|
|
34
|
+
$Parent = Split-Path -Parent $VENV
|
|
35
|
+
Write-Host "==> mkdir -p $Parent"
|
|
36
|
+
New-Item -ItemType Directory -Force -Path $Parent | Out-Null
|
|
30
37
|
Write-Host "==> uv venv --python $PY_VER $VENV"
|
|
31
38
|
uv venv --python $PY_VER $VENV
|
|
32
39
|
}
|
|
@@ -35,7 +42,7 @@ if (Test-Path $VENV) {
|
|
|
35
42
|
Write-Host "==> uv pip install -r $REQ"
|
|
36
43
|
uv pip install --python $VENV -r $REQ
|
|
37
44
|
|
|
38
|
-
# 3) 验证导入(uv run
|
|
45
|
+
# 3) 验证导入(uv run 跨平台,自动用该 venv 里的解释器;requests 必须可导入——传输层缺它会回退 urllib 并丢失 gzip 透明解压,大数据量查询慢 7 倍以上)
|
|
39
46
|
Write-Host "==> 验证导入"
|
|
40
47
|
uv run --python $VENV python -c "import pandas, numpy, plotly, jinja2, requests; print('OK', pandas.__version__, numpy.__version__, plotly.__version__, jinja2.__version__, 'requests', requests.__version__)"
|
|
41
48
|
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
# 苍穹数据分析 preset —— Python 运行时初始化(幂等,macOS/Linux 版)
|
|
3
3
|
# 用法(macOS/Linux):bash {PRESET}/skills/erp-analysis/scripts/init-python.sh
|
|
4
4
|
# 用法(Windows):pwsh {PRESET}/skills/erp-analysis/scripts/init-python.ps1
|
|
5
|
-
#
|
|
5
|
+
# 行为:把 .venv 建在 **机器级** 目录 `$DSH_HOME/cache/cosmic/venv`(与 preset 版本解耦,
|
|
6
|
+
# 升级 preset 不重建;多工作区共享);已存在则跳过创建,但仍按 requirements.txt 同步依赖。
|
|
6
7
|
set -euo pipefail
|
|
7
8
|
|
|
8
9
|
# 国内镜像(可用环境变量覆盖):Python 包走清华源、Python 解释器走 npmmirror
|
|
@@ -17,8 +18,11 @@ if ! command -v uv >/dev/null 2>&1; then
|
|
|
17
18
|
fi
|
|
18
19
|
|
|
19
20
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # .../skills/erp-analysis/scripts
|
|
20
|
-
ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" # preset
|
|
21
|
-
|
|
21
|
+
ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" # preset 根目录(run.py 所在)
|
|
22
|
+
# Python 运行时是「机器级」的:放 $DSH_HOME 下,与 preset 包解耦。
|
|
23
|
+
# $DSH_HOME 由 dsh 注入每次 shell;缺省 ~/.dsh(与 dsh 的 resolveDshHome 同规则)。
|
|
24
|
+
DSH_HOME="${DSH_HOME:-$HOME/.dsh}"
|
|
25
|
+
VENV="${COSMIC_VENV:-$DSH_HOME/cache/cosmic/venv}"
|
|
22
26
|
REQ="$SCRIPT_DIR/requirements.txt"
|
|
23
27
|
PY_VER="3.14"
|
|
24
28
|
|
|
@@ -27,8 +31,10 @@ echo "==> venv: $VENV"
|
|
|
27
31
|
|
|
28
32
|
# 1) 创建 venv(幂等;uv 会自动下载缺失的 3.14)
|
|
29
33
|
if [ -d "$VENV" ]; then
|
|
30
|
-
echo "==>
|
|
34
|
+
echo "==> venv 已存在,跳过创建(继续同步依赖)"
|
|
31
35
|
else
|
|
36
|
+
echo "==> mkdir -p $(dirname "$VENV")"
|
|
37
|
+
mkdir -p "$(dirname "$VENV")"
|
|
32
38
|
echo "==> uv venv --python $PY_VER $VENV"
|
|
33
39
|
uv venv --python "$PY_VER" "$VENV"
|
|
34
40
|
fi
|
|
@@ -37,7 +43,7 @@ fi
|
|
|
37
43
|
echo "==> uv pip install -r $REQ"
|
|
38
44
|
uv pip install --python "$VENV" -r "$REQ"
|
|
39
45
|
|
|
40
|
-
# 3) 验证导入(uv run
|
|
46
|
+
# 3) 验证导入(uv run 跨平台,自动用该 venv 里的解释器;requests 必须可导入——传输层缺它会回退 urllib 并丢失 gzip 透明解压,大数据量查询慢 7 倍以上)
|
|
41
47
|
echo "==> 验证导入"
|
|
42
48
|
uv run --python "$VENV" python -c 'import pandas, numpy, plotly, jinja2, requests; print("OK", pandas.__version__, numpy.__version__, plotly.__version__, jinja2.__version__, "requests", requests.__version__)'
|
|
43
49
|
|
|
@@ -2,12 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Python 运行时(统一约定)
|
|
4
4
|
|
|
5
|
-
所有 cosmic-build / erp-analysis 的 .py 脚本,统一用
|
|
6
|
-
不用系统 python3 / 裸 python
|
|
7
|
-
|
|
8
|
-
- `{PRESET}` =
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
所有 cosmic-build / erp-analysis 的 .py 脚本,统一用 cosmic venv 解释器执行,
|
|
6
|
+
不用系统 python3 / 裸 python。
|
|
7
|
+
|
|
8
|
+
- `{PRESET}` = preset 包目录 = **`$DSH_PROFILE_DIR/node_modules/@shundoo-ai/dsh-cosmic`**
|
|
9
|
+
(`$DSH_PROFILE_DIR` 由 dsh 注入每次 shell,即 `<DSH_HOME>/profiles/<profile>`)。
|
|
10
|
+
权威定义见 `{PRESET}/run.py` 的 `PRESET = os.path.dirname(os.path.abspath(__file__))`
|
|
11
|
+
——等价说法:本 SKILL.md 所在目录的上两级(布局是 `{PRESET}/skills/<skill名>/`)。
|
|
12
|
+
- `{VENV}` = `$DSH_HOME/cache/cosmic/venv` —— **机器级** Python 运行时,与 preset 版本解耦
|
|
13
|
+
(升级 preset 不会重建它)。`$DSH_HOME` 由 dsh 注入每次 shell,缺省 `~/.dsh`。
|
|
14
|
+
- macOS/Linux:`{VENV}/bin/python`
|
|
15
|
+
- Windows:`{VENV}/Scripts/python.exe`
|
|
16
|
+
|
|
17
|
+
> 首次使用、或 `$DSH_HOME/cache/cosmic/venv` 被删后,需初始化:
|
|
18
|
+
> macOS/Linux `bash {PRESET}/skills/erp-analysis/scripts/init-python.sh`;
|
|
19
|
+
> Windows `pwsh {PRESET}/skills/erp-analysis/scripts/init-python.ps1`。
|
|
20
|
+
> 脚本**幂等**:已存在则跳过创建,但仍会按 `requirements.txt` 同步依赖——升级 preset 后重跑一次即可。
|
|
11
21
|
|
|
12
22
|
## 公共信息
|
|
13
23
|
|
|
@@ -30,10 +40,10 @@
|
|
|
30
40
|
| cosmic_home | gradle.properties `systemProp.cosmic_home`(优先于环境变量 `COSMIC_HOME`) | 苍穹安装目录;config.gradle 据此定位 `${cosmic_home}/mservice-cosmic/lib/*`(bos/trd/biz/cus),编译插件无需 export |
|
|
31
41
|
| GRADLE_USER_HOME | `<cwd>/.gradle/user-home` | gradle wrapper 缓存;dist 从系统 `~/.gradle/wrapper/dists` **复制**(勿用软链——wrapper 会删链重解压) |
|
|
32
42
|
| gradlew / gradlew.bat | POSIX:项目根 `gradlew` 需 `chmod +x`;Windows:需 `gradle/wrapper/`(gradle-wrapper.properties + gradle-wrapper.jar)齐全,`gradlew.bat` 才可运行 | 模板生成时可能缺 x 位;缺 wrapper 元数据时从模板/系统 dist 补齐 |
|
|
33
|
-
| 插件编译脚本 | `{
|
|
43
|
+
| 插件编译脚本 | `{VENV}/bin/python compile_plugin_source.py` | 脚本只注入 `JAVA_HOME`、**不注入 `GRADLE_USER_HOME`**,调用方必须显式 `export GRADLE_USER_HOME=<cwd>/.gradle/user-home`,否则 Gradle 默认写用户主目录(Windows:`%USERPROFILE%\.gradle`)触发权限拦截;cosmic_home、解释器约定见上 |
|
|
34
44
|
| 构建权限边界 | 产 jar 走 `:<模块>:build`(写工作区);勿用 `buildJar`/`deployJar`(写 cosmic 安装目录 outputdir,工作区外) | Windows 另有 `CreatePipe` 限制,构建/热部署仍须放开权限;Attacher classpath 分隔符 Windows 用 `;` |
|
|
35
45
|
|
|
36
46
|
> 📌 配置按**工作区**隔离(appconfig / GRADLE_USER_HOME / ERP 凭证均在 `<cwd>` 下),多工作区可并行开展不同项目;bash 每次调用为独立 shell,命令中需显式携带工作区约定值(如 `export GRADLE_USER_HOME=<cwd>/.gradle/user-home`),勿依赖跨调用 export。沙箱写权限仅限工作区(preset 技能脚本 `~/.dsh/...`、`~/kd` 等外部路径修改需授权)。权限放开按平台:**macOS/Linux 无管道限制,构建/热部署无需放开**(缓存入工作区即可);**Windows 禁跨进程管道(`CreatePipe error=5`),构建/热部署每次须单命令级放开 `danger-full-access`**(或会话级放宽;`--no-daemon` 无效)。
|
|
37
|
-
> 📌 app-build 脚本(`bootstrap_cosmic_context.py` / `appconfig_load.py` / `prepare_plugin_handoff.py` / `compile_plugin_source.py` / `pipeline_gate.py` / `register_plugins.py` / `render_output_cards.py` 等)同样统一用 `{
|
|
47
|
+
> 📌 app-build 脚本(`bootstrap_cosmic_context.py` / `appconfig_load.py` / `prepare_plugin_handoff.py` / `compile_plugin_source.py` / `pipeline_gate.py` / `register_plugins.py` / `render_output_cards.py` 等)同样统一用 `{VENV}/bin/python` 执行——app-build SKILL.md 模板里的 `python3 {ROOT_DIR}/scripts/...` 写法与本约定冲突时,以本约定为准。
|
|
38
48
|
|
|
39
49
|
<!-- 后续按需补充:数据分析、元数据建模等约定 -->
|
package/agent.cordis.yml
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
# The `standard` agent preset: the full coding agent, mounted once per process.
|
|
2
|
-
#
|
|
3
|
-
# This file is an AGENT-PLANE composition. The roster mounts it ONCE under a
|
|
4
|
-
# standing scope; every session naming it joins by scope parentage, so the
|
|
5
|
-
# tools and prompt sections registered here cover each joined agent while a
|
|
6
|
-
# session's own state stays keyed per Session/Agent inside the plugins. The
|
|
7
|
-
# host composition (`base.cordis.yml` + `web.cordis.yml`) keeps everything a
|
|
8
|
-
# preset must not own: the registries themselves, the sandbox and approval
|
|
9
|
-
# stack, persistence, and the model route.
|
|
10
|
-
#
|
|
11
|
-
# A service row here MUST sit inside a group carrying an `isolate` realm.
|
|
12
|
-
# Without one it publishes into the root realm, where it is process-global —
|
|
13
|
-
# another preset publishing the same name collides, and a host reader would
|
|
14
|
-
# resolve one preset's instance for every session; `dsh-agent-presets` rejects
|
|
15
|
-
# that at mount. `true` means an entry-local realm: this standing mount's own
|
|
16
|
-
# private instance, apart from every other preset's. (A shared label does NOT
|
|
17
|
-
# pool instances — `provide()` throws on the second registration under the
|
|
18
|
-
# same realm symbol; labels join REALMS, and are not what this file needs.)
|
|
19
|
-
|
|
20
|
-
# ── identity ────────────────────────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
# The preset's own persona, shadowing the deployment default for this agent.
|
|
23
|
-
# `{{model}}` and `{{cwd}}` resolve from the agent's own route and workspace.
|
|
24
|
-
- id: persona
|
|
25
|
-
name: '@deepseek-ai/dsh-persona'
|
|
26
|
-
config:
|
|
27
|
-
suffix: Your working directory is {{cwd}}.
|
|
28
|
-
prefix: >-
|
|
29
|
-
You are 苍穹助手 (Cosmic Assistant), the 金蝶云星空 (Kingdee Cloud Cosmic) 开发与数据分析 agent, powered by the {{model}} model. Two capabilities: (1) 苍穹开发 — build and modify 苍穹 apps, menus, forms, entities, fields, plugins, APIs, workflows, and scheduling; follow the cosmic-dev-best-practices and app-build skills for that work. (2) 数据分析 — answer business-data questions through the 苍穹 OpenAPI, analyze with Python (pandas/plotly), and deliver markdown tables in chat plus interactive HTML reports; load the erp-analysis skill before any data query (its SKILL.md is the authority for the workflow and report format). Match the user's intent to the right capability and load the appropriate skill.
|
|
30
|
-
|
|
31
|
-
- id: agent-instructions
|
|
32
|
-
name: '@deepseek-ai/dsh-agent-instructions'
|
|
33
|
-
config:
|
|
34
|
-
maxBytes: 65536
|
|
35
|
-
|
|
36
|
-
# ── shell ───────────────────────────────────────────────────────────────────
|
|
37
|
-
|
|
38
|
-
# `shell-env` stays in the HOST composition: `apps/cli/src/web.ts` injects it to
|
|
39
|
-
# publish `DSH_WEB_URL`/`DSH_WEB_MODE`, and a host row that injects a service is
|
|
40
|
-
# the criterion for host-plane ownership — injection resolves before any session
|
|
41
|
-
# exists, so there is no agent to key by. Behind a preset realm those variables
|
|
42
|
-
# never reached the model's shell at all. Both shell tools consume the host
|
|
43
|
-
# registry from here; their executors (`bash-sandbox`/`pwsh-sandbox`) are
|
|
44
|
-
# host-plane too.
|
|
45
|
-
- id: tool-bash
|
|
46
|
-
name: '@deepseek-ai/dsh-tool-bash'
|
|
47
|
-
disabled: !!js process.platform === 'win32'
|
|
48
|
-
|
|
49
|
-
- id: tool-pwsh
|
|
50
|
-
name: '@deepseek-ai/dsh-tool-pwsh'
|
|
51
|
-
disabled: !!js process.platform !== 'win32'
|
|
52
|
-
|
|
53
|
-
# ── filesystem ──────────────────────────────────────────────────────────────
|
|
54
|
-
|
|
55
|
-
# Both register into the host `tools` registry and provide nothing, so
|
|
56
|
-
# they need no realm. The `fs` service and its policy stay in the host.
|
|
57
|
-
- id: tool-fs
|
|
58
|
-
name: '@deepseek-ai/dsh-tool-fs'
|
|
59
|
-
|
|
60
|
-
- id: tool-fs-search
|
|
61
|
-
name: '@deepseek-ai/dsh-tool-fs-search'
|
|
62
|
-
config:
|
|
63
|
-
sampleOverCapGlobResults: false
|
|
64
|
-
|
|
65
|
-
# ── background jobs ────────────────────────────────────────────────────────
|
|
66
|
-
|
|
67
|
-
# Only the model-facing controls. The task REGISTRY stays on the host plane:
|
|
68
|
-
# its producers sit outside any realm this file could put it in — `tool-bash`
|
|
69
|
-
# above resolves it with `ctx.get`, and an entry-local realm here is invisible
|
|
70
|
-
# to every sibling row, so `run_in_background` would answer "background jobs
|
|
71
|
-
# unavailable" while these controls sat in the catalog. The registry is keyed by
|
|
72
|
-
# owning agent anyway, so one host instance serves every session. What a preset
|
|
73
|
-
# chooses is whether its agent can collect and stop background work at all.
|
|
74
|
-
- id: tool-jobs
|
|
75
|
-
name: '@deepseek-ai/dsh-tool-jobs'
|
|
76
|
-
|
|
77
|
-
# ── skills ──────────────────────────────────────────────────────────────────
|
|
78
|
-
|
|
79
|
-
# The skill REGISTRY lives in the host composition and is layered per scope:
|
|
80
|
-
# these rows register into THIS preset's layer of it, so they need no realm.
|
|
81
|
-
# `skill-filesystem` contributes local-root discovery for agents on this preset, and
|
|
82
|
-
# `tool-skill` gives them the catalog and loader; the merged catalog also
|
|
83
|
-
# carries whatever the deployment registered globally (repository plugins).
|
|
84
|
-
- id: skill-filesystem
|
|
85
|
-
name: '@deepseek-ai/dsh-skill-filesystem'
|
|
86
|
-
config:
|
|
87
|
-
customSkillDirs:
|
|
88
|
-
- !!js "process.getBuiltinModule('node:url').fileURLToPath(new URL('skills/', baseUrl))"
|
|
89
|
-
|
|
90
|
-
- id: tool-skill
|
|
91
|
-
name: '@deepseek-ai/dsh-tool-skill'
|
|
92
|
-
|
|
93
|
-
# ── goals ───────────────────────────────────────────────────────────────────
|
|
94
|
-
|
|
95
|
-
# The goal service and session driver stay on the host plane, where the Gateway
|
|
96
|
-
# can resolve them. The human command and model-facing tool register into this
|
|
97
|
-
# preset's scoped layers.
|
|
98
|
-
- id: command-goal
|
|
99
|
-
name: '@deepseek-ai/dsh-command-goal'
|
|
100
|
-
|
|
101
|
-
- id: tool-goal
|
|
102
|
-
name: '@deepseek-ai/dsh-tool-goal'
|
|
103
|
-
|
|
104
|
-
# ── plan mode ───────────────────────────────────────────────────────────────
|
|
105
|
-
|
|
106
|
-
# Plan state is per-agent by nature, so an entry-local realm is not a
|
|
107
|
-
# workaround here — it is the correct lifetime.
|
|
108
|
-
- id: planning
|
|
109
|
-
name: cordis:group
|
|
110
|
-
group: true
|
|
111
|
-
isolate:
|
|
112
|
-
planMode: true
|
|
113
|
-
config:
|
|
114
|
-
- id: plan-mode
|
|
115
|
-
name: '@deepseek-ai/dsh-plan-mode'
|
|
116
|
-
config:
|
|
117
|
-
section: |
|
|
118
|
-
You are in plan mode. Stay in plan mode until exit_plan_mode succeeds or the user switches the session mode. Imperative language to implement changes means plan the implementation, not execute it. A user's conversational agreement — including an answer confirming something you asked — approves nothing and does not end plan mode; fold the confirmed decision into the plan and submit it through exit_plan_mode.
|
|
119
|
-
|
|
120
|
-
Explore first. Use non-mutating reads, searches, static analysis, and checks to ground the plan in the actual repository. Do not edit or write files, change configuration, run formatters or code generation that rewrites tracked files, commit, or otherwise carry out the plan. Prefer existing functions and patterns over new machinery.
|
|
121
|
-
|
|
122
|
-
The tool catalog stays the same across modes for request-cache stability. These plan-mode rules override any later tool description or guidance that suggests using mutation tools; those tools remain listed to keep the tool catalog unchanged. Do not use todo_write to track this planning phase: it tracks implementation after an approved plan, while the plan itself belongs in exit_plan_mode.
|
|
123
|
-
|
|
124
|
-
Resolve discoverable facts by inspection. Use ask_user_question only for user-owned choices or material ambiguity that inspection cannot answer. Do not ask the user where code lives or how current behavior works when you can find out.
|
|
125
|
-
|
|
126
|
-
Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.
|
|
127
|
-
|
|
128
|
-
When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
|
|
129
|
-
|
|
130
|
-
# ── compaction ──────────────────────────────────────────────────────────────
|
|
131
|
-
|
|
132
|
-
# `compaction-basic` reads `toolResultPrune` through `ctx.get`, so the pruner must
|
|
133
|
-
# share this realm rather than sit outside it.
|
|
134
|
-
#
|
|
135
|
-
# `tokenMeter` is deliberately NOT in this realm: the meter stays on the HOST
|
|
136
|
-
# plane, and the rows here resolve that one instance. It takes no configuration,
|
|
137
|
-
# keys every fold by Session, and owns the context-meter projection units the
|
|
138
|
-
# browser reads for every session — behind a realm those units would come and go
|
|
139
|
-
# with whichever presets happen to be mounted. What a preset chooses is whether
|
|
140
|
-
# its agent compacts at all, which is `compaction-basic` below.
|
|
141
|
-
- id: compaction
|
|
142
|
-
name: cordis:group
|
|
143
|
-
group: true
|
|
144
|
-
isolate:
|
|
145
|
-
compaction: true
|
|
146
|
-
toolResultPruner: true
|
|
147
|
-
config:
|
|
148
|
-
- id: compaction-basic
|
|
149
|
-
name: '@deepseek-ai/dsh-compaction-basic'
|
|
150
|
-
|
|
151
|
-
- id: command-compact
|
|
152
|
-
name: '@deepseek-ai/dsh-command-compact'
|
|
153
|
-
|
|
154
|
-
- id: tool-result-pruner
|
|
155
|
-
name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
|
|
156
|
-
config:
|
|
157
|
-
thresholdChars: 8192
|
|
158
|
-
headChars: 4096
|
|
159
|
-
tailChars: 1024
|
|
160
|
-
|
|
161
|
-
# ── delegation and workflows ────────────────────────────────────────────────
|
|
162
|
-
|
|
163
|
-
# The `subagents` registry and its spawn/fork backends live in the HOST
|
|
164
|
-
# composition: the registry is a process singleton whose cross-session queries
|
|
165
|
-
# the api-proxy serves to the browser, and a provider name may only be
|
|
166
|
-
# registered once. This preset contributes the delegation TOOLS, which resolve
|
|
167
|
-
# that host registry.
|
|
168
|
-
#
|
|
169
|
-
# `workflows` is different — nothing outside an agent reads it — so every row
|
|
170
|
-
# that reaches it shares one entry-local realm here, and a consumer left
|
|
171
|
-
# outside would resolve a host registry this preset does not populate.
|
|
172
|
-
- id: delegation
|
|
173
|
-
name: cordis:group
|
|
174
|
-
group: true
|
|
175
|
-
isolate:
|
|
176
|
-
workflowEngine: true
|
|
177
|
-
config:
|
|
178
|
-
- id: tool-subagent-control
|
|
179
|
-
name: '@deepseek-ai/dsh-tool-subagent-control'
|
|
180
|
-
|
|
181
|
-
- id: tool-subagent-list-agents
|
|
182
|
-
name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
|
|
183
|
-
|
|
184
|
-
- id: tool-subagent
|
|
185
|
-
name: '@deepseek-ai/dsh-tool-subagent'
|
|
186
|
-
config:
|
|
187
|
-
provider: spawn
|
|
188
|
-
toolName: subagent
|
|
189
|
-
modelSelectionSettings: true
|
|
190
|
-
backgroundMode: continuable
|
|
191
|
-
|
|
192
|
-
# Fork omits model selection so provider/model stay equal to the parent and
|
|
193
|
-
# the inherited history remains eligible for KV Cache reuse. This preset
|
|
194
|
-
# keeps fork continuable; parent and child inherit the same messaging tool,
|
|
195
|
-
# while the parent id and return guidance follow the inherited history.
|
|
196
|
-
- id: tool-subagent-fork
|
|
197
|
-
name: '@deepseek-ai/dsh-tool-subagent'
|
|
198
|
-
config:
|
|
199
|
-
provider: fork
|
|
200
|
-
toolName: subagent_fork
|
|
201
|
-
backgroundMode: continuable
|
|
202
|
-
|
|
203
|
-
# Production dsh does not install these optional providers. Install the
|
|
204
|
-
# matching Bundle in this Profile and restart the Host, then copy this
|
|
205
|
-
# preset and remove `disabled` from the matching tool row. Host availability
|
|
206
|
-
# alone grants no tool.
|
|
207
|
-
- id: tool-subagent-codex
|
|
208
|
-
name: '@deepseek-ai/dsh-tool-subagent'
|
|
209
|
-
disabled: true
|
|
210
|
-
config:
|
|
211
|
-
provider: codex
|
|
212
|
-
toolName: subagent_codex
|
|
213
|
-
backgroundMode: one-shot
|
|
214
|
-
maxDepth: provider-managed
|
|
215
|
-
|
|
216
|
-
- id: tool-subagent-claude-code
|
|
217
|
-
name: '@deepseek-ai/dsh-tool-subagent'
|
|
218
|
-
disabled: true
|
|
219
|
-
config:
|
|
220
|
-
provider: claude-code
|
|
221
|
-
toolName: subagent_claude_code
|
|
222
|
-
backgroundMode: one-shot
|
|
223
|
-
maxDepth: provider-managed
|
|
224
|
-
|
|
225
|
-
- id: workflow-ptc
|
|
226
|
-
name: '@deepseek-ai/dsh-workflow-ptc'
|
|
227
|
-
config:
|
|
228
|
-
provider: spawn
|
|
229
|
-
|
|
230
|
-
- id: tool-workflow
|
|
231
|
-
name: '@deepseek-ai/dsh-tool-workflow'
|
|
232
|
-
|
|
233
|
-
# Off by default with the base row it mirrors: the tool description
|
|
234
|
-
# restricts `ralph` to runs the human explicitly asked for, and completion
|
|
235
|
-
# is a worker self-report, not an independent evaluation. Preset files take
|
|
236
|
-
# no patches, so a session that wants it duplicates this preset under a new
|
|
237
|
-
# id and drops `disabled`; the shipped root shadows a copy that reuses this
|
|
238
|
-
# id.
|
|
239
|
-
- id: tool-ralph
|
|
240
|
-
name: '@deepseek-ai/dsh-tool-ralph'
|
|
241
|
-
disabled: true
|
|
242
|
-
config:
|
|
243
|
-
subagentProvider: spawn
|
|
244
|
-
maxRounds: 64
|
|
245
|
-
|
|
246
|
-
# ── remaining model-facing rows ─────────────────────────────────────────────
|
|
247
|
-
|
|
248
|
-
- id: tool-ask-user
|
|
249
|
-
name: '@deepseek-ai/dsh-tool-ask-user'
|
|
250
|
-
|
|
251
|
-
- id: tool-todo
|
|
252
|
-
name: '@deepseek-ai/dsh-tool-todo'
|
|
253
|
-
config:
|
|
254
|
-
allowParallelInProgress: true
|
|
255
|
-
|
|
256
|
-
# The `web` service and its search provider stay in the host composition; only
|
|
257
|
-
# the model-facing tool is per-session.
|
|
258
|
-
- id: tool-web
|
|
259
|
-
name: '@deepseek-ai/dsh-tool-web'
|
|
260
|
-
config:
|
|
261
|
-
fetch: true
|
|
262
|
-
searchTimeoutMs: 60000
|
|
263
|
-
|
|
264
|
-
- id: present
|
|
265
|
-
name: '@deepseek-ai/dsh-tool-present'
|
|
266
|
-
|
|
267
|
-
- id: tool-plugin-manager
|
|
268
|
-
name: '@deepseek-ai/dsh-plugin-manager/tools'
|
|
269
|
-
disabled: true
|
package/preset.yml
DELETED