@morlay/ui-conversation-message-actions 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -29
- package/dist/client.cjs +12 -47
- package/dist/client.d.cts +3 -4
- package/dist/client.d.mts +3 -4
- package/dist/index.d.cts +6 -6
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +22 -13
- package/dist/invariant.d.cts +4 -5
- package/dist/invariant.d.mts +4 -5
- package/dist/{plan-BKgGPZdD.d.mts → plan-CRswvwkb.d.mts} +2 -1
- package/dist/{plan-BUTplrpz.d.cts → plan-DeCB5_cR.d.cts} +2 -1
- package/dist/plan.d.cts +2 -2
- package/dist/plan.d.mts +2 -2
- package/dist/plan.mjs +13 -1
- package/dist/rolldown-runtime-BMI-E3GI.mjs +44 -0
- package/dist/shared-DG86bLrc.mjs +11 -0
- package/dist/testing.d.cts +2041 -93
- package/dist/testing.d.mts +2040 -93
- package/dist/testing.mjs +92 -290
- package/package.json +6 -6
- package/src/client/chat-node/MessageItem.tsx +2 -4
- package/src/client/composer-stats/StatsPills.tsx +25 -50
- package/src/client/composer-stats/token-format.ts +2 -3
- package/src/client/controller.ts +15 -32
- package/src/index.ts +29 -15
- package/src/plan.ts +28 -0
- package/src/shared.ts +12 -1
- package/src/testing.ts +3 -2
- package/dist/shared-BBbOTwy4.mjs +0 -4
package/README.md
CHANGED
|
@@ -1,37 +1,24 @@
|
|
|
1
1
|
# @morlay/ui-conversation-message-actions
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
`conversation.chat.node` 的
|
|
6
|
-
`conversation.composer.dock` 的 `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
|
|
12
|
-
`ctx.sessionPersistence`(provider 由同一聚合层装配,如 `@morlay/session-rdb`)与
|
|
13
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
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(
|
|
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/client.d.cts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Context } from "@deepseek-ai/cordis";
|
|
2
2
|
//#region src/client/index.d.ts
|
|
3
|
-
declare const inject: string[];
|
|
4
|
-
declare function apply(ctx: Context): void;
|
|
5
|
-
//#endregion
|
|
6
|
-
export { apply, inject };
|
|
3
|
+
export declare const inject: string[];
|
|
4
|
+
export declare function apply(ctx: Context): void;
|
|
5
|
+
//#endregion
|
package/dist/client.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Context } from "@deepseek-ai/cordis";
|
|
2
2
|
//#region src/client/index.d.ts
|
|
3
|
-
declare const inject: string[];
|
|
4
|
-
declare function apply(ctx: Context): void;
|
|
5
|
-
//#endregion
|
|
6
|
-
export { apply, inject };
|
|
3
|
+
export declare const inject: string[];
|
|
4
|
+
export declare function apply(ctx: Context): void;
|
|
5
|
+
//#endregion
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as
|
|
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";
|
|
@@ -9,7 +9,7 @@ declare module "@deepseek-ai/cordis" {
|
|
|
9
9
|
sessionEditor: SessionEditor;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
interface EditorAgent {
|
|
12
|
+
export interface EditorAgent {
|
|
13
13
|
readonly session: Session;
|
|
14
14
|
followup(message: UserMessage): void;
|
|
15
15
|
whenIdle(): Promise<void>;
|
|
@@ -17,11 +17,11 @@ interface EditorAgent {
|
|
|
17
17
|
keepInbox?: boolean;
|
|
18
18
|
}): void;
|
|
19
19
|
}
|
|
20
|
-
interface EditorAgentHandle {
|
|
20
|
+
export interface EditorAgentHandle {
|
|
21
21
|
readonly agent: EditorAgent;
|
|
22
22
|
dispose(): Promise<void>;
|
|
23
23
|
}
|
|
24
|
-
interface EditorAgentRegistry {
|
|
24
|
+
export interface EditorAgentRegistry {
|
|
25
25
|
get(sessionId: SessionId): EditorAgent | undefined;
|
|
26
26
|
create(options: {
|
|
27
27
|
sessionId?: SessionId;
|
|
@@ -47,7 +47,7 @@ interface EditorAgentRegistry {
|
|
|
47
47
|
};
|
|
48
48
|
}): Promise<EditorAgentHandle>;
|
|
49
49
|
}
|
|
50
|
-
declare class SessionEditor extends Service {
|
|
50
|
+
export declare class SessionEditor extends Service {
|
|
51
51
|
static inject: string[];
|
|
52
52
|
constructor(ctx: Context);
|
|
53
53
|
readBranchPrefix(id: SessionId, atSeq?: number, mode?: "after" | "before", signal?: AbortSignal): Promise<BranchBoundary>;
|
|
@@ -69,4 +69,4 @@ declare class SessionEditor extends Service {
|
|
|
69
69
|
private prepareReplay;
|
|
70
70
|
}
|
|
71
71
|
//#endregion
|
|
72
|
-
export { type CascadePolicy, type EditOperation, type EditableBlockKind, type EditableMessageBlock,
|
|
72
|
+
export { type CascadePolicy, type EditOperation, type EditableBlockKind, type EditableMessageBlock, type RecallOperation, type RerollOperation, type RetryOperation, type RetryableTurn, type RewindOperation, SessionEditor as default, type SessionEditorOperation, type SessionEditorResult, closedTurns, editableMessages, retryableTurns };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as
|
|
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";
|
|
@@ -9,7 +9,7 @@ declare module "@deepseek-ai/cordis" {
|
|
|
9
9
|
sessionEditor: SessionEditor;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
interface EditorAgent {
|
|
12
|
+
export interface EditorAgent {
|
|
13
13
|
readonly session: Session;
|
|
14
14
|
followup(message: UserMessage): void;
|
|
15
15
|
whenIdle(): Promise<void>;
|
|
@@ -17,11 +17,11 @@ interface EditorAgent {
|
|
|
17
17
|
keepInbox?: boolean;
|
|
18
18
|
}): void;
|
|
19
19
|
}
|
|
20
|
-
interface EditorAgentHandle {
|
|
20
|
+
export interface EditorAgentHandle {
|
|
21
21
|
readonly agent: EditorAgent;
|
|
22
22
|
dispose(): Promise<void>;
|
|
23
23
|
}
|
|
24
|
-
interface EditorAgentRegistry {
|
|
24
|
+
export interface EditorAgentRegistry {
|
|
25
25
|
get(sessionId: SessionId): EditorAgent | undefined;
|
|
26
26
|
create(options: {
|
|
27
27
|
sessionId?: SessionId;
|
|
@@ -47,7 +47,7 @@ interface EditorAgentRegistry {
|
|
|
47
47
|
};
|
|
48
48
|
}): Promise<EditorAgentHandle>;
|
|
49
49
|
}
|
|
50
|
-
declare class SessionEditor extends Service {
|
|
50
|
+
export declare class SessionEditor extends Service {
|
|
51
51
|
static inject: string[];
|
|
52
52
|
constructor(ctx: Context);
|
|
53
53
|
readBranchPrefix(id: SessionId, atSeq?: number, mode?: "after" | "before", signal?: AbortSignal): Promise<BranchBoundary>;
|
|
@@ -69,4 +69,4 @@ declare class SessionEditor extends Service {
|
|
|
69
69
|
private prepareReplay;
|
|
70
70
|
}
|
|
71
71
|
//#endregion
|
|
72
|
-
export { type CascadePolicy, type EditOperation, type EditableBlockKind, type EditableMessageBlock,
|
|
72
|
+
export { type CascadePolicy, type EditOperation, type EditableBlockKind, type EditableMessageBlock, type RecallOperation, type RerollOperation, type RetryOperation, type RetryableTurn, type RewindOperation, SessionEditor as default, type SessionEditorOperation, type SessionEditorResult, closedTurns, editableMessages, retryableTurns };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as
|
|
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 = [
|
|
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 (
|
|
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
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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
|
package/dist/invariant.d.cts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Context } from "@deepseek-ai/cordis";
|
|
2
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 };
|
|
3
|
+
export declare const name = "ui-conversation-message-actions-invariant";
|
|
4
|
+
export declare const inject: string[];
|
|
5
|
+
export declare const apply: (ctx: Context) => Promise<() => void>;
|
|
6
|
+
//#endregion
|
package/dist/invariant.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Context } from "@deepseek-ai/cordis";
|
|
2
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 };
|
|
3
|
+
export declare const name = "ui-conversation-message-actions-invariant";
|
|
4
|
+
export declare const inject: string[];
|
|
5
|
+
export declare const apply: (ctx: Context) => Promise<() => void>;
|
|
6
|
+
//#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 {
|
|
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 {
|
|
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
|
|
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
|
|
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,44 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esmMin = (fn, res, err) => () => {
|
|
10
|
+
if (err) throw err[0];
|
|
11
|
+
try {
|
|
12
|
+
return fn && (res = fn(fn = 0)), res;
|
|
13
|
+
} catch (e) {
|
|
14
|
+
throw err = [e], e;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
18
|
+
var __exportAll = (all, no_symbols) => {
|
|
19
|
+
let target = {};
|
|
20
|
+
for (var name in all) __defProp(target, name, {
|
|
21
|
+
get: all[name],
|
|
22
|
+
enumerable: true
|
|
23
|
+
});
|
|
24
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
25
|
+
return target;
|
|
26
|
+
};
|
|
27
|
+
var __copyProps = (to, from, except, desc) => {
|
|
28
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
29
|
+
key = keys[i];
|
|
30
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
31
|
+
get: ((k) => from[k]).bind(null, key),
|
|
32
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return to;
|
|
36
|
+
};
|
|
37
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
38
|
+
value: mod,
|
|
39
|
+
enumerable: true
|
|
40
|
+
}) : target, mod));
|
|
41
|
+
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
42
|
+
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
|
|
43
|
+
//#endregion
|
|
44
|
+
export { __toCommonJS as a, __require as i, __esmMin as n, __toESM as o, __exportAll as r, __commonJSMin as t };
|
|
@@ -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 };
|