Skip to content

feat(amsg-server): onBeforeFire skip 出口 + GET /messages 投影 charId/clientTaskId#28

Merged
Tosd0 merged 2 commits into
mainfrom
feat/amsg-before-fire-skip
Jul 21, 2026
Merged

feat(amsg-server): onBeforeFire skip 出口 + GET /messages 投影 charId/clientTaskId#28
Tosd0 merged 2 commits into
mainfrom
feat/amsg-before-fire-skip

Conversation

@Tosd0

@Tosd0 Tosd0 commented Jul 21, 2026

Copy link
Copy Markdown
Owner

本 PR 含两项上游改动,同属一次发版(下游 SullyOS amsg2 多任务改造依赖这两项)。均只动 @rei-standard/amsg-server,各带 changeset(minor),未发版。


1. onBeforeFire 支持 { skip: true } 生成前跳过

onBeforeFire hook 新增第三条出口:返回 { skip: true },让宿主在第一次 LLM 调用之前作废本次定时触发。

原来只有两条路——返回 messages(fire 时刻现场组装 prompt),或返回 null(回退排程时冻结的 completePrompt 老链路)。现在多一条:{ skip: true } 直接把本次 fire 当成一次零推送的成功投递结束(status: 'skipped'),一次性任务照删、循环任务照推进到下次,不调用 LLM、不消耗 token

用途:宿主在 fire 时刻就能判断这条消息已经多余(比如排程之后对话又有了新进展)时作废它。返回 null 的既有语义不变。

文件 改动
server/src/server/lib/agentic-fire.js before == null 判断后新增 { skip: true } 分支,返回形状与既有 skip-push 一致(iterations: 0);同步更新文件头流程注释、@returns JSDoc、AGENTIC_BAD_BEFORE_FIRE 文案
server/src/server/lib/message-processor.js fire-time hooks 注释补 skip 语义
server/examples/cloudflare-single-user/README.md onBeforeFire 契约补 { skip: true } 一行

2. GET /messages 投影 charId / clientTaskId

GET /messages 每条任务额外返回 charId / clientTaskId(取自任务 metadata 的 charId / amsgClientTaskId,缺省 null),供宿主按角色归属筛选任务——contactName 会在不同角色间重名,不可靠。

边界:只投影这两个字段,不回传整个 metadata(其余可能是宿主自定义数据);凭据类字段照旧不回传;老任务无这俩字段返回 null 不报错;响应照旧整体加密。分页未动。

文件 改动
server/src/server/handlers/messages.js decryptedTasks 投影加 charId / clientTaskId?? null 兜底)

验证

  • 两项均 TDD:先写失败测试跑红,再实现转绿。
  • packages/rei-standard-amsg/server 全量测试 185 passed / 0 failed

https://claude.ai/code/session_017mfb5T9eZU4iHpFbCEmeqR

宿主在 fire 时刻就能判断消息已多余时,onBeforeFire 返回 { skip: true }
作废本次触发:算一次零推送成功(status: 'skipped'),一次性任务照删、
循环任务照推进到下次,不调 LLM、不耗 token。返回 null 的老语义不变。

Claude-Session: https://claude.ai/code/session_017mfb5T9eZU4iHpFbCEmeqR

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new { skip: true } return option for the onBeforeFire hook, allowing the host to cancel a scheduled message fire before the first LLM call is made, resulting in a zero-push success. The feedback suggests improving code cohesion by centralizing the validation of { skip: true } inside normalizeBeforeFireResult to avoid inconsistencies with its updated error message, and simplifying the redundant type check typeof before === 'object' in runAgenticFire since before is already verified to be non-null.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

}
throw new TypeError(
'AGENTIC_BAD_BEFORE_FIRE: onBeforeFire must return ChatMessage[] | { messages, maxToolIterations?, totalTimeoutMs? } | null'
'AGENTIC_BAD_BEFORE_FIRE: onBeforeFire must return ChatMessage[] | { messages, maxToolIterations?, totalTimeoutMs? } | { skip: true } | null'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

虽然在 runAgenticFire 中提前拦截了 { skip: true },但 normalizeBeforeFireResult 函数内部并没有实际支持 { skip: true } 的解析。如果直接传入 { skip: true },该函数仍然会抛出 TypeError。这使得 normalizeBeforeFireResult 的错误提示信息与其实际行为不一致,且验证逻辑有些分散。建议将 { skip: true } 的解析和验证也统一放入 normalizeBeforeFireResult 中,使代码更加内聚和易于维护。

// conversation moved on after the task was scheduled). Shaped exactly like
// the post-LLM 'skipped' result, so run-tick's success handling (delete
// once-off / advance recurrence) applies unchanged — and zero tokens spent.
if (typeof before === 'object' && before.skip === true) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

由于在第 183 行已经进行了 before == null 的空值检查,此时 before 已经确保不为 nullundefined。在 JavaScript 中,对任何非空原始类型(如字符串、数字、布尔值等)访问属性都是安全的(会返回 undefined 而不会报错)。因此,这里的 typeof before === 'object' 判断是多余的,可以直接简化为 before.skip === true,使代码更加简洁和地道。

Suggested change
if (typeof before === 'object' && before.skip === true) {
if (before.skip === true) {

每条任务额外返回 charId / clientTaskId(取自任务 metadata 的 charId /
amsgClientTaskId,缺省 null),供宿主按角色归属筛选任务。metadata 其余
字段与凭据类字段照旧不回传。

Claude-Session: https://claude.ai/code/session_017mfb5T9eZU4iHpFbCEmeqR
@Tosd0 Tosd0 changed the title feat(amsg-server): onBeforeFire 支持 { skip: true } 生成前跳过 feat(amsg-server): onBeforeFire skip 出口 + GET /messages 投影 charId/clientTaskId Jul 21, 2026
@Tosd0
Tosd0 merged commit fd9e1a0 into main Jul 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant