@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.
@@ -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
- maxHeight: windowHeight * 0.72,
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({ visible, title, subtitle, isDark, onClose, headerRight, children }: HeaderSheetProps) {\n const insets = useSafeAreaInsets();\n const { height: windowHeight } = useWindowDimensions();\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 maxHeight: windowHeight * 0.72,\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 {children}\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});\n"],"names":[],"mappings":"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"}
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,useMemo,useCallback}from'react';import {ScrollView,StyleSheet,Text,Pressable,View}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useGatewayContext,parseActiveSkills,skillDisplayName}from'../../contexts/GatewayContext.js';import {useAgentSessionState}from'../../hooks/useAgentSessionState.js';import {mobileTokens}from'../../theme/mobileTokens.js';import {HeaderSheet}from'./HeaderSheet.js';import {HeaderToolbarButton}from'./HeaderToolbarButton.js';const BUILTIN_SKILLS = [{
2
- key: "yantra-github-search",
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(SkillsSheet, { isDark, onClose: () => setOpen(false) }) : null
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,View}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {MAX_CONCURRENT_TASKS}from'../../config/constants.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 = {
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 statusColor(status, isDark) {
10
- if (status === "running" || status === "connecting") return isDark ? "#60a5fa" : "#2563eb";
11
- if (status === "completed") return isDark ? "#4ade80" : "#16a34a";
12
- if (status === "failed") return isDark ? "#f87171" : "#dc2626";
13
- if (status === "aborted") return isDark ? "#fb923c" : "#ea580c";
14
- return isDark ? "#94a3b8" : mobileTokens.color.textMuted;
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 > 72 ? `${last.content.slice(0, 72)}\u2026` : last.content : "No messages yet";
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(View, { style: [styles.dot, {
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__ */ jsx(Text, { style: [styles.rowTitle, {
35
- color: foreground
36
- }], numberOfLines: 1, children: task.title }),
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: "close", size: 16, color: muted }) })
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 foreground = isDark ? "#e2e8f0" : mobileTokens.color.text;
55
- const canCreate = session.tasks.length < MAX_CONCURRENT_TASKS;
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: session.gatewayConnected ? `${session.tasks.length} of ${MAX_CONCURRENT_TASKS} slots` : "Connect Yantra to keep agent sessions running", isDark, onClose, headerRight: /* @__PURE__ */ jsxs(Pressable, { onPress: handleNew, disabled: !canCreate, accessibilityLabel: "Start new task", style: ({
62
- pressed
63
- }) => [styles.newBtn, pressed && styles.pressed, !canCreate && styles.disabled], children: [
64
- /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "plus", size: 16, color: mobileTokens.color.primary }),
65
- /* @__PURE__ */ jsx(Text, { style: styles.newBtnLabel, children: "New" })
66
- ] }), children: /* @__PURE__ */ jsxs(ScrollView, { contentContainerStyle: styles.list, keyboardShouldPersistTaps: "handled", children: [
67
- session.tasks.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [styles.empty, {
68
- color: muted
69
- }], children: "No running tasks. Start one to keep an agent session alive alongside chat." }) : 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)),
70
- !session.gatewayConnected ? /* @__PURE__ */ jsx(Text, { style: [styles.hint, {
71
- color: foreground
72
- }], children: "Tasks stay on this device until Yantra is connected." }) : null
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: "center",
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
- dot: {
116
- width: 8,
117
- height: 8,
118
- borderRadius: 4
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
- hint: {
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: 2,
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
- paddingHorizontal: 8,
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":"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;AAGO,SAAS,iBAAiB,QAA0B,EAAA;AACzD,EAAA,OAAO,QAAS,CAAA,KAAA,CAAM,GAAG,CAAA,CAAE,KAAS,IAAA,QAAA;AACtC"}
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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"}