{"id":"ec4dd2c0-9046-46de-b44a-3ac4a0509828","entityType":"agent","slug":"clawhub-xddcode-insentek-api-skill","name":"insentek-api-skill","canonicalUrl":"https://www.xpersona.co/agent/clawhub-xddcode-insentek-api-skill","canonicalPath":"/agent/clawhub-xddcode-insentek-api-skill","generatedAt":"2026-10-11T20:56:07.273Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:16:29.334Z","emptyReason":null},"description":"通过自然语言查询 insentek（东方智感）物联网设备数据。 支持土壤墒情仪、气象站、见厘液位计等多种设备类型的实时数据、 历史数据、趋势分析、跨设备对比与数据导出。","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s1776e0bqhtsht8hhbrm0y6dvh874b9c:insentek-api-skill","sourceUrl":"https://clawhub.ai/xddcode/insentek-api-skill","homepage":"https://clawhub.ai/xddcode/skills/insentek-api-skill","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/xddcode/insentek-api-skill","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/xddcode/skills/insentek-api-skill","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"insentek-api-skill technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:16:29.334Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:16:29.334Z","emptyReason":null},"stars":null,"forks":null,"downloads":1020,"packageName":null,"latestVersion":"1.2.2","tractionLabel":"1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:16:29.255Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T17:16:29.334Z","lastCrawledAt":"2026-10-11T17:16:29.255Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T17:16:29.255Z","lastVerifiedAt":null,"highlights":[{"version":"1.2.2","createdAt":"2026-05-26T09:35:14.742Z","changelog":"## v1.2.2 — Agent 调用规范与 HTTPS 修正 Agent 误用包名/命令、Python 路径不明确等问题；API 默认切换 HTTPS；新增 `latest` 子命令。 ### 变更 - 统一 `npx @insentek/openapi-skill` 调用，修正引导文案中的错误包名 - `${PYTHON}` 由 `info --json` 的 `python.command` 解析，不再硬编码 `python` - 默认 API 地址改为 `https://openapi.ecois.info` ### 新功能 - `insentek_cli.py latest --sn SN` — 查询设备最新数据 - 统一错误信封 `normalize_error`，WAF HTML 错误页自动截断 ### 修复 - Python 最低版本要求修正为 `>=3.10` - `doctor` 移除无关的 `git` 检测 - 文档结构与 OpenClaw 安装说明修正 ### 升级 ```bash npx @insentek/openapi-skill@1.2.2 install --force npx @insentek/openapi-skill update -y","fileCount":50,"zipByteSize":97571},{"version":"1.2.1","createdAt":"2026-05-26T08:32:33.001Z","changelog":"appid/secret 不再通过对话传递，改为 CLI 本地加密存储；Agent 调用路径与 OpenClaw 安装路径一并修正。 ## 新功能 - npx insentek-api-skill login / logout / auth status — 凭据 AES-256-GCM 加密保存至 ~/.config/insentek/ - status / info --json 输出 scripts.cli 等路径，便于 Agent 定位脚本 ## 变更 - Agent 禁止在对话中索要 appid/secret；401/403 时引导用户执行 login - API 调用统一为 python ${SKILL_ROOT}/scripts/insentek_cli.py ... - OpenClaw workspace 安装路径修正为 ~/.openclaw/workspace/skills/insentek-openapi ## 修复 - Windows --force 覆盖安装 EPERM - Python 与 Node CLI 凭据解密互通 - Agent 误用相对路径或 npx ... devices 等问题 ## 升级 ``` npx @insentek/openapi-skill install --force npx insentek-api-skill login ```","fileCount":50,"zipByteSize":92685},{"version":"1.2.0","createdAt":"2026-05-25T09:33:41.213Z","changelog":"## What's Changed * feat: 持久化存储访问凭据，避免会话间重复输入 by @fre2d0m in https://github.com/insentek/insentek-api-skills/pull/6 ## New Contributors * @fre2d0m made their first contribution in https://github.com/insentek/insentek-api-skills/pull/6 **Full Changelog**: https://github.com/insentek/insentek-api-skills/compare/v1.1.0...v1.2.0","fileCount":17,"zipByteSize":51767},{"version":"1.1.0","createdAt":"2026-05-22T07:45:06.058Z","changelog":"1. skill.md 模块化重构 - 从 1100+ 行瘦身至 241 行（Runtime Contract 风格） - 拆分出 docs/interaction.md（交互规范）和 docs/analysis.md（分析策略） - 解决 Prompt Token 爆炸和 MUST 密度过高问题 2. 分析策略语气降级 - 安全/护栏规则保持 MUST - 分析方法从 MUST 改为 SHOULD / RECOMMENDED / PREFER - 提升 Agent 分析灵活性和创造力 3. 数据可用性校验 - query_data 返回后自动检查实际数据范围 vs 请求范围 - 覆盖不足 50% 或少于 7 天时，必须向用户确认后才生成报告 - 防止\"请求近3个月但设备只有13天数据\"的误导性报告 4. CSV 导出修复 - 修复长数字 SN 在 Excel 中显示为科学计数法的问题 - SN 字段加前导制表符强制文本格式 5. API 文档统一 - 删除 docs/api-reference.md - 统一使用 reference/api-doc.md 作为权威源","fileCount":18,"zipByteSize":51321},{"version":"1.0.2","createdAt":"2026-05-21T07:50:57.649Z","changelog":"- Removed deprecated `report` / `chart` / `export --format html` from `scripts/insentek_cli.py` - Deleted `generate_report()`, `generate_chart()`, `get_device_info()`, `extract_param_names()` (~480 lines) - HTML reports are now fully Agent-generated; no hard-coded templates - Updated docstring and argparse to reflect only csv/json export - Updated `skill.md` - Replaced Section 6.4 `generate_report (DEPRECATED)` with 6.4 `write_html` - Added `write_html.py` to environment check items (non-critical) - Changed API doc reference from active guidance to fallback note in Notes - Updated `--dry-run` note to remove `report` and `chart` - Updated `.planning/STATE.md` - Added `write_html.py` to Utility Scripts list - Removed HTML export from `insentek_cli.py` description","fileCount":18,"zipByteSize":408772},{"version":"1.0.1","createdAt":"2026-05-21T06:04:04.070Z","changelog":"- --dry-run preview mode (scripts/insentek_cli.py) - data, export (csv/json/html), report, chart subcommands all support --dry-run - Only outputs record count, time range, field summary (nodes/parameters), and first 5 sample rows - Does not write files or output full data, preventing context explosion during debugging - --dry-run preview mode (scripts/export_excel.py) - Added --dry-run parameter, behavior consistent with CLI script - Does not generate Excel file, only returns structured JSON preview - Raw data output prohibition (skill.md) - Added Section 2.4 \"Raw Data Output Prohibition\" - Explicitly prohibits Agent from outputting raw sensor full data directly into conversation - Specifies handling for four common scenarios: summary sampling, --dry-run, guided export, direct refusal - YAML Guardrails declaration (skill.md frontmatter) - Added guardrails.raw_data_output: PROHIBITED - Added guardrails.dry_run_preview_rows: 5 - Added guardrails.max_chat_rows: 200 - Added guardrails.max_export_rows: 50000 - Dry-run documentation (skill.md) - Added Section 6.0 \"dry-run preview mode (common to all export scripts)\" - Added --dry-run example in query_data Agent Action - Added \"Dry-run first\" and \"Raw data prohibition\" development guidelines in Notes","fileCount":14,"zipByteSize":408803},{"version":"1.0.0","createdAt":"2026-05-21T02:05:50.258Z","changelog":"insentek-api-skill 2.0.0 — Major Update - Complete rewrite and rebrand as \"insentek-openapi\" with enhanced natural language query support for IoT devices. - Detailed, layered intent resolution (查询/对比/导出/报告) ensures user intentions are always clarified. - Enforces strict query guardrails (time span, data limits, environment pre-checks) to guarantee reliability and usability. - Step-by-step guides for environment setup and robust runtime checks for dependencies and service availability. - Secure, script-driven token authentication flow with conversation-scoped token management. - Expanded documentation with sample dialogs, error handling, tool definitions, and user-friendly feedback for all scenarios.","fileCount":5,"zipByteSize":28636}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s1776e0bqhtsht8hhbrm0y6dvh874b9c:insentek-api-skill","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s1776e0bqhtsht8hhbrm0y6dvh874b9c:insentek-api-skill` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/xddcode/insentek-api-skill before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-xddcode-insentek-api-skill/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-xddcode-insentek-api-skill/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-xddcode-insentek-api-skill/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-xddcode-insentek-api-skill/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-xddcode-insentek-api-skill/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-xddcode-insentek-api-skill/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T20:56:07.271Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-xddcode-insentek-api-skill/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-xddcode-insentek-api-skill/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-xddcode-insentek-api-skill/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-xddcode-insentek-api-skill/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:16:29.334Z","emptyReason":null},"readme":"Skill: insentek-api-skill\n\nOwner: xddcode\n\nSummary: 通过自然语言查询 insentek（东方智感）物联网设备数据。 支持土壤墒情仪、气象站、见厘液位计等多种设备类型的实时数据、 历史数据、趋势分析、跨设备对比与数据导出。\n\nTags: latest:1.2.2\n\nVersion history:\n\nv1.2.2 | 2026-05-26T09:35:14.742Z | user\n\n## v1.2.2 — Agent 调用规范与 HTTPS\r\n\r\n修正 Agent 误用包名/命令、Python 路径不明确等问题；API 默认切换 HTTPS；新增 `latest` 子命令。\r\n\r\n### 变更\r\n- 统一 `npx @insentek/openapi-skill` 调用，修正引导文案中的错误包名\r\n- `${PYTHON}` 由 `info --json` 的 `python.command` 解析，不再硬编码 `python`\r\n- 默认 API 地址改为 `https://openapi.ecois.info`\r\n\r\n### 新功能\r\n- `insentek_cli.py latest --sn SN` — 查询设备最新数据\r\n- 统一错误信封 `normalize_error`，WAF HTML 错误页自动截断\r\n\r\n### 修复\r\n- Python 最低版本要求修正为 `>=3.10`\r\n- `doctor` 移除无关的 `git` 检测\r\n- 文档结构与 OpenClaw 安装说明修正\r\n\r\n### 升级\r\n```bash\r\nnpx @insentek/openapi-skill@1.2.2 install --force\r\nnpx @insentek/openapi-skill update -y\n\nv1.2.1 | 2026-05-26T08:32:33.001Z | user\n\nappid/secret 不再通过对话传递，改为 CLI 本地加密存储；Agent 调用路径与 OpenClaw 安装路径一并修正。\r\n\r\n## 新功能\r\n- npx insentek-api-skill login / logout / auth status — 凭据 AES-256-GCM 加密保存至 ~/.config/insentek/\r\n- status / info --json 输出 scripts.cli 等路径，便于 Agent 定位脚本\r\n## 变更\r\n- Agent 禁止在对话中索要 appid/secret；401/403 时引导用户执行 login\r\n- API 调用统一为 python ${SKILL_ROOT}/scripts/insentek_cli.py ...\r\n- OpenClaw workspace 安装路径修正为 ~/.openclaw/workspace/skills/insentek-openapi\r\n## 修复\r\n- Windows --force 覆盖安装 EPERM\r\n- Python 与 Node CLI 凭据解密互通\r\n- Agent 误用相对路径或 npx ... devices 等问题\r\n\r\n## 升级\r\n\r\n```\r\nnpx @insentek/openapi-skill install --force\r\nnpx insentek-api-skill login\r\n\r\n```\n\nv1.2.0 | 2026-05-25T09:33:41.213Z | user\n\n## What's Changed\r\n* feat: 持久化存储访问凭据，避免会话间重复输入 by @fre2d0m in https://github.com/insentek/insentek-api-skills/pull/6\r\n\r\n## New Contributors\r\n* @fre2d0m made their first contribution in https://github.com/insentek/insentek-api-skills/pull/6\r\n\r\n**Full Changelog**: https://github.com/insentek/insentek-api-skills/compare/v1.1.0...v1.2.0\n\nv1.1.0 | 2026-05-22T07:45:06.058Z | user\n\n1. skill.md 模块化重构\r\n    - 从 1100+ 行瘦身至 241 行（Runtime Contract 风格）\r\n    - 拆分出 docs/interaction.md（交互规范）和 docs/analysis.md（分析策略）\r\n    - 解决 Prompt Token 爆炸和 MUST 密度过高问题\r\n  2. 分析策略语气降级\r\n    - 安全/护栏规则保持 MUST\r\n    - 分析方法从 MUST 改为 SHOULD / RECOMMENDED / PREFER\r\n    - 提升 Agent 分析灵活性和创造力\r\n  3. 数据可用性校验\r\n    - query_data 返回后自动检查实际数据范围 vs 请求范围\r\n    - 覆盖不足 50% 或少于 7 天时，必须向用户确认后才生成报告\r\n    - 防止\"请求近3个月但设备只有13天数据\"的误导性报告\r\n  4. CSV 导出修复\r\n    - 修复长数字 SN 在 Excel 中显示为科学计数法的问题\r\n    - SN 字段加前导制表符强制文本格式\r\n  5. API 文档统一\r\n    - 删除 docs/api-reference.md\r\n    - 统一使用 reference/api-doc.md 作为权威源\n\nv1.0.2 | 2026-05-21T07:50:57.649Z | user\n\n- Removed deprecated `report` / `chart` / `export --format html` from `scripts/insentek_cli.py`\r\n  - Deleted `generate_report()`, `generate_chart()`, `get_device_info()`, `extract_param_names()` (~480 lines)\r\n  - HTML reports are now fully Agent-generated; no hard-coded templates\r\n  - Updated docstring and argparse to reflect only csv/json export\r\n\r\n- Updated `skill.md`\r\n  - Replaced Section 6.4 `generate_report (DEPRECATED)` with 6.4 `write_html`\r\n  - Added `write_html.py` to environment check items (non-critical)\r\n  - Changed API doc reference from active guidance to fallback note in Notes\r\n  - Updated `--dry-run` note to remove `report` and `chart`\r\n\r\n- Updated `.planning/STATE.md`\r\n  - Added `write_html.py` to Utility Scripts list\r\n  - Removed HTML export from `insentek_cli.py` description\n\nv1.0.1 | 2026-05-21T06:04:04.070Z | user\n\n- --dry-run preview mode (scripts/insentek_cli.py)\n  - data, export (csv/json/html), report, chart subcommands all support --dry-run\n  - Only outputs record count, time range, field summary (nodes/parameters), and first 5 sample rows\n  - Does not write files or output full data, preventing context explosion during debugging\n\n- --dry-run preview mode (scripts/export_excel.py)\n  - Added --dry-run parameter, behavior consistent with CLI script\n  - Does not generate Excel file, only returns structured JSON preview\n\n- Raw data output prohibition (skill.md)\n  - Added Section 2.4 \"Raw Data Output Prohibition\"\n  - Explicitly prohibits Agent from outputting raw sensor full data directly into conversation\n  - Specifies handling for four common scenarios: summary sampling, --dry-run, guided export, direct refusal\n\n- YAML Guardrails declaration (skill.md frontmatter)\n  - Added guardrails.raw_data_output: PROHIBITED\n  - Added guardrails.dry_run_preview_rows: 5\n  - Added guardrails.max_chat_rows: 200\n  - Added guardrails.max_export_rows: 50000\n\n- Dry-run documentation (skill.md)\n  - Added Section 6.0 \"dry-run preview mode (common to all export scripts)\"\n  - Added --dry-run example in query_data Agent Action\n  - Added \"Dry-run first\" and \"Raw data prohibition\" development guidelines in Notes\n\nv1.0.0 | 2026-05-21T02:05:50.258Z | user\n\ninsentek-api-skill 2.0.0 — Major Update\n\n- Complete rewrite and rebrand as \"insentek-openapi\" with enhanced natural language query support for IoT devices.\n- Detailed, layered intent resolution (查询/对比/导出/报告) ensures user intentions are always clarified.\n- Enforces strict query guardrails (time span, data limits, environment pre-checks) to guarantee reliability and usability.\n- Step-by-step guides for environment setup and robust runtime checks for dependencies and service availability.\n- Secure, script-driven token authentication flow with conversation-scoped token management.\n- Expanded documentation with sample dialogs, error handling, tool definitions, and user-friendly feedback for all scenarios.\n\nArchive index:\n\nArchive v1.2.2: 50 files, 97571 bytes\n\nFiles: CHANGELOG.md (12000b), CLAUDE.md (1214b), docs/analysis.md (4559b), docs/getting-started.md (4209b), docs/interaction.md (6913b), docs/platform-setup.md (9191b), examples/flows.md (3539b), examples/queries.md (6056b), examples/reports.md (5766b), packages/insentek-skill-cli/bin/insentek-api-skill.js (319b), packages/insentek-skill-cli/lib/cli.js (15271b), packages/insentek-skill-cli/lib/commands/auth.js (910b), packages/insentek-skill-cli/lib/commands/doctor.js (4851b), packages/insentek-skill-cli/lib/commands/login.js (2552b), packages/insentek-skill-cli/lib/commands/logout.js (653b), packages/insentek-skill-cli/lib/commands/status.js (2139b), packages/insentek-skill-cli/lib/constants.js (521b), packages/insentek-skill-cli/lib/copy.js (3678b), packages/insentek-skill-cli/lib/core/credentials.js (6738b), packages/insentek-skill-cli/lib/core/installer.js (1817b), packages/insentek-skill-cli/lib/core/manifest.js (932b), packages/insentek-skill-cli/lib/core/resolver.js (1237b), packages/insentek-skill-cli/lib/core/scope.js (2015b), packages/insentek-skill-cli/lib/os.js (872b), packages/insentek-skill-cli/lib/output.js (4299b), packages/insentek-skill-cli/lib/python.js (544b), packages/insentek-skill-cli/lib/runtime/claude.js (1204b), packages/insentek-skill-cli/lib/runtime/index.js (1491b), packages/insentek-skill-cli/lib/runtime/openclaw.js (1656b), packages/insentek-skill-cli/lib/script-paths.js (332b), packages/insentek-skill-cli/lib/utils.js (1900b), packages/insentek-skill-cli/package-lock.json (17394b), packages/insentek-skill-cli/package.json (1047b), packages/insentek-skill-cli/README.md (4064b), packages/insentek-skill-cli/scripts/sync-assets.js (2227b), packages/insentek-skill-cli/test/cli-json.test.js (2870b), packages/insentek-skill-cli/test/copy.test.js (3368b), packages/insentek-skill-cli/test/credentials.test.js (2571b), packages/insentek-skill-cli/test/runtime.test.js (2816b), README.md (8241b), reference/api-doc.md (28346b), scripts/credential_store.py (5146b), scripts/export_excel.py (9192b), scripts/insentek_cli.py (26901b), scripts/README.md (4246b), scripts/write_html.py (6398b), skill-card.md (2822b), skill.json (203b), SKILL.md (14349b), _meta.json (137b)\n\nFile v1.2.2:SKILL.md\n\n---\nname: insentek-openapi\nversion: 1.2.2\ndescription: >\n  通过自然语言查询 insentek（东方智感）物联网设备数据。\n  支持土壤墒情仪、气象站、见厘液位计等多种设备类型的实时数据、\n  历史数据、趋势分析、跨设备对比与数据导出。\napi_base_url: https://openapi.ecois.info\nauthor: insentek-api-skills\nguardrails:\n  raw_data_output: PROHIBITED\n  dry_run_preview_rows: 5\n  max_chat_rows: 200\n  max_export_rows: 50000\n---\n\n<!--\n  Note: `api_base_url` above is informational only; it is not consumed by\n  any script. To override at runtime, set the INSENTEK_API_BASE environment\n  variable before invoking scripts/insentek_cli.py.\n-->\n\n\n# Insentek OpenAPI Skill\n\n> 轻量 Runtime Contract。完整交互规范见 `docs/interaction.md`，分析策略见 `docs/analysis.md`。\n> 兼容平台：OpenClaw、Hermes-Agent、Claude Code、ChatGPT\n\n---\n\n## 1. Routing\n\n用户意图 → 工具路由：\n\n| L1 意图 | L2 输出 | 调用 |\n|---------|---------|------|\n| 查询数据 | 对话展示 | `query_device` → `query_data` → 按输出格式回复 |\n| 查询数据 | 文件导出 | `query_device` → `export_*` → 返回文件路径 |\n| 生成报告 | 文件导出 | `query_device` → `query_data` → 分析 → `write_html` |\n| 对比设备 | 对话展示 | `query_device` (xN) → `query_data` (xN) → 对比表格 |\n| 对比设备 | 文件导出 | `query_device` (xN) → `query_data` (xN) → `export_excel` |\n\n**任何一层意图不明确时，MUST 向用户确认，不得假设。** 详见 `docs/interaction.md` Section 1。\n\n---\n\n## 2. Tools\n\n**认证约束（MUST）：** Agent **禁止**向用户索要 `appid` 或 `secret`，也 **禁止**在对话中接收、存储或回显这些凭据。凭据仅通过 CLI 在本地配置：\n\n```bash\nnpx @insentek/openapi-skill login       # 配置（加密保存）\nnpx @insentek/openapi-skill logout      # 清除\nnpx @insentek/openapi-skill auth status # 查看连接状态\n```\n\n> npm 包名为 `@insentek/openapi-skill`（已发布到 npm registry）。`insentek-api-skill` 是它的可执行别名，**仅在该包已被安装时**可用。**所有 `npx` 调用都应使用 scoped 包名** `@insentek/openapi-skill`，否则未安装的用户机器会得到 \"npm ERR! 404\"。\n\n### 命令分工（MUST）\n\n| 用途 | 工具 | 示例 |\n|------|------|------|\n| 安装 / 更新 skill | `npx @insentek/openapi-skill` | `install -r openclaw -s workspace -y` |\n| 配置 / 清除凭据 | `npx @insentek/openapi-skill login/logout` | `npx @insentek/openapi-skill login` |\n| 查连接状态 | `npx @insentek/openapi-skill auth status` | — |\n| 查安装路径 / 脚本位置 | `npx @insentek/openapi-skill info/status/doctor --json` | 见下方「脚本路径解析」 |\n| **查询 API** | `python3 <SKILL_ROOT>/scripts/insentek_cli.py` | `python3 .../insentek_cli.py devices` |\n\n### 脚本路径解析（MUST，API 调用前）\n\nAgent 工作目录通常**不是** skill 安装目录。**禁止**使用相对路径 `python3 scripts/insentek_cli.py ...`。\n\n**首次 API 调用前**，或脚本路径未知 / 返回「文件找不到」时，**必须先**查实际安装位置。`info --json` 会列出所有 runtime × scope 的解析结果及 `installed` 标记，无需提前知道用户是哪种安装：\n\n```bash\nnpx @insentek/openapi-skill info --json\n```\n\n从输出中遍历 `runtimes[].scopes[]`，挑选第一个 `installed: true` 的条目，将其 `installDir` 作为 `${SKILL_ROOT}`，将 `scripts.cli` / `scripts.exportExcel` / `scripts.writeHtml` 作为脚本绝对路径，并将 `python.command`（如 `python3` / `py` / `python`）作为 `${PYTHON}`。解析后在**本会话内缓存**，后续 API 调用复用，**不要**重复猜测路径。\n\n如果用户已经明确告诉过你 runtime / scope（例如刚刚 `install -r openclaw -s workspace -y`），也可以用 `status --json` 精确查询：\n\n```bash\nnpx @insentek/openapi-skill status -r openclaw -s workspace --json\n# 或 -r claude -s global / -s project，按用户场景选择\n```\n\nOpenClaw workspace 常见路径（仅供参考，**以 info/status 返回为准**）：\n`~/.openclaw/workspace/skills/insentek-openapi`\n\n**禁止（MUST NOT）：**\n- `python3 scripts/insentek_cli.py ...` — 相对路径在 OpenClaw 等环境下会失败\n- `npx insentek-api-skill ...` — npm registry 上没有这个包名，对未安装本包的新用户会 404\n- `npx @insentek/openapi-skill devices` — `devices` 不是顶层命令，会被 commander 当成 `install` 的子命令而触发安装流程\n- 文件找不到时乱试其它命令 — **应重新 `info --json`**\n\n用户说「配置好了，继续吧」→ 从**中断前的意图**继续；若已有 `${SKILL_ROOT}` 直接调 API，**不要**重新 login。\n\n若工具返回 `authentication_required` 或 HTTP 401/403，**STOP** 并 **原样** 向用户展示以下固定文案（不得改写、不得追加索要 secret）：\n\n```\n这台电脑还没有连接 Insentek API，需要先完成一次本地配置，通常 1 分钟就好。\n\n请在终端运行：\n\nnpx @insentek/openapi-skill login\n\n按提示输入 appid 和 secret 即可（加密保存在本机，无需发到这个对话）。配置完成后回来继续提问，我接着帮你处理。\n```\n\n---\n\n### query_device\n\n查询设备信息：列表、详情、别名解析。\n\n```json\n{\n  \"page\": { \"type\": \"integer\", \"default\": 1 },\n  \"limit\": { \"type\": \"integer\", \"default\": 20 },\n  \"sn\": { \"type\": \"string\", \"description\": \"设备序列号，与 alias 二选一\" },\n  \"alias\": { \"type\": \"string\", \"description\": \"设备别名，支持部分匹配\" }\n}\n```\n\n```bash\n# 列表（${SKILL_ROOT} / ${PYTHON} 由 info --json 解析，见上方）\n${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py devices [--page ${page}] [--limit ${limit}]\n# 详情\n${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py device --sn ${sn}\n```\n\n> `${PYTHON}` 在 macOS/Linux 默认为 `python3`，Windows 默认为 `python`（亦可为 `py`）；以 `info --json` 输出的 `python.command` 为准。**禁止**使用裸 `python`——在 macOS 系统默认配置、新版 Ubuntu/Fedora 等环境下 `python` 命令不存在或指向 Python 2，会直接失败。\n\n**注意：** `--token` 变为可选。若未提供且已配置持久化凭据，脚本自动获取。\n\n**行为：** alias → 模糊匹配 → 多匹配时反问用户 → 单匹配时缓存 alias→sn 映射。\n\n---\n\n### query_data\n\n查询设备历史数据或实时数据。\n\n```json\n{\n  \"sn\": { \"type\": \"string\", \"required\": true },\n  \"time_expression\": { \"type\": \"string\", \"description\": \"自然语言时间描述，如'现在'、'昨天'、'最近7天'。不传默认最近24小时。\" },\n  \"range\": { \"type\": \"string\", \"description\": \"YYYYMMDD,YYYYMMDD，由 time_expression 自动计算\" },\n  \"includeParameters\": { \"type\": \"string\", \"description\": \"指定参数，逗号分隔，如 moisture,temperature\" }\n}\n```\n\n```bash\n# 历史数据\n${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py data --sn ${sn} --range ${range} [--include-params ${params}]\n\n# 预览（调试/验证用）\n${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py data --sn ${sn} --range ${range} --dry-run\n\n# 实时数据（latest）\n${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py latest --sn ${sn}\n```\n\n**注意：** `--token` 变为可选。若未提供且已配置持久化凭据，脚本自动获取。\n\n时间表达式解析见 `docs/interaction.md` Section 2。\n\n---\n\n### export_csv / export_excel / export_json\n\n用户意图明确为\"导出/下载\"时调用，而非 `query_data`。\n\n```bash\n# CSV\n${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py export --sn ${sn} --range ${range} --format csv --output ${file}.csv\n\n# Excel\n${PYTHON} ${SKILL_ROOT}/scripts/export_excel.py --sn ${sn} --range ${range} --output ${file}.xlsx\n\n# JSON\n${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py export --sn ${sn} --range ${range} --format json --output ${file}.json\n```\n\n**注意：** `--token` 变为可选。若未提供且已配置持久化凭据，脚本自动获取。\n\n所有导出脚本均支持 `--dry-run`。\n\n---\n\n### write_html\n\nAgent 完成数据分析后，将动态生成的 HTML 内容写入文件。**推荐**使用 `--input-file` 避免 shell 转义吞掉换行 / 引号 / 反斜杠：\n\n```bash\n# 1. 先把 HTML 内容写到临时文件（写文件工具按平台决定）\n#    e.g. write to /tmp/report.html or %TEMP%\\report.html\n# 2. 然后调用 write_html.py 落盘\n${PYTHON} ${SKILL_ROOT}/scripts/write_html.py --input-file ${tmp_html} --output ${file}.html\n\n# 也支持 stdin（注意 echo 会破坏 HTML 中的换行/引号，仅用于简单片段）：\necho \"${html_content}\" | ${PYTHON} ${SKILL_ROOT}/scripts/write_html.py --output ${file}.html\n```\n\n---\n\n## 3. Guardrails\n\n### 3.1 硬限制\n\n| 限制项 | 规则 | 超限处理 |\n|--------|------|----------|\n| 单次查询跨度 | ≤ 365 天 | 拒绝，提供拆分选项 |\n| 历史回溯 | ≤ 3 年 | 拒绝，提示最早日期 |\n| 对话展示 | ≤ 200 条 | 展示摘要 + 首尾各 10 条抽样 |\n| 文件导出 | ≤ 50,000 条 | 拒绝，建议缩小范围或分批 |\n\n### 3.2 数据可用性校验（MUST）\n\n`query_data` 返回后，检查实际数据范围 vs 请求范围：\n\n```\nrequested_days = 用户请求的天数\nactual_days    = 实际返回数据的天数\ncoverage       = actual_days / requested_days\n\nIF coverage < 0.5 OR actual_days < 7:\n  → STOP\n  → 告知用户实际范围，询问是否继续\n  → 等待确认后才可生成报告/分析\nELSE IF actual_range < requested_range:\n  → 继续，但报告 MUST 使用 actual_range 标注\n```\n\n### 3.3 原始数据输出禁令（MUST）\n\nAgent **禁止**将原始传感器全量数据输出到对话中。\n\n| 场景 | 处理 |\n|------|------|\n| \"看看数据\" | 统计摘要 + 首尾各 5 条 |\n| \"调试\" | `--dry-run` 预览 |\n| \"给我原始数据\" | 引导导出 CSV/Excel |\n| \"全部发给我\" | 拒绝，解释 Token 限制 |\n\n完整输出格式规范见 `docs/interaction.md` Section 4。\n\n---\n\n## 4. Authentication\n\n### 4.1 CLI 本地凭据（唯一方式）\n\n用户 **必须** 通过 CLI 在本地配置凭据，Agent **不得** 在对话中收集 appid/secret：\n\n```bash\nnpx @insentek/openapi-skill login\nnpx @insentek/openapi-skill logout\nnpx @insentek/openapi-skill auth status\n```\n\n凭据加密保存在 `~/.config/insentek/credentials.json`（文件权限 600）。\n\n### 4.2 Agent 行为约束（MUST）\n\n| 场景 | Agent 行为 |\n|------|-----------|\n| 用户首次使用 / 未连接 | 展示 Section 2 固定引导文案，**禁止**索要 secret |\n| 用户主动发送 appid/secret | **拒绝接收**，说明请改用 CLI login |\n| 401/403 / `authentication_required` | 展示 Section 2 固定引导文案，STOP |\n| 用户要求\"重新认证\" | 引导 `npx @insentek/openapi-skill login`（更新）或 `logout` 后再 `login` |\n\n### 4.3 Token 获取策略\n\n脚本**管理 token 生命周期**，实现缓存 + 自动刷新机制：\n- CLI `login` 验证凭据后，凭据和 token 一并加密保存\n- 后续各命令 `--token` 参数变为可选\n- 未提供 `--token` 时，脚本**优先从配置文件读取缓存的 token**\n- 请求 API 时如果返回 401/403，脚本**自动刷新 token** 并重试一次\n- 刷新失败则返回 `authentication_required`，Agent 引导用户重新 `login`\n- 不检查 token 过期时间，靠 HTTP 401/403 触发刷新\n\n### 4.4 Token 缓存流程\n\n```\n请求 API\n  ├── 使用缓存 token\n  ├── 成功 → 返回数据\n  └── 401/403 → 调用 /v3/token 获取新 token → 更新配置文件 → 重试请求\n        └── 仍失败 → 返回 authentication_required → 引导 CLI login\n```\n\n### 4.5 安全说明\n\n- Secret **绝不**出现在对话、日志或 Agent 上下文中\n- 凭据文件权限 600，内容 AES-256-GCM 加密（机器绑定密钥）\n- Token 缓存有效期约 2 小时，靠 HTTP 401/403 触发自动刷新\n\n---\n\n**向后兼容：** 所有命令仍支持 `--token` 参数，现有调用方式不受影响。\n\n---\n\n## 5. Environment Check\n\n首次交互前，在解析 `${SKILL_ROOT}` / `${PYTHON}` 后执行：\n\n```bash\n${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py check\n```\n\n关键项失败时 STOP，可选项失败时降级运行并告知用户。\n\n若 `${PYTHON}` 解析失败（`info --json` 的 `python.ok` 为 `false`），说明本机没有可用的 Python 3.10+，**STOP** 并原样向用户展示：\n\n```\n当前电脑没有可用的 Python（需要 3.10 或更高版本）。请先安装 Python：\n\n- macOS: brew install python\n- Ubuntu/Debian: sudo apt install python3 python3-pip\n- Fedora: sudo dnf install python3\n- Windows: 到 https://www.python.org/downloads/ 下载安装包，安装时勾选 \"Add Python to PATH\"\n\n安装完成后请回来继续提问，我接着帮你处理。\n```\n\n若 `checks.credentials.ok` 为 `false`，展示 Section 2 固定引导文案，**禁止**继续调用 API 或向用户索要 secret。\n\n---\n\n## 6. Error Handling\n\n| HTTP | 处理 |\n|------|------|\n| 200 | 正常处理 |\n| 400 | 检查参数格式后重试 |\n| 401/403 | **STOP**，展示 CLI login 引导文案，**禁止**向用户索要 secret |\n| 脚本找不到 / ENOENT | **STOP**，执行 `status --json` 或 `info --json` 解析 `${SKILL_ROOT}`，**禁止**乱试 npx 子命令 |\n| 404 | 确认设备 SN/别名 |\n| 429 | 限流，等待后重试 |\n| 500 | 指数退避重试 3 次 |\n\n脚本返回 `\"success\": false` 且 `error` 为 `authentication_required` 时，展示 Section 2 固定引导文案并 STOP。其他错误解析 `error`/`message` 字段：含\"范围/限制\"则解释护栏，否则展示友好错误。\n\n---\n\n## Notes\n\n- **Pagination**: `page` starts at 1.\n- **Values**: Nested `{node_name: {parameter_code: value}}`\n- **Alias**: Case-insensitive partial match on `alias`.\n- **Param names**: Use Chinese names from `/description` endpoint for display.\n- **Script-first**: API 用 `${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py`；`${SKILL_ROOT}` 和 `${PYTHON}` 由 `info --json` 解析（`runtimes[].scopes[]` 中 `installed: true` 的条目对应 `installDir` / `scripts.cli` / `python.command`）\n- **Dry-run**: Append `--dry-run` for preview; never output raw data to chat.\n- **Reference**: Edge cases → `reference/api-doc.md` (OpenAPI v3.1.9).\n\nFile v1.2.2:packages/insentek-skill-cli/README.md\n\n# @insentek/openapi-skill\n\nBootstrap the **insentek-openapi** skill for **OpenClaw** and **Claude Code**.\n\n| 类型 | 名称 |\n|------|------|\n| npm package | `@insentek/openapi-skill` |\n| skill id | `insentek-openapi` |\n| 安装目录 | `insentek-openapi` |\n| CLI 命令 | `insentek-api-skill` |\n\n安装路径由 CLI **按 runtime + scope 动态解析**。用 `info` / `doctor` 查看本机实际路径。\n\n## Quick Start\n\n```bash\nnpx @insentek/openapi-skill\n```\n\n## OpenClaw 用户：ClawHub 安装（独立方式）\n\nOpenClaw 用户也可通过 ClawHub 单独安装，与本 CLI 无关：\n\n```bash\nclawhub skill install insentek-api-skill\nclawhub skill remove insentek-api-skill\n```\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `install` | 安装 skill（默认命令，可交互选择 runtime） |\n| `login` | 配置 Insentek API 凭据（加密本地保存） |\n| `logout` | 清除已保存的凭据 |\n| `auth status` | 查看凭据连接状态 |\n| `update` | 更新已安装 skill 到当前包版本 |\n| `uninstall` | 卸载 |\n| `status` | 查看安装状态 |\n| `doctor` | 诊断路径、manifest、脚本与环境 |\n| `info` | 查看 package / skill / 动态解析路径 |\n\n## Options\n\n| Option | Description |\n|--------|-------------|\n| `-r, --runtime` | `claude`, `openclaw`, `all` |\n| `-s, --scope` | 见下方 Scope 说明 |\n| `-f, --force` | 覆盖已有安装 |\n| `-y, --yes` | 非交互（需配合 `-r`） |\n| `--json` | 输出 JSON（`install`/`update`/`uninstall` 需配合 `-y`） |\n\n### Scope 说明\n\n| Runtime | 支持的 scope |\n|---------|-------------|\n| Claude Code | `global`（默认）, `project` |\n| OpenClaw | `global`, `project`, `workspace` |\n\n`workspace` 仅 OpenClaw 支持；Claude Code 没有 workspace 概念。OpenClaw `workspace` 安装路径为 `~/.openclaw/workspace/skills`（Windows: `%USERPROFILE%\\.openclaw\\workspace\\skills`）。\n\n## Examples\n\n```bash\n# 交互式安装\nnpx @insentek/openapi-skill\n\n# 安装到 Claude Code（global）\nnpx @insentek/openapi-skill install -r claude -s global -y\n\n# 安装到 OpenClaw workspace\nnpx @insentek/openapi-skill install -r openclaw -s workspace -y\n\n# 查安装路径与脚本位置（Agent 应用此解析 SKILL_ROOT）\nnpx @insentek/openapi-skill status -r openclaw -s workspace --json\n\n# 凭据 / 诊断\nnpx @insentek/openapi-skill update -r claude -y\nnpx @insentek/openapi-skill doctor\nnpx @insentek/openapi-skill login\nnpx @insentek/openapi-skill logout\nnpx @insentek/openapi-skill auth status\nnpx @insentek/openapi-skill info\n\n# 脚本 / CI 使用 JSON 输出\nnpx @insentek/openapi-skill status -r claude --json\nnpx @insentek/openapi-skill install -r claude -s global -y --json\nnpx @insentek/openapi-skill doctor --json\n```\n\n## Development / 本地测试\n\n包尚未发布到 npm 时，`npx @insentek/openapi-skill` 会失败。本地请用下面任一方式：\n\n```powershell\ncd packages/insentek-skill-cli\nnpm install\nnpm run sync-assets\nnpm test\n```\n\n**方式一：直接跑（最简单）**\n\n```powershell\nnode bin/insentek-api-skill.js info\nnode bin/insentek-api-skill.js\nnode bin/insentek-api-skill.js install -r claude -s global -y\n```\n\n**方式二：模拟 npx（在 CLI 目录下）**\n\n```powershell\nnpx . info\nnpx .\nnpx . install -r claude -s global -y\n```\n\n**方式三：全局 link 后按发布命令测**\n\n```powershell\nnpm link\nnpx @insentek/openapi-skill info\ninsentek-api-skill doctor\n```\n\n**方式四：模拟正式发布**\n\n```powershell\nnpm run sync-assets\nnpm pack\nnpm install -g .\\insentek-openapi-skill-1.2.2.tgz\ninsentek-api-skill info\n```\n\n修改 `SKILL.md` / `scripts/` 后需重新 `npm run sync-assets` 再测。\n\n## Requirements\n\n- Node.js 18+\n- Python 3.10+（用于运行 `scripts/insentek_cli.py` 等脚本；CLI 会通过 `findPythonCommand()` 在 macOS/Linux 上优先选择 `python3`，Windows 上优先 `python` / `py`）\n\n`info --json` 输出会在 `environment.python` 以及每个 `runtimes[].scopes[]` 条目下暴露 `python.command`，Agent 应以该值作为脚本调用前缀，而不是裸用 `python`。\n\nFile v1.2.2:README.md\n\n# Insentek OpenAPI Skill\n\n> 让终端用户用自然语言轻松查询 insentek（东方智感）物联网设备数据。\n\n---\n\n## 简介\n\n本项目基于 insentek OpenAPI v3，产出一份通用 `skill.md` 技能文件及配套文档与示例。终端用户可在 **OpenClaw、Hermes-Agent、Claude Code、ChatGPT** 等 Agent 平台上直接对话使用，通过自然语言调用 API 完成设备数据查询、报告生成与实时分析。\n\n**支持的设备类型：**\n- 🌱 **Z** — 土壤墒情仪（土壤温度、水分、电导率）\n- 🌤️ **T** — 气象站（空气温度、湿度、风速、降雨量、PM2.5 等）\n- 📏 **J** — 见厘液位计（激光液位、电池电压）\n\n---\n\n## 快速开始\n\n### 前置依赖\n\n| 依赖 | 版本 | 用途 |\n|------|------|------|\n| Node.js | ≥ 18 | 运行 `npx @insentek/openapi-skill` CLI |\n| Python | ≥ 3.10 | 运行 `scripts/insentek_cli.py` 等脚本（脚本使用了 PEP 604 联合类型语法） |\n| openpyxl（可选） | 任意 | 仅当需要 Excel 导出时 |\n\n> macOS / Linux 通常应使用 `python3` 命令调用脚本，不要使用裸 `python`（在新版 macOS 与 Ubuntu/Fedora 上不存在或指向 Python 2）。CLI 的 `info --json` 会输出 `python.command`，Agent 必须以该值作为脚本调用前缀。\n\n### 1. 获取认证信息\n\n登录 [E 生态](https://cloud.ecois.info)，在「应用管理」中创建应用，获取 `appid` 和 `secret`。\n\n### 2. 安装 Skill\n\n**一键安装（推荐）：**\n\n```bash\nnpx @insentek/openapi-skill\n```\n\n| 类型 | 名称 |\n|------|------|\n| npm package | `@insentek/openapi-skill` |\n| skill id | `insentek-openapi` |\n| 安装目录 | `insentek-openapi` |\n\nCLI 会引导选择 **runtime**（OpenClaw / Claude Code），支持 **scope**（`global` / `project` / `workspace`），并动态解析本机安装路径。\n\n```bash\nnpx @insentek/openapi-skill install -r claude -s global -y\nnpx @insentek/openapi-skill update -r claude -y\nnpx @insentek/openapi-skill doctor\nnpx @insentek/openapi-skill info\n```\n\nOpenClaw 用户也可通过 ClawHub 单独安装（与本 CLI 无关）：\n\n```bash\nclawhub skill install insentek-api-skill\n```\n\n| 命令 | 说明 |\n|------|------|\n| `install` | 安装 skill |\n| `update` | 更新到当前包版本 |\n| `status` / `doctor` | 查看状态 / 诊断 |\n| `uninstall` | 卸载 |\n\n> CLI 源码见 [`packages/insentek-skill-cli/`](packages/insentek-skill-cli/)。路径因 runtime/scope/OS 而异，请用 `info` / `doctor` 查看本机实际位置。\n\n### 命名约定\n\n仓库中涉及三套名字，用途不同，**不要混用**：\n\n| 维度 | 取值 | 用途 |\n|------|------|------|\n| Skill ID（`skill.json` / SKILL.md frontmatter） | `insentek-openapi` | 安装目录名、Agent 内部标识 |\n| ClawHub slug | `insentek-api-skill` | `clawhub skill install <slug>` 时使用 |\n| npm 包名 | `@insentek/openapi-skill` | **所有 `npx` 调用必须使用此名**（registry 上没有 `insentek-api-skill`） |\n| CLI 二进制名 | `insentek-api-skill` | 仅在 `@insentek/openapi-skill` 已安装时作为可执行别名 |\n\n### 3. 开始对话\n\n```\nUser: 我的 appid 是 xxx，secret 是 yyy，查看所有设备\n```\n\n更多用法见 [`docs/getting-started.md`](docs/getting-started.md)。\n\n---\n\n## 项目结构\n\n```\n.\n├── SKILL.md                     # 核心技能文件 (Runtime Contract)\n├── skill.json                   # Skill manifest (id / version / runtime)\n├── docs/\n│   ├── getting-started.md       # 快速开始指南\n│   ├── platform-setup.md        # 各平台配置指南\n│   ├── interaction.md           # 交互规范 (意图/时间/输出格式)\n│   └── analysis.md              # 分析策略 (报告/告警/行业参数)\n├── reference/\n│   └── api-doc.md               # 完整 API 文档 (OpenAPI v3.1.9)\n├── examples/\n│   ├── queries.md               # 查询类对话示例\n│   ├── reports.md               # 报告生成示例\n│   └── flows.md                 # 核心交互流程示例\n├── scripts/                     # 参考实现脚本\n│   ├── insentek_cli.py          # 统一 CLI（认证/查询/实时/导出）\n│   ├── credential_store.py      # 加密凭据读写\n│   ├── export_excel.py          # Excel 导出\n│   ├── write_html.py            # HTML 报告落盘工具\n│   └── README.md                # 脚本使用说明\n└── packages/insentek-skill-cli/ # npm 包 @insentek/openapi-skill 源码\n    ├── bin/                     # CLI 二进制入口\n    ├── lib/                     # commander / inquirer 实现\n    └── test/                    # node:test 测试\n```\n\n---\n\n## 核心功能\n\n| 功能 | 说明 |\n|------|------|\n| 🔐 自动认证 | appid+secret → token，自动缓存与刷新 |\n| 📋 设备管理 | 列表查询、别名解析、单设备详情 |\n| 📊 数据查询 | 实时/历史/指定时刻/增量同步 |\n| 🧠 智能推断 | 自然语言时间自动解析（\"上周\"→日期范围） |\n| 🔗 链式调用 | alias → SN → 数据，自动串联 |\n| 📈 趋势分析 | 平均值/最大值/最小值/变化率自动计算 |\n| ⚖️ 跨设备对比 | 并排比较 + 差异高亮 |\n| ⚠️ 异常检测 | 电池过低、水分异常、温度突变自动标记 |\n| 🏭 多行业适配 | Z/T/J 设备类型自动识别与参数翻译 |\n| 🎯 意图确认 | 输出形式不明确时自动询问（查看/导出/报告） |\n| 🛡️ 查询边界 | 最大1年/3年回溯/5万条导出上限，超限自动拦截 |\n| 📤 数据导出 | CSV / Excel / JSON / HTML 报告一键生成 |\n| 🔍 环境检查 | 首次使用前自动检查 Python、脚本、依赖、API 可达性 |\n\n---\n\n## 对话示例\n\n**查看设备列表**\n```\nUser: 查看我的设备\nAgent: 📋 设备列表（共 3 台）...\n```\n\n**查询实时数据**\n```\nUser: 1号大棚现在的温度\nAgent: 📍 1号大棚 — 10cm: 18.5℃, 20cm: 17.2℃ ...\n```\n\n**历史趋势**\n```\nUser: 最近7天的土壤湿度变化\nAgent: 📊 趋势表格 + 平均/最高/最低/变化率小结\n```\n\n**异常检测**\n```\nUser: 检查所有设备的电池\nAgent: 🔋 巡检报告 — 2号大棚 2.85V 🔴 过低\n```\n\n更多示例见 [`examples/`](examples/)。\n\n---\n\n## 时间表达支持\n\n| 你说 | Agent 理解 |\n|------|-----------|\n| \"现在\" / \"最新\" / \"实时\" | 调用 /latest |\n| \"昨天\" / \"上周\" / \"本月\" | 自动计算 YYYYMMDD,YYYYMMDD |\n| \"最近7天\" / \"近一周\" | 过去 7 天 |\n| \"12点30分\" / \"某时刻\" | 调用 /moment/{datetime} |\n| \"同步\" / \"增量\" | 调用 /incremental |\n| *(没提时间)* | 默认最近 24 小时 |\n\n---\n\n## 平台兼容性\n\n| 特性 | OpenClaw | Claude Code | ChatGPT | Hermes-Agent |\n|------|:--------:|:-----------:|:-------:|:------------:|\n| Function Schema | ✅ | ✅ | ⚠️ Actions | ✅ |\n| 自动 Token 刷新 | ✅ | ✅ | ⚠️ | ✅ |\n| 别名解析 | ✅ | ✅ | ✅ | ✅ |\n| 时间推断 | ✅ | ✅ | ✅ | ✅ |\n| 链式调用 | ✅ | ✅ | ✅ | ✅ |\n\n⚠️ = 需额外配置（详见 [`docs/platform-setup.md`](docs/platform-setup.md)）\n\n---\n\n## API 参考\n\n- **Base URL**: `https://openapi.ecois.info`（如需指向自建/测试环境，设置 `INSENTEK_API_BASE` 环境变量）\n- **认证**: `GET /v3/token?appid={appid}&secret={secret}`\n- **设备**: `/v3/devices`, `/v3/device/{sn}`, `/v3/device/{sn}/description`\n- **数据**: `/v3/device/{sn}/data`, `/latest`, `/moment/{datetime}`, `/incremental`\n\n完整参数说明见 [`reference/api-doc.md`](reference/api-doc.md)。\n\n---\n\n## 版本\n\n- **当前版本**: v1.2.2\n- **API 版本**: insentek OpenAPI v3\n- **更新日期**: 2026-05-26（见 [`CHANGELOG.md`](CHANGELOG.md)）\n\n---\n\n## 贡献\n\n本项目为内容产出型项目，主要交付物为 `skill.md` 及配套文档。\n\n如需反馈问题或建议：\n1. 先在本机运行 `npx @insentek/openapi-skill doctor --json` 与 `python3 scripts/insentek_cli.py check` 收集环境信息\n2. 提交 issue 到项目仓库，附上 doctor / check 的 JSON 输出\n\n---\n\n## 许可证\n\n待定 / 请参考 insentek 官方使用条款\n\n---\n\n*Generated with Claude Code · 基于 insentek OpenAPI v3*\n\nFile v1.2.2:scripts/README.md\n\n# Insentek OpenAPI Scripts\n\n本目录包含 Insentek OpenAPI 的参考实现脚本。Agent 通过调用这些脚本完成 API 交互、数据导出和报告生成，而非直接使用 `curl` 命令。\n\n## 设计原则\n\n1. **统一入口**: `insentek_cli.py` 封装所有 API 调用，Agent 只需学习一套参数风格\n2. **边界内置**: 脚本内部实现时间范围限制、数据量检查，Agent 无需重复实现\n3. **结构化输出**: 所有脚本输出 JSON 到 stdout，便于 Agent 解析和决策\n4. **零配置运行**: 仅依赖 Python 标准库（Excel 导出除外）\n\n## 脚本列表\n\n| 脚本 | 功能 | 依赖 |\n|------|------|------|\n| `insentek_cli.py` | 统一 CLI：设备查询、实时/历史数据查询、CSV/JSON 导出 | Python 3.10+ |\n| `credential_store.py` | 凭据加密读写（与 CLI login 兼容） | Python 3.10+, cryptography（读取加密凭据时） |\n| `write_html.py` | HTML 文件写入：将 AI 生成的 HTML 内容安全落盘 | Python 3.10+ |\n| `export_excel.py` | Excel 导出（多 sheet：原始数据 + 统计摘要） | Python 3.10+, openpyxl |\n\n> 脚本使用了 PEP 604 联合类型（`int | None`），需要 Python 3.10 及以上。\n\n## 使用示例\n\n### 环境检查（首次使用前必做）\n\n> Agent 应使用 `python3`（macOS/Linux）或 `python` / `py`（Windows，以 `npx @insentek/openapi-skill info --json` 的 `python.command` 为准）调用脚本。下面示例统一写为 `python3`。\n\n```bash\npython3 insentek_cli.py check\n```\n\n输出示例：\n```json\n{\n  \"success\": true,\n  \"all_checks_passed\": true,\n  \"checks\": {\n    \"python\": {\"ok\": true, \"version\": \"3.11.0\", \"executable\": \"/usr/bin/python3\", \"message\": \"Python 3.11.0 满足要求 (>=3.10)\"},\n    \"scripts_cli\": {\"ok\": true, \"path\": \"...\", \"message\": \"核心脚本 insentek_cli.py 已找到\"},\n    \"scripts_excel\": {\"ok\": true, \"path\": \"...\", \"message\": \"Excel 脚本 export_excel.py 已找到\"},\n    \"scripts_write_html\": {\"ok\": true, \"path\": \"...\", \"message\": \"HTML 写入脚本 write_html.py 已找到\"},\n    \"openpyxl\": {\"ok\": true, \"version\": \"3.1.2\", \"message\": \"openpyxl 3.1.2 已安装，Excel 导出可用\"},\n    \"curl\": {\"ok\": true, \"message\": \"curl 可用，可作为脚本不可用时的 fallback\"},\n    \"api_reachable\": {\"ok\": true, \"status\": 400, \"message\": \"API 服务可访问（HTTP 400，未提供认证参数）\"}\n  },\n  \"summary\": {\n    \"critical\": \"通过\",\n    \"optional\": \"全部通过\",\n    \"message\": \"环境检查通过，所有功能可用。\"\n  }\n}\n```\n\n### 认证\n\n凭据通过 CLI 本地配置，**不要在对话中提供 secret**：\n\n```bash\nnpx @insentek/openapi-skill login\nnpx @insentek/openapi-skill logout\nnpx @insentek/openapi-skill auth status\n```\n\n脚本会自动从 `~/.config/insentek/credentials.json` 读取加密凭据，`--token` 参数可选。\n\n### 查询设备列表\n```bash\npython3 insentek_cli.py devices --page 1 --limit 20\n```\n\n### 查询数据（含边界检查）\n```bash\npython3 insentek_cli.py data --sn 00000000000000 --range 20250101,20250131\n```\n\n### 实时数据\n```bash\npython3 insentek_cli.py latest --sn 00000000000000\n```\n\n### 导出 CSV\n```bash\npython3 insentek_cli.py export --sn 00000000000000 --range 20250101,20250131 --format csv --output data.csv\n```\n\n### 导出 Excel\n```bash\npython3 export_excel.py --sn 00000000000000 --range 20250101,20250131 --output data.xlsx\n```\n\n### 写入 HTML 报告（AI 动态生成内容后落盘）\n```bash\n# 推荐：先把 HTML 写到临时文件，再传 --input-file，避免 shell 吞掉换行/引号\npython3 write_html.py --input-file /tmp/report.html --output report.html\n```\n\n## 输出格式\n\n所有脚本成功时输出：\n```json\n{\n  \"success\": true,\n  \"total\": 1000,\n  \"file\": \"/path/to/file.csv\",\n  \"message\": \"成功导出 1000 条数据到 data.csv\"\n}\n```\n\n失败时输出：\n```json\n{\n  \"success\": false,\n  \"error\": \"单次查询最多支持 1 年范围...\"\n}\n```\n\n## 边界限制\n\n| 限制项 | 值 | 说明 |\n|--------|-----|------|\n| 单次最大跨度 | 365 天 | 超过则拒绝并提示拆分 |\n| 最大历史回溯 | 3 年 | 基于当前日期 |\n| 对话展示上限 | 200 条 | 超过则展示摘要+抽样 |\n| 文件导出上限 | 50,000 条 | 超过则拒绝并建议缩小范围 |\n\nFile v1.2.2:_meta.json\n\n{\n  \"ownerId\": \"kn7dcqpad4aeh2nt5shjf3aerd875anm\",\n  \"slug\": \"insentek-api-skill\",\n  \"version\": \"1.2.2\",\n  \"publishedAt\": 1779788114742\n}\n\nFile v1.2.2:CHANGELOG.md\n\nChangelog\n=========\n\n[1.2.2] - 2026-05-26\n--------------------\n\nChanged\n-------\n\n- **统一 `npx` 调用为 scoped 包名 `@insentek/openapi-skill`**\n  - `NOT_CONNECTED_MESSAGE`（Python + Node 两份）、SKILL.md 固定文案、`docs/interaction.md`、`docs/getting-started.md` 中所有 `npx insentek-api-skill ...` 改为 `npx @insentek/openapi-skill ...`，避免未安装包的新用户被引导执行不存在的 npm 包名\n  - README 新增「命名约定」表，说明 Skill ID / ClawHub slug / npm 包名 / CLI 二进制名各自用途\n  - SKILL.md MUST NOT 列表更正描述：`npx insentek-api-skill ...` 实际会以 npm 404 失败，而 `npx @insentek/openapi-skill devices` 才是会误触 `install` 默认命令的形态\n\n- **`python3` 显式化 + JSON 中暴露 `python.command`**\n  - SKILL.md / docs 中所有 `python ${SKILL_ROOT}/...` 改为 `${PYTHON} ${SKILL_ROOT}/...`，并明确 `${PYTHON}` 来自 `npx @insentek/openapi-skill info --json` 的 `python.command`（macOS/Linux 默认 `python3`，Windows 默认 `python` / `py`）\n  - `lib/output.js` 的 `serializeStatus` / `serializeInstallLocation` / `buildInfoPayload` 输出新增 `python` 对象（`ok` / `command` / `version`），每个 scope 条目还额外暴露 `installed` 布尔，让 Agent 通过 `info --json` 一次性发现安装位置而无需先猜 runtime/scope\n  - `scripts/insentek_cli.py` 的 `check` 把 Python 最低版本要求从 `>=3.8` 修正为 `>=3.10`（脚本实际使用了 PEP 604 `int | None` 联合类型，3.10 之前会语法错误）；同时 doctor 的 Python 检测 message 同步更新\n  - SKILL.md 新增 Python 未安装时的固定引导文案，让 Agent 不要在无 Python 环境下反复尝试\n\n- **所有 API 调用切换到 HTTPS**\n  - 默认 `API_BASE_URL` 从 `http://openapi.ecois.info` 改为 `https://openapi.ecois.info`（`scripts/insentek_cli.py` / `scripts/export_excel.py` / `lib/core/credentials.js` / SKILL.md frontmatter / README / docs / `reference/api-doc.md` 16 处）\n  - `docs/platform-setup.md` 的环境变量示例顺手修正：`INSENTEK_BASE_URL` → `INSENTEK_API_BASE`（脚本实际读取的变量名）\n\nAdded\n-----\n\n- **`latest` 子命令**：`scripts/insentek_cli.py` 新增 `latest --sn SN`，统一走加密凭据 + 自动刷新 token，取代 SKILL.md 之前不可执行的 `curl /v3/device/{sn}/latest` 示例（Agent 无法从加密凭据中拿到明文 token）\n- **统一错误信封 `normalize_error`**：`cmd_data` / `get_latest` 现在把内部 `_validation_error` / `_http_error` / `authentication_required` 统一转换为 `{success: false, error: <kind>, message: ...}`，并对上游 WAF HTML 错误页截断到 500 字符\n\nFixed\n-----\n\n- `docs/platform-setup.md` 中 OpenClaw 小节里两个同名的「方式二」标题（重命名为「方式三/四」）\n- README 项目结构里把 `skill.md` 修正为 `SKILL.md`（Linux 大小写敏感），删除已不存在的 `ref/` 和 `PLATFORM-TEST.md` 引用\n- `lib/commands/doctor.js` 移除与 skill 功能无关的 `git` 检测，避免最小化容器环境 doctor 报红\n- SKILL.md frontmatter 的 `api_base_url` 注明为信息字段（脚本实际通过 `INSENTEK_API_BASE` 环境变量切换 base URL）\n- `write_html.py` 调用示例从易丢换行/引号的 `echo | python ...` 改为推荐 `--input-file <tmpfile>` 模式\n\n[1.2.1] - 2026-05-26\n--------------------\n\nAdded\n-----\n\n- **`@insentek/openapi-skill` CLI 凭据管理**\n  - `login` — 交互式配置 appid/secret，AES-256-GCM 加密保存至 `~/.config/insentek/credentials.json`\n  - `logout` — 清除本地凭据\n  - `auth status` — 查看连接状态（脱敏展示）\n  - 安装流程检测凭据，未配置时引导 `login`\n\n- **`scripts/credential_store.py`**\n  - 与 CLI 加密格式兼容，供 `insentek_cli.py` 读取本地凭据\n  - 修复 `AESGCM.decrypt()` 缺少 `associated_data=None` 导致解密失败的问题\n\n- **CLI `status` / `info --json` 脚本路径**\n  - JSON 输出新增 `scripts.cli`、`scripts.exportExcel`、`scripts.writeHtml`，便于 Agent 解析 `${SKILL_ROOT}`\n\nChanged\n-------\n\n- **认证安全模型（skill.md / docs）**\n  - Agent **禁止**在对话中索要或接收 appid/secret\n  - 401/403 / `authentication_required` 时展示固定引导文案，引导 `npx insentek-api-skill login`\n  - API 调用使用 `python ${SKILL_ROOT}/scripts/insentek_cli.py`；`${SKILL_ROOT}` 由 `status/info --json` 解析，**禁止**相对路径 `scripts/...`\n  - 文件找不到时先查安装路径，**禁止**乱试 `npx insentek-api-skill devices` 等错误命令\n\n- **OpenClaw workspace 安装路径**\n  - `workspace` scope 修正为 `~/.openclaw/workspace/skills/insentek-openapi`（Windows: `%USERPROFILE%\\.openclaw\\workspace\\skills\\...`）\n\n- **Windows 覆盖安装**\n  - `--force` 安装时在 Windows 上改为原地覆盖文件，避免 OpenClaw 占用目录导致 `rename` EPERM\n\n- **`insentek_cli.py`**\n  - 移除对话侧 `auth --appid/--secret` 写入能力；凭据仅通过 CLI `login` 配置\n  - `check` 增加 `credentials` 检查项\n\n- **文档**\n  - 更新 `docs/getting-started.md`、`docs/interaction.md`、`docs/platform-setup.md`、`examples/queries.md`\n  - CLI README 补充 scope 路径说明与凭据命令\n\nFixed\n-----\n\n- OpenClaw workspace 目录解析错误（此前误用项目根目录下的 `skills/`）\n- Python 无法解密 Node CLI 写入的加密凭据\n- Agent 在 login 后误用 `npx insentek-api-skill devices`（非顶层命令）或相对路径脚本\n\n[1.1.0] - 2026-05-22\n--------------------\n\nChanged\n-------\n\n- **结构性重构: skill.md 模块化拆分**\n  - 主 `skill.md` 从 1100+ 行瘦身至 ~250 行 (Runtime Contract 风格)\n  - 新增 `docs/interaction.md` — 意图解析、时间表达式、输出格式、确认策略\n  - 新增 `docs/analysis.md` — 分析策略、报告生成、告警规则、行业参数\n  - 新增 `examples/flows.md` — 3 个核心交互示例（查询/导出/报告含数据校验）\n  - 删除 `examples/alerts.md`（内容合并至 docs/analysis.md）\n\n- **MUST → SHOULD 降级**\n  - 安全/护栏类保持 MUST（raw_data_output, span limit, auth security）\n  - 分析类降级为 SHOULD / RECOMMENDED / PREFER\n  - 模型分析创造力不再被规则过度压制\n\n- **三层职责分离**\n  - Runtime Contract（skill.md）: 工具、护栏、认证、路由\n  - Interaction Policy（docs/interaction.md）: UX、确认、输出格式\n  - Analysis Engine（docs/analysis.md）: 动态分析、报告、可视化\n\n- **新增 Routing 决策表**\n  - skill.md Section 1: L1意图 × L2输出 → 工具路由矩阵\n  - Agent 无需逐行阅读即可快速定位调用路径\n\n- **版本号统一 bumped 1.0.3 → 1.1.0**\n  - skill.md, README.md, PLATFORM-TEST.md, docs/platform-setup.md\n\n[1.0.3] - 2026-05-22\n--------------------\n\nAdded\n-----\n\n- 数据可用性校验 (skill.md Section 2.5)\n  - `query_data` 返回后 Agent 必须检查实际数据范围 vs 用户请求范围\n  - 若实际覆盖比例 < 50% 或天数 < 7 天，必须 STOP 并向用户确认\n  - 确认消息包含：请求范围、实际范围、可能原因（设备未部署/离线）\n  - 用户确认后才允许继续生成报告\n\n- 报告时间范围标注规范 (skill.md Section 8.3)\n  - 实际范围 = 请求范围：正常标注\n  - 实际范围 < 请求范围：必须注明 \"基于实际可用数据: [actual_range]\"\n  - 绝不允许用请求范围替代实际范围，避免误导用户\n\n- Flow 7 数据范围不匹配处理示例 (skill.md Section 12)\n  - 新增完整交互示例：用户请求近3个月，实际仅13天\n  - 展示 Agent 如何向用户说明情况并等待确认\n\nChanged\n-------\n\n- 报告生成流程 (skill.md Section 8.3)\n  - 在 `query_data` 与 `Agent analyzes data` 之间插入数据可用性校验步骤\n  - Flow 6 增加 `[数据可用性校验] → PASS` 标注\n\n- 版本号统一 bumped 1.0.2 → 1.0.3\n  - skill.md, README.md, PLATFORM-TEST.md, docs/platform-setup.md\n\nWhy\n---\n\n- 用户实际测试发现：请求近3个月数据时，设备仅有13天数据\n- 旧版本直接生成报告并标注\"近3个月\"，对用户产生严重误导\n- 新增校验机制确保报告时间范围真实反映数据可用性\n\n[1.0.2] - 2026-05-21\n--------------------\n\nAdded\n-----\n\n- `scripts/write_html.py` — HTML file writer utility\n  - Receives AI-generated HTML content and writes it to disk\n  - No templating or data processing; purely a safe file-writing tool\n  - Supports `--content`, `--input-file`, and stdin input\n  - Minimal HTML structure validation (warnings only, non-blocking)\n  - Structured JSON output for Agent consumption\n\nChanged\n-------\n\n- Removed deprecated `report` / `chart` / `export --format html` from `scripts/insentek_cli.py`\n  - Deleted `generate_report()`, `generate_chart()`, `get_device_info()`, `extract_param_names()` (~480 lines)\n  - HTML reports are now fully Agent-generated; no hard-coded templates\n  - Updated docstring and argparse to reflect only csv/json export\n\n- Updated `skill.md`\n  - Replaced Section 6.4 `generate_report (DEPRECATED)` with 6.4 `write_html`\n  - Added `write_html.py` to environment check items (non-critical)\n  - Changed API doc reference from active guidance to fallback note in Notes\n  - Updated `--dry-run` note to remove `report` and `chart`\n\n- Updated `.planning/STATE.md`\n  - Added `write_html.py` to Utility Scripts list\n  - Removed HTML export from `insentek_cli.py` description\n\nWhy\n---\n\n- User requirements for reports are diverse; fixed templates cannot cover all scenarios\n- Delegate report generation to AI for flexibility (dynamic analysis, custom visualizations)\n- Provide a clean, single-purpose tool for HTML file output rather than monolithic report generators\n\n[1.0.1] - 2026-05-21\n--------------------\n\nAdded\n-----\n\n- --dry-run preview mode (scripts/insentek_cli.py)\n  - data, export (csv/json/html), report, chart subcommands all support --dry-run\n  - Only outputs record count, time range, field summary (nodes/parameters), and first 5 sample rows\n  - Does not write files or output full data, preventing context explosion during debugging\n\n- --dry-run preview mode (scripts/export_excel.py)\n  - Added --dry-run parameter, behavior consistent with CLI script\n  - Does not generate Excel file, only returns structured JSON preview\n\n- Raw data output prohibition (skill.md)\n  - Added Section 2.4 \"Raw Data Output Prohibition\"\n  - Explicitly prohibits Agent from outputting raw sensor full data directly into conversation\n  - Specifies handling for four common scenarios: summary sampling, --dry-run, guided export, direct refusal\n\n- YAML Guardrails declaration (skill.md frontmatter)\n  - Added guardrails.raw_data_output: PROHIBITED\n  - Added guardrails.dry_run_preview_rows: 5\n  - Added guardrails.max_chat_rows: 200\n  - Added guardrails.max_export_rows: 50000\n\n- Dry-run documentation (skill.md)\n  - Added Section 6.0 \"dry-run preview mode (common to all export scripts)\"\n  - Added --dry-run example in query_data Agent Action\n  - Added \"Dry-run first\" and \"Raw data prohibition\" development guidelines in Notes\n\nChanged\n-------\n\n- Version bumped from 1.0.0 to 1.0.1 (skill.md, README.md, PLATFORM-TEST.md, .planning/STATE.md)\n\nWhy\n---\n\n- Prevent accidental full sensor data injection into conversation context\n- Save Token consumption and improve model processing efficiency\n- Promote as Skill development standard: summaries in chat, full data in files\n\n\n[1.0.0] - 2026-05-14\n--------------------\n\nAdded\n-----\n\n- Initial release with intent resolution, query guardrails, and export scripts\n- Three-layer intent model (L1 core -> L2 output -> L3 format)\n- Query guardrails: max 365 days span, max 3 years history, max 200 chat rows, max 50000 export rows\n- Utility scripts: insentek_cli.py (unified CLI), export_excel.py (Excel export)\n- Environment prerequisites check command\n- Session-based authentication caching\n- Multi-industry adaptation (agriculture, meteorology, industrial level monitoring)\n\nFile v1.2.2:CLAUDE.md\n\n# insentek-api-skills\n\nThis is a GSD-managed project. Use `/gsd-progress` to check status and next steps.\n\n## Project Overview\n\n基于 insentek OpenAPI 工程仓库和接口文档，产出一份通用 `skill.md` 技能文件及配套文档与示例。终端用户可在 OpenClaw、Hermes-Agent、Claude Code、ChatGPT 等 Agent 平台上直接对话使用，通过自然语言调用 insentek API 完成设备数据查询、报告生成与实时分析。\n\n## Quick Links\n\n- Project context: `.planning/PROJECT.md`\n- Requirements: `.planning/REQUIREMENTS.md`\n- Roadmap: `.planning/ROADMAP.md`\n- Current state: `.planning/STATE.md`\n\n## Working with This Project\n\n1. Always read `.planning/STATE.md` first to understand current phase and focus\n2. Check `.planning/PROJECT.md` for core value and constraints\n3. Follow the roadmap phase order\n4. Update STATE.md when phase status changes\n\n## Key Decisions\n\n- Single universal `skill.md` (not per-industry splits)\n- Content production project (not a tool/generator)\n- Horizontal Layers phase structure\n- 1-2 week delivery timeline\n\n## Reference Materials\n\n- API codebase: `ref/api-repo/` (Spring Boot 3.5.4, Java 21)\n- API documentation: `ref/api-document-latest.pdf`\n\nFile v1.2.2:docs/analysis.md\n\n# Analysis Guide — 分析与报告\n\n> Agent 驱动的数据分析策略、报告生成规范、告警检测规则。\n> 本文件按需加载，仅在用户提出分析/报告需求时读取。\n\n---\n\n## 1. Analysis Philosophy\n\n分析由 Agent **动态推理**完成，避免硬编码模板。\n\n**推荐流程：**\n1. **Parse intent** — 用户到底想知道什么？（相关性、异常、趋势、对比）\n2. **Select method** — 根据问题选择合适的统计/数学方法\n3. **Compute** — 用 Python 脚本实时计算\n4. **Synthesize** — 用自然语言解释，结合领域上下文\n5. **Deliver** — 表格、图表、HTML 报告\n\n**语气：** 分析部分使用 SHOULD / RECOMMENDED / PREFER，不强制具体方法。\n\n---\n\n## 2. Common Patterns\n\n| 用户问题 | 推荐方法 | 交付物 |\n|---------|---------|--------|\n| \"分析 X 和 Y 的关系\" | Pearson/Spearman 相关 + 散点图 | 相关系数 + 散点图 + 解释 |\n| \"找出异常数据\" | 阈值检测或统计离群点 | 异常列表 + 时间标记 |\n| \"对比两台设备\" | 并排统计 + 差异分析 | 对比表 + 差异高亮 |\n| \"最近有什么趋势\" | 线性回归 / 变化率 | 趋势方向 + 变化率 + 图表 |\n| \"降雨最多的几天\" | 百分位 / 最大值筛选 | 极值列表 + 日期 |\n| \"数据分布如何\" | 直方图 / 分位数 (P10/P50/P90) | 分布图 + 分位数 |\n| \"昼夜温差多大\" | 昼夜分段 + 范围计算 | 昼夜统计对比表 |\n| \"近一年每日趋势\" | 按天聚合 (daily average) | 折线图 + 月度统计 |\n\n**Key Principle:** 输出应直接回答用户问题，而非堆砌统计数据。\n\n---\n\n## 3. Report Generation Guide\n\n### 3.1 流程\n\n```\nquery_device → resolve sn\nquery_data → retrieve data\n[数据可用性校验] → 见 skill.md 3.2\nanalyze (statistics, trends, anomalies)\nconstruct HTML (ECharts + CSS)\nwrite_html → return path\n```\n\n### 3.2 HTML 结构（RECOMMENDED）\n\n```html\n<!-- 最小骨架示例 -->\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <script src=\"https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js\"></script>\n  <style>/* 简洁响应式布局 */ body { font-family: sans-serif; max-width: 960px; margin: 0 auto; } </style>\n</head>\n<body>\n  <h1>设备分析报告</h1>\n  <div class=\"header\">\n    设备: [别名] (SN: [后4位]) | 类型: [Z/T/J] | 位置: [城市]\n    分析时段: [actual_range] | 数据点: [N] 条\n  </div>\n  <div class=\"key-findings\"><!-- 核心指标卡片 --></div>\n  <div class=\"charts\"><!-- ECharts 图表容器 --></div>\n  <div class=\"details\"><!-- 详细表格 --></div>\n  <div class=\"conclusion\"><!-- 文字总结 --></div>\n</body>\n</html>\n```\n\n### 3.3 时间范围标注规范（MUST）\n\n| 场景 | 标注方式 |\n|------|---------|\n| 实际 = 请求 | `\"分析时段: [范围]\"` |\n| 实际 < 请求 | `\"分析时段: [actual_range]（您请求的 [requested_range] 中，该设备仅有此区间数据）\"` |\n\n**绝不允许**用请求范围替代实际范围。\n\n### 3.4 可视化推荐\n\n- **时间序列趋势** → ECharts line chart\n- **两变量关系** → ECharts scatter plot\n- **多维度对比** → ECharts bar chart 或 radar chart\n- **地理分布** → ECharts map (如有位置数据)\n- **分布分析** → ECharts histogram 或 box plot\n\n### 3.5 Anti-patterns\n\n- 不要在项目目录中创建 `generate_report_v2.py` 等可复用脚本\n- 每个报告应 ad-hoc 生成，用完即删临时脚本\n- 不要只放图表不加文字解释\n\n完整报告示例见 `examples/reports.md`。\n\n---\n\n## 4. Alert Detection Rules\n\n数据获取后，自动扫描异常：\n\n| 参数 | 告警条件 | 严重级别 |\n|------|---------|---------|\n| `moisture` (土壤水分) | < 5% or > 50% | Warning |\n| `temperature` (温度) | 1小时内变化 > 10°C | Critical |\n| `battery` (电池电压) | < 3.0V | Critical |\n| `ec` (电导率) | < 0 or > 20 | Warning |\n| `laserliquidLevel` (激光液位) | < 0 | Warning |\n\n**输出格式：**\n```\n⚠️ 异常数据检测\n- [参数名] 在 [节点] [时间]: [值] [单位] — [异常描述]\n```\n\n---\n\n## 5. Multi-Industry Parameters\n\n设备类型决定显示参数的中文名：\n\n| 类型码 | 行业 | 关键参数 |\n|--------|------|---------|\n| `Z` | 农业 / 土壤监测 | moisture, temperature, ec |\n| `T` | 气象 / 气象站 | airTemperature, relativeHumidity, rainfall, wind... |\n| `J` | 工业 / 液位监测 | laserliquidLevel, battery |\n\n通过 `/v3/device/{sn}/description` 获取参数中文名，优先用中文展示。\n\n完整参数参考见 `reference/api-doc.md`。\n\nFile v1.2.2:docs/getting-started.md\n\n# Getting Started — 快速开始\n\n> 5 分钟内配置完成，开始用自然语言查询设备数据。\n\n---\n\n## 你需要什么\n\n| 项目 | 说明 | 获取方式 |\n|------|------|---------|\n| `appid` | 应用 ID | E 生态后台创建应用后获得 |\n| `secret` | 应用密钥 | 与 appid 同时生成 |\n| 设备 | 已接入 insentek 平台的物联网设备 | 联系 insentek 或自行部署 |\n\n---\n\n## 第一步：在 E 生态获取 appid 和 secret\n\n1. 登录 [E 生态](https://www.ecois.info)\n2. 进入「应用管理」→「创建应用」\n3. 复制 `appid` 和 `secret`\n4. **妥善保存 secret** — 后续仅在 CLI `login` 时输入，**不要**在 Agent 对话中发送\n\n---\n\n## 第二步：安装 Skill 并通过 CLI 配置凭据\n\n推荐使用 CLI 一键安装：\n\n```bash\nnpx @insentek/openapi-skill\n```\n\n安装过程中若检测到尚未配置凭据，CLI 会引导你运行：\n\n```bash\nnpx @insentek/openapi-skill login\n```\n\n在 `login` 提示中输入第一步获得的 appid 和 secret。凭据会加密保存在 `~/.config/insentek/credentials.json`（文件权限 600）。\n\n也可手动将 `skill.md` 加载到 Agent 平台，但仍需先完成 CLI `login`，详见 [platform-setup.md](platform-setup.md)。\n\n---\n\n## 第三步：开始对话\n\n配置完成后，直接用自然语言查询：\n\n> **User:** 帮我查看所有设备。\n\nAgent 会自动读取本地凭据、查询设备列表并返回结果。\n\n若未连接 API，Agent 会展示如下固定引导文案（见 `skill.md` Section 2）：\n\n```\n这台电脑还没有连接 Insentek API，需要先完成一次本地配置，通常 1 分钟就好。\n\n请在终端运行：\n\nnpx @insentek/openapi-skill login\n\n按提示输入 appid 和 secret 即可（加密保存在本机，无需发到这个对话）。配置完成后回来继续提问，我接着帮你处理。\n```\n\n---\n\n## 常用查询示例\n\n### 查看设备列表\n```\n查看我的设备\n```\n\n### 查询实时数据\n```\n3号设备现在的温度是多少？\n```\n\n### 查询历史数据\n```\n1号设备上周的土壤湿度变化\n```\n\n### 多设备对比\n```\n对比一下1号和2号设备的温度\n```\n\n### 异常检测\n```\n检查一下所有设备的电池状态\n```\n\n---\n\n## 支持的设备类型\n\n| 类型代码 | 设备名称 | 典型参数 |\n|---------|---------|---------|\n| `Z` | 土壤墒情仪 | 土壤温度、土壤水分、电导率 |\n| `T` | 气象站 | 空气温度、湿度、风速、降雨量 |\n| `J` | 见厘液位计 | 激光液位、电池电压 |\n\n---\n\n## 时间表达支持\n\n你可以用自然语言描述时间，Agent 会自动转换：\n\n| 你说 | Agent 理解 |\n|------|-----------|\n| \"现在\" / \"最新\" / \"实时\" | 调用实时数据接口 |\n| \"昨天\" | 昨天的全部数据 |\n| \"最近7天\" / \"近一周\" | 过去 7 天的数据 |\n| \"上周\" | 上周一至周日 |\n| \"本月\" | 本月 1 号到今天 |\n| \"某时刻\" / \"12点30分\" | 指定时间点的数据 |\n| *(没提时间)* | 默认最近 24 小时 |\n\n---\n\n## 下一步\n\n- 查看 [platform-setup.md](platform-setup.md) 了解各平台详细配置步骤\n- 查看 [`reference/api-doc.md`](../reference/api-doc.md) 了解完整 API 参数详情\n- 查看项目根目录 `examples/` 目录中的对话示例\n\n---\n\n## 常见问题\n\n**Q: token 多久过期？**\nA: 默认 2 小时（7200 秒）。脚本在 API 返回 401/403 时自动刷新 token，无需在对话中重新提供凭据。\n\n**Q: 可以在对话里告诉 Agent 我的 appid 和 secret 吗？**\nA: **不可以。** 凭据仅通过 `npx @insentek/openapi-skill login` 在本地配置，Agent 不会也不应接收这些敏感信息。\n\n**Q: 可以用设备别名查询吗？**\nA: 可以。Agent 支持别名部分匹配，如 \"3号\" 会匹配别名为 \"3号大棚\" 的设备。\n\n**Q: 数据查询有时间范围限制吗？**\nA: 增量同步接口（/incremental）首次调用返回最近 3 个月数据。历史数据查询最大支持 3 年回溯，单次查询跨度不超过 365 天。建议单次查询不超过 30 天以提高响应速度。\n\n**Q: 支持英文查询吗？**\nA: skill.md 中的 Prompt 指令为中文，但 Agent 平台通常支持多语言理解。英文查询的效果取决于具体 Agent 平台。\n\nFile v1.2.2:docs/interaction.md\n\n# Interaction Guide — 交互规范\n\n> 完整交互流程、时间解析、输出格式、确认策略。\n> 本文件按需加载，非每次调用必读。\n\n---\n\n## 0. Authentication Behavior\n\n**MUST 遵守（与 `skill.md` Section 2 / 4 一致）：**\n\n- Agent **禁止**向用户索要或接收 `appid` / `secret`\n- 用户主动发送凭据时 → **拒绝接收**，引导 CLI `login`\n- 脚本返回 `authentication_required` 或 HTTP 401/403 → **STOP**，原样展示固定引导文案：\n\n```\n这台电脑还没有连接 Insentek API，需要先完成一次本地配置，通常 1 分钟就好。\n\n请在终端运行：\n\nnpx @insentek/openapi-skill login\n\n按提示输入 appid 和 secret 即可（加密保存在本机，无需发到这个对话）。配置完成后回来继续提问，我接着帮你处理。\n```\n\n- 用户说\"重新认证\" → 引导 `npx @insentek/openapi-skill login` 或先 `logout` 再 `login`\n\n### 0.1 脚本路径（与 `skill.md` Section 2 一致）\n\n- API 调用用 `${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py`，其中 `${PYTHON}` 来自 `info --json` 的 `python.command`（缺省 `python3`），**禁止**相对路径 `scripts/...`\n- 首次调用前或 ENOENT：`npx @insentek/openapi-skill info --json`，遍历 `runtimes[].scopes[]` 挑选 `installed: true` 的条目，读取 `installDir` / `scripts.cli` / `python.command`\n- npm registry 上不存在 `insentek-api-skill` 包，**禁止**使用 `npx insentek-api-skill ...`\n\n---\n\n## 1. Intent Resolution\n\n### 1.1 三层模型\n\n| 层级 | 名称 | 说明 | 缺失时处理 |\n|------|------|------|-----------|\n| L1 | 核心意图 | 查数据 / 对比 / 导出 / 生成报告 | 反问：\"您想查询数据、对比设备，还是导出报告？\" |\n| L2 | 输出意图 | 对话展示 / 文件导出 | 提供选项让用户选择 |\n| L3 | 格式意图 | CSV / Excel / JSON / HTML | L2=文件时询问；推荐 CSV 为默认 |\n\n### 1.2 关键词映射\n\n| 用户关键词 | 推断 L1 | 推断 L2 | 需确认 L3？ |\n|-----------|---------|---------|-------------|\n| \"查一下\"、\"看看\"、\"多少\" | 查询数据 | 对话展示 | 否 |\n| \"导出\"、\"下载\"、\"保存\" | 查询数据 | 文件导出 | **是** |\n| \"生成报告\"、\"做一份报告\" | 生成报告 | 文件导出 | **是** |\n| \"对比\"、\"比较\"、\"哪个高\" | 对比设备 | 对话展示 | 否 |\n| \"把对比结果导出来\" | 对比设备 | 文件导出 | **是** |\n\n### 1.3 快捷意图（无需确认）\n\n- \"导出 [设备] [时间段] 数据为 [格式]\"\n- \"下载 [设备] 的 [时间段] CSV\"\n- \"生成 [设备] [时间段] 的 HTML 报告\"\n- \"把 [设备A] 和 [设备B] [时间段] 的对比结果导出为 Excel\"\n\n---\n\n## 2. Time Expression Parsing\n\n| 表达式 | 开始 | 结束 | 示例 (today=2025-05-13) |\n|--------|------|------|------------------------|\n| \"现在\" / \"最新\" / \"实时\" | — | — | `GET /latest` |\n| \"昨天\" | yesterday | yesterday | `20250512,20250512` |\n| \"最近7天\" / \"近一周\" | today-7d | today | `20250506,20250513` |\n| \"上周\" | last Monday | last Sunday | `20250505,20250511` |\n| \"本周\" | this Monday | today | `20250512,20250513` |\n| \"本月\" | 1st | today | `20250501,20250513` |\n| \"上月\" | 1st of last month | last day of last month | `20250401,20250430` |\n| \"今年\" | Jan 1 | today | `20250101,20250513` |\n| \"最近1个月\" | today-30d | today | `20250413,20250513` |\n| \"最近3个月\" | today-90d | today | `20250212,20250513` |\n| \"最近1年\" | today-365d | today | `20240513,20250513` |\n| *(default)* | today-1d | today | `20250512,20250513` |\n\n**编码规则：** `YYYYMMDD`，Range: `startYYYYMMDD,endYYYYMMDD`。Moment: `YYYY-MM-DD HH:MM:SS` URL-encoded。\n\n**月份边界：** \"上月\"在 1月31日说 → 12月全月；\"本月\"在当月任意日期 → 1号至今天。\n\n---\n\n## 3. Confirmation Patterns\n\n**MUST 向用户确认的场景：**\n\n1. L1/L2 意图不明确（见 1.1）\n2. 数据可用性覆盖 < 50% 或 < 7 天（见 `skill.md` 3.2）\n3. 多设备 alias 模糊匹配到多个结果\n4. 导出数据量 > 50,000 条\n5. 查询跨度 > 365 天\n\n**可直接执行的场景：**\n- 一句话完整表达（见 1.3）\n- 同一会话内再次查询（已有缓存）\n- 实时数据查询（/latest）\n\n---\n\n## 4. Output Format Guide\n\n### 4.1 实时数据 → 简洁卡片\n\n```\n📍 [设备别名] ([SN后4位])\n─────────────────────────\n🌡️ [参数中文名]: [值] [单位]  @[时间]\n💧 [参数中文名]: [值] [单位]\n🔋 [参数中文名]: [值] [单位]\n─────────────────────────\n状态: [状态描述]  |  位置: [城市]\n```\n\n### 4.2 历史数据（对话）→ 表格 + 趋势\n\n≤ 200 条：完整表格 + 趋势小结\n\n> 200 条：统计摘要 + 首尾各 10 条抽样 + 提示导出\n\n```\n📊 数据概览（共 N 条，展示摘要）\n\n统计摘要:\n| 参数 | 平均 | 最大 | 最小 | 变化率 |\n|------|------|------|------|--------|\n\n💡 提示: 该时间段数据量较大，如需完整数据请说\"导出为CSV\"。\n```\n\n### 4.3 文件导出 → 确认信息\n\n```\n✅ 导出成功\n📄 文件: [filename.csv]\n📊 数据条数: [N] 条\n📅 时间范围: [开始] 至 [结束]\n📥 文件路径: [绝对路径]\n```\n\n### 4.4 对比分析 → 并排表格\n\n```markdown\n| 参数 | [设备A] | [设备B] | 差异 |\n|------|---------|---------|------|\n```\n\n### 4.5 告警报告 → 标记列表\n\n```\n⚠️ 检测到 N 条异常数据:\n1. [时间] [节点] [参数]: [值] — [异常原因]\n```\n\n---\n\n## 5. Interaction Examples\n\n### Flow 1: 查询历史数据（对话展示）\n\n```\nUser: \"3号设备上周的土壤湿度\"\n  → ${PYTHON} ${SKILL_ROOT}/scripts/insentek_cli.py check (optional) or direct query\n  → if authentication_required → STOP, show skill.md Section 2 fixed message\n  → query_device(alias=\"3号\") → resolve sn\n  → query_data(sn, \"上周\") → /data\n  → data points ≤ 200 → show table + trend\n```\n\n### Flow 2: 导出数据（文件导出）\n\n```\nUser: \"导出3号设备上个月数据为CSV\"\n  → if authentication_required → STOP, show skill.md Section 2 fixed message\n  → query_device(alias=\"3号\") → resolve sn\n  → validate range (30d ≤ 365d) → OK\n  → export_csv(sn, range, \"data.csv\") → return path\n```\n\n### Flow 3: 生成报告（数据不匹配 → 确认）\n\n```\nUser: \"分析3号近三个月数据，生成报告\"\n  → if authentication_required → STOP, show skill.md Section 2 fixed message\n  → query_device(alias=\"3号\") → resolve sn\n  → query_data(sn, \"最近3个月\")\n     → 请求: 90天 / 实际: 13天 → coverage 14%\n  → STOP: \"您请求近3个月共90天，该设备实际仅13天数据。是否继续？\"\n  → User: \"继续\"\n  → analyze → construct HTML → write_html → return path\n```\n\n完整多设备对比、分批导出等示例见 `examples/flows.md`。\n\nFile v1.2.2:docs/platform-setup.md\n\n# Platform Setup Guide — 各 Agent 平台配置指南\n\n> 将 insentek skill 安装到不同 Agent 平台的完整步骤，含安装路径、卸载方法和故障排查。\n\n---\n\n## 通用前置：CLI 安装与凭据配置（推荐）\n\n无论使用哪个 Agent 平台，都建议先完成 CLI 安装和本地凭据配置：\n\n```bash\n# 安装 skill 到 Claude Code / OpenClaw（交互式）\nnpx @insentek/openapi-skill\n\n# 配置 API 凭据（加密本地保存，不要在对话中发送 secret）\nnpx @insentek/openapi-skill login\n\n# 查看连接状态\nnpx @insentek/openapi-skill auth status\n```\n\n凭据保存在 `~/.config/insentek/credentials.json`。Agent 通过 `scripts/insentek_cli.py` 自动读取，**不会**在对话中索要 appid/secret。\n\n---\n\n## 目录\n\n- [OpenClaw](#openclaw)\n- [Claude Code](#claude-code)\n- [ChatGPT](#chatgpt)\n- [Hermes-Agent](#hermes-agent)\n- [平台兼容性速查](#平台兼容性速查)\n- [故障排查](#故障排查)\n\n---\n\n## OpenClaw\n\n### 安装\n\n#### 方式一：CLI 安装（推荐）\n\n```bash\nnpx @insentek/openapi-skill install -r openclaw -s global -y\nnpx @insentek/openapi-skill login\n```\n\n#### 方式二：从 ClawHub 安装\n\n```bash\n# 安装最新版本（slug 见 .github/workflows/publish.yml）\nclawhub skill install insentek-api-skill\n\n# 安装指定版本\nclawhub skill install insentek-api-skill@1.2.2\n\n# 从 ClawHub 搜索确认\nclawhub skill search insentek\n```\n\n安装完成后，skill 会自动注册到 OpenClaw 的技能列表中。\n\n> 注意：ClawHub 上的 slug 是 `insentek-api-skill`，但 skill 本身的 id（`skill.json` / SKILL.md frontmatter 中的 `name`）始终是 `insentek-openapi`。两者均合法，只是用途不同。\n\n#### 方式三：本地文件安装\n\n```bash\n# 从本地 SKILL.md 安装\nclawhub skill add ./SKILL.md\n\n# 或使用绝对路径\nclawhub skill add /path/to/SKILL.md\n```\n\n#### 方式四：Web UI 安装\n\n1. 打开 OpenClaw 客户端，进入 **Skills** 页面\n2. 点击 **Import Skill** → 选择文件\n3. 选择项目根目录的 `SKILL.md` 文件\n4. 确认导入\n\n### 卸载\n\n```bash\n# CLI 卸载（npm 包安装方式）\nnpx @insentek/openapi-skill uninstall -r openclaw -s workspace -y\n# 或 ClawHub 安装方式\nclawhub skill remove insentek-api-skill\n```\n\n或在 Web UI 中：Skills → 找到 \"insentek-api-skill\" → **Remove**。\n\n### 配置参数\n\n| 参数 | 值 | 说明 |\n|------|-----|------|\n| API Base URL | `https://openapi.ecois.info` | 默认即可 |\n\n### 首次使用\n\n先在本机配置 API 凭据：\n\n```bash\nnpx @insentek/openapi-skill login\n```\n\n然后在 OpenClaw 中直接查询：\n\n```\nUser: 查看所有设备\n```\n\n---\n\n## Claude Code\n\n### 安装\n\nClaude Code 通过读取 skill 文件来加载技能上下文，支持项目级和全局级两种方式。\n\n#### 方式一：CLI 安装（推荐）\n\n```bash\nnpx @insentek/openapi-skill install -r claude -s global -y\nnpx @insentek/openapi-skill login\n```\n\n#### 方式二：全局 Skills 目录（手动）\n\nClaude Code 会从全局 skills 目录自动加载所有 skill 文件，无需在每个项目中重复放置。\n\n**Windows:**\n```powershell\n# 创建 skills 目录（如果不存在）\nNew-Item -ItemType Directory -Force -Path \"$env:USERPROFILE\\.claude\\skills\"\n\n# 复制 skill 文件\nCopy-Item skill.md \"$env:USERPROFILE\\.claude\\skills\\insentek-api-skill.md\"\n```\n\n**macOS:**\n```bash\nmkdir -p ~/.claude/skills\ncp skill.md ~/.claude/skills/insentek-api-skill.md\n```\n\n**Linux:**\n```bash\nmkdir -p ~/.claude/skills\ncp skill.md ~/.claude/skills/insentek-api-skill.md\n```\n\n放置后重启 Claude Code 或重新打开对话即可生效。\n\n#### 方式三：项目目录加载\n\n将 `skill.md` 放入当前工作项目的根目录，Claude Code 会自动识别为项目上下文：\n\n```bash\n# 任意项目目录\ncp skill.md ./skill.md\n```\n\n#### 方式四：对话中直接引用\n\n```\n# 在 Claude Code 对话中执行\n/load skill.md\n```\n\n或直接将 `skill.md` 内容粘贴到对话中。\n\n### 卸载\n\n- **全局级（推荐）**：从 `~/.claude/skills/` 目录移除对应文件\n  ```bash\n  # Windows\n  Remove-Item \"$env:USERPROFILE\\.claude\\skills\\insentek-api-skill.md\"\n\n  # macOS / Linux\n  rm ~/.claude/skills/insentek-api-skill.md\n  ```\n- **项目级**：删除项目根目录的 `skill.md` 文件\n- **对话级**：执行 `/clear` 清除当前对话上下文\n\n### 首次使用\n\n```bash\nnpx @insentek/openapi-skill login\n```\n\n```\nUser: 查看所有设备\n```\n\nClaude Code 会读取 skill.md 中的 tool definitions，脚本自动使用本地凭据。\n\n### 注意事项\n\n- 确保 skill.md 中的 YAML frontmatter 被正确解析\n- 如果 function calling 未触发，尝试明确说出工具名称如 \"query_device\"\n\n---\n\n## ChatGPT\n\n### 安装\n\n#### 方式一：创建 GPT（推荐，需 Plus 订阅）\n\n1. 打开 [ChatGPT](https://chat.openai.com) → **Explore GPTs** → **Create**\n2. 在 Configure 标签页：\n   - **Name**: Insentek Device Query\n   - **Description**: 查询 insentek 物联网设备数据\n   - **Instructions**: 粘贴 `skill.md` 的完整内容\n3. 在 **Capabilities** 中启用 \"Code Interpreter\"（如需数据处理）\n4. 保存并发布（可选设为 Private）\n\n#### 方式二：Actions（API 直连，需 Plus 订阅）\n\n1. 创建 GPT 时，在 Configure 页面点击 **Add actions**\n2. 粘贴由 `skill.md` function schema 生成的 OpenAPI schema\n3. 设置认证方式：API Key（Header: `Authorization`）— **不要将 appid/secret 写入 GPT 配置或对话**\n4. 在本机运行 `npx @insentek/openapi-skill login`，由脚本管理 token\n5. 保存后 GPT 可直接调用 insentek API\n\n#### 方式三：Custom Instructions（个人使用）\n\n适合临时使用，无需创建 GPT。\n\n1. 打开 ChatGPT → 点击头像 → **Custom Instructions**\n2. 在 \"How would you like ChatGPT to respond?\" 中粘贴 `skill.md` 的 Prompt 区内容\n3. 在 \"What would you like ChatGPT to know about you?\" 中说明你有 insentek 物联网设备即可（**不要**写入 appid/secret）\n4. 在本机运行 `npx @insentek/openapi-skill login` 配置凭据\n5. 保存后开始新对话\n\n**限制：** Custom Instructions 不支持真正的 function calling，API 调用需要手动复制 URL。\n\n### 卸载\n\n- **GPTs 方式**：ChatGPT → Explore GPTs → 找到对应 GPT → 右上角 ⋮ → **Delete GPT**\n- **Actions 方式**：编辑 GPT → Configure → Actions → **删除对应 Action**\n- **Custom Instructions**：ChatGPT → 头像 → Custom Instructions → **清空内容**\n\n### 首次使用\n\n```\nUser: 查看我的所有设备\n```\n\n如果已在本地运行 `npx @insentek/openapi-skill login`，脚本会自动认证并查询。\n\n---\n\n## Hermes-Agent\n\n### 安装\n\nHermes-Agent 通过读取 skills 目录下的 skill 文件来加载技能。\n\n#### 步骤\n\n**Windows:**\n```powershell\n# 创建 skills 目录（如果不存在）\nNew-Item -ItemType Directory -Force -Path \"$env:USERPROFILE\\.hermes\\skills\"\n\n# 复制 skill 文件\nCopy-Item skill.md \"$env:USERPROFILE\\.hermes\\skills\\insentek-api-skill.md\"\n```\n\n**macOS:**\n```bash\nmkdir -p ~/.hermes/skills\ncp skill.md ~/.hermes/skills/insentek-api-skill.md\n```\n\n**Linux:**\n```bash\nmkdir -p ~/.hermes/skills\ncp skill.md ~/.hermes/skills/insentek-api-skill.md\n```\n\n**重启或刷新：**\n```bash\nhermes skill reload\n# 或重启 Hermes-Agent 服务\n```\n\n### 卸载\n\n**Windows:**\n```powershell\nRemove-Item \"$env:USERPROFILE\\.hermes\\skills\\insentek-api-skill.md\"\n```\n\n**macOS / Linux:**\n```bash\nrm ~/.hermes/skills/insentek-api-skill.md\nhermes skill reload\n```\n\n### 配置环境变量（可选）\n\n```bash\nexport INSENTEK_API_BASE=https://openapi.ecois.info\n```\n\n### 首次使用\n\n```bash\nnpx @insentek/openapi-skill login\n```\n\n```\nUser: 查看设备\n```\n\n---\n\n## 平台兼容性速查\n\n| 特性 | OpenClaw | Claude Code | ChatGPT (GPTs) | Hermes-Agent |\n|------|----------|-------------|----------------|--------------|\n| Function Schema | Native | Native | Via Actions | Native |\n| YAML Frontmatter | ✅ | ✅ | ⚠️ | ✅ |\n| Auto Token Refresh | ✅ | ✅ | Manual | ✅ |\n| Alias Resolution | ✅ | ✅ | ✅ | ✅ |\n| Time Parsing | ✅ | ✅ | ✅ | ✅ |\n| Chain Calling | ✅ | ✅ | ✅ | ✅ |\n| CLI 凭据管理 | ✅ | ✅ | ⚠️ 需本机 login | ✅ |\n| ClawHub 一键安装 | ✅ | ❌ | ❌ | ❌ |\n\n**图例：** ✅ 原生支持 | ⚠️ 需额外配置 | ❌ 不支持\n\n---\n\n## 故障排查\n\n### Function Schema 未被识别\n\n- **Claude Code**: 确保 skill.md 位于项目根目录，且文件名为 `skill.md`\n- **ChatGPT**: 使用 GPTs 的 Actions 功能，或手动粘贴 Instructions\n- **通用**: 检查 YAML frontmatter 格式是否正确（`---` 开头和结尾）\n\n### 认证失败\n\n1. 运行 `npx @insentek/openapi-skill auth status` 检查连接状态\n2. 重新配置：`npx @insentek/openapi-skill login`\n3. 检查网络是否能访问 `https://openapi.ecois.info`\n4. **不要在对话中发送 secret**，凭据仅通过 CLI 配置\n\n### 查询无数据返回\n\n1. 确认设备已正确接入 insentek 平台\n2. 检查时间范围是否合理（默认最近 24 小时可能无数据）\n3. 尝试扩大时间范围如 \"最近7天\"\n\n---\n\n*配置问题请联系：参考 insentek 官方支持渠道*\n\nFile v1.2.2:examples/flows.md\n\n# Examples: Core Interaction Flows\n\n> 3 个核心交互流程，覆盖最常见的使用场景。\n> 完整交互规范见 `docs/interaction.md`。\n\n---\n\n## Flow 1: Query Historical Data (Chat)\n\n### User Input\n```\n3号设备上周的土壤湿度\n```\n\n### Agent Thinking\n1. alias=\"3号\" → resolve sn via `query_device`\n2. time=\"上周\" → range = last Monday ~ last Sunday\n3. param=\"土壤湿度\" → includeParams = moisture\n4. output intent = chat (implicit)\n\n### Tool Calls\n```\nquery_device(alias=\"3号\")\n  → sn = \"00000000000001\"\n\nquery_data(sn=\"00000000000001\", time_expression=\"上周\", includeParameters=\"moisture\")\n  → GET /v3/device/00000000000001/data?range=20250505,20250511&includeParams=moisture\n```\n\n### Output\n```markdown\n📊 3号大棚 — 上周土壤湿度 (2025-05-05 ~ 2025-05-11)\n\n| 日期 | 10cm | 20cm | 30cm | 40cm |\n|------|------|------|------|------|\n| 05-05 | 22.1 | 23.5 | 25.1 | 26.5 |\n| ... | ... | ... | ... | ... |\n\n📈 趋势小结:\n- 各层湿度平稳，40cm深层保持最高\n- 10cm表层受蒸发影响日间波动稍大\n```\n\n---\n\n## Flow 2: Export Data (File)\n\n### User Input\n```\n导出3号设备上个月数据为CSV\n```\n\n### Agent Thinking\n1. alias=\"3号\" → resolve sn\n2. time=\"上个月\" → range = 20250401,20250430\n3. format=\"CSV\" → export_csv\n4. Validate: 30 days ≤ 365 days → OK\n\n### Tool Calls\n```\nquery_device(alias=\"3号\") → sn = \"00000000000001\"\n\nexport_csv(sn=\"00000000000001\", range=\"20250401,20250430\", output=\"3号_2025-04.csv\")\n  → 成功导出 720 条数据\n```\n\n### Output\n```\n✅ 导出成功\n\n📄 文件: 3号_2025-04.csv\n📊 数据条数: 720 条\n📅 时间范围: 2025-04-01 至 2025-04-30\n📥 文件路径: /absolute/path/to/3号_2025-04.csv\n```\n\n---\n\n## Flow 3: Generate Report (Data Availability Mismatch)\n\n### User Input\n```\n分析11684501348336近三个月的数据，生成报告\n```\n\n### Agent Thinking\n1. alias=\"11684501348336\" → resolve sn\n2. time=\"近3个月\" → requested range = 2026-02-22 ~ 2026-05-22 (90 days)\n3. query_data → retrieve actual data\n4. **数据可用性校验**: actual = 2025-05-10 ~ 2025-05-22 (13 days)\n5. coverage = 13/90 = 14% < 50% → **STOP and confirm**\n\n### Tool Calls\n```\nquery_device(alias=\"11684501348336\") → sn = \"11684501348336\"\n\nquery_data(sn=\"11684501348336\", time_expression=\"最近3个月\")\n  → actual range: 2025-05-10 ~ 2025-05-22 (13 records)\n```\n\n### Agent Confirmation\n```\n您请求的『近3个月』共约 90 天，\n但该设备实际仅有 2025-05-10 至 2025-05-22 共 13 天的数据。\n\n可能原因：\n- 设备在该时间段尚未部署或激活\n- 设备期间出现离线/故障导致数据缺失\n\n是否继续基于现有 13 天数据生成报告？\n```\n\n### User Response\n```\n继续\n```\n\n### Analysis & Report Generation\n```\n→ 统计摘要: 均值、最大、最小、标准差\n→ 趋势分析: 线性变化率\n→ 异常检测: 扫描 battery, moisture, temperature\n→ 构建 HTML (ECharts line chart + summary cards)\n→ write_html → report.html\n```\n\n### Output\n```\n✅ 报告已生成\n\n📄 文件: report_11684501348336.html\n📊 分析数据: 13 条 (2025-05-10 至 2025-05-22)\n⚠️  注: 基于实际可用数据，非完整 3 个月\n📥 文件路径: /absolute/path/to/report_11684501348336.html\n```\n\n---\n\n## Other Scenarios\n\n更多场景（多设备对比、批量导出、实时查询、告警检测）见：\n- `examples/queries.md` — 查询类对话示例\n- `examples/reports.md` — 报告生成示例\n- `docs/interaction.md` Section 5 — 完整确认策略\n\nArchive v1.2.1: 50 files, 92685 bytes\n\nFiles: CHANGELOG.md (8671b), CLAUDE.md (1214b), docs/analysis.md (4559b), docs/getting-started.md (4204b), docs/interaction.md (6722b), docs/platform-setup.md (8819b), examples/flows.md (3539b), examples/queries.md (5984b), examples/reports.md (5766b), packages/insentek-skill-cli/bin/insentek-api-skill.js (319b), packages/insentek-skill-cli/lib/cli.js (15271b), packages/insentek-skill-cli/lib/commands/auth.js (910b), packages/insentek-skill-cli/lib/commands/doctor.js (5074b), packages/insentek-skill-cli/lib/commands/login.js (2552b), packages/insentek-skill-cli/lib/commands/logout.js (653b), packages/insentek-skill-cli/lib/commands/status.js (2139b), packages/insentek-skill-cli/lib/constants.js (521b), packages/insentek-skill-cli/lib/copy.js (3678b), packages/insentek-skill-cli/lib/core/credentials.js (6732b), packages/insentek-skill-cli/lib/core/installer.js (1817b), packages/insentek-skill-cli/lib/core/manifest.js (932b), packages/insentek-skill-cli/lib/core/resolver.js (1237b), packages/insentek-skill-cli/lib/core/scope.js (2015b), packages/insentek-skill-cli/lib/os.js (872b), packages/insentek-skill-cli/lib/output.js (3366b), packages/insentek-skill-cli/lib/python.js (544b), packages/insentek-skill-cli/lib/runtime/claude.js (1204b), packages/insentek-skill-cli/lib/runtime/index.js (1491b), packages/insentek-skill-cli/lib/runtime/openclaw.js (1656b), packages/insentek-skill-cli/lib/script-paths.js (332b), packages/insentek-skill-cli/lib/utils.js (1900b), packages/insentek-skill-cli/package-lock.json (17394b), packages/insentek-skill-cli/package.json (1047b), packages/insentek-skill-cli/README.md (3678b), packages/insentek-skill-cli/scripts/sync-assets.js (2227b), packages/insentek-skill-cli/test/cli-json.test.js (2082b), packages/insentek-skill-cli/test/copy.test.js (3368b), packages/insentek-skill-cli/test/credentials.test.js (2571b), packages/insentek-skill-cli/test/runtime.test.js (2816b), README.md (6675b), reference/api-doc.md (28329b), scripts/credential_store.py (5141b), scripts/export_excel.py (9191b), scripts/insentek_cli.py (24512b), scripts/README.md (3765b), scripts/write_html.py (6398b), skill-card.md (2987b), skill.json (203b), SKILL.md (11684b), _meta.json (137b)\n\nFile v1.2.1:SKILL.md\n\n---\nname: insentek-openapi\nversion: 1.2.1\ndescription: >\n  通过自然语言查询 insentek（东方智感）物联网设备数据。\n  支持土壤墒情仪、气象站、见厘液位计等多种设备类型的实时数据、\n  历史数据、趋势分析、跨设备对比与数据导出。\napi_base_url: http://openapi.ecois.info\nauthor: insentek-api-skills\nguardrails:\n  raw_data_output: PROHIBITED\n  dry_run_preview_rows: 5\n  max_chat_rows: 200\n  max_export_rows: 50000\n---\n\n# Insentek OpenAPI Skill\n\n> 轻量 Runtime Contract。完整交互规范见 `docs/interaction.md`，分析策略见 `docs/analysis.md`。\n> 兼容平台：OpenClaw、Hermes-Agent、Claude Code、ChatGPT\n\n---\n\n## 1. Routing\n\n用户意图 → 工具路由：\n\n| L1 意图 | L2 输出 | 调用 |\n|---------|---------|------|\n| 查询数据 | 对话展示 | `query_device` → `query_data` → 按输出格式回复 |\n| 查询数据 | 文件导出 | `query_device` → `export_*` → 返回文件路径 |\n| 生成报告 | 文件导出 | `query_device` → `query_data` → 分析 → `write_html` |\n| 对比设备 | 对话展示 | `query_device` (xN) → `query_data` (xN) → 对比表格 |\n| 对比设备 | 文件导出 | `query_device` (xN) → `query_data` (xN) → `export_excel` |\n\n**任何一层意图不明确时，MUST 向用户确认，不得假设。** 详见 `docs/interaction.md` Section 1。\n\n---\n\n## 2. Tools\n\n**认证约束（MUST）：** Agent **禁止**向用户索要 `appid` 或 `secret`，也 **禁止**在对话中接收、存储或回显这些凭据。凭据仅通过 CLI 在本地配置：\n\n```bash\nnpx @insentek/openapi-skill login       # 配置（加密保存）\nnpx @insentek/openapi-skill logout      # 清除\nnpx @insentek/openapi-skill auth status # 查看连接状态\n```\n\n> npm 包名为 `@insentek/openapi-skill`，CLI 命令为 `insentek-api-skill`，两者等价。\n\n### 命令分工（MUST）\n\n| 用途 | 工具 | 示例 |\n|------|------|------|\n| 安装 / 更新 skill | `npx @insentek/openapi-skill` | `install -r openclaw -s workspace -y` |\n| 配置 / 清除凭据 | `npx insentek-api-skill login/logout/auth` | `npx insentek-api-skill login` |\n| 查安装路径 / 脚本位置 | `npx insentek-api-skill info/status/doctor --json` | 见下方「脚本路径解析」 |\n| **查询 API** | `python <SKILL_ROOT>/scripts/insentek_cli.py` | `python .../insentek_cli.py devices` |\n\n### 脚本路径解析（MUST，API 调用前）\n\nAgent 工作目录通常**不是** skill 安装目录。**禁止**使用相对路径 `python scripts/insentek_cli.py ...`。\n\n**首次 API 调用前**，或脚本路径未知 / 返回「文件找不到」时，**必须先**查实际安装位置：\n\n```bash\nnpx @insentek/openapi-skill status -r openclaw -s workspace --json\n# 或 info --json / doctor --json\n```\n\n从 JSON 读取 `results[].installDir` 作为 `${SKILL_ROOT}`，或直接使用 `results[].scripts.cli`。解析后在**本会话内缓存**，后续 API 调用复用，**不要**重复猜测路径。\n\nOpenClaw workspace 常见路径（仅供参考，**以 status/info 返回为准**）：\n`~/.openclaw/workspace/skills/insentek-openapi`\n\n**禁止（MUST NOT）：**\n- `python scripts/insentek_cli.py ...` — 相对路径在 OpenClaw 等环境下会失败\n- `npx insentek-api-skill devices` — `devices` 不是顶层命令，会误触发 `install`\n- 文件找不到时乱试其他命令 — **应重新 `status --json` 或 `info --json`**\n\n用户说「配置好了，继续吧」→ 从**中断前的意图**继续；若已有 `${SKILL_ROOT}` 直接调 API，**不要**重新 login。\n\n若工具返回 `authentication_required` 或 HTTP 401/403，**STOP** 并 **原样** 向用户展示以下固定文案（不得改写、不得追加索要 secret）：\n\n```\n这台电脑还没有连接 Insentek API，需要先完成一次本地配置，通常 1 分钟就好。\n\n请在终端运行：\n\nnpx insentek-api-skill login\n\n按提示输入 appid 和 secret 即可（加密保存在本机，无需发到这个对话）。配置完成后回来继续提问，我接着帮你处理。\n```\n\n---\n\n### query_device\n\n查询设备信息：列表、详情、别名解析。\n\n```json\n{\n  \"page\": { \"type\": \"integer\", \"default\": 1 },\n  \"limit\": { \"type\": \"integer\", \"default\": 20 },\n  \"sn\": { \"type\": \"string\", \"description\": \"设备序列号，与 alias 二选一\" },\n  \"alias\": { \"type\": \"string\", \"description\": \"设备别名，支持部分匹配\" }\n}\n```\n\n```bash\n# 列表（${SKILL_ROOT} 由 status/info 解析，见上方）\npython ${SKILL_ROOT}/scripts/insentek_cli.py devices [--page ${page}] [--limit ${limit}]\n# 详情\npython ${SKILL_ROOT}/scripts/insentek_cli.py device --sn ${sn}\n```\n\n**注意：** `--token` 变为可选。若未提供且已配置持久化凭据，脚本自动获取。\n\n**行为：** alias → 模糊匹配 → 多匹配时反问用户 → 单匹配时缓存 alias→sn 映射。\n\n---\n\n### query_data\n\n查询设备历史数据或实时数据。\n\n```json\n{\n  \"sn\": { \"type\": \"string\", \"required\": true },\n  \"time_expression\": { \"type\": \"string\", \"description\": \"自然语言时间描述，如'现在'、'昨天'、'最近7天'。不传默认最近24小时。\" },\n  \"range\": { \"type\": \"string\", \"description\": \"YYYYMMDD,YYYYMMDD，由 time_expression 自动计算\" },\n  \"includeParameters\": { \"type\": \"string\", \"description\": \"指定参数，逗号分隔，如 moisture,temperature\" }\n}\n```\n\n```bash\n# 历史数据\npython ${SKILL_ROOT}/scripts/insentek_cli.py data --sn ${sn} --range ${range} [--include-params ${params}]\n\n# 预览（调试/验证用）\npython ${SKILL_ROOT}/scripts/insentek_cli.py data --sn ${sn} --range ${range} --dry-run\n\n# 实时数据（latest）— 允许直接用 curl\n curl -s -H \"Authorization: ${token}\" \"http://openapi.ecois.info/v3/device/${sn}/latest\"\n```\n\n**注意：** `--token` 变为可选。若未提供且已配置持久化凭据，脚本自动获取。\n\n时间表达式解析见 `docs/interaction.md` Section 2。\n\n---\n\n### export_csv / export_excel / export_json\n\n用户意图明确为\"导出/下载\"时调用，而非 `query_data`。\n\n```bash\n# CSV\npython ${SKILL_ROOT}/scripts/insentek_cli.py export --sn ${sn} --range ${range} --format csv --output ${file}.csv\n\n# Excel\npython ${SKILL_ROOT}/scripts/export_excel.py --sn ${sn} --range ${range} --output ${file}.xlsx\n\n# JSON\npython ${SKILL_ROOT}/scripts/insentek_cli.py export --sn ${sn} --range ${range} --format json --output ${file}.json\n```\n\n**注意：** `--token` 变为可选。若未提供且已配置持久化凭据，脚本自动获取。\n\n所有导出脚本均支持 `--dry-run`。\n\n---\n\n### write_html\n\nAgent 完成数据分析后，将动态生成的 HTML 内容写入文件。\n\n```bash\necho \"${html_content}\" | python ${SKILL_ROOT}/scripts/write_html.py --output ${file}.html\n```\n\n---\n\n## 3. Guardrails\n\n### 3.1 硬限制\n\n| 限制项 | 规则 | 超限处理 |\n|--------|------|----------|\n| 单次查询跨度 | ≤ 365 天 | 拒绝，提供拆分选项 |\n| 历史回溯 | ≤ 3 年 | 拒绝，提示最早日期 |\n| 对话展示 | ≤ 200 条 | 展示摘要 + 首尾各 10 条抽样 |\n| 文件导出 | ≤ 50,000 条 | 拒绝，建议缩小范围或分批 |\n\n### 3.2 数据可用性校验（MUST）\n\n`query_data` 返回后，检查实际数据范围 vs 请求范围：\n\n```\nrequested_days = 用户请求的天数\nactual_days    = 实际返回数据的天数\ncoverage       = actual_days / requested_days\n\nIF coverage < 0.5 OR actual_days < 7:\n  → STOP\n  → 告知用户实际范围，询问是否继续\n  → 等待确认后才可生成报告/分析\nELSE IF actual_range < requested_range:\n  → 继续，但报告 MUST 使用 actual_range 标注\n```\n\n### 3.3 原始数据输出禁令（MUST）\n\nAgent **禁止**将原始传感器全量数据输出到对话中。\n\n| 场景 | 处理 |\n|------|------|\n| \"看看数据\" | 统计摘要 + 首尾各 5 条 |\n| \"调试\" | `--dry-run` 预览 |\n| \"给我原始数据\" | 引导导出 CSV/Excel |\n| \"全部发给我\" | 拒绝，解释 Token 限制 |\n\n完整输出格式规范见 `docs/interaction.md` Section 4。\n\n---\n\n## 4. Authentication\n\n### 4.1 CLI 本地凭据（唯一方式）\n\n用户 **必须** 通过 CLI 在本地配置凭据，Agent **不得** 在对话中收集 appid/secret：\n\n```bash\nnpx @insentek/openapi-skill login\nnpx @insentek/openapi-skill logout\nnpx @insentek/openapi-skill auth status\n```\n\n凭据加密保存在 `~/.config/insentek/credentials.json`（文件权限 600）。\n\n### 4.2 Agent 行为约束（MUST）\n\n| 场景 | Agent 行为 |\n|------|-----------|\n| 用户首次使用 / 未连接 | 展示 Section 2 固定引导文案，**禁止**索要 secret |\n| 用户主动发送 appid/secret | **拒绝接收**，说明请改用 CLI login |\n| 401/403 / `authentication_required` | 展示 Section 2 固定引导文案，STOP |\n| 用户要求\"重新认证\" | 引导 `npx @insentek/openapi-skill login`（更新）或 `logout` 后再 `login` |\n\n### 4.3 Token 获取策略\n\n脚本**管理 token 生命周期**，实现缓存 + 自动刷新机制：\n- CLI `login` 验证凭据后，凭据和 token 一并加密保存\n- 后续各命令 `--token` 参数变为可选\n- 未提供 `--token` 时，脚本**优先从配置文件读取缓存的 token**\n- 请求 API 时如果返回 401/403，脚本**自动刷新 token** 并重试一次\n- 刷新失败则返回 `authentication_required`，Agent 引导用户重新 `login`\n- 不检查 token 过期时间，靠 HTTP 401/403 触发刷新\n\n### 4.4 Token 缓存流程\n\n```\n请求 API\n  ├── 使用缓存 token\n  ├── 成功 → 返回数据\n  └── 401/403 → 调用 /v3/token 获取新 token → 更新配置文件 → 重试请求\n        └── 仍失败 → 返回 authentication_required → 引导 CLI login\n```\n\n### 4.5 安全说明\n\n- Secret **绝不**出现在对话、日志或 Agent 上下文中\n- 凭据文件权限 600，内容 AES-256-GCM 加密（机器绑定密钥）\n- Token 缓存有效期约 2 小时，靠 HTTP 401/403 触发自动刷新\n\n---\n\n**向后兼容：** 所有命令仍支持 `--token` 参数，现有调用方式不受影响。\n\n---\n\n## 5. Environment Check\n\n首次交互前，在解析 `${SKILL_ROOT}` 后执行：\n\n```bash\npython ${SKILL_ROOT}/scripts/insentek_cli.py check\n```\n\n关键项失败时 STOP，可选项失败时降级运行并告知用户。\n\n若 `checks.credentials.ok` 为 `false`，展示 Section 2 固定引导文案，**禁止**继续调用 API 或向用户索要 secret。\n\n---\n\n## 6. Error Handling\n\n| HTTP | 处理 |\n|------|------|\n| 200 | 正常处理 |\n| 400 | 检查参数格式后重试 |\n| 401/403 | **STOP**，展示 CLI login 引导文案，**禁止**向用户索要 secret |\n| 脚本找不到 / ENOENT | **STOP**，执行 `status --json` 或 `info --json` 解析 `${SKILL_ROOT}`，**禁止**乱试 npx 子命令 |\n| 404 | 确认设备 SN/别名 |\n| 429 | 限流，等待后重试 |\n| 500 | 指数退避重试 3 次 |\n\n脚本返回 `\"success\": false` 且 `error` 为 `authentication_required` 时，展示 Section 2 固定引导文案并 STOP。其他错误解析 `error`/`message` 字段：含\"范围/限制\"则解释护栏，否则展示友好错误。\n\n---\n\n## Notes\n\n- **Pagination**: `page` starts at 1.\n- **Values**: Nested `{node_name: {parameter_code: value}}`\n- **Alias**: Case-insensitive partial match on `alias`.\n- **Param names**: Use Chinese names from `/description` endpoint for display.\n- **Script-first**: API 用 `python ${SKILL_ROOT}/scripts/insentek_cli.py`；`${SKILL_ROOT}` 由 `status/info --json` 解析\n- **Dry-run**: Append `--dry-run` for preview; never output raw data to chat.\n- **Reference**: Edge cases → `reference/api-doc.md` (OpenAPI v3.1.9).\n\nFile v1.2.1:packages/insentek-skill-cli/README.md\n\n# @insentek/openapi-skill\n\nBootstrap the **insentek-openapi** skill for **OpenClaw** and **Claude Code**.\n\n| 类型 | 名称 |\n|------|------|\n| npm package | `@insentek/openapi-skill` |\n| skill id | `insentek-openapi` |\n| 安装目录 | `insentek-openapi` |\n| CLI 命令 | `insentek-api-skill` |\n\n安装路径由 CLI **按 runtime + scope 动态解析**。用 `info` / `doctor` 查看本机实际路径。\n\n## Quick Start\n\n```bash\nnpx @insentek/openapi-skill\n```\n\n## OpenClaw 用户：ClawHub 安装（独立方式）\n\nOpenClaw 用户也可通过 ClawHub 单独安装，与本 CLI 无关：\n\n```bash\nclawhub skill install insentek-api-skill\nclawhub skill remove insentek-api-skill\n```\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `install` | 安装 skill（默认命令，可交互选择 runtime） |\n| `login` | 配置 Insentek API 凭据（加密本地保存） |\n| `logout` | 清除已保存的凭据 |\n| `auth status` | 查看凭据连接状态 |\n| `update` | 更新已安装 skill 到当前包版本 |\n| `uninstall` | 卸载 |\n| `status` | 查看安装状态 |\n| `doctor` | 诊断路径、manifest、脚本与环境 |\n| `info` | 查看 package / skill / 动态解析路径 |\n\n## Options\n\n| Option | Description |\n|--------|-------------|\n| `-r, --runtime` | `claude`, `openclaw`, `all` |\n| `-s, --scope` | 见下方 Scope 说明 |\n| `-f, --force` | 覆盖已有安装 |\n| `-y, --yes` | 非交互（需配合 `-r`） |\n| `--json` | 输出 JSON（`install`/`update`/`uninstall` 需配合 `-y`） |\n\n### Scope 说明\n\n| Runtime | 支持的 scope |\n|---------|-------------|\n| Claude Code | `global`（默认）, `project` |\n| OpenClaw | `global`, `project`, `workspace` |\n\n`workspace` 仅 OpenClaw 支持；Claude Code 没有 workspace 概念。OpenClaw `workspace` 安装路径为 `~/.openclaw/workspace/skills`（Windows: `%USERPROFILE%\\.openclaw\\workspace\\skills`）。\n\n## Examples\n\n```bash\n# 交互式安装\nnpx @insentek/openapi-skill\n\n# 安装到 Claude Code（global）\nnpx @insentek/openapi-skill install -r claude -s global -y\n\n# 安装到 OpenClaw workspace\nnpx @insentek/openapi-skill install -r openclaw -s workspace -y\n\n# 查安装路径与脚本位置（Agent 应用此解析 SKILL_ROOT）\nnpx @insentek/openapi-skill status -r openclaw -s workspace --json\n\n# 凭据 / 诊断\nnpx @insentek/openapi-skill update -r claude -y\nnpx @insentek/openapi-skill doctor\nnpx @insentek/openapi-skill login\nnpx @insentek/openapi-skill logout\nnpx @insentek/openapi-skill auth status\nnpx @insentek/openapi-skill info\n\n# 脚本 / CI 使用 JSON 输出\nnpx @insentek/openapi-skill status -r claude --json\nnpx @insentek/openapi-skill install -r claude -s global -y --json\nnpx @insentek/openapi-skill doctor --json\n```\n\n## Development / 本地测试\n\n包尚未发布到 npm 时，`npx @insentek/openapi-skill` 会失败。本地请用下面任一方式：\n\n```powershell\ncd packages/insentek-skill-cli\nnpm install\nnpm run sync-assets\nnpm test\n```\n\n**方式一：直接跑（最简单）**\n\n```powershell\nnode bin/insentek-api-skill.js info\nnode bin/insentek-api-skill.js\nnode bin/insentek-api-skill.js install -r claude -s global -y\n```\n\n**方式二：模拟 npx（在 CLI 目录下）**\n\n```powershell\nnpx . info\nnpx .\nnpx . install -r claude -s global -y\n```\n\n**方式三：全局 link 后按发布命令测**\n\n```powershell\nnpm link\nnpx @insentek/openapi-skill info\ninsentek-api-skill doctor\n```\n\n**方式四：模拟正式发布**\n\n```powershell\nnpm run sync-assets\nnpm pack\nnpm install -g .\\insentek-openapi-skill-1.2.1.tgz\ninsentek-api-skill info\n```\n\n修改 `SKILL.md` / `scripts/` 后需重新 `npm run sync-assets` 再测。\n\nRequires Node.js 18+.\n\nFile v1.2.1:README.md\n\n# Insentek OpenAPI Skill\n\n> 让终端用户用自然语言轻松查询 insentek（东方智感）物联网设备数据。\n\n---\n\n## 简介\n\n本项目基于 insentek OpenAPI v3，产出一份通用 `skill.md` 技能文件及配套文档与示例。终端用户可在 **OpenClaw、Hermes-Agent、Claude Code、ChatGPT** 等 Agent 平台上直接对话使用，通过自然语言调用 API 完成设备数据查询、报告生成与实时分析。\n\n**支持的设备类型：**\n- 🌱 **Z** — 土壤墒情仪（土壤温度、水分、电导率）\n- 🌤️ **T** — 气象站（空气温度、湿度、风速、降雨量、PM2.5 等）\n- 📏 **J** — 见厘液位计（激光液位、电池电压）\n\n---\n\n## 快速开始\n\n### 1. 获取认证信息\n\n登录 [E 生态](https://cloud.ecois.info)，在「应用管理」中创建应用，获取 `appid` 和 `secret`。\n\n### 2. 安装 Skill\n\n**一键安装（推荐）：**\n\n```bash\nnpx @insentek/openapi-skill\n```\n\n| 类型 | 名称 |\n|------|------|\n| npm package | `@insentek/openapi-skill` |\n| skill id | `insentek-openapi` |\n| 安装目录 | `insentek-openapi` |\n\nCLI 会引导选择 **runtime**（OpenClaw / Claude Code），支持 **scope**（`global` / `project` / `workspace`），并动态解析本机安装路径。\n\n```bash\nnpx @insentek/openapi-skill install -r claude -s global -y\nnpx @insentek/openapi-skill update -r claude -y\nnpx @insentek/openapi-skill doctor\nnpx @insentek/openapi-skill info\n```\n\nOpenClaw 用户也可通过 ClawHub 单独安装（与本 CLI 无关）：\n\n```bash\nopenclaw skills install insentek-api-skill\n```\n\n| 命令 | 说明 |\n|------|------|\n| `install` | 安装 skill |\n| `update` | 更新到当前包版本 |\n| `status` / `doctor` | 查看状态 / 诊断 |\n| `uninstall` | 卸载 |\n\n> CLI 源码见 [`packages/insentek-skill-cli/`](packages/insentek-skill-cli/)。路径因 runtime/scope/OS 而异，请用 `info` / `doctor` 查看本机实际位置。\n\n### 3. 开始对话\n\n```\nUser: 我的 appid 是 xxx，secret 是 yyy，查看所有设备\n```\n\n更多用法见 [`docs/getting-started.md`](docs/getting-started.md)。\n\n---\n\n## 项目结构\n\n```\n.\n├── skill.md                     # 核心技能文件 (Runtime Contract)\n├── docs/\n│   ├── getting-started.md       # 快速开始指南\n│   ├── platform-setup.md        # 各平台配置指南\n│   ├── interaction.md           # 交互规范 (意图/时间/输出格式)\n│   └── analysis.md              # 分析策略 (报告/告警/行业参数)\n├── reference/\n│   └── api-doc.md               # 完整 API 文档 (OpenAPI v3.1.9)\n├── examples/\n│   ├── queries.md               # 查询类对话示例\n│   ├── reports.md               # 报告生成示例\n│   └── flows.md                 # 核心交互流程示例\n├── scripts/                     # 参考实现脚本\n│   ├── insentek_cli.py          # 统一 CLI（认证/查询/导出）\n│   ├── export_excel.py          # Excel 导出\n│   └── README.md                # 脚本使用说明\n├── PLATFORM-TEST.md             # 跨平台测试计划（自检清单）\n└── ref/                         # 参考材料（API 仓库 + 文档）\n    ├── api-repo/                # Spring Boot API 源码\n    └── api-document-latest.pdf  # 官方接口文档\n```\n\n---\n\n## 核心功能\n\n| 功能 | 说明 |\n|------|------|\n| 🔐 自动认证 | appid+secret → token，自动缓存与刷新 |\n| 📋 设备管理 | 列表查询、别名解析、单设备详情 |\n| 📊 数据查询 | 实时/历史/指定时刻/增量同步 |\n| 🧠 智能推断 | 自然语言时间自动解析（\"上周\"→日期范围） |\n| 🔗 链式调用 | alias → SN → 数据，自动串联 |\n| 📈 趋势分析 | 平均值/最大值/最小值/变化率自动计算 |\n| ⚖️ 跨设备对比 | 并排比较 + 差异高亮 |\n| ⚠️ 异常检测 | 电池过低、水分异常、温度突变自动标记 |\n| 🏭 多行业适配 | Z/T/J 设备类型自动识别与参数翻译 |\n| 🎯 意图确认 | 输出形式不明确时自动询问（查看/导出/报告） |\n| 🛡️ 查询边界 | 最大1年/3年回溯/5万条导出上限，超限自动拦截 |\n| 📤 数据导出 | CSV / Excel / JSON / HTML 报告一键生成 |\n| 🔍 环境检查 | 首次使用前自动检查 Python、脚本、依赖、API 可达性 |\n\n---\n\n## 对话示例\n\n**查看设备列表**\n```\nUser: 查看我的设备\nAgent: 📋 设备列表（共 3 台）...\n```\n\n**查询实时数据**\n```\nUser: 1号大棚现在的温度\nAgent: 📍 1号大棚 — 10cm: 18.5℃, 20cm: 17.2℃ ...\n```\n\n**历史趋势**\n```\nUser: 最近7天的土壤湿度变化\nAgent: 📊 趋势表格 + 平均/最高/最低/变化率小结\n```\n\n**异常检测**\n```\nUser: 检查所有设备的电池\nAgent: 🔋 巡检报告 — 2号大棚 2.85V 🔴 过低\n```\n\n更多示例见 [`examples/`](examples/)。\n\n---\n\n## 时间表达支持\n\n| 你说 | Agent 理解 |\n|------|-----------|\n| \"现在\" / \"最新\" / \"实时\" | 调用 /latest |\n| \"昨天\" / \"上周\" / \"本月\" | 自动计算 YYYYMMDD,YYYYMMDD |\n| \"最近7天\" / \"近一周\" | 过去 7 天 |\n| \"12点30分\" / \"某时刻\" | 调用 /moment/{datetime} |\n| \"同步\" / \"增量\" | 调用 /incremental |\n| *(没提时间)* | 默认最近 24 小时 |\n\n---\n\n## 平台兼容性\n\n| 特性 | OpenClaw | Claude Code | ChatGPT | Hermes-Agent |\n|------|:--------:|:-----------:|:-------:|:------------:|\n| Function Schema | ✅ | ✅ | ⚠️ Actions | ✅ |\n| 自动 Token 刷新 | ✅ | ✅ | ⚠️ | ✅ |\n| 别名解析 | ✅ | ✅ | ✅ | ✅ |\n| 时间推断 | ✅ | ✅ | ✅ | ✅ |\n| 链式调用 | ✅ | ✅ | ✅ | ✅ |\n\n⚠️ = 需额外配置（详见 [`docs/platform-setup.md`](docs/platform-setup.md)）\n\n---\n\n## API 参考\n\n- **Base URL**: `http://openapi.ecois.info`\n- **认证**: `GET /v3/token?appid={appid}&secret={secret}`\n- **设备**: `/v3/devices`, `/v3/device/{sn}`, `/v3/device/{sn}/description`\n- **数据**: `/v3/device/{sn}/data`, `/latest`, `/moment/{datetime}`, `/incremental`\n\n完整参数说明见 [`reference/api-doc.md`](reference/api-doc.md)。\n\n---\n\n## 版本\n\n- **当前版本**: v1.1.0\n- **API 版本**: insentek OpenAPI v3\n- **更新日期**: 2026-05-22\n\n---\n\n## 贡献\n\n本项目为内容产出型项目，主要交付物为 `skill.md` 及配套文档。\n\n如需反馈问题或建议：\n1. 检查 [`PLATFORM-TEST.md`](PLATFORM-TEST.md) 确认是否为已知限制\n2. 提交 issue 到项目仓库\n\n---\n\n## 许可证\n\n待定 / 请参考 insentek 官方使用条款\n\n---\n\n*Generated with Claude Code · 基于 insentek OpenAPI v3*\n\nFile v1.2.1:scripts/README.md\n\n# Insentek OpenAPI Scripts\n\n本目录包含 Insentek OpenAPI 的参考实现脚本。Agent 通过调用这些脚本完成 API 交互、数据导出和报告生成，而非直接使用 `curl` 命令。\n\n## 设计原则\n\n1. **统一入口**: `insentek_cli.py` 封装所有 API 调用，Agent 只需学习一套参数风格\n2. **边界内置**: 脚本内部实现时间范围限制、数据量检查，Agent 无需重复实现\n3. **结构化输出**: 所有脚本输出 JSON 到 stdout，便于 Agent 解析和决策\n4. **零配置运行**: 仅依赖 Python 标准库（Excel 导出除外）\n\n## 脚本列表\n\n| 脚本 | 功能 | 依赖 |\n|------|------|------|\n| `insentek_cli.py` | 统一 CLI：设备查询、数据查询、CSV/JSON 导出 | Python 3.8+ |\n| `credential_store.py` | 凭据加密读写（与 CLI login 兼容） | Python 3.8+, cryptography（读取加密凭据时） |\n| `write_html.py` | HTML 文件写入：将 AI 生成的 HTML 内容安全落盘 | Python 3.8+ |\n| `export_excel.py` | Excel 导出（多 sheet：原始数据 + 统计摘要） | Python 3.8+, openpyxl |\n\n## 使用示例\n\n### 环境检查（首次使用前必做）\n```bash\npython insentek_cli.py check\n```\n\n输出示例：\n```json\n{\n  \"success\": true,\n  \"all_checks_passed\": true,\n  \"checks\": {\n    \"python\": {\"ok\": true, \"version\": \"3.11.0\", \"message\": \"Python 3.11.0 满足要求 (>=3.8)\"},\n    \"scripts_cli\": {\"ok\": true, \"path\": \"...\", \"message\": \"核心脚本 insentek_cli.py 已找到\"},\n    \"scripts_excel\": {\"ok\": true, \"path\": \"...\", \"message\": \"Excel 脚本 export_excel.py 已找到\"},\n    \"scripts_write_html\": {\"ok\": true, \"path\": \"...\", \"message\": \"HTML 写入脚本 write_html.py 已找到\"},\n    \"openpyxl\": {\"ok\": true, \"version\": \"3.1.2\", \"message\": \"openpyxl 3.1.2 已安装，Excel 导出可用\"},\n    \"curl\": {\"ok\": true, \"message\": \"curl 可用，可作为脚本不可用时的 fallback\"},\n    \"api_reachable\": {\"ok\": true, \"status\": 400, \"message\": \"API 服务可访问（HTTP 400，未提供认证参数）\"}\n  },\n  \"summary\": {\n    \"critical\": \"通过\",\n    \"optional\": \"全部通过\",\n    \"message\": \"环境检查通过，所有功能可用。\"\n  }\n}\n```\n\n### 认证\n\n凭据通过 CLI 本地配置，**不要在对话中提供 secret**：\n\n```bash\nnpx @insentek/openapi-skill login\nnpx @insentek/openapi-skill logout\nnpx @insentek/openapi-skill auth status\n```\n\n脚本会自动从 `~/.config/insentek/credentials.json` 读取加密凭据，`--token` 参数可选。\n\n### 查询设备列表\n```bash\npython insentek_cli.py devices --page 1 --limit 20\n```\n\n### 查询数据（含边界检查）\n```bash\npython insentek_cli.py data --token YOUR_TOKEN --sn 00000000000000 --range 20250101,20250131\n```\n\n### 导出 CSV\n```bash\npython insentek_cli.py export --token YOUR_TOKEN --sn 00000000000000 --range 20250101,20250131 --format csv --output data.csv\n```\n\n### 导出 Excel\n```bash\npython export_excel.py --token YOUR_TOKEN --sn 00000000000000 --range 20250101,20250131 --output data.xlsx\n```\n\n### 写入 HTML 报告（AI 动态生成内容后落盘）\n```bash\npython write_html.py --content \"<html>...</html>\" --output report.html\n```\n\n## 输出格式\n\n所有脚本成功时输出：\n```json\n{\n  \"success\": true,\n  \"total\": 1000,\n  \"file\": \"/path/to/file.csv\",\n  \"message\": \"成功导出 1000 条数据到 data.csv\"\n}\n```\n\n失败时输出：\n```json\n{\n  \"success\": false,\n  \"error\": \"单次查询最多支持 1 年范围...\"\n}\n```\n\n## 边界限制\n\n| 限制项 | 值 | 说明 |\n|--------|-----|------|\n| 单次最大跨度 | 365 天 | 超过则拒绝并提示拆分 |\n| 最大历史回溯 | 3 年 | 基于当前日期 |\n| 对话展示上限 | 200 条 | 超过则展示摘要+抽样 |\n| 文件导出上限 | 50,000 条 | 超过则拒绝并建议缩小范围 |\n\nFile v1.2.1:_meta.json\n\n{\n  \"ownerId\": \"kn7dcqpad4aeh2nt5shjf3aerd875anm\",\n  \"slug\": \"insentek-api-skill\",\n  \"version\": \"1.2.1\",\n  \"publishedAt\": 1779784353001\n}\n\nFile v1.2.1:CHANGELOG.md\n\nChangelog\n=========\n\n[1.2.1] - 2026-05-26\n--------------------\n\nAdded\n-----\n\n- **`@insentek/openapi-skill` CLI 凭据管理**\n  - `login` — 交互式配置 appid/secret，AES-256-GCM 加密保存至 `~/.config/insentek/credentials.json`\n  - `logout` — 清除本地凭据\n  - `auth status` — 查看连接状态（脱敏展示）\n  - 安装流程检测凭据，未配置时引导 `login`\n\n- **`scripts/credential_store.py`**\n  - 与 CLI 加密格式兼容，供 `insentek_cli.py` 读取本地凭据\n  - 修复 `AESGCM.decrypt()` 缺少 `associated_data=None` 导致解密失败的问题\n\n- **CLI `status` / `info --json` 脚本路径**\n  - JSON 输出新增 `scripts.cli`、`scripts.exportExcel`、`scripts.writeHtml`，便于 Agent 解析 `${SKILL_ROOT}`\n\nChanged\n-------\n\n- **认证安全模型（skill.md / docs）**\n  - Agent **禁止**在对话中索要或接收 appid/secret\n  - 401/403 / `authentication_required` 时展示固定引导文案，引导 `npx insentek-api-skill login`\n  - API 调用使用 `python ${SKILL_ROOT}/scripts/insentek_cli.py`；`${SKILL_ROOT}` 由 `status/info --json` 解析，**禁止**相对路径 `scripts/...`\n  - 文件找不到时先查安装路径，**禁止**乱试 `npx insentek-api-skill devices` 等错误命令\n\n- **OpenClaw workspace 安装路径**\n  - `workspace` scope 修正为 `~/.openclaw/workspace/skills/insentek-openapi`（Windows: `%USERPROFILE%\\.openclaw\\workspace\\skills\\...`）\n\n- **Windows 覆盖安装**\n  - `--force` 安装时在 Windows 上改为原地覆盖文件，避免 OpenClaw 占用目录导致 `rename` EPERM\n\n- **`insentek_cli.py`**\n  - 移除对话侧 `auth --appid/--secret` 写入能力；凭据仅通过 CLI `login` 配置\n  - `check` 增加 `credentials` 检查项\n\n- **文档**\n  - 更新 `docs/getting-started.md`、`docs/interaction.md`、`docs/platform-setup.md`、`examples/queries.md`\n  - CLI README 补充 scope 路径说明与凭据命令\n\nFixed\n-----\n\n- OpenClaw workspace 目录解析错误（此前误用项目根目录下的 `skills/`）\n- Python 无法解密 Node CLI 写入的加密凭据\n- Agent 在 login 后误用 `npx insentek-api-skill devices`（非顶层命令）或相对路径脚本\n\n[1.1.0] - 2026-05-22\n--------------------\n\nChanged\n-------\n\n- **结构性重构: skill.md 模块化拆分**\n  - 主 `skill.md` 从 1100+ 行瘦身至 ~250 行 (Runtime Contract 风格)\n  - 新增 `docs/interaction.md` — 意图解析、时间表达式、输出格式、确认策略\n  - 新增 `docs/analysis.md` — 分析策略、报告生成、告警规则、行业参数\n  - 新增 `examples/flows.md` — 3 个核心交互示例（查询/导出/报告含数据校验）\n  - 删除 `examples/alerts.md`（内容合并至 docs/analysis.md）\n\n- **MUST → SHOULD 降级**\n  - 安全/护栏类保持 MUST（raw_data_output, span limit, auth security）\n  - 分析类降级为 SHOULD / RECOMMENDED / PREFER\n  - 模型分析创造力不再被规则过度压制\n\n- **三层职责分离**\n  - Runtime Contract（skill.md）: 工具、护栏、认证、路由\n  - Interaction Policy（docs/interaction.md）: UX、确认、输出格式\n  - Analysis Engine（docs/analysis.md）: 动态分析、报告、可视化\n\n- **新增 Routing 决策表**\n  - skill.md Section 1: L1意图 × L2输出 → 工具路由矩阵\n  - Agent 无需逐行阅读即可快速定位调用路径\n\n- **版本号统一 bumped 1.0.3 → 1.1.0**\n  - skill.md, README.md, PLATFORM-TEST.md, docs/platform-setup.md\n\n[1.0.3] - 2026-05-22\n--------------------\n\nAdded\n-----\n\n- 数据可用性校验 (skill.md Section 2.5)\n  - `query_data` 返回后 Agent 必须检查实际数据范围 vs 用户请求范围\n  - 若实际覆盖比例 < 50% 或天数 < 7 天，必须 STOP 并向用户确认\n  - 确认消息包含：请求范围、实际范围、可能原因（设备未部署/离线）\n  - 用户确认后才允许继续生成报告\n\n- 报告时间范围标注规范 (skill.md Section 8.3)\n  - 实际范围 = 请求范围：正常标注\n  - 实际范围 < 请求范围：必须注明 \"基于实际可用数据: [actual_range]\"\n  - 绝不允许用请求范围替代实际范围，避免误导用户\n\n- Flow 7 数据范围不匹配处理示例 (skill.md Section 12)\n  - 新增完整交互示例：用户请求近3个月，实际仅13天\n  - 展示 Agent 如何向用户说明情况并等待确认\n\nChanged\n-------\n\n- 报告生成流程 (skill.md Section 8.3)\n  - 在 `query_data` 与 `Agent analyzes data` 之间插入数据可用性校验步骤\n  - Flow 6 增加 `[数据可用性校验] → PASS` 标注\n\n- 版本号统一 bumped 1.0.2 → 1.0.3\n  - skill.md, README.md, PLATFORM-TEST.md, docs/platform-setup.md\n\nWhy\n---\n\n- 用户实际测试发现：请求近3个月数据时，设备仅有13天数据\n- 旧版本直接生成报告并标注\"近3个月\"，对用户产生严重误导\n- 新增校验机制确保报告时间范围真实反映数据可用性\n\n[1.0.2] - 2026-05-21\n--------------------\n\nAdded\n-----\n\n- `scripts/write_html.py` — HTML file writer utility\n  - Receives AI-generated HTML content and writes it to disk\n  - No templating or data processing; purely a safe file-writing tool\n  - Supports `--content`, `--input-file`, and stdin input\n  - Minimal HTML structure validation (warnings only, non-blocking)\n  - Structured JSON output for Agent consumption\n\nChanged\n-------\n\n- Removed deprecated `report` / `chart` / `export --format html` from `scripts/insentek_cli.py`\n  - Deleted `generate_report()`, `generate_chart()`, `get_device_info()`, `extract_param_names()` (~480 lines)\n  - HTML reports are now fully Agent-generated; no hard-coded templates\n  - Updated docstring and argparse to reflect only csv/json export\n\n- Updated `skill.md`\n  - Replaced Section 6.4 `generate_report (DEPRECATED)` with 6.4 `write_html`\n  - Added `write_html.py` to environment check items (non-critical)\n  - Changed API doc reference from active guidance to fallback note in Notes\n  - Updated `--dry-run` note to remove `report` and `chart`\n\n- Updated `.planning/STATE.md`\n  - Added `write_html.py` to Utility Scripts list\n  - Removed HTML export from `insentek_cli.py` description\n\nWhy\n---\n\n- User requirements for reports are diverse; fixed templates cannot cover all scenarios\n- Delegate report generation to AI for flexibility (dynamic analysis, custom visualizations)\n- Provide a clean, single-purpose tool for HTML file output rather than monolithic report generators\n\n[1.0.1] - 2026-05-21\n--------------------\n\nAdded\n-----\n\n- --dry-run preview mode (scripts/insentek_cli.py)\n  - data, export (csv/json/html), report, chart subcommands all support --dry-run\n  - Only outputs record count, time range, field summary (nodes/parameters), and first 5 sample rows\n  - Does not write files or output full data, preventing context explosion during debugging\n\n- --dry-run preview mode (scripts/export_excel.py)\n  - Added --dry-run parameter, behavior consistent with CLI script\n  - Does not generate Excel file, only returns structured JSON preview\n\n- Raw data output prohibition (skill.md)\n  - Added Section 2.4 \"Raw Data Output Prohibition\"\n  - Explicitly prohibits Agent from outputting raw sensor full data directly into conversation\n  - Specifies handling for four common scenarios: summary sampling, --dry-run, guided export, direct refusal\n\n- YAML Guardrails declaration (skill.md frontmatter)\n  - Added guardrails.raw_data_output: PROHIBITED\n  - Added guardrails.dry_run_preview_rows: 5\n  - Added guardrails.max_chat_rows: 200\n  - Added guardrails.max_export_rows: 50000\n\n- Dry-run documentation (skill.md)\n  - Added Section 6.0 \"dry-run preview mode (common to all export scripts)\"\n  - Added --dry-run example in query_data Agent Action\n  - Added \"Dry-run first\" and \"Raw data prohibition\" development guidelines in Notes\n\nChanged\n-------\n\n- Version bumped from 1.0.0 to 1.0.1 (skill.md, README.md, PLATFORM-TEST.md, .planning/STATE.md)\n\nWhy\n---\n\n- Prevent accidental full sensor data injection into conversation context\n- Save Token consumption and improve model processing efficiency\n- Promote as Skill development standard: summaries in chat, full data in files\n\n\n[1.0.0] - 2026-05-14\n--------------------\n\nAdded\n-----\n\n- Initial release with intent resolution, query guardrails, and export scripts\n- Three-layer intent model (L1 core -> L2 output -> L3 format)\n- Query guardrails: max 365 days span, max 3 years history, max 200 chat rows, max 50000 export rows\n- Utility scripts: insentek_cli.py (unified CLI), export_excel.py (Excel export)\n- Environment prerequisites check command\n- Session-based authentication caching\n- Multi-industry adaptation (agriculture, meteorology, industrial level monitoring)\n\nFile v1.2.1:CLAUDE.md\n\n# insentek-api-skills\n\nThis is a GSD-managed project. Use `/gsd-progress` to check status and next steps.\n\n## Project Overview\n\n基于 insentek OpenAPI 工程仓库和接口文档，产出一份通用 `skill.md` 技能文件及配套文档与示例。终端用户可在 OpenClaw、Hermes-Agent、Claude Code、ChatGPT 等 Agent 平台上直接对话使用，通过自然语言调用 insentek API 完成设备数据查询、报告生成与实时分析。\n\n## Quick Links\n\n- Project context: `.planning/PROJECT.md`\n- Requirements: `.planning/REQUIREMENTS.md`\n- Roadmap: `.planning/ROADMAP.md`\n- Current state: `.planning/STATE.md`\n\n## Working with This Project\n\n1. Always read `.planning/STATE.md` first to understand current phase and focus\n2. Check `.planning/PROJECT.md` for core value and constraints\n3. Follow the roadmap phase order\n4. Update STATE.md when phase status changes\n\n## Key Decisions\n\n- Single universal `skill.md` (not per-industry splits)\n- Content production project (not a tool/generator)\n- Horizontal Layers phase structure\n- 1-2 week delivery timeline\n\n## Reference Materials\n\n- API codebase: `ref/api-repo/` (Spring Boot 3.5.4, Java 21)\n- API documentation: `ref/api-document-latest.pdf`\n\nFile v1.2.1:docs/analysis.md\n\n# Analysis Guide — 分析与报告\n\n> Agent 驱动的数据分析策略、报告生成规范、告警检测规则。\n> 本文件按需加载，仅在用户提出分析/报告需求时读取。\n\n---\n\n## 1. Analysis Philosophy\n\n分析由 Agent **动态推理**完成，避免硬编码模板。\n\n**推荐流程：**\n1. **Parse intent** — 用户到底想知道什么？（相关性、异常、趋势、对比）\n2. **Select method** — 根据问题选择合适的统计/数学方法\n3. **Compute** — 用 Python 脚本实时计算\n4. **Synthesize** — 用自然语言解释，结合领域上下文\n5. **Deliver** — 表格、图表、HTML 报告\n\n**语气：** 分析部分使用 SHOULD / RECOMMENDED / PREFER，不强制具体方法。\n\n---\n\n## 2. Common Patterns\n\n| 用户问题 | 推荐方法 | 交付物 |\n|---------|---------|--------|\n| \"分析 X 和 Y 的关系\" | Pearson/Spearman 相关 + 散点图 | 相关系数 + 散点图 + 解释 |\n| \"找出异常数据\" | 阈值检测或统计离群点 | 异常列表 + 时间标记 |\n| \"对比两台设备\" | 并排统计 + 差异分析 | 对比表 + 差异高亮 |\n| \"最近有什么趋势\" | 线性回归 / 变化率 | 趋势方向 + 变化率 + 图表 |\n| \"降雨最多的几天\" | 百分位 / 最大值筛选 | 极值列表 + 日期 |\n| \"数据分布如何\" | 直方图 / 分位数 (P10/P50/P90) | 分布图 + 分位数 |\n| \"昼夜温差多大\" | 昼夜分段 + 范围计算 | 昼夜统计对比表 |\n| \"近一年每日趋势\" | 按天聚合 (daily average) | 折线图 + 月度统计 |\n\n**Key Principle:** 输出应直接回答用户问题，而非堆砌统计数据。\n\n---\n\n## 3. Report Generation Guide\n\n### 3.1 流程\n\n```\nquery_device → resolve sn\nquery_data → retrieve data\n[数据可用性校验] → 见 skill.md 3.2\nanalyze (statistics, trends, anomalies)\nconstruct HTML (ECharts + CSS)\nwrite_html → return path\n```\n\n### 3.2 HTML 结构（RECOMMENDED）\n\n```html\n<!-- 最小骨架示例 -->\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <script src=\"https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js\"></script>\n  <style>/* 简洁响应式布局 */ body { font-family: sans-serif; max-width: 960px; margin: 0 auto; } </style>\n</head>\n<body>\n  <h1>设备分析报告</h1>\n  <div class=\"header\">\n    设备: [别名] (SN: [后4位]) | 类型: [Z/T/J] | 位置: [城市]\n    分析时段: [actual_range] | 数据点: [N] 条\n  </div>\n  <div class=\"key-findings\"><!-- 核心指标卡片 --></div>\n  <div class=\"charts\"><!-- ECharts 图表容器 --></div>\n  <div class=\"details\"><!-- 详细表格 --></div>\n  <div class=\"conclusion\"><!-- 文字总结 --></div>\n</body>\n</html>\n```\n\n### 3.3 时间范围标注规范（MUST）\n\n| 场景 | 标注方式 |\n|------|---------|\n| 实际 = 请求 | `\"分析时段: [范围]\"` |\n| 实际 < 请求 | `\"分析时段: [actual_range]（您请求的 [requested_range] 中，该设备仅有此区间数据）\"` |\n\n**绝不允许**用请求范围替代实际范围。\n\n### 3.4 可视化推荐\n\n- **时间序列趋势** → ECharts line chart\n- **两变量关系** → ECharts scatter plot\n- **多维度对比** → ECharts bar chart 或 radar chart\n- **地理分布** → ECharts map (如有位置数据)\n- **分布分析** → ECharts histogram 或 box plot\n\n### 3.5 Anti-patterns\n\n- 不要在项目目录中创建 `generate_report_v2.py` 等可复用脚本\n- 每个报告应 ad-hoc 生成，用完即删临时脚本\n- 不要只放图表不加文字解释\n\n完整报告示例见 `examples/reports.md`。\n\n---\n\n## 4. Alert Detection Rules\n\n数据获取后，自动扫描异常：\n\n| 参数 | 告警条件 | 严重级别 |\n|------|---------|---------|\n| `moisture` (土壤水分) | < 5% or > 50% | Warning |\n| `temperature` (温度) | 1小时内变化 > 10°C | Critical |\n| `battery` (电池电压) | < 3.0V | Critical |\n| `ec` (电导率) | < 0 or > 20 | Warning |\n| `laserliquidLevel` (激光液位) | < 0 | Warning |\n\n**输出格式：**\n```\n⚠️ 异常数据检测\n- [参数名] 在 [节点] [时间]: [值] [单位] — [异常描述]\n```\n\n---\n\n## 5. Multi-Industry Parameters\n\n设备类型决定显示参数的中文名：\n\n| 类型码 | 行业 | 关键参数 |\n|--------|------|---------|\n| `Z` | 农业 / 土壤监测 | moisture, temperature, ec |\n| `T` | 气象 / 气象站 | airTemperature, relativeHumidity, rainfall, wind... |\n| `J` | 工业 / 液位监测 | laserliquidLevel, battery |\n\n通过 `/v3/device/{sn}/description` 获取参数中文名，优先用中文展示。\n\n完整参数参考见 `reference/api-doc.md`。\n\nFile v1.2.1:docs/getting-started.md\n\n# Getting Started — 快速开始\n\n> 5 分钟内配置完成，开始用自然语言查询设备数据。\n\n---\n\n## 你需要什么\n\n| 项目 | 说明 | 获取方式 |\n|------|------|---------|\n| `appid` | 应用 ID | E 生态后台创建应用后获得 |\n| `secret` | 应用密钥 | 与 appid 同时生成 |\n| 设备 | 已接入 insentek 平台的物联网设备 | 联系 insentek 或自行部署 |\n\n---\n\n## 第一步：在 E 生态获取 appid 和 secret\n\n1. 登录 [E 生态](https://www.ecois.info)\n2. 进入「应用管理」→「创建应用」\n3. 复制 `appid` 和 `secret`\n4. **妥善保存 secret** — 后续仅在 CLI `login` 时输入，**不要**在 Agent 对话中发送\n\n---\n\n## 第二步：安装 Skill 并通过 CLI 配置凭据\n\n推荐使用 CLI 一键安装：\n\n```bash\nnpx @insentek/openapi-skill\n```\n\n安装过程中若检测到尚未配置凭据，CLI 会引导你运行：\n\n```bash\nnpx @insentek/openapi-skill login\n```\n\n在 `login` 提示中输入第一步获得的 appid 和 secret。凭据会加密保存在 `~/.config/insentek/credentials.json`（文件权限 600）。\n\n也可手动将 `skill.md` 加载到 Agent 平台，但仍需先完成 CLI `login`，详见 [platform-setup.md](platform-setup.md)。\n\n---\n\n## 第三步：开始对话\n\n配置完成后，直接用自然语言查询：\n\n> **User:** 帮我查看所有设备。\n\nAgent 会自动读取本地凭据、查询设备列表并返回结果。\n\n若未连接 API，Agent 会展示如下固定引导文案（见 `skill.md` Section 2）：\n\n```\n这台电脑还没有连接 Insentek API，需要先完成一次本地配置，通常 1 分钟就好。\n\n请在终端运行：\n\nnpx insentek-api-skill login\n\n按提示输入 appid 和 secret 即可（加密保存在本机，无需发到这个对话）。配置完成后回来继续提问，我接着帮你处理。\n```\n\n---\n\n## 常用查询示例\n\n### 查看设备列表\n```\n查看我的设备\n```\n\n### 查询实时数据\n```\n3号设备现在的温度是多少？\n```\n\n### 查询历史数据\n```\n1号设备上周的土壤湿度变化\n```\n\n### 多设备对比\n```\n对比一下1号和2号设备的温度\n```\n\n### 异常检测\n```\n检查一下所有设备的电池状态\n```\n\n---\n\n## 支持的设备类型\n\n| 类型代码 | 设备名称 | 典型参数 |\n|---------|---------|---------|\n| `Z` | 土壤墒情仪 | 土壤温度、土壤水分、电导率 |\n| `T` | 气象站 | 空气温度、湿度、风速、降雨量 |\n| `J` | 见厘液位计 | 激光液位、电池电压 |\n\n---\n\n## 时间表达支持\n\n你可以用自然语言描述时间，Agent 会自动转换：\n\n| 你说 | Agent 理解 |\n|------|-----------|\n| \"现在\" / \"最新\" / \"实时\" | 调用实时数据接口 |\n| \"昨天\" | 昨天的全部数据 |\n| \"最近7天\" / \"近一周\" | 过去 7 天的数据 |\n| \"上周\" | 上周一至周日 |\n| \"本月\" | 本月 1 号到今天 |\n| \"某时刻\" / \"12点30分\" | 指定时间点的数据 |\n| *(没提时间)* | 默认最近 24 小时 |\n\n---\n\n## 下一步\n\n- 查看 [platform-setup.md](platform-setup.md) 了解各平台详细配置步骤\n- 查看 [`reference/api-doc.md`](../reference/api-doc.md) 了解完整 API 参数详情\n- 查看项目根目录 `examples/` 目录中的对话示例\n\n---\n\n## 常见问题\n\n**Q: token 多久过期？**\nA: 默认 2 小时（7200 秒）。脚本在 API 返回 401/403 时自动刷新 token，无需在对话中重新提供凭据。\n\n**Q: 可以在对话里告诉 Agent 我的 appid 和 secret 吗？**\nA: **不可以。** 凭据仅通过 `npx @insentek/openapi-skill login` 在本地配置，Agent 不会也不应接收这些敏感信息。\n\n**Q: 可以用设备别名查询吗？**\nA: 可以。Agent 支持别名部分匹配，如 \"3号\" 会匹配别名为 \"3号大棚\" 的设备。\n\n**Q: 数据查询有时间范围限制吗？**\nA: 增量同步接口（/incremental）首次调用返回最近 3 个月数据。历史数据查询最大支持 3 年回溯，单次查询跨度不超过 365 天。建议单次查询不超过 30 天以提高响应速度。\n\n**Q: 支持英文查询吗？**\nA: skill.md 中的 Prompt 指令为中文，但 Agent 平台通常支持多语言理解。英文查询的效果取决于具体 Agent 平台。\n\nFile v1.2.1:docs/interaction.md\n\n# Interaction Guide — 交互规范\n\n> 完整交互流程、时间解析、输出格式、确认策略。\n> 本文件按需加载，非每次调用必读。\n\n---\n\n## 0. Authentication Behavior\n\n**MUST 遵守（与 `skill.md` Section 2 / 4 一致）：**\n\n- Agent **禁止**向用户索要或接收 `appid` / `secret`\n- 用户主动发送凭据时 → **拒绝接收**，引导 CLI `login`\n- 脚本返回 `authentication_required` 或 HTTP 401/403 → **STOP**，原样展示固定引导文案：\n\n```\n这台电脑还没有连接 Insentek API，需要先完成一次本地配置，通常 1 分钟就好。\n\n请在终端运行：\n\nnpx insentek-api-skill login\n\n按提示输入 appid 和 secret 即可（加密保存在本机，无需发到这个对话）。配置完成后回来继续提问，我接着帮你处理。\n```\n\n- 用户说\"重新认证\" → 引导 `npx @insentek/openapi-skill login` 或先 `logout` 再 `login`\n\n### 0.1 脚本路径（与 `skill.md` Section 2 一致）\n\n- API 调用用 `python ${SKILL_ROOT}/scripts/insentek_cli.py`，**禁止**相对路径 `scripts/...`\n- 首次调用前或 ENOENT：`npx @insentek/openapi-skill status -r openclaw -s workspace --json`，读 `installDir` / `scripts.cli`\n- 文件找不到时 **禁止**乱试 `npx insentek-api-skill devices` 等命令\n\n---\n\n## 1. Intent Resolution\n\n### 1.1 三层模型\n\n| 层级 | 名称 | 说明 | 缺失时处理 |\n|------|------|------|-----------|\n| L1 | 核心意图 | 查数据 / 对比 / 导出 / 生成报告 | 反问：\"您想查询数据、对比设备，还是导出报告？\" |\n| L2 | 输出意图 | 对话展示 / 文件导出 | 提供选项让用户选择 |\n| L3 | 格式意图 | CSV / Excel / JSON / HTML | L2=文件时询问；推荐 CSV 为默认 |\n\n### 1.2 关键词映射\n\n| 用户关键词 | 推断 L1 | 推断 L2 | 需确认 L3？ |\n|-----------|---------|---------|-------------|\n| \"查一下\"、\"看看\"、\"多少\" | 查询数据 | 对话展示 | 否 |\n| \"导出\"、\"下载\"、\"保存\" | 查询数据 | 文件导出 | **是** |\n| \"生成报告\"、\"做一份报告\" | 生成报告 | 文件导出 | **是** |\n| \"对比\"、\"比较\"、\"哪个高\" | 对比设备 | 对话展示 | 否 |\n| \"把对比结果导出来\" | 对比设备 | 文件导出 | **是** |\n\n### 1.3 快捷意图（无需确认）\n\n- \"导出 [设备] [时间段] 数据为 [格式]\"\n- \"下载 [设备] 的 [时间段] CSV\"\n- \"生成 [设备] [时间段] 的 HTML 报告\"\n- \"把 [设备A] 和 [设备B] [时间段] 的对比结果导出为 Excel\"\n\n---\n\n## 2. Time Expression Parsing\n\n| 表达式 | 开始 | 结束 | 示例 (today=2025-05-13) |\n|--------|------|------|------------------------|\n| \"现在\" / \"最新\" / \"实时\" | — | — | `GET /latest` |\n| \"昨天\" | yesterday | yesterday | `20250512,20250512` |\n| \"最近7天\" / \"近一周\" | today-7d | today | `20250506,20250513` |\n| \"上周\" | last Monday | last Sunday | `20250505,20250511` |\n| \"本周\" | this Monday | today | `20250512,20250513` |\n| \"本月\" | 1st | today | `20250501,20250513` |\n| \"上月\" | 1st of last month | last day of last month | `20250401,20250430` |\n| \"今年\" | Jan 1 | today | `20250101,20250513` |\n| \"最近1个月\" | today-30d | today | `20250413,20250513` |\n| \"最近3个月\" | today-90d | today | `20250212,20250513` |\n| \"最近1年\" | today-365d | today | `20240513,20250513` |\n| *(default)* | today-1d | today | `20250512,20250513` |\n\n**编码规则：** `YYYYMMDD`，Range: `startYYYYMMDD,endYYYYMMDD`。Moment: `YYYY-MM-DD HH:MM:SS` URL-encoded。\n\n**月份边界：** \"上月\"在 1月31日说 → 12月全月；\"本月\"在当月任意日期 → 1号至今天。\n\n---\n\n## 3. Confirmation Patterns\n\n**MUST 向用户确认的场景：**\n\n1. L1/L2 意图不明确（见 1.1）\n2. 数据可用性覆盖 < 50% 或 < 7 天（见 `skill.md` 3.2）\n3. 多设备 alias 模糊匹配到多个结果\n4. 导出数据量 > 50,000 条\n5. 查询跨度 > 365 天\n\n**可直接执行的场景：**\n- 一句话完整表达（见 1.3）\n- 同一会话内再次查询（已有缓存）\n- 实时数据查询（/latest）\n\n---\n\n## 4. Output Format Guide\n\n### 4.1 实时数据 → 简洁卡片\n\n```\n📍 [设备别名] ([SN后4位])\n─────────────────────────\n🌡️ [参数中文名]: [值] [单位]  @[时间]\n💧 [参数中文名]: [值] [单位]\n🔋 [参数中文名]: [值] [单位]\n─────────────────────────\n状态: [状态描述]  |  位置: [城市]\n```\n\n### 4.2 历史数据（对话）→ 表格 + 趋势\n\n≤ 200 条：完整表格 + 趋势小结\n\n> 200 条：统计摘要 + 首尾各 10 条抽样 + 提示导出\n\n```\n📊 数据概览（共 N 条，展示摘要）\n\n统计摘要:\n| 参数 | 平均 | 最大 | 最小 | 变化率 |\n|------|------|------|------|--------|\n\n💡 提示: 该时间段数据量较大，如需完整数据请说\"导出为CSV\"。\n```\n\n### 4.3 文件导出 → 确认信息\n\n```\n✅ 导出成功\n📄 文件: [filename.csv]\n📊 数据条数: [N] 条\n📅 时间范围: [开始] 至 [结束]\n📥 文件路径: [绝对路径]\n```\n\n### 4.4 对比分析 → 并排表格\n\n```markdown\n| 参数 | [设备A] | [设备B] | 差异 |\n|------|---------|---------|------|\n```\n\n### 4.5 告警报告 → 标记列表\n\n```\n⚠️ 检测到 N 条异常数据:\n1. [时间] [节点] [参数]: [值] — [异常原因]\n```\n\n---\n\n## 5. Interaction Examples\n\n### Flow 1: 查询历史数据（对话展示）\n\n```\nUser: \"3号设备上周的土壤湿度\"\n  → python scripts/insentek_cli.py check (optional) or direct query\n  → if authentication_required → STOP, show skill.md Section 2 fixed message\n  → query_device(alias=\"3号\") → resolve sn\n  → query_data(sn, \"上周\") → /data\n  → data points ≤ 200 → show table + trend\n```\n\n### Flow 2: 导出数据（文件导出）\n\n```\nUser: \"导出3号设备上个月数据为CSV\"\n  → if authentication_required → STOP, show skill.md Section 2 fixed message\n  → query_device(alias=\"3号\") → resolve sn\n  → validate range (30d ≤ 365d) → OK\n  → export_csv(sn, range, \"data.csv\") → return path\n```\n\n### Flow 3: 生成报告（数据不匹配 → 确认）\n\n```\nUser: \"分析3号近三个月数据，生成报告\"\n  → if authentication_required → STOP, show skill.md Section 2 fixed message\n  → query_device(alias=\"3号\") → resolve sn\n  → query_data(sn, \"最近3个月\")\n     → 请求: 90天 / 实际: 13天 → coverage 14%\n  → STOP: \"您请求近3个月共90天，该设备实际仅13天数据。是否继续？\"\n  → User: \"继续\"\n  → analyze → construct HTML → write_html → return path\n```\n\n完整多设备对比、分批导出等示例见 `examples/flows.md`。\n\nFile v1.2.1:docs/platform-setup.md\n\n# Platform Setup Guide — 各 Agent 平台配置指南\n\n> 将 insentek skill 安装到不同 Agent 平台的完整步骤，含安装路径、卸载方法和故障排查。\n\n---\n\n## 通用前置：CLI 安装与凭据配置（推荐）\n\n无论使用哪个 Agent 平台，都建议先完成 CLI 安装和本地凭据配置：\n\n```bash\n# 安装 skill 到 Claude Code / OpenClaw（交互式）\nnpx @insentek/openapi-skill\n\n# 配置 API 凭据（加密本地保存，不要在对话中发送 secret）\nnpx @insentek/openapi-skill login\n\n# 查看连接状态\nnpx @insentek/openapi-skill auth status\n```\n\n凭据保存在 `~/.config/insentek/credentials.json`。Agent 通过 `scripts/insentek_cli.py` 自动读取，**不会**在对话中索要 appid/secret。\n\n---\n\n## 目录\n\n- [OpenClaw](#openclaw)\n- [Claude Code](#claude-code)\n- [ChatGPT](#chatgpt)\n- [Hermes-Agent](#hermes-agent)\n- [平台兼容性速查](#平台兼容性速查)\n- [故障排查](#故障排查)\n\n---\n\n## OpenClaw\n\n### 安装\n\n#### 方式一：CLI 安装（推荐）\n\n```bash\nnpx @insentek/openapi-skill install -r openclaw -s global -y\nnpx @insentek/openapi-skill login\n```\n\n#### 方式二：从 ClawHub 安装\n\n```bash\n# 安装最新版本\nclawhub skill install insentek-api-skill\n\n# 安装指定版本\nclawhub skill install insentek-api-skill@1.1.0\n\n# 从 ClawHub 搜索确认\nclawhub skill search insentek\n```\n\n安装完成后，skill 会自动注册到 OpenClaw 的技能列表中。\n\n#### 方式二：本地文件安装\n\n```bash\n# 从本地 skill.md 安装\nclawhub skill add ./skill.md\n\n# 或使用绝对路径\nclawhub skill add /path/to/skill.md\n```\n\n#### 方式三：Web UI 安装\n\n1. 打开 OpenClaw 客户端，进入 **Skills** 页面\n2. 点击 **Import Skill** → 选择文件\n3. 选择项目根目录的 `skill.md` 文件\n4. 确认导入\n\n### 卸载\n\n```bash\n# CLI 卸载\nclawhub skill remove insentek-api-skill\n```\n\n或在 Web UI 中：Skills → 找到 \"insentek-api-skill\" → **Remove**。\n\n### 配置参数\n\n| 参数 | 值 | 说明 |\n|------|-----|------|\n| API Base URL | `http://openapi.ecois.info` | 默认即可 |\n\n### 首次使用\n\n先在本机配置 API 凭据：\n\n```bash\nnpx @insentek/openapi-skill login\n```\n\n然后在 OpenClaw 中直接查询：\n\n```\nUser: 查看所有设备\n```\n\n---\n\n## Claude Code\n\n### 安装\n\nClaude Code 通过读取 skill 文件来加载技能上下文，支持项目级和全局级两种方式。\n\n#### 方式一：CLI 安装（推荐）\n\n```bash\nnpx @insentek/openapi-skill install -r claude -s global -y\nnpx @insentek/openapi-skill login\n```\n\n#### 方式二：全局 Skills 目录（手动）\n\nClaude Code 会从全局 skills 目录自动加载所有 skill 文件，无需在每个项目中重复放置。\n\n**Windows:**\n```powershell\n# 创建 skills 目录（如果不存在）\nNew-Item -ItemType Directory -Force -Path \"$env:USERPROFILE\\.claude\\skills\"\n\n# 复制 skill 文件\nCopy-Item skill.md \"$env:USERPROFILE\\.claude\\skills\\insentek-api-skill.md\"\n```\n\n**macOS:**\n```bash\nmkdir -p ~/.claude/skills\ncp skill.md ~/.claude/skills/insentek-api-skill.md\n```\n\n**Linux:**\n```bash\nmkdir -p ~/.claude/skills\ncp skill.md ~/.claude/skills/insentek-api-skill.md\n```\n\n放置后重启 Claude Code 或重新打开对话即可生效。\n\n#### 方式三：项目目录加载\n\n将 `skill.md` 放入当前工作项目的根目录，Claude Code 会自动识别为项目上下文：\n\n```bash\n# 任意项目目录\ncp skill.md ./skill.md\n```\n\n#### 方式四：对话中直接引用\n\n```\n# 在 Claude Code 对话中执行\n/load skill.md\n```\n\n或直接将 `skill.md` 内容粘贴到对话中。\n\n### 卸载\n\n- **全局级（推荐）**：从 `~/.claude/skills/` 目录移除对应文件\n  ```bash\n  # Windows\n  Remove-Item \"$env:USERPROFILE\\.claude\\skills\\insentek-api-skill.md\"\n\n  # macOS / Linux\n  rm ~/.claude/skills/insentek-api-skill.md\n  ```\n- **项目级**：删除项目根目录的 `skill.md` 文件\n- **对话级**：执行 `/clear` 清除当前对话上下文\n\n### 首次使用\n\n```bash\nnpx @insentek/openapi-skill login\n```\n\n```\nUser: 查看所有设备\n```\n\nClaude Code 会读取 skill.md 中的 tool definitions，脚本自动使用本地凭据。\n\n### 注意事项\n\n- 确保 skill.md 中的 YAML frontmatter 被正确解析\n- 如果 function calling 未触发，尝试明确说出工具名称如 \"query_device\"\n\n---\n\n## ChatGPT\n\n### 安装\n\n#### 方式一：创建 GPT（推荐，需 Plus 订阅）\n\n1. 打开 [ChatGPT](https://chat.openai.com) → **Explore GPTs** → **Create**\n2. 在 Configure 标签页：\n   - **Name**: Insentek Device Query\n   - **Description**: 查询 insentek 物联网设备数据\n   - **Instructions**: 粘贴 `skill.md` 的完整内容\n3. 在 **Capabilities** 中启用 \"Code Interpreter\"（如需数据处理）\n4. 保存并发布（可选设为 Private）\n\n#### 方式二：Actions（API 直连，需 Plus 订阅）\n\n1. 创建 GPT 时，在 Configure 页面点击 **Add actions**\n2. 粘贴由 `skill.md` function schema 生成的 OpenAPI schema\n3. 设置认证方式：API Key（Header: `Authorization`）— **不要将 appid/secret 写入 GPT 配置或对话**\n4. 在本机运行 `npx @insentek/openapi-skill login`，由脚本管理 token\n5. 保存后 GPT 可直接调用 insentek API\n\n#### 方式三：Custom Instructions（个人使用）\n\n适合临时使用，无需创建 GPT。\n\n1. 打开 ChatGPT → 点击头像 → **Custom Instructions**\n2. 在 \"How would you like ChatGPT to respond?\" 中粘贴 `skill.md` 的 Prompt 区内容\n3. 在 \"What would you like ChatGPT to know about you?\" 中说明你有 insentek 物联网设备即可（**不要**写入 appid/secret）\n4. 在本机运行 `npx @insentek/openapi-skill login` 配置凭据\n5. 保存后开始新对话\n\n**限制：** Custom Instructions 不支持真正的 function calling，API 调用需要手动复制 URL。\n\n### 卸载\n\n- **GPTs 方式**：ChatGPT → Explore GPTs → 找到对应 GPT → 右上角 ⋮ → **Delete GPT**\n- **Actions 方式**：编辑 GPT → Configure → Actions → **删除对应 Action**\n- **Custom Instructions**：ChatGPT → 头像 → Custom Instructions → **清空内容**\n\n### 首次使用\n\n```\nUser: 查看我的所有设备\n```\n\n如果已在本地运行 `npx @insentek/openapi-skill login`，脚本会自动认证并查询。\n\n---\n\n## Hermes-Agent\n\n### 安装\n\nHermes-Agent 通过读取 skills 目录下的 skill 文件来加载技能。\n\n#### 步骤\n\n**Windows:**\n```powershell\n# 创建 skills 目录（如果不存在）\nNew-Item -ItemType Directory -Force -Path \"$env:USERPROFILE\\.hermes\\skills\"\n\n# 复制 skill 文件\nCopy-Item skill.md \"$env:USERPROFILE\\.hermes\\skills\\insentek-api-skill.md\"\n```\n\n**macOS:**\n```bash\nmkdir -p ~/.hermes/skills\ncp skill.md ~/.hermes/skills/insentek-api-skill.md\n```\n\n**Linux:**\n```bash\nmkdir -p ~/.hermes/skills\ncp skill.md ~/.hermes/skills/insentek-api-skill.md\n```\n\n**重启或刷新：**\n```bash\nhermes skill reload\n# 或重启 Hermes-Agent 服务\n```\n\n### 卸载\n\n**Windows:**\n```powershell\nRemove-Item \"$env:USERPROFILE\\.hermes\\skills\\insentek-api-skill.md\"\n```\n\n**macOS / Linux:**\n```bash\nrm ~/.hermes/skills/insentek-api-skill.md\nhermes skill reload\n```\n\n### 配置环境变量（可选）\n\n```bash\nexport INSENTEK_BASE_URL=http://openapi.ecois.info\n```\n\n### 首次使用\n\n```bash\nnpx @insentek/openapi-skill login\n```\n\n```\nUser: 查看设备\n```\n\n---\n\n## 平台兼容性速查\n\n| 特性 | OpenClaw | Claude Code | ChatGPT (GPTs) | Hermes-Agent |\n|------|----------|-------------|----------------|--------------|\n| Function Schema | Native | Native | Via Actions | Native |\n| YAML Frontmatter | ✅ | ✅ | ⚠️ | ✅ |\n| Auto Token Refresh | ✅ | ✅ | Manual | ✅ |\n| Alias Resolution | ✅ | ✅ | ✅ | ✅ |\n| Time Parsing | ✅ | ✅ | ✅ | ✅ |\n| Chain Calling | ✅ | ✅ | ✅ | ✅ |\n| CLI 凭据管理 | ✅ | ✅ | ⚠️ 需本机 login | ✅ |\n| ClawHub 一键安装 | ✅ | ❌ | ❌ | ❌ |\n\n**图例：** ✅ 原生支持 | ⚠️ 需额外配置 | ❌ 不支持\n\n---\n\n## 故障排查\n\n### Function Schema 未被识别\n\n- **Claude Code**: 确保 skill.md 位于项目根目录，且文件名为 `skill.md`\n- **ChatGPT**: 使用 GPTs 的 Actions 功能，或手动粘贴 Instructions\n- **通用**: 检查 YAML frontmatter 格式是否正确（`---` 开头和结尾）\n\n### 认证失败\n\n1. 运行 `npx @insentek/openapi-skill auth status` 检查连接状态\n2. 重新配置：`npx @insentek/openapi-skill login`\n3. 检查网络是否能访问 `http://openapi.ecois.info`\n4. **不要在对话中发送 secret**，凭据仅通过 CLI 配置\n\n### 查询无数据返回\n\n1. 确认设备已正确接入 insentek 平台\n2. 检查时间范围是否合理（默认最近 24 小时可能无数据）\n3. 尝试扩大时间范围如 \"最近7天\"\n\n---\n\n*配置问题请联系：参考 insentek 官方支持渠道*\n\nFile v1.2.1:examples/flows.md\n\n# Examples: Core Interaction Flows\n\n> 3 个核心交互流程，覆盖最常见的使用场景。\n> 完整交互规范见 `docs/interaction.md`。\n\n---\n\n## Flow 1: Query Historical Data (Chat)\n\n### User Input\n```\n3号设备上周的土壤湿度\n```\n\n### Agent Thinking\n1. alias=\"3号\" → resolve sn via `query_device`\n2. time=\"上周\" → range = last Monday ~ last Sunday\n3. param=\"土壤湿度\" → includeParams = moisture\n4. output intent = chat (implicit)\n\n### Tool Calls\n```\nquery_device(alias=\"3号\")\n  → sn = \"00000000000001\"\n\nquery_data(sn=\"00000000000001\", time_expression=\"上周\", includeParameters=\"moisture\")\n  → GET /v3/device/00000000000001/data?range=20250505,20250511&includeParams=moisture\n```\n\n### Output\n```markdown\n📊 3号大棚 — 上周土壤湿度 (2025-05-05 ~ 2025-05-11)\n\n| 日期 | 10cm | 20cm | 30cm | 40cm |\n|------|------|------|------|------|\n| 05-05 | 22.1 | 23.5 | 25.1 | 26.5 |\n| ... | ... | ... | ... | ... |\n\n📈 趋势小结:\n- 各层湿度平稳，40cm深层保持最高\n- 10cm表层受蒸发影响日间波动稍大\n```\n\n---\n\n## Flow 2: Export Data (File)\n\n### User Input\n```\n导出3号设备上个月数据为CSV\n```\n\n### Agent Thinking\n1. alias=\"3号\" → resolve sn\n2. time=\"上个月\" → range = 20250401,20250430\n3. format=\"CSV\" → export_csv\n4. Validate: 30 days ≤ 365 days → OK\n\n### Tool Calls\n```\nquery_device(alias=\"3号\") → sn = \"00000000000001\"\n\nexport_csv(sn=\"00000000000001\", range=\"20250401,20250430\", output=\"3号_2025-04.csv\")\n  → 成功导出 720 条数据\n```\n\n### Output\n```\n✅ 导出成功\n\n📄 文件: 3号_2025-04.csv\n📊 数据条数: 720 条\n📅 时间范围: 2025-04-01 至 2025-04-30\n📥 文件路径: /absolute/path/to/3号_2025-04.csv\n```\n\n---\n\n## Flow 3: Generate Report (Data Availability Mismatch)\n\n### User Input\n```\n分析11684501348336近三个月的数据，生成报告\n```\n\n### Agent Thinking\n1. alias=\"11684501348336\" → resolve sn\n2. time=\"近3个月\" → requested range = 2026-02-22 ~ 2026-05-22 (90 days)\n3. query_data → retrieve actual data\n4. **数据可用性校验**: actual = 2025-05-10 ~ 2025-05-22 (13 days)\n5. coverage = 13/90 = 14% < 50% → **STOP and confirm**\n\n### Tool Calls\n```\nquery_device(alias=\"11684501348336\") → sn = \"11684501348336\"\n\nquery_data(sn=\"11684501348336\", time_expression=\"最近3个月\")\n  → actual range: 2025-05-10 ~ 2025-05-22 (13 records)\n```\n\n### Agent Confirmation\n```\n您请求的『近3个月』共约 90 天，\n但该设备实际仅有 2025-05-10 至 2025-05-22 共 13 天的数据。\n\n可能原因：\n- 设备在该时间段尚未部署或激活\n- 设备期间出现离线/故障导致数据缺失\n\n是否继续基于现有 13 天数据生成报告？\n```\n\n### User Response\n```\n继续\n```\n\n### Analysis & Report Generation\n```\n→ 统计摘要: 均值、最大、最小、标准差\n→ 趋势分析: 线性变化率\n→ 异常检测: 扫描 battery, moisture, temperature\n→ 构建 HTML (ECharts line chart + summary cards)\n→ write_html → report.html\n```\n\n### Output\n```\n✅ 报告已生成\n\n📄 文件: report_11684501348336.html\n📊 分析数据: 13 条 (2025-05-10 至 2025-05-22)\n⚠️  注: 基于实际可用数据，非完整 3 个月\n📥 文件路径: /absolute/path/to/report_11684501348336.html\n```\n\n---\n\n## Other Scenarios\n\n更多场景（多设备对比、批量导出、实时查询、告警检测）见：\n- `examples/queries.md` — 查询类对话示例\n- `examples/reports.md` — 报告生成示例\n- `docs/interaction.md` Section 5 — 完整确认策略\n\nArchive v1.2.0: 17 files, 51767 bytes\n\nFiles: CHANGELOG.md (6506b), CLAUDE.md (1214b), docs/analysis.md (4559b), docs/getting-started.md (3681b), docs/interaction.md (5399b), docs/platform-setup.md (7665b), examples/flows.md (3539b), examples/queries.md (5794b), examples/reports.md (5766b), README.md (6254b), reference/api-doc.md (28329b), scripts/export_excel.py (9191b), scripts/insentek_cli.py (27064b), scripts/README.md (3446b), scripts/write_html.py (6398b), skill.md (8808b), _meta.json (137b)\n\nFile v1.2.0:skill.md\n\n---\nname: insentek-openapi\nversion: 1.2.0\ndescription: >\n  通过自然语言查询 insentek（东方智感）物联网设备数据。\n  支持土壤墒情仪、气象站、见厘液位计等多种设备类型的实时数据、\n  历史数据、趋势分析、跨设备对比与数据导出。\napi_base_url: http://openapi.ecois.info\nauthor: insentek-api-skills\nguardrails:\n  raw_data_output: PROHIBITED\n  dry_run_preview_rows: 5\n  max_chat_rows: 200\n  max_export_rows: 50000\n---\n\n# Insentek OpenAPI Skill\n\n> 轻量 Runtime Contract。完整交互规范见 `docs/interaction.md`，分析策略见 `docs/analysis.md`。\n> 兼容平台：OpenClaw、Hermes-Agent、Claude Code、ChatGPT\n\n---\n\n## 1. Routing\n\n用户意图 → 工具路由：\n\n| L1 意图 | L2 输出 | 调用 |\n|---------|---------|------|\n| 查询数据 | 对话展示 | `query_device` → `query_data` → 按输出格式回复 |\n| 查询数据 | 文件导出 | `query_device` → `export_*` → 返回文件路径 |\n| 生成报告 | 文件导出 | `query_device` → `query_data` → 分析 → `write_html` |\n| 对比设备 | 对话展示 | `query_device` (xN) → `query_data` (xN) → 对比表格 |\n| 对比设备 | 文件导出 | `query_device` (xN) → `query_data` (xN) → `export_excel` |\n\n**任何一层意图不明确时，MUST 向用户确认，不得假设。** 详见 `docs/interaction.md` Section 1。\n\n---\n\n## 2. Tools\n\n### authenticate\n\n用户首次提供 appid/secret 时调用，或缓存凭据失效时。\n\n**方式一：持久化配置（推荐）**\n```bash\n# 配置并保存（仅需一次）\npython scripts/insentek_cli.py auth --appid ${appid} --secret ${secret} --save\n\n# 查看状态\npython scripts/insentek_cli.py auth --status\n\n# 清除配置\npython scripts/insentek_cli.py auth --clear\n```\n\n**方式二：临时获取 token**\n```bash\npython scripts/insentek_cli.py auth --appid ${appid} --secret ${secret}\n```\n\n成功后输出 token。若使用 `--save`，凭据保存到 `~/.config/insentek/credentials.json`，后续所有命令无需再传 `--token`。\n\n---\n\n### query_device\n\n查询设备信息：列表、详情、别名解析。\n\n```json\n{\n  \"page\": { \"type\": \"integer\", \"default\": 1 },\n  \"limit\": { \"type\": \"integer\", \"default\": 20 },\n  \"sn\": { \"type\": \"string\", \"description\": \"设备序列号，与 alias 二选一\" },\n  \"alias\": { \"type\": \"string\", \"description\": \"设备别名，支持部分匹配\" }\n}\n```\n\n```bash\n# 列表\npython scripts/insentek_cli.py devices [--token ${token}] --page ${page} --limit ${limit}\n# 详情\npython scripts/insentek_cli.py device [--token ${token}] --sn ${sn}\n```\n\n**注意：** `--token` 变为可选。若未提供且已配置持久化凭据，脚本自动获取。\n\n**行为：** alias → 模糊匹配 → 多匹配时反问用户 → 单匹配时缓存 alias→sn 映射。\n\n---\n\n### query_data\n\n查询设备历史数据或实时数据。\n\n```json\n{\n  \"sn\": { \"type\": \"string\", \"required\": true },\n  \"time_expression\": { \"type\": \"string\", \"description\": \"自然语言时间描述，如'现在'、'昨天'、'最近7天'。不传默认最近24小时。\" },\n  \"range\": { \"type\": \"string\", \"description\": \"YYYYMMDD,YYYYMMDD，由 time_expression 自动计算\" },\n  \"includeParameters\": { \"type\": \"string\", \"description\": \"指定参数，逗号分隔，如 moisture,temperature\" }\n}\n```\n\n```bash\n# 历史数据\npython scripts/insentek_cli.py data [--token ${token}] --sn ${sn} --range ${range} [--include-params ${params}]\n\n# 预览（调试/验证用）\npython scripts/insentek_cli.py data [--token ${token}] --sn ${sn} --range ${range} --dry-run\n\n# 实时数据（latest）— 允许直接用 curl\n curl -s -H \"Authorization: ${token}\" \"http://openapi.ecois.info/v3/device/${sn}/latest\"\n```\n\n**注意：** `--token` 变为可选。若未提供且已配置持久化凭据，脚本自动获取。\n\n时间表达式解析见 `docs/interaction.md` Section 2。\n\n---\n\n### export_csv / export_excel / export_json\n\n用户意图明确为\"导出/下载\"时调用，而非 `query_data`。\n\n```bash\n# CSV\npython scripts/insentek_cli.py export [--token ${token}] --sn ${sn} --range ${range} --format csv --output ${file}.csv\n\n# Excel\npython scripts/export_excel.py [--token ${token}] --sn ${sn} --range ${range} --output ${file}.xlsx\n\n# JSON\npython scripts/insentek_cli.py export [--token ${token}] --sn ${sn} --range ${range} --format json --output ${file}.json\n```\n\n**注意：** `--token` 变为可选。若未提供且已配置持久化凭据，脚本自动获取。\n\n所有导出脚本均支持 `--dry-run`。\n\n---\n\n### write_html\n\nAgent 完成数据分析后，将动态生成的 HTML 内容写入文件。\n\n```bash\necho \"${html_content}\" | python scripts/write_html.py --output ${file}.html\n```\n\n---\n\n## 3. Guardrails\n\n### 3.1 硬限制\n\n| 限制项 | 规则 | 超限处理 |\n|--------|------|----------|\n| 单次查询跨度 | ≤ 365 天 | 拒绝，提供拆分选项 |\n| 历史回溯 | ≤ 3 年 | 拒绝，提示最早日期 |\n| 对话展示 | ≤ 200 条 | 展示摘要 + 首尾各 10 条抽样 |\n| 文件导出 | ≤ 50,000 条 | 拒绝，建议缩小范围或分批 |\n\n### 3.2 数据可用性校验（MUST）\n\n`query_data` 返回后，检查实际数据范围 vs 请求范围：\n\n```\nrequested_days = 用户请求的天数\nactual_days    = 实际返回数据的天数\ncoverage       = actual_days / requested_days\n\nIF coverage < 0.5 OR actual_days < 7:\n  → STOP\n  → 告知用户实际范围，询问是否继续\n  → 等待确认后才可生成报告/分析\nELSE IF actual_range < requested_range:\n  → 继续，但报告 MUST 使用 actual_range 标注\n```\n\n### 3.3 原始数据输出禁令（MUST）\n\nAgent **禁止**将原始传感器全量数据输出到对话中。\n\n| 场景 | 处理 |\n|------|------|\n| \"看看数据\" | 统计摘要 + 首尾各 5 条 |\n| \"调试\" | `--dry-run` 预览 |\n| \"给我原始数据\" | 引导导出 CSV/Excel |\n| \"全部发给我\" | 拒绝，解释 Token 限制 |\n\n完整输出格式规范见 `docs/interaction.md` Section 4。\n\n---\n\n## 4. Authentication\n\n### 4.1 持久化凭据（推荐）\n\n首次使用时配置凭据，后续自动读取：\n\n```bash\n# 配置并保存凭据（仅需执行一次）\npython scripts/insentek_cli.py auth --appid xxx --secret *** --save\n\n# 查看当前配置状态\npython scripts/insentek_cli.py auth --status\n\n# 清除配置\npython scripts/insentek_cli.py auth --clear\n```\n\n凭据存储在 `~/.config/insentek/credentials.json`，文件权限 600（仅所有者可读写）。\n\n### 4.2 命令行传参（临时/多账号场景）\n\n```bash\npython scripts/insentek_cli.py auth --appid xxx --secret ***\n```\n\n命令行参数优先级高于配置文件，便于临时覆盖或多账号切换。\n\n### 4.3 Token 获取策略\n\n脚本**管理 token 生命周期**，实现缓存 + 自动刷新机制：\n- 首次 `auth --save` 时，凭据和 token 一并保存到配置文件\n- 后续各命令 `--token` 参数变为可选\n- 未提供 `--token` 时，脚本**优先从配置文件读取缓存的 token**\n- 请求 API 时如果返回 401/403，脚本**自动刷新 token** 并重试一次\n- 刷新后的 token 自动写回配置文件\n- 不检查 token 过期时间，靠 HTTP 401/403 触发刷新\n\n### 4.4 Token 缓存流程\n\n```\n请求 API\n  ├── 使用缓存 token\n  ├── 成功 → 返回数据\n  └── 401/403 → 调用 /v3/token 获取新 token → 更新配置文件 → 重试请求\n```\n\n### 4.4 安全说明\n\n- Secret **绝不**输出到对话\n- 配置文件权限 600，仅所有者可读写\n- Token 按需临时获取，不长期存储\n- `authenticate` 命令返回 token 供一次性使用，或让脚本自动管理\n\n---\n\n**向后兼容：** 所有命令仍支持 `--token` 参数，现有调用方式不受影响。\n\n---\n\n## 5. Environment Check\n\n首次交互前执行：\n\n```bash\npython scripts/insentek_cli.py check\n```\n\n关键项失败时 STOP，可选项失败时降级运行并告知用户。\n\n---\n\n## 6. Error Handling\n\n| HTTP | 处理 |\n|------|------|\n| 200 | 正常处理 |\n| 400 | 检查参数格式后重试 |\n| 401/403 | 重新认证 |\n| 404 | 确认设备 SN/别名 |\n| 429 | 限流，等待后重试 |\n| 500 | 指数退避重试 3 次 |\n\n脚本返回 `\"success\": false` 时，解析 `error` 字段：含\"认证\"则重认证，含\"范围/限制\"则解释护栏，否则展示友好错误。\n\n---\n\n## Notes\n\n- **Pagination**: `page` starts at 1.\n- **Values**: Nested `{node_name: {parameter_code: value}}`\n- **Alias**: Case-insensitive partial match on `alias`.\n- **Param names**: Use Chinese names from `/description` endpoint for display.\n- **Script-first**: Prefer `scripts/insentek_cli.py` over raw `curl`.\n- **Dry-run**: Append `--dry-run` for preview; never output raw data to chat.\n- **Reference**: Edge cases → `reference/api-doc.md` (OpenAPI v3.1.9).\n\nFile v1.2.0:README.md\n\n# Insentek OpenAPI Skill\n\n> 让终端用户用自然语言轻松查询 insentek（东方智感）物联网设备数据。\n\n---\n\n## 简介\n\n本项目基于 insentek OpenAPI v3，产出一份通用 `skill.md` 技能文件及配套文档与示例。终端用户可在 **OpenClaw、Hermes-Agent、Claude Code、ChatGPT** 等 Agent 平台上直接对话使用，通过自然语言调用 API 完成设备数据查询、报告生成与实时分析。\n\n**支持的设备类型：**\n- 🌱 **Z** — 土壤墒情仪（土壤温度、水分、电导率）\n- 🌤️ **T** — 气象站（空气温度、湿度、风速、降雨量、PM2.5 等）\n- 📏 **J** — 见厘液位计（激光液位、电池电压）\n\n---\n\n## 快速开始\n\n### 1. 获取认证信息\n\n登录 [E 生态](https://www.ecois.info)，在「应用管理」中创建应用，获取 `appid` 和 `secret`。\n\n### 2. 安装 Skill\n\n| 平台 | 安装方式 | 卸载 |\n|------|---------|------|\n| **OpenClaw** | `openclaw skills install insentek-api-skill` | `openclaw skills install insentek-api-skill` |\n| **Claude Code** | 项目根目录放 `skill.md` 或 `/load skill.md` | 删除文件或 `/clear` |\n| **ChatGPT** | GPTs Instructions 粘贴 / Actions Schema 导入 | Delete GPT / 删除 Action |\n| **Hermes-Agent** | `~/.hermes/skills/` 目录下放 skill 文件 | `rm` 文件后 `reload` |\n\n> 各平台分操作系统（Windows / macOS / Linux）的详细安装路径、ClawHub 安装命令、卸载步骤见 [`docs/platform-setup.md`](docs/platform-setup.md)。\n\n### 3. 开始对话\n\n```\nUser: 我的 appid 是 xxx，secret 是 yyy，查看所有设备\n```\n\n更多用法见 [`docs/getting-started.md`](docs/getting-started.md)。\n\n---\n\n## 项目结构\n\n```\n.\n├── skill.md                     # 核心技能文件 (Runtime Contract)\n├── docs/\n│   ├── getting-started.md       # 快速开始指南\n│   ├── platform-setup.md        # 各平台配置指南\n│   ├── interaction.md           # 交互规范 (意图/时间/输出格式)\n│   └── analysis.md              # 分析策略 (报告/告警/行业参数)\n├── reference/\n│   └── api-doc.md               # 完整 API 文档 (OpenAPI v3.1.9)\n├── examples/\n│   ├── queries.md               # 查询类对话示例\n│   ├── reports.md               # 报告生成示例\n│   └── flows.md                 # 核心交互流程示例\n├── scripts/                     # 参考实现脚本\n│   ├── insentek_cli.py          # 统一 CLI（认证/查询/导出）\n│   ├── export_excel.py          # Excel 导出\n│   └── README.md                # 脚本使用说明\n├── PLATFORM-TEST.md             # 跨平台测试计划（自检清单）\n└── ref/                         # 参考材料（API 仓库 + 文档）\n    ├── api-repo/                # Spring Boot API 源码\n    └── api-document-latest.pdf  # 官方接口文档\n```\n\n---\n\n## 核心功能\n\n| 功能 | 说明 |\n|------|------|\n| 🔐 自动认证 | appid+secret → token，自动缓存与刷新 |\n| 📋 设备管理 | 列表查询、别名解析、单设备详情 |\n| 📊 数据查询 | 实时/历史/指定时刻/增量同步 |\n| 🧠 智能推断 | 自然语言时间自动解析（\"上周\"→日期范围） |\n| 🔗 链式调用 | alias → SN → 数据，自动串联 |\n| 📈 趋势分析 | 平均值/最大值/最小值/变化率自动计算 |\n| ⚖️ 跨设备对比 | 并排比较 + 差异高亮 |\n| ⚠️ 异常检测 | 电池过低、水分异常、温度突变自动标记 |\n| 🏭 多行业适配 | Z/T/J 设备类型自动识别与参数翻译 |\n| 🎯 意图确认 | 输出形式不明确时自动询问（查看/导出/报告） |\n| 🛡️ 查询边界 | 最大1年/3年回溯/5万条导出上限，超限自动拦截 |\n| 📤 数据导出 | CSV / Excel / JSON / HTML 报告一键生成 |\n| 🔍 环境检查 | 首次使用前自动检查 Python、脚本、依赖、API 可达性 |\n\n---\n\n## 对话示例\n\n**查看设备列表**\n```\nUser: 查看我的设备\nAgent: 📋 设备列表（共 3 台）...\n```\n\n**查询实时数据**\n```\nUser: 1号大棚现在的温度\nAgent: 📍 1号大棚 — 10cm: 18.5℃, 20cm: 17.2℃ ...\n```\n\n**历史趋势**\n```\nUser: 最近7天的土壤湿度变化\nAgent: 📊 趋势表格 + 平均/最高/最低/变化率小结\n```\n\n**异常检测**\n```\nUser: 检查所有设备的电池\nAgent: 🔋 巡检报告 — 2号大棚 2.85V 🔴 过低\n```\n\n更多示例见 [`examples/`](examples/)。\n\n---\n\n## 时间表达支持\n\n| 你说 | Agent 理解 |\n|------|-----------|\n| \"现在\" / \"最新\" / \"实时\" | 调用 /latest |\n| \"昨天\" / \"上周\" / \"本月\" | 自动计算 YYYYMMDD,YYYYMMDD |\n| \"最近7天\" / \"近一周\" | 过去 7 天 |\n| \"12点30分\" / \"某时刻\" | 调用 /moment/{datetime} |\n| \"同步\" / \"增量\" | 调用 /incremental |\n| *(没提时间)* | 默认最近 24 小时 |\n\n---\n\n## 平台兼容性\n\n| 特性 | OpenClaw | Claude Code | ChatGPT | Hermes-Agent |\n|------|:--------:|:-----------:|:-------:|:------------:|\n| Function Schema | ✅ | ✅ | ⚠️ Actions | ✅ |\n| 自动 Token 刷新 | ✅ | ✅ | ⚠️ | ✅ |\n| 别名解析 | ✅ | ✅ | ✅ | ✅ |\n| 时间推断 | ✅ | ✅ | ✅ | ✅ |\n| 链式调用 | ✅ | ✅ | ✅ | ✅ |\n\n⚠️ = 需额外配置（详见 [`docs/platform-setup.md`](docs/platform-setup.md)）\n\n---\n\n## API 参考\n\n- **Base URL**: `http://openapi.ecois.info`\n- **认证**: `GET /v3/token?appid={appid}&secret={secret}`\n- **设备**: `/v3/devices`, `/v3/device/{sn}`, `/v3/device/{sn}/description`\n- **数据**: `/v3/device/{sn}/data`, `/latest`, `/moment/{datetime}`, `/incremental`\n\n完整参数说明见 [`reference/api-doc.md`](reference/api-doc.md)。\n\n---\n\n## 版本\n\n- **当前版本**: v1.1.0\n- **API 版本**: insentek OpenAPI v3\n- **更新日期**: 2026-05-22\n\n---\n\n## 贡献\n\n本项目为内容产出型项目，主要交付物为 `skill.md` 及配套文档。\n\n如需反馈问题或建议：\n1. 检查 [`PLATFORM-TEST.md`](PLATFORM-TEST.md) 确认是否为已知限制\n2. 提交 issue 到项目仓库\n\n---\n\n## 许可证\n\n待定 / 请参考 insentek 官方使用条款\n\n---\n\n*Generated with Claude Code · 基于 insentek OpenAPI v3*\n\nFile v1.2.0:scripts/README.md\n\n# Insentek OpenAPI Scripts\n\n本目录包含 Insentek OpenAPI 的参考实现脚本。Agent 通过调用这些脚本完成 API 交互、数据导出和报告生成，而非直接使用 `curl` 命令。\n\n## 设计原则\n\n1. **统一入口**: `insentek_cli.py` 封装所有 API 调用，Agent 只需学习一套参数风格\n2. **边界内置**: 脚本内部实现时间范围限制、数据量检查，Agent 无需重复实现\n3. **结构化输出**: 所有脚本输出 JSON 到 stdout，便于 Agent 解析和决策\n4. **零配置运行**: 仅依赖 Python 标准库（Excel 导出除外）\n\n## 脚本列表\n\n| 脚本 | 功能 | 依赖 |\n|------|------|------|\n| `insentek_cli.py` | 统一 CLI：认证、设备查询、数据查询、CSV/JSON 导出 | Python 3.8+ |\n| `write_html.py` | HTML 文件写入：将 AI 生成的 HTML 内容安全落盘 | Python 3.8+ |\n| `export_excel.py` | Excel 导出（多 sheet：原始数据 + 统计摘要） | Python 3.8+, openpyxl |\n\n## 使用示例\n\n### 环境检查（首次使用前必做）\n```bash\npython insentek_cli.py check\n```\n\n输出示例：\n```json\n{\n  \"success\": true,\n  \"all_checks_passed\": true,\n  \"checks\": {\n    \"python\": {\"ok\": true, \"version\": \"3.11.0\", \"message\": \"Python 3.11.0 满足要求 (>=3.8)\"},\n    \"scripts_cli\": {\"ok\": true, \"path\": \"...\", \"message\": \"核心脚本 insentek_cli.py 已找到\"},\n    \"scripts_excel\": {\"ok\": true, \"path\": \"...\", \"message\": \"Excel 脚本 export_excel.py 已找到\"},\n    \"scripts_write_html\": {\"ok\": true, \"path\": \"...\", \"message\": \"HTML 写入脚本 write_html.py 已找到\"},\n    \"openpyxl\": {\"ok\": true, \"version\": \"3.1.2\", \"message\": \"openpyxl 3.1.2 已安装，Excel 导出可用\"},\n    \"curl\": {\"ok\": true, \"message\": \"curl 可用，可作为脚本不可用时的 fallback\"},\n    \"api_reachable\": {\"ok\": true, \"status\": 400, \"message\": \"API 服务可访问（HTTP 400，未提供认证参数）\"}\n  },\n  \"summary\": {\n    \"critical\": \"通过\",\n    \"optional\": \"全部通过\",\n    \"message\": \"环境检查通过，所有功能可用。\"\n  }\n}\n```\n\n### 认证\n```bash\npython insentek_cli.py auth --appid YOUR_APPID --secret YOUR_SECRET\n```\n\n### 查询设备列表\n```bash\npython insentek_cli.py devices --token YOUR_TOKEN --page 1 --limit 20\n```\n\n### 查询数据（含边界检查）\n```bash\npython insentek_cli.py data --token YOUR_TOKEN --sn 00000000000000 --range 20250101,20250131\n```\n\n### 导出 CSV\n```bash\npython insentek_cli.py export --token YOUR_TOKEN --sn 00000000000000 --range 20250101,20250131 --format csv --output data.csv\n```\n\n### 导出 Excel\n```bash\npython export_excel.py --token YOUR_TOKEN --sn 00000000000000 --range 20250101,20250131 --output data.xlsx\n```\n\n### 写入 HTML 报告（AI 动态生成内容后落盘）\n```bash\npython write_html.py --content \"<html>...</html>\" --output report.html\n```\n\n## 输出格式\n\n所有脚本成功时输出：\n```json\n{\n  \"success\": true,\n  \"total\": 1000,\n  \"file\": \"/path/to/file.csv\",\n  \"message\": \"成功导出 1000 条数据到 data.csv\"\n}\n```\n\n失败时输出：\n```json\n{\n  \"success\": false,\n  \"error\": \"单次查询最多支持 1 年范围...\"\n}\n```\n\n## 边界限制\n\n| 限制项 | 值 | 说明 |\n|--------|-----|------|\n| 单次最大跨度 | 365 天 | 超过则拒绝并提示拆分 |\n| 最大历史回溯 | 3 年 | 基于当前日期 |\n| 对话展示上限 | 200 条 | 超过则展示摘要+抽样 |\n| 文件导出上限 | 50,000 条 | 超过则拒绝并建议缩小范围 |\n\nFile v1.2.0:_meta.json\n\n{\n  \"ownerId\": \"kn7dcqpad4aeh2nt5shjf3aerd875anm\",\n  \"slug\": \"insentek-api-skill\",\n  \"version\": \"1.2.0\",\n  \"publishedAt\": 1779701621213\n}\n\nFile v1.2.0:CHANGELOG.md\n\nChangelog\n=========\n\n[1.1.0] - 2026-05-22\n--------------------\n\nChanged\n-------\n\n- **结构性重构: skill.md 模块化拆分**\n  - 主 `skill.md` 从 1100+ 行瘦身至 ~250 行 (Runtime Contract 风格)\n  - 新增 `docs/interaction.md` — 意图解析、时间表达式、输出格式、确认策略\n  - 新增 `docs/analysis.md` — 分析策略、报告生成、告警规则、行业参数\n  - 新增 `examples/flows.md` — 3 个核心交互示例（查询/导出/报告含数据校验）\n  - 删除 `examples/alerts.md`（内容合并至 docs/analysis.md）\n\n- **MUST → SHOULD 降级**\n  - 安全/护栏类保持 MUST（raw_data_output, span limit, auth security）\n  - 分析类降级为 SHOULD / RECOMMENDED / PREFER\n  - 模型分析创造力不再被规则过度压制\n\n- **三层职责分离**\n  - Runtime Contract（skill.md）: 工具、护栏、认证、路由\n  - Interaction Policy（docs/interaction.md）: UX、确认、输出格式\n  - Analysis Engine（docs/analysis.md）: 动态分析、报告、可视化\n\n- **新增 Routing 决策表**\n  - skill.md Section 1: L1意图 × L2输出 → 工具路由矩阵\n  - Agent 无需逐行阅读即可快速定位调用路径\n\n- **版本号统一 bumped 1.0.3 → 1.1.0**\n  - skill.md, README.md, PLATFORM-TEST.md, docs/platform-setup.md\n\n[1.0.3] - 2026-05-22\n--------------------\n\nAdded\n-----\n\n- 数据可用性校验 (skill.md Section 2.5)\n  - `query_data` 返回后 Agent 必须检查实际数据范围 vs 用户请求范围\n  - 若实际覆盖比例 < 50% 或天数 < 7 天，必须 STOP 并向用户确认\n  - 确认消息包含：请求范围、实际范围、可能原因（设备未部署/离线）\n  - 用户确认后才允许继续生成报告\n\n- 报告时间范围标注规范 (skill.md Section 8.3)\n  - 实际范围 = 请求范围：正常标注\n  - 实际范围 < 请求范围：必须注明 \"基于实际可用数据: [actual_range]\"\n  - 绝不允许用请求范围替代实际范围，避免误导用户\n\n- Flow 7 数据范围不匹配处理示例 (skill.md Section 12)\n  - 新增完整交互示例：用户请求近3个月，实际仅13天\n  - 展示 Agent 如何向用户说明情况并等待确认\n\nChanged\n-------\n\n- 报告生成流程 (skill.md Section 8.3)\n  - 在 `query_data` 与 `Agent analyzes data` 之间插入数据可用性校验步骤\n  - Flow 6 增加 `[数据可用性校验] → PASS` 标注\n\n- 版本号统一 bumped 1.0.2 → 1.0.3\n  - skill.md, README.md, PLATFORM-TEST.md, docs/platform-setup.md\n\nWhy\n---\n\n- 用户实际测试发现：请求近3个月数据时，设备仅有13天数据\n- 旧版本直接生成报告并标注\"近3个月\"，对用户产生严重误导\n- 新增校验机制确保报告时间范围真实反映数据可用性\n\n[1.0.2] - 2026-05-21\n--------------------\n\nAdded\n-----\n\n- `scripts/write_html.py` — HTML file writer utility\n  - Receives AI-generated HTML content and writes it to disk\n  - No templating or data processing; purely a safe file-writing tool\n  - Supports `--content`, `--input-file`, and stdin input\n  - Minimal HTML structure validation (warnings only, non-blocking)\n  - Structured JSON output for Agent consumption\n\nChanged\n-------\n\n- Removed deprecated `report` / `chart` / `export --format html` from `scripts/insentek_cli.py`\n  - Deleted `generate_report()`, `generate_chart()`, `get_device_info()`, `extract_param_names()` (~480 lines)\n  - HTML reports are now fully Agent-generated; no hard-coded templates\n  - Updated docstring and argparse to reflect only csv/json export\n\n- Updated `skill.md`\n  - Replaced Section 6.4 `generate_report (DEPRECATED)` with 6.4 `write_html`\n  - Added `write_html.py` to environment check items (non-critical)\n  - Changed API doc reference from active guidance to fallback note in Notes\n  - Updated `--dry-run` note to remove `report` and `chart`\n\n- Updated `.planning/STATE.md`\n  - Added `write_html.py` to Utility Scripts list\n  - Removed HTML export from `insentek_cli.py` description\n\nWhy\n---\n\n- User requirements for reports are diverse; fixed templates cannot cover all scenarios\n- Delegate report generation to AI for flexibility (dynamic analysis, custom visualizations)\n- Provide a clean, single-purpose tool for HTML file output rather than monolithic report generators\n\n[1.0.1] - 2026-05-21\n--------------------\n\nAdded\n-----\n\n- --dry-run preview mode (scripts/insentek_cli.py)\n  - data, export (csv/json/html), report, chart subcommands all support --dry-run\n  - Only outputs record count, time range, field summary (nodes/parameters), and first 5 sample rows\n  - Does not write files or output full data, preventing context explosion during debugging\n\n- --dry-run preview mode (scripts/export_excel.py)\n  - Added --dry-run parameter, behavior consistent with CLI script\n  - Does not generate Excel file, only returns structured JSON preview\n\n- Raw data output prohibition (skill.md)\n  - Added Section 2.4 \"Raw Data Output Prohibition\"\n  - Explicitly prohibits Agent from outputting raw sensor full data directly into conversation\n  - Specifies handling for four common scenarios: summary sampling, --dry-run, guided export, direct refusal\n\n- YAML Guardrails declaration (skill.md frontmatter)\n  - Added guardrails.raw_data_output: PROHIBITED\n  - Added guardrails.dry_run_preview_rows: 5\n  - Added guardrails.max_chat_rows: 200\n  - Added guardrails.max_export_rows: 50000\n\n- Dry-run documentation (skill.md)\n  - Added Section 6.0 \"dry-run preview mode (common to all export scripts)\"\n  - Added --dry-run example in query_data Agent Action\n  - Added \"Dry-run first\" and \"Raw data prohibition\" development guidelines in Notes\n\nChanged\n-------\n\n- Version bumped from 1.0.0 to 1.0.1 (skill.md, README.md, PLATFORM-TEST.md, .planning/STATE.md)\n\nWhy\n---\n\n- Prevent accidental full sensor data injection into conversation context\n- Save Token consumption and improve model processing efficiency\n- Promote as Skill development standard: summaries in chat, full data in files\n\n\n[1.0.0] - 2026-05-14\n--------------------\n\nAdded\n-----\n\n- Initial release with intent resolution, query guardrails, and export scripts\n- Three-layer intent model (L1 core -> L2 output -> L3 format)\n- Query guardrails: max 365 days span, max 3 years history, max 200 chat rows, max 50000 export rows\n- Utility scripts: insentek_cli.py (unified CLI), export_excel.py (Excel export)\n- Environment prerequisites check command\n- Session-based authentication caching\n- Multi-industry adaptation (agriculture, meteorology, industrial level monitoring)\n\nFile v1.2.0:CLAUDE.md\n\n# insentek-api-skills\n\nThis is a GSD-managed project. Use `/gsd-progress` to check status and next steps.\n\n## Project Overview\n\n基于 insentek OpenAPI 工程仓库和接口文档，产出一份通用 `skill.md` 技能文件及配套文档与示例。终端用户可在 OpenClaw、Hermes-Agent、Claude Code、ChatGPT 等 Agent 平台上直接对话使用，通过自然语言调用 insentek API 完成设备数据查询、报告生成与实时分析。\n\n## Quick Links\n\n- Project context: `.planning/PROJECT.md`\n- Requirements: `.planning/REQUIREMENTS.md`\n- Roadmap: `.planning/ROADMAP.md`\n- Current state: `.planning/STATE.md`\n\n## Working with This Project\n\n1. Always read `.planning/STATE.md` first to understand current phase and focus\n2. Check `.planning/PROJECT.md` for core value and constraints\n3. Follow the roadmap phase order\n4. Update STATE.md when phase status changes\n\n## Key Decisions\n\n- Single universal `skill.md` (not per-industry splits)\n- Content production project (not a tool/generator)\n- Horizontal Layers phase structure\n- 1-2 week delivery timeline\n\n## Reference Materials\n\n- API codebase: `ref/api-repo/` (Spring Boot 3.5.4, Java 21)\n- API documentation: `ref/api-document-latest.pdf`\n\nFile v1.2.0:docs/analysis.md\n\n# Analysis Guide — 分析与报告\n\n> Agent 驱动的数据分析策略、报告生成规范、告警检测规则。\n> 本文件按需加载，仅在用户提出分析/报告需求时读取。\n\n---\n\n## 1. Analysis Philosophy\n\n分析由 Agent **动态推理**完成，避免硬编码模板。\n\n**推荐流程：**\n1. **Parse intent** — 用户到底想知道什么？（相关性、异常、趋势、对比）\n2. **Select method** — 根据问题选择合适的统计/数学方法\n3. **Compute** — 用 Python 脚本实时计算\n4. **Synthesize** — 用自然语言解释，结合领域上下文\n5. **Deliver** — 表格、图表、HTML 报告\n\n**语气：** 分析部分使用 SHOULD / RECOMMENDED / PREFER，不强制具体方法。\n\n---\n\n## 2. Common Patterns\n\n| 用户问题 | 推荐方法 | 交付物 |\n|---------|---------|--------|\n| \"分析 X 和 Y 的关系\" | Pearson/Spearman 相关 + 散点图 | 相关系数 + 散点图 + 解释 |\n| \"找出异常数据\" | 阈值检测或统计离群点 | 异常列表 + 时间标记 |\n| \"对比两台设备\" | 并排统计 + 差异分析 | 对比表 + 差异高亮 |\n| \"最近有什么趋势\" | 线性回归 / 变化率 | 趋势方向 + 变化率 + 图表 |\n| \"降雨最多的几天\" | 百分位 / 最大值筛选 | 极值列表 + 日期 |\n| \"数据分布如何\" | 直方图 / 分位数 (P10/P50/P90) | 分布图 + 分位数 |\n| \"昼夜温差多大\" | 昼夜分段 + 范围计算 | 昼夜统计对比表 |\n| \"近一年每日趋势\" | 按天聚合 (daily average) | 折线图 + 月度统计 |\n\n**Key Principle:** 输出应直接回答用户问题，而非堆砌统计数据。\n\n---\n\n## 3. Report Generation Guide\n\n### 3.1 流程\n\n```\nquery_device → resolve sn\nquery_data → retrieve data\n[数据可用性校验] → 见 skill.md 3.2\nanalyze (statistics, trends, anomalies)\nconstruct HTML (ECharts + CSS)\nwrite_html → return path\n```\n\n### 3.2 HTML 结构（RECOMMENDED）\n\n```html\n<!-- 最小骨架示例 -->\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <script src=\"https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js\"></script>\n  <style>/* 简洁响应式布局 */ body { font-family: sans-serif; max-width: 960px; margin: 0 auto; } </style>\n</head>\n<body>\n  <h1>设备分析报告</h1>\n  <div class=\"header\">\n    设备: [别名] (SN: [后4位]) | 类型: [Z/T/J] | 位置: [城市]\n    分析时段: [actual_range] | 数据点: [N] 条\n  </div>\n  <div class=\"key-findings\"><!-- 核心指标卡片 --></div>\n  <div class=\"charts\"><!-- ECharts 图表容器 --></div>\n  <div class=\"details\"><!-- 详细表格 --></div>\n  <div class=\"conclusion\"><!-- 文字总结 --></div>\n</body>\n</html>\n```\n\n### 3.3 时间范围标注规范（MUST）\n\n| 场景 | 标注方式 |\n|------|---------|\n| 实际 = 请求 | `\"分析时段: [范围]\"` |\n| 实际 < 请求 | `\"分析时段: [actual_range]（您请求的 [requested_range] 中，该设备仅有此区间数据）\"` |\n\n**绝不允许**用请求范围替代实际范围。\n\n### 3.4 可视化推荐\n\n- **时间序列趋势** → ECharts line chart\n- **两变量关系** → ECharts scatter plot\n- **多维度对比** → ECharts bar chart 或 radar chart\n- **地理分布** → ECharts map (如有位置数据)\n- **分布分析** → ECharts histogram 或 box plot\n\n### 3.5 Anti-patterns\n\n- 不要在项目目录中创建 `generate_report_v2.py` 等可复用脚本\n- 每个报告应 ad-hoc 生成，用完即删临时脚本\n- 不要只放图表不加文字解释\n\n完整报告示例见 `examples/reports.md`。\n\n---\n\n## 4. Alert Detection Rules\n\n数据获取后，自动扫描异常：\n\n| 参数 | 告警条件 | 严重级别 |\n|------|---------|---------|\n| `moisture` (土壤水分) | < 5% or > 50% | Warning |\n| `temperature` (温度) | 1小时内变化 > 10°C | Critical |\n| `battery` (电池电压) | < 3.0V | Critical |\n| `ec` (电导率) | < 0 or > 20 | Warning |\n| `laserliquidLevel` (激光液位) | < 0 | Warning |\n\n**输出格式：**\n```\n⚠️ 异常数据检测\n- [参数名] 在 [节点] [时间]: [值] [单位] — [异常描述]\n```\n\n---\n\n## 5. Multi-Industry Parameters\n\n设备类型决定显示参数的中文名：\n\n| 类型码 | 行业 | 关键参数 |\n|--------|------|---------|\n| `Z` | 农业 / 土壤监测 | moisture, temperature, ec |\n| `T` | 气象 / 气象站 | airTemperature, relativeHumidity, rainfall, wind... |\n| `J` | 工业 / 液位监测 | laserliquidLevel, battery |\n\n通过 `/v3/device/{sn}/description` 获取参数中文名，优先用中文展示。\n\n完整参数参考见 `reference/api-doc.md`。\n\nFile v1.2.0:docs/getting-started.md\n\n# Getting Started — 快速开始\n\n> 5 分钟内配置完成，开始用自然语言查询设备数据。\n\n---\n\n## 你需要什么\n\n| 项目 | 说明 | 获取方式 |\n|------|------|---------|\n| `appid` | 应用 ID | E 生态后台创建应用后获得 |\n| `secret` | 应用密钥 | 与 appid 同时生成 |\n| 设备 | 已接入 insentek 平台的物联网设备 | 联系 insentek 或自行部署 |\n\n---\n\n## 第一步：获取认证信息\n\n1. 登录 [E 生态](https://www.ecois.info)\n2. 进入「应用管理」→「创建应用」\n3. 复制 `appid` 和 `secret`\n4. **妥善保存 secret，不要泄露给他人**\n\n---\n\n## 第二步：选择平台并加载 Skill\n\n将 `skill.md` 文件内容加载到你使用的 Agent 平台：\n\n| 平台 | 加载方式 | 详见 |\n|------|---------|------|\n| **OpenClaw** | 导入 skill 文件 | [platform-setup.md](platform-setup.md#openclaw) |\n| **Claude Code** | 放入项目目录或粘贴到对话 | [platform-setup.md](platform-setup.md#claude-code) |\n| **ChatGPT** | 粘贴到 Custom Instructions 或 GPTs 配置 | [platform-setup.md](platform-setup.md#chatgpt) |\n| **Hermes-Agent** | 导入技能包 | [platform-setup.md](platform-setup.md#hermes-agent) |\n\n---\n\n## 第三步：开始对话\n\n首次对话时，提供你的 `appid` 和 `secret`：\n\n> **User:** 我的 appid 是 test，secret 是 test，帮我查看所有设备。\n\nAgent 会自动：\n1. 用 appid + secret 获取 token\n2. 查询你的设备列表\n3. 返回设备信息\n\n后续对话无需重复提供认证信息（token 会在对话中自动缓存）。\n\n---\n\n## 常用查询示例\n\n### 查看设备列表\n```\n查看我的设备\n```\n\n### 查询实时数据\n```\n3号设备现在的温度是多少？\n```\n\n### 查询历史数据\n```\n1号设备上周的土壤湿度变化\n```\n\n### 多设备对比\n```\n对比一下1号和2号设备的温度\n```\n\n### 异常检测\n```\n检查一下所有设备的电池状态\n```\n\n---\n\n## 支持的设备类型\n\n| 类型代码 | 设备名称 | 典型参数 |\n|---------|---------|---------|\n| `Z` | 土壤墒情仪 | 土壤温度、土壤水分、电导率 |\n| `T` | 气象站 | 空气温度、湿度、风速、降雨量 |\n| `J` | 见厘液位计 | 激光液位、电池电压 |\n\n---\n\n## 时间表达支持\n\n你可以用自然语言描述时间，Agent 会自动转换：\n\n| 你说 | Agent 理解 |\n|------|-----------|\n| \"现在\" / \"最新\" / \"实时\" | 调用实时数据接口 |\n| \"昨天\" | 昨天的全部数据 |\n| \"最近7天\" / \"近一周\" | 过去 7 天的数据 |\n| \"上周\" | 上周一至周日 |\n| \"本月\" | 本月 1 号到今天 |\n| \"某时刻\" / \"12点30分\" | 指定时间点的数据 |\n| *(没提时间)* | 默认最近 24 小时 |\n\n---\n\n## 下一步\n\n- 查看 [platform-setup.md](platform-setup.md) 了解各平台详细配置步骤\n- 查看 [`reference/api-doc.md`](../reference/api-doc.md) 了解完整 API 参数详情\n- 查看项目根目录 `examples/` 目录中的对话示例\n\n---\n\n## 常见问题\n\n**Q: token 多久过期？**\nA: 默认 2 小时（7200 秒）。Agent 会在过期前 5 分钟自动刷新，无需你操作。\n\n**Q: 可以用设备别名查询吗？**\nA: 可以。Agent 支持别名部分匹配，如 \"3号\" 会匹配别名为 \"3号大棚\" 的设备。\n\n**Q: 数据查询有时间范围限制吗？**\nA: 增量同步接口（/incremental）首次调用返回最近 3 个月数据。历史数据查询最大支持 3 年回溯，单次查询跨度不超过 365 天。建议单次查询不超过 30 天以提高响应速度。\n\n**Q: 支持英文查询吗？**\nA: skill.md 中的 Prompt 指令为中文，但 Agent 平台通常支持多语言理解。英文查询的效果取决于具体 Agent 平台。\n\nFile v1.2.0:docs/interaction.md\n\n# Interaction Guide — 交互规范\n\n> 完整交互流程、时间解析、输出格式、确认策略。\n> 本文件按需加载，非每次调用必读。\n\n---\n\n## 1. Intent Resolution\n\n### 1.1 三层模型\n\n| 层级 | 名称 | 说明 | 缺失时处理 |\n|------|------|------|-----------|\n| L1 | 核心意图 | 查数据 / 对比 / 导出 / 生成报告 | 反问：\"您想查询数据、对比设备，还是导出报告？\" |\n| L2 | 输出意图 | 对话展示 / 文件导出 | 提供选项让用户选择 |\n| L3 | 格式意图 | CSV / Excel / JSON / HTML | L2=文件时询问；推荐 CSV 为默认 |\n\n### 1.2 关键词映射\n\n| 用户关键词 | 推断 L1 | 推断 L2 | 需确认 L3？ |\n|-----------|---------|---------|-------------|\n| \"查一下\"、\"看看\"、\"多少\" | 查询数据 | 对话展示 | 否 |\n| \"导出\"、\"下载\"、\"保存\" | 查询数据 | 文件导出 | **是** |\n| \"生成报告\"、\"做一份报告\" | 生成报告 | 文件导出 | **是** |\n| \"对比\"、\"比较\"、\"哪个高\" | 对比设备 | 对话展示 | 否 |\n| \"把对比结果导出来\" | 对比设备 | 文件导出 | **是** |\n\n### 1.3 快捷意图（无需确认）\n\n- \"导出 [设备] [时间段] 数据为 [格式]\"\n- \"下载 [设备] 的 [时间段] CSV\"\n- \"生成 [设备] [时间段] 的 HTML 报告\"\n- \"把 [设备A] 和 [设备B] [时间段] 的对比结果导出为 Excel\"\n\n---\n\n## 2. Time Expression Parsing\n\n| 表达式 | 开始 | 结束 | 示例 (today=2025-05-13) |\n|--------|------|------|------------------------|\n| \"现在\" / \"最新\" / \"实时\" | — | — | `GET /latest` |\n| \"昨天\" | yesterday | yesterday | `20250512,20250512` |\n| \"最近7天\" / \"近一周\" | today-7d | today | `20250506,20250513` |\n| \"上周\" | last Monday | last Sunday | `20250505,20250511` |\n| \"本周\" | this Monday | today | `20250512,20250513` |\n| \"本月\" | 1st | today | `20250501,20250513` |\n| \"上月\" | 1st of last month | last day of last month | `20250401,20250430` |\n| \"今年\" | Jan 1 | today | `20250101,20250513` |\n| \"最近1个月\" | today-30d | today | `20250413,20250513` |\n| \"最近3个月\" | today-90d | today | `20250212,20250513` |\n| \"最近1年\" | today-365d | today | `20240513,20250513` |\n| *(default)* | today-1d | today | `20250512,20250513` |\n\n**编码规则：** `YYYYMMDD`，Range: `startYYYYMMDD,endYYYYMMDD`。Moment: `YYYY-MM-DD HH:MM:SS` URL-encoded。\n\n**月份边界：** \"上月\"在 1月31日说 → 12月全月；\"本月\"在当月任意日期 → 1号至今天。\n\n---\n\n## 3. Confirmation Patterns\n\n**MUST 向用户确认的场景：**\n\n1. L1/L2 意图不明确（见 1.1）\n2. 数据可用性覆盖 < 50% 或 < 7 天（见 `skill.md` 3.2）\n3. 多设备 alias 模糊匹配到多个结果\n4. 导出数据量 > 50,000 条\n5. 查询跨度 > 365 天\n\n**可直接执行的场景：**\n- 一句话完整表达（见 1.3）\n- 同一会话内再次查询（已有缓存）\n- 实时数据查询（/latest）\n\n---\n\n## 4. Output Format Guide\n\n### 4.1 实时数据 → 简洁卡片\n\n```\n📍 [设备别名] ([SN后4位])\n─────────────────────────\n🌡️ [参数中文名]: [值] [单位]  @[时间]\n💧 [参数中文名]: [值] [单位]\n🔋 [参数中文名]: [值] [单位]\n─────────────────────────\n状态: [状态描述]  |  位置: [城市]\n```\n\n### 4.2 历史数据（对话）→ 表格 + 趋势\n\n≤ 200 条：完整表格 + 趋势小结\n\n> 200 条：统计摘要 + 首尾各 10 条抽样 + 提示导出\n\n```\n📊 数据概览（共 N 条，展示摘要）\n\n统计摘要:\n| 参数 | 平均 | 最大 | 最小 | 变化率 |\n|------|------|------|------|--------|\n\n💡 提示: 该时间段数据量较大，如需完整数据请说\"导出为CSV\"。\n```\n\n### 4.3 文件导出 → 确认信息\n\n```\n✅ 导出成功\n📄 文件: [filename.csv]\n📊 数据条数: [N] 条\n📅 时间范围: [开始] 至 [结束]\n📥 文件路径: [绝对路径]\n```\n\n### 4.4 对比分析 → 并排表格\n\n```markdown\n| 参数 | [设备A] | [设备B] | 差异 |\n|------|---------|---------|------|\n```\n\n### 4.5 告警报告 → 标记列表\n\n```\n⚠️ 检测到 N 条异常数据:\n1. [时间] [节点] [参数]: [值] — [异常原因]\n```\n\n---\n\n## 5. Interaction Examples\n\n### Flow 1: 查询历史数据（对话展示）\n\n```\nUser: \"3号设备上周的土壤湿度\"\n  → check auth → authenticate if needed\n  → query_device(alias=\"3号\") → resolve sn\n  → query_data(sn, \"上周\") → /data\n  → data points ≤ 200 → show table + trend\n```\n\n### Flow 2: 导出数据（文件导出）\n\n```\nUser: \"导出3号设备上个月数据为CSV\"\n  → check auth → authenticate if needed\n  → query_device(alias=\"3号\") → resolve sn\n  → validate range (30d ≤ 365d) → OK\n  → export_csv(sn, range, \"data.csv\") → return path\n```\n\n### Flow 3: 生成报告（数据不匹配 → 确认）\n\n```\nUser: \"分析3号近三个月数据，生成报告\"\n  → check auth → authenticate if needed\n  → query_device(alias=\"3号\") → resolve sn\n  → query_data(sn, \"最近3个月\")\n     → 请求: 90天 / 实际: 13天 → coverage 14%\n  → STOP: \"您请求近3个月共90天，该设备实际仅13天数据。是否继续？\"\n  → User: \"继续\"\n  → analyze → construct HTML → write_html → return path\n```\n\n完整多设备对比、分批导出等示例见 `examples/flows.md`。\n\nFile v1.2.0:docs/platform-setup.md\n\n# Platform Setup Guide — 各 Agent 平台配置指南\n\n> 将 insentek skill 安装到不同 Agent 平台的完整步骤，含安装路径、卸载方法和故障排查。\n\n---\n\n## 目录\n\n- [OpenClaw](#openclaw)\n- [Claude Code](#claude-code)\n- [ChatGPT](#chatgpt)\n- [Hermes-Agent](#hermes-agent)\n- [平台兼容性速查](#平台兼容性速查)\n- [故障排查](#故障排查)\n\n---\n\n## OpenClaw\n\n### 安装\n\n#### 方式一：从 ClawHub 安装（推荐）\n\n```bash\n# 安装最新版本\nclawhub skill install insentek-api-skill\n\n# 安装指定版本\nclawhub skill install insentek-api-skill@1.1.0\n\n# 从 ClawHub 搜索确认\nclawhub skill search insentek\n```\n\n安装完成后，skill 会自动注册到 OpenClaw 的技能列表中。\n\n#### 方式二：本地文件安装\n\n```bash\n# 从本地 skill.md 安装\nclawhub skill add ./skill.md\n\n# 或使用绝对路径\nclawhub skill add /path/to/skill.md\n```\n\n#### 方式三：Web UI 安装\n\n1. 打开 OpenClaw 客户端，进入 **Skills** 页面\n2. 点击 **Import Skill** → 选择文件\n3. 选择项目根目录的 `skill.md` 文件\n4. 确认导入\n\n### 卸载\n\n```bash\n# CLI 卸载\nclawhub skill remove insentek-api-skill\n```\n\n或在 Web UI 中：Skills → 找到 \"insentek-api-skill\" → **Remove**。\n\n### 配置参数\n\n| 参数 | 值 | 说明 |\n|------|-----|------|\n| API Base URL | `http://openapi.ecois.info` | 默认即可 |\n\n### 首次使用\n\n```\nUser: 我的 appid 是 xxx，secret 是 yyy，查看所有设备\n```\n\nOpenClaw 会自动解析 skill.md 中的 function schema 并调用 authenticate 工具。\n\n---\n\n## Claude Code\n\n### 安装\n\nClaude Code 通过读取 skill 文件来加载技能上下文，支持项目级和全局级两种方式。\n\n#### 方式一：全局 Skills 目录（推荐）\n\nClaude Code 会从全局 skills 目录自动加载所有 skill 文件，无需在每个项目中重复放置。\n\n**Windows:**\n```powershell\n# 创建 skills 目录（如果不存在）\nNew-Item -ItemType Directory -Force -Path \"$env:USERPROFILE\\.claude\\skills\"\n\n# 复制 skill 文件\nCopy-Item skill.md \"$env:USERPROFILE\\.claude\\skills\\insentek-api-skill.md\"\n```\n\n**macOS:**\n```bash\nmkdir -p ~/.claude/skills\ncp skill.md ~/.claude/skills/insentek-api-skill.md\n```\n\n**Linux:**\n```bash\nmkdir -p ~/.claude/skills\ncp skill.md ~/.claude/skills/insentek-api-skill.md\n```\n\n放置后重启 Claude Code 或重新打开对话即可生效。\n\n#### 方式二：项目目录加载\n\n将 `skill.md` 放入当前工作项目的根目录，Claude Code 会自动识别为项目上下文：\n\n```bash\n# 任意项目目录\ncp skill.md ./skill.md\n```\n\n#### 方式三：对话中直接引用\n\n```\n# 在 Claude Code 对话中执行\n/load skill.md\n```\n\n或直接将 `skill.md` 内容粘贴到对话中。\n\n### 卸载\n\n- **全局级（推荐）**：从 `~/.claude/skills/` 目录移除对应文件\n  ```bash\n  # Windows\n  Remove-Item \"$env:USERPROFILE\\.claude\\skills\\insentek-api-skill.md\"\n\n  # macOS / Linux\n  rm ~/.claude/skills/insentek-api-skill.md\n  ```\n- **项目级**：删除项目根目录的 `skill.md` 文件\n- **对话级**：执行 `/clear` 清除当前对话上下文\n\n### 首次使用\n\n```\nUser: 我的 appid 是 xxx，secret 是 yyy，查看所有设备\n```\n\nClaude Code 会读取 skill.md 中的 tool definitions，使用 function calling 调用 API。\n\n### 注意事项\n\n- 确保 skill.md 中的 YAML frontmatter 被正确解析\n- 如果 function calling 未触发，尝试明确说出工具名称如 \"query_device\"\n\n---\n\n## ChatGPT\n\n### 安装\n\n#### 方式一：创建 GPT（推荐，需 Plus 订阅）\n\n1. 打开 [ChatGPT](https://chat.openai.com) → **Explore GPTs** → **Create**\n2. 在 Configure 标签页：\n   - **Name**: Insentek Device Query\n   - **Description**: 查询 insentek 物联网设备数据\n   - **Instructions**: 粘贴 `skill.md` 的完整内容\n3. 在 **Capabilities** 中启用 \"Code Interpreter\"（如需数据处理）\n4. 保存并发布（可选设为 Private）\n\n#### 方式二：Actions（API 直连，需 Plus 订阅）\n\n1. 创建 GPT 时，在 Configure 页面点击 **Add actions**\n2. 粘贴由 `skill.md` function schema 生成的 OpenAPI schema\n3. 设置认证方式：API Key（Header: `Authorization`）\n4. 保存后 GPT 可直接调用 insentek API\n\n#### 方式三：Custom Instructions（个人使用）\n\n适合临时使用，无需创建 GPT。\n\n1. 打开 ChatGPT → 点击头像 → **Custom Instructions**\n2. 在 \"How would you like ChatGPT to respond?\" 中粘贴 `skill.md` 的 Prompt 区内容\n3. 在 \"What would you like ChatGPT to know about you?\" 中填入：\n   ```\n   我有 insentek 物联网设备，appid: xxx, secret: yyy\n   ```\n4. 保存后开始新对话\n\n**限制：** Custom Instructions 不支持真正的 function calling，API 调用需要手动复制 URL。\n\n### 卸载\n\n- **GPTs 方式**：ChatGPT → Explore GPTs → 找到对应 GPT → 右上角 ⋮ → **Delete GPT**\n- **Actions 方式**：编辑 GPT → Configure → Actions → **删除对应 Action**\n- **Custom Instructions**：ChatGPT → 头像 → Custom Instructions → **清空内容**\n\n### 首次使用\n\n```\nUser: 查看我的所有设备\n```\n\n如果已配置 appid/secret，ChatGPT 会自动认证并查询。\n\n---\n\n## Hermes-Agent\n\n### 安装\n\nHermes-Agent 通过读取 skills 目录下的 skill 文件来加载技能。\n\n#### 步骤\n\n**Windows:**\n```powershell\n# 创建 skills 目录（如果不存在）\nNew-Item -ItemType Directory -Force -Path \"$env:USERPROFILE\\.hermes\\skills\"\n\n# 复制 skill 文件\nCopy-Item skill.md \"$env:USERPROFILE\\.hermes\\skills\\insentek-api-skill.md\"\n```\n\n**macOS:**\n```bash\nmkdir -p ~/.hermes/skills\ncp skill.md ~/.hermes/skills/insentek-api-skill.md\n```\n\n**Linux:**\n```bash\nmkdir -p ~/.hermes/skills\ncp skill.md ~/.hermes/skills/insentek-api-skill.md\n```\n\n**重启或刷新：**\n```bash\nhermes skill reload\n# 或重启 Hermes-Agent 服务\n```\n\n### 卸载\n\n**Windows:**\n```powershell\nRemove-Item \"$env:USERPROFILE\\.hermes\\skills\\insentek-api-skill.md\"\n```\n\n**macOS / Linux:**\n```bash\nrm ~/.hermes/skills/insentek-api-skill.md\nhermes skill reload\n```\n\n### 配置环境变量（可选）\n\n```bash\nexport INSENTEK_BASE_URL=http://openapi.ecois.info\n```\n\n### 首次使用\n\n```\nUser: appid xxx secret yyy，查看设备\n```\n\nHermes-Agent 会解析 skill.md 中的工具定义并执行对应动作。\n\n---\n\n## 平台兼容性速查\n\n| 特性 | OpenClaw | Claude Code | ChatGPT (GPTs) | Hermes-Agent |\n|------|----------|-------------|----------------|--------------|\n| Function Schema | Native | Native | Via Actions | Native |\n| YAML Frontmatter | ✅ | ✅ | ⚠️ | ✅ |\n| Auto Token Refresh | ✅ | ✅ | Manual | ✅ |\n| Alias Resolution | ✅ | ✅ | ✅ | ✅ |\n| Time Parsing | ✅ | ✅ | ✅ | ✅ |\n| Chain Calling | ✅ | ✅ | ✅ | ✅ |\n| ClawHub 一键安装 | ✅ | ❌ | ❌ | ❌ |\n\n**图例：** ✅ 原生支持 | ⚠️ 需额外配置 | ❌ 不支持\n\n---\n\n## 故障排查\n\n### Function Schema 未被识别\n\n- **Claude Code**: 确保 skill.md 位于项目根目录，且文件名为 `skill.md`\n- **ChatGPT**: 使用 GPTs 的 Actions 功能，或手动粘贴 Instructions\n- **通用**: 检查 YAML frontmatter 格式是否正确（`---` 开头和结尾）\n\n### 认证失败\n\n1. 确认 appid 和 secret 正确（无多余空格）\n2. 检查网络是否能访问 `http://openapi.ecois.info`\n3. 确认 token 未过期（skill 会自动刷新，但首次需手动提供）\n\n### 查询无数据返回\n\n1. 确认设备已正确接入 insentek 平台\n2. 检查时间范围是否合理（默认最近 24 小时可能无数据）\n3. 尝试扩大时间范围如 \"最近7天\"\n\n---\n\n*配置问题请联系：参考 insentek 官方支持渠道*\n\nFile v1.2.0:examples/flows.md\n\n# Examples: Core Interaction Flows\n\n> 3 个核心交互流程，覆盖最常见的使用场景。\n> 完整交互规范见 `docs/interaction.md`。\n\n---\n\n## Flow 1: Query Historical Data (Chat)\n\n### User Input\n```\n3号设备上周的土壤湿度\n```\n\n### Agent Thinking\n1. alias=\"3号\" → resolve sn via `query_device`\n2. time=\"上周\" → range = last Monday ~ last Sunday\n3. param=\"土壤湿度\" → includeParams = moisture\n4. output intent = chat (implicit)\n\n### Tool Calls\n```\nquery_device(alias=\"3号\")\n  → sn = \"00000000000001\"\n\nquery_data(sn=\"00000000000001\", time_expression=\"上周\", includeParameters=\"moisture\")\n  → GET /v3/device/00000000000001/data?range=20250505,20250511&includeParams=moisture\n```\n\n### Output\n```markdown\n📊 3号大棚 — 上周土壤湿度 (2025-05-05 ~ 2025-05-11)\n\n| 日期 | 10cm | 20cm | 30cm | 40cm |\n|------|------|------|------|------|\n| 05-05 | 22.1 | 23.5 | 25.1 | 26.5 |\n| ... | ... | ... | ... | ... |\n\n📈 趋势小结:\n- 各层湿度平稳，40cm深层保持最高\n- 10cm表层受蒸发影响日间波动稍大\n```\n\n---\n\n## Flow 2: Export Data (File)\n\n### User Input\n```\n导出3号设备上个月数据为CSV\n```\n\n### Agent Thinking\n1. alias=\"3号\" → resolve sn\n2. time=\"上个月\" → range = 20250401,20250430\n3. format=\"CSV\" → export_csv\n4. Validate: 30 days ≤ 365 days → OK\n\n### Tool Calls\n```\nquery_device(alias=\"3号\") → sn = \"00000000000001\"\n\nexport_csv(sn=\"00000000000001\", range=\"20250401,20250430\", output=\"3号_2025-04.csv\")\n  → 成功导出 720 条数据\n```\n\n### Output\n```\n✅ 导出成功\n\n📄 文件: 3号_2025-04.csv\n📊 数据条数: 720 条\n📅 时间范围: 2025-04-01 至 2025-04-30\n📥 文件路径: /absolute/path/to/3号_2025-04.csv\n```\n\n---\n\n## Flow 3: Generate Report (Data Availability Mismatch)\n\n### User Input\n```\n分析11684501348336近三个月的数据，生成报告\n```\n\n### Agent Thinking\n1. alias=\"11684501348336\" → resolve sn\n2. time=\"近3个月\" → requested range = 2026-02-22 ~ 2026-05-22 (90 days)\n3. query_data → retrieve actual data\n4. **数据可用性校验**: actual = 2025-05-10 ~ 2025-05-22 (13 days)\n5. coverage = 13/90 = 14% < 50% → **STOP and confirm**\n\n### Tool Calls\n```\nquery_device(alias=\"11684501348336\") → sn = \"11684501348336\"\n\nquery_data(sn=\"11684501348336\", time_expression=\"最近3个月\")\n  → actual range: 2025-05-10 ~ 2025-05-22 (13 records)\n```\n\n### Agent Confirmation\n```\n您请求的『近3个月』共约 90 天，\n但该设备实际仅有 2025-05-10 至 2025-05-22 共 13 天的数据。\n\n可能原因：\n- 设备在该时间段尚未部署或激活\n- 设备期间出现离线/故障导致数据缺失\n\n是否继续基于现有 13 天数据生成报告？\n```\n\n### User Response\n```\n继续\n```\n\n### Analysis & Report Generation\n```\n→ 统计摘要: 均值、最大、最小、标准差\n→ 趋势分析: 线性变化率\n→ 异常检测: 扫描 battery, moisture, temperature\n→ 构建 HTML (ECharts line chart + summary cards)\n→ write_html → report.html\n```\n\n### Output\n```\n✅ 报告已生成\n\n📄 文件: report_11684501348336.html\n📊 分析数据: 13 条 (2025-05-10 至 2025-05-22)\n⚠️  注: 基于实际可用数据，非完整 3 个月\n📥 文件路径: /absolute/path/to/report_11684501348336.html\n```\n\n---\n\n## Other Scenarios\n\n更多场景（多设备对比、批量导出、实时查询、告警检测）见：\n- `examples/queries.md` — 查询类对话示例\n- `examples/reports.md` — 报告生成示例\n- `docs/interaction.md` Section 5 — 完整确认策略\n\nFile v1.2.0:examples/queries.md\n\n# Examples: Query Conversations — 查询类对话示例\n\n> 展示用户如何用自然语言查询设备数据，以及 Agent 的完整处理过程。\n> 完整交互规范见 [`docs/interaction.md`](../docs/interaction.md)。\n\n---\n\n## Example 1: 查看设备列表\n\n### User Input\n```\n查看我的所有设备\n```\n\n### Agent Thinking\n1. 用户没有提供 sn 或 alias → 调用设备列表查询\n2. 无时间线索 → 不需要 query_data\n3. 需要认证（如 token 未缓存）\n\n### Tool Calls\n```\nauthenticate(appid=\"xxx\", secret=\"yyy\")\n  → { token: \"abc123\", expires: 7200 }\n\nquery_device(page=1, limit=20)\n  → GET /v3/devices?page=1&limit=20\n```\n\n### Formatted Output\n```\n📋 设备列表（共 3 台）\n\n┌─────┬──────────────┬──────────┬────────┬──────────┐\n│ 序号 │ 别名         │ 类型     │ 状态   │ 位置     │\n├─────┼──────────────┼──────────┼────────┼──────────┤\n│ 1   │ 1号大棚      │ 土壤监测 │ 工作中 │ 甘肃兰州 │\n│ 2   │ 2号大棚      │ 土壤监测 │ 工作中 │ 甘肃兰州 │\n│ 3   │ 气象站A      │ 气象监测 │ 工作中 │ 甘肃兰州 │\n└─────┴──────────────┴──────────┴────────┴──────────┘\n\n💡 提示: 直接说\"1号大棚的温度\"即可查询具体设备数据\n```\n\n---\n\n## Example 2: 查询实时数据\n\n### User Input\n```\n1号大棚现在的土壤温度和湿度\n```\n\n### Agent Thinking\n1. 用户提供了 alias=\"1号大棚\" → 需要先解析为 sn\n2. 时间线索: \"现在\" → 调用 /latest 端点\n3. 参数过滤: \"土壤温度\" → temperature, \"湿度\" → moisture\n\n### Tool Calls\n```\nquery_device(alias=\"1号大棚\")\n  → GET /v3/devices (find matching alias)\n  → sn = \"00000000000001\"\n  → GET /v3/device/00000000000001/description\n\nquery_data(sn=\"00000000000001\", time_expression=\"现在\", includeParameters=\"temperature,moisture\")\n  → GET /v3/device/00000000000001/latest\n```\n\n### Formatted Output\n```\n📍 1号大棚 (0001)\n─────────────────────────\n🕐 2025-05-13 14:32:18\n\n🌡️ 土壤温度:\n   10cm: 18.5 ℃\n   20cm: 17.2 ℃\n   30cm: 16.8 ℃\n   40cm: 16.1 ℃\n\n💧 土壤水分:\n   10cm: 23.4 %\n   20cm: 24.1 %\n   30cm: 25.6 %\n   40cm: 27.2 %\n\n─────────────────────────\n状态: 工作中 | 位置: 甘肃兰州\n```\n\n---\n\n## Example 3: 查询历史数据（带趋势分析）\n\n### User Input\n```\n1号大棚最近7天的土壤温度变化趋势\n```\n\n### Agent Thinking\n1. alias=\"1号大棚\" → 解析 sn\n2. 时间线索: \"最近7天\" → range = today-7d ~ today\n3. 参数: \"土壤温度\" → temperature\n4. 用户要求\"趋势\" → 需要计算平均值、最大值、最小值、变化率\n\n### Tool Calls\n```\nquery_device(alias=\"1号大棚\")\n  → sn = \"00000000000001\"\n\nquery_data(sn=\"00000000000001\", time_expression=\"最近7天\", includeParameters=\"temperature\")\n  → GET /v3/device/00000000000001/data?range=20250506,20250513&includeParameters=temperature\n```\n\n### Formatted Output\n```\n📊 1号大棚 — 最近7天土壤温度\n\n| 日期       | 10cm  | 20cm  | 30cm  | 40cm  |\n|-----------|-------|-------|-------|-------|\n| 05-06     | 17.2  | 16.5  | 16.1  | 15.8  |\n| 05-07     | 18.1  | 17.0  | 16.5  | 16.0  |\n| 05-08     | 19.5  | 17.8  | 17.0  | 16.3  |\n| 05-09     | 20.3  | 18.5  | 17.4  | 16.5  |\n| 05-10     | 19.8  | 18.2  | 17.2  | 16.4  |\n| 05-11     | 18.6  | 17.5  | 16.8  | 16.1  |\n| 05-12     | 18.0  | 17.0  | 16.5  | 15.9  |\n| 05-13     | 18.5  | 17.2  | 16.8  | 16.1  |\n\n📈 趋势小结（10cm 层）:\n• 平均: 18.75 ℃\n• 最高: 20.3 ℃ @ 05-09\n• 最低: 17.2 ℃ @ 05-06\n• 变化: +1.3 ℃ (+7.6%) — 总体平稳略升\n```\n\n---\n\n## Example 4: 查询指定时刻数据\n\n### User Input\n```\n气象站A昨天中午12点的数据\n```\n\n### Agent Thinking\n1. alias=\"气象站A\" → 解析 sn\n2. 时间线索: \"昨天中午12点\" → /moment/{datetime}\n3. datetime = \"2025-05-12 12:00:00\"\n\n### Tool Calls\n```\nquery_device(alias=\"气象站A\")\n  → sn = \"00000000000003\"\n\nquery_data(sn=\"00000000000003\", time_expression=\"昨天中午12点\")\n  → GET /v3/device/00000000000003/data/moment/2025-05-12%2012:00:00\n```\n\n### Formatted Output\n```\n📍 气象站A — 2025-05-12 12:00:00\n\n🌡️ 空气温度: 24.5 ℃\n💧 相对湿度: 58.3 %\n💨 风速: 3.2 m/s (东南)\n🌧️ 降雨量: 0.0 mm\n☀️ 太阳辐射: 856 W/m²\n```\n\n---\n\n## Example 5: 多设备对比\n\n### User Input\n```\n对比一下1号大棚和2号大棚的土壤湿度\n```\n\n### Agent Thinking\n1. 两个 alias 需要分别解析\n2. 时间: 无 → 默认\"现在\"（/latest）\n3. 参数: \"土壤湿度\" → moisture\n4. 需要并排比较并计算差异\n\n### Tool Calls\n```\nquery_device(alias=\"1号大棚\") → sn1 = \"00000000000001\"\nquery_device(alias=\"2号大棚\") → sn2 = \"00000000000002\"\n\nquery_data(sn=\"00000000000001\", time_expression=\"现在\", includeParameters=\"moisture\")\nquery_data(sn=\"00000000000002\", time_expression=\"现在\", includeParameters=\"moisture\")\n```\n\n### Formatted Output\n```\n📊 土壤湿度对比 — 实时数据\n\n| 深度  | 1号大棚 | 2号大棚 | 差异     │\n|-------|---------|---------|----------│\n| 10cm  | 23.4 %  │ 19.8 %  │ +3.6 % ↑ │\n| 20cm  | 24.1 %  │ 21.5 %  │ +2.6 % ↑ │\n| 30cm  | 25.6 %  │ 24.2 %  │ +1.4 % ↑ │\n| 40cm  | 27.2 %  │ 26.8 %  │ +0.4 % ↑ │\n\n💡 分析: 1号大棚各层湿度均高于2号大棚，10cm层差异最大（+3.6%）\n```\n\nArchive v1.1.0: 18 files, 51321 bytes\n\nFiles: CHANGELOG.md (6506b), CLAUDE.md (1214b), docs/analysis.md (4559b), docs/getting-started.md (3681b), docs/interaction.md (5399b), docs/platform-setup.md (7665b), examples/flows.md (3539b), examples/queries.md (5794b), examples/reports.md (5766b), PLATFORM-TEST.md (4637b), README.md (6423b), reference/api-doc.md (28329b), scripts/export_excel.py (9191b), scripts/insentek_cli.py (18934b), scripts/README.md (3446b), scripts/write_html.py (6398b), skill.md (7089b), _meta.json (137b)\n\nFile v1.1.0:skill.md\n\n---\nname: insentek-openapi\nversion: 1.1.0\ndescription: >\n  通过自然语言查询 insentek（东方智感）物联网设备数据。\n  支持土壤墒情仪、气象站、见厘液位计等多种设备类型的实时数据、\n  历史数据、趋势分析、跨设备对比与数据导出。\napi_base_url: http://openapi.ecois.info\nauthor: insentek-api-skills\nguardrails:\n  raw_data_output: PROHIBITED\n  dry_run_preview_rows: 5\n  max_chat_rows: 200\n  max_export_rows: 50000\n---\n\n# Insentek OpenAPI Skill\n\n> 轻量 Runtime Contract。完整交互规范见 `docs/interaction.md`，分析策略见 `docs/analysis.md`。\n> 兼容平台：OpenClaw、Hermes-Agent、Claude Code、ChatGPT\n\n---\n\n## 1. Routing\n\n用户意图 → 工具路由：\n\n| L1 意图 | L2 输出 | 调用 |\n|---------|---------|------|\n| 查询数据 | 对话展示 | `query_device` → `query_data` → 按输出格式回复 |\n| 查询数据 | 文件导出 | `query_device` → `export_*` → 返回文件路径 |\n| 生成报告 | 文件导出 | `query_device` → `query_data` → 分析 → `write_html` |\n| 对比设备 | 对话展示 | `query_device` (xN) → `query_data` (xN) → 对比表格 |\n| 对比设备 | 文件导出 | `query_device` (xN) → `query_data` (xN) → `export_excel` |\n\n**任何一层意图不明确时，MUST 向用户确认，不得假设。** 详见 `docs/interaction.md` Section 1。\n\n---\n\n## 2. Tools\n\n### authenticate\n\n用户首次提供 appid/secret 时调用，或缓存凭据失效时。\n\n```json\n{\n  \"appid\": { \"type\": \"string\", \"description\": \"E 生态应用 ID\" },\n  \"secret\": { \"type\": \"string\", \"description\": \"E 生态应用密钥\" }\n}\n```\n\n```bash\npython scripts/insentek_cli.py auth --appid ${appid} --secret ${secret}\n```\n\n成功后缓存 `appid`, `secret`, `token`, `expires_at` 到会话内存。同一会话不再询问。\n\n---\n\n### query_device\n\n查询设备信息：列表、详情、别名解析。\n\n```json\n{\n  \"page\": { \"type\": \"integer\", \"default\": 1 },\n  \"limit\": { \"\n\nArchive v1.0.2: 18 files, 408772 bytes\n\nFiles: assets/echarts.min.js (1034101b), CHANGELOG.md (3785b), CLAUDE.md (1214b), docs/api-reference.md (8702b), docs/getting-started.md (3662b), docs/platform-setup.md (4970b), examples/alerts.md (6005b), examples/queries.md (5719b), examples/reports.md (5697b), PLATFORM-TEST.md (4637b), README.md (6166b), reference/api-doc.md (28329b), scripts/export_excel.py (9191b), scripts/insentek_cli.py (18932b), scripts/README.md (3446b), scripts/write_html.py (6398b), skill.md (37343b), _meta.json (137b)\n\nArchive v1.0.1: 14 files, 408803 bytes\n\nFiles: assets/echarts.min.js (1034145b), docs/api-reference.md (8702b), docs/getting-started.md (3662b), docs/platform-setup.md (4970b), examples/alerts.md (6005b), examples/queries.md (5719b), examples/reports.md (5697b), reference/api-doc-full.txt (14408b), reference/api-document-latest.txt (33762b), scripts/export_excel.py (9191b), scripts/insentek_cli.py (44820b), scripts/README.md (3252b), skill.md (36440b), _meta.json (137b)\n\nArchive v1.0.0: 5 files, 28636 bytes\n\nFiles: scripts/export_excel.py (7826b), scripts/insentek_cli.py (42479b), scripts/README.md (3252b), skill.md (30587b), _meta.json (137b)","readmeExcerpt":"Skill: insentek-api-skill Owner: xddcode Summary: 通过自然语言查询 insentek（东方智感）物联网设备数据。 支持土壤墒情仪、气象站、见厘液位计等多种设备类型的实时数据、 历史数据、趋势分析、跨设备对比与数据导出。 Tags: latest:1.2.2 Version history: v1.2.2 | 2026-05-26T09:35:14.742Z | user v1.2.2 — Agent 调用规范与 HTTPS 修正 Agent 误用包名/命令、Python 路径不明确等问题；API 默认切换 HTTPS；新增 latest 子命令。 变更 - 统一 npx @insentek/openapi-skill 调用，修正引导文案中的错误包名 - ${PYTHON} 由 info --json 的 python.command 解析，不再硬编码 python - 默认 AP","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"v1.2.0 | 2026-05-25T09:33:41.213Z | user\n\n## What's Changed\r\n* feat: 持久化存储访问凭据，避免会话间重复输入 by @fre2d0m in https://github.com/insentek/insentek-api-skills/pull/6\r\n\r\n## New Contributors\r\n* @fre2d0m made their first contribution in https://github.com/insentek/insentek-api-skills/pull/6\r\n\r\n**Full Changelog**: https://github.com/insentek/insentek-api-skills/compare/v1.1.0...v1.2.0\n\nv1.1.0 | 2026-05-22T07:45:06.058Z | user\n\n1. skill.md 模块化重构\r\n    - 从 1100+ 行瘦身至 241 行（Runtime Contract 风格）\r\n    - 拆分出 docs/interaction.md（交互规范）和 docs/analysis.md（分析策略）\r\n    - 解决 Prompt Token 爆炸和 MUST 密度过高问题\r\n  2. 分析策略语气降级\r\n    - 安全/护栏规则保持 MUST\r\n    - 分析方法从 MUST 改为 SHOULD / RECOMMENDED / PREFER\r\n    - 提升 Agent 分析灵活性和创造力\r\n  3. 数据可用性校验\r\n    - query_data 返回后自动检查实际数据范围 vs 请求范围\r\n    - 覆盖不足 50% 或少于 7 天时，必须向用户确认后才生成报告\r\n    - 防止\"请求近3个月但设备只有13天数据\"的误导性报告\r\n  4. CSV 导出修复\r\n    - 修复长数字 SN 在 Excel 中显示为科学计数法的问题\r\n    - SN 字段加前导制表符强制文本格式\r\n  5. API 文档统一\r\n    - 删除 docs/api-reference.md\r\n    - 统一使用 reference/api-doc.md 作为权威源\n\nv1.0.2 | 2026-05-21T07:50:57.649Z | user\n\n- Removed deprecated `report` / `chart` / `export --format html` from `scripts/insentek_cli.py`\r\n  - Deleted `generate_report()`, `generate_chart()`, `get_device_info()`, `extract_param_names()` (~480 lines)\r\n  - HTML reports are now fully Agent-generated; no hard-coded templates\r\n  - Updated docstring and argparse to reflect only csv/json export\r\n\r\n- Updated `skill.md`\r\n  - Replaced Section 6.4 `generate_report (DEPRECATED)` with 6.4 `write_html`\r\n  - Added `write_html.py` to environment check items (non-critical)\r\n  - Changed API doc reference from active guidance to fallback note in Notes\r\n  - Updated `--dry-run` note to remove `report` and `chart`\r\n\r\n- Updated `.planning/STATE.md`\r\n  - Added `write_html.py` to Utility Scripts list\r\n  - Removed HTML export from `insentek_cli.py` description\n\nv1.0.1 | 2026-05-21T06:04:04.070Z | user\n\n- --dry-run preview mode (scripts/insentek_cli.py)\n  - data, export (csv/json/html), report, chart subcommands all suppo"},{"language":"text","snippet":"> npm 包名为 `@insentek/openapi-skill`（已发布到 npm registry）。`insentek-api-skill` 是它的可执行别名，**仅在该包已被安装时**可用。**所有 `npx` 调用都应使用 scoped 包名** `@insentek/openapi-skill`，否则未安装的用户机器会得到 \"npm ERR! 404\"。\n\n### 命令分工（MUST）\n\n| 用途 | 工具 | 示例 |\n|------|------|------|\n| 安装 / 更新 skill | `npx @insentek/openapi-skill` | `install -r openclaw -s workspace -y` |\n| 配置 / 清除凭据 | `npx @insentek/openapi-skill login/logout` | `npx @insentek/openapi-skill login` |\n| 查连接状态 | `npx @insentek/openapi-skill auth status` | — |\n| 查安装路径 / 脚本位置 | `npx @insentek/openapi-skill info/status/doctor --json` | 见下方「脚本路径解析」 |\n| **查询 API** | `python3 <SKILL_ROOT>/scripts/insentek_cli.py` | `python3 .../insentek_cli.py devices` |\n\n### 脚本路径解析（MUST，API 调用前）\n\nAgent 工作目录通常**不是** skill 安装目录。**禁止**使用相对路径 `python3 scripts/insentek_cli.py ...`。\n\n**首次 API 调用前**，或脚本路径未知 / 返回「文件找不到」时，**必须先**查实际安装位置。`info --json` 会列出所有 runtime × scope 的解析结果及 `installed` 标记，无需提前知道用户是哪种安装："},{"language":"text","snippet":"从输出中遍历 `runtimes[].scopes[]`，挑选第一个 `installed: true` 的条目，将其 `installDir` 作为 `${SKILL_ROOT}`，将 `scripts.cli` / `scripts.exportExcel` / `scripts.writeHtml` 作为脚本绝对路径，并将 `python.command`（如 `python3` / `py` / `python`）作为 `${PYTHON}`。解析后在**本会话内缓存**，后续 API 调用复用，**不要**重复猜测路径。\n\n如果用户已经明确告诉过你 runtime / scope（例如刚刚 `install -r openclaw -s workspace -y`），也可以用 `status --json` 精确查询："},{"language":"text","snippet":"OpenClaw workspace 常见路径（仅供参考，**以 info/status 返回为准**）：\n`~/.openclaw/workspace/skills/insentek-openapi`\n\n**禁止（MUST NOT）：**\n- `python3 scripts/insentek_cli.py ...` — 相对路径在 OpenClaw 等环境下会失败\n- `npx insentek-api-skill ...` — npm registry 上没有这个包名，对未安装本包的新用户会 404\n- `npx @insentek/openapi-skill devices` — `devices` 不是顶层命令，会被 commander 当成 `install` 的子命令而触发安装流程\n- 文件找不到时乱试其它命令 — **应重新 `info --json`**\n\n用户说「配置好了，继续吧」→ 从**中断前的意图**继续；若已有 `${SKILL_ROOT}` 直接调 API，**不要**重新 login。\n\n若工具返回 `authentication_required` 或 HTTP 401/403，**STOP** 并 **原样** 向用户展示以下固定文案（不得改写、不得追加索要 secret）："},{"language":"text","snippet":"---\n\n### query_device\n\n查询设备信息：列表、详情、别名解析。"},{"language":"text","snippet":"> `${PYTHON}` 在 macOS/Linux 默认为 `python3`，Windows 默认为 `python`（亦可为 `py`）；以 `info --json` 输出的 `python.command` 为准。**禁止**使用裸 `python`——在 macOS 系统默认配置、新版 Ubuntu/Fedora 等环境下 `python` 命令不存在或指向 Python 2，会直接失败。\n\n**注意：** `--token` 变为可选。若未提供且已配置持久化凭据，脚本自动获取。\n\n**行为：** alias → 模糊匹配 → 多匹配时反问用户 → 单匹配时缓存 alias→sn 映射。\n\n---\n\n### query_data\n\n查询设备历史数据或实时数据。"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: insentek-openapi\nversion: 1.2.2\ndescription: >\n  通过自然语言查询 insentek（东方智感）物联网设备数据。\n  支持土壤墒情仪、气象站、见厘液位计等多种设备类型的实时数据、\n  历史数据、趋势分析、跨设备对比与数据导出。\napi_base_url: https://openapi.ecois.info\nauthor: insentek-api-skills\nguardrails:\n  raw_data_output: PROHIBITED\n  dry_run_preview_rows: 5\n  max_chat_rows: 200\n  max_export_rows: 50000\n---\n\n<!--\n  Note: `api_base_url` above is informational only; it is not consumed by\n  any script. To override at runtime, set the INSENTEK_API_BASE environment\n  variable before invoking scripts/insentek_cli.py.\n-->\n\n\n# Insentek OpenAPI Skill\n\n> 轻量 Runtime Contract。完整交互规范见 `docs/interaction.md`，分析策略见 `docs/analysis.md`。\n> 兼容平台：OpenClaw、Hermes-Agent、Claude Code、ChatGPT\n\n---\n\n## 1. Routing\n\n用户意图 → 工具路由：\n\n| L1 意图 | L2 输出 | 调用 |\n|---------|---------|------|\n| 查询数据 | 对话展示 | `query_device` → `query_data` → 按输出格式回复 |\n| 查询数据 | 文件导出 | `query_device` → `export_*` → 返回文件路径 |\n| 生成报告 | 文件导出 | `query_device` → `query_data` → 分析 → `write_html` |\n| 对比设备 | 对话展示 | `query_device` (xN) → `query_data` (xN) → 对比表格 |\n| 对比设备 | 文件导出 | `query_device` (xN) → `query_data` (xN) → `export_excel` |\n\n**任何一层意图不明确时，MUST 向用户确认，不得假设。** 详见 `docs/interaction.md` Section 1。\n\n---\n\n## 2. Tools\n\n**认证约束（MUST）：** Agent **禁止**向用户索要 `appid` 或 `secret`，也 **禁止**在对话中接收、存储或回显这些凭据。凭据仅通过 CLI 在本地配置：\n\n```bash\nnpx @insentek/openapi-skill login       # 配置（加密保存）\nnpx @insentek/openapi-skill logout      # 清除\nnpx @insentek/openapi-skill auth status # 查看连接状态\n```\n\n> npm 包名为 `@insentek/openapi-skill`（已发布到 npm registry）。`insentek-api-skill` 是它的可执行别名，**仅在该包已被安装时**可用。**所有 `npx` 调用都应使用 scoped 包名** `@insentek/openapi-skill`，否则未安装的用户机器会得到 \"npm ERR! 404\"。\n\n### 命令分工（MUST）\n\n| 用途 | 工具 | 示例 |\n|------|------|------|\n| 安装 / 更新 skill | `npx @insentek/openapi-skill` | `install -r openclaw -s workspace -y` |\n| 配置 / 清除凭据 | `npx @insentek/openapi-skill login/logout` | `npx @insentek/openapi-skill login` |\n| 查连接状态 | `npx @insentek/openapi-skill auth status` | — |\n| 查安装路径 / 脚本位置 | `npx @insentek/openapi-skill info/status/doctor --json` | 见下方「脚本路径解析」 |\n| **查询 API** | `python3 <SKILL_ROOT>/scripts/insentek_cli.py` | `python3 .../insentek_cli.py devices` |\n\n### 脚本路径解析（MUST，API 调用前）\n\nAgent 工作目录通常**不是** skill 安装目录。**禁止**使用相对路径 `python3 scripts/insentek_cli.py ...`。\n\n**首次 API 调用前**，或脚本路径未知 / 返回「文件找不到」时，**必须先**查实际安装位置。`info --json` 会列出所有 runtime × scope 的解析结果及 `installed` 标记，无需提前知道用户是哪种安装：\n\n```bash\nnpx @insentek/openapi-skill info --json\n```\n\n从输出中遍历 `runtimes[].scopes[]`，挑选第一个 `installed: true` 的条目，将其 `installDir` 作为 `${SKILL_ROOT}`，将 `scripts.cli` / `scripts.exportExcel` / `scripts.writeHtml` 作为脚本绝对路径，并将 `python.command`（如 `python3` / `py` / `python`）作为 `${PYTHON}`。解析后在**本会话内缓存**，后续 API 调用复用，**不要**重复猜测路径。\n\n如果用户已经明确告诉过你 runtime / scope（例如刚刚 `install -r openclaw -s workspace -y`），也可以用 `status --json` 精确查询：\n\n```bash\nnpx @insentek/openapi-skill status -r openclaw -s workspace --json\n# 或 -r claude -s global / -s project，按用户场景选择\n```\n\nOpenClaw workspace 常见路径（仅供参考，**以 info/status 返回为准**）：\n`~/.openclaw/workspace/skill"},{"path":"packages/insentek-skill-cli/README.md","content":"# @insentek/openapi-skill\n\nBootstrap the **insentek-openapi** skill for **OpenClaw** and **Claude Code**.\n\n| 类型 | 名称 |\n|------|------|\n| npm package | `@insentek/openapi-skill` |\n| skill id | `insentek-openapi` |\n| 安装目录 | `insentek-openapi` |\n| CLI 命令 | `insentek-api-skill` |\n\n安装路径由 CLI **按 runtime + scope 动态解析**。用 `info` / `doctor` 查看本机实际路径。\n\n## Quick Start\n\n```bash\nnpx @insentek/openapi-skill\n```\n\n## OpenClaw 用户：ClawHub 安装（独立方式）\n\nOpenClaw 用户也可通过 ClawHub 单独安装，与本 CLI 无关：\n\n```bash\nclawhub skill install insentek-api-skill\nclawhub skill remove insentek-api-skill\n```\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `install` | 安装 skill（默认命令，可交互选择 runtime） |\n| `login` | 配置 Insentek API 凭据（加密本地保存） |\n| `logout` | 清除已保存的凭据 |\n| `auth status` | 查看凭据连接状态 |\n| `update` | 更新已安装 skill 到当前包版本 |\n| `uninstall` | 卸载 |\n| `status` | 查看安装状态 |\n| `doctor` | 诊断路径、manifest、脚本与环境 |\n| `info` | 查看 package / skill / 动态解析路径 |\n\n## Options\n\n| Option | Description |\n|--------|-------------|\n| `-r, --runtime` | `claude`, `openclaw`, `all` |\n| `-s, --scope` | 见下方 Scope 说明 |\n| `-f, --force` | 覆盖已有安装 |\n| `-y, --yes` | 非交互（需配合 `-r`） |\n| `--json` | 输出 JSON（`install`/`update`/`uninstall` 需配合 `-y`） |\n\n### Scope 说明\n\n| Runtime | 支持的 scope |\n|---------|-------------|\n| Claude Code | `global`（默认）, `project` |\n| OpenClaw | `global`, `project`, `workspace` |\n\n`workspace` 仅 OpenClaw 支持；Claude Code 没有 workspace 概念。OpenClaw `workspace` 安装路径为 `~/.openclaw/workspace/skills`（Windows: `%USERPROFILE%\\.openclaw\\workspace\\skills`）。\n\n## Examples\n\n```bash\n# 交互式安装\nnpx @insentek/openapi-skill\n\n# 安装到 Claude Code（global）\nnpx @insentek/openapi-skill install -r claude -s global -y\n\n# 安装到 OpenClaw workspace\nnpx @insentek/openapi-skill install -r openclaw -s workspace -y\n\n# 查安装路径与脚本位置（Agent 应用此解析 SKILL_ROOT）\nnpx @insentek/openapi-skill status -r openclaw -s workspace --json\n\n# 凭据 / 诊断\nnpx @insentek/openapi-skill update -r claude -y\nnpx @insentek/openapi-skill doctor\nnpx @insentek/openapi-skill login\nnpx @insentek/openapi-skill logout\nnpx @insentek/openapi-skill auth status\nnpx @insentek/openapi-skill info\n\n# 脚本 / CI 使用 JSON 输出\nnpx @insentek/openapi-skill status -r claude --json\nnpx @insentek/openapi-skill install -r claude -s global -y --json\nnpx @insentek/openapi-skill doctor --json\n```\n\n## Development / 本地测试\n\n包尚未发布到 npm 时，`npx @insentek/openapi-skill` 会失败。本地请用下面任一方式：\n\n```powershell\ncd packages/insentek-skill-cli\nnpm install\nnpm run sync-assets\nnpm test\n```\n\n**方式一：直接跑（最简单）**\n\n```powershell\nnode bin/insentek-api-skill.js info\nnode bin/insentek-api-skill.js\nnode bin/insentek-api-skill.js install -r claude -s global -y\n```\n\n**方式二：模拟 npx（在 CLI 目录下）**\n\n```powershell\nnpx . info\nnpx .\nnpx . install -r claude -s global -y\n```\n\n**方式三：全局 link 后按发布命令测**\n\n```powershell\nnpm link\nnpx @insentek/openapi-skill info\ninsentek-api-skill doctor\n```\n\n**方式四：模拟正式发布**\n\n```powershell\nnpm run sync-assets\nnpm pack\nnpm install -g .\\insentek-openapi-skill-1.2.2.tgz\ninsentek-api-skill info\n```\n\n修改 `SKILL.md` / `scripts/` 后需"},{"path":"README.md","content":"# Insentek OpenAPI Skill\n\n> 让终端用户用自然语言轻松查询 insentek（东方智感）物联网设备数据。\n\n---\n\n## 简介\n\n本项目基于 insentek OpenAPI v3，产出一份通用 `skill.md` 技能文件及配套文档与示例。终端用户可在 **OpenClaw、Hermes-Agent、Claude Code、ChatGPT** 等 Agent 平台上直接对话使用，通过自然语言调用 API 完成设备数据查询、报告生成与实时分析。\n\n**支持的设备类型：**\n- 🌱 **Z** — 土壤墒情仪（土壤温度、水分、电导率）\n- 🌤️ **T** — 气象站（空气温度、湿度、风速、降雨量、PM2.5 等）\n- 📏 **J** — 见厘液位计（激光液位、电池电压）\n\n---\n\n## 快速开始\n\n### 前置依赖\n\n| 依赖 | 版本 | 用途 |\n|------|------|------|\n| Node.js | ≥ 18 | 运行 `npx @insentek/openapi-skill` CLI |\n| Python | ≥ 3.10 | 运行 `scripts/insentek_cli.py` 等脚本（脚本使用了 PEP 604 联合类型语法） |\n| openpyxl（可选） | 任意 | 仅当需要 Excel 导出时 |\n\n> macOS / Linux 通常应使用 `python3` 命令调用脚本，不要使用裸 `python`（在新版 macOS 与 Ubuntu/Fedora 上不存在或指向 Python 2）。CLI 的 `info --json` 会输出 `python.command`，Agent 必须以该值作为脚本调用前缀。\n\n### 1. 获取认证信息\n\n登录 [E 生态](https://cloud.ecois.info)，在「应用管理」中创建应用，获取 `appid` 和 `secret`。\n\n### 2. 安装 Skill\n\n**一键安装（推荐）：**\n\n```bash\nnpx @insentek/openapi-skill\n```\n\n| 类型 | 名称 |\n|------|------|\n| npm package | `@insentek/openapi-skill` |\n| skill id | `insentek-openapi` |\n| 安装目录 | `insentek-openapi` |\n\nCLI 会引导选择 **runtime**（OpenClaw / Claude Code），支持 **scope**（`global` / `project` / `workspace`），并动态解析本机安装路径。\n\n```bash\nnpx @insentek/openapi-skill install -r claude -s global -y\nnpx @insentek/openapi-skill update -r claude -y\nnpx @insentek/openapi-skill doctor\nnpx @insentek/openapi-skill info\n```\n\nOpenClaw 用户也可通过 ClawHub 单独安装（与本 CLI 无关）：\n\n```bash\nclawhub skill install insentek-api-skill\n```\n\n| 命令 | 说明 |\n|------|------|\n| `install` | 安装 skill |\n| `update` | 更新到当前包版本 |\n| `status` / `doctor` | 查看状态 / 诊断 |\n| `uninstall` | 卸载 |\n\n> CLI 源码见 [`packages/insentek-skill-cli/`](packages/insentek-skill-cli/)。路径因 runtime/scope/OS 而异，请用 `info` / `doctor` 查看本机实际位置。\n\n### 命名约定\n\n仓库中涉及三套名字，用途不同，**不要混用**：\n\n| 维度 | 取值 | 用途 |\n|------|------|------|\n| Skill ID（`skill.json` / SKILL.md frontmatter） | `insentek-openapi` | 安装目录名、Agent 内部标识 |\n| ClawHub slug | `insentek-api-skill` | `clawhub skill install <slug>` 时使用 |\n| npm 包名 | `@insentek/openapi-skill` | **所有 `npx` 调用必须使用此名**（registry 上没有 `insentek-api-skill`） |\n| CLI 二进制名 | `insentek-api-skill` | 仅在 `@insentek/openapi-skill` 已安装时作为可执行别名 |\n\n### 3. 开始对话\n\n```\nUser: 我的 appid 是 xxx，secret 是 yyy，查看所有设备\n```\n\n更多用法见 [`docs/getting-started.md`](docs/getting-started.md)。\n\n---\n\n## 项目结构\n\n```\n.\n├── SKILL.md                     # 核心技能文件 (Runtime Contract)\n├── skill.json                   # Skill manifest (id / version / runtime)\n├── docs/\n│   ├── getting-started.md       # 快速开始指南\n│   ├── platform-setup.md        # 各平台配置指南\n│   ├── interaction.md           # 交互规范 (意图/时间/输出格式)\n│   └── analysis.md              # 分析策略 (报告/告警/行业参数)\n├── reference/\n│   └── api-doc.md               # 完整 API 文档 (OpenAPI v3.1.9)\n├── examples/\n│   ├── queries.md               # 查询类对话示例\n│   ├── reports.md               # 报告生成示例\n│   └── flows.md                 # 核心交互流程示例\n├── scripts/                     # 参考实现脚本\n│   ├── insentek_cli.py          # 统一 CLI（认证/查询/实时/导出）\n│   ├── credential_store.py      # 加密凭据读写\n│   ├── export_excel.py  "},{"path":"scripts/README.md","content":"# Insentek OpenAPI Scripts\n\n本目录包含 Insentek OpenAPI 的参考实现脚本。Agent 通过调用这些脚本完成 API 交互、数据导出和报告生成，而非直接使用 `curl` 命令。\n\n## 设计原则\n\n1. **统一入口**: `insentek_cli.py` 封装所有 API 调用，Agent 只需学习一套参数风格\n2. **边界内置**: 脚本内部实现时间范围限制、数据量检查，Agent 无需重复实现\n3. **结构化输出**: 所有脚本输出 JSON 到 stdout，便于 Agent 解析和决策\n4. **零配置运行**: 仅依赖 Python 标准库（Excel 导出除外）\n\n## 脚本列表\n\n| 脚本 | 功能 | 依赖 |\n|------|------|------|\n| `insentek_cli.py` | 统一 CLI：设备查询、实时/历史数据查询、CSV/JSON 导出 | Python 3.10+ |\n| `credential_store.py` | 凭据加密读写（与 CLI login 兼容） | Python 3.10+, cryptography（读取加密凭据时） |\n| `write_html.py` | HTML 文件写入：将 AI 生成的 HTML 内容安全落盘 | Python 3.10+ |\n| `export_excel.py` | Excel 导出（多 sheet：原始数据 + 统计摘要） | Python 3.10+, openpyxl |\n\n> 脚本使用了 PEP 604 联合类型（`int | None`），需要 Python 3.10 及以上。\n\n## 使用示例\n\n### 环境检查（首次使用前必做）\n\n> Agent 应使用 `python3`（macOS/Linux）或 `python` / `py`（Windows，以 `npx @insentek/openapi-skill info --json` 的 `python.command` 为准）调用脚本。下面示例统一写为 `python3`。\n\n```bash\npython3 insentek_cli.py check\n```\n\n输出示例：\n```json\n{\n  \"success\": true,\n  \"all_checks_passed\": true,\n  \"checks\": {\n    \"python\": {\"ok\": true, \"version\": \"3.11.0\", \"executable\": \"/usr/bin/python3\", \"message\": \"Python 3.11.0 满足要求 (>=3.10)\"},\n    \"scripts_cli\": {\"ok\": true, \"path\": \"...\", \"message\": \"核心脚本 insentek_cli.py 已找到\"},\n    \"scripts_excel\": {\"ok\": true, \"path\": \"...\", \"message\": \"Excel 脚本 export_excel.py 已找到\"},\n    \"scripts_write_html\": {\"ok\": true, \"path\": \"...\", \"message\": \"HTML 写入脚本 write_html.py 已找到\"},\n    \"openpyxl\": {\"ok\": true, \"version\": \"3.1.2\", \"message\": \"openpyxl 3.1.2 已安装，Excel 导出可用\"},\n    \"curl\": {\"ok\": true, \"message\": \"curl 可用，可作为脚本不可用时的 fallback\"},\n    \"api_reachable\": {\"ok\": true, \"status\": 400, \"message\": \"API 服务可访问（HTTP 400，未提供认证参数）\"}\n  },\n  \"summary\": {\n    \"critical\": \"通过\",\n    \"optional\": \"全部通过\",\n    \"message\": \"环境检查通过，所有功能可用。\"\n  }\n}\n```\n\n### 认证\n\n凭据通过 CLI 本地配置，**不要在对话中提供 secret**：\n\n```bash\nnpx @insentek/openapi-skill login\nnpx @insentek/openapi-skill logout\nnpx @insentek/openapi-skill auth status\n```\n\n脚本会自动从 `~/.config/insentek/credentials.json` 读取加密凭据，`--token` 参数可选。\n\n### 查询设备列表\n```bash\npython3 insentek_cli.py devices --page 1 --limit 20\n```\n\n### 查询数据（含边界检查）\n```bash\npython3 insentek_cli.py data --sn 00000000000000 --range 20250101,20250131\n```\n\n### 实时数据\n```bash\npython3 insentek_cli.py latest --sn 00000000000000\n```\n\n### 导出 CSV\n```bash\npython3 insentek_cli.py export --sn 00000000000000 --range 20250101,20250131 --format csv --output data.csv\n```\n\n### 导出 Excel\n```bash\npython3 export_excel.py --sn 00000000000000 --range 20250101,20250131 --output data.xlsx\n```\n\n### 写入 HTML 报告（AI 动态生成内容后落盘）\n```bash\n# 推荐：先把 HTML 写到临时文件，再传 --input-file，避免 shell 吞掉换行/引号\npython3 write_html.py --input-file /tmp/report.html --output report.html\n```\n\n## 输出格式\n\n所有脚本成功时输出：\n```json\n{\n  \"success\": true,\n  \"total\": 1000,\n  \"file\": \"/path/to/file.csv\",\n  \"message\": \"成功导出 1000 条数据到 data.csv\"\n}\n```\n\n失败时输出：\n```json\n{\n  \"success\": false,\n  \"error\": \"单次查询最多支持 1 年范围...\"\n}\n```\n\n## 边界限制\n\n| 限制项 | 值 | 说明 |\n|--------|-----|------|\n| 单次最大跨度 | 365 天 | 超过则拒绝并提示拆分 |"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7dcqpad4aeh2nt5shjf3aerd875anm\",\n  \"slug\": \"insentek-api-skill\",\n  \"version\": \"1.2.2\",\n  \"publishedAt\": 1779788114742\n}"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1564,"uniquenessScore":38,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T17:16:29.334Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T17:16:29.334Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T20:56:07.273Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}