ltcai 8.0.0 → 8.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.
Files changed (103) hide show
  1. package/README.md +32 -50
  2. package/docs/CHANGELOG.md +14 -0
  3. package/docs/V3_FRONTEND.md +11 -5
  4. package/lattice_brain/__init__.py +1 -1
  5. package/lattice_brain/embeddings.py +9 -1
  6. package/lattice_brain/runtime/multi_agent.py +1 -1
  7. package/latticeai/__init__.py +1 -1
  8. package/latticeai/app_factory.py +13 -134
  9. package/latticeai/core/local_embeddings.py +8 -0
  10. package/latticeai/core/marketplace.py +1 -1
  11. package/latticeai/core/mcp_registry.py +140 -1
  12. package/latticeai/core/workspace_os.py +1 -1
  13. package/latticeai/services/architecture_readiness.py +6 -5
  14. package/latticeai/services/model_runtime.py +36 -2
  15. package/latticeai/services/product_readiness.py +18 -18
  16. package/package.json +2 -2
  17. package/scripts/build_frontend_assets.mjs +11 -2
  18. package/src-tauri/Cargo.lock +1 -1
  19. package/src-tauri/Cargo.toml +1 -1
  20. package/src-tauri/tauri.conf.json +1 -1
  21. package/static/app/asset-manifest.json +11 -102
  22. package/static/app/assets/Act-BOO66G-c.js +1 -0
  23. package/static/app/assets/Brain-C6lEYiD7.js +321 -0
  24. package/static/app/assets/{Capture-B9Tlhzqr.js → Capture-TATXBRDw.js} +1 -2
  25. package/static/app/assets/Library-DK4FIp8a.js +1 -0
  26. package/static/app/assets/System-Bgs6Ql7x.js +1 -0
  27. package/static/app/assets/core-CwxXejkd.js +1 -2
  28. package/static/app/assets/index-Bvv79nre.js +16 -0
  29. package/static/app/assets/index-Dslqglia.css +2 -0
  30. package/static/app/assets/primitives-B70WOra0.js +1 -0
  31. package/static/app/assets/{textarea-BZk6ybp5.js → textarea-Czrd9gwM.js} +1 -2
  32. package/static/app/index.html +3 -10
  33. package/static/app/theme-boot.js +8 -0
  34. package/static/sw.js +1 -1
  35. package/frontend/index.html +0 -24
  36. package/frontend/openapi.json +0 -15425
  37. package/frontend/src/App.tsx +0 -243
  38. package/frontend/src/api/client.ts +0 -580
  39. package/frontend/src/api/openapi.ts +0 -17892
  40. package/frontend/src/components/AdminAccessGate.tsx +0 -70
  41. package/frontend/src/components/FeedbackState.tsx +0 -45
  42. package/frontend/src/components/LanguageSwitcher.tsx +0 -23
  43. package/frontend/src/components/LivingBrain.tsx +0 -220
  44. package/frontend/src/components/ProductFlow.tsx +0 -171
  45. package/frontend/src/components/WorkspaceProfileSwitcher.tsx +0 -176
  46. package/frontend/src/components/onboarding/AnalysisScreen.tsx +0 -135
  47. package/frontend/src/components/onboarding/DownloadConsentPanel.tsx +0 -29
  48. package/frontend/src/components/onboarding/InstallScreen.tsx +0 -263
  49. package/frontend/src/components/onboarding/LanguageChooser.tsx +0 -23
  50. package/frontend/src/components/onboarding/LoginScreen.tsx +0 -131
  51. package/frontend/src/components/onboarding/ProductFlowScreens.tsx +0 -13
  52. package/frontend/src/components/onboarding/RecommendationScreen.tsx +0 -116
  53. package/frontend/src/components/onboarding/recommendationModel.ts +0 -189
  54. package/frontend/src/components/primitives.tsx +0 -392
  55. package/frontend/src/components/ui/badge.tsx +0 -27
  56. package/frontend/src/components/ui/button.tsx +0 -37
  57. package/frontend/src/components/ui/card.tsx +0 -22
  58. package/frontend/src/components/ui/input.tsx +0 -16
  59. package/frontend/src/components/ui/textarea.tsx +0 -16
  60. package/frontend/src/features/admin/AdminConsole.tsx +0 -334
  61. package/frontend/src/features/brain/BrainCarePanel.tsx +0 -254
  62. package/frontend/src/features/brain/BrainComposer.tsx +0 -85
  63. package/frontend/src/features/brain/BrainConversation.tsx +0 -688
  64. package/frontend/src/features/brain/BrainGraphLayer.tsx +0 -365
  65. package/frontend/src/features/brain/BrainHome.tsx +0 -624
  66. package/frontend/src/features/brain/BrainMemoryLayer.tsx +0 -45
  67. package/frontend/src/features/brain/BrainOverviewPanel.tsx +0 -149
  68. package/frontend/src/features/brain/BrainRelationshipLayer.tsx +0 -43
  69. package/frontend/src/features/brain/DepthEmergence.tsx +0 -53
  70. package/frontend/src/features/brain/brainData.ts +0 -246
  71. package/frontend/src/features/brain/graphLayout.ts +0 -37
  72. package/frontend/src/features/brain/types.ts +0 -150
  73. package/frontend/src/features/review/ReviewCard.tsx +0 -100
  74. package/frontend/src/features/review/ReviewInbox.tsx +0 -127
  75. package/frontend/src/features/review/reviewHelpers.ts +0 -69
  76. package/frontend/src/i18n.ts +0 -1303
  77. package/frontend/src/lib/utils.ts +0 -33
  78. package/frontend/src/main.tsx +0 -23
  79. package/frontend/src/pages/Act.tsx +0 -458
  80. package/frontend/src/pages/Ask.tsx +0 -14
  81. package/frontend/src/pages/Brain.tsx +0 -914
  82. package/frontend/src/pages/Capture.tsx +0 -258
  83. package/frontend/src/pages/Library.tsx +0 -486
  84. package/frontend/src/pages/System.tsx +0 -621
  85. package/frontend/src/routes.ts +0 -92
  86. package/frontend/src/store/appStore.ts +0 -94
  87. package/frontend/src/styles.css +0 -6579
  88. package/static/app/assets/Act-DOvf59ru.js +0 -2
  89. package/static/app/assets/Act-DOvf59ru.js.map +0 -1
  90. package/static/app/assets/Brain-C7_0mEiI.js +0 -322
  91. package/static/app/assets/Brain-C7_0mEiI.js.map +0 -1
  92. package/static/app/assets/Capture-B9Tlhzqr.js.map +0 -1
  93. package/static/app/assets/Library-BJPEEm5O.js +0 -2
  94. package/static/app/assets/Library-BJPEEm5O.js.map +0 -1
  95. package/static/app/assets/System-D6t9jo9V.js +0 -2
  96. package/static/app/assets/System-D6t9jo9V.js.map +0 -1
  97. package/static/app/assets/core-CwxXejkd.js.map +0 -1
  98. package/static/app/assets/index-C7g26IF6.css +0 -2
  99. package/static/app/assets/index-DbcEYJQ2.js +0 -17
  100. package/static/app/assets/index-DbcEYJQ2.js.map +0 -1
  101. package/static/app/assets/primitives-CD38lt4n.js +0 -2
  102. package/static/app/assets/primitives-CD38lt4n.js.map +0 -1
  103. package/static/app/assets/textarea-BZk6ybp5.js.map +0 -1
@@ -1,580 +0,0 @@
1
- import createClient from "openapi-fetch";
2
- import type { components, operations, paths } from "./openapi";
3
- import { useAppStore } from "@/store/appStore";
4
-
5
- export type ApiResult<T = unknown> = {
6
- ok: boolean;
7
- status: number;
8
- data: T;
9
- source: "live" | "unavailable";
10
- error?: string;
11
- };
12
-
13
- type HttpMethod = "GET" | "POST" | "PATCH" | "DELETE";
14
- type Query = Record<string, string | number | boolean | null | undefined>;
15
- export type AdminAuditFilters = {
16
- q?: string;
17
- actor?: string;
18
- action?: string;
19
- severity?: string;
20
- limit?: number;
21
- };
22
-
23
- const TIMEOUT_MS = 10_000;
24
- type OpenApiClient = ReturnType<typeof createClient<paths>>;
25
- type OperationJson200<Operation> = Operation extends {
26
- responses: { 200: { content: { "application/json": infer Result } } };
27
- } ? Result : never;
28
- type ReviewListOperation = operations["list_items_automation_reviews_get"];
29
- type ReviewItemOperation =
30
- | operations["approve_item_automation_reviews__item_id__approve_post"]
31
- | operations["dismiss_item_automation_reviews__item_id__dismiss_post"]
32
- | operations["run_now_item_automation_reviews__item_id__run_now_post"]
33
- | operations["snooze_item_automation_reviews__item_id__snooze_post"]
34
- | operations["unsnooze_item_automation_reviews__item_id__unsnooze_post"];
35
-
36
- const clients = new Map<string, OpenApiClient>();
37
- let desktopBase: Promise<string | null> | null = null;
38
-
39
- declare global {
40
- interface Window {
41
- __TAURI_INTERNALS__?: unknown;
42
- }
43
- }
44
-
45
- function sameOriginBase() {
46
- return "";
47
- }
48
-
49
- async function tauriBackendOrigin(): Promise<string | null> {
50
- if (!window.__TAURI_INTERNALS__) return null;
51
- if (!desktopBase) {
52
- desktopBase = import("@tauri-apps/api/core")
53
- .then(({ invoke }) => invoke<string>("backend_origin"))
54
- .then((origin) => origin || null)
55
- .catch(() => null);
56
- }
57
- return desktopBase;
58
- }
59
-
60
- async function tauriInvoke<T>(command: string): Promise<T | null> {
61
- if (!window.__TAURI_INTERNALS__) return null;
62
- try {
63
- const { invoke } = await import("@tauri-apps/api/core");
64
- return await invoke<T>(command);
65
- } catch {
66
- return null;
67
- }
68
- }
69
-
70
- async function apiBase() {
71
- const stateBase = useAppStore.getState().apiBase;
72
- if (stateBase) return stateBase;
73
- const desktop = await tauriBackendOrigin();
74
- if (desktop) {
75
- useAppStore.getState().setApiBase(desktop);
76
- return desktop;
77
- }
78
- return sameOriginBase();
79
- }
80
-
81
- function clientFor(baseUrl: string) {
82
- if (!clients.has(baseUrl)) {
83
- clients.set(baseUrl, createClient<paths>({ baseUrl, credentials: "same-origin" }));
84
- }
85
- return clients.get(baseUrl)!;
86
- }
87
-
88
- function emptyFor<T>(shape: T): T {
89
- if (Array.isArray(shape)) return [] as T;
90
- if (shape && typeof shape === "object") return { ...(shape as Record<string, unknown>) } as T;
91
- return shape;
92
- }
93
-
94
- function workspaceHeaders(): Record<string, string> {
95
- const workspaceId = useAppStore.getState().workspaceId;
96
- return workspaceId ? { "X-Workspace-Id": workspaceId } : {};
97
- }
98
-
99
- function friendlyError(error: unknown, fallback: string) {
100
- if (!error) return fallback;
101
- const record = typeof error === "object" && error !== null ? error as Record<string, unknown> : null;
102
- const detail = record?.detail;
103
- if (typeof detail === "string") return detail;
104
- const detailRecord = typeof detail === "object" && detail !== null ? detail as Record<string, unknown> : null;
105
- if (detailRecord) {
106
- const message = detailRecord.user_message || detailRecord.reason || detailRecord.action || detailRecord.status;
107
- if (message) return String(message);
108
- }
109
- const message = record?.message || record?.error;
110
- if (message) return String(message);
111
- return fallback;
112
- }
113
-
114
- function friendlyCaughtError(error: unknown, fallback: string) {
115
- const message = error instanceof Error ? error.message : String(error);
116
- if (/not valid JSON|Unexpected token|JSON/i.test(message)) return fallback;
117
- if (/aborted|abort/i.test(message)) return "Request timed out. Check that the local Lattice service is running.";
118
- return message || fallback;
119
- }
120
-
121
- async function apiJson<T>(
122
- method: HttpMethod,
123
- path: string,
124
- opts: { body?: unknown; query?: Query; headers?: Record<string, string>; shape: T },
125
- ): Promise<ApiResult<T>> {
126
- const base = await apiBase();
127
- const client = clientFor(base);
128
- const ctrl = new AbortController();
129
- const timer = window.setTimeout(() => ctrl.abort(), TIMEOUT_MS);
130
- try {
131
- const request = {
132
- body: opts.body,
133
- params: { query: opts.query || {} },
134
- headers: { ...workspaceHeaders(), ...(opts.headers || {}) },
135
- signal: ctrl.signal,
136
- } as never;
137
- const call =
138
- method === "GET" ? client.GET :
139
- method === "POST" ? client.POST :
140
- method === "PATCH" ? client.PATCH :
141
- client.DELETE;
142
- const result = await (call as unknown as (p: never, r: never) => Promise<{ data?: unknown; error?: unknown; response: Response }>)(path as never, request);
143
- const { data, error, response } = result;
144
- if (response.ok && data !== undefined) {
145
- return { ok: true, status: response.status, data: data as T, source: "live" };
146
- }
147
- return {
148
- ok: false,
149
- status: response.status,
150
- data: emptyFor(opts.shape),
151
- source: "unavailable",
152
- error: friendlyError(error, response.statusText),
153
- };
154
- } catch (err) {
155
- return {
156
- ok: false,
157
- status: 0,
158
- data: emptyFor(opts.shape),
159
- source: "unavailable",
160
- error: friendlyCaughtError(err, "The local Lattice service returned an unavailable response."),
161
- };
162
- } finally {
163
- window.clearTimeout(timer);
164
- }
165
- }
166
-
167
- async function openApiJson<T>(
168
- shape: T,
169
- execute: (client: OpenApiClient, signal: AbortSignal) => Promise<{ data?: T; error?: unknown; response: Response }>,
170
- ): Promise<ApiResult<T>> {
171
- const base = await apiBase();
172
- const client = clientFor(base);
173
- const ctrl = new AbortController();
174
- const timer = window.setTimeout(() => ctrl.abort(), TIMEOUT_MS);
175
- try {
176
- const { data, error, response } = await execute(client, ctrl.signal);
177
- if (response.ok && data !== undefined) {
178
- return { ok: true, status: response.status, data, source: "live" };
179
- }
180
- return {
181
- ok: false,
182
- status: response.status,
183
- data: emptyFor(shape),
184
- source: "unavailable",
185
- error: friendlyError(error, response.statusText),
186
- };
187
- } catch (err) {
188
- return {
189
- ok: false,
190
- status: 0,
191
- data: emptyFor(shape),
192
- source: "unavailable",
193
- error: friendlyCaughtError(err, "The local Lattice service returned an unavailable response."),
194
- };
195
- } finally {
196
- window.clearTimeout(timer);
197
- }
198
- }
199
-
200
- function get<T>(path: string, shape: T, query?: Query) {
201
- return apiJson<T>("GET", path, { query, shape });
202
- }
203
-
204
- function post<T>(path: string, body: unknown, shape: T) {
205
- return apiJson<T>("POST", path, { body, shape });
206
- }
207
-
208
- function patch<T>(path: string, body: unknown, shape: T) {
209
- return apiJson<T>("PATCH", path, { body, shape });
210
- }
211
-
212
- function del<T>(path: string, shape: T) {
213
- return apiJson<T>("DELETE", path, { shape });
214
- }
215
-
216
- export type ReviewItem = components["schemas"]["ReviewItem"];
217
- export type ReviewItemList = components["schemas"]["ReviewItemList"];
218
- export type ReviewStatusFilter = "pending" | "snoozed" | "approved" | "dismissed" | "all";
219
- export type ReviewSourceFilter = "workflow_run" | "trigger" | "kg_change_digest" | "all";
220
-
221
- function reviewItemShape(): ReviewItem {
222
- return {
223
- id: "",
224
- status: "pending",
225
- effective_status: "pending",
226
- title: "",
227
- summary: "",
228
- source: "workflow_run",
229
- kind: "suggestion",
230
- payload: {},
231
- provenance: {},
232
- };
233
- }
234
-
235
- function reviewItemListShape(): ReviewItemList {
236
- return { items: [] };
237
- }
238
-
239
- function reviewList(query?: { status?: Exclude<ReviewStatusFilter, "all">; source?: Exclude<ReviewSourceFilter, "all"> }) {
240
- return openApiJson<OperationJson200<ReviewListOperation>>(
241
- reviewItemListShape(),
242
- (client, signal) => client.GET("/automation/reviews", {
243
- params: { query: query || {} },
244
- headers: workspaceHeaders(),
245
- signal,
246
- }),
247
- );
248
- }
249
-
250
- function reviewAction(
251
- id: string,
252
- action: "approve" | "dismiss" | "run_now" | "unsnooze",
253
- ) {
254
- return openApiJson<OperationJson200<ReviewItemOperation>>(
255
- reviewItemShape(),
256
- (client, signal) => {
257
- const request = {
258
- params: { path: { item_id: id } },
259
- headers: workspaceHeaders(),
260
- signal,
261
- };
262
- if (action === "approve") return client.POST("/automation/reviews/{item_id}/approve", request);
263
- if (action === "dismiss") return client.POST("/automation/reviews/{item_id}/dismiss", request);
264
- if (action === "run_now") return client.POST("/automation/reviews/{item_id}/run_now", request);
265
- return client.POST("/automation/reviews/{item_id}/unsnooze", request);
266
- },
267
- );
268
- }
269
-
270
- function snoozeReview(id: string, until: string) {
271
- return openApiJson<OperationJson200<operations["snooze_item_automation_reviews__item_id__snooze_post"]>>(
272
- reviewItemShape(),
273
- (client, signal) => client.POST("/automation/reviews/{item_id}/snooze", {
274
- params: { path: { item_id: id } },
275
- body: { until },
276
- headers: workspaceHeaders(),
277
- signal,
278
- }),
279
- );
280
- }
281
-
282
- async function uploadDocument(file: File): Promise<ApiResult<Record<string, unknown> | null>> {
283
- const base = await apiBase();
284
- const form = new FormData();
285
- form.append("file", file);
286
- try {
287
- const res = await fetch(`${base}/upload/document`, {
288
- method: "POST",
289
- credentials: "same-origin",
290
- headers: { Accept: "application/json", ...workspaceHeaders() } satisfies HeadersInit,
291
- body: form,
292
- });
293
- const data = await res.json().catch(() => null);
294
- return { ok: res.ok, status: res.status, data, source: res.ok ? "live" : "unavailable" };
295
- } catch (err) {
296
- return { ok: false, status: 0, data: null, source: "unavailable", error: String(err) };
297
- }
298
- }
299
-
300
- export type ChatEventHandlers = {
301
- onChunk?: (delta: string, fullText: string) => void;
302
- onTrace?: (trace: unknown) => void;
303
- signal?: AbortSignal;
304
- };
305
-
306
- export type ModelPrepareHandlers = {
307
- onProgress?: (data: Record<string, unknown>) => void;
308
- onDone?: (data: Record<string, unknown>) => void;
309
- onError?: (data: Record<string, unknown>) => void;
310
- signal?: AbortSignal;
311
- };
312
-
313
- async function streamModelPrepare(
314
- body: { model: string; engine?: string; allow_download?: boolean },
315
- handlers: ModelPrepareHandlers = {},
316
- ) {
317
- const base = await apiBase();
318
- const res = await fetch(`${base}/engines/prepare-model/stream`, {
319
- method: "POST",
320
- credentials: "same-origin",
321
- signal: handlers.signal,
322
- headers: {
323
- "Content-Type": "application/json",
324
- Accept: "text/event-stream",
325
- ...workspaceHeaders(),
326
- } satisfies HeadersInit,
327
- body: JSON.stringify({ engine: null, allow_download: false, ...body }),
328
- });
329
- if (!res.ok || !res.body || !(res.headers.get("content-type") || "").includes("text/event-stream")) {
330
- const payload = await res.json().catch(() => null);
331
- const detail = payload?.detail && typeof payload.detail === "object" ? payload.detail : payload;
332
- const message = friendlyError(payload, res.statusText);
333
- handlers.onError?.({ status: "error", user_message: message, ...(detail || {}) });
334
- return { source: "live" as const, ok: false, status: res.status, data: detail || {}, error: message };
335
- }
336
- const reader = res.body.getReader();
337
- const decoder = new TextDecoder();
338
- let buffer = "";
339
- let eventName = "message";
340
- let finalData: Record<string, unknown> = {};
341
- for (;;) {
342
- const { done, value } = await reader.read();
343
- if (done) break;
344
- buffer += decoder.decode(value, { stream: true });
345
- const parts = buffer.split("\n\n");
346
- buffer = parts.pop() || "";
347
- for (const part of parts) {
348
- const lines = part.split("\n");
349
- eventName = lines.find((item) => item.startsWith("event:"))?.slice(6).trim() || "message";
350
- const dataLine = lines.find((item) => item.startsWith("data:"));
351
- if (!dataLine) continue;
352
- const raw = dataLine.slice(5).trim();
353
- const data = raw ? JSON.parse(raw) as Record<string, unknown> : {};
354
- if (eventName === "progress") handlers.onProgress?.(data);
355
- if (eventName === "error") {
356
- const detail = typeof data.detail === "object" && data.detail !== null ? data.detail as Record<string, unknown> : data;
357
- handlers.onError?.(detail);
358
- return { source: "live" as const, ok: false, status: Number(data.status_code || 500), data: detail, error: friendlyError({ detail }, "Model setup failed") };
359
- }
360
- if (eventName === "done") {
361
- finalData = data;
362
- handlers.onDone?.(data);
363
- }
364
- }
365
- }
366
- return { source: "live" as const, ok: true, status: 200, data: finalData };
367
- }
368
-
369
- async function streamChat(body: Record<string, unknown>, handlers: ChatEventHandlers = {}) {
370
- const base = await apiBase();
371
- const res = await fetch(`${base}/chat`, {
372
- method: "POST",
373
- credentials: "same-origin",
374
- signal: handlers.signal,
375
- headers: {
376
- "Content-Type": "application/json",
377
- Accept: "text/event-stream",
378
- ...workspaceHeaders(),
379
- } satisfies HeadersInit,
380
- body: JSON.stringify({ stream: true, max_tokens: 2048, temperature: 0.2, ...body }),
381
- });
382
- if (!res.ok || !res.body || !(res.headers.get("content-type") || "").includes("text/event-stream")) {
383
- const payload = await res.json().catch(() => null);
384
- return { source: "live", text: "", trace: null, error: payload?.error || payload?.detail || res.statusText };
385
- }
386
- const reader = res.body.getReader();
387
- const decoder = new TextDecoder();
388
- let buffer = "";
389
- let text = "";
390
- let trace: unknown = null;
391
- for (;;) {
392
- const { done, value } = await reader.read();
393
- if (done) break;
394
- buffer += decoder.decode(value, { stream: true });
395
- const parts = buffer.split("\n\n");
396
- buffer = parts.pop() || "";
397
- for (const part of parts) {
398
- const line = part.split("\n").find((item) => item.startsWith("data:"));
399
- if (!line) continue;
400
- const raw = line.slice(5).trim();
401
- if (raw === "[DONE]") return { source: "live", text, trace };
402
- const data = JSON.parse(raw);
403
- const delta = data.chunk || data.text || "";
404
- if (delta) {
405
- text += delta;
406
- handlers.onChunk?.(delta, text);
407
- }
408
- if (data.trace) {
409
- trace = data.trace;
410
- handlers.onTrace?.(trace);
411
- }
412
- }
413
- }
414
- return { source: "live", text, trace };
415
- }
416
-
417
- export const latticeApi = {
418
- raw: get,
419
- desktopBackendStatus: async (): Promise<ApiResult<Record<string, unknown>>> => {
420
- const status = await tauriInvoke<Record<string, unknown>>("backend_status");
421
- if (status) return { ok: true, status: 200, data: status, source: "live" };
422
- return { ok: false, status: 0, data: {}, source: "unavailable", error: "Desktop backend status is available only inside the Tauri shell." };
423
- },
424
- health: () => get("/health", {}),
425
- workspaceOs: () => get("/workspace/os", { counts: {}, models: {}, workspace_registry: { workspaces: [] } }),
426
- workspaceVscodeStatus: () => get("/workspace/vscode/status", {
427
- connected: false,
428
- last_seen_ms: 0,
429
- status: "offline",
430
- index_status: "unknown",
431
- }),
432
- indexStatus: () => get("/api/index/status", {}),
433
- rebuildIndex: () => post("/api/index/rebuild", { full: false, include_nodes: true, include_chunks: true }, {}),
434
- graph: () => get("/knowledge-graph/graph", { nodes: [], edges: [] }),
435
- graphStats: () => get("/knowledge-graph/stats", { nodes: {}, edges: {}, total_nodes: 0, total_edges: 0 }),
436
- graphPortability: () => get("/api/knowledge-graph/portability", {}),
437
- brainStorage: () => get("/api/brain/storage", {}),
438
- backupHealth: () => get("/api/knowledge-graph/backup-health", {}),
439
- dockerPostgres: (body: { consent: boolean; dry_run?: boolean; port?: number }) => post("/api/brain/storage/postgres/docker", body, {}),
440
- migratePostgres: (body: { dsn: string; schema_name?: string; dry_run?: boolean }) => post("/api/brain/storage/migrate-postgres", body, {}),
441
- graphProvenance: (limit = 50) => get("/api/knowledge-graph/provenance", { items: [] }, { limit }),
442
- graphCoverage: () => get("/knowledge-graph/provenance/coverage", {}),
443
- graphExport: () => post("/api/knowledge-graph/export", {}, {}),
444
- graphBackup: () => post("/api/knowledge-graph/backup", {}, {}),
445
- graphImport: (artifact: unknown, dry_run = true) => post("/api/knowledge-graph/import", { artifact, mode: "merge", dry_run }, {}),
446
- brainArchive: (body: { path?: string | null; passphrase: string }) => post("/api/knowledge-graph/archive", body, {}),
447
- brainArchiveInspect: (body: { path: string; passphrase?: string | null }) => post("/api/knowledge-graph/archive/inspect", body, {}),
448
- brainArchiveVerify: (body: { path: string; passphrase: string }) => post("/api/knowledge-graph/archive/verify", body, {}),
449
- brainArchiveRestore: (body: { path: string; passphrase: string; dry_run?: boolean; confirm?: boolean }) => post("/api/knowledge-graph/archive/restore", body, {}),
450
- brainArchiveImport: (body: { path: string; passphrase: string; dry_run?: boolean; confirm?: boolean }) => post("/api/knowledge-graph/archive/import", body, {}),
451
- hybridSearch: async (query: string, weights?: unknown) => {
452
- const res = await post<Record<string, unknown>>("/api/search/hybrid", { query, ...(weights ? { weights } : {}) }, { matches: [] });
453
- const data = res.data as Record<string, unknown>;
454
- if (res.ok && !Array.isArray(data.matches) && Array.isArray(data.results)) {
455
- return { ...res, data: { ...data, matches: data.results } };
456
- }
457
- return res;
458
- },
459
- browserReadUrl: (url: string) => post("/api/browser/read-url", { url }, {}),
460
- ingestNote: (content: string, title = "Brain note") => post(
461
- "/knowledge-graph/ingest",
462
- { type: "note", content, title, source: "brain_home" },
463
- {},
464
- ),
465
- memoryManager: () => get("/api/memory/manager", { sources: [], tiers: [], usage: {} }),
466
- memoryBrainQuality: () => get("/api/memory/brain-quality", {}),
467
- memoryBrainProof: (query = "", limit = 3) => get("/api/memory/brain-proof", { proofs: {}, recall: { items: [] }, model_continuity: {}, claims: {} }, { q: query, limit }),
468
- memoryRecall: (query: string, limit = 20) => post("/api/memory/recall", { query, limit }, { matches: [] }),
469
- memoryCompact: () => post("/api/memory/compact", {}, {}),
470
- memoryRebuild: () => post("/api/memory/rebuild", { target: "vector" }, {}),
471
- chatHistory: () => get("/history/conversations", []),
472
- conversation: (id: string) => get(`/history/conversations/${encodeURIComponent(id)}`, { messages: [] }),
473
- deleteConversation: (id: string) => del(`/history/conversations/${encodeURIComponent(id)}`, {}),
474
- streamChat,
475
- uploadDocument,
476
- documents: (limit = 200) => get("/knowledge-graph/documents", { documents: [] }, { limit }),
477
- localSources: () => get("/knowledge-graph/local/sources", { sources: [], watch: { available: false, active: {} } }),
478
- localAgent: () => get("/api/local-agent/status", { agent: { online: false }, sources: [] }),
479
- connectFolder: (path: string) => post("/knowledge-graph/local/index", { path, approved: true, watch_enabled: true, consent: { approved: true, source: "desktop-spa" } }, {}),
480
- localWatchStop: (source_id: string) => post("/knowledge-graph/local/watch/stop", { source_id }, {}),
481
- models: () => get("/models", { catalog: [], loaded: [], recommended: [] }),
482
- setupScan: () => get("/setup/scan", { environment: {}, recommendations: {}, zero_config: {} }),
483
- modelRecommendations: (engine = "local_mlx") => get("/models/recommendations", { profile: {}, recommendations: { models: [], families: [], counts: {} } }, { engine }),
484
- installEngine: (engine: string) => post("/engines/install", { engine }, {}),
485
- prepareModel: (model: string, engine?: string, allow_download = false) => post("/engines/prepare-model", { model, engine: engine || null, allow_download }, {}),
486
- streamModelPrepare,
487
- loadModel: (model_id: string, engine?: string, allow_download = false) => post("/models/load", { model_id, engine: engine || null, allow_download }, {}),
488
- unloadModel: (model_id: string) => del(`/models/unload/${encodeURIComponent(model_id)}`, {}),
489
- embeddingsStatus: () => get("/api/embeddings/status", {}),
490
- agentRuntime: () => get("/agents/api/runtime/status", { runtime: {}, agents: [], runs: [] }),
491
- agentRunPreview: (goal: string, roles: string[] = []) => post("/agents/api/run/preview", { goal, roles }, { ready: false, blocking_reasons: [] }),
492
- runAgent: (goal: string, roles: string[]) => post("/agents/api/run", { goal, roles }, {}),
493
- toolRegistryDiagnostics: () => get("/tools/registry/diagnostics", { diagnostics: { ready: false } }),
494
- toolRegistry: () => get("/tools/registry", { status: "unavailable", diagnostics: {}, tools: [] }),
495
- agentRun: (id: string) => get(`/agents/api/runs/${encodeURIComponent(id)}`, {}),
496
- stopAgentRun: (id: string) => post(`/agents/api/runs/${encodeURIComponent(id)}/stop`, {}, {}),
497
- agentRegistry: () => get("/agents/api/registry", { agents: [] }),
498
- agentCapabilities: () => get("/agents/api/registry/capabilities", { capabilities: {} }),
499
- registerAgent: (body: unknown) => post("/agents/api/registry", body, {}),
500
- updateAgent: (id: string, body: unknown) => patch(`/agents/api/registry/${encodeURIComponent(id)}`, body, {}),
501
- removeAgent: (id: string) => del(`/agents/api/registry/${encodeURIComponent(id)}`, {}),
502
- workflowDefinitions: () => get("/workflows/api/definitions", { workflows: [] }),
503
- workflowRuns: () => get("/workflows/api/runs", { runs: [] }),
504
- workflowTriggers: () => get("/workflows/api/triggers", { armed: [] }),
505
- automationRecipes: () => get("/workflows/api/automation/recipes", { recipes: [], principles: {} }),
506
- installAutomationRecipe: (recipeId: string, enabled = false) => post(`/workflows/api/automation/recipes/${encodeURIComponent(recipeId)}`, { enabled }, {}),
507
- createWorkflow: (body: { name: string; nodes: Array<Record<string, unknown>>; metadata?: Record<string, unknown> }) => post("/workflows/api/definitions", body, {}),
508
- importWorkflow: (data: Record<string, unknown>) => post("/workflows/api/import", { data }, {}),
509
- exportWorkflow: (id: string) => get(`/workflows/api/export/${encodeURIComponent(id)}`, {}),
510
- runWorkflow: (id: string) => post(`/workflows/api/definitions/${encodeURIComponent(id)}/run`, {}, {}),
511
- updateWorkflow: (id: string, body: unknown) => patch(`/workflows/api/definitions/${encodeURIComponent(id)}`, body, {}),
512
- stopWorkflowRun: (id: string) => post(`/workflows/api/runs/${encodeURIComponent(id)}/stop`, {}, {}),
513
- resumeWorkflowRun: (id: string, approved: boolean) => post(`/workflows/api/runs/${encodeURIComponent(id)}/resume`, { approved }, {}),
514
- hooks: () => get("/api/hooks", { hooks: [] }),
515
- hookRuns: () => get("/api/hooks/runs", { runs: [] }, { limit: 50 }),
516
- hookRun: (body: unknown) => post("/api/hooks/run", body, {}),
517
- automationReviews: reviewList,
518
- approveReviewItem: (id: string) => reviewAction(id, "approve"),
519
- dismissReviewItem: (id: string) => reviewAction(id, "dismiss"),
520
- snoozeReviewItem: snoozeReview,
521
- unsnoozeReviewItem: (id: string) => reviewAction(id, "unsnooze"),
522
- runNowReviewItem: (id: string) => reviewAction(id, "run_now"),
523
- permissionsPending: () => get("/permissions/pending", { pending: {}, count: 0 }),
524
- approvePermission: (token: string) => post(`/permissions/approve/${encodeURIComponent(token)}`, {}, {}),
525
- denyPermission: (token: string) => post(`/permissions/deny/${encodeURIComponent(token)}`, {}, {}),
526
- skills: () => get("/workspace/skills", { skills: [] }),
527
- skillToggle: (skill: string, enabled: boolean) => post(enabled ? "/workspace/skills/disable" : "/workspace/skills/enable", { skill }, {}),
528
- skillsMarketplace: () => get("/skills/marketplace", { skills: [] }),
529
- skillInstall: (skill: string, plugin?: string) => post("/workspace/skills/install", { skill, plugin: plugin || "" }, {}),
530
- mcpTools: () => get("/mcp/tools", { tools: [], installed_mcps: [] }),
531
- mcpRecommend: (query: string) => post("/mcp/recommend", { query, limit: 6 }, {}),
532
- templates: () => get("/marketplace/templates", { templates: [], kinds: [] }),
533
- installTemplate: (data: unknown) => post("/marketplace/templates/install", { data }, {}),
534
- pluginsRegistry: () => get("/plugins/registry", { plugins: [] }),
535
- pluginsDirectory: () => get("/plugins/directory", { plugins: [] }),
536
- profile: () => get("/account/profile", {}),
537
- login: (email: string, password: string) => post("/login", { email, password }, {}),
538
- register: (body: unknown) => post("/register", body, {}),
539
- logout: () => post("/logout", {}, {}),
540
- updateProfile: (body: unknown) => patch("/account/profile", body, {}),
541
- changePassword: (current_password: string, new_password: string) => post("/account/change-password", { current_password, new_password }, {}),
542
- ssoConfig: () => get("/auth/sso/config", { enabled: false, providers: [] }),
543
- workspaceRegistry: () => get("/workspace/registry", { workspaces: [] }),
544
- createOrg: (name: string) => post("/workspace/orgs", { name }, {}),
545
- activateWorkspace: (workspace_id: string) => post("/workspace/activate", { workspace_id }, {}),
546
- archiveWorkspace: (workspace_id: string) => post(`/workspace/orgs/${encodeURIComponent(workspace_id)}/archive`, {}, {}),
547
- addWorkspaceMember: (workspace_id: string, user_id: string, role: string) => post(`/workspace/orgs/${encodeURIComponent(workspace_id)}/members`, { user_id, role }, {}),
548
- removeWorkspaceMember: (workspace_id: string, user_id: string) => del(`/workspace/orgs/${encodeURIComponent(workspace_id)}/members/${encodeURIComponent(user_id)}`, {}),
549
- invitations: () => get("/invitations", { invitations: [] }),
550
- createInvitation: (body: unknown) => post("/invitations", body, {}),
551
- acceptInvitation: (token: string) => post(`/invitations/${encodeURIComponent(token)}/accept`, {}, {}),
552
- snapshots: () => get("/workspace/snapshots", { snapshots: [] }),
553
- createSnapshot: (name: string) => post("/workspace/snapshots", { name }, {}),
554
- compareSnapshots: (before_id: string, after_id: string) => post("/workspace/snapshots/compare", { before_id, after_id }, {}),
555
- restoreSnapshot: (id: string) => post(`/workspace/snapshots/${encodeURIComponent(id)}/restore`, {}, {}),
556
- exportSnapshot: (id: string) => post(`/workspace/snapshots/${encodeURIComponent(id)}/export`, {}, {}),
557
- timeMachine: () => get("/workspace/time-machine", { events: [] }, { limit: 100 }),
558
- realtimeFeed: () => get("/realtime/feed", { events: [] }, { limit: 80 }),
559
- presence: () => get("/realtime/presence", { presence: [] }),
560
- networkIdentity: () => get("/network/identity", {}),
561
- networkPeers: () => get("/network/peers", { peers: [] }),
562
- pairPeer: (body: unknown) => post("/network/peers", body, {}),
563
- unpairPeer: (id: string) => del(`/network/peers/${encodeURIComponent(id)}`, {}),
564
- pushPeer: (id: string, workspace_id?: string | null) => post(`/network/push/${encodeURIComponent(id)}`, { workspace_id }, {}),
565
- sysinfo: () => get("/local/sysinfo", {}),
566
- computerMemory: () => get("/workspace/computer-memory", {}),
567
- setComputerMemory: (enabled: boolean) => post("/workspace/computer-memory", { enabled, consent: { approved: enabled } }, {}),
568
- adminSummary: () => get("/admin/summary", {}),
569
- adminStats: () => get("/admin/stats", {}),
570
- adminUsers: () => get("/admin/users", []),
571
- adminAudit: (filters?: AdminAuditFilters) => get("/admin/audit", { recent_events: [], filters: {} }, filters),
572
- adminRoles: () => get("/admin/roles", { roles: [] }),
573
- adminPolicies: () => get("/admin/policies", { policies: [] }),
574
- adminLogRetention: () => get("/admin/log-retention", {}),
575
- adminProductHardening: () => get("/admin/product-hardening", {}),
576
- adminSecurity: () => get("/admin/security/overview", {}),
577
- adminSecurityEvents: (limit = 50) => get("/admin/security/events", { events: [] }, { limit }),
578
- vpcStatus: () => get("/vpc/status", {}),
579
- toolPermissions: () => get("/tools/permissions", { permissions: [] }),
580
- };