@morlay/ui-conversation-message-actions 0.0.11 → 0.0.13
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 +0 -6
- package/dist/client.js +831 -0
- package/dist/index.d.mts +105 -0
- package/dist/index.mjs +3 -0
- package/dist/invariant.d.mts +7 -0
- package/dist/invariant.mjs +8 -0
- package/dist/plan-Bw4zoI4N.d.mts +86 -0
- package/dist/plan.d.mts +2 -0
- package/dist/plan.mjs +225 -0
- package/dist/src-CXYW0Bc0.mjs +408 -0
- package/dist/testing.d.mts +707 -0
- package/dist/testing.mjs +23690 -0
- package/package.json +60 -31
- package/src/client/chat-node/MessageEditDialog.module.css +24 -0
- package/src/client/chat-node/MessageEditDialog.tsx +71 -0
- package/src/client/chat-node/MessageIconActions.module.css +86 -0
- package/src/client/chat-node/MessageIconActions.tsx +189 -0
- package/src/client/chat-node/MessageItem.module.css +290 -0
- package/src/client/chat-node/MessageItem.tsx +198 -0
- package/src/client/chat-node/message-chrome.ts +61 -0
- package/src/client/chat-node/register.ts +33 -0
- package/src/client/chat-node/use-calendar-day.ts +23 -0
- package/src/client/controller.ts +327 -0
- package/src/client/css-modules.d.ts +4 -0
- package/src/client/import-action.tsx +74 -0
- package/src/client/index.ts +50 -0
- package/src/index.ts +650 -0
- package/src/invariant.ts +13 -0
- package/src/plan.ts +322 -0
- package/src/shared.ts +167 -0
- package/src/testing.ts +151 -0
- package/src/types.ts +73 -0
- package/lib/client.js +0 -2243
- package/lib/client.js.map +0 -1
- package/lib/index.d.mts +0 -211
- package/lib/index.d.mts.map +0 -1
- package/lib/index.mjs +0 -685
- package/lib/index.mjs.map +0 -1
- package/lib/invariant.d.mts +0 -15
- package/lib/invariant.d.mts.map +0 -1
- package/lib/invariant.mjs +0 -22
- package/lib/invariant.mjs.map +0 -1
package/lib/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["SESSION_BRANCH_VERSION_SCHEMA"],"sources":["../src/shared.ts","../src/index.ts"],"sourcesContent":["/**\n * Host 与 client 共享的类型与常量:HTTP 路由、操作判别联合、Timeline 响应。\n *\n * @module @morlay/ui-conversation-message-actions/shared\n */\n\nimport type { SessionId } from \"@deepseek-ai/dsh-session\";\nimport type { BranchTimeline, CascadePolicy } from \"@morlay/session-branch\";\nimport type { VersionOperation } from \"@morlay/session-branch\";\n\n/** 同源 HTTP 端点(host 注册、client fetch)。 */\nexport const SESSION_EDITOR_PATH = \"/session-editor\";\n\nexport type { VersionOperation } from \"@morlay/session-branch\";\n\n/** 编辑一个已落定文本块并从其轮次边界分支。 */\nexport interface EditOperation {\n action: \"edit\";\n sessionId: SessionId;\n eventSeq: number;\n blockIndex: number;\n text: string;\n cascade: CascadePolicy;\n}\n\n/** 重生成最后一条已落定助手回复。 */\nexport interface RerollOperation {\n action: \"reroll\";\n sessionId: SessionId;\n}\n\n/** 重试任意历史回合。 */\nexport interface RetryOperation {\n action: \"retry\";\n sessionId: SessionId;\n turn: number;\n cascade: CascadePolicy;\n}\n\n/** 截断式回退:原会话回退到闭合边界。 */\nexport interface RewindOperation {\n action: \"rewind\";\n sessionId: SessionId;\n toBoundary: number;\n}\n\n/** 派生式分支:从闭合边界派生新会话。 */\nexport interface ForkOperation {\n action: \"fork\";\n sessionId: SessionId;\n atSeq?: number;\n childSessionId?: SessionId;\n}\n\n/** 清洗一个会话的 surface/provenance 坐标为稠密空间(修复历史加载失败)。 */\nexport interface CleanseOperation {\n action: \"cleanse\";\n sessionId: SessionId;\n}\n\n/** HTTP 接受的判别联合。 */\nexport type SessionEditorOperation =\n | EditOperation\n | RerollOperation\n | RetryOperation\n | RewindOperation\n | ForkOperation\n | CleanseOperation;\n\n/** 操作响应(分支式返回新版本 id;rewind 返回原 id)。 */\nexport interface SessionEditorOperationResult {\n sessionId: SessionId;\n queuedTurns: number;\n /** 操作后会话是否仍有 live owner(客户端据此决定是否重载页面)。 */\n live?: boolean;\n /** cleanse 操作实际重写的事件数。 */\n changed?: number;\n}\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\n/** 可重试回合(重试面枚举)。 */\nexport interface RetryableTurn {\n turn: number;\n userEventSeq: number;\n preview: string;\n time: number;\n}\n\n/** 版本摘要(Timeline 节点投影,值级)。 */\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\n/** GET /session-editor 的完整投影(Timeline + 编辑/重试面)。 */\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\n/** 把 {@link BranchTimeline} 投影成 client 用的 {@link SessionEditorTimeline}。 */\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\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","/**\n * 编排层 `SessionEditor`:在 `@morlay/session-branch` 的 provider 抽象之上\n * 组装 rewind / retry / fork 的**完整功能**(参考 `dsh-message-edit` 的\n * 产品语义:edit / reroll / retry + 级联策略 + 版本树)。\n *\n * 分层边界:\n * - 数据层(forkFrom / rewind / readBranchPrefix)由 `ctx.sessionBranch`\n * (provider 实现,如 `@morlay/session-rdb`)提供;\n * - 本服务只做**编排**:闭合轮次扫描、版本效果事件构造、派生 seed 组装、\n * rewind 命令透传、版本树投影;\n * - agent 驱动(重放用户输入 / 创建子 agent)是**可选增强**:`agents`\n * 服务以 duck-typed 接口使用(不硬依赖 `@deepseek-ai/dsh-agent`),\n * 缺失时退化为「创建持久化版本」——版本已 durable,之后可随时 resume。\n *\n * @module @morlay/ui-conversation-message-actions\n */\n\nimport { 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\n/** 闭合轮次折叠(纯函数,供编辑面枚举与测试)。 */\nexport { closedTurns, editableMessages, retryableTurns };\nexport { SESSION_BRANCH_VERSION_SCHEMA } from \"@morlay/session-branch\";\n\n/** 版本树投影别名(透传 `@morlay/session-branch`)。 */\nexport type { BranchTimeline, SessionBranchVersionEvent } from \"@morlay/session-branch\";\n\ndeclare module \"@deepseek-ai/cordis\" {\n interface Context {\n sessionEditor: SessionEditor;\n }\n}\n\n/** —— agent 驱动的 duck-typed 接口(不硬依赖 @deepseek-ai/dsh-agent) —— */\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 /** 从已持久化会话恢复 agent(`AgentRegistry.resume`;create 对已持久化会话失败)。 */\n resume(options: {\n resumeSessionId: SessionId;\n agentOptions?: { provider: string; model: string; maxTokens?: number };\n }): Promise<EditorAgentHandle>;\n}\n\n/** —— 闭合轮次扫描(纯函数) —— */\n\ninterface ClosedTurn {\n turn: number;\n startSeq: number;\n /** 闭合轮次的 `turn/end` seq;未闭合轮次为 undefined。 */\n endSeq?: number;\n /** 是否已闭合(有 `turn/end`)。未闭合轮次的 user 消息仍可编辑。 */\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 // 未闭合轮次(log 尾部没有 turn/end)也保留:其 user 消息已 append 落定,\n // 编辑时 rewind 到该消息(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 // 未闭合轮次不可重试(无已落定回复可重生成;UI 的 retry 按钮也要求\n // turn 已闭合)。\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\n/** —— 版本效果与派生计划 —— */\n\ninterface OperationPlan {\n /** 目标轮 startSeq(`before` 锚定用;派生点 = 该轮之前最后一个 turn/end)。 */\n anchorSeq: number;\n /**\n * 未闭合轮次 user 编辑:rewind 边界 = 该 user 消息 seq(exclusive——drop\n * 该消息及其后,由编辑版重放替换)。闭合轮次编辑不设置(boundary 走\n * 前一轮 turn/end 的 inclusive 语义)。\n */\n rewindBoundary?: number;\n version: SessionBranchVersionEvent;\n /** 助手块编辑:以编辑后内容构造的完整手工闭合回合。 */\n manualTurn?: { turn: number; user: UserMessage; assistant: AssistantMessage };\n /** 排队重放的用户输入(truncate = 目标轮输入;preserve = 目标轮起全部)。 */\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\n/** —— 种子事件构造(本地纯事件构造器;Session 构造时统一验证) —— */\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\", { turn, reason: { kind: \"completed\" } });\n}\n\n/**\n * 把派生 seed 后缀落地到 **live** 会话。上游 `Session.append` 不保留\n * `ignorable` 标记(只保留 type/data/surface 元数据),而版本效果事件必须\n * 保持 ignorable(live log 保留、不落 canonical log),因此:\n * - ignorable 事件(版本效果)直接 push 内存 log(不发布 `session/event`;\n * 服务端语义事件,客户端无需感知;surfaceManager 对非 surface 事件 fold\n * 无副作用);\n * - 其余事件(手工回合 manualTurn)走 `append`(surface 校验 + 发布)。\n * 后续统一由 write-behind flush 落盘(RDB 稠密化时过滤 ignorable)。\n */\nfunction appendSeedSuffixLive(session: Session, seedSuffix: readonly SessionEvent[]): void {\n for (const event of seedSuffix) {\n if (event.ignorable === true) {\n const s = session as unknown as {\n log: SessionEvent[];\n eventsSnapshot?: unknown;\n };\n // 版本效果:ignorable 语义(live log 保留、不落 canonical log)。\n // session.append 不保留 ignorable 标记,因此直接 push 内存 log(不发布\n // session/event;服务端语义事件,客户端无需感知;surfaceManager 对非\n // surface 事件 fold 无副作用)。seq 按 log 续接重编号(seedSuffix 内部\n // 编号从 0 起,与截断后 live log 不对齐)。\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\n/** —— 编排服务 —— */\n\n/**\n * `ctx.sessionEditor`:rewind / retry / fork 的完整功能编排。\n * 组合 `ctx.sessionBranch`(provider 抽象)与可选的 `agents` 服务。\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(ctx.n)先于本类实例化。\n registerHttpRoutes(ctx);\n }\n\n /** 定位 `atSeq` 锚定的闭合边界(透传 provider)。 */\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 /** 从持久化源派生新会话(透传 provider;不驱动 agent)。 */\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 /** 截断式回退:原会话回退到闭合边界(透传 provider)。 */\n rewind(id: SessionId, toBoundary: number, signal?: AbortSignal) {\n return this.ctx.sessionBranch.rewind(id, toBoundary, signal);\n }\n\n /**\n * 清洗一个会话的 surface/provenance 坐标为稠密空间(透传 sessionBranch)。\n * 历史加载失败(坐标混叠导致 seed 校验失败)时调用,清洗后重新加载即可。\n * `cleanseSession` 是 rdb 实现层新增的服务面(契约层 `SessionBranch`\n * 没有此方法),经运行时访问。\n */\n cleanseSession(sessionId: SessionId, signal?: AbortSignal): Promise<{ changed: number }> {\n const branch = this.ctx.sessionBranch as unknown as {\n cleanseSession(id: SessionId, signal?: AbortSignal): Promise<{ changed: number }>;\n };\n return branch.cleanseSession(sessionId, signal);\n }\n\n /** 完整版本树投影(透传 provider 组合)。 */\n timeline(sessionId: SessionId, signal?: AbortSignal): Promise<BranchTimeline> {\n return this.ctx.sessionBranch.timeline(sessionId, signal);\n }\n\n /** 编辑一个已落定文本块并从其轮次边界分支。 */\n edit(operation: EditOperation, signal?: AbortSignal): Promise<SessionEditorResult> {\n return this.branchOperation(operation, signal);\n }\n\n /** 重生成最后一条已落定助手回复。 */\n reroll(operation: RerollOperation, signal?: AbortSignal): Promise<SessionEditorResult> {\n return this.branchOperation(operation, signal);\n }\n\n /** 重试任意历史回合。 */\n retry(operation: RetryOperation, signal?: AbortSignal): Promise<SessionEditorResult> {\n return this.branchOperation(operation, signal);\n }\n\n /** 可编辑消息块枚举(Timeline 编辑面)。 */\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 /** 可重试回合枚举(Timeline 重试面)。 */\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 /** 执行一个分支式操作(edit / reroll / retry)。 */\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 层后端特判保留),保证非 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 // 就地编辑:不创建新会话、不改变 session id。先 rewind 截断原会话到\n // 目标轮之前的闭合边界(抛弃后续事件),再把版本效果与重放输入\n // append 回同一会话,最后(可选)驱动 agent 重放排队输入。\n // 未闭合轮次 user 编辑:rewind 边界 = 该 user 消息 seq(exclusive drop\n // 该消息及其后,由编辑版重放替换);闭合轮次编辑走前一轮 turn/end 的\n // inclusive 语义。\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:落地内存 log(版本效果 ignorable 保留、manualTurn 走 append),\n // 同步 coordinator cursor 后显式 flush(版本效果 push 不发布、不进\n // 缓冲,cursor 会落后 log——不 sync 则 manualTurn 的 seq 校验错位)。\n appendSeedSuffixLive(live, seedSuffix);\n this.ctx.sessionBranch.syncLiveCursor(operation.sessionId);\n await this.ctx.sessions.flush(live);\n } else {\n // rewind 后保留的事件数:turn/end inclusive = boundary + 1;\n // user/message exclusive = boundary(该消息被 drop,由编辑版替换)。\n // 与 rdb rewind 一致地平衡化:exclusive 截断可能残留未配对的\n // step/start(真实 agent-loop 的 step/start 在 user/message 之前),\n // 续写 seq 必须从平衡后的保留前缀续接,否则落盘 log 对 token meter\n // 重放非法(孤儿 step/start 使后续 step/start 报错)。\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 标记:操作后是否仍有 live owner(driveAgent 可能 resume 出 agent)。\n live: this.ctx.sessions.get(operation.sessionId) !== undefined,\n };\n }\n\n /** 读取会话事件:live 优先,否则走持久化原始读取(不含合成 closers)。 */\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.events;\n // cold:读原始事件(`loadStored`,scanRows 只做 torn-tail 切割、不补\n // closers)。`inspect` 会经 coordinator 的 `prepareCore` 给未闭合 log\n // 补合成 step/end + turn/end——未闭合轮次被掩盖成闭合,编辑未闭合轮次\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 /**\n * 可选 agent 驱动:优先复用现有 live agent(用户会话驻留——rewind 已截断\n * 其 session 内存,followup 会基于截断后历史重放),否则 `resume` 已持久化\n * 会话。模型配置来自 branchOperation 在 rewind 前解析的 `headerConfig`\n * (rewind 可能截断 request/header);缺失时回退到当前 events。无 agents\n * 服务、无可用模型路由或恢复失败时退化为持久化版本(已 durable)。\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 /** 经 live agent(复用)或 resume(重建)排队重放输入;返回排队数。 */\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\n // 内存已被 rewind 截断,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——\n // dispose 会把 session 从 store 移除,破坏客户端打开的窗口。\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)。参考 dsh-message-edit 的同源端点。\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 /** dsh web 的 HTTP route carrier(@deepseek-ai/dsh-host-webserver,`WebRoute` 协议)。 */\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 case \"cleanse\":\n return { action: \"cleanse\", sessionId };\n default:\n throw new TypeError(\"action 必须是 edit、reroll、retry、rewind、fork 或 cleanse。\");\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\n/** GET 投影:timeline + 编辑/重试面。 */\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 case \"cleanse\": {\n const { changed } = await editor.cleanseSession(operation.sessionId);\n return { sessionId: operation.sessionId, queuedTurns: 0, changed };\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, { error: message });\n }\n}\n\n/** 注册同源 HTTP 路由(`ctx.webServer` 由 dsh web 的 webserver 包提供;缺失时跳过)。 */\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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"}
|
package/lib/invariant.d.mts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Context } from "@deepseek-ai/cordis";
|
|
2
|
-
//#region src/invariant.d.ts
|
|
3
|
-
/** Cordis companion plugin name. */
|
|
4
|
-
declare const name = "ui-conversation-message-actions-invariant";
|
|
5
|
-
/** Service required before the companion can reserve package ownership. */
|
|
6
|
-
declare const inject: string[];
|
|
7
|
-
/**
|
|
8
|
-
* Register this package's invariant companion.
|
|
9
|
-
* @param ctx - Cordis context carrying the invariant service.
|
|
10
|
-
* @returns the installed registration's disposer after setup succeeds.
|
|
11
|
-
*/
|
|
12
|
-
declare const apply: (ctx: Context) => Promise<() => void>;
|
|
13
|
-
//#endregion
|
|
14
|
-
export { apply, inject, name };
|
|
15
|
-
//# sourceMappingURL=invariant.d.mts.map
|
package/lib/invariant.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"invariant.d.mts","names":[],"sources":["../src/invariant.ts"],"mappings":";;;cAWa;;cAEA;;;;;;cAcA,QAAK,KAAS,YAAU"}
|
package/lib/invariant.mjs
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
//#region src/invariant.ts
|
|
2
|
-
const PACKAGE_NAME = "@morlay/ui-conversation-message-actions";
|
|
3
|
-
/** Cordis companion plugin name. */
|
|
4
|
-
const name = "ui-conversation-message-actions-invariant";
|
|
5
|
-
/** Service required before the companion can reserve package ownership. */
|
|
6
|
-
const inject = ["invariants"];
|
|
7
|
-
/**
|
|
8
|
-
* No runtime invariant: orchestration correctness (in-place rewind/retry,
|
|
9
|
-
* version-effect ignorable semantics) is covered by editor contract tests;
|
|
10
|
-
* this package exposes no continuously observable in-process relation.
|
|
11
|
-
*/
|
|
12
|
-
const install = () => {};
|
|
13
|
-
/**
|
|
14
|
-
* Register this package's invariant companion.
|
|
15
|
-
* @param ctx - Cordis context carrying the invariant service.
|
|
16
|
-
* @returns the installed registration's disposer after setup succeeds.
|
|
17
|
-
*/
|
|
18
|
-
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
19
|
-
//#endregion
|
|
20
|
-
export { apply, inject, name };
|
|
21
|
-
|
|
22
|
-
//# sourceMappingURL=invariant.mjs.map
|
package/lib/invariant.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"invariant.mjs","names":[],"sources":["../src/invariant.ts"],"sourcesContent":["/**\n * Package-owned invariant companion for `@morlay/ui-conversation-message-actions`.\n * @module @morlay/ui-conversation-message-actions/invariant\n */\n\nimport type { Context } from \"@deepseek-ai/cordis\";\nimport type { InvariantInstaller } from \"@deepseek-ai/dsh-invariants\";\n\nconst PACKAGE_NAME = \"@morlay/ui-conversation-message-actions\";\n\n/** Cordis companion plugin name. */\nexport const name = \"ui-conversation-message-actions-invariant\";\n/** Service required before the companion can reserve package ownership. */\nexport const inject = [\"invariants\"];\n\n/**\n * No runtime invariant: orchestration correctness (in-place rewind/retry,\n * version-effect ignorable semantics) is covered by editor contract tests;\n * this package exposes no continuously observable in-process relation.\n */\nconst install: InvariantInstaller = () => {};\n\n/**\n * Register this package's invariant companion.\n * @param ctx - Cordis context carrying the invariant service.\n * @returns the installed registration's disposer after setup succeeds.\n */\nexport const apply = (ctx: Context): Promise<() => void> =>\n Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));\n"],"mappings":";AAQA,MAAM,eAAe;;AAGrB,MAAa,OAAO;;AAEpB,MAAa,SAAS,CAAC,YAAY;;;;;;AAOnC,MAAM,gBAAoC,CAAC;;;;;;AAO3C,MAAa,SAAS,QACpB,QAAQ,QAAQ,IAAI,WAAW,SAAS,cAAc,OAAO,CAAC"}
|