linkshell-cli 0.3.14 → 0.3.16
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/dist/cli/src/index.js +0 -0
- package/dist/cli/src/runtime/acp/agent-workspace.d.ts +4 -0
- package/dist/cli/src/runtime/acp/agent-workspace.js +65 -7
- package/dist/cli/src/runtime/acp/agent-workspace.js.map +1 -1
- package/dist/cli/src/runtime/acp/claude-sdk-client.d.ts +1 -0
- package/dist/cli/src/runtime/acp/claude-sdk-client.js +45 -7
- package/dist/cli/src/runtime/acp/claude-sdk-client.js.map +1 -1
- package/dist/cli/src/runtime/acp/claude-stream-json-client.js +22 -2
- package/dist/cli/src/runtime/acp/claude-stream-json-client.js.map +1 -1
- package/dist/cli/src/runtime/acp/codex-rpc-bridge.d.ts +16 -0
- package/dist/cli/src/runtime/acp/codex-rpc-bridge.js +53 -0
- package/dist/cli/src/runtime/acp/codex-rpc-bridge.js.map +1 -0
- package/dist/cli/src/runtime/acp/json-rpc.d.ts +25 -1
- package/dist/cli/src/runtime/acp/json-rpc.js +9 -1
- package/dist/cli/src/runtime/acp/json-rpc.js.map +1 -1
- package/dist/cli/src/runtime/bridge-session.js +25 -0
- package/dist/cli/src/runtime/bridge-session.js.map +1 -1
- package/dist/cli/tsconfig.tsbuildinfo +1 -1
- package/dist/shared-protocol/src/index.d.ts +939 -459
- package/dist/shared-protocol/src/index.js +56 -0
- package/dist/shared-protocol/src/index.js.map +1 -1
- package/package.json +13 -13
- package/src/runtime/acp/agent-workspace.ts +66 -7
- package/src/runtime/acp/claude-sdk-client.ts +50 -7
- package/src/runtime/acp/claude-stream-json-client.ts +25 -2
- package/src/runtime/acp/codex-rpc-bridge.ts +70 -0
- package/src/runtime/acp/json-rpc.ts +13 -4
- package/src/runtime/bridge-session.ts +27 -0
package/dist/cli/src/index.js
CHANGED
|
File without changes
|
|
@@ -3,8 +3,11 @@ import type { AgentProvider } from "./provider-resolver.js";
|
|
|
3
3
|
export declare class AgentWorkspaceProxy {
|
|
4
4
|
private readonly input;
|
|
5
5
|
private clients;
|
|
6
|
+
private codexRpcBridge;
|
|
6
7
|
private agentProtocols;
|
|
7
8
|
private providerCapabilities;
|
|
9
|
+
private providerCapabilityErrors;
|
|
10
|
+
private capabilitiesRevision;
|
|
8
11
|
private initialized;
|
|
9
12
|
private status;
|
|
10
13
|
private error;
|
|
@@ -35,6 +38,7 @@ export declare class AgentWorkspaceProxy {
|
|
|
35
38
|
handleEnvelope(envelope: Envelope): Promise<void>;
|
|
36
39
|
stop(): void;
|
|
37
40
|
private clientForProvider;
|
|
41
|
+
private codexRpc;
|
|
38
42
|
private protocolForProvider;
|
|
39
43
|
private initialize;
|
|
40
44
|
private ensureProviderClient;
|
|
@@ -6,8 +6,9 @@ import { createEnvelope, parseTypedPayload, } from "@linkshell/protocol";
|
|
|
6
6
|
import { AcpClient } from "./acp-client.js";
|
|
7
7
|
import { ClaudeSdkClient } from "./claude-sdk-client.js";
|
|
8
8
|
import { ClaudeStreamJsonClient } from "./claude-stream-json-client.js";
|
|
9
|
+
import { CodexRpcBridge } from "./codex-rpc-bridge.js";
|
|
9
10
|
import { listClaudeStoredSessions, loadClaudeStoredTimeline } from "./claude-sessions.js";
|
|
10
|
-
import {
|
|
11
|
+
import { loadCodexStoredTimeline } from "./codex-sessions.js";
|
|
11
12
|
import { resolveAgentCommand } from "./provider-resolver.js";
|
|
12
13
|
const PERMISSION_TIMEOUT_MS = 5 * 60_000;
|
|
13
14
|
const MAX_TIMELINE_ITEMS = 200;
|
|
@@ -1176,8 +1177,11 @@ function normalizeAgentStatus(value) {
|
|
|
1176
1177
|
export class AgentWorkspaceProxy {
|
|
1177
1178
|
input;
|
|
1178
1179
|
clients = new Map();
|
|
1180
|
+
codexRpcBridge;
|
|
1179
1181
|
agentProtocols = new Map();
|
|
1180
1182
|
providerCapabilities = new Map();
|
|
1183
|
+
providerCapabilityErrors = new Map();
|
|
1184
|
+
capabilitiesRevision = 0;
|
|
1181
1185
|
initialized = false;
|
|
1182
1186
|
status = "unavailable";
|
|
1183
1187
|
error;
|
|
@@ -1202,6 +1206,32 @@ export class AgentWorkspaceProxy {
|
|
|
1202
1206
|
}
|
|
1203
1207
|
async handleEnvelope(envelope) {
|
|
1204
1208
|
switch (envelope.type) {
|
|
1209
|
+
case "agent.codex.rpc": {
|
|
1210
|
+
const payload = parseTypedPayload("agent.codex.rpc", envelope.payload);
|
|
1211
|
+
try {
|
|
1212
|
+
this.codexRpc().send(payload);
|
|
1213
|
+
}
|
|
1214
|
+
catch (error) {
|
|
1215
|
+
const idValue = payload && typeof payload === "object" && "id" in payload
|
|
1216
|
+
? payload.id
|
|
1217
|
+
: undefined;
|
|
1218
|
+
if (typeof idValue === "string" || typeof idValue === "number") {
|
|
1219
|
+
this.input.send(createEnvelope({
|
|
1220
|
+
type: "agent.codex.rpc",
|
|
1221
|
+
hostDeviceId: this.input.hostDeviceId,
|
|
1222
|
+
payload: {
|
|
1223
|
+
jsonrpc: "2.0",
|
|
1224
|
+
id: idValue,
|
|
1225
|
+
error: {
|
|
1226
|
+
code: -32000,
|
|
1227
|
+
message: error instanceof Error ? error.message : String(error),
|
|
1228
|
+
},
|
|
1229
|
+
},
|
|
1230
|
+
}));
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
break;
|
|
1234
|
+
}
|
|
1205
1235
|
case "agent.v2.capabilities.request":
|
|
1206
1236
|
await this.initialize();
|
|
1207
1237
|
this.sendCapabilities();
|
|
@@ -1274,6 +1304,8 @@ export class AgentWorkspaceProxy {
|
|
|
1274
1304
|
}
|
|
1275
1305
|
}
|
|
1276
1306
|
stop() {
|
|
1307
|
+
this.codexRpcBridge?.stop();
|
|
1308
|
+
this.codexRpcBridge = undefined;
|
|
1277
1309
|
for (const client of this.clients.values()) {
|
|
1278
1310
|
client.stop();
|
|
1279
1311
|
}
|
|
@@ -1282,6 +1314,16 @@ export class AgentWorkspaceProxy {
|
|
|
1282
1314
|
clientForProvider(provider) {
|
|
1283
1315
|
return this.clients.get(provider);
|
|
1284
1316
|
}
|
|
1317
|
+
codexRpc() {
|
|
1318
|
+
this.codexRpcBridge ??= new CodexRpcBridge({
|
|
1319
|
+
command: this.input.command,
|
|
1320
|
+
cwd: this.input.cwd,
|
|
1321
|
+
hostDeviceId: this.input.hostDeviceId,
|
|
1322
|
+
send: this.input.send,
|
|
1323
|
+
verbose: this.input.verbose,
|
|
1324
|
+
});
|
|
1325
|
+
return this.codexRpcBridge;
|
|
1326
|
+
}
|
|
1285
1327
|
protocolForProvider(provider) {
|
|
1286
1328
|
return this.agentProtocols.get(provider);
|
|
1287
1329
|
}
|
|
@@ -1290,7 +1332,9 @@ export class AgentWorkspaceProxy {
|
|
|
1290
1332
|
return;
|
|
1291
1333
|
this.initialized = true;
|
|
1292
1334
|
// Eagerly start all detected providers so capabilities report real status
|
|
1293
|
-
const startPromises = this.input.availableProviders
|
|
1335
|
+
const startPromises = this.input.availableProviders
|
|
1336
|
+
.filter((provider) => provider !== "codex")
|
|
1337
|
+
.map((p) => this.ensureProviderClient(p));
|
|
1294
1338
|
await Promise.allSettled(startPromises);
|
|
1295
1339
|
this.status = "idle";
|
|
1296
1340
|
this.error = undefined;
|
|
@@ -1396,10 +1440,13 @@ export class AgentWorkspaceProxy {
|
|
|
1396
1440
|
try {
|
|
1397
1441
|
const result = await listModels.call(client);
|
|
1398
1442
|
const runtimeCapabilities = parseModelListCapabilities(result);
|
|
1399
|
-
if (runtimeCapabilities)
|
|
1443
|
+
if (runtimeCapabilities) {
|
|
1400
1444
|
this.providerCapabilities.set(provider, runtimeCapabilities);
|
|
1445
|
+
this.providerCapabilityErrors.delete(provider);
|
|
1446
|
+
}
|
|
1401
1447
|
}
|
|
1402
1448
|
catch (error) {
|
|
1449
|
+
this.providerCapabilityErrors.set(provider, error instanceof Error ? error.message : String(error));
|
|
1403
1450
|
if (this.input.verbose) {
|
|
1404
1451
|
process.stderr.write(`[agent:v2] model/list failed for ${provider}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
1405
1452
|
}
|
|
@@ -1407,7 +1454,6 @@ export class AgentWorkspaceProxy {
|
|
|
1407
1454
|
}
|
|
1408
1455
|
async syncProviderSessions() {
|
|
1409
1456
|
await this.initialize();
|
|
1410
|
-
this.upsertProviderSessions("codex", listCodexStoredSessions(this.input.cwd));
|
|
1411
1457
|
this.upsertProviderSessions("claude", listClaudeStoredSessions(this.input.cwd));
|
|
1412
1458
|
for (const [provider, client] of this.clients) {
|
|
1413
1459
|
try {
|
|
@@ -1460,12 +1506,14 @@ export class AgentWorkspaceProxy {
|
|
|
1460
1506
|
sendCapabilities() {
|
|
1461
1507
|
const providers = this.input.availableProviders.map((provider) => {
|
|
1462
1508
|
const client = this.clients.get(provider);
|
|
1463
|
-
const protocol = this.agentProtocols.get(provider);
|
|
1509
|
+
const protocol = provider === "codex" ? "codex-app-server" : this.agentProtocols.get(provider);
|
|
1464
1510
|
const runtimeCapabilities = this.providerCapabilities.get(provider);
|
|
1465
|
-
const enabled = Boolean(client);
|
|
1511
|
+
const enabled = provider === "codex" ? true : Boolean(client);
|
|
1512
|
+
const hasRuntimeModels = Boolean(runtimeCapabilities?.models?.length);
|
|
1466
1513
|
const supportsImages = enabled && protocolSupportsImages(protocol);
|
|
1514
|
+
const isClaudeSdk = protocol === "claude-agent-sdk";
|
|
1467
1515
|
const isClaudeFallback = protocol === "claude-stream-json";
|
|
1468
|
-
const supportsPermission = enabled && !isClaudeFallback;
|
|
1516
|
+
const supportsPermission = enabled && (isClaudeSdk || !isClaudeFallback);
|
|
1469
1517
|
const supportsReasoningEffort = enabled;
|
|
1470
1518
|
const commands = mergeCommands(defaultProviderCommands(provider, this.input.cwd, enabled), runtimeCapabilities?.commands);
|
|
1471
1519
|
const currentMode = [...this.conversations.values()].find((conversation) => conversation.provider === provider)?.collaborationMode;
|
|
@@ -1474,12 +1522,15 @@ export class AgentWorkspaceProxy {
|
|
|
1474
1522
|
label: providerLabel(provider),
|
|
1475
1523
|
enabled,
|
|
1476
1524
|
reason: enabled ? undefined : `${providerLabel(provider)} 未安装或启动失败`,
|
|
1525
|
+
providerProtocol: protocol,
|
|
1477
1526
|
supportsImages,
|
|
1478
1527
|
supportsPermission,
|
|
1479
1528
|
supportsPlan: enabled,
|
|
1480
1529
|
supportsCancel: enabled,
|
|
1481
1530
|
models: runtimeCapabilities?.models ?? [{ id: "default", label: "默认模型" }],
|
|
1482
1531
|
defaultModel: runtimeCapabilities?.defaultModel,
|
|
1532
|
+
modelsSource: hasRuntimeModels ? "runtime" : enabled ? "fallback" : "unavailable",
|
|
1533
|
+
modelListError: this.providerCapabilityErrors.get(provider),
|
|
1483
1534
|
reasoningEfforts: supportsReasoningEffort
|
|
1484
1535
|
? runtimeCapabilities?.reasoningEfforts ?? (provider === "claude" ? [...CLAUDE_REASONING_EFFORTS] : [...ALL_REASONING_EFFORTS])
|
|
1485
1536
|
: [],
|
|
@@ -1493,6 +1544,7 @@ export class AgentWorkspaceProxy {
|
|
|
1493
1544
|
plan: enabled,
|
|
1494
1545
|
cancel: enabled,
|
|
1495
1546
|
reasoningEffort: supportsReasoningEffort,
|
|
1547
|
+
claudeSdk: isClaudeSdk,
|
|
1496
1548
|
streamJsonFallback: isClaudeFallback,
|
|
1497
1549
|
},
|
|
1498
1550
|
};
|
|
@@ -1508,6 +1560,7 @@ export class AgentWorkspaceProxy {
|
|
|
1508
1560
|
providers,
|
|
1509
1561
|
protocolVersion: 1,
|
|
1510
1562
|
workspaceProtocolVersion: 2,
|
|
1563
|
+
capabilitiesRevision: ++this.capabilitiesRevision,
|
|
1511
1564
|
error: anyEnabled ? undefined : "没有可用的 Agent provider。请安装 Claude Code 或 Codex CLI。",
|
|
1512
1565
|
supportsSessionList: anyEnabled,
|
|
1513
1566
|
supportsSessionLoad: anyEnabled,
|
|
@@ -2021,6 +2074,9 @@ export class AgentWorkspaceProxy {
|
|
|
2021
2074
|
this.conversationByAgentSessionId.set(agentSessionId, conversationId);
|
|
2022
2075
|
const conversation = this.conversations.get(conversationId);
|
|
2023
2076
|
if (conversation) {
|
|
2077
|
+
if (conversation.agentSessionId && conversation.agentSessionId !== agentSessionId) {
|
|
2078
|
+
this.conversationByAgentSessionId.delete(conversation.agentSessionId);
|
|
2079
|
+
}
|
|
2024
2080
|
conversation.agentSessionId = agentSessionId;
|
|
2025
2081
|
conversation.lastActivityAt = Date.now();
|
|
2026
2082
|
this.emitConversation(conversation);
|
|
@@ -2935,6 +2991,8 @@ export class AgentWorkspaceProxy {
|
|
|
2935
2991
|
...existing,
|
|
2936
2992
|
...toolCall,
|
|
2937
2993
|
id: targetToolId,
|
|
2994
|
+
input: toolCall.input ?? existing?.input,
|
|
2995
|
+
output: toolCall.output ?? existing?.output,
|
|
2938
2996
|
createdAt: existing?.createdAt ?? toolCall.createdAt ?? Date.now(),
|
|
2939
2997
|
};
|
|
2940
2998
|
this.toolConversationIds.set(toolCall.id, conversationId);
|