draftgo-cli 4.0.22 → 4.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/draftgo.js +8 -8
- package/package.json +72 -72
- package/resources/custom-service-sdk/auth_test.go +56 -0
- package/resources/custom-service-sdk/manifest.json +14 -9
- package/resources/custom-service-sdk/platform.go +19 -27
- package/resources/custom-service-sdk/resources.go +1 -0
- package/resources/custom-service-sdk/resources_scope_test.go +10 -5
- package/resources/custom-service-sdk/sdk.go +6 -5
- package/resources/skill/SKILL.md +1 -1
- package/resources/skill/manifest.json +1 -1
- package/resources/skill/references/aihub.md +74 -74
- package/resources/skill/references/app-api.md +78 -78
- package/resources/skill/references/architecture.md +40 -40
- package/resources/skill/references/checkout.md +105 -105
- package/resources/skill/references/custom-services.md +6 -6
- package/resources/skill/references/data.md +168 -168
- package/resources/skill/references/methods.md +3 -0
- package/resources/skill/references/modules.md +48 -48
- package/resources/skill/references/runtime.md +95 -96
- package/resources/skill/story/SKILL.md +264 -264
- package/src/commands/help.js +72 -72
- package/src/commands/listTargets.js +12 -12
- package/src/commands/status.js +2 -2
- package/src/commands/uninstall.js +45 -45
- package/src/commands/update.js +20 -20
- package/src/customServices.js +5 -4
- package/src/detect.js +14 -14
- package/src/fsx.js +67 -67
- package/src/index.js +25 -25
- package/src/localRuntime/detect.js +76 -76
- package/src/localRuntime/mysqlClient.js +138 -138
- package/src/logger.js +37 -37
- package/src/mcp/client.js +586 -595
- package/src/mcp/hosts.js +520 -520
- package/src/mcp/protocol.js +184 -164
- package/src/prompt.js +94 -94
- package/src/updateCheck.js +16 -16
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
---
|
|
2
|
-
read_when: 创建或调优 AI Agent 时 · 需要工具/子智能体/记忆/多轮/结构化输出/多模态时
|
|
3
|
-
---
|
|
4
|
-
|
|
1
|
+
---
|
|
2
|
+
read_when: 创建或调优 AI Agent 时 · 需要工具/子智能体/记忆/多轮/结构化输出/多模态时
|
|
3
|
+
---
|
|
4
|
+
|
|
5
5
|
# AIHub / Agent 资源
|
|
6
6
|
|
|
7
7
|
## 最短管理流程
|
|
@@ -24,86 +24,86 @@ AIHub 与知识库是独立权限域:Agent、模型和 AI 运行使用 `aihub:
|
|
|
24
24
|
|
|
25
25
|
AIHub 是结构化远端资源,不 checkout,也不生成本地镜像。先使用 MCP `draftgo_resource_search`/`draftgo_resource_list`
|
|
26
26
|
定位资产;未知 operation 才用 `draftgo_api_search`,首次使用或 registry revision 变化时 `draftgo_api_describe`,然后通过 `draftgo_api_call` 读写。
|
|
27
|
-
更新 AIHub 资产时只发送实时契约允许的字段;常见字段包括
|
|
28
|
-
`type, name, data, priority, version, tags, describe, permission, status`。供应商和模型使用各自的实时接口,
|
|
29
|
-
不要经旧 AIHub 资产接口写入。任何输出、工作区文件或调用参数都不得保存 API Key 或 header 值;只可处理
|
|
30
|
-
“是否已配置”以及 header 名称等非秘密元数据。
|
|
31
|
-
**Agent 的全部行为都在 `data`(尤其 `data.spec`)里**——本页就是 `data.spec` 的字段地图。
|
|
32
|
-
|
|
33
|
-
## 条目骨架
|
|
34
|
-
|
|
35
|
-
```jsonc
|
|
36
|
-
{
|
|
37
|
-
"type": "agent", // AIHub 资产类型
|
|
38
|
-
"name": "产品顾问",
|
|
39
|
-
"describe": "面向用户的产品答疑助手",
|
|
40
|
-
"status": "active",
|
|
41
|
-
"data": {
|
|
42
|
-
"mode": "chat", // chat | image_generation
|
|
43
|
-
"spec": { /* 见下表 */ }
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
页面对话 UI 使用 `<dg-chat protocol="draftgo-agent" agent-id="AGENT_ID">` 或 `DraftGoChat.create()`;
|
|
49
|
-
旧代码/无 UI 文本调用可用 `DraftGoAI.chat(...)`,图片模式使用 `DraftGoAI.images(...)`。调用前都必须加载
|
|
27
|
+
更新 AIHub 资产时只发送实时契约允许的字段;常见字段包括
|
|
28
|
+
`type, name, data, priority, version, tags, describe, permission, status`。供应商和模型使用各自的实时接口,
|
|
29
|
+
不要经旧 AIHub 资产接口写入。任何输出、工作区文件或调用参数都不得保存 API Key 或 header 值;只可处理
|
|
30
|
+
“是否已配置”以及 header 名称等非秘密元数据。
|
|
31
|
+
**Agent 的全部行为都在 `data`(尤其 `data.spec`)里**——本页就是 `data.spec` 的字段地图。
|
|
32
|
+
|
|
33
|
+
## 条目骨架
|
|
34
|
+
|
|
35
|
+
```jsonc
|
|
36
|
+
{
|
|
37
|
+
"type": "agent", // AIHub 资产类型
|
|
38
|
+
"name": "产品顾问",
|
|
39
|
+
"describe": "面向用户的产品答疑助手",
|
|
40
|
+
"status": "active",
|
|
41
|
+
"data": {
|
|
42
|
+
"mode": "chat", // chat | image_generation
|
|
43
|
+
"spec": { /* 见下表 */ }
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
页面对话 UI 使用 `<dg-chat protocol="draftgo-agent" agent-id="AGENT_ID">` 或 `DraftGoChat.create()`;
|
|
49
|
+
旧代码/无 UI 文本调用可用 `DraftGoAI.chat(...)`,图片模式使用 `DraftGoAI.images(...)`。调用前都必须加载
|
|
50
50
|
`/assets/draftgo-chat.js`,完整用法见 `references/chat-sdk.md`。后端 operation 与可调用 Agent 列表通过 MCP 实时确认;已知契约可复用项目缓存。
|
|
51
|
-
|
|
52
|
-
## `data.spec` 字段地图
|
|
53
|
-
|
|
54
|
-
留空即维持默认/旧行为;除标注外都是可选。运行时统一在 `parseOrchestrationConfig` + 就地读取时带默认值与 clamp。
|
|
55
|
-
|
|
56
|
-
| 字段 | 类型 / 取值 | 说明 |
|
|
57
|
-
|---|---|---|
|
|
51
|
+
|
|
52
|
+
## `data.spec` 字段地图
|
|
53
|
+
|
|
54
|
+
留空即维持默认/旧行为;除标注外都是可选。运行时统一在 `parseOrchestrationConfig` + 就地读取时带默认值与 clamp。
|
|
55
|
+
|
|
56
|
+
| 字段 | 类型 / 取值 | 说明 |
|
|
57
|
+
|---|---|---|
|
|
58
58
|
| `mode` | `chat` / `image_generation` | 决定主要交互形态;具体 Responses、Embedding、Rerank、TTS、ASR、Video operation 以 MCP 和模型 capability 为准 |
|
|
59
|
-
| `model` | string | 主模型(逻辑模型名,映射到供应商路由) |
|
|
60
|
-
| `fallback_models` | string[] | 主模型失败后按序回退(跨模型 failover) |
|
|
61
|
-
| `model_selection.user_selectable` | bool | 是否允许调用方在请求里覆盖 `model`(配合 `selectable-models`) |
|
|
62
|
-
| `ttft_timeout` | number(秒,1–600,空=不启用) | 首字超时 failover:首个 SSE data 事件超时即跨模型+跨供应商切换,推理模型不误杀 |
|
|
59
|
+
| `model` | string | 主模型(逻辑模型名,映射到供应商路由) |
|
|
60
|
+
| `fallback_models` | string[] | 主模型失败后按序回退(跨模型 failover) |
|
|
61
|
+
| `model_selection.user_selectable` | bool | 是否允许调用方在请求里覆盖 `model`(配合 `selectable-models`) |
|
|
62
|
+
| `ttft_timeout` | number(秒,1–600,空=不启用) | 首字超时 failover:首个 SSE data 事件超时即跨模型+跨供应商切换,推理模型不误杀 |
|
|
63
63
|
| `sync_request_timeout` | number(秒,1–600,默认 100) | 非流式请求上限 |
|
|
64
64
|
| `stream_ttl` | number(秒,1–3600,默认 600) | 流式请求上限 |
|
|
65
65
|
| `max_tokens` | number / 空 | 最大输出 token;留空时不写入请求,即不由 Agent 额外限制 |
|
|
66
66
|
| `reasoning_effort` | `off`/`minimal`/`low`/`medium`/`high` | `off`/留空均不透传;其它值仅 OpenAI 系模型生效 |
|
|
67
|
-
| `system_prompt_template` | string | 系统提示模板 |
|
|
68
|
-
| `context.max_history` | number(默认 20) | 工作窗口:保留最近 N 条;关闭持续对话时即滑动窗口硬上限 |
|
|
69
|
-
| `output_format.mode` | `text` / `json` | JSON 时按 `output_format.json.{schema,schema_name,strategy}` 约束/校验/降级 |
|
|
70
|
-
| `capabilities.vision.{enabled,input,max_mb}` | 见值 | 图片/视觉输入(`image_url` part),`input`⊂{base64,url},默认 5MB |
|
|
71
|
-
| `capabilities.files.{enabled,allowed_ext,max_mb}` | 见值 | 文件附件抽取成文本注入;白名单 `.txt .md .docx .pdf .xlsx .json .csv`(pptx 不支持),默认 8MB |
|
|
72
|
-
| `tools.max_iterations` | 1–50(默认 10) | ReAct 工具循环步数上限 |
|
|
73
|
-
| `tools.sources[].{type,id}` | `mcp` / `custom_script` | 绑定 MCP 与「自定义服务作为工具」 |
|
|
74
|
-
| `knowledge_base_ids` | int[] | 绑定知识库,生成检索工具 |
|
|
75
|
-
| `skills` | 见运行时 | 绑定 Skill |
|
|
76
|
-
| `sub_agent_ids` | int[] | 子智能体:为每个 id 生成 `agent_{id}` 委派工具(用法同 `knowledge_base_ids`) |
|
|
67
|
+
| `system_prompt_template` | string | 系统提示模板 |
|
|
68
|
+
| `context.max_history` | number(默认 20) | 工作窗口:保留最近 N 条;关闭持续对话时即滑动窗口硬上限 |
|
|
69
|
+
| `output_format.mode` | `text` / `json` | JSON 时按 `output_format.json.{schema,schema_name,strategy}` 约束/校验/降级 |
|
|
70
|
+
| `capabilities.vision.{enabled,input,max_mb}` | 见值 | 图片/视觉输入(`image_url` part),`input`⊂{base64,url},默认 5MB |
|
|
71
|
+
| `capabilities.files.{enabled,allowed_ext,max_mb}` | 见值 | 文件附件抽取成文本注入;白名单 `.txt .md .docx .pdf .xlsx .json .csv`(pptx 不支持),默认 8MB |
|
|
72
|
+
| `tools.max_iterations` | 1–50(默认 10) | ReAct 工具循环步数上限 |
|
|
73
|
+
| `tools.sources[].{type,id}` | `mcp` / `custom_script` | 绑定 MCP 与「自定义服务作为工具」 |
|
|
74
|
+
| `knowledge_base_ids` | int[] | 绑定知识库,生成检索工具 |
|
|
75
|
+
| `skills` | 见运行时 | 绑定 Skill |
|
|
76
|
+
| `sub_agent_ids` | int[] | 子智能体:为每个 id 生成 `agent_{id}` 委派工具(用法同 `knowledge_base_ids`) |
|
|
77
77
|
| `call_permissions` | 角色配置 | 哪些角色可以调用此 Agent;调用接口与筛选条件以 MCP 实时契约为准 |
|
|
78
78
|
| `billing_mode` | `disabled` / `inherit_model` / `per_call` / `usage` | Agent 零售计费;公开 Agent 强制 `disabled`,订阅/会员额度由业务服务管理 |
|
|
79
|
-
|
|
80
|
-
### `orchestration.*`(编排开关)
|
|
81
|
-
|
|
82
|
-
| 字段 | 默认 | 说明 |
|
|
83
|
-
|---|---|---|
|
|
84
|
-
| `tool_concurrency` | 8(1–32) | 单步内并发执行工具数 |
|
|
85
|
-
| `on_max_steps` | `error` | 达步数上限:`error` 报错 / `stop` 返回最后一条 |
|
|
86
|
-
| `tool_disclosure.{mode,threshold_tools}` | `off` | 工具渐进披露:`off`/`auto`/`always`,首轮只给目录+`load_tools` |
|
|
87
|
-
| `planning.{enabled,prompt}` | false | 规划层:执行前先让模型列步骤,提示折叠进 system |
|
|
88
|
-
| `memory.{enabled,scope}` | false / `user_agent` | 长期记忆:对话后自动提炼、下轮召回注入;作用域 `agent`/`user`/`user_agent` |
|
|
89
|
-
| `compaction.{enabled,keep_recent,trigger_messages,trigger_tokens,preset}` | 关闭 | **持续对话/上下文闭环**:见下 |
|
|
90
|
-
| `checkpoint_input_mode` / `checkpoint_max_messages` / `checkpoint_ttl_seconds` | 全量 / 100 / 86400 | 会话历史持久化(配合请求 `session_id`) |
|
|
79
|
+
|
|
80
|
+
### `orchestration.*`(编排开关)
|
|
81
|
+
|
|
82
|
+
| 字段 | 默认 | 说明 |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| `tool_concurrency` | 8(1–32) | 单步内并发执行工具数 |
|
|
85
|
+
| `on_max_steps` | `error` | 达步数上限:`error` 报错 / `stop` 返回最后一条 |
|
|
86
|
+
| `tool_disclosure.{mode,threshold_tools}` | `off` | 工具渐进披露:`off`/`auto`/`always`,首轮只给目录+`load_tools` |
|
|
87
|
+
| `planning.{enabled,prompt}` | false | 规划层:执行前先让模型列步骤,提示折叠进 system |
|
|
88
|
+
| `memory.{enabled,scope}` | false / `user_agent` | 长期记忆:对话后自动提炼、下轮召回注入;作用域 `agent`/`user`/`user_agent` |
|
|
89
|
+
| `compaction.{enabled,keep_recent,trigger_messages,trigger_tokens,preset}` | 关闭 | **持续对话/上下文闭环**:见下 |
|
|
90
|
+
| `checkpoint_input_mode` / `checkpoint_max_messages` / `checkpoint_ttl_seconds` | 全量 / 100 / 86400 | 会话历史持久化(配合请求 `session_id`) |
|
|
91
91
|
| `delegation.{max_depth,max_total_calls}` | 2 / 8 | 最大嵌套层数与整棵调用树共享的子 Agent 调用次数;并行分支也从同一预算扣减 |
|
|
92
92
|
|
|
93
93
|
同一模型步骤返回多个子 Agent 工具调用时,运行时立即按 `tool_concurrency` 并发执行;不同步骤自然串行,由模型自行决定编排方式。委派成功后,子 Agent 的每个模型回合 token 会汇总到入口 run,总量也写入对应委派 span。一次入口请求只创建一条主 run,Agent 列归属入口 Agent,委派链路从 span 查看。
|
|
94
|
-
|
|
95
|
-
### 持续对话(上下文闭环)
|
|
96
|
-
|
|
97
|
-
- `compaction.enabled=true` = 闭环:填满工作窗口后把溢出旧消息**摘要成一条滚动 summary** 续接,
|
|
98
|
-
而非直接丢弃。此时后端**跳过 `context.max_history` 硬砍**,让完整 checkpoint 历史进入压缩器蒸馏。
|
|
99
|
-
- 触发为双通道任一命中:`trigger_messages`(条数)或 `trigger_tokens`(估算 token,256–2000000)。
|
|
100
|
-
- `keep_recent`:保留最近 N 条不压缩。`preset`(`aggressive`/`balanced`/`conservative`)是管理台档位回显,
|
|
101
|
-
后端只认 `keep_recent`/`trigger_messages`/`trigger_tokens` 三个底层字段。
|
|
102
|
-
- 配合请求体 `session_id` 才会加载/续写会话历史;`<dg-chat>` 为每个 UI thread 自动维护该值,兼容门面可通过 `DraftGoAI.chat(..., {sessionId})` 显式传入。不传即无状态单轮。
|
|
103
|
-
- 关闭时逐字回退为 `max_history` 滑动窗口(旧行为,零影响)。
|
|
104
|
-
|
|
105
|
-
## 观测
|
|
106
|
-
|
|
94
|
+
|
|
95
|
+
### 持续对话(上下文闭环)
|
|
96
|
+
|
|
97
|
+
- `compaction.enabled=true` = 闭环:填满工作窗口后把溢出旧消息**摘要成一条滚动 summary** 续接,
|
|
98
|
+
而非直接丢弃。此时后端**跳过 `context.max_history` 硬砍**,让完整 checkpoint 历史进入压缩器蒸馏。
|
|
99
|
+
- 触发为双通道任一命中:`trigger_messages`(条数)或 `trigger_tokens`(估算 token,256–2000000)。
|
|
100
|
+
- `keep_recent`:保留最近 N 条不压缩。`preset`(`aggressive`/`balanced`/`conservative`)是管理台档位回显,
|
|
101
|
+
后端只认 `keep_recent`/`trigger_messages`/`trigger_tokens` 三个底层字段。
|
|
102
|
+
- 配合请求体 `session_id` 才会加载/续写会话历史;`<dg-chat>` 为每个 UI thread 自动维护该值,兼容门面可通过 `DraftGoAI.chat(..., {sessionId})` 显式传入。不传即无状态单轮。
|
|
103
|
+
- 关闭时逐字回退为 `max_history` 滑动窗口(旧行为,零影响)。
|
|
104
|
+
|
|
105
|
+
## 观测
|
|
106
|
+
|
|
107
107
|
每次调用都开一条 AI run,管理台 `/admin/ai-runs` 展示状态、tokens、延迟、`ttft_ms` 与 span 链路。
|
|
108
108
|
运行记录接口通过 MCP 实时发现,不维护静态路径表;已知 operation 复用 registry revision 未变化的契约缓存。
|
|
109
109
|
|
|
@@ -112,5 +112,5 @@ profile、transport readiness 和实际 route;不要只根据供应商名称
|
|
|
112
112
|
能力名大小写敏感,使用实时 describe 返回的 canonical 值,不使用历史别名。
|
|
113
113
|
|
|
114
114
|
Agent 对外响应(`/api/agents/{id}/chat`、图片接口、Go/Script SDK Agent 调用)不返回内部 `model`、`fallback_models` 或 `upstream_model`;错误也不暴露内部模型名、供应商名称、服务地址或运行时实现名。只有显式启用 `model_selection.user_selectable` 后,`/selectable-models` 才作为授权的模型选择目录返回可选逻辑模型名。运行日志仍在服务端保留真实模型、供应商与链路信息用于定位。
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
> 权威细节以 DraftGo `docs/modules/ai-platform/agent-runtime.md` 和实时 MCP schema 为准;本页是基座开发者视角的字段速查。
|
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
---
|
|
2
|
-
read_when: 页面开发时需要查 App API · 忘记某个方法签名时
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# App 对象速查表
|
|
6
|
-
|
|
7
|
-
```javascript
|
|
8
|
-
const App = window.parent?.App;
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## 请求
|
|
12
|
-
|
|
13
|
-
| 方法 | 签名 | 说明 |
|
|
14
|
-
|---|---|---|
|
|
1
|
+
---
|
|
2
|
+
read_when: 页面开发时需要查 App API · 忘记某个方法签名时
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# App 对象速查表
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
const App = window.parent?.App;
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 请求
|
|
12
|
+
|
|
13
|
+
| 方法 | 签名 | 说明 |
|
|
14
|
+
|---|---|---|
|
|
15
15
|
| `App.get` | `(path, params?, headers?)` | GET,params 为 query 参数 |
|
|
16
16
|
| `App.post` | `(path, body?, headers?)` | POST |
|
|
17
17
|
| `App.put` | `(path, body?, headers?)` | PUT |
|
|
18
18
|
| `App.patch` | `(path, body?, headers?)` | PATCH |
|
|
19
19
|
| `App.delete` | `(path, params?, headers?)` | DELETE |
|
|
20
|
-
| `App.uploadFile` | `(file, onProgress?)` | 文件上传,返回标准信封 |
|
|
21
|
-
|
|
22
|
-
**响应格式**:`{ code: 200, data: <载荷>, message: "success" }`
|
|
23
|
-
**消费范式**:
|
|
24
|
-
```javascript
|
|
25
|
-
const res = await App.get('pages'); // 不传分页参数时全量返回
|
|
26
|
-
if (res.code !== 200) { App.showError(res.message); return; }
|
|
27
|
-
const items = res.data.items;
|
|
28
|
-
|
|
29
|
-
const paged = await App.get('pages', { page: 1, page_size: 20 }); // 显式分页
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## 反馈
|
|
33
|
-
|
|
34
|
-
| 方法 | 签名 | 说明 |
|
|
35
|
-
|---|---|---|
|
|
20
|
+
| `App.uploadFile` | `(file, onProgress?)` | 文件上传,返回标准信封 |
|
|
21
|
+
|
|
22
|
+
**响应格式**:`{ code: 200, data: <载荷>, message: "success" }`
|
|
23
|
+
**消费范式**:
|
|
24
|
+
```javascript
|
|
25
|
+
const res = await App.get('pages'); // 不传分页参数时全量返回
|
|
26
|
+
if (res.code !== 200) { App.showError(res.message); return; }
|
|
27
|
+
const items = res.data.items;
|
|
28
|
+
|
|
29
|
+
const paged = await App.get('pages', { page: 1, page_size: 20 }); // 显式分页
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 反馈
|
|
33
|
+
|
|
34
|
+
| 方法 | 签名 | 说明 |
|
|
35
|
+
|---|---|---|
|
|
36
36
|
| `App.showSuccess` | `(msg)` | 成功 Toast |
|
|
37
37
|
| `App.showError` | `(msg)` | 错误 Toast |
|
|
38
38
|
| `App.showWarning` | `(msg)` | 警告 Toast |
|
|
39
39
|
| `App.showInfo` | `(msg)` | 信息 Toast |
|
|
40
|
-
| `App.toast` | `(msg, type?)` | 通用 Toast,type: success/error/warning/info |
|
|
41
|
-
| `App.confirm` | `(msg, title?)` | 确认弹窗,返回 `Promise<boolean>` |
|
|
42
|
-
| `App.showModal` | `(msg, title?)` | 信息模态框(替代 alert) |
|
|
43
|
-
| `App.showLoading` | `()` | 全局 loading 蒙层 |
|
|
44
|
-
| `App.hideLoading` | `()` | 关闭 loading |
|
|
45
|
-
|
|
46
|
-
## 路由
|
|
47
|
-
|
|
48
|
-
| 方法 | 说明 |
|
|
49
|
-
|---|---|
|
|
50
|
-
| `App.navigate(route)` | 路由跳转(pushState) |
|
|
51
|
-
| `App.getCurrentRoute()` | 当前路径字符串 |
|
|
52
|
-
| `App.getCurrentRouteContext()` | 完整路由上下文,含 `query` |
|
|
53
|
-
|
|
54
|
-
**读取 URL 参数**(必须用此方式,不能用 `window.location.search`):
|
|
55
|
-
```javascript
|
|
56
|
-
const routeContext =
|
|
57
|
-
window.__DG_ROUTE_CONTEXT__
|
|
58
|
-
|| window.__DG_GET_ROUTE_CONTEXT__?.()
|
|
59
|
-
|| window.parent?.App?.getCurrentRouteContext?.()
|
|
60
|
-
|| { query: {} };
|
|
61
|
-
const { patientId, visitId } = routeContext.query;
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## 状态
|
|
65
|
-
|
|
66
|
-
| 属性 | 类型 | 说明 |
|
|
67
|
-
|---|---|---|
|
|
68
|
-
| `App.currentUser` | object \| null | 当前用户,未登录为 null |
|
|
40
|
+
| `App.toast` | `(msg, type?)` | 通用 Toast,type: success/error/warning/info |
|
|
41
|
+
| `App.confirm` | `(msg, title?)` | 确认弹窗,返回 `Promise<boolean>` |
|
|
42
|
+
| `App.showModal` | `(msg, title?)` | 信息模态框(替代 alert) |
|
|
43
|
+
| `App.showLoading` | `()` | 全局 loading 蒙层 |
|
|
44
|
+
| `App.hideLoading` | `()` | 关闭 loading |
|
|
45
|
+
|
|
46
|
+
## 路由
|
|
47
|
+
|
|
48
|
+
| 方法 | 说明 |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `App.navigate(route)` | 路由跳转(pushState) |
|
|
51
|
+
| `App.getCurrentRoute()` | 当前路径字符串 |
|
|
52
|
+
| `App.getCurrentRouteContext()` | 完整路由上下文,含 `query` |
|
|
53
|
+
|
|
54
|
+
**读取 URL 参数**(必须用此方式,不能用 `window.location.search`):
|
|
55
|
+
```javascript
|
|
56
|
+
const routeContext =
|
|
57
|
+
window.__DG_ROUTE_CONTEXT__
|
|
58
|
+
|| window.__DG_GET_ROUTE_CONTEXT__?.()
|
|
59
|
+
|| window.parent?.App?.getCurrentRouteContext?.()
|
|
60
|
+
|| { query: {} };
|
|
61
|
+
const { patientId, visitId } = routeContext.query;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 状态
|
|
65
|
+
|
|
66
|
+
| 属性 | 类型 | 说明 |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| `App.currentUser` | object \| null | 当前用户,未登录为 null |
|
|
69
69
|
| `App.isAdmin` | boolean | 是否管理员 |
|
|
70
70
|
| `App.permissions` | string[] | 当前用户有效 permission grant 的展示投影;仅用于页面显隐,不替代服务端授权 |
|
|
71
71
|
| `App.isAuthenticated` | boolean | 是否已认证 |
|
|
72
|
-
| `App.hasToken` | boolean | 是否有 token(含未验证) |
|
|
73
|
-
| `App.config` | object | 系统配置 KV |
|
|
74
|
-
| `App.theme` | `'light'` \| `'dark'` | 当前显示模式 |
|
|
72
|
+
| `App.hasToken` | boolean | 是否有 token(含未验证) |
|
|
73
|
+
| `App.config` | object | 系统配置 KV |
|
|
74
|
+
| `App.theme` | `'light'` \| `'dark'` | 当前显示模式 |
|
|
75
75
|
| `App.colorScheme` | string | 当前配色方案 |
|
|
76
76
|
| `App.scopeContext` | object | null | 当前候选范围;`scope_type` 为 `platform` / `space` |
|
|
77
77
|
| `App.availableSpaces` | object[] | 当前用户可选择的工作区与递归空间 |
|
|
@@ -118,22 +118,22 @@ await App.get('business-items', { page: 1 });
|
|
|
118
118
|
const platformHeaders = { 'X-DraftGo-Scope-Type': 'platform' };
|
|
119
119
|
await App.get('roles', {}, platformHeaders);
|
|
120
120
|
```
|
|
121
|
-
|
|
122
|
-
## 主题
|
|
123
|
-
|
|
124
|
-
```javascript
|
|
125
|
-
App.applyTheme('dark'); // 切换显示模式
|
|
126
|
-
App.setColorScheme('deep-blue-white'); // 切换预设配色
|
|
127
|
-
App.setColorScheme('custom', customVarsObject); // 自定义配色
|
|
128
|
-
App.getColorScheme(); // 获取方案详情
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
## 其他
|
|
132
|
-
|
|
133
|
-
```javascript
|
|
121
|
+
|
|
122
|
+
## 主题
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
App.applyTheme('dark'); // 切换显示模式
|
|
126
|
+
App.setColorScheme('deep-blue-white'); // 切换预设配色
|
|
127
|
+
App.setColorScheme('custom', customVarsObject); // 自定义配色
|
|
128
|
+
App.getColorScheme(); // 获取方案详情
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## 其他
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
134
|
await App.logout(); // 服务端登出、清理状态并跳转配置的登录页
|
|
135
|
-
App.setAuthTokens({ access_token, refresh_token }); // 登录后写入 token
|
|
136
|
-
App.reloadGlobalLayer(); // 重载全局层
|
|
135
|
+
App.setAuthTokens({ access_token, refresh_token }); // 登录后写入 token
|
|
136
|
+
App.reloadGlobalLayer(); // 重载全局层
|
|
137
137
|
App.openGlobalWidget(name); // 触发全局挂件打开
|
|
138
138
|
App.getScopeContext(); // 读取当前作用域
|
|
139
139
|
App.setScopeContext({ scope_type: 'space', space_id: '120' });
|
|
@@ -141,5 +141,5 @@ App.clearScopeContext(); // 清除手工选择,恢复服务端默
|
|
|
141
141
|
App.t(key, fallback?, values?); // 页面级国际化文本,values 保留 ICU 占位符
|
|
142
142
|
App.formatDateTime(value, options?); // 按 system_timezone 格式化 API 返回的 UTC 时间
|
|
143
143
|
```
|
|
144
|
-
|
|
144
|
+
|
|
145
145
|
Token、刷新、路由上下文和认证事件见 `references/runtime.md`。AI 对话、图片和兼容门面的完整契约见 `references/chat-sdk.md`,Agent 能力见 `references/aihub.md`。
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
---
|
|
2
|
-
read_when: 进入陌生 DraftGo 项目时 · 理解平台机制时(3 分钟速读)
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# DraftGo 架构认知
|
|
6
|
-
|
|
7
|
-
## 核心概念(30 秒)
|
|
8
|
-
|
|
9
|
-
DraftGo **不是传统 SPA**,是「数据库驱动的页面资产运行时」:
|
|
10
|
-
|
|
11
|
-
- 壳层(React + Vite)负责平台前端、runtime 编排、管理界面
|
|
12
|
-
- 业务页面 HTML 存在数据库 `page.value.html`,运行在 `iframe.srcdoc`
|
|
13
|
-
- 导航栏 HTML 存在数据库 `navigation.html`,壳层按需加载
|
|
14
|
-
- 页面与壳层通过 `window.parent.App` 通信
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## 为什么这样设计(1 分钟)
|
|
19
|
-
|
|
20
|
-
| 问题 | 传统 SPA | DraftGo 方案 |
|
|
21
|
-
|---|---|---|
|
|
22
|
-
| 页面内容更新 | 需要重新编译部署 | 直接改数据库 HTML,秒级生效 |
|
|
23
|
-
| 多租户/多项目 | 需要多套工程 | 一套壳层,数据库隔离内容 |
|
|
24
|
-
| 权限控制 | 路由守卫 + 条件渲染 | `page.permission` 字段控制,壳层统一拦截 |
|
|
1
|
+
---
|
|
2
|
+
read_when: 进入陌生 DraftGo 项目时 · 理解平台机制时(3 分钟速读)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# DraftGo 架构认知
|
|
6
|
+
|
|
7
|
+
## 核心概念(30 秒)
|
|
8
|
+
|
|
9
|
+
DraftGo **不是传统 SPA**,是「数据库驱动的页面资产运行时」:
|
|
10
|
+
|
|
11
|
+
- 壳层(React + Vite)负责平台前端、runtime 编排、管理界面
|
|
12
|
+
- 业务页面 HTML 存在数据库 `page.value.html`,运行在 `iframe.srcdoc`
|
|
13
|
+
- 导航栏 HTML 存在数据库 `navigation.html`,壳层按需加载
|
|
14
|
+
- 页面与壳层通过 `window.parent.App` 通信
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 为什么这样设计(1 分钟)
|
|
19
|
+
|
|
20
|
+
| 问题 | 传统 SPA | DraftGo 方案 |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| 页面内容更新 | 需要重新编译部署 | 直接改数据库 HTML,秒级生效 |
|
|
23
|
+
| 多租户/多项目 | 需要多套工程 | 一套壳层,数据库隔离内容 |
|
|
24
|
+
| 权限控制 | 路由守卫 + 条件渲染 | `page.permission` 字段控制,壳层统一拦截 |
|
|
25
25
|
| 导航定制 | 改代码重部署 | MCP 定位后 checkout navigation.html,commit 即生效 |
|
|
26
|
-
|
|
27
|
-
**核心推论**:在 DraftGo 里「修改页面」= 修改数据库里的 HTML 字符串,不是修改 `.tsx` 文件。
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
26
|
+
|
|
27
|
+
**核心推论**:在 DraftGo 里「修改页面」= 修改数据库里的 HTML 字符串,不是修改 `.tsx` 文件。
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
31
|
## App 对象是什么(1 分钟)
|
|
32
32
|
|
|
33
33
|
壳层将能力对象赋值给 `window.App`,数据库页面通过 `window.parent.App` 使用带认证的请求、反馈、路由、当前用户和主题能力。方法签名见 `references/app-api.md`;iframe 注入、认证事件和路由参数见 `references/runtime.md`。
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## 技术栈(30 秒)
|
|
38
|
-
|
|
39
|
-
| 层 | 技术 |
|
|
40
|
-
|---|---|
|
|
41
|
-
| 后端 | Go 1.26 · 标准库 `net/http` · `database/sql`(go-sql-driver/mysql)· MySQL · Redis |
|
|
42
|
-
| 壳层前端 | React · Vite |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 技术栈(30 秒)
|
|
38
|
+
|
|
39
|
+
| 层 | 技术 |
|
|
40
|
+
|---|---|
|
|
41
|
+
| 后端 | Go 1.26 · 标准库 `net/http` · `database/sql`(go-sql-driver/mysql)· MySQL · Redis |
|
|
42
|
+
| 壳层前端 | React · Vite |
|
|
43
43
|
| 数据库页面 | HTML 文档运行时 · Tailwind CSS 4 · Basecoat UI(默认)· Oat UI(可选)· Font Awesome · GSAP · 内置 SVG 图标库 |
|
|
44
|
-
| CLI | Node.js(draftgo-cli) |
|
|
45
|
-
|
|
44
|
+
| CLI | Node.js(draftgo-cli) |
|
|
45
|
+
|
|
46
46
|
数据库页面以完整 HTML 文档运行,直接加载平台提供的本地资源;壳层源码按 React + Vite 工程构建。开发时按目标所属层使用上表对应技术栈。
|