synabun 1.3.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/CHANGELOG.md +665 -0
- package/LICENSE +191 -0
- package/README.md +853 -0
- package/hooks/claude-code/post-plan.mjs +391 -0
- package/hooks/claude-code/post-remember.mjs +239 -0
- package/hooks/claude-code/pre-compact.mjs +241 -0
- package/hooks/claude-code/pre-websearch.mjs +90 -0
- package/hooks/claude-code/prompt-submit.mjs +861 -0
- package/hooks/claude-code/session-start.mjs +494 -0
- package/hooks/claude-code/shared.mjs +368 -0
- package/hooks/claude-code/stop.mjs +646 -0
- package/hooks/claude-code/test-user-learning.mjs +531 -0
- package/mcp-server/package.json +38 -0
- package/mcp-server/run.mjs +10 -0
- package/mcp-server/src/config.ts +70 -0
- package/mcp-server/src/http.ts +93 -0
- package/mcp-server/src/index.ts +203 -0
- package/mcp-server/src/preload-http.ts +25 -0
- package/mcp-server/src/preload.ts +29 -0
- package/mcp-server/src/scripts/migrate-qdrant-to-sqlite.ts +506 -0
- package/mcp-server/src/services/categories.ts +429 -0
- package/mcp-server/src/services/discord.ts +702 -0
- package/mcp-server/src/services/file-checksums.ts +33 -0
- package/mcp-server/src/services/local-embeddings.ts +77 -0
- package/mcp-server/src/services/neural-interface.ts +344 -0
- package/mcp-server/src/services/sqlite.ts +823 -0
- package/mcp-server/src/tools/browser-advanced.ts +123 -0
- package/mcp-server/src/tools/browser-interact.ts +255 -0
- package/mcp-server/src/tools/browser-navigate.ts +77 -0
- package/mcp-server/src/tools/browser-observe.ts +1330 -0
- package/mcp-server/src/tools/browser.ts +107 -0
- package/mcp-server/src/tools/card-tools.ts +193 -0
- package/mcp-server/src/tools/card.ts +22 -0
- package/mcp-server/src/tools/category.ts +379 -0
- package/mcp-server/src/tools/discord-channel.ts +274 -0
- package/mcp-server/src/tools/discord-guild.ts +188 -0
- package/mcp-server/src/tools/discord-member.ts +158 -0
- package/mcp-server/src/tools/discord-message.ts +231 -0
- package/mcp-server/src/tools/discord-onboarding.ts +228 -0
- package/mcp-server/src/tools/discord-role.ts +209 -0
- package/mcp-server/src/tools/discord-thread.ts +110 -0
- package/mcp-server/src/tools/discord-webhook.ts +176 -0
- package/mcp-server/src/tools/discord.ts +40 -0
- package/mcp-server/src/tools/forget.ts +38 -0
- package/mcp-server/src/tools/git-tools.ts +141 -0
- package/mcp-server/src/tools/git.ts +13 -0
- package/mcp-server/src/tools/image-tools.ts +98 -0
- package/mcp-server/src/tools/image.ts +17 -0
- package/mcp-server/src/tools/leonardo-browser-tools.ts +281 -0
- package/mcp-server/src/tools/leonardo.ts +28 -0
- package/mcp-server/src/tools/loop.ts +348 -0
- package/mcp-server/src/tools/memories.ts +118 -0
- package/mcp-server/src/tools/recall.ts +323 -0
- package/mcp-server/src/tools/reflect.ts +145 -0
- package/mcp-server/src/tools/remember.ts +115 -0
- package/mcp-server/src/tools/response.ts +26 -0
- package/mcp-server/src/tools/restore.ts +34 -0
- package/mcp-server/src/tools/sync.ts +114 -0
- package/mcp-server/src/tools/tictactoe-tools.ts +98 -0
- package/mcp-server/src/tools/tictactoe.ts +13 -0
- package/mcp-server/src/tools/utils.ts +25 -0
- package/mcp-server/src/tools/whiteboard-tools.ts +260 -0
- package/mcp-server/src/tools/whiteboard.ts +22 -0
- package/mcp-server/src/tui.ts +940 -0
- package/mcp-server/src/types.ts +85 -0
- package/mcp-server/tsconfig.json +19 -0
- package/neural-interface/package.json +27 -0
- package/neural-interface/public/apple-touch-icon.png +0 -0
- package/neural-interface/public/category-logos/claude.svg +1 -0
- package/neural-interface/public/category-logos/gemini-color.svg +1 -0
- package/neural-interface/public/category-logos/openai.svg +1 -0
- package/neural-interface/public/category-logos/synabun.png +0 -0
- package/neural-interface/public/claude-chat.css +878 -0
- package/neural-interface/public/claude-chat.html +92 -0
- package/neural-interface/public/claude-chat.js +1168 -0
- package/neural-interface/public/favicon-16x16.png +0 -0
- package/neural-interface/public/favicon-32x32.png +0 -0
- package/neural-interface/public/gallery.svg +6 -0
- package/neural-interface/public/icon-192.png +0 -0
- package/neural-interface/public/icon-512.png +0 -0
- package/neural-interface/public/index-legacy.html +14677 -0
- package/neural-interface/public/index.html +212 -0
- package/neural-interface/public/index2d-legacy.html +8193 -0
- package/neural-interface/public/index2d.html +127 -0
- package/neural-interface/public/invite.html +351 -0
- package/neural-interface/public/leonardoai.svg +1 -0
- package/neural-interface/public/logo-synabun.png +0 -0
- package/neural-interface/public/logoHD.png +0 -0
- package/neural-interface/public/manifest.json +14 -0
- package/neural-interface/public/offline.html +299 -0
- package/neural-interface/public/onboarding.html +2335 -0
- package/neural-interface/public/openclaw-logo-text.png +0 -0
- package/neural-interface/public/pin-svgrepo-com.svg +25 -0
- package/neural-interface/public/sessionicon.svg +8 -0
- package/neural-interface/public/shared/ansi-parser.js +305 -0
- package/neural-interface/public/shared/api.js +1043 -0
- package/neural-interface/public/shared/colors.js +153 -0
- package/neural-interface/public/shared/constants.js +141 -0
- package/neural-interface/public/shared/html-shell.js +777 -0
- package/neural-interface/public/shared/html-term-renderer.js +1022 -0
- package/neural-interface/public/shared/i18n.js +147 -0
- package/neural-interface/public/shared/registry.js +82 -0
- package/neural-interface/public/shared/state.js +86 -0
- package/neural-interface/public/shared/storage.js +150 -0
- package/neural-interface/public/shared/styles.css +21212 -0
- package/neural-interface/public/shared/ui-automation-studio.js +3573 -0
- package/neural-interface/public/shared/ui-bookmarks.js +231 -0
- package/neural-interface/public/shared/ui-claude-panel.js +6333 -0
- package/neural-interface/public/shared/ui-command-runner.js +534 -0
- package/neural-interface/public/shared/ui-cost-widget.js +602 -0
- package/neural-interface/public/shared/ui-detail.js +1454 -0
- package/neural-interface/public/shared/ui-explorer.js +1356 -0
- package/neural-interface/public/shared/ui-file-explorer.js +2750 -0
- package/neural-interface/public/shared/ui-games.js +411 -0
- package/neural-interface/public/shared/ui-help.js +107 -0
- package/neural-interface/public/shared/ui-image-gallery.js +461 -0
- package/neural-interface/public/shared/ui-invite.js +519 -0
- package/neural-interface/public/shared/ui-keybinds.js +452 -0
- package/neural-interface/public/shared/ui-layouts.js +297 -0
- package/neural-interface/public/shared/ui-link.js +731 -0
- package/neural-interface/public/shared/ui-loading.js +255 -0
- package/neural-interface/public/shared/ui-menubar.js +499 -0
- package/neural-interface/public/shared/ui-multiselect.js +93 -0
- package/neural-interface/public/shared/ui-navbar.js +222 -0
- package/neural-interface/public/shared/ui-notifications.js +287 -0
- package/neural-interface/public/shared/ui-panels.js +309 -0
- package/neural-interface/public/shared/ui-resume.js +653 -0
- package/neural-interface/public/shared/ui-search.js +145 -0
- package/neural-interface/public/shared/ui-sessions.js +531 -0
- package/neural-interface/public/shared/ui-settings.js +5987 -0
- package/neural-interface/public/shared/ui-sidebar.js +1905 -0
- package/neural-interface/public/shared/ui-skills.js +2805 -0
- package/neural-interface/public/shared/ui-stats.js +38 -0
- package/neural-interface/public/shared/ui-sync.js +201 -0
- package/neural-interface/public/shared/ui-terminal.js +6385 -0
- package/neural-interface/public/shared/ui-tooltip.js +123 -0
- package/neural-interface/public/shared/ui-trash.js +439 -0
- package/neural-interface/public/shared/ui-tutorial-draw.js +875 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +2276 -0
- package/neural-interface/public/shared/ui-tutorial.js +1117 -0
- package/neural-interface/public/shared/ui-update.js +244 -0
- package/neural-interface/public/shared/ui-whiteboard.js +3262 -0
- package/neural-interface/public/shared/ui-workspaces.js +722 -0
- package/neural-interface/public/shared/utils.js +360 -0
- package/neural-interface/public/shared/vterm-buffer.js +1102 -0
- package/neural-interface/public/sw.js +52 -0
- package/neural-interface/public/synabun.png +0 -0
- package/neural-interface/public/toolbar-album.svg +8 -0
- package/neural-interface/public/toolbar-question.svg +6 -0
- package/neural-interface/public/toolbar-sessions.svg +6 -0
- package/neural-interface/public/variant/2d/background.js +113 -0
- package/neural-interface/public/variant/2d/context-menu.js +133 -0
- package/neural-interface/public/variant/2d/gfx.js +45 -0
- package/neural-interface/public/variant/2d/graph.js +1635 -0
- package/neural-interface/public/variant/2d/hulls.js +207 -0
- package/neural-interface/public/variant/2d/lasso.js +135 -0
- package/neural-interface/public/variant/2d/layout.js +594 -0
- package/neural-interface/public/variant/2d/main.js +521 -0
- package/neural-interface/public/variant/2d/minimap.js +312 -0
- package/neural-interface/public/variant/2d/settings-gfx.js +98 -0
- package/neural-interface/public/variant/3d/background.js +884 -0
- package/neural-interface/public/variant/3d/camera.js +661 -0
- package/neural-interface/public/variant/3d/gfx.js +116 -0
- package/neural-interface/public/variant/3d/graph.js +2399 -0
- package/neural-interface/public/variant/3d/main.js +500 -0
- package/neural-interface/public/variant/3d/settings-gfx.js +228 -0
- package/neural-interface/scripts/rebuild-pty.js +100 -0
- package/neural-interface/server.js +15000 -0
- package/neural-interface/templates/CLAUDE-template.md +211 -0
- package/package.json +53 -0
- package/postinstall.js +135 -0
- package/setup.js +260 -0
- package/skills/leonardo/SKILL.md +159 -0
- package/skills/leonardo/icon.svg +1 -0
- package/skills/leonardo/modules/browser-guide.md +378 -0
- package/skills/leonardo/modules/image-prompter.md +277 -0
- package/skills/leonardo/modules/model-advisor.md +100 -0
- package/skills/leonardo/modules/prompt-library.md +110 -0
- package/skills/leonardo/modules/style-guide.md +186 -0
- package/skills/leonardo/modules/video-prompter.md +311 -0
- package/skills/synabun/SKILL.md +185 -0
- package/skills/synabun/icon.png +0 -0
- package/skills/synabun/modules/audit.md +374 -0
- package/skills/synabun/modules/changelog.md +194 -0
- package/skills/synabun/modules/idea.md +144 -0
- package/skills/synabun/modules/memorize.md +188 -0
- package/skills/synabun/synabunicon.png +0 -0
|
@@ -0,0 +1,1043 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — API Client
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
// Single source of truth for all REST API calls.
|
|
5
|
+
// Every fetch('/api/...') in the UI should route through here.
|
|
6
|
+
|
|
7
|
+
// ─── Helpers ─────────────────────────────
|
|
8
|
+
|
|
9
|
+
async function jsonFetch(url, options = {}) {
|
|
10
|
+
const res = await fetch(url, options);
|
|
11
|
+
if (!res.ok) {
|
|
12
|
+
let errMsg = `HTTP ${res.status}`;
|
|
13
|
+
try { const body = await res.json(); errMsg = body.error || errMsg; } catch {}
|
|
14
|
+
if (res.status === 403) {
|
|
15
|
+
console.warn(`[api] 403 Forbidden: ${url}`);
|
|
16
|
+
// Trigger global toast for guest feedback
|
|
17
|
+
window.dispatchEvent(new CustomEvent('synabun:forbidden', { detail: errMsg }));
|
|
18
|
+
const err = new Error(errMsg);
|
|
19
|
+
err.forbidden = true;
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
throw new Error(errMsg);
|
|
23
|
+
}
|
|
24
|
+
return res.json();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function jsonBody(data) {
|
|
28
|
+
return {
|
|
29
|
+
headers: { 'Content-Type': 'application/json' },
|
|
30
|
+
body: JSON.stringify(data),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ─── Health ──────────────────────────────
|
|
35
|
+
|
|
36
|
+
export async function fetchHealth() {
|
|
37
|
+
const res = await fetch('/api/health', { signal: AbortSignal.timeout(3000) });
|
|
38
|
+
return res.json();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function startHealth() {
|
|
42
|
+
const res = await fetch('/api/health/start', { method: 'POST' });
|
|
43
|
+
return res.json();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ─── Memories ────────────────────────────
|
|
47
|
+
|
|
48
|
+
export async function fetchMemories(includeLinks = true) {
|
|
49
|
+
const url = includeLinks ? '/api/memories' : '/api/memories?links=false';
|
|
50
|
+
const res = await fetch(url);
|
|
51
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
52
|
+
return res.json();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function fetchLinks() {
|
|
56
|
+
return jsonFetch('/api/links');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function fetchMemory(id) {
|
|
60
|
+
return jsonFetch(`/api/memory/${encodeURIComponent(id)}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function updateMemory(id, payload) {
|
|
64
|
+
return jsonFetch(`/api/memory/${encodeURIComponent(id)}`, {
|
|
65
|
+
method: 'PATCH',
|
|
66
|
+
...jsonBody(payload),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function deleteMemory(id) {
|
|
71
|
+
return jsonFetch(`/api/memory/${encodeURIComponent(id)}`, {
|
|
72
|
+
method: 'DELETE',
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export async function deleteMemoryPermanent(id) {
|
|
77
|
+
return jsonFetch(`/api/memory/${encodeURIComponent(id)}?permanent=true`, {
|
|
78
|
+
method: 'DELETE',
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ─── Search ──────────────────────────────
|
|
83
|
+
|
|
84
|
+
export async function searchMemories(query, limit = 15) {
|
|
85
|
+
return jsonFetch('/api/search', {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
...jsonBody({ query, limit }),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─── Stats ───────────────────────────────
|
|
92
|
+
|
|
93
|
+
export async function fetchStats() {
|
|
94
|
+
return jsonFetch('/api/stats');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ─── Categories ──────────────────────────
|
|
98
|
+
|
|
99
|
+
export async function fetchCategories() {
|
|
100
|
+
return jsonFetch('/api/categories');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function createCategory(payload) {
|
|
104
|
+
// payload: { name, description, color?, parent?, is_parent? }
|
|
105
|
+
return jsonFetch('/api/categories', {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
...jsonBody(payload),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export async function updateCategory(name, updates) {
|
|
112
|
+
// updates: { new_name?, description?, parent?, color?, is_parent? }
|
|
113
|
+
return jsonFetch(`/api/categories/${encodeURIComponent(name)}`, {
|
|
114
|
+
method: 'PUT',
|
|
115
|
+
...jsonBody(updates),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export async function patchCategory(name, updates) {
|
|
120
|
+
// updates: { description? }
|
|
121
|
+
return jsonFetch(`/api/categories/${encodeURIComponent(name)}`, {
|
|
122
|
+
method: 'PATCH',
|
|
123
|
+
...jsonBody(updates),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export async function deleteCategory(name, body = {}) {
|
|
128
|
+
// body: { reassign_to?, reassign_children_to?, delete_memories? }
|
|
129
|
+
return jsonFetch(`/api/categories/${encodeURIComponent(name)}`, {
|
|
130
|
+
method: 'DELETE',
|
|
131
|
+
...jsonBody(body),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export async function exportCategory(name) {
|
|
136
|
+
const res = await fetch(`/api/categories/${encodeURIComponent(name)}/export`);
|
|
137
|
+
if (!res.ok) {
|
|
138
|
+
let errMsg = 'Export failed';
|
|
139
|
+
try { const body = await res.json(); errMsg = body.error || errMsg; } catch {}
|
|
140
|
+
throw new Error(errMsg);
|
|
141
|
+
}
|
|
142
|
+
return res.blob();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export async function uploadCategoryLogo(name, fileBuffer, contentType) {
|
|
146
|
+
return jsonFetch(`/api/categories/${encodeURIComponent(name)}/logo`, {
|
|
147
|
+
method: 'POST',
|
|
148
|
+
headers: { 'Content-Type': contentType || 'image/png' },
|
|
149
|
+
body: fileBuffer,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export async function deleteCategoryLogo(name) {
|
|
154
|
+
return jsonFetch(`/api/categories/${encodeURIComponent(name)}/logo`, {
|
|
155
|
+
method: 'DELETE',
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ─── Trash ───────────────────────────────
|
|
160
|
+
|
|
161
|
+
export async function fetchTrash() {
|
|
162
|
+
return jsonFetch('/api/trash');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export async function restoreFromTrash(id) {
|
|
166
|
+
return jsonFetch(`/api/trash/${encodeURIComponent(id)}/restore`, {
|
|
167
|
+
method: 'POST',
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export async function purgeTrash() {
|
|
172
|
+
return jsonFetch('/api/trash/purge', {
|
|
173
|
+
method: 'DELETE',
|
|
174
|
+
...jsonBody({}),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ─── Settings ────────────────────────────
|
|
179
|
+
|
|
180
|
+
export async function fetchSettings() {
|
|
181
|
+
return jsonFetch('/api/settings');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export async function saveSettings(payload) {
|
|
185
|
+
// payload: { databasePath? }
|
|
186
|
+
return jsonFetch('/api/settings', {
|
|
187
|
+
method: 'PUT',
|
|
188
|
+
...jsonBody(payload),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ─── Display Settings ────────────────────
|
|
193
|
+
|
|
194
|
+
export async function fetchDisplaySettings() {
|
|
195
|
+
return jsonFetch('/api/display-settings');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export async function saveDisplaySettings(payload) {
|
|
199
|
+
// payload: { recallMaxChars? }
|
|
200
|
+
return jsonFetch('/api/display-settings', {
|
|
201
|
+
method: 'PUT',
|
|
202
|
+
...jsonBody(payload),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ─── Keybinds ────────────────────────────
|
|
207
|
+
|
|
208
|
+
export async function fetchKeybinds() {
|
|
209
|
+
return jsonFetch('/api/keybinds');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export async function saveKeybindsToServer(payload) {
|
|
213
|
+
return jsonFetch('/api/keybinds', {
|
|
214
|
+
method: 'PUT',
|
|
215
|
+
...jsonBody(payload),
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ─── Connections ─────────────────────────
|
|
220
|
+
|
|
221
|
+
export async function fetchConnections() {
|
|
222
|
+
return jsonFetch('/api/connections');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export async function suggestPort() {
|
|
226
|
+
return jsonFetch('/api/connections/suggest-port');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export async function createConnection(payload) {
|
|
230
|
+
// payload: { id, label, url, apiKey, collection }
|
|
231
|
+
return jsonFetch('/api/connections', {
|
|
232
|
+
method: 'POST',
|
|
233
|
+
...jsonBody(payload),
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export async function setActiveConnection(id) {
|
|
238
|
+
return jsonFetch('/api/connections/active', {
|
|
239
|
+
method: 'PUT',
|
|
240
|
+
...jsonBody({ id }),
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export async function deleteConnection(id) {
|
|
245
|
+
return jsonFetch(`/api/connections/${encodeURIComponent(id)}`, {
|
|
246
|
+
method: 'DELETE',
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export async function syncConnectionEnv() {
|
|
251
|
+
return jsonFetch('/api/connections/sync-env', { method: 'POST' });
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export async function startConnectionContainer(id) {
|
|
255
|
+
return jsonFetch('/api/connections/start-container', {
|
|
256
|
+
method: 'POST',
|
|
257
|
+
...jsonBody({ id }),
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export async function backupConnection(id) {
|
|
262
|
+
const res = await fetch(`/api/connections/${encodeURIComponent(id)}/backup`, {
|
|
263
|
+
method: 'POST',
|
|
264
|
+
});
|
|
265
|
+
if (!res.ok) {
|
|
266
|
+
let errMsg = 'Backup failed';
|
|
267
|
+
try { const body = await res.json(); errMsg = body.error || errMsg; } catch {}
|
|
268
|
+
throw new Error(errMsg);
|
|
269
|
+
}
|
|
270
|
+
// Returns a blob (snapshot file) with content-disposition header
|
|
271
|
+
const blob = await res.blob();
|
|
272
|
+
const disposition = res.headers.get('content-disposition') || '';
|
|
273
|
+
const filenameMatch = disposition.match(/filename="?([^"]+)"?/);
|
|
274
|
+
const filename = filenameMatch ? filenameMatch[1] : `backup-${id}.snapshot`;
|
|
275
|
+
return { blob, filename };
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export async function restoreConnection(id, snapshotBuffer) {
|
|
279
|
+
return jsonFetch(`/api/connections/${encodeURIComponent(id)}/restore`, {
|
|
280
|
+
method: 'POST',
|
|
281
|
+
headers: { 'Content-Type': 'application/octet-stream' },
|
|
282
|
+
body: snapshotBuffer,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export async function restoreStandalone(params, snapshotBuffer) {
|
|
287
|
+
// params: { url, apiKey, collection, label? }
|
|
288
|
+
const qs = new URLSearchParams(params).toString();
|
|
289
|
+
return jsonFetch(`/api/connections/restore-standalone?${qs}`, {
|
|
290
|
+
method: 'POST',
|
|
291
|
+
headers: { 'Content-Type': 'application/octet-stream' },
|
|
292
|
+
body: snapshotBuffer,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ─── Full System Backup & Restore ────────
|
|
297
|
+
|
|
298
|
+
export async function systemBackup() {
|
|
299
|
+
const res = await fetch('/api/system/backup');
|
|
300
|
+
if (!res.ok) {
|
|
301
|
+
let errMsg = 'Backup failed';
|
|
302
|
+
try { const body = await res.json(); errMsg = body.error || errMsg; } catch {}
|
|
303
|
+
throw new Error(errMsg);
|
|
304
|
+
}
|
|
305
|
+
const blob = await res.blob();
|
|
306
|
+
const disposition = res.headers.get('content-disposition') || '';
|
|
307
|
+
const filenameMatch = disposition.match(/filename="?([^"]+)"?/);
|
|
308
|
+
const filename = filenameMatch ? filenameMatch[1] : 'synabun-backup.zip';
|
|
309
|
+
return { blob, filename };
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export async function systemRestorePreview(zipBuffer) {
|
|
313
|
+
const res = await fetch('/api/system/restore/preview', {
|
|
314
|
+
method: 'POST',
|
|
315
|
+
headers: { 'Content-Type': 'application/zip' },
|
|
316
|
+
body: zipBuffer,
|
|
317
|
+
});
|
|
318
|
+
if (!res.ok) {
|
|
319
|
+
let errMsg = 'Preview failed';
|
|
320
|
+
try { const body = await res.json(); errMsg = body.error || errMsg; } catch {}
|
|
321
|
+
throw new Error(errMsg);
|
|
322
|
+
}
|
|
323
|
+
return res.json();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export async function systemRestore(zipBuffer, mode = 'full') {
|
|
327
|
+
const res = await fetch(`/api/system/restore?mode=${encodeURIComponent(mode)}`, {
|
|
328
|
+
method: 'POST',
|
|
329
|
+
headers: { 'Content-Type': 'application/zip' },
|
|
330
|
+
body: zipBuffer,
|
|
331
|
+
});
|
|
332
|
+
if (!res.ok) {
|
|
333
|
+
let errMsg = 'Restore failed';
|
|
334
|
+
try { const body = await res.json(); errMsg = body.error || errMsg; } catch {}
|
|
335
|
+
throw new Error(errMsg);
|
|
336
|
+
}
|
|
337
|
+
return res.json();
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export async function createCollection(payload) {
|
|
341
|
+
// payload: { url, apiKey, collection }
|
|
342
|
+
return jsonFetch('/api/connections/create-collection', {
|
|
343
|
+
method: 'POST',
|
|
344
|
+
...jsonBody(payload),
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// ─── OpenClaw Bridge ─────────────────────
|
|
349
|
+
|
|
350
|
+
export async function fetchOpenClawBridge() {
|
|
351
|
+
return jsonFetch('/api/bridges/openclaw');
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export async function connectOpenClawBridge() {
|
|
355
|
+
return jsonFetch('/api/bridges/openclaw/connect', {
|
|
356
|
+
method: 'POST',
|
|
357
|
+
...jsonBody({}),
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export async function syncOpenClawBridge() {
|
|
362
|
+
return jsonFetch('/api/bridges/openclaw/sync', { method: 'POST' });
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export async function disconnectOpenClawBridge() {
|
|
366
|
+
return jsonFetch('/api/bridges/openclaw', { method: 'DELETE' });
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// ─── Memory Sync ─────────────────────────
|
|
370
|
+
|
|
371
|
+
export async function checkSync() {
|
|
372
|
+
return jsonFetch('/api/sync/check');
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// ─── Claude Code Integrations ────────────
|
|
376
|
+
|
|
377
|
+
export async function fetchClaudeCodeIntegrations() {
|
|
378
|
+
return jsonFetch('/api/claude-code/integrations');
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export async function toggleClaudeCodeIntegration(method, payload) {
|
|
382
|
+
// method: 'POST' | 'DELETE'
|
|
383
|
+
// payload: { target, projectPath?, hook? }
|
|
384
|
+
return jsonFetch('/api/claude-code/integrations', {
|
|
385
|
+
method,
|
|
386
|
+
...jsonBody(payload),
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export async function removeClaudeCodeProject(index) {
|
|
391
|
+
return jsonFetch(`/api/claude-code/projects/${index}`, {
|
|
392
|
+
method: 'DELETE',
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export async function fetchClaudeCodeHookFeatures() {
|
|
397
|
+
return jsonFetch('/api/claude-code/hook-features');
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export async function updateClaudeCodeHookFeature(feature, enabled) {
|
|
401
|
+
return jsonFetch('/api/claude-code/hook-features', {
|
|
402
|
+
method: 'PUT',
|
|
403
|
+
...jsonBody({ feature, enabled }),
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
export async function fetchClaudeCodeRuleset() {
|
|
408
|
+
return jsonFetch('/api/claude-code/ruleset');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// ─── Claude Code MCP ─────────────────────
|
|
412
|
+
|
|
413
|
+
export async function fetchClaudeCodeMcp() {
|
|
414
|
+
return jsonFetch('/api/claude-code/mcp');
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export async function toggleClaudeCodeMcp(method) {
|
|
418
|
+
// method: 'POST' to register, 'DELETE' to unregister
|
|
419
|
+
return jsonFetch('/api/claude-code/mcp', { method });
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// ─── Claude Code Skills ──────────────────
|
|
423
|
+
|
|
424
|
+
export async function fetchClaudeCodeSkills() {
|
|
425
|
+
return jsonFetch('/api/claude-code/skills');
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export async function toggleClaudeCodeSkill(method, skillName) {
|
|
429
|
+
// method: 'POST' to install, 'DELETE' to uninstall
|
|
430
|
+
return jsonFetch('/api/claude-code/skills', {
|
|
431
|
+
method,
|
|
432
|
+
...jsonBody({ name: skillName }),
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// ─── Skills Studio ───────────────────────
|
|
437
|
+
|
|
438
|
+
export async function fetchSkillsLibrary() {
|
|
439
|
+
return jsonFetch('/api/skills-studio/library');
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
export async function fetchSkillsArtifact(encodedId) {
|
|
443
|
+
return jsonFetch(`/api/skills-studio/artifact/${encodedId}`);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
export async function saveSkillsArtifact(encodedId, rawContent) {
|
|
447
|
+
return jsonFetch(`/api/skills-studio/artifact/${encodedId}`, {
|
|
448
|
+
method: 'PUT',
|
|
449
|
+
...jsonBody({ rawContent }),
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export async function fetchSkillsSubFile(encodedId, path) {
|
|
454
|
+
return jsonFetch(`/api/skills-studio/artifact/${encodedId}/file?path=${encodeURIComponent(path)}`);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export async function saveSkillsSubFile(encodedId, path, content) {
|
|
458
|
+
return jsonFetch(`/api/skills-studio/artifact/${encodedId}/file`, {
|
|
459
|
+
method: 'PUT',
|
|
460
|
+
...jsonBody({ path, content }),
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export async function createSkillsSubFile(encodedId, path, content, isDir) {
|
|
465
|
+
return jsonFetch(`/api/skills-studio/artifact/${encodedId}/file`, {
|
|
466
|
+
method: 'POST',
|
|
467
|
+
...jsonBody({ path, content, isDir }),
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
export async function deleteSkillsSubFile(encodedId, path) {
|
|
472
|
+
return jsonFetch(`/api/skills-studio/artifact/${encodedId}/file`, {
|
|
473
|
+
method: 'DELETE',
|
|
474
|
+
...jsonBody({ path }),
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export async function createSkillsArtifact(payload) {
|
|
479
|
+
return jsonFetch('/api/skills-studio/create', {
|
|
480
|
+
method: 'POST',
|
|
481
|
+
...jsonBody(payload),
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
export async function deleteSkillsArtifact(encodedId) {
|
|
486
|
+
return jsonFetch(`/api/skills-studio/artifact/${encodedId}`, {
|
|
487
|
+
method: 'DELETE',
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export async function validateSkillsArtifact(rawContent, type) {
|
|
492
|
+
return jsonFetch('/api/skills-studio/validate', {
|
|
493
|
+
method: 'POST',
|
|
494
|
+
...jsonBody({ rawContent, type }),
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export async function installSkillsBundled(dirName) {
|
|
499
|
+
return jsonFetch('/api/skills-studio/install', {
|
|
500
|
+
method: 'POST',
|
|
501
|
+
...jsonBody({ dirName }),
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
export async function uninstallSkillsBundled(dirName) {
|
|
506
|
+
return jsonFetch('/api/skills-studio/install', {
|
|
507
|
+
method: 'DELETE',
|
|
508
|
+
...jsonBody({ dirName }),
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
export async function importSkillsBundle(bundle, scope, projectPath) {
|
|
513
|
+
return jsonFetch('/api/skills-studio/import', {
|
|
514
|
+
method: 'POST',
|
|
515
|
+
...jsonBody({ bundle, scope, projectPath }),
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
export function getSkillsExportUrl(encodedId) {
|
|
520
|
+
return `/api/skills-studio/export/${encodedId}`;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
export function getSkillsIconUrl(encodedId) {
|
|
524
|
+
return `/api/skills-studio/artifact/${encodedId}/icon`;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
export async function uploadSkillsIcon(encodedId, fileBuffer, contentType) {
|
|
528
|
+
return jsonFetch(`/api/skills-studio/artifact/${encodedId}/icon`, {
|
|
529
|
+
method: 'POST',
|
|
530
|
+
headers: { 'Content-Type': contentType || 'image/png' },
|
|
531
|
+
body: fileBuffer,
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
export async function deleteSkillsIcon(encodedId) {
|
|
536
|
+
return jsonFetch(`/api/skills-studio/artifact/${encodedId}/icon`, { method: 'DELETE' });
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// ─── MCP Key ─────────────────────────────
|
|
540
|
+
|
|
541
|
+
export async function fetchMcpKey() {
|
|
542
|
+
return jsonFetch('/api/mcp-key');
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
export async function generateMcpKey() {
|
|
546
|
+
return jsonFetch('/api/mcp-key', { method: 'POST' });
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
export async function revokeMcpKey() {
|
|
550
|
+
return jsonFetch('/api/mcp-key', { method: 'DELETE' });
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// ─── Tunnel ──────────────────────────────
|
|
554
|
+
|
|
555
|
+
export async function fetchTunnelStatus() {
|
|
556
|
+
return jsonFetch('/api/tunnel/status');
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
export async function startTunnel() {
|
|
560
|
+
return jsonFetch('/api/tunnel/start', { method: 'POST' });
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
export async function stopTunnel() {
|
|
564
|
+
return jsonFetch('/api/tunnel/stop', { method: 'POST' });
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// ─── Last Session (resume after restart) ──
|
|
568
|
+
|
|
569
|
+
export async function fetchLastSession() {
|
|
570
|
+
const r = await fetch('/api/last-session');
|
|
571
|
+
if (!r.ok) return null;
|
|
572
|
+
return r.json();
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
export async function dismissLastSession() {
|
|
576
|
+
return fetch('/api/last-session', { method: 'DELETE' });
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// ─── Terminal ────────────────────────────
|
|
580
|
+
|
|
581
|
+
export async function fetchTerminalSessions() {
|
|
582
|
+
return jsonFetch('/api/terminal/sessions');
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
export async function createTerminalSession(profile, cols, rows, cwd, opts = {}) {
|
|
586
|
+
return jsonFetch('/api/terminal/sessions', {
|
|
587
|
+
method: 'POST',
|
|
588
|
+
...jsonBody({ profile, cols, rows, cwd, ...opts }),
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// ─── Claude Code Sessions (Resume) ─────
|
|
593
|
+
|
|
594
|
+
export async function fetchClaudeSessions({ project, limit, offset, search, refresh } = {}) {
|
|
595
|
+
const params = new URLSearchParams();
|
|
596
|
+
if (project) params.set('project', project);
|
|
597
|
+
if (limit) params.set('limit', String(limit));
|
|
598
|
+
if (offset) params.set('offset', String(offset));
|
|
599
|
+
if (search) params.set('search', search);
|
|
600
|
+
if (refresh) params.set('refresh', 'true');
|
|
601
|
+
return jsonFetch(`/api/claude-code/sessions?${params}`);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// ─── Session Indexing ─────
|
|
605
|
+
|
|
606
|
+
export async function startSessionIndexing({ project, reindex, sessionIds } = {}) {
|
|
607
|
+
return jsonFetch('/api/session-indexing/start', {
|
|
608
|
+
method: 'POST',
|
|
609
|
+
headers: { 'Content-Type': 'application/json' },
|
|
610
|
+
body: JSON.stringify({ project, reindex, sessionIds }),
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
export async function cancelSessionIndexing() {
|
|
615
|
+
return jsonFetch('/api/session-indexing/cancel', {
|
|
616
|
+
method: 'POST',
|
|
617
|
+
headers: { 'Content-Type': 'application/json' },
|
|
618
|
+
body: JSON.stringify({}),
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
export async function fetchIndexingStatus() {
|
|
623
|
+
return jsonFetch('/api/session-indexing/status');
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
export async function deleteTerminalSession(sessionId) {
|
|
627
|
+
return jsonFetch(`/api/terminal/sessions/${encodeURIComponent(sessionId)}`, {
|
|
628
|
+
method: 'DELETE',
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
export async function fetchTerminalFiles(dirPath, search) {
|
|
633
|
+
let url = `/api/terminal/files?path=${encodeURIComponent(dirPath)}`;
|
|
634
|
+
if (search) url += `&search=${encodeURIComponent(search)}`;
|
|
635
|
+
return jsonFetch(url);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export async function fetchTerminalBranches(dirPath) {
|
|
639
|
+
return jsonFetch(`/api/terminal/branches?path=${encodeURIComponent(dirPath)}`);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
export async function checkoutTerminalBranch(dirPath, branch) {
|
|
643
|
+
return jsonFetch('/api/terminal/checkout', {
|
|
644
|
+
method: 'POST',
|
|
645
|
+
...jsonBody({ path: dirPath, branch }),
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// ─── Terminal Links ──────────────────────
|
|
650
|
+
|
|
651
|
+
export async function fetchTerminalLinks() {
|
|
652
|
+
return jsonFetch('/api/terminal/links');
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
export async function fetchTerminalLink(linkId) {
|
|
656
|
+
return jsonFetch(`/api/terminal/links/${encodeURIComponent(linkId)}`);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
export async function createTerminalLink(sessions, config = {}) {
|
|
660
|
+
return jsonFetch('/api/terminal/links', {
|
|
661
|
+
method: 'POST',
|
|
662
|
+
...jsonBody({ sessions, ...config }),
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export async function deleteTerminalLink(linkId) {
|
|
667
|
+
return jsonFetch(`/api/terminal/links/${encodeURIComponent(linkId)}`, {
|
|
668
|
+
method: 'DELETE',
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
export async function detectClaudeSession(terminalSessionId) {
|
|
673
|
+
return jsonFetch(`/api/terminal/sessions/${encodeURIComponent(terminalSessionId)}/claude-session`);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
export async function updateTerminalLink(linkId, config) {
|
|
677
|
+
return jsonFetch(`/api/terminal/links/${encodeURIComponent(linkId)}`, {
|
|
678
|
+
method: 'PATCH',
|
|
679
|
+
...jsonBody(config),
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
export async function sendLinkMessage(linkId, message, targetIdx) {
|
|
684
|
+
return jsonFetch(`/api/terminal/links/${encodeURIComponent(linkId)}/send`, {
|
|
685
|
+
method: 'POST',
|
|
686
|
+
...jsonBody({ message, targetIdx }),
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
export async function pauseLink(linkId) {
|
|
691
|
+
return jsonFetch(`/api/terminal/links/${encodeURIComponent(linkId)}/pause`, {
|
|
692
|
+
method: 'POST',
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
export async function resumeLink(linkId) {
|
|
697
|
+
return jsonFetch(`/api/terminal/links/${encodeURIComponent(linkId)}/resume`, {
|
|
698
|
+
method: 'POST',
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
export async function nudgeLink(linkId) {
|
|
703
|
+
return jsonFetch(`/api/terminal/links/${encodeURIComponent(linkId)}/nudge`, {
|
|
704
|
+
method: 'POST',
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// ─── Browser Sessions ────────────────────
|
|
709
|
+
|
|
710
|
+
export async function fetchBrowserSessions() {
|
|
711
|
+
return jsonFetch('/api/browser/sessions');
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
export async function createBrowserSession(url, width, height, fingerprint, opts = {}) {
|
|
715
|
+
return jsonFetch('/api/browser/sessions', {
|
|
716
|
+
method: 'POST',
|
|
717
|
+
...jsonBody({ url, width, height, ...fingerprint, ...opts }),
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
export async function deleteBrowserSession(sessionId) {
|
|
722
|
+
return jsonFetch(`/api/browser/sessions/${encodeURIComponent(sessionId)}`, {
|
|
723
|
+
method: 'DELETE',
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
export async function navigateBrowser(sessionId, url) {
|
|
728
|
+
return jsonFetch(`/api/browser/sessions/${encodeURIComponent(sessionId)}/navigate`, {
|
|
729
|
+
method: 'POST',
|
|
730
|
+
...jsonBody({ url }),
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
export async function browserBack(sessionId) {
|
|
735
|
+
return jsonFetch(`/api/browser/sessions/${encodeURIComponent(sessionId)}/back`, {
|
|
736
|
+
method: 'POST',
|
|
737
|
+
...jsonBody({}),
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
export async function browserForward(sessionId) {
|
|
742
|
+
return jsonFetch(`/api/browser/sessions/${encodeURIComponent(sessionId)}/forward`, {
|
|
743
|
+
method: 'POST',
|
|
744
|
+
...jsonBody({}),
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
export async function browserReload(sessionId) {
|
|
749
|
+
return jsonFetch(`/api/browser/sessions/${encodeURIComponent(sessionId)}/reload`, {
|
|
750
|
+
method: 'POST',
|
|
751
|
+
...jsonBody({}),
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
export async function fetchBrowserCdp(sessionId) {
|
|
756
|
+
return jsonFetch(`/api/browser/sessions/${encodeURIComponent(sessionId)}/cdp`);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// ─── Setup (Onboarding) ─────────────────
|
|
760
|
+
|
|
761
|
+
export async function checkSetupDeps() {
|
|
762
|
+
return jsonFetch('/api/setup/check-deps');
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
export async function fetchSetupStatus() {
|
|
766
|
+
return jsonFetch('/api/setup/onboarding');
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
export async function saveSetupConfig(payload) {
|
|
770
|
+
return jsonFetch('/api/setup/save-config', {
|
|
771
|
+
method: 'POST',
|
|
772
|
+
...jsonBody(payload),
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
export async function setupCreateCollection(payload) {
|
|
777
|
+
return jsonFetch('/api/setup/create-collection', {
|
|
778
|
+
method: 'POST',
|
|
779
|
+
...jsonBody(payload),
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
export async function setupBuild() {
|
|
784
|
+
return jsonFetch('/api/setup/build', { method: 'POST' });
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
export async function testDatabase() {
|
|
788
|
+
return jsonFetch('/api/setup/test-qdrant');
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
export async function testDatabaseRemote(payload) {
|
|
792
|
+
return jsonFetch('/api/setup/test-qdrant-cloud', {
|
|
793
|
+
method: 'POST',
|
|
794
|
+
...jsonBody(payload),
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
export async function writeMcpJson(payload) {
|
|
799
|
+
return jsonFetch('/api/setup/write-mcp-json', {
|
|
800
|
+
method: 'POST',
|
|
801
|
+
...jsonBody(payload),
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
export async function writeInstructions(payload) {
|
|
806
|
+
return jsonFetch('/api/setup/write-instructions', {
|
|
807
|
+
method: 'POST',
|
|
808
|
+
...jsonBody(payload),
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
export async function completeSetup() {
|
|
813
|
+
return jsonFetch('/api/setup/complete', { method: 'POST' });
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// ─── Invite / Session Sharing ─────────────
|
|
817
|
+
|
|
818
|
+
export async function fetchInviteStatus() {
|
|
819
|
+
return jsonFetch('/api/invite/status');
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
export async function generateInviteKey(custom) {
|
|
823
|
+
const body = custom ? { custom } : {};
|
|
824
|
+
return jsonFetch('/api/invite/key', {
|
|
825
|
+
method: 'POST',
|
|
826
|
+
...jsonBody(body),
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
export async function revokeInviteKey() {
|
|
831
|
+
return jsonFetch('/api/invite/key', { method: 'DELETE' });
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
export async function revokeAllInviteSessions() {
|
|
835
|
+
return jsonFetch('/api/invite/sessions', { method: 'DELETE' });
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
export async function saveInviteProxy(config) {
|
|
839
|
+
return jsonFetch('/api/invite/proxy', {
|
|
840
|
+
method: 'PUT',
|
|
841
|
+
...jsonBody(config),
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
export async function fetchInvitePermissions() {
|
|
846
|
+
return jsonFetch('/api/invite/permissions');
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
export async function saveInvitePermissions(perms) {
|
|
850
|
+
return jsonFetch('/api/invite/permissions', {
|
|
851
|
+
method: 'PUT',
|
|
852
|
+
...jsonBody(perms),
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// ── Loop Templates ──
|
|
857
|
+
|
|
858
|
+
export async function fetchLoopTemplates() {
|
|
859
|
+
return jsonFetch('/api/loop/templates');
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
export async function createLoopTemplate(payload) {
|
|
863
|
+
return jsonFetch('/api/loop/templates', {
|
|
864
|
+
method: 'POST',
|
|
865
|
+
...jsonBody(payload),
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
export async function updateLoopTemplate(id, payload) {
|
|
870
|
+
return jsonFetch(`/api/loop/templates/${id}`, {
|
|
871
|
+
method: 'PUT',
|
|
872
|
+
...jsonBody(payload),
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
export async function deleteLoopTemplate(id) {
|
|
877
|
+
return jsonFetch(`/api/loop/templates/${id}`, { method: 'DELETE' });
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
export async function importLoopTemplates(data) {
|
|
881
|
+
return jsonFetch('/api/loop/templates/import', {
|
|
882
|
+
method: 'POST',
|
|
883
|
+
...jsonBody(data),
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
export async function fetchActiveLoop() {
|
|
888
|
+
return jsonFetch('/api/loop/active');
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
export async function launchLoop(params) {
|
|
892
|
+
return jsonFetch('/api/loop/launch', {
|
|
893
|
+
method: 'POST',
|
|
894
|
+
...jsonBody(params),
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
export async function stopLoop() {
|
|
899
|
+
return jsonFetch('/api/loop/stop', { method: 'POST' });
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
export async function fetchLoopHistory(limit = 50) {
|
|
903
|
+
return jsonFetch(`/api/loop/history?limit=${limit}`);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
export async function deleteLoopHistory(id) {
|
|
907
|
+
return jsonFetch(`/api/loop/history/${id}`, { method: 'DELETE' });
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
export async function storeLoopCompletion(data) {
|
|
911
|
+
return jsonFetch('/api/loop/complete', {
|
|
912
|
+
method: 'POST',
|
|
913
|
+
...jsonBody(data),
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
export async function searchMemoriesByCategory(query, category, limit = 15) {
|
|
918
|
+
return jsonFetch('/api/search/memories', {
|
|
919
|
+
method: 'POST',
|
|
920
|
+
...jsonBody({ query, category, limit }),
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
// ── Loop Schedules ──
|
|
925
|
+
|
|
926
|
+
export async function fetchSchedules() {
|
|
927
|
+
return jsonFetch('/api/schedules');
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
export async function createSchedule(params) {
|
|
931
|
+
return jsonFetch('/api/schedules', {
|
|
932
|
+
method: 'POST',
|
|
933
|
+
...jsonBody(params),
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
export async function fetchSchedule(id) {
|
|
938
|
+
return jsonFetch(`/api/schedules/${encodeURIComponent(id)}`);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
export async function updateSchedule(id, params) {
|
|
942
|
+
return jsonFetch(`/api/schedules/${encodeURIComponent(id)}`, {
|
|
943
|
+
method: 'PUT',
|
|
944
|
+
...jsonBody(params),
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
export async function deleteSchedule(id) {
|
|
949
|
+
return jsonFetch(`/api/schedules/${encodeURIComponent(id)}`, {
|
|
950
|
+
method: 'DELETE',
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
export async function testSchedule(id) {
|
|
955
|
+
return jsonFetch(`/api/schedules/${encodeURIComponent(id)}/test`, {
|
|
956
|
+
method: 'POST',
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
export async function startScheduleTimer(id, minutes) {
|
|
961
|
+
return jsonFetch(`/api/schedules/${encodeURIComponent(id)}/timer`, {
|
|
962
|
+
method: 'POST',
|
|
963
|
+
...jsonBody({ minutes }),
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
export async function cancelScheduleTimer(id) {
|
|
968
|
+
return jsonFetch(`/api/schedules/${encodeURIComponent(id)}/timer`, {
|
|
969
|
+
method: 'DELETE',
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
export async function fetchScheduleTimers() {
|
|
974
|
+
return jsonFetch('/api/schedules/timers');
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// ── Quick Timers ──
|
|
978
|
+
|
|
979
|
+
export async function createQuickTimer(templateId, minutes, { profile, model, usesBrowser } = {}) {
|
|
980
|
+
return jsonFetch('/api/quick-timer', {
|
|
981
|
+
method: 'POST',
|
|
982
|
+
...jsonBody({ templateId, minutes, profile, model, usesBrowser }),
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
export async function fetchQuickTimers() {
|
|
987
|
+
return jsonFetch('/api/quick-timers');
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
export async function cancelQuickTimer(id) {
|
|
991
|
+
return jsonFetch(`/api/quick-timers/${encodeURIComponent(id)}`, {
|
|
992
|
+
method: 'DELETE',
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
export async function triggerQuickTimerNow(templateId, { profile, model, usesBrowser } = {}) {
|
|
997
|
+
return jsonFetch('/api/quick-timer/now', {
|
|
998
|
+
method: 'POST',
|
|
999
|
+
...jsonBody({ templateId, profile, model, usesBrowser }),
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// ── Isolated Agents ──
|
|
1004
|
+
|
|
1005
|
+
export async function launchAgent(params) {
|
|
1006
|
+
return jsonFetch('/api/agents/launch', {
|
|
1007
|
+
method: 'POST',
|
|
1008
|
+
...jsonBody(params),
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
export async function fetchAgents() {
|
|
1013
|
+
return jsonFetch('/api/agents');
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
export async function fetchAgent(id) {
|
|
1017
|
+
return jsonFetch(`/api/agents/${id}`);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
export async function stopAgent(id) {
|
|
1021
|
+
return jsonFetch(`/api/agents/${id}/stop`, { method: 'POST' });
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
export async function removeAgent(id) {
|
|
1025
|
+
return jsonFetch(`/api/agents/${id}`, { method: 'DELETE' });
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// ─── Image Gallery ──────────────────────
|
|
1029
|
+
|
|
1030
|
+
export async function fetchImages() {
|
|
1031
|
+
return jsonFetch('/api/images');
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
export async function toggleImageFavorite(filename, favorite) {
|
|
1035
|
+
return jsonFetch('/api/images/favorite', {
|
|
1036
|
+
method: 'POST',
|
|
1037
|
+
...jsonBody({ filename, favorite }),
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
export async function deleteImage(filename) {
|
|
1042
|
+
return jsonFetch(`/api/images/${encodeURIComponent(filename)}`, { method: 'DELETE' });
|
|
1043
|
+
}
|