exflower-license-server 1.0.7 → 1.0.8
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 +33 -34
- package/package.json +1 -1
- package/routes.js +22 -10
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ npm install -g exflower-license-server
|
|
|
12
12
|
|
|
13
13
|
# 查看版本
|
|
14
14
|
exflower-license-server --version
|
|
15
|
-
# 输出: 1.0.
|
|
15
|
+
# 输出: 1.0.7
|
|
16
16
|
|
|
17
17
|
# 运行
|
|
18
18
|
exflower-license-server
|
|
@@ -145,9 +145,9 @@ sudo systemctl enable --now exflower-license-server
|
|
|
145
145
|
启动后访问 `http://localhost:4001/admin`,使用 `ADMIN_TOKEN` 登录。
|
|
146
146
|
|
|
147
147
|
管理后台功能:
|
|
148
|
-
-
|
|
148
|
+
- **企业管理**:创建公司时可选择有效期(1/3/6 个月、1 年、2 年、永久);列表显示剩余天数(<30 天标黄、过期标红);支持编辑(改有效期/配额)、暂停/恢复、删除
|
|
149
149
|
- **实例管理**:查看已激活的实例列表
|
|
150
|
-
-
|
|
150
|
+
- **模板管理**:按类型选择上传方式(见下方"模板系统"),支持按公司分发,查看导入统计(次数/公司/实例)
|
|
151
151
|
|
|
152
152
|
## API 端点
|
|
153
153
|
|
|
@@ -177,17 +177,26 @@ sudo systemctl enable --now exflower-license-server
|
|
|
177
177
|
|
|
178
178
|
## 模板系统
|
|
179
179
|
|
|
180
|
-
模板用于向客户端分发预设配置。管理后台支持创建 `agent`、`
|
|
180
|
+
模板用于向客户端分发预设配置。管理后台支持创建 `agent`、`excard`、`workflow`、`doc` 四种类型的模板。
|
|
181
|
+
|
|
182
|
+
### 上传方式(v1.0.7 起)
|
|
183
|
+
|
|
184
|
+
管理后台根据类型提供不同的上传方式:
|
|
185
|
+
|
|
186
|
+
- **agent / excard / doc**:**Markdown 原生上传**。直接上传客户端导出的 `.md` 文件(或粘贴 Markdown 文本),后台自动解析 frontmatter 预填模板名称并生成 `content_json`,无需手写 JSON。
|
|
187
|
+
- **workflow**:仍以 JSON 描述步骤结构(步骤间的 excardId 引用和分支跳转无法由 Markdown 表达),上传框预填骨架示例。
|
|
188
|
+
|
|
189
|
+
通过 API 创建模板时,`content_json` 与 `content_md` 至少提供一个(`workflow` 类型必须提供 `content_json`)。
|
|
181
190
|
|
|
182
191
|
### 通用字段
|
|
183
192
|
|
|
184
193
|
| 字段 | 必填 | 说明 |
|
|
185
194
|
|------|------|------|
|
|
186
|
-
| `type` | 是 | 模板类型:`agent` / `
|
|
195
|
+
| `type` | 是 | 模板类型:`agent` / `excard` / `workflow` / `doc` |
|
|
187
196
|
| `name` | 是 | 模板名称 |
|
|
188
197
|
| `description` | 否 | 模板简介(一句话描述) |
|
|
189
|
-
| `content_json` |
|
|
190
|
-
| `content_md` |
|
|
198
|
+
| `content_json` | 视类型 | 结构化数据(JSON 对象);`workflow` 必填,其余类型可由 `content_md` 代替 |
|
|
199
|
+
| `content_md` | 视类型 | Markdown 内容;`agent` / `excard` / `doc` 推荐以此为主 |
|
|
191
200
|
| `company_id` | 否 | `NULL` = 全局模板(所有公司可见);指定公司 ID = 仅该公司可见 |
|
|
192
201
|
| `tags` | 否 | 标签数组 JSON,如 `["营销", "运营"]` |
|
|
193
202
|
| `version` | 否 | 版本号,默认 `1.0` |
|
|
@@ -196,9 +205,9 @@ sudo systemctl enable --now exflower-license-server
|
|
|
196
205
|
|
|
197
206
|
#### `agent` — Agent 成员模板
|
|
198
207
|
|
|
199
|
-
用于创建 CrewAI Agent
|
|
208
|
+
用于创建 CrewAI Agent。**推荐直接上传客户端 agent 的 `.md` 文件**(YAML frontmatter + Backstory/Experience 正文),frontmatter 字段即 `content_json`。
|
|
200
209
|
|
|
201
|
-
**content_json 字段:**
|
|
210
|
+
**frontmatter / content_json 字段:**
|
|
202
211
|
|
|
203
212
|
| 字段 | 必填 | 类型 | 说明 |
|
|
204
213
|
|------|------|------|------|
|
|
@@ -217,6 +226,18 @@ sudo systemctl enable --now exflower-license-server
|
|
|
217
226
|
**content_md 格式(推荐提供):**
|
|
218
227
|
|
|
219
228
|
```markdown
|
|
229
|
+
---
|
|
230
|
+
id: agent-xxx
|
|
231
|
+
name: 小红书运营专家
|
|
232
|
+
role: 小红书内容运营与增长策略师
|
|
233
|
+
goal: 帮助用户制定并执行高效的小红书内容策略
|
|
234
|
+
tools: []
|
|
235
|
+
allowDelegation: false
|
|
236
|
+
maxIter: 25
|
|
237
|
+
memory: true
|
|
238
|
+
allowScriptExecution: disabled
|
|
239
|
+
---
|
|
240
|
+
|
|
220
241
|
# Backstory
|
|
221
242
|
|
|
222
243
|
Agent 的完整背景故事,支持 Markdown 格式...
|
|
@@ -231,33 +252,11 @@ Agent 的完整背景故事,支持 Markdown 格式...
|
|
|
231
252
|
|
|
232
253
|
---
|
|
233
254
|
|
|
234
|
-
#### `crew` — 项目组模板
|
|
235
|
-
|
|
236
|
-
用于创建 Crew(Agent 团队)。
|
|
237
|
-
|
|
238
|
-
**content_json 字段:**
|
|
239
|
-
|
|
240
|
-
| 字段 | 必填 | 类型 | 说明 |
|
|
241
|
-
|------|------|------|------|
|
|
242
|
-
| `name` | 是 | string | 项目组名称 |
|
|
243
|
-
| `description` | 否 | string | 项目组描述 |
|
|
244
|
-
| `agentIds` | 否 | string[] | 成员 Agent ID 列表 |
|
|
245
|
-
| `tasks` | 否 | object[] | 任务列表,每个任务包含: |
|
|
246
|
-
| `tasks[].id` | 是 | string | 任务 ID |
|
|
247
|
-
| `tasks[].agentId` | 是 | string | 执行任务的 Agent ID |
|
|
248
|
-
| `tasks[].description` | 是 | string | 任务描述 |
|
|
249
|
-
| `tasks[].order` | 否 | number | 执行顺序 |
|
|
250
|
-
| `tasks[].expectedOutput` | 否 | string | 期望输出 |
|
|
251
|
-
| `process` | 否 | string | 执行流程:`sequential`(顺序)/ `hierarchical`(层级),默认 `sequential` |
|
|
252
|
-
| `managerAgentId` | 否 | string | Manager Agent ID(层级流程时必填) |
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
255
|
#### `excard` — ExCard 执行模板
|
|
257
256
|
|
|
258
|
-
用于创建工作流执行的 ExCard
|
|
257
|
+
用于创建工作流执行的 ExCard 模板。**推荐直接上传客户端导出的标准 ExCard `.md` 文件**(与客户端"导出 ExCard"产物格式一致):模板只需存 `content_md`,客户端导入时走标准 MD 导入链路(`POST /api/excards/import`),由客户端解析为结构化数据。frontmatter 会被后台自动提取为 `content_json` 用于列表展示。
|
|
259
258
|
|
|
260
|
-
**content_json 字段:**
|
|
259
|
+
**frontmatter / content_json 字段:**
|
|
261
260
|
|
|
262
261
|
| 字段 | 必填 | 类型 | 说明 |
|
|
263
262
|
|------|------|------|------|
|
|
@@ -271,7 +270,7 @@ Agent 的完整背景故事,支持 Markdown 格式...
|
|
|
271
270
|
|
|
272
271
|
**content_md 格式(必须提供):**
|
|
273
272
|
|
|
274
|
-
ExCard 的完整 Markdown
|
|
273
|
+
ExCard 的完整 Markdown 文档(frontmatter + 资源依赖 + 执行步骤 + 执行约定),与客户端 `~/.exflower/excards-md/` 下的文件格式一致。
|
|
275
274
|
|
|
276
275
|
---
|
|
277
276
|
|
package/package.json
CHANGED
package/routes.js
CHANGED
|
@@ -267,11 +267,18 @@ function setupRoutes(app) {
|
|
|
267
267
|
return res.status(404).json({ success: false, message: 'Invalid license key' });
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
270
|
+
// 按设备过滤:导入状态跟着设备(instance_id)走,而非激活码;
|
|
271
|
+
// 未传 instance_id 的旧版客户端保持 company 级聚合(向后兼容)
|
|
272
|
+
const instanceId = req.query.instance_id;
|
|
273
|
+
let sql = `SELECT template_id, COUNT(*) as count, MIN(imported_at) as first_import, MAX(imported_at) as last_import
|
|
274
|
+
FROM template_imports WHERE company_id = ?`;
|
|
275
|
+
const params = [company.id];
|
|
276
|
+
if (instanceId) {
|
|
277
|
+
sql += ' AND instance_id = ?';
|
|
278
|
+
params.push(instanceId);
|
|
279
|
+
}
|
|
280
|
+
sql += ' GROUP BY template_id';
|
|
281
|
+
const rows = queryAll(sql, params);
|
|
275
282
|
const map = {};
|
|
276
283
|
for (const r of rows) {
|
|
277
284
|
map[r.template_id] = { count: r.count, first_import: r.first_import, last_import: r.last_import };
|
|
@@ -511,11 +518,16 @@ function setupRoutes(app) {
|
|
|
511
518
|
return res.status(404).json({ success: false, message: 'Invalid license key' });
|
|
512
519
|
}
|
|
513
520
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
521
|
+
// 按设备过滤(见 import-summary 注释)
|
|
522
|
+
const instanceId = req.query.instance_id;
|
|
523
|
+
let sql = `SELECT COUNT(*) as count, MIN(imported_at) as first_import, MAX(imported_at) as last_import
|
|
524
|
+
FROM template_imports WHERE template_id = ? AND company_id = ?`;
|
|
525
|
+
const params = [req.params.id, company.id];
|
|
526
|
+
if (instanceId) {
|
|
527
|
+
sql += ' AND instance_id = ?';
|
|
528
|
+
params.push(instanceId);
|
|
529
|
+
}
|
|
530
|
+
const stats = queryGet(sql, params);
|
|
519
531
|
res.json({ success: true, imported: stats.count > 0, count: stats.count, first_import: stats.first_import, last_import: stats.last_import });
|
|
520
532
|
});
|
|
521
533
|
|