create-claudeportal 0.3.9 → 0.5.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/assets/index-0CleGcfY.js +171 -0
- package/dist/assets/index-BhQb4ZZk.css +1 -0
- package/dist/index.html +2 -2
- package/electron/builder.config.js +47 -0
- package/electron/icons/.gitkeep +0 -0
- package/electron/main.js +93 -0
- package/electron/preload.js +7 -0
- package/package.json +13 -2
- package/server/index.js +4 -0
- package/server/lib/agent-storage.js +64 -0
- package/server/lib/agents.js +81 -0
- package/server/lib/brain-manager.js +72 -0
- package/server/lib/supabase.js +60 -0
- package/server/routes/agent.js +144 -0
- package/server/routes/auth.js +34 -0
- package/server/routes/brain.js +22 -0
- package/supabase/migrations/007_brain_migration.sql +56 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/assets/index-CjHE0n_q.js +0 -161
- package/dist/assets/index-DuJJJuzg.css +0 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const { createClient } = require('@supabase/supabase-js')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const os = require('os')
|
|
5
|
+
|
|
6
|
+
const SUPABASE_URL = process.env.SUPABASE_URL || 'https://wiwlydjvpwvlosfojdbz.supabase.co'
|
|
7
|
+
const SUPABASE_ANON_KEY = process.env.SUPABASE_ANON_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Indpd2x5ZGp2cHd2bG9zZm9qZGJ6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzA2MTkyNjYsImV4cCI6MjA0NjE5NTI2Nn0.placeholder'
|
|
8
|
+
|
|
9
|
+
let SESSION_PATH = path.join(os.homedir(), 'Claude', 'brain', '.session')
|
|
10
|
+
|
|
11
|
+
function parseJwt(token) {
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString())
|
|
14
|
+
} catch { return {} }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getSession() {
|
|
18
|
+
try {
|
|
19
|
+
if (fs.existsSync(SESSION_PATH)) {
|
|
20
|
+
return JSON.parse(fs.readFileSync(SESSION_PATH, 'utf8'))
|
|
21
|
+
}
|
|
22
|
+
} catch {}
|
|
23
|
+
return null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function saveSession(session) {
|
|
27
|
+
const dir = path.dirname(SESSION_PATH)
|
|
28
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
29
|
+
fs.writeFileSync(SESSION_PATH, JSON.stringify(session, null, 2))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function deleteSession() {
|
|
33
|
+
try { fs.unlinkSync(SESSION_PATH) } catch {}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getAuthenticatedClient() {
|
|
37
|
+
const session = getSession()
|
|
38
|
+
const accessToken = session?.access_token || null
|
|
39
|
+
|
|
40
|
+
const client = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
|
|
41
|
+
global: {
|
|
42
|
+
headers: accessToken ? { Authorization: `Bearer ${accessToken}` } : {},
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const userId = accessToken ? parseJwt(accessToken).sub || null : null
|
|
47
|
+
return { client, userId }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = {
|
|
51
|
+
getAuthenticatedClient,
|
|
52
|
+
getSession,
|
|
53
|
+
saveSession,
|
|
54
|
+
deleteSession,
|
|
55
|
+
parseJwt,
|
|
56
|
+
get SESSION_PATH() { return SESSION_PATH },
|
|
57
|
+
set SESSION_PATH(v) { SESSION_PATH = v },
|
|
58
|
+
SUPABASE_URL,
|
|
59
|
+
SUPABASE_ANON_KEY,
|
|
60
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const express = require('express')
|
|
2
|
+
const { getAgent, buildAgentPrompt, trimHistoryToTokenBudget } = require('../lib/agents')
|
|
3
|
+
const { getHistory, saveHistory, getTasks, saveTasks, getApiKey, saveApiKey } = require('../lib/agent-storage')
|
|
4
|
+
|
|
5
|
+
const router = express.Router()
|
|
6
|
+
|
|
7
|
+
// Check if API key is configured
|
|
8
|
+
router.get('/agent-config', (_req, res) => {
|
|
9
|
+
const key = getApiKey()
|
|
10
|
+
res.json({ hasApiKey: !!key })
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
// Save API key
|
|
14
|
+
router.post('/agent-config', (req, res) => {
|
|
15
|
+
const { apiKey } = req.body
|
|
16
|
+
if (!apiKey || typeof apiKey !== 'string' || !apiKey.startsWith('sk-')) {
|
|
17
|
+
return res.status(400).json({ error: 'Invalid API key — should start with sk-' })
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
saveApiKey(apiKey)
|
|
21
|
+
res.json({ saved: true })
|
|
22
|
+
} catch (err) {
|
|
23
|
+
res.status(500).json({ error: err.message })
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// Get chat history for an agent
|
|
28
|
+
router.get('/agent-history', (req, res) => {
|
|
29
|
+
const { agentId } = req.query
|
|
30
|
+
if (!agentId || !getAgent(agentId)) {
|
|
31
|
+
return res.status(400).json({ error: 'Invalid agentId' })
|
|
32
|
+
}
|
|
33
|
+
res.json({ messages: getHistory(agentId) })
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// Save chat history for an agent
|
|
37
|
+
router.post('/agent-history', (req, res) => {
|
|
38
|
+
const { agentId, messages } = req.body
|
|
39
|
+
if (!agentId || !getAgent(agentId)) {
|
|
40
|
+
return res.status(400).json({ error: 'Invalid agentId' })
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
saveHistory(agentId, messages || [])
|
|
44
|
+
res.json({ saved: true })
|
|
45
|
+
} catch (err) {
|
|
46
|
+
res.status(500).json({ error: err.message })
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
// Get tasks for an agent
|
|
51
|
+
router.get('/agent-tasks', (req, res) => {
|
|
52
|
+
const { agentId } = req.query
|
|
53
|
+
if (!agentId || !getAgent(agentId)) {
|
|
54
|
+
return res.status(400).json({ error: 'Invalid agentId' })
|
|
55
|
+
}
|
|
56
|
+
res.json({ tasks: getTasks(agentId) })
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
// Save tasks for an agent
|
|
60
|
+
router.post('/agent-tasks', (req, res) => {
|
|
61
|
+
const { agentId, tasks } = req.body
|
|
62
|
+
if (!agentId || !getAgent(agentId)) {
|
|
63
|
+
return res.status(400).json({ error: 'Invalid agentId' })
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
saveTasks(agentId, tasks || [])
|
|
67
|
+
res.json({ saved: true })
|
|
68
|
+
} catch (err) {
|
|
69
|
+
res.status(500).json({ error: err.message })
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// Chat with an agent — streams response via SSE
|
|
74
|
+
router.post('/agent-chat', async (req, res) => {
|
|
75
|
+
const { agentId, message, history } = req.body
|
|
76
|
+
|
|
77
|
+
const agent = getAgent(agentId)
|
|
78
|
+
if (!agent) {
|
|
79
|
+
return res.status(400).json({ error: 'Unknown agent' })
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const apiKey = getApiKey()
|
|
83
|
+
if (!apiKey) {
|
|
84
|
+
return res.status(500).json({ error: 'ANTHROPIC_API_KEY not configured' })
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Set up SSE
|
|
88
|
+
res.setHeader('Content-Type', 'text/event-stream')
|
|
89
|
+
res.setHeader('Cache-Control', 'no-cache')
|
|
90
|
+
res.setHeader('Connection', 'keep-alive')
|
|
91
|
+
res.setHeader('X-Accel-Buffering', 'no')
|
|
92
|
+
|
|
93
|
+
const send = (data) => {
|
|
94
|
+
try { res.write(`data: ${JSON.stringify(data)}\n\n`) } catch {}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const Anthropic = require('@anthropic-ai/sdk')
|
|
99
|
+
const client = new Anthropic({ apiKey })
|
|
100
|
+
|
|
101
|
+
const os = require('os')
|
|
102
|
+
const path = require('path')
|
|
103
|
+
const brainDir = path.join(os.homedir(), 'Claude', 'brain')
|
|
104
|
+
const systemPrompt = buildAgentPrompt(agentId, brainDir)
|
|
105
|
+
|
|
106
|
+
// Build messages array — trim history to token budget
|
|
107
|
+
const trimmedHistory = trimHistoryToTokenBudget(history || [], 8000)
|
|
108
|
+
const messages = [
|
|
109
|
+
...trimmedHistory.map(m => ({ role: m.role, content: m.content })),
|
|
110
|
+
{ role: 'user', content: message },
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
const stream = client.messages.stream({
|
|
114
|
+
model: 'claude-sonnet-4-20250514',
|
|
115
|
+
max_tokens: 4096,
|
|
116
|
+
system: systemPrompt,
|
|
117
|
+
messages,
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
stream.on('text', (text) => {
|
|
121
|
+
send({ delta: text })
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
stream.on('end', () => {
|
|
125
|
+
send({ done: true })
|
|
126
|
+
res.end()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
stream.on('error', (err) => {
|
|
130
|
+
send({ error: `Agent response failed: ${err.message}` })
|
|
131
|
+
res.end()
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
// Handle client disconnect
|
|
135
|
+
req.on('close', () => {
|
|
136
|
+
stream.abort()
|
|
137
|
+
})
|
|
138
|
+
} catch (err) {
|
|
139
|
+
send({ error: `Agent response failed: ${err.message}` })
|
|
140
|
+
res.end()
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
module.exports = router
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const express = require('express')
|
|
2
|
+
const { getSession, saveSession, deleteSession, parseJwt } = require('../lib/supabase')
|
|
3
|
+
|
|
4
|
+
const router = express.Router()
|
|
5
|
+
|
|
6
|
+
router.get('/auth/session', (_req, res) => {
|
|
7
|
+
const session = getSession()
|
|
8
|
+
if (session && session.access_token) {
|
|
9
|
+
const payload = parseJwt(session.access_token)
|
|
10
|
+
res.json({
|
|
11
|
+
authenticated: true,
|
|
12
|
+
userId: payload.sub || null,
|
|
13
|
+
email: session.user?.email || payload.email || null,
|
|
14
|
+
})
|
|
15
|
+
} else {
|
|
16
|
+
res.json({ authenticated: false, userId: null, email: null })
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
router.post('/auth/save-session', (req, res) => {
|
|
21
|
+
const session = req.body
|
|
22
|
+
if (!session || !session.access_token) {
|
|
23
|
+
return res.status(400).json({ error: 'Missing access_token in session' })
|
|
24
|
+
}
|
|
25
|
+
saveSession(session)
|
|
26
|
+
res.json({ ok: true })
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
router.post('/auth/logout', (_req, res) => {
|
|
30
|
+
deleteSession()
|
|
31
|
+
res.json({ ok: true })
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
module.exports = router
|
package/server/routes/brain.js
CHANGED
|
@@ -35,6 +35,8 @@ router.post('/brain/save', (req, res) => {
|
|
|
35
35
|
try {
|
|
36
36
|
saveBrainCategory(category, fields)
|
|
37
37
|
ensureClaudeMdReference()
|
|
38
|
+
// Sync to Supabase (non-blocking — don't fail the request if sync fails)
|
|
39
|
+
brainManager.syncBrainToSupabase().catch(() => {})
|
|
38
40
|
const status = getBrainStatus()
|
|
39
41
|
res.json({ saved: true, ...status })
|
|
40
42
|
} catch (err) {
|
|
@@ -150,6 +152,8 @@ router.post('/brain/import', (req, res) => {
|
|
|
150
152
|
}
|
|
151
153
|
}
|
|
152
154
|
ensureClaudeMdReference()
|
|
155
|
+
// Sync to Supabase (non-blocking — don't fail the request if sync fails)
|
|
156
|
+
brainManager.syncBrainToSupabase().catch(() => {})
|
|
153
157
|
const status = getBrainStatus()
|
|
154
158
|
res.json({ imported: true, ...status, importedCategories: imported })
|
|
155
159
|
} catch (err) {
|
|
@@ -204,6 +208,8 @@ router.post('/brain/documents', express.raw({ type: '*/*', limit: '50mb' }), (re
|
|
|
204
208
|
}
|
|
205
209
|
|
|
206
210
|
ensureClaudeMdReference()
|
|
211
|
+
// Sync to Supabase (non-blocking — don't fail the request if sync fails)
|
|
212
|
+
brainManager.syncBrainToSupabase().catch(() => {})
|
|
207
213
|
const status = getBrainStatus()
|
|
208
214
|
const binaryFile = !textExts.includes(ext)
|
|
209
215
|
let message = 'File saved'
|
|
@@ -252,4 +258,20 @@ router.get('/brain-fields', (req, res) => {
|
|
|
252
258
|
}
|
|
253
259
|
})
|
|
254
260
|
|
|
261
|
+
// Pull brain from Supabase and update local cache
|
|
262
|
+
router.post('/brain/pull', async (_req, res) => {
|
|
263
|
+
try {
|
|
264
|
+
const brain = await brainManager.pullBrainFromSupabase()
|
|
265
|
+
if (brain) {
|
|
266
|
+
brainManager.ensureClaudeMdReference()
|
|
267
|
+
const status = brainManager.getBrainStatus()
|
|
268
|
+
res.json({ pulled: true, ...status })
|
|
269
|
+
} else {
|
|
270
|
+
res.json({ pulled: false, reason: 'No brain data in Supabase or not authenticated' })
|
|
271
|
+
}
|
|
272
|
+
} catch (err) {
|
|
273
|
+
res.status(500).json({ error: err.message })
|
|
274
|
+
}
|
|
275
|
+
})
|
|
276
|
+
|
|
255
277
|
module.exports = router
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
-- 007: Brain JSONB migration — replaces Ring columns with unified Brain
|
|
2
|
+
-- Run against AI Team Hub Supabase project (wiwlydjvpwvlosfojdbz)
|
|
3
|
+
|
|
4
|
+
BEGIN;
|
|
5
|
+
|
|
6
|
+
-- Link user_profiles to Supabase Auth
|
|
7
|
+
ALTER TABLE user_profiles
|
|
8
|
+
ADD COLUMN IF NOT EXISTS auth_id UUID UNIQUE REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
9
|
+
|
|
10
|
+
-- Auto-create user_profile on sign-up
|
|
11
|
+
CREATE OR REPLACE FUNCTION public.handle_new_user()
|
|
12
|
+
RETURNS trigger
|
|
13
|
+
LANGUAGE plpgsql
|
|
14
|
+
SECURITY DEFINER SET search_path = ''
|
|
15
|
+
AS $$
|
|
16
|
+
BEGIN
|
|
17
|
+
INSERT INTO public.user_profiles (auth_id, name, email)
|
|
18
|
+
VALUES (new.id, new.raw_user_meta_data->>'name', new.email);
|
|
19
|
+
RETURN new;
|
|
20
|
+
END;
|
|
21
|
+
$$;
|
|
22
|
+
|
|
23
|
+
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
|
|
24
|
+
CREATE TRIGGER on_auth_user_created
|
|
25
|
+
AFTER INSERT ON auth.users
|
|
26
|
+
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
|
|
27
|
+
|
|
28
|
+
-- Add auth_id directly to business_context
|
|
29
|
+
ALTER TABLE business_context
|
|
30
|
+
ADD COLUMN IF NOT EXISTS auth_id UUID UNIQUE REFERENCES auth.users(id) ON DELETE CASCADE;
|
|
31
|
+
|
|
32
|
+
-- Add brain JSONB column
|
|
33
|
+
ALTER TABLE business_context
|
|
34
|
+
ADD COLUMN IF NOT EXISTS brain JSONB DEFAULT '{}';
|
|
35
|
+
|
|
36
|
+
-- Drop Ring columns (clean slate)
|
|
37
|
+
ALTER TABLE business_context
|
|
38
|
+
DROP COLUMN IF EXISTS ring_avatar,
|
|
39
|
+
DROP COLUMN IF EXISTS ring_problem_dream,
|
|
40
|
+
DROP COLUMN IF EXISTS ring_product,
|
|
41
|
+
DROP COLUMN IF EXISTS ring_offer,
|
|
42
|
+
DROP COLUMN IF EXISTS ring_channels,
|
|
43
|
+
DROP COLUMN IF EXISTS ring_voice,
|
|
44
|
+
DROP COLUMN IF EXISTS ring_objections,
|
|
45
|
+
DROP COLUMN IF EXISTS ring_money_models;
|
|
46
|
+
|
|
47
|
+
-- RLS: users can only access their own brain
|
|
48
|
+
DROP POLICY IF EXISTS "Allow all business_context" ON business_context;
|
|
49
|
+
CREATE POLICY "Users can read own context"
|
|
50
|
+
ON business_context FOR SELECT USING (auth.uid() = auth_id);
|
|
51
|
+
CREATE POLICY "Users can insert own context"
|
|
52
|
+
ON business_context FOR INSERT WITH CHECK (auth.uid() = auth_id);
|
|
53
|
+
CREATE POLICY "Users can update own context"
|
|
54
|
+
ON business_context FOR UPDATE USING (auth.uid() = auth_id);
|
|
55
|
+
|
|
56
|
+
COMMIT;
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/app.tsx","./src/main.tsx","./src/components/brain/brainonboarding.tsx","./src/components/brain/brainstepdocuments.tsx","./src/components/brain/brainstepimport.tsx","./src/components/brain/brainsteptools.tsx","./src/components/brain/brainstepwebsite.tsx","./src/components/chat/buildsidebar.tsx","./src/components/checklist/brainstatussection.tsx","./src/components/checklist/clistatussection.tsx","./src/components/checklist/featurebuilder.tsx","./src/components/checklist/futurebuildsection.tsx","./src/components/checklist/healthcheckitem.tsx","./src/components/checklist/healthsection.tsx","./src/components/checklist/prepushsection.tsx","./src/components/checklist/testingsection.tsx","./src/components/document/contextsection.tsx","./src/components/document/docsidebar.tsx","./src/components/document/foldersection.tsx","./src/components/document/mcpsection.tsx","./src/components/document/outcomesection.tsx","./src/components/document/outputpanel.tsx","./src/components/document/stylereferencesection.tsx","./src/components/layout/checklistdrawer.tsx","./src/components/layout/errorbanner.tsx","./src/components/layout/iconrail.tsx","./src/components/layout/topbar.tsx","./src/components/preview/previewpanel.tsx","./src/components/setup/howitworks.tsx","./src/components/setup/projectselector.tsx","./src/components/setup/setupwizard.tsx","./src/components/setup/tooldetection.tsx","./src/components/setup/toolinstaller.tsx","./src/components/terminal/terminalpanel.tsx","./src/context/docmodecontext.tsx","./src/context/projectcontext.tsx","./src/context/terminalcontext.tsx","./src/hooks/usedocevents.ts","./src/hooks/usehealthscan.ts","./src/hooks/useprojectinfo.ts","./src/hooks/usesse.ts","./src/lib/api.ts","./src/lib/doc-prompts.ts","./src/lib/storage.ts","./src/lib/style-templates.ts","./src/types/doc.ts","./src/types/index.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["./src/app.tsx","./src/main.tsx","./src/components/agents/agentchat.tsx","./src/components/agents/agentslayout.tsx","./src/components/agents/agentssidebar.tsx","./src/components/agents/apikeysetup.tsx","./src/components/agents/messagebubble.tsx","./src/components/auth/signinscreen.tsx","./src/components/brain/brainonboarding.tsx","./src/components/brain/brainstepdocuments.tsx","./src/components/brain/brainstepimport.tsx","./src/components/brain/brainsteptools.tsx","./src/components/brain/brainstepwebsite.tsx","./src/components/chat/buildsidebar.tsx","./src/components/checklist/brainstatussection.tsx","./src/components/checklist/clistatussection.tsx","./src/components/checklist/featurebuilder.tsx","./src/components/checklist/futurebuildsection.tsx","./src/components/checklist/healthcheckitem.tsx","./src/components/checklist/healthsection.tsx","./src/components/checklist/prepushsection.tsx","./src/components/checklist/testingsection.tsx","./src/components/document/contextsection.tsx","./src/components/document/docsidebar.tsx","./src/components/document/foldersection.tsx","./src/components/document/mcpsection.tsx","./src/components/document/outcomesection.tsx","./src/components/document/outputpanel.tsx","./src/components/document/stylereferencesection.tsx","./src/components/layout/checklistdrawer.tsx","./src/components/layout/errorbanner.tsx","./src/components/layout/iconrail.tsx","./src/components/layout/topbar.tsx","./src/components/preview/previewpanel.tsx","./src/components/setup/howitworks.tsx","./src/components/setup/projectselector.tsx","./src/components/setup/setupwizard.tsx","./src/components/setup/tooldetection.tsx","./src/components/setup/toolinstaller.tsx","./src/components/terminal/terminalpanel.tsx","./src/context/agentscontext.tsx","./src/context/docmodecontext.tsx","./src/context/projectcontext.tsx","./src/context/terminalcontext.tsx","./src/hooks/usedocevents.ts","./src/hooks/usehealthscan.ts","./src/hooks/useprojectinfo.ts","./src/hooks/usesse.ts","./src/lib/api.ts","./src/lib/doc-prompts.ts","./src/lib/storage.ts","./src/lib/style-templates.ts","./src/types/doc.ts","./src/types/index.ts"],"version":"5.9.3"}
|