aitable-workflow-cli 0.1.23 → 0.1.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.
Files changed (77) hide show
  1. package/README.md +1 -6
  2. package/dist/{chunk-IGB6WDLR.js → chunk-UNPV6DTX.js} +1 -1
  3. package/dist/cli.js +47 -47
  4. package/dist/config-set-FBOQBRSJ.js +13 -0
  5. package/dist/{config-ui-server-CORDAOYI.js → config-ui-server-IUSACAOT.js} +1 -1
  6. package/package.json +3 -3
  7. package/dist/config-set-EGLLIMVJ.js +0 -13
  8. package/templates/support-qa/.env.example +0 -16
  9. package/templates/support-qa/aitable-workflow.config.yml +0 -46
  10. package/templates/support-qa/coding-agents.config.json +0 -18
  11. package/templates/support-qa/lib/__tests__/declarative-matcher.test.ts +0 -240
  12. package/templates/support-qa/lib/__tests__/dingtalk-group-membership.test.ts +0 -144
  13. package/templates/support-qa/lib/__tests__/memory-events.test.ts +0 -90
  14. package/templates/support-qa/lib/__tests__/sandbox-agent.test.ts +0 -382
  15. package/templates/support-qa/lib/__tests__/thread-adapter.test.ts +0 -242
  16. package/templates/support-qa/lib/__tests__/thread-observe-step.test.ts +0 -391
  17. package/templates/support-qa/lib/__tests__/thread-observer-handler.test.ts +0 -274
  18. package/templates/support-qa/lib/action-dispatch.ts +0 -262
  19. package/templates/support-qa/lib/contract.ts +0 -253
  20. package/templates/support-qa/lib/declarative-matcher.ts +0 -398
  21. package/templates/support-qa/lib/dingtalk-group-membership.ts +0 -158
  22. package/templates/support-qa/lib/guards.ts +0 -18
  23. package/templates/support-qa/lib/memory-events.ts +0 -113
  24. package/templates/support-qa/lib/owner-resolver.ts +0 -94
  25. package/templates/support-qa/lib/preflight.ts +0 -294
  26. package/templates/support-qa/lib/profile.ts +0 -51
  27. package/templates/support-qa/lib/sandbox-agent.ts +0 -653
  28. package/templates/support-qa/lib/thread-adapter.ts +0 -281
  29. package/templates/support-qa/lib/thread-digest.ts +0 -144
  30. package/templates/support-qa/npmrc +0 -1
  31. package/templates/support-qa/package.json +0 -27
  32. package/templates/support-qa/profiles/aitable/profile/escalation/contacts.json +0 -37
  33. package/templates/support-qa/profiles/aitable/profile/escalation/owner-map.json +0 -18
  34. package/templates/support-qa/profiles/aitable/profile/fastpath/known-answers.yml +0 -561
  35. package/templates/support-qa/profiles/aitable/profile/profile.yml +0 -219
  36. package/templates/support-qa/profiles/aitable/profile/prompts/kb-editor.md +0 -3
  37. package/templates/support-qa/profiles/aitable/profile/prompts/persona.md +0 -49
  38. package/templates/support-qa/profiles/aitable/profile/prompts/troubleshooter.md +0 -5
  39. package/templates/support-qa/profiles/aitable/profile/troubleshoot/classifiers.yml +0 -36
  40. package/templates/support-qa/profiles/aitable/skills/troubleshooting/SKILL.md +0 -58
  41. package/templates/support-qa/profiles/aitable/skills/troubleshooting/aitable-import-troubleshooter/SKILL.md +0 -485
  42. package/templates/support-qa/profiles/aitable/skills/troubleshooting/aitable-openapi-troubleshooter/SKILL.md +0 -183
  43. package/templates/support-qa/profiles/aitable/skills/troubleshooting/import-openapi-e2e-troubleshooter/SKILL.md +0 -459
  44. package/templates/support-qa/profiles/aitable/skills/troubleshooting/notable-datasource-troubleshooter/SKILL.md +0 -1286
  45. package/templates/support-qa/profiles/aitable/skills/troubleshooting/notable-field-troubleshooter/SKILL.md +0 -673
  46. package/templates/support-qa/profiles/aitable/skills/troubleshooting/spreadsheet-datasync-troubleshooter/SKILL.md +0 -322
  47. package/templates/support-qa/profiles/default/profile/fastpath/known-answers.yml +0 -32
  48. package/templates/support-qa/profiles/default/profile/profile.yml +0 -217
  49. package/templates/support-qa/profiles/default/profile/troubleshoot/classifiers.yml +0 -37
  50. package/templates/support-qa/profiles/default/wiki/support//345/270/270/350/247/201/351/227/256/351/242/230.md +0 -10
  51. package/templates/support-qa/tsconfig.json +0 -16
  52. package/templates/support-qa/vitest.config.ts +0 -9
  53. package/templates/support-qa/workflows/admin-kb-update/recipes/kb-refine.recipe.ts +0 -137
  54. package/templates/support-qa/workflows/admin-kb-update/recipes/kb_sync_handler.recipe.ts +0 -119
  55. package/templates/support-qa/workflows/admin-kb-update/workflow.yml +0 -96
  56. package/templates/support-qa/workflows/config-sync/recipes/config_sync.recipe.ts +0 -668
  57. package/templates/support-qa/workflows/config-sync/recipes/config_sync_handler.recipe.ts +0 -16
  58. package/templates/support-qa/workflows/config-sync/workflow.yml +0 -62
  59. package/templates/support-qa/workflows/daily-review/recipes/daily_review.recipe.ts +0 -602
  60. package/templates/support-qa/workflows/daily-review/recipes/daily_review_handler.recipe.ts +0 -26
  61. package/templates/support-qa/workflows/daily-review/workflow.yml +0 -65
  62. package/templates/support-qa/workflows/group-qa/recipes/answer.recipe.ts +0 -231
  63. package/templates/support-qa/workflows/group-qa/recipes/conversation_handler.recipe.ts +0 -394
  64. package/templates/support-qa/workflows/group-qa/recipes/fastpath.recipe.ts +0 -72
  65. package/templates/support-qa/workflows/group-qa/recipes/on-action.recipe.ts +0 -225
  66. package/templates/support-qa/workflows/group-qa/recipes/reply-to-group.recipe.ts +0 -202
  67. package/templates/support-qa/workflows/group-qa/recipes/troubleshoot.recipe.ts +0 -273
  68. package/templates/support-qa/workflows/group-qa/workflow.yml +0 -268
  69. package/templates/support-qa/workflows/thread-observer/README.md +0 -96
  70. package/templates/support-qa/workflows/thread-observer/recipes/thread_observe.recipe.ts +0 -415
  71. package/templates/support-qa/workflows/thread-observer/recipes/thread_observer_handler.recipe.ts +0 -213
  72. package/templates/support-qa/workflows/thread-observer/workflow.yml +0 -185
  73. package/templates/support-qa/workspaces/daily-review/AGENTS.md +0 -233
  74. package/templates/support-qa/workspaces/kb-editor/AGENTS.md +0 -32
  75. package/templates/support-qa/workspaces/support/AGENTS.md +0 -156
  76. package/templates/support-qa/workspaces/thread-observer/AGENTS.md +0 -156
  77. package/templates/support-qa/workspaces/troubleshooter/AGENTS.md +0 -71
@@ -1,137 +0,0 @@
1
- import { z } from "zod";
2
- import { type RecipeDefinition, type RecipeContext, type RecipeResult } from "aitable-workflow-core";
3
- import { KB_STATUS, resolveCurationTarget, DEFAULT_CURATION_TARGET } from "../../../lib/contract.js";
4
-
5
- /**
6
- * 知识提炼并写入本地知识库(管理员知识更新流的唯一步骤)
7
- *
8
- * 输入来自 kb_sync_handler 建的工单:原问题(question) + 对话上下文(context) + 管理员结论(adminUpdate)。
9
- * 流程:coding agent 依据三者【提炼】出要追加的 Markdown 结论(只输出结论正文,不决定写哪个文件),
10
- * 再由本 recipe 用 file toolkit 确定性追加到固定目标文件(config.kb_file,缺省 FAQ.md,jail 在 base_dir 内),
11
- * ~60s 自动重编生效。kb_file 规则收口在 contract.resolveCurationTarget(与 assemble 定点回写共用,
12
- * 评审 P1):不自动补扩展名、不静默回退,显式非法配置直接 failed。
13
- *
14
- * 不发群消息(本流无 reply 步骤)。提炼规范见执行 workspace 下的 AGENTS.md(CLI 自动读取)。
15
- */
16
-
17
- /** 从 agent 响应中取出要追加的正文:剥离可能的 ``` 代码块围栏,其余原样 */
18
- function extractContent(raw: string): string {
19
- if (!raw) return "";
20
- const s = raw.trim();
21
- const fence = s.match(/```(?:markdown|md)?\s*([\s\S]*?)```/i);
22
- return (fence?.[1] ?? s).trim();
23
- }
24
-
25
- const recipe: RecipeDefinition = {
26
- meta: {
27
- id: "kb_refine",
28
- name: "提炼并写入知识库",
29
- role: "kb-editor",
30
- description: "coding agent 依据问答与管理员结论提炼要追加的结论,file toolkit 写入本地知识库",
31
- version: "1.0.0",
32
- requiresAgent: true,
33
- timeoutMs: 180_000,
34
- config: z.object({
35
- coding: z.object({ engine: z.string().optional() }).optional(),
36
- file: z.object({ base_dir: z.string().optional() }).optional(),
37
- kb_file: z.string().optional().describe(`追加目标 .md 文件(相对 file.base_dir),缺省 ${DEFAULT_CURATION_TARGET}`),
38
- }),
39
- },
40
-
41
- async execute(ctx: RecipeContext): Promise<RecipeResult> {
42
- const { input, toolkit, config, log } = ctx;
43
- const adminUpdate = String(input.adminUpdate ?? "").trim();
44
- const question = String(input.question ?? "").trim();
45
- const context = String(input.context ?? "").trim();
46
- const srcBaseId = String(input.srcBaseId ?? "").trim();
47
- const srcTableId = String(input.srcTableId ?? "").trim();
48
- const srcRecordId = String(input.srcRecordId ?? "").trim();
49
- // 与 assemble 定点回写同源的目标文件规则(评审 P1):显式非法配置是配置错误而非瞬时故障,
50
- // 直接 failed 暴露(不自动修正到另一个文件,避免与 profile/workflow 声明值分家)
51
- const kbTarget = resolveCurationTarget(config.kb_file);
52
- if (kbTarget.error) {
53
- log(`kb_file 配置非法,阻断写入: ${kbTarget.error}`);
54
- return { status: "failed", output: { kb_synced: "失败" }, error: `kb_refine: ${kbTarget.error}`, logs: ["kb_file 配置非法 → failed(请修正 profile/workflow 配置)"] };
55
- }
56
- const kbFile = kbTarget.value;
57
-
58
- if (!adminUpdate) {
59
- // 空更新是数据问题而非瞬时故障,重试无益 → 保持 success 终态留痕
60
- log("管理员更新为空,跳过(本流工单应始终带管理员更新)");
61
- return { status: "success", output: { kb_synced: "失败" }, logs: ["管理员更新为空 → 跳过"] };
62
- }
63
-
64
- const prompt = `请把「管理员的权威结论」提炼成一条规范、可检索的知识库 FAQ 条目,并【只输出要追加到知识库的结论正文】。
65
-
66
- ## 素材
67
- ### 原始问题
68
- ${question || "(未提供)"}
69
- ### 对话上下文
70
- ${context || "(无)"}
71
- ### 管理员结论(权威依据,以此为准)
72
- ${adminUpdate}
73
-
74
- ## 输出要求
75
- - 只输出要追加的 Markdown 结论正文本身(形如 "## 问题\\n\\n答案");简洁、准确、可检索。
76
- - 不要输出目标文件名、不要输出 JSON、不要任何前后缀说明或代码块包裹。
77
- 详细提炼规范见本工作目录下的 AGENTS.md。`;
78
-
79
- // 执行 workspace(含该角色 AGENTS.md)由 coding toolkit 按角色自动准备,recipe 无需关心 workDir。
80
- log(`kb_refine 调 coding agent 提炼: ${(question || adminUpdate).slice(0, 40)}`);
81
- const result = await toolkit.coding.run(prompt);
82
-
83
- // 以下三类失败均返回 status: "failed"(评审 P1):触发引擎按 max_step_failures 重试;
84
- // 重试耗尽后源行仍是「待沉淀」,handler 内存 seen 过期/重启后会重新建单——
85
- // 收敛唯一锚点是成功回写「已沉淀」,知识更新不会因一次失败永久卡死。
86
- if (!result.response) {
87
- log("coding agent 无有效响应,标记失败(可重试)");
88
- return { status: "failed", output: { kb_synced: "失败" }, error: "kb_refine: coding agent 无有效响应", logs: ["agent 无响应 → failed(可重试)"] };
89
- }
90
-
91
- const content = extractContent(result.response);
92
- if (!content) {
93
- log("提炼结果为空,标记失败(可重试)");
94
- return {
95
- status: "failed",
96
- output: { kb_synced: "失败" },
97
- error: "kb_refine: 提炼结果为空",
98
- logs: ["提炼内容为空 → failed(可重试)", `原始: ${result.response.slice(0, 120)}`],
99
- };
100
- }
101
-
102
- try {
103
- await toolkit.file.append({ path: kbFile, content: `\n\n${content}\n` });
104
- } catch (error) {
105
- const msg = error instanceof Error ? error.message : String(error);
106
- log(`写入知识库失败: ${kbFile} — ${msg}`);
107
- return { status: "failed", output: { kb_synced: "失败" }, error: `kb_refine: 写入知识库失败 ${msg}`, logs: ["file.append 失败 → failed(可重试)"] };
108
- }
109
-
110
- const title = content.split("\n").find((l) => l.trim())?.replace(/^#+\s*/, "").slice(0, 40) ?? "";
111
- log(`已追加到知识库: ${kbFile}(${content.length} 字,${title})`);
112
-
113
- // 回写 group-qa 源行「知识沉淀=已沉淀」,使事件源过滤集收敛(不再重复拉取该行)。
114
- // 幂等:仅成功路径回写;失败只 log 不阻断,下轮源行仍为「待沉淀」会自动重试。
115
- if (srcBaseId && srcTableId && srcRecordId) {
116
- try {
117
- await toolkit.table.updateRecordIn(
118
- { baseId: srcBaseId, tableId: srcTableId },
119
- srcRecordId,
120
- { "知识沉淀": KB_STATUS.PERSISTED },
121
- );
122
- log(`已回写源行 ${srcRecordId} 知识沉淀=已沉淀`);
123
- } catch (error) {
124
- const msg = error instanceof Error ? error.message : String(error);
125
- log(`回写源行知识沉淀失败(不阻断,下轮重试): ${srcRecordId} — ${msg}`);
126
- }
127
- }
128
-
129
- return {
130
- status: "success",
131
- output: { kb_synced: "已同步", kb_article: kbFile },
132
- logs: [`已写入 ${kbFile}`, "答疑侧直接读取原文,追加即生效"],
133
- };
134
- },
135
- };
136
-
137
- export default recipe;
@@ -1,119 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { z } from "zod";
3
- import type {
4
- EventHandlerRecipeDefinition,
5
- HandlerInitContext,
6
- HandlerInstance,
7
- } from "aitable-workflow-core";
8
-
9
- /**
10
- * 管理员知识更新 — 事件过滤 + 去重 + 建单(dumb handler,不碰 toolkit)
11
- *
12
- * aitable_record 源监听「群问答表」(filter: 知识沉淀=待沉淀),产出 record_created/record_updated。
13
- * 本 handler 只做三件事:
14
- * 1. 过滤:只处理「管理员更新」列非空的行;
15
- * 2. 去重:按 hash(recordId + 管理员更新内容) 做**进程内存 + TTL** 抑制——
16
- * 只防同进程短窗口内的重复建单(同一行反复触发事件/emit_existing 首轮重放);
17
- * **故意不持久化**:收敛的唯一锚点是 kb_refine 成功后回写源行「知识沉淀=已沉淀」
18
- * (事件源过滤集随之收敛)。若 kb_refine 失败(返回 failed → 引擎按 max_step_failures
19
- * 重试),源行仍是「待沉淀」,进程重启/TTL 过期后 emit_existing 会重放建单,
20
- * 天然构成失败恢复通道——持久 seen 会把失败行永久卡死(评审 P1)。
21
- * 3. 建单:把 消息内容/对话上下文/管理员更新 复制进【本流】的知识更新表,
22
- * 交给 kb_refine 步骤用 coding agent 提炼后写库。
23
- */
24
-
25
- const SEEN_TTL_MS = 30 * 60 * 1000; // 覆盖 refine 执行 + 引擎重试窗口即可,无需更长
26
- const SEEN_CAPACITY = 1000;
27
-
28
- /** 把 aitable cell 值稳健地转成纯文本(兼容 string / number / {text}/{value} / 数组) */
29
- function cellToString(value: unknown): string {
30
- if (value == null) return "";
31
- if (typeof value === "string") return value;
32
- if (typeof value === "number" || typeof value === "boolean") return String(value);
33
- if (Array.isArray(value)) return value.map(cellToString).filter(Boolean).join("\n");
34
- if (typeof value === "object") {
35
- const rec = value as Record<string, unknown>;
36
- if (typeof rec.text === "string") return rec.text;
37
- if (typeof rec.value === "string") return rec.value;
38
- if (typeof rec.name === "string") return rec.name;
39
- }
40
- return "";
41
- }
42
-
43
- const recipe: EventHandlerRecipeDefinition = {
44
- meta: {
45
- id: "kb_sync_handler",
46
- name: "管理员知识更新过滤器",
47
- description: "过滤群问答表「管理员更新」列非空的行,短窗口去重后建知识更新工单(交给 kb_refine 提炼写库)",
48
- config: z.object({
49
- admin_field: z.string().optional().describe("管理员填结论的列名,默认「管理员更新」"),
50
- question_field: z.string().optional().describe("原问题列名,默认「消息内容」"),
51
- context_field: z.string().optional().describe("对话上下文列名,默认「对话上下文」"),
52
- }),
53
- },
54
-
55
- create(ctx: HandlerInitContext): HandlerInstance {
56
- const adminField = String(ctx.config.admin_field ?? "管理员更新");
57
- const questionField = String(ctx.config.question_field ?? "消息内容");
58
- const contextField = String(ctx.config.context_field ?? "对话上下文");
59
- // 进程内存去重(key → 首见时间);重启即清空(见文件头注释:这是特性不是缺陷)
60
- const seen = new Map<string, number>();
61
-
62
- function seenRecently(key: string): boolean {
63
- const now = Date.now();
64
- const at = seen.get(key);
65
- if (at !== undefined && now - at <= SEEN_TTL_MS) return true;
66
- seen.set(key, now);
67
- // 容量/TTL 裁剪
68
- if (seen.size > SEEN_CAPACITY) {
69
- for (const [k, ts] of seen) {
70
- if (now - ts > SEEN_TTL_MS) seen.delete(k);
71
- if (seen.size <= SEEN_CAPACITY) break;
72
- }
73
- }
74
- return false;
75
- }
76
-
77
- return {
78
- onEvent(event) {
79
- const cells = (event.payload?.cells ?? {}) as Record<string, unknown>;
80
- const admin = cellToString(cells[adminField]).trim();
81
- if (!admin) return; // 绝大多数群问答字段变更事件在此快速返回
82
-
83
- const recordId = String(event.itemId ?? "");
84
- const key = createHash("sha1").update(`${recordId}\u0000${admin}`).digest("hex");
85
- if (seenRecently(key)) {
86
- ctx.log(`管理员更新短窗口内已建单(seen TTL 命中),跳过: ${recordId}`);
87
- return;
88
- }
89
-
90
- const question = cellToString(cells[questionField]).trim();
91
- const context = cellToString(cells[contextField]).trim();
92
-
93
- // 源行坐标:供 kb_refine 处理完回写 group-qa 源行「知识沉淀=已沉淀」,使拉取集收敛。
94
- const payload = (event.payload ?? {}) as Record<string, unknown>;
95
- const srcBaseId = typeof payload.baseId === "string" ? payload.baseId : "";
96
- const srcTableId = typeof payload.tableId === "string" ? payload.tableId : "";
97
-
98
- ctx.log(`捕获管理员更新(源行 ${recordId}),建知识更新工单`);
99
- ctx.pushEvent({
100
- action: "create_record",
101
- fields: {
102
- "标题": `知识更新: ${(question || admin).slice(0, 20)}`,
103
- "消息内容": question,
104
- "对话上下文": context,
105
- "管理员更新": admin,
106
- "源表BaseId": srcBaseId,
107
- "源表TableId": srcTableId,
108
- "源行RecordId": recordId,
109
- },
110
- });
111
- },
112
- stop() {
113
- seen.clear();
114
- },
115
- };
116
- },
117
- };
118
-
119
- export default recipe;
@@ -1,96 +0,0 @@
1
- meta:
2
- name: "管理员知识更新"
3
- version: "1.0.0"
4
- domain: kb_admin
5
- description: "监听群问答表「知识沉淀=待沉淀」行的「管理员更新」列,coding agent 提炼后写入本地知识库(不发群消息)。知识飞轮三路进料(手工/缺口/学习候选)在此汇合入库"
6
-
7
- # ─── 通知配置 ─────────────────────────────────────
8
- notification:
9
- channel: "none"
10
-
11
- # ─── 数据表(独立于群问答表:本流自己的「知识更新工单表」)─────
12
- # table_id 留空 → setup 自动建表并回写到本文件;不可与 group-qa 同表,
13
- # 否则 group-qa 的 reconcile 会把知识更新工单也当群问答处理。
14
- # ⚠️ 占位:部署前替换为你自己的 base_id
15
- tracker:
16
- label: "管理员知识更新留痕表"
17
- description: "记录知识沉淀内容的表格,提炼后写入本地知识库"
18
- base_id: ""
19
- table_id: ""
20
-
21
- states:
22
- initial: "待处理"
23
- active: [ "处理中" ]
24
- terminal: [ "已完成", "已关闭" ]
25
- blocked: "已阻塞"
26
-
27
- fields:
28
- state: "状态"
29
- title: "标题"
30
- current_step: "当前步骤"
31
- event_log: "事件日志"
32
-
33
- field_definitions:
34
- - name: 消息内容
35
- type: text
36
- - name: 对话上下文
37
- type: text
38
- - name: 管理员更新
39
- type: text
40
- - name: 知识库文章
41
- type: text
42
- - name: 知识库同步
43
- type: singleSelect
44
- options:
45
- - 已同步
46
- - 失败
47
- - name: 源表BaseId
48
- type: text
49
- - name: 源表TableId
50
- type: text
51
- - name: 源行RecordId
52
- type: text
53
-
54
- views:
55
- - id: default_grid
56
- type: Grid
57
- name: 表格
58
- field_order:
59
- - 标题
60
- - 消息内容
61
- - 管理员更新
62
- - 知识库文章
63
- - 知识库同步
64
- - 状态
65
- - 当前步骤
66
- - 事件日志
67
- description: 管理员知识更新 - 处理留痕
68
-
69
- # ─── 事件源:监听群问答表「知识沉淀=待沉淀」行的「管理员更新」列 ─────
70
- event_sources:
71
- - name: 管理员更新监听
72
- type: aitable_record
73
- handler: kb_sync_handler
74
-
75
- # ─── 步骤:唯一一步,coding agent 提炼后写库(无 reply 步骤 → 不发群)─────
76
- steps:
77
- - id: kb_refine
78
- name: "提炼并写入知识库"
79
- recipe: kb-refine
80
- auto: true
81
- input_mapping:
82
- question: "消息内容"
83
- context: "对话上下文"
84
- adminUpdate: "管理员更新"
85
- srcBaseId: "源表BaseId"
86
- srcTableId: "源表TableId"
87
- srcRecordId: "源行RecordId"
88
- output_mapping:
89
- kb_synced: "知识库同步"
90
- kb_article: "知识库文章"
91
-
92
- edges:
93
- - from: __start__
94
- to: kb_refine
95
- - from: kb_refine
96
- to: __end__