{"id":"cba0f19a-6898-47a5-9b08-985c9a7b0bcf","entityType":"agent","slug":"clawhub-wahsonleung-smartbi-cli","name":"SmartBI CLI","canonicalUrl":"https://www.xpersona.co/agent/clawhub-wahsonleung-smartbi-cli","canonicalPath":"/agent/clawhub-wahsonleung-smartbi-cli","generatedAt":"2026-10-10T21:43:03.231Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-10T17:15:05.623Z","emptyReason":null},"description":"Query model/report data and operate SmartBI APIs Skill: SmartBI CLI Owner: wahsonleung Summary: Query model/report data and operate SmartBI APIs Tags: latest:2.1.0 Version history: v2.1.0 | 2026-09-22T10:33:13.891Z | user **Major update with expanded scenario support and improved agent integration.** - Data query and insight scenarios now have dedicated guides and workflow overrides (scenarios/data-query.md), supporting direct, multi-step query/insight calls. - Add","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.3K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17903ewqvyed96apj0ghpecr987c1r3:smartbi-cli","sourceUrl":"https://clawhub.ai/wahsonleung/smartbi-cli","homepage":"https://clawhub.ai/wahsonleung/skills/smartbi-cli","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/wahsonleung/smartbi-cli","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/wahsonleung/skills/smartbi-cli","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":62,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Query model/report data and operate SmartBI APIs Skill: SmartBI CLI Owner: wahsonleung Summary: Query model/report data and operate SmartBI APIs Tags: latest:2."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T17:15:05.623Z","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-10T17:15:05.623Z","emptyReason":null},"stars":null,"forks":null,"downloads":1323,"packageName":null,"latestVersion":"2.1.0","tractionLabel":"1.3K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T17:15:05.623Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T17:15:05.623Z","lastCrawledAt":"2026-10-10T17:15:05.623Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T17:15:05.623Z","lastVerifiedAt":null,"highlights":[{"version":"2.1.0","createdAt":"2026-09-22T10:33:13.891Z","changelog":"**Major update with expanded scenario support and improved agent integration.** - Data query and insight scenarios now have dedicated guides and workflow overrides (`scenarios/data-query.md`), supporting direct, multi-step query/insight calls. - Added comprehensive reference docs for agents, custom tools, artifact handling, agent workflows, data/metric model queries, report queries, troubleshooting, and more. - Improved environment and credential selection: new logic for experience center entry, explicit address/user flow, non-intrusive profile management. - More robust request body file handling (system temp directory, Windows path fallback, enforced clean-up/clarity) and safer credential use (supports environment variable and system keyring with secure handling). - Enhanced agent workflow, agent export/import, and toolkit extension guidance via new reference docs and scripts. - Removed unused or outdated documentation (`skill-card.md`) for better maintainability.","fileCount":30,"zipByteSize":115368},{"version":"2.0.0","createdAt":"2026-09-10T02:23:36.564Z","changelog":"Version 2.0.0 - CLI最低版本要求提升到2.0.0，所有流程以新版能力为基准。 - CLI安装与首次配置流程更新，所有profile相关操作、配置文件管理、令牌存储等完全兼容新版`init`参数和profile命令族。 - 新增对令牌多种存储方式（环境变量、系统钥匙串、标准明文配置）的兼容与分支说明。 - `skill-card.md`已移除，无影响主流程。 - 其余策略流程、参数构造、场景路由保持不变，细节合入`SKILL.md`主文件。","fileCount":15,"zipByteSize":51279},{"version":"1.3.0","createdAt":"2026-08-20T07:53:46.316Z","changelog":"Smartbi CLI 1.3.0 introduces multi-environment (profile) management and updates configuration flow. - 增加多环境 profile 配置与选择机制，所有操作显式带 `--profile`，支持 config.yaml 多 profile 并处理版本兼容 - 全局约定与首次配置流程调整，新增和更换环境按 references/profiles.md 规范执行 - 安装检测增加 `--profile` 参数支持校验 - references/profiles.md 文档新增，分流 skill-card.md 说明 - 其他相关描述和流程同步支持 profile 功能","fileCount":15,"zipByteSize":50100},{"version":"1.2.0","createdAt":"2026-06-04T07:49:12.543Z","changelog":"**Smartbi-cli 1.2.0 introduces scenario routing, explicit business coverage, improved documentation paths, and modular reference files.** - Added scenario routing: user queries now match defined business scenarios first (e.g., schedule task, push message) before entering the general API call workflow. - Expanded and clarified business coverage in the skill overview, reflecting detailed Smartbi product domains (AI analysis, data modeling, permissions, etc.). - Introduced modular documentation: new scenario and reference files (`scenarios/*`, `references/*`), plus a script utility for safe payload injection. - Updated config and CLI setup logic for stricter npm-only installation, version gating, and step-by-step guided config initialization. - Removed legacy inline skill card; all documentation is now structured and discoverable. - Output, error handling, and parameter construction policies are now explicitly sequenced and contractually defined.","fileCount":14,"zipByteSize":46606},{"version":"1.1.0","createdAt":"2026-05-29T02:06:38.061Z","changelog":"# smartbi-cli v1.1.0 Changelog - Removed the `skill-card.md` file. - Updated installation and configuration instructions: now uses `smartbi init --tmpl` for placeholder templates, with background config file creation (user does not see intermediate steps). - Tightened configuration checks: `serverType` must be exactly `sdk-server` or `smartbi` (no variants allowed). - Refined Phase 1 workflow: only uses `search` for candidate disambiguation (not for all Top-N). - Clarified Smartbi documentation loading: `smartbi doc <path> --agent` only affects error output, standard output is the raw document. - Improved step-by-step user prompting for missing configuration items.","fileCount":8,"zipByteSize":21997},{"version":"1.0.1","createdAt":"2026-05-27T01:34:57.452Z","changelog":"- Removed the file: `skill-card.md` - SKILL.md: Clarified that `serverType` (sdk-server or Smartbi) is a required config, and specified the server address format examples for each type. - SKILL.md: Updated pre-execution checks to explicitly prompt for server type and accept both sdk-server and Smartbi addresses/configuration. - No behavioral changes to workflows or phases; documentation and config checks are now more precise and explicit.","fileCount":8,"zipByteSize":23869},{"version":"1.0.0","createdAt":"2026-05-26T02:31:06.689Z","changelog":"smartbi-cli v1.0.0 - Initial public release: triggers and executes Smartbi BI operations (training, analytics, statistics, LLM queries, chained workflows) by mapping user intent to unique operationKey via the smartbi CLI. - Enforces strict installation and configuration requirements: only allows global npm install; requires standard init flow and verified config. - Includes a phased workflow: candidate discovery (list/search), detailed describe, doc-led parameter construction, call execution, and error diagnosis. - Prioritizes business documentation for parameter construction, falling back to schema only if documents are unavailable. - Built-in pre-checks: immediately halts and prompts user if CLI is missing or minimal connection/config/auth requirements are unmet. - Supports recursive loading of referenced business docs and robust handling of chained dependencies before each call.","fileCount":8,"zipByteSize":23793}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17903ewqvyed96apj0ghpecr987c1r3:smartbi-cli","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"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-wahsonleung-smartbi-cli/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wahsonleung-smartbi-cli/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wahsonleung-smartbi-cli/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-wahsonleung-smartbi-cli/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-wahsonleung-smartbi-cli/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-wahsonleung-smartbi-cli/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-10T21:43:03.227Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wahsonleung-smartbi-cli/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wahsonleung-smartbi-cli/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wahsonleung-smartbi-cli/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wahsonleung-smartbi-cli/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":"high","updatedAt":"2026-10-10T17:15:05.623Z","emptyReason":null},"readme":"Skill: SmartBI CLI\n\nOwner: wahsonleung\n\nSummary: Query model/report data and operate SmartBI APIs\n\nTags: latest:2.1.0\n\nVersion history:\n\nv2.1.0 | 2026-09-22T10:33:13.891Z | user\n\n**Major update with expanded scenario support and improved agent integration.**\n\n- Data query and insight scenarios now have dedicated guides and workflow overrides (`scenarios/data-query.md`), supporting direct, multi-step query/insight calls.\n- Added comprehensive reference docs for agents, custom tools, artifact handling, agent workflows, data/metric model queries, report queries, troubleshooting, and more.\n- Improved environment and credential selection: new logic for experience center entry, explicit address/user flow, non-intrusive profile management.\n- More robust request body file handling (system temp directory, Windows path fallback, enforced clean-up/clarity) and safer credential use (supports environment variable and system keyring with secure handling).\n- Enhanced agent workflow, agent export/import, and toolkit extension guidance via new reference docs and scripts.\n- Removed unused or outdated documentation (`skill-card.md`) for better maintainability.\n\nv2.0.0 | 2026-09-10T02:23:36.564Z | user\n\nVersion 2.0.0\n\n- CLI最低版本要求提升到2.0.0，所有流程以新版能力为基准。\n- CLI安装与首次配置流程更新，所有profile相关操作、配置文件管理、令牌存储等完全兼容新版`init`参数和profile命令族。\n- 新增对令牌多种存储方式（环境变量、系统钥匙串、标准明文配置）的兼容与分支说明。\n- `skill-card.md`已移除，无影响主流程。\n- 其余策略流程、参数构造、场景路由保持不变，细节合入`SKILL.md`主文件。\n\nv1.3.0 | 2026-08-20T07:53:46.316Z | user\n\nSmartbi CLI 1.3.0 introduces multi-environment (profile) management and updates configuration flow.\n\n- 增加多环境 profile 配置与选择机制，所有操作显式带 `--profile`，支持 config.yaml 多 profile 并处理版本兼容\n- 全局约定与首次配置流程调整，新增和更换环境按 references/profiles.md 规范执行\n- 安装检测增加 `--profile` 参数支持校验\n- references/profiles.md 文档新增，分流 skill-card.md 说明\n- 其他相关描述和流程同步支持 profile 功能\n\nv1.2.0 | 2026-06-04T07:49:12.543Z | user\n\n**Smartbi-cli 1.2.0 introduces scenario routing, explicit business coverage, improved documentation paths, and modular reference files.**\n\n- Added scenario routing: user queries now match defined business scenarios first (e.g., schedule task, push message) before entering the general API call workflow.\n- Expanded and clarified business coverage in the skill overview, reflecting detailed Smartbi product domains (AI analysis, data modeling, permissions, etc.).\n- Introduced modular documentation: new scenario and reference files (`scenarios/*`, `references/*`), plus a script utility for safe payload injection.\n- Updated config and CLI setup logic for stricter npm-only installation, version gating, and step-by-step guided config initialization.\n- Removed legacy inline skill card; all documentation is now structured and discoverable.\n- Output, error handling, and parameter construction policies are now explicitly sequenced and contractually defined.\n\nv1.1.0 | 2026-05-29T02:06:38.061Z | user\n\n# smartbi-cli v1.1.0 Changelog\n\n- Removed the `skill-card.md` file.\n- Updated installation and configuration instructions: now uses `smartbi init --tmpl` for placeholder templates, with background config file creation (user does not see intermediate steps).\n- Tightened configuration checks: `serverType` must be exactly `sdk-server` or `smartbi` (no variants allowed).\n- Refined Phase 1 workflow: only uses `search` for candidate disambiguation (not for all Top-N).\n- Clarified Smartbi documentation loading: `smartbi doc <path> --agent` only affects error output, standard output is the raw document.\n- Improved step-by-step user prompting for missing configuration items.\n\nv1.0.1 | 2026-05-27T01:34:57.452Z | user\n\n- Removed the file: `skill-card.md`\n- SKILL.md: Clarified that `serverType` (sdk-server or Smartbi) is a required config, and specified the server address format examples for each type.\n- SKILL.md: Updated pre-execution checks to explicitly prompt for server type and accept both sdk-server and Smartbi addresses/configuration.\n- No behavioral changes to workflows or phases; documentation and config checks are now more precise and explicit.\n\nv1.0.0 | 2026-05-26T02:31:06.689Z | user\n\nsmartbi-cli v1.0.0\n\n- Initial public release: triggers and executes Smartbi BI operations (training, analytics, statistics, LLM queries, chained workflows) by mapping user intent to unique operationKey via the smartbi CLI.\n- Enforces strict installation and configuration requirements: only allows global npm install; requires standard init flow and verified config.\n- Includes a phased workflow: candidate discovery (list/search), detailed describe, doc-led parameter construction, call execution, and error diagnosis.\n- Prioritizes business documentation for parameter construction, falling back to schema only if documents are unavailable.\n- Built-in pre-checks: immediately halts and prompts user if CLI is missing or minimal connection/config/auth requirements are unmet.\n- Supports recursive loading of referenced business docs and robust handling of chained dependencies before each call.\n\nArchive index:\n\nArchive v2.1.0: 30 files, 115368 bytes\n\nFiles: agents/openai.yaml (387b), README.md (9723b), references/agent-workflows.md (4513b), references/artifact-handling.md (932b), references/call.md (9123b), references/custom-tools.md (3408b), references/data-model-query.md (15961b), references/describe.md (4121b), references/discovery.md (12229b), references/doc-index.md (4639b), references/init.md (10792b), references/insight-agent-behavior.md (1418b), references/metric-model-query.md (3812b), references/profiles.md (4853b), references/query-routing.md (23869b), references/report-query.md (10316b), references/rhino-template.md (18794b), references/sessions-and-logs.md (11057b), references/strategy.md (4671b), references/troubleshooting.md (5966b), scenarios/data-query.md (9336b), scenarios/push-message.md (5829b), scenarios/schedule-task.md (18816b), scripts/artifact_io.py (16225b), scripts/baize_session.py (14710b), scripts/inject-script.mjs (3153b), scripts/smartbi_internal.py (12937b), skill-card.md (2812b), SKILL.md (21443b), _meta.json (130b)\n\nFile v2.1.0:SKILL.md\n\n---\nname: smartbi-cli\ndescription: 广州思迈特软件有限公司（思迈特）提供的 SmartBI 通用业务操作技能。当用户需要连接 SmartBI、查询数据模型或指标模型、对已有报表问数、进行 AI 问数与复杂洞察，或管理智能体、知识库与知识图谱、数据模型、数据源、定时任务与 ETL、消息推送、资源及权限时使用。通过 @smartbi/cli 发现并调用当前环境的 SmartBI API，支持 MQL 与只读 SQL 直接取数。\n---\n\n# SmartBI CLI\n\n## 流程概览\n- **Step 0 — Scenario Router**（入口）：先看用户问句是否命中 Part 2 场景索引。命中 → 加载对应场景文件执行；未命中 → 进入 Part 1。组合请求按业务步骤衔接，不让取数场景覆盖调度、推送或资源操作。\n- **Part 1 — Core CLI Workflow**（骨架）：任何 `domain.operationId` 的发现→理解→调用→排错流程一致。\n- **Part 2 — Scenario Guides**（场景）：高频业务场景的端到端模板，按需加载。\n- **`references/`**（参考）：各 Phase 的详细流程、策略模板与文档路径索引。\n\n数据查询与洞察的扩展路径见 [scenarios/data-query.md](scenarios/data-query.md)，按需加载，不改变其他场景的通用调用流程。\n\n命中数据查询与洞察场景后，已知 operationKey 按场景文件的最短可验证调用链执行；资源未知时按该场景定位业务资源。该场景已授权只读调用不执行下文 Phase 3 的逐次确认；下文 Part 1 的通用接口发现与写操作规则继续用于其他业务操作。\n\n## Triggers（触发条件）\n\n当用户描述 **BI 业务动作 + 业务对象**，但未显式给出接口名/operationKey（例如\"帮我训练模型资源A\"\"基于模型资源A分析去年销售额\"）时触发。\n\n当用户问及 BI 相关业务操作（分析、训练、指标查询、报表/问句类需求、定时计划任务等）时触发本 skill。触发后进入 Step 0 路由判断。\n\n`operationKey` 格式为 `${domain}.${operationId}`（如 `demo.createOrder`、`aichat.getAgentItems`）。`list` 输出结果可直接复制作为 `describe`/`call` 的参数。\n\n---\n\n## 全局约定（所有路径共用）\n\n以下规则适用于 **所有** 执行路径（Part 1 通用流程和 Part 2 场景流程）。先读完全局约定，再进入 Step 0 路由判断。\n\n### CLI 安装与配置\n\n- MUST 仅通过 **npm 全局安装** 获得可执行命令 `smartbi`：`npm install -g @smartbi/cli@latest`，随后 `smartbi --version` 验证版本 **≥ 2.0.0**，并执行 `smartbi profile list --help` 确认 profile 命令族可用。\n- MUST NOT 使用 `yarn` / `pnpm` / `bun` / `npx` 或其它程序代替上述 `smartbi`。\n- 初始化 MUST：由 CLI 全参数生成配置：`smartbi init --server-type <sdk-server|smartbi> --base-url <url> --token <token> [--profile <name>]`；凭证方式按用户选择，可使用字面令牌、环境变量或钥匙串，细节见 `references/init.md`。\n- 配置文件路径：默认 **`~/.smartbi/config.yaml`**，或用户在 init 后 **明确指定** 的 `--config <path>`。MUST NOT 在系统中猜测或套用其它文件。config.yaml 可包含多个环境（profiles），默认环境由 `profile:` 字段指定；多环境的选择、配置与错误处理见 `references/profiles.md`。\n- CLI 不存在时的处理流程见 `references/init.md`「标准安装」。\n\n### 环境选择（多 profile）\n\n任务开始时在内部确定本次使用的 profile：用户指定连接或客户时按 `references/profiles.md` 匹配或新建，未指定时用默认 profile（config.yaml 的 `profile:` 字段）。普通业务对话不询问或展示 `dev`、profile 名、`--profile` 等内部配置；多个连接无法区分时只按服务器地址或用户熟悉的业务名称澄清。\n\n环境确定后，**所有** `smartbi` 命令（`list`/`search`/`describe`/`call`/`doc`）**一律带 `--profile <name>`**。\n\n完整规范（确定/告知/配置/错误处理/版本约束）见 `references/profiles.md`。\n\n### 首次配置\n\n仅在无配置或所选环境缺少必要信息时补齐配置。复用已知地址、服务器类型、环境名和有效凭证来源（字面令牌、环境变量或钥匙串），只询问缺失项，一次一个问题。已有地址但缺少/失效令牌时只处理凭证，不再推荐体验中心。已有配置的修复见 `references/init.md`，不得用全量初始化覆盖其他环境。以下完整流程用于首次无配置的情况：\n\n1. **先问地址**：用户提供 SmartBI 地址 → `serverType: smartbi`。如果用户只表达“连接 SmartBI”或“连接 SmartBI 地址”但没有提供具体地址，第一问直接说：“是否连接 SmartBI 官网体验中心 https://cloud.smartbi.com.cn/smartbi？如果要连接自己的环境，请提供地址。”不得只问“要连接哪个环境”而遗漏体验中心选项；也不得在用户确认前将体验中心写入配置或发起连接。用户确认后使用该地址和 `serverType: smartbi`。用户拒绝或需要其他环境时，再询问实际 SmartBI 地址；用户无法提供 SmartBI 地址时，询问 SDK Server 地址并使用 `serverType: sdk-server`；两者均无法提供时暂停。\n2. **再问令牌**：问令牌时一并说明获取路径和存储方式（仅一句）：\"请提供 SmartBI 个人访问令牌（登录 SmartBI 后，在「个人中心 → 我的设置 → 个人访问令牌」中新建）。令牌默认直接存进配置；如对安全有更高要求，也可以改用「环境变量」或「系统钥匙串」存储。\"首次配置不再询问环境名；若用户选择其他存储方式，步骤 3 按其选择生成。\n3. 执行 `smartbi init --server-type <sdk-server|smartbi> --base-url <地址> --token <令牌> [--profile <环境名>]`（不指定 `--profile` 时默认 `dev`；CLI 写盘 `~/.smartbi/config.yaml`，该环境同时为默认环境）。若用户选择其他存储方式：「环境变量」→ 以 `--token-env <VAR>` 替代 `--token`；「系统钥匙串」→ agent 无交互终端，使用当前 shell 的安全 stdin 管道传入令牌，并带 `--token-keyring --token-stdin`；不要把字面令牌写进命令历史（裸 `--token-keyring` 在无 TTY 下会直接失败）。\n4. 配置成功后继续原业务请求；仅需区分多个连接或排错时，用服务器地址或用户熟悉的名称说明当前连接，不单独展示内部 profile 名。\n\n`serverType` 取值约束（MUST）：只能是 `sdk-server` 或 `smartbi`，不得使用其他变体。\n\n新增连接（追加写入、不动默认环境）的流程见 `references/profiles.md`「连接配置流程」。详细提问模板见 `references/init.md`。\n\n### 参数构造规范\n\n构造 `smartbi call` 的请求体时，按以下优先级确定取值来源：\n1. **用户输入或上下文已知事实**：对话中已明确提供的值\n2. **文档内容**（优先）：字段业务含义、合法枚举值、字段间依赖、完整使用示例（通过 `smartbi doc` 加载）\n3. **`requestBodySchema`**（兜底）：文档不可用或未覆盖时使用\n4. **`callParameterPlan`**：CLI 标志映射\n5. **`suggestedCall`**：仅供参考的命令模板，不应直接复用其占位值\n6. **仍无法确定的字段**：向用户确认，不得自行编造\n\n若通用指南/示例与当前 operation 的 required、字段类型、枚举或外层包装冲突，结构以当前 operation 契约为准；业务语义冲突需进一步核实，不能盲从示例或猜测。\n\n构造 call 参数时，应主动获取 `docs/specs/` 下的业务文档作为理论依据；文档不可用或未覆盖时，以 schema 定义兜底。已加载路径不重复加载。\n\n**请求体文件规范（MUST）**：\n- JSON 请求体必须使用 `-d @file.json`（避免跨 shell/OS 转义差异）\n- MUST NOT 使用内联 JSON（如 `-d '{\"k\":\"v\"}'` 或 `-d \"{\\\"k\\\":\\\"v\\\"}\"`）\n- 为本轮 `call` **新建**的 JSON 文件：在 `smartbi call` 流程结束后 **MUST** 删除；不得删除用户自带的 `@` 文件\n- 临时文件优先写入当前运行环境可写、且 CLI 能解析的系统临时目录，结束时清理；Windows 上若 Git Bash 的 `/tmp` 路径报 `Body file not found`，改用 Windows 临时目录的绝对路径，不写死用户名；清理被权限阻止时报告残留位置与原因，不声称删除成功，不将请求、日志或结果写入 Skill 目录\n- 写入请求体前，若有 Rhino 脚本等需转义的内容，MUST 使用 `scripts/inject-script.mjs` 工具，禁止手工转义\n\n### 子任务机制\n\n执行 `call` 前，若某些参数值依赖其他 `smartbi` 操作（如先查资源 ID、先创建关联对象），MUST 以子任务方式自动完成，**不得让用户手动查找**。\n\n- 子任务执行路径：继承父任务已选场景。数据查询场景中已知 operationKey 的只读前置操作按该场景最短可验证调用链执行；其他前置操作绕过 Step 0 场景匹配，进入 Part 1 Phase 1→3 通用流程（`list` → `describe` → `call`）。完成后把结果填回父 call。\n- 退出硬限制（任一触发即停止自动化，执行用户升级流程，详见 `references/call.md`「前置条件与子任务」）：\n  - **深度上限**：嵌套深度 ≤ 3（原始 call 为深度 0）\n  - **数量上限**：每个父 call 的直接前置子任务 ≤ 5 个\n  - **去重**：同一 `operationKey` + 相同参数意图，同一调用链内已完成的前置操作不再重复发起\n- 子任务失败时向用户报告原因并暂停当前 call。\n\n### 重试与幂等\n\n- **写请求**（POST / PUT / PATCH / DELETE）：仅当 `--idempotent` 指定或 describe 元数据 `idempotent === true` 时才可自动重试，否则最多尝试 1 次\n- **可触发的 HTTP 状态重试**（在剩余次数内）：429 / 502 / 503\n- **最大尝试次数**：允许重试时最多 3 次（含指数退避与抖动）\n\n### 输出格式（Output Contract）\n\n每次调用完成后，按以下固定顺序输出：\n1. `operationKey`\n2. 最终执行命令\n3. 关键结果（`status`/`tid`/核心业务字段）\n4. 若失败：单行修复建议 + 下一条可执行命令\n\n直接取数路径对用户优先展示业务答案、口径与结果范围；上述技术明细仅在排错、审计或用户要求时展示，不逐接口打断业务流程。\n\n### Agent 与自定义工具操作\n\n- 创建、导出或修改 Agent 工作流：读取 [references/agent-workflows.md](references/agent-workflows.md)。\n- OpenAPI Provider、工具解析和绑定：读取 [references/custom-tools.md](references/custom-tools.md)。\n- 标准 SDK 未覆盖时才按上述参考使用 `scripts/smartbi_internal.py`；修改前导出、备份和校验，修改后回读并验证。普通查询不会触发这些修改。\n\n### 参考文件按需加载\n\n默认只使用 SKILL.md 本摘要。需要模板/字段映射/检查清单/异常分支时，以及需要加载接口关联文档时，才读取 `references/` 下的对应文件或执行 `smartbi doc`。\n\n# Part 1: Core CLI Workflow（骨架流程）\n\n以下四个 Phase 定义了从用户意图到 API 调用的完整流程。\n通用参数构造、子任务等底层规则在 [全局约定](#全局约定所有路径共用) 中定义，这里只描述各阶段的执行顺序。\n\n## Phase 0 — 惰性预检\n\n默认不强制在每个新会话先检查安装/配置。直接进入 Phase 1（`list` / discover）。\n\n当**任意一次**实际执行 `smartbi`（任意子命令）时，若出现下列情况，才按 [全局约定 · CLI 安装与配置](#cli-安装与配置) 补齐与排查：\n\n- **CLI 不存在**（`command not found` / 退出码 127 等）→ 立即停止，按标准安装流程处理\n- **鉴权/凭证**：`AUTH_FAILED` / `FORBIDDEN` / `PROFILE_NOT_FOUND`\n- **服务不可达**：`NETWORK_TIMEOUT` / `NETWORK_ERROR` / `UPSTREAM_UNAVAILABLE`\n- **配置缺失或不合法**：`INVALID_ARGUMENT` 且 hint 指向 `Config file not found`\n\n其余错误跳过惰性预检，由 Phase 4 诊断处理。\n\n## Phase 1 — Discover\n\n```\nsmartbi list --profile <name> --agent\n```\n\n1. 默认先执行 `smartbi list --profile <name> --agent`，将候选全集交给大模型做语义重排。\n2. 若结果过大，先加 `--domain` / `--service` 再次 `list` 收敛。\n3. 若候选唯一且语义明确匹配（用户意图与接口 summary 高度一致，无歧义）→ 直接进入 Phase 2，在 Phase 3 `call` 前向用户展示\"准备调用 `<operationKey>`，参数如下…\"做一次性确认。不要继续 search，也不要单独停下来等用户确认 operationKey。\n4. 若候选唯一但语义匹配度存疑（摘要与意图不完全对应）→ 展示该候选给用户，等用户明确确认后进入 Phase 2。\n5. 若存在多条疑似候选无法区分 → 仅对难以区分的候选调用 `smartbi search <operationKey> --profile <name> --verbose --agent` 获取详细信息以消歧。MUST NOT 对所有 Top-N 逐个 search。\n6. `search` 的关键词检索仅作为补充回退手段（例如用户提供了明确关键词锚点时），不作为默认第一步。\n\nPhase 1 定位约束（MUST）：\n- MUST 默认使用 `list` 路径定位接口，不得先走 `search` 作为主路径。\n- `search --verbose` 仅用于消歧，不得对每个候选盲目执行。\n- 存在多候选时 MUST 等在候选阶段让用户选择，不得替用户拍板。唯一且明确匹配时可直接进入 Phase 2（在 Phase 3 call 前做一次性确认）。\n\n细节见 `references/discovery.md`。\n\n## Phase 2 — Contract\n\n```\nsmartbi describe <operationKey> --profile <name> --agent\n```\n\n消费字段：`callParameterPlan`、`requestBodySchema`、`consumes/produces`、`suggestedCall`。\n\n### 文档加载（优先获取，不可用时兜底）\n\n`describe` 完成后，应主动尝试加载关联文档作为理解接口语义的理论依据。\n\n**步骤 1 — 识别文档来源**：\n\n| 维度 | 识别方式 | 示例 |\n|------|----------|------|\n| `description` 中的链接 | 扫描 `describe` 输出的 `description` 字段中的 Markdown 链接 | `[MQL详情](/docs/specs/datamodel/mql/mql.md)` |\n| `requestBodySchema` 中的链接 | 沿 `$ref` 链查找被引用 schema 的 `description` 中的链接 | schemas.yaml 中组件定义的 description |\n| domain 推断 | 根据 `operationKey` 所属 domain 推断相关文档目录 | `createDataSet` → `docs/specs/tabularmodel/` |\n| 数据类型推断 | 根据请求体中涉及的核心数据类型推断参考文档 | 含 `DataSetMeasure` → `docs/specs/tabularmodel/mdl/references/measures.md` |\n| `llmBrief` / `summary` 中的引用 | 检查 describe 输出其他字段中的文档引用 | — |\n\n**步骤 2 — 加载与穿透**：对识别到的文档路径，执行 `smartbi doc <path> --profile <name> --agent`，stdout 纳入上下文。文档中的引用链接继续递归加载，硬限制：\n- **深度 ≤ 3**（初始文档为深度 0），**去重**（已加载路径不重复）\n- 绝对路径 `/...` → 直接传给 `smartbi doc`；相对路径 → 基于当前文档路径解析；外部 URL → WebFetch\n\n**步骤 3 — 文档优先，schema 兜底**：按 [全局约定 · 参数构造规范](#参数构造规范) 的优先级规则取值。文档有定义时以文档为准，不可用时以 schema 兜底。\n\nMUST NOT 忽略链接或自行猜测文档内容。细节见 `references/describe.md`。\n\n## Phase 3 — Execute\n\n```\nsmartbi call <operationKey> -d @body.json --profile <name> --agent\n```\n（`<name>` 为本次操作环境；所有命令一律带 `--profile`，见全局约定「环境选择」）\n\n- 参数构造、请求体格式、临时文件清理等底层规则见 [全局约定 · 参数构造规范](#参数构造规范)\n- 前置参数依赖的子任务机制见 [全局约定 · 子任务机制](#子任务机制)\n- 重试策略与幂等门控见 [全局约定 · 重试与幂等](#重试与幂等)\n- 复杂参数组合策略见 `references/strategy.md`\n\n细节见 `references/call.md`。\n\n## Phase 4 — Diagnose\n\n失败后 `smartbi describe <operationKey> --profile <name> --agent`；仍有契约歧义再加 `--include-raw-schema`。\n诊断策略参考 `references/strategy.md`。\n\n# Part 2: Scenario Guides（场景索引）\n\n**入口先走 Step 0 — Scenario Router。** 将业务操作问句与下表比对：\n- 命中 → 加载对应场景文件，按场景流程执行\n- 未命中 → Part 1 通用流程\n- 加载后场景判定不适用 → 回退 Part 1\n\n| 场景 | 关键触发词 | 场景文件 |\n|------|-----------|---------|\n| S1 定时计划任务 | 每天/每周/定时/cron + 查询/统计/推送/ETL | `scenarios/schedule-task.md` |\n| S2 消息推送 | 发送/推送/通知 + 企微/钉钉/飞书/邮件 | `scenarios/push-message.md` |\n| 数据查询与洞察（扩展） | 模型/已有报表取数、指标查询、比较、归因、报告分析 | [scenarios/data-query.md](scenarios/data-query.md) |\n\n触发词仅用于快速匹配；精确判定由场景文件 `## 触发` 节负责。仅命中时才加载对应文件。\n\n场景随 OpenAPI 的扩展可持续追加；新增场景按类型完成端到端验证后才可声明支持，尚未验收的分支须标明边界。\n\n> **开发者**：扩展场景在 `scenarios/` 中声明触发条件与执行路径，通过本表挂接；复用 Part 1 和现有参考，不复制安装、鉴权或接口调用框架。\n\n---\n\n## 常见错误速查\n\n### CLI / 连接类\n\n| 错误 | 原因 | 处理 |\n|------|------|------|\n| `command not found` (127) / `is not recognized` | 未安装 CLI | → Phase 0 标准安装 |\n| `AUTH_FAILED` (401) | token 无效或已过期 | 让用户重新申请令牌；用 `smartbi profile show <name>` 诊断凭证来源后更新配置 |\n| `FORBIDDEN` (403) | 用户无权限执行该 operation | 检查 `x-funcPerm` 要求，确认用户角色 |\n| `Plain token is disabled by allowPlainToken=false`（AUTH_FAILED） | 字面量 token 被 `allowPlainToken: false` 拦截（配置通常被外部改动过） | 按 init.md 修复凭证来源；保留该 profile 的其他设置和其他环境，不擅自改为明文或覆盖初始化 |\n| `KEYRING_UNAVAILABLE` | 配置了 `tokenKeyring: true` 但系统钥匙串不可用（无头/无桌面会话） | 恢复钥匙串可用性，或按用户选择更换凭证来源；遵循 init.md 保留现有配置 |\n| `NETWORK_TIMEOUT` / `NETWORK_ERROR` | 服务不可达 | 检查 `baseUrl` 是否正确，网络是否通 |\n| `UPSTREAM_UNAVAILABLE` (503) | SmartBI 服务未启动或过载 | 确认服务状态后重试 |\n| `Config file not found` (INVALID_ARGUMENT) | 配置文件不存在 | → Phase 0 init 流程 |\n| `Config file is invalid`（INVALID_ARGUMENT，附逐条 `- 路径: 原因`） | 配置内容不合法 | 按逐条摘要修正字段，保留现有环境和自定义设置，不用重新 init 覆盖 |\n| `PROFILE_NOT_FOUND` | 指定的环境不存在 | `smartbi profile list` 列出现有环境让用户选择，或按 `references/profiles.md` 新建 |\n| `SpecRejected` / `path not in spec` | sdk-server 路径前缀错误 | 确认 `serverType` 与 `baseUrl` 配置一致 |\n\n### API 业务类\n\n| 错误 | 原因 | 处理 |\n|------|------|------|\n| `getDataModelTrees` 的空 `modelIds` 返回 `[]` | 空数组不是“列出全部模型” | 用目录枚举或搜索找到实际模型 ID，再取字段树 |\n| MQL `没有找到层次字段` | `dims` 可能用了技术名或缺少模型要求的层级路径 | 对照当前字段树/模型契约，使用已核实的维度层级标识；不猜英文 `refColumn` |\n| MQL `表未找到` / SQL `DAO_ID_IS_NULL` | `from`/`FROM` 可能用了物理表名，或模型视图未解析 | 先核对字段树中的来源别名；仍不足时按需读 `getDataSet` 的 `views` 并验证逻辑别名，不盲改字段或切换查询方式 |\n| `选择字段不能为空` | dims/metrics 空或不匹配 | 先调 `getDataModelTrees` 确认字段 label |\n| `Failed to obtain two-dimensional data` | `showDataTable: true` 不兼容某些模型 | 改为 `false`，下载 s3Url 产物并识别真实格式，不预设 Parquet |\n| `unsupported literal in MQL filter` | MQL `:param` 占位符不兼容 | 改为字面量 `'值'`，内部单引号双写 |\n| `connector.remoteInvoke` 报错 | RMI 签名不匹配 | 调 `getTaskScriptEnv` 查看可用方法 |\n| HTTP 500 / `Internal Server Error` | 服务端异常 | 记录 `tid`，用 `describe --include-raw-schema` 排查请求体 |\n\n---\n\n## 参考（按需加载）\n\n| 文件 | 内容 |\n|------|------|\n| `references/init.md` | 安装与配置 |\n| `references/profiles.md` | 多环境（profile）规范：确定/告知/配置/错误处理 |\n| `references/discovery.md` | Phase 1 接口发现 |\n| `references/describe.md` | Phase 2 契约理解 |\n| `references/call.md` | Phase 3 执行调用 |\n| `references/strategy.md` | 策略与常见模式（Phase 3 构造复杂参数或 Phase 4 诊断时加载） |\n| `references/rhino-template.md` | MQL 取数 Rhino JS 模板（定时任务场景共用） |\n| `references/doc-index.md` | domain → 文档路径索引（Phase 2 文档加载时参照） |\n| `scenarios/schedule-task.md` | S1 定时计划任务 |\n| `scripts/inject-script.mjs` | 脚本注入工具：将多行 JS 文件自动 JSON 转义后注入请求体 |\n\nFile v2.1.0:README.md\n\n# SmartBI CLI Skill\n\nSkill 版本：**2.1.0**。运行时依赖的 `@smartbi/cli` 版本独立管理，最低要求为 2.0.0。\n\n保留标准 Skill 的业务路由，为数据类请求采用基于模型的直接取数路径：用户问句 → 读取必要模型信息 → 根据模型与 SDK 能力选择 MQL 或只读 SQL → CLI 调用 SDK → 校验数据 → 桌面智能体分析/展示。直接取数不依赖模型训练或 AI 问数，无需额外查询框架。详见 `references/query-routing.md`。\n\n在原版场景索引中新增数据查询与洞察，入口为 `scenarios/data-query.md`；原有通用 API、定时任务和推送保留。外部智能体通过接口定位资源，不依赖 SmartBI 页面预选信息。模型取数按语义选择 MQL/只读 SQL，已有报表按定义与参数查询/导出；正式报告、归因、预测和综合大屏按路由默认白泽，用户指定直接取数或本地分析时遵循其选择。已有数据制图和文件转换继续本地处理；创建或修改 SmartBI 报表仍走资源操作接口。\n\n普通取数依赖 Node/npm 全局安装的 SmartBI CLI（>=2.0.0）。Python 仅用于可选辅助脚本/文件读取，不是 MQL 前置条件。跨桌面客户端需具备命令执行和文件读写能力；不能把单一客户端的实测视为所有客户端已验证。\n\n支持具备命令执行和文件读写能力的桌面智能体，通过 `@smartbi/cli` 发现并调用当前环境开放且有权限的 SmartBI API。\n\n## 目标\n\n```\n          ┌──────────┐\n          │ 任意 Agent │\n          └─────┬────┘\n                │ 自然语言意图\n                ▼\n┌───────────────────────────────┐\n│   smartbi-cli skill           │\n│                               │\n│  意图 → operationKey → call   │\n│                               │\n│  定时计划任务 / ...           │\n└───────────────┬───────────────┘\n                │ smartbi call\n                ▼\n┌───────────────────────────────┐\n│   SmartBI OpenAPI             │\n│   (datamodel / scheduletask   │\n│    tabularmodel / aichat ...) │\n└───────────────────────────────┘\n```\n\nSkill 提供业务路由与调用规则，实际能力取决于当前 SDK、模型定义和账号权限。\n\n普通“查询XXX数据”默认取齐指定条件和粒度下的结果；`limit`控制单次批量，满批且无结束证据时继续分页。明确TopN/前N条/样本时按指定范围停止。数据默认直接展示，文件按需交付；不能将首批或预览称为全部，执行受容量或耗时限制时明确说明未完成范围。\n\n## 架构\n\n```\nSKILL.md                         ← 入口（agent 加载）\n│\n├─ 直接取数                       ← 必要元数据 → MQL/SQL → 校验 → 本地分析/交付\n│   query-routing.md / data-model-query.md\n│\n├─ Part 1: Core CLI Workflow     ← 骨架，所有 OpenAPI 调用通用\n│   Phase 0  惰性预检\n│   Phase 1  Discover  (smartbi list)\n│   Phase 2  Contract  (smartbi describe + doc)\n│   Phase 3  Execute   (smartbi call)\n│   Phase 4  Diagnose  (失败诊断)\n│\n├─ Part 2: Scenario Guides（索引）  ← 按意图路由，命中后加载对应文件\n│\n├─ scenarios/                    ← 场景文件（每个独立验证）\n│   ├─ schedule-task.md          S1 定时计划任务\n│   ├─ push-message.md           S2 消息推送\n│   └─ data-query.md             数据查询与洞察\n│\n└─ references/                   ← 参考手册（按需加载）\n    ├─ init.md                   安装与配置\n    ├─ profiles.md               多环境（profile）规范\n    ├─ discovery.md              Phase 1 详细流程\n    ├─ describe.md               Phase 2 详细流程\n    ├─ call.md                   Phase 3 详细流程\n    ├─ strategy.md               策略与常见模式\n    ├─ rhino-template.md         MQL 取数 Rhino JS 模板（共用）\n    └─ doc-index.md              domain → 文档路径索引\n```\n\n## 当前能力\n\n| 场景 | 能力 | 状态 |\n|------|------|------|\n| **直接 MQL 取数** | 字段发现、过滤、聚合、排序、分页及按需计算，本地分析与文件交付 | 按目标环境契约、模型字段和查询结果逐次校验 |\n| **通用 OpenAPI 调用** | `smartbi list` → `describe` → `call`，按当前注册接口执行 | 保留原标准流程 |\n| **S1 定时计划任务 / S2 推送** | 定时任务、脚本及消息推送指南 | 保留原场景，本轮只读验收不代表写操作已复测 |\n| **已有报表取数** | 资源发现、元数据、参数、导出与文件校验 | 按报表类型、有效参数和业务结果逐次校验 |\n| **SmartBI AI / Baize** | 按数据查询与洞察场景处理显式请求或复杂洞察 | 按需分支，不是普通直接取数前置 |\n\n> 新场景按具体类型和路径完成端到端验收后才声明支持；已加入的扩展说明须保留未验证边界。\n\n## 依赖\n\n- **npm 包**：`@smartbi/cli >= 2.0.0`（`npm install -g @smartbi/cli@latest`）\n- **外部 skill**：**零**。本 skill 自闭环，不依赖任何其他 skill。\n\n## 使用说明\n\n### 安装\n\n```bash\nnpm install -g @smartbi/cli@latest\nsmartbi --version   # 确认 >= 2.0.0\nsmartbi init --server-type <sdk-server|smartbi> --base-url <url> --token <token>\n                    # 全参数生成 ~/.smartbi/config.yaml\n```\n\n### 在 Agent 中使用\n\n1. 将本目录放到 agent 的 skills 路径下（如 Cursor 的 `.cursor/skills/`、Claude Code 的配置的 skills 目录等）\n2. Agent 加载 `SKILL.md` 后自动获得以下能力：\n   - 发现接口：未知操作时由 `smartbi list --profile <name> --agent` 语义匹配 → 得到 `operationKey`\n   - 查询快速路径：已知并核实 operationKey 时直接调用；尚未核实时 `describe → call`；只有契约不足才读取 doc\n   - 理解契约：`smartbi describe <key> --profile <name> --agent` → 加载文档 → 理解参数\n   - 执行调用：`smartbi call <key> --profile <name> -d @body.json --agent` → 返回结果\n   - 定时任务：识别定时意图 → 生成 Rhino JS → 创建 task + schedule → 启用\n\n### 场景路由\n\nAgent 根据用户问句自动选择场景：\n\n```\n用户问句\n  ├─ 明确要求定时、推送或资源操作 → 原场景 / 通用 API 流程\n  ├─ 普通模型问数 → 模型元数据 → MQL/只读 SQL → 校验结果\n  ├─ 已有报表问数 → 报表定义与参数 → 只读查询/导出 → 校验结果\n  ├─ 明确白泽或默认复杂洞察 → 会话流程（用户指定直接/本地优先）\n  └─ 已有数据的本地报告、图表或文件转换 → 桌面智能体本地处理\n```\n\n## 如何新增 Scenario\n\n1. 新建 `scenarios/<name>.md` — 自描述文件：触发条件 + 请求体模板 + 注意事项\n2. 通过实际 API 调用端到端验证（Python 脚本或 smartbi call）\n3. `SKILL.md` Part 2 索引表加一行\n4. 如有新的共享代码模板 → `references/` 下新增\n\n每个新场景必须经过端到端验证后才可入库，不添加未验证的 placeholder。\n\n## 示例对话\n\n**即时查询**：\n> 用户：帮我查一下上个月各分支行的贷款余额\n> Agent：复用或定位模型，核实余额口径后直接MQL查询，返回各分支行余额、日期范围和必要说明；需要文件时下载校验后给本地文件，不暴露签名地址。\n\n**定时计划任务**：\n> 用户：每天 9:00 发送保额大于 20 万的保单数据到邮箱\n> Agent：创建 Rhino JS 脚本（MQL 取数 + 过滤 + HTML 格式化）→ 创建任务 → 创建计划（DAY, 9:00, MAIL）→ 启用\n\n## 文件清单\n\n```\nsmartbi-cli/\n├── README.md                    ← 本文件\n├── SKILL.md                     ← skill 入口（agent 加载）\n├── agents/                      ← Agent入口提示\n│   └── openai.yaml\n├── scripts/                     ← 按需辅助工具，不是普通查询前置\n│   ├── artifact_io.py           文件识别、下载与读取\n│   ├── baize_session.py         白泽路径的会话工具\n│   ├── smartbi_internal.py      会话工具共用模块\n│   └── inject-script.mjs        脚本参数注入\n├── scenarios/                   ← 保留标准业务场景\n│   ├── schedule-task.md         S1 定时计划任务\n│   ├── push-message.md          S2 消息推送\n│   └── data-query.md            数据查询与洞察（扩展）\n└── references/                  ← 参考手册\n    ├── query-routing.md         直接取数范围、最小路径及校验\n    ├── data-model-query.md      MQL/SQL接口契约与示例\n    ├── report-query.md          已有报表定位、参数、导出与校验\n    ├── artifact-handling.md     文件值保真及格式处理\n    ├── sessions-and-logs.md     白泽会话与执行校验\n    ├── agent-workflows.md / custom-tools.md / insight-agent-behavior.md\n    ├── troubleshooting.md      按失败层级排错\n    ├── init.md\n    ├── profiles.md\n    ├── discovery.md\n    ├── describe.md\n    ├── call.md\n    ├── strategy.md\n    ├── rhino-template.md        MQL 取数 Rhino JS 模板（共用）\n    └── doc-index.md\n```\n\nFile v2.1.0:_meta.json\n\n{\n  \"ownerId\": \"kn7bgapafkp5xjwz4xafxyynzx87dnfb\",\n  \"slug\": \"smartbi-cli\",\n  \"version\": \"2.1.0\",\n  \"publishedAt\": 1790073193891\n}\n\nFile v2.1.0:references/agent-workflows.md\n\n# Agent workflow export and modification\n\nResolve `<PYTHON>` to an available Python 3 interpreter and `<SKILL_DIR>` to this Skill's absolute directory. Wrapped POSIX examples show argument grouping; adapt continuation characters to the current shell.\n\n## Capability boundary\n\nThe standard `aichat` CLI currently exposes Agent discovery and execution but not the full workflow graph lifecycle. Confirm this with `smartbi list --profile <PROFILE> --domain aichat --agent` in the target installation before using internal APIs.\n\nThe following internal SmartBI internal contracts are source-confirmed but not stable public SDK commitments:\n\n| Action | Method and path |\n| --- | --- |\n| Get Agent | `GET /smartbi/smartbix/api/dataagent/graph/{id}` |\n| Search Agent graphs | `POST /smartbi/smartbix/api/dataagent/graphs` |\n| Create Agent | `POST /smartbi/smartbix/api/dataagent/graph/create/{parentId}` |\n| Update Agent | `POST /smartbi/smartbix/api/dataagent/graph/update` |\n| Download definition | `GET /smartbi/smartbix/api/dataagent/define/download/{id}` |\n| Upload definition | `POST /smartbi/smartbix/api/dataagent/define/upload` |\n\nThe raw workflow ID is used here. Remove only the leading `customagent_` that `queryRpc` adds; do not otherwise transform the ID.\n\n## Authentication\n\nInternal calls require an authenticated SmartBI session with `AI_AGENT` permissions. Put the complete header value in an environment variable supplied through a secure channel, for example:\n\n```bash\nexport SMARTBI_SESSION_COOKIE='<secret value>'\n```\n\nPass only the environment variable name to the helper:\n\n```bash\n--header-env Cookie=SMARTBI_SESSION_COOKIE\n```\n\nNever place the value in command history, request JSON, source control, or logs.\n\n## Export\n\n```bash\n<PYTHON> <SKILL_DIR>/scripts/smartbi_internal.py \\\n  --base-url <BASE_URL> \\\n  --header-env Cookie=SMARTBI_SESSION_COOKIE \\\n  agent-get \\\n  --agent-id <RAW_AGENT_ID> \\\n  --output <EXPORTED_AGENT_JSON>\n```\n\nThe command reports the graph SHA-256 and node/link counts without printing the full definition.\n\n## Modify safely\n\nStart from the exported object. Preserve every unknown graph field. Change only the required nodes, ports, links, prompts, or settings. Before applying:\n\n- parse `define` as JSON;\n- verify every link source/target node exists;\n- verify referenced input/output port IDs exist on the corresponding nodes;\n- keep node IDs stable unless a new node is genuinely required;\n- give each new node and port a collision-free ID;\n- ensure finish nodes do not wait for mutually exclusive branches;\n- do not put secrets into prompts, node inputs, or settings.\n\nFirst run a dry-run:\n\n```bash\n<PYTHON> <SKILL_DIR>/scripts/smartbi_internal.py \\\n  --base-url <BASE_URL> \\\n  --header-env Cookie=SMARTBI_SESSION_COOKIE \\\n  agent-update \\\n  --agent-id <RAW_AGENT_ID> \\\n  --file <CANDIDATE_OR_PATCH_JSON> \\\n  --backup-dir <BACKUP_DIR>\n```\n\nReview `changed_fields`, node/link counts, and `current_sha256`. Apply exactly once using that hash:\n\n```bash\n<PYTHON> <SKILL_DIR>/scripts/smartbi_internal.py \\\n  --base-url <BASE_URL> \\\n  --header-env Cookie=SMARTBI_SESSION_COOKIE \\\n  agent-update \\\n  --agent-id <RAW_AGENT_ID> \\\n  --file <CANDIDATE_OR_PATCH_JSON> \\\n  --backup-dir <BACKUP_DIR> \\\n  --expect-sha256 <CURRENT_SHA256> \\\n  --apply\n```\n\nThe helper rejects a stale hash, writes a timestamped backup before mutation, updates once, and reads back all editable fields. It has no delete or rollback command; rollback is an explicit update using the reviewed backup.\n\n## Create\n\nCreation requires a confirmed catalog parent ID and `AI_AGENT / EDIT` permission:\n\n```bash\n<PYTHON> <SKILL_DIR>/scripts/smartbi_internal.py \\\n  --base-url <BASE_URL> \\\n  --header-env Cookie=SMARTBI_SESSION_COOKIE \\\n  agent-create \\\n  --parent-id <CATALOG_PARENT_ID> \\\n  --file <AGENT_JSON>\n```\n\nThis is a dry-run. Add `--apply` only after reviewing the name, alias, node/link counts, parent, tool bindings, and permissions. Creation does not imply publication or visibility in `getAgentItems`; deployment relations differ by SmartBI version and must be discovered and verified separately.\n\n## Verification\n\nAfter update or creation:\n\n1. export/read back the Agent;\n2. confirm Provider and Tool IDs still exist;\n3. call `aichat.getAgentItems` and `getAgentCard` when applicable;\n4. create a fresh conversation rather than reusing cached execution state;\n5. test both success and failure branches;\n6. inspect rounds and chat logs;\n7. retain the backup and evidence manifest until acceptance.\n\nFile v2.1.0:references/artifact-handling.md\n\n# Artifact Handling\n\nBaize file artifacts are server URIs, not local paths. Inspect the captured SSE stream with `scripts/artifact_io.py`, download artifacts through the configured SmartBI profile, then read and verify the resulting Excel, CSV, or Parquet file. Do not treat a preview table as a complete extract or expose signed URLs.\n\nThe same reader can inspect downloaded direct-query files. CSV values stay as text, including leading zeros, decimal text and literal `NA`/`NULL`; blank cells remain empty strings. Excel preserves stored cell types, and Parquet uses its schema. Convert numeric measures explicitly from model metadata before calculating; identifier columns must retain their original values. CSV alone cannot distinguish an empty string from an exported null, and Excel number formatting may display zeros that are absent from its stored numeric value. Do not invent missing identifier digits or null semantics.\n\nFile v2.1.0:references/call.md\n\n# `call` 参考\n\n本文件为 **SmartBI CLI Skill** 的附属参考；流程性 MUST 以上级 `SKILL.md` 为准。\n\n**用途**：Phase 3（Execute）— 在已明确 `operationKey` 与参数来源的前提下发起 HTTP 调用。参数与 body **必须与** `describe` 中的 `callParameterPlan` 与 `requestBodySchema` 一致；未知字段值须先向用户确认。\n\n自动化流程默认优先使用 `--agent`；仅在下游明确要求单行 JSON 时使用 `--json`。\n\n## 参数构造依据（文档优先，schema 兜底）\n\n构造每个字段的值时，按以下优先级确定取值来源：\n\n1. **用户输入或上下文已知事实**：用户在对话中已明确提供的值\n2. **文档内容**（优先）：Phase 2 加载的文档中定义的合法枚举值、字段语义、组合约束、完整示例\n3. **`requestBodySchema`**（兜底）：文档不可用或未覆盖时，以 schema 的字段类型约束、必填/可选为准\n4. **`callParameterPlan`**：CLI 标志映射\n5. **`suggestedCall`**：仅供参考的命令模板，不应直接复用其占位值\n\n文档有定义时以其为准，文档未覆盖时以 schema 为准；不应仅看字段名猜测语义或编造值。\n\n## 命令形式\n\n```bash\nsmartbi call <operationKey> --profile <name> [选项...] [--json|--yaml|--agent]\n```\n\n## 常用选项\n\n\n| 选项                      | 说明                          |\n| ----------------------- | --------------------------- |\n| `--profile <name>`      | 环境名；**所有命令一律带**（环境选择见 `references/profiles.md`） |\n| `-d, --data <json>`     | JSON 请求体；**必须**使用 `-d @file.json`（将 JSON 写入文件后传入 @ 路径） |\n| `-F, --form <k=v\\|k=@file>` | multipart 字段（可重复）      |\n| `--path <k=v>`          | 路径参数（可重复）                   |\n| `--query <k=v>`         | 查询参数（可重复）                   |\n| `--header <k=v>`        | 请求头（可重复）                    |\n| `--timeout <ms>`        | 超时（毫秒）                      |\n| `--dry-run`             | 仅打印请求预览，不发送网络请求             |\n| `--idempotent`          | 允许对**写请求**按策略自动重试（须业务上可幂等）  |\n| `--stream`              | 流式响应（如 SSE）                 |\n| `--stream-format <fmt>` | 流式解析提示（保留/按实现）              |\n| `--max-events <n>`      | 流式最多处理事件/块数                 |\n| `-o, --output <path>`   | 二进制响应写入文件                   |\n| `--stdout`              | 二进制响应写入标准输出                 |\n| `--refresh`             | 强制刷新 registry 缓存            |\n| `--json` / `--yaml` / `--agent` | 与 list/search/describe 相同约定 |\n| `--config <path>`       | 配置文件路径                      |\n\n\n## 与 `describe` 的对应关系\n\n- `--path` / `--query` / `--header`：与 `callParameterPlan` 中各分组的 `name`、`cli` 一致。\n- `-d`：在 `body.kind === json` 且 `consumes` 含 JSON 类类型时使用；**必须**使用 `-d @file.json`，JSON 内容须满足 `requestBodySchema`。\n- MUST NOT 使用内联 JSON（如 `-d '{\"k\":\"v\"}'` 或 `-d \"{\\\"k\\\":\\\"v\\\"}\"`）。\n- `-F`：在 `body.kind === multipart` 时使用；文件字段遵循 schema 中 `format: binary` 等约定。\n- **无 body**：`body.kind === none` 时不要强行带 `-d`/`-F`（除非 OpenAPI 另有约定且已在 describe 中体现）。\n\n## 临时请求体文件（`-d @data.json` 等）的生命周期（MUST）\n\n- 由代理/自动化**为本轮 `call` 新建**的 JSON 文件（例如 `data.json`、`*-body.json`）：在 **`smartbi call` 整段流程结束**后（含成功、失败、dry-run、重试耗尽）**MUST** 删除该文件，除非用户**明确要求保留**（例如留档审计）。\n- MUST NOT 在任务收尾后长期遗留含业务参数或可能含敏感字段的临时 JSON；优先写入系统临时目录，或仓库内已 `.gitignore` 的路径，降低误提交风险。\n- 若 `-d @` 指向的是**用户已有文件**（非本轮创建），MUST NOT 擅自删除。\n\n## 成功响应中可观测字段\n\n自动化场景下，除 HTTP 语义外，成功 JSON 中常关注：\n\n- `status`：HTTP 状态码\n- `tid`：追踪标识（若存在）\n- `data`：业务载体；失败或业务错误时可能含 `data.success`、`data.error`（与 Phase 4 诊断字段一致）\n\n具体形状以当前安装 CLI 的 `smartbi call --help`、目标 operation 的 `describe` 响应和实际实现为准；Skill 不捆绑版本固定的 schema 文件。\n\n## 重试与幂等（与 CLI 实现对齐）\n\n- **写方法**：`POST`、`PUT`、`PATCH`、`DELETE` 视为写请求。\n- **是否允许写请求自动重试**：仅当 `--idempotent` 传入，或 describe 元数据中 `idempotent === true`（通常来自 OpenAPI `x-idempotent`）时，写请求才可进入与读请求相同的重试路径；否则写请求 **最多尝试 1 次**。\n- **重试次数**：允许重试时，最多 **3 次** 尝试（含指数退避与抖动）。\n- **可因 HTTP 状态触发的重试**（在仍有剩余次数时）：**429**、**502**、**503**。\n- **网络类错误**：在 CLI 判定为可重试的网络超时/错误时，同样可在上述次数内退避重试。\n- **代理义务**：不得对非幂等写请求假设可安全重放；须满足主 Skill 的幂等门控后再依赖 `--idempotent` 或元数据 `idempotent`。\n\n## 前置条件与子任务（MUST）\n\n执行 `call` 前，若 Phase 2 的 `describe` 输出表明某些参数值**无法由用户直接提供**，而需要先调用其他 `smartbi` 操作获取（例如：创建资源后得到 ID、查询列表后选取条目），则属于前置条件。\n\n处理流程：\n\n1. 识别前置条件：从 `callParameterPlan` 与 `requestBodySchema` 中判定哪些必填参数的值依赖其他 `smartbi` 操作。\n2. 创建子任务：子任务内容为再次发动 `smartbi-cli` 技能，以用户原始业务意图描述该前置操作，获取所需的参数值。\n3. 等待子任务完成，将返回结果填入当前 `call` 的参数。\n4. 所有前置条件满足后，继续执行当前 `call`。\n\n约束：\n\n- MUST NOT 跳过前置条件直接用占位值/假值发起 `call`。\n- MUST NOT 要求用户手动去查找前置数据（用户不知道接口映射关系），而应通过子任务自动完成。\n- 若前置子任务失败，应向用户报告失败原因并暂停当前 `call`。\n\n### 退出机制（MUST）\n\n为防止无限递归或子任务爆炸，子任务链受以下硬限制保护。任一限制触发时，MUST 立即停止所有自动化子任务处理，执行**用户升级流程**。\n\n**术语定义：**\n\n- **调用链**：从原始 `call` 到当前深度的全链路所有节点（含兄弟子任务）。同一调用链内的已完成结果可跨节点复用。\n- **参数意图**：子任务所要获取的具体参数值及其用途描述（如\"查询项目A的ID\"与\"查询项目B的ID\"属于不同参数意图，即使使用同一 operationKey）。\n\n**硬限制：**\n\n| 限制项 | 阈值 | 作用域 | 说明 |\n|--------|------|--------|------|\n| 深度上限 | ≤ 3 | 全链路 | 原始 `call` 为深度 0，每嵌套一层子任务深度 +1 |\n| 数量上限 | ≤ 5 | 每个父 call | 单个父 call 最多产生 5 个直接前置子任务 |\n| 去重 | 复用 | 同一调用链 | 同一 `operationKey` + 相同参数意图的前置操作已完成时，直接复用结果，不重复发起 |\n\n**用户升级流程（触发任一硬限制时 MUST 执行）：**\n\n1. 停止所有子任务处理，不继续发起新的 `smartbi call`。\n2. 向用户输出以下信息：\n   - **触发原因**：说明触发了哪条限制（深度/数量/重复），当前计数是多少。\n   - **前置条件清单**：列出当前 `call` 所有已识别但尚未满足的前置参数，格式为「参数名：需要什么值（可通过哪个 operationKey 获取）」。\n   - **已完成的前置结果**：列出已通过子任务成功获取的参数名及其值，供用户参考和复用。\n3. 请用户选择后续操作：\n   - 直接提供缺失参数的值（推荐）\n   - 指定其中部分前置条件继续自动处理\n   - 跳过某个非必填的前置条件\n4. MUST NOT 在用户未响应前自行继续。\n\n### 深度追踪（MUST）\n\n每次发动子任务时，MUST 在子任务 prompt 中显式标注当前深度。子任务 prompt 模板：\n\n```\n[前置子任务 | 深度 {N}/3] 为父操作 \"{parentOperationKey}\" 获取参数 \"{paramName}\"。\n用户原始意图：{userIntent}。\n完成后将获取到的值返回，填入父 call 的 {paramName} 字段。\n```\n\n若子任务识别到自身已达到深度上限（深度 = 3）且仍需进一步前置操作，MUST 立即触发用户升级流程而非继续嵌套。\n\n## 输出契约（机器校验）\n\n- 当前安装 CLI 的 `smartbi call --help` 和目标 operation 的 `describe` 响应\n\n与 CLI 行为或 schema 不一致时，以**当前安装的 `smartbi call --help` 与上述 schema 文件**为准。\n\nFile v2.1.0:references/custom-tools.md\n\n# OpenAPI custom tools\n\nResolve `<PYTHON>` to an available Python 3 interpreter and `<SKILL_DIR>` to this Skill's absolute directory. Wrapped POSIX examples show argument grouping; adapt continuation characters to the current shell.\n\n## Preference order\n\n1. Standard SDK metadata read (`getToolProviders`) when available.\n2. Standard `smartbi` CLI operations discovered through `list`/`describe`.\n3. Source-confirmed internal SmartBI internal APIs when the standard surface is missing.\n4. Browser/HAR evidence only to confirm an uncovered contract; never replay credentials from a HAR.\n\n## Internal contracts\n\nThe following internal routes are source-confirmed under `/smartbi/smartbix/api/dataagent/tools`:\n\n| Action | Method and path | Notes |\n| --- | --- | --- |\n| Parse without saving | `POST /parse?type=OPENAPI` | Request body is the OpenAPI text |\n| List | `POST /list` | Read-only metadata |\n| Get by name | `GET /getByName?name=...` | Returns definition and tools |\n| Execute | `POST /execute` | Remote tool side effects depend on the OpenAPI operation |\n| Create | `POST /create` | Write; no automatic retry |\n| Update | `POST /update` | Recreates all Tool IDs |\n| Delete | `POST /delete?id=...` | Destructive; not automated by this skill |\n\nUse the included read/parse commands:\n\n```bash\n<PYTHON> <SKILL_DIR>/scripts/smartbi_internal.py \\\n  --base-url <BASE_URL> \\\n  --header-env Cookie=SMARTBI_SESSION_COOKIE \\\n  provider-list --output <PROVIDERS_JSON>\n\n<PYTHON> <SKILL_DIR>/scripts/smartbi_internal.py \\\n  --base-url <BASE_URL> \\\n  --header-env Cookie=SMARTBI_SESSION_COOKIE \\\n  provider-get --name '<PROVIDER_NAME>' --output <PROVIDER_JSON>\n\n<PYTHON> <SKILL_DIR>/scripts/smartbi_internal.py \\\n  --base-url <BASE_URL> \\\n  --header-env Cookie=SMARTBI_SESSION_COOKIE \\\n  provider-parse --openapi-file <OPENAPI_YAML> --output <PARSED_JSON>\n```\n\nProvider writes are intentionally not automated by the bundled script. When a write is authorized, save the current Provider definition, parse the candidate first, call create/update exactly once, read it back, obtain the new Tool IDs, rebind affected Agent nodes, and run a fresh conversation.\n\n## Reliable OpenAPI subset\n\n- OpenAPI 3 with exactly one `servers` entry;\n- operations limited to `GET`, `POST`, `PUT`, and `DELETE`;\n- each operation has `operationId` and an explicit `200` response;\n- request body uses a simple inline object where possible;\n- one content type, preferably `application/json`;\n- top-level flat parameters for workflow-node compatibility;\n- no dependence on `default` response, `2XX` wildcard, or deep `$ref` chains.\n\nCurrent SmartBI versions may emit request-body parameter metadata with `name` but no stable `id`. A Provider saving successfully therefore does not prove ReAct can pass parameters. Use a workflow node with explicit named inputs until a real read-back and conversation test proves parameter IDs are valid.\n\nUpdating a Provider deletes and recreates all of its Tool records. Any Agent node bound by Tool ID may become stale even if the Provider ID and name remain unchanged.\n\n## Server-side safety\n\nFor read-only planning, validation, or governance tools, enforce non-execution on the remote server. Do not depend on prompts, an OpenAPI `default: false`, or the LLM to keep an execution switch disabled. Test false values as emitted by the actual SmartBI UI; some builds serialize a checkbox as `\"[false]\"`.\n\nFile v2.1.0:references/data-model-query.md\n\n# Direct SmartBI model query contract\n\nUse the target environment's registered OpenAPI operations and current `describe` contract. Examples below are request shapes, not customer model definitions; replace every model, source, field and filter using current metadata and the user's question.\n\n## Discovery and metadata\n\nWhen the model, route and scope are already clear, use this guide directly; load `query-routing.md` only for unresolved routing, discovery, scope, completeness, or semantic-validation decisions. Prefer MQL for supported model dimensions and measures; use read-only SQL when explicitly requested or MQL is unsuitable and SQL contracts and semantic metadata are sufficient. No model training or conversation is required. First resolve the **business resource** in the catalog unless a model ID is already verified. `smartbi list` enumerates registered API operations, not models. Use a confirmed catalog search for a named business topic; list by resource type only when enumeration is needed or search is unavailable. Then use the verified model ID for metadata and query. Follow the shortest verified chain: call directly when the operation contract is already confirmed for the current environment and version; otherwise describe the known operation, load docs only for unresolved contract details, and discover operations only when the operation key is unknown. Prefer a registered Overview that supplies the needed metadata; reuse sufficient metadata already read in this task. Field trees and full definitions fill gaps. The SQL overview below is one such source, not a mandatory CGI probe. The following commands are **alternatives/conditional steps, not a sequence to run in full**:\n\n```bash\nsmartbi call catalogtree.searchCatalogTree \\\n  -d @model-search.json --profile <PROFILE> --agent\n\nsmartbi call catalogtree.listCatalogElementsByResourceType \\\n  -d @model-list.json --profile <PROFILE> --agent\n\nsmartbi call datamodel.cgi.getSqlModelOverview \\\n  -d @sql-overview.json --profile <PROFILE> --agent\n\nsmartbi call datamodel.getDataModelTrees \\\n  -d @field-tree.json --profile <PROFILE> --agent\n```\n\nThis file's MQL/SQL chain is for `AUGMENTED_DATASET`; the broader model discovery and `MT_MODEL`/`TABULAR_DATASET` query paths are in `metric-model-query.md`. A `MT_MODEL` catalog ID is not an augmented-dataset ID; resolve its associated queryable model or deployment-specific query contract before direct retrieval. Model IDs and types are environment-specific. When the current search contract supports `purviewType`, set the appropriate explicit permission (for ordinary visible resources, commonly `REF`); do not assume the omitted-value behavior is identical across deployments. If a targeted search is empty, verify the permission and search mode before concluding that no model exists. `catalogtree.searchCatalogElementsByAlias` is an exact alias search; its hit can be a same-named folder rather than a model. Always inspect the returned resource type and ID before requesting model metadata. Use type enumeration when the user asks which models are available, or as a bounded fallback when targeted search fails.\n\nThe field-tree API `datamodel.getDataModelTrees` requires the plural array form:\n\n```json\n{\"modelIds\": [\"<MODEL_ID>\"]}\n```\n\n`<MODEL_ID>` must be a nonempty, catalog-verified ID. The `suggestedCall` value `{\"modelIds\":[]}` is a schema placeholder and yields no model metadata; do not execute it. If no ID is available, search the catalog instead of asking the business user to supply one. Check each catalog operation against the current `describe` contract before first use.\n\nA field-tree response can also be `[]` for a verified, nonempty model ID; this alone does not establish that the model is missing or inaccessible. If the model definition is needed, try the registered `tabularmodel.getDataSet` with that ID and inspect the relevant views, dimensions, measures and relations. Do not turn this fallback into a routine full-definition fetch when the field tree already supplies enough metadata.\n\nThe SQL overview operation may not be registered on every installation; verify it with `describe` before calling it.\n\n## SQL\n\nOperation: `datamodel.queryDataBySql`\nHTTP: `POST /api/v1/datamodel/datamodel/query-data-by-sql`\nRequest body: an outer `req` object containing:\n\n```json\n{\n  \"req\": {\n    \"modelId\": \"<MODEL_ID>\",\n    \"modelType\": \"<MODEL_TYPE>\",\n    \"sql\": \"SELECT year(\\\"<DATE_COLUMN>\\\") AS \\\"年\\\", SUM(\\\"<ADDITIVE_MEASURE>\\\") AS \\\"<ADDITIVE_MEASURE>\\\" FROM \\\"<LOGICAL_TABLE>\\\" WHERE \\\"<DATE_COLUMN>\\\" >= DATE '2025-01-01' AND \\\"<DATE_COLUMN>\\\" < DATE '2026-01-01' GROUP BY year(\\\"<DATE_COLUMN>\\\") ORDER BY \\\"年\\\" LIMIT 100\",\n    \"params\": [],\n    \"extraTables\": [],\n    \"showDataTable\": true\n  }\n}\n```\n\n`sql` is DuckDB SQL over the model's available logical tables. It must be read-only. Use the model overview or field tree to determine exact logical table/column names and joins; do not use underlying physical database table names. `params` contains model parameters as `{name, values}`; omit or leave empty only when the model has no global parameters. `extraTables` is for explicitly supported additional tables and must not be used to bypass model governance.\n\nThe SQL aggregation shown is valid only for a confirmed additive measure. Resolve the underlying column and model formula before using SUM; semantic time levels are not necessarily stored columns. The illustrative date range must be replaced by the requested range.\n\n### Resolving SQL FROM\n\nThe SQL `FROM` value is a data-model logical table or view alias, not a physical database table name. Derive it from the current model's metadata. In some verified models this is the same source/measure-folder alias exposed by `datamodel.getDataModelTrees` and used as `mql.from`; this is a model-specific observation, not a universal alias.\n\nIf `DAO_ID_IS_NULL` occurs for an otherwise valid read-only SQL shape, first verify that the logical `FROM` resolves in the model. Do not start renaming columns or inventing physical table names. If the metadata does not expose a usable logical source, stop and report that the SQL model metadata is insufficient.\n\nSemantic time levels such as `年`, `年季`, and `年月` may not be physical columns of the logical fact table. When the metadata identifies a date column, derive the requested level with DuckDB functions such as `year(\"<DATE_COLUMN>\")` rather than assuming a same-named base column.\n\n## MQL\n\nOperation: `datamodel.queryDataByMql`\nHTTP: `POST /api/v1/datamodel/datamodel/query-data-by-mql`\nRequest body: an outer `req` object containing:\n\n```json\n{\n  \"req\": {\n    \"modelId\": \"<MODEL_ID>\",\n    \"modelType\": \"<MODEL_TYPE>\",\n    \"mql\": {\n      \"from\": \"<MODEL_SOURCE>\",\n      \"dims\": [\"年\"],\n      \"metrics\": [\"<ADDITIVE_MEASURE>\"],\n      \"dimFilter\": \"\\\"年\\\" >= 2022\",\n      \"metricFilter\": \"\",\n      \"sort\": [[\"年\", \"ASC\"]],\n      \"limit\": 100,\n      \"offset\": 0\n    },\n    \"params\": [],\n    \"showDataTable\": true\n  }\n}\n```\n\nUse only dimensions, metrics, source names, and filters confirmed by the field tree/model metadata. Preserve the dimension's hierarchy/path where the contract requires it (for example `客户维.分公司名称` rather than an unqualified technical field name). A physical table such as `dim_cust_info` is not a verified MQL `from` or SQL logical `FROM` merely because it appears in model internals. `mql.with` supports calculated columns, base measures, and calculated measures; calculated-measure expressions use MDX semantics, not SQL syntax.\n\nConstruct `dimFilter` using the current MQL contract and verified dimension paths and value types. In a verified model, string comparisons used single-quoted values and hierarchy-qualified fields, with `AND` between conditions; do not generalize one model's names or assume every filter expression is accepted. For a value whose presence or encoding is uncertain, a bounded unfiltered grouping of the relevant dimension can establish candidate values before a filtered query. Do not make that extra call when values are already verified; if a filtered result is empty and the value domain was not checked, distinguish “zero returned rows” from a proven absence of matching business data.\n\nWhen the field tree cannot establish a measure formula, raw-column mapping, relation, parameter, or usable source alias, discover and describe `tabularmodel.getDataSet` if available. Its request is `{\"req\":{\"dataSetId\":\"<MODEL_ID>\"}}`; inspect only the relevant parts of views, relations, measures and parameters. In a verified model, a physical `views[*].name` failed as SQL `FROM` while its `views[*].alias` succeeded; use the alias only after checking the model's query contract. The full definition is an on-demand supplement, not a routine prerequisite. Do not treat hidden supporting measures as user-facing fields merely because the full definition includes them.\n\nFor model-level calculated measures spanning multiple sources, use the model's formula and verified contract. `from` is optional in the MQL contract; do not invent a single fact-table source for a root-level measure. Validate its components at the same filters and grain. A formula explicitly defined by the model takes precedence over a calculation inferred from its business name.\n\nAn aggregation enum in the schema is not proof it executes on this model/server. If a combined `with` request fails, isolate the suspected definition with a bounded diagnostic call; do not retry the entire failing bundle repeatedly or conclude all aggregation types are unavailable. Never silently replace a failed percentile/median with an average. Where independent raw detail cannot be obtained, report statistical identity checks separately from full numerical verification.\n\nPreserving a model definition does not prove its business label is correct: a measure named as an amount may actually use COUNT. Disclose conflicts with the requested business meaning and resolve the intended measure before presenting a monetary answer; do not silently change the model aggregation.\n\nFor median/percentile questions, verify the statistical convention when it affects the answer (e.g. even-sized median and continuous vs discrete percentile). Runtime success and min/max bounds do not prove the expected convention. If a complete bounded raw sample is available, calculate independently and disclose any discrepancy; otherwise qualify the result instead of calling it verified. Local fallback must state the method and completeness, not masquerade as native MQL success.\n\nWhen a source is needed, `mql.from` is the logical model-view/source alias that contains the requested measures. Select it from the current field tree; it is not automatically the model name or model alias. Model-level calculated measures follow the optional-source rule above. If multiple candidate aliases exist, choose the one that contains the target measures. Retry at most once with another candidate explicitly present in the same metadata response; do not guess names.\n\n## Slicing validation\n\nBefore grouping a measure by a dimension from another view or fact source, use already available model metadata to check source ownership, relation direction/cardinality and whether the dimension can filter the measure at the requested grain. If the field tree cannot establish this, read only the relevant `getDataSet` definition on demand. Lack of a *direct* relation alone is not proof that MQL is invalid: a verified shared dimension or bridge can be valid. Conversely, the mere presence of both fields in one model does not prove that slicing is valid. If no sound path is established, do not send a speculative grouped MQL. Use read-only SQL only when logical views, join keys, row grain and aggregation semantics are verified; aggregate at the correct fact grain before any join that could fan out. Otherwise explain the unresolved model relationship rather than inventing a join.\n\nAfter a grouped query, repeated identical values across distinct categories are a warning, particularly for a cross-fact slice; equal values can also be real data. If mutually exclusive groups each repeat an already verified overall total, the slice is inconsistent and must not be delivered; no duplicate total query is needed. Otherwise check whether the filter actually applies and whether the grouped result is consistent with the model's relationship. Withhold a suspect business conclusion until verified. For an additive metric split into mutually exclusive, exhaustive groups, reconcile the complete grouped sum with a same-scope, same-period total, reusing a total already obtained in this task when valid. Preserve null/unclassified groups and use precision-appropriate tolerance. Do not sum stock values across time, distinct counts, ratios or overlapping groups merely to force this check. A failed reconciliation blocks that grouped conclusion; a passed one does not independently prove each group's source value. Do not promote a diagnostic SQL rewrite to the answer without the same checks.\n\nAlso check the *visible dimension tuple*, not just whether metric values repeat. A query may return multiple rows with the same displayed dimension values; those rows are not distinct business groups. Before reporting a group total, establish whether the metric is additive across those rows and the complete row sum reconciles with a separate same-filter total (or another verified equivalent). Otherwise preserve the returned rows and state that the requested visible grain has not been established; do not silently deduplicate or present one row as the group total.\n\n## Result handling\n\nOrdinary queries target the complete result at the requested filters and grain, and can deliver validated `dataTable` rows directly; CSV or another file is optional. Unless the user asks for TopN, first N or a sample, `limit` is a request batch size rather than a delivery cap. Continue full pages until completion is established; follow `query-routing.md` when result size or runtime prevents completion. Count the actual rows in `dataTable.data` for each page. Do not assume `rowCount` equals that page size: some MQL responses return a larger count for a limited page. Establish rowCount semantics from the current contract/observed pagination before using it as a total or consistency check. Check current `describe` for transport capabilities: the verified MQL and SQL contracts declare `streaming: false` and `application/json`. Client-side page delivery is possible, but neither CLI chunking nor Baize SSE establishes native row streaming for these operations.\n\nBoth operations return a result with modelId, s3Url, rowCount and optional dataTable. Check CLI ok and business success/error. When s3Url is non-empty, download using the supported SDK contract and verify actual bytes/file format (do not assume Parquet from the suffix). If s3Url is absent, the actual `dataTable.data` rows can serve as the complete result of a bounded query only after its requested range and pagination end are verified; `rowCount` alone cannot establish this. If the page reaches `limit`, continue with stable pagination until an end condition is verified; if completion cannot be established, report the delivered range as partial. Validate ratio/time-grain semantics per query-routing.md before aggregating or merging results.\n\nWithin one task, reuse model metadata and confirmed operation contracts while the environment, identity and model definition remain applicable; a full model definition is not a default prerequisite and is not persisted as a Skill cache. Combine compatible measures in one query only when source, filter, time grain and aggregation semantics align. If a combined query fails, isolate the failing measure rather than treating every measure as unsupported. Query latency and tool timeout diagnosis follow `troubleshooting.md`; no historical duration is a cross-environment baseline.\n\nFile v2.1.0:references/describe.md\n\n# `describe` 参考\n\n本文件为 **SmartBI CLI Skill** 的附属参考；流程性 MUST 以上级 `SKILL.md` 为准。\n\n**用途**：Phase 2（Contract）与 Phase 4（Diagnose）— 读取契约与诊断信息。按 Skill 要求，**默认只消费最小字段集**；其余字段仅在升级诊断时查阅。\n\n## 命令形式\n\n```bash\nsmartbi describe <operationKey> --profile <name> [--json] [--yaml] [--agent] [--include-raw-schema] [--refresh] [--config <path>]\n```\n\n\n| 选项                     | 说明                                                                       |\n| ---------------------- | ------------------------------------------------------------------------ |\n| `--json`               | 成功时 `stdout` 单行 JSON；失败时 `stderr` 默认可为人类可读                               |\n| `--yaml`               | 成功时 `stdout` 输出 YAML 文档；失败时 `stderr` 默认可为人类可读                     |\n| `--agent`              | 默认成功 `stdout` 为 YAML，失败时 `stderr` 必须输出结构化 JSON；成功体可含 Agent 侧重字段（见下节） |\n| `--include-raw-schema` | 附加 `requestBodySchemaRaw`、`responseSchemaRaw`（保留 OpenAPI 侧 `$ref` 等，供调试） |\n| `--refresh`            | 强制刷新 registry 缓存                                                         |\n| `--profile <name>`     | 环境名；**所有命令一律带**（环境选择见 `references/profiles.md`）                     |\n| `--config`             | 配置文件路径                                                                   |\n\n\n## Phase 2 必读字段（与 Skill 对齐）\n\n执行 `describe --agent` 后，消费以下字段：\n\n- **`callParameterPlan`**：path/query/header/cookie/body 分组与 CLI 示意；无某类参数时，对应键可能省略（仅 `body`、`checklist` 恒在）。\n- **`requestBodySchema`**：请求体结构（仅 body，不含 path/query/header）；与 `callParameterPlan` 共同约束如何组 `call -d` / `-F`。\n- **`consumes` / `produces`**：媒体类型。\n- **`suggestedCall`**：单行命令模板（占位符与示例，**不能替代**用户对未知字段的确认）。\n\n字段值规则仍以主 Skill 为准：**用户输入或上下文已知事实优先；其次以文档为依据，schema 兜底**（详见主 Skill「文档优先级原则」）。\n\n## 文档加载（优先获取，不可用时兜底）\n\n`describe` 完成后，应主动按主 Skill Phase 2「文档加载」步骤 1 识别文档来源，通过 `smartbi doc <path> --profile <name> --agent` 加载并递归穿透。文档有定义时以其为基准理解 schema；文档不可用或未覆盖的字段，直接使用 schema。\n\n文档路径索引见 `references/doc-index.md`，各 domain 的主要文档目录可从该文件快速定位。\n\n**递归限制（MUST）**：\n- 递归深度 ≤ 3 层（初始文档为深度 0，最多穿透到深度 3）。\n- 已加载路径（绝对路径规范化后）不重复加载，防止循环引用。\n- 超出深度的链接在当前上下文中跳过，不报错。\n\n## `--agent` 额外字段（诊断与摘要）\n\n在 `--agent` 成功响应中，通常还包含；具体字段以当前 CLI 版本的实际输出为准，Skill 不捆绑版本固定的 schema 文件：\n\n- `summary`、`description`、`requiredAll`、`llmBrief`、`constraintsHints`\n- 以及 `idempotent`、`deprecated` 等元信息\n\n用于压缩上下文下的理解与排错，**不替代**完整 `requestBodySchema`。\n\n## Phase 4 升级\n\n1. 先根据调用失败结构中的 `code`、`status`、`hint`、`details` 等定位（见主 Skill）。\n2. 需要更紧凑的必填与约束提示时，使用 **`describe <operationKey> --profile <name> --agent`**。\n3. 仅在仍有契约歧义时，使用 **`describe <operationKey> --profile <name> --agent --include-raw-schema`**。\n\n## 输出契约（机器校验）\n\n- 当前安装 CLI 的 `smartbi describe --help` 和目标 operation 的实际响应\n\n与说明不一致时，以**当前安装的 `smartbi describe --help` 与目标 operation 的实际响应**为准。\n\nFile v2.1.0:references/discovery.md\n\n# `list` / `search` 参考\n\n直接取数（模型 MQL/只读 SQL、报表读取/导出）遵循主 Skill 的已授权只读例外：复用已确认接口，不重复发现或逐接口确认。下文确认规则用于通用业务操作；取数只对影响答案的资源、字段、筛选或口径歧义提问。\n\n外部智能体须区分 API 发现与业务资源发现：`list/describe` 说明可调用的操作，不替代目录/资源搜索。没有预选资源时，以用户提供的名称、ID、链接或业务关键词通过已发现的只读资源接口定位；按资源类型进入模型、报表或其他业务路径。不能把内嵌 AIChat 的数据来源上下文视为已存在，也不全量读取所有候选定义。已有明确资源与充分元数据则直接复用。\n\n数据查询场景优先使用已知目录 operationKey；只有该 operationKey 在当前环境未知或不可用时，才以 `list --domain catalogtree` 等有范围的接口发现方式回退。本页下文的全量 `list` 主路径仅适用于未知操作的一般 Part 1 流程，不覆盖数据查询场景的资源定位顺序。`--agent` 返回 `UNKNOWN_ERROR` 时先查看结构化错误和 CLI 诊断，不能仅凭代码推断认证或网络故障；如果证据指向输出格式/呈现层，可对**同一个有范围的命令**改用 `--json` 重试。不要直接退到无过滤的注册表。Shell 管道或工具截断后的空匹配不是“没有目录接口”的证据；优先收窄域并检查命令退出状态和输出是否完整。通用 Part 1 确需检索全量注册表且执行工具会截断输出时，先让 CLI 的完整输出写入临时文件，再在同一环境中本地筛选和清理文件；不能把被截断的展示内容当成全集。\n\n本文件为 **SmartBI CLI Skill** 的附属参考，仅规范 `list` / `search` 用法；流程性 MUST 以上级 `SKILL.md` 为准。\n\n**用途**：Phase 1（Discover）— 在最小输出下定位唯一 `operationKey`。按需查阅，勿一次性展开全部条目。\n\n## 共同约定\n\n- `--json`：成功时 `stdout` 为单行 JSON；失败时 `stderr` 默认可为人类可读。\n- `--yaml`：成功时 `stdout` 为 YAML 文档；失败时 `stderr` 默认可为人类可读。\n- `--agent`：默认成功 `stdout` 为 YAML（`--stream` 下为 NDJSON），且失败时 `stderr` 必须输出结构化 JSON；字段以当前 CLI 版本的实际输出契约为准。\n- 自动化流程默认优先使用 `--agent`；仅在下游明确要求 JSON 时使用 `--json`。\n- `--verbose`：在列表项中追加较长字段（如 `description`、`tags`、`consumes`、`produces`）。\n- `--with-version`：在每个结果项中附加 `apiVersion`。\n- `--with-root-version`：在顶层结果中附加 `rootVersion`。\n- `--refresh`：本次强制刷新 registry 缓存，优先级高于配置中的 `checkIntervalSeconds`。\n- `--config <path>`：指定配置文件路径（默认 `~/.smartbi/config.yaml`）。\n- 环境确定后，`list`/`search` 一律带 `--profile <name>`；CLI 版本不支持时去掉并提示（见 `references/profiles.md`「执行规则」）。\n\n## `smartbi list`\n\n**用途**：枚举当前缓存中的 operation，适合浏览 domain/service 范围。\n\n| 选项                              | 说明                      |\n| ------------------------------- | ----------------------- |\n| `--domain <domain>`             | 仅列出该 domain             |\n| `--service <service>`           | 仅列出该 service            |\n| `--verbose`                     | 输出扩展字段                  |\n| `--with-version`                | 每个 item 附加 `apiVersion` |\n| `--with-root-version`           | 顶层附加 `rootVersion`      |\n| `--refresh`                     | 强制刷新缓存                  |\n| `--json` / `--yaml` / `--agent` | 见上                      |\n\n输出字段以当前安装 CLI 的 `smartbi list --help` 和实际 `--agent` 响应为准；Skill 不捆绑版本固定的 schema 文件。\n\n**典型用法**：\n\n```bash\nsmartbi list --profile <PROFILE> --agent\nsmartbi list --profile <PROFILE> --domain demo --service file --agent\nsmartbi list --profile <PROFILE> --verbose --with-version --with-root-version --agent\n```\n\n## `smartbi search <keyword>`\n\n**用途**：按关键词检索 operation，适合从自然语言或片段定位 `operationKey`。\n\n| 选项                                                                                                                  | 说明                                                                                                                               |\n| ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |\n| `--domain` / `--service`                                                                                            | 与 list 相同，缩小范围                                                                                                                   |\n| `--in <fields>`                                                                                                     | 可重复；检索字段：`operationKey`、`operationId`、`summary`、`path`、`tags`、`description`、`requestBodySchema`、`responseSchema`（逗号分隔或多次 `--in`） |\n| `--fuzzy`                                                                                                           | 模糊匹配                                                                                                                             |\n| `--case-sensitive`                                                                                                  | 大小写敏感                                                                                                                            |\n| `--limit <n>`                                                                                                       | 最大条数（默认 20）                                                                                                                      |\n| `--verbose` / `--with-version` / `--with-root-version` / `--refresh` / `--json` / `--yaml` / `--agent` / `--config` | 同 list                                                                                                                           |\n\n输出字段以当前安装 CLI 的 `smartbi search --help` 和实际 `--agent` 响应为准；Skill 不捆绑版本固定的 schema 文件。\n\n**典型用法**：\n\n```bash\nsmartbi search getAgentItems --profile <PROFILE> --in description,operationKey,operationId --agent\nsmartbi search order --profile <PROFILE> --in operationKey,summary --in description,operationKey,operationId --agent\nsmartbi search \"支付\" --profile <PROFILE> --in description,tags --fuzzy --limit 10 --agent\n```\n\n## 与 Skill 流程的衔接\n\n- Phase 1 默认优先 `list` 并让大模型做候选重排；结果过大时先追加 `--domain` / `--service` 收敛。\n- 候选唯一且语义明确匹配（意图与接口 summary 高度一致，无歧义）时，直接进入 Phase 2，在 Phase 3 `call` 前向用户展示\"准备调用 `<operationKey>`，参数如下…\"做一次性确认，无需单独暂停等用户确认 operationKey。\n- 候选唯一但语义匹配度存疑时，展示候选给用户等明确确认后再进入 Phase 2。\n- 仅在有多个疑似候选难以区分时，才对疑似候选调用 `smartbi search <operationKey> --profile <name> --verbose --agent` 以消歧。\n- `search` 的关键词检索不作为默认第一步，仅在需要关键词锚点补充定位或消歧时使用。\n- 若经消歧后仍存在多个候选 `operationKey`，必须先让用户选择，再进入 `describe`。\n- 选定唯一 `operationKey` 后进入 Phase 2（`describe`），见 `references/describe.md`。\n\n`search` 回退门禁（MUST）：\n\n- `smartbi search` 仅作补充回退，不得替代默认 `list` 主路径。\n- `search` 的 `<keyword>` 必须是短关键词，不得是整句业务问句。\n- 若 `search` 0 命中，优先回到 `list` 路径并结合 `--domain` / `--service` 收敛。\n\n检索字段门禁（MUST）：\n\n- `smartbi search` 检索候选时，必须至少包含：`--in description,operationKey,operationId`\n- 若用户额外指定其它 `--in` 字段，仍必须保证上述三字段必在\n\n反例 / 正例：\n\n```bash\n# 反例（整句问句，命中率低）\nsmartbi search \"大模型问句 交易记录数 交易金额 近3年\" --profile <PROFILE> --in description,operationKey,operationId --agent\n\n# 正例（拆解为短关键词，分批检索）\nsmartbi search \"交易记录\" --profile <PROFILE> --in description,operationKey,operationId --agent\nsmartbi search \"交易金额\" --profile <PROFILE> --in description,operationKey,operationId --agent\nsmartbi search \"近3年\" --profile <PROFILE> --in description,operationKey,operationId --fuzzy --agent\n```\n\n## 未命中处理（list 重排或 search 检索 0 候选时 MUST）\n\n一旦 0 候选，MUST：\n\n1. 向用户如实反馈。话术：\"在当前接口列表中未能匹配到与'<用户意图摘要>'直接对应的操作。\"\n2. 让用户提供更具体的业务关键词或场景说明，然后重新执行 Phase 1。\n3. MUST NOT 在 0 候选时强行猜测一个不相关的 `operationKey`，不得进入 `describe` / `call`。\n\n## 检索异常分支（LLM 友好）\n\n- `search` 0 个候选：先放宽检索（`--fuzzy`、调整 `--in` 字段、缩短关键词），再检索一次。若仍 0 候选 → 按上节「未命中处理」执行。\n- >5 个候选：优先追加 `--domain` / `--service` / `--limit 5` 收敛，再让用户选择。\n- 多候选未收敛：必须进入“用户选择模板”，不得跳过。\n\n## 默认策略：list 重排 → 消歧时 search 详查 → 用户确认\n\nDiscover 阶段默认执行：\n\n1. 先执行 `smartbi list --profile <name> --agent`。\n2. 将 `list` 返回的候选全集交给大模型做语义重排，产出 Top-N 候选 `operationKey`。\n3. 若候选唯一且语义明确匹配（意图与 summary 高度一致）→ 直接进入 Phase 2，在 Phase 3 `call` 前做一次性展示确认（\"准备调用 X，参数如下…\"）。不要继续 search，也不要单独停下来等用户确认。\n4. 若候选唯一但语义匹配度存疑 → 展示该候选，等用户明确确认后进入 Phase 2。\n5. 若存在多条疑似候选无法区分 → 仅对**难以区分的候选**调用 `smartbi search <operationKey> --profile <name> --verbose --agent` 获取详细信息以消歧。MUST NOT 对所有 Top-N 逐个 search。\n6. 消歧后仍有多条 → 按\"用户选择模板\"让用户确认。不得直接替用户拍板。\n7. 若 list 重排后**无候选匹配用户意图** → 按「未命中处理」执行。\n\n建议：\n\n- 若结果过大，优先先加 `--domain` / `--service` 再 `list`，避免一次性灌入过多噪音。\n- `search` 仅用于消歧，不应作为必经步骤对每个候选执行。\n- `search <operationKey> --profile <name> --verbose --agent` 的详细输出可提供比 `list` 摘要更丰富的判断依据，仅用于消歧场景。\n\n## 多候选时的用户选择模板\n\n当候选 `operationKey` 大于 1 时，按以下最小信息展示给用户选择（不要直接替用户决定）：\n\n```text\n我找到了多个候选 operationKey，请选择一个：\n1) <operationKey> | <method> <endpoint> | <summary>\n2) <operationKey> | <method> <endpoint> | <summary>\n3) <operationKey> | <method> <endpoint> | <summary>\n...\n请回复序号或完整 operationKey。\n```\n\n展示约束：\n\n- 每个候选至少包含：`operationKey`、`method`、`endpoint`、`summary`。\n- 默认最多展示前 5 个；若超过 5 个，先提示可追加筛选条件（如 `--domain` / `--service` / `--in` / `--limit`）再继续收敛。\n- 用户未明确选择前，不得进入 `describe` 或 `call`。\n\n## 首次环境（`init`）\n\n无有效配置时，须先完成初始化再执行 `list` / `search`。  \n完整安装、`init` 与配置要求见：`references/init.md`。\n\nFile v2.1.0:references/doc-index.md\n\n# Domain → 文档路径索引\n\n各 domain 的主要业务文档路径，供 Phase 2 文档加载时快速定位。\n**仅收录 `docs/specs/` 下已有独立文档的 domain**。\n\n> 本索引为 `SKILL.md` Phase 2 的补充参考，核心契约理解流程以 `SKILL.md` 为准。\n\n| domain | 入口文档 | 说明 |\n|--------|---------|------|\n| `datamodel` | `/docs/specs/datamodel/guide.md` | 数据模型查询 |\n| `tabularmodel` | `/docs/specs/tabularmodel/guide.md` | 表格模型管理 |\n| `datamining` | `/docs/specs/datamining/guide.md` | 数据挖掘（ETL / 因果图 / 作业流） |\n\n## datamodel\n\nMQL 查数接口相关文档：\n\n| 路径 | 说明 |\n|------|------|\n| `/docs/specs/datamodel/guides/query-data-by-mql.md` | MQL 取数使用指南（请求/响应/调用方式） |\n| `/docs/specs/datamodel/mql/mql.md` | MQL 语法总览（dims/metrics/from/filter/sort/with） |\n| `/docs/specs/datamodel/mql/common-types.md` | 公共类型（DataType/AggType/ParamValue/DataTable/ParquetResult） |\n| `/docs/specs/datamodel/mql/references/cal-measures.md` | 计算指标（CAL_MEASURE / mdxExpr） |\n| `/docs/specs/datamodel/mql/references/with-column.md` | 派生列（COLUMN / sqlExpr） |\n| `/docs/specs/datamodel/mql/references/with-measure.md` | 派生度量（MEASURE / ref + aggType） |\n\n## tabularmodel\n\n数据模型管理相关文档：\n\n| 路径 | 说明 |\n|------|------|\n| `/docs/specs/tabularmodel/mdl/mdl.md` | MDL 结构总览 |\n| `/docs/specs/tabularmodel/mdl/common-types.md` | MDL 公共类型 |\n| `/docs/specs/tabularmodel/mdl/references/measures.md` | 度量定义 |\n| `/docs/specs/tabularmodel/mdl/references/dimensions.md` | 维度定义 |\n| `/docs/specs/tabularmodel/mdl/references/columns.md` | 列定义 |\n| `/docs/specs/tabularmodel/mdl/references/views.md` | 视图定义 |\n| `/docs/specs/tabularmodel/mdl/references/relations.md` | 关系定义 |\n| `/docs/specs/tabularmodel/mdl/references/calc-members.md` | 计算成员 |\n| `/docs/specs/tabularmodel/mdl/references/named-sets.md` | 命名集 |\n| `/docs/specs/tabularmodel/mdl/references/metrics-sets.md` | 指标集 |\n| `/docs/specs/tabularmodel/mdl/references/parameters.md` | 参数定义 |\n| `/docs/specs/tabularmodel/mdl/references/pre-aggregates.md` | 预聚合 |\n| `/docs/specs/tabularmodel/mdl/references/obj-trees.md` | 对象树 |\n| `/docs/specs/tabularmodel/mdl/references/table-relationships.md` | 表关系 |\n\n## datamining\n\n数据挖掘相关文档：\n\n| 路径 | 说明 |\n|------|------|\n| `/docs/specs/datamining/etl/etl.md` | ETL 结构总览 |\n| `/docs/specs/datamining/etl/references/node-structure.md` | ETL 节点结构 |\n| `/docs/specs/datamining/etl/references/sql-node.md` | SQL 节点 |\n| `/docs/specs/datamining/etl/references/smartbi-query.md` | SmartBI 查询节点 |\n| `/docs/specs/datamining/etl/references/python-script.md` | Python 脚本节点 |\n| `/docs/specs/datamining/etl/references/jdbc-datasource.md` | JDBC 数据源 |\n| `/docs/specs/datamining/etl/references/jdbc-datatarget.md` | JDBC 数据目标 |\n| `/docs/specs/datamining/etl/references/link.md` | ETL 连接 |\n| `/docs/specs/datamining/etl/references/rules.md` | ETL 规则 |\n| `/docs/specs/datamining/etl/references/examples.md` | ETL 示例 |\n| `/docs/specs/datamining/jobflow/jobflow.md` | 作业流总览 |\n| `/docs/specs/datamining/jobflow/references/node-structure.md` | 作业流节点结构 |\n| `/docs/specs/datamining/jobflow/references/etl-job.md` | ETL 作业节点 |\n| `/docs/specs/datamining/jobflow/references/start-job.md` | 启动作业节点 |\n| `/docs/specs/datamining/jobflow/references/link.md` | 作业流连接 |\n| `/docs/specs/datamining/jobflow/references/rules.md` | 作业流规则 |\n| `/docs/specs/datamining/jobflow/references/examples.md` | 作业流示例 |\n| `/docs/specs/datamining/casualgraph/casualgraph.md` | 因果图总览 |\n| `/docs/specs/datamining/casualgraph/references/casual-node.md` | 因果节点 |\n| `/docs/specs/datamining/casualgraph/references/casual-link.md` | 因果连接 |\n| `/docs/specs/datamining/casualgraph/references/differences.md` | 因果图与作业流差异 |\n| `/docs/specs/datamining/casualgraph/references/top-level.md` | 顶级结构 |\n| `/docs/specs/datamining/casualgraph/references/examples.md` | 因果图示例 |\n\n## 使用方式\n\nPhase 2 `describe` 输出中，若 `description` 包含 `[说明](/docs/specs/...)` 形式的链接，直接用 `smartbi doc /docs/specs/... --profile <name> --agent` 加载。\n\n本索引用于在 `description` 中无显式链接时，根据 domain 推断可能存在的文档路径。加载时仍应使用 `smartbi doc` 验证路径可用性。\n\nFile v2.1.0:references/init.md\n\n# `init` / 安装与配置参考\n\n本文件为 **SmartBI CLI Skill** 的附属参考；流程性 MUST 以上级 `SKILL.md` 为准。\n\n**用途**：仅当 skill 的惰性预检（lazy preflight）触发时，用于完成标准安装、初始化与最小可用配置。\n\n## 安装与配置边界（MUST，禁止自由发挥）\n\n- **唯一允许的获取方式**：使用下方 **标准安装** 中的命令，通过 **npm** 全局安装 `**@smartbi/cli@latest`**，得到可在 PATH 中调用的 `smartbi`。\n- **最低版本要求**：`smartbi` 版本 MUST >= `2.0.0`（profile 命令族与 init/profile add 写盘的最低版本）。安装后必须执行 `smartbi --version` 验证版本。若版本低于 2.0.0，必须重新执行 `npm install -g @smartbi/cli@latest` 升级。\n- MUST NOT 使用 `yarn` / `pnpm` / `bun` / `npx` 等替代上述 **npm 全局安装** 作为本 skill 的默认安装路径（避免版本漂移与不可审计环境）。\n- MUST NOT 调用项目目录内随意脚本、其它产品 CLI、或路径/名称相近的可执行文件冒充 `smartbi`。\n- **配置文件唯一来源**：安装并执行 `smartbi init` 后，使用默认路径 `**~/.smartbi/config.yaml`**（或你明确使用且与 init 产物一致的 `--config` 路径）。MUST NOT 从全盘、用户主目录或其它产品中“找一个长得像的配置文件”复制或 `--config` 指向。\n\n## CLI 不存在时（MUST 先于一切）\n\n若执行 `smartbi` 时系统/shell 明确提示 **命令不存在**（例如 `command not found`、`'smartbi' 不是内部或外部命令`、`is not recognized as an internal or external command`、`ENOENT`、退出码 **127** 等），说明 **SmartBI CLI 尚未安装、未加入 PATH，或会话中途被卸载/破坏**。\n\n此时 MUST：\n\n1. **不要**继续在 skill 流程里尝试 `list`/`search`/`describe`/`call` 或猜测接口；不要换目录“盲找”可执行文件；不要用 `curl`/HTTP 等替代 CLI。\n2. **直接**按下方 **标准安装** 在终端**实际执行**安装命令，然后执行 `smartbi --version` 验证。\n3. 验证通过后按下方 **重装后恢复顺序** 处理 init 与配置，再回到业务 Phase。\n\n## 重装后恢复顺序（MUST）\n\n在 `**npm install -g @smartbi/cli@latest` 且 `smartbi --version` 已成功** 之后，按顺序执行；不得口述“已安装”、不得跳过 `--version`。\n\n1. **检查默认配置是否存在且可读**：`~/.smartbi/config.yaml`（或用户此前声明的 `--config` 路径）。\n2. **若文件不存在**：按 **生成配置文件** 与 **缺项时固定提问模板** 补齐配置。文件存在但解析失败时按具体错误处理，不能因“不确定”而覆盖配置。\n3. **若已有可读配置**：复用所选环境和已知信息，无需用户再次确认配置仍可信。用原任务所需的最小只读命令继续验证；失败按原因处理：鉴权错误只处理凭证，网络错误检查连通性，权限错误核对权限，不回退全量 init。`--dry-run`只能验证本地请求构造，不能证明服务器可达或令牌有效。\n4. 仅当满足 **Phase 0 退出标准** 后，才恢复 `list`/`search`/`describe`/`call` 等业务命令。\n\n## 标准安装\n\n```bash\nnpm install -g @smartbi/cli@latest\nsmartbi --version\n```\n\n要求：\n\n- `smartbi` 版本 MUST >= `2.0.0`\n- Node.js `>=18`\n- 默认配置文件：`~/.smartbi/config.yaml`\n\n## 生成配置文件\n\n分「首次配置」与「新增连接」两条路径。只补问缺失的地址或令牌；内部 profile 名不向普通业务用户提问。环境确定、执行规则与错误处理见 `references/profiles.md`。\n\n### 首次配置（无配置文件时）\n\n1. 按「缺项时固定提问模板」只收集缺失的连接信息（一次一个问题）。\n2. 执行 `smartbi init --server-type <sdk-server|smartbi> --base-url <地址> --token <令牌> [--profile <环境名>]`（不指定 `--profile` 时默认 `dev`）。默认字面量存储；若用户选择「环境变量」→ 改用 `--token-env <VAR>`（提醒用户该环境变量后续需保持可用）；「系统钥匙串」→ 使用当前 shell 的安全 stdin 管道传入令牌并带 `--token-keyring --token-stdin`，不要把字面令牌写进命令历史（裸 `--token-keyring` 会失败并提示补值方式）。\n3. CLI 原子写盘 `~/.smartbi/config.yaml`（该环境同时为默认环境）。stderr 的 \"prefer tokenEnv or keyring\" 提示属正常输出。\n4. 不向用户展示配置文件路径、内部 profile 名或内容；配置成功后继续原业务请求。需要区分多个连接时按 `references/profiles.md` 用服务器地址或业务名称说明。\n\n存储方式的说明已含于「缺项时固定提问模板」第二步的令牌问询话术内，写入后不要再重复询问。\n\n### 新增环境（已有配置文件时）\n\n1. 按「缺项时固定提问模板」只收集缺失的连接信息（一次一个问题）。\n2. 执行 `smartbi profile add <name> --server-type <sdk-server|smartbi> --base-url <地址> --token <令牌>`（默认环境保持不变）。用户选择「环境变量」→ 以 `--token-env <VAR>` 替代 `--token`（提醒该环境变量后续需保持可用）；「系统钥匙串」→ 使用当前 shell 的安全 stdin 管道传入令牌并带 `--token-keyring --token-stdin`，不要把字面令牌写进命令历史。\n3. 需要新环境成为默认时——先经用户确认，再执行 `smartbi profile set-default <name>`。\n4. 写入后继续原业务请求；需要告知连接状态时说“已连接到所选 SmartBI 地址”，不展示内部 profile 名或配置内容。存储方式的说明已含于令牌问询话术（「缺项时固定提问模板」第二步），写入后不要再重复询问。\n\n### 修复已有环境\n\n缺少地址才询问地址；地址已知而令牌不可用时仅补凭证。配置了tokenEnv或tokenKeyring不等于缺少令牌，先检查对应来源可用性，不打印凭证。环境变量缺失时恢复该变量，不擅自改为字面量存储。更新已有环境按当前CLI契约使用profile操作，保留其他环境和默认选择，不使用`init --force`。`profile add --force`会替换所选profile，不能假设它只更新令牌；执行前核对需要保留的地址、服务器类型及其他设置，不可静默丢失自定义配置。\n\n### 配置字段说明\n\n- **`baseUrl`**：SmartBI 或 SDK Server 的根 URL。用户提供 SmartBI 地址（如 `http://127.0.0.1:8080/smartbi`）→ `serverType: smartbi`；用户提供 SDK Server 地址（如 `http://127.0.0.1:8086`）→ `serverType: sdk-server`。\n- **`token`**：SmartBI 个人访问令牌（登录 SmartBI 后，在「个人中心 → 我的设置 → 个人访问令牌」中新建）。token 存储三选一（schema 互斥，只能配其一）：`token` 字面量（默认）/ `tokenEnv`（环境变量名）/ `tokenKeyring: true`（系统钥匙串，service=smartbi-cli、account=profile 名）。\n- **`serverType`**：只能为 `sdk-server` 或 `smartbi` 两个值之一，不得使用其他大小写或命名变体（如 `smartbi-server`、`sdk_server` 等）。\n\n约束：\n- 不得臆造配置值；缺失时必须先向用户提问并等待补齐。\n- 用自然语言提问，不要暴露 `baseUrlEnv` / `tokenEnv` 等配置键名；如需提及更安全的存储方式，用「环境变量 / 系统钥匙串」的口语表述（存储说明见「缺项时固定提问模板」第二步）。\n- 写入后不向普通业务用户展示配置文件路径或内部 profile 名；直接继续原业务请求。\n- **内部 profile 名**：首次配置省略 `--profile`，由 CLI 使用默认值；新增连接按 `references/profiles.md` 在内部生成不冲突的名称，不为此单独提问。\n\n### 缺项时固定提问模板（MUST）\n\n当所选环境缺少必要连接信息时，只补问尚未确认的项目；已知项跳过。凭证来源不可用按上方“修复已有环境”处理。**一次只问一个问题**，以下模板按实际缺项选择，不要求每次从第一步重新开始：\n\n**第一步——先问地址：**\n\n```text\n继续执行前需要配置服务器连接。是否连接 SmartBI 官网体验中心 https://cloud.smartbi.com.cn/smartbi？如果要连接自己的环境，请提供 SmartBI 地址。\n```\n\n- 用户提供地址 → `serverType` 直接设为 `smartbi`（无需检测 URL 格式），写入 `baseUrl`\n- 无现成地址、用户只说连接 SmartBI 时第一问就按上方话术提供体验中心选项；确认后使用 `https://cloud.smartbi.com.cn/smartbi`，`serverType` 设为 `smartbi`。已有地址或配置时不重复推荐；确认前不写入配置或发起连接。\n- 用户明确说\"没有 SmartBI 地址\"、\"不知道\"、\"无法提供\" → 使用以下**精确话术**回复：\n  \"了解。也可以使用 SDK Server 地址代替（如 http://127.0.0.1:8086）。请问有 SDK Server 地址吗？\"\n  - 用户提供 SDK Server 地址 → `serverType` 设为 `sdk-server`\n  - 用户仍无法提供 → 暂停，等待用户找到地址后再继续\n- 高级用户可直接说 `sdkserver: http://xxx` → `serverType` 直接设为 `sdk-server`，跳过上述流程\n- 两项都拿到后，按上方「生成配置文件」流程在后台生成配置，不向用户展示配置细节\n\n**第二步——再问令牌：**\n\n```text\n已记录服务器地址。请提供 SmartBI 个人访问令牌（登录 SmartBI 后，在「个人中心 → 我的设置 → 个人访问令牌」中新建）。令牌默认直接存进配置；如对安全有更高要求，也可以改用「环境变量」或「系统钥匙串」存储。\n```\n\n在你补齐前，我会先暂停，不会继续调用 `smartbi` 命令。\n\n**内部命名（不向普通业务用户提问）：** 首次配置省略 `--profile`；CLI 的默认 profile 名为 `dev`，仅用于命令和配置。用户明确要求新增连接时，按 `references/profiles.md` 从已提供的业务名称或连接顺序生成不冲突的内部名称。客户无需理解或设置该名称。\n\n## 最小可用配置（示例）\n\n```yaml\nprofile: dev\nprofiles:\n  dev:\n    serverType: sdk-server\n    baseUrl: \"http://127.0.0.1:8086\"\n    token: \"your-api-token\"\n    allowPlainToken: true\n    timeoutMs: 300000\n    # 可选替代（三选一，勿与 token 并存）：\n    # tokenEnv: SMARTBI_TOKEN_DEV\n    # tokenKeyring: true\nregistry:\n  source: remote\n  checkIntervalSeconds: 300\n```\n\n## Phase 0 退出标准\n\n- `smartbi --version` 可执行；\n- 所选profile的地址与服务器类型已确定，且所选凭证来源（token/tokenEnv/tokenKeyring之一）可用；不要求环境变量或钥匙串模式另配字面token。\n- 配置可用于后续 `list/search/describe/call`。\n\nArchive v2.0.0: 15 files, 51279 bytes\n\nFiles: README.md (5671b), references/call.md (8995b), references/describe.md (4042b), references/discovery.md (10138b), references/doc-index.md (4622b), references/init.md (9322b), references/profiles.md (4181b), references/rhino-template.md (15435b), references/strategy.md (4013b), scenarios/push-message.md (5353b), scenarios/schedule-task.md (18051b), scripts/inject-script.mjs (3153b), skill-card.md (3200b), SKILL.md (17624b), _meta.json (130b)\n\nFile v2.0.0:SKILL.md\n\n---\nname: smartbi-cli\ndescription: Smartbi BI 业务操作入口：AI 对话分析（大模型问数、智能体、知识库/知识图谱构建与训练、数据解释）、数据查询（MQL/DuckDB 取数、指标统计、字段发现）、数据建模（维度/指标/计算成员/命名集管理）、数据源管理（JDBC连接、Schema 与表同步、元数据刷新）、定时任务与 ETL（计划调度、作业流、因果图）、消息推送（企微/钉钉/飞书/邮件/系统消息）、资源与权限管理（目录树、用户/角色/组）。通过 @smartbi/cli 发现与调用 API。\n---\n\n# Smartbi CLI\n## 流程概览\n- **Step 0 — Scenario Router**（入口）：先看用户问句是否命中已有场景。命中 → 加载 `scenarios/` 下对应文件执行；未命中 → 进入 Part 1。\n- **Part 1 — Core CLI Workflow**（骨架）：任何 `domain.operationId` 的发现→理解→调用→排错流程一致。\n- **Part 2 — Scenario Guides**（场景）：高频业务场景的端到端模板，按需加载。\n- **`references/`**（参考）：各 Phase 的详细流程、策略模板与文档路径索引。\n\n## Triggers（触发条件）\n\n当用户描述 **BI 业务动作 + 业务对象**，但未显式给出接口名/operationKey（例如\"帮我训练模型资源A\"\"基于模型资源A分析去年销售额\"）时触发。\n\n当用户问及 BI 相关业务操作（分析、训练、指标查询、报表/问句类需求、定时计划任务等）时触发本 skill。触发后进入 Step 0 路由判断。\n\n`operationKey` 格式为 `${domain}.${operationId}`（如 `demo.createOrder`、`aichat.getAgentItems`）。`list` 输出结果可直接复制作为 `describe`/`call` 的参数。\n\n---\n\n## 全局约定（所有路径共用）\n\n以下规则适用于 **所有** 执行路径（Part 1 通用流程和 Part 2 场景流程）。先读完全局约定，再进入 Step 0 路由判断。\n\n### CLI 安装与配置\n\n- MUST 仅通过 **npm 全局安装** 获得可执行命令 `smartbi`：`npm install -g @smartbi/cli@latest`，随后 `smartbi --version` 验证版本 **≥ 2.0.0**，并执行 `smartbi profile list --help` 确认 profile 命令族可用。\n- MUST NOT 使用 `yarn` / `pnpm` / `bun` / `npx` 或其它程序代替上述 `smartbi`。\n- 初始化 MUST：由 CLI 全参数生成配置：`smartbi init --server-type <sdk-server|smartbi> --base-url <url> --token <token> [--profile <name>]`；token 以字面量存储，细节见 `references/init.md`。\n- 配置文件路径：默认 **`~/.smartbi/config.yaml`**，或用户在 init 后 **明确指定** 的 `--config <path>`。MUST NOT 在系统中猜测或套用其它文件。config.yaml 可包含多个环境（profiles），默认环境由 `profile:` 字段指定；多环境的选择、配置与错误处理见 `references/profiles.md`。\n- CLI 不存在时的处理流程见 `references/init.md`「标准安装」。\n\n### 环境选择（多 profile）\n\n任务开始时确定本次操作环境并**告知一次**（\"本次操作环境：`<name>`\"）：用户指定环境/客户时按 `references/profiles.md` 匹配或新建，未指定时用默认环境（config.yaml 的 `profile:` 字段）。\n\n环境确定后，**所有** `smartbi` 命令（`list`/`search`/`describe`/`call`/`doc`）**一律带 `--profile <name>`**。\n\n完整规范（确定/告知/配置/错误处理/版本约束）见 `references/profiles.md`。\n\n### 首次配置\n\n在首次运行 `smartbi`（任意子命令）时，若检测到无配置文件或 `baseUrl`/`token` 缺失，MUST 分步向用户索要（一次一个问题），全部获取后后台生成配置文件：\n\n1. **先问地址**：用户提供 Smartbi 地址 → `serverType: smartbi`；用户无法提供 → 问 SDK Server 地址 → `serverType: sdk-server`；均无法提供 → 暂停。\n2. **再问令牌**：问令牌时一并说明存储方式（仅一句）：\"请提供 Smartbi 个人令牌（可登录 Smartbi，在个人中心申请）。令牌默认直接存进配置；如对安全有更高要求，也可以改用「环境变量」或「系统钥匙串」存储。\"用户提供后，若环境名仍未确定，最后问名字（\"不填则默认 dev\"）。若用户选择其他存储方式，步骤 3 按其选择生成。\n3. 执行 `smartbi init --server-type <sdk-server|smartbi> --base-url <地址> --token <令牌> [--profile <环境名>]`（不指定 `--profile` 时默认 `dev`；CLI 写盘 `~/.smartbi/config.yaml`，该环境同时为默认环境）。若用户选择其他存储方式：「环境变量」→ 以 `--token-env <VAR>` 替代 `--token`；「系统钥匙串」→ agent 无交互终端，必须用管道喂令牌：`echo -n '<令牌>' | smartbi init --server-type <sdk-server|smartbi> --base-url <地址> --token-keyring --token-stdin [--profile <环境名>]`（裸 `--token-keyring` 在无 TTY 下会直接失败）。\n4. 告知本次操作环境：\"本次操作环境：`<name>`\"。\n\n`serverType` 取值约束（MUST）：只能是 `sdk-server` 或 `smartbi`，不得使用其他变体。\n\n新增环境（追加写入、不动默认环境）的流程见 `references/profiles.md`「配置三要素流程」。详细提问模板见 `references/init.md`。\n\n### 参数构造规范\n\n构造 `smartbi call` 的请求体时，按以下优先级确定取值来源：\n1. **用户输入或上下文已知事实**：对话中已明确提供的值\n2. **文档内容**（优先）：字段业务含义、合法枚举值、字段间依赖、完整使用示例（通过 `smartbi doc` 加载）\n3. **`requestBodySchema`**（兜底）：文档不可用或未覆盖时使用\n4. **`callParameterPlan`**：CLI 标志映射\n5. **`suggestedCall`**：仅供参考的命令模板，不应直接复用其占位值\n6. **仍无法确定的字段**：向用户确认，不得自行编造\n\n构造 call 参数时，应主动获取 `docs/specs/` 下的业务文档作为理论依据；文档不可用或未覆盖时，以 schema 定义兜底。已加载路径不重复加载。\n\n**请求体文件规范（MUST）**：\n- JSON 请求体必须使用 `-d @file.json`（避免跨 shell/OS 转义差异）\n- MUST NOT 使用内联 JSON（如 `-d '{\"k\":\"v\"}'` 或 `-d \"{\\\"k\\\":\\\"v\\\"}\"`）\n- 为本轮 `call` **新建**的 JSON 文件：在 `smartbi call` 流程结束后 **MUST** 删除；不得删除用户自带的 `@` 文件\n- 临时文件写入系统临时目录或仓库内已 `.gitignore` 的路径，降低误提交风险\n- 写入请求体前，若有 Rhino 脚本等需转义的内容，MUST 使用 `scripts/inject-script.mjs` 工具，禁止手工转义\n\n### 子任务机制\n\n执行 `call` 前，若某些参数值依赖其他 smartbi 操作（如先查资源 ID、先创建关联对象），MUST 以子任务方式自动完成，**不得让用户手动查找**。\n\n- 子任务执行路径：**绕过 Step 0 场景匹配**，直接进入 Part 1 Phase 1→3 通用流程（`list` → `describe` → `call`），完成前置操作后把结果填回父 call。\n- 退出硬限制（任一触发即停止自动化，执行用户升级流程，详见 `references/call.md`「前置条件与子任务」）：\n  - **深度上限**：嵌套深度 ≤ 3（原始 call 为深度 0）\n  - **数量上限**：每个父 call 的直接前置子任务 ≤ 5 个\n  - **去重**：同一 `operationKey` + 相同参数意图，同一调用链内已完成的前置操作不再重复发起\n- 子任务失败时向用户报告原因并暂停当前 call。\n\n### 重试与幂等\n\n- **写请求**（POST / PUT / PATCH / DELETE）：仅当 `--idempotent` 指定或 describe 元数据 `idempotent === true` 时才可自动重试，否则最多尝试 1 次\n- **可触发的 HTTP 状态重试**（在剩余次数内）：429 / 502 / 503\n- **最大尝试次数**：允许重试时最多 3 次（含指数退避与抖动）\n\n### 输出格式（Output Contract）\n\n每次调用完成后，按以下固定顺序输出：\n1. `operationKey`\n2. 最终执行命令\n3. 关键结果（`status`/`tid`/核心业务字段）\n4. 若失败：单行修复建议 + 下一条可执行命令\n\n### 参考文件按需加载\n\n默认只使用 SKILL.md 本摘要。需要模板/字段映射/检查清单/异常分支时，以及需要加载接口关联文档时，才读取 `references/` 下的对应文件或执行 `smartbi doc`。\n\n# Part 1: Core CLI Workflow（骨架流程）\n\n以下四个 Phase 定义了从用户意图到 API 调用的完整流程。\n通用参数构造、子任务等底层规则在 [全局约定](#全局约定所有路径共用) 中定义，这里只描述各阶段的执行顺序。\n\n## Phase 0 — 惰性预检\n\n默认不强制在每个新会话先检查安装/配置。直接进入 Phase 1（`list` / discover）。\n\n当**任意一次**实际执行 `smartbi`（任意子命令）时，若出现下列情况，才按 [全局约定 · CLI 安装与配置](#cli-安装与配置) 补齐与排查：\n\n- **CLI 不存在**（`command not found` / 退出码 127 等）→ 立即停止，按标准安装流程处理\n- **鉴权/凭证**：`AUTH_FAILED` / `FORBIDDEN` / `PROFILE_NOT_FOUND`\n- **服务不可达**：`NETWORK_TIMEOUT` / `NETWORK_ERROR` / `UPSTREAM_UNAVAILABLE`\n- **配置缺失或不合法**：`INVALID_ARGUMENT` 且 hint 指向 `Config file not found`\n\n其余错误跳过惰性预检，由 Phase 4 诊断处理。\n\n## Phase 1 — Discover\n\n```\nsmartbi list --profile <name> --agent\n```\n\n1. 默认先执行 `smartbi list --agent`，将候选全集交给大模型做语义重排。\n2. 若结果过大，先加 `--domain` / `--service` 再次 `list` 收敛。\n3. 若候选唯一且语义明确匹配（用户意图与接口 summary 高度一致，无歧义）→ 直接进入 Phase 2，在 Phase 3 `call` 前向用户展示\"准备调用 `<operationKey>`，参数如下…\"做一次性确认。不要继续 search，也不要单独停下来等用户确认 operationKey。\n4. 若候选唯一但语义匹配度存疑（摘要与意图不完全对应）→ 展示该候选给用户，等用户明确确认后进入 Phase 2。\n5. 若存在多条疑似候选无法区分 → 仅对难以区分的候选调用 `smartbi search <operationKey> --verbose --agent` 获取详细信息以消歧。MUST NOT 对所有 Top-N 逐个 search。\n6. `search` 的关键词检索仅作为补充回退手段（例如用户提供了明确关键词锚点时），不作为默认第一步。\n\nPhase 1 定位约束（MUST）：\n- MUST 默认使用 `list` 路径定位接口，不得先走 `search` 作为主路径。\n- `search --verbose` 仅用于消歧，不得对每个候选盲目执行。\n- 存在多候选时 MUST 等在候选阶段让用户选择，不得替用户拍板。唯一且明确匹配时可直接进入 Phase 2（在 Phase 3 call 前做一次性确认）。\n\n细节见 `references/discovery.md`。\n\n## Phase 2 — Contract\n\n```\nsmartbi describe <operationKey> --profile <name> --agent\n```\n\n消费字段：`callParameterPlan`、`requestBodySchema`、`consumes/produces`、`suggestedCall`。\n\n### 文档加载（优先获取，不可用时兜底）\n\n`describe` 完成后，应主动尝试加载关联文档作为理解接口语义的理论依据。\n\n**步骤 1 — 识别文档来源**：\n\n| 维度 | 识别方式 | 示例 |\n|------|----------|------|\n| `description` 中的链接 | 扫描 `describe` 输出的 `description` 字段中的 Markdown 链接 | `[MQL详情](/docs/specs/datamodel/mql/mql.md)` |\n| `requestBodySchema` 中的链接 | 沿 `$ref` 链查找被引用 schema 的 `description` 中的链接 | schemas.yaml 中组件定义的 description |\n| domain 推断 | 根据 `operationKey` 所属 domain 推断相关文档目录 | `createDataSet` → `docs/specs/tabularmodel/` |\n| 数据类型推断 | 根据请求体中涉及的核心数据类型推断参考文档 | 含 `DataSetMeasure` → `docs/specs/tabularmodel/mdl/references/measures.md` |\n| `llmBrief` / `summary` 中的引用 | 检查 describe 输出其他字段中的文档引用 | — |\n\n**步骤 2 — 加载与穿透**：对识别到的文档路径，执行 `smartbi doc <path> --agent`，stdout 纳入上下文。文档中的引用链接继续递归加载，硬限制：\n- **深度 ≤ 3**（初始文档为深度 0），**去重**（已加载路径不重复）\n- 绝对路径 `/...` → 直接传给 `smartbi doc`；相对路径 → 基于当前文档路径解析；外部 URL → WebFetch\n\n**步骤 3 — 文档优先，schema 兜底**：按 [全局约定 · 参数构造规范](#参数构造规范) 的优先级规则取值。文档有定义时以文档为准，不可用时以 schema 兜底。\n\nMUST NOT 忽略链接或自行猜测文档内容。细节见 `references/describe.md`。\n\n## Phase 3 — Execute\n\n```\nsmartbi call <operationKey> -d @body.json --profile <name> --agent\n```\n（`<name>` 为本次操作环境；所有命令一律带 `--profile`，见全局约定「环境选择」）\n\n- 参数构造、请求体格式、临时文件清理等底层规则见 [全局约定 · 参数构造规范](#参数构造规范)\n- 前置参数依赖的子任务机制见 [全局约定 · 子任务机制](#子任务机制)\n- 重试策略与幂等门控见 [全局约定 · 重试与幂等](#重试与幂等)\n- 复杂参数组合策略见 `references/strategy.md`\n\n细节见 `references/call.md`。\n\n## Phase 4 — Diagnose\n\n失败后 `smartbi describe <operationKey> --agent`；仍有契约歧义再加 `--include-raw-schema`。\n诊断策略参考 `references/strategy.md`。\n\n# Part 2: Scenario Guides（场景索引）\n\n**入口先走 Step 0 — Scenario Router。** 将用户问句与下表比对：\n- 命中 → 加载对应场景文件，按场景流程执行\n- 未命中 → Part 1 通用流程\n- 加载后场景判定不适用 → 回退 Part 1\n\n| 场景 | 关键触发词 | 场景文件 |\n|------|-----------|---------|\n| S1 定时计划任务 | 每天/每周/定时/cron + 查询/统计/推送/ETL | `scenarios/schedule-task.md` |\n| S2 消息推送 | 发送/推送/通知 + 企微/钉钉/飞书/邮件 | `scenarios/push-message.md` |\n\n触发词仅用于快速匹配；精确判定由场景文件 `## 触发` 节负责。仅命中时才加载对应文件。\n\n场景随 OpenAPI 的扩展可持续追加，每个新场景须经过端到端验证后再入库。\n\n> **开发者**：新增场景操作指南见 `docs/guide/smartbi-cli-新增场景操作手册.md`。\n\n---\n\n## 常见错误速查\n\n### CLI / 连接类\n\n| 错误 | 原因 | 处理 |\n|------|------|------|\n| `command not found` (127) / `is not recognized` | 未安装 CLI | → Phase 0 标准安装 |\n| `AUTH_FAILED` (401) | token 无效或已过期 | 让用户重新申请令牌；用 `smartbi profile show <name>` 诊断凭证来源后更新配置 |\n| `FORBIDDEN` (403) | 用户无权限执行该 operation | 检查 `x-funcPerm` 要求，确认用户角色 |\n| `Plain token is disabled by allowPlainToken=false`（AUTH_FAILED） | 字面量 token 被 `allowPlainToken: false` 拦截（配置通常被外部改动过） | 用 `smartbi profile add <name> --server-type <…> --base-url <…> --token <新令牌> --force` 重写该 profile（已存在需 `--force`）；勿用 `init --force`（会整份重建配置、影响其他环境） |\n| `KEYRING_UNAVAILABLE` | 配置了 `tokenKeyring: true` 但系统钥匙串不可用（无头/无桌面会话） | 改用字面量 token（重新 `init`/`profile add --token`），或改用 tokenEnv |\n| `NETWORK_TIMEOUT` / `NETWORK_ERROR` | 服务不可达 | 检查 `baseUrl` 是否正确，网络是否通 |\n| `UPSTREAM_UNAVAILABLE` (503) | Smartbi 服务未启动或过载 | 确认服务状态后重试 |\n| `Config file not found` (INVALID_ARGUMENT) | 配置文件不存在 | → Phase 0 init 流程 |\n| `Config file is invalid`（INVALID_ARGUMENT，附逐条 `- 路径: 原因`） | 配置内容不合法 | 按逐条摘要修正字段，或重新 init 生成 |\n| `PROFILE_NOT_FOUND` | 指定的环境不存在 | `smartbi profile list` 列出现有环境让用户选择，或按 `references/profiles.md` 新建 |\n| `SpecRejected` / `path not in spec` | sdk-server 路径前缀错误 | 确认 `serverType` 与 `baseUrl` 配置一致 |\n\n### API 业务类\n\n| 错误 | 原因 | 处理 |\n|------|------|------|\n| `选择字段不能为空` | dims/metrics 空或不匹配 | 先调 `getDataModelTrees` 确认字段 label |\n| `Failed to obtain two-dimensional data` | `showDataTable: true` 不兼容某些模型 | 改为 `false`，走 s3Url Parquet |\n| `unsupported literal in MQL filter` | MQL `:param` 占位符不兼容 | 改为字面量 `'值'`，内部单引号双写 |\n| `connector.remoteInvoke` 报错 | RMI 签名不匹配 | 调 `getTaskScriptEnv` 查看可用方法 |\n| HTTP 500 / `Internal Server Error` | 服务端异常 | 记录 `tid`，用 `describe --include-raw-schema` 排查请求体 |\n\n---\n\n## 参考（按需加载）\n\n| 文件 | 内容 |\n|------|------|\n| `references/init.md` | 安装与配置 |\n| `references/profiles.md` | 多环境（profile）规范：确定/告知/配置/错误处理 |\n| `references/discovery.md` | Phase 1 接口发现 |\n| `references/describe.md` | Phase 2 契约理解 |\n| `references/call.md` | Phase 3 执行调用 |\n| `references/strategy.md` | 策略与常见模式（Phase 3 构造复杂参数或 Phase 4 诊断时加载） |\n| `references/rhino-template.md` | MQL 取数 Rhino JS 模板（定时任务场景共用） |\n| `references/doc-index.md` | domain → 文档路径索引（Phase 2 文档加载时参照） |\n| `scenarios/schedule-task.md` | S1 定时计划任务 |\n| `scripts/inject-script.mjs` | 脚本注入工具：将多行 JS 文件自动 JSON 转义后注入请求体 |\n\nFile v2.0.0:README.md\n\n# Smartbi CLI Skill\n\n让**任意 AI agent**（Cursor、Claude Code、Copilot 等）通过 `@smartbi/cli` npm 工具发现并调用 Smartbi 全部 OpenAPI 能力。\n\n## 目标\n\n```\n          ┌──────────┐\n          │ 任意 Agent │\n          └─────┬────┘\n                │ 自然语言意图\n                ▼\n┌───────────────────────────────┐\n│   smartbi-cli skill           │\n│                               │\n│  意图 → operationKey → call   │\n│                               │\n│  定时计划任务 / ...           │\n└───────────────┬───────────────┘\n                │ smartbi call\n                ▼\n┌───────────────────────────────┐\n│   Smartbi OpenAPI             │\n│   (datamodel / scheduletask   │\n│    tabularmodel / aichat ...) │\n└───────────────────────────────┘\n```\n\n**一句话**：一个 skill 文件 + 一个 npm 包 = 任意 agent 获得 Smartbi 全平台能力。\n\n## 架构\n\n```\nSKILL.md                         ← 入口（agent 加载）\n│\n├─ Part 1: Core CLI Workflow     ← 骨架，所有 OpenAPI 调用通用\n│   Phase 0  惰性预检\n│   Phase 1  Discover  (smartbi list)\n│   Phase 2  Contract  (smartbi describe + doc)\n│   Phase 3  Execute   (smartbi call)\n│   Phase 4  Diagnose  (失败诊断)\n│\n├─ Part 2: Scenario Guides（索引）  ← 按意图路由，命中后加载对应文件\n│\n├─ scenarios/                    ← 场景文件（每个独立验证）\n│   ├─ schedule-task.md          S1 定时计划任务\n│   └─ push-message.md           S2 消息推送\n│\n└─ references/                   ← 参考手册（按需加载）\n    ├─ init.md                   安装与配置\n    ├─ profiles.md               多环境（profile）规范\n    ├─ discovery.md              Phase 1 详细流程\n    ├─ describe.md               Phase 2 详细流程\n    ├─ call.md                   Phase 3 详细流程\n    ├─ strategy.md               策略与常见模式\n    ├─ rhino-template.md         MQL 取数 Rhino JS 模板（共用）\n    └─ doc-index.md              domain → 文档路径索引\n```\n\n## 当前能力\n\n| 场景 | 能力 | 状态 |\n|------|------|------|\n| **通用 OpenAPI 调用** | `smartbi list` → `describe` → `call` 全流程，覆盖任意 `domain.operationId` | 完整 |\n| **S1 定时计划任务** | 创建调度计划 + Rhino JS 脚本任务 + 邮件/消息推送（API schema + Rhino 模板已确认） | 完整 |\n\n> 新场景须经过端到端验证后才可入库。\n\n## 依赖\n\n- **npm 包**：`@smartbi/cli >= 2.0.0`（`npm install -g @smartbi/cli@latest`）\n- **外部 skill**：**零**。本 skill 自闭环，不依赖任何其他 skill。\n\n## 使用说明\n\n### 安装\n\n```bash\nnpm install -g @smartbi/cli@latest\nsmartbi --version   # 确认 >= 2.0.0\nsmartbi init --server-type <sdk-server|smartbi> --base-url <url> --token <token>\n                    # 全参数生成 ~/.smartbi/config.yaml\n```\n\n### 在 Agent 中使用\n\n1. 将本目录放到 agent 的 skills 路径下（如 Cursor 的 `.cursor/skills/`、Claude Code 的配置的 skills 目录等）\n2. Agent 加载 `SKILL.md` 后自动获得以下能力：\n   - 发现接口：用户描述需求 → `smartbi list --agent` 语义匹配 → 得到 `operationKey`\n   - 理解契约：`smartbi describe <key> --agent` → 加载文档 → 理解参数\n   - 执行调用：`smartbi call <key> -d @body.json --agent` → 返回结果\n   - 定时任务：识别定时意图 → 生成 Rhino JS → 创建 task + schedule → 启用\n\n### 场景路由\n\nAgent 根据用户问句自动选择场景：\n\n```\n用户问句\n  ├─ 有「每天/每周/定时/几点」? \n  │   └─ 是 → S1 定时计划任务（生成 task + schedule；是否推送由语义决定）\n  └─ 否 → 走 Part 1 通用流程\n```\n\n## 如何新增 Scenario\n\n1. 新建 `scenarios/<name>.md` — 自描述文件：触发条件 + 请求体模板 + 注意事项\n2. 通过实际 API 调用端到端验证（Python 脚本或 smartbi call）\n3. `SKILL.md` Part 2 索引表加一行\n4. 如有新的共享代码模板 → `references/` 下新增\n\n每个新场景必须经过端到端验证后才可入库，不添加未验证的 placeholder。\n\n## 示例对话\n\n**即时查询**：\n> 用户：帮我查一下上个月各分支行的贷款余额\n> Agent：找到 `datamodel.queryDataByMql`，确认模型字段后执行查询，返回 s3Url + rowCount\n\n**定时计划任务**：\n> 用户：每天 9:00 发送保额大于 20 万的保单数据到邮箱\n> Agent：创建 Rhino JS 脚本（MQL 取数 + 过滤 + HTML 格式化）→ 创建任务 → 创建计划（DAY, 9:00, MAIL）→ 启用\n\n## 文件清单\n\n```\nsmartbi-cli/\n├── README.md                    ← 本文件\n├── SKILL.md                     ← skill 入口（agent 加载）\n├── scenarios/                   ← 已验证场景\n│   ├── schedule-task.md         S1 定时计划任务\n│   └── push-message.md          S2 消息推送\n└── references/                  ← 参考手册\n    ├── init.md\n    ├── profiles.md\n    ├── discovery.md\n    ├── describe.md\n    ├── call.md\n    ├── strategy.md\n    ├── rhino-template.md        MQL 取数 Rhino JS 模板（共用）\n    └── doc-index.md\n```\n\nFile v2.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn7bgapafkp5xjwz4xafxyynzx87dnfb\",\n  \"slug\": \"smartbi-cli\",\n  \"version\": \"2.0.0\",\n  \"publishedAt\": 1789007016564\n}\n\nFile v2.0.0:references/call.md\n\n# `call` 参考\n\n本文件为 **Smartbi CLI Skill** 的附属参考；流程性 MUST 以上级 `SKILL.md` 为准。\n\n**用途**：Phase 3（Execute）— 在已明确 `operationKey` 与参数来源的前提下发起 HTTP 调用。参数与 body **必须与** `describe` 中的 `callParameterPlan` 与 `requestBodySchema` 一致；未知字段值须先向用户确认。\n\n自动化流程默认优先使用 `--agent`；仅在下游明确要求单行 JSON 时使用 `--json`。\n\n## 参数构造依据（文档优先，schema 兜底）\n\n构造每个字段的值时，按以下优先级确定取值来源：\n\n1. **用户输入或上下文已知事实**：用户在对话中已明确提供的值\n2. **文档内容**（优先）：Phase 2 加载的文档中定义的合法枚举值、字段语义、组合约束、完整示例\n3. **`requestBodySchema`**（兜底）：文档不可用或未覆盖时，以 schema 的字段类型约束、必填/可选为准\n4. **`callParameterPlan`**：CLI 标志映射\n5. **`suggestedCall`**：仅供参考的命令模板，不应直接复用其占位值\n\n文档有定义时以其为准，文档未覆盖时以 schema 为准；不应仅看字段名猜测语义或编造值。\n\n## 命令形式\n\n```bash\nsmartbi call <operationKey> [选项...] [--json|--yaml|--agent]\n```\n\n## 常用选项\n\n\n| 选项                      | 说明                          |\n| ----------------------- | --------------------------- |\n| `--profile <name>`      | 环境名；**所有命令一律带**（环境选择见 `references/profiles.md`） |\n| `-d, --data <json>`     | JSON 请求体；**必须**使用 `-d @file.json`（将 JSON 写入文件后传入 @ 路径） |\n| `-F, --form <k=v\\|k=@file>` | multipart 字段（可重复）      |\n| `--path <k=v>`          | 路径参数（可重复）                   |\n| `--query <k=v>`         | 查询参数（可重复）                   |\n| `--header <k=v>`        | 请求头（可重复）                    |\n| `--timeout <ms>`        | 超时（毫秒）                      |\n| `--dry-run`             | 仅打印请求预览，不发送网络请求             |\n| `--idempotent`          | 允许对**写请求**按策略自动重试（须业务上可幂等）  |\n| `--stream`              | 流式响应（如 SSE）                 |\n| `--stream-format <fmt>` | 流式解析提示（保留/按实现）              |\n| `--max-events <n>`      | 流式最多处理事件/块数                 |\n| `-o, --output <path>`   | 二进制响应写入文件                   |\n| `--stdout`              | 二进制响应写入标准输出                 |\n| `--refresh`             | 强制刷新 registry 缓存            |\n| `--json` / `--yaml` / `--agent` | 与 list/search/describe 相同约定 |\n| `--config <path>`       | 配置文件路径                      |\n\n\n## 与 `describe` 的对应关系\n\n- `--path` / `--query` / `--header`：与 `callParameterPlan` 中各分组的 `name`、`cli` 一致。\n- `-d`：在 `body.kind === json` 且 `consumes` 含 JSON 类类型时使用；**必须**使用 `-d @file.json`，JSON 内容须满足 `requestBodySchema`。\n- MUST NOT 使用内联 JSON（如 `-d '{\"k\":\"v\"}'` 或 `-d \"{\\\"k\\\":\\\"v\\\"}\"`）。\n- `-F`：在 `body.kind === multipart` 时使用；文件字段遵循 schema 中 `format: binary` 等约定。\n- **无 body**：`body.kind === none` 时不要强行带 `-d`/`-F`（除非 OpenAPI 另有约定且已在 describe 中体现）。\n\n## 临时请求体文件（`-d @data.json` 等）的生命周期（MUST）\n\n- 由代理/自动化**为本轮 `call` 新建**的 JSON 文件（例如 `data.json`、`*-body.json`）：在 **`smartbi call` 整段流程结束**后（含成功、失败、dry-run、重试耗尽）**MUST** 删除该文件，除非用户**明确要求保留**（例如留档审计）。\n- MUST NOT 在任务收尾后长期遗留含业务参数或可能含敏感字段的临时 JSON；优先写入系统临时目录，或仓库内已 `.gitignore` 的路径，降低误提交风险。\n- 若 `-d @` 指向的是**用户已有文件**（非本轮创建），MUST NOT 擅自删除。\n\n## 成功响应中可观测字段\n\n自动化场景下，除 HTTP 语义外，成功 JSON 中常关注：\n\n- `status`：HTTP 状态码\n- `tid`：追踪标识（若存在）\n- `data`：业务载体；失败或业务错误时可能含 `data.success`、`data.error`（与 Phase 4 诊断字段一致）\n\n具体形状以 `smartbi-cli/schemas/smartbi.cli.call.v1.schema.json` 与当前实现为准。\n\n## 重试与幂等（与 CLI 实现对齐）\n\n- **写方法**：`POST`、`PUT`、`PATCH`、`DELETE` 视为写请求。\n- **是否允许写请求自动重试**：仅当 `--idempotent` 传入，或 describe 元数据中 `idempotent === true`（通常来自 OpenAPI `x-idempotent`）时，写请求才可进入与读请求相同的重试路径；否则写请求 **最多尝试 1 次**。\n- **重试次数**：允许重试时，最多 **3 次** 尝试（含指数退避与抖动）。\n- **可因 HTTP 状态触发的重试**（在仍有剩余次数时）：**429**、**502**、**503**。\n- **网络类错误**：在 CLI 判定为可重试的网络超时/错误时，同样可在上述次数内退避重试。\n- **代理义务**：不得对非幂等写请求假设可安全重放；须满足主 Skill 的幂等门控后再依赖 `--idempotent` 或元数据 `idempotent`。\n\n## 前置条件与子任务（MUST）\n\n执行 `call` 前，若 Phase 2 的 `describe` 输出表明某些参数值**无法由用户直接提供**，而需要先调用其他 smartbi 操作获取（例如：创建资源后得到 ID、查询列表后选取条目），则属于前置条件。\n\n处理流程：\n\n1. 识别前置条件：从 `callParameterPlan` 与 `requestBodySchema` 中判定哪些必填参数的值依赖其他 smartbi 操作。\n2. 创建子任务：子任务内容为再次发动 `smartbi-cli` 技能，以用户原始业务意图描述该前置操作，获取所需的参数值。\n3. 等待子任务完成，将返回结果填入当前 `call` 的参数。\n4. 所有前置条件满足后，继续执行当前 `call`。\n\n约束：\n\n- MUST NOT 跳过前置条件直接用占位值/假值发起 `call`。\n- MUST NOT 要求用户手动去查找前置数据（用户不知道接口映射关系），而应通过子任务自动完成。\n- 若前置子任务失败，应向用户报告失败原因并暂停当前 `call`。\n\n### 退出机制（MUST）\n\n为防止无限递归或子任务爆炸，子任务链受以下硬限制保护。任一限制触发时，MUST 立即停止所有自动化子任务处理，执行**用户升级流程**。\n\n**术语定义：**\n\n- **调用链**：从原始 `call` 到当前深度的全链路所有节点（含兄弟子任务）。同一调用链内的已完成结果可跨节点复用。\n- **参数意图**：子任务所要获取的具体参数值及其用途描述（如\"查询项目A的ID\"与\"查询项目B的ID\"属于不同参数意图，即使使用同一 operationKey）。\n\n**硬限制：**\n\n| 限制项 | 阈值 | 作用域 | 说明 |\n|--------|------|--------|------|\n| 深度上限 | ≤ 3 | 全链路 | 原始 `call` 为深度 0，每嵌套一层子任务深度 +1 |\n| 数量上限 | ≤ 5 | 每个父 call | 单个父 call 最多产生 5 个直接前置子任务 |\n| 去重 | 复用 | 同一调用链 | 同一 `operationKey` + 相同参数意图的前置操作已完成时，直接复用结果，不重复发起 |\n\n**用户升级流程（触发任一硬限制时 MUST 执行）：**\n\n1. 停止所有子任务处理，不继续发起新的 `smartbi call`。\n2. 向用户输出以下信息：\n   - **触发原因**：说明触发了哪条限制（深度/数量/重复），当前计数是多少。\n   - **前置条件清单**：列出当前 `call` 所有已识别但尚未满足的前置参数，格式为「参数名：需要什么值（可通过哪个 operationKey 获取）」。\n   - **已完成的前置结果**：列出已通过子任务成功获取的参数名及其值，供用户参考和复用。\n3. 请用户选择后续操作：\n   - 直接提供缺失参数的值（推荐）\n   - 指定其中部分前置条件继续自动处理\n   - 跳过某个非必填的前置条件\n4. MUST NOT 在用户未响应前自行继续。\n\n### 深度追踪（MUST）\n\n每次发动子任务时，MUST 在子任务 prompt 中显式标注当前深度。子任务 prompt 模板：\n\n```\n[前置子任务 | 深度 {N}/3] 为父操作 \"{parentOperationKey}\" 获取参数 \"{paramName}\"。\n用户原始意图：{userIntent}。\n完成后将获取到的值返回，填入父 call 的 {paramName} 字段。\n```\n\n若子任务识别到自身已达到深度上限（深度 = 3）且仍需进一步前置操作，MUST 立即触发用户升级流程而非继续嵌套。\n\n## 输出契约（机器校验）\n\n- `smartbi-cli/schemas/smartbi.cli.call.v1.schema.json`\n\n与 CLI 行为或 schema 不一致时，以**当前安装的 `smartbi call --help` 与上述 schema 文件**为准。\n\nFile v2.0.0:references/describe.md\n\n# `describe` 参考\n\n本文件为 **Smartbi CLI Skill** 的附属参考；流程性 MUST 以上级 `SKILL.md` 为准。\n\n**用途**：Phase 2（Contract）与 Phase 4（Diagnose）— 读取契约与诊断信息。按 Skill 要求，**默认只消费最小字段集**；其余字段仅在升级诊断时查阅。\n\n## 命令形式\n\n```bash\nsmartbi describe <operationKey> [--profile <name>] [--json] [--yaml] [--agent] [--include-raw-schema] [--refresh] [--config <path>]\n```\n\n\n| 选项                     | 说明                                                                       |\n| ---------------------- | ------------------------------------------------------------------------ |\n| `--json`               | 成功时 `stdout` 单行 JSON；失败时 `stderr` 默认可为人类可读                               |\n| `--yaml`               | 成功时 `stdout` 输出 YAML 文档；失败时 `stderr` 默认可为人类可读                     |\n| `--agent`              | 默认成功 `stdout` 为 YAML，失败时 `stderr` 必须输出结构化 JSON；成功体可含 Agent 侧重字段（见下节） |\n| `--include-raw-schema` | 附加 `requestBodySchemaRaw`、`responseSchemaRaw`（保留 OpenAPI 侧 `$ref` 等，供调试） |\n| `--refresh`            | 强制刷新 registry 缓存                                                         |\n| `--profile <name>`     | 环境名；**所有命令一律带**（环境选择见 `references/profiles.md`）                     |\n| `--config`             | 配置文件路径                                                                   |\n\n\n## Phase 2 必读字段（与 Skill 对齐）\n\n执行 `describe --agent` 后，消费以下字段：\n\n- **`callParameterPlan`**：path/query/header/cookie/body 分组与 CLI 示意；无某类参数时，对应键可能省略（仅 `body`、`checklist` 恒在）。\n- **`requestBodySchema`**：请求体结构（仅 body，不含 path/query/header）；与 `callParameterPlan` 共同约束如何组 `call -d` / `-F`。\n- **`consumes` / `produces`**：媒体类型。\n- **`suggestedCall`**：单行命令模板（占位符与示例，**不能替代**用户对未知字段的确认）。\n\n字段值规则仍以主 Skill 为准：**用户输入或上下文已知事实优先；其次以文档为依据，schema 兜底**（详见主 Skill「文档优先级原则」）。\n\n## 文档加载（优先获取，不可用时兜底）\n\n`describe` 完成后，应主动按主 Skill Phase 2「文档加载」步骤 1 识别文档来源，通过 `smartbi doc <path> --agent` 加载并递归穿透。文档有定义时以其为基准理解 schema；文档不可用或未覆盖的字段，直接使用 schema。\n\n文档路径索引见 `references/doc-index.md`，各 domain 的主要文档目录可从该文件快速定位。\n\n**递归限制（MUST）**：\n- 递归深度 ≤ 3 层（初始文档为深度 0，最多穿透到深度 3）。\n- 已加载路径（绝对路径规范化后）不重复加载，防止循环引用。\n- 超出深度的链接在当前上下文中跳过，不报错。\n\n## `--agent` 额外字段（诊断与摘要）\n\n在 `--agent` 成功响应中，通常还包含（具体以当前 CLI 与 `smartbi-cli/schemas/smartbi.cli.describe.v1.schema.json` 为准）：\n\n- `summary`、`description`、`requiredAll`、`llmBrief`、`constraintsHints`\n- 以及 `idempotent`、`deprecated` 等元信息\n\n用于压缩上下文下的理解与排错，**不替代**完整 `requestBodySchema`。\n\n## Phase 4 升级\n\n1. 先根据调用失败结构中的 `code`、`status`、`hint`、`details` 等定位（见主 Skill）。\n2. 需要更紧凑的必填与约束提示时，使用 **`describe <operationKey> --agent`**。\n3. 仅在仍有契约歧义时，使用 **`describe <operationKey> --agent --include-raw-schema`**。\n\n## 输出契约（机器校验）\n\n- `smartbi-cli/schemas/smartbi.cli.describe.v1.schema.json`\n\n与 CLI 行为或 schema 不一致时，以**当前安装的 `smartbi describe --help` 与上述 schema 文件**为准。\n\nFile v2.0.0:references/discovery.md\n\n# `list` / `search` 参考\n\n本文件为 **Smartbi CLI Skill** 的附属参考，仅规范 `list` / `search` 用法；流程性 MUST 以上级 `SKILL.md` 为准。\n\n**用途**：Phase 1（Discover）— 在最小输出下定位唯一 `operationKey`。按需查阅，勿一次性展开全部条目。\n\n## 共同约定\n\n- `--json`：成功时 `stdout` 为单行 JSON；失败时 `stderr` 默认可为人类可读。\n- `--yaml`：成功时 `stdout` 为 YAML 文档；失败时 `stderr` 默认可为人类可读。\n- `--agent`：默认成功 `stdout` 为 YAML（`--stream` 下为 NDJSON），且失败时 `stderr` 必须输出结构化 JSON（字段以当前 CLI 与对应 `smartbi.cli.*.v1.schema.json` 为准）。\n- 自动化流程默认优先使用 `--agent`；仅在下游明确要求 JSON 时使用 `--json`。\n- `--verbose`：在列表项中追加较长字段（如 `description`、`tags`、`consumes`、`produces`）。\n- `--with-version`：在每个结果项中附加 `apiVersion`。\n- `--with-root-version`：在顶层结果中附加 `rootVersion`。\n- `--refresh`：本次强制刷新 registry 缓存，优先级高于配置中的 `checkIntervalSeconds`。\n- `--config <path>`：指定配置文件路径（默认 `~/.smartbi/config.yaml`）。\n- 环境确定后，`list`/`search` 一律带 `--profile <name>`；CLI 版本不支持时去掉并提示（见 `references/profiles.md`「执行规则」）。\n\n## `smartbi list`\n\n**用途**：枚举当前缓存中的 operation，适合浏览 domain/service 范围。\n\n| 选项                              | 说明                      |\n| ------------------------------- | ----------------------- |\n| `--domain <domain>`             | 仅列出该 domain             |\n| `--service <service>`           | 仅列出该 service            |\n| `--verbose`                     | 输出扩展字段                  |\n| `--with-version`                | 每个 item 附加 `apiVersion` |\n| `--with-root-version`           | 顶层附加 `rootVersion`      |\n| `--refresh`                     | 强制刷新缓存                  |\n| `--json` / `--yaml` / `--agent` | 见上                      |\n\n**输出契约（机器校验）**：`smartbi-cli/schemas/smartbi.cli.list.v1.schema.json`。\n\n**典型用法**：\n\n```bash\nsmartbi list --agent\nsmartbi list --domain demo --service file --agent\nsmartbi list --verbose --with-version --with-root-version --agent\n```\n\n## `smartbi search <keyword>`\n\n**用途**：按关键词检索 operation，适合从自然语言或片段定位 `operationKey`。\n\n| 选项                                                                                                                  | 说明                                                                                                                               |\n| ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |\n| `--domain` / `--service`                                                                                            | 与 list 相同，缩小范围                                                                                                                   |\n| `--in <fields>`                                                                                                     | 可重复；检索字段：`operationKey`、`operationId`、`summary`、`path`、`tags`、`description`、`requestBodySchema`、`responseSchema`（逗号分隔或多次 `--in`） |\n| `--fuzzy`                                                                                                           | 模糊匹配                                                                                                                             |\n| `--case-sensitive`                                                                                                  | 大小写敏感                                                                                                                            |\n| `--limit <n>`                                                                                                       | 最大条数（默认 20）                                                                                                                      |\n| `--verbose` / `--with-version` / `--with-root-version` / `--refresh` / `--json` / `--yaml` / `--agent` / `--config` | 同 list                                                                                                                           |\n\n**输出契约（机器校验）**：`smartbi-cli/schemas/smartbi.cli.search.v1.schema.json`。\n\n**典型用法**：\n\n```bash\nsmartbi search getAgentItems --in description,operationKey,operationId --agent\nsmartbi search order --in operationKey,summary --in description,operationKey,operationId --agent\nsmartbi search \"支付\" --in description,tags --fuzzy --limit 10 --agent\n```\n\n## 与 Skill 流程的衔接\n\n- Phase 1 默认优先 `list` 并让大模型做候选重排；结果过大时先追加 `--domain` / `--service` 收敛。\n- 候选唯一且语义明确匹配（意图与接口 summary 高度一致，无歧义）时，直接进入 Phase 2，在 Phase 3 `call` 前向用户展示\"准备调用 `<operationKey>`，参数如下…\"做一次性确认，无需单独暂停等用户确认 operationKey。\n- 候选唯一但语义匹配度存疑时，展示候选给用户等明确确认后再进入 Phase 2。\n- 仅在有多个疑似候选难以区分时，才对疑似候选调用 `smartbi search <operationKey> --verbose --agent` 以消歧。\n- `search` 的关键词检索不作为默认第一步，仅在需要关键词锚点补充定位或消歧时使用。\n- 若经消歧后仍存在多个候选 `operationKey`，必须先让用户选择，再进入 `describe`。\n- 选定唯一 `operationKey` 后进入 Phase 2（`describe`），见 `references/describe.md`。\n\n`search` 回退门禁（MUST）：\n\n- `smartbi search` 仅作补充回退，不得替代默认 `list` 主路径。\n- `search` 的 `<keyword>` 必须是短关键词，不得是整句业务问句。\n- 若 `search` 0 命中，优先回到 `list` 路径并结合 `--domain` / `--service` 收敛。\n\n检索字段门禁（MUST）：\n\n- `smartbi search` 检索候选时，必须至少包含：`--in description,operationKey,operationId`\n- 若用户额外指定其它 `--in` 字段，仍必须保证上述三字段必在\n\n反例 / 正例：\n\n```bash\n# 反例（整句问句，命中率低）\nsmartbi search \"大模型问句 交易记录数 交易金额 近3年\" --in description,operationKey,operationId --agent\n\n# 正例（拆解为短关键词，分批检索）\nsmartbi search \"交易记录\" --in description,operationKey,operationId --agent\nsmartbi search \"交易金额\" --in description,operationKey,operationId --agent\nsmartbi search \"近3年\" --in description,operationKey,operationId --fuzzy --agent\n```\n\n## 未命中处理（list 重排或 search 检索 0 候选时 MUST）\n\n一旦 0 候选，MUST：\n\n1. 向用户如实反馈。话术：\"在当前接口列表中未能匹配到与'<用户意图摘要>'直接对应的操作。\"\n2. 让用户提供更具体的业务关键词或场景说明，然后重新执行 Phase 1。\n3. MUST NOT 在 0 候选时强行猜测一个不相关的 `operationKey`，不得进入 `describe` / `call`。\n\n## 检索异常分支（LLM 友好）\n\n- `search` 0 个候选：先放宽检索（`--fuzzy`、调整 `--in` 字段、缩短关键词），再检索一次。若仍 0 候选 → 按上节「未命中处理」执行。\n- >5 个候选：优先追加 `--domain` / `--service` / `--limit 5` 收敛，再让用户选择。\n- 多候选未收敛：必须进入“用户选择模板”，不得跳过。\n\n## 默认策略：list 重排 → 消歧时 search 详查 → 用户确认\n\nDiscover 阶段默认执行：\n\n1. 先执行 `smartbi list --agent`。\n2. 将 `list` 返回的候选全集交给大模型做语义重排，产出 Top-N 候选 `operationKey`。\n3. 若候选唯一且语义明确匹配（意图与 summary 高度一致）→ 直接进入 Phase 2，在 Phase 3 `call` 前做一次性展示确认（\"准备调用 X，参数如下…\"）。不要继续 search，也不要单独停下来等用户确认。\n4. 若候选唯一但语义匹配度存疑 → 展示该候选，等用户明确确认后进入 Phase 2。\n5. 若存在多条疑似候选无法区分 → 仅对**难以区分的候选**调用 `smartbi search <operationKey> --verbose --agent` 获取详细信息以消歧。MUST NOT 对所有 Top-N 逐个 search。\n6. 消歧后仍有多条 → 按\"用户选择模板\"让用户确认。不得直接替用户拍板。\n7. 若 list 重排后**无候选匹配用户意图** → 按「未命中处理」执行。\n\n建议：\n\n- 若结果过大，优先先加 `--domain` / `--service` 再 `list`，避免一次性灌入过多噪音。\n- `search` 仅用于消歧，不应作为必经步骤对每个候选执行。\n- `search <operationKey> --verbose --agent` 的详细输出可提供比 `list` 摘要更丰富的判断依据，仅用于消歧场景。\n\n## 多候选时的用户选择模板\n\n当候选 `operationKey` 大于 1 时，按以下最小信息展示给用户选择（不要直接替用户决定）：\n\n```text\n我找到了多个候选 operationKey，请选择一个：\n1) <operationKey> | <method> <endpoint> | <summary>\n2) <operationKey> | <method> <endpoint> | <summary>\n3) <operationKey> | <method> <endpoint> | <summary>\n...\n请回复序号或完整 operationKey。\n```\n\n展示约束：\n\n- 每个候选至少包含：`operationKey`、`method`、`endpoint`、`summary`。\n- 默认最多展示前 5 个；若超过 5 个，先提示可追加筛选条件（如 `--domain` / `--service` / `--in` / `--limit`）再继续收敛。\n- 用户未明确选择前，不得进入 `describe` 或 `call`。\n\n## 首次环境（`init`）\n\n无有效配置时，须先完成初始化再执行 `list` / `search`。  \n完整安装、`init` 与配置要求见：`references/init.md`。\n\nFile v2.0.0:references/doc-index.md\n\n# Domain → 文档路径索引\n\n各 domain 的主要业务文档路径，供 Phase 2 文档加载时快速定位。\n**仅收录 `docs/specs/` 下已有独立文档的 domain**。\n\n> 本索引为 `SKILL.md` Phase 2 的补充参考，核心契约理解流程以 `SKILL.md` 为准。\n\n| domain | 入口文档 | 说明 |\n|--------|---------|------|\n| `datamodel` | `/docs/specs/datamodel/guide.md` | 数据模型查询 |\n| `tabularmodel` | `/docs/specs/tabularmodel/guide.md` | 表格模型管理 |\n| `datamining` | `/docs/specs/datamining/guide.md` | 数据挖掘（ETL / 因果图 / 作业流） |\n\n## datamodel\n\nMQL 查数接口相关文档：\n\n| 路径 | 说明 |\n|------|------|\n| `/docs/specs/datamodel/guides/query-data-by-mql.md` | MQL 取数使用指南（请求/响应/调用方式） |\n| `/docs/specs/datamodel/mql/mql.md` | MQL 语法总览（dims/metrics/from/filter/sort/with） |\n| `/docs/specs/datamodel/mql/common-types.md` | 公共类型（DataType/AggType/ParamValue/DataTable/ParquetResult） |\n| `/docs/specs/datamodel/mql/references/cal-measures.md` | 计算指标（CAL_MEASURE / mdxExpr） |\n| `/docs/specs/datamodel/mql/references/with-column.md` | 派生列（COLUMN / sqlExpr） |\n| `/docs/specs/datamodel/mql/references/with-measure.md` | 派生度量（MEASURE / ref + aggType） |\n\n## tabularmodel\n\n数据模型管理相关文档：\n\n| 路径 | 说明 |\n|------|------|\n| `/docs/specs/tabularmodel/mdl/mdl.md` | MDL 结构总览 |\n| `/docs/specs/tabularmodel/mdl/common-types.md` | MDL 公共类型 |\n| `/docs/specs/tabularmodel/mdl/references/measures.md` | 度量定义 |\n| `/docs/specs/tabularmodel/mdl/references/dimensions.md` | 维度定义 |\n| `/docs/specs/tabularmodel/mdl/references/columns.md` | 列定义 |\n| `/docs/specs/tabularmodel/mdl/references/views.md` | 视图定义 |\n| `/docs/specs/tabularmodel/mdl/references/relations.md` | 关系定义 |\n| `/docs/specs/tabularmodel/mdl/references/calc-members.md` | 计算成员 |\n| `/docs/specs/tabularmodel/mdl/references/named-sets.md` | 命名集 |\n| `/docs/specs/tabularmodel/mdl/references/metrics-sets.md` | 指标集 |\n| `/docs/specs/tabularmodel/mdl/references/parameters.md` | 参数定义 |\n| `/docs/specs/tabularmodel/mdl/references/pre-aggregates.md` | 预聚合 |\n| `/docs/specs/tabularmodel/mdl/references/obj-trees.md` | 对象树 |\n| `/docs/specs/tabularmodel/mdl/references/table-relationships.md` | 表关系 |\n\n## datamining\n\n数据挖掘相关文档：\n\n| 路径 | 说明 |\n|------|------|\n| `/docs/specs/datamining/etl/etl.md` | ETL 结构总览 |\n| `/docs/specs/datamining/etl/references/node-structure.md` | ETL 节点结构 |\n| `/docs/specs/datamining/etl/references/sql-node.md` | SQL 节点 |\n| `/docs/specs/datamining/etl/references/smartbi-query.md` | Smartbi 查询节点 |\n| `/docs/specs/datamining/etl/references/python-script.md` | Python 脚本节点 |\n| `/docs/specs/datamining/etl/references/jdbc-datasource.md` | JDBC 数据源 |\n| `/docs/specs/datamining/etl/references/jdbc-datatarget.md` | JDBC 数据目标 |\n| `/docs/specs/datamining/etl/references/link.md` | ETL 连接 |\n| `/docs/specs/datamining/etl/references/rules.md` | ETL 规则 |\n| `/docs/specs/datamining/etl/references/examples.md` | ETL 示例 |\n| `/docs/specs/datamining/jobflow/jobflow.md` | 作业流总览 |\n| `/docs/specs/datamining/jobflow/references/node-structure.md` | 作业流节点结构 |\n| `/docs/specs/datamining/jobflow/references/etl-job.md` | ETL 作业节点 |\n| `/docs/specs/datamining/jobflow/references/start-job.md` | 启动作业节点 |\n| `/docs/specs/datamining/jobflow/references/link.md` | 作业流连接 |\n| `/docs/specs/datamining/jobflow/references/rules.md` | 作业流规则 |\n| `/docs/specs/datamining/jobflow/references/examples.md` | 作业流示例 |\n| `/docs/specs/datamining/casualgraph/casualgraph.md` | 因果图总览 |\n| `/docs/specs/datamining/casualgraph/references/casual-node.md` | 因果节点 |\n| `/docs/specs/datamining/casualgraph/references/casual-link.md` | 因果连接 |\n| `/docs/specs/datamining/casualgraph/references/differences.md` | 因果图与作业流差异 |\n| `/docs/specs/datamining/casualgraph/references/top-level.md` | 顶级结构 |\n| `/docs/specs/datamining/casualgraph/references/examples.md` | 因果图示例 |\n\n## 使用方式\n\nPhase 2 `describe` 输出中，若 `description` 包含 `[说明](/docs/specs/...)` 形式的链接，直接用 `smartbi doc /docs/specs/... --agent` 加载。\n\n本索引用于在 `description` 中无显式链接时，根据 domain 推断可能存在的文档路径。加载时仍应使用 `smartbi doc` 验证路径可用性。\n\nFile v2.0.0:references/init.md\n\n# `init` / 安装与配置参考\n\n本文件为 **Smartbi CLI Skill** 的附属参考；流程性 MUST 以上级 `SKILL.md` 为准。\n\n**用途**：仅当 skill 的惰性预检（lazy preflight）触发时，用于完成标准安装、初始化与最小可用配置。\n\n## 安装与配置边界（MUST，禁止自由发挥）\n\n- **唯一允许的获取方式**：使用下方 **标准安装** 中的命令，通过 **npm** 全局安装 `**@smartbi/cli@latest`**，得到可在 PATH 中调用的 `smartbi`。\n- **最低版本要求**：`smartbi` 版本 MUST >= `2.0.0`（profile 命令族与 init/profile add 写盘的最低版本）。安装后必须执行 `smartbi --version` 验证版本。若版本低于 2.0.0，必须重新执行 `npm install -g @smartbi/cli@latest` 升级。\n- MUST NOT 使用 `yarn` / `pnpm` / `bun` / `npx` 等替代上述 **npm 全局安装** 作为本 skill 的默认安装路径（避免版本漂移与不可审计环境）。\n- MUST NOT 调用项目目录内随意脚本、其它产品 CLI、或路径/名称相近的可执行文件冒充 `smartbi`。\n- **配置文件唯一来源**：安装并执行 `smartbi init` 后，使用默认路径 `**~/.smartbi/config.yaml`**（或你明确使用且与 init 产物一致的 `--config` 路径）。MUST NOT 从全盘、用户主目录或其它产品中“找一个长得像的配置文件”复制或 `--config` 指向。\n\n## CLI 不存在时（MUST 先于一切）\n\n若执行 `smartbi` 时系统/shell 明确提示 **命令不存在**（例如 `command not found`、`'smartbi' 不是内部或外部命令`、`is not recognized as an internal or external command`、`ENOENT`、退出码 **127** 等），说明 **Smartbi CLI 尚未安装、未加入 PATH，或会话中途被卸载/破坏**。\n\n此时 MUST：\n\n1. **不要**继续在 skill 流程里尝试 `list`/`search`/`describe`/`call` 或猜测接口；不要换目录“盲找”可执行文件；不要用 `curl`/HTTP 等替代 CLI。\n2. **直接**按下方 **标准安装** 在终端**实际执行**安装命令，然后执行 `smartbi --version` 验证。\n3. 验证通过后按下方 **重装后恢复顺序** 处理 init 与配置，再回到业务 Phase。\n\n## 重装后恢复顺序（MUST）\n\n在 `**npm install -g @smartbi/cli@latest` 且 `smartbi --version` 已成功** 之后，按顺序执行；不得口述“已安装”、不得跳过 `--version`。\n\n1. **检查默认配置是否存在且可读**：`~/.smartbi/config.yaml`（或用户此前声明的 `--config` 路径）。\n2. **若文件不存在、明显损坏、或不确定是否仍有效**：直接按 **生成配置文件** 与 **缺项时固定提问模板** 补齐配置。\n3. **若用户明确确认配置文件未被删除且仍可信**：可先不重复 `smartbi init`，但必须用一次最小只读命令（例如带 `--dry-run` 若 CLI 支持，否则 `smartbi list --agent` 在配置已齐的前提下）验证 CLI 与配置可用；**一旦失败**，回到步骤 2 全量 init + 补齐流程。\n4. 仅当满足 **Phase 0 退出标准** 后，才恢复 `list`/`search`/`describe`/`call` 等业务命令。\n\n## 标准安装\n\n```bash\nnpm install -g @smartbi/cli@latest\nsmartbi --version\n```\n\n要求：\n\n- `smartbi` 版本 MUST >= `2.0.0`\n- Node.js `>=18`\n- 默认配置文件：`~/.smartbi/config.yaml`\n\n## 生成配置文件\n\n分「首次配置」与「新增环境」两条路径。三要素（名字/地址/令牌）的提问顺序见「缺项时固定提问模板」。环境确定、执行规则与错误处理见 `references/profiles.md`。\n\n### 首次配置（无配置文件时）\n\n1. 按「缺项时固定提问模板」收集三要素（一次一个问题）。\n2. 执行 `smartbi init --server-type <sdk-server|smartbi> --base-url <地址> --token <令牌> [--profile <环境名>]`（不指定 `--profile` 时默认 `dev`）。默认字面量存储；若用户选择「环境变量」→ 改用 `--token-env <VAR>`（提醒用户该环境变量后续需保持可用）；「系统钥匙串」→ 改用管道形式：`echo -n '<令牌>' | smartbi init --server-type <sdk-server|smartbi> --base-url <地址> --token-keyring --token-stdin [--profile <环境名>]`（agent 无交互终端，必须带 `--token-stdin`；裸 `--token-keyring` 会失败并提示补值方式）。\n3. CLI 原子写盘 `~/.smartbi/config.yaml`（该环境同时为默认环境）。stderr 的 \"prefer tokenEnv or keyring\" 提示属正常输出。\n4. 不向用户展示配置文件路径与内容；直接告知本次操作环境（见 `references/profiles.md`「环境确定」）。\n\n存储方式的说明已含于「缺项时固定提问模板」第二步的令牌问询话术内，写入后不要再重复询问。\n\n### 新增环境（已有配置文件时）\n\n1. 按「缺项时固定提问模板」收集三要素（一次一个问题）。\n2. 执行 `smartbi profile add <name> --server-type <sdk-server|smartbi> --base-url <地址> --token <令牌>`（默认环境保持不变）。用户选择「环境变量」→ 以 `--token-env <VAR>` 替代 `--token`（提醒该环境变量后续需保持可用）；「系统钥匙串」→ 管道形式：`echo -n '<令牌>' | smartbi profile add <name> --server-type <sdk-server|smartbi> --base-url <地址> --token-keyring --token-stdin`。\n3. 需要新环境成为默认时——先经用户确认，再执行 `smartbi profile set-default <name>`。\n4. 写入后告知：\"环境 `<name>` 已配置 ✓\"，不展示文件内容。存储方式的说明已含于令牌问询话术（「缺项时固定提问模板」第二步），写入后不要再重复询问。\n\n### 配置字段说明\n\n- **`baseUrl`**：Smartbi 或 SDK Server 的根 URL。用户提供 Smartbi 地址（如 `http://127.0.0.1:8080/smartbi`）→ `serverType: smartbi`；用户提供 SDK Server 地址（如 `http://127.0.0.1:8086`）→ `serverType: sdk-server`。\n- **`token`**：Smartbi 个人令牌（可登录 Smartbi，在个人中心申请）。token 存储三选一（schema 互斥，只能配其一）：`token` 字面量（默认）/ `tokenEnv`（环境变量名）/ `tokenKeyring: true`（系统钥匙串，service=smartbi-cli、account=profile 名）。\n- **`serverType`**：只能为 `sdk-server` 或 `smartbi` 两个值之一，不得使用其他变体（如 `Smartbi`、`smartbi-server`、`sdk_server` 等）。\n\n约束：\n- 不得臆造配置值；缺失时必须先向用户提问并等待补齐。\n- 用自然语言提问，不要暴露 `baseUrlEnv` / `tokenEnv` 等配置键名；如需提及更安全的存储方式，用「环境变量 / 系统钥匙串」的口语表述（存储说明见「缺项时固定提问模板」第二步）。\n- 写入后不向用户透露配置文件路径，只确认环境名即可。\n- **环境名**：由用户确认；用户未提供线索时最后问（\"不填则默认 dev\"）。\n\n### 缺项时固定提问模板（MUST）\n\n当检测到 `baseUrl` / `token` 任一必要项缺失时，必须先向用户提问，禁止继续执行业务命令。**一次只问一个问题**，按以下顺序：\n\n**第一步——先问地址：**\n\n```text\n继续执行前需要配置服务器连接。请提供您的 Smartbi 地址（如 http://127.0.0.1:8080/smartbi）。\n```\n\n- 用户提供地址 → `serverType` 直接设为 `smartbi`（无需检测 URL 格式），写入 `baseUrl`\n- 用户明确说\"没有 Smartbi 地址\"、\"不知道\"、\"无法提供\" → 使用以下**精确话术**回复：\n  \"了解。也可以使用 SDK Server 地址代替（如 http://127.0.0.1:8086）。请问有 SDK Server 地址吗？\"\n  - 用户提供 SDK Server 地址 → `serverType` 设为 `sdk-server`\n  - 用户仍无法提供 → 暂停，等待用户找到地址后再继续\n- 高级用户可直接说 `sdkserver: http://xxx` → `serverType` 直接设为 `sdk-server`，跳过上述流程\n- 两项都拿到后，按上方「生成配置文件」流程在后台生成配置，不向用户展示配置细节\n\n**第二步——再问令牌：**\n\n```text\n已记录服务器地址。请提供 Smartbi 个人令牌（可登录 Smartbi，在个人中心申请）。令牌默认直接存进配置；如对安全有更高要求，也可以改用「环境变量」或「系统钥匙串」存储。\n```\n\n在你补齐前，我会先暂停，不会继续调用 smartbi 命令。\n\n**第三步——名字兜底：**\n\n```text\n这个环境叫什么名字？（不填则默认 dev）\n```\n\n- 用户提供 → 用作环境名（含 `profile:` 字段与 `profiles.<name>` 键）\n- 用户留空或说\"都行\" → 环境名 `dev`\n- 用户在对话中已给出环境线索（如\"客户A的测试环境\"）→ 第一步先确认名字，跳过本步\n\n## 最小可用配置（示例）\n\n```yaml\nprofile: dev\nprofiles:\n  dev:\n    serverType: sdk-server\n    baseUrl: \"http://127.0.0.1:8086\"\n    token: \"your-api-token\"\n    allowPlainToken: true\n    timeoutMs: 300000\n    # 可选替代（三选一，勿与 token 并存）：\n    # tokenEnv: SMARTBI_TOKEN_DEV\n    # tokenKeyring: true\nregistry:\n  source: remote\n  checkIntervalSeconds: 300\n```\n\n## Phase 0 退出标准\n\n- `smartbi --version` 可执行；\n- YAML 中已为 profile 配置了 **`baseUrl`**、**`token`** 和 **`serverType`**，且 `serverType` 正确匹配用户服务器类型。\n- 配置可用于后续 `list/search/describe/call`。\n\nFile v2.0.0:references/profiles.md\n\n# 多环境（Profile）规范\n\n本文件为 **Smartbi CLI Skill** 的附属参考；流程性 MUST 以上级 `SKILL.md` 为准。\n\n**用途**：环境（profile）的确定、告知、配置与错误处理。用户视角只感知\"一个环境\"；`--profile`、默认环境等是内部细节，不进入用户视野。\n\n## 核心原则\n\n1. **用户只感知一个环境**：任务开始时确定并告知一次，之后全程静默\n2. **配置 = 三要素**：地址、令牌、名字；首次与新增共用同一套提问\n3. **执行零分支**：所有 `smartbi` 命令一律带 `--profile <name>`\n4. **不动默认环境**：新增环境不带 `--set-default`；用户明确要求切换默认时用 `smartbi profile set-default <name>`\n5. **向后兼容**：用户未指定环境时走默认环境，行为与单环境时代一致\n\n## 环境确定\n\n任务开始时，按以下顺序确定环境：\n\n1. 扫描对话识别环境/客户关键词（环境名、`prod`/`qa`/`dev` 等后缀、客户名），与 config.yaml 的 `profiles` 键匹配\n2. 唯一匹配 → 使用该环境\n3. 多个匹配 → 问用户，不猜\n4. 无匹配且用户提供了新环境的地址/令牌 → 走「配置三要素」新建\n5. 未指定任何环境信息 → 默认环境（config.yaml 的 `profile:` 字段）\n\n确定后 MUST 告知用户一次：\n\n> 本次操作环境：`<name>`\n\n用户中途明确\"切到 Y\"→ 按上述流程重新确定，并再次告知一次。\n\n## 执行规则\n\n- 环境确定后，所有 `smartbi` 命令（`list`/`search`/`describe`/`call`/`doc`）**一律带 `--profile <name>`**\n\n## 配置三要素流程（首次与新增统一）\n\n触发：首次使用（无配置文件）、用户要求配置新环境、指定的环境不存在。\n\n按顺序提问（一次一个）：\n\n1. **名字**：用户已提供环境线索（如\"客户A的测试环境\"）→ 确认名字；未提供 → 先跳过\n2. **地址**：提供 Smartbi 地址 → `serverType: smartbi`；无法提供 → 问 SDK Server 地址 → `serverType: sdk-server`；均无法提供 → 暂停\n3. **令牌**：问令牌时一并说明存储方式（仅一句）：\"请提供 Smartbi 个人令牌（可登录 Smartbi，在个人中心申请）。令牌默认直接存进配置；如对安全有更高要求，也可以改用「环境变量」或「系统钥匙串」存储。\"\n4. **名字（兜底）**：仍未确定时问：\"这个环境叫什么名字？（不填则默认 dev）\"\n\n写入方式：\n\n| 场景 | 命令 | `profile:` 默认环境 |\n|------|------|-------------------|\n| 首次（无配置文件） | `smartbi init --server-type <sdk-server\\|smartbi> --base-url <地址> --token <令牌> [--profile <环境名>]`（不指定 `--profile` 时默认 `dev`） | CLI 自动设为该环境 |\n| 新增 | `smartbi profile add <name> --server-type <sdk-server\\|smartbi> --base-url <地址> --token <令牌>`（创建时即预期为新默认，直接加 `--set-default`） | 不动（需要成为默认时，经用户确认后执行 `smartbi profile set-default <name>`，无需重建） |\n\n完成后告知：\"环境 `<name>` 已配置 ✓\"，并按「环境确定」告知本次操作环境。存储方式的说明已含于第 3 步令牌问询话术内，写入后不要重复询问。\n\n## 错误处理\n\n| 错误 | 处理 |\n|------|------|\n| `PROFILE_NOT_FOUND` | `smartbi profile list` 列出现有环境 → 用户选择，或走「配置三要素」新建 |\n| `AUTH_FAILED` | 提示\"`<name>` 环境的 token 无效或已过期\"；执行 `smartbi profile show <name>` 查看凭证来源（env/keyring/字面量）与可用性，请用户确认该环境凭证 |\n| 其他 | 按 SKILL.md Phase 4 通用诊断，报告本次调用所用环境 |\n\n## 版本约束\n\n- **版本要求**：CLI ≥ **2.0.0**（profile 命令族与 init/profile add 写盘的最低版本）。安装后验证：`smartbi --version` ≥ 2.0.0，或 `smartbi profile list --help` 可用；低于 2.0.0 时按 `references/init.md`「标准安装」升级\n- **命名规则**：profile 名仅允许 `[A-Za-z0-9_-]`；\"环境 × 客户\"维度通过命名约定 `<客户>-<环境>` 承载（如 `customerA-test`），不强制\n\nFile v2.0.0:references/rhino-template.md\n\n# MQL 取数 — Rhino 1.7R2 脚本模板\n\n本文件是 `scenarios/schedule-task.md`（S1 定时计划任务）共享的 Rhino JS 代码模板，也可用于 Part 1 通用流程中的即时数据查询场景。\n\n`<...>` 占位符由 agent 根据用户问句填入。\n\n## 完整模板\n\n```js\n// === <任务名称> ===\n// 运行时自动注入: logger, context, connector\n\nvar print = (typeof logger !== \"undefined\")\n    ? function(m) { logger.info(String(m)); }\n    : function(m) { java.lang.System.out.println(String(m)); };\n\n// BASE_URL：优先从环境变量 SMARTBI_SDK_BASE_URL 获取，不存在时使用占位值\nvar BASE_URL = java.lang.System.getenv(\"SMARTBI_SDK_BASE_URL\") || \"<SMARTBI_BASE_URL>\";\nvar newline = String.fromCharCode(10);\n\n// ===== Token 获取 =====\n// 优先级：环境变量 SMARTBI_TOKEN_DEV > RMI generateTempToken > context/占位值\n// connector 已用当前用户身份登录，可通过 RMI 调用 UserService 生成临时令牌。\n// generateTempToken：临时令牌，自动命名无重复，存于 session，执行结束即释放。\nvar TOKEN = java.lang.System.getenv(\"SMARTBI_TOKEN_DEV\");\nif (TOKEN) {\n    print(\"Token from env SMARTBI_TOKEN_DEV\");\n} else {\n    try {\n        var expireTime = java.lang.System.currentTimeMillis() + 30 * 60 * 1000;\n        var tokenResult = connector.remoteInvoke(\"UserService\", \"generateTempToken\", [expireTime]);\n        TOKEN = tokenResult.getResult().toString();\n        print(\"Token generated via generateTempToken\");\n    } catch (e) {\n        print(\"Token generation failed: \" + e);\n        TOKEN = null;\n    }\n    if (!TOKEN) {\n        TOKEN = context.get(\"API_TOKEN\") || \"<TOKEN>\";\n    }\n}\nvar MODEL_ID = \"<MODEL_ID>\";\n\n// ===== HTTP POST (Java 桥接) =====\nfunction httpPostJson(url, token, body) {\n    var c = new java.net.URL(url).openConnection();\n    c.setRequestMethod(\"POST\");\n    c.setDoOutput(true); c.setDoInput(true);\n    c.setRequestProperty(\"Content-Type\", \"application/json; charset=utf-8\");\n    c.setRequestProperty(\"Authorization\", \"Bearer \" + token);\n    c.setConnectTimeout(30000); c.setReadTimeout(120000);\n    var w = new java.io.OutputStreamWriter(c.getOutputStream(), \"UTF-8\");\n    w.write(body); w.flush(); w.close();\n    var s = c.getResponseCode() == 200 ? c.getInputStream() : c.getErrorStream();\n    var r = new java.io.BufferedReader(new java.io.InputStreamReader(s, \"UTF-8\"));\n    var sb = new java.lang.StringBuilder(); var l;\n    while ((l = r.readLine()) != null) sb.append(l);\n    r.close(); c.disconnect();\n    return { code: c.getResponseCode(), body: sb.toString() };\n}\n\n// ===== MQL 查询 =====\n// 优先 showDataTable:true 获取二维表数据以渲染邮件正文表格；\n// 若服务端报错（旧版本 bug 或模型不兼容）则降级为 false，仅显示 rowCount + s3Url。\nfunction queryData(dims, metrics, opt) {\n    opt = opt || {};\n    var mql = { dims: dims, metrics: metrics };\n    if (opt.dimFilter)    mql.dimFilter    = opt.dimFilter;\n    if (opt.metricFilter) mql.metricFilter = opt.metricFilter;\n    if (opt.sort)          mql.sort         = opt.sort;\n    // Rhino 中 JS Number 为 double，序列化 JSON 时带 .0（如 5.0）；\n    // 转为 java.lang.Integer 确保输出整数（5）\n    if (opt.limit)         mql.limit         = new java.lang.Integer(opt.limit);\n    if (opt.offset)        mql.offset        = new java.lang.Integer(opt.offset);\n    var bodyPayload = {\n        req: { modelId: MODEL_ID, modelType: \"AUGMENTED_DATASET\", showDataTable: true, mql: mql }\n    };\n    var body = Packages.smartbi.net.sf.json.JSONObject.fromObject(bodyPayload).toString();\n    var url = BASE_URL + \"/api/v1/datamodel/datamodel/query-data-by-mql\";\n    var resp = httpPostJson(url, TOKEN, body);\n    if (resp.code != 200) { logger.error(\"MQL HTTP \" + resp.code + \": \" + resp.body); return null; }\n    var dObj = Packages.smartbi.net.sf.json.JSONObject.fromObject(resp.body);\n    if (dObj.optBoolean(\"success\", false)) {\n        return dObj.opt(\"result\");\n    }\n    // 降级：旧版本或部分模型不支持 showDataTable=true，改用 false 重试\n    print(\"showDataTable=true failed, retrying with false\");\n    bodyPayload.req.showDataTable = false;\n    body = Packages.smartbi.net.sf.json.JSONObject.fromObject(bodyPayload).toString();\n    resp = httpPostJson(url, TOKEN, body);\n    if (resp.code != 200) { logger.error(\"MQL retry HTTP \" + resp.code + \": \" + resp.body); return null; }\n    dObj = Packages.smartbi.net.sf.json.JSONObject.fromObject(resp.body);\n    return dObj.optBoolean(\"success\", false) ? dObj.opt(\"result\") : (logger.error(\"MQL retry: \" + resp.body), null);\n}\n\n// ===== dataTable → HTML 表格 =====\nfunction buildTableHtml(dt) {\n    var html = \"<table border='1' cellpadding='4' cellspacing='0'>\";\n    html += \"<tr style='background-color:#f0f0f0'>\";\n    var headers = dt.optJSONArray(\"headers\");\n    if (headers) {\n        for (var i = 0; i < headers.size(); i++) {\n            html += \"<th>\" + headers.getString(i) + \"</th>\";\n        }\n    }\n    html += \"</tr>\";\n    var rows = dt.optJSONArray(\"data\");\n    if (rows) {\n        for (var r = 0; r < rows.size(); r++) {\n            html += \"<tr>\";\n            var row = rows.getJSONArray(r);\n            for (var c = 0; c < row.size(); c++) {\n                html += \"<td>\" + row.getString(c) + \"</td>\";\n            }\n            html += \"</tr>\";\n        }\n    }\n    html += \"</table>\";\n    return html;\n}\n\n// ===== Push API 通用发送（辅助函数，独立于渠道） =====\n// var PUSH_URL = BASE_URL + \"/api/v1/push/push/send-message\";  // sdk-server\n// var PROGRESS_URL = BASE_URL + \"/api/v1/push/push/get-send-progress\";\n//\n// function pushMessage(channelType, content, contentType, recipients, config) {\n//     var payload = {\n//         sendMessageRequest: {\n//             channelType: channelType,\n//             content: content,\n//             contentType: contentType || \"MARKDOWN\",\n//             title: \"<任务名称>\"\n//         }\n//     };\n//     if (recipients && recipients.length > 0) {\n//         payload.sendMessageRequest.recipients = recipients;\n//     }\n//     if (config) {\n//         payload.sendMessageRequest.config = config;\n//     }\n//     var body = Packages.smartbi.net.sf.json.JSONObject.fromObject(payload).toString();\n//     var resp = httpPostJson(PUSH_URL, TOKEN, body);\n//     print(\"Push [\" + channelType + \"] HTTP \" + resp.code + \": \" + resp.body);\n//     if (resp.code == 200) {\n//         var respObj = Packages.smartbi.net.sf.json.JSONObject.fromObject(resp.body);\n//         var result = respObj.optJSONObject(\"result\");\n//         if (result) {\n//             var platformTaskId = result.optString(\"platformTaskId\", \"\");\n//             if (platformTaskId) {\n//                 print(\"  -> platformTaskId=\" + platformTaskId);\n//                 return platformTaskId;\n//             }\n//         }\n//     }\n//     return null;\n// }\n//\n// // 可选：查询某次推送的最终状态\n// function queryPushProgress(platformTaskId) {\n//     var payload = { platformTaskId: platformTaskId };\n//     var body = Packages.smartbi.net.sf.json.JSONObject.fromObject(payload).toString();\n//     var resp = httpPostJson(PROGRESS_URL, TOKEN, body);\n//     print(\"Push progress [\" + platformTaskId + \"] HTTP \" + resp.code + \": \" + resp.body);\n//     return resp.code == 200;\n// }\n\n// ===== 主流程 =====\ntry {\n    print(\"开始: <任务名称>\");\n\n    var result = queryData(\n        [<DIMS>],        // 示例: \"业务机构名称\", \"年月\"\n        [<METRICS>],     // 示例: \"贷款余额\", \"不良率\"\n        {\n            // dimFilter: \"<SQL过滤>\",   // 示例: \"贷款余额 > 200000\"\n            sort: [[\"<SORT_FIELD>\", \"DESC\"]],\n            limit: 100\n        }\n    );\n\n    if (result) {\n        var rowCount = result.optInt(\"rowCount\", 0);\n        var s3Url = result.optString(\"s3Url\", \"\");\n        var dt = result.opt(\"dataTable\");\n        var html = \"<h3><任务名称></h3>\" + newline;\n        if (dt) {\n            // showDataTable:true 成功，渲染数据表格\n            html += buildTableHtml(dt);\n        } else {\n            // 降级为 showDataTable:false，仅显示摘要\n            html += \"<p>总行数: \" + rowCount + \"</p>\" + newline\n                + \"<p>数据文件: \" + s3Url + \"</p>\";\n        }\n        // 聊天渠道用 Markdown（企微/钉钉/飞书群机器人不支持 HTML，MESSAGE 推荐 Markdown）\n        var markdown = \"### <任务名称>\\n\\n\"\n            + \"- 总行数: \" + rowCount + \"\\n\"\n            + \"- 数据文件: \" + s3Url;\n        context.put(\"resultTitle\", \"<任务名称>\");\n        context.put(\"resultContent\", html);\n        context.put(\"resultIsHtml\", true);\n        print(\"完成, rowCount=\" + result.rowCount);\n\n        // ===== 推送（可选，仅当用户要求推送时生成此段） =====\n        // 多渠道路由规则：\n        //   - 邮件 → sendToMail Routine（代码简洁，依赖系统 SMTP 配置）\n        //   - 企微/钉钉/飞书（群机器人）→ pushMessage() + Markdown\n        //   - 系统消息 → pushMessage() + Markdown\n        //   - 企微/钉钉（企业应用）→ pushMessage() + agentId / toUsers\n        // 各渠道独立 try-catch，互不影响。Agent 按用户意图启用对应渠道。\n        // pushMessage() 返回 platformTaskId（可用于 queryPushProgress 查询最终状态）。\n        //\n        // var pushResults = [];  // 收集 platformTaskId 供日志查看\n        //\n        // // --- 1. 邮件（sendToMail 内置 Routine）---\n        // // RoutineExecutor：isXxx()/getXxx() → 属性名按 Java Bean 规范（isHTMLText → HTMLText）\n        // execute(\"sendToMail\", {\n        //     taskName: \"<任务名称>\",\n        //     sendSetting: {\n        //         mailList: \"<收件邮箱>\",     // 多个用\";\"分隔\n        //         title: \"<任务名称>\",\n        //         text: html,                 // 邮件用 HTML 格式\n        //         HTMLText: true,             // isHTMLText() → HTMLText\n        //         doZip: false,\n        //         doUnzip: false,\n        //         picInMail: false,\n        //         ccMailList: \"\",\n        //         bccMailList: \"\"\n        //     },\n        //     files: [],\n        //     paramValueMap: {}\n        // });\n        //\n        // // --- 2. 企业微信群机器人（无需扩展） ---\n        // pushMessage(\"WECHAT_WORK\", markdown, \"MARKDOWN\", [],\n        //     { webhookUrl: \"<企微群机器人webhook地址>\" });\n        //\n        // // --- 3. 钉钉群机器人（无需扩展） ---\n        // pushMessage(\"DINGTALK\", markdown, \"MARKDOWN\", [],\n        //     { webhookUrl: \"<钉钉群机器人webhook地址>\" });\n        //\n        // // --- 4. 飞书群机器人（无需扩展） ---\n        // pushMessage(\"FEISHU\", markdown, \"MARKDOWN\", [],\n        //     { webhookUrl: \"<飞书群机器人webhook地址>\" });\n        //\n        // // --- 5. 企业微信企业应用（依赖 WeiXinExt 扩展） ---\n        // pushMessage(\"WECHAT_WORK\", markdown, \"MARKDOWN\", [],\n        //     { agentId: \"<企微应用agentId>\", toUsers: \"<userid1|userid2>\" });\n        //\n        // // --- 6. 钉钉工作通知（依赖 DingdingExt 扩展） ---\n        // pushMessage(\"DINGTALK\", markdown, \"MARKDOWN\", [],\n        //     { toUsers: \"<钉钉userid1,钉钉userid2>\" });\n        //\n        // // --- 7. 系统消息 ---\n        // pushMessage(\"MESSAGE\", markdown, \"MARKDOWN\",\n        //     [\"<Smartbi用户ID>\"], {});\n    }\n} catch (e) { logger.error(\"异常: \" + (e.message || e)); }\n```\n\n## 占位符说明\n\n| 占位符 | 来源 | 说明 |\n|--------|------|------|\n| `<任务名称>` | 自动生成 | 如 \"每日贷款质量分析\" |\n| `<SMARTBI_BASE_URL>` | 兜底 | Smartbi 服务地址（优先从环境变量 `SMARTBI_SDK_BASE_URL` 获取） |\n| `<TOKEN>` | 兜底 | 优先从环境变量 `SMARTBI_TOKEN_DEV` 获取，不存在时通过 `generateTempToken` 生成临时令牌（30 分钟有效） |\n| `<MODEL_ID>` | 数据模型 ID | 通过问句检索或用户提供 |\n| `<DIMS>` | 问句提取（**MUST 来自 getDataModelTrees 返回的 label**） | 如 `\"订单日期\"`, `\"产品类别\"`。禁止编造不存在的字段名，否则触发 \"没有找到层次字段: xxx\" 500 错误 |\n| `<METRICS>` | 问句提取（**MUST 来自 getDataModelTrees 返回的 label**） | 如 `\"销售额\"`, `\"订单量\"`。禁止编造 |\n| `<SORT_FIELD>` | 默认取第一个 `<METRICS>` label | 排序字段，必须是 dims 或 metrics 中的 label |\n| `dimFilter` | 问句中的过滤条件 | 如 `\"贷款余额 > 200000\"`（SQL 语法，字符串用单引号，内部单引号双写 `'it''s'`） |\n\n### 推送占位符（按渠道）\n\n| 渠道 | 方式 | 占位符 | 内容格式 | 依赖扩展 |\n|------|------|--------|---------|---------|\n| 邮件 | `sendToMail` | 收件邮箱地址 | HTML（`html` 变量） | — |\n| 企微群机器人 | `pushMessage(\"WECHAT_WORK\", ...)` | `webhookUrl` | MARKDOWN | — |\n| 钉钉群机器人 | `pushMessage(\"DINGTALK\", ...)` | `webhookUrl` | MARKDOWN | — |\n| 飞书群机器人 | `pushMessage(\"FEISHU\", ...)` | `webhookUrl` | MARKDOWN | — |\n| 企微企业应用 | `pushMessage(\"WECHAT_WORK\", ...)` | `agentId` + `toUsers`（`\\|` 分隔） | MARKDOWN | WeiXinExt |\n| 钉钉工作通知 | `pushMessage(\"DINGTALK\", ...)` | `toUsers`（逗号分隔） | MARKDOWN | DingdingExt |\n| 系统消息 | `pushMessage(\"MESSAGE\", ...)` | Smartbi 用户 ID | MARKDOWN | — |\n\n## 脚本注入方式\n\n模板代码写入 `.js` 文件后，**使用 `scripts/inject-script.mjs` 工具**自动完成 JSON 转义并注入请求体。\n详见 `scenarios/schedule-task.md`「script 字段处理」章节。\n\n**MUST 使用 inject-script 工具**，禁止手动 JSON.stringify 或手写转义。工具会自动处理换行、引号、反斜杠等转义字符。\n\n### 如需在脚本中使用特殊字符\n\n当需要在 HTML 输出中包含换行时，使用 `String.fromCharCode(10)` 代替字面量 `\\n`，\n避免 Rhino 引擎在解析某些上下文时将 JavaScript 中的 `\\n` 误判。\n\n## 注意事项\n\n- **`showDataTable` 降级策略**：模板默认 `true` 优先获取二维表数据渲染邮件表格；若服务端返回错误（旧版本 bug），`queryData()` 自动降级为 `false` 重试，仅显示 `rowCount` + `s3Url`。Agent 无需手动调整此值\n- sdk-server 路径为 `/api/v1/datamodel/datamodel/query-data-by-mql`（双 datamodel）\n- 字段名用 label（展示名），不是内部 name；先用 `getDataModelTrees` 确认（参考 Step 2）\n- 核心指标（资本充足率等）不可与业务维度（机构名称等）跨表混用\n- **push API 路径**：\n  - `serverType=sdk-server`：`/api/v1/push/push/send-message`（双 push）\n  - `serverType=smartbi`（直连）：`/api/v1/push/send-message`（单 push）\n  - 在脚本中建议先确定 BASE_URL 对应的 serverType 再拼路径\n- **邮件推送优先用 sendToMail Routine**：须按 `SendToMail.Input` 接口提供 `taskName`/`sendSetting`/`files`/`paramValueMap` 四个属性，`sendSetting` 内须含 `IMailSetting` 全部字段（`mailList`/`title`/`text`/`HTMLText`/`doZip`/`doUnzip`/`picInMail`/`ccMailList`/`bccMailList`）。RoutineExecutor 按 Java Bean 规范转换属性名（`isHTMLText()` → 属性 `HTMLText`）。详见模板中注释掉的示例代码\n- `dimFilter` SQL 字符串值用单引号括起，内部单引号双写转义\n\nFile v2.0.0:references/strategy.md\n\n# `strategy` 参考（决策树 / 槽位抽取 / serverType 路径）\n\n本文件为 **Smartbi CLI Skill** 的附属参考；流程性 MUST 以上级 `SKILL.md` 为准。\n\n## Fast Path Decision Tree\n\n1. 已有明确失败信息（报错/状态码/失败日志）→ `diagnose`\n2. 唯一 `operationKey` 但参数未确认 → `contract`\n3. 唯一 `operationKey` 且参数齐全 → `execute`\n4. 无 `operationKey` 或仅业务目标表达 → `discover`\n5. `discover` 出现多候选 → 先让用户选择再进入 `contract`\n\n## Slot Extraction（业务语义抽取）\n\n当用户未显式提供接口名时，先抽取以下槽位：\n\n| 槽位 | 含义 | 映射到 describe 输出 | 示例 |\n|------|------|---------------------|------|\n| `action` | 业务动作 | 匹配 operationId 动词部分 | 训练/分析/查询/导出/发布 |\n| `resource` | 业务对象 | 匹配 domain 或 requestBody 关键字段 | 模型资源/数据集/报表主题 |\n| `dims` | 维度 | `requestBodySchema` 中 `mql.dims` | 分支行/年月/产品名称 |\n| `metrics` | 指标 | `requestBodySchema` 中 `mql.metrics` | 销售额/贷款余额/转化率 |\n| `filters` | 过滤条件 | `requestBodySchema` 中 `dimFilter`/`metricFilter` | 区域=华东/近30天/余额>100万 |\n| `sort` | 排序 | `requestBodySchema` 中 `mql.sort` | 按销售额降序 |\n| `limit` | 行数 | `requestBodySchema` 中 `mql.limit` | 前10/前100 |\n| `time_range` | 时间范围 | 转化为 `dimFilter` SQL 表达式 | 去年→`\"年份 = '2025'\"` |\n\n把槽位拼成 2-3 组关键词，配合 `smartbi list --domain <domain> --agent` 收敛（search 仅作 list 的补充回退）。\n\n## 槽位缺失处理\n\n| 缺失槽位 | 处理策略 |\n|---------|---------|\n| `action` 未知 | 让用户补充要做什么（查/导出/创建等） |\n| `resource` 未知 | 从上下文推断，或 `list --agent` 全量重排让用户选 |\n| `dims`/`metrics` 未知 | 调用 `getDataModelTrees` 列出字段，让用户指定 |\n| `filters` 未知 | 若用户未提过滤语义，可省略，不影响主查询 |\n| `modelId` 未知 | 调用 `listCatalogElementsByResourceType` 列出可用模型，让用户选择 |\n\n## serverType 路径差异\n\n两种 `serverType` 的 API 路径格式不同，影响 Rhino 脚本内 HTTP 调用及 `smartbi call` 行为：\n\n| `serverType` | 配置 `baseUrl` 示例 | 实际请求路径（queryDataByMql） |\n|-------------|-------------------|-------------------------------|\n| `smartbi` | `http://host/smartbi` | `http://host/smartbi/api/v1/datamodel/datamodel/query-data-by-mql` |\n| `sdk-server` | `http://host:8086` | `http://host:8086/api/v1/datamodel/datamodel/query-data-by-mql` |\n\n关键差异：\n- `smartbi` 模式下 `baseUrl` 本身含 `/smartbi` 路径前缀，拼接后完整路径含两个层级\n- `sdk-server` 模式部分接口路径中 domain 重复（`datamodel/datamodel`），需注意区分\n- 使用 `smartbi call` CLI 时无需手动拼路径（CLI 内部处理前缀），但若在 Rhino/JS 脚本中直连 HTTP 需按 serverType 构造完整 URL\n\n## 诊断决策树（Phase 4 扩展）\n\n```\n失败响应\n  ├─ HTTP 4xx\n  │   ├─ 401 AUTH_FAILED    → token 无效 → 让用户重新申请\n  │   ├─ 403 FORBIDDEN      → 无权限 → 查 describe 中 x-funcPerm\n  │   ├─ 404 path not in spec → serverType/baseUrl 配置不匹配\n  │   └─ 400 INVALID_ARGUMENT → describe --agent 对照必填字段逐一检查\n  ├─ HTTP 5xx\n  │   ├─ 500               → 记录 tid，对照 describe --include-raw-schema\n  │   ├─ 502/503           → 服务不可达，等 UPSTREAM_UNAVAILABLE 恢复后重试\n  │   └─ 429               → 限流，退避后重试（CLI 内置处理）\n  ├─ 网络类\n  │   ├─ NETWORK_TIMEOUT   → baseUrl 错误或网络不通\n  │   └─ NETWORK_ERROR     → DNS/代理/防火墙问题\n  └─ 业务错误（200 但 data.success=false）\n      └─ 读 data.error/data.message，对照本 skill 错误速查表\n```\n\nFile v2.0.0:scenarios/push-message.md\n\n# S2: 消息推送\n\n## 触发\n\n用户问句含「推送/发送/通知」+「渠道名称」。\n\n> 若问句不含推送语义或不含渠道名称，本场景不适用，回退到 Part 1 通用流程。\n\n| 条件 | 关键词 |\n|------|--------|\n| **推送动作** | 发送/推送/通知/发到/推到/上报 |\n| **渠道名称** | 企业微信/企微/微信/WeChat/钉钉/DingTalk/飞书/Feishu/邮件/email/系统消息/站内消息 |\n\n**示例**：\n- \"发送今天的销售额报表到企微群\"\n- \"推送客户流失报告到钉钉\"\n- \"邮件通知管理员系统状态\"\n\n> 若问句**同时**含「定时/每天/每周」+「推送」→ 走 S1 定时计划任务（脚本中调用 push API），非本场景。\n\n## 意图解析\n\n| 参数 | 来源 | 示例 |\n|------|------|------|\n| channelType | 渠道名称 | \"企微/企微群\"→WECHAT_WORK, \"钉钉\"→DINGTALK, \"邮件\"→MAIL |\n| content | 用户描述/上下文数据 | Agent 拼接的 Markdown/HTML |\n| config | 渠道专属 | webhookUrl（群机器人）/ agentId（企微应用）/ recipients（邮件/消息） |\n\n## 执行步骤\n\n```\nStep 1: smartbi list --domain push --agent\n   ↓    确认 push 接口可用，记录 operationKey\nStep 2: smartbi describe push.sendMessage --agent\n   ↓    理解 config 参数结构，加载关联文档\nStep 3: 按渠道 + 内容构造 JSON 请求体\n   ↓\nStep 4: smartbi call push.sendMessage -d @body.json --agent\n   ↓    返回 {\"ok\":true, \"data\": {\"platformTaskId\": \"...\"}}\nStep 5 (可选): smartbi call push.getSendProgress -d @progress.json --agent\n        查询推送结果\n```\n\n## API 请求体\n\n### 发送消息\n\n```\nPOST /api/v1/push/send-message\n```\n\n**企微群机器人**：\n\n```json\n{\n  \"sendMessageRequest\": {\n    \"channelType\": \"WECHAT_WORK\",\n    \"content\": \"## 每日销售额\\n\\n今日销售额：**¥1,234,567**\\n较昨日增长：8.5%\",\n    \"contentType\": \"MARKDOWN\",\n    \"title\": \"每日销售额报表\",\n    \"config\": {\n      \"webhookUrl\": \"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx\"\n    }\n  }\n}\n```\n\n**企微企业应用**：\n\n```json\n{\n  \"sendMessageRequest\": {\n    \"channelType\": \"WECHAT_WORK\",\n    \"content\": \"## 告警通知\\n\\n服务器 CPU 使用率超过 90%\",\n    \"config\": {\n      \"agentId\": \"1000002\",\n      \"toUsers\": \"zhangsan|lisi\"\n    }\n  }\n}\n```\n\n**钉钉群机器人（带加签）**：\n\n```json\n{\n  \"sendMessageRequest\": {\n    \"channelType\": \"DINGTALK\",\n    \"content\": \"## 客户流失报告\\n\\n本月流失客户数：12\\n流失率：3.2%\",\n    \"title\": \"客户流失报告\",\n    \"config\": {\n      \"webhookUrl\": \"https://oapi.dingtalk.com/robot/send?access_token=xxx\",\n      \"secret\": \"SECxxx\"\n    }\n  }\n}\n```\n\n**邮件**：\n\n```json\n{\n  \"sendMessageRequest\": {\n    \"channelType\": \"MAIL\",\n    \"content\": \"<h1>系统状态报告</h1><p>各服务正常运行</p>\",\n    \"contentType\": \"HTML\",\n    \"title\": \"系统状态报告\",\n    \"recipients\": [\"admin@company.com\", \"ops@company.com\"]\n  }\n}\n```\n\n**系统消息**：\n\n```json\n{\n  \"sendMessageRequest\": {\n    \"channelType\": \"MESSAGE\",\n    \"content\": \"审批流程已完成，请查看。\",\n    \"title\": \"审批通知\",\n    \"recipients\": [\"userId1\", \"userId2\"]\n  }\n}\n```\n\n### 查询进度\n\n```\nPOST /api/v1/push/get-send-progress\n```\n\n```json\n{\n  \"platformTaskId\": \"<sendMessage 返回的 platformTaskId>\"\n}\n```\n\n## 渠道识别映射\n\n| 用户说… | channelType | config 模式 |\n|---------|-------------|------------|\n| 企微/企业微信/微信/WeChat + 群里/机器人/webhook | `WECHAT_WORK` | `config.webhookUrl` |\n| 企微/企业微信 + 应用/通知/agentId | `WECHAT_WORK` | `config.agentId` |\n| 钉钉/DingTalk + 群里/机器人/webhook | `DINGTALK` | `config.webhookUrl` |\n| 钉钉/DingTalk + 工作通知/toUsers | `DINGTALK` | `config.toUsers` |\n| 飞书/Feishu | `FEISHU` | `config.webhookUrl` |\n| 邮件/email/邮箱 | `MAIL` | `recipients`（邮箱地址） |\n| 系统消息/站内消息/消息通知 | `MESSAGE` | `recipients`（用户 ID） |\n\n> 如用户未明确群机器人/企业应用，默认使用群机器人模式（更简单，只需 webhookUrl）。\n\n## 注意\n\n- 企微群机器人和钉钉群机器人的 webhookUrl 需用户提供——Agent 应主动询问\"请提供企微/钉钉群机器人 webhook 地址\"\n- `WECHAT_WORK` 和 `DINGTALK` 通过 `config` 内容区分群机器人/企业应用模式，无需用户手动选择子类型\n- 推送是异步的——`sendMessage` 返回 `platformTaskId` 后，可通过 `getSendProgress` 查询最终结果\n- content 默认 Markdown 格式，也可指定 TEXT（纯文本）或 HTML（仅邮件渠道推荐）\n\n## 在定时任务脚本中调用（S1 场景）\n\n当推送作为 S1 定时计划任务的组成部分时，**不走 CLI `smartbi call`**，而是在 Rhino JS 脚本中通过 HTTP 调用 push API。详见 `references/rhino-template.md` 中的 `pushMessage()` 辅助函数和多渠道路由模式。\n\n核心差异：\n- 认证：脚本中复用 `TOKEN`（环境变量或 RMI `generateTempToken`），无需重新鉴权\n- 序列化：使用 `Packages.smartbi.net.sf.json.JSONObject.fromObject(payload).toString()`\n- 路径：sdk-server 为 `/api/v1/push/push/send-message`（双 push），Smartbi 直连为 `/api/v1/push/send-message`\n- 邮件渠道：脚本中优先用 `sendToMail` 内置 Routine（更简洁），非邮件渠道才走 push API\n\nArchive v1.3.0: 15 files, 50100 bytes\n\nFiles: README.md (5411b), references/call.md (8995b), references/describe.md (4042b), references/discovery.md (10138b), references/doc-index.md (4622b), references/init.md (8288b), references/profiles.md (3894b), references/rhino-template.md (15435b), references/strategy.md (4013b), scenarios/push-message.md (5353b), scenarios/schedule-task.md (18051b), scripts/inject-script.mjs (3153b), skill-card.md (3081b), SKILL.md (16327b), _meta.json (130b)\n\nFile v1.3.0:SKILL.md\n\n---\nname: smartbi-cli\ndescription: Smartbi BI 业务操作入口：AI 对话分析（大模型问数、智能体、知识库/知识图谱构建与训练、数据解释）、数据查询（MQL/DuckDB 取数、指标统计、字段发现）、数据建模（维度/指标/计算成员/命名集管理）、数据源管理（JDBC连接、Schema 与表同步、元数据刷新）、定时任务与 ETL（计划调度、作业流、因果图）、消息推送（企微/钉钉/飞书/邮件/系统消息）、资源与权限管理（目录树、用户/角色/组）。通过 @smartbi/cli 发现与调用 API。\n---\n\n# Smartbi CLI\n## 流程概览\n- **Step 0 — Scenario Router**（入口）：先看用户问句是否命中已有场景。命中 → 加载 `scenarios/` 下对应文件执行；未命中 → 进入 Part 1。\n- **Part 1 — Core CLI Workflow**（骨架）：任何 `domain.operationId` 的发现→理解→调用→排错流程一致。\n- **Part 2 — Scenario Guides**（场景）：高频业务场景的端到端模板，按需加载。\n- **`references/`**（参考）：各 Phase 的详细流程、策略模板与文档路径索引。\n\n## Triggers（触发条件）\n\n当用户描述 **BI 业务动作 + 业务对象**，但未显式给出接口名/operationKey（例如\"帮我训练模型资源A\"\"基于模型资源A分析去年销售额\"）时触发。\n\n当用户问及 BI 相关业务操作（分析、训练、指标查询、报表/问句类需求、定时计划任务等）时触发本 skill。触发后进入 Step 0 路由判断。\n\n`operationKey` 格式为 `${domain}.${operationId}`（如 `demo.createOrder`、`aichat.getAgentItems`）。`list` 输出结果可直接复制作为 `describe`/`call` 的参数。\n\n---\n\n## 全局约定（所有路径共用）\n\n以下规则适用于 **所有** 执行路径（Part 1 通用流程和 Part 2 场景流程）。先读完全局约定，再进入 Step 0 路由判断。\n\n### CLI 安装与配置\n\n- MUST 仅通过 **npm 全局安装** 获得可执行命令 `smartbi`：`npm install -g @smartbi/cli@latest`，随后 `smartbi --version` 验证版本，并执行 `smartbi list --help` 确认输出包含 `--profile`（多环境功能的最低版本要求；低于支持版本时按 `references/profiles.md`「版本约束与已知限制」兜底）。\n- MUST NOT 使用 `yarn` / `pnpm` / `bun` / `npx` 或其它程序代替上述 `smartbi`。\n- 初始化 MUST：`smartbi init`（或 `smartbi init --tmpl` 获取占位符模板），再按 `references/init.md` 补齐配置；不得跳过 init 手写。\n- 配置文件路径：默认 **`~/.smartbi/config.yaml`**，或用户在 init 后 **明确指定** 的 `--config <path>`。MUST NOT 在系统中猜测或套用其它文件。config.yaml 可包含多个环境（profiles），默认环境由 `profile:` 字段指定；多环境的选择、配置与错误处理见 `references/profiles.md`。\n- CLI 不存在时的处理流程见 `references/init.md`「标准安装」。\n\n### 环境选择（多 profile）\n\n任务开始时确定本次操作环境并**告知一次**（\"本次操作环境：`<name>`\"）：用户指定环境/客户时按 `references/profiles.md` 匹配或新建，未指定时用默认环境（config.yaml 的 `profile:` 字段）。\n\n环境确定后，**所有** `smartbi` 命令（`list`/`search`/`describe`/`call`/`doc`）**一律带 `--profile <name>`**；CLI 版本不支持时按 `references/profiles.md`「执行规则」兜底。\n\n完整规范（确定/告知/配置/错误处理/版本约束）见 `references/profiles.md`。\n\n### 首次配置\n\n在首次运行 `smartbi`（任意子命令）时，若检测到无配置文件或 `baseUrl`/`token` 缺失，MUST 分步向用户索要（一次一个问题），全部获取后后台生成配置文件：\n\n1. **先问地址**：用户提供 Smartbi 地址 → `serverType: smartbi`；用户无法提供 → 问 SDK Server 地址 → `serverType: sdk-server`；均无法提供 → 暂停。\n2. **再问令牌**：用户提供后，若环境名仍未确定，最后问名字（\"不填则默认 dev\"）。\n3. 执行 `smartbi init --tmpl` 获取占位符模板 → 替换 `{{SERVER_TYPE}}`、`{{BASE_URL}}`、`{{TOKEN}}`，并把模板中 `profile:` 字段与 `profiles` 下的键改为确认的环境名 → 写入 `~/.smartbi/config.yaml`（该环境同时为默认环境）。仅告知用户\"配置已写入\"，不展示文件内容。\n4. 告知本次操作环境：\"本次操作环境：`<name>`\"。\n\n`serverType` 取值约束（MUST）：只能是 `sdk-server` 或 `smartbi`，不得使用其他变体。\n\n新增环境（追加写入、不动默认环境）的流程见 `references/profiles.md`「配置三要素流程」。详细提问模板见 `references/init.md`。\n\n### 参数构造规范\n\n构造 `smartbi call` 的请求体时，按以下优先级确定取值来源：\n1. **用户输入或上下文已知事实**：对话中已明确提供的值\n2. **文档内容**（优先）：字段业务含义、合法枚举值、字段间依赖、完整使用示例（通过 `smartbi doc` 加载）\n3. **`requestBodySchema`**（兜底）：文档不可用或未覆盖时使用\n4. **`callParameterPlan`**：CLI 标志映射\n5. **`suggestedCall`**：仅供参考的命令模板，不应直接复用其占位值\n6. **仍无法确定的字段**：向用户确认，不得自行编造\n\n构造 call 参数时，应主动获取 `docs/specs/` 下的业务文档作为理论依据；文档不可用或未覆盖时，以 schema 定义兜底。已加载路径不重复加载。\n\n**请求体文件规范（MUST）**：\n- JSON 请求体必须使用 `-d @file.json`（避免跨 shell/OS 转义差异）\n- MUST NOT 使用内联 JSON（如 `-d '{\"k\":\"v\"}'` 或 `-d \"{\\\"k\\\":\\\"v\\\"}\"`）\n- 为本轮 `call` **新建**的 JSON 文件：在 `smartbi call` 流程结束后 **MUST** 删除；不得删除用户自带的 `@` 文件\n- 临时文件写入系统临时目录或仓库内已 `.gitignore` 的路径，降低误提交风险\n- 写入请求体前，若有 Rhino 脚本等需转义的内容，MUST 使用 `scripts/inject-script.mjs` 工具，禁止手工转义\n\n### 子任务机制\n\n执行 `call` 前，若某些参数值依赖其他 smartbi 操作（如先查资源 ID、先创建关联对象），MUST 以子任务方式自动完成，**不得让用户手动查找**。\n\n- 子任务执行路径：**绕过 Step 0 场景匹配**，直接进入 Part 1 Phase 1→3 通用流程（`list` → `describe` → `call`），完成前置操作后把结果填回父 call。\n- 退出硬限制（任一触发即停止自动化，执行用户升级流程，详见 `references/call.md`「前置条件与子任务」）：\n  - **深度上限**：嵌套深度 ≤ 3（原始 call 为深度 0）\n  - **数量上限**：每个父 call 的直接前置子任务 ≤ 5 个\n  - **去重**：同一 `operationKey` + 相同参数意图，同一调用链内已完成的前置操作不再重复发起\n- 子任务失败时向用户报告原因并暂停当前 call。\n\n### 重试与幂等\n\n- **写请求**（POST / PUT / PATCH / DELETE）：仅当 `--idempotent` 指定或 describe 元数据 `idempotent === true` 时才可自动重试，否则最多尝试 1 次\n- **可触发的 HTTP 状态重试**（在剩余次数内）：429 / 502 / 503\n- **最大尝试次数**：允许重试时最多 3 次（含指数退避与抖动）\n\n### 输出格式（Output Contract）\n\n每次调用完成后，按以下固定顺序输出：\n1. `operationKey`\n2. 最终执行命令\n3. 关键结果（`status`/`tid`/核心业务字段）\n4. 若失败：单行修复建议 + 下一条可执行命令\n\n### 参考文件按需加载\n\n默认只使用 SKILL.md 本摘要。需要模板/字段映射/检查清单/异常分支时，以及需要加载接口关联文档时，才读取 `references/` 下的对应文件或执行 `smartbi doc`。\n\n# Part 1: Core CLI Workflow（骨架流程）\n\n以下四个 Phase 定义了从用户意图到 API 调用的完整流程。\n通用参数构造、子任务等底层规则在 [全局约定](#全局约定所有路径共用) 中定义，这里只描述各阶段的执行顺序。\n\n## Phase 0 — 惰性预检\n\n默认不强制在每个新会话先检查安装/配置。直接进入 Phase 1（`list` / discover）。\n\n当**任意一次**实际执行 `smartbi`（任意子命令）时，若出现下列情况，才按 [全局约定 · CLI 安装与配置](#cli-安装与配置) 补齐与排查：\n\n- **CLI 不存在**（`command not found` / 退出码 127 等）→ 立即停止，按标准安装流程处理\n- **鉴权/凭证**：`AUTH_FAILED` / `FORBIDDEN` / `PROFILE_NOT_FOUND`\n- **服务不可达**：`NETWORK_TIMEOUT` / `NETWORK_ERROR` / `UPSTREAM_UNAVAILABLE`\n- **配置缺失或不合法**：`INVALID_ARGUMENT` 且 hint 指向 `Config file not found`\n\n其余错误跳过惰性预检，由 Phase 4 诊断处理。\n\n## Phase 1 — Discover\n\n```\nsmartbi list --profile <name> --agent\n```\n\n1. 默认先执行 `smartbi list --agent`，将候选全集交给大模型做语义重排。\n2. 若结果过大，先加 `--domain` / `--service` 再次 `list` 收敛。\n3. 若候选唯一且语义明确匹配（用户意图与接口 summary 高度一致，无歧义）→ 直接进入 Phase 2，在 Phase 3 `call` 前向用户展示\"准备调用 `<operationKey>`，参数如下…\"做一次性确认。不要继续 search，也不要单独停下来等用户确认 operationKey。\n4. 若候选唯一但语义匹配度存疑（摘要与意图不完全对应）→ 展示该候选给用户，等用户明确确认后进入 Phase 2。\n5. 若存在多条疑似候选无法区分 → 仅对难以区分的候选调用 `smartbi search <operationKey> --verbose --agent` 获取详细信息以消歧。MUST NOT 对所有 Top-N 逐个 search。\n6. `search` 的关键词检索仅作为补充回退手段（例如用户提供了明确关键词锚点时），不作为默认第一步。\n\nPhase 1 定位约束（MUST）：\n- MUST 默认使用 `list` 路径定位接口，不得先走 `search` 作为主路径。\n- `search --verbose` 仅用于消歧，不得对每个候选盲目执行。\n- 存在多候选时 MUST 等在候选阶段让用户选择，不得替用户拍板。唯一且明确匹配时可直接进入 Phase 2（在 Phase 3 call 前做一次性确认）。\n\n细节见 `references/discovery.md`。\n\n## Phase 2 — Contract\n\n```\nsmartbi describe <operationKey> --profile <name> --agent\n```\n\n消费字段：`callParameterPlan`、`requestBodySchema`、`consumes/produces`、`suggestedCall`。\n\n### 文档加载（优先获取，不可用时兜底）\n\n`describe` 完成后，应主动尝试加载关联文档作为理解接口语义的理论依据。\n\n**步骤 1 — 识别文档来源**：\n\n| 维度 | 识别方式 | 示例 |\n|------|----------|------|\n| `description` 中的链接 | 扫描 `describe` 输出的 `description` 字段中的 Markdown 链接 | `[MQL详情](/docs/specs/datamodel/mql/mql.md)` |\n| `requestBodySchema` 中的链接 | 沿 `$ref` 链查找被引用 schema 的 `description` 中的链接 | schemas.yaml 中组件定义的 description |\n| domain 推断 | 根据 `operationKey` 所属 domain 推断相关文档目录 | `createDataSet` → `docs/specs/tabularmodel/` |\n| 数据类型推断 | 根据请求体中涉及的核心数据类型推断参考文档 | 含 `DataSetMeasure` → `docs/specs/tabularmodel/mdl/references/measures.md` |\n| `llmBrief` / `summary` 中的引用 | 检查 describe 输出其他字段中的文档引用 | — |\n\n**步骤 2 — 加载与穿透**：对识别到的文档路径，执行 `smartbi doc <path> --agent`，stdout 纳入上下文。文档中的引用链接继续递归加载，硬限制：\n- **深度 ≤ 3**（初始文档为深度 0），**去重**（已加载路径不重复）\n- 绝对路径 `/...` → 直接传给 `smartbi doc`；相对路径 → 基于当前文档路径解析；外部 URL → WebFetch\n\n**步骤 3 — 文档优先，schema 兜底**：按 [全局约定 · 参数构造规范](#参数构造规范) 的优先级规则取值。文档有定义时以文档为准，不可用时以 schema 兜底。\n\nMUST NOT 忽略链接或自行猜测文档内容。细节见 `references/describe.md`。\n\n## Phase 3 — Execute\n\n```\nsmartbi call <operationKey> -d @body.json --profile <name> --agent\n```\n（`<name>` 为本次操作环境；所有命令一律带 `--profile`，见全局约定「环境选择」）\n\n- 参数构造、请求体格式、临时文件清理等底层规则见 [全局约定 · 参数构造规范](#参数构造规范)\n- 前置参数依赖的子任务机制见 [全局约定 · 子任务机制](#子任务机制)\n- 重试策略与幂等门控见 [全局约定 · 重试与幂等](#重试与幂等)\n- 复杂参数组合策略见 `references/strategy.md`\n\n细节见 `references/call.md`。\n\n## Phase 4 — Diagnose\n\n失败后 `smartbi describe <operationKey> --agent`；仍有契约歧义再加 `--include-raw-schema`。\n诊断策略参考 `references/strategy.md`。\n\n# Part 2: Scenario Guides（场景索引）\n\n**入口先走 Step 0 — Scenario Router。** 将用户问句与下表比对：\n- 命中 → 加载对应场景文件，按场景流程执行\n- 未命中 → Part 1 通用流程\n- 加载后场景判定不适用 → 回退 Part 1\n\n| 场景 | 关键触发词 | 场景文件 |\n|------|-----------|---------|\n| S1 定时计划任务 | 每天/每周/定时/cron + 查询/统计/推送/ETL | `scenarios/schedule-task.md` |\n| S2 消息推送 | 发送/推送/通知 + 企微/钉钉/飞书/邮件 | `scenarios/push-message.md` |\n\n触发词仅用于快速匹配；精确判定由场景文件 `## 触发` 节负责。仅命中时才加载对应文件。\n\n场景随 OpenAPI 的扩展可持续追加，每个新场景须经过端到端验证后再入库。\n\n> **开发者**：新增场景操作指南见 `docs/guide/smartbi-cli-新增场景操作手册.md`。\n\n---\n\n## 常见错误速查\n\n### CLI / 连接类\n\n| 错误 | 原因 | 处理 |\n|------|------|------|\n| `command not found` (127) / `is not recognized` | 未安装 CLI | → Phase 0 标准安装 |\n| `AUTH_FAILED` (401) | token 无效或已过期 | 让用户重新申请令牌，更新 `config.yaml` |\n| `FORBIDDEN` (403) | 用户无权限执行该 operation | 检查 `x-funcPerm` 要求，确认用户角色 |\n| `NETWORK_TIMEOUT` / `NETWORK_ERROR` | 服务不可达 | 检查 `baseUrl` 是否正确，网络是否通 |\n| `UPSTREAM_UNAVAILABLE` (503) | Smartbi 服务未启动或过载 | 确认服务状态后重试 |\n| `Config file not found` (INVALID_ARGUMENT) | 配置文件不存在 | → Phase 0 init 流程 |\n| `PROFILE_NOT_FOUND` | 指定的环境不存在 | 列出现有环境让用户选择，或按 `references/profiles.md` 新建 |\n| `SpecRejected` / `path not in spec` | sdk-server 路径前缀错误 | 确认 `serverType` 与 `baseUrl` 配置一致 |\n\n### API 业务类\n\n| 错误 | 原因 | 处理 |\n|------|------|------|\n| `选择字段不能为空` | dims/metrics 空或不匹配 | 先调 `getDataModelTrees` 确认字段 label |\n| `Failed to obtain two-dimensional data` | `showDataTable: true` 不兼容某些模型 | 改为 `false`，走 s3Url Parquet |\n| `unsupported literal in MQL filter` | MQL `:param` 占位符不兼容 | 改为字面量 `'值'`，内部单引号双写 |\n| `connector.remoteInvoke` 报错 | RMI 签名不匹配 | 调 `getTaskScriptEnv` 查看可用方法 |\n| HTTP 500 / `Internal Server Error` | 服务端异常 | 记录 `tid`，用 `describe --include-raw-schema` 排查请求体 |\n\n---\n\n## 参考（按需加载）\n\n| 文件 | 内容 |\n|------|------|\n| `references/init.md` | 安装与配置 |\n| `references/profiles.md` | 多环境（profile）规范：确定/告知/配置/错误处理 |\n| `references/discovery.md` | Phase 1 接口发现 |\n| `references/describe.md` | Phase 2 契约理解 |\n| `references/call.md` | Phase 3 执行调用 |\n| `references/strategy.md` | 策略与常见模式（Phase 3 构造复杂参数或 Phase 4 诊断时加载） |\n| `references/rhino-template.md` | MQL 取数 Rhino JS 模板（定时任务场景共用） |\n| `references/doc-index.md` | domain → 文档路径索引（Phase 2 文档加载时参照） |\n| `scenarios/schedule-task.md` | S1 定时计划任务 |\n| `scripts/inject-script.mjs` | 脚本注入工具：将多行 JS 文件自动 JSON 转义后注入请求体 |\n\nFile v1.3.0:README.md\n\n# Smartbi CLI Skill\n\n让**任意 AI agent**（Cursor、Claude Code、Copilot 等）通过 `@smartbi/cli` npm 工具发现并调用 Smartbi 全部 OpenAPI 能力。\n\n## 目标\n\n```\n          ┌──────────┐\n          │ 任意 Agent │\n          └─────┬────┘\n                │ 自然语言意图\n                ▼\n┌───────────────────────────────┐\n│   smartbi-cli skill           │\n│                               │\n│  意图 → operationKey → call   │\n│                               │\n│  定时计划任务 / ...           │\n└───────────────┬───────────────┘\n                │ smartbi call\n                ▼\n┌───────────────────────────────┐\n│   Smartbi OpenAPI             │\n│   (datamodel / scheduletask   │\n│    tabularmodel / aichat ...) │\n└───────────────────────────────┘\n```\n\n**一句话**：一个 skill 文件 + 一个 npm 包 = 任意 agent 获得 Smartbi 全平台能力。\n\n## 架构\n\n```\nSKILL.md                         ← 入口（agent 加载）\n│\n├─ Part 1: Core CLI Workflow     ← 骨架，所有 OpenAPI 调用通用\n│   Phase 0  惰性预检\n│   Phase 1  Discover  (smartbi list)\n│   Phase 2  Contract  (smartbi describe + doc)\n│   Phase 3  Execute   (smartbi call)\n│   Phase 4  Diagnose  (失败诊断)\n│\n├─ Part 2: Scenario Guides（索引）  ← 按意图路由，命中后加载对应文件\n│\n├─ scenarios/                    ← 场景文件（每个独立验证）\n│   └─ schedule-task.md          S1 定时计划任务\n│\n└─ references/                   ← 参考手册（按需加载）\n    ├─ init.md                   安装与配置\n    ├─ discovery.md              Phase 1 详细流程\n    ├─ describe.md               Phase 2 详细流程\n    ├─ call.md                   Phase 3 详细流程\n    ├─ strategy.md               策略与常见模式\n    ├─ rhino-template.md         MQL 取数 Rhino JS 模板（共用）\n    └─ doc-index.md              domain → 文档路径索引\n```\n\n## 当前能力\n\n| 场景 | 能力 | 状态 |\n|------|------|------|\n| **通用 OpenAPI 调用** | `smartbi list` → `describe` → `call` 全流程，覆盖任意 `domain.operationId` | 完整 |\n| **S1 定时计划任务** | 创建调度计划 + Rhino JS 脚本任务 + 邮件/消息推送（API schema + Rhino 模板已确认） | 完整 |\n\n> 新场景须经过端到端验证后才可入库。\n\n## 依赖\n\n- **npm 包**：`@smartbi/cli >= 1.1.0`（`npm install -g @smartbi/cli@latest`）\n- **外部 skill**：**零**。本 skill 自闭环，不依赖任何其他 skill。\n\n## 使用说明\n\n### 安装\n\n```bash\nnpm install -g @smartbi/cli@latest\nsmartbi --version   # 确认 >= 1.1.0\nsmartbi init        # 生成 ~/.smartbi/config.yaml，按提示填入 baseUrl + token\n```\n\n### 在 Agent 中使用\n\n1. 将本目录放到 agent 的 skills 路径下（如 Cursor 的 `.cursor/skills/`、Claude Code 的配置的 skills 目录等）\n2. Agent 加载 `SKILL.md` 后自动获得以下能力：\n   - 发现接口：用户描述需求 → `smartbi list --agent` 语义匹配 → 得到 `operationKey`\n   - 理解契约：`smartbi describe <key> --agent` → 加载文档 → 理解参数\n   - 执行调用：`smartbi call <key> -d @body.json --agent` → 返回结果\n   - 定时任务：识别定时意图 → 生成 Rhino JS → 创建 task + schedule → 启用\n\n### 场景路由\n\nAgent 根据用户问句自动选择场景：\n\n```\n用户问句\n  ├─ 有「每天/每周/定时/几点」? \n  │   └─ 是 → S1 定时计划任务（生成 task + schedule；是否推送由语义决定）\n  └─ 否 → 走 Part 1 通用流程\n```\n\n## 如何新增 Scenario\n\n1. 新建 `scenarios/<name>.md` — 自描述文件：触发条件 + 请求体模板 + 注意事项\n2. 通过实际 API 调用端到端验证（Python 脚本或 smartbi call）\n3. `SKILL.md` Part 2 索引表加一行\n4. 如有新的共享代码模板 → `references/` 下新增\n\n每个新场景必须经过端到端验证后才可入库，不添加未验证的 placeholder。\n\n## 示例对话\n\n**即时查询**：\n> 用户：帮我查一下上个月各分支行的贷款余额\n> Agent：找到 `datamodel.queryDataByMql`，确认模型\n\nArchive v1.2.0: 14 files, 46606 bytes\n\nFiles: README.md (5411b), references/call.md (8955b), references/describe.md (3890b), references/discovery.md (9978b), references/doc-index.md (4622b), references/init.md (6991b), references/rhino-template.md (15435b), references/strategy.md (4013b), scenarios/push-message.md (5353b), scenarios/schedule-task.md (18051b), scripts/inject-script.mjs (3153b), skill-card.md (2733b), SKILL.md (14673b), _meta.json (130b)\n\nArchive v1.1.0: 8 files, 21997 bytes\n\nFiles: references/call.md (8955b), references/describe.md (3509b), references/discovery.md (9428b), references/init.md (6991b), references/strategy.md (978b), skill-card.md (2545b), SKILL.md (13900b), _meta.json (130b)\n\nArchive v1.0.1: 8 files, 23869 bytes\n\nFiles: references/call.md (8955b), references/describe.md (3509b), references/discovery.md (8942b), references/init.md (6922b), references/strategy.md (4797b), skill-card.md (2707b), SKILL.md (14019b), _meta.json (130b)\n\nArchive v1.0.0: 8 files, 23793 bytes\n\nFiles: references/call.md (9101b), references/describe.md (3567b), references/discovery.md (9083b), references/init.md (7058b), references/strategy.md (4906b), skill-card.md (2555b), SKILL.md (13957b), _meta.json (130b)","readmeExcerpt":"Skill: SmartBI CLI Owner: wahsonleung Summary: Query model/report data and operate SmartBI APIs Tags: latest:2.1.0 Version history: v2.1.0 | 2026-09-22T10:33:13.891Z | user **Major update with expanded scenario support and improved agent integration.** - Data query and insight scenarios now have dedicated guides and workflow overrides (scenarios/data-query.md), supporting direct, multi-step query/insight calls. - Add","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"smartbi list --profile <name> --agent"},{"language":"text","snippet":"smartbi describe <operationKey> --profile <name> --agent"},{"language":"text","snippet":"smartbi call <operationKey> -d @body.json --profile <name> --agent"},{"language":"text","snippet":"┌──────────┐\n          │ 任意 Agent │\n          └─────┬────┘\n                │ 自然语言意图\n                ▼\n┌───────────────────────────────┐\n│   smartbi-cli skill           │\n│                               │\n│  意图 → operationKey → call   │\n│                               │\n│  定时计划任务 / ...           │\n└───────────────┬───────────────┘\n                │ smartbi call\n                ▼\n┌───────────────────────────────┐\n│   SmartBI OpenAPI             │\n│   (datamodel / scheduletask   │\n│    tabularmodel / aichat ...) │\n└───────────────────────────────┘"},{"language":"text","snippet":"SKILL.md                         ← 入口（agent 加载）\n│\n├─ 直接取数                       ← 必要元数据 → MQL/SQL → 校验 → 本地分析/交付\n│   query-routing.md / data-model-query.md\n│\n├─ Part 1: Core CLI Workflow     ← 骨架，所有 OpenAPI 调用通用\n│   Phase 0  惰性预检\n│   Phase 1  Discover  (smartbi list)\n│   Phase 2  Contract  (smartbi describe + doc)\n│   Phase 3  Execute   (smartbi call)\n│   Phase 4  Diagnose  (失败诊断)\n│\n├─ Part 2: Scenario Guides（索引）  ← 按意图路由，命中后加载对应文件\n│\n├─ scenarios/                    ← 场景文件（每个独立验证）\n│   ├─ schedule-task.md          S1 定时计划任务\n│   ├─ push-message.md           S2 消息推送\n│   └─ data-query.md             数据查询与洞察\n│\n└─ references/                   ← 参考手册（按需加载）\n    ├─ init.md                   安装与配置\n    ├─ profiles.md               多环境（profile）规范\n    ├─ discovery.md              Phase 1 详细流程\n    ├─ describe.md               Phase 2 详细流程\n    ├─ call.md                   Phase 3 详细流程\n    ├─ strategy.md               策略与常见模式\n    ├─ rhino-template.md         MQL 取数 Rhino JS 模板（共用）\n    └─ doc-index.md              domain → 文档路径索引"},{"language":"bash","snippet":"npm install -g @smartbi/cli@latest\nsmartbi --version   # 确认 >= 2.0.0\nsmartbi init --server-type <sdk-server|smartbi> --base-url <url> --token <token>\n                    # 全参数生成 ~/.smartbi/config.yaml"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: smartbi-cli\ndescription: 广州思迈特软件有限公司（思迈特）提供的 SmartBI 通用业务操作技能。当用户需要连接 SmartBI、查询数据模型或指标模型、对已有报表问数、进行 AI 问数与复杂洞察，或管理智能体、知识库与知识图谱、数据模型、数据源、定时任务与 ETL、消息推送、资源及权限时使用。通过 @smartbi/cli 发现并调用当前环境的 SmartBI API，支持 MQL 与只读 SQL 直接取数。\n---\n\n# SmartBI CLI\n\n## 流程概览\n- **Step 0 — Scenario Router**（入口）：先看用户问句是否命中 Part 2 场景索引。命中 → 加载对应场景文件执行；未命中 → 进入 Part 1。组合请求按业务步骤衔接，不让取数场景覆盖调度、推送或资源操作。\n- **Part 1 — Core CLI Workflow**（骨架）：任何 `domain.operationId` 的发现→理解→调用→排错流程一致。\n- **Part 2 — Scenario Guides**（场景）：高频业务场景的端到端模板，按需加载。\n- **`references/`**（参考）：各 Phase 的详细流程、策略模板与文档路径索引。\n\n数据查询与洞察的扩展路径见 [scenarios/data-query.md](scenarios/data-query.md)，按需加载，不改变其他场景的通用调用流程。\n\n命中数据查询与洞察场景后，已知 operationKey 按场景文件的最短可验证调用链执行；资源未知时按该场景定位业务资源。该场景已授权只读调用不执行下文 Phase 3 的逐次确认；下文 Part 1 的通用接口发现与写操作规则继续用于其他业务操作。\n\n## Triggers（触发条件）\n\n当用户描述 **BI 业务动作 + 业务对象**，但未显式给出接口名/operationKey（例如\"帮我训练模型资源A\"\"基于模型资源A分析去年销售额\"）时触发。\n\n当用户问及 BI 相关业务操作（分析、训练、指标查询、报表/问句类需求、定时计划任务等）时触发本 skill。触发后进入 Step 0 路由判断。\n\n`operationKey` 格式为 `${domain}.${operationId}`（如 `demo.createOrder`、`aichat.getAgentItems`）。`list` 输出结果可直接复制作为 `describe`/`call` 的参数。\n\n---\n\n## 全局约定（所有路径共用）\n\n以下规则适用于 **所有** 执行路径（Part 1 通用流程和 Part 2 场景流程）。先读完全局约定，再进入 Step 0 路由判断。\n\n### CLI 安装与配置\n\n- MUST 仅通过 **npm 全局安装** 获得可执行命令 `smartbi`：`npm install -g @smartbi/cli@latest`，随后 `smartbi --version` 验证版本 **≥ 2.0.0**，并执行 `smartbi profile list --help` 确认 profile 命令族可用。\n- MUST NOT 使用 `yarn` / `pnpm` / `bun` / `npx` 或其它程序代替上述 `smartbi`。\n- 初始化 MUST：由 CLI 全参数生成配置：`smartbi init --server-type <sdk-server|smartbi> --base-url <url> --token <token> [--profile <name>]`；凭证方式按用户选择，可使用字面令牌、环境变量或钥匙串，细节见 `references/init.md`。\n- 配置文件路径：默认 **`~/.smartbi/config.yaml`**，或用户在 init 后 **明确指定** 的 `--config <path>`。MUST NOT 在系统中猜测或套用其它文件。config.yaml 可包含多个环境（profiles），默认环境由 `profile:` 字段指定；多环境的选择、配置与错误处理见 `references/profiles.md`。\n- CLI 不存在时的处理流程见 `references/init.md`「标准安装」。\n\n### 环境选择（多 profile）\n\n任务开始时在内部确定本次使用的 profile：用户指定连接或客户时按 `references/profiles.md` 匹配或新建，未指定时用默认 profile（config.yaml 的 `profile:` 字段）。普通业务对话不询问或展示 `dev`、profile 名、`--profile` 等内部配置；多个连接无法区分时只按服务器地址或用户熟悉的业务名称澄清。\n\n环境确定后，**所有** `smartbi` 命令（`list`/`search`/`describe`/`call`/`doc`）**一律带 `--profile <name>`**。\n\n完整规范（确定/告知/配置/错误处理/版本约束）见 `references/profiles.md`。\n\n### 首次配置\n\n仅在无配置或所选环境缺少必要信息时补齐配置。复用已知地址、服务器类型、环境名和有效凭证来源（字面令牌、环境变量或钥匙串），只询问缺失项，一次一个问题。已有地址但缺少/失效令牌时只处理凭证，不再推荐体验中心。已有配置的修复见 `references/init.md`，不得用全量初始化覆盖其他环境。以下完整流程用于首次无配置的情况：\n\n1. **先问地址**：用户提供 SmartBI 地址 → `serverType: smartbi`。如果用户只表达“连接 SmartBI”或“连接 SmartBI 地址”但没有提供具体地址，第一问直接说：“是否连接 SmartBI 官网体验中心 https://cloud.smartbi.com.cn/smartbi？如果要连接自己的环境，请提供地址。”不得只问“要连接哪个环境”而遗漏体验中心选项；也不得在用户确认前将体验中心写入配置或发起连接。用户确认后使用该地址和 `serverType: smartbi`。用户拒绝或需要其他环境时，再询问实际 SmartBI 地址；用户无法提供 SmartBI 地址时，询问 SDK Server 地址并使用 `serverType: sdk-server`；两者均无法提供时暂停。\n2. **再问令牌**：问令牌时一并说明获取路径和存储方式（仅一句）：\"请提供 SmartBI 个人访问令牌（登录 SmartBI 后，在「个人中心 → 我的设置 → 个人访问令牌」中新建）。令牌默认直接存进配置；如对安全有更高要求，也可以改用「环境变量」或「系统钥匙串」存储。\"首次配置不再询问环境名；若用户选择其他存储方式，步骤 3 按其选择生成。\n3. 执行 `smartbi init --server-type <sdk-server|smartbi> "},{"path":"README.md","content":"# SmartBI CLI Skill\n\nSkill 版本：**2.1.0**。运行时依赖的 `@smartbi/cli` 版本独立管理，最低要求为 2.0.0。\n\n保留标准 Skill 的业务路由，为数据类请求采用基于模型的直接取数路径：用户问句 → 读取必要模型信息 → 根据模型与 SDK 能力选择 MQL 或只读 SQL → CLI 调用 SDK → 校验数据 → 桌面智能体分析/展示。直接取数不依赖模型训练或 AI 问数，无需额外查询框架。详见 `references/query-routing.md`。\n\n在原版场景索引中新增数据查询与洞察，入口为 `scenarios/data-query.md`；原有通用 API、定时任务和推送保留。外部智能体通过接口定位资源，不依赖 SmartBI 页面预选信息。模型取数按语义选择 MQL/只读 SQL，已有报表按定义与参数查询/导出；正式报告、归因、预测和综合大屏按路由默认白泽，用户指定直接取数或本地分析时遵循其选择。已有数据制图和文件转换继续本地处理；创建或修改 SmartBI 报表仍走资源操作接口。\n\n普通取数依赖 Node/npm 全局安装的 SmartBI CLI（>=2.0.0）。Python 仅用于可选辅助脚本/文件读取，不是 MQL 前置条件。跨桌面客户端需具备命令执行和文件读写能力；不能把单一客户端的实测视为所有客户端已验证。\n\n支持具备命令执行和文件读写能力的桌面智能体，通过 `@smartbi/cli` 发现并调用当前环境开放且有权限的 SmartBI API。\n\n## 目标\n\n```\n          ┌──────────┐\n          │ 任意 Agent │\n          └─────┬────┘\n                │ 自然语言意图\n                ▼\n┌───────────────────────────────┐\n│   smartbi-cli skill           │\n│                               │\n│  意图 → operationKey → call   │\n│                               │\n│  定时计划任务 / ...           │\n└───────────────┬───────────────┘\n                │ smartbi call\n                ▼\n┌───────────────────────────────┐\n│   SmartBI OpenAPI             │\n│   (datamodel / scheduletask   │\n│    tabularmodel / aichat ...) │\n└───────────────────────────────┘\n```\n\nSkill 提供业务路由与调用规则，实际能力取决于当前 SDK、模型定义和账号权限。\n\n普通“查询XXX数据”默认取齐指定条件和粒度下的结果；`limit`控制单次批量，满批且无结束证据时继续分页。明确TopN/前N条/样本时按指定范围停止。数据默认直接展示，文件按需交付；不能将首批或预览称为全部，执行受容量或耗时限制时明确说明未完成范围。\n\n## 架构\n\n```\nSKILL.md                         ← 入口（agent 加载）\n│\n├─ 直接取数                       ← 必要元数据 → MQL/SQL → 校验 → 本地分析/交付\n│   query-routing.md / data-model-query.md\n│\n├─ Part 1: Core CLI Workflow     ← 骨架，所有 OpenAPI 调用通用\n│   Phase 0  惰性预检\n│   Phase 1  Discover  (smartbi list)\n│   Phase 2  Contract  (smartbi describe + doc)\n│   Phase 3  Execute   (smartbi call)\n│   Phase 4  Diagnose  (失败诊断)\n│\n├─ Part 2: Scenario Guides（索引）  ← 按意图路由，命中后加载对应文件\n│\n├─ scenarios/                    ← 场景文件（每个独立验证）\n│   ├─ schedule-task.md          S1 定时计划任务\n│   ├─ push-message.md           S2 消息推送\n│   └─ data-query.md             数据查询与洞察\n│\n└─ references/                   ← 参考手册（按需加载）\n    ├─ init.md                   安装与配置\n    ├─ profiles.md               多环境（profile）规范\n    ├─ discovery.md              Phase 1 详细流程\n    ├─ describe.md               Phase 2 详细流程\n    ├─ call.md                   Phase 3 详细流程\n    ├─ strategy.md               策略与常见模式\n    ├─ rhino-template.md         MQL 取数 Rhino JS 模板（共用）\n    └─ doc-index.md              domain → 文档路径索引\n```\n\n## 当前能力\n\n| 场景 | 能力 | 状态 |\n|------|------|------|\n| **直接 MQL 取数** | 字段发现、过滤、聚合、排序、分页及按需计算，本地分析与文件交付 | 按目标环境契约、模型字段和查询结果逐次校验 |\n| **通用 OpenAPI 调用** | `smartbi list` → `describe` → `call`，按当前注册接口执行 | 保留原标准流程 |\n| **S1 定时计划任务 / S2 推送** | 定时任务、脚本及消息推送指南 | 保留原场景，本轮只读验收不代表写操作已复测 |\n| **已有报表取数** | 资源发现、元数据、参数、导出与文件校验 | 按报表类型、有效参数和业务结果逐次校验 |\n| **SmartBI AI / Baize** | 按数据查询与洞察场景处理显式请求或复杂洞察 | 按需分支，不是普通直接取数前置 |\n\n> 新场景按具体类型和路径完成端到端验收后才声明支持；已加入的扩展说明须保留未验证边界。\n\n## 依赖\n\n- **npm 包**：`@smartbi/cli >= 2.0.0`（`npm install -g @smartbi/cli@lates"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7bgapafkp5xjwz4xafxyynzx87dnfb\",\n  \"slug\": \"smartbi-cli\",\n  \"version\": \"2.1.0\",\n  \"publishedAt\": 1790073193891\n}"},{"path":"references/agent-workflows.md","content":"# Agent workflow export and modification\n\nResolve `<PYTHON>` to an available Python 3 interpreter and `<SKILL_DIR>` to this Skill's absolute directory. Wrapped POSIX examples show argument grouping; adapt continuation characters to the current shell.\n\n## Capability boundary\n\nThe standard `aichat` CLI currently exposes Agent discovery and execution but not the full workflow graph lifecycle. Confirm this with `smartbi list --profile <PROFILE> --domain aichat --agent` in the target installation before using internal APIs.\n\nThe following internal SmartBI internal contracts are source-confirmed but not stable public SDK commitments:\n\n| Action | Method and path |\n| --- | --- |\n| Get Agent | `GET /smartbi/smartbix/api/dataagent/graph/{id}` |\n| Search Agent graphs | `POST /smartbi/smartbix/api/dataagent/graphs` |\n| Create Agent | `POST /smartbi/smartbix/api/dataagent/graph/create/{parentId}` |\n| Update Agent | `POST /smartbi/smartbix/api/dataagent/graph/update` |\n| Download definition | `GET /smartbi/smartbix/api/dataagent/define/download/{id}` |\n| Upload definition | `POST /smartbi/smartbix/api/dataagent/define/upload` |\n\nThe raw workflow ID is used here. Remove only the leading `customagent_` that `queryRpc` adds; do not otherwise transform the ID.\n\n## Authentication\n\nInternal calls require an authenticated SmartBI session with `AI_AGENT` permissions. Put the complete header value in an environment variable supplied through a secure channel, for example:\n\n```bash\nexport SMARTBI_SESSION_COOKIE='<secret value>'\n```\n\nPass only the environment variable name to the helper:\n\n```bash\n--header-env Cookie=SMARTBI_SESSION_COOKIE\n```\n\nNever place the value in command history, request JSON, source control, or logs.\n\n## Export\n\n```bash\n<PYTHON> <SKILL_DIR>/scripts/smartbi_internal.py \\\n  --base-url <BASE_URL> \\\n  --header-env Cookie=SMARTBI_SESSION_COOKIE \\\n  agent-get \\\n  --agent-id <RAW_AGENT_ID> \\\n  --output <EXPORTED_AGENT_JSON>\n```\n\nThe command reports the graph SHA-256 and node/link counts without printing the full definition.\n\n## Modify safely\n\nStart from the exported object. Preserve every unknown graph field. Change only the required nodes, ports, links, prompts, or settings. Before applying:\n\n- parse `define` as JSON;\n- verify every link source/target node exists;\n- verify referenced input/output port IDs exist on the corresponding nodes;\n- keep node IDs stable unless a new node is genuinely required;\n- give each new node and port a collision-free ID;\n- ensure finish nodes do not wait for mutually exclusive branches;\n- do not put secrets into prompts, node inputs, or settings.\n\nFirst run a dry-run:\n\n```bash\n<PYTHON> <SKILL_DIR>/scripts/smartbi_internal.py \\\n  --base-url <BASE_URL> \\\n  --header-env Cookie=SMARTBI_SESSION_COOKIE \\\n  agent-update \\\n  --agent-id <RAW_AGENT_ID> \\\n  --file <CANDIDATE_OR_PATCH_JSON> \\\n  --backup-dir <BACKUP_DIR>\n```\n\nReview `changed_fields`, node/link counts, and `current_sha256`. Apply exactly once using that hash:\n\n```bash\n<PY"},{"path":"references/artifact-handling.md","content":"# Artifact Handling\n\nBaize file artifacts are server URIs, not local paths. Inspect the captured SSE stream with `scripts/artifact_io.py`, download artifacts through the configured SmartBI profile, then read and verify the resulting Excel, CSV, or Parquet file. Do not treat a preview table as a complete extract or expose signed URLs.\n\nThe same reader can inspect downloaded direct-query files. CSV values stay as text, including leading zeros, decimal text and literal `NA`/`NULL`; blank cells remain empty strings. Excel preserves stored cell types, and Parquet uses its schema. Convert numeric measures explicitly from model metadata before calculating; identifier columns must retain their original values. CSV alone cannot distinguish an empty string from an exported null, and Excel number formatting may display zeros that are absent from its stored numeric value. Do not invent missing identifier digits or null semantics."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Query model/report data and operate SmartBI APIs Skill: SmartBI CLI Owner: wahsonleung Summary: Query model/report data and operate SmartBI APIs Tags: latest:2.1.0 Version history: v2.1.0 | 2026-09-22T10:33:13.891Z | user **Major update with expanded scenario support and improved agent integration.** - Data query and insight scenarios now have dedicated guides and workflow overrides (scenarios/data-query.md), supporting direct, multi-step query/insight calls. - Add","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1661,"uniquenessScore":47,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T17:15:05.623Z","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-10T17:15:05.623Z","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-10T21:43:03.231Z","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"}]}}}