linkshell-cli 0.3.5 → 0.3.7

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.
@@ -9,6 +9,8 @@ import {
9
9
  import { AcpClient } from "./acp-client.js";
10
10
  import { ClaudeSdkClient } from "./claude-sdk-client.js";
11
11
  import { ClaudeStreamJsonClient } from "./claude-stream-json-client.js";
12
+ import { listClaudeStoredSessions } from "./claude-sessions.js";
13
+ import { listCodexStoredSessions } from "./codex-sessions.js";
12
14
  import type { AgentProtocol, AgentProvider } from "./provider-resolver.js";
13
15
  import { resolveAgentCommand } from "./provider-resolver.js";
14
16
 
@@ -1161,6 +1163,7 @@ function parseRemoteSessions(value: unknown): Array<{
1161
1163
  model?: string;
1162
1164
  createdAt?: number;
1163
1165
  lastActivityAt?: number;
1166
+ archived?: boolean;
1164
1167
  }> {
1165
1168
  const raw = asRecord(value);
1166
1169
  const sessionsValue =
@@ -1176,6 +1179,7 @@ function parseRemoteSessions(value: unknown): Array<{
1176
1179
  model?: string;
1177
1180
  createdAt?: number;
1178
1181
  lastActivityAt?: number;
1182
+ archived?: boolean;
1179
1183
  }> = [];
1180
1184
  for (const entry of sessionsValue) {
1181
1185
  const session = asRecord(entry);
@@ -1194,6 +1198,7 @@ function parseRemoteSessions(value: unknown): Array<{
1194
1198
  model: firstString(source, ["model", "modelId"]),
1195
1199
  createdAt: parseTimestamp(source.createdAt ?? source.created_at),
1196
1200
  lastActivityAt: parseTimestamp(source.lastActivityAt ?? source.updatedAt ?? source.modifiedAt ?? source.lastModified ?? source.updated_at),
1201
+ archived: typeof source.archived === "boolean" ? source.archived : undefined,
1197
1202
  });
1198
1203
  }
1199
1204
  return result;
@@ -1437,36 +1442,12 @@ export class AgentWorkspaceProxy {
1437
1442
 
1438
1443
  private async syncProviderSessions(): Promise<void> {
1439
1444
  await this.initialize();
1445
+ this.upsertProviderSessions("codex", listCodexStoredSessions(this.input.cwd));
1446
+ this.upsertProviderSessions("claude", listClaudeStoredSessions(this.input.cwd));
1440
1447
  for (const [provider, client] of this.clients) {
1441
1448
  try {
1442
1449
  const result = await client.listSessions();
1443
- for (const remote of parseRemoteSessions(result)) {
1444
- const agentSessionId = remote.id;
1445
- const existingId = this.conversationByAgentSessionId.get(agentSessionId);
1446
- const now = Date.now();
1447
- const conversationId = existingId ?? `agent:${agentSessionId}`;
1448
- const existing = this.conversations.get(conversationId);
1449
- const cwd = remote.cwd ?? existing?.cwd ?? this.input.cwd;
1450
- const conversation: AgentConversation = {
1451
- id: conversationId,
1452
- agentSessionId,
1453
- provider,
1454
- cwd,
1455
- title: remote.title ?? existing?.title ?? titleFromCwd(cwd),
1456
- model: remote.model ?? existing?.model,
1457
- reasoningEffort: existing?.reasoningEffort,
1458
- permissionMode: existing?.permissionMode,
1459
- collaborationMode: existing?.collaborationMode,
1460
- status: existing?.status ?? "idle",
1461
- archived: existing?.archived ?? false,
1462
- lastMessagePreview: existing?.lastMessagePreview,
1463
- lastActivityAt: remote.lastActivityAt ?? existing?.lastActivityAt ?? now,
1464
- createdAt: remote.createdAt ?? existing?.createdAt ?? now,
1465
- };
1466
- this.conversations.set(conversation.id, conversation);
1467
- this.conversationByAgentSessionId.set(agentSessionId, conversation.id);
1468
- this.timelines.set(conversation.id, this.timelines.get(conversation.id) ?? []);
1469
- }
1450
+ this.upsertProviderSessions(provider, result);
1470
1451
  } catch (error) {
1471
1452
  if (this.input.verbose) {
1472
1453
  process.stderr.write(`[agent:v2] session list failed for ${provider}: ${error instanceof Error ? error.message : String(error)}\n`);
@@ -1475,6 +1456,36 @@ export class AgentWorkspaceProxy {
1475
1456
  }
1476
1457
  }
1477
1458
 
1459
+ private upsertProviderSessions(provider: AgentProvider, result: unknown): void {
1460
+ for (const remote of parseRemoteSessions(result)) {
1461
+ const agentSessionId = remote.id;
1462
+ const existingId = this.conversationByAgentSessionId.get(agentSessionId);
1463
+ const now = Date.now();
1464
+ const conversationId = existingId ?? `agent:${agentSessionId}`;
1465
+ const existing = this.conversations.get(conversationId);
1466
+ const cwd = remote.cwd ?? existing?.cwd ?? this.input.cwd;
1467
+ const conversation: AgentConversation = {
1468
+ id: conversationId,
1469
+ agentSessionId,
1470
+ provider,
1471
+ cwd,
1472
+ title: remote.title ?? existing?.title ?? titleFromCwd(cwd),
1473
+ model: remote.model ?? existing?.model,
1474
+ reasoningEffort: existing?.reasoningEffort,
1475
+ permissionMode: existing?.permissionMode,
1476
+ collaborationMode: existing?.collaborationMode,
1477
+ status: existing?.status ?? "idle",
1478
+ archived: remote.archived ?? existing?.archived ?? false,
1479
+ lastMessagePreview: existing?.lastMessagePreview,
1480
+ lastActivityAt: remote.lastActivityAt ?? existing?.lastActivityAt ?? now,
1481
+ createdAt: remote.createdAt ?? existing?.createdAt ?? now,
1482
+ };
1483
+ this.conversations.set(conversation.id, conversation);
1484
+ this.conversationByAgentSessionId.set(agentSessionId, conversation.id);
1485
+ this.timelines.set(conversation.id, this.timelines.get(conversation.id) ?? []);
1486
+ }
1487
+ }
1488
+
1478
1489
  private sendCapabilities(): void {
1479
1490
  const providers = this.input.availableProviders.map((provider) => {
1480
1491
  const client = this.clients.get(provider);
@@ -11,6 +11,7 @@ export interface CodexStoredSession {
11
11
  title?: string;
12
12
  createdAt?: number;
13
13
  lastModified: number;
14
+ archived?: boolean;
14
15
  }
15
16
 
16
17
  interface CodexIndexEntry {
@@ -158,15 +159,15 @@ function readCodexSessionFile(filePath: string, fallbackCwd: string): Omit<Codex
158
159
  };
159
160
  }
160
161
 
161
- function collectJsonlFiles(dir: string, result: string[]): void {
162
+ function collectJsonlFiles(dir: string, result: Array<{ path: string; archived: boolean }>, archived: boolean): void {
162
163
  if (!existsSync(dir)) return;
163
164
  try {
164
165
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
165
166
  const path = join(dir, entry.name);
166
167
  if (entry.isDirectory()) {
167
- collectJsonlFiles(path, result);
168
+ collectJsonlFiles(path, result, archived);
168
169
  } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
169
- result.push(path);
170
+ result.push({ path, archived });
170
171
  }
171
172
  }
172
173
  } catch {
@@ -179,13 +180,13 @@ export function listCodexStoredSessions(inputCwd: string): { sessions: CodexStor
179
180
  if (!existsSync(root)) return { sessions: [] };
180
181
 
181
182
  const index = loadSessionIndex(root);
182
- const files: string[] = [];
183
- collectJsonlFiles(join(root, "sessions"), files);
184
- collectJsonlFiles(join(root, "archived_sessions"), files);
183
+ const files: Array<{ path: string; archived: boolean }> = [];
184
+ collectJsonlFiles(join(root, "sessions"), files, false);
185
+ collectJsonlFiles(join(root, "archived_sessions"), files, true);
185
186
 
186
187
  const sessionsById = new Map<string, CodexStoredSession>();
187
188
  for (const file of files) {
188
- const metadata = readCodexSessionFile(file, inputCwd);
189
+ const metadata = readCodexSessionFile(file.path, inputCwd);
189
190
  if (!metadata) continue;
190
191
  const indexed = index.get(metadata.id);
191
192
  const session: CodexStoredSession = {
@@ -194,9 +195,10 @@ export function listCodexStoredSessions(inputCwd: string): { sessions: CodexStor
194
195
  title: indexed?.title,
195
196
  createdAt: metadata.createdAt,
196
197
  lastModified: indexed?.updatedAt ?? metadata.lastModified ?? Date.now(),
198
+ archived: file.archived,
197
199
  };
198
200
  const existing = sessionsById.get(session.id);
199
- if (!existing || session.lastModified > existing.lastModified) {
201
+ if (!existing || session.lastModified > existing.lastModified || session.archived) {
200
202
  sessionsById.set(session.id, session);
201
203
  }
202
204
  }
@@ -208,6 +210,7 @@ export function listCodexStoredSessions(inputCwd: string): { sessions: CodexStor
208
210
  cwd: resolve(inputCwd),
209
211
  title: indexed.title,
210
212
  lastModified: indexed.updatedAt ?? Date.now(),
213
+ archived: false,
211
214
  });
212
215
  }
213
216