news 2026/9/8 16:20:01

CLI-Anything × AnyGen:构建云异步内容生成任务的 Agent 原生 CLI 编排指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CLI-Anything × AnyGen:构建云异步内容生成任务的 Agent 原生 CLI 编排指南

CLI-Anything × AnyGen:构建云异步内容生成任务的 Agent 原生 CLI 编排指南

【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything

导读

本文围绕 CLI-Anything 仓库中 AnyGen 模块的架构分析文档,讲解如何将 AnyGen 云端异步内容生成服务(PPT、DOCX、SmartDraw 图表、网页、故事书、数据分析报告)封装为面向 AI Agent 的状态化命令行工具。读完本文,你将掌握 AnyGen REST API 的任务全生命周期调用方式、cli-anything-anygen的安装配置与命令用法、.anygen-task.json本地持久化机制,以及结合仓库源码理解其轮询、下载、文件校验和会话撤销等底层实现。

一、AnyGen 与 CLI-Anything 的整体架构定位

AnyGen 是一个云端异步内容生成平台,通过 REST API 提供专业幻灯片(PPT)、文档(DOCX)、网站、故事书、图表(SmartDraw)和数据分析报告等生成能力。与仓库中大多数面向本地 GUI 的目标软件不同,AnyGen 没有可调用的本地软件本体——所有渲染均在服务端完成,CLI 只是负责提交任务、轮询状态并下载生成文件的"编排层"。

在 ANYGEN.md 中给出了其服务端与 CLI 的整体协作架构:云端一侧由 Slide / Doc / SmartDraw / Website / Storybook / Data Analysis 六类内容引擎承载生成能力,中间由 Task Orchestration Layer(异步队列、状态跟踪、文件存储)统一调度,最外层通过基于 OpenAPI 3.1 的 REST API(/v1/openapi/tasks等端点)对客户端开放;CLI 一侧则是基于 Click 的命令行加 REPL 的cli-anything-anygen,支持 JSON 与人类可读两种输出。

┌──────────────────────────────────────────────────┐ │ AnyGen Cloud Service │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │ │ Slide │ │ Doc │ │ SmartDraw │ │ │ │ Engine │ │ Engine │ │ Engine │ │ │ └────┬─────┘ └────┬─────┘ └────────┬─────────┘ │ │ ┌────┘ ┌─────────┘ ┌─────────────┘ │ │ │ ┌────┴────┐ ┌─────┴─────┐ ┌───────────────┐ │ │ │ │ Website │ │ Storybook │ │ Data Analysis │ │ │ │ │ Engine │ │ Engine │ │ Engine │ │ │ │ └────┬────┘ └─────┬─────┘ └───────┬───────┘ │ │ │ │ │ │ │ │ ┌───────┴─────────────┴───────────────┴───────┐ │ │ │ Task Orchestration Layer │ │ │ │ Async queue · status tracking · file store │ │ │ └──────────────────┬──────────────────────────┘ │ │ │ │ │ ┌──────────────────┴──────────────────────────┐ │ │ │ REST API (OpenAPI 3.1) │ │ │ │ POST /v1/openapi/tasks │ │ │ │ GET /v1/openapi/tasks/:id │ │ │ │ POST /v1/openapi/files/upload │ │ │ │ POST /v1/openapi/tasks/prepare │ │ │ └──────────────────┬──────────────────────────┘ │ └─────────────────────┼────────────────────────────┘ │ HTTPS + Bearer sk-… ┌────────────┴─────────────┐ │ cli-anything-anygen │ │ Click CLI + REPL │ │ JSON / human output │ └──────────────────────────┘

二、CLI 策略:为什么需要一个结构化 HTTP 客户端

由于 AnyGen 是纯云端服务,cli-anything-anygen本质上是封装 AnyGen OpenAPI 的结构化 HTTP 客户端,由以下几个部分组成:

  1. requests:Python HTTP 库,承担所有 API 调用;
  2. 轮询循环(Polling loop):任务创建后,按可配置间隔(默认 3 秒,最长 20 分钟)轮询GET /v1/openapi/tasks/:id,直到状态变为completedfailed
  3. 文件下载:任务完成后下载生成文件(PPTX、DOCX、HTML、SVG、PDF 等)到本地路径;
  4. 文件上传:通过POST /v1/openapi/files/upload上传参考资料,换取file_token用于创建任务;
  5. Prepare(多轮对话)POST /v1/openapi/tasks/prepare支持在创建任务前进行多轮需求澄清。

为什么 Agent 需要 CLI 包装器?

文档在 ANYGEN.md 的 "Why a CLI Wrapper?" 一节给出了四条核心理由:

  • Agent 无法直接编排多步骤 HTTP 工作流(认证 → 上传 → prepare → 创建 → 轮询 → 下载);
  • CLI 提供单条task run命令即可编排完整生命周期;
  • 结构化的--json输出便于 Agent 解析任务 ID、状态与文件路径;
  • REPL 支持对任务类型与参数进行交互式探索。

从源码看,这一设计贯穿整个命令树:全局--json开关在 anygen_cli.py 中被解析后置为模块级状态,所有命令的结果统一经output()函数输出——JSON 模式下用json.dumps(data, indent=2, default=str)输出可解析的结构,人类模式下则递归打印嵌套字典/列表。

三、安装与 API Key 配置

cli-anything-anygen由 setup.py 定义,包名为cli-anything-anygen,安装后提供cli-anything-anygen控制台命令(同时支持python3 -m cli_anything.anygen方式运行)。依赖为click>=8.0.0requests>=2.28.0prompt-toolkit>=3.0.0,要求 Python 3.10+。

# 源码方式安装(在 anygen/agent-harness 目录内) pip install -e . # 安装运行时依赖 pip install requests click prompt_toolkit

API Key 的三种配置来源(按优先级)

认证信息解析实现在 anygen_backend.py 的get_api_key()中,按以下优先级依次解析:

  1. --api-keyCLI 选项(优先级最高);
  2. ANYGEN_API_KEY环境变量;
  3. 配置文件~/.config/anygen/config.json
# 方式一:CLI 选项(单次命令生效) cli-anything-anygen --api-key sk-xxx task status task_xxx # 方式二:环境变量 export ANYGEN_API_KEY="sk-xxx" # 方式三:写入配置文件(推荐,配置保存时会 chmod 0600 保护权限) cli-anything-anygen config set api_key "sk-xxx"

值得注意的源码细节:get_api_key()CLI 参数优先于环境变量、环境变量优先于配置文件;而最终发送请求时_make_auth_token()(见 anygen_backend.py)会自动为不以"Bearer "开头的 key 补上前缀,统一放入Authorization请求头。配置文件写盘时使用chmod(0o600)收紧权限;config set/get在回显 API Key 时会做掩码处理(仅显示前 10 位),避免密钥泄露到终端日志。若最终仍未找到 key,_require_api_key()会抛出带三种配置指引的RuntimeError

四、支持的 Operation 类型与命令映射

VALID_OPERATIONS定义在 anygen_backend.py,与文档一致共 7 类;其中仅slidedocsmart_draw三种在任务完成后返回可下载文件,其余以任务 URL 交付。

OperationAPI ValueOutput FormatDownloadable File
Slides / PPTslidePPTXYes
Documents / DOCXdocDOCXYes
SmartDrawsmart_drawdrawio / excalidrawYes
General / ChatchatNo (task URL)
StorybookstorybookNo (task URL)
Data Analysisdata_analysisNo (task URL)
WebsitewebsiteNo (task URL)

Agent 动作到 CLI 命令的映射

ANYGEN.md 中整理了一张"Agent 想做什么 → 敲什么命令"的速查表,是编写 Agent 技能(skill)时的命令级契约:

Agent ActionCLI Command
Create a slide decktask create --operation slide --prompt "..." -o task.json
Create a documenttask create --operation doc --prompt "..." -o task.json
Draw a diagramtask create --operation smart_draw --prompt "..." -o task.json
Full workflow (create→poll→download)task run --operation slide --prompt "..." --output ./
Check task statustask status <task-id>
Poll until completiontask poll <task-id> [--output ./]
Download result filetask download <task-id> --output ./
Download thumbnailtask thumbnail <task-id> --output ./
Upload a reference filefile upload <path>
Multi-turn requirement analysistask prepare --message "..." [--save conv.json]
Configure API keyconfig set api_key sk-xxx
View configurationconfig get [key]
View task historysession history
Undo last operationsession undo

命令实现上,taskfileconfigsession四组 Click 命令组定义于 anygen_cli.py,其中--operation参数使用click.Choice(VALID_OPERATIONS, case_sensitive=False)做输入校验,--ratio限定为16:9/4:3。不指定任何子命令时自动进入 REPL。

五、REST API 细节:端点、请求体与状态响应

Base URL:https://www.anygen.ioAuth:Bearer token(sk-…),经Authorization请求头传递。

端点一览

MethodEndpointDescription
POST/v1/openapi/tasksCreate a new generation task
GET/v1/openapi/tasks/:idQuery task status and metadata
POST/v1/openapi/files/uploadUpload a reference file →file_token
POST/v1/openapi/tasks/prepareMulti-turn requirement analysis

Create Task 请求体

{ "auth_token": "Bearer sk-xxx", "operation": "slide", "prompt": "Create a quarterly business review presentation", "language": "en-US", "slide_count": 10, "template": "business", "ratio": "16:9", "export_format": "pptx", "file_tokens": ["tk_abc123"], "files": [] }

从 anygen_backend.py 的create_task()可看到请求体组装的几个隐藏行为:

  • operation会先校验是否在VALID_OPERATIONS内;
  • style参数并不单独入体,而是以追加段落的方式拼进promptf"{prompt}\n\nStyle requirement: {style}"),即"风格要求"会被当作提示词的一部分交给生成引擎;
  • languageexport_formatfile_tokens为通用可选参数,有值才加入 body;
  • slide_counttemplateratio仅在operation == "slide"时才生效(从 CLI 与 API 两层都做了约束);
  • 请求体中的files字段是 legacy 的 base64 内嵌方式:encode_file()(见 anygen_backend.py)会按扩展名推断 MIME 类型(pdf/png/jpg/gif/txt/doc/docx/ppt/pptx)并做 base64 编码——现代用法推荐改用file_tokens引用预上传文件;
  • 创建请求超时 30 秒,返回{"task_id", "task_url"}

Task 状态响应

{ "task_id": "task_xxx", "status": "completed", "progress": 100, "output": { "file_url": "https://...", "file_name": "presentation.pptx", "thumbnail_url": "https://...", "task_url": "https://www.anygen.io/task/task_xxx", "slide_count": 10, "word_count": 2500 } }

query_task()(见 anygen_backend.py)对状态查询端点发起GET并返回完整任务字典;CLI 层的task status命令会从中抽取task_id/status/progress,若已完成则附带file_nametask_url

六、本地任务持久化:.anygen-task.json

为了让 CLI 具备"历史与回放(history and replay)"能力,每次创建/轮询/下载都会把任务元数据持久化到本地,格式即文档所述的.anygen-task.json

{ "version": "1.0", "task_id": "task_xxx", "operation": "slide", "prompt": "Create a quarterly business review presentation", "status": "completed", "created_at": "2026-03-09T12:00:00Z", "completed_at": "2026-03-09T12:01:23Z", "output": { "file_url": "https://...", "file_name": "presentation.pptx", "task_url": "https://www.anygen.io/task/task_xxx" }, "local_file": "./output/presentation.pptx", "metadata": { "file_size": 2048576 } }

源码层面的实现位于 core/task.py:记录并非散落在任务目录,而是统一存入~/.cli-anything-anygen/tasks/<task_id>.jsonTASK_HISTORY_DIR)。每个函数职责清晰:

  • create_task():写初始记录(status 为pending,含created_attask_url);
  • query_task()/poll_task():回填最新status/progress,轮询完成时补completed_at
  • download_file():回填local_filemetadata.file_size
  • list_task_records(limit, status_filter):按修改时间倒序列出本地缓存记录,支持按状态过滤——对应task list命令。

version: "1.0"字段为后续格式演进预留了兼容空间。

七、端到端实战:从上传素材到拿回成品文件

综合 README.md 与源码,下面是一条完整可复制的实战链路。

1. 配置 API Key

cli-anything-anygen config set api_key "sk-xxx"

2. 上传参考资料(拿到 file_token)

cli-anything-anygen file upload ./quarterly_data.pdf # Output: ✓ Uploaded: quarterly_data.pdf → token: tk_abc123

file upload的底层实现在 anygen_backend.py:以 multipart/form-data 方式POST /v1/openapi/files/upload,超时 60 秒,成功返回{file_token, filename, file_size};路径不存在会抛FileNotFoundError

3. 多轮需求澄清(可选,但强烈推荐)

# 第一轮:提交需求,AnyGen 会追问澄清问题 cli-anything-anygen task prepare --message "I need a quarterly review slide deck" --save conv.json # AnyGen asks clarifying questions... # 第二轮:补充关键信息并回灌上下文 cli-anything-anygen task prepare --message "Focus on revenue growth, 10 slides" --input conv.json --save conv.json # Status: ready, suggested operation: slide

task prepare的 CLI 实现(anygen_cli.py)支持--file-token(可重复)、--input conv.json载入既有对话、--save conv.json保存会话。API 请求体包含auth_tokenmessages(结构为[{role, content:[{type:text/file, ...}]}])与可选的file_tokens,超时放宽到 120 秒以容纳多轮推理。响应中的suggested_task_params会直接建议operation等建参,Agent 可据此自动续接创建任务。

4. 一条命令走完全流程(create → poll → download)

cli-anything-anygen task run \ --operation slide \ --prompt "Quarterly business review..." \ --file-token tk_abc123 \ --slide-count 10 \ --style "business formal" \ --output ./output/

5. 或按需分步执行

# 只创建(拿到任务 ID) cli-anything-anygen task create --operation doc --prompt "Technical design document" # Task ID: task_xxx # 轮询直到完成,并在完成后自动下载到 ./output/ cli-anything-anygen task poll task_xxx --output ./output/ # ✓ Downloaded: ./output/presentation.pptx (2,048,576 bytes) # 单独下载结果文件 / 缩略图 cli-anything-anygen task download task_xxx --output ./output/ cli-anything-anygen task thumbnail task_xxx --output ./output/ # 查看本地任务历史 cli-anything-anygen task list --limit 20 --status completed

6. Agent 消费:JSON 输出模式

cli-anything-anygen --json task status task_xxx cli-anything-anygen --json task list --limit 5

Create Task 参数完整表

ParameterShortDescriptionRequired
--operation-oOperation type (slide/doc/smart_draw/chat/...)Yes
--prompt-pContent descriptionYes
--language-lzh-CN / en-USNo
--slide-count-cNumber of PPT pages (slide only)No
--template-tPPT template (slide only)No
--ratio-r16:9 / 4:3 (slide only)No
--export-format-fpptx/image/thumbnail/docx/drawio/excalidrawNo
--file-tokenFile token from upload (repeatable)No
--style-sStyle preferenceNo

八、渲染管线:服务端异步模型与轮询原理

对 AnyGen 而言,"渲染"发生在服务端,CLI 负责编排。文档将其分为五步:

  1. 校验 operation 类型与 prompt;
  2. 携带认证头向 AnyGen API 提交任务(POST);
  3. 以 3 秒间隔轮询GET /v1/openapi/tasks/:id(最长 20 分钟);
  4. 完成后经 output 中的file_url下载文件;
  5. 保存到本地并校验文件完整性(大小 > 0、格式正确)。

轮询的核心实现在 anygen_backend.py 的poll_task():模块常量POLL_INTERVAL = 3MAX_POLL_TIME = 1200与文档描述完全对应;每次轮询比对progress变化并通过on_progress(status, pct)回调输出进度;遇到failed状态会抛出携带服务端error信息的RuntimeError;超过max_time则抛TimeoutError

渲染缺口评估:低(Low)

文档评估本模块的渲染缺口为Low,理由如下:

  • 所有渲染均在服务端完成,CLI 只是一个薄编排层;
  • 无需本地滤镜翻译或格式转换;
  • 风险集中在网络问题与 API 可用性上;
  • 唯一的例外:SmartDraw 生成的 drawio/excalidraw 若需转 PNG,可能依赖本地 Chromium 渲染

九、文件下载与完整性校验:不轻信任何一个字节

AnyGen CLI 在拿到生成文件后并不是简单落盘了事,而是叠加了一层完整性验证。下载逻辑在download_file()(anygen_backend.py)中:先确认任务确为completed、存在file_url,再流式写入目标目录;遇到同名文件时自动追加_1_2序号避免覆盖。缩略图则固定命名为thumbnail_<task_id>.png

校验器在 core/export.py 的verify_file(),按魔数与结构判断格式:

  • PPTX/DOCX/XLSX:检查 ZIP 魔数PK\x03\x04,再确认 zip 内含[Content_Types].xml以判定为合法 OOXML(否则标记为普通 ZIP);
  • PDF:检查%PDF-头部;
  • PNG:检查\x89PNG\r\n\x1a\n魔数;
  • SVG / drawio / XML:读取文本并检测<svg标签或 XML 声明;
  • JSON:实际执行json.load验证可解析性。

该函数会被 E2E 测试直接调用,作为"下载物确实是合法 OOXML/ZIP"的证据链。

十、Session 会话机制与 REPL:为"误操作"留一条退路

除了任务记录,CLI 还维护一份命令会话:每次task create/poll/download/runfile upload都会在 core/session.py 中被Session.record()记录为一条HistoryEntry(command、args、result、timestamp),并自动持久化到~/.cli-anything-anygen/session.json

session status # 查看历史条数、可 undo/redo 状态 session history --limit 20 # 查看最近命令 session undo # 撤销上一条操作 session redo # 重做被撤销的操作

两个值得称道的源码细节:

  • 撤销/重做是双向栈undo()将历史栈顶弹出并推入redo_stackredo()反之;新record()会清空 redo 栈,符合标准编辑器语义;
  • 写盘带进程锁_locked_save_json()利用fcntl.flock独占锁实现原子化写文件(在无fcntl的平台自动降级),避免多进程并发写坏 session.json——详见 core/session.py。

交互场景下,直接运行cli-anything-anygen进入 REPL(基于 prompt_toolkit),可用help列出全部可用命令,或在提示符中输入与命令行相同的子命令(如task run ...)。

十一、测试覆盖计划:Mock 单测 + 真实 E2E 双轨

文档将测试策略划分为两层,对应仓库中的两个测试文件:

1. 单元测试(test_core.py)—— Mock HTTP,无需真实 API

覆盖点包括:

  • task create/status/poll 的参数构造;
  • 配置加载(API key 来自 env / 文件 / CLI 选项的优先级);
  • 轮询逻辑(超时、重试、状态迁移);
  • JSON 输出格式;
  • 基于任务历史的 session undo/redo;
  • 错误处理(认证失败、限流、服务端错误);
  • 文件上传参数校验。

2. E2E 测试(test_full_e2e.py)—— 真实 API,需要ANYGEN_API_KEY

覆盖点包括:

  • 完整工作流:create task → poll → download → verify file;
  • slide 与 doc 操作产出可下载文件;
  • 文件格式校验(PPTX 是合法 ZIP,DOCX 是合法 OOXML);
  • 通过_resolve_cli进行 CLI 子进程调用;
  • 错误场景(非法 operation、空 prompt、坏 API key)。

从 test_full_e2e.py 源码看,E2E 用pytest.mark.skipif(not API_KEY)在未配置 key 时自动跳过;_resolve_cli()优先查找已安装命令,找不到时回退到python3 -m cli_anything.anygen.anygen_cli,方便开发环境直接跑。测试会对下载文件断言"大小 > 1000 字节"并调用verify_file()校验格式。

运行方式:

# 单元测试(Mock HTTP,无需 API key) python3 -m pytest cli_anything/anygen/tests/test_core.py -v # E2E 测试(需 ANYGEN_API_KEY) ANYGEN_API_KEY=sk-xxx python3 -m pytest cli_anything/anygen/tests/test_full_e2e.py -v # 全部测试 python3 -m pytest cli_anything/anygen/tests/ -v

十二、面向 Agent 的设计考量与使用边界

CLI 的 Agent 原生(agent-native)设计可归结为三点:

  1. 有状态的本地记录:任务与命令历史都落在~/.cli-anything-anygen/下(tasks/*.json+session.json),配合session undo/redo,Agent 具备"可回放、可回滚"的容错能力;
  2. 机器可读输出:全局--json使任何命令的输出都能被 Agent 直接解析,错误也以{"error": ..., "type": ...}结构化返回(见handle_error装饰器);
  3. 随包分发的技能文档:仓库在 skills/SKILL.md 提供描述命令组与用法的 agent skill 元数据,便于接入 LLM 工具注册。

最后需要明确边界:本 CLI 的正确性高度依赖 AnyGen 云端服务的可用性与 API 契约稳定性,生成质量与耗时由服务端引擎决定;若需要把 SmartDraw 结果本地渲染为 PNG 类位图,还需另行准备 Chromium 环境。在使用前,请通过 AnyGen 控制台(anygen.io/home → Setting → Integration)申请sk-格式的 API Key,并妥善保管——源码中对其回显做了掩码、写盘做了 0600 权限,Agent 在透传 key 时也应注意同样的安全策略。


本文基于 ANYGEN.md 写成,实现细节分别以 anygen_backend.py、core/task.py、core/export.py、core/session.py、anygen_cli.py 与两个测试文件为准。

【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 16:18:03

Penpot 数据模型详解:从 Profile 到 Shape 的完整实体体系

Penpot 数据模型详解&#xff1a;从 Profile 到 Shape 的完整实体体系 【免费下载链接】penpot Penpot: The open-source design platform for Product teams that need scalable collaboration. 项目地址: https://gitcode.com/GitHub_Trending/pe/penpot 本篇技术指南…

作者头像 李华
网站建设 2026/9/8 16:13:54

Transformer核心原理与PyTorch实现:自注意力、位置编码及训练避坑指南

我第一次把Transformer的代码跑通时&#xff0c;输出的序列和训练目标毫无关系——训练了一整晚&#xff0c;模型学会了把输入原封不动复制一遍。那时候网上还没有现在这么多教程&#xff0c;我只能对着《Attention Is All You Need》原文一个符号一个符号地抠。今天回头看&…

作者头像 李华
网站建设 2026/9/8 16:13:25

React Router 数据模式路由指南:从路由对象配置到匹配原理

React Router 数据模式路由指南&#xff1a;从路由对象配置到匹配原理 【免费下载链接】react-router Declarative routing for React 项目地址: https://gitcode.com/GitHub_Trending/re/react-router 本文基于当前仓库 docs/start/data/routing.md 展开。React Router …

作者头像 李华
网站建设 2026/9/8 16:13:17

如何用 IntelliJ IDEA 社区版源码构建并调试自己的 IDE

如何用 IntelliJ IDEA 社区版源码构建并调试自己的 IDE 【免费下载链接】intellij-community IntelliJ IDEA & IntelliJ Platform 项目地址: https://gitcode.com/GitHub_Trending/in/intellij-community IntelliJ IDEA 社区版源码仓库是 JetBrains 全系 IDE 的开源…

作者头像 李华
网站建设 2026/9/8 16:11:50

2026毕设封神工具|一篇吃透PaperXie!零基础直接无脑用✅

不吹不黑&#xff0c;2026年做毕设&#xff0c;有PaperXie真的能少熬80%的夜&#xff01; 很多大四同学忙到崩溃&#xff0c;不是因为论文太难&#xff0c;是没找对工具。大多数人只知道它能查重降重&#xff0c;却不知道它是从开题到答辩全覆盖的一站式毕设神器。 不用来回切…

作者头像 李华