Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0278745
feat(amsg): three-axis push schema unification (next pre-release)
Tosd0 May 19, 2026
ba003d8
fix(amsg): avatarUrl 软清空 — 不再 400 整个任务
Tosd0 May 20, 2026
261ac0e
docs: avatarUrl 软清空策略同步到 §6.2 / READMEs
Tosd0 May 20, 2026
31205e4
fix(sw): 标题 fallback 至「来自 {contactName}」— 模仿 0.6.x 行为
Tosd0 May 20, 2026
6926b3d
chore(amsg): bump pre-release to *-next.1 — fold avatarUrl 软清空 + SW 标…
Tosd0 May 20, 2026
e00bf22
chore(amsg): release amsg-shared 0.1.0-next.2 / amsg-instant 0.8.0-ne…
Tosd0 May 20, 2026
2ce7de5
chore(amsg): sync package-lock with amsg-shared@0.1.0-next.2 bump
Tosd0 May 20, 2026
87df60b
chore(amsg): release amsg-shared 0.1.0-next.3 / amsg-instant 0.8.0-ne…
Tosd0 May 20, 2026
695b61b
feat(amsg-instant)!: 0.8.0-next.4 — reject removed split-pattern fields
Tosd0 May 21, 2026
85cfec2
feat(amsg-instant)!: 0.8.0-next.4 — reject decision.pushPayload + pus…
Tosd0 May 21, 2026
2d4a7c5
feat(amsg-instant)!: 0.8.0-next.4 — sendPushesSequentially(pushPayloads)
Tosd0 May 21, 2026
b68e249
feat(amsg-instant)!: 0.8.0-next.4 — reasoning auto-emit single-layer
Tosd0 May 21, 2026
b0a4846
docs(amsg-instant): justify reasoning floor + document undefined-iter…
Tosd0 May 21, 2026
db24967
test(amsg-instant)!: migrate hook tests to pushPayloads array
Tosd0 May 21, 2026
11bbe0e
test(amsg-instant)!: delete split-pattern suites
Tosd0 May 21, 2026
e2d7242
test(amsg-instant): 13-case pushPayloads contract matrix
Tosd0 May 21, 2026
ff4b03e
docs(amsg-instant)!: rewrite README §Hook for pushPayloads-only API
Tosd0 May 21, 2026
b23355c
docs(amsg-instant): README polish — fix messageKind dup + auto-fill t…
Tosd0 May 21, 2026
1088430
docs(amsg-instant)!: 0.8.0-next.4 CHANGELOG + migration guide + versi…
Tosd0 May 21, 2026
c98db03
docs(amsg-instant): fix Recipe 5 i-scope typo + clarify randomUUID so…
Tosd0 May 21, 2026
0f8f223
docs(amsg-instant): scrub stale exports + add server-divergence note …
Tosd0 May 21, 2026
19e878b
docs(amsg-instant): generic-ify hook examples — drop SullyOS-flavored…
Tosd0 May 21, 2026
dbba6a1
feat(amsg-instant): tighten messageId contract + drop split helpers +…
Tosd0 May 21, 2026
a2db930
chore(amsg-instant): sync package-lock with 0.8.0-next.4 bump
Tosd0 May 21, 2026
926d2c8
fix(amsg-instant): validateMessagesArray 放宽 OpenAI tool-call 形态 (0.8.…
Tosd0 May 22, 2026
e43fdff
feat(amsg-instant,amsg-sw)!: unify generic multipart transport
Tosd0 May 24, 2026
c3de7ae
feat(amsg-sw): add onBusinessPayload offline hook (2.1.0-next.3)
Tosd0 May 24, 2026
26894f9
feat(amsg): push notification.show support and multipart optimization
Tosd0 May 24, 2026
d678fd2
chore(release): lockfile and missing files for next.4
Tosd0 May 24, 2026
027a9cd
feat(amsg-instant): add waitUntil lifecycle support
Tosd0 May 25, 2026
ae3cf69
docs: finalize v2.1.0 and 0.8.0 docs
Tosd0 May 25, 2026
8fc7920
feat(amsg-instant): implement text segmentation tool with protected b…
Tosd0 May 26, 2026
0b923e9
fix(amsg): harden push transport edge cases
Tosd0 May 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 61 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,68 @@

| 包 | 版本 | 用途 |
|---|---|---|
| [`@rei-standard/amsg-instant`](./packages/rei-standard-amsg/instant/README.md) | `0.6.1` | 一次性即时推送(无 DB、无 cron、无租户) |
| [`@rei-standard/amsg-server`](./packages/rei-standard-amsg/server/README.md) | `2.3.2` | 定时 / 周期消息,多租户 Blob 配置 + token 鉴权 |
| [`@rei-standard/amsg-client`](./packages/rei-standard-amsg/client/README.md) | `2.2.3` | 浏览器 SDK:加密、请求封装、Push 订阅 |
| [`@rei-standard/amsg-sw`](./packages/rei-standard-amsg/sw/README.md) | `2.0.1` | Service Worker:推送展示、离线队列 |
| [`@rei-standard/amsg-shared`](./packages/rei-standard-amsg/shared/README.md) | `0.1.0` | 三轴推送契约(`AmsgPush` 判别联合 + builders + 类型守卫) |
| [`@rei-standard/amsg-instant`](./packages/rei-standard-amsg/instant/README.md) | `0.8.0` | 一次性即时推送(无 DB、无 cron、无租户) |
| [`@rei-standard/amsg-server`](./packages/rei-standard-amsg/server/README.md) | `2.4.0` | 定时 / 周期消息,多租户 Blob 配置 + token 鉴权 |
| [`@rei-standard/amsg-client`](./packages/rei-standard-amsg/client/README.md) | `2.3.0` | 浏览器 SDK:加密、请求封装、Push 订阅 |
| [`@rei-standard/amsg-sw`](./packages/rei-standard-amsg/sw/README.md) | `2.1.0` | Service Worker:推送展示、离线队列 |

`amsg-shared` 是依赖图最底层:其他四个包都依赖它,反过来不行;它本身零运行时依赖。

**怎么挑服务端包**:只发"按钮点了就立刻推一条" → `amsg-instant`;要定时或周期任务 → `amsg-server`;两种都要就都装,共用同一套 VAPID 与 masterKey。

### 协调发布说明:稳定版发布(shared 0.1.0 / instant 0.8.0 / sw 2.1.0 / client 2.3.0 / server 2.4.0)

本轮是一次跨包协调的 minor 升级,统一 push wire shape 到 `@rei-standard/amsg-shared` 的 `AmsgPush` 判别联合(以 `messageKind` 为字面量类型判别器)。所有 amsg 子包同时上调一个 minor 并正式发布。

- `@rei-standard/amsg-shared` 新增 → `0.1.0`
- `@rei-standard/amsg-instant`:`0.7.0` → `0.8.0`
- `@rei-standard/amsg-server`:`2.3.2` → `2.4.0`
- `@rei-standard/amsg-sw`:`2.0.1` → `2.1.0`
- `@rei-standard/amsg-client`:`2.2.3` → `2.3.0`

包间依赖一律使用**精确版本**(不带 `^`),所有 `dependencies` 字段都钉死在对应的版本,避免 npm 在生态系统里解析出混版本图。同时本轮移除了旧的 `{ type: 'error', code: '...' }` 错误信封——错误推送统一走 `ErrorPush`(`messageKind: 'error'`)。

**安装最新版(`latest` dist-tag)**:

```bash
npm install @rei-standard/amsg-shared @rei-standard/amsg-instant @rei-standard/amsg-server @rei-standard/amsg-sw @rei-standard/amsg-client
```

## 三轴推送语义(Three-axis push schema)

每一条推送都由三个**正交**的维度描述。把"用什么方式发出去"(dispatch)、"业务命名空间"(business)、"载荷里装的是什么"(content)拆开,让一个 axis 加值的时候不需要动另外两个 axis。

| 轴 | 字段 | 取值 | 由谁定 |
|---|---|---|---|
| Dispatch | `messageType` | `instant` / `fixed` / `prompted` / `auto` | 包(固定枚举) |
| Business | `messageSubtype` | 任意字符串 | 调用方(自由命名) |
| Content | `messageKind` | `content` / `reasoning` / `tool_request` / `error` | 包(固定枚举) |

外加一个 `source: 'instant' | 'scheduled'` —— 路由来源(`instant` 来自 `amsg-instant`,`scheduled` 来自 `amsg-server` 的任何输出)。

**`messageKind` 四种值**(载荷里到底是什么):

- `content` —— 最终面向用户的文本片段。携带 `message`、可选 `messageIndex` / `totalMessages`(N 段分句 burst 用)、`title`、`contactName`、`avatarUrl` 等。
- `reasoning` —— LLM 的思考过程(`choices[0].message.reasoning_content`)。携带 `reasoningContent`。**不带** `messageIndex` / `totalMessages`,因为推理是一轮 LLM 一条,不是分句 burst。
- `tool_request` —— Agentic loop 钩子返回的工具调用请求。携带 `toolCalls`(OpenAI `tool_calls` 透传形状),客户端执行后通过 `/continue` 恢复。
- `error` —— 生产端诊断错误(如 `HOOK_THREW` / `LOOP_EXCEEDED`)。携带 `code`、`message`、可选 `iteration`。**取代了 0.7.x 那个 `{ type: 'error', code: '...' }` 旧信封**。

**`messageType` 四种值**(怎么发出来的):

- `instant` —— 一次性即时推送(`amsg-instant` 一发即走,无 DB、无 cron)。总是配 `source: 'instant'`。
- `fixed` —— 固定文本的定时任务(`amsg-server`,无 LLM)。
- `prompted` —— LLM 生成 + 定时调度(`amsg-server` 的 prompted 路径)。
- `auto` —— LLM 生成 + 自动周期(`amsg-server` 的 auto 路径)。

后三种 `messageType` 总是配 `source: 'scheduled'`。

**`messageSubtype`** 是调用方自有命名空间,框架不解读、不强约束格式(producers 默认填 `'chat'`)。业务侧爱怎么切就怎么切。

**`sessionId` 不变性**:同一个 LLM 轮次内自动发出的 `ReasoningPush` 和后续 `ContentPush` burst 共享同一个 `sessionId`;agentic-loop 路径下,同一个 `/instant` 请求的所有 iteration 也共享一个 `sessionId`。客户端可以靠 `sessionId` 把"思考中"UI 和真正回复拼回到同一条消息上。

字段表、builders(`buildContentPush` / `buildReasoningPush` / `buildToolRequestPush` / `buildErrorPush`)、类型守卫(`isContentPush` / `isReasoningPush` / …)与常量(`MESSAGE_KIND` / `MESSAGE_TYPE` / `PUSH_SOURCE`)的完整说明见 [`packages/rei-standard-amsg/shared/README.md`](./packages/rei-standard-amsg/shared/README.md)。

## 🚀 接入

1. 服务端:按你选的包打开它的 README,里面有环境变量、`createReiServer` / `createInstantHandler` 用法、各平台 (Netlify / Vercel / Cloudflare / Node) 的适配器。
Expand All @@ -34,7 +89,8 @@ npm install @rei-standard/amsg-client @rei-standard/amsg-sw
```text
ReiStandard/
├── standards/ # 权威规范文本(端点、字段、错误码)
├── packages/rei-standard-amsg/ # 4 个发布到 npm 的 SDK 包
├── packages/rei-standard-amsg/ # 5 个发布到 npm 的 SDK 包
│ ├── shared/ # 三轴推送契约(最底层,其他包都依赖)
│ ├── server/ # 定时 / 周期消息(多租户 Blob + token)
│ ├── instant/ # 一次性即时推送(无 DB / 无 cron)
│ ├── client/ # 浏览器 SDK(加密、请求封装、Push 订阅)
Expand Down
18 changes: 18 additions & 0 deletions bump.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import fs from 'fs';
import path from 'path';

function updatePkg(pkgPath, version, sharedDep) {
const file = path.resolve(pkgPath);
const json = JSON.parse(fs.readFileSync(file, 'utf8'));
json.version = version;
if (json.dependencies && json.dependencies['@rei-standard/amsg-shared']) {
json.dependencies['@rei-standard/amsg-shared'] = sharedDep;
}
fs.writeFileSync(file, JSON.stringify(json, null, 2) + '\n');
}

updatePkg('packages/rei-standard-amsg/shared/package.json', '0.1.0', null);
updatePkg('packages/rei-standard-amsg/sw/package.json', '2.1.0', '0.1.0');
updatePkg('packages/rei-standard-amsg/instant/package.json', '0.8.0', '0.1.0');
updatePkg('packages/rei-standard-amsg/client/package.json', '2.3.0', '0.1.0');
updatePkg('packages/rei-standard-amsg/server/package.json', '2.4.0', '0.1.0');
Loading
Loading