@shulex/cxclawctl 0.1.2 → 0.1.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.
- package/README.md +25 -22
- package/capabilities.lock.json +535 -131
- package/dist/cli.js +2203 -127
- package/dist/cli.js.map +1 -1
- package/package.json +20 -6
- package/requirements-cli.txt +0 -2
- package/skills/__lib__/__init__.py +0 -0
- package/skills/__lib__/skill-runtime/bootstrap.py +0 -134
- package/skills/__lib__/solvea-api/__init__.py +0 -0
- package/skills/__lib__/solvea-api/client.py +0 -1944
- package/skills/__lib__/solvea-api/dashboard.py +0 -100
- package/skills/__lib__/solvea-api/solvea_api.py +0 -1341
- package/skills/agent-analytics/SKILL.md +0 -74
- package/skills/agent-analytics/references/chat-report-fields.md +0 -36
- package/skills/agent-analytics/references/report-fields.md +0 -130
- package/skills/agent-analytics/references/transcript.md +0 -110
- package/skills/agent-builder/SKILL.md +0 -42
- package/skills/agent-builder/interfaces/fallback-chatflow.md +0 -47
- package/skills/agent-builder/references/chatflow/graph-spec.md +0 -259
- package/skills/agent-builder/references/chatflow/node-selection.md +0 -89
- package/skills/agent-builder/references/chatflow/nodes/agent.md +0 -350
- package/skills/agent-builder/references/chatflow/nodes/business-track.md +0 -43
- package/skills/agent-builder/references/chatflow/nodes/code.md +0 -157
- package/skills/agent-builder/references/chatflow/nodes/collect-order.md +0 -47
- package/skills/agent-builder/references/chatflow/nodes/finish.md +0 -34
- package/skills/agent-builder/references/chatflow/nodes/human-review.md +0 -60
- package/skills/agent-builder/references/chatflow/nodes/if-else.md +0 -100
- package/skills/agent-builder/references/chatflow/nodes/intent.md +0 -79
- package/skills/agent-builder/references/chatflow/nodes/knowledge-reply.md +0 -43
- package/skills/agent-builder/references/chatflow/nodes/llm.md +0 -117
- package/skills/agent-builder/references/chatflow/nodes/note.md +0 -38
- package/skills/agent-builder/references/chatflow/nodes/question.md +0 -97
- package/skills/agent-builder/references/chatflow/nodes/rag-reply.md +0 -68
- package/skills/agent-builder/references/chatflow/nodes/reply.md +0 -97
- package/skills/agent-builder/references/chatflow/nodes/start.md +0 -35
- package/skills/agent-builder/references/chatflow/nodes/sub-graph.md +0 -48
- package/skills/agent-builder/references/chatflow/nodes/tool.md +0 -138
- package/skills/agent-builder/references/chatflow/nodes/transfer-to-human.md +0 -63
- package/skills/agent-builder/references/chatflow/nodes/variable-assignment.md +0 -52
- package/skills/agent-builder/references/chatflow/nodes/variable-extract.md +0 -50
- package/skills/agent-builder/references/chatflow/nodes/variable-process.md +0 -70
- package/skills/agent-builder/references/chatflow/overview.md +0 -53
- package/skills/agent-builder/references/chatflow/visual-translation.md +0 -64
- package/skills/agent-builder/references/chatflow/workflow.md +0 -134
- package/skills/agent-builder/references/multi-agent/create-update.md +0 -185
- package/skills/agent-builder/references/multi-agent/graph-spec.md +0 -246
- package/skills/agent-builder/references/multi-agent/graph-structure.md +0 -12
- package/skills/agent-builder/references/multi-agent/migrate-to-chatflow.md +0 -13
- package/skills/agent-builder/references/multi-agent/migration/large.md +0 -554
- package/skills/agent-builder/references/multi-agent/migration/principles.md +0 -446
- package/skills/agent-builder/references/multi-agent/migration/small.md +0 -225
- package/skills/agent-builder/references/multi-agent/orchestration.md +0 -11
- package/skills/agent-builder/references/multi-agent/overview.md +0 -48
- package/skills/agent-builder/references/multi-agent/update.md +0 -128
- package/skills/agent-builder/references/multi-agent/workflow.md +0 -87
- package/skills/agent-builder/references/single-agent/overview.md +0 -48
- package/skills/agent-builder/references/single-agent/prompt.md +0 -16
- package/skills/agent-builder/references/single-agent/tools.md +0 -36
- package/skills/agent-builder/references/single-agent/voice.md +0 -46
- package/skills/agent-builder/references/tools/http-tool.md +0 -315
- package/skills/agent-builder/references/tools/mock-tool.md +0 -279
- package/skills/agent-builder/references/tools/overview.md +0 -46
- package/skills/agent-builder/references/tools/tool-config.md +0 -43
- package/skills/agent-builder/references/tools/x-token.md +0 -34
- package/skills/agent-builder/scripts/chatflow/chatflow_builder.py +0 -3458
- package/skills/agent-builder/scripts/chatflow/validate_graph.py +0 -1697
- package/skills/agent-builder/scripts/copy_marketplace_agent.py +0 -61
- package/skills/agent-builder/scripts/multi-agent/legacy_graph_analyzer.py +0 -5974
- package/skills/agent-builder/scripts/multi-agent/replay_compare.py +0 -679
- package/skills/agent-builder/scripts/patch_agent_tools.py +0 -135
- package/skills/agent-builder/scripts/tools/validate_tool_config.py +0 -384
- package/skills/agent-tester/SKILL.md +0 -35
- package/skills/agent-tester/batch-test/overview.md +0 -86
- package/skills/agent-tester/scripts/batch_test_sheet.py +0 -213
- package/skills/agent-tester/single-test/badcase-retest.md +0 -85
- package/skills/agent-tester/single-test/direct-test.md +0 -24
- package/skills/agent-tester/single-test/overview.md +0 -142
- package/skills/delivery/SKILL.md +0 -112
- package/skills/delivery/interfaces/classify.md +0 -38
- package/skills/delivery/interfaces/create-agents.md +0 -89
- package/skills/delivery/interfaces/delivery-test.md +0 -67
- package/skills/delivery/references/flow.md +0 -40
- package/skills/delivery/references/validation.md +0 -15
- package/skills/delivery/scripts/batch_test.py +0 -704
- package/skills/delivery/scripts/classify.py +0 -22
- package/skills/delivery/scripts/create_agents.py +0 -695
- package/skills/delivery/scripts/gen_delivery_report.py +0 -335
- package/skills/delivery/scripts/gen_excel.py +0 -234
- package/skills/delivery/scripts/gen_report.py +0 -208
- package/skills/delivery/scripts/plan.py +0 -163
- package/skills/delivery/scripts/render.py +0 -713
- package/skills/delivery/scripts/render_summary.py +0 -38
- package/skills/delivery/scripts/sample_history_cases.py +0 -109
- package/skills/kb-builder/SKILL.md +0 -80
- package/skills/kb-builder/interfaces/qa-upload.md +0 -55
- package/skills/kb-builder/interfaces/web-kb.md +0 -84
- package/skills/kb-builder/references/directory.md +0 -373
- package/skills/kb-builder/references/export.md +0 -282
- package/skills/kb-builder/references/isolation-keywords.md +0 -113
- package/skills/kb-builder/references/knowledge.md +0 -153
- package/skills/kb-builder/references/product.md +0 -52
- package/skills/kb-builder/references/qa-from-help-center.md +0 -58
- package/skills/kb-builder/references/qa-from-pdf.md +0 -94
- package/skills/kb-builder/references/qa-from-tickets.md +0 -168
- package/skills/kb-builder/references/qa-from-web.md +0 -98
- package/skills/kb-builder/references/qa-quality.md +0 -73
- package/skills/kb-builder/references/reply-template.md +0 -237
- package/skills/kb-builder/references/tag-isolation-migration.md +0 -61
- package/skills/kb-builder/references/tags.md +0 -45
- package/skills/kb-builder/references/upload.md +0 -130
- package/skills/kb-builder/scripts/batch_extract_ticket_qa.py +0 -333
- package/skills/kb-builder/scripts/build_directory_plan.py +0 -144
- package/skills/kb-builder/scripts/crawl_site.py +0 -433
- package/skills/kb-builder/scripts/create_dirs.py +0 -146
- package/skills/kb-builder/scripts/export_knowledge.py +0 -454
- package/skills/kb-builder/scripts/extract_ticket_qa.py +0 -441
- package/skills/kb-builder/scripts/extract_web_qa.py +0 -118
- package/skills/kb-builder/scripts/import_qa.py +0 -219
- package/skills/kb-builder/scripts/import_source_documents.py +0 -143
- package/skills/kb-builder/scripts/import_templates.py +0 -409
- package/skills/poc/SKILL.md +0 -125
- package/skills/poc/assets/default_manual.css +0 -279
- package/skills/poc/assets/notice_escalate.png +0 -0
- package/skills/poc/assets/notice_escalate2.png +0 -0
- package/skills/poc/assets/notice_new_chat.png +0 -0
- package/skills/poc/assets/poc_test_template.html +0 -645
- package/skills/poc/assets/poc_test_template.md +0 -104
- package/skills/poc/assets/step3_preview.png +0 -0
- package/skills/poc/assets/step4_order_note.png +0 -0
- package/skills/poc/interfaces/classify.md +0 -38
- package/skills/poc/interfaces/create-agents.md +0 -108
- package/skills/poc/interfaces/poc-test.md +0 -94
- package/skills/poc/references/flow.md +0 -47
- package/skills/poc/references/kb-directory.md +0 -22
- package/skills/poc/references/validation.md +0 -17
- package/skills/poc/scripts/classify.py +0 -22
- package/skills/poc/scripts/create_agents.py +0 -818
- package/skills/poc/scripts/gen_excel.py +0 -234
- package/skills/poc/scripts/gen_poc_manual.py +0 -249
- package/skills/poc/scripts/gen_report.py +0 -208
- package/skills/poc/scripts/inspect_chatflow.py +0 -209
- package/skills/poc/scripts/plan.py +0 -178
- package/skills/poc/scripts/poc_test.py +0 -495
- package/skills/poc/scripts/render.py +0 -713
- package/skills/poc/scripts/render_summary.py +0 -41
- package/skills/runtime-inspector/SKILL.md +0 -51
- package/skills/runtime-inspector/references/frontend-rendering.md +0 -126
- package/skills/runtime-inspector/references/model.md +0 -59
- package/skills/runtime-inspector/references/sandbox.md +0 -131
- package/skills/runtime-inspector/scripts/model_inspect.py +0 -68
- package/skills/runtime-inspector/scripts/prepare.py +0 -98
- package/skills/runtime-inspector/scripts/process.py +0 -84
- package/skills/runtime-inspector/scripts/read_state.py +0 -32
- package/skills/runtime-inspector/scripts/sandbox_inspect.py +0 -463
- package/skills/runtime-inspector/scripts/test_claude_proxy.py +0 -49
- package/skills/runtime-inspector/scripts/test_openai_proxy.py +0 -41
- package/skills/runtime-inspector/scripts/verify_persistence.py +0 -101
- package/skills/runtime-inspector/scripts/write_test.py +0 -41
- package/skills/setup/SKILL.md +0 -17
- package/skills/shulex-support/SKILL.md +0 -39
- package/skills/shulex-support/references/badcase-analysis/overview.md +0 -34
- package/skills/shulex-support/references/badcase-analysis/text/conversation-record.md +0 -105
- package/skills/shulex-support/references/badcase-analysis/text/core-flow.md +0 -89
- package/skills/shulex-support/references/badcase-analysis/text/log-query-rules.md +0 -36
- package/skills/shulex-support/references/badcase-analysis/text/m1-entry.md +0 -53
- package/skills/shulex-support/references/badcase-analysis/text/m10-chatflow-service.md +0 -259
- package/skills/shulex-support/references/badcase-analysis/text/m11-algorithm-service.md +0 -148
- package/skills/shulex-support/references/badcase-analysis/text/m12-quality-inspection.md +0 -57
- package/skills/shulex-support/references/badcase-analysis/text/m2-intent.md +0 -120
- package/skills/shulex-support/references/badcase-analysis/text/m3-strategy.md +0 -126
- package/skills/shulex-support/references/badcase-analysis/text/m4-aifield.md +0 -121
- package/skills/shulex-support/references/badcase-analysis/text/m5-agent.md +0 -208
- package/skills/shulex-support/references/badcase-analysis/text/m6-tool.md +0 -115
- package/skills/shulex-support/references/badcase-analysis/text/m7-reply.md +0 -72
- package/skills/shulex-support/references/badcase-analysis/text/m8-error.md +0 -92
- package/skills/shulex-support/references/badcase-analysis/text/m9-knowledge-search.md +0 -147
- package/skills/shulex-support/references/badcase-analysis/text/sls-query.md +0 -283
- package/skills/shulex-support/references/badcase-analysis/voice/core-flow.md +0 -77
- package/skills/shulex-support/references/badcase-analysis/voice/dependencies.md +0 -19
- package/skills/shulex-support/references/badcase-analysis/voice/platform-api.md +0 -23
- package/skills/shulex-support/references/badcase-analysis/voice/sls-playbook.md +0 -31
- package/skills/shulex-support/references/product-docs.md +0 -70
- package/skills/shulex-support/references/tickets.md +0 -184
- package/skills/shulex-support/scripts/support.py +0 -427
- package/skills/solvea-desk/SKILL.md +0 -39
- package/skills/solvea-desk/references/report/fields.md +0 -82
- package/skills/solvea-desk/references/report/report-design.md +0 -200
- package/skills/solvea-desk/references/report/report-template.html +0 -44
- package/skills/solvea-desk/references/report/report.css +0 -517
- package/skills/solvea-desk/references/report/workflow.md +0 -464
- package/skills/solvea-desk/references/tickets/query.md +0 -103
- package/skills/solvea-desk/references/tickets/tags.md +0 -83
- package/skills/solvea-desk/scripts/report/fetch_sources.py +0 -580
- package/skills/solvea-desk/scripts/report/render_report.py +0 -763
- package/skills/solvea-desk/scripts/tickets/desk_api.py +0 -73
- package/skills/solvea-desk/scripts/tickets/fetch_tickets.py +0 -403
- package/skills/solvea-desk/scripts/tickets/ticket_tags.py +0 -305
- package/skills/solvea-kit/SKILL.md +0 -84
- package/skills/solvea-kit/references/agent.md +0 -145
- package/skills/solvea-kit/references/chat.md +0 -244
- package/skills/solvea-kit/references/intent.md +0 -69
- package/skills/solvea-kit/references/plugin.md +0 -53
- package/skills/solvea-kit/references/quality-inspection.md +0 -75
- package/skills/solvea-kit/references/strategy.md +0 -62
- package/skills/solvea-kit/references/tagging.md +0 -231
- package/skills/solvea-kit/references/variables.md +0 -53
- package/skills/solvea-kit/scripts/generate_label_import_file.py +0 -151
- package/skills/solvea-kit/scripts/intent_classify.py +0 -843
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
# Shulex Desk 报表工作流
|
|
2
|
-
|
|
3
|
-
根据用户维度使用历史回复/解决报表事实或当前工单列表快照,支持后端过滤下推、正文分类、趋势、时效、复杂过滤和 XLSX/报表交付。数据来自工单系统,与 Shulex 客服智能体(Agent)运营数据是两套独立产品,不要混用。
|
|
4
|
-
|
|
5
|
-
## 执行入口
|
|
6
|
-
|
|
7
|
-
每次使用本 skill,先按这个入口判断,不要等读到后文才决定:
|
|
8
|
-
|
|
9
|
-
1. 先读 `workspace/state/solvea-desk/latest_task.json`,判断是否复用已有 task。**该文件只在第一次 fetch 后才生成;读不到 / 文件不存在是首次使用的正常情况,不是错误**——此时直接按"没有可复用 task、需要新建 task"处理,继续后面的步骤,不要把它当成工具失败而中断。读到内容时:追问、改口径、补维度、换图表、生成/更新报表、导出明细,且时间窗和数据源范围没变时,复用同一 task;时间窗或数据源范围变了才新建 task。
|
|
10
|
-
复用前还必须确认 `source_type` 一致:报表分析快照是 `ticket_report_snapshot`,原始工单明细快照是 `ticket_list_snapshot`,两者不能互相复用。
|
|
11
|
-
2. 先判断数据源语义:按时间窗内实际回复/解决行为分析时使用 `ticket_report_snapshot`;按工单当前状态、最后来信、当前负责人或正文分析时使用 `ticket_list_snapshot`。不要只根据“报表”“工单”字样选源。
|
|
12
|
-
3. 只有 `ticket_report_snapshot` 必须判断用户是否给了明确时间范围。明确时间范围包括绝对日期、月份/季度、今天/昨天、本周/上周、本月/上月,或“沿用刚才范围”。首轮新 task 且没有明确时间范围时,先面向用户确认时间范围,不要默认本月,不要 fetch。
|
|
13
|
-
4. 报表快照有明确时间范围时,把它换算成具体起止时间,用一句话告知,然后直接 fetch 或复用 task;不要让用户再确认一遍。**单次 fetch 最大 60 天**,超过 60 天要按 ≤60 天拆窗分别 fetch(见「数据源快照」规则),不要一次性拉。当前工单是当前状态快照;后端不支持的时间字段在 `analysis.py` 中按响应字段处理。
|
|
14
|
-
5. 回复必须面向用户说话,不要把内部判断写成旁白。不要说“用户说 3 月”“用户要求查看...”“没有已有 task,需要新建”。应说“我按 2026 年 3 月理解,统计范围是 2026-03-01 00:00:00 至 2026-03-31 23:59:59(北京时间),现在拉取这段数据并分析回复率趋势。”
|
|
15
|
-
6. 只有缺少必要信息、需要用户选择口径或时间范围时才停下来提问;否则继续完成拉取、分析、对话内图表、Markdown 表格和报表生成。除非缺少必要信息、需要用户选择时间范围或口径,否则不要为了生成报表再停下来等确认。
|
|
16
|
-
7. 对用户只说“报表”,不要说“HTML”;内部文件扩展名和脚本参数可以照常使用 `.html`。
|
|
17
|
-
|
|
18
|
-
## 文件索引
|
|
19
|
-
|
|
20
|
-
```text
|
|
21
|
-
/skills/solvea-desk/
|
|
22
|
-
SKILL.md # 主流程:task、拉数、分析、图表、最终回复规则
|
|
23
|
-
scripts/
|
|
24
|
-
report/
|
|
25
|
-
fetch_sources.py # 按时间范围拉取历史报表事实
|
|
26
|
-
render_report.py # 根据结构化分析结果渲染报表
|
|
27
|
-
tickets/
|
|
28
|
-
fetch_tickets.py # 按视图和后端过滤条件拉当前工单快照
|
|
29
|
-
references/
|
|
30
|
-
report/
|
|
31
|
-
fields.md # 历史报表事实字段
|
|
32
|
-
report-design.md # 报表结构和渲染契约
|
|
33
|
-
report.css # 固定样式
|
|
34
|
-
report-template.html # 固定模板
|
|
35
|
-
tickets/
|
|
36
|
-
fields.md # ticket/list 请求参数和响应字段
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
按需读取:分析历史报表事实时读 `references/report/fields.md`;查询当前工单快照时读 `references/tickets/query.md`;生成报表前读 `references/report/report-design.md`;不要把 CSS / 模板复制进 `analysis.py`。
|
|
40
|
-
|
|
41
|
-
本 skill 是“受控快照 + Agent 分析师 + 可复算口径账本”:
|
|
42
|
-
|
|
43
|
-
- **受控部分**:只能通过 skill 脚本调用场景对应的受控分页接口,账号范围 / 项目范围 / 鉴权由工程逻辑处理,Agent 不得直接 curl 工单接口。
|
|
44
|
-
- **数据边界**:Agent 只认受控 fetch 脚本写出的 `datasource.xlsx` 和内部快照元信息;报表字段以 `/skills/solvea-desk/references/report/fields.md` 为准,当前工单字段以 `/skills/solvea-desk/references/tickets/query.md` 为准。
|
|
45
|
-
- **开放部分**:拿到本地快照后,Agent 可按用户需求自写 `analysis.py`,做复杂过滤、换维度、改口径和对比分析。
|
|
46
|
-
- **可信部分**:每个核心数字必须写入 `calculation_notes.json`,用业务语言说明算法、范围和口径。
|
|
47
|
-
- **展示部分**:对话内给核心结论、图表和表格,同时生成或更新报表;对话内图表只能通过 `render_chart` 工具展示;用户可下载交付物只写入 `workspace/outputs/solvea-desk/<task_id>/`。
|
|
48
|
-
|
|
49
|
-
## 任务生命周期
|
|
50
|
-
|
|
51
|
-
一个 task 表示一次已确认数据范围下的快照和围绕它持续迭代的分析产物。报表快照的数据范围是时间窗;当前工单快照的数据范围是当前用户权限、`viewId` 和后端过滤条件。用户几轮都在调整同一批数据、同一类分析时,复用同一个 task;不要每问一句都重新创建目录和拉快照。`task_id` 用 fetch 脚本输出的 ID。
|
|
52
|
-
|
|
53
|
-
```text
|
|
54
|
-
workspace/state/solvea-desk/<task_id>/
|
|
55
|
-
datasource.xlsx # 固定名,本轮数据源快照,多 sheet,来自 fetch 接口;工作文件,不作为下载物
|
|
56
|
-
manifest.json # 固定名,内部快照元信息:时间范围、分页、行数、截断状态、文件清单
|
|
57
|
-
analysis.py # 固定名,本次最终分析脚本,保留用于复现
|
|
58
|
-
report_data.json # 固定名,报表结构化输入,由 analysis.py 写入
|
|
59
|
-
calculation_notes.json # 固定名,核心指标口径账本,最终回复必须参考
|
|
60
|
-
|
|
61
|
-
workspace/outputs/solvea-desk/<task_id>/
|
|
62
|
-
<report_slug>.html # 用户可下载报表;文件名按本轮分析场景命名
|
|
63
|
-
<report_slug>_detail.xlsx # 可选明细导出;和报表 slug 对齐
|
|
64
|
-
|
|
65
|
-
workspace/tmp/solvea-desk/<task_id>/
|
|
66
|
-
raw_page_001.json # 固定模式,接口原始分页响应,仅用于本轮排查 / 重放
|
|
67
|
-
... # 草稿脚本、临时 CSV、图表中间数据等
|
|
68
|
-
|
|
69
|
-
workspace/state/solvea-desk/
|
|
70
|
-
latest_task.json # 固定名,每次 fetch 覆盖,记录最近一次 task_id / 时间窗 / 状态
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
规则:
|
|
74
|
-
|
|
75
|
-
- `state/<task_id>/` 是本轮工作快照和可复算账本,路径带 task_id,每个新 task 不同;不要把它当用户下载物。
|
|
76
|
-
- `outputs/<task_id>/` 只放本轮用户可下载交付物,通常是 `<report_slug>.html` 和可选 `<report_slug>_detail.xlsx`;不要把 `datasource.xlsx` / `manifest.json` / `analysis.py` / `calculation_notes.json` 放进 outputs。
|
|
77
|
-
- `tmp/<task_id>/` 是中间过程,可丢弃;不要把最终报表只放 tmp。
|
|
78
|
-
- `state/latest_task.json` 是跨轮 task 指针,每次新 fetch 覆盖;不要把用户可下载报表放 state。
|
|
79
|
-
- 开始处理前先读 `latest_task.json` 判断是否有可复用 task;该文件由对应 fetch 脚本首次拉数时创建,读不到或不存在就代表还没有任何 task,按新建 task 流程继续,不要当成错误。
|
|
80
|
-
- 同一 task 的判断:`source_type` 相同,用户在追问、改口径、补维度、换图表、生成/更新报表、导出明细,且没有改变时间窗、`viewId`、后端过滤条件或其他数据源范围。
|
|
81
|
-
- 新 task 的判断:`source_type` 改变,用户明确更换时间窗、`viewId`、后端过滤条件或明显不同的数据源范围,或上一次快照标记截断且用户接受缩小范围后重新拉取。
|
|
82
|
-
- 复用 task 时,读取同一 `state_task_dir` 下的 `datasource.xlsx` / `manifest.json`,修改并重跑 `analysis.py`;不要重新调用 fetch。
|
|
83
|
-
- 新建 task 时才调用与 `source_type` 对应的 fetch 脚本拉快照。
|
|
84
|
-
- 报表文件名必须是 ASCII 小写语义化 slug,例如 `weekly_ticket_summary.html`、`assignee_group_weekly.html`、`channel_trend.html`。不要使用固定裸名 `report.html`。
|
|
85
|
-
- 同一 task 只维护一份主报表:首次分析确定 `REPORT_SLUG` 后,后续追问、改口径、补维度、换图表都覆盖同一个 `<report_slug>.html`,让下载入口始终指向这一份报表的最新版。
|
|
86
|
-
- 用户明确更换时间窗或数据源范围导致新 task 时,才重新确定新的 `REPORT_SLUG`。
|
|
87
|
-
- 生成报表前必须读取 `/skills/solvea-desk/references/report/report-design.md`,按其中的结构和 `report_data.json` 契约组织数据。
|
|
88
|
-
- 报表必须通过 `/skills/solvea-desk/scripts/report/render_report.py` 生成;不要在 `analysis.py` 里内联固定 CSS 或大段模板。
|
|
89
|
-
|
|
90
|
-
## 数据源快照
|
|
91
|
-
|
|
92
|
-
Shulex Desk 有两种不能混用的数据源:
|
|
93
|
-
|
|
94
|
-
| 数据源 | `source_type` | 入口 | 适用场景 |
|
|
95
|
-
|---|---|---|---|
|
|
96
|
-
| 历史报表事实 | `ticket_report_snapshot` | `scripts/report/fetch_sources.py` | 时间范围内实际发生的回复/解决行为、实际回复人/解决人、趋势和时效 |
|
|
97
|
-
| 当前工单快照 | `ticket_list_snapshot` | `scripts/tickets/fetch_tickets.py` | 当前负责人、当前状态、最后来信、语言、标题正文、标签和视图内核对 |
|
|
98
|
-
|
|
99
|
-
- 用户问“某段时间实际由谁回复/解决”、回复趋势、解决趋势、实际回复人、实际解决人或后端报表时效时,使用 `scripts/report/fetch_sources.py`。
|
|
100
|
-
- 用户问当前负责人、当前状态、最后来信、语言、标题正文、标签,或明确用 `lastResponseTime` 等当前列表字段筛选时,使用 `scripts/tickets/fetch_tickets.py`。
|
|
101
|
-
- 用户口中的“处理人”含义不清时,根据其他维度判断:与回复/解决动作绑定的是历史事实;与当前队列、状态或最后来信绑定的是当前工单。仍会改变结果时再追问。
|
|
102
|
-
- 同时需要正文分类和实际回复人/报表时效时,分别拉两种快照,以 `ticketNumber` / `ticketId` 关联;必须说明两个接口的时间语义和快照时点,不能用当前 `agent` 替代历史 `responder`。
|
|
103
|
-
- `shulex-support` 的 `list-tickets` 查询的是 Shulex 产品售后工单,不属于 Desk 客服台数据。
|
|
104
|
-
|
|
105
|
-
新建 task 时必须通过 fetch 脚本拉取数据源;复用 task 时不要重新 fetch。报表分析快照按时间范围调用:
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
npx --yes @shulex/cxclawctl@latest script skills/solvea-desk/scripts/report/fetch_sources.py \
|
|
109
|
-
--start "2026-06-01T00:00:00+08:00" \
|
|
110
|
-
--end "2026-06-01T00:00:00+08:00" \
|
|
111
|
-
--timezone Asia/Shanghai \
|
|
112
|
-
--page-size 200 \
|
|
113
|
-
--max-pages 200 \
|
|
114
|
-
--max-rows 200000
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
查询当前用户权限与指定工单视图内的原始工单明细:
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
npx --yes @shulex/cxclawctl@latest script skills/solvea-desk/scripts/tickets/fetch_tickets.py \
|
|
121
|
-
--view-id 1 \
|
|
122
|
-
--page-size 100 \
|
|
123
|
-
--max-pages 120 \
|
|
124
|
-
--max-rows 200000 \
|
|
125
|
-
--sort last_update_time \
|
|
126
|
-
--order DESC
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
`fetch_tickets.py` 调用 `/api_v2/tars/api/ticket/list`,输出固定标记 `source_type=ticket_list_snapshot`、`data_scope=current_user`、`snapshot_semantics=current_state`。请求过滤参数和响应字段见 `references/tickets/query.md`。
|
|
130
|
-
|
|
131
|
-
当前工单查询必须遵守:
|
|
132
|
-
|
|
133
|
-
- 把后端已经支持、且值已明确的条件写入 `--filters-json`,例如渠道、负责人 ID、状态、店铺、标签、工单号;不要先拉全量再做这些过滤。
|
|
134
|
-
- `--filters-json` 的字段名必须与 `TicketListPageDTO` 一致。不要放入 `page`、`pageSize`、`viewId`、`sort`、`order`;这些使用独立参数。
|
|
135
|
-
- `agentIdList` 只接受 ID。用户只给姓名且没有可靠 ID 映射时,不要猜 ID;先使用其他可下推条件缩小数据,再按返回的 `agent` 精确过滤,并在口径中说明它是当前负责人。
|
|
136
|
-
- `ticket/list` 不支持的筛选维度不要伪装成请求参数;拉取后在 `analysis.py` 中按响应字段过滤,并在口径中说明。
|
|
137
|
-
- 脚本持续分页直到接口无下一页或命中安全上限;命中安全上限按截断处理。
|
|
138
|
-
|
|
139
|
-
例如,按当前负责人 ID 和 eBay 渠道查询:
|
|
140
|
-
|
|
141
|
-
```bash
|
|
142
|
-
npx --yes @shulex/cxclawctl@latest script skills/solvea-desk/scripts/tickets/fetch_tickets.py \
|
|
143
|
-
--view-id 1 \
|
|
144
|
-
--filters-json '{"channelList":["ebay"],"agentIdList":[474501]}' \
|
|
145
|
-
--page-size 100 \
|
|
146
|
-
--max-pages 120
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
以下规则仅适用于 `fetch_sources.py` 的报表分析快照:
|
|
150
|
-
|
|
151
|
-
规则:
|
|
152
|
-
|
|
153
|
-
- Agent 只调用场景对应的受控 fetch 脚本,不要直接调用工单接口。
|
|
154
|
-
- 数据源只支持按自然日拉取,start 和 end 都包含。查询 2026-07-10 至 2026-07-16,应传 `--start "2026-07-10T00:00:00+08:00" --end "2026-07-16T00:00:00+08:00"`。
|
|
155
|
-
- 所有时间统一按北京时间 `Asia/Shanghai` 解释,`start` 和 `end` 必须对齐北京时间 00:00:00。脚本发给 Tars 的是北京时间本地无 offset 时间,不转 UTC,也不支持其他业务时区。
|
|
156
|
-
- 默认不传 `timeRangeType`,由 Tars 使用默认的 `report_activity_date`,按回复日期或解决日期筛选。
|
|
157
|
-
- 只有用户明确要求按工单创建时间维度筛选时,才增加 `--time-range-type created_at`。Kit 对 `created_at` 同样只开放北京时间自然日,不允许用户指定时分秒。
|
|
158
|
-
- 不要拆成半天或小时窗口。接口会丢弃时分秒,只保留日期,因此同一天内继续缩小时段不会减少查询范围。超时降级只能按完整自然日拆窗。
|
|
159
|
-
- page-size 最大值为 200,推荐固定使用 `--page-size 200`。不要传 500、1000 等更大值;脚本会直接拒绝,Tars 服务端也只会按 200 处理。
|
|
160
|
-
- **数据源单次最大时间范围 60 天**(硬上限)。用户要求的范围超过 60 天时,不要一次性 fetch——接口会直接报错(5xx)。必须按 ≤60 天拆成多个时间窗分别 fetch,或先和用户确认收窄范围;分段拉取后合并分析时,在 `calculation_notes.json` 和最终回复里说明数据是分窗拼接的。
|
|
161
|
-
- 字段说明固定维护在 `/skills/solvea-desk/references/report/fields.md`;`fetch_sources.py` 不生成 `schema.md`。
|
|
162
|
-
- 原始接口通常落为 `data` sheet;如果接口临时返回多个 list dataset,脚本仍会分别落为 sheet,但分析时优先使用 `data` sheet。
|
|
163
|
-
- 用户 / Agent 传入的时间统一按北京时间 `Asia/Shanghai` 解释;如果时间字符串自带 `Z` / 其他 offset,则先转换到北京时间,再校验是否为自然日边界。
|
|
164
|
-
- 内部快照元信息会记录用户业务时间窗口、实际拉取窗口、分页、行数和截断状态。
|
|
165
|
-
- fetch 脚本返回的 `task_id`、`state_task_dir` / `output_task_dir` / `tmp_task_dir` 是后续读写路径来源。读取快照用 `state_task_dir`,写用户下载物用 `output_task_dir`,写草稿用 `tmp_task_dir`。
|
|
166
|
-
- 如果脚本返回 `truncated=true` 或退出码 `3`,说明命中分页 / 行数上限;必须提示用户缩小时间范围或降低分析粒度,不能把结果说成全量精确。
|
|
167
|
-
- 只按时间拉快照,因此首响、解决时长、解决率等生命周期指标可能受窗口边界影响;有风险时必须在 `calculation_notes.json` 和最终回复里说明。
|
|
168
|
-
|
|
169
|
-
## 字段说明
|
|
170
|
-
|
|
171
|
-
`datasource.xlsx` 默认读取 `data` sheet。根据 source type 读取 `/skills/solvea-desk/references/report/fields.md` 或 `/skills/solvea-desk/references/tickets/query.md` 确认字段含义。
|
|
172
|
-
|
|
173
|
-
## 分析脚本
|
|
174
|
-
|
|
175
|
-
Agent 读取 `manifest.json` 和 `datasource.xlsx` 后,自写最终脚本:
|
|
176
|
-
|
|
177
|
-
```text
|
|
178
|
-
workspace/state/solvea-desk/<task_id>/analysis.py
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
分析脚本必须使用下面的路径模板,不要在 Python 代码里硬编码 `/workspace/...`:
|
|
182
|
-
|
|
183
|
-
```python
|
|
184
|
-
import os
|
|
185
|
-
from pathlib import Path
|
|
186
|
-
|
|
187
|
-
WORKSPACE_DIR = Path(os.environ["WORKSPACE_DIR"])
|
|
188
|
-
TASK_ID = "<对应 fetch 脚本返回的 task_id>"
|
|
189
|
-
STATE_TASK_DIR = WORKSPACE_DIR / "state" / "solvea-desk" / TASK_ID
|
|
190
|
-
OUTPUT_TASK_DIR = WORKSPACE_DIR / "outputs" / "solvea-desk" / TASK_ID
|
|
191
|
-
TMP_TASK_DIR = WORKSPACE_DIR / "tmp" / "solvea-desk" / TASK_ID
|
|
192
|
-
|
|
193
|
-
OUTPUT_TASK_DIR.mkdir(parents=True, exist_ok=True)
|
|
194
|
-
TMP_TASK_DIR.mkdir(parents=True, exist_ok=True)
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
`analysis.py` 构造 `report_data.json` 时必须先定义下面这些 helper,再用 helper 组装数据,减少结构写错:
|
|
198
|
-
|
|
199
|
-
```python
|
|
200
|
-
REPORT_SLUG = "<semantic_slug>"
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
def kpi(label, value, basis):
|
|
204
|
-
return {"label": label, "value": str(value), "basis": basis}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
def col(key, label, numeric=False):
|
|
208
|
-
item = {"key": key, "label": label}
|
|
209
|
-
if numeric:
|
|
210
|
-
item["numeric"] = True
|
|
211
|
-
return item
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
def section(title, columns, rows, chart=None, description="", note=""):
|
|
215
|
-
return {
|
|
216
|
-
"title": title,
|
|
217
|
-
"description": description,
|
|
218
|
-
"columns": columns,
|
|
219
|
-
"rows": rows,
|
|
220
|
-
**({"chart": chart} if chart else {}),
|
|
221
|
-
**({"note": note} if note else {}),
|
|
222
|
-
}
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
要求:
|
|
226
|
-
|
|
227
|
-
- 只读取同一 `STATE_TASK_DIR` 下的 `datasource.xlsx` / `manifest.json`。
|
|
228
|
-
- 字段含义只参考对应 source type 的字段文档,不要要求或生成 `schema.md`。
|
|
229
|
-
- 用 pandas / openpyxl 处理 XLSX。
|
|
230
|
-
- 不调用外部接口,不访问当前授权范围之外的数据。
|
|
231
|
-
- 必须输出 `STATE_TASK_DIR/calculation_notes.json` 和 `STATE_TASK_DIR/report_data.json`。
|
|
232
|
-
- `analysis.py` 里显式定义 `REPORT_SLUG = "<semantic_slug>"`,并写入 `report_data.json.report_slug`;同一报表迭代复用同一个 slug,新场景换新 slug。
|
|
233
|
-
- `report_data.json` 必须按 `references/report/report-design.md` 契约写顶层 `kpis` 和 `sections`;不要把 `overview`、`personal_performance`、`daily_trend`、`status_distribution` 这类分析中间结果直接当作 renderer 输入。
|
|
234
|
-
- columns 必须是对象数组,也就是 `sections[].columns` 每列至少包含 `key` 和 `label`,例如 `col("date", "日期")`;不要写成字符串数组。
|
|
235
|
-
- 有图表的 section 仍然必须提供同一份 `rows`;报表默认先展示表格,并提供表格 / 图表切换。报表静态图支持 `line`、`bar`、`pie`、`scatter`,与 `render_chart` 工具支持类型一致。
|
|
236
|
-
- 报表图表配置只写小型结构:`bar` / `line` / `scatter` 用 `{"chartType": "...", "xKey": "...", "yKey": "...", "label": "..."}`;`pie` 用 `{"chartType": "pie", "nameKey": "...", "valueKey": "...", "label": "..."}`。不要写 ECharts option、`x`、`series` 或图表模板。
|
|
237
|
-
- `analysis.py` 只负责计算和写结构化数据,不要拼接固定模板/CSS。
|
|
238
|
-
- 每次运行 `analysis.py` 写完 `report_data.json` 后,必须立刻执行 `render_report.py --validate-only` 校验结构;校验失败时修改并重跑 `analysis.py`,不要在生成报表阶段临时重写 `report_data.json`。
|
|
239
|
-
- 生成或更新报表时调用:
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
npx --yes @shulex/cxclawctl@latest script skills/solvea-desk/scripts/report/render_report.py \
|
|
243
|
-
--task-id "<task_id>" \
|
|
244
|
-
--report-slug "<semantic_slug>"
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
- 校验命令:
|
|
248
|
-
|
|
249
|
-
```bash
|
|
250
|
-
npx --yes @shulex/cxclawctl@latest script skills/solvea-desk/scripts/report/render_report.py \
|
|
251
|
-
--task-id "<task_id>" \
|
|
252
|
-
--report-slug "<semantic_slug>" \
|
|
253
|
-
--validate-only
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
- renderer 默认读取 `STATE_TASK_DIR/report_data.json` 和 `STATE_TASK_DIR/calculation_notes.json`,输出 `OUTPUT_TASK_DIR/<report_slug>.html`。生成报表阶段只允许调用 `render_report.py`;如果发现 `report_data.json` 不符合契约,回到 `analysis.py` 修改并重跑 `analysis.py`,不要用一次性脚本临时改 `report_data.json`。
|
|
257
|
-
- 用户要求明细或脚本判断需要明细时,输出 `OUTPUT_TASK_DIR/<report_slug>_detail.xlsx`。
|
|
258
|
-
- 临时草稿、调试 CSV、图表中间数据写 `TMP_TASK_DIR`。
|
|
259
|
-
- 无法判断口径时,在 `calculation_notes.json` 里写明假设或限制,不要假装精确。
|
|
260
|
-
|
|
261
|
-
轻量查询流程:
|
|
262
|
-
|
|
263
|
-
- 用户说“看看本周工单”“看一下今天工单”“本月情况”这类轻量业务问题时,也必须完成:拉快照或复用 task、写/更新分析脚本、写 `calculation_notes.json`、写/更新 `report_data.json`、调用至少一次 `render_chart`、生成或更新报表,最终正文给核心数字说明和 Markdown 表格。
|
|
264
|
-
- 轻量查询默认输出 3-5 个核心数字,例如工单总量、每日趋势、渠道分布、状态分布、AI 回复相关指标;具体字段以对应 source type 的字段文档为准,字段缺失就说明不能算。
|
|
265
|
-
- 图表优先给每日趋势 + 渠道 / 状态分布,放在一次 `render_chart` 调用的 `charts` 数组中;不要只生成下载文件后结束。
|
|
266
|
-
|
|
267
|
-
报表生成规则:
|
|
268
|
-
|
|
269
|
-
- 用户要求业务指标、趋势、对比、可视化、明细或报表时,默认生成或更新报表。
|
|
270
|
-
- 只要时间范围、数据源范围和必要口径足够明确,就直接调用 `render_report.py` 生成或更新报表;不要额外询问“是否生成报表”。
|
|
271
|
-
- 除非缺少必要信息、需要用户选择时间范围或口径,否则不要为了生成报表再停下来等确认。
|
|
272
|
-
- 用户要求换图表、改口径、补维度时,基于同一 task 重算,更新对话内图表/表格,并覆盖同一份主报表。
|
|
273
|
-
- 对用户只说“报表”,不要说“HTML”;正文里可以写实际文件名,但不要解释文件格式技术细节。
|
|
274
|
-
|
|
275
|
-
输出收敛原则:
|
|
276
|
-
|
|
277
|
-
- 按用户问题的复杂度收敛动作和正文。用户只是确认数据结构、字段、行数、某个中间结果时,直接回答确认结果即可,不要强行生成完整报表、图表和交付物。
|
|
278
|
-
- 用户要求业务指标、趋势、对比、可视化、明细或报表时,默认生成或更新报表,并给对话内图表、表格和口径说明。用户只是确认数据结构、字段、行数、某个中间结果时,可以不生成报表。
|
|
279
|
-
|
|
280
|
-
## 业务分析规则
|
|
281
|
-
|
|
282
|
-
MVP 目标是辅助分析,不是权威财务 / 税务 / 对外汇报数据源。
|
|
283
|
-
|
|
284
|
-
优先支持:
|
|
285
|
-
|
|
286
|
-
- **复杂过滤**:渠道、店铺 / 邮箱、客服 / 客服组、品牌、品类、关键词、工作日 / 周末、AI / 人工、满意度评分 / 是否有满意度反馈等;具体字段以对应 source type 的字段文档为准。
|
|
287
|
-
- **换维度**:按渠道、店铺、邮箱、客服、客服组、品牌、品类、日期桶、满意度评分档等分组;字段不存在时说明无法直接计算。
|
|
288
|
-
- **改口径**:用户明确说“不要剔除广告”“只算人工”“分子只算客户回复谢谢”等时,以用户口径优先。
|
|
289
|
-
- **满意度(CSAT)分析**:用户要看满意度时,用 `satisfactionScore` 算平均满意度 / 评分分布 / 好评差评占比,用 `satisfactionFeedback` 摘录差评原声做归因。分母只算有评分的工单,并同时给出满意度回收率(有评分工单 / 工单总数);样本过小或回收率低时必须在口径里说明,不要拿少量评分代表整体。
|
|
290
|
-
|
|
291
|
-
默认规则:
|
|
292
|
-
|
|
293
|
-
- 报表快照的新 task 用户没说时间时先确认时间范围,不要默认本月;同一 task 的追问沿用当前 task 时间范围。原始工单明细快照不要求时间范围。
|
|
294
|
-
- 用户明确说“本周”时,按当前日期所在 ISO 周计算:周一 00:00:00 到当前时刻;如需整周报表可以到周日 23:59:59,但必须在范围里说清楚。不要把周二误写成周一。
|
|
295
|
-
- 用户没说口径,沿用工单报表默认业务口径;如果当前快照字段无法支撑默认口径,必须说明替代口径。
|
|
296
|
-
- 用户要求对比时,优先用等长上一周期;同比 / 环比必须写清楚对比时间窗。
|
|
297
|
-
- 不要凭字段名猜业务含义。字段说明缺失时,可以在最终回复中标为“按字段名推断”,并降低结论确定性。
|
|
298
|
-
|
|
299
|
-
## 口径账本
|
|
300
|
-
|
|
301
|
-
`calculation_notes.json` 是最终回复和报表的可信来源。每个核心指标都应有一条记录:
|
|
302
|
-
|
|
303
|
-
```json
|
|
304
|
-
[
|
|
305
|
-
{
|
|
306
|
-
"metric": "解决率",
|
|
307
|
-
"value": "14.29%",
|
|
308
|
-
"algorithm": "1 个已解决工单 / 共 7 个工单",
|
|
309
|
-
"range": "2026-05-01 至 2026-05-17",
|
|
310
|
-
"filters": ["Email 渠道", "排除 AI 关单"],
|
|
311
|
-
"definition": "已解决 = 在统计范围内标记为已解决的工单",
|
|
312
|
-
"limitations": []
|
|
313
|
-
}
|
|
314
|
-
]
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
输出要求:
|
|
318
|
-
|
|
319
|
-
- 每个核心数字必须能生成下面 4 行说明,全部用业务语言,不出现字段名、SQL、接口内部名。
|
|
320
|
-
- 对话最终回复中的口径说明必须使用 Markdown 列表:每个指标一条一级列表,算法 / 范围 / 口径用二级列表。不要把口径说明写成普通段落里的单换行,因为标准 Markdown 会把段落内单换行折叠成空格。
|
|
321
|
-
|
|
322
|
-
```markdown
|
|
323
|
-
- **解决率:14.29%**
|
|
324
|
-
- 算法:1 个已解决工单 / 共 7 个工单
|
|
325
|
-
- 范围:2026-05-01 至 2026-05-17,剔除广告/通知工单
|
|
326
|
-
- 口径:已解决 = 标记已解决时间在范围内的工单
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
- `calculation_notes.json` 每条记录至少包含 `metric`、`value`、`algorithm`、`range`、`definition`、`filters`、`limitations`。旧字段名 `formula` 不要再新增。
|
|
330
|
-
- 主视图用业务语言,不直接展示 SQL、内部字段名或 `manifest.json` 这类内部文件名;面对用户说“数据范围、数据行数、是否截断、快照生成时间”。
|
|
331
|
-
- 有窗口边界、截断、字段缺失、样本过小等风险时,`limitations` 不能为空。
|
|
332
|
-
- 用户质疑口径时,基于同一快照修改 `analysis.py` 重算;不要只改文案。
|
|
333
|
-
|
|
334
|
-
## 图表展示
|
|
335
|
-
|
|
336
|
-
对话内图表不使用 Markdown code fence,不新增 SSE 自定义事件。需要图表时必须调用内置工具:
|
|
337
|
-
|
|
338
|
-
```json
|
|
339
|
-
{
|
|
340
|
-
"charts": [
|
|
341
|
-
{
|
|
342
|
-
"title": "Ticket Trend",
|
|
343
|
-
"description": "Daily ticket count in the selected range.",
|
|
344
|
-
"chartType": "line",
|
|
345
|
-
"option": {
|
|
346
|
-
"xAxis": {"type": "category", "data": ["Mon", "Tue"]},
|
|
347
|
-
"yAxis": {"type": "value"},
|
|
348
|
-
"series": [{"name": "Tickets", "type": "line", "data": [12, 18]}]
|
|
349
|
-
}
|
|
350
|
-
},
|
|
351
|
-
{
|
|
352
|
-
"title": "Channel Share",
|
|
353
|
-
"description": "Ticket share by source.",
|
|
354
|
-
"chartType": "pie",
|
|
355
|
-
"option": {
|
|
356
|
-
"series": [
|
|
357
|
-
{
|
|
358
|
-
"name": "Source",
|
|
359
|
-
"type": "pie",
|
|
360
|
-
"data": [{"name": "Email", "value": 12}, {"name": "Chat", "value": 18}]
|
|
361
|
-
}
|
|
362
|
-
]
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
]
|
|
366
|
-
}
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
约束:
|
|
370
|
-
|
|
371
|
-
- 调用 `render_chart` 前必须先用一句简洁自然语言说明本次要渲染的统计维度和指标,例如:“下面渲染每日工单量、渠道分布和状态分布三张概览图。”不要突然甩出图表工具调用。
|
|
372
|
-
- `render_chart` 工具内部会校验 ECharts option;校验失败会作为 tool error 返回,必须修正后再继续。
|
|
373
|
-
- 不要在 ECharts option 里使用函数、字符串模板或高风险配置;例如 `tooltip.formatter` 会被工具安全校验拒绝,直接使用 `tooltip.trigger` 即可。
|
|
374
|
-
- 一次调用最多传 4 张图。报表预览有多个图时优先放在同一个 `charts` 数组里,让前端自适应网格展示;超过 4 张时拆成多次 `render_chart` 调用,不要为了“测试上限”故意传 5 张触发失败。
|
|
375
|
-
- 成功结果唯一协议为 `{"type":"chart","version":1,"charts":[...]}`,Agent 不要手写这段 result。
|
|
376
|
-
- 支持图表类型:`line`、`bar`、`pie`、`scatter`。
|
|
377
|
-
- 如果用户指定的图表类型不在 line、bar、pie、scatter 中,例如漏斗图、雷达图、热力图、桑基图、地图,必须先说明当前 `render_chart` 暂不支持该图表类型,并给出最接近的支持方案;不要调用 render_chart 去试错。
|
|
378
|
-
- 图表数据要控制体量,长明细放明细文件或报表,不要塞进工具入参。
|
|
379
|
-
- 不要在普通 assistant 文本里输出 ECharts JSON 或 Markdown code fence。
|
|
380
|
-
|
|
381
|
-
ECharts option 安全兜底:
|
|
382
|
-
|
|
383
|
-
- 只使用纯 JSON option,不使用 JS 函数、回调、URL 或字符串模板。
|
|
384
|
-
- 禁止任何层级的 `formatter` 和 `renderItem`,包括 `tooltip.formatter`、`label.formatter`、`axisLabel.formatter`。这些在 ECharts 中可用,但当前工具会递归拒绝。
|
|
385
|
-
- 需要显示数据值时,用 `series[].label.show = true`,并按图表类型补 `position`:柱状图用 `top`,折线 / 散点用 `top`,饼图用 `outside`。
|
|
386
|
-
- 需要 tooltip 时,只写 `tooltip: {"trigger": "axis"}` 或 `tooltip: {"trigger": "item"}`。
|
|
387
|
-
- 需要图例时,只写 `legend` 的基础布局,例如 `{"top": 0}` 或 `{"left": "left", "orient": "vertical"}`。
|
|
388
|
-
- 需要控制边距时,只写 `grid: {"left": 48, "right": 24, "top": 48, "bottom": 48, "containLabel": true}`。
|
|
389
|
-
- 类目轴标签包含客服组、店铺、渠道等名称时,默认加 `xAxis.axisLabel.interval = 0`,保证所有类目都显示;如果名称较长,再加 `xAxis.axisLabel.rotate = 20` 到 `35`,并把 `grid.bottom` 提到 72 以上。
|
|
390
|
-
- 类目名称特别长时,xAxis 可使用短显示名,完整名称放在图表 `description` 或最终回复表格里;不要让长标签把坐标轴挤没。
|
|
391
|
-
- 字段名、单位、百分比等说明放在图表 `title` / `description` / 轴 `name` / 最终回复口径说明里,不靠 formatter 拼接。
|
|
392
|
-
|
|
393
|
-
优先套用这些安全模板:
|
|
394
|
-
|
|
395
|
-
```json
|
|
396
|
-
{
|
|
397
|
-
"line_or_bar": {
|
|
398
|
-
"tooltip": {"trigger": "axis"},
|
|
399
|
-
"legend": {"top": 0},
|
|
400
|
-
"grid": {"left": 48, "right": 24, "top": 48, "bottom": 72, "containLabel": true},
|
|
401
|
-
"xAxis": {
|
|
402
|
-
"type": "category",
|
|
403
|
-
"data": ["06-01", "06-02"],
|
|
404
|
-
"axisLabel": {"interval": 0, "rotate": 20}
|
|
405
|
-
},
|
|
406
|
-
"yAxis": {"type": "value", "name": "工单数"},
|
|
407
|
-
"series": [
|
|
408
|
-
{
|
|
409
|
-
"name": "工单数",
|
|
410
|
-
"type": "bar",
|
|
411
|
-
"data": [12, 18],
|
|
412
|
-
"label": {"show": true, "position": "top"}
|
|
413
|
-
}
|
|
414
|
-
]
|
|
415
|
-
},
|
|
416
|
-
"pie": {
|
|
417
|
-
"tooltip": {"trigger": "item"},
|
|
418
|
-
"legend": {"left": "left", "orient": "vertical"},
|
|
419
|
-
"series": [
|
|
420
|
-
{
|
|
421
|
-
"name": "渠道",
|
|
422
|
-
"type": "pie",
|
|
423
|
-
"radius": "60%",
|
|
424
|
-
"data": [{"name": "Email", "value": 12}, {"name": "Chat", "value": 18}],
|
|
425
|
-
"label": {"show": true, "position": "outside"}
|
|
426
|
-
}
|
|
427
|
-
]
|
|
428
|
-
},
|
|
429
|
-
"scatter": {
|
|
430
|
-
"tooltip": {"trigger": "item"},
|
|
431
|
-
"grid": {"left": 48, "right": 24, "top": 48, "bottom": 48, "containLabel": true},
|
|
432
|
-
"xAxis": {"type": "value", "name": "响应时长"},
|
|
433
|
-
"yAxis": {"type": "value", "name": "满意度"},
|
|
434
|
-
"series": [
|
|
435
|
-
{
|
|
436
|
-
"name": "样本",
|
|
437
|
-
"type": "scatter",
|
|
438
|
-
"data": [[3, 4.9], [8, 4.7]],
|
|
439
|
-
"label": {"show": true, "position": "top"}
|
|
440
|
-
}
|
|
441
|
-
]
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
## 最终回复格式
|
|
447
|
-
|
|
448
|
-
回复用户时:
|
|
449
|
-
|
|
450
|
-
1. 用普通文本说明核心结论。
|
|
451
|
-
2. 用一句话说明即将渲染的图表维度和指标,然后调用 `render_chart` 工具生成图表块;轻量查询也至少调用一次。
|
|
452
|
-
3. 输出用于核对的 Markdown 表格数据,例如每日趋势、渠道分布、状态分布或用户指定维度;不要只给图不列数据。
|
|
453
|
-
4. 每个核心数字按 Markdown 列表格式输出,内容来自 `calculation_notes.json`。每个指标一条一级列表,算法 / 范围 / 口径用二级列表;不要写成普通段落里的单换行。
|
|
454
|
-
5. 如果本次生成或更新了报表 / 明细文件,再补一个简短“交付物”小节:
|
|
455
|
-
|
|
456
|
-
```markdown
|
|
457
|
-
## 交付物
|
|
458
|
-
|
|
459
|
-
- 报表:`<report_slug>.html`
|
|
460
|
-
- 明细文件:`<report_slug>_detail.xlsx`(如有)
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
前端 finished 事件会展示 outputs 下载链接;正文里只写本轮实际文件名,例如 `assignee_group_weekly.html`,不要写占位名。
|
|
464
|
-
6. 最后用一句话主动引导下一步。已生成报表时,提示可改维度、补明细或换口径;未生成报表时,只说明缺少哪些必要信息。
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# Desk 当前工单列表接口
|
|
2
|
-
|
|
3
|
-
`fetch_tickets.py` 忠实封装 `/api_v2/tars/api/ticket/list`:把受支持的请求条件传给后端,按接口分页拉取,并将响应列表原样写入 `datasource.xlsx` 的 `data` sheet。脚本不增加业务筛选语义,也不修改返回结果集。
|
|
4
|
-
|
|
5
|
-
## 请求参数说明
|
|
6
|
-
|
|
7
|
-
分页和视图参数使用独立 CLI 参数:
|
|
8
|
-
|
|
9
|
-
| CLI 参数 | 后端字段 | 说明 |
|
|
10
|
-
|---|---|---|
|
|
11
|
-
| `--view-id` | `viewId` | 工单视图 ID,默认 `1`;视图条件与当前用户数据权限共同生效 |
|
|
12
|
-
| `--page-size` | `pageSize` | 每页数量,范围 1~100 |
|
|
13
|
-
| `--sort` | `sort` | 排序字段,默认 `last_update_time` |
|
|
14
|
-
| `--order` | `order` | `ASC` 或 `DESC`,默认 `DESC` |
|
|
15
|
-
| `--max-pages` | 不下发 | 客户端安全上限 |
|
|
16
|
-
| `--max-rows` | 不下发 | 客户端安全上限 |
|
|
17
|
-
|
|
18
|
-
业务过滤条件通过 `--filters-json` 或 `--filters-file` 传入 JSON 对象。字段名与 Tars `TicketListPageDTO` 一致,并在 Elasticsearch 查询阶段执行。
|
|
19
|
-
|
|
20
|
-
`page`、`pageSize`、`viewId`、`sort`、`order` 不允许放进过滤对象,避免覆盖脚本控制的分页与视图参数。
|
|
21
|
-
|
|
22
|
-
| 维度 | JSON 字段 | 值类型/含义 |
|
|
23
|
-
|---|---|---|
|
|
24
|
-
| 工单号 | `ticketNumber`、`ticketNumberList` | 字符串、字符串数组 |
|
|
25
|
-
| 状态 | `ticketStatusList` | 字符串数组 |
|
|
26
|
-
| 渠道/平台 | `channelList`、`platformList` | 字符串数组 |
|
|
27
|
-
| 店铺/邮箱/电话入口 | `channelIdList`、`supportEmailIdList`、`supportPhoneList` | ID 数组、ID 数组、字符串数组 |
|
|
28
|
-
| 当前负责人 | `agentIdList` | 用户 ID 数组,不接受姓名 |
|
|
29
|
-
| 回复人条件 | `replyUserList` | 用户 ID 数组;这是列表查询条件,不等于报表事实中的 `responder` |
|
|
30
|
-
| 标签 | `tagList`、`noTag` | ID 数组、布尔值 |
|
|
31
|
-
| 客户 | `customerEmail`、`customerName`、`customerEmailFull`、`customerPhone` | 字符串 |
|
|
32
|
-
| 创建时间 | `createTimeBegin`、`createTimeEnd` | 带 offset 的 ISO-8601 时间字符串 |
|
|
33
|
-
| 综合搜索 | `keyword` | 匹配正文、备注、主题、客户、工单号或订单号等后端搜索字段 |
|
|
34
|
-
| 市场/订单 | `marketList`、`orderId` | 字符串数组、字符串 |
|
|
35
|
-
| 品类/品牌 | `categoryList`、`brandList` | 字符串数组 |
|
|
36
|
-
| 处理状态 | `humanHandling`、`myTicket`、`snoozed`、`scheduled` | 布尔值 |
|
|
37
|
-
| 排除项 | `notSpam`、`notNotification` | 布尔值 |
|
|
38
|
-
| Bot/Persona | `botIdList`、`personaId` | ID 数组、ID |
|
|
39
|
-
| 未读/发送失败 | `unread`、`sendFailure` | 布尔值 |
|
|
40
|
-
| Campaign | `campaignName` | 字符串 |
|
|
41
|
-
| Voice | `lastVoiceAnswerType`、`lastVoicePhoneType` | 字符串 |
|
|
42
|
-
|
|
43
|
-
示例:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
npx --yes @shulex/cxclawctl@latest script skills/solvea-desk/scripts/tickets/fetch_tickets.py \
|
|
47
|
-
--view-id 1 \
|
|
48
|
-
--filters-json '{"channelList":["ebay"],"agentIdList":[474501],"ticketStatusList":["open","pending"]}' \
|
|
49
|
-
--page-size 100 \
|
|
50
|
-
--sort last_update_time \
|
|
51
|
-
--order DESC
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
只下推值已经明确的条件。用户只给负责人姓名时不要猜 `agentId`;可以下推其他已知条件,再在响应字段 `agent` 上完成本地分析。
|
|
55
|
-
|
|
56
|
-
接口不支持按 `lastMessageTime`、`lastResponseTime`、`firstAgentResponseTime` 或 `lastUpdateTime` 传时间范围。用户要求这些口径时,先按后端已有条件拉取,再由 `analysis.py` 对响应字段进行筛选。不要创造额外的 fetch 参数或偷偷替换时间字段。
|
|
57
|
-
|
|
58
|
-
脚本根据响应 `total` 判断是否还有下一页;没有 `total` 时以当前页是否满页兜底。`manifest.json.truncated=true` 表示命中 `max-pages` 或 `max-rows`,不能声称已经获取全部工单。原始分页响应保存在 `tmp_task_dir/raw_page_*.json`,仅用于排查和重放。
|
|
59
|
-
|
|
60
|
-
## 响应参数说明
|
|
61
|
-
|
|
62
|
-
这是当前用户权限和指定 `viewId` 下的**当前工单列表快照**,不是历史报表事实。工单后来被重新分配、回复或关闭后,再次拉取时字段可能变化。
|
|
63
|
-
|
|
64
|
-
| 字段 | 含义 | 使用提醒 |
|
|
65
|
-
|---|---|---|
|
|
66
|
-
| `id` | 工单内部 ID | 对应报表快照的 `ticketId` |
|
|
67
|
-
| `ticketNumber` | 对外工单编号 | 展示和跨快照关联优先使用 |
|
|
68
|
-
| `channel` / `channelId` | 渠道及渠道授权 ID | `channelId` 可区分店铺或渠道实例 |
|
|
69
|
-
| `customerEmail` / `customerName` / `customerPhone` | 当前客户信息 | 输出时注意隐私 |
|
|
70
|
-
| `area` / `language` | 地区和语言 | 空值表示当前工单没有可用值 |
|
|
71
|
-
| `touchMethod` | 工单创建/触达方式 | 枚举以接口实际返回为准 |
|
|
72
|
-
| `creatorId` / `creator` | 创建人 ID / 姓名 | 当前展示值 |
|
|
73
|
-
| `createTime` | 工单创建时间 | 接口按 UTC 序列化,分析时转换到业务时区 |
|
|
74
|
-
| `ticketType` | 工单类型 | 枚举以接口实际返回为准 |
|
|
75
|
-
| `ticketStatus` | 当前工单状态 | 不是历史时点状态 |
|
|
76
|
-
| `subject` / `title` | 工单主题和标题 | 两者可能相同或其中一项为空 |
|
|
77
|
-
| `agentId` / `agent` | 当前负责人 ID / 姓名 | 不代表某一条历史回复的实际发送人 |
|
|
78
|
-
| `notes` / `lastNotes` | 备注相关字段 | 以实际返回内容为准 |
|
|
79
|
-
| `lastMessageTime` | 最近客户来信时间 | 不等于回复时间 |
|
|
80
|
-
| `lastResponseTime` | 当前记录的最近回复时间 | 后续回复会改变这个值 |
|
|
81
|
-
| `firstAgentResponseTime` | 客服首次回复时间 | 可与 `createTime` 计算当前列表口径的首响时效 |
|
|
82
|
-
| `sendFailureTime` | 最近发送失败时间 | 为空表示没有可用记录 |
|
|
83
|
-
| `lastUpdateTime` | 最近来信与最近回复中的较晚时间 | 默认列表排序字段对应的业务时点 |
|
|
84
|
-
| `slaHours` / `slaMinutes` | 当前剩余 SLA | 动态值,不适合作为历史处理时长 |
|
|
85
|
-
| `read` | 当前是否已读 | 当前状态 |
|
|
86
|
-
| `supportEmail` | 售后邮箱 | 由后端补充的展示字段 |
|
|
87
|
-
| `tagInfoList` | 标签完整路径信息 | 通常为嵌套 JSON,可辅助分类 |
|
|
88
|
-
| `customerStatus` | 当前客户状态 | 当前状态 |
|
|
89
|
-
| `replied` | 最后一封来信是否已回复 | 只描述当前最后一封来信 |
|
|
90
|
-
| `lastMessageContent` | 最后一封客户来信内容 | 可用于正文分类;不是完整消息历史 |
|
|
91
|
-
| `snoozed` / `snoozedTime` | 稍后处理状态和时间 | 当前状态 |
|
|
92
|
-
| `botId` / `botName` | Bot ID / 名称 | 由工单索引和后端补充字段组成 |
|
|
93
|
-
| `scheduled` / `scheduledTime` | 定时处理状态和时间 | 当前状态 |
|
|
94
|
-
| `voiceAnswerType` / `voiceDuration` / `voicePhoneType` | Voice 接听类型、时长和方向 | 仅相关 Voice 工单有值 |
|
|
95
|
-
| `voiceSummary` / `voiceMessageType` | Voice 摘要和消息子类型 | 仅相关 Voice/SMS 工单有值 |
|
|
96
|
-
| `providerDeliveryStatus` | SMS 服务商送达状态 | 仅 SMS 工单有值 |
|
|
97
|
-
|
|
98
|
-
与 `/api_v2/tars/api/ticket/report/raw/page` 历史报表事实的关键边界:
|
|
99
|
-
|
|
100
|
-
- 当前列表的 `agent` 是当前负责人;报表事实的 `responder`、`resolver` 分别表示实际回复人和解决人。
|
|
101
|
-
- 当前列表提供 `subject`、`title`、`lastMessageContent`;报表事实不提供消息正文。
|
|
102
|
-
- 当前列表时间字段反映当前记录;报表事实按回复日/解决日或创建日形成时间范围。
|
|
103
|
-
- 联合分析时优先用 `ticketNumber`,内部 ID 则用 `id` 对应报表的 `ticketId`,并注明两个快照的生成时间。
|