news 2026/9/10 13:51:27

如何为 CLI-Anything 会话型 CLI 实现一次性命令自动保存与 --dry-run 跳过写入

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何为 CLI-Anything 会话型 CLI 实现一次性命令自动保存与 --dry-run 跳过写入

如何为 CLI-Anything 会话型 CLI 实现一次性命令自动保存与 --dry-run 跳过写入

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

按 HARNESS.md 搭建 CLI-Anything 会话型 CLI 时,会碰到一个具体缺陷:形如cli-anything-kdenlive --project p.json bin import video.mp4的一次性(one-shot)命令只修改了内存中的项目对象,退出前从未调用save_session()。进程结束后磁盘上的项目文件没有任何变化,修改被静默丢失。

本文解决的就是这个问题:在<software>_cli.py中做两处改动,让一次性命令执行完成后自动把项目写回磁盘,同时新增--dry-run标志让调用方可以执行命令、查看输出但不落盘。仓库中的 auto-save-dry-run.md 给出完整方案,kdenlive_cli.py 是一份可对照的现成实现。

适用条件:先确认你的 harness 属于会话型

官方指南给出了明确的适用边界。这一套模式适用于同时满足以下条件的 harness:

  • core/session.py存在,且带有save_session()方法和_modified修改标记;
  • CLI 接受--project参数来加载文件支撑的项目;
  • 命令在修改项目前调用sess.snapshot()记录 undo 快照。

无状态的 API 客户端、服务包装器或不带持久化项目文件的 harness 不适用——它们没有"修改后需要保存"的概念,不要硬套。

前置步骤:确认 save_session 使用带锁的 JSON 写入

自动保存最终会调用sess.save_session(),而它底层的文件写入必须使用 _locked_save_json 模式。直接用open("w") + json.dump()是不行的:open("w")在任何锁获取之前就会把文件截断,并发写入会损坏数据。

正确做法是先用"r+"打开(打开时不截断),拿到排他锁后再在锁内截断:

def _locked_save_json(path, data, **dump_kwargs) -> None: """Atomically write JSON with exclusive file locking.""" try: f = open(path, "r+") # no truncation on open except FileNotFoundError: os.makedirs(os.path.dirname(os.path.abspath(path)), exist_ok=True) f = open(path, "w") # first save — file doesn't exist yet with f: _locked = False try: import fcntl fcntl.flock(f.fileno(), fcntl.LOCK_EX) _locked = True except (ImportError, OSError): pass # Windows / unsupported FS — proceed unlocked try: f.seek(0) f.truncate() # truncate INSIDE the lock json.dump(data, f, **dump_kwargs) f.flush() finally: if _locked: fcntl.flock(f.fileno(), fcntl.LOCK_UN)

两点行为说明来自指南:fcntl不可用或文件系统不支持时(如 Windows),代码按无锁方式继续写;文件不存在时首次保存会先创建目录再用"w"打开。kdenlive harness 中的实际实现在 core/session.py,save_session()在写入后把self._modified重置为False(L125-L139)。

如果现有 harness 的core/session.py里已经是这个模式,可以直接跳到下一步。

改动一:在 main CLI group 上增加 --dry-run

指南要求在<software>_cli.py的主 Click group 上添加--dry-run选项:

@click.group(invoke_without_command=True) @click.option("--json", "use_json", is_flag=True, help="Output as JSON") @click.option("--project", "project_path", type=str, default=None, help="Path to project file") @click.option("--dry-run", "dry_run", is_flag=True, default=False, help="Run command without saving changes to disk") @click.pass_context def cli(ctx, use_json, project_path, dry_run): ...

click会把 group 上的 option 值透传给后面的result_callback,所以下一步的回调函数里能直接拿到dry_run。kdenlive 的对应代码见 kdenlive_cli.py 第 124-L131 行。

改动二:用 @cli.result_callback() 实现退出时自动保存

在 group 定义之后追加一个 result callback:

@cli.result_callback() def auto_save_on_exit(result, use_json, project_path, dry_run, **kwargs): """Auto-save project after one-shot commands if state was modified.""" if _repl_mode: return if dry_run: return sess = get_session() if sess.has_project() and sess._modified and sess.project_path: try: sess.save_session() except Exception as e: click.echo(f"Warning: Auto-save failed: {e}", err=True)

result_callback在 CLI group 的整条命令链执行完之后触发一次。回调里做三道检查,任何一条不满足就跳过保存:

  • _repl_mode为真时跳过——REPL 模式下用户手动保存,不自动写盘;
  • dry_run为真时跳过——这是--dry-run的语义来源;
  • sess._modified为假时跳过——没有任何修改发生就没有东西可存(snapshot()在每次变更前置位这个标记)。

保存失败不会抛异常中断,而是向 stderr 输出一行Warning: Auto-save failed: ...。另外指南明确指出:如果错误路径中handle_error调用了sys.exit(1),result callback 不会触发——这是预期行为,错误退出时不做保存。

如果上面的get_session()_repl_mode等符号在你的 harness 里名字不同,按自己的会话模块替换即可;kdenlive 的实现与指南模板逐行一致,见 kdenlive_cli.py 第 149-L161 行。

可选替代:ctx.call_on_close 闭包模式

如果你的 harness 不是在 group 入口通过全局单例拿会话,而是在 group 内部内联打开会话,指南给出了替代写法——用闭包把会话和dry_run捕获进ctx.call_on_close回调:

def cli(ctx, use_json, project_path, dry_run): ... if project_path: sess = get_session() proj = proj_mod.open_project(project_path) sess.set_project(proj, project_path) def _auto_save(): if dry_run: return if sess._modified and sess.project_path and not _repl_mode: sess.save_session() ctx.call_on_close(_auto_save)

两种方式二选一,不要把两套都挂上,否则同一次修改会被保存两遍。

--dry-run 的完整语义

指南用一个表格定义了三种模式下的行为,实现时以此为准:

模式行为
One-shot(默认)命令执行,输出打印,项目自动保存
One-shot +--dry-run命令执行,输出打印,项目保存
REPL--dry-run被接受但忽略(REPL 从不自动保存)

注意第三行:在 REPL 中传--dry-run不会报错,也不会产生任何额外效果,因为 REPL 本来就不自动保存。

验证改动是否生效

改动完成后按两条命令核对行为,判断依据是项目文件本身:

  1. 默认路径:对磁盘上的项目文件执行一次有修改的一次性命令(kdenlive 示例中是cli-anything-kdenlive --project p.json bin import video.mp4)。执行完毕后检查项目文件——命令执行、输出正常打印,且文件内容已更新为修改后的状态,说明自动保存生效。这正是修复前"进程退出时文件无变化"问题的反面验证。
  2. 跳过写入路径:对同一文件加上--dry-run重跑同一条命令。命令照常执行并打印输出,但项目文件内容与运行前一致,说明写入被正确抑制。
  3. 如果保存过程出错(如路径不可写),命令行会输出Warning: Auto-save failed: <错误信息>而不是静默吞掉异常,可以据此判断写入环节的问题。

仓库里可以直接读源码对照的参考实现:kdenlive_cli.py(group 定义与auto_save_on_exit回调)和 core/session.py(_locked_save_jsonsave_session())。

边界与限制

  • 该模式只覆盖"文件支撑的项目 + 一次性命令"这一条链路;REPL 会话的保存责任仍在用户(或驱动 REPL 的 agent)手上。
  • fcntl锁依赖 POSIX 文件系统;在 Windows 或不支持锁的文件系统上,_locked_save_json会退化为无锁写入,并发写入的防护随之失效,指南对此的说明是"proceed unlocked"。
  • 无状态 harness 不需要也不应该引入这套逻辑。

完整的方案文档见 guides/auto-save-dry-run.md,锁写入模式见 guides/session-locking.md,harness 整体开发流程(Phase 3 的会话管理要求)见 HARNESS.md。

【免费下载链接】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/10 13:50:49

2026企业AI办公工具选型指南:从功能堆砌到业务场景匹配

数字化转型进程中&#xff0c;AI办公工具已经从尝鲜试点&#xff0c;逐步进入企业正式采购清单。不少IT负责人、业务管理者在调研各类产品时&#xff0c;习惯直接对比功能清单&#xff0c;统计模型能力、对话模式、插件数量&#xff0c;或是单纯参考市场热度、采购预算来敲定方…

作者头像 李华
网站建设 2026/9/10 13:50:13

Java汽车租赁项目实战:状态机、事务与Redis防超租

简介&#xff1a;一套基于SpringBoot的汽车租赁管理系统Java源码&#xff0c;面向计算机、电子信息工程等专业学习者&#xff0c;适合作为毕业设计、课程设计或期末大作业参考。系统采用B/S架构与MVC模式&#xff0c;整合MySQL、MyBatis、Vue等主流技术栈&#xff0c;涵盖车辆管…

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

数据湖成本优化:存储与计算资源管理实践

1. 数据湖成本控制的行业背景与核心挑战 在大数据技术快速发展的今天&#xff0c;数据湖已经成为企业数据架构中不可或缺的组成部分。不同于传统数据仓库的严格模式约束&#xff0c;数据湖以其"原始存储按需处理"的灵活特性&#xff0c;能够容纳结构化、半结构化和非…

作者头像 李华
网站建设 2026/9/10 13:49:04

主数据管理定制化实践与行业解决方案

1. 主数据管理为何需要量体裁衣主数据管理&#xff08;Master Data Management&#xff0c;简称MDM&#xff09;就像企业数据体系的"身份证系统"。想象一下&#xff0c;如果一家跨国公司的客户信息在销售、财务、物流系统中各自为政&#xff0c;同一个客户可能被记录…

作者头像 李华
网站建设 2026/9/10 13:48:59

Python+BLE自制手环:从传感器数据到人机交互闭环实战

可穿戴设备的人机交互&#xff0c;听起来像是实验室里才有的课题&#xff0c;但落到代码和硬件上&#xff0c;其实就是“如何让设备知道你抬了一下手腕、心率飙到了多少&#xff0c;然后给出正确的反馈”。这篇文章来自我自己捣鼓的一个完整小项目&#xff1a;用Python做上位机…

作者头像 李华