@morlay/ui-conversation-message-actions 0.0.19-alpha.3 → 0.0.19-alpha.4

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 CHANGED
@@ -15,14 +15,15 @@
15
15
  ```ts
16
16
  // host:装配后直接调服务
17
17
  await ctx.sessionEditor.retry({ action: "retry", sessionId, turn: 2, cascade: "truncate" });
18
- const timeline = await ctx.sessionEditor.timeline({ sessionId });
18
+ const result = await ctx.sessionEditor.retry({ sessionId, turn, cascade: "truncate" });
19
19
  ```
20
20
 
21
- HTTP 面:web 模式 `POST` / `GET /session-editor`;宿主内嵌客户端走 `connection.fetch` 的 `/api/session-editor`。
21
+ HTTP 面:`POST /session-editor`(注册面与页面侧路径口径见
22
+ [设计 20260917-编排层操作语义](./.agents/designs/20260917-编排层操作语义.md))。
22
23
 
23
24
  ## 结论
24
25
 
25
- edit / retry / reroll 就地重写**同一会话**(session id 不变、版本树单根),只有 `fork` 派生新 id;`recall` 只截断并把文本
26
+ edit / retry / reroll 就地重写**同一会话**(session id 不变),只有 `fork` 派生新 id;`recall` 只截断并把文本
26
27
  交回 composer,由用户改后自己发
27
28
  ([ADR 就地编辑重写同一会话而非新建会话](./.agents/adrs/20260917-就地编辑重写同一会话而非新建会话.md))。
28
29
 
package/dist/client.cjs CHANGED
@@ -4,176 +4,43 @@ window.__ModuleLoader__.load({
4
4
  var module = { exports: {} };
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
- let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
8
7
  require("@morlay/dsh-client-ui-conversation/client");
9
8
  let _morlay_dsh_client_ui_primitives_client = require("@morlay/dsh-client-ui-primitives/client");
10
9
  let react = require("react");
11
10
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
12
11
  let react_jsx_runtime = require("react/jsx-runtime");
13
12
  let react_dom = require("react-dom");
14
- //#region src/shared.ts
15
- const SESSION_EDITOR_PATH = "/session-editor";
16
13
  //#endregion
17
14
  //#region src/client/controller.ts
18
- function editorApiPath() {
19
- return globalThis.__DSH_TRANSPORT__?.ownsHost === true ? `/api${SESSION_EDITOR_PATH}` : SESSION_EDITOR_PATH;
20
- }
21
- function messageOf(error) {
22
- return error instanceof Error ? error.message : String(error);
23
- }
24
- function conversationRevision(snapshot) {
25
- return [
26
- snapshot.openState,
27
- snapshot.removed,
28
- snapshot.hasMore
29
- ].join("|");
30
- }
15
+ /** 编辑器的 HTTP 路径:宿主(web 与桌面)在同一张路由表上服务它,页面不再按 ownsHost 加前缀。 */
16
+ const EDITOR_API_PATH = "/session-editor";
31
17
  var SessionEditorController = class {
32
18
  sessionId;
33
- store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
34
- status: "idle",
35
- error: null,
36
- pending: null,
37
- timeline: null
38
- });
39
19
  face;
40
- ctx;
41
20
  sessions;
42
- uiWorkspace;
43
- sessionSource;
44
- sessionSourceDispose;
45
- sessionRevision;
46
- disposed = false;
47
- users = 0;
21
+ pending = null;
48
22
  constructor(ctx, sessionId) {
49
23
  this.sessionId = sessionId;
50
- this.ctx = ctx;
51
24
  this.sessions = ctx.get("sessions");
52
- this.uiWorkspace = ctx.get("uiWorkspace");
53
25
  this.face = {
54
- hooks: { sessionEditor: this.store },
55
- acquire: () => {
56
- this.users += 1;
57
- if (this.users === 1 && this.disposed) this.revive();
58
- return () => this.release();
59
- },
60
- load: () => {
61
- this.load();
62
- },
63
- edit: (message, text, cascade) => this.mutate({
64
- action: "edit",
65
- sessionId: this.sessionId,
66
- eventSeq: message.eventSeq,
67
- blockIndex: message.blockIndex,
68
- text,
69
- cascade
70
- }),
71
26
  retry: (turn, cascade) => this.mutate({
72
27
  action: "retry",
73
28
  sessionId: this.sessionId,
74
29
  turn,
75
30
  cascade
76
31
  }),
77
- reroll: () => this.mutate({
78
- action: "reroll",
79
- sessionId: this.sessionId
80
- }),
81
- rewind: (toBoundary) => this.mutate({
82
- action: "rewind",
83
- sessionId: this.sessionId,
84
- toBoundary
85
- }),
86
- recall: (message) => this.mutate({
32
+ recall: (message, texts) => this.mutate({
87
33
  action: "recall",
88
34
  sessionId: this.sessionId,
89
35
  eventSeq: message.eventSeq
90
- }, () => this.setComposerDraft(this.messageTexts(message))),
91
- openVersion: (sessionId) => {
92
- this.uiWorkspace.openSession(sessionId);
93
- return Promise.resolve();
94
- }
36
+ }, () => this.setComposerDraft(texts.join("\n\n")))
95
37
  };
96
- this.observe();
97
- }
98
- observe() {
99
- this.sessionSource = void 0;
100
- this.sessionSourceDispose?.();
101
- this.bindSessionSource();
102
- this.sessions.list.subscribe(() => this.invalidate());
103
- }
104
- bindSessionSource() {
105
- const source = this.sessions.binding(this.sessionId)?.session;
106
- if (source === this.sessionSource) return;
107
- this.sessionSourceDispose?.();
108
- this.sessionSource = source;
109
- this.sessionRevision = source === void 0 ? void 0 : conversationRevision(source.getSnapshot());
110
- this.sessionSourceDispose = source?.subscribe(() => {
111
- this.invalidate();
112
- });
113
- }
114
- invalidate() {
115
- if (this.disposed || this.store.getSnapshot().status === "idle") return;
116
- this.load();
117
- }
118
- release() {
119
- this.users -= 1;
120
- if (this.users <= 0) this.dispose();
121
- }
122
- dispose() {
123
- if (this.disposed) return;
124
- this.disposed = true;
125
- this.sessionSourceDispose?.();
126
- this.sessionSourceDispose = void 0;
127
- this.sessionSource = void 0;
128
- this.sessionRevision = void 0;
129
- }
130
- revive() {
131
- this.disposed = false;
132
- this.observe();
133
- this.load();
134
- }
135
- async load() {
136
- if (this.disposed) return;
137
- this.store.update((state) => {
138
- state.status = "loading";
139
- state.error = null;
140
- });
141
- try {
142
- const response = await fetch(`${editorApiPath()}?sessionId=${encodeURIComponent(this.sessionId)}`, {
143
- method: "GET",
144
- headers: { accept: "application/json" },
145
- cache: "no-store"
146
- });
147
- const value = await response.json();
148
- if (this.disposed) return;
149
- if (response.ok) this.store.update((state) => {
150
- state.status = "ready";
151
- state.error = null;
152
- state.timeline = value;
153
- });
154
- else {
155
- const error = value["error"];
156
- this.store.update((state) => {
157
- state.status = "error";
158
- state.error = typeof error === "string" ? error : `请求失败:HTTP ${String(response.status)}`;
159
- });
160
- }
161
- } catch (error) {
162
- if (this.disposed) return;
163
- this.store.update((state) => {
164
- state.status = "error";
165
- state.error = messageOf(error);
166
- });
167
- }
168
38
  }
169
39
  async mutate(operation, onApplied) {
170
- if (this.store.getSnapshot().pending !== null) return false;
171
- this.store.update((state) => {
172
- state.pending = operation.action;
173
- state.error = null;
174
- });
40
+ if (this.pending !== null) return false;
41
+ this.pending = operation.action;
175
42
  try {
176
- const response = await fetch(editorApiPath(), {
43
+ const response = await fetch(EDITOR_API_PATH, {
177
44
  method: "POST",
178
45
  headers: {
179
46
  accept: "application/json",
@@ -182,54 +49,48 @@ window.__ModuleLoader__.load({
182
49
  body: JSON.stringify(operation)
183
50
  });
184
51
  const value = await response.json();
185
- if (this.disposed) return true;
186
52
  if (!response.ok) {
187
53
  const error = value["error"];
188
54
  throw new Error(typeof error === "string" ? error : `请求失败:HTTP ${String(response.status)}`);
189
55
  }
190
- this.store.update((state) => {
191
- state.pending = null;
192
- });
193
56
  onApplied?.();
194
- const result = value;
195
- if (String(result.sessionId) !== String(this.sessionId)) {
196
- this.uiWorkspace.openSession(result.sessionId);
197
- return true;
57
+ try {
58
+ await this.rebuildWindow();
59
+ } catch (error) {
60
+ console.warn("[session-editor] 操作已生效,但会话窗口重建失败:", error);
198
61
  }
199
- const face = this.sessions.binding(this.sessionId)?.session;
200
- const resync = face.resync;
201
- if (resync !== void 0) try {
202
- await resync.call(face);
203
- const projections = face.projections;
204
- if (typeof projections?.truncate !== "function") {
205
- location.reload();
206
- return true;
207
- }
208
- projections.truncate(-1);
209
- this.load();
210
- return true;
211
- } catch {}
212
- location.reload();
213
62
  return true;
214
- } catch (error) {
215
- if (this.disposed) return false;
216
- this.store.update((state) => {
217
- state.pending = null;
218
- state.error = messageOf(error);
219
- });
63
+ } catch {
220
64
  return false;
65
+ } finally {
66
+ this.pending = null;
221
67
  }
222
68
  }
223
- messageTexts(message) {
224
- const prefix = `${String(message.eventSeq)}:`;
225
- const blocks = (this.store.getSnapshot().timeline?.messages ?? []).filter((row) => row.kind === "user" && row.key.startsWith(prefix)).sort((left, right) => left.blockIndex - right.blockIndex).map((row) => row.text);
226
- return blocks.length === 0 ? [message.text] : blocks;
69
+ /**
70
+ * 让上游重开该会话的历史窗口(rewind 之后客户端窗口的 seq 基线已经失效)。
71
+ *
72
+ * 探测顺序:`binding(id).session.resync()`(上游 ClientSession 的重建入口,类型面没暴露)
73
+ * → `sessions.refresh()`(只刷列表元数据,聊胜于无)→ 都没有就记一条 warn。
74
+ */
75
+ async rebuildWindow() {
76
+ const sessions = this.sessions;
77
+ const face = sessions.binding?.(this.sessionId)?.session;
78
+ const resync = face?.resync;
79
+ if (typeof resync === "function") {
80
+ await resync.call(face);
81
+ return;
82
+ }
83
+ if (typeof sessions.refresh === "function") {
84
+ await sessions.refresh();
85
+ return;
86
+ }
87
+ console.warn("[session-editor] 未找到会话窗口重建入口(binding.resync / refresh 都不可用),窗口可能停留在 rewind 之前的状态");
227
88
  }
228
- setComposerDraft(texts) {
89
+ setComposerDraft(text) {
229
90
  if (this.sessions.binding(this.sessionId) === void 0) return;
230
91
  const scoped = this.sessions.scope(this.sessionId);
231
92
  if (scoped === void 0) return;
232
- scoped.get("conversation")?.input?.for(scoped).restoreDraft(texts.join("\n\n"));
93
+ scoped.get("conversation")?.input?.for(scoped).restoreDraft(text);
233
94
  }
234
95
  };
235
96
  //#endregion
@@ -710,6 +571,7 @@ window.__ModuleLoader__.load({
710
571
  }
711
572
  return {
712
573
  text: texts.join("\n\n"),
574
+ texts,
713
575
  images,
714
576
  rest
715
577
  };
@@ -744,6 +606,7 @@ window.__ModuleLoader__.load({
744
606
  }
745
607
  const UserMessageNodeView = (0, react.memo)(function UserMessageNodeView({ node, renderMessageImages, t, openFile, openSkill, recall, retry }) {
746
608
  const data = node.data;
609
+ const recallTexts = contentParts(data.content).texts;
747
610
  const [confirmingRecall, setConfirmingRecall] = (0, react.useState)(null);
748
611
  const [confirmingRetry, setConfirmingRetry] = (0, react.useState)(false);
749
612
  const turnLocation = node.location.kind === "turn" || node.location.kind === "step" ? node.location.turn : void 0;
@@ -783,7 +646,7 @@ window.__ModuleLoader__.load({
783
646
  onClick: () => {
784
647
  const target = confirmingRecall;
785
648
  setConfirmingRecall(null);
786
- recall(target);
649
+ recall(target, recallTexts);
787
650
  },
788
651
  children: "撤回并编辑"
789
652
  })]
@@ -1366,9 +1229,6 @@ window.__ModuleLoader__.load({
1366
1229
  }
1367
1230
  return controller;
1368
1231
  };
1369
- ctx.on("connection/reset", () => {
1370
- for (const controller of controllers.values()) controller.load();
1371
- });
1372
1232
  registerChatNodeRenderers(ctx, controllerFor);
1373
1233
  ctx.slots.inject("conversation.composer.dock", () => registerComposerStats(ctx.slots));
1374
1234
  }
package/dist/index.d.cts CHANGED
@@ -1,8 +1,8 @@
1
- import { C as SessionEditorResult, S as SessionEditorOperation, _ as RecallOperation, b as RetryableTurn, c as editableMessages, g as EditableMessageBlock, h as EditOperation, i as closedTurns, m as retryableTurns, v as RerollOperation, x as RewindOperation, y as RetryOperation } from "./plan-CT_6Y1fD.cjs";
1
+ import { C as SessionEditorResult, S as SessionEditorOperation, _ as RecallOperation, b as RetryableTurn, c as editableMessages, g as EditableMessageBlock, h as EditOperation, i as closedTurns, m as retryableTurns, v as RerollOperation, x as RewindOperation, y as RetryOperation } from "./plan-BUTplrpz.cjs";
2
2
  import { Context, Service } from "@deepseek-ai/cordis";
3
3
  import { UserMessage } from "@deepseek-ai/dsh-llm";
4
4
  import { AgentCancelCause, Session, SessionEvent, SessionId } from "@deepseek-ai/dsh-session";
5
- import { BranchBoundary, BranchTimeline, BranchTimeline as BranchTimeline$1, CascadePolicy, EditableBlockKind, SESSION_BRANCH_VERSION_SCHEMA, SessionBranchVersionEvent } from "@morlay/session-branch";
5
+ import { BranchBoundary, CascadePolicy, EditableBlockKind } from "@morlay/session-branch";
6
6
  //#region src/index.d.ts
7
7
  declare module "@deepseek-ai/cordis" {
8
8
  interface Context {
@@ -56,13 +56,10 @@ declare class SessionEditor extends Service {
56
56
  agentPreset?: string;
57
57
  }, signal?: AbortSignal): Promise<SessionId>;
58
58
  rewind(id: SessionId, toBoundary: number, signal?: AbortSignal): Promise<import("@deepseek-ai/dsh-session-persistence").SessionPersistenceSnapshot>;
59
- timeline(sessionId: SessionId, signal?: AbortSignal): Promise<BranchTimeline$1>;
60
59
  edit(operation: EditOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
61
60
  reroll(operation: RerollOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
62
61
  retry(operation: RetryOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
63
62
  recall(operation: RecallOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
64
- editableMessages(sessionId: SessionId, signal?: AbortSignal): Promise<EditableMessageBlock[]>;
65
- retryableTurns(sessionId: SessionId, signal?: AbortSignal): Promise<RetryableTurn[]>;
66
63
  private branchOperation;
67
64
  private recallOperation;
68
65
  private seedStart;
@@ -72,4 +69,4 @@ declare class SessionEditor extends Service {
72
69
  private prepareReplay;
73
70
  }
74
71
  //#endregion
75
- export { type BranchTimeline, type CascadePolicy, type EditOperation, type EditableBlockKind, type EditableMessageBlock, EditorAgent, EditorAgentHandle, EditorAgentRegistry, type RecallOperation, type RerollOperation, type RetryOperation, type RetryableTurn, type RewindOperation, SESSION_BRANCH_VERSION_SCHEMA, type SessionBranchVersionEvent, SessionEditor, SessionEditor as default, type SessionEditorOperation, type SessionEditorResult, closedTurns, editableMessages, retryableTurns };
72
+ export { type CascadePolicy, type EditOperation, type EditableBlockKind, type EditableMessageBlock, EditorAgent, EditorAgentHandle, EditorAgentRegistry, type RecallOperation, type RerollOperation, type RetryOperation, type RetryableTurn, type RewindOperation, SessionEditor, SessionEditor as default, type SessionEditorOperation, type SessionEditorResult, closedTurns, editableMessages, retryableTurns };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { C as SessionEditorResult, S as SessionEditorOperation, _ as RecallOperation, b as RetryableTurn, c as editableMessages, g as EditableMessageBlock, h as EditOperation, i as closedTurns, m as retryableTurns, v as RerollOperation, x as RewindOperation, y as RetryOperation } from "./plan-Cm9hCord.mjs";
1
+ import { C as SessionEditorResult, S as SessionEditorOperation, _ as RecallOperation, b as RetryableTurn, c as editableMessages, g as EditableMessageBlock, h as EditOperation, i as closedTurns, m as retryableTurns, v as RerollOperation, x as RewindOperation, y as RetryOperation } from "./plan-BKgGPZdD.mjs";
2
2
  import { Context, Service } from "@deepseek-ai/cordis";
3
3
  import { AgentCancelCause, Session, SessionEvent, SessionId } from "@deepseek-ai/dsh-session";
4
- import { BranchBoundary, BranchTimeline, BranchTimeline as BranchTimeline$1, CascadePolicy, EditableBlockKind, SESSION_BRANCH_VERSION_SCHEMA, SessionBranchVersionEvent } from "@morlay/session-branch";
4
+ import { BranchBoundary, CascadePolicy, EditableBlockKind } from "@morlay/session-branch";
5
5
  import { UserMessage } from "@deepseek-ai/dsh-llm";
6
6
  //#region src/index.d.ts
7
7
  declare module "@deepseek-ai/cordis" {
@@ -56,13 +56,10 @@ declare class SessionEditor extends Service {
56
56
  agentPreset?: string;
57
57
  }, signal?: AbortSignal): Promise<SessionId>;
58
58
  rewind(id: SessionId, toBoundary: number, signal?: AbortSignal): Promise<import("@deepseek-ai/dsh-session-persistence").SessionPersistenceSnapshot>;
59
- timeline(sessionId: SessionId, signal?: AbortSignal): Promise<BranchTimeline$1>;
60
59
  edit(operation: EditOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
61
60
  reroll(operation: RerollOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
62
61
  retry(operation: RetryOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
63
62
  recall(operation: RecallOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
64
- editableMessages(sessionId: SessionId, signal?: AbortSignal): Promise<EditableMessageBlock[]>;
65
- retryableTurns(sessionId: SessionId, signal?: AbortSignal): Promise<RetryableTurn[]>;
66
63
  private branchOperation;
67
64
  private recallOperation;
68
65
  private seedStart;
@@ -72,4 +69,4 @@ declare class SessionEditor extends Service {
72
69
  private prepareReplay;
73
70
  }
74
71
  //#endregion
75
- export { type BranchTimeline, type CascadePolicy, type EditOperation, type EditableBlockKind, type EditableMessageBlock, EditorAgent, EditorAgentHandle, EditorAgentRegistry, type RecallOperation, type RerollOperation, type RetryOperation, type RetryableTurn, type RewindOperation, SESSION_BRANCH_VERSION_SCHEMA, type SessionBranchVersionEvent, SessionEditor, SessionEditor as default, type SessionEditorOperation, type SessionEditorResult, closedTurns, editableMessages, retryableTurns };
72
+ export { type CascadePolicy, type EditOperation, type EditableBlockKind, type EditableMessageBlock, EditorAgent, EditorAgentHandle, EditorAgentRegistry, type RecallOperation, type RerollOperation, type RetryOperation, type RetryableTurn, type RewindOperation, SessionEditor, SessionEditor as default, type SessionEditorOperation, type SessionEditorResult, closedTurns, editableMessages, retryableTurns };
package/dist/index.mjs CHANGED
@@ -1,16 +1,15 @@
1
- import { n as toTimelinePayload, t as SESSION_EDITOR_PATH } from "./shared-LK3nImWW.mjs";
1
+ import { t as SESSION_EDITOR_PATH } from "./shared-BBbOTwy4.mjs";
2
2
  import { closedTurns, droppedCompactions, editPlan, editableMessages, precedingContentIndex, recallBoundary, rerollPlan, restoreCompactions, retryPlan, retryableTurns } from "./plan.mjs";
3
3
  import { Service } from "@deepseek-ai/cordis";
4
4
  import { SessionSeq } from "@deepseek-ai/dsh-session";
5
- import { SESSION_BRANCH_VERSION_SCHEMA, SessionBranchError, balanceRewindPrefix } from "@morlay/session-branch";
5
+ import { SessionBranchError, balanceRewindPrefix } from "@morlay/session-branch";
6
6
  //#region src/index.ts
7
- function appendLogSeedEvent(events, type, data, ignorable = false) {
7
+ function appendLogSeedEvent(events, type, data) {
8
8
  events.push({
9
9
  type,
10
10
  seq: events.length,
11
11
  time: Date.now(),
12
- data,
13
- ...ignorable ? { ignorable: true } : {}
12
+ data
14
13
  });
15
14
  }
16
15
  function appendSurfaceSeedEvent(events, type, data, intent) {
@@ -50,22 +49,8 @@ function keepFromOf(events, boundary) {
50
49
  if (boundary < 0) return 0;
51
50
  return events[boundary]?.type === "turn/end" ? boundary + 1 : boundary;
52
51
  }
53
- async function appendSeedSuffixLive(session, seedSuffix, appendDirect) {
52
+ async function appendSeedSuffixLive(session, seedSuffix) {
54
53
  for (const event of seedSuffix) {
55
- if (event.ignorable === true) {
56
- const s = session;
57
- const seq = s.log.length;
58
- await appendDirect([{
59
- ...event,
60
- seq
61
- }]);
62
- s.log.push({
63
- ...event,
64
- seq
65
- });
66
- s.eventsSnapshot = void 0;
67
- continue;
68
- }
69
54
  const s = session;
70
55
  const raw = event;
71
56
  if (raw.surfaceOp !== void 0) s.append(event.type, event.data, {
@@ -99,9 +84,6 @@ var SessionEditor = class extends Service {
99
84
  await this.stopLoop(id, signal);
100
85
  return this.ctx.sessionBranch.rewind(id, toBoundary, signal);
101
86
  }
102
- timeline(sessionId, signal) {
103
- return this.ctx.sessionBranch.timeline(sessionId, signal);
104
- }
105
87
  edit(operation, signal) {
106
88
  return this.branchOperation(operation, signal);
107
89
  }
@@ -114,14 +96,6 @@ var SessionEditor = class extends Service {
114
96
  recall(operation, signal) {
115
97
  return this.recallOperation(operation, signal);
116
98
  }
117
- async editableMessages(sessionId, signal) {
118
- const events = await this.readEvents(sessionId, signal);
119
- return editableMessages(closedTurns(events));
120
- }
121
- async retryableTurns(sessionId, signal) {
122
- const events = await this.readEvents(sessionId, signal);
123
- return retryableTurns(closedTurns(events));
124
- }
125
99
  async branchOperation(operation, signal) {
126
100
  signal?.throwIfAborted();
127
101
  const events = await this.readEvents(operation.sessionId, signal);
@@ -134,8 +108,6 @@ var SessionEditor = class extends Service {
134
108
  const keepFrom = keepFromOf(events, boundary);
135
109
  const compactions = droppedCompactions(events, keepFrom, plan.targetSeq);
136
110
  const replayTurn = preceding < 0 ? 1 : turns[preceding].turn + 1;
137
- const versionSeed = [];
138
- appendLogSeedEvent(versionSeed, "session-branch/version", plan.version, true);
139
111
  const manualSeed = [];
140
112
  if (plan.manualTurn !== void 0) appendManualTurn(manualSeed, {
141
113
  ...plan.manualTurn,
@@ -146,11 +118,7 @@ var SessionEditor = class extends Service {
146
118
  const live = this.ctx.sessions.get(operation.sessionId);
147
119
  await this.ctx.sessionBranch.rewind(operation.sessionId, boundary, signal);
148
120
  const seedStart = this.seedStart(live, events, keepFrom);
149
- const seedSuffix = [
150
- ...versionSeed,
151
- ...restoreCompactions(compactions, keepFrom, seedStart + versionSeed.length),
152
- ...manualSeed
153
- ];
121
+ const seedSuffix = [...restoreCompactions(compactions, keepFrom, seedStart), ...manualSeed];
154
122
  await this.appendSeedSuffix(operation.sessionId, live, seedSuffix, events, keepFrom);
155
123
  let queuedTurns = 0;
156
124
  if (replay.agent !== void 0 && plan.queuedUsers.length > 0) {
@@ -191,10 +159,8 @@ var SessionEditor = class extends Service {
191
159
  async appendSeedSuffix(sessionId, live, seedSuffix, events, keepFrom) {
192
160
  if (seedSuffix.length === 0) return;
193
161
  if (live !== void 0) {
194
- const handle = this.ctx.sessionPersistence.tracker.writerOf(sessionId);
195
- if (handle === void 0) throw new Error(`session "${sessionId}" has no live write handle for the version effect`);
196
162
  await this.ctx.sessions.flush(live);
197
- await appendSeedSuffixLive(live, seedSuffix, (batch) => handle.append(batch));
163
+ await appendSeedSuffixLive(live, seedSuffix);
198
164
  await this.ctx.sessions.flush(live);
199
165
  return;
200
166
  }
@@ -342,12 +308,6 @@ function respondJson(response, status, value) {
342
308
  });
343
309
  response.end(JSON.stringify(value));
344
310
  }
345
- async function readTimeline(editor, sessionId) {
346
- const timeline = await editor.timeline(sessionId);
347
- const messages = await editor.editableMessages(sessionId);
348
- const retryable = await editor.retryableTurns(sessionId);
349
- return toTimelinePayload(sessionId, timeline, messages, retryable);
350
- }
351
311
  async function runOperation(editor, operation) {
352
312
  switch (operation.action) {
353
313
  case "edit": {
@@ -396,10 +356,6 @@ async function runOperation(editor, operation) {
396
356
  }
397
357
  async function handleRoute(editor, request, response) {
398
358
  try {
399
- if (request.method === "GET") {
400
- respondJson(response, 200, await readTimeline(editor, sessionIdOf(new URL(request.url ?? "/session-editor", "http://session-editor.local").searchParams.get("sessionId"))));
401
- return;
402
- }
403
359
  if (request.method === "POST") {
404
360
  respondJson(response, 200, await runOperation(editor, decodeOperation(await requestJson(request))));
405
361
  return;
@@ -422,40 +378,6 @@ function registerHttpRoutes(ctx) {
422
378
  handler: (request, response) => handleRoute(editor, request, response)
423
379
  });
424
380
  }, "session-editor: HTTP route");
425
- const registerConnectionRoute = () => {
426
- const connection = ctx.get("connection", false);
427
- if (connection === void 0) return;
428
- const editor = ctx.sessionEditor;
429
- ctx.effect(() => connection.fetch.register({
430
- path: `/api${SESSION_EDITOR_PATH}`,
431
- methods: ["GET", "POST"],
432
- requestBody: "buffered",
433
- fetch: (request) => handleFetchRoute(editor, request)
434
- }), "session-editor: connection fetch route");
435
- };
436
- ctx.on("internal/service", (name) => {
437
- if (name === "connection") registerConnectionRoute();
438
- });
439
- registerConnectionRoute();
440
- }
441
- async function handleFetchRoute(editor, request) {
442
- try {
443
- if (request.method === "GET") return jsonResponse(200, await readTimeline(editor, sessionIdOf(new URL(request.url).searchParams.get("sessionId"))));
444
- if (request.method === "POST") return jsonResponse(200, await runOperation(editor, decodeOperation(await request.json())));
445
- return new Response(null, { status: 405 });
446
- } catch (error) {
447
- const message = error instanceof Error ? error.message : String(error);
448
- return jsonResponse(error instanceof TypeError ? 400 : 409, { error: message });
449
- }
450
- }
451
- function jsonResponse(status, value) {
452
- return new Response(JSON.stringify(value), {
453
- status,
454
- headers: {
455
- "content-type": "application/json; charset=utf-8",
456
- "cache-control": "no-store"
457
- }
458
- });
459
381
  }
460
382
  //#endregion
461
- export { SESSION_BRANCH_VERSION_SCHEMA, SessionEditor, SessionEditor as default, closedTurns, editableMessages, retryableTurns };
383
+ export { SessionEditor, SessionEditor as default, closedTurns, editableMessages, retryableTurns };
@@ -1,6 +1,6 @@
1
- import { AssistantMessage, UserMessage } from "@deepseek-ai/dsh-llm";
2
1
  import { SessionEvent, SessionId } from "@deepseek-ai/dsh-session";
3
- import { BranchTimeline, CascadePolicy, SessionBranchVersionEvent } from "@morlay/session-branch";
2
+ import { CascadePolicy } from "@morlay/session-branch";
3
+ import { AssistantMessage, UserMessage } from "@deepseek-ai/dsh-llm";
4
4
  //#region src/types.d.ts
5
5
  interface EditOperation {
6
6
  action: "edit";
@@ -71,7 +71,6 @@ interface ClosedTurn {
71
71
  interface OperationPlan {
72
72
  anchorSeq: number;
73
73
  rewindBoundary?: number;
74
- version: SessionBranchVersionEvent;
75
74
  manualTurn?: {
76
75
  turn: number;
77
76
  user: UserMessage;
@@ -1,6 +1,6 @@
1
- import { SessionEvent, SessionId } from "@deepseek-ai/dsh-session";
2
- import { BranchTimeline, CascadePolicy, SessionBranchVersionEvent } from "@morlay/session-branch";
3
1
  import { AssistantMessage, UserMessage } from "@deepseek-ai/dsh-llm";
2
+ import { SessionEvent, SessionId } from "@deepseek-ai/dsh-session";
3
+ import { CascadePolicy } from "@morlay/session-branch";
4
4
  //#region src/types.d.ts
5
5
  interface EditOperation {
6
6
  action: "edit";
@@ -71,7 +71,6 @@ interface ClosedTurn {
71
71
  interface OperationPlan {
72
72
  anchorSeq: number;
73
73
  rewindBoundary?: number;
74
- version: SessionBranchVersionEvent;
75
74
  manualTurn?: {
76
75
  turn: number;
77
76
  user: UserMessage;
package/dist/plan.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as downstreamUsers, c as editableMessages, d as rerollPlan, f as restoreCompactions, i as closedTurns, l as precedingContentIndex, m as retryableTurns, n as CompactionBracket, o as droppedCompactions, p as retryPlan, r as OperationPlan, s as editPlan, t as ClosedTurn, u as recallBoundary } from "./plan-CT_6Y1fD.cjs";
1
+ import { a as downstreamUsers, c as editableMessages, d as rerollPlan, f as restoreCompactions, i as closedTurns, l as precedingContentIndex, m as retryableTurns, n as CompactionBracket, o as droppedCompactions, p as retryPlan, r as OperationPlan, s as editPlan, t as ClosedTurn, u as recallBoundary } from "./plan-BUTplrpz.cjs";
2
2
  export { ClosedTurn, CompactionBracket, OperationPlan, closedTurns, downstreamUsers, droppedCompactions, editPlan, editableMessages, precedingContentIndex, recallBoundary, rerollPlan, restoreCompactions, retryPlan, retryableTurns };
package/dist/plan.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as downstreamUsers, c as editableMessages, d as rerollPlan, f as restoreCompactions, i as closedTurns, l as precedingContentIndex, m as retryableTurns, n as CompactionBracket, o as droppedCompactions, p as retryPlan, r as OperationPlan, s as editPlan, t as ClosedTurn, u as recallBoundary } from "./plan-Cm9hCord.mjs";
1
+ import { a as downstreamUsers, c as editableMessages, d as rerollPlan, f as restoreCompactions, i as closedTurns, l as precedingContentIndex, m as retryableTurns, n as CompactionBracket, o as droppedCompactions, p as retryPlan, r as OperationPlan, s as editPlan, t as ClosedTurn, u as recallBoundary } from "./plan-BKgGPZdD.mjs";
2
2
  export { ClosedTurn, CompactionBracket, OperationPlan, closedTurns, downstreamUsers, droppedCompactions, editPlan, editableMessages, precedingContentIndex, recallBoundary, rerollPlan, restoreCompactions, retryPlan, retryableTurns };