@adminide-stack/yantra-mobile 12.0.51-alpha.2 → 12.0.51-alpha.4
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/lib/config/env-config.js +21 -0
- package/lib/config/env-config.js.map +1 -1
- package/lib/features/apps/AppsCatalog.js +1 -3
- package/lib/features/apps/AppsCatalog.js.map +1 -1
- package/lib/features/characters/nativeCharactersRegistry.js.map +1 -1
- package/lib/hooks/resolveSurfaceAuthGraphqlUrl.js +5 -4
- package/lib/hooks/resolveSurfaceAuthGraphqlUrl.js.map +1 -1
- package/lib/hooks/useChatApi.js +4 -4
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/hooks/useChatStream.js +2 -2
- package/lib/hooks/useChatStream.js.map +1 -1
- package/lib/screens/Characters/index.js +7 -20
- package/lib/screens/Characters/index.js.map +1 -1
- package/lib/state/chatThreadMerge.js +44 -0
- package/lib/state/chatThreadMerge.js.map +1 -0
- package/package.json +3 -3
package/lib/config/env-config.js
CHANGED
|
@@ -68,6 +68,16 @@ const baseConfig = cleanEnv(env, {
|
|
|
68
68
|
CHARACTERS_NATIVE_MANIFEST_URL: str({
|
|
69
69
|
default: ""
|
|
70
70
|
}),
|
|
71
|
+
/**
|
|
72
|
+
* Character community subgraph GraphQL URL the federated character studio
|
|
73
|
+
* reads (Discover feed, publish/edit). Empty by default → DERIVED from the
|
|
74
|
+
* same backend the surface token is minted against (swap the first DNS label
|
|
75
|
+
* `ideback.x.y` → `character-subgraph.x.y`, the convention the character
|
|
76
|
+
* surfaces use). Set explicitly only to pin a non-standard origin.
|
|
77
|
+
*/
|
|
78
|
+
CHARACTERS_SUBGRAPH_URL: str({
|
|
79
|
+
default: ""
|
|
80
|
+
}),
|
|
71
81
|
APP_NAME: str({
|
|
72
82
|
default: "Yantra"
|
|
73
83
|
}),
|
|
@@ -100,6 +110,16 @@ function resolveCharactersManifestUrl(explicit, template) {
|
|
|
100
110
|
const base = (template || "https://{slug}-surface.yantra-app-v1.cdebase.dev/").replace("{slug}", "characters-native").replace(/\/+$/, "");
|
|
101
111
|
return `${base}/native/characters.json`;
|
|
102
112
|
}
|
|
113
|
+
function resolveCharacterSubgraphUrl(explicit, graphqlUrl, canvasBackend) {
|
|
114
|
+
if (explicit) return explicit;
|
|
115
|
+
const isLocal = /^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])(:|\/|$)/i.test((graphqlUrl || "").trim());
|
|
116
|
+
const backend = isLocal ? canvasBackend : graphqlUrl;
|
|
117
|
+
const match = (backend || "").trim().match(/^(https?:)\/\/([^/]+)/i);
|
|
118
|
+
if (!match) return "";
|
|
119
|
+
const labels = match[2].split(".");
|
|
120
|
+
if (labels.length < 3) return "";
|
|
121
|
+
return `${match[1]}//character-subgraph.${labels.slice(1).join(".")}/graphql`;
|
|
122
|
+
}
|
|
103
123
|
function resolveAgentGatewayGraphqlUrl() {
|
|
104
124
|
if (baseConfig.USE_PROXY_STAGING_GATEWAY && baseConfig.PROXY_STAGING_GATEWAY_URL) {
|
|
105
125
|
return baseConfig.PROXY_STAGING_GATEWAY_URL;
|
|
@@ -120,6 +140,7 @@ const clampedCdecliTimeoutSec = Math.min(600, Math.max(15, Math.round(baseConfig
|
|
|
120
140
|
const config = __spreadProps(__spreadValues({}, baseConfig), {
|
|
121
141
|
CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: clampedCdecliTimeoutSec,
|
|
122
142
|
CHARACTERS_NATIVE_MANIFEST_URL: resolveCharactersManifestUrl(baseConfig.CHARACTERS_NATIVE_MANIFEST_URL, baseConfig.SURFACE_URL_TEMPLATE),
|
|
143
|
+
CHARACTERS_SUBGRAPH_URL: resolveCharacterSubgraphUrl(baseConfig.CHARACTERS_SUBGRAPH_URL, baseConfig.GRAPHQL_URL, baseConfig.CANVAS_BACKEND_GRAPHQL_URL),
|
|
123
144
|
AGENT_GATEWAY_GRAPHQL_URL: agentGatewayGraphqlUrl,
|
|
124
145
|
AGENT_GATEWAY_WS_URL: resolveAgentGatewayWsUrl(agentGatewayGraphqlUrl)
|
|
125
146
|
});export{config};//# sourceMappingURL=env-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env-config.js","sources":["../../src/config/env-config.ts"],"sourcesContent":["import { str, cleanEnv, bool, num } from 'envalid';\n\nconst env = (process as { APP_ENV?: NodeJS.ProcessEnv; env?: NodeJS.ProcessEnv }).APP_ENV || process.env;\n\nconst baseConfig = cleanEnv(env, {\n GRAPHQL_URL: str({ default: 'http://localhost:8080/graphql' }),\n CLIENT_URL: str({ default: 'http://localhost:3000' }),\n /** Standalone Web Builder surface embedded in the mobile WebView shell. */\n WEB_BUILDER_URL: str({ default: 'http://localhost:5174/' }),\n /** Standalone Design surface — local vite is 5174/4174 next to canvas 5175. */\n DESIGN_SURFACE_URL: str({ default: 'http://localhost:5174/' }),\n /** Standalone Canvas surface embedded in the same WebView shell. */\n CANVAS_SURFACE_URL: str({ default: 'http://localhost:5175/' }),\n /**\n * GraphQL backend whose JWT keys the canvas index will verify.\n * Must stay in lockstep with canvas-surface `.env.development`\n * (`VITE_BACKEND_GRAPHQL_URL` / `VITE_SURFACE_INDEX_URL`). A locally\n * minted token 401s against `surface-index-backend.yantra-app-v1`.\n */\n CANVAS_BACKEND_GRAPHQL_URL: str({ default: 'https://ideback.yantra-app-v1.cdebase.dev/graphql' }),\n /** Explicit canvas index GraphQL URL. Empty → derived from the canvas auth backend. */\n SURFACE_INDEX_URL: str({ default: '' }),\n /**\n * Origin template for every other deployed surface: `{slug}` is the app's\n * `surfaceSlug`. One var instead of 20+ near-identical URLs, and it keeps the\n * environment (dev cluster / prod) in one place.\n */\n SURFACE_URL_TEMPLATE: str({ default: 'https://{slug}-surface.yantra-app-v1.cdebase.dev/' }),\n /**\n * Characters gallery manifest (`characters.json`). Empty by default →\n * DERIVED from SURFACE_URL_TEMPLATE + the wipe-immune `characters-native`\n * slug (see below), so a prod build reads prod and a dev build reads dev\n * with no per-profile URL to maintain. Set explicitly only to pin a\n * non-standard origin.\n */\n CHARACTERS_NATIVE_MANIFEST_URL: str({ default: '' }),\n APP_NAME: str({ default: 'Yantra' }),\n GROQ_API_KEY: str({ default: '' }),\n CDECLI_AGENT_ENDPOINT: str({ default: 'https://cdecli-agent.cdebase.dev' }),\n CDECLI_AGENT_AUTH_TOKEN: str({ default: '' }),\n /** Seconds to wait for CDeCLI stream completion before timing out (then fallback chat API runs). Min 15, max 600. */\n /** Aligned with web `useCdecliChannel` (120s). Mobile hook uses the same constant inline. */\n CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: num({ default: 120 }),\n BACKEND_URL: str({ default: '' }),\n USE_PROXY_STAGING_GATEWAY: bool({ default: false }),\n PROXY_STAGING_GATEWAY_URL: str({ default: '' }),\n});\n\n/**\n * Where the app fetches the characters gallery manifest.\n *\n * Mirrors metro.federation.js `charactersRemoteUrl()`: the manifest lives on\n * the dedicated `characters-native` artifacts slug, NOT `character-surface`.\n * The bulk web-surface republish redeploys character-surface from its pinned\n * web bundle and wipes anything hand-added under /native, so the gallery data\n * (like the federated remote) must ride the wipe-immune slug. The origin\n * DERIVES from SURFACE_URL_TEMPLATE, so prod builds read prod and dev builds\n * read dev automatically. An explicit CHARACTERS_NATIVE_MANIFEST_URL still\n * wins for a one-off pin.\n */\nfunction resolveCharactersManifestUrl(explicit: string, template: string): string {\n if (explicit) return explicit;\n const base = (template || 'https://{slug}-surface.yantra-app-v1.cdebase.dev/')\n .replace('{slug}', 'characters-native')\n .replace(/\\/+$/, '');\n return `${base}/native/characters.json`;\n}\n\nfunction resolveAgentGatewayGraphqlUrl(): string {\n if (baseConfig.USE_PROXY_STAGING_GATEWAY && baseConfig.PROXY_STAGING_GATEWAY_URL) {\n return baseConfig.PROXY_STAGING_GATEWAY_URL;\n }\n if (baseConfig.GRAPHQL_URL) return baseConfig.GRAPHQL_URL;\n if (baseConfig.BACKEND_URL) return `${baseConfig.BACKEND_URL.replace(/\\/$/, '')}/graphql`;\n return '/graphql';\n}\n\nfunction resolveBaseWsUrl(graphqlUrl: string): string {\n const base = graphqlUrl.replace(/\\/graphql$/, '');\n return base.replace(/^http/, 'ws');\n}\n\nfunction resolveAgentGatewayWsUrl(graphqlUrl: string): string {\n return `${resolveBaseWsUrl(graphqlUrl)}/ws/openclaw-chat`;\n}\n\nconst agentGatewayGraphqlUrl = resolveAgentGatewayGraphqlUrl();\n\nconst clampedCdecliTimeoutSec = Math.min(600, Math.max(15, Math.round(baseConfig.CDECLI_CHAT_RESPONSE_TIMEOUT_SEC)));\n\nexport const config = {\n ...baseConfig,\n CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: clampedCdecliTimeoutSec,\n CHARACTERS_NATIVE_MANIFEST_URL: resolveCharactersManifestUrl(\n baseConfig.CHARACTERS_NATIVE_MANIFEST_URL,\n baseConfig.SURFACE_URL_TEMPLATE,\n ),\n AGENT_GATEWAY_GRAPHQL_URL: agentGatewayGraphqlUrl,\n AGENT_GATEWAY_WS_URL: resolveAgentGatewayWsUrl(agentGatewayGraphqlUrl),\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"env-config.js","sources":["../../src/config/env-config.ts"],"sourcesContent":["import { str, cleanEnv, bool, num } from 'envalid';\n\nconst env = (process as { APP_ENV?: NodeJS.ProcessEnv; env?: NodeJS.ProcessEnv }).APP_ENV || process.env;\n\nconst baseConfig = cleanEnv(env, {\n GRAPHQL_URL: str({ default: 'http://localhost:8080/graphql' }),\n CLIENT_URL: str({ default: 'http://localhost:3000' }),\n /** Standalone Web Builder surface embedded in the mobile WebView shell. */\n WEB_BUILDER_URL: str({ default: 'http://localhost:5174/' }),\n /** Standalone Design surface — local vite is 5174/4174 next to canvas 5175. */\n DESIGN_SURFACE_URL: str({ default: 'http://localhost:5174/' }),\n /** Standalone Canvas surface embedded in the same WebView shell. */\n CANVAS_SURFACE_URL: str({ default: 'http://localhost:5175/' }),\n /**\n * GraphQL backend whose JWT keys the canvas index will verify.\n * Must stay in lockstep with canvas-surface `.env.development`\n * (`VITE_BACKEND_GRAPHQL_URL` / `VITE_SURFACE_INDEX_URL`). A locally\n * minted token 401s against `surface-index-backend.yantra-app-v1`.\n */\n CANVAS_BACKEND_GRAPHQL_URL: str({ default: 'https://ideback.yantra-app-v1.cdebase.dev/graphql' }),\n /** Explicit canvas index GraphQL URL. Empty → derived from the canvas auth backend. */\n SURFACE_INDEX_URL: str({ default: '' }),\n /**\n * Origin template for every other deployed surface: `{slug}` is the app's\n * `surfaceSlug`. One var instead of 20+ near-identical URLs, and it keeps the\n * environment (dev cluster / prod) in one place.\n */\n SURFACE_URL_TEMPLATE: str({ default: 'https://{slug}-surface.yantra-app-v1.cdebase.dev/' }),\n /**\n * Characters gallery manifest (`characters.json`). Empty by default →\n * DERIVED from SURFACE_URL_TEMPLATE + the wipe-immune `characters-native`\n * slug (see below), so a prod build reads prod and a dev build reads dev\n * with no per-profile URL to maintain. Set explicitly only to pin a\n * non-standard origin.\n */\n CHARACTERS_NATIVE_MANIFEST_URL: str({ default: '' }),\n /**\n * Character community subgraph GraphQL URL the federated character studio\n * reads (Discover feed, publish/edit). Empty by default → DERIVED from the\n * same backend the surface token is minted against (swap the first DNS label\n * `ideback.x.y` → `character-subgraph.x.y`, the convention the character\n * surfaces use). Set explicitly only to pin a non-standard origin.\n */\n CHARACTERS_SUBGRAPH_URL: str({ default: '' }),\n APP_NAME: str({ default: 'Yantra' }),\n GROQ_API_KEY: str({ default: '' }),\n CDECLI_AGENT_ENDPOINT: str({ default: 'https://cdecli-agent.cdebase.dev' }),\n CDECLI_AGENT_AUTH_TOKEN: str({ default: '' }),\n /** Seconds to wait for CDeCLI stream completion before timing out (then fallback chat API runs). Min 15, max 600. */\n /** Aligned with web `useCdecliChannel` (120s). Mobile hook uses the same constant inline. */\n CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: num({ default: 120 }),\n BACKEND_URL: str({ default: '' }),\n USE_PROXY_STAGING_GATEWAY: bool({ default: false }),\n PROXY_STAGING_GATEWAY_URL: str({ default: '' }),\n});\n\n/**\n * Where the app fetches the characters gallery manifest.\n *\n * Mirrors metro.federation.js `charactersRemoteUrl()`: the manifest lives on\n * the dedicated `characters-native` artifacts slug, NOT `character-surface`.\n * The bulk web-surface republish redeploys character-surface from its pinned\n * web bundle and wipes anything hand-added under /native, so the gallery data\n * (like the federated remote) must ride the wipe-immune slug. The origin\n * DERIVES from SURFACE_URL_TEMPLATE, so prod builds read prod and dev builds\n * read dev automatically. An explicit CHARACTERS_NATIVE_MANIFEST_URL still\n * wins for a one-off pin.\n */\nfunction resolveCharactersManifestUrl(explicit: string, template: string): string {\n if (explicit) return explicit;\n const base = (template || 'https://{slug}-surface.yantra-app-v1.cdebase.dev/')\n .replace('{slug}', 'characters-native')\n .replace(/\\/+$/, '');\n return `${base}/native/characters.json`;\n}\n\n/**\n * Character community subgraph URL. Derives from the SAME backend the surface\n * session token is minted against, so it stays authoritative across dev/prod and\n * matches the token's audience: a locally minted token is scoped to\n * CANVAS_BACKEND_GRAPHQL_URL (the cluster backend), so a local GRAPHQL_URL uses\n * that cluster host too - a subgraph on localhost would 401 the same JWT.\n */\nfunction resolveCharacterSubgraphUrl(explicit: string, graphqlUrl: string, canvasBackend: string): string {\n if (explicit) return explicit;\n const isLocal = /^https?:\\/\\/(localhost|127\\.0\\.0\\.1|\\[::1\\])(:|\\/|$)/i.test((graphqlUrl || '').trim());\n const backend = isLocal ? canvasBackend : graphqlUrl;\n const match = (backend || '').trim().match(/^(https?:)\\/\\/([^/]+)/i);\n if (!match) return '';\n const labels = match[2].split('.');\n if (labels.length < 3) return '';\n return `${match[1]}//character-subgraph.${labels.slice(1).join('.')}/graphql`;\n}\n\nfunction resolveAgentGatewayGraphqlUrl(): string {\n if (baseConfig.USE_PROXY_STAGING_GATEWAY && baseConfig.PROXY_STAGING_GATEWAY_URL) {\n return baseConfig.PROXY_STAGING_GATEWAY_URL;\n }\n if (baseConfig.GRAPHQL_URL) return baseConfig.GRAPHQL_URL;\n if (baseConfig.BACKEND_URL) return `${baseConfig.BACKEND_URL.replace(/\\/$/, '')}/graphql`;\n return '/graphql';\n}\n\nfunction resolveBaseWsUrl(graphqlUrl: string): string {\n const base = graphqlUrl.replace(/\\/graphql$/, '');\n return base.replace(/^http/, 'ws');\n}\n\nfunction resolveAgentGatewayWsUrl(graphqlUrl: string): string {\n return `${resolveBaseWsUrl(graphqlUrl)}/ws/openclaw-chat`;\n}\n\nconst agentGatewayGraphqlUrl = resolveAgentGatewayGraphqlUrl();\n\nconst clampedCdecliTimeoutSec = Math.min(600, Math.max(15, Math.round(baseConfig.CDECLI_CHAT_RESPONSE_TIMEOUT_SEC)));\n\nexport const config = {\n ...baseConfig,\n CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: clampedCdecliTimeoutSec,\n CHARACTERS_NATIVE_MANIFEST_URL: resolveCharactersManifestUrl(\n baseConfig.CHARACTERS_NATIVE_MANIFEST_URL,\n baseConfig.SURFACE_URL_TEMPLATE,\n ),\n CHARACTERS_SUBGRAPH_URL: resolveCharacterSubgraphUrl(\n baseConfig.CHARACTERS_SUBGRAPH_URL,\n baseConfig.GRAPHQL_URL,\n baseConfig.CANVAS_BACKEND_GRAPHQL_URL,\n ),\n AGENT_GATEWAY_GRAPHQL_URL: agentGatewayGraphqlUrl,\n AGENT_GATEWAY_WS_URL: resolveAgentGatewayWsUrl(agentGatewayGraphqlUrl),\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -57,9 +57,7 @@ function AppsCatalog({
|
|
|
57
57
|
if (app.nativeRoute === "characters-native") {
|
|
58
58
|
navigation.dispatch(CommonActions.navigate({
|
|
59
59
|
name: "MainStack.CharactersNative",
|
|
60
|
-
params
|
|
61
|
-
manifestUrl: config.CHARACTERS_NATIVE_MANIFEST_URL
|
|
62
|
-
})
|
|
60
|
+
params
|
|
63
61
|
}));
|
|
64
62
|
return;
|
|
65
63
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppsCatalog.js","sources":["../../../src/features/apps/AppsCatalog.tsx"],"sourcesContent":["/**\n * Full-screen Apps catalog: search + grouped tiles, then navigate into a\n * native surface or a new chat. Shared by the Apps screen (not a popup).\n */\nimport React, { useCallback, useMemo, useState } from 'react';\nimport { Pressable, ScrollView, StyleSheet, Text, TextInput, View, useColorScheme } from 'react-native';\nimport { CommonActions, useNavigation, useRoute } from '@react-navigation/native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { v4 as uuidv4 } from 'uuid';\nimport { config } from '../../config/env-config';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport { useChatMutations } from '../../hooks/useChatApi';\nimport { resolveSurfaceUrl } from './resolveSurfaceUrl';\nimport { groupMobileApps, MOBILE_APP_CATALOG, type MobileAppItem } from './mobileAppCatalog';\n\nfunction buildChannelTitle(channelId: string): string {\n return `chat-channel-${channelId}`;\n}\n\nexport function AppsCatalog({ orgName: orgNameProp }: { orgName?: string | null }) {\n const navigation = useNavigation<any>();\n const route = useRoute<any>();\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n const { createChannel } = useChatMutations();\n const [query, setQuery] = useState('');\n\n const orgName = useMemo(() => {\n if (typeof orgNameProp === 'string' && orgNameProp.trim()) return orgNameProp.trim();\n const raw = (route?.params?.orgName as string | undefined) ?? '';\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [orgNameProp, route?.params?.orgName]);\n\n const grouped = useMemo(() => groupMobileApps(MOBILE_APP_CATALOG, query), [query]);\n\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const surface = isDark ? '#111827' : mobileTokens.color.surface;\n const screenBg = isDark ? '#0f172a' : mobileTokens.color.bg;\n const borderColor = isDark ? 'rgba(148,163,184,0.22)' : mobileTokens.color.border;\n const fieldBg = isDark ? '#1e293b' : mobileTokens.color.surfaceMuted;\n const accent = isDark ? '#a5b4fc' : mobileTokens.color.primary;\n const accentSoft = isDark ? 'rgba(99,102,241,0.18)' : mobileTokens.color.primarySoft;\n\n const openApp = useCallback(\n (app: MobileAppItem) => {\n const channelId = uuidv4();\n const params: Record<string, unknown> = {\n orgName: orgName ?? undefined,\n channelId,\n appTitle: app.label,\n };\n\n if (app.nativeRoute === 'characters-native') {\n // Same wiring as AppsMenu: the tile opens the native character\n // studio, never a chat with the tile's prompt.\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.CharactersNative',\n params: {\n ...params,\n manifestUrl: config.CHARACTERS_NATIVE_MANIFEST_URL,\n },\n }),\n );\n return;\n }\n\n if (app.nativeRoute === 'canvas-native') {\n // Web canvas opens the boards grid first. Do not mint a chat\n // channelId here — that id is not an index row, and passing it\n // looks like a deep link into a board that does not exist.\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.CanvasNative',\n params: { orgName: orgName ?? undefined, appTitle: app.label },\n }),\n );\n return;\n }\n\n if (app.nativeRoute === 'webbuilder') {\n const surfaceUrl = resolveSurfaceUrl(app, config);\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: surfaceUrl ? { ...params, url: surfaceUrl } : params,\n }),\n );\n return;\n }\n\n void createChannel({\n id: channelId,\n title: buildChannelTitle(channelId),\n isShared: false,\n sharedSlug: null,\n isArchived: false,\n isPinned: false,\n model: null,\n systemPrompt: null,\n orgName,\n } as any).catch((err) => {\n console.error('[AppsCatalog] createChannel failed:', err);\n });\n\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.Chat',\n params: {\n ...params,\n initialQuery: app.prompt,\n initialMode: 'chat',\n },\n }),\n );\n },\n [createChannel, navigation, orgName],\n );\n\n return (\n <View style={[styles.root, { backgroundColor: screenBg }]}>\n <View style={[styles.searchWrap, { backgroundColor: fieldBg, borderColor }]}>\n <MaterialCommunityIcons name=\"magnify\" size={18} color={muted} />\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder=\"Search apps\"\n placeholderTextColor={muted}\n autoCorrect={false}\n autoCapitalize=\"none\"\n style={[styles.searchInput, { color: foreground }]}\n />\n </View>\n <ScrollView keyboardShouldPersistTaps=\"handled\" contentContainerStyle={styles.list}>\n {grouped.length === 0 ? (\n <Text style={[styles.empty, { color: muted }]}>No apps match that search.</Text>\n ) : (\n grouped.map((group) => (\n <View key={group.label} style={styles.group}>\n <Text style={[styles.groupLabel, { color: muted }]}>{group.label}</Text>\n <View style={styles.groupGrid}>\n {group.items.map((app) => (\n <Pressable\n key={app.key}\n onPress={() => openApp(app)}\n accessibilityRole=\"button\"\n accessibilityLabel={app.label}\n style={({ pressed }) => [\n styles.appTile,\n {\n backgroundColor: surface,\n borderColor,\n },\n pressed && { backgroundColor: accentSoft },\n ]}\n >\n <View style={[styles.appIcon, { backgroundColor: accentSoft }]}>\n <MaterialCommunityIcons name={app.icon} size={18} color={accent} />\n </View>\n <Text style={[styles.appLabel, { color: foreground }]} numberOfLines={2}>\n {app.label}\n </Text>\n </Pressable>\n ))}\n </View>\n </View>\n ))\n )}\n </ScrollView>\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n root: {\n flex: 1,\n },\n searchWrap: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n marginHorizontal: 16,\n marginTop: 12,\n marginBottom: 8,\n borderWidth: 1,\n borderRadius: 12,\n paddingHorizontal: 12,\n minHeight: 42,\n },\n searchInput: {\n flex: 1,\n fontSize: 15,\n paddingVertical: 8,\n },\n list: {\n paddingHorizontal: 16,\n paddingTop: 8,\n paddingBottom: 28,\n gap: 16,\n },\n group: {\n gap: 8,\n },\n groupLabel: {\n fontSize: 11,\n fontWeight: '600',\n letterSpacing: 0.7,\n textTransform: 'uppercase',\n },\n groupGrid: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n gap: 8,\n },\n appTile: {\n width: '31%',\n flexGrow: 1,\n minWidth: 96,\n maxWidth: '32.5%',\n borderWidth: 1,\n borderRadius: 14,\n paddingHorizontal: 10,\n paddingVertical: 12,\n gap: 8,\n },\n appIcon: {\n width: 32,\n height: 32,\n borderRadius: 10,\n alignItems: 'center',\n justifyContent: 'center',\n },\n appLabel: {\n fontSize: 13,\n fontWeight: '600',\n lineHeight: 17,\n },\n empty: {\n textAlign: 'center',\n paddingVertical: 28,\n fontSize: 14,\n },\n});\n"],"names":["_a","uuidv4"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AppsCatalog.js","sources":["../../../src/features/apps/AppsCatalog.tsx"],"sourcesContent":["/**\n * Full-screen Apps catalog: search + grouped tiles, then navigate into a\n * native surface or a new chat. Shared by the Apps screen (not a popup).\n */\nimport React, { useCallback, useMemo, useState } from 'react';\nimport { Pressable, ScrollView, StyleSheet, Text, TextInput, View, useColorScheme } from 'react-native';\nimport { CommonActions, useNavigation, useRoute } from '@react-navigation/native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { v4 as uuidv4 } from 'uuid';\nimport { config } from '../../config/env-config';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport { useChatMutations } from '../../hooks/useChatApi';\nimport { resolveSurfaceUrl } from './resolveSurfaceUrl';\nimport { groupMobileApps, MOBILE_APP_CATALOG, type MobileAppItem } from './mobileAppCatalog';\n\nfunction buildChannelTitle(channelId: string): string {\n return `chat-channel-${channelId}`;\n}\n\nexport function AppsCatalog({ orgName: orgNameProp }: { orgName?: string | null }) {\n const navigation = useNavigation<any>();\n const route = useRoute<any>();\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n const { createChannel } = useChatMutations();\n const [query, setQuery] = useState('');\n\n const orgName = useMemo(() => {\n if (typeof orgNameProp === 'string' && orgNameProp.trim()) return orgNameProp.trim();\n const raw = (route?.params?.orgName as string | undefined) ?? '';\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [orgNameProp, route?.params?.orgName]);\n\n const grouped = useMemo(() => groupMobileApps(MOBILE_APP_CATALOG, query), [query]);\n\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const surface = isDark ? '#111827' : mobileTokens.color.surface;\n const screenBg = isDark ? '#0f172a' : mobileTokens.color.bg;\n const borderColor = isDark ? 'rgba(148,163,184,0.22)' : mobileTokens.color.border;\n const fieldBg = isDark ? '#1e293b' : mobileTokens.color.surfaceMuted;\n const accent = isDark ? '#a5b4fc' : mobileTokens.color.primary;\n const accentSoft = isDark ? 'rgba(99,102,241,0.18)' : mobileTokens.color.primarySoft;\n\n const openApp = useCallback(\n (app: MobileAppItem) => {\n const channelId = uuidv4();\n const params: Record<string, unknown> = {\n orgName: orgName ?? undefined,\n channelId,\n appTitle: app.label,\n };\n\n if (app.nativeRoute === 'characters-native') {\n // Same wiring as AppsMenu: the tile opens the self-contained native\n // character studio (never a chat with the tile's prompt). The host\n // contributes only the session token + subgraph endpoint, built in\n // the screen, so no manifest/handoff params are needed here.\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.CharactersNative',\n params,\n }),\n );\n return;\n }\n\n if (app.nativeRoute === 'canvas-native') {\n // Web canvas opens the boards grid first. Do not mint a chat\n // channelId here — that id is not an index row, and passing it\n // looks like a deep link into a board that does not exist.\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.CanvasNative',\n params: { orgName: orgName ?? undefined, appTitle: app.label },\n }),\n );\n return;\n }\n\n if (app.nativeRoute === 'webbuilder') {\n const surfaceUrl = resolveSurfaceUrl(app, config);\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: surfaceUrl ? { ...params, url: surfaceUrl } : params,\n }),\n );\n return;\n }\n\n void createChannel({\n id: channelId,\n title: buildChannelTitle(channelId),\n isShared: false,\n sharedSlug: null,\n isArchived: false,\n isPinned: false,\n model: null,\n systemPrompt: null,\n orgName,\n } as any).catch((err) => {\n console.error('[AppsCatalog] createChannel failed:', err);\n });\n\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.Chat',\n params: {\n ...params,\n initialQuery: app.prompt,\n initialMode: 'chat',\n },\n }),\n );\n },\n [createChannel, navigation, orgName],\n );\n\n return (\n <View style={[styles.root, { backgroundColor: screenBg }]}>\n <View style={[styles.searchWrap, { backgroundColor: fieldBg, borderColor }]}>\n <MaterialCommunityIcons name=\"magnify\" size={18} color={muted} />\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder=\"Search apps\"\n placeholderTextColor={muted}\n autoCorrect={false}\n autoCapitalize=\"none\"\n style={[styles.searchInput, { color: foreground }]}\n />\n </View>\n <ScrollView keyboardShouldPersistTaps=\"handled\" contentContainerStyle={styles.list}>\n {grouped.length === 0 ? (\n <Text style={[styles.empty, { color: muted }]}>No apps match that search.</Text>\n ) : (\n grouped.map((group) => (\n <View key={group.label} style={styles.group}>\n <Text style={[styles.groupLabel, { color: muted }]}>{group.label}</Text>\n <View style={styles.groupGrid}>\n {group.items.map((app) => (\n <Pressable\n key={app.key}\n onPress={() => openApp(app)}\n accessibilityRole=\"button\"\n accessibilityLabel={app.label}\n style={({ pressed }) => [\n styles.appTile,\n {\n backgroundColor: surface,\n borderColor,\n },\n pressed && { backgroundColor: accentSoft },\n ]}\n >\n <View style={[styles.appIcon, { backgroundColor: accentSoft }]}>\n <MaterialCommunityIcons name={app.icon} size={18} color={accent} />\n </View>\n <Text style={[styles.appLabel, { color: foreground }]} numberOfLines={2}>\n {app.label}\n </Text>\n </Pressable>\n ))}\n </View>\n </View>\n ))\n )}\n </ScrollView>\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n root: {\n flex: 1,\n },\n searchWrap: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n marginHorizontal: 16,\n marginTop: 12,\n marginBottom: 8,\n borderWidth: 1,\n borderRadius: 12,\n paddingHorizontal: 12,\n minHeight: 42,\n },\n searchInput: {\n flex: 1,\n fontSize: 15,\n paddingVertical: 8,\n },\n list: {\n paddingHorizontal: 16,\n paddingTop: 8,\n paddingBottom: 28,\n gap: 16,\n },\n group: {\n gap: 8,\n },\n groupLabel: {\n fontSize: 11,\n fontWeight: '600',\n letterSpacing: 0.7,\n textTransform: 'uppercase',\n },\n groupGrid: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n gap: 8,\n },\n appTile: {\n width: '31%',\n flexGrow: 1,\n minWidth: 96,\n maxWidth: '32.5%',\n borderWidth: 1,\n borderRadius: 14,\n paddingHorizontal: 10,\n paddingVertical: 12,\n gap: 8,\n },\n appIcon: {\n width: 32,\n height: 32,\n borderRadius: 10,\n alignItems: 'center',\n justifyContent: 'center',\n },\n appLabel: {\n fontSize: 13,\n fontWeight: '600',\n lineHeight: 17,\n },\n empty: {\n textAlign: 'center',\n paddingVertical: 28,\n fontSize: 14,\n },\n});\n"],"names":["_a","uuidv4"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nativeCharactersRegistry.js","sources":["../../../src/features/characters/nativeCharactersRegistry.ts"],"sourcesContent":["/**\n * The characters viewer seam - same pattern as the canvas registry\n * ([[nativeViewerRegistry]]): the APP (the Module Federation host) registers\n * the federated experience component at startup; the Characters screen in\n * this package reads it. The package itself never names the remote, so\n * rollup's lib/ build stays free of `characters_native/...` specifiers.\n *\n * Exported from the package index ON PURPOSE: reachability from the entry is\n * what stops rollup tree-shaking the register function as internally-unused\n * and constant-folding readers to undefined (the exact failure ya#965 fixed\n * for canvas).\n */\nimport type * as React from 'react';\nimport type {
|
|
1
|
+
{"version":3,"file":"nativeCharactersRegistry.js","sources":["../../../src/features/characters/nativeCharactersRegistry.ts"],"sourcesContent":["/**\n * The characters viewer seam - same pattern as the canvas registry\n * ([[nativeViewerRegistry]]): the APP (the Module Federation host) registers\n * the federated experience component at startup; the Characters screen in\n * this package reads it. The package itself never names the remote, so\n * rollup's lib/ build stays free of `characters_native/...` specifiers.\n *\n * Exported from the package index ON PURPOSE: reachability from the entry is\n * what stops rollup tree-shaking the register function as internally-unused\n * and constant-folding readers to undefined (the exact failure ya#965 fixed\n * for canvas).\n */\nimport type * as React from 'react';\nimport type { CharacterStudioProps } from './characterStudioProps';\n\ntype ExperienceComponent = React.ComponentType<CharacterStudioProps>;\n\nlet current: ExperienceComponent | null = null;\n\nexport function registerNativeCharactersExperience(component: ExperienceComponent): void {\n current = component;\n}\n\nexport function getNativeCharactersExperience(): ExperienceComponent | null {\n return current;\n}\n"],"names":[],"mappings":"AAeA,IAAI,OAAsC,GAAA,IAAA;AACnC,SAAS,mCAAmC,SAAsC,EAAA;AACvF,EAAU,OAAA,GAAA,SAAA;AACZ;AACO,SAAS,6BAA4D,GAAA;AAC1E,EAAO,OAAA,OAAA;AACT"}
|
|
@@ -35,14 +35,15 @@ function isCanvasSurfaceUrl(surfaceUrl, canvasSurfaceUrl) {
|
|
|
35
35
|
function resolveSurfaceAuthGraphqlUrl(surfaceUrl, appGraphqlUrl, cfg = {}) {
|
|
36
36
|
var _a;
|
|
37
37
|
const app = normalizeGraphqlUrl(appGraphqlUrl);
|
|
38
|
-
if (!isCanvasSurfaceUrl(surfaceUrl, cfg.CANVAS_SURFACE_URL)) return app;
|
|
39
38
|
try {
|
|
40
39
|
const u = new URL(surfaceUrl);
|
|
41
40
|
const m = u.hostname.match(/^[a-z0-9-]+-surface\.(.+)$/i);
|
|
42
41
|
if (m) return normalizeGraphqlUrl(`${u.protocol}//ideback.${m[1]}/graphql`);
|
|
43
42
|
} catch (e) {
|
|
44
43
|
}
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
if (isCanvasSurfaceUrl(surfaceUrl, cfg.CANVAS_SURFACE_URL) && isLoopbackOrPrivateHost(hostnameOf(app))) {
|
|
45
|
+
const harness = ((_a = cfg.CANVAS_BACKEND_GRAPHQL_URL) == null ? void 0 : _a.trim()) || DEFAULT_CANVAS_HARNESS_BACKEND;
|
|
46
|
+
return normalizeGraphqlUrl(harness);
|
|
47
|
+
}
|
|
48
|
+
return app;
|
|
48
49
|
}export{isCanvasSurfaceUrl,resolveSurfaceAuthGraphqlUrl};//# sourceMappingURL=resolveSurfaceAuthGraphqlUrl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveSurfaceAuthGraphqlUrl.js","sources":["../../src/hooks/resolveSurfaceAuthGraphqlUrl.ts"],"sourcesContent":["/**\n * Which GraphQL backend to mint the WebView system JWT against.\n *\n *
|
|
1
|
+
{"version":3,"file":"resolveSurfaceAuthGraphqlUrl.js","sources":["../../src/hooks/resolveSurfaceAuthGraphqlUrl.ts"],"sourcesContent":["/**\n * Which GraphQL backend to mint the WebView system JWT against.\n *\n * A deployed surface's index (`surface-index-backend.<cluster>`) verifies JWTs\n * with that CLUSTER's SECRET_API_TOKEN_* keys. A token minted against a\n * different backend 401s as `{\"message\":\"Unauthorized\"}`. So EVERY deployed\n * `*-surface.<cluster>` (canvas, design, webbuilder, …) must mint against\n * `ideback.<cluster>` derived from its own host — not the app's GRAPHQL_URL.\n * On dev these coincide (GRAPHQL_URL is already ideback.yantra-app-v1.cdebase.dev),\n * but on prod GRAPHQL_URL is ideback.yantra-app-v1.yantra.app while the surfaces\n * live under ideback.yantra.app, so a canvas-only remap left design/webbuilder\n * minting against the wrong backend and their index reads 401'd\n * (surface-index \"Couldn't reach the … index\"). Canvas already worked because it\n * got this remap; generalizing it fixes the sibling surfaces the same way.\n *\n * Canvas local harness (`packages/canvas/.env.development`, ports 5175/4175)\n * still mints against the cluster harness backend so local dev reaches a real\n * index; other local surfaces keep the app URL.\n */\n\nexport type SurfaceAuthUrlConfig = {\n CANVAS_SURFACE_URL?: string;\n CANVAS_BACKEND_GRAPHQL_URL?: string;\n};\n\nconst DEFAULT_CANVAS_HARNESS_BACKEND = 'https://ideback.yantra-app-v1.cdebase.dev/graphql';\n\nfunction normalizeGraphqlUrl(url: string): string {\n return url.trim().replace(/\\/$/, '');\n}\n\nfunction isLoopbackOrPrivateHost(hostname: string): boolean {\n const host = hostname.toLowerCase();\n if (host === 'localhost' || host === '127.0.0.1' || host === '::1') return true;\n if (/^10\\./.test(host)) return true;\n if (/^192\\.168\\./.test(host)) return true;\n if (/^172\\.(1[6-9]|2\\d|3[0-1])\\./.test(host)) return true;\n return false;\n}\n\nfunction hostnameOf(url: string): string {\n try {\n return new URL(url).hostname;\n } catch {\n return '';\n }\n}\n\n/**\n * True when `surfaceUrl` is the canvas SPA (local harness or deployed\n * `canvas-surface.*`). Web Builder is 5174/4174; canvas vite is 5175/4175.\n */\nexport function isCanvasSurfaceUrl(surfaceUrl: string, canvasSurfaceUrl?: string): boolean {\n try {\n const u = new URL(surfaceUrl);\n if (u.hostname.toLowerCase().startsWith('canvas-surface.')) return true;\n if (u.port === '5175' || u.port === '4175') return true;\n const configured = canvasSurfaceUrl?.trim();\n if (configured) {\n const c = new URL(configured);\n if (u.origin === c.origin) return true;\n }\n } catch {\n return /canvas-surface/i.test(surfaceUrl);\n }\n return false;\n}\n\nexport function resolveSurfaceAuthGraphqlUrl(\n surfaceUrl: string,\n appGraphqlUrl: string,\n cfg: SurfaceAuthUrlConfig = {},\n): string {\n const app = normalizeGraphqlUrl(appGraphqlUrl);\n\n // Any DEPLOYED surface host mints against its own cluster's ideback — the\n // backend whose SECRET_API_TOKEN_* keys the matching surface-index verifies\n // with. Applies to every `*-surface.<cluster>` (canvas, design, webbuilder…),\n // not just canvas, so their index reads authenticate on prod as well as dev.\n try {\n const u = new URL(surfaceUrl);\n const m = u.hostname.match(/^[a-z0-9-]+-surface\\.(.+)$/i);\n if (m) return normalizeGraphqlUrl(`${u.protocol}//ideback.${m[1]}/graphql`);\n } catch {\n /* localhost / unparseable — fall through */\n }\n\n // Local canvas harness (5175/4175 or a configured canvas origin) still mints\n // against the cluster harness backend when the app URL is local; other local\n // surfaces keep the app URL (their index is the local dev backend).\n if (isCanvasSurfaceUrl(surfaceUrl, cfg.CANVAS_SURFACE_URL) && isLoopbackOrPrivateHost(hostnameOf(app))) {\n const harness = cfg.CANVAS_BACKEND_GRAPHQL_URL?.trim() || DEFAULT_CANVAS_HARNESS_BACKEND;\n return normalizeGraphqlUrl(harness);\n }\n\n return app;\n}\n"],"names":[],"mappings":"AAwBA,MAAM,8BAAiC,GAAA,mDAAA;AACvC,SAAS,oBAAoB,GAAqB,EAAA;AAChD,EAAA,OAAO,GAAI,CAAA,IAAA,EAAO,CAAA,OAAA,CAAQ,OAAO,EAAE,CAAA;AACrC;AACA,SAAS,wBAAwB,QAA2B,EAAA;AAC1D,EAAM,MAAA,IAAA,GAAO,SAAS,WAAY,EAAA;AAClC,EAAA,IAAI,SAAS,WAAe,IAAA,IAAA,KAAS,WAAe,IAAA,IAAA,KAAS,OAAc,OAAA,IAAA;AAC3E,EAAA,IAAI,OAAQ,CAAA,IAAA,CAAK,IAAI,CAAA,EAAU,OAAA,IAAA;AAC/B,EAAA,IAAI,aAAc,CAAA,IAAA,CAAK,IAAI,CAAA,EAAU,OAAA,IAAA;AACrC,EAAA,IAAI,6BAA8B,CAAA,IAAA,CAAK,IAAI,CAAA,EAAU,OAAA,IAAA;AACrD,EAAO,OAAA,KAAA;AACT;AACA,SAAS,WAAW,GAAqB,EAAA;AACvC,EAAI,IAAA;AACF,IAAO,OAAA,IAAI,GAAI,CAAA,GAAG,CAAE,CAAA,QAAA;AAAA,GACd,CAAA,OAAA,CAAA,EAAA;AACN,IAAO,OAAA,EAAA;AAAA;AAEX;AAMgB,SAAA,kBAAA,CAAmB,YAAoB,gBAAoC,EAAA;AACzF,EAAI,IAAA;AACF,IAAM,MAAA,CAAA,GAAI,IAAI,GAAA,CAAI,UAAU,CAAA;AAC5B,IAAA,IAAI,EAAE,QAAS,CAAA,WAAA,GAAc,UAAW,CAAA,iBAAiB,GAAU,OAAA,IAAA;AACnE,IAAA,IAAI,EAAE,IAAS,KAAA,MAAA,IAAU,CAAE,CAAA,IAAA,KAAS,QAAe,OAAA,IAAA;AACnD,IAAA,MAAM,aAAa,gBAAkB,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAA,IAAA,EAAA;AACrC,IAAA,IAAI,UAAY,EAAA;AACd,MAAM,MAAA,CAAA,GAAI,IAAI,GAAA,CAAI,UAAU,CAAA;AAC5B,MAAA,IAAI,CAAE,CAAA,MAAA,KAAW,CAAE,CAAA,MAAA,EAAe,OAAA,IAAA;AAAA;AACpC,GACM,CAAA,OAAA,CAAA,EAAA;AACN,IAAO,OAAA,iBAAA,CAAkB,KAAK,UAAU,CAAA;AAAA;AAE1C,EAAO,OAAA,KAAA;AACT;AACO,SAAS,4BAA6B,CAAA,UAAA,EAAoB,aAAuB,EAAA,GAAA,GAA4B,EAAY,EAAA;AA/DhI,EAAA,IAAA,EAAA;AAgEE,EAAM,MAAA,GAAA,GAAM,oBAAoB,aAAa,CAAA;AAM7C,EAAI,IAAA;AACF,IAAM,MAAA,CAAA,GAAI,IAAI,GAAA,CAAI,UAAU,CAAA;AAC5B,IAAA,MAAM,CAAI,GAAA,CAAA,CAAE,QAAS,CAAA,KAAA,CAAM,6BAA6B,CAAA;AACxD,IAAI,IAAA,CAAA,EAAU,OAAA,mBAAA,CAAoB,CAAG,EAAA,CAAA,CAAE,QAAQ,CAAa,UAAA,EAAA,CAAA,CAAE,CAAC,CAAC,CAAU,QAAA,CAAA,CAAA;AAAA,GACpE,CAAA,OAAA,CAAA,EAAA;AAAA;AAOR,EAAI,IAAA,kBAAA,CAAmB,YAAY,GAAI,CAAA,kBAAkB,KAAK,uBAAwB,CAAA,UAAA,CAAW,GAAG,CAAC,CAAG,EAAA;AACtG,IAAA,MAAM,OAAU,GAAA,CAAA,CAAA,EAAA,GAAA,GAAA,CAAI,0BAAJ,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAgC,IAAU,EAAA,KAAA,8BAAA;AAC1D,IAAA,OAAO,oBAAoB,OAAO,CAAA;AAAA;AAEpC,EAAO,OAAA,GAAA;AACT"}
|
package/lib/hooks/useChatApi.js
CHANGED
|
@@ -391,15 +391,15 @@ function flattenPostsWithReplies(posts, fallbackChannelId) {
|
|
|
391
391
|
const ids = new Set(uniq.map(getId));
|
|
392
392
|
const roots = uniq.filter((post) => !(post == null ? void 0 : post.parentId) || !ids.has(String(post.parentId)));
|
|
393
393
|
const replies = uniq.filter((post) => (post == null ? void 0 : post.parentId) && ids.has(String(post.parentId)));
|
|
394
|
-
const
|
|
394
|
+
const byTime = (a, b) => postTimestamp(a.createdAt) - postTimestamp(b.createdAt);
|
|
395
395
|
const ordered = [];
|
|
396
|
-
for (const root of [...roots].sort(
|
|
396
|
+
for (const root of [...roots].sort(byTime)) {
|
|
397
397
|
const rootId = getId(root);
|
|
398
398
|
ordered.push(root);
|
|
399
|
-
ordered.push(...replies.filter((reply) => String(reply.parentId) === rootId).sort(
|
|
399
|
+
ordered.push(...replies.filter((reply) => String(reply.parentId) === rootId).sort(byTime));
|
|
400
400
|
}
|
|
401
401
|
const seen = new Set(ordered.map(getId));
|
|
402
|
-
ordered.push(...replies.filter((reply) => !seen.has(getId(reply))).sort(
|
|
402
|
+
ordered.push(...replies.filter((reply) => !seen.has(getId(reply))).sort(byTime));
|
|
403
403
|
const out = [];
|
|
404
404
|
const emitted = /* @__PURE__ */ new Set();
|
|
405
405
|
for (const post of ordered) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatApi.js","sources":["../../src/hooks/useChatApi.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { useApolloClient } from '@apollo/client';\nimport { AiAgentMessageRole, PostTypeEnum, RoomType, SortEnum } from 'common';\nimport {\n GetChannelsByUserWithLastMessageDocument,\n MessagesDocument,\n useAddChannelMutation,\n useGetChannelsByUserWithLastMessageQuery,\n useMessagesQuery,\n useSendMessagesMutation,\n} from 'common/graphql';\nimport type {\n IAccountCreateChatSessionInput,\n IAccountSaveChatMessagesInput as IAccountSaveChatMessagesInputBase,\n} from 'common/server';\nimport { useCallback, useMemo } from 'react';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n attachmentsFromUserContent,\n historyAttachmentTitle,\n isAttachedCaption,\n} from '../features/attachments/historyAttachmentLabel';\n\nconst MESSAGES_PAGE_LIMIT = 100;\n\n/** Same variables as web Inbox / AIAgent: list AI assistant channels for the current user. */\nexport const AI_ASSISTANT_CHANNELS_QUERY_VARS = {\n criteria: { type: RoomType.Aiassistant },\n limit: 100,\n skip: 0,\n sort: { key: 'updatedAt', value: SortEnum.Desc },\n};\n\nexport const HISTORY_PAGE_SIZE = 20;\n\n/**\n * Variables for the channels-based chat history list (`ChatHistoryLanding`).\n *\n * IMPORTANT: pass the user's org `slug` (e.g. `tarun-upadhyay-qraw`) so the\n * `channelsByUser` resolver's `$in: [criteria.orgName, orgId]` includes\n * channels stored under the slug. When `criteria.orgName` is omitted, the\n * `$in` collapses to just `[orgId]` and channels saved with the slug as\n * `orgName` (the mobile create path) never match. That's the cause of the\n * silently-empty history screen.\n *\n * Kept as a builder (not a constant) because the slug varies per user and\n * because Apollo treats different `variables` as different cached entries —\n * if the create mutation refetches a no-orgName variant, the orgName-variant\n * the screen watches stays stale.\n */\nexport function getHistoryChannelsQueryVariables(orgName?: string | null, options?: { skip?: number; limit?: number }) {\n const trimmedOrg = typeof orgName === 'string' && orgName.trim().length > 0 ? orgName.trim() : undefined;\n return {\n criteria: {\n type: RoomType.Aiassistant,\n ...(trimmedOrg ? { orgName: trimmedOrg } : {}),\n },\n limit: options?.limit ?? HISTORY_PAGE_SIZE,\n skip: options?.skip ?? 0,\n sort: { key: 'updatedAt' as const, value: SortEnum.Desc },\n };\n}\n\n/** @deprecated Use {@link getHistoryChannelsQueryVariables} so `orgName` is included. */\nexport const HISTORY_QUERY_BASE = getHistoryChannelsQueryVariables();\n\nfunction normalizeOptionalString(value: string | null | undefined): string | undefined {\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;\n}\n\n/** Cache slots the history list watches — used to prepend a created channel without refetching. */\nexport function getChatHistoryChannelRefetchQueries(orgName?: string | null) {\n const trimmedOrg = normalizeOptionalString(orgName);\n return [\n { query: GetChannelsByUserWithLastMessageDocument, variables: AI_ASSISTANT_CHANNELS_QUERY_VARS },\n ...(trimmedOrg\n ? [\n {\n query: GetChannelsByUserWithLastMessageDocument,\n variables: getHistoryChannelsQueryVariables(trimmedOrg),\n },\n ]\n : []),\n { query: GetChannelsByUserWithLastMessageDocument, variables: HISTORY_QUERY_BASE },\n ];\n}\n\nfunction getThreadMessagesQueryVariables(sessionId: string) {\n return {\n channelId: sessionId,\n limit: MESSAGES_PAGE_LIMIT,\n skip: 0,\n sort: { key: 'createdAt' as const, value: SortEnum.Asc },\n };\n}\n\n/**\n * Variables for the chat-history feed on the mobile `ChatHistory` screen.\n *\n * First page uses `HISTORY_PAGE_SIZE` (20) posts; \"Load older\" paginates by post\n * `skip` in increments of 20. Rows are still one per channel (collapsed from posts).\n *\n * This query intentionally hits `messages` (not `channelsByUser`) — the same\n * pattern the web sidebar uses (`useNewChatPageHistorySessions`). Reasons:\n * 1. `channelsByUser` is server-side gated by an injected `orgName` /\n * `members` filter that can mismatch when channels were stored with an\n * org slug while the resolver injects the org id. The `messages`\n * resolver filters Post directly by `editedBy: accountId`, so the\n * user's own AI-assistant posts always show up.\n * 2. The user-authored post IS the conversation's natural title — no need\n * to walk `lastMessage.propsConfiguration.contents.parent` to recover\n * the original prompt.\n *\n * - `type: AIASSISTANT` scopes to AI chat (not direct/service rooms).\n * - `props.role: 'user'` selects only the user's turns. The assistant reply\n * is ignored here; it would override the title with the agent's words.\n * - `editedBy: accountUserId` scopes to the current user's own posts,\n * independent of channel membership / org name.\n */\nexport function getChatHistoryMessagesQueryVariables(\n accountUserId: string,\n options?: { skip?: number; limit?: number },\n) {\n return {\n limit: options?.limit ?? HISTORY_PAGE_SIZE,\n skip: options?.skip ?? 0,\n sort: { key: 'updatedAt' as const, value: SortEnum.Desc },\n type: PostTypeEnum.Aiassistant,\n editedBy: accountUserId,\n props: { role: 'user' },\n };\n}\n\nexport type ChatHistoryMode = 'chat' | 'deep-search' | 'build';\n\nexport interface ChatHistorySession {\n /** Channel id — used to navigate to the Chat screen. */\n channelId: string;\n /** User's most recent prompt in this channel (used as the row title). */\n title: string;\n /** Second line: latest post `message` field (same as Manus subtitle). */\n preview: string;\n /** Conversation mode (chat / deep-search / build), inferred from channel title or last message. */\n mode: ChatHistoryMode;\n /** Most-recent activity timestamp (sort key + bucket key for Today/Yesterday/…). */\n updatedAt: Date;\n createdAt: Date;\n /**\n * True when no concrete prompt was recoverable (no parent, no user turn, no\n * meaningful channel.title). UI renders the title in a quieter style.\n */\n isPlaceholder: boolean;\n /** First turn was a file send (`Attached: …`). Row uses a paperclip tile + \"New chat\". */\n isAttachment?: boolean;\n}\n\n/**\n * Collapse a list of user-authored AI assistant posts (newest first) into one\n * row per channel. First post per `channel.id` wins the title, which — because\n * the query is sorted by `updatedAt DESC` — is the user's latest prompt in\n * that channel. Posts whose `channel.id` is missing (unexpected, but possible\n * if the resolver omits the relation) are skipped.\n */\nexport function chatHistorySessionsFromMessages(\n data: { messages?: { data?: unknown[] | null } | null } | null | undefined,\n): ChatHistorySession[] {\n const rows = data?.messages?.data;\n if (!rows?.length) return [];\n\n const seen = new Set<string>();\n const sessions: ChatHistorySession[] = [];\n\n for (const post of rows as any[]) {\n const channelId = post?.channel?.id ? String(post.channel.id) : '';\n if (!channelId || seen.has(channelId)) continue;\n\n const rawTitle = String(post?.message ?? '')\n .replace(/\\s+/g, ' ')\n .trim();\n if (/^thinking[.…]*$/i.test(rawTitle)) continue;\n\n seen.add(channelId);\n const updatedAt = post?.updatedAt ? new Date(post.updatedAt) : new Date();\n const createdAt = post?.createdAt ? new Date(post.createdAt) : updatedAt;\n const isAttachment = isAttachedCaption(rawTitle);\n const title = isAttachment ? historyAttachmentTitle(rawTitle) : rawTitle || 'New chat';\n\n sessions.push({\n channelId,\n title,\n preview: '',\n mode: 'chat',\n updatedAt,\n createdAt,\n isPlaceholder: !rawTitle && !isAttachment,\n isAttachment,\n });\n }\n\n return sessions;\n}\n\n/**\n * Mobile parity hook for the web sidebar's `useNewChatPageHistorySessions`.\n *\n * Returns one row per channel where the user has authored at least one AI assistant\n * post, with the title taken from that user's latest prompt. Skipped when\n * `accountUserId` isn't known yet (we don't want to fire a query without it).\n */\nexport function useChatHistorySessionsFromMessages(\n accountUserId: string | null | undefined,\n options?: { skip?: boolean },\n) {\n const skip = options?.skip || !accountUserId;\n const { data, loading, error, refetch } = useMessagesQuery({\n variables: accountUserId ? getChatHistoryMessagesQueryVariables(accountUserId, { limit: 100 }) : undefined,\n skip,\n // cache-first + `messages` typePolicy (keyed by editedBy/type/props).\n // Later visits read the cache — no repeated network hit.\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n context: { cacheKey: 'new-chat-history-messages' },\n });\n\n const sessions = useMemo(() => chatHistorySessionsFromMessages(data), [data]);\n const sourcePostCount = data?.messages?.data?.length ?? 0;\n\n return { sessions, loading, error, refetch, sourcePostCount };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Channels-based chat history (parent + lastMessage) */\n/* -------------------------------------------------------------------------- */\n\ninterface ChannelLastMessageLike {\n message?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n props?: { role?: string | null; mode?: string | null } | null;\n propsConfiguration?: {\n contents?: {\n role?: string | null;\n mode?: string | null;\n template?: string | null;\n parent?: {\n message?: string | null;\n props?: { role?: string | null } | null;\n } | null;\n fragment?: {\n title?: string | null;\n sandboxUrl?: string | null;\n sandboxId?: string | null;\n } | null;\n } | null;\n content?: { role?: string | null; mode?: string | null } | null;\n } | null;\n}\n\ninterface ChannelLike {\n id?: string | null;\n type?: string | null;\n displayName?: string | null;\n title?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n lastMessage?: ChannelLastMessageLike | null;\n}\n\nfunction getLastMessageRole(lastMessage: ChannelLastMessageLike | null | undefined): string {\n return String(\n lastMessage?.propsConfiguration?.contents?.role ??\n lastMessage?.propsConfiguration?.content?.role ??\n lastMessage?.props?.role ??\n '',\n ).toUpperCase();\n}\n\nfunction getParentUserPrompt(lastMessage: ChannelLastMessageLike | null | undefined): string {\n const parent = lastMessage?.propsConfiguration?.contents?.parent;\n if (!parent) return '';\n return String(parent?.message ?? '').trim();\n}\n\nfunction isBuildLastMessage(lastMessage: ChannelLastMessageLike | null | undefined): boolean {\n if (!lastMessage) return false;\n const contents = lastMessage.propsConfiguration?.contents;\n const mode = String(\n contents?.mode ?? lastMessage.propsConfiguration?.content?.mode ?? lastMessage?.props?.mode ?? '',\n ).toLowerCase();\n if (mode === 'build' || mode === 'workflow') return true;\n const fragment = contents?.fragment;\n if (fragment?.sandboxUrl || fragment?.sandboxId) return true;\n if (String(contents?.template ?? '').trim()) return true;\n return false;\n}\n\nfunction detectMode(channel: ChannelLike): ChatHistoryMode {\n if (isBuildLastMessage(channel?.lastMessage)) {\n return 'build';\n }\n const display = String(channel?.displayName ?? '').toLowerCase();\n const title = String(channel?.title ?? '').toLowerCase();\n if (display.startsWith('build-channel') || title.startsWith('build-channel') || title.startsWith('build channel')) {\n return 'build';\n }\n const parent = getParentUserPrompt(channel?.lastMessage).toLowerCase();\n if (/^build\\s*me\\s*:/.test(parent)) {\n return 'build';\n }\n if (display.startsWith('deep-search') || title.startsWith('deep search') || title.startsWith('deep-search')) {\n return 'deep-search';\n }\n return 'chat';\n}\n\n/**\n * Drop the internal slug we use as `channel.title` for server-side mode detection\n * (`chat-channel-<uuid>` / `deep-search-<uuid>`) so it doesn't leak into the row\n * label. The server sometimes also reformats this slug into `displayName` as\n * title-cased text with spaces (e.g. `\"Deep Search b64be4f7 9fe6 …\"`) — those\n * are equally machine-generated and must NOT be shown to the user.\n *\n * Pattern accepts:\n * • `deep-search-<uuid>` / `chat-channel-<uuid>` (raw, mode signal)\n * • `Deep Search <uuid>` / `Chat Channel <uuid>` (display-cased, server-reformatted)\n * • UUID may use hyphens, spaces, or be partially truncated as long as the\n * trailing chunk is hex.\n */\nfunction cleanChannelTitle(rawTitle: string | null | undefined): string {\n const t = String(rawTitle ?? '').trim();\n if (!t) return '';\n if (/^(chat[\\s-]channel|deep[\\s-]search|build[\\s-]channel)[\\s-][0-9a-f][0-9a-f\\s-]{7,}\\.?$/i.test(t)) return '';\n // Creation defaults carry no meaning either (parity with the browser sidebar).\n if (/^(new chat|workflow|deep search)$/i.test(t)) return '';\n return t;\n}\n\n/** `[Active connectors: …]` routing prefix on persisted gateway user posts. */\nconst ACTIVE_CONNECTORS_PREFIX_RE = /^\\s*\\[Active connectors:[^\\]]*\\]\\s*/i;\n\nfunction cleanMessageText(raw: string): string {\n return raw.replace(ACTIVE_CONNECTORS_PREFIX_RE, '').replace(/\\s+/g, ' ').trim();\n}\n\n/** Status / tool stubs that must not become a history title or subtitle. */\nfunction isTransientHistoryText(text: string): boolean {\n const t = cleanMessageText(text);\n if (!t) return true;\n if (/^thinking[.…]*$/i.test(t)) return true;\n if (/^let me check on that requested skill/i.test(t)) return true;\n if (/^(working on it|one moment|just a (sec|second|moment))[.…]*$/i.test(t)) return true;\n if (/^[⚙️⚠]/.test(t)) return true;\n return false;\n}\n\nfunction looksLikeAssistantReply(text: string, role: string): boolean {\n if (role === 'ASSISTANT' || role === 'AI' || role === 'BOT' || role === 'AGENT') return true;\n if (role === 'USER') return false;\n const t = text.trim();\n if (/^(let me |i'll |i will |sure[,.] |here's |here is )/i.test(t)) return true;\n if (t.length > 180) return true;\n return false;\n}\n\nfunction cleanHistoryPreview(raw: string): string {\n let t = cleanMessageText(raw);\n t = t.replace(/^(thinking[.…]*\\s*)+/i, '').trim();\n t = t.replace(/^let me check on that requested skill[^\\n.!?]*[.!?-]?\\s*/i, '').trim();\n t = t.replace(/^(?:⚙️[^\\n]*\\n)+\\s*/g, '').trim();\n return t;\n}\n\n/**\n * Map one channel into a session row (Manus-style two-line list):\n *\n * **Title (line 1):** `lastMessage.propsConfiguration.contents.parent.message`\n * when present (the user turn the thread is anchored on). Otherwise fall back\n * to the last post body if that post is still a user message, then a\n * machine-slug-stripped channel title, then a machine-slug-stripped\n * `displayName`, then `\"Thinking…\"`. Machine slugs (`deep-search-<uuid>`,\n * `chat-channel-<uuid>`, and their server-reformatted display variants)\n * are filtered via `cleanChannelTitle`, so they never reach the row.\n *\n * **Preview (line 2):** `lastMessage.message` as returned by the API (trimmed,\n * whitespace collapsed). Agent errors that start with `⚠` stay visible in the\n * subtitle, matching the reference UI.\n *\n * If preview text equals the title after trim, the second line is omitted\n * (single-line channel, no duplicate).\n */\nexport function buildSessionFromChannel(channel: ChannelLike): ChatHistorySession | null {\n const channelId = String(channel?.id ?? '');\n if (!channelId) return null;\n\n const lastMessage = channel?.lastMessage ?? null;\n const lastMessageRole = getLastMessageRole(lastMessage);\n const parentTrimmed = cleanHistoryPreview(getParentUserPrompt(lastMessage));\n const lastBody = cleanHistoryPreview(String(lastMessage?.message ?? ''));\n const userTurn = lastMessageRole === 'USER' && lastBody ? lastBody : '';\n const cleanedChannelTitle = cleanChannelTitle(channel?.title);\n /**\n * Apply the same machine-slug cleaner to `displayName`. The server\n * sometimes derives displayName from the title (`\"deep-search-<uuid>\"`\n * → `\"Deep Search <uuid>\"`), so without this the slug bypasses\n * `cleanedChannelTitle` and lands directly in the row label.\n */\n const cleanedDisplayName = cleanChannelTitle(channel?.displayName);\n\n let resolvedTitle = cleanedChannelTitle || parentTrimmed || userTurn || cleanedDisplayName;\n if (\n !resolvedTitle &&\n lastBody &&\n !isTransientHistoryText(lastBody) &&\n !looksLikeAssistantReply(lastBody, lastMessageRole)\n ) {\n resolvedTitle = lastBody;\n }\n if (!resolvedTitle) {\n const rawDefault = String(channel?.title ?? '').trim();\n if (rawDefault && !/^(chat[\\s-]channel|deep[\\s-]search)[\\s-][0-9a-f][0-9a-f\\s-]{7,}\\.?$/i.test(rawDefault)) {\n resolvedTitle = rawDefault;\n }\n }\n const isAttachment =\n isAttachedCaption(resolvedTitle) || isAttachedCaption(parentTrimmed) || isAttachedCaption(userTurn);\n if (isAttachment) resolvedTitle = historyAttachmentTitle(resolvedTitle);\n const isPlaceholder = !resolvedTitle;\n if (isPlaceholder) resolvedTitle = 'New chat';\n\n let preview = lastBody;\n if (\n isTransientHistoryText(preview) ||\n isAttachedCaption(preview) ||\n preview === resolvedTitle ||\n preview === parentTrimmed\n ) {\n preview = '';\n }\n if (lastMessageRole === 'USER' && !looksLikeAssistantReply(lastBody, lastMessageRole)) {\n preview = '';\n }\n\n const sortAt = (() => {\n const candidates = [channel?.updatedAt, lastMessage?.updatedAt, lastMessage?.createdAt, channel?.createdAt];\n for (const candidate of candidates) {\n if (candidate) {\n const t = new Date(candidate).getTime();\n if (Number.isFinite(t) && t > 0) return t;\n }\n }\n return Date.now();\n })();\n\n const createdAtRaw = channel?.createdAt ? new Date(channel.createdAt).getTime() : sortAt;\n\n return {\n channelId,\n title: resolvedTitle,\n preview,\n mode: detectMode(channel),\n updatedAt: new Date(sortAt),\n createdAt: new Date(Number.isFinite(createdAtRaw) ? createdAtRaw : sortAt),\n isPlaceholder,\n isAttachment,\n };\n}\n\n/** Collapse a `channelsByUser` response into session rows for the history list. */\nexport function chatHistorySessionsFromChannels(\n data: { channelsByUser?: (ChannelLike | null)[] | null } | null | undefined,\n): ChatHistorySession[] {\n const channels = (data?.channelsByUser ?? []) as (ChannelLike | null)[];\n const now = Date.now();\n return channels\n .filter((c): c is ChannelLike => Boolean(c?.id) && (!c?.type || c.type === RoomType.Aiassistant))\n .map((c) => buildSessionFromChannel(c))\n .filter((row): row is ChatHistorySession => row !== null)\n .filter((row) => {\n if (!row.isPlaceholder) return true;\n if (row.preview) return true;\n return now - row.updatedAt.getTime() < 2 * 60 * 1000;\n })\n .sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());\n}\n\n/**\n * Overlay user-authored prompts from `messages` onto channel rows whose\n * lastMessage never carried `parent.message` (typical cdecli/gateway chats).\n */\nexport function enrichHistorySessionsWithUserPrompts(\n fromChannels: ChatHistorySession[],\n fromMessages: ChatHistorySession[],\n): ChatHistorySession[] {\n if (!fromMessages.length) return fromChannels;\n const byId = new Map(fromMessages.map((session) => [session.channelId, session]));\n return fromChannels.map((row) => {\n const fromUser = byId.get(row.channelId);\n if (!fromUser?.title || isTransientHistoryText(fromUser.title)) return row;\n const titleMissing = row.isPlaceholder || isTransientHistoryText(row.title) || /^new chat$/i.test(row.title);\n if (!titleMissing) {\n return row.preview ? row : { ...row, preview: fromUser.preview || row.preview };\n }\n return {\n ...row,\n title: fromUser.title,\n preview: row.preview && !isTransientHistoryText(row.preview) ? row.preview : fromUser.preview,\n isPlaceholder: false,\n isAttachment: fromUser.isAttachment || row.isAttachment,\n };\n });\n}\n\n/**\n * Chat history feed driven by `channelsByUser`. Each row: parent prompt as title,\n * `lastMessage.message` as subtitle (Manus-style), when the API provides them.\n *\n * Caller MUST pass `orgName` (the org slug). Without it, the resolver only\n * matches channels whose `orgName` field equals the user's `orgId`, which is\n * never the case for mobile-created channels (those store the slug). The hook\n * suspends the query (`skip: true`) until `orgName` is known, so we never\n * fire a guaranteed-empty request.\n *\n * Pagination is by channel count (one channel = one row in this query),\n * unlike the messages-based path which paginates by raw post rows.\n */\nexport function useChatHistorySessionsFromChannels(orgName: string | null | undefined, options?: { skip?: boolean }) {\n const skip = options?.skip || !orgName;\n const variables = useMemo(() => getHistoryChannelsQueryVariables(orgName), [orgName]);\n\n const { data, loading, error, refetch } = useGetChannelsByUserWithLastMessageQuery({\n variables,\n skip,\n // cache-first + `channelsByUser` typePolicy (keyArgs drop skip/limit/sort).\n // Later navigations read the canonical list from cache — no repeated\n // GetChannelsByUserWithLastMessage. Freshness comes from pull-to-refresh\n // / createChannel cache writes, not per-visit network hits.\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n context: { cacheKey: 'chat-history-channels-list' },\n });\n\n const sessions = useMemo(() => chatHistorySessionsFromChannels(data), [data]);\n const sourceChannelCount = data?.channelsByUser?.length ?? 0;\n /**\n * `sessionsLoaded` means \"we have data we can show\", regardless of whether a\n * background revalidation is still in flight. Same contract as `messagesLoaded`\n * in `useChatMessages` — lets the screen show the cached list (or empty state)\n * immediately on revisit instead of flashing a loader for the network round-trip.\n */\n const sessionsLoaded = data !== undefined;\n\n return { sessions, loading, sessionsLoaded, error, refetch, sourceChannelCount };\n}\n\nfunction stripModelCostHeader(content: string): string {\n const normalized = content.replace(/\\r\\n/g, '\\n');\n return normalized.replace(\n /^\\s*(?:[^\\w\\n]+\\s*)?[a-z0-9][a-z0-9._-]*\\s*\\(\\s*\\$[\\d.]+\\s*\\/\\s*MTok\\s+in\\s*\\)\\s*\\n+/i,\n '',\n );\n}\n\nfunction sanitizeAssistantContentByRole(role: unknown, content: string): string {\n return role === 'assistant' ? stripModelCostHeader(content) : content;\n}\n\nfunction omitContent<T extends Record<string, any>>(value: T | null | undefined): Omit<T, 'content'> {\n const clone = { ...(value ?? {}) } as Record<string, any>;\n delete clone.content;\n return clone as Omit<T, 'content'>;\n}\n\nexport interface ChatSessionUI {\n id: string;\n title: string;\n createdAt: Date;\n updatedAt: Date;\n messageCount?: number;\n}\n\nexport function useChatSessions(options?: { includeArchived?: boolean; skip?: boolean }) {\n const { data, loading, error, refetch } = useGetChannelsByUserWithLastMessageQuery({\n variables: AI_ASSISTANT_CHANNELS_QUERY_VARS,\n skip: options?.skip,\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n\n const sessions: ChatSessionUI[] = useMemo(() => {\n const channels = data?.channelsByUser ?? [];\n return channels\n .filter((c): c is NonNullable<typeof c> => Boolean(c?.id))\n .map((channel) => ({\n id: channel.id,\n title: channel.title || channel.displayName || 'New Chat',\n createdAt: new Date(channel.createdAt ?? Date.now()),\n updatedAt: new Date(channel.updatedAt ?? Date.now()),\n messageCount: undefined,\n }));\n }, [data]);\n\n return { sessions, loading, error, refetch };\n}\n\nexport interface ChatMessageUI {\n id: string;\n sessionId: string;\n role: 'user' | 'assistant' | 'system';\n content: string;\n attachments?: Array<{ id: string; name: string; type: string; mimeType?: string; size?: number; url?: string }>;\n tokenCount?: number;\n model?: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\ninterface MinimalFile {\n id?: string | null;\n name?: string | null;\n mimeType?: string | null;\n size?: number | null;\n url?: string | null;\n}\n\ninterface MinimalPost {\n id?: string | null;\n parentId?: string | null;\n message?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n channel?: { id?: string | null } | null;\n files?: { data?: MinimalFile[] | null } | null;\n replies?: { data?: MinimalPost[] | null } | null;\n props?: { role?: string | null; tokenCount?: number | null; model?: string | null } | null;\n propsConfiguration?: {\n contents?: { role?: string | null } | null;\n content?: { role?: string | null } | null;\n } | null;\n}\n\nfunction postTimestamp(value: string | null | undefined): number {\n if (!value) return 0;\n const t = new Date(value).getTime();\n return Number.isFinite(t) ? t : 0;\n}\n\n/**\n * Same flatten as account/browser `useChatApi`: merge roots + nested\n * `replies.data`, then emit each root followed by its children (oldest first).\n * Omitting this left assistant replies unordered or sitting above the prompt.\n */\nfunction flattenPostsWithReplies(posts: MinimalPost[], fallbackChannelId: string): ChatMessageUI[] {\n const getId = (post: MinimalPost) => String(post?.id ?? '');\n const nestedReplies = posts.flatMap((post) => (Array.isArray(post?.replies?.data) ? post.replies.data : []));\n const byId = new Map<string, MinimalPost>();\n for (const post of [...posts, ...nestedReplies]) {\n const id = getId(post);\n if (id) byId.set(id, post);\n }\n const uniq = Array.from(byId.values());\n const ids = new Set(uniq.map(getId));\n const roots = uniq.filter((post) => !post?.parentId || !ids.has(String(post.parentId)));\n const replies = uniq.filter((post) => post?.parentId && ids.has(String(post.parentId)));\n const byTimeThenId = (a: MinimalPost, b: MinimalPost) =>\n postTimestamp(a.createdAt) - postTimestamp(b.createdAt) || getId(a).localeCompare(getId(b));\n\n const ordered: MinimalPost[] = [];\n for (const root of [...roots].sort(byTimeThenId)) {\n const rootId = getId(root);\n ordered.push(root);\n ordered.push(...replies.filter((reply) => String(reply.parentId) === rootId).sort(byTimeThenId));\n }\n const seen = new Set(ordered.map(getId));\n ordered.push(...replies.filter((reply) => !seen.has(getId(reply))).sort(byTimeThenId));\n\n const out: ChatMessageUI[] = [];\n const emitted = new Set<string>();\n for (const post of ordered) {\n const id = getId(post);\n if (!id || emitted.has(id)) continue;\n emitted.add(id);\n out.push(mapPostToChatMessageUI(post, fallbackChannelId));\n }\n return out;\n}\n\nfunction mapPostToChatMessageUI(post: MinimalPost, fallbackChannelId: string): ChatMessageUI {\n const props = (post.props ?? {}) as Record<string, any>;\n const contents = post.propsConfiguration?.contents ?? {};\n const roleRaw = props.role ?? contents.role ?? post.propsConfiguration?.content?.role;\n let role: ChatMessageUI['role'] = 'assistant';\n if (roleRaw === 'user' || roleRaw === AiAgentMessageRole.User) role = 'user';\n else if (roleRaw === 'assistant' || roleRaw === AiAgentMessageRole.Assistant) role = 'assistant';\n else if (roleRaw === 'system') role = 'system';\n\n const rawContent = post?.message ?? '';\n const content = sanitizeAssistantContentByRole(role, rawContent);\n\n const fromFiles = (post?.files?.data ?? []).map((file) => ({\n id: file.id ?? uuidv4(),\n name: file.name ?? 'file',\n type: (typeof file.mimeType === 'string' && file.mimeType.startsWith('image/') ? 'screenshot' : 'file') as\n | 'screenshot'\n | 'file',\n mimeType: file.mimeType ?? undefined,\n size: file.size ?? undefined,\n url: file.url ?? undefined,\n }));\n const fromProps = Array.isArray(props.attachments)\n ? props.attachments.map((file: MinimalFile & { type?: string }) => ({\n id: file.id ?? uuidv4(),\n name: file.name ?? 'file',\n type: (file.type === 'screenshot' ||\n (typeof file.mimeType === 'string' && file.mimeType.startsWith('image/'))\n ? 'screenshot'\n : 'file') as 'screenshot' | 'file',\n mimeType: file.mimeType ?? undefined,\n size: file.size ?? undefined,\n url: file.url ?? undefined,\n }))\n : [];\n const attachments = attachmentsFromUserContent(content, fromFiles.length ? fromFiles : fromProps);\n\n return {\n id: post?.id ?? uuidv4(),\n sessionId: post?.channel?.id ?? fallbackChannelId,\n role,\n content,\n attachments,\n tokenCount: props.tokenCount ?? undefined,\n model: props.model ?? undefined,\n createdAt: post?.createdAt ? new Date(post.createdAt) : new Date(0),\n updatedAt: post?.updatedAt ? new Date(post.updatedAt) : new Date(0),\n };\n}\n\nexport function useChatMessages(sessionId: string | null, options?: { skip?: boolean }) {\n const { data, loading, error, refetch } = useMessagesQuery({\n variables: sessionId ? getThreadMessagesQueryVariables(sessionId) : undefined,\n skip: !sessionId || options?.skip,\n // cache-first + `messages` typePolicy (keyed by channelId). Opening a thread\n // that was already loaded does not refetch. New channels still hit the\n // network once. saveMessages writes new posts into this cache slot.\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n /**\n * Cache key is per-channel so switching sessions doesn't read another channel's response.\n * Keeping this as a constant ('messages-list') used to cause cross-session bleed in the\n * custom Apollo link before reaching the normalized cache.\n */\n context: { cacheKey: sessionId ? `messages-list:${sessionId}` : 'messages-list' },\n });\n\n /**\n * `messagesLoaded` means \"we have data we can show\". cache-first fills `data`\n * synchronously on a hit so revisiting a thread does not flash a loader.\n */\n const messagesLoaded = data !== undefined;\n\n const messages: ChatMessageUI[] = useMemo(() => {\n if (!sessionId) return [];\n const rows = (data?.messages?.data ?? []) as MinimalPost[];\n return flattenPostsWithReplies(rows, sessionId);\n }, [data, sessionId]);\n\n return { messages, loading, messagesLoaded, error, refetch };\n}\n\nexport type IAccountSaveChatMessagesInput = IAccountSaveChatMessagesInputBase & {\n mode?: 'plan' | 'build';\n createdBy?: string;\n};\n\n/** Backend/gateway may have already inserted the post (E11000 duplicate `_id`). */\nfunction isDuplicatePostError(error: unknown): boolean {\n const parts: string[] = [];\n if (error && typeof error === 'object' && 'graphQLErrors' in error) {\n const gqlErrors = (error as { graphQLErrors?: Array<{ message?: string }> }).graphQLErrors ?? [];\n parts.push(...gqlErrors.map((e) => e?.message ?? ''));\n }\n if (error instanceof Error) {\n parts.push(error.message);\n } else if (error != null) {\n parts.push(String(error));\n }\n const msg = parts.join(' ');\n return /E11000|duplicate key/i.test(msg);\n}\n\nfunction prependCreatedChannelToHistoryCache(\n cache: any,\n created: { id?: string | null; title?: string | null; type?: string | null } | null | undefined,\n fallbackTitle: string,\n orgName?: string | null,\n) {\n if (!created?.id) return;\n const nowIso = new Date().toISOString();\n // Fill every field the history query selects so cache-first stays complete\n // (a partial Channel makes the whole channelsByUser read a miss).\n const optimisticChannel = {\n __typename: 'Channel',\n id: created.id,\n title: created.title ?? fallbackTitle,\n description: null,\n type: created.type ?? RoomType.Aiassistant,\n displayName: null,\n members: [],\n creator: null,\n lastMessage: null,\n createdAt: nowIso,\n updatedAt: nowIso,\n };\n for (const { query, variables } of getChatHistoryChannelRefetchQueries(orgName)) {\n try {\n cache.updateQuery({ query, variables }, (data: any) => {\n const list = (data?.channelsByUser ?? []) as any[];\n if (list.some((c) => c?.id === created.id)) return data;\n return { ...(data ?? {}), channelsByUser: [optimisticChannel, ...list] };\n });\n } catch (err) {\n console.warn('[useChatApi] prepend channel to history cache failed:', err);\n }\n }\n}\n\nfunction appendPostsToThreadCache(client: ReturnType<typeof useApolloClient>, sessionId: string, posts: MinimalPost[]) {\n const incoming = posts.filter((post) => post?.id);\n if (!sessionId || incoming.length === 0) return;\n try {\n client.cache.updateQuery(\n { query: MessagesDocument, variables: getThreadMessagesQueryVariables(sessionId) },\n (data: any) => {\n const existing = (data?.messages?.data ?? []) as MinimalPost[];\n const seen = new Set(existing.map((post) => post?.id).filter(Boolean));\n const next = [...existing];\n for (const post of incoming) {\n if (post?.id && !seen.has(post.id)) {\n seen.add(post.id);\n next.push(post);\n }\n }\n if (next.length === existing.length) return data;\n return {\n ...(data ?? {}),\n messages: {\n ...(data?.messages ?? {}),\n __typename: data?.messages?.__typename ?? 'Messages',\n data: next,\n },\n };\n },\n );\n } catch (err) {\n console.warn('[useChatApi] append posts to thread cache failed:', err);\n }\n}\n\nexport function useChatMutations() {\n const client = useApolloClient();\n const [addChannelMutation, { loading: createChannelLoading }] = useAddChannelMutation();\n const [sendMessagesMutation, { loading: sendMessagesLoading }] = useSendMessagesMutation();\n\n const createChannel = useCallback(\n async (input?: IAccountCreateChatSessionInput): Promise<ChatSessionUI> => {\n const {\n orgName: orgNameArg,\n projectId: projectIdArg,\n ...inputForSettings\n } = (input ?? {}) as IAccountCreateChatSessionInput & {\n orgName?: string | null;\n projectId?: string | null;\n };\n const orgName =\n typeof orgNameArg === 'string' && orgNameArg.trim().length > 0 ? orgNameArg.trim() : undefined;\n const projectId =\n typeof projectIdArg === 'string' && projectIdArg.trim().length > 0 ? projectIdArg.trim() : undefined;\n\n const settings = {\n title: input?.title ?? 'New Chat',\n description: input?.systemPrompt ?? null,\n isShared: false,\n sharedSlug: null,\n isArchived: false,\n isPinned: false,\n model: input?.model ?? null,\n systemPrompt: input?.systemPrompt ?? null,\n ...inputForSettings,\n };\n\n const { data } = await addChannelMutation({\n variables: {\n channelId: input?.id ?? null,\n name: input?.title ?? 'New Chat',\n description: input?.systemPrompt ?? null,\n type: RoomType.Aiassistant,\n settings,\n ...(orgName ? { orgName } : {}),\n ...(projectId ? { projectId } : {}),\n },\n // Same as browser: write the new channel into the cached list.\n // Do not refetch GetChannelsByUserWithLastMessage on every create.\n awaitRefetchQueries: false,\n update: (cache: any, res: any) => {\n prependCreatedChannelToHistoryCache(\n cache,\n res?.data?.createChannel,\n input?.title ?? 'New Chat',\n orgName,\n );\n },\n });\n\n if (!data?.createChannel?.id) {\n throw new Error('Failed to create channel');\n }\n\n const channel = data.createChannel;\n const title = channel.title ?? input?.title ?? 'New Chat';\n const now = new Date();\n\n return {\n id: channel.id,\n title,\n createdAt: now,\n updatedAt: now,\n };\n },\n [addChannelMutation],\n );\n\n const saveMessages = useCallback(\n async (\n input: IAccountSaveChatMessagesInput,\n ): Promise<{\n userMessage: ChatMessageUI;\n assistantMessage: ChatMessageUI;\n session: ChatSessionUI;\n }> => {\n const sanitizedAssistantContent = stripModelCostHeader(input.assistantMessage.content ?? '');\n const assistantMessageWithoutContent = omitContent((input.assistantMessage as any) ?? {});\n\n let userPost: MinimalPost | null | undefined;\n try {\n const userResult = await sendMessagesMutation({\n variables: {\n channelId: input.sessionId,\n type: RoomType.Aiassistant,\n content: input.userMessage.content ?? '',\n ...(input.createdBy ? { createdBy: input.createdBy } : {}),\n extraProps: {\n type: PostTypeEnum.Aiassistant,\n role: 'user',\n attachments: input.userMessage.attachments ?? [],\n isActive: true,\n status: 'complete',\n ...(input.userMessage as any),\n ...(input.mode ? { mode: input.mode } : {}),\n },\n } as any,\n });\n userPost = userResult.data?.sendMessage as MinimalPost | undefined;\n } catch (err) {\n if (!isDuplicatePostError(err)) {\n throw err;\n }\n console.warn('[saveMessages] user post already persisted (skipping duplicate insert)');\n }\n\n /**\n * Keep the prompting user post id in metadata. `sendMessage.postId` is the id of\n * the post being created, so reusing the user post id for the assistant reply would\n * collide and leave only the user message persisted.\n */\n const userPostId = userPost?.id ?? null;\n\n let assistantPost: MinimalPost | null | undefined;\n try {\n const assistantResult = await sendMessagesMutation({\n variables: {\n channelId: input.sessionId,\n type: RoomType.Aiassistant,\n content: sanitizedAssistantContent,\n extraProps: {\n type: PostTypeEnum.Aiassistant,\n role: 'assistant',\n attachments: input.assistantMessage.attachments ?? [],\n tokenCount: input.assistantMessage.tokenCount,\n latencyMs: input.assistantMessage.latencyMs,\n model: input.assistantMessage.model,\n finishReason: (input.assistantMessage as any).finishReason ?? null,\n isActive: true,\n status: 'complete',\n ...assistantMessageWithoutContent,\n ...(userPostId ? { parentId: userPostId } : {}),\n ...(input.mode ? { mode: input.mode } : {}),\n },\n } as any,\n });\n assistantPost = assistantResult.data?.sendMessage as MinimalPost | undefined;\n } catch (err) {\n if (!isDuplicatePostError(err)) {\n throw err;\n }\n console.warn('[saveMessages] assistant post already persisted (skipping duplicate insert)');\n }\n\n if (!userPost && !assistantPost) {\n throw new Error('Failed to send messages');\n }\n\n appendPostsToThreadCache(\n client,\n input.sessionId,\n [userPost, assistantPost].filter(Boolean) as MinimalPost[],\n );\n\n const now = new Date();\n const fallbackUser: ChatMessageUI = {\n id: userPostId ?? uuidv4(),\n sessionId: input.sessionId,\n role: 'user',\n content: input.userMessage.content ?? '',\n createdAt: now,\n updatedAt: now,\n };\n const fallbackAssistant: ChatMessageUI = {\n id: uuidv4(),\n sessionId: input.sessionId,\n role: 'assistant',\n content: sanitizedAssistantContent,\n createdAt: now,\n updatedAt: now,\n tokenCount: input.assistantMessage.tokenCount,\n model: input.assistantMessage.model,\n };\n return {\n userMessage: userPost ? mapPostToChatMessageUI(userPost, input.sessionId) : fallbackUser,\n assistantMessage: assistantPost\n ? mapPostToChatMessageUI(assistantPost, input.sessionId)\n : fallbackAssistant,\n session: {\n id: input.sessionId,\n title: 'Chat',\n createdAt: now,\n updatedAt: now,\n },\n };\n },\n [client, sendMessagesMutation],\n );\n\n return {\n createChannel,\n createSession: createChannel,\n saveMessages,\n loading: { create: createChannelLoading, saveMessages: sendMessagesLoading },\n };\n}\n"],"names":["_a","_b","_c","_d","_e","uuidv4"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useChatApi.js","sources":["../../src/hooks/useChatApi.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { useApolloClient } from '@apollo/client';\nimport { AiAgentMessageRole, PostTypeEnum, RoomType, SortEnum } from 'common';\nimport {\n GetChannelsByUserWithLastMessageDocument,\n MessagesDocument,\n useAddChannelMutation,\n useGetChannelsByUserWithLastMessageQuery,\n useMessagesQuery,\n useSendMessagesMutation,\n} from 'common/graphql';\nimport type {\n IAccountCreateChatSessionInput,\n IAccountSaveChatMessagesInput as IAccountSaveChatMessagesInputBase,\n} from 'common/server';\nimport { useCallback, useMemo } from 'react';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n attachmentsFromUserContent,\n historyAttachmentTitle,\n isAttachedCaption,\n} from '../features/attachments/historyAttachmentLabel';\n\nconst MESSAGES_PAGE_LIMIT = 100;\n\n/** Same variables as web Inbox / AIAgent: list AI assistant channels for the current user. */\nexport const AI_ASSISTANT_CHANNELS_QUERY_VARS = {\n criteria: { type: RoomType.Aiassistant },\n limit: 100,\n skip: 0,\n sort: { key: 'updatedAt', value: SortEnum.Desc },\n};\n\nexport const HISTORY_PAGE_SIZE = 20;\n\n/**\n * Variables for the channels-based chat history list (`ChatHistoryLanding`).\n *\n * IMPORTANT: pass the user's org `slug` (e.g. `tarun-upadhyay-qraw`) so the\n * `channelsByUser` resolver's `$in: [criteria.orgName, orgId]` includes\n * channels stored under the slug. When `criteria.orgName` is omitted, the\n * `$in` collapses to just `[orgId]` and channels saved with the slug as\n * `orgName` (the mobile create path) never match. That's the cause of the\n * silently-empty history screen.\n *\n * Kept as a builder (not a constant) because the slug varies per user and\n * because Apollo treats different `variables` as different cached entries —\n * if the create mutation refetches a no-orgName variant, the orgName-variant\n * the screen watches stays stale.\n */\nexport function getHistoryChannelsQueryVariables(orgName?: string | null, options?: { skip?: number; limit?: number }) {\n const trimmedOrg = typeof orgName === 'string' && orgName.trim().length > 0 ? orgName.trim() : undefined;\n return {\n criteria: {\n type: RoomType.Aiassistant,\n ...(trimmedOrg ? { orgName: trimmedOrg } : {}),\n },\n limit: options?.limit ?? HISTORY_PAGE_SIZE,\n skip: options?.skip ?? 0,\n sort: { key: 'updatedAt' as const, value: SortEnum.Desc },\n };\n}\n\n/** @deprecated Use {@link getHistoryChannelsQueryVariables} so `orgName` is included. */\nexport const HISTORY_QUERY_BASE = getHistoryChannelsQueryVariables();\n\nfunction normalizeOptionalString(value: string | null | undefined): string | undefined {\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;\n}\n\n/** Cache slots the history list watches — used to prepend a created channel without refetching. */\nexport function getChatHistoryChannelRefetchQueries(orgName?: string | null) {\n const trimmedOrg = normalizeOptionalString(orgName);\n return [\n { query: GetChannelsByUserWithLastMessageDocument, variables: AI_ASSISTANT_CHANNELS_QUERY_VARS },\n ...(trimmedOrg\n ? [\n {\n query: GetChannelsByUserWithLastMessageDocument,\n variables: getHistoryChannelsQueryVariables(trimmedOrg),\n },\n ]\n : []),\n { query: GetChannelsByUserWithLastMessageDocument, variables: HISTORY_QUERY_BASE },\n ];\n}\n\nfunction getThreadMessagesQueryVariables(sessionId: string) {\n return {\n channelId: sessionId,\n limit: MESSAGES_PAGE_LIMIT,\n skip: 0,\n sort: { key: 'createdAt' as const, value: SortEnum.Asc },\n };\n}\n\n/**\n * Variables for the chat-history feed on the mobile `ChatHistory` screen.\n *\n * First page uses `HISTORY_PAGE_SIZE` (20) posts; \"Load older\" paginates by post\n * `skip` in increments of 20. Rows are still one per channel (collapsed from posts).\n *\n * This query intentionally hits `messages` (not `channelsByUser`) — the same\n * pattern the web sidebar uses (`useNewChatPageHistorySessions`). Reasons:\n * 1. `channelsByUser` is server-side gated by an injected `orgName` /\n * `members` filter that can mismatch when channels were stored with an\n * org slug while the resolver injects the org id. The `messages`\n * resolver filters Post directly by `editedBy: accountId`, so the\n * user's own AI-assistant posts always show up.\n * 2. The user-authored post IS the conversation's natural title — no need\n * to walk `lastMessage.propsConfiguration.contents.parent` to recover\n * the original prompt.\n *\n * - `type: AIASSISTANT` scopes to AI chat (not direct/service rooms).\n * - `props.role: 'user'` selects only the user's turns. The assistant reply\n * is ignored here; it would override the title with the agent's words.\n * - `editedBy: accountUserId` scopes to the current user's own posts,\n * independent of channel membership / org name.\n */\nexport function getChatHistoryMessagesQueryVariables(\n accountUserId: string,\n options?: { skip?: number; limit?: number },\n) {\n return {\n limit: options?.limit ?? HISTORY_PAGE_SIZE,\n skip: options?.skip ?? 0,\n sort: { key: 'updatedAt' as const, value: SortEnum.Desc },\n type: PostTypeEnum.Aiassistant,\n editedBy: accountUserId,\n props: { role: 'user' },\n };\n}\n\nexport type ChatHistoryMode = 'chat' | 'deep-search' | 'build';\n\nexport interface ChatHistorySession {\n /** Channel id — used to navigate to the Chat screen. */\n channelId: string;\n /** User's most recent prompt in this channel (used as the row title). */\n title: string;\n /** Second line: latest post `message` field (same as Manus subtitle). */\n preview: string;\n /** Conversation mode (chat / deep-search / build), inferred from channel title or last message. */\n mode: ChatHistoryMode;\n /** Most-recent activity timestamp (sort key + bucket key for Today/Yesterday/…). */\n updatedAt: Date;\n createdAt: Date;\n /**\n * True when no concrete prompt was recoverable (no parent, no user turn, no\n * meaningful channel.title). UI renders the title in a quieter style.\n */\n isPlaceholder: boolean;\n /** First turn was a file send (`Attached: …`). Row uses a paperclip tile + \"New chat\". */\n isAttachment?: boolean;\n}\n\n/**\n * Collapse a list of user-authored AI assistant posts (newest first) into one\n * row per channel. First post per `channel.id` wins the title, which — because\n * the query is sorted by `updatedAt DESC` — is the user's latest prompt in\n * that channel. Posts whose `channel.id` is missing (unexpected, but possible\n * if the resolver omits the relation) are skipped.\n */\nexport function chatHistorySessionsFromMessages(\n data: { messages?: { data?: unknown[] | null } | null } | null | undefined,\n): ChatHistorySession[] {\n const rows = data?.messages?.data;\n if (!rows?.length) return [];\n\n const seen = new Set<string>();\n const sessions: ChatHistorySession[] = [];\n\n for (const post of rows as any[]) {\n const channelId = post?.channel?.id ? String(post.channel.id) : '';\n if (!channelId || seen.has(channelId)) continue;\n\n const rawTitle = String(post?.message ?? '')\n .replace(/\\s+/g, ' ')\n .trim();\n if (/^thinking[.…]*$/i.test(rawTitle)) continue;\n\n seen.add(channelId);\n const updatedAt = post?.updatedAt ? new Date(post.updatedAt) : new Date();\n const createdAt = post?.createdAt ? new Date(post.createdAt) : updatedAt;\n const isAttachment = isAttachedCaption(rawTitle);\n const title = isAttachment ? historyAttachmentTitle(rawTitle) : rawTitle || 'New chat';\n\n sessions.push({\n channelId,\n title,\n preview: '',\n mode: 'chat',\n updatedAt,\n createdAt,\n isPlaceholder: !rawTitle && !isAttachment,\n isAttachment,\n });\n }\n\n return sessions;\n}\n\n/**\n * Mobile parity hook for the web sidebar's `useNewChatPageHistorySessions`.\n *\n * Returns one row per channel where the user has authored at least one AI assistant\n * post, with the title taken from that user's latest prompt. Skipped when\n * `accountUserId` isn't known yet (we don't want to fire a query without it).\n */\nexport function useChatHistorySessionsFromMessages(\n accountUserId: string | null | undefined,\n options?: { skip?: boolean },\n) {\n const skip = options?.skip || !accountUserId;\n const { data, loading, error, refetch } = useMessagesQuery({\n variables: accountUserId ? getChatHistoryMessagesQueryVariables(accountUserId, { limit: 100 }) : undefined,\n skip,\n // cache-first + `messages` typePolicy (keyed by editedBy/type/props).\n // Later visits read the cache — no repeated network hit.\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n context: { cacheKey: 'new-chat-history-messages' },\n });\n\n const sessions = useMemo(() => chatHistorySessionsFromMessages(data), [data]);\n const sourcePostCount = data?.messages?.data?.length ?? 0;\n\n return { sessions, loading, error, refetch, sourcePostCount };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Channels-based chat history (parent + lastMessage) */\n/* -------------------------------------------------------------------------- */\n\ninterface ChannelLastMessageLike {\n message?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n props?: { role?: string | null; mode?: string | null } | null;\n propsConfiguration?: {\n contents?: {\n role?: string | null;\n mode?: string | null;\n template?: string | null;\n parent?: {\n message?: string | null;\n props?: { role?: string | null } | null;\n } | null;\n fragment?: {\n title?: string | null;\n sandboxUrl?: string | null;\n sandboxId?: string | null;\n } | null;\n } | null;\n content?: { role?: string | null; mode?: string | null } | null;\n } | null;\n}\n\ninterface ChannelLike {\n id?: string | null;\n type?: string | null;\n displayName?: string | null;\n title?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n lastMessage?: ChannelLastMessageLike | null;\n}\n\nfunction getLastMessageRole(lastMessage: ChannelLastMessageLike | null | undefined): string {\n return String(\n lastMessage?.propsConfiguration?.contents?.role ??\n lastMessage?.propsConfiguration?.content?.role ??\n lastMessage?.props?.role ??\n '',\n ).toUpperCase();\n}\n\nfunction getParentUserPrompt(lastMessage: ChannelLastMessageLike | null | undefined): string {\n const parent = lastMessage?.propsConfiguration?.contents?.parent;\n if (!parent) return '';\n return String(parent?.message ?? '').trim();\n}\n\nfunction isBuildLastMessage(lastMessage: ChannelLastMessageLike | null | undefined): boolean {\n if (!lastMessage) return false;\n const contents = lastMessage.propsConfiguration?.contents;\n const mode = String(\n contents?.mode ?? lastMessage.propsConfiguration?.content?.mode ?? lastMessage?.props?.mode ?? '',\n ).toLowerCase();\n if (mode === 'build' || mode === 'workflow') return true;\n const fragment = contents?.fragment;\n if (fragment?.sandboxUrl || fragment?.sandboxId) return true;\n if (String(contents?.template ?? '').trim()) return true;\n return false;\n}\n\nfunction detectMode(channel: ChannelLike): ChatHistoryMode {\n if (isBuildLastMessage(channel?.lastMessage)) {\n return 'build';\n }\n const display = String(channel?.displayName ?? '').toLowerCase();\n const title = String(channel?.title ?? '').toLowerCase();\n if (display.startsWith('build-channel') || title.startsWith('build-channel') || title.startsWith('build channel')) {\n return 'build';\n }\n const parent = getParentUserPrompt(channel?.lastMessage).toLowerCase();\n if (/^build\\s*me\\s*:/.test(parent)) {\n return 'build';\n }\n if (display.startsWith('deep-search') || title.startsWith('deep search') || title.startsWith('deep-search')) {\n return 'deep-search';\n }\n return 'chat';\n}\n\n/**\n * Drop the internal slug we use as `channel.title` for server-side mode detection\n * (`chat-channel-<uuid>` / `deep-search-<uuid>`) so it doesn't leak into the row\n * label. The server sometimes also reformats this slug into `displayName` as\n * title-cased text with spaces (e.g. `\"Deep Search b64be4f7 9fe6 …\"`) — those\n * are equally machine-generated and must NOT be shown to the user.\n *\n * Pattern accepts:\n * • `deep-search-<uuid>` / `chat-channel-<uuid>` (raw, mode signal)\n * • `Deep Search <uuid>` / `Chat Channel <uuid>` (display-cased, server-reformatted)\n * • UUID may use hyphens, spaces, or be partially truncated as long as the\n * trailing chunk is hex.\n */\nfunction cleanChannelTitle(rawTitle: string | null | undefined): string {\n const t = String(rawTitle ?? '').trim();\n if (!t) return '';\n if (/^(chat[\\s-]channel|deep[\\s-]search|build[\\s-]channel)[\\s-][0-9a-f][0-9a-f\\s-]{7,}\\.?$/i.test(t)) return '';\n // Creation defaults carry no meaning either (parity with the browser sidebar).\n if (/^(new chat|workflow|deep search)$/i.test(t)) return '';\n return t;\n}\n\n/** `[Active connectors: …]` routing prefix on persisted gateway user posts. */\nconst ACTIVE_CONNECTORS_PREFIX_RE = /^\\s*\\[Active connectors:[^\\]]*\\]\\s*/i;\n\nfunction cleanMessageText(raw: string): string {\n return raw.replace(ACTIVE_CONNECTORS_PREFIX_RE, '').replace(/\\s+/g, ' ').trim();\n}\n\n/** Status / tool stubs that must not become a history title or subtitle. */\nfunction isTransientHistoryText(text: string): boolean {\n const t = cleanMessageText(text);\n if (!t) return true;\n if (/^thinking[.…]*$/i.test(t)) return true;\n if (/^let me check on that requested skill/i.test(t)) return true;\n if (/^(working on it|one moment|just a (sec|second|moment))[.…]*$/i.test(t)) return true;\n if (/^[⚙️⚠]/.test(t)) return true;\n return false;\n}\n\nfunction looksLikeAssistantReply(text: string, role: string): boolean {\n if (role === 'ASSISTANT' || role === 'AI' || role === 'BOT' || role === 'AGENT') return true;\n if (role === 'USER') return false;\n const t = text.trim();\n if (/^(let me |i'll |i will |sure[,.] |here's |here is )/i.test(t)) return true;\n if (t.length > 180) return true;\n return false;\n}\n\nfunction cleanHistoryPreview(raw: string): string {\n let t = cleanMessageText(raw);\n t = t.replace(/^(thinking[.…]*\\s*)+/i, '').trim();\n t = t.replace(/^let me check on that requested skill[^\\n.!?]*[.!?-]?\\s*/i, '').trim();\n t = t.replace(/^(?:⚙️[^\\n]*\\n)+\\s*/g, '').trim();\n return t;\n}\n\n/**\n * Map one channel into a session row (Manus-style two-line list):\n *\n * **Title (line 1):** `lastMessage.propsConfiguration.contents.parent.message`\n * when present (the user turn the thread is anchored on). Otherwise fall back\n * to the last post body if that post is still a user message, then a\n * machine-slug-stripped channel title, then a machine-slug-stripped\n * `displayName`, then `\"Thinking…\"`. Machine slugs (`deep-search-<uuid>`,\n * `chat-channel-<uuid>`, and their server-reformatted display variants)\n * are filtered via `cleanChannelTitle`, so they never reach the row.\n *\n * **Preview (line 2):** `lastMessage.message` as returned by the API (trimmed,\n * whitespace collapsed). Agent errors that start with `⚠` stay visible in the\n * subtitle, matching the reference UI.\n *\n * If preview text equals the title after trim, the second line is omitted\n * (single-line channel, no duplicate).\n */\nexport function buildSessionFromChannel(channel: ChannelLike): ChatHistorySession | null {\n const channelId = String(channel?.id ?? '');\n if (!channelId) return null;\n\n const lastMessage = channel?.lastMessage ?? null;\n const lastMessageRole = getLastMessageRole(lastMessage);\n const parentTrimmed = cleanHistoryPreview(getParentUserPrompt(lastMessage));\n const lastBody = cleanHistoryPreview(String(lastMessage?.message ?? ''));\n const userTurn = lastMessageRole === 'USER' && lastBody ? lastBody : '';\n const cleanedChannelTitle = cleanChannelTitle(channel?.title);\n /**\n * Apply the same machine-slug cleaner to `displayName`. The server\n * sometimes derives displayName from the title (`\"deep-search-<uuid>\"`\n * → `\"Deep Search <uuid>\"`), so without this the slug bypasses\n * `cleanedChannelTitle` and lands directly in the row label.\n */\n const cleanedDisplayName = cleanChannelTitle(channel?.displayName);\n\n let resolvedTitle = cleanedChannelTitle || parentTrimmed || userTurn || cleanedDisplayName;\n if (\n !resolvedTitle &&\n lastBody &&\n !isTransientHistoryText(lastBody) &&\n !looksLikeAssistantReply(lastBody, lastMessageRole)\n ) {\n resolvedTitle = lastBody;\n }\n if (!resolvedTitle) {\n const rawDefault = String(channel?.title ?? '').trim();\n if (rawDefault && !/^(chat[\\s-]channel|deep[\\s-]search)[\\s-][0-9a-f][0-9a-f\\s-]{7,}\\.?$/i.test(rawDefault)) {\n resolvedTitle = rawDefault;\n }\n }\n const isAttachment =\n isAttachedCaption(resolvedTitle) || isAttachedCaption(parentTrimmed) || isAttachedCaption(userTurn);\n if (isAttachment) resolvedTitle = historyAttachmentTitle(resolvedTitle);\n const isPlaceholder = !resolvedTitle;\n if (isPlaceholder) resolvedTitle = 'New chat';\n\n let preview = lastBody;\n if (\n isTransientHistoryText(preview) ||\n isAttachedCaption(preview) ||\n preview === resolvedTitle ||\n preview === parentTrimmed\n ) {\n preview = '';\n }\n if (lastMessageRole === 'USER' && !looksLikeAssistantReply(lastBody, lastMessageRole)) {\n preview = '';\n }\n\n const sortAt = (() => {\n const candidates = [channel?.updatedAt, lastMessage?.updatedAt, lastMessage?.createdAt, channel?.createdAt];\n for (const candidate of candidates) {\n if (candidate) {\n const t = new Date(candidate).getTime();\n if (Number.isFinite(t) && t > 0) return t;\n }\n }\n return Date.now();\n })();\n\n const createdAtRaw = channel?.createdAt ? new Date(channel.createdAt).getTime() : sortAt;\n\n return {\n channelId,\n title: resolvedTitle,\n preview,\n mode: detectMode(channel),\n updatedAt: new Date(sortAt),\n createdAt: new Date(Number.isFinite(createdAtRaw) ? createdAtRaw : sortAt),\n isPlaceholder,\n isAttachment,\n };\n}\n\n/** Collapse a `channelsByUser` response into session rows for the history list. */\nexport function chatHistorySessionsFromChannels(\n data: { channelsByUser?: (ChannelLike | null)[] | null } | null | undefined,\n): ChatHistorySession[] {\n const channels = (data?.channelsByUser ?? []) as (ChannelLike | null)[];\n const now = Date.now();\n return channels\n .filter((c): c is ChannelLike => Boolean(c?.id) && (!c?.type || c.type === RoomType.Aiassistant))\n .map((c) => buildSessionFromChannel(c))\n .filter((row): row is ChatHistorySession => row !== null)\n .filter((row) => {\n if (!row.isPlaceholder) return true;\n if (row.preview) return true;\n return now - row.updatedAt.getTime() < 2 * 60 * 1000;\n })\n .sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());\n}\n\n/**\n * Overlay user-authored prompts from `messages` onto channel rows whose\n * lastMessage never carried `parent.message` (typical cdecli/gateway chats).\n */\nexport function enrichHistorySessionsWithUserPrompts(\n fromChannels: ChatHistorySession[],\n fromMessages: ChatHistorySession[],\n): ChatHistorySession[] {\n if (!fromMessages.length) return fromChannels;\n const byId = new Map(fromMessages.map((session) => [session.channelId, session]));\n return fromChannels.map((row) => {\n const fromUser = byId.get(row.channelId);\n if (!fromUser?.title || isTransientHistoryText(fromUser.title)) return row;\n const titleMissing = row.isPlaceholder || isTransientHistoryText(row.title) || /^new chat$/i.test(row.title);\n if (!titleMissing) {\n return row.preview ? row : { ...row, preview: fromUser.preview || row.preview };\n }\n return {\n ...row,\n title: fromUser.title,\n preview: row.preview && !isTransientHistoryText(row.preview) ? row.preview : fromUser.preview,\n isPlaceholder: false,\n isAttachment: fromUser.isAttachment || row.isAttachment,\n };\n });\n}\n\n/**\n * Chat history feed driven by `channelsByUser`. Each row: parent prompt as title,\n * `lastMessage.message` as subtitle (Manus-style), when the API provides them.\n *\n * Caller MUST pass `orgName` (the org slug). Without it, the resolver only\n * matches channels whose `orgName` field equals the user's `orgId`, which is\n * never the case for mobile-created channels (those store the slug). The hook\n * suspends the query (`skip: true`) until `orgName` is known, so we never\n * fire a guaranteed-empty request.\n *\n * Pagination is by channel count (one channel = one row in this query),\n * unlike the messages-based path which paginates by raw post rows.\n */\nexport function useChatHistorySessionsFromChannels(orgName: string | null | undefined, options?: { skip?: boolean }) {\n const skip = options?.skip || !orgName;\n const variables = useMemo(() => getHistoryChannelsQueryVariables(orgName), [orgName]);\n\n const { data, loading, error, refetch } = useGetChannelsByUserWithLastMessageQuery({\n variables,\n skip,\n // cache-first + `channelsByUser` typePolicy (keyArgs drop skip/limit/sort).\n // Later navigations read the canonical list from cache — no repeated\n // GetChannelsByUserWithLastMessage. Freshness comes from pull-to-refresh\n // / createChannel cache writes, not per-visit network hits.\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n context: { cacheKey: 'chat-history-channels-list' },\n });\n\n const sessions = useMemo(() => chatHistorySessionsFromChannels(data), [data]);\n const sourceChannelCount = data?.channelsByUser?.length ?? 0;\n /**\n * `sessionsLoaded` means \"we have data we can show\", regardless of whether a\n * background revalidation is still in flight. Same contract as `messagesLoaded`\n * in `useChatMessages` — lets the screen show the cached list (or empty state)\n * immediately on revisit instead of flashing a loader for the network round-trip.\n */\n const sessionsLoaded = data !== undefined;\n\n return { sessions, loading, sessionsLoaded, error, refetch, sourceChannelCount };\n}\n\nfunction stripModelCostHeader(content: string): string {\n const normalized = content.replace(/\\r\\n/g, '\\n');\n return normalized.replace(\n /^\\s*(?:[^\\w\\n]+\\s*)?[a-z0-9][a-z0-9._-]*\\s*\\(\\s*\\$[\\d.]+\\s*\\/\\s*MTok\\s+in\\s*\\)\\s*\\n+/i,\n '',\n );\n}\n\nfunction sanitizeAssistantContentByRole(role: unknown, content: string): string {\n return role === 'assistant' ? stripModelCostHeader(content) : content;\n}\n\nfunction omitContent<T extends Record<string, any>>(value: T | null | undefined): Omit<T, 'content'> {\n const clone = { ...(value ?? {}) } as Record<string, any>;\n delete clone.content;\n return clone as Omit<T, 'content'>;\n}\n\nexport interface ChatSessionUI {\n id: string;\n title: string;\n createdAt: Date;\n updatedAt: Date;\n messageCount?: number;\n}\n\nexport function useChatSessions(options?: { includeArchived?: boolean; skip?: boolean }) {\n const { data, loading, error, refetch } = useGetChannelsByUserWithLastMessageQuery({\n variables: AI_ASSISTANT_CHANNELS_QUERY_VARS,\n skip: options?.skip,\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n });\n\n const sessions: ChatSessionUI[] = useMemo(() => {\n const channels = data?.channelsByUser ?? [];\n return channels\n .filter((c): c is NonNullable<typeof c> => Boolean(c?.id))\n .map((channel) => ({\n id: channel.id,\n title: channel.title || channel.displayName || 'New Chat',\n createdAt: new Date(channel.createdAt ?? Date.now()),\n updatedAt: new Date(channel.updatedAt ?? Date.now()),\n messageCount: undefined,\n }));\n }, [data]);\n\n return { sessions, loading, error, refetch };\n}\n\nexport interface ChatMessageUI {\n id: string;\n sessionId: string;\n role: 'user' | 'assistant' | 'system';\n content: string;\n attachments?: Array<{ id: string; name: string; type: string; mimeType?: string; size?: number; url?: string }>;\n tokenCount?: number;\n model?: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\ninterface MinimalFile {\n id?: string | null;\n name?: string | null;\n mimeType?: string | null;\n size?: number | null;\n url?: string | null;\n}\n\ninterface MinimalPost {\n id?: string | null;\n parentId?: string | null;\n message?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n channel?: { id?: string | null } | null;\n files?: { data?: MinimalFile[] | null } | null;\n replies?: { data?: MinimalPost[] | null } | null;\n props?: { role?: string | null; tokenCount?: number | null; model?: string | null } | null;\n propsConfiguration?: {\n contents?: { role?: string | null } | null;\n content?: { role?: string | null } | null;\n } | null;\n}\n\nfunction postTimestamp(value: string | null | undefined): number {\n if (!value) return 0;\n const t = new Date(value).getTime();\n return Number.isFinite(t) ? t : 0;\n}\n\n/**\n * Same flatten as account/browser `useChatApi`: merge roots + nested\n * `replies.data`, then emit each root followed by its children (oldest first).\n * Omitting this left assistant replies unordered or sitting above the prompt.\n */\nfunction flattenPostsWithReplies(posts: MinimalPost[], fallbackChannelId: string): ChatMessageUI[] {\n const getId = (post: MinimalPost) => String(post?.id ?? '');\n const nestedReplies = posts.flatMap((post) => (Array.isArray(post?.replies?.data) ? post.replies.data : []));\n const byId = new Map<string, MinimalPost>();\n for (const post of [...posts, ...nestedReplies]) {\n const id = getId(post);\n if (id) byId.set(id, post);\n }\n const uniq = Array.from(byId.values());\n const ids = new Set(uniq.map(getId));\n const roots = uniq.filter((post) => !post?.parentId || !ids.has(String(post.parentId)));\n const replies = uniq.filter((post) => post?.parentId && ids.has(String(post.parentId)));\n // Order by timestamp only (like account/browser). Array.sort is stable, so posts\n // that share a `createdAt` - a user prompt and its assistant reply are commonly\n // persisted with the same millisecond - keep the backend's `createdAt ASC` order\n // instead of being re-shuffled. An id tiebreaker here sorted such ties by UUID\n // string, which could float the assistant reply above the prompt.\n const byTime = (a: MinimalPost, b: MinimalPost) => postTimestamp(a.createdAt) - postTimestamp(b.createdAt);\n\n const ordered: MinimalPost[] = [];\n for (const root of [...roots].sort(byTime)) {\n const rootId = getId(root);\n ordered.push(root);\n ordered.push(...replies.filter((reply) => String(reply.parentId) === rootId).sort(byTime));\n }\n const seen = new Set(ordered.map(getId));\n ordered.push(...replies.filter((reply) => !seen.has(getId(reply))).sort(byTime));\n\n const out: ChatMessageUI[] = [];\n const emitted = new Set<string>();\n for (const post of ordered) {\n const id = getId(post);\n if (!id || emitted.has(id)) continue;\n emitted.add(id);\n out.push(mapPostToChatMessageUI(post, fallbackChannelId));\n }\n return out;\n}\n\nfunction mapPostToChatMessageUI(post: MinimalPost, fallbackChannelId: string): ChatMessageUI {\n const props = (post.props ?? {}) as Record<string, any>;\n const contents = post.propsConfiguration?.contents ?? {};\n const roleRaw = props.role ?? contents.role ?? post.propsConfiguration?.content?.role;\n let role: ChatMessageUI['role'] = 'assistant';\n if (roleRaw === 'user' || roleRaw === AiAgentMessageRole.User) role = 'user';\n else if (roleRaw === 'assistant' || roleRaw === AiAgentMessageRole.Assistant) role = 'assistant';\n else if (roleRaw === 'system') role = 'system';\n\n const rawContent = post?.message ?? '';\n const content = sanitizeAssistantContentByRole(role, rawContent);\n\n const fromFiles = (post?.files?.data ?? []).map((file) => ({\n id: file.id ?? uuidv4(),\n name: file.name ?? 'file',\n type: (typeof file.mimeType === 'string' && file.mimeType.startsWith('image/') ? 'screenshot' : 'file') as\n | 'screenshot'\n | 'file',\n mimeType: file.mimeType ?? undefined,\n size: file.size ?? undefined,\n url: file.url ?? undefined,\n }));\n const fromProps = Array.isArray(props.attachments)\n ? props.attachments.map((file: MinimalFile & { type?: string }) => ({\n id: file.id ?? uuidv4(),\n name: file.name ?? 'file',\n type: (file.type === 'screenshot' ||\n (typeof file.mimeType === 'string' && file.mimeType.startsWith('image/'))\n ? 'screenshot'\n : 'file') as 'screenshot' | 'file',\n mimeType: file.mimeType ?? undefined,\n size: file.size ?? undefined,\n url: file.url ?? undefined,\n }))\n : [];\n const attachments = attachmentsFromUserContent(content, fromFiles.length ? fromFiles : fromProps);\n\n return {\n id: post?.id ?? uuidv4(),\n sessionId: post?.channel?.id ?? fallbackChannelId,\n role,\n content,\n attachments,\n tokenCount: props.tokenCount ?? undefined,\n model: props.model ?? undefined,\n createdAt: post?.createdAt ? new Date(post.createdAt) : new Date(0),\n updatedAt: post?.updatedAt ? new Date(post.updatedAt) : new Date(0),\n };\n}\n\nexport function useChatMessages(sessionId: string | null, options?: { skip?: boolean }) {\n const { data, loading, error, refetch } = useMessagesQuery({\n variables: sessionId ? getThreadMessagesQueryVariables(sessionId) : undefined,\n skip: !sessionId || options?.skip,\n // cache-first + `messages` typePolicy (keyed by channelId). Opening a thread\n // that was already loaded does not refetch. New channels still hit the\n // network once. saveMessages writes new posts into this cache slot.\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n /**\n * Cache key is per-channel so switching sessions doesn't read another channel's response.\n * Keeping this as a constant ('messages-list') used to cause cross-session bleed in the\n * custom Apollo link before reaching the normalized cache.\n */\n context: { cacheKey: sessionId ? `messages-list:${sessionId}` : 'messages-list' },\n });\n\n /**\n * `messagesLoaded` means \"we have data we can show\". cache-first fills `data`\n * synchronously on a hit so revisiting a thread does not flash a loader.\n */\n const messagesLoaded = data !== undefined;\n\n const messages: ChatMessageUI[] = useMemo(() => {\n if (!sessionId) return [];\n const rows = (data?.messages?.data ?? []) as MinimalPost[];\n return flattenPostsWithReplies(rows, sessionId);\n }, [data, sessionId]);\n\n return { messages, loading, messagesLoaded, error, refetch };\n}\n\nexport type IAccountSaveChatMessagesInput = IAccountSaveChatMessagesInputBase & {\n mode?: 'plan' | 'build';\n createdBy?: string;\n};\n\n/** Backend/gateway may have already inserted the post (E11000 duplicate `_id`). */\nfunction isDuplicatePostError(error: unknown): boolean {\n const parts: string[] = [];\n if (error && typeof error === 'object' && 'graphQLErrors' in error) {\n const gqlErrors = (error as { graphQLErrors?: Array<{ message?: string }> }).graphQLErrors ?? [];\n parts.push(...gqlErrors.map((e) => e?.message ?? ''));\n }\n if (error instanceof Error) {\n parts.push(error.message);\n } else if (error != null) {\n parts.push(String(error));\n }\n const msg = parts.join(' ');\n return /E11000|duplicate key/i.test(msg);\n}\n\nfunction prependCreatedChannelToHistoryCache(\n cache: any,\n created: { id?: string | null; title?: string | null; type?: string | null } | null | undefined,\n fallbackTitle: string,\n orgName?: string | null,\n) {\n if (!created?.id) return;\n const nowIso = new Date().toISOString();\n // Fill every field the history query selects so cache-first stays complete\n // (a partial Channel makes the whole channelsByUser read a miss).\n const optimisticChannel = {\n __typename: 'Channel',\n id: created.id,\n title: created.title ?? fallbackTitle,\n description: null,\n type: created.type ?? RoomType.Aiassistant,\n displayName: null,\n members: [],\n creator: null,\n lastMessage: null,\n createdAt: nowIso,\n updatedAt: nowIso,\n };\n for (const { query, variables } of getChatHistoryChannelRefetchQueries(orgName)) {\n try {\n cache.updateQuery({ query, variables }, (data: any) => {\n const list = (data?.channelsByUser ?? []) as any[];\n if (list.some((c) => c?.id === created.id)) return data;\n return { ...(data ?? {}), channelsByUser: [optimisticChannel, ...list] };\n });\n } catch (err) {\n console.warn('[useChatApi] prepend channel to history cache failed:', err);\n }\n }\n}\n\nfunction appendPostsToThreadCache(client: ReturnType<typeof useApolloClient>, sessionId: string, posts: MinimalPost[]) {\n const incoming = posts.filter((post) => post?.id);\n if (!sessionId || incoming.length === 0) return;\n try {\n client.cache.updateQuery(\n { query: MessagesDocument, variables: getThreadMessagesQueryVariables(sessionId) },\n (data: any) => {\n const existing = (data?.messages?.data ?? []) as MinimalPost[];\n const seen = new Set(existing.map((post) => post?.id).filter(Boolean));\n const next = [...existing];\n for (const post of incoming) {\n if (post?.id && !seen.has(post.id)) {\n seen.add(post.id);\n next.push(post);\n }\n }\n if (next.length === existing.length) return data;\n return {\n ...(data ?? {}),\n messages: {\n ...(data?.messages ?? {}),\n __typename: data?.messages?.__typename ?? 'Messages',\n data: next,\n },\n };\n },\n );\n } catch (err) {\n console.warn('[useChatApi] append posts to thread cache failed:', err);\n }\n}\n\nexport function useChatMutations() {\n const client = useApolloClient();\n const [addChannelMutation, { loading: createChannelLoading }] = useAddChannelMutation();\n const [sendMessagesMutation, { loading: sendMessagesLoading }] = useSendMessagesMutation();\n\n const createChannel = useCallback(\n async (input?: IAccountCreateChatSessionInput): Promise<ChatSessionUI> => {\n const {\n orgName: orgNameArg,\n projectId: projectIdArg,\n ...inputForSettings\n } = (input ?? {}) as IAccountCreateChatSessionInput & {\n orgName?: string | null;\n projectId?: string | null;\n };\n const orgName =\n typeof orgNameArg === 'string' && orgNameArg.trim().length > 0 ? orgNameArg.trim() : undefined;\n const projectId =\n typeof projectIdArg === 'string' && projectIdArg.trim().length > 0 ? projectIdArg.trim() : undefined;\n\n const settings = {\n title: input?.title ?? 'New Chat',\n description: input?.systemPrompt ?? null,\n isShared: false,\n sharedSlug: null,\n isArchived: false,\n isPinned: false,\n model: input?.model ?? null,\n systemPrompt: input?.systemPrompt ?? null,\n ...inputForSettings,\n };\n\n const { data } = await addChannelMutation({\n variables: {\n channelId: input?.id ?? null,\n name: input?.title ?? 'New Chat',\n description: input?.systemPrompt ?? null,\n type: RoomType.Aiassistant,\n settings,\n ...(orgName ? { orgName } : {}),\n ...(projectId ? { projectId } : {}),\n },\n // Same as browser: write the new channel into the cached list.\n // Do not refetch GetChannelsByUserWithLastMessage on every create.\n awaitRefetchQueries: false,\n update: (cache: any, res: any) => {\n prependCreatedChannelToHistoryCache(\n cache,\n res?.data?.createChannel,\n input?.title ?? 'New Chat',\n orgName,\n );\n },\n });\n\n if (!data?.createChannel?.id) {\n throw new Error('Failed to create channel');\n }\n\n const channel = data.createChannel;\n const title = channel.title ?? input?.title ?? 'New Chat';\n const now = new Date();\n\n return {\n id: channel.id,\n title,\n createdAt: now,\n updatedAt: now,\n };\n },\n [addChannelMutation],\n );\n\n const saveMessages = useCallback(\n async (\n input: IAccountSaveChatMessagesInput,\n ): Promise<{\n userMessage: ChatMessageUI;\n assistantMessage: ChatMessageUI;\n session: ChatSessionUI;\n }> => {\n const sanitizedAssistantContent = stripModelCostHeader(input.assistantMessage.content ?? '');\n const assistantMessageWithoutContent = omitContent((input.assistantMessage as any) ?? {});\n\n let userPost: MinimalPost | null | undefined;\n try {\n const userResult = await sendMessagesMutation({\n variables: {\n channelId: input.sessionId,\n type: RoomType.Aiassistant,\n content: input.userMessage.content ?? '',\n ...(input.createdBy ? { createdBy: input.createdBy } : {}),\n extraProps: {\n type: PostTypeEnum.Aiassistant,\n role: 'user',\n attachments: input.userMessage.attachments ?? [],\n isActive: true,\n status: 'complete',\n ...(input.userMessage as any),\n ...(input.mode ? { mode: input.mode } : {}),\n },\n } as any,\n });\n userPost = userResult.data?.sendMessage as MinimalPost | undefined;\n } catch (err) {\n if (!isDuplicatePostError(err)) {\n throw err;\n }\n console.warn('[saveMessages] user post already persisted (skipping duplicate insert)');\n }\n\n /**\n * Keep the prompting user post id in metadata. `sendMessage.postId` is the id of\n * the post being created, so reusing the user post id for the assistant reply would\n * collide and leave only the user message persisted.\n */\n const userPostId = userPost?.id ?? null;\n\n let assistantPost: MinimalPost | null | undefined;\n try {\n const assistantResult = await sendMessagesMutation({\n variables: {\n channelId: input.sessionId,\n type: RoomType.Aiassistant,\n content: sanitizedAssistantContent,\n extraProps: {\n type: PostTypeEnum.Aiassistant,\n role: 'assistant',\n attachments: input.assistantMessage.attachments ?? [],\n tokenCount: input.assistantMessage.tokenCount,\n latencyMs: input.assistantMessage.latencyMs,\n model: input.assistantMessage.model,\n finishReason: (input.assistantMessage as any).finishReason ?? null,\n isActive: true,\n status: 'complete',\n ...assistantMessageWithoutContent,\n ...(userPostId ? { parentId: userPostId } : {}),\n ...(input.mode ? { mode: input.mode } : {}),\n },\n } as any,\n });\n assistantPost = assistantResult.data?.sendMessage as MinimalPost | undefined;\n } catch (err) {\n if (!isDuplicatePostError(err)) {\n throw err;\n }\n console.warn('[saveMessages] assistant post already persisted (skipping duplicate insert)');\n }\n\n if (!userPost && !assistantPost) {\n throw new Error('Failed to send messages');\n }\n\n appendPostsToThreadCache(\n client,\n input.sessionId,\n [userPost, assistantPost].filter(Boolean) as MinimalPost[],\n );\n\n const now = new Date();\n const fallbackUser: ChatMessageUI = {\n id: userPostId ?? uuidv4(),\n sessionId: input.sessionId,\n role: 'user',\n content: input.userMessage.content ?? '',\n createdAt: now,\n updatedAt: now,\n };\n const fallbackAssistant: ChatMessageUI = {\n id: uuidv4(),\n sessionId: input.sessionId,\n role: 'assistant',\n content: sanitizedAssistantContent,\n createdAt: now,\n updatedAt: now,\n tokenCount: input.assistantMessage.tokenCount,\n model: input.assistantMessage.model,\n };\n return {\n userMessage: userPost ? mapPostToChatMessageUI(userPost, input.sessionId) : fallbackUser,\n assistantMessage: assistantPost\n ? mapPostToChatMessageUI(assistantPost, input.sessionId)\n : fallbackAssistant,\n session: {\n id: input.sessionId,\n title: 'Chat',\n createdAt: now,\n updatedAt: now,\n },\n };\n },\n [client, sendMessagesMutation],\n );\n\n return {\n createChannel,\n createSession: createChannel,\n saveMessages,\n loading: { create: createChannelLoading, saveMessages: sendMessagesLoading },\n };\n}\n"],"names":["_a","_b","_c","_d","_e","uuidv4"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {useState,useRef,useCallback,useEffect,useMemo}from'react';import {useCreateAccountChatFileUploadLinksMutation,useCreateAccountChatFileDownloadLinksMutation}from'common/graphql';import {useChatMutations,useChatMessages}from'./useChatApi.js';import {useCdecliChannel,isNoActiveSessionError}from'./useCdecliChannel.js';import {usePrerequisiteIds}from'./usePrerequisiteIds.js';import {buildGatewayMediaPreferUrls}from'../features/attachments/buildGatewayMedia.js';import {preserveAttachmentPreviews}from'../features/attachments/preserveAttachmentPreviews.js';var __defProp = Object.defineProperty;
|
|
1
|
+
import {useState,useRef,useCallback,useEffect,useMemo}from'react';import {useCreateAccountChatFileUploadLinksMutation,useCreateAccountChatFileDownloadLinksMutation}from'common/graphql';import {useChatMutations,useChatMessages}from'./useChatApi.js';import {useCdecliChannel,isNoActiveSessionError}from'./useCdecliChannel.js';import {usePrerequisiteIds}from'./usePrerequisiteIds.js';import {buildGatewayMediaPreferUrls}from'../features/attachments/buildGatewayMedia.js';import {preserveAttachmentPreviews}from'../features/attachments/preserveAttachmentPreviews.js';import {mergeOptimisticGatewayMessages}from'../state/chatThreadMerge.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __defProps = Object.defineProperties;
|
|
3
3
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
@@ -254,7 +254,7 @@ function useChatStream(sessionId, routing = {
|
|
|
254
254
|
} : void 0
|
|
255
255
|
};
|
|
256
256
|
});
|
|
257
|
-
setMessages((prev) => preserveAttachmentPreviews(prev, formatted));
|
|
257
|
+
setMessages((prev) => preserveAttachmentPreviews(prev, mergeOptimisticGatewayMessages(prev, formatted)));
|
|
258
258
|
setResponse("");
|
|
259
259
|
}
|
|
260
260
|
}, [sessionId, backendMessages, backendMessagesLoaded]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatStream.js","sources":["../../src/hooks/useChatStream.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n useCreateAccountChatFileDownloadLinksMutation,\n useCreateAccountChatFileUploadLinksMutation,\n} from 'common/graphql';\nimport { useChatMutations, useChatMessages } from './useChatApi';\nimport { isNoActiveSessionError, useCdecliChannel } from './useCdecliChannel';\nimport { usePrerequisiteIds } from './usePrerequisiteIds';\nimport { buildGatewayMediaPreferUrls } from '../features/attachments/buildGatewayMedia';\nimport { preserveAttachmentPreviews } from '../features/attachments/preserveAttachmentPreviews';\n\n/** Agent returned an error while the cdecli-serve channel stayed connected (e.g. bad LLM API key). */\nfunction isCdecliAgentFailureOutput(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n return (\n /⚠\\s*Error:/.test(t) ||\n /LLM stream error/i.test(t) ||\n /Incorrect API key/i.test(t) ||\n /invalid_api_key/i.test(t) ||\n /authentication_error/i.test(t)\n );\n}\n\nexport interface MessageAttachment {\n id: string;\n name: string;\n type: 'file' | 'screenshot';\n dataUrl?: string;\n mimeType?: string;\n size?: number;\n url?: string;\n}\n\nexport interface ChatMessage {\n role: 'user' | 'assistant';\n content: string;\n attachments?: MessageAttachment[];\n metadata?: {\n tokenUsage?: { inputTokens: number; outputTokens: number; totalTokens: number };\n model?: string;\n };\n}\n\n/** Mobile chat routes exclusively through CDeCLI (messenger-gateway). */\nexport interface UseChatStreamRouting {\n channelConnected: boolean;\n accountId: string;\n /** When `'backend'`, the gateway persists posts — skip client `saveMessages`. */\n persistenceMode?: 'backend' | 'frontend';\n}\n\nexport function useChatStream(\n sessionId: string | null,\n routing: UseChatStreamRouting = {\n channelConnected: false,\n accountId: 'default',\n persistenceMode: 'backend',\n },\n) {\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [response, setResponse] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const isSendingRef = useRef(false);\n /** Follow-ups typed before cdecli has an active session. Flushed after the first token. */\n const pendingSteersRef = useRef<string[]>([]);\n /** True once this turn has produced at least one stream chunk (steer is valid). */\n const sessionLiveRef = useRef(false);\n const flushPendingSteersRef = useRef<() => Promise<void>>(async () => {});\n const sendMessageRef = useRef<\n (\n content: string,\n attachments?: MessageAttachment[],\n sessionIdOverride?: string | null,\n alreadyVisible?: boolean,\n ) => Promise<void>\n >(async () => {});\n\n /** Ensures GraphQL stream subscriptions use the id from createChannel+send before the next parent render. */\n const [cdecliStreamOverrideId, setCdecliStreamOverrideId] = useState<string | undefined>(undefined);\n const userMsgForSaveRef = useRef<ChatMessage | null>(null);\n const saveSessionIdRef = useRef<string | null>(null);\n /** Blocks duplicate cdecli `onComplete` from appending assistant twice / saving twice per send. */\n const cdecliRoundHandledRef = useRef(false);\n const routingRef = useRef(routing);\n routingRef.current = routing;\n\n /** Coalesce token deltas so Fabric is not committing a native tree every chunk. */\n const pendingStreamRef = useRef('');\n const streamFlushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearPendingStream = useCallback(() => {\n if (streamFlushTimerRef.current != null) {\n clearTimeout(streamFlushTimerRef.current);\n streamFlushTimerRef.current = null;\n }\n pendingStreamRef.current = '';\n }, []);\n\n const flushPendingStream = useCallback(() => {\n streamFlushTimerRef.current = null;\n const pending = pendingStreamRef.current;\n if (!pending) return;\n pendingStreamRef.current = '';\n setResponse((r) => r + pending);\n }, []);\n\n useEffect(() => () => clearPendingStream(), [clearPendingStream]);\n\n const { saveMessages } = useChatMutations();\n const { accountUserId } = usePrerequisiteIds();\n const [createAccountChatFileUploadLinksMutation] = useCreateAccountChatFileUploadLinksMutation();\n const [createAccountChatFileDownloadLinksMutation] = useCreateAccountChatFileDownloadLinksMutation();\n const {\n messages: backendMessages,\n loading: backendMessagesLoading,\n messagesLoaded: backendMessagesLoaded,\n } = useChatMessages(sessionId);\n const lastHydratedSessionIdRef = useRef<string | null>(null);\n\n const streamChannelId = sessionId || cdecliStreamOverrideId;\n\n const finalizeCdecliRound = useCallback(\n (assistantContent?: string) => {\n clearPendingStream();\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n sessionLiveRef.current = false;\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n if (assistantContent !== undefined) {\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: assistantContent }]);\n }\n },\n [clearPendingStream],\n );\n\n const cdecliCallbacks = useMemo(\n () => ({\n onChunk: (text: string) => {\n pendingStreamRef.current += text;\n if (!sessionLiveRef.current) {\n sessionLiveRef.current = true;\n void flushPendingSteersRef.current();\n }\n if (streamFlushTimerRef.current == null) {\n streamFlushTimerRef.current = setTimeout(flushPendingStream, 50);\n }\n },\n // The brain's provisional answer is the WHOLE reply-so-far, not a chunk:\n // it is set outright, and set to '' when the real stream supersedes it.\n // It deliberately does not mark the session live - steers wait for the\n // agent, which is the only side that can act on them.\n onQuickReply: (text: string) => {\n setResponse(text);\n },\n onComplete: (text: string) => {\n clearPendingStream();\n if (cdecliRoundHandledRef.current) {\n return;\n }\n\n if (isCdecliAgentFailureOutput(text)) {\n cdecliRoundHandledRef.current = true;\n pendingSteersRef.current = [];\n setError('CDeCLI agent error. Check gateway status and server-side LLM configuration.');\n finalizeCdecliRound(text);\n return;\n }\n\n cdecliRoundHandledRef.current = true;\n\n const sid = saveSessionIdRef.current;\n const um = userMsgForSaveRef.current;\n const leftover = pendingSteersRef.current;\n pendingSteersRef.current = [];\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n sessionLiveRef.current = false;\n\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: text }]);\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n\n const rt = routingRef.current;\n const persistClientSide = rt.persistenceMode !== 'backend';\n\n if (sid && um && persistClientSide) {\n saveMessages({\n sessionId: sid,\n ...(accountUserId ? { createdBy: accountUserId } : {}),\n userMessage: {\n content: um.content,\n attachments: um.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type,\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n },\n assistantMessage: {\n content: text,\n tokenCount: undefined,\n model: 'cdecli-serve',\n },\n }).catch((e) => {\n console.error('[useChatStream] saveMessages (cdecli):', e);\n });\n }\n\n if (leftover.length > 0) {\n const [first, ...rest] = leftover;\n pendingSteersRef.current = rest;\n queueMicrotask(() => {\n void sendMessageRef.current(first, undefined, sid, true);\n });\n }\n },\n onError: (err: string) => {\n if (cdecliRoundHandledRef.current) return;\n cdecliRoundHandledRef.current = true;\n pendingSteersRef.current = [];\n setError(err || 'CDeCLI stream error.');\n finalizeCdecliRound();\n },\n }),\n [saveMessages, accountUserId, finalizeCdecliRound, flushPendingStream, clearPendingStream],\n );\n\n const {\n sendMessage: sendCdecliMessage,\n steer: steerCdecliMessage,\n cancel: cancelCdecliTurn,\n } = useCdecliChannel(routing.channelConnected, routing.accountId, streamChannelId, cdecliCallbacks);\n\n const flushPendingSteers = useCallback(async () => {\n if (!sessionLiveRef.current || !isSendingRef.current) return;\n const sid = saveSessionIdRef.current;\n if (!sid) return;\n\n while (pendingSteersRef.current.length > 0 && sessionLiveRef.current && isSendingRef.current) {\n const next = pendingSteersRef.current[0];\n const result = await steerCdecliMessage(next, sid);\n if (result.ok) {\n pendingSteersRef.current.shift();\n continue;\n }\n if (isNoActiveSessionError(result.error)) {\n return;\n }\n pendingSteersRef.current.shift();\n setError(result.error || 'Could not send follow-up. Try again.');\n return;\n }\n }, [steerCdecliMessage]);\n\n flushPendingSteersRef.current = flushPendingSteers;\n\n useEffect(() => {\n if (sessionId && cdecliStreamOverrideId && sessionId === cdecliStreamOverrideId) {\n setCdecliStreamOverrideId(undefined);\n }\n }, [sessionId, cdecliStreamOverrideId]);\n\n useEffect(() => {\n if (isSendingRef.current) return;\n\n if (!sessionId) {\n setMessages([]);\n setResponse('');\n lastHydratedSessionIdRef.current = null;\n return;\n }\n\n const sessionChanged = lastHydratedSessionIdRef.current !== sessionId;\n if (sessionChanged) {\n lastHydratedSessionIdRef.current = sessionId;\n // Keep cached thread visible; only clear when this channel is a cache miss.\n if (!backendMessagesLoaded) {\n setMessages([]);\n setResponse('');\n }\n }\n\n if (backendMessagesLoaded) {\n const formatted: ChatMessage[] = (backendMessages ?? []).map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: msg.content ?? '',\n attachments: msg.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type === 'screenshot' ? 'screenshot' : 'file',\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n metadata: msg.tokenCount\n ? {\n tokenUsage: {\n inputTokens: 0,\n outputTokens: msg.tokenCount,\n totalTokens: msg.tokenCount,\n },\n model: msg.model,\n }\n : undefined,\n }));\n setMessages((prev) => preserveAttachmentPreviews(prev, formatted));\n setResponse('');\n }\n }, [sessionId, backendMessages, backendMessagesLoaded]);\n\n const sendMessage = useCallback(\n async (\n content: string,\n attachments?: MessageAttachment[],\n sessionIdOverride?: string | null,\n alreadyVisible = false,\n ) => {\n if (!content.trim() && !attachments?.length) return;\n\n const effectiveSessionId = sessionIdOverride !== undefined ? sessionIdOverride : sessionId;\n const rt = routingRef.current;\n const trimmed = content.trim();\n const sendText =\n trimmed ||\n (attachments?.length\n ? `Attached: ${attachments\n .map((a) => a.name)\n .filter(Boolean)\n .join(', ')}`\n : '');\n\n const userMessage: ChatMessage = {\n role: 'user',\n content: sendText,\n attachments,\n };\n\n /**\n * A turn is already in flight. Keep the follow-up visible and queue it.\n * cdecli rejects steer until the agent session exists (\"no active session\"),\n * which is after the first token. Flush then. Never error/LogBox for that race.\n */\n if (isSendingRef.current) {\n if (!rt.channelConnected || !effectiveSessionId) {\n setError(\n !rt.channelConnected\n ? 'CDeCLI is not connected yet. Check gateway status in the header.'\n : 'Missing chat session id.',\n );\n return;\n }\n setMessages((prev) => [...prev, userMessage]);\n setError(null);\n pendingSteersRef.current = [...pendingSteersRef.current, sendText];\n void flushPendingSteers();\n return;\n }\n\n isSendingRef.current = true;\n sessionLiveRef.current = false;\n if (!alreadyVisible) {\n setMessages((prev) => [...prev, userMessage]);\n }\n setResponse('');\n setIsLoading(true);\n setIsStreaming(true);\n setError(null);\n userMsgForSaveRef.current = userMessage;\n saveSessionIdRef.current = effectiveSessionId ?? null;\n cdecliRoundHandledRef.current = false;\n\n if (!rt.channelConnected) {\n setError('CDeCLI is not connected yet. Check gateway status in the header.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n if (!effectiveSessionId) {\n setError('Missing chat session id.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n\n if (sessionIdOverride) {\n setCdecliStreamOverrideId(sessionIdOverride);\n await new Promise<void>((resolve) => {\n setTimeout(resolve, 0);\n });\n }\n\n const ok = await sendCdecliMessage(\n sendText,\n effectiveSessionId,\n await buildGatewayMediaPreferUrls(\n attachments,\n async (filenames) => {\n const result = await createAccountChatFileUploadLinksMutation({ variables: { filenames } });\n return result.data?.createAccountChatFileUploadLinks || [];\n },\n async (urls) => {\n const result = await createAccountChatFileDownloadLinksMutation({ variables: { urls } });\n return result.data?.createAccountChatFileDownloadLinks || [];\n },\n ),\n );\n if (!ok && !cdecliRoundHandledRef.current) {\n cdecliRoundHandledRef.current = true;\n setError('Failed to send message via CDeCLI. Check gateway connection.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n }\n },\n [\n sessionId,\n sendCdecliMessage,\n flushPendingSteers,\n createAccountChatFileUploadLinksMutation,\n createAccountChatFileDownloadLinksMutation,\n ],\n );\n\n sendMessageRef.current = sendMessage;\n\n const cancel = useCallback(() => {\n clearPendingStream();\n pendingSteersRef.current = [];\n sessionLiveRef.current = false;\n const sid = saveSessionIdRef.current ?? sessionId;\n void cancelCdecliTurn(sid ?? 'messenger');\n if (!cdecliRoundHandledRef.current) {\n cdecliRoundHandledRef.current = true;\n finalizeCdecliRound();\n }\n }, [cancelCdecliTurn, finalizeCdecliRound, sessionId, clearPendingStream]);\n\n const clearMessages = useCallback(() => {\n clearPendingStream();\n setMessages([]);\n setResponse('');\n setError(null);\n }, [clearPendingStream]);\n\n const messagesLoading = !!sessionId && backendMessagesLoading && !backendMessagesLoaded;\n\n return {\n messages,\n response,\n error,\n isLoading,\n isStreaming,\n messagesLoading,\n hasMessages: messages.length > 0 || !!response,\n sendMessage,\n cancel,\n clearMessages,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useChatStream.js","sources":["../../src/hooks/useChatStream.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n useCreateAccountChatFileDownloadLinksMutation,\n useCreateAccountChatFileUploadLinksMutation,\n} from 'common/graphql';\nimport { useChatMutations, useChatMessages } from './useChatApi';\nimport { isNoActiveSessionError, useCdecliChannel } from './useCdecliChannel';\nimport { usePrerequisiteIds } from './usePrerequisiteIds';\nimport { buildGatewayMediaPreferUrls } from '../features/attachments/buildGatewayMedia';\nimport { preserveAttachmentPreviews } from '../features/attachments/preserveAttachmentPreviews';\nimport { mergeOptimisticGatewayMessages } from '../state/chatThreadMerge';\n\n/** Agent returned an error while the cdecli-serve channel stayed connected (e.g. bad LLM API key). */\nfunction isCdecliAgentFailureOutput(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n return (\n /⚠\\s*Error:/.test(t) ||\n /LLM stream error/i.test(t) ||\n /Incorrect API key/i.test(t) ||\n /invalid_api_key/i.test(t) ||\n /authentication_error/i.test(t)\n );\n}\n\nexport interface MessageAttachment {\n id: string;\n name: string;\n type: 'file' | 'screenshot';\n dataUrl?: string;\n mimeType?: string;\n size?: number;\n url?: string;\n}\n\nexport interface ChatMessage {\n role: 'user' | 'assistant';\n content: string;\n attachments?: MessageAttachment[];\n metadata?: {\n tokenUsage?: { inputTokens: number; outputTokens: number; totalTokens: number };\n model?: string;\n };\n}\n\n/** Mobile chat routes exclusively through CDeCLI (messenger-gateway). */\nexport interface UseChatStreamRouting {\n channelConnected: boolean;\n accountId: string;\n /** When `'backend'`, the gateway persists posts — skip client `saveMessages`. */\n persistenceMode?: 'backend' | 'frontend';\n}\n\nexport function useChatStream(\n sessionId: string | null,\n routing: UseChatStreamRouting = {\n channelConnected: false,\n accountId: 'default',\n persistenceMode: 'backend',\n },\n) {\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [response, setResponse] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const isSendingRef = useRef(false);\n /** Follow-ups typed before cdecli has an active session. Flushed after the first token. */\n const pendingSteersRef = useRef<string[]>([]);\n /** True once this turn has produced at least one stream chunk (steer is valid). */\n const sessionLiveRef = useRef(false);\n const flushPendingSteersRef = useRef<() => Promise<void>>(async () => {});\n const sendMessageRef = useRef<\n (\n content: string,\n attachments?: MessageAttachment[],\n sessionIdOverride?: string | null,\n alreadyVisible?: boolean,\n ) => Promise<void>\n >(async () => {});\n\n /** Ensures GraphQL stream subscriptions use the id from createChannel+send before the next parent render. */\n const [cdecliStreamOverrideId, setCdecliStreamOverrideId] = useState<string | undefined>(undefined);\n const userMsgForSaveRef = useRef<ChatMessage | null>(null);\n const saveSessionIdRef = useRef<string | null>(null);\n /** Blocks duplicate cdecli `onComplete` from appending assistant twice / saving twice per send. */\n const cdecliRoundHandledRef = useRef(false);\n const routingRef = useRef(routing);\n routingRef.current = routing;\n\n /** Coalesce token deltas so Fabric is not committing a native tree every chunk. */\n const pendingStreamRef = useRef('');\n const streamFlushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearPendingStream = useCallback(() => {\n if (streamFlushTimerRef.current != null) {\n clearTimeout(streamFlushTimerRef.current);\n streamFlushTimerRef.current = null;\n }\n pendingStreamRef.current = '';\n }, []);\n\n const flushPendingStream = useCallback(() => {\n streamFlushTimerRef.current = null;\n const pending = pendingStreamRef.current;\n if (!pending) return;\n pendingStreamRef.current = '';\n setResponse((r) => r + pending);\n }, []);\n\n useEffect(() => () => clearPendingStream(), [clearPendingStream]);\n\n const { saveMessages } = useChatMutations();\n const { accountUserId } = usePrerequisiteIds();\n const [createAccountChatFileUploadLinksMutation] = useCreateAccountChatFileUploadLinksMutation();\n const [createAccountChatFileDownloadLinksMutation] = useCreateAccountChatFileDownloadLinksMutation();\n const {\n messages: backendMessages,\n loading: backendMessagesLoading,\n messagesLoaded: backendMessagesLoaded,\n } = useChatMessages(sessionId);\n const lastHydratedSessionIdRef = useRef<string | null>(null);\n\n const streamChannelId = sessionId || cdecliStreamOverrideId;\n\n const finalizeCdecliRound = useCallback(\n (assistantContent?: string) => {\n clearPendingStream();\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n sessionLiveRef.current = false;\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n if (assistantContent !== undefined) {\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: assistantContent }]);\n }\n },\n [clearPendingStream],\n );\n\n const cdecliCallbacks = useMemo(\n () => ({\n onChunk: (text: string) => {\n pendingStreamRef.current += text;\n if (!sessionLiveRef.current) {\n sessionLiveRef.current = true;\n void flushPendingSteersRef.current();\n }\n if (streamFlushTimerRef.current == null) {\n streamFlushTimerRef.current = setTimeout(flushPendingStream, 50);\n }\n },\n // The brain's provisional answer is the WHOLE reply-so-far, not a chunk:\n // it is set outright, and set to '' when the real stream supersedes it.\n // It deliberately does not mark the session live - steers wait for the\n // agent, which is the only side that can act on them.\n onQuickReply: (text: string) => {\n setResponse(text);\n },\n onComplete: (text: string) => {\n clearPendingStream();\n if (cdecliRoundHandledRef.current) {\n return;\n }\n\n if (isCdecliAgentFailureOutput(text)) {\n cdecliRoundHandledRef.current = true;\n pendingSteersRef.current = [];\n setError('CDeCLI agent error. Check gateway status and server-side LLM configuration.');\n finalizeCdecliRound(text);\n return;\n }\n\n cdecliRoundHandledRef.current = true;\n\n const sid = saveSessionIdRef.current;\n const um = userMsgForSaveRef.current;\n const leftover = pendingSteersRef.current;\n pendingSteersRef.current = [];\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n sessionLiveRef.current = false;\n\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: text }]);\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n\n const rt = routingRef.current;\n const persistClientSide = rt.persistenceMode !== 'backend';\n\n if (sid && um && persistClientSide) {\n saveMessages({\n sessionId: sid,\n ...(accountUserId ? { createdBy: accountUserId } : {}),\n userMessage: {\n content: um.content,\n attachments: um.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type,\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n },\n assistantMessage: {\n content: text,\n tokenCount: undefined,\n model: 'cdecli-serve',\n },\n }).catch((e) => {\n console.error('[useChatStream] saveMessages (cdecli):', e);\n });\n }\n\n if (leftover.length > 0) {\n const [first, ...rest] = leftover;\n pendingSteersRef.current = rest;\n queueMicrotask(() => {\n void sendMessageRef.current(first, undefined, sid, true);\n });\n }\n },\n onError: (err: string) => {\n if (cdecliRoundHandledRef.current) return;\n cdecliRoundHandledRef.current = true;\n pendingSteersRef.current = [];\n setError(err || 'CDeCLI stream error.');\n finalizeCdecliRound();\n },\n }),\n [saveMessages, accountUserId, finalizeCdecliRound, flushPendingStream, clearPendingStream],\n );\n\n const {\n sendMessage: sendCdecliMessage,\n steer: steerCdecliMessage,\n cancel: cancelCdecliTurn,\n } = useCdecliChannel(routing.channelConnected, routing.accountId, streamChannelId, cdecliCallbacks);\n\n const flushPendingSteers = useCallback(async () => {\n if (!sessionLiveRef.current || !isSendingRef.current) return;\n const sid = saveSessionIdRef.current;\n if (!sid) return;\n\n while (pendingSteersRef.current.length > 0 && sessionLiveRef.current && isSendingRef.current) {\n const next = pendingSteersRef.current[0];\n const result = await steerCdecliMessage(next, sid);\n if (result.ok) {\n pendingSteersRef.current.shift();\n continue;\n }\n if (isNoActiveSessionError(result.error)) {\n return;\n }\n pendingSteersRef.current.shift();\n setError(result.error || 'Could not send follow-up. Try again.');\n return;\n }\n }, [steerCdecliMessage]);\n\n flushPendingSteersRef.current = flushPendingSteers;\n\n useEffect(() => {\n if (sessionId && cdecliStreamOverrideId && sessionId === cdecliStreamOverrideId) {\n setCdecliStreamOverrideId(undefined);\n }\n }, [sessionId, cdecliStreamOverrideId]);\n\n useEffect(() => {\n if (isSendingRef.current) return;\n\n if (!sessionId) {\n setMessages([]);\n setResponse('');\n lastHydratedSessionIdRef.current = null;\n return;\n }\n\n const sessionChanged = lastHydratedSessionIdRef.current !== sessionId;\n if (sessionChanged) {\n lastHydratedSessionIdRef.current = sessionId;\n // Keep cached thread visible; only clear when this channel is a cache miss.\n if (!backendMessagesLoaded) {\n setMessages([]);\n setResponse('');\n }\n }\n\n if (backendMessagesLoaded) {\n const formatted: ChatMessage[] = (backendMessages ?? []).map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: msg.content ?? '',\n attachments: msg.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type === 'screenshot' ? 'screenshot' : 'file',\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n metadata: msg.tokenCount\n ? {\n tokenUsage: {\n inputTokens: 0,\n outputTokens: msg.tokenCount,\n totalTokens: msg.tokenCount,\n },\n model: msg.model,\n }\n : undefined,\n }));\n // Positional merge first so assistant replies the gateway never persisted\n // (cdecli skill turns emit no chatMessageAdded) survive this snapshot instead\n // of being dropped, then preserve in-memory attachment previews on the result.\n setMessages((prev) => preserveAttachmentPreviews(prev, mergeOptimisticGatewayMessages(prev, formatted)));\n setResponse('');\n }\n }, [sessionId, backendMessages, backendMessagesLoaded]);\n\n const sendMessage = useCallback(\n async (\n content: string,\n attachments?: MessageAttachment[],\n sessionIdOverride?: string | null,\n alreadyVisible = false,\n ) => {\n if (!content.trim() && !attachments?.length) return;\n\n const effectiveSessionId = sessionIdOverride !== undefined ? sessionIdOverride : sessionId;\n const rt = routingRef.current;\n const trimmed = content.trim();\n const sendText =\n trimmed ||\n (attachments?.length\n ? `Attached: ${attachments\n .map((a) => a.name)\n .filter(Boolean)\n .join(', ')}`\n : '');\n\n const userMessage: ChatMessage = {\n role: 'user',\n content: sendText,\n attachments,\n };\n\n /**\n * A turn is already in flight. Keep the follow-up visible and queue it.\n * cdecli rejects steer until the agent session exists (\"no active session\"),\n * which is after the first token. Flush then. Never error/LogBox for that race.\n */\n if (isSendingRef.current) {\n if (!rt.channelConnected || !effectiveSessionId) {\n setError(\n !rt.channelConnected\n ? 'CDeCLI is not connected yet. Check gateway status in the header.'\n : 'Missing chat session id.',\n );\n return;\n }\n setMessages((prev) => [...prev, userMessage]);\n setError(null);\n pendingSteersRef.current = [...pendingSteersRef.current, sendText];\n void flushPendingSteers();\n return;\n }\n\n isSendingRef.current = true;\n sessionLiveRef.current = false;\n if (!alreadyVisible) {\n setMessages((prev) => [...prev, userMessage]);\n }\n setResponse('');\n setIsLoading(true);\n setIsStreaming(true);\n setError(null);\n userMsgForSaveRef.current = userMessage;\n saveSessionIdRef.current = effectiveSessionId ?? null;\n cdecliRoundHandledRef.current = false;\n\n if (!rt.channelConnected) {\n setError('CDeCLI is not connected yet. Check gateway status in the header.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n if (!effectiveSessionId) {\n setError('Missing chat session id.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n\n if (sessionIdOverride) {\n setCdecliStreamOverrideId(sessionIdOverride);\n await new Promise<void>((resolve) => {\n setTimeout(resolve, 0);\n });\n }\n\n const ok = await sendCdecliMessage(\n sendText,\n effectiveSessionId,\n await buildGatewayMediaPreferUrls(\n attachments,\n async (filenames) => {\n const result = await createAccountChatFileUploadLinksMutation({ variables: { filenames } });\n return result.data?.createAccountChatFileUploadLinks || [];\n },\n async (urls) => {\n const result = await createAccountChatFileDownloadLinksMutation({ variables: { urls } });\n return result.data?.createAccountChatFileDownloadLinks || [];\n },\n ),\n );\n if (!ok && !cdecliRoundHandledRef.current) {\n cdecliRoundHandledRef.current = true;\n setError('Failed to send message via CDeCLI. Check gateway connection.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n }\n },\n [\n sessionId,\n sendCdecliMessage,\n flushPendingSteers,\n createAccountChatFileUploadLinksMutation,\n createAccountChatFileDownloadLinksMutation,\n ],\n );\n\n sendMessageRef.current = sendMessage;\n\n const cancel = useCallback(() => {\n clearPendingStream();\n pendingSteersRef.current = [];\n sessionLiveRef.current = false;\n const sid = saveSessionIdRef.current ?? sessionId;\n void cancelCdecliTurn(sid ?? 'messenger');\n if (!cdecliRoundHandledRef.current) {\n cdecliRoundHandledRef.current = true;\n finalizeCdecliRound();\n }\n }, [cancelCdecliTurn, finalizeCdecliRound, sessionId, clearPendingStream]);\n\n const clearMessages = useCallback(() => {\n clearPendingStream();\n setMessages([]);\n setResponse('');\n setError(null);\n }, [clearPendingStream]);\n\n const messagesLoading = !!sessionId && backendMessagesLoading && !backendMessagesLoaded;\n\n return {\n messages,\n response,\n error,\n isLoading,\n isStreaming,\n messagesLoading,\n hasMessages: messages.length > 0 || !!response,\n sendMessage,\n cancel,\n clearMessages,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +1,16 @@
|
|
|
1
|
-
import {jsx,jsxs}from'react/jsx-runtime';import {
|
|
2
|
-
var _a;
|
|
3
|
-
const navigation = useNavigation();
|
|
4
|
-
const route = useRoute();
|
|
1
|
+
import {jsx,jsxs}from'react/jsx-runtime';import {useColorScheme,StyleSheet,View,Text}from'react-native';import {SafeAreaView}from'react-native-safe-area-context';import {getNativeCharactersExperience}from'../../features/characters/nativeCharactersRegistry.js';import {useCanvasSession}from'../../features/canvas/useCanvasSession.js';import {config}from'../../config/env-config.js';function CharactersScreen() {
|
|
5
2
|
const isDark = useColorScheme() === "dark";
|
|
6
3
|
const Experience = getNativeCharactersExperience();
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
params: {
|
|
12
|
-
orgName: params.orgName,
|
|
13
|
-
channelId: v4(),
|
|
14
|
-
initialQuery: prompt,
|
|
15
|
-
initialMode: "chat",
|
|
16
|
-
headerTitle: character.name
|
|
17
|
-
}
|
|
18
|
-
}));
|
|
19
|
-
}, [navigation, params.orgName]);
|
|
20
|
-
if (!Experience || !params.manifestUrl) {
|
|
4
|
+
const {
|
|
5
|
+
token
|
|
6
|
+
} = useCanvasSession();
|
|
7
|
+
if (!Experience) {
|
|
21
8
|
return /* @__PURE__ */ jsx(SafeAreaView, { style: [styles.fill, isDark && styles.fillDark], children: /* @__PURE__ */ jsxs(View, { style: styles.center, children: [
|
|
22
9
|
/* @__PURE__ */ jsx(Text, { style: [styles.title, isDark && styles.textLight], children: "Characters unavailable" }),
|
|
23
|
-
/* @__PURE__ */ jsx(Text, { style: [styles.detail, isDark && styles.textMuted], children:
|
|
10
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.detail, isDark && styles.textMuted], children: "This build does not carry the federation host runtime." })
|
|
24
11
|
] }) });
|
|
25
12
|
}
|
|
26
|
-
return /* @__PURE__ */ jsx(SafeAreaView, { style: [styles.fill, isDark && styles.fillDark], edges: ["left", "right", "bottom"], children: /* @__PURE__ */ jsx(Experience, {
|
|
13
|
+
return /* @__PURE__ */ jsx(SafeAreaView, { style: [styles.fill, isDark && styles.fillDark], edges: ["left", "right", "bottom"], children: /* @__PURE__ */ jsx(Experience, { token, subgraphUrl: config.CHARACTERS_SUBGRAPH_URL }) });
|
|
27
14
|
}
|
|
28
15
|
const styles = StyleSheet.create({
|
|
29
16
|
fill: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/screens/Characters/index.tsx"],"sourcesContent":["/**\n * Native Characters screen - the host route for the federated
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/screens/Characters/index.tsx"],"sourcesContent":["/**\n * Native Characters screen - the host route for the federated character STUDIO.\n *\n * Same delivery contract as CanvasBoard: the App (MF host) registers the\n * federated component; this screen only reads the registry and hands over what\n * the remote cannot know - a surface session token and the character subgraph\n * endpoint for this environment. Opening it triggers the runtime fetch of\n * `characters_native/Characters` from the character surface; none of that code\n * ships in the app binary. The remaining seams (runAction / storage / playAudio)\n * are injected by the App's FederatedCharactersExperience wrapper.\n */\nimport React from 'react';\nimport { StyleSheet, Text, View, useColorScheme } from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport { getNativeCharactersExperience } from '../../features/characters/nativeCharactersRegistry';\nimport { useCanvasSession } from '../../features/canvas/useCanvasSession';\nimport { config } from '../../config/env-config';\n\nexport interface CharactersRouteParams {\n orgName?: string;\n}\n\nexport default function CharactersScreen() {\n const isDark = useColorScheme() === 'dark';\n const Experience = getNativeCharactersExperience();\n // The shared surface session (token + auto-renewal); the studio's authed\n // subgraph and connector calls ride the same JWT the canvas index uses.\n const { token } = useCanvasSession();\n\n if (!Experience) {\n return (\n <SafeAreaView style={[styles.fill, isDark && styles.fillDark]}>\n <View style={styles.center}>\n <Text style={[styles.title, isDark && styles.textLight]}>Characters unavailable</Text>\n <Text style={[styles.detail, isDark && styles.textMuted]}>\n This build does not carry the federation host runtime.\n </Text>\n </View>\n </SafeAreaView>\n );\n }\n\n return (\n <SafeAreaView style={[styles.fill, isDark && styles.fillDark]} edges={['left', 'right', 'bottom']}>\n <Experience token={token} subgraphUrl={config.CHARACTERS_SUBGRAPH_URL} />\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n fill: { flex: 1, backgroundColor: '#f8fafc' },\n fillDark: { backgroundColor: '#0f172a' },\n center: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24 },\n title: { fontSize: 17, fontWeight: '600', color: '#0f172a', marginBottom: 6 },\n detail: { fontSize: 13, color: '#64748b', textAlign: 'center' },\n textLight: { color: '#f1f5f9' },\n textMuted: { color: '#94a3b8' },\n});\n"],"names":[],"mappings":"6XAoBA,SAAwB,gBAAmB,GAAA;AACzC,EAAM,MAAA,MAAA,GAAS,gBAAqB,KAAA,MAAA;AACpC,EAAA,MAAM,aAAa,6BAA8B,EAAA;AAGjD,EAAM,MAAA;AAAA,IACJ;AAAA,MACE,gBAAiB,EAAA;AACrB,EAAA,IAAI,CAAC,UAAY,EAAA;AACf,IAAA,uBAAQ,GAAA,CAAA,YAAA,EAAA,EAAa,KAAO,EAAA,CAAC,OAAO,IAAM,EAAA,MAAA,IAAU,MAAO,CAAA,QAAQ,CACvD,EAAA,QAAA,kBAAA,IAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,OAAO,MAChB,EAAA,QAAA,EAAA;AAAA,sBAAC,GAAA,CAAA,IAAA,EAAA,EAAK,OAAO,CAAC,MAAA,CAAO,OAAO,MAAU,IAAA,MAAA,CAAO,SAAS,CAAA,EAAG,QAAsB,EAAA,wBAAA,EAAA,CAAA;AAAA,sBAC/E,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,QAAQ,MAAU,IAAA,MAAA,CAAO,SAAS,CAAA,EAAG,QAE1D,EAAA,wDAAA,EAAA;AAAA,KAAA,EACJ,CACJ,EAAA,CAAA;AAAA;AAEV,EAAO,uBAAA,GAAA,CAAC,gBAAa,KAAO,EAAA,CAAC,OAAO,IAAM,EAAA,MAAA,IAAU,MAAO,CAAA,QAAQ,CAAG,EAAA,KAAA,EAAO,CAAC,MAAQ,EAAA,OAAA,EAAS,QAAQ,CAC7F,EAAA,QAAA,kBAAA,GAAA,CAAC,cAAW,KAAc,EAAA,WAAA,EAAa,MAAO,CAAA,uBAAA,EAAyB,CAC3E,EAAA,CAAA;AACR;AACA,MAAM,MAAA,GAAS,WAAW,MAAO,CAAA;AAAA,EAC/B,IAAM,EAAA;AAAA,IACJ,IAAM,EAAA,CAAA;AAAA,IACN,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,QAAU,EAAA;AAAA,IACR,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,CAAA;AAAA,IACN,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA,QAAA;AAAA,IAChB,OAAS,EAAA;AAAA,GACX;AAAA,EACA,KAAO,EAAA;AAAA,IACL,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,KAAA;AAAA,IACZ,KAAO,EAAA,SAAA;AAAA,IACP,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,QAAU,EAAA,EAAA;AAAA,IACV,KAAO,EAAA,SAAA;AAAA,IACP,SAAW,EAAA;AAAA,GACb;AAAA,EACA,SAAW,EAAA;AAAA,IACT,KAAO,EAAA;AAAA,GACT;AAAA,EACA,SAAW,EAAA;AAAA,IACT,KAAO,EAAA;AAAA;AAEX,CAAC,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
function isEphemeralStreamStatus(text) {
|
|
2
|
+
const t = (text != null ? text : "").trim();
|
|
3
|
+
if (!t) return false;
|
|
4
|
+
return /^(Initializing\.?\.?\.?|Setting up( your (project|workspace))?\.?\.?\.?)$/i.test(t);
|
|
5
|
+
}
|
|
6
|
+
function mergeOptimisticGatewayMessages(optimistic, backend) {
|
|
7
|
+
var _a;
|
|
8
|
+
if (!optimistic.length || !backend.length) return backend;
|
|
9
|
+
const norm = (value) => value.trim();
|
|
10
|
+
const merged = [];
|
|
11
|
+
let cursor = 0;
|
|
12
|
+
for (const message of optimistic) {
|
|
13
|
+
let matchIndex = -1;
|
|
14
|
+
for (let j = cursor; j < backend.length; j++) {
|
|
15
|
+
const candidate = backend[j];
|
|
16
|
+
if (candidate.role === message.role && norm(candidate.content) === norm(message.content)) {
|
|
17
|
+
matchIndex = j;
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (matchIndex >= 0) {
|
|
22
|
+
while (cursor <= matchIndex) {
|
|
23
|
+
merged.push(backend[cursor]);
|
|
24
|
+
cursor += 1;
|
|
25
|
+
}
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (message.role === "user") {
|
|
29
|
+
merged.push(message);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (((_a = backend[cursor]) == null ? void 0 : _a.role) === "assistant") {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (norm(message.content) && !isEphemeralStreamStatus(message.content)) {
|
|
36
|
+
merged.push(message);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
while (cursor < backend.length) {
|
|
40
|
+
merged.push(backend[cursor]);
|
|
41
|
+
cursor += 1;
|
|
42
|
+
}
|
|
43
|
+
return merged;
|
|
44
|
+
}export{isEphemeralStreamStatus,mergeOptimisticGatewayMessages};//# sourceMappingURL=chatThreadMerge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatThreadMerge.js","sources":["../../src/state/chatThreadMerge.ts"],"sourcesContent":["/**\n * Positional thread merge, mirroring the browser package's\n * `state/chatThreadMerge.ts` (yantra-app PR #750). Kept as a dependency-free leaf\n * so it can be unit-tested without dragging in the Apollo / inversify import chain\n * that `useChatStream` pulls in.\n *\n * Mobile chat routes exclusively through CDeCLI (messenger-gateway) and lets the\n * gateway persist posts (`persistenceMode: 'backend'`). Many gateway lanes -\n * notably cdecli-serve skill turns - NEVER persist the assistant post: no\n * `chatMessageAdded` ever arrives and the reply lives only in the in-memory\n * thread. Before this merge the hydration effect wholesale-replaced the visible\n * thread with the backend snapshot on every refetch, so those replies vanished\n * the moment the next backend snapshot landed (and were gone on reopen).\n *\n * The merge keeps backend rows authoritative wherever they content-match, while\n * preserving optimistic-only rows in place:\n * - a user send the backend has not written yet stays visible (on mobile every\n * send is a gateway send, so there is no separate frontend-save lane that would\n * re-deliver it);\n * - an assistant reply the backend has no row for stays visible, unless the\n * backend's next row is itself an assistant for that turn (prefer the persisted\n * text, e.g. a webbuilder RESULT) or the text is an ephemeral status line.\n *\n * Attachment previews are intentionally NOT handled here - the caller composes\n * this with `preserveAttachmentPreviews`, which owns grafting the in-memory\n * data-URL onto the persisted user row.\n */\n\ntype MergeableMessage = {\n role: string;\n content: string;\n};\n\n/** Short gateway/workflow progress lines that must not stick under a final reply. */\nexport function isEphemeralStreamStatus(text: string | null | undefined): boolean {\n const t = (text ?? '').trim();\n if (!t) return false;\n return /^(Initializing\\.?\\.?\\.?|Setting up( your (project|workspace))?\\.?\\.?\\.?)$/i.test(t);\n}\n\nexport function mergeOptimisticGatewayMessages<T extends MergeableMessage>(optimistic: T[], backend: T[]): T[] {\n if (!optimistic.length || !backend.length) return backend;\n\n const norm = (value: string) => value.trim();\n\n const merged: T[] = [];\n let cursor = 0;\n for (const message of optimistic) {\n let matchIndex = -1;\n for (let j = cursor; j < backend.length; j++) {\n const candidate = backend[j];\n if (candidate.role === message.role && norm(candidate.content) === norm(message.content)) {\n matchIndex = j;\n break;\n }\n }\n if (matchIndex >= 0) {\n // Adopt every backend row up to and including the match so rows persisted\n // by other paths (channel mirror, sibling client) keep their position.\n while (cursor <= matchIndex) {\n merged.push(backend[cursor]);\n cursor += 1;\n }\n continue;\n }\n if (message.role === 'user') {\n // Every mobile send is a gateway send; keep it until the backend writes it.\n merged.push(message);\n continue;\n }\n // Assistant reply with no backend row. If the backend's next row is itself an\n // assistant (this turn's canonical reply, possibly different text), prefer it.\n // Otherwise keep the optimistic reply - dropping it here is what made replies\n // vanish the moment the next message was sent. Ephemeral status lines never\n // earn a permanent bubble.\n if (backend[cursor]?.role === 'assistant') {\n continue;\n }\n if (norm(message.content) && !isEphemeralStreamStatus(message.content)) {\n merged.push(message);\n }\n }\n // Backend rows past the last match (e.g. the assistant post landing mid-merge)\n // still belong at the end.\n while (cursor < backend.length) {\n merged.push(backend[cursor]);\n cursor += 1;\n }\n\n return merged;\n}\n"],"names":[],"mappings":"AAkCO,SAAS,wBAAwB,IAA0C,EAAA;AAChF,EAAM,MAAA,CAAA,GAAA,CAAK,IAAQ,IAAA,IAAA,GAAA,IAAA,GAAA,EAAA,EAAI,IAAK,EAAA;AAC5B,EAAI,IAAA,CAAC,GAAU,OAAA,KAAA;AACf,EAAO,OAAA,4EAAA,CAA6E,KAAK,CAAC,CAAA;AAC5F;AACgB,SAAA,8BAAA,CAA2D,YAAiB,OAAmB,EAAA;AAvC/G,EAAA,IAAA,EAAA;AAwCE,EAAA,IAAI,CAAC,UAAW,CAAA,MAAA,IAAU,CAAC,OAAA,CAAQ,QAAe,OAAA,OAAA;AAClD,EAAA,MAAM,IAAO,GAAA,CAAC,KAAkB,KAAA,KAAA,CAAM,IAAK,EAAA;AAC3C,EAAA,MAAM,SAAc,EAAC;AACrB,EAAA,IAAI,MAAS,GAAA,CAAA;AACb,EAAA,KAAA,MAAW,WAAW,UAAY,EAAA;AAChC,IAAA,IAAI,UAAa,GAAA,EAAA;AACjB,IAAA,KAAA,IAAS,CAAI,GAAA,MAAA,EAAQ,CAAI,GAAA,OAAA,CAAQ,QAAQ,CAAK,EAAA,EAAA;AAC5C,MAAM,MAAA,SAAA,GAAY,QAAQ,CAAC,CAAA;AAC3B,MAAI,IAAA,SAAA,CAAU,IAAS,KAAA,OAAA,CAAQ,IAAQ,IAAA,IAAA,CAAK,SAAU,CAAA,OAAO,CAAM,KAAA,IAAA,CAAK,OAAQ,CAAA,OAAO,CAAG,EAAA;AACxF,QAAa,UAAA,GAAA,CAAA;AACb,QAAA;AAAA;AACF;AAEF,IAAA,IAAI,cAAc,CAAG,EAAA;AAGnB,MAAA,OAAO,UAAU,UAAY,EAAA;AAC3B,QAAO,MAAA,CAAA,IAAA,CAAK,OAAQ,CAAA,MAAM,CAAC,CAAA;AAC3B,QAAU,MAAA,IAAA,CAAA;AAAA;AAEZ,MAAA;AAAA;AAEF,IAAI,IAAA,OAAA,CAAQ,SAAS,MAAQ,EAAA;AAE3B,MAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AACnB,MAAA;AAAA;AAOF,IAAA,IAAA,CAAA,CAAI,EAAQ,GAAA,OAAA,CAAA,MAAM,CAAd,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAiB,UAAS,WAAa,EAAA;AACzC,MAAA;AAAA;AAEF,IAAI,IAAA,IAAA,CAAK,QAAQ,OAAO,CAAA,IAAK,CAAC,uBAAwB,CAAA,OAAA,CAAQ,OAAO,CAAG,EAAA;AACtE,MAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AAAA;AACrB;AAIF,EAAO,OAAA,MAAA,GAAS,QAAQ,MAAQ,EAAA;AAC9B,IAAO,MAAA,CAAA,IAAA,CAAK,OAAQ,CAAA,MAAM,CAAC,CAAA;AAC3B,IAAU,MAAA,IAAA,CAAA;AAAA;AAEZ,EAAO,OAAA,MAAA;AACT"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminide-stack/yantra-mobile",
|
|
3
|
-
"version": "12.0.51-alpha.
|
|
3
|
+
"version": "12.0.51-alpha.4",
|
|
4
4
|
"description": "Sample core for higher packages to depend on",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "CDMBase LLC",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"uuid": "^9.0.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"common": "12.0.51-alpha.
|
|
28
|
+
"common": "12.0.51-alpha.4"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"@admin-layout/gluestack-ui-mobile": "*",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"typescript": {
|
|
58
58
|
"definition": "lib/index.d.ts"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "a953658078529dc90cb1286415bccb5a81c43313"
|
|
61
61
|
}
|