@sumicom/quicksave 0.8.8 → 0.8.10

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 (122) hide show
  1. package/dist/ai/cardBuilder.d.ts +65 -4
  2. package/dist/ai/cardBuilder.d.ts.map +1 -1
  3. package/dist/ai/cardBuilder.js +338 -28
  4. package/dist/ai/cardBuilder.js.map +1 -1
  5. package/dist/ai/claudeCliProvider.d.ts +15 -0
  6. package/dist/ai/claudeCliProvider.d.ts.map +1 -1
  7. package/dist/ai/claudeCliProvider.js +87 -3
  8. package/dist/ai/claudeCliProvider.js.map +1 -1
  9. package/dist/ai/claudeCodeProvider.d.ts +4 -0
  10. package/dist/ai/claudeCodeProvider.d.ts.map +1 -1
  11. package/dist/ai/claudeCodeProvider.js +41 -0
  12. package/dist/ai/claudeCodeProvider.js.map +1 -1
  13. package/dist/ai/claudeSdkProvider.d.ts +1 -0
  14. package/dist/ai/claudeSdkProvider.d.ts.map +1 -1
  15. package/dist/ai/claudeSdkProvider.js +14 -2
  16. package/dist/ai/claudeSdkProvider.js.map +1 -1
  17. package/dist/ai/claudeTerminal/cardSynth.d.ts +63 -0
  18. package/dist/ai/claudeTerminal/cardSynth.d.ts.map +1 -0
  19. package/dist/ai/claudeTerminal/cardSynth.js +92 -0
  20. package/dist/ai/claudeTerminal/cardSynth.js.map +1 -0
  21. package/dist/ai/claudeTerminal/hookBridge.d.ts +56 -0
  22. package/dist/ai/claudeTerminal/hookBridge.d.ts.map +1 -0
  23. package/dist/ai/claudeTerminal/hookBridge.js +131 -0
  24. package/dist/ai/claudeTerminal/hookBridge.js.map +1 -0
  25. package/dist/ai/claudeTerminal/hookHandler.d.ts +18 -0
  26. package/dist/ai/claudeTerminal/hookHandler.d.ts.map +1 -0
  27. package/dist/ai/claudeTerminal/hookHandler.js +124 -0
  28. package/dist/ai/claudeTerminal/hookHandler.js.map +1 -0
  29. package/dist/ai/claudeTerminal/index.d.ts +5 -0
  30. package/dist/ai/claudeTerminal/index.d.ts.map +1 -0
  31. package/dist/ai/claudeTerminal/index.js +7 -0
  32. package/dist/ai/claudeTerminal/index.js.map +1 -0
  33. package/dist/ai/claudeTerminal/jsonlTail.d.ts +40 -0
  34. package/dist/ai/claudeTerminal/jsonlTail.d.ts.map +1 -0
  35. package/dist/ai/claudeTerminal/jsonlTail.js +129 -0
  36. package/dist/ai/claudeTerminal/jsonlTail.js.map +1 -0
  37. package/dist/ai/claudeTerminal/provider.d.ts +106 -0
  38. package/dist/ai/claudeTerminal/provider.d.ts.map +1 -0
  39. package/dist/ai/claudeTerminal/provider.js +579 -0
  40. package/dist/ai/claudeTerminal/provider.js.map +1 -0
  41. package/dist/ai/claudeTerminal/settingsBuilder.d.ts +44 -0
  42. package/dist/ai/claudeTerminal/settingsBuilder.d.ts.map +1 -0
  43. package/dist/ai/claudeTerminal/settingsBuilder.js +40 -0
  44. package/dist/ai/claudeTerminal/settingsBuilder.js.map +1 -0
  45. package/dist/ai/codexAppServer/cardAdapter.d.ts.map +1 -1
  46. package/dist/ai/codexAppServer/cardAdapter.js +13 -5
  47. package/dist/ai/codexAppServer/cardAdapter.js.map +1 -1
  48. package/dist/ai/codexAppServer/provider.d.ts +10 -2
  49. package/dist/ai/codexAppServer/provider.d.ts.map +1 -1
  50. package/dist/ai/codexAppServer/provider.js +158 -22
  51. package/dist/ai/codexAppServer/provider.js.map +1 -1
  52. package/dist/ai/openCodeProvider.d.ts +106 -0
  53. package/dist/ai/openCodeProvider.d.ts.map +1 -0
  54. package/dist/ai/openCodeProvider.js +617 -0
  55. package/dist/ai/openCodeProvider.js.map +1 -0
  56. package/dist/ai/openCodeServer.d.ts +88 -0
  57. package/dist/ai/openCodeServer.d.ts.map +1 -0
  58. package/dist/ai/openCodeServer.js +350 -0
  59. package/dist/ai/openCodeServer.js.map +1 -0
  60. package/dist/ai/profiles/project-sandbox.sb +26 -0
  61. package/dist/ai/provider.d.ts +54 -1
  62. package/dist/ai/provider.d.ts.map +1 -1
  63. package/dist/ai/provider.js +10 -0
  64. package/dist/ai/provider.js.map +1 -1
  65. package/dist/ai/queuedUserPrompts.d.ts +8 -0
  66. package/dist/ai/queuedUserPrompts.d.ts.map +1 -0
  67. package/dist/ai/queuedUserPrompts.js +19 -0
  68. package/dist/ai/queuedUserPrompts.js.map +1 -0
  69. package/dist/ai/realtimeTranscription.d.ts +39 -0
  70. package/dist/ai/realtimeTranscription.d.ts.map +1 -0
  71. package/dist/ai/realtimeTranscription.js +154 -0
  72. package/dist/ai/realtimeTranscription.js.map +1 -0
  73. package/dist/ai/sandboxMcp.d.ts +7 -0
  74. package/dist/ai/sandboxMcp.d.ts.map +1 -1
  75. package/dist/ai/sandboxMcp.js +4 -0
  76. package/dist/ai/sandboxMcp.js.map +1 -1
  77. package/dist/ai/sandboxMcpStdio.d.ts +1 -1
  78. package/dist/ai/sandboxMcpStdio.js +120 -47
  79. package/dist/ai/sandboxMcpStdio.js.map +1 -1
  80. package/dist/ai/sessionManager.d.ts +20 -1
  81. package/dist/ai/sessionManager.d.ts.map +1 -1
  82. package/dist/ai/sessionManager.js +220 -10
  83. package/dist/ai/sessionManager.js.map +1 -1
  84. package/dist/ai/sessionRegistry.d.ts +6 -0
  85. package/dist/ai/sessionRegistry.d.ts.map +1 -1
  86. package/dist/ai/sessionRegistry.js +13 -0
  87. package/dist/ai/sessionRegistry.js.map +1 -1
  88. package/dist/ai/sessionRegistryLocator.d.ts +14 -0
  89. package/dist/ai/sessionRegistryLocator.d.ts.map +1 -0
  90. package/dist/ai/sessionRegistryLocator.js +44 -0
  91. package/dist/ai/sessionRegistryLocator.js.map +1 -0
  92. package/dist/ai/systemPrompt.d.ts.map +1 -1
  93. package/dist/ai/systemPrompt.js +2 -1
  94. package/dist/ai/systemPrompt.js.map +1 -1
  95. package/dist/ai/voiceStream.d.ts +74 -0
  96. package/dist/ai/voiceStream.d.ts.map +1 -0
  97. package/dist/ai/voiceStream.js +179 -0
  98. package/dist/ai/voiceStream.js.map +1 -0
  99. package/dist/ai/voiceTranscription.d.ts +33 -0
  100. package/dist/ai/voiceTranscription.d.ts.map +1 -0
  101. package/dist/ai/voiceTranscription.js +122 -0
  102. package/dist/ai/voiceTranscription.js.map +1 -0
  103. package/dist/files/fileBrowser.d.ts.map +1 -1
  104. package/dist/files/fileBrowser.js +15 -2
  105. package/dist/files/fileBrowser.js.map +1 -1
  106. package/dist/handlers/legacyBusAdapter.d.ts +1 -1
  107. package/dist/handlers/legacyBusAdapter.d.ts.map +1 -1
  108. package/dist/handlers/legacyBusAdapter.js +7 -1
  109. package/dist/handlers/legacyBusAdapter.js.map +1 -1
  110. package/dist/handlers/messageHandler.d.ts +6 -0
  111. package/dist/handlers/messageHandler.d.ts.map +1 -1
  112. package/dist/handlers/messageHandler.js +119 -8
  113. package/dist/handlers/messageHandler.js.map +1 -1
  114. package/dist/index.js +2 -2
  115. package/dist/index.js.map +1 -1
  116. package/dist/service/ipcClient.js +1 -1
  117. package/dist/service/ipcClient.js.map +1 -1
  118. package/dist/service/run.d.ts.map +1 -1
  119. package/dist/service/run.js +81 -3
  120. package/dist/service/run.js.map +1 -1
  121. package/dist/service/types.js +1 -1
  122. package/package.json +6 -3
@@ -9,8 +9,12 @@ import { CommitSummaryCliService, CommitSummaryCliError } from '../ai/commitSumm
9
9
  import { CommitSummaryStateStore } from '../ai/commitSummaryStore.js';
10
10
  import { SessionManager } from '../ai/sessionManager.js';
11
11
  import { ClaudeCodeProvider } from '../ai/claudeCodeProvider.js';
12
+ import { ClaudeTerminalProvider } from '../ai/claudeTerminal/index.js';
13
+ import { OpenCodeProvider } from '../ai/openCodeProvider.js';
12
14
  import { AttachmentStaging } from '../ai/attachmentStaging.js';
13
15
  import { loadAttachment, removeSessionAttachments } from '../ai/attachmentStore.js';
16
+ import { transcribeAudio, listModels } from '../ai/voiceTranscription.js';
17
+ import { probeAudioSupport } from '../ai/voiceStream.js';
14
18
  import { CodexAppServerProvider } from '../ai/codexAppServer/index.js';
15
19
  import { CodexLoginManager } from '../ai/codexLogin.js';
16
20
  import { getTerminalManager } from '../terminal/terminalManager.js';
@@ -87,7 +91,7 @@ function projectAppServerModel(m) {
87
91
  }
88
92
  export class MessageHandler {
89
93
  repos;
90
- agentVersion = '0.8.8';
94
+ agentVersion = '0.8.10';
91
95
  defaultRepoPath;
92
96
  clientRepos = new Map(); // peerAddress -> repoPath
93
97
  repoLocks = new Map(); // repoPath -> peerAddress holding lock
@@ -124,7 +128,12 @@ export class MessageHandler {
124
128
  this.defaultRepoPath = repos.length > 0 ? repos[0].path : '';
125
129
  this.productionBuild = productionBuild;
126
130
  this.claudeService = options?.sessionManager
127
- ?? new SessionManager([new ClaudeCodeProvider(), new CodexAppServerProvider()]);
131
+ ?? new SessionManager([
132
+ new ClaudeCodeProvider(),
133
+ new ClaudeTerminalProvider(),
134
+ new CodexAppServerProvider(),
135
+ new OpenCodeProvider(),
136
+ ]);
128
137
  this.codexCacheDir = options?.codexCacheDir ?? join(homedir(), '.codex');
129
138
  // Load explicit coding paths only (repos and coding paths are independent)
130
139
  if (codingPaths) {
@@ -234,7 +243,7 @@ export class MessageHandler {
234
243
  try {
235
244
  handle = await spawnAppServer({
236
245
  clientInfo: { name: 'quicksave-agent', title: 'Quicksave Agent', version: '0.0.0' },
237
- capabilities: { experimentalApi: false, optOutNotificationMethods: null },
246
+ capabilities: { experimentalApi: true, optOutNotificationMethods: null },
238
247
  });
239
248
  const res = await handle.rpc.request('model/list', { cursor: null, limit: null, includeHidden: false });
240
249
  return res.data
@@ -525,6 +534,8 @@ export class MessageHandler {
525
534
  return this.handleAgentUpdate(message);
526
535
  case 'agent:restart':
527
536
  return this.handleAgentRestart(message);
537
+ case 'agent:probe':
538
+ return this.handleAgentProbe();
528
539
  case 'systemd:status':
529
540
  return this.handleSystemdStatus(message);
530
541
  case 'systemd:install':
@@ -544,6 +555,10 @@ export class MessageHandler {
544
555
  return this.handleClaudeStart(message, peerAddress);
545
556
  case 'claude:resume':
546
557
  return this.handleClaudeResume(message, peerAddress);
558
+ case 'claude:interrupt':
559
+ return this.handleClaudeInterrupt(message);
560
+ case 'claude:steer-queued':
561
+ return this.handleClaudeSteerQueued(message);
547
562
  case 'claude:cancel':
548
563
  return this.handleClaudeCancel(message);
549
564
  case 'claude:close':
@@ -570,6 +585,8 @@ export class MessageHandler {
570
585
  return this.handleListArchived(message);
571
586
  case 'session:mark-read':
572
587
  return this.handleMarkRead(message);
588
+ case 'session:dismiss-pending-mission':
589
+ return this.handleDismissPendingMission(message);
573
590
  case 'project:list-summaries':
574
591
  return this.handleListProjectSummaries(message);
575
592
  case 'project:list-repos':
@@ -598,14 +615,19 @@ export class MessageHandler {
598
615
  return this.handleAttachmentCancel(message, peerAddress);
599
616
  case 'attachment:fetch':
600
617
  return this.handleAttachmentFetch(message);
618
+ case 'voice:transcribe':
619
+ return this.handleVoiceTranscribe(message);
620
+ case 'voice:list-models':
621
+ return this.handleVoiceListModels(message);
601
622
  default:
602
623
  return this.createErrorResponse(message.id, 'UNKNOWN_MESSAGE_TYPE', `Unknown message type: ${message.type}`);
603
624
  }
604
625
  }
605
- handleHandshake(message, peerAddress) {
626
+ async handleHandshake(message, peerAddress) {
606
627
  // Fire-and-forget: check npm registry + OpenAI models (12h dedup each)
607
628
  this.checkLatestVersion().catch(() => { });
608
629
  this.fetchCodexModels().catch(() => { });
630
+ const availableProviders = await this.claudeService.probeProviders();
609
631
  const response = createMessage('handshake:ack', {
610
632
  success: true,
611
633
  agentVersion: this.agentVersion,
@@ -617,6 +639,8 @@ export class MessageHandler {
617
639
  devBuild: !this.productionBuild || undefined,
618
640
  codexModels: this.codexModelsCache?.models,
619
641
  platform: normalizePlatform(osPlatform()),
642
+ availableProviders: availableProviders.length > 0 ? availableProviders : undefined,
643
+ audio: await probeAudioSupport(),
620
644
  });
621
645
  response.id = message.id;
622
646
  return response;
@@ -1157,6 +1181,40 @@ export class MessageHandler {
1157
1181
  return response;
1158
1182
  }
1159
1183
  }
1184
+ async handleVoiceTranscribe(message) {
1185
+ const { audioBase64, mimeType, config } = message.payload;
1186
+ try {
1187
+ const audio = Buffer.from(audioBase64, 'base64');
1188
+ const text = await transcribeAudio(audio, mimeType, config);
1189
+ const response = createMessage('voice:transcribe:response', { text });
1190
+ response.id = message.id;
1191
+ return response;
1192
+ }
1193
+ catch (error) {
1194
+ const response = createMessage('voice:transcribe:response', {
1195
+ text: '',
1196
+ error: error instanceof Error ? error.message : 'Transcription failed',
1197
+ });
1198
+ response.id = message.id;
1199
+ return response;
1200
+ }
1201
+ }
1202
+ async handleVoiceListModels(message) {
1203
+ try {
1204
+ const models = await listModels(message.payload.config);
1205
+ const response = createMessage('voice:list-models:response', { models });
1206
+ response.id = message.id;
1207
+ return response;
1208
+ }
1209
+ catch (error) {
1210
+ const response = createMessage('voice:list-models:response', {
1211
+ models: [],
1212
+ error: error instanceof Error ? error.message : 'Failed to list models',
1213
+ });
1214
+ response.id = message.id;
1215
+ return response;
1216
+ }
1217
+ }
1160
1218
  handleGetApiKeyStatus(message) {
1161
1219
  const response = createMessage('ai:get-api-key-status:response', {
1162
1220
  configured: hasAnthropicApiKey(),
@@ -1548,6 +1606,10 @@ export class MessageHandler {
1548
1606
  return response;
1549
1607
  }
1550
1608
  }
1609
+ async handleAgentProbe() {
1610
+ const availableProviders = await this.claudeService.probeProviders();
1611
+ return createMessage('agent:probe:response', { availableProviders });
1612
+ }
1551
1613
  // ==========================================================================
1552
1614
  // systemd user-unit (Linux auto-start at login)
1553
1615
  //
@@ -1735,6 +1797,7 @@ export class MessageHandler {
1735
1797
  model,
1736
1798
  reasoningEffort,
1737
1799
  contextWindow,
1800
+ mcpCorrId: this.claudeService.getSessionMcpCorrId(sessionId),
1738
1801
  });
1739
1802
  this.onHistoryUpdated?.(cwd, registry.getEntry(cwd, sessionId), 'upsert');
1740
1803
  const response = createMessage('claude:start:response', { success: true, sessionId });
@@ -1749,7 +1812,7 @@ export class MessageHandler {
1749
1812
  }
1750
1813
  }
1751
1814
  async handleClaudeResume(message, peerAddress) {
1752
- const { sessionId: requestedId, prompt, cwd: payloadCwd, agent, attachmentIds } = message.payload;
1815
+ const { sessionId: requestedId, prompt, cwd: payloadCwd, agent, attachmentIds, interruptCurrentTurn } = message.payload;
1753
1816
  const legacyProvider = message.payload.provider;
1754
1817
  const cwd = payloadCwd || this.getClientRepoPath(peerAddress);
1755
1818
  const resolvedAgent = agent ?? (legacyProvider === 'codex-mcp' ? 'codex' : legacyProvider ? 'claude-code' : undefined);
@@ -1775,6 +1838,7 @@ export class MessageHandler {
1775
1838
  cwd,
1776
1839
  agent: resolvedAgent,
1777
1840
  attachments,
1841
+ interruptCurrentTurn,
1778
1842
  });
1779
1843
  console.log(`[agent:resume] session resumed: ${actualSessionId}`);
1780
1844
  getEventStore().record({
@@ -1794,9 +1858,14 @@ export class MessageHandler {
1794
1858
  agent: actualAgent,
1795
1859
  lastAccessedAt: Date.now(),
1796
1860
  gitBranch,
1861
+ mcpCorrId: this.claudeService.getSessionMcpCorrId(actualSessionId) ?? existing?.mcpCorrId,
1797
1862
  });
1798
1863
  this.onHistoryUpdated?.(cwd, registry.getEntry(cwd, actualSessionId), 'upsert');
1799
- const response = createMessage('claude:resume:response', { success: true, sessionId: actualSessionId });
1864
+ const response = createMessage('claude:resume:response', {
1865
+ success: true,
1866
+ sessionId: actualSessionId,
1867
+ queueState: this.claudeService.buildSessionUpdatePayload(actualSessionId).queueState,
1868
+ });
1800
1869
  response.id = message.id;
1801
1870
  return response;
1802
1871
  }
@@ -1817,6 +1886,20 @@ export class MessageHandler {
1817
1886
  response.id = message.id;
1818
1887
  return response;
1819
1888
  }
1889
+ async handleClaudeInterrupt(message) {
1890
+ const { sessionId } = message.payload;
1891
+ const success = await this.claudeService.interruptSession(sessionId);
1892
+ const response = createMessage('claude:interrupt:response', { success, error: success ? undefined : 'Session not found or already ended' });
1893
+ response.id = message.id;
1894
+ return response;
1895
+ }
1896
+ async handleClaudeSteerQueued(message) {
1897
+ const { sessionId, interruptCurrentTurn } = message.payload;
1898
+ const success = await this.claudeService.steerQueuedMessage(sessionId, { interruptCurrentTurn });
1899
+ const response = createMessage('claude:steer-queued:response', { success, error: success ? undefined : 'No queued message or active turn to steer' });
1900
+ response.id = message.id;
1901
+ return response;
1902
+ }
1820
1903
  handleClaudeClose(message) {
1821
1904
  const { sessionId } = message.payload;
1822
1905
  const success = this.claudeService.closeSession(sessionId);
@@ -1861,8 +1944,15 @@ export class MessageHandler {
1861
1944
  return response;
1862
1945
  }
1863
1946
  handleClaudeUserInputResponse(message) {
1864
- const resolved = this.claudeService.resolveUserInput(message.payload);
1865
- console.log(`[agent:user-input-response] requestId=${message.payload.requestId} action=${message.payload.action} resolved=${resolved}`);
1947
+ const { payload } = message;
1948
+ // On plan approval, update permission level synchronously before resolving
1949
+ // so the CLI sees the correct mode for its first tool call after ExitPlanMode.
1950
+ if (payload.action === 'allow' && payload.permissionMode) {
1951
+ this.claudeService.setPermissionLevel(payload.sessionId, payload.permissionMode)
1952
+ .catch(err => console.error('[plan-approve] setPermissionLevel failed:', err));
1953
+ }
1954
+ const resolved = this.claudeService.resolveUserInput(payload);
1955
+ console.log(`[agent:user-input-response] requestId=${payload.requestId} action=${payload.action} resolved=${resolved}`);
1866
1956
  // No dedicated response type — just acknowledge
1867
1957
  const response = createMessage('claude:user-input-response', { success: resolved });
1868
1958
  response.id = message.id;
@@ -2024,6 +2114,27 @@ export class MessageHandler {
2024
2114
  response.id = message.id;
2025
2115
  return response;
2026
2116
  }
2117
+ handleDismissPendingMission(message) {
2118
+ const { sessionId, cwd, dismissedAt } = message.payload;
2119
+ const stamp = typeof dismissedAt === 'number' ? dismissedAt : Date.now();
2120
+ const existing = getSessionRegistry().getEntry(cwd, sessionId);
2121
+ if (!existing?.pendingMission) {
2122
+ const failed = createMessage('session:dismiss-pending-mission:response', { success: false, error: 'Pending mission not found' });
2123
+ failed.id = message.id;
2124
+ return failed;
2125
+ }
2126
+ const pendingMission = {
2127
+ ...existing.pendingMission,
2128
+ dismissedAt: Math.max(existing.pendingMission.dismissedAt ?? 0, stamp),
2129
+ };
2130
+ const updated = getSessionRegistry().updateEntry(cwd, sessionId, { pendingMission });
2131
+ const entry = updated ?? { ...existing, pendingMission };
2132
+ this.onHistoryUpdated?.(cwd, entry, 'upsert');
2133
+ this.claudeService.emitSessionUpdate(sessionId);
2134
+ const response = createMessage('session:dismiss-pending-mission:response', { success: true, pendingMission });
2135
+ response.id = message.id;
2136
+ return response;
2137
+ }
2027
2138
  handleListProjectSummaries(message) {
2028
2139
  const allEntries = getSessionRegistry().getEntriesForProject();
2029
2140
  // Group by cwd