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.
Files changed (28) hide show
  1. package/dist/cli/src/index.js +0 -0
  2. package/dist/cli/src/runtime/acp/agent-workspace.d.ts +4 -0
  3. package/dist/cli/src/runtime/acp/agent-workspace.js +65 -7
  4. package/dist/cli/src/runtime/acp/agent-workspace.js.map +1 -1
  5. package/dist/cli/src/runtime/acp/claude-sdk-client.d.ts +1 -0
  6. package/dist/cli/src/runtime/acp/claude-sdk-client.js +45 -7
  7. package/dist/cli/src/runtime/acp/claude-sdk-client.js.map +1 -1
  8. package/dist/cli/src/runtime/acp/claude-stream-json-client.js +22 -2
  9. package/dist/cli/src/runtime/acp/claude-stream-json-client.js.map +1 -1
  10. package/dist/cli/src/runtime/acp/codex-rpc-bridge.d.ts +16 -0
  11. package/dist/cli/src/runtime/acp/codex-rpc-bridge.js +53 -0
  12. package/dist/cli/src/runtime/acp/codex-rpc-bridge.js.map +1 -0
  13. package/dist/cli/src/runtime/acp/json-rpc.d.ts +25 -1
  14. package/dist/cli/src/runtime/acp/json-rpc.js +9 -1
  15. package/dist/cli/src/runtime/acp/json-rpc.js.map +1 -1
  16. package/dist/cli/src/runtime/bridge-session.js +25 -0
  17. package/dist/cli/src/runtime/bridge-session.js.map +1 -1
  18. package/dist/cli/tsconfig.tsbuildinfo +1 -1
  19. package/dist/shared-protocol/src/index.d.ts +939 -459
  20. package/dist/shared-protocol/src/index.js +56 -0
  21. package/dist/shared-protocol/src/index.js.map +1 -1
  22. package/package.json +13 -13
  23. package/src/runtime/acp/agent-workspace.ts +66 -7
  24. package/src/runtime/acp/claude-sdk-client.ts +50 -7
  25. package/src/runtime/acp/claude-stream-json-client.ts +25 -2
  26. package/src/runtime/acp/codex-rpc-bridge.ts +70 -0
  27. package/src/runtime/acp/json-rpc.ts +13 -4
  28. package/src/runtime/bridge-session.ts +27 -0
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 { listCodexStoredSessions, loadCodexStoredTimeline } from "./codex-sessions.js";
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.map((p) => this.ensureProviderClient(p));
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);