lark-remote 0.5.12 → 0.5.14
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 +28 -2
- package/README.en.md +1 -14
- package/README.md +1 -14
- 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 +1 -0
- package/dist/bridge/approval-coordinator.js +12 -24
- package/dist/bridge/final-usage.d.ts +8 -17
- package/dist/bridge/final-usage.js +1 -18
- package/dist/bridge/index.d.ts +52 -38
- package/dist/bridge/index.js +255 -433
- package/dist/bridge/queue-manager.d.ts +25 -1
- package/dist/bridge/queue-manager.js +179 -160
- package/dist/bridge/run-approval.d.ts +16 -0
- package/dist/bridge/run-approval.js +41 -0
- package/dist/bridge/run-usage.d.ts +32 -0
- package/dist/bridge/run-usage.js +87 -0
- package/dist/bridge/session-writeback.d.ts +19 -0
- package/dist/bridge/session-writeback.js +36 -0
- package/dist/card/approval-render.d.ts +3 -2
- package/dist/card/approval-render.js +3 -2
- package/dist/card/bash-card-session.js +2 -5
- 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 +6 -2
- package/dist/card/card-session.js +28 -28
- package/dist/card/card-shared.d.ts +4 -4
- package/dist/card/card-shared.js +4 -10
- package/dist/card/collapsible.js +3 -2
- package/dist/card/final-answer-overflow.d.ts +1 -0
- package/dist/card/final-answer-overflow.js +46 -0
- package/dist/card/run-card-session.d.ts +2 -2
- package/dist/card/run-card-session.js +4 -9
- package/dist/card/run-renderer.d.ts +14 -0
- package/dist/card/run-renderer.js +126 -23
- package/dist/card/run-state.d.ts +40 -51
- package/dist/card/run-state.js +96 -34
- 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/codex-config.js +4 -4
- package/dist/config/index.d.ts +18 -20
- package/dist/config/index.js +6 -20
- 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 +3 -4
- package/dist/dsh/home.d.ts +2 -0
- package/dist/dsh/home.js +8 -0
- package/dist/dsh/protocol.d.ts +9 -0
- package/dist/dsh/protocol.js +61 -0
- package/dist/inbound/turn-assembler.js +6 -0
- package/dist/index.js +25 -414
- package/dist/message-handlers.d.ts +26 -0
- package/dist/message-handlers.js +275 -0
- 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/card-action-payload.d.ts +1 -1
- package/dist/router/card-action-payload.js +1 -1
- package/dist/router/commands/ls.d.ts +9 -0
- package/dist/router/commands/ls.js +243 -0
- package/dist/router/commands/order.d.ts +12 -0
- package/dist/router/commands/order.js +178 -0
- package/dist/router/commands/resume.d.ts +48 -0
- package/dist/router/commands/resume.js +246 -0
- package/dist/router/commands/ws.d.ts +15 -0
- package/dist/router/commands/ws.js +189 -0
- package/dist/router/config/claude.js +5 -4
- package/dist/router/config/codex.js +2 -6
- package/dist/router/config/common/render.d.ts +5 -1
- package/dist/router/config/common/render.js +6 -13
- package/dist/router/config/common/turn-idle.d.ts +2 -0
- package/dist/router/config/common/turn-idle.js +9 -0
- package/dist/router/config/dsh.d.ts +1 -1
- package/dist/router/config/index.d.ts +1 -1
- package/dist/router/config/kimi.js +2 -6
- package/dist/router/config/opencode.js +2 -6
- package/dist/router/config/types.d.ts +11 -3
- package/dist/router/index.d.ts +55 -33
- package/dist/router/index.js +233 -1376
- package/dist/router/paging.d.ts +13 -0
- package/dist/router/paging.js +20 -0
- package/dist/router/path-validation.d.ts +27 -0
- package/dist/router/path-validation.js +45 -0
- package/dist/runner/agent-choices-common.d.ts +1 -1
- package/dist/runner/claude/runner.d.ts +23 -6
- package/dist/runner/claude/runner.js +6 -20
- package/dist/runner/claude/session.js +1 -1
- package/dist/runner/codex/app-server/runner.d.ts +3 -1
- package/dist/runner/codex/app-server/translator.d.ts +13 -0
- package/dist/runner/codex/app-server/translator.js +114 -151
- package/dist/runner/common/acp/base-acp-runner.d.ts +3 -1
- package/dist/runner/common/acp/base-translator.d.ts +3 -8
- package/dist/runner/common/acp/base-translator.js +16 -7
- package/dist/runner/common/connection-based-runner.d.ts +3 -1
- package/dist/runner/common/jsonrpc/transport.js +17 -7
- package/dist/runner/common/spawning-runner.js +10 -4
- package/dist/runner/common/turn-started.d.ts +2 -0
- package/dist/runner/common/turn-started.js +10 -0
- package/dist/runner/dsh/client.d.ts +2 -10
- package/dist/runner/dsh/client.js +13 -220
- package/dist/runner/dsh/daemon.d.ts +0 -2
- package/dist/runner/dsh/daemon.js +9 -7
- package/dist/runner/dsh/errors.d.ts +5 -0
- package/dist/runner/dsh/errors.js +11 -0
- package/dist/runner/dsh/exit-cancel.d.ts +0 -2
- package/dist/runner/dsh/exit-cancel.js +2 -2
- package/dist/runner/dsh/inflight.d.ts +0 -2
- package/dist/runner/dsh/inflight.js +1 -1
- package/dist/runner/dsh/mux-stream.d.ts +26 -0
- package/dist/runner/dsh/mux-stream.js +176 -0
- package/dist/runner/dsh/runner.d.ts +21 -1
- package/dist/runner/dsh/runner.js +76 -73
- package/dist/runner/dsh/translator.d.ts +1 -11
- package/dist/runner/dsh/translator.js +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/kimi/acp/translator.js +1 -12
- 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 +3 -1
- package/dist/runner/opencode/acp/translator.js +1 -12
- package/dist/runner/pi/rpc/runner.d.ts +2 -1
- package/dist/runner/pi/rpc/translator.d.ts +2 -8
- package/dist/runner/pi/rpc/translator.js +2 -7
- package/dist/runner/probe.d.ts +1 -1
- package/dist/runner/probe.js +10 -9
- package/dist/runner/registry.d.ts +2 -20
- package/dist/runner/registry.js +0 -32
- package/dist/runner/types.d.ts +37 -155
- package/dist/runner/types.js +4 -24
- package/dist/session/claude/session-index.d.ts +11 -4
- package/dist/session/claude/session-index.js +34 -10
- 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 +37 -10
- package/dist/session/opencode/sessions.d.ts +1 -1
- package/dist/session/opencode/sessions.js +53 -48
- package/dist/session/pi/sessions.d.ts +1 -1
- package/dist/session/pi/sessions.js +23 -9
- 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}/types.d.ts +0 -0
- /package/dist/{runner/dsh → dsh}/types.js +0 -0
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* `result` from that response.
|
|
11
11
|
* - `agent_settled` is ignored for compaction turns (no double result).
|
|
12
12
|
*/
|
|
13
|
+
import { makeTurnStartedEvent } from '../../common/turn-started.js';
|
|
13
14
|
export class PiRpcTranslator {
|
|
14
15
|
content = [];
|
|
15
16
|
currentContentIndex = -1;
|
|
@@ -135,13 +136,7 @@ export class PiRpcTranslator {
|
|
|
135
136
|
/** Self-produced turn_started (no wire equivalent). */
|
|
136
137
|
produceTurnStarted(sessionId, turnId) {
|
|
137
138
|
this.sessionId = sessionId;
|
|
138
|
-
return
|
|
139
|
-
type: 'turn_started',
|
|
140
|
-
threadId: sessionId,
|
|
141
|
-
turnId,
|
|
142
|
-
operationKind: this.operationKind === 'compact' ? 'compaction' : 'turn',
|
|
143
|
-
timestamp: new Date().toISOString(),
|
|
144
|
-
};
|
|
139
|
+
return makeTurnStartedEvent(sessionId, turnId, this.operationKind);
|
|
145
140
|
}
|
|
146
141
|
/** Result for a completed normal turn (agent_settled). */
|
|
147
142
|
produceResultFromSettled() {
|
package/dist/runner/probe.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* does PATH + X_OK on posix (same semantics) and PATH × PATHEXT on win32,
|
|
18
18
|
* with no child process at all.
|
|
19
19
|
*/
|
|
20
|
-
import type { AgentKind } from '
|
|
20
|
+
import type { AgentKind } from '../agent-kinds.js';
|
|
21
21
|
/**
|
|
22
22
|
* Probe a single agent, using cache when fresh.
|
|
23
23
|
* Updates cache on completion.
|
package/dist/runner/probe.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* with no child process at all.
|
|
19
19
|
*/
|
|
20
20
|
import { resolveExecutable } from '../platform/command.js';
|
|
21
|
+
import { TtlCache } from '../common/ttl-cache.js';
|
|
21
22
|
/** Map from AgentKind to its CLI binary name. */
|
|
22
23
|
const BINARY_MAP = {
|
|
23
24
|
claude: 'claude',
|
|
@@ -30,8 +31,11 @@ const BINARY_MAP = {
|
|
|
30
31
|
dsh: '',
|
|
31
32
|
};
|
|
32
33
|
const CACHE_TTL_MS = 5 * 60_000;
|
|
33
|
-
/**
|
|
34
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Module-level cache, survives across calls within the process. 键集就是
|
|
36
|
+
* AgentKind(有界),因此不设条目上限;共享 `TtlCache` 与 session readers 同语义。
|
|
37
|
+
*/
|
|
38
|
+
const cache = new TtlCache(CACHE_TTL_MS);
|
|
35
39
|
/**
|
|
36
40
|
* Probe a single agent's availability (pure PATH lookup; dsh has no CLI
|
|
37
41
|
* binary and is always unavailable here).
|
|
@@ -49,10 +53,10 @@ async function probeOne(kind) {
|
|
|
49
53
|
*/
|
|
50
54
|
export async function probeAgentAvailability(kind) {
|
|
51
55
|
const cached = cache.get(kind);
|
|
52
|
-
if (cached
|
|
53
|
-
return cached
|
|
56
|
+
if (cached !== undefined)
|
|
57
|
+
return cached;
|
|
54
58
|
const ok = await probeOne(kind);
|
|
55
|
-
cache.set(kind,
|
|
59
|
+
cache.set(kind, ok);
|
|
56
60
|
return ok;
|
|
57
61
|
}
|
|
58
62
|
/**
|
|
@@ -76,10 +80,7 @@ export async function probeAllAgents() {
|
|
|
76
80
|
* Used by synchronous code paths (e.g. buildConfigCard) that cannot await.
|
|
77
81
|
*/
|
|
78
82
|
export function getCachedAvailability(kind) {
|
|
79
|
-
|
|
80
|
-
if (!cached || Date.now() - cached.ts >= CACHE_TTL_MS)
|
|
81
|
-
return undefined;
|
|
82
|
-
return cached.ok;
|
|
83
|
+
return cache.get(kind);
|
|
83
84
|
}
|
|
84
85
|
/** Clear all cache entries. Exported for test use only (cache auto-expires via TTL). */
|
|
85
86
|
export function _clearCacheForTest() {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { AgentKind
|
|
1
|
+
import type { AgentKind } from '../agent-kinds.js';
|
|
2
|
+
import type { Runner } from './index.js';
|
|
2
3
|
/**
|
|
3
4
|
* Registry of agent factories, keyed by `AgentKind`. `index.ts` registers one
|
|
4
5
|
* factory per available agent at startup; `Bridge.getRunner(cwd)` looks
|
|
@@ -14,28 +15,9 @@ import type { AgentKind, Runner } from './index.js';
|
|
|
14
15
|
*/
|
|
15
16
|
export declare class AgentRegistry {
|
|
16
17
|
private readonly factories;
|
|
17
|
-
private readonly displayNames;
|
|
18
18
|
/** Container for runtime config updates (pi provider dynamic reload). */
|
|
19
19
|
private configContainer?;
|
|
20
20
|
register(kind: AgentKind, factory: (cwd: string) => Runner): void;
|
|
21
|
-
/**
|
|
22
|
-
* 注册 agent 的显示名。应在 register(kind, factory) 后调用。
|
|
23
|
-
* 用于 agentDisplayName 等全局查询,实现单点真相。
|
|
24
|
-
*/
|
|
25
|
-
registerDisplayName(kind: AgentKind, displayName: string): void;
|
|
26
|
-
/**
|
|
27
|
-
* 获取 agent 显示名。未注册时返回原始 kind。
|
|
28
|
-
*/
|
|
29
|
-
getDisplayName(kind: AgentKind): string;
|
|
30
|
-
/**
|
|
31
|
-
* 设置全局 registry 实例,供 agentDisplayName 等全局函数使用。
|
|
32
|
-
* 在 index.ts 初始化所有 agents 后调用。
|
|
33
|
-
*/
|
|
34
|
-
static setGlobalInstance(reg: AgentRegistry | undefined): void;
|
|
35
|
-
/**
|
|
36
|
-
* 获取全局 registry 实例。
|
|
37
|
-
*/
|
|
38
|
-
static getGlobalInstance(): AgentRegistry | undefined;
|
|
39
21
|
/**
|
|
40
22
|
* Set config container reference. Call after bridge config is updated.
|
|
41
23
|
* Factory functions can read latest config from here.
|
package/dist/runner/registry.js
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 单例 registry 实例,供 agentDisplayName 等全局查询使用。
|
|
3
|
-
* 在 index.ts 初始化后设置。
|
|
4
|
-
*/
|
|
5
|
-
let globalRegistry;
|
|
6
1
|
/**
|
|
7
2
|
* Registry of agent factories, keyed by `AgentKind`. `index.ts` registers one
|
|
8
3
|
* factory per available agent at startup; `Bridge.getRunner(cwd)` looks
|
|
@@ -18,38 +13,11 @@ let globalRegistry;
|
|
|
18
13
|
*/
|
|
19
14
|
export class AgentRegistry {
|
|
20
15
|
factories = new Map();
|
|
21
|
-
displayNames = new Map();
|
|
22
16
|
/** Container for runtime config updates (pi provider dynamic reload). */
|
|
23
17
|
configContainer;
|
|
24
18
|
register(kind, factory) {
|
|
25
19
|
this.factories.set(kind, factory);
|
|
26
20
|
}
|
|
27
|
-
/**
|
|
28
|
-
* 注册 agent 的显示名。应在 register(kind, factory) 后调用。
|
|
29
|
-
* 用于 agentDisplayName 等全局查询,实现单点真相。
|
|
30
|
-
*/
|
|
31
|
-
registerDisplayName(kind, displayName) {
|
|
32
|
-
this.displayNames.set(kind, displayName);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* 获取 agent 显示名。未注册时返回原始 kind。
|
|
36
|
-
*/
|
|
37
|
-
getDisplayName(kind) {
|
|
38
|
-
return this.displayNames.get(kind) ?? kind;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* 设置全局 registry 实例,供 agentDisplayName 等全局函数使用。
|
|
42
|
-
* 在 index.ts 初始化所有 agents 后调用。
|
|
43
|
-
*/
|
|
44
|
-
static setGlobalInstance(reg) {
|
|
45
|
-
globalRegistry = reg;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* 获取全局 registry 实例。
|
|
49
|
-
*/
|
|
50
|
-
static getGlobalInstance() {
|
|
51
|
-
return globalRegistry;
|
|
52
|
-
}
|
|
53
21
|
/**
|
|
54
22
|
* Set config container reference. Call after bridge config is updated.
|
|
55
23
|
* Factory functions can read latest config from here.
|
package/dist/runner/types.d.ts
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 本文件包含所有 Agent 相关的类型定义,从 runner/index.ts 提取。
|
|
5
5
|
* 所有下游模块应从本文件 import 类型,而非直接依赖实现。
|
|
6
|
+
* (例外:`AgentKind` 住在 `src/agent-kinds.ts`,见文件底部说明。)
|
|
6
7
|
*/
|
|
8
|
+
import type { AgentKind } from '../agent-kinds.js';
|
|
9
|
+
import type { AgentSessionReader } from '../session-contract.js';
|
|
7
10
|
export interface SystemInitEvent {
|
|
8
11
|
type: 'system';
|
|
9
12
|
subtype: 'init';
|
|
@@ -263,6 +266,22 @@ export interface AssistantEvent {
|
|
|
263
266
|
content: AssistantContent[];
|
|
264
267
|
};
|
|
265
268
|
}
|
|
269
|
+
/**
|
|
270
|
+
* Authoritative final answer from an agent protocol.
|
|
271
|
+
*
|
|
272
|
+
* This is deliberately separate from ordinary assistant text: progress
|
|
273
|
+
* narration and tool-loop messages have lower display priority than the answer
|
|
274
|
+
* the user actually asked for. Agents without an explicit protocol marker
|
|
275
|
+
* promote their last text block when the turn finishes.
|
|
276
|
+
*/
|
|
277
|
+
export interface FinalAnswerEvent {
|
|
278
|
+
type: 'final_answer';
|
|
279
|
+
text: string;
|
|
280
|
+
/** Source item id, used to remove the streamed progress copy of the answer. */
|
|
281
|
+
itemId?: string;
|
|
282
|
+
complete?: boolean;
|
|
283
|
+
timestamp?: string;
|
|
284
|
+
}
|
|
266
285
|
export interface UserEvent {
|
|
267
286
|
type: 'user';
|
|
268
287
|
timestamp?: string;
|
|
@@ -470,7 +489,7 @@ export interface TurnDiffEvent {
|
|
|
470
489
|
export type RunnerLifetime = 'turn' | 'workspace';
|
|
471
490
|
/** 工具渲染 hint:runner 自愿声明,渲染层只消费不推断。 */
|
|
472
491
|
export type ToolHint = 'shell' | 'file' | 'search' | 'web' | 'patch';
|
|
473
|
-
export type AgentEvent = SystemInitEvent | SystemCompactEvent | ApprovalRequestedEvent | ApprovalResolvedEvent | ApprovalViewUpdatedEvent | ApprovalExpiredEvent | AssistantEvent | UserEvent | ResultEvent | PlanEvent | FileChangeEvent | TurnStartedEvent | TurnDiffEvent | NoticeEvent | SessionInfoEvent | RunStatusEvent | BackgroundJobsEvent | GoalStateEvent;
|
|
492
|
+
export type AgentEvent = SystemInitEvent | SystemCompactEvent | ApprovalRequestedEvent | ApprovalResolvedEvent | ApprovalViewUpdatedEvent | ApprovalExpiredEvent | AssistantEvent | FinalAnswerEvent | UserEvent | ResultEvent | PlanEvent | FileChangeEvent | TurnStartedEvent | TurnDiffEvent | NoticeEvent | SessionInfoEvent | RunStatusEvent | BackgroundJobsEvent | GoalStateEvent;
|
|
474
493
|
export interface SpawnOptions {
|
|
475
494
|
cwd: string;
|
|
476
495
|
sessionId?: string;
|
|
@@ -536,18 +555,7 @@ export interface Runner {
|
|
|
536
555
|
*/
|
|
537
556
|
unregisterExitHandlers?(): void;
|
|
538
557
|
}
|
|
539
|
-
|
|
540
|
-
* Agent 名单单源(运行时数组 + 类型同源,二者不可能漂移)。
|
|
541
|
-
*
|
|
542
|
-
* 历史上这份名单被手抄成多份(router 的 VALID_AGENTS、bridge 的 resume.compact
|
|
543
|
-
* 校验、各 agent 的 config builder…),漂移过:dsh 加入后 bridge 的
|
|
544
|
-
* resume.compact 仍只有 5 个,带 dsh 的 resume 卡片会静默退回 defaultAgent。
|
|
545
|
-
* 新增 agent 只改这里。
|
|
546
|
-
*/
|
|
547
|
-
export declare const AGENT_KINDS: readonly ["claude", "codex", "opencode", "pi", "kimi", "dsh"];
|
|
548
|
-
export type AgentKind = (typeof AGENT_KINDS)[number];
|
|
549
|
-
/** 用户可见 agent 显示名单源:启动注册与无 registry 的回退路径共用。 */
|
|
550
|
-
export declare const AGENT_DISPLAY_NAMES: Record<AgentKind, string>;
|
|
558
|
+
export { AGENT_DISPLAY_NAMES } from '../agent-kinds.js';
|
|
551
559
|
/**
|
|
552
560
|
* Compact 能力声明(运行时门控的能力清单,编译期强制完整)。
|
|
553
561
|
*
|
|
@@ -563,147 +571,6 @@ export declare const AGENT_DISPLAY_NAMES: Record<AgentKind, string>;
|
|
|
563
571
|
export declare const COMPACT_CAPABILITY: Readonly<Record<AgentKind, boolean>>;
|
|
564
572
|
/** 该 agent 是否声明支持 compact(渲染门控与执行门控共用的唯一判据)。 */
|
|
565
573
|
export declare function supportsCompact(kind: AgentKind): boolean;
|
|
566
|
-
/** Unified session descriptor returned by every AgentSessionReader. */
|
|
567
|
-
export interface AgentSession {
|
|
568
|
-
sessionId: string;
|
|
569
|
-
summary: string;
|
|
570
|
-
mtime: number;
|
|
571
|
-
/** DSH:session 创建时固定的 preset;其他 agent 无此概念(undefined)。 */
|
|
572
|
-
agentPreset?: string;
|
|
573
|
-
/**
|
|
574
|
-
* 服务端投影已有的会话标题(DSH `projections.values.title`)。
|
|
575
|
-
*
|
|
576
|
-
* 与 `summary` 的区别:`summary` 是「首条用户输入」的兜底口径(claude /
|
|
577
|
-
* codex / pi / kimi 无标题字段),`title` 是 agent 自己起的标题。列表卡
|
|
578
|
-
* 用它决定标签文案(标题 / 会话摘要),缺省时回退 `summary`。
|
|
579
|
-
*/
|
|
580
|
-
title?: string;
|
|
581
|
-
/**
|
|
582
|
-
* 最后一轮用户输入(服务端投影,单行预览)。
|
|
583
|
-
*
|
|
584
|
-
* 只给「列表响应里已顺带返回」的 reader 用(DSH 的 `turnOutline` 末条),
|
|
585
|
-
* 目的是让列表卡不必为每行做一次全量内容读取。
|
|
586
|
-
*/
|
|
587
|
-
lastUserMessage?: string;
|
|
588
|
-
/** 最后一轮助手输出(服务端投影已截断,单行预览)。 */
|
|
589
|
-
lastAssistantMessage?: string;
|
|
590
|
-
}
|
|
591
|
-
/** A single renderable event from session history. */
|
|
592
|
-
export interface AgentSessionContentEvent {
|
|
593
|
-
type: string;
|
|
594
|
-
/** 正文(展开后的面板内容)。 */
|
|
595
|
-
content: string;
|
|
596
|
-
/**
|
|
597
|
-
* 面板标题(可选,覆盖 reader 的默认标签)。
|
|
598
|
-
*
|
|
599
|
-
* 折叠面板默认只显示标题:工具调用这种"标题即全部信息"的事件必须把
|
|
600
|
-
* `bash — npm test` 这类摘要放进标题,否则折叠态只剩 `🔧 工具调用`。
|
|
601
|
-
*/
|
|
602
|
-
title?: string;
|
|
603
|
-
timestamp?: string;
|
|
604
|
-
}
|
|
605
|
-
export interface AgentSessionUsage {
|
|
606
|
-
inputTokens: number;
|
|
607
|
-
outputTokens: number;
|
|
608
|
-
contextLength: number;
|
|
609
|
-
/** Agent 上报的当前模型 context window 上限(codex token_count.info.model_context_window)。
|
|
610
|
-
* 仅 codex 提供;缺省时卡片只显示绝对量、不显示百分比。 */
|
|
611
|
-
contextLimit?: number;
|
|
612
|
-
/** Claude auto-compact 次数(数 compact_boundary 事件);codex/opencode 无此概念,留 undefined。 */
|
|
613
|
-
compactCount?: number;
|
|
614
|
-
/** 压缩前上下文水位(codex compact 后从会话 jsonl 读取,仅会话以压缩收尾时有值)。 */
|
|
615
|
-
compactPreContextLength?: number;
|
|
616
|
-
/** 从缓存读取的 token 数(节省的费用)。 */
|
|
617
|
-
cacheReadTokens?: number;
|
|
618
|
-
/** 新建缓存的 token 数。 */
|
|
619
|
-
cacheCreationTokens?: number;
|
|
620
|
-
/** Agent 声明的总量;展示用 max(total, 分项和)。 */
|
|
621
|
-
totalTokens?: number;
|
|
622
|
-
/** 会话累计 total token(所有 run 之和,含本次)。用于 Run 卡片"累计"展示。 */
|
|
623
|
-
cumulativeTotalTokens?: number;
|
|
624
|
-
/** 会话累计 input token(所有 run 之和,含本次)。用于 Run 卡片"累计"展示。 */
|
|
625
|
-
cumulativeInputTokens?: number;
|
|
626
|
-
/** 会话累计 output token(所有 run 之和,含本次)。 */
|
|
627
|
-
cumulativeOutputTokens?: number;
|
|
628
|
-
/** 会话累计 cache read token(所有 run 之和)。用于 Run 卡片展示累计缓存命中。 */
|
|
629
|
-
cumulativeCacheReadTokens?: number;
|
|
630
|
-
/** 会话累计 cache creation token(所有 run 之和)。 */
|
|
631
|
-
cumulativeCacheCreationTokens?: number;
|
|
632
|
-
}
|
|
633
|
-
/** Unified session content payload returned by every AgentSessionReader. */
|
|
634
|
-
export interface SessionContent {
|
|
635
|
-
events: AgentSessionContentEvent[];
|
|
636
|
-
usage?: AgentSessionUsage;
|
|
637
|
-
aiTitle?: string;
|
|
638
|
-
recap?: string;
|
|
639
|
-
displayTitle?: string;
|
|
640
|
-
}
|
|
641
|
-
/**
|
|
642
|
-
* Lightweight session summary used by `/resume` list prefetch.
|
|
643
|
-
*
|
|
644
|
-
* Carries only the display fields (title / recap / usage) — **no `events`
|
|
645
|
-
* array**. Readers that can extract these without constructing the full event
|
|
646
|
-
* list (e.g. codex, which would otherwise JSON.parse every response_item and
|
|
647
|
-
* build an `events[]` that the prefetch immediately discards) implement the
|
|
648
|
-
* optional `readSessionSummary` on `AgentSessionReader`.
|
|
649
|
-
*/
|
|
650
|
-
export interface SessionSummary {
|
|
651
|
-
aiTitle?: string;
|
|
652
|
-
recap?: string;
|
|
653
|
-
displayTitle?: string;
|
|
654
|
-
usage?: AgentSessionUsage;
|
|
655
|
-
}
|
|
656
|
-
/**
|
|
657
|
-
* Reads an agent's session history. Each agent implements its own (Claude reads
|
|
658
|
-
* `~/.claude/projects/`, Codex calls `thread/list`, OpenCode calls `GET /session`).
|
|
659
|
-
*
|
|
660
|
-
* Q-C decision: `projectsDir` and other agent-specific path config live on the
|
|
661
|
-
* concrete reader's constructor, NOT on these method opts. The router/bridge
|
|
662
|
-
* depend only on this interface and never pass path config.
|
|
663
|
-
*/
|
|
664
|
-
export interface AgentSessionReader {
|
|
665
|
-
/**
|
|
666
|
-
* List sessions for a cwd, newest first by mtime.
|
|
667
|
-
*
|
|
668
|
-
* `sessions` is the page `[offset, offset+limit)` of the full set ordered
|
|
669
|
-
* by mtime desc, with same-mtime ties broken by a deterministic secondary
|
|
670
|
-
* key (sessionId/file path) so ordering is stable across calls. When
|
|
671
|
-
* `limit` is omitted, codex/pi/kimi return their default-sized page
|
|
672
|
-
* (default 20); claude/opencode return the full remaining set from
|
|
673
|
-
* `offset`. `total` is ALWAYS the size of the full cwd-matched set before
|
|
674
|
-
* pagination — never the truncated page length. A negative `offset` is
|
|
675
|
-
* clamped to 0 (first page).
|
|
676
|
-
*/
|
|
677
|
-
listSessions(cwd: string, opts?: {
|
|
678
|
-
limit?: number;
|
|
679
|
-
offset?: number;
|
|
680
|
-
}): {
|
|
681
|
-
sessions: AgentSession[];
|
|
682
|
-
total: number;
|
|
683
|
-
};
|
|
684
|
-
getNewestSession(cwd: string): AgentSession | null;
|
|
685
|
-
readSessionContent(sessionId: string, cwd: string, opts?: {
|
|
686
|
-
maxEvents?: number;
|
|
687
|
-
}): SessionContent;
|
|
688
|
-
/**
|
|
689
|
-
* Optional lightweight summary for list-prefetch.
|
|
690
|
-
*
|
|
691
|
-
* Returns only the display fields (aiTitle/recap/displayTitle/usage) without
|
|
692
|
-
* constructing the full `events` array. When absent, callers fall back to
|
|
693
|
-
* `readSessionContent` and take the needed fields.
|
|
694
|
-
*/
|
|
695
|
-
readSessionSummary?(sessionId: string, cwd: string): SessionSummary;
|
|
696
|
-
/**
|
|
697
|
-
* Whether a session is still active (process may still be running).
|
|
698
|
-
*
|
|
699
|
-
* Dormant API: no production caller reads this today — the router decides
|
|
700
|
-
* "is an agent running" via the in-memory `bridge.isBusyFor(cwd)` (see
|
|
701
|
-
* `cmdPs`), not by probing session files. Retained on the reader contract
|
|
702
|
-
* because all 5 readers implement it and it is the natural hook if a
|
|
703
|
-
* file-based liveness check is ever needed; not wired into the bridge.
|
|
704
|
-
*/
|
|
705
|
-
isSessionActive(sessionId: string, cwd: string): boolean;
|
|
706
|
-
}
|
|
707
574
|
/**
|
|
708
575
|
* AgentRunner extends Runner with agent identity and a session reader.
|
|
709
576
|
* Bridge/Router depend on this interface so adding a new agent is
|
|
@@ -716,6 +583,22 @@ export interface AgentRunner extends Runner {
|
|
|
716
583
|
getStatusInfo(): AgentStatusInfo;
|
|
717
584
|
/** Whether this runner provides live usage data (vs. file-based). */
|
|
718
585
|
getUsageAuthority?(): 'live' | 'jsonl';
|
|
586
|
+
/**
|
|
587
|
+
* 回传审批决策(codex thread/permissions、ACP elicitation、DSH approval
|
|
588
|
+
* resolve)。未实现的 agent 由协调器按「无人应答」超时收尾。
|
|
589
|
+
*/
|
|
590
|
+
respondApproval?(requestId: number | string, response: unknown): Promise<void>;
|
|
591
|
+
/**
|
|
592
|
+
* 停止 agent 侧的一个后台任务(DSH 的 background job)。只有支持后台任务的
|
|
593
|
+
* agent 实现;调用方按能力存在与否门控。
|
|
594
|
+
*/
|
|
595
|
+
killJob?(sessionId: string, jobId: string): Promise<boolean>;
|
|
596
|
+
/**
|
|
597
|
+
* 热更审批模式/权限预设(config.save 后推给在跑的 runner,不必重启会话)。
|
|
598
|
+
* 各家 settings 词表不同(codex: approvalPolicy/sandbox;kimi: permissionMode;
|
|
599
|
+
* opencode: mode;dsh: permissionPreset),故为开放载荷。
|
|
600
|
+
*/
|
|
601
|
+
updateApprovalMode?(settings: Record<string, unknown>): Promise<void>;
|
|
719
602
|
}
|
|
720
603
|
/** Agent self-describing status info for /status display. */
|
|
721
604
|
export interface AgentStatusInfo {
|
|
@@ -730,4 +613,3 @@ export interface AgentStatusInfo {
|
|
|
730
613
|
/** Agent-specific extra fields (e.g. codex.sandbox). */
|
|
731
614
|
extras?: Record<string, string>;
|
|
732
615
|
}
|
|
733
|
-
export {};
|
package/dist/runner/types.js
CHANGED
|
@@ -1,30 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Runner 模块类型定义
|
|
3
|
-
*
|
|
4
|
-
* 本文件包含所有 Agent 相关的类型定义,从 runner/index.ts 提取。
|
|
5
|
-
* 所有下游模块应从本文件 import 类型,而非直接依赖实现。
|
|
6
|
-
*/
|
|
7
1
|
// =============================================================================
|
|
8
2
|
// Multi-Agent Adapter Types
|
|
9
3
|
// =============================================================================
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* 校验、各 agent 的 config builder…),漂移过:dsh 加入后 bridge 的
|
|
15
|
-
* resume.compact 仍只有 5 个,带 dsh 的 resume 卡片会静默退回 defaultAgent。
|
|
16
|
-
* 新增 agent 只改这里。
|
|
17
|
-
*/
|
|
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
|
-
};
|
|
4
|
+
// Agent 名单与显示名住在 `src/agent-kinds.ts`(中立层,config/session/card 都
|
|
5
|
+
// 要用);本模块只 import `AgentKind` 类型来签名 runner 契约。保留旧路径的
|
|
6
|
+
// re-export 兼容调用方,但值仍只由 agent-kinds.ts 定义。
|
|
7
|
+
export { AGENT_DISPLAY_NAMES } from '../agent-kinds.js';
|
|
28
8
|
/**
|
|
29
9
|
* Compact 能力声明(运行时门控的能力清单,编译期强制完整)。
|
|
30
10
|
*
|
|
@@ -74,15 +74,22 @@ export declare class SessionIndex {
|
|
|
74
74
|
private readonly byCwd;
|
|
75
75
|
private lastRefreshAt;
|
|
76
76
|
private built;
|
|
77
|
+
private scanError?;
|
|
77
78
|
constructor(projectsDir: string, opts?: SessionIndexOptions);
|
|
78
79
|
/** Whether a full scan has ever completed successfully (readdir succeeded). */
|
|
79
80
|
get isBuilt(): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* 最近一次全量扫描的非 ENOENT 失败(undefined = 上次扫描正常)。
|
|
83
|
+
* list 路径用它把「读不到」与「真的没有」区分开。
|
|
84
|
+
*/
|
|
85
|
+
get lastScanError(): unknown;
|
|
80
86
|
build(): void;
|
|
81
87
|
refresh(): void;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
/**
|
|
89
|
+
* 该 cwd 的全部会话(newest first)。分页不在这里:`listSessions` 的
|
|
90
|
+
* offset/limit 契约由 reader 用共享 `paginate()` 完成,索引只负责有序全集。
|
|
91
|
+
*/
|
|
92
|
+
listByCwd(cwd: string): SessionIndexEntry[];
|
|
86
93
|
/**
|
|
87
94
|
* Find a session entry by sessionId and cwd.
|
|
88
95
|
* Re-stats the file to verify fingerprint before returning (拍板 3):
|
|
@@ -83,6 +83,7 @@ export function parseSessionJsonl(filePath) {
|
|
|
83
83
|
});
|
|
84
84
|
// If file couldn't be opened, return empty result
|
|
85
85
|
if (!ok) {
|
|
86
|
+
getLogger().debug(`[session-index] unreadable session file ${filePath}, treating as empty`);
|
|
86
87
|
return { cwdSet: new Set(), summary: '(无摘要)' };
|
|
87
88
|
}
|
|
88
89
|
return { cwdSet, summary };
|
|
@@ -98,7 +99,12 @@ export function buildFingerprint(filePath) {
|
|
|
98
99
|
try {
|
|
99
100
|
st = fs.statSync(filePath, { bigint: true });
|
|
100
101
|
}
|
|
101
|
-
catch {
|
|
102
|
+
catch (err) {
|
|
103
|
+
// ENOENT = 文件在扫描间隙被删除(正常竞态)。其余(EACCES/EBUSY…)留痕,
|
|
104
|
+
// 否则该会话会静默从 /resume 列表里消失。
|
|
105
|
+
if (err.code !== 'ENOENT') {
|
|
106
|
+
getLogger().warn(`[session-index] cannot stat ${filePath}: ${err?.message ?? String(err)}`);
|
|
107
|
+
}
|
|
102
108
|
return '';
|
|
103
109
|
}
|
|
104
110
|
const parts = [String(st.size), String(st.mtimeNs)];
|
|
@@ -153,6 +159,7 @@ export class SessionIndex {
|
|
|
153
159
|
byCwd = new Map();
|
|
154
160
|
lastRefreshAt = 0;
|
|
155
161
|
built = false;
|
|
162
|
+
scanError;
|
|
156
163
|
constructor(projectsDir, opts = {}) {
|
|
157
164
|
this.projectsDir = projectsDir;
|
|
158
165
|
this.refreshIntervalMs = opts.refreshIntervalMs ?? 5000;
|
|
@@ -162,6 +169,13 @@ export class SessionIndex {
|
|
|
162
169
|
get isBuilt() {
|
|
163
170
|
return this.built;
|
|
164
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* 最近一次全量扫描的非 ENOENT 失败(undefined = 上次扫描正常)。
|
|
174
|
+
* list 路径用它把「读不到」与「真的没有」区分开。
|
|
175
|
+
*/
|
|
176
|
+
get lastScanError() {
|
|
177
|
+
return this.scanError;
|
|
178
|
+
}
|
|
165
179
|
// ── Build (initial full scan) ───────────────────────────
|
|
166
180
|
build() {
|
|
167
181
|
this.fullScan();
|
|
@@ -177,7 +191,11 @@ export class SessionIndex {
|
|
|
177
191
|
this.lastRefreshAt = now;
|
|
178
192
|
}
|
|
179
193
|
// ── Query: listByCwd ────────────────────────────────────
|
|
180
|
-
|
|
194
|
+
/**
|
|
195
|
+
* 该 cwd 的全部会话(newest first)。分页不在这里:`listSessions` 的
|
|
196
|
+
* offset/limit 契约由 reader 用共享 `paginate()` 完成,索引只负责有序全集。
|
|
197
|
+
*/
|
|
198
|
+
listByCwd(cwd) {
|
|
181
199
|
const paths = this.byCwd.get(pathKey(cwd, { platform: this.platform }));
|
|
182
200
|
if (!paths || paths.size === 0)
|
|
183
201
|
return [];
|
|
@@ -194,10 +212,7 @@ export class SessionIndex {
|
|
|
194
212
|
}
|
|
195
213
|
const sorted = [...byId.values()];
|
|
196
214
|
sortByRecencyDesc(sorted, (s) => s.mtimeMs, (s) => s.sessionId);
|
|
197
|
-
|
|
198
|
-
const limit = opts.limit;
|
|
199
|
-
const sliced = limit === undefined ? sorted.slice(offset) : sorted.slice(offset, offset + limit);
|
|
200
|
-
return sliced;
|
|
215
|
+
return sorted;
|
|
201
216
|
}
|
|
202
217
|
// ── Query: findBySessionIdAndCwd ────────────────────────
|
|
203
218
|
/**
|
|
@@ -261,11 +276,18 @@ export class SessionIndex {
|
|
|
261
276
|
try {
|
|
262
277
|
entries = fs.readdirSync(this.projectsDir);
|
|
263
278
|
}
|
|
264
|
-
catch {
|
|
279
|
+
catch (err) {
|
|
265
280
|
// readdir failure → preserve old index, degrade to fallback
|
|
266
|
-
|
|
281
|
+
if (err.code === 'ENOENT') {
|
|
282
|
+
// projectsDir 不存在 = 全新环境(真空态),不是故障。
|
|
283
|
+
this.scanError = undefined;
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
this.scanError = err;
|
|
287
|
+
getLogger().warn(`[session-index] readdir ${this.projectsDir} failed, preserving old index: ${err?.message ?? String(err)}`);
|
|
267
288
|
return;
|
|
268
289
|
}
|
|
290
|
+
this.scanError = undefined;
|
|
269
291
|
// readdir succeeded → the snapshot is authoritative for what we could read.
|
|
270
292
|
this.built = true;
|
|
271
293
|
const currentPaths = new Set();
|
|
@@ -277,14 +299,16 @@ export class SessionIndex {
|
|
|
277
299
|
if (!st.isDirectory())
|
|
278
300
|
continue;
|
|
279
301
|
}
|
|
280
|
-
catch {
|
|
302
|
+
catch (err) {
|
|
303
|
+
getLogger().debug(`[session-index] skipped unreadable project dir ${subdir}: ${err?.message ?? String(err)}`);
|
|
281
304
|
continue;
|
|
282
305
|
}
|
|
283
306
|
let files;
|
|
284
307
|
try {
|
|
285
308
|
files = fs.readdirSync(subdir).filter((f) => f.endsWith('.jsonl'));
|
|
286
309
|
}
|
|
287
|
-
catch {
|
|
310
|
+
catch (err) {
|
|
311
|
+
getLogger().debug(`[session-index] skipped unreadable project subdir ${subdir}: ${err?.message ?? String(err)}`);
|
|
288
312
|
continue;
|
|
289
313
|
}
|
|
290
314
|
for (const f of files) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentSession, AgentSessionReader, SessionContent } from '../../
|
|
1
|
+
import type { AgentSession, AgentSessionReader, SessionContent } from '../../session-contract.js';
|
|
2
2
|
/**
|
|
3
3
|
* Adapter that exposes Claude Code's session-reading functions through the
|
|
4
4
|
* unified `AgentSessionReader` interface. This lets `SessionReaderRegistry`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentSession, AgentSessionContentEvent, AgentSessionUsage } from '../../
|
|
1
|
+
import type { AgentSession, AgentSessionContentEvent, AgentSessionUsage } from '../../session-contract.js';
|
|
2
2
|
/**
|
|
3
3
|
* List Claude Code sessions for a given cwd, newest first. Each entry has
|
|
4
4
|
* the sessionId (= jsonl filename stem), a one-line summary extracted from
|
|
@@ -15,7 +15,7 @@ export declare function getNewestSession(cwd: string, opts?: {
|
|
|
15
15
|
}): AgentSession | undefined;
|
|
16
16
|
/**
|
|
17
17
|
* Check if a Claude session (by sessionId + cwd) is still active.
|
|
18
|
-
* Public wrapper around the internal `
|
|
18
|
+
* Public wrapper around the internal `hasRecentFileActivity(filePath, mtimeMs, now)`
|
|
19
19
|
* for use by `ClaudeSessionReader` and the multi-agent adapter layer.
|
|
20
20
|
*
|
|
21
21
|
* Resolves the jsonl path via `projectDirForCwd`, stats it for mtime, then
|