@morlay/session-branch 0.0.2 → 0.0.3

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/dist/index.d.mts CHANGED
@@ -117,5 +117,4 @@ declare module "@deepseek-ai/cordis" {
117
117
  }
118
118
  declare function apply(_ctx: Context): void;
119
119
  //#endregion
120
- export { type BranchAnchorMode, BranchBoundary, BranchForkMeta, BranchTimeline, BranchVersionNode, CascadePolicy, EditableBlockKind, ForkFromOptions, type OwnEventsReader, SESSION_BRANCH_VERSION_SCHEMA, SessionBranch, SessionBranchEffect, SessionBranchError, SessionBranchErrorCode, SessionBranchInverse, type SessionBranchProvider, SessionBranchVersionEvent, SessionBranchVersionEventEnvelope, VersionOperation, _branchKeyVisible, apply, balanceRewindPrefix, buildTimeline, isSessionBranchVersionEvent };
121
- //# sourceMappingURL=index.d.mts.map
120
+ export { type BranchAnchorMode, BranchBoundary, BranchForkMeta, BranchTimeline, BranchVersionNode, CascadePolicy, EditableBlockKind, ForkFromOptions, type OwnEventsReader, SESSION_BRANCH_VERSION_SCHEMA, SessionBranch, SessionBranchEffect, SessionBranchError, SessionBranchErrorCode, SessionBranchInverse, type SessionBranchProvider, SessionBranchVersionEvent, SessionBranchVersionEventEnvelope, VersionOperation, _branchKeyVisible, apply, balanceRewindPrefix, buildTimeline, isSessionBranchVersionEvent };
package/dist/index.mjs CHANGED
@@ -106,5 +106,3 @@ function balanceRewindPrefix(events) {
106
106
  function apply(_ctx) {}
107
107
  //#endregion
108
108
  export { SESSION_BRANCH_VERSION_SCHEMA, SessionBranch, SessionBranchError, _branchKeyVisible, apply, balanceRewindPrefix, buildTimeline, isSessionBranchVersionEvent };
109
-
110
- //# sourceMappingURL=index.mjs.map
@@ -4,5 +4,4 @@ declare const name = "session-branch-invariant";
4
4
  declare const inject: string[];
5
5
  declare const apply: (ctx: Context) => Promise<() => void>;
6
6
  //#endregion
7
- export { apply, inject, name };
8
- //# sourceMappingURL=invariant.d.mts.map
7
+ export { apply, inject, name };
@@ -6,5 +6,3 @@ const install = () => {};
6
6
  const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
7
7
  //#endregion
8
8
  export { apply, inject, name };
9
-
10
- //# sourceMappingURL=invariant.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morlay/session-branch",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Provider abstraction + high-level service for rewind / retry / fork over DeepSeek Harness event-sourced sessions.",
5
5
  "keywords": [
6
6
  "dsh",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/provider.ts","../src/branch.ts","../src/timeline.ts","../src/balance.ts","../src/index.ts"],"mappings":";;;;KAMK,yDAAyD;cACjD,mBAAmB;cAEnB;KAED;KAEA;KAEA;UAEK;EACf;EACA,WAAW;EACX,SAAS;EAET;EAEA;EACA;EACA,YAAY;EAEZ;EAEA;;UAGe;EACf;EACA,WAAW;;UAGI;EACf,sBAAsB;EACtB,QAAQ;EACR,SAAS;;;YAIC;IACR,0BAA0B;;;UAIb;EACf;EAEA,iBAAiB;;UAGF;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EAEA,aAHe;EAKf,sBAAsB;EAEtB,iBAAiB;EAEjB,OAAO;;UAGQ;EACf,WAAW;EACX,kBAAkB;EAElB;EACA;EAEA,SAAS;EAET,mBAAmB;;UAGJ;EACf,MAAM;EACN,OAAO;;KAGG;cAOC,2BAA2B;WAC7B,MAAM;EACf,YAAY,iBAAiB,MAAM;;UAOpB;EACf;EACA;EACA;EACA;EACA,MAAM;;iBAGQ,4BACd,OAAO;EAAiB;EAAc;IACrC,SAAS;;;KCnHA;UAEK;WACN;EAET,iBACE,IAAI,WACJ,gBACA,OAAO,kBACP,SAAS,cACR,QAAQ;EAEX,SACE,UAAU,WACV,UAAU,iBACV,SAAS,cACR,QAAQ;EAEX,OACE,IAAI,WACJ,oBACA,SAAS,cACR,QAAQ;;;;uBCrBS,sBAAsB;EAC1C,YAAY,mCAAmC;WAItC,iBACP,IAAI,WACJ,gBACA,OAFI,kBAGJ,SAAS,cACR,QAAQ;WAEF,SACP,UAAU,WACV,UAAU,iBACV,SAAS,cACR,QAAQ;WAEF,OACP,IAAI,WACJ,oBACA,SAAS,cACR,QAAQ;WAEF,SAAS,WAAW,WAAW,SAAS,cAAc,QAAQ;EAEvE,eAAe,YAAY;;;;KCrBjB,iBAAiB;EAC3B;;KAGU,mBACV,IAAI,WACJ,iBACA,SAAS,gBACN,oDAAoD;iBAEnC,cACpB,oBAAoB,kBACpB,eAAe,iBACf,WAAW,WACX,SAAS,cACR,QAAQ;;;iBCvBK,oBAAoB,iBAAiB,iBAAiB;;;;YCS1D;IACR,eAAe;;;iBAIH,MAAM,MAAM"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/branch.ts","../src/types.ts","../src/timeline.ts","../src/balance.ts","../src/index.ts"],"sourcesContent":["import { Service } from \"@deepseek-ai/cordis\";\nimport type { SessionId } from \"@deepseek-ai/dsh-session\";\nimport type { SessionPersistenceSnapshot } from \"@deepseek-ai/dsh-session-persistence\";\nimport type { BranchBoundary, BranchTimeline, ForkFromOptions } from \"./types.ts\";\n\nexport abstract class SessionBranch extends Service {\n constructor(ctx: import(\"@deepseek-ai/cordis\").Context) {\n super(ctx, \"sessionBranch\");\n }\n\n abstract readBranchPrefix(\n id: SessionId,\n atSeq?: number,\n mode?: import(\"./provider.ts\").BranchAnchorMode,\n signal?: AbortSignal,\n ): Promise<BranchBoundary>;\n\n abstract forkFrom(\n sourceId: SessionId,\n options?: ForkFromOptions,\n signal?: AbortSignal,\n ): Promise<SessionId>;\n\n abstract rewind(\n id: SessionId,\n toBoundary: number,\n signal?: AbortSignal,\n ): Promise<SessionPersistenceSnapshot>;\n\n abstract timeline(sessionId: SessionId, signal?: AbortSignal): Promise<BranchTimeline>;\n\n syncLiveCursor(_sessionId: SessionId): void {\n // 默认无操作。\n }\n}\n","import type { SessionEvent, SessionId } from \"@deepseek-ai/dsh-session\";\nimport type { SessionEventMap } from \"@deepseek-ai/dsh-session\";\n\n// 编译期诊断:module augmentation 后 `keyof SessionEventMap` 可见,但\n// dsh-session 内已解析的 `SessionEventType` 别名不会重求值——因此\n// `SessionEvent<\"session-branch/version\">` 泛型不可用,守卫/消费走结构化。\ntype _BranchKeyCheck = \"session-branch/version\" extends keyof SessionEventMap ? true : false;\nexport const _branchKeyVisible: _BranchKeyCheck = true as const;\n\nexport const SESSION_BRANCH_VERSION_SCHEMA = 1;\n\nexport type CascadePolicy = \"truncate\" | \"preserve\";\n\nexport type VersionOperation = \"edit\" | \"reroll\" | \"retry\" | \"fork\" | \"rewind\";\n\nexport type EditableBlockKind = \"user\" | \"assistant.reasoning\" | \"assistant.response\";\n\nexport interface SessionBranchEffect {\n id: string;\n operation: VersionOperation;\n cascade: CascadePolicy;\n\n targetTurn: number;\n\n targetEventSeq: number;\n targetBlockIndex?: number;\n blockKind?: EditableBlockKind;\n\n before?: string;\n\n after?: string;\n}\n\nexport interface SessionBranchInverse {\n kind: \"restore-version\";\n sessionId: SessionId;\n}\n\nexport interface SessionBranchVersionEvent {\n schemaVersion: typeof SESSION_BRANCH_VERSION_SCHEMA;\n effect: SessionBranchEffect;\n inverse: SessionBranchInverse;\n}\n\ndeclare module \"@deepseek-ai/dsh-session\" {\n interface SessionEventMap {\n \"session-branch/version\": SessionBranchVersionEvent;\n }\n}\n\nexport interface BranchBoundary {\n seq: number;\n\n events: readonly SessionEvent[];\n}\n\nexport interface BranchForkMeta {\n cwd?: string;\n createdAt?: number;\n agentPreset?: string;\n origin?: \"subagent\";\n delegationDepth?: number;\n}\n\nexport interface ForkFromOptions {\n atSeq?: number;\n\n anchorMode?: import(\"./provider.ts\").BranchAnchorMode;\n\n seedSuffix?: readonly SessionEvent[];\n\n childSessionId?: SessionId;\n\n meta?: BranchForkMeta;\n}\n\nexport interface BranchVersionNode {\n sessionId: SessionId;\n parentSessionId?: SessionId;\n\n seedLength: number;\n createdAt: number;\n\n effect?: SessionBranchEffect;\n\n inverseSessionId?: SessionId;\n}\n\nexport interface BranchTimeline {\n root: BranchVersionNode;\n nodes: BranchVersionNode[];\n}\n\nexport type SessionBranchErrorCode =\n | \"SESSION_NOT_FOUND\"\n | \"INVALID_BOUNDARY\"\n | \"OPEN_TURN\"\n | \"FORK_UNAVAILABLE\"\n | \"REWIND_CONFLICT\";\n\nexport class SessionBranchError extends Error {\n readonly code: SessionBranchErrorCode;\n constructor(message: string, code: SessionBranchErrorCode) {\n super(message);\n this.name = \"SessionBranchError\";\n this.code = code;\n }\n}\n\nexport interface SessionBranchVersionEventEnvelope {\n type: \"session-branch/version\";\n seq: number;\n time: number;\n ignorable?: true;\n data: SessionBranchVersionEvent;\n}\n\nexport function isSessionBranchVersionEvent(\n event: SessionEvent | { type: string; data: unknown },\n): event is SessionBranchVersionEventEnvelope {\n return (\n event.type === \"session-branch/version\" &&\n (event.data as { schemaVersion?: unknown }).schemaVersion === SESSION_BRANCH_VERSION_SCHEMA\n );\n}\n","import type { SessionId } from \"@deepseek-ai/dsh-session\";\nimport type { SessionPersistenceSnapshot } from \"@deepseek-ai/dsh-session-persistence\";\nimport {\n SessionBranchError,\n isSessionBranchVersionEvent,\n type BranchTimeline,\n type BranchVersionNode,\n type SessionBranchVersionEventEnvelope,\n} from \"./types.ts\";\n\nexport type BranchSnapshot = SessionPersistenceSnapshot & {\n inheritedEventCount: number;\n};\n\nexport type OwnEventsReader = (\n id: SessionId,\n fromSeq: number,\n signal?: AbortSignal,\n) => Promise<readonly import(\"@deepseek-ai/dsh-session\").SessionEvent[]>;\n\nexport async function buildTimeline(\n snapshots: readonly BranchSnapshot[],\n readOwnEvents: OwnEventsReader,\n sessionId: SessionId,\n signal?: AbortSignal,\n): Promise<BranchTimeline> {\n const byId = new Map(snapshots.map((snapshot) => [snapshot.header.id, snapshot] as const));\n\n // 回溯到根(当前会话 → 祖先链)。\n const ancestors: SessionId[] = [];\n let cursor: SessionId | undefined = sessionId;\n const seen = new Set<SessionId>();\n while (cursor !== undefined) {\n if (seen.has(cursor))\n throw new SessionBranchError(\"lineage contains a cycle\", \"INVALID_BOUNDARY\");\n seen.add(cursor);\n ancestors.push(cursor);\n const snapshot = byId.get(cursor);\n cursor = snapshot?.header.parentSession;\n }\n const rootId = ancestors.at(-1);\n if (rootId === undefined) {\n throw new SessionBranchError(`session \"${sessionId}\" is not persisted`, \"SESSION_NOT_FOUND\");\n }\n\n // 根向下的完整后代(BFS;按 createdAt 稳定排序)。\n const ordered: SessionId[] = [];\n const queue: SessionId[] = [rootId];\n while (queue.length > 0) {\n const id = queue.shift();\n if (id === undefined) continue;\n ordered.push(id);\n const children = snapshots\n .filter((snapshot) => snapshot.header.parentSession === id)\n .sort(\n (left, right) =>\n left.header.createdAt - right.header.createdAt ||\n String(left.header.id).localeCompare(String(right.header.id)),\n )\n .map((snapshot) => snapshot.header.id);\n queue.push(...children);\n }\n\n const nodes: BranchVersionNode[] = [];\n const effectIds = new Set<string>();\n for (const id of ordered) {\n const snapshot = byId.get(id);\n if (snapshot === undefined) continue;\n const header = snapshot.header;\n const node: BranchVersionNode = {\n sessionId: header.id,\n ...(header.parentSession === undefined ? {} : { parentSessionId: header.parentSession }),\n seedLength: snapshot.inheritedEventCount ?? 0,\n createdAt: header.createdAt,\n };\n // 根节点不可能带版本效果;其余节点读自有后缀。\n if (header.parentSession !== undefined) {\n const events = await readOwnEvents(header.id, node.seedLength, signal);\n // 结构化守卫 + find(版本事件类型不在固化的 SessionEventType 中)。\n let version: SessionBranchVersionEventEnvelope | undefined;\n for (const event of events) {\n if (isSessionBranchVersionEvent(event)) {\n if (version !== undefined) {\n throw new SessionBranchError(\n `session ${header.id} carries multiple own version effects`,\n \"INVALID_BOUNDARY\",\n );\n }\n version = event;\n }\n }\n if (version !== undefined) {\n const data = version.data;\n if (\n data.inverse.kind !== \"restore-version\" ||\n data.inverse.sessionId !== header.parentSession\n ) {\n throw new SessionBranchError(\n `session ${header.id} version inverse does not match its parent`,\n \"INVALID_BOUNDARY\",\n );\n }\n if (effectIds.has(data.effect.id)) {\n throw new SessionBranchError(\n `version effect ${data.effect.id} is duplicated`,\n \"INVALID_BOUNDARY\",\n );\n }\n effectIds.add(data.effect.id);\n node.effect = data.effect;\n node.inverseSessionId = data.inverse.sessionId;\n }\n }\n nodes.push(node);\n }\n\n const root = nodes.find((node) => node.parentSessionId === undefined);\n if (root === undefined) {\n throw new SessionBranchError(`session \"${sessionId}\" lineage has no root`, \"SESSION_NOT_FOUND\");\n }\n return { root, nodes };\n}\n","import type { SessionEvent } from \"@deepseek-ai/dsh-session\";\n\nexport function balanceRewindPrefix(events: readonly SessionEvent[]): SessionEvent[] {\n let keep = events.length;\n // 从尾部向前待配对的 step/end 数(每个配对它之前的 step/start)。\n let openStepEnds = 0;\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const type = events[index]?.type;\n if (type === \"turn/end\") break; // 轮次闭合:之前的 step 全部配对。\n if (type === \"step/end\") {\n openStepEnds += 1;\n continue;\n }\n if (type === \"step/start\") {\n if (openStepEnds > 0) {\n openStepEnds -= 1; // 配对成功。\n } else {\n keep = index; // 孤儿 step/start:剔除它及其后。\n }\n }\n }\n return events.slice(0, keep);\n}\n","import type { Context } from \"@deepseek-ai/cordis\";\nimport { SessionBranch } from \"./branch.ts\";\n\nexport { SessionBranch } from \"./branch.ts\";\nexport type { SessionBranchProvider, BranchAnchorMode } from \"./provider.ts\";\nexport { buildTimeline } from \"./timeline.ts\";\nexport type { OwnEventsReader } from \"./timeline.ts\";\nexport { balanceRewindPrefix } from \"./balance.ts\";\nexport * from \"./types.ts\";\n\ndeclare module \"@deepseek-ai/cordis\" {\n interface Context {\n sessionBranch: SessionBranch;\n }\n}\n\nexport function apply(_ctx: Context): void {\n // 契约层不发布服务:ctx.sessionBranch 由实现 provider 的后端插件注册。\n // 保留 apply 仅为 cordis 插件装配兼容,不注入任何服务。\n}\n"],"mappings":";;AAKA,IAAsB,gBAAtB,cAA4C,QAAQ;CAClD,YAAY,KAA4C;EACtD,MAAM,KAAK,eAAe;CAC5B;CAuBA,eAAe,YAA6B,CAE5C;AACF;;;AC3BA,MAAa,oBAAqC;AAElD,MAAa,gCAAgC;AA2F7C,IAAa,qBAAb,cAAwC,MAAM;CAC5C;CACA,YAAY,SAAiB,MAA8B;EACzD,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO;CACd;AACF;AAUA,SAAgB,4BACd,OAC4C;CAC5C,OACE,MAAM,SAAS,4BACd,MAAM,KAAqC,kBAAA;AAEhD;;;ACxGA,eAAsB,cACpB,WACA,eACA,WACA,QACyB;CACzB,MAAM,OAAO,IAAI,IAAI,UAAU,KAAK,aAAa,CAAC,SAAS,OAAO,IAAI,QAAQ,CAAU,CAAC;CAGzF,MAAM,YAAyB,CAAC;CAChC,IAAI,SAAgC;CACpC,MAAM,uBAAO,IAAI,IAAe;CAChC,OAAO,WAAW,KAAA,GAAW;EAC3B,IAAI,KAAK,IAAI,MAAM,GACjB,MAAM,IAAI,mBAAmB,4BAA4B,kBAAkB;EAC7E,KAAK,IAAI,MAAM;EACf,UAAU,KAAK,MAAM;EAErB,SADiB,KAAK,IAAI,MACV,CAAC,EAAE,OAAO;CAC5B;CACA,MAAM,SAAS,UAAU,GAAG,EAAE;CAC9B,IAAI,WAAW,KAAA,GACb,MAAM,IAAI,mBAAmB,YAAY,UAAU,qBAAqB,mBAAmB;CAI7F,MAAM,UAAuB,CAAC;CAC9B,MAAM,QAAqB,CAAC,MAAM;CAClC,OAAO,MAAM,SAAS,GAAG;EACvB,MAAM,KAAK,MAAM,MAAM;EACvB,IAAI,OAAO,KAAA,GAAW;EACtB,QAAQ,KAAK,EAAE;EACf,MAAM,WAAW,UACd,QAAQ,aAAa,SAAS,OAAO,kBAAkB,EAAE,CAAC,CAC1D,MACE,MAAM,UACL,KAAK,OAAO,YAAY,MAAM,OAAO,aACrC,OAAO,KAAK,OAAO,EAAE,CAAC,CAAC,cAAc,OAAO,MAAM,OAAO,EAAE,CAAC,CAChE,CAAC,CACA,KAAK,aAAa,SAAS,OAAO,EAAE;EACvC,MAAM,KAAK,GAAG,QAAQ;CACxB;CAEA,MAAM,QAA6B,CAAC;CACpC,MAAM,4BAAY,IAAI,IAAY;CAClC,KAAK,MAAM,MAAM,SAAS;EACxB,MAAM,WAAW,KAAK,IAAI,EAAE;EAC5B,IAAI,aAAa,KAAA,GAAW;EAC5B,MAAM,SAAS,SAAS;EACxB,MAAM,OAA0B;GAC9B,WAAW,OAAO;GAClB,GAAI,OAAO,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,OAAO,cAAc;GACtF,YAAY,SAAS,uBAAuB;GAC5C,WAAW,OAAO;EACpB;EAEA,IAAI,OAAO,kBAAkB,KAAA,GAAW;GACtC,MAAM,SAAS,MAAM,cAAc,OAAO,IAAI,KAAK,YAAY,MAAM;GAErE,IAAI;GACJ,KAAK,MAAM,SAAS,QAClB,IAAI,4BAA4B,KAAK,GAAG;IACtC,IAAI,YAAY,KAAA,GACd,MAAM,IAAI,mBACR,WAAW,OAAO,GAAG,wCACrB,kBACF;IAEF,UAAU;GACZ;GAEF,IAAI,YAAY,KAAA,GAAW;IACzB,MAAM,OAAO,QAAQ;IACrB,IACE,KAAK,QAAQ,SAAS,qBACtB,KAAK,QAAQ,cAAc,OAAO,eAElC,MAAM,IAAI,mBACR,WAAW,OAAO,GAAG,6CACrB,kBACF;IAEF,IAAI,UAAU,IAAI,KAAK,OAAO,EAAE,GAC9B,MAAM,IAAI,mBACR,kBAAkB,KAAK,OAAO,GAAG,iBACjC,kBACF;IAEF,UAAU,IAAI,KAAK,OAAO,EAAE;IAC5B,KAAK,SAAS,KAAK;IACnB,KAAK,mBAAmB,KAAK,QAAQ;GACvC;EACF;EACA,MAAM,KAAK,IAAI;CACjB;CAEA,MAAM,OAAO,MAAM,MAAM,SAAS,KAAK,oBAAoB,KAAA,CAAS;CACpE,IAAI,SAAS,KAAA,GACX,MAAM,IAAI,mBAAmB,YAAY,UAAU,wBAAwB,mBAAmB;CAEhG,OAAO;EAAE;EAAM;CAAM;AACvB;;;ACvHA,SAAgB,oBAAoB,QAAiD;CACnF,IAAI,OAAO,OAAO;CAElB,IAAI,eAAe;CACnB,KAAK,IAAI,QAAQ,OAAO,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;EAC1D,MAAM,OAAO,OAAO,MAAM,EAAE;EAC5B,IAAI,SAAS,YAAY;EACzB,IAAI,SAAS,YAAY;GACvB,gBAAgB;GAChB;EACF;EACA,IAAI,SAAS,cAAc;GACzB,IAAI,eAAe,GACjB,gBAAgB;QAEhB,OAAO;EAEX;CACF;CACA,OAAO,OAAO,MAAM,GAAG,IAAI;AAC7B;;;ACNA,SAAgB,MAAM,MAAqB,CAG3C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"invariant.d.mts","names":[],"sources":["../src/invariant.ts"],"mappings":";;cAKa;cAEA;cAIA,QAAK,KAAS,YAAU"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"invariant.mjs","names":[],"sources":["../src/invariant.ts"],"sourcesContent":["import type { Context } from \"@deepseek-ai/cordis\";\nimport type { InvariantInstaller } from \"@deepseek-ai/dsh-invariants\";\n\nconst PACKAGE_NAME = \"@morlay/session-branch\";\n\nexport const name = \"session-branch-invariant\";\n\nexport const inject = [\"invariants\"];\n\nconst install: InvariantInstaller = () => {};\n\nexport const apply = (ctx: Context): Promise<() => void> =>\n Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));\n"],"mappings":";AAGA,MAAM,eAAe;AAErB,MAAa,OAAO;AAEpB,MAAa,SAAS,CAAC,YAAY;AAEnC,MAAM,gBAAoC,CAAC;AAE3C,MAAa,SAAS,QACpB,QAAQ,QAAQ,IAAI,WAAW,SAAS,cAAc,OAAO,CAAC"}