@shulex/cxclawctl 0.1.2 → 0.1.3

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 (208) hide show
  1. package/README.md +25 -22
  2. package/dist/cli.js +2202 -127
  3. package/dist/cli.js.map +1 -1
  4. package/package.json +19 -6
  5. package/capabilities.lock.json +0 -898
  6. package/requirements-cli.txt +0 -2
  7. package/skills/__lib__/__init__.py +0 -0
  8. package/skills/__lib__/skill-runtime/bootstrap.py +0 -134
  9. package/skills/__lib__/solvea-api/__init__.py +0 -0
  10. package/skills/__lib__/solvea-api/client.py +0 -1944
  11. package/skills/__lib__/solvea-api/dashboard.py +0 -100
  12. package/skills/__lib__/solvea-api/solvea_api.py +0 -1341
  13. package/skills/agent-analytics/SKILL.md +0 -74
  14. package/skills/agent-analytics/references/chat-report-fields.md +0 -36
  15. package/skills/agent-analytics/references/report-fields.md +0 -130
  16. package/skills/agent-analytics/references/transcript.md +0 -110
  17. package/skills/agent-builder/SKILL.md +0 -42
  18. package/skills/agent-builder/interfaces/fallback-chatflow.md +0 -47
  19. package/skills/agent-builder/references/chatflow/graph-spec.md +0 -259
  20. package/skills/agent-builder/references/chatflow/node-selection.md +0 -89
  21. package/skills/agent-builder/references/chatflow/nodes/agent.md +0 -350
  22. package/skills/agent-builder/references/chatflow/nodes/business-track.md +0 -43
  23. package/skills/agent-builder/references/chatflow/nodes/code.md +0 -157
  24. package/skills/agent-builder/references/chatflow/nodes/collect-order.md +0 -47
  25. package/skills/agent-builder/references/chatflow/nodes/finish.md +0 -34
  26. package/skills/agent-builder/references/chatflow/nodes/human-review.md +0 -60
  27. package/skills/agent-builder/references/chatflow/nodes/if-else.md +0 -100
  28. package/skills/agent-builder/references/chatflow/nodes/intent.md +0 -79
  29. package/skills/agent-builder/references/chatflow/nodes/knowledge-reply.md +0 -43
  30. package/skills/agent-builder/references/chatflow/nodes/llm.md +0 -117
  31. package/skills/agent-builder/references/chatflow/nodes/note.md +0 -38
  32. package/skills/agent-builder/references/chatflow/nodes/question.md +0 -97
  33. package/skills/agent-builder/references/chatflow/nodes/rag-reply.md +0 -68
  34. package/skills/agent-builder/references/chatflow/nodes/reply.md +0 -97
  35. package/skills/agent-builder/references/chatflow/nodes/start.md +0 -35
  36. package/skills/agent-builder/references/chatflow/nodes/sub-graph.md +0 -48
  37. package/skills/agent-builder/references/chatflow/nodes/tool.md +0 -138
  38. package/skills/agent-builder/references/chatflow/nodes/transfer-to-human.md +0 -63
  39. package/skills/agent-builder/references/chatflow/nodes/variable-assignment.md +0 -52
  40. package/skills/agent-builder/references/chatflow/nodes/variable-extract.md +0 -50
  41. package/skills/agent-builder/references/chatflow/nodes/variable-process.md +0 -70
  42. package/skills/agent-builder/references/chatflow/overview.md +0 -53
  43. package/skills/agent-builder/references/chatflow/visual-translation.md +0 -64
  44. package/skills/agent-builder/references/chatflow/workflow.md +0 -134
  45. package/skills/agent-builder/references/multi-agent/create-update.md +0 -185
  46. package/skills/agent-builder/references/multi-agent/graph-spec.md +0 -246
  47. package/skills/agent-builder/references/multi-agent/graph-structure.md +0 -12
  48. package/skills/agent-builder/references/multi-agent/migrate-to-chatflow.md +0 -13
  49. package/skills/agent-builder/references/multi-agent/migration/large.md +0 -554
  50. package/skills/agent-builder/references/multi-agent/migration/principles.md +0 -446
  51. package/skills/agent-builder/references/multi-agent/migration/small.md +0 -225
  52. package/skills/agent-builder/references/multi-agent/orchestration.md +0 -11
  53. package/skills/agent-builder/references/multi-agent/overview.md +0 -48
  54. package/skills/agent-builder/references/multi-agent/update.md +0 -128
  55. package/skills/agent-builder/references/multi-agent/workflow.md +0 -87
  56. package/skills/agent-builder/references/single-agent/overview.md +0 -48
  57. package/skills/agent-builder/references/single-agent/prompt.md +0 -16
  58. package/skills/agent-builder/references/single-agent/tools.md +0 -36
  59. package/skills/agent-builder/references/single-agent/voice.md +0 -46
  60. package/skills/agent-builder/references/tools/http-tool.md +0 -315
  61. package/skills/agent-builder/references/tools/mock-tool.md +0 -279
  62. package/skills/agent-builder/references/tools/overview.md +0 -46
  63. package/skills/agent-builder/references/tools/tool-config.md +0 -43
  64. package/skills/agent-builder/references/tools/x-token.md +0 -34
  65. package/skills/agent-builder/scripts/chatflow/chatflow_builder.py +0 -3458
  66. package/skills/agent-builder/scripts/chatflow/validate_graph.py +0 -1697
  67. package/skills/agent-builder/scripts/copy_marketplace_agent.py +0 -61
  68. package/skills/agent-builder/scripts/multi-agent/legacy_graph_analyzer.py +0 -5974
  69. package/skills/agent-builder/scripts/multi-agent/replay_compare.py +0 -679
  70. package/skills/agent-builder/scripts/patch_agent_tools.py +0 -135
  71. package/skills/agent-builder/scripts/tools/validate_tool_config.py +0 -384
  72. package/skills/agent-tester/SKILL.md +0 -35
  73. package/skills/agent-tester/batch-test/overview.md +0 -86
  74. package/skills/agent-tester/scripts/batch_test_sheet.py +0 -213
  75. package/skills/agent-tester/single-test/badcase-retest.md +0 -85
  76. package/skills/agent-tester/single-test/direct-test.md +0 -24
  77. package/skills/agent-tester/single-test/overview.md +0 -142
  78. package/skills/delivery/SKILL.md +0 -112
  79. package/skills/delivery/interfaces/classify.md +0 -38
  80. package/skills/delivery/interfaces/create-agents.md +0 -89
  81. package/skills/delivery/interfaces/delivery-test.md +0 -67
  82. package/skills/delivery/references/flow.md +0 -40
  83. package/skills/delivery/references/validation.md +0 -15
  84. package/skills/delivery/scripts/batch_test.py +0 -704
  85. package/skills/delivery/scripts/classify.py +0 -22
  86. package/skills/delivery/scripts/create_agents.py +0 -695
  87. package/skills/delivery/scripts/gen_delivery_report.py +0 -335
  88. package/skills/delivery/scripts/gen_excel.py +0 -234
  89. package/skills/delivery/scripts/gen_report.py +0 -208
  90. package/skills/delivery/scripts/plan.py +0 -163
  91. package/skills/delivery/scripts/render.py +0 -713
  92. package/skills/delivery/scripts/render_summary.py +0 -38
  93. package/skills/delivery/scripts/sample_history_cases.py +0 -109
  94. package/skills/kb-builder/SKILL.md +0 -80
  95. package/skills/kb-builder/interfaces/qa-upload.md +0 -55
  96. package/skills/kb-builder/interfaces/web-kb.md +0 -84
  97. package/skills/kb-builder/references/directory.md +0 -373
  98. package/skills/kb-builder/references/export.md +0 -282
  99. package/skills/kb-builder/references/isolation-keywords.md +0 -113
  100. package/skills/kb-builder/references/knowledge.md +0 -153
  101. package/skills/kb-builder/references/product.md +0 -52
  102. package/skills/kb-builder/references/qa-from-help-center.md +0 -58
  103. package/skills/kb-builder/references/qa-from-pdf.md +0 -94
  104. package/skills/kb-builder/references/qa-from-tickets.md +0 -168
  105. package/skills/kb-builder/references/qa-from-web.md +0 -98
  106. package/skills/kb-builder/references/qa-quality.md +0 -73
  107. package/skills/kb-builder/references/reply-template.md +0 -237
  108. package/skills/kb-builder/references/tag-isolation-migration.md +0 -61
  109. package/skills/kb-builder/references/tags.md +0 -45
  110. package/skills/kb-builder/references/upload.md +0 -130
  111. package/skills/kb-builder/scripts/batch_extract_ticket_qa.py +0 -333
  112. package/skills/kb-builder/scripts/build_directory_plan.py +0 -144
  113. package/skills/kb-builder/scripts/crawl_site.py +0 -433
  114. package/skills/kb-builder/scripts/create_dirs.py +0 -146
  115. package/skills/kb-builder/scripts/export_knowledge.py +0 -454
  116. package/skills/kb-builder/scripts/extract_ticket_qa.py +0 -441
  117. package/skills/kb-builder/scripts/extract_web_qa.py +0 -118
  118. package/skills/kb-builder/scripts/import_qa.py +0 -219
  119. package/skills/kb-builder/scripts/import_source_documents.py +0 -143
  120. package/skills/kb-builder/scripts/import_templates.py +0 -409
  121. package/skills/poc/SKILL.md +0 -125
  122. package/skills/poc/assets/default_manual.css +0 -279
  123. package/skills/poc/assets/notice_escalate.png +0 -0
  124. package/skills/poc/assets/notice_escalate2.png +0 -0
  125. package/skills/poc/assets/notice_new_chat.png +0 -0
  126. package/skills/poc/assets/poc_test_template.html +0 -645
  127. package/skills/poc/assets/poc_test_template.md +0 -104
  128. package/skills/poc/assets/step3_preview.png +0 -0
  129. package/skills/poc/assets/step4_order_note.png +0 -0
  130. package/skills/poc/interfaces/classify.md +0 -38
  131. package/skills/poc/interfaces/create-agents.md +0 -108
  132. package/skills/poc/interfaces/poc-test.md +0 -94
  133. package/skills/poc/references/flow.md +0 -47
  134. package/skills/poc/references/kb-directory.md +0 -22
  135. package/skills/poc/references/validation.md +0 -17
  136. package/skills/poc/scripts/classify.py +0 -22
  137. package/skills/poc/scripts/create_agents.py +0 -818
  138. package/skills/poc/scripts/gen_excel.py +0 -234
  139. package/skills/poc/scripts/gen_poc_manual.py +0 -249
  140. package/skills/poc/scripts/gen_report.py +0 -208
  141. package/skills/poc/scripts/inspect_chatflow.py +0 -209
  142. package/skills/poc/scripts/plan.py +0 -178
  143. package/skills/poc/scripts/poc_test.py +0 -495
  144. package/skills/poc/scripts/render.py +0 -713
  145. package/skills/poc/scripts/render_summary.py +0 -41
  146. package/skills/runtime-inspector/SKILL.md +0 -51
  147. package/skills/runtime-inspector/references/frontend-rendering.md +0 -126
  148. package/skills/runtime-inspector/references/model.md +0 -59
  149. package/skills/runtime-inspector/references/sandbox.md +0 -131
  150. package/skills/runtime-inspector/scripts/model_inspect.py +0 -68
  151. package/skills/runtime-inspector/scripts/prepare.py +0 -98
  152. package/skills/runtime-inspector/scripts/process.py +0 -84
  153. package/skills/runtime-inspector/scripts/read_state.py +0 -32
  154. package/skills/runtime-inspector/scripts/sandbox_inspect.py +0 -463
  155. package/skills/runtime-inspector/scripts/test_claude_proxy.py +0 -49
  156. package/skills/runtime-inspector/scripts/test_openai_proxy.py +0 -41
  157. package/skills/runtime-inspector/scripts/verify_persistence.py +0 -101
  158. package/skills/runtime-inspector/scripts/write_test.py +0 -41
  159. package/skills/setup/SKILL.md +0 -17
  160. package/skills/shulex-support/SKILL.md +0 -39
  161. package/skills/shulex-support/references/badcase-analysis/overview.md +0 -34
  162. package/skills/shulex-support/references/badcase-analysis/text/conversation-record.md +0 -105
  163. package/skills/shulex-support/references/badcase-analysis/text/core-flow.md +0 -89
  164. package/skills/shulex-support/references/badcase-analysis/text/log-query-rules.md +0 -36
  165. package/skills/shulex-support/references/badcase-analysis/text/m1-entry.md +0 -53
  166. package/skills/shulex-support/references/badcase-analysis/text/m10-chatflow-service.md +0 -259
  167. package/skills/shulex-support/references/badcase-analysis/text/m11-algorithm-service.md +0 -148
  168. package/skills/shulex-support/references/badcase-analysis/text/m12-quality-inspection.md +0 -57
  169. package/skills/shulex-support/references/badcase-analysis/text/m2-intent.md +0 -120
  170. package/skills/shulex-support/references/badcase-analysis/text/m3-strategy.md +0 -126
  171. package/skills/shulex-support/references/badcase-analysis/text/m4-aifield.md +0 -121
  172. package/skills/shulex-support/references/badcase-analysis/text/m5-agent.md +0 -208
  173. package/skills/shulex-support/references/badcase-analysis/text/m6-tool.md +0 -115
  174. package/skills/shulex-support/references/badcase-analysis/text/m7-reply.md +0 -72
  175. package/skills/shulex-support/references/badcase-analysis/text/m8-error.md +0 -92
  176. package/skills/shulex-support/references/badcase-analysis/text/m9-knowledge-search.md +0 -147
  177. package/skills/shulex-support/references/badcase-analysis/text/sls-query.md +0 -283
  178. package/skills/shulex-support/references/badcase-analysis/voice/core-flow.md +0 -77
  179. package/skills/shulex-support/references/badcase-analysis/voice/dependencies.md +0 -19
  180. package/skills/shulex-support/references/badcase-analysis/voice/platform-api.md +0 -23
  181. package/skills/shulex-support/references/badcase-analysis/voice/sls-playbook.md +0 -31
  182. package/skills/shulex-support/references/product-docs.md +0 -70
  183. package/skills/shulex-support/references/tickets.md +0 -184
  184. package/skills/shulex-support/scripts/support.py +0 -427
  185. package/skills/solvea-desk/SKILL.md +0 -39
  186. package/skills/solvea-desk/references/report/fields.md +0 -82
  187. package/skills/solvea-desk/references/report/report-design.md +0 -200
  188. package/skills/solvea-desk/references/report/report-template.html +0 -44
  189. package/skills/solvea-desk/references/report/report.css +0 -517
  190. package/skills/solvea-desk/references/report/workflow.md +0 -464
  191. package/skills/solvea-desk/references/tickets/query.md +0 -103
  192. package/skills/solvea-desk/references/tickets/tags.md +0 -83
  193. package/skills/solvea-desk/scripts/report/fetch_sources.py +0 -580
  194. package/skills/solvea-desk/scripts/report/render_report.py +0 -763
  195. package/skills/solvea-desk/scripts/tickets/desk_api.py +0 -73
  196. package/skills/solvea-desk/scripts/tickets/fetch_tickets.py +0 -403
  197. package/skills/solvea-desk/scripts/tickets/ticket_tags.py +0 -305
  198. package/skills/solvea-kit/SKILL.md +0 -84
  199. package/skills/solvea-kit/references/agent.md +0 -145
  200. package/skills/solvea-kit/references/chat.md +0 -244
  201. package/skills/solvea-kit/references/intent.md +0 -69
  202. package/skills/solvea-kit/references/plugin.md +0 -53
  203. package/skills/solvea-kit/references/quality-inspection.md +0 -75
  204. package/skills/solvea-kit/references/strategy.md +0 -62
  205. package/skills/solvea-kit/references/tagging.md +0 -231
  206. package/skills/solvea-kit/references/variables.md +0 -53
  207. package/skills/solvea-kit/scripts/generate_label_import_file.py +0 -151
  208. package/skills/solvea-kit/scripts/intent_classify.py +0 -843
@@ -1,409 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Import an Excel/CSV file into Solvea template library.
4
-
5
- Required columns:
6
- - name
7
- - content
8
-
9
- Optional columns:
10
- - status: defaults to ENABLED
11
- - scene: empty/default for normal templates, voice_sms for SMS templates
12
- - AUTO, ENGLISH, CHINESE, JAPANESE, FRENCH, GERMAN, SPANISH, ARABIC,
13
- RUSSIAN, PORTUGUESE, ITALIAN, KOREAN, DUTCH, INDONESIAN, TURKISH,
14
- ROMANIAN, POLISH, PHILIPPINES
15
-
16
- Usage:
17
- python3 /skills/kb-builder/scripts/import_templates.py --xlsx /mounted/chat-files/user/templates.xlsx --dry-run
18
- python3 /skills/kb-builder/scripts/import_templates.py --xlsx /mounted/chat-files/user/templates.xlsx --name-col "Topic" --content-col "Message" --dry-run
19
- python3 /skills/kb-builder/scripts/import_templates.py --xlsx /mounted/chat-files/user/templates.xlsx --skip-duplicates --dry-run
20
- python3 /skills/kb-builder/scripts/import_templates.py --plan-file /workspace/outputs/kb-builder/template_import_plan_<ts>.json
21
- python3 /skills/kb-builder/scripts/import_templates.py --xlsx /mounted/chat-files/user/templates.xlsx
22
- """
23
- from __future__ import annotations
24
-
25
- import argparse
26
- import csv
27
- import html
28
- import json
29
- import os
30
- import sys
31
- from pathlib import Path
32
- from typing import Any
33
-
34
- sys.path.insert(0, os.path.join(os.environ.get("SOLVEA_LIB_DIR", os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "__lib__"))), "skill-runtime"))
35
- from bootstrap import * # noqa: F403
36
-
37
- from client import SolveaClient
38
-
39
- try:
40
- from openpyxl import load_workbook
41
- except ImportError: # pragma: no cover - runtime image should include openpyxl in sandbox deps
42
- load_workbook = None
43
-
44
-
45
- HEADER_ALIASES = {
46
- "name": {
47
- "name",
48
- "title",
49
- "topic",
50
- "template",
51
- "template_name",
52
- "template name",
53
- "template title",
54
- "模板名称",
55
- "模板名",
56
- "模版名称",
57
- "模版名",
58
- "名称",
59
- "标题",
60
- "主题",
61
- },
62
- "content": {
63
- "content",
64
- "message",
65
- "body",
66
- "reply",
67
- "answer",
68
- "response",
69
- "template_content",
70
- "template content",
71
- "reply text",
72
- "模板内容",
73
- "模板回复",
74
- "模版内容",
75
- "模版回复",
76
- "回复内容",
77
- "回复话术",
78
- "话术",
79
- "答案",
80
- "内容",
81
- },
82
- "status": {"status", "state", "状态", "发布状态"},
83
- "scene": {"scene", "usage", "scenario", "场景", "适用场景"},
84
- }
85
-
86
- LANGUAGE_COLUMNS = {
87
- "AUTO",
88
- "ENGLISH",
89
- "CHINESE",
90
- "JAPANESE",
91
- "FRENCH",
92
- "GERMAN",
93
- "SPANISH",
94
- "ARABIC",
95
- "RUSSIAN",
96
- "PORTUGUESE",
97
- "ITALIAN",
98
- "KOREAN",
99
- "DUTCH",
100
- "INDONESIAN",
101
- "TURKISH",
102
- "ROMANIAN",
103
- "POLISH",
104
- "PHILIPPINES",
105
- }
106
-
107
-
108
- def normalize_header(value: Any) -> str:
109
- return str(value or "").strip().lower().replace("-", "_")
110
-
111
-
112
- def normalize_cell(value: Any) -> str:
113
- if value is None:
114
- return ""
115
- return html.unescape(str(value).strip())
116
-
117
-
118
- def canonical_header(header: Any) -> str:
119
- raw = str(header or "").strip()
120
- normalized = normalize_header(raw)
121
- for canonical, aliases in HEADER_ALIASES.items():
122
- if normalized in {normalize_header(alias) for alias in aliases}:
123
- return canonical
124
- upper = raw.upper().strip()
125
- if upper in LANGUAGE_COLUMNS:
126
- return upper
127
- return normalized
128
-
129
-
130
- def load_templates_from_excel(
131
- path: str | Path,
132
- sheet: str | None = None,
133
- *,
134
- name_col: str | None = None,
135
- content_col: str | None = None,
136
- status_col: str | None = None,
137
- scene_col: str | None = None,
138
- lang_cols: dict[str, str] | None = None,
139
- skip_duplicates: bool = False,
140
- include_stats: bool = False,
141
- ) -> list[dict[str, Any]] | tuple[list[dict[str, Any]], list[dict[str, Any]]]:
142
- path = Path(path)
143
- rows = _load_rows(path, sheet)
144
- if not rows:
145
- if include_stats:
146
- return [], []
147
- return []
148
-
149
- raw_headers = [normalize_cell(cell) for cell in rows[0]]
150
- headers = resolve_headers(
151
- raw_headers,
152
- name_col=name_col,
153
- content_col=content_col,
154
- status_col=status_col,
155
- scene_col=scene_col,
156
- lang_cols=lang_cols,
157
- )
158
- templates: list[dict[str, Any]] = []
159
- seen_names: set[str] = set()
160
- skipped_duplicates: list[dict[str, Any]] = []
161
- for row_idx, row in enumerate(rows[1:], start=2):
162
- values = {
163
- headers[idx]: normalize_cell(row[idx]) if idx < len(row) else ""
164
- for idx in range(len(headers))
165
- if headers[idx]
166
- }
167
- name = values.get("name", "")
168
- content = values.get("content", "")
169
- if not name and not content:
170
- continue
171
- if not name or not content:
172
- raise ValueError(f"row {row_idx}: name and content are required")
173
- if name in seen_names:
174
- if skip_duplicates:
175
- skipped_duplicates.append({"row": row_idx, "name": name})
176
- continue
177
- raise ValueError(f"row {row_idx}: duplicate template name in file: {name}")
178
- seen_names.add(name)
179
-
180
- multi_content = {"AUTO": values.get("AUTO") or content}
181
- for language in sorted(LANGUAGE_COLUMNS - {"AUTO"}):
182
- if values.get(language):
183
- multi_content[language] = values[language]
184
-
185
- templates.append({
186
- "name": name,
187
- "content": content,
188
- "status": values.get("status") or "ENABLED",
189
- "scene": values.get("scene") or None,
190
- "multiContent": multi_content,
191
- })
192
- if include_stats:
193
- return templates, skipped_duplicates
194
- return templates
195
-
196
-
197
- def resolve_headers(
198
- raw_headers: list[str],
199
- *,
200
- name_col: str | None = None,
201
- content_col: str | None = None,
202
- status_col: str | None = None,
203
- scene_col: str | None = None,
204
- lang_cols: dict[str, str] | None = None,
205
- ) -> list[str]:
206
- headers = [canonical_header(cell) for cell in raw_headers]
207
-
208
- overrides = {
209
- "name": name_col,
210
- "content": content_col,
211
- "status": status_col,
212
- "scene": scene_col,
213
- }
214
- for canonical, requested_col in overrides.items():
215
- if requested_col:
216
- headers[_require_raw_header(raw_headers, requested_col, f"--{canonical.replace('_', '-')}-col")] = canonical
217
-
218
- for language, requested_col in (lang_cols or {}).items():
219
- language = language.upper()
220
- if language not in LANGUAGE_COLUMNS:
221
- raise ValueError(f"Unsupported language '{language}'. Supported languages: {sorted(LANGUAGE_COLUMNS)}")
222
- headers[_require_raw_header(raw_headers, requested_col, f"--lang-col {language}")] = language
223
-
224
- if "name" not in headers or "content" not in headers:
225
- raise ValueError(
226
- "Cannot detect template name/content columns. "
227
- "Use --name-col and --content-col after inspecting the uploaded file header. "
228
- f"Available columns: {raw_headers}"
229
- )
230
- return headers
231
-
232
-
233
- def _require_raw_header(raw_headers: list[str], requested_col: str, arg_name: str) -> int:
234
- requested = normalize_header(requested_col)
235
- for idx, header in enumerate(raw_headers):
236
- if normalize_header(header) == requested:
237
- return idx
238
- raise ValueError(f"{arg_name} '{requested_col}' not found. Available columns: {raw_headers}")
239
-
240
-
241
- def _load_rows(path: Path, sheet: str | None) -> list[list[Any]]:
242
- suffix = path.suffix.lower()
243
- if suffix == ".csv":
244
- with path.open(newline="", encoding="utf-8-sig") as f:
245
- return list(csv.reader(f))
246
- if suffix not in {".xlsx", ".xlsm"}:
247
- raise ValueError("Only .xlsx, .xlsm, and .csv files are supported")
248
- if load_workbook is None:
249
- raise RuntimeError("openpyxl is required to read Excel files")
250
- wb = load_workbook(path, read_only=True, data_only=True)
251
- ws = wb[sheet] if sheet else wb.active
252
- return [list(row) for row in ws.iter_rows(values_only=True)]
253
-
254
-
255
- def import_templates(
256
- client: SolveaClient,
257
- *,
258
- xlsx_path: str | Path | None = None,
259
- plan_file: str | Path | None = None,
260
- dry_run: bool,
261
- sheet: str | None = None,
262
- name_col: str | None = None,
263
- content_col: str | None = None,
264
- status_col: str | None = None,
265
- scene_col: str | None = None,
266
- lang_cols: dict[str, str] | None = None,
267
- skip_duplicates: bool = False,
268
- ) -> dict[str, Any]:
269
- if bool(xlsx_path) == bool(plan_file):
270
- raise ValueError("Exactly one of xlsx_path or plan_file is required")
271
- if plan_file:
272
- templates = load_templates_from_plan(plan_file)
273
- skipped_duplicates: list[dict[str, Any]] = []
274
- source_path = str(plan_file)
275
- else:
276
- templates, skipped_duplicates = load_templates_from_excel(
277
- xlsx_path,
278
- sheet=sheet,
279
- name_col=name_col,
280
- content_col=content_col,
281
- status_col=status_col,
282
- scene_col=scene_col,
283
- lang_cols=lang_cols,
284
- skip_duplicates=skip_duplicates,
285
- include_stats=True,
286
- )
287
- source_path = str(xlsx_path)
288
- OUTPUTS_DIR.mkdir(parents=True, exist_ok=True) # noqa: F405
289
- plan_path: Path | None = None
290
- if dry_run:
291
- plan_path = OUTPUTS_DIR / f"template_import_plan_{timestamp()}.json" # noqa: F405
292
- plan_path.write_text(json.dumps(templates, ensure_ascii=False, indent=2), encoding="utf-8")
293
-
294
- created = 0
295
- failed = 0
296
- created_items: list[dict[str, Any]] = []
297
- errors: list[dict[str, str]] = []
298
- if not dry_run:
299
- for item in templates:
300
- try:
301
- response = client.create_template(item)
302
- template_id = extract_template_id(response)
303
- created += 1
304
- created_items.append({"id": template_id, "name": item["name"]})
305
- suffix = f" id={template_id}" if template_id is not None else ""
306
- print(f" [OK] {item['name']}{suffix}")
307
- except Exception as exc:
308
- failed += 1
309
- errors.append({"name": item["name"], "error": str(exc)})
310
- print(f" [FAIL] {item['name']}: {exc}", file=sys.stderr)
311
-
312
- result_path: Path | None = None
313
- if not dry_run:
314
- result_path = OUTPUTS_DIR / f"template_import_result_{timestamp()}.json" # noqa: F405
315
-
316
- result = {
317
- "input": len(templates),
318
- "created": created,
319
- "failed": failed,
320
- "source_path": source_path,
321
- "plan_path": str(plan_path) if plan_path else None,
322
- "result_path": str(result_path) if result_path else None,
323
- "created_items": created_items,
324
- "skipped_duplicates": skipped_duplicates,
325
- "errors": errors,
326
- }
327
- if result_path:
328
- result_path.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
329
- print(json.dumps(result, ensure_ascii=False, indent=2))
330
- return result
331
-
332
-
333
- def extract_template_id(response: Any) -> Any:
334
- if not isinstance(response, dict):
335
- return None
336
- if response.get("id") is not None:
337
- return response.get("id")
338
- data = response.get("data")
339
- if isinstance(data, dict):
340
- return data.get("id")
341
- return None
342
-
343
-
344
- def load_templates_from_plan(plan_file: str | Path) -> list[dict[str, Any]]:
345
- path = Path(plan_file)
346
- data = json.loads(path.read_text(encoding="utf-8"))
347
- if not isinstance(data, list):
348
- raise ValueError("template import plan must be a JSON array")
349
- for idx, item in enumerate(data, start=1):
350
- if not isinstance(item, dict) or not item.get("name") or not item.get("content"):
351
- raise ValueError(f"invalid template import plan item at index {idx}")
352
- return data
353
-
354
-
355
- def main() -> None:
356
- parser = argparse.ArgumentParser(description="Import Excel/CSV templates into Solvea template library")
357
- source = parser.add_mutually_exclusive_group(required=True)
358
- source.add_argument("--xlsx", default=None, help="Excel/CSV file path")
359
- source.add_argument("--plan-file", default=None, help="Import from a dry-run template_import_plan JSON file")
360
- parser.add_argument("--sheet", default=None, help="Optional Excel sheet name")
361
- parser.add_argument("--name-col", default=None, help="Column containing template name")
362
- parser.add_argument("--content-col", default=None, help="Column containing default template content")
363
- parser.add_argument("--status-col", default=None, help="Optional status column")
364
- parser.add_argument("--scene-col", default=None, help="Optional scene column")
365
- parser.add_argument(
366
- "--lang-col",
367
- action="append",
368
- default=[],
369
- help="Optional language column mapping, e.g. CHINESE=中文话术. Can be repeated.",
370
- )
371
- parser.add_argument("--dry-run", action="store_true", help="Parse and write plan without creating templates")
372
- parser.add_argument(
373
- "--skip-duplicates",
374
- action="store_true",
375
- help="Keep the first row for duplicate template names and skip later duplicates",
376
- )
377
- args = parser.parse_args()
378
-
379
- import_templates(
380
- SolveaClient(),
381
- xlsx_path=args.xlsx,
382
- plan_file=args.plan_file,
383
- sheet=args.sheet,
384
- dry_run=args.dry_run,
385
- name_col=args.name_col,
386
- content_col=args.content_col,
387
- status_col=args.status_col,
388
- scene_col=args.scene_col,
389
- lang_cols=parse_lang_cols(args.lang_col),
390
- skip_duplicates=args.skip_duplicates,
391
- )
392
-
393
-
394
- def parse_lang_cols(values: list[str]) -> dict[str, str]:
395
- result: dict[str, str] = {}
396
- for value in values:
397
- if "=" not in value:
398
- raise ValueError(f"--lang-col must use LANGUAGE=COLUMN format, got: {value}")
399
- language, column = value.split("=", 1)
400
- language = language.strip().upper()
401
- column = column.strip()
402
- if not language or not column:
403
- raise ValueError(f"--lang-col must use LANGUAGE=COLUMN format, got: {value}")
404
- result[language] = column
405
- return result
406
-
407
-
408
- if __name__ == "__main__":
409
- main()
@@ -1,125 +0,0 @@
1
- ---
2
- name: poc
3
- description: 售前 POC 业务编排。只负责阶段推进、用户确认和交付物汇总;具体意图、Agent、KB、批测能力通过其他 skill 的 interfaces 调用。
4
- requires:
5
- skills: [agent-builder, kb-builder]
6
- ---
7
-
8
- # POC
9
-
10
- 售前 POC 编排 skill。职责是把现有原子能力串成业务流程,不复制其他 skill 的内部职责。
11
-
12
- ## 边界原则
13
-
14
- - 只调用其他 skill 暴露的 `interfaces/` 能力,不读取或复述其他 skill 的完整内部流程。
15
- - 不在本 skill 维护 intent 创建、chatflow graph、KB crawl、QA 上传、批测 runner 的实现细节。
16
- - 顶层状态只保存跨阶段引用,不复制底层 skill 的完整 state。
17
- - 每个会产生外部写入或业务结果变化的阶段完成后,先向用户确认,再进入下一阶段。
18
-
19
- ## 必读文件
20
-
21
- 按需读取以下 interface:
22
-
23
- | 阶段 | Interface |
24
- |---|---|
25
- | 意图分类 | `/skills/poc/interfaces/classify.md` |
26
- | POC agent / 策略创建 | `/skills/poc/interfaces/create-agents.md` |
27
- | 兜底 chatflow agent | `/skills/agent-builder/interfaces/fallback-chatflow.md` |
28
- | 知识库,可选 | `/skills/kb-builder/interfaces/web-kb.md` / `/skills/kb-builder/interfaces/qa-upload.md` |
29
- | POC 标准 KB 目录规范 | `/skills/poc/references/kb-directory.md` |
30
- | POC 批测与手册 | `/skills/poc/interfaces/poc-test.md` |
31
-
32
- ## 顶层状态
33
-
34
- 状态文件:`/workspace/state/poc/progress.json`。
35
-
36
- 每次开始处理 POC 前,先运行:
37
-
38
- ```bash
39
- npx --yes @shulex/cxclawctl@latest script skills/poc/scripts/plan.py --init
40
- ```
41
-
42
- 阶段完成后用 `plan.py` 更新顶层状态,例如:
43
-
44
- ```bash
45
- npx --yes @shulex/cxclawctl@latest script skills/poc/scripts/plan.py \
46
- --status business_agents_created \
47
- --set intent.created_log_path=/workspace/outputs/poc/created_<ts>.json
48
- ```
49
-
50
- 需要汇总当前交付物时运行:
51
-
52
- ```bash
53
- npx --yes @shulex/cxclawctl@latest script skills/poc/scripts/render_summary.py
54
- ```
55
-
56
- 状态只记录跨阶段引用:
57
-
58
- ```json
59
- {
60
- "status": "empty | classified | business_agents_created | fallback_agent_created | fallback_strategy_linked | kb_done | cases_ready | test_done | done",
61
- "tenant": "",
62
- "brand_name": "",
63
- "brand_website": "",
64
- "intent": {
65
- "progress_path": "/workspace/state/poc/progress.json",
66
- "created_log_path": "",
67
- "classification_report_path": "",
68
- "classification_excel_path": ""
69
- },
70
- "fallback_agent": {
71
- "agent_id": "",
72
- "agent_name": "",
73
- "created": false
74
- },
75
- "kb": {
76
- "enabled": false,
77
- "source_url": "",
78
- "directory_plan_path": "",
79
- "qa_plan_path": "",
80
- "upload_result_path": ""
81
- },
82
- "test": {
83
- "agents": [],
84
- "cases_json_path": "",
85
- "results_path": "",
86
- "manual_path": ""
87
- },
88
- "updated_at": ""
89
- }
90
- ```
91
-
92
- ## 起点判断
93
-
94
- 按用户消息判断起点,命中即跳;都没命中时询问用户从哪个阶段开始。
95
-
96
- | 用户消息含 | 起点 |
97
- |---|---|
98
- | 「指定 agent / 用现有 agent / 跳过意图 / 直接测试」 | 批测与手册 |
99
- | 「补充知识 / 提取 QA / 加进 KB」+ 知识源附件 | 知识库 |
100
- | 「建知识库目录 / 搭知识库」+ 网站/知识来源 URL | 知识库 |
101
- | 「上传 qa_plan.json」 | 知识库上传 |
102
- | 给了 xlsx 路径 | 意图分类 |
103
- | 「接着上次」 | 读 `/workspace/state/poc/progress.json`,缺失时再看底层状态引用 |
104
-
105
- 如果只输入 `/poc` 或信息不足,询问:
106
-
107
- ```text
108
- 您想从哪个阶段开始?
109
-
110
- 1. 阶段一:意图分类与场景创建
111
- 2. 阶段二:知识库搭建(可选)
112
- 3. 阶段三:批量测试 + POC 手册
113
-
114
- 请告诉我从哪一步开始以及已有素材路径。
115
- ```
116
-
117
- ## 流程
118
-
119
- 详见 `/skills/poc/references/flow.md`。
120
-
121
- ## 可恢复缺口
122
-
123
- POC 的预置业务 agent 只是默认来源,不是硬阻塞。执行创建脚本后如果 state 或 created log 出现
124
- `preset_agent_missing` / `preset_agent_errors`,必须向用户说明缺失项,并询问是从零新建 CHAT_FLOW 业务
125
- agent,还是使用其他现有 agent 替代;不要直接报告“预置 Agent 不存在,必须开发修复后才能继续”。