asmgr 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +283 -147
- package/dist/asmgr.mjs +11637 -834
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|

|
|
6
6
|

|
|
7
7
|
|
|
8
|
-
**把编码 agent 的 CLI
|
|
8
|
+
**把编码 agent 的 CLI 会话与公开 ChatGPT 分享导出成 Markdown 或单文件 HTML。** `asmgr`(Agent Session ManaGeR)读取 GitHub Copilot CLI、Claude Code、OpenAI Codex CLI、DeepSeek Harness(DSH)写在本地的会话历史,也可捕获公开 ChatGPT `/share/` 页面,再把选定的会话导出成自包含报告;来源无法完整保留的内容会显式标记。它是**一个**无 scope 的公开 npm 包,命令也叫 `asmgr`;HTML 与 Markdown 是它的导出能力,而非独立发布的产品。
|
|
9
9
|
|
|
10
10
|
HTML 产物高度复刻 Copilot CLI 内置 `/share html` 的排版(Primer 主题、sticky header、类型筛选 pill、侧栏目录、上一条/下一条用户消息跳转、搜索),差异见 [ADR 0003](docs/adr/0003-archive-reconstruction-fidelity.md)。Markdown 产物遵循 Copilot CLI `/share file` 的结构与约定(`### 💬/👤/🔧/✅` 标题、`<sub>⏱️</sub>` 耗时戳、`<details>` 折叠、diff 围栏、`[!NOTE]` 头块)。
|
|
11
11
|
|
|
12
|
-
它对 agent 状态目录**只读**:不写 `.copilot`、`.claude`、`.codex
|
|
12
|
+
它对 agent 状态目录**只读**:不写 `.copilot`、`.claude`、`.codex`、`.dsh`。传本地 session id 或 `--file` 时,`list` / `search` / `show` / `html` / `md` 都严格本地。只有显式导入或直接读取 ChatGPT 分享 URL,以及按配置访问 restic 仓库的 `backup` 命令会联网。
|
|
13
13
|
|
|
14
|
-
> **归档 ≠ 恢复。** 导出的报告是有损、只读、给人看的产物,**不能**反推回可 `--resume` 的原生会话。把会话忠实恢复到"另一台机器能续聊"是一条**规划中**的独立能力(来源 = 备份快照 ∪ 另一台机器),与只读归档严格分层——理念见 [ADR 0001](docs/adr/0001-scope-archive-and-restore.md)
|
|
14
|
+
> **归档 ≠ 恢复。** 导出的报告是有损、只读、给人看的产物,**不能**反推回可 `--resume` 的原生会话。把会话忠实恢复到"另一台机器能续聊"是一条**规划中**的独立能力(来源 = 备份快照 ∪ 另一台机器),与只读归档严格分层——理念见 [ADR 0001](docs/adr/0001-scope-archive-and-restore.md)。
|
|
15
15
|
|
|
16
16
|
## 功能
|
|
17
17
|
|
|
@@ -22,32 +22,66 @@ HTML 产物高度复刻 Copilot CLI 内置 `/share html` 的排版(Primer 主
|
|
|
22
22
|
| 在单个会话内搜索 | `asmgr search "关键词" --session <session-id>` |
|
|
23
23
|
| 打印一个会话 | `asmgr show <session-id> --agent claude` |
|
|
24
24
|
| 只看对话主干(跳过工具调用) | `asmgr show <session-id> --format dialogue` |
|
|
25
|
+
| 导入公开 ChatGPT 分享 | `asmgr import 'https://chatgpt.com/share/<id>'` |
|
|
26
|
+
| 直接读取 ChatGPT 分享主干 | `asmgr show 'https://chatgpt.com/share/<id>' --format dialogue` |
|
|
25
27
|
| 导出 Markdown(Copilot `/share file` 风格) | `asmgr md <session-id> -o session.md` |
|
|
26
28
|
| 导出 HTML(高度复刻 `/share html`) | `asmgr html <session-id> -o session.html` |
|
|
29
|
+
| 直接把 ChatGPT 分享导出 HTML | `asmgr html 'https://chatgpt.com/share/<id>' -o session.html` |
|
|
27
30
|
| 读取任意位置的会话文件(scp 来的 / 恢复出来的) | `asmgr html --file /path/to/events.jsonl -o session.html` |
|
|
28
|
-
|
|
|
29
|
-
|
|
|
31
|
+
| 搜索任意位置的会话目录 | `asmgr search "关键词" --file /path/to/sessions` |
|
|
32
|
+
| 运行加密增量备份 | `asmgr backup run --dry-run` |
|
|
33
|
+
| 把备份快照恢复到隔离缓存 | `asmgr backup cache latest --target ~/.cache/asmgr/restic-cache` |
|
|
30
34
|
|
|
31
35
|
## 支持的 agent 与数据来源
|
|
32
36
|
|
|
33
37
|
- **Copilot CLI**:读取 `~/.copilot/session-state/*/events.jsonl`;同时用 `~/.copilot/session-store.db` 列出会话与元信息。events.jsonl 缺失(老会话被 prune、或只迁移了 DB)时回退到 DB 的 `turns` 表(lossy:只有 user/assistant 文本,工具与用户决策不可恢复)。所有读命令可用 `--copilot-db <path>` 覆盖 DB 路径。
|
|
34
38
|
- **Claude Code**:读取 `~/.claude/projects/**/*.jsonl`
|
|
35
39
|
- **Codex CLI**:读取 `~/.codex/sessions/**/*.jsonl`
|
|
40
|
+
- **DeepSeek Harness(DSH)**:读取 `${DSH_HOME:-~/.dsh}/sessions/<project>/<session>/session[.vN].jsonl[.zstd]`;用 `--dsh-root <path>` 覆盖会话根目录。目录发现选择每个会话的最高版本文件;`--file` 指向单个文件时读取指定版本。
|
|
41
|
+
- **ChatGPT 公共分享**:`asmgr import <url>` 从 `/share/<id>` 页面的 React Router 水合数据读取
|
|
42
|
+
`linear_conversation`。默认托管目录中的快照会自动进入 `list/search/show/html/md`;
|
|
43
|
+
也可把 URL 直接传给 `show/html/md`,不落盘使用。
|
|
36
44
|
|
|
37
|
-
每个读命令(`list` / `search` / `show` / `html` / `md`)都接受 `--file <path>`(别名 `--events <path>`),读一个显式的 `*.jsonl` 文件——或一个会被遍历出这些文件的目录——而不是 live agent 主目录。每个文件的 agent 格式自动探测(用 `--agent`
|
|
45
|
+
每个读命令(`list` / `search` / `show` / `html` / `md`)都接受 `--file <path>`(别名 `--events <path>`),读一个显式的 `*.jsonl` / DSH `*.jsonl.zstd` / `*.chatgpt-share.json` 文件——或一个会被遍历出这些文件的目录——而不是 live agent 主目录。每个文件的 agent 格式自动探测(用 `--agent` 覆盖)。未知 JSON 会明确报错,不再静默显示成空会话。
|
|
46
|
+
|
|
47
|
+
### DSH 读取与主干
|
|
48
|
+
|
|
49
|
+
**默认自动使用 DSH home,无需传 `--dsh-root`。** 会话目录优先级为:显式 `--dsh-root` → 环境变量 `DSH_HOME` 下的 `sessions/` → 当前用户的 `~/.dsh/sessions/`。`--dsh-root` 仅用于覆盖会话日志根目录,例如读取备份;它不是 DSH 源码目录,也不是项目工作目录。
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
asmgr list --agent dsh
|
|
53
|
+
asmgr show <session-id> --agent dsh --format dialogue
|
|
54
|
+
asmgr show --file /path/to/session.jsonl.zstd --format dialogue
|
|
55
|
+
asmgr html <session-id> --agent dsh -o dsh-session.html
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
以官方 [`dsh-v0.1.5-rc.1`](https://github.com/deepseek-ai/deepseek-harness/tree/dsh-v0.1.5-rc.1) 为基线,直接使用 `dsh-session-format-catalog` 的 v0→v3 解码/迁移及 `dsh-session/surface` 的原始追加消息筛选。迁移在内存中进行,不依赖本机 DSH 安装、不启动插件、不改写源日志。主干包含直接用户输入、助手正文,以及原生或 PTC 调用中 `ask_user_question` 的题目、全部选项与匹配的回答;普通工具的参数和结果完全不显示。回答按官方格式记录,不额外推断回答者身份。
|
|
59
|
+
|
|
60
|
+
范围保持有限:不解释未知插件事件、注入上下文、失败模型尝试或任意 `meta`;不把压缩 replacement 当成新对话,不重复拼接 fork 的父会话。只显示官方 compact checkpoint 对应的摘要。图片/文件只显示占位符并提示损失;完整工具仍在 text/HTML/Markdown 中保留。HTML/Markdown 暂无独立的主干导出开关。
|
|
61
|
+
|
|
62
|
+
压缩日志需要运行时提供 Zstandard API(Node.js ≥ 22.15);运行时缺少帧解码能力时明确报错,不把未读取内容当空会话。未知版本、官方迁移器拒绝的旧日志、损坏或未写完的文件会报出路径与原因,不尝试自定义补救,也不会自动回退到旧一代文件。已知官方边界包括 v0 中的 `subagent/descriptor.version: 2`:最新迁移器明确拒绝它;不能仅把该字段改成 3 来冒充兼容。
|
|
38
63
|
|
|
39
64
|
## <a id="install"></a>安装
|
|
40
65
|
|
|
41
|
-
|
|
66
|
+
`asmgr` 已发布为单一、无 scope 的公开 npm 包。以下是安装已发布版本的方法;维护者推送代码前请先看[版本与发布](#release),**普通推送 `main` 可能自动发版**。
|
|
42
67
|
|
|
43
|
-
### npm
|
|
68
|
+
### npm
|
|
44
69
|
|
|
45
70
|
```bash
|
|
46
71
|
npm i -g asmgr
|
|
47
72
|
asmgr list --agent all
|
|
48
73
|
```
|
|
49
74
|
|
|
50
|
-
|
|
75
|
+
各安装方式当前能力如下:
|
|
76
|
+
|
|
77
|
+
| 安装方式 | 读取、搜索、导入与导出 | `asmgr backup` |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| npm / `npm i -g github:` | ✅ | ❌ 暂未包含备份运行时 |
|
|
80
|
+
| 原生二进制 | ✅,但不读取 Copilot live SQLite | ❌ 暂未包含备份运行时 |
|
|
81
|
+
| 源码 checkout | ✅ | ✅ |
|
|
82
|
+
|
|
83
|
+
<details>
|
|
84
|
+
<summary>其他安装方式与运行时差异</summary>
|
|
51
85
|
|
|
52
86
|
### 原生二进制(无需 Node)
|
|
53
87
|
|
|
@@ -92,6 +126,8 @@ asmgr list --agent all
|
|
|
92
126
|
|
|
93
127
|
开发时直接跑源码:`pnpm dev list --agent all`(经 tsx)。自行编译原生二进制(需要 [Bun](https://bun.sh)):`pnpm run binaries`,四平台产物落在 `dist/asmgr-*`。
|
|
94
128
|
|
|
129
|
+
</details>
|
|
130
|
+
|
|
95
131
|
## 首次运行
|
|
96
132
|
|
|
97
133
|
1. 按上面任一方式装好 `asmgr`。
|
|
@@ -127,7 +163,7 @@ asmgr list --agent claude --claude-root /path/to/claude/projects
|
|
|
127
163
|
|
|
128
164
|
```bash
|
|
129
165
|
asmgr list --by project # 按仓库聚类会话
|
|
130
|
-
asmgr list --by agent # 按 copilot / claude / codex 分组
|
|
166
|
+
asmgr list --by agent # 按 copilot / claude / codex / chatgpt 分组
|
|
131
167
|
```
|
|
132
168
|
|
|
133
169
|
分组模式每组打印一个 `# <组> (<数量>)` 头(组间排序,组内按最后活动时间从新到旧),随后是 `组`、`agent`、`session-id`、`最后活动`、`条目数` 的 tab 分隔行。
|
|
@@ -145,6 +181,47 @@ asmgr search "database migration" --session <session-id> # 只在一个会话
|
|
|
145
181
|
|
|
146
182
|
`--session <id>` 把搜索限定到一个会话(先精确匹配 id,否则按前缀匹配)——用来在**当前这个会话**里按关键词找模型回复,不必先用 `--file` 指路径。
|
|
147
183
|
|
|
184
|
+
### `asmgr import`
|
|
185
|
+
|
|
186
|
+
导入公开 ChatGPT 分享页:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
asmgr import 'https://chatgpt.com/share/<conversation-id>'
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
默认写入 asmgr 托管目录,随后可直接用 session id 执行 `list/search/show/html/md`。
|
|
193
|
+
也可以把分享 URL 直接传给 `show/html/md`,跳过本地保存。
|
|
194
|
+
|
|
195
|
+
<details>
|
|
196
|
+
<summary>ChatGPT 存储路径、输出方式与保真限制</summary>
|
|
197
|
+
|
|
198
|
+
托管目录优先使用 `ASMGR_DATA_HOME`,其次使用 `XDG_DATA_HOME`;都未设置时按平台选择:
|
|
199
|
+
|
|
200
|
+
| 平台 | 默认目录 |
|
|
201
|
+
|---|---|
|
|
202
|
+
| Linux | `~/.local/share/asmgr/imports/chatgpt` |
|
|
203
|
+
| macOS | `~/Library/Application Support/asmgr/imports/chatgpt` |
|
|
204
|
+
| Windows | `%LOCALAPPDATA%\asmgr\imports\chatgpt` |
|
|
205
|
+
|
|
206
|
+
三种写入方式的后续读取不同:
|
|
207
|
+
|
|
208
|
+
| 导入方式 | 后续读取 |
|
|
209
|
+
|---|---|
|
|
210
|
+
| 默认目录 | 自动进入 `list/search/show/html/md` |
|
|
211
|
+
| `--chatgpt-root <dir>` | 后续读命令继续传相同的 `--chatgpt-root` |
|
|
212
|
+
| `-o <path>` | 用 `--file <path>` 显式读取;若改为扫描目录,文件名需以 `.chatgpt-share.json` 结尾 |
|
|
213
|
+
|
|
214
|
+
新快照权限为 `0600`;目标已存在时拒绝覆盖,确认要刷新才加 `--force`。普通 ChatGPT 页面、私有
|
|
215
|
+
`/c/...`、`/g/.../c/...` 地址栏会话及其它网站 URL 都不会发起抓取:检测到地址栏私有
|
|
216
|
+
会话链接时,会用中文明确提示先在 ChatGPT 中点击“分享”,再复制 `/share/` 链接。
|
|
217
|
+
|
|
218
|
+
捕获不启动浏览器:直接解码页面 HTML 内的 turbo-stream 水合数据。快照保留完整公开
|
|
219
|
+
`linear_conversation`,便于未来适配器改进后重新解析。公开页隐藏的工具结果无法恢复;
|
|
220
|
+
图片或附件若只有资源指针而没有内容,会显示占位符并把来源标记为 lossy。工具调用与结果
|
|
221
|
+
只有在同一用户轮次内存在唯一匹配时才合并,关联不明确时保留独立结果或 pending 状态。
|
|
222
|
+
|
|
223
|
+
</details>
|
|
224
|
+
|
|
148
225
|
### `asmgr show`
|
|
149
226
|
|
|
150
227
|
以 text、dialogue 或 JSON 打印一个会话:
|
|
@@ -153,20 +230,30 @@ asmgr search "database migration" --session <session-id> # 只在一个会话
|
|
|
153
230
|
asmgr show <session-id> --agent codex
|
|
154
231
|
asmgr show <session-id> --agent copilot --format dialogue
|
|
155
232
|
asmgr show <session-id> --agent codex --format json
|
|
233
|
+
asmgr show 'https://chatgpt.com/share/<id>' --format dialogue
|
|
156
234
|
```
|
|
157
235
|
|
|
158
|
-
`--format dialogue` 只保留**用户消息 /
|
|
236
|
+
`--format dialogue` 只保留**用户消息 / 交互式提问与选项 / 用户决策或回答 / 压缩摘要 / 助手回复**,跳过普通工具调用的全部内容与 reasoning。DSH 的 `ask_user_question` 保留题目、全部选项、单/多选信息、选中项和自由回答;Copilot 的 `ask_user` 保留题目、全部候选项及回答。工具噪音被剔掉后,每条用户 prompt 直接紧跟回答它的助手回复,prompt↔回复的对应关系一目了然——适合会话复盘、交接和收尾盘点等需要通读对话主干的场景。`--format text` 则含完整工具参数+结果、子代理/技能/计划/压缩统计。
|
|
159
237
|
|
|
160
238
|
### `asmgr html`
|
|
161
239
|
|
|
162
|
-
写出一份自包含 HTML
|
|
240
|
+
写出一份自包含 HTML 报告,支持搜索、筛选、侧栏目录、主题切换、Markdown 表格与 KaTeX 数学:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
asmgr html <session-id> --agent copilot -o report.html
|
|
244
|
+
asmgr html <session-id> -s agent-summary.html -o report.html # 顶部钉一份 HTML 总结
|
|
245
|
+
asmgr html 'https://chatgpt.com/share/<id>' -o report.html
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
<details>
|
|
249
|
+
<summary>HTML 与 Copilot CLI `/share html` 的差异</summary>
|
|
163
250
|
|
|
164
251
|
- **用 React 渲染,而非官方 vanilla bundle 资产。** 抽取的上游 CSS/JS 只当逆向参照,不随运行时产物发布。
|
|
165
252
|
- **Shiki 语法高亮**,覆盖 markdown 代码围栏与 diff 风格的工具输出,双 light+dark 主题,页面切主题时代码无需重载即重新着色。
|
|
166
253
|
- **24 小时制时间戳**(会话起点 `YYYY-MM-DD HH:MM:SS`;同日条目 `HH:MM:SS`,跨日 `MM-DD HH:MM:SS`)——en-US 默认的 12 小时制(`PM/AM`)太容易读错。
|
|
167
254
|
- **耗时 pill**,由 `startedAt` → 最后一条条目算出,显示在 header。
|
|
168
255
|
- **agent 总结卡片**,用 `--summary <file.html>` 钉在时间线顶部(原样渲染受信任 HTML;`data-index="summary"`,真实第 1 条仍是第 1 条)。
|
|
169
|
-
-
|
|
256
|
+
- **合并的工具卡片**,六种结果态(success / failure / rejected / denied / pending / redacted),配对应的边框色与状态图标。
|
|
170
257
|
- **`ask_user` 的回答被抽成一等「用户决策」条目**(`user/decision`):既保留原始工具卡片,又让用户的选择/回答在时间线里单独、显眼地出现——复盘或交接时不会把决策埋没在成百上千次工具调用里。
|
|
171
258
|
- **子代理 / 技能 / 计划条目**,从 `events.jsonl` 解析、各自成卡片 + 筛选 pill。子代理卡片在可得时显示记录到的身份、模型、描述、失败详情。这些超出 Copilot 自身 `/share html` 的筛选集。
|
|
172
259
|
- **数据源回退警告 pill**,当解析器不得不读 `events.jsonl` 之外的东西时显示在 header;回退到 `db.turns` 时进一步说明「交互式用户决策与工具条目在此模式下不可恢复」。
|
|
@@ -174,10 +261,7 @@ asmgr show <session-id> --agent codex --format json
|
|
|
174
261
|
- **单行 info 条目**(模型切换 / 取消)默认展开而非折叠——与官方 bundle 不同,让「Model changed from X to Y」「Operation cancelled by user」这类一行信息一眼可见;多行 info 仍折叠。
|
|
175
262
|
- **只存在于 live 内存的条目离线无法重建**,包括吉祥物启动横幅、临时重试提示、`/share` 成功回执。见 [ADR 0003](docs/adr/0003-archive-reconstruction-fidelity.md) 与下文[「Copilot 时间线与离线映射」](#timeline-ref)。
|
|
176
263
|
|
|
177
|
-
|
|
178
|
-
asmgr html <session-id> --agent copilot -o report.html
|
|
179
|
-
asmgr html <session-id> -s agent-summary.html -o report.html # 顶部钉一份 HTML 总结
|
|
180
|
-
```
|
|
264
|
+
</details>
|
|
181
265
|
|
|
182
266
|
### `asmgr md`
|
|
183
267
|
|
|
@@ -187,41 +271,93 @@ asmgr html <session-id> -s agent-summary.html -o report.html # 顶部钉一份
|
|
|
187
271
|
asmgr md <session-id> --agent copilot -o report.md
|
|
188
272
|
asmgr md <session-id> --no-reasoning -o report.md # 去掉 reasoning 条目
|
|
189
273
|
asmgr md <session-id> -s summary.md -o report.md # 注入一份 markdown 总结
|
|
274
|
+
asmgr md 'https://chatgpt.com/share/<id>' -o report.md
|
|
190
275
|
```
|
|
191
276
|
|
|
192
277
|
### `asmgr backup`
|
|
193
278
|
|
|
194
|
-
`backup`
|
|
279
|
+
`backup` 是正式的 restic 备份命令组:
|
|
195
280
|
|
|
196
281
|
```bash
|
|
197
|
-
asmgr backup run --dry-run
|
|
198
|
-
asmgr backup run
|
|
199
|
-
asmgr backup
|
|
200
|
-
asmgr backup cache latest --target ~/.cache/asmgr/restic-cache # 把一个快照恢复进缓存目录
|
|
282
|
+
asmgr backup run --dry-run
|
|
283
|
+
asmgr backup run
|
|
284
|
+
asmgr backup cache latest --target ~/.cache/asmgr/restic-cache
|
|
201
285
|
```
|
|
202
286
|
|
|
203
|
-
`backup
|
|
287
|
+
`backup run` 默认备份 `~/.copilot`、`~/.claude`、`~/.codex` 与 asmgr 托管的 ChatGPT
|
|
288
|
+
导入目录,只处理实际存在的路径。运行时会先尽力把 Copilot 的 SQLite WAL 合入主库,
|
|
289
|
+
再执行加密、去重、增量备份;SQLite 热文件、锁文件和 Copilot 进程日志不会进入快照。
|
|
290
|
+
每次快照带 `agent-session-manager` 与当前主机标签,并应用 daily / weekly / monthly
|
|
291
|
+
保留策略。
|
|
292
|
+
|
|
293
|
+
`backup cache` 把指定快照恢复到独立缓存,明确拒绝 home 目录及 live 的
|
|
294
|
+
`~/.copilot`、`~/.claude`、`~/.codex`,也拒绝 asmgr 托管的 ChatGPT 导入目录。
|
|
295
|
+
缓存用于 `list/search/show/html/md --file`,不等于把会话恢复成原 agent 可以
|
|
296
|
+
`--resume` 的状态。
|
|
297
|
+
|
|
298
|
+
> 当前备份命令需要从源码 checkout 运行;npm 包和原生二进制尚未包含备份运行时。
|
|
299
|
+
|
|
300
|
+
<details>
|
|
301
|
+
<summary>备份配置与 systemd 自动运行</summary>
|
|
204
302
|
|
|
205
|
-
|
|
303
|
+
#### 配置
|
|
304
|
+
|
|
305
|
+
复制配置模板并限制权限:
|
|
206
306
|
|
|
207
307
|
```bash
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
asmgr html <session-id> --file /tmp/cache -o s.html
|
|
308
|
+
cp secrets.env.example secrets.env
|
|
309
|
+
chmod 600 secrets.env
|
|
211
310
|
```
|
|
212
311
|
|
|
312
|
+
必填项是 `RESTIC_REPOSITORY` 与 `RESTIC_PASSWORD`;S3 兼容后端还需要
|
|
313
|
+
`AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY`。可用 `RESTIC_BIN` 覆盖 restic
|
|
314
|
+
位置、用 `BACKUP_AGENT_DIRS` 调整数据源、用 `BACKUP_EXCLUDE_REWIND=1` 排除
|
|
315
|
+
Copilot rewind 快照。通过 `--chatgpt-root` 或 `-o` 放到其它位置的 ChatGPT 快照不会
|
|
316
|
+
自动进入备份,需要显式加入 `BACKUP_AGENT_DIRS`。
|
|
317
|
+
|
|
318
|
+
新仓库先加载配置并初始化,再运行备份:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
set -a; source secrets.env; set +a
|
|
322
|
+
restic init
|
|
323
|
+
asmgr backup run --dry-run
|
|
324
|
+
asmgr backup run
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
`RESTIC_PASSWORD` 是读取所有快照的唯一密钥,初始化后必须保存到密码管理器或另一台设备。
|
|
328
|
+
|
|
329
|
+
#### 自动运行
|
|
330
|
+
|
|
331
|
+
`systemd/` 提供 user service 与 timer 示例,每天运行一次,并用随机延迟避免整点拥塞;
|
|
332
|
+
`Persistent=true` 会在机器重新启动后补跑错过的任务。复制示例后按源码 checkout 和日志
|
|
333
|
+
位置调整 service,再启用 timer:
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
mkdir -p ~/.config/systemd/user
|
|
337
|
+
cp systemd/agent-session-manager.service.example ~/.config/systemd/user/agent-session-manager.service
|
|
338
|
+
cp systemd/agent-session-manager.timer.example ~/.config/systemd/user/agent-session-manager.timer
|
|
339
|
+
systemctl --user daemon-reload
|
|
340
|
+
systemctl --user enable --now agent-session-manager.timer
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
同一个 restic 仓库只应由一台机器负责定时运行。需要在登出后继续执行时,为该用户启用
|
|
344
|
+
systemd lingering。
|
|
345
|
+
|
|
346
|
+
</details>
|
|
347
|
+
|
|
213
348
|
## 从 live 目录之外读取会话
|
|
214
349
|
|
|
215
|
-
`--file <path>`(别名 `--events <path>`)让 `list` / `search` / `show` / `html` / `md` 读一个显式路径,而不是
|
|
350
|
+
`--file <path>`(别名 `--events <path>`)让 `list` / `search` / `show` / `html` / `md` 读一个显式路径,而不是 live agent / import 主目录:
|
|
216
351
|
|
|
217
352
|
```bash
|
|
218
353
|
# 从别的机器拷来的单个会话文件(agent 自动探测)
|
|
219
354
|
asmgr show --file ~/dl/events.jsonl --format json
|
|
220
355
|
asmgr html --file ~/dl/events.jsonl -o report.html
|
|
356
|
+
asmgr show --file ~/dl/conversation.chatgpt-share.json --format dialogue
|
|
221
357
|
|
|
222
|
-
# 整个目录(遍历 *.jsonl;每个文件各自探测 agent)
|
|
223
|
-
asmgr list --file /tmp/
|
|
224
|
-
asmgr search "migration" --file /tmp/
|
|
358
|
+
# 整个目录(遍历 *.jsonl / *.chatgpt-share.json;每个文件各自探测 agent)
|
|
359
|
+
asmgr list --file /tmp/session-archive
|
|
360
|
+
asmgr search "migration" --file /tmp/session-archive
|
|
225
361
|
```
|
|
226
362
|
|
|
227
363
|
`--file` 指向单个文件时,`<session-id>` 参数可省。指向的目录若产出多个会话,传一个 `<session-id>` 挑一个(用 `asmgr list --file <dir>` 看 id)。
|
|
@@ -229,21 +365,23 @@ asmgr search "migration" --file /tmp/restored-cache
|
|
|
229
365
|
## 术语
|
|
230
366
|
|
|
231
367
|
- **会话(Session)**:agent CLI 持久化的一次对话,可由 UUID、JSONL 路径,或某 agent 本地数据库中的一行标识。
|
|
232
|
-
- **agent 适配器(Adapter)**:知道如何发现并解析某一家 agent 持久化格式的代码。当前适配 GitHub Copilot CLI、Claude Code、OpenAI Codex CLI
|
|
368
|
+
- **agent 适配器(Adapter)**:知道如何发现并解析某一家 agent 持久化格式的代码。当前适配 GitHub Copilot CLI、Claude Code、OpenAI Codex CLI 与 ChatGPT 公共分享快照。
|
|
233
369
|
- **事件(Event)**:agent 持久化流里的一条原始记录。Copilot 的事件存在 `events.jsonl`,是离线时间线重建的输入,而非 live `/share html` 直接渲染的对象。
|
|
234
370
|
- **时间线条目(Timeline entry)**:时间线里的一个展示单元(用户消息、助手回复、reasoning 块、工具调用等)。Copilot 把 live 条目放内存里;`asmgr` 从持久化事件重建规范化条目,供搜索与渲染共用。
|
|
235
371
|
- **归档(Archive / 只读检索)**:`asmgr` 只读地取回历史会话——搜索、文本显示、JSON 导出、给人看的 HTML/Markdown。归档**从不**把会话恢复回原 agent 的 live 状态。
|
|
236
372
|
- **恢复(Restore)**:忠实重建**可 `--resume` 的原生会话状态**(规划中)。**归档 ≠ 恢复**:报告不可反推回可续聊的原生态。
|
|
237
|
-
- **归档源(Archive source)**:可读取会话文件的地方——包括 live 本地 agent
|
|
373
|
+
- **归档源(Archive source)**:可读取会话文件的地方——包括 live 本地 agent 目录,以及通过 `--file` 显式指定的文件或目录。
|
|
238
374
|
|
|
239
375
|
## 设计文档(ADR)
|
|
240
376
|
|
|
241
377
|
重要决策的理念记录在 [`docs/adr/`](docs/adr/):
|
|
242
378
|
|
|
243
|
-
- [ADR 0001](docs/adr/0001-scope-archive-and-restore.md) ——
|
|
244
|
-
- [ADR 0002](docs/adr/0002-single-package-asmgr-distribution.md) —— 单一 `asmgr`
|
|
245
|
-
- [ADR 0003](docs/adr/0003-archive-reconstruction-fidelity.md) ——
|
|
246
|
-
|
|
379
|
+
- [ADR 0001](docs/adr/0001-scope-archive-and-restore.md) —— 产品范围与"归档 ≠ 恢复"。
|
|
380
|
+
- [ADR 0002](docs/adr/0002-single-package-asmgr-distribution.md) —— 单一 `asmgr` 包与统一命令入口。
|
|
381
|
+
- [ADR 0003](docs/adr/0003-archive-reconstruction-fidelity.md) —— 归档数据的规范化与保真度。
|
|
382
|
+
|
|
383
|
+
<details>
|
|
384
|
+
<summary>实现参考:Copilot 时间线、目录结构与漂移探针</summary>
|
|
247
385
|
|
|
248
386
|
## <a id="timeline-ref"></a>Copilot 时间线与离线映射(参考)
|
|
249
387
|
|
|
@@ -266,110 +404,6 @@ asmgr search "migration" --file /tmp/restored-cache
|
|
|
266
404
|
|
|
267
405
|
**置信度**:`getTimelineEntries()` 用法、空会话消息、12 类筛选、`reasoningText` 不对称、上列 live-only 条目——置信度高;compaction 时的文件截断机制置信度较低,需对新版本复验。Copilot 升级后重跑[漂移探针](#drift-oracle)并查 unknown 诊断。
|
|
268
406
|
|
|
269
|
-
## 备份配置
|
|
270
|
-
|
|
271
|
-
`asmgr backup`(`backup.sh` 的薄封装)用 [restic](https://restic.net) 对 agent 历史做加密、去重、增量备份。部署相关的值(restic 仓库 URL、凭据、到存储后端的确切网络路径)都放在 `secrets.env`(gitignore、`600`)——不进被跟踪的文件,让仓库里没有内网 IP / 主机名(见下文[「公开前的安全检查」](#safety))。
|
|
272
|
-
|
|
273
|
-
### 备份什么
|
|
274
|
-
|
|
275
|
-
`backup.sh` 读 `BACKUP_AGENT_DIRS`(默认 `~/.copilot:~/.claude:~/.codex`),备份其中存在的 agent 主目录。以 Copilot(`~/.copilot`)为例:
|
|
276
|
-
|
|
277
|
-
| 路径 | 典型大小 | 是什么 | 是否备份 |
|
|
278
|
-
|---|---|---|---|
|
|
279
|
-
| `session-state/<id>/events.jsonl` | 大(合计 GB 级) | 持久化的每会话事件流——resume 时回放、并被 `asmgr` 映射成离线条目 | ✅ 核心 |
|
|
280
|
-
| `session-state/<id>/{checkpoints,files,research}/` | 中小 | 每会话产物(检查点、附件、research 笔记) | ✅ |
|
|
281
|
-
| `session-store.db` | 数十 MB | 全会话的 SQLite 索引(摘要、turns、文件 / 引用索引、FTS) | ✅ —— 先 checkpoint WAL 保证副本自洽 |
|
|
282
|
-
| `session-store.db-wal` / `-shm` | 小 | SQLite WAL / 共享内存(热文件) | ❌ 排除(`exclude.txt`) |
|
|
283
|
-
| `*.lock`(如 `inuse.<pid>.lock`) | 极小 | 运行时锁文件 | ❌ 排除(`exclude.txt`) |
|
|
284
|
-
| `logs/` | 很大(GB 级) | CLI 进程日志 | ❌ 始终排除(`backup.sh` 里)——量大、恢复价值低 |
|
|
285
|
-
| `session-state/<id>/rewind-snapshots/` | 大(GB 级) | 支撑 `/rewind` 撤销功能的快照 | ⚠️ 可选——`BACKUP_EXCLUDE_REWIND=1` 时排除 |
|
|
286
|
-
| `config.json`、`settings.json`、`mcp-config.json`、`servers/` | 极小 | CLI + MCP 配置 | ✅ |
|
|
287
|
-
|
|
288
|
-
Claude Code(`~/.claude`)与 Codex(`~/.codex`)主目录存在时整体备份。
|
|
289
|
-
|
|
290
|
-
**`rewind-snapshots/` 为什么可选**:Copilot 的 `/rewind` 靠 `~/.copilot/session-state/<id>/rewind-snapshots/`(一个 `index.json` 加快照数据)撤销本会话的编辑。设 `BACKUP_EXCLUDE_REWIND=1` 把它们排除——省的空间比任何单项排除都多,且**不影响** `/share html`、`--resume`、`asmgr`(后两者从始终备份的 `events.jsonl` 重建);唯一失去的是对**恢复出来的**会话执行 `/rewind` 的能力。
|
|
291
|
-
|
|
292
|
-
### 端到端加密与架构
|
|
293
|
-
|
|
294
|
-
restic 跑在**客户端**,在数据离开主机前做**端到端 AES-256 加密**,再写入 **S3 兼容端点**(`RESTIC_REPOSITORY=s3:<endpoint>/<bucket>`;任何 restic 后端都行——rustfs / MinIO / SeaweedFS / AWS S3 / B2 / R2 / 本地路径 / sftp / rest)。后端只见密文,存储主机被攻破也不暴露你的历史。
|
|
295
|
-
|
|
296
|
-
反面:`RESTIC_PASSWORD` 是整个仓库**唯一**的钥匙——丢了它,所有快照永久不可读。`restic init` 后立刻把它抄进密码管理器 / 另一台设备。
|
|
297
|
-
|
|
298
|
-
到端点可能要过若干网络跳转(如 mesh 覆盖网 → 主机端口代理 → WSL2 端口转发 → 容器端口);这条跳转链是部署相关、含内网地址的,记在 `secrets.env` 头部注释里而**非**本文件——换机重新部署时只改 `secrets.env`,`backup.sh` / `exclude.txt` / 本文都是通用的。
|
|
299
|
-
|
|
300
|
-
### 配置与运行
|
|
301
|
-
|
|
302
|
-
复制模板、填入你自己的后端:
|
|
303
|
-
|
|
304
|
-
```bash
|
|
305
|
-
cp secrets.env.example secrets.env
|
|
306
|
-
chmod 600 secrets.env
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
必填变量:
|
|
310
|
-
|
|
311
|
-
| 变量 | 含义 |
|
|
312
|
-
|---|---|
|
|
313
|
-
| `RESTIC_REPOSITORY` | restic 仓库 URL,例如一个 S3 兼容桶 |
|
|
314
|
-
| `RESTIC_PASSWORD` | restic 仓库的加密口令 |
|
|
315
|
-
| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | S3 凭据,仅 S3 兼容后端需要 |
|
|
316
|
-
|
|
317
|
-
可选变量:
|
|
318
|
-
|
|
319
|
-
| 变量 | 默认值 |
|
|
320
|
-
|---|---|
|
|
321
|
-
| `RESTIC_BIN` | `$HOME/.local/bin/restic` |
|
|
322
|
-
| `BACKUP_AGENT_DIRS` | `$HOME/.copilot:$HOME/.claude:$HOME/.codex` |
|
|
323
|
-
| `BACKUP_EXCLUDE_REWIND` | 未设置;设为 `1` 跳过 Copilot rewind 快照 |
|
|
324
|
-
|
|
325
|
-
首次初始化一个新的 restic 仓库:
|
|
326
|
-
|
|
327
|
-
```bash
|
|
328
|
-
set -a; source secrets.env; set +a
|
|
329
|
-
restic init
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
然后运行:
|
|
333
|
-
|
|
334
|
-
```bash
|
|
335
|
-
asmgr backup run --dry-run
|
|
336
|
-
asmgr backup run
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
把 `RESTIC_PASSWORD` 存进密码管理器或另一台设备。丢了它,加密备份就再也读不出来。
|
|
340
|
-
|
|
341
|
-
### 保留策略
|
|
342
|
-
|
|
343
|
-
每次运行给快照打 `agent-session-manager` + `$(hostname)` 标签,然后:
|
|
344
|
-
|
|
345
|
-
```
|
|
346
|
-
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
> 迁移注记:快照标签历经 `session-recall` → `agent-session-exporter` → `agent-session-manager`。若把新 checkout 指向已有仓库,先对齐标签(如 `restic tag --set agent-session-manager --tag agent-session-exporter`,或加匹配的 `--keep-tag`),让 `forget` 按预期血缘 prune、而非遗弃旧快照。
|
|
350
|
-
|
|
351
|
-
## 用 systemd 自动备份
|
|
352
|
-
|
|
353
|
-
示例 unit 文件在 `systemd/`:
|
|
354
|
-
|
|
355
|
-
```bash
|
|
356
|
-
mkdir -p ~/.config/systemd/user
|
|
357
|
-
cp systemd/agent-session-manager.service.example ~/.config/systemd/user/agent-session-manager.service
|
|
358
|
-
cp systemd/agent-session-manager.timer.example ~/.config/systemd/user/agent-session-manager.timer
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
编辑 `agent-session-manager.service`,把路径指向你的 checkout,然后:
|
|
362
|
-
|
|
363
|
-
```bash
|
|
364
|
-
systemctl --user daemon-reload
|
|
365
|
-
systemctl --user enable --now agent-session-manager.timer
|
|
366
|
-
systemctl --user list-timers agent-session-manager.timer
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
若希望登出后 timer 仍运行,请用你的系统管理员账户开启 user lingering。
|
|
370
|
-
|
|
371
|
-
> 只应有**一台**机器拥有该 timer。若从旧部署迁来(unit 曾指向别的 checkout、或快照打的是旧标签如 `session-recall`),先禁用并删掉旧 unit(`systemctl --user disable --now <old>.timer` 再删文件),以免跑两份备份或把保留血缘劈成两半。
|
|
372
|
-
|
|
373
407
|
## 目录结构
|
|
374
408
|
|
|
375
409
|
`asmgr` 是**一个** npm 包;下面的 `src/*` 是它的内部模块(相对 import 串联),不是各自发布的包。
|
|
@@ -383,7 +417,6 @@ systemctl --user list-timers agent-session-manager.timer
|
|
|
383
417
|
| `scripts` | esbuild 单文件打包、bun 原生二进制、构建期资源内联(gen-assets) |
|
|
384
418
|
| `fixtures` | 脱敏的解析器与 CLI fixtures |
|
|
385
419
|
| [`tools/copilot`](tools/copilot/) | Copilot `/share` bundle 漂移探针(仅逆向研究,非运行时依赖) |
|
|
386
|
-
| `backup.sh` | `asmgr backup` 用的 restic 封装 |
|
|
387
420
|
|
|
388
421
|
### <a id="drift-oracle"></a>漂移探针(`tools/copilot`)
|
|
389
422
|
|
|
@@ -395,9 +428,15 @@ node tools/copilot/extract-share-assets.cjs [path/to/@github/copilot/app.js] [ou
|
|
|
395
428
|
|
|
396
429
|
**为什么保留**:它是**漂移探针**。Copilot 升级可能改动时间线条目 / 筛选类、Primer 明暗主题规则、按钮 id 等 DOM 钩子。升级后重跑并 diff 上一次输出,把有意义的变化当作"复核离线事件映射与 React 渲染器"的提示,而不是自动搬进产物。维护中的 HTML 渲染器是 `src/html` 的 React 实现,不 import 也不发布这些抽取资产;仓库里目前没有大小 / 哈希基线,可在下次比较时记录探针打印的长度与本地校验和。
|
|
397
430
|
|
|
431
|
+
</details>
|
|
432
|
+
|
|
433
|
+
<details>
|
|
434
|
+
<summary>同类项目调研与差异</summary>
|
|
435
|
+
|
|
398
436
|
## 同类项目对比
|
|
399
437
|
|
|
400
|
-
|
|
438
|
+
这个问题空间已有多种 CLI、TUI、Web 与桌面实现。下表是 2026-07-24 整理文档时的调研快照;
|
|
439
|
+
Stars 只反映当时状态,不作为持续更新的排名。
|
|
401
440
|
|
|
402
441
|
| 仓库 | Stars | 语言 | 形态 | 覆盖 agent | 备注 |
|
|
403
442
|
|---|---:|---|---|---|---|
|
|
@@ -428,6 +467,101 @@ node tools/copilot/extract-share-assets.cjs [path/to/@github/copilot/app.js] [ou
|
|
|
428
467
|
|
|
429
468
|
这些灵感项都作为 GitHub issue 跟踪(每条写明 `Inspired by …`),见 [issues](https://github.com/TMYTiMidlY/agent-session-manager/issues):项目层级索引页(`claude-code-log`)、Token / 成本分析视图(`token-dashboard`)、实时 tail 模式(`claude-code-trace` / `tail-claude`)、按项目分组侧栏(`agent-session-viewer` / `codex-history-viewer`)、VS Code 扩展封装(`codex-history-viewer`)、Pages 静态导出 tarball(`claude-code-transcripts`)。
|
|
430
469
|
|
|
470
|
+
</details>
|
|
471
|
+
|
|
472
|
+
## <a id="release"></a>维护者:版本与发布
|
|
473
|
+
|
|
474
|
+
> **推送 `main` 不等于“只同步代码”。** 当前使用 **semantic-release** 自动推导并发布版本,
|
|
475
|
+
> 不是维护者先运行 `cz bump` 再推 tag。发布前必须检查上次发布以来的**全部提交**,不能只看本次提交的类型。
|
|
476
|
+
|
|
477
|
+
操作规则以 [`release.yml`](.github/workflows/release.yml)(触发条件、测试与权限)和
|
|
478
|
+
[`.releaserc.json`](.releaserc.json)(提交分析、版本写回、构建与发布插件)为准。
|
|
479
|
+
|
|
480
|
+
### 什么操作会启动发布
|
|
481
|
+
|
|
482
|
+
| 操作 | 当前行为 |
|
|
483
|
+
|---|---|
|
|
484
|
+
| 向 `main` 推送,或合并 PR 使 `main` 更新 | 自动运行 `release` 工作流:安装依赖 → `pnpm test` → `semantic-release`;没有按文件路径过滤,纯文档推送也会启动 |
|
|
485
|
+
| 在 GitHub Actions 手动运行 `release`,选择 `main` | 运行同一条发布流水线;**不是预演**,也不强制一定产生新版本 |
|
|
486
|
+
| 只在本地 commit、推送非 `main` 分支、仅创建 PR,或单独推 tag | 不触发当前发布工作流;semantic-release 的发布分支也仅配置了 `main` |
|
|
487
|
+
|
|
488
|
+
**启动工作流 ≠ 一定发版。** 测试通过后,semantic-release 分析上个发布 tag 到本次运行提交之间的
|
|
489
|
+
提交记录;没有符合发布规则的提交时,不生成新版本。有可发布变更且验证、构建等步骤成功时,就会实际发布。
|
|
490
|
+
|
|
491
|
+
### 提交如何决定版本
|
|
492
|
+
|
|
493
|
+
当前未自定义 `releaseRules` 或解析器,使用默认 Angular 风格的提交解析(如 `fix(parser): ...`):
|
|
494
|
+
|
|
495
|
+
| 提交内容 | 版本变化(以上一版 `0.2.0` 为例) |
|
|
496
|
+
|---|---|
|
|
497
|
+
| `fix: ...`、`perf: ...` | patch → `0.2.1` |
|
|
498
|
+
| `feat: ...` | minor → `0.3.0` |
|
|
499
|
+
| 正文或页脚含 `BREAKING CHANGE: ...` | major → `1.0.0`,不会因仍处于 `0.x` 自动降为 minor |
|
|
500
|
+
| 被解析为 revert 的回退提交 | 默认 patch;在分析区间内成功匹配的原提交与回退会被成对过滤 |
|
|
501
|
+
| 普通 `docs:`、`chore:`、`ci:`、`test:`、`refactor:` 等,不含破坏性变更说明 | 自身不要求发布 |
|
|
502
|
+
|
|
503
|
+
同一分析区间按**最高级别**决定一个版本,而非每条提交各发一版。破坏性变更请使用明确的
|
|
504
|
+
`BREAKING CHANGE:` 正文或页脚,**不要只写 `feat!:` / `fix!:`**:当前默认解析器不凭标题中的 `!` 识别破坏性变更。
|
|
505
|
+
|
|
506
|
+
“本次只有 `docs:`”**不保证不发版**:如果此前有尚未发布的 `fix:` / `feat:`,本次运行仍会把它们纳入分析。
|
|
507
|
+
发布的是本次运行所检出的完整源码,不是只打包触发版本升级的那几条提交;CHANGELOG 则按提交规则生成摘要。
|
|
508
|
+
|
|
509
|
+
### 版本、标签和产物由谁生成
|
|
510
|
+
|
|
511
|
+
日常维护不要用 `cz bump`、`npm version`、手工改 `package.json` 版本或手工打发布 tag 来推动发版。
|
|
512
|
+
semantic-release 以 Git 发布历史为依据,在 CI 中自动完成:
|
|
513
|
+
|
|
514
|
+
1. 推导下个版本并生成 release notes,更新 `CHANGELOG.md` 与 `package.json` 的版本。
|
|
515
|
+
2. 构建 Node 单文件 bundle、Linux x64 / macOS Intel / macOS Apple Silicon / Windows x64 四平台二进制及 `SHA256SUMS.txt`。
|
|
516
|
+
3. 将 `package.json` 和 `CHANGELOG.md` 以 `chore(release): X.Y.Z [skip ci]` 提交回 `main`,并创建、推送 `vX.Y.Z` tag。
|
|
517
|
+
4. 发布公开 npm 包 [`asmgr`](https://www.npmjs.com/package/asmgr),创建 [GitHub Release](https://github.com/TMYTiMidlY/agent-session-manager/releases),附上 notes、二进制、Node bundle 和校验和。
|
|
518
|
+
|
|
519
|
+
npm 发布走 OIDC Trusted Publishing(`npmjs` environment),GitHub 操作使用工作流的 `GITHUB_TOKEN`。
|
|
520
|
+
它是直接发布,不是先生成等待人工确认的 npm 暂存版本。
|
|
521
|
+
|
|
522
|
+
### 只推代码:优先使用非 `main` 分支
|
|
523
|
+
|
|
524
|
+
不准备发布时,将提交保留在工作分支并只推该分支,例如:
|
|
525
|
+
|
|
526
|
+
```bash
|
|
527
|
+
# 从当前提交创建工作分支;分支名按需替换
|
|
528
|
+
git switch -c work/my-change
|
|
529
|
+
# 在该分支完成提交后,只推当前分支,不更新 main
|
|
530
|
+
git push -u origin HEAD
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
合并该分支到 `main` 仍可能发版,合并前需要重新确认发布范围。
|
|
534
|
+
|
|
535
|
+
如果确实要把代码推到 `main`,但只想跳过**这次 push** 的工作流,可在提交消息中加 `[skip ci]`
|
|
536
|
+
(例如 `fix: handle large sessions [skip ci]`)。注意:
|
|
537
|
+
|
|
538
|
+
- 它跳过匹配的 `push` / `pull_request` 工作流,**测试也会跳过**;不会取消已启动的运行,也不阻止手动 `workflow_dispatch`。
|
|
539
|
+
- 它不是 semantic-release 的“永不发布此提交”标记。该修复仍在上个 tag 之后,下一次未跳过的 `main` 推送或手动发布仍会分析并可能发布它。
|
|
540
|
+
- 因而它只适合临时跳过一次触发,不能作为长期发布闸门,也不能防止其他维护者后续推送带出该变更。
|
|
541
|
+
|
|
542
|
+
### 明确批准一次发布
|
|
543
|
+
|
|
544
|
+
1. 维护者先核对目标 `main` 提交 SHA、上个发布 tag 之后的全部变更与预期版本,确认这些内容都允许公开发布。
|
|
545
|
+
2. 明确批准后,再向 `main` 普通推送 / 合并以启动自动发布;若待发布提交已在 `main`(例如此前用了 `[skip ci]`),
|
|
546
|
+
可在 GitHub Actions → `release` → **Run workflow** 选择 `main`,或执行:
|
|
547
|
+
|
|
548
|
+
```bash
|
|
549
|
+
# 真正启动发布,不是 dry-run;只在明确批准后执行
|
|
550
|
+
gh workflow run release.yml --ref main
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
3. 检查运行结果,以及回写的版本 / CHANGELOG、`vX.Y.Z` tag、npm 版本和 GitHub Release 附件。手动运行没有绕过提交分析;无可发布变更时仍不会发新版本。
|
|
554
|
+
|
|
555
|
+
**“单独提交”只授权本地 commit,不包含 push 或发布;“只推代码”应使用非 `main` 分支。**
|
|
556
|
+
自动化助手执行可能发版的 `main` 推送 / 合并或手动运行前,必须说明发布影响并取得维护者明确同意。
|
|
557
|
+
|
|
558
|
+
当前工作流没有 `publish=true` 一类的二次确认输入;`environment: npmjs` 本身也**不代表已有人工审批**,
|
|
559
|
+
是否等待审批取决于仓库 Settings → Environments → `npmjs` 的保护规则。若需要每次都强制人工批准,
|
|
560
|
+
应在那里配置 required reviewers(以仓库支持情况为准),或另行修改工作流为仅手动发布;这些都需要单独配置,不能靠 `[skip ci]` 实现。
|
|
561
|
+
|
|
562
|
+
<details>
|
|
563
|
+
<summary>维护者:公开前安全检查</summary>
|
|
564
|
+
|
|
431
565
|
## <a id="safety"></a>公开前的安全检查
|
|
432
566
|
|
|
433
567
|
把本仓库推到任何公开位置前,只检查被跟踪的文件:
|
|
@@ -437,13 +571,15 @@ git ls-files
|
|
|
437
571
|
git grep -nE 'PRIVATE|SECRET|TOKEN|PASSWORD|AKIA|/(h[o]me|Users)/|10\\.|192\\.168\\.|172\\.|D[E]SKTOP|[Ww]orkstation'
|
|
438
572
|
```
|
|
439
573
|
|
|
440
|
-
`secrets.env`、`backup.log`、`node_modules
|
|
574
|
+
`secrets.env`、`backup.log`、`node_modules/` 与构建产物都被忽略,应保持未跟踪。
|
|
575
|
+
|
|
576
|
+
</details>
|
|
441
577
|
|
|
442
578
|
## <a id="roadmap"></a>路线图
|
|
443
579
|
|
|
444
580
|
待办与灵感项都在 [GitHub issues](https://github.com/TMYTiMidlY/agent-session-manager/issues) 跟踪。两条值得单独点名的方向:
|
|
445
581
|
|
|
446
|
-
- **忠实恢复 / 迁移**:把会话恢复到"另一台机器能 `--resume`"的原生状态(来源 = 备份快照 ∪
|
|
447
|
-
- **本地 Web 界面 `asmgr web
|
|
582
|
+
- **忠实恢复 / 迁移**:把会话恢复到"另一台机器能 `--resume`"的原生状态(来源 = 备份快照 ∪ 另一台机器)——边界见 [ADR 0001](docs/adr/0001-scope-archive-and-restore.md)。
|
|
583
|
+
- **本地 Web 界面 `asmgr web`**:本机启动、仅供自己查看的会话浏览界面。
|
|
448
584
|
|
|
449
|
-
单文件分发与 npm 发布**已实现**(单一无 scope 包 `asmgr`、四平台原生二进制、semantic-release、`npm i -g github:` 免 registry
|
|
585
|
+
单文件分发与 npm 发布**已实现**(单一无 scope 包 `asmgr`、四平台原生二进制、semantic-release、`npm i -g github:` 免 registry 安装)——使用方式见[安装](#install),发布规则见[维护者:版本与发布](#release)。其余(持久化索引外部会话目录、提升适配器保真度、项目层级索引页、Token / 成本视图、实时 tail、VS Code 扩展、Pages 导出 tarball、跨多会话仪表盘)见 issues。
|