@rickydata/react 0.1.0

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/dist/index.cjs ADDED
@@ -0,0 +1,968 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ RickyDataProvider: () => RickyDataProvider,
24
+ SecretForm: () => SecretForm,
25
+ SecretOrchestrator: () => SecretOrchestrator,
26
+ WalletChip: () => WalletChip,
27
+ agentKeys: () => agentKeys,
28
+ apiKeyKeys: () => apiKeyKeys,
29
+ balanceKeys: () => balanceKeys,
30
+ sessionKeys: () => sessionKeys,
31
+ useAgent: () => useAgent,
32
+ useAgentChat: () => useAgentChat,
33
+ useAgents: () => useAgents,
34
+ useApiKeyStatus: () => useApiKeyStatus,
35
+ useDeleteApiKey: () => useDeleteApiKey,
36
+ useDeleteSession: () => useDeleteSession,
37
+ useOpenAIApiKeyStatus: () => useOpenAIApiKeyStatus,
38
+ useRickyData: () => useRickyData,
39
+ useSecrets: () => useSecrets,
40
+ useSession: () => useSession,
41
+ useSessions: () => useSessions,
42
+ useSetApiKey: () => useSetApiKey,
43
+ useSetOpenAIApiKey: () => useSetOpenAIApiKey,
44
+ useWalletBalance: () => useWalletBalance,
45
+ useWalletSettings: () => useWalletSettings,
46
+ useWalletTransactions: () => useWalletTransactions,
47
+ walletSettingsKeys: () => walletSettingsKeys
48
+ });
49
+ module.exports = __toCommonJS(index_exports);
50
+
51
+ // src/providers/RickyDataProvider.tsx
52
+ var import_react = require("react");
53
+ var import_agent = require("rickydata/agent");
54
+ var import_jsx_runtime = require("react/jsx-runtime");
55
+ var RickyDataContext = (0, import_react.createContext)(null);
56
+ function RickyDataProvider({ config, client, children }) {
57
+ const agentClient = (0, import_react.useMemo)(() => {
58
+ if (client) return client;
59
+ if (!config) throw new Error("RickyDataProvider requires either `config` or `client`");
60
+ return new import_agent.AgentClient({
61
+ tokenGetter: config.getAuthToken,
62
+ gatewayUrl: config.gatewayUrl
63
+ });
64
+ }, [client, config?.getAuthToken, config?.gatewayUrl]);
65
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RickyDataContext.Provider, { value: agentClient, children });
66
+ }
67
+ function useRickyData() {
68
+ const ctx = (0, import_react.useContext)(RickyDataContext);
69
+ if (!ctx) {
70
+ throw new Error("useRickyData must be used within a <RickyDataProvider>");
71
+ }
72
+ return ctx;
73
+ }
74
+
75
+ // src/hooks/agents.ts
76
+ var import_react_query = require("@tanstack/react-query");
77
+ var agentKeys = {
78
+ all: ["agents"],
79
+ lists: () => [...agentKeys.all, "list"],
80
+ details: () => [...agentKeys.all, "detail"],
81
+ detail: (id) => [...agentKeys.details(), id]
82
+ };
83
+ function useAgents() {
84
+ const client = useRickyData();
85
+ return (0, import_react_query.useQuery)({
86
+ queryKey: agentKeys.lists(),
87
+ queryFn: () => client.listAgents(),
88
+ staleTime: 5 * 60 * 1e3
89
+ // 5 min
90
+ });
91
+ }
92
+ function useAgent(agentId) {
93
+ const client = useRickyData();
94
+ return (0, import_react_query.useQuery)({
95
+ queryKey: agentKeys.detail(agentId),
96
+ queryFn: () => client.getAgent(agentId),
97
+ enabled: !!agentId
98
+ });
99
+ }
100
+
101
+ // src/hooks/apikey.ts
102
+ var import_react_query2 = require("@tanstack/react-query");
103
+ var apiKeyKeys = {
104
+ all: ["apikey"],
105
+ status: () => [...apiKeyKeys.all, "status"],
106
+ openai: () => [...apiKeyKeys.all, "openai"]
107
+ };
108
+ function useApiKeyStatus() {
109
+ const client = useRickyData();
110
+ return (0, import_react_query2.useQuery)({
111
+ queryKey: apiKeyKeys.status(),
112
+ queryFn: () => client.getApiKeyStatus(),
113
+ staleTime: 3e4
114
+ });
115
+ }
116
+ function useSetApiKey() {
117
+ const client = useRickyData();
118
+ const queryClient = (0, import_react_query2.useQueryClient)();
119
+ return (0, import_react_query2.useMutation)({
120
+ mutationFn: (apiKey) => client.setApiKey(apiKey),
121
+ onSuccess: () => {
122
+ queryClient.invalidateQueries({ queryKey: apiKeyKeys.status() });
123
+ }
124
+ });
125
+ }
126
+ function useDeleteApiKey() {
127
+ const client = useRickyData();
128
+ const queryClient = (0, import_react_query2.useQueryClient)();
129
+ return (0, import_react_query2.useMutation)({
130
+ mutationFn: () => client.deleteApiKey(),
131
+ onSuccess: () => {
132
+ queryClient.invalidateQueries({ queryKey: apiKeyKeys.status() });
133
+ }
134
+ });
135
+ }
136
+ function useOpenAIApiKeyStatus() {
137
+ const client = useRickyData();
138
+ return (0, import_react_query2.useQuery)({
139
+ queryKey: apiKeyKeys.openai(),
140
+ queryFn: () => client.getOpenAIApiKeyStatus(),
141
+ staleTime: 3e4
142
+ });
143
+ }
144
+ function useSetOpenAIApiKey() {
145
+ const client = useRickyData();
146
+ const queryClient = (0, import_react_query2.useQueryClient)();
147
+ return (0, import_react_query2.useMutation)({
148
+ mutationFn: (apiKey) => client.storeOpenAIApiKey(apiKey),
149
+ onSuccess: () => {
150
+ queryClient.invalidateQueries({ queryKey: apiKeyKeys.openai() });
151
+ }
152
+ });
153
+ }
154
+
155
+ // src/hooks/balance.ts
156
+ var import_react_query3 = require("@tanstack/react-query");
157
+ var balanceKeys = {
158
+ all: ["wallet-balance"],
159
+ balance: () => [...balanceKeys.all, "balance"],
160
+ transactions: (limit, offset) => [...balanceKeys.all, "transactions", { limit, offset }]
161
+ };
162
+ function useWalletBalance(opts) {
163
+ const client = useRickyData();
164
+ const query = (0, import_react_query3.useQuery)({
165
+ queryKey: balanceKeys.balance(),
166
+ queryFn: () => client.getWalletBalance(),
167
+ staleTime: opts?.staleTime ?? 6e4,
168
+ enabled: opts?.enabled !== false
169
+ });
170
+ const balance = query.data?.availableBalance ?? "0";
171
+ const num = parseFloat(balance);
172
+ const balanceDisplay = isNaN(num) ? "$0.00" : num >= 0.01 ? `$${num.toFixed(2)}` : num > 0 ? `$${num.toFixed(4)}` : "$0.00";
173
+ return {
174
+ ...query,
175
+ balance,
176
+ balanceDisplay,
177
+ depositAddress: query.data?.unifiedDepositAddress,
178
+ agentSpends: query.data?.agentSpends,
179
+ refresh: () => query.refetch()
180
+ };
181
+ }
182
+ function useWalletTransactions(limit, offset) {
183
+ const client = useRickyData();
184
+ return (0, import_react_query3.useQuery)({
185
+ queryKey: balanceKeys.transactions(limit, offset),
186
+ queryFn: () => client.getWalletTransactions(limit, offset),
187
+ staleTime: 3e4
188
+ });
189
+ }
190
+
191
+ // src/hooks/sessions.ts
192
+ var import_react_query4 = require("@tanstack/react-query");
193
+ var sessionKeys = {
194
+ all: ["sessions"],
195
+ lists: (agentId) => [...sessionKeys.all, "list", agentId],
196
+ details: () => [...sessionKeys.all, "detail"],
197
+ detail: (agentId, sessionId) => [...sessionKeys.details(), agentId, sessionId]
198
+ };
199
+ function useSessions(agentId) {
200
+ const client = useRickyData();
201
+ return (0, import_react_query4.useQuery)({
202
+ queryKey: sessionKeys.lists(agentId),
203
+ queryFn: () => client.listSessions(agentId),
204
+ enabled: !!agentId,
205
+ staleTime: 3e4
206
+ });
207
+ }
208
+ function useSession(agentId, sessionId) {
209
+ const client = useRickyData();
210
+ return (0, import_react_query4.useQuery)({
211
+ queryKey: sessionKeys.detail(agentId, sessionId),
212
+ queryFn: () => client.getSession(agentId, sessionId),
213
+ enabled: !!agentId && !!sessionId
214
+ });
215
+ }
216
+ function useDeleteSession() {
217
+ const client = useRickyData();
218
+ const queryClient = (0, import_react_query4.useQueryClient)();
219
+ return (0, import_react_query4.useMutation)({
220
+ mutationFn: ({ agentId, sessionId }) => client.deleteSession(agentId, sessionId),
221
+ onSuccess: (_data, { agentId }) => {
222
+ queryClient.invalidateQueries({ queryKey: sessionKeys.lists(agentId) });
223
+ }
224
+ });
225
+ }
226
+
227
+ // src/hooks/wallet-settings.ts
228
+ var import_react_query5 = require("@tanstack/react-query");
229
+ var walletSettingsKeys = {
230
+ all: ["wallet-settings"],
231
+ settings: () => [...walletSettingsKeys.all, "current"]
232
+ };
233
+ function useWalletSettings() {
234
+ const client = useRickyData();
235
+ const queryClient = (0, import_react_query5.useQueryClient)();
236
+ const query = (0, import_react_query5.useQuery)({
237
+ queryKey: walletSettingsKeys.settings(),
238
+ queryFn: () => client.getWalletSettings(),
239
+ staleTime: 6e4
240
+ });
241
+ const mutation = (0, import_react_query5.useMutation)({
242
+ mutationFn: (settings) => client.updateWalletSettings(settings),
243
+ onSuccess: (data) => {
244
+ queryClient.setQueryData(walletSettingsKeys.settings(), data);
245
+ }
246
+ });
247
+ return {
248
+ ...query,
249
+ settings: query.data,
250
+ updateSettings: mutation.mutateAsync,
251
+ isUpdating: mutation.isPending
252
+ };
253
+ }
254
+
255
+ // src/hooks/secrets.ts
256
+ var import_react2 = require("react");
257
+ function useSecrets({ agentId, mcpServers = [] }) {
258
+ const client = useRickyData();
259
+ const [sections, setSections] = (0, import_react2.useState)([]);
260
+ const [loading, setLoading] = (0, import_react2.useState)(true);
261
+ const fetchRequirements = (0, import_react2.useCallback)(async () => {
262
+ setLoading(true);
263
+ const result = [];
264
+ try {
265
+ const { configured } = await client.getApiKeyStatus();
266
+ if (!configured) {
267
+ result.push({
268
+ id: "anthropic",
269
+ label: "Anthropic API Key",
270
+ keys: ["ANTHROPIC_API_KEY"],
271
+ configuredKeys: [],
272
+ save: async (secrets) => {
273
+ const key = secrets["ANTHROPIC_API_KEY"];
274
+ if (key) await client.setApiKey(key);
275
+ }
276
+ });
277
+ }
278
+ } catch {
279
+ }
280
+ try {
281
+ const status = await client.getAgentSecretStatus(agentId);
282
+ if (status.missingRequired.length > 0) {
283
+ result.push({
284
+ id: `agent-${agentId}`,
285
+ label: "Agent Secrets",
286
+ keys: status.missingRequired,
287
+ configuredKeys: status.configuredSecrets,
288
+ save: async (secrets) => {
289
+ await client.storeAgentSecrets(agentId, secrets);
290
+ }
291
+ });
292
+ }
293
+ } catch {
294
+ }
295
+ if (mcpServers.length > 0) {
296
+ try {
297
+ const reqs = await client.getMcpRequirements(agentId);
298
+ for (const server of reqs.servers) {
299
+ const missing = server.missing || server.required.filter((k) => !server.configured?.includes(k));
300
+ if (missing.length > 0) {
301
+ result.push({
302
+ id: `mcp-${server.serverId}`,
303
+ label: `MCP: ${server.name || server.serverId}`,
304
+ keys: missing,
305
+ configuredKeys: server.configured || [],
306
+ save: async (secrets) => {
307
+ await client.storeMcpSecrets(server.serverId, secrets);
308
+ }
309
+ });
310
+ }
311
+ }
312
+ } catch {
313
+ }
314
+ }
315
+ setSections(result);
316
+ setLoading(false);
317
+ }, [client, agentId, mcpServers.join(",")]);
318
+ (0, import_react2.useEffect)(() => {
319
+ fetchRequirements();
320
+ }, [fetchRequirements]);
321
+ return {
322
+ sections,
323
+ loading,
324
+ allConfigured: !loading && sections.length === 0,
325
+ refresh: fetchRequirements
326
+ };
327
+ }
328
+
329
+ // src/hooks/chat.ts
330
+ var import_react3 = require("react");
331
+ var import_agent2 = require("rickydata/agent");
332
+ function useAgentChat({
333
+ agentId,
334
+ model = "haiku",
335
+ resumeSessionId
336
+ }) {
337
+ const client = useRickyData();
338
+ const [messages, setMessages] = (0, import_react3.useState)([]);
339
+ const [messagesLoading, setMessagesLoading] = (0, import_react3.useState)(!!resumeSessionId);
340
+ const [sending, setSending] = (0, import_react3.useState)(false);
341
+ const [sessionId, setSessionId] = (0, import_react3.useState)(resumeSessionId || null);
342
+ const [streamingPhase, setStreamingPhase] = (0, import_react3.useState)("idle");
343
+ const [activeTools, setActiveTools] = (0, import_react3.useState)([]);
344
+ const [apiKeyConfigured, setApiKeyConfigured] = (0, import_react3.useState)(null);
345
+ const modelRef = (0, import_react3.useRef)(model);
346
+ modelRef.current = model;
347
+ (0, import_react3.useEffect)(() => {
348
+ let cancelled = false;
349
+ client.getApiKeyStatus().then(({ configured }) => {
350
+ if (!cancelled) setApiKeyConfigured(configured);
351
+ }).catch(() => {
352
+ if (!cancelled) setApiKeyConfigured(false);
353
+ });
354
+ return () => {
355
+ cancelled = true;
356
+ };
357
+ }, [client]);
358
+ (0, import_react3.useEffect)(() => {
359
+ if (!resumeSessionId) return;
360
+ let cancelled = false;
361
+ client.getSession(agentId, resumeSessionId).then((session) => {
362
+ if (cancelled) return;
363
+ const msgs = session.messages.map((m, i) => ({
364
+ id: `restored-${i}`,
365
+ role: m.role === "user" ? "user" : "agent",
366
+ content: m.content,
367
+ timestamp: m.timestamp || session.createdAt
368
+ }));
369
+ setMessages(msgs);
370
+ setMessagesLoading(false);
371
+ }).catch(() => {
372
+ if (!cancelled) setMessagesLoading(false);
373
+ });
374
+ return () => {
375
+ cancelled = true;
376
+ };
377
+ }, [client, agentId, resumeSessionId]);
378
+ const sendMessage = (0, import_react3.useCallback)(async (text) => {
379
+ if (!text.trim() || sending) return;
380
+ if (apiKeyConfigured === false) {
381
+ setMessages((prev) => [...prev, {
382
+ id: `msg-${Date.now()}-error`,
383
+ role: "agent",
384
+ content: "Anthropic API key required. Configure ANTHROPIC_API_KEY before chatting.",
385
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
386
+ }]);
387
+ return;
388
+ }
389
+ const userMessage = {
390
+ id: `msg-${Date.now()}`,
391
+ role: "user",
392
+ content: text.trim(),
393
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
394
+ };
395
+ setMessages((prev) => [...prev, userMessage]);
396
+ setSending(true);
397
+ try {
398
+ let sid = sessionId;
399
+ if (!sid) {
400
+ const session = await client.createSession(agentId, modelRef.current);
401
+ sid = session.id;
402
+ setSessionId(sid);
403
+ }
404
+ const response = await client.chatRaw(agentId, sid, text.trim(), modelRef.current);
405
+ let textAccum = "";
406
+ const toolExecutions = [];
407
+ let messageCost = "";
408
+ let toolIdCounter = 0;
409
+ const streamingMsgId = `agent-streaming-${Date.now()}`;
410
+ setActiveTools([]);
411
+ setStreamingPhase("idle");
412
+ await (0, import_agent2.streamSSEEvents)(response, (event) => {
413
+ switch (event.type) {
414
+ case "text":
415
+ setStreamingPhase("streaming");
416
+ setActiveTools([]);
417
+ textAccum += event.data;
418
+ setMessages((prev) => {
419
+ const existing = prev.find((m) => m.id === streamingMsgId);
420
+ if (!existing) {
421
+ return [...prev, {
422
+ id: streamingMsgId,
423
+ role: "agent",
424
+ content: textAccum,
425
+ toolExecutions: toolExecutions.length > 0 ? [...toolExecutions] : void 0,
426
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
427
+ }];
428
+ }
429
+ return prev.map(
430
+ (m) => m.id === streamingMsgId ? { ...m, content: textAccum, toolExecutions: toolExecutions.length > 0 ? [...toolExecutions] : void 0 } : m
431
+ );
432
+ });
433
+ break;
434
+ case "tool_call": {
435
+ const data = event.data;
436
+ const displayName = data.displayName || data.name.split("__").pop() || data.name;
437
+ toolExecutions.push({
438
+ id: data.id || `tool-${++toolIdCounter}`,
439
+ name: data.name,
440
+ displayName,
441
+ args: data.args
442
+ });
443
+ setActiveTools((prev) => [...prev, displayName]);
444
+ setStreamingPhase("tools");
445
+ break;
446
+ }
447
+ case "tool_result": {
448
+ const resultData = event.data;
449
+ const resultContent = resultData.result ?? resultData.content;
450
+ let matched = false;
451
+ if (resultData.id) {
452
+ const idx = toolExecutions.findIndex((t) => t.id === resultData.id);
453
+ if (idx !== -1) {
454
+ toolExecutions[idx].result = { content: resultContent, isError: resultData.isError };
455
+ matched = true;
456
+ }
457
+ }
458
+ if (!matched) {
459
+ for (let i = toolExecutions.length - 1; i >= 0; i--) {
460
+ if (toolExecutions[i].name === resultData.name && !toolExecutions[i].result) {
461
+ toolExecutions[i].result = { content: resultContent, isError: resultData.isError };
462
+ break;
463
+ }
464
+ }
465
+ }
466
+ break;
467
+ }
468
+ case "done":
469
+ if (event.data.cost) messageCost = event.data.cost;
470
+ break;
471
+ case "error":
472
+ textAccum += `
473
+
474
+ Error: ${event.data.message}`;
475
+ break;
476
+ }
477
+ });
478
+ setMessages((prev) => {
479
+ const withoutStreaming = prev.filter((m) => m.id !== streamingMsgId);
480
+ return [...withoutStreaming, {
481
+ id: `msg-${Date.now()}-agent`,
482
+ role: "agent",
483
+ content: textAccum || "(No response)",
484
+ toolExecutions: toolExecutions.length > 0 ? [...toolExecutions] : void 0,
485
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
486
+ costUSD: messageCost || void 0
487
+ }];
488
+ });
489
+ } catch (err) {
490
+ const errStatus = typeof err === "object" && err !== null && "status" in err ? err.status : 0;
491
+ const errMessage = err instanceof Error ? err.message : String(err);
492
+ if (errStatus === 402) {
493
+ setMessages((prev) => [...prev, {
494
+ id: `msg-${Date.now()}-error`,
495
+ role: "agent",
496
+ content: "Insufficient balance. Please deposit funds to continue.",
497
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
498
+ }]);
499
+ } else if (errStatus === 404 || /session not found|not found/i.test(errMessage)) {
500
+ setSessionId(null);
501
+ setMessages((prev) => [...prev, {
502
+ id: `msg-${Date.now()}-error`,
503
+ role: "agent",
504
+ content: "Session expired. Starting a new conversation...",
505
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
506
+ }]);
507
+ } else if (errStatus === 401 || /unauthorized|authentication|invalid.*token|expired.*token/i.test(errMessage)) {
508
+ setSessionId(null);
509
+ setMessages((prev) => [...prev, {
510
+ id: `msg-${Date.now()}-error`,
511
+ role: "agent",
512
+ content: "Re-authenticating... please send again.",
513
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
514
+ }]);
515
+ } else if (errStatus === 400 && /anthropic api key|required/i.test(errMessage)) {
516
+ setApiKeyConfigured(false);
517
+ setMessages((prev) => [...prev, {
518
+ id: `msg-${Date.now()}-error`,
519
+ role: "agent",
520
+ content: errMessage,
521
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
522
+ }]);
523
+ } else {
524
+ setMessages((prev) => [...prev, {
525
+ id: `msg-${Date.now()}-error`,
526
+ role: "agent",
527
+ content: `Error: ${errMessage}`,
528
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
529
+ }]);
530
+ }
531
+ } finally {
532
+ setSending(false);
533
+ setStreamingPhase("idle");
534
+ setActiveTools([]);
535
+ }
536
+ }, [client, agentId, sending, sessionId, apiKeyConfigured]);
537
+ const refreshApiKeyStatus = (0, import_react3.useCallback)(() => {
538
+ client.getApiKeyStatus().then(({ configured }) => setApiKeyConfigured(configured)).catch(() => {
539
+ });
540
+ }, [client]);
541
+ const prevApiKeyRef = (0, import_react3.useRef)(apiKeyConfigured);
542
+ (0, import_react3.useEffect)(() => {
543
+ if (prevApiKeyRef.current === false && apiKeyConfigured === true) {
544
+ setMessages((prev) => [...prev, {
545
+ id: `msg-${Date.now()}-system`,
546
+ role: "agent",
547
+ content: "API key configured successfully! You can start chatting now.",
548
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
549
+ }]);
550
+ }
551
+ prevApiKeyRef.current = apiKeyConfigured;
552
+ }, [apiKeyConfigured]);
553
+ const clearChat = (0, import_react3.useCallback)(() => {
554
+ setMessages([]);
555
+ setSessionId(null);
556
+ setStreamingPhase("idle");
557
+ setActiveTools([]);
558
+ }, []);
559
+ return {
560
+ messages,
561
+ messagesLoading,
562
+ sending,
563
+ sessionId,
564
+ streamingPhase,
565
+ activeTools,
566
+ apiKeyConfigured,
567
+ sendMessage,
568
+ clearChat,
569
+ refreshApiKeyStatus
570
+ };
571
+ }
572
+
573
+ // src/components/SecretForm.tsx
574
+ var import_react4 = require("react");
575
+ var import_jsx_runtime2 = require("react/jsx-runtime");
576
+ var container = {
577
+ display: "flex",
578
+ flexDirection: "column",
579
+ gap: "12px"
580
+ };
581
+ var labelStyle = {
582
+ display: "block",
583
+ fontSize: "12px",
584
+ fontWeight: 500,
585
+ fontFamily: "monospace",
586
+ color: "#9ca3af",
587
+ marginBottom: "4px"
588
+ };
589
+ var configuredBadge = {
590
+ marginLeft: "6px",
591
+ color: "#10b981",
592
+ fontFamily: "sans-serif"
593
+ };
594
+ var inputWrapper = {
595
+ position: "relative"
596
+ };
597
+ var inputStyle = {
598
+ width: "100%",
599
+ padding: "8px 36px 8px 12px",
600
+ fontSize: "14px",
601
+ fontFamily: "monospace",
602
+ borderRadius: "8px",
603
+ border: "1px solid rgba(255,255,255,0.1)",
604
+ backgroundColor: "#1f2937",
605
+ color: "#fff",
606
+ outline: "none",
607
+ boxSizing: "border-box"
608
+ };
609
+ var toggleBtn = {
610
+ position: "absolute",
611
+ right: "8px",
612
+ top: "50%",
613
+ transform: "translateY(-50%)",
614
+ padding: "4px",
615
+ background: "none",
616
+ border: "none",
617
+ color: "#9ca3af",
618
+ cursor: "pointer",
619
+ fontSize: "14px"
620
+ };
621
+ var feedbackBase = {
622
+ display: "flex",
623
+ alignItems: "center",
624
+ gap: "8px",
625
+ padding: "8px",
626
+ borderRadius: "8px",
627
+ fontSize: "12px"
628
+ };
629
+ var feedbackSuccess = {
630
+ ...feedbackBase,
631
+ backgroundColor: "rgba(16,185,129,0.1)",
632
+ border: "1px solid rgba(16,185,129,0.2)",
633
+ color: "#34d399"
634
+ };
635
+ var feedbackError = {
636
+ ...feedbackBase,
637
+ backgroundColor: "rgba(239,68,68,0.1)",
638
+ border: "1px solid rgba(239,68,68,0.2)",
639
+ color: "#f87171"
640
+ };
641
+ var btnRow = {
642
+ display: "flex",
643
+ alignItems: "center",
644
+ justifyContent: "space-between"
645
+ };
646
+ var saveBtn = {
647
+ display: "inline-flex",
648
+ alignItems: "center",
649
+ gap: "6px",
650
+ padding: "6px 12px",
651
+ fontSize: "12px",
652
+ fontWeight: 500,
653
+ borderRadius: "6px",
654
+ border: "none",
655
+ backgroundColor: "#6366f1",
656
+ color: "#fff",
657
+ cursor: "pointer",
658
+ transition: "opacity 0.15s"
659
+ };
660
+ var cancelBtn = {
661
+ padding: "6px 12px",
662
+ fontSize: "12px",
663
+ fontWeight: 500,
664
+ borderRadius: "6px",
665
+ border: "none",
666
+ background: "none",
667
+ color: "#9ca3af",
668
+ cursor: "pointer"
669
+ };
670
+ var deleteBtn = {
671
+ display: "inline-flex",
672
+ alignItems: "center",
673
+ gap: "4px",
674
+ padding: "6px 10px",
675
+ fontSize: "12px",
676
+ fontWeight: 500,
677
+ borderRadius: "6px",
678
+ border: "none",
679
+ background: "none",
680
+ color: "#f87171",
681
+ cursor: "pointer"
682
+ };
683
+ function SecretForm({ secretKeys, configuredKeys, onSave, onDelete, onClose, className }) {
684
+ const [values, setValues] = (0, import_react4.useState)(() => {
685
+ const init = {};
686
+ for (const key of secretKeys) init[key] = "";
687
+ return init;
688
+ });
689
+ const [showValues, setShowValues] = (0, import_react4.useState)({});
690
+ const [saving, setSaving] = (0, import_react4.useState)(false);
691
+ const [deleting, setDeleting] = (0, import_react4.useState)(false);
692
+ const [feedback, setFeedback] = (0, import_react4.useState)(null);
693
+ const hasAnyValue = Object.values(values).some((v) => v.trim().length > 0);
694
+ const handleSave = async () => {
695
+ const secrets = {};
696
+ for (const [key, val] of Object.entries(values)) {
697
+ if (val.trim()) secrets[key] = val.trim();
698
+ }
699
+ if (Object.keys(secrets).length === 0) return;
700
+ setSaving(true);
701
+ setFeedback(null);
702
+ try {
703
+ await onSave(secrets);
704
+ setFeedback({ type: "success", message: "Secrets saved successfully." });
705
+ setValues((prev) => {
706
+ const next = { ...prev };
707
+ for (const k of Object.keys(next)) next[k] = "";
708
+ return next;
709
+ });
710
+ if (onClose) setTimeout(onClose, 800);
711
+ } catch (err) {
712
+ setFeedback({ type: "error", message: err instanceof Error ? err.message : "Failed to save." });
713
+ } finally {
714
+ setSaving(false);
715
+ }
716
+ };
717
+ const handleDelete = async () => {
718
+ if (!onDelete) return;
719
+ setDeleting(true);
720
+ setFeedback(null);
721
+ try {
722
+ await onDelete();
723
+ setFeedback({ type: "success", message: "Secrets removed." });
724
+ if (onClose) setTimeout(onClose, 800);
725
+ } catch (err) {
726
+ setFeedback({ type: "error", message: err instanceof Error ? err.message : "Failed to remove." });
727
+ } finally {
728
+ setDeleting(false);
729
+ }
730
+ };
731
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: container, className, children: [
732
+ secretKeys.map((key) => {
733
+ const isVisible = showValues[key] ?? false;
734
+ const isConfigured = configuredKeys.includes(key);
735
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
736
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { style: labelStyle, children: [
737
+ key,
738
+ isConfigured && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: configuredBadge, children: "(configured)" })
739
+ ] }),
740
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: inputWrapper, children: [
741
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
742
+ "input",
743
+ {
744
+ type: isVisible ? "text" : "password",
745
+ value: values[key],
746
+ onChange: (e) => setValues((prev) => ({ ...prev, [key]: e.target.value })),
747
+ placeholder: isConfigured ? "Enter new value to update" : "Enter value",
748
+ style: inputStyle
749
+ }
750
+ ),
751
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
752
+ "button",
753
+ {
754
+ type: "button",
755
+ onClick: () => setShowValues((prev) => ({ ...prev, [key]: !isVisible })),
756
+ style: toggleBtn,
757
+ "aria-label": isVisible ? "Hide" : "Show",
758
+ children: isVisible ? "\u{1F441}\uFE0F\u200D\u{1F5E8}\uFE0F" : "\u{1F441}\uFE0F"
759
+ }
760
+ )
761
+ ] })
762
+ ] }, key);
763
+ }),
764
+ feedback && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: feedback.type === "success" ? feedbackSuccess : feedbackError, children: [
765
+ feedback.type === "success" ? "\u2713" : "\u26A0",
766
+ " ",
767
+ feedback.message
768
+ ] }),
769
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: btnRow, children: [
770
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
771
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
772
+ "button",
773
+ {
774
+ onClick: handleSave,
775
+ disabled: saving || !hasAnyValue,
776
+ style: { ...saveBtn, opacity: saving || !hasAnyValue ? 0.4 : 1 },
777
+ children: saving ? "Saving..." : "Save Keys"
778
+ }
779
+ ),
780
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: onClose, style: cancelBtn, children: "Cancel" })
781
+ ] }),
782
+ onDelete && configuredKeys.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: handleDelete, disabled: deleting, style: deleteBtn, children: deleting ? "..." : "\u{1F5D1} Remove" })
783
+ ] })
784
+ ] });
785
+ }
786
+
787
+ // src/components/SecretOrchestrator.tsx
788
+ var import_react5 = require("react");
789
+ var import_jsx_runtime3 = require("react/jsx-runtime");
790
+ var wrapper = {
791
+ display: "flex",
792
+ flexDirection: "column",
793
+ gap: "8px"
794
+ };
795
+ var loadingBox = {
796
+ display: "flex",
797
+ alignItems: "center",
798
+ gap: "8px",
799
+ padding: "12px",
800
+ borderRadius: "12px",
801
+ border: "1px solid rgba(245,158,11,0.2)",
802
+ backgroundColor: "rgba(31,41,55,0.8)",
803
+ fontSize: "12px",
804
+ color: "#fcd34d"
805
+ };
806
+ var sectionBox = {
807
+ borderRadius: "12px",
808
+ border: "1px solid rgba(245,158,11,0.2)",
809
+ backgroundColor: "rgba(31,41,55,0.8)",
810
+ overflow: "hidden"
811
+ };
812
+ var headerBtn = {
813
+ width: "100%",
814
+ display: "flex",
815
+ alignItems: "center",
816
+ gap: "8px",
817
+ padding: "12px 16px",
818
+ textAlign: "left",
819
+ background: "none",
820
+ border: "none",
821
+ cursor: "pointer",
822
+ color: "inherit"
823
+ };
824
+ var headerLabel = {
825
+ flex: 1,
826
+ fontSize: "12px",
827
+ fontWeight: 500,
828
+ color: "#fcd34d"
829
+ };
830
+ var bodyBox = {
831
+ padding: "0 16px 16px"
832
+ };
833
+ function SecretOrchestrator({
834
+ agentId,
835
+ mcpServers,
836
+ onAllConfigured,
837
+ className,
838
+ compact
839
+ }) {
840
+ const { sections, loading, allConfigured, refresh } = useSecrets({ agentId, mcpServers });
841
+ const [expandedId, setExpandedId] = (0, import_react5.useState)(null);
842
+ (0, import_react5.useEffect)(() => {
843
+ if (sections.length > 0 && expandedId === null) {
844
+ setExpandedId(sections[0].id);
845
+ }
846
+ }, [sections, expandedId]);
847
+ (0, import_react5.useEffect)(() => {
848
+ if (allConfigured) onAllConfigured?.();
849
+ }, [allConfigured, onAllConfigured]);
850
+ if (loading) {
851
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: loadingBox, className, children: [
852
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { animation: "spin 1s linear infinite" }, children: "\u21BB" }),
853
+ "Checking configuration requirements..."
854
+ ] });
855
+ }
856
+ if (sections.length === 0) return null;
857
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: wrapper, className, children: sections.map((section) => {
858
+ const isExpanded = expandedId === section.id;
859
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: sectionBox, children: [
860
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
861
+ "button",
862
+ {
863
+ onClick: () => setExpandedId(isExpanded ? null : section.id),
864
+ style: headerBtn,
865
+ children: [
866
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "#f59e0b" }, children: "\u26A0" }),
867
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: headerLabel, children: [
868
+ section.label,
869
+ " required"
870
+ ] }),
871
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "#6b7280", fontSize: "12px" }, children: isExpanded ? "\u25BC" : "\u25B6" })
872
+ ]
873
+ }
874
+ ),
875
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: bodyBox, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
876
+ SecretForm,
877
+ {
878
+ secretKeys: section.keys,
879
+ configuredKeys: section.configuredKeys,
880
+ onSave: async (secrets) => {
881
+ await section.save(secrets);
882
+ refresh();
883
+ },
884
+ onClose: compact ? void 0 : () => setExpandedId(null)
885
+ }
886
+ ) })
887
+ ] }, section.id);
888
+ }) });
889
+ }
890
+
891
+ // src/components/WalletChip.tsx
892
+ var import_jsx_runtime4 = require("react/jsx-runtime");
893
+ var chipStyle = {
894
+ display: "inline-flex",
895
+ alignItems: "center",
896
+ gap: "6px",
897
+ padding: "4px 10px",
898
+ borderRadius: "9999px",
899
+ backgroundColor: "rgba(255,255,255,0.08)",
900
+ border: "1px solid rgba(255,255,255,0.1)",
901
+ fontSize: "12px",
902
+ fontFamily: "monospace",
903
+ color: "#d1d5db",
904
+ cursor: "default",
905
+ transition: "background-color 0.15s"
906
+ };
907
+ var chipClickable = {
908
+ ...chipStyle,
909
+ cursor: "pointer"
910
+ };
911
+ var balanceBadge = {
912
+ padding: "1px 6px",
913
+ borderRadius: "9999px",
914
+ backgroundColor: "rgba(99,102,241,0.2)",
915
+ color: "#a5b4fc",
916
+ fontSize: "11px",
917
+ fontFamily: "sans-serif",
918
+ fontWeight: 500
919
+ };
920
+ function truncateAddress(address) {
921
+ if (address.length <= 10) return address;
922
+ return `${address.slice(0, 6)}...${address.slice(-4)}`;
923
+ }
924
+ function WalletChip({ address, balanceDisplay, displayName, onPress, className }) {
925
+ const Tag = onPress ? "button" : "div";
926
+ const style = onPress ? chipClickable : chipStyle;
927
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
928
+ Tag,
929
+ {
930
+ onClick: onPress,
931
+ style: { ...style, ...onPress ? { border: "1px solid rgba(255,255,255,0.1)", background: "rgba(255,255,255,0.08)" } : {} },
932
+ className,
933
+ ...Tag === "button" ? { type: "button" } : {},
934
+ children: [
935
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: displayName || truncateAddress(address) }),
936
+ balanceDisplay && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: balanceBadge, children: balanceDisplay })
937
+ ]
938
+ }
939
+ );
940
+ }
941
+ // Annotate the CommonJS export names for ESM import in node:
942
+ 0 && (module.exports = {
943
+ RickyDataProvider,
944
+ SecretForm,
945
+ SecretOrchestrator,
946
+ WalletChip,
947
+ agentKeys,
948
+ apiKeyKeys,
949
+ balanceKeys,
950
+ sessionKeys,
951
+ useAgent,
952
+ useAgentChat,
953
+ useAgents,
954
+ useApiKeyStatus,
955
+ useDeleteApiKey,
956
+ useDeleteSession,
957
+ useOpenAIApiKeyStatus,
958
+ useRickyData,
959
+ useSecrets,
960
+ useSession,
961
+ useSessions,
962
+ useSetApiKey,
963
+ useSetOpenAIApiKey,
964
+ useWalletBalance,
965
+ useWalletSettings,
966
+ useWalletTransactions,
967
+ walletSettingsKeys
968
+ });