@liem-opc/chat-to-article-mcp-ui 0.1.0 → 0.1.1
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 -0
- package/dist/cli.js +107 -4
- package/dist/views/figure.html +306 -306
- package/dist/views/review.html +82 -82
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
| `review_writing_plan` | 文体标签、读者、目的、七条偏好轴、备选行文方案;每项都能批注 | 确认计划 / 让 agent 再想想 / 先不写 | 确认后写 `writing-plan.json` |
|
|
25
25
|
| `review_claims` | 每条主张:采用 / 待定 / 有疑问 / 不要,可改字、批注、补一条;疑似密钥要勾选「已处理」;提示哪些块会因此过期 | 提交决定 / 让 agent 再查 | 调用时把新主张以 candidate 写入 `claims.jsonl`;提交时写入决定和 `materials.json` |
|
|
26
26
|
| `review_outline` | 章节排序、增删、主张和图的分配、块拆分;未覆盖的主张 | 确认大纲 / 让 agent 重排 | 确认后写 `outline.json` 和图位 |
|
|
27
|
+
| `review_variants` | 同一块的 2–4 种笔调并排,标出「按你的偏好」那一版;每版可写喜欢或不喜欢的地方 | 就用这版 / 都不满意,换一组 / 稍后再说 | 调用时不写文件;选定后把那版以 draft 写入 `blocks/<id>.md`,返回 `pick-variant` 命令 |
|
|
27
28
|
| `review_block` | 所见即所得的修订模式:直接改字留痕(插入下划线、删除线),逐处或全部接受/拒绝;选中文字加批注;词表实时检查;前后块只读;与上一版的差异 | 接受这块 / 按批注修改 / 稍后再说 | 调用时以 draft 写入 `blocks/<id>.md`;提交时保存你的修改 |
|
|
28
29
|
| `review_figure` | Mermaid 实时预览、源文件、图注、替代文字 | 接受这张图 / 让 agent 改 / 稍后再说 | 调用时写图源;提交时更新 `figures/manifest.json` |
|
|
29
30
|
| `review_style_candidates` | 每条候选:写进风格 / 再观察 / 不是我的习惯,措辞可改 | 提交 / 稍后再说 | 不写文件,返回 `bump-style` 命令 |
|
package/dist/cli.js
CHANGED
|
@@ -20,6 +20,7 @@ var ACTIONS = [
|
|
|
20
20
|
"review_writing_plan",
|
|
21
21
|
"review_claims",
|
|
22
22
|
"review_outline",
|
|
23
|
+
"review_variants",
|
|
23
24
|
"review_block",
|
|
24
25
|
"review_figure",
|
|
25
26
|
"review_style_candidates"
|
|
@@ -146,6 +147,28 @@ var reviewOutlineResult = z.object({
|
|
|
146
147
|
comments: z.array(z.object({ sectionId: z.string(), text: z.string() })),
|
|
147
148
|
note: z.string().optional()
|
|
148
149
|
});
|
|
150
|
+
var variantDraft = z.object({
|
|
151
|
+
id: z.string().min(1).describe("\u7248\u672C id\uFF0C\u4F8B\u5982 A\u3001B\u3001C"),
|
|
152
|
+
voice: z.string().min(1).describe("\u5185\u7F6E\u7B14\u8C03 id\uFF08cta.py presets \u5217\u51FA\uFF09\u3001profile\uFF08\u6309\u4F5C\u8005\u7684\u504F\u597D\u5199\uFF09\u6216 custom"),
|
|
153
|
+
label: z.string().min(1).describe("\u7ED9\u4F5C\u8005\u770B\u7684\u540D\u5B57\uFF0C\u4F8B\u5982\u300C\u6309\u4F60\u7684\u504F\u597D\u300D\u300C\u8DDF\u540C\u4E8B\u590D\u76D8\u300D"),
|
|
154
|
+
summary: z.string().optional().describe("\u4E00\u53E5\u8BDD\u8BF4\u8FD9\u7248\u548C\u5176\u4ED6\u7248\u5DEE\u5728\u54EA"),
|
|
155
|
+
body: z.string().min(1).describe("\u8FD9\u4E00\u7248\u7684 Markdown \u6B63\u6587")
|
|
156
|
+
});
|
|
157
|
+
var reviewVariantsInput = {
|
|
158
|
+
article: articlePath,
|
|
159
|
+
blockId: z.string().min(1).describe("\u5927\u7EB2\u91CC\u7684\u5757 id\uFF0C\u4F8B\u5982 b001"),
|
|
160
|
+
variants: z.array(variantDraft).min(2).max(4).describe("\u540C\u4E00\u5757\u3001\u540C\u6837\u4E3B\u5F20\u3001\u4E0D\u540C\u7B14\u8C03\u7684\u51E0\u7248\uFF1B\u6709\u504F\u597D\u6750\u6599\u65F6\u5176\u4E2D\u4E00\u7248\u7684 voice \u4E3A profile"),
|
|
161
|
+
claimIds: z.array(z.string()).optional(),
|
|
162
|
+
figureIds: z.array(z.string()).optional(),
|
|
163
|
+
context: z.string().optional().describe("\u4E3A\u4EC0\u4E48\u51FA\u8FD9\u51E0\u7248\uFF0C\u4F8B\u5982\u300C\u8FD8\u6CA1\u9009\u5B9A\u7B14\u8C03\u300D")
|
|
164
|
+
};
|
|
165
|
+
var reviewVariantsArgs = z.object(reviewVariantsInput);
|
|
166
|
+
var reviewVariantsResult = z.object({
|
|
167
|
+
decision: z.enum(["pick", "regenerate", "later"]),
|
|
168
|
+
chosenId: z.string().optional(),
|
|
169
|
+
feedback: z.array(z.object({ variantId: z.string(), text: z.string() })),
|
|
170
|
+
note: z.string().optional()
|
|
171
|
+
});
|
|
149
172
|
var reviewBlockInput = {
|
|
150
173
|
article: articlePath,
|
|
151
174
|
blockId: z.string().min(1).describe("\u5927\u7EB2\u91CC\u7684\u5757 id\uFF0C\u4F8B\u5982 b001"),
|
|
@@ -567,6 +590,9 @@ function pinnedProfile(meta) {
|
|
|
567
590
|
if (!meta || voice.profile.revision === meta.styleRevision) return voice.profile;
|
|
568
591
|
return voice.history.find((h) => h.revision === meta.styleRevision)?.profile ?? voice.profile;
|
|
569
592
|
}
|
|
593
|
+
function articlePreferences(dir) {
|
|
594
|
+
return readJsonl(join7(dir, "preferences.jsonl")).filter((p) => p.status === "active" && p.kind !== "voice").map((p) => ({ id: p.id, text: p.text }));
|
|
595
|
+
}
|
|
570
596
|
function outlineBlockIds(dir) {
|
|
571
597
|
return loadOutline(dir).sections.flatMap((s) => s.blockIds);
|
|
572
598
|
}
|
|
@@ -928,6 +954,74 @@ var reviewOutline = {
|
|
|
928
954
|
);
|
|
929
955
|
}
|
|
930
956
|
};
|
|
957
|
+
var LEARN_HINT = "\u5148\u628A\u4FEE\u8BA2\u548C\u6279\u6CE8\u91CC\u80FD\u63A8\u5E7F\u5230\u522B\u7684\u5757\u7684\u5199\u6CD5\uFF08\u7528\u8BCD\u3001\u53E5\u5F0F\u3001\u8BED\u6C14\u3001\u8282\u594F\u3001\u4EBA\u79F0\u3001\u6BB5\u843D\u5904\u7406\uFF09\u5F52\u7EB3\u6210 0\u20133 \u6761\u504F\u597D\uFF0C\u9010\u6761\u8FD0\u884C learn \u8BB0\u4E0B\uFF0C\u5E76\u7528\u4E00\u53E5\u8BDD\u544A\u8BC9\u7528\u6237\u8BB0\u4E86\u4EC0\u4E48\uFF1B\u53EA\u5BF9\u8FD9\u4E00\u5904\u6210\u7ACB\u7684\u4FEE\u6539\u4E0D\u8BB0\u3002";
|
|
958
|
+
var reviewVariants = {
|
|
959
|
+
kind: "review_variants",
|
|
960
|
+
description: "\u672C\u7BC7\u8FD8\u6CA1\u9009\u5B9A\u7B14\u8C03\u65F6\uFF0C\u628A\u540C\u4E00\u5757\u7684 2\u20134 \u7248\uFF08\u540C\u6837\u7684\u4E3B\u5F20\u3001\u4E0D\u540C\u7B14\u8C03\uFF09\u5E76\u6392\u5D4C\u5165\u5BF9\u8BDD\uFF0C\u8BA9\u7528\u6237\u6311\u4E00\u7248\uFF0C\u5E76\u5BF9\u5404\u7248\u5199\u559C\u6B22\u6216\u4E0D\u559C\u6B22\u7684\u5730\u65B9\u3002\u8C03\u7528\u65F6\u4E0D\u5199\u6587\u4EF6\uFF1B\u7528\u6237\u9009\u5B9A\u540E\uFF0C\u9009\u4E2D\u7684\u6B63\u6587\u4EE5 draft \u5199\u5165 blocks/<id>.md\u3002\u8D77\u8349\u95E8\u7981\u4E0E check-draft \u76F8\u540C\u3002",
|
|
961
|
+
args: reviewVariantsArgs,
|
|
962
|
+
result: reviewVariantsResult,
|
|
963
|
+
prepare(input) {
|
|
964
|
+
const dir = resolveArticle(input.article);
|
|
965
|
+
const meta = requireArticle(dir);
|
|
966
|
+
const gate = checkDraft(dir, input.blockId);
|
|
967
|
+
if (gate) throw new UserFacingError(gate);
|
|
968
|
+
const ids = new Set(input.variants.map((v) => v.id));
|
|
969
|
+
if (ids.size !== input.variants.length) throw new UserFacingError("\u7248\u672C id \u4E0D\u80FD\u91CD\u590D\u3002");
|
|
970
|
+
const section = sectionOfBlock(dir, input.blockId);
|
|
971
|
+
const claims = new Map(loadClaims(dir).map((c) => [c.id, c]));
|
|
972
|
+
const outlineIds = loadOutline(dir).sections.flatMap((s) => s.blockIds);
|
|
973
|
+
const prevId = outlineIds[outlineIds.indexOf(input.blockId) - 1];
|
|
974
|
+
const prev = prevId ? loadBlock(dir, prevId) : null;
|
|
975
|
+
const context = {
|
|
976
|
+
sectionTitle: section?.title ?? null,
|
|
977
|
+
claims: (input.claimIds ?? section?.claimIds ?? []).map((id) => ({
|
|
978
|
+
id,
|
|
979
|
+
text: claims.get(id)?.text ?? "\uFF08\u4E3B\u5F20\u7F3A\u5931\uFF09",
|
|
980
|
+
status: claims.get(id)?.status ?? "missing"
|
|
981
|
+
})),
|
|
982
|
+
prev: prev?.exists ? { id: prev.id, body: prev.body } : null,
|
|
983
|
+
preferences: articlePreferences(dir)
|
|
984
|
+
};
|
|
985
|
+
return { title: `\u9009\u7B14\u8C03\uFF1A${meta.title} \xB7 ${context.sectionTitle ?? ""} \xB7 ${input.blockId}`, article: dir, context };
|
|
986
|
+
},
|
|
987
|
+
submit(input, result) {
|
|
988
|
+
const dir = resolveArticle(input.article);
|
|
989
|
+
const cta = ctaCommand(dir);
|
|
990
|
+
const label = (id) => {
|
|
991
|
+
const v = input.variants.find((x) => x.id === id);
|
|
992
|
+
return v ? `${v.id}\u300C${v.label}\u300D` : id;
|
|
993
|
+
};
|
|
994
|
+
const feedback = result.feedback.filter((f) => f.text.trim()).map((f) => `- ${label(f.variantId)}\uFF1A${f.text.trim()}`);
|
|
995
|
+
if (result.decision === "later") return lines(`\u7528\u6237\u6682\u65F6\u4E0D\u9009 ${input.blockId} \u7684\u7248\u672C\uFF0C\u6CA1\u6709\u5199\u5165\u4EFB\u4F55\u6587\u4EF6\u3002`, note(result.note), ...feedback);
|
|
996
|
+
if (result.decision === "regenerate")
|
|
997
|
+
return lines(
|
|
998
|
+
`\u7528\u6237\u5BF9 ${input.blockId} \u7684\u51E0\u7248\u90FD\u4E0D\u6EE1\u610F\uFF0C\u6CA1\u6709\u5199\u5165\u4EFB\u4F55\u6587\u4EF6\u3002`,
|
|
999
|
+
feedback.length ? "\u7528\u6237\u5BF9\u5404\u7248\u7684\u8BC4\u4EF7\uFF1A" : null,
|
|
1000
|
+
...feedback,
|
|
1001
|
+
note(result.note),
|
|
1002
|
+
`\u628A\u8BC4\u4EF7\u91CC\u80FD\u63A8\u5E7F\u7684\u5199\u6CD5\u7528 learn --source variant \u8BB0\u4E0B\uFF0C\u7136\u540E\u6309\u8BC4\u4EF7\u6362\u4E00\u7EC4\u7248\u672C\uFF0C\u518D\u8C03\u7528 review_variants\u3002`
|
|
1003
|
+
);
|
|
1004
|
+
const chosen = input.variants.find((v) => v.id === result.chosenId);
|
|
1005
|
+
if (!chosen) throw new UserFacingError("\u9009\u5B9A\u65F6\u5FC5\u987B\u7ED9\u51FA chosenId\u3002");
|
|
1006
|
+
writeBlockDraft(dir, input.blockId, chosen.body, {
|
|
1007
|
+
claimIds: input.claimIds,
|
|
1008
|
+
figureIds: input.figureIds,
|
|
1009
|
+
instruction: `\u7528\u6237\u4ECE\u591A\u7248\u4E2D\u9009\u4E86 ${chosen.label}`
|
|
1010
|
+
});
|
|
1011
|
+
const chosenFeedback = result.feedback.find((f) => f.variantId === chosen.id)?.text.trim();
|
|
1012
|
+
const voiceNote = [chosen.voice === "custom" ? chosen.summary ?? chosen.label : null, chosenFeedback, result.note?.trim()].filter(Boolean).join("\uFF1B");
|
|
1013
|
+
return lines(
|
|
1014
|
+
`\u7528\u6237\u9009\u4E86 ${label(chosen.id)}\uFF08\u7B14\u8C03 ${chosen.voice}\uFF09\uFF0C\u6B63\u6587\u5DF2\u4EE5 draft \u5199\u5165 blocks/${input.blockId}.md\u3002`,
|
|
1015
|
+
feedback.length ? "\u7528\u6237\u5BF9\u5404\u7248\u7684\u8BC4\u4EF7\uFF08\u6CA1\u9009\u4E2D\u7684\u7248\u672C\u4E5F\u8BF4\u660E\u4E86\u504F\u597D\uFF09\uFF1A" : null,
|
|
1016
|
+
...feedback,
|
|
1017
|
+
note(result.note),
|
|
1018
|
+
"\u4E0B\u4E00\u6B65\uFF1A",
|
|
1019
|
+
`${cta} pick-variant --article ${q(dir)} --block ${input.blockId} --voice ${chosen.voice}${voiceNote ? ` --note ${q(voiceNote)}` : ""}`,
|
|
1020
|
+
`\u7136\u540E\u628A\u8BC4\u4EF7\u91CC\u80FD\u63A8\u5E7F\u7684\u5199\u6CD5\u9010\u6761\u7528 ${cta} learn --article ${q(dir)} --block ${input.blockId} --source variant --text "\u2026" \u8BB0\u4E0B\uFF0C`,
|
|
1021
|
+
"\u518D\u8C03\u7528 review_block \u628A\u9009\u4E2D\u7684\u8FD9\u7248\u4EA4\u7ED9\u7528\u6237\u7CBE\u4FEE\uFF08body \u7528\u9009\u4E2D\u7684\u6B63\u6587\uFF0C\u6309\u521A\u8BB0\u4E0B\u7684\u504F\u597D\u5148\u8C03\u597D\uFF09\u3002"
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
931
1025
|
function describeChanges(result) {
|
|
932
1026
|
return result.changes.map((c) => {
|
|
933
1027
|
const where = c.context ? `\uFF08${c.context}\uFF09` : "";
|
|
@@ -973,8 +1067,11 @@ var reviewBlock = {
|
|
|
973
1067
|
prev: neighbor(idx - 1),
|
|
974
1068
|
next: neighbor(idx + 1),
|
|
975
1069
|
rules: lexiconRules(dir),
|
|
976
|
-
styleRules:
|
|
977
|
-
|
|
1070
|
+
styleRules: [
|
|
1071
|
+
...articlePreferences(dir).map((p) => ({ id: p.id, text: p.text, strength: "\u672C\u7BC7" })),
|
|
1072
|
+
...(profile?.rules ?? []).filter((r) => r.status === "active").map((r) => ({ id: r.id, text: r.text, strength: r.strength }))
|
|
1073
|
+
],
|
|
1074
|
+
paragraph: null,
|
|
978
1075
|
styleRevision: meta.styleRevision ?? null
|
|
979
1076
|
};
|
|
980
1077
|
return { title: `${meta.title} \xB7 ${context.sectionTitle ?? ""} \xB7 ${input.blockId}`, article: dir, context };
|
|
@@ -1001,6 +1098,7 @@ var reviewBlock = {
|
|
|
1001
1098
|
...comments,
|
|
1002
1099
|
note(result.note),
|
|
1003
1100
|
`\u4E0B\u4E00\u6B65\uFF1A${cta} accept-block --article ${q(dir)} --block ${input.blockId}`,
|
|
1101
|
+
(changes.length || comments.length || result.note?.trim()) && `\u5199\u4E0B\u4E00\u5757\u4E4B\u524D\uFF0C${LEARN_HINT}\u547D\u4EE4\uFF1A${cta} learn --article ${q(dir)} --block ${input.blockId} --source edit --text "\u2026" --evidence "\u6539\u524D \u2192 \u6539\u540E"`,
|
|
1004
1102
|
"\u7136\u540E\u53EA\u628A\u4E0B\u4E00\u5757\u4EA4\u7ED9\u7528\u6237\u770B\u3002"
|
|
1005
1103
|
);
|
|
1006
1104
|
return lines(
|
|
@@ -1010,9 +1108,11 @@ var reviewBlock = {
|
|
|
1010
1108
|
comments.length ? "\u6279\u6CE8\uFF1A" : null,
|
|
1011
1109
|
...comments,
|
|
1012
1110
|
note(result.note),
|
|
1111
|
+
LEARN_HINT,
|
|
1112
|
+
`\u547D\u4EE4\uFF1A${cta} learn --article ${q(dir)} --block ${input.blockId} --source annotation --text "\u2026" --evidence "\u6539\u524D \u2192 \u6539\u540E"`,
|
|
1013
1113
|
"\u5F53\u524D\u6B63\u6587\uFF1A",
|
|
1014
1114
|
result.finalBody.trim(),
|
|
1015
|
-
"\u53EA\u6539\u8FD9\u4E00\u5757\uFF0C\u53EA\u7528\u8FD9\u5757 claimIds \u91CC\u5DF2\u63A5\u53D7\u7684\u4E3B\u5F20\uFF1B\u6539\u5B8C\u518D\u8C03\u7528 review_block\uFF08instruction \u5199\u660E\u6539\u4E86\u4EC0\u4E48\uFF09\u3002"
|
|
1115
|
+
"\u53EA\u6539\u8FD9\u4E00\u5757\uFF0C\u53EA\u7528\u8FD9\u5757 claimIds \u91CC\u5DF2\u63A5\u53D7\u7684\u4E3B\u5F20\uFF1B\u6539\u7684\u65F6\u5019\u4E5F\u7167\u521A\u8BB0\u4E0B\u7684\u504F\u597D\u8C03\u6574\u6574\u5757\uFF0C\u4E0D\u53EA\u6539\u6279\u6CE8\u6307\u5230\u7684\u5B57\u3002\u6539\u5B8C\u518D\u8C03\u7528 review_block\uFF08instruction \u5199\u660E\u6539\u4E86\u4EC0\u4E48\uFF09\u3002"
|
|
1016
1116
|
);
|
|
1017
1117
|
}
|
|
1018
1118
|
};
|
|
@@ -1095,6 +1195,7 @@ var HANDLERS = {
|
|
|
1095
1195
|
review_writing_plan: reviewWritingPlan,
|
|
1096
1196
|
review_claims: reviewClaims,
|
|
1097
1197
|
review_outline: reviewOutline,
|
|
1198
|
+
review_variants: reviewVariants,
|
|
1098
1199
|
review_block: reviewBlock,
|
|
1099
1200
|
review_figure: reviewFigure,
|
|
1100
1201
|
review_style_candidates: reviewStyleCandidates
|
|
@@ -1110,6 +1211,7 @@ var VIEW_OF = {
|
|
|
1110
1211
|
review_writing_plan: "review",
|
|
1111
1212
|
review_claims: "review",
|
|
1112
1213
|
review_outline: "review",
|
|
1214
|
+
review_variants: "review",
|
|
1113
1215
|
review_block: "review",
|
|
1114
1216
|
review_figure: "figure",
|
|
1115
1217
|
review_style_candidates: "review"
|
|
@@ -1119,6 +1221,7 @@ var TITLES = {
|
|
|
1119
1221
|
review_writing_plan: "\u5BA1\u9605\u5199\u4F5C\u8BA1\u5212",
|
|
1120
1222
|
review_claims: "\u5BA1\u9605\u4E3B\u5F20",
|
|
1121
1223
|
review_outline: "\u5BA1\u9605\u5927\u7EB2",
|
|
1224
|
+
review_variants: "\u591A\u7248\u6311\u7B14\u8C03",
|
|
1122
1225
|
review_block: "\u5BA1\u9605\u6B63\u6587\u5757\uFF08\u4FEE\u8BA2\u6A21\u5F0F\uFF09",
|
|
1123
1226
|
review_figure: "\u5BA1\u9605\u56FE",
|
|
1124
1227
|
review_style_candidates: "\u786E\u8BA4\u98CE\u683C\u5019\u9009"
|
|
@@ -1327,7 +1430,7 @@ var SessionManager = class {
|
|
|
1327
1430
|
};
|
|
1328
1431
|
|
|
1329
1432
|
// src/server/cli.ts
|
|
1330
|
-
var VERSION = true ? "0.1.
|
|
1433
|
+
var VERSION = true ? "0.1.1" : "dev";
|
|
1331
1434
|
var HELP = `chat-to-article-mcp-ui \u2014 \u804A\u51FA\u6587\u7AE0\u6765\u7684 MCP Apps \u5BA1\u9605\u754C\u9762
|
|
1332
1435
|
|
|
1333
1436
|
\u4F5C\u4E3A MCP \u670D\u52A1\u5668\u8FD0\u884C\uFF08stdio\uFF09\u3002\u5BA1\u9605\u5DE5\u5177\u4F1A\u5728 agent \u5BF9\u8BDD\u91CC\u5D4C\u5165\u4EA4\u4E92\u754C\u9762\uFF08MCP Apps\uFF0Cui:// \u8D44\u6E90\uFF09\uFF0C
|