@base44/superagent-native 0.0.1 → 0.0.2

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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +12 -20
  3. package/lib/commonjs/AgentSettingsPanel.js +32 -15
  4. package/lib/commonjs/AgentSettingsPanel.js.map +1 -1
  5. package/lib/commonjs/AttachmentPickerStatusModal.js +2 -2
  6. package/lib/commonjs/AttachmentPickerStatusModal.js.map +1 -1
  7. package/lib/commonjs/ConversationChat.js +27 -11
  8. package/lib/commonjs/ConversationChat.js.map +1 -1
  9. package/lib/commonjs/ConversationComposer.js +10 -6
  10. package/lib/commonjs/ConversationComposer.js.map +1 -1
  11. package/lib/commonjs/ConversationScreen.js +2 -0
  12. package/lib/commonjs/ConversationScreen.js.map +1 -1
  13. package/lib/commonjs/MarkdownText.js +1 -1
  14. package/lib/commonjs/MarkdownText.js.map +1 -1
  15. package/lib/commonjs/MessageActionBar.js +10 -3
  16. package/lib/commonjs/MessageActionBar.js.map +1 -1
  17. package/lib/commonjs/SuperagentHomeScreen.js +17 -3
  18. package/lib/commonjs/SuperagentHomeScreen.js.map +1 -1
  19. package/lib/commonjs/ToolApprovalCard.js +1 -1
  20. package/lib/commonjs/ToolApprovalCard.js.map +1 -1
  21. package/lib/commonjs/ToolCallSummary.js +5 -1
  22. package/lib/commonjs/ToolCallSummary.js.map +1 -1
  23. package/lib/commonjs/attachmentUpload.js +2 -1
  24. package/lib/commonjs/attachmentUpload.js.map +1 -1
  25. package/lib/commonjs/conversationRuntime.js +37 -2
  26. package/lib/commonjs/conversationRuntime.js.map +1 -1
  27. package/lib/commonjs/fileTreeUtils.js +7 -0
  28. package/lib/commonjs/fileTreeUtils.js.map +1 -1
  29. package/lib/commonjs/screenParts.js +3 -3
  30. package/lib/commonjs/styles.js +43 -43
  31. package/lib/commonjs/useSuperagentConversation.js +117 -34
  32. package/lib/commonjs/useSuperagentConversation.js.map +1 -1
  33. package/lib/commonjs/useSuperagentRuntime.js +79 -24
  34. package/lib/commonjs/useSuperagentRuntime.js.map +1 -1
  35. package/lib/module/AgentSettingsPanel.js +32 -15
  36. package/lib/module/AgentSettingsPanel.js.map +1 -1
  37. package/lib/module/AttachmentPickerStatusModal.js +2 -2
  38. package/lib/module/AttachmentPickerStatusModal.js.map +1 -1
  39. package/lib/module/ConversationChat.js +27 -11
  40. package/lib/module/ConversationChat.js.map +1 -1
  41. package/lib/module/ConversationComposer.js +10 -6
  42. package/lib/module/ConversationComposer.js.map +1 -1
  43. package/lib/module/ConversationScreen.js +2 -0
  44. package/lib/module/ConversationScreen.js.map +1 -1
  45. package/lib/module/MarkdownText.js +1 -1
  46. package/lib/module/MarkdownText.js.map +1 -1
  47. package/lib/module/MessageActionBar.js +10 -3
  48. package/lib/module/MessageActionBar.js.map +1 -1
  49. package/lib/module/SuperagentHomeScreen.js +18 -4
  50. package/lib/module/SuperagentHomeScreen.js.map +1 -1
  51. package/lib/module/ToolApprovalCard.js +1 -1
  52. package/lib/module/ToolApprovalCard.js.map +1 -1
  53. package/lib/module/ToolCallSummary.js +5 -1
  54. package/lib/module/ToolCallSummary.js.map +1 -1
  55. package/lib/module/attachmentUpload.js +2 -1
  56. package/lib/module/attachmentUpload.js.map +1 -1
  57. package/lib/module/conversationRuntime.js +36 -2
  58. package/lib/module/conversationRuntime.js.map +1 -1
  59. package/lib/module/fileTreeUtils.js +6 -0
  60. package/lib/module/fileTreeUtils.js.map +1 -1
  61. package/lib/module/screenParts.js +3 -3
  62. package/lib/module/styles.js +43 -43
  63. package/lib/module/useSuperagentConversation.js +118 -35
  64. package/lib/module/useSuperagentConversation.js.map +1 -1
  65. package/lib/module/useSuperagentRuntime.js +80 -25
  66. package/lib/module/useSuperagentRuntime.js.map +1 -1
  67. package/lib/typescript/commonjs/AgentSettingsPanel.d.ts.map +1 -1
  68. package/lib/typescript/commonjs/ConversationChat.d.ts.map +1 -1
  69. package/lib/typescript/commonjs/ConversationComposer.d.ts.map +1 -1
  70. package/lib/typescript/commonjs/ConversationScreen.d.ts +1 -1
  71. package/lib/typescript/commonjs/ConversationScreen.d.ts.map +1 -1
  72. package/lib/typescript/commonjs/SuperagentHomeScreen.d.ts.map +1 -1
  73. package/lib/typescript/commonjs/conversationRuntime.d.ts +3 -2
  74. package/lib/typescript/commonjs/conversationRuntime.d.ts.map +1 -1
  75. package/lib/typescript/commonjs/fileTreeUtils.d.ts +1 -0
  76. package/lib/typescript/commonjs/fileTreeUtils.d.ts.map +1 -1
  77. package/lib/typescript/commonjs/types.d.ts +1 -0
  78. package/lib/typescript/commonjs/types.d.ts.map +1 -1
  79. package/lib/typescript/commonjs/useSuperagentConversation.d.ts.map +1 -1
  80. package/lib/typescript/commonjs/useSuperagentRuntime.d.ts +3 -1
  81. package/lib/typescript/commonjs/useSuperagentRuntime.d.ts.map +1 -1
  82. package/lib/typescript/module/AgentSettingsPanel.d.ts.map +1 -1
  83. package/lib/typescript/module/ConversationChat.d.ts.map +1 -1
  84. package/lib/typescript/module/ConversationComposer.d.ts.map +1 -1
  85. package/lib/typescript/module/ConversationScreen.d.ts +1 -1
  86. package/lib/typescript/module/ConversationScreen.d.ts.map +1 -1
  87. package/lib/typescript/module/SuperagentHomeScreen.d.ts.map +1 -1
  88. package/lib/typescript/module/conversationRuntime.d.ts +3 -2
  89. package/lib/typescript/module/conversationRuntime.d.ts.map +1 -1
  90. package/lib/typescript/module/fileTreeUtils.d.ts +1 -0
  91. package/lib/typescript/module/fileTreeUtils.d.ts.map +1 -1
  92. package/lib/typescript/module/types.d.ts +1 -0
  93. package/lib/typescript/module/types.d.ts.map +1 -1
  94. package/lib/typescript/module/useSuperagentConversation.d.ts.map +1 -1
  95. package/lib/typescript/module/useSuperagentRuntime.d.ts +3 -1
  96. package/lib/typescript/module/useSuperagentRuntime.d.ts.map +1 -1
  97. package/package.json +13 -11
  98. package/src/AgentSettingsPanel.tsx +28 -9
  99. package/src/AttachmentPickerStatusModal.tsx +2 -2
  100. package/src/ConversationChat.tsx +37 -9
  101. package/src/ConversationComposer.tsx +11 -6
  102. package/src/ConversationScreen.tsx +2 -0
  103. package/src/MarkdownText.tsx +1 -1
  104. package/src/MessageActionBar.tsx +9 -3
  105. package/src/SuperagentHomeScreen.tsx +18 -3
  106. package/src/ToolApprovalCard.tsx +1 -1
  107. package/src/ToolCallSummary.tsx +4 -1
  108. package/src/attachmentUpload.ts +2 -1
  109. package/src/conversationRuntime.ts +48 -4
  110. package/src/fileTreeUtils.ts +13 -0
  111. package/src/screenParts.tsx +3 -3
  112. package/src/styles.ts +43 -43
  113. package/src/types.ts +1 -0
  114. package/src/useSuperagentConversation.ts +116 -31
  115. package/src/useSuperagentRuntime.ts +80 -24
@@ -1,6 +1,7 @@
1
1
  import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
2
+ import { Alert } from 'react-native';
2
3
  import { createSuperagentNativeClient } from './apiClient';
3
- import { DEFAULT_SANDBOX_FILE_PATHS, normalizeFilePaths } from './fileTreeUtils';
4
+ import { DEFAULT_SANDBOX_FILE_PATHS, normalizeFilePaths, sanitizeSandboxFilePath } from './fileTreeUtils';
4
5
  import {
5
6
  createSuperagentSocketClient,
6
7
  type SuperagentSocketLike,
@@ -146,6 +147,10 @@ export function useSuperagentRuntime({
146
147
  }), [config.baseUrl, config.currentUserId, config.getAccessToken, config.getHeaders]);
147
148
  const [agents, setAgents] = useState<SuperagentAgent[]>([]);
148
149
  const [activeAgentId, setActiveAgentId] = useState<string | null>(initialAgentId ?? null);
150
+ // Always-latest active agent id, so a slow load for a previous agent can detect
151
+ // that the user has since switched and skip applying its (now stale) result.
152
+ const activeAgentIdRef = useRef(activeAgentId);
153
+ activeAgentIdRef.current = activeAgentId;
149
154
  const [currentRoute, setCurrentRoute] = useState<SuperagentRoute>(
150
155
  initialAgentId ? {name: 'agent', agentId: initialAgentId} : {name: 'home'},
151
156
  );
@@ -209,13 +214,15 @@ export function useSuperagentRuntime({
209
214
  setIsLoadingConnectors(true);
210
215
  try {
211
216
  const connectors = await superagentService.listConnectors(agentId);
217
+ if (activeAgentIdRef.current !== agentId) return;
212
218
  setAvailableConnectors(connectors.availableConnectors);
213
219
  setConnectedConnectors(connectors.connectedConnectors);
214
220
  } catch {
221
+ if (activeAgentIdRef.current !== agentId) return;
215
222
  setAvailableConnectors([]);
216
223
  setConnectedConnectors([]);
217
224
  } finally {
218
- setIsLoadingConnectors(false);
225
+ if (activeAgentIdRef.current === agentId) setIsLoadingConnectors(false);
219
226
  }
220
227
  }, [superagentService]);
221
228
 
@@ -223,19 +230,23 @@ export function useSuperagentRuntime({
223
230
  setIsLoadingAutomations(true);
224
231
  try {
225
232
  const loadedAutomations = await superagentService.listAutomations(agentId);
233
+ if (activeAgentIdRef.current !== agentId) return;
226
234
  setAutomations(loadedAutomations);
227
235
  } catch {
236
+ if (activeAgentIdRef.current !== agentId) return;
228
237
  setAutomations([]);
229
238
  } finally {
230
- setIsLoadingAutomations(false);
239
+ if (activeAgentIdRef.current === agentId) setIsLoadingAutomations(false);
231
240
  }
232
241
  }, [superagentService]);
233
242
 
234
243
  const loadAutomationCredits = useCallback(async (agentId: string) => {
235
244
  try {
236
245
  const loadedCredits = await superagentService.listAutomationCredits(agentId);
246
+ if (activeAgentIdRef.current !== agentId) return;
237
247
  setAutomationCredits(loadedCredits);
238
248
  } catch {
249
+ if (activeAgentIdRef.current !== agentId) return;
239
250
  setAutomationCredits({});
240
251
  }
241
252
  }, [superagentService]);
@@ -244,16 +255,18 @@ export function useSuperagentRuntime({
244
255
  setIsLoadingFiles(true);
245
256
  try {
246
257
  const loadedFilePaths = await superagentService.listSandboxFiles(agentId);
258
+ if (activeAgentIdRef.current !== agentId) return;
247
259
  const normalizedFilePaths = normalizeFilePaths(loadedFilePaths);
248
260
  setFilePaths(normalizedFilePaths.length > 0 ? normalizedFilePaths : DEFAULT_SANDBOX_FILE_PATHS);
249
261
  setFileLoadError(null);
250
262
  setFileLoadFailed(false);
251
263
  } catch (error) {
264
+ if (activeAgentIdRef.current !== agentId) return;
252
265
  setFilePaths(DEFAULT_SANDBOX_FILE_PATHS);
253
266
  setFileLoadError(getErrorMessage(error));
254
267
  setFileLoadFailed(true);
255
268
  } finally {
256
- setIsLoadingFiles(false);
269
+ if (activeAgentIdRef.current === agentId) setIsLoadingFiles(false);
257
270
  }
258
271
  }, [superagentService]);
259
272
 
@@ -261,11 +274,13 @@ export function useSuperagentRuntime({
261
274
  setIsLoadingAgentSettings(true);
262
275
  try {
263
276
  const loadedSecrets = await superagentService.listSecrets(agentId);
277
+ if (activeAgentIdRef.current !== agentId) return;
264
278
  setSecrets(loadedSecrets);
265
279
  } catch {
280
+ if (activeAgentIdRef.current !== agentId) return;
266
281
  setSecrets([]);
267
282
  } finally {
268
- setIsLoadingAgentSettings(false);
283
+ if (activeAgentIdRef.current === agentId) setIsLoadingAgentSettings(false);
269
284
  }
270
285
  }, [superagentService]);
271
286
 
@@ -273,11 +288,13 @@ export function useSuperagentRuntime({
273
288
  setIsLoadingCollaborators(true);
274
289
  try {
275
290
  const loadedCollaborators = await superagentService.listCollaborators(agentId);
291
+ if (activeAgentIdRef.current !== agentId) return;
276
292
  setCollaborators(loadedCollaborators);
277
293
  } catch {
294
+ if (activeAgentIdRef.current !== agentId) return;
278
295
  setCollaborators([]);
279
296
  } finally {
280
- setIsLoadingCollaborators(false);
297
+ if (activeAgentIdRef.current === agentId) setIsLoadingCollaborators(false);
281
298
  }
282
299
  }, [superagentService]);
283
300
 
@@ -298,6 +315,7 @@ export function useSuperagentRuntime({
298
315
  try {
299
316
  const token = await resolveRuntimeToken(agentId);
300
317
  const status = await superagentService.getChannelStatus(agentId, token);
318
+ if (activeAgentIdRef.current !== agentId) return;
301
319
  setChannelStatus((current) => ({
302
320
  ...status,
303
321
  imessage: {
@@ -310,9 +328,10 @@ export function useSuperagentRuntime({
310
328
  },
311
329
  }));
312
330
  } catch {
331
+ if (activeAgentIdRef.current !== agentId) return;
313
332
  setChannelStatus({});
314
333
  } finally {
315
- setIsLoadingChannels(false);
334
+ if (activeAgentIdRef.current === agentId) setIsLoadingChannels(false);
316
335
  }
317
336
  }, [resolveRuntimeToken, superagentService]);
318
337
 
@@ -324,16 +343,23 @@ export function useSuperagentRuntime({
324
343
  }, [loadAutomationCredits, loadAutomations]);
325
344
 
326
345
  useEffect(() => {
346
+ // Reset per-agent state on every active-agent change (not just when it goes
347
+ // null) so the drawer never shows the previous agent's secrets/connectors/
348
+ // files/collaborators/automations during the new agent's load window — which
349
+ // could otherwise let a destructive action target the wrong agent.
350
+ setAvailableConnectors([]);
351
+ setAutomationCredits({});
352
+ setAutomations([]);
353
+ setChannelStatus({});
354
+ setCollaborators([]);
355
+ setConnectingChannelId(null);
356
+ setConnectedConnectors([]);
357
+ setFilePaths([]);
358
+ setFileLoadError(null);
359
+ setFileLoadFailed(false);
360
+ setSecrets([]);
361
+
327
362
  if (!activeAgentId) {
328
- setAvailableConnectors([]);
329
- setAutomationCredits({});
330
- setAutomations([]);
331
- setChannelStatus({});
332
- setCollaborators([]);
333
- setConnectingChannelId(null);
334
- setConnectedConnectors([]);
335
- setFilePaths([]);
336
- setSecrets([]);
337
363
  return;
338
364
  }
339
365
 
@@ -545,6 +571,9 @@ export function useSuperagentRuntime({
545
571
  await loadAgentSettings(agentId);
546
572
  } catch (error) {
547
573
  showAlert(nativeAdapters, 'Secret save failed', getErrorMessage(error));
574
+ // Rethrow so the form keeps the user's input instead of clearing on a
575
+ // failed save.
576
+ throw error;
548
577
  }
549
578
  }, [loadAgentSettings, nativeAdapters, superagentService]);
550
579
 
@@ -705,12 +734,12 @@ export function useSuperagentRuntime({
705
734
  }, [config.baseUrl, config.webUrl, nativeAdapters]);
706
735
 
707
736
  const onOpenSandboxFile = useCallback(async ({agentId, path}: SuperagentSandboxFileActionInput) => {
708
- return superagentService.readSandboxFile(agentId, path);
737
+ return superagentService.readSandboxFile(agentId, sanitizeSandboxFilePath(path));
709
738
  }, [superagentService]);
710
739
 
711
740
  const onSaveSandboxFile = useCallback(async ({agentId, content, path}: SuperagentSandboxFileSaveInput) => {
712
741
  try {
713
- await superagentService.writeSandboxFile(agentId, path, content);
742
+ await superagentService.writeSandboxFile(agentId, sanitizeSandboxFilePath(path), content);
714
743
  await loadFiles(agentId);
715
744
  } catch (error) {
716
745
  showAlert(nativeAdapters, 'Save failed', getErrorMessage(error));
@@ -725,11 +754,14 @@ export function useSuperagentRuntime({
725
754
  return [];
726
755
  }
727
756
 
757
+ const writtenPaths: string[] = [];
728
758
  for (const file of files) {
729
- await superagentService.writeSandboxFile(agentId, file.name, file.content);
759
+ const safePath = sanitizeSandboxFilePath(file.name) || 'upload';
760
+ await superagentService.writeSandboxFile(agentId, safePath, file.content);
761
+ writtenPaths.push(safePath);
730
762
  }
731
763
  await loadFiles(agentId);
732
- return files.map((file) => ({path: file.name}));
764
+ return writtenPaths.map((path) => ({path}));
733
765
  } catch (error) {
734
766
  if (nativeAdapters.isAttachmentPickerCancel?.(error)) {
735
767
  return [];
@@ -1022,6 +1054,7 @@ export function useSuperagentRuntime({
1022
1054
  }, [loadConnectors, nativeAdapters, superagentService]);
1023
1055
 
1024
1056
  return {
1057
+ activeAgentId,
1025
1058
  agents,
1026
1059
  apiClient,
1027
1060
  availableConnectors,
@@ -1033,6 +1066,10 @@ export function useSuperagentRuntime({
1033
1066
  connectingConnectorId,
1034
1067
  connectedConnectors,
1035
1068
  currentRoute,
1069
+ // Also expose as initialRoute, the prop SuperagentHomeScreen actually consumes,
1070
+ // so spreading the runtime opens on the deep-linked agent (initialAgentId)
1071
+ // instead of defaulting to the home route.
1072
+ initialRoute: currentRoute,
1036
1073
  currentUserAvatarUrl: config.currentUserAvatarUrl,
1037
1074
  currentUserName: config.currentUserName,
1038
1075
  fileLoadError,
@@ -1086,7 +1123,10 @@ export function useSuperagentRuntime({
1086
1123
  onShareAgentLink,
1087
1124
  onShareIMessageCode,
1088
1125
  onShareLineCode,
1089
- onStartLiveVoice,
1126
+ // Only expose Live Voice when the native audio adapter is actually installed;
1127
+ // otherwise the composer would prefer it and fail on tap ("audio callbacks are
1128
+ // not installed") instead of falling back to onStartVoiceInput.
1129
+ onStartLiveVoice: nativeAdapters.liveVoiceAudio?.startAudioCapture ? onStartLiveVoice : undefined,
1090
1130
  onSetupTelegram,
1091
1131
  onToggleAutomation,
1092
1132
  onUpdateAgentModel,
@@ -1153,11 +1193,27 @@ async function confirmAction(
1153
1193
  nativeAdapters: SuperagentNativeRuntimeAdapters,
1154
1194
  input: Parameters<NonNullable<SuperagentNativeRuntimeAdapters['confirm']>>[0],
1155
1195
  ) {
1156
- if (!nativeAdapters.confirm) {
1157
- return true;
1196
+ if (nativeAdapters.confirm) {
1197
+ return nativeAdapters.confirm(input);
1158
1198
  }
1159
1199
 
1160
- return nativeAdapters.confirm(input);
1200
+ // No host confirm adapter — fall back to a native prompt so destructive actions
1201
+ // still require explicit confirmation instead of silently proceeding.
1202
+ return new Promise<boolean>((resolve) => {
1203
+ Alert.alert(
1204
+ input.title,
1205
+ input.message,
1206
+ [
1207
+ { onPress: () => resolve(false), style: 'cancel', text: 'Cancel' },
1208
+ {
1209
+ onPress: () => resolve(true),
1210
+ style: input.destructive ? 'destructive' : 'default',
1211
+ text: input.confirmText ?? 'Confirm',
1212
+ },
1213
+ ],
1214
+ { cancelable: true, onDismiss: () => resolve(false) },
1215
+ );
1216
+ });
1161
1217
  }
1162
1218
 
1163
1219
  function buildWebUrl(baseUrl: string, path: string) {