@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.
- package/README.md +25 -22
- package/dist/cli.js +2202 -127
- package/dist/cli.js.map +1 -1
- package/package.json +19 -6
- package/capabilities.lock.json +0 -898
- 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,41 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Render a concise POC progress / deliverables summary."""
|
|
3
|
-
import os, sys
|
|
4
|
-
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"))
|
|
5
|
-
from bootstrap import * # noqa: F401,F403
|
|
6
|
-
|
|
7
|
-
import json
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
STATE_FILE = STATE_DIR / "progress.json"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def main() -> None:
|
|
14
|
-
if not STATE_FILE.exists():
|
|
15
|
-
print("POC progress not found. Run `python3 /skills/poc/scripts/plan.py --init` first.")
|
|
16
|
-
return
|
|
17
|
-
state = json.loads(STATE_FILE.read_text(encoding="utf-8"))
|
|
18
|
-
print("# POC Progress Summary")
|
|
19
|
-
print(f"- status: `{state.get('status', 'empty')}`")
|
|
20
|
-
print(f"- tenant: `{state.get('tenant') or '-'}`")
|
|
21
|
-
print(f"- brand: `{state.get('brand_name') or '-'}`")
|
|
22
|
-
intent = state.get("intent") or {}
|
|
23
|
-
fallback = state.get("fallback_agent") or {}
|
|
24
|
-
kb = state.get("kb") or {}
|
|
25
|
-
test = state.get("test") or {}
|
|
26
|
-
if intent.get("classification_report_path"):
|
|
27
|
-
print(f"- classification report: `{intent['classification_report_path']}`")
|
|
28
|
-
if intent.get("created_log_path"):
|
|
29
|
-
print(f"- created log: `{intent['created_log_path']}`")
|
|
30
|
-
if fallback.get("agent_id"):
|
|
31
|
-
print(f"- fallback agent: `{fallback.get('agent_name') or '-'} ({fallback['agent_id']})`")
|
|
32
|
-
if kb.get("enabled"):
|
|
33
|
-
print(f"- kb qa plan: `{kb.get('qa_plan_path') or '-'}`")
|
|
34
|
-
if test.get("manual_path"):
|
|
35
|
-
print(f"- POC manual: `{test['manual_path']}`")
|
|
36
|
-
if test.get("results_path"):
|
|
37
|
-
print(f"- test results: `{test['results_path']}`")
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if __name__ == "__main__":
|
|
41
|
-
main()
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: runtime-inspector
|
|
3
|
-
description: Solvea Kit 运行时自检套件。覆盖沙箱机制、模型行为和 CXClaw 前端消息渲染。仅 canary/dev channel 启用。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Runtime Inspector
|
|
7
|
-
|
|
8
|
-
执行前必须先调用 `cxclaw.capabilities`。只有返回 `runtime-inspector: true` 时才继续;stable channel 或生产环境必须拒绝执行。
|
|
9
|
-
|
|
10
|
-
按 **domain × scenario** 路由到具体测试入口。本 SKILL.md 只做路由,不写测试细节。
|
|
11
|
-
|
|
12
|
-
## 反问机制
|
|
13
|
-
|
|
14
|
-
用户说"测试运行时"/"自检"/"测沙箱"等模糊指令时,先反问让用户选 domain:
|
|
15
|
-
|
|
16
|
-
> 想测哪类?
|
|
17
|
-
> - **sandbox**:环境变量、目录挂载、虚拟路径、bash 执行链路、依赖库、跨轮持久化
|
|
18
|
-
> - **model**:LLM 输出截断(max_tokens)、Claude proxy 连通性
|
|
19
|
-
> - **frontend**:Markdown、消息气泡、连续工具过程、运行/完成/失败状态、Subagent 嵌套
|
|
20
|
-
>
|
|
21
|
-
> 或具体说"测目录持久化"、"测 max_tokens 截断"、"测依赖库"等具体场景,我直接执行对应 scenario。
|
|
22
|
-
|
|
23
|
-
如果用户已经说出具体场景关键词("测挂载"、"测截断"、"测依赖"、"测 Markdown"、"测工具块"、"测 Subagent"、"全量测沙箱"、"全量测前端渲染"),直接走对应 scenario,不再反问。
|
|
24
|
-
|
|
25
|
-
frontend 请求同时命中 `markdown`、`process`、`subagent` 中两个及以上场景,或明确要求“完整/全量”时,统一路由到 `frontend × all`。
|
|
26
|
-
|
|
27
|
-
## 场景路由表
|
|
28
|
-
|
|
29
|
-
| domain | scenario | 触发关键词 | 入口 | 详细文档 |
|
|
30
|
-
|---|---|---|---|---|
|
|
31
|
-
| sandbox | env | 环境变量、注入、安全 | `sandbox_inspect.py --scenario env` | `references/sandbox.md` |
|
|
32
|
-
| sandbox | fs | 目录、读写权限、挂载 | `sandbox_inspect.py --scenario fs` | `references/sandbox.md` |
|
|
33
|
-
| sandbox | execute | bash 执行、CWD、相对路径 | `sandbox_inspect.py --scenario execute` | `references/sandbox.md` |
|
|
34
|
-
| sandbox | paths | 虚拟路径、bash/Python 互通 | `sandbox_inspect.py --scenario paths` | `references/sandbox.md` |
|
|
35
|
-
| sandbox | deps | 依赖库可用性 | `sandbox_inspect.py --scenario deps` | `references/sandbox.md` |
|
|
36
|
-
| sandbox | persistence | 跨轮持久化(两轮测试) | `prepare.py` + `process.py` + `verify_persistence.py` | `references/sandbox.md` |
|
|
37
|
-
| sandbox | claude_proxy | 沙箱内 Claude proxy 连通 | `test_claude_proxy.py` | `references/sandbox.md` |
|
|
38
|
-
| sandbox | all | 沙箱全量(env+fs+execute+paths+deps) | `sandbox_inspect.py` | `references/sandbox.md` |
|
|
39
|
-
| model | truncation | LLM 输出 max_tokens 截断诊断 | `model_inspect.py --scenario truncation` | `references/model.md` |
|
|
40
|
-
| frontend | markdown | Markdown、标题、列表、表格、引用、代码块、链接 | Agent 按 reference 直接输出格式矩阵 | `references/frontend-rendering.md` |
|
|
41
|
-
| frontend | process | 工具块、连续工具、分组、运行、完成、失败、计时、折叠 | Agent 按 reference 调用真实工具 | `references/frontend-rendering.md` |
|
|
42
|
-
| frontend | subagent | Subagent、task、嵌套执行过程、内部消息 | Agent 按 reference 调用 `task` | `references/frontend-rendering.md` |
|
|
43
|
-
| frontend | all | 前端渲染、全量消息格式、完整验收 | 依次执行 markdown + process + subagent | `references/frontend-rendering.md` |
|
|
44
|
-
|
|
45
|
-
涉及脚本的场景均用绝对虚拟路径调用:`npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/<name>.py [args]`
|
|
46
|
-
|
|
47
|
-
## 详细执行步骤
|
|
48
|
-
|
|
49
|
-
- **沙箱场景**(输出判定标准 / 跨轮持久化分两轮的执行流):`/skills/runtime-inspector/references/sandbox.md`
|
|
50
|
-
- **模型场景**(如何触发 max_tokens 截断、查日志判定结果):`/skills/runtime-inspector/references/model.md`
|
|
51
|
-
- **前端渲染场景**(Markdown 矩阵 / 工具分组 / Subagent / 实时与历史一致性):`/skills/runtime-inspector/references/frontend-rendering.md`
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
# Frontend Rendering 场景详细说明
|
|
2
|
-
|
|
3
|
-
端到端验证 CXClaw 对 AI 消息、Markdown、工具事件和 Subagent 事件的实时渲染。这里测试的是真实事件流与刷新后的历史回放,不是静态 HTML。
|
|
4
|
-
|
|
5
|
-
## 执行约束
|
|
6
|
-
|
|
7
|
-
1. 优先在标准版执行并观察;内部员工再切换专业版复核。普通用户只验标准版。
|
|
8
|
-
2. 除了明确的“AI 消息边界”步骤,连续工具调用之间不要输出解释文字。
|
|
9
|
-
3. 测试文件只写入 `/workspace/tmp/runtime-inspector/frontend-rendering/`。
|
|
10
|
-
4. 先观察流式执行过程,再刷新当前会话,确认历史回放的内容、顺序和分组一致。
|
|
11
|
-
5. 不要自行宣称视觉 PASS。执行完输出验收清单,让用户确认实际界面。
|
|
12
|
-
|
|
13
|
-
## scenario `markdown`
|
|
14
|
-
|
|
15
|
-
在一条 AI 消息中原样输出下面的 Markdown 格式矩阵。不要放进一个外层代码块:
|
|
16
|
-
|
|
17
|
-
````markdown
|
|
18
|
-
# 一级标题
|
|
19
|
-
## 二级标题
|
|
20
|
-
### 三级标题
|
|
21
|
-
|
|
22
|
-
普通正文包含 **粗体**、*斜体*、~~删除线~~、`inline_code` 和 [可点击链接](https://example.com/cxclaw-render-test)。
|
|
23
|
-
|
|
24
|
-
> 这是一段引用。
|
|
25
|
-
> 第二行用于检查换行和左侧引用线。
|
|
26
|
-
|
|
27
|
-
- 无序列表第一项
|
|
28
|
-
- 无序列表第二项
|
|
29
|
-
- 二级列表
|
|
30
|
-
|
|
31
|
-
1. 有序列表第一项
|
|
32
|
-
2. 有序列表第二项
|
|
33
|
-
|
|
34
|
-
- [x] 已完成事项
|
|
35
|
-
- [ ] 未完成事项
|
|
36
|
-
|
|
37
|
-
| 字段 | 状态 | 说明 |
|
|
38
|
-
|---|---:|---|
|
|
39
|
-
| Markdown | PASS | 表格、对齐与长文本换行 |
|
|
40
|
-
| Tool block | RUNNING | 等待后续场景 |
|
|
41
|
-
|
|
42
|
-
```json
|
|
43
|
-
{
|
|
44
|
-
"name": "cxclaw-render-test",
|
|
45
|
-
"enabled": true,
|
|
46
|
-
"count": 3
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
printf 'frontend-rendering-ok\n'
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
中英文混排:CXClaw 支持 customer support、订单号 `ORDER-20260717-001`,以及长链接 https://example.com/a/very/long/path/that/must/wrap/inside/the/message/container?source=runtime-inspector&mode=standard 。
|
|
55
|
-
````
|
|
56
|
-
|
|
57
|
-
检查标题字号层级、段落间距、列表缩进、表格横向溢出、代码块滚动、链接点击区域和长文本换行。
|
|
58
|
-
|
|
59
|
-
## scenario `process`
|
|
60
|
-
|
|
61
|
-
### 第一组:连续成功工具
|
|
62
|
-
|
|
63
|
-
连续调用以下工具,中间不输出 AI 文本:
|
|
64
|
-
|
|
65
|
-
1. `execute`:`command` 使用 `mkdir -p /workspace/tmp/runtime-inspector/frontend-rendering && python3 -c 'import time; time.sleep(3); print("timer-ok")'`,`description` 写“等待 3 秒验证运行态计时”。
|
|
66
|
-
2. `write_file`:写入 `/workspace/tmp/runtime-inspector/frontend-rendering/sample.md`,内容固定为 `# Render fixture\n\nSecond line with **bold text**.`。
|
|
67
|
-
3. `ls`:列出 `/workspace/tmp/runtime-inspector/frontend-rendering/`。
|
|
68
|
-
4. `read_file`:读取刚写入的 `sample.md`。
|
|
69
|
-
|
|
70
|
-
观察点:
|
|
71
|
-
|
|
72
|
-
- 四个工具属于同一个过程块。
|
|
73
|
-
- 当前步骤显示旋转图标和递增计时。
|
|
74
|
-
- 完成步骤变为绿色勾,不常驻显示耗时;hover 绿色勾时显示耗时 Tooltip。
|
|
75
|
-
- 全部完成后过程块自动收拢,点击可展开全部步骤。
|
|
76
|
-
- 每个步骤显示与工具类型匹配的图标、友好名称和关键参数摘要。
|
|
77
|
-
|
|
78
|
-
### AI 消息边界
|
|
79
|
-
|
|
80
|
-
第一组结束后,单独输出一条 AI 消息:
|
|
81
|
-
|
|
82
|
-
> 过程分组边界:第一组结束,下面开始第二组。
|
|
83
|
-
|
|
84
|
-
然后再调用工具。该 AI 消息必须截断前一个过程块,后续工具进入新过程块。
|
|
85
|
-
|
|
86
|
-
### 第二组:失败状态
|
|
87
|
-
|
|
88
|
-
调用 `execute`,`command` 使用 `sh -c 'echo intentional-render-error >&2; exit 7'`,`description` 写“触发预期失败状态”。这是预期失败;收到工具错误后不要重试,继续输出一句“预期失败已返回,前端渲染测试继续。”,用于确认错误不阻断后续 AI 消息。
|
|
89
|
-
|
|
90
|
-
观察失败图标、错误文案、过程块展开状态,以及错误后最终 AI 消息是否正常显示。
|
|
91
|
-
|
|
92
|
-
## scenario `subagent`
|
|
93
|
-
|
|
94
|
-
调用一次 `task` / General Purpose Subagent,任务说明使用下面的要求:
|
|
95
|
-
|
|
96
|
-
```text
|
|
97
|
-
这是 CXClaw 前端渲染自检。先用 ls 查看 /skills/runtime-inspector,再用 read_file 读取 /skills/runtime-inspector/SKILL.md;两次工具调用之间不要输出解释文字。然后输出一句“Subagent AI 消息边界”。最后用 grep 在 /skills/runtime-inspector/SKILL.md 中搜索 frontend。不要修改任何文件。
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
观察点:
|
|
101
|
-
|
|
102
|
-
- Subagent 是独立过程块,不与外层普通工具混排。
|
|
103
|
-
- Subagent 内部连续工具按同一规则聚合。
|
|
104
|
-
- Subagent 内部 AI 消息会截断内部过程组,后续工具新开一组。
|
|
105
|
-
- 外层和内层各自展示运行、完成和耗时状态,不出现重复 footer。失败状态由 `process` scenario 单独覆盖。
|
|
106
|
-
|
|
107
|
-
如果当前 runtime 没有 `task` 工具,明确报告“当前运行时不支持 Subagent 渲染场景”,不要用普通工具伪造 Subagent。
|
|
108
|
-
|
|
109
|
-
## scenario `all`
|
|
110
|
-
|
|
111
|
-
按 `markdown` → `process` → `subagent` 顺序直接执行,不额外添加阶段标题或开场说明。`process` 中规定的 AI 边界消息必须保留;禁止在要求连续的工具调用之间插入说明。
|
|
112
|
-
|
|
113
|
-
## 验收清单
|
|
114
|
-
|
|
115
|
-
| 检查项 | PASS 条件 |
|
|
116
|
-
|---|---|
|
|
117
|
-
| 用户消息 | 深色气泡;skill 使用图标 + skill 名,不显示 `/skill-name` |
|
|
118
|
-
| AI 消息 | Markdown 层级正确;最后一条消息只有一行操作栏 |
|
|
119
|
-
| 连续工具 | 无 AI 消息时聚合为一个过程块 |
|
|
120
|
-
| AI 边界 | AI 消息前后拆成两个过程块 |
|
|
121
|
-
| 运行步骤 | 旋转图标 + 实时计时 |
|
|
122
|
-
| 完成步骤 | 绿色勾;仅 hover 显示耗时 |
|
|
123
|
-
| 失败步骤 | 错误状态明确且不影响后续消息 |
|
|
124
|
-
| Subagent | 独立块;内部递归应用相同分组规则 |
|
|
125
|
-
| 标准/专业 | 标准版精简、专业版保留明细,消息内容一致 |
|
|
126
|
-
| 历史回放 | 刷新后顺序、分组、状态和 Markdown 与实时态一致 |
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# Model 场景详细说明
|
|
2
|
-
|
|
3
|
-
测试 LLM 在当前 endpoint 配置下的运行时行为。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## scenario `truncation` — max_tokens 截断诊断
|
|
8
|
-
|
|
9
|
-
### 背景
|
|
10
|
-
|
|
11
|
-
LLM 一次输出超过 endpoint 配置的 `max_tokens` 时会被强制停止(`stop_reason=max_tokens`)。
|
|
12
|
-
若被截断的恰好是 `tool_use` 调用的 input JSON,会出现 tool 入参不完整的错误,例如:
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
Error invoking tool 'write_file' with kwargs {'file_path': '...'} with error:
|
|
16
|
-
content: Field required
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
`file_path` 已生成、`content` 还没生成完就被切断 → schema 校验失败。这种问题用日志才能定性。
|
|
20
|
-
|
|
21
|
-
### 触发方式
|
|
22
|
-
|
|
23
|
-
`model_inspect.py --scenario truncation` 让 LLM 主动构造一个**会消耗大量输出 token 的 write_file 调用**:
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/model_inspect.py --scenario truncation
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
脚本只是**给 agent 一个引导文本**——告诉 agent 用 write_file 写一个长 markdown 内容到 `/workspace/tmp/runtime-inspector/truncation_test.md`,要求 ≥6000 字英文 lorem ipsum 段落。
|
|
30
|
-
|
|
31
|
-
是否真触发取决于当前 endpoint 的 `max_tokens` 配置:
|
|
32
|
-
- `max_tokens` ≤ 4096 → 几乎必触发
|
|
33
|
-
- `max_tokens` ≥ 16384 → 难触发,需要更夸张的 content(agent 可主动加大要求)
|
|
34
|
-
|
|
35
|
-
### 判定(看日志)
|
|
36
|
-
|
|
37
|
-
服务进程日志里搜 `SLG model_response`:
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
SLG model_response req=... chat=... stop_reason=end_turn output_tokens=3500 tool_calls=1
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
- `stop_reason=end_turn` / `tool_use`:正常完成,**没截断**
|
|
44
|
-
- `stop_reason=max_tokens` / `length`:**触发了截断**,会同时打 ⚠ warning 行:
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
⚠ SLG output truncated by max_tokens req=... output_tokens=4096 — increase endpoint max_tokens or split the work
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### 修复方向
|
|
51
|
-
|
|
52
|
-
1. **endpoint 配置层**:`settings.local.yaml` / Nacos 给对应 endpoint 加 `max_tokens` 字段(claude sonnet/haiku 4 系列上限 64000,建议 32000)
|
|
53
|
-
2. **skill 流程层**:避免单次 LLM 输出超大 content。例如 kb-builder 的 qa_plan 应分批写到 `qa_plan_part_NN.json`,由脚本合并
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## scenario `claude_proxy` — Claude Proxy 连通性
|
|
58
|
-
|
|
59
|
-
不属于 model domain,归在 sandbox(沙箱内通过 internal proxy 调 Claude),见 `references/sandbox.md`。
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
# Sandbox 场景详细说明
|
|
2
|
-
|
|
3
|
-
端到端验证沙箱的环境变量、目录结构、bash 执行链路、依赖库、跨轮持久化。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 单轮检查
|
|
8
|
-
|
|
9
|
-
`sandbox_inspect.py` 支持全量或单项 scenario:
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
# 全量(默认,等价于 --scenario all)
|
|
13
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/sandbox_inspect.py
|
|
14
|
-
|
|
15
|
-
# 仅环境变量注入与安全校验
|
|
16
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/sandbox_inspect.py --scenario env
|
|
17
|
-
|
|
18
|
-
# 仅目录结构与读写权限
|
|
19
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/sandbox_inspect.py --scenario fs
|
|
20
|
-
|
|
21
|
-
# 仅 bash 执行路径行为(CWD、$WORKSPACE_DIR、相对路径写文件)
|
|
22
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/sandbox_inspect.py --scenario execute
|
|
23
|
-
|
|
24
|
-
# 仅虚拟路径行为(bash/Python 路径映射对齐)
|
|
25
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/sandbox_inspect.py --scenario paths
|
|
26
|
-
|
|
27
|
-
# 仅依赖库可用性
|
|
28
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/sandbox_inspect.py --scenario deps
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### 各 scenario 检查内容
|
|
32
|
-
|
|
33
|
-
| scenario | 主要校验项 |
|
|
34
|
-
|----------|-----------|
|
|
35
|
-
| `env` | WORKSPACE_DIR 路径可写、SOLVEA_LIB_DIR 路径存在、Anthropic / OpenAI proxy 地址非真实端点、敏感变量安全 |
|
|
36
|
-
| `fs` | workspace/outputs/state/tmp 可写;mounted 目录逻辑只读(OS 可写属正常);skills 文件只读 |
|
|
37
|
-
| `execute` | CWD 为沙箱根、bash 能读 $WORKSPACE_DIR/$SOLVEA_LIB_DIR、相对路径写文件 Python 可读、python3 来自 venv |
|
|
38
|
-
| `paths` | WORKSPACE/MOUNTED_USER/MOUNTED_TENANT 路径存在;OUTPUTS_DIR/STATE_DIR/TMP_DIR 父目录存在;bash/Python 路径写读互通 |
|
|
39
|
-
| `deps` | anthropic/httpx/pandas/openpyxl 等库是否可 import(不可用记录为 ⬜,非错误) |
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## Internal Claude Proxy 测试
|
|
44
|
-
|
|
45
|
-
单独验证沙箱内能否通过 internal proxy 调用 Claude,不依赖 sandbox_inspect 全量:
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/test_claude_proxy.py
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
打印 `ANTHROPIC_BASE_URL`、实际发一条 haiku 请求,输出 `PASS model=... in=... out=... elapsed=...s` 或 `FAIL error=...`。
|
|
52
|
-
|
|
53
|
-
## Internal OpenAI Proxy 测试
|
|
54
|
-
|
|
55
|
-
验证沙箱内能否通过 internal proxy 调用 OpenAI-compatible 模型:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/test_openai_proxy.py
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
模型由主服务的 Nacos 配置统一决定。输出 `PASS model=...` 表示代理与模型权限均正常。
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## 持久化两轮测试
|
|
66
|
-
|
|
67
|
-
验证前一次对话写入的 outputs/state 在新对话中是否可用。**仅在用户明确要求时才执行,不要在单轮检查后自动继续。**
|
|
68
|
-
|
|
69
|
-
### 第一次对话:写入数据
|
|
70
|
-
|
|
71
|
-
#### 步骤 1 — 准备数据
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
# 有用户文件
|
|
75
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/prepare.py --source /mounted/chat-files/user/{文件名}
|
|
76
|
-
|
|
77
|
-
# 无用户文件(自动生成测试数据)
|
|
78
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/prepare.py
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
#### 步骤 2 — 处理并写入
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/process.py
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
#### 步骤 3 — 确认写入正常
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/sandbox_inspect.py --scenario fs
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
确认 `workspace/outputs/` 和 `workspace/state/` 均 ✅ 可写且有文件。
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
### 第二次对话:验证可用性
|
|
98
|
-
|
|
99
|
-
#### 步骤 A — 跑断言脚本(直接验证 eager 还原)
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/verify_persistence.py
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
脚本直接用 `Path.read_text()` 读 `OUTPUTS_DIR.glob("results_*.json")` 和 `STATE_DIR / "inspect.json"`,**全程不调用 `read_file` 工具**。
|
|
106
|
-
|
|
107
|
-
eager 模型保障:上一轮写入 `workspace/outputs/` 和 `workspace/state/` 的文件,本轮启动时已自动还原到同一路径,脚本直接 `open()` 就能读到。
|
|
108
|
-
|
|
109
|
-
- 全部 ✅ → eager 还原工作正常,跨轮路径稳定
|
|
110
|
-
- 出现 `FileNotFoundError —— eager 还原可能未生效` ❌ → 检查 `_build_file_manifest._restore` 流程 / Java 回调 / S3 上传
|
|
111
|
-
|
|
112
|
-
#### 步骤 B — 全量检查(可选)
|
|
113
|
-
|
|
114
|
-
```bash
|
|
115
|
-
npx --yes @shulex/cxclawctl@latest script skills/runtime-inspector/scripts/sandbox_inspect.py --scenario fs
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
`fs` scenario 中"上一轮 agent outputs"项会显示 `workspace/outputs/runtime-inspector/` 下文件数量,可肉眼对照第一轮的 process.py 输出。
|
|
119
|
-
|
|
120
|
-
---
|
|
121
|
-
|
|
122
|
-
## 判断标准
|
|
123
|
-
|
|
124
|
-
| 检查项 | PASS 条件 |
|
|
125
|
-
|--------|-----------|
|
|
126
|
-
| `--scenario env` | RESULT: ✅ PASS,无 ❌ |
|
|
127
|
-
| `--scenario fs` | workspace 目录均 ✅ 可写,mounted 目录存在 |
|
|
128
|
-
| `--scenario execute` | CWD 对齐、bash 变量可读、写文件 Python 可读、python3 来自 venv |
|
|
129
|
-
| `--scenario deps` | 核心库(anthropic/httpx)✅,sandbox 组库不可用属正常 |
|
|
130
|
-
| 步骤 A read_file results | 返回内容包含 records 数组 |
|
|
131
|
-
| 步骤 B verify_persistence | 全部断言输出 ✅ PASS |
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
model_inspect.py — runtime-inspector 的 model 域入口。
|
|
4
|
-
|
|
5
|
-
scenarios:
|
|
6
|
-
truncation — 引导 agent 触发 max_tokens 截断;脚本本身不真的调 LLM,
|
|
7
|
-
只输出一个引导任务,由 agent 在沙箱外用 write_file 工具执行。
|
|
8
|
-
|
|
9
|
-
Usage:
|
|
10
|
-
python3 /skills/runtime-inspector/scripts/model_inspect.py --scenario truncation
|
|
11
|
-
"""
|
|
12
|
-
from __future__ import annotations
|
|
13
|
-
import argparse, os, sys
|
|
14
|
-
sys.path.insert(0, os.path.join(os.environ["SOLVEA_LIB_DIR"], "skill-runtime"))
|
|
15
|
-
from bootstrap import *
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def scenario_truncation() -> None:
|
|
19
|
-
"""打印一段引导文本,告诉 agent 主动构造一个会消耗大量输出 token 的 write_file。
|
|
20
|
-
|
|
21
|
-
脚本本身不调 LLM、不写文件——agent 看到本脚本输出后,按引导执行 write_file 工具调用。
|
|
22
|
-
实际是否触发 max_tokens 取决于当前 endpoint 的 max_tokens 配置。
|
|
23
|
-
"""
|
|
24
|
-
target = TMP_DIR / "truncation_test.md"
|
|
25
|
-
target.parent.mkdir(parents=True, exist_ok=True)
|
|
26
|
-
print(f"[truncation] target_path={target}")
|
|
27
|
-
print()
|
|
28
|
-
print("=" * 72)
|
|
29
|
-
print("AGENT INSTRUCTION")
|
|
30
|
-
print("=" * 72)
|
|
31
|
-
print()
|
|
32
|
-
print(f"Use the write_file tool to write a long markdown document to:")
|
|
33
|
-
print(f" {target}")
|
|
34
|
-
print()
|
|
35
|
-
print("Content requirements (designed to push past max_tokens):")
|
|
36
|
-
print(" - 60+ paragraphs of English lorem ipsum style technical text")
|
|
37
|
-
print(" - Each paragraph 8-12 sentences")
|
|
38
|
-
print(" - Topic: 'Best practices for distributed systems observability'")
|
|
39
|
-
print(" - Target output length: ~6000 words (~8000 tokens)")
|
|
40
|
-
print()
|
|
41
|
-
print("After invoking write_file, regardless of whether it succeeds or fails:")
|
|
42
|
-
print(" 1. Tell the user to grep service logs for 'SLG model_response'")
|
|
43
|
-
print(" 2. Report the stop_reason and output_tokens shown in that log line")
|
|
44
|
-
print()
|
|
45
|
-
print("Expected outcomes:")
|
|
46
|
-
print(" - stop_reason=end_turn / tool_use → max_tokens is sufficient")
|
|
47
|
-
print(" - stop_reason=max_tokens / length → truncation triggered, see references/model.md")
|
|
48
|
-
print()
|
|
49
|
-
print("Do NOT analyse the resulting file content — this test is about the LLM")
|
|
50
|
-
print("response metadata, not about the document being well-formed.")
|
|
51
|
-
print("=" * 72)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
SCENARIOS = {
|
|
55
|
-
"truncation": scenario_truncation,
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def main() -> int:
|
|
60
|
-
ap = argparse.ArgumentParser()
|
|
61
|
-
ap.add_argument("--scenario", required=True, choices=sorted(SCENARIOS.keys()))
|
|
62
|
-
args = ap.parse_args()
|
|
63
|
-
SCENARIOS[args.scenario]()
|
|
64
|
-
return 0
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if __name__ == "__main__":
|
|
68
|
-
raise SystemExit(main())
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
步骤 1:准备数据,分批写入 /workspace/tmp/runtime-inspector/。
|
|
4
|
-
|
|
5
|
-
- 有 --source 时:读取用户上传的文件(csv/json/txt),解析内容
|
|
6
|
-
- 无 --source 时:自动生成 30 条测试记录
|
|
7
|
-
- 读取 state,展示当前任务状态
|
|
8
|
-
- 将数据按 10 条一批写入 tmp,更新 state → status: batched
|
|
9
|
-
"""
|
|
10
|
-
import os, sys
|
|
11
|
-
sys.path.insert(0, os.path.join(os.environ["SOLVEA_LIB_DIR"], "skill-runtime"))
|
|
12
|
-
from bootstrap import *
|
|
13
|
-
import argparse, csv, io, json
|
|
14
|
-
from datetime import datetime, timezone
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def parse_source(path: str) -> list[dict]:
|
|
18
|
-
"""解析用户上传的文件,支持 json / csv / txt(每行一条)。"""
|
|
19
|
-
p = Path(path)
|
|
20
|
-
if not p.exists():
|
|
21
|
-
raise FileNotFoundError(f"文件不存在: {path}")
|
|
22
|
-
suffix = p.suffix.lower()
|
|
23
|
-
content = p.read_text(encoding="utf-8")
|
|
24
|
-
if suffix == ".json":
|
|
25
|
-
data = json.loads(content)
|
|
26
|
-
if isinstance(data, list):
|
|
27
|
-
return [{"text": str(item)} if not isinstance(item, dict) else item for item in data]
|
|
28
|
-
return [data]
|
|
29
|
-
if suffix == ".csv":
|
|
30
|
-
reader = csv.DictReader(io.StringIO(content))
|
|
31
|
-
return list(reader)
|
|
32
|
-
# txt / 其他:每行一条
|
|
33
|
-
return [{"text": line.strip()} for line in content.splitlines() if line.strip()]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def generate_test_data(n: int = 30) -> list[dict]:
|
|
37
|
-
return [{"id": i + 1, "text": f"测试记录 #{i + 1}", "value": (i + 1) * 10} for i in range(n)]
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def main():
|
|
41
|
-
parser = argparse.ArgumentParser()
|
|
42
|
-
parser.add_argument("--source", default=None, help="用户上传文件路径(可选)")
|
|
43
|
-
parser.add_argument("--batch-size", type=int, default=10)
|
|
44
|
-
args = parser.parse_args()
|
|
45
|
-
|
|
46
|
-
# 读取并展示当前状态
|
|
47
|
-
_state_file = STATE_DIR / "inspect.json"
|
|
48
|
-
state = {}
|
|
49
|
-
if _state_file.exists():
|
|
50
|
-
try:
|
|
51
|
-
state = json.loads(_state_file.read_text(encoding="utf-8"))
|
|
52
|
-
except Exception:
|
|
53
|
-
pass
|
|
54
|
-
if state:
|
|
55
|
-
print(f"[state] 读取到上一轮状态: status={state.get('status')} "
|
|
56
|
-
f"batches={state.get('total_batches')} "
|
|
57
|
-
f"written_at={state.get('written_at', 'N/A')}")
|
|
58
|
-
else:
|
|
59
|
-
print("[state] 首次运行,无历史状态")
|
|
60
|
-
|
|
61
|
-
# 解析或生成数据
|
|
62
|
-
if args.source:
|
|
63
|
-
records = parse_source(args.source)
|
|
64
|
-
print(f"[prepare] 解析用户文件 {args.source} → {len(records)} 条记录")
|
|
65
|
-
else:
|
|
66
|
-
records = generate_test_data(30)
|
|
67
|
-
print(f"[prepare] 自动生成 {len(records)} 条测试数据")
|
|
68
|
-
|
|
69
|
-
# 清空 tmp 目录
|
|
70
|
-
if TMP_DIR.exists():
|
|
71
|
-
import shutil
|
|
72
|
-
shutil.rmtree(TMP_DIR)
|
|
73
|
-
TMP_DIR.mkdir(parents=True, exist_ok=True)
|
|
74
|
-
|
|
75
|
-
# 分批写入 tmp
|
|
76
|
-
batches = [records[i:i + args.batch_size] for i in range(0, len(records), args.batch_size)]
|
|
77
|
-
for idx, batch in enumerate(batches):
|
|
78
|
-
batch_file = TMP_DIR / f"batch_{idx:03d}.json"
|
|
79
|
-
batch_file.write_text(json.dumps(batch, ensure_ascii=False, indent=2), encoding="utf-8")
|
|
80
|
-
print(f"[prepare] 写入 {batch_file.name} ({len(batch)} 条)")
|
|
81
|
-
|
|
82
|
-
# 更新状态
|
|
83
|
-
_sf = STATE_DIR / "inspect.json"
|
|
84
|
-
_sf.parent.mkdir(parents=True, exist_ok=True)
|
|
85
|
-
_sf.write_text(json.dumps({
|
|
86
|
-
"status": "batched",
|
|
87
|
-
"total_records": len(records),
|
|
88
|
-
"total_batches": len(batches),
|
|
89
|
-
"batch_size": args.batch_size,
|
|
90
|
-
"source": args.source or "auto-generated",
|
|
91
|
-
"written_at": datetime.now(timezone.utc).isoformat(),
|
|
92
|
-
}, ensure_ascii=False, indent=2), encoding="utf-8")
|
|
93
|
-
print(f"\n✅ 分批完成: {len(batches)} 个批次写入 {TMP_DIR}")
|
|
94
|
-
print(" 下一步: python3 /skills/runtime-inspector/scripts/process.py")
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if __name__ == "__main__":
|
|
98
|
-
main()
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
步骤 2:读取 tmp 批次文件,处理后写结果到 workspace/outputs/。
|
|
4
|
-
|
|
5
|
-
- 遍历 workspace/tmp/runtime-inspector/batch_*.json
|
|
6
|
-
- 对每条记录做简单处理(模拟业务逻辑)
|
|
7
|
-
- 汇总结果写入 workspace/outputs/runtime-inspector/results.json
|
|
8
|
-
- 更新 state → status: done
|
|
9
|
-
"""
|
|
10
|
-
import os, sys
|
|
11
|
-
sys.path.insert(0, os.path.join(os.environ["SOLVEA_LIB_DIR"], "skill-runtime"))
|
|
12
|
-
from bootstrap import *
|
|
13
|
-
import json
|
|
14
|
-
from datetime import datetime, timezone
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def process_record(record: dict) -> dict:
|
|
18
|
-
"""模拟业务处理:给每条记录加上处理时间戳和摘要。"""
|
|
19
|
-
return {
|
|
20
|
-
**record,
|
|
21
|
-
"_processed": True,
|
|
22
|
-
"_summary": f"processed: {str(record)[:60]}",
|
|
23
|
-
"_at": datetime.now(timezone.utc).isoformat(),
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def main():
|
|
28
|
-
_state_file = STATE_DIR / "inspect.json"
|
|
29
|
-
state = {}
|
|
30
|
-
if _state_file.exists():
|
|
31
|
-
try:
|
|
32
|
-
state = json.loads(_state_file.read_text(encoding="utf-8"))
|
|
33
|
-
except Exception:
|
|
34
|
-
pass
|
|
35
|
-
if state.get("status") != "batched":
|
|
36
|
-
print(f"[process] 当前状态: {state.get('status', '不存在')},需先运行 prepare.py")
|
|
37
|
-
return
|
|
38
|
-
|
|
39
|
-
print(f"[process] 读取状态: {state.get('total_batches')} 批次,"
|
|
40
|
-
f"{state.get('total_records')} 条记录,来源: {state.get('source')}")
|
|
41
|
-
|
|
42
|
-
# 读取所有批次
|
|
43
|
-
batch_files = sorted(TMP_DIR.glob("batch_*.json")) if TMP_DIR.exists() else []
|
|
44
|
-
if not batch_files:
|
|
45
|
-
print(f"[process] ❌ 未找到批次文件: {TMP_DIR}")
|
|
46
|
-
return
|
|
47
|
-
|
|
48
|
-
all_results = []
|
|
49
|
-
for batch_file in batch_files:
|
|
50
|
-
batch = json.loads(batch_file.read_text(encoding="utf-8"))
|
|
51
|
-
processed = [process_record(r) for r in batch]
|
|
52
|
-
all_results.extend(processed)
|
|
53
|
-
print(f"[process] 处理 {batch_file.name}: {len(batch)} 条")
|
|
54
|
-
|
|
55
|
-
# 写结果到 outputs(带时间戳,每轮新建,历史文件保留)
|
|
56
|
-
OUTPUTS_DIR.mkdir(parents=True, exist_ok=True)
|
|
57
|
-
run_ts = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
58
|
-
results_file = OUTPUTS_DIR / f"results_{run_ts}.json"
|
|
59
|
-
results_file.write_text(
|
|
60
|
-
json.dumps({
|
|
61
|
-
"total": len(all_results),
|
|
62
|
-
"processed_at": datetime.now(timezone.utc).isoformat(),
|
|
63
|
-
"source": state.get("source"),
|
|
64
|
-
"records": all_results,
|
|
65
|
-
}, ensure_ascii=False, indent=2),
|
|
66
|
-
encoding="utf-8",
|
|
67
|
-
)
|
|
68
|
-
print(f"\n[process] ✅ 结果写入: {results_file} ({len(all_results)} 条)")
|
|
69
|
-
|
|
70
|
-
# 更新状态
|
|
71
|
-
_sf = STATE_DIR / "inspect.json"
|
|
72
|
-
_sf.parent.mkdir(parents=True, exist_ok=True)
|
|
73
|
-
_sf.write_text(json.dumps({
|
|
74
|
-
"status": "done",
|
|
75
|
-
"total_processed": len(all_results),
|
|
76
|
-
"results_path": str(results_file),
|
|
77
|
-
"done_at": datetime.now(timezone.utc).isoformat(),
|
|
78
|
-
}, ensure_ascii=False, indent=2), encoding="utf-8")
|
|
79
|
-
print("[process] state → status: done")
|
|
80
|
-
print("\n 下一步: python3 /skills/runtime-inspector/scripts/sandbox_inspect.py")
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if __name__ == "__main__":
|
|
84
|
-
main()
|