draftgo-cli 4.0.23 → 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 +1 -1
- package/bin/draftgo.js +8 -8
- package/package.json +72 -72
- package/resources/custom-service-sdk/auth_test.go +1 -1
- package/resources/custom-service-sdk/manifest.json +11 -11
- package/resources/custom-service-sdk/platform.go +10 -3
- 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 +4 -3
- 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 +4 -4
- package/resources/skill/references/data.md +168 -168
- package/resources/skill/references/methods.md +3 -0
- package/resources/skill/references/modules.md +47 -47
- 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 +167 -167
- package/src/prompt.js +94 -94
- package/src/updateCheck.js +16 -16
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
---
|
|
2
|
-
read_when: 操作动态 DB 之前 · 设计数据结构时 · 使用 filters 检索时 · 定义关联关系时
|
|
3
|
-
---
|
|
4
|
-
|
|
1
|
+
---
|
|
2
|
+
read_when: 操作动态 DB 之前 · 设计数据结构时 · 使用 filters 检索时 · 定义关联关系时
|
|
3
|
+
---
|
|
4
|
+
|
|
5
5
|
# 动态 DB & 数据层
|
|
6
6
|
|
|
7
7
|
## 最短管理流程
|
|
@@ -20,180 +20,180 @@ draftgo api search "dynamic db record"
|
|
|
20
20
|
完成条件:schema 可按 `type` 回读,目标角色的最小 CRUD 与筛选行为通过;批量写入还要验证失败时整批回滚。
|
|
21
21
|
|
|
22
22
|
## DB Meta 结构
|
|
23
|
-
|
|
24
|
-
```json
|
|
25
|
-
{
|
|
26
|
-
"type": "order",
|
|
27
|
-
"label": "订单",
|
|
28
|
-
"schema": {
|
|
29
|
-
"type": "object",
|
|
30
|
-
"properties": {
|
|
31
|
-
"name": { "type": "string", "title": "姓名", "required": true, "searchable": "fuzzy" },
|
|
32
|
-
"status": { "type": "string", "title": "状态", "required": false, "searchable": "exact" },
|
|
33
|
-
"amount": { "type": "number", "title": "金额", "required": false, "searchable": "range" },
|
|
34
|
-
"paid_at": { "type": "datetime", "title": "支付时间", "required": false, "searchable": "range" },
|
|
35
|
-
"tags": { "type": "array", "title": "标签", "required": false, "searchable": "contains" },
|
|
36
|
-
"note": { "type": "string", "title": "备注", "required": false, "searchable": false }
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
"permission": {
|
|
40
|
-
"public": { "read": "none", "create": "none", "update": "none", "delete": "none" },
|
|
41
|
-
"login": { "read": "all", "create": "all", "update": "owner", "delete": "owner" },
|
|
42
|
-
"admin": { "read": "all", "create": "all", "update": "all", "delete": "all" }
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
**searchable 模式**:`false`(不可检索)/ `"exact"`(精确)/ `"fuzzy"`(模糊)/ `"range"`(数值/时间范围)/ `"contains"`(数组包含)
|
|
48
|
-
|
|
49
|
-
`date` 字段保存为 `YYYY-MM-DD`;`datetime` 字段保存为 ISO 8601 字符串,带时区的输入会规范化为 UTC。`searchable: true` 对 `number` / `date` / `datetime` 会自动推断为 `range`。
|
|
50
|
-
|
|
51
|
-
**系统字段**:以下系统字段**无需在 schema 中定义**,可直接用于检索和排序:
|
|
52
|
-
|
|
53
|
-
| 字段 | 类型 | 检索模式 | 说明 |
|
|
54
|
-
|---|---|---|---|
|
|
55
|
-
| `id` | number | range | 记录 ID,支持 `eq` / `gte` / `lte` / `gt` / `lt` / `in` |
|
|
56
|
-
| `userid` | number | range | 所属用户 ID,支持 `eq` / `gte` / `lte` / `gt` / `lt` / `in` |
|
|
57
|
-
| `created_at` | datetime | range | 创建时间,支持 `eq` / `gte` / `lte` / `gt` / `lt` / `in` |
|
|
58
|
-
| `updated_at` | datetime | range | 更新时间,支持 `eq` / `gte` / `lte` / `gt` / `lt` / `in` |
|
|
59
|
-
|
|
60
|
-
⚠️ **注意**:虽然 DB 表有 `status` 系统列(1=正常 0=禁用 -1=删除),但由于业务常用此字段名,**需在 schema 中显式声明 `status` 的 searchable 才可检索**。
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"type": "order",
|
|
27
|
+
"label": "订单",
|
|
28
|
+
"schema": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"properties": {
|
|
31
|
+
"name": { "type": "string", "title": "姓名", "required": true, "searchable": "fuzzy" },
|
|
32
|
+
"status": { "type": "string", "title": "状态", "required": false, "searchable": "exact" },
|
|
33
|
+
"amount": { "type": "number", "title": "金额", "required": false, "searchable": "range" },
|
|
34
|
+
"paid_at": { "type": "datetime", "title": "支付时间", "required": false, "searchable": "range" },
|
|
35
|
+
"tags": { "type": "array", "title": "标签", "required": false, "searchable": "contains" },
|
|
36
|
+
"note": { "type": "string", "title": "备注", "required": false, "searchable": false }
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"permission": {
|
|
40
|
+
"public": { "read": "none", "create": "none", "update": "none", "delete": "none" },
|
|
41
|
+
"login": { "read": "all", "create": "all", "update": "owner", "delete": "owner" },
|
|
42
|
+
"admin": { "read": "all", "create": "all", "update": "all", "delete": "all" }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**searchable 模式**:`false`(不可检索)/ `"exact"`(精确)/ `"fuzzy"`(模糊)/ `"range"`(数值/时间范围)/ `"contains"`(数组包含)
|
|
48
|
+
|
|
49
|
+
`date` 字段保存为 `YYYY-MM-DD`;`datetime` 字段保存为 ISO 8601 字符串,带时区的输入会规范化为 UTC。`searchable: true` 对 `number` / `date` / `datetime` 会自动推断为 `range`。
|
|
50
|
+
|
|
51
|
+
**系统字段**:以下系统字段**无需在 schema 中定义**,可直接用于检索和排序:
|
|
52
|
+
|
|
53
|
+
| 字段 | 类型 | 检索模式 | 说明 |
|
|
54
|
+
|---|---|---|---|
|
|
55
|
+
| `id` | number | range | 记录 ID,支持 `eq` / `gte` / `lte` / `gt` / `lt` / `in` |
|
|
56
|
+
| `userid` | number | range | 所属用户 ID,支持 `eq` / `gte` / `lte` / `gt` / `lt` / `in` |
|
|
57
|
+
| `created_at` | datetime | range | 创建时间,支持 `eq` / `gte` / `lte` / `gt` / `lt` / `in` |
|
|
58
|
+
| `updated_at` | datetime | range | 更新时间,支持 `eq` / `gte` / `lte` / `gt` / `lt` / `in` |
|
|
59
|
+
|
|
60
|
+
⚠️ **注意**:虽然 DB 表有 `status` 系统列(1=正常 0=禁用 -1=删除),但由于业务常用此字段名,**需在 schema 中显式声明 `status` 的 searchable 才可检索**。
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
64
|
## 自定义服务内的 ctx.DB.Query
|
|
65
65
|
|
|
66
66
|
Go 自定义服务使用 `ctx.DB.Query(type, sdk.QueryOptions{...})` 操作动态 DB,返回 `sdk.QueryResult`:
|
|
67
67
|
|
|
68
68
|
```go
|
|
69
69
|
result, err := ctx.DB.Query("order", sdk.QueryOptions{
|
|
70
|
-
Filters: map[string]any{"status": "paid"},
|
|
71
|
-
Page: 1, PageSize: 20, OrderBy: "id", Order: "desc",
|
|
72
|
-
})
|
|
73
|
-
items := result.Items
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
| 参数 | 说明 |
|
|
77
|
-
|---|---|
|
|
78
|
-
| `filters` | 字典形式结构化过滤;默认 `{field: value}` 是 `eq` 精确匹配 |
|
|
79
|
-
| `Page` / `PageSize` | 分页参数;零值交由平台使用默认列表行为 |
|
|
80
|
-
| `order_by` / `order` | 按 searchable 字段排序,`order` 为 `asc` / `desc` |
|
|
81
|
-
|
|
82
|
-
⚠️ 返回结构为 `sdk.QueryResult{Items, Total, Page, PageSize}`。需要完整数据时必须按 `Total` 分页读取,不能用超大 `PageSize` 假装全量。
|
|
83
|
-
|
|
84
|
-
普通用户调用时只读 `status=1` 数据;系统身份/管理员脚本可读全部状态数据,但仍受 db_meta permission 约束。不要把“拿不到禁用数据”和分页截断混在一起排查。
|
|
85
|
-
|
|
86
|
-
`filters` 操作符示例:
|
|
87
|
-
|
|
88
|
-
```go
|
|
70
|
+
Filters: map[string]any{"status": "paid"},
|
|
71
|
+
Page: 1, PageSize: 20, OrderBy: "id", Order: "desc",
|
|
72
|
+
})
|
|
73
|
+
items := result.Items
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
| 参数 | 说明 |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `filters` | 字典形式结构化过滤;默认 `{field: value}` 是 `eq` 精确匹配 |
|
|
79
|
+
| `Page` / `PageSize` | 分页参数;零值交由平台使用默认列表行为 |
|
|
80
|
+
| `order_by` / `order` | 按 searchable 字段排序,`order` 为 `asc` / `desc` |
|
|
81
|
+
|
|
82
|
+
⚠️ 返回结构为 `sdk.QueryResult{Items, Total, Page, PageSize}`。需要完整数据时必须按 `Total` 分页读取,不能用超大 `PageSize` 假装全量。
|
|
83
|
+
|
|
84
|
+
普通用户调用时只读 `status=1` 数据;系统身份/管理员脚本可读全部状态数据,但仍受 db_meta permission 约束。不要把“拿不到禁用数据”和分页截断混在一起排查。
|
|
85
|
+
|
|
86
|
+
`filters` 操作符示例:
|
|
87
|
+
|
|
88
|
+
```go
|
|
89
89
|
ctx.DB.Query("order", sdk.QueryOptions{Filters: map[string]any{
|
|
90
|
-
"status": "paid",
|
|
91
|
-
"customer_name": map[string]any{"op": "like", "value": "张"},
|
|
92
|
-
"amount": map[string]any{"op": "gte", "value": 100},
|
|
93
|
-
"id": map[string]any{"op": "in", "value": []int{1, 2, 3}},
|
|
94
|
-
}})
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
字段必须在 db_meta schema 中标记 `searchable`,系统字段 `id/userid/created_at/updated_at` 可直接检索和排序。`status` 若作为业务字段检索,仍需在 schema 中显式声明。
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
90
|
+
"status": "paid",
|
|
91
|
+
"customer_name": map[string]any{"op": "like", "value": "张"},
|
|
92
|
+
"amount": map[string]any{"op": "gte", "value": 100},
|
|
93
|
+
"id": map[string]any{"op": "in", "value": []int{1, 2, 3}},
|
|
94
|
+
}})
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
字段必须在 db_meta schema 中标记 `searchable`,系统字段 `id/userid/created_at/updated_at` 可直接检索和排序。`status` 若作为业务字段检索,仍需在 schema 中显式声明。
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
101
|
## 关联关系(ref)
|
|
102
102
|
|
|
103
103
|
关系只在需要时读取 `references/db-relations.md`。核心不变量:`many-to-one` 与 `many-to-many` 在真实持有引用 ID 的字段上配置 `ref` 和 `onDelete`;`one-to-many` 是用于 `populate` 的虚拟反向关系。级联继承当前用户权限并在同一事务中执行,不要在前端用多次 DELETE 模拟。
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
|
107
|
-
## CRUD 操作范式
|
|
108
|
-
|
|
109
|
-
```javascript
|
|
110
|
-
// 查询(分页 + 结构化检索)
|
|
111
|
-
const res = await App.get(`db/order`, {
|
|
112
|
-
page: 1, page_size: 20,
|
|
113
|
-
filters: ['name:like:张', 'status:eq:paid', 'amount:gte:100'],
|
|
114
|
-
order_by: 'amount', order: 'desc',
|
|
115
|
-
});
|
|
116
|
-
const { items, total } = res.data;
|
|
117
|
-
|
|
118
|
-
// 非后台管理页面读取业务列表时,如果当前用户含 admin 角色,带 scope=mine
|
|
119
|
-
// 这只影响 GET /api/db/{type} 列表,让管理员业务视角只看自己的 owner 数据
|
|
120
|
-
const ownOrders = await App.get(`db/order`, {
|
|
121
|
-
page: 1,
|
|
122
|
-
page_size: 20,
|
|
123
|
-
scope: 'mine',
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// 系统字段检索和排序(无需在 schema 中定义)
|
|
127
|
-
const res = await App.get(`db/order`, {
|
|
128
|
-
filters: ['created_at:gte:2024-01-01', 'userid:eq:123'],
|
|
129
|
-
order_by: 'created_at', order: 'desc',
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
// 创建(业务字段必须放在 data 包裹里)
|
|
133
|
-
await App.post(`db/order`, { data: { name: '张三', amount: 200 }, status: 1 });
|
|
134
|
-
|
|
135
|
-
// 更新
|
|
136
|
-
await App.put(`db/order/${id}`, { data: { amount: 250 } });
|
|
137
|
-
|
|
138
|
-
// 删除
|
|
139
|
-
await App.delete(`db/order/${id}`);
|
|
140
|
-
|
|
141
|
-
// 批量更新(原子事务,任一失败全批回滚)
|
|
142
|
-
await App.patch(`db/order/batch`, [
|
|
143
|
-
{ id: 1, data: { status: 'paid' } },
|
|
144
|
-
{ id: 2, data: { status: 'paid' } },
|
|
145
|
-
]);
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
## filters 操作符
|
|
151
|
-
|
|
152
|
-
| 操作符 | 含义 | 适用 searchable 模式 |
|
|
153
|
-
|---|---|---|
|
|
154
|
-
| `eq` | 精确等于 | exact / fuzzy / range |
|
|
155
|
-
| `like` | 模糊包含 | fuzzy |
|
|
156
|
-
| `gte` / `lte` / `gt` / `lt` | 数值/时间范围 | range |
|
|
157
|
-
| `in` | 枚举命中(值逗号分隔:`status:in:paid,pending`) | exact / fuzzy / range |
|
|
158
|
-
| `contains` | 数组字段包含某值 | contains |
|
|
159
|
-
|
|
160
|
-
- 省略操作符(`filters: ['name:张三']`)默认 `like`
|
|
161
|
-
- 多个 filters 为 AND
|
|
162
|
-
- 字段未标 searchable 或操作符不匹配 → 后端返回 400
|
|
163
|
-
- **系统字段**(`id` / `userid` / `created_at` / `updated_at`)无需在 schema 中声明,可直接使用
|
|
164
|
-
- `scope=mine` 只对拥有 admin 角色的用户在 `GET /api/db/{type}` 列表请求中生效;非后台管理页面若当前用户是管理员,读取动态 DB 业务列表时应带该参数;后台管理页不要带,详情和写操作也不要带
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## db_meta 实时契约
|
|
169
|
-
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## CRUD 操作范式
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
// 查询(分页 + 结构化检索)
|
|
111
|
+
const res = await App.get(`db/order`, {
|
|
112
|
+
page: 1, page_size: 20,
|
|
113
|
+
filters: ['name:like:张', 'status:eq:paid', 'amount:gte:100'],
|
|
114
|
+
order_by: 'amount', order: 'desc',
|
|
115
|
+
});
|
|
116
|
+
const { items, total } = res.data;
|
|
117
|
+
|
|
118
|
+
// 非后台管理页面读取业务列表时,如果当前用户含 admin 角色,带 scope=mine
|
|
119
|
+
// 这只影响 GET /api/db/{type} 列表,让管理员业务视角只看自己的 owner 数据
|
|
120
|
+
const ownOrders = await App.get(`db/order`, {
|
|
121
|
+
page: 1,
|
|
122
|
+
page_size: 20,
|
|
123
|
+
scope: 'mine',
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// 系统字段检索和排序(无需在 schema 中定义)
|
|
127
|
+
const res = await App.get(`db/order`, {
|
|
128
|
+
filters: ['created_at:gte:2024-01-01', 'userid:eq:123'],
|
|
129
|
+
order_by: 'created_at', order: 'desc',
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// 创建(业务字段必须放在 data 包裹里)
|
|
133
|
+
await App.post(`db/order`, { data: { name: '张三', amount: 200 }, status: 1 });
|
|
134
|
+
|
|
135
|
+
// 更新
|
|
136
|
+
await App.put(`db/order/${id}`, { data: { amount: 250 } });
|
|
137
|
+
|
|
138
|
+
// 删除
|
|
139
|
+
await App.delete(`db/order/${id}`);
|
|
140
|
+
|
|
141
|
+
// 批量更新(原子事务,任一失败全批回滚)
|
|
142
|
+
await App.patch(`db/order/batch`, [
|
|
143
|
+
{ id: 1, data: { status: 'paid' } },
|
|
144
|
+
{ id: 2, data: { status: 'paid' } },
|
|
145
|
+
]);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## filters 操作符
|
|
151
|
+
|
|
152
|
+
| 操作符 | 含义 | 适用 searchable 模式 |
|
|
153
|
+
|---|---|---|
|
|
154
|
+
| `eq` | 精确等于 | exact / fuzzy / range |
|
|
155
|
+
| `like` | 模糊包含 | fuzzy |
|
|
156
|
+
| `gte` / `lte` / `gt` / `lt` | 数值/时间范围 | range |
|
|
157
|
+
| `in` | 枚举命中(值逗号分隔:`status:in:paid,pending`) | exact / fuzzy / range |
|
|
158
|
+
| `contains` | 数组字段包含某值 | contains |
|
|
159
|
+
|
|
160
|
+
- 省略操作符(`filters: ['name:张三']`)默认 `like`
|
|
161
|
+
- 多个 filters 为 AND
|
|
162
|
+
- 字段未标 searchable 或操作符不匹配 → 后端返回 400
|
|
163
|
+
- **系统字段**(`id` / `userid` / `created_at` / `updated_at`)无需在 schema 中声明,可直接使用
|
|
164
|
+
- `scope=mine` 只对拥有 admin 角色的用户在 `GET /api/db/{type}` 列表请求中生效;非后台管理页面若当前用户是管理员,读取动态 DB 业务列表时应带该参数;后台管理页不要带,详情和写操作也不要带
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## db_meta 实时契约
|
|
169
|
+
|
|
170
170
|
db_meta 是结构化远端资源,不 checkout,也不生成本地索引。未知 operation 才通过 MCP
|
|
171
171
|
`draftgo_api_search` 定位;首次使用或 registry revision 变化时 `draftgo_api_describe`,再用
|
|
172
172
|
`draftgo_api_call` 查询目标 type 和 schema。
|
|
173
|
-
典型返回条目如下:
|
|
174
|
-
|
|
175
|
-
```json
|
|
176
|
-
[
|
|
177
|
-
{
|
|
178
|
-
"id": 1,
|
|
179
|
-
"type": "order",
|
|
180
|
-
"label": "订单",
|
|
181
|
-
"schema": { ... }
|
|
182
|
-
}
|
|
183
|
-
]
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
⚠️ **GET `/api/db-meta/{type}` 用 type(如 `order`),不是 id。PUT/DELETE 才用 id。**
|
|
187
|
-
|
|
188
|
-
---
|
|
189
|
-
|
|
190
|
-
## 通用筛选参数(非动态 DB)
|
|
191
|
-
|
|
192
|
-
用于 users / roles / pages / navigations / feedback 等标准资源:
|
|
193
|
-
|
|
194
|
-
| 参数 | 说明 |
|
|
195
|
-
|---|---|
|
|
196
|
-
| `page` / `page_size` | 分页(不传返回全量且无上限;任一传入则分页,缺失项按 `page=1` / `page_size=20` 兜底) |
|
|
197
|
-
| `search` | 全文搜索(动态 DB 不用此参数) |
|
|
198
|
-
| `status` | 状态过滤 |
|
|
199
|
-
| `type` / `tag` | 类型/标签过滤 |
|
|
173
|
+
典型返回条目如下:
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
[
|
|
177
|
+
{
|
|
178
|
+
"id": 1,
|
|
179
|
+
"type": "order",
|
|
180
|
+
"label": "订单",
|
|
181
|
+
"schema": { ... }
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
⚠️ **GET `/api/db-meta/{type}` 用 type(如 `order`),不是 id。PUT/DELETE 才用 id。**
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 通用筛选参数(非动态 DB)
|
|
191
|
+
|
|
192
|
+
用于 users / roles / pages / navigations / feedback 等标准资源:
|
|
193
|
+
|
|
194
|
+
| 参数 | 说明 |
|
|
195
|
+
|---|---|
|
|
196
|
+
| `page` / `page_size` | 分页(不传返回全量且无上限;任一传入则分页,缺失项按 `page=1` / `page_size=20` 兜底) |
|
|
197
|
+
| `search` | 全文搜索(动态 DB 不用此参数) |
|
|
198
|
+
| `status` | 状态过滤 |
|
|
199
|
+
| `type` / `tag` | 类型/标签过滤 |
|
|
@@ -60,6 +60,7 @@ DataRange = 作用域内记录策略:none / own / all
|
|
|
60
60
|
|
|
61
61
|
platform AccessGrant 可跨空间,但只覆盖角色中显式列出的权限;space Grant 只能覆盖同根的 self/subtree。请求 header 只是候选上下文。
|
|
62
62
|
创建、读取、更新、删除都必须由服务端同时校验动作权限、持久化 ResourceOwnership 和 DataRange。
|
|
63
|
+
用户注册成功时,服务端会授予所有启用的注册默认平台 Role,并将用户加入系统默认工作区及其 `default_members` 用户组;前者创建 AccessGrant,后者创建成员关系,两者互不替代。
|
|
63
64
|
|
|
64
65
|
### 空间化最短流程
|
|
65
66
|
|
|
@@ -84,6 +85,8 @@ platform AccessGrant 可跨空间,但只覆盖角色中显式列出的权限
|
|
|
84
85
|
|
|
85
86
|
适用场景:修改已有 page/navigation/article 完整正文,或创建后继续编辑正文。
|
|
86
87
|
|
|
88
|
+
`docs/articles` 是系统说明使用的平台资源,只接受 platform scope;不要为文档传 `scope_type=space` 或 `space_id`。
|
|
89
|
+
|
|
87
90
|
```bash
|
|
88
91
|
draftgo map --type pages --route /admin/channel-ops --output json
|
|
89
92
|
draftgo checkout pages <id>
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
---
|
|
2
|
-
read_when: 评估功能可行性时 · 选择开发路径时 · 进入新项目做全局了解时
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# DraftGo 模块地图
|
|
6
|
-
|
|
7
|
-
## 可开发模块(开发者负责实现)
|
|
8
|
-
|
|
9
|
-
| 模块 | 开发方式 | 入口 |
|
|
10
|
-
|---|---|---|
|
|
1
|
+
---
|
|
2
|
+
read_when: 评估功能可行性时 · 选择开发路径时 · 进入新项目做全局了解时
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# DraftGo 模块地图
|
|
6
|
+
|
|
7
|
+
## 可开发模块(开发者负责实现)
|
|
8
|
+
|
|
9
|
+
| 模块 | 开发方式 | 入口 |
|
|
10
|
+
|---|---|---|
|
|
11
11
|
| 页面 | 数据库 HTML(`page.value.html`) | 已有页面由 MCP 定位后 `checkout pages` / `commit pages`;新页面先按实时 API 契约创建并取得 ID |
|
|
12
|
-
| 导航栏 | 数据库 HTML(`navigation.html`) | MCP 定位,`checkout nav` / `commit nav` 编辑正文 |
|
|
12
|
+
| 导航栏 | 数据库 HTML(`navigation.html`) | MCP 定位,`checkout nav` / `commit nav` 编辑正文 |
|
|
13
13
|
| 动态 DB | db_meta 定义 schema 并操作结构化记录 | MCP `api_search` / `api_describe` / `api_call` |
|
|
14
14
|
| 文件资产 | 文件夹、文件元数据、绑定、下载、回收站和对象存储 | MCP 实时 API;文件字节不进入普通 tool result |
|
|
15
15
|
| 自定义服务 | 单一 Go `Register` 服务;后端从注册代码自动发现 Route/Event/Scheduled handler | MCP 定位/创建;正文用 `checkout custom-services` / `commit custom-services` |
|
|
16
|
-
| AIHub | 配置 AI Agent(模型/编排/能力/子智能体/记忆);页面对话使用 `<dg-chat>`,图片模式使用 `DraftGoAI.images`;见 `references/chat-sdk.md` 与 `references/aihub.md` | MCP 实时 API;不创建本地镜像 |
|
|
17
|
-
| 文档中心 | Markdown/HTML
|
|
16
|
+
| AIHub | 配置 AI Agent(模型/编排/能力/子智能体/记忆);页面对话使用 `<dg-chat>`,图片模式使用 `DraftGoAI.images`;见 `references/chat-sdk.md` 与 `references/aihub.md` | MCP 实时 API;不创建本地镜像 |
|
|
17
|
+
| 文档中心 | 平台级 Markdown/HTML 系统文章 + 分类树 | 正文用 `checkout docs` / `commit docs`;分类用 MCP;不传 space scope |
|
|
18
18
|
| 系统配置 | KV 存储,含全局前端层槽位 | MCP 实时 API;不创建本地镜像 |
|
|
19
19
|
| 商业与计费 | 账本、余额、权益、支付订单、退款、套餐、订阅和 AI 计费 | 管理任务用 MCP 实时 API;自定义服务用 `ctx.Billing` / `ctx.Admin.Billing`;不要用动态 DB 重建金钱状态 |
|
|
20
|
-
|
|
21
|
-
## 平台内置模块(开箱即用,不需实现)
|
|
22
|
-
|
|
23
|
-
| 模块 | 能力 | 调用方式 |
|
|
24
|
-
|---|---|---|
|
|
20
|
+
|
|
21
|
+
## 平台内置模块(开箱即用,不需实现)
|
|
22
|
+
|
|
23
|
+
| 模块 | 能力 | 调用方式 |
|
|
24
|
+
|---|---|---|
|
|
25
25
|
| 认证 | 注册/登录/刷新/找回密码/微信登录/手机邮箱验证 | 页面使用 `App`;服务端操作通过 MCP 实时描述接口 |
|
|
26
26
|
| 角色权限 | 无作用域 Role 模板 + 带 `platform` / `space` 范围的 AccessGrant | 页面可用 `App.permissions` 辅助显隐;服务端按资源授权 |
|
|
27
27
|
| 工作区与空间 | 根工作区成员、用户组和递归 Space;成员关系本身不授权 | `App.scopeContext` + MCP space/group/grant operations;资源保存直接归属 |
|
|
@@ -33,7 +33,7 @@ read_when: 评估功能可行性时 · 选择开发路径时 · 进入新项目
|
|
|
33
33
|
|
|
34
34
|
`App.currentUser.role_code` 是展示投影,不是用户表中的可写字段。真正的资源/API 授权由服务端根据 ResourceOwnership 与有效 AccessGrant 决定;platform Grant 也只能使用角色中显式声明的权限。
|
|
35
35
|
|
|
36
|
-
用户 API Key 只是一种用户认证方式;它不改变 AccessGrant、ResourceOwnership、DataRange
|
|
36
|
+
用户 API Key 只是一种用户认证方式;它不改变 AccessGrant、ResourceOwnership、DataRange 或管理员边界。无人值守任务由平台运行时以 system 身份执行。
|
|
37
37
|
|
|
38
38
|
## 新模块权限接入检查表
|
|
39
39
|
|
|
@@ -47,12 +47,12 @@ AI 新建或扩展受保护模块时,按以下最小闭环逐项确认;缺
|
|
|
47
47
|
- [ ] 保留最小拒绝证据:无 Grant、space Grant 跨根、伪造归属;支持 own/all 时再覆盖他人记录拒绝。不要为同一规则复制一套测试框架。
|
|
48
48
|
|
|
49
49
|
实现位置和具体 API 以目标 DraftGo 服务端仓库的现有 Catalog、ResourceOwnership 与 WorkspaceAuthorizer 模式为准;本 Skill 不复制服务端动态 schema。
|
|
50
|
-
|
|
51
|
-
## 模块选型决策
|
|
52
|
-
|
|
53
|
-
```
|
|
50
|
+
|
|
51
|
+
## 模块选型决策
|
|
52
|
+
|
|
53
|
+
```
|
|
54
54
|
要存储业务数据?
|
|
55
|
-
→ 有固定结构 → 动态 DB(db_meta 定义 schema)
|
|
55
|
+
→ 有固定结构 → 动态 DB(db_meta 定义 schema)
|
|
56
56
|
→ 仅需 KV → sys_config(category 自定义)
|
|
57
57
|
|
|
58
58
|
要保存文件?
|
|
@@ -60,35 +60,35 @@ AI 新建或扩展受保护模块时,按以下最小闭环逐项确认;缺
|
|
|
60
60
|
|
|
61
61
|
要做余额、支付、会员或订阅?
|
|
62
62
|
→ 管理操作走 money/payment/subscription/billing 的 MCP 实时契约;自定义服务读 `.draftgo-sdk/billing.go` 并使用 Billing SDK,不自行实现账本或扣费一致性
|
|
63
|
-
|
|
64
|
-
要调用 AI?
|
|
65
|
-
→ 聊天/问答 UI → AIHub + `<dg-chat>`(自动隔离 thread/session)
|
|
66
|
-
→ 无 UI 的旧代码文本调用 → AIHub + DraftGoAI.chat()(兼容门面)
|
|
63
|
+
|
|
64
|
+
要调用 AI?
|
|
65
|
+
→ 聊天/问答 UI → AIHub + `<dg-chat>`(自动隔离 thread/session)
|
|
66
|
+
→ 无 UI 的旧代码文本调用 → AIHub + DraftGoAI.chat()(兼容门面)
|
|
67
67
|
→ 图片生成 → AIHub + DraftGoAI.images()
|
|
68
68
|
→ Responses、Embedding、Rerank、TTS、ASR 或 Video → AIHub capability 与 provider readiness;先确认模型的 canonical capability 和 transport
|
|
69
|
-
→ 需要工具/子智能体/记忆/结构化输出/多模态 → 都是 Agent spec 开关,见 references/aihub.md
|
|
70
|
-
|
|
71
|
-
要调用第三方服务?
|
|
69
|
+
→ 需要工具/子智能体/记忆/结构化输出/多模态 → 都是 Agent spec 开关,见 references/aihub.md
|
|
70
|
+
|
|
71
|
+
要调用第三方服务?
|
|
72
72
|
→ 自定义服务(用 `ctx.HTTP` 请求;在同一 Go 服务中按需注册 Route/Event/Scheduled handler)
|
|
73
|
-
|
|
74
|
-
要展示内容文档?
|
|
75
|
-
→ 文档中心(Markdown + 分类树)
|
|
76
|
-
|
|
77
|
-
要做定时任务或事件响应?
|
|
73
|
+
|
|
74
|
+
要展示内容文档?
|
|
75
|
+
→ 文档中心(Markdown + 分类树)
|
|
76
|
+
|
|
77
|
+
要做定时任务或事件响应?
|
|
78
78
|
→ 自定义服务(用 `app.Schedule` / `app.On` 注册;后端自动识别定时任务和事件 handler)
|
|
79
|
-
|
|
80
|
-
要做后台管理页?
|
|
81
|
-
→ 业务页面 + 动态 DB + 角色权限
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## 自定义服务边界
|
|
85
|
-
|
|
86
|
-
- 新服务使用 Go `Register(app *sdk.App)` 自动注册路由、事件和定时任务;完整语言、`draftgo` 和 SDK 契约见 `references/custom-services.md`。
|
|
79
|
+
|
|
80
|
+
要做后台管理页?
|
|
81
|
+
→ 业务页面 + 动态 DB + 角色权限
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 自定义服务边界
|
|
85
|
+
|
|
86
|
+
- 新服务使用 Go `Register(app *sdk.App)` 自动注册路由、事件和定时任务;完整语言、`draftgo` 和 SDK 契约见 `references/custom-services.md`。
|
|
87
87
|
- `Route`:对外暴露 HTTP 端点;同一 Go 服务可用多个 `app.Route(method, path, handler)` 注册多个端点,实际路径通过 MCP 实时发现,草稿行为先用 `draftgo test custom-services` 验证。
|
|
88
88
|
- `Event`:响应平台事件,如 `db.created` / `db.updated` / `user.registered`;用 `app.On(event, handler)` 注册,可为同一事件注册多个 handler。
|
|
89
89
|
- `Scheduled`:用 `app.Schedule("分 时 日 月 周", handler)` 注册 cron;同一服务可声明多个定时 handler。
|
|
90
|
-
- 新 Go 服务的 `Register` 是唯一触发器事实来源;旧 `triggers` 字段不参与注册。
|
|
90
|
+
- 新 Go 服务的 `Register` 是唯一触发器事实来源;旧 `triggers` 字段不参与注册。
|
|
91
91
|
- 管理面由角色 RBAC 的 `scripts:*` 动作控制;Route 不再读取服务级 `permission`,由宿主认证、持久化 ownership 和 `scripts:execute` AccessGrant 统一控制。
|
|
92
|
-
- Go 服务在独立子进程中构建/运行;只有可信角色才能获得 `scripts:create` / `scripts:update`。
|
|
93
|
-
- 自定义服务适合服务端加工、鉴权后聚合、第三方回调、定时任务和事件响应;普通 CRUD 管理界面优先用“页面 + 动态 DB”,不要把所有业务后台都塞进 route 脚本。
|
|
92
|
+
- Go 服务在独立子进程中构建/运行;只有可信角色才能获得 `scripts:create` / `scripts:update`。
|
|
93
|
+
- 自定义服务适合服务端加工、鉴权后聚合、第三方回调、定时任务和事件响应;普通 CRUD 管理界面优先用“页面 + 动态 DB”,不要把所有业务后台都塞进 route 脚本。
|
|
94
94
|
- 脚本内读动态 DB 用 `ctx.DB.Query(type, sdk.QueryOptions{...})`;返回 `sdk.QueryResult`,分页和筛选见 `references/custom-services.md`。
|