@artflo-ai/artflo-openclaw-plugin 0.0.12 → 0.0.13

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/dist/index.js CHANGED
@@ -64,6 +64,18 @@ const plugin = {
64
64
  const sessions = createSessionRegistryService(config);
65
65
  api.registerService(sessions.service);
66
66
  registerArtfloTools(api, { config, workspaceDir: api.rootDir, sessions: sessions.registry });
67
+ api.on('before_prompt_build', async () => {
68
+ return {
69
+ appendSystemContext: [
70
+ `[Artflo Plugin] env=${config.env}, apiKey=未配置`,
71
+ '[MANDATORY] 在调用任何 artflo_* 工具之前,你必须先读取 artflo_canvas Skill(skills/artflo-canvas/SKILL.md)。' +
72
+ '该 Skill 包含路由优先级、API Key 前置检查、操作策略、澄清标准、推荐流程、任务收尾规范等关键规则。' +
73
+ '未读取 Skill 直接调用工具将导致参数错误、流程遗漏和用户体验问题。' +
74
+ '如果你已在当前会话中读取过该 Skill,可以跳过此步骤。',
75
+ 'API Key 未配置,请引导用户通过 artflo_set_api_key 设置。',
76
+ ].join('\n'),
77
+ };
78
+ });
67
79
  return;
68
80
  }
69
81
  // ── 自动获取 appKey / vipAppId / vipGroup ─────────────────────────
@@ -96,12 +108,19 @@ const plugin = {
96
108
  workspaceDir: api.rootDir,
97
109
  sessions: sessions.registry,
98
110
  });
99
- // ── 每次 prompt 构建时注入 Artflo 配置和用户状态 ──────────────
111
+ // ── 每次 prompt 构建时注入 Artflo 配置、用户状态和 Skill 强制提醒 ──
100
112
  api.on('before_prompt_build', async () => {
101
113
  const masked = config.apiKey
102
114
  ? `****${config.apiKey.slice(-4)}`
103
115
  : '未配置';
104
- const lines = [`[Artflo Plugin] env=${config.env}, apiKey=${masked}, tz=${config.timeZone}, country=${config.countryCode}`];
116
+ const lines = [
117
+ `[Artflo Plugin] env=${config.env}, apiKey=${masked}, tz=${config.timeZone}, country=${config.countryCode}`,
118
+ ];
119
+ // ── Skill 强制读取提醒 ──
120
+ lines.push('[MANDATORY] 在调用任何 artflo_* 工具之前,你必须先读取 artflo_canvas Skill(skills/artflo-canvas/SKILL.md)。' +
121
+ '该 Skill 包含路由优先级、API Key 前置检查、操作策略、澄清标准、推荐流程、任务收尾规范等关键规则。' +
122
+ '未读取 Skill 直接调用工具将导致参数错误、流程遗漏和用户体验问题。' +
123
+ '如果你已在当前会话中读取过该 Skill,可以跳过此步骤。');
105
124
  if (!config.apiKey) {
106
125
  lines.push('API Key 未配置,请引导用户通过 artflo_set_api_key 设置。');
107
126
  }
@@ -114,7 +133,7 @@ const plugin = {
114
133
  lines.push('API Key 已配置,用户状态获取失败。');
115
134
  }
116
135
  }
117
- return { appendSystemContext: lines.join(' | ') };
136
+ return { appendSystemContext: lines.join('\n') };
118
137
  });
119
138
  },
120
139
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artflo-ai/artflo-openclaw-plugin",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin that connects directly to Artflo canvas WebSocket runtime.",
6
6
  "keywords": [
@@ -40,7 +40,7 @@ metadata:
40
40
 
41
41
  > 你还没有配置 Artflo API Key,需要先设置才能使用画布功能。
42
42
  >
43
- > 请登录 [artflo.ai](https://artflo.ai),在设置页面获取 API Key,然后直接发给我,我帮你配置好。
43
+ > 请登录 artflo.ai ,在设置页面获取 API Key,然后直接发给我,我帮你配置好。
44
44
 
45
45
  3. 当用户发来 API Key 后,调用 `artflo_set_api_key` 工具保存到配置中。
46
46
  4. 保存成功后,gateway 会自动重新加载配置。**告诉用户配置已保存,需要等待约 10 秒让 gateway 重载完成,然后开始新会话(/new)再继续操作。** 不要在当前会话中立即调用其他 Artflo 工具,因为 gateway 重载期间旧的 config(没有 API Key)仍在内存中。
@@ -49,8 +49,8 @@ metadata:
49
49
 
50
50
  - 优先采用先规划、后执行的工作流,而不是临时拼接低层级修改步骤。
51
51
  - 在创建或扩展多节点工作流之前,先判断用户需求是否已经足够明确,能否安全规划。
52
- - 如果缺少关键创意输入,先提出澄清问题,此时不要调用 `artflo_canvas_execute_plan`。
53
- - 只有在用户补全缺失信息,或者明确允许你做合理假设之后,才组织结构化 plan 并调用 `artflo_canvas_execute_plan`。
52
+ - 澄清遵循两级标准(见下方「澄清标准」),只有必须确认的字段缺失时才提问,可以合理假设的字段直接用默认值。
53
+ - 只有在用户补全必须确认的字段,或者明确允许你做合理假设之后,才组织结构化 plan 并调用 `artflo_canvas_execute_plan`。
54
54
  - 低层级工具只用于定向检查、修复、删除、重跑或调试。
55
55
  - 不要用 `artflo_canvas_change_elements` 从零手工拼一个多节点工作流。
56
56
  - 规划时不要臆造底层画布数字节点类型。应使用 plan 中的节点类型,例如 `input`、`refine`、`process`、`selector`、`batch`、`crop`。
@@ -71,30 +71,102 @@ metadata:
71
71
  - 支持的时长(仅视频模型)
72
72
  - 当插件布局引擎可用时,不要手工编造节点坐标。
73
73
 
74
+ ## 澄清标准
75
+
76
+ 将用户输入中可能缺失的信息分为两级:
77
+
78
+ ### 必须确认(缺失会导致生成结果方向性错误)
79
+
80
+ | 字段 | 为什么必须问 | 示例 |
81
+ |------|-------------|------|
82
+ | 目标用途 | 影响比例、分辨率和模型选择(海报 vs 头像 vs 视频 vs Logo 差异巨大) | 「这是用来做海报还是社交头像?」 |
83
+ | 是否有参考图 | 决定 tool_type 选 1(文生图)还是 2(图生图) | 「你有想参考的图片吗?有的话发给我」 |
84
+
85
+ ### 可以合理假设(不需要主动询问,直接用默认值)
86
+
87
+ | 字段 | 默认值 | 说明 |
88
+ |------|--------|------|
89
+ | 比例 | 1:1 | 除非用途暗示特定比例(如海报→竖版、壁纸→16:9) |
90
+ | 分辨率 | 2K | 通用默认 |
91
+ | 风格 | 从 prompt 推断 | 用户描述中通常隐含风格倾向 |
92
+ | 模型 | 可用模型中的默认模型 | 除非用户指定或用途有明确最优选择 |
93
+ | 生成数量 | 1 | 除非用户说「多个」「几种风格」等 |
94
+
95
+ > 原则:宁可用合理默认值快速出图让用户看到结果再调整,也不要连问三个问题把用户问烦。
96
+
74
97
  ## 默认编辑规则
75
98
 
99
+ - 画布节点的所有业务参数(prompt、tool_type、current_model、ratio、resolution、status、medias 等)都嵌套在 `data` 对象内部。使用 `artflo_canvas_change_elements` 修改节点时,变更的字段必须放在 `data` 里,不能放在顶层或 `properties` 里。详见 `references/node-schema.md` 的「画布元素数据模型」章节。
76
100
  - 除非用户明确要求修改现有节点,否则优先通过新增下游分支来扩展现有图。
77
101
  - 除非用户明确要求,否则不要删除已有节点。
78
102
  - 保持图结构清晰可读;优先依赖插件提供的自动布局,而不是手工摆放。
79
103
  - 创建工作流时,优先使用完整 graph plan 配合 `artflo_canvas_execute_plan`,而不是低层级工具链。
80
- - 如果主题、风格、约束、输出格式、目标模型或下游用途这些需求仍未明确,不要开始执行。
81
- - 将需求收集和工作流执行视为两个阶段: 先澄清,再规划,最后执行。
104
+ - 如果「澄清标准」中的必须确认字段仍未明确,不要开始执行。可以合理假设的字段直接用默认值。
105
+ - 将需求收集和工作流执行视为两个阶段:先按澄清标准判断是否需要提问,再规划,最后执行。
82
106
  - **节点 ID 规范**: 不要自行编造节点 ID。通过 `artflo_canvas_execute_plan` 创建的节点由执行器自动分配 UUID。使用低层级工具操作已有节点时,必须先通过 `artflo_canvas_find_nodes` 或 `artflo_canvas_get_state` 获取真实的节点 ID,不要猜测或拼接。
83
107
  - **节点参数规范**: 生成的节点参数必须严格符合 `references/node-schema.json` 中定义的字段和类型。模型名称必须使用 `artflo_canvas_get_config` 返回的 `model_key`(如 `Praline_2`、`ToffeeV1-Lite`),不要使用显示名称(如 `Nano Banana 2`)或自行编造的模型名。ratio 和 resolution 必须在该模型的 `supportedRatios` 和 `supportedResolutions` 范围内。
84
108
 
85
109
  ## 推荐流程
86
110
 
87
- 1. 检查是否有可用的 canvas id。如果没有,调用 `artflo_canvas_get_last` 获取上次使用的画布,没有的话调用 `artflo_canvas_create` 创建新画布,并将返回的 URL 分享给用户。
88
- 2. 调用 `artflo_canvas_connection_status` 检查连接状态。
89
- 3. 如果未连接,使用目标 canvas id 调用 `artflo_canvas_connect`。
90
- 4. **调用 `artflo_canvas_get_config` 获取可用模型列表、订阅状态和 Prompt Refine 分类。** 或者调用 `artflo_canvas_list_models` 获取更详细的模型信息(含分辨率价格、订阅要求等),适合需要向用户展示模型选择时使用。
91
- 5. 判断当前请求是否已经包含构建高质量工作流所需的足够信息。
92
- 6. 如果缺少关键创意输入,先提出聚焦的补充问题,并在规划或执行前停下来。
93
- 7. 当需求清晰后,参照 `references/planning-guide.md` 把用户请求转换成包含 `nodes` `edges` 的结构化 PlanV2 JSON。
94
- 8. 调用 `artflo_canvas_execute_plan` 执行该 plan。
95
- 9. 如果是检查现状,使用 `artflo_canvas_get_state`、`artflo_canvas_get_node` `artflo_canvas_find_nodes`。
96
- 10. 如果是定向修复,使用 `artflo_canvas_change_elements`、`artflo_canvas_delete_elements`、`artflo_canvas_run_nodes` `artflo_canvas_wait_for_completion`。
97
- 11. 生成成功必须告知用户源文件的资源链接,与生成文件分开发送
111
+ 1. **API Key 前置检查**(硬卡点,必须最先执行):
112
+ - 如果 before_prompt_build 上下文显示 `apiKey=未配置`,**立即停止**,按「API Key 配置检查」区块引导用户设置,不要继续后续步骤。
113
+ - 如果上下文中没有 apiKey 状态信息,调用任意 Artflo 工具时收到 401 错误,也应立即停止并引导用户配置 API Key,不要重试其他工具。
114
+ 2. **快速路径判断**(同一会话内优先走热路径,避免重复调用):
115
+ - **已有 canvasId 且已连接** → 跳到步骤 5
116
+ - **已有 canvasId 但未连接** → 调用 `artflo_canvas_connect`,然后跳到步骤 5。
117
+ - **canvasId 未知** 调用 `artflo_canvas_get_last` 获取上次使用的画布;如果没有,调用 `artflo_canvas_create` 创建新画布,将返回的 URL 分享给用户。然后调用 `artflo_canvas_connect`。
118
+ 3. (热路径跳过此步)如需确认连接状态,调用 `artflo_canvas_connection_status`。
119
+ 4. (热路径跳过此步)如果未连接,使用目标 canvas id 调用 `artflo_canvas_connect`。
120
+ 5. **调用 `artflo_canvas_get_config` 获取可用模型列表、订阅状态和 Prompt Refine 分类。** 同一会话内 `get_config` 结果可复用,无需每次任务重复调用。如需向用户展示模型选择,调用 `artflo_canvas_list_models` 获取更详细信息(含分辨率价格、订阅要求等)。
121
+ 6. 按「澄清标准」判断当前请求是否缺少必须确认的字段。
122
+ 7. 如果必须确认的字段缺失,先提出聚焦的补充问题,并在规划或执行前停下来。可以合理假设的字段直接用默认值。
123
+ 8. 如果用户提供了本地图片或图片 URL 作为参考,先调用 `artflo_upload_file` 上传,拿到 CDN URL 后再开始规划(在 Input 节点的 `data.sources` 中使用该 URL)。
124
+ 9. 当需求清晰后,参照 `references/planning-guide.md` 把用户请求转换成包含 `nodes` 和 `edges` 的结构化 PlanV2 JSON。
125
+ 10. 调用 `artflo_canvas_execute_plan` 执行该 plan。执行器会自动创建节点、连接、运行并等待完成。
126
+ 11. **执行完成后,立即按「任务收尾规范」执行收尾步骤**(find_nodes → get_node 提取资源 URL → get_user_status 查代币 → 向用户报告)。这是必须步骤,不可跳过。
127
+ 12. 如果是检查现状,使用 `artflo_canvas_get_state`、`artflo_canvas_get_node` 或 `artflo_canvas_find_nodes`。
128
+ 13. 如果是定向修复,使用 `artflo_canvas_change_elements`、`artflo_canvas_delete_elements`、`artflo_canvas_run_nodes` 和 `artflo_canvas_wait_for_completion`。
129
+
130
+ ## 任务收尾规范
131
+
132
+ 任务执行完成(`artflo_canvas_wait_for_completion` 返回或节点状态变为终态)后,必须执行以下收尾步骤:
133
+
134
+ ### 获取生成结果(必须)
135
+
136
+ `wait_for_completion` 只返回完成状态,不返回生成的资源。你必须主动获取:
137
+
138
+ 1. 调用 `artflo_canvas_find_nodes` 查找已完成的生成节点(status=2 的 Process/Batch 节点)。
139
+ 2. 对每个完成的生成节点,调用 `artflo_canvas_get_node` 读取完整数据。
140
+ 3. 从节点的 `data` 字段中提取输出资源 URL(图片或视频链接,通常在 `data.medias`、`data.output`、`data.result` 等字段中,具体字段名取决于节点类型)。
141
+ 4. **必须发送资源文件给用户**:
142
+ - 使用当前 Channel 提供的发送图片/视频 tool(如微信的图片/视频发送工具)将生成的资源文件直接发送给用户。
143
+ - 同时在文字消息中贴出资源的纯文本 URL,方便用户复制保存。
144
+ - 如果当前 Channel 没有对应的发送 tool,则退回到贴纯文本 URL。
145
+
146
+ ### 获取代币信息(必须)
147
+
148
+ 生成完成后,调用 `artflo_get_user_status` 获取当前代币余额,告知用户剩余代币数。
149
+
150
+ ### 收尾消息格式
151
+
152
+ 按以下顺序向用户报告:
153
+ 1. 完成状态(成功/部分失败)
154
+ 2. 生成的资源链接(图片/视频 URL,直接贴出)
155
+ 3. 画布地址(纯文本 URL)
156
+ 4. 代币余额
157
+
158
+ ### 异常情况
159
+
160
+ - **部分失败**:说明哪个节点失败、失败原因(从 `error_code` / `error_message` 读取),已成功的节点结果仍然可用,同样提供成功节点的资源链接。
161
+ - **超时**(`wait_for_completion` 超过 120 秒未返回):告知用户任务仍在运行中,附上画布链接让用户自行查看进度,不要自动重试。
162
+ - **不要主动追问下一步**:完成后简洁告知结果即可,不要主动问「还需要什么」「要不要调整」。让用户主导后续操作。
163
+
164
+ ### 格式规范
165
+
166
+ - **禁止使用 markdown 超链接语法**(如 `[文字](url)`)。运行环境(如微信)不支持渲染 markdown 链接,用户会看到原始语法。
167
+ - URL 必须以纯文本形式直接输出,例如:`画布:https://artflo.ai/project/xxx`
168
+ - 资源链接同理,直接贴 URL,不要包裹在 markdown 语法中。
169
+ - **画布 URL 格式**:`{webApiBaseUrl}/project/{canvasId}`。其中 `webApiBaseUrl` 从插件配置获取(release 环境为 `https://artflo.ai`,test 环境为 `https://test.artflo.ai`)。不要使用 `/canvas/` 或其他路径,正确路径是 `/project/`。
98
170
 
99
171
  ## 规划核心要点
100
172
 
@@ -105,7 +177,7 @@ metadata:
105
177
  - **需求详细** → Input + Process(策略 B)
106
178
 
107
179
  ### 模型选择
108
- - 必须先调用 `artflo_canvas_get_config` 获取可用模型
180
+ - 必须先调用 `artflo_canvas_get_config` 获取可用模型(同一会话内结果可复用,无需每次任务重复调用)
109
181
  - 只使用 `available: true` 的模型
110
182
  - 验证 ratio 和 resolution 是否在模型支持范围内
111
183
  - 未订阅用户不能使用 `requiresSubscription: true` 的模型
@@ -117,6 +189,7 @@ metadata:
117
189
  - Batch 节点最多 20 个生成结果
118
190
  - Batch 后面必须跟 Selector
119
191
  - 不要手工指定节点坐标,使用 `dependsOn` 让布局引擎处理
192
+ - `edges` 决定数据流(必须),`dependsOn` 决定节点在画布上的布局位置(可选但推荐写上,不影响执行)
120
193
 
121
194
  ### 输出格式
122
195
  - 纯 JSON,不要 markdown 代码块
@@ -2,6 +2,32 @@
2
2
  "version": "1.0",
3
3
  "referenceType": "artflo_canvas_node_schema",
4
4
  "description": "JSON reference for planning Artflo workflows with artflo_canvas_execute_plan. Keeps the original Markdown guide and adds a machine-readable companion adapted from artflo-agent-v2 schema.json plus plugin-specific planning rules.",
5
+ "elementStructure": {
6
+ "description": "Every canvas element (node or edge) follows this structure. All business fields (prompt, tool_type, current_model, ratio, resolution, status, medias, etc.) are nested inside the 'data' object. They MUST NOT be placed at the top level or in a 'properties' field.",
7
+ "schema": {
8
+ "id": "string — unique element ID (UUID, assigned by system)",
9
+ "type": "number — runtime type code (e.g. 110000=Input, 130000=Process, 130500=Refine)",
10
+ "position": "{ x: number, y: number } — canvas coordinates (optional)",
11
+ "data": "Record<string, unknown> — ALL business fields go here"
12
+ },
13
+ "changeElementsFormat": {
14
+ "description": "When using artflo_canvas_change_elements, each item in the 'changes' array is a Partial<CanvasElement>. It MUST contain 'id' and the fields to update. Business fields MUST be inside 'data'.",
15
+ "correct": {
16
+ "id": "target-node-id",
17
+ "data": { "current_model": "Praline_2", "ratio": "16:9" }
18
+ },
19
+ "wrong_top_level": {
20
+ "id": "target-node-id",
21
+ "current_model": "Praline_2",
22
+ "ratio": "16:9"
23
+ },
24
+ "wrong_properties": {
25
+ "id": "target-node-id",
26
+ "properties": { "current_model": "Praline_2" }
27
+ }
28
+ },
29
+ "fieldsNote": "The 'fields' object in each nodeTypes entry below lists fields that belong INSIDE 'data'. For example, Process.fields.tool_type means data.tool_type, NOT a top-level tool_type."
30
+ },
5
31
  "generalRules": [
6
32
  "Use plan node types such as input, refine, process, selector, and batch.",
7
33
  "Do not invent raw canvas numeric node types in plans.",
@@ -6,6 +6,91 @@ Read `references/node-schema.json` first for the machine-readable version of the
6
6
  Machine-readable companion:
7
7
  - `references/node-schema.json`
8
8
 
9
+ ## 画布元素数据模型(Canvas Element Data Model)
10
+
11
+ 理解这个数据模型是正确使用所有 Artflo 工具的前提。
12
+
13
+ ### 核心结构
14
+
15
+ 画布上的每个元素(节点或边)都是一个 `CanvasElement` 对象,结构如下:
16
+
17
+ ```typescript
18
+ interface CanvasElement {
19
+ id: string; // 节点唯一 ID(UUID,由系统分配)
20
+ type: number; // 运行时类型码(如 110000=Input, 130000=Process)
21
+ position?: { // 画布上的坐标位置
22
+ x: number;
23
+ y: number;
24
+ };
25
+ data: { // ← 所有业务字段都在这里
26
+ prompt?: string;
27
+ tool_type?: number;
28
+ current_model?: string;
29
+ ratio?: string;
30
+ resolution?: string;
31
+ status?: number;
32
+ // ... 其他字段
33
+ };
34
+ }
35
+ ```
36
+
37
+ 关键规则:`prompt`、`tool_type`、`current_model`、`ratio`、`resolution`、`status`、`medias`、`sources` 等所有业务参数都嵌套在 `data` 对象内部,不在顶层。顶层只有 `id`、`type`、`position` 等结构性字段。
38
+
39
+ ### `artflo_canvas_change_elements` 的 changes 格式
40
+
41
+ `changes` 数组中的每个对象是 `Partial<CanvasElement>`——即 `CanvasElement` 的部分更新。必须包含 `id` 来标识要修改的节点,然后只提供需要变更的字段。
42
+
43
+ 正确示例——修改 Process 节点的模型和比例:
44
+ ```json
45
+ {
46
+ "canvasId": "xxx",
47
+ "changes": [
48
+ {
49
+ "id": "目标节点ID",
50
+ "data": {
51
+ "current_model": "Praline_2",
52
+ "ratio": "16:9"
53
+ }
54
+ }
55
+ ]
56
+ }
57
+ ```
58
+
59
+ 错误示例——把业务字段放到顶层或 properties 里:
60
+ ```json
61
+ // ✗ 错误:字段不在 data 里
62
+ {
63
+ "id": "目标节点ID",
64
+ "current_model": "Praline_2",
65
+ "ratio": "16:9"
66
+ }
67
+
68
+ // ✗ 错误:使用了不存在的 properties 字段
69
+ {
70
+ "id": "目标节点ID",
71
+ "properties": {
72
+ "current_model": "Praline_2"
73
+ }
74
+ }
75
+ ```
76
+
77
+ ### `artflo_canvas_get_node` / `artflo_canvas_get_state` 返回的数据
78
+
79
+ 这些工具返回的节点数据也遵循同样的结构。读取节点信息时,业务字段在 `element.data` 下:
80
+
81
+ ```
82
+ element.data.prompt → 提示词
83
+ element.data.tool_type → 工具类型
84
+ element.data.status → 执行状态(0=空闲, 1=等待, 2=处理中, 3=完成, 400=错误)
85
+ element.data.medias → 生成的媒体资源
86
+ element.data.error_code → 错误码
87
+ element.data.error_message → 错误信息
88
+ ```
89
+
90
+ ### node-schema.json 中 fields 的含义
91
+
92
+ `node-schema.json` 中每个节点类型的 `fields` 对象列出的是 `data` 内部的字段定义。例如 Process 节点的 `fields.tool_type` 表示的是 `data.tool_type`,不是顶层的 `tool_type`。
93
+
9
94
  ## General Rules
10
95
 
11
96
  - Use plan node types such as `input`, `refine`, `process`, `selector`, and `batch`.