@base44/superagent-native 0.0.1 → 0.0.3
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/LICENSE +21 -0
- package/README.md +12 -20
- package/lib/commonjs/AgentSettingsPanel.js +155 -62
- package/lib/commonjs/AgentSettingsPanel.js.map +1 -1
- package/lib/commonjs/AgentSphereIcon.js +14 -118
- package/lib/commonjs/AgentSphereIcon.js.map +1 -1
- package/lib/commonjs/AttachmentPickerStatusModal.js +5 -4
- package/lib/commonjs/AttachmentPickerStatusModal.js.map +1 -1
- package/lib/commonjs/ChannelsPanel.js +66 -44
- package/lib/commonjs/ChannelsPanel.js.map +1 -1
- package/lib/commonjs/ConversationChat.js +38 -13
- package/lib/commonjs/ConversationChat.js.map +1 -1
- package/lib/commonjs/ConversationComposer.js +18 -13
- package/lib/commonjs/ConversationComposer.js.map +1 -1
- package/lib/commonjs/ConversationScreen.js +4 -0
- package/lib/commonjs/ConversationScreen.js.map +1 -1
- package/lib/commonjs/EditorDrawer.js +54 -24
- package/lib/commonjs/EditorDrawer.js.map +1 -1
- package/lib/commonjs/FilesPanel.js +56 -20
- package/lib/commonjs/FilesPanel.js.map +1 -1
- package/lib/commonjs/MarkdownText.js +1 -1
- package/lib/commonjs/MarkdownText.js.map +1 -1
- package/lib/commonjs/MessageActionBar.js +10 -3
- package/lib/commonjs/MessageActionBar.js.map +1 -1
- package/lib/commonjs/RenameAgentModal.js +2 -1
- package/lib/commonjs/RenameAgentModal.js.map +1 -1
- package/lib/commonjs/ShareAgentModal.js +11 -10
- package/lib/commonjs/ShareAgentModal.js.map +1 -1
- package/lib/commonjs/ShareAgentModal.styles.js +2 -2
- package/lib/commonjs/ShareAgentModal.styles.js.map +1 -1
- package/lib/commonjs/SuperagentHomeScreen.js +44 -12
- package/lib/commonjs/SuperagentHomeScreen.js.map +1 -1
- package/lib/commonjs/ToolApprovalCard.js +73 -15
- package/lib/commonjs/ToolApprovalCard.js.map +1 -1
- package/lib/commonjs/ToolCallSummary.js +19 -10
- package/lib/commonjs/ToolCallSummary.js.map +1 -1
- package/lib/commonjs/agentSphereAssets.js +327 -0
- package/lib/commonjs/agentSphereAssets.js.map +1 -0
- package/lib/commonjs/agentSphereStyles.js +3 -3
- package/lib/commonjs/agentSphereStyles.js.map +1 -1
- package/lib/commonjs/apiClient.js +7 -0
- package/lib/commonjs/apiClient.js.map +1 -1
- package/lib/commonjs/attachmentUpload.js +2 -1
- package/lib/commonjs/attachmentUpload.js.map +1 -1
- package/lib/commonjs/composerStyles.js +2 -2
- package/lib/commonjs/composerStyles.js.map +1 -1
- package/lib/commonjs/connectorBrandIcons.generated.js +625 -0
- package/lib/commonjs/connectorBrandIcons.generated.js.map +1 -0
- package/lib/commonjs/connectorBrandIcons.js +3 -55
- package/lib/commonjs/connectorBrandIcons.js.map +1 -1
- package/lib/commonjs/connectorCatalog.js +19 -1
- package/lib/commonjs/connectorCatalog.js.map +1 -1
- package/lib/commonjs/conversationParts.js +5 -4
- package/lib/commonjs/conversationParts.js.map +1 -1
- package/lib/commonjs/conversationRuntime.js +152 -9
- package/lib/commonjs/conversationRuntime.js.map +1 -1
- package/lib/commonjs/conversationStyles.js +2 -1
- package/lib/commonjs/conversationStyles.js.map +1 -1
- package/lib/commonjs/editorShellStyles.js +6 -2
- package/lib/commonjs/editorShellStyles.js.map +1 -1
- package/lib/commonjs/fileTreeUtils.js +7 -0
- package/lib/commonjs/fileTreeUtils.js.map +1 -1
- package/lib/commonjs/index.js +7 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/markdownStyles.js +2 -2
- package/lib/commonjs/markdownStyles.js.map +1 -1
- package/lib/commonjs/messageActionStyles.js +2 -2
- package/lib/commonjs/messageActionStyles.js.map +1 -1
- package/lib/commonjs/realtimeClient.js +4 -1
- package/lib/commonjs/realtimeClient.js.map +1 -1
- package/lib/commonjs/renameAgentModalStyles.js +2 -2
- package/lib/commonjs/renameAgentModalStyles.js.map +1 -1
- package/lib/commonjs/screenParts.js +24 -41
- package/lib/commonjs/screenParts.js.map +1 -1
- package/lib/commonjs/styles.js +32 -21
- package/lib/commonjs/styles.js.map +1 -1
- package/lib/commonjs/superagentApiClient.js +63 -18
- package/lib/commonjs/superagentApiClient.js.map +1 -1
- package/lib/commonjs/theme.js +249 -0
- package/lib/commonjs/theme.js.map +1 -0
- package/lib/commonjs/useSuperagentConversation.js +240 -44
- package/lib/commonjs/useSuperagentConversation.js.map +1 -1
- package/lib/commonjs/useSuperagentRuntime.js +245 -105
- package/lib/commonjs/useSuperagentRuntime.js.map +1 -1
- package/lib/module/AgentSettingsPanel.js +157 -64
- package/lib/module/AgentSettingsPanel.js.map +1 -1
- package/lib/module/AgentSphereIcon.js +15 -118
- package/lib/module/AgentSphereIcon.js.map +1 -1
- package/lib/module/AttachmentPickerStatusModal.js +6 -5
- package/lib/module/AttachmentPickerStatusModal.js.map +1 -1
- package/lib/module/ChannelsPanel.js +67 -45
- package/lib/module/ChannelsPanel.js.map +1 -1
- package/lib/module/ConversationChat.js +38 -13
- package/lib/module/ConversationChat.js.map +1 -1
- package/lib/module/ConversationComposer.js +18 -13
- package/lib/module/ConversationComposer.js.map +1 -1
- package/lib/module/ConversationScreen.js +4 -0
- package/lib/module/ConversationScreen.js.map +1 -1
- package/lib/module/EditorDrawer.js +55 -25
- package/lib/module/EditorDrawer.js.map +1 -1
- package/lib/module/FilesPanel.js +56 -20
- package/lib/module/FilesPanel.js.map +1 -1
- package/lib/module/MarkdownText.js +1 -1
- package/lib/module/MarkdownText.js.map +1 -1
- package/lib/module/MessageActionBar.js +10 -3
- package/lib/module/MessageActionBar.js.map +1 -1
- package/lib/module/RenameAgentModal.js +2 -1
- package/lib/module/RenameAgentModal.js.map +1 -1
- package/lib/module/ShareAgentModal.js +11 -10
- package/lib/module/ShareAgentModal.js.map +1 -1
- package/lib/module/ShareAgentModal.styles.js +2 -2
- package/lib/module/ShareAgentModal.styles.js.map +1 -1
- package/lib/module/SuperagentHomeScreen.js +45 -13
- package/lib/module/SuperagentHomeScreen.js.map +1 -1
- package/lib/module/ToolApprovalCard.js +73 -15
- package/lib/module/ToolApprovalCard.js.map +1 -1
- package/lib/module/ToolCallSummary.js +19 -10
- package/lib/module/ToolCallSummary.js.map +1 -1
- package/lib/module/agentSphereAssets.js +323 -0
- package/lib/module/agentSphereAssets.js.map +1 -0
- package/lib/module/agentSphereStyles.js +3 -3
- package/lib/module/agentSphereStyles.js.map +1 -1
- package/lib/module/apiClient.js +7 -0
- package/lib/module/apiClient.js.map +1 -1
- package/lib/module/attachmentUpload.js +2 -1
- package/lib/module/attachmentUpload.js.map +1 -1
- package/lib/module/composerStyles.js +2 -2
- package/lib/module/composerStyles.js.map +1 -1
- package/lib/module/connectorBrandIcons.generated.js +621 -0
- package/lib/module/connectorBrandIcons.generated.js.map +1 -0
- package/lib/module/connectorBrandIcons.js +1 -53
- package/lib/module/connectorBrandIcons.js.map +1 -1
- package/lib/module/connectorCatalog.js +17 -0
- package/lib/module/connectorCatalog.js.map +1 -1
- package/lib/module/conversationParts.js +5 -4
- package/lib/module/conversationParts.js.map +1 -1
- package/lib/module/conversationRuntime.js +149 -9
- package/lib/module/conversationRuntime.js.map +1 -1
- package/lib/module/conversationStyles.js +3 -2
- package/lib/module/conversationStyles.js.map +1 -1
- package/lib/module/editorShellStyles.js +6 -2
- package/lib/module/editorShellStyles.js.map +1 -1
- package/lib/module/fileTreeUtils.js +6 -0
- package/lib/module/fileTreeUtils.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/markdownStyles.js +2 -2
- package/lib/module/markdownStyles.js.map +1 -1
- package/lib/module/messageActionStyles.js +2 -2
- package/lib/module/messageActionStyles.js.map +1 -1
- package/lib/module/realtimeClient.js +4 -1
- package/lib/module/realtimeClient.js.map +1 -1
- package/lib/module/renameAgentModalStyles.js +2 -2
- package/lib/module/renameAgentModalStyles.js.map +1 -1
- package/lib/module/screenParts.js +25 -42
- package/lib/module/screenParts.js.map +1 -1
- package/lib/module/styles.js +32 -21
- package/lib/module/styles.js.map +1 -1
- package/lib/module/superagentApiClient.js +63 -18
- package/lib/module/superagentApiClient.js.map +1 -1
- package/lib/module/theme.js +239 -0
- package/lib/module/theme.js.map +1 -0
- package/lib/module/useSuperagentConversation.js +242 -46
- package/lib/module/useSuperagentConversation.js.map +1 -1
- package/lib/module/useSuperagentRuntime.js +246 -106
- package/lib/module/useSuperagentRuntime.js.map +1 -1
- package/lib/typescript/commonjs/AgentSettingsPanel.d.ts.map +1 -1
- package/lib/typescript/commonjs/AgentSphereIcon.d.ts.map +1 -1
- package/lib/typescript/commonjs/AttachmentPickerStatusModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/ChannelsPanel.d.ts.map +1 -1
- package/lib/typescript/commonjs/ConversationChat.d.ts +1 -1
- package/lib/typescript/commonjs/ConversationChat.d.ts.map +1 -1
- package/lib/typescript/commonjs/ConversationComposer.d.ts.map +1 -1
- package/lib/typescript/commonjs/ConversationMessageList.d.ts +1 -1
- package/lib/typescript/commonjs/ConversationMessageList.d.ts.map +1 -1
- package/lib/typescript/commonjs/ConversationScreen.d.ts +2 -1
- package/lib/typescript/commonjs/ConversationScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/EditorDrawer.d.ts +1 -1
- package/lib/typescript/commonjs/EditorDrawer.d.ts.map +1 -1
- package/lib/typescript/commonjs/FilesPanel.d.ts.map +1 -1
- package/lib/typescript/commonjs/RenameAgentModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/ShareAgentModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/ShareAgentModal.styles.d.ts.map +1 -1
- package/lib/typescript/commonjs/SuperagentHomeScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ToolApprovalCard.d.ts +3 -3
- package/lib/typescript/commonjs/ToolApprovalCard.d.ts.map +1 -1
- package/lib/typescript/commonjs/ToolCallSummary.d.ts +1 -1
- package/lib/typescript/commonjs/ToolCallSummary.d.ts.map +1 -1
- package/lib/typescript/commonjs/agentSphereAssets.d.ts +2 -0
- package/lib/typescript/commonjs/agentSphereAssets.d.ts.map +1 -0
- package/lib/typescript/commonjs/agentSphereStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/apiClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/composerStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/connectorBrandIcons.d.ts.map +1 -1
- package/lib/typescript/commonjs/connectorBrandIcons.generated.d.ts +2 -0
- package/lib/typescript/commonjs/connectorBrandIcons.generated.d.ts.map +1 -0
- package/lib/typescript/commonjs/connectorCatalog.d.ts +2 -0
- package/lib/typescript/commonjs/connectorCatalog.d.ts.map +1 -1
- package/lib/typescript/commonjs/conversationParts.d.ts +1 -1
- package/lib/typescript/commonjs/conversationParts.d.ts.map +1 -1
- package/lib/typescript/commonjs/conversationRuntime.d.ts +9 -3
- package/lib/typescript/commonjs/conversationRuntime.d.ts.map +1 -1
- package/lib/typescript/commonjs/conversationStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/editorShellStyles.d.ts +4 -0
- package/lib/typescript/commonjs/editorShellStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/fileTreeUtils.d.ts +1 -0
- package/lib/typescript/commonjs/fileTreeUtils.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/markdownStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/messageActionStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/realtimeClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/renameAgentModalStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/screenParts.d.ts +1 -1
- package/lib/typescript/commonjs/screenParts.d.ts.map +1 -1
- package/lib/typescript/commonjs/styles.d.ts +20 -11
- package/lib/typescript/commonjs/styles.d.ts.map +1 -1
- package/lib/typescript/commonjs/superagentApiClient.d.ts +2 -1
- package/lib/typescript/commonjs/superagentApiClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme.d.ts +36 -0
- package/lib/typescript/commonjs/theme.d.ts.map +1 -0
- package/lib/typescript/commonjs/types.d.ts +17 -2
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/useSuperagentConversation.d.ts +3 -2
- package/lib/typescript/commonjs/useSuperagentConversation.d.ts.map +1 -1
- package/lib/typescript/commonjs/useSuperagentRuntime.d.ts +5 -2
- package/lib/typescript/commonjs/useSuperagentRuntime.d.ts.map +1 -1
- package/lib/typescript/module/AgentSettingsPanel.d.ts.map +1 -1
- package/lib/typescript/module/AgentSphereIcon.d.ts.map +1 -1
- package/lib/typescript/module/AttachmentPickerStatusModal.d.ts.map +1 -1
- package/lib/typescript/module/ChannelsPanel.d.ts.map +1 -1
- package/lib/typescript/module/ConversationChat.d.ts +1 -1
- package/lib/typescript/module/ConversationChat.d.ts.map +1 -1
- package/lib/typescript/module/ConversationComposer.d.ts.map +1 -1
- package/lib/typescript/module/ConversationMessageList.d.ts +1 -1
- package/lib/typescript/module/ConversationMessageList.d.ts.map +1 -1
- package/lib/typescript/module/ConversationScreen.d.ts +2 -1
- package/lib/typescript/module/ConversationScreen.d.ts.map +1 -1
- package/lib/typescript/module/EditorDrawer.d.ts +1 -1
- package/lib/typescript/module/EditorDrawer.d.ts.map +1 -1
- package/lib/typescript/module/FilesPanel.d.ts.map +1 -1
- package/lib/typescript/module/RenameAgentModal.d.ts.map +1 -1
- package/lib/typescript/module/ShareAgentModal.d.ts.map +1 -1
- package/lib/typescript/module/ShareAgentModal.styles.d.ts.map +1 -1
- package/lib/typescript/module/SuperagentHomeScreen.d.ts.map +1 -1
- package/lib/typescript/module/ToolApprovalCard.d.ts +3 -3
- package/lib/typescript/module/ToolApprovalCard.d.ts.map +1 -1
- package/lib/typescript/module/ToolCallSummary.d.ts +1 -1
- package/lib/typescript/module/ToolCallSummary.d.ts.map +1 -1
- package/lib/typescript/module/agentSphereAssets.d.ts +2 -0
- package/lib/typescript/module/agentSphereAssets.d.ts.map +1 -0
- package/lib/typescript/module/agentSphereStyles.d.ts.map +1 -1
- package/lib/typescript/module/apiClient.d.ts.map +1 -1
- package/lib/typescript/module/composerStyles.d.ts.map +1 -1
- package/lib/typescript/module/connectorBrandIcons.d.ts.map +1 -1
- package/lib/typescript/module/connectorBrandIcons.generated.d.ts +2 -0
- package/lib/typescript/module/connectorBrandIcons.generated.d.ts.map +1 -0
- package/lib/typescript/module/connectorCatalog.d.ts +2 -0
- package/lib/typescript/module/connectorCatalog.d.ts.map +1 -1
- package/lib/typescript/module/conversationParts.d.ts +1 -1
- package/lib/typescript/module/conversationParts.d.ts.map +1 -1
- package/lib/typescript/module/conversationRuntime.d.ts +9 -3
- package/lib/typescript/module/conversationRuntime.d.ts.map +1 -1
- package/lib/typescript/module/conversationStyles.d.ts.map +1 -1
- package/lib/typescript/module/editorShellStyles.d.ts +4 -0
- package/lib/typescript/module/editorShellStyles.d.ts.map +1 -1
- package/lib/typescript/module/fileTreeUtils.d.ts +1 -0
- package/lib/typescript/module/fileTreeUtils.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/markdownStyles.d.ts.map +1 -1
- package/lib/typescript/module/messageActionStyles.d.ts.map +1 -1
- package/lib/typescript/module/realtimeClient.d.ts.map +1 -1
- package/lib/typescript/module/renameAgentModalStyles.d.ts.map +1 -1
- package/lib/typescript/module/screenParts.d.ts +1 -1
- package/lib/typescript/module/screenParts.d.ts.map +1 -1
- package/lib/typescript/module/styles.d.ts +20 -11
- package/lib/typescript/module/styles.d.ts.map +1 -1
- package/lib/typescript/module/superagentApiClient.d.ts +2 -1
- package/lib/typescript/module/superagentApiClient.d.ts.map +1 -1
- package/lib/typescript/module/theme.d.ts +36 -0
- package/lib/typescript/module/theme.d.ts.map +1 -0
- package/lib/typescript/module/types.d.ts +17 -2
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/lib/typescript/module/useSuperagentConversation.d.ts +3 -2
- package/lib/typescript/module/useSuperagentConversation.d.ts.map +1 -1
- package/lib/typescript/module/useSuperagentRuntime.d.ts +5 -2
- package/lib/typescript/module/useSuperagentRuntime.d.ts.map +1 -1
- package/package.json +13 -11
- package/src/AgentSettingsPanel.tsx +146 -58
- package/src/AgentSphereIcon.tsx +11 -62
- package/src/AttachmentPickerStatusModal.tsx +6 -5
- package/src/ChannelsPanel.tsx +59 -39
- package/src/ConversationChat.tsx +49 -12
- package/src/ConversationComposer.tsx +18 -12
- package/src/ConversationMessageList.tsx +1 -1
- package/src/ConversationScreen.tsx +5 -0
- package/src/EditorDrawer.tsx +66 -41
- package/src/FilesPanel.tsx +48 -20
- package/src/MarkdownText.tsx +1 -1
- package/src/MessageActionBar.tsx +9 -3
- package/src/RenameAgentModal.tsx +2 -1
- package/src/ShareAgentModal.styles.ts +2 -1
- package/src/ShareAgentModal.tsx +9 -8
- package/src/SuperagentHomeScreen.tsx +45 -10
- package/src/ToolApprovalCard.tsx +83 -15
- package/src/ToolCallSummary.tsx +22 -13
- package/src/agentSphereAssets.ts +325 -0
- package/src/agentSphereStyles.ts +3 -2
- package/src/apiClient.ts +7 -0
- package/src/attachmentUpload.ts +2 -1
- package/src/composerStyles.ts +2 -1
- package/src/connectorBrandIcons.generated.ts +618 -0
- package/src/connectorBrandIcons.tsx +1 -53
- package/src/connectorCatalog.ts +24 -0
- package/src/conversationParts.tsx +6 -5
- package/src/conversationRuntime.ts +166 -11
- package/src/conversationStyles.ts +2 -1
- package/src/editorShellStyles.ts +6 -1
- package/src/fileTreeUtils.ts +13 -0
- package/src/index.ts +2 -0
- package/src/markdownStyles.ts +2 -1
- package/src/messageActionStyles.ts +2 -1
- package/src/realtimeClient.ts +7 -1
- package/src/renameAgentModalStyles.ts +2 -1
- package/src/screenParts.tsx +17 -29
- package/src/styles.ts +25 -16
- package/src/superagentApiClient.ts +68 -18
- package/src/theme.ts +254 -0
- package/src/types.ts +22 -2
- package/src/useSuperagentConversation.ts +247 -45
- package/src/useSuperagentRuntime.ts +244 -107
|
@@ -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
|
);
|
|
@@ -169,6 +174,11 @@ export function useSuperagentRuntime({
|
|
|
169
174
|
const [isLoading, setIsLoading] = useState(true);
|
|
170
175
|
const [loadError, setLoadError] = useState<string | null>(null);
|
|
171
176
|
const [runtimeAuthToken, setRuntimeAuthToken] = useState<string | null>(null);
|
|
177
|
+
// Caches the resolved runtime token keyed by the agent it belongs to. The
|
|
178
|
+
// runtimeAuthToken state lags an agent switch (it's cleared in a later effect),
|
|
179
|
+
// so resolveRuntimeToken must not trust it as a cache — this ref can never hand
|
|
180
|
+
// back a different agent's token.
|
|
181
|
+
const runtimeTokenRef = useRef<{ agentId: string; token: string } | null>(null);
|
|
172
182
|
const [realtimeClient, setRealtimeClient] = useState<SuperagentRealtimeClient | undefined>();
|
|
173
183
|
const [secrets, setSecrets] = useState<SuperagentSecret[]>([]);
|
|
174
184
|
const connectorFlowRef = useRef<ConnectorFlow | null>(null);
|
|
@@ -209,13 +219,15 @@ export function useSuperagentRuntime({
|
|
|
209
219
|
setIsLoadingConnectors(true);
|
|
210
220
|
try {
|
|
211
221
|
const connectors = await superagentService.listConnectors(agentId);
|
|
222
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
212
223
|
setAvailableConnectors(connectors.availableConnectors);
|
|
213
224
|
setConnectedConnectors(connectors.connectedConnectors);
|
|
214
225
|
} catch {
|
|
226
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
215
227
|
setAvailableConnectors([]);
|
|
216
228
|
setConnectedConnectors([]);
|
|
217
229
|
} finally {
|
|
218
|
-
setIsLoadingConnectors(false);
|
|
230
|
+
if (activeAgentIdRef.current === agentId) setIsLoadingConnectors(false);
|
|
219
231
|
}
|
|
220
232
|
}, [superagentService]);
|
|
221
233
|
|
|
@@ -223,19 +235,23 @@ export function useSuperagentRuntime({
|
|
|
223
235
|
setIsLoadingAutomations(true);
|
|
224
236
|
try {
|
|
225
237
|
const loadedAutomations = await superagentService.listAutomations(agentId);
|
|
238
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
226
239
|
setAutomations(loadedAutomations);
|
|
227
240
|
} catch {
|
|
241
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
228
242
|
setAutomations([]);
|
|
229
243
|
} finally {
|
|
230
|
-
setIsLoadingAutomations(false);
|
|
244
|
+
if (activeAgentIdRef.current === agentId) setIsLoadingAutomations(false);
|
|
231
245
|
}
|
|
232
246
|
}, [superagentService]);
|
|
233
247
|
|
|
234
248
|
const loadAutomationCredits = useCallback(async (agentId: string) => {
|
|
235
249
|
try {
|
|
236
250
|
const loadedCredits = await superagentService.listAutomationCredits(agentId);
|
|
251
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
237
252
|
setAutomationCredits(loadedCredits);
|
|
238
253
|
} catch {
|
|
254
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
239
255
|
setAutomationCredits({});
|
|
240
256
|
}
|
|
241
257
|
}, [superagentService]);
|
|
@@ -244,16 +260,18 @@ export function useSuperagentRuntime({
|
|
|
244
260
|
setIsLoadingFiles(true);
|
|
245
261
|
try {
|
|
246
262
|
const loadedFilePaths = await superagentService.listSandboxFiles(agentId);
|
|
263
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
247
264
|
const normalizedFilePaths = normalizeFilePaths(loadedFilePaths);
|
|
248
265
|
setFilePaths(normalizedFilePaths.length > 0 ? normalizedFilePaths : DEFAULT_SANDBOX_FILE_PATHS);
|
|
249
266
|
setFileLoadError(null);
|
|
250
267
|
setFileLoadFailed(false);
|
|
251
268
|
} catch (error) {
|
|
269
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
252
270
|
setFilePaths(DEFAULT_SANDBOX_FILE_PATHS);
|
|
253
271
|
setFileLoadError(getErrorMessage(error));
|
|
254
272
|
setFileLoadFailed(true);
|
|
255
273
|
} finally {
|
|
256
|
-
setIsLoadingFiles(false);
|
|
274
|
+
if (activeAgentIdRef.current === agentId) setIsLoadingFiles(false);
|
|
257
275
|
}
|
|
258
276
|
}, [superagentService]);
|
|
259
277
|
|
|
@@ -261,11 +279,13 @@ export function useSuperagentRuntime({
|
|
|
261
279
|
setIsLoadingAgentSettings(true);
|
|
262
280
|
try {
|
|
263
281
|
const loadedSecrets = await superagentService.listSecrets(agentId);
|
|
282
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
264
283
|
setSecrets(loadedSecrets);
|
|
265
284
|
} catch {
|
|
285
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
266
286
|
setSecrets([]);
|
|
267
287
|
} finally {
|
|
268
|
-
setIsLoadingAgentSettings(false);
|
|
288
|
+
if (activeAgentIdRef.current === agentId) setIsLoadingAgentSettings(false);
|
|
269
289
|
}
|
|
270
290
|
}, [superagentService]);
|
|
271
291
|
|
|
@@ -273,31 +293,43 @@ export function useSuperagentRuntime({
|
|
|
273
293
|
setIsLoadingCollaborators(true);
|
|
274
294
|
try {
|
|
275
295
|
const loadedCollaborators = await superagentService.listCollaborators(agentId);
|
|
296
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
276
297
|
setCollaborators(loadedCollaborators);
|
|
277
298
|
} catch {
|
|
299
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
278
300
|
setCollaborators([]);
|
|
279
301
|
} finally {
|
|
280
|
-
setIsLoadingCollaborators(false);
|
|
302
|
+
if (activeAgentIdRef.current === agentId) setIsLoadingCollaborators(false);
|
|
281
303
|
}
|
|
282
304
|
}, [superagentService]);
|
|
283
305
|
|
|
284
306
|
const resolveRuntimeToken = useCallback(async (agentId: string) => {
|
|
285
|
-
|
|
286
|
-
|
|
307
|
+
// Use the agent-keyed ref, not the runtimeAuthToken state: the state still
|
|
308
|
+
// holds the previous agent's token during a switch (it's cleared in a later
|
|
309
|
+
// effect), so trusting it could return the wrong agent's token here.
|
|
310
|
+
const cached = runtimeTokenRef.current;
|
|
311
|
+
if (cached && cached.agentId === agentId) {
|
|
312
|
+
return cached.token;
|
|
287
313
|
}
|
|
288
314
|
|
|
289
315
|
const token = await superagentService.getRuntimeAuthToken(agentId);
|
|
290
|
-
|
|
316
|
+
runtimeTokenRef.current = { agentId, token };
|
|
317
|
+
// Compare against the latest active agent (ref), not the closure-captured
|
|
318
|
+
// activeAgentId: the user may have switched agents while the fetch was in
|
|
319
|
+
// flight, and writing a stale agent's token into shared state would point
|
|
320
|
+
// realtime/channel calls at the wrong agent.
|
|
321
|
+
if (agentId === activeAgentIdRef.current) {
|
|
291
322
|
setRuntimeAuthToken(token);
|
|
292
323
|
}
|
|
293
324
|
return token;
|
|
294
|
-
}, [
|
|
325
|
+
}, [superagentService]);
|
|
295
326
|
|
|
296
327
|
const loadChannels = useCallback(async (agentId: string) => {
|
|
297
328
|
setIsLoadingChannels(true);
|
|
298
329
|
try {
|
|
299
330
|
const token = await resolveRuntimeToken(agentId);
|
|
300
331
|
const status = await superagentService.getChannelStatus(agentId, token);
|
|
332
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
301
333
|
setChannelStatus((current) => ({
|
|
302
334
|
...status,
|
|
303
335
|
imessage: {
|
|
@@ -310,9 +342,10 @@ export function useSuperagentRuntime({
|
|
|
310
342
|
},
|
|
311
343
|
}));
|
|
312
344
|
} catch {
|
|
345
|
+
if (activeAgentIdRef.current !== agentId) return;
|
|
313
346
|
setChannelStatus({});
|
|
314
347
|
} finally {
|
|
315
|
-
setIsLoadingChannels(false);
|
|
348
|
+
if (activeAgentIdRef.current === agentId) setIsLoadingChannels(false);
|
|
316
349
|
}
|
|
317
350
|
}, [resolveRuntimeToken, superagentService]);
|
|
318
351
|
|
|
@@ -324,16 +357,24 @@ export function useSuperagentRuntime({
|
|
|
324
357
|
}, [loadAutomationCredits, loadAutomations]);
|
|
325
358
|
|
|
326
359
|
useEffect(() => {
|
|
360
|
+
// Reset per-agent state on every active-agent change (not just when it goes
|
|
361
|
+
// null) so the drawer never shows the previous agent's secrets/connectors/
|
|
362
|
+
// files/collaborators/automations during the new agent's load window — which
|
|
363
|
+
// could otherwise let a destructive action target the wrong agent.
|
|
364
|
+
setAvailableConnectors([]);
|
|
365
|
+
setAutomationCredits({});
|
|
366
|
+
setAutomations([]);
|
|
367
|
+
setChannelStatus({});
|
|
368
|
+
setCollaborators([]);
|
|
369
|
+
setConnectingChannelId(null);
|
|
370
|
+
setConnectingConnectorId(null);
|
|
371
|
+
setConnectedConnectors([]);
|
|
372
|
+
setFilePaths([]);
|
|
373
|
+
setFileLoadError(null);
|
|
374
|
+
setFileLoadFailed(false);
|
|
375
|
+
setSecrets([]);
|
|
376
|
+
|
|
327
377
|
if (!activeAgentId) {
|
|
328
|
-
setAvailableConnectors([]);
|
|
329
|
-
setAutomationCredits({});
|
|
330
|
-
setAutomations([]);
|
|
331
|
-
setChannelStatus({});
|
|
332
|
-
setCollaborators([]);
|
|
333
|
-
setConnectingChannelId(null);
|
|
334
|
-
setConnectedConnectors([]);
|
|
335
|
-
setFilePaths([]);
|
|
336
|
-
setSecrets([]);
|
|
337
378
|
return;
|
|
338
379
|
}
|
|
339
380
|
|
|
@@ -380,25 +421,16 @@ export function useSuperagentRuntime({
|
|
|
380
421
|
return;
|
|
381
422
|
}
|
|
382
423
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
424
|
+
// The callback event carries no connection/connector identifier, so it can't
|
|
425
|
+
// be reliably attributed to this flow — a late callback from a superseded
|
|
426
|
+
// connect could otherwise mark the wrong flow. Don't mutate flow state here;
|
|
427
|
+
// waitForConnectorAuthorization polls the authoritative per-connection status
|
|
428
|
+
// (it detects ACTIVE/FAILED on its own). Just refresh the connector list so
|
|
429
|
+
// the UI reflects the latest state.
|
|
430
|
+
if (event.status === 'success' || event.status === 'error') {
|
|
387
431
|
await loadConnectors(flow.agentId);
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
if (event.status === 'error') {
|
|
392
|
-
flow.cancelled = true;
|
|
393
|
-
connectorFlowRef.current = null;
|
|
394
|
-
setConnectingConnectorId(null);
|
|
395
|
-
await loadConnectors(flow.agentId);
|
|
396
|
-
showAlert(nativeAdapters, 'Connector failed', 'OAuth authorization did not complete. Please try connecting again.');
|
|
397
|
-
return;
|
|
398
432
|
}
|
|
399
|
-
|
|
400
|
-
await loadConnectors(flow.agentId);
|
|
401
|
-
}, [loadConnectors, nativeAdapters]);
|
|
433
|
+
}, [loadConnectors]);
|
|
402
434
|
|
|
403
435
|
useEffect(() => {
|
|
404
436
|
return nativeAdapters.subscribeToExternalAuthCallbacks?.(completePendingConnectorFromCallback);
|
|
@@ -536,6 +568,9 @@ export function useSuperagentRuntime({
|
|
|
536
568
|
)));
|
|
537
569
|
} catch (error) {
|
|
538
570
|
showAlert(nativeAdapters, 'Permissions update failed', getErrorMessage(error));
|
|
571
|
+
// Rethrow so optimistic callers (the permission toggle) can revert; the
|
|
572
|
+
// guard-config caller wraps this in try/catch since the alert already fired.
|
|
573
|
+
throw error;
|
|
539
574
|
}
|
|
540
575
|
}, [nativeAdapters, superagentService]);
|
|
541
576
|
|
|
@@ -545,6 +580,9 @@ export function useSuperagentRuntime({
|
|
|
545
580
|
await loadAgentSettings(agentId);
|
|
546
581
|
} catch (error) {
|
|
547
582
|
showAlert(nativeAdapters, 'Secret save failed', getErrorMessage(error));
|
|
583
|
+
// Rethrow so the form keeps the user's input instead of clearing on a
|
|
584
|
+
// failed save.
|
|
585
|
+
throw error;
|
|
548
586
|
}
|
|
549
587
|
}, [loadAgentSettings, nativeAdapters, superagentService]);
|
|
550
588
|
|
|
@@ -605,7 +643,10 @@ export function useSuperagentRuntime({
|
|
|
605
643
|
}, [config.baseUrl, config.webUrl, nativeAdapters]);
|
|
606
644
|
|
|
607
645
|
const onCloneAgent = useCallback(({agentId}: SuperagentAgentActionInput) => {
|
|
608
|
-
|
|
646
|
+
// Use the Superagent clone route — /remix-app is an app route that the web
|
|
647
|
+
// builder redirects back to /superagent/:id for user_agent apps (reopening the
|
|
648
|
+
// original instead of cloning). /clone-superagent/:id is the agent clone flow.
|
|
649
|
+
nativeAdapters.openWebUrl?.(buildWebUrl(config.webUrl ?? config.baseUrl, `/clone-superagent/${encodeURIComponent(agentId)}`));
|
|
609
650
|
}, [config.baseUrl, config.webUrl, nativeAdapters]);
|
|
610
651
|
|
|
611
652
|
const onDeleteAgent = useCallback(async ({agentId}: SuperagentAgentActionInput) => {
|
|
@@ -705,12 +746,12 @@ export function useSuperagentRuntime({
|
|
|
705
746
|
}, [config.baseUrl, config.webUrl, nativeAdapters]);
|
|
706
747
|
|
|
707
748
|
const onOpenSandboxFile = useCallback(async ({agentId, path}: SuperagentSandboxFileActionInput) => {
|
|
708
|
-
return superagentService.readSandboxFile(agentId, path);
|
|
749
|
+
return superagentService.readSandboxFile(agentId, sanitizeSandboxFilePath(path));
|
|
709
750
|
}, [superagentService]);
|
|
710
751
|
|
|
711
752
|
const onSaveSandboxFile = useCallback(async ({agentId, content, path}: SuperagentSandboxFileSaveInput) => {
|
|
712
753
|
try {
|
|
713
|
-
await superagentService.writeSandboxFile(agentId, path, content);
|
|
754
|
+
await superagentService.writeSandboxFile(agentId, sanitizeSandboxFilePath(path), content);
|
|
714
755
|
await loadFiles(agentId);
|
|
715
756
|
} catch (error) {
|
|
716
757
|
showAlert(nativeAdapters, 'Save failed', getErrorMessage(error));
|
|
@@ -725,11 +766,17 @@ export function useSuperagentRuntime({
|
|
|
725
766
|
return [];
|
|
726
767
|
}
|
|
727
768
|
|
|
769
|
+
const writtenPaths: string[] = [];
|
|
728
770
|
for (const file of files) {
|
|
729
|
-
|
|
771
|
+
const safeName = sanitizeSandboxFilePath(file.name) || 'upload';
|
|
772
|
+
// Stage uploads under a dedicated folder so a picked file named like a
|
|
773
|
+
// generated-app file (package.json, README.md, ...) can't overwrite it.
|
|
774
|
+
const safePath = `incoming_files/${safeName}`;
|
|
775
|
+
await superagentService.writeSandboxFile(agentId, safePath, file.content);
|
|
776
|
+
writtenPaths.push(safePath);
|
|
730
777
|
}
|
|
731
778
|
await loadFiles(agentId);
|
|
732
|
-
return
|
|
779
|
+
return writtenPaths.map((path) => ({path}));
|
|
733
780
|
} catch (error) {
|
|
734
781
|
if (nativeAdapters.isAttachmentPickerCancel?.(error)) {
|
|
735
782
|
return [];
|
|
@@ -760,19 +807,31 @@ export function useSuperagentRuntime({
|
|
|
760
807
|
setConnectingChannelId('whatsapp');
|
|
761
808
|
try {
|
|
762
809
|
const token = await resolveRuntimeToken(agentId);
|
|
810
|
+
// Editor gate: the connect redirect only authenticates the app-user token and
|
|
811
|
+
// does not re-check live editor access, so a downgraded viewer could otherwise
|
|
812
|
+
// open it. /whatsapp/status enforces the two-layer editor check and throws
|
|
813
|
+
// (403) for viewers — require it to pass before opening the setup page.
|
|
814
|
+
await superagentService.getWhatsAppStatus(agentId, token);
|
|
763
815
|
const connectUrl = superagentService.getWhatsAppConnectUrl(agentId, token);
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
816
|
+
if (activeAgentIdRef.current === agentId) {
|
|
817
|
+
setChannelStatus((current) => ({
|
|
818
|
+
...current,
|
|
819
|
+
whatsapp: {
|
|
820
|
+
...current.whatsapp,
|
|
821
|
+
connectUrl,
|
|
822
|
+
},
|
|
823
|
+
}));
|
|
824
|
+
}
|
|
825
|
+
if (!nativeAdapters.openUrl) {
|
|
826
|
+
// Without a URL opener the setup page never launches; surface an error
|
|
827
|
+
// instead of completing silently (mirrors the connector OAuth flow).
|
|
828
|
+
throw new Error('This app cannot open the WhatsApp setup page. Connect WhatsApp from the web app.');
|
|
829
|
+
}
|
|
830
|
+
await nativeAdapters.openUrl(connectUrl);
|
|
772
831
|
} catch (error) {
|
|
773
832
|
showAlert(nativeAdapters, 'WhatsApp setup failed', getErrorMessage(error));
|
|
774
833
|
} finally {
|
|
775
|
-
setConnectingChannelId(null);
|
|
834
|
+
if (activeAgentIdRef.current === agentId) setConnectingChannelId(null);
|
|
776
835
|
}
|
|
777
836
|
}, [nativeAdapters, resolveRuntimeToken, superagentService]);
|
|
778
837
|
|
|
@@ -781,12 +840,14 @@ export function useSuperagentRuntime({
|
|
|
781
840
|
try {
|
|
782
841
|
const runtimeToken = await resolveRuntimeToken(agentId);
|
|
783
842
|
const telegram = await superagentService.setupTelegram(agentId, runtimeToken, token);
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
843
|
+
if (activeAgentIdRef.current === agentId) {
|
|
844
|
+
setChannelStatus((current) => ({
|
|
845
|
+
...current,
|
|
846
|
+
telegram,
|
|
847
|
+
}));
|
|
848
|
+
}
|
|
788
849
|
} finally {
|
|
789
|
-
setConnectingChannelId(null);
|
|
850
|
+
if (activeAgentIdRef.current === agentId) setConnectingChannelId(null);
|
|
790
851
|
}
|
|
791
852
|
}, [resolveRuntimeToken, superagentService]);
|
|
792
853
|
|
|
@@ -805,14 +866,16 @@ export function useSuperagentRuntime({
|
|
|
805
866
|
try {
|
|
806
867
|
const token = await resolveRuntimeToken(agentId);
|
|
807
868
|
await superagentService.disconnectTelegram(agentId, token);
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
869
|
+
if (activeAgentIdRef.current === agentId) {
|
|
870
|
+
setChannelStatus((current) => ({
|
|
871
|
+
...current,
|
|
872
|
+
telegram: {connected: false},
|
|
873
|
+
}));
|
|
874
|
+
}
|
|
812
875
|
} catch (error) {
|
|
813
876
|
showAlert(nativeAdapters, 'Telegram disconnect failed', getErrorMessage(error));
|
|
814
877
|
} finally {
|
|
815
|
-
setConnectingChannelId(null);
|
|
878
|
+
if (activeAgentIdRef.current === agentId) setConnectingChannelId(null);
|
|
816
879
|
}
|
|
817
880
|
}, [nativeAdapters, resolveRuntimeToken, superagentService]);
|
|
818
881
|
|
|
@@ -821,18 +884,20 @@ export function useSuperagentRuntime({
|
|
|
821
884
|
try {
|
|
822
885
|
const token = await resolveRuntimeToken(agentId);
|
|
823
886
|
const activation = await superagentService.generateLineCode(agentId, token);
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
887
|
+
if (activeAgentIdRef.current === agentId) {
|
|
888
|
+
setChannelStatus((current) => ({
|
|
889
|
+
...current,
|
|
890
|
+
line: {
|
|
891
|
+
...current.line,
|
|
892
|
+
activation,
|
|
893
|
+
connected: false,
|
|
894
|
+
},
|
|
895
|
+
}));
|
|
896
|
+
}
|
|
832
897
|
} catch (error) {
|
|
833
898
|
showAlert(nativeAdapters, 'LINE setup failed', getErrorMessage(error));
|
|
834
899
|
} finally {
|
|
835
|
-
setConnectingChannelId(null);
|
|
900
|
+
if (activeAgentIdRef.current === agentId) setConnectingChannelId(null);
|
|
836
901
|
}
|
|
837
902
|
}, [nativeAdapters, resolveRuntimeToken, superagentService]);
|
|
838
903
|
|
|
@@ -841,20 +906,22 @@ export function useSuperagentRuntime({
|
|
|
841
906
|
try {
|
|
842
907
|
const token = await resolveRuntimeToken(agentId);
|
|
843
908
|
const activation = await superagentService.generateIMessageCode(agentId, token);
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
909
|
+
if (activeAgentIdRef.current === agentId) {
|
|
910
|
+
setChannelStatus((current) => ({
|
|
911
|
+
...current,
|
|
912
|
+
imessage: {
|
|
913
|
+
...current.imessage,
|
|
914
|
+
activation,
|
|
915
|
+
connected: current.imessage?.connected ?? false,
|
|
916
|
+
},
|
|
917
|
+
}));
|
|
918
|
+
}
|
|
852
919
|
return activation;
|
|
853
920
|
} catch (error) {
|
|
854
921
|
showAlert(nativeAdapters, 'iMessage setup failed', getErrorMessage(error));
|
|
855
922
|
throw error;
|
|
856
923
|
} finally {
|
|
857
|
-
setConnectingChannelId(null);
|
|
924
|
+
if (activeAgentIdRef.current === agentId) setConnectingChannelId(null);
|
|
858
925
|
}
|
|
859
926
|
}, [nativeAdapters, resolveRuntimeToken, superagentService]);
|
|
860
927
|
|
|
@@ -873,20 +940,25 @@ export function useSuperagentRuntime({
|
|
|
873
940
|
try {
|
|
874
941
|
const token = await resolveRuntimeToken(agentId);
|
|
875
942
|
const imessage = await superagentService.disconnectIMessage(agentId, token);
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
943
|
+
if (activeAgentIdRef.current === agentId) {
|
|
944
|
+
setChannelStatus((current) => ({
|
|
945
|
+
...current,
|
|
946
|
+
imessage,
|
|
947
|
+
}));
|
|
948
|
+
}
|
|
880
949
|
} catch (error) {
|
|
881
950
|
showAlert(nativeAdapters, 'iMessage disconnect failed', getErrorMessage(error));
|
|
882
951
|
} finally {
|
|
883
|
-
setConnectingChannelId(null);
|
|
952
|
+
if (activeAgentIdRef.current === agentId) setConnectingChannelId(null);
|
|
884
953
|
}
|
|
885
954
|
}, [nativeAdapters, resolveRuntimeToken, superagentService]);
|
|
886
955
|
|
|
887
956
|
const onOpenIMessage = useCallback(async ({code, phoneNumber}: SuperagentIMessageCodeShareInput) => {
|
|
888
957
|
try {
|
|
889
|
-
|
|
958
|
+
if (!nativeAdapters.openUrl) {
|
|
959
|
+
throw new Error('This app cannot open Messages. Use the web app to share the iMessage code.');
|
|
960
|
+
}
|
|
961
|
+
await nativeAdapters.openUrl(buildIMessageUrl(phoneNumber, code));
|
|
890
962
|
} catch (error) {
|
|
891
963
|
showAlert(nativeAdapters, 'iMessage link unavailable', getErrorMessage(error));
|
|
892
964
|
}
|
|
@@ -901,7 +973,11 @@ export function useSuperagentRuntime({
|
|
|
901
973
|
}, [nativeAdapters]);
|
|
902
974
|
|
|
903
975
|
const onShareLineCode = useCallback(async ({addFriendUrl, code}: SuperagentLineCodeShareInput) => {
|
|
904
|
-
|
|
976
|
+
if (!nativeAdapters.share) {
|
|
977
|
+
showAlert(nativeAdapters, 'Sharing unavailable', 'This app cannot share the activation code. Copy it manually instead.');
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
await nativeAdapters.share({
|
|
905
981
|
message: `LINE activation code: ${code}\n${addFriendUrl}`,
|
|
906
982
|
title: 'LINE activation code',
|
|
907
983
|
url: addFriendUrl,
|
|
@@ -909,7 +985,11 @@ export function useSuperagentRuntime({
|
|
|
909
985
|
}, [nativeAdapters]);
|
|
910
986
|
|
|
911
987
|
const onShareIMessageCode = useCallback(async ({code, phoneNumber}: SuperagentIMessageCodeShareInput) => {
|
|
912
|
-
|
|
988
|
+
if (!nativeAdapters.share) {
|
|
989
|
+
showAlert(nativeAdapters, 'Sharing unavailable', 'This app cannot share the activation code. Copy it manually instead.');
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
await nativeAdapters.share({
|
|
913
993
|
message: `Text ${code} to ${phoneNumber} to connect this Superagent on iMessage.`,
|
|
914
994
|
title: 'iMessage activation code',
|
|
915
995
|
url: buildIMessageUrl(phoneNumber, code),
|
|
@@ -944,26 +1024,38 @@ export function useSuperagentRuntime({
|
|
|
944
1024
|
connectorFlowRef.current = null;
|
|
945
1025
|
setConnectingConnectorId(null);
|
|
946
1026
|
await loadConnectors(agentId);
|
|
947
|
-
|
|
1027
|
+
// Return the connection_id (string) so the connector tool-approval can
|
|
1028
|
+
// submit it; fall back to `true` when the backend omits it.
|
|
1029
|
+
return connection.connection_id ?? true;
|
|
948
1030
|
}
|
|
949
1031
|
|
|
950
1032
|
if (!connection.redirect_url || !connection.connection_id) {
|
|
951
1033
|
throw new Error('The backend did not return an authorization URL for this connector.');
|
|
952
1034
|
}
|
|
953
1035
|
|
|
954
|
-
|
|
955
|
-
|
|
1036
|
+
if (!nativeAdapters.openUrl) {
|
|
1037
|
+
// Without a URL opener the browser never launches, so polling would just
|
|
1038
|
+
// time out after ~2 minutes. Fail immediately with an actionable error.
|
|
1039
|
+
throw new Error('This app cannot open the authorization page. Connect this integration from the web app.');
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
await nativeAdapters.openUrl(connection.redirect_url);
|
|
1043
|
+
const connected = await waitForConnectorAuthorization(superagentService, agentId, connectorId, connection.connection_id, flow);
|
|
956
1044
|
|
|
957
|
-
if
|
|
1045
|
+
// Only clear shared state if this flow is still the active one — a newer
|
|
1046
|
+
// connect may have superseded it (and owns connectorFlowRef now).
|
|
1047
|
+
if (connectorFlowRef.current === flow) {
|
|
958
1048
|
connectorFlowRef.current = null;
|
|
959
1049
|
setConnectingConnectorId(null);
|
|
1050
|
+
}
|
|
1051
|
+
if (connected) {
|
|
960
1052
|
await loadConnectors(agentId);
|
|
961
|
-
return true;
|
|
962
1053
|
}
|
|
963
|
-
|
|
964
|
-
|
|
1054
|
+
// On success return the connection_id so the connector tool-approval can
|
|
1055
|
+
// submit it for backend verification; `false` on failure.
|
|
1056
|
+
return connected ? connection.connection_id : false;
|
|
965
1057
|
} catch (error) {
|
|
966
|
-
if (
|
|
1058
|
+
if (connectorFlowRef.current === flow) {
|
|
967
1059
|
connectorFlowRef.current = null;
|
|
968
1060
|
setConnectingConnectorId(null);
|
|
969
1061
|
showAlert(nativeAdapters, 'Connector failed', getErrorMessage(error));
|
|
@@ -1022,6 +1114,7 @@ export function useSuperagentRuntime({
|
|
|
1022
1114
|
}, [loadConnectors, nativeAdapters, superagentService]);
|
|
1023
1115
|
|
|
1024
1116
|
return {
|
|
1117
|
+
activeAgentId,
|
|
1025
1118
|
agents,
|
|
1026
1119
|
apiClient,
|
|
1027
1120
|
availableConnectors,
|
|
@@ -1033,7 +1126,12 @@ export function useSuperagentRuntime({
|
|
|
1033
1126
|
connectingConnectorId,
|
|
1034
1127
|
connectedConnectors,
|
|
1035
1128
|
currentRoute,
|
|
1129
|
+
// Also expose as initialRoute, the prop SuperagentHomeScreen actually consumes,
|
|
1130
|
+
// so spreading the runtime opens on the deep-linked agent (initialAgentId)
|
|
1131
|
+
// instead of defaulting to the home route.
|
|
1132
|
+
initialRoute: currentRoute,
|
|
1036
1133
|
currentUserAvatarUrl: config.currentUserAvatarUrl,
|
|
1134
|
+
currentUserId: config.currentUserId,
|
|
1037
1135
|
currentUserName: config.currentUserName,
|
|
1038
1136
|
fileLoadError,
|
|
1039
1137
|
fileLoadFailed,
|
|
@@ -1086,7 +1184,10 @@ export function useSuperagentRuntime({
|
|
|
1086
1184
|
onShareAgentLink,
|
|
1087
1185
|
onShareIMessageCode,
|
|
1088
1186
|
onShareLineCode,
|
|
1089
|
-
|
|
1187
|
+
// Only expose Live Voice when the native audio adapter is actually installed;
|
|
1188
|
+
// otherwise the composer would prefer it and fail on tap ("audio callbacks are
|
|
1189
|
+
// not installed") instead of falling back to onStartVoiceInput.
|
|
1190
|
+
onStartLiveVoice: nativeAdapters.liveVoiceAudio?.startAudioCapture ? onStartLiveVoice : undefined,
|
|
1090
1191
|
onSetupTelegram,
|
|
1091
1192
|
onToggleAutomation,
|
|
1092
1193
|
onUpdateAgentModel,
|
|
@@ -1103,25 +1204,32 @@ async function waitForConnectorAuthorization(
|
|
|
1103
1204
|
connectorId: string,
|
|
1104
1205
|
connectionId: string,
|
|
1105
1206
|
flow: ConnectorFlow,
|
|
1106
|
-
) {
|
|
1207
|
+
): Promise<boolean> {
|
|
1208
|
+
// The connection status (scoped to this flow's connectionId) is the
|
|
1209
|
+
// authoritative source of truth — not a global callback flag, which can't be
|
|
1210
|
+
// attributed to a specific flow. Returns whether the connector ended up ACTIVE.
|
|
1211
|
+
const isActive = async () =>
|
|
1212
|
+
(await superagentService.getConnectorConnectionStatus(agentId, connectorId, connectionId)) === 'ACTIVE';
|
|
1213
|
+
|
|
1107
1214
|
const maxAttempts = 40;
|
|
1108
1215
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1109
1216
|
if (flow.cancelled) {
|
|
1110
|
-
|
|
1217
|
+
// Cancelled — but OAuth may have already completed; confirm with the
|
|
1218
|
+
// authoritative status before reporting not-connected.
|
|
1219
|
+
return isActive().catch(() => false);
|
|
1111
1220
|
}
|
|
1112
1221
|
|
|
1113
1222
|
await delay(3000);
|
|
1114
|
-
if (flow.cancelled) {
|
|
1115
|
-
return;
|
|
1116
|
-
}
|
|
1117
1223
|
|
|
1118
1224
|
const status = await superagentService.getConnectorConnectionStatus(agentId, connectorId, connectionId);
|
|
1119
1225
|
if (status === 'ACTIVE') {
|
|
1120
|
-
return;
|
|
1226
|
+
return true;
|
|
1121
1227
|
}
|
|
1122
1228
|
if (status === 'FAILED') {
|
|
1123
1229
|
throw new Error('OAuth connection failed.');
|
|
1124
1230
|
}
|
|
1231
|
+
// If the user cancelled during the delay, the next iteration's top-of-loop
|
|
1232
|
+
// check re-confirms via the authoritative status before returning.
|
|
1125
1233
|
}
|
|
1126
1234
|
|
|
1127
1235
|
throw new Error('Connection timed out after 2 minutes.');
|
|
@@ -1138,26 +1246,55 @@ async function openAllowedExternalUrl(
|
|
|
1138
1246
|
return;
|
|
1139
1247
|
}
|
|
1140
1248
|
|
|
1249
|
+
if (!nativeAdapters.openUrl) {
|
|
1250
|
+
// No URL opener: surface it instead of passing the host check and then
|
|
1251
|
+
// silently doing nothing.
|
|
1252
|
+
showAlert(nativeAdapters, fallbackMessage, 'This app cannot open external links. Use the web app instead.');
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1141
1256
|
try {
|
|
1142
|
-
await nativeAdapters.openUrl
|
|
1257
|
+
await nativeAdapters.openUrl(url);
|
|
1143
1258
|
} catch (error) {
|
|
1144
1259
|
showAlert(nativeAdapters, fallbackMessage, getErrorMessage(error));
|
|
1145
1260
|
}
|
|
1146
1261
|
}
|
|
1147
1262
|
|
|
1148
1263
|
function showAlert(nativeAdapters: SuperagentNativeRuntimeAdapters, title: string, message?: string) {
|
|
1149
|
-
nativeAdapters.alert
|
|
1264
|
+
if (nativeAdapters.alert) {
|
|
1265
|
+
nativeAdapters.alert(title, message);
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
// No host alert adapter — fall back to React Native's Alert (as confirmAction
|
|
1269
|
+
// does) so connector/channel/file/model errors aren't silently swallowed.
|
|
1270
|
+
Alert.alert(title, message);
|
|
1150
1271
|
}
|
|
1151
1272
|
|
|
1152
1273
|
async function confirmAction(
|
|
1153
1274
|
nativeAdapters: SuperagentNativeRuntimeAdapters,
|
|
1154
1275
|
input: Parameters<NonNullable<SuperagentNativeRuntimeAdapters['confirm']>>[0],
|
|
1155
1276
|
) {
|
|
1156
|
-
if (
|
|
1157
|
-
return
|
|
1277
|
+
if (nativeAdapters.confirm) {
|
|
1278
|
+
return nativeAdapters.confirm(input);
|
|
1158
1279
|
}
|
|
1159
1280
|
|
|
1160
|
-
|
|
1281
|
+
// No host confirm adapter — fall back to a native prompt so destructive actions
|
|
1282
|
+
// still require explicit confirmation instead of silently proceeding.
|
|
1283
|
+
return new Promise<boolean>((resolve) => {
|
|
1284
|
+
Alert.alert(
|
|
1285
|
+
input.title,
|
|
1286
|
+
input.message,
|
|
1287
|
+
[
|
|
1288
|
+
{ onPress: () => resolve(false), style: 'cancel', text: 'Cancel' },
|
|
1289
|
+
{
|
|
1290
|
+
onPress: () => resolve(true),
|
|
1291
|
+
style: input.destructive ? 'destructive' : 'default',
|
|
1292
|
+
text: input.confirmText ?? 'Confirm',
|
|
1293
|
+
},
|
|
1294
|
+
],
|
|
1295
|
+
{ cancelable: true, onDismiss: () => resolve(false) },
|
|
1296
|
+
);
|
|
1297
|
+
});
|
|
1161
1298
|
}
|
|
1162
1299
|
|
|
1163
1300
|
function buildWebUrl(baseUrl: string, path: string) {
|