@morlay/session-branch 0.1.1 → 0.1.2
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 +18 -41
- package/dist/index.d.mts +1 -12
- package/dist/index.mjs +1 -4
- package/locale/en.json +1 -1
- package/package.json +2 -2
- package/src/balance.ts +2 -3
- package/src/types.ts +2 -20
package/README.md
CHANGED
|
@@ -1,50 +1,27 @@
|
|
|
1
1
|
# @morlay/session-branch
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
分支式会话编辑的**契约层**:数据层分支原语 `SessionBranchProvider`(`readBranchPrefix` / `forkFrom` /
|
|
4
|
+
`rewind`)与高层服务 `SessionBranch`(`ctx.sessionBranch`),接口形状见
|
|
5
|
+
[`src/provider.ts`](./src/provider.ts)。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## 用法
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
[`@morlay/better-session`](../../bundles/better-session/README.md),`session-branch` 行由它的 patch 插入。
|
|
13
|
-
|
|
14
|
-
## 与上游 `SessionHandle` 的关系
|
|
15
|
-
|
|
16
|
-
上游持久化模型是 `SessionHandle`(append-only:`create` / `open` / `append` /
|
|
17
|
-
`flush` / `stat` / `list`),没有显式回退原语;本包在其旁边定义**分支面**
|
|
18
|
-
provider,负责显式回退与闭合边界派生:
|
|
19
|
-
|
|
20
|
-
| 面 | 上游 `SessionHandle` | 本包 `SessionBranchProvider` |
|
|
21
|
-
| ------ | -------------------------------------- | ------------------------------------------------------ |
|
|
22
|
-
| 覆盖 | 持久读写(append-only) | 显式回退 + 闭合边界派生(分支面) |
|
|
23
|
-
| 原语 | `create` / `open` / `append` / `flush` | `readBranchPrefix` / `forkFrom` / `rewind` |
|
|
24
|
-
| 实现方 | JSONL / RDB 等 | RDB 等(`@morlay/session-rdb` 同时实现两者,形成闭环) |
|
|
25
|
-
|
|
26
|
-
## Provider 抽象
|
|
9
|
+
装配入口是聚合层 [`@morlay/better-session`](../../bundles/better-session/README.md)——本包没有自己的 bundle
|
|
10
|
+
patch,`session-branch` 行由它的 patch 插入;实现方是 [`@morlay/session-rdb`](../session-rdb/README.md)
|
|
11
|
+
(同一个后端也实现上游 `SessionHandle`)。
|
|
27
12
|
|
|
28
13
|
```ts
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
readBranchPrefix(id, atSeq?, mode?, signal?): Promise<BranchBoundary>;
|
|
32
|
-
forkFrom(sourceId, options?, signal?): Promise<SessionId>;
|
|
33
|
-
rewind(id, toBoundary, signal?): Promise<SessionPersistenceSnapshot>;
|
|
34
|
-
}
|
|
14
|
+
const boundary = await ctx.sessionBranch.readBranchPrefix(sessionId, userEventSeq, "before");
|
|
15
|
+
await ctx.sessionBranch.rewind(sessionId, boundary.seq);
|
|
35
16
|
```
|
|
36
17
|
|
|
37
|
-
- `readBranchPrefix`:定位 `atSeq` 锚定的闭合 `turn/end`
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
`@morlay/session-rdb` 的 [分支能力](../session-rdb/.agents/designs/20260917-分支能力.md))。
|
|
45
|
-
|
|
46
|
-
## 版本效果(历史形状)
|
|
18
|
+
- `readBranchPrefix(id, atSeq?, mode?)`:定位 `atSeq` 锚定的闭合 `turn/end` 边界并返回前缀;`mode: "after"`
|
|
19
|
+
含目标轮(fork 语义)/ `"before"` 排除目标轮(编辑 / 重掷 / 重试语义)。
|
|
20
|
+
- `forkFrom(sourceId, options?)`:纯 append 派生新会话(`parentSession` / `seedLength`,seed = 边界前缀 +
|
|
21
|
+
`seedSuffix`),不触碰源会话。
|
|
22
|
+
- `rewind(id, toBoundary)`:唯一的显式回退原语,事务整体提交或回滚;支持 live 会话(内存 log 截断 +
|
|
23
|
+
派生缓存复位 + handle cursor / 继承前缀对齐,机制见 session-rdb 的
|
|
24
|
+
[设计 20260917-分支能力](../session-rdb/.agents/designs/20260917-分支能力.md))。
|
|
47
25
|
|
|
48
|
-
`session-branch/version`
|
|
49
|
-
|
|
50
|
-
[ADR-删除版本树投影并停止写版本效果](./.agents/adrs/20260920-删除版本树投影并停止写版本效果.md)。
|
|
26
|
+
`session-branch/version` 事件的类型仍在 `src/types.ts`:它只用于识别旧会话里已落库的该事件,本仓库当前
|
|
27
|
+
没有生产方与消费者([ADR-删除版本树投影并停止写版本效果](./.agents/adrs/20260920-删除版本树投影并停止写版本效果.md))。
|
package/dist/index.d.mts
CHANGED
|
@@ -54,17 +54,6 @@ declare class SessionBranchError extends Error {
|
|
|
54
54
|
readonly code: SessionBranchErrorCode;
|
|
55
55
|
constructor(message: string, code: SessionBranchErrorCode);
|
|
56
56
|
}
|
|
57
|
-
interface SessionBranchVersionEventEnvelope {
|
|
58
|
-
type: "session-branch/version";
|
|
59
|
-
seq: number;
|
|
60
|
-
time: number;
|
|
61
|
-
ignorable?: true;
|
|
62
|
-
data: SessionBranchVersionEvent;
|
|
63
|
-
}
|
|
64
|
-
declare function isSessionBranchVersionEvent(event: SessionEvent | {
|
|
65
|
-
type: string;
|
|
66
|
-
data: unknown;
|
|
67
|
-
}): event is SessionBranchVersionEventEnvelope;
|
|
68
57
|
//#endregion
|
|
69
58
|
//#region src/provider.d.ts
|
|
70
59
|
type BranchAnchorMode = "after" | "before";
|
|
@@ -98,4 +87,4 @@ declare module "@deepseek-ai/cordis" {
|
|
|
98
87
|
}
|
|
99
88
|
declare function apply(_ctx: Context): void;
|
|
100
89
|
//#endregion
|
|
101
|
-
export { type BranchAnchorMode, BranchBoundary, BranchForkMeta, CascadePolicy, EditableBlockKind, ForkFromOptions, SESSION_BRANCH_VERSION_SCHEMA, SessionBranch, SessionBranchEffect, SessionBranchError, SessionBranchErrorCode, SessionBranchInverse, type SessionBranchProvider, SessionBranchVersionEvent,
|
|
90
|
+
export { type BranchAnchorMode, BranchBoundary, BranchForkMeta, CascadePolicy, EditableBlockKind, ForkFromOptions, SESSION_BRANCH_VERSION_SCHEMA, SessionBranch, SessionBranchEffect, SessionBranchError, SessionBranchErrorCode, SessionBranchInverse, type SessionBranchProvider, SessionBranchVersionEvent, VersionOperation, apply, balanceRewindPrefix, rewindKeepLength };
|
package/dist/index.mjs
CHANGED
|
@@ -65,11 +65,8 @@ var SessionBranchError = class extends Error {
|
|
|
65
65
|
this.code = code;
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
|
-
function isSessionBranchVersionEvent(event) {
|
|
69
|
-
return event.type === "session-branch/version" && event.data.schemaVersion === 1;
|
|
70
|
-
}
|
|
71
68
|
//#endregion
|
|
72
69
|
//#region src/index.ts
|
|
73
70
|
function apply(_ctx) {}
|
|
74
71
|
//#endregion
|
|
75
|
-
export { SESSION_BRANCH_VERSION_SCHEMA, SessionBranch, SessionBranchError, apply, balanceRewindPrefix,
|
|
72
|
+
export { SESSION_BRANCH_VERSION_SCHEMA, SessionBranch, SessionBranchError, apply, balanceRewindPrefix, rewindKeepLength };
|
package/locale/en.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"title": "Session Branch",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Contract layer for branch-based session editing: the data-layer provider abstraction and the high-level service for rewind / retry / fork over event-sourced sessions."
|
|
5
5
|
}
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morlay/session-branch",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Contract layer for branch-based session editing: the provider abstraction (rewind / forkFrom / readBranchPrefix) plus the high-level service over DeepSeek Harness event-sourced sessions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
7
7
|
"dsh-plugin",
|
package/src/balance.ts
CHANGED
|
@@ -41,9 +41,8 @@ export function balanceRewindPrefix(
|
|
|
41
41
|
return events.slice(0, keep);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
// rewind 只按 seq 读尾部窗口(`types`
|
|
45
|
-
//
|
|
46
|
-
// step/start 一并丢弃,避免它之后的追加(重放的新 step)撞上未闭合的旧 step。
|
|
44
|
+
// rewind 只按 seq 读尾部窗口(`types` 是窗口内升序的事件类型),在窗口上做同样的配对修剪:从尾部往回扫,
|
|
45
|
+
// 遇到 turn/end 即停;尾部未闭合的 step/start 一并丢弃,避免它之后的追加撞上未闭合的旧 step。
|
|
47
46
|
// 调用方必须保证窗口覆盖到「最近一个 turn/end」或前缀开头,否则结果不完整。
|
|
48
47
|
export function rewindKeepLength(types: readonly string[], rawKeepLength: number): number {
|
|
49
48
|
let relativeKeep = types.length;
|
package/src/types.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { SessionEvent, SessionId } from "@deepseek-ai/dsh-session";
|
|
2
2
|
|
|
3
|
-
// `session-branch/version`
|
|
4
|
-
// (见 ADR
|
|
5
|
-
// ignorable 事件,不再有新事件产生、也没有读者。
|
|
3
|
+
// `session-branch/version` 的形状定义:只用于识别既有日志里已落库的该事件,本仓库不产出它、读侧也不参与投影
|
|
4
|
+
// (见 ADR-删除版本树投影并停止写版本效果)。
|
|
6
5
|
export const SESSION_BRANCH_VERSION_SCHEMA = 1;
|
|
7
6
|
|
|
8
7
|
export type CascadePolicy = "truncate" | "preserve";
|
|
@@ -85,20 +84,3 @@ export class SessionBranchError extends Error {
|
|
|
85
84
|
this.code = code;
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
|
-
|
|
89
|
-
export interface SessionBranchVersionEventEnvelope {
|
|
90
|
-
type: "session-branch/version";
|
|
91
|
-
seq: number;
|
|
92
|
-
time: number;
|
|
93
|
-
ignorable?: true;
|
|
94
|
-
data: SessionBranchVersionEvent;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function isSessionBranchVersionEvent(
|
|
98
|
-
event: SessionEvent | { type: string; data: unknown },
|
|
99
|
-
): event is SessionBranchVersionEventEnvelope {
|
|
100
|
-
return (
|
|
101
|
-
event.type === "session-branch/version" &&
|
|
102
|
-
(event.data as { schemaVersion?: unknown }).schemaVersion === SESSION_BRANCH_VERSION_SCHEMA
|
|
103
|
-
);
|
|
104
|
-
}
|