@spzxg/cli-ui 0.4.0 → 0.6.1
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 +84 -10
- package/dist/cli-ui-embed-Dk2QGHxn.js +41146 -0
- package/dist/cli-ui-index-BFpRZXn4.js +11209 -0
- package/dist/cli-ui-jszip.min-B9tqMA-e.js +2324 -0
- package/dist/cli-ui-jszip.min-DIavJzUG.js +26 -0
- package/dist/cli-ui-xlsx-BKHhqcoa.js +93 -0
- package/dist/cli-ui.css +1 -1
- package/dist/cli-ui.js +1 -1
- package/package.json +3 -1
- package/src/board/BrowserPane.tsx +396 -96
- package/src/board/ChangesPane.tsx +13 -4
- package/src/board/CliBoard.tsx +219 -37
- package/src/board/FileViewer.tsx +387 -73
- package/src/board/FilesPane.tsx +51 -4
- package/src/board/blocks.tsx +3 -2
- package/src/board/fileKind.ts +31 -0
- package/src/board/fileOps.ts +55 -0
- package/src/board/folderDownload.ts +161 -0
- package/src/board/frameQuote.ts +50 -0
- package/src/board/textLoad.ts +99 -0
- package/src/board/workspace.ts +129 -0
- package/src/board/zip.ts +85 -0
- package/src/chat/CliChat.tsx +122 -23
- package/src/chat/Composer.tsx +4 -4
- package/src/core/blocks.ts +69 -11
- package/src/core/client.ts +285 -41
- package/src/core/config.ts +18 -5
- package/src/core/conversation.ts +17 -7
- package/src/core/store.ts +340 -71
- package/src/core/textDecode.ts +24 -0
- package/src/core/types.ts +21 -6
- package/src/core/xlsx.ts +142 -0
- package/src/elements.tsx +106 -11
- package/src/index.ts +7 -2
- package/src/layout/CliSplit.tsx +53 -0
- package/src/layout/split.ts +214 -0
- package/src/msglist/CliMsgList.tsx +50 -22
- package/src/styles.css +101 -0
- package/src/ui/ErrorBoundary.tsx +38 -0
- package/src/ui/TextBlock.tsx +1 -1
- package/src/ui/Transcript.tsx +10 -5
- package/src/ui/transcriptModel.ts +66 -9
- package/dist/cli-ui-embed-D7xtcvGG.js +0 -37967
- package/dist/cli-ui-index-O0krpZBg.js +0 -13516
package/src/core/conversation.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* 界面以节点转录为主;转录还没有(没派发、节点连不上)时用轮次的 input / reply 兜底。
|
|
8
8
|
*/
|
|
9
9
|
import { isBatchSnapshot, type AskAnswers, type AskQuestion, type BatchStreamSnapshot, type BatchStreamTask, type CenterTurn, type ConversationClosedCallback, type ConversationTurnCallback, type JobStatus, type Message, type Msg, type NodeEvent, type StreamItem, type StreamSnapshot, type StreamTask, type ToolData, type TurnUsage } from "./types.js";
|
|
10
|
-
import { indexFromEnd, mergeSnapshot, toolDataOf } from "../ui/transcriptModel.js";
|
|
10
|
+
import { indexFromEnd, mergeSnapshot, prependOlder, toolDataOf } from "../ui/transcriptModel.js";
|
|
11
11
|
import { formatAnswersText } from "../ui/format.js";
|
|
12
12
|
|
|
13
13
|
export const TERMINAL_TURN = new Set(["succeeded", "failed", "cancelled", "merged"]);
|
|
@@ -68,6 +68,8 @@ export interface ConvState {
|
|
|
68
68
|
/** 节点转录(Operator 消息)。 */
|
|
69
69
|
msgs: Msg[];
|
|
70
70
|
hasTranscript: boolean;
|
|
71
|
+
/** 节点转录里比 msgs 更早、还没取的条数(实时流只给最新一段;往上翻时 store.loadOlder 分页取)。 */
|
|
72
|
+
older: number;
|
|
71
73
|
nodeRunning: boolean;
|
|
72
74
|
resolvedModel: string | null;
|
|
73
75
|
/** 上次刷新任务详情之后,实时流里累计的用量(usage 事件)。 */
|
|
@@ -89,7 +91,7 @@ export interface ConvState {
|
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
export const emptyConv = (key: string): ConvState => ({
|
|
92
|
-
key, ...parseConvKey(key), job: null, task: null, turns: [], msgs: [], hasTranscript: false, nodeRunning: false, resolvedModel: null,
|
|
94
|
+
key, ...parseConvKey(key), job: null, task: null, turns: [], msgs: [], hasTranscript: false, older: 0, nodeRunning: false, resolvedModel: null,
|
|
93
95
|
liveUsage: { fresh: 0, cacheRead: 0 }, stream: "idle", streamError: null, endReason: null, continuedBy: null, localAnswers: {},
|
|
94
96
|
batch: false, batchTask: null, remoteTaskId: null,
|
|
95
97
|
});
|
|
@@ -152,7 +154,7 @@ function focusBatchTask(conv: ConvState, task: BatchStreamTask | null): ConvStat
|
|
|
152
154
|
const batchTask = task ? { ...kept, ...task } : null;
|
|
153
155
|
return {
|
|
154
156
|
...conv, batch: true, batchTask, task: batchTask ? batchStreamTask(batchTask) : null, remoteTaskId: remote,
|
|
155
|
-
...(sameRemote ? {} : { msgs: [], hasTranscript: false, nodeRunning: false }),
|
|
157
|
+
...(sameRemote ? {} : { msgs: [], hasTranscript: false, older: 0, nodeRunning: false }),
|
|
156
158
|
};
|
|
157
159
|
}
|
|
158
160
|
|
|
@@ -175,7 +177,7 @@ function applyBatchTask(conv: ConvState, task: BatchStreamTask): ConvState {
|
|
|
175
177
|
}
|
|
176
178
|
|
|
177
179
|
// 缺字段时兜底:generation 缺省 1(按它分会话,缺了会把顺序排乱);时间缺就不显示。
|
|
178
|
-
const toMsg = (m: Message): Msg => ({ id: m.id, role: m.role, content: m.content, generation: typeof m.generation === "number" ? m.generation : 1, ...(typeof m.created_at === "number" ? { ts: m.created_at } : {}) });
|
|
180
|
+
export const toMsg = (m: Message): Msg => ({ id: m.id, role: m.role, content: m.content, generation: typeof m.generation === "number" ? m.generation : 1, ...(typeof m.created_at === "number" ? { ts: m.created_at } : {}) });
|
|
179
181
|
|
|
180
182
|
export function applyItems(conv: ConvState, items: StreamItem[]): ConvState {
|
|
181
183
|
let next = conv;
|
|
@@ -185,7 +187,8 @@ export function applyItems(conv: ConvState, items: StreamItem[]): ConvState {
|
|
|
185
187
|
if (item.type === "transcript") {
|
|
186
188
|
// 节点转录全量(连上 / 重连节点时各一次):整体替换,没变的消息保留对象引用。
|
|
187
189
|
const messages = Array.isArray(item.messages) ? item.messages.map(toMsg) : [];
|
|
188
|
-
|
|
190
|
+
const merged = mergeSnapshot(next.msgs, messages, typeof item.older === "number" ? item.older : 0);
|
|
191
|
+
next = { ...next, msgs: merged.msgs, older: merged.older, hasTranscript: true, nodeRunning: item.running === true };
|
|
189
192
|
} else if (item.type === "node") {
|
|
190
193
|
next = applyNodeEvent(next, item.event);
|
|
191
194
|
} else if (item.type === "turn") {
|
|
@@ -285,6 +288,11 @@ export function applyNodeEvent(conv: ConvState, ev: NodeEvent): ConvState {
|
|
|
285
288
|
}
|
|
286
289
|
}
|
|
287
290
|
|
|
291
|
+
/** 往上翻取到的一页更早的节点消息(旧的在前)。older:再往前还剩几条。 */
|
|
292
|
+
export function applyOlderPage(conv: ConvState, page: Message[], older: number): ConvState {
|
|
293
|
+
return { ...conv, msgs: prependOlder(conv.msgs, page.map(toMsg)), older: Math.max(0, older) };
|
|
294
|
+
}
|
|
295
|
+
|
|
288
296
|
/** 这个对话结束了:整个对话任务结束,或者只是这一个对话被关闭。 */
|
|
289
297
|
export const convEnded = (conv: Pick<ConvState, "job" | "task">) => !!conv.task?.closed || (!!conv.job && TERMINAL_JOB.has(conv.job.status));
|
|
290
298
|
|
|
@@ -312,7 +320,8 @@ export function viewMessages(conv: ConvState): Msg[] {
|
|
|
312
320
|
// 转录里的第一条用户消息、内容又不是开出会话那一轮的原文,就是它;措辞以后变了也认得出。
|
|
313
321
|
// 之后的消息里再出现这句固定语句(例如会话被重启),按原文匹配。
|
|
314
322
|
const openerText = opener ? opener.sent_input ?? opener.input : null;
|
|
315
|
-
|
|
323
|
+
// 更早的消息还没取(older > 0)时,手里的第一条用户消息不是会话的开场:不按位置认。
|
|
324
|
+
let replaced = conv.older > 0;
|
|
316
325
|
for (const m of conv.msgs) {
|
|
317
326
|
const firstUser = !replaced && m.role === "user";
|
|
318
327
|
if (firstUser) replaced = true;
|
|
@@ -378,7 +387,8 @@ function batchViewMessages(conv: ConvState): Msg[] {
|
|
|
378
387
|
const out: Msg[] = [];
|
|
379
388
|
const task = conv.batchTask;
|
|
380
389
|
const opener = task?.opener_prompt ?? null;
|
|
381
|
-
|
|
390
|
+
// 更早的消息还没取时,手里的第一条用户消息不是开场语句。
|
|
391
|
+
const firstUserId = conv.older > 0 ? undefined : conv.msgs.find((m) => m.role === "user")?.id;
|
|
382
392
|
for (let i = 0; i < conv.msgs.length; i++) {
|
|
383
393
|
const m = conv.msgs[i];
|
|
384
394
|
if (m.role === "user" && m.content.includes(CONFIRM_MARK)) {
|