@morlay/ui-conversation-message-actions 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,37 +1,24 @@
1
1
  # @morlay/ui-conversation-message-actions
2
2
 
3
- `rewind / retry / recall / fork` 的**编排层**:在 `@morlay/session-branch` 的 provider 抽象之上组装完整功能(产品语义
4
- 对齐 [dsh-message-edit](https://github.com/Moeblack/dsh-message-edit)),并提供**浏览器半**(client bundle):替换
5
- `conversation.chat.node` 的 `user` / `steering` 渲染(在 user 消息行内直接挂编辑 / 重试入口),并覆盖
6
- `conversation.composer.dock` 的 `stats` 行(composer 统计:修好的 token 口径 + `data-composer-stats`)。
3
+ 会话编辑的**编排层**:在 `@morlay/session-branch` 的 provider 抽象之上组装 **六个动作** `edit` / `retry` /
4
+ `reroll` / `recall` / `rewind` / `fork`(`ctx.sessionEditor`,HTTP 面一条 exact
5
+ `POST /session-editor`),并提供**浏览器半**(client bundle):替换 `conversation.chat.node` 的
6
+ `user` / `steering` 渲染(user 消息行内挂编辑 / 重试入口),覆盖 `conversation.composer.dock` 的 `stats` 行
7
+ (token 口径 + `data-composer-stats`)。产品语义对齐
8
+ [dsh-message-edit](https://github.com/Moeblack/dsh-message-edit)。
7
9
 
8
10
  ## 用法
9
11
 
10
- 装配入口是聚合层 [`@morlay/better-session`](../../bundles/better-session/README.md):由它的 bundle patch 插入本包的行并注册
11
- `ctx.sessionEditor`(本包自己没有 bundle patch,不作为独立 bundle 安装)。依赖 `ctx.sessionBranch` /
12
- `ctx.sessionPersistence`(provider 由同一聚合层装配,如 `@morlay/session-rdb`)与 `ctx.sessions`;`agents` 可选,
13
- 缺失时重放退化为「已 durable 的就地版本」。
12
+ 装配入口是聚合层 [`@morlay/better-session`](../../bundles/better-session/README.md):由它的 bundle patch 插入
13
+ 本包的行并注册 `ctx.sessionEditor`(本包没有自己的 bundle patch,不作为独立 bundle 安装)。依赖
14
+ `ctx.sessionBranch` / `ctx.sessionPersistence`(provider 由同一聚合层装配,如 `@morlay/session-rdb`)与
15
+ `ctx.sessions`;`agents` 可选,缺失时重放退化为「已 durable 的就地版本」。
14
16
 
15
17
  ```ts
16
- // host:装配后直接调服务
17
- await ctx.sessionEditor.retry({ action: "retry", sessionId, turn: 2, cascade: "truncate" });
18
- const result = await ctx.sessionEditor.retry({ sessionId, turn, cascade: "truncate" });
18
+ const result = await ctx.sessionEditor.retry({
19
+ action: "retry",
20
+ sessionId,
21
+ turn: 2,
22
+ cascade: "truncate",
23
+ });
19
24
  ```
20
-
21
- HTTP 面:`POST /session-editor`(注册面与页面侧路径口径见
22
- [设计 20260917-编排层操作语义](./.agents/designs/20260917-编排层操作语义.md))。
23
-
24
- ## 结论
25
-
26
- edit / retry / reroll 就地重写**同一会话**(session id 不变),只有 `fork` 派生新 id;`recall` 只截断并把文本
27
- 交回 composer,由用户改后自己发
28
- ([ADR 就地编辑重写同一会话而非新建会话](./.agents/adrs/20260917-就地编辑重写同一会话而非新建会话.md))。
29
-
30
- ## 文档
31
-
32
- - 操作语义全文(服务面 / 就地编辑 / agent 驱动 / 浏览器半 / 分层边界):
33
- [设计 20260917-编排层操作语义](./.agents/designs/20260917-编排层操作语义.md)
34
- - 决策:[`.agents/adrs/`](./.agents/adrs)(接管官方 `ui-conversation` 行、client bundle 单文件与 shadow 渲染、引用解析、
35
- 编辑入口门控…)
36
- - 接缝、测试落点与未覆盖:[本包规范 how-to-verify](./.agents/standards/how-to-verify.md)
37
- - 整体设计:[设计 20260917-会话编辑闭环装配](../../bundles/better-session/.agents/designs/20260917-会话编辑闭环装配.md)
package/dist/client.cjs CHANGED
@@ -10,10 +10,17 @@ window.__ModuleLoader__.load({
10
10
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
11
11
  let react_jsx_runtime = require("react/jsx-runtime");
12
12
  let react_dom = require("react-dom");
13
+ //#region src/shared.ts
14
+ const SESSION_EDITOR_PATHS = {
15
+ edit: "/api/morlay/v1/session/edit",
16
+ reroll: "/api/morlay/v1/session/reroll",
17
+ retry: "/api/morlay/v1/session/retry",
18
+ rewind: "/api/morlay/v1/session/rewind",
19
+ recall: "/api/morlay/v1/session/recall",
20
+ fork: "/api/morlay/v1/session/fork"
21
+ };
13
22
  //#endregion
14
23
  //#region src/client/controller.ts
15
- /** 编辑器的 HTTP 路径:宿主(web 与桌面)在同一张路由表上服务它,页面不再按 ownsHost 加前缀。 */
16
- const EDITOR_API_PATH = "/session-editor";
17
24
  var SessionEditorController = class {
18
25
  sessionId;
19
26
  face;
@@ -45,13 +52,14 @@ window.__ModuleLoader__.load({
45
52
  if (this.pending !== null) return false;
46
53
  this.pending = operation.action;
47
54
  try {
48
- const response = await fetch(EDITOR_API_PATH, {
55
+ const { action, ...payload } = operation;
56
+ const response = await fetch(SESSION_EDITOR_PATHS[action], {
49
57
  method: "POST",
50
58
  headers: {
51
59
  accept: "application/json",
52
60
  "content-type": "application/json"
53
61
  },
54
- body: JSON.stringify(operation)
62
+ body: JSON.stringify(payload)
55
63
  });
56
64
  const value = await response.json();
57
65
  if (!response.ok) {
@@ -71,12 +79,6 @@ window.__ModuleLoader__.load({
71
79
  this.pending = null;
72
80
  }
73
81
  }
74
- /**
75
- * 让上游重开该会话的历史窗口(rewind 之后客户端窗口的 seq 基线已经失效)。
76
- *
77
- * 探测顺序:`binding(id).session.resync()`(上游 ClientSession 的重建入口,类型面没暴露)
78
- * → `sessions.refresh()`(只刷列表元数据,聊胜于无)→ 都没有就记一条 warn。
79
- */
80
82
  async rebuildWindow() {
81
83
  const sessions = this.sessions;
82
84
  const face = sessions.binding?.(this.sessionId)?.session;
@@ -91,14 +93,6 @@ window.__ModuleLoader__.load({
91
93
  }
92
94
  console.warn("[session-editor] 未找到会话窗口重建入口(binding.resync / refresh 都不可用),窗口可能停留在 rewind 之前的状态");
93
95
  }
94
- /**
95
- * 撤回后把会话视口送回底部:rewind 把窗口换短,而上游 ChatView 只在读者已经贴底时
96
- * 才跟随(`tipMoved && atBottom`),停在中途的视口会悬在被截断的位置上;撤回的下一步
97
- * 是改完再发,所以这里无条件送到底。容器用上游既有契约 `[data-conversation-scroll]`
98
- * (ChatView / ConversationWidthControls / StatsPills 同用)。
99
- *
100
- * 窗口替换的渲染落在 resync 之后:写早了会被下一轮布局覆盖,因此等两帧再写。
101
- */
102
96
  returnViewportToEnd() {
103
97
  const scrollport = document.querySelector("[data-conversation-scroll]");
104
98
  if (scrollport === null) return;
@@ -921,18 +915,6 @@ window.__ModuleLoader__.load({
921
915
  };
922
916
  //#endregion
923
917
  //#region src/client/composer-stats/StatsPills.tsx
924
- /**
925
- * Fold assistant and tool-result nodes into window-scoped display totals —
926
- * the FALLBACK for assemblies without the `sessionStats` projection.
927
- *
928
- * Every displayed figure rides that durable whole-log projection (and token
929
- * accounting rides `tokenUsage`) because the window is paged and compaction
930
- * rewrites it; this fold answers "what is on screen" only when no projection
931
- * value is served. Its field names deliberately mirror the projection's so
932
- * the two swap wholesale.
933
- * @param nodes - snapshot nodes.
934
- * @returns fallback counts and summed wall times.
935
- */
936
918
  function deriveStats(nodes) {
937
919
  const turns = /* @__PURE__ */ new Set();
938
920
  let steps = 0;
@@ -972,11 +954,6 @@ window.__ModuleLoader__.load({
972
954
  decodeTokens
973
955
  };
974
956
  }
975
- /**
976
- * Compact duration: 45.2s under a minute, 2m42s from there on.
977
- * @param ms - duration in milliseconds.
978
- * @returns display string.
979
- */
980
957
  function formatDuration(ms, t) {
981
958
  const s = ms / 1e3;
982
959
  if (s < 60) return t("duration.compactSeconds", { seconds: Math.round(s * 10) / 10 });
@@ -986,22 +963,10 @@ window.__ModuleLoader__.load({
986
963
  seconds: whole % 60
987
964
  });
988
965
  }
989
- /**
990
- * Display-ready cache-hit share of prompt-side input over the whole durable log.
991
- * @param usage - the session's token-usage projection value.
992
- * @returns integer text when integer rounding stays below 100, otherwise the
993
- * minimum decimal precision that still rounds below 100; a full hit returns
994
- * 100, and no billed input returns null.
995
- */
996
966
  function cacheHitPercent(usage) {
997
967
  const denominator = billedInputTokens(usage);
998
968
  return formatCacheHitPercent(usage.cacheReadTokens, denominator);
999
969
  }
1000
- /**
1001
- * Sum the three disjoint prompt-side billing buckets.
1002
- * @param usage - the session's token-usage projection value.
1003
- * @returns billed input tokens.
1004
- */
1005
970
  function billedInputTokens(usage) {
1006
971
  return usage.uncachedInputTokens + usage.cacheReadTokens + usage.cacheWriteTokens;
1007
972
  }
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
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";
1
+ import { C as SessionEditorOperation, S as RewindOperation, _ as EditableMessageBlock, b as RetryOperation, c as editableMessages, g as EditOperation, h as retryableTurns, i as closedTurns, v as RecallOperation, w as SessionEditorResult, x as RetryableTurn, y as RerollOperation } from "./plan-DeCB5_cR.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";
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
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";
1
+ import { C as SessionEditorOperation, S as RewindOperation, _ as EditableMessageBlock, b as RetryOperation, c as editableMessages, g as EditOperation, h as retryableTurns, i as closedTurns, v as RecallOperation, w as SessionEditorResult, x as RetryableTurn, y as RerollOperation } from "./plan-CRswvwkb.mjs";
2
2
  import { Context, Service } from "@deepseek-ai/cordis";
3
3
  import { AgentCancelCause, Session, SessionEvent, SessionId } from "@deepseek-ai/dsh-session";
4
4
  import { BranchBoundary, CascadePolicy, EditableBlockKind } from "@morlay/session-branch";
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { t as SESSION_EDITOR_PATH } from "./shared-BBbOTwy4.mjs";
2
- import { closedTurns, droppedCompactions, editPlan, editableMessages, precedingContentIndex, recallBoundary, rerollPlan, restoreCompactions, retryPlan, retryableTurns } from "./plan.mjs";
1
+ import { t as SESSION_EDITOR_PATHS } from "./shared-DG86bLrc.mjs";
2
+ import { closedTurns, droppedCompactions, editPlan, editableMessages, keptConfigEvents, 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
5
  import { SessionBranchError, balanceRewindPrefix } from "@morlay/session-branch";
@@ -107,6 +107,7 @@ var SessionEditor = class extends Service {
107
107
  const boundary = plan.rewindBoundary !== void 0 ? plan.rewindBoundary : preceding < 0 ? -1 : turns[preceding].endSeq;
108
108
  const keepFrom = keepFromOf(events, boundary);
109
109
  const compactions = droppedCompactions(events, keepFrom, plan.targetSeq);
110
+ const configs = keptConfigEvents(events, keepFrom, plan.targetSeq);
110
111
  const replayTurn = preceding < 0 ? 1 : turns[preceding].turn + 1;
111
112
  const manualSeed = [];
112
113
  if (plan.manualTurn !== void 0) appendManualTurn(manualSeed, {
@@ -118,7 +119,11 @@ var SessionEditor = class extends Service {
118
119
  const live = this.ctx.sessions.get(operation.sessionId);
119
120
  await this.ctx.sessionBranch.rewind(operation.sessionId, boundary, signal);
120
121
  const seedStart = this.seedStart(live, events, keepFrom);
121
- const seedSuffix = [...restoreCompactions(compactions, keepFrom, seedStart), ...manualSeed];
122
+ const seedSuffix = [
123
+ ...restoreCompactions(compactions, keepFrom, seedStart),
124
+ ...configs,
125
+ ...manualSeed
126
+ ];
122
127
  await this.appendSeedSuffix(operation.sessionId, live, seedSuffix, events, keepFrom);
123
128
  let queuedTurns = 0;
124
129
  if (replay.agent !== void 0 && plan.queuedUsers.length > 0) {
@@ -143,10 +148,11 @@ var SessionEditor = class extends Service {
143
148
  const boundary = recallBoundary(events, closedTurns(events), operation.eventSeq);
144
149
  const keepFrom = keepFromOf(events, boundary);
145
150
  const compactions = droppedCompactions(events, keepFrom, operation.eventSeq);
151
+ const configs = keptConfigEvents(events, keepFrom, operation.eventSeq);
146
152
  await this.stopLoop(operation.sessionId, signal);
147
153
  const live = this.ctx.sessions.get(operation.sessionId);
148
154
  await this.ctx.sessionBranch.rewind(operation.sessionId, boundary, signal);
149
- await this.appendSeedSuffix(operation.sessionId, live, restoreCompactions(compactions, keepFrom, this.seedStart(live, events, keepFrom)), events, keepFrom);
155
+ await this.appendSeedSuffix(operation.sessionId, live, [...restoreCompactions(compactions, keepFrom, this.seedStart(live, events, keepFrom)), ...configs], events, keepFrom);
150
156
  return {
151
157
  sessionId: operation.sessionId,
152
158
  queuedTurns: 0,
@@ -240,10 +246,10 @@ function cascadeOf(value) {
240
246
  if (value !== "truncate" && value !== "preserve") throw new TypeError("cascade 必须是 truncate 或 preserve。");
241
247
  return value;
242
248
  }
243
- function decodeOperation(value) {
249
+ function decodeOperation(value, action) {
244
250
  const record = objectValue(value);
245
251
  const sessionId = sessionIdOf(record["sessionId"]);
246
- switch (record["action"]) {
252
+ switch (action) {
247
253
  case "edit":
248
254
  if (typeof record["text"] !== "string") throw new TypeError("text 必须是字符串。");
249
255
  return {
@@ -354,10 +360,10 @@ async function runOperation(editor, operation) {
354
360
  };
355
361
  }
356
362
  }
357
- async function handleRoute(editor, request, response) {
363
+ async function handleRoute(editor, action, request, response) {
358
364
  try {
359
365
  if (request.method === "POST") {
360
- respondJson(response, 200, await runOperation(editor, decodeOperation(await requestJson(request))));
366
+ respondJson(response, 200, await runOperation(editor, decodeOperation(await requestJson(request), action)));
361
367
  return;
362
368
  }
363
369
  response.writeHead(405);
@@ -371,11 +377,14 @@ function registerHttpRoutes(ctx, editor) {
371
377
  ctx.inject(["webServer"], (scope) => {
372
378
  const webServer = scope.get("webServer");
373
379
  if (webServer === void 0) return;
374
- scope.effect(() => webServer.register({
375
- kind: "exact",
376
- path: SESSION_EDITOR_PATH,
377
- handler: (request, response) => handleRoute(editor, request, response)
378
- }), "session-editor: HTTP route");
380
+ for (const [action, path] of Object.entries(SESSION_EDITOR_PATHS)) {
381
+ const verb = action;
382
+ scope.effect(() => webServer.register({
383
+ kind: "exact",
384
+ path,
385
+ handler: (request, response) => handleRoute(editor, verb, request, response)
386
+ }), `session-editor: HTTP route ${path}`);
387
+ }
379
388
  });
380
389
  }
381
390
  //#endregion
@@ -95,6 +95,7 @@ interface CompactionBracket {
95
95
  end: SessionEvent;
96
96
  }
97
97
  declare function droppedCompactions(events: readonly SessionEvent[], keepFrom: number, targetSeq: number): CompactionBracket[];
98
+ declare function keptConfigEvents(events: readonly SessionEvent[], keepFrom: number, targetSeq: number): SessionEvent[];
98
99
  declare function restoreCompactions(brackets: readonly CompactionBracket[], keepFrom: number, base: number): SessionEvent[];
99
100
  //#endregion
100
- export { SessionEditorResult as C, SessionEditorOperation as S, RecallOperation as _, downstreamUsers as a, RetryableTurn as b, editableMessages as c, rerollPlan as d, restoreCompactions as f, EditableMessageBlock as g, EditOperation as h, closedTurns as i, precedingContentIndex as l, retryableTurns as m, CompactionBracket as n, droppedCompactions as o, retryPlan as p, OperationPlan as r, editPlan as s, ClosedTurn as t, recallBoundary as u, RerollOperation as v, RewindOperation as x, RetryOperation as y };
101
+ export { SessionEditorOperation as C, RewindOperation as S, EditableMessageBlock as _, downstreamUsers as a, RetryOperation as b, editableMessages as c, recallBoundary as d, rerollPlan as f, EditOperation as g, retryableTurns as h, closedTurns as i, keptConfigEvents as l, retryPlan as m, CompactionBracket as n, droppedCompactions as o, restoreCompactions as p, OperationPlan as r, editPlan as s, ClosedTurn as t, precedingContentIndex as u, RecallOperation as v, SessionEditorResult as w, RetryableTurn as x, RerollOperation as y };
@@ -95,6 +95,7 @@ interface CompactionBracket {
95
95
  end: SessionEvent;
96
96
  }
97
97
  declare function droppedCompactions(events: readonly SessionEvent[], keepFrom: number, targetSeq: number): CompactionBracket[];
98
+ declare function keptConfigEvents(events: readonly SessionEvent[], keepFrom: number, targetSeq: number): SessionEvent[];
98
99
  declare function restoreCompactions(brackets: readonly CompactionBracket[], keepFrom: number, base: number): SessionEvent[];
99
100
  //#endregion
100
- export { SessionEditorResult as C, SessionEditorOperation as S, RecallOperation as _, downstreamUsers as a, RetryableTurn as b, editableMessages as c, rerollPlan as d, restoreCompactions as f, EditableMessageBlock as g, EditOperation as h, closedTurns as i, precedingContentIndex as l, retryableTurns as m, CompactionBracket as n, droppedCompactions as o, retryPlan as p, OperationPlan as r, editPlan as s, ClosedTurn as t, recallBoundary as u, RerollOperation as v, RewindOperation as x, RetryOperation as y };
101
+ export { SessionEditorOperation as C, RewindOperation as S, EditableMessageBlock as _, downstreamUsers as a, RetryOperation as b, editableMessages as c, recallBoundary as d, rerollPlan as f, EditOperation as g, retryableTurns as h, closedTurns as i, keptConfigEvents as l, retryPlan as m, CompactionBracket as n, droppedCompactions as o, restoreCompactions as p, OperationPlan as r, editPlan as s, ClosedTurn as t, precedingContentIndex as u, RecallOperation as v, SessionEditorResult as w, RetryableTurn as x, RerollOperation as y };
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-BUTplrpz.cjs";
2
- export { ClosedTurn, CompactionBracket, OperationPlan, closedTurns, downstreamUsers, droppedCompactions, editPlan, editableMessages, precedingContentIndex, recallBoundary, rerollPlan, restoreCompactions, retryPlan, retryableTurns };
1
+ import { a as downstreamUsers, c as editableMessages, d as recallBoundary, f as rerollPlan, h as retryableTurns, i as closedTurns, l as keptConfigEvents, m as retryPlan, n as CompactionBracket, o as droppedCompactions, p as restoreCompactions, r as OperationPlan, s as editPlan, t as ClosedTurn, u as precedingContentIndex } from "./plan-DeCB5_cR.cjs";
2
+ export { ClosedTurn, CompactionBracket, OperationPlan, closedTurns, downstreamUsers, droppedCompactions, editPlan, editableMessages, keptConfigEvents, 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-BKgGPZdD.mjs";
2
- export { ClosedTurn, CompactionBracket, OperationPlan, closedTurns, downstreamUsers, droppedCompactions, editPlan, editableMessages, precedingContentIndex, recallBoundary, rerollPlan, restoreCompactions, retryPlan, retryableTurns };
1
+ import { a as downstreamUsers, c as editableMessages, d as recallBoundary, f as rerollPlan, h as retryableTurns, i as closedTurns, l as keptConfigEvents, m as retryPlan, n as CompactionBracket, o as droppedCompactions, p as restoreCompactions, r as OperationPlan, s as editPlan, t as ClosedTurn, u as precedingContentIndex } from "./plan-CRswvwkb.mjs";
2
+ export { ClosedTurn, CompactionBracket, OperationPlan, closedTurns, downstreamUsers, droppedCompactions, editPlan, editableMessages, keptConfigEvents, precedingContentIndex, recallBoundary, rerollPlan, restoreCompactions, retryPlan, retryableTurns };
package/dist/plan.mjs CHANGED
@@ -247,6 +247,18 @@ function compactionBrackets(events) {
247
247
  function droppedCompactions(events, keepFrom, targetSeq) {
248
248
  return compactionBrackets(events).filter((bracket) => bracket.start.seq >= keepFrom && bracket.end.seq < targetSeq);
249
249
  }
250
+ const CONFIG_EVENT_TYPES = /* @__PURE__ */ new Set([
251
+ "model/selection",
252
+ "permission/preset",
253
+ "approval/policy",
254
+ "sandbox/mode",
255
+ "plan/mode",
256
+ "agent-preset/selected",
257
+ "session-mode/selected"
258
+ ]);
259
+ function keptConfigEvents(events, keepFrom, targetSeq) {
260
+ return events.filter((event) => event.seq >= keepFrom && event.seq < targetSeq && CONFIG_EVENT_TYPES.has(event.type));
261
+ }
250
262
  function replacementRange(event) {
251
263
  const op = event.surfaceOp;
252
264
  if (op?.op !== "replace") return void 0;
@@ -337,4 +349,4 @@ function replacementCheckpoint(event, seq, range, sources) {
337
349
  };
338
350
  }
339
351
  //#endregion
340
- export { closedTurns, downstreamUsers, droppedCompactions, editPlan, editableMessages, precedingContentIndex, recallBoundary, rerollPlan, restoreCompactions, retryPlan, retryableTurns };
352
+ export { closedTurns, downstreamUsers, droppedCompactions, editPlan, editableMessages, keptConfigEvents, precedingContentIndex, recallBoundary, rerollPlan, restoreCompactions, retryPlan, retryableTurns };
@@ -0,0 +1,11 @@
1
+ //#region src/shared.ts
2
+ const SESSION_EDITOR_PATHS = {
3
+ edit: "/api/morlay/v1/session/edit",
4
+ reroll: "/api/morlay/v1/session/reroll",
5
+ retry: "/api/morlay/v1/session/retry",
6
+ rewind: "/api/morlay/v1/session/rewind",
7
+ recall: "/api/morlay/v1/session/recall",
8
+ fork: "/api/morlay/v1/session/fork"
9
+ };
10
+ //#endregion
11
+ export { SESSION_EDITOR_PATHS as t };
@@ -3005,7 +3005,15 @@ declare function meta(id: string, cwd?: string): SessionHeader$1;
3005
3005
  declare function oneTurnLog(): SessionEvent$1[];
3006
3006
  //#endregion
3007
3007
  //#region src/shared.d.ts
3008
- declare const SESSION_EDITOR_PATH = "/session-editor";
3008
+ declare const SESSION_EDITOR_PATHS: {
3009
+ readonly edit: "/api/morlay/v1/session/edit";
3010
+ readonly reroll: "/api/morlay/v1/session/reroll";
3011
+ readonly retry: "/api/morlay/v1/session/retry";
3012
+ readonly rewind: "/api/morlay/v1/session/rewind";
3013
+ readonly recall: "/api/morlay/v1/session/recall";
3014
+ readonly fork: "/api/morlay/v1/session/fork";
3015
+ };
3016
+ type SessionEditorAction = keyof typeof SESSION_EDITOR_PATHS;
3009
3017
  //#endregion
3010
3018
  //#region src/testing.d.ts
3011
3019
  interface Harness {
@@ -3027,4 +3035,4 @@ declare function turnLog(base: number, turn: number, opts?: {
3027
3035
  time?: number;
3028
3036
  }): SessionEvent[];
3029
3037
  //#endregion
3030
- export { Harness, SESSION_EDITOR_PATH, Session, type SessionEvent, type SessionHeader, SessionIdBrand, SessionSeq, SessionStore, TokenMeter, assistantMessage, createPersisted, harness, meta, oneTurnLog, parseJsonlArtifact, turnLog, twoTurnLog, userMessage };
3038
+ export { Harness, SESSION_EDITOR_PATHS, Session, type SessionEditorAction, type SessionEvent, type SessionHeader, SessionIdBrand, SessionSeq, SessionStore, TokenMeter, assistantMessage, createPersisted, harness, meta, oneTurnLog, parseJsonlArtifact, turnLog, twoTurnLog, userMessage };
@@ -3005,7 +3005,15 @@ declare function meta(id: string, cwd?: string): SessionHeader$1;
3005
3005
  declare function oneTurnLog(): SessionEvent$1[];
3006
3006
  //#endregion
3007
3007
  //#region src/shared.d.ts
3008
- declare const SESSION_EDITOR_PATH = "/session-editor";
3008
+ declare const SESSION_EDITOR_PATHS: {
3009
+ readonly edit: "/api/morlay/v1/session/edit";
3010
+ readonly reroll: "/api/morlay/v1/session/reroll";
3011
+ readonly retry: "/api/morlay/v1/session/retry";
3012
+ readonly rewind: "/api/morlay/v1/session/rewind";
3013
+ readonly recall: "/api/morlay/v1/session/recall";
3014
+ readonly fork: "/api/morlay/v1/session/fork";
3015
+ };
3016
+ type SessionEditorAction = keyof typeof SESSION_EDITOR_PATHS;
3009
3017
  //#endregion
3010
3018
  //#region src/testing.d.ts
3011
3019
  interface Harness {
@@ -3027,4 +3035,4 @@ declare function turnLog(base: number, turn: number, opts?: {
3027
3035
  time?: number;
3028
3036
  }): SessionEvent[];
3029
3037
  //#endregion
3030
- export { Harness, SESSION_EDITOR_PATH, Session, type SessionEvent, type SessionHeader, SessionIdBrand, SessionSeq, SessionStore, TokenMeter, assistantMessage, createPersisted, harness, meta, oneTurnLog, parseJsonlArtifact, turnLog, twoTurnLog, userMessage };
3038
+ export { Harness, SESSION_EDITOR_PATHS, Session, type SessionEditorAction, type SessionEvent, type SessionHeader, SessionIdBrand, SessionSeq, SessionStore, TokenMeter, assistantMessage, createPersisted, harness, meta, oneTurnLog, parseJsonlArtifact, turnLog, twoTurnLog, userMessage };