linkshell-cli 0.3.7 → 0.3.9
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 +1 -0
- package/dist/cli/src/runtime/acp/agent-workspace.js +52 -12
- package/dist/cli/src/runtime/acp/agent-workspace.js.map +1 -1
- package/dist/cli/src/runtime/acp/claude-sessions.d.ts +17 -0
- package/dist/cli/src/runtime/acp/claude-sessions.js +147 -1
- package/dist/cli/src/runtime/acp/claude-sessions.js.map +1 -1
- package/dist/cli/src/runtime/acp/codex-sessions.d.ts +17 -0
- package/dist/cli/src/runtime/acp/codex-sessions.js +163 -3
- package/dist/cli/src/runtime/acp/codex-sessions.js.map +1 -1
- package/dist/cli/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/runtime/acp/agent-workspace.ts +54 -20
- package/src/runtime/acp/claude-sessions.ts +160 -1
- package/src/runtime/acp/codex-sessions.ts +178 -3
|
@@ -83,6 +83,7 @@ export declare class AgentWorkspaceProxy {
|
|
|
83
83
|
private updateConversationPreview;
|
|
84
84
|
private updateConversationStatus;
|
|
85
85
|
private sendSnapshot;
|
|
86
|
+
private hydrateStoredTimeline;
|
|
86
87
|
private conversationIdFromParams;
|
|
87
88
|
private fallbackConversationId;
|
|
88
89
|
private rememberTurnConversationId;
|
|
@@ -5,8 +5,8 @@ import { createEnvelope, parseTypedPayload, } from "@linkshell/protocol";
|
|
|
5
5
|
import { AcpClient } from "./acp-client.js";
|
|
6
6
|
import { ClaudeSdkClient } from "./claude-sdk-client.js";
|
|
7
7
|
import { ClaudeStreamJsonClient } from "./claude-stream-json-client.js";
|
|
8
|
-
import { listClaudeStoredSessions } from "./claude-sessions.js";
|
|
9
|
-
import { listCodexStoredSessions } from "./codex-sessions.js";
|
|
8
|
+
import { listClaudeStoredSessions, loadClaudeStoredTimeline } from "./claude-sessions.js";
|
|
9
|
+
import { listCodexStoredSessions, loadCodexStoredTimeline } from "./codex-sessions.js";
|
|
10
10
|
import { resolveAgentCommand } from "./provider-resolver.js";
|
|
11
11
|
const PERMISSION_TIMEOUT_MS = 5 * 60_000;
|
|
12
12
|
const MAX_TIMELINE_ITEMS = 200;
|
|
@@ -1291,16 +1291,6 @@ export class AgentWorkspaceProxy {
|
|
|
1291
1291
|
}
|
|
1292
1292
|
async openConversation(payload) {
|
|
1293
1293
|
const provider = payload.provider ?? this.input.availableProviders[0];
|
|
1294
|
-
if (!provider) {
|
|
1295
|
-
return this.openFailure(payload, "没有可用的 Agent provider。");
|
|
1296
|
-
}
|
|
1297
|
-
if (!this.input.availableProviders.includes(provider)) {
|
|
1298
|
-
return this.openFailure(payload, `${providerLabel(provider)} 未安装或不可用。`);
|
|
1299
|
-
}
|
|
1300
|
-
const client = await this.ensureProviderClient(provider);
|
|
1301
|
-
if (!client) {
|
|
1302
|
-
return this.openFailure(payload, `${providerLabel(provider)} 启动失败。请确认 CLI 已安装并可用。`);
|
|
1303
|
-
}
|
|
1304
1294
|
const cwd = payload.cwd ?? this.input.cwd;
|
|
1305
1295
|
let agentSessionId = payload.agentSessionId;
|
|
1306
1296
|
let existingConversation = (payload.conversationId ? this.conversations.get(payload.conversationId) : undefined) ??
|
|
@@ -1309,6 +1299,7 @@ export class AgentWorkspaceProxy {
|
|
|
1309
1299
|
if (payload.conversationId && existingConversation.id !== payload.conversationId) {
|
|
1310
1300
|
existingConversation = this.adoptConversationId(existingConversation.id, payload.conversationId);
|
|
1311
1301
|
}
|
|
1302
|
+
this.hydrateStoredTimeline(existingConversation);
|
|
1312
1303
|
this.activeConversationId = existingConversation.id;
|
|
1313
1304
|
this.input.send(createEnvelope({
|
|
1314
1305
|
type: "agent.v2.conversation.opened",
|
|
@@ -1320,6 +1311,16 @@ export class AgentWorkspaceProxy {
|
|
|
1320
1311
|
}));
|
|
1321
1312
|
return existingConversation;
|
|
1322
1313
|
}
|
|
1314
|
+
if (!provider) {
|
|
1315
|
+
return this.openFailure(payload, "没有可用的 Agent provider。");
|
|
1316
|
+
}
|
|
1317
|
+
if (!this.input.availableProviders.includes(provider)) {
|
|
1318
|
+
return this.openFailure(payload, `${providerLabel(provider)} 未安装或不可用。`);
|
|
1319
|
+
}
|
|
1320
|
+
const client = await this.ensureProviderClient(provider);
|
|
1321
|
+
if (!client) {
|
|
1322
|
+
return this.openFailure(payload, `${providerLabel(provider)} 启动失败。请确认 CLI 已安装并可用。`);
|
|
1323
|
+
}
|
|
1323
1324
|
try {
|
|
1324
1325
|
const result = agentSessionId
|
|
1325
1326
|
? await client.loadSession({ sessionId: agentSessionId, cwd })
|
|
@@ -1348,6 +1349,7 @@ export class AgentWorkspaceProxy {
|
|
|
1348
1349
|
this.conversationByAgentSessionId.set(agentSessionId, conversation.id);
|
|
1349
1350
|
this.activeConversationId = conversation.id;
|
|
1350
1351
|
this.timelines.set(conversation.id, this.timelines.get(conversation.id) ?? []);
|
|
1352
|
+
this.hydrateStoredTimeline(conversation);
|
|
1351
1353
|
this.input.send(createEnvelope({
|
|
1352
1354
|
type: "agent.v2.conversation.opened",
|
|
1353
1355
|
hostDeviceId: this.input.hostDeviceId,
|
|
@@ -2579,6 +2581,16 @@ export class AgentWorkspaceProxy {
|
|
|
2579
2581
|
this.emitConversation(conversation);
|
|
2580
2582
|
}
|
|
2581
2583
|
sendSnapshot(conversationId) {
|
|
2584
|
+
if (conversationId) {
|
|
2585
|
+
const conversation = this.conversations.get(conversationId);
|
|
2586
|
+
if (conversation)
|
|
2587
|
+
this.hydrateStoredTimeline(conversation);
|
|
2588
|
+
}
|
|
2589
|
+
else if (this.activeConversationId) {
|
|
2590
|
+
const conversation = this.conversations.get(this.activeConversationId);
|
|
2591
|
+
if (conversation)
|
|
2592
|
+
this.hydrateStoredTimeline(conversation);
|
|
2593
|
+
}
|
|
2582
2594
|
const conversations = [...this.conversations.values()];
|
|
2583
2595
|
const items = conversationId
|
|
2584
2596
|
? this.timelines.get(conversationId) ?? []
|
|
@@ -2593,6 +2605,34 @@ export class AgentWorkspaceProxy {
|
|
|
2593
2605
|
},
|
|
2594
2606
|
}));
|
|
2595
2607
|
}
|
|
2608
|
+
hydrateStoredTimeline(conversation) {
|
|
2609
|
+
if (!conversation.agentSessionId)
|
|
2610
|
+
return;
|
|
2611
|
+
const existing = this.timelines.get(conversation.id) ?? [];
|
|
2612
|
+
if (existing.length > 0)
|
|
2613
|
+
return;
|
|
2614
|
+
const result = conversation.provider === "codex"
|
|
2615
|
+
? loadCodexStoredTimeline(conversation.agentSessionId, conversation.id, conversation.cwd || this.input.cwd)
|
|
2616
|
+
: conversation.provider === "claude"
|
|
2617
|
+
? loadClaudeStoredTimeline(conversation.agentSessionId, conversation.id)
|
|
2618
|
+
: { items: [] };
|
|
2619
|
+
if (result.items.length === 0)
|
|
2620
|
+
return;
|
|
2621
|
+
const items = result.items
|
|
2622
|
+
.sort((a, b) => a.createdAt - b.createdAt)
|
|
2623
|
+
.slice(-MAX_TIMELINE_ITEMS);
|
|
2624
|
+
this.timelines.set(conversation.id, items);
|
|
2625
|
+
for (const item of items)
|
|
2626
|
+
this.rememberItemConversationId(conversation.id, item);
|
|
2627
|
+
const lastMessage = [...items].reverse().find((item) => item.text?.trim());
|
|
2628
|
+
if (lastMessage?.text && !conversation.lastMessagePreview) {
|
|
2629
|
+
conversation.lastMessagePreview = previewText(lastMessage.text);
|
|
2630
|
+
}
|
|
2631
|
+
const lastActivityAt = items.at(-1)?.createdAt;
|
|
2632
|
+
if (lastActivityAt) {
|
|
2633
|
+
conversation.lastActivityAt = Math.max(conversation.lastActivityAt, lastActivityAt);
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2596
2636
|
conversationIdFromParams(params) {
|
|
2597
2637
|
const raw = asRecord(params);
|
|
2598
2638
|
if (!raw)
|