linkshell-cli 0.2.113 → 0.2.115

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.
@@ -10,6 +10,7 @@ export declare class AgentWorkspaceProxy {
10
10
  private error;
11
11
  private activeConversationId;
12
12
  private currentTurnIds;
13
+ private turnConversationIds;
13
14
  private conversations;
14
15
  private conversationByAgentSessionId;
15
16
  private timelines;
@@ -19,6 +20,7 @@ export declare class AgentWorkspaceProxy {
19
20
  private permissionSources;
20
21
  private pendingStructuredInputs;
21
22
  private structuredInputWaiters;
23
+ private itemConversationIds;
22
24
  private toolConversationIds;
23
25
  constructor(input: {
24
26
  sessionId: string;
@@ -81,6 +83,10 @@ export declare class AgentWorkspaceProxy {
81
83
  private updateConversationStatus;
82
84
  private sendSnapshot;
83
85
  private conversationIdFromParams;
86
+ private fallbackConversationId;
87
+ private rememberTurnConversationId;
88
+ private forgetCurrentTurn;
89
+ private rememberItemConversationId;
84
90
  private handleProviderExit;
85
91
  private cancelPendingPermissions;
86
92
  private extractSessionId;
@@ -512,6 +512,73 @@ function providerLabel(provider) {
512
512
  const ALL_REASONING_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh"];
513
513
  const ALL_PERMISSION_MODES = ["read_only", "workspace_write", "full_access"];
514
514
  const CODEX_COMMAND_NAMES = ["plan", "exit-plan", "compact", "clear", "status", "review", "subagents"];
515
+ const CLAUDE_REMOTE_HIDDEN_COMMANDS = new Set([
516
+ "add-dir",
517
+ "agents",
518
+ "allowed-tools",
519
+ "android",
520
+ "app",
521
+ "bashes",
522
+ "branch",
523
+ "bug",
524
+ "checkpoint",
525
+ "chrome",
526
+ "color",
527
+ "config",
528
+ "continue",
529
+ "copy",
530
+ "cost",
531
+ "desktop",
532
+ "diff",
533
+ "doctor",
534
+ "exit",
535
+ "export",
536
+ "extra-usage",
537
+ "feedback",
538
+ "focus",
539
+ "fork",
540
+ "hooks",
541
+ "ide",
542
+ "init",
543
+ "install-github-app",
544
+ "install-slack-app",
545
+ "ios",
546
+ "keybindings",
547
+ "login",
548
+ "logout",
549
+ "mcp",
550
+ "memory",
551
+ "migrate-installer",
552
+ "mobile",
553
+ "model",
554
+ "passes",
555
+ "permissions",
556
+ "plugin",
557
+ "powerup",
558
+ "pr-comments",
559
+ "privacy-settings",
560
+ "quit",
561
+ "rc",
562
+ "release-notes",
563
+ "remote-control",
564
+ "remote-env",
565
+ "resume",
566
+ "rewind",
567
+ "settings",
568
+ "statusline",
569
+ "stickers",
570
+ "tasks",
571
+ "teleport",
572
+ "terminal-setup",
573
+ "theme",
574
+ "tp",
575
+ "tui",
576
+ "undo",
577
+ "upgrade",
578
+ "vim",
579
+ "voice",
580
+ "web-setup",
581
+ ]);
515
582
  const CLAUDE_BUILT_IN_COMMANDS = [
516
583
  { name: "add-dir", description: "Add a working directory for file access", argsMode: "required" },
517
584
  { name: "agents", description: "Manage agent configurations", argsMode: "none" },
@@ -615,6 +682,9 @@ const CLAUDE_BUILT_IN_COMMANDS = [
615
682
  { name: "voice", description: "Toggle voice dictation" },
616
683
  { name: "web-setup", description: "Connect your GitHub account to Claude Code on the web", argsMode: "none" },
617
684
  ];
685
+ function isClaudeRemoteFriendlyCommand(name) {
686
+ return !CLAUDE_REMOTE_HIDDEN_COMMANDS.has(name.replace(/^\/+/, ""));
687
+ }
618
688
  function commandId(provider, name, source = "built_in") {
619
689
  return `${provider}:${source}:${name.replace(/^\/+/, "")}`;
620
690
  }
@@ -725,7 +795,9 @@ function defaultProviderCommands(provider, cwd, enabled) {
725
795
  }));
726
796
  }
727
797
  if (provider === "claude") {
728
- const builtIns = CLAUDE_BUILT_IN_COMMANDS.map((entry) => makeCommand({
798
+ const builtIns = CLAUDE_BUILT_IN_COMMANDS
799
+ .filter((entry) => isClaudeRemoteFriendlyCommand(entry.name))
800
+ .map((entry) => makeCommand({
729
801
  provider,
730
802
  name: entry.name,
731
803
  description: entry.description,
@@ -758,7 +830,12 @@ function mergeCommands(...groups) {
758
830
  for (const group of groups) {
759
831
  for (const command of group ?? []) {
760
832
  const key = `${command.provider ?? ""}:${command.name}`;
761
- map.set(key, { ...map.get(key), ...command });
833
+ const existing = map.get(key);
834
+ map.set(key, {
835
+ ...existing,
836
+ ...command,
837
+ disabledReason: command.disabledReason ?? existing?.disabledReason,
838
+ });
762
839
  }
763
840
  }
764
841
  return [...map.values()].sort((a, b) => a.name.localeCompare(b.name));
@@ -774,6 +851,8 @@ function runtimeCommands(provider, value) {
774
851
  return commandsValue
775
852
  .map((entry) => {
776
853
  if (typeof entry === "string") {
854
+ if (provider === "claude" && !isClaudeRemoteFriendlyCommand(entry))
855
+ return undefined;
777
856
  return makeCommand({
778
857
  provider,
779
858
  name: entry,
@@ -787,6 +866,8 @@ function runtimeCommands(provider, value) {
787
866
  const name = firstString(record, ["name", "command", "id"]);
788
867
  if (!name)
789
868
  return undefined;
869
+ if (provider === "claude" && !isClaudeRemoteFriendlyCommand(name))
870
+ return undefined;
790
871
  return makeCommand({
791
872
  provider,
792
873
  name,
@@ -886,6 +967,7 @@ export class AgentWorkspaceProxy {
886
967
  error;
887
968
  activeConversationId;
888
969
  currentTurnIds = new Map();
970
+ turnConversationIds = new Map();
889
971
  conversations = new Map();
890
972
  conversationByAgentSessionId = new Map();
891
973
  timelines = new Map();
@@ -895,6 +977,7 @@ export class AgentWorkspaceProxy {
895
977
  permissionSources = new Map();
896
978
  pendingStructuredInputs = new Map();
897
979
  structuredInputWaiters = new Map();
980
+ itemConversationIds = new Map();
898
981
  toolConversationIds = new Map();
899
982
  constructor(input) {
900
983
  this.input = input;
@@ -945,7 +1028,7 @@ export class AgentWorkspaceProxy {
945
1028
  sessionId: conversation?.agentSessionId,
946
1029
  turnId: this.currentTurnIds.get(payload.conversationId),
947
1030
  });
948
- this.currentTurnIds.delete(payload.conversationId);
1031
+ this.forgetCurrentTurn(payload.conversationId);
949
1032
  this.updateConversationStatus(payload.conversationId, "idle");
950
1033
  this.emitStatus(payload.conversationId, "idle", "已停止");
951
1034
  break;
@@ -1382,7 +1465,7 @@ export class AgentWorkspaceProxy {
1382
1465
  }
1383
1466
  const turnId = this.extractTurnId(result);
1384
1467
  if (turnId)
1385
- this.currentTurnIds.set(conversation.id, turnId);
1468
+ this.rememberTurnConversationId(conversation.id, turnId);
1386
1469
  if (conversation.status === "running" && protocol !== "codex-app-server") {
1387
1470
  this.updateConversationStatus(conversation.id, "idle");
1388
1471
  }
@@ -1589,7 +1672,7 @@ export class AgentWorkspaceProxy {
1589
1672
  process.stderr.write(`[agent:v2] ${method} ${stringify(params).slice(0, 500)}\n`);
1590
1673
  }
1591
1674
  if (method === "initialized") {
1592
- const conversationId = this.conversationIdFromParams(params) ?? this.activeConversationId;
1675
+ const conversationId = this.conversationIdFromParams(params) ?? this.fallbackConversationId();
1593
1676
  const provider = conversationId ? this.conversations.get(conversationId)?.provider : this.input.availableProviders[0];
1594
1677
  if (provider) {
1595
1678
  const commands = runtimeCommands(provider, params);
@@ -1612,7 +1695,7 @@ export class AgentWorkspaceProxy {
1612
1695
  method === "mcpServer/oauthLogin/completed") {
1613
1696
  return;
1614
1697
  }
1615
- const conversationId = this.conversationIdFromParams(params) ?? this.activeConversationId;
1698
+ const conversationId = this.conversationIdFromParams(params) ?? this.fallbackConversationId();
1616
1699
  if (method === "item/tool/requestUserInput" || method === "tool/requestUserInput") {
1617
1700
  this.handleStructuredInput(params);
1618
1701
  return;
@@ -1639,14 +1722,14 @@ export class AgentWorkspaceProxy {
1639
1722
  if (conversationId) {
1640
1723
  const turnId = this.extractTurnId(params);
1641
1724
  if (turnId)
1642
- this.currentTurnIds.set(conversationId, turnId);
1725
+ this.rememberTurnConversationId(conversationId, turnId);
1643
1726
  this.updateConversationStatus(conversationId, "running");
1644
1727
  }
1645
1728
  return;
1646
1729
  }
1647
1730
  if (method === "turn/completed") {
1648
1731
  if (conversationId) {
1649
- this.currentTurnIds.delete(conversationId);
1732
+ this.forgetCurrentTurn(conversationId, this.extractTurnId(params));
1650
1733
  this.updateConversationStatus(conversationId, "idle");
1651
1734
  }
1652
1735
  return;
@@ -1703,7 +1786,7 @@ export class AgentWorkspaceProxy {
1703
1786
  const raw = asRecord(params);
1704
1787
  if (!raw)
1705
1788
  return;
1706
- const conversationId = this.conversationIdFromParams(raw) ?? this.activeConversationId;
1789
+ const conversationId = this.conversationIdFromParams(raw) ?? this.fallbackConversationId();
1707
1790
  if (!conversationId)
1708
1791
  return;
1709
1792
  const itemId = firstString(raw, ["itemId", "id", "messageId"]) ?? id("msg");
@@ -1728,7 +1811,7 @@ export class AgentWorkspaceProxy {
1728
1811
  }
1729
1812
  handlePlanUpdated(params) {
1730
1813
  const raw = asRecord(params);
1731
- const conversationId = this.conversationIdFromParams(raw) ?? this.activeConversationId;
1814
+ const conversationId = this.conversationIdFromParams(raw) ?? this.fallbackConversationId();
1732
1815
  if (!conversationId)
1733
1816
  return;
1734
1817
  const plan = Array.isArray(raw?.plan) ? raw.plan : [];
@@ -1760,7 +1843,7 @@ export class AgentWorkspaceProxy {
1760
1843
  const raw = asRecord(params);
1761
1844
  if (!raw)
1762
1845
  return;
1763
- const conversationId = this.conversationIdFromParams(raw) ?? this.activeConversationId;
1846
+ const conversationId = this.conversationIdFromParams(raw) ?? this.fallbackConversationId();
1764
1847
  if (!conversationId)
1765
1848
  return;
1766
1849
  const itemId = firstString(raw, ["itemId", "id"]) ?? "plan";
@@ -1784,24 +1867,26 @@ export class AgentWorkspaceProxy {
1784
1867
  const item = extractItem(params);
1785
1868
  if (!item)
1786
1869
  return;
1787
- const itemType = firstString(item, ["type"]);
1870
+ const sourceConversationId = this.conversationIdFromParams(params);
1871
+ const routedItem = sourceConversationId ? { ...item, conversationId: sourceConversationId } : item;
1872
+ const itemType = firstString(routedItem, ["type"]);
1788
1873
  const normalizedItemType = normalizedIdentifier(itemType);
1789
1874
  if (normalizedItemType === "agentmessage" || normalizedItemType === "assistantmessage") {
1790
- this.handleCompletedMessageItem(item, true);
1875
+ this.handleCompletedMessageItem(routedItem, true);
1791
1876
  return;
1792
1877
  }
1793
1878
  if (normalizedItemType === "plan") {
1794
- this.handlePlanUpdated({ plan: [item] });
1879
+ this.handlePlanUpdated({ plan: [routedItem], conversationId: sourceConversationId });
1795
1880
  return;
1796
1881
  }
1797
1882
  if (isSubagentItemType(itemType)) {
1798
- this.handleSubagentItem(item, "running", true);
1883
+ this.handleSubagentItem(routedItem, "running", true);
1799
1884
  return;
1800
1885
  }
1801
- if (this.handleSemanticSystemItem(item, "running", true))
1886
+ if (this.handleSemanticSystemItem(routedItem, "running", true))
1802
1887
  return;
1803
- const conversationId = this.conversationIdFromParams(item) ?? this.activeConversationId;
1804
- const toolCall = this.toolCallFromItem(item, "running");
1888
+ const conversationId = this.conversationIdFromParams(routedItem) ?? this.fallbackConversationId();
1889
+ const toolCall = this.toolCallFromItem(routedItem, "running");
1805
1890
  if (!conversationId || !toolCall)
1806
1891
  return;
1807
1892
  this.toolConversationIds.set(toolCall.id, conversationId);
@@ -1811,24 +1896,26 @@ export class AgentWorkspaceProxy {
1811
1896
  const item = extractItem(params);
1812
1897
  if (!item)
1813
1898
  return;
1814
- const itemType = firstString(item, ["type"]);
1899
+ const sourceConversationId = this.conversationIdFromParams(params);
1900
+ const routedItem = sourceConversationId ? { ...item, conversationId: sourceConversationId } : item;
1901
+ const itemType = firstString(routedItem, ["type"]);
1815
1902
  const normalizedItemType = normalizedIdentifier(itemType);
1816
1903
  if (normalizedItemType === "agentmessage" || normalizedItemType === "assistantmessage") {
1817
- this.handleCompletedMessageItem(item, false);
1904
+ this.handleCompletedMessageItem(routedItem, false);
1818
1905
  return;
1819
1906
  }
1820
1907
  if (normalizedItemType === "plan") {
1821
- this.handlePlanDelta({ ...item, delta: firstString(item, ["text", "content", "message"]) });
1908
+ this.handlePlanDelta({ ...routedItem, delta: firstString(routedItem, ["text", "content", "message"]) });
1822
1909
  return;
1823
1910
  }
1824
1911
  if (isSubagentItemType(itemType)) {
1825
- this.handleSubagentItem(item, normalizeToolStatus(item.status, true), false);
1912
+ this.handleSubagentItem(routedItem, normalizeToolStatus(routedItem.status, true), false);
1826
1913
  return;
1827
1914
  }
1828
- if (this.handleSemanticSystemItem(item, normalizeToolStatus(item.status, true), false))
1915
+ if (this.handleSemanticSystemItem(routedItem, normalizeToolStatus(routedItem.status, true), false))
1829
1916
  return;
1830
- const conversationId = this.conversationIdFromParams(item) ?? this.activeConversationId;
1831
- const toolCall = this.toolCallFromItem(item, normalizeToolStatus(item.status, true));
1917
+ const conversationId = this.conversationIdFromParams(routedItem) ?? this.fallbackConversationId();
1918
+ const toolCall = this.toolCallFromItem(routedItem, normalizeToolStatus(routedItem.status, true));
1832
1919
  if (!conversationId || !toolCall)
1833
1920
  return;
1834
1921
  const bufferedOutput = this.toolOutputBuffers.get(toolCall.id);
@@ -1846,7 +1933,8 @@ export class AgentWorkspaceProxy {
1846
1933
  return;
1847
1934
  const conversationId = this.conversationIdFromParams(raw) ??
1848
1935
  this.toolConversationIds.get(itemId) ??
1849
- this.activeConversationId;
1936
+ this.itemConversationIds.get(itemId) ??
1937
+ this.fallbackConversationId();
1850
1938
  if (!conversationId)
1851
1939
  return;
1852
1940
  const output = appendCapped(this.toolOutputBuffers.get(itemId), delta, 6000);
@@ -1868,7 +1956,8 @@ export class AgentWorkspaceProxy {
1868
1956
  const itemId = firstString(raw, ["itemId", "id"]) ?? id("file");
1869
1957
  const conversationId = this.conversationIdFromParams(raw) ??
1870
1958
  this.toolConversationIds.get(itemId) ??
1871
- this.activeConversationId;
1959
+ this.itemConversationIds.get(itemId) ??
1960
+ this.fallbackConversationId();
1872
1961
  if (!conversationId)
1873
1962
  return;
1874
1963
  const output = extractDiffText(raw) ??
@@ -1887,7 +1976,7 @@ export class AgentWorkspaceProxy {
1887
1976
  const raw = asRecord(params);
1888
1977
  if (!raw)
1889
1978
  return;
1890
- const conversationId = this.conversationIdFromParams(raw) ?? this.activeConversationId;
1979
+ const conversationId = this.conversationIdFromParams(raw) ?? this.fallbackConversationId();
1891
1980
  if (!conversationId)
1892
1981
  return;
1893
1982
  const diff = extractDiffText(raw);
@@ -1917,7 +2006,8 @@ export class AgentWorkspaceProxy {
1917
2006
  return;
1918
2007
  const conversationId = this.conversationIdFromParams(raw) ??
1919
2008
  this.toolConversationIds.get(processId) ??
1920
- this.activeConversationId;
2009
+ this.itemConversationIds.get(processId) ??
2010
+ this.fallbackConversationId();
1921
2011
  if (!conversationId)
1922
2012
  return;
1923
2013
  const output = appendCapped(this.toolOutputBuffers.get(processId), delta, 6000);
@@ -1934,7 +2024,7 @@ export class AgentWorkspaceProxy {
1934
2024
  }
1935
2025
  handleAutoApprovalReview(params, streaming) {
1936
2026
  const raw = asRecord(params) ?? {};
1937
- const conversationId = this.conversationIdFromParams(raw) ?? this.activeConversationId;
2027
+ const conversationId = this.conversationIdFromParams(raw) ?? this.fallbackConversationId();
1938
2028
  if (!conversationId)
1939
2029
  return;
1940
2030
  const itemId = firstString(raw, ["itemId", "id", "reviewId"]) ?? "auto-approval-review";
@@ -1963,7 +2053,7 @@ export class AgentWorkspaceProxy {
1963
2053
  this.updateConversationPreview(conversationId, streaming ? "正在审查自动授权" : "已完成自动授权审查", streaming ? "running" : undefined);
1964
2054
  }
1965
2055
  handleCompletedMessageItem(item, streaming) {
1966
- const conversationId = this.conversationIdFromParams(item) ?? this.activeConversationId;
2056
+ const conversationId = this.conversationIdFromParams(item) ?? this.fallbackConversationId();
1967
2057
  if (!conversationId)
1968
2058
  return;
1969
2059
  const itemId = firstString(item, ["id"]) ?? id("msg");
@@ -1991,7 +2081,7 @@ export class AgentWorkspaceProxy {
1991
2081
  firstString(nested, ["delta", "text", "content", "message"]);
1992
2082
  if (!text)
1993
2083
  return;
1994
- const conversationId = this.conversationIdFromParams(raw) ?? this.activeConversationId;
2084
+ const conversationId = this.conversationIdFromParams(raw) ?? this.fallbackConversationId();
1995
2085
  if (!conversationId)
1996
2086
  return;
1997
2087
  if (firstString(raw, ["toolName", "tool", "name"])) {
@@ -2024,7 +2114,7 @@ export class AgentWorkspaceProxy {
2024
2114
  handleSemanticSystemItem(item, status, streaming) {
2025
2115
  const itemType = firstString(item, ["type"]);
2026
2116
  const normalized = normalizedIdentifier(itemType);
2027
- const conversationId = this.conversationIdFromParams(item) ?? this.activeConversationId;
2117
+ const conversationId = this.conversationIdFromParams(item) ?? this.fallbackConversationId();
2028
2118
  if (!conversationId)
2029
2119
  return false;
2030
2120
  const itemId = firstString(item, ["id", "itemId"]) ?? id("item");
@@ -2072,7 +2162,7 @@ export class AgentWorkspaceProxy {
2072
2162
  return false;
2073
2163
  }
2074
2164
  handleSubagentItem(item, status, streaming) {
2075
- const conversationId = this.conversationIdFromParams(item) ?? this.activeConversationId;
2165
+ const conversationId = this.conversationIdFromParams(item) ?? this.fallbackConversationId();
2076
2166
  if (!conversationId)
2077
2167
  return;
2078
2168
  const subagent = decodeSubagentAction(item, status);
@@ -2099,7 +2189,7 @@ export class AgentWorkspaceProxy {
2099
2189
  }
2100
2190
  handleStructuredInput(params, waitForResponse = false) {
2101
2191
  const raw = asRecord(params) ?? {};
2102
- const conversationId = this.conversationIdFromParams(raw) ?? this.activeConversationId;
2192
+ const conversationId = this.conversationIdFromParams(raw) ?? this.fallbackConversationId();
2103
2193
  const source = firstString(raw, ["method", "source", "requestMethod"]);
2104
2194
  const formatResponse = source === "mcpServer/elicitation/request"
2105
2195
  ? formatMcpElicitationResponse
@@ -2165,7 +2255,7 @@ export class AgentWorkspaceProxy {
2165
2255
  }
2166
2256
  handlePermission(params, waitForResponse, source) {
2167
2257
  const raw = asRecord(params) ?? {};
2168
- const conversationId = this.conversationIdFromParams(raw) ?? this.activeConversationId;
2258
+ const conversationId = this.conversationIdFromParams(raw) ?? this.fallbackConversationId();
2169
2259
  if (!conversationId)
2170
2260
  return waitForResponse ? Promise.resolve({ outcome: { outcome: "cancelled" } }) : undefined;
2171
2261
  const requestId = firstString(raw, ["requestId", "id", "permissionId"]) ?? id("perm");
@@ -2279,6 +2369,7 @@ export class AgentWorkspaceProxy {
2279
2369
  });
2280
2370
  }
2281
2371
  addItem(conversationId, item) {
2372
+ this.rememberItemConversationId(conversationId, item);
2282
2373
  const timeline = this.timelines.get(conversationId) ?? [];
2283
2374
  timeline.push(item);
2284
2375
  timeline.sort((a, b) => a.createdAt - b.createdAt);
@@ -2289,6 +2380,7 @@ export class AgentWorkspaceProxy {
2289
2380
  this.emitItem(conversationId, item);
2290
2381
  }
2291
2382
  upsertItem(conversationId, item) {
2383
+ this.rememberItemConversationId(conversationId, item);
2292
2384
  const timeline = this.timelines.get(conversationId) ?? [];
2293
2385
  const index = timeline.findIndex((entry) => entry.id === item.id);
2294
2386
  if (index >= 0)
@@ -2317,6 +2409,8 @@ export class AgentWorkspaceProxy {
2317
2409
  };
2318
2410
  this.toolConversationIds.set(toolCall.id, conversationId);
2319
2411
  this.toolConversationIds.set(nextToolCall.id, conversationId);
2412
+ this.itemConversationIds.set(toolCall.id, conversationId);
2413
+ this.itemConversationIds.set(nextToolCall.id, conversationId);
2320
2414
  const kind = nextToolCall.name.includes("文件")
2321
2415
  ? "file_change"
2322
2416
  : nextToolCall.name.includes("命令")
@@ -2401,6 +2495,22 @@ export class AgentWorkspaceProxy {
2401
2495
  this.toolConversationIds.set(toolId, newId);
2402
2496
  }
2403
2497
  }
2498
+ for (const [turnId, conversationId] of this.turnConversationIds) {
2499
+ if (conversationId === oldId) {
2500
+ this.turnConversationIds.set(turnId, newId);
2501
+ }
2502
+ }
2503
+ const currentTurnId = this.currentTurnIds.get(oldId);
2504
+ if (currentTurnId) {
2505
+ this.currentTurnIds.delete(oldId);
2506
+ this.currentTurnIds.set(newId, currentTurnId);
2507
+ this.turnConversationIds.set(currentTurnId, newId);
2508
+ }
2509
+ for (const [itemId, conversationId] of this.itemConversationIds) {
2510
+ if (conversationId === oldId) {
2511
+ this.itemConversationIds.set(itemId, newId);
2512
+ }
2513
+ }
2404
2514
  if (this.activeConversationId === oldId) {
2405
2515
  this.activeConversationId = newId;
2406
2516
  }
@@ -2468,14 +2578,87 @@ export class AgentWorkspaceProxy {
2468
2578
  }
2469
2579
  conversationIdFromParams(params) {
2470
2580
  const raw = asRecord(params);
2471
- const agentSessionId = this.extractSessionId(raw);
2472
- if (agentSessionId)
2473
- return this.conversationByAgentSessionId.get(agentSessionId);
2581
+ if (!raw)
2582
+ return undefined;
2583
+ const directConversationId = firstString(raw, ["conversationId"]);
2584
+ if (directConversationId && this.conversations.has(directConversationId)) {
2585
+ return directConversationId;
2586
+ }
2474
2587
  const threadId = firstString(raw, ["threadId", "sessionId", "agentSessionId"]);
2475
- if (threadId)
2476
- return this.conversationByAgentSessionId.get(threadId);
2588
+ if (threadId) {
2589
+ const conversationId = this.conversationByAgentSessionId.get(threadId);
2590
+ if (conversationId)
2591
+ return conversationId;
2592
+ }
2593
+ const agentSessionId = this.extractSessionId(raw);
2594
+ if (agentSessionId) {
2595
+ const conversationId = this.conversationByAgentSessionId.get(agentSessionId);
2596
+ if (conversationId)
2597
+ return conversationId;
2598
+ }
2599
+ const turnId = this.extractTurnId(raw) ?? firstString(raw, ["turnId"]);
2600
+ if (turnId) {
2601
+ const conversationId = this.turnConversationIds.get(turnId);
2602
+ if (conversationId)
2603
+ return conversationId;
2604
+ }
2605
+ const itemId = firstString(raw, [
2606
+ "itemId",
2607
+ "messageId",
2608
+ "toolCallId",
2609
+ "processId",
2610
+ "callId",
2611
+ "requestId",
2612
+ "permissionId",
2613
+ "id",
2614
+ ]);
2615
+ if (itemId) {
2616
+ const conversationId = this.itemConversationIds.get(itemId) ??
2617
+ this.toolConversationIds.get(itemId);
2618
+ if (conversationId)
2619
+ return conversationId;
2620
+ }
2621
+ for (const nested of [raw.params, raw.item, raw.message, raw.toolCall, raw.command, raw.event]) {
2622
+ const nestedRecord = asRecord(nested);
2623
+ if (!nestedRecord || nestedRecord === raw)
2624
+ continue;
2625
+ const conversationId = this.conversationIdFromParams(nestedRecord);
2626
+ if (conversationId)
2627
+ return conversationId;
2628
+ }
2477
2629
  return undefined;
2478
2630
  }
2631
+ fallbackConversationId() {
2632
+ const liveConversations = [...this.conversations.values()].filter((conversation) => conversation.status === "running" || conversation.status === "waiting_permission");
2633
+ return liveConversations.length === 1 ? liveConversations[0]?.id : undefined;
2634
+ }
2635
+ rememberTurnConversationId(conversationId, turnId) {
2636
+ this.currentTurnIds.set(conversationId, turnId);
2637
+ this.turnConversationIds.set(turnId, conversationId);
2638
+ }
2639
+ forgetCurrentTurn(conversationId, turnId) {
2640
+ const currentTurnId = this.currentTurnIds.get(conversationId);
2641
+ this.currentTurnIds.delete(conversationId);
2642
+ if (turnId)
2643
+ this.turnConversationIds.delete(turnId);
2644
+ if (currentTurnId && currentTurnId !== turnId)
2645
+ this.turnConversationIds.delete(currentTurnId);
2646
+ }
2647
+ rememberItemConversationId(conversationId, item) {
2648
+ const keys = [
2649
+ item.id,
2650
+ item.itemId,
2651
+ item.toolCall?.id,
2652
+ item.permission?.requestId,
2653
+ item.structuredInput?.requestId,
2654
+ ].filter((key) => Boolean(key));
2655
+ for (const key of keys) {
2656
+ this.itemConversationIds.set(key, conversationId);
2657
+ }
2658
+ if (item.turnId) {
2659
+ this.turnConversationIds.set(item.turnId, conversationId);
2660
+ }
2661
+ }
2479
2662
  handleProviderExit(provider, message) {
2480
2663
  this.clients.delete(provider);
2481
2664
  this.agentProtocols.delete(provider);