@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,818 +0,0 @@
1
- """
2
- POC intent / agent / strategy creation pipeline.
3
-
4
- Creates all intents, tries to clone 3 fixed marketplace agents, creates 3
5
- business strategies when those presets are available, and marks the remaining
6
- intents as fallback_pending. If a preset agent is unavailable, the script writes
7
- a recoverable state instead of raising, so the operator can ask whether to build
8
- new agents from scratch or use substitute agents.
9
-
10
- Usage:
11
- # poc business setup: create all intents + 3 cloned agents + 3 strategies
12
- python3 scripts/create_agents.py --mode poc
13
-
14
- # poc fallback link: bind a previously-built fallback agent to remaining intents
15
- python3 scripts/create_agents.py --mode poc --poc-fallback-agent-id 99999
16
-
17
- # disable SYSTEM intents after a creation run
18
- python3 scripts/create_agents.py --disable-system
19
-
20
- # dry-run preview (no API calls beyond marketplace listing in non-disable mode)
21
- python3 scripts/create_agents.py --dry-run
22
- """
23
-
24
- import os, sys
25
- 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"))
26
- from bootstrap import *
27
-
28
- import json, argparse
29
- from pathlib import Path
30
-
31
- from client import SolveaClient
32
-
33
-
34
- def _read_state() -> dict:
35
- _sf = STATE_DIR / "progress.json"
36
- if _sf.exists():
37
- try:
38
- return json.loads(_sf.read_text(encoding="utf-8"))
39
- except Exception:
40
- pass
41
- return {}
42
-
43
-
44
- def _write_state(data: dict) -> None:
45
- _sf = STATE_DIR / "progress.json"
46
- _sf.parent.mkdir(parents=True, exist_ok=True)
47
- _sf.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
48
-
49
-
50
- # ── Fixed mapping table ────────────────────────────────────────────────────────
51
-
52
- STANDARD_INTENT_NAMES = [
53
- "Pre-Sales Inquiry",
54
- "Invoices",
55
- "Order Issues",
56
- "Logistics Issues",
57
- "Package issues",
58
- "Product issues",
59
- "Return and exchange",
60
- ]
61
-
62
-
63
- # POC 固定绑定:每个 binding 把若干 L1 意图绑到同一个广场 agent(按 squareAgent_id)。
64
- # 不在任何 binding 中的意图,全部走兜底策略(由 --poc-fallback-agent-id 阶段绑定)。
65
- POC_AGENT_BINDINGS = [
66
- {
67
- "name": "Package_Logistics",
68
- "intents": ["Package issues", "Logistics Issues"],
69
- "square_agent_id": 38433,
70
- },
71
- {
72
- "name": "PreSales",
73
- "intents": ["Pre-Sales Inquiry"],
74
- "square_agent_id": 38429,
75
- },
76
- {
77
- "name": "Product",
78
- "intents": ["Product issues"],
79
- "square_agent_id": 38428,
80
- },
81
- ]
82
-
83
- POC_BUSINESS_INTENT_NAMES = {n for b in POC_AGENT_BINDINGS for n in b["intents"]}
84
-
85
- # 兜底策略的优先级(数值越大越后匹配)。业务策略默认 0,兜底设大避免抢匹配。
86
- POC_FALLBACK_STRATEGY_PRIORITY = 999
87
-
88
-
89
- # ── Data loading ───────────────────────────────────────────────────────────────
90
-
91
- def load_results(state: dict) -> dict:
92
- """Load classification results pointed to by state.results_path.
93
-
94
- eager 模型下 workspace/outputs/ 跨轮路径稳定,state 里存的绝对路径下轮直接可用。
95
- """
96
- path = state.get("results_path")
97
- if not path:
98
- raise FileNotFoundError("state.results_path missing. Run classify.py first.")
99
- if not os.path.exists(path):
100
- raise FileNotFoundError(f"Results file missing: {path}")
101
- with open(path) as f:
102
- return json.load(f)
103
-
104
-
105
- # ── Feature pre-flight checks ─────────────────────────────────────────────────
106
-
107
- def check_and_enable_intent_feature(solvea: SolveaClient) -> None:
108
- """创建意图前确保意图功能已开启(configurationWizard.intent=true)。
109
-
110
- 查询:GET /api_v2/gpt/project/{projectId}/config → configurationWizard.intent
111
- 开启:PUT /api_v2/gpt/project/{projectId} → body: {configurationWizard: {intent: true}}
112
- """
113
- resp = solvea._curl("GET", f"/api_v2/gpt/project/{solvea.project_id}/config")
114
- payload = resp.get("data", resp) or {}
115
- wizard = payload.get("configurationWizard") or {}
116
- if wizard.get("intent"):
117
- return
118
- solvea._curl("PUT", f"/api_v2/gpt/project/{solvea.project_id}", {
119
- "configurationWizard": {"intent": True}
120
- })
121
- print("[NOTICE] 该租户意图功能(Intent)原本未开启,已自动启用")
122
-
123
-
124
- def check_and_enable_variable_feature(solvea: SolveaClient) -> None:
125
- """复制 agent 前确保变量功能已初始化(isInitAiField=true)。
126
-
127
- 查询:POST /api_v2/tars/api/field/manage/guide/record → isInitAiField
128
- 开启:GET /api_v2/tars/api/field/manage/pre/install
129
- """
130
- resp = solvea._curl("POST", "/api_v2/tars/api/field/manage/guide/record")
131
- payload = resp.get("data", resp) or {}
132
- if payload.get("isInitAiField"):
133
- return
134
- solvea._curl("GET", "/api_v2/tars/api/field/manage/pre/install")
135
- print("[NOTICE] 该租户变量功能(AI Field)原本未开启,已自动初始化预装字段")
136
-
137
-
138
- # ── Marketplace agent lookup ───────────────────────────────────────────────────
139
-
140
- def copy_marketplace_agent_by_id(solvea: SolveaClient, square_agent_id: int) -> str:
141
- """直接按广场 agent ID 克隆到当前租户,返回新 agent_id。
142
-
143
- POC 按固定 squareAgent_id 复制广场 agent,取代"查广场→按名字匹配"。
144
- 链路,避免广场 agent 名字漂移。
145
- """
146
- result = solvea._curl("POST", "/api_v2/gpt/ap/copyAgent", {
147
- "projectId": int(solvea.project_id),
148
- "agentId": int(square_agent_id),
149
- })
150
- new_id = str(
151
- result.get("id") or
152
- result.get("agentId") or
153
- result.get("data", {}).get("id", "")
154
- )
155
- if not new_id:
156
- raise RuntimeError(f"copyAgent(square_agent_id={square_agent_id}) returned no id: {result}")
157
- print(f"[copy_agent] square_id={square_agent_id} → new id={new_id}")
158
- return new_id
159
-
160
-
161
- # ── L1 intent creation ─────────────────────────────────────────────────────────
162
-
163
- def _intent_items(result) -> list:
164
- if isinstance(result, list):
165
- return result
166
- if isinstance(result, dict):
167
- for key in ("data", "list", "records"):
168
- if isinstance(result.get(key), list):
169
- return result[key]
170
- return []
171
-
172
-
173
- def _find_existing_intent_by_name(solvea: SolveaClient, name: str) -> dict | None:
174
- result = solvea.list_intents()
175
- for item in _intent_items(result):
176
- if isinstance(item, dict) and item.get("name") == name:
177
- intent_id = item.get("id") or item.get("intentId")
178
- if intent_id:
179
- return item
180
- return None
181
-
182
-
183
- def create_l1_intent(
184
- solvea: SolveaClient,
185
- intent: dict,
186
- dry_run: bool = False,
187
- existing_by_name: dict | None = None,
188
- ) -> dict | None:
189
- name = intent["name"]
190
- definition = intent.get("definition") or f"Customer messages related to {name}."
191
- data = {
192
- "name": name,
193
- "description": definition,
194
- "example": definition,
195
- "status": "ENABLED",
196
- }
197
- if dry_run:
198
- print(f"[dry-run] create_intent: {name}")
199
- return None
200
-
201
- existing = (existing_by_name or {}).get(name)
202
- if existing:
203
- intent_id = existing.get("id") or existing.get("intentId")
204
- print(f"[create_intent] existing same-name intent found, reusing id={intent_id} name={name}")
205
- return {"id": intent_id, **existing}
206
-
207
- print(f"[create_intent] {name} ...")
208
- try:
209
- result = solvea.create_intent(data)
210
- except RuntimeError as exc:
211
- if "already exists" not in str(exc):
212
- raise
213
- existing = _find_existing_intent_by_name(solvea, name)
214
- if not existing:
215
- raise
216
- intent_id = existing.get("id") or existing.get("intentId")
217
- print(f"[create_intent] already exists, reusing id={intent_id} name={name}")
218
- return {"id": intent_id, **existing}
219
- intent_id = result.get("id") or result.get("intentId")
220
- if not intent_id:
221
- if "already exists" in str(result.get("errmsg", "")):
222
- existing = _find_existing_intent_by_name(solvea, name)
223
- if existing:
224
- intent_id = existing.get("id") or existing.get("intentId")
225
- print(f"[create_intent] already exists, reusing id={intent_id} name={name}")
226
- result["id"] = intent_id
227
- if not intent_id:
228
- raise RuntimeError(f"create_intent returned no id for '{name}': {result}")
229
- else:
230
- print(f"[create_intent] OK → id={intent_id}")
231
- return result
232
-
233
-
234
- # ── Strategy creation ──────────────────────────────────────────────────────────
235
-
236
- def create_strategy_for_intent(
237
- solvea: SolveaClient,
238
- intent_id: str,
239
- agent_id: str,
240
- intent_name: str,
241
- dry_run: bool = False,
242
- ) -> dict | None:
243
- if dry_run:
244
- print(f"[dry-run] create_strategy: intent={intent_id} → agent={agent_id}")
245
- return None
246
- data = {
247
- "name": f"Route_{intent_name}",
248
- "status": "ENABLED",
249
- "priority": 0,
250
- "trigger": "MESSAGE",
251
- "condition": {
252
- "and": [{
253
- "rules": [{
254
- "apiName": "__intent_ids",
255
- "apiType": "TEXT",
256
- "relation": "IN",
257
- "type": "GENERIC",
258
- "values": [int(intent_id)],
259
- }]
260
- }]
261
- },
262
- "action": {
263
- "type": "AGENT",
264
- "agentId": int(agent_id),
265
- },
266
- }
267
- print(f"[create_strategy] Route_{intent_name} ...")
268
- result = solvea.create_strategy(data)
269
- strategy_id = result.get("id") or result.get("strategyId")
270
- if not strategy_id:
271
- raise RuntimeError(
272
- f"create_strategy returned no id for '{intent_name}' "
273
- f"(intent={intent_id}, agent={agent_id}): {result}"
274
- )
275
- print(f"[create_strategy] OK → id={strategy_id}")
276
- return result
277
-
278
-
279
- def create_strategy_for_intents(
280
- solvea: SolveaClient,
281
- intent_ids: list,
282
- agent_id: str,
283
- name: str,
284
- priority: int = 0,
285
- dry_run: bool = False,
286
- ) -> dict | None:
287
- """N 个意图 → 1 个 agent 的策略(rules.values 多值)。POC 模式专用。"""
288
- if not intent_ids:
289
- raise ValueError(f"create_strategy_for_intents '{name}': intent_ids is empty")
290
- if dry_run:
291
- print(f"[dry-run] create_strategy: intents={intent_ids} → agent={agent_id} (priority={priority})")
292
- return None
293
- data = {
294
- "name": f"Route_{name}",
295
- "status": "ENABLED",
296
- "priority": priority,
297
- "trigger": "MESSAGE",
298
- "condition": {
299
- "and": [{
300
- "rules": [{
301
- "apiName": "__intent_ids",
302
- "apiType": "TEXT",
303
- "relation": "IN",
304
- "type": "GENERIC",
305
- "values": [int(i) for i in intent_ids],
306
- }]
307
- }]
308
- },
309
- "action": {
310
- "type": "AGENT",
311
- "agentId": int(agent_id),
312
- },
313
- }
314
- print(f"[create_strategy] Route_{name} (intents={intent_ids}, priority={priority}) ...")
315
- result = solvea.create_strategy(data)
316
- strategy_id = result.get("id") or result.get("strategyId")
317
- if not strategy_id:
318
- raise RuntimeError(
319
- f"create_strategy returned no id for '{name}' "
320
- f"(intents={intent_ids}, agent={agent_id}): {result}"
321
- )
322
- print(f"[create_strategy] OK → id={strategy_id}")
323
- return result
324
-
325
-
326
- # ── Disable SYSTEM intents ────────────────────────────────────────────────────
327
-
328
- def disable_system_intents(solvea: SolveaClient, keep_names: set, dry_run: bool = False) -> int:
329
- """Disable SYSTEM-source intents whose name is not in keep_names."""
330
- result = solvea.list_intents()
331
- intents = result if isinstance(result, list) else result.get("data", result.get("list", []))
332
- to_disable = [
333
- i for i in intents
334
- if i.get("source") == "SYSTEM"
335
- and i.get("name") not in keep_names
336
- and i.get("status") != "DISABLED"
337
- ]
338
- print(f"[disable_system] {len(to_disable)} SYSTEM intents to disable "
339
- f"(keeping {len(keep_names)} by name match)")
340
- for i in to_disable:
341
- if dry_run:
342
- print(f"[dry-run] disable intent: {i['name']} id={i['id']}")
343
- else:
344
- solvea.toggle_intent(i["id"], enabled=False)
345
- print(f"[disable_system] disabled: {i['name']} id={i['id']}")
346
- return len(to_disable)
347
-
348
-
349
- # ── POC handlers ──────────────────────────────────────────────────────────────
350
-
351
- def _run_poc_business(
352
- solvea: SolveaClient,
353
- all_intents: list,
354
- run_id: str,
355
- dry_run: bool = False,
356
- ) -> None:
357
- """POC 业务阶段:建全部意图 + 克隆 3 个固定广场 agent + 建 3 条业务策略。
358
-
359
- 其余意图标 fallback_pending,等 agent-builder 的 chatflow 能力建好兜底 agent 后回调
360
- `_run_poc_fallback_link` 绑定兜底策略。
361
- """
362
- creation_log = []
363
- intent_name_to_id: dict = {}
364
- existing_by_name = {}
365
- if not dry_run:
366
- existing_by_name = {
367
- item.get("name"): item
368
- for item in _intent_items(solvea.list_intents())
369
- if isinstance(item, dict) and item.get("name") and (item.get("id") or item.get("intentId"))
370
- }
371
-
372
- print(f"\n[poc.business] Step 1/3 — create {len(all_intents)} intents")
373
- for intent in all_intents:
374
- name = intent["name"]
375
- intent_result = create_l1_intent(
376
- solvea,
377
- intent,
378
- dry_run=dry_run,
379
- existing_by_name=existing_by_name,
380
- )
381
- intent_id = str(intent_result.get("id")) if intent_result else f"dry_{name}"
382
- intent_name_to_id[name] = intent_id
383
- creation_log.append({
384
- "intent_name": name,
385
- "intent_id": intent_id,
386
- "agent_id": None,
387
- "strategy_id": None,
388
- "binding": None,
389
- "fallback_pending": True,
390
- })
391
-
392
- print(f"\n[poc.business] Step 2/3 — clone {len(POC_AGENT_BINDINGS)} marketplace agents + create business strategies")
393
- preset_agent_errors = []
394
- for binding in POC_AGENT_BINDINGS:
395
- bname = binding["name"]
396
- target_intent_names = binding["intents"]
397
- square_id = binding["square_agent_id"]
398
- bound_intent_ids = [intent_name_to_id[n] for n in target_intent_names if n in intent_name_to_id]
399
- missing = [n for n in target_intent_names if n not in intent_name_to_id]
400
- if missing:
401
- print(f"[poc.business] WARNING binding '{bname}': intents not created: {missing}; skipping binding")
402
- continue
403
- if not bound_intent_ids:
404
- print(f"[poc.business] WARNING binding '{bname}': no intents to bind; skipping")
405
- continue
406
-
407
- if dry_run:
408
- print(f"[dry-run] copyAgent(square_id={square_id}) for binding '{bname}'")
409
- agent_id = f"dry_agent_{bname}"
410
- else:
411
- try:
412
- agent_id = copy_marketplace_agent_by_id(solvea, square_id)
413
- except Exception as exc:
414
- preset_agent_errors.append({
415
- "binding": bname,
416
- "square_agent_id": square_id,
417
- "intent_names": target_intent_names,
418
- "intent_ids": bound_intent_ids,
419
- "error": str(exc),
420
- })
421
- print(
422
- f"[poc.business] PRESET_AGENT_MISSING binding={bname} "
423
- f"square_agent_id={square_id}: {exc}"
424
- )
425
- break
426
-
427
- if preset_agent_errors:
428
- break
429
-
430
- strategy_result = create_strategy_for_intents(
431
- solvea, bound_intent_ids, agent_id, bname, priority=0, dry_run=dry_run
432
- )
433
- strategy_id = str(strategy_result.get("id")) if strategy_result else f"dry_strategy_{bname}"
434
-
435
- for item in creation_log:
436
- if item["intent_name"] in target_intent_names:
437
- item["agent_id"] = agent_id
438
- item["strategy_id"] = strategy_id
439
- item["binding"] = bname
440
- item["fallback_pending"] = False
441
-
442
- if preset_agent_errors:
443
- fallback_pending = [item for item in creation_log if item["fallback_pending"]]
444
- fallback_pending_intent_ids = [item["intent_id"] for item in fallback_pending]
445
- print(
446
- f"\n[poc.business] Step 3/3 — preset agent unavailable; "
447
- f"{len(fallback_pending)} intent(s) remain pending"
448
- )
449
-
450
- OUTPUTS_DIR.mkdir(parents=True, exist_ok=True)
451
- log_path = str(OUTPUTS_DIR / f"created_{timestamp()}.json")
452
- with open(log_path, "w", encoding="utf-8") as f:
453
- json.dump({
454
- "intents": creation_log,
455
- "mode": "poc",
456
- "run_id": run_id,
457
- "fallback_pending_intent_ids": fallback_pending_intent_ids,
458
- "fallback_strategy": None,
459
- "preset_agent_errors": preset_agent_errors,
460
- "next_action": (
461
- "Ask the user whether to build new CHAT_FLOW business agents "
462
- "from scratch or use substitute existing agents, then continue "
463
- "with agent-builder or an explicit agent mapping."
464
- ),
465
- }, f, ensure_ascii=False, indent=2)
466
-
467
- state = _read_state()
468
- state.update({
469
- "status": "preset_agent_missing",
470
- "mode": "poc",
471
- "created_log_path": log_path,
472
- "preset_agent_errors": preset_agent_errors,
473
- "updated_at": timestamp(),
474
- })
475
- _write_state(state)
476
-
477
- print(f"\n[poc.business] Recoverable stop. Log → {log_path}")
478
- print("[poc.business] Do not report this as a hard system blocker.")
479
- print("[poc.business] Ask the user to choose one option:")
480
- print(" 1. Build new CHAT_FLOW business agents from scratch for the missing preset binding(s).")
481
- print(" 2. Use existing substitute agent id(s) for the affected business binding(s).")
482
- print(f"[poc.business] Pending intent IDs ({len(fallback_pending_intent_ids)}): {fallback_pending_intent_ids}")
483
- return
484
-
485
- fallback_pending = [item for item in creation_log if item["fallback_pending"]]
486
- fallback_pending_intent_ids = [item["intent_id"] for item in fallback_pending]
487
- print(f"\n[poc.business] Step 3/3 — write log; {len(fallback_pending)} intent(s) pending fallback binding")
488
-
489
- OUTPUTS_DIR.mkdir(parents=True, exist_ok=True)
490
- log_path = str(OUTPUTS_DIR / f"created_{timestamp()}.json")
491
- with open(log_path, "w", encoding="utf-8") as f:
492
- json.dump({
493
- "intents": creation_log,
494
- "mode": "poc",
495
- "run_id": run_id,
496
- "fallback_pending_intent_ids": fallback_pending_intent_ids,
497
- "fallback_strategy": None,
498
- }, f, ensure_ascii=False, indent=2)
499
-
500
- state = _read_state()
501
- state.update({
502
- "status": "created",
503
- "mode": "poc",
504
- "created_log_path": log_path,
505
- "updated_at": timestamp(),
506
- })
507
- _write_state(state)
508
-
509
- # Report SYSTEM intents that could be disabled.
510
- if not dry_run:
511
- our_names = {item["intent_name"] for item in creation_log}
512
- result2 = solvea.list_intents()
513
- intents2 = result2 if isinstance(result2, list) else result2.get("data", result2.get("list", []))
514
- pending_disable = [
515
- i for i in intents2
516
- if i.get("source") == "SYSTEM"
517
- and i.get("name") not in our_names
518
- and i.get("status") != "DISABLED"
519
- ]
520
- if pending_disable:
521
- print(f"\n[system_intents] {len(pending_disable)} SYSTEM intents can be disabled:")
522
- for i in pending_disable:
523
- print(f" id={i['id']} name={i['name']}")
524
- print("[system_intents] Run with --disable-system to disable them.")
525
- else:
526
- print("\n[system_intents] No active SYSTEM intents to disable.")
527
-
528
- print(f"\n[poc.business] Done. Log → {log_path}")
529
- print(f"[poc.business] Summary:")
530
- for item in creation_log:
531
- if item["fallback_pending"]:
532
- print(f" {item['intent_name']}: intent={item['intent_id']} (fallback-pending)")
533
- else:
534
- print(f" {item['intent_name']}: intent={item['intent_id']} "
535
- f"agent={item['agent_id']} strategy={item['strategy_id']} binding={item['binding']}")
536
- print(f"\n[poc.business] Next step: build a fallback chatflow agent with agent-builder, then re-invoke:")
537
- print(f" python3 /skills/poc/scripts/create_agents.py --mode poc --poc-fallback-agent-id <new_agent_id>")
538
- print(f"[poc.business] Pending intent IDs ({len(fallback_pending_intent_ids)}): {fallback_pending_intent_ids}")
539
-
540
-
541
- def _run_poc_fallback_link(
542
- solvea: SolveaClient,
543
- log_path: str,
544
- fallback_agent_id: str,
545
- dry_run: bool = False,
546
- ) -> None:
547
- """POC 兜底阶段:把 fallback_pending 的意图绑定到 chatflow 兜底 agent。"""
548
- if not log_path or not os.path.exists(log_path):
549
- raise FileNotFoundError(
550
- f"created_log not found (state.created_log_path={log_path}). "
551
- "Run `--mode poc` business stage first."
552
- )
553
- with open(log_path) as f:
554
- log_data = json.load(f)
555
-
556
- if log_data.get("mode") != "poc":
557
- raise RuntimeError(f"created_log mode is {log_data.get('mode')!r}, expected 'poc'.")
558
- if log_data.get("fallback_strategy"):
559
- existing = log_data["fallback_strategy"]
560
- print(f"[poc.fallback] WARNING fallback strategy already linked: "
561
- f"agent={existing.get('agent_id')} strategy={existing.get('strategy_id')}")
562
- print(f"[poc.fallback] Re-binding (will create another strategy). Disable the old one manually if needed.")
563
-
564
- pending_ids = log_data.get("fallback_pending_intent_ids") or []
565
- if not pending_ids:
566
- print("[poc.fallback] No fallback_pending_intent_ids in log — nothing to bind.")
567
- return
568
-
569
- print(f"[poc.fallback] Binding {len(pending_ids)} intent(s) → agent {fallback_agent_id} "
570
- f"(priority={POC_FALLBACK_STRATEGY_PRIORITY})")
571
- strategy_result = create_strategy_for_intents(
572
- solvea, pending_ids, str(fallback_agent_id), name="Fallback",
573
- priority=POC_FALLBACK_STRATEGY_PRIORITY, dry_run=dry_run,
574
- )
575
- strategy_id = str(strategy_result.get("id")) if strategy_result else "dry_strategy_Fallback"
576
-
577
- log_data["fallback_strategy"] = {
578
- "agent_id": str(fallback_agent_id),
579
- "strategy_id": strategy_id,
580
- "intent_ids": pending_ids,
581
- "name": "Route_Fallback",
582
- "priority": POC_FALLBACK_STRATEGY_PRIORITY,
583
- }
584
- for item in log_data.get("intents", []):
585
- if item.get("intent_id") in pending_ids:
586
- item["strategy_id"] = strategy_id
587
- item["agent_id"] = str(fallback_agent_id)
588
- item["binding"] = "Fallback"
589
- item["fallback_pending"] = False
590
-
591
- with open(log_path, "w", encoding="utf-8") as f:
592
- json.dump(log_data, f, ensure_ascii=False, indent=2)
593
-
594
- state = _read_state()
595
- state.update({
596
- "status": "created",
597
- "mode": "poc",
598
- "created_log_path": log_path,
599
- "updated_at": timestamp(),
600
- })
601
- _write_state(state)
602
-
603
- print(f"\n[poc.fallback] Done. Strategy id={strategy_id}; log updated → {log_path}")
604
-
605
-
606
- def _load_agent_map(path: str) -> dict:
607
- if not path or not os.path.exists(path):
608
- raise FileNotFoundError(f"custom agent map not found: {path}")
609
- with open(path, encoding="utf-8") as f:
610
- data = json.load(f)
611
- if isinstance(data, dict) and isinstance(data.get("bindings"), dict):
612
- data = data["bindings"]
613
- if not isinstance(data, dict):
614
- raise ValueError("custom agent map must be a JSON object or {'bindings': {...}}")
615
- return {str(k): str(v) for k, v in data.items() if v not in (None, "")}
616
-
617
-
618
- def _run_poc_custom_agent_link(
619
- solvea: SolveaClient,
620
- log_path: str,
621
- map_path: str,
622
- dry_run: bool = False,
623
- ) -> None:
624
- """把用户确认的新建/替代业务 Agent 按 POC binding 写入策略。"""
625
- if not log_path or not os.path.exists(log_path):
626
- raise FileNotFoundError(
627
- f"created_log not found (state.created_log_path={log_path}). "
628
- "Run `--mode poc` business stage first."
629
- )
630
- with open(log_path, encoding="utf-8") as f:
631
- log_data = json.load(f)
632
- if log_data.get("mode") != "poc":
633
- raise RuntimeError(f"created_log mode is {log_data.get('mode')!r}, expected 'poc'.")
634
-
635
- agent_map = _load_agent_map(map_path)
636
- intents_by_name = {
637
- item.get("intent_name"): item
638
- for item in log_data.get("intents", [])
639
- if item.get("intent_name") and item.get("intent_id")
640
- }
641
- linked = []
642
- for binding in POC_AGENT_BINDINGS:
643
- bname = binding["name"]
644
- agent_id = agent_map.get(bname)
645
- if not agent_id:
646
- continue
647
- target_items = [intents_by_name[name] for name in binding["intents"] if name in intents_by_name]
648
- intent_ids = [item["intent_id"] for item in target_items]
649
- if not intent_ids:
650
- print(f"[poc.custom] WARNING binding '{bname}' has no matching created intents; skipped")
651
- continue
652
- print(f"[poc.custom] Binding {bname}: intents={intent_ids} → agent {agent_id}")
653
- strategy_result = create_strategy_for_intents(
654
- solvea,
655
- intent_ids,
656
- str(agent_id),
657
- name=bname,
658
- priority=0,
659
- dry_run=dry_run,
660
- )
661
- strategy_id = str(strategy_result.get("id")) if strategy_result else f"dry_strategy_{bname}"
662
- for item in target_items:
663
- item["agent_id"] = str(agent_id)
664
- item["strategy_id"] = strategy_id
665
- item["binding"] = bname
666
- item["fallback_pending"] = False
667
- item["custom_agent"] = True
668
- linked.append({"binding": bname, "agent_id": str(agent_id), "intent_ids": intent_ids, "strategy_id": strategy_id})
669
-
670
- if not linked:
671
- raise ValueError(
672
- "custom agent map did not match any POC binding. "
673
- f"Expected keys: {[b['name'] for b in POC_AGENT_BINDINGS]}"
674
- )
675
-
676
- fallback_pending = [item for item in log_data.get("intents", []) if item.get("fallback_pending")]
677
- log_data["fallback_pending_intent_ids"] = [item["intent_id"] for item in fallback_pending]
678
- log_data["custom_agent_strategies"] = [*(log_data.get("custom_agent_strategies") or []), *linked]
679
- log_data["next_action"] = "Build/link fallback agent for remaining fallback_pending_intent_ids, then continue KB/test."
680
-
681
- with open(log_path, "w", encoding="utf-8") as f:
682
- json.dump(log_data, f, ensure_ascii=False, indent=2)
683
-
684
- state = _read_state()
685
- state.update({
686
- "status": "created",
687
- "mode": "poc",
688
- "created_log_path": log_path,
689
- "updated_at": timestamp(),
690
- })
691
- _write_state(state)
692
- print(f"\n[poc.custom] Done. Linked {len(linked)} business binding(s); log updated → {log_path}")
693
-
694
-
695
- # ── Main ───────────────────────────────────────────────────────────────────────
696
-
697
- def main():
698
- parser = argparse.ArgumentParser(
699
- description="Create intents + copy marketplace agents + strategy routing"
700
- )
701
- parser.add_argument("--mode", choices=["poc"], default="poc",
702
- help="POC only: create all intents, clone 3 fixed marketplace agents, "
703
- "build 3 business strategies, expose fallback_pending_intent_ids "
704
- "for agent-builder chatflow handoff.")
705
- parser.add_argument("--select", default=None,
706
- help="DEPRECATED — ignored in all modes (all intents are now created).")
707
- parser.add_argument("--poc-fallback-agent-id", dest="poc_fallback_agent_id", default=None,
708
- help="POC fallback-link stage: bind a previously-built chatflow agent "
709
- "to all fallback_pending intents. Must run after `--mode poc` "
710
- "business stage. Requires --mode poc.")
711
- parser.add_argument("--custom-agent-map", default=None,
712
- help="POC recovery stage: JSON map of POC binding name to custom/existing agent id, "
713
- "for example {'Package_Logistics': 2641, 'PreSales': 2642, 'Product': 2643}.")
714
- parser.add_argument("--dry-run", action="store_true")
715
- parser.add_argument("--disable-system", action="store_true",
716
- help="Disable active SYSTEM intents not matching created intent names")
717
- args = parser.parse_args()
718
-
719
- # ── Early args sanity ──────────────────────────────────────────────────────
720
- if args.poc_fallback_agent_id and args.mode != "poc":
721
- print(f"[main] ERROR: --poc-fallback-agent-id requires --mode poc (got {args.mode!r}).")
722
- sys.exit(2)
723
- if args.custom_agent_map and args.poc_fallback_agent_id:
724
- print("[main] ERROR: --custom-agent-map and --poc-fallback-agent-id are separate stages.")
725
- sys.exit(2)
726
- if args.select:
727
- print(f"[main] WARNING: --select is deprecated and ignored (mode={args.mode}). "
728
- "All intents will be created.")
729
-
730
- state = _read_state()
731
- if not state:
732
- raise FileNotFoundError(
733
- "No state found. Run classify.py first (state should contain run_id and results_path)."
734
- )
735
-
736
- run_id = state.get("run_id")
737
- if not run_id:
738
- raise ValueError("state.run_id missing. Re-run classify.py.")
739
-
740
- # ── Disable-only mode ──────────────────────────────────────────────────────
741
- if args.disable_system:
742
- log_path = state.get("created_log_path")
743
- if not log_path or not os.path.exists(log_path):
744
- raise FileNotFoundError(
745
- f"No creation log found (state.created_log_path={log_path}). "
746
- "Run without --disable-system first."
747
- )
748
- with open(log_path) as f:
749
- existing_log = json.load(f)
750
- our_names = {item["intent_name"] for item in existing_log.get("intents", [])}
751
- solvea = SolveaClient()
752
- print(f"[main] Disable-only mode. project_id={solvea.project_id}")
753
- disable_system_intents(solvea, keep_names=our_names, dry_run=args.dry_run)
754
- return
755
-
756
- if args.mode == "poc" and args.poc_fallback_agent_id:
757
- solvea = SolveaClient()
758
- if not args.dry_run:
759
- print(f"[main] project_id={solvea.project_id}")
760
- _run_poc_fallback_link(
761
- solvea,
762
- log_path=state.get("created_log_path"),
763
- fallback_agent_id=args.poc_fallback_agent_id,
764
- dry_run=args.dry_run,
765
- )
766
- return
767
-
768
- if args.mode == "poc" and args.custom_agent_map:
769
- solvea = SolveaClient()
770
- if not args.dry_run:
771
- print(f"[main] project_id={solvea.project_id}")
772
- _run_poc_custom_agent_link(
773
- solvea,
774
- log_path=state.get("created_log_path"),
775
- map_path=args.custom_agent_map,
776
- dry_run=args.dry_run,
777
- )
778
- return
779
-
780
- results = load_results(state)
781
- all_intents = results.get("intents", []) + results.get("new_intents", [])
782
- print(f"[main] {len(all_intents)} intents loaded, run_id={run_id} (mode={args.mode})")
783
-
784
- if not all_intents:
785
- print("[main] No intents found. Run classify.py first.")
786
- return
787
-
788
- solvea = SolveaClient()
789
- if not args.dry_run:
790
- print(f"[main] project_id={solvea.project_id}")
791
-
792
- # ── 兜底补全固定 7 个意图 ─────────────────────────────────────────────────
793
- # 客户数据里如果没有某个固定意图的样本,classify.py 不会产生它;
794
- # POC 要建全部 7 个标准意图,这里强制补入缺失的(fallback-link 阶段跳过)。
795
- found_names = {i["name"] for i in all_intents}
796
- for fixed_name in STANDARD_INTENT_NAMES:
797
- if fixed_name not in found_names:
798
- print(f"[main] '{fixed_name}' missing from classification results → added from fixed taxonomy")
799
- all_intents.append({"name": fixed_name, "definition": ""})
800
-
801
- # ── Feature pre-flight ────────────────────────────────────────────────────
802
- if not args.dry_run:
803
- check_and_enable_intent_feature(solvea) # 建意图前
804
- check_and_enable_variable_feature(solvea) # copyAgent 前
805
-
806
- # ── POC business stage ─────────────────────────────────────────────────────
807
- if args.mode == "poc":
808
- _run_poc_business(
809
- solvea,
810
- all_intents=all_intents,
811
- run_id=run_id,
812
- dry_run=args.dry_run,
813
- )
814
- return
815
-
816
-
817
- if __name__ == "__main__":
818
- main()