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.
- package/dist/cli/src/runtime/acp/agent-workspace.d.ts +6 -0
- package/dist/cli/src/runtime/acp/agent-workspace.js +224 -41
- package/dist/cli/src/runtime/acp/agent-workspace.js.map +1 -1
- package/dist/cli/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/runtime/acp/agent-workspace.ts +229 -47
|
@@ -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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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(
|
|
1875
|
+
this.handleCompletedMessageItem(routedItem, true);
|
|
1791
1876
|
return;
|
|
1792
1877
|
}
|
|
1793
1878
|
if (normalizedItemType === "plan") {
|
|
1794
|
-
this.handlePlanUpdated({ plan: [
|
|
1879
|
+
this.handlePlanUpdated({ plan: [routedItem], conversationId: sourceConversationId });
|
|
1795
1880
|
return;
|
|
1796
1881
|
}
|
|
1797
1882
|
if (isSubagentItemType(itemType)) {
|
|
1798
|
-
this.handleSubagentItem(
|
|
1883
|
+
this.handleSubagentItem(routedItem, "running", true);
|
|
1799
1884
|
return;
|
|
1800
1885
|
}
|
|
1801
|
-
if (this.handleSemanticSystemItem(
|
|
1886
|
+
if (this.handleSemanticSystemItem(routedItem, "running", true))
|
|
1802
1887
|
return;
|
|
1803
|
-
const conversationId = this.conversationIdFromParams(
|
|
1804
|
-
const toolCall = this.toolCallFromItem(
|
|
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
|
|
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(
|
|
1904
|
+
this.handleCompletedMessageItem(routedItem, false);
|
|
1818
1905
|
return;
|
|
1819
1906
|
}
|
|
1820
1907
|
if (normalizedItemType === "plan") {
|
|
1821
|
-
this.handlePlanDelta({ ...
|
|
1908
|
+
this.handlePlanDelta({ ...routedItem, delta: firstString(routedItem, ["text", "content", "message"]) });
|
|
1822
1909
|
return;
|
|
1823
1910
|
}
|
|
1824
1911
|
if (isSubagentItemType(itemType)) {
|
|
1825
|
-
this.handleSubagentItem(
|
|
1912
|
+
this.handleSubagentItem(routedItem, normalizeToolStatus(routedItem.status, true), false);
|
|
1826
1913
|
return;
|
|
1827
1914
|
}
|
|
1828
|
-
if (this.handleSemanticSystemItem(
|
|
1915
|
+
if (this.handleSemanticSystemItem(routedItem, normalizeToolStatus(routedItem.status, true), false))
|
|
1829
1916
|
return;
|
|
1830
|
-
const conversationId = this.conversationIdFromParams(
|
|
1831
|
-
const toolCall = this.toolCallFromItem(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
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
|
-
|
|
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);
|