lark-remote 0.5.6 → 0.5.8
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 +46 -6
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/dist/bridge/index.d.ts +63 -1
- package/dist/bridge/index.js +147 -14
- package/dist/bridge/queue-manager.js +41 -58
- package/dist/card/approval-render.js +2 -1
- package/dist/card/bash-card-session.d.ts +0 -1
- package/dist/card/bash-card-session.js +0 -8
- package/dist/card/bash-renderer.js +2 -1
- package/dist/card/card-budget.d.ts +37 -0
- package/dist/card/card-budget.js +143 -24
- package/dist/card/card-session.d.ts +3 -13
- package/dist/card/card-session.js +4 -18
- package/dist/card/card-shared.d.ts +11 -0
- package/dist/card/card-shared.js +19 -13
- package/dist/card/run-card-session.d.ts +0 -1
- package/dist/card/run-card-session.js +0 -6
- package/dist/card/run-renderer.d.ts +18 -0
- package/dist/card/run-renderer.js +330 -62
- package/dist/card/run-state.d.ts +26 -0
- package/dist/card/run-state.js +45 -0
- package/dist/card/text-truncate.d.ts +3 -5
- package/dist/card/text-truncate.js +3 -5
- package/dist/card/time.d.ts +14 -0
- package/dist/card/time.js +30 -0
- package/dist/card/tool-render.d.ts +15 -2
- package/dist/card/tool-render.js +42 -82
- package/dist/common/text-width.d.ts +24 -0
- package/dist/common/text-width.js +93 -0
- package/dist/common/tool-summary.d.ts +19 -0
- package/dist/common/tool-summary.js +171 -0
- package/dist/common/turn-failure.d.ts +13 -0
- package/dist/common/turn-failure.js +18 -0
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +1 -1
- package/dist/connector/index.js +1 -1
- package/dist/index.js +66 -13
- package/dist/order/index.d.ts +2 -0
- package/dist/order/index.js +2 -0
- package/dist/platform/command.js +1 -1
- package/dist/platform/shell.d.ts +2 -2
- package/dist/platform/spawn.d.ts +1 -1
- package/dist/platform/spawn.js +2 -2
- package/dist/platform/types.d.ts +1 -1
- package/dist/router/card-helpers.d.ts +18 -16
- package/dist/router/card-helpers.js +88 -46
- package/dist/router/config/codex.js +2 -3
- package/dist/router/config/common/model-patch.d.ts +8 -0
- package/dist/router/config/common/model-patch.js +13 -0
- package/dist/router/config/common/render.js +30 -77
- package/dist/router/config/dsh.js +2 -1
- package/dist/router/config/kimi.js +3 -3
- package/dist/router/index.d.ts +9 -11
- package/dist/router/index.js +165 -356
- package/dist/router/order-exec-dispatch.js +2 -1
- package/dist/runner/claude/session.d.ts +1 -1
- package/dist/runner/claude/session.js +3 -3
- package/dist/runner/common/defaults.d.ts +2 -0
- package/dist/runner/common/defaults.js +3 -0
- package/dist/runner/common/jsonrpc/connection-manager.js +1 -1
- package/dist/runner/common/jsonrpc/transport.d.ts +1 -1
- package/dist/runner/common/jsonrpc/transport.js +3 -3
- package/dist/runner/common/spawning-runner.d.ts +1 -1
- package/dist/runner/common/spawning-runner.js +2 -2
- package/dist/runner/dsh/auth.js +2 -1
- package/dist/runner/dsh/client.d.ts +100 -3
- package/dist/runner/dsh/client.js +290 -6
- package/dist/runner/dsh/exit-cancel.d.ts +32 -0
- package/dist/runner/dsh/exit-cancel.js +72 -0
- package/dist/runner/dsh/inflight.d.ts +62 -0
- package/dist/runner/dsh/inflight.js +140 -0
- package/dist/runner/dsh/runner.d.ts +90 -4
- package/dist/runner/dsh/runner.js +436 -18
- package/dist/runner/dsh/translator.d.ts +1 -1
- package/dist/runner/dsh/translator.js +103 -1
- package/dist/runner/dsh/types.d.ts +60 -0
- package/dist/runner/types.d.ts +95 -2
- package/dist/runner/types.js +9 -0
- package/dist/session/claude/session-index.d.ts +0 -4
- package/dist/session/claude/session-index.js +0 -8
- package/dist/session/claude/sessions.js +2 -2
- package/dist/session/dsh/sessions.js +157 -17
- package/dist/update/install.js +1 -1
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* completed → success; aborted/interrupted → interrupted;
|
|
13
13
|
* blocked/error/max-tokens → error (errorMessage carries the reason)
|
|
14
14
|
*
|
|
15
|
-
* Token accounting (ccusage
|
|
15
|
+
* Token accounting (ccusage 口径): DSH emits ONE usage per model
|
|
16
16
|
* call (per step) — a tool-looping turn has several `assistant/message` events.
|
|
17
17
|
* The result event therefore carries **the sum of the turn's samplings**, not the
|
|
18
18
|
* last one (codex `token_count` has the same shape). `lastUsage` is kept only as
|
|
@@ -118,6 +118,48 @@ export class DshTranslator {
|
|
|
118
118
|
}
|
|
119
119
|
return [];
|
|
120
120
|
}
|
|
121
|
+
case 'tool/call': {
|
|
122
|
+
// DSH 把「模型发起调用」落成独立事件(name/arguments 是模型原始输出)。
|
|
123
|
+
// 这是卡片工具行的唯一来源:assistant/message 里只有完成后的正文块,
|
|
124
|
+
// 不含调用轨迹。
|
|
125
|
+
const call = ev.data;
|
|
126
|
+
const id = typeof call.callId === 'string' ? call.callId : '';
|
|
127
|
+
const name = typeof call.name === 'string' ? call.name : '';
|
|
128
|
+
if (!id || !name)
|
|
129
|
+
return [];
|
|
130
|
+
return [
|
|
131
|
+
{
|
|
132
|
+
type: 'assistant',
|
|
133
|
+
message: {
|
|
134
|
+
content: [{ type: 'tool_use', id, name, input: parseToolArguments(call.arguments) }],
|
|
135
|
+
},
|
|
136
|
+
timestamp: new Date(ev.time).toISOString(),
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
case 'tool/result': {
|
|
141
|
+
const data = ev.data;
|
|
142
|
+
const msg = data.message;
|
|
143
|
+
const toolCallId = typeof msg?.toolCallId === 'string' ? msg.toolCallId : '';
|
|
144
|
+
if (!toolCallId)
|
|
145
|
+
return [];
|
|
146
|
+
return [
|
|
147
|
+
{
|
|
148
|
+
type: 'user',
|
|
149
|
+
message: {
|
|
150
|
+
content: [
|
|
151
|
+
{
|
|
152
|
+
type: 'tool_result',
|
|
153
|
+
tool_use_id: toolCallId,
|
|
154
|
+
content: toolResultText(msg?.content, data.error),
|
|
155
|
+
is_error: msg?.isError === true,
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
timestamp: new Date(ev.time).toISOString(),
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
}
|
|
121
163
|
case 'turn/end': {
|
|
122
164
|
const turnReason = ev.data.reason;
|
|
123
165
|
const reason = turnReason?.kind;
|
|
@@ -153,6 +195,66 @@ export class DshTranslator {
|
|
|
153
195
|
}
|
|
154
196
|
}
|
|
155
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Parse a `tool/call.arguments` payload (a JSON string on the wire) into the
|
|
200
|
+
* object shape the card renderer consumes. Non-JSON arguments (a truncated or
|
|
201
|
+
* provider-mangled payload) are kept verbatim so the header can still show
|
|
202
|
+
* something instead of silently rendering an empty summary.
|
|
203
|
+
*/
|
|
204
|
+
function parseToolArguments(raw) {
|
|
205
|
+
if (typeof raw !== 'string')
|
|
206
|
+
return raw ?? {};
|
|
207
|
+
const trimmed = raw.trim();
|
|
208
|
+
if (!trimmed)
|
|
209
|
+
return {};
|
|
210
|
+
try {
|
|
211
|
+
return JSON.parse(trimmed);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return trimmed;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Flatten a `tool/result.message.content` block list into display text.
|
|
219
|
+
*
|
|
220
|
+
* DSH content is a block array (`{type:'text',text}` / `{type:'image',...}`),
|
|
221
|
+
* the same shape the LLM sees. Images collapse to a marker: the card cannot
|
|
222
|
+
* render them and the raw base64 would blow the byte budget.
|
|
223
|
+
*/
|
|
224
|
+
function toolResultText(content, error) {
|
|
225
|
+
const err = error;
|
|
226
|
+
const errorHint = typeof err?.message === 'string' ? err.message : '';
|
|
227
|
+
if (content == null)
|
|
228
|
+
return errorHint;
|
|
229
|
+
if (typeof content === 'string')
|
|
230
|
+
return content;
|
|
231
|
+
if (Array.isArray(content)) {
|
|
232
|
+
const parts = [];
|
|
233
|
+
for (const block of content) {
|
|
234
|
+
if (typeof block === 'string') {
|
|
235
|
+
parts.push(block);
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
if (!block || typeof block !== 'object')
|
|
239
|
+
continue;
|
|
240
|
+
const rec = block;
|
|
241
|
+
if (typeof rec.text === 'string') {
|
|
242
|
+
parts.push(rec.text);
|
|
243
|
+
}
|
|
244
|
+
else if (rec.type === 'image') {
|
|
245
|
+
parts.push('[image]');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const text = parts.join('\n');
|
|
249
|
+
return text || errorHint;
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
return JSON.stringify(content);
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
return String(content);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
156
258
|
/** Map DSH TokenUsage → ResultEvent.usage (cacheWrite = cache creation). */
|
|
157
259
|
export function mapUsage(u) {
|
|
158
260
|
return mapAggregatedUsage({
|
|
@@ -60,6 +60,27 @@ export interface DshSessionSummary {
|
|
|
60
60
|
export interface DshSessionListValue {
|
|
61
61
|
items: DshSessionSummary[];
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* One pending inbox occurrence from the `inbox` projection.
|
|
65
|
+
*
|
|
66
|
+
* DSH 在 prompt 被受理但还没被 turn 取走时,把它记录成 `inbox.next-turn[]`
|
|
67
|
+
* 的一项;`source.rpcId` 回显 `session/prompt` 的 requestId,因此调用方可以
|
|
68
|
+
* 精确找到“我这条还没开始的消息”。`session/updateQueue` 用 `id` 删除它。
|
|
69
|
+
*/
|
|
70
|
+
export interface DshInboxItem {
|
|
71
|
+
id: string;
|
|
72
|
+
source?: {
|
|
73
|
+
kind?: string;
|
|
74
|
+
rpcId?: string;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** `session/projections` → value(只声明本仓库用到的部分)。 */
|
|
78
|
+
export interface DshProjectionSnapshot {
|
|
79
|
+
asOfSeq?: number;
|
|
80
|
+
values: Record<string, unknown>;
|
|
81
|
+
}
|
|
82
|
+
/** Whether the host currently has a turn open for a session. */
|
|
83
|
+
export type DshOpenTurnState = 'open' | 'closed' | 'unknown';
|
|
63
84
|
/** session/page → value.records[]. */
|
|
64
85
|
export interface DshPageRecord {
|
|
65
86
|
event: DshSessionEvent;
|
|
@@ -309,3 +330,42 @@ export type DshStreamItem = {
|
|
|
309
330
|
callId?: string;
|
|
310
331
|
reason?: string;
|
|
311
332
|
};
|
|
333
|
+
/**
|
|
334
|
+
* One finished projection value from the Host-wide `session/control` stream.
|
|
335
|
+
*
|
|
336
|
+
* DSH 的 `session/control` 是唯一的"服务端变一次推一次"通道:连接先收到一份
|
|
337
|
+
* baseline(覆盖当前所有活跃 session 的全部投影值),之后每个投影变化推一帧
|
|
338
|
+
* `{type:'projection', sessionId, key, value, seq}`。调用方按 sessionId 过滤。
|
|
339
|
+
*/
|
|
340
|
+
export interface DshProjectionItem {
|
|
341
|
+
kind: 'projection';
|
|
342
|
+
sessionId: string;
|
|
343
|
+
key: string;
|
|
344
|
+
value: unknown;
|
|
345
|
+
}
|
|
346
|
+
/** `contextPressure` 投影(只声明本仓库消费的字段)。 */
|
|
347
|
+
export interface DshContextPressure {
|
|
348
|
+
/** 上一次采样实际占用的 token。 */
|
|
349
|
+
pressureTokens?: number;
|
|
350
|
+
/** 下一次请求的预估占用(官方 UI 优先用它算百分比)。 */
|
|
351
|
+
projectedTokens?: number;
|
|
352
|
+
/** 当前模型上下文窗口。 */
|
|
353
|
+
contextWindow?: number;
|
|
354
|
+
}
|
|
355
|
+
/** `sessionStats` 投影(只声明本仓库消费的字段)。 */
|
|
356
|
+
export interface DshSessionStats {
|
|
357
|
+
turns?: number;
|
|
358
|
+
steps?: number;
|
|
359
|
+
toolMs?: number;
|
|
360
|
+
}
|
|
361
|
+
/** One background job row from the `job/list` stream (fields lark-remote consumes). */
|
|
362
|
+
export interface DshJobView {
|
|
363
|
+
id: string;
|
|
364
|
+
kind?: string;
|
|
365
|
+
label?: string;
|
|
366
|
+
status?: 'running' | 'stopping' | 'completed' | 'killed' | 'failed';
|
|
367
|
+
progress?: string;
|
|
368
|
+
detail?: string;
|
|
369
|
+
startedAt?: number;
|
|
370
|
+
finishedAt?: number;
|
|
371
|
+
}
|
package/dist/runner/types.d.ts
CHANGED
|
@@ -325,6 +325,45 @@ export interface SessionInfoEvent {
|
|
|
325
325
|
mode?: string;
|
|
326
326
|
timestamp?: string;
|
|
327
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* 运行期状态投影(上下文水位 / 会话累计统计)。
|
|
330
|
+
*
|
|
331
|
+
* 不是内容块:卡片把它渲染在状态行(statusRow),不进内容流,因此不参与
|
|
332
|
+
* blocks 分组与 MAX_BLOCKS 裁剪。字段缺省表示该维度本次未变。
|
|
333
|
+
*
|
|
334
|
+
* 数据源是 agent 服务端自己算好的投影(DSH `session/control` 的
|
|
335
|
+
* contextPressure / sessionStats),bridge 不重算口径——百分比只在两端都
|
|
336
|
+
* 有值时才渲染。
|
|
337
|
+
*/
|
|
338
|
+
export interface RunStatusEvent {
|
|
339
|
+
type: 'run_status';
|
|
340
|
+
/** 已投影 token(官方口径 projectedTokens ?? pressureTokens)。 */
|
|
341
|
+
contextUsed?: number;
|
|
342
|
+
/** 上下文窗口上限(contextWindow)。 */
|
|
343
|
+
contextLimit?: number;
|
|
344
|
+
/** 会话累计步骤数(sessionStats.steps)。 */
|
|
345
|
+
steps?: number;
|
|
346
|
+
/** 会话累计工具耗时(毫秒,sessionStats.toolMs)。 */
|
|
347
|
+
toolMs?: number;
|
|
348
|
+
timestamp?: string;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* 运行结束后仍在后台运行的任务(终态卡展示 + 逐个停止入口)。
|
|
352
|
+
*
|
|
353
|
+
* 为什么必须出现在 run 卡片上:后台任务的生命周期跨 turn(`bash
|
|
354
|
+
* run_in_background` 起的东西能活过 run 结束),卡片收尾时如果不说,用户就
|
|
355
|
+
* 以为这一轮真的结束了——机器上却还在跑。
|
|
356
|
+
*/
|
|
357
|
+
export interface BackgroundJobsEvent {
|
|
358
|
+
type: 'background_jobs';
|
|
359
|
+
jobs: Array<{
|
|
360
|
+
id: string;
|
|
361
|
+
label: string;
|
|
362
|
+
status?: string;
|
|
363
|
+
progress?: string;
|
|
364
|
+
}>;
|
|
365
|
+
timestamp?: string;
|
|
366
|
+
}
|
|
328
367
|
/** File change event — for agents that report file modifications (e.g. Codex). */
|
|
329
368
|
export interface FileChangeEvent {
|
|
330
369
|
type: 'file_change';
|
|
@@ -392,7 +431,7 @@ export interface TurnDiffEvent {
|
|
|
392
431
|
export type RunnerLifetime = 'turn' | 'workspace';
|
|
393
432
|
/** 工具渲染 hint:runner 自愿声明,渲染层只消费不推断。 */
|
|
394
433
|
export type ToolHint = 'shell' | 'file' | 'search' | 'web' | 'patch';
|
|
395
|
-
export type AgentEvent = SystemInitEvent | SystemCompactEvent | ApprovalRequestedEvent | ApprovalResolvedEvent | ApprovalViewUpdatedEvent | ApprovalExpiredEvent | AssistantEvent | UserEvent | ResultEvent | PlanEvent | FileChangeEvent | TurnStartedEvent | TurnDiffEvent | NoticeEvent | SessionInfoEvent;
|
|
434
|
+
export type AgentEvent = SystemInitEvent | SystemCompactEvent | ApprovalRequestedEvent | ApprovalResolvedEvent | ApprovalViewUpdatedEvent | ApprovalExpiredEvent | AssistantEvent | UserEvent | ResultEvent | PlanEvent | FileChangeEvent | TurnStartedEvent | TurnDiffEvent | NoticeEvent | SessionInfoEvent | RunStatusEvent | BackgroundJobsEvent;
|
|
396
435
|
export interface SpawnOptions {
|
|
397
436
|
cwd: string;
|
|
398
437
|
sessionId?: string;
|
|
@@ -402,6 +441,29 @@ export interface SpawnOptions {
|
|
|
402
441
|
reasoningEffort?: string;
|
|
403
442
|
settings?: string;
|
|
404
443
|
}
|
|
444
|
+
/**
|
|
445
|
+
* What a stop request actually achieved.
|
|
446
|
+
*
|
|
447
|
+
* Local-process runners (`claude`/`codex`/…) can answer this from the kill
|
|
448
|
+
* itself and keep returning `void`. DSH turns live in the shared Web Host, so
|
|
449
|
+
* its stop is a session-scoped request: the outcome is the only way callers can
|
|
450
|
+
* tell "the turn is gone" apart from "we asked, but it is still running".
|
|
451
|
+
*
|
|
452
|
+
* - `withdrawn` — the prompt had not started yet and was removed from the
|
|
453
|
+
* host's inbox; no turn was cancelled.
|
|
454
|
+
* - `cancelled` — the active turn (or maintenance job) was cancelled and the
|
|
455
|
+
* host reported the session idle.
|
|
456
|
+
* - `unconfirmed` — the cancel was rejected/lost, or the session still reports
|
|
457
|
+
* an open turn afterwards. A turn may still be running.
|
|
458
|
+
* - `noop` — there was no session to stop (e.g. stop during setup).
|
|
459
|
+
*/
|
|
460
|
+
export type StopStatus = 'withdrawn' | 'cancelled' | 'unconfirmed' | 'noop';
|
|
461
|
+
export interface StopOutcome {
|
|
462
|
+
status: StopStatus;
|
|
463
|
+
sessionId?: string;
|
|
464
|
+
/** Human-readable reason for `unconfirmed` (logged, not shown verbatim). */
|
|
465
|
+
detail?: string;
|
|
466
|
+
}
|
|
405
467
|
/**
|
|
406
468
|
* Seam (§3): the contract any agent runner (claude/codex/opencode/pi/kimi/dsh)
|
|
407
469
|
* must satisfy for the router/bridge.
|
|
@@ -417,10 +479,14 @@ export interface Runner {
|
|
|
417
479
|
* Stop the running process. SIGTERM → grace → SIGKILL on the per-workspace
|
|
418
480
|
* proc. `immediate: true` skips the grace period and SIGKILLs directly
|
|
419
481
|
* (used by user-initiated `/stop`).
|
|
482
|
+
*
|
|
483
|
+
* Runners whose work is remote (DSH) return a {@link StopOutcome} instead of
|
|
484
|
+
* `void` so callers can tell a confirmed stop from a best-effort request;
|
|
485
|
+
* process runners keep returning `void`.
|
|
420
486
|
*/
|
|
421
487
|
stop(opts?: {
|
|
422
488
|
immediate?: boolean;
|
|
423
|
-
}): Promise<void>;
|
|
489
|
+
}): Promise<void | StopOutcome>;
|
|
424
490
|
killOrphan(): void;
|
|
425
491
|
registerExitHandlers(): void;
|
|
426
492
|
/**
|
|
@@ -441,6 +507,8 @@ export interface Runner {
|
|
|
441
507
|
*/
|
|
442
508
|
export declare const AGENT_KINDS: readonly ["claude", "codex", "opencode", "pi", "kimi", "dsh"];
|
|
443
509
|
export type AgentKind = (typeof AGENT_KINDS)[number];
|
|
510
|
+
/** 用户可见 agent 显示名单源:启动注册与无 registry 的回退路径共用。 */
|
|
511
|
+
export declare const AGENT_DISPLAY_NAMES: Record<AgentKind, string>;
|
|
444
512
|
/**
|
|
445
513
|
* Compact 能力声明(运行时门控的能力清单,编译期强制完整)。
|
|
446
514
|
*
|
|
@@ -463,11 +531,36 @@ export interface AgentSession {
|
|
|
463
531
|
mtime: number;
|
|
464
532
|
/** DSH:session 创建时固定的 preset;其他 agent 无此概念(undefined)。 */
|
|
465
533
|
agentPreset?: string;
|
|
534
|
+
/**
|
|
535
|
+
* 服务端投影已有的会话标题(DSH `projections.values.title`)。
|
|
536
|
+
*
|
|
537
|
+
* 与 `summary` 的区别:`summary` 是「首条用户输入」的兜底口径(claude /
|
|
538
|
+
* codex / pi / kimi 无标题字段),`title` 是 agent 自己起的标题。列表卡
|
|
539
|
+
* 用它决定标签文案(标题 / 会话摘要),缺省时回退 `summary`。
|
|
540
|
+
*/
|
|
541
|
+
title?: string;
|
|
542
|
+
/**
|
|
543
|
+
* 最后一轮用户输入(服务端投影,单行预览)。
|
|
544
|
+
*
|
|
545
|
+
* 只给「列表响应里已顺带返回」的 reader 用(DSH 的 `turnOutline` 末条),
|
|
546
|
+
* 目的是让列表卡不必为每行做一次全量内容读取。
|
|
547
|
+
*/
|
|
548
|
+
lastUserMessage?: string;
|
|
549
|
+
/** 最后一轮助手输出(服务端投影已截断,单行预览)。 */
|
|
550
|
+
lastAssistantMessage?: string;
|
|
466
551
|
}
|
|
467
552
|
/** A single renderable event from session history. */
|
|
468
553
|
export interface AgentSessionContentEvent {
|
|
469
554
|
type: string;
|
|
555
|
+
/** 正文(展开后的面板内容)。 */
|
|
470
556
|
content: string;
|
|
557
|
+
/**
|
|
558
|
+
* 面板标题(可选,覆盖 reader 的默认标签)。
|
|
559
|
+
*
|
|
560
|
+
* 折叠面板默认只显示标题:工具调用这种"标题即全部信息"的事件必须把
|
|
561
|
+
* `bash — npm test` 这类摘要放进标题,否则折叠态只剩 `🔧 工具调用`。
|
|
562
|
+
*/
|
|
563
|
+
title?: string;
|
|
471
564
|
timestamp?: string;
|
|
472
565
|
}
|
|
473
566
|
export interface AgentSessionUsage {
|
package/dist/runner/types.js
CHANGED
|
@@ -16,6 +16,15 @@
|
|
|
16
16
|
* 新增 agent 只改这里。
|
|
17
17
|
*/
|
|
18
18
|
export const AGENT_KINDS = ['claude', 'codex', 'opencode', 'pi', 'kimi', 'dsh'];
|
|
19
|
+
/** 用户可见 agent 显示名单源:启动注册与无 registry 的回退路径共用。 */
|
|
20
|
+
export const AGENT_DISPLAY_NAMES = {
|
|
21
|
+
claude: 'Claude',
|
|
22
|
+
codex: 'Codex',
|
|
23
|
+
opencode: 'Opencode',
|
|
24
|
+
pi: 'Pi',
|
|
25
|
+
kimi: 'Kimi',
|
|
26
|
+
dsh: 'DSH',
|
|
27
|
+
};
|
|
19
28
|
/**
|
|
20
29
|
* Compact 能力声明(运行时门控的能力清单,编译期强制完整)。
|
|
21
30
|
*
|
|
@@ -74,10 +74,6 @@ export declare class SessionIndex {
|
|
|
74
74
|
private readonly byCwd;
|
|
75
75
|
private lastRefreshAt;
|
|
76
76
|
private built;
|
|
77
|
-
/** Test-only: count of parseSessionJsonl calls since creation */
|
|
78
|
-
parseCount: number;
|
|
79
|
-
/** Test-only: count of directory scan operations */
|
|
80
|
-
scanCount: number;
|
|
81
77
|
constructor(projectsDir: string, opts?: SessionIndexOptions);
|
|
82
78
|
/** Whether a full scan has ever completed successfully (readdir succeeded). */
|
|
83
79
|
get isBuilt(): boolean;
|
|
@@ -146,10 +146,6 @@ export class SessionIndex {
|
|
|
146
146
|
byCwd = new Map();
|
|
147
147
|
lastRefreshAt = 0;
|
|
148
148
|
built = false;
|
|
149
|
-
/** Test-only: count of parseSessionJsonl calls since creation */
|
|
150
|
-
parseCount = 0;
|
|
151
|
-
/** Test-only: count of directory scan operations */
|
|
152
|
-
scanCount = 0;
|
|
153
149
|
constructor(projectsDir, opts = {}) {
|
|
154
150
|
this.projectsDir = projectsDir;
|
|
155
151
|
this.refreshIntervalMs = opts.refreshIntervalMs ?? 5000;
|
|
@@ -161,7 +157,6 @@ export class SessionIndex {
|
|
|
161
157
|
}
|
|
162
158
|
// ── Build (initial full scan) ───────────────────────────
|
|
163
159
|
build() {
|
|
164
|
-
this.scanCount++;
|
|
165
160
|
this.fullScan();
|
|
166
161
|
this.lastRefreshAt = Date.now();
|
|
167
162
|
}
|
|
@@ -171,7 +166,6 @@ export class SessionIndex {
|
|
|
171
166
|
if (now - this.lastRefreshAt < this.refreshIntervalMs) {
|
|
172
167
|
return; // throttled
|
|
173
168
|
}
|
|
174
|
-
this.scanCount++;
|
|
175
169
|
this.fullScan();
|
|
176
170
|
this.lastRefreshAt = now;
|
|
177
171
|
}
|
|
@@ -232,7 +226,6 @@ export class SessionIndex {
|
|
|
232
226
|
}
|
|
233
227
|
// Fingerprint changed → re-parse this single file
|
|
234
228
|
const parsed = parseSessionJsonl(p);
|
|
235
|
-
this.parseCount++;
|
|
236
229
|
try {
|
|
237
230
|
const st = fs.statSync(p, { bigint: true });
|
|
238
231
|
const updated = {
|
|
@@ -303,7 +296,6 @@ export class SessionIndex {
|
|
|
303
296
|
// Concurrent-write guard: stat before and after parse, compare fingerprints
|
|
304
297
|
const fpBefore = fp;
|
|
305
298
|
const parsed = parseSessionJsonl(fullPath);
|
|
306
|
-
this.parseCount++;
|
|
307
299
|
const fpAfter = buildFingerprint(fullPath);
|
|
308
300
|
if (fpBefore !== fpAfter) {
|
|
309
301
|
// File was modified during parse → skip this round, retry next refresh
|
|
@@ -15,8 +15,8 @@ import { SessionIndex, extractText, isTaskNotificationText, CLAUDE_MAPPING, } fr
|
|
|
15
15
|
* win32 上 `\` 同样是分隔符、`:` 是非法文件名字符,一并归一为 `-`
|
|
16
16
|
* (`C:\Users\x\proj` -> `C--Users-x-proj`);见 encodeProjectDirName。
|
|
17
17
|
*
|
|
18
|
-
* Note: this encoding is LOSSY (`
|
|
19
|
-
* `
|
|
18
|
+
* Note: this encoding is LOSSY (`my_data/foo` and `my-data/foo` both encode to
|
|
19
|
+
* `my-data-foo`). It is only safe to use the result to **locate** files; never
|
|
20
20
|
* to **decode** a directory name back to a cwd. The cwd must always be read
|
|
21
21
|
* from the JSONL content (regression 2026-06-21 /resume & /cd 路径错乱).
|
|
22
22
|
*/
|