npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@forget2save/opencode-goal-mode

v0.2.0

Published

A persistent, budgeted Goal mode plugin for OpenCode.

Downloads

107

Readme

OpenCode Goal Mode

这是一个可以加载到 OpenCode 1.16.x–1.18.x 的 Goal 模式插件。普通 turn 返回最终文本后,如果当前 session 仍有 active Goal,插件会监听 session.idle,注入 synthetic continuation,并让同一 session 继续处理剩余缺口。Goal 完成、暂停、阻塞或触及预算后,循环停止。

当前版本采用“显式终态工具”路线:工作 agent 必须调用 goal_complete,提交总体证据,并逐项覆盖验收条件;普通 final answer 本身不会结束 Goal。它不是独立 judge,因此证据仍属于 agent 自报。

已实现能力

  • Goal 按 session 持久化到项目的 .opencode/goal-mode/
  • active → paused | blocked | complete | budget_limited 状态机。
  • paused | blocked → active 恢复路径。
  • continuation 次数与 wall-clock deadline 双预算。
  • session.idle 自动续跑,消息标记为 synthetic,不伪装成真实用户输入。
  • session 级并发门禁,避免一次 idle 被重复调度。
  • 替换、暂停、完成、清理、删除 session 或卸载插件时取消正在执行的续跑。
  • 派发前再次检查 deadline;取消或派发失败会释放预留次数,失败时转为 paused,避免重试风暴。
  • 每次模型调用前只注入静态 Goal 安全合同,目标正文仍按用户数据处理。
  • 状态文件使用严格校验、抗碰撞文件名和可恢复替换,并自动迁移旧版状态。
  • 五个用户命令和七个模型工具。

兼容性

当前声明的兼容范围为 @opencode-ai/plugin >=1.16.0 <1.19.0,并使用 OpenCode 的稳定插件接口:

  • 配置字段是单数 plugin
  • 插件入口是 Plugin 函数;
  • 自动续跑调用 client.session.promptAsync()
  • 状态注入使用 experimental.chat.system.transform

官方另有仍处于 beta 的 V2/opencode2 插件接口,它使用复数 plugins。两套接口不能混用。

以下版本已经分别完成兼容性验证:

| OpenCode | 验证结果 | | --- | --- | | 1.16.0 | 通过 | | 1.16.1 | 通过 | | 1.16.2 | 通过 | | 1.18.15 | 通过 |

这里的宿主验证覆盖插件加载和适配路径,不等同于真实模型提供商下的长时间稳定性证明。由于自动续跑依赖 session.idlepromptAsync(),长驻的 TUI/server 是主要使用场景;opencode run 可能在 idle 后先行退出,不建议把它作为无人值守 Goal 循环的可靠宿主。

插件使用 TypeScript,因为 OpenCode 会在自身进程中加载 JavaScript/TypeScript 模块。教程中的 Python 示例不改变宿主插件 ABI。

安装

推荐直接在目标项目的 opencode.jsonc 中引用 npm 包:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["@forget2save/opencode-goal-mode"]
}

OpenCode 启动时会自动下载并缓存插件。用下面的命令确认配置和插件可以正常加载:

opencode debug startup

如果要在本地开发插件,先在插件目录安装依赖:

cd opencode-goal-mode
bun install

然后使用相对于配置文件的本地路径:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["./opencode-goal-mode"]
}

也可以把整个包复制到目标项目,再调整相对路径。本地包依赖不会由 OpenCode 自动替你安装,所以复制后仍需在插件目录运行一次 bun install

使用

创建 Goal:

/goal 把 HTTP 客户端迁移到 httpx.AsyncClient;保持 API 行为不变;pytest 和 mypy 通过;不要部署

命令会要求模型调用 goal_set,然后立即开始工作。普通 turn 结束而 Goal 仍为 active 时,插件会自动开始下一次 continuation。

控制命令会先读取当前 Goal ID,再调用对应工具:

/goal-status
/goal-pause 我需要先检查当前改动
/goal-resume
/goal-clear

模型可用工具:

  • goal_set:创建或替换 Goal,可单独指定验收条件、最大续跑次数和最大分钟数。
  • goal_status:读取状态和剩余预算。
  • goal_pause:使用当前 Goal ID 暂停。
  • goal_resume:使用当前 Goal ID 从 pausedblocked 恢复。
  • goal_complete:使用当前 Goal ID,携带总体证据和逐项验收证据进入终态。
  • goal_block:使用当前 Goal ID,记录真正的外部阻塞及其证据。
  • goal_clear:使用当前 Goal ID 删除该 session 的 Goal 状态。

goal_setgoal_status 外,所有状态变更工具都要求 goal_id。如果 ID 已过期,工具会拒绝修改并提示重新调用 goal_status,防止旧请求覆盖新 Goal。

默认预算为 12 次 continuation 和 60 分钟。单个 Goal 可以通过 goal_setmax_continuationsmax_minutes 覆盖。

状态与数据

每个 session 使用一个 JSON 文件,包含:

  • 目标与验收条件;
  • 状态、创建时间和 deadline;
  • continuation 已用量和上限;
  • 总体完成证据、逐项验收证据、阻塞证据或最后一次调度错误;
  • Goal ID 与 revision。

状态格式当前为 schema v2;插件会读取 schema v1 状态,并在下一次写入时迁移。每个 session 使用 SHA-256 文件名,读取时限制状态文件大小并核对文件内的 session ID。新的 goal_set 会用新 Goal ID 替换该 session 的旧 Goal。收到 session.deleted 后,插件会同步删除对应状态。

安全边界

  • Goal 模式不会扩大 OpenCode 原有工具权限。
  • continuation 有次数和时间上限。
  • complete 必须带非空总体证据,并为每条验收条件提供对应证据;当前版本不会独立验证证据真实性。
  • blocked 必须同时提供阻塞原因和阻塞证据。
  • blockedpaused 不会自动继续;恢复需要显式操作。
  • 调度失败会释放本次预留并进入 paused,不会消耗次数后无限重试。
  • 状态会跨插件重载保留;但重启后已经处于 idle 的 session 不一定重新发出 idle 事件,需要用户执行 /goal-resume 或发送一条消息重新唤醒。
  • 目标文本作为用户数据被明确分隔,不得覆盖 system policy 或权限边界。

开发与验证

bun run check
bun test test
bun run build
bun run smoke

或者一次完成:

bun run verify

实现分层:

  • src/domain.ts:Goal 数据合同、状态机和预算判定。
  • src/store.ts:JSON 持久化与同 session 串行更新。
  • src/controller.ts:idle gate、continuation 预留和错误降级。
  • src/system-hook.ts:隔离 experimental system hook 与静态安全合同。
  • src/index.ts:OpenCode hooks、commands 与 tools 适配。
  • test/:状态机、持久化、预算、并发和失败路径测试。
  • scripts/plugin-smoke.mjs:从编译产物实例化插件并验证完整适配路径。

当前限制

插件不会独立判定证据真实性。OpenCode 的 experimental.chat.system.transform 仍带有 experimental 前缀;OpenCode 升级后应重新运行完整验证,并检查该 hook 是否更名。