@adminide-stack/yantra-mobile 12.0.49-alpha.0 → 12.0.49-alpha.1
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/components/NavigationHeader/HeaderSheet.js +8 -2
- package/lib/components/NavigationHeader/HeaderSheet.js.map +1 -1
- package/lib/components/NavigationHeader/HeaderSkillsButton.js +42 -111
- package/lib/components/NavigationHeader/HeaderSkillsButton.js.map +1 -1
- package/lib/components/NavigationHeader/HeaderTasksButton.js +77 -50
- package/lib/components/NavigationHeader/HeaderTasksButton.js.map +1 -1
- package/lib/contexts/GatewayContext.js +1 -4
- package/lib/contexts/GatewayContext.js.map +1 -1
- package/lib/features/chat/ChatTranscript.js +10 -9
- package/lib/features/chat/ChatTranscript.js.map +1 -1
- package/lib/features/skills/SkillTemplatePicker.js +261 -0
- package/lib/features/skills/SkillTemplatePicker.js.map +1 -0
- package/lib/features/skills/skillTemplates.js +12 -0
- package/lib/features/skills/skillTemplates.js.map +1 -0
- package/lib/features/skills/useGatewaySkills.js +59 -0
- package/lib/features/skills/useGatewaySkills.js.map +1 -0
- package/lib/hooks/useChatApi.js +192 -18
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/screens/Home/components/ChatHistoryLanding.js +120 -15
- package/lib/screens/Home/components/ChatHistoryLanding.js.map +1 -1
- package/lib/services/agentSessionManager.js +9 -4
- package/lib/services/agentSessionManager.js.map +1 -1
- package/package.json +4 -4
|
@@ -24,12 +24,14 @@ function HeaderSheet({
|
|
|
24
24
|
isDark,
|
|
25
25
|
onClose,
|
|
26
26
|
headerRight,
|
|
27
|
+
maxHeightFraction = 0.72,
|
|
27
28
|
children
|
|
28
29
|
}) {
|
|
29
30
|
const insets = useSafeAreaInsets();
|
|
30
31
|
const {
|
|
31
32
|
height: windowHeight
|
|
32
33
|
} = useWindowDimensions();
|
|
34
|
+
const sheetHeight = Math.round(windowHeight * maxHeightFraction);
|
|
33
35
|
const sheetBg = isDark ? "#0f172a" : mobileTokens.color.surface;
|
|
34
36
|
const borderColor = isDark ? "rgba(148,163,184,0.22)" : mobileTokens.color.border;
|
|
35
37
|
const foreground = isDark ? "#e2e8f0" : mobileTokens.color.text;
|
|
@@ -39,7 +41,7 @@ function HeaderSheet({
|
|
|
39
41
|
/* @__PURE__ */ jsxs(View, { style: [styles.sheet, {
|
|
40
42
|
backgroundColor: sheetBg,
|
|
41
43
|
borderColor,
|
|
42
|
-
|
|
44
|
+
height: sheetHeight,
|
|
43
45
|
paddingBottom: Math.max(insets.bottom, 16)
|
|
44
46
|
}], children: [
|
|
45
47
|
/* @__PURE__ */ jsx(View, { style: styles.handleWrap, children: /* @__PURE__ */ jsx(View, { style: [styles.handle, {
|
|
@@ -61,7 +63,7 @@ function HeaderSheet({
|
|
|
61
63
|
}) => [styles.closeBtn, pressed && styles.pressed], children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "close", size: 18, color: muted }) })
|
|
62
64
|
] })
|
|
63
65
|
] }),
|
|
64
|
-
children
|
|
66
|
+
/* @__PURE__ */ jsx(View, { style: styles.body, children })
|
|
65
67
|
] })
|
|
66
68
|
] }) });
|
|
67
69
|
}
|
|
@@ -126,5 +128,9 @@ const styles = StyleSheet.create({
|
|
|
126
128
|
},
|
|
127
129
|
pressed: {
|
|
128
130
|
opacity: 0.6
|
|
131
|
+
},
|
|
132
|
+
body: {
|
|
133
|
+
flex: 1,
|
|
134
|
+
minHeight: 0
|
|
129
135
|
}
|
|
130
136
|
});export{HeaderSheet};//# sourceMappingURL=HeaderSheet.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderSheet.js","sources":["../../../src/components/NavigationHeader/HeaderSheet.tsx"],"sourcesContent":["/**\n * Bottom sheet chrome for header pickers (Tasks, Skills, Settings).\n * Matches the Apps launcher sheet so every toolbar menu feels like one family.\n */\nimport React, { type ReactNode } from 'react';\nimport { Modal, Pressable, StyleSheet, Text, View, useWindowDimensions } from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { mobileTokens } from '../../theme/mobileTokens';\n\nexport type HeaderSheetProps = {\n visible: boolean;\n title: string;\n subtitle?: string;\n isDark: boolean;\n onClose: () => void;\n headerRight?: ReactNode;\n children: ReactNode;\n};\n\nexport function HeaderSheet({
|
|
1
|
+
{"version":3,"file":"HeaderSheet.js","sources":["../../../src/components/NavigationHeader/HeaderSheet.tsx"],"sourcesContent":["/**\n * Bottom sheet chrome for header pickers (Tasks, Skills, Settings).\n * Matches the Apps launcher sheet so every toolbar menu feels like one family.\n */\nimport React, { type ReactNode } from 'react';\nimport { Modal, Pressable, StyleSheet, Text, View, useWindowDimensions } from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { mobileTokens } from '../../theme/mobileTokens';\n\nexport type HeaderSheetProps = {\n visible: boolean;\n title: string;\n subtitle?: string;\n isDark: boolean;\n onClose: () => void;\n headerRight?: ReactNode;\n /** Fraction of window height for the sheet (default 0.72). */\n maxHeightFraction?: number;\n children: ReactNode;\n};\n\nexport function HeaderSheet({\n visible,\n title,\n subtitle,\n isDark,\n onClose,\n headerRight,\n maxHeightFraction = 0.72,\n children,\n}: HeaderSheetProps) {\n const insets = useSafeAreaInsets();\n const { height: windowHeight } = useWindowDimensions();\n const sheetHeight = Math.round(windowHeight * maxHeightFraction);\n const sheetBg = isDark ? '#0f172a' : mobileTokens.color.surface;\n const borderColor = isDark ? 'rgba(148,163,184,0.22)' : mobileTokens.color.border;\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n\n return (\n <Modal visible={visible} transparent animationType=\"slide\" onRequestClose={onClose}>\n <View style={styles.modalRoot}>\n <Pressable style={styles.backdrop} onPress={onClose} accessibilityLabel=\"Close\" />\n <View\n style={[\n styles.sheet,\n {\n backgroundColor: sheetBg,\n borderColor,\n height: sheetHeight,\n paddingBottom: Math.max(insets.bottom, 16),\n },\n ]}\n >\n <View style={styles.handleWrap}>\n <View style={[styles.handle, { backgroundColor: borderColor }]} />\n </View>\n <View style={styles.header}>\n <View style={styles.headerText}>\n <Text style={[styles.title, { color: foreground }]}>{title}</Text>\n {subtitle ? <Text style={[styles.subtitle, { color: muted }]}>{subtitle}</Text> : null}\n </View>\n <View style={styles.headerActions}>\n {headerRight}\n <Pressable\n onPress={onClose}\n accessibilityLabel=\"Close\"\n accessibilityRole=\"button\"\n hitSlop={8}\n style={({ pressed }) => [styles.closeBtn, pressed && styles.pressed]}\n >\n <MaterialCommunityIcons name=\"close\" size={18} color={muted} />\n </Pressable>\n </View>\n </View>\n <View style={styles.body}>{children}</View>\n </View>\n </View>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n modalRoot: {\n flex: 1,\n justifyContent: 'flex-end',\n },\n backdrop: {\n ...StyleSheet.absoluteFillObject,\n backgroundColor: 'rgba(15, 23, 42, 0.36)',\n },\n sheet: {\n borderTopLeftRadius: 18,\n borderTopRightRadius: 18,\n width: '100%',\n overflow: 'hidden',\n borderWidth: StyleSheet.hairlineWidth,\n },\n handleWrap: {\n alignItems: 'center',\n paddingTop: 8,\n paddingBottom: 4,\n },\n handle: {\n width: 36,\n height: 4,\n borderRadius: 999,\n },\n header: {\n flexDirection: 'row',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n paddingHorizontal: 16,\n paddingBottom: 10,\n gap: 12,\n },\n headerText: {\n flex: 1,\n minWidth: 0,\n gap: 2,\n },\n headerActions: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n },\n title: {\n fontSize: 20,\n fontWeight: '700',\n letterSpacing: -0.4,\n },\n subtitle: {\n fontSize: 13,\n lineHeight: 18,\n },\n closeBtn: {\n width: 32,\n height: 32,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 16,\n },\n pressed: {\n opacity: 0.6,\n },\n body: {\n flex: 1,\n minHeight: 0,\n },\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -1,120 +1,51 @@
|
|
|
1
|
-
import {jsxs,Fragment,jsx}from'react/jsx-runtime';import {useState,
|
|
2
|
-
|
|
3
|
-
name: "GitHub Research",
|
|
4
|
-
description: "Search and summarize relevant GitHub repositories."
|
|
5
|
-
}];
|
|
6
|
-
function SkillsSheet({
|
|
7
|
-
isDark,
|
|
8
|
-
onClose
|
|
1
|
+
import {jsxs,Fragment,jsx}from'react/jsx-runtime';import {useState,useCallback}from'react';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useGatewayContext,parseActiveSkills}from'../../contexts/GatewayContext.js';import {SkillTemplatePicker}from'../../features/skills/SkillTemplatePicker.js';import {agentSessionManager}from'../../services/agentSessionManager.js';import {HeaderToolbarButton}from'./HeaderToolbarButton.js';function HeaderSkillsButton({
|
|
2
|
+
isDark
|
|
9
3
|
}) {
|
|
10
4
|
const {
|
|
11
5
|
activeSkill,
|
|
12
|
-
setActiveSkill
|
|
6
|
+
setActiveSkill,
|
|
7
|
+
selectedGateway
|
|
13
8
|
} = useGatewayContext();
|
|
14
9
|
const cdecli = useCdecliConnection();
|
|
15
|
-
const session = useAgentSessionState();
|
|
16
|
-
const activeKeys = useMemo(() => parseActiveSkills(activeSkill), [activeSkill]);
|
|
17
|
-
const foreground = isDark ? "#e2e8f0" : mobileTokens.color.text;
|
|
18
|
-
const muted = isDark ? "#94a3b8" : mobileTokens.color.textMuted;
|
|
19
|
-
const rows = useMemo(() => {
|
|
20
|
-
const fromGateway = session.skills.map((skill) => ({
|
|
21
|
-
key: skill.skillKey,
|
|
22
|
-
name: skill.name || skillDisplayName(skill.skillKey),
|
|
23
|
-
description: skill.description || (skill.eligible ? "Available" : "Not eligible")
|
|
24
|
-
}));
|
|
25
|
-
const seen = new Set(fromGateway.map((row) => row.key));
|
|
26
|
-
const extras = BUILTIN_SKILLS.filter((row) => !seen.has(row.key));
|
|
27
|
-
return [...extras, ...fromGateway];
|
|
28
|
-
}, [session.skills]);
|
|
29
|
-
const toggle = useCallback(async (key) => {
|
|
30
|
-
const next = activeKeys.includes(key) ? activeKeys.filter((item) => item !== key) : [...activeKeys, key];
|
|
31
|
-
const csv = next.length > 0 ? next.join(",") : null;
|
|
32
|
-
setActiveSkill(csv);
|
|
33
|
-
if (csv && cdecli.cdecliSelected) {
|
|
34
|
-
try {
|
|
35
|
-
await cdecli.connectWithSkill(csv);
|
|
36
|
-
} catch (e) {
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}, [activeKeys, cdecli, setActiveSkill]);
|
|
40
|
-
return /* @__PURE__ */ jsx(HeaderSheet, { visible: true, title: "Skills", subtitle: activeKeys.length > 0 ? `${activeKeys.length} active` : "Pick a skill template for this session", isDark, onClose, children: /* @__PURE__ */ jsx(ScrollView, { contentContainerStyle: styles.list, keyboardShouldPersistTaps: "handled", children: rows.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [styles.empty, {
|
|
41
|
-
color: muted
|
|
42
|
-
}], children: "No skill templates yet. Connect Yantra to load gateway skills." }) : rows.map((row) => {
|
|
43
|
-
const selected = activeKeys.includes(row.key);
|
|
44
|
-
return /* @__PURE__ */ jsxs(Pressable, { onPress: () => {
|
|
45
|
-
void toggle(row.key);
|
|
46
|
-
}, style: ({
|
|
47
|
-
pressed
|
|
48
|
-
}) => [styles.row, selected && styles.rowActive, isDark && selected && styles.rowActiveDark, pressed && styles.pressed], children: [
|
|
49
|
-
/* @__PURE__ */ jsxs(View, { style: styles.rowBody, children: [
|
|
50
|
-
/* @__PURE__ */ jsx(Text, { style: [styles.rowTitle, {
|
|
51
|
-
color: foreground
|
|
52
|
-
}], numberOfLines: 1, children: row.name }),
|
|
53
|
-
/* @__PURE__ */ jsx(Text, { style: [styles.rowMeta, {
|
|
54
|
-
color: muted
|
|
55
|
-
}], numberOfLines: 2, children: row.description })
|
|
56
|
-
] }),
|
|
57
|
-
selected ? /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "check", size: 18, color: mobileTokens.color.primary }) : null
|
|
58
|
-
] }, row.key);
|
|
59
|
-
}) }) });
|
|
60
|
-
}
|
|
61
|
-
function HeaderSkillsButton({
|
|
62
|
-
isDark
|
|
63
|
-
}) {
|
|
64
|
-
const {
|
|
65
|
-
activeSkill
|
|
66
|
-
} = useGatewayContext();
|
|
67
10
|
const [open, setOpen] = useState(false);
|
|
68
11
|
const count = parseActiveSkills(activeSkill).length;
|
|
12
|
+
const cdecliSelected = (selectedGateway == null ? void 0 : selectedGateway.channelType) === "cdecli-serve";
|
|
13
|
+
const applyTemplate = useCallback((template) => {
|
|
14
|
+
var _a;
|
|
15
|
+
const skill = ((_a = template.requiredSkills) == null ? void 0 : _a.join(",")) || template.name;
|
|
16
|
+
setActiveSkill(skill || null);
|
|
17
|
+
if (cdecliSelected && skill) {
|
|
18
|
+
void cdecli.connectWithSkill(skill, template.model, template.soul || void 0);
|
|
19
|
+
agentSessionManager.createTask({
|
|
20
|
+
title: template.name,
|
|
21
|
+
skillTemplate: template.id,
|
|
22
|
+
skillTemplateName: template.name,
|
|
23
|
+
model: template.model
|
|
24
|
+
});
|
|
25
|
+
} else if (!cdecliSelected) {
|
|
26
|
+
agentSessionManager.createTask({
|
|
27
|
+
title: template.name,
|
|
28
|
+
skillTemplate: template.id,
|
|
29
|
+
skillTemplateName: template.name,
|
|
30
|
+
model: template.model
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}, [cdecli, cdecliSelected, setActiveSkill]);
|
|
34
|
+
const applySkills = useCallback((skills) => {
|
|
35
|
+
const keys = skills.map((s) => s.skillKey).filter(Boolean);
|
|
36
|
+
if (!keys.length) return;
|
|
37
|
+
const csv = keys.join(",");
|
|
38
|
+
setActiveSkill(csv);
|
|
39
|
+
if (cdecliSelected) {
|
|
40
|
+
void cdecli.connectWithSkill(csv);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
for (const key of keys) {
|
|
44
|
+
void agentSessionManager.toggleSkill(key, true);
|
|
45
|
+
}
|
|
46
|
+
}, [cdecli, cdecliSelected, setActiveSkill]);
|
|
69
47
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
70
|
-
/* @__PURE__ */ jsx(HeaderToolbarButton, { icon: "puzzle-outline", label: "Skills", badge: count, active: open || count > 0, onPress: () => setOpen(true), accessibilityLabel: "Skill templates", isDark }),
|
|
71
|
-
open ? /* @__PURE__ */ jsx(
|
|
48
|
+
/* @__PURE__ */ jsx(HeaderToolbarButton, { icon: "puzzle-outline", label: "Skills", badge: count, active: open || count > 0, onPress: () => setOpen(true), accessibilityLabel: "Skill templates", isDark, iconColor: count > 0 ? "#7c3aed" : void 0 }),
|
|
49
|
+
open ? /* @__PURE__ */ jsx(SkillTemplatePicker, { open: true, isDark, onClose: () => setOpen(false), onSelectTemplate: applyTemplate, onSelectSkills: applySkills }) : null
|
|
72
50
|
] });
|
|
73
|
-
}
|
|
74
|
-
const styles = StyleSheet.create({
|
|
75
|
-
list: {
|
|
76
|
-
paddingHorizontal: 16,
|
|
77
|
-
paddingBottom: 12,
|
|
78
|
-
gap: 8
|
|
79
|
-
},
|
|
80
|
-
row: {
|
|
81
|
-
flexDirection: "row",
|
|
82
|
-
alignItems: "center",
|
|
83
|
-
gap: 10,
|
|
84
|
-
borderRadius: 12,
|
|
85
|
-
borderWidth: 1,
|
|
86
|
-
borderColor: "transparent",
|
|
87
|
-
paddingHorizontal: 12,
|
|
88
|
-
paddingVertical: 10,
|
|
89
|
-
backgroundColor: mobileTokens.color.surfaceMuted
|
|
90
|
-
},
|
|
91
|
-
rowActive: {
|
|
92
|
-
borderColor: mobileTokens.color.primaryBorder,
|
|
93
|
-
backgroundColor: mobileTokens.color.primarySoft
|
|
94
|
-
},
|
|
95
|
-
rowActiveDark: {
|
|
96
|
-
backgroundColor: "rgba(79,70,229,0.18)"
|
|
97
|
-
},
|
|
98
|
-
pressed: {
|
|
99
|
-
opacity: 0.7
|
|
100
|
-
},
|
|
101
|
-
rowBody: {
|
|
102
|
-
flex: 1,
|
|
103
|
-
minWidth: 0,
|
|
104
|
-
gap: 2
|
|
105
|
-
},
|
|
106
|
-
rowTitle: {
|
|
107
|
-
fontSize: 14,
|
|
108
|
-
fontWeight: "600"
|
|
109
|
-
},
|
|
110
|
-
rowMeta: {
|
|
111
|
-
fontSize: 12,
|
|
112
|
-
lineHeight: 16
|
|
113
|
-
},
|
|
114
|
-
empty: {
|
|
115
|
-
fontSize: 14,
|
|
116
|
-
lineHeight: 20,
|
|
117
|
-
paddingVertical: 20,
|
|
118
|
-
textAlign: "center"
|
|
119
|
-
}
|
|
120
|
-
});export{HeaderSkillsButton};//# sourceMappingURL=HeaderSkillsButton.js.map
|
|
51
|
+
}export{HeaderSkillsButton};//# sourceMappingURL=HeaderSkillsButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderSkillsButton.js","sources":["../../../src/components/NavigationHeader/HeaderSkillsButton.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useState } from 'react';\nimport { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { useCdecliConnection } from '../../contexts/CdecliConnectionContext';\nimport { parseActiveSkills, skillDisplayName, useGatewayContext } from '../../contexts/GatewayContext';\nimport { useAgentSessionState } from '../../hooks/useAgentSessionState';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport { HeaderSheet } from './HeaderSheet';\nimport { HeaderToolbarButton } from './HeaderToolbarButton';\n\ntype Props = {\n isDark: boolean;\n};\n\nconst BUILTIN_SKILLS = [\n {\n key: 'yantra-github-search',\n name: 'GitHub Research',\n description: 'Search and summarize relevant GitHub repositories.',\n },\n];\n\nfunction SkillsSheet({ isDark, onClose }: { isDark: boolean; onClose: () => void }) {\n const { activeSkill, setActiveSkill } = useGatewayContext();\n const cdecli = useCdecliConnection();\n const session = useAgentSessionState();\n const activeKeys = useMemo(() => parseActiveSkills(activeSkill), [activeSkill]);\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n\n const rows = useMemo(() => {\n const fromGateway = session.skills.map((skill) => ({\n key: skill.skillKey,\n name: skill.name || skillDisplayName(skill.skillKey),\n description: skill.description || (skill.eligible ? 'Available' : 'Not eligible'),\n }));\n const seen = new Set(fromGateway.map((row) => row.key));\n const extras = BUILTIN_SKILLS.filter((row) => !seen.has(row.key));\n return [...extras, ...fromGateway];\n }, [session.skills]);\n\n const toggle = useCallback(\n async (key: string) => {\n const next = activeKeys.includes(key) ? activeKeys.filter((item) => item !== key) : [...activeKeys, key];\n const csv = next.length > 0 ? next.join(',') : null;\n setActiveSkill(csv);\n if (csv && cdecli.cdecliSelected) {\n try {\n await cdecli.connectWithSkill(csv);\n } catch {\n /* connectWithSkill already records status on the connection. */\n }\n }\n },\n [activeKeys, cdecli, setActiveSkill],\n );\n\n return (\n <HeaderSheet\n visible\n title=\"Skills\"\n subtitle={activeKeys.length > 0 ? `${activeKeys.length} active` : 'Pick a skill template for this session'}\n isDark={isDark}\n onClose={onClose}\n >\n <ScrollView contentContainerStyle={styles.list} keyboardShouldPersistTaps=\"handled\">\n {rows.length === 0 ? (\n <Text style={[styles.empty, { color: muted }]}>\n No skill templates yet. Connect Yantra to load gateway skills.\n </Text>\n ) : (\n rows.map((row) => {\n const selected = activeKeys.includes(row.key);\n return (\n <Pressable\n key={row.key}\n onPress={() => {\n void toggle(row.key);\n }}\n style={({ pressed }) => [\n styles.row,\n selected && styles.rowActive,\n isDark && selected && styles.rowActiveDark,\n pressed && styles.pressed,\n ]}\n >\n <View style={styles.rowBody}>\n <Text style={[styles.rowTitle, { color: foreground }]} numberOfLines={1}>\n {row.name}\n </Text>\n <Text style={[styles.rowMeta, { color: muted }]} numberOfLines={2}>\n {row.description}\n </Text>\n </View>\n {selected ? (\n <MaterialCommunityIcons name=\"check\" size={18} color={mobileTokens.color.primary} />\n ) : null}\n </Pressable>\n );\n })\n )}\n </ScrollView>\n </HeaderSheet>\n );\n}\n\nexport function HeaderSkillsButton({ isDark }: Props) {\n const { activeSkill } = useGatewayContext();\n const [open, setOpen] = useState(false);\n const count = parseActiveSkills(activeSkill).length;\n\n return (\n <>\n <HeaderToolbarButton\n icon=\"puzzle-outline\"\n label=\"Skills\"\n badge={count}\n active={open || count > 0}\n onPress={() => setOpen(true)}\n accessibilityLabel=\"Skill templates\"\n isDark={isDark}\n />\n {open ? <SkillsSheet isDark={isDark} onClose={() => setOpen(false)} /> : null}\n </>\n );\n}\n\nconst styles = StyleSheet.create({\n list: {\n paddingHorizontal: 16,\n paddingBottom: 12,\n gap: 8,\n },\n row: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 10,\n borderRadius: 12,\n borderWidth: 1,\n borderColor: 'transparent',\n paddingHorizontal: 12,\n paddingVertical: 10,\n backgroundColor: mobileTokens.color.surfaceMuted,\n },\n rowActive: {\n borderColor: mobileTokens.color.primaryBorder,\n backgroundColor: mobileTokens.color.primarySoft,\n },\n rowActiveDark: {\n backgroundColor: 'rgba(79,70,229,0.18)',\n },\n pressed: {\n opacity: 0.7,\n },\n rowBody: {\n flex: 1,\n minWidth: 0,\n gap: 2,\n },\n rowTitle: {\n fontSize: 14,\n fontWeight: '600',\n },\n rowMeta: {\n fontSize: 12,\n lineHeight: 16,\n },\n empty: {\n fontSize: 14,\n lineHeight: 20,\n paddingVertical: 20,\n textAlign: 'center',\n },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HeaderSkillsButton.js","sources":["../../../src/components/NavigationHeader/HeaderSkillsButton.tsx"],"sourcesContent":["import React, { useCallback, useState } from 'react';\nimport { useCdecliConnection } from '../../contexts/CdecliConnectionContext';\nimport { parseActiveSkills, useGatewayContext } from '../../contexts/GatewayContext';\nimport { SkillTemplatePicker } from '../../features/skills/SkillTemplatePicker';\nimport type { GatewaySkillEntry } from '../../features/skills/useGatewaySkills';\nimport type { SkillTemplate } from '../../features/skills/skillTemplates';\nimport { agentSessionManager } from '../../services/agentSessionManager';\nimport { HeaderToolbarButton } from './HeaderToolbarButton';\n\ntype Props = {\n isDark: boolean;\n};\n\nexport function HeaderSkillsButton({ isDark }: Props) {\n const { activeSkill, setActiveSkill, selectedGateway } = useGatewayContext();\n const cdecli = useCdecliConnection();\n const [open, setOpen] = useState(false);\n const count = parseActiveSkills(activeSkill).length;\n const cdecliSelected = selectedGateway?.channelType === 'cdecli-serve';\n\n const applyTemplate = useCallback(\n (template: SkillTemplate) => {\n const skill = template.requiredSkills?.join(',') || template.name;\n setActiveSkill(skill || null);\n if (cdecliSelected && skill) {\n void cdecli.connectWithSkill(skill, template.model, template.soul || undefined);\n agentSessionManager.createTask({\n title: template.name,\n skillTemplate: template.id,\n skillTemplateName: template.name,\n model: template.model,\n });\n } else if (!cdecliSelected) {\n agentSessionManager.createTask({\n title: template.name,\n skillTemplate: template.id,\n skillTemplateName: template.name,\n model: template.model,\n });\n }\n },\n [cdecli, cdecliSelected, setActiveSkill],\n );\n\n const applySkills = useCallback(\n (skills: GatewaySkillEntry[]) => {\n const keys = skills.map((s) => s.skillKey).filter(Boolean);\n if (!keys.length) return;\n const csv = keys.join(',');\n setActiveSkill(csv);\n if (cdecliSelected) {\n void cdecli.connectWithSkill(csv);\n return;\n }\n for (const key of keys) {\n void agentSessionManager.toggleSkill(key, true);\n }\n },\n [cdecli, cdecliSelected, setActiveSkill],\n );\n\n return (\n <>\n <HeaderToolbarButton\n icon=\"puzzle-outline\"\n label=\"Skills\"\n badge={count}\n active={open || count > 0}\n onPress={() => setOpen(true)}\n accessibilityLabel=\"Skill templates\"\n isDark={isDark}\n iconColor={count > 0 ? '#7c3aed' : undefined}\n />\n {open ? (\n <SkillTemplatePicker\n open\n isDark={isDark}\n onClose={() => setOpen(false)}\n onSelectTemplate={applyTemplate}\n onSelectSkills={applySkills}\n />\n ) : null}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {jsxs,Fragment,jsx}from'react/jsx-runtime';import {useState,useCallback}from'react';import {ScrollView,StyleSheet,Text,Pressable,
|
|
1
|
+
import {jsxs,Fragment,jsx}from'react/jsx-runtime';import {useState,useCallback}from'react';import {ScrollView,StyleSheet,Text,View,Pressable,ActivityIndicator}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {MAX_CONCURRENT_TASKS}from'../../config/constants.js';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useGatewayContext}from'../../contexts/GatewayContext.js';import {useAgentSessionState}from'../../hooks/useAgentSessionState.js';import {agentSessionManager}from'../../services/agentSessionManager.js';import {mobileTokens}from'../../theme/mobileTokens.js';import {HeaderSheet}from'./HeaderSheet.js';import {HeaderToolbarButton}from'./HeaderToolbarButton.js';const STATUS_LABEL = {
|
|
2
2
|
idle: "Idle",
|
|
3
3
|
connecting: "Connecting",
|
|
4
4
|
running: "Running",
|
|
@@ -6,12 +6,16 @@ import {jsxs,Fragment,jsx}from'react/jsx-runtime';import {useState,useCallback}f
|
|
|
6
6
|
failed: "Failed",
|
|
7
7
|
aborted: "Aborted"
|
|
8
8
|
};
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (status === "
|
|
14
|
-
|
|
9
|
+
function StatusGlyph({
|
|
10
|
+
status,
|
|
11
|
+
isDark
|
|
12
|
+
}) {
|
|
13
|
+
if (status === "running" || status === "connecting") {
|
|
14
|
+
return /* @__PURE__ */ jsx(ActivityIndicator, { size: 14, color: isDark ? "#60a5fa" : "#2563eb" });
|
|
15
|
+
}
|
|
16
|
+
const name = status === "completed" ? "check-circle-outline" : status === "failed" ? "alert-circle-outline" : status === "aborted" ? "close-circle-outline" : "circle-outline";
|
|
17
|
+
const color = status === "completed" ? isDark ? "#4ade80" : "#16a34a" : status === "failed" ? isDark ? "#f87171" : "#dc2626" : status === "aborted" ? isDark ? "#fb923c" : "#ea580c" : isDark ? "#94a3b8" : mobileTokens.color.textMuted;
|
|
18
|
+
return /* @__PURE__ */ jsx(MaterialCommunityIcons, { name, size: 16, color });
|
|
15
19
|
}
|
|
16
20
|
function TaskRow({
|
|
17
21
|
task,
|
|
@@ -23,17 +27,21 @@ function TaskRow({
|
|
|
23
27
|
const foreground = isDark ? "#e2e8f0" : mobileTokens.color.text;
|
|
24
28
|
const muted = isDark ? "#94a3b8" : mobileTokens.color.textMuted;
|
|
25
29
|
const last = task.messages[task.messages.length - 1];
|
|
26
|
-
const preview = last ? last.content.length >
|
|
30
|
+
const preview = last ? last.content.length > 60 ? `${last.content.slice(0, 60)}\u2026` : last.content : "No messages yet";
|
|
31
|
+
const skillLabel = task.skillTemplateName || task.skillTemplate;
|
|
27
32
|
return /* @__PURE__ */ jsxs(Pressable, { onPress: onSelect, style: ({
|
|
28
33
|
pressed
|
|
29
34
|
}) => [styles.row, isActive && styles.rowActive, isDark && isActive && styles.rowActiveDark, pressed && styles.pressed], children: [
|
|
30
|
-
/* @__PURE__ */ jsx(
|
|
31
|
-
backgroundColor: statusColor(task.status, isDark)
|
|
32
|
-
}] }),
|
|
35
|
+
/* @__PURE__ */ jsx(StatusGlyph, { status: task.status, isDark }),
|
|
33
36
|
/* @__PURE__ */ jsxs(View, { style: styles.rowBody, children: [
|
|
34
|
-
/* @__PURE__ */
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
/* @__PURE__ */ jsxs(View, { style: styles.titleRow, children: [
|
|
38
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.rowTitle, {
|
|
39
|
+
color: foreground
|
|
40
|
+
}], numberOfLines: 1, children: task.title }),
|
|
41
|
+
skillLabel ? /* @__PURE__ */ jsx(View, { style: [styles.skillChip, isDark && styles.skillChipDark], children: /* @__PURE__ */ jsx(Text, { style: [styles.skillChipText, {
|
|
42
|
+
color: muted
|
|
43
|
+
}], numberOfLines: 1, children: skillLabel }) }) : null
|
|
44
|
+
] }),
|
|
37
45
|
/* @__PURE__ */ jsxs(Text, { style: [styles.rowMeta, {
|
|
38
46
|
color: muted
|
|
39
47
|
}], numberOfLines: 1, children: [
|
|
@@ -42,7 +50,7 @@ function TaskRow({
|
|
|
42
50
|
preview
|
|
43
51
|
] })
|
|
44
52
|
] }),
|
|
45
|
-
/* @__PURE__ */ jsx(Pressable, { onPress: onRemove, hitSlop: 8, accessibilityLabel: "Remove task", children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "
|
|
53
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: onRemove, hitSlop: 8, accessibilityLabel: "Remove task", children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "trash-can-outline", size: 16, color: muted }) })
|
|
46
54
|
] });
|
|
47
55
|
}
|
|
48
56
|
function TasksSheet({
|
|
@@ -50,27 +58,32 @@ function TasksSheet({
|
|
|
50
58
|
onClose
|
|
51
59
|
}) {
|
|
52
60
|
const session = useAgentSessionState();
|
|
61
|
+
const {
|
|
62
|
+
selectedGateway
|
|
63
|
+
} = useGatewayContext();
|
|
64
|
+
const cdecli = useCdecliConnection();
|
|
53
65
|
const muted = isDark ? "#94a3b8" : mobileTokens.color.textMuted;
|
|
54
|
-
const
|
|
55
|
-
const
|
|
66
|
+
const cdecliSelected = (selectedGateway == null ? void 0 : selectedGateway.channelType) === "cdecli-serve";
|
|
67
|
+
const connected = cdecliSelected ? cdecli.channelConnected : session.gatewayConnected;
|
|
68
|
+
const canCreate = session.tasks.length < MAX_CONCURRENT_TASKS && (cdecliSelected || session.gatewayConnected);
|
|
56
69
|
const handleNew = useCallback(() => {
|
|
70
|
+
if (!canCreate) return;
|
|
57
71
|
agentSessionManager.createTask({
|
|
58
72
|
title: "General Assistant"
|
|
59
73
|
});
|
|
60
|
-
}, []);
|
|
61
|
-
return /* @__PURE__ */ jsx(HeaderSheet, { visible: true, title: "Tasks", subtitle:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
/* @__PURE__ */ jsx(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
] }) });
|
|
74
|
+
}, [canCreate]);
|
|
75
|
+
return /* @__PURE__ */ jsx(HeaderSheet, { visible: true, title: "Tasks", subtitle: `${session.tasks.length} of ${MAX_CONCURRENT_TASKS} slots`, isDark, onClose, headerRight: /* @__PURE__ */ jsxs(View, { style: styles.headerRight, children: [
|
|
76
|
+
/* @__PURE__ */ jsx(View, { style: [styles.gwDot, {
|
|
77
|
+
backgroundColor: connected ? "#22c55e" : "#94a3b8"
|
|
78
|
+
}] }),
|
|
79
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: handleNew, disabled: !canCreate, accessibilityLabel: "Start new task", style: ({
|
|
80
|
+
pressed
|
|
81
|
+
}) => [styles.newBtn, pressed && styles.pressed, !canCreate && styles.disabled], children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "plus", size: 16, color: mobileTokens.color.primary }) })
|
|
82
|
+
] }), children: /* @__PURE__ */ jsx(ScrollView, { style: {
|
|
83
|
+
flex: 1
|
|
84
|
+
}, contentContainerStyle: styles.list, keyboardShouldPersistTaps: "handled", children: session.tasks.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [styles.empty, {
|
|
85
|
+
color: muted
|
|
86
|
+
}], children: connected ? "No tasks yet. Create one to get started." : "Connect Yantra to create tasks." }) : session.tasks.map((task) => /* @__PURE__ */ jsx(TaskRow, { task, isActive: session.activeTaskId === task.id, isDark, onSelect: () => agentSessionManager.setActiveTask(task.id), onRemove: () => agentSessionManager.removeTask(task.id) }, task.id)) }) });
|
|
74
87
|
}
|
|
75
88
|
function HeaderTasksButton({
|
|
76
89
|
isDark
|
|
@@ -90,7 +103,7 @@ const styles = StyleSheet.create({
|
|
|
90
103
|
},
|
|
91
104
|
row: {
|
|
92
105
|
flexDirection: "row",
|
|
93
|
-
alignItems: "
|
|
106
|
+
alignItems: "flex-start",
|
|
94
107
|
gap: 10,
|
|
95
108
|
borderRadius: 12,
|
|
96
109
|
borderWidth: 1,
|
|
@@ -112,10 +125,25 @@ const styles = StyleSheet.create({
|
|
|
112
125
|
disabled: {
|
|
113
126
|
opacity: 0.4
|
|
114
127
|
},
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
128
|
+
titleRow: {
|
|
129
|
+
flexDirection: "row",
|
|
130
|
+
alignItems: "center",
|
|
131
|
+
gap: 6,
|
|
132
|
+
minWidth: 0
|
|
133
|
+
},
|
|
134
|
+
skillChip: {
|
|
135
|
+
maxWidth: 96,
|
|
136
|
+
borderRadius: 6,
|
|
137
|
+
paddingHorizontal: 6,
|
|
138
|
+
paddingVertical: 2,
|
|
139
|
+
backgroundColor: mobileTokens.color.surface
|
|
140
|
+
},
|
|
141
|
+
skillChipDark: {
|
|
142
|
+
backgroundColor: "#0f172a"
|
|
143
|
+
},
|
|
144
|
+
skillChipText: {
|
|
145
|
+
fontSize: 10,
|
|
146
|
+
fontWeight: "600"
|
|
119
147
|
},
|
|
120
148
|
rowBody: {
|
|
121
149
|
flex: 1,
|
|
@@ -123,6 +151,7 @@ const styles = StyleSheet.create({
|
|
|
123
151
|
gap: 2
|
|
124
152
|
},
|
|
125
153
|
rowTitle: {
|
|
154
|
+
flexShrink: 1,
|
|
126
155
|
fontSize: 14,
|
|
127
156
|
fontWeight: "600"
|
|
128
157
|
},
|
|
@@ -135,23 +164,21 @@ const styles = StyleSheet.create({
|
|
|
135
164
|
paddingVertical: 20,
|
|
136
165
|
textAlign: "center"
|
|
137
166
|
},
|
|
138
|
-
|
|
139
|
-
fontSize: 12,
|
|
140
|
-
lineHeight: 18,
|
|
141
|
-
paddingTop: 4,
|
|
142
|
-
opacity: 0.7
|
|
143
|
-
},
|
|
144
|
-
newBtn: {
|
|
167
|
+
headerRight: {
|
|
145
168
|
flexDirection: "row",
|
|
146
169
|
alignItems: "center",
|
|
147
|
-
gap:
|
|
170
|
+
gap: 6
|
|
171
|
+
},
|
|
172
|
+
gwDot: {
|
|
173
|
+
width: 6,
|
|
174
|
+
height: 6,
|
|
175
|
+
borderRadius: 3
|
|
176
|
+
},
|
|
177
|
+
newBtn: {
|
|
178
|
+
width: 32,
|
|
148
179
|
height: 32,
|
|
149
|
-
|
|
180
|
+
alignItems: "center",
|
|
181
|
+
justifyContent: "center",
|
|
150
182
|
borderRadius: 10
|
|
151
|
-
},
|
|
152
|
-
newBtnLabel: {
|
|
153
|
-
fontSize: 13,
|
|
154
|
-
fontWeight: "600",
|
|
155
|
-
color: mobileTokens.color.primary
|
|
156
183
|
}
|
|
157
184
|
});export{HeaderTasksButton};//# sourceMappingURL=HeaderTasksButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderTasksButton.js","sources":["../../../src/components/NavigationHeader/HeaderTasksButton.tsx"],"sourcesContent":["import React, { useCallback, useState } from 'react';\nimport { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { MAX_CONCURRENT_TASKS } from '../../config/constants';\nimport { useAgentSessionState } from '../../hooks/useAgentSessionState';\nimport { agentSessionManager, type AgentTask, type TaskStatus } from '../../services/agentSessionManager';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport { HeaderSheet } from './HeaderSheet';\nimport { HeaderToolbarButton } from './HeaderToolbarButton';\n\ntype Props = {\n isDark: boolean;\n};\n\nconst STATUS_LABEL: Record<TaskStatus, string> = {\n idle: 'Idle',\n connecting: 'Connecting',\n running: 'Running',\n completed: 'Completed',\n failed: 'Failed',\n aborted: 'Aborted',\n};\n\nfunction statusColor(status: TaskStatus, isDark: boolean): string {\n if (status === 'running' || status === 'connecting') return isDark ? '#60a5fa' : '#2563eb';\n if (status === 'completed') return isDark ? '#4ade80' : '#16a34a';\n if (status === 'failed') return isDark ? '#f87171' : '#dc2626';\n if (status === 'aborted') return isDark ? '#fb923c' : '#ea580c';\n return isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n}\n\nfunction TaskRow({\n task,\n isActive,\n isDark,\n onSelect,\n onRemove,\n}: {\n task: AgentTask;\n isActive: boolean;\n isDark: boolean;\n onSelect: () => void;\n onRemove: () => void;\n}) {\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const last = task.messages[task.messages.length - 1];\n const preview = last\n ? last.content.length > 72\n ? `${last.content.slice(0, 72)}…`\n : last.content\n : 'No messages yet';\n\n return (\n <Pressable\n onPress={onSelect}\n style={({ pressed }) => [\n styles.row,\n isActive && styles.rowActive,\n isDark && isActive && styles.rowActiveDark,\n pressed && styles.pressed,\n ]}\n >\n <View style={[styles.dot, { backgroundColor: statusColor(task.status, isDark) }]} />\n <View style={styles.rowBody}>\n <Text style={[styles.rowTitle, { color: foreground }]} numberOfLines={1}>\n {task.title}\n </Text>\n <Text style={[styles.rowMeta, { color: muted }]} numberOfLines={1}>\n {STATUS_LABEL[task.status]} · {preview}\n </Text>\n </View>\n <Pressable onPress={onRemove} hitSlop={8} accessibilityLabel=\"Remove task\">\n <MaterialCommunityIcons name=\"close\" size={16} color={muted} />\n </Pressable>\n </Pressable>\n );\n}\n\nfunction TasksSheet({ isDark, onClose }: { isDark: boolean; onClose: () => void }) {\n const session = useAgentSessionState();\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const canCreate = session.tasks.length < MAX_CONCURRENT_TASKS;\n\n const handleNew = useCallback(() => {\n agentSessionManager.createTask({ title: 'General Assistant' });\n }, []);\n\n return (\n <HeaderSheet\n visible\n title=\"Tasks\"\n subtitle={\n session.gatewayConnected\n ? `${session.tasks.length} of ${MAX_CONCURRENT_TASKS} slots`\n : 'Connect Yantra to keep agent sessions running'\n }\n isDark={isDark}\n onClose={onClose}\n headerRight={\n <Pressable\n onPress={handleNew}\n disabled={!canCreate}\n accessibilityLabel=\"Start new task\"\n style={({ pressed }) => [styles.newBtn, pressed && styles.pressed, !canCreate && styles.disabled]}\n >\n <MaterialCommunityIcons name=\"plus\" size={16} color={mobileTokens.color.primary} />\n <Text style={styles.newBtnLabel}>New</Text>\n </Pressable>\n }\n >\n <ScrollView contentContainerStyle={styles.list} keyboardShouldPersistTaps=\"handled\">\n {session.tasks.length === 0 ? (\n <Text style={[styles.empty, { color: muted }]}>\n No running tasks. Start one to keep an agent session alive alongside chat.\n </Text>\n ) : (\n session.tasks.map((task) => (\n <TaskRow\n key={task.id}\n task={task}\n isActive={session.activeTaskId === task.id}\n isDark={isDark}\n onSelect={() => agentSessionManager.setActiveTask(task.id)}\n onRemove={() => agentSessionManager.removeTask(task.id)}\n />\n ))\n )}\n {!session.gatewayConnected ? (\n <Text style={[styles.hint, { color: foreground }]}>\n Tasks stay on this device until Yantra is connected.\n </Text>\n ) : null}\n </ScrollView>\n </HeaderSheet>\n );\n}\n\nexport function HeaderTasksButton({ isDark }: Props) {\n const session = useAgentSessionState();\n const [open, setOpen] = useState(false);\n\n return (\n <>\n <HeaderToolbarButton\n icon=\"pulse\"\n label=\"Tasks\"\n badge={session.tasks.length}\n active={open}\n onPress={() => setOpen(true)}\n accessibilityLabel=\"Tasks\"\n isDark={isDark}\n />\n {open ? <TasksSheet isDark={isDark} onClose={() => setOpen(false)} /> : null}\n </>\n );\n}\n\nconst styles = StyleSheet.create({\n list: {\n paddingHorizontal: 16,\n paddingBottom: 12,\n gap: 8,\n },\n row: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 10,\n borderRadius: 12,\n borderWidth: 1,\n borderColor: 'transparent',\n paddingHorizontal: 12,\n paddingVertical: 10,\n backgroundColor: mobileTokens.color.surfaceMuted,\n },\n rowActive: {\n borderColor: mobileTokens.color.primaryBorder,\n backgroundColor: mobileTokens.color.primarySoft,\n },\n rowActiveDark: {\n backgroundColor: 'rgba(79,70,229,0.18)',\n },\n pressed: {\n opacity: 0.7,\n },\n disabled: {\n opacity: 0.4,\n },\n dot: {\n width: 8,\n height: 8,\n borderRadius: 4,\n },\n rowBody: {\n flex: 1,\n minWidth: 0,\n gap: 2,\n },\n rowTitle: {\n fontSize: 14,\n fontWeight: '600',\n },\n rowMeta: {\n fontSize: 12,\n },\n empty: {\n fontSize: 14,\n lineHeight: 20,\n paddingVertical: 20,\n textAlign: 'center',\n },\n hint: {\n fontSize: 12,\n lineHeight: 18,\n paddingTop: 4,\n opacity: 0.7,\n },\n newBtn: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 2,\n height: 32,\n paddingHorizontal: 8,\n borderRadius: 10,\n },\n newBtnLabel: {\n fontSize: 13,\n fontWeight: '600',\n color: mobileTokens.color.primary,\n },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HeaderTasksButton.js","sources":["../../../src/components/NavigationHeader/HeaderTasksButton.tsx"],"sourcesContent":["import React, { useCallback, useState } from 'react';\nimport { ActivityIndicator, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { MAX_CONCURRENT_TASKS } from '../../config/constants';\nimport { useCdecliConnection } from '../../contexts/CdecliConnectionContext';\nimport { useGatewayContext } from '../../contexts/GatewayContext';\nimport { useAgentSessionState } from '../../hooks/useAgentSessionState';\nimport { agentSessionManager, type AgentTask, type TaskStatus } from '../../services/agentSessionManager';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport { HeaderSheet } from './HeaderSheet';\nimport { HeaderToolbarButton } from './HeaderToolbarButton';\n\ntype Props = {\n isDark: boolean;\n};\n\nconst STATUS_LABEL: Record<TaskStatus, string> = {\n idle: 'Idle',\n connecting: 'Connecting',\n running: 'Running',\n completed: 'Completed',\n failed: 'Failed',\n aborted: 'Aborted',\n};\n\nfunction StatusGlyph({ status, isDark }: { status: TaskStatus; isDark: boolean }) {\n if (status === 'running' || status === 'connecting') {\n return <ActivityIndicator size={14} color={isDark ? '#60a5fa' : '#2563eb'} />;\n }\n const name =\n status === 'completed'\n ? 'check-circle-outline'\n : status === 'failed'\n ? 'alert-circle-outline'\n : status === 'aborted'\n ? 'close-circle-outline'\n : 'circle-outline';\n const color =\n status === 'completed'\n ? isDark\n ? '#4ade80'\n : '#16a34a'\n : status === 'failed'\n ? isDark\n ? '#f87171'\n : '#dc2626'\n : status === 'aborted'\n ? isDark\n ? '#fb923c'\n : '#ea580c'\n : isDark\n ? '#94a3b8'\n : mobileTokens.color.textMuted;\n return <MaterialCommunityIcons name={name} size={16} color={color} />;\n}\n\nfunction TaskRow({\n task,\n isActive,\n isDark,\n onSelect,\n onRemove,\n}: {\n task: AgentTask;\n isActive: boolean;\n isDark: boolean;\n onSelect: () => void;\n onRemove: () => void;\n}) {\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const last = task.messages[task.messages.length - 1];\n const preview = last\n ? last.content.length > 60\n ? `${last.content.slice(0, 60)}…`\n : last.content\n : 'No messages yet';\n const skillLabel = task.skillTemplateName || task.skillTemplate;\n\n return (\n <Pressable\n onPress={onSelect}\n style={({ pressed }) => [\n styles.row,\n isActive && styles.rowActive,\n isDark && isActive && styles.rowActiveDark,\n pressed && styles.pressed,\n ]}\n >\n <StatusGlyph status={task.status} isDark={isDark} />\n <View style={styles.rowBody}>\n <View style={styles.titleRow}>\n <Text style={[styles.rowTitle, { color: foreground }]} numberOfLines={1}>\n {task.title}\n </Text>\n {skillLabel ? (\n <View style={[styles.skillChip, isDark && styles.skillChipDark]}>\n <Text style={[styles.skillChipText, { color: muted }]} numberOfLines={1}>\n {skillLabel}\n </Text>\n </View>\n ) : null}\n </View>\n <Text style={[styles.rowMeta, { color: muted }]} numberOfLines={1}>\n {STATUS_LABEL[task.status]} · {preview}\n </Text>\n </View>\n <Pressable onPress={onRemove} hitSlop={8} accessibilityLabel=\"Remove task\">\n <MaterialCommunityIcons name=\"trash-can-outline\" size={16} color={muted} />\n </Pressable>\n </Pressable>\n );\n}\n\nfunction TasksSheet({ isDark, onClose }: { isDark: boolean; onClose: () => void }) {\n const session = useAgentSessionState();\n const { selectedGateway } = useGatewayContext();\n const cdecli = useCdecliConnection();\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const cdecliSelected = selectedGateway?.channelType === 'cdecli-serve';\n const connected = cdecliSelected ? cdecli.channelConnected : session.gatewayConnected;\n const canCreate = session.tasks.length < MAX_CONCURRENT_TASKS && (cdecliSelected || session.gatewayConnected);\n\n const handleNew = useCallback(() => {\n if (!canCreate) return;\n agentSessionManager.createTask({ title: 'General Assistant' });\n }, [canCreate]);\n\n return (\n <HeaderSheet\n visible\n title=\"Tasks\"\n subtitle={`${session.tasks.length} of ${MAX_CONCURRENT_TASKS} slots`}\n isDark={isDark}\n onClose={onClose}\n headerRight={\n <View style={styles.headerRight}>\n <View style={[styles.gwDot, { backgroundColor: connected ? '#22c55e' : '#94a3b8' }]} />\n <Pressable\n onPress={handleNew}\n disabled={!canCreate}\n accessibilityLabel=\"Start new task\"\n style={({ pressed }) => [\n styles.newBtn,\n pressed && styles.pressed,\n !canCreate && styles.disabled,\n ]}\n >\n <MaterialCommunityIcons name=\"plus\" size={16} color={mobileTokens.color.primary} />\n </Pressable>\n </View>\n }\n >\n <ScrollView style={{ flex: 1 }} contentContainerStyle={styles.list} keyboardShouldPersistTaps=\"handled\">\n {session.tasks.length === 0 ? (\n <Text style={[styles.empty, { color: muted }]}>\n {connected ? 'No tasks yet. Create one to get started.' : 'Connect Yantra to create tasks.'}\n </Text>\n ) : (\n session.tasks.map((task) => (\n <TaskRow\n key={task.id}\n task={task}\n isActive={session.activeTaskId === task.id}\n isDark={isDark}\n onSelect={() => agentSessionManager.setActiveTask(task.id)}\n onRemove={() => agentSessionManager.removeTask(task.id)}\n />\n ))\n )}\n </ScrollView>\n </HeaderSheet>\n );\n}\n\nexport function HeaderTasksButton({ isDark }: Props) {\n const session = useAgentSessionState();\n const [open, setOpen] = useState(false);\n\n return (\n <>\n <HeaderToolbarButton\n icon=\"pulse\"\n label=\"Tasks\"\n badge={session.tasks.length}\n active={open}\n onPress={() => setOpen(true)}\n accessibilityLabel=\"Tasks\"\n isDark={isDark}\n />\n {open ? <TasksSheet isDark={isDark} onClose={() => setOpen(false)} /> : null}\n </>\n );\n}\n\nconst styles = StyleSheet.create({\n list: {\n paddingHorizontal: 16,\n paddingBottom: 12,\n gap: 8,\n },\n row: {\n flexDirection: 'row',\n alignItems: 'flex-start',\n gap: 10,\n borderRadius: 12,\n borderWidth: 1,\n borderColor: 'transparent',\n paddingHorizontal: 12,\n paddingVertical: 10,\n backgroundColor: mobileTokens.color.surfaceMuted,\n },\n rowActive: {\n borderColor: mobileTokens.color.primaryBorder,\n backgroundColor: mobileTokens.color.primarySoft,\n },\n rowActiveDark: {\n backgroundColor: 'rgba(79,70,229,0.18)',\n },\n pressed: {\n opacity: 0.7,\n },\n disabled: {\n opacity: 0.4,\n },\n titleRow: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 6,\n minWidth: 0,\n },\n skillChip: {\n maxWidth: 96,\n borderRadius: 6,\n paddingHorizontal: 6,\n paddingVertical: 2,\n backgroundColor: mobileTokens.color.surface,\n },\n skillChipDark: {\n backgroundColor: '#0f172a',\n },\n skillChipText: {\n fontSize: 10,\n fontWeight: '600',\n },\n rowBody: {\n flex: 1,\n minWidth: 0,\n gap: 2,\n },\n rowTitle: {\n flexShrink: 1,\n fontSize: 14,\n fontWeight: '600',\n },\n rowMeta: {\n fontSize: 12,\n },\n empty: {\n fontSize: 14,\n lineHeight: 20,\n paddingVertical: 20,\n textAlign: 'center',\n },\n headerRight: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 6,\n },\n gwDot: {\n width: 6,\n height: 6,\n borderRadius: 3,\n },\n newBtn: {\n width: 32,\n height: 32,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 10,\n },\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -78,7 +78,4 @@ function useGatewayContext() {
|
|
|
78
78
|
function parseActiveSkills(activeSkill) {
|
|
79
79
|
if (!activeSkill) return [];
|
|
80
80
|
return activeSkill.split(",").map((s) => s.trim()).filter(Boolean);
|
|
81
|
-
}
|
|
82
|
-
function skillDisplayName(skillKey) {
|
|
83
|
-
return skillKey.split("/").pop() || skillKey;
|
|
84
|
-
}export{GatewayContextProvider,parseActiveSkills,skillDisplayName,useGatewayContext};//# sourceMappingURL=GatewayContext.js.map
|
|
81
|
+
}export{GatewayContextProvider,parseActiveSkills,useGatewayContext};//# sourceMappingURL=GatewayContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GatewayContext.js","sources":["../../src/contexts/GatewayContext.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\nimport type { GatewayEntry, GatewayId } from '../config/constants';\nimport { useGatewayRegistry } from '../hooks/useGatewayRegistry';\nimport { GatewaySelectionStorage } from '../utils/gatewaySelectionStorage';\n\nexport interface GatewayContextValue {\n selectedGatewayId: GatewayId;\n selectedGateway: GatewayEntry;\n gateways: Record<string, GatewayEntry>;\n gatewayList: Array<{ id: string } & GatewayEntry>;\n setSelectedGateway: (gatewayId: GatewayId) => void;\n loading: boolean;\n activeSkill: string | null;\n setActiveSkill: (skill: string | null) => void;\n}\n\nconst GatewayContext = createContext<GatewayContextValue | null>(null);\nGatewayContext.displayName = 'GatewayContext';\n\nexport function GatewayContextProvider({ children }: { children: ReactNode }) {\n const { gateways, gatewayList, loading } = useGatewayRegistry();\n const safeGateways = gateways && typeof gateways === 'object' ? gateways : {};\n const safeGatewayList = Array.isArray(gatewayList) ? gatewayList : [];\n const hasGateway = (gatewayId: string) => Object.prototype.hasOwnProperty.call(safeGateways, gatewayId);\n\n const [selectedGatewayId, setGatewayId] = useState<GatewayId>('cdecli');\n const [activeSkill, setActiveSkill] = useState<string | null>(null);\n const [storageReady, setStorageReady] = useState(false);\n\n useEffect(() => {\n let cancelled = false;\n GatewaySelectionStorage.load().then((s) => {\n if (cancelled) return;\n if (s.selectedGatewayId) {\n setGatewayId(s.selectedGatewayId);\n }\n setStorageReady(true);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n if (!storageReady || loading) return;\n if (selectedGatewayId && hasGateway(selectedGatewayId)) return;\n const fallbackId = hasGateway('cdecli') ? 'cdecli' : safeGatewayList[0]?.id || '';\n if (fallbackId) {\n setGatewayId(fallbackId);\n GatewaySelectionStorage.save({ selectedGatewayId: fallbackId });\n }\n }, [storageReady, loading, safeGateways, safeGatewayList, selectedGatewayId]);\n\n const setSelectedGateway = useCallback(\n (gatewayId: GatewayId) => {\n if (!hasGateway(gatewayId)) return;\n setGatewayId(gatewayId);\n void GatewaySelectionStorage.save({ selectedGatewayId: gatewayId });\n setActiveSkill(null);\n },\n [safeGateways],\n );\n\n const selectedGateway: GatewayEntry = (selectedGatewayId && safeGateways[selectedGatewayId]) ||\n safeGatewayList[0] || {\n name: '',\n description: '',\n channelType: '',\n extensionId: '',\n icon: 'plug',\n isBuiltin: false,\n priority: 0,\n };\n\n const value = useMemo<GatewayContextValue>(\n () => ({\n selectedGatewayId,\n selectedGateway,\n gateways: safeGateways,\n gatewayList: safeGatewayList,\n setSelectedGateway,\n loading,\n activeSkill,\n setActiveSkill,\n }),\n [selectedGatewayId, selectedGateway, safeGateways, safeGatewayList, setSelectedGateway, loading, activeSkill],\n );\n\n return <GatewayContext.Provider value={value}>{children}</GatewayContext.Provider>;\n}\n\nexport function useGatewayContext(): GatewayContextValue {\n const context = useContext(GatewayContext);\n if (!context) {\n throw new Error('useGatewayContext must be used within GatewayContextProvider');\n }\n return context;\n}\n\n/** Split the comma-separated {@link GatewayContextValue.activeSkill} into its skill keys. */\nexport function parseActiveSkills(activeSkill: string | null | undefined): string[] {\n if (!activeSkill) return [];\n return activeSkill\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\n/** Last segment of a namespaced key (`Non-designer-skill/soft-skill` → `soft-skill`). */\nexport function skillDisplayName(skillKey: string): string {\n return skillKey.split('/').pop() || skillKey;\n}\n"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"GatewayContext.js","sources":["../../src/contexts/GatewayContext.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\nimport type { GatewayEntry, GatewayId } from '../config/constants';\nimport { useGatewayRegistry } from '../hooks/useGatewayRegistry';\nimport { GatewaySelectionStorage } from '../utils/gatewaySelectionStorage';\n\nexport interface GatewayContextValue {\n selectedGatewayId: GatewayId;\n selectedGateway: GatewayEntry;\n gateways: Record<string, GatewayEntry>;\n gatewayList: Array<{ id: string } & GatewayEntry>;\n setSelectedGateway: (gatewayId: GatewayId) => void;\n loading: boolean;\n activeSkill: string | null;\n setActiveSkill: (skill: string | null) => void;\n}\n\nconst GatewayContext = createContext<GatewayContextValue | null>(null);\nGatewayContext.displayName = 'GatewayContext';\n\nexport function GatewayContextProvider({ children }: { children: ReactNode }) {\n const { gateways, gatewayList, loading } = useGatewayRegistry();\n const safeGateways = gateways && typeof gateways === 'object' ? gateways : {};\n const safeGatewayList = Array.isArray(gatewayList) ? gatewayList : [];\n const hasGateway = (gatewayId: string) => Object.prototype.hasOwnProperty.call(safeGateways, gatewayId);\n\n const [selectedGatewayId, setGatewayId] = useState<GatewayId>('cdecli');\n const [activeSkill, setActiveSkill] = useState<string | null>(null);\n const [storageReady, setStorageReady] = useState(false);\n\n useEffect(() => {\n let cancelled = false;\n GatewaySelectionStorage.load().then((s) => {\n if (cancelled) return;\n if (s.selectedGatewayId) {\n setGatewayId(s.selectedGatewayId);\n }\n setStorageReady(true);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n if (!storageReady || loading) return;\n if (selectedGatewayId && hasGateway(selectedGatewayId)) return;\n const fallbackId = hasGateway('cdecli') ? 'cdecli' : safeGatewayList[0]?.id || '';\n if (fallbackId) {\n setGatewayId(fallbackId);\n GatewaySelectionStorage.save({ selectedGatewayId: fallbackId });\n }\n }, [storageReady, loading, safeGateways, safeGatewayList, selectedGatewayId]);\n\n const setSelectedGateway = useCallback(\n (gatewayId: GatewayId) => {\n if (!hasGateway(gatewayId)) return;\n setGatewayId(gatewayId);\n void GatewaySelectionStorage.save({ selectedGatewayId: gatewayId });\n setActiveSkill(null);\n },\n [safeGateways],\n );\n\n const selectedGateway: GatewayEntry = (selectedGatewayId && safeGateways[selectedGatewayId]) ||\n safeGatewayList[0] || {\n name: '',\n description: '',\n channelType: '',\n extensionId: '',\n icon: 'plug',\n isBuiltin: false,\n priority: 0,\n };\n\n const value = useMemo<GatewayContextValue>(\n () => ({\n selectedGatewayId,\n selectedGateway,\n gateways: safeGateways,\n gatewayList: safeGatewayList,\n setSelectedGateway,\n loading,\n activeSkill,\n setActiveSkill,\n }),\n [selectedGatewayId, selectedGateway, safeGateways, safeGatewayList, setSelectedGateway, loading, activeSkill],\n );\n\n return <GatewayContext.Provider value={value}>{children}</GatewayContext.Provider>;\n}\n\nexport function useGatewayContext(): GatewayContextValue {\n const context = useContext(GatewayContext);\n if (!context) {\n throw new Error('useGatewayContext must be used within GatewayContextProvider');\n }\n return context;\n}\n\n/** Split the comma-separated {@link GatewayContextValue.activeSkill} into its skill keys. */\nexport function parseActiveSkills(activeSkill: string | null | undefined): string[] {\n if (!activeSkill) return [];\n return activeSkill\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\n/** Last segment of a namespaced key (`Non-designer-skill/soft-skill` → `soft-skill`). */\nexport function skillDisplayName(skillKey: string): string {\n return skillKey.split('/').pop() || skillKey;\n}\n"],"names":[],"mappings":"kQAiBA,MAAM,cAAA,GAAiB,cAA0C,IAAI,CAAA;AACrE,cAAA,CAAe,WAAc,GAAA,gBAAA;AACtB,SAAS,sBAAuB,CAAA;AAAA,EACrC;AACF,CAEG,EAAA;AACD,EAAM,MAAA;AAAA,IACJ,QAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,MACE,kBAAmB,EAAA;AACvB,EAAA,MAAM,eAAe,QAAY,IAAA,OAAO,QAAa,KAAA,QAAA,GAAW,WAAW,EAAC;AAC5E,EAAA,MAAM,kBAAkB,KAAM,CAAA,OAAA,CAAQ,WAAW,CAAA,GAAI,cAAc,EAAC;AACpE,EAAM,MAAA,UAAA,GAAa,CAAC,SAAsB,KAAA,MAAA,CAAO,UAAU,cAAe,CAAA,IAAA,CAAK,cAAc,SAAS,CAAA;AACtG,EAAA,MAAM,CAAC,iBAAA,EAAmB,YAAY,CAAA,GAAI,SAAoB,QAAQ,CAAA;AACtE,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAwB,IAAI,CAAA;AAClE,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,KAAK,CAAA;AACtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAY,GAAA,KAAA;AAChB,IAAwB,uBAAA,CAAA,IAAA,EAAO,CAAA,IAAA,CAAK,CAAK,CAAA,KAAA;AACvC,MAAA,IAAI,SAAW,EAAA;AACf,MAAA,IAAI,EAAE,iBAAmB,EAAA;AACvB,QAAA,YAAA,CAAa,EAAE,iBAAiB,CAAA;AAAA;AAElC,MAAA,eAAA,CAAgB,IAAI,CAAA;AAAA,KACrB,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAY,SAAA,GAAA,IAAA;AAAA,KACd;AAAA,GACF,EAAG,EAAE,CAAA;AACL,EAAA,SAAA,CAAU,MAAM;AAhDlB,IAAA,IAAA,EAAA;AAiDI,IAAI,IAAA,CAAC,gBAAgB,OAAS,EAAA;AAC9B,IAAI,IAAA,iBAAA,IAAqB,UAAW,CAAA,iBAAiB,CAAG,EAAA;AACxD,IAAM,MAAA,UAAA,GAAa,WAAW,QAAQ,CAAA,GAAI,aAAW,EAAgB,GAAA,eAAA,CAAA,CAAC,CAAjB,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAoB,EAAM,KAAA,EAAA;AAC/E,IAAA,IAAI,UAAY,EAAA;AACd,MAAA,YAAA,CAAa,UAAU,CAAA;AACvB,MAAA,uBAAA,CAAwB,IAAK,CAAA;AAAA,QAC3B,iBAAmB,EAAA;AAAA,OACpB,CAAA;AAAA;AACH,KACC,CAAC,YAAA,EAAc,SAAS,YAAc,EAAA,eAAA,EAAiB,iBAAiB,CAAC,CAAA;AAC5E,EAAM,MAAA,kBAAA,GAAqB,WAAY,CAAA,CAAC,SAAyB,KAAA;AAC/D,IAAI,IAAA,CAAC,UAAW,CAAA,SAAS,CAAG,EAAA;AAC5B,IAAA,YAAA,CAAa,SAAS,CAAA;AACtB,IAAA,KAAK,wBAAwB,IAAK,CAAA;AAAA,MAChC,iBAAmB,EAAA;AAAA,KACpB,CAAA;AACD,IAAA,cAAA,CAAe,IAAI,CAAA;AAAA,GACrB,EAAG,CAAC,YAAY,CAAC,CAAA;AACjB,EAAA,MAAM,kBAAgC,iBAAqB,IAAA,YAAA,CAAa,iBAAiB,CAAK,IAAA,eAAA,CAAgB,CAAC,CAAK,IAAA;AAAA,IAClH,IAAM,EAAA,EAAA;AAAA,IACN,WAAa,EAAA,EAAA;AAAA,IACb,WAAa,EAAA,EAAA;AAAA,IACb,WAAa,EAAA,EAAA;AAAA,IACb,IAAM,EAAA,MAAA;AAAA,IACN,SAAW,EAAA,KAAA;AAAA,IACX,QAAU,EAAA;AAAA,GACZ;AACA,EAAM,MAAA,KAAA,GAAQ,QAA6B,OAAO;AAAA,IAChD,iBAAA;AAAA,IACA,eAAA;AAAA,IACA,QAAU,EAAA,YAAA;AAAA,IACV,WAAa,EAAA,eAAA;AAAA,IACb,kBAAA;AAAA,IACA,OAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF,CAAA,EAAI,CAAC,iBAAmB,EAAA,eAAA,EAAiB,cAAc,eAAiB,EAAA,kBAAA,EAAoB,OAAS,EAAA,WAAW,CAAC,CAAA;AACjH,EAAA,uBAAQ,GAAA,CAAA,cAAA,CAAe,QAAf,EAAA,EAAwB,OAAe,QAAS,EAAA,CAAA;AAC1D;AACO,SAAS,iBAAyC,GAAA;AACvD,EAAM,MAAA,OAAA,GAAU,WAAW,cAAc,CAAA;AACzC,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAM,MAAA,IAAI,MAAM,8DAA8D,CAAA;AAAA;AAEhF,EAAO,OAAA,OAAA;AACT;AAGO,SAAS,kBAAkB,WAAkD,EAAA;AAClF,EAAI,IAAA,CAAC,WAAa,EAAA,OAAO,EAAC;AAC1B,EAAO,OAAA,WAAA,CAAY,KAAM,CAAA,GAAG,CAAE,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA,CAAA,CAAE,IAAK,EAAC,CAAE,CAAA,MAAA,CAAO,OAAO,CAAA;AACjE"}
|