@adminide-stack/yantra-mobile 12.0.49-alpha.0 → 12.0.49-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/config/env-config.js +4 -0
- package/lib/config/env-config.js.map +1 -1
- package/lib/contexts/GatewayContext.js +1 -4
- package/lib/contexts/GatewayContext.js.map +1 -1
- package/lib/features/apps/AppsCatalog.js +4 -1
- package/lib/features/apps/AppsCatalog.js.map +1 -1
- package/lib/features/canvas/surfaceIndex.js +9 -1
- package/lib/features/canvas/surfaceIndex.js.map +1 -1
- package/lib/features/canvas/useCanvasSession.js +25 -9
- package/lib/features/canvas/useCanvasSession.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
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {useState,useMemo}from'react';import {Modal,Pressable,StyleSheet,View,Text,TextInput,FlatList}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {BUILTIN_SKILL_TEMPLATES}from'./skillTemplates.js';import {useGatewaySkills}from'./useGatewaySkills.js';function SkillTemplatePicker({
|
|
2
|
+
open,
|
|
3
|
+
isDark,
|
|
4
|
+
onClose,
|
|
5
|
+
onSelectTemplate,
|
|
6
|
+
onSelectSkills
|
|
7
|
+
}) {
|
|
8
|
+
const [tab, setTab] = useState("templates");
|
|
9
|
+
const [query, setQuery] = useState("");
|
|
10
|
+
const [picked, setPicked] = useState(/* @__PURE__ */ new Set());
|
|
11
|
+
const gateway = useGatewaySkills();
|
|
12
|
+
const c = palette(isDark);
|
|
13
|
+
const needle = query.trim().toLowerCase();
|
|
14
|
+
const templates = useMemo(() => needle ? BUILTIN_SKILL_TEMPLATES.filter((t) => [t.name, t.description, ...t.tags].join(" ").toLowerCase().includes(needle)) : BUILTIN_SKILL_TEMPLATES, [needle]);
|
|
15
|
+
const skills = useMemo(() => needle ? gateway.skills.filter((s) => {
|
|
16
|
+
var _a;
|
|
17
|
+
return [s.skillKey, s.name, (_a = s.description) != null ? _a : ""].join(" ").toLowerCase().includes(needle);
|
|
18
|
+
}) : gateway.skills, [needle, gateway.skills]);
|
|
19
|
+
const togglePick = (key) => setPicked((prev) => {
|
|
20
|
+
const next = new Set(prev);
|
|
21
|
+
if (next.has(key)) next.delete(key);
|
|
22
|
+
else next.add(key);
|
|
23
|
+
return next;
|
|
24
|
+
});
|
|
25
|
+
const applyPicked = () => {
|
|
26
|
+
const chosen = gateway.skills.filter((s) => picked.has(s.skillKey));
|
|
27
|
+
if (chosen.length && onSelectSkills) onSelectSkills(chosen);
|
|
28
|
+
onClose();
|
|
29
|
+
};
|
|
30
|
+
return /* @__PURE__ */ jsxs(Modal, { visible: open, transparent: true, animationType: "slide", onRequestClose: onClose, children: [
|
|
31
|
+
/* @__PURE__ */ jsx(Pressable, { style: styles.scrim, onPress: onClose, accessibilityLabel: "Close skills" }),
|
|
32
|
+
/* @__PURE__ */ jsxs(View, { style: [styles.sheet, {
|
|
33
|
+
backgroundColor: c.bg
|
|
34
|
+
}], children: [
|
|
35
|
+
/* @__PURE__ */ jsx(View, { style: styles.grabber }),
|
|
36
|
+
/* @__PURE__ */ jsxs(View, { style: styles.head, children: [
|
|
37
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.title, {
|
|
38
|
+
color: c.text
|
|
39
|
+
}], children: "Skills" }),
|
|
40
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: onClose, hitSlop: 10, accessibilityRole: "button", accessibilityLabel: "Close", children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "close", size: 21, color: c.text }) })
|
|
41
|
+
] }),
|
|
42
|
+
/* @__PURE__ */ jsx(View, { style: styles.tabs, children: [{
|
|
43
|
+
id: "templates",
|
|
44
|
+
label: "Templates"
|
|
45
|
+
}, {
|
|
46
|
+
id: "skills",
|
|
47
|
+
label: `Gateway skills${gateway.skills.length ? ` (${gateway.skills.length})` : ""}`
|
|
48
|
+
}].map((entry) => {
|
|
49
|
+
const active = tab === entry.id;
|
|
50
|
+
return /* @__PURE__ */ jsx(Pressable, { onPress: () => setTab(entry.id), style: [styles.tab, active && {
|
|
51
|
+
backgroundColor: c.raised
|
|
52
|
+
}], accessibilityRole: "tab", accessibilityState: {
|
|
53
|
+
selected: active
|
|
54
|
+
}, children: /* @__PURE__ */ jsx(Text, { style: [styles.tabLabel, {
|
|
55
|
+
color: active ? c.text : c.dim
|
|
56
|
+
}], children: entry.label }) }, entry.id);
|
|
57
|
+
}) }),
|
|
58
|
+
/* @__PURE__ */ jsxs(View, { style: [styles.search, {
|
|
59
|
+
backgroundColor: c.raised
|
|
60
|
+
}], children: [
|
|
61
|
+
/* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "magnify", size: 16, color: c.dim }),
|
|
62
|
+
/* @__PURE__ */ jsx(TextInput, { value: query, onChangeText: setQuery, placeholder: tab === "templates" ? "Search templates\u2026" : "Search skills\u2026", placeholderTextColor: c.faint, style: [styles.searchInput, {
|
|
63
|
+
color: c.text
|
|
64
|
+
}], selectionColor: "#7c3aed" })
|
|
65
|
+
] }),
|
|
66
|
+
tab === "templates" ? /* @__PURE__ */ jsx(FlatList, { data: templates, keyExtractor: (t) => t.id, contentContainerStyle: styles.list, ListEmptyComponent: /* @__PURE__ */ jsxs(Text, { style: [styles.empty, {
|
|
67
|
+
color: c.dim
|
|
68
|
+
}], children: [
|
|
69
|
+
'No template matches "',
|
|
70
|
+
query.trim(),
|
|
71
|
+
'".'
|
|
72
|
+
] }), renderItem: ({
|
|
73
|
+
item
|
|
74
|
+
}) => /* @__PURE__ */ jsxs(Pressable, { onPress: () => {
|
|
75
|
+
onSelectTemplate == null ? void 0 : onSelectTemplate(item);
|
|
76
|
+
onClose();
|
|
77
|
+
}, style: [styles.row, {
|
|
78
|
+
backgroundColor: c.raised
|
|
79
|
+
}], accessibilityRole: "button", accessibilityLabel: item.name, children: [
|
|
80
|
+
/* @__PURE__ */ jsx(Text, { style: styles.rowIcon, children: item.icon }),
|
|
81
|
+
/* @__PURE__ */ jsxs(View, { style: styles.rowBody, children: [
|
|
82
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.rowTitle, {
|
|
83
|
+
color: c.text
|
|
84
|
+
}], children: item.name }),
|
|
85
|
+
/* @__PURE__ */ jsx(Text, { numberOfLines: 2, style: [styles.rowDetail, {
|
|
86
|
+
color: c.dim
|
|
87
|
+
}], children: item.description }),
|
|
88
|
+
/* @__PURE__ */ jsxs(Text, { style: [styles.rowMeta, {
|
|
89
|
+
color: c.faint
|
|
90
|
+
}], children: [
|
|
91
|
+
item.category,
|
|
92
|
+
item.model ? ` \xB7 ${item.model}` : ""
|
|
93
|
+
] })
|
|
94
|
+
] }),
|
|
95
|
+
/* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "chevron-right", size: 19, color: c.faint })
|
|
96
|
+
] }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
97
|
+
/* @__PURE__ */ jsx(FlatList, { data: skills, keyExtractor: (s) => s.skillKey, contentContainerStyle: styles.list, ListEmptyComponent: /* @__PURE__ */ jsx(Text, { style: [styles.empty, {
|
|
98
|
+
color: c.dim
|
|
99
|
+
}], children: gateway.loading ? "Loading skills\u2026" : gateway.source === "none" ? "The selected gateway does not report installed skills." : needle ? `No skill matches "${query.trim()}".` : "No skills installed on this gateway." }), renderItem: ({
|
|
100
|
+
item
|
|
101
|
+
}) => {
|
|
102
|
+
var _a;
|
|
103
|
+
const selected = picked.has(item.skillKey);
|
|
104
|
+
return /* @__PURE__ */ jsxs(Pressable, { onPress: () => togglePick(item.skillKey), style: [styles.row, {
|
|
105
|
+
backgroundColor: c.raised
|
|
106
|
+
}, selected && styles.rowPicked], accessibilityRole: "checkbox", accessibilityState: {
|
|
107
|
+
checked: selected
|
|
108
|
+
}, accessibilityLabel: item.name || item.skillKey, children: [
|
|
109
|
+
/* @__PURE__ */ jsx(MaterialCommunityIcons, { name: selected ? "checkbox-marked" : "checkbox-blank-outline", size: 19, color: selected ? "#7c3aed" : c.dim }),
|
|
110
|
+
/* @__PURE__ */ jsxs(View, { style: styles.rowBody, children: [
|
|
111
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.rowTitle, {
|
|
112
|
+
color: c.text
|
|
113
|
+
}], children: item.name || item.skillKey }),
|
|
114
|
+
item.description ? /* @__PURE__ */ jsx(Text, { numberOfLines: 2, style: [styles.rowDetail, {
|
|
115
|
+
color: c.dim
|
|
116
|
+
}], children: item.description }) : null,
|
|
117
|
+
((_a = item.subSkills) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsxs(Text, { style: [styles.rowMeta, {
|
|
118
|
+
color: c.faint
|
|
119
|
+
}], children: [
|
|
120
|
+
"bundle \xB7 ",
|
|
121
|
+
item.subSkills.length,
|
|
122
|
+
" skills"
|
|
123
|
+
] }) : null
|
|
124
|
+
] })
|
|
125
|
+
] });
|
|
126
|
+
} }),
|
|
127
|
+
picked.size > 0 ? /* @__PURE__ */ jsx(Pressable, { onPress: applyPicked, style: styles.apply, accessibilityRole: "button", children: /* @__PURE__ */ jsxs(Text, { style: styles.applyLabel, children: [
|
|
128
|
+
"Enable ",
|
|
129
|
+
picked.size,
|
|
130
|
+
" skill",
|
|
131
|
+
picked.size === 1 ? "" : "s"
|
|
132
|
+
] }) }) : null
|
|
133
|
+
] })
|
|
134
|
+
] })
|
|
135
|
+
] });
|
|
136
|
+
}
|
|
137
|
+
function palette(isDark) {
|
|
138
|
+
return isDark ? {
|
|
139
|
+
bg: "#0f172a",
|
|
140
|
+
raised: "#1e293b",
|
|
141
|
+
text: "#f8fafc",
|
|
142
|
+
dim: "#94a3b8",
|
|
143
|
+
faint: "#64748b"
|
|
144
|
+
} : {
|
|
145
|
+
bg: "#ffffff",
|
|
146
|
+
raised: "#f1f5f9",
|
|
147
|
+
text: "#0f172a",
|
|
148
|
+
dim: "#64748b",
|
|
149
|
+
faint: "#94a3b8"
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
const styles = StyleSheet.create({
|
|
153
|
+
scrim: {
|
|
154
|
+
flex: 1,
|
|
155
|
+
backgroundColor: "rgba(2, 6, 23, 0.45)"
|
|
156
|
+
},
|
|
157
|
+
sheet: {
|
|
158
|
+
maxHeight: "82%",
|
|
159
|
+
borderTopLeftRadius: 20,
|
|
160
|
+
borderTopRightRadius: 20,
|
|
161
|
+
paddingHorizontal: 16,
|
|
162
|
+
paddingBottom: 18
|
|
163
|
+
},
|
|
164
|
+
grabber: {
|
|
165
|
+
alignSelf: "center",
|
|
166
|
+
width: 36,
|
|
167
|
+
height: 4,
|
|
168
|
+
borderRadius: 2,
|
|
169
|
+
backgroundColor: "rgba(148, 163, 184, 0.5)",
|
|
170
|
+
marginVertical: 8
|
|
171
|
+
},
|
|
172
|
+
head: {
|
|
173
|
+
flexDirection: "row",
|
|
174
|
+
alignItems: "center",
|
|
175
|
+
justifyContent: "space-between",
|
|
176
|
+
paddingVertical: 4
|
|
177
|
+
},
|
|
178
|
+
title: {
|
|
179
|
+
fontSize: 17,
|
|
180
|
+
fontWeight: "700"
|
|
181
|
+
},
|
|
182
|
+
tabs: {
|
|
183
|
+
flexDirection: "row",
|
|
184
|
+
gap: 8,
|
|
185
|
+
paddingVertical: 8
|
|
186
|
+
},
|
|
187
|
+
tab: {
|
|
188
|
+
paddingHorizontal: 12,
|
|
189
|
+
paddingVertical: 7,
|
|
190
|
+
borderRadius: 999
|
|
191
|
+
},
|
|
192
|
+
tabLabel: {
|
|
193
|
+
fontSize: 13,
|
|
194
|
+
fontWeight: "600"
|
|
195
|
+
},
|
|
196
|
+
search: {
|
|
197
|
+
flexDirection: "row",
|
|
198
|
+
alignItems: "center",
|
|
199
|
+
gap: 7,
|
|
200
|
+
paddingHorizontal: 11,
|
|
201
|
+
borderRadius: 11,
|
|
202
|
+
marginBottom: 8
|
|
203
|
+
},
|
|
204
|
+
searchInput: {
|
|
205
|
+
flex: 1,
|
|
206
|
+
fontSize: 14,
|
|
207
|
+
paddingVertical: 9
|
|
208
|
+
},
|
|
209
|
+
list: {
|
|
210
|
+
gap: 8,
|
|
211
|
+
paddingBottom: 8
|
|
212
|
+
},
|
|
213
|
+
empty: {
|
|
214
|
+
fontSize: 13,
|
|
215
|
+
textAlign: "center",
|
|
216
|
+
paddingVertical: 22,
|
|
217
|
+
paddingHorizontal: 12,
|
|
218
|
+
lineHeight: 19
|
|
219
|
+
},
|
|
220
|
+
row: {
|
|
221
|
+
flexDirection: "row",
|
|
222
|
+
alignItems: "center",
|
|
223
|
+
gap: 11,
|
|
224
|
+
padding: 12,
|
|
225
|
+
borderRadius: 13
|
|
226
|
+
},
|
|
227
|
+
rowPicked: {
|
|
228
|
+
borderWidth: 1,
|
|
229
|
+
borderColor: "#7c3aed"
|
|
230
|
+
},
|
|
231
|
+
rowIcon: {
|
|
232
|
+
fontSize: 20
|
|
233
|
+
},
|
|
234
|
+
rowBody: {
|
|
235
|
+
flex: 1,
|
|
236
|
+
gap: 2
|
|
237
|
+
},
|
|
238
|
+
rowTitle: {
|
|
239
|
+
fontSize: 14,
|
|
240
|
+
fontWeight: "600"
|
|
241
|
+
},
|
|
242
|
+
rowDetail: {
|
|
243
|
+
fontSize: 12,
|
|
244
|
+
lineHeight: 16.5
|
|
245
|
+
},
|
|
246
|
+
rowMeta: {
|
|
247
|
+
fontSize: 10.5
|
|
248
|
+
},
|
|
249
|
+
apply: {
|
|
250
|
+
alignItems: "center",
|
|
251
|
+
paddingVertical: 13,
|
|
252
|
+
borderRadius: 13,
|
|
253
|
+
backgroundColor: "#7c3aed",
|
|
254
|
+
marginTop: 4
|
|
255
|
+
},
|
|
256
|
+
applyLabel: {
|
|
257
|
+
color: "#ffffff",
|
|
258
|
+
fontSize: 14.5,
|
|
259
|
+
fontWeight: "700"
|
|
260
|
+
}
|
|
261
|
+
});export{SkillTemplatePicker};//# sourceMappingURL=SkillTemplatePicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkillTemplatePicker.js","sources":["../../../src/features/skills/SkillTemplatePicker.tsx"],"sourcesContent":["/**\n * Skill template picker - the mobile twin of the browser's\n * SkillTemplatePicker, sized for a phone sheet. Two tabs:\n *\n * - Templates: the built-in skill templates (soul + required skills + model)\n * -> `onSelectTemplate` starts an agent task from one.\n * - Skills: whatever the SELECTED gateway reports as installed\n * (useGatewaySkills) -> multi-select -> `onSelectSkills` enables them.\n *\n * The callbacks are the contract HeaderSkillsButton already speaks; this\n * component owns only presentation and selection state.\n */\nimport React, { useMemo, useState } from 'react';\nimport { FlatList, Modal, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { BUILTIN_SKILL_TEMPLATES, type SkillTemplate } from './skillTemplates';\nimport { useGatewaySkills, type GatewaySkillEntry } from './useGatewaySkills';\n\nexport interface SkillTemplatePickerProps {\n open: boolean;\n isDark: boolean;\n onClose: () => void;\n onSelectTemplate?: (template: SkillTemplate) => void;\n onSelectSkills?: (skills: GatewaySkillEntry[]) => void;\n}\n\ntype Tab = 'templates' | 'skills';\n\nexport function SkillTemplatePicker({\n open,\n isDark,\n onClose,\n onSelectTemplate,\n onSelectSkills,\n}: SkillTemplatePickerProps) {\n const [tab, setTab] = useState<Tab>('templates');\n const [query, setQuery] = useState('');\n const [picked, setPicked] = useState<Set<string>>(new Set());\n const gateway = useGatewaySkills();\n const c = palette(isDark);\n\n const needle = query.trim().toLowerCase();\n const templates = useMemo(\n () =>\n needle\n ? BUILTIN_SKILL_TEMPLATES.filter((t) =>\n [t.name, t.description, ...t.tags].join(' ').toLowerCase().includes(needle),\n )\n : BUILTIN_SKILL_TEMPLATES,\n [needle],\n );\n const skills = useMemo(\n () =>\n needle\n ? gateway.skills.filter((s) =>\n [s.skillKey, s.name, s.description ?? ''].join(' ').toLowerCase().includes(needle),\n )\n : gateway.skills,\n [needle, gateway.skills],\n );\n\n const togglePick = (key: string) =>\n setPicked((prev) => {\n const next = new Set(prev);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n\n const applyPicked = () => {\n const chosen = gateway.skills.filter((s) => picked.has(s.skillKey));\n if (chosen.length && onSelectSkills) onSelectSkills(chosen);\n onClose();\n };\n\n return (\n <Modal visible={open} transparent animationType=\"slide\" onRequestClose={onClose}>\n <Pressable style={styles.scrim} onPress={onClose} accessibilityLabel=\"Close skills\" />\n <View style={[styles.sheet, { backgroundColor: c.bg }]}>\n <View style={styles.grabber} />\n <View style={styles.head}>\n <Text style={[styles.title, { color: c.text }]}>Skills</Text>\n <Pressable onPress={onClose} hitSlop={10} accessibilityRole=\"button\" accessibilityLabel=\"Close\">\n <MaterialCommunityIcons name=\"close\" size={21} color={c.text} />\n </Pressable>\n </View>\n <View style={styles.tabs}>\n {(\n [\n { id: 'templates' as Tab, label: 'Templates' },\n {\n id: 'skills' as Tab,\n label: `Gateway skills${gateway.skills.length ? ` (${gateway.skills.length})` : ''}`,\n },\n ] as const\n ).map((entry) => {\n const active = tab === entry.id;\n return (\n <Pressable\n key={entry.id}\n onPress={() => setTab(entry.id)}\n style={[styles.tab, active && { backgroundColor: c.raised }]}\n accessibilityRole=\"tab\"\n accessibilityState={{ selected: active }}\n >\n <Text style={[styles.tabLabel, { color: active ? c.text : c.dim }]}>{entry.label}</Text>\n </Pressable>\n );\n })}\n </View>\n <View style={[styles.search, { backgroundColor: c.raised }]}>\n <MaterialCommunityIcons name=\"magnify\" size={16} color={c.dim} />\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder={tab === 'templates' ? 'Search templates…' : 'Search skills…'}\n placeholderTextColor={c.faint}\n style={[styles.searchInput, { color: c.text }]}\n selectionColor=\"#7c3aed\"\n />\n </View>\n\n {tab === 'templates' ? (\n <FlatList\n data={templates}\n keyExtractor={(t) => t.id}\n contentContainerStyle={styles.list}\n ListEmptyComponent={\n <Text style={[styles.empty, { color: c.dim }]}>No template matches \"{query.trim()}\".</Text>\n }\n renderItem={({ item }) => (\n <Pressable\n onPress={() => {\n onSelectTemplate?.(item);\n onClose();\n }}\n style={[styles.row, { backgroundColor: c.raised }]}\n accessibilityRole=\"button\"\n accessibilityLabel={item.name}\n >\n <Text style={styles.rowIcon}>{item.icon}</Text>\n <View style={styles.rowBody}>\n <Text style={[styles.rowTitle, { color: c.text }]}>{item.name}</Text>\n <Text numberOfLines={2} style={[styles.rowDetail, { color: c.dim }]}>\n {item.description}\n </Text>\n <Text style={[styles.rowMeta, { color: c.faint }]}>\n {item.category}\n {item.model ? ` · ${item.model}` : ''}\n </Text>\n </View>\n <MaterialCommunityIcons name=\"chevron-right\" size={19} color={c.faint} />\n </Pressable>\n )}\n />\n ) : (\n <>\n <FlatList\n data={skills}\n keyExtractor={(s) => s.skillKey}\n contentContainerStyle={styles.list}\n ListEmptyComponent={\n <Text style={[styles.empty, { color: c.dim }]}>\n {gateway.loading\n ? 'Loading skills…'\n : gateway.source === 'none'\n ? 'The selected gateway does not report installed skills.'\n : needle\n ? `No skill matches \"${query.trim()}\".`\n : 'No skills installed on this gateway.'}\n </Text>\n }\n renderItem={({ item }) => {\n const selected = picked.has(item.skillKey);\n return (\n <Pressable\n onPress={() => togglePick(item.skillKey)}\n style={[\n styles.row,\n { backgroundColor: c.raised },\n selected && styles.rowPicked,\n ]}\n accessibilityRole=\"checkbox\"\n accessibilityState={{ checked: selected }}\n accessibilityLabel={item.name || item.skillKey}\n >\n <MaterialCommunityIcons\n name={selected ? 'checkbox-marked' : 'checkbox-blank-outline'}\n size={19}\n color={selected ? '#7c3aed' : c.dim}\n />\n <View style={styles.rowBody}>\n <Text style={[styles.rowTitle, { color: c.text }]}>\n {item.name || item.skillKey}\n </Text>\n {item.description ? (\n <Text numberOfLines={2} style={[styles.rowDetail, { color: c.dim }]}>\n {item.description}\n </Text>\n ) : null}\n {item.subSkills?.length ? (\n <Text style={[styles.rowMeta, { color: c.faint }]}>\n bundle · {item.subSkills.length} skills\n </Text>\n ) : null}\n </View>\n </Pressable>\n );\n }}\n />\n {picked.size > 0 ? (\n <Pressable onPress={applyPicked} style={styles.apply} accessibilityRole=\"button\">\n <Text style={styles.applyLabel}>\n Enable {picked.size} skill{picked.size === 1 ? '' : 's'}\n </Text>\n </Pressable>\n ) : null}\n </>\n )}\n </View>\n </Modal>\n );\n}\n\nfunction palette(isDark: boolean) {\n return isDark\n ? { bg: '#0f172a', raised: '#1e293b', text: '#f8fafc', dim: '#94a3b8', faint: '#64748b' }\n : { bg: '#ffffff', raised: '#f1f5f9', text: '#0f172a', dim: '#64748b', faint: '#94a3b8' };\n}\n\nconst styles = StyleSheet.create({\n scrim: { flex: 1, backgroundColor: 'rgba(2, 6, 23, 0.45)' },\n sheet: {\n maxHeight: '82%',\n borderTopLeftRadius: 20,\n borderTopRightRadius: 20,\n paddingHorizontal: 16,\n paddingBottom: 18,\n },\n grabber: {\n alignSelf: 'center',\n width: 36,\n height: 4,\n borderRadius: 2,\n backgroundColor: 'rgba(148, 163, 184, 0.5)',\n marginVertical: 8,\n },\n head: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingVertical: 4 },\n title: { fontSize: 17, fontWeight: '700' },\n tabs: { flexDirection: 'row', gap: 8, paddingVertical: 8 },\n tab: { paddingHorizontal: 12, paddingVertical: 7, borderRadius: 999 },\n tabLabel: { fontSize: 13, fontWeight: '600' },\n search: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 7,\n paddingHorizontal: 11,\n borderRadius: 11,\n marginBottom: 8,\n },\n searchInput: { flex: 1, fontSize: 14, paddingVertical: 9 },\n list: { gap: 8, paddingBottom: 8 },\n empty: { fontSize: 13, textAlign: 'center', paddingVertical: 22, paddingHorizontal: 12, lineHeight: 19 },\n row: { flexDirection: 'row', alignItems: 'center', gap: 11, padding: 12, borderRadius: 13 },\n rowPicked: { borderWidth: 1, borderColor: '#7c3aed' },\n rowIcon: { fontSize: 20 },\n rowBody: { flex: 1, gap: 2 },\n rowTitle: { fontSize: 14, fontWeight: '600' },\n rowDetail: { fontSize: 12, lineHeight: 16.5 },\n rowMeta: { fontSize: 10.5 },\n apply: {\n alignItems: 'center',\n paddingVertical: 13,\n borderRadius: 13,\n backgroundColor: '#7c3aed',\n marginTop: 4,\n },\n applyLabel: { color: '#ffffff', fontSize: 14.5, fontWeight: '700' },\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const BUILTIN_SKILL_TEMPLATES = [{
|
|
2
|
+
id: "yantra-github-search",
|
|
3
|
+
name: "GitHub Research",
|
|
4
|
+
description: "Search and analyze GitHub repositories. Ask a question and get an AI-powered summary of the most relevant open-source projects.",
|
|
5
|
+
icon: "\u{1F50D}",
|
|
6
|
+
soul: "You are a GitHub research assistant powered by the yantra-github-search connector. When the user provides a topic or question, search GitHub for relevant repositories, analyze the top results, and return a concise summary with key findings and citations.",
|
|
7
|
+
model: void 0,
|
|
8
|
+
requiredSkills: ["yantra-github-search"],
|
|
9
|
+
category: "research",
|
|
10
|
+
tags: ["github", "search", "repositories", "open-source", "analysis"],
|
|
11
|
+
builtin: true
|
|
12
|
+
}];export{BUILTIN_SKILL_TEMPLATES};//# sourceMappingURL=skillTemplates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skillTemplates.js","sources":["../../../src/features/skills/skillTemplates.ts"],"sourcesContent":["/**\n * Skill templates - the mobile twin of the browser's\n * `services/skillTemplates.ts`. The SkillTemplate shape is the CONTRACT\n * (HeaderSkillsButton hands one to cdecli connect + agentSessionManager) and\n * must not drift from the web's.\n *\n * Mobile v1 ships the built-in templates only: the web additionally merges\n * marketplace `aiTemplates` (uiLayout settings) and user-custom templates\n * from localStorage - both need a mobile owner (settings loader / storage)\n * and arrive with the header sheet's next iteration.\n */\n\nexport interface SkillTemplate {\n id: string;\n name: string;\n description: string;\n icon: string;\n /** SOUL.md content - agent persona/instructions */\n soul: string;\n /** Recommended model (e.g. 'anthropic/claude-opus-4-6') */\n model?: string;\n /** Skills that should be enabled for this template */\n requiredSkills?: string[];\n /** Category for UI grouping */\n category: 'coding' | 'research' | 'automation' | 'creative' | 'data' | 'general';\n /** Tags for search/filtering */\n tags: string[];\n /**\n * Shipped with the app (not backed by a marketplace form_table row) - the\n * template's `id` is a connector slug, so form_table lookups must be\n * skipped.\n */\n builtin?: boolean;\n}\n\nexport const BUILTIN_SKILL_TEMPLATES: SkillTemplate[] = [\n {\n id: 'yantra-github-search',\n name: 'GitHub Research',\n description:\n 'Search and analyze GitHub repositories. Ask a question and get an AI-powered summary of the most relevant open-source projects.',\n icon: '🔍',\n soul: 'You are a GitHub research assistant powered by the yantra-github-search connector. When the user provides a topic or question, search GitHub for relevant repositories, analyze the top results, and return a concise summary with key findings and citations.',\n model: undefined,\n requiredSkills: ['yantra-github-search'],\n category: 'research',\n tags: ['github', 'search', 'repositories', 'open-source', 'analysis'],\n builtin: true,\n },\n];\n"],"names":[],"mappings":"AAkCO,MAAM,0BAA2C,CAAC;AAAA,EACvD,EAAI,EAAA,sBAAA;AAAA,EACJ,IAAM,EAAA,iBAAA;AAAA,EACN,WAAa,EAAA,iIAAA;AAAA,EACb,IAAM,EAAA,WAAA;AAAA,EACN,IAAM,EAAA,gQAAA;AAAA,EACN,KAAO,EAAA,MAAA;AAAA,EACP,cAAA,EAAgB,CAAC,sBAAsB,CAAA;AAAA,EACvC,QAAU,EAAA,UAAA;AAAA,EACV,MAAM,CAAC,QAAA,EAAU,QAAU,EAAA,cAAA,EAAgB,eAAe,UAAU,CAAA;AAAA,EACpE,OAAS,EAAA;AACX,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {useQuery,gql}from'@apollo/client/index.js';import {useMemo}from'react';import {useGatewayContext}from'../../contexts/GatewayContext.js';import {useAgentSessionState}from'../../hooks/useAgentSessionState.js';const GATEWAY_SKILLS_QUERY = gql`
|
|
2
|
+
query GatewaySkills {
|
|
3
|
+
gatewaySkills {
|
|
4
|
+
skillKey
|
|
5
|
+
name
|
|
6
|
+
description
|
|
7
|
+
source
|
|
8
|
+
subSkills {
|
|
9
|
+
skillKey
|
|
10
|
+
name
|
|
11
|
+
description
|
|
12
|
+
source
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
function useGatewaySkills() {
|
|
18
|
+
const {
|
|
19
|
+
selectedGateway
|
|
20
|
+
} = useGatewayContext();
|
|
21
|
+
const sessionState = useAgentSessionState();
|
|
22
|
+
const cdecliSelected = (selectedGateway == null ? void 0 : selectedGateway.channelType) === "cdecli-serve";
|
|
23
|
+
const {
|
|
24
|
+
data,
|
|
25
|
+
loading,
|
|
26
|
+
error
|
|
27
|
+
} = useQuery(GATEWAY_SKILLS_QUERY, {
|
|
28
|
+
skip: !cdecliSelected,
|
|
29
|
+
fetchPolicy: "cache-and-network"
|
|
30
|
+
});
|
|
31
|
+
return useMemo(() => {
|
|
32
|
+
var _a;
|
|
33
|
+
if (cdecliSelected) {
|
|
34
|
+
const skills = error ? [] : (_a = data == null ? void 0 : data.gatewaySkills) != null ? _a : [];
|
|
35
|
+
return {
|
|
36
|
+
skills,
|
|
37
|
+
loading: loading && !data,
|
|
38
|
+
source: "cdecli-serve"
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (sessionState.gatewayConnected && sessionState.skills.length > 0) {
|
|
42
|
+
return {
|
|
43
|
+
skills: sessionState.skills.map((s) => ({
|
|
44
|
+
skillKey: s.skillKey,
|
|
45
|
+
name: s.name,
|
|
46
|
+
description: s.description,
|
|
47
|
+
enabled: s.enabled
|
|
48
|
+
})),
|
|
49
|
+
loading: false,
|
|
50
|
+
source: "gateway-ws"
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
skills: [],
|
|
55
|
+
loading: false,
|
|
56
|
+
source: "none"
|
|
57
|
+
};
|
|
58
|
+
}, [cdecliSelected, data, loading, error, sessionState.gatewayConnected, sessionState.skills]);
|
|
59
|
+
}export{useGatewaySkills};//# sourceMappingURL=useGatewaySkills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGatewaySkills.js","sources":["../../../src/features/skills/useGatewaySkills.ts"],"sourcesContent":["/**\n * Installed-skill listing for the SELECTED gateway - the mobile twin of the\n * browser's `hooks/useGatewaySkills.ts`, with the same entry shape and\n * per-gateway sourcing rules:\n * - `cdecli-serve` → `gatewaySkills` GraphQL query (messenger-gateway\n * proxies cdecli serve `GET /v1/skills`; bundles carry nested sub-skills).\n * Degrades to an empty list while the deployed gateway-server predates\n * the query.\n * - anything else (openclaw/workspace WS gateways) → the `skills.status`\n * snapshot agentSessionManager already holds from the gateway WebSocket.\n */\nimport { gql, useQuery } from '@apollo/client';\nimport { useMemo } from 'react';\nimport { useGatewayContext } from '../../contexts/GatewayContext';\nimport { useAgentSessionState } from '../../hooks/useAgentSessionState';\n\nexport interface GatewaySubSkillEntry {\n skillKey: string;\n name: string;\n description?: string | null;\n source?: string | null;\n}\n\nexport interface GatewaySkillEntry extends GatewaySubSkillEntry {\n /** Only reported by WS gateways (skills.status); undefined for cdecli. */\n enabled?: boolean;\n /** Nested sub-skills when this entry is a bundle (cdecli only). */\n subSkills?: GatewaySubSkillEntry[];\n}\n\nexport type GatewaySkillSource = 'cdecli-serve' | 'gateway-ws' | 'none';\n\nexport interface UseGatewaySkillsReturn {\n skills: GatewaySkillEntry[];\n loading: boolean;\n /** Which backend produced the list - 'none' when the selected gateway has no listing. */\n source: GatewaySkillSource;\n}\n\n// Raw document (not codegen): the installed @messenger-box/gateway-server may\n// predate the gatewaySkills field, so the generated models don't include it.\nconst GATEWAY_SKILLS_QUERY = gql`\n query GatewaySkills {\n gatewaySkills {\n skillKey\n name\n description\n source\n subSkills {\n skillKey\n name\n description\n source\n }\n }\n }\n`;\n\nexport function useGatewaySkills(): UseGatewaySkillsReturn {\n const { selectedGateway } = useGatewayContext();\n const sessionState = useAgentSessionState();\n const cdecliSelected = selectedGateway?.channelType === 'cdecli-serve';\n\n const { data, loading, error } = useQuery<{ gatewaySkills?: GatewaySkillEntry[] | null }>(GATEWAY_SKILLS_QUERY, {\n skip: !cdecliSelected,\n fetchPolicy: 'cache-and-network',\n });\n\n return useMemo(() => {\n if (cdecliSelected) {\n // An older gateway-server without the field answers with a GraphQL\n // error - treat as \"no listing\", never as a failure the UI blocks on.\n const skills = error ? [] : (data?.gatewaySkills ?? []);\n return { skills, loading: loading && !data, source: 'cdecli-serve' as const };\n }\n if (sessionState.gatewayConnected && sessionState.skills.length > 0) {\n return {\n skills: sessionState.skills.map((s) => ({\n skillKey: s.skillKey,\n name: s.name,\n description: s.description,\n enabled: s.enabled,\n })),\n loading: false,\n source: 'gateway-ws' as const,\n };\n }\n return { skills: [], loading: false, source: 'none' as const };\n }, [cdecliSelected, data, loading, error, sessionState.gatewayConnected, sessionState.skills]);\n}\n"],"names":[],"mappings":"uNAqCA,MAAM,oBAAuB,GAAA,GAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAgBtB,SAAS,gBAA2C,GAAA;AACzD,EAAM,MAAA;AAAA,IACJ;AAAA,MACE,iBAAkB,EAAA;AACtB,EAAA,MAAM,eAAe,oBAAqB,EAAA;AAC1C,EAAM,MAAA,cAAA,GAAA,CAAiB,mDAAiB,WAAgB,MAAA,cAAA;AACxD,EAAM,MAAA;AAAA,IACJ,IAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF,GAAI,SAED,oBAAsB,EAAA;AAAA,IACvB,MAAM,CAAC,cAAA;AAAA,IACP,WAAa,EAAA;AAAA,GACd,CAAA;AACD,EAAA,OAAO,QAAQ,MAAM;AArEvB,IAAA,IAAA,EAAA;AAsEI,IAAA,IAAI,cAAgB,EAAA;AAGlB,MAAA,MAAM,SAAS,KAAQ,GAAA,MAAK,EAAM,GAAA,IAAA,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAA,aAAA,KAAN,YAAuB,EAAC;AACpD,MAAO,OAAA;AAAA,QACL,MAAA;AAAA,QACA,OAAA,EAAS,WAAW,CAAC,IAAA;AAAA,QACrB,MAAQ,EAAA;AAAA,OACV;AAAA;AAEF,IAAA,IAAI,YAAa,CAAA,gBAAA,IAAoB,YAAa,CAAA,MAAA,CAAO,SAAS,CAAG,EAAA;AACnE,MAAO,OAAA;AAAA,QACL,MAAQ,EAAA,YAAA,CAAa,MAAO,CAAA,GAAA,CAAI,CAAM,CAAA,MAAA;AAAA,UACpC,UAAU,CAAE,CAAA,QAAA;AAAA,UACZ,MAAM,CAAE,CAAA,IAAA;AAAA,UACR,aAAa,CAAE,CAAA,WAAA;AAAA,UACf,SAAS,CAAE,CAAA;AAAA,SACX,CAAA,CAAA;AAAA,QACF,OAAS,EAAA,KAAA;AAAA,QACT,MAAQ,EAAA;AAAA,OACV;AAAA;AAEF,IAAO,OAAA;AAAA,MACL,QAAQ,EAAC;AAAA,MACT,OAAS,EAAA,KAAA;AAAA,MACT,MAAQ,EAAA;AAAA,KACV;AAAA,GACF,EAAG,CAAC,cAAA,EAAgB,IAAM,EAAA,OAAA,EAAS,OAAO,YAAa,CAAA,gBAAA,EAAkB,YAAa,CAAA,MAAM,CAAC,CAAA;AAC/F"}
|