diff --git a/.changeset/pre.json b/.changeset/pre.json index 233877d..96174a3 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -26,6 +26,7 @@ "amsg-engines-range-align", "amsg-instant-adapter-degradation", "amsg-instant-auth-exports", + "amsg-instant-chunk-probe-auth", "amsg-instant-multipart-chunk-cap", "amsg-instant-stream-first-byte-500", "amsg-llm-200-error-body", @@ -56,9 +57,11 @@ "amsg-server-expose-capabilities", "amsg-server-fine-grained-cleanup", "amsg-server-fire-settled", + "amsg-server-generation-retry-policy", "amsg-server-gzip-request-body", "amsg-server-hook-contract-identity", "amsg-server-hook-write-state", + "amsg-server-inflight-and-resume", "amsg-server-last-error-nonretryable", "amsg-server-lasterror-terminal-lease", "amsg-server-lease-heartbeat-runtask", @@ -93,6 +96,7 @@ "amsg-sw-failure-visibility", "amsg-sw-multipart-done-memory-fallback", "amsg-sw-multipart-failure-visibility", + "amsg-sw-multipart-give-up-reason", "amsg-sw-notification-show-cost", "amsg-task-detail-and-contact-name", "amsg-user-push-subscription", @@ -102,6 +106,7 @@ "blob-store-cjs-types", "blob-store-content-scan", "blob-store-gc-numeric-guard", + "blob-store-id-charset-single-source", "blob-store-initial", "blob-store-restore", "license-files", diff --git a/package-lock.json b/package-lock.json index f38d975..3f3f3d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3617,7 +3617,7 @@ }, "packages/rei-standard-amsg/instant": { "name": "@rei-standard/amsg-instant", - "version": "0.11.0-next.8", + "version": "0.11.0-next.9", "license": "MIT", "dependencies": { "@rei-standard/amsg-shared": "^0.4.0-next.10" @@ -3632,7 +3632,7 @@ }, "packages/rei-standard-amsg/server": { "name": "@rei-standard/amsg-server", - "version": "2.6.0-next.30", + "version": "2.6.0-next.31", "license": "MIT", "dependencies": { "@netlify/blobs": "^8.1.0", @@ -3676,7 +3676,7 @@ }, "packages/rei-standard-amsg/sw": { "name": "@rei-standard/amsg-sw", - "version": "2.4.0-next.7", + "version": "2.4.0-next.8", "license": "MIT", "dependencies": { "@rei-standard/amsg-shared": "^0.4.0-next.9" @@ -3691,7 +3691,7 @@ }, "packages/rei-standard-blob-store": { "name": "@rei-standard/blob-store", - "version": "0.1.0-next.2", + "version": "0.1.0-next.3", "license": "MIT", "devDependencies": { "@types/react": "^18.0.0", diff --git a/packages/rei-standard-amsg/instant/CHANGELOG.md b/packages/rei-standard-amsg/instant/CHANGELOG.md index c110c4a..785c159 100644 --- a/packages/rei-standard-amsg/instant/CHANGELOG.md +++ b/packages/rei-standard-amsg/instant/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog — @rei-standard/amsg-instant +## 0.11.0-next.9 + +### Patch Changes + +- 14406f1: 分片大小上限的校验按最长的 messageKind 算;X-Client-Token 的校验只留一份实现 + + `multipart.maxChunkBytes` 的上限校验用一条探针量信封开销,探针之前固定用 `reasoning`,比最长的 `tool_request` 短 3 字节。把 `maxChunkBytes` 配在上限附近(例如照着 `createInstantHandler` 抛错时建议的最大值去配)的部署,`content` / `reasoning` 的分片发得出去,`tool_request` 的分片每一片都超出单条 push 的明文上限、被推送服务拒收。现在按真实取值里最长的那个量,报出来的最大值对所有类型都成立。 + + 导出的 `validateClientAuth` 与 `createInstantHandler` 内部的校验现在共用同一份实现(存在性检查、常时比较、401 响应体都是同一处),两边不会再各自漂。函数签名和行为不变,handler 仍然用启动时编好的 token 字节,没有每请求重编。 + ## 0.11.0-next.8 ### Patch Changes diff --git a/packages/rei-standard-amsg/instant/package.json b/packages/rei-standard-amsg/instant/package.json index e5b0526..81e3b97 100644 --- a/packages/rei-standard-amsg/instant/package.json +++ b/packages/rei-standard-amsg/instant/package.json @@ -1,6 +1,6 @@ { "name": "@rei-standard/amsg-instant", - "version": "0.11.0-next.8", + "version": "0.11.0-next.9", "description": "ReiStandard Active Messaging — agentic-loop framework for instant push. Pluggable per-turn hook + optional blob envelope for oversize payloads. Three-axis push schema (messageKind / messageType / messageSubtype) from @rei-standard/amsg-shared. Auto-emits ReasoningPush when the LLM response carries reasoning_content. Pure Web Crypto. Deployable to Cloudflare Workers / Vercel Edge / Netlify / Node with no flags.", "repository": { "type": "git", diff --git a/packages/rei-standard-amsg/server/CHANGELOG.md b/packages/rei-standard-amsg/server/CHANGELOG.md index 9f5d8fa..2910607 100644 --- a/packages/rei-standard-amsg/server/CHANGELOG.md +++ b/packages/rei-standard-amsg/server/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog — @rei-standard/amsg-server +## 2.6.0-next.31 + +### Minor Changes + +- 0e644ed: Add per-task `maxGenerationRetries` configuration and `onFireSettled.willRetry` / `failureStage` receipts. Interactive requests can stop after their first generation failure without provider-specific error codes, while committed outbox batches retain delivery-only retries. Existing tasks and default retry behavior remain compatible. +- 0822c47: 改任务不再让这次触发重新生成一遍;顶替旧任务在 pg / neon 上也一起成败;投递进行中不接受改排期 + + **改任务不再让已经落定的那次触发重新生成。** 一次触发的整批内容落进收件箱之后推送失败、任务进入重试,这期间用户调 `PUT /update-message` 改了任何字段(哪怕只是联系人名字),重试那一跳之前会重新调 LLM 生成一整条:旧那批还在收件箱里等客户端补收,同一个时刻于是冒出两份内容,生成的钱也白花一次。原因是「这次触发有没有落定的内容」之前靠 `retry_count > 0` 判断,而改任务会把重试计数清零(这是它该做的——修好 apiKey 的任务不该背着旧账)。现在每次投递都直接去收件箱里认这次触发的批次,认到就只补推送。代价是每次定时触发多一次收件箱查询(D1 走已有索引;pg / neon 没有收件箱,这一步直接跳过)。 + + 一次触发的内容一旦落定,这次就按落定的那份发完;改动从下一次触发开始生效。一次性任务在这个窗口里改内容,改的这一版就用不上了。 + + **`supersedesUuid` 顶替旧任务在 pg / neon 上也是一条语句。** 之前只有 D1 是「删旧 + 建新一起成败」,pg / neon 退回先删旧、再建新两步:建新那一步失败(uuid 撞了、连接一时抖了)时旧任务已经删掉,接口却回失败,客户端以为旧任务还在,其实再也找不回来。现在 `pg` / `neon` 也实现了 `createTaskSuperseding`(数据修改型 CTE,INSERT 抛错时 DELETE 跟着回滚)。没实现这个方法的自定义适配器仍走两步退路,但顺序改成先建新、后删旧——最坏是两条都留着,客户端重试一次就能收拾干净。 + + **任务正在投递时不接受改排期。** 投递收尾会按它领取时看到的排期推进下一次(一次性任务标成已发送),这期间写进去的新时刻随后就被盖掉,接口却已经回了成功。现在三个内置适配器的 `updateTaskByUuid` 在改 `next_send_at` 时多一道租约门: + + | 入口 | 碰上正在投递的任务 | + | ---------------------------------------------- | ------------------------------------------------------------------------------------- | + | `PUT /update-message` 带 `nextSendAt` | 409 `TASK_IN_FLIGHT`(任务不存在仍是 404,行不是 pending 仍是 409 `UPDATE_CONFLICT`) | + | fire hook 的 `ctx.renewTask(uuid, nextSendAt)` | `{ renewed: false, reason: 'in_flight' }` | + + 投递一般几秒到几十秒(agentic 链路默认最多 240 秒),worker 中途没了的话租约在 ~90 秒内到期,之后照常能改。只改正文这类字段不受这道门约束:它们只影响以后的触发,收尾本来就不覆盖用户刚保存的内容。等重试的那几分钟任务没被占用,照常能改。 + + **分片大小上限的校验按最长的 `messageKind` 算。** `multipart.maxChunkBytes` 的上限校验用一条探针量信封开销,探针之前固定用 `reasoning`,比最长的 `tool_request` 短 3 字节。把 `maxChunkBytes` 配在上限附近(例如照着校验失败时建议的最大值去配)的部署,`content` / `reasoning` 的分片发得出去,`tool_request` 的分片每一片都超出单条 push 的明文上限、被推送服务拒收。现在按真实取值里最长的那个量,报出来的最大值对所有类型都成立。 + ## 2.6.0-next.30 ### Minor Changes diff --git a/packages/rei-standard-amsg/server/package.json b/packages/rei-standard-amsg/server/package.json index 206a5d7..215c345 100644 --- a/packages/rei-standard-amsg/server/package.json +++ b/packages/rei-standard-amsg/server/package.json @@ -1,6 +1,6 @@ { "name": "@rei-standard/amsg-server", - "version": "2.6.0-next.30", + "version": "2.6.0-next.31", "description": "ReiStandard Active Messaging server SDK with pluggable database adapters. Three-axis push schema (messageKind / messageType / messageSubtype) from @rei-standard/amsg-shared. Auto-emits ReasoningPush when the LLM response carries reasoning_content.", "repository": { "type": "git", diff --git a/packages/rei-standard-amsg/sw/CHANGELOG.md b/packages/rei-standard-amsg/sw/CHANGELOG.md index e23dd4d..ff5deb7 100644 --- a/packages/rei-standard-amsg/sw/CHANGELOG.md +++ b/packages/rei-standard-amsg/sw/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog — @rei-standard/amsg-sw +## 2.4.0-next.8 + +### Patch Changes + +- 0b13bda: 放弃一条分片消息时,报的原因不再被墓碑写失败盖成「存储故障」 + + 分片重组有四条当场放弃的路径:重组窗口走完、同一个 id 的分片对 total / encoding 各说各话、累计字节超过 `maxTotalBytes`、分片齐了却拼不回原 payload。这几条都会先写「这个 id 到此为止」的墓碑再广播 `MULTIPART_EXPIRED`,而墓碑写失败(存储压力大的时候正是它容易失败)时异常会冒到外层兜底,页面收到的原因于是一律变成 `storage-failed`,本来那条具体原因(`chunk-conflict` / `size-limit-exceeded` / `restore-failed` / `ttl-expired`)丢了——宿主拿这个原因做诊断的话,压力下会把发送端发冲突分片这类问题统一误读成存储故障。 + + 现在这四条路径的收尾失败按住不外抛(结论此前已经记进内存兜底表,后续分片和推送服务的重投照样进不来),仍然用本来那条原因广播一次事件,收尾失败另留一条日志。页面收到的事件次数不变。 + ## 2.4.0-next.7 ### Patch Changes diff --git a/packages/rei-standard-amsg/sw/package.json b/packages/rei-standard-amsg/sw/package.json index a080b64..c4f0275 100644 --- a/packages/rei-standard-amsg/sw/package.json +++ b/packages/rei-standard-amsg/sw/package.json @@ -1,6 +1,6 @@ { "name": "@rei-standard/amsg-sw", - "version": "2.4.0-next.7", + "version": "2.4.0-next.8", "description": "ReiStandard Active Messaging service worker SDK — three-axis push schema (content / reasoning / tool_request / error) with per-kind client postMessage events", "repository": { "type": "git", diff --git a/packages/rei-standard-blob-store/CHANGELOG.md b/packages/rei-standard-blob-store/CHANGELOG.md index bd7f58c..d11d358 100644 --- a/packages/rei-standard-blob-store/CHANGELOG.md +++ b/packages/rei-standard-blob-store/CHANGELOG.md @@ -1,5 +1,13 @@ # @rei-standard/blob-store +## 0.1.0-next.3 + +### Patch Changes + +- 26ba771: 令牌 id 的字符集判定收到一处 + + `gc` / `content-scan` / `store` 三处此前各写了一份 `[A-Za-z0-9_]` 的判定,注释互相提醒「要和 `extractRefs` 保持一致」。GC 判断一个 Blob 能不能回收,靠的就是这几处规则完全一致。现在字符集只在 `token.js` 定义一次,四处判定都用它。行为不变,公共 API 没有变化。 + ## 0.1.0-next.2 ### Minor Changes diff --git a/packages/rei-standard-blob-store/package.json b/packages/rei-standard-blob-store/package.json index 9435b5a..5b75541 100644 --- a/packages/rei-standard-blob-store/package.json +++ b/packages/rei-standard-blob-store/package.json @@ -1,6 +1,6 @@ { "name": "@rei-standard/blob-store", - "version": "0.1.0-next.2", + "version": "0.1.0-next.3", "description": "ReiStandard token-based Blob storage — binary in IndexedDB, a short blobref: token in your data fields; orphan GC included", "repository": { "type": "git",