@clawhub-zhushanwei-6bfdaf69d7
舆情风险预诊工具。单段文本快速风险评估,输出风险评分 (1-10)、风险等级 (蓝/黄/橙/红/黑)、传播力×危害力矩阵。适用于客服筛查、社交媒体预检。
---
name: reputation-thermometer
description: 舆情风险预诊工具。单段文本快速风险评估,输出风险评分 (1-10)、风险等级 (蓝/黄/橙/红/黑)、传播力×危害力矩阵。适用于客服筛查、社交媒体预检。
---
# 声誉体温计 v4.0 (精简版)
AI 时代舆情"体温计"——快速判断哪条内容会爆。
## 核心功能
- **三维分析**: 情绪烈度 × 传播潜力 × AI 伪造嫌疑
- **风险等级**: 🔵蓝 (1-2.9) 🟡黄 (3-4.9) 🟠橙 (5-6.9) 🔴红 (7-8.9) ⚫黑 (9-10)
- **行业识别**: 食品/医疗/教育/金融/娱乐/职场
- **ML 分类器**: 轻量级贝叶斯 + 规则加权
## 使用
```bash
# 标准报告
python scripts/analyze_risk.py "文本"
# JSON 输出
python scripts/analyze_risk.py -j "文本"
```
## 风险等级响应
| 等级 | 评分 | 响应时限 | 处理 |
|-----|------|---------|------|
| ⚫ 黑 | 9-10 | 1h | 启动危机预案 |
| 🔴 红 | 7-8.9 | 2h | 高度关注 |
| 🟠 橙 | 5-6.9 | 4h | 建议关注 |
| 🟡 黄 | 3-4.9 | 24h | 保持观察 |
| 🔵 蓝 | 1-2.9 | - | 暂不处理 |
## 行业模板
| 行业 | 关键词 | 响应 |
|-----|-------|------|
| 食品/餐饮 | 中毒/呕吐/老鼠/地沟油 | 1h |
| 医疗/健康 | 死亡/误诊/疫苗 | 1h |
| 教育/培训 | 体罚/虐待/跑路 | 2h |
| 金融/理财 | 暴雷/失联/无法兑付 | 2h |
| 娱乐/明星 | 吸毒/出轨/偷税 | 4h |
| 职场/劳动 | 996/裁员/pua | 12h |
## 案例
| 输入 | 结果 |
|-----|------|
| "幼儿园食物中毒,50 名儿童送医" | 9.0/10, ⚫黑 |
| "歌手吸毒被抓,粉丝脱粉" | 7.5/10, 🔴红 |
| "餐厅吃出老鼠,顾客呕吐" | 6.2/10, 🟠橙 |
| "公司 996 加班,员工抱怨" | 3.5/10, 🟡黄 |
| "这家餐厅很好吃" | 1.0/10, 🔵蓝 |
## 限制
✅ 适合:单点预诊、初步筛查
❌ 不适合:全网监控、深度分析
## 版本
v4.1 (2026-03-24) - 精简版 (单脚本,14KB,137 行)
## 协议
MIT License
FILE:scripts/analyze_risk.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""声誉体温计 - 舆情风险预诊工具 v4.1 (精简版)"""
import json,sys,io,math
from datetime import datetime
from typing import Dict,List,Any,Tuple
from collections import defaultdict
if sys.platform=='win32':
sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8',errors='replace')
sys.stderr=io.TextIOWrapper(sys.stderr.buffer,encoding='utf-8',errors='replace')
EMOTION_KW="anger:愤怒,气愤,恶心,垃圾,骗子,黑心,维权,曝光,投诉,强烈,退款,欺诈,倒闭,坑人,智商税,潜规则,拖欠,克扣,滚蛋,滚出,抵制,侮辱,丑化,抹黑,傲慢,恶意|fear:害怕,恐惧,危险,安全,威胁,紧急,救命,求助,裁员,癌症,无助,封杀,辞退|sadness:悲伤,绝望,心痛,遗憾,可怜,悲剧,失望,去世,死了,死亡,受伤,呕吐,腹泻,送医,抢救,病危,婴儿,儿童,孩子|disgust:恶心,肮脏,无耻,垃圾,老鼠,虫子,地沟油,三聚氰胺,过期,虐待,偷税,吸毒,出轨,阴间审美,蜥蜴|surprise:震惊,意外,没想到,居然,竟然|contempt:呵呵,冷笑,鄙视,可笑,笑话,旱涝保收,专家,建议,肉糜,房租,闲置,吃不起饭"
VIRAL_KW="热搜,转发,扩散,爆料,曝光,真相,紧急,速看,震惊,突发,刚刚,实锤,明星,死亡,受伤,中毒,疫苗,过期,婴儿,儿童,幼儿园,跑路,暴雷,维权,拉横幅,围堵,偷税,吸毒,虐待,地沟油,三聚氰胺,火灾,爆炸,坍塌,事故,裁员,996,加班,欺诈,差评,避雷,老鼠,虫子,呕吐,腹泻,潜规则,出轨,塌房,拒赔,泄露,泄漏,数据安全,隐私,黑客,攻击,漏洞,违规,违法,监管,处罚,立案,调查,实名,身份证,手机号,银行卡,密码,账户,500 万,千万,百万,用户信息,个人信息,数据库,公网,备份,没钱,兑付,理财,利息,拆东墙,创始人,赶紧跑,被逼,滚出中国,抵制,丑化,侮辱,抹黑,辱华,傲慢,阴间审美,龙,蜥蜴,东方,文化,民族,品牌,广告,恶意,赚中国人的钱,小动作,国际品牌,内部消息,囤物资,交通管制,交警严查,紧急通知,谣言,造谣,恐慌"
SENSITIVE_KW="死亡,婴儿,儿童,孩子,幼儿,学生,中毒,病危,抢救,三聚氰胺,爆炸,坍塌,吸毒,偷税,未成年,虐待,地沟油,食品安全,群体中毒,多人死亡,药品,工业原料,爆料,拿命,老鼠,呕吐,潜规则,出轨,拒赔,暴雷,跑路,失联,无法兑付,投资人,血本无归,百亿,误诊,病情,数据泄露,隐私泄露,信息泄露,泄露,泄漏,黑客,攻击,漏洞,违规,违法,监管,处罚,立案,调查,实名,身份证,手机号,银行卡,密码,账户,用户信息,个人信息,数据库,网络安全,数据安全,没钱,兑付,理财,利息,拆东墙补西墙,创始人,赶紧跑,被逼,资金链断裂,庞氏骗局,丑化,侮辱,抹黑,辱华,傲慢,阴间审美,文化侮辱,民族情绪,抵制,滚出中国,国际品牌,内部消息,囤物资,交通管制,谣言,造谣,恐慌,全市,封路,封锁,紧急通知"
AI_PATTERNS="据知情人士,内部消息,独家渠道,匿名人士,网传,疑似,震惊!,重磅!,刚刚!,声音平稳,无呼吸,无停顿,AI 合成,AI 伪造,深度伪造,语音合成,TTS"
INDUSTRY_KW="food:中毒,腹泻,呕吐,老鼠,地沟油|medical:死亡,误诊,疫苗,红包|education:体罚,虐待,跑路,校车|finance:暴雷,跑路,失联,无法兑付|entertainment:吸毒,出轨,偷税,塌房|workplace:996,加班,裁员,pua"
ML_DATA="工厂爆炸 3 人死亡=黑|幼儿园校车侧翻儿童受伤=黑|奶粉检出三聚氰胺=黑|食物中毒 50 名儿童送医=黑|数据泄露 500 万用户信息曝光=黑|数据库公开到公网涉及百万实名=黑|用户隐私泄露监管立案调查=黑|理财平台暴雷无法兑付=红|创始人录音曝光公司没钱了=红|庞氏骗局拆东墙补西墙=红|品牌广告丑化中国抵制滚出中国=红|国际品牌辱华赚中国人的钱=红|紧急通知交通管制囤物资=黑|内部消息全市封路别出门=黑|歌手吸毒被抓=红|导演潜规则曝光=红|明星偷税漏税=红|保险公司拒赔=红|餐厅吃出老鼠=橙|医院误诊=橙|幼儿园虐待儿童=橙|食堂吃出虫子=橙|4S 店卖事故车=橙|专家建议吃不起饭可以吃肉糜=黄|没工作的人把闲置房租出去=黄|公司 996 加班=黄|年终奖缩水=黄|领导 pua 员工=黄|手机卡顿=黄|APP 闪退=黄|这家餐厅很好吃=蓝|快递很快=蓝|客服态度好=蓝|产品质量不错=蓝|明天公司团建=蓝"
def parse_kws(s,sep1='|',sep2=':'): return {p.split(sep2)[0]:p.split(sep2)[1].split(',') for p in s.split(sep1)} if sep2 in s else s.split(',')
EMOTION_KEYWORDS=parse_kws(EMOTION_KW)
INDUSTRY_TEMPLATES={k:{"name":{"food":"食品/餐饮","medical":"医疗/健康","education":"教育/培训","finance":"金融/理财","entertainment":"娱乐/明星","workplace":"职场/劳动"}[k],"keywords":v.split(','),"response":{"food":"1h","medical":"1h","education":"2h","finance":"2h","entertainment":"4h","workplace":"12h"}[k]} for k,v in [p.split(':') for p in INDUSTRY_KW.split('|')]}
ML_DATA=[p.rsplit('=',1) for p in ML_DATA.split('|')]
class MLClassifier:
def __init__(self):
self.classes=["蓝","黄","橙","红","黑"]
self.class_probs={}
self.word_probs=defaultdict(lambda:defaultdict(float))
self.train()
def train(self):
word_counts=defaultdict(lambda:defaultdict(int))
class_counts=defaultdict(int)
for text,label in ML_DATA:
class_counts[label]+=1
for char in text:
if '\u4e00'<=char<='\u9fff': word_counts[label][char]+=1
total_docs=len(ML_DATA)
vocab_size=len(set(c for t,_ in ML_DATA for c in t if '\u4e00'<=c<='\u9fff'))
for cls in self.classes:
self.class_probs[cls]=class_counts[cls]/total_docs
total_words=sum(word_counts[cls].values())
for word in word_counts[cls]:
self.word_probs[cls][word]=(word_counts[cls][word]+1)/(total_words+vocab_size)
def predict(self,text:str)->Tuple[str,float]:
log_probs={}
for cls in self.classes:
log_prob=math.log(self.class_probs.get(cls,0.01)+1e-10)
for char in text:
if '\u4e00'<=char<='\u9fff': log_prob+=math.log(self.word_probs[cls].get(char,1e-10)+1e-10)
log_probs[cls]=log_prob
if ("死亡" in text or "死了" in text) and ("儿童" in text or "婴儿" in text): log_probs["黑"]+=2.5
if "中毒" in text and ("食物" in text or "儿童" in text): log_probs["黑"]+=2.0
if any(k in text for k in ["暴雷","失联","跑路"]) and any(k in text for k in ["百亿","投资人"]): log_probs["红"]+=1.8
if any(k in text for k in ["吸毒","出轨","偷税"]) and any(k in text for k in ["明星","演员"]): log_probs["红"]+=1.5
best=max(log_probs,key=log_probs.get)
max_p=log_probs[best]
exp_p={c:math.exp(lp-max_p) for c,lp in log_probs.items()}
return best,round(exp_p[best]/sum(exp_p.values()),2)
def detect_industry(text:str)->str:
for ind,t in INDUSTRY_TEMPLATES.items():
if any(k in text for k in t["keywords"]): return ind
return "general"
def analyze_emotion(text:str)->Dict:
scores={e:min(sum(1 for k in kws if k in text)*2,10) for e,kws in EMOTION_KEYWORDS.items()}
matched=[e for e,s in scores.items() if s>0]
return {"score":max(scores.values()) if scores else 0,"emotions":matched}
def analyze_viral(text:str)->Dict:
viral=sum(1 for k in VIRAL_KW.split(',') if k in text)
sensitive=sum(1 for k in SENSITIVE_KW.split(',') if k in text)
return {"score":min(round(viral*1.5+sensitive*2,1),10),"keywords":viral,"sensitive":sensitive}
def analyze_ai(text:str)->Dict:
patterns=sum(1 for p in AI_PATTERNS.split(',') if p in text)
exclam=text.count("!")+text.count("!")
ai_score=patterns*2+min(exclam,5)
if "声音" in text and ("平稳" in text or "无呼吸" in text or "无停顿" in text): ai_score+=4
if "录音" in text and ("转录" in text or "合成" in text or "伪造" in text): ai_score+=3
return {"score":min(ai_score,10),"patterns":patterns}
def calc_risk(emotion:int,viral:int,ai:int,text:str,ml_level:str,ml_conf:float)->Dict:
harm=emotion*0.5+viral*0.4+ai*0.1
if ("死亡" in text or "死了" in text) and ("儿童" in text or "婴儿" in text): harm+=2
if "中毒" in text and ("群体" in text or "多人" in text): harm+=2
if "三聚氰胺" in text: harm+=2
if ("儿童" in text or "婴儿" in text or "孩子" in text or "幼儿" in text) and ("药" in text or "中毒" in text or "原料" in text or "食品" in text): harm+=2
if "爆料" in text or "内部" in text: harm+=1
if ("泄露" in text or "泄漏" in text or "公开" in text) and ("数据" in text or "信息" in text or "数据库" in text):
harm+=3 if any(k in text for k in ["500 万","千万","百万","大规模"]) else 2
if any(k in text for k in ["隐瞒","不上报","偷偷","当没发生过"]): harm+=2
if any(k in text for k in ["监管","违法","违规","处罚"]): harm+=1
if any(k in text for k in ["理财","兑付","利息"]) and any(k in text for k in ["没钱","无法","暴雷"]): harm+=2
if any(k in text for k in ["拆东墙补西墙","庞氏骗局"]): harm+=2
if any(k in text for k in ["创始人","董事长","CEO","老板"]) and any(k in text for k in ["跑路","被抓","录音"]): harm+=2
if any(k in text for k in ["丑化","侮辱","抹黑","辱华"]): harm+=2
if any(k in text for k in ["国际品牌","外国品牌"]) and any(k in text for k in ["赚中国人的钱","抵制","滚出中国"]): harm+=2
if any(k in text for k in ["阴间审美","文化侵略"]): harm+=1
if any(k in text for k in ["紧急通知","内部消息"]) and any(k in text for k in ["交通管制","封路","封锁","囤物资"]): harm+=3
if any(k in text for k in ["谣言","造谣"]): harm+=2
if "专家" in text and any(k in text for k in ["建议","肉糜","房租","闲置"]): harm+=1
harm=min(harm,10)
ml_scores={"蓝":1,"黄":3,"橙":6,"红":8,"黑":10}
trad=harm*0.5+viral*0.5
if harm>=8: trad=trad*0.8+ml_scores.get(ml_level,5)*0.2
elif ml_conf>=0.9: trad=trad*0.3+ml_scores.get(ml_level,5)*0.7
elif ml_conf>0.7: trad=trad*0.5+ml_scores.get(ml_level,5)*0.5
elif ml_conf>0.5: trad=trad*0.7+ml_scores.get(ml_level,5)*0.3
score=round(max(1,min(10,trad)),1)
if score>=8: level,sugg="黑","立即启动危机预案,1 小时内响应"
elif score>=6: level,sugg="红","高度关注,2 小时内制定方案"
elif score>=4: level,sugg="橙","建议关注,4 小时内评估"
elif score>=2: level,sugg="黄","保持观察,24 小时内复盘"
else: level,sugg="蓝","暂不处理,归档记录"
return {"score":score,"level":level,"suggestion":sugg,"harm":round(harm,1),"spread":round(viral,1)}
def analyze(text:str)->Dict:
emotion=analyze_emotion(text)
viral=analyze_viral(text)
ai=analyze_ai(text)
ml=MLClassifier()
ml_level,ml_conf=ml.predict(text)
industry=detect_industry(text)
risk=calc_risk(emotion["score"],viral["score"],ai["score"],text,ml_level,ml_conf)
tags=[]
if emotion["emotions"]: tags.append(f"情绪:{','.join(emotion['emotions'])}")
if viral["keywords"]>3: tags.append("高传播")
if viral["sensitive"]>0: tags.append("高敏感")
if ai["score"]>=6: tags.append("AI 嫌疑")
return {"risk_score":risk["score"],"risk_level":risk["level"],"suggestion":risk["suggestion"],"industry":INDUSTRY_TEMPLATES.get(industry,INDUSTRY_TEMPLATES["workplace"])["name"],"ml_prediction":{"level":ml_level,"confidence":ml_conf},"dimensions":{"emotion":emotion,"viral":viral,"ai":ai},"matrix":{"harm":risk["harm"],"spread":risk["spread"]},"tags":tags or ["常规"]}
def format_report(r:Dict)->str:
emoji={"黑":"⚫","红":"🔴","橙":"🟠","黄":"🟡","蓝":"🔵"}
e,v,a,m=r["dimensions"]["emotion"],r["dimensions"]["viral"],r["dimensions"]["ai"],r["matrix"]
return "\n".join(["="*60,"📊 声誉体温报告 v4.1 (精简版)","="*60,f"风险等级:{emoji.get(r['risk_level'],'⚪')} {r['risk_level']}级 | 评分:{r['risk_score']}/10",f"处理建议:{r['suggestion']}",f"行业:{r['industry']} | ML: {r['ml_prediction']['level']}级 ({int(r['ml_prediction']['confidence']*100)}%)",f"标签:{' | '.join(r['tags'])}","","维度分析:",f" • 情绪:{e['score']}/10 ({','.join(e['emotions']) or '无'})",f" • 传播:{v['score']}/10 (关键词:{v['keywords']},敏感:{v['sensitive']})",f" • AI 嫌疑:{a['score']}/10 (模式:{a['patterns']})","","二维矩阵:",f" 危害力:{m['harm']}/10 | 传播力:{m['spread']}/10","="*60])
def main():
import argparse
parser=argparse.ArgumentParser(description='声誉体温计 v4.1')
parser.add_argument('text',nargs='?',help='分析文本')
parser.add_argument('--json','-j',action='store_true',help='仅 JSON')
args=parser.parse_args()
text=args.text if args.text else (sys.stdin.read().strip() if not sys.stdin.isatty() else "")
if not text: print(json.dumps({"error":"请提供文本"},ensure_ascii=False,indent=2)); sys.exit(1)
r=analyze(text)
print(json.dumps(r,ensure_ascii=False,indent=2) if args.json else format_report(r))
if __name__=="__main__": main()
FILE:references/examples.md
# 案例库
## 黑色危机 (9-10 分)
| 案例 | 评分 | 关键触发 |
|-----|------|---------|
| 幼儿园食物中毒,50 名儿童送医 | 9.5 | 儿童 + 中毒 + 群体 |
| 工厂爆炸,3 人死亡多人受伤 | 9.3 | 死亡 + 事故 + 多人 |
| 奶粉检出三聚氰胺,婴儿患病 | 9.8 | 婴儿 + 三聚氰胺 |
| 儿童退烧药被曝用工业原料 | 9.2 | 儿童 + 药品 + 内部爆料 |
## 红色严重 (7-8.9 分)
| 案例 | 评分 | 关键触发 |
|-----|------|---------|
| 歌手吸毒被抓,粉丝脱粉 | 7.5 | 明星 + 吸毒 |
| 导演潜规则女演员,录音曝光 | 7.8 | 潜规则 + 录音 |
| 理财平台暴雷,投资人血本无归 | 8.0 | 暴雷 + 投资人 |
| 保险公司拒赔,癌症患者无助 | 7.2 | 拒赔 + 癌症 |
## 橙色高风险 (5-6.9 分)
| 案例 | 评分 | 关键触发 |
|-----|------|---------|
| 餐厅吃出老鼠,顾客呕吐 | 6.2 | 老鼠 + 呕吐 |
| 医院误诊导致病情恶化 | 6.5 | 误诊 + 病情恶化 |
| 4S 店卖事故车,车主维权 | 6.0 | 事故车 + 维权 |
| 培训机构跑路,家长拉横幅 | 6.3 | 跑路 + 维权 |
## 黄色中风险 (3-4.9 分)
| 案例 | 评分 | 关键触发 |
|-----|------|---------|
| 公司 996 加班,员工抱怨 | 3.5 | 996 + 抱怨 |
| 年终奖缩水,员工不满 | 3.8 | 年终奖 + 不满 |
| 手机用半年就卡顿 | 3.2 | 卡顿 + 失望 |
| APP 频繁闪退,体验差 | 3.0 | 闪退 + 差 |
## 蓝色低风险 (1-2.9 分)
| 案例 | 评分 | 说明 |
|-----|------|------|
| 这家餐厅很好吃,推荐 | 1.0 | 正面评价 |
| 快递很快,包装完好 | 1.2 | 正面评价 |
| 客服态度好,问题解决 | 1.0 | 正面评价 |
| 明天公司团建,记得穿运动鞋 | 1.0 | 中性通知 |
## 判定规则速查
**黑级触发** (满足任一):
- 死亡 + 儿童/婴儿
- 中毒 + 群体/多人
- 三聚氰胺/地沟油
**红级触发**:
- 明星 + 吸毒/出轨/偷税
- 理财 + 暴雷/失联/百亿
**橙级触发**:
- 食品安全问题 (老鼠/虫子)
- 医疗纠纷 (误诊/拒赔)
- 群体维权 (拉横幅/围堵)
ZeeLin Deep Research 深度研究是一款 AI 驱动的专业研究辅助平台,支持一句话生成与多步骤生成,提供深度、专家两大研究路径。从快速信息梳理、系统分析到超万字专家报告全流程覆盖,依托多轮推理与多源数据整合,高效完成企业分析、市场洞察、招商研究等复杂任务,一站式提升研究效率与决策质量。
---
name: ZeeLin Deep Research 深度研究
description: "ZeeLin Deep Research 深度研究是一款 AI 驱动的专业研究辅助平台,支持一句话生成与多步骤生成,提供深度、专家两大研究路径。从快速信息梳理、系统分析到超万字专家报告全流程覆盖,依托多轮推理与多源数据整合,高效完成企业分析、市场洞察、招商研究等复杂任务,一站式提升研究效率与决策质量。"
metadata: { "openclaw": { "emoji": "🔍", "requires": { "bins": ["python3"], "pip": ["requests"] } } }
---
# ZeeLin Deep Research 深度研究
> ZeeLin Deep Research 深度研究是一款 AI 驱动的专业研究辅助平台,支持一句话生成与多步骤生成,提供深度、专家两大研究路径。从快速信息梳理、系统分析到超万字专家报告全流程覆盖,依托多轮推理与多源数据整合,高效完成企业分析、市场洞察、招商研究等复杂任务,一站式提升研究效率与决策质量。
## 功能特点
- ✅ **自动推送**:任务完成后自动发送 PDF下载链接 给用户
- ✅ **后台执行**:通过子代理执行,不阻塞主会话
- ✅ **自动配置**:首次使用时自动获取用户渠道和 ID
## 没有 API Key?
前往 https://skills.zeelin.cn/console/apps 免费注册获取
获取后,编辑 skill 目录下的 `config.json` 文件:
```json
{
"api_key": "你的API_KEY"
}
```
**配置文件位置**:`config.json`
## thinking 参数
| 模式 | 用途 |
|-----|-----|
| `deep` | 概念解释、信息聚合、快速调研 |
| `major` | 行业分析、企业研究、万字报告 |
### 模式选择指南
**使用深度模式 (deep) 的场景**:
- 概念解释/知识梳理 — "什么是 XXX"、"XXX 的原理是什么"
- 事件/趋势分析 — 某个热点事件的来龙去脉、发展趋势
- 信息聚合 — 围绕某个话题汇总多方信息和观点
- 快速调研 — 用户没有明确要求深度报告的一般性研究问题
**使用专家模式 (major) 的场景**:
- 行业/市场分析 — 涉及特定行业的全景分析、市场格局、竞争态势
- 企业/公司研究 — 某个企业的财务分析、战略评估、业务拆解
- 政策/法规研究 — 需要系统梳理政策影响、合规要求
- 技术/产品深度对比 — 多维度的技术路线对比、产品竞品分析
- 投资/商业决策 — 需要数据支撑的投资分析、可行性评估
**如果不确定使用哪种模式**:可以询问用户确认
## 使用方式
### spawn 子代理执行
```
spawn 执行 python3 scripts/zeelin_start.py "调研内容" deep
```
**示例**:
```
spawn 执行 python3 scripts/zeelin_start.py "调研合肥地理位置分析" deep
```
## 工作流程
```
用户发送调研请求
↓
spawn 子代理执行 zeelin_start.py
↓
创建 ZeeLin 任务,获取 session_id
↓
后台监控任务状态(每30秒检查)
↓
状态变为完成(status=2)
↓
自动推送PDF下载链接到用户
```
## 文件位置
- 配置文件:`config.json`
- 启动脚本:`scripts/zeelin_start.py`
- 监控脚本:`scripts/zeelin_watch.py`
## 状态码
| 状态码 | 含义 |
|-------|------|
| 1 | 进行中 |
| 2 | ✅ 完成 |
| 3 | 用户终止 |
| 4 | ❌ 失败 |
| 5 | 排队中 |
## 常见错误
| 错误 | 解决方法 |
|-------|---------|
| code=315 当前接口调用已超限 | ⚠️ 请等待当前任务执行完成后再提交新任务 |
| code=315 试用已超限 | 前往 https://skills.zeelin.cn/console/recharge 充值 |
FILE:config.json
{
"api_key": ""
}
FILE:_meta.json
{
"ownerId": "kn70rvb50msptzn6jegcqqfgzd829k3q",
"slug": "zeelin-deep-research-pro",
"version": "1.0.0",
"publishedAt": 1773994256821
}
FILE:scripts/zeelin_start.py
#!/usr/bin/env python3
"""ZeeLin 调研任务封装 - 创建任务并启动监控子代理"""
import os, sys, json, requests, subprocess
from pathlib import Path
# 配置文件路径(脚本在 scripts/ 下,config.json 在 skill/ 下)
SCRIPT_DIR = Path(__file__).resolve().parent
CONFIG_FILE = SCRIPT_DIR.parent / "config.json"
WATCH_SCRIPT = SCRIPT_DIR / "zeelin_watch.py"
def load_config():
"""从配置文件读取配置"""
if CONFIG_FILE.exists():
try:
with open(CONFIG_FILE, "r") as f:
return json.load(f)
except:
pass
return {}
def save_config(config):
"""保存配置到文件"""
with open(CONFIG_FILE, "w") as f:
json.dump(config, f, ensure_ascii=False, indent=2)
def ensure_target_config():
"""确保配置中有 target_user 和 channel,如果没有则尝试从环境变量获取并保存"""
config = load_config()
# 检查是否需要更新
needs_save = False
# 尝试从环境变量获取
target_user = os.environ.get("ZEELIN_TARGET_USER", "")
channel = os.environ.get("ZEELIN_CHANNEL", "")
if target_user and not config.get("target_user"):
config["target_user"] = target_user
needs_save = True
print(f"自动配置 target_user: {target_user}")
if channel and not config.get("channel"):
config["channel"] = channel
needs_save = True
print(f"自动配置 channel: {channel}")
if needs_save:
save_config(config)
print(f"配置已保存到 {CONFIG_FILE}")
return config
def load_api_key():
"""从配置文件读取 API Key"""
config = load_config()
key = config.get("api_key", "").strip()
if key:
return key
print(f"ERROR: API Key not found in {CONFIG_FILE}")
print("获取 API Key: https://skills.zeelin.cn/console/apps")
sys.exit(1)
API_KEY = load_api_key()
CONTENT = sys.argv[1] if len(sys.argv) > 1 else "测试调研"
THINKING = sys.argv[2] if len(sys.argv) > 2 else "deep" # 默认 deep
# 确保配置中有 target_user 和 channel(首次使用时自动配置)
ensure_target_config()
# 创建任务
resp = requests.post(
"https://desearch.zeelin.cn/api/conversation/anew",
json={
"content": CONTENT,
"thinking": THINKING,
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
},
headers={"x-skill-key": API_KEY}
)
data = resp.json()
if data.get("code") != 200:
print(f"ERROR: {data}")
sys.exit(1)
session_id = data.get("data", {}).get("sessionId")
title = data.get("data", {}).get("title", CONTENT)
if not session_id:
print(f"ERROR: Failed to create task: {data}")
sys.exit(1)
print(f"CREATED: session_id={session_id}")
print(f"TITLE: {title}")
# 启动子代理监控
# 方式1: 后台运行(环境变量问题,可能失效)
# 方式2: 直接运行(会阻塞,但能在子代理中正确发送消息)
# 检查是否是交互式调用
log_file = f"/tmp/zeelin_watch_{session_id}.log"
if sys.stdout.isatty():
# 交互式,后台运行
env = os.environ.copy()
env["ZEELIN_SESSION_ID"] = session_id
env["ZEELIN_CONTENT"] = title
import subprocess
with open(log_file, "w") as f:
subprocess.Popen(
["nohup", "python3", "-u", str(WATCH_SCRIPT)],
env=env,
stdout=f,
stderr=subprocess.STDOUT
)
print(f"SPAWNED: watching in background")
print(f"LOG: {log_file}")
else:
# 非交互式(如子代理调用),直接运行并等待完成
env = os.environ.copy()
env["ZEELIN_SESSION_ID"] = session_id
env["ZEELIN_CONTENT"] = title
import subprocess
subprocess.run(
["python3", "-u", str(WATCH_SCRIPT)],
env=env
)
print(f"COMPLETED: task finished")
FILE:scripts/zeelin_watch.py
# -*- coding: utf-8 -*-
#!/usr/bin/env python3 -u
"""ZeeLin 任务监控脚本 - 子代理用"""
import os, sys, time, json, requests
from pathlib import Path
# 配置文件路径(脚本在 scripts/ 下,config.json 在 skill/ 下)
CONFIG_FILE = Path(__file__).resolve().parent.parent / "config.json"
def load_config():
"""从配置文件读取配置"""
if CONFIG_FILE.exists():
try:
with open(CONFIG_FILE, "r") as f:
return json.load(f)
except:
pass
return {}
config = load_config()
def load_api_key():
"""从配置文件读取 API Key"""
key = config.get("api_key", "").strip()
if key:
return key
print(f"ERROR: API Key not found in {CONFIG_FILE}")
sys.exit(1)
API_KEY = load_api_key()
TARGET_USER = config.get("target_user", "")
CHANNEL = config.get("channel", "dingtalk")
BASE_URL = "https://desearch.zeelin.cn"
API_URL = f"{BASE_URL}/api/conversation/status"
SESSION_ID = os.environ.get("ZEELIN_SESSION_ID", "")
TITLE = os.environ.get("ZEELIN_CONTENT", "调研任务")
def check_status(session_id):
resp = requests.get(
f"{API_URL}?sessionId={session_id}",
headers={"x-skill-key": API_KEY}
)
data = resp.json()
return data.get("data", {}).get("status"), data.get("data", {})
def get_pdf(session_id):
"""获取 PDF 下载链接"""
resp = requests.get(
f"{BASE_URL}/api/conversation/to_report?sessionId={session_id}&reportType=pdf",
headers={"x-skill-key": API_KEY}
)
data = resp.json()
return data.get("data", "")
def notify_done(title):
"""任务完成后通知用户(发送 PDF 下载地址)"""
# 获取 PDF 下载地址(接口返回的原始 URL)
pdf_url = get_pdf(SESSION_ID)
import subprocess
# 直接发送 PDF 下载地址的原始链接
cmd = [
"openclaw", "message", "send",
"--channel", CHANNEL,
"--target", TARGET_USER,
"--message", f"✅ 调研完成:{title}\n\n📥 PDF下载链接:{pdf_url}"
]
result = subprocess.run(cmd, capture_output=True, text=True)
print(f"NOTIFY_OUTPUT: {result.stdout}")
if result.returncode != 0:
print(f"NOTIFY_ERROR: {result.stderr}")
def main():
if not SESSION_ID:
print("ERROR: ZEELIN_SESSION_ID not set")
sys.exit(1)
if not API_KEY:
print("ERROR: API_KEY not configured")
sys.exit(1)
print(f"Watching task: {SESSION_ID}")
print(f"Title: {TITLE}")
while True:
time.sleep(30)
status, data = check_status(SESSION_ID)
print(f"Status: {status}")
if status == 2: # 完成
title = data.get("title", TITLE)
print(f"DONE: {title}")
# 直接发送链接
notify_done(title)
print("NOTIFIED_USER")
break
elif status in [3, 4]: # 终止/失败
print(f"FAILED: status={status}")
break
if __name__ == "__main__":
main()
ZeeLin Deep Research 深度研究是一款 AI 驱动的专业研究辅助平台,支持一句话生成与多步骤生成,提供深度、专家两大研究路径。从快速信息梳理、系统分析到超万字专家报告全流程覆盖,依托多轮推理与多源数据整合,高效完成企业分析、市场洞察、招商研究等复杂任务,一站式提升研究效率与决策质量。
---
name: ZeeLin Deep Research 深度研究
description: "ZeeLin Deep Research 深度研究是一款 AI 驱动的专业研究辅助平台,支持一句话生成与多步骤生成,提供深度、专家两大研究路径。从快速信息梳理、系统分析到超万字专家报告全流程覆盖,依托多轮推理与多源数据整合,高效完成企业分析、市场洞察、招商研究等复杂任务,一站式提升研究效率与决策质量。"
metadata: { "openclaw": { "emoji": "🔍", "requires": { "bins": ["curl"] } } }
---
# ZeeLin Deep Research 深度研究
> ZeeLin Deep Research 深度研究是一款 AI 驱动的专业研究辅助平台,支持一句话生成与多步骤生成,提供深度、专家两大研究路径。从快速信息梳理、系统分析到超万字专家报告全流程覆盖,依托多轮推理与多源数据整合,高效完成企业分析、市场洞察、招商研究等复杂任务,一站式提升研究效率与决策质量。
## 没有 API Key 怎么办?
如果用户没有提供 api_key,提示用户前往 https://desearch.zeelin.cn/skill-activity 进行免费注册或登录,获取点数及 api_key
## API 基础信息
- **Base URL**: `https://desearch.zeelin.cn`
- **认证方式**: Header `x-api-key`
- **接口**: `POST /api/conversation/anew`
## thinking 参数
- `deep` - 深度思考模式 - 需要全面分析但不需要万字报告
- `major` - 专家模式 - 需要深度系统性输出、万字报告
### 模式选择指南
**使用深度模式 (deep) 的场景**:
- 概念解释/知识梳理 — "什么是 XXX"、"XXX 的原理是什么"
- 事件/趋势分析 — 某个热点事件的来龙去脉、发展趋势
- 信息聚合 — 围绕某个话题汇总多方信息和观点
- 快速调研 — 用户没有明确要求深度报告的一般性研究问题
**使用专家模式 (major) 的场景**:
- 行业/市场分析 — 涉及特定行业的全景分析、市场格局、竞争态势
- 企业/公司研究 — 某个企业的财务分析、战略评估、业务拆解
- 政策/法规研究 — 需要系统梳理政策影响、合规要求
- 技术/产品深度对比 — 多维度的技术路线对比、产品竞品分析
- 投资/商业决策 — 需要数据支撑的投资分析、可行性评估
**如果不确定使用哪种模式**:可以询问用户确认
## 使用示例
### 深度思考模式
```bash
API_KEY="DESEARCH_API_KEY"
curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}'
```
### 专家模式
```bash
API_KEY="DESEARCH_API_KEY"
curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "major",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}'
```
## 多轮对话
第一轮返回的 `sessionId` 可以用于后续对话:
```bash
API_KEY="DESEARCH_API_KEY"
curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "上一轮的sessionId",
"content": "追问内容",
"thinking": "deep",
"workflow": "",
"moreSettings": {}
}'
```
## 快速调用
用户 API key 从环境变量 `DESEARCH_API_KEY` 读取。
**设置方式:**
```bash
export DESEARCH_API_KEY="你的API Key"
```
### 深度模式调用示例
```bash
API_KEY="DESEARCH_API_KEY"
curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "调研一下汽车产业规模",
"thinking": "deep",
"workflow": "",
"moreSettings": {}
}'
```
## 注意事项
- `sessionId` 为空时创建新对话
- `thinking` 参数决定推理深度
- API 返回 JSON,包含回答内容
---
## 查询任务状态
任务提交后,需要轮询查询状态:
```bash
API_KEY="DESEARCH_API_KEY"
curl -s -X GET "https://desearch.zeelin.cn/api/conversation/status?sessionId={sessionId}" \
-H "x-api-key: API_KEY"
```
**返回示例:**
```json
{
"code": 200,
"v": "v1.5.0",
"msg": "成功",
"data": {
"status": 2,
"thinking": "deep",
"workflow": "",
"message": "会话已生成",
"content": "调研一下汽车产业规模",
"time": "",
"thinkingWorkflowName": "深度模式",
"pptUrl": "",
"wavUrl": "",
"mdxUrl": "",
"mdUrl": "",
"htmlUrl": "",
"wavScriptUrl": "",
"isShare": 0,
"isMine": 0,
"title": "调研一下汽车产业规模",
"short": "jVICQSS5",
"questionId": 281697,
"sessionId": "b9162dfdefa74461a764aebe51366d87",
"useKnowledge": 0,
"onlyKnowledge": 0,
"searchRange": "web"
}
}
```
**状态码说明:**
- `1` = 进行中
- `2` = 正常结束 ✅
- `3` = 用户主动结束
- `4` = 失败
- `5` = 排队中
---
## 完整任务流程
1. **创建任务** → POST `/api/conversation/anew` 获取 `sessionId`
2. **轮询状态** → 每隔一段时间调用 `/api/conversation/status?sessionId={id}` 检查状态
3. **状态 = 2** → 任务完成
4. **获取 PDF 报告** → 调用 `/api/conversation/to_report?sessionId={id}&reportType=pdf` 获取 PDF 下载链接
5. **下载 PDF** → 从 data 字段获取 URL,下载 PDF 文件到本地
6. **发送消息** → 使用 `message` 工具发送 PDF 文件到用户
## 错误处理
### 接口调用超限错误 (code=315)
当 API 返回 code=315 且 msg 包含"当前接口调用已超限"时,表示当前并发任务数已达到上限(max_limit_conversation),需要等待当前任务执行完成后再提交新任务:
```bash
# 检查返回码
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
CODE=$(echo $RESULT | jq -r '.code')
MSG=$(echo $RESULT | jq -r '.msg')
if [ "$CODE" = "315" ] && echo "$MSG" | grep -q "当前接口调用已超限"; then
# 发送提示给用户,等待当前任务完成
message action=send target=用户ID message="⚠️ 当前接口调用已超限,请等待当前任务执行完成后再提交新任务。"
exit 1
fi
```
**返回示例:**
```json
{
"code": 315,
"v": "0.0.914",
"msg": "当前接口调用已超限,请联系我们",
"data": {
"max_limit_conversation": 1,
"now_conversation": 1
}
}
```
### 试用超限错误 (code=315)
当 API 返回 code=315 且 msg 包含"试用已超限"时,需要引导用户充值:
```bash
# 检查返回码
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
CODE=$(echo $RESULT | jq -r '.code')
MSG=$(echo $RESULT | jq -r '.msg')
if [ "$CODE" = "315" ] && echo "$MSG" | grep -q "试用已超限"; then
# 发送充值提示给用户
message action=send target=用户ID message="⚠️ 您的点数已超限,无法继续使用。请前往充值页面购买点数:https://desearch.zeelin.cn/skill-activity"
exit 1
fi
```
**充值地址**: https://desearch.zeelin.cn/skill-activity
### 完整流程示例
```bash
# 1. 创建任务
API_KEY="DESEARCH_API_KEY"
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
SESSION_ID=$(echo $RESULT | jq -r '.data.sessionId')
QUESTION_ID=$(echo $RESULT | jq -r '.data.id')
echo "Session ID: $SESSION_ID, Question ID: $QUESTION_ID"
# 2. 轮询状态直到完成
while true; do
STATUS=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/status?sessionId=SESSION_ID" \
-H "x-api-key: API_KEY" | jq -r '.data.status')
if [ "$STATUS" = "2" ]; then
echo "任务完成"
break
fi
echo "状态: $STATUS, 等待中..."
sleep 60 # 每分钟检查一次
done
# 3. 获取 PDF 报告链接
REPORT_RESULT=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/to_report?sessionId=SESSION_ID&reportType=pdf" \
-H "x-api-key: API_KEY")
PDF_URL=$(echo $REPORT_RESULT | jq -r '.data')
echo "PDF URL: $PDF_URL"
# 4. 下载 PDF 文件
curl -s -o /tmp/research_result.pdf "$PDF_URL"
# 5. 发送 PDF 文件给用户
message action=send target=用户ID filePath=/tmp/research_result.pdf
```
### 实际调用命令(执行时替换对应变量)
```bash
# 1. 创建任务
API_KEY="DESEARCH_API_KEY"
curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}'
```
### 轮询状态脚本
```bash
# 轮询直到任务完成 (status = 2)
API_KEY="DESEARCH_API_KEY"
SESSION_ID="替换为实际的sessionId"
while true; do
STATUS_RESPONSE=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/status?sessionId=SESSION_ID" \
-H "x-api-key: API_KEY")
STATUS=$(echo $STATUS_RESPONSE | jq -r '.data.status')
echo "当前状态: $STATUS"
if [ "$STATUS" = "2" ]; then
echo "任务完成!"
break
fi
sleep 60 # 每分钟检查一次
done
# 获取 PDF 报告链接
REPORT_RESULT=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/to_report?sessionId=SESSION_ID&reportType=pdf" \
-H "x-api-key: API_KEY")
PDF_URL=$(echo $REPORT_RESULT | jq -r '.data')
# 下载 PDF 文件
curl -s -o /tmp/research_result.pdf "$PDF_URL"
# 发送 PDF 文件给用户
message action=send target=用户ID filePath=/tmp/research_result.pdf
```
---
## ⚠️ 重要:必须保存文件再发送
**❌ 禁止直接发送文字内容给用户**
**✅ 必须:获取 PDF 链接 → 下载 PDF 文件 → 发送 PDF 文件给用户**
### 正确流程示例(飞书文档)
```bash
# 1. 创建任务
API_KEY="DESEARCH_API_KEY"
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "用户的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
SESSION_ID=$(echo $RESULT | jq -r '.data.sessionId')
# 2. 轮询状态直到完成 (status=2)
while true; do
STATUS=$(curl -s "https://desearch.zeelin.cn/api/conversation/status?sessionId=SESSION_ID" \
-H "x-api-key: API_KEY" | jq -r '.data.status')
[ "$STATUS" = "2" ] && break
sleep 30
done
# 3. 获取 PDF 报告链接
REPORT_RESULT=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/to_report?sessionId=SESSION_ID&reportType=pdf" \
-H "x-api-key: API_KEY")
PDF_URL=$(echo $REPORT_RESULT | jq -r '.data')
# 4. 下载 PDF 文件
curl -s -o /tmp/research_result.pdf "$PDF_URL"
# 5. 发送 PDF 文件给用户
message action=send target=用户ID filePath=/tmp/research_result.pdf
```
### 关键点
- 任务完成后调用 `/api/conversation/to_report?sessionId={id}&reportType=pdf` 获取 PDF 下载链接
- 从返回的 `data` 字段提取 PDF URL
- 使用 curl 下载 PDF 文件到本地
- 直接发送 PDF 文件给用户
### 后台执行与自动发送
**确保任务完成后自动发送 PDF 的关键:**
1. **使用足够长的 timeout**:设置 `timeout=1200` 或更长,确保 exec 命令等待任务完成
2. **轮询循环内检查状态**:
```bash
while true; do
STATUS=$(curl -s "https://desearch.zeelin.cn/api/conversation/status?sessionId=SESSION_ID" \
-H "x-api-key: API_KEY" | jq -r '.data.status')
[ "$STATUS" = "2" ] && break # 任务完成后跳出循环
[ "$STATUS" = "4" ] && exit 1 # 任务失败则退出
sleep 30
done
```
3. **任务完成后立即发送**:在轮询循环结束后,立即调用 message 工具发送 PDF
```bash
# 下载 PDF 后立即发送
curl -s -o /tmp/research_result.pdf "$PDF_URL"
message action=send target=用户ID filePath=/tmp/research_result.pdf
```
**❌ 错误做法**:轮询后不等待结果就退出,或超时时间太短导致任务未完成就退出
**✅ 正确做法**:使用 while 循环 + 足够长的 timeout,任务完成后立即发送 PDF
### 后台执行(用户可同时做其他事情)
当用户希望任务在后台运行、同时可以让你执行其他任务时,使用 OpenClaw 的后台执行功能:
**方式一:使用 `background=true` 参数**
```bash
exec command="..." background=true timeout=1200
```
这样命令会在后台运行,不会阻塞当前会话,你可以继续给其他命令。
**方式二:使用 `exec` + `yieldMs` 参数**
```bash
exec command="..." yieldMs=10000
```
设置 yieldMs 让出控制权,命令在后台继续运行。
**方式三:使用 `process` 工具管理后台任务**
1. 先启动后台任务:
```bash
exec command="完整的轮询+发送脚本" timeout=1200
```
2. 使用 `process(action=poll)` 轮询结果:
```bash
process action=poll sessionId=<session_id> timeout=600000
```
**后台任务完整示例:**
```bash
# 1. 创建任务(立即返回)
API_KEY="DESEARCH_API_KEY"
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "用户的研究问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
SESSION_ID=$(echo "$RESULT" | jq -r '.data.sessionId')
echo "任务已创建: $SESSION_ID"
# 2. 后台轮询 + 下载 + 发送(设置长timeout)
exec command="
SESSION_ID='$SESSION_ID'
API_KEY='$API_KEY'
# 轮询直到完成
while true; do
STATUS=\$(curl -s 'https://desearch.zeelin.cn/api/conversation/status?sessionId=\SESSION_ID' \\
-H 'x-api-key: \API_KEY' | jq -r '.data.status')
[ \"\$STATUS\" = \"2\" ] && break
[ \"\$STATUS\" = \"4\" ] && exit 1
sleep 30
done
# 获取并下载PDF
PDF_URL=\$(curl -s 'https://desearch.zeelin.cn/api/conversation/to_report?sessionId=\SESSION_ID&reportType=pdf' \\
-H 'x-api-key: \API_KEY' | jq -r '.data')
curl -s -o /tmp/report.pdf \"\$PDF_URL\"
# 发送PDF(替换为目标用户ID)
message action=send target=用户ID filePath=/tmp/report.pdf
" timeout=1200
```
**用户可以:**
- 随时查询任务状态
- 在后台任务运行期间执行其他命令
- 任务完成后自动收到 PDF
---
## ⚠️ 跨渠道发送文件注意事项
### 不同渠道的文件限制
| 渠道 | 文件大小限制 |
|-----|------------|
| 钉钉 | 20MB |
| 飞书 | 20MB |
| Telegram | 50MB |
| Discord | 8MB |
| WhatsApp | 16MB |
---
## ⚠️ 飞书渠道:必须创建飞书文档发送
**当用户渠道为飞书时,禁止直接发送 PDF 文件给用户,必须按以下流程操作:**
### 飞书渠道完整流程
```bash
# 1. 创建任务
API_KEY="DESEARCH_API_KEY"
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "用户的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
SESSION_ID=$(echo $RESULT | jq -r '.data.sessionId')
TITLE=$(echo $RESULT | jq -r '.data.title')
# 2. 轮询状态直到完成 (status=2)
while true; do
STATUS=$(curl -s "https://desearch.zeelin.cn/api/conversation/status?sessionId=SESSION_ID" \
-H "x-api-key: API_KEY" | jq -r '.data.status')
[ "$STATUS" = "2" ] && break
sleep 30
done
# 3. 获取 Word 报告链接(Word 格式更容易提取文字内容)
REPORT_RESULT=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/to_report?sessionId=SESSION_ID&reportType=word" \
-H "x-api-key: API_KEY")
WORD_URL=$(echo $REPORT_RESULT | jq -r '.data')
# 4. 下载 Word 文件
curl -s -o /tmp/research.docx "$WORD_URL"
# 5. 解压 Word 文件提取文字内容
unzip -q /tmp/research.docx -d /tmp/research_docx/
sed 's/<[^>]*>//g' /tmp/research_docx/word/document.xml | tr -s ' \n' > /tmp/research.txt
# 6. 创建飞书文档
DOC_RESULT=$(feishu_doc action=create title="调研报告:TITLE")
DOC_TOKEN=$(echo $DOC_RESULT | jq -r '.document_id')
DOC_URL=$(echo $DOC_RESULT | jq -r '.url')
# 7. 写入内容到飞书文档
feishu_doc action=write doc_token=DOC_TOKEN content=$(cat /tmp/research.txt)
# 8. 发送文档链接给用户
message action=send target=用户ID message="📄 调研报告已生成:DOC_URL"
```
### 飞书渠道检查清单
- [ ] 渠道是飞书吗?
- [ ] 是否已创建飞书文档?
- [ ] 是否已将报告内容写入飞书文档?
- [ ] 是否发送的是飞书文档链接而非 PDF?
### 飞书渠道 ❌ 禁止事项
- ❌ 直接发送 PDF 文件(用户打不开)
- ❌ 直接发送本地文件路径
- ❌ 发送服务器目录
### 飞书渠道 ✅ 正确做法
- ✅ 创建飞书文档 (feishu_doc action=create)
- ✅ 写入内容 (feishu_doc action=write)
- ✅ 发送文档链接 (message action=send 附带 URL)
### 确保发送成功的检查
```bash
# 检查文件是否存在且非空
if [ -f /tmp/research.md ] && [ -s /tmp/research.md ]; then
# 发送文件
message action=send target=用户ID filePath=/tmp/research.md
else
echo "文件无效或为空"
fi
```
---
FILE:_meta.json
{
"ownerId": "kn70rvb50msptzn6jegcqqfgzd829k3q",
"slug": "zeelin-deep-research",
"version": "1.0.1",
"publishedAt": 1772613151972
}ZeeLin Deep Research 深度研究是一款 AI 驱动的专业研究辅助平台,支持一句话生成与多步骤生成,提供深度、专家两大研究路径。从快速信息梳理、系统分析到超万字专家报告全流程覆盖,依托多轮推理与多源数据整合,高效完成企业分析、市场洞察、招商研究等复杂任务,一站式提升研究效率与决策质量。
---
name: ZeeLin Deep Research 深度研究
description: "ZeeLin Deep Research 深度研究是一款 AI 驱动的专业研究辅助平台,支持一句话生成与多步骤生成,提供深度、专家两大研究路径。从快速信息梳理、系统分析到超万字专家报告全流程覆盖,依托多轮推理与多源数据整合,高效完成企业分析、市场洞察、招商研究等复杂任务,一站式提升研究效率与决策质量。"
metadata: { "openclaw": { "emoji": "🔍", "requires": { "bins": ["curl"] } } }
---
# ZeeLin Deep Research 深度研究
> ZeeLin Deep Research 深度研究是一款 AI 驱动的专业研究辅助平台,支持一句话生成与多步骤生成,提供深度、专家两大研究路径。从快速信息梳理、系统分析到超万字专家报告全流程覆盖,依托多轮推理与多源数据整合,高效完成企业分析、市场洞察、招商研究等复杂任务,一站式提升研究效率与决策质量。
## 没有 API Key 怎么办?
如果用户没有提供 api_key,提示用户前往 https://desearch.zeelin.cn/skill-activity 进行免费注册或登录,获取点数及 api_key
## API 基础信息
- **Base URL**: `https://desearch.zeelin.cn`
- **认证方式**: Header `x-api-key`
- **接口**: `POST /api/conversation/anew`
## thinking 参数
- `deep` - 深度思考模式 - 需要全面分析但不需要万字报告
- `major` - 专家模式 - 需要深度系统性输出、万字报告
### 模式选择指南
**使用深度模式 (deep) 的场景**:
- 概念解释/知识梳理 — "什么是 XXX"、"XXX 的原理是什么"
- 事件/趋势分析 — 某个热点事件的来龙去脉、发展趋势
- 信息聚合 — 围绕某个话题汇总多方信息和观点
- 快速调研 — 用户没有明确要求深度报告的一般性研究问题
**使用专家模式 (major) 的场景**:
- 行业/市场分析 — 涉及特定行业的全景分析、市场格局、竞争态势
- 企业/公司研究 — 某个企业的财务分析、战略评估、业务拆解
- 政策/法规研究 — 需要系统梳理政策影响、合规要求
- 技术/产品深度对比 — 多维度的技术路线对比、产品竞品分析
- 投资/商业决策 — 需要数据支撑的投资分析、可行性评估
**如果不确定使用哪种模式**:可以询问用户确认
## 使用示例
### 深度思考模式
```bash
API_KEY="DESEARCH_API_KEY"
curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}'
```
### 专家模式
```bash
API_KEY="DESEARCH_API_KEY"
curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "major",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}'
```
## 多轮对话
第一轮返回的 `sessionId` 可以用于后续对话:
```bash
API_KEY="DESEARCH_API_KEY"
curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "上一轮的sessionId",
"content": "追问内容",
"thinking": "deep",
"workflow": "",
"moreSettings": {}
}'
```
## 快速调用
用户 API key 从环境变量 `DESEARCH_API_KEY` 读取。
**设置方式:**
```bash
export DESEARCH_API_KEY="你的API Key"
```
### 深度模式调用示例
```bash
API_KEY="DESEARCH_API_KEY"
curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "调研一下汽车产业规模",
"thinking": "deep",
"workflow": "",
"moreSettings": {}
}'
```
## 注意事项
- `sessionId` 为空时创建新对话
- `thinking` 参数决定推理深度
- API 返回 JSON,包含回答内容
---
## 查询任务状态
任务提交后,需要轮询查询状态:
```bash
API_KEY="DESEARCH_API_KEY"
curl -s -X GET "https://desearch.zeelin.cn/api/conversation/status?sessionId={sessionId}" \
-H "x-api-key: API_KEY"
```
**返回示例:**
```json
{
"code": 200,
"v": "v1.5.0",
"msg": "成功",
"data": {
"status": 2,
"thinking": "deep",
"workflow": "",
"message": "会话已生成",
"content": "调研一下汽车产业规模",
"time": "",
"thinkingWorkflowName": "深度模式",
"pptUrl": "",
"wavUrl": "",
"mdxUrl": "",
"mdUrl": "",
"htmlUrl": "",
"wavScriptUrl": "",
"isShare": 0,
"isMine": 0,
"title": "调研一下汽车产业规模",
"short": "jVICQSS5",
"questionId": 281697,
"sessionId": "b9162dfdefa74461a764aebe51366d87",
"useKnowledge": 0,
"onlyKnowledge": 0,
"searchRange": "web"
}
}
```
**状态码说明:**
- `1` = 进行中
- `2` = 正常结束 ✅
- `3` = 用户主动结束
- `4` = 失败
- `5` = 排队中
---
## 完整任务流程
1. **创建任务** → POST `/api/conversation/anew` 获取 `sessionId`
2. **轮询状态** → 每隔一段时间调用 `/api/conversation/status?sessionId={id}` 检查状态
3. **状态 = 2** → 任务完成
4. **获取 PDF 报告** → 调用 `/api/conversation/to_report?sessionId={id}&reportType=pdf` 获取 PDF 下载链接
5. **下载 PDF** → 从 data 字段获取 URL,下载 PDF 文件到本地
6. **发送消息** → 使用 `message` 工具发送 PDF 文件到用户
## 错误处理
### 接口调用超限错误 (code=315)
当 API 返回 code=315 且 msg 包含"当前接口调用已超限"时,表示当前并发任务数已达到上限(max_limit_conversation),需要等待当前任务执行完成后再提交新任务:
```bash
# 检查返回码
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
CODE=$(echo $RESULT | jq -r '.code')
MSG=$(echo $RESULT | jq -r '.msg')
if [ "$CODE" = "315" ] && echo "$MSG" | grep -q "当前接口调用已超限"; then
# 发送提示给用户,等待当前任务完成
message action=send target=用户ID message="⚠️ 当前接口调用已超限,请等待当前任务执行完成后再提交新任务。"
exit 1
fi
```
**返回示例:**
```json
{
"code": 315,
"v": "0.0.914",
"msg": "当前接口调用已超限,请联系我们",
"data": {
"max_limit_conversation": 1,
"now_conversation": 1
}
}
```
### 试用超限错误 (code=315)
当 API 返回 code=315 且 msg 包含"试用已超限"时,需要引导用户充值:
```bash
# 检查返回码
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
CODE=$(echo $RESULT | jq -r '.code')
MSG=$(echo $RESULT | jq -r '.msg')
if [ "$CODE" = "315" ] && echo "$MSG" | grep -q "试用已超限"; then
# 发送充值提示给用户
message action=send target=用户ID message="⚠️ 您的点数已超限,无法继续使用。请前往充值页面购买点数:https://desearch.zeelin.cn/skill-activity"
exit 1
fi
```
**充值地址**: https://desearch.zeelin.cn/skill-activity
### 完整流程示例
```bash
# 1. 创建任务
API_KEY="DESEARCH_API_KEY"
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
SESSION_ID=$(echo $RESULT | jq -r '.data.sessionId')
QUESTION_ID=$(echo $RESULT | jq -r '.data.id')
echo "Session ID: $SESSION_ID, Question ID: $QUESTION_ID"
# 2. 轮询状态直到完成
while true; do
STATUS=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/status?sessionId=SESSION_ID" \
-H "x-api-key: API_KEY" | jq -r '.data.status')
if [ "$STATUS" = "2" ]; then
echo "任务完成"
break
fi
echo "状态: $STATUS, 等待中..."
sleep 60 # 每分钟检查一次
done
# 3. 获取 PDF 报告链接
REPORT_RESULT=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/to_report?sessionId=SESSION_ID&reportType=pdf" \
-H "x-api-key: API_KEY")
PDF_URL=$(echo $REPORT_RESULT | jq -r '.data')
echo "PDF URL: $PDF_URL"
# 4. 下载 PDF 文件
curl -s -o /tmp/research_result.pdf "$PDF_URL"
# 5. 发送 PDF 文件给用户
message action=send target=用户ID filePath=/tmp/research_result.pdf
```
### 实际调用命令(执行时替换对应变量)
```bash
# 1. 创建任务
API_KEY="DESEARCH_API_KEY"
curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "你的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}'
```
### 轮询状态脚本
```bash
# 轮询直到任务完成 (status = 2)
API_KEY="DESEARCH_API_KEY"
SESSION_ID="替换为实际的sessionId"
while true; do
STATUS_RESPONSE=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/status?sessionId=SESSION_ID" \
-H "x-api-key: API_KEY")
STATUS=$(echo $STATUS_RESPONSE | jq -r '.data.status')
echo "当前状态: $STATUS"
if [ "$STATUS" = "2" ]; then
echo "任务完成!"
break
fi
sleep 60 # 每分钟检查一次
done
# 获取 PDF 报告链接
REPORT_RESULT=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/to_report?sessionId=SESSION_ID&reportType=pdf" \
-H "x-api-key: API_KEY")
PDF_URL=$(echo $REPORT_RESULT | jq -r '.data')
# 下载 PDF 文件
curl -s -o /tmp/research_result.pdf "$PDF_URL"
# 发送 PDF 文件给用户
message action=send target=用户ID filePath=/tmp/research_result.pdf
```
---
## ⚠️ 重要:必须保存文件再发送
**❌ 禁止直接发送文字内容给用户**
**✅ 必须:获取 PDF 链接 → 下载 PDF 文件 → 发送 PDF 文件给用户**
### 正确流程示例(飞书文档)
```bash
# 1. 创建任务
API_KEY="DESEARCH_API_KEY"
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "用户的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
SESSION_ID=$(echo $RESULT | jq -r '.data.sessionId')
# 2. 轮询状态直到完成 (status=2)
while true; do
STATUS=$(curl -s "https://desearch.zeelin.cn/api/conversation/status?sessionId=SESSION_ID" \
-H "x-api-key: API_KEY" | jq -r '.data.status')
[ "$STATUS" = "2" ] && break
sleep 30
done
# 3. 获取 PDF 报告链接
REPORT_RESULT=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/to_report?sessionId=SESSION_ID&reportType=pdf" \
-H "x-api-key: API_KEY")
PDF_URL=$(echo $REPORT_RESULT | jq -r '.data')
# 4. 下载 PDF 文件
curl -s -o /tmp/research_result.pdf "$PDF_URL"
# 5. 发送 PDF 文件给用户
message action=send target=用户ID filePath=/tmp/research_result.pdf
```
### 关键点
- 任务完成后调用 `/api/conversation/to_report?sessionId={id}&reportType=pdf` 获取 PDF 下载链接
- 从返回的 `data` 字段提取 PDF URL
- 使用 curl 下载 PDF 文件到本地
- 直接发送 PDF 文件给用户
### 后台执行与自动发送
**确保任务完成后自动发送 PDF 的关键:**
1. **使用足够长的 timeout**:设置 `timeout=1200` 或更长,确保 exec 命令等待任务完成
2. **轮询循环内检查状态**:
```bash
while true; do
STATUS=$(curl -s "https://desearch.zeelin.cn/api/conversation/status?sessionId=SESSION_ID" \
-H "x-api-key: API_KEY" | jq -r '.data.status')
[ "$STATUS" = "2" ] && break # 任务完成后跳出循环
[ "$STATUS" = "4" ] && exit 1 # 任务失败则退出
sleep 30
done
```
3. **任务完成后立即发送**:在轮询循环结束后,立即调用 message 工具发送 PDF
```bash
# 下载 PDF 后立即发送
curl -s -o /tmp/research_result.pdf "$PDF_URL"
message action=send target=用户ID filePath=/tmp/research_result.pdf
```
**❌ 错误做法**:轮询后不等待结果就退出,或超时时间太短导致任务未完成就退出
**✅ 正确做法**:使用 while 循环 + 足够长的 timeout,任务完成后立即发送 PDF
### 后台执行(用户可同时做其他事情)
当用户希望任务在后台运行、同时可以让你执行其他任务时,使用 OpenClaw 的后台执行功能:
**方式一:使用 `background=true` 参数**
```bash
exec command="..." background=true timeout=1200
```
这样命令会在后台运行,不会阻塞当前会话,你可以继续给其他命令。
**方式二:使用 `exec` + `yieldMs` 参数**
```bash
exec command="..." yieldMs=10000
```
设置 yieldMs 让出控制权,命令在后台继续运行。
**方式三:使用 `process` 工具管理后台任务**
1. 先启动后台任务:
```bash
exec command="完整的轮询+发送脚本" timeout=1200
```
2. 使用 `process(action=poll)` 轮询结果:
```bash
process action=poll sessionId=<session_id> timeout=600000
```
**后台任务完整示例:**
```bash
# 1. 创建任务(立即返回)
API_KEY="DESEARCH_API_KEY"
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "用户的研究问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
SESSION_ID=$(echo "$RESULT" | jq -r '.data.sessionId')
echo "任务已创建: $SESSION_ID"
# 2. 后台轮询 + 下载 + 发送(设置长timeout)
exec command="
SESSION_ID='$SESSION_ID'
API_KEY='$API_KEY'
# 轮询直到完成
while true; do
STATUS=\$(curl -s 'https://desearch.zeelin.cn/api/conversation/status?sessionId=\SESSION_ID' \\
-H 'x-api-key: \API_KEY' | jq -r '.data.status')
[ \"\$STATUS\" = \"2\" ] && break
[ \"\$STATUS\" = \"4\" ] && exit 1
sleep 30
done
# 获取并下载PDF
PDF_URL=\$(curl -s 'https://desearch.zeelin.cn/api/conversation/to_report?sessionId=\SESSION_ID&reportType=pdf' \\
-H 'x-api-key: \API_KEY' | jq -r '.data')
curl -s -o /tmp/report.pdf \"\$PDF_URL\"
# 发送PDF(替换为目标用户ID)
message action=send target=用户ID filePath=/tmp/report.pdf
" timeout=1200
```
**用户可以:**
- 随时查询任务状态
- 在后台任务运行期间执行其他命令
- 任务完成后自动收到 PDF
---
## ⚠️ 跨渠道发送文件注意事项
### 不同渠道的文件限制
| 渠道 | 文件大小限制 |
|-----|------------|
| 钉钉 | 20MB |
| 飞书 | 20MB |
| Telegram | 50MB |
| Discord | 8MB |
| WhatsApp | 16MB |
---
## ⚠️ 飞书渠道:必须创建飞书文档发送
**当用户渠道为飞书时,禁止直接发送 PDF 文件给用户,必须按以下流程操作:**
### 飞书渠道完整流程
```bash
# 1. 创建任务
API_KEY="DESEARCH_API_KEY"
RESULT=$(curl -s -X POST "https://desearch.zeelin.cn/api/conversation/anew" \
-H "Content-Type: application/json" \
-H "x-api-key: API_KEY" \
-d '{
"sessionId": "",
"content": "用户的问题",
"thinking": "deep",
"workflow": "",
"needEditChapter": 0,
"moreSettings": {}
}')
SESSION_ID=$(echo $RESULT | jq -r '.data.sessionId')
TITLE=$(echo $RESULT | jq -r '.data.title')
# 2. 轮询状态直到完成 (status=2)
while true; do
STATUS=$(curl -s "https://desearch.zeelin.cn/api/conversation/status?sessionId=SESSION_ID" \
-H "x-api-key: API_KEY" | jq -r '.data.status')
[ "$STATUS" = "2" ] && break
sleep 30
done
# 3. 获取 Word 报告链接(Word 格式更容易提取文字内容)
REPORT_RESULT=$(curl -s -X GET "https://desearch.zeelin.cn/api/conversation/to_report?sessionId=SESSION_ID&reportType=word" \
-H "x-api-key: API_KEY")
WORD_URL=$(echo $REPORT_RESULT | jq -r '.data')
# 4. 下载 Word 文件
curl -s -o /tmp/research.docx "$WORD_URL"
# 5. 解压 Word 文件提取文字内容
unzip -q /tmp/research.docx -d /tmp/research_docx/
sed 's/<[^>]*>//g' /tmp/research_docx/word/document.xml | tr -s ' \n' > /tmp/research.txt
# 6. 创建飞书文档
DOC_RESULT=$(feishu_doc action=create title="调研报告:TITLE")
DOC_TOKEN=$(echo $DOC_RESULT | jq -r '.document_id')
DOC_URL=$(echo $DOC_RESULT | jq -r '.url')
# 7. 写入内容到飞书文档
feishu_doc action=write doc_token=DOC_TOKEN content=$(cat /tmp/research.txt)
# 8. 发送文档链接给用户
message action=send target=用户ID message="📄 调研报告已生成:DOC_URL"
```
### 飞书渠道检查清单
- [ ] 渠道是飞书吗?
- [ ] 是否已创建飞书文档?
- [ ] 是否已将报告内容写入飞书文档?
- [ ] 是否发送的是飞书文档链接而非 PDF?
### 飞书渠道 ❌ 禁止事项
- ❌ 直接发送 PDF 文件(用户打不开)
- ❌ 直接发送本地文件路径
- ❌ 发送服务器目录
### 飞书渠道 ✅ 正确做法
- ✅ 创建飞书文档 (feishu_doc action=create)
- ✅ 写入内容 (feishu_doc action=write)
- ✅ 发送文档链接 (message action=send 附带 URL)
### 确保发送成功的检查
```bash
# 检查文件是否存在且非空
if [ -f /tmp/research.md ] && [ -s /tmp/research.md ]; then
# 发送文件
message action=send target=用户ID filePath=/tmp/research.md
else
echo "文件无效或为空"
fi
```
---
FILE:_meta.json
{
"ownerId": "kn70rvb50msptzn6jegcqqfgzd829k3q",
"slug": "desearch",
"version": "1.0.12",
"publishedAt": 1772709933924
}