{"id":"84a5d84f-6396-413c-8a74-380046c3a41d","entityType":"agent","slug":"clawhub-financial-ai-analyst-stock-earnings-review","name":"Earnings Review Agent","canonicalUrl":"https://www.xpersona.co/agent/clawhub-financial-ai-analyst-stock-earnings-review","canonicalPath":"/agent/clawhub-financial-ai-analyst-stock-earnings-review","generatedAt":"2026-10-10T07:11:06.190Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-09T02:24:38.784Z","emptyReason":null},"description":"依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。 当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。 用户点名具体公司/股票... Skill: Earnings Review Agent Owner: financial-ai-analyst Summary: 依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。 当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。 用户点名具体公司/股票... Tags: financial:1.0.2, latest:1.0.3, performance:1.0.2, research:1.0.2, stock:1.0.2, valuation:1.0.2 Version history: v1.0.3 | 2026-04-17T11:19:33.126Z | user Publish 1.0.3 v1.0.2 | 2026-04-10T","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 9.8K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s172qfps754dhtdynwv0gwshes83mtd4:stock-earnings-review","sourceUrl":"https://clawhub.ai/financial-ai-analyst/stock-earnings-review","homepage":"https://clawhub.ai/financial-ai-analyst/skills/stock-earnings-review","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/financial-ai-analyst/stock-earnings-review","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/financial-ai-analyst/skills/stock-earnings-review","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":77,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。 当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。 用户点名具体公司/股票..."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T02:24:38.784Z","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-09T02:24:38.784Z","emptyReason":null},"stars":null,"forks":null,"downloads":9794,"packageName":null,"latestVersion":"1.0.3","tractionLabel":"9.8K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T02:24:38.784Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T02:24:38.784Z","lastCrawledAt":"2026-10-09T02:24:38.784Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T02:24:38.784Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.3","createdAt":"2026-04-17T11:19:33.126Z","changelog":"Publish 1.0.3","fileCount":8,"zipByteSize":17070},{"version":"1.0.2","createdAt":"2026-04-10T11:04:35.217Z","changelog":"- update verify parameter","fileCount":7,"zipByteSize":15858},{"version":"1.0.1","createdAt":"2026-04-03T09:53:06.635Z","changelog":"- 调整了 openclaw metadata，增加 requires 字段并优化依赖说明。 - 精简描述，突出关键触发条件和应用市场。 - 其余核心业务逻辑、调用流程、输出规范与前置校验规则均保持一致。 - 没有新增代码或接口变更，仅文档结构化与表述优化。","fileCount":7,"zipByteSize":15854},{"version":"1.0.0","createdAt":"2026-03-27T10:29:18.555Z","changelog":"Initial release of stock-earnings-review skill. - Generates earnings reviews for listed companies upon user request for financial or earnings analysis. - Supports company/stock analysis across China A-share, Beijing, Hong Kong, and US markets. - Provides stepwise scripts for entity recognition, report period matching, and review generation, with PDF/Word attachments saved locally. - Debug mode outputs detailed JSON logs for each processing stage. - Enforces strict error handling and security protocols; does not fabricate results if pre-checks fail. - Includes robust documentation and usage examples for integration.","fileCount":7,"zipByteSize":15903}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s172qfps754dhtdynwv0gwshes83mtd4:stock-earnings-review","setupComplexity":"low","setupSteps":["Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.","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-financial-ai-analyst-stock-earnings-review/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-financial-ai-analyst-stock-earnings-review/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-financial-ai-analyst-stock-earnings-review/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-financial-ai-analyst-stock-earnings-review/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-financial-ai-analyst-stock-earnings-review/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-financial-ai-analyst-stock-earnings-review/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-10T07:11:06.189Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-financial-ai-analyst-stock-earnings-review/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-financial-ai-analyst-stock-earnings-review/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-financial-ai-analyst-stock-earnings-review/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-financial-ai-analyst-stock-earnings-review/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-09T02:24:38.784Z","emptyReason":null},"readme":"Skill: Earnings Review Agent\n\nOwner: financial-ai-analyst\n\nSummary: 依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。 当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。 用户点名具体公司/股票...\n\nTags: financial:1.0.2, latest:1.0.3, performance:1.0.2, research:1.0.2, stock:1.0.2, valuation:1.0.2\n\nVersion history:\n\nv1.0.3 | 2026-04-17T11:19:33.126Z | user\n\nPublish 1.0.3\n\nv1.0.2 | 2026-04-10T11:04:35.217Z | user\n\n- update verify parameter\n\nv1.0.1 | 2026-04-03T09:53:06.635Z | user\n\n- 调整了 openclaw metadata，增加 requires 字段并优化依赖说明。\n- 精简描述，突出关键触发条件和应用市场。\n- 其余核心业务逻辑、调用流程、输出规范与前置校验规则均保持一致。\n- 没有新增代码或接口变更，仅文档结构化与表述优化。\n\nv1.0.0 | 2026-03-27T10:29:18.555Z | user\n\nInitial release of stock-earnings-review skill.\n\n- Generates earnings reviews for listed companies upon user request for financial or earnings analysis.\n- Supports company/stock analysis across China A-share, Beijing, Hong Kong, and US markets.\n- Provides stepwise scripts for entity recognition, report period matching, and review generation, with PDF/Word attachments saved locally.\n- Debug mode outputs detailed JSON logs for each processing stage.\n- Enforces strict error handling and security protocols; does not fabricate results if pre-checks fail.\n- Includes robust documentation and usage examples for integration.\n\nArchive index:\n\nArchive v1.0.3: 8 files, 17070 bytes\n\nFiles: BUSINESS_LOGIC.md (7690b), scripts/call_review_api.py (4355b), scripts/common.py (7057b), scripts/normalize_report_period.py (4598b), scripts/validate_entity.py (2629b), skill-card.md (2283b), SKILL.md (9434b), _meta.json (140b)\n\nFile v1.0.3:SKILL.md\n\n---\nname: stock-earnings-review\ndescription: >\n  依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。\n  当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。\n  用户点名具体公司/股票并希望获得业绩与盈利维度的分析评价时，应触发本 Skill。\n  即使用户未明说「业绩点评」，只要意图是对该公司财报或业绩作分析解读，也应触发。\nmetadata:\n  {\n    \"openclaw\": {\n      \"requires\": {\n        \"env\":[\"EM_API_KEY\"]\n      },\n      \"install\": [\n        {\n          \"id\": \"pip-deps\",\n          \"kind\": \"python\",\n          \"package\": \"httpx\",\n          \"label\": \"Install Python dependencies\"\n        }\n      ]\n    }\n  }\n---\n\n# 上市公司业绩点评 (stock-earnings-review)\n\n通过用户问句完成**实体识别 → 报告期匹配 → 业绩点评接口生成**，并在本地保存 PDF/Word 附件（base64 解码保存）。`JSON` 过程日志仅在 `debug` 模式落盘。最终对用户返回标题、接口 `content` 文本整理结果、附件本地路径、溯源说明与分享链接。\n\n## 密钥来源与安全说明\n\n- 本技能仅使用一个环境变量：`EM_API_KEY`（请求头 `em_api_key`）。\n- `EM_API_KEY` 由东方财富妙想相关服务签发，用于接口鉴权；使用前请确认来源、范围与有效期。\n- 禁止在代码、提示词、日志或输出中硬编码或明文暴露密钥。\n\n## 上层编排协议（支持分步骤调用）\n\n本 skill 采用**分步骤调用**：由大模型按流程依次调用  \n1) `scripts/validate_entity.py` 获得实体  \n2) `scripts/normalize_report_period.py` 获得报告期候选  \n3) 大模型基于用户语义选择 `reportDate`  \n4) `scripts/call_review_api.py` 生成点评并保存附件\n\n无论采用哪种方式，**禁止**仅由大模型凭知识库「编造」业绩点评全文并冒充 skill 结果。\n\n## 输出目录与文件结构（默认）\n\n与 `mx_macro_data` 相同约定：**默认根目录**为当前工作目录下的 `miaoxiang/stock-earnings-review/`（无需手动创建，脚本会自动 `mkdir`）。\n\n每次执行会在该根目录下再创建**一次运行子目录**（`run_id`，含时间戳与短 UUID），结构如下：\n\n| 路径（相对本次 run 根目录） | 说明 |\n|----------------------------|------|\n| `01_entity.json` | 实体识别结果（仅 `--debug`） |\n| `02_report_period.json` | 报告期列表与匹配结果（仅 `--debug`） |\n| `03_comment_raw.json` | 业绩点评接口原始响应（仅 `--debug`） |\n| `04_review_result.json` | 解析后的点评结果与章节信息（仅 `--debug`） |\n| `05_final_result.json` | 汇总与 `finalOutput`（仅 `--debug`） |\n| `attachments/review.pdf` | 接口返回 `pdfBase64` 解码后的文件（若接口有返回） |\n| `attachments/review.doc` | 接口返回 `wordBase64` 解码后的文件（若接口有返回） |\n\n**说明**：若接口未返回对应 base64，则不会生成对应文件。非 `debug` 模式不会生成 `01~05.json`，但附件仍会保存。\n\n## 环境变量\n\n| 变量名 | 说明 | 默认 |\n|--------|------|------|\n| `EM_API_KEY` | 接口鉴权密钥（必填） | 无 |\n| `STOCK_EARNINGS_REVIEW_OUTPUT_DIR` | 日志与附件的**根目录**（其下仍按每次 run 分子目录） | `miaoxiang/stock-earnings-review`（相对当前工作目录） |\n| `EARNINGS_REVIEW_LOG_DIR` | 与上一项同义，兼容旧配置 | 同上 |\n\n\n## 前提条件\n\n### 1. 配置 `EM_API_KEY`\n\n```bash\n# macOS / Linux\nexport EM_API_KEY=\"your_api_key_here\"\n```\n\n```powershell\n# Windows PowerShell\n$env:EM_API_KEY=\"your_api_key_here\"\n```\n\n### 2. 安装依赖\n\n```bash\npip3 install httpx --user\n```\n\n## 快速开始\n\n### 分步骤调用（适配外层大模型编排）\n\n```bash\n# 第一步：实体识别\npython3 {baseDir}/stock-earnings-review/scripts/validate_entity.py --query \"东方财富 业绩点评\"\n\n# 第二步：获取报告期候选\npython3 {baseDir}/stock-earnings-review/scripts/normalize_report_period.py \\\n  --secu-code 300059 --market-char SZ --class-code 002001\n\n# 第三步：外层大模型选择 reportDate 后调用点评\npython3 {baseDir}/stock-earnings-review/scripts/call_review_api.py \\\n  --secu-code 300059 --market-char SZ --class-code 002001 \\\n  --report-date 2025-12-31 --secu-name 东方财富\n```\n\n可选参数：\n\n| 参数 | 说明 | 必填 |\n|------|------|------|\n| `validate_entity.py --query` | 用户原始问句（需含公司/股票信息） | ✅ |\n| `normalize_report_period.py --selected-report-date` | 可选，由上层模型已决策时传入；传入值须在候选列表中 | 否 |\n| `call_review_api.py --attachment-dir` | 附件保存目录；不传则默认为 `miaoxiang/stock-earnings-review/<run_id>/attachments` | 否 |\n| `call_review_api.py --debug` | 输出完整中间字段并落盘调试日志 | 否 |\n\n注意：**禁止调用 任何「后台执行、稍后汇报」的方式跑本脚本**，只能在当前会话中同步等待到命令完成，拿到 stdout 的结果后再继续，否则会导致本 Skill 失败。\n\n---\n\n## 处理流程（摘要）\n\n整体流程分为三步：实体识别与市场校验 → 报告期匹配 → 生成点评并落盘。\n\n### 第一步：实体识别与市场校验\n\n调用 `scripts/validate_entity.py`，将用户**原始问句**传入实体识别接口，返回 `secuCode`、`marketChar`、`classCode`、`secuName` 等；多个实体时取第一个。\n\n### 第二步：报告期匹配\n\n调用 `scripts/normalize_report_period.py` 获取报告期列表；由**上层模型**根据用户意图选择 `reportDate`（或通过 `--report-date` 传入）。若用户未指定报告期，默认取列表中**最新一期**（以脚本实现为准）。\n\n`/assistant/write/choice/reportList` 接口返回的是该实体**已发布**的报告期列表，不包含未发布报告期。\n例如请求 `{\"emCode\":\"NVDA.O\"}` 时，返回结果即为英伟达已发布报告期集合。\n\n### 第三步：业绩点评与落盘\n\n调用 `scripts/call_review_api.py`，请求业绩点评接口，解析标题与正文 `content`，将 PDF/Word base64 写入 `attachments/`。各阶段 JSON 日志仅在 `debug` 模式写入。\n\n#### 对用户输出格式（逻辑）\n\n- **标题**：接口返回标题。\n- **正文**：直接基于接口返回的 `content` 文本进行整理后输出。\n- **分享链接**：接口返回的 `shareUrl`。\n- **文件路径**：返回 `files.pdf` / `files.word` / `files.dataSheet`（若生成）。\n\n第三步 `call_review_api.py` 输出仅使用以下字段：`title`、`content`、`shareUrl`、`files`。\n\n#### 输出格式模板（Markdown 示意）\n\n```markdown\n# {title}\n\n{content}\n\n如需查看详细信息，请查看附件 PDF 或 DOC.......\n- **附件**：{files}\n- **分享链接**：{shareUrl}\n```\n\n### 关键约束（必须遵守）\n\n- 不要尝试读取、解析或总结 `review.pdf` / `review.doc` 的文件内容。\n- 不要因为 PDF 文本截断或 DOC 为二进制而再次走“读附件内容”的流程。\n- 仅基于 `call_review_api.py` 返回的结构化字段（尤其是 `summary`/`content`）整理并回复用户。\n\n### 前置校验失败约束（必须遵守）\n\n- 出现以下任一情况必须立即停止流程，不得继续调用后续接口，不得编造结果：\n  - 实体识别为空或实体不在支持范围；\n  - 报告期列表为空；\n  - 用户指定的 `selected_report_date` 不在候选列表（`strict` 模式）。\n- 当脚本返回 `ok=false` 或返回体中存在 `message` 字段时，必须原样输出 `message`，不得改写或替换。\n- 当报告期匹配失败且运行在非严格模式时，可回退到最新一期，但必须明确提示“已回退到最新可用报告期”。\n\n---\n\n## 格式要求\n\n响应中的数学公式格式：\n\n- 行内公式使用 `\\(...\\)` 格式（不使用 `$...$`）\n- 行间公式使用 `\\[...\\]` 格式\n- 行间公式块内部内容保持不变\n\n## 错误处理汇总\n\n| 错误场景 | 处理方式 |\n|----------|----------|\n| 问句中无实体 | 向用户确认需要点评的公司名称 |\n| 实体识别失败 | 提示用户确认公司名称或股票代码 |\n| 实体不在支持市场 | 返回「目前仅支持沪深京港美实体进行业绩点评」 |\n| 报告期列表为空 | 提示「暂无该实体的可用报告期数据」 |\n| 报告期接口调用失败 | 提示「暂时无法获取报告期信息，请稍后重试」 |\n| 业绩点评接口调用失败 | 提示「业绩点评生成失败，请稍后重试」 |\n| 用户要求看完整正文 | 直接返回接口 `content` 文本；如需原文件可提示附件路径，但不读取附件内容 |\n\n## 脚本与文档\n\n| 脚本/文件 | 功能 |\n|-----------|------|\n| `scripts/validate_entity.py` | 实体识别 |\n| `scripts/normalize_report_period.py` | 报告期列表与匹配 |\n| `scripts/call_review_api.py` | 业绩点评接口与附件落盘 |\n| `BUSINESS_LOGIC.md` | **业务逻辑详版**：前置检查、报告期 A 股/港美股规则、交付模板、完整错误表、与脚本 `strict` 模式说明 |\n\n编排层实现完整规则时请同时阅读 `BUSINESS_LOGIC.md`。\n\nFile v1.0.3:_meta.json\n\n{\n  \"ownerId\": \"kn7b4ptpdag877t9kmq8axyja182taab\",\n  \"slug\": \"stock-earnings-review\",\n  \"version\": \"1.0.3\",\n  \"publishedAt\": 1776424773126\n}\n\nFile v1.0.3:BUSINESS_LOGIC.md\n\n# stock-earnings-review — 业务逻辑说明（详版）\n\n本文档保留编排层（大模型 / 规划引擎）需要遵循的**完整业务规则**，与精简后的 `SKILL.md` 配套使用。  \n实现细节以 `scripts/` 下代码及仓库根目录 `api_integration.md` 为准。\n\n调用方式说明：本 skill 采用**分步骤编排**（实体识别 -> 报告期候选 -> 模型选期 -> 业绩点评）。\n\n---\n\n## 1. 前置检查（进入流程前）\n\n- 若用户问句中**未提及**任何公司名称、股票简称或股票代码，**不要**进入实体识别与后续接口调用；应直接向用户确认需要点评的公司或代码。\n- 常见实体形式包括：\n  - 公司全称（如「贵州茅台酒股份有限公司」）\n  - 股票简称（如「东方财富」「腾讯控股」）\n  - 股票代码（如「600519」「AAPL」）\n- 若用户输入中**出现多个实体**，优先取**第一个**明确的公司实体。\n\n---\n\n## 2. 第一步：实体识别与市场校验\n\n### 2.1 调用方式\n\n- 调用 `scripts/validate_entity.py`，将用户的**原始问句**作为输入，请求实体识别接口，一次性完成实体识别与市场分类校验。\n\n### 2.2 脚本侧期望输出（概念）\n\n- 成功：返回标准化实体信息，至少包括：\n  - `secuCode`：股票代码  \n  - `marketChar`：市场代码（如 SH / SZ / BJ / HK / US 等，以接口为准）  \n  - `classCode`：市场分类码（用于判断是否属于支持的市场）  \n  - `secuName`：证券简称（如有）\n- 多个候选时：**取第一个**有效实体。\n\n### 2.3 编排层分支\n\n| 情况 | 处理 |\n|------|------|\n| 识别成功且属于支持市场 | 进入第二步 |\n| 识别结果为空或不支持的市场 | 提示：**「目前仅支持沪深京港美实体进行业绩点评。您提供的实体不在支持范围内，请确认后重新输入。」**（或等价表述），终止流程 |\n| 接口失败 / 脚本异常 | 提示接口或系统错误，终止流程 |\n\n---\n\n## 3. 第二步：报告期列表与匹配\n\n### 3.1 报告期列表获取\n\n- 调用 `scripts/normalize_report_period.py`，传入第一步得到的实体信息，由脚本请求**报告期列表接口**，得到该标的**已披露**的报告期集合。\n\n### 3.2 谁来选择具体报告期（核心）\n\n- **由上层模型（或调用方）**根据用户问句、实体及完整报告期列表，选定一个 `reportDate`（格式一般为 `YYYY-MM-DD`）。这是分步骤编排中的关键决策步骤。\n- 模型选定的 `reportDate` 可通过 `normalize_report_period.py --selected-report-date` 做有效性校验；未传时默认取候选列表第一项（通常为最新）。\n\n### 3.3 用户意图解析（编排层建议）\n\n1. 从问句中解析报告期意图：年份、季度类型、是否「最新」「最近」等。  \n2. 结合市场类型在列表中匹配**最佳**报告期。  \n3. 若用户**完全未指定**报告期，或仅表述为「最新」「最近一期」等，通常对应列表中的**最新一期**（列表排序以接口返回为准，一般为新→旧）。\n\n### 3.4 A 股报告期匹配（自然年≈财年，可直接按日期匹配）\n\n- 用户指定**年份 + 季度**（如「2024 年三季报」）→ 在列表中**精确匹配**对应报告期末日。  \n- 用户只指定**季度**未指定年份（如「三季报」）→ 在列表中匹配**最近一次**出现的该季度。  \n- 用户只指定**年份**未指定季度（如「2024 年」）→ 匹配该自然年内列表中**最新可用**的一期。  \n- 季度与报告期常见对应：一季报 / 半年报 / 三季报 / 年报（全年）等，以列表中实际 `reportDate` 为准。\n\n### 3.5 港美股报告期匹配（财年与自然年可能不一致）\n\n- 港美股公司财年结束日可能不是 12 月；用户说的「2024 年年报」在不同公司上对应的**自然日期区间**可能不同。  \n- 建议规则：  \n  - 用户使用**自然年**表述 → 按自然年维度在列表中匹配；  \n  - 用户使用**财年**表述（如 FY2024）→ 按财年语义匹配；  \n  - 若财年与自然年表述**产生歧义**，优先按**财年**匹配，并在最终输出中**说明**该公司财年结束月份及本次匹配到的自然报告期。\n\n### 3.6 匹配失败与近似匹配\n\n| 情况 | 编排层建议 |\n|------|------------|\n| 列表中**无精确匹配** | 可选用**时间最接近**的一期，并明确提示：「未找到精确匹配的报告期，已为您匹配最接近的报告期：{实际 reportDate }」 |\n| 报告期列表**为空** | 提示「暂无该实体的可用报告期数据」，终止 |\n| 接口失败 | 提示「暂时无法获取报告期信息，请稍后重试」，终止 |\n\n### 3.7 与当前脚本行为的关系（重要）\n\n- `choose_report_option_by_model(..., strict=True)` 下：若传入的 `selected_report_date` **不在**接口返回的候选列表中，脚本会**报错**，而**不会**静默回退到「最接近一期」。  \n- 因此：编排层若采用「最接近报告期」策略，应自行算好目标日期并保证传入值**落在列表中**，或调整调用方式（例如先不向脚本传错误日期）。  \n- 未传 `selected_report_date` 时，当前实现为取列表**第一项**作为默认（通常需保证接口列表已按新→旧排序）。\n\n---\n\n## 4. 第三步：业绩点评生成与交付形态\n\n### 4.1 调用方式\n\n- 调用 `scripts/call_review_api.py`，传入实体信息与最终 `reportDate`。\n- 日志口径统一：`JSON` 过程日志（如 `01~05.json`、`03_comment_raw.json`）仅在 `debug` 模式下落盘；非 `debug` 模式不生成这些日志文件。\n- 附件口径统一：无论是否 `debug`，只要接口返回了 `pdfBase64` / `wordBase64`（及可选的数据底稿 base64），都应正常保存到本地附件目录。\n\n### 4.2 若第二步存在附带说明\n\n- 若报告期为**近似匹配**、或港美股存在**财年说明**，应在最终输出**末尾**一并展示，避免用户误解所选报告期。\n\n---\n\n## 5. 数学与排版格式（对用户回复）\n\n- 行内公式：`\\(...\\)`（不使用 `$...$`）。  \n- 行间公式：`\\[...\\]`。  \n- 行间公式块内部内容保持与源一致。\n\n---\n\n## 6. 错误处理汇总（完整表）\n\n| 错误场景 | 处理方式 |\n|----------|----------|\n| 问句中无实体 | 向用户确认需要点评的公司名称 |\n| 实体识别失败 | 提示用户确认公司名称或股票代码 |\n| 实体不在支持市场 | 返回「目前仅支持沪深京港美实体进行业绩点评」 |\n| 报告期列表为空 | 提示「暂无该实体的可用报告期数据」 |\n| 报告期接口调用失败 | 提示「暂时无法获取报告期信息，请稍后重试」 |\n| 报告期无法从问句解析 | 引导用户明确报告期（如「请问您想查看哪个季度的报告？」） |\n| 报告期在列表中无法精确匹配 | 采用最接近一期并说明；**注意与脚本 `strict` 传参一致** |\n| 港美股财年歧义 | 说明财年结束月份及实际匹配到的自然报告期 |\n| 业绩点评接口调用失败 | 提示「业绩点评生成失败，请稍后重试」 |\n| 用户要求阅读完整正文 | 引导下载附件：「完整正文内容请查看附件中的 PDF 或 Word 版报告」 |\n\n---\n\n## 7. 与 `SKILL.md` 的分工\n\n| 文档 | 用途 |\n|------|------|\n| `SKILL.md` | OpenClaw 元数据、环境变量、目录结构、快速开始、编排强制协议（精简） |\n| `BUSINESS_LOGIC.md`（本文） | 前置检查、三步业务规则、报告期匹配细节、交付形态、完整错误表、与脚本差异说明 |\n\nFile v1.0.3:skill-card.md\n\n## Description:\n\nGenerates earnings review commentary for listed companies and stocks across Shanghai, Shenzhen, Beijing, Hong Kong, and U.S. markets using Eastmoney data.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[financial-ai-analyst](https://clawhub.ai/user/financial-ai-analyst)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and financial analysis agents use this skill to validate a company or stock, select a disclosed reporting period, and produce an earnings review with analysis text, a share link, and saved report attachments.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill sends user queries and stock or report identifiers to Eastmoney APIs.\n\nMitigation: Use only with data appropriate for that external service and provide an EM_API_KEY from a trusted, scoped source.\n\nRisk: The skill saves returned PDF, Word, or spreadsheet attachments locally and may write debug logs when debug mode is enabled.\n\nMitigation: Review the output directory, avoid debug mode for sensitive workflows unless needed, and handle saved files according to local data-retention requirements.\n\nRisk: Generated links and saved attachments are external content returned by the API service.\n\nMitigation: Review generated links and attachments before sharing or relying on them.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/financial-ai-analyst/skills/stock-earnings-review)\n- [Publisher profile](https://clawhub.ai/user/financial-ai-analyst)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, files, configuration, guidance]\n\n**Output Format:** [Markdown response with generated earnings commentary, share link, and local attachment paths; scripts return JSON.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May save PDF, Word, and spreadsheet attachments locally; debug mode may write intermediate JSON logs.]\n\n## Skill Version(s):\n\n1.0.3 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.2: 7 files, 15858 bytes\n\nFiles: BUSINESS_LOGIC.md (7690b), scripts/call_review_api.py (4355b), scripts/common.py (7057b), scripts/normalize_report_period.py (4598b), scripts/validate_entity.py (2629b), SKILL.md (9434b), _meta.json (140b)\n\nFile v1.0.2:SKILL.md\n\n---\nname: stock-earnings-review\ndescription: >\n  依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。\n  当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。\n  用户点名具体公司/股票并希望获得业绩与盈利维度的分析评价时，应触发本 Skill。\n  即使用户未明说「业绩点评」，只要意图是对该公司财报或业绩作分析解读，也应触发。\nmetadata:\n  {\n    \"openclaw\": {\n      \"requires\": {\n        \"env\":[\"EM_API_KEY\"]\n      },\n      \"install\": [\n        {\n          \"id\": \"pip-deps\",\n          \"kind\": \"python\",\n          \"package\": \"httpx\",\n          \"label\": \"Install Python dependencies\"\n        }\n      ]\n    }\n  }\n---\n\n# 上市公司业绩点评 (stock-earnings-review)\n\n通过用户问句完成**实体识别 → 报告期匹配 → 业绩点评接口生成**，并在本地保存 PDF/Word 附件（base64 解码保存）。`JSON` 过程日志仅在 `debug` 模式落盘。最终对用户返回标题、接口 `content` 文本整理结果、附件本地路径、溯源说明与分享链接。\n\n## 密钥来源与安全说明\n\n- 本技能仅使用一个环境变量：`EM_API_KEY`（请求头 `em_api_key`）。\n- `EM_API_KEY` 由东方财富妙想相关服务签发，用于接口鉴权；使用前请确认来源、范围与有效期。\n- 禁止在代码、提示词、日志或输出中硬编码或明文暴露密钥。\n\n## 上层编排协议（支持分步骤调用）\n\n本 skill 采用**分步骤调用**：由大模型按流程依次调用  \n1) `scripts/validate_entity.py` 获得实体  \n2) `scripts/normalize_report_period.py` 获得报告期候选  \n3) 大模型基于用户语义选择 `reportDate`  \n4) `scripts/call_review_api.py` 生成点评并保存附件\n\n无论采用哪种方式，**禁止**仅由大模型凭知识库「编造」业绩点评全文并冒充 skill 结果。\n\n## 输出目录与文件结构（默认）\n\n与 `mx_macro_data` 相同约定：**默认根目录**为当前工作目录下的 `miaoxiang/stock-earnings-review/`（无需手动创建，脚本会自动 `mkdir`）。\n\n每次执行会在该根目录下再创建**一次运行子目录**（`run_id`，含时间戳与短 UUID），结构如下：\n\n| 路径（相对本次 run 根目录） | 说明 |\n|----------------------------|------|\n| `01_entity.json` | 实体识别结果（仅 `--debug`） |\n| `02_report_period.json` | 报告期列表与匹配结果（仅 `--debug`） |\n| `03_comment_raw.json` | 业绩点评接口原始响应（仅 `--debug`） |\n| `04_review_result.json` | 解析后的点评结果与章节信息（仅 `--debug`） |\n| `05_final_result.json` | 汇总与 `finalOutput`（仅 `--debug`） |\n| `attachments/review.pdf` | 接口返回 `pdfBase64` 解码后的文件（若接口有返回） |\n| `attachments/review.doc` | 接口返回 `wordBase64` 解码后的文件（若接口有返回） |\n\n**说明**：若接口未返回对应 base64，则不会生成对应文件。非 `debug` 模式不会生成 `01~05.json`，但附件仍会保存。\n\n## 环境变量\n\n| 变量名 | 说明 | 默认 |\n|--------|------|------|\n| `EM_API_KEY` | 接口鉴权密钥（必填） | 无 |\n| `STOCK_EARNINGS_REVIEW_OUTPUT_DIR` | 日志与附件的**根目录**（其下仍按每次 run 分子目录） | `miaoxiang/stock-earnings-review`（相对当前工作目录） |\n| `EARNINGS_REVIEW_LOG_DIR` | 与上一项同义，兼容旧配置 | 同上 |\n\n\n## 前提条件\n\n### 1. 配置 `EM_API_KEY`\n\n```bash\n# macOS / Linux\nexport EM_API_KEY=\"your_api_key_here\"\n```\n\n```powershell\n# Windows PowerShell\n$env:EM_API_KEY=\"your_api_key_here\"\n```\n\n### 2. 安装依赖\n\n```bash\npip3 install httpx --user\n```\n\n## 快速开始\n\n### 分步骤调用（适配外层大模型编排）\n\n```bash\n# 第一步：实体识别\npython3 {baseDir}/stock-earnings-review/scripts/validate_entity.py --query \"东方财富 业绩点评\"\n\n# 第二步：获取报告期候选\npython3 {baseDir}/stock-earnings-review/scripts/normalize_report_period.py \\\n  --secu-code 300059 --market-char SZ --class-code 002001\n\n# 第三步：外层大模型选择 reportDate 后调用点评\npython3 {baseDir}/stock-earnings-review/scripts/call_review_api.py \\\n  --secu-code 300059 --market-char SZ --class-code 002001 \\\n  --report-date 2025-12-31 --secu-name 东方财富\n```\n\n可选参数：\n\n| 参数 | 说明 | 必填 |\n|------|------|------|\n| `validate_entity.py --query` | 用户原始问句（需含公司/股票信息） | ✅ |\n| `normalize_report_period.py --selected-report-date` | 可选，由上层模型已决策时传入；传入值须在候选列表中 | 否 |\n| `call_review_api.py --attachment-dir` | 附件保存目录；不传则默认为 `miaoxiang/stock-earnings-review/<run_id>/attachments` | 否 |\n| `call_review_api.py --debug` | 输出完整中间字段并落盘调试日志 | 否 |\n\n注意：**禁止调用 任何「后台执行、稍后汇报」的方式跑本脚本**，只能在当前会话中同步等待到命令完成，拿到 stdout 的结果后再继续，否则会导致本 Skill 失败。\n\n---\n\n## 处理流程（摘要）\n\n整体流程分为三步：实体识别与市场校验 → 报告期匹配 → 生成点评并落盘。\n\n### 第一步：实体识别与市场校验\n\n调用 `scripts/validate_entity.py`，将用户**原始问句**传入实体识别接口，返回 `secuCode`、`marketChar`、`classCode`、`secuName` 等；多个实体时取第一个。\n\n### 第二步：报告期匹配\n\n调用 `scripts/normalize_report_period.py` 获取报告期列表；由**上层模型**根据用户意图选择 `reportDate`（或通过 `--report-date` 传入）。若用户未指定报告期，默认取列表中**最新一期**（以脚本实现为准）。\n\n`/assistant/write/choice/reportList` 接口返回的是该实体**已发布**的报告期列表，不包含未发布报告期。\n例如请求 `{\"emCode\":\"NVDA.O\"}` 时，返回结果即为英伟达已发布报告期集合。\n\n### 第三步：业绩点评与落盘\n\n调用 `scripts/call_review_api.py`，请求业绩点评接口，解析标题与正文 `content`，将 PDF/Word base64 写入 `attachments/`。各阶段 JSON 日志仅在 `debug` 模式写入。\n\n#### 对用户输出格式（逻辑）\n\n- **标题**：接口返回标题。\n- **正文**：直接基于接口返回的 `content` 文本进行整理后输出。\n- **分享链接**：接口返回的 `shareUrl`。\n- **文件路径**：返回 `files.pdf` / `files.word` / `files.dataSheet`（若生成）。\n\n第三步 `call_review_api.py` 输出仅使用以下字段：`title`、`content`、`shareUrl`、`files`。\n\n#### 输出格式模板（Markdown 示意）\n\n```markdown\n# {title}\n\n{content}\n\n如需查看详细信息，请查看附件 PDF 或 DOC.......\n- **附件**：{files}\n- **分享链接**：{shareUrl}\n```\n\n### 关键约束（必须遵守）\n\n- 不要尝试读取、解析或总结 `review.pdf` / `review.doc` 的文件内容。\n- 不要因为 PDF 文本截断或 DOC 为二进制而再次走“读附件内容”的流程。\n- 仅基于 `call_review_api.py` 返回的结构化字段（尤其是 `summary`/`content`）整理并回复用户。\n\n### 前置校验失败约束（必须遵守）\n\n- 出现以下任一情况必须立即停止流程，不得继续调用后续接口，不得编造结果：\n  - 实体识别为空或实体不在支持范围；\n  - 报告期列表为空；\n  - 用户指定的 `selected_report_date` 不在候选列表（`strict` 模式）。\n- 当脚本返回 `ok=false` 或返回体中存在 `message` 字段时，必须原样输出 `message`，不得改写或替换。\n- 当报告期匹配失败且运行在非严格模式时，可回退到最新一期，但必须明确提示“已回退到最新可用报告期”。\n\n---\n\n## 格式要求\n\n响应中的数学公式格式：\n\n- 行内公式使用 `\\(...\\)` 格式（不使用 `$...$`）\n- 行间公式使用 `\\[...\\]` 格式\n- 行间公式块内部内容保持不变\n\n## 错误处理汇总\n\n| 错误场景 | 处理方式 |\n|----------|----------|\n| 问句中无实体 | 向用户确认需要点评的公司名称 |\n| 实体识别失败 | 提示用户确认公司名称或股票代码 |\n| 实体不在支持市场 | 返回「目前仅支持沪深京港美实体进行业绩点评」 |\n| 报告期列表为空 | 提示「暂无该实体的可用报告期数据」 |\n| 报告期接口调用失败 | 提示「暂时无法获取报告期信息，请稍后重试」 |\n| 业绩点评接口调用失败 | 提示「业绩点评生成失败，请稍后重试」 |\n| 用户要求看完整正文 | 直接返回接口 `content` 文本；如需原文件可提示附件路径，但不读取附件内容 |\n\n## 脚本与文档\n\n| 脚本/文件 | 功能 |\n|-----------|------|\n| `scripts/validate_entity.py` | 实体识别 |\n| `scripts/normalize_report_period.py` | 报告期列表与匹配 |\n| `scripts/call_review_api.py` | 业绩点评接口与附件落盘 |\n| `BUSINESS_LOGIC.md` | **业务逻辑详版**：前置检查、报告期 A 股/港美股规则、交付模板、完整错误表、与脚本 `strict` 模式说明 |\n\n编排层实现完整规则时请同时阅读 `BUSINESS_LOGIC.md`。\n\nFile v1.0.2:_meta.json\n\n{\n  \"ownerId\": \"kn7b4ptpdag877t9kmq8axyja182taab\",\n  \"slug\": \"stock-earnings-review\",\n  \"version\": \"1.0.2\",\n  \"publishedAt\": 1775819075217\n}\n\nFile v1.0.2:BUSINESS_LOGIC.md\n\n# stock-earnings-review — 业务逻辑说明（详版）\n\n本文档保留编排层（大模型 / 规划引擎）需要遵循的**完整业务规则**，与精简后的 `SKILL.md` 配套使用。  \n实现细节以 `scripts/` 下代码及仓库根目录 `api_integration.md` 为准。\n\n调用方式说明：本 skill 采用**分步骤编排**（实体识别 -> 报告期候选 -> 模型选期 -> 业绩点评）。\n\n---\n\n## 1. 前置检查（进入流程前）\n\n- 若用户问句中**未提及**任何公司名称、股票简称或股票代码，**不要**进入实体识别与后续接口调用；应直接向用户确认需要点评的公司或代码。\n- 常见实体形式包括：\n  - 公司全称（如「贵州茅台酒股份有限公司」）\n  - 股票简称（如「东方财富」「腾讯控股」）\n  - 股票代码（如「600519」「AAPL」）\n- 若用户输入中**出现多个实体**，优先取**第一个**明确的公司实体。\n\n---\n\n## 2. 第一步：实体识别与市场校验\n\n### 2.1 调用方式\n\n- 调用 `scripts/validate_entity.py`，将用户的**原始问句**作为输入，请求实体识别接口，一次性完成实体识别与市场分类校验。\n\n### 2.2 脚本侧期望输出（概念）\n\n- 成功：返回标准化实体信息，至少包括：\n  - `secuCode`：股票代码  \n  - `marketChar`：市场代码（如 SH / SZ / BJ / HK / US 等，以接口为准）  \n  - `classCode`：市场分类码（用于判断是否属于支持的市场）  \n  - `secuName`：证券简称（如有）\n- 多个候选时：**取第一个**有效实体。\n\n### 2.3 编排层分支\n\n| 情况 | 处理 |\n|------|------|\n| 识别成功且属于支持市场 | 进入第二步 |\n| 识别结果为空或不支持的市场 | 提示：**「目前仅支持沪深京港美实体进行业绩点评。您提供的实体不在支持范围内，请确认后重新输入。」**（或等价表述），终止流程 |\n| 接口失败 / 脚本异常 | 提示接口或系统错误，终止流程 |\n\n---\n\n## 3. 第二步：报告期列表与匹配\n\n### 3.1 报告期列表获取\n\n- 调用 `scripts/normalize_report_period.py`，传入第一步得到的实体信息，由脚本请求**报告期列表接口**，得到该标的**已披露**的报告期集合。\n\n### 3.2 谁来选择具体报告期（核心）\n\n- **由上层模型（或调用方）**根据用户问句、实体及完整报告期列表，选定一个 `reportDate`（格式一般为 `YYYY-MM-DD`）。这是分步骤编排中的关键决策步骤。\n- 模型选定的 `reportDate` 可通过 `normalize_report_period.py --selected-report-date` 做有效性校验；未传时默认取候选列表第一项（通常为最新）。\n\n### 3.3 用户意图解析（编排层建议）\n\n1. 从问句中解析报告期意图：年份、季度类型、是否「最新」「最近」等。  \n2. 结合市场类型在列表中匹配**最佳**报告期。  \n3. 若用户**完全未指定**报告期，或仅表述为「最新」「最近一期」等，通常对应列表中的**最新一期**（列表排序以接口返回为准，一般为新→旧）。\n\n### 3.4 A 股报告期匹配（自然年≈财年，可直接按日期匹配）\n\n- 用户指定**年份 + 季度**（如「2024 年三季报」）→ 在列表中**精确匹配**对应报告期末日。  \n- 用户只指定**季度**未指定年份（如「三季报」）→ 在列表中匹配**最近一次**出现的该季度。  \n- 用户只指定**年份**未指定季度（如「2024 年」）→ 匹配该自然年内列表中**最新可用**的一期。  \n- 季度与报告期常见对应：一季报 / 半年报 / 三季报 / 年报（全年）等，以列表中实际 `reportDate` 为准。\n\n### 3.5 港美股报告期匹配（财年与自然年可能不一致）\n\n- 港美股公司财年结束日可能不是 12 月；用户说的「2024 年年报」在不同公司上对应的**自然日期区间**可能不同。  \n- 建议规则：  \n  - 用户使用**自然年**表述 → 按自然年维度在列表中匹配；  \n  - 用户使用**财年**表述（如 FY2024）→ 按财年语义匹配；  \n  - 若财年与自然年表述**产生歧义**，优先按**财年**匹配，并在最终输出中**说明**该公司财年结束月份及本次匹配到的自然报告期。\n\n### 3.6 匹配失败与近似匹配\n\n| 情况 | 编排层建议 |\n|------|------------|\n| 列表中**无精确匹配** | 可选用**时间最接近**的一期，并明确提示：「未找到精确匹配的报告期，已为您匹配最接近的报告期：{实际 reportDate }」 |\n| 报告期列表**为空** | 提示「暂无该实体的可用报告期数据」，终止 |\n| 接口失败 | 提示「暂时无法获取报告期信息，请稍后重试」，终止 |\n\n### 3.7 与当前脚本行为的关系（重要）\n\n- `choose_report_option_by_model(..., strict=True)` 下：若传入的 `selected_report_date` **不在**接口返回的候选列表中，脚本会**报错**，而**不会**静默回退到「最接近一期」。  \n- 因此：编排层若采用「最接近报告期」策略，应自行算好目标日期并保证传入值**落在列表中**，或调整调用方式（例如先不向脚本传错误日期）。  \n- 未传 `selected_report_date` 时，当前实现为取列表**第一项**作为默认（通常需保证接口列表已按新→旧排序）。\n\n---\n\n## 4. 第三步：业绩点评生成与交付形态\n\n### 4.1 调用方式\n\n- 调用 `scripts/call_review_api.py`，传入实体信息与最终 `reportDate`。\n- 日志口径统一：`JSON` 过程日志（如 `01~05.json`、`03_comment_raw.json`）仅在 `debug` 模式下落盘；非 `debug` 模式不生成这些日志文件。\n- 附件口径统一：无论是否 `debug`，只要接口返回了 `pdfBase64` / `wordBase64`（及可选的数据底稿 base64），都应正常保存到本地附件目录。\n\n### 4.2 若第二步存在附带说明\n\n- 若报告期为**近似匹配**、或港美股存在**财年说明**，应在最终输出**末尾**一并展示，避免用户误解所选报告期。\n\n---\n\n## 5. 数学与排版格式（对用户回复）\n\n- 行内公式：`\\(...\\)`（不使用 `$...$`）。  \n- 行间公式：`\\[...\\]`。  \n- 行间公式块内部内容保持与源一致。\n\n---\n\n## 6. 错误处理汇总（完整表）\n\n| 错误场景 | 处理方式 |\n|----------|----------|\n| 问句中无实体 | 向用户确认需要点评的公司名称 |\n| 实体识别失败 | 提示用户确认公司名称或股票代码 |\n| 实体不在支持市场 | 返回「目前仅支持沪深京港美实体进行业绩点评」 |\n| 报告期列表为空 | 提示「暂无该实体的可用报告期数据」 |\n| 报告期接口调用失败 | 提示「暂时无法获取报告期信息，请稍后重试」 |\n| 报告期无法从问句解析 | 引导用户明确报告期（如「请问您想查看哪个季度的报告？」） |\n| 报告期在列表中无法精确匹配 | 采用最接近一期并说明；**注意与脚本 `strict` 传参一致** |\n| 港美股财年歧义 | 说明财年结束月份及实际匹配到的自然报告期 |\n| 业绩点评接口调用失败 | 提示「业绩点评生成失败，请稍后重试」 |\n| 用户要求阅读完整正文 | 引导下载附件：「完整正文内容请查看附件中的 PDF 或 Word 版报告」 |\n\n---\n\n## 7. 与 `SKILL.md` 的分工\n\n| 文档 | 用途 |\n|------|------|\n| `SKILL.md` | OpenClaw 元数据、环境变量、目录结构、快速开始、编排强制协议（精简） |\n| `BUSINESS_LOGIC.md`（本文） | 前置检查、三步业务规则、报告期匹配细节、交付形态、完整错误表、与脚本差异说明 |\n\nArchive v1.0.1: 7 files, 15854 bytes\n\nFiles: BUSINESS_LOGIC.md (7690b), scripts/call_review_api.py (4357b), scripts/common.py (7057b), scripts/normalize_report_period.py (4599b), scripts/validate_entity.py (2630b), SKILL.md (9426b), _meta.json (140b)\n\nFile v1.0.1:SKILL.md\n\n---\nname: stock-earnings-review\ndescription: >\n  依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。\n  当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。\n  用户点名具体公司/股票并希望获得业绩与盈利维度的分析评价时，应触发本 Skill。\n  即使用户未明说「业绩点评」，只要意图是对该公司财报或业绩作分析解读，也应触发。\nmetadata:\n  {\n    \"openclaw\": {\n      \"requires\": {\n        \"env\":[\"EM_API_KEY\"]\n      },\n      \"install\": [\n        {\n          \"id\": \"pip-deps\",\n          \"kind\": \"python\",\n          \"package\": \"httpx\",\n          \"label\": \"Install Python dependencies\"\n        }\n      ]\n    }\n  }\n---\n\n# 上市公司业绩点评 (stock-earnings-review)\n\n通过用户问句完成**实体识别 → 报告期匹配 → 业绩点评接口生成**，并在本地保存 PDF/Word 附件（base64 解码保存）。`JSON` 过程日志仅在 `debug` 模式落盘。最终对用户返回标题、接口 `content` 文本整理结果、附件本地路径、溯源说明与分享链接。\n\n## 密钥来源与安全说明\n\n- 本技能仅使用一个环境变量：`EM_API_KEY`（请求头 `em_api_key`）。\n- `EM_API_KEY` 由东方财富妙想相关服务签发，用于接口鉴权；使用前请确认来源、范围与有效期。\n- 禁止在代码、提示词、日志或输出中硬编码或明文暴露密钥。\n\n## 上层编排协议（支持分步骤调用）\n\n本 skill 采用**分步骤调用**：由大模型按流程依次调用\n1) `scripts/validate_entity.py` 获得实体\n2) `scripts/normalize_report_period.py` 获得报告期候选\n3) 大模型基于用户语义选择 `reportDate`\n4) `scripts/call_review_api.py` 生成点评并保存附件\n\n无论采用哪种方式，**禁止**仅由大模型凭知识库「编造」业绩点评全文并冒充 skill 结果。\n\n## 输出目录与文件结构（默认）\n\n与 `mx_macro_data` 相同约定：**默认根目录**为当前工作目录下的 `miaoxiang/stock-earnings-review/`（无需手动创建，脚本会自动 `mkdir`）。\n\n每次执行会在该根目录下再创建**一次运行子目录**（`run_id`，含时间戳与短 UUID），结构如下：\n\n| 路径（相对本次 run 根目录） | 说明 |\n|----------------------------|------|\n| `01_entity.json` | 实体识别结果（仅 `--debug`） |\n| `02_report_period.json` | 报告期列表与匹配结果（仅 `--debug`） |\n| `03_comment_raw.json` | 业绩点评接口原始响应（仅 `--debug`） |\n| `04_review_result.json` | 解析后的点评结果与章节信息（仅 `--debug`） |\n| `05_final_result.json` | 汇总与 `finalOutput`（仅 `--debug`） |\n| `attachments/review.pdf` | 接口返回 `pdfBase64` 解码后的文件（若接口有返回） |\n| `attachments/review.doc` | 接口返回 `wordBase64` 解码后的文件（若接口有返回） |\n\n**说明**：若接口未返回对应 base64，则不会生成对应文件。非 `debug` 模式不会生成 `01~05.json`，但附件仍会保存。\n\n## 环境变量\n\n| 变量名 | 说明 | 默认 |\n|--------|------|------|\n| `EM_API_KEY` | 接口鉴权密钥（必填） | 无 |\n| `STOCK_EARNINGS_REVIEW_OUTPUT_DIR` | 日志与附件的**根目录**（其下仍按每次 run 分子目录） | `miaoxiang/stock-earnings-review`（相对当前工作目录） |\n| `EARNINGS_REVIEW_LOG_DIR` | 与上一项同义，兼容旧配置 | 同上 |\n\n\n## 前提条件\n\n### 1. 配置 `EM_API_KEY`\n\n```bash\n# macOS / Linux\nexport EM_API_KEY=\"your_api_key_here\"\n```\n\n```powershell\n# Windows PowerShell\n$env:EM_API_KEY=\"your_api_key_here\"\n```\n\n### 2. 安装依赖\n\n```bash\npip3 install httpx --user\n```\n\n## 快速开始\n\n### 分步骤调用（适配外层大模型编排）\n\n```bash\n# 第一步：实体识别\npython3 {baseDir}/stock-earnings-review/scripts/validate_entity.py --query \"东方财富 业绩点评\"\n\n# 第二步：获取报告期候选\npython3 {baseDir}/stock-earnings-review/scripts/normalize_report_period.py \\\n  --secu-code 300059 --market-char SZ --class-code 002001\n\n# 第三步：外层大模型选择 reportDate 后调用点评\npython3 {baseDir}/stock-earnings-review/scripts/call_review_api.py \\\n  --secu-code 300059 --market-char SZ --class-code 002001 \\\n  --report-date 2025-12-31 --secu-name 东方财富\n```\n\n可选参数：\n\n| 参数 | 说明 | 必填 |\n|------|------|------|\n| `validate_entity.py --query` | 用户原始问句（需含公司/股票信息） | ✅ |\n| `normalize_report_period.py --selected-report-date` | 可选，由上层模型已决策时传入；传入值须在候选列表中 | 否 |\n| `call_review_api.py --attachment-dir` | 附件保存目录；不传则默认为 `miaoxiang/stock-earnings-review/<run_id>/attachments` | 否 |\n| `call_review_api.py --debug` | 输出完整中间字段并落盘调试日志 | 否 |\n\n注意：**禁止调用 任何「后台执行、稍后汇报」的方式跑本脚本**，只能在当前会话中同步等待到命令完成，拿到 stdout 的结果后再继续，否则会导致本 Skill 失败。\n\n---\n\n## 处理流程（摘要）\n\n整体流程分为三步：实体识别与市场校验 → 报告期匹配 → 生成点评并落盘。\n\n### 第一步：实体识别与市场校验\n\n调用 `scripts/validate_entity.py`，将用户**原始问句**传入实体识别接口，返回 `secuCode`、`marketChar`、`classCode`、`secuName` 等；多个实体时取第一个。\n\n### 第二步：报告期匹配\n\n调用 `scripts/normalize_report_period.py` 获取报告期列表；由**上层模型**根据用户意图选择 `reportDate`（或通过 `--report-date` 传入）。若用户未指定报告期，默认取列表中**最新一期**（以脚本实现为准）。\n\n`/assistant/write/choice/reportList` 接口返回的是该实体**已发布**的报告期列表，不包含未发布报告期。\n例如请求 `{\"emCode\":\"NVDA.O\"}` 时，返回结果即为英伟达已发布报告期集合。\n\n### 第三步：业绩点评与落盘\n\n调用 `scripts/call_review_api.py`，请求业绩点评接口，解析标题与正文 `content`，将 PDF/Word base64 写入 `attachments/`。各阶段 JSON 日志仅在 `debug` 模式写入。\n\n#### 对用户输出格式（逻辑）\n\n- **标题**：接口返回标题。\n- **正文**：直接基于接口返回的 `content` 文本进行整理后输出。\n- **分享链接**：接口返回的 `shareUrl`。\n- **文件路径**：返回 `files.pdf` / `files.word` / `files.dataSheet`（若生成）。\n\n第三步 `call_review_api.py` 输出仅使用以下字段：`title`、`content`、`shareUrl`、`files`。\n\n#### 输出格式模板（Markdown 示意）\n\n```markdown\n# {title}\n\n{content}\n\n如需查看详细信息，请查看附件 PDF 或 DOC.......\n- **附件**：{files}\n- **分享链接**：{shareUrl}\n```\n\n### 关键约束（必须遵守）\n\n- 不要尝试读取、解析或总结 `review.pdf` / `review.doc` 的文件内容。\n- 不要因为 PDF 文本截断或 DOC 为二进制而再次走“读附件内容”的流程。\n- 仅基于 `call_review_api.py` 返回的结构化字段（尤其是 `summary`/`content`）整理并回复用户。\n\n### 前置校验失败约束（必须遵守）\n\n- 出现以下任一情况必须立即停止流程，不得继续调用后续接口，不得编造结果：\n  - 实体识别为空或实体不在支持范围；\n  - 报告期列表为空；\n  - 用户指定的 `selected_report_date` 不在候选列表（`strict` 模式）。\n- 当脚本返回 `ok=false` 或返回体中存在 `message` 字段时，必须原样输出 `message`，不得改写或替换。\n- 当报告期匹配失败且运行在非严格模式时，可回退到最新一期，但必须明确提示“已回退到最新可用报告期”。\n\n---\n\n## 格式要求\n\n响应中的数学公式格式：\n\n- 行内公式使用 `\\(...\\)` 格式（不使用 `$...$`）\n- 行间公式使用 `\\[...\\]` 格式\n- 行间公式块内部内容保持不变\n\n## 错误处理汇总\n\n| 错误场景 | 处理方式 |\n|----------|----------|\n| 问句中无实体 | 向用户确认需要点评的公司名称 |\n| 实体识别失败 | 提示用户确认公司名称或股票代码 |\n| 实体不在支持市场 | 返回「目前仅支持沪深京港美实体进行业绩点评」 |\n| 报告期列表为空 | 提示「暂无该实体的可用报告期数据」 |\n| 报告期接口调用失败 | 提示「暂时无法获取报告期信息，请稍后重试」 |\n| 业绩点评接口调用失败 | 提示「业绩点评生成失败，请稍后重试」 |\n| 用户要求看完整正文 | 直接返回接口 `content` 文本；如需原文件可提示附件路径，但不读取附件内容 |\n\n## 脚本与文档\n\n| 脚本/文件 | 功能 |\n|-----------|------|\n| `scripts/validate_entity.py` | 实体识别 |\n| `scripts/normalize_report_period.py` | 报告期列表与匹配 |\n| `scripts/call_review_api.py` | 业绩点评接口与附件落盘 |\n| `BUSINESS_LOGIC.md` | **业务逻辑详版**：前置检查、报告期 A 股/港美股规则、交付模板、完整错误表、与脚本 `strict` 模式说明 |\n\n编排层实现完整规则时请同时阅读 `BUSINESS_LOGIC.md`。\n\nFile v1.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn7b4ptpdag877t9kmq8axyja182taab\",\n  \"slug\": \"stock-earnings-review\",\n  \"version\": \"1.0.1\",\n  \"publishedAt\": 1775209986635\n}\n\nFile v1.0.1:BUSINESS_LOGIC.md\n\n# stock-earnings-review — 业务逻辑说明（详版）\n\n本文档保留编排层（大模型 / 规划引擎）需要遵循的**完整业务规则**，与精简后的 `SKILL.md` 配套使用。  \n实现细节以 `scripts/` 下代码及仓库根目录 `api_integration.md` 为准。\n\n调用方式说明：本 skill 采用**分步骤编排**（实体识别 -> 报告期候选 -> 模型选期 -> 业绩点评）。\n\n---\n\n## 1. 前置检查（进入流程前）\n\n- 若用户问句中**未提及**任何公司名称、股票简称或股票代码，**不要**进入实体识别与后续接口调用；应直接向用户确认需要点评的公司或代码。\n- 常见实体形式包括：\n  - 公司全称（如「贵州茅台酒股份有限公司」）\n  - 股票简称（如「东方财富」「腾讯控股」）\n  - 股票代码（如「600519」「AAPL」）\n- 若用户输入中**出现多个实体**，优先取**第一个**明确的公司实体。\n\n---\n\n## 2. 第一步：实体识别与市场校验\n\n### 2.1 调用方式\n\n- 调用 `scripts/validate_entity.py`，将用户的**原始问句**作为输入，请求实体识别接口，一次性完成实体识别与市场分类校验。\n\n### 2.2 脚本侧期望输出（概念）\n\n- 成功：返回标准化实体信息，至少包括：\n  - `secuCode`：股票代码  \n  - `marketChar`：市场代码（如 SH / SZ / BJ / HK / US 等，以接口为准）  \n  - `classCode`：市场分类码（用于判断是否属于支持的市场）  \n  - `secuName`：证券简称（如有）\n- 多个候选时：**取第一个**有效实体。\n\n### 2.3 编排层分支\n\n| 情况 | 处理 |\n|------|------|\n| 识别成功且属于支持市场 | 进入第二步 |\n| 识别结果为空或不支持的市场 | 提示：**「目前仅支持沪深京港美实体进行业绩点评。您提供的实体不在支持范围内，请确认后重新输入。」**（或等价表述），终止流程 |\n| 接口失败 / 脚本异常 | 提示接口或系统错误，终止流程 |\n\n---\n\n## 3. 第二步：报告期列表与匹配\n\n### 3.1 报告期列表获取\n\n- 调用 `scripts/normalize_report_period.py`，传入第一步得到的实体信息，由脚本请求**报告期列表接口**，得到该标的**已披露**的报告期集合。\n\n### 3.2 谁来选择具体报告期（核心）\n\n- **由上层模型（或调用方）**根据用户问句、实体及完整报告期列表，选定一个 `reportDate`（格式一般为 `YYYY-MM-DD`）。这是分步骤编排中的关键决策步骤。\n- 模型选定的 `reportDate` 可通过 `normalize_report_period.py --selected-report-date` 做有效性校验；未传时默认取候选列表第一项（通常为最新）。\n\n### 3.3 用户意图解析（编排层建议）\n\n1. 从问句中解析报告期意图：年份、季度类型、是否「最新」「最近」等。  \n2. 结合市场类型在列表中匹配**最佳**报告期。  \n3. 若用户**完全未指定**报告期，或仅表述为「最新」「最近一期」等，通常对应列表中的**最新一期**（列表排序以接口返回为准，一般为新→旧）。\n\n### 3.4 A 股报告期匹配（自然年≈财年，可直接按日期匹配）\n\n- 用户指定**年份 + 季度**（如「2024 年三季报」）→ 在列表中**精确匹配**对应报告期末日。  \n- 用户只指定**季度**未指定年份（如「三季报」）→ 在列表中匹配**最近一次**出现的该季度。  \n- 用户只指定**年份**未指定季度（如「2024 年」）→ 匹配该自然年内列表中**最新可用**的一期。  \n- 季度与报告期常见对应：一季报 / 半年报 / 三季报 / 年报（全年）等，以列表中实际 `reportDate` 为准。\n\n### 3.5 港美股报告期匹配（财年与自然年可能不一致）\n\n- 港美股公司财年结束日可能不是 12 月；用户说的「2024 年年报」在不同公司上对应的**自然日期区间**可能不同。  \n- 建议规则：  \n  - 用户使用**自然年**表述 → 按自然年维度在列表中匹配；  \n  - 用户使用**财年**表述（如 FY2024）→ 按财年语义匹配；  \n  - 若财年与自然年表述**产生歧义**，优先按**财年**匹配，并在最终输出中**说明**该公司财年结束月份及本次匹配到的自然报告期。\n\n### 3.6 匹配失败与近似匹配\n\n| 情况 | 编排层建议 |\n|------|------------|\n| 列表中**无精确匹配** | 可选用**时间最接近**的一期，并明确提示：「未找到精确匹配的报告期，已为您匹配最接近的报告期：{实际 reportDate }」 |\n| 报告期列表**为空** | 提示「暂无该实体的可用报告期数据」，终止 |\n| 接口失败 | 提示「暂时无法获取报告期信息，请稍后重试」，终止 |\n\n### 3.7 与当前脚本行为的关系（重要）\n\n- `choose_report_option_by_model(..., strict=True)` 下：若传入的 `selected_report_date` **不在**接口返回的候选列表中，脚本会**报错**，而**不会**静默回退到「最接近一期」。  \n- 因此：编排层若采用「最接近报告期」策略，应自行算好目标日期并保证传入值**落在列表中**，或调整调用方式（例如先不向脚本传错误日期）。  \n- 未传 `selected_report_date` 时，当前实现为取列表**第一项**作为默认（通常需保证接口列表已按新→旧排序）。\n\n---\n\n## 4. 第三步：业绩点评生成与交付形态\n\n### 4.1 调用方式\n\n- 调用 `scripts/call_review_api.py`，传入实体信息与最终 `reportDate`。\n- 日志口径统一：`JSON` 过程日志（如 `01~05.json`、`03_comment_raw.json`）仅在 `debug` 模式下落盘；非 `debug` 模式不生成这些日志文件。\n- 附件口径统一：无论是否 `debug`，只要接口返回了 `pdfBase64` / `wordBase64`（及可选的数据底稿 base64），都应正常保存到本地附件目录。\n\n### 4.2 若第二步存在附带说明\n\n- 若报告期为**近似匹配**、或港美股存在**财年说明**，应在最终输出**末尾**一并展示，避免用户误解所选报告期。\n\n---\n\n## 5. 数学与排版格式（对用户回复）\n\n- 行内公式：`\\(...\\)`（不使用 `$...$`）。  \n- 行间公式：`\\[...\\]`。  \n- 行间公式块内部内容保持与源一致。\n\n---\n\n## 6. 错误处理汇总（完整表）\n\n| 错误场景 | 处理方式 |\n|----------|----------|\n| 问句中无实体 | 向用户确认需要点评的公司名称 |\n| 实体识别失败 | 提示用户确认公司名称或股票代码 |\n| 实体不在支持市场 | 返回「目前仅支持沪深京港美实体进行业绩点评」 |\n| 报告期列表为空 | 提示「暂无该实体的可用报告期数据」 |\n| 报告期接口调用失败 | 提示「暂时无法获取报告期信息，请稍后重试」 |\n| 报告期无法从问句解析 | 引导用户明确报告期（如「请问您想查看哪个季度的报告？」） |\n| 报告期在列表中无法精确匹配 | 采用最接近一期并说明；**注意与脚本 `strict` 传参一致** |\n| 港美股财年歧义 | 说明财年结束月份及实际匹配到的自然报告期 |\n| 业绩点评接口调用失败 | 提示「业绩点评生成失败，请稍后重试」 |\n| 用户要求阅读完整正文 | 引导下载附件：「完整正文内容请查看附件中的 PDF 或 Word 版报告」 |\n\n---\n\n## 7. 与 `SKILL.md` 的分工\n\n| 文档 | 用途 |\n|------|------|\n| `SKILL.md` | OpenClaw 元数据、环境变量、目录结构、快速开始、编排强制协议（精简） |\n| `BUSINESS_LOGIC.md`（本文） | 前置检查、三步业务规则、报告期匹配细节、交付形态、完整错误表、与脚本差异说明 |\n\nArchive v1.0.0: 7 files, 15903 bytes\n\nFiles: BUSINESS_LOGIC.md (7690b), scripts/call_review_api.py (4485b), scripts/common.py (7275b), scripts/normalize_report_period.py (4599b), scripts/validate_entity.py (2709b), SKILL.md (9556b), _meta.json (140b)\n\nFile v1.0.0:SKILL.md\n\n---\r\nname: stock-earnings-review\r\ndescription: >\r\n  业绩点评生成 skill。当用户请求对某个上市公司（股票）进行业绩点评、财报分析、业绩解读时触发此 skill。\r\n  触发关键词包括但不限于：业绩点评、财报点评、业绩分析、季报/半年报/年报点评、财务分析、盈利分析、\r\n  业绩解读等。支持沪深京港美五大市场的上市公司。当用户提到某个公司/股票名称并希望获得业绩方面的\r\n  分析评价时，请务必使用此 skill。即使用户没有明确说「业绩点评」，只要意图是对某公司财报或业绩进行\r\n  分析解读，也应该触发此 skill。\r\nmetadata:\r\n  {\r\n    \"openclaw\": {\r\n      \"install\": [\r\n        {\r\n          \"id\": \"pip-deps\",\r\n          \"kind\": \"python\",\r\n          \"package\": \"httpx\",\r\n          \"label\": \"Install Python dependencies\"\r\n        }\r\n      ]\r\n    }\r\n  }\r\n---\r\n\r\n# 上市公司业绩点评 (stock-earnings-review)\r\n\r\n通过用户问句完成**实体识别 → 报告期匹配 → 业绩点评接口生成**，并在本地保存 PDF/Word 附件（base64 解码保存）。`JSON` 过程日志仅在 `debug` 模式落盘。最终对用户返回标题、接口 `content` 文本整理结果、附件本地路径、溯源说明与分享链接。\r\n\r\n## 密钥来源与安全说明\r\n\r\n- 本技能仅使用一个环境变量：`EM_API_KEY`（请求头 `em_api_key`）。\r\n- `EM_API_KEY` 由东方财富妙想相关服务签发，用于接口鉴权；使用前请确认来源、范围与有效期。\r\n- 禁止在代码、提示词、日志或输出中硬编码或明文暴露密钥。\r\n\r\n## 上层编排协议（支持分步骤调用）\r\n\r\n本 skill 采用**分步骤调用**：由大模型按流程依次调用  \r\n1) `scripts/validate_entity.py` 获得实体  \r\n2) `scripts/normalize_report_period.py` 获得报告期候选  \r\n3) 大模型基于用户语义选择 `reportDate`  \r\n4) `scripts/call_review_api.py` 生成点评并保存附件\r\n\r\n无论采用哪种方式，**禁止**仅由大模型凭知识库「编造」业绩点评全文并冒充 skill 结果。\r\n\r\n## 输出目录与文件结构（默认）\r\n\r\n与 `mx_macro_data` 相同约定：**默认根目录**为当前工作目录下的 `miaoxiang/stock-earnings-review/`（无需手动创建，脚本会自动 `mkdir`）。\r\n\r\n每次执行会在该根目录下再创建**一次运行子目录**（`run_id`，含时间戳与短 UUID），结构如下：\r\n\r\n| 路径（相对本次 run 根目录） | 说明 |\r\n|----------------------------|------|\r\n| `01_entity.json` | 实体识别结果（仅 `--debug`） |\r\n| `02_report_period.json` | 报告期列表与匹配结果（仅 `--debug`） |\r\n| `03_comment_raw.json` | 业绩点评接口原始响应（仅 `--debug`） |\r\n| `04_review_result.json` | 解析后的点评结果与章节信息（仅 `--debug`） |\r\n| `05_final_result.json` | 汇总与 `finalOutput`（仅 `--debug`） |\r\n| `attachments/review.pdf` | 接口返回 `pdfBase64` 解码后的文件（若接口有返回） |\r\n| `attachments/review.doc` | 接口返回 `wordBase64` 解码后的文件（若接口有返回） |\r\n\r\n**说明**：若接口未返回对应 base64，则不会生成对应文件。非 `debug` 模式不会生成 `01~05.json`，但附件仍会保存。\r\n\r\n## 环境变量\r\n\r\n| 变量名 | 说明 | 默认 |\r\n|--------|------|------|\r\n| `EM_API_KEY` | 接口鉴权密钥（必填） | 无 |\r\n| `STOCK_EARNINGS_REVIEW_OUTPUT_DIR` | 日志与附件的**根目录**（其下仍按每次 run 分子目录） | `miaoxiang/stock-earnings-review`（相对当前工作目录） |\r\n| `EARNINGS_REVIEW_LOG_DIR` | 与上一项同义，兼容旧配置 | 同上 |\r\n\r\n\r\n## 前提条件\r\n\r\n### 1. 配置 `EM_API_KEY`\r\n\r\n```bash\r\n# macOS / Linux\r\nexport EM_API_KEY=\"your_api_key_here\"\r\n```\r\n\r\n```powershell\r\n# Windows PowerShell\r\n$env:EM_API_KEY=\"your_api_key_here\"\r\n```\r\n\r\n### 2. 安装依赖\r\n\r\n```bash\r\npip3 install httpx --user\r\n```\r\n\r\n## 快速开始\r\n\r\n### 分步骤调用（适配外层大模型编排）\r\n\r\n```bash\r\n# 第一步：实体识别\r\npython3 {baseDir}/stock-earnings-review/scripts/validate_entity.py --query \"东方财富 业绩点评\"\r\n\r\n# 第二步：获取报告期候选\r\npython3 {baseDir}/stock-earnings-review/scripts/normalize_report_period.py \\\r\n  --secu-code 300059 --market-char SZ --class-code 002001\r\n\r\n# 第三步：外层大模型选择 reportDate 后调用点评\r\npython3 {baseDir}/stock-earnings-review/scripts/call_review_api.py \\\r\n  --secu-code 300059 --market-char SZ --class-code 002001 \\\r\n  --report-date 2025-12-31 --secu-name 东方财富\r\n```\r\n\r\n可选参数：\r\n\r\n| 参数 | 说明 | 必填 |\r\n|------|------|------|\r\n| `validate_entity.py --query` | 用户原始问句（需含公司/股票信息） | ✅ |\r\n| `normalize_report_period.py --selected-report-date` | 可选，由上层模型已决策时传入；传入值须在候选列表中 | 否 |\r\n| `call_review_api.py --attachment-dir` | 附件保存目录；不传则默认为 `miaoxiang/stock-earnings-review/<run_id>/attachments` | 否 |\r\n| `call_review_api.py --debug` | 输出完整中间字段并落盘调试日志 | 否 |\r\n\r\n注意：**禁止调用 任何「后台执行、稍后汇报」的方式跑本脚本**，只能在当前会话中同步等待到命令完成，拿到 stdout 的结果后再继续，否则会导致本 Skill 失败。\r\n\r\n---\r\n\r\n## 处理流程（摘要）\r\n\r\n整体流程分为三步：实体识别与市场校验 → 报告期匹配 → 生成点评并落盘。\r\n\r\n### 第一步：实体识别与市场校验\r\n\r\n调用 `scripts/validate_entity.py`，将用户**原始问句**传入实体识别接口，返回 `secuCode`、`marketChar`、`classCode`、`secuName` 等；多个实体时取第一个。\r\n\r\n### 第二步：报告期匹配\r\n\r\n调用 `scripts/normalize_report_period.py` 获取报告期列表；由**上层模型**根据用户意图选择 `reportDate`（或通过 `--report-date` 传入）。若用户未指定报告期，默认取列表中**最新一期**（以脚本实现为准）。\r\n\r\n`/assistant/write/choice/reportList` 接口返回的是该实体**已发布**的报告期列表，不包含未发布报告期。\r\n例如请求 `{\"emCode\":\"NVDA.O\"}` 时，返回结果即为英伟达已发布报告期集合。\r\n\r\n### 第三步：业绩点评与落盘\r\n\r\n调用 `scripts/call_review_api.py`，请求业绩点评接口，解析标题与正文 `content`，将 PDF/Word base64 写入 `attachments/`。各阶段 JSON 日志仅在 `debug` 模式写入。\r\n\r\n#### 对用户输出格式（逻辑）\r\n\r\n- **标题**：接口返回标题。\r\n- **正文**：直接基于接口返回的 `content` 文本进行整理后输出。\r\n- **分享链接**：接口返回的 `shareUrl`。\r\n- **文件路径**：返回 `files.pdf` / `files.word` / `files.dataSheet`（若生成）。\r\n\r\n第三步 `call_review_api.py` 输出仅使用以下字段：`title`、`content`、`shareUrl`、`files`。\r\n\r\n#### 输出格式模板（Markdown 示意）\r\n\r\n```markdown\r\n# {title}\r\n\r\n{content}\r\n\r\n如需查看详细信息，请查看附件 PDF 或 DOC.......\r\n- **附件**：{files}\r\n- **分享链接**：{shareUrl}\r\n```\r\n\r\n### 关键约束（必须遵守）\r\n\r\n- 不要尝试读取、解析或总结 `review.pdf` / `review.doc` 的文件内容。\r\n- 不要因为 PDF 文本截断或 DOC 为二进制而再次走“读附件内容”的流程。\r\n- 仅基于 `call_review_api.py` 返回的结构化字段（尤其是 `summary`/`content`）整理并回复用户。\r\n\r\n### 前置校验失败约束（必须遵守）\r\n\r\n- 出现以下任一情况必须立即停止流程，不得继续调用后续接口，不得编造结果：\r\n  - 实体识别为空或实体不在支持范围；\r\n  - 报告期列表为空；\r\n  - 用户指定的 `selected_report_date` 不在候选列表（`strict` 模式）。\r\n- 当脚本返回 `ok=false` 或返回体中存在 `message` 字段时，必须原样输出 `message`，不得改写或替换。\r\n- 当报告期匹配失败且运行在非严格模式时，可回退到最新一期，但必须明确提示“已回退到最新可用报告期”。\r\n\r\n---\r\n\r\n## 格式要求\r\n\r\n响应中的数学公式格式：\r\n\r\n- 行内公式使用 `\\(...\\)` 格式（不使用 `$...$`）\r\n- 行间公式使用 `\\[...\\]` 格式\r\n- 行间公式块内部内容保持不变\r\n\r\n## 错误处理汇总\r\n\r\n| 错误场景 | 处理方式 |\r\n|----------|----------|\r\n| 问句中无实体 | 向用户确认需要点评的公司名称 |\r\n| 实体识别失败 | 提示用户确认公司名称或股票代码 |\r\n| 实体不在支持市场 | 返回「目前仅支持沪深京港美实体进行业绩点评」 |\r\n| 报告期列表为空 | 提示「暂无该实体的可用报告期数据」 |\r\n| 报告期接口调用失败 | 提示「暂时无法获取报告期信息，请稍后重试」 |\r\n| 业绩点评接口调用失败 | 提示「业绩点评生成失败，请稍后重试」 |\r\n| 用户要求看完整正文 | 直接返回接口 `content` 文本；如需原文件可提示附件路径，但不读取附件内容 |\r\n\r\n## 脚本与文档\r\n\r\n| 脚本/文件 | 功能 |\r\n|-----------|------|\r\n| `scripts/validate_entity.py` | 实体识别 |\r\n| `scripts/normalize_report_period.py` | 报告期列表与匹配 |\r\n| `scripts/call_review_api.py` | 业绩点评接口与附件落盘 |\r\n| `BUSINESS_LOGIC.md` | **业务逻辑详版**：前置检查、报告期 A 股/港美股规则、交付模板、完整错误表、与脚本 `strict` 模式说明 |\r\n\r\n编排层实现完整规则时请同时阅读 `BUSINESS_LOGIC.md`。\n\nFile v1.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b4ptpdag877t9kmq8axyja182taab\",\n  \"slug\": \"stock-earnings-review\",\n  \"version\": \"1.0.0\",\n  \"publishedAt\": 1774607358555\n}\n\nFile v1.0.0:BUSINESS_LOGIC.md\n\n# stock-earnings-review — 业务逻辑说明（详版）\n\n本文档保留编排层（大模型 / 规划引擎）需要遵循的**完整业务规则**，与精简后的 `SKILL.md` 配套使用。  \n实现细节以 `scripts/` 下代码及仓库根目录 `api_integration.md` 为准。\n\n调用方式说明：本 skill 采用**分步骤编排**（实体识别 -> 报告期候选 -> 模型选期 -> 业绩点评）。\n\n---\n\n## 1. 前置检查（进入流程前）\n\n- 若用户问句中**未提及**任何公司名称、股票简称或股票代码，**不要**进入实体识别与后续接口调用；应直接向用户确认需要点评的公司或代码。\n- 常见实体形式包括：\n  - 公司全称（如「贵州茅台酒股份有限公司」）\n  - 股票简称（如「东方财富」「腾讯控股」）\n  - 股票代码（如「600519」「AAPL」）\n- 若用户输入中**出现多个实体**，优先取**第一个**明确的公司实体。\n\n---\n\n## 2. 第一步：实体识别与市场校验\n\n### 2.1 调用方式\n\n- 调用 `scripts/validate_entity.py`，将用户的**原始问句**作为输入，请求实体识别接口，一次性完成实体识别与市场分类校验。\n\n### 2.2 脚本侧期望输出（概念）\n\n- 成功：返回标准化实体信息，至少包括：\n  - `secuCode`：股票代码  \n  - `marketChar`：市场代码（如 SH / SZ / BJ / HK / US 等，以接口为准）  \n  - `classCode`：市场分类码（用于判断是否属于支持的市场）  \n  - `secuName`：证券简称（如有）\n- 多个候选时：**取第一个**有效实体。\n\n### 2.3 编排层分支\n\n| 情况 | 处理 |\n|------|------|\n| 识别成功且属于支持市场 | 进入第二步 |\n| 识别结果为空或不支持的市场 | 提示：**「目前仅支持沪深京港美实体进行业绩点评。您提供的实体不在支持范围内，请确认后重新输入。」**（或等价表述），终止流程 |\n| 接口失败 / 脚本异常 | 提示接口或系统错误，终止流程 |\n\n---\n\n## 3. 第二步：报告期列表与匹配\n\n### 3.1 报告期列表获取\n\n- 调用 `scripts/normalize_report_period.py`，传入第一步得到的实体信息，由脚本请求**报告期列表接口**，得到该标的**已披露**的报告期集合。\n\n### 3.2 谁来选择具体报告期（核心）\n\n- **由上层模型（或调用方）**根据用户问句、实体及完整报告期列表，选定一个 `reportDate`（格式一般为 `YYYY-MM-DD`）。这是分步骤编排中的关键决策步骤。\n- 模型选定的 `reportDate` 可通过 `normalize_report_period.py --selected-report-date` 做有效性校验；未传时默认取候选列表第一项（通常为最新）。\n\n### 3.3 用户意图解析（编排层建议）\n\n1. 从问句中解析报告期意图：年份、季度类型、是否「最新」「最近」等。  \n2. 结合市场类型在列表中匹配**最佳**报告期。  \n3. 若用户**完全未指定**报告期，或仅表述为「最新」「最近一期」等，通常对应列表中的**最新一期**（列表排序以接口返回为准，一般为新→旧）。\n\n### 3.4 A 股报告期匹配（自然年≈财年，可直接按日期匹配）\n\n- 用户指定**年份 + 季度**（如「2024 年三季报」）→ 在列表中**精确匹配**对应报告期末日。  \n- 用户只指定**季度**未指定年份（如「三季报」）→ 在列表中匹配**最近一次**出现的该季度。  \n- 用户只指定**年份**未指定季度（如「2024 年」）→ 匹配该自然年内列表中**最新可用**的一期。  \n- 季度与报告期常见对应：一季报 / 半年报 / 三季报 / 年报（全年）等，以列表中实际 `reportDate` 为准。\n\n### 3.5 港美股报告期匹配（财年与自然年可能不一致）\n\n- 港美股公司财年结束日可能不是 12 月；用户说的「2024 年年报」在不同公司上对应的**自然日期区间**可能不同。  \n- 建议规则：  \n  - 用户使用**自然年**表述 → 按自然年维度在列表中匹配；  \n  - 用户使用**财年**表述（如 FY2024）→ 按财年语义匹配；  \n  - 若财年与自然年表述**产生歧义**，优先按**财年**匹配，并在最终输出中**说明**该公司财年结束月份及本次匹配到的自然报告期。\n\n### 3.6 匹配失败与近似匹配\n\n| 情况 | 编排层建议 |\n|------|------------|\n| 列表中**无精确匹配** | 可选用**时间最接近**的一期，并明确提示：「未找到精确匹配的报告期，已为您匹配最接近的报告期：{实际 reportDate }」 |\n| 报告期列表**为空** | 提示「暂无该实体的可用报告期数据」，终止 |\n| 接口失败 | 提示「暂时无法获取报告期信息，请稍后重试」，终止 |\n\n### 3.7 与当前脚本行为的关系（重要）\n\n- `choose_report_option_by_model(..., strict=True)` 下：若传入的 `selected_report_date` **不在**接口返回的候选列表中，脚本会**报错**，而**不会**静默回退到「最接近一期」。  \n- 因此：编排层若采用「最接近报告期」策略，应自行算好目标日期并保证传入值**落在列表中**，或调整调用方式（例如先不向脚本传错误日期）。  \n- 未传 `selected_report_date` 时，当前实现为取列表**第一项**作为默认（通常需保证接口列表已按新→旧排序）。\n\n---\n\n## 4. 第三步：业绩点评生成与交付形态\n\n### 4.1 调用方式\n\n- 调用 `scripts/call_review_api.py`，传入实体信息与最终 `reportDate`。\n- 日志口径统一：`JSON` 过程日志（如 `01~05.json`、`03_comment_raw.json`）仅在 `debug` 模式下落盘；非 `debug` 模式不生成这些日志文件。\n- 附件口径统一：无论是否 `debug`，只要接口返回了 `pdfBase64` / `wordBase64`（及可选的数据底稿 base64），都应正常保存到本地附件目录。\n\n### 4.2 若第二步存在附带说明\n\n- 若报告期为**近似匹配**、或港美股存在**财年说明**，应在最终输出**末尾**一并展示，避免用户误解所选报告期。\n\n---\n\n## 5. 数学与排版格式（对用户回复）\n\n- 行内公式：`\\(...\\)`（不使用 `$...$`）。  \n- 行间公式：`\\[...\\]`。  \n- 行间公式块内部内容保持与源一致。\n\n---\n\n## 6. 错误处理汇总（完整表）\n\n| 错误场景 | 处理方式 |\n|----------|----------|\n| 问句中无实体 | 向用户确认需要点评的公司名称 |\n| 实体识别失败 | 提示用户确认公司名称或股票代码 |\n| 实体不在支持市场 | 返回「目前仅支持沪深京港美实体进行业绩点评」 |\n| 报告期列表为空 | 提示「暂无该实体的可用报告期数据」 |\n| 报告期接口调用失败 | 提示「暂时无法获取报告期信息，请稍后重试」 |\n| 报告期无法从问句解析 | 引导用户明确报告期（如「请问您想查看哪个季度的报告？」） |\n| 报告期在列表中无法精确匹配 | 采用最接近一期并说明；**注意与脚本 `strict` 传参一致** |\n| 港美股财年歧义 | 说明财年结束月份及实际匹配到的自然报告期 |\n| 业绩点评接口调用失败 | 提示「业绩点评生成失败，请稍后重试」 |\n| 用户要求阅读完整正文 | 引导下载附件：「完整正文内容请查看附件中的 PDF 或 Word 版报告」 |\n\n---\n\n## 7. 与 `SKILL.md` 的分工\n\n| 文档 | 用途 |\n|------|------|\n| `SKILL.md` | OpenClaw 元数据、环境变量、目录结构、快速开始、编排强制协议（精简） |\n| `BUSINESS_LOGIC.md`（本文） | 前置检查、三步业务规则、报告期匹配细节、交付形态、完整错误表、与脚本差异说明 |","readmeExcerpt":"Skill: Earnings Review Agent Owner: financial-ai-analyst Summary: 依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。 当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。 用户点名具体公司/股票... Tags: financial:1.0.2, latest:1.0.3, performance:1.0.2, research:1.0.2, stock:1.0.2, valuation:1.0.2 Version history: v1.0.3 | 2026-04-17T11:19:33.126Z | user Publish 1.0.3 v1.0.2 | 2026-04-10T","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"# macOS / Linux\nexport EM_API_KEY=\"your_api_key_here\""},{"language":"powershell","snippet":"# Windows PowerShell\n$env:EM_API_KEY=\"your_api_key_here\""},{"language":"bash","snippet":"pip3 install httpx --user"},{"language":"bash","snippet":"# 第一步：实体识别\npython3 {baseDir}/stock-earnings-review/scripts/validate_entity.py --query \"东方财富 业绩点评\"\n\n# 第二步：获取报告期候选\npython3 {baseDir}/stock-earnings-review/scripts/normalize_report_period.py \\\n  --secu-code 300059 --market-char SZ --class-code 002001\n\n# 第三步：外层大模型选择 reportDate 后调用点评\npython3 {baseDir}/stock-earnings-review/scripts/call_review_api.py \\\n  --secu-code 300059 --market-char SZ --class-code 002001 \\\n  --report-date 2025-12-31 --secu-name 东方财富"},{"language":"markdown","snippet":"# {title}\n\n{content}\n\n如需查看详细信息，请查看附件 PDF 或 DOC.......\n- **附件**：{files}\n- **分享链接**：{shareUrl}"},{"language":"bash","snippet":"# macOS / Linux\nexport EM_API_KEY=\"your_api_key_here\""}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: stock-earnings-review\ndescription: >\n  依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。\n  当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。\n  用户点名具体公司/股票并希望获得业绩与盈利维度的分析评价时，应触发本 Skill。\n  即使用户未明说「业绩点评」，只要意图是对该公司财报或业绩作分析解读，也应触发。\nmetadata:\n  {\n    \"openclaw\": {\n      \"requires\": {\n        \"env\":[\"EM_API_KEY\"]\n      },\n      \"install\": [\n        {\n          \"id\": \"pip-deps\",\n          \"kind\": \"python\",\n          \"package\": \"httpx\",\n          \"label\": \"Install Python dependencies\"\n        }\n      ]\n    }\n  }\n---\n\n# 上市公司业绩点评 (stock-earnings-review)\n\n通过用户问句完成**实体识别 → 报告期匹配 → 业绩点评接口生成**，并在本地保存 PDF/Word 附件（base64 解码保存）。`JSON` 过程日志仅在 `debug` 模式落盘。最终对用户返回标题、接口 `content` 文本整理结果、附件本地路径、溯源说明与分享链接。\n\n## 密钥来源与安全说明\n\n- 本技能仅使用一个环境变量：`EM_API_KEY`（请求头 `em_api_key`）。\n- `EM_API_KEY` 由东方财富妙想相关服务签发，用于接口鉴权；使用前请确认来源、范围与有效期。\n- 禁止在代码、提示词、日志或输出中硬编码或明文暴露密钥。\n\n## 上层编排协议（支持分步骤调用）\n\n本 skill 采用**分步骤调用**：由大模型按流程依次调用  \n1) `scripts/validate_entity.py` 获得实体  \n2) `scripts/normalize_report_period.py` 获得报告期候选  \n3) 大模型基于用户语义选择 `reportDate`  \n4) `scripts/call_review_api.py` 生成点评并保存附件\n\n无论采用哪种方式，**禁止**仅由大模型凭知识库「编造」业绩点评全文并冒充 skill 结果。\n\n## 输出目录与文件结构（默认）\n\n与 `mx_macro_data` 相同约定：**默认根目录**为当前工作目录下的 `miaoxiang/stock-earnings-review/`（无需手动创建，脚本会自动 `mkdir`）。\n\n每次执行会在该根目录下再创建**一次运行子目录**（`run_id`，含时间戳与短 UUID），结构如下：\n\n| 路径（相对本次 run 根目录） | 说明 |\n|----------------------------|------|\n| `01_entity.json` | 实体识别结果（仅 `--debug`） |\n| `02_report_period.json` | 报告期列表与匹配结果（仅 `--debug`） |\n| `03_comment_raw.json` | 业绩点评接口原始响应（仅 `--debug`） |\n| `04_review_result.json` | 解析后的点评结果与章节信息（仅 `--debug`） |\n| `05_final_result.json` | 汇总与 `finalOutput`（仅 `--debug`） |\n| `attachments/review.pdf` | 接口返回 `pdfBase64` 解码后的文件（若接口有返回） |\n| `attachments/review.doc` | 接口返回 `wordBase64` 解码后的文件（若接口有返回） |\n\n**说明**：若接口未返回对应 base64，则不会生成对应文件。非 `debug` 模式不会生成 `01~05.json`，但附件仍会保存。\n\n## 环境变量\n\n| 变量名 | 说明 | 默认 |\n|--------|------|------|\n| `EM_API_KEY` | 接口鉴权密钥（必填） | 无 |\n| `STOCK_EARNINGS_REVIEW_OUTPUT_DIR` | 日志与附件的**根目录**（其下仍按每次 run 分子目录） | `miaoxiang/stock-earnings-review`（相对当前工作目录） |\n| `EARNINGS_REVIEW_LOG_DIR` | 与上一项同义，兼容旧配置 | 同上 |\n\n\n## 前提条件\n\n### 1. 配置 `EM_API_KEY`\n\n```bash\n# macOS / Linux\nexport EM_API_KEY=\"your_api_key_here\"\n```\n\n```powershell\n# Windows PowerShell\n$env:EM_API_KEY=\"your_api_key_here\"\n```\n\n### 2. 安装依赖\n\n```bash\npip3 install httpx --user\n```\n\n## 快速开始\n\n### 分步骤调用（适配外层大模型编排）\n\n```bash\n# 第一步：实体识别\npython3 {baseDir}/stock-earnings-review/scripts/validate_entity.py --query \"东方财富 业绩点评\"\n\n# 第二步：获取报告期候选\npython3 {baseDir}/stock-earnings-review/scripts/normalize_report_period.py \\\n  --secu-code 300059 --market-char SZ --class-code 002001\n\n# 第三步：外层大模型选择 reportDate 后调用点评\npython3 {baseDir}/stock-earnings-review/scripts/call_review_api.py \\\n  --secu-code 300059 --market-char SZ --class-code 002001 \\\n  --report-date 2025-12-31 --secu-name 东方财富\n```\n\n可选参数：\n\n| 参数 | 说明 | 必填 |\n|------|------|------|\n| `validate_entity.py --query` | 用户原始问句（需含公司/股票信息） | ✅ |\n| `normalize_report_period.py --selected-report-da"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7b4ptpdag877t9kmq8axyja182taab\",\n  \"slug\": \"stock-earnings-review\",\n  \"version\": \"1.0.3\",\n  \"publishedAt\": 1776424773126\n}"},{"path":"BUSINESS_LOGIC.md","content":"# stock-earnings-review — 业务逻辑说明（详版）\n\n本文档保留编排层（大模型 / 规划引擎）需要遵循的**完整业务规则**，与精简后的 `SKILL.md` 配套使用。  \n实现细节以 `scripts/` 下代码及仓库根目录 `api_integration.md` 为准。\n\n调用方式说明：本 skill 采用**分步骤编排**（实体识别 -> 报告期候选 -> 模型选期 -> 业绩点评）。\n\n---\n\n## 1. 前置检查（进入流程前）\n\n- 若用户问句中**未提及**任何公司名称、股票简称或股票代码，**不要**进入实体识别与后续接口调用；应直接向用户确认需要点评的公司或代码。\n- 常见实体形式包括：\n  - 公司全称（如「贵州茅台酒股份有限公司」）\n  - 股票简称（如「东方财富」「腾讯控股」）\n  - 股票代码（如「600519」「AAPL」）\n- 若用户输入中**出现多个实体**，优先取**第一个**明确的公司实体。\n\n---\n\n## 2. 第一步：实体识别与市场校验\n\n### 2.1 调用方式\n\n- 调用 `scripts/validate_entity.py`，将用户的**原始问句**作为输入，请求实体识别接口，一次性完成实体识别与市场分类校验。\n\n### 2.2 脚本侧期望输出（概念）\n\n- 成功：返回标准化实体信息，至少包括：\n  - `secuCode`：股票代码  \n  - `marketChar`：市场代码（如 SH / SZ / BJ / HK / US 等，以接口为准）  \n  - `classCode`：市场分类码（用于判断是否属于支持的市场）  \n  - `secuName`：证券简称（如有）\n- 多个候选时：**取第一个**有效实体。\n\n### 2.3 编排层分支\n\n| 情况 | 处理 |\n|------|------|\n| 识别成功且属于支持市场 | 进入第二步 |\n| 识别结果为空或不支持的市场 | 提示：**「目前仅支持沪深京港美实体进行业绩点评。您提供的实体不在支持范围内，请确认后重新输入。」**（或等价表述），终止流程 |\n| 接口失败 / 脚本异常 | 提示接口或系统错误，终止流程 |\n\n---\n\n## 3. 第二步：报告期列表与匹配\n\n### 3.1 报告期列表获取\n\n- 调用 `scripts/normalize_report_period.py`，传入第一步得到的实体信息，由脚本请求**报告期列表接口**，得到该标的**已披露**的报告期集合。\n\n### 3.2 谁来选择具体报告期（核心）\n\n- **由上层模型（或调用方）**根据用户问句、实体及完整报告期列表，选定一个 `reportDate`（格式一般为 `YYYY-MM-DD`）。这是分步骤编排中的关键决策步骤。\n- 模型选定的 `reportDate` 可通过 `normalize_report_period.py --selected-report-date` 做有效性校验；未传时默认取候选列表第一项（通常为最新）。\n\n### 3.3 用户意图解析（编排层建议）\n\n1. 从问句中解析报告期意图：年份、季度类型、是否「最新」「最近」等。  \n2. 结合市场类型在列表中匹配**最佳**报告期。  \n3. 若用户**完全未指定**报告期，或仅表述为「最新」「最近一期」等，通常对应列表中的**最新一期**（列表排序以接口返回为准，一般为新→旧）。\n\n### 3.4 A 股报告期匹配（自然年≈财年，可直接按日期匹配）\n\n- 用户指定**年份 + 季度**（如「2024 年三季报」）→ 在列表中**精确匹配**对应报告期末日。  \n- 用户只指定**季度**未指定年份（如「三季报」）→ 在列表中匹配**最近一次**出现的该季度。  \n- 用户只指定**年份**未指定季度（如「2024 年」）→ 匹配该自然年内列表中**最新可用**的一期。  \n- 季度与报告期常见对应：一季报 / 半年报 / 三季报 / 年报（全年）等，以列表中实际 `reportDate` 为准。\n\n### 3.5 港美股报告期匹配（财年与自然年可能不一致）\n\n- 港美股公司财年结束日可能不是 12 月；用户说的「2024 年年报」在不同公司上对应的**自然日期区间**可能不同。  \n- 建议规则：  \n  - 用户使用**自然年**表述 → 按自然年维度在列表中匹配；  \n  - 用户使用**财年**表述（如 FY2024）→ 按财年语义匹配；  \n  - 若财年与自然年表述**产生歧义**，优先按**财年**匹配，并在最终输出中**说明**该公司财年结束月份及本次匹配到的自然报告期。\n\n### 3.6 匹配失败与近似匹配\n\n| 情况 | 编排层建议 |\n|------|------------|\n| 列表中**无精确匹配** | 可选用**时间最接近**的一期，并明确提示：「未找到精确匹配的报告期，已为您匹配最接近的报告期：{实际 reportDate }」 |\n| 报告期列表**为空** | 提示「暂无该实体的可用报告期数据」，终止 |\n| 接口失败 | 提示「暂时无法获取报告期信息，请稍后重试」，终止 |\n\n### 3.7 与当前脚本行为的关系（重要）\n\n- `choose_report_option_by_model(..., strict=True)` 下：若传入的 `selected_report_date` **不在**接口返回的候选列表中，脚本会**报错**，而**不会**静默回退到「最接近一期」。  \n- 因此：编排层若采用「最接近报告期」策略，应自行算好目标日期并保证传入值**落在列表中**，或调整调用方式（例如先不向脚本传错误日期）。  \n- 未传 `selected_report_date` 时，当前实现为取列表**第一项**作为默认（通常需保证接口列表已按新→旧排序）。\n\n---\n\n## 4. 第三步：业绩点评生成与交付形态\n\n### 4.1 调用方式\n\n- 调用 `scripts/call_review_api.py`，传入实体信息与最终 `reportDate`。\n- 日志口径统一：`JSON` 过程日志（如 `01~05.json`、`03_comment_raw.json`）仅在 `debug` 模式下落盘；非 `debug` 模式不生成这些日志文件。\n- 附件口径统一：无论是否 `debug`，只要接口返回了 `pdfBase64` / `wordBase64`（及可选的数据底稿 base64），都应正常保存到本地附件目录。\n\n### 4.2 若第二步存在附带说明\n\n- 若报告期为**近似匹配**、或港美股存在**财年说明**，应在最终输出**末尾**一并展示，避免用户误解所选报告期。\n\n---\n\n## 5. 数学与排版格式（对用户回复）\n\n- 行内公式：`\\(...\\)`（不使用 `$...$`）。  \n- 行间公式：`\\[...\\]`。  \n- 行间公式块内部内容保持与源一致。\n\n---\n\n## 6. 错误处理汇总（完整表）\n\n| 错误场景 | 处理方式"},{"path":"skill-card.md","content":"## Description:\n\nGenerates earnings review commentary for listed companies and stocks across Shanghai, Shenzhen, Beijing, Hong Kong, and U.S. markets using Eastmoney data.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[financial-ai-analyst](https://clawhub.ai/user/financial-ai-analyst)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and financial analysis agents use this skill to validate a company or stock, select a disclosed reporting period, and produce an earnings review with analysis text, a share link, and saved report attachments.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill sends user queries and stock or report identifiers to Eastmoney APIs.\n\nMitigation: Use only with data appropriate for that external service and provide an EM_API_KEY from a trusted, scoped source.\n\nRisk: The skill saves returned PDF, Word, or spreadsheet attachments locally and may write debug logs when debug mode is enabled.\n\nMitigation: Review the output directory, avoid debug mode for sensitive workflows unless needed, and handle saved files according to local data-retention requirements.\n\nRisk: Generated links and saved attachments are external content returned by the API service.\n\nMitigation: Review generated links and attachments before sharing or relying on them.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/financial-ai-analyst/skills/stock-earnings-review)\n- [Publisher profile](https://clawhub.ai/user/financial-ai-analyst)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, files, configuration, guidance]\n\n**Output Format:** [Markdown response with generated earnings commentary, share link, and local attachment paths; scripts return JSON.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May save PDF, Word, and spreadsheet attachments locally; debug mode may write intermediate JSON logs.]\n\n## Skill Version(s):\n\n1.0.3 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。 当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。 用户点名具体公司/股票... Skill: Earnings Review Agent Owner: financial-ai-analyst Summary: 依托东方财富数据库，面向沪深京港美五大市场的上市公司/股票，生成业绩点评类输出（含财报分析、业绩解读）。 当用户明确提出业绩点评、财报分析、业绩解读需求，或出现「业绩点评」「财报点评」「业绩分析」「季报/半年报/年报点评」「财务分析」「盈利分析」「业绩解读」等表述时，应触发本 Skill。 用户点名具体公司/股票... Tags: financial:1.0.2, latest:1.0.3, performance:1.0.2, research:1.0.2, stock:1.0.2, valuation:1.0.2 Version history: v1.0.3 | 2026-04-17T11:19:33.126Z | user Publish 1.0.3 v1.0.2 | 2026-04-10T","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":956,"uniquenessScore":52,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T02:24:38.784Z","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-09T02:24:38.784Z","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-10T07:11:06.190Z","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"}]}}}