@wwkit/harness 1.0.4

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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -0
  3. package/agents/extract.md +38 -0
  4. package/agents/query.md +54 -0
  5. package/agents/revise.md +40 -0
  6. package/package.json +55 -0
  7. package/plugin.js +19 -0
  8. package/readme/development.md +37 -0
  9. package/readme/publish.md +38 -0
  10. package/readme/testing.md +36 -0
  11. package/skills/extract/SKILL.md +100 -0
  12. package/skills/extract/references/build-xpath.js +31 -0
  13. package/skills/extract/references/clean-html.js +91 -0
  14. package/skills/extract/references/detail.md +60 -0
  15. package/skills/extract/references/detail.schema.json5 +49 -0
  16. package/skills/extract/references/extract-detail.js +72 -0
  17. package/skills/extract/references/extract-regex.js +82 -0
  18. package/skills/extract/references/extract-sample.js +49 -0
  19. package/skills/extract/references/format-aliases.json5 +22 -0
  20. package/skills/extract/references/input.schema.json5 +23 -0
  21. package/skills/extract/references/list-rule-gen.md +109 -0
  22. package/skills/extract/references/list.schema.json5 +34 -0
  23. package/skills/extract/references/list_from_html.md +74 -0
  24. package/skills/extract/references/list_from_json.md +52 -0
  25. package/skills/extract/references/list_from_text.md +60 -0
  26. package/skills/extract/references/navi.md +49 -0
  27. package/skills/extract/references/navi.schema.json5 +23 -0
  28. package/skills/extract/references/text.md +46 -0
  29. package/skills/extract/references/text.schema.json5 +22 -0
  30. package/skills/extract/references/to-text.js +21 -0
  31. package/skills/extract/references/validate-schema.js +40 -0
  32. package/skills/revise/SKILL.md +113 -0
  33. package/skills/revise/references/article.md +44 -0
  34. package/skills/revise/references/article.schema.json5 +40 -0
  35. package/skills/revise/references/format-aliases.json5 +22 -0
  36. package/skills/revise/references/gallery.md +43 -0
  37. package/skills/revise/references/gallery.schema.json5 +40 -0
  38. package/skills/revise/references/input.schema.json5 +28 -0
  39. package/skills/revise/references/question.md +41 -0
  40. package/skills/revise/references/question.schema.json5 +31 -0
  41. package/skills/revise/references/status.md +40 -0
  42. package/skills/revise/references/status.schema.json5 +27 -0
  43. package/skills/revise/references/validate-schema.js +40 -0
@@ -0,0 +1,52 @@
1
+ # list_from_json 提取流程
2
+
3
+ 将结构化 JSON 数据(text/href/src)规范化为统一列表格式。
4
+
5
+ ## 输入
6
+
7
+ - `source`:JSON 数组字符串或文件路径,每项含 `{text, href, src}` 三个字段:
8
+ - `text`:容器内纯文本(已去标签,末尾可能带时间如 `09:44` 或日期如 `29日`)
9
+ - `href`:第一个 `<a href>` 链接地址
10
+ - `src`:第一个 `<img src>` 图片地址
11
+ - `url`:页面 URL(可选,相对路径转绝对)
12
+
13
+ ## 输出
14
+
15
+ 符合 `list.schema.json5` 的 JSON 数组:
16
+
17
+ ```json
18
+ [
19
+ {
20
+ "title": "标题",
21
+ "author": "作者",
22
+ "date": "2026-06-12",
23
+ "url": "https://example.com/article/123",
24
+ "thumb": "https://example.com/thumb.jpg"
25
+ }
26
+ ]
27
+ ```
28
+
29
+ 字段:`title`(必填,空则跳过本条)、`author` / `date` / `url` / `thumb`(可选)。
30
+
31
+ ## 步骤
32
+
33
+ ### Step 1 — 理解输入
34
+
35
+ 输入 JSON 数组每项含三个字段:
36
+ - `text`:容器内纯文本(末尾可能带时间如 `09:44` 或日期如 `29日`)
37
+ - `href`:第一个 `<a href>` 链接地址
38
+ - `src`:第一个 `<img src>` 图片地址
39
+
40
+ ### Step 2 — LLM 规范化
41
+
42
+ 1. 从 `text` 末尾提取时间/日期(`HH:MM` → 当天,`NN日` → 当月,跨月则月份-1),从 text 中移除
43
+ 2. 剩余 text 作为 `title`
44
+ 3. `href` 作为 `url` 字段(相对路径基于 `{{ url }}` 转为绝对)
45
+ 4. `src` 作为 `thumb` 字段(同上)
46
+ 5. **去重:基于 `url` 去重,重复的只保留第一条,移除后续相同 url 的条目**
47
+ 6. 保持条目相对顺序不变(去重后)
48
+ 7. 输出必须是 JSON 数组
49
+
50
+ ### Step 3 — 验证
51
+
52
+ 检查每项 title 非空(空时输出 Warning),输出规范后的 JSON 数组(供 extract 技能阶段 4 校验)。
@@ -0,0 +1,60 @@
1
+ # list_from_text 提取流程
2
+
3
+ 从**纯文本**(无 HTML 标签)的重复结构中提取结构化信息,完全由 LLM 完成,不调用任何本地脚本。
4
+
5
+ ## 输入
6
+
7
+ - `source`:纯文本内容(如列表页去除标签后的文本,每条的字段以固定行序或空行分隔)
8
+ - `url`:页面 URL(可选,相对路径转绝对)
9
+
10
+ ## 输出
11
+
12
+ 符合 `list.schema.json5` 的 JSON 数组:
13
+
14
+ ```json
15
+ [
16
+ {
17
+ "title": "标题",
18
+ "author": "作者",
19
+ "date": "2026-06-12",
20
+ "url": "https://example.com/article/123",
21
+ "thumb": "https://example.com/thumb.jpg"
22
+ }
23
+ ]
24
+ ```
25
+
26
+ 字段:`title`(必填,空则跳过本条)、`author` / `date` / `url` / `thumb`(可选,无则留空)。
27
+
28
+ ## 步骤
29
+
30
+ ### Step 1 — 识别重复单元并切块
31
+
32
+ 分析源文本,找出重复出现的条目结构。常见形态:
33
+
34
+ - 每条记录由固定行序构成(如 标题/摘要/作者/日期/阅读量,各占一行,条目间以空行或紧邻分隔)
35
+ - 每条记录由空行分隔的多行块构成
36
+
37
+ 按识别出的边界把源文本切分为若干候选条目块,末尾的导航/分页类文本(如「加载更多」)不属于任何条目,丢弃。
38
+
39
+ ### Step 2 — 字段映射
40
+
41
+ 对每个块,依据语义把内容映射到字段:
42
+
43
+ - `title`:条目标题(必须非空;找不到则跳过该条)
44
+ - `author`:作者(无则留空)
45
+ - `date`:发布时间(无则留空)
46
+ - `thumb`:图片/缩略图地址(无则留空)
47
+ - `url`:链接地址(无则留空)
48
+
49
+ 无法确定归属的行(如摘要、阅读量等不在 schema 内的信息)直接丢弃,不进入输出。
50
+
51
+ ### Step 3 — 规范化
52
+
53
+ - 日期统一格式 `yyyy-mm-dd`(如「今天」→ 当天、「昨天」→ 前一天、`HH:MM` → 当天)
54
+ - `url` / `thumb` 若为相对路径,基于 `{{ url }}` 转为绝对地址
55
+ - **保持条目数量和顺序不变**
56
+ - 输出必须是 JSON 数组(不是对象包裹)
57
+
58
+ ### Step 4 — 验证
59
+
60
+ 检查每项 `title` 非空,输出规范后的 JSON 数组(供 extract 技能阶段 4 校验)。
@@ -0,0 +1,49 @@
1
+ # navi 提取流程
2
+
3
+ 从列表页文本中提取标题并生成 XPath 选择器。LLM 只负责识别条目并输出 title,XPath 由内置脚本根据 title 构造(引号拆分 + XML 转义)。
4
+
5
+ ## 输入
6
+
7
+ - `source`:列表内容。可能是纯文本或 JSON 字符串;若为后者,自行识别并提取正文文本,忽略 url/screenshot 等非文本字段
8
+
9
+ ## 输出
10
+
11
+ 符合 `navi.schema.json5` 的 JSON 数组:
12
+
13
+ ```json
14
+ [
15
+ {"selector": "//text()[contains(.,'标题原文') and not(ancestor::script)]/..", "title": "标题原文"}
16
+ ]
17
+ ```
18
+
19
+ ## 步骤
20
+
21
+ ### Step 1 — 输入处理
22
+
23
+ - 若 `source` 为文件路径则读取内容,否则直接作为输入
24
+ - 若为 JSON 字符串,只提取其中的正文文本字段,忽略 url、screenshot、image 等非文本字段
25
+ - **若 source 中无正文文本**(如仅含 url/screenshot 等元数据),**立即输出 `[]` 并结束**
26
+
27
+ ### Step 2 — LLM 提取标题
28
+
29
+ 分析文本换行结构,识别列表条目,仅输出 title 数组:
30
+
31
+ - 提取标题文本,忽略作者、日期、阅读量等附属信息
32
+ - 忽略空白行、分隔线、页码、"加载更多"等非条目内容
33
+ - 输出标题的**完整原始文本**,不做任何改写(包括引号)
34
+ - 按文本出现顺序输出
35
+ - 即使只有 1 个条目也正常输出,不要因缺少重复结构而输出 `[]`
36
+
37
+ ```json
38
+ [{"title": "新闻标题一"}, {"title": "新闻标题二"}]
39
+ ```
40
+
41
+ ### Step 3 — 构造 XPath
42
+
43
+ 用 `write` 工具将 Step 2 的 title 数组写入临时文件,再 stdin 重定向给脚本转为最终输出(引号拆分 + XML 转义):
44
+
45
+ ```bash
46
+ node '<技能目录>/references/build-xpath.js' < <临时 title 文件>
47
+ ```
48
+
49
+ 输出:`{selector, title}` 数组,供 extract 技能阶段 4 校验。
@@ -0,0 +1,23 @@
1
+ {
2
+ // 省略 $schema 字段,避免 bash -c "" 中 $ 展开问题
3
+ "title": "导航 XPath 提取格式",
4
+ "description": "导航 XPath(navi)输出校验 schema(数组)",
5
+ "type": "array",
6
+ "items": {
7
+ "type": "object",
8
+ "properties": {
9
+ "selector": {
10
+ "type": "string",
11
+ "minLength": 1,
12
+ "description": "XPath 选择器,非空"
13
+ },
14
+ "title": {
15
+ "type": "string",
16
+ "minLength": 1,
17
+ "description": "标题原文,非空"
18
+ }
19
+ },
20
+ "required": ["selector", "title"],
21
+ "additionalProperties": false
22
+ }
23
+ }
@@ -0,0 +1,46 @@
1
+ # text 提取流程
2
+
3
+ 将 HTML 转换为纯文本,不做任何结构化提取。移除所有标签、解码实体、归一空白。
4
+
5
+ ## 输入
6
+
7
+ - `source`:网页 HTML 源码
8
+ - `url`:页面 URL(透传至输出)
9
+
10
+ ## 输出
11
+
12
+ 符合 `text.schema.json5` 的 JSON 数组(仅含 1 项):
13
+
14
+ ```json
15
+ [
16
+ {
17
+ "url": "https://example.com/page",
18
+ "content": "纯文本内容,已去标签、解码实体、归一空白"
19
+ }
20
+ ]
21
+ ```
22
+
23
+ 字段:`url`(可选,直接用输入 `{{ url }}`)、`content`(必填,纯文本内容)。
24
+
25
+ ## 步骤
26
+
27
+ ### Step 1 — HTML 转纯文本
28
+
29
+ 用 `write` 工具将 HTML 写入临时文件,再用 stdin 重定向交给 Node.js 去除所有 HTML 标签、解码实体、归一空白:
30
+
31
+ ```bash
32
+ node '<技能目录>/references/to-text.js' < <临时 HTML 文件>
33
+ ```
34
+
35
+ ### Step 2 — 组装输出
36
+
37
+ 将纯文本结果组装为 JSON 数组:
38
+
39
+ ```json
40
+ [
41
+ {
42
+ "url": "{{ url }}",
43
+ "content": "<上一步输出的纯文本>"
44
+ }
45
+ ]
46
+ ```
@@ -0,0 +1,22 @@
1
+ {
2
+ // 省略 $schema 字段,避免 bash -c "" 中 $ 展开问题
3
+ "title": "纯文本提取格式",
4
+ "description": "HTML 转纯文本(text)输出校验 schema(数组,仅 1 项)",
5
+ "type": "array",
6
+ "items": {
7
+ "type": "object",
8
+ "properties": {
9
+ "url": {
10
+ "type": "string",
11
+ "description": "页面 URL,可选"
12
+ },
13
+ "content": {
14
+ "type": "string",
15
+ "minLength": 1,
16
+ "description": "纯文本内容,非空"
17
+ }
18
+ },
19
+ "required": ["content"],
20
+ "additionalProperties": false
21
+ }
22
+ }
@@ -0,0 +1,21 @@
1
+ import { fileURLToPath } from 'url';
2
+
3
+ export function htmlToText(raw) {
4
+ if (!raw) return '';
5
+ let text = raw.replace(/<[^>]+>/g, '');
6
+ text = text.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&').replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&nbsp;/g, ' ');
7
+ text = text.replace(/\s+/g, ' ').trim();
8
+ return text;
9
+ }
10
+
11
+ function main() {
12
+ const chunks = [];
13
+ process.stdin.on('data', chunk => chunks.push(chunk));
14
+ process.stdin.on('end', () => {
15
+ const html = Buffer.concat(chunks).toString();
16
+ process.stdout.write(htmlToText(html));
17
+ });
18
+ }
19
+
20
+ export default htmlToText;
21
+ if (process.argv[1] === fileURLToPath(import.meta.url)) main();
@@ -0,0 +1,40 @@
1
+ import { fileURLToPath } from 'url';
2
+ import { readFileSync } from 'fs';
3
+ import Ajv from 'ajv';
4
+ import json5 from 'json5';
5
+
6
+ const ajv = new Ajv({ strict: false, validateFormats: true });
7
+ ajv.addFormat('uri', /^[a-z][a-z0-9+.-]*:(\/\/)?[^\s]*$/i);
8
+
9
+ export function validateSchema(data, schemaPath) {
10
+ const schemaContent = readFileSync(schemaPath, 'utf-8');
11
+ let schema;
12
+ try {
13
+ schema = JSON.parse(schemaContent);
14
+ } catch {
15
+ schema = json5.parse(schemaContent);
16
+ }
17
+
18
+ const validate = ajv.compile(schema);
19
+ const valid = validate(data);
20
+
21
+ if (valid) return { valid: true, message: 'VALID' };
22
+ return { valid: false, message: 'INVALID: ' + (validate.errors?.[0]?.message || 'unknown error') };
23
+ }
24
+
25
+ function main() {
26
+ const chunks = [];
27
+ process.stdin.on('data', chunk => chunks.push(chunk));
28
+ process.stdin.on('end', () => {
29
+ try {
30
+ const input = JSON.parse(Buffer.concat(chunks).toString());
31
+ const result = validateSchema(input.data, input.schema_path);
32
+ console.log(result.message);
33
+ } catch (e) {
34
+ console.log('INVALID: ' + e.message);
35
+ }
36
+ });
37
+ }
38
+
39
+ export default validateSchema;
40
+ if (process.argv[1] === fileURLToPath(import.meta.url)) main();
@@ -0,0 +1,113 @@
1
+ ---
2
+ name: revise
3
+ description: |
4
+ 基于原始素材进行二次创作,输出符合特定格式的结果(始终为 JSON 数组)。
5
+ 通过 count 参数控制生成条目数量(默认 1),通过 schema 校验确保输出格式正确,校验失败自动重试(最多 3 次)。
6
+ 支持 language 参数指定输出语言(默认中文)。不写入任何文件。
7
+ 适用:内容创作(question/status/gallery/article 等)。
8
+ license: MIT
9
+ metadata:
10
+ workflow: sequential
11
+ ---
12
+
13
+ # revise 技能
14
+
15
+ ## 输入参数
16
+
17
+ 入参来自调用方(agent)已规整后的字段,字段清单(字段/类型/必填/默认值)见 `references/input.schema.json5`。
18
+
19
+ ## 输出
20
+
21
+ 返回符合指定格式的 JSON **数组**,包含 `{{ count }}` 个 item(即使 count=1 也输出数组)。**不写入任何文件**。
22
+
23
+ ## 工作流程
24
+
25
+ ### 阶段 1:输入处理
26
+
27
+ - `{{ source }}`:原始素材。若值是现有文件路径,读取文件内容;否则直接以值作为内容。
28
+ - `{{ format }}`:创作格式,用于定位 `references/` 下的 prompt 和 schema 文件。
29
+ - `{{ count }}`:生成的 item 数量,解析为整数,默认 1。为空、非整数或小于 1 时按 1 处理。
30
+ - `{{ language }}`:输出内容语言,默认 `中文`。为空或仅含空白时按 `中文` 处理。
31
+
32
+ 本技能仅使用 `source`、`format`、`count`、`language` 四个字段。忽略传入的所有其他字段(如 `output` 等),不得读取、写入或据此推断任何行为。
33
+
34
+ 若 `{{ source }}` 为空、null 或仅含空白:直接输出 `[]` 并结束,**禁止**继续执行。
35
+
36
+ 若 `{{ format }}` 为空或对应 prompt 文件不存在:直接输出 `[]` 并结束。
37
+
38
+ ### 阶段 2:加载 Prompt 和 Schema
39
+
40
+ 从技能目录的 `references/` 加载对应格式的文件:
41
+
42
+ - Prompt 文件:`references/{{ format }}.md` — LLM 创作指令
43
+ - Schema 文件:`references/{{ format }}.schema.json5` — 输出校验规则(JSON Schema)
44
+
45
+ 用 `read` 工具读取两个文件内容,并**记录 schema 文件的绝对路径**(阶段 4 校验时需要)。若任一文件不存在,则输出 `[]` 并结束。
46
+
47
+ ### 阶段 3:内容生成
48
+
49
+ 先判断 `{{ source }}` 是否为 JSON 字符串:若是则解析为结构化对象作为素材;否则直接作为文本素材。**禁止用 bash 解析 JSON**,直接依据内容理解处理。
50
+
51
+ 将素材结合 Prompt 文件内容调用 LLM 生成符合格式的结果。**必须生成 `{{ count }}` 个 item,整体输出为 JSON 数组(即使 count=1)。** 内容语言使用 `{{ language }}`(默认中文)。
52
+
53
+ 生成时向 LLM 传入:
54
+ - 原始素材(完整 source,已解析为可读格式)
55
+ - Prompt 文件内容(创作指令)
56
+ - `{{ count }}`(生成 item 数量)
57
+ - `{{ language }}`(输出语言)
58
+ - 输出格式说明和示例
59
+
60
+ ### 阶段 4:Schema 校验
61
+
62
+ 用 `write` 工具将待校验的 JSON 数组写入临时文件,再用 `write` 工具将 `{"data": <JSON 数组>, "schema_path": "<schema 绝对路径>"}` 写入 JSON 输入文件,stdin 重定向交给 Node.js 校验:
63
+
64
+ ```bash
65
+ node '<技能目录>/references/validate-schema.js' < <临时 JSON 输入文件>
66
+ ```
67
+
68
+ - 若校验通过,进入阶段 6
69
+ - 若校验失败,进入阶段 5 进行修复重试(最多 3 次)
70
+
71
+ ### 阶段 5:校验失败时修复重试
72
+
73
+ 当 Schema 校验失败时,将错误信息反馈给 LLM,要求其根据原始素材重新生成。
74
+
75
+ 传入内容:
76
+ - 原始素材(完整 source)
77
+ - Prompt 文件内容
78
+ - 上一轮生成的不合格内容
79
+ - Schema 校验错误详情
80
+
81
+ 重新生成后,再次执行阶段 4 校验。**最多重试 3 次**,超过则将最后一次重试的 schema 校验错误信息及「重试 {N} 次后 schema 校验仍然失败」输出到 stderr 并结束。
82
+
83
+ ### 阶段 6:输出
84
+
85
+ **若校验未通过(重试耗尽):** 将最后一次重试的 schema 校验错误信息及「重试 {N} 次后 schema 校验仍然失败」输出到 stderr 并结束。
86
+
87
+ **若校验通过:** 将最终 JSON **数组**作为结果返回。**禁止写入任何文件**;文件写入由调用方(agent)负责。
88
+
89
+ ## 约束
90
+
91
+ - 只处理已声明字段(source/format/count/language),忽略所有其他传入参数(如 `output`),**禁止**以任何形式使用它们。
92
+ - 本技能不读取、不写入任何输出文件;仅返回 JSON 数组。
93
+ - `{{ source }}` 为空时必须输出 `[]`,**禁止**使用 WebFetch 或其他方式获取外部内容。
94
+ - 忽略参数中除已声明字段之外的所有字段。
95
+ - 内部重试步骤的中间产物禁止写入任何文件。
96
+
97
+ ## references/ 目录结构
98
+
99
+ 每个 format 需要两个文件,schema 定义为**数组**(`minItems: 1`),`items` 描述单个 item 的结构:
100
+
101
+ ```
102
+ references/
103
+ ├── input.schema.json5 # 入参字段清单(纯文档)
104
+ ├── question.md # 社交媒体问题 prompt
105
+ ├── question.schema.json5 # 输出 JSON Schema
106
+ ├── status.md # 社交媒体动态 prompt
107
+ ├── status.schema.json5
108
+ ├── gallery.md # 社交媒体图集 prompt
109
+ ├── gallery.schema.json5
110
+ ├── article.md # 社交媒体图文文章 prompt
111
+ ├── article.schema.json5
112
+ └── ...
113
+ ```
@@ -0,0 +1,44 @@
1
+ # 社交媒体图文文章创作 Prompt
2
+
3
+ ## 任务
4
+
5
+ 根据原始素材提取并创作一篇**适合社交媒体传播的图文文章(article)**。
6
+
7
+ ## 输入
8
+
9
+ - `source`:原始素材(文本或 JSON 字符串)
10
+ - `count`:生成的文章数量(默认 1,输出为数组)
11
+ - 创作格式要求见下方
12
+
13
+ ## 输出格式
14
+
15
+ 输出为 JSON **数组**,每个元素的结构必须严格符合 schema `references/article.schema.json5`(阶段 2 已读取)——字段、类型、必填项、数组数量、title 长度、图片块数量均以 schema 为准。
16
+
17
+ > 字数计算采用 **cn_length** 规则:中文字符算 1,非中文字符(英文/数字/符号)算 0.5,结果向上取整。
18
+
19
+ ## 创作要求
20
+
21
+ 1. **标题要抓人**:有吸引力、有冲突点,读者靠标题决定是否点开
22
+ 2. **正文适合快速阅读**:图文混排,段落短、节奏快,文本块与图片块交替出现,建议文本为主、图片辅助,整体 1-20 行
23
+ 3. **图片按需提取**:从原始素材中提取图片地址作为 `{"type": "image"}` 块,**最多 5 个图片块**;素材无图片时全部用 `{"type": "text"}` 块
24
+ 4. **基于素材创作**:从素材中提炼核心信息,重组为流畅文章,不能凭空编造
25
+
26
+ ## 输出示例
27
+
28
+ ```json
29
+ [
30
+ {
31
+ "title": "三星二季度营业利润暴涨18倍,AI存储成最大赢家",
32
+ "blocks": [
33
+ {"type": "text", "content": "市场对DRAM、NAND的供不应求,助推三星电子迎来史上空前的盈利预期。"},
34
+ {"type": "image", "content": "https://example.com/pic1.jpg"},
35
+ {"type": "text", "content": "花旗研究所报告显示,二季度DRAM均价环比上涨44%,NAND涨幅达53%。"}
36
+ ]
37
+ }
38
+ ]
39
+ ```
40
+
41
+ ## 注意事项
42
+
43
+ - 仅输出 JSON 数组,不要包含任何解释、思考过程或额外文本
44
+ - 输出始终为数组,包含 count 个 item(默认 1),禁止输出单个对象
@@ -0,0 +1,40 @@
1
+ {
2
+ // 省略 $schema 字段,避免 bash -c "" 中 $ 展开问题
3
+ "title": "文章格式",
4
+ "description": "社交媒体图文文章(article)输出校验 schema(数组,至少 1 个 item)",
5
+ "type": "array",
6
+ "minItems": 1,
7
+ "items": {
8
+ "type": "object",
9
+ "properties": {
10
+ "title": {
11
+ "type": "string",
12
+ "description": "文章标题,10-30 字(cn_length),需有吸引力"
13
+ },
14
+ "blocks": {
15
+ "type": "array",
16
+ "description": "正文块列表,1-20 行,图文混排",
17
+ "minItems": 1,
18
+ "maxItems": 20,
19
+ "items": {
20
+ "type": "object",
21
+ "properties": {
22
+ "type": {
23
+ "type": "string",
24
+ "enum": ["text", "image"],
25
+ "description": "块类型:text 文本 / image 图片"
26
+ },
27
+ "content": {
28
+ "type": "string",
29
+ "description": "文本段落内容或图片地址"
30
+ }
31
+ },
32
+ "required": ["type", "content"],
33
+ "additionalProperties": false
34
+ }
35
+ }
36
+ },
37
+ "required": ["title", "blocks"],
38
+ "additionalProperties": false
39
+ }
40
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ // format 别名映射表:供 agent 将用户的自然语言描述翻译为 format 标准值。
3
+ // 用户可能用中文/口语而非英文标识,按以下 terms 命中匹配。
4
+ "aliases": {
5
+ "question": {
6
+ "description": "社交媒体风格问题:尖锐标题 + 简洁描述,激发讨论/互动",
7
+ "terms": ["问题", "提问", "互动话题", "话题", "question"]
8
+ },
9
+ "status": {
10
+ "description": "简短社交动态:微博/朋友圈式的一句话或短文字",
11
+ "terms": ["动态", "微博", "朋友圈", "状态", "一句话", "status"]
12
+ },
13
+ "gallery": {
14
+ "description": "多图图集:以图片为主的多图形式",
15
+ "terms": ["图集", "相册", "多图", "图片合集", "gallery"]
16
+ },
17
+ "article": {
18
+ "description": "图文文章:较长的图文长文",
19
+ "terms": ["文章", "图文", "长文", "推文", "article"]
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,43 @@
1
+ # 社交媒体图集创作 Prompt
2
+
3
+ ## 任务
4
+
5
+ 根据原始素材提取并创作一个**适合社交媒体传播的图集(gallery)**。
6
+
7
+ ## 输入
8
+
9
+ - `source`:原始素材(文本或 JSON 字符串)
10
+ - `count`:生成的图集数量(默认 1,输出为数组)
11
+ - 创作格式要求见下方
12
+
13
+ ## 输出格式
14
+
15
+ 输出为 JSON **数组**,每个元素的结构必须严格符合 schema `references/gallery.schema.json5`(阶段 2 已读取)——字段、类型、必填项、数组数量、title 长度均以 schema 为准。
16
+
17
+ > 字数计算采用 **cn_length** 规则:中文字符算 1,非中文字符(英文/数字/符号)算 0.5,结果向上取整。
18
+
19
+ ## 创作要求
20
+
21
+ 1. **标题要吸引**:点明图集主题,有看点、让人想点开
22
+ 2. **每张图配说明**:title 简要说明图片内容,有助于读者理解
23
+ 3. **图片从素材提取**:从原始素材中提取图片地址,素材中图片不足时可适当精选
24
+ 4. **基于素材创作**:从素材中提炼主题,不能凭空编造
25
+
26
+ ## 输出示例
27
+
28
+ ```json
29
+ [
30
+ {
31
+ "title": "三星电子二季度财报亮点图集",
32
+ "images": [
33
+ {"url": "https://example.com/pic1.jpg", "title": "三星第二季度初步财报发布"},
34
+ {"url": "https://example.com/pic2.jpg", "title": "全球存储芯片市场供需"}
35
+ ]
36
+ }
37
+ ]
38
+ ```
39
+
40
+ ## 注意事项
41
+
42
+ - 仅输出 JSON 数组,不要包含任何解释、思考过程或额外文本
43
+ - 输出始终为数组,包含 count 个 item(默认 1),禁止输出单个对象
@@ -0,0 +1,40 @@
1
+ {
2
+ // 省略 $schema 字段,避免 bash -c "" 中 $ 展开问题
3
+ "title": "图集格式",
4
+ "description": "社交媒体图集(gallery)输出校验 schema(数组,至少 1 个 item)",
5
+ "type": "array",
6
+ "minItems": 1,
7
+ "items": {
8
+ "type": "object",
9
+ "properties": {
10
+ "title": {
11
+ "type": "string",
12
+ "description": "图集标题,10-30 字(cn_length)"
13
+ },
14
+ "images": {
15
+ "type": "array",
16
+ "description": "图片列表,1-50 张",
17
+ "minItems": 1,
18
+ "maxItems": 50,
19
+ "items": {
20
+ "type": "object",
21
+ "properties": {
22
+ "url": {
23
+ "type": "string",
24
+ "format": "uri",
25
+ "description": "图片地址"
26
+ },
27
+ "title": {
28
+ "type": "string",
29
+ "description": "图片标题/简短说明,10-30 字(cn_length)"
30
+ }
31
+ },
32
+ "required": ["url", "title"],
33
+ "additionalProperties": false
34
+ }
35
+ }
36
+ },
37
+ "required": ["title", "images"],
38
+ "additionalProperties": false
39
+ }
40
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ // revise 技能入参字段清单(纯文档用途,供 agent 解析入参时参照,不做运行时校验)。
3
+ "title": "revise 技能入参字段清单",
4
+ "type": "object",
5
+ "properties": {
6
+ "source": {
7
+ "type": "string",
8
+ "description": "原始素材:普通文本或 JSON 字符串,或本地文件路径",
9
+ "required": true
10
+ },
11
+ "format": {
12
+ "type": "string",
13
+ "description": "创作格式。标准值为 question/status/gallery/article 之一",
14
+ "enum": ["question", "status", "gallery", "article"],
15
+ "required": true
16
+ },
17
+ "count": {
18
+ "type": "integer",
19
+ "description": "生成的 item 数量,默认 1",
20
+ "default": 1
21
+ },
22
+ "language": {
23
+ "type": "string",
24
+ "description": "输出内容语言,默认 中文",
25
+ "default": "中文"
26
+ }
27
+ }
28
+ }