Skip to content

feat: 上游九项能力落地(条件写护栏 / immediate·supersede / 租约心跳 / last_error / NonRetryableError / cancel·renew / outbox+ack / 导出常量 / usage)+ llmExtraBody - #50

Merged
Tosd0 merged 1 commit into
mainfrom
claude/client-state-delivery-fixes-v1oqi6
Aug 7, 2026

Conversation

@Tosd0

@Tosd0 Tosd0 commented Aug 6, 2026

Copy link
Copy Markdown
Owner

按包装层审查清单,把九项 major/结构级/卫生级问题的上游半边一次落地,另加一项 llmExtraBody 透传(thinking 参数必需)。全部 764 个测试通过(含新增 19 个),npm run ci 绿。

高优先:消 major

  1. client_state 条件写护栏(major Add Instant message type documentation #2 / add @rei-standard/amsg-instant + client sendInstant #7):PUT /client-state 的 entry 认可选 version / builtAt,last-write-wins 按内容新旧而不是请求先后比较——慢网下晚到的旧 fire_pack 盖不掉先到的新包。被拦下的 key 在 data.skippedEntries 逐条回报。hook 的 ctx.writeState() 同样认 version
  2. /schedule-message immediate + 原子 supersede(major Add AI guidelines to API documentation #3、次要 C7):immediate: true 跳过未来校验、next_send_at = now(下一跳 cron 直接触发),pullTaskDue 裸 SQL、31s 兜底、INSTANT_SCHEDULE_LEAD_MS 推导全部可退役;supersedesUuid 在 D1 上走新的 createTaskSuperseding(同一 batch 删旧建新,撞 uuid 整体回滚),响应带 superseded
  3. 租约心跳续租 + runTask(major Remove unused encryption imports from messages route #1):占位只写 90s 短租约,投递期间每 30s 滚动续租(新适配器方法 renewTaskLease,D1/pg/neon 均实现;失败路径照旧主动清租约)——isolate 死亡后任务 ~90s 内被下一跳接手,不再等 10 分钟死租约。leaseHeartbeatMs: 0 退回旧行为。另导出 runTask(ctx, uuid):与 tick 完全同链的单任务入口,供 CF Queue 消费者(15 分钟预算)使用,彻底解决而非缓解。
  4. last_error 列 + GET /message 透出 + onFireSettled 带 metadata(major release(amsg): SSE transport + instant backup push, de-deprecate in-server instant (shared 0.2.0 / client 2.5.0 / instant 0.9.1 / server 2.5.2 / sw 2.3.1) #11):scheduled_messageslast_error(脱敏 JSON 摘要,sanitizeErrorSummary 遮 token、截 500 字符),每次失败都写(等重试期间也可见)、成功清掉;GET /message?id= 对已失败的行在 409 error.details 里带 { status, lastError }onFireSettled 载荷加解密 metadata(charId、amsgInstantChat 标记从此拿得到),chat_fail 侧信道可整体退役。缺列的老库自动退字段重写,状态推进不受影响。
  5. NonRetryableError(major Add Instant message type documentation #2/release(amsg): SSE transport + instant backup push, de-deprecate in-server instant (shared 0.2.0 / client 2.5.0 / instant 0.9.1 / server 2.5.2 / sw 2.3.1) #11 的 12 分钟徒劳重试、E3 重复计费):hook 抛它(或任何 permanent: true 的错误)即直接终审处置,run-tick 与 instant 路径都不再重排。
  6. fire ctx 补 cancelTask / renewTask(major release: amsg shared 0.2.0 / sw 2.2.0 / instant 0.9.0 / client 2.4.0 / server 2.5.0 #10):语义与 DELETE /cancel-messagePUT /update-message 一致,挂在 fireCtx 与每轮 sessionCtx;不允许操作当前正在 fire 的行(收尾归 run-tick)。

结构级

  1. 原生 outbox + ack(major Add Instant messaging notification logic to service worker #4/Restructure ReiStandard as single-package SDK with pluggable database adapters #5/[ENHANCEMENT] 分句传配置 #6/add @rei-standard/amsg-instant + client sendInstant #7、次要 B5/B7):新表 message_outbox——每条 push 发送前落行(per-user 密文、(user_id, message_id) 唯一,重试不加行、不复活已 ack 的),发出后标 delivered_at,半途失败只标已发出的段;GET /outbox?since= 拉未 ack(加密信封、游标翻页)、POST /outbox/ack 幂等确认;tick 顺手清理(acked 7 天 / 全量 28 天)。collectReceivedMessageIds 那套对账可整体退役。D1 专属(与 client_state 同待遇),outbox 全程 best-effort 不影响投递。

卫生级

  1. 导出鉴权与常量:instant 导出 validateClientAuth(presence + 常时比较,与 handler 同语义)、DEFAULT_MAX_LOOP_ITERATIONSCORS_ALLOW_HEADERS(且 cors.allowHeaders 可配);server 导出 CORS_ALLOW_HEADERS / CORS_ALLOW_METHODSDEFAULT_MAX_TOOL_ITERATIONS / DEFAULT_TOTAL_TIMEOUT_MS / MIN_SCHEDULE_LEAD_MS 等。包装层的两份手抄可删。
  2. usage 透出(次要 A2):shared buildSessionContextusagellmResponse.usage 引用,instant/server hook 同步获得);server 的 onAfterSend / onFireSettled 带最后一轮 usage

追加

  1. llmExtraBody 透传buildLlmRequestBody 先展开 payload.llmExtraBody 再写核心字段(model/messages/temperature/max_tokens/tools 永远以库为准);/schedule-message 白名单加 llmExtraBody,fire 内 scheduleTask 自排任务继承。

兼容与迁移

  • 新列/新表全部走 initSchema()POST /init-tenant)幂等补齐;升级后建议重跑一次 init。缺 last_error 列的写入有自动降级,不会卡住状态推进。
  • 心跳、护栏、outbox 对不传新参数/不实现新适配器方法的部署均保持旧行为;capabilities 新增 12 个特性位(client-state-version-guardschedule-immediateschedule-supersedetick-lease-heartbeatrun-task-entrypointtask-last-errornon-retryable-erroragentic-cancel-renew-taskmessage-outboxfire-settled-metadatahook-usagellm-extra-body)供前端探测。
  • 已按 changesets pre 模式 bump:server 2.6.0-next.15、instant 0.11.0-next.3、shared 0.4.0-next.5(9 个 changeset 附详细说明)。

测试

  • 新增 server/test/upstream-additions.test.mjs(18 例:护栏、immediate/supersede、心跳/runTask、last_error/NonRetryable、cancel/renew、outbox 全链路)+ buildAiRequestBody 的 llmExtraBody 用例。
  • 既有断言随契约更新(capabilities 名单、writeState 返回形状、sessionCtx 键白名单)。
  • npm run ci(esm 检查 + build + 全部 workspace 测试):90+187+349+75+63 全过。

🤖 Generated with Claude Code

https://claude.ai/code/session_01MSPJNCXJTnryLw3njT43df


Generated by Claude Code

…Error、cancel/renew、outbox+ack、导出常量、usage 透出)+ llmExtraBody 透传

高优先(消 major):
- client_state 条件写:PUT /client-state 的 entry 认 version/builtAt 护栏,
  按内容新旧比较;被拦下的 key 在 data.skippedEntries 逐条回报
- POST /schedule-message 认 immediate: true(next_send_at = now,下一跳 cron
  直接触发)与 supersedesUuid(D1 走 createTaskSuperseding 原子删旧建新)
- 租约按心跳滚动续租(30s 心跳 / 90s 租约,renewTaskLease),isolate 死亡后
  分钟级被接手;导出 runTask(ctx, uuid) 单任务入口给 Queue 消费者
- 任务行加 last_error 列(脱敏摘要,失败即写、成功清掉),GET /message 对
  已失败的行透出(409 details);onFireSettled 载荷带解密 metadata
- 导出 NonRetryableError:确定性失败直接终审处置,不再重试三轮
- fire ctx 补 cancelTask / renewTask(语义与 HTTP 端点一致)

结构级:
- message_outbox 表 + GET /outbox / POST /outbox/ack:push 发送前落行、发出
  标 delivered、客户端 ack——补收从「猜」变成「拉未 ack」

卫生级:
- instant 导出 validateClientAuth / DEFAULT_MAX_LOOP_ITERATIONS /
  CORS_ALLOW_HEADERS(cors.allowHeaders 可配);server 导出 CORS 头列表与
  agentic 预算常量
- SessionContext 带 usage;onAfterSend / onFireSettled 带最后一轮 usage
- buildLlmRequestBody 展开 llmExtraBody(核心字段优先),schedule-message
  白名单与 scheduleTask 继承链跟上

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSPJNCXJTnryLw3njT43df
@Tosd0
Tosd0 merged commit 2a8ed56 into main Aug 7, 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.

2 participants