lark-remote 0.5.13 → 0.5.15
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/CHANGELOG.md +31 -0
- package/dist/agent-kinds.d.ts +27 -0
- package/dist/agent-kinds.js +38 -0
- package/dist/bridge/approval-actions.d.ts +95 -0
- package/dist/bridge/approval-actions.js +104 -0
- package/dist/bridge/approval-coordinator.d.ts +13 -0
- package/dist/bridge/approval-coordinator.js +18 -0
- package/dist/bridge/final-usage.d.ts +8 -17
- package/dist/bridge/final-usage.js +1 -18
- package/dist/bridge/index.d.ts +46 -39
- package/dist/bridge/index.js +269 -240
- package/dist/bridge/queue-manager.d.ts +25 -1
- package/dist/bridge/queue-manager.js +179 -160
- package/dist/bridge/run-approval.d.ts +2 -1
- package/dist/bridge/run-usage.d.ts +21 -30
- package/dist/bridge/run-usage.js +47 -51
- package/dist/bridge/session-writeback.d.ts +3 -2
- package/dist/card/approval-render.d.ts +3 -2
- package/dist/card/approval-render.js +3 -2
- package/dist/{router → card}/card-helpers.d.ts +7 -7
- package/dist/{router → card}/card-helpers.js +8 -8
- package/dist/card/card-session.d.ts +4 -2
- package/dist/card/card-session.js +8 -6
- package/dist/card/card-shared.d.ts +1 -1
- package/dist/card/card-shared.js +1 -1
- package/dist/card/final-answer-overflow.d.ts +0 -6
- package/dist/card/final-answer-overflow.js +1 -1
- package/dist/card/run-card-session.d.ts +2 -2
- package/dist/card/run-card-session.js +2 -2
- package/dist/card/run-renderer.js +29 -30
- package/dist/card/run-state.d.ts +28 -50
- package/dist/card/run-state.js +23 -0
- package/dist/card/usage-format.d.ts +30 -0
- package/dist/{router → card}/usage-format.js +3 -10
- package/dist/clone.js +6 -1
- package/dist/config/index.d.ts +16 -20
- package/dist/config/index.js +0 -16
- package/dist/config/pi-config.js +6 -4
- package/dist/connector/index.d.ts +2 -4
- package/dist/connector/index.js +7 -11
- package/dist/{runner/dsh → dsh}/auth.js +1 -1
- package/dist/dsh/protocol.d.ts +9 -0
- package/dist/dsh/protocol.js +61 -0
- package/dist/index.js +10 -5
- package/dist/model-catalog.d.ts +14 -0
- package/dist/model-catalog.js +25 -0
- package/dist/platform/path.d.ts +9 -0
- package/dist/platform/path.js +18 -0
- package/dist/router/active-run-usage.d.ts +4 -0
- package/dist/router/active-run-usage.js +12 -0
- package/dist/router/commands/ls.js +1 -1
- package/dist/router/commands/order.js +1 -1
- package/dist/router/commands/resume.d.ts +5 -4
- package/dist/router/commands/resume.js +4 -4
- package/dist/router/commands/ws.js +1 -1
- package/dist/router/config/claude.js +2 -1
- package/dist/router/config/common/render.d.ts +5 -1
- package/dist/router/config/common/render.js +6 -13
- package/dist/router/config/dsh.d.ts +1 -1
- package/dist/router/config/index.d.ts +1 -1
- package/dist/router/config/types.d.ts +11 -3
- package/dist/router/index.d.ts +41 -11
- package/dist/router/index.js +169 -233
- package/dist/runner/agent-choices-common.d.ts +1 -1
- package/dist/runner/claude/runner.d.ts +20 -2
- package/dist/runner/claude/runner.js +2 -15
- package/dist/runner/codex/app-server/runner.d.ts +3 -1
- package/dist/runner/codex/app-server/translator.d.ts +11 -0
- package/dist/runner/codex/app-server/translator.js +56 -149
- package/dist/runner/common/acp/base-acp-runner.d.ts +19 -1
- package/dist/runner/common/acp/base-acp-runner.js +37 -3
- package/dist/runner/common/connection-based-runner.d.ts +3 -1
- package/dist/runner/common/jsonrpc/transport.js +17 -7
- package/dist/runner/dsh/client.d.ts +1 -4
- package/dist/runner/dsh/client.js +7 -55
- package/dist/runner/dsh/daemon.js +9 -2
- package/dist/runner/dsh/exit-cancel.js +1 -1
- package/dist/runner/dsh/mux-stream.js +21 -2
- package/dist/runner/dsh/runner.d.ts +21 -1
- package/dist/runner/dsh/runner.js +97 -78
- package/dist/runner/dsh/translator.d.ts +1 -1
- package/dist/runner/index.d.ts +1 -1
- package/dist/runner/kimi/acp/runner.d.ts +22 -1
- package/dist/runner/kimi/acp/runner.js +83 -60
- package/dist/runner/opencode/acp/error-monitor.d.ts +11 -0
- package/dist/runner/opencode/acp/error-monitor.js +31 -2
- package/dist/runner/opencode/acp/runner.d.ts +14 -1
- package/dist/runner/opencode/acp/runner.js +13 -2
- package/dist/runner/pi/rpc/runner.d.ts +2 -1
- package/dist/runner/probe.d.ts +1 -1
- package/dist/runner/probe.js +10 -9
- package/dist/runner/registry.d.ts +2 -1
- package/dist/runner/types.d.ts +20 -154
- package/dist/runner/types.js +4 -24
- package/dist/session/claude/session-index.d.ts +11 -4
- package/dist/session/claude/session-index.js +30 -8
- package/dist/session/claude/session-reader.d.ts +1 -1
- package/dist/session/claude/sessions.d.ts +2 -2
- package/dist/session/claude/sessions.js +41 -26
- package/dist/session/codex/rollout-reader.d.ts +1 -1
- package/dist/session/codex/rollout-reader.js +14 -13
- package/dist/session/codex/sessions.d.ts +1 -1
- package/dist/session/codex/sessions.js +4 -2
- package/dist/session/common/jsonl.js +7 -1
- package/dist/session/common/pagination.d.ts +2 -0
- package/dist/session/common/pagination.js +1 -1
- package/dist/session/common/recency.d.ts +6 -0
- package/dist/session/common/recency.js +7 -5
- package/dist/session/common/two-pass.d.ts +1 -1
- package/dist/session/common/usage-accumulator.d.ts +1 -1
- package/dist/session/dsh/sessions.d.ts +1 -1
- package/dist/session/dsh/sessions.js +37 -12
- package/dist/session/kimi/sessions.d.ts +1 -1
- package/dist/session/kimi/sessions.js +72 -27
- package/dist/session/opencode/sessions.d.ts +1 -1
- package/dist/session/opencode/sessions.js +164 -81
- package/dist/session/pi/sessions.d.ts +1 -1
- package/dist/session/pi/sessions.js +20 -7
- package/dist/session/registry.d.ts +2 -1
- package/dist/session/session-store.d.ts +1 -2
- package/dist/session/session-store.js +14 -7
- package/dist/session-contract.d.ts +178 -0
- package/dist/session-contract.js +9 -0
- package/package.json +1 -1
- package/dist/router/usage-format.d.ts +0 -60
- /package/dist/{runner/dsh → dsh}/auth.d.ts +0 -0
- /package/dist/{runner/dsh → dsh}/home.d.ts +0 -0
- /package/dist/{runner/dsh → dsh}/home.js +0 -0
- /package/dist/{runner/dsh → dsh}/types.d.ts +0 -0
- /package/dist/{runner/dsh → dsh}/types.js +0 -0
|
@@ -9,6 +9,7 @@ import { truncateMarkdownTables } from './text-truncate.js';
|
|
|
9
9
|
import { truncateUtf8 } from '../common/truncate.js';
|
|
10
10
|
import { cardButton } from './card-shared.js';
|
|
11
11
|
import { countCardElements } from './card-budget.js';
|
|
12
|
+
import { isRunActive } from './run-state.js';
|
|
12
13
|
/** Unique nonce for card button callbacks (SDK dedup + router validation). */
|
|
13
14
|
function mkNonce() {
|
|
14
15
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
@@ -156,9 +157,9 @@ export function renderApprovalAreaCompact(approval, opts) {
|
|
|
156
157
|
}
|
|
157
158
|
return elements;
|
|
158
159
|
}
|
|
159
|
-
/** 终态隐藏判定(renderApprovalArea 与 compact
|
|
160
|
+
/** 终态隐藏判定(renderApprovalArea 与 compact 共用):仍在推进的 run 不隐藏按钮。 */
|
|
160
161
|
function isTerminalHidden(opts) {
|
|
161
|
-
return !!opts?.terminal && opts.terminal
|
|
162
|
+
return !!opts?.terminal && !isRunActive(opts.terminal);
|
|
162
163
|
}
|
|
163
164
|
/**
|
|
164
165
|
* Render approval action buttons from the real protocol decision list.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* ls, ws, etc.).
|
|
2
|
+
* 卡片构造的共享工具(会话历史卡、分页条、搜索条、ls/ws 面板等)。
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* 归属 card/:这些是纯建卡函数,此前住在 router/ 导致 card→router 与
|
|
5
|
+
* bridge→router 两条反向依赖。`markdownDiv` 从 `card/collapsible.ts` 复用,
|
|
6
|
+
* 会话内容相关的 builder(如 `sessionEventPanel`)在这里单源,router 与
|
|
7
|
+
* bridge 都只调用不复制。
|
|
8
8
|
*/
|
|
9
|
-
import { markdownDiv } from '
|
|
10
|
-
import type { AgentSessionContentEvent } from '../
|
|
9
|
+
import { markdownDiv } from './collapsible.js';
|
|
10
|
+
import type { AgentSessionContentEvent } from '../session-contract.js';
|
|
11
11
|
import { formatUsageStats } from './usage-format.js';
|
|
12
12
|
type SessionUsageLike = Parameters<typeof formatUsageStats>[0];
|
|
13
13
|
export declare function sessionEventPanel(ev: AgentSessionContentEvent, index: number, totalEvents: number, tailExpandedCount?: number, agentKind?: string): object;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* ls, ws, etc.).
|
|
2
|
+
* 卡片构造的共享工具(会话历史卡、分页条、搜索条、ls/ws 面板等)。
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* 归属 card/:这些是纯建卡函数,此前住在 router/ 导致 card→router 与
|
|
5
|
+
* bridge→router 两条反向依赖。`markdownDiv` 从 `card/collapsible.ts` 复用,
|
|
6
|
+
* 会话内容相关的 builder(如 `sessionEventPanel`)在这里单源,router 与
|
|
7
|
+
* bridge 都只调用不复制。
|
|
8
8
|
*/
|
|
9
|
-
import { agentDisplayName, cardButton } from '
|
|
10
|
-
import { collapsibleMarkdownPanel, markdownDiv } from '
|
|
11
|
-
import { formatMonthDayClock } from '
|
|
9
|
+
import { agentDisplayName, cardButton } from './card-shared.js';
|
|
10
|
+
import { collapsibleMarkdownPanel, markdownDiv } from './collapsible.js';
|
|
11
|
+
import { formatMonthDayClock } from './time.js';
|
|
12
12
|
import { displayWidth, truncateMiddleToDisplayWidth } from '../common/text-width.js';
|
|
13
13
|
import { formatUsageStats } from './usage-format.js';
|
|
14
14
|
/**
|
|
@@ -107,11 +107,13 @@ export declare abstract class CardSession<S, RO = unknown> {
|
|
|
107
107
|
start(): Promise<void>;
|
|
108
108
|
settle(): Promise<StreamSettleResult>;
|
|
109
109
|
/**
|
|
110
|
-
*
|
|
110
|
+
* 渲染当前状态对应的卡片(单一渲染入口)。
|
|
111
|
+
*
|
|
112
|
+
* 所有生产子类的 renderer 都自带 stringify 级预算保护
|
|
111
113
|
* (run/bash 的 degraded/extreme 路径);发送前 Bridge 还会再走一次
|
|
112
114
|
* enforceCardBudget,因此这里不再重复裁剪。
|
|
113
115
|
*/
|
|
114
|
-
protected
|
|
116
|
+
protected renderCurrentCard(): object;
|
|
115
117
|
/**
|
|
116
118
|
* Push an update to the card. Tries controller.update first, falls back to
|
|
117
119
|
* connector.updateCard if the controller is unavailable or fails.
|
|
@@ -150,11 +150,11 @@ export class CardSession {
|
|
|
150
150
|
// those early events. The"reuse first render" optimization was
|
|
151
151
|
// rejected for this reason (premise "two renders with identical input"
|
|
152
152
|
// does not hold).
|
|
153
|
-
const stream = this.connector.streamCard(this.chatId, this.
|
|
153
|
+
const stream = this.connector.streamCard(this.chatId, this.renderCurrentCard(), async (controller) => {
|
|
154
154
|
this.controller = controller;
|
|
155
155
|
this.messageId = controller.messageId;
|
|
156
156
|
try {
|
|
157
|
-
await controller.update(this.
|
|
157
|
+
await controller.update(this.renderCurrentCard());
|
|
158
158
|
}
|
|
159
159
|
catch (error) {
|
|
160
160
|
getLogger().warn(`${this.logPrefix} initial controller update failed:`, error);
|
|
@@ -186,7 +186,7 @@ export class CardSession {
|
|
|
186
186
|
if (!this.messageId)
|
|
187
187
|
return 'unsent';
|
|
188
188
|
try {
|
|
189
|
-
await this.connector.updateCard(this.messageId, this.
|
|
189
|
+
await this.connector.updateCard(this.messageId, this.renderCurrentCard());
|
|
190
190
|
return 'updated';
|
|
191
191
|
}
|
|
192
192
|
catch (error) {
|
|
@@ -195,11 +195,13 @@ export class CardSession {
|
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
/**
|
|
198
|
-
*
|
|
198
|
+
* 渲染当前状态对应的卡片(单一渲染入口)。
|
|
199
|
+
*
|
|
200
|
+
* 所有生产子类的 renderer 都自带 stringify 级预算保护
|
|
199
201
|
* (run/bash 的 degraded/extreme 路径);发送前 Bridge 还会再走一次
|
|
200
202
|
* enforceCardBudget,因此这里不再重复裁剪。
|
|
201
203
|
*/
|
|
202
|
-
|
|
204
|
+
renderCurrentCard() {
|
|
203
205
|
return this.renderCard(this.state, this.renderOptions);
|
|
204
206
|
}
|
|
205
207
|
/**
|
|
@@ -207,7 +209,7 @@ export class CardSession {
|
|
|
207
209
|
* connector.updateCard if the controller is unavailable or fails.
|
|
208
210
|
*/
|
|
209
211
|
async updateCard() {
|
|
210
|
-
const safeCard = this.
|
|
212
|
+
const safeCard = this.renderCurrentCard();
|
|
211
213
|
if (this.controller) {
|
|
212
214
|
try {
|
|
213
215
|
await this.controller.update(safeCard);
|
package/dist/card/card-shared.js
CHANGED
|
@@ -1,7 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Split an authoritative final answer into plain-text messages without losing
|
|
3
|
-
* any content. Feishu cards have a hard size budget; a long answer must spill
|
|
4
|
-
* rather than being silently truncated inside the progress card.
|
|
5
|
-
*/
|
|
6
|
-
export declare const FINAL_ANSWER_CHUNK_BYTES = 20000;
|
|
7
1
|
export declare function splitFinalAnswer(text: string, maxBytes?: number): string[];
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* any content. Feishu cards have a hard size budget; a long answer must spill
|
|
4
4
|
* rather than being silently truncated inside the progress card.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
const FINAL_ANSWER_CHUNK_BYTES = 20_000;
|
|
7
7
|
export function splitFinalAnswer(text, maxBytes = FINAL_ANSWER_CHUNK_BYTES) {
|
|
8
8
|
if (!text || maxBytes <= 0)
|
|
9
9
|
return text ? [text] : [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CardSession, type CardChannel } from './card-session.js';
|
|
2
2
|
import type { AgentEvent } from '../runner/index.js';
|
|
3
|
-
import { type FinishMeta, type
|
|
3
|
+
import { type FinishMeta, type RunFinalTerminal, type RunState } from './run-state.js';
|
|
4
4
|
import { type RunCardRenderOptions } from './run-renderer.js';
|
|
5
5
|
export type { CardChannel as RunCardChannel };
|
|
6
6
|
export declare class RunCardSession extends CardSession<RunState, RunCardRenderOptions> {
|
|
@@ -20,5 +20,5 @@ export declare class RunCardSession extends CardSession<RunState, RunCardRenderO
|
|
|
20
20
|
protected renderCard(state: RunState, options: RunCardRenderOptions): object;
|
|
21
21
|
protected isFlushableState(): boolean;
|
|
22
22
|
push(event: AgentEvent): Promise<void>;
|
|
23
|
-
finish(terminal:
|
|
23
|
+
finish(terminal: RunFinalTerminal, meta?: FinishMeta): Promise<void>;
|
|
24
24
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CardSession } from './card-session.js';
|
|
2
|
-
import { createInitialRunState, finishRun, reduceRunState, } from './run-state.js';
|
|
2
|
+
import { createInitialRunState, finishRun, isRunActive, reduceRunState, } from './run-state.js';
|
|
3
3
|
import { renderRunCard } from './run-renderer.js';
|
|
4
4
|
export class RunCardSession extends CardSession {
|
|
5
5
|
constructor(opts) {
|
|
@@ -25,7 +25,7 @@ export class RunCardSession extends CardSession {
|
|
|
25
25
|
isFlushableState() {
|
|
26
26
|
// finish() 已转终态(done/error/interrupted/idle_timeout)时不再 patch;
|
|
27
27
|
// 'finalizing' 是非终态,in-flight/延迟 flush 仍可渲染累积事件。
|
|
28
|
-
return this.state.terminal
|
|
28
|
+
return isRunActive(this.state.terminal);
|
|
29
29
|
}
|
|
30
30
|
async push(event) {
|
|
31
31
|
// state 每事件立即 reduce(始终最新),但 updateCard 延迟到合批窗口末尾。
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRunTerminal, } from './run-state.js';
|
|
1
|
+
import { isRunActive, isRunTerminal, } from './run-state.js';
|
|
2
2
|
import { terminalToColor, terminalToLabel, newSessionButton, stopButton, compactButton, cardButton, agentDisplayName, } from './card-shared.js';
|
|
3
3
|
import { collapsibleMarkdownPanel, markdownDiv } from './collapsible.js';
|
|
4
4
|
import { toolBodyMd, toolHeaderText } from './tool-render.js';
|
|
@@ -8,7 +8,7 @@ import { countCardElements, MAX_CARD_ELEMENTS } from './card-budget.js';
|
|
|
8
8
|
import { displayWidth, truncateToDisplayWidth } from '../common/text-width.js';
|
|
9
9
|
import { isContentFilterFailure } from '../common/turn-failure.js';
|
|
10
10
|
import { formatClock, formatTimestamp } from './time.js';
|
|
11
|
-
import { formatUsageStats } from '
|
|
11
|
+
import { formatUsageStats } from './usage-format.js';
|
|
12
12
|
import { renderApprovalArea, renderApprovalAreaCompact } from './approval-render.js';
|
|
13
13
|
const REASONING_BYTES = 4_500;
|
|
14
14
|
const TEXT_BYTES = 10_000;
|
|
@@ -406,7 +406,7 @@ const EXTREME_TIER = {
|
|
|
406
406
|
function actionButtonList(state, options) {
|
|
407
407
|
const actionButtons = [];
|
|
408
408
|
// finalizing 也显示停止按钮(进程未退出,用户可 /stop)
|
|
409
|
-
const showStop = state.terminal
|
|
409
|
+
const showStop = isRunActive(state.terminal);
|
|
410
410
|
if (showStop) {
|
|
411
411
|
actionButtons.push(stopButton(state.runId));
|
|
412
412
|
}
|
|
@@ -1137,13 +1137,12 @@ function buildSummaryContent(state, options = {}) {
|
|
|
1137
1137
|
}
|
|
1138
1138
|
}
|
|
1139
1139
|
else if (state.terminal === 'interrupted') {
|
|
1140
|
-
//
|
|
1141
|
-
//
|
|
1142
|
-
//
|
|
1143
|
-
// 必须活到终态渲染(2026-08-15 事故回归)。
|
|
1140
|
+
// 中断来源三元:审批超时 / 用户取消审批 / 用户主动终止。
|
|
1141
|
+
// 显式原因优先:approvalExpired 是粘性标记(cancel 语义下 agent 可能继续跑),
|
|
1142
|
+
// 用户随后主动 /stop 时若仍按过期渲染,就把「我自己停的」误报成自动取消。
|
|
1144
1143
|
const expiredApproval = state.interruptedReason === 'approval_timeout' ||
|
|
1145
|
-
state.
|
|
1146
|
-
|
|
1144
|
+
(state.interruptedReason === undefined &&
|
|
1145
|
+
(state.approvalExpired === true || (state.approvals ?? []).some((a) => a.expired)));
|
|
1147
1146
|
elements.push(markdownDiv(expiredApproval
|
|
1148
1147
|
? '⏰ **审批超时未响应,已自动取消**'
|
|
1149
1148
|
: state.interruptedReason === 'approval_cancelled'
|
|
@@ -1165,31 +1164,21 @@ function buildSummaryContent(state, options = {}) {
|
|
|
1165
1164
|
: state.operationKind === 'compaction'
|
|
1166
1165
|
? '\n\n🗜 Compact 完成'
|
|
1167
1166
|
: '\n\n(未返回内容)';
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
totalTokens: state.totalTokens,
|
|
1176
|
-
inputTokens: state.inputTokens,
|
|
1177
|
-
outputTokens: state.outputTokens,
|
|
1178
|
-
cumulativeTotalTokens: state.cumulativeTotalTokens,
|
|
1179
|
-
cumulativeInputTokens: state.cumulativeInputTokens,
|
|
1180
|
-
cumulativeOutputTokens: state.cumulativeOutputTokens,
|
|
1181
|
-
cumulativeCacheReadTokens: state.cumulativeCacheReadTokens,
|
|
1182
|
-
cumulativeCacheCreationTokens: state.cumulativeCacheCreationTokens,
|
|
1183
|
-
model: state.model,
|
|
1184
|
-
costUsd: state.costUsd,
|
|
1185
|
-
reasoningTokens: state.reasoningTokens,
|
|
1186
|
-
}, {
|
|
1167
|
+
// goal 本 run 读不到(known=false)时不能写「已完成」:这是 GoalStateEvent
|
|
1168
|
+
// 契约里明令禁止的推断(读不到 ≠ 没有目标)。run 本身成功,只是目标维度未知。
|
|
1169
|
+
const goalUnknown = state.terminal === 'done' && state.goalKnown === false;
|
|
1170
|
+
// RunState 的用量字段就是 formatUsageStats 的入参形态(同为
|
|
1171
|
+
// `UsageSnapshot`)——原先这里逐字段抄了 17 行,加一个字段要同时改
|
|
1172
|
+
// RunState、FinishMeta 和这张清单(§9.21)。
|
|
1173
|
+
const usageStatsStr = formatUsageStats(state, {
|
|
1187
1174
|
showResult: true,
|
|
1188
1175
|
result,
|
|
1189
1176
|
// 本轮结束但目标继续:不能报"已完成",也不能说"出错"。
|
|
1190
1177
|
...(state.terminal === 'goal_continuing'
|
|
1191
1178
|
? { completedLabel: '⏳ 本轮结束 · 目标仍在继续' }
|
|
1192
|
-
:
|
|
1179
|
+
: goalUnknown
|
|
1180
|
+
? { completedLabel: '✅ 本轮完成 · 目标状态未确认' }
|
|
1181
|
+
: {}),
|
|
1193
1182
|
});
|
|
1194
1183
|
elements.push(markdownDiv(usageStatsStr + empty));
|
|
1195
1184
|
// 后台任务:跨 turn 生命周期,必须显式告知并可逐个停止。
|
|
@@ -1317,7 +1306,17 @@ function headerTitle(state, options = {}) {
|
|
|
1317
1306
|
if (state.terminal === 'goal_continuing')
|
|
1318
1307
|
return `⏳ ${agent} · 本轮结束(目标继续)`;
|
|
1319
1308
|
if (state.terminal === 'done') {
|
|
1320
|
-
|
|
1309
|
+
// goal 维度优先于「完成」:blocked/paused 不是任务做完了,complete 才是;
|
|
1310
|
+
// 读不到(goalKnown=false)时也不能替宿主宣布完成。
|
|
1311
|
+
if (state.goal?.phase === 'complete')
|
|
1312
|
+
return `✅ ${agent} · 目标已完成`;
|
|
1313
|
+
if (state.goal?.phase === 'blocked')
|
|
1314
|
+
return `⛔ ${agent} · 目标被阻断`;
|
|
1315
|
+
if (state.goal?.phase === 'paused')
|
|
1316
|
+
return `⏸ ${agent} · 目标已暂停`;
|
|
1317
|
+
if (state.goalKnown === false)
|
|
1318
|
+
return `✅ ${agent} · 完成(目标未确认)`;
|
|
1319
|
+
return `✅ ${agent} · 已完成`;
|
|
1321
1320
|
}
|
|
1322
1321
|
if (state.terminal === 'error')
|
|
1323
1322
|
return `⚠️ ${agent} · 出错`;
|
package/dist/card/run-state.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentEvent, ApprovalView, ToolHint, GoalView } from '../runner/index.js';
|
|
2
|
+
import type { UsageSnapshot } from '../session-contract.js';
|
|
2
3
|
export type RunTerminal = 'running' | 'finalizing' | 'done' | 'error' | 'interrupted' | 'idle_timeout'
|
|
3
4
|
/**
|
|
4
5
|
* 本轮 turn 已结束,但会话的 goal 仍 active:宿主会自动开始下一轮,任务没有
|
|
@@ -17,6 +18,16 @@ declare const RUN_TERMINAL_STATES: readonly ["done", "error", "interrupted", "id
|
|
|
17
18
|
export type RunFinalTerminal = (typeof RUN_TERMINAL_STATES)[number];
|
|
18
19
|
/** 该状态是否已收尾(非 running/finalizing)。 */
|
|
19
20
|
export declare function isRunTerminal(terminal: RunTerminal): terminal is RunFinalTerminal;
|
|
21
|
+
/** 仍在推进的两个状态(`RunTerminal` 的非终态部分)。 */
|
|
22
|
+
export type RunActiveTerminal = 'running' | 'finalizing';
|
|
23
|
+
/**
|
|
24
|
+
* 该状态是否仍在推进(running 或 finalizing)。
|
|
25
|
+
*
|
|
26
|
+
* `finalizing` 是「result 已到、进程还在收尾」的非终态:卡片仍要处理事件、
|
|
27
|
+
* 仍要显示停止按钮。这个判据此前在 card/bridge 里逐字抄了四处,与
|
|
28
|
+
* `isRunTerminal` 互为反义却各写各的——收在这儿与终态判据并排。
|
|
29
|
+
*/
|
|
30
|
+
export declare function isRunActive(terminal: RunTerminal): terminal is RunActiveTerminal;
|
|
20
31
|
export type RunFooter = 'thinking' | 'tool_running' | 'streaming' | null;
|
|
21
32
|
/** 中断来源(interrupted 终态的原因),供卡片如实归因。 */
|
|
22
33
|
export type InterruptedReason = 'approval_timeout' | 'user_stop' | 'approval_cancelled';
|
|
@@ -91,7 +102,12 @@ export interface FinalAnswerState {
|
|
|
91
102
|
complete: boolean;
|
|
92
103
|
source: 'protocol' | 'inferred';
|
|
93
104
|
}
|
|
94
|
-
|
|
105
|
+
/**
|
|
106
|
+
* 一张 run 卡的状态。用量字段(context/tokens/cache/累计/推理)一律来自
|
|
107
|
+
* `UsageSnapshot` 单源——原先在这里、`FinishMeta`、`usage-format` 和桥侧各抄
|
|
108
|
+
* 一份(§9.21「五处一致」靠人记),加一个字段要改四遍。
|
|
109
|
+
*/
|
|
110
|
+
export interface RunState extends UsageSnapshot {
|
|
95
111
|
runId: string;
|
|
96
112
|
terminal: RunTerminal;
|
|
97
113
|
footer: RunFooter;
|
|
@@ -109,30 +125,8 @@ export interface RunState {
|
|
|
109
125
|
resultSubtype?: 'success' | 'error' | 'interrupted';
|
|
110
126
|
/** interrupted 终态的中断来源;undefined = 未归类(渲染默认文案)。 */
|
|
111
127
|
interruptedReason?: InterruptedReason;
|
|
112
|
-
contextLength?: number;
|
|
113
|
-
/** 当前模型 context window 上限(codex jsonl 提供);卡片据此渲染百分比。 */
|
|
114
|
-
contextLimit?: number;
|
|
115
128
|
errorMsg?: string;
|
|
116
129
|
idleTimeoutMinutes?: number;
|
|
117
|
-
compactCount?: number;
|
|
118
|
-
cacheReadTokens?: number;
|
|
119
|
-
cacheCreationTokens?: number;
|
|
120
|
-
/** Agent-declared total; the done card uses max(total, sum of parts). */
|
|
121
|
-
totalTokens?: number;
|
|
122
|
-
/** Real input tokens from the agent's result event (codex/opencode).
|
|
123
|
-
* When present, the done card shows the real value instead of the
|
|
124
|
-
* contextLength-based estimate. */
|
|
125
|
-
inputTokens?: number;
|
|
126
|
-
/** Real output tokens from the agent's result event. */
|
|
127
|
-
outputTokens?: number;
|
|
128
|
-
/** 会话累计 total/input/output(所有 run 之和),Run 卡片展示"累计"。 */
|
|
129
|
-
cumulativeTotalTokens?: number;
|
|
130
|
-
cumulativeInputTokens?: number;
|
|
131
|
-
cumulativeOutputTokens?: number;
|
|
132
|
-
/** 会话累计 cache read token(所有 run 之和)。 */
|
|
133
|
-
cumulativeCacheReadTokens?: number;
|
|
134
|
-
/** 会话累计 cache creation token(所有 run 之和)。 */
|
|
135
|
-
cumulativeCacheCreationTokens?: number;
|
|
136
130
|
plan?: string;
|
|
137
131
|
/** 实际生效模型(system.init 携带;失败兜底 synthetic init 为 '',渲染须容忍)。 */
|
|
138
132
|
model?: string;
|
|
@@ -146,12 +140,8 @@ export interface RunState {
|
|
|
146
140
|
sessionTitle?: string;
|
|
147
141
|
/** 当前模式(ACP current_mode_update.currentModeId)。 */
|
|
148
142
|
mode?: string;
|
|
149
|
-
/** 推理 token(pi usage.reasoning 累加,经 finish meta 写入)。 */
|
|
150
|
-
reasoningTokens?: number;
|
|
151
143
|
/** Codex 操作类型:'turn' 表示普通 run,'compaction' 表示 compact 运行。 */
|
|
152
144
|
operationKind?: 'turn' | 'compaction';
|
|
153
|
-
/** 压缩前上下文水位(codex compact 卡展示「压缩前 X → 压缩后 Y」)。 */
|
|
154
|
-
compactPreContextLength?: number;
|
|
155
145
|
/**
|
|
156
146
|
* 待审批请求列表(app-server 模式)。同一 turn 内并发多个审批
|
|
157
147
|
* 时全部渲染,避免后到者顶掉先到者的按钮(单槽会丢 UI,只能等超时 cancel)。
|
|
@@ -200,35 +190,23 @@ export interface RunState {
|
|
|
200
190
|
*/
|
|
201
191
|
goalKnown?: boolean;
|
|
202
192
|
}
|
|
203
|
-
|
|
193
|
+
/** 终态卡片的一次性元信息;用量部分与 `RunState` 同源(`UsageSnapshot`)。 */
|
|
194
|
+
export interface FinishMeta extends UsageSnapshot {
|
|
204
195
|
resultSubtype?: 'success' | 'error' | 'interrupted';
|
|
205
196
|
/** 中断来源:由桥侧在 finish 时显式传入(/stop → user_stop、审批卡取消 → approval_cancelled)。 */
|
|
206
197
|
interruptedReason?: InterruptedReason;
|
|
207
|
-
contextLength?: number;
|
|
208
|
-
/** 当前模型 context window 上限;透传到 RunState 供 done 卡片显示百分比。 */
|
|
209
|
-
contextLimit?: number;
|
|
210
198
|
errorMsg?: string;
|
|
211
199
|
idleTimeoutMinutes?: number;
|
|
212
|
-
compactCount?: number;
|
|
213
|
-
compactPreContextLength?: number;
|
|
214
|
-
cacheReadTokens?: number;
|
|
215
|
-
cacheCreationTokens?: number;
|
|
216
|
-
/** Agent-declared total; threaded to RunState for the done card. */
|
|
217
|
-
totalTokens?: number;
|
|
218
|
-
/** Real input/output tokens from the agent's result event. Threaded through
|
|
219
|
-
* to RunState so the done card can display real values instead of estimates. */
|
|
220
|
-
inputTokens?: number;
|
|
221
|
-
outputTokens?: number;
|
|
222
|
-
/** 会话累计 total/input/output(所有 run 之和),从 session jsonl 读取。 */
|
|
223
|
-
cumulativeTotalTokens?: number;
|
|
224
|
-
cumulativeInputTokens?: number;
|
|
225
|
-
cumulativeOutputTokens?: number;
|
|
226
|
-
cumulativeCacheReadTokens?: number;
|
|
227
|
-
cumulativeCacheCreationTokens?: number;
|
|
228
|
-
/** 推理 token(pi usage.reasoning 累加,经 usageMeta 透传)。 */
|
|
229
|
-
reasoningTokens?: number;
|
|
230
200
|
}
|
|
231
201
|
export declare function createInitialRunState(runId: string): RunState;
|
|
232
202
|
export declare function reduceRunState(state: RunState, event: AgentEvent): RunState;
|
|
233
|
-
|
|
203
|
+
/**
|
|
204
|
+
* 用户停止某个后台任务成功后,从卡片状态里摘掉它。
|
|
205
|
+
*
|
|
206
|
+
* run 此时已经收尾(没有流再消费事件),所以这条不走 reducer 的事件入口;但
|
|
207
|
+
* RunState 的形状只允许在本模块内拼装——bridge 直接展开 state 曾把「摘一条」
|
|
208
|
+
* 写成「整体重建」,字段一多就会漏带。
|
|
209
|
+
*/
|
|
210
|
+
export declare function removeBackgroundJob(state: RunState, jobId: string): RunState;
|
|
211
|
+
export declare function finishRun(state: RunState, terminal: RunFinalTerminal, meta?: FinishMeta): RunState;
|
|
234
212
|
export {};
|
package/dist/card/run-state.js
CHANGED
|
@@ -22,6 +22,16 @@ const RUN_TERMINAL_STATES = [
|
|
|
22
22
|
export function isRunTerminal(terminal) {
|
|
23
23
|
return RUN_TERMINAL_STATES.includes(terminal);
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* 该状态是否仍在推进(running 或 finalizing)。
|
|
27
|
+
*
|
|
28
|
+
* `finalizing` 是「result 已到、进程还在收尾」的非终态:卡片仍要处理事件、
|
|
29
|
+
* 仍要显示停止按钮。这个判据此前在 card/bridge 里逐字抄了四处,与
|
|
30
|
+
* `isRunTerminal` 互为反义却各写各的——收在这儿与终态判据并排。
|
|
31
|
+
*/
|
|
32
|
+
export function isRunActive(terminal) {
|
|
33
|
+
return terminal === 'running' || terminal === 'finalizing';
|
|
34
|
+
}
|
|
25
35
|
export function createInitialRunState(runId) {
|
|
26
36
|
return {
|
|
27
37
|
runId,
|
|
@@ -411,6 +421,19 @@ function reduceBackgroundJobsEvent(state, event) {
|
|
|
411
421
|
return state;
|
|
412
422
|
return { ...state, backgroundJobs: event.jobs };
|
|
413
423
|
}
|
|
424
|
+
/**
|
|
425
|
+
* 用户停止某个后台任务成功后,从卡片状态里摘掉它。
|
|
426
|
+
*
|
|
427
|
+
* run 此时已经收尾(没有流再消费事件),所以这条不走 reducer 的事件入口;但
|
|
428
|
+
* RunState 的形状只允许在本模块内拼装——bridge 直接展开 state 曾把「摘一条」
|
|
429
|
+
* 写成「整体重建」,字段一多就会漏带。
|
|
430
|
+
*/
|
|
431
|
+
export function removeBackgroundJob(state, jobId) {
|
|
432
|
+
return {
|
|
433
|
+
...state,
|
|
434
|
+
backgroundJobs: (state.backgroundJobs ?? []).filter((job) => job.id !== jobId),
|
|
435
|
+
};
|
|
436
|
+
}
|
|
414
437
|
/**
|
|
415
438
|
* 运行期状态投影 → 状态行。
|
|
416
439
|
*
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format session/run usage stats (context, compact count, tokens, cost) into
|
|
3
|
+
* the display strings shown on cards. Pure — no Router state.
|
|
4
|
+
*
|
|
5
|
+
* 归属 card/:渲染层(run-renderer)与 router 都只消费它的展示字符串,此前
|
|
6
|
+
* 住在 router/ 让它成为 card→router 的唯一理由。
|
|
7
|
+
*/
|
|
8
|
+
import type { UsageSnapshot } from '../session-contract.js';
|
|
9
|
+
/** `formatUsageStats` 只读这几项:会话/进度卡片上的紧凑用量行。 */
|
|
10
|
+
export type SessionDisplayUsage = Pick<UsageSnapshot, 'contextLength' | 'contextLimit' | 'compactCount' | 'cacheReadTokens' | 'cacheCreationTokens'>;
|
|
11
|
+
/**
|
|
12
|
+
* Format usage stats (context length, compact count, cache tokens) into a display string.
|
|
13
|
+
* Each stat on its own line with blank lines between sections.
|
|
14
|
+
* @param usage - Usage stats object
|
|
15
|
+
* @param options - Optional display options (showResult adds result line)
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatUsageStats(usage?: UsageSnapshot & {
|
|
18
|
+
/** 实际生效模型(system.init 携带)。非空字符串才显示。 */
|
|
19
|
+
model?: string;
|
|
20
|
+
/** 本次 run 花费(USD)。存在才显示。 */
|
|
21
|
+
costUsd?: number;
|
|
22
|
+
}, options?: {
|
|
23
|
+
showResult?: boolean;
|
|
24
|
+
result?: string;
|
|
25
|
+
/**
|
|
26
|
+
* 首行状态文案。默认 `✅ 已完成`;goal 仍 active 的收尾卡必须换掉它——
|
|
27
|
+
* 本轮 turn 结束不等于任务结束。
|
|
28
|
+
*/
|
|
29
|
+
completedLabel?: string;
|
|
30
|
+
}): string;
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Format session/run usage stats (context, compact count, tokens, cost) into
|
|
3
3
|
* the display strings shown on cards. Pure — no Router state.
|
|
4
|
+
*
|
|
5
|
+
* 归属 card/:渲染层(run-renderer)与 router 都只消费它的展示字符串,此前
|
|
6
|
+
* 住在 router/ 让它成为 card→router 的唯一理由。
|
|
4
7
|
*/
|
|
5
|
-
export function activeRunUsage(activeRun) {
|
|
6
|
-
if (!activeRun || activeRun.contextLength === undefined)
|
|
7
|
-
return undefined;
|
|
8
|
-
return {
|
|
9
|
-
contextLength: activeRun.contextLength,
|
|
10
|
-
compactCount: activeRun.compactCount,
|
|
11
|
-
cacheReadTokens: activeRun.cacheReadTokens,
|
|
12
|
-
cacheCreationTokens: activeRun.cacheCreationTokens,
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
8
|
/**
|
|
16
9
|
* Format number to human-readable unit string.
|
|
17
10
|
* - >= 1M: one decimal, M suffix (e.g., 1200000 → 1.2M, 25000000 → 25M)
|
package/dist/clone.js
CHANGED
|
@@ -390,7 +390,12 @@ export class CloneSession {
|
|
|
390
390
|
const raw = JSON.parse(fs.readFileSync(path.join(this.configDir, 'startup-contact.json'), 'utf-8'));
|
|
391
391
|
return typeof raw.userId === 'string' && raw.userId ? raw.userId : undefined;
|
|
392
392
|
}
|
|
393
|
-
catch {
|
|
393
|
+
catch (err) {
|
|
394
|
+
// ENOENT = 旧实例从未写过 startup-contact(正常)。其余(解析失败/权限)
|
|
395
|
+
// 留痕:否则下游会误归因成「旧 owner 无条目」。
|
|
396
|
+
if (err.code !== 'ENOENT') {
|
|
397
|
+
getLogger().debug(`[clone] cannot read startup-contact.json for previous owner: ${err?.message ?? String(err)}`);
|
|
398
|
+
}
|
|
394
399
|
return undefined;
|
|
395
400
|
}
|
|
396
401
|
}
|
package/dist/config/index.d.ts
CHANGED
|
@@ -34,27 +34,23 @@ export declare const DEFAULT_APPROVAL_TIMEOUT_MS: number;
|
|
|
34
34
|
*/
|
|
35
35
|
export declare const DEFAULT_INBOUND_MEDIA_DIR_NAME = ".lark-remote-temp";
|
|
36
36
|
export declare const DEFAULT_INBOUND_MEDIA_MAX_SIZE_MB = 100;
|
|
37
|
-
/** 模型 ID → alias 映射。 */
|
|
38
|
-
export declare const MODEL_ID_TO_ALIAS: Record<string, string>;
|
|
39
|
-
/** alias → model ID 反向映射。 */
|
|
40
|
-
export declare const MODEL_ALIAS_TO_ID: Record<string, string>;
|
|
41
37
|
declare const ClaudeConfigSchema: z.ZodObject<{
|
|
42
38
|
model: z.ZodDefault<z.ZodString>;
|
|
43
39
|
effort: z.ZodDefault<z.ZodEnum<{
|
|
44
|
-
medium: "medium";
|
|
45
40
|
low: "low";
|
|
46
41
|
high: "high";
|
|
47
|
-
xhigh: "xhigh";
|
|
48
42
|
max: "max";
|
|
43
|
+
medium: "medium";
|
|
44
|
+
xhigh: "xhigh";
|
|
49
45
|
}>>;
|
|
50
46
|
permissionMode: z.ZodDefault<z.ZodEnum<{
|
|
51
47
|
default: "default";
|
|
52
|
-
plan: "plan";
|
|
53
|
-
auto: "auto";
|
|
54
|
-
manual: "manual";
|
|
55
48
|
acceptEdits: "acceptEdits";
|
|
49
|
+
auto: "auto";
|
|
56
50
|
bypassPermissions: "bypassPermissions";
|
|
51
|
+
manual: "manual";
|
|
57
52
|
dontAsk: "dontAsk";
|
|
53
|
+
plan: "plan";
|
|
58
54
|
}>>;
|
|
59
55
|
approvalTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
60
56
|
idleTtlMinutes: z.ZodDefault<z.ZodNumber>;
|
|
@@ -102,11 +98,11 @@ declare const PiConfigSchema: z.ZodObject<{
|
|
|
102
98
|
provider: z.ZodDefault<z.ZodString>;
|
|
103
99
|
model: z.ZodDefault<z.ZodString>;
|
|
104
100
|
thinking: z.ZodDefault<z.ZodEnum<{
|
|
105
|
-
medium: "medium";
|
|
106
|
-
off: "off";
|
|
107
101
|
low: "low";
|
|
108
102
|
high: "high";
|
|
103
|
+
medium: "medium";
|
|
109
104
|
xhigh: "xhigh";
|
|
105
|
+
off: "off";
|
|
110
106
|
minimal: "minimal";
|
|
111
107
|
}>>;
|
|
112
108
|
tools: z.ZodDefault<z.ZodString>;
|
|
@@ -121,8 +117,8 @@ declare const KimiConfigSchema: z.ZodObject<{
|
|
|
121
117
|
}>>;
|
|
122
118
|
permissionMode: z.ZodDefault<z.ZodEnum<{
|
|
123
119
|
auto: "auto";
|
|
124
|
-
yolo: "yolo";
|
|
125
120
|
manual: "manual";
|
|
121
|
+
yolo: "yolo";
|
|
126
122
|
}>>;
|
|
127
123
|
acp: z.ZodOptional<z.ZodObject<{
|
|
128
124
|
binary: z.ZodDefault<z.ZodString>;
|
|
@@ -156,20 +152,20 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
156
152
|
claude: z.ZodDefault<z.ZodObject<{
|
|
157
153
|
model: z.ZodDefault<z.ZodString>;
|
|
158
154
|
effort: z.ZodDefault<z.ZodEnum<{
|
|
159
|
-
medium: "medium";
|
|
160
155
|
low: "low";
|
|
161
156
|
high: "high";
|
|
162
|
-
xhigh: "xhigh";
|
|
163
157
|
max: "max";
|
|
158
|
+
medium: "medium";
|
|
159
|
+
xhigh: "xhigh";
|
|
164
160
|
}>>;
|
|
165
161
|
permissionMode: z.ZodDefault<z.ZodEnum<{
|
|
166
162
|
default: "default";
|
|
167
|
-
plan: "plan";
|
|
168
|
-
auto: "auto";
|
|
169
|
-
manual: "manual";
|
|
170
163
|
acceptEdits: "acceptEdits";
|
|
164
|
+
auto: "auto";
|
|
171
165
|
bypassPermissions: "bypassPermissions";
|
|
166
|
+
manual: "manual";
|
|
172
167
|
dontAsk: "dontAsk";
|
|
168
|
+
plan: "plan";
|
|
173
169
|
}>>;
|
|
174
170
|
approvalTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
175
171
|
idleTtlMinutes: z.ZodDefault<z.ZodNumber>;
|
|
@@ -215,11 +211,11 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
215
211
|
provider: z.ZodDefault<z.ZodString>;
|
|
216
212
|
model: z.ZodDefault<z.ZodString>;
|
|
217
213
|
thinking: z.ZodDefault<z.ZodEnum<{
|
|
218
|
-
medium: "medium";
|
|
219
|
-
off: "off";
|
|
220
214
|
low: "low";
|
|
221
215
|
high: "high";
|
|
216
|
+
medium: "medium";
|
|
222
217
|
xhigh: "xhigh";
|
|
218
|
+
off: "off";
|
|
223
219
|
minimal: "minimal";
|
|
224
220
|
}>>;
|
|
225
221
|
tools: z.ZodDefault<z.ZodString>;
|
|
@@ -233,8 +229,8 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
233
229
|
}>>;
|
|
234
230
|
permissionMode: z.ZodDefault<z.ZodEnum<{
|
|
235
231
|
auto: "auto";
|
|
236
|
-
yolo: "yolo";
|
|
237
232
|
manual: "manual";
|
|
233
|
+
yolo: "yolo";
|
|
238
234
|
}>>;
|
|
239
235
|
acp: z.ZodOptional<z.ZodObject<{
|
|
240
236
|
binary: z.ZodDefault<z.ZodString>;
|