@morlay/ui-conversation-message-actions 0.0.11 → 0.0.12

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.
@@ -3,58 +3,41 @@ import { BranchBoundary, BranchTimeline, BranchTimeline as BranchTimeline$1, Cas
3
3
  import { UserMessage } from "@deepseek-ai/dsh-llm";
4
4
  import { Session, SessionEvent, SessionId } from "@deepseek-ai/dsh-session";
5
5
  //#region src/types.d.ts
6
- /** 编辑一个已落定文本块(用户 / 助手 reasoning / 助手 response)并从其轮次边界分支。 */
7
6
  interface EditOperation {
8
7
  action: "edit";
9
8
  sessionId: SessionId;
10
- /** 目标事件 seq(`user/message` 或 `assistant/message`)。 */
11
9
  eventSeq: number;
12
- /** 目标内容块索引(text / reasoning)。 */
13
10
  blockIndex: number;
14
- /** 替换后的文本。 */
15
11
  text: string;
16
12
  cascade: CascadePolicy$1;
17
13
  }
18
- /** 重生成最后一条已落定助手回复(使用原用户输入)。 */
19
14
  interface RerollOperation {
20
15
  action: "reroll";
21
16
  sessionId: SessionId;
22
17
  }
23
- /** 重试任意历史回合(从目标轮之前分支,重放其用户输入)。 */
24
18
  interface RetryOperation {
25
19
  action: "retry";
26
20
  sessionId: SessionId;
27
21
  turn: number;
28
22
  cascade: CascadePolicy$1;
29
23
  }
30
- /** 截断式回退:原会话回退到 `toBoundary`(闭合 `turn/end`)。 */
31
24
  interface RewindOperation {
32
25
  action: "rewind";
33
26
  sessionId: SessionId;
34
27
  toBoundary: number;
35
28
  }
36
- /** 派生式分支:从 `atSeq` 锚定的闭合边界派生新会话。 */
37
29
  interface ForkOperation {
38
30
  action: "fork";
39
31
  sessionId: SessionId;
40
32
  atSeq?: number;
41
33
  childSessionId?: SessionId;
42
34
  }
43
- /** 编排层接受的操作判别联合。 */
44
35
  type SessionEditorOperation = EditOperation | RerollOperation | RetryOperation | RewindOperation | ForkOperation;
45
- /** 操作结果:分支式操作返回新版本 id;`rewind` 返回原会话 id。 */
46
36
  interface SessionEditorResult {
47
37
  sessionId: SessionId;
48
- /** 排队重新执行的用户输入轮数(无 agent 驱动时为 0)。 */
49
38
  queuedTurns: number;
50
- /**
51
- * 操作后会话是否仍有 live owner(agent 驻留 / driveAgent 已恢复)。
52
- * 客户端据此决定是否需要重载页面:live 会话的事件流会增量同步
53
- * conversation(不闪屏);cold 会话无事件流,需重载以反映修剪。
54
- */
55
39
  live?: boolean;
56
40
  }
57
- /** 可编辑消息块(编辑面枚举;来自闭合轮次扫描)。 */
58
41
  interface EditableMessageBlock {
59
42
  key: string;
60
43
  turn: number;
@@ -64,7 +47,6 @@ interface EditableMessageBlock {
64
47
  text: string;
65
48
  time: number;
66
49
  }
67
- /** 可重试回合(重试面枚举)。 */
68
50
  interface RetryableTurn {
69
51
  turn: number;
70
52
  userEventSeq: number;
@@ -78,7 +60,6 @@ declare module "@deepseek-ai/cordis" {
78
60
  sessionEditor: SessionEditor;
79
61
  }
80
62
  }
81
- /** —— agent 驱动的 duck-typed 接口(不硬依赖 @deepseek-ai/dsh-agent) —— */
82
63
  interface EditorAgent {
83
64
  readonly session: Session;
84
65
  followup(message: UserMessage): void;
@@ -104,7 +85,6 @@ interface EditorAgentRegistry {
104
85
  maxTokens?: number;
105
86
  };
106
87
  }): Promise<EditorAgentHandle>;
107
- /** 从已持久化会话恢复 agent(`AgentRegistry.resume`;create 对已持久化会话失败)。 */
108
88
  resume(options: {
109
89
  resumeSessionId: SessionId;
110
90
  agentOptions?: {
@@ -114,13 +94,10 @@ interface EditorAgentRegistry {
114
94
  };
115
95
  }): Promise<EditorAgentHandle>;
116
96
  }
117
- /** —— 闭合轮次扫描(纯函数) —— */
118
97
  interface ClosedTurn {
119
98
  turn: number;
120
99
  startSeq: number;
121
- /** 闭合轮次的 `turn/end` seq;未闭合轮次为 undefined。 */
122
100
  endSeq?: number;
123
- /** 是否已闭合(有 `turn/end`)。未闭合轮次的 user 消息仍可编辑。 */
124
101
  closed: boolean;
125
102
  user?: SessionEvent<"user/message">;
126
103
  assistants: SessionEvent<"assistant/message">[];
@@ -128,58 +105,24 @@ interface ClosedTurn {
128
105
  declare function closedTurns(events: readonly SessionEvent[]): ClosedTurn[];
129
106
  declare function editableMessages(turns: readonly ClosedTurn[]): EditableMessageBlock[];
130
107
  declare function retryableTurns(turns: readonly ClosedTurn[]): RetryableTurn[];
131
- /** —— 编排服务 —— */
132
- /**
133
- * `ctx.sessionEditor`:rewind / retry / fork 的完整功能编排。
134
- * 组合 `ctx.sessionBranch`(provider 抽象)与可选的 `agents` 服务。
135
- */
136
108
  declare class SessionEditor extends Service {
137
109
  static inject: string[];
138
110
  constructor(ctx: Context);
139
- /** 定位 `atSeq` 锚定的闭合边界(透传 provider)。 */
140
111
  readBranchPrefix(id: SessionId, atSeq?: number, mode?: "after" | "before", signal?: AbortSignal): Promise<BranchBoundary>;
141
- /** 从持久化源派生新会话(透传 provider;不驱动 agent)。 */
142
112
  fork(sourceId: SessionId, atSeq?: number, childSessionId?: SessionId, meta?: {
143
113
  cwd?: string;
144
114
  agentPreset?: string;
145
115
  }, signal?: AbortSignal): Promise<SessionId>;
146
- /** 截断式回退:原会话回退到闭合边界(透传 provider)。 */
147
116
  rewind(id: SessionId, toBoundary: number, signal?: AbortSignal): Promise<import("@deepseek-ai/dsh-session-persistence").SessionPersistenceSnapshot>;
148
- /**
149
- * 清洗一个会话的 surface/provenance 坐标为稠密空间(透传 sessionBranch)。
150
- * 历史加载失败(坐标混叠导致 seed 校验失败)时调用,清洗后重新加载即可。
151
- * `cleanseSession` 是 rdb 实现层新增的服务面(契约层 `SessionBranch`
152
- * 没有此方法),经运行时访问。
153
- */
154
- cleanseSession(sessionId: SessionId, signal?: AbortSignal): Promise<{
155
- changed: number;
156
- }>;
157
- /** 完整版本树投影(透传 provider 组合)。 */
158
117
  timeline(sessionId: SessionId, signal?: AbortSignal): Promise<BranchTimeline$1>;
159
- /** 编辑一个已落定文本块并从其轮次边界分支。 */
160
118
  edit(operation: EditOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
161
- /** 重生成最后一条已落定助手回复。 */
162
119
  reroll(operation: RerollOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
163
- /** 重试任意历史回合。 */
164
120
  retry(operation: RetryOperation, signal?: AbortSignal): Promise<SessionEditorResult>;
165
- /** 可编辑消息块枚举(Timeline 编辑面)。 */
166
121
  editableMessages(sessionId: SessionId, signal?: AbortSignal): Promise<EditableMessageBlock[]>;
167
- /** 可重试回合枚举(Timeline 重试面)。 */
168
122
  retryableTurns(sessionId: SessionId, signal?: AbortSignal): Promise<RetryableTurn[]>;
169
- /** 执行一个分支式操作(edit / reroll / retry)。 */
170
123
  private branchOperation;
171
- /** 读取会话事件:live 优先,否则走持久化原始读取(不含合成 closers)。 */
172
124
  private readEvents;
173
- /**
174
- * 可选 agent 驱动:优先复用现有 live agent(用户会话驻留——rewind 已截断
175
- * 其 session 内存,followup 会基于截断后历史重放),否则 `resume` 已持久化
176
- * 会话。模型配置来自 branchOperation 在 rewind 前解析的 `headerConfig`
177
- * (rewind 可能截断 request/header);缺失时回退到当前 events。无 agents
178
- * 服务、无可用模型路由或恢复失败时退化为持久化版本(已 durable)。
179
- * 返回实际排队的输入数。
180
- */
181
125
  private driveAgent;
182
- /** 经 live agent(复用)或 resume(重建)排队重放输入;返回排队数。 */
183
126
  private queueThroughAgent;
184
127
  }
185
128
  interface HttpRequestLike {
@@ -202,7 +145,6 @@ interface HttpServerLike {
202
145
  }
203
146
  declare module "@deepseek-ai/cordis" {
204
147
  interface Context {
205
- /** dsh web 的 HTTP route carrier(@deepseek-ai/dsh-host-webserver,`WebRoute` 协议)。 */
206
148
  webServer: HttpServerLike;
207
149
  }
208
150
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/index.ts"],"mappings":";;;;;UAGiB;EACf;EACA,WAAW;EAEX;EAEA;EAEA;EACA,SAAS;;UAGM;EACf;EACA,WAAW;;UAGI;EACf;EACA,WAAW;EACX;EACA,SAAS;;UAGM;EACf;EACA,WAAW;EACX;;UAGe;EACf;EACA,WAAW;EACX;EACA,iBAAiB;;KAGP,yBACR,gBACA,kBACA,iBACA,kBACA;UAEa;EACf,WAAW;EAEX;EAEA;;UAKe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;;;;YCjBU;IACR,eAAe;;;UAIF;WACN,SAAS;EAClB,SAAS,SAAS;;UAGH;WACN,OAAO;EAChB,WAAW;;UAGI;EACf,IAAI,WAAW,YAAY;EAC3B,OAAO;IACL,YAAY;IACZ,gBAAgB;IAChB;MACE;MACA,gBAAgB;MAChB;MACA;;IAEF;MAAiB;MAAkB;MAAe;;MAChD,QAAQ;EAEZ,OAAO;IACL,iBAAiB;IACjB;MAAiB;MAAkB;MAAe;;MAChD,QAAQ;;UAGJ;EACR;EACA;EAEA;EAEA;EACA,OAAO;EACP,YAAY;;iBAGL,YAAY,iBAAiB,iBAAiB;iBAsE9C,iBAAiB,gBAAgB,eAAe;iBAqChD,eAAe,gBAAgB,eAAe;cAmR1C,sBAAsB;SAC1B;EAEP,YAAY,KAAK;EAOjB,iBACE,IAAI,WACJ,gBACA,2BACA,SAAS,cACR,QAAQ;EAIX,KACE,UAAU,WACV,gBACA,iBAAiB,WACjB;IAAS;IAAc;KACvB,SAAS,cACR,QAAQ;EAYX,OAAO,IAAI,WAAW,oBAAoB,SAAS,cAAW,uDAAA;EAI9D,SAAS,WAAW,WAAW,SAAS,cAAc,QAAQ;EAI9D,KAAK,WAAW,eAAe,SAAS,cAAc,QAAQ;EAI9D,OAAO,WAAW,iBAAiB,SAAS,cAAc,QAAQ;EAIlE,MAAM,WAAW,gBAAgB,SAAS,cAAc,QAAQ;EAI1D,iBACJ,WAAW,WACX,SAAS,cACR,QAAQ;EAKL,eAAe,WAAW,WAAW,SAAS,cAAc,QAAQ;UAK5D;UA0EA;UAiBA;UA+BA;;UA2CN;EACR;EACA;EACA,GAAG,eAAe,WAAW,OAAO;EACpC,GAAG,cAAc;EACjB,GAAG,gBAAgB,WAAW;;UAGtB;EACR,UAAU,gBAAgB,UAAU;EACpC,IAAI;;UAGI;EACR,SAAS;IACP;IACA;IACA,UAAU,SAAS,iBAAiB,UAAU,4BAA4B;;;;YAKlE;IACR,WAAW"}
@@ -2,9 +2,7 @@ import { Service } from "@deepseek-ai/cordis";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { SESSION_BRANCH_VERSION_SCHEMA, SESSION_BRANCH_VERSION_SCHEMA as SESSION_BRANCH_VERSION_SCHEMA$1, SessionBranchError, balanceRewindPrefix } from "@morlay/session-branch";
4
4
  //#region src/shared.ts
5
- /** 同源 HTTP 端点(host 注册、client fetch)。 */
6
5
  const SESSION_EDITOR_PATH = "/session-editor";
7
- /** 把 {@link BranchTimeline} 投影成 client 用的 {@link SessionEditorTimeline}。 */
8
6
  function toTimelinePayload(sessionId, timeline, messages, retryableTurns) {
9
7
  const currentPath = /* @__PURE__ */ new Set();
10
8
  for (const node of timeline.nodes) currentPath.add(String(node.sessionId));
@@ -44,7 +42,6 @@ function toTimelinePayload(sessionId, timeline, messages, retryableTurns) {
44
42
  redoSessionIds
45
43
  };
46
44
  }
47
- /** 计算节点到根的深度。 */
48
45
  function depthOf(timeline, sessionId) {
49
46
  const byId = new Map(timeline.nodes.map((node) => [String(node.sessionId), node]));
50
47
  let depth = 0;
@@ -59,22 +56,6 @@ function depthOf(timeline, sessionId) {
59
56
  }
60
57
  //#endregion
61
58
  //#region src/index.ts
62
- /**
63
- * 编排层 `SessionEditor`:在 `@morlay/session-branch` 的 provider 抽象之上
64
- * 组装 rewind / retry / fork 的**完整功能**(参考 `dsh-message-edit` 的
65
- * 产品语义:edit / reroll / retry + 级联策略 + 版本树)。
66
- *
67
- * 分层边界:
68
- * - 数据层(forkFrom / rewind / readBranchPrefix)由 `ctx.sessionBranch`
69
- * (provider 实现,如 `@morlay/session-rdb`)提供;
70
- * - 本服务只做**编排**:闭合轮次扫描、版本效果事件构造、派生 seed 组装、
71
- * rewind 命令透传、版本树投影;
72
- * - agent 驱动(重放用户输入 / 创建子 agent)是**可选增强**:`agents`
73
- * 服务以 duck-typed 接口使用(不硬依赖 `@deepseek-ai/dsh-agent`),
74
- * 缺失时退化为「创建持久化版本」——版本已 durable,之后可随时 resume。
75
- *
76
- * @module @morlay/ui-conversation-message-actions
77
- */
78
59
  function closedTurns(events) {
79
60
  const result = [];
80
61
  let current;
@@ -287,7 +268,6 @@ function rerollPlan(operation, turns) {
287
268
  }
288
269
  throw new SessionBranchError("当前会话没有可重生成的已落定助手回复。", "INVALID_BOUNDARY");
289
270
  }
290
- /** —— 种子事件构造(本地纯事件构造器;Session 构造时统一验证) —— */
291
271
  function appendLogSeedEvent(events, type, data, ignorable = false) {
292
272
  events.push({
293
273
  type,
@@ -332,16 +312,6 @@ function appendManualTurn(events, manual) {
332
312
  reason: { kind: "completed" }
333
313
  });
334
314
  }
335
- /**
336
- * 把派生 seed 后缀落地到 **live** 会话。上游 `Session.append` 不保留
337
- * `ignorable` 标记(只保留 type/data/surface 元数据),而版本效果事件必须
338
- * 保持 ignorable(live log 保留、不落 canonical log),因此:
339
- * - ignorable 事件(版本效果)直接 push 内存 log(不发布 `session/event`;
340
- * 服务端语义事件,客户端无需感知;surfaceManager 对非 surface 事件 fold
341
- * 无副作用);
342
- * - 其余事件(手工回合 manualTurn)走 `append`(surface 校验 + 发布)。
343
- * 后续统一由 write-behind flush 落盘(RDB 稠密化时过滤 ignorable)。
344
- */
345
315
  function appendSeedSuffixLive(session, seedSuffix) {
346
316
  for (const event of seedSuffix) {
347
317
  if (event.ignorable === true) {
@@ -362,11 +332,6 @@ function appendSeedSuffixLive(session, seedSuffix) {
362
332
  else s.append(event.type, event.data);
363
333
  }
364
334
  }
365
- /** —— 编排服务 —— */
366
- /**
367
- * `ctx.sessionEditor`:rewind / retry / fork 的完整功能编排。
368
- * 组合 `ctx.sessionBranch`(provider 抽象)与可选的 `agents` 服务。
369
- */
370
335
  var SessionEditor = class extends Service {
371
336
  static inject = [
372
337
  "sessionBranch",
@@ -377,11 +342,9 @@ var SessionEditor = class extends Service {
377
342
  super(ctx, "sessionEditor");
378
343
  registerHttpRoutes(ctx);
379
344
  }
380
- /** 定位 `atSeq` 锚定的闭合边界(透传 provider)。 */
381
345
  readBranchPrefix(id, atSeq, mode, signal) {
382
346
  return this.ctx.sessionBranch.readBranchPrefix(id, atSeq, mode, signal);
383
347
  }
384
- /** 从持久化源派生新会话(透传 provider;不驱动 agent)。 */
385
348
  fork(sourceId, atSeq, childSessionId, meta, signal) {
386
349
  return this.ctx.sessionBranch.forkFrom(sourceId, {
387
350
  ...atSeq === void 0 ? {} : { atSeq },
@@ -389,44 +352,27 @@ var SessionEditor = class extends Service {
389
352
  ...meta === void 0 ? {} : { meta }
390
353
  }, signal);
391
354
  }
392
- /** 截断式回退:原会话回退到闭合边界(透传 provider)。 */
393
355
  rewind(id, toBoundary, signal) {
394
356
  return this.ctx.sessionBranch.rewind(id, toBoundary, signal);
395
357
  }
396
- /**
397
- * 清洗一个会话的 surface/provenance 坐标为稠密空间(透传 sessionBranch)。
398
- * 历史加载失败(坐标混叠导致 seed 校验失败)时调用,清洗后重新加载即可。
399
- * `cleanseSession` 是 rdb 实现层新增的服务面(契约层 `SessionBranch`
400
- * 没有此方法),经运行时访问。
401
- */
402
- cleanseSession(sessionId, signal) {
403
- return this.ctx.sessionBranch.cleanseSession(sessionId, signal);
404
- }
405
- /** 完整版本树投影(透传 provider 组合)。 */
406
358
  timeline(sessionId, signal) {
407
359
  return this.ctx.sessionBranch.timeline(sessionId, signal);
408
360
  }
409
- /** 编辑一个已落定文本块并从其轮次边界分支。 */
410
361
  edit(operation, signal) {
411
362
  return this.branchOperation(operation, signal);
412
363
  }
413
- /** 重生成最后一条已落定助手回复。 */
414
364
  reroll(operation, signal) {
415
365
  return this.branchOperation(operation, signal);
416
366
  }
417
- /** 重试任意历史回合。 */
418
367
  retry(operation, signal) {
419
368
  return this.branchOperation(operation, signal);
420
369
  }
421
- /** 可编辑消息块枚举(Timeline 编辑面)。 */
422
370
  async editableMessages(sessionId, signal) {
423
371
  return editableMessages(closedTurns(await this.readEvents(sessionId, signal)));
424
372
  }
425
- /** 可重试回合枚举(Timeline 重试面)。 */
426
373
  async retryableTurns(sessionId, signal) {
427
374
  return retryableTurns(closedTurns(await this.readEvents(sessionId, signal)));
428
375
  }
429
- /** 执行一个分支式操作(edit / reroll / retry)。 */
430
376
  async branchOperation(operation, signal) {
431
377
  signal?.throwIfAborted();
432
378
  const events = await this.readEvents(operation.sessionId, signal);
@@ -462,20 +408,11 @@ var SessionEditor = class extends Service {
462
408
  live: this.ctx.sessions.get(operation.sessionId) !== void 0
463
409
  };
464
410
  }
465
- /** 读取会话事件:live 优先,否则走持久化原始读取(不含合成 closers)。 */
466
411
  async readEvents(sessionId, signal) {
467
412
  const live = this.ctx.sessions.get(sessionId);
468
- if (live !== void 0) return live.events;
413
+ if (live !== void 0) return live.snapshotEvents();
469
414
  return (await this.ctx.sessionBranch.readRawEvents(sessionId, signal)).events;
470
415
  }
471
- /**
472
- * 可选 agent 驱动:优先复用现有 live agent(用户会话驻留——rewind 已截断
473
- * 其 session 内存,followup 会基于截断后历史重放),否则 `resume` 已持久化
474
- * 会话。模型配置来自 branchOperation 在 rewind 前解析的 `headerConfig`
475
- * (rewind 可能截断 request/header);缺失时回退到当前 events。无 agents
476
- * 服务、无可用模型路由或恢复失败时退化为持久化版本(已 durable)。
477
- * 返回实际排队的输入数。
478
- */
479
416
  async driveAgent(sessionId, queuedUsers, signal, headerConfig) {
480
417
  if (queuedUsers.length === 0) return 0;
481
418
  signal?.throwIfAborted();
@@ -491,7 +428,6 @@ var SessionEditor = class extends Service {
491
428
  }
492
429
  return this.queueThroughAgent(sessionId, queuedUsers, signal, provider, model);
493
430
  }
494
- /** 经 live agent(复用)或 resume(重建)排队重放输入;返回排队数。 */
495
431
  async queueThroughAgent(sessionId, queuedUsers, signal, provider, model) {
496
432
  const agents = this.ctx.get("agents");
497
433
  if (agents === void 0) return 0;
@@ -567,11 +503,7 @@ function decodeOperation(value) {
567
503
  ...record["atSeq"] === void 0 ? {} : { atSeq: integerOf(record["atSeq"], "atSeq") },
568
504
  ...record["childSessionId"] === void 0 ? {} : { childSessionId: sessionIdOf(record["childSessionId"]) }
569
505
  };
570
- case "cleanse": return {
571
- action: "cleanse",
572
- sessionId
573
- };
574
- default: throw new TypeError("action 必须是 edit、reroll、retry、rewind、fork 或 cleanse。");
506
+ default: throw new TypeError("action 必须是 edit、reroll、retry、rewind 或 fork。");
575
507
  }
576
508
  }
577
509
  function requestJson(request) {
@@ -599,7 +531,6 @@ function respondJson(response, status, value) {
599
531
  });
600
532
  response.end(JSON.stringify(value));
601
533
  }
602
- /** GET 投影:timeline + 编辑/重试面。 */
603
534
  async function readTimeline(editor, sessionId) {
604
535
  return toTimelinePayload(sessionId, await editor.timeline(sessionId), await editor.editableMessages(sessionId), await editor.retryableTurns(sessionId));
605
536
  }
@@ -639,14 +570,6 @@ async function runOperation(editor, operation) {
639
570
  sessionId: await editor.fork(operation.sessionId, operation.atSeq, operation.childSessionId),
640
571
  queuedTurns: 0
641
572
  };
642
- case "cleanse": {
643
- const { changed } = await editor.cleanseSession(operation.sessionId);
644
- return {
645
- sessionId: operation.sessionId,
646
- queuedTurns: 0,
647
- changed
648
- };
649
- }
650
573
  }
651
574
  }
652
575
  async function handleRoute(editor, request, response) {
@@ -666,7 +589,6 @@ async function handleRoute(editor, request, response) {
666
589
  respondJson(response, error instanceof TypeError ? 400 : 409, { error: message });
667
590
  }
668
591
  }
669
- /** 注册同源 HTTP 路由(`ctx.webServer` 由 dsh web 的 webserver 包提供;缺失时跳过)。 */
670
592
  function registerHttpRoutes(ctx) {
671
593
  const webServer = ctx.get("webServer");
672
594
  if (webServer === void 0) return;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["SESSION_BRANCH_VERSION_SCHEMA"],"sources":["../src/shared.ts","../src/index.ts"],"sourcesContent":["import type { SessionId } from \"@deepseek-ai/dsh-session\";\nimport type { BranchTimeline, CascadePolicy } from \"@morlay/session-branch\";\nimport type { VersionOperation } from \"@morlay/session-branch\";\n\nexport const SESSION_EDITOR_PATH = \"/session-editor\";\n\nexport type { VersionOperation } from \"@morlay/session-branch\";\n\nexport interface EditOperation {\n action: \"edit\";\n sessionId: SessionId;\n eventSeq: number;\n blockIndex: number;\n text: string;\n cascade: CascadePolicy;\n}\n\nexport interface RerollOperation {\n action: \"reroll\";\n sessionId: SessionId;\n}\n\nexport interface RetryOperation {\n action: \"retry\";\n sessionId: SessionId;\n turn: number;\n cascade: CascadePolicy;\n}\n\nexport interface RewindOperation {\n action: \"rewind\";\n sessionId: SessionId;\n toBoundary: number;\n}\n\nexport interface ForkOperation {\n action: \"fork\";\n sessionId: SessionId;\n atSeq?: number;\n childSessionId?: SessionId;\n}\n\nexport type SessionEditorOperation =\n | EditOperation\n | RerollOperation\n | RetryOperation\n | RewindOperation\n | ForkOperation;\n\nexport interface SessionEditorOperationResult {\n sessionId: SessionId;\n queuedTurns: number;\n\n live?: boolean;\n}\n\nexport interface EditableMessageBlock {\n key: string;\n turn: number;\n eventSeq: number;\n blockIndex: number;\n kind: \"user\" | \"assistant.reasoning\" | \"assistant.response\";\n text: string;\n time: number;\n}\n\nexport interface RetryableTurn {\n turn: number;\n userEventSeq: number;\n preview: string;\n time: number;\n}\n\nexport interface VersionSummary {\n sessionId: string;\n parentSessionId?: string;\n effectId?: string;\n inverseSessionId?: string;\n createdAt: number;\n depth: number;\n current: boolean;\n onCurrentEffectPath: boolean;\n operation?: VersionOperation;\n cascade?: CascadePolicy;\n targetTurn?: number;\n blockKind?: EditableMessageBlock[\"kind\"];\n before?: string;\n after?: string;\n}\n\nexport interface SessionEditorTimeline {\n sessionId: string;\n messages: EditableMessageBlock[];\n retryableTurns: RetryableTurn[];\n versions: VersionSummary[];\n\n undoStack: string[];\n\n redoSessionIds: string[];\n}\n\nexport function toTimelinePayload(\n sessionId: SessionId,\n timeline: BranchTimeline,\n messages: EditableMessageBlock[],\n retryableTurns: RetryableTurn[],\n): SessionEditorTimeline {\n const currentPath = new Set<string>();\n for (const node of timeline.nodes) currentPath.add(String(node.sessionId));\n const versions: VersionSummary[] = timeline.nodes.map((node) => ({\n sessionId: String(node.sessionId),\n ...(node.parentSessionId === undefined\n ? {}\n : { parentSessionId: String(node.parentSessionId) }),\n ...(node.effect === undefined\n ? {}\n : {\n effectId: node.effect.id,\n inverseSessionId: String(node.inverseSessionId),\n operation: node.effect.operation,\n cascade: node.effect.cascade,\n targetTurn: node.effect.targetTurn,\n ...(node.effect.blockKind === undefined ? {} : { blockKind: node.effect.blockKind }),\n ...(node.effect.before === undefined ? {} : { before: node.effect.before }),\n ...(node.effect.after === undefined ? {} : { after: node.effect.after }),\n }),\n createdAt: node.createdAt,\n depth: depthOf(timeline, node.sessionId),\n current: String(node.sessionId) === String(sessionId),\n onCurrentEffectPath: currentPath.has(String(node.sessionId)),\n }));\n const versionsById = new Map(versions.map((version) => [version.sessionId, version]));\n const undoStack: string[] = [];\n let cursor = versionsById.get(String(sessionId));\n while (cursor?.inverseSessionId !== undefined) {\n if (undoStack.includes(cursor.inverseSessionId)) break;\n undoStack.push(cursor.inverseSessionId);\n cursor = versionsById.get(cursor.inverseSessionId);\n }\n const redoSessionIds = versions\n .filter((version) => version.inverseSessionId === String(sessionId))\n .map((version) => version.sessionId);\n return {\n sessionId: String(sessionId),\n messages,\n retryableTurns,\n versions,\n undoStack,\n redoSessionIds,\n };\n}\n\nfunction depthOf(\n timeline: BranchTimeline,\n sessionId: import(\"@deepseek-ai/dsh-session\").SessionId,\n): number {\n const byId = new Map(timeline.nodes.map((node) => [String(node.sessionId), node]));\n let depth = 0;\n let cursor = byId.get(String(sessionId));\n const seen = new Set<string>();\n while (cursor?.parentSessionId !== undefined && !seen.has(String(cursor.sessionId))) {\n seen.add(String(cursor.sessionId));\n depth += 1;\n cursor = byId.get(String(cursor.parentSessionId));\n }\n return depth;\n}\n","import { Service, type Context } from \"@deepseek-ai/cordis\";\nimport type { AssistantMessage, ContentBlock, UserMessage } from \"@deepseek-ai/dsh-llm\";\nimport type {\n Session,\n SessionEvent,\n SessionId,\n SurfaceEventType,\n SurfaceIntent,\n} from \"@deepseek-ai/dsh-session\";\nimport { randomUUID } from \"node:crypto\";\nimport {\n SESSION_BRANCH_VERSION_SCHEMA,\n SessionBranchError,\n balanceRewindPrefix,\n type BranchBoundary,\n type BranchTimeline,\n type EditableBlockKind,\n type SessionBranchEffect,\n type SessionBranchVersionEvent,\n} from \"@morlay/session-branch\";\nimport type {\n EditOperation,\n EditableMessageBlock,\n RerollOperation,\n RetryOperation,\n RetryableTurn,\n SessionEditorResult,\n} from \"./types.ts\";\nimport {\n SESSION_EDITOR_PATH,\n type SessionEditorOperation,\n type SessionEditorOperationResult,\n type SessionEditorTimeline,\n toTimelinePayload,\n} from \"./shared.ts\";\n\nexport type { CascadePolicy, EditableBlockKind } from \"@morlay/session-branch\";\nexport type {\n EditableMessageBlock,\n EditOperation,\n RerollOperation,\n RetryOperation,\n RetryableTurn,\n RewindOperation,\n SessionEditorOperation,\n SessionEditorResult,\n} from \"./types.ts\";\n\nexport { closedTurns, editableMessages, retryableTurns };\nexport { SESSION_BRANCH_VERSION_SCHEMA } from \"@morlay/session-branch\";\n\nexport type { BranchTimeline, SessionBranchVersionEvent } from \"@morlay/session-branch\";\n\ndeclare module \"@deepseek-ai/cordis\" {\n interface Context {\n sessionEditor: SessionEditor;\n }\n}\n\nexport interface EditorAgent {\n readonly session: Session;\n followup(message: UserMessage): void;\n}\n\nexport interface EditorAgentHandle {\n readonly agent: EditorAgent;\n dispose(): Promise<void>;\n}\n\nexport interface EditorAgentRegistry {\n get(sessionId: SessionId): EditorAgent | undefined;\n create(options: {\n sessionId?: SessionId;\n seed?: readonly SessionEvent[];\n meta?: {\n cwd?: string;\n parentSession?: SessionId;\n seedLength?: number;\n agentPreset?: string;\n };\n agentOptions?: { provider: string; model: string; maxTokens?: number };\n }): Promise<EditorAgentHandle>;\n\n resume(options: {\n resumeSessionId: SessionId;\n agentOptions?: { provider: string; model: string; maxTokens?: number };\n }): Promise<EditorAgentHandle>;\n}\n\ninterface ClosedTurn {\n turn: number;\n startSeq: number;\n\n endSeq?: number;\n\n closed: boolean;\n user?: SessionEvent<\"user/message\">;\n assistants: SessionEvent<\"assistant/message\">[];\n}\n\nfunction closedTurns(events: readonly SessionEvent[]): ClosedTurn[] {\n const result: ClosedTurn[] = [];\n let current: Omit<ClosedTurn, \"endSeq\" | \"closed\"> | undefined;\n for (const event of events) {\n if (event.type === \"turn/start\") {\n current = { turn: event.data.turn, startSeq: event.seq, assistants: [] };\n continue;\n }\n if (current === undefined) continue;\n if (\n event.type === \"user/message\" &&\n current.user === undefined &&\n event.data.source.kind === \"user\"\n ) {\n current.user = event;\n continue;\n }\n if (event.type === \"assistant/message\" && event.data.turn === current.turn) {\n current.assistants.push(event);\n continue;\n }\n if (event.type === \"turn/end\" && event.data.turn === current.turn) {\n result.push({ ...current, endSeq: event.seq, closed: true });\n current = undefined;\n }\n }\n // 未闭合轮次(无 turn/end)也保留:user 消息已落定,编辑时 rewind 到该\n // 消息(exclusive drop)重放即可。\n if (current !== undefined) result.push({ ...current, closed: false });\n return result;\n}\n\nfunction isTextualBlock(\n block: ContentBlock | undefined,\n): block is Extract<ContentBlock, { type: \"text\" | \"reasoning\" }> {\n return block?.type === \"text\" || block?.type === \"reasoning\";\n}\n\nfunction userText(message: UserMessage): string {\n return message.content\n .filter((block): block is Extract<ContentBlock, { type: \"text\" }> => block.type === \"text\")\n .map((block) => block.text)\n .join(\"\\n\");\n}\n\nfunction cloneUser(\n message: UserMessage,\n content: ContentBlock[] = structuredClone(message.content),\n): UserMessage {\n return Object.freeze({\n id: randomUUID(),\n role: \"user\",\n content: Object.freeze(content),\n source: Object.freeze({ kind: \"user\" }),\n }) as UserMessage;\n}\n\nfunction replaceTextBlock(\n content: readonly ContentBlock[],\n blockIndex: number,\n text: string,\n): ContentBlock[] {\n const block = content[blockIndex];\n if (!isTextualBlock(block))\n throw new SessionBranchError(\"所选内容块不是可编辑文本。\", \"INVALID_BOUNDARY\");\n return content.map((candidate, index) =>\n index === blockIndex ? ({ ...candidate, text } as ContentBlock) : structuredClone(candidate),\n );\n}\n\nfunction editableMessages(turns: readonly ClosedTurn[]): EditableMessageBlock[] {\n const result: EditableMessageBlock[] = [];\n for (const turn of turns) {\n if (turn.user !== undefined) {\n for (const [blockIndex, block] of turn.user.data.content.entries()) {\n if (block.type !== \"text\") continue;\n result.push({\n key: `${String(turn.user.seq)}:${String(blockIndex)}`,\n turn: turn.turn,\n eventSeq: turn.user.seq,\n blockIndex,\n kind: \"user\",\n text: block.text,\n time: turn.user.time,\n });\n }\n }\n // 未闭合轮次的助手消息是流式 partial,不可编辑。\n if (!turn.closed) continue;\n for (const event of turn.assistants) {\n for (const [blockIndex, block] of event.data.message.content.entries()) {\n if (!isTextualBlock(block)) continue;\n result.push({\n key: `${String(event.seq)}:${String(blockIndex)}`,\n turn: turn.turn,\n eventSeq: event.seq,\n blockIndex,\n kind: block.type === \"reasoning\" ? \"assistant.reasoning\" : \"assistant.response\",\n text: block.text,\n time: event.time,\n });\n }\n }\n }\n return result;\n}\n\nfunction retryableTurns(turns: readonly ClosedTurn[]): RetryableTurn[] {\n return turns.flatMap((turn): RetryableTurn[] =>\n // 未闭合轮次无已落定回复可重生成,不可重试。\n turn.user === undefined || !turn.closed\n ? []\n : [\n {\n turn: turn.turn,\n userEventSeq: turn.user.seq,\n preview: userText(turn.user.data),\n time: turn.user.time,\n },\n ],\n );\n}\n\nfunction downstreamUsers(turns: readonly ClosedTurn[], start: number): UserMessage[] {\n return turns\n .slice(start)\n .flatMap((turn): UserMessage[] => (turn.user === undefined ? [] : [cloneUser(turn.user.data)]));\n}\n\nfunction assistantReplacement(\n event: SessionEvent<\"assistant/message\">,\n blockIndex: number,\n text: string,\n): AssistantMessage {\n const replaced = replaceTextBlock(event.data.message.content, blockIndex, text).filter(\n (block) => block.type === \"text\" || block.type === \"reasoning\",\n );\n return Object.freeze({\n id: randomUUID(),\n role: \"assistant\",\n content: Object.freeze(replaced),\n source: Object.freeze({\n kind: \"model\",\n provider: event.data.message.source.provider,\n model: event.data.message.source.model,\n }),\n }) as AssistantMessage;\n}\n\ninterface OperationPlan {\n anchorSeq: number;\n\n rewindBoundary?: number;\n version: SessionBranchVersionEvent;\n\n manualTurn?: { turn: number; user: UserMessage; assistant: AssistantMessage };\n\n queuedUsers: UserMessage[];\n}\n\nfunction pairVersionEffect(\n sourceSessionId: SessionId,\n effect: Omit<SessionBranchEffect, \"id\">,\n): SessionBranchVersionEvent {\n return {\n schemaVersion: SESSION_BRANCH_VERSION_SCHEMA,\n effect: { ...effect, id: randomUUID() },\n inverse: { kind: \"restore-version\", sessionId: sourceSessionId },\n };\n}\n\nfunction editPlan(operation: EditOperation, turns: readonly ClosedTurn[]): OperationPlan {\n const turnIndex = turns.findIndex(\n (turn) =>\n operation.eventSeq > turn.startSeq &&\n (turn.endSeq === undefined || operation.eventSeq < turn.endSeq),\n );\n const turn = turns[turnIndex];\n if (turn === undefined)\n throw new SessionBranchError(\"所选消息不属于已落定回合。\", \"INVALID_BOUNDARY\");\n const event =\n turn.user?.seq === operation.eventSeq\n ? turn.user\n : turn.assistants.find((candidate) => candidate.seq === operation.eventSeq);\n if (event === undefined)\n throw new SessionBranchError(\"所选消息不存在或不可编辑。\", \"INVALID_BOUNDARY\");\n\n if (event.type === \"user/message\") {\n const before = event.data.content[operation.blockIndex];\n if (before?.type !== \"text\")\n throw new SessionBranchError(\"所选用户消息块不是文本。\", \"INVALID_BOUNDARY\");\n const edited = cloneUser(\n event.data,\n replaceTextBlock(event.data.content, operation.blockIndex, operation.text),\n );\n const later = operation.cascade === \"preserve\" ? downstreamUsers(turns, turnIndex + 1) : [];\n return {\n anchorSeq: turn.startSeq,\n // 未闭合轮次:rewind 到该 user 消息(exclusive drop),由编辑版替换;\n // 闭合轮次走前一轮 turn/end 的 inclusive 语义。\n ...(turn.closed ? {} : { rewindBoundary: event.seq }),\n version: pairVersionEffect(operation.sessionId, {\n operation: \"edit\",\n cascade: operation.cascade,\n targetTurn: turn.turn,\n targetEventSeq: event.seq,\n targetBlockIndex: operation.blockIndex,\n blockKind: \"user\",\n before: before.text,\n after: operation.text,\n }),\n queuedUsers: [edited, ...later],\n };\n }\n\n // 未闭合轮次的助手消息是流式 partial,无最终内容可编辑。\n if (!turn.closed)\n throw new SessionBranchError(\"未闭合轮次的助手消息不可编辑。\", \"INVALID_BOUNDARY\");\n const before = event.data.message.content[operation.blockIndex];\n if (!isTextualBlock(before))\n throw new SessionBranchError(\"所选助手消息块不是文本或思考。\", \"INVALID_BOUNDARY\");\n const blockKind: EditableBlockKind =\n before.type === \"reasoning\" ? \"assistant.reasoning\" : \"assistant.response\";\n if (turn.user === undefined)\n throw new SessionBranchError(\"所选助手消息没有可重建的用户输入。\", \"INVALID_BOUNDARY\");\n return {\n anchorSeq: turn.startSeq,\n version: pairVersionEffect(operation.sessionId, {\n operation: \"edit\",\n cascade: operation.cascade,\n targetTurn: turn.turn,\n targetEventSeq: event.seq,\n targetBlockIndex: operation.blockIndex,\n blockKind,\n before: before.text,\n after: operation.text,\n }),\n manualTurn: {\n turn: turn.turn,\n user: cloneUser(turn.user.data),\n assistant: assistantReplacement(event, operation.blockIndex, operation.text),\n },\n queuedUsers: operation.cascade === \"preserve\" ? downstreamUsers(turns, turnIndex + 1) : [],\n };\n}\n\nfunction retryPlan(operation: RetryOperation, turns: readonly ClosedTurn[]): OperationPlan {\n const turnIndex = turns.findIndex((turn) => turn.turn === operation.turn);\n const turn = turns[turnIndex];\n if (turn?.user === undefined)\n throw new SessionBranchError(\"所选回合没有可重放的用户输入。\", \"INVALID_BOUNDARY\");\n return {\n anchorSeq: turn.startSeq,\n version: pairVersionEffect(operation.sessionId, {\n operation: \"retry\",\n cascade: operation.cascade,\n targetTurn: turn.turn,\n targetEventSeq: turn.user.seq,\n }),\n queuedUsers:\n operation.cascade === \"preserve\"\n ? downstreamUsers(turns, turnIndex)\n : [cloneUser(turn.user.data)],\n };\n}\n\nfunction rerollPlan(operation: RerollOperation, turns: readonly ClosedTurn[]): OperationPlan {\n for (let index = turns.length - 1; index >= 0; index -= 1) {\n const turn = turns[index];\n // 未闭合轮次无已落定的助手回复可重生成。\n if (turn?.user === undefined || !turn.closed) continue;\n const target = turn.assistants.findLast((event) =>\n event.data.message.content.some(isTextualBlock),\n );\n if (target === undefined) continue;\n return {\n anchorSeq: turn.startSeq,\n version: pairVersionEffect(operation.sessionId, {\n operation: \"reroll\",\n cascade: \"truncate\",\n targetTurn: turn.turn,\n targetEventSeq: target.seq,\n }),\n queuedUsers: [cloneUser(turn.user.data)],\n };\n }\n throw new SessionBranchError(\"当前会话没有可重生成的已落定助手回复。\", \"INVALID_BOUNDARY\");\n}\n\nfunction appendLogSeedEvent(\n events: SessionEvent[],\n type: string,\n data: unknown,\n ignorable = false,\n): void {\n events.push({\n type: type as SessionEvent[\"type\"],\n seq: events.length,\n time: Date.now(),\n data: data as SessionEvent[\"data\"],\n ...(ignorable ? { ignorable: true as const } : {}),\n } as SessionEvent);\n}\n\nfunction appendSurfaceSeedEvent<T extends SurfaceEventType>(\n events: SessionEvent[],\n type: T,\n data: import(\"@deepseek-ai/dsh-session\").SessionEvent<T>[\"data\"],\n intent: SurfaceIntent,\n): void {\n events.push({\n type,\n seq: events.length,\n time: Date.now(),\n data,\n surfaceOp: intent.surfaceOp,\n ...(intent.sourceEventSeqs === undefined ? {} : { sourceEventSeqs: intent.sourceEventSeqs }),\n } as SessionEvent<T>);\n}\n\nfunction appendManualTurn(\n events: SessionEvent[],\n manual: { turn: number; user: UserMessage; assistant: AssistantMessage },\n): void {\n const { turn, user, assistant } = manual;\n appendLogSeedEvent(events, \"turn/start\", { turn });\n appendSurfaceSeedEvent(events, \"user/message\", user, { surfaceOp: \"append\" });\n appendLogSeedEvent(events, \"step/start\", { turn, step: 1 });\n appendSurfaceSeedEvent(\n events,\n \"assistant/message\",\n { turn, step: 1, message: assistant },\n {\n surfaceOp: \"append\",\n sourceEventSeqs: [],\n },\n );\n appendLogSeedEvent(events, \"step/end\", { turn, step: 1 });\n appendLogSeedEvent(events, \"turn/end\", {\n turn,\n reason: { kind: \"completed\" },\n });\n}\n\nfunction appendSeedSuffixLive(session: Session, seedSuffix: readonly SessionEvent[]): void {\n for (const event of seedSuffix) {\n // 版本效果事件携带 ignorable 标记(上游类型无此字段,duck-type 读取)。\n const ignorable = (event as { ignorable?: boolean }).ignorable === true;\n if (ignorable) {\n const s = session as unknown as {\n log: SessionEvent[];\n eventsSnapshot?: unknown;\n };\n // ignorable 语义:live log 保留、不落 canonical log。session.append 不\n // 保留 ignorable 标记,因此直接 push 内存 log(不发布);seq 按 log\n // 续接重编号(seedSuffix 内部编号从 0 起)。\n s.log.push({ ...event, seq: s.log.length } as SessionEvent);\n s.eventsSnapshot = undefined;\n continue;\n }\n const s = session as unknown as {\n append(\n type: string,\n data: unknown,\n opts?: { surfaceOp?: unknown; sourceEventSeqs?: readonly number[] },\n ): SessionEvent;\n };\n const raw = event as SessionEvent & {\n surfaceOp?: unknown;\n sourceEventSeqs?: readonly number[];\n };\n if (raw.surfaceOp !== undefined) {\n s.append(event.type, event.data, {\n surfaceOp: raw.surfaceOp,\n ...(raw.sourceEventSeqs === undefined ? {} : { sourceEventSeqs: raw.sourceEventSeqs }),\n });\n } else {\n s.append(event.type, event.data);\n }\n }\n}\n\nexport class SessionEditor extends Service {\n static inject = [\"sessionBranch\", \"sessionPersistence\", \"sessions\"];\n\n constructor(ctx: Context) {\n super(ctx, \"sessionEditor\");\n // HTTP 路由随类构造注册(dsh 用 default 类插件,apply 不被调用);\n // bundles 顺序保证 webserver 先于本类实例化。\n registerHttpRoutes(ctx);\n }\n\n readBranchPrefix(\n id: SessionId,\n atSeq?: number,\n mode?: \"after\" | \"before\",\n signal?: AbortSignal,\n ): Promise<BranchBoundary> {\n return this.ctx.sessionBranch.readBranchPrefix(id, atSeq, mode, signal);\n }\n\n fork(\n sourceId: SessionId,\n atSeq?: number,\n childSessionId?: SessionId,\n meta?: { cwd?: string; agentPreset?: string },\n signal?: AbortSignal,\n ): Promise<SessionId> {\n return this.ctx.sessionBranch.forkFrom(\n sourceId,\n {\n ...(atSeq === undefined ? {} : { atSeq }),\n ...(childSessionId === undefined ? {} : { childSessionId }),\n ...(meta === undefined ? {} : { meta }),\n },\n signal,\n );\n }\n\n rewind(id: SessionId, toBoundary: number, signal?: AbortSignal) {\n return this.ctx.sessionBranch.rewind(id, toBoundary, signal);\n }\n\n timeline(sessionId: SessionId, signal?: AbortSignal): Promise<BranchTimeline> {\n return this.ctx.sessionBranch.timeline(sessionId, signal);\n }\n\n edit(operation: EditOperation, signal?: AbortSignal): Promise<SessionEditorResult> {\n return this.branchOperation(operation, signal);\n }\n\n reroll(operation: RerollOperation, signal?: AbortSignal): Promise<SessionEditorResult> {\n return this.branchOperation(operation, signal);\n }\n\n retry(operation: RetryOperation, signal?: AbortSignal): Promise<SessionEditorResult> {\n return this.branchOperation(operation, signal);\n }\n\n async editableMessages(\n sessionId: SessionId,\n signal?: AbortSignal,\n ): Promise<EditableMessageBlock[]> {\n const events = await this.readEvents(sessionId, signal);\n return editableMessages(closedTurns(events));\n }\n\n async retryableTurns(sessionId: SessionId, signal?: AbortSignal): Promise<RetryableTurn[]> {\n const events = await this.readEvents(sessionId, signal);\n return retryableTurns(closedTurns(events));\n }\n\n private async branchOperation(\n operation: EditOperation | RerollOperation | RetryOperation,\n signal?: AbortSignal,\n ): Promise<SessionEditorResult> {\n signal?.throwIfAborted();\n const events = await this.readEvents(operation.sessionId, signal);\n const turns = closedTurns(events);\n const plan =\n operation.action === \"edit\"\n ? editPlan(operation, turns)\n : operation.action === \"retry\"\n ? retryPlan(operation, turns)\n : rerollPlan(operation, turns);\n // rewind 前解析模型配置:就地编辑可能截断最后的 request/header\n // (编辑第一轮 boundary = -1 清空全部),重放 agent 需要 provider/model。\n const headerConfig = events.findLast((event) => event.type === \"request/header\")?.data.header\n .config;\n\n // 派生 seed 后缀:版本效果 + 可选手工回合。版本事件对核心是 ignorable,\n // 保证非 branch 读者可安全跳过。\n const seedSuffix: SessionEvent[] = [];\n appendLogSeedEvent(seedSuffix, \"session-branch/version\", plan.version, true);\n if (plan.manualTurn !== undefined) appendManualTurn(seedSuffix, plan.manualTurn);\n\n // 就地编辑:不创建新会话、不改变 id。先 rewind 截断到目标轮之前的闭合\n // 边界,再 append 版本效果与重放输入,最后(可选)驱动 agent 重放。\n const turnIndex = turns.findIndex((turn) => turn.startSeq === plan.anchorSeq);\n const boundary =\n plan.rewindBoundary !== undefined\n ? plan.rewindBoundary\n : turnIndex <= 0\n ? -1\n : turns[turnIndex - 1]!.endSeq!;\n const live = this.ctx.sessions.get(operation.sessionId);\n await this.ctx.sessionBranch.rewind(operation.sessionId, boundary, signal);\n if (seedSuffix.length > 0) {\n if (live !== undefined) {\n // live:版本效果 push 内存 log(ignorable 保留)、manualTurn 走 append,\n // 同步 cursor 后显式 flush(push 不发布、不进缓冲,cursor 会落后)。\n appendSeedSuffixLive(live, seedSuffix);\n this.ctx.sessionBranch.syncLiveCursor(operation.sessionId);\n await this.ctx.sessions.flush(live);\n } else {\n // cold:续写 seq 从平衡后的保留前缀接续(exclusive 截断可能残留\n // 孤儿 step/start,落盘 log 对 token meter 重放非法)。\n const rawKeepLength = boundary + (plan.rewindBoundary === undefined ? 1 : 0);\n const keepLength = balanceRewindPrefix(events.slice(0, rawKeepLength)).length;\n const renumbered = seedSuffix.map(\n (event, index) =>\n ({\n ...event,\n seq: keepLength + index,\n }) as SessionEvent,\n );\n await this.ctx.sessionPersistence.append(operation.sessionId, renumbered);\n }\n }\n\n // 可选增强:agent 驱动(重放排队用户输入)。缺失 agents 服务时退化为\n // 已 durable 的就地版本。\n const queuedTurns = await this.driveAgent(\n operation.sessionId,\n plan.queuedUsers,\n signal,\n headerConfig,\n );\n return {\n sessionId: operation.sessionId,\n queuedTurns,\n // 操作后是否仍有 live owner(driveAgent 可能 resume 出 agent)。\n live: this.ctx.sessions.get(operation.sessionId) !== undefined,\n };\n }\n\n private async readEvents(\n sessionId: SessionId,\n signal?: AbortSignal,\n ): Promise<readonly SessionEvent[]> {\n const live = this.ctx.sessions.get(sessionId);\n if (live !== undefined) return live.snapshotEvents();\n // cold:读原始事件(loadStored 不补 closers)——inspect 会把未闭合 log\n // 补成闭合,编辑未闭合轮次的 user 消息会走错边界。\n const branch = this.ctx.sessionBranch as unknown as {\n readRawEvents(\n id: SessionId,\n signal?: AbortSignal,\n ): Promise<{ meta: unknown; events: readonly SessionEvent[] }>;\n };\n return (await branch.readRawEvents(sessionId, signal)).events;\n }\n\n private async driveAgent(\n sessionId: SessionId,\n queuedUsers: readonly UserMessage[],\n signal?: AbortSignal,\n headerConfig?: { provider?: string; model?: string; maxTokens?: number },\n ): Promise<number> {\n if (queuedUsers.length === 0) return 0;\n signal?.throwIfAborted();\n const agents = this.ctx.get(\"agents\") as EditorAgentRegistry | undefined;\n if (agents === undefined) return 0;\n const provider = headerConfig?.provider ?? \"\";\n const model = headerConfig?.model ?? \"\";\n if (provider.length === 0 || model.length === 0) {\n // 兜底:从当前会话 events 解析(headerConfig 未提供时)。\n const events = await this.readEvents(sessionId, signal);\n const config = events.findLast((event) => event.type === \"request/header\")?.data.header\n .config;\n const fallbackProvider = config?.provider ?? \"\";\n const fallbackModel = config?.model ?? \"\";\n if (fallbackProvider.length === 0 || fallbackModel.length === 0) return 0;\n return this.queueThroughAgent(\n sessionId,\n queuedUsers,\n signal,\n fallbackProvider,\n fallbackModel,\n );\n }\n return this.queueThroughAgent(sessionId, queuedUsers, signal, provider, model);\n }\n\n private async queueThroughAgent(\n sessionId: SessionId,\n queuedUsers: readonly UserMessage[],\n signal: AbortSignal | undefined,\n provider: string,\n model: string,\n ): Promise<number> {\n const agents = this.ctx.get(\"agents\") as EditorAgentRegistry | undefined;\n if (agents === undefined) return 0;\n // 现有 live agent:直接排队输入(其 session 内存已被 rewind 截断,\n // followup 基于截断后历史重放,不改 id、不重建)。\n const existing = agents.get(sessionId);\n if (existing !== undefined) {\n for (const message of queuedUsers) existing.followup(message);\n await this.ctx.sessions.flush(existing.session);\n return queuedUsers.length;\n }\n // cold:resume 已持久化会话(create 会因「已存在持久化日志」失败)。\n // resume 后 agent 驻留,不 dispose(dispose 会破坏客户端打开的窗口)。\n const handle = await agents\n .resume({ resumeSessionId: sessionId, agentOptions: { provider, model } })\n .catch((error: unknown) => {\n // agent 组合失败不应使已 durable 的版本失效:退化为持久化版本。\n this.ctx.logger.warn(\n \"session-editor: agent resume failed (%s); version remains durable\",\n String(error),\n );\n return undefined;\n });\n if (handle === undefined) return 0;\n for (const message of queuedUsers) handle.agent.followup(message);\n await this.ctx.sessions.flush(handle.agent.session);\n return queuedUsers.length;\n }\n}\n\nexport default SessionEditor;\n\n// ---------------------------------------------------------------------------\n// HTTP 面(host):GET /session-editor(timeline 投影)/ POST /session-editor\n// (edit | reroll | retry | rewind | fork)。\n// ---------------------------------------------------------------------------\n\ninterface HttpRequestLike {\n method?: string;\n url?: string;\n on(event: \"data\", listener: (chunk: Uint8Array | string) => void): this;\n on(event: \"end\", listener: () => void): this;\n on(event: \"error\", listener: (error: unknown) => void): this;\n}\n\ninterface HttpResponseLike {\n writeHead(status: number, headers?: Record<string, string>): unknown;\n end(body?: string): void;\n}\n\ninterface HttpServerLike {\n register(route: {\n kind: \"exact\";\n path: string;\n handler: (request: HttpRequestLike, response: HttpResponseLike) => void | Promise<void>;\n }): () => void;\n}\n\ndeclare module \"@deepseek-ai/cordis\" {\n interface Context {\n webServer: HttpServerLike;\n }\n}\n\nfunction objectValue(value: unknown): Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new TypeError(\"请求体必须是 JSON 对象。\");\n }\n return value as Record<string, unknown>;\n}\n\nfunction sessionIdOf(value: unknown): SessionId {\n if (typeof value !== \"string\" || value.length === 0)\n throw new TypeError(\"sessionId 必须是非空字符串。\");\n return value as SessionId;\n}\n\nfunction integerOf(value: unknown, name: string): number {\n if (!Number.isSafeInteger(value) || (value as number) < 0) {\n throw new TypeError(`${name} 必须是非负安全整数。`);\n }\n return value as number;\n}\n\nfunction cascadeOf(value: unknown): import(\"@morlay/session-branch\").CascadePolicy {\n if (value !== \"truncate\" && value !== \"preserve\")\n throw new TypeError(\"cascade 必须是 truncate 或 preserve。\");\n return value;\n}\n\nfunction decodeOperation(value: unknown): SessionEditorOperation {\n const record = objectValue(value);\n const sessionId = sessionIdOf(record[\"sessionId\"]);\n switch (record[\"action\"]) {\n case \"edit\":\n if (typeof record[\"text\"] !== \"string\") throw new TypeError(\"text 必须是字符串。\");\n return {\n action: \"edit\",\n sessionId,\n eventSeq: integerOf(record[\"eventSeq\"], \"eventSeq\"),\n blockIndex: integerOf(record[\"blockIndex\"], \"blockIndex\"),\n text: record[\"text\"],\n cascade: cascadeOf(record[\"cascade\"]),\n };\n case \"reroll\":\n return { action: \"reroll\", sessionId };\n case \"retry\":\n return {\n action: \"retry\",\n sessionId,\n turn: integerOf(record[\"turn\"], \"turn\"),\n cascade: cascadeOf(record[\"cascade\"]),\n };\n case \"rewind\":\n return {\n action: \"rewind\",\n sessionId,\n toBoundary: integerOf(record[\"toBoundary\"], \"toBoundary\"),\n };\n case \"fork\":\n return {\n action: \"fork\",\n sessionId,\n ...(record[\"atSeq\"] === undefined ? {} : { atSeq: integerOf(record[\"atSeq\"], \"atSeq\") }),\n ...(record[\"childSessionId\"] === undefined\n ? {}\n : { childSessionId: sessionIdOf(record[\"childSessionId\"]) }),\n };\n default:\n throw new TypeError(\"action 必须是 edit、reroll、retry、rewind 或 fork。\");\n }\n}\n\nfunction requestJson(request: HttpRequestLike): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const decoder = new TextDecoder();\n let text = \"\";\n request.on(\"data\", (chunk) => {\n text += typeof chunk === \"string\" ? chunk : decoder.decode(chunk, { stream: true });\n });\n request.on(\"end\", () => {\n try {\n text += decoder.decode();\n resolve(JSON.parse(text) as unknown);\n } catch (error) {\n reject(error);\n }\n });\n request.on(\"error\", reject);\n });\n}\n\nfunction respondJson(response: HttpResponseLike, status: number, value: unknown): void {\n response.writeHead(status, {\n \"content-type\": \"application/json; charset=utf-8\",\n \"cache-control\": \"no-store\",\n });\n response.end(JSON.stringify(value));\n}\n\nasync function readTimeline(\n editor: SessionEditor,\n sessionId: SessionId,\n): Promise<SessionEditorTimeline> {\n const timeline = await editor.timeline(sessionId);\n const messages = await editor.editableMessages(sessionId);\n const retryable = await editor.retryableTurns(sessionId);\n return toTimelinePayload(sessionId, timeline, messages, retryable);\n}\n\nasync function runOperation(\n editor: SessionEditor,\n operation: SessionEditorOperation,\n): Promise<SessionEditorOperationResult> {\n switch (operation.action) {\n case \"edit\": {\n const result = await editor.edit(operation);\n return {\n sessionId: result.sessionId,\n queuedTurns: result.queuedTurns,\n ...(result.live === undefined ? {} : { live: result.live }),\n };\n }\n case \"reroll\": {\n const result = await editor.reroll(operation);\n return {\n sessionId: result.sessionId,\n queuedTurns: result.queuedTurns,\n ...(result.live === undefined ? {} : { live: result.live }),\n };\n }\n case \"retry\": {\n const result = await editor.retry(operation);\n return {\n sessionId: result.sessionId,\n queuedTurns: result.queuedTurns,\n ...(result.live === undefined ? {} : { live: result.live }),\n };\n }\n case \"rewind\":\n await editor.rewind(operation.sessionId, operation.toBoundary);\n return { sessionId: operation.sessionId, queuedTurns: 0 };\n case \"fork\":\n return {\n sessionId: await editor.fork(\n operation.sessionId,\n operation.atSeq,\n operation.childSessionId,\n ),\n queuedTurns: 0,\n };\n }\n}\n\nasync function handleRoute(\n editor: SessionEditor,\n request: HttpRequestLike,\n response: HttpResponseLike,\n): Promise<void> {\n try {\n if (request.method === \"GET\") {\n const url = new URL(request.url ?? SESSION_EDITOR_PATH, \"http://session-editor.local\");\n const sessionId = sessionIdOf(url.searchParams.get(\"sessionId\"));\n respondJson(response, 200, await readTimeline(editor, sessionId));\n return;\n }\n if (request.method === \"POST\") {\n respondJson(\n response,\n 200,\n await runOperation(editor, decodeOperation(await requestJson(request))),\n );\n return;\n }\n response.writeHead(405);\n response.end();\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n respondJson(response, error instanceof TypeError ? 400 : 409, {\n error: message,\n });\n }\n}\n\nfunction registerHttpRoutes(ctx: Context): void {\n const webServer = ctx.get(\"webServer\") as HttpServerLike | undefined;\n if (webServer === undefined) return;\n ctx.effect(() => {\n const editor = ctx.sessionEditor;\n return webServer.register({\n kind: \"exact\",\n path: SESSION_EDITOR_PATH,\n handler: (request, response) => handleRoute(editor, request, response),\n });\n }, \"session-editor: HTTP route\");\n}\n"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { Context } from "@deepseek-ai/cordis";
2
+ //#region src/invariant.d.ts
3
+ declare const name = "ui-conversation-message-actions-invariant";
4
+ declare const inject: string[];
5
+ declare const apply: (ctx: Context) => Promise<() => void>;
6
+ //#endregion
7
+ export { apply, inject, name };
8
+ //# sourceMappingURL=invariant.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invariant.d.mts","names":[],"sources":["../src/invariant.ts"],"mappings":";;cAKa;cAEA;cAIA,QAAK,KAAS,YAAU"}
@@ -0,0 +1,10 @@
1
+ //#region src/invariant.ts
2
+ const PACKAGE_NAME = "@morlay/ui-conversation-message-actions";
3
+ const name = "ui-conversation-message-actions-invariant";
4
+ const inject = ["invariants"];
5
+ const install = () => {};
6
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
7
+ //#endregion
8
+ export { apply, inject, name };
9
+
10
+ //# sourceMappingURL=invariant.mjs.map
@@ -0,0 +1 @@
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/ui-conversation-message-actions\";\n\nexport const name = \"ui-conversation-message-actions-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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morlay/ui-conversation-message-actions",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "Rewind / retry / fork orchestration (host) plus conversation.chat.node renderer replacement (browser) — message edit / retry actions on user bubbles.",
5
5
  "keywords": [
6
6
  "conversation-chat-node",
@@ -19,47 +19,53 @@
19
19
  "url": "https://github.com/morlay/better-session.git"
20
20
  },
21
21
  "files": [
22
- "lib",
23
- "cordis.patch.yml"
22
+ "dist",
23
+ "src",
24
+ "cordis.patch.yml",
25
+ "!**/__tests__"
24
26
  ],
25
27
  "type": "module",
26
28
  "exports": {
27
29
  ".": {
28
- "types": "./lib/index.d.mts",
29
- "default": "./lib/index.mjs"
30
+ "types": "./dist/index.d.mts",
31
+ "default": "./dist/index.mjs"
30
32
  },
31
- "./client": "./lib/client.js",
33
+ "./client": "./dist/client.js",
32
34
  "./invariant": {
33
- "types": "./lib/invariant.d.mts",
34
- "default": "./lib/invariant.mjs"
35
+ "types": "./dist/invariant.d.mts",
36
+ "default": "./dist/invariant.mjs"
35
37
  },
36
38
  "./package.json": "./package.json",
37
39
  "./cordis.patch.yml": "./cordis.patch.yml"
38
40
  },
39
41
  "dependencies": {
40
- "@morlay/session-branch": "^0.0.11"
42
+ "@morlay/session-branch": "^0.0.2"
41
43
  },
42
44
  "devDependencies": {
43
- "@deepseek-ai/dsh-attachment": "^0.1.1-rc.2",
44
- "@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2",
45
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
46
- "@deepseek-ai/dsh-client-ui-attachment": "^0.1.1-rc.2",
47
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.1-rc.2",
48
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.1-rc.2",
49
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
50
- "@deepseek-ai/dsh-token-meter": "^0.1.1-rc.2",
51
45
  "@types/react": "^19.2.18",
52
46
  "@types/react-dom": "^19.2.5",
53
- "lightningcss": "^1.33.0",
47
+ "lightningcss": "^1.32.0",
54
48
  "react": "^19.2.8",
55
49
  "react-dom": "^19.2.8"
56
50
  },
57
51
  "peerDependencies": {
58
- "@deepseek-ai/cordis": "^4.0.1",
59
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
60
- "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
61
- "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
62
- "@deepseek-ai/dsh-session-persistence": "^0.1.1-rc.2"
52
+ "@deepseek-ai/cordis": "^4.0.2",
53
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.2-rc.1",
54
+ "@deepseek-ai/dsh-attachment": "^0.1.2-rc.1",
55
+ "@deepseek-ai/dsh-client-connection": "^0.1.2-rc.1",
56
+ "@deepseek-ai/dsh-client-store": "^0.1.2-rc.1",
57
+ "@deepseek-ai/dsh-client-ui-attachment": "^0.1.2-rc.1",
58
+ "@deepseek-ai/dsh-client-ui-chat": "^0.1.2-rc.1",
59
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.2-rc.1",
60
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-rc.1",
61
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-rc.1",
62
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
63
+ "@deepseek-ai/dsh-invariants": "^0.1.2-rc.1",
64
+ "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
65
+ "@deepseek-ai/dsh-session": "^0.1.2-rc.1",
66
+ "@deepseek-ai/dsh-session-persistence": "^0.1.2-rc.1",
67
+ "@deepseek-ai/dsh-session-projection": "^0.1.2-rc.1",
68
+ "@deepseek-ai/dsh-token-meter": "^0.1.2-rc.1"
63
69
  },
64
70
  "dsh": {
65
71
  "bundle": {
@@ -69,10 +75,13 @@
69
75
  "platform": "web",
70
76
  "inject": [
71
77
  "@deepseek-ai/dsh-client-connection",
72
- "@deepseek-ai/dsh-client-runtime",
73
- "@deepseek-ai/dsh-client-ui-conversation"
78
+ "@deepseek-ai/dsh-client-store",
79
+ "@deepseek-ai/dsh-client-ui-conversation",
80
+ "@deepseek-ai/dsh-client-ui-chat"
74
81
  ]
75
82
  }
76
83
  },
77
- "scripts": {}
84
+ "scripts": {
85
+ "build": "pnpm exec tsdown"
86
+ }
78
87
  }