lark-remote 0.1.5 → 0.1.7
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 +39 -0
- package/README.en.md +5 -1
- package/README.md +10 -2
- package/dist/bridge/approval-coordinator.d.ts +131 -0
- package/dist/bridge/approval-coordinator.js +409 -0
- package/dist/bridge/inbound-media.d.ts +62 -0
- package/dist/bridge/inbound-media.js +282 -0
- package/dist/bridge/index.d.ts +138 -5
- package/dist/bridge/index.js +569 -65
- package/dist/bridge/queue-manager.d.ts +11 -1
- package/dist/bridge/queue-manager.js +20 -11
- package/dist/card/approval-render.d.ts +16 -0
- package/dist/card/approval-render.js +363 -0
- package/dist/card/bash-card-session.d.ts +2 -24
- package/dist/card/bash-card-session.js +6 -73
- package/dist/card/bash-renderer.js +2 -3
- package/dist/card/card-budget.js +29 -75
- package/dist/card/card-session.d.ts +48 -0
- package/dist/card/card-session.js +86 -0
- package/dist/card/card-shared.d.ts +13 -10
- package/dist/card/card-shared.js +27 -24
- package/dist/card/run-card-session.d.ts +2 -55
- package/dist/card/run-card-session.js +6 -104
- package/dist/card/run-renderer.js +140 -202
- package/dist/card/run-state.d.ts +38 -3
- package/dist/card/run-state.js +221 -11
- package/dist/card/text-truncate.d.ts +13 -12
- package/dist/card/text-truncate.js +13 -63
- package/dist/common/fs.d.ts +8 -0
- package/dist/common/fs.js +17 -0
- package/dist/common/guards.d.ts +0 -20
- package/dist/common/guards.js +0 -43
- package/dist/common/sleep.d.ts +2 -0
- package/dist/common/sleep.js +5 -0
- package/dist/common/truncate.d.ts +39 -0
- package/dist/common/truncate.js +92 -0
- package/dist/config/codex-config.d.ts +1 -1
- package/dist/config/codex-config.js +1 -1
- package/dist/config/dir.js +1 -1
- package/dist/config/index.d.ts +116 -9
- package/dist/config/index.js +122 -29
- package/dist/connector/index.d.ts +74 -2
- package/dist/connector/index.js +119 -1
- package/dist/index.js +139 -99
- package/dist/instance-lock.js +4 -12
- package/dist/order/alias-resolve.d.ts +13 -0
- package/dist/order/alias-resolve.js +22 -0
- package/dist/order/alias-store.d.ts +38 -0
- package/dist/order/alias-store.js +106 -0
- package/dist/persistence/atomic-write.d.ts +8 -2
- package/dist/persistence/atomic-write.js +23 -7
- package/dist/restart.js +2 -1
- package/dist/router/card-helpers.d.ts +63 -0
- package/dist/router/card-helpers.js +146 -0
- package/dist/router/config/claude.js +25 -1
- package/dist/router/config/codex.d.ts +1 -1
- package/dist/router/config/codex.js +33 -5
- package/dist/router/config/common/model-patch.d.ts +22 -0
- package/dist/router/config/common/model-patch.js +26 -0
- package/dist/router/config/common/render.js +9 -4
- package/dist/router/config/index.d.ts +12 -0
- package/dist/router/config/index.js +25 -1
- package/dist/router/config/kimi.d.ts +4 -1
- package/dist/router/config/kimi.js +27 -0
- package/dist/router/config/opencode.js +18 -5
- package/dist/router/config/pi.js +4 -5
- package/dist/router/config/types.d.ts +12 -3
- package/dist/router/index.d.ts +77 -17
- package/dist/router/index.js +455 -549
- package/dist/router/utils.d.ts +4 -0
- package/dist/router/utils.js +9 -2
- package/dist/runner/agent-choices-common.d.ts +16 -0
- package/dist/runner/agent-choices-common.js +31 -0
- package/dist/runner/claude/runner.d.ts +47 -10
- package/dist/runner/claude/runner.js +117 -46
- package/dist/runner/claude/session.d.ts +166 -0
- package/dist/runner/claude/session.js +749 -0
- package/dist/runner/codex/app-server/protocol-types.d.ts +519 -0
- package/dist/runner/codex/app-server/protocol-types.js +56 -0
- package/dist/runner/codex/app-server/runner.d.ts +104 -0
- package/dist/runner/codex/app-server/runner.js +377 -0
- package/dist/runner/codex/app-server/translator.d.ts +89 -0
- package/dist/runner/codex/app-server/translator.js +716 -0
- package/dist/runner/codex/index.d.ts +1 -1
- package/dist/runner/codex/index.js +1 -1
- package/dist/runner/common/acp/protocol-helpers.d.ts +14 -0
- package/dist/runner/common/acp/protocol-helpers.js +21 -0
- package/dist/runner/common/acp/protocol-types.d.ts +238 -0
- package/dist/runner/common/acp/protocol-types.js +75 -0
- package/dist/runner/common/connection-based-runner.d.ts +111 -0
- package/dist/runner/common/connection-based-runner.js +261 -0
- package/dist/runner/common/jsonrpc/client.d.ts +89 -0
- package/dist/runner/common/jsonrpc/client.js +243 -0
- package/dist/runner/common/jsonrpc/connection-manager.d.ts +125 -0
- package/dist/runner/common/jsonrpc/connection-manager.js +205 -0
- package/dist/runner/common/jsonrpc/transport.d.ts +50 -0
- package/dist/runner/common/jsonrpc/transport.js +230 -0
- package/dist/runner/common/jsonrpc/types.d.ts +32 -0
- package/dist/runner/common/jsonrpc/types.js +9 -0
- package/dist/runner/common/process-stopper.d.ts +2 -1
- package/dist/runner/common/process-stopper.js +1 -0
- package/dist/runner/common/runner-utils.d.ts +6 -13
- package/dist/runner/common/runner-utils.js +6 -47
- package/dist/runner/common/spawning-runner.d.ts +24 -70
- package/dist/runner/common/spawning-runner.js +98 -152
- package/dist/runner/common/usage.d.ts +2 -0
- package/dist/runner/common/usage.js +2 -0
- package/dist/runner/index.d.ts +5 -5
- package/dist/runner/index.js +4 -4
- package/dist/runner/kimi/acp/runner.d.ts +106 -0
- package/dist/runner/kimi/acp/runner.js +448 -0
- package/dist/runner/kimi/acp/translator.d.ts +124 -0
- package/dist/runner/kimi/acp/translator.js +336 -0
- package/dist/runner/kimi/index.d.ts +1 -1
- package/dist/runner/kimi/index.js +1 -1
- package/dist/runner/opencode/acp/index.d.ts +1 -0
- package/dist/runner/opencode/acp/index.js +2 -0
- package/dist/runner/opencode/acp/runner.d.ts +121 -0
- package/dist/runner/opencode/acp/runner.js +429 -0
- package/dist/runner/opencode/acp/translator.d.ts +119 -0
- package/dist/runner/opencode/acp/translator.js +345 -0
- package/dist/runner/opencode/index.d.ts +1 -1
- package/dist/runner/opencode/index.js +1 -1
- package/dist/runner/pi/index.d.ts +1 -1
- package/dist/runner/pi/index.js +1 -1
- package/dist/runner/pi/rpc/client.d.ts +52 -0
- package/dist/runner/pi/rpc/client.js +114 -0
- package/dist/runner/pi/rpc/index.d.ts +4 -0
- package/dist/runner/pi/rpc/index.js +4 -0
- package/dist/runner/pi/rpc/protocol-types.d.ts +127 -0
- package/dist/runner/pi/rpc/protocol-types.js +21 -0
- package/dist/runner/pi/rpc/runner.d.ts +80 -0
- package/dist/runner/pi/rpc/runner.js +199 -0
- package/dist/runner/pi/rpc/translator.d.ts +55 -0
- package/dist/runner/pi/rpc/translator.js +258 -0
- package/dist/runner/registry.d.ts +7 -8
- package/dist/runner/registry.js +3 -4
- package/dist/runner/resolve-agent-choices.js +18 -59
- package/dist/runner/sync-agent-choices.js +16 -67
- package/dist/runner/types.d.ts +153 -2
- package/dist/session/claude/session-index.js +2 -3
- package/dist/session/claude/session-reader.js +3 -6
- package/dist/session/claude/sessions.js +6 -13
- package/dist/session/codex/rollout-reader.d.ts +2 -2
- package/dist/session/codex/rollout-reader.js +57 -17
- package/dist/session/codex/sessions.d.ts +1 -1
- package/dist/session/codex/sessions.js +2 -2
- package/dist/session/common/content-blocks.d.ts +7 -0
- package/dist/session/common/content-blocks.js +13 -9
- package/dist/session/common/jsonl.d.ts +8 -25
- package/dist/session/common/jsonl.js +126 -261
- package/dist/session/common/pagination.d.ts +28 -0
- package/dist/session/common/pagination.js +33 -0
- package/dist/session/kimi/sessions.d.ts +34 -1
- package/dist/session/kimi/sessions.js +208 -98
- package/dist/session/opencode/sessions.d.ts +17 -3
- package/dist/session/opencode/sessions.js +29 -29
- package/dist/session/pi/sessions.d.ts +5 -1
- package/dist/session/pi/sessions.js +12 -16
- package/dist/session/session-store.d.ts +11 -1
- package/dist/session/session-store.js +75 -178
- package/dist/update/index.d.ts +2 -2
- package/dist/update/index.js +2 -2
- package/dist/update/install.d.ts +20 -2
- package/dist/update/install.js +51 -7
- package/package.json +1 -1
- package/dist/runner/codex/argv.d.ts +0 -33
- package/dist/runner/codex/argv.js +0 -40
- package/dist/runner/codex/jsonl.d.ts +0 -37
- package/dist/runner/codex/jsonl.js +0 -221
- package/dist/runner/codex/runner.d.ts +0 -63
- package/dist/runner/codex/runner.js +0 -124
- package/dist/runner/common/exec-translator.d.ts +0 -73
- package/dist/runner/common/exec-translator.js +0 -105
- package/dist/runner/kimi/jsonl.d.ts +0 -28
- package/dist/runner/kimi/jsonl.js +0 -143
- package/dist/runner/kimi/runner.d.ts +0 -49
- package/dist/runner/kimi/runner.js +0 -105
- package/dist/runner/opencode/argv.d.ts +0 -32
- package/dist/runner/opencode/argv.js +0 -35
- package/dist/runner/opencode/jsonl.d.ts +0 -68
- package/dist/runner/opencode/jsonl.js +0 -295
- package/dist/runner/opencode/runner.d.ts +0 -61
- package/dist/runner/opencode/runner.js +0 -93
- package/dist/runner/pi/jsonl.d.ts +0 -128
- package/dist/runner/pi/jsonl.js +0 -249
- package/dist/runner/pi/runner.d.ts +0 -36
- package/dist/runner/pi/runner.js +0 -76
- package/dist/session/common/catch-up.d.ts +0 -12
- package/dist/session/common/catch-up.js +0 -31
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { choiceFieldsFor } from './agent-choices-common.js';
|
|
1
2
|
export function resolveAgentChoices(config) {
|
|
2
|
-
const choices = config.agentChoices;
|
|
3
3
|
const agent = config.defaultAgent;
|
|
4
|
+
const choices = config.agentChoices;
|
|
4
5
|
if (!choices || !agent) {
|
|
5
6
|
return config;
|
|
6
7
|
}
|
|
@@ -9,67 +10,25 @@ export function resolveAgentChoices(config) {
|
|
|
9
10
|
return config;
|
|
10
11
|
}
|
|
11
12
|
const agentChoices = choices[agent];
|
|
12
|
-
|
|
13
|
+
const fields = choiceFieldsFor(agent);
|
|
14
|
+
if (!agentChoices || !fields) {
|
|
13
15
|
return config;
|
|
14
16
|
}
|
|
15
17
|
// Clone to avoid mutation
|
|
16
|
-
const resolved =
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (!resolvedAny.agents.codex.modelProvider && agentChoicesAny.modelProvider) {
|
|
31
|
-
resolvedAny.agents.codex.modelProvider = agentChoicesAny.modelProvider;
|
|
32
|
-
}
|
|
33
|
-
break;
|
|
34
|
-
case 'pi':
|
|
35
|
-
if (!resolvedAny.agents)
|
|
36
|
-
resolvedAny.agents = {};
|
|
37
|
-
if (!resolvedAny.agents.pi)
|
|
38
|
-
resolvedAny.agents.pi = {};
|
|
39
|
-
if (!resolvedAny.agents.pi.model && agentChoicesAny.model) {
|
|
40
|
-
resolvedAny.agents.pi.model = agentChoicesAny.model;
|
|
41
|
-
}
|
|
42
|
-
if (!resolvedAny.agents.pi.provider && agentChoicesAny.provider) {
|
|
43
|
-
resolvedAny.agents.pi.provider = agentChoicesAny.provider;
|
|
44
|
-
}
|
|
45
|
-
if (!resolvedAny.agents.pi.thinking && agentChoicesAny.thinking) {
|
|
46
|
-
resolvedAny.agents.pi.thinking = agentChoicesAny.thinking;
|
|
47
|
-
}
|
|
48
|
-
break;
|
|
49
|
-
case 'opencode':
|
|
50
|
-
if (!resolvedAny.agents)
|
|
51
|
-
resolvedAny.agents = {};
|
|
52
|
-
if (!resolvedAny.agents.opencode)
|
|
53
|
-
resolvedAny.agents.opencode = {};
|
|
54
|
-
if (!resolvedAny.agents.opencode.modelID && agentChoicesAny.modelID) {
|
|
55
|
-
resolvedAny.agents.opencode.modelID = agentChoicesAny.modelID;
|
|
56
|
-
}
|
|
57
|
-
if (!resolvedAny.agents.opencode.providerID && agentChoicesAny.providerID) {
|
|
58
|
-
resolvedAny.agents.opencode.providerID = agentChoicesAny.providerID;
|
|
59
|
-
}
|
|
60
|
-
break;
|
|
61
|
-
case 'kimi':
|
|
62
|
-
if (!resolvedAny.agents)
|
|
63
|
-
resolvedAny.agents = {};
|
|
64
|
-
if (!resolvedAny.agents.kimi)
|
|
65
|
-
resolvedAny.agents.kimi = {};
|
|
66
|
-
if (!resolvedAny.agents.kimi.model && agentChoicesAny.model) {
|
|
67
|
-
resolvedAny.agents.kimi.model = agentChoicesAny.model;
|
|
68
|
-
}
|
|
69
|
-
if (!resolvedAny.agents.kimi.thinkingEffort && agentChoicesAny.thinkingEffort) {
|
|
70
|
-
resolvedAny.agents.kimi.thinkingEffort = agentChoicesAny.thinkingEffort;
|
|
71
|
-
}
|
|
72
|
-
break;
|
|
18
|
+
const resolved = structuredClone(config);
|
|
19
|
+
// agents.codex 在 schema 中必填(带默认值),此处按旧语义补空对象;
|
|
20
|
+
// 运行时只往 [agent] 槽位写字段,不依赖 codex 默认值。
|
|
21
|
+
if (!resolved.agents) {
|
|
22
|
+
resolved.agents = {};
|
|
23
|
+
}
|
|
24
|
+
const agents = resolved.agents;
|
|
25
|
+
const target = (agents[agent] ??= {});
|
|
26
|
+
const source = agentChoices;
|
|
27
|
+
for (const { configKey, choicesKey } of fields) {
|
|
28
|
+
const value = source[choicesKey];
|
|
29
|
+
if (!target[configKey] && value) {
|
|
30
|
+
target[configKey] = value;
|
|
31
|
+
}
|
|
73
32
|
}
|
|
74
33
|
return resolved;
|
|
75
34
|
}
|
|
@@ -1,72 +1,21 @@
|
|
|
1
|
+
import { choiceFieldsFor } from './agent-choices-common.js';
|
|
1
2
|
export function syncAgentChoices(config, agent) {
|
|
2
|
-
//
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const agentCfg = agents[agent];
|
|
6
|
-
// claude reads from top-level config.claude, not agents.claude
|
|
7
|
-
if (agent !== 'claude' && !agentCfg) {
|
|
3
|
+
// claude 的配置在顶层 config.claude,不在 agents 下,无需同步
|
|
4
|
+
const fields = choiceFieldsFor(agent);
|
|
5
|
+
if (!fields)
|
|
8
6
|
return config;
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
updatedAny.agentChoices.codex.model = agentCfg.model;
|
|
22
|
-
}
|
|
23
|
-
if (agentCfg.modelProvider) {
|
|
24
|
-
if (!updatedAny.agentChoices.codex)
|
|
25
|
-
updatedAny.agentChoices.codex = {};
|
|
26
|
-
updatedAny.agentChoices.codex.modelProvider = agentCfg.modelProvider;
|
|
27
|
-
}
|
|
28
|
-
break;
|
|
29
|
-
case 'pi':
|
|
30
|
-
if (agentCfg.model) {
|
|
31
|
-
if (!updatedAny.agentChoices.pi)
|
|
32
|
-
updatedAny.agentChoices.pi = {};
|
|
33
|
-
updatedAny.agentChoices.pi.model = agentCfg.model;
|
|
34
|
-
}
|
|
35
|
-
if (agentCfg.provider) {
|
|
36
|
-
if (!updatedAny.agentChoices.pi)
|
|
37
|
-
updatedAny.agentChoices.pi = {};
|
|
38
|
-
updatedAny.agentChoices.pi.provider = agentCfg.provider;
|
|
39
|
-
}
|
|
40
|
-
if (agentCfg.thinking) {
|
|
41
|
-
if (!updatedAny.agentChoices.pi)
|
|
42
|
-
updatedAny.agentChoices.pi = {};
|
|
43
|
-
updatedAny.agentChoices.pi.thinking = agentCfg.thinking;
|
|
44
|
-
}
|
|
45
|
-
break;
|
|
46
|
-
case 'opencode':
|
|
47
|
-
if (agentCfg.modelID) {
|
|
48
|
-
if (!updatedAny.agentChoices.opencode)
|
|
49
|
-
updatedAny.agentChoices.opencode = {};
|
|
50
|
-
updatedAny.agentChoices.opencode.modelID = agentCfg.modelID;
|
|
51
|
-
}
|
|
52
|
-
if (agentCfg.providerID) {
|
|
53
|
-
if (!updatedAny.agentChoices.opencode)
|
|
54
|
-
updatedAny.agentChoices.opencode = {};
|
|
55
|
-
updatedAny.agentChoices.opencode.providerID = agentCfg.providerID;
|
|
56
|
-
}
|
|
57
|
-
break;
|
|
58
|
-
case 'kimi':
|
|
59
|
-
if (agentCfg.model) {
|
|
60
|
-
if (!updatedAny.agentChoices.kimi)
|
|
61
|
-
updatedAny.agentChoices.kimi = {};
|
|
62
|
-
updatedAny.agentChoices.kimi.model = agentCfg.model;
|
|
63
|
-
}
|
|
64
|
-
if (agentCfg.thinkingEffort) {
|
|
65
|
-
if (!updatedAny.agentChoices.kimi)
|
|
66
|
-
updatedAny.agentChoices.kimi = {};
|
|
67
|
-
updatedAny.agentChoices.kimi.thinkingEffort = agentCfg.thinkingEffort;
|
|
68
|
-
}
|
|
69
|
-
break;
|
|
7
|
+
const agents = config.agents;
|
|
8
|
+
const agentCfg = agents?.[agent];
|
|
9
|
+
if (!agentCfg)
|
|
10
|
+
return config;
|
|
11
|
+
const updated = structuredClone(config);
|
|
12
|
+
const choices = (updated.agentChoices ??= {});
|
|
13
|
+
const agentChoices = (choices[agent] ??= {});
|
|
14
|
+
const source = agentCfg;
|
|
15
|
+
for (const { configKey, choicesKey } of fields) {
|
|
16
|
+
const value = source[configKey];
|
|
17
|
+
if (value)
|
|
18
|
+
agentChoices[choicesKey] = value;
|
|
70
19
|
}
|
|
71
20
|
return updated;
|
|
72
21
|
}
|
package/dist/runner/types.d.ts
CHANGED
|
@@ -21,6 +21,105 @@ interface SystemCompactEvent {
|
|
|
21
21
|
preTokens: number;
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
+
export interface ApprovalRequestedEvent {
|
|
25
|
+
type: 'approval_requested';
|
|
26
|
+
/** JSON-RPC id of the server request. Wire type is string | integer — keep raw. */
|
|
27
|
+
requestId: number | string;
|
|
28
|
+
kind: 'command' | 'file' | 'permissions' | 'question';
|
|
29
|
+
threadId: string;
|
|
30
|
+
turnId: string;
|
|
31
|
+
itemId: string;
|
|
32
|
+
view: ApprovalView;
|
|
33
|
+
timestamp?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ApprovalResolvedEvent {
|
|
36
|
+
type: 'approval_resolved';
|
|
37
|
+
requestId: number | string;
|
|
38
|
+
outcome: 'resolved' | 'expired';
|
|
39
|
+
timestamp?: string;
|
|
40
|
+
}
|
|
41
|
+
/** Approval card content update (out-of-order item/started arrives late). */
|
|
42
|
+
export interface ApprovalViewUpdatedEvent {
|
|
43
|
+
type: 'approval_view_updated';
|
|
44
|
+
requestId: number | string;
|
|
45
|
+
view: ApprovalView;
|
|
46
|
+
timestamp?: string;
|
|
47
|
+
}
|
|
48
|
+
/** Approval expired locally (bridge-side timeout) — card should show expired UI. */
|
|
49
|
+
export interface ApprovalExpiredEvent {
|
|
50
|
+
type: 'approval_expired';
|
|
51
|
+
requestId: number | string;
|
|
52
|
+
timestamp?: string;
|
|
53
|
+
}
|
|
54
|
+
/** 审批决策(bridge ApprovalCoordinator → runner.respondApproval 的响应载荷)。 */
|
|
55
|
+
export type ApprovalAction = {
|
|
56
|
+
action: 'accept';
|
|
57
|
+
} | {
|
|
58
|
+
action: 'accept_for_session';
|
|
59
|
+
} | {
|
|
60
|
+
action: 'accept_with_execpolicy_amendment';
|
|
61
|
+
}
|
|
62
|
+
/** Claude:允许当前请求 + 本会话后续所有权限请求自动放行(允许所有)。 */
|
|
63
|
+
| {
|
|
64
|
+
action: 'accept_all';
|
|
65
|
+
} | {
|
|
66
|
+
action: 'decline';
|
|
67
|
+
} | {
|
|
68
|
+
action: 'cancel';
|
|
69
|
+
}
|
|
70
|
+
/** Claude AskUserQuestion 答案(question → label 或 label[])。 */
|
|
71
|
+
| {
|
|
72
|
+
action: 'answer';
|
|
73
|
+
answers: Record<string, string | string[]>;
|
|
74
|
+
};
|
|
75
|
+
/** Claude Code AskUserQuestion 的单个选项(control_request input.questions[].options[])。 */
|
|
76
|
+
export interface ClaudeUserQuestionOption {
|
|
77
|
+
label: string;
|
|
78
|
+
description?: string;
|
|
79
|
+
}
|
|
80
|
+
/** Claude Code AskUserQuestion 的单个问题(control_request input.questions[])。 */
|
|
81
|
+
export interface ClaudeUserQuestion {
|
|
82
|
+
question: string;
|
|
83
|
+
header?: string;
|
|
84
|
+
multiSelect?: boolean;
|
|
85
|
+
options: ClaudeUserQuestionOption[];
|
|
86
|
+
/**
|
|
87
|
+
* 当前已选选项 label(卡片渲染与多选切换用;单选在协调器内即时提交)。
|
|
88
|
+
* 与 permissions.items.selected 同模式:协调器原地更新后以
|
|
89
|
+
* approval_view_updated 重新渲染。
|
|
90
|
+
*/
|
|
91
|
+
selected?: string[];
|
|
92
|
+
}
|
|
93
|
+
export interface ApprovalView {
|
|
94
|
+
requestId: number | string;
|
|
95
|
+
kind: 'command' | 'file' | 'permissions' | 'question';
|
|
96
|
+
reason?: string;
|
|
97
|
+
command?: string;
|
|
98
|
+
commandCwd?: string;
|
|
99
|
+
fileChanges?: Array<{
|
|
100
|
+
path: string;
|
|
101
|
+
kind: 'add' | 'update' | 'delete';
|
|
102
|
+
diff?: string;
|
|
103
|
+
}>;
|
|
104
|
+
permissions?: {
|
|
105
|
+
items: Array<{
|
|
106
|
+
id: string;
|
|
107
|
+
label: string;
|
|
108
|
+
target: {
|
|
109
|
+
kind: 'network';
|
|
110
|
+
} | {
|
|
111
|
+
kind: 'fsRead' | 'fsWrite';
|
|
112
|
+
path: string;
|
|
113
|
+
};
|
|
114
|
+
selected: boolean;
|
|
115
|
+
}>;
|
|
116
|
+
};
|
|
117
|
+
/** Claude AskUserQuestion 问题列表(kind === 'question' 时存在)。 */
|
|
118
|
+
questions?: ClaudeUserQuestion[];
|
|
119
|
+
availableDecisions: string[];
|
|
120
|
+
/** Raw payloads for structured decisions (e.g. acceptWithExecpolicyAmendment). */
|
|
121
|
+
decisionPayloads?: Record<string, unknown>;
|
|
122
|
+
}
|
|
24
123
|
interface ThinkingContent {
|
|
25
124
|
type: 'thinking';
|
|
26
125
|
thinking: string;
|
|
@@ -58,7 +157,7 @@ export interface UserEvent {
|
|
|
58
157
|
}
|
|
59
158
|
export interface ResultEvent {
|
|
60
159
|
type: 'result';
|
|
61
|
-
subtype: 'success' | 'error';
|
|
160
|
+
subtype: 'success' | 'error' | 'interrupted';
|
|
62
161
|
session_id: string;
|
|
63
162
|
timestamp?: string;
|
|
64
163
|
usage?: {
|
|
@@ -75,6 +174,9 @@ export interface ResultEvent {
|
|
|
75
174
|
cache_creation_input_tokens?: number;
|
|
76
175
|
/** Agent-declared total; when present the display uses max(total, sum of parts). */
|
|
77
176
|
total_tokens?: number;
|
|
177
|
+
/** 当前模型 context window 上限(codex app-server tokenUsage.modelContextWindow
|
|
178
|
+
* 透传)。仅 app-server 提供;缺省时卡片只显示绝对量、不显示百分比。 */
|
|
179
|
+
context_limit?: number;
|
|
78
180
|
};
|
|
79
181
|
total_cost_usd?: number;
|
|
80
182
|
errorMessage?: string;
|
|
@@ -99,7 +201,50 @@ export interface FileChangeEvent {
|
|
|
99
201
|
operation: 'create' | 'edit' | 'delete' | 'read';
|
|
100
202
|
timestamp?: string;
|
|
101
203
|
}
|
|
102
|
-
export
|
|
204
|
+
export interface TurnStartedEvent {
|
|
205
|
+
type: 'turn_started';
|
|
206
|
+
threadId: string;
|
|
207
|
+
turnId: string;
|
|
208
|
+
operationKind: 'turn' | 'compaction';
|
|
209
|
+
timestamp?: string;
|
|
210
|
+
}
|
|
211
|
+
export interface TurnDiffEvent {
|
|
212
|
+
type: 'turn_diff';
|
|
213
|
+
/**
|
|
214
|
+
* Thread item id this snapshot belongs to (app-server item-scoped stream).
|
|
215
|
+
* Each content item (reasoning / agentMessage / commandExecution / plan /
|
|
216
|
+
* fileChange) is tracked independently, so interleaved items keep their
|
|
217
|
+
* real chronology and update their own block instead of a shared one.
|
|
218
|
+
*/
|
|
219
|
+
itemId: string;
|
|
220
|
+
/** Full accumulated assistant text snapshot for this item (replaces previous). */
|
|
221
|
+
text?: string;
|
|
222
|
+
/** Full accumulated reasoning snapshot for this item (replaces previous). */
|
|
223
|
+
reasoning?: string;
|
|
224
|
+
/** Full accumulated tool output snapshot for this item (replaces previous). */
|
|
225
|
+
toolOutput?: string;
|
|
226
|
+
/** Full accumulated plan text snapshot for this item (replaces previous). */
|
|
227
|
+
plan?: string;
|
|
228
|
+
/** Current set of file changes for this item (replaces previous). */
|
|
229
|
+
fileChanges?: Array<{
|
|
230
|
+
path: string;
|
|
231
|
+
kind: 'add' | 'update' | 'delete';
|
|
232
|
+
diff?: string;
|
|
233
|
+
}>;
|
|
234
|
+
/**
|
|
235
|
+
* Authoritative completion snapshot (item/completed or turn/completed).
|
|
236
|
+
* The reducer finalizes the block in place: thinking/plan active=false,
|
|
237
|
+
* tool status ok, completedAt stamped. Never reorders blocks.
|
|
238
|
+
*/
|
|
239
|
+
complete?: boolean;
|
|
240
|
+
/** Authoritative tool status at completion (commandExecution item). */
|
|
241
|
+
toolStatus?: 'ok' | 'error';
|
|
242
|
+
threadId: string;
|
|
243
|
+
turnId: string;
|
|
244
|
+
timestamp?: string;
|
|
245
|
+
}
|
|
246
|
+
export type RunnerLifetime = 'turn' | 'workspace';
|
|
247
|
+
export type AgentEvent = SystemInitEvent | SystemCompactEvent | ApprovalRequestedEvent | ApprovalResolvedEvent | ApprovalViewUpdatedEvent | ApprovalExpiredEvent | AssistantEvent | UserEvent | ResultEvent | PlanEvent | FileChangeEvent | TurnStartedEvent | TurnDiffEvent;
|
|
103
248
|
export interface SpawnOptions {
|
|
104
249
|
cwd: string;
|
|
105
250
|
sessionId?: string;
|
|
@@ -117,6 +262,8 @@ export interface SpawnOptions {
|
|
|
117
262
|
*/
|
|
118
263
|
export interface Runner {
|
|
119
264
|
readonly isRunning: boolean;
|
|
265
|
+
readonly lifetime?: RunnerLifetime;
|
|
266
|
+
dispose?(): Promise<void>;
|
|
120
267
|
run(message: string, opts: SpawnOptions): AsyncGenerator<AgentEvent>;
|
|
121
268
|
/**
|
|
122
269
|
* Stop the running process. SIGTERM → grace → SIGKILL on the per-workspace
|
|
@@ -158,6 +305,8 @@ export interface AgentSessionUsage {
|
|
|
158
305
|
contextLimit?: number;
|
|
159
306
|
/** Claude auto-compact 次数(数 compact_boundary 事件);codex/opencode 无此概念,留 undefined。 */
|
|
160
307
|
compactCount?: number;
|
|
308
|
+
/** 压缩前上下文水位(codex compact 后从会话 jsonl 读取,仅会话以压缩收尾时有值)。 */
|
|
309
|
+
compactPreContextLength?: number;
|
|
161
310
|
/** 从缓存读取的 token 数(节省的费用)。 */
|
|
162
311
|
cacheReadTokens?: number;
|
|
163
312
|
/** 新建缓存的 token 数。 */
|
|
@@ -236,6 +385,8 @@ export interface AgentRunner extends Runner {
|
|
|
236
385
|
readonly sessionReader: AgentSessionReader;
|
|
237
386
|
/** Return current status info for /status display. */
|
|
238
387
|
getStatusInfo(): AgentStatusInfo;
|
|
388
|
+
/** Whether this runner provides live usage data (vs. file-based). */
|
|
389
|
+
getUsageAuthority?(): 'live' | 'jsonl';
|
|
239
390
|
}
|
|
240
391
|
/** Agent self-describing status info for /status display. */
|
|
241
392
|
export interface AgentStatusInfo {
|
|
@@ -2,7 +2,6 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { scanJsonlLines } from '../common/jsonl.js';
|
|
4
4
|
import { extractContentBlocks } from '../common/content-blocks.js';
|
|
5
|
-
import { truncate } from '../../card/card-shared.js';
|
|
6
5
|
import { getLogger } from '../../logger/index.js';
|
|
7
6
|
// ─── Claude content block mapping (shared with sessions.ts) ─
|
|
8
7
|
/** Claude-specific field-name mapping for content block extraction. */
|
|
@@ -224,7 +223,7 @@ export class SessionIndex {
|
|
|
224
223
|
path: p,
|
|
225
224
|
fingerprint: currentFp,
|
|
226
225
|
mtimeMs: Number(st.mtimeMs),
|
|
227
|
-
summary:
|
|
226
|
+
summary: parsed.summary.replace(/\s+/g, ' ').trim(),
|
|
228
227
|
cwdSet: parsed.cwdSet,
|
|
229
228
|
};
|
|
230
229
|
this.updateEntry(p, updated);
|
|
@@ -302,7 +301,7 @@ export class SessionIndex {
|
|
|
302
301
|
path: fullPath,
|
|
303
302
|
fingerprint: fpAfter,
|
|
304
303
|
mtimeMs: Number(fileStat.mtimeMs),
|
|
305
|
-
summary:
|
|
304
|
+
summary: parsed.summary.replace(/\s+/g, ' ').trim(),
|
|
306
305
|
cwdSet: parsed.cwdSet,
|
|
307
306
|
};
|
|
308
307
|
this.updateEntry(fullPath, newEntry);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { paginate } from '../common/pagination.js';
|
|
1
2
|
import { listClaudeSessions, getNewestSession, readSessionContent, isClaudeSessionActive, } from '../../session/claude/sessions.js';
|
|
2
3
|
/**
|
|
3
4
|
* Adapter that exposes Claude Code's session-reading functions through the
|
|
@@ -22,12 +23,8 @@ export class ClaudeSessionReader {
|
|
|
22
23
|
// 先拿全集(不传 limit → listClaudeSessions 不切片),total 用全集长度,
|
|
23
24
|
// 再由 reader 按 [offset, offset+limit) 切片。
|
|
24
25
|
const all = listClaudeSessions(cwd, this.readerOpts());
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
sessions: limit === undefined ? all.slice(offset) : all.slice(offset, offset + limit),
|
|
29
|
-
total: all.length,
|
|
30
|
-
};
|
|
26
|
+
const { items, total } = paginate(all, opts ?? {});
|
|
27
|
+
return { sessions: items, total };
|
|
31
28
|
}
|
|
32
29
|
getNewestSession(cwd) {
|
|
33
30
|
const session = getNewestSession(cwd, this.readerOpts());
|
|
@@ -3,9 +3,9 @@ import path from 'node:path';
|
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import { findJsonlLine, readLastJsonlLine, scanJsonlLines, readJsonlLinesFromOffset, } from '../common/jsonl.js';
|
|
5
5
|
import { STALE_MS } from '../common/constants.js';
|
|
6
|
+
import { capEvents } from '../common/pagination.js';
|
|
6
7
|
import { extractContentBlocks } from '../common/content-blocks.js';
|
|
7
8
|
import { UsageAccumulator } from '../common/usage-accumulator.js';
|
|
8
|
-
import { truncate } from '../../card/card-shared.js';
|
|
9
9
|
import { SessionIndex, extractText, isTaskNotificationText, CLAUDE_MAPPING, } from './session-index.js';
|
|
10
10
|
/**
|
|
11
11
|
* Directory Claude Code uses to store session transcripts for a given cwd.
|
|
@@ -262,7 +262,7 @@ function scalarScan(filePath) {
|
|
|
262
262
|
lastPostTokens = cm.postTokens;
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
|
-
// --- last user message offset
|
|
265
|
+
// --- last user message offset ---
|
|
266
266
|
// Record the byte offset where the tail should start: the beginning of
|
|
267
267
|
// the NEXT line after this user message. We compute it as this line's
|
|
268
268
|
// start offset + its byte length + 1 (the trailing '\n').
|
|
@@ -382,12 +382,7 @@ function extractEventsFromTail(tailLines, maxEvents) {
|
|
|
382
382
|
events.push({ type: role, content: `(${role} event)`, timestamp });
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
|
-
|
|
386
|
-
if (maxEvents <= 0)
|
|
387
|
-
return [];
|
|
388
|
-
return events.slice(-maxEvents);
|
|
389
|
-
}
|
|
390
|
-
return events;
|
|
385
|
+
return capEvents(events, maxEvents);
|
|
391
386
|
}
|
|
392
387
|
export function readSessionContent(sessionId, cwd, opts = {}) {
|
|
393
388
|
const { maxEvents } = opts;
|
|
@@ -447,11 +442,9 @@ export function readSessionContent(sessionId, cwd, opts = {}) {
|
|
|
447
442
|
// show.
|
|
448
443
|
const tailLines = readJsonlLinesFromOffset(filePath, scan.tailOffset >= 0 ? scan.tailOffset : 0);
|
|
449
444
|
const events = extractEventsFromTail(tailLines, maxEvents);
|
|
450
|
-
// Use aiTitle if available, otherwise fallback to last user message
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
? truncate(scan.lastUserMessage, 200, { normalizeWhitespace: true })
|
|
454
|
-
: undefined);
|
|
445
|
+
// Use aiTitle if available, otherwise fallback to last user message.
|
|
446
|
+
// Truncation is deferred to the consumer (router card building).
|
|
447
|
+
const displayTitle = scan.aiTitle ?? scan.lastUserMessage ?? undefined;
|
|
455
448
|
return {
|
|
456
449
|
events,
|
|
457
450
|
usage,
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
* ```
|
|
12
12
|
*
|
|
13
13
|
* Note: This handles the **rollout file format** (historical logging), NOT the
|
|
14
|
-
* `codex exec --json` stdout format
|
|
15
|
-
* (see design doc appendix B vs C).
|
|
14
|
+
* `codex exec --json` stdout format(已随 exec 模式移除)。
|
|
16
15
|
*/
|
|
17
16
|
import type { AgentSessionContentEvent, SessionContent, AgentSessionUsage } from '../../runner/index.js';
|
|
18
17
|
interface CodexRolloutEntry {
|
|
@@ -83,6 +82,7 @@ export declare function readCodexSessionContent(sessionId: string, opts?: {
|
|
|
83
82
|
export declare function isCodexSessionActive(sessionId: string, opts?: {
|
|
84
83
|
codexHome?: string;
|
|
85
84
|
activeThresholdMs?: number;
|
|
85
|
+
cwd?: string;
|
|
86
86
|
}): boolean;
|
|
87
87
|
/** Clear the session index cache. Exposed for tests. */
|
|
88
88
|
export declare function clearSessionIndexCache(): void;
|
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
* ```
|
|
12
12
|
*
|
|
13
13
|
* Note: This handles the **rollout file format** (historical logging), NOT the
|
|
14
|
-
* `codex exec --json` stdout format
|
|
15
|
-
* (see design doc appendix B vs C).
|
|
14
|
+
* `codex exec --json` stdout format(已随 exec 模式移除)。
|
|
16
15
|
*/
|
|
17
16
|
import fs from 'node:fs';
|
|
18
17
|
import path from 'node:path';
|
|
19
18
|
import { readJsonlLines, findJsonlLine } from '../common/jsonl.js';
|
|
19
|
+
import { STALE_MS } from '../common/constants.js';
|
|
20
|
+
import { paginate, capEvents } from '../common/pagination.js';
|
|
20
21
|
import { getLogger } from '../../logger/index.js';
|
|
21
22
|
import { isRecord, stringValue } from '../../common/guards.js';
|
|
22
23
|
import { resolveCodexHome } from '../../config/codex-config.js';
|
|
@@ -58,6 +59,18 @@ export function readCodexRollout(filePath) {
|
|
|
58
59
|
// Run card's "累计" display. Codex emits this alongside last_token_usage.
|
|
59
60
|
let lastTotalUsage;
|
|
60
61
|
let previousTotals;
|
|
62
|
+
// Compaction 统计:codex 的 compact turn 在会话文件里写顶层 `compacted`
|
|
63
|
+
// 事件(含摘要),压缩前后的上下文水位由相邻 token_count 表达。压缩收尾的
|
|
64
|
+
// token_count 增量是 input/cached/output 全 0、只有 total_tokens 有值
|
|
65
|
+
// (窗口被摘要+replacement history 占据),现有 zero-filter 会跳过它,
|
|
66
|
+
// 因此这里必须单独捕获,不能复用 lastRawUsage。
|
|
67
|
+
// 单位口径(review P3-9):前后两侧统一用 total_tokens —— 压缩前取最近一次
|
|
68
|
+
// 非零 token_count 的 total_tokens(input+output,即该 turn 在窗口内的全部
|
|
69
|
+
// token),压缩后取收尾事件的 total_tokens(压缩后窗口)。不得一边 input
|
|
70
|
+
// 一边 total,否则「压缩前 X → 压缩后 Y」两边单位不一致。
|
|
71
|
+
let compactCount = 0;
|
|
72
|
+
let compactPreContextLength;
|
|
73
|
+
let compactPostContextLength;
|
|
61
74
|
for (const line of lines) {
|
|
62
75
|
const trimmed = line.trim();
|
|
63
76
|
if (!trimmed)
|
|
@@ -101,6 +114,27 @@ export function readCodexRollout(filePath) {
|
|
|
101
114
|
const ctxWindow = info?.model_context_window;
|
|
102
115
|
lastContextLimit = typeof ctxWindow === 'number' ? ctxWindow : undefined;
|
|
103
116
|
}
|
|
117
|
+
// 压缩后的水位:压缩收尾 token_count 全 0(raw 不满足上面 zero-filter),
|
|
118
|
+
// 但 total_tokens 表达真实窗口;之后若出现普通 turn(input>0),
|
|
119
|
+
// 水位回归该 turn,post-compact 值失效。
|
|
120
|
+
if (compactCount > 0 && raw) {
|
|
121
|
+
if (raw.total_tokens &&
|
|
122
|
+
!raw.input_tokens &&
|
|
123
|
+
!raw.cached_input_tokens &&
|
|
124
|
+
!raw.output_tokens) {
|
|
125
|
+
compactPostContextLength = raw.total_tokens;
|
|
126
|
+
}
|
|
127
|
+
else if (raw.input_tokens > 0) {
|
|
128
|
+
compactPostContextLength = undefined;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else if (parsed.type === 'compacted') {
|
|
134
|
+
// 顶层 compacted 事件:压缩次数 +1,压缩前水位取最近一次非零 token_count。
|
|
135
|
+
compactCount++;
|
|
136
|
+
if (lastRawUsage?.total_tokens !== undefined) {
|
|
137
|
+
compactPreContextLength = lastRawUsage.total_tokens;
|
|
104
138
|
}
|
|
105
139
|
}
|
|
106
140
|
else if (parsed.type === 'response_item' && parsed.payload) {
|
|
@@ -170,6 +204,16 @@ export function readCodexRollout(filePath) {
|
|
|
170
204
|
usage.cumulativeCacheReadTokens = cumCached;
|
|
171
205
|
usage.cumulativeCacheCreationTokens = 0; // Codex 不报告 cache creation
|
|
172
206
|
}
|
|
207
|
+
// 压缩统计:会话内出现过 compacted 事件就计数(供 /resume 与 Compact 卡
|
|
208
|
+
// 展示);仅当会话以压缩收尾时(post-compact 水位存在),contextLength
|
|
209
|
+
// 覆盖为压缩后水位并暴露压缩前水位——后续还有普通 turn 时水位回归该 turn。
|
|
210
|
+
if (compactCount > 0) {
|
|
211
|
+
usage.compactCount = compactCount;
|
|
212
|
+
if (compactPostContextLength !== undefined) {
|
|
213
|
+
usage.contextLength = compactPostContextLength;
|
|
214
|
+
usage.compactPreContextLength = compactPreContextLength;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
173
217
|
}
|
|
174
218
|
return {
|
|
175
219
|
threadId: sessionId,
|
|
@@ -200,8 +244,6 @@ export function readCodexRollout(filePath) {
|
|
|
200
244
|
*/
|
|
201
245
|
export function listCodexRollouts(opts = {}) {
|
|
202
246
|
const codexHome = resolveCodexHome(opts.codexHome);
|
|
203
|
-
const limit = opts.limit ?? 20;
|
|
204
|
-
const offset = Math.max(0, opts.offset ?? 0);
|
|
205
247
|
const filterCwd = opts.cwd;
|
|
206
248
|
// Full index: every rollout file's session_meta + mtime, no early break.
|
|
207
249
|
const index = getSessionIndex(codexHome);
|
|
@@ -220,8 +262,7 @@ export function listCodexRollouts(opts = {}) {
|
|
|
220
262
|
// Same-mtime ties use filePath as a deterministic secondary key so index
|
|
221
263
|
// rebuilds / walk order changes never reorder the page.
|
|
222
264
|
matched.sort((a, b) => b.mtimeMs - a.mtimeMs || a.filePath.localeCompare(b.filePath));
|
|
223
|
-
const total = matched.
|
|
224
|
-
const page = matched.slice(offset, offset + limit);
|
|
265
|
+
const { items: page, total } = paginate(matched, { limit: opts.limit, offset: opts.offset });
|
|
225
266
|
// Full-parse only the page being returned (summary/usage).
|
|
226
267
|
const entries = [];
|
|
227
268
|
for (const item of page) {
|
|
@@ -274,22 +315,14 @@ export function readCodexSessionContent(sessionId, opts = {}) {
|
|
|
274
315
|
}
|
|
275
316
|
// Apply maxEvents cap: keep the LAST N events (most recent).
|
|
276
317
|
// See function docstring for rationale.
|
|
277
|
-
|
|
278
|
-
// full-array trap (no caller passes 0 today, but the contract must hold).
|
|
279
|
-
const events = opts.maxEvents !== undefined && opts.maxEvents > 0 && rollout.events.length > opts.maxEvents
|
|
280
|
-
? rollout.events.slice(-opts.maxEvents)
|
|
281
|
-
: opts.maxEvents !== undefined && opts.maxEvents <= 0
|
|
282
|
-
? []
|
|
283
|
-
: rollout.events;
|
|
318
|
+
const events = capEvents(rollout.events, opts.maxEvents);
|
|
284
319
|
return {
|
|
285
320
|
events,
|
|
286
321
|
// displayTitle = LAST real user message (matches the
|
|
287
322
|
// "最近输入" label). recap is undefined: codex has no
|
|
288
323
|
// compact-summary concept, so never fake one from a user
|
|
289
324
|
// message (was: firstUserMessage = injected project rules).
|
|
290
|
-
displayTitle: rollout.lastRealUserMessage
|
|
291
|
-
? rollout.lastRealUserMessage.slice(0, 50)
|
|
292
|
-
: undefined,
|
|
325
|
+
displayTitle: rollout.lastRealUserMessage || undefined,
|
|
293
326
|
recap: undefined,
|
|
294
327
|
usage: rollout.usage,
|
|
295
328
|
};
|
|
@@ -304,7 +337,9 @@ export function readCodexSessionContent(sessionId, opts = {}) {
|
|
|
304
337
|
*/
|
|
305
338
|
export function isCodexSessionActive(sessionId, opts = {}) {
|
|
306
339
|
const codexHome = resolveCodexHome(opts.codexHome);
|
|
307
|
-
|
|
340
|
+
// Unify with the other readers' 1-hour stale window (claude/pi/opencode/kimi
|
|
341
|
+
// all use STALE_MS). Previously codex used a divergent 10-minute default.
|
|
342
|
+
const threshold = opts.activeThresholdMs ?? STALE_MS;
|
|
308
343
|
// P2-4: Use session index for direct file lookup + mtime check
|
|
309
344
|
let index = getSessionIndex(codexHome);
|
|
310
345
|
let entry = index.get(sessionId);
|
|
@@ -323,6 +358,11 @@ export function isCodexSessionActive(sessionId, opts = {}) {
|
|
|
323
358
|
if (entry.isSubagent) {
|
|
324
359
|
return false;
|
|
325
360
|
}
|
|
361
|
+
// Cwd guard: when a cwd is provided, the session's working directory must
|
|
362
|
+
// match (align with claude/pi/opencode which validate cwd).
|
|
363
|
+
if (opts.cwd && entry.cwd !== opts.cwd) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
326
366
|
// Re-stat to get fresh mtime (index may be up to INDEX_TTL_MS stale)
|
|
327
367
|
try {
|
|
328
368
|
const stat = fs.statSync(entry.filePath);
|
|
@@ -16,6 +16,6 @@ export declare class CodexSessionReader implements AgentSessionReader {
|
|
|
16
16
|
readSessionContent(sessionId: string, cwd: string, opts?: {
|
|
17
17
|
maxEvents?: number;
|
|
18
18
|
}): SessionContent;
|
|
19
|
-
isSessionActive(sessionId: string,
|
|
19
|
+
isSessionActive(sessionId: string, cwd: string): boolean;
|
|
20
20
|
}
|
|
21
21
|
export {};
|
|
@@ -34,8 +34,8 @@ export class CodexSessionReader {
|
|
|
34
34
|
cwd,
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
-
isSessionActive(sessionId,
|
|
38
|
-
return isCodexSessionActive(sessionId, { codexHome: this.codexHome });
|
|
37
|
+
isSessionActive(sessionId, cwd) {
|
|
38
|
+
return isCodexSessionActive(sessionId, { codexHome: this.codexHome, cwd });
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
//# sourceMappingURL=sessions.js.map
|